Rogerjs commited on
Commit
b7e02dd
·
verified ·
1 Parent(s): 44eaeed

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +43 -38
app.py CHANGED
@@ -32,15 +32,14 @@ def inspect_file(file):
32
  return "No file uploaded.", [], "No preview available."
33
  file_path = file.name
34
  _, file_ext = os.path.splitext(file_path)
35
-
36
  file_ext = file_ext.lower()
 
37
  if file_ext == ".fif":
38
- # FIF files: We know they're MNE compatible
39
- # No columns to choose from, just proceed with default analysis
40
  return (
41
- "FIF file detected. No need for time column selection. Default sampling frequency will be read from file.",
42
  [],
43
- "FIF file doesn't require further inspection."
44
  )
45
  elif file_ext == ".csv":
46
  # Read a small portion of the CSV to determine columns
@@ -52,14 +51,13 @@ def inspect_file(file):
52
  cols = list(df.columns)
53
  preview = df.head().to_markdown()
54
  return (
55
- "CSV file detected. Select a time column if available, or leave it blank and specify a default frequency.",
56
  cols,
57
  preview
58
  )
59
  else:
60
  return "Unsupported file format.", [], "No preview available."
61
 
62
-
63
  def load_eeg_data(file_path, default_sfreq=256.0, time_col='time'):
64
  """
65
  Load EEG data with flexibility.
@@ -77,8 +75,8 @@ def load_eeg_data(file_path, default_sfreq=256.0, time_col='time'):
77
  elif file_ext == '.csv':
78
  df = pd.read_csv(file_path)
79
 
80
- # If time_col is specified and in df, use it to compute sfreq
81
  if time_col and time_col in df.columns:
 
82
  time = df[time_col].values
83
  data_df = df.drop(columns=[time_col])
84
 
@@ -88,20 +86,28 @@ def load_eeg_data(file_path, default_sfreq=256.0, time_col='time'):
88
  data_df = data_df.drop(columns=[col])
89
 
90
  if len(time) < 2:
91
- # Not enough time points, fallback to default_sfreq
92
  sfreq = default_sfreq
93
  else:
94
  # Compute sfreq from time
95
- sfreq = 1.0 / np.mean(np.diff(time))
 
 
 
 
 
96
  else:
97
  # No time column used, assume default_sfreq
98
- # Drop non-numeric columns
99
  for col in df.columns:
100
  if not pd.api.types.is_numeric_dtype(df[col]):
101
  df = df.drop(columns=[col])
102
  data_df = df
103
  sfreq = default_sfreq
104
 
 
 
 
 
105
  ch_names = list(data_df.columns)
106
  data = data_df.values.T # shape: (n_channels, n_samples)
107
 
@@ -117,9 +123,15 @@ def load_eeg_data(file_path, default_sfreq=256.0, time_col='time'):
117
  def analyze_eeg(file, default_sfreq, time_col):
118
  if time_col == "(No time column)":
119
  time_col = None
120
- raw = load_eeg_data(file.name, default_sfreq=float(default_sfreq), time_col=time_col)
121
 
122
- psd, freqs = mne.time_frequency.psd_welch(raw, fmin=1, fmax=40)
 
 
 
 
 
 
 
123
  alpha_power = compute_band_power(psd, freqs, 8, 12)
124
  beta_power = compute_band_power(psd, freqs, 13, 30)
125
 
@@ -130,7 +142,6 @@ def analyze_eeg(file, default_sfreq, time_col):
130
 
131
  prompt = f"""You are a neuroscientist analyzing EEG features.
132
  Data Summary: {data_summary}
133
-
134
  Provide a concise, user-friendly interpretation of these findings in simple terms.
135
  """
136
  inputs = tokenizer.encode(prompt, return_tensors="pt").to(model.device)
@@ -140,49 +151,43 @@ Provide a concise, user-friendly interpretation of these findings in simple term
140
  summary = tokenizer.decode(outputs[0], skip_special_tokens=True)
141
  return summary
142
 
143
-
144
- #########################
145
- # BUILD THE GRADIO INTERFACE
146
- #########################
147
-
148
- # Step 1: Inspect file
149
  def preview_file(file):
150
  msg, cols, preview = inspect_file(file)
151
- # Add placeholder choice
152
- if len(cols) > 0:
153
- cols = ["(No time column)"] + cols
154
- default_value = "(No time column)"
155
- else:
156
- cols = []
157
- default_value = None
158
-
159
- # Use gr.update(...) for the dropdown output
160
- return msg, gr.update(choices=cols, value=default_value), preview
161
-
162
 
 
 
163
 
164
  with gr.Blocks() as demo:
165
  gr.Markdown("# NeuroNarrative-Lite: EEG Summary with Flexible Preprocessing")
166
  gr.Markdown(
167
- "Upload an EEG file (FIF or CSV). If it's CSV, we will inspect the file and let you choose a time column. "
168
- "If no suitable time column is found, leave it blank and provide a default sampling frequency."
 
 
169
  )
170
 
171
  file_input = gr.File(label="Upload your EEG data (FIF or CSV)")
172
  preview_button = gr.Button("Inspect File")
173
  msg_output = gr.Markdown()
174
- cols_dropdown = gr.Dropdown(label="Select Time Column (optional)", interactive=True)
 
175
  preview_output = gr.Markdown()
176
 
177
  preview_button.click(preview_file, inputs=[file_input], outputs=[msg_output, cols_dropdown, preview_output])
178
 
179
- default_sfreq_input = gr.Textbox(label="Default Sampling Frequency (Hz) if no time column", value="256")
180
  analyze_button = gr.Button("Run Analysis")
181
  result_output = gr.Textbox(label="Analysis Summary")
182
 
183
- analyze_button.click(analyze_eeg,
184
- inputs=[file_input, default_sfreq_input, cols_dropdown],
185
- outputs=[result_output])
 
 
186
 
187
  if __name__ == "__main__":
188
  demo.launch()
 
32
  return "No file uploaded.", [], "No preview available."
33
  file_path = file.name
34
  _, file_ext = os.path.splitext(file_path)
 
35
  file_ext = file_ext.lower()
36
+
37
  if file_ext == ".fif":
38
+ # FIF files: MNE compatible, no columns needed
 
39
  return (
40
+ "FIF file detected. No need for time column selection. The file's sampling frequency will be used.",
41
  [],
42
+ "FIF file doesn't require column inspection."
43
  )
44
  elif file_ext == ".csv":
45
  # Read a small portion of the CSV to determine columns
 
51
  cols = list(df.columns)
52
  preview = df.head().to_markdown()
53
  return (
54
+ "CSV file detected. Select a time column if available, or choose (No time column) and specify a default frequency.",
55
  cols,
56
  preview
57
  )
58
  else:
59
  return "Unsupported file format.", [], "No preview available."
60
 
 
61
  def load_eeg_data(file_path, default_sfreq=256.0, time_col='time'):
62
  """
