22
33from collections import defaultdict
44from io import BytesIO
5+ from itertools import cycle
56import math
67import os
78import unicodedata
1516
1617from openadapt .config import PERFORMANCE_PLOTS_DIR_PATH , config
1718from openadapt .models import ActionEvent
18- from openadapt import common , utils
19+ from openadapt import common , models , utils
1920
2021
2122# TODO: move parameters to config
@@ -321,15 +322,15 @@ def display_event(
321322
322323
323324def plot_performance (
324- recording_timestamp : float = None ,
325+ recording : models . Recording | None = None ,
325326 view_file : bool = False ,
326327 save_file : bool = True ,
327328 dark_mode : bool = False ,
328329) -> str :
329330 """Plot the performance of the event processing and writing.
330331
331332 Args:
332- recording_timestamp : The timestamp of the recording (defaults to latest)
333+ recording : The Recording whose performance to plot (defaults to latest).
333334 view_file: Whether to view the file after saving it.
334335 save_file: Whether to save the file.
335336 dark_mode: Whether to use dark mode.
@@ -339,34 +340,56 @@ def plot_performance(
339340 """
340341 type_to_proc_times = defaultdict (list )
341342 type_to_timestamps = defaultdict (list )
342- event_types = set ()
343343
344344 if dark_mode :
345345 plt .style .use ("dark_background" )
346346
347- # avoid circular import
348347 from openadapt .db import crud
349348
350- if not recording_timestamp :
351- recording_timestamp = crud .get_latest_recording ().timestamp
352- perf_stats = crud .get_perf_stats (recording_timestamp )
349+ if not recording :
350+ recording = crud .get_latest_recording ()
351+ session = crud .get_new_session (read_only = True )
352+ perf_stats = crud .get_perf_stats (session , recording )
353353 for perf_stat in perf_stats :
354354 event_type = perf_stat .event_type
355355 start_time = perf_stat .start_time
356356 end_time = perf_stat .end_time
357357 type_to_proc_times [event_type ].append (end_time - start_time )
358- event_types .add (event_type )
359358 type_to_timestamps [event_type ].append (start_time )
360359
361360 fig , ax = plt .subplots (1 , 1 , figsize = (20 , 10 ))
361+
362+ # Define markers to distinguish different event types
363+ markers = [
364+ "o" ,
365+ "s" ,
366+ "D" ,
367+ "^" ,
368+ "v" ,
369+ ">" ,
370+ "<" ,
371+ "p" ,
372+ "*" ,
373+ "h" ,
374+ "H" ,
375+ "+" ,
376+ "x" ,
377+ "X" ,
378+ "d" ,
379+ "|" ,
380+ "_" ,
381+ ]
382+ marker_cycle = cycle (markers )
383+
362384 for event_type in type_to_proc_times :
363385 x = type_to_timestamps [event_type ]
364386 y = type_to_proc_times [event_type ]
365- ax .scatter (x , y , label = event_type )
387+ ax .scatter (x , y , label = event_type , marker = next (marker_cycle ))
388+
366389 ax .legend ()
367390 ax .set_ylabel ("Duration (seconds)" )
368391
369- mem_stats = crud .get_memory_stats (recording_timestamp )
392+ mem_stats = crud .get_memory_stats (session , recording )
370393 timestamps = []
371394 mem_usages = []
372395 for mem_stat in mem_stats :
@@ -383,21 +406,18 @@ def plot_performance(
383406 memory_ax .set_ylabel ("Memory Usage (bytes)" )
384407
385408 if len (mem_usages ) > 0 :
386- # Get the handles and labels from both axes
387409 handles1 , labels1 = ax .get_legend_handles_labels ()
388410 handles2 , labels2 = memory_ax .get_legend_handles_labels ()
389411
390- # Combine the handles and labels from both axes
391412 all_handles = handles1 + handles2
392413 all_labels = labels1 + labels2
393414
394415 ax .legend (all_handles , all_labels )
395416
396- ax .set_title (f"{ recording_timestamp = } " )
417+ ax .set_title (f"{ recording . timestamp = } " )
397418
398- # TODO: add PROC_WRITE_BY_EVENT_TYPE
399419 if save_file :
400- fname_parts = ["performance" , str (recording_timestamp )]
420+ fname_parts = ["performance" , str (recording . timestamp )]
401421 fname = "-" .join (fname_parts ) + ".png"
402422 os .makedirs (PERFORMANCE_PLOTS_DIR_PATH , exist_ok = True )
403423 fpath = os .path .join (PERFORMANCE_PLOTS_DIR_PATH , fname )
0 commit comments