Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,19 +64,28 @@ dependencies = [
[project.optional-dependencies]
docs = [
"sphinx>=5.0",
"sphinx-rtd-theme>=1.0",
"sphinx-rtd-theme>=1.0",
"myst-parser>=0.18",
"sphinx-autobuild>=2021.3.14",
"linkify-it-py>=2.0"
]
bo = [
"torch",
"botorch",
"botorch",
"gpytorch"
]
abc = [
"pyabc"
]
gui = [
"pyqt5",
"seaborn",
]
all =
"uq_physicell[bo]",
"uq_physicell[abc]",
"uq_physicell[gui]",
]

[project.scripts]
uq_physicell = "uq_physicell.gui.main_window:main"
Expand Down
4 changes: 2 additions & 2 deletions uq_physicell/database/ma_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -728,7 +728,7 @@ def check_simulations_db(PhysiCellModel: PhysiCell_Model, sampler: str, param_di
for sample_id, params in dic_samples.items():
# Use set items comparison to ignore order of keys
if set(dic_samples_db[sample_id].items()) != set(params.items()):
raise ValueError(f"ParameterSpace mismatch for SampleID {sample_id}. Expected: {params}, Found: {dic_samples_db[sample_id]}.")
raise ValueError(f"ParameterSpace mismatch for SampleID {sample_id}. Expected: {sorted(params.items())}, Found: {sorted(dic_samples_db[sample_id].items())}.")

# Check if QoIs match the expected values
if qois_dic:
Expand Down Expand Up @@ -813,4 +813,4 @@ def get_database_type(db_file: str) -> bool:
elif 'BO_Method' in columns:
return "BO"
else:
return None
return None
27 changes: 18 additions & 9 deletions uq_physicell/gui/tab1_select_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def create_tab1(main_window):
main_window.combo_box.setEnabled(False)
main_window.combo_hbox.addWidget(main_window.combo_box)
main_window.combo_hbox.addStretch()

# Create a group box for parameter details
main_window.param_details_groupbox = QGroupBox("Parameter Details")
param_details_layout = QVBoxLayout()
Expand Down Expand Up @@ -151,12 +151,12 @@ def create_tab1(main_window):
lambda: [
main_window.set_param_button.setEnabled(main_window.new_value_input.text().strip() != ""),
main_window.set_param_button.setStyleSheet(
"background-color: lightgreen; color: black;" if main_window.new_value_input.text().strip()
"background-color: lightgreen; color: black;" if main_window.new_value_input.text().strip()
else "background-color: lightgreen; color: darkgray;"
),
main_window.add_analysis_button.setEnabled(not main_window.set_param_button.isEnabled()),
main_window.add_analysis_button.setStyleSheet(
"background-color: lightgreen; color: black;" if not main_window.new_value_input.text().strip()
"background-color: lightgreen; color: black;" if not main_window.new_value_input.text().strip()
else "background-color: lightgreen; color: darkgray;"
)
]
Expand Down Expand Up @@ -264,6 +264,10 @@ def create_combo_box(main_window, parent_node, label):
# Append the 'index' attribute if it exists
if "index" in child.attrib:
display_name = f"{display_name}[{int(child.get('index')) + 1}]"
# Append the 'ID' attribute for Dirichlet_options boundary_value
elif display_name == "boundary_value":
display_name = f"{display_name}[@ID='" + child.get('ID') + "']"
# Generic
combo_box.addItem(display_name)
combo_box.currentIndexChanged.connect(lambda: main_window.handle_combo_selection(main_window, combo_box, parent_node))

Expand Down Expand Up @@ -295,6 +299,9 @@ def handle_combo_selection(main_window, combo_box, parent_node):
display_name = child.get("name", child.tag)
if "index" in child.attrib:
display_name = f"{display_name}[{int(child.get('index')) + 1}]"
elif display_name == "boundary_value":
display_name = f"{display_name}[@ID='{child.get('ID')}']"

if display_name == selected_display_name:
# Clear combo boxes below the current one
main_window.clear_combo_boxes(main_window, starting_index=main_window.combo_hbox.indexOf(combo_box) + 1)
Expand All @@ -313,7 +320,6 @@ def handle_combo_selection(main_window, combo_box, parent_node):
main_window.update_selected_param_label(main_window, path, value)
break


def update_selected_param_label(main_window, path, value):
# Determine the displayed value
new_value = ''
Expand Down Expand Up @@ -436,12 +442,12 @@ def create_rule_section(main_window):
lambda: [
set_rule_button.setEnabled(main_window.new_value_input_rule.text().strip() != ""),
set_rule_button.setStyleSheet(
"background-color: lightgreen; color: black;" if main_window.new_value_input_rule.text().strip()
"background-color: lightgreen; color: black;" if main_window.new_value_input_rule.text().strip()
else "background-color: lightgreen; color: darkgray;"
),
add_rule_analysis_button.setEnabled(not set_rule_button.isEnabled()),
add_rule_analysis_button.setStyleSheet(
"background-color: lightgreen; color: black;" if not main_window.new_value_input_rule.text().strip()
"background-color: lightgreen; color: black;" if not main_window.new_value_input_rule.text().strip()
else "background-color: lightgreen; color: darkgray;"
)
]
Expand Down Expand Up @@ -651,8 +657,11 @@ def get_parameter_path_xml(main_window, node):
if "name" in node.attrib:
node_name += f"[@name='{node.get('name')}']"
# Append 'index' attribute if it exists
if "index" in node.attrib:
elif "index" in node.attrib:
node_name += f"[{int(node.get('index')) + 1}]"
# Use ID attribute if Dirichlet_options boundary_value
elif "boundary_value" == node.tag :
node_name += f"[@ID='{node.get('ID')}']"
path.insert(0, node_name)
node = main_window.parent_map.get(node) # Use the parent map to find the parent
return ".//" + "/".join(path)
Expand Down Expand Up @@ -844,8 +853,8 @@ def save_ini_file(main_window):
config.read(file_path)
if struc_name in config.sections():
# Ask the user if they want to overwrite
reply = QMessageBox.question(main_window, "Overwrite Confirmation",
f"Structure '{struc_name}' already exists. Do you want to overwrite it?",
reply = QMessageBox.question(main_window, "Overwrite Confirmation",
f"Structure '{struc_name}' already exists. Do you want to overwrite it?",
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes:
# Remove the existing section
Expand Down
7 changes: 4 additions & 3 deletions uq_physicell/model_analysis/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def mcds_list_to_qoi_df_long(recreated_qoi_funcs, all_sample_ids, chunk_size, db
and ReplicateID, with columns for each QoI - columns combined with time points.
"""
# Process samples in chunks to avoid memory issues
ls_column = ['SampleID','ReplicateID', 'time'] + sorted(recreated_qoi_funcs.keys())
ls_column = ['SampleID','time','ReplicateID'] + sorted(recreated_qoi_funcs.keys())
llo_data = []
for i in range(0, len(all_sample_ids), chunk_size):
chunk_sample_ids = all_sample_ids[i:i + chunk_size]
Expand All @@ -134,19 +134,20 @@ def mcds_list_to_qoi_df_long(recreated_qoi_funcs, all_sample_ids, chunk_size, db
mcds_ts_list = df_sample[df_sample['ReplicateID'] == ReplicateID]['Data'].values[0]
# print(f"SampleID: {SampleID}, ReplicateID: {ReplicateID} - mcds_ts_list: {mcds_ts_list}")
for mcds in mcds_ts_list:
lo_data = [SampleID, ReplicateID, mcds.get_time()]
lo_data = [SampleID, mcds.get_time(), ReplicateID]
try:
for qoi_name, qoi_func in sorted(recreated_qoi_funcs.items()):
# Store functions the qoi result
function_result = safe_call_qoi_function(qoi_func, mcds=mcds, list_mcds=mcds_ts_list)
lo_data.append(function_result)
except Exception as e:
raise RuntimeError(f"Error calculating QoIs for SampleID: {SampleID}, ReplicateID: {ReplicateID} - QoI: {qoi_name}_{id_time}: {e}")
raise RuntimeError(f"Error calculating QoIs for SampleID: {SampleID}, ReplicateID: {ReplicateID} - QoI: {qoi_name} {qoi_func}: {e}")
# Store the mcds results
llo_data.append(lo_data)

# Gernate data frame
df_qois = pd.DataFrame(llo_data, columns=ls_column)
df_qois = df_qois.sort_values(['SampleID','time','ReplicateID'], ignore_index=True)
return df_qois

def mcds_list_to_qoi_df_for_calib(recreated_qoi_funcs, all_sample_ids, chunk_size, db_file) -> pd.DataFrame:
Expand Down
4 changes: 3 additions & 1 deletion uq_physicell/pc_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,8 @@ def _set_xml_element_value(xml_root: ET.Element, key: str, val: Union[str, int,
# Check and extract the attribute name using regex
attribute = _attr_name_re.search(last_seg)
elem = elems[0]
if last_seg.startswith('boundary_value[@ID'):
attribute = False
if attribute:
elem.set(attribute.group(1), str(val))
else:
Expand Down Expand Up @@ -780,4 +782,4 @@ def compile_physicell(pc_path, model_path, executable_path=None, force_compile=F

finally:
# Restore original working directory
os.chdir(original_cwd)
os.chdir(original_cwd)
Loading