63
  Load EEG data with flexibility.
 
75
  elif file_ext == '.csv':
76
  df = pd.read_csv(file_path)
77
 
 
78
  if time_col and time_col in df.columns:
79
+ # Use the selected time column to compute sfreq
80
  time = df[time_col].values
81
  data_df = df.drop(columns=[time_col])
82
 
 
86
  data_df = data_df.drop(columns=[col])
87
 
88
  if len(time) < 2:
89
+ # Not enough time points to compute sfreq, fallback
90
  sfreq = default_sfreq
91
  else:
92
  # Compute sfreq from time
93
+ dt = np.mean(np.diff(time))
94
+ # Ensure dt is positive
95
+ if dt <= 0:
96
+ sfreq = default_sfreq
97
+ else:
98
+ sfreq = 1.0 / dt
99
  else:
100
  # No time column used, assume default_sfreq
 
101
  for col in df.columns:
102
  if not pd.api.types.is_numeric_dtype(df[col]):
103
  df = df.drop(columns=[col])
104
  data_df = df
105
  sfreq = default_sfreq
106
 
107
+ # Ensure sfreq is positive
108
+ if sfreq <= 0:
109
+ sfreq = 256.0 # fallback if something odd happens
110
+
111
  ch_names = list(data_df.columns)
112
  data = data_df.values.T # shape: (n_channels, n_samples)
113
 
 
123
  def analyze_eeg(file, default_sfreq, time_col):
124
  if time_col == "(No time column)":
125
  time_col = None
 
126
 
127
+ fs = float(default_sfreq)
128
+ if fs <= 0:
129
+ fs = 256.0
130
+
131
+ raw = load_eeg_data(file.name, default_sfreq=fs, time_col=time_col)
132
+
133
+ # Use the directly imported psd_welch function
134
+ psd, freqs = psd_welch(raw, fmin=1, fmax=40)
135
  alpha_power = compute_band_power(psd, freqs, 8, 12)
136
  beta_power = compute_band_power(psd, freqs, 13, 30)
137
 
 
142
 
143
  prompt = f"""You are a neuroscientist analyzing EEG features.
144
  Data Summary: {data_summary}
 
145
  Provide a concise, user-friendly interpretation of these findings in simple terms.
146
  """
147
  inputs = tokenizer.encode(prompt, return_tensors="pt").to(model.device)
 
151
  summary = tokenizer.decode(outputs[0], skip_special_tokens=True)
152
  return summary
153
 
 
 
 
 
 
 
154
  def preview_file(file):
155
  msg, cols, preview = inspect_file(file)
156
+ # Always include (No time column) as the first choice
157
+ # If no columns were found, we still have (No time column) as an option
158
+ cols = ["(No time column)"] + cols
159
+ default_value = "(No time column)"
 
 
 
 
 
 
 
160
 
161
+ # Return an update dict for the dropdown
162
+ return msg, gr.update(choices=cols, value=default_value), preview
163
 
164
  with gr.Blocks() as demo:
165
  gr.Markdown("# NeuroNarrative-Lite: EEG Summary with Flexible Preprocessing")
166
  gr.Markdown(
167
+ "Upload an EEG file (FIF or CSV). If it's CSV, click 'Inspect File' to preview columns. "
168
+ "Select a time column if available or '(No time column)' if not. "
169
+ "If no time column is chosen, provide a default sampling frequency. "
170
+ "Then click 'Run Analysis'."
171
  )
172
 
173
  file_input = gr.File(label="Upload your EEG data (FIF or CSV)")
174
  preview_button = gr.Button("Inspect File")
175
  msg_output = gr.Markdown()
176
+ # Allow custom values in case something goes off
177
+ cols_dropdown = gr.Dropdown(label="Select Time Column (optional)", allow_custom_value=True, interactive=True)
178
  preview_output = gr.Markdown()
179
 
180
  preview_button.click(preview_file, inputs=[file_input], outputs=[msg_output, cols_dropdown, preview_output])
181
 
182
+ default_sfreq_input = gr.Textbox(label="Default Sampling Frequency (Hz) if no time column", value="100")
183
  analyze_button = gr.Button("Run Analysis")
184
  result_output = gr.Textbox(label="Analysis Summary")
185
 
186
+ analyze_button.click(
187
+ analyze_eeg,
188
+ inputs=[file_input, default_sfreq_input, cols_dropdown],
189
+ outputs=[result_output]
190
+ )
191
 
192
  if __name__ == "__main__":
193
  demo.launch()