Develop an app for oil & gas incident management to generate cause-and-effect trees. Users should add four categories: "Task," "Tools," "Individual," and "Environment," linking them with two relationship types: Conjunction - Antecedents are independent but jointly necessary. Chain of Events - Antecedent alone is sufficient. The app should feature a drag-and-drop interface, customizable box details, real-time validation, dynamic visualization, and exportable reports for root cause analysis.
To upload files, please first save the app
import streamlit as st
import networkx as nx
from pyvis.network import Network
import pandas as pd
import json
from datetime import datetime
import base64
from io import BytesIO
# Initialize session state
if 'graph' not in st.session_state:
st.session_state.graph = nx.DiGraph()
if 'node_data' not in st.session_state:
st.session_state.node_data = {}
if 'next_node_id' not in st.session_state:
st.session_state.next_node_id = 1
st.set_page_config(layout="wide", page_title="Oil & Gas Incident Analysis")
# Styling
st.markdown("""
<style>
.main {
padding: 20px;
}
.stButton button {
width: 100%;
}
</style>
""", unsafe_allow_html=True)
st.title("Oil & Gas Incident Cause-and-Effect Analysis")
# Sidebar for adding nodes and relationships
with st.sidebar:
st.header("Add Elements")
# Node creation
node_category = st.selectbox(
"Select Category",
["Task", "Tools", "Individual", "Environment"]
)
node_description = st.text_area("Description")
node_details = st.text_area("Additional Details")
if st.button("Add Node"):
node_id = f"node_{st.session_state.next_node_id}"
st.session_state.graph.add_node(node_id)
st.session_state.node_data[node_id] = {
"category": node_category,
"description": node_description,
"details": node_details
}
st.session_state.next_node_id += 1
st.success("Node added successfully!")
# Edge creation
st.header("Add Relationship")
available_nodes = list(st.session_state.graph.nodes())
if len(available_nodes) >= 2:
source = st.selectbox("Source Node", available_nodes)
target = st.selectbox("Target Node", [n for n in available_nodes if n != source])
relationship_type = st.radio(
"Relationship Type",
["Conjunction", "Chain of Events"]
)
if st.button("Add Relationship"):
st.session_state.graph.add_edge(
source, target,
relationship_type=relationship_type
)
st.success("Relationship added successfully!")
# Main content area
col1, col2 = st.columns([2, 1])
with col1:
st.header("Cause-and-Effect Visualization")
# Create visualization
net = Network(height="600px", width="100%", directed=True)
# Add nodes with different colors based on category
color_map = {
"Task": "#FF9999",
"Tools": "#99FF99",
"Individual": "#9999FF",
"Environment": "#FFFF99"
}
for node in st.session_state.graph.nodes():
node_info = st.session_state.node_data[node]
net.add_node(
node,
label=f"{node_info['category']}\n{node_info['description']}",
color=color_map[node_info['category']],
title=node_info['details']
)
# Add edges with different styles based on relationship type
for edge in st.session_state.graph.edges(data=True):
source, target, data = edge
if data['relationship_type'] == 'Conjunction':
net.add_edge(source, target, color='blue', dashes=True)
else:
net.add_edge(source, target, color='red')
# Save and display the network
net.save_graph("temp_network.html")
with open("temp_network.html", "r", encoding="utf-8") as f:
st.components.v1.html(f.read(), height=600)
with col2:
st.header("Analysis Details")
# Display node information
st.subheader("Node Information")
for node, data in st.session_state.node_data.items():
with st.expander(f"{data['category']}: {data['description'][:30]}..."):
st.write(f"Category: {data['category']}")
st.write(f"Description: {data['description']}")
st.write(f"Details: {data['details']}")
# Export functionality
st.header("Export Analysis")
if st.button("Generate Report"):
report_data = {
"nodes": st.session_state.node_data,
"relationships": [
{
"source": s,
"target": t,
"type": d["relationship_type"]
}
for s, t, d in st.session_state.graph.edges(data=True)
],
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
# Convert to DataFrame for easy viewing
df = pd.DataFrame([
{
"Node ID": node_id,
"Category": data["category"],
"Description": data["description"],
"Details": data["details"]
}
for node_id, data in st.session_state.node_data.items()
])
# Create download button
csv = df.to_csv(index=False)
b64 = base64.b64encode(csv.encode()).decode()
href = f'<a href="data:file/csv;base64,{b64}" download="incident_analysis_report.csv">Download CSV Report</a>'
st.markdown(href, unsafe_allow_html=True)
# Display json for complete data
st.download_button(
"Download Full Analysis (JSON)",
data=json.dumps(report_data, indent=2),
file_name="complete_analysis.json",
mime="application/json"
)
Hi! I can help you with any questions about Streamlit and Python. What would you like to know?