mainly whitespace, but also some generic qol improvements

This commit is contained in:
tyler committed 2026-10-14 20:17:23 -07:00
1 parent 2a5e3f5606
commit 3a8ffbdf70
26 files changed
+1871 -1224

No files matched your search

+80 -78
View File
@@ -12,6 +12,7 @@ import os
from typing import Any
# External library imports
from mne import Epochs
from pandas import DataFrame
from mne.io.base import BaseRaw
@@ -25,8 +26,9 @@ from src.shared.shareddata import APP_NAME
class ExportToCSVWidget(CSVUIMixin, FlaresBaseWidget):
def __init__(
self,
haemo_dict: dict[str, BaseRaw],
self,
haemo_dict: dict[str, BaseRaw],
epochs_dict: dict[str, Epochs],
cha_dict: dict[str, DataFrame],
df_ind_dict: dict[str, DataFrame],
design_matrix_dict: dict[str, DataFrame],
@@ -36,10 +38,11 @@ class ExportToCSVWidget(CSVUIMixin, FlaresBaseWidget):
fir_feature_dict: dict[str, dict[str, Any]],
qc_dict: dict[str, dict[str, Any]],
) -> None:
super().__init__("ExportToCSV")
self.setWindowTitle(f"Export To CSV Viewer - {APP_NAME.upper()}")
self.haemo_dict = haemo_dict
self.epochs_dict = epochs_dict
self.cha_dict = cha_dict
self.df_ind_dict = df_ind_dict
self.design_matrix = design_matrix_dict
@@ -48,20 +51,19 @@ class ExportToCSVWidget(CSVUIMixin, FlaresBaseWidget):
self.config_dict = config_dict
self.fir_feature_dict = fir_feature_dict
self.qc_dict = qc_dict
self.setup_csv_ui(["0 (Export Data to CSV)", "1 (CSV for SPARKS)", "2 (Export Configuration to CSV)", "3 (Paragraph of Configuration)", "4 (Export FIR Waveform Features to CSV)",
"5 (Export Quality Control Metrics to CSV)",
"6 (Export Master Consolidated Matrix [All Participants into 1 CSV])"
"5 (Export Quality Control Metrics to CSV)", "6 (Export Master Consolidated Matrix [All Participants into 1 CSV])"
])
def process_request(self):
selected_display_names = self._get_checked_items(self.participant_dropdown)
selected_file_paths: list[str] = []
for display_name in selected_display_names:
for fp, short_label in self.participant_map.items():
expected_display = f"{short_label} ({os.path.basename(fp)})"
if display_name == expected_display:
if display_name == expected_display:
selected_file_paths.append(fp)
break
@@ -74,7 +76,7 @@ class ExportToCSVWidget(CSVUIMixin, FlaresBaseWidget):
return
output_dir = QFileDialog.getExistingDirectory(self, "Select Output Folder for CSV Exports")
if not output_dir:
print("Export cancelled: No folder selected.")
return
@@ -120,78 +122,78 @@ class ExportToCSVWidget(CSVUIMixin, FlaresBaseWidget):
magic_string = self.gen_magic_str(first_params)
self.placeholder_label.setText(magic_string)
# elif idx == 4:
# # FIR Waveform Features Export
# fir_data = self.fir_feature_dict.get(file_path)
# if fir_data and isinstance(fir_data, dict):
# names = fir_data.get("feature_names", [])
# vals = fir_data.get("features", [])
# chans = fir_data.get("feature_channels", [])
elif idx == 4:
# FIR Waveform Features Export
fir_data = self.fir_feature_dict.get(file_path)
if fir_data:
names = fir_data.get("feature_names", [])
vals = fir_data.get("features", [])
chans = fir_data.get("feature_channels", [])
# fir_df = DataFrame({
# "Feature_Name": names,
# "Channel": chans if len(chans) == len(names) else ["N/A"] * len(names),
# "Value": vals
# })
# save_path = os.path.join(output_dir, f"{base_filename}_fir_features.csv")
# fir_df.to_csv(save_path, index=False)
# success_count += 1
fir_df = DataFrame({
"Feature_Name": names,
"Channel": chans if len(chans) == len(names) else ["N/A"] * len(names),
"Value": vals
})
save_path = os.path.join(output_dir, f"{base_filename}_fir_features.csv")
fir_df.to_csv(save_path, index=False)
success_count += 1
# elif idx == 5:
# # Quality Control (QC) Metrics Export
# qc_data = self.qc_dict.get(file_path)
# if qc_data and isinstance(qc_data, dict):
# qc_df = DataFrame(list(qc_data.items()), columns=["Metric", "Value"])
# save_path = os.path.join(output_dir, f"{base_filename}_qc_metrics.csv")
# qc_df.to_csv(save_path, index=False)
# success_count += 1
elif idx == 5:
# Quality Control (QC) Metrics Export
qc_data = self.qc_dict.get(file_path)
if qc_data and isinstance(qc_data, dict):
qc_df = DataFrame(list(qc_data.items()), columns=["Metric", "Value"])
save_path = os.path.join(output_dir, f"{base_filename}_qc_metrics.csv")
qc_df.to_csv(save_path, index=False)
success_count += 1
# elif idx == 6:
# # Master Consolidated Matrix (1 single CSV combining all selected participants)
# save_path = os.path.join(output_dir, f"{APP_NAME}_master_consolidated.csv")
# if not os.path.exists(save_path):
# master_rows: list[dict[str, Any]] = []
# for fp in selected_file_paths:
# abs_path = os.path.abspath(fp)
# grp = self.group_dict.get(fp, "Unknown")
# row: dict[str, Any] = {"Participant": abs_path, "Group": grp}
elif idx == 6:
# Master Consolidated Matrix (1 single CSV combining all selected participants)
save_path = os.path.join(output_dir, f"{APP_NAME}_master_consolidated.csv")
if not os.path.exists(save_path):
master_rows: list[dict[str, Any]] = []
for fp in selected_file_paths:
abs_path = os.path.abspath(fp)
grp = self.group_dict.get(fp, "Unknown")
row: dict[str, Any] = {"Participant": abs_path, "Group": grp}
# # QC Metrics
# qc_info = self.qc_dict.get(fp, {})
# if isinstance(qc_info, dict):
# for mk, mv in qc_info.items():
# row[f"QC_{mk}"] = mv
# QC Metrics
qc_info = self.qc_dict.get(fp, {})
if isinstance(qc_info, dict):
for mk, mv in qc_info.items():
row[f"QC_{mk}"] = mv
# # FIR Features
# fir_info = self.fir_feature_dict.get(fp, {})
# print("1")
# if isinstance(fir_info, dict):
# print("2")
# f_names = fir_info.get("feature_names", [])
# f_vals = fir_info.get("features", [])
# print("3")
# if len(f_names) == len(f_vals):
# print("4")
# for fn, fv in zip(f_names, f_vals):
# row[f"FIR_{fn}"] = fv
# FIR Features
fir_info = self.fir_feature_dict.get(fp, {})
print("1")
if isinstance(fir_info, dict):
print("2")
f_names = fir_info.get("feature_names", [])
f_vals = fir_info.get("features", [])
print("3")
if len(f_names) == len(f_vals):
print("4")
for fn, fv in zip(f_names, f_vals):
row[f"FIR_{fn}"] = fv
# master_rows.append(row)
master_rows.append(row)
# if master_rows:
# df_master = DataFrame(master_rows)
# df_master.to_csv(save_path, index=False)
# success_count += 1
if master_rows:
df_master = DataFrame(master_rows)
df_master.to_csv(save_path, index=False)
success_count += 1
else:
print(f"No method defined for index {idx}")
except Exception as e:
print(f"Failed to export {file_path} (Type {idx}): {e}")
# 4. Final Notification
if success_count > 0:
QMessageBox.information(self, "Export Complete", f"Successfully saved {success_count} CSV files to:\n{output_dir}")
# # If SPARKS export was included, show the Event Window once at the end
# if 1 in selected_indexes:
# win = UpdateEventsWindow(
@@ -203,62 +205,62 @@ class ExportToCSVWidget(CSVUIMixin, FlaresBaseWidget):
def gen_magic_str(self, all_params: dict[str, str]) -> str:
magic_str = "To start, the data was loaded into the application. "
if all_params['DOWNSAMPLE']:
magic_str += f"The data was downsampled to {all_params['DOWNSAMPLE_FREQUENCY']}hz. "
else:
magic_str += "The data was not downsampled and was retained at its original sampling frequency. "
if all_params['TRIM']:
magic_str += f"The data was then trimmed to only keep {all_params['SECONDS_TO_KEEP']} seconds before the first event, as the earlier data with no events would not be needed. "
else:
magic_str += "The data was not trimmed and was retained at its original length. "
if all_params['OPTODE_PLACEMENT']:
magic_str += f"A visualization check of the optode locations in 3D space was performed to ensure that they were at the correct location. "
if all_params['SHORT_CHANNELS']:
magic_str += f"A short channel(s) was specified with the maximum length of a short channel being {all_params['SHORT_CHANNELS_THRESHOLD']} metres. Channels that were over this distance but under {all_params['LONG_CHANNELS_THRESHOLD']} metres were retained. "
else:
magic_str += f"No short channel was specified. Channels between the lengths of {all_params['SHORT_CHANNELS_THRESHOLD']} and {all_params['LONG_CHANNELS_THRESHOLD']} meters were used with all other channles being discarded. "
if all_params['HEART_RATE']:
magic_str += f"The heart rate of the participant was attempted to be calculated. {all_params['SECONDS_TO_STRIP_HR']} seconds were ignored from the start of the file to avoid motion artifacts. "
magic_str += f"The heart rate had hard limits of {all_params['MAX_LOW_HR']} to {all_params['MAX_HIGH_HR']} and was smoothed across {all_params['SMOOTHING_WINDOW_HR']} samples. "
else:
magic_str += "The heart rate of the participants was not attempted to be calculated. "
if all_params['SCI']:
magic_str += f"The Scalp Coupling Index was calculated over {all_params['SCI_TIME_WINDOW']} second windows. The threshold value was {all_params['SCI_THRESHOLD']}. "
else:
magic_str += "Scalp Coupling Index was not used. "
if all_params['SNR']:
magic_str += f"The Signal to Noise Ratio was calculated. The threshold value was set to {all_params['SNR_THRESHOLD']}db. "
else:
magic_str += "The Signal to Noise Ratio was not used. "
if all_params['PSP']:
magic_str += f"Peak Spectral Power was calculated over {all_params['PSP_TIME_WINDOW']} second windows. The threshold value was {all_params['PSP_THRESHOLD']}. "
else:
magic_str += "Peak Spectral Power was not used. "
if all_params['COEFF_VAR']:
magic_str += f"The Coefficient of Variation was calculated. The threshold value was set to {all_params['COEFF_VAR_THRESHOLD']}. "
else:
magic_str += "The Coefficient of Variation was not used. "
if all_params['MAD']:
magic_str += f"Median Absolute Deviation was calculated. The threshold value was set to {all_params['MAD_THRESHOLD']}. "
else:
magic_str += "Median Absolute Deviation was not used. "
if all_params['PSD_NOISE']:
magic_str += f"Power Spectral Density Noise was calculated with a target frequency divisor of {all_params['TARGET_FREQ_DIV']} and a decibal limit of {all_params['DB_LIMIT']}. "
else:
magic_str += f"Power Spectral Density Noise was not used. "
magic_str += "More coming soon."
return magic_str