clockclock commited on
Commit
cac722b
·
verified ·
1 Parent(s): ca7b998

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +37 -22
app.py CHANGED
@@ -1,4 +1,4 @@
1
- # app.py
2
  import pandas as pd
3
  import numpy as np
4
  import matplotlib.pyplot as plt
@@ -30,6 +30,7 @@ class EnhancedAIvsRealGazeAnalyzer:
30
  self.model = None
31
  self.scaler = None
32
  self.feature_names = []
 
33
 
34
  def _find_and_standardize_participant_col(self, df, filename):
35
  participant_col = next((c for c in df.columns if 'participant' in str(c).lower()), None)
@@ -84,7 +85,10 @@ class EnhancedAIvsRealGazeAnalyzer:
84
  self.combined_data['Answer_Correctness'] = self.combined_data['Correct'].map({True: 'Correct', False: 'Incorrect'})
85
 
86
  self.numeric_cols = self.combined_data.select_dtypes(include=np.number).columns.tolist()
87
- self.time_ metrics = [c for c in self.numeric_cols if any(k in c.lower() for k in ['time', 'duration', 'fixation'])]
 
 
 
88
  self.valid_playback_participants = sorted(list(self.valid_playback_trials.keys()))
89
  print(f"--- Data Loading Successful. Found {len(self.valid_playback_participants)} participants with fixation data. ---")
90
  return self
@@ -178,28 +182,22 @@ class EnhancedAIvsRealGazeAnalyzer:
178
  valid_questions = self.valid_playback_trials.get(participant, [])
179
  return gr.Dropdown(choices=sorted(valid_questions), interactive=True, value=None, label="2. Select a Question")
180
 
181
- # <<< FIX START: Step 1 -> Add a new handler method for when a question is selected. >>>
182
- # This function provides a clean, single entry point to reset the visualization.
183
  def handle_new_trial_selection(self, participant, question):
184
  """Called when a new trial is selected. Resets the view to the first fixation."""
185
  if not participant or not question:
186
- # Return a default/empty state for all outputs if nothing is selected
187
  return "Select a trial to begin.", None, gr.Slider(value=0, interactive=False)
188
-
189
- # Start the playback at the very first fixation for a better user experience.
190
- # You can change '1' to '0' if you prefer it to start completely empty.
191
  initial_fixation_num = 1
192
-
193
- # Call the main generation function with this fixed initial value
194
  return self.generate_gaze_playback(participant, question, initial_fixation_num)
195
- # <<< FIX END >>>
196
 
197
  # --- DATA SETUP & GRADIO APP ---
198
  def setup_and_load_data():
199
  repo_url = "https://github.com/RextonRZ/GenAIEyeTrackingCleanedDataset"
200
  repo_dir = "GenAIEyeTrackingCleanedDataset"
201
- if not os.path.exists(repo_dir): git.Repo.clone_from(repo_url, repo_dir)
202
- else: print("Data repository already exists.")
 
 
 
203
  base_path = repo_dir
204
  response_file_path = os.path.join(repo_dir, "GenAI Response.xlsx")
205
  analyzer = EnhancedAIvsRealGazeAnalyzer().load_and_process_data(base_path, response_file_path)
@@ -248,35 +246,52 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
248
 
249
  rq1_metric_dropdown.change(fn=analyzer.analyze_rq1_metric, inputs=rq1_metric_dropdown, outputs=[rq1_plot_output, rq1_summary_output])
250
 
251
- rq2_test_size_slider.release(fn=analyzer.run_prediction_model, inputs=[rq2_test_size_slider, rq2_estimators_slider], outputs=outputs_rq2)
252
  rq2_estimators_slider.release(fn=analyzer.run_prediction_model, inputs=[rq2_test_size_slider, rq2_estimators_slider], outputs=outputs_rq2)
253
 
254
- # <<< FIX START: Step 2 -> Update the event wiring for Tab 3. >>>
255
- # Chained dropdown logic for Tab 3
256
  playback_participant.change(
257
  fn=analyzer.update_question_dropdown,
258
  inputs=playback_participant,
259
  outputs=playback_question
260
  )
261
 
262
- # When a question is selected, call the new handler to reset the entire playback view.
263
- # This is much cleaner and more reliable than the previous .then() chain.
264
  playback_question.change(
265
  fn=analyzer.handle_new_trial_selection,
266
  inputs=[playback_participant, playback_question],
267
  outputs=outputs_playback
268
  )
269
 
270
- # The slider event handler remains the same and works correctly for scrubbing through fixations.
271
  playback_slider.release(
272
  fn=analyzer.generate_gaze_playback,
273
  inputs=[playback_participant, playback_question, playback_slider],
274
  outputs=outputs_playback
275
  )
276
- # <<< FIX END >>>
277
 
278
- demo.load(fn=analyzer.analyze_rq1_metric, inputs=rq1_metric_dropdown, outputs=[rq1_plot_output, rq1_summary_output])
279
- demo.load(fn=analyzer.run_prediction_model, inputs=[rq2_test_size_slider, rq2_estimators_slider], outputs=outputs_rq2)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
280
 
