small rewrite to impose dry principles
This commit is contained in:
@@ -268,7 +268,13 @@ SECTIONS = [
|
||||
{"name": "N_JOBS", "default": 1, "type": int, "help": "The number of CPUs to use to do the GLM computation. -1 means 'all CPUs'."},
|
||||
]
|
||||
},
|
||||
{
|
||||
{
|
||||
"title": "Region of Interest",
|
||||
"params": [
|
||||
{"name": "JSON_LOCATION", "default": "", "type": str, "help": "Location of the JSON file containing region of interest results for significance calculations."},
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Finishing Touches",
|
||||
"params": [
|
||||
# Intentionally empty (TODO)
|
||||
@@ -287,6 +293,19 @@ SECTIONS = [
|
||||
|
||||
|
||||
|
||||
DATA_SCHEMA = [
|
||||
{"key": "raw_haemo_dict", "help": "Dict[file_path, MNE RawArray]: Haemodynamic raw data"},
|
||||
{"key": "epochs_dict", "help": "Dict[file_path, MNE Epochs]: Time-locked epoch data"},
|
||||
{"key": "cha_dict", "help": "Dict[file_path, DataFrame]: Channel analysis results"},
|
||||
{"key": "df_ind_dict", "help": "Dict[file_path, DataFrame]: Individual-level data/ROI results"},
|
||||
{"key": "design_matrix_dict", "help": "Dict[file_path, DataFrame]: GLM design matrices"},
|
||||
{"key": "config_dict", "help": "Dict[file_path, dict]: Processing configuration parameters"},
|
||||
{"key": "fig_bytes_dict", "help": "Dict[file_path, dict]: Serialized figure data"},
|
||||
{"key": "contrast_results_dict", "help": "Dict[file_path, dict]: Calculated contrast statistical results"},
|
||||
{"key": "valid_dict", "help": "Dict[file_path, bool]: Boolean validity status per file"}
|
||||
]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -488,15 +507,9 @@ class MainApplication(QMainWindow):
|
||||
|
||||
|
||||
# Initialization to ensure that saving can occur
|
||||
self.raw_haemo_dict = {} # Processed Hemodynamic data
|
||||
self.config_dict = {} # Analysis parameters/settings
|
||||
self.epochs_dict = {} # Timing/Event data
|
||||
self.cha_dict = {} # Channel configurations
|
||||
self.contrast_results_dict = {} # Statistical results
|
||||
self.df_ind_dict = {} # Individual dataframes
|
||||
self.design_matrix_dict = {} # GLM Design matrices
|
||||
self.valid_dict = {} # Quality control/Validity flags
|
||||
self.fig_bytes_dict = {} # Cached plot images (serialized)
|
||||
for item in DATA_SCHEMA:
|
||||
setattr(self, item["key"], {})
|
||||
|
||||
self.file_metadata = {} # AGE, GENDER, GROUP
|
||||
self.metadata_cache = {} # Internal file/path information metadata cache
|
||||
self.bubble_widgets = {} # References to the UI "Bubble" objects
|
||||
@@ -878,15 +891,8 @@ class MainApplication(QMainWindow):
|
||||
self.files_done = set()
|
||||
self.files_failed = set()
|
||||
|
||||
self.raw_haemo_dict = {}
|
||||
self.config_dict = {}
|
||||
self.epochs_dict = {}
|
||||
self.fig_bytes_dict = {}
|
||||
self.cha_dict = {}
|
||||
self.contrast_results_dict = {}
|
||||
self.df_ind_dict = {}
|
||||
self.design_matrix_dict = {}
|
||||
self.valid_dict = {}
|
||||
for item in DATA_SCHEMA:
|
||||
setattr(self, item["key"], {})
|
||||
|
||||
self.metadata_cache = {}
|
||||
|
||||
@@ -1045,7 +1051,22 @@ class MainApplication(QMainWindow):
|
||||
|
||||
|
||||
def open_launcher_window(self):
|
||||
self.launcher_window = ViewerLauncherWidget(self.raw_haemo_dict, self.config_dict, self.fig_bytes_dict, self.cha_dict, self.contrast_results_dict, self.df_ind_dict, self.design_matrix_dict, self.epochs_dict, self.folding_bypass)
|
||||
data_map = {item["key"]: getattr(self, item["key"]) for item in DATA_SCHEMA}
|
||||
|
||||
# 2. Extract values in the specific order the widget constructor expects
|
||||
args = [
|
||||
data_map["raw_haemo_dict"],
|
||||
data_map["epochs_dict"],
|
||||
data_map["cha_dict"],
|
||||
data_map["df_ind_dict"],
|
||||
data_map["design_matrix_dict"],
|
||||
data_map["config_dict"],
|
||||
data_map["fig_bytes_dict"],
|
||||
data_map["contrast_results_dict"],
|
||||
self.folding_bypass
|
||||
]
|
||||
|
||||
self.launcher_window = ViewerLauncherWidget(*args)
|
||||
self.launcher_window.show()
|
||||
|
||||
def copy_text(self):
|
||||
@@ -1188,7 +1209,7 @@ class MainApplication(QMainWindow):
|
||||
def open_folder_dialog(self):
|
||||
folder_path = QFileDialog.getExistingDirectory(self, "Select Folder", "")
|
||||
if folder_path:
|
||||
snirf_files = [os.path.normpath(str(f)) for f in Path(folder_path).glob("*.snirf")]
|
||||
snirf_files = [os.path.normpath(str(f)) for f in Path(folder_path).rglob("*.snirf")]
|
||||
self._load_files_into_pipeline(snirf_files)
|
||||
|
||||
|
||||
@@ -1297,7 +1318,10 @@ class MainApplication(QMainWindow):
|
||||
has_param_changes = any(section.has_any_changes() for section in self.param_sections)
|
||||
|
||||
# Check if there is processed data
|
||||
has_processed_data = bool(getattr(self, 'raw_haemo_dict', None))
|
||||
has_processed_data = any(
|
||||
len(getattr(self, item["key"], {})) > 0
|
||||
for item in DATA_SCHEMA
|
||||
)
|
||||
|
||||
if not (has_processed_data or has_metadata or has_param_changes):
|
||||
if not onCrash: # Don't show popups during a crash/autosave
|
||||
@@ -1368,23 +1392,17 @@ class MainApplication(QMainWindow):
|
||||
current_params = self.config_dict[first_file]
|
||||
|
||||
version = CURRENT_VERSION
|
||||
project_data = {
|
||||
|
||||
project_data = {item["key"]: getattr(self, item["key"]) for item in DATA_SCHEMA}
|
||||
|
||||
project_data.update({
|
||||
"version": version,
|
||||
"file_list": file_list,
|
||||
"progress_states": progress_states,
|
||||
"raw_haemo_dict": self.raw_haemo_dict,
|
||||
"file_metadata": rel_metadata,
|
||||
"file_parameters": rel_file_params,
|
||||
"config_dict": self.config_dict,
|
||||
"epochs_dict": self.epochs_dict,
|
||||
"fig_bytes_dict": self.fig_bytes_dict,
|
||||
"cha_dict": self.cha_dict,
|
||||
"current_ui_params": current_params,
|
||||
"contrast_results_dict": self.contrast_results_dict,
|
||||
"df_ind_dict": self.df_ind_dict,
|
||||
"design_matrix_dict": self.design_matrix_dict,
|
||||
"valid_dict": self.valid_dict,
|
||||
}
|
||||
})
|
||||
|
||||
def sanitize(obj):
|
||||
if isinstance(obj, Path):
|
||||
@@ -1472,15 +1490,9 @@ class MainApplication(QMainWindow):
|
||||
return
|
||||
|
||||
|
||||
self.raw_haemo_dict = data.get("raw_haemo_dict", {})
|
||||
self.config_dict = data.get("config_dict", {})
|
||||
self.epochs_dict = data.get("epochs_dict", {})
|
||||
self.fig_bytes_dict = data.get("fig_bytes_dict", {})
|
||||
self.cha_dict = data.get("cha_dict", {})
|
||||
self.contrast_results_dict = data.get("contrast_results_dict", {})
|
||||
self.df_ind_dict = data.get("df_ind_dict", {})
|
||||
self.design_matrix_dict = data.get("design_matrix_dict", {})
|
||||
self.valid_dict = data.get("valid_dict", {})
|
||||
for item in DATA_SCHEMA:
|
||||
key = item["key"]
|
||||
setattr(self, key, data.get(key, {}))
|
||||
|
||||
project_dir = Path(filename).parent
|
||||
|
||||
@@ -1530,7 +1542,7 @@ class MainApplication(QMainWindow):
|
||||
first_file = next(iter(self.config_dict.keys()))
|
||||
self.restore_sections_from_config(self.config_dict[first_file])
|
||||
|
||||
has_data = bool(self.raw_haemo_dict)
|
||||
has_data = any(len(getattr(self, item["key"], {})) > 0 for item in DATA_SCHEMA)
|
||||
self.button1.setVisible(not has_data)
|
||||
self.button3.setVisible(has_data)
|
||||
|
||||
@@ -1955,15 +1967,8 @@ class MainApplication(QMainWindow):
|
||||
|
||||
self.button3.setVisible(False)
|
||||
|
||||
self.raw_haemo_dict = {}
|
||||
self.config_dict = {}
|
||||
self.epochs_dict = {}
|
||||
self.fig_bytes_dict = {}
|
||||
self.cha_dict = {}
|
||||
self.contrast_results_dict = {}
|
||||
self.df_ind_dict = {}
|
||||
self.design_matrix_dict = {}
|
||||
self.valid_dict = {}
|
||||
for item in DATA_SCHEMA:
|
||||
setattr(self, item["key"], {})
|
||||
|
||||
self.button1.clicked.disconnect(self.on_run_task)
|
||||
self.button1.setText("Cancel")
|
||||
@@ -2091,27 +2096,13 @@ class MainApplication(QMainWindow):
|
||||
# print(f"[DEBUG] Progress: {len(self.files_done)} / {self.files_total}")
|
||||
|
||||
if msg.get("success"):
|
||||
# Unpack the massive tuple
|
||||
raw_haemo, config, epochs, fig_bytes, cha, contrast, df_ind, design, valid = msg["result"]
|
||||
|
||||
# Initialize dictionaries once if needed
|
||||
if not hasattr(self, 'raw_haemo_dict') or self.raw_haemo_dict is None:
|
||||
attrs = ['raw_haemo_dict', 'config_dict', 'epochs_dict', 'fig_bytes_dict',
|
||||
'cha_dict', 'contrast_results_dict', 'df_ind_dict',
|
||||
'design_matrix_dict', 'valid_dict']
|
||||
for attr in attrs:
|
||||
setattr(self, attr, {})
|
||||
|
||||
self.files_results[file_path] = msg["result"]
|
||||
self.raw_haemo_dict[file_path] = raw_haemo
|
||||
self.config_dict[file_path] = config
|
||||
self.epochs_dict[file_path] = epochs
|
||||
self.fig_bytes_dict[file_path] = fig_bytes
|
||||
self.cha_dict[file_path] = cha
|
||||
self.contrast_results_dict[file_path] = contrast
|
||||
self.df_ind_dict[file_path] = df_ind
|
||||
self.design_matrix_dict[file_path] = design
|
||||
self.valid_dict[file_path] = valid
|
||||
results = msg["result"]
|
||||
self.files_results[file_path] = results
|
||||
|
||||
# Simple, clean assignment
|
||||
for item, value in zip(DATA_SCHEMA, results):
|
||||
getattr(self, item["key"])[file_path] = value
|
||||
|
||||
self.statusbar.showMessage(f"Processed: {os.path.basename(file_path)}")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user