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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +42 -7
app.py CHANGED
@@ -1,4 +1,4 @@
1
- # app.py (Final, Robust, and Workable Version with Chained Dropdowns)
2
  import pandas as pd
3
  import numpy as np
4
  import matplotlib.pyplot as plt
@@ -84,7 +84,7 @@ 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
@@ -161,7 +161,7 @@ class EnhancedAIvsRealGazeAnalyzer:
161
  trial_info = self.combined_data[(self.combined_data['participant_id'] == str(participant)) & (self.combined_data['Question'] == question)].iloc[0]
162
  summary_text = f"**Actual Answer:** `{trial_info['Answer_Correctness']}`"
163
 
164
- return summary_text, fig, gr.Slider(maximum=slider_max, value=fixation_num, interactive=True)
165
 
166
  def analyze_rq1_metric(self, metric):
167
  if not metric or metric not in self.combined_data.columns: return None, "Metric not found."
@@ -176,7 +176,23 @@ class EnhancedAIvsRealGazeAnalyzer:
176
  def update_question_dropdown(self, participant):
177
  """Dynamically updates the question dropdown based on the selected participant."""
178
  valid_questions = self.valid_playback_trials.get(participant, [])
179
- return gr.Dropdown(choices=sorted(valid_questions), interactive=True, value=None)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
 
181
  # --- DATA SETUP & GRADIO APP ---
182
  def setup_and_load_data():
@@ -235,10 +251,29 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
235
  rq2_test_size_slider.release(fn=analyzer.run_prediction_model, inputs=[rq2_test_size_slider, rq2_estimators_slider], outputs=outputs_rq2)
236
  rq2_estimators_slider.release(fn=analyzer.run_prediction_model, inputs=[rq2_test_size_slider, rq2_estimators_slider], outputs=outputs_rq2)
237
 
 
238
  # Chained dropdown logic for Tab 3
239
- playback_participant.change(fn=analyzer.update_question_dropdown, inputs=playback_participant, outputs=playback_question)
240
- playback_question.change(lambda: 0, None, playback_slider).then(fn=analyzer.generate_gaze_playback, inputs=[playback_participant, playback_question, playback_slider], outputs=outputs_playback)
241
- playback_slider.release(fn=analyzer.generate_gaze_playback, inputs=[playback_participant, playback_question, playback_slider], outputs=outputs_playback)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
242
 
243
  demo.load(fn=analyzer.analyze_rq1_metric, inputs=rq1_metric_dropdown, outputs=[rq1_plot_output, rq1_summary_output])
244
  demo.load(fn=analyzer.run_prediction_model, inputs=[rq2_test_size_slider, rq2_estimators_slider], outputs=outputs_rq2)
 
1
+ # app.py
2
  import pandas as pd
3
  import numpy as np
4
  import matplotlib.pyplot as plt
 
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
 
161
  trial_info = self.combined_data[(self.combined_data['participant_id'] == str(participant)) & (self.combined_data['Question'] == question)].iloc[0]
162
  summary_text = f"**Actual Answer:** `{trial_info['Answer_Correctness']}`"
163
 
164
+ return summary_text, fig, gr.Slider(maximum=slider_max, value=fixation_num, interactive=True, step=1, minimum=0)
165
 
166
  def analyze_rq1_metric(self, metric):
167
  if not metric or metric not in self.combined_data.columns: return None, "Metric not found."
 
176
  def update_question_dropdown(self, participant):
177
  """Dynamically updates the question dropdown based on the selected participant."""
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():
 
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)