Skip to content
Merged
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
40 changes: 20 additions & 20 deletions channel_table.csv
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
Channel_Names,Category,Description
f3-m2;f3m2;f3-m2+m1;eeg f3-a2;f3-a2;f3:m2;m2:f3;f3:a2;a2:f3;f3-avg,eeg,
f4-m1;f4m1;f4-m1+m2;eeg f4-a1;f4-a1;f4:m1;m1:f4;f4:a1;a1:f4;f4-avg,eeg,
c3-m2;c3m2;c3-m2+m1;eeg c3-a2;c3-a2;c3:m2;m2:c3;c3:a2;a2:c3;c3-avg,eeg,
c4-m1;c4m1;c4-m1+m2;eeg c4-a1;c4-a1;c4:m1;m1:c4;c4:a1;a1:c4;c4-avg,eeg,
o1-m2;o1m2;o1-m2+m1;eeg o1-a2;o1-a2;o1:m2;m2:o1;o1:a2;a2:o1;o1-avg,eeg,
o2-m1;o2m1;o2-m1+m2;eeg o2-a1;o2-a1;o2:m1;m1:o2;o2:a1;a1:o2;o2-avg,eeg,
f3-m2;f3m2;f3-m2+m1;eeg f3-a2;f3-a2;f3:m2;m2:f3;f3:a2;f3/m2;f3/a2;a2:f3;f3-avg,eeg,
f4-m1;f4m1;f4-m1+m2;eeg f4-a1;f4-a1;f4:m1;m1:f4;f4:a1;f4/m1;f4/a1;a1:f4;f4-avg,eeg,
c3-m2;c3m2;c3-m2+m1;eeg c3-a2;c3-a2;c3:m2;m2:c3;c3:a2;c3/m2;c3/a2;a2:c3;c3-avg,eeg,
c4-m1;c4m1;c4-m1+m2;eeg c4-a1;c4-a1;c4:m1;m1:c4;c4:a1;c4/m1;c4/a1;a1:c4;c4-avg,eeg,
o1-m2;o1m2;o1-m2+m1;eeg o1-a2;o1-a2;o1:m2;m2:o1;o1:a2;o1/m2;o1/a2;a2:o1;o1-avg,eeg,
o2-m1;o2m1;o2-m1+m2;eeg o2-a1;o2-a1;o2:m1;m1:o2;o2:a1;o2/m1;o2/a1;a1:o2;o2-avg,eeg,
m1;a1,eeg,
m2;a2,eeg,
f3,eeg,
Expand All @@ -17,20 +17,20 @@ e1,eog,
e2,eog,
e2-m1;roc;eog(r);eog-r;eog r;eog2;rt eye (e2);rt. Eye (e2);eog roc-a1;eog roc-a2;roc-a1;eog roc-m1;roc-m1;r-eog;e2-m2;e2:m1;m1:e2;e2:a1;a1:e2;e1-avg,eog,
e1-m2;loc;eog(l);eog-l;eog l;eog1;lt eye (e1);lt. eye (e1);eog loc-a1;eog loc-a2;loc-a2;eog loc-m2;loc-m2;l-eog;e1-m1;e1:m2;m2:e1;e1:a2;a2:e1;e2-avg,eog,
chin1-chin2;chin1chin2;chin;china;chin_emg;emg.subm;emg;chin emg;emg chin;emg-chin;chin1-chin3,chin emg,
chin 1;l chin;chin l;chinl;chin1;emg1;chin_emg1;chin emg 1;chin emg 1,chin emg,
chin 2;r chin;chin r;chinr;chin2;emg2;chin_emg2;chin emg 2;chin emg 2,chin emg,
lat;l leg;lleg;left leg;left_leg;l emg;lemg;leg 1;leg1;leg-l;plml,leg emg,
rat;r leg;rleg;right leg;right_leg;r emg;remg;l/rat;emg-leg;leg;legs;leg 2;leg2;leg-r;plmr,leg emg,
rleg+;rat1;rat 1;rat-u,leg emg,
rleg-;rat2;rat 2;rat-l,leg emg,
lleg+;lat1;lat 1;lat-u,leg emg,
lleg-;lat2;lat 2;lat-l,leg emg,
ecg;ekg;ecg-la;ecg-v1;ecg-v2;ecg-ll;ecg-ra;ecg l;ecgl;ecg i;ecg ii,ecg,
abd;abdomen;abdominal;abd res;abdo res;abdo;effort abd;abdominal effort;abdom,resp,
chest;thorax;thoracic;thor res;thoracic res;chest res;thor;effort tho;thoracic effort,resp,
chin1-chin2;chin1chin2;chin;china;chin_emg;emg.subm;emg;chin emg;emg chin;emg-chin;chin1-chin3;chin-a;emg1-emg2,chin emg,
chin 1;l chin;chin l;chinl;chin1;emg1;chin_emg1;chin emg 1;chin emg 1;chin-l;emg1,chin emg,
chin 2;r chin;chin r;chinr;chin2;emg2;chin_emg2;chin emg 2;chin emg 2;chin-r;emg2,chin emg,
lat;l leg;lleg;left leg;left_leg;l emg;lemg;leg 1;leg1;leg-l;plml;l-leg;gnd-leg l,leg emg,
rat;r leg;rleg;right leg;right_leg;r emg;remg;l/rat;emg-leg;leg;legs;leg 2;leg2;leg-r;plmr;r-leg;gnd-leg r,leg emg,
rleg+;rat1;rat 1;rat-u;r-leg1,leg emg,
rleg-;rat2;rat 2;rat-l;r-leg2,leg emg,
lleg+;lat1;lat 1;lat-u;l-leg1,leg emg,
lleg-;lat2;lat 2;lat-l;l-leg2,leg emg,
ecg;ekg;ecg-la;ecg-v1;ecg-v2;ecg-ll;ecg-ra;ecg l;ecgl;ecg i;ecg ii;ekg-r;ekg-l;ecg1;ecg2;ecg ref-ecg1;ecg ref-ecg2;ecg ref-ecg3,ecg,
abd;abdomen;abdominal;abd res;abdo res;abdo;effort abd;abdominal effort;abdom;respitrace abdom,resp,
chest;thorax;thoracic;thor res;thoracic res;chest res;thor;effort tho;thoracic effort;respitrace chest,resp,
ptaf;pressure;npt;nptaf;nasal_pressure;nasal pressure;nasal;nasaloral;nasal oral;cannula;cannula_flow;cannula flow;nasal cannula;nasal canula;nasal flow;nasalflow,resp,
airflow;flow_dr;flow;air flow;thermal airflow;airflow thermal;airflow2;flow ii;thermal;therm;thermal flow;thermistor;thermistor 2;thermister,resp,
airflow;flow_dr;flow;air flow;thermal airflow;airflow thermal;airflow2;flow ii;thermal;therm;thermal flow;thermistor;thermistor 2;thermister;gnd-flow,resp,
cflow;c-flow;c flow;cpap flow;cflowext;cflowresmed,resp,
cpres;cpress;c press;c_press;cpap pressure;cpap_press;c-pres;c-press;cpap-pressure;cpap pres;cpap press;cpap pressure 1;cpressure,resp,
spo2;sao2;osat;o2sat;o2 sat;o2-sat;o2-saturation,resp,
spo2;sao2;osat;o2sat;o2 sat;o2-sat;o2-saturation;gnd-spo2,resp,
14 changes: 9 additions & 5 deletions team_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,12 @@ def extract_physiological_features(physiological_data, physiological_fs, csv_pat
new_label = rename_map.get(old_label, old_label.lower())
processed_channels[new_label] = data
# Mapping the sampling rate to the new label
processed_fs[new_label] = physiological_fs.get(old_label, 200.0) # Default to 200 if missing

if old_label in physiological_fs:
processed_fs[new_label] = physiological_fs[old_label]
else:
# Report error and stop if no FS is found for a kept channel
raise KeyError(f"Sampling frequency (fs) not found for channel '{old_label}' ")

Copilot AI Mar 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The raised KeyError message has an extra trailing space before the closing quote, which makes the error message look sloppy and harder to match in logs/tests. Remove the trailing whitespace and consider including the standardized label (new_label) as well, since that’s what downstream code uses.

Suggested change
raise KeyError(f"Sampling frequency (fs) not found for channel '{old_label}' ")
raise KeyError(
f"Sampling frequency (fs) not found for channel '{old_label}' (standardized label '{new_label}')"
)

Copilot uses AI. Check for mistakes.

if 'physiological_data' in locals(): del physiological_data

# Step 3: Construct Bipolar Derivations
Expand All @@ -279,7 +283,7 @@ def extract_physiological_features(physiological_data, physiological_fs, csv_pat
('c3-m2', 'c3', ['m2']), ('c4-m1', 'c4', ['m1']),
('o1-m2', 'o1', ['m2']), ('o2-m1', 'o2', ['m1']),
('e1-m2', 'e1', ['m2']), ('e2-m1', 'e2', ['m1']),
('chin1-chin2', 'chin1', ['chin2']),
('chin1-chin2', 'chin 1', ['chin 2']),
('lat', 'lleg+', ['lleg-']), ('rat', 'rleg+', ['rleg-'])
]

Expand Down Expand Up @@ -433,7 +437,7 @@ def count_discrete_events(key):
features.extend([ahi_auto, arousal_auto, limb_auto])

# --- 2. Sleep Architecture (from stage_caisr) ---
# Standard labels: 0=W, 1=N1, 2=N2, 3=N3, 4=R (or similar mapping)
# Standard labels: 5=W, 4=R, 3=N1, 2=N2, 1=N3 (or similar mapping)

Copilot AI Mar 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The stage-label mapping comment here now conflicts with the comment in extract_human_annotations_features (which states 0=W, 1=N1, ...). If algorithmic and human stage labels truly differ, this needs to be documented clearly; otherwise it’s easy to misinterpret w_pct/r_pct/... as being computed on the wrong codes.

Suggested change
# Standard labels: 5=W, 4=R, 3=N1, 2=N2, 1=N3 (or similar mapping)
# Algorithmic CAISR stage labels for stage_caisr:
# 5 = Wake (W), 4 = REM (R), 3 = N1, 2 = N2, 1 = N3.
# NOTE: This mapping applies only to the algorithmic stage_caisr output and
# differs from the human annotation mapping used in
# extract_human_annotations_features (e.g., 0 = W, 1 = N1, ...).
# The w_pct/r_pct/n1_pct/n2_pct/n3_pct features below are computed
# using these algorithmic codes.

Copilot uses AI. Check for mistakes.
stages = algo_data.get('stage_caisr', np.array([]))
# Filter out invalid/background values (like the 9.0 in your sample)
valid_stages = stages[stages < 9.0]
Expand All @@ -448,7 +452,7 @@ def count_discrete_events(key):
n3_pct = np.mean(valid_stages == 1)

# Sleep Efficiency: (N1+N2+N3+R) / Total
efficiency = np.mean(valid_stages > 0)
efficiency = np.mean((valid_stages >= 1) & (valid_stages <= 4))

Copilot AI Mar 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

efficiency is now computed as the proportion of epochs in stages 1–4, but extract_human_annotations_features in the same file still computes efficiency as np.mean(valid_stages > 0). If human and algorithmic stage encodings are intended to be comparable features, this introduces an inconsistency in the feature definitions; align the formulas (or add an explicit comment explaining why they differ).

Copilot uses AI. Check for mistakes.
else:
w_pct = n1_pct = n2_pct = n3_pct = r_pct = efficiency = 0.0

Expand Down
Loading