def __init__(self, config, esp32, *args, **kwargs): #pylint: disable=too-many-statements """ Initializes the main window for the MVM GUI. See below for subfunction setup description. """ super(MainWindow, self).__init__(*args, **kwargs) uifile = os.path.join(os.path.dirname(os.path.realpath(__file__)), "mainwindow.ui") uic.loadUi(uifile, self) self.config = config self.esp32 = esp32 settings_file = SettingsFile(self.config["settings_file_path"]) self.user_settings = settings_file.load() ''' Start the alarm handler, which will check for ESP alarms ''' # Instantiate the critical alarm handler meant for severe communications and hardware error self.critical_alarm_handler = CriticalAlarmHandler(self, esp32) self.alarm_h = AlarmHandler( self.config, self.esp32, self.alarmbar, self.critical_alarm_handler.call_system_failure) ''' Get the toppane and child pages ''' self.toppane = self.findChild(QtWidgets.QStackedWidget, "toppane") self.main = self.findChild(QtWidgets.QWidget, "main") self.initial = self.findChild(QtWidgets.QWidget, "initial") self.startup = self.findChild(QtWidgets.QWidget, "startup") self.criticalerrorpage = self.findChild(QtWidgets.QWidget, "criticalerrorpage") ''' Get the center pane (plots) widgets ''' self.centerpane = self.findChild(QtWidgets.QStackedWidget, "centerpane") self.plots_all = self.findChild(QtWidgets.QWidget, "plots_all") self.alarms_settings = self.findChild(QtWidgets.QWidget, "alarms_settings") ''' Get the bottombar and child pages ''' self.bottombar = self.findChild(QtWidgets.QStackedWidget, "bottombar") self.toolbar = self.findChild(QtWidgets.QWidget, "toolbar") self.menu = self.findChild(QtWidgets.QWidget, "menu") self.frozen_bot = self.findChild(QtWidgets.QWidget, "frozenplots_bottom") self.settingsbar = self.findChild(QtWidgets.QWidget, "settingsbar") self.specialbar = self.findChild(QtWidgets.QWidget, "specialbar") self.blank = self.findChild(QtWidgets.QWidget, "blank") self.settingsfork = self.findChild(QtWidgets.QWidget, "settingsforkbar") self.alarmsbar = self.findChild(QtWidgets.QWidget, "alarmsbar") self.numpadbar = self.findChild(QtWidgets.QWidget, "numpadbar") self.criticalerrorbar = self.findChild(QtWidgets.QWidget, "criticalerrorbar") ''' Get the stackable bits on the right ''' self.rightbar = self.main.findChild(QtWidgets.QStackedWidget, "rightbar") self.monitors_bar = self.main.findChild(QtWidgets.QWidget, "monitors_bar") self.frozen_right = self.main.findChild(QtWidgets.QWidget, "frozenplots_right") ''' Get initial and startup buttons ''' self.button_new_patient = self.initial.findChild( QtWidgets.QPushButton, "button_new_patient") self.button_resume_patient = self.initial.findChild( QtWidgets.QPushButton, "button_resume_patient") self.button_resume_patient.setEnabled(self.user_settings != {}) self.button_start_settings = self.startup.findChild( QtWidgets.QPushButton, "button_start_settings") self.button_start_vent = self.startup.findChild( QtWidgets.QPushButton, "button_start_vent") self.button_start_test = self.startup.findChild( QtWidgets.QPushButton, "button_start_test") ''' Get toolbar widgets ''' self.button_menu = self.toolbar.findChild(QtWidgets.QPushButton, "button_menu") self.button_unlockscreen = self.toolbar.findChild( QtWidgets.QPushButton, "button_unlockscreen") self.home_button = self.toolbar.findChild(QtWidgets.QWidget, "home_button") self.goto_menu = self.toolbar.findChild(QtWidgets.QWidget, "goto_menu") self.goto_unlock = self.toolbar.findChild(QtWidgets.QWidget, "goto_unlock") self.label_status = self.toolbar.findChild(QtWidgets.QLabel, "label_status") # Get menu widgets and connect settings for the menu widget self.button_back = self.menu.findChild(QtWidgets.QPushButton, "button_back") self.button_settingsfork = self.menu.findChild(QtWidgets.QPushButton, "button_settingsfork") self.button_startstop = self.menu.findChild(QtWidgets.QPushButton, "button_startstop") self.button_autoassist = self.menu.findChild(QtWidgets.QPushButton, "button_autoassist") self.button_specialops = self.menu.findChild(QtWidgets.QPushButton, "button_specialops") self.button_alarms = self.settingsfork.findChild( QtWidgets.QPushButton, "button_alarms") self.button_settings = self.settingsfork.findChild( QtWidgets.QPushButton, "button_settings") self.button_lockscreen = self.settingsfork.findChild( QtWidgets.QPushButton, "button_lockscreen") self.button_backsettings = self.settingsfork.findChild( QtWidgets.QPushButton, "button_backsettings") self.button_backalarms = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_backalarms") self.button_applyalarm = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_applyalarm") self.button_resetalarm = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_resetalarm") self.button_upalarm = self.alarmsbar.findChild(QtWidgets.QPushButton, "button_upalarm") self.button_downalarm = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_downalarm") self.button_offalarm = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_offalarm") self.button_freeze = self.specialbar.findChild(QtWidgets.QPushButton, "button_freeze") self.button_backspecial = self.specialbar.findChild( QtWidgets.QPushButton, "button_backspecial") # Get frozen plots bottom bar widgets and connect self.button_unfreeze = self.frozen_bot.findChild( QtWidgets.QPushButton, "button_unfreeze") # Connect initial startup buttons self.button_resume_patient.pressed.connect(self.goto_resume_patient) self.button_new_patient.pressed.connect(self.goto_new_patient) self.button_start_vent.pressed.connect(self.goto_main) self.button_start_test.pressed.connect(self.goto_selftest) self.button_spiro_calib.pressed.connect(self.goto_spiro_calibration) self.button_start_settings.pressed.connect(self.goto_settings) # Connect back and menu buttons to toolbar and menu # This effectively defines navigation from the bottombar. # Toolbar self.button_menu.pressed.connect(self.show_menu) # Menu self.button_back.pressed.connect(self.show_toolbar) self.button_alarms.pressed.connect(self.goto_alarms) self.button_settingsfork.pressed.connect(self.show_settingsfork) self.button_specialops.pressed.connect(self.show_specialbar) # Settings self.button_settings.pressed.connect(self.goto_settings) self.button_lockscreen.pressed.connect(self.lock_screen) self.button_backsettings.pressed.connect(self.show_menu) # Special self.button_freeze.pressed.connect(self.freeze_plots) self.button_unfreeze.pressed.connect(self.unfreeze_plots) self.button_backspecial.pressed.connect(self.show_menu) # Confirmation bar self.messagebar = MessageBar(self) self.bottombar.insertWidget(self.bottombar.count(), self.messagebar) # Spirometer Calibration self.spiro_calib.connect_mainwindow_esp32(self, self.esp32) # Self Test self.self_test.connect_mainwindow_esp32_selftestbar( self, self.esp32, self.selftestbar) # Assign unlock screen button and setup state self.unlockscreen_interval = self.config['unlockscreen_interval'] self.button_unlockscreen._state = 0 self.button_unlockscreen.setAutoRepeat(True) self.button_unlockscreen.setAutoRepeatInterval( self.unlockscreen_interval) self.button_unlockscreen.clicked.connect(self.handle_unlock) self.numpad = NumPad(self) self.numpad.assign_code(self.config['unlockscreen_code'], self.unlock_screen) self.numpad.button_back.pressed.connect(self.lock_screen) self.button_backalarms.pressed.connect(self.exit_alarms) #Instantiate the DataFiller, which takes #care of filling plots data self.data_filler = DataFiller(config) #Set up tool settings (bottom bar) #self.toolsettings[..] are the objects that hold min, max values for a given setting as #as the current value (displayed as a slider and as a number). toolsettings_names = { "toolsettings_1", "toolsettings_2", "toolsettings_3" } self.toolsettings = {} for name in toolsettings_names: toolsettings = self.toolbar.findChild(QtWidgets.QWidget, name) toolsettings.connect_config(config) self.toolsettings[name] = toolsettings # Set up data monitor/alarms (side bar) and plots #self.monitors[..] are the objects that hold monitor values and #thresholds for alarm min and max. The current value and #optional stats for the monitored value (mean, max) are set #here. # plot slot widget names self.plots = {} for name in config['plots']: plot = self.main.findChild(QtWidgets.QWidget, name) plot.setFixedHeight(130) self.data_filler.connect_plot(name, plot) self.plots[name] = plot # The monitored fields from the default_settings.yaml config file self.monitors = {} for name in config['monitors']: monitor = Monitor(name, config) self.monitors[name] = monitor self.data_filler.connect_monitor(monitor) # The alarms are from the default_settings.yaml config file # self.alarms = {} # for name in config['alarms']: # alarm = GuiAlarm(name, config, self.monitors, self.alarm_h) # self.alarms[name] = alarm self.gui_alarm = GuiAlarms(config, self.esp32, self.monitors) for monitor in self.monitors.values(): monitor.connect_gui_alarm(self.gui_alarm) # Get displayed monitors self.monitors_slots = self.main.findChild(QtWidgets.QVBoxLayout, "monitors_slots") self.alarms_settings.connect_monitors(self) self.alarms_settings.populate_monitors() self.button_applyalarm.pressed.connect( self.alarms_settings.apply_selected) self.button_resetalarm.pressed.connect( self.alarms_settings.reset_selected) self.button_offalarm.pressed.connect( self.alarms_settings.move_selected_off) self.button_upalarm.pressed.connect( self.alarms_settings.move_selected_up) self.button_downalarm.pressed.connect( self.alarms_settings.move_selected_down) # Connect the frozen plots # Requires building of an ordered array to associate the correct # controls with the plot. active_plots = [] for slotname in self.plots: active_plots.append(self.plots[slotname]) self.cursor = Cursor(active_plots) self.frozen_bot.connect_workers(self.data_filler, active_plots, self.cursor) self.frozen_right.connect_workers(active_plots, self.cursor) #Instantiate DataHandler, which will start a new #thread to read data from the ESP32. We also connect #the DataFiller to it, so the thread will pass the #data directly to the DataFiller, which will #then display them. self._data_h = DataHandler(config, self.esp32, self.data_filler, self.gui_alarm) self.specialbar.connect_datahandler_config_esp32( self._data_h, self.config, self.esp32, self.messagebar) #Connect settings button to Settings overlay. self.settings = Settings(self) self.toppane.insertWidget(self.toppane.count(), self.settings) #Set up start/stop auto/min mode buttons. #Connect each to their respective mode toggle functions. #The StartStopWorker class takes care of starting and stopping a run self._start_stop_worker = StartStopWorker(self, self.config, self.esp32, self.button_startstop, self.button_autoassist, self.toolbar, self.settings) if self._start_stop_worker.is_running(): self.goto_main() self.button_startstop.released.connect( self._start_stop_worker.toggle_start_stop) self.button_autoassist.released.connect( self._start_stop_worker.toggle_mode) self.gui_alarm.connect_workers(self._start_stop_worker)
def __init__(self, config, main_path, mode='normal', diagnostic=False, verbose=False, simulation=False, logdata=False, *args, **kwargs): """ Initializes the main window """ super(MainWindow, self).__init__(*args, **kwargs) uic.loadUi('mainwindow.ui', self) # Load the .ui file # set mode if mode.lower() == 'debug': self.fast_update_time = 100 self.fslow_update_time = 1000 self.mode_verbose = True else: self.fast_update_time = 10 self.slow_update_time = 1000 self.mode_verbose = False # show full screen if running on a raspberry pi if 'raspberrypi' in os.uname(): self.showFullScreen() # configuration self.config = config # data filler self.data_filler = data_filler.DataFiller(config=self.config) # run in verbose mode? do this if requested specifically or if running in debug mode self.verbose = (verbose) or (self.mode_verbose) # define the top level main path self.main_path = main_path if self.verbose: print(f"main: main path = {self.main_path}") # define the slow and fast data classes that hold the data generated by the loops self.time_to_display = 10 #seconds self.num_samples = int(self.time_to_display * 1000 / self.fast_update_time) #hold an index about where in the plot (ie an index within num_samples) to put the next data self.index = 0 self.fastdata = data_handler.fast_data() self.slowdata = data_handler.slow_data() self.breathdata = data_handler.breath_data() self.breathpar = data_handler.breath_par() # Start up the fast loop (data acquisition) self.fast_loop = data_handler.fast_loop(main_path=self.main_path, config=self.config, simulation=simulation, logdata=logdata, verbose=self.verbose) # once the sensor is initialized, start the fastloop self.sensor_initialized.connect(self.start_fastloop) while True: if self.fast_loop.sensor.initialized: self.sensor_initialized.emit() print( 'fastloop: sensor initialized. safe to start data acquisition: ' ) break # if the fastloop signals it has new data, grab it self.fast_loop.newdata.connect(self.update_fast_data) # start up the slow loop (calculations) self.slow_loop = data_handler.slow_loop(main_path=self.main_path, config=self.config, verbose=self.verbose) self.slow_loop.start() self.slow_loop.new_slowdata.connect(self.update_slow_data) #self.restart_looping_plot.connect(self.fast_loop.sensor.update_ambient_pressure) self.slow_loop.new_breathpar.connect(self.update_breath_params) # if the slowloop requests new data, send it the current fastdata self.slow_loop.request_fastdata.connect(self.slowloop_request) self.request_from_slowloop.connect(self.slow_loop.update_fast_data) # rezero the volume offset #self.update_vol_offset.connect(self.fast_loop.update_vol_offset) #self.update_vol_offset.connect(self.fast_loop.update_flow_trend) #self.update_vol_offset.connect(self.fast_loop.update_vol_trend) #self.update_vol_offset.connect(self.fast_loop.restart_integral) # if new breath detected tell fastloop to reset the integral #self.restart_looping_plot.connect(self.fast_loop.update_vol_trend) #if new breath data is received from fastloop, pass it to slowloop and ask for the breath params to be calculated self.new_breath_data.connect(self.slow_loop.calculate_breath_params) # if a new sensor calibration is selected, pass the new selection to fastdata.sensor self.new_sensor_cal.connect(self.fast_loop.sensor.set_mouthpiece) # if the fastloop sends new breath data, populate the mainloop breathdata self.fast_loop.new_breath.connect(self.update_breath_data) self.fast_loop.new_breath.connect(self.slow_loop.update_breath_data) # want to just show the plots to dewbug the calculations? self.diagnostic = diagnostic ### GUI stuff ### self.setWindowTitle("Open Respiratory Monitor") ''' Get the toppane and child pages ''' #self.toppane = self.findChild(QtWidgets.QStackedWidget, "toppane") self.main = self.findChild(QtWidgets.QWidget, "main") #self.initial = self.findChild(QtWidgets.QWidget, "initial") #self.startup = self.findChild(QtWidgets.QWidget, "startup") self.alarmbar = self.findChild(QtWidgets.QWidget, "alarmbar") self.toolbar = self.findChild(QtWidgets.QWidget, "toolbar") self.calpage = self.findChild(QtWidgets.QWidget, "calibration") self.statspage = self.findChild(QtWidgets.QWidget, "statspage") self.rezero_page = self.findChild(QtWidgets.QWidget, "rezero_page") ''' Get the center pane (plots) widgets ''' self.centerpane = self.findChild(QtWidgets.QStackedWidget, "centerpane") self.plots_all = self.findChild(QtWidgets.QWidget, "plots_all") self.plots_loops = self.centerpane.findChild(QtWidgets.QWidget, "plots_loops") self.plots = {} for name in self.config['plots']: plot = self.main.findChild(QtWidgets.QWidget, name) self.data_filler.connect_plot(name, plot) self.plots[name] = plot # set up the loop plots self.plot_left = self.plots_loops.findChild(QtWidgets.QWidget, "plot_left") self.plot_right = self.plots_loops.findChild(QtWidgets.QWidget, "plot_right") labelStyle = { 'color': self.config['axis_line_color'], 'font-size': '18pt' } self.plot_left.setLabel( 'left', self.config['monitors']['tidal_volume']['name'] + '' + self.config['monitors']['tidal_volume']['units'], **labelStyle) self.plot_left.setLabel( 'bottom', 'Pressure' + '' + self.config['monitors']['peep']['units'], **labelStyle) self.plot_right.setLabel( 'left', self.config['monitors']['flow']['name'] + '' + self.config['monitors']['tidal_volume']['units'], **labelStyle) self.plot_right.setLabel( 'bottom', 'Pressure' + '' + self.config['monitors']['peep']['units'], **labelStyle) # Remove mouse interaction with plots self.plot_left.setMouseEnabled(x=False, y=False) self.plot_left.setMenuEnabled(False) self.plot_right.setMouseEnabled(x=False, y=False) self.plot_right.setMenuEnabled(False) yellow = pg.mkPen(color='y', width=2) pink = pg.mkPen(color='m', width=2) blue = pg.mkPen(color='b', width=2) green = pg.mkPen(color='g', width=2) # define the curves to plot self.line_left = self.plot_left.plot([0], [0], pen=yellow) self.line_right = self.plot_right.plot([0], [0], pen=blue) ''' Get the alarm-related stuff ''' self.alarms_settings = self.findChild(QtWidgets.QWidget, "alarms_settings") self.alarmsbar = self.findChild(QtWidgets.QWidget, "alarmsbar") ''' Get the stackable bits on the right ''' self.rightbar = self.main.findChild(QtWidgets.QStackedWidget, "rightbar") self.monitors_bar = self.main.findChild(QtWidgets.QWidget, "monitors_bar") self.frozen_right = self.main.findChild(QtWidgets.QWidget, "frozenplots_right") self.button_backalarms = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_backalarms") self.button_applyalarm = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_applyalarm") self.button_resetalarm = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_resetalarm") self.button_upalarm = self.alarmsbar.findChild(QtWidgets.QPushButton, "button_upalarm") self.button_downalarm = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_downalarm") self.button_offalarm = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_offalarm") ''' Get the bar at the bottom ''' self.frozen_bot = self.findChild(QtWidgets.QWidget, "frozenplots_bottom") # Get frozen plots bottom bar widgets and connect self.button_unfreeze = self.frozen_bot.findChild( QtWidgets.QPushButton, "button_unfreeze") self.settingsfork = self.findChild(QtWidgets.QWidget, "settingsforkbar") self.button_alarms = self.settingsfork.findChild( QtWidgets.QPushButton, "button_alarms") self.button_arm = self.settingsfork.findChild(QtWidgets.QPushButton, "button_arm") self.button_silence = self.settingsfork.findChild( QtWidgets.QPushButton, "button_silence") self.button_freeze = self.settingsfork.findChild( QtWidgets.QPushButton, "button_freeze") self.button_tools = self.settingsfork.findChild( QtWidgets.QPushButton, "button_tools") self.button_viewwaves = self.settingsfork.findChild( QtWidgets.QPushButton, "button_viewwaves") self.button_viewloops = self.settingsfork.findChild( QtWidgets.QPushButton, "button_viewloops") self.button_backalarms = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_backalarms") self.button_applyalarm = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_applyalarm") self.button_resetalarm = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_resetalarm") self.button_upalarm = self.alarmsbar.findChild(QtWidgets.QPushButton, "button_upalarm") self.button_downalarm = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_downalarm") self.button_offalarm = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_offalarm") ''' # stats bar ''' self.statsbar = self.findChild(QtWidgets.QWidget, "statsbar") self.button_backstats = self.statsbar.findChild( QtWidgets.QPushButton, "button_back") self.button_tidal = self.statsbar.findChild(QtWidgets.QPushButton, "button_tidal") self.button_peak = self.statsbar.findChild(QtWidgets.QPushButton, "button_peak") self.button_peep = self.statsbar.findChild(QtWidgets.QPushButton, "button_peep") self.button_resetstats = self.statspage.findChild( QtWidgets.QPushButton, "button_resetstats") ''' stats page ''' self.stats_name = self.statspage.findChild(QtWidgets.QLabel, "name_parameter") self.stats_mean = self.statspage.findChild(QtWidgets.QLabel, "num_mean") self.stats_min = self.statspage.findChild(QtWidgets.QLabel, "num_min") self.stats_max = self.statspage.findChild(QtWidgets.QLabel, "num_max") self.stats_pcterr = self.statspage.findChild(QtWidgets.QLabel, "num_pcterror") self.stats_stderr = self.statspage.findChild(QtWidgets.QLabel, "num_stderror") self.stats_units = self.statspage.findChild(QtWidgets.QLabel, "num_units") self.statplot = self.statspage.findChild(QtWidgets.QWidget, "plot_stats") self.button_resetstats = self.statspage.findChild( QtWidgets.QPushButton, "button_resetstats") # make the plot pen = pg.mkPen(color='y', width=2) pen = pg.mkPen(None) self.statline = self.statplot.plot([0], [0], pen=pen, symbol='o', symbolSize=20, symbolBrush=('y')) # set up the statistics set which will hold useful statistics about the breaths self.statset = Statset() for name in self.config['statistics']: self.statset.add_stat(name) #print("found statistic: ",name) # set the current stat that will be shown (by default its the first one in the config) self.current_stat = self.config['statistics'][0] print('mainloop: current stat = ', self.current_stat) self.set_displayed_stat(self.current_stat) ''' # toolbar buttons ''' self.button_backsettings = self.toolbar.findChild( QtWidgets.QPushButton, "button_back") self.button_calsettings = self.toolbar.findChild( QtWidgets.QPushButton, "button_calsettings") self.button_hamilton = self.calpage.findChild(QtWidgets.QPushButton, "button_hamilton") self.button_iqspiro = self.calpage.findChild(QtWidgets.QPushButton, "button_iqspiro") self.button_stats = self.toolbar.findChild(QtWidgets.QPushButton, "button_stats") self.button_rezero = self.calpage.findChild(QtWidgets.QPushButton, "button_rezero") self.button_rezero_yes = self.rezero_page.findChild( QtWidgets.QPushButton, "button_rezero_yes") self.button_rezero_no = self.rezero_page.findChild( QtWidgets.QPushButton, "button_rezero_no") self.num_p1 = self.rezero_page.findChild(QtWidgets.QLabel, "num_p1") self.num_p2 = self.rezero_page.findChild(QtWidgets.QLabel, "num_p2") ''' Frozen Plot menu ''' # Connect the frozen plots # Requires building of an ordered array to associate the correct # controls with the plot. active_plots = [] for slotname in self.plots: active_plots.append(self.plots[slotname]) self.cursor = Cursor(active_plots) self.frozen_bot.connect_workers(self.data_filler, active_plots, self.cursor) self.frozen_right.connect_workers(active_plots, self.cursor) # Frozen Plots self.button_freeze.pressed.connect(self.freeze_plots) self.button_unfreeze.pressed.connect(self.unfreeze_plots) ''' Define the monitors ''' # The monitored fields from the default_settings.yaml config file self.monitors = {} for name in config['monitors']: monitor = Monitor(name, config) self.monitors[name] = monitor self.data_filler.connect_monitor(monitor) # Get displayed monitors self.monitors_slots = self.main.findChild(QtWidgets.QVBoxLayout, "monitors_slots") self.alarms_settings.connect_monitors(self) self.alarms_settings.populate_monitors() self.button_applyalarm.pressed.connect( self.alarms_settings.apply_selected) self.button_resetalarm.pressed.connect( self.alarms_settings.reset_selected) self.button_offalarm.pressed.connect( self.alarms_settings.move_selected_off) self.button_upalarm.pressed.connect( self.alarms_settings.move_selected_up) self.button_downalarm.pressed.connect( self.alarms_settings.move_selected_down) ''' Start the alarm handler, which will check for ESP alarms ''' self.alarm_h = AlarmHandler(self.config, self.alarmbar) # The alarms are from the default_settings.yaml config file # self.alarms = {} # for name in config['alarms']: # alarm = GuiAlarm(name, config, self.monitors, self.alarm_h) # self.alarms[name] = alarm self.gui_alarm = GuiAlarms(config, self.monitors) print('trying to connect alarms') for monitor in self.monitors.values(): monitor.connect_gui_alarm(self.gui_alarm) ''' Connect the menu buttons to actions ''' self.button_alarms.pressed.connect(self.goto_alarms) self.alarms_settings.connect_monitors(self) self.alarms_settings.populate_monitors() self.button_applyalarm.pressed.connect( self.alarms_settings.apply_selected) self.button_resetalarm.pressed.connect( self.alarms_settings.reset_selected) self.button_offalarm.pressed.connect( self.alarms_settings.move_selected_off) self.button_upalarm.pressed.connect( self.alarms_settings.move_selected_up) self.button_downalarm.pressed.connect( self.alarms_settings.move_selected_down) self.button_backalarms.pressed.connect(self.exit_alarms) self.button_viewloops.pressed.connect(self.show_loops) self.button_viewwaves.pressed.connect(self.show_waveforms) #self.button_zero_flow.pressed.connect(self.zero_sensor_flow) # toolbar self.button_tools.pressed.connect(self.show_toolbar) self.button_backsettings.pressed.connect(self.exit_alarms) self.button_calsettings.pressed.connect(self.goto_calsettings) self.button_stats.pressed.connect(self.goto_stats) self.button_backstats.pressed.connect(self.show_toolbar) # calibration selection self.button_hamilton.toggled.connect(self.togglecal_hamilton) self.button_iqspiro.toggled.connect(self.togglecal_iqspiro) self.button_rezero.pressed.connect(self.goto_rezero_page) self.button_rezero_yes.pressed.connect(self.rezero_sensor) self.button_rezero_no.pressed.connect(self.goto_calsettings) self.button_rezero_no.pressed.connect(self.show_toolbar) # stats page self.button_tidal.pressed.connect( lambda: self.set_displayed_stat('tidal_volume')) self.button_peak.pressed.connect( lambda: self.set_displayed_stat('peak')) self.button_peep.pressed.connect( lambda: self.set_displayed_stat('peep')) self.button_resetstats.pressed.connect(self.reset_stats) ''' arming the alarms ''' self.button_arm.toggled.connect(self.arm_disarm_alarms) # set up the mute audio alarm buttion self.button_silence.pressed.connect(self.silence_alarms) # Show the Page self.goto_main() self.show_settingsfork() ### Stuff from the original just plots gui ### if self.diagnostic: self.graph0 = pg.PlotWidget() self.graph1 = pg.PlotWidget() self.graph2 = pg.PlotWidget() self.graph3 = pg.PlotWidget() layout = QtWidgets.QVBoxLayout() layout.addWidget(self.graph0) layout.addWidget(self.graph1) layout.addWidget(self.graph2) layout.addWidget(self.graph3) widget = QtWidgets.QWidget() widget.setLayout(layout) # make the window with a graph widget self.setCentralWidget(widget) # set the plot properties self.graph0.setBackground('k') self.graph0.showGrid(x=True, y=True) self.graph1.setBackground('k') self.graph1.showGrid(x=True, y=True) self.graph2.setBackground('k') self.graph2.showGrid(x=True, y=True) self.graph3.setBackground('k') self.graph3.showGrid(x=True, y=True) # Set the label properties with valid CSS commands -- https://groups.google.com/forum/#!topic/pyqtgraph/jS1Ju8R6PXk labelStyle = {'color': '#FFF', 'font-size': '12pt'} self.graph0.setLabel('left', 'Inspiring', 'cmH20', **labelStyle) self.graph1.setLabel('left', 'Flow ', 'L/m', **labelStyle) self.graph2.setLabel('left', 'Flow Slope', 'L/m/s', **labelStyle) self.graph3.setLabel('left', 'V', 'mL', **labelStyle) self.graph3.setLabel('bottom', 'Time', 's', **labelStyle) # change the plot range #self.graph1.setYRange(-10,40,padding = 0.1) #self.graph2.setYRange(-100,100,padding = 0.1) #self.graph3.setYRange(0,750,padding = 0.1) # make a QPen object to hold the marker properties yellow = pg.mkPen(color='y', width=2) pink = pg.mkPen(color='m', width=2) blue = pg.mkPen(color='b', width=2) green = pg.mkPen(color='g', width=2) # define the curves to plot self.data_line0 = self.graph0.plot(self.fastdata.dt, self.fastdata.p1, pen=yellow) self.data_line1 = self.graph1.plot(self.fastdata.dt, self.fastdata.flow, pen=blue) #self.data_line1b = self.graph1.plot(self.fastdata.dt, self.fastdata.p2, pen = bluepen) self.data_line2 = self.graph2.plot(self.fastdata.dt, self.fastdata.dflow, pen=pink) self.data_line3 = self.graph3.plot(self.fastdata.dt, self.fastdata.vol * 1000, pen=green) # update the graphs at regular intervals (so it runs in a separate thread!!) # Stuff with the timer self.t_update = self.config[ 'plot_interval'] #self.fast_update_time*5 #update time of timer in ms self.timer = QtCore.QTimer() self.timer.setInterval(self.t_update) self.timer.timeout.connect(self.update_plots) self.timer.start()
class MainWindow(QtWidgets.QMainWindow): def __init__(self, config, esp32, *args, **kwargs): """ Initializes the main window for the MVM GUI. See below for subfunction setup description. """ super(MainWindow, self).__init__(*args, **kwargs) uic.loadUi('mainwindow.ui', self) # Load the .ui file self.config = config self.esp32 = esp32 settings_file = SettingsFile(self.config["settings_file_path"]) self.user_settings = settings_file.load() ''' Start the alarm handler, which will check for ESP alarms ''' self.alarm_h = AlarmHandler(self.config, self.esp32) ''' Get the toppane and child pages ''' self.toppane = self.findChild(QtWidgets.QStackedWidget, "toppane") self.main = self.findChild(QtWidgets.QWidget, "main") self.initial = self.findChild(QtWidgets.QWidget, "initial") self.startup = self.findChild(QtWidgets.QWidget, "startup") ''' Get the center pane (plots) widgets ''' self.centerpane = self.findChild(QtWidgets.QStackedWidget, "centerpane") self.plots_all = self.findChild(QtWidgets.QWidget, "plots_all") self.alarms_settings = self.findChild(QtWidgets.QWidget, "alarms_settings") ''' Get the bottombar and child pages ''' self.bottombar = self.findChild(QtWidgets.QStackedWidget, "bottombar") self.toolbar = self.findChild(QtWidgets.QWidget, "toolbar") self.menu = self.findChild(QtWidgets.QWidget, "menu") self.frozen_bot = self.findChild(QtWidgets.QWidget, "frozenplots_bottom") self.settingsbar = self.findChild(QtWidgets.QWidget, "settingsbar") self.specialbar = self.findChild(QtWidgets.QWidget, "specialbar") self.blank = self.findChild(QtWidgets.QWidget, "blank") self.settingsfork = self.findChild(QtWidgets.QWidget, "settingsforkbar") self.alarmsbar = self.findChild(QtWidgets.QWidget, "alarmsbar") self.numpadbar = self.findChild(QtWidgets.QWidget, "numpadbar") ''' Get the stackable bits on the right ''' self.rightbar = self.main.findChild(QtWidgets.QStackedWidget, "rightbar") self.monitors_bar = self.main.findChild(QtWidgets.QWidget, "monitors_bar") self.frozen_right = self.main.findChild(QtWidgets.QWidget, "frozenplots_right") ''' Get initial and startup buttons ''' self.button_new_patient = self.initial.findChild( QtWidgets.QPushButton, "button_new_patient") self.button_resume_patient = self.initial.findChild( QtWidgets.QPushButton, "button_resume_patient") self.button_resume_patient.setEnabled(self.user_settings != {}) self.button_start_settings = self.startup.findChild( QtWidgets.QPushButton, "button_start_settings") self.button_start_vent = self.startup.findChild( QtWidgets.QPushButton, "button_start_vent") self.button_start_test = self.startup.findChild( QtWidgets.QPushButton, "button_start_test") ''' Get toolbar widgets ''' self.button_menu = self.toolbar.findChild(QtWidgets.QPushButton, "button_menu") self.button_unlockscreen = self.toolbar.findChild( QtWidgets.QPushButton, "button_unlockscreen") self.home_button = self.toolbar.findChild(QtWidgets.QWidget, "home_button") self.goto_menu = self.toolbar.findChild(QtWidgets.QWidget, "goto_menu") self.goto_unlock = self.toolbar.findChild(QtWidgets.QWidget, "goto_unlock") self.label_status = self.toolbar.findChild(QtWidgets.QLabel, "label_status") toolsettings_names = { "toolsettings_1", "toolsettings_2", "toolsettings_3" } self.toolsettings = {} for name in toolsettings_names: toolsettings = self.toolbar.findChild(QtWidgets.QWidget, name) toolsettings.connect_config(config) self.toolsettings[name] = toolsettings ''' Get menu widgets and connect settings for the menu widget ''' self.button_back = self.menu.findChild(QtWidgets.QPushButton, "button_back") self.button_settingsfork = self.menu.findChild(QtWidgets.QPushButton, "button_settingsfork") self.button_startstop = self.menu.findChild(QtWidgets.QPushButton, "button_startstop") self.button_autoassist = self.menu.findChild(QtWidgets.QPushButton, "button_autoassist") self.button_specialops = self.menu.findChild(QtWidgets.QPushButton, "button_specialops") self.button_alarms = self.settingsfork.findChild( QtWidgets.QPushButton, "button_alarms") self.button_settings = self.settingsfork.findChild( QtWidgets.QPushButton, "button_settings") self.button_lockscreen = self.settingsfork.findChild( QtWidgets.QPushButton, "button_lockscreen") self.button_backsettings = self.settingsfork.findChild( QtWidgets.QPushButton, "button_backsettings") self.button_backalarms = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_backalarms") self.button_applyalarm = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_applyalarm") self.button_resetalarm = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_resetalarm") self.button_upalarm = self.alarmsbar.findChild(QtWidgets.QPushButton, "button_upalarm") self.button_downalarm = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_downalarm") self.button_offalarm = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_offalarm") self.button_freeze = self.specialbar.findChild(QtWidgets.QPushButton, "button_freeze") self.button_backspecial = self.specialbar.findChild( QtWidgets.QPushButton, "button_backspecial") ''' Get frozen plots bottom bar widgets and connect ''' self.button_unfreeze = self.frozen_bot.findChild( QtWidgets.QPushButton, "button_unfreeze") ''' Connect initial startup buttons ''' self.button_resume_patient.pressed.connect(self.goto_resume_patient) self.button_new_patient.pressed.connect(self.goto_new_patient) self.button_start_vent.pressed.connect(self.goto_main) # TODO: connect to circuit test on ESP # self.button_start_test.pressed.connect() self.button_start_settings.pressed.connect(self.goto_settings) ''' Connect back and menu buttons to toolbar and menu This effectively defines navigation from the bottombar. ''' # Toolbar self.button_menu.pressed.connect(self.show_menu) # Menu self.button_back.pressed.connect(self.show_toolbar) self.button_alarms.pressed.connect(self.goto_alarms) self.button_settingsfork.pressed.connect(self.show_settingsfork) self.button_specialops.pressed.connect(self.show_specialbar) # Settings self.button_settings.pressed.connect(self.goto_settings) self.button_lockscreen.pressed.connect(self.lock_screen) self.button_backsettings.pressed.connect(self.show_menu) # Special self.button_freeze.pressed.connect(self.freeze_plots) self.button_unfreeze.pressed.connect(self.unfreeze_plots) self.button_backspecial.pressed.connect(self.show_menu) # Assign unlock screen button and setup state self.unlockscreen_interval = self.config['unlockscreen_interval'] self.button_unlockscreen._state = 0 self.button_unlockscreen.setAutoRepeat(True) self.button_unlockscreen.setAutoRepeatInterval( self.unlockscreen_interval) self.button_unlockscreen.clicked.connect(self.handle_unlock) self.numpad = NumPad(self) self.numpad.assign_code(self.config['unlockscreen_code'], self.unlock_screen) self.numpad.button_back.pressed.connect(self.lock_screen) self.button_backalarms.pressed.connect(self.exit_alarms) ''' Instantiate the DataFiller, which takes care of filling plots data ''' self.data_filler = DataFiller(config) ''' Set up tool settings (bottom bar) self.toolsettings[..] are the objects that hold min, max values for a given setting as as the current value (displayed as a slider and as a number). ''' toolsettings_names = { "toolsettings_1", "toolsettings_2", "toolsettings_3" } self.toolsettings = {} for name in toolsettings_names: toolsettings = self.toolbar.findChild(QtWidgets.QWidget, name) toolsettings.connect_config(config) self.toolsettings[name] = toolsettings ''' Set up data monitor/alarms (side bar) and plots self.monitors[..] are the objects that hold monitor values and thresholds for alarm min and max. The current value and optional stats for the monitored value (mean, max) are set here. ''' # plot slot widget names self.plots = {} for name in config['plots']: plot = self.main.findChild(QtWidgets.QWidget, name) plot.setFixedHeight(130) self.data_filler.connect_plot(name, plot) self.plots[name] = plot # The monitored fields from the default_settings.yaml config file self.monitors = {} for name in config['monitors']: monitor = Monitor(name, config) self.monitors[name] = monitor self.data_filler.connect_monitor(monitor) # The alarms are from the default_settings.yaml config file # self.alarms = {} # for name in config['alarms']: # alarm = GuiAlarm(name, config, self.monitors, self.alarm_h) # self.alarms[name] = alarm self.gui_alarm = GuiAlarms(config, self.esp32, self.monitors) for m in self.monitors.values(): m.connect_gui_alarm(self.gui_alarm) # Get displayed monitors self.monitors_slots = self.main.findChild(QtWidgets.QVBoxLayout, "monitors_slots") self.alarms_settings.connect_monitors(self) self.alarms_settings.populate_monitors() self.button_applyalarm.pressed.connect( self.alarms_settings.apply_selected) self.button_resetalarm.pressed.connect( self.alarms_settings.reset_selected) self.button_offalarm.pressed.connect( self.alarms_settings.move_selected_off) self.button_upalarm.pressed.connect( self.alarms_settings.move_selected_up) self.button_downalarm.pressed.connect( self.alarms_settings.move_selected_down) # Connect the frozen plots # Requires building of an ordered array to associate the correct controls with the plot. active_plots = [] for slotname in self.plots: active_plots.append(self.plots[slotname]) self.cursor = Cursor(active_plots) self.frozen_bot.connect_workers(self.data_filler, active_plots, self.cursor) self.frozen_right.connect_workers(active_plots, self.cursor) ''' Instantiate DataHandler, which will start a new thread to read data from the ESP32. We also connect the DataFiller to it, so the thread will pass the data directly to the DataFiller, which will then display them. ''' self._data_h = DataHandler(config, self.esp32, self.data_filler, self.gui_alarm) self.specialbar.connect_datahandler_config_esp32( self._data_h, self.config, self.esp32) ''' Connect settings button to Settings overlay. ''' self.settings = Settings(self) self.toppane.insertWidget(self.toppane.count(), self.settings) ''' Set up start/stop auto/min mode buttons. Connect each to their respective mode toggle functions. The StartStopWorker class takes care of starting and stopping a run ''' self._start_stop_worker = StartStopWorker(self, self.config, self.esp32, self.button_startstop, self.button_autoassist, self.toolbar, self.settings) self.button_startstop.released.connect( self._start_stop_worker.toggle_start_stop) self.button_autoassist.released.connect( self._start_stop_worker.toggle_mode) self.gui_alarm.connect_workers(self._start_stop_worker) ''' Instantiate ControllerStatus ''' self._ctr_status = ControllerStatus(config, self.esp32, self.settings, self._start_stop_worker) def lock_screen(self): self.toppane.setDisabled(True) self.show_toolbar(locked_state=True) self.alarms_settings.set_enabled_state(False) def unlock_screen(self): self.toppane.setEnabled(True) self.show_toolbar(locked_state=False) self.alarms_settings.set_enabled_state(True) def handle_unlock(self): button = self.button_unlockscreen if button.isDown(): if button._state == 0: button._state = 1 button.setAutoRepeatInterval(50) else: self.show_numpadbar() button._state = 0 button.setAutoRepeatInterval(self.unlockscreen_interval) def goto_new_patient(self): self.show_startup() def goto_resume_patient(self): self.settings.update_config(self.user_settings) self.show_startup() def goto_settings(self): self.show_settings() self.show_settingsbar() if self._start_stop_worker.mode == self._start_stop_worker.MODE_ASSIST: self.settings.tabs.setCurrentWidget(self.settings.tab_psv) elif self._start_stop_worker.mode == self._start_stop_worker.MODE_AUTO: self.settings.tabs.setCurrentWidget(self.settings.tab_pcv) def goto_main(self): self.show_main() self.show_toolbar() def exit_settings(self): self.show_main() self.show_menu() def goto_alarms(self): self.show_alarms() self.show_alarmsbar() self.alarms_settings.config_monitors() def exit_alarms(self): self.show_menu() self.show_plots() self.alarms_settings.deconfig_monitors() def show_settings(self): self.toppane.setCurrentWidget(self.settings) self.settings.tabs.setFocus() def show_startup(self): self.toppane.setCurrentWidget(self.startup) def show_menu(self): self.bottombar.setCurrentWidget(self.menu) def show_numpadbar(self): self.bottombar.setCurrentWidget(self.numpadbar) def show_toolbar(self, locked_state=False): """ Shows the toolbar in the bottom bar. locked_state: If true, shows the unlock button. Otherwise shows the menu button. """ self.bottombar.setCurrentWidget(self.toolbar) if locked_state: self.home_button.setCurrentWidget(self.goto_unlock) else: self.home_button.setCurrentWidget(self.goto_menu) def show_settingsbar(self): self.bottombar.setCurrentWidget(self.settingsbar) def show_specialbar(self): self.bottombar.setCurrentWidget(self.specialbar) def show_main(self): self.toppane.setCurrentWidget(self.main) def show_settingsfork(self): self.bottombar.setCurrentWidget(self.settingsfork) def show_alarms(self): self.centerpane.setCurrentWidget(self.alarms_settings) def show_plots(self): self.centerpane.setCurrentWidget(self.plots_all) def show_alarmsbar(self): self.bottombar.setCurrentWidget(self.alarmsbar) def freeze_plots(self): self.data_filler.freeze() self.rightbar.setCurrentWidget(self.frozen_right) self.bottombar.setCurrentWidget(self.frozen_bot) def unfreeze_plots(self): self.data_filler.unfreeze() self.rightbar.setCurrentWidget(self.monitors_bar) self.show_specialbar()
class MainWindow(QtWidgets.QMainWindow): """ The class taking care for the main window. It is top-level with respect to other panes, menus, plots and monitors. """ # this is a signal that sends fastdata from the mainloop to the slowloop request_from_slowloop = QtCore.pyqtSignal(object) request_to_update_cal = QtCore.pyqtSignal(object) update_vol_offset = QtCore.pyqtSignal(float) restart_looping_plot = QtCore.pyqtSignal() new_sensor_cal = QtCore.pyqtSignal(str) new_breath_data = QtCore.pyqtSignal( object) #received new breath data from fastloop sensor_initialized = QtCore.pyqtSignal( ) # emits once the sensor has done its initial rezero process def __init__(self, config, main_path, mode='normal', diagnostic=False, verbose=False, simulation=False, logdata=False, *args, **kwargs): """ Initializes the main window """ super(MainWindow, self).__init__(*args, **kwargs) uic.loadUi('mainwindow.ui', self) # Load the .ui file # set mode if mode.lower() == 'debug': self.fast_update_time = 100 self.fslow_update_time = 1000 self.mode_verbose = True else: self.fast_update_time = 10 self.slow_update_time = 1000 self.mode_verbose = False # show full screen if running on a raspberry pi if 'raspberrypi' in os.uname(): self.showFullScreen() # configuration self.config = config # data filler self.data_filler = data_filler.DataFiller(config=self.config) # run in verbose mode? do this if requested specifically or if running in debug mode self.verbose = (verbose) or (self.mode_verbose) # define the top level main path self.main_path = main_path if self.verbose: print(f"main: main path = {self.main_path}") # define the slow and fast data classes that hold the data generated by the loops self.time_to_display = 10 #seconds self.num_samples = int(self.time_to_display * 1000 / self.fast_update_time) #hold an index about where in the plot (ie an index within num_samples) to put the next data self.index = 0 self.fastdata = data_handler.fast_data() self.slowdata = data_handler.slow_data() self.breathdata = data_handler.breath_data() self.breathpar = data_handler.breath_par() # Start up the fast loop (data acquisition) self.fast_loop = data_handler.fast_loop(main_path=self.main_path, config=self.config, simulation=simulation, logdata=logdata, verbose=self.verbose) # once the sensor is initialized, start the fastloop self.sensor_initialized.connect(self.start_fastloop) while True: if self.fast_loop.sensor.initialized: self.sensor_initialized.emit() print( 'fastloop: sensor initialized. safe to start data acquisition: ' ) break # if the fastloop signals it has new data, grab it self.fast_loop.newdata.connect(self.update_fast_data) # start up the slow loop (calculations) self.slow_loop = data_handler.slow_loop(main_path=self.main_path, config=self.config, verbose=self.verbose) self.slow_loop.start() self.slow_loop.new_slowdata.connect(self.update_slow_data) #self.restart_looping_plot.connect(self.fast_loop.sensor.update_ambient_pressure) self.slow_loop.new_breathpar.connect(self.update_breath_params) # if the slowloop requests new data, send it the current fastdata self.slow_loop.request_fastdata.connect(self.slowloop_request) self.request_from_slowloop.connect(self.slow_loop.update_fast_data) # rezero the volume offset #self.update_vol_offset.connect(self.fast_loop.update_vol_offset) #self.update_vol_offset.connect(self.fast_loop.update_flow_trend) #self.update_vol_offset.connect(self.fast_loop.update_vol_trend) #self.update_vol_offset.connect(self.fast_loop.restart_integral) # if new breath detected tell fastloop to reset the integral #self.restart_looping_plot.connect(self.fast_loop.update_vol_trend) #if new breath data is received from fastloop, pass it to slowloop and ask for the breath params to be calculated self.new_breath_data.connect(self.slow_loop.calculate_breath_params) # if a new sensor calibration is selected, pass the new selection to fastdata.sensor self.new_sensor_cal.connect(self.fast_loop.sensor.set_mouthpiece) # if the fastloop sends new breath data, populate the mainloop breathdata self.fast_loop.new_breath.connect(self.update_breath_data) self.fast_loop.new_breath.connect(self.slow_loop.update_breath_data) # want to just show the plots to dewbug the calculations? self.diagnostic = diagnostic ### GUI stuff ### self.setWindowTitle("Open Respiratory Monitor") ''' Get the toppane and child pages ''' #self.toppane = self.findChild(QtWidgets.QStackedWidget, "toppane") self.main = self.findChild(QtWidgets.QWidget, "main") #self.initial = self.findChild(QtWidgets.QWidget, "initial") #self.startup = self.findChild(QtWidgets.QWidget, "startup") self.alarmbar = self.findChild(QtWidgets.QWidget, "alarmbar") self.toolbar = self.findChild(QtWidgets.QWidget, "toolbar") self.calpage = self.findChild(QtWidgets.QWidget, "calibration") self.statspage = self.findChild(QtWidgets.QWidget, "statspage") self.rezero_page = self.findChild(QtWidgets.QWidget, "rezero_page") ''' Get the center pane (plots) widgets ''' self.centerpane = self.findChild(QtWidgets.QStackedWidget, "centerpane") self.plots_all = self.findChild(QtWidgets.QWidget, "plots_all") self.plots_loops = self.centerpane.findChild(QtWidgets.QWidget, "plots_loops") self.plots = {} for name in self.config['plots']: plot = self.main.findChild(QtWidgets.QWidget, name) self.data_filler.connect_plot(name, plot) self.plots[name] = plot # set up the loop plots self.plot_left = self.plots_loops.findChild(QtWidgets.QWidget, "plot_left") self.plot_right = self.plots_loops.findChild(QtWidgets.QWidget, "plot_right") labelStyle = { 'color': self.config['axis_line_color'], 'font-size': '18pt' } self.plot_left.setLabel( 'left', self.config['monitors']['tidal_volume']['name'] + '' + self.config['monitors']['tidal_volume']['units'], **labelStyle) self.plot_left.setLabel( 'bottom', 'Pressure' + '' + self.config['monitors']['peep']['units'], **labelStyle) self.plot_right.setLabel( 'left', self.config['monitors']['flow']['name'] + '' + self.config['monitors']['tidal_volume']['units'], **labelStyle) self.plot_right.setLabel( 'bottom', 'Pressure' + '' + self.config['monitors']['peep']['units'], **labelStyle) # Remove mouse interaction with plots self.plot_left.setMouseEnabled(x=False, y=False) self.plot_left.setMenuEnabled(False) self.plot_right.setMouseEnabled(x=False, y=False) self.plot_right.setMenuEnabled(False) yellow = pg.mkPen(color='y', width=2) pink = pg.mkPen(color='m', width=2) blue = pg.mkPen(color='b', width=2) green = pg.mkPen(color='g', width=2) # define the curves to plot self.line_left = self.plot_left.plot([0], [0], pen=yellow) self.line_right = self.plot_right.plot([0], [0], pen=blue) ''' Get the alarm-related stuff ''' self.alarms_settings = self.findChild(QtWidgets.QWidget, "alarms_settings") self.alarmsbar = self.findChild(QtWidgets.QWidget, "alarmsbar") ''' Get the stackable bits on the right ''' self.rightbar = self.main.findChild(QtWidgets.QStackedWidget, "rightbar") self.monitors_bar = self.main.findChild(QtWidgets.QWidget, "monitors_bar") self.frozen_right = self.main.findChild(QtWidgets.QWidget, "frozenplots_right") self.button_backalarms = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_backalarms") self.button_applyalarm = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_applyalarm") self.button_resetalarm = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_resetalarm") self.button_upalarm = self.alarmsbar.findChild(QtWidgets.QPushButton, "button_upalarm") self.button_downalarm = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_downalarm") self.button_offalarm = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_offalarm") ''' Get the bar at the bottom ''' self.frozen_bot = self.findChild(QtWidgets.QWidget, "frozenplots_bottom") # Get frozen plots bottom bar widgets and connect self.button_unfreeze = self.frozen_bot.findChild( QtWidgets.QPushButton, "button_unfreeze") self.settingsfork = self.findChild(QtWidgets.QWidget, "settingsforkbar") self.button_alarms = self.settingsfork.findChild( QtWidgets.QPushButton, "button_alarms") self.button_arm = self.settingsfork.findChild(QtWidgets.QPushButton, "button_arm") self.button_silence = self.settingsfork.findChild( QtWidgets.QPushButton, "button_silence") self.button_freeze = self.settingsfork.findChild( QtWidgets.QPushButton, "button_freeze") self.button_tools = self.settingsfork.findChild( QtWidgets.QPushButton, "button_tools") self.button_viewwaves = self.settingsfork.findChild( QtWidgets.QPushButton, "button_viewwaves") self.button_viewloops = self.settingsfork.findChild( QtWidgets.QPushButton, "button_viewloops") self.button_backalarms = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_backalarms") self.button_applyalarm = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_applyalarm") self.button_resetalarm = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_resetalarm") self.button_upalarm = self.alarmsbar.findChild(QtWidgets.QPushButton, "button_upalarm") self.button_downalarm = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_downalarm") self.button_offalarm = self.alarmsbar.findChild( QtWidgets.QPushButton, "button_offalarm") ''' # stats bar ''' self.statsbar = self.findChild(QtWidgets.QWidget, "statsbar") self.button_backstats = self.statsbar.findChild( QtWidgets.QPushButton, "button_back") self.button_tidal = self.statsbar.findChild(QtWidgets.QPushButton, "button_tidal") self.button_peak = self.statsbar.findChild(QtWidgets.QPushButton, "button_peak") self.button_peep = self.statsbar.findChild(QtWidgets.QPushButton, "button_peep") self.button_resetstats = self.statspage.findChild( QtWidgets.QPushButton, "button_resetstats") ''' stats page ''' self.stats_name = self.statspage.findChild(QtWidgets.QLabel, "name_parameter") self.stats_mean = self.statspage.findChild(QtWidgets.QLabel, "num_mean") self.stats_min = self.statspage.findChild(QtWidgets.QLabel, "num_min") self.stats_max = self.statspage.findChild(QtWidgets.QLabel, "num_max") self.stats_pcterr = self.statspage.findChild(QtWidgets.QLabel, "num_pcterror") self.stats_stderr = self.statspage.findChild(QtWidgets.QLabel, "num_stderror") self.stats_units = self.statspage.findChild(QtWidgets.QLabel, "num_units") self.statplot = self.statspage.findChild(QtWidgets.QWidget, "plot_stats") self.button_resetstats = self.statspage.findChild( QtWidgets.QPushButton, "button_resetstats") # make the plot pen = pg.mkPen(color='y', width=2) pen = pg.mkPen(None) self.statline = self.statplot.plot([0], [0], pen=pen, symbol='o', symbolSize=20, symbolBrush=('y')) # set up the statistics set which will hold useful statistics about the breaths self.statset = Statset() for name in self.config['statistics']: self.statset.add_stat(name) #print("found statistic: ",name) # set the current stat that will be shown (by default its the first one in the config) self.current_stat = self.config['statistics'][0] print('mainloop: current stat = ', self.current_stat) self.set_displayed_stat(self.current_stat) ''' # toolbar buttons ''' self.button_backsettings = self.toolbar.findChild( QtWidgets.QPushButton, "button_back") self.button_calsettings = self.toolbar.findChild( QtWidgets.QPushButton, "button_calsettings") self.button_hamilton = self.calpage.findChild(QtWidgets.QPushButton, "button_hamilton") self.button_iqspiro = self.calpage.findChild(QtWidgets.QPushButton, "button_iqspiro") self.button_stats = self.toolbar.findChild(QtWidgets.QPushButton, "button_stats") self.button_rezero = self.calpage.findChild(QtWidgets.QPushButton, "button_rezero") self.button_rezero_yes = self.rezero_page.findChild( QtWidgets.QPushButton, "button_rezero_yes") self.button_rezero_no = self.rezero_page.findChild( QtWidgets.QPushButton, "button_rezero_no") self.num_p1 = self.rezero_page.findChild(QtWidgets.QLabel, "num_p1") self.num_p2 = self.rezero_page.findChild(QtWidgets.QLabel, "num_p2") ''' Frozen Plot menu ''' # Connect the frozen plots # Requires building of an ordered array to associate the correct # controls with the plot. active_plots = [] for slotname in self.plots: active_plots.append(self.plots[slotname]) self.cursor = Cursor(active_plots) self.frozen_bot.connect_workers(self.data_filler, active_plots, self.cursor) self.frozen_right.connect_workers(active_plots, self.cursor) # Frozen Plots self.button_freeze.pressed.connect(self.freeze_plots) self.button_unfreeze.pressed.connect(self.unfreeze_plots) ''' Define the monitors ''' # The monitored fields from the default_settings.yaml config file self.monitors = {} for name in config['monitors']: monitor = Monitor(name, config) self.monitors[name] = monitor self.data_filler.connect_monitor(monitor) # Get displayed monitors self.monitors_slots = self.main.findChild(QtWidgets.QVBoxLayout, "monitors_slots") self.alarms_settings.connect_monitors(self) self.alarms_settings.populate_monitors() self.button_applyalarm.pressed.connect( self.alarms_settings.apply_selected) self.button_resetalarm.pressed.connect( self.alarms_settings.reset_selected) self.button_offalarm.pressed.connect( self.alarms_settings.move_selected_off) self.button_upalarm.pressed.connect( self.alarms_settings.move_selected_up) self.button_downalarm.pressed.connect( self.alarms_settings.move_selected_down) ''' Start the alarm handler, which will check for ESP alarms ''' self.alarm_h = AlarmHandler(self.config, self.alarmbar) # The alarms are from the default_settings.yaml config file # self.alarms = {} # for name in config['alarms']: # alarm = GuiAlarm(name, config, self.monitors, self.alarm_h) # self.alarms[name] = alarm self.gui_alarm = GuiAlarms(config, self.monitors) print('trying to connect alarms') for monitor in self.monitors.values(): monitor.connect_gui_alarm(self.gui_alarm) ''' Connect the menu buttons to actions ''' self.button_alarms.pressed.connect(self.goto_alarms) self.alarms_settings.connect_monitors(self) self.alarms_settings.populate_monitors() self.button_applyalarm.pressed.connect( self.alarms_settings.apply_selected) self.button_resetalarm.pressed.connect( self.alarms_settings.reset_selected) self.button_offalarm.pressed.connect( self.alarms_settings.move_selected_off) self.button_upalarm.pressed.connect( self.alarms_settings.move_selected_up) self.button_downalarm.pressed.connect( self.alarms_settings.move_selected_down) self.button_backalarms.pressed.connect(self.exit_alarms) self.button_viewloops.pressed.connect(self.show_loops) self.button_viewwaves.pressed.connect(self.show_waveforms) #self.button_zero_flow.pressed.connect(self.zero_sensor_flow) # toolbar self.button_tools.pressed.connect(self.show_toolbar) self.button_backsettings.pressed.connect(self.exit_alarms) self.button_calsettings.pressed.connect(self.goto_calsettings) self.button_stats.pressed.connect(self.goto_stats) self.button_backstats.pressed.connect(self.show_toolbar) # calibration selection self.button_hamilton.toggled.connect(self.togglecal_hamilton) self.button_iqspiro.toggled.connect(self.togglecal_iqspiro) self.button_rezero.pressed.connect(self.goto_rezero_page) self.button_rezero_yes.pressed.connect(self.rezero_sensor) self.button_rezero_no.pressed.connect(self.goto_calsettings) self.button_rezero_no.pressed.connect(self.show_toolbar) # stats page self.button_tidal.pressed.connect( lambda: self.set_displayed_stat('tidal_volume')) self.button_peak.pressed.connect( lambda: self.set_displayed_stat('peak')) self.button_peep.pressed.connect( lambda: self.set_displayed_stat('peep')) self.button_resetstats.pressed.connect(self.reset_stats) ''' arming the alarms ''' self.button_arm.toggled.connect(self.arm_disarm_alarms) # set up the mute audio alarm buttion self.button_silence.pressed.connect(self.silence_alarms) # Show the Page self.goto_main() self.show_settingsfork() ### Stuff from the original just plots gui ### if self.diagnostic: self.graph0 = pg.PlotWidget() self.graph1 = pg.PlotWidget() self.graph2 = pg.PlotWidget() self.graph3 = pg.PlotWidget() layout = QtWidgets.QVBoxLayout() layout.addWidget(self.graph0) layout.addWidget(self.graph1) layout.addWidget(self.graph2) layout.addWidget(self.graph3) widget = QtWidgets.QWidget() widget.setLayout(layout) # make the window with a graph widget self.setCentralWidget(widget) # set the plot properties self.graph0.setBackground('k') self.graph0.showGrid(x=True, y=True) self.graph1.setBackground('k') self.graph1.showGrid(x=True, y=True) self.graph2.setBackground('k') self.graph2.showGrid(x=True, y=True) self.graph3.setBackground('k') self.graph3.showGrid(x=True, y=True) # Set the label properties with valid CSS commands -- https://groups.google.com/forum/#!topic/pyqtgraph/jS1Ju8R6PXk labelStyle = {'color': '#FFF', 'font-size': '12pt'} self.graph0.setLabel('left', 'Inspiring', 'cmH20', **labelStyle) self.graph1.setLabel('left', 'Flow ', 'L/m', **labelStyle) self.graph2.setLabel('left', 'Flow Slope', 'L/m/s', **labelStyle) self.graph3.setLabel('left', 'V', 'mL', **labelStyle) self.graph3.setLabel('bottom', 'Time', 's', **labelStyle) # change the plot range #self.graph1.setYRange(-10,40,padding = 0.1) #self.graph2.setYRange(-100,100,padding = 0.1) #self.graph3.setYRange(0,750,padding = 0.1) # make a QPen object to hold the marker properties yellow = pg.mkPen(color='y', width=2) pink = pg.mkPen(color='m', width=2) blue = pg.mkPen(color='b', width=2) green = pg.mkPen(color='g', width=2) # define the curves to plot self.data_line0 = self.graph0.plot(self.fastdata.dt, self.fastdata.p1, pen=yellow) self.data_line1 = self.graph1.plot(self.fastdata.dt, self.fastdata.flow, pen=blue) #self.data_line1b = self.graph1.plot(self.fastdata.dt, self.fastdata.p2, pen = bluepen) self.data_line2 = self.graph2.plot(self.fastdata.dt, self.fastdata.dflow, pen=pink) self.data_line3 = self.graph3.plot(self.fastdata.dt, self.fastdata.vol * 1000, pen=green) # update the graphs at regular intervals (so it runs in a separate thread!!) # Stuff with the timer self.t_update = self.config[ 'plot_interval'] #self.fast_update_time*5 #update time of timer in ms self.timer = QtCore.QTimer() self.timer.setInterval(self.t_update) self.timer.timeout.connect(self.update_plots) self.timer.start() ### gui-related functions ### def show_waveforms(self): self.centerpane.setCurrentWidget(self.plots_all) def show_loops(self): self.centerpane.setCurrentWidget(self.plots_loops) def lock_screen(self): """ Perform screen locking. """ self.toppane.setDisabled(True) #self.show_toolbar(locked_state=True) self.alarms_settings.set_enabled_state(False) def unlock_screen(self): """ Perform screen unlocking. """ self.toppane.setEnabled(True) #self.show_toolbar(locked_state=False) self.alarms_settings.set_enabled_state(True) def handle_unlock(self): """ Handle the screen unlock procedure. """ button = self.button_unlockscreen if button.isDown(): if button._state == 0: button._state = 1 button.setAutoRepeatInterval(50) else: self.show_numpadbar() button._state = 0 button.setAutoRepeatInterval(self.unlockscreen_interval) def goto_new_patient(self): """ Go ahead with shallow set of operational parameters. """ self.show_startup() def goto_resume_patient(self): """ Go ahead with previously used operational parameters. """ self.settings.update_config(self.user_settings) self.show_startup() def goto_stats(self): """ open up the statistics page """ self.toppane.setCurrentWidget(self.statspage) self.show_statsbar() def goto_rezero_page(self): """ open up the statistics page """ self.toppane.setCurrentWidget(self.rezero_page) self.show_toolbar() def show_statsbar(self): self.bottombar.setCurrentWidget(self.statsbar) def goto_calsettings(self): """ open the calibration settings pane """ self.check_sensor_cal() self.toppane.setCurrentWidget(self.calpage) self.show_toolbar() #self.calpage.tabs.setFocus() def togglecal_hamilton(self): """ toggles the calibration when you click iqspiro """ if self.button_hamilton.isChecked(): self.button_iqspiro.setChecked(False) elif not (self.button_hamilton.isChecked()): self.button_iqspiro.setChecked(True) self.update_sensor_cal() def togglecal_iqspiro(self): """ toggles the calibration when you click iqspiro """ if self.button_iqspiro.isChecked(): self.button_hamilton.setChecked(False) elif not (self.button_iqspiro.isChecked()): self.button_hamilton.setChecked(True) self.update_sensor_cal() def update_sensor_cal(self): """ updates the calibration ie mouthpiece selection of the sensor """ if self.button_iqspiro.isChecked(): self.new_sensor_cal.emit('iqspiro') else: self.new_sensor_cal.emit('hamilton') def check_sensor_cal(self): """ checks the current sensor cal to decide which box to check in the menu """ print("mainloop: mouthpiece = ", self.fast_loop.sensor.mouthpiece) if self.fast_loop.sensor.mouthpiece == 'hamilton': self.button_hamilton.setChecked(True) self.button_iqspiro.setChecked(False) elif self.fast_loop.sensor.mouthpiece == 'iqspiro': self.button_hamilton.setChecked(False) self.button_iqspiro.setChecked(True) def goto_settings(self): """ Open the Settings pane. """ self.show_settings() self.show_settingsbar() if self._start_stop_worker.mode() == self._start_stop_worker.MODE_PSV: self.settings.tabs.setCurrentWidget(self.settings.tab_psv) elif self._start_stop_worker.mode( ) == self._start_stop_worker.MODE_PCV: self.settings.tabs.setCurrentWidget(self.settings.tab_pcv) def goto_main(self): """ Open the home ui """ self.show_main() #self.show_toolbar() def exit_settings(self): """ Go back to home ui from the Settings pane. """ self.show_main() self.show_menu() def goto_alarms(self): """ Open the alarms settings pane. """ self.show_alarms() self.show_alarmsbar() self.alarms_settings.config_monitors() def exit_alarms(self): """ Go back to home ui from the alarms settings pane. """ self.show_main() self.show_plots() self.show_settingsfork() self.alarms_settings.deconfig_monitors() def show_settings(self): """ Open the Settings pane. """ self.toppane.setCurrentWidget(self.settings) self.settings.tabs.setFocus() def show_startup(self): """ Show the startup pane. """ self.toppane.setCurrentWidget(self.startup) def show_menu(self): """ Open the menu on the bottom of the home pane. """ self.bottombar.setCurrentWidget(self.menu) def show_numpadbar(self): """ Shows the numeric pad in the bottom of the home pane. """ self.bottombar.setCurrentWidget(self.numpadbar) def show_toolbar(self, locked_state=False): """ Shows the toolbar in the bottom bar. arguments: - locked_state: If true, shows the unlock button. Otherwise shows the menu button. """ self.bottombar.setCurrentWidget(self.toolbar) """ if locked_state: self.home_button.setCurrentWidget(self.goto_unlock) else: self.home_button.setCurrentWidget(self.goto_menu) """ def show_settingsbar(self): """ Open the settings submenu. """ self.bottombar.setCurrentWidget(self.settingsbar) def show_specialbar(self): """ Open the special operations submenu. """ self.bottombar.setCurrentWidget(self.specialbar) def show_main(self): """ Show the home pane. """ self.toppane.setCurrentWidget(self.main) self.show_waveforms() def show_settingsfork(self): """ Show the intermediate settings submenu """ self.bottombar.setCurrentWidget(self.settingsfork) def show_alarms(self): """ Shows the alarm settings controls in the center of the alarm settings pane. """ self.centerpane.setCurrentWidget(self.alarms_settings) def show_plots(self): """ Shows the plots in the center of the home pane. """ self.centerpane.setCurrentWidget(self.plots_all) def show_alarmsbar(self): """ Shows the alarm settings controls in the bottom of the alarm settings pane. """ self.bottombar.setCurrentWidget(self.alarmsbar) def freeze_plots(self): """ Open the frozen plots pane. """ self.data_filler.freeze() self.rightbar.setCurrentWidget(self.frozen_right) self.bottombar.setCurrentWidget(self.frozen_bot) def unfreeze_plots(self): """ Go back to the home pane from the frozen plots pane. """ self.data_filler.unfreeze() self.rightbar.setCurrentWidget(self.monitors_bar) self.show_main() self.show_settingsfork() ### gui-related functions def arm_disarm_alarms(self): if self.button_arm.isChecked(): self.gui_alarm.arm_alarms() self.button_arm.setText('DISARM \nAlarms') self.button_arm.setStyleSheet('QPushButton {color: red;}') print('main: ARMED BUTTON CHECKED') elif not self.button_arm.isChecked(): self.gui_alarm.disarm_alarms() print('main: ARMED BUTTON UNCHECKED') self.button_arm.setText('ARM \nAlarms') self.button_arm.setStyleSheet('QPushButton {color: green;}') def set_displayed_stat(self, name): # set the currently display stats in the statspage self.current_stat = name print('mainloop: current stat = ', self.current_stat) self.update_displayed_stats() def silence_alarms(self): self.gui_alarm.silence_alarms() def update_plots(self): # update the plots with the new data if self.diagnostic: self.data_line0.setData(self.fastdata.dt, self.fastdata.insp) #self.data_line1b.setData(self.fastdata.dt, self.fastdata.p2) self.data_line1.setData(self.fastdata.dt, self.fastdata.flow) self.data_line2.setData(self.fastdata.dt, self.fastdata.dflow) #flow) self.data_line3.setData(self.fastdata.dt, self.fastdata.vol * 1000) #update the data # else: # add the data to the plot vectors for key in self.fastdata.all_fields.keys(): self.data_filler.add_data_point(key, self.fastdata.all_fields[key]) # update the plots #self.data_filler.update_all_plots() self.data_filler.update_plot('pressure') self.data_filler.update_plot('flow') self.data_filler.update_plot('volume') #check if the looping is restarting if self.data_filler._looping_restart: if True: print('main: restarting loop on plots') #self.update_vol_offset.emit(self.slowdata.t_last) self.restart_looping_plot.emit() def update_monitors(self): """ displayed_monitors: - peak - peep - minute_volume_measured - tidal_volume - respiratory_rate - i_to_e_ratio - cstat - apnea_time - battery_low - battery_charging self.monitor_mapping = {'peak' : self.slowdata.pip, 'peep' : self.slowdata.peep, 'minute_volume_measured' : self.slowdata.mve_meas, 'tidal_volume' : self.slowdata.vt, 'respiratory_rate': self.slowdata.rr, 'i_to_e_ratio' : self.slowdata.ie, 'cstat' : self.slowdata.c, 'apnea_time' : self.slowdata.dt_last, 'battery_low': self.slowdata.lowbatt, 'battery_charging' : self.slowdata.battery_charging} """ # define the mapping between monitor names and data points self.monitor_mapping = { 'peak': self.breathpar.pip, 'peep': self.breathpar.peep, 'minute_volume_measured': self.slowdata.mve_meas, 'tidal_volume': self.breathpar.vt, 'respiratory_rate': self.breathpar.rr, 'i_to_e_ratio': self.breathpar.ie, 'cstat': self.breathpar.c, 'apnea_time': self.slowdata.dt_last, 'battery_low': self.slowdata.lowbatt, 'battery_charging': self.slowdata.charging } for key in self.monitor_mapping.keys(): try: value = self.monitor_mapping[key] if self.verbose: print(f'main: adding to {key}: {value}') self.data_filler.add_data_point(key, value) self.data_filler.update_all_monitors() except Exception as e: #print(f'main: could not update monitor {key}: ',e) pass # update the p1 and p2 values in the rezero plot self.num_p1.setText('%0.3f' % self.fastdata.p1[-1]) self.num_p2.setText('%0.3f' % self.fastdata.p2[-1]) # check for alarms """ self.gui_alarm = GuiAlarms(config, self.monitors) print('trying to connect alarms') for monitor in self.monitors.values(): monitor.connect_gui_alarm(self.gui_alarm) """ try: self.gui_alarm.set_data(self.monitor_mapping) except Exception as e: print('main: could not send data to guialarm: ', e) def update_loop_plots(self): self.line_left.setData(self.breathdata.p, self.breathdata.vol) self.line_right.setData(self.breathdata.p, self.breathdata.flow) # set the axis ranges pmax = np.max(self.breathdata.p) vmax = np.max(self.breathdata.vol) flowmax = np.max(np.abs(self.breathdata.flow)) if pmax > 40: pmax_plot = pmax else: pmax_plot = 40 if vmax > 1000: vmax_plot = vmax else: vmax_plot = 1000 if flowmax > 75: flowmax_plot = flowmax else: flowmax_plot = 75 # left plot (vol vs pressure) self.plot_left.setXRange(-5, pmax_plot) self.plot_left.setYRange(0, vmax_plot) # right plot (flow vs pressure) self.plot_right.setXRange(-5, pmax_plot) self.plot_right.setYRange(-flowmax_plot, flowmax_plot) ### slots to handle data transfer between threads ### def reset_stats(self): print('main: trying to reset stats') #clear out the data in the stats self.statset.reset_all() self.update_displayed_stats() def update_displayed_stats(self): # sends the stats for the selected statistic to the monitor stat = self.statset.stats[self.current_stat] name = self.config['monitors'][self.current_stat]['name'] self.stats_name.setText(name) self.stats_mean.setText('%0.2f' % stat.mean) self.stats_min.setText('%0.2f' % stat.min) self.stats_max.setText('%0.2f' % stat.max) self.stats_pcterr.setText('%0.2f' % stat.pcterr) self.stats_stderr.setText('%0.2f' % stat.stderr) units = self.config['monitors'][self.current_stat]['units'] self.stats_units.setText(units) labelStyle = { 'color': self.config['axis_line_color'], 'font-size': '18pt' } self.statplot.setLabel('left', name, units, **labelStyle) self.statplot.setLabel('bottom', 'Sample ', '', **labelStyle) self.statline.setData(np.arange(len(stat.data)), stat.data) self.statplot.enableAutoRange(axis='y', enable=True) def update_breath_data(self, data): # gets the new breath data from the fast loop if self.verbose: print("main: received new breath data from fastloop") self.breathdata = data #print(f'main: self.breathdata.tsi = {self.breathdata.tsi}') #print(f'main: self.breathdata.tei = {self.breathdata.tei}') #print(f'main: self.breathdata.tee = {self.breathdata.tee}') self.update_loop_plots() self.new_breath_data.emit(self.breathdata) def update_breath_params(self, data): # gets the new breath parameters calculated by the slow loop if self.verbose: print("main: received new breath parameters from slowloop") self.breathpar = data print(f"main: peep = {self.breathpar.peep}") self.update_monitors() # add the new data for the tracked statistics for name in self.config['statistics']: try: datapoint = self.monitor_mapping[name] if True: #self.verbose: print(f'adding to statistics for {name}: {datapoint}') self.statset.add_data_point(name, datapoint) except Exception as e: print(f'main: could not update statistics for {name}', e) self.update_displayed_stats() def update_fast_data(self, data): if self.verbose: print("main: received new data from fastloop!") self.fastdata = data #self.update_plots() #def reset_volume_offset(self): #self.fastloop. def rezero_sensor(self): ''' Set the current pressure and flow to zero ''' self.fast_loop.sensor.rezero() #self.goto_calsettings() def update_slow_data(self, data): if True: #self.verbose: print("main: received new data from slowloop!") self.slowdata = data print(f"main: slowloop data: dt_last = {self.slowdata.dt_last}") self.update_monitors() #os.system('cls' if os.name == 'nt' else 'clear') #data.print_data() def slowloop_request(self): if self.verbose: print(f"main: received request for data from slowloop") self.request_from_slowloop.emit(self.fastdata) def start_fastloop(self): """ Starts up the data acquisition fast loop """ print('main: starting fastloop') self.fast_loop.start()