class TimeEdit(WidgetWithTZinfo): def __init__(self, parent=None): super(TimeEdit, self).__init__(parent) self.initQTimeEdit() self.initTZinfoEdit() def initQTimeEdit(self): self.timeEdit = QDateTimeEdit(self) self.timeEdit.setKeyboardTracking(False) self.timeEdit.setDisplayFormat("hh:mm:ss.zzz") self.layout().addWidget(self.timeEdit) def time(self) -> datetime.time: time = self.timeEdit.time().toPyTime() tzinfo = self.tzinfoEdit.getObj2add() time = time.replace(tzinfo=tzinfo) return time def setTime(self, val: datetime.time): if isinstance(val, datetime.time): self.timeEdit.setTime(val) self.tzinfoEdit.setVal(val.tzinfo) else: raise TypeError("arg1 must be instance of type datetime.time", type(val))
class Demo(QWidget): def __init__(self): super(Demo, self).__init__() self.datetime_1 = QDateTimeEdit(self) # 1 self.datetime_1.dateChanged.connect(lambda: print('Date Changed!')) self.datetime_2 = QDateTimeEdit(QDateTime.currentDateTime(), self) # 2 self.datetime_2.setDisplayFormat('yyyy-MM-dd HH:mm:ss') self.datetime_2.timeChanged.connect(lambda: print('Time Changed!')) print(self.datetime_2.date()) print(self.datetime_2.time()) print(self.datetime_2.dateTime()) self.datetime_3 = QDateTimeEdit(QDateTime.currentDateTime(), self) # 3 self.datetime_3.dateTimeChanged.connect(lambda: print('DateTimeChanged!')) self.datetime_3.setCalendarPopup(True) self.datetime_4 = QDateTimeEdit(QDate.currentDate(), self) # 4 self.datetime_5 = QDateTimeEdit(QTime.currentTime(), self) self.date = QDateEdit(QDate.currentDate(), self) # 5 self.date.setDisplayFormat('yyyy/MM/dd') print(self.date.date()) self.time = QTimeEdit(QTime.currentTime(), self) # 6 self.time.setDisplayFormat('HH:mm:ss') print(self.time.time()) self.v_layout = QVBoxLayout() self.v_layout.addWidget(self.datetime_1) self.v_layout.addWidget(self.datetime_2) self.v_layout.addWidget(self.datetime_3) self.v_layout.addWidget(self.datetime_4) self.v_layout.addWidget(self.datetime_5) self.v_layout.addWidget(self.date) self.v_layout.addWidget(self.time) self.setLayout(self.v_layout)
class CountdownWidget(QWidget): """Define custom widget as countdown control panel.""" def __init__(self, ctrl, parent=None): """Init completer.""" super().__init__(parent) self.controller = ctrl self.createLayout() self.loadSettings() self.connect() def createLayout(self): """Create widget to control the countdown browser source.""" layout = QGridLayout() self.rb_static = QRadioButton(_("Static Countdown to date:"), self) layout.addWidget(self.rb_static, 0, 0) self.rb_dynamic = QRadioButton(_("Dynamic Countdown duration:"), self) self.rb_dynamic.setChecked(True) self.rb_dynamic.toggled.connect(self.toggleRadio) layout.addWidget(self.rb_dynamic, 1, 0) self.te_datetime = QDateTimeEdit() self.te_datetime.setCalendarPopup(True) self.te_datetime.setContextMenuPolicy(Qt.CustomContextMenu) self.te_datetime.customContextMenuRequested.connect( self.openDateTimeMenu) layout.addWidget(self.te_datetime, 0, 1) self.te_duration = QTimeEdit() self.te_duration.setDisplayFormat("HH 'h' mm 'm' ss 's'") self.te_duration.setContextMenuPolicy(Qt.CustomContextMenu) self.te_duration.customContextMenuRequested.connect( self.openDurationMenu) layout.addWidget(self.te_duration, 1, 1) self.event_label = QLabel(' ' + _('Event description:')) layout.addWidget(self.event_label, 0, 2) self.le_desc = QLineEdit() self.le_desc.setAlignment(Qt.AlignCenter) layout.addWidget(self.le_desc, 0, 3, 1, 2) self.cb_restart = QCheckBox( _('Restart countdown when source becomes active')) layout.addWidget(self.cb_restart, 1, 2, 1, 2) self.pb_start = QPushButton(" " + _('Start Countdown') + " ") layout.addWidget(self.pb_start, 1, 4) layout.setColumnStretch(2, 1) layout.setColumnStretch(3, 2) self.setLayout(layout) def openDateTimeMenu(self, position): """Open menu to set date to today.""" menu = QMenu() act1 = QAction(_("Set Today")) act1.triggered.connect(self.setToday) menu.addAction(act1) menu.exec_(QCursor.pos()) def openDurationMenu(self, position): """Open menu to set the duration.""" menu = QMenu() for duration in [15, 10, 5, 3, 1]: act = QAction(_("Set {} min").format(duration), menu) act.triggered.connect( lambda x, duration=duration: self.setDuration(duration)) menu.addAction(act) menu.exec_(QCursor.pos()) def setToday(self): """Set date to today.""" today = QDateTime.currentDateTime() today.setTime(self.te_datetime.time()) self.te_datetime.setDateTime(today) def setFromTimestamp(self, timestamp): """Set time and date based on timestamp.""" self.te_datetime.setDateTime(QDateTime.fromTime_t(int(timestamp))) def setDuration(self, duration): """Set the duration.""" self.te_duration.setTime(QTime(0, duration, 0)) def toggleRadio(self): """Toggle radio buttion.""" static = self.rb_static.isChecked() self.te_datetime.setEnabled(static) self.te_duration.setEnabled(not static) self.cb_restart.setEnabled(not static) self.pb_start.setEnabled(not static) def loadSettings(self): """Load data from settings.""" static = scctool.settings.config.parser.getboolean( "Countdown", "static") if static: self.rb_static.setChecked(True) else: self.rb_dynamic.setChecked(True) description = scctool.settings.config.parser.get( 'Countdown', 'description') self.le_desc.setText(description.strip()) restart = scctool.settings.config.parser.getboolean( "Countdown", "restart") self.cb_restart.setChecked(restart) duration = QTime() string = scctool.settings.config.parser.get('Countdown', 'duration').strip() duration = QTime.fromString(string, 'HH:mm:ss') self.te_duration.setTime(duration) string = scctool.settings.config.parser.get('Countdown', 'datetime').strip() datetime = QDateTime.fromString(string, 'yyyy-MM-dd HH:mm') self.te_datetime.setDateTime(datetime) def connect(self): """Connect all form elements.""" self.le_desc.textChanged.connect(self.changed_description) self.cb_restart.toggled.connect(self.changed_restart) self.te_datetime.dateTimeChanged.connect(self.changed_datetime) self.te_duration.timeChanged.connect(self.changed_duration) self.rb_static.toggled.connect(self.changed_static) self.pb_start.pressed.connect(self.start_pressed) def changed_description(self): """Change the description.""" desc = self.le_desc.text().strip() scctool.settings.config.parser.set('Countdown', 'description', desc) self.controller.websocketThread.sendData2Path('countdown', "DESC", desc) def changed_restart(self): """Handle change of restart option.""" restart = self.cb_restart.isChecked() scctool.settings.config.parser.set('Countdown', 'restart', str(restart)) self.controller.websocketThread.sendData2Path('countdown', "RESTART", restart) def changed_datetime(self, time): """Handle change of datetime.""" datetime = time.toString('yyyy-MM-dd HH:mm') scctool.settings.config.parser.set('Countdown', 'datetime', datetime) self.sendData() def changed_duration(self, time): """Handle change of duration.""" duration = time.toString('HH:mm:ss') scctool.settings.config.parser.set('Countdown', 'duration', duration) self.sendData() def changed_static(self): """Handle change of static/dynamic.""" static = self.rb_static.isChecked() scctool.settings.config.parser.set('Countdown', 'static', str(static)) self.sendData() def start_pressed(self): """Handle press of the start button.""" self.controller.websocketThread.sendData2Path('countdown', 'START') def sendData(self): """Send the data to the websocket.""" self.controller.websocketThread.sendData2Path( 'countdown', "DATA", self.controller.websocketThread.getCountdownData())
class App(QMainWindow): switch_window = QtCore.pyqtSignal() def __init__(self): super().__init__() self.title = "To-Do List" # set title.. self.left = 70 # x-pos when you open application.. self.top = 60 # y-pos when you open application.. self.width = 500 # width of the application.. self.height = 500 # height of the application.. self.fName = 'To-Do List File.txt' # set file name when you save your file.. self.uncompletedTaskFile, self.completedTaskFile = 'UncompletedTask.txt', 'CompletedTask.txt' self.initUI() # initialize the UI of the application.. def makeLabel(self, x, y, text): # make label method... self.taskLabel = QLabel(self) self.taskLabel.setText(text) self.taskLabel.move(x, y) def createTaskFile(self): if not os.path.exists(self.uncompletedTaskFile) and not os.path.exists( self.completedTaskFile): with open(self.uncompletedTaskFile, 'w') as f: f.close() with open(self.completedTaskFile, 'w') as g: g.close() def setMenuBarAction(self): # add Action to the menu bar... self.saveAction = QAction('Save', self) # save Action.. self.saveAction.setStatusTip('Sae The To-Do') self.saveAction.setShortcut("Ctrl+S") self.saveAction.triggered.connect(self.saveFile) self.saveAllAction = QAction('Save All', self) # save All Action.. self.saveAllAction.setStatusTip('Save All To-Do') self.saveAllAction.triggered.connect(self.saveAllFile) self.exitAction = QAction('Exit', self) # Exit Action.. self.exitAction.setStatusTip('Exit') self.exitAction.triggered.connect(self.exitApp) self.aboutToDo = QAction('About To-Do List', self) # About Action.. self.aboutToDo.triggered.connect(self.aboutInfo) def appMenuBar(self): menuBar = self.menuBar() # Create Menu Bar.. self.setMenuBarAction() # Set Action for Menu Bar.. self.homeMenu = menuBar.addMenu( 'File') # Set File Menu to The MenuBar.. self.helpMenu = menuBar.addMenu( 'Help') # Set Help Menu to The MenuBar.. self.homeMenu.addAction( self.saveAction) # Save Action Added to File Menu.. self.homeMenu.addAction( self.saveAllAction) # Save All Action Added to File Menu.. self.homeMenu.addAction( self.exitAction) # Exit Action Added to File Menu.. self.helpMenu.addAction( self.aboutToDo) # Abouut Action Added to Help Menu.. def initUI(self): self.setWindowTitle(self.title) # Set title for the Application.. self.setWindowIcon(QIcon("./logo.png")) # set Icon for the Application self.setGeometry(self.left, self.top, self.width, self.height) # set app size.. self.setMaximumSize(QtCore.QSize( self.width, self.height)) # disabling Application Maximize button.. self.appMenuBar() # Set application MenuBar.. self.createTaskFile() # creating Task File for application.. # Task Text Input.. self.taskText = QLineEdit(self) self.taskText.move(10, 45) self.taskText.resize(self.width // 2 - 20, 50) self.taskText.setPlaceholderText('Enter Task Here..') # setting up uncompleted task text Area... self.textArea = QTextEdit(self) self.textArea.setReadOnly(True) # readonly text area.. self.textArea.move(self.width // 2, 45) self.textArea.resize(self.width // 2 - 2, self.height - 50) self.textArea.setLineWrapMode(QTextEdit.NoWrap) self.textArea.setTextColor(QColor(180, 0, 0)) # give font color to red.. self.textArea.setFontPointSize(10) # font size = 10.. # make Labels..... self.makeLabel(10, 21, 'Add Task Here') self.makeLabel(self.width // 2, 20, 'Uncompleted Task') self.makeLabel(5, self.height // 2 - 15, 'Completed Task List') self.makeLabel(10, 95, 'Set Reminder') # setting up completed task text Area.. self.completedtextArea = QTextEdit(self) self.completedtextArea.setReadOnly(True) # readonly text area.. self.completedtextArea.move(5, self.height // 2 + 10) self.completedtextArea.resize(self.width // 2 - 13, self.height // 2 - 15) self.completedtextArea.setLineWrapMode(QTextEdit.NoWrap) self.completedtextArea.setTextColor(QColor( 0, 180, 0)) # give font color to green.. self.completedtextArea.setFontPointSize(10) # font size = 10.. self.dateTimeBox = QDateTimeEdit(self) self.dateTimeBox.setGeometry(10, 125, 140, 25) self.loadTask() # loading preveiously stord To-Do Task.. self.Buttons() # make all the buttons for the Application.. self.show() # display the application..a def Buttons(self): # Add To-Do Button self.addButton = QPushButton("Add To-Do", self) self.addButton.move(15, 164) # Add Clear All Button self.clearAllButton = QPushButton("Clear All", self) self.clearAllButton.move(130, 164) # Adding Mark All Completed Button.. self.completedButton = QPushButton("Mark All Completed", self) self.completedButton.move(58, 203) self.completedButton.resize(140, 30) # Button events.. self.addButton.clicked.connect(self.onClick) self.clearAllButton.clicked.connect(self.clearAll) self.completedButton.clicked.connect(self.completeTask) def loadTask(self): if os.path.exists(self.uncompletedTaskFile): with open(self.uncompletedTaskFile, 'r') as f: text = f.read() if text != '': self.textArea.append(text) if os.path.exists(self.completedTaskFile): with open(self.completedTaskFile, 'r') as g: texts = g.read().split('\n') for text in texts: if text != '': self.completedtextArea.append(text) @pyqtSlot() def saveFile(self): file = self.textArea.toPlainText() try: fHandle = open(self.fName, 'a') fHandle.write(file) except: with open(self.fName, 'w') as f: f.write(file) fHandle.close() @pyqtSlot() def saveAllFile(self): uncompletedToDOText = self.textArea.toPlainText() completedToDOText = self.completedtextArea.toPlainText() if uncompletedToDOText == '': # if there is no task in uncompleted task list then skip it.. with open(self.fName, 'w') as f: f.write('Completed To-Do Task:\n\n') f.write(completedToDOText) elif completedToDOText == '': # if there is no task in completed task list then skip it.. with open(self.fName, 'w') as f: f.write('Uncompleted To-Do Task:\n\n') f.write(uncompletedToDOText + '\n\n') else: with open(self.fName, 'w') as f: # both.. f.write('Uncompleted To-Do Task:\n\n') f.write(uncompletedToDOText + '\n\n') f.write('Completed To-Do Task:\n\n') f.write(completedToDOText) @pyqtSlot() def aboutInfo(self): msg = QMessageBox() msg.setWindowTitle('To-Do List') msg.setGeometry(280, 190, 500, 420) msg.setWindowIcon(QIcon('logo.png')) msg.setText( '''Add Your Daily To-Do Task \n Bulid With Python & PyQt5. ''') msg.exec_() @pyqtSlot() def exitApp(self): sys.exit() # exit from the App.. @pyqtSlot() def onClick(self): textvalue = self.taskText.text() date = self.dateTimeBox.date() time = self.dateTimeBox.time() text = f'{textvalue} Date: {date.toPyDate()} Time: {time.toPyTime()}\n' # convert to string.. if textvalue == '': # If textvalue in taskText is blank then return don't update textArea.. return else: if os.path.exists(self.uncompletedTaskFile): with open(self.uncompletedTaskFile, 'a') as f: f.write(text) else: with open(self.uncompletedTaskFile, 'w') as f: f.write(text) self.textArea.append(text) # else update textArea.. self.taskText.setText('') #clear taskText.. @pyqtSlot() def clearAll(self): self.textArea.setText('') # clear uncompleted task list textArea.. self.completedtextArea.setText( '') # clear completed task list textArea.. with open(self.uncompletedTaskFile, 'w') as f, open(self.completedTaskFile, 'w') as g: f.close() g.close() @pyqtSlot() def completeTask(self): textValue = self.textArea.toPlainText( ) # get uncompleted task list text.. with open(self.uncompletedTaskFile, 'r+') as g: dataFile = g.read().split('\n') texts = textValue.split('\n') for text in texts: for data in dataFile: if data.startswith(text): g.truncate(0) if textValue == '': return else: if os.path.exists(self.completedTaskFile): with open(self.completedTaskFile, 'a') as f: texts = textValue.split('\n') for text in texts: if text != '': f.write(textValue) else: with open(self.completedTaskFile, 'w') as f: texts = textValue.split('\n') for text in texts: if text != '': f.write(textValue) texts = textValue.split('\n') for text in texts: if text != '': self.completedtextArea.append( text) # append to completed task list section.. self.textArea.setText('')
class BRFManager(myqt.QFrameLayout): sig_brfperiod_changed = QSignal(list) def __init__(self, wldset=None, parent=None): super(BRFManager, self).__init__(parent) self.viewer = BRFViewer(wldset, parent) self.kgs_brf_installer = None self.__initGUI__() def __initGUI__(self): self.setContentsMargins(10, 10, 10, 10) # ---- Detrend and Correct Options self.baro_spinbox = myqt.QDoubleSpinBox(100, 0, show_buttons=True) self.baro_spinbox.setRange(0, 9999) self.baro_spinbox.setKeyboardTracking(True) self.earthtides_spinbox = myqt.QDoubleSpinBox(100, 0, show_buttons=True) self.earthtides_spinbox.setRange(0, 9999) self.earthtides_spinbox.setKeyboardTracking(True) self.earthtides_cbox = QCheckBox('Nbr of ET lags :') self.earthtides_cbox.setChecked(True) self.earthtides_cbox.stateChanged.connect( lambda: self.earthtides_spinbox.setEnabled(self.earthtides_cbox. isChecked())) self.detrend_waterlevels_cbox = QCheckBox('Detrend water levels') self.detrend_waterlevels_cbox.setChecked(True) # Setup options layout. options_layout = QGridLayout() options_layout.addWidget(QLabel('Nbr of BP lags :'), 0, 0) options_layout.addWidget(self.baro_spinbox, 0, 2) options_layout.addWidget(self.earthtides_cbox, 1, 0) options_layout.addWidget(self.earthtides_spinbox, 1, 2) options_layout.addWidget(self.detrend_waterlevels_cbox, 2, 0, 1, 3) options_layout.setColumnStretch(1, 100) options_layout.setContentsMargins(0, 0, 0, 0) # ---- BRF date range self.date_start_edit = QDateTimeEdit() self.date_start_edit.setCalendarPopup(True) self.date_start_edit.setDisplayFormat('dd/MM/yyyy hh:mm') self.date_start_edit.dateChanged.connect( lambda: self.sig_brfperiod_changed.emit(self.get_brfperiod())) self.date_start_edit.dateChanged.connect( lambda: self.wldset.save_brfperiod(self.get_brfperiod())) self.date_end_edit = QDateTimeEdit() self.date_end_edit.setCalendarPopup(True) self.date_end_edit.setDisplayFormat('dd/MM/yyyy hh:mm') self.date_end_edit.dateChanged.connect( lambda: self.sig_brfperiod_changed.emit(self.get_brfperiod())) self.date_end_edit.dateChanged.connect( lambda: self.wldset.save_brfperiod(self.get_brfperiod())) self.btn_seldata = OnOffToolButton('select_range', size='small') self.btn_seldata.setToolTip("Select a BRF calculation period with " "the mouse cursor on the graph.") # Setup BRF date range layout. daterange_layout = QGridLayout() daterange_layout.addWidget(QLabel('BRF Start :'), 0, 0) daterange_layout.addWidget(self.date_start_edit, 0, 2) daterange_layout.addWidget(QLabel('BRF End :'), 1, 0) daterange_layout.addWidget(self.date_end_edit, 1, 2) daterange_layout.setColumnStretch(1, 100) daterange_layout.setContentsMargins(0, 0, 0, 0) seldata_layout = QGridLayout() seldata_layout.addWidget(self.btn_seldata, 0, 0) seldata_layout.setRowStretch(1, 100) seldata_layout.setContentsMargins(0, 0, 0, 0) # ---- Toolbar btn_comp = QPushButton('Compute BRF') btn_comp.clicked.connect(self.calc_brf) btn_comp.setFocusPolicy(Qt.NoFocus) self.btn_show = QToolButtonSmall(icons.get_icon('search')) self.btn_show.clicked.connect(self.viewer.show) # ---- Main Layout self.addLayout(daterange_layout, 0, 0) self.addLayout(seldata_layout, 0, 1) self.setRowMinimumHeight(1, 15) self.addLayout(options_layout, 2, 0) self.setRowMinimumHeight(3, 15) self.setRowStretch(3, 100) self.addWidget(btn_comp, 4, 0) self.addWidget(self.btn_show, 4, 1) self.setColumnStretch(0, 100) # ---- Install Panel if not KGSBRFInstaller().kgsbrf_is_installed(): self.__install_kgs_brf_installer() # ---- Properties @property def nlag_baro(self): """Return the number of lags to use for barometric correction.""" return self.baro_spinbox.value() @property def nlag_earthtides(self): """Return the number of lags to use for Earth tides correction.""" return (self.earthtides_spinbox.value() if self.earthtides_cbox.isChecked() else -1) @property def detrend_waterlevels(self): return self.detrend_waterlevels_cbox.isChecked() @property def correct_waterlevels(self): return True def get_brfperiod(self): """ Get the period over which the BRF would be evaluated as a list of two numerical Excel date values. """ year, month, day = self.date_start_edit.date().getDate() hour = self.date_start_edit.time().hour() minute = self.date_start_edit.time().minute() dstart = xldate_from_datetime_tuple( (year, month, day, hour, minute, 0), 0) year, month, day = self.date_end_edit.date().getDate() hour = self.date_end_edit.time().hour() minute = self.date_end_edit.time().minute() dend = xldate_from_datetime_tuple((year, month, day, hour, minute, 0), 0) return [dstart, dend] def set_brfperiod(self, period): """ Set the value of the date_start_edit and date_end_edit widgets used to define the period over which the BRF is evaluated. Also save the period to the waterlevel dataset. """ period = np.sort(period).tolist() widgets = (self.date_start_edit, self.date_end_edit) for xldate, widget in zip(period, widgets): if xldate is not None: widget.blockSignals(True) widget.setDateTime(qdatetime_from_xldate(xldate)) widget.blockSignals(False) self.wldset.save_brfperiod(period) # ---- KGS BRF installer def __install_kgs_brf_installer(self): """ Installs a KGSBRFInstaller that overlays the whole brf tool layout until the KGS_BRF program is installed correctly. """ self.kgs_brf_installer = KGSBRFInstaller() self.kgs_brf_installer.sig_kgs_brf_installed.connect( self.__uninstall_kgs_brf_installer) self.addWidget(self.kgs_brf_installer, 0, 0, self.rowCount(), self.columnCount()) def __uninstall_kgs_brf_installer(self): """ Uninstall the KGSBRFInstaller after the KGS_BRF program has been installed properly. """ self.kgs_brf_installer.sig_kgs_brf_installed.disconnect() self.kgs_brf_installer = None def set_wldset(self, wldset): """Set the namespace for the wldset in the widget.""" self.wldset = wldset self.viewer.set_wldset(wldset) self.btn_seldata.setAutoRaise(True) self.setEnabled(wldset is not None) if wldset is not None: xldates = self.wldset.xldates self.set_daterange((xldates[0], xldates[-1])) # Set the period over which the BRF would be evaluated. saved_brfperiod = wldset.get_brfperiod() self.set_brfperiod( (saved_brfperiod[0] or np.floor(xldates[0]), saved_brfperiod[1] or np.floor(xldates[-1]))) def set_daterange(self, daterange): """ Set the minimum and maximum value of date_start_edit and date_end_edit widgets from the specified list of Excel numeric dates. """ for widget in (self.date_start_edit, self.date_end_edit): widget.blockSignals(True) widget.setMinimumDateTime(qdatetime_from_xldate(daterange[0])) widget.setMaximumDateTime(qdatetime_from_xldate(daterange[1])) widget.blockSignals(False) def calc_brf(self): """Prepare the data, calcul the brf, and save and plot the results.""" # Prepare the datasets. well = self.wldset['Well'] brfperiod = self.get_brfperiod() t1 = min(brfperiod) i1 = np.where(self.wldset.xldates >= t1)[0][0] t2 = max(brfperiod) i2 = np.where(self.wldset.xldates <= t2)[0][-1] time = np.copy(self.wldset.xldates[i1:i2 + 1]) wl = np.copy(self.wldset['WL'][i1:i2 + 1]) bp = np.copy(self.wldset['BP'][i1:i2 + 1]) if len(bp) == 0: msg = ("The barometric response function cannot be computed" " because the currently selected water level dataset does" " not contain any barometric data for the selected period.") QMessageBox.warning(self, 'Warning', msg, QMessageBox.Ok) return et = np.copy(self.wldset['ET'][i1:i2 + 1]) if len(et) == 0: et = np.zeros(len(wl)) # Fill the gaps in the waterlevel data. dt = np.min(np.diff(time)) tc = np.arange(t1, t2 + dt / 2, dt) if len(tc) != len(time) or np.any(np.isnan(wl)): print('Filling gaps in data with linear interpolation.') indx = np.where(~np.isnan(wl))[0] wl = np.interp(tc, time[indx], wl[indx]) indx = np.where(~np.isnan(bp))[0] bp = np.interp(tc, time[indx], bp[indx]) indx = np.where(~np.isnan(et))[0] et = np.interp(tc, time[indx], et[indx]) time = tc QApplication.setOverrideCursor(Qt.WaitCursor) print('calculating the BRF') bm.produce_BRFInputtxt(well, time, wl, bp, et) msg = ("Not enough data. Try enlarging the selected period " "or reduce the number of BP lags.") if self.nlag_baro >= len(time) or self.nlag_earthtides >= len(time): QApplication.restoreOverrideCursor() QMessageBox.warning(self, 'Warning', msg, QMessageBox.Ok) return bm.produce_par_file(self.nlag_baro, self.nlag_earthtides, self.detrend_waterlevels, self.correct_waterlevels) bm.run_kgsbrf() try: dataf = bm.read_brf_output() date_start, date_end = (xldate_as_datetime(xldate, 0) for xldate in self.get_brfperiod()) self.wldset.save_brf(dataf, date_start, date_end, self.detrend_waterlevels) self.viewer.new_brf_added() self.viewer.show() QApplication.restoreOverrideCursor() except Exception: QApplication.restoreOverrideCursor() QMessageBox.warning(self, 'Warning', msg, QMessageBox.Ok) return
class BRFManager(myqt.QFrameLayout): sig_brfperiod_changed = QSignal(list) def __init__(self, wldset=None, parent=None): super(BRFManager, self).__init__(parent) self.viewer = BRFViewer(wldset, parent) self.kgs_brf_installer = None self.__initGUI__() def __initGUI__(self): self.setContentsMargins(10, 10, 10, 10) # ---- Detrend and Correct Options self.baro_spinbox = myqt.QDoubleSpinBox(100, 0, show_buttons=True) self.baro_spinbox.setRange(0, 9999) self.baro_spinbox.setKeyboardTracking(True) self.earthtides_spinbox = myqt.QDoubleSpinBox( 100, 0, show_buttons=True) self.earthtides_spinbox.setRange(0, 9999) self.earthtides_spinbox.setKeyboardTracking(True) self.earthtides_cbox = QCheckBox('Nbr of ET lags :') self.earthtides_cbox.setChecked(True) self.earthtides_cbox.stateChanged.connect( lambda: self.earthtides_spinbox.setEnabled( self.earthtides_cbox.isChecked())) self.detrend_waterlevels_cbox = QCheckBox('Detrend water levels') self.detrend_waterlevels_cbox.setChecked(True) # Setup options layout. options_layout = QGridLayout() options_layout.addWidget(QLabel('Nbr of BP lags :'), 0, 0) options_layout.addWidget(self.baro_spinbox, 0, 2) options_layout.addWidget(self.earthtides_cbox, 1, 0) options_layout.addWidget(self.earthtides_spinbox, 1, 2) options_layout.addWidget(self.detrend_waterlevels_cbox, 2, 0, 1, 3) options_layout.setColumnStretch(1, 100) options_layout.setContentsMargins(0, 0, 0, 0) # ---- BRF date range self.date_start_edit = QDateTimeEdit() self.date_start_edit.setCalendarPopup(True) self.date_start_edit.setDisplayFormat('dd/MM/yyyy hh:mm') self.date_start_edit.dateChanged.connect( lambda: self.sig_brfperiod_changed.emit(self.get_brfperiod())) self.date_start_edit.dateChanged.connect( lambda: self.wldset.save_brfperiod(self.get_brfperiod())) self.date_end_edit = QDateTimeEdit() self.date_end_edit.setCalendarPopup(True) self.date_end_edit.setDisplayFormat('dd/MM/yyyy hh:mm') self.date_end_edit.dateChanged.connect( lambda: self.sig_brfperiod_changed.emit(self.get_brfperiod())) self.date_end_edit.dateChanged.connect( lambda: self.wldset.save_brfperiod(self.get_brfperiod())) self.btn_seldata = OnOffToolButton('select_range', size='small') self.btn_seldata.setToolTip("Select a BRF calculation period with " "the mouse cursor on the graph.") # Setup BRF date range layout. daterange_layout = QGridLayout() daterange_layout.addWidget(QLabel('BRF Start :'), 0, 0) daterange_layout.addWidget(self.date_start_edit, 0, 2) daterange_layout.addWidget(QLabel('BRF End :'), 1, 0) daterange_layout.addWidget(self.date_end_edit, 1, 2) daterange_layout.setColumnStretch(1, 100) daterange_layout.setContentsMargins(0, 0, 0, 0) seldata_layout = QGridLayout() seldata_layout.addWidget(self.btn_seldata, 0, 0) seldata_layout.setRowStretch(1, 100) seldata_layout.setContentsMargins(0, 0, 0, 0) # ---- Toolbar btn_comp = QPushButton('Compute BRF') btn_comp.clicked.connect(self.calc_brf) btn_comp.setFocusPolicy(Qt.NoFocus) self.btn_show = QToolButtonSmall(icons.get_icon('search')) self.btn_show.clicked.connect(self.viewer.show) # ---- Main Layout self.addLayout(daterange_layout, 0, 0) self.addLayout(seldata_layout, 0, 1) self.setRowMinimumHeight(1, 15) self.addLayout(options_layout, 2, 0) self.setRowMinimumHeight(3, 15) self.setRowStretch(3, 100) self.addWidget(btn_comp, 4, 0) self.addWidget(self.btn_show, 4, 1) self.setColumnStretch(0, 100) # ---- Install Panel if not KGSBRFInstaller().kgsbrf_is_installed(): self.__install_kgs_brf_installer() # ---- Properties @property def nlag_baro(self): """Return the number of lags to use for barometric correction.""" return self.baro_spinbox.value() @property def nlag_earthtides(self): """Return the number of lags to use for Earth tides correction.""" return (self.earthtides_spinbox.value() if self.earthtides_cbox.isChecked() else -1) @property def detrend_waterlevels(self): return self.detrend_waterlevels_cbox.isChecked() @property def correct_waterlevels(self): return True def get_brfperiod(self): """ Get the period over which the BRF would be evaluated as a list of two numerical Excel date values. """ year, month, day = self.date_start_edit.date().getDate() hour = self.date_start_edit.time().hour() minute = self.date_start_edit.time().minute() dstart = xldate_from_datetime_tuple( (year, month, day, hour, minute, 0), 0) year, month, day = self.date_end_edit.date().getDate() hour = self.date_end_edit.time().hour() minute = self.date_end_edit.time().minute() dend = xldate_from_datetime_tuple( (year, month, day, hour, minute, 0), 0) return [dstart, dend] def set_brfperiod(self, period): """ Set the value of the date_start_edit and date_end_edit widgets used to define the period over which the BRF is evaluated. Also save the period to the waterlevel dataset. """ period = np.sort(period).tolist() widgets = (self.date_start_edit, self.date_end_edit) for xldate, widget in zip(period, widgets): if xldate is not None: widget.blockSignals(True) widget.setDateTime(qdatetime_from_xldate(xldate)) widget.blockSignals(False) self.wldset.save_brfperiod(period) # ---- KGS BRF installer def __install_kgs_brf_installer(self): """ Installs a KGSBRFInstaller that overlays the whole brf tool layout until the KGS_BRF program is installed correctly. """ self.kgs_brf_installer = KGSBRFInstaller() self.kgs_brf_installer.sig_kgs_brf_installed.connect( self.__uninstall_kgs_brf_installer) self.addWidget(self.kgs_brf_installer, 0, 0, self.rowCount(), self.columnCount()) def __uninstall_kgs_brf_installer(self): """ Uninstall the KGSBRFInstaller after the KGS_BRF program has been installed properly. """ self.kgs_brf_installer.sig_kgs_brf_installed.disconnect() self.kgs_brf_installer = None def set_wldset(self, wldset): """Set the namespace for the wldset in the widget.""" self.wldset = wldset self.viewer.set_wldset(wldset) self.btn_seldata.setAutoRaise(True) self.setEnabled(wldset is not None) if wldset is not None: xldates = self.wldset.xldates self.set_daterange((xldates[0], xldates[-1])) # Set the period over which the BRF would be evaluated. saved_brfperiod = wldset.get_brfperiod() self.set_brfperiod((saved_brfperiod[0] or np.floor(xldates[0]), saved_brfperiod[1] or np.floor(xldates[-1]))) def set_daterange(self, daterange): """ Set the minimum and maximum value of date_start_edit and date_end_edit widgets from the specified list of Excel numeric dates. """ for widget in (self.date_start_edit, self.date_end_edit): widget.blockSignals(True) widget.setMinimumDateTime(qdatetime_from_xldate(daterange[0])) widget.setMaximumDateTime(qdatetime_from_xldate(daterange[1])) widget.blockSignals(False) def calc_brf(self): """Prepare the data, calcul the brf, and save and plot the results.""" # Prepare the datasets. well = self.wldset['Well'] brfperiod = self.get_brfperiod() t1 = min(brfperiod) i1 = np.where(self.wldset.xldates >= t1)[0][0] t2 = max(brfperiod) i2 = np.where(self.wldset.xldates <= t2)[0][-1] time = np.copy(self.wldset.xldates[i1:i2+1]) wl = np.copy(self.wldset['WL'][i1:i2+1]) bp = np.copy(self.wldset['BP'][i1:i2+1]) if len(bp) == 0: msg = ("The barometric response function cannot be computed" " because the currently selected water level dataset does" " not contain any barometric data for the selected period.") QMessageBox.warning(self, 'Warning', msg, QMessageBox.Ok) return et = np.copy(self.wldset['ET'][i1:i2+1]) if len(et) == 0: et = np.zeros(len(wl)) # Fill the gaps in the waterlevel data. dt = np.min(np.diff(time)) tc = np.arange(t1, t2+dt/2, dt) if len(tc) != len(time) or np.any(np.isnan(wl)): print('Filling gaps in data with linear interpolation.') indx = np.where(~np.isnan(wl))[0] wl = np.interp(tc, time[indx], wl[indx]) indx = np.where(~np.isnan(bp))[0] bp = np.interp(tc, time[indx], bp[indx]) indx = np.where(~np.isnan(et))[0] et = np.interp(tc, time[indx], et[indx]) time = tc QApplication.setOverrideCursor(Qt.WaitCursor) print('calculating the BRF') bm.produce_BRFInputtxt(well, time, wl, bp, et) msg = ("Not enough data. Try enlarging the selected period " "or reduce the number of BP lags.") if self.nlag_baro >= len(time) or self.nlag_earthtides >= len(time): QApplication.restoreOverrideCursor() QMessageBox.warning(self, 'Warning', msg, QMessageBox.Ok) return bm.produce_par_file( self.nlag_baro, self.nlag_earthtides, self.detrend_waterlevels, self.correct_waterlevels) bm.run_kgsbrf() try: dataf = bm.read_brf_output() date_start, date_end = (xldate_as_datetime(xldate, 0) for xldate in self.get_brfperiod()) self.wldset.save_brf(dataf, date_start, date_end, self.detrend_waterlevels) self.viewer.new_brf_added() self.viewer.show() QApplication.restoreOverrideCursor() except Exception: QApplication.restoreOverrideCursor() QMessageBox.warning(self, 'Warning', msg, QMessageBox.Ok) return