class SearchInputWidget(QWidget): """ Input fields for specifying searches on SearchResultsModel """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.search_bar = QLineEdit() search_bar_layout = QHBoxLayout() search_bar_layout.addWidget(QLabel('Custom Query:')) search_bar_layout.addWidget(self.search_bar) mongo_query_help_button = QPushButton() mongo_query_help_button.setText('?') search_bar_layout.addWidget(mongo_query_help_button) mongo_query_help_button.clicked.connect(self.show_mongo_query_help) self.since_widget = QDateTimeEdit() self.since_widget.setCalendarPopup(True) self.since_widget.setDisplayFormat('yyyy-MM-dd HH:mm') since_layout = QHBoxLayout() since_layout.addWidget(QLabel('Since:')) since_layout.addWidget(self.since_widget) self.until_widget = QDateTimeEdit() self.until_widget.setCalendarPopup(True) self.until_widget.setDisplayFormat('yyyy-MM-dd HH:mm') until_layout = QHBoxLayout() until_layout.addWidget(QLabel('Until:')) until_layout.addWidget(self.until_widget) layout = QVBoxLayout() layout.addLayout(since_layout) layout.addLayout(until_layout) layout.addLayout(search_bar_layout) self.setLayout(layout) def mark_custom_query(self, valid): "Indicate whether the current text is a parsable query." if valid: stylesheet = GOOD_TEXT_INPUT else: stylesheet = BAD_TEXT_INPUT self.search_bar.setStyleSheet(stylesheet) def show_mongo_query_help(self): "Launch a Message Box with instructions for custom queries." msg = QMessageBox() msg.setIcon(QMessageBox.Information) msg.setText( "For advanced search capability, enter a valid Mongo query.") msg.setInformativeText(""" Examples: {'plan_name': 'scan'} {'proposal': 1234}, {'$and': ['proposal': 1234, 'sample_name': 'Ni']} """) msg.setWindowTitle("Custom Mongo Query") msg.setStandardButtons(QMessageBox.Ok) msg.exec_()
class SearchInputWidget(QWidget): """ Input fields for specifying searches on SearchResultsModel """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.search_bar = QLineEdit() search_bar_layout = QHBoxLayout() search_bar_layout.addWidget(QLabel('Custom Query:')) search_bar_layout.addWidget(self.search_bar) mongo_query_help_button = QPushButton() mongo_query_help_button.setText('?') search_bar_layout.addWidget(mongo_query_help_button) mongo_query_help_button.clicked.connect(self.show_mongo_query_help) self.since_widget = QDateTimeEdit() self.since_widget.setCalendarPopup(True) self.since_widget.setDisplayFormat('yyyy-MM-dd HH:mm') since_layout = QHBoxLayout() since_layout.addWidget(QLabel('Since:')) since_layout.addWidget(self.since_widget) self.until_widget = QDateTimeEdit() self.until_widget.setCalendarPopup(True) self.until_widget.setDisplayFormat('yyyy-MM-dd HH:mm') until_layout = QHBoxLayout() until_layout.addWidget(QLabel('Until:')) until_layout.addWidget(self.until_widget) layout = QVBoxLayout() layout.addLayout(since_layout) layout.addLayout(until_layout) layout.addLayout(search_bar_layout) self.setLayout(layout) def mark_custom_query(self, valid): "Indicate whether the current text is a parsable query." if valid: stylesheet = GOOD_TEXT_INPUT else: stylesheet = BAD_TEXT_INPUT self.search_bar.setStyleSheet(stylesheet) def show_mongo_query_help(self): "Launch a Message Box with instructions for custom queries." msg = QMessageBox() msg.setIcon(QMessageBox.Information) msg.setText("For advanced search capability, enter a valid Mongo query.") msg.setInformativeText(""" Examples: {'plan_name': 'scan'} {'proposal': 1234}, {'$and': ['proposal': 1234, 'sample_name': 'Ni']} """) msg.setWindowTitle("Custom Mongo Query") msg.setStandardButtons(QMessageBox.Ok) msg.exec_()
class QtSearchInput(QWidget): """ Qt view for SearchInput Parameters ---------- model: SearchInput """ def __init__(self, model, *args, **kwargs): self.model = model super().__init__(*args, **kwargs) self.setLayout(QFormLayout()) # Radiobuttons to quickly select default time period self.all_widget = QRadioButton("All") self.year_widget = QRadioButton("1 Year") self.month_widget = QRadioButton("30 Days") self.week_widget = QRadioButton("1 Week") self.today_widget = QRadioButton("24h") self.hour_widget = QRadioButton("1 Hour") self.radio_button_group = QButtonGroup() self.radio_button_group.addButton(self.all_widget) self.radio_button_group.addButton(self.year_widget) self.radio_button_group.addButton(self.month_widget) self.radio_button_group.addButton(self.week_widget) self.radio_button_group.addButton(self.today_widget) self.radio_button_group.addButton(self.hour_widget) default_period_layout = QGridLayout() default_period_layout.setHorizontalSpacing(85) default_period_layout.setVerticalSpacing(10) default_period_layout.addWidget(self.all_widget, 0, 0, 1, 2) default_period_layout.addWidget(self.year_widget, 1, 0, 1, 2) default_period_layout.addWidget(self.month_widget, 2, 0, 1, 2) default_period_layout.addWidget(self.week_widget, 0, 1, 1, 2) default_period_layout.addWidget(self.today_widget, 1, 1, 1, 2) default_period_layout.addWidget(self.hour_widget, 2, 1, 1, 2) self.layout().addRow("When:", default_period_layout) # TODO: rethink if restriction to acceptable timedelta values is required # from ..models.search.search_input import SearchInput # self.allowed = {timedelta(days=-1), timedelta(days=-30), timedelta(minutes=-60), timedelta(days=-7), # timedelta(days=-365)} # def time_validator(since=None, until=None): # """ # Enforce that since and until are values that a UI can represent. # This is an example similar to what will be used in the Qt UI. # """ # now = timedelta() # if isinstance(since, timedelta): # if not (until is None or until == now): # raise ValueError( # "This UI cannot express since=timedelta(...) unless until " # "is timedelta() or None." # ) # for item in allowed: # if since == item: # break # else: # # No matches # raise ValueError( # "This UI can only express since as a timedelta if it is " # f"one of {allowed}. The value {since} is not allowed" # ) # s = SearchInput() # s.time_validator = time_validator # "Since: <datetime picker>" self.since_widget = QDateTimeEdit() self.since_widget.setCalendarPopup(True) self.since_widget.setDisplayFormat("yyyy-MM-dd HH:mm") self.layout().addRow("Since:", self.since_widget) # "Until: <datetime picker>" self.until_widget = QDateTimeEdit() self.until_widget.setCalendarPopup(True) self.until_widget.setDisplayFormat("yyyy-MM-dd HH:mm") self.layout().addRow("Until:", self.until_widget) # Refresh Button self.refresh_button = QPushButton("Refresh") self.layout().addWidget(self.refresh_button) # Changes to the GUI update the model. self.since_widget.dateTimeChanged.connect(self.on_since_view_changed) self.until_widget.dateTimeChanged.connect(self.on_until_view_changed) self.refresh_button.clicked.connect(self.model.request_reload) self.model.events.reload.connect(self.on_reload) self.model.events.query.connect(self.on_reload) # Changes to the model update the GUI. self.model.events.since.connect(self.on_since_model_changed) self.model.events.until.connect(self.on_until_model_changed) # connect QRadioButtons and change date dropdowns (since/until widgets) accordingly self.hour_widget.toggled.connect(self.on_toggle_hour) self.today_widget.toggled.connect(self.on_toggle_24h) self.week_widget.toggled.connect(self.on_toggle_week) self.month_widget.toggled.connect(self.on_toggle_month) self.year_widget.toggled.connect(self.on_toggle_year) self.all_widget.toggled.connect(self.on_toggle_all) self.all_widget.setChecked(True) def on_reload(self, event): now = datetime.now(LOCAL_TIMEZONE) if isinstance(self.model.since, timedelta): with _blocked(self.since_widget): self.since_widget.setDateTime(as_qdatetime(now + self.model.since)) if isinstance(self.model.until, timedelta): with _blocked(self.until_widget): self.until_widget.setDateTime(as_qdatetime(now + self.model.until)) def on_since_view_changed(self, qdatetime): # When GUI is updated self.model.since = QDateTime.toPython(qdatetime) def on_since_model_changed(self, event): # When model is updated (e.g. from console or by clicking a QRadioButton) now = datetime.now(LOCAL_TIMEZONE) if isinstance(event.date, timedelta): qdatetime = as_qdatetime(now + event.date) if event.date == timedelta(minutes=-60): self.hour_widget.setChecked(True) elif event.date == timedelta(days=-1): self.today_widget.setChecked(True) elif event.date == timedelta(days=-7): self.week_widget.setChecked(True) elif event.date == timedelta(days=-30): self.month_widget.setChecked(True) elif event.date == timedelta(days=-365): self.year_widget.setChecked(True) else: # No checkbox associated with this custom timedelta pass else: # Must be a datetime if event.date == ADA_LOVELACE_BIRTHDAY: self.all_widget.setChecked(True) else: self.uncheck_radiobuttons() qdatetime = as_qdatetime(event.date) with _blocked(self.since_widget): self.since_widget.setDateTime(qdatetime) with _blocked(self.until_widget): self.until_widget.setDateTime(as_qdatetime(now)) def on_until_view_changed(self, qdatetime): # When GUI is updated self.model.until = QDateTime.toPython(qdatetime) def on_until_model_changed(self, event): # When model is updated (e.g. from console or by clicking a QRadioButton) if not isinstance(event.date, timedelta): qdatetime = as_qdatetime(event.date) self.uncheck_radiobuttons() with _blocked(self.until_widget): self.until_widget.setDateTime(qdatetime) def on_toggle_24h(self): if self.today_widget.isChecked(): self.model.since = timedelta(days=-1) self.model.until = timedelta() def on_toggle_hour(self): if self.hour_widget.isChecked(): self.model.since = timedelta(minutes=-60) self.model.until = timedelta() def on_toggle_week(self): if self.week_widget.isChecked(): self.model.since = timedelta(days=-7) self.model.until = timedelta() def on_toggle_month(self): if self.month_widget.isChecked(): self.model.since = timedelta(days=-30) self.model.until = timedelta() def on_toggle_year(self): if self.year_widget.isChecked(): self.model.since = timedelta(days=-365) self.model.until = timedelta() def on_toggle_all(self): # Search for all catalogs since Ada Lovelace's Birthday. if self.all_widget.isChecked(): self.model.since = ADA_LOVELACE_BIRTHDAY self.model.until = timedelta() def uncheck_radiobuttons(self): self.radio_button_group.setExclusive(False) self.all_widget.setChecked(False) self.year_widget.setChecked(False) self.month_widget.setChecked(False) self.week_widget.setChecked(False) self.today_widget.setChecked(False) self.hour_widget.setChecked(False) self.radio_button_group.setExclusive(True)
class QtSearchInput(QWidget): """ Qt view for SearchInput Parameters ---------- model: SearchInput """ def __init__(self, model, *args, **kwargs): self.model = model super().__init__(*args, **kwargs) # "Since: <datetime picker>" self.since_widget = QDateTimeEdit() self.since_widget.setCalendarPopup(True) self.since_widget.setDisplayFormat("yyyy-MM-dd HH:mm") since_layout = QHBoxLayout() since_layout.addWidget(QLabel("Since:")) since_layout.addWidget(self.since_widget) since_layout_widget = QWidget() since_layout_widget.setLayout(since_layout) # "Until: <datetime picker>" self.until_widget = QDateTimeEdit() self.until_widget.setCalendarPopup(True) self.until_widget.setDisplayFormat("yyyy-MM-dd HH:mm") until_layout = QHBoxLayout() until_layout.addWidget(QLabel("Until:")) until_layout.addWidget(self.until_widget) until_layout_widget = QWidget() until_layout_widget.setLayout(until_layout) self.refresh_button = QPushButton("Refresh") # Stack them up. layout = QVBoxLayout() layout.addWidget(since_layout_widget) layout.addWidget(until_layout_widget) layout.addWidget(self.refresh_button) self.setLayout(layout) # Initialize values. qdatetime = QDateTime() qdatetime.setSecsSinceEpoch(self.model.since) self.since_widget.setDateTime(qdatetime) qdatetime = QDateTime() qdatetime.setSecsSinceEpoch(self.model.until) self.until_widget.setDateTime(qdatetime) # Changes to the GUI update the model. self.since_widget.dateTimeChanged.connect(self.on_since_view_changed) self.until_widget.dateTimeChanged.connect(self.on_until_view_changed) self.refresh_button.clicked.connect(self.model.events.reload) # Changes to the model update the GUI. self.model.events.since.connect(self.on_since_model_changed) self.model.events.until.connect(self.on_until_model_changed) def on_since_view_changed(self, qdatetime): # When GUI is updated self.model.since = qdatetime.toSecsSinceEpoch() def on_since_model_changed(self, event): # When model is updated (e.g. from console) qdatetime = QDateTime() qdatetime.setSecsSinceEpoch(event.date) self.since_widget.setDateTime(qdatetime) def on_until_view_changed(self, qdatetime): # When GUI is updated self.model.until = qdatetime.toSecsSinceEpoch() def on_until_model_changed(self, event): # When model is updated (e.g. from console) qdatetime = QDateTime() qdatetime.setSecsSinceEpoch(event.date) self.until_widget.setDateTime(qdatetime)
class MacReportWindow(SiriusMainWindow): """Machine Report Window.""" def __init__(self, parent=None): """Init.""" super().__init__(parent) self._macreport = MacReport() self._macreport.connector.timeout = 5 * 60 self.setWindowIcon(qta.icon('fa.book', color='gray')) self.setWindowTitle('Machine Reports') self._fsi = '{:8d}' self._fs1 = '{:8.3f}' self._fs2 = '{:8.3f} ± {:8.3f}' self._fst1 = '{:02d}h{:02d}' self._fst2 = '{:02d}h{:02d} ± {:02d}h{:02d}' self._update_task = None self._setupUi() self.setFocusPolicy(Qt.StrongFocus) self.setFocus(True) def _setupUi(self): cwid = QWidget(self) self.setCentralWidget(cwid) title = QLabel('<h3>Machine Reports</h3>', self, alignment=Qt.AlignCenter) self._timesel_gbox = self._setupTimePeriodSelWidget() self._timesel_gbox.setObjectName('timesel_gbox') self._timesel_gbox.setStyleSheet( "#timesel_gbox{min-height: 8em; max-height: 8em;}") self._progress_list = QListWidget(self) self._progress_list.setObjectName('progress_list') self._progress_list.setStyleSheet( "#progress_list{min-height: 8em; max-height: 8em;}") self._reports_wid = QTabWidget(cwid) self._reports_wid.setObjectName('ASTab') self._reports_wid.addTab(self._setupUserShiftStatsWidget(), 'User Shift Stats') self._reports_wid.addTab(self._setupLightSourceUsageStats(), 'Light Source Usage Stats') self._reports_wid.addTab(self._setupStoredCurrentStats(), 'Stored Current Stats') self._pb_showraw = QPushButton(qta.icon('mdi.chart-line'), 'Show Raw Data', self) self._pb_showraw.setEnabled(False) self._pb_showraw.clicked.connect(self._show_raw_data) self._pb_showpvsd = QPushButton(qta.icon('mdi.chart-line'), 'Show Progrmd.vs.Delivered Hours', self) self._pb_showpvsd.setEnabled(False) self._pb_showpvsd.clicked.connect(self._show_progmd_vs_delivd) lay = QGridLayout(cwid) lay.setVerticalSpacing(10) lay.setHorizontalSpacing(10) lay.setContentsMargins(18, 9, 18, 9) lay.addWidget(title, 0, 0, 1, 3) lay.addWidget(self._timesel_gbox, 1, 0) lay.addWidget(self._progress_list, 1, 1, 1, 2, alignment=Qt.AlignBottom) lay.addWidget(self._reports_wid, 2, 0, 1, 3) lay.addWidget(self._pb_showpvsd, 4, 0, alignment=Qt.AlignLeft) lay.addWidget(self._pb_showraw, 4, 2, alignment=Qt.AlignRight) self._updateUserShiftStats(setup=True) self._updateStoredCurrentStats(setup=True) self._updateLightSourceUsageStats(setup=True) def _setupTimePeriodSelWidget(self): tnow = Time.now() ld_tstart = QLabel('Time start: ') self.dt_start = QDateTimeEdit(tnow - 10 * 60, self) self.dt_start.setCalendarPopup(True) self.dt_start.setMinimumDate(Time(2020, 1, 1)) self.dt_start.setDisplayFormat('dd/MM/yyyy hh:mm') ld_tstop = QLabel('Time stop: ') self.dt_stop = QDateTimeEdit(tnow, self) self.dt_stop.setCalendarPopup(True) self.dt_stop.setMinimumDate(Time(2020, 1, 1)) self.dt_stop.setDisplayFormat('dd/MM/yyyy hh:mm') self.pb_search = QPushButton(qta.icon('fa5s.search'), 'Search', self) self.pb_search.clicked.connect(self._do_update) self.pb_search.setObjectName('pb_search') self.pb_search.setStyleSheet(""" #pb_search{ min-width:100px; max-width:100px; min-height:25px; max-height:25px; icon-size:20px;} """) wid = QGroupBox('Select interval: ', self) lay = QGridLayout(wid) lay.addWidget(ld_tstart, 0, 0) lay.addWidget(self.dt_start, 0, 1) lay.addWidget(ld_tstop, 1, 0) lay.addWidget(self.dt_stop, 1, 1) lay.addWidget(self.pb_search, 2, 1, alignment=Qt.AlignRight) return wid def _setupUserShiftStatsWidget(self): self.lb_uspt = LbData('') self.lb_usdt = LbData('') self.lb_ustt = LbData('') self.lb_uset = LbData('') self.lb_uspc = LbData('') self.lb_cav = LbData('') self.lb_cbav = LbData('') self.lb_ceav = LbData('') self.lb_tft = LbData('') self.lb_bdc = LbData('') self.lb_mttr = LbData('') self.lb_mtbf = LbData('') self.lb_reli = LbData('') self.lb_tsbt = LbData('') self.lb_tubt = LbData('') self.lb_mtbu = LbData('') self.lb_rsbt = LbData('') self.lb_itav = LbData('') wid = QWidget(self) lay = QGridLayout(wid) lay.setVerticalSpacing(0) lay.setHorizontalSpacing(0) lay.setAlignment(Qt.AlignTop) lay.addItem(QSpacerItem(120, 1, QSzPlcy.Fixed, QSzPlcy.Ignored), 0, 0) lay.addWidget(LbHHeader('Programmed Time (h)'), 0, 1) lay.addWidget(self.lb_uspt, 0, 2) lay.addWidget(LbHHeader('Delivered Time (h)'), 1, 1) lay.addWidget(self.lb_usdt, 1, 2) lay.addWidget(LbHHeader('Total Time (h)'), 2, 1) lay.addWidget(self.lb_ustt, 2, 2) lay.addWidget(LbHHeader('Extra Time (h)'), 3, 1) lay.addWidget(self.lb_uset, 3, 2) lay.addWidget(LbHHeader('# Programmed Shifts'), 4, 1) lay.addWidget(self.lb_uspc, 4, 2) lay.addWidget(LbHHeader('Current (avg ± std) (mA)'), 5, 1) lay.addWidget(self.lb_cav, 5, 2) lay.addWidget( LbHHeader('Current at the Beg. of the Shift (avg ± std) (mA)'), 6, 1) lay.addWidget(self.lb_cbav, 6, 2) lay.addWidget( LbHHeader('Current at the End of the Shift (avg ± std) (mA)'), 7, 1) lay.addWidget(self.lb_ceav, 7, 2) lay.addWidget(LbHHeader('Total Failures Time (h)'), 8, 1) lay.addWidget(self.lb_tft, 8, 2) lay.addWidget(LbHHeader('# Beam Dumps'), 9, 1) lay.addWidget(self.lb_bdc, 9, 2) lay.addWidget(LbHHeader('Time To Recover (avg ± std) (h)'), 10, 1) lay.addWidget(self.lb_mttr, 10, 2) lay.addWidget(LbHHeader('Time Between Failures (avg) (h)'), 11, 1) lay.addWidget(self.lb_mtbf, 11, 2) lay.addWidget(LbHHeader('Beam Reliability (%)'), 12, 1) lay.addWidget(self.lb_reli, 12, 2) lay.addWidget(LbHHeader('Total stable beam time (h)'), 13, 1) lay.addWidget(self.lb_tsbt, 13, 2) lay.addWidget(LbHHeader('Total unstable beam time (h)'), 14, 1) lay.addWidget(self.lb_tubt, 14, 2) lay.addWidget(LbHHeader('Time between unstable beams (avg) (h)'), 15, 1) lay.addWidget(self.lb_mtbu, 15, 2) lay.addWidget(LbHHeader('Relative stable beam time (%)'), 16, 1) lay.addWidget(self.lb_rsbt, 16, 2) lay.addWidget(LbHHeader('Injection time (avg ± std) (h)'), 17, 1) lay.addWidget(self.lb_itav, 17, 2) lay.addItem(QSpacerItem(120, 1, QSzPlcy.Fixed, QSzPlcy.Ignored), 0, 3) return wid def _updateUserShiftStats(self, setup=False): w2r = { 'uspt': [ 'usershift_progmd_time', ], 'usdt': [ 'usershift_delivd_time', ], 'ustt': [ 'usershift_total_time', ], 'uset': [ 'usershift_extra_time', ], 'uspc': [ 'usershift_progmd_count', ], 'cav': ['usershift_current_average', 'usershift_current_stddev'], 'cbav': ['usershift_current_beg_average', 'usershift_current_beg_stddev'], 'ceav': ['usershift_current_end_average', 'usershift_current_end_stddev'], 'tft': [ 'usershift_total_failures_time', ], 'bdc': [ 'usershift_beam_dump_count', ], 'mttr': [ 'usershift_time_to_recover_average', 'usershift_time_to_recover_stddev' ], 'mtbf': [ 'usershift_time_between_failures_average', ], 'reli': [ 'usershift_beam_reliability', ], 'tsbt': [ 'usershift_total_stable_beam_time', ], 'tubt': [ 'usershift_total_unstable_beam_time', ], 'mtbu': ['usershift_time_between_unstable_beams_average'], 'rsbt': ['usershift_relative_stable_beam_time'], 'itav': [ 'usershift_injection_time_average', 'usershift_injection_time_stddev' ] } for wname, rname in w2r.items(): wid = getattr(self, 'lb_' + wname) items = [getattr(self._macreport, n) for n in rname] if 'time' in rname[0] and 'relative' not in rname[0]: if len(items) == 2: if items[0] not in [None, _np.inf]: hour1 = int(items[0]) minu1 = int((items[0] - hour1) * 60) hour2 = int(items[1]) minu2 = int((items[1] - hour2) * 60) items = [hour1, minu1, hour2, minu2] str2fmt = self._fst2 else: str2fmt = self._fs1 elif items[0] not in [None, _np.inf]: hour = int(items[0]) minu = int((items[0] - hour) * 60) items = [hour, minu] str2fmt = self._fst1 else: str2fmt = self._fs1 else: str2fmt = getattr( self, '_fsi' if 'count' in rname[0] else '_fs' + str(len(rname))) text = '' if any([i is None for i in items]) \ else str2fmt.format(*items) wid.setText(text) if setup: wid.setToolTip(getattr(MacReport, rname[0]).__doc__) def _setupStoredCurrentStats(self): self.lb_user_mb_avg = LbData('') self.lb_user_mb_intvl = LbData('') self.lb_user_sb_avg = LbData('') self.lb_user_sb_intvl = LbData('') self.lb_user_tt_avg = LbData('') self.lb_user_tt_intvl = LbData('') self.lb_commi_mb_avg = LbData('') self.lb_commi_mb_intvl = LbData('') self.lb_commi_sb_avg = LbData('') self.lb_commi_sb_intvl = LbData('') self.lb_commi_tt_avg = LbData('') self.lb_commi_tt_intvl = LbData('') self.lb_condi_mb_avg = LbData('') self.lb_condi_mb_intvl = LbData('') self.lb_condi_sb_avg = LbData('') self.lb_condi_sb_intvl = LbData('') self.lb_condi_tt_avg = LbData('') self.lb_condi_tt_intvl = LbData('') self.lb_mstdy_mb_avg = LbData('') self.lb_mstdy_mb_intvl = LbData('') self.lb_mstdy_sb_avg = LbData('') self.lb_mstdy_sb_intvl = LbData('') self.lb_mstdy_tt_avg = LbData('') self.lb_mstdy_tt_intvl = LbData('') self.lb_stord_mb_avg = LbData('') self.lb_stord_mb_intvl = LbData('') self.lb_stord_sb_avg = LbData('') self.lb_stord_sb_intvl = LbData('') self.lb_stord_tt_avg = LbData('') self.lb_stord_tt_intvl = LbData('') wid = QWidget(self) lay = QGridLayout(wid) lay.setVerticalSpacing(0) lay.setHorizontalSpacing(0) lay.setAlignment(Qt.AlignTop) lay.addWidget(LbHHeader('Current (avg ± std) (mA) (MB)'), 1, 0) lay.addWidget(LbHHeader('Time in MB mode (h)'), 2, 0) lay.addWidget(LbHHeader('Current (avg ± std) (mA) (SB)'), 3, 0) lay.addWidget(LbHHeader('Time in SB mode (h)'), 4, 0) lay.addWidget(LbHHeader('Current (avg ± std) (mA) (SB+MB)'), 5, 0) lay.addWidget(LbHHeader('Total Time (h) (SB+MB)'), 6, 0) lay.addWidget(LbVHeader('Users'), 0, 1) lay.addWidget(self.lb_user_mb_avg, 1, 1) lay.addWidget(self.lb_user_mb_intvl, 2, 1) lay.addWidget(self.lb_user_sb_avg, 3, 1) lay.addWidget(self.lb_user_sb_intvl, 4, 1) lay.addWidget(self.lb_user_tt_avg, 5, 1) lay.addWidget(self.lb_user_tt_intvl, 6, 1) lay.addWidget(LbVHeader('Commissioning'), 0, 2) lay.addWidget(self.lb_commi_mb_avg, 1, 2) lay.addWidget(self.lb_commi_mb_intvl, 2, 2) lay.addWidget(self.lb_commi_sb_avg, 3, 2) lay.addWidget(self.lb_commi_sb_intvl, 4, 2) lay.addWidget(self.lb_commi_tt_avg, 5, 2) lay.addWidget(self.lb_commi_tt_intvl, 6, 2) lay.addWidget(LbVHeader('Conditioning'), 0, 3) lay.addWidget(self.lb_condi_mb_avg, 1, 3) lay.addWidget(self.lb_condi_mb_intvl, 2, 3) lay.addWidget(self.lb_condi_sb_avg, 3, 3) lay.addWidget(self.lb_condi_sb_intvl, 4, 3) lay.addWidget(self.lb_condi_tt_avg, 5, 3) lay.addWidget(self.lb_condi_tt_intvl, 6, 3) lay.addWidget(LbVHeader('Machine Study'), 0, 4) lay.addWidget(self.lb_mstdy_mb_avg, 1, 4) lay.addWidget(self.lb_mstdy_mb_intvl, 2, 4) lay.addWidget(self.lb_mstdy_sb_avg, 3, 4) lay.addWidget(self.lb_mstdy_sb_intvl, 4, 4) lay.addWidget(self.lb_mstdy_tt_avg, 5, 4) lay.addWidget(self.lb_mstdy_tt_intvl, 6, 4) lay.addWidget(LbVHeader('All Stored Beam'), 0, 5) lay.addWidget(self.lb_stord_mb_avg, 1, 5) lay.addWidget(self.lb_stord_mb_intvl, 2, 5) lay.addWidget(self.lb_stord_sb_avg, 3, 5) lay.addWidget(self.lb_stord_sb_intvl, 4, 5) lay.addWidget(self.lb_stord_tt_avg, 5, 5) lay.addWidget(self.lb_stord_tt_intvl, 6, 5) return wid def _updateStoredCurrentStats(self, setup=False): shifttype = { 'mstdy': 'machinestudy', 'commi': 'commissioning', 'condi': 'conditioning', 'stord': 'ebeam', 'user': '******' } fillmode = {'mb': 'multibunch', 'sb': 'singlebunch', 'tt': 'total'} stats = { 'avg': ['average', 'stddev'], 'intvl': [ 'time', ] } for wsht, rsht in shifttype.items(): for wfm, rfm in fillmode.items(): for wstt, rstt in stats.items(): wid = getattr(self, 'lb_' + wsht + '_' + wfm + '_' + wstt) pname = 'current_' + rsht + '_' + rfm + '_' items = [getattr(self._macreport, pname + i) for i in rstt] if 'time' in rstt[0] and items[0] is not None: hour = int(items[0]) minu = int((items[0] - hour) * 60) items = [hour, minu] str2fmt = getattr( self, '_fst1' if ('time' in rstt[0]) else '_fs' + str(len(rstt))) text = '' if any([i is None for i in items]) \ else str2fmt.format(*items) wid.setText(text) if setup: wid.setToolTip( getattr(MacReport, pname + rstt[0]).__doc__) def _setupLightSourceUsageStats(self): self.lb_mstdy_fail_intvl = LbData('') self.lb_mstdy_fail_pcntl = LbData('') self.lb_mstdy_oper_intvl = LbData('') self.lb_mstdy_oper_pcntl = LbData('') self.lb_mstdy_total_intvl = LbData('') self.lb_mstdy_total_pcntl = LbData('') self.lb_commi_fail_intvl = LbData('') self.lb_commi_fail_pcntl = LbData('') self.lb_commi_oper_intvl = LbData('') self.lb_commi_oper_pcntl = LbData('') self.lb_commi_total_intvl = LbData('') self.lb_commi_total_pcntl = LbData('') self.lb_condi_fail_intvl = LbData('') self.lb_condi_fail_pcntl = LbData('') self.lb_condi_oper_intvl = LbData('') self.lb_condi_oper_pcntl = LbData('') self.lb_condi_total_intvl = LbData('') self.lb_condi_total_pcntl = LbData('') self.lb_maint_fail_intvl = LbData('') self.lb_maint_fail_pcntl = LbData('') self.lb_maint_oper_intvl = LbData('') self.lb_maint_oper_pcntl = LbData('') self.lb_maint_total_intvl = LbData('') self.lb_maint_total_pcntl = LbData('') self.lb_user_fail_intvl = LbData('') self.lb_user_fail_pcntl = LbData('') self.lb_user_oper_intvl = LbData('') self.lb_user_oper_pcntl = LbData('') self.lb_user_total_intvl = LbData('') self.lb_user_total_pcntl = LbData('') self.lb_total_intvl = LbHHeader('Total Usage Time (h): - ') wid = QWidget(self) lay = QGridLayout(wid) lay.setVerticalSpacing(0) lay.setHorizontalSpacing(0) lay.setAlignment(Qt.AlignTop) lay.addWidget(LbHHeader('Operational Time (h)'), 1, 0) lay.addWidget(LbHHeader('Operational Percentage (%)'), 2, 0) lay.addWidget(LbHHeader('Failures Time (h)'), 3, 0) lay.addWidget(LbHHeader('Failures Percentage (%)'), 4, 0) lay.addWidget(LbHHeader('Shift Time (h)'), 5, 0) lay.addWidget(LbHHeader('Shift Percentage (%)'), 6, 0) lay.addWidget(self.lb_total_intvl, 7, 0, 1, 6) lay.addWidget(LbVHeader('Users'), 0, 1) lay.addWidget(self.lb_user_oper_intvl, 1, 1) lay.addWidget(self.lb_user_oper_pcntl, 2, 1) lay.addWidget(self.lb_user_fail_intvl, 3, 1) lay.addWidget(self.lb_user_fail_pcntl, 4, 1) lay.addWidget(self.lb_user_total_intvl, 5, 1) lay.addWidget(self.lb_user_total_pcntl, 6, 1) lay.addWidget(LbVHeader('Commissioning'), 0, 2) lay.addWidget(self.lb_commi_oper_intvl, 1, 2) lay.addWidget(self.lb_commi_oper_pcntl, 2, 2) lay.addWidget(self.lb_commi_fail_intvl, 3, 2) lay.addWidget(self.lb_commi_fail_pcntl, 4, 2) lay.addWidget(self.lb_commi_total_intvl, 5, 2) lay.addWidget(self.lb_commi_total_pcntl, 6, 2) lay.addWidget(LbVHeader('Conditioning'), 0, 3) lay.addWidget(self.lb_condi_oper_intvl, 1, 3) lay.addWidget(self.lb_condi_oper_pcntl, 2, 3) lay.addWidget(self.lb_condi_fail_intvl, 3, 3) lay.addWidget(self.lb_condi_fail_pcntl, 4, 3) lay.addWidget(self.lb_condi_total_intvl, 5, 3) lay.addWidget(self.lb_condi_total_pcntl, 6, 3) lay.addWidget(LbVHeader('Machine Study'), 0, 4) lay.addWidget(self.lb_mstdy_oper_intvl, 1, 4) lay.addWidget(self.lb_mstdy_oper_pcntl, 2, 4) lay.addWidget(self.lb_mstdy_fail_intvl, 3, 4) lay.addWidget(self.lb_mstdy_fail_pcntl, 4, 4) lay.addWidget(self.lb_mstdy_total_intvl, 5, 4) lay.addWidget(self.lb_mstdy_total_pcntl, 6, 4) lay.addWidget(LbVHeader('Maintenance'), 0, 5) lay.addWidget(self.lb_maint_oper_intvl, 1, 5) lay.addWidget(self.lb_maint_oper_pcntl, 2, 5) lay.addWidget(self.lb_maint_fail_intvl, 3, 5) lay.addWidget(self.lb_maint_fail_pcntl, 4, 5) lay.addWidget(self.lb_maint_total_intvl, 5, 5) lay.addWidget(self.lb_maint_total_pcntl, 6, 5) return wid def _updateLightSourceUsageStats(self, setup=False): shifttype = { 'mstdy': 'machinestudy', 'commi': 'commissioning', 'condi': 'conditioning', 'maint': 'maintenance', 'user': '******' } intervaltype = { 'fail': '_failures', 'oper': '_operational', 'total': '' } for wst, rst in shifttype.items(): for wit, rit in intervaltype.items(): widt = getattr(self, 'lb_' + wst + '_' + wit + '_intvl') tname = 'lsusage_' + rst + rit + '_time' tval = getattr(self._macreport, tname) if tval is None: text = '' else: hour = int(tval) minu = int((tval - hour) * 60) text = self._fst1.format(hour, minu) widt.setText(text) if setup: widt.setToolTip(getattr(MacReport, tname).__doc__) widp = getattr(self, 'lb_' + wst + '_' + wit + '_pcntl') pname = 'lsusage_' + rst + rit pval = getattr(self._macreport, pname) text = '' if pval is None else self._fs1.format(pval) widp.setText(text) if setup: widp.setToolTip(getattr(MacReport, pname).__doc__) text = 'Total Usage Time (h): ' if self._macreport.lsusage_total_time is not None: val = self._macreport.lsusage_total_time hour = int(val) minu = int((val - hour) * 60) text += self._fst1.format(hour, minu) self.lb_total_intvl.setText(text) def _do_update(self): if self.sender().text() == 'Abort': self._update_task.terminate() now = Time.now().strftime('%Y/%m/%d-%H:%M:%S') item = QListWidgetItem(now + ' Aborted.') self._progress_list.addItem(item) self._progress_list.scrollToBottom() self._setup_search_button() else: if self.dt_start.dateTime() >= self.dt_stop.dateTime() or \ self.dt_start.dateTime() > Time.now() or \ self.dt_stop.dateTime() > Time.now(): QMessageBox.warning(self, 'Ops...', 'Insert a valid time interval.') return self._macreport.timestamp_start = \ self.dt_start.dateTime().toSecsSinceEpoch() self._macreport.timestamp_stop = \ self.dt_stop.dateTime().toSecsSinceEpoch() self._progress_list.clear() self._pb_showraw.setEnabled(False) self._pb_showpvsd.setEnabled(False) self._setup_search_button() self._update_task = UpdateTask(self._macreport) self._update_task.updated.connect(self._update_progress) self._update_task.start() def _update_progress(self, message): item = QListWidgetItem(message) self._progress_list.addItem(item) self._progress_list.scrollToBottom() if 'Collected' in message: self._setup_search_button() self._updateUserShiftStats() self._updateStoredCurrentStats() self._updateLightSourceUsageStats() self._pb_showraw.setEnabled(True) self._pb_showpvsd.setEnabled(True) def _setup_search_button(self): if self.pb_search.text() == 'Abort': self.pb_search.setIcon(qta.icon('fa5s.search')) self.pb_search.setText('Search') else: self.pb_search.setIcon( qta.icon('fa5s.spinner', animation=qta.Spin(self.pb_search))) self.pb_search.setText('Abort') def _show_raw_data(self): fig = self._macreport.plot_raw_data() wid = MatplotlibWidget(fig) wid.setWindowTitle('Machine Reports - Raw Data (' + str(self._macreport.time_start) + ' -> ' + str(self._macreport.time_stop) + ')') wid.show() def _show_progmd_vs_delivd(self): fig = self._macreport.plot_progmd_vs_delivd_hours() wid = MatplotlibWidget(fig) wid.setWindowTitle( 'Machine Reports - Programmed vs. Delivered Hours (' + str(self._macreport.time_start) + ' -> ' + str(self._macreport.time_stop) + ')') wid.show()