@@ -57,7 +57,9 @@ def __init__(self, filename):
5757
5858 self .input_ref = None
5959 self .output_ref = None
60- self .figure = plt .figure (figsize = (8 , 6 ))
60+ self .coherence_ref = None
61+ self .coherence_info_text = None
62+ self .figure = plt .figure (figsize = (8 , 6 ), layout = "constrained" )
6163 self .canvas = FigureCanvas (self .figure )
6264 self .initPlots ()
6365
@@ -87,6 +89,10 @@ def __init__(self, filename):
8789 layout_v .addLayout (top_group )
8890 layout_v .addWidget (self .canvas )
8991
92+ self .label_warning = QLabel ("" )
93+ self .label_warning .setStyleSheet ("color: red; font-weight: bold;" )
94+ layout_v .addWidget (self .label_warning )
95+
9096 btn_ok = QPushButton ("Load selection" )
9197 btn_ok .clicked .connect (self .loadSelection )
9298 layout_v .addWidget (btn_ok )
@@ -101,7 +107,7 @@ def __init__(self, filename):
101107 self .browseFiles ()
102108
103109 def loadSelection (self ):
104- if (self .t_start is None and self .t_start is None ) or (self .t_stop > self .t_start ):
110+ if (self .t_start is None and self .t_stop is None ) or (self .t_stop > self .t_start ):
105111 (self .t , self .u , self .y , self .v ) = self .data_extractor .getInputOutputData (self .topics [self .index_u ], self .topics [self .index_y ], self .t_start , self .t_stop )
106112 self .accept ()
107113 else :
@@ -213,12 +219,12 @@ def initPlots(self):
213219
214220 # --- Coherence Plot (Bottom) ---
215221 self .ax_coherence = self .figure .add_subplot (2 , 1 , 2 )
222+ color_coherence = 'tab:grey'
223+ plot_refs = self .ax_coherence .plot ([], [], color = color_coherence )
224+ self .coherence_ref = plot_refs [0 ]
216225 self .ax_coherence .set_title ("Coherence" )
217- self .ax_coherence .set_xlabel ("Frequency [Hz] " )
226+ self .ax_coherence .set_xlabel ("Frequency (Hz) " )
218227 self .ax_coherence .set_ylabel ("Coherence" )
219- self .coherence_ref , = self .ax_coherence .plot ([], [])
220-
221- self .figure .tight_layout ()
222228
223229 self .canvas .mpl_connect ('scroll_event' , self .zoom_fun )
224230 self .canvas .draw ()
@@ -243,10 +249,22 @@ def plotY(self):
243249 self .ax_out .set_ylim ([min_y , max_y ])
244250 self .canvas .draw ()
245251
252+ def onselect (self , xmin , xmax ):
253+ indmin , indmax = np .searchsorted (self .t , (xmin , xmax ))
254+ indmax = min (len (self .t ) - 1 , indmax )
255+ indmin = min (indmin , indmax )
256+
257+ self .t_start = self .t [indmin ]
258+ self .t_stop = self .t [indmax ]
259+ self .ax .set_xlim (self .t_start - 1.0 , self .t_stop + 1.0 )
260+ self .canvas .draw ()
261+
262+ self .plotCoherence ()
263+
246264 def plotCoherence (self ):
247265 if len (self .t ) == 0 or len (self .u ) == 0 or len (self .y ) == 0 :
248266 return
249-
267+
250268 # Use getInputOutputData with selected range
251269 if self .t_start is not None and self .t_stop is not None and self .t_stop > self .t_start :
252270 t_sel , u_sel , y_sel , _ = self .data_extractor .getInputOutputData (
@@ -260,14 +278,16 @@ def plotCoherence(self):
260278 )
261279
262280 num_samples = len (t_sel )
263- if num_samples < 256 : # I kind of made up this number -> maybe requires some research
264- self .ax_coherence .clear ()
265- self .ax_coherence .set_title ("Coherence (Selection too short)" )
266- self .ax_coherence .text (0.5 , 0.5 , f"Not enough data ({ num_samples } samples).\n Select a larger window." ,
267- ha = 'center' , va = 'center' , transform = self .ax_coherence .transAxes ,
268- fontsize = 10 , color = 'red' )
269- self .canvas .draw ()
270- return
281+
282+ if num_samples < 256 :
283+ self .label_warning .setText (f"Not enough data ({ num_samples } samples). Select a larger window." )
284+ self .label_warning .show ()
285+
286+ self .coherence_ref .set_xdata ([])
287+ self .coherence_ref .set_ydata ([])
288+ return
289+ else :
290+ self .label_warning .hide ()
271291
272292 # Estimate sampling frequency
273293 time_diffs = np .diff (t_sel )
@@ -277,45 +297,35 @@ def plotCoherence(self):
277297 fs = 1 / avg_time_diff
278298
279299 # Choose segment size
280- nperseg = min (1024 , max ( 256 , num_samples // 8 ) )
300+ nperseg = min (1024 , num_samples // 4 )
281301
282302 # Compute coherence
283303 freq , Cuy = signal .coherence (u_sel , y_sel , fs , nperseg = nperseg )
284304
285- # Update coherence plot
286- self .ax_coherence .clear ()
287- self .ax_coherence .plot (freq , Cuy , label = 'Coherence(u, y)' )
288- self .ax_coherence .set_title ("Coherence" )
289- self .ax_coherence .set_xlabel ("Frequency [Hz]" )
290- self .ax_coherence .set_ylabel ("Coherence" )
305+ # Update coherence plot
306+ self .coherence_ref .set_xdata (freq )
307+ self .coherence_ref .set_ydata (Cuy )
291308 self .ax_coherence .set_xlim ([min (freq ), max (freq )])
292309 self .ax_coherence .set_ylim ([0 , 1 ])
293- self .ax_coherence .grid (True )
294310
295- # Add informative annotation
311+ # Remove previous annotation if it exists
312+ if self .coherence_info_text is not None :
313+ self .coherence_info_text .remove ()
314+ self .coherence_info_text = None
315+
296316 duration = t_sel [- 1 ] - t_sel [0 ]
297317 freq_res = fs / nperseg
298318 info_text = (f"Samples: { num_samples } , Duration: { duration :.2f} s, "
299319 f"fs: { fs :.1f} Hz, nperseg: { nperseg } , Δf: { freq_res :.2f} Hz" )
320+
321+ self .coherence_info_text = self .ax_coherence .text (
322+ 0.98 , 0.02 , info_text ,
323+ ha = 'right' , va = 'bottom' ,
324+ transform = self .ax_coherence .transAxes ,
325+ fontsize = 8 , color = 'gray' )
300326
301- self .ax_coherence .text (0.98 , 0.02 , info_text ,
302- ha = 'right' , va = 'bottom' ,
303- transform = self .ax_coherence .transAxes ,
304- fontsize = 8 , color = 'gray' )
305-
306- self .canvas .draw ()
307-
308- def onselect (self , xmin , xmax ):
309- indmin , indmax = np .searchsorted (self .t , (xmin , xmax ))
310- indmax = min (len (self .t ) - 1 , indmax )
311- indmin = min (indmin , indmax )
312-
313- self .t_start = self .t [indmin ]
314- self .t_stop = self .t [indmax ]
315- self .ax .set_xlim (self .t_start - 1.0 , self .t_stop + 1.0 )
316327 self .canvas .draw ()
317328
318- self .plotCoherence ()
319329
320330 def zoom_fun (self , event ):
321331 base_scale = 1.1
0 commit comments