File size: 7,159 Bytes
b11aca7 4eb270e b11aca7 a29f92f 4eb270e b11aca7 4eb270e b11aca7 4eb270e b11aca7 4eb270e b11aca7 4eb270e b11aca7 4eb270e b11aca7 4eb270e b11aca7 4eb270e b11aca7 4eb270e b11aca7 4eb270e b11aca7 4eb270e b11aca7 10c94eb b11aca7 10c94eb b11aca7 4eb270e b11aca7 4eb270e b11aca7 4eb270e b11aca7 4eb270e b11aca7 10c94eb 3db7729 b11aca7 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
import streamlit as st, pandas as pd, os, io
from modeci_mdf.mdf import Model, Graph, Node, Parameter, OutputPort
from modeci_mdf.utils import load_mdf_json, load_mdf, load_mdf_yaml
from modeci_mdf.execution_engine import EvaluableGraph
import json
st.set_page_config(layout="wide")
st.title("🔋 MDF Simulator")
import requests
# models: Purpose: To store the state of the model and update the model
def run_simulation(param_inputs, mdf_model):
mod_graph = mdf_model.graphs[0]
nodes = mod_graph.nodes[0]
parameters = nodes.parameters
outputs = nodes.output_ports
eg = EvaluableGraph(mod_graph, verbose=False)
duration = param_inputs["Simulation Duration (s)"]
dt = param_inputs["Time Step (s)"]
t = 0
times = []
output_values = {op.value: [] for op in outputs}
while t <= duration:
times.append(t)
if t == 0:
eg.evaluate()
else:
eg.evaluate(time_increment=dt)
for param in output_values:
eval_param = eg.enodes[nodes.id].evaluable_parameters[param]
output_values[param].append(eval_param.curr_value)
t += dt
chart_data = pd.DataFrame(output_values)
chart_data['Time'] = times
chart_data.set_index('Time', inplace=True)
return chart_data
# views: Purpose: To display the state of the model and update the view
def show_simulation_results(chart_data):
st.line_chart(chart_data, use_container_width=True, height=400)
st.write("Output Values")
st.write(chart_data)
def show_mdf_graph(mdf_model):
st.subheader("MDF Graph")
mdf_model.to_graph_image(engine="dot", output_format="png", view_on_render=False, level=3, filename_root=mdf_model.id, only_warn_on_fail=(os.name == "nt"))
image_path = mdf_model.id + ".png"
st.image(image_path, caption="Model Graph Visualization")
def show_json_output(mdf_model):
st.subheader("JSON Output")
st.json(mdf_model.to_json())
def view_tabs(mdf_model, param_inputs): # view
tab1, tab2, tab3 = st.tabs(["Simulation Results", "MDF Graph", "Json Output"])
with tab1:
chart_data = run_simulation(param_inputs, mdf_model) # model
show_simulation_results(chart_data) # view
with tab2:
show_mdf_graph(mdf_model) # view
with tab3:
show_json_output(mdf_model) # view
def parameter_form_to_update_model_and_view(mdf_model, parameters, param_inputs, mod_graph, nodes):
form = st.form(key="parameter_form")
valid_inputs = True
for i, param in enumerate(parameters):
if isinstance(param.value, str) or param.value is None:
continue
key = f"{param.id}_{i}"
if mdf_model.metadata:
value = form.text_input(f"{param.metadata.get('description', param.id)} ({param.id})", value=str(param.value), key=key)
else:
value = form.text_input(f"{param.id}", value=str(param.value), key=key)
try:
param_inputs[param.id] = float(value)
except ValueError:
st.error(f"Invalid input for {param.id}. Please enter a valid number.")
valid_inputs = False
sim_duration = form.text_input("Simulation Duration (s)", value=str(param_inputs["Simulation Duration (s)"]), key="sim_duration")
time_step = form.text_input("Time Step (s)", value=str(param_inputs["Time Step (s)"]), key="time_step")
try:
param_inputs["Simulation Duration (s)"] = float(sim_duration)
except ValueError:
st.error("Invalid input for Simulation Duration. Please enter a valid number.")
valid_inputs = False
try:
param_inputs["Time Step (s)"] = float(time_step)
except ValueError:
st.error("Invalid input for Time Step. Please enter a valid number.")
valid_inputs = False
run_button = form.form_submit_button("Run Simulation")
if run_button:
if valid_inputs:
for param in parameters:
if param.id in param_inputs:
param.value = param_inputs[param.id]
view_tabs(mdf_model, param_inputs)
# else:
# st.error("Please correct the invalid inputs before running the simulation.")
def upload_file_and_load_to_model():
st.write("Choose how to load the model:")
load_option = st.radio("", ("Upload File", "GitHub URL"))
if load_option == "Upload File":
uploaded_file = st.file_uploader("Choose a JSON/YAML/BSON file", type=["json", "yaml", "bson"])
if uploaded_file is not None:
file_content = uploaded_file.getvalue()
file_extension = uploaded_file.name.split('.')[-1].lower()
return load_model_from_content(file_content, file_extension)
else:
st.write("sample_github_url = https://raw.githubusercontent.com/ModECI/MDF/development/examples/MDF/NewtonCoolingModel.json")
github_url = st.text_input("Enter GitHub raw file URL:", placeholder="Enter GitHub raw file URL")
if github_url:
try:
response = requests.get(github_url)
response.raise_for_status()
file_content = response.content
# print(file_content)
file_extension = github_url.split('.')[-1].lower()
return load_model_from_content(file_content, file_extension)
except requests.RequestException as e:
st.error(f"Error loading file from GitHub: {e}")
return None
return None
def load_model_from_content(file_content, file_extension):
try:
if file_extension == 'json':
json_data = json.loads(file_content)
mdf_model = Model.from_dict(json_data)
elif file_extension in ['yaml', 'yml']:
mdf_model = load_mdf_yaml(io.BytesIO(file_content))
else:
st.error("Unsupported file format. Please use JSON or YAML files.")
return None
st.session_state.original_mdf_model = mdf_model # Save the original model
st.session_state.mdf_model_yaml = mdf_model # Save the current model state
return mdf_model
except Exception as e:
st.error(f"Error loading model: {e}")
return None
def main():
st.write("Text box changed to input. Github URL is allowed. Added some warnings eg. on adding text in input fields. Now working on multiple parameters allow.")
mdf_model = upload_file_and_load_to_model() # controller
if mdf_model:
mod_graph = mdf_model.graphs[0]
nodes = mod_graph.nodes[0]
parameters = nodes.parameters
param_inputs = {}
if mdf_model.metadata:
preferred_duration = float(mdf_model.metadata.get("preferred_duration", 10))
preferred_dt = float(mdf_model.metadata.get("preferred_dt", 0.1))
else:
preferred_duration = 100
preferred_dt = 0.1
param_inputs["Simulation Duration (s)"] = preferred_duration
param_inputs["Time Step (s)"] = preferred_dt
parameter_form_to_update_model_and_view(mdf_model, parameters, param_inputs, mod_graph, nodes)
if __name__ == "__main__":
main()
|