281
  if __name__ == "__main__":
282
  demo.launch()
 
1
+ # app.py (Corrected and Ready to Run)
2
  import pandas as pd
3
  import numpy as np
4
  import matplotlib.pyplot as plt
 
30
  self.model = None
31
  self.scaler = None
32
  self.feature_names = []
33
+ self.time_metrics = [] # Initialize here
34
 
35
  def _find_and_standardize_participant_col(self, df, filename):
36
  participant_col = next((c for c in df.columns if 'participant' in str(c).lower()), None)
 
85
  self.combined_data['Answer_Correctness'] = self.combined_data['Correct'].map({True: 'Correct', False: 'Incorrect'})
86
 
87
  self.numeric_cols = self.combined_data.select_dtypes(include=np.number).columns.tolist()
88
+
89
+ # <<< FIX: Removed the space in the variable name here >>>
90
+ self.time_metrics = [c for c in self.numeric_cols if any(k in c.lower() for k in ['time', 'duration', 'fixation'])]
91
+
92
  self.valid_playback_participants = sorted(list(self.valid_playback_trials.keys()))
93
  print(f"--- Data Loading Successful. Found {len(self.valid_playback_participants)} participants with fixation data. ---")
94
  return self
 
182
  valid_questions = self.valid_playback_trials.get(participant, [])
183
  return gr.Dropdown(choices=sorted(valid_questions), interactive=True, value=None, label="2. Select a Question")
184
 
 
 
185
  def handle_new_trial_selection(self, participant, question):
186
  """Called when a new trial is selected. Resets the view to the first fixation."""
187
  if not participant or not question:
 
188
  return "Select a trial to begin.", None, gr.Slider(value=0, interactive=False)
 
 
 
189
  initial_fixation_num = 1
 
 
190
  return self.generate_gaze_playback(participant, question, initial_fixation_num)
 
191
 
192
  # --- DATA SETUP & GRADIO APP ---
193
  def setup_and_load_data():
194
  repo_url = "https://github.com/RextonRZ/GenAIEyeTrackingCleanedDataset"
195
  repo_dir = "GenAIEyeTrackingCleanedDataset"
196
+ if not os.path.exists(repo_dir):
197
+ print(f"Cloning repository {repo_url}...")
198
+ git.Repo.clone_from(repo_url, repo_dir)
199
+ else:
200
+ print("Data repository already exists.")
201
  base_path = repo_dir
202
  response_file_path = os.path.join(repo_dir, "GenAI Response.xlsx")
203
  analyzer = EnhancedAIvsRealGazeAnalyzer().load_and_process_data(base_path, response_file_path)
 
246
 
247
  rq1_metric_dropdown.change(fn=analyzer.analyze_rq1_metric, inputs=rq1_metric_dropdown, outputs=[rq1_plot_output, rq1_summary_output])
248
 
249
+ train_event = rq2_test_size_slider.release(fn=analyzer.run_prediction_model, inputs=[rq2_test_size_slider, rq2_estimators_slider], outputs=outputs_rq2)
250
  rq2_estimators_slider.release(fn=analyzer.run_prediction_model, inputs=[rq2_test_size_slider, rq2_estimators_slider], outputs=outputs_rq2)
251
 
 
 
252
  playback_participant.change(
253
  fn=analyzer.update_question_dropdown,
254
  inputs=playback_participant,
255
  outputs=playback_question
256
  )
257
 
 
 
258
  playback_question.change(
259
  fn=analyzer.handle_new_trial_selection,
260
  inputs=[playback_participant, playback_question],
261
  outputs=outputs_playback
262
  )
263
 
 
264
  playback_slider.release(
265
  fn=analyzer.generate_gaze_playback,
266
  inputs=[playback_participant, playback_question, playback_slider],
267
  outputs=outputs_playback
268
  )
 
269
 
270
+ # Pre-load the initial state of the dashboard
271
+ def initial_load():
272
+ # Load the first tab's content
273
+ rq1_fig, rq1_summary = analyzer.analyze_rq1_metric(analyzer.time_metrics[0] if analyzer.time_metrics else None)
274
+
275
+ # Train the initial model for the second tab
276
+ model_summary, report_df, feature_fig, status_md = analyzer.run_prediction_model(0.3, 100)
277
+
278
+ # Return all the values needed to populate the outputs on load
279
+ return {
280
+ rq1_plot_output: rq1_fig,
281
+ rq1_summary_output: rq1_summary,
282
+ rq2_summary_output: model_summary,
283
+ rq2_table_output: report_df,
284
+ rq2_plot_output: feature_fig,
285
+ rq2_status: status_md
286
+ }
287
+
288
+ demo.load(
289
+ fn=initial_load,
290
+ outputs=[
291
+ rq1_plot_output, rq1_summary_output,
292
+ rq2_summary_output, rq2_table_output, rq2_plot_output, rq2_status
293
+ ]
294
+ )
295
 
296
  if __name__ == "__main__":
297
  demo.launch()