From 12d732385137f933e641a78d2999f8506d5486c6 Mon Sep 17 00:00:00 2001 From: Markus Rosenstihl Date: Wed, 21 Oct 2026 22:48:46 +0200 Subject: [PATCH] added persistent ADC overflow warning --- src/damaris/gui/DamarisGUI.py | 89 +++++++++++++++++++++++++++++++++- src/damaris/gui/damaris3.glade | 35 +++++++++++-- 2 files changed, 118 insertions(+), 6 deletions(-) diff --git a/src/damaris/gui/DamarisGUI.py b/src/damaris/gui/DamarisGUI.py index e4f5863..3f66751 100644 --- a/src/damaris/gui/DamarisGUI.py +++ b/src/damaris/gui/DamarisGUI.py @@ -253,6 +253,7 @@ class DamarisGUI: "on_display_copy_data_to_clipboard_button_clicked": self.monitor.copy_display_data_to_clipboard, "on_display_copy_png_button_clicked": self.monitor.copy_canvas_as_png, "on_display_copy_svg_button_clicked": self.monitor.copy_canvas_as_svg, + "on_statusbar_overflow_label_clicked": self.monitor.clear_overflow_indicator, "on_experiment_script_textview_event": self.sw.textviews_modified, "on_main_notebook_switch_page": self.nopevent, "main_window_close": self.nopevent @@ -524,6 +525,8 @@ class DamarisGUI: logger.error("Experiment is still running or cleaning up!") return + self.monitor.clear_overflow_indicator( ) + # get config values: config_start = time.time() actual_config = self.config.get( ) @@ -714,6 +717,8 @@ class DamarisGUI: # cleanup self.si = None + if self.monitor.overflow_job_ids: + logger.warning( "ADC overflow occurred in jobs: %s", ', '.join( [str( j ) for j in self.monitor.overflow_job_ids] )) self.state = DamarisGUI.Edit_State self.sw.enable_editing( ) self.toolbar_run_button.set_sensitive( True ) @@ -917,6 +922,8 @@ class DamarisGUI: self.lockfile.del_experiment(self.id) # now everything is stopped + if self.monitor.overflow_job_ids: + logger.warning( "ADC overflow occurred in jobs: %s", ', '.join( [str( j ) for j in self.monitor.overflow_job_ids] )) self.state = DamarisGUI.Edit_State self.sw.enable_editing( ) self.toolbar_run_button.set_sensitive( True ) @@ -2959,13 +2966,28 @@ class MonitorWidgets: self.display_autoscaling_checkbutton = self.xml_gui.get_object( "display_autoscaling_checkbutton" ) self.display_statistics_checkbutton = self.xml_gui.get_object( "display_statistics_checkbutton" ) - self.display_descriptions_checkbutton = gtk.CheckButton(label="Show Desc.") + self.display_descriptions_checkbutton = gtk.CheckButton(label="Descr.") self.display_descriptions_checkbutton.set_active(True) self.display_descriptions_checkbutton.show() self.display_settings_frame.set_property("n-columns", 5) self.display_settings_frame.attach(self.display_descriptions_checkbutton, 4, 5, 0, 1, gtk.AttachOptions.FILL, 0, 0, 0) self.display_descriptions_checkbutton.connect("toggled", self.display_descriptions_toggled) + # ADC overflow indicator: "ADC" button, green = OK, red = overflow, + # right click opens a menu to reset the state + css = gtk.CssProvider( ) + css.load_from_data( b".adc_ok { background-image: none; background-color: #4caf50; }" + b".adc_error { background-image: none; background-color: #e53935; }" ) + gtk.StyleContext.add_provider_for_screen( gdk.Screen.get_default( ), css, gtk.STYLE_PROVIDER_PRIORITY_APPLICATION ) + self.overflow_css = css + self.overflow_indicator_button = gtk.Button( label="ADC" ) + self.overflow_indicator_button.set_tooltip_text( "ADC overflow indicator, red if an overflow occurred" ) + self.overflow_job_ids = [ ] + self.overflow_indicator_button.connect( "button-press-event", self.overflow_indicator_button_press ) + self.display_settings_frame.attach(self.overflow_indicator_button, 4, 5, 1, 2, gtk.AttachOptions.FILL, 0, 0, 0) + self.overflow_indicator_button.show( ) + self.set_overflow_indicator( False ) + # Matplot (Display_Table, 1st Row) -------------------------------------------------------- # create new plot @@ -3069,6 +3091,7 @@ class MonitorWidgets: self.fitresultlines = [ ] self.fit_source_keys = set( ) self.clipping_marker = None + self.statusbar_overflow_label = self.xml_gui.get_object( "statusbar_overflow_label" ) self.source_list_cache = {} def source_list_reset( self ): @@ -3709,6 +3732,61 @@ class MonitorWidgets: except Exception as e: logger.error("Error copying figure to clipboard: %s", e) + def set_overflow_indicator( self, clipped ): + """ + Set the background color of the ADC indicator button: green if + clipped is False, red if clipped is True. + + >>> monitor.set_overflow_indicator(True) # button turns red + """ + style = self.overflow_indicator_button.get_style_context( ) + style.remove_class( "adc_ok" ) + style.remove_class( "adc_error" ) + style.add_class( "adc_error" if clipped else "adc_ok" ) + + def overflow_indicator_button_press( self, widget, event ): + """ + ADC indicator button press handler: left click shows a dialog with + the list of job ids where an ADC overflow occurred, right click + opens a menu to reset the overflow state. + + >>> monitor.overflow_indicator_button_press(button, event) + """ + if event.button == 1: + if self.overflow_job_ids: + text = "\n".join( str( job_id ) for job_id in self.overflow_job_ids ) + else: + text = "No ADC overflow recorded." + dialog = gtk.MessageDialog(parent=self.main_window, + type=gtk.MessageType.WARNING, + flags=gtk.DialogFlags.MODAL, + buttons=("_OK", gtk.ResponseType.OK)) + dialog.set_markup("ADC OVERFLOW in jobs:") + dialog.format_secondary_text( text ) + dialog.run( ) + dialog.destroy( ) + elif event.button == 3: + menu = gtk.Menu( ) + item = gtk.MenuItem( label="Reset overflow state" ) + item.connect("activate", self.clear_overflow_indicator) + menu.append( item ) + menu.show_all( ) + menu.popup_at_pointer( event ) + return False + + def clear_overflow_indicator( self, widget=None, event=None ): + """ + Reset handler for the ADC overflow warning: sets the circle back to + green and clears the status bar warning, without starting a new + experiment. + + >>> monitor.clear_overflow_indicator() + """ + self.statusbar_overflow_label.set_text( "" ) + self.set_overflow_indicator( False ) + self.overflow_job_ids = [ ] + return False + ##################### functions to feed display def clear_display( self ): """ @@ -3986,6 +4064,15 @@ class MonitorWidgets: color="red", fontsize=20, fontweight="bold", ha="center", va="top", bbox=dict(facecolor='white', alpha=0.7, edgecolor='red')) + # the warning is only justified for results with a valid job_id; + # results without job id (e.g. backend errors) only get the plot marker + if getattr(in_result, "job_id", None) is not None: + if self.statusbar_overflow_label.get_text() == "": + self.statusbar_overflow_label.set_markup('ADC OVERFLOW') + self.set_overflow_indicator( True ) + if in_result.job_id not in self.overflow_job_ids: + self.overflow_job_ids.append( in_result.job_id ) + logger.warning( "ADC overflow detected in job %s", in_result.job_id ) elif self.clipping_marker is not None: try: self.clipping_marker.remove() diff --git a/src/damaris/gui/damaris3.glade b/src/damaris/gui/damaris3.glade index 9c36f3d..04e63da 100644 --- a/src/damaris/gui/damaris3.glade +++ b/src/damaris/gui/damaris3.glade @@ -1191,10 +1191,11 @@ Public License instead of this License. - Auto-Scaling + Autoscale True True False + start Rescale graph if new ymax is larger than the old one or shrinked more than 20% True True @@ -1211,10 +1212,11 @@ Public License instead of this License. - Show Statistics + Statistics True True False + start Plot error-bars if result to plot uses statistic True True @@ -2343,7 +2345,7 @@ Public License instead of this License. True False - 8 + 9 True @@ -2430,6 +2432,29 @@ Public License instead of this License. + + + True + False + True + + + + True + False + + True + ADC overflow detected. Click to acknowledge. + + + + + 7 + 8 + + + + True @@ -2438,8 +2463,8 @@ Public License instead of this License. 0 - 7 - 8 + 8 + 9