11"""Some small helpers for getting timing information."""
22
33import logging
4+ import pathlib
45import re
56
67import matplotlib .pyplot as plt
1011import rich .console
1112import seaborn as sns
1213
13- DEFAULT_FOLDERS = ["frontend" , "backend" , "lcd" , "timing" ]
14- FRONTEND_TIMERS = ["frontend/spin" ]
15- BACKEND_TIMERS = ["backend/spin" ]
16- OBJECT_TIMERS = ["frontend/objects_detection" , "frontend/objects_graph_update" ]
17- PLACE_TIMERS = ["frontend/detect_gvd" , "frontend/update_gvd_places" ]
18- ROOM_TIMERS = ["backend/room_detection" ]
1914DEFAULT_COMPARE_KEYS = [
2015 "frontend/object_detection" ,
2116 "gvd/extract_graph" ,
@@ -31,11 +26,12 @@ def _get_time_array_from_log(filename):
3126 return arr
3227
3328
34- def _get_filenames (result_path , subdir ):
35- if not (result_path / subdir ).exists ():
29+ def _get_filenames (result_path ):
30+ result_path = pathlib .Path (result_path )
31+ if not result_path .exists ():
3632 return []
3733
38- return [f for f in ( result_path / subdir ). iterdir () if f . match ("*timing_raw.csv" )]
34+ return [f for f in result_path . rglob ("*timing_raw.csv" )]
3935
4036
4137def _get_timer_name (path ):
@@ -64,22 +60,20 @@ def _get_longform_df(durations, filter_func=None):
6460 continue
6561
6662 times = np .squeeze (info [:, 1 ])
67- part_name = name .split ("/" )[1 ]
6863 data = np .concatenate ((data , times ), axis = None )
69- names += [part_name ] * len (times )
64+ names += [name ] * len (times )
7065
7166 if len (names ) == 0 :
7267 return None
7368
7469 return pd .DataFrame ({"Name" : names , "Elapsed Time [s]" : data })
7570
7671
77- def collect_timing_info (path , default_folders = None ):
72+ def collect_timing_info (path , folders_to_use = None ):
7873 """Collect timing info for a specfic path."""
79- timing_files = []
80- folders_to_use = default_folders or DEFAULT_FOLDERS
81- for folder in folders_to_use :
82- timing_files += _get_filenames (path , folder )
74+ timing_files = _get_filenames (path )
75+ if folders_to_use :
76+ timing_files = [x for x in timing_files if x .parent in folders_to_use ]
8377
8478 return {_get_timer_name (f ): _get_time_array_from_log (f ) for f in timing_files }
8579
@@ -139,30 +133,30 @@ def _get_stat_str(stat):
139133 console .print (table )
140134
141135
142- def plot_durations (durations , keys = [ "frontend" , "backend" ], rt_threshold = None ):
136+ def plot_durations (durations , keys ):
143137 """Make a plot of durations."""
144138 sns .set ()
145139 sns .set_style ("whitegrid" )
146140 sns .set_context ("notebook" )
147141 fig , ax = plt .subplots (len (keys ), 1 , squeeze = False )
148142
149143 for idx , key in enumerate (keys ):
150- ax [idx ][0 ].set_title (f"{ key .capitalize ()} Timing Distributions" )
151- df = _get_longform_df (durations , lambda x : key not in x )
144+ matcher = re .compile (key )
145+ ax [idx ][0 ].set_title (f"{ key } Timing Distributions" )
146+ df = _get_longform_df (durations , lambda x : matcher .match (x ))
152147 if df is None :
153148 continue
154149
155150 sns .boxenplot (data = df , x = "Name" , y = "Elapsed Time [s]" , ax = ax [idx ][0 ])
156151 lax = ax [idx ][0 ]
157152 lax .set_xticks (lax .get_xticks (), lax .get_xticklabels (), rotation = 30 , ha = "right" )
158- _draw_realtime_threshold (lax , rt_threshold )
159153
160154 fig .set_size_inches ([14 , 12 * len (keys )])
161155 fig .tight_layout ()
162156 plt .show ()
163157
164158
165- def plot_trends (durations , keys = [ "frontend" , "backend" ], rt_threshold = None ):
159+ def plot_trends (durations , keys ):
166160 """Make a plot of durations."""
167161 sns .set ()
168162 sns .set_style ("whitegrid" )
@@ -171,8 +165,9 @@ def plot_trends(durations, keys=["frontend", "backend"], rt_threshold=None):
171165
172166 for idx , key in enumerate (keys ):
173167 added_plot = False
168+ matcher = re .compile (key )
174169 for name , time_array in durations .items ():
175- if key not in name :
170+ if not matcher . match ( name ) :
176171 continue
177172
178173 assert len (time_array .shape ) == 2 and time_array .shape [1 ] == 2
@@ -183,60 +178,51 @@ def plot_trends(durations, keys=["frontend", "backend"], rt_threshold=None):
183178 ax [idx ][0 ].plot (to_plot [:, 0 ], to_plot [:, 1 ], label = name )
184179 added_plot = True
185180
186- ax [idx ][0 ].set_title (f"{ key . capitalize () } Timing Trends" )
181+ ax [idx ][0 ].set_title (f"{ key } Timing Trends" )
187182 ax [idx ][0 ].set_xlabel ("Timestamp [s]" )
188183 ax [idx ][0 ].set_ylabel ("Elapsed Time [s]" )
189184 if added_plot :
190- _draw_realtime_threshold (ax [idx ][0 ], rt_threshold )
191185 ax [idx ][0 ].legend ()
192186
193187 fig .set_size_inches ([16 , 8 * len (keys )])
194188 plt .show ()
195189
196190
197- def plot_comparison (results , plot_config , keys , use_bars = False , rt_threshold = None ):
191+ def plot_comparison (results , keys , use_bars = False ):
198192 """Plot timing comparison for different results directories."""
193+ sns .set ()
194+ sns .set_style ("whitegrid" )
195+ sns .set_context ("notebook" )
196+
199197 data = np .array ([])
200198 labels = []
201199 result_set = []
202200
203201 keys = [x .replace ("/" , "_" ) for x in keys ]
204202 for stem , result in results .items ():
205- result_label = plot_config .get ("result_map" , {}).get (stem , stem .upper ())
206203 for key in keys :
207204 if key not in result :
208205 continue
209206
210- # TODO(nathan) remap key to actual name
211- # TODO(nathan) add result key
212- key_label = plot_config .get ("key_map" , {}).get (key , key )
213-
214207 num_values = len (result [key ])
215- labels += num_values * [key_label ]
216- result_set += num_values * [result_label ]
208+ data = np .hstack ((data , np .squeeze (result [key ][:, 1 ])))
209+ labels += num_values * [key ]
210+ result_set += num_values * [stem .upper ()]
217211
218- sns .set ()
219- sns .set_style ("white" )
220- sns .set_context ("poster" , font_scale = 1.7 , rc = {"lines.linewidth" : 2.0 })
221-
222- fig , ax = plt .subplots ()
223212 value_key = "Elapsed Time [s]"
224- timer_key = plot_config . get ( "xlabel" , " Timer Name")
213+ timer_key = " Timer Name"
225214 result_key = "Result Name"
226215
216+ fig , ax = plt .subplots ()
227217 df = pd .DataFrame ({value_key : data , timer_key : labels , result_key : result_set })
228218 if use_bars :
229- sns .barplot (x = timer_key , y = value_key , hue = result_key , data = df )
219+ sns .barplot (x = timer_key , y = value_key , hue = result_key , data = df , ax = ax )
230220 else :
231- sns .boxenplot (x = timer_key , y = value_key , hue = result_key , data = df )
232-
233- if "title" in plot_config :
234- ax .set_title (plot_config ["title" ])
221+ sns .boxenplot (x = timer_key , y = value_key , hue = result_key , data = df , ax = ax )
235222
236- _draw_realtime_threshold (ax , rt_threshold )
237223 ax .legend ()
224+ ax .set_xticks (ax .get_xticks (), ax .get_xticklabels (), rotation = 30 , ha = "right" )
238225
239- sns .despine ()
240226 fig .set_size_inches ([14 , 12 ])
241227 fig .tight_layout ()
242228 plt .show ()
0 commit comments