def calcall(self): fr_d_t = self.FromDateTime.dateTime().toPyDateTime() to_d_t = self.ToDateTime.dateTime().toPyDateTime() # sanity1 = utils.sql_load_fr_db("""SELECT obs_points.h_toc FROM obs_points LEFT JOIN w_levels WHERE w_levels.obsid = obs_points.obsid AND obs_points.h_toc""")[1] sanity1 = utils.sql_load_fr_db("""SELECT obs_points.h_toc FROM obs_points LEFT JOIN w_levels WHERE w_levels.obsid = obs_points.obsid""")[1] sanity2 = utils.sql_load_fr_db("""SELECT obs_points.h_toc FROM obs_points LEFT JOIN w_levels WHERE w_levels.obsid = obs_points.obsid AND obs_points.h_toc NOT NULL""")[1] if len(sanity1) == len(sanity2): #only if h_toc exists for all objects!! sql1 = """UPDATE OR IGNORE w_levels SET h_toc = (SELECT obs_points.h_toc FROM obs_points WHERE w_levels.obsid = obs_points.obsid) WHERE """ sql1 += """date_time >= '""" sql1 += str(fr_d_t) sql1 += """' AND date_time <= '""" sql1 += str(to_d_t) sql1 += """' """ utils.sql_alter_db(sql1) sql2 = """UPDATE OR IGNORE w_levels SET level_masl = h_toc - meas WHERE """ sql2 += """date_time >= '""" sql2 += str(fr_d_t) sql2 += """' AND date_time <= '""" sql2 += str(to_d_t) sql2 += """' """ utils.sql_alter_db(sql2) self.close() else: utils.pop_up_info('Calculation aborted! There seems to be NULL values in your table obs_points, column h_toc.','Error') self.close()
def calibrateandplot(self): obsid = unicode(self.combobox_obsid.currentText()) if not obsid=='': sanity1sql = """select count(obsid) from w_levels_logger where obsid = '""" + obsid[0] + """'""" sanity2sql = """select count(obsid) from w_levels_logger where head_cm not null and head_cm !='' and obsid = '""" + obsid[0] + """'""" if utils.sql_load_fr_db(sanity1sql)[1] == utils.sql_load_fr_db(sanity2sql)[1]: # This must only be done if head_cm exists for all data fr_d_t = self.FromDateTime.dateTime().toPyDateTime() to_d_t = self.ToDateTime.dateTime().toPyDateTime() newzref = self.LoggerPos.text() if len(newzref)>0: sql =r"""UPDATE w_levels_logger SET level_masl = """ sql += str(newzref) sql += """ + head_cm / 100 WHERE obsid = '""" sql += obsid sql += """' AND date_time >= '""" sql += str(fr_d_t) sql += """' AND date_time <= '""" sql += str(to_d_t) sql += """' """ dummy = utils.sql_alter_db(sql) self.CalibrationPlot(obsid) self.getlastcalibration() else: utils.pop_up_info("Calibration aborted!!\nThere must not be empty cells or\nnull values in the 'head_cm' column!") else: self.INFO.setText("Select the observation point with logger data to be calibrated.")
def settings_strings_dialogs(self): msg = ru( QCoreApplication.translate( u'ExportToFieldLogger', u'Edit the settings string for input fields browser and restart export fieldlogger dialog\nto load the change.' )) browser_updated = self.ask_and_update_settings( [self.parameter_browser], self.stored_settingskey_parameterbrowser, msg) msg = ru( QCoreApplication.translate( u'ExportToFieldLogger', u'Edit the settings string for input fields groups and restart export fieldlogger dialog\nto load the change.' )) groups_updated = self.ask_and_update_settings(self.parameter_groups, self.stored_settingskey, msg) if browser_updated or groups_updated: utils.pop_up_info( ru( QCoreApplication.translate( u'ExportToFieldLogger', u'Settings updated. Restart Export to Fieldlogger dialog\nor press "Save settings" to undo.' )))
def calcselected(self): obsar = utils.getselectedobjectnames(self.layer) observations = obsar i=0 for obs in obsar: observations[i] = obs.encode('utf-8') #turn into a list of python byte strings i += 1 fr_d_t = self.FromDateTime.dateTime().toPyDateTime() to_d_t = self.ToDateTime.dateTime().toPyDateTime() sanity1 = utils.sql_load_fr_db("""SELECT obs_points.h_toc FROM obs_points LEFT JOIN w_levels WHERE w_levels.obsid = obs_points.obsid AND obs_points.obsid IN """ + (str(observations)).encode('utf-8').replace('[','(').replace(']',')'))[1] sanity2 = utils.sql_load_fr_db("""SELECT obs_points.h_toc FROM obs_points LEFT JOIN w_levels WHERE w_levels.obsid = obs_points.obsid AND obs_points.h_toc NOT NULL AND obs_points.obsid IN """ + (str(observations)).encode('utf-8').replace('[','(').replace(']',')'))[1] if len(sanity1) == len(sanity2): #only if h_toc exists for all objects sql1 = """UPDATE OR IGNORE w_levels SET h_toc = (SELECT obs_points.h_toc FROM obs_points WHERE w_levels.obsid = obs_points.obsid) WHERE obsid IN """ sql1 += str(observations) sql1 += """ AND date_time >= '""" sql1 += str(fr_d_t) sql1 += """' AND date_time <= '""" sql1 += str(to_d_t) sql1 += """' """ utils.sql_alter_db(sql1.replace("[","(").replace("]",")")) sql2 = """UPDATE OR IGNORE w_levels SET level_masl = h_toc - meas WHERE obsid IN """ sql2 += str(observations) sql2 += """ AND date_time >= '""" sql2 += str(fr_d_t) sql2 += """' AND date_time <= '""" sql2 += str(to_d_t) sql2 += """' """ utils.sql_alter_db(sql2.replace("[","(").replace("]",")")) self.close() else: utils.pop_up_info('Calculation aborted! There seems to be NULL values in your table obs_points, column h_toc.','Error') self.close()
def calculate_offset(self): """ Part of adjustment method 3. adjust level_masl by clicking in plot. this method extracts the head from head_ts with the same date as the line node. 4. Calculating y-position - head (or level_masl) and setting self.LoggerPos. 5. Run calibration. """ if self.log_pos is not None and self.y_pos is not None: utils.start_waiting_cursor() logger_ts = self.level_masl_ts y_pos = self.y_pos log_pos = self.log_pos self.y_pos = None self.log_pos = None log_pos_date = datestring_to_date(log_pos).replace(tzinfo=None) logger_value = None #Get the value for the selected node for raw_date, logger_value in logger_ts: date = datestring_to_date(raw_date).replace(tzinfo=None) if date == log_pos_date: break if logger_value is None: utils.pop_up_info(ru(QCoreApplication.translate('Calibrlogger', "No connection between level_masl dates and logger date could be made!\nTry again or choose a new logger line node!"))) else: self.Add2Levelmasl.setText(str(float(y_pos) - float(logger_value))) utils.stop_waiting_cursor() self.pushButtonMpos.setEnabled(False)
def calc_best_fit(self): """ Calculates the self.LoggerPos from self.meas_ts and self.head_ts First matches measurements from self.meas_ts to logger values from self.head_ts. This is done by making a mean of all logger values inside self.meas_ts date - tolerance and self.meas_ts date + tolerance. (this could probably be change to get only the closest logger value inside the tolerance instead) (Tolerance is gotten from self.get_tolerance()) Then calculates the mean of all matches and set to self.LoggerPos. """ obsid = self.load_obsid_and_init() self.reset_plot_selects_and_calib_help() tolerance = self.get_tolerance() really_calibrate_question = utils.askuser("YesNo", """This will calibrate all values inside the chosen period\nusing the mean difference between logger values and measurements.\n\nTime tolerance for matching logger and measurement nodes set to '""" + ' '.join(tolerance) + """'\n\nContinue?""") if really_calibrate_question.result == 0: # if the user wants to abort return PyQt4.QtGui.QApplication.setOverrideCursor(PyQt4.QtCore.Qt.WaitCursor) if self.loggerpos_masl_or_offset_state == 1: logger_ts = self.head_ts else: logger_ts = self.level_masl_ts coupled_vals = self.match_ts_values(self.meas_ts, logger_ts, tolerance) if not coupled_vals: utils.pop_up_info("There was no matched measurements or logger values inside the chosen period.\n Try to increase the tolerance!") else: self.LoggerPos.setText(str(utils.calc_mean_diff(coupled_vals))) self.calibrateandplot() PyQt4.QtGui.QApplication.restoreOverrideCursor()
def showSurvey(self): #lyr = self.iface.activeLayer() # THIS IS TSPLOT-method, GETS THE SELECTED LAYER lyr = self.layer ids = lyr.selectedFeaturesIds() if len(ids) == 0: utils.pop_up_info( ru( QCoreApplication.translate(u' Stratigraphy', u"No selection")), ru( QCoreApplication.translate(u' Stratigraphy', u"No features are selected"))) return # initiate the datastore if not yet done self.initStore() PyQt4.QtGui.QApplication.setOverrideCursor( PyQt4.QtCore.Qt.WaitCursor) # Sets the mouse cursor to wait symbol try: # return from store.getData is stored in data only if no object belonging to DataSanityError class is created self.data = self.store.getData(ids, lyr) # added lyr as an argument!!! except DataSanityError, e: # if an object 'e' belonging to DataSanityError is created, then do following print("DataSanityError %s" % str(e)) PyQt4.QtGui.QApplication.restoreOverrideCursor() utils.pop_up_info( ru( QCoreApplication.translate( u' Stratigraphy', u"Data sanity problem, obsid: %s\n%s")) % (e.sond_id, e.message)) return
def __init__(self, obsids=[''], settingsdict = {}): reportfolder = os.path.join(QDir.tempPath(), 'midvatten_reports') if not os.path.exists(reportfolder): os.makedirs(reportfolder) reportpath = os.path.join(reportfolder, "drill_report.html") logopath = os.path.join(os.sep,os.path.dirname(__file__),"..","templates","midvatten_logga.png") imgpath = os.path.join(os.sep,os.path.dirname(__file__),"..","templates") if len(obsids) == 0: utils.pop_up_info(ru(QCoreApplication.translate('Drillreport', "Must select one or more obsids!"))) return None elif len(obsids) == 1: merged_question = False else: #Due to problems regarding speed when opening many tabs, only the merge mode is used. #merged_question = utils.Askuser(question='YesNo', msg="Do you want to open all drill reports merged on the same tab?\n" # "Else they will be opened separately.\n\n(If answering no, creating drill reports for many obsids take 0.2 seconds per obsid.\nIt might fail if the computer is to slow.\nIf it fails, try to select only one obsid at the time)").result merged_question = True if merged_question: f, rpt = self.open_file(', '.join(obsids), reportpath) for obsid in obsids: self.write_obsid(obsid, rpt, imgpath, logopath, f) self.close_file(f, reportpath) else: #opened = False for obsid in obsids: f, rpt = self.open_file(obsid, reportpath) self.write_obsid(obsid, rpt, imgpath, logopath, f) url_status = self.close_file(f, reportpath)
def showSurvey(self): #lyr = self.iface.activeLayer() # THIS IS TSPLOT-method, GETS THE SELECTED LAYER lyr = self.layer ids = lyr.selectedFeatureIds() if len(ids) == 0: utils.pop_up_info(ru(QCoreApplication.translate(' Stratigraphy', "No selection")), ru(QCoreApplication.translate(' Stratigraphy', "No features are selected"))) return # initiate the datastore if not yet done self.initStore() utils.start_waiting_cursor() # Sets the mouse cursor to wait symbol try: # return from store.getData is stored in data only if no object belonging to DataSanityError class is created self.data = self.store.getData(ids, lyr) # added lyr as an argument!!! except DataSanityError as e: # if an object 'e' belonging to DataSanityError is created, then do following print("DataSanityError %s"%str(e)) utils.stop_waiting_cursor() utils.pop_up_info(ru(QCoreApplication.translate(' Stratigraphy', "Data sanity problem, obsid: %s\n%s")) % (e.sond_id, e.message)) return except Exception as e: # if an object 'e' belonging to DataSanityError is created, then do following print("exception : %s"%str(e)) utils.stop_waiting_cursor() utils.MessagebarAndLog.critical(bar_msg=ru(QCoreApplication.translate(' Stratigraphy', "The stratigraphy plot failed, check Midvatten plugin settings and your data!"))) return utils.stop_waiting_cursor() # Restores the mouse cursor to normal symbol # show widget w = SurveyDialog() #w.widget.setData2_nosorting(data) #THIS IS IF DATA IS NOT TO BE SORTED!! w.widget.setData(self.data) #THIS IS ONLY TO SORT DATA!! w.show() self.w = w # save reference so it doesn't get deleted immediately This has to be done both here and also in midvatten instance
def delete_selected_range(self, table_name): """ Deletes the current selected range from the database from w_levels_logger :return: De """ current_loaded_obsid = self.obsid selected_obsid = self.load_obsid_and_init() if current_loaded_obsid != selected_obsid: utils.pop_up_info(ru(QCoreApplication.translate('Calibrlogger', "Error!\n The obsid selection has been changed but the plot has not been updated. No deletion done.\nUpdating plot."))) self.update_plot() return elif selected_obsid is None: utils.pop_up_info(ru(QCoreApplication.translate('Calibrlogger', "Error!\n No obsid was selected. No deletion done.\nUpdating plot."))) self.update_plot() return fr_d_t = str((self.FromDateTime.dateTime().toPyDateTime() - datetime.datetime(1970,1,1)).total_seconds()) to_d_t = str((self.ToDateTime.dateTime().toPyDateTime() - datetime.datetime(1970,1,1)).total_seconds()) sql_list = [] sql_list.append(r"""DELETE FROM "%s" """%table_name) sql_list.append(r"""WHERE obsid = '%s' """%selected_obsid) # This %s is db formatting for seconds. It is not used as python formatting! sql_list.append(r"""AND CAST(strftime('%s', date_time) AS NUMERIC) """) sql_list.append(r""" > '%s' """%fr_d_t) # This %s is db formatting for seconds. It is not used as python formatting! sql_list.append(r"""AND CAST(strftime('%s', date_time) AS NUMERIC) """) sql_list.append(r""" < '%s' """%to_d_t) sql = ''.join(sql_list) really_delete = utils.Askuser("YesNo", ru(QCoreApplication.translate('Calibrlogger', "Do you want to delete the period %s to %s for obsid %s from table %s?"))%(str(self.FromDateTime.dateTime().toPyDateTime()), str(self.ToDateTime.dateTime().toPyDateTime()), selected_obsid, table_name)).result if really_delete: utils.start_waiting_cursor() db_utils.sql_alter_db(sql) utils.stop_waiting_cursor() self.update_plot()
def delete_selected_range(self, table_name): """ Deletes the current selected range from the database from w_levels_logger :return: De """ current_loaded_obsid = self.obsid selected_obsid = self.load_obsid_and_init() if current_loaded_obsid != selected_obsid: utils.pop_up_info("Error!\n The obsid selection has been changed but the plot has not been updated. No deletion done.\nUpdating plot.") self.update_plot() return fr_d_t = str((self.FromDateTime.dateTime().toPyDateTime() - datetime.datetime(1970,1,1)).total_seconds()) to_d_t = str((self.ToDateTime.dateTime().toPyDateTime() - datetime.datetime(1970,1,1)).total_seconds()) sql_list = [] sql_list.append(r"""delete from "%s" """%table_name) sql_list.append(r"""where obsid = '%s' """%selected_obsid) sql_list.append(r"""AND CAST(strftime('%s', date_time) AS NUMERIC) """) sql_list.append(r""" >= '%s' """%fr_d_t) sql_list.append(r"""AND CAST(strftime('%s', date_time) AS NUMERIC) """) sql_list.append(r""" <= '%s' """%to_d_t) sql = ''.join(sql_list) really_delete = utils.askuser("YesNo", "Do you want to delete the period " + str(self.FromDateTime.dateTime().toPyDateTime()) + " to " + str(self.ToDateTime.dateTime().toPyDateTime()) + " for obsid " + selected_obsid + " from table " + table_name + "?").result if really_delete: utils.sql_alter_db(sql) self.update_plot()
def calcselected(self): obsids = ru(utils.getselectedobjectnames(self.layer), keep_containers=True) if not obsids: utils.pop_up_info(ru(QCoreApplication.translate('Calclvl', 'Adjustment aborted! No obsids selected.')), ru(QCoreApplication.translate('Calclvl', 'Error'))) else: self.calc(obsids)
def settings_strings_dialogs(self): msg = ru(QCoreApplication.translate('ExportToFieldLogger', 'Edit the settings string for input fields browser and restart export fieldlogger dialog\nto load the change.')) browser_updated = self.ask_and_update_settings([self.parameter_browser], self.stored_settingskey_parameterbrowser, msg) msg = ru(QCoreApplication.translate('ExportToFieldLogger', 'Edit the settings string for input fields groups and restart export fieldlogger dialog\nto load the change.')) groups_updated = self.ask_and_update_settings(self.parameter_groups, self.stored_settingskey, msg) if browser_updated or groups_updated: utils.pop_up_info(ru(QCoreApplication.translate('ExportToFieldLogger', 'Settings updated. Restart Export to Fieldlogger dialog\nor press "Save settings" to undo.')))
def calibrate_from_plot_selection(self): """ Calibrates by selecting a line node and a y-position on the plot The user have to click on the button three times and follow instructions. The process: 1. Selecting a line node. 2. Selecting a selecting a y-position from the plot. 3. Extracting the head from head_ts with the same date as the line node. 4. Calculating y-position - head (or level_masl) and setting self.LoggerPos. 5. Run calibration. """ #Run init to make sure self.meas_ts and self.head_ts is updated for the current obsid. self.load_obsid_and_init() self.deactivate_pan_zoom() self.canvas.setFocusPolicy(Qt.ClickFocus) self.canvas.setFocus() if self.log_pos is None: self.calib_help.setText("Select a logger node.") self.cid.append(self.canvas.mpl_connect('pick_event', self.set_log_pos_from_node_date_click)) if self.log_pos is not None and self.y_pos is None: self.calib_help.setText("Select a y position to move to.") self.cid.append(self.canvas.mpl_connect('button_press_event', self.set_y_pos_from_y_click)) if self.log_pos is not None and self.y_pos is not None: PyQt4.QtGui.QApplication.setOverrideCursor(PyQt4.QtCore.Qt.WaitCursor) if self.loggerpos_masl_or_offset_state == 1: logger_ts = self.head_ts else: logger_ts = self.level_masl_ts y_pos = self.y_pos log_pos = self.log_pos self.y_pos = None self.log_pos = None log_pos_date = datestring_to_date(log_pos).replace(tzinfo=None) logger_value = None #Get the value for the selected node for idx, date_value_tuple in enumerate(logger_ts): raw_date, logger_value = date_value_tuple date = datestring_to_date(raw_date).replace(tzinfo=None) if date == log_pos_date: break if logger_value is None: utils.pop_up_info("No connection between head_ts dates and logger date could be made!\nTry again or choose a new logger line node!") else: self.LoggerPos.setText(str(float(y_pos) - float(logger_value))) PyQt4.QtGui.QApplication.restoreOverrideCursor() self.calibrateandplot() self.calib_help.setText("")
def calcall(self): obsids = db_utils.sql_load_fr_db("""SELECT DISTINCT obsid FROM w_levels""")[1] if obsids: obsids = [x[0] for x in obsids] self.calc(obsids) else: utils.pop_up_info(ru(QCoreApplication.translate('Calclvl', 'Adjustment aborted! No obsids in w_levels.')), ru(QCoreApplication.translate('Calclvl', 'Error')))
def file_data_loaded_popup(self): if self.file_data is not None: for button in (self.select_file_button, self.import_all_features_button, self.import_selected_features_button): button.setEnabled(False) utils.pop_up_info(msg=ru( QCoreApplication.translate( u'GeneralCsvImportGui', u'File data loaded. Select table to import to.')))
def write_printlist_to_file(printlist): filename = utils.get_save_file_name_no_extension(parent=None, caption=ru(QCoreApplication.translate('ExportToFieldLogger', 'Choose a file name')), directory='', filter='csv (*.csv)') if os.path.splitext(filename)[1] != '.csv': filename += '.csv' try: with open(filename, 'w') as f: f.write('\n'.join(printlist)) except IOError as e: utils.pop_up_info(ru(QCoreApplication.translate('ExportToFieldLogger', "Writing of file failed!: %s "))%str(e)) except UnicodeDecodeError as e: utils.pop_up_info(ru(QCoreApplication.translate('ExportToFieldLogger', "Error writing %s"))%str(printlist))
def restore_default_settings(self): input_field_browser, input_fields_groups = defs.export_fieldlogger_defaults( ) self.update_settings(input_field_browser, self.stored_settingskey_parameterbrowser) self.update_settings(input_fields_groups, self.stored_settingskey) utils.pop_up_info( ru( QCoreApplication.translate( u'ExportToFieldLogger', u'Input fields and "Create Input Fields" updated to default.\nRestart Export to Fieldlogger dialog to complete,\nor press "Save settings" to save current input fields settings again.' )))
def excecute_sqlfile(self, sqlfilename): with open(sqlfilename, 'r') as f: f.readline() # first line is encoding info.... for line in f: if not line: continue if line.startswith("#"): continue try: self.cur.execute(line) # use tags to find and replace SRID and versioning info except Exception, e: utils.pop_up_info('Failed to create DB! sql failed:\n' + line + '\n\nerror msg:\n' + str(e))
def get_search_radius(self): """ Get the period search radius, default to 10 minutes """ if not self.bestFitSearchRadius.text(): search_radius = '10 minutes' self.bestFitSearchRadius.setText(search_radius) else: search_radius = self.bestFitSearchRadius.text() search_radius_splitted = search_radius.split() if len(search_radius_splitted) != 2: utils.pop_up_info("Must write time resolution also, ex. 10 minutes") return tuple(search_radius_splitted)
def get_tolerance(self): """ Get the period tolerance, default to 10 minutes """ if not self.bestFitTolerance.text(): tol = '10 minutes' self.bestFitTolerance.setText(tol) else: tol = self.bestFitTolerance.text() tol_splitted = tol.split() if len(tol_splitted) != 2: utils.pop_up_info("Must write time resolution also, ex. 10 minutes") return tuple(tol_splitted)
def get_search_radius(self): """ Get the period search radius, default to 10 minutes """ if not self.bestFitSearchRadius.text(): search_radius = '10 minutes' self.bestFitSearchRadius.setText(search_radius) else: search_radius = self.bestFitSearchRadius.text() search_radius_splitted = ru(search_radius).split() if len(search_radius_splitted) != 2: utils.pop_up_info(ru(QCoreApplication.translate('Calibrlogger', "Must write time resolution also, ex. %s"))%'10 minutes') return tuple(search_radius_splitted)
def GetData(self, obsid = '', tablename='', debug = 'n'): # GetData method that returns a table with water quality data # Load all data in obs_points table sql = r"""select * from """ sql += tablename sql += r""" where obsid = '""" sql += obsid sql += r"""'""" if tablename == 'stratigraphy': sql += r""" order by stratid""" if debug == 'y': utils.pop_up_info(sql) ConnectionOK, data = utils.sql_load_fr_db(sql) return ConnectionOK, data
def __init__(self, observations=[]):#observations is supposed to be a list of unicode strings self.observations = observations i = 0 for obs in observations: self.observations[i] = obs.encode('utf-8') #turn into a list of python byte strings i += 1 self.sqlpart2 =(str(self.observations).encode('utf-8').replace('[','(')).replace(']',')')#turn list into string and also encode to utf-8 byte string to enable replace """check whether there are observations without coordinates""" sql = r"""select obsid from obs_points where (east is null or east ='' or north is null or north = '') and obsid in """ + self.sqlpart2 ConnectionOK, result = utils.sql_load_fr_db(sql) if len(result)==0: self.do_it() else: utils.pop_up_info("Coordinates are missing for\n" + result[0][0] + "\nPositions (geometry) will not be updated.")
def choose_method(self): tables_columns = self.tables_columns file_header = self.file_header import_method_name = self.import_method try: layer = utils.find_layer(import_method_name) except utils.UsageError: pass else: if layer is not None: if layer.isEditable(): utils.pop_up_info(ru(QCoreApplication.translate('ImportTableChooser', "Layer %s is currently in editing mode.\nPlease exit this mode before proceeding with this operation."))%str(layer.name()), ru(QCoreApplication.translate('GeneralCsvImportGui', "Error")),) self.import_method = '' import_method_name = None self.specific_table_info.setText(defs.specific_table_info.get(import_method_name, '')) if file_header is None: return None try: self.layout.removeWidget(self.grid.widget) self.grid.widget.close() except: pass self.columns = [] if not import_method_name: return None self.grid = RowEntryGrid() self.layout.addWidget(self.grid.widget) self.grid.layout.addWidget(qgis.PyQt.QtWidgets.QLabel(ru(QCoreApplication.translate('ImportTableChooser', 'Column name'))), 0, 0) self.grid.layout.addWidget(qgis.PyQt.QtWidgets.QLabel(ru(QCoreApplication.translate('ImportTableChooser', 'File column'))), 0, 1) self.grid.layout.addWidget(qgis.PyQt.QtWidgets.QLabel(ru(QCoreApplication.translate('ImportTableChooser', 'Static value'))), 0, 2) self.grid.layout.addWidget(qgis.PyQt.QtWidgets.QLabel(ru(QCoreApplication.translate('ImportTableChooser', 'Factor'))), 0, 3) self.grid.layout.addWidget(qgis.PyQt.QtWidgets.QLabel(ru(QCoreApplication.translate('ImportTableChooser', 'Ignore not null warning'))), 0, 4) for index, tables_columns_info in enumerate(sorted(tables_columns[import_method_name], key=itemgetter(0))): column = ColumnEntry(tables_columns_info, file_header, self.numeric_datatypes) rownr = self.grid.layout.rowCount() for colnr, wid in enumerate(column.column_widgets): self.grid.layout.addWidget(wid, rownr, colnr) self.columns.append(column) self.grid.layout.setColumnStretch(5, 5)
def showSurvey(self): #lyr = self.iface.activeLayer() # THIS IS TSPLOT-method, GETS THE SELECTED LAYER lyr = self.layer ids = lyr.selectedFeaturesIds() if len(ids) == 0: utils.pop_up_info("No selection", "No features are selected") return # initiate the datastore if not yet done self.initStore() PyQt4.QtGui.QApplication.setOverrideCursor(PyQt4.QtCore.Qt.WaitCursor) # Sets the mouse cursor to wait symbol try: # return from store.getData is stored in data only if no object belonging to DataSanityError class is created data = self.store.getData(ids, lyr) # added lyr as an argument!!! except DataSanityError, e: # if an object 'e' belonging to DataSanityError is created, then do following PyQt4.QtGui.QApplication.restoreOverrideCursor() utils.pop_up_info("Data sanity problem, obsid: %s\n%s" % (e.sond_id, e.message)) return
def choose_method(self): tables_columns = self.tables_columns file_header = self.file_header import_method_name = self.import_method layer = utils.find_layer(import_method_name) if layer is not None: if layer.isEditable(): utils.pop_up_info(ru(QCoreApplication.translate('ImportTableChooser', "Layer %s is currently in editing mode.\nPlease exit this mode before proceeding with this operation."))%str(layer.name()), ru(QCoreApplication.translate('GeneralCsvImportGui', "Error")),) self.import_method = '' import_method_name = None self.specific_table_info.setText(defs.specific_table_info.get(import_method_name, '')) if file_header is None: return None #Remove stretch self.layout.takeAt(-1) try: self.layout.removeWidget(self.grid.widget) self.grid.widget.close() except: pass self.columns = [] if not import_method_name: self.layout.insertStretch(-1, 4) return None self.grid = RowEntryGrid() self.layout.addWidget(self.grid.widget) self.grid.layout.addWidget(qgis.PyQt.QtWidgets.QLabel(ru(QCoreApplication.translate('ImportTableChooser', 'Column name'))), 0, 0) self.grid.layout.addWidget(qgis.PyQt.QtWidgets.QLabel(ru(QCoreApplication.translate('ImportTableChooser', 'File column'))), 0, 1) self.grid.layout.addWidget(qgis.PyQt.QtWidgets.QLabel(ru(QCoreApplication.translate('ImportTableChooser', 'Static value'))), 0, 2) self.grid.layout.addWidget(qgis.PyQt.QtWidgets.QLabel(ru(QCoreApplication.translate('ImportTableChooser', 'Factor'))), 0, 3) for index, tables_columns_info in enumerate(sorted(tables_columns[import_method_name], key=itemgetter(0))): column = ColumnEntry(tables_columns_info, file_header, self.numeric_datatypes) rownr = self.grid.layout.rowCount() for colnr, wid in enumerate(column.column_widgets): self.grid.layout.addWidget(wid, rownr, colnr) self.columns.append(column) self.layout.insertStretch(-1, 4)
def GetData( self, obsid='', tablename='', debug='n' ): # GetData method that returns a table with water quality data # Load all data in obs_points table sql = r"""select * from """ sql += tablename sql += r""" where obsid = '""" sql += obsid sql += r"""'""" if tablename == 'stratigraphy': sql += r""" order by stratid""" if debug == 'y': utils.pop_up_info(sql) ConnectionOK, data = db_utils.sql_load_fr_db(sql) return ConnectionOK, data
def showSurvey(self): #lyr = self.iface.activeLayer() # THIS IS TSPLOT-method, GETS THE SELECTED LAYER lyr = self.layer ids = lyr.selectedFeatureIds() if len(ids) == 0: utils.pop_up_info( ru(QCoreApplication.translate(' Stratigraphy', "No selection")), ru( QCoreApplication.translate(' Stratigraphy', "No features are selected"))) return # initiate the datastore if not yet done self.initStore() utils.start_waiting_cursor() # Sets the mouse cursor to wait symbol try: # return from store.getData is stored in data only if no object belonging to DataSanityError class is created self.data = self.store.getData(ids, lyr) # added lyr as an argument!!! except DataSanityError as e: # if an object 'e' belonging to DataSanityError is created, then do following print("DataSanityError %s" % str(e)) utils.stop_waiting_cursor() utils.pop_up_info( ru( QCoreApplication.translate( ' Stratigraphy', "Data sanity problem, obsid: %s\n%s")) % (e.sond_id, e.message)) return except Exception as e: # if an object 'e' belonging to DataSanityError is created, then do following print("exception : %s" % str(e)) utils.stop_waiting_cursor() utils.MessagebarAndLog.critical(bar_msg=ru( QCoreApplication.translate( ' Stratigraphy', "The stratigraphy plot failed, check Midvatten plugin settings and your data!" ))) return utils.stop_waiting_cursor( ) # Restores the mouse cursor to normal symbol # show widget w = SurveyDialog() #w.widget.setData2_nosorting(data) #THIS IS IF DATA IS NOT TO BE SORTED!! w.widget.setData(self.data) #THIS IS ONLY TO SORT DATA!! w.show() self.w = w # save reference so it doesn't get deleted immediately This has to be done both here and also in midvatten instance
def load_obsid_and_init(self): """ Checks the current obsid and reloads all ts. :return: obsid Info: Before, some time series was only reloaded when the obsid was changed, but this caused a problem if the data was changed in the background in for example spatialite gui. Now all time series are reloaded always. It's rather fast anyway. """ obsid = unicode(self.combobox_obsid.currentText()) if not obsid: utils.pop_up_info("ERROR: no obsid is chosen") meas_sql = r"""SELECT date_time, level_masl FROM w_levels WHERE obsid = '""" + obsid + """' ORDER BY date_time""" self.meas_ts = self.sql_into_recarray(meas_sql) head_sql = r"""SELECT date_time as 'date [datetime]', head_cm / 100 FROM w_levels_logger WHERE obsid = '""" + obsid + """' ORDER BY date_time""" self.head_ts = self.sql_into_recarray(head_sql) self.obsid = obsid level_masl_ts_sql = r"""SELECT date_time as 'date [datetime]', level_masl FROM w_levels_logger WHERE obsid = '""" + self.obsid + """' ORDER BY date_time""" self.level_masl_ts = self.sql_into_recarray(level_masl_ts_sql) return obsid
def calc(self, obsids): fr_d_t = self.FromDateTime.dateTime().toPyDateTime() to_d_t = self.ToDateTime.dateTime().toPyDateTime() sql = """SELECT obsid FROM obs_points WHERE obsid IN ({}) AND h_toc IS NULL""".format(', '.join(["'{}'".format(x) for x in obsids])) obsid_with_h_toc_null = db_utils.sql_load_fr_db(sql)[1] if obsid_with_h_toc_null: obsid_with_h_toc_null = [x[0] for x in obsid_with_h_toc_null] if self.checkBox_stop_if_null.isChecked(): any_nulls = [obsid for obsid in obsids if obsid in obsid_with_h_toc_null] if any_nulls: utils.pop_up_info(ru(QCoreApplication.translate('Calclvl', 'Adjustment aborted! There seems to be NULL values in your table obs_points, column h_toc.')), ru(QCoreApplication.translate('Calclvl', 'Error'))) return None else: obsids = [obsid for obsid in obsids if obsid not in obsid_with_h_toc_null] if not obsids: utils.pop_up_info(ru(QCoreApplication.translate('Calclvl', 'Adjustment aborted! All h_tocs were NULL.')), ru(QCoreApplication.translate('Calclvl', 'Error'))) return None formatted_obsids = ', '.join(["'{}'".format(x) for x in obsids]) where_args = {'fr_dt': str(fr_d_t), 'to_dt': str(to_d_t), 'obsids': formatted_obsids} where_sql = """meas IS NOT NULL AND date_time >= '{fr_dt}' AND date_time <= '{to_dt}' AND obsid IN ({obsids})""".format(**where_args) if not self.checkBox_overwrite_prev.isChecked(): where_sql += """ AND level_masl IS NULL """ sql1 = """UPDATE w_levels SET h_toc = (SELECT obs_points.h_toc FROM obs_points WHERE w_levels.obsid = obs_points.obsid) WHERE {}""".format(where_sql) self.updated_h_tocs = self.log_msg(where_sql) db_utils.sql_alter_db(sql1) where_sql += """ AND h_toc IS NOT NULL""" sql2 = """UPDATE w_levels SET level_masl = h_toc - meas WHERE h_toc IS NOT NULL AND {}""".format(where_sql) self.updated_level_masl = self.log_msg(where_sql) db_utils.sql_alter_db(sql2) utils.MessagebarAndLog.info(bar_msg=ru(QCoreApplication.translate('Calclvl', 'Calculation done, see log message panel')), log_msg=ru(QCoreApplication.translate('Calclvl', 'H_toc added and level_masl calculated for\nobsid;min date;max date;calculated number of measurements: \n%s'))%(self.updated_level_masl)) self.close()
def write_printlist_to_file(printlist): filename = PyQt4.QtGui.QFileDialog.getSaveFileName( parent=None, caption=ru( QCoreApplication.translate(u'ExportToFieldLogger', u'Choose a file name')), directory='', filter='csv (*.csv)') if not filename: return if os.path.splitext(filename)[1] != u'.csv': filename += u'.csv' try: with open(filename, 'w') as f: f.write(u'\n'.join(printlist).encode('utf-8')) except IOError, e: utils.pop_up_info( ru( QCoreApplication.translate( u'ExportToFieldLogger', u"Writing of file failed!: %s ")) % str(e))
def calc_best_fit(self): """ Calculates the self.LoggerPos from self.meas_ts and self.head_ts First matches measurements from self.meas_ts to logger values from self.head_ts. This is done by making a mean of all logger values inside self.meas_ts date - search_radius and self.meas_ts date + search_radius. (this could probably be change to get only the closest logger value inside the search_radius instead) (search_radius is gotten from self.get_search_radius()) Then calculates the mean of all matches and set to self.LoggerPos. """ obsid = self.load_obsid_and_init() self.reset_plot_selects_and_calib_help() search_radius = self.get_search_radius() if self.loggerpos_masl_or_offset_state == 1:# UPDATE TO RELEVANT TEXT logger_ts = self.head_ts text_field = self.LoggerPos calib_func = self.set_logger_pos really_calibrate_question = utils.askuser("YesNo", """This will calibrate all values inside the chosen period\nusing the mean difference between head_cm and w_levels measurements.\n\nSearch radius for matching logger and measurement nodes set to '""" + ' '.join(search_radius) + """'\n\nContinue?""") else:# UPDATE TO RELEVANT TEXT logger_ts = self.level_masl_ts text_field = self.Add2Levelmasl calib_func = self.add_to_level_masl really_calibrate_question = utils.askuser("YesNo", """This will calibrate all values inside the chosen period\nusing the mean difference between level_masl and w_levels measurements.\n\nSearch radius for matching logger and measurement nodes set to '""" + ' '.join(search_radius) + """'\n\nContinue?""") if really_calibrate_question.result == 0: # if the user wants to abort return PyQt4.QtGui.QApplication.setOverrideCursor(PyQt4.QtCore.Qt.WaitCursor) coupled_vals = self.match_ts_values(self.meas_ts, logger_ts, search_radius) if not coupled_vals: utils.pop_up_info("There was no matched measurements or logger values inside the chosen period.\n Try to increase the search radius!") else: text_field.setText(str(utils.calc_mean_diff(coupled_vals))) calib_func() PyQt4.QtGui.QApplication.restoreOverrideCursor()
def calc_best_fit(self): """ Calculates the self.LoggerPos from self.meas_ts and self.head_ts First matches measurements from self.meas_ts to logger values from self.head_ts. This is done by making a mean of all logger values inside self.meas_ts date - search_radius and self.meas_ts date + search_radius. (this could probably be change to get only the closest logger value inside the search_radius instead) (search_radius is gotten from self.get_search_radius()) Then calculates the mean of all matches and set to self.LoggerPos. """ obsid = self.load_obsid_and_init() utils.start_waiting_cursor() self.reset_plot_selects_and_calib_help() search_radius = self.get_search_radius() if self.loggerpos_masl_or_offset_state == 1:# UPDATE TO RELEVANT TEXT logger_ts = self.head_ts text_field = self.LoggerPos calib_func = self.set_logger_pos else:# UPDATE TO RELEVANT TEXT logger_ts = self.level_masl_ts text_field = self.Add2Levelmasl calib_func = self.add_to_level_masl coupled_vals = self.match_ts_values(self.meas_ts, logger_ts, search_radius) if not coupled_vals: utils.pop_up_info(ru(QCoreApplication.translate('Calibrlogger', "There was no match found between measurements and logger values inside the chosen period.\n Try to increase the search radius!"))) else: calculated_diff = str(utils.calc_mean_diff(coupled_vals)) if not calculated_diff or calculated_diff.lower() == 'nan': utils.pop_up_info(ru(QCoreApplication.translate('Calibrlogger', "There was no matched measurements or logger values inside the chosen period.\n Try to increase the search radius!"))) utils.MessagebarAndLog.info(log_msg=ru(QCoreApplication.translate('Calibrlogger', "Calculated water level from logger: utils.calc_mean_diff(coupled_vals) didn't return a useable value."))) else: text_field.setText(calculated_diff) calib_func(obsid) utils.stop_waiting_cursor()
def calibrate(self): self.calib_help.setText("Calibrating") PyQt4.QtGui.QApplication.setOverrideCursor(PyQt4.QtCore.Qt.WaitCursor) obsid = self.load_obsid_and_init() if not obsid=='': sanity1sql = """select count(obsid) from w_levels_logger where obsid = '""" + obsid[0] + """'""" sanity2sql = """select count(obsid) from w_levels_logger where head_cm not null and head_cm !='' and obsid = '""" + obsid[0] + """'""" if utils.sql_load_fr_db(sanity1sql)[1] == utils.sql_load_fr_db(sanity2sql)[1]: # This must only be done if head_cm exists for all data fr_d_t = self.FromDateTime.dateTime().toPyDateTime() to_d_t = self.ToDateTime.dateTime().toPyDateTime() if self.loggerpos_masl_or_offset_state == 1: self.update_level_masl_from_head(obsid, fr_d_t, to_d_t, self.LoggerPos.text()) else: self.update_level_masl_from_level_masl(obsid, fr_d_t, to_d_t, self.LoggerPos.text()) self.getlastcalibration() else: utils.pop_up_info("Calibration aborted!!\nThere must not be empty cells or\nnull values in the 'head_cm' column!") else: self.INFO.setText("Select the observation point with logger data to be calibrated.") self.calib_help.setText("") PyQt4.QtGui.QApplication.restoreOverrideCursor()
def __init__(self, obsids=[''], settingsdict={}): reportfolder = os.path.join(QDir.tempPath(), 'midvatten_reports') if not os.path.exists(reportfolder): os.makedirs(reportfolder) reportpath = os.path.join(reportfolder, "drill_report.html") logopath = os.path.join(os.sep, os.path.dirname(__file__), "..", "templates", "midvatten_logga.png") imgpath = os.path.join(os.sep, os.path.dirname(__file__), "..", "templates") if len(obsids) == 0: utils.pop_up_info( ru( QCoreApplication.translate( 'Drillreport', "Must select one or more obsids!"))) return None elif len(obsids) == 1: merged_question = False else: #Due to problems regarding speed when opening many tabs, only the merge mode is used. #merged_question = utils.Askuser(question='YesNo', msg="Do you want to open all drill reports merged on the same tab?\n" # "Else they will be opened separately.\n\n(If answering no, creating drill reports for many obsids take 0.2 seconds per obsid.\nIt might fail if the computer is to slow.\nIf it fails, try to select only one obsid at the time)").result merged_question = True obsids = sorted(set(obsids)) if merged_question: f, rpt = self.open_file(', '.join(obsids), reportpath) for obsid in obsids: self.write_obsid(obsid, rpt, imgpath, logopath, f) self.close_file(f, reportpath) else: #opened = False for obsid in obsids: f, rpt = self.open_file(obsid, reportpath) self.write_obsid(obsid, rpt, imgpath, logopath, f) url_status = self.close_file(f, reportpath)
def _getDataStep1(self, featureIds, vlayer): """ STEP 1: get data from selected layer""" # _CHANGE_ Completely revised to TSPLot method provider = vlayer.dataProvider() #_CHANGE_ THIS IS TSPLOT-method, we do not use the db loadeds by ARPAT _init_ surveystore obsid_ColNo = provider.fieldNameIndex('obsid') # _CHANGE_ THIS IS TSPLOT-method To find the column named 'obsid' if obsid_ColNo == -1: obsid_ColNo = provider.fieldNameIndex('OBSID') # backwards compatibility h_gs_ColNo = provider.fieldNameIndex('h_gs') # _CHANGE_ THIS IS TSPLOT-method To find the column named 'h_gs' h_toc_ColNo = provider.fieldNameIndex('h_toc') # _CHANGE_ THIS IS TSPLOT-method To find the column named 'h_toc' if h_gs_ColNo == -1 and h_toc_ColNo == -1: h_gs_ColNo = provider.fieldNameIndex('SURF_LVL') # backwards compatibility surveys = {} strata = {} if(vlayer): nF = vlayer.selectedFeatureCount() if (nF > 0): # Load all selected observation points ob = vlayer.selectedFeatures() obsid_list=[None]*nF # List for obsid toplvl_list=[None]*nF # List for top_lvl coord_list=[None]*nF # List for coordinates i=0 for k in ob: # Loop through all selected objects, a plot is added for each one of the observation points (i.e. selected objects) attributes = ob[i] obsid_list[i] = unicode(str(attributes[obsid_ColNo])) # Copy value in column obsid in the attribute list if attributes[h_gs_ColNo] and utils.isfloat(attributes[h_gs_ColNo]) and attributes[h_gs_ColNo]>-999: # Only get h_gs if it exists toplvl_list[i] = attributes[h_gs_ColNo] # Copy value in column h_gs in the attribute list elif attributes[h_toc_ColNo] and utils.isfloat(attributes[h_toc_ColNo]) and attributes[h_toc_ColNo] >-999: # else get h_toc if that exists toplvl_list[i] = attributes[h_toc_ColNo] # Copy value in column h_gs in the attribute list else: # otherwise, if neither h_gs nor h_toc exists - plot as if h_gs is zero toplvl_list[i] = 0 coord_list[i]= k.geometry().asPoint() # add to array surveys[obsid_list[i]] = SurveyInfo(obsid_list[i], toplvl_list[i], coord_list[i]) i = i+1 else: utils.pop_up_info("getDataStep1 failed ") # _CHANGE_ for debugging return surveys
def __init__(self, parent, midv_settings): self.iface = parent self.ms = midv_settings PyQt4.QtGui.QDialog.__init__(self, parent) self.setAttribute(PyQt4.QtCore.Qt.WA_DeleteOnClose) self.setupUi(self) # Required by Qt4 to initialize the UI self.setWindowTitle( ru( QCoreApplication.translate(u'ExportToFieldLogger', u"Export to Fieldlogger dialog")) ) # Set the title for the dialog self.widget.setMinimumWidth(180) tables_columns = db_utils.tables_columns() self.parameter_groups = None self.stored_settingskey = 'fieldlogger_export_pgroups' self.stored_settingskey_parameterbrowser = 'fieldlogger_export_pbrowser' for settingskey in [ self.stored_settingskey, self.stored_settingskey_parameterbrowser ]: if settingskey not in self.ms.settingsdict: utils.MessagebarAndLog.warning(bar_msg=ru( QCoreApplication.translate( u'ExportToFieldLogger', u'%s did not exist in settingsdict')) % settingskey) self.parameter_groups = self.create_parameter_groups_using_stored_settings( utils.get_stored_settings(self.ms, self.stored_settingskey), self.connect) if self.parameter_groups is None or not self.parameter_groups: self.parameter_groups = [ParameterGroup(self.connect)] self.main_vertical_layout.addWidget( PyQt4.QtGui.QLabel( ru( QCoreApplication.translate( u'ExportToFieldLogger', u'Fieldlogger input fields and locations:')))) self.main_vertical_layout.addWidget(get_line()) self.splitter = SplitterWithHandel(PyQt4.QtCore.Qt.Vertical) self.main_vertical_layout.addWidget(self.splitter) #This is about adding a messagebar to the fieldlogger window. But for some reason qgis crashes or closes #when the timer ends for the regular messagebar #self.lbl = MessageBar(self.splitter) #qgis.utils.iface.optional_bar = self.lbl self.widgets_layouts = self.init_splitters_layouts(self.splitter) if self.parameter_groups: for export_object in self.parameter_groups: self.add_parameter_group_to_gui(self.widgets_layouts, export_object) #Buttons #ParameterUnitBrowser self.parameter_browser = ParameterBrowser(tables_columns, self.connect, self.widget) self.parameter_browser_button = PyQt4.QtGui.QPushButton( ru( QCoreApplication.translate(u'ExportToFieldLogger', u'Create Input Fields'))) self.gridLayout_buttons.addWidget(self.parameter_browser_button, 0, 0) self.connect(self.parameter_browser_button, PyQt4.QtCore.SIGNAL("clicked()"), lambda: self.parameter_browser.show()) self.update_parameter_browser_using_stored_settings( utils.get_stored_settings( self.ms, self.stored_settingskey_parameterbrowser), self.parameter_browser) self.add_parameter_group = PyQt4.QtGui.QPushButton( ru( QCoreApplication.translate(u'ExportToFieldLogger', u'More Fields and Locations'))) self.add_parameter_group.setToolTip( ru( QCoreApplication.translate( u'ExportToFieldLogger', u'Creates an additional empty input field group.'))) self.gridLayout_buttons.addWidget(self.add_parameter_group, 1, 0) #Lambda and map is used to run several functions for every button click self.connect( self.add_parameter_group, PyQt4.QtCore.SIGNAL("clicked()"), lambda: map(lambda x: x(), [ lambda: self.parameter_groups.append( ParameterGroup(self.connect)), lambda: self.add_parameter_group_to_gui( self.widgets_layouts, self.parameter_groups[-1]) ])) self.gridLayout_buttons.addWidget(get_line(), 2, 0) #Buttons self.save_settings_button = PyQt4.QtGui.QPushButton( ru( QCoreApplication.translate(u'ExportToFieldLogger', u'Save settings'))) self.save_settings_button.setToolTip( ru( QCoreApplication.translate( u'ExportToFieldLogger', u'Saves the current input fields settings.'))) self.gridLayout_buttons.addWidget(self.save_settings_button, 3, 0) self.connect( self.save_settings_button, PyQt4.QtCore.SIGNAL("clicked()"), lambda: map(lambda x: x(), [ lambda: utils.save_stored_settings( self.ms, self.update_stored_settings( self.parameter_groups), self.stored_settingskey), lambda: utils.save_stored_settings( self.ms, self.update_stored_settings([self.parameter_browser]), self .stored_settingskey_parameterbrowser) ])) self.clear_settings_button = PyQt4.QtGui.QPushButton( ru( QCoreApplication.translate(u'ExportToFieldLogger', u'Clear settings'))) self.clear_settings_button.setToolTip( ru( QCoreApplication.translate( u'ExportToFieldLogger', u'Clear all input fields settings.'))) self.gridLayout_buttons.addWidget(self.clear_settings_button, 4, 0) self.connect( self.clear_settings_button, PyQt4.QtCore.SIGNAL("clicked()"), lambda: map(lambda x: x(), [ lambda: utils.save_stored_settings(self.ms, [ ], self.stored_settingskey), lambda: utils.pop_up_info( ru( QCoreApplication.translate( u'ExportToFieldLogger', u'Settings cleared. Restart Export to Fieldlogger dialog to complete,\nor press "Save settings" to save current input fields settings again.' ))) ])) self.settings_strings_button = PyQt4.QtGui.QPushButton( ru( QCoreApplication.translate(u'ExportToFieldLogger', u'Settings strings'))) self.settings_strings_button.setToolTip( ru( QCoreApplication.translate( u'ExportToFieldLogger', u'Access the settings strings ("Create input fields" and input fields) to copy and paste all settings between different qgis projects.\n Usage: Select string and copy to a text editor or directly into Settings strings dialog of another qgis project.' ))) self.gridLayout_buttons.addWidget(self.settings_strings_button, 5, 0) self.connect(self.settings_strings_button, PyQt4.QtCore.SIGNAL("clicked()"), self.settings_strings_dialogs) self.default_settings_button = PyQt4.QtGui.QPushButton( ru( QCoreApplication.translate(u'ExportToFieldLogger', u'Default settings'))) self.default_settings_button.setToolTip( ru( QCoreApplication.translate( u'ExportToFieldLogger', u'Updates "Create input fields" and input fields to default settings.' ))) self.gridLayout_buttons.addWidget(self.default_settings_button, 6, 0) self.connect(self.default_settings_button, PyQt4.QtCore.SIGNAL("clicked()"), self.restore_default_settings) self.gridLayout_buttons.addWidget(get_line(), 7, 0) self.preview_button = PyQt4.QtGui.QPushButton( ru(QCoreApplication.translate(u'ExportToFieldLogger', u'Preview'))) self.preview_button.setToolTip( ru( QCoreApplication.translate( u'ExportToFieldLogger', u'View a preview of the Fieldlogger location file as pop-up info.' ))) self.gridLayout_buttons.addWidget(self.preview_button, 8, 0) # Lambda and map is used to run several functions for every button click self.connect(self.preview_button, PyQt4.QtCore.SIGNAL("clicked()"), self.preview) self.export_button = PyQt4.QtGui.QPushButton( ru(QCoreApplication.translate(u'ExportToFieldLogger', u'Export'))) self.export_button.setToolTip( ru( QCoreApplication.translate( u'ExportToFieldLogger', u'Exports the current combination of locations and input fields to a Fieldlogger location file.' ))) self.gridLayout_buttons.addWidget(self.export_button, 9, 0) # Lambda and map is used to run several functions for every button click self.connect(self.export_button, PyQt4.QtCore.SIGNAL("clicked()"), self.export) self.gridLayout_buttons.setRowStretch(10, 1) self.show()
def _getDataStep1(self, featureIds, vlayer): """ STEP 1: get data from selected layer""" # _CHANGE_ Completely revised to TSPLot method provider = vlayer.dataProvider( ) #_CHANGE_ THIS IS TSPLOT-method, we do not use the db loadeds by ARPAT _init_ surveystore obsid_ColNo = provider.fieldNameIndex( 'obsid' ) # _CHANGE_ THIS IS TSPLOT-method To find the column named 'obsid' if obsid_ColNo == -1: obsid_ColNo = provider.fieldNameIndex( 'OBSID') # backwards compatibility h_gs_ColNo = provider.fieldNameIndex( 'h_gs' ) # _CHANGE_ THIS IS TSPLOT-method To find the column named 'h_gs' h_toc_ColNo = provider.fieldNameIndex( 'h_toc' ) # _CHANGE_ THIS IS TSPLOT-method To find the column named 'h_toc' if h_gs_ColNo == -1 and h_toc_ColNo == -1: h_gs_ColNo = provider.fieldNameIndex( 'SURF_LVL') # backwards compatibility surveys = {} strata = {} if (vlayer): nF = vlayer.selectedFeatureCount() if (nF > 0): # Load all selected observation points ob = vlayer.selectedFeatures() obsid_list = [None] * nF # List for obsid toplvl_list = [None] * nF # List for top_lvl coord_list = [None] * nF # List for coordinates for i, k in enumerate( ob ): # Loop through all selected objects, a plot is added for each one of the observation points (i.e. selected objects) attributes = ob[i] obsid = ru(attributes[obsid_ColNo]) obsid_list[ i] = obsid # Copy value in column obsid in the attribute list h_gs = ru(attributes[h_gs_ColNo]) level_val = None error_msg = False if h_gs: try: level_val = float(h_gs) except ValueError: error_msg = ru( QCoreApplication.translate( u'Stratigraphy', u'Converting to float failed.')) except Exception as e: error_msg = e if level_val is None: h_toc = ru(attributes[h_toc_ColNo]) try: level_val = float(h_toc) except: using = u'-1' level_val = -1 else: using = u'h_toc' utils.MessagebarAndLog.warning(bar_msg=ru( QCoreApplication.translate( u'Stratigraphy', u"Obsid %s: using h_gs '%s' failed, using '%s' instead." )) % (obsid, h_gs, using), log_msg=ru( QCoreApplication. translate( u'Stratigraphy', u'%s')) % error_msg, duration=90) if self.warning_popup: utils.pop_up_info( ru( QCoreApplication.translate( u'Stratigraphy', u'Warning, h_gs is missing. See messagebar.' ))) self.warning_popup = False toplvl_list[i] = level_val coord_list[i] = k.geometry().asPoint() # add to array surveys[obsid_list[i]] = SurveyInfo( obsid_list[i], toplvl_list[i], coord_list[i]) else: utils.pop_up_info( ru( QCoreApplication.translate( u'Stratigraphy', u"getDataStep1 failed"))) # _CHANGE_ for debugging return surveys
def create_new_db(self, verno, user_select_CRS='y', EPSG_code='4326'):#CreateNewDB(self, verno): """Open a new DataBase (create an empty one if file doesn't exists) and set as default DB""" if user_select_CRS=='y': EPSGID=str(self.ask_for_CRS()[0]) else: EPSGID=EPSG_code PyQt4.QtGui.QApplication.setOverrideCursor(PyQt4.QtCore.Qt.WaitCursor) if EPSGID=='0' or not EPSGID: utils.pop_up_info("Cancelling...") else: # If a CRS is selectd, go on and create the database #path and name of new db self.dbpath = PyQt4.QtGui.QFileDialog.getSaveFileName(None, "New DB","midv_obsdb.sqlite","Spatialite (*.sqlite)") if not self.dbpath: PyQt4.QtGui.QApplication.restoreOverrideCursor() return '' #create Spatialite database else: try: # creating/connecting the test_db self.conn = sqlite.connect(self.dbpath) # creating a Cursor self.cur = self.conn.cursor() self.cur.execute("PRAGMA foreign_keys = ON") #Foreign key constraints are disabled by default (for backwards compatibility), so must be enabled separately for each database connection separately. except: utils.pop_up_info("Impossible to connect to selected DataBase") return '' PyQt4.QtGui.QApplication.restoreOverrideCursor() #First, find spatialite version versionstext = self.cur.execute('select spatialite_version()').fetchall() #print versionstext#debug # load sql syntax to initialise spatial metadata, automatically create GEOMETRY_COLUMNS and SPATIAL_REF_SYS # then the syntax defines a Midvatten project db according to the loaded .sql-file if int(versionstext[0][0][0]) > 3: # which file to use depends on spatialite version installed SQLFile = os.path.join(os.sep,os.path.dirname(__file__),"..","definitions","create_db_splite4.sql") else: SQLFile = os.path.join(os.sep,os.path.dirname(__file__),"..","definitions","create_db.sql") qgisverno = QGis.QGIS_VERSION#We want to store info about which qgis-version that created the db f = open(SQLFile, 'r') linecounter = 1 for line in f: if linecounter > 1: # first line is encoding info.... self.rs = self.cur.execute(line.replace('CHANGETORELEVANTEPSGID',str(EPSGID)).replace('CHANGETOPLUGINVERSION',str(verno)).replace('CHANGETOQGISVERSION',str(qgisverno)).replace('CHANGETOSPLITEVERSION',str(versionstext[0][0]))) # use tags to find and replace SRID and versioning info linecounter += 1 self.cur.execute("PRAGMA foreign_keys = OFF") #FINISHED WORKING WITH THE DATABASE, CLOSE CONNECTIONS self.rs.close() self.conn.close() #create SpatiaLite Connection in QGIS QSettings settings=PyQt4.QtCore.QSettings() settings.beginGroup('/SpatiaLite/connections') #settings.setValue(u'%s/sqlitepath'%os.path.basename(str(self.dbpath)),'%s'%self.dbpath) settings.setValue(u'%s/sqlitepath'%os.path.basename(self.dbpath),'%s'%self.dbpath) settings.endGroup() """ #The intention is to keep layer styles in the database by using the class AddLayerStyles but due to limitations in how layer styles are stored in the database, I will put this class on hold for a while. #Finally add the layer styles info into the data base AddLayerStyles(self.dbpath) """ PyQt4.QtGui.QApplication.restoreOverrideCursor()
def showtheplot( self, layer ): # PlotTS method that, at the moment, performs all the real work provider = layer.dataProvider() #Something with OGR kolumnindex = provider.fieldNameIndex( 'obsid') # To find the column named 'obsid' if kolumnindex == -1: kolumnindex = provider.fieldNameIndex( 'OBSID') # backwards compatibility if (layer): nF = layer.selectedFeatureCount() if (nF > 0): # Load all selected observation points ob = layer.getSelectedFeatures() # Create a plot window with one single subplot fig = plt.figure( ) # causes conflict with plugins "statist" and "chartmaker" ax = fig.add_subplot(111) p = [None] * nF # List for plot objects plabel = [None] * nF # List for label strings for i, k in enumerate( ob ): # Loop through all selected objects, a plot is added for each one of the observation points (i.e. selected objects) attributes = k.attributes() obsid = ru(attributes[kolumnindex]) # Load all observations (full time series) for the object [i] (i.e. selected observation point no i) sql = r"""SELECT date_time, """ sql += str(self.settingsdict['tscolumn']) #MacOSX fix1 sql += """ FROM """ sql += str(self.settingsdict['tstable']) #MacOSX fix1 sql += r""" WHERE obsid = '""" sql += obsid sql += """' ORDER BY date_time """ connection_ok, recs = db_utils.sql_load_fr_db(sql) """Transform data to a numpy.recarray""" My_format = [ ('date_time', datetime.datetime), ('values', float) ] #Define format with help from function datetime table = np.array(recs, dtype=My_format) #NDARRAY table2 = table.view( np.recarray ) # RECARRAY Makes the two columns inte callable objects, i.e. write table2.values """ Get help from function datestr2num to get date and time into float""" myTimestring = [] #LIST for j, row in enumerate(table2): myTimestring.append(table2.date_time[j]) numtime = datestr2num( myTimestring ) #conv list of strings to numpy.ndarray of floats if self.settingsdict[ 'tsdotmarkers'] == 2: # If the checkbox is checked - markers will be plotted #MacOSX fix1 if self.settingsdict[ 'tsstepplot'] == 2: # If the checkbox is checked - draw a step plot #MacOSX fix1 p[i], = ax.plot_date(numtime, table2.values, marker='o', linestyle='-', drawstyle='steps-pre', label=obsid) # PLOT!! else: p[i], = ax.plot_date(numtime, table2.values, 'o-', label=obsid) else: # NO markers wil be plotted, , just a line if self.settingsdict[ 'tsstepplot'] == 2: # If the checkbox is checked - draw a step plot #MacOSX fix1 p[i], = ax.plot_date(numtime, table2.values, marker='None', linestyle='-', drawstyle='steps-pre', label=obsid) # PLOT!! else: p[i], = ax.plot_date(numtime, table2.values, '-', label=obsid) plabel[i] = obsid # Label for the plot """ Finish plot """ ax.grid(True) ax.yaxis.set_major_formatter( tick.ScalarFormatter(useOffset=False, useMathText=False)) fig.autofmt_xdate() ax.set_ylabel(self.settingsdict['tscolumn']) #MacOSX fix1 ax.set_title(self.settingsdict['tstable']) #MacOSX fix1 leg = fig.legend(p, plabel, loc=0) #leg = fig.legend(p, plabel, 'right') try: leg.set_draggable(state=True) except AttributeError: # For older version of matplotlib leg.draggable(state=True) frame = leg.get_frame( ) # the matplotlib.patches.Rectangle instance surrounding the legend frame.set_facecolor( '0.80') # set the frame face color to light gray frame.set_fill(False) # set the frame face color transparent for t in leg.get_texts(): t.set_fontsize(10) # the legend text fontsize for label in ax.xaxis.get_ticklabels(): label.set_fontsize(10) for label in ax.yaxis.get_ticklabels(): label.set_fontsize(10) #plt.ion()#force interactivity to prevent the plot window from blocking the qgis app fig.show() #plt.close(fig) #plt.draw() else: utils.pop_up_info( ru( QCoreApplication.translate( 'TimeSeriesPlot', "Please select at least one point with time series data" ))) else: utils.pop_up_info( ru( QCoreApplication.translate( 'TimeSeriesPlot', "Please select a layer with time series observation points" )))
def __init__(self, obsids, settingsdict, general_metadata, geo_metadata, strat_columns, header_in_table, skip_empty, include_comments, general_metadata_header, geo_metadata_header, strat_columns_header, comment_header, empty_row_between_obsids, topleft_topright_colwidths, general_colwidth, geo_colwidth, decimal_separator): reportfolder = os.path.join(QDir.tempPath(), 'midvatten_reports') if not os.path.exists(reportfolder): os.makedirs(reportfolder) reportpath = os.path.join(reportfolder, "drill_report.html") logopath = os.path.join(os.sep, os.path.dirname(__file__), "..", "templates", "midvatten_logga.png") imgpath = os.path.join(os.sep, os.path.dirname(__file__), "..", "templates") if len(obsids) == 0: utils.pop_up_info( ru( QCoreApplication.translate( 'Drillreport', "Must select one or more obsids!"))) return None obsids = sorted(set(obsids)) obs_points_translations = { 'obsid': ru(QCoreApplication.translate('Drillreport2', 'obsid')), 'name': ru(QCoreApplication.translate('Drillreport2', 'name')), 'place': ru(QCoreApplication.translate('Drillreport2', 'place')), 'type': ru(QCoreApplication.translate('Drillreport2', 'type')), 'length': ru(QCoreApplication.translate('Drillreport2', 'length')), 'drillstop': ru(QCoreApplication.translate('Drillreport2', 'drillstop')), 'diam': ru(QCoreApplication.translate('Drillreport2', 'diam')), 'material': ru(QCoreApplication.translate('Drillreport2', 'material')), 'screen': ru(QCoreApplication.translate('Drillreport2', 'screen')), 'capacity': ru(QCoreApplication.translate('Drillreport2', 'capacity')), 'drilldate': ru(QCoreApplication.translate('Drillreport2', 'drilldate')), 'wmeas_yn': ru(QCoreApplication.translate('Drillreport2', 'wmeas_yn')), 'wlogg_yn': ru(QCoreApplication.translate('Drillreport2', 'wlogg_yn')), 'east': ru(QCoreApplication.translate('Drillreport2', 'east')), 'north': ru(QCoreApplication.translate('Drillreport2', 'north')), 'ne_accur': ru(QCoreApplication.translate('Drillreport2', 'ne_accur')), 'ne_source': ru(QCoreApplication.translate('Drillreport2', 'ne_source')), 'h_toc': ru(QCoreApplication.translate('Drillreport2', 'h_toc')), 'h_tocags': ru(QCoreApplication.translate('Drillreport2', 'h_tocags')), 'h_gs': ru(QCoreApplication.translate('Drillreport2', 'h_gs')), 'h_accur': ru(QCoreApplication.translate('Drillreport2', 'h_accur')), 'h_syst': ru(QCoreApplication.translate('Drillreport2', 'h_syst')), 'h_source': ru(QCoreApplication.translate('Drillreport2', 'h_source')), 'source': ru(QCoreApplication.translate('Drillreport2', 'source')), 'com_onerow': ru(QCoreApplication.translate('Drillreport2', 'com_onerow')), 'com_html': ru(QCoreApplication.translate('Drillreport2', 'com_html')) } """ thelist = [ "obsid", "stratid", "depthtop", "depthbot", "geology", "geoshort", "capacity", "development", "comment"] >>> y = '\n'.join(["'%s'"%x + ': ' + "ru(QCoreApplication.translate('Drillreport2', '%s')),"%x for x in thelist]) >>> print(y) """ dbconnection = db_utils.DbConnectionManager() obs_points_cols = [ "obsid", "name", "place", "type", "length", "drillstop", "diam", "material", "screen", "capacity", "drilldate", "wmeas_yn", "wlogg_yn", "east", "north", "ne_accur", "ne_source", "h_toc", "h_tocags", "h_gs", "h_accur", "h_syst", "h_source", "source", "com_onerow", "com_html" ] all_obs_points_data = ru(db_utils.get_sql_result_as_dict( 'SELECT %s FROM obs_points WHERE obsid IN (%s) ORDER BY obsid' % (', '.join(obs_points_cols), ', '.join( ["'{}'".format(x) for x in obsids])), dbconnection=dbconnection)[1], keep_containers=True) if strat_columns: strat_sql_columns_list = [x.split(';')[0] for x in strat_columns] if 'depth' in strat_sql_columns_list: strat_sql_columns_list.extend(['depthtop', 'depthbot']) strat_sql_columns_list.remove('depth') strat_sql_columns_list = [ x for x in strat_sql_columns_list if x not in ('obsid') ] all_stratigrapy_data = ru(db_utils.get_sql_result_as_dict( 'SELECT obsid, %s FROM stratigraphy WHERE obsid IN (%s) ORDER BY obsid, stratid' % (', '.join(strat_sql_columns_list), ', '.join( ["'{}'".format(x) for x in obsids])), dbconnection=dbconnection)[1], keep_containers=True) else: all_stratigrapy_data = {} strat_sql_columns_list = [] crs = ru( db_utils.sql_load_fr_db( """SELECT srid FROM geometry_columns where f_table_name = 'obs_points'""", dbconnection=dbconnection)[1][0][0]) crsname = ru(db_utils.get_srid_name(crs, dbconnection=dbconnection)) dbconnection.closedb() f, rpt = self.open_file(', '.join(obsids), reportpath) rpt += r"""<html>""" for obsid in obsids: obs_points_data = all_obs_points_data[obsid][0] general_data_no_rounding = [ x.split(';')[0] for x in general_metadata ] general_rounding = [ x.split(';')[1] if len(x.split(';')) == 2 else None for x in general_metadata ] general_data = [ (obs_points_translations.get(header, header), obs_points_data[obs_points_cols.index(header) - 1]) for header in general_data_no_rounding ] if geo_metadata: geo_metadata_no_rounding = [ x.split(';')[0] for x in geo_metadata ] geo_rounding = [ x.split(';')[1] if len(x.split(';')) == 2 else None for x in geo_metadata ] geo_data = [ (obs_points_translations.get(header, header), obs_points_data[obs_points_cols.index(header) - 1]) for header in geo_metadata_no_rounding ] if 'east' in geo_metadata_no_rounding or 'north' in geo_metadata_no_rounding: geo_data.append( (ru( QCoreApplication.translate('Drillreport2', 'XY Reference system')), '%s' % ('%s, ' % crsname if crsname else '') + 'EPSG:' + crs)) else: geo_data = [] geo_rounding = [] strat_data = all_stratigrapy_data.get(obsid, None) if include_comments: comment_data = [ obs_points_data[obs_points_cols.index(header) - 1] for header in ('com_onerow', 'com_html') if all([ obs_points_data[obs_points_cols.index(header) - 1] is not None, obs_points_data[ obs_points_cols.index(header) - 1].replace('NULL', ''), obs_points_data[ obs_points_cols.index(header) - 1].strip(), 'text-indent:0px;"><br /></p>' not in obs_points_data[obs_points_cols.index(header) - 1], 'text-indent:0px;"></p>' not in obs_points_data[obs_points_cols.index(header) - 1], 'text-indent:0px;">NULL</p>' not in obs_points_data[obs_points_cols.index(header) - 1].strip() ]) ] else: comment_data = [] rpt += self.write_obsid( obsid, general_data, geo_data, strat_data, comment_data, strat_columns, header_in_table=header_in_table, skip_empty=skip_empty, general_metadata_header=general_metadata_header, geo_metadata_header=geo_metadata_header, strat_columns_header=strat_columns_header, comment_header=comment_header, general_rounding=general_rounding, geo_rounding=geo_rounding, strat_sql_columns_list=strat_sql_columns_list, topleft_topright_colwidths=topleft_topright_colwidths, general_colwidth=general_colwidth, geo_colwidth=geo_colwidth, decimal_separator=decimal_separator) rpt += r"""<p> </p>""" if empty_row_between_obsids: rpt += r"""<p>empty_row_between_obsids</p>""" rpt += r"""</html>""" f.write(rpt) self.close_file(f, reportpath)
def create_new_spatialite_db(self, verno, user_select_CRS='y', EPSG_code='4326', delete_srids=True): #CreateNewDB(self, verno): """Open a new DataBase (create an empty one if file doesn't exists) and set as default DB""" utils.stop_waiting_cursor() set_locale = self.ask_for_locale() utils.start_waiting_cursor() if user_select_CRS=='y': utils.stop_waiting_cursor() EPSGID=str(self.ask_for_CRS(set_locale)[0]) utils.start_waiting_cursor() else: EPSGID=EPSG_code if EPSGID=='0' or not EPSGID: raise utils.UserInterruptError() # If a CRS is selectd, go on and create the database #path and name of new db utils.stop_waiting_cursor() dbpath = ru(utils.get_save_file_name_no_extension(parent=None, caption="New DB", directory="midv_obsdb.sqlite", filter="Spatialite (*.sqlite)")) utils.start_waiting_cursor() if os.path.exists(dbpath): utils.MessagebarAndLog.critical( bar_msg=ru(QCoreApplication.translate('NewDb', 'A database with the chosen name already existed. Cancelling...'))) utils.stop_waiting_cursor() return '' #Create the database conn = db_utils.connect_with_spatialite_connect(dbpath) conn.close() self.db_settings = ru(utils.anything_to_string_representation({'spatialite': {'dbpath': dbpath}})) #dbconnection = db_utils.DbConnectionManager(self.db_settings) try: # creating/connecting the test_db dbconnection = db_utils.DbConnectionManager(self.db_settings) dbconnection.execute("PRAGMA foreign_keys = ON") #Foreign key constraints are disabled by default (for backwards compatibility), so must be enabled separately for each database dbconnection separately. except Exception as e: utils.MessagebarAndLog.critical(bar_msg=ru(QCoreApplication.translate('NewDb', "Impossible to connect to selected DataBase, see log message panel")), log_msg=ru(QCoreApplication.translate('NewDb', 'Msg:\n') + str(e))) #utils.pop_up_info("Impossible to connect to selected DataBase") utils.stop_waiting_cursor() return '' d =dbconnection.connector #First, find spatialite version versionstext = dbconnection.execute_and_fetchall('select spatialite_version()')[0][0] # load sql syntax to initialise spatial metadata, automatically create GEOMETRY_COLUMNS and SPATIAL_REF_SYS # then the syntax defines a Midvatten project db according to the loaded .sql-file if not int(versionstext[0][0]) > 3: # which file to use depends on spatialite version installed utils.pop_up_info(ru(QCoreApplication.translate('NewDb', "Midvatten plugin needs spatialite4.\nDatabase can not be created"))) utils.stop_waiting_cursor() return '' filenamestring = "create_db.sql" SQLFile = os.path.join(os.sep,os.path.dirname(__file__),"..","definitions",filenamestring) qgisverno = Qgis.QGIS_VERSION#We want to store info about which qgis-version that created the db replace_word_replace_with = [('CHANGETORELEVANTEPSGID', ru(EPSGID)), ('CHANGETOPLUGINVERSION', ru(verno)), ('CHANGETOQGISVERSION', ru(qgisverno)), ('CHANGETODBANDVERSION', 'SpatiaLite version %s'%ru(versionstext)), ('CHANGETOLOCALE', ru(set_locale)), (('SPATIALITE ', ''))] with open(SQLFile, 'r') as f: f.readline() # first line is encoding info.... lines = [ru(line) for line in f] sql_lines = ['{};'.format(l) for l in ' '.join(lines).split(';') if l] for line in sql_lines: if all([line, not line.startswith("#"), 'POSTGIS' not in line]): sql = self.replace_words(line, replace_word_replace_with) try: dbconnection.execute(sql) except: try: print(str(sql)) except: pass raise if delete_srids: db_utils.delete_srids(dbconnection, EPSGID) self.insert_datadomains(set_locale, dbconnection) execute_sqlfile(get_full_filename("insert_obs_points_triggers.sql"), dbconnection) execute_sqlfile(get_full_filename('qgis3_obsp_fix.sql'), dbconnection) self.add_metadata_to_about_db(dbconnection) #FINISHED WORKING WITH THE DATABASE, CLOSE CONNECTIONS dbconnection.commit() dbconnection.vacuum() dbconnection.commit_and_closedb() #create SpatiaLite Connection in QGIS QSettings settings=qgis.PyQt.QtCore.QSettings() settings.beginGroup('/SpatiaLite/dbconnections') settings.setValue('%s/sqlitepath'%os.path.basename(dbpath),'%s'%dbpath) settings.endGroup() """ #The intention is to keep layer styles in the database by using the class AddLayerStyles but due to limitations in how layer styles are stored in the database, I will put this class on hold for a while. #Finally add the layer styles info into the data base AddLayerStyles(dbpath) """ utils.stop_waiting_cursor()
def parse(self, filenames): """ Reads the interlab :param filenames: :return: A dict like {<lablittera>: {u'metadata': {u'metadataheader': value, ...}, <par1_name>: {u'dataheader': value, ...}}} """ all_lab_results = {} for filename in filenames: file_settings = self.parse_filesettings(filename) file_error, version, encoding, decimalsign, quotechar = file_settings if file_error: utils.pop_up_info( ru( QCoreApplication.translate( u'Interlab4Import', u"Warning: The file information %s could not be read. Skipping file" )) % filename) continue with open(filename, 'rb') as f: if quotechar: unicode_reader = utils.UnicodeReader( f, encoding=encoding, quotechar=str(quotechar), delimiter=';') else: unicode_reader = utils.UnicodeReader(f, encoding=encoding, delimiter=';') lab_results = {} file_error = False read_metadata_header = False parse_metadata_values = False read_data_header = False parse_data_values = False metadata_header = None data_header = None for cols in unicode_reader: if not cols: continue if cols[0].lower().startswith(u'#s**t'): break #cols = ru(cols, keep_containers=True) if cols[0].lower().startswith(u'#provadm'): parse_data_values = False parse_metadata_values = False read_data_header = False read_metadata_header = True data_header = None metadata_header = None continue if cols[0].lower().startswith(u'#provdat'): parse_data_values = False parse_metadata_values = False read_metadata_header = False read_data_header = True continue if read_metadata_header: metadata_header = [x.lower() for x in cols] read_metadata_header = False parse_metadata_values = True continue if parse_metadata_values: metadata = dict([(metadata_header[idx], value.lstrip(' ').rstrip(' ')) for idx, value in enumerate(cols) if value.lstrip(' ').rstrip(' ')]) lab_results.setdefault(metadata[u'lablittera'], {})[u'metadata'] = metadata continue if read_data_header: data_header = [x.lower() for x in cols] read_data_header = False parse_data_values = True continue if parse_data_values: data = dict([(data_header[idx], value.lstrip(' ').rstrip(' ')) for idx, value in enumerate(cols) if value.lstrip(' ').rstrip(' ')]) if u'mätvärdetal' in data: data[u'mätvärdetal'] = data[ u'mätvärdetal'].replace(decimalsign, '.') if not u'parameter' in data: utils.pop_up_info( ru( QCoreApplication.translate( u'Interlab4Import', "WARNING: Parsing error. The parameter is missing on row %s" )) % str(cols)) continue if data[u'lablittera'] not in lab_results: utils.pop_up_info( ru( QCoreApplication.translate( u'Interlab4Import', "WARNING: Parsing error. Data for %s read before it's metadata." )) % data['lablittera']) file_error = True break """ Kalium (This part is VERY specific to Midvatten data analyses and probably doesn't affect anyone else) Kalium is (in our very specific case) measured using two different methods. A high and a low resolution method. The lowest value for low resolution method is '<2,5' (in the parameter 'mätvärdetext') and '<1' for the high resolution method. If two kalium is present, we try to extract the high resolution method and store that one in the database. If kalium is between 1 and 2,5, the high resolution method will show 1,5 (for example) while the low resolution will show '<2,5'. If kalium is below 1, they will have values '<2,5' and '<1' in 'mätvärdetext' If both are above 2,5, there is no good way to separate them. In that case, use the last one. """ if u'kalium' in data[u'parameter'].lower(): current_kalium_name = data[u'parameter'].lower() existing_same_names = [ x for x in lab_results[data[u'lablittera']] if x == current_kalium_name ] if not existing_same_names: #kalium has not been parsed yet. Keep the current one. pass else: parameter_chosen = False #Method 1: Use mätosäkerhet to find the high resolution kalium. _previous_resolution = lab_results[data[ u'lablittera']][current_kalium_name].get( u'mätosäkerhet', u'') previous_resolution = _previous_resolution.replace( u'±', u'').replace(u'<', u'') _current_resolution = data.get( u'mätosäkerhet', u'') current_resolution = _current_resolution.replace( u'±', u'').replace(u'<', u'') if previous_resolution and current_resolution: try: previous_resolution = float( previous_resolution) current_resolution = float( current_resolution) except ValueError: #mätosäkerhet could not be used. Try the other method parameter_chosen = False pass else: if previous_resolution > current_resolution: # The current one is the high resolution one. Keep it to overwrite the other one. parameter_chosen = True utils.MessagebarAndLog.info( log_msg=ru( QCoreApplication.translate( u'Interlab4Import', u'Kalium was found more than once. The one with mätosäkerhet %s was used."' )) % _current_resolution) elif current_resolution > previous_resolution: # The current one is the low resolution one, skip it. utils.MessagebarAndLog.info( log_msg=ru( QCoreApplication.translate( u'Interlab4Import', u'Kalium was found more than once. The one with mätosäkerhet %s was used."' )) % _previous_resolution) parameter_chosen = True continue elif current_resolution == previous_resolution: # This method could not be used to find the high resolution one. Try the other method. parameter_chosen = False if not parameter_chosen: current_txt = data.get( u'mätvärdetext', u'').strip(u' ') previous_txt = lab_results[ data[u'lablittera']][ current_kalium_name].get( u'mätvärdetext', u'') #Method 2: Use < and <2.5 limits to try to find the high resolution one. if current_txt == u'<1' or previous_txt.strip( u' ').replace(u',', u'.') == u'<2.5': #The current one is the high resolution one. Keep it to overwrite the other one. utils.MessagebarAndLog.info(log_msg=ru( QCoreApplication.translate( u'Interlab4Import', u'Kalium was found more than once. The one with mätvärdetext %s was used."' )) % current_txt) pass elif current_txt == u'<2.5' or previous_txt.strip( u' ') == u'<1': #The current one is the low resolution one, skip it. utils.MessagebarAndLog.info(log_msg=ru( QCoreApplication.translate( u'Interlab4Import', u'Kalium was found more than once. The one with mätvärdetext %s was used."' )) % previous_txt) continue else: utils.MessagebarAndLog.info(log_msg=ru( QCoreApplication.translate( u'Interlab4Import', u'Kalium was found more than once. The high resolution one could not be found. The one with mätvärdetext %s was used."' )) % current_txt) #Hope that the current one (the last one) is the high resolution one and let it overwrite the existing one pass lab_results[data[u'lablittera']][ data[u'parameter']] = data continue if not file_error: all_lab_results.update(lab_results) return all_lab_results
def showtheplot( self, layer ): # PlotTS method that, at the moment, performs all the real work provider = layer.dataProvider() #Something with OGR kolumnindex = provider.fieldNameIndex( 'obsid') # To find the column named 'obsid' if kolumnindex == -1: kolumnindex = provider.fieldNameIndex( 'OBSID') # backwards compatibility if (layer): nF = layer.selectedFeatureCount() if (nF > 0): # Load all selected observation points ob = layer.getSelectedFeatures() # Create a plot window with one single subplot fig = plt.figure( ) # causes conflict with plugins "statist" and "chartmaker" ax = fig.add_subplot(111) if len(self.y3col): nY = 3 elif len(self.y2col): nY = 2 else: nY = 1 p = [None] * nF * nY # List for plot objects plabel = [None] * nF * nY # List for label strings j = 0 for feature in ob: # Loop through all selected objects, a plot is added for each one of the observation points (i.e. selected objects) attributes = feature.attributes() obsid = attributes[ kolumnindex] # Copy value in column obsid in the attribute list # Load all observations (full time series) for the object [i] (i.e. selected observation point no i) sql = r"""SELECT """ sql += str(self.xcol) #MacOSX fix1 sql += r""" as 'x'""" if len(self.y1col): sql += r""", """ sql += str(self.y1col) #MacOSX fix1 sql += r""" as 'y1'""" if len(self.y2col): sql += r""", """ sql += str(self.y2col) #MacOSX fix1 sql += r""" as 'y2'""" if len(self.y3col): sql += r""", """ sql += str(self.y3col) #MacOSX fix1 sql += r""" as 'y3'""" sql += """ FROM """ sql += str(self.table) #MacOSX fix1 sql += r""" WHERE obsid = '""" sql += obsid sql += """' ORDER BY """ sql += str(self.xcol) #MacOSX fix1 connection_ok, recs = db_utils.sql_load_fr_db(sql) """Transform data to a numpy.recarray""" if len(self.y1col): My_format = [('x', float), ('y1', float)] if len(self.y2col): My_format.append(('y2', float)) if len(self.y3col): My_format.append(('y3', float)) table = np.array(recs, dtype=My_format) #NDARRAY table2 = table.view( np.recarray ) # RECARRAY Makes the two columns inte callable objects, i.e. write table2.values if self.markers == 2: # If the checkbox is checked - markers will be plotted, just a line #MacOSX fix1 p[j], = ax.plot(table2.x, table2.y1, marker='o', linestyle='-', label=obsid) # PLOT!! else: p[j], = ax.plot(table2.x, table2.y1, marker='None', linestyle='-', label=obsid) # PLOT!! plabel[j] = obsid + str( self.y1col) #+ str(j)# Label for the plot #MacOSX fix1 if len(self.y2col): j = j + 1 if self.markers == 2: # If the checkbox is checked - markers will be plotted, just a line #MacOSX fix1 p[j], = ax.plot(table2.x, table2.y2, marker='o', linestyle='-', label=obsid) # PLOT!! else: p[j], = ax.plot(table2.x, table2.y2, marker='None', linestyle='-', label=obsid) # PLOT!! plabel[j] = obsid + str( self.y2col ) #+ str(j)# Label for the plot #MacOSX fix1 if len(self.y3col): j = j + 1 if self.markers == 2: # If the checkbox is checked - markers will be plotted, just a line #MacOSX fix1 p[j], = ax.plot(table2.x, table2.y3, marker='o', linestyle='-', label=obsid) # PLOT!! else: p[j], = ax.plot(table2.x, table2.y3, marker='None', linestyle='-', label=obsid) # PLOT!! plabel[j] = obsid + str( self.y3col ) #+ str(j)# Label for the plot #MacOSX fix1 j = j + 1 """ Finish plot """ ax.grid(True) ax.yaxis.set_major_formatter( tick.ScalarFormatter(useOffset=False, useMathText=False)) ax.set_xlabel(self.xcol) #MacOSX fix1 ylabel = str(self.y1col) + ", \n" + str( self.y2col) + ", \n" + str(self.y3col) #MacOSX fix1 ax.set_ylabel(ylabel) ax.set_title(self.settingsdict['xytable']) #MacOSX fix1 leg = fig.legend(p, plabel, loc=0) leg.draggable(state=True) frame = leg.get_frame( ) # the matplotlib.patches.Rectangle instance surrounding the legend frame.set_facecolor( '0.80') # set the frame face color to light gray frame.set_fill(False) # set the frame face color transparent for t in leg.get_texts(): t.set_fontsize(10) # the legend text fontsize for label in ax.xaxis.get_ticklabels(): label.set_fontsize(10) for label in ax.yaxis.get_ticklabels(): label.set_fontsize(10) fig.show( ) # causes conflict with plugins "statist" and "chartmaker" else: utils.pop_up_info( ru( QCoreApplication.translate( 'XYPlot', "Please select at least one point with xy data"))) else: utils.pop_up_info( ru( QCoreApplication.translate( 'XYPlot', "Please select a layer containing observations with xy data" )))
return if os.path.splitext(filename)[1] != u'.csv': filename += u'.csv' try: with open(filename, 'w') as f: f.write(u'\n'.join(printlist).encode('utf-8')) except IOError, e: utils.pop_up_info( ru( QCoreApplication.translate( u'ExportToFieldLogger', u"Writing of file failed!: %s ")) % str(e)) except UnicodeDecodeError, e: utils.pop_up_info( ru( QCoreApplication.translate(u'ExportToFieldLogger', u"Error writing %s")) % str(printlist)) class ParameterGroup(object): def __init__(self, connect): """ """ #Widget list: self._location_suffix = PyQt4.QtGui.QLineEdit() self._sublocation_suffix = PyQt4.QtGui.QLineEdit() self._input_field_group_list = ExtendedQPlainTextEdit( keep_sorted=False) self._obsid_list = ExtendedQPlainTextEdit(keep_sorted=True)
def __init__(self, settingsdict, num_data_cols, rowheader_colwidth_percent, empty_row_between_tables, page_break_between_tables, from_active_layer, sql_table): #show the user this may take a long time... utils.start_waiting_cursor() self.nr_header_rows = 3 reportfolder = os.path.join(QDir.tempPath(), 'midvatten_reports') if not os.path.exists(reportfolder): os.makedirs(reportfolder) reportpath = os.path.join(reportfolder, "w_qual_report.html") f = codecs.open(reportpath, "wb", "utf-8") #write some initiating html rpt = r"""<head><title>%s</title></head>""" % ru( QCoreApplication.translate( 'Wqualreport', 'water quality report from Midvatten plugin for QGIS')) rpt += r""" <meta http-equiv="content-type" content="text/html; charset=utf-8" />""" #NOTE, all report data must be in 'utf-8' rpt += "<html><body>" f.write(rpt) if from_active_layer: utils.pop_up_info( ru( QCoreApplication.translate( 'CompactWqualReport', 'Check that exported number of rows are identical to expected number of rows!\nFeatures in layers from sql queries can be invalid and then excluded from the report!' )), 'Warning!') w_qual_lab_layer = qgis.utils.iface.activeLayer() if w_qual_lab_layer is None: raise utils.UsageError( ru( QCoreApplication.translate('CompactWqualReport', 'Must select a layer!'))) if not w_qual_lab_layer.selectedFeatureCount(): w_qual_lab_layer.selectAll() data = self.get_data_from_qgislayer(w_qual_lab_layer) else: data = self.get_data_from_sql(sql_table, utils.getselectedobjectnames()) report_data, num_data = self.data_to_printlist(data) utils.MessagebarAndLog.info(bar_msg=ru( QCoreApplication.translate( 'CompactWqualReport', 'Created report from %s number of rows.')) % str(num_data)) for startcol in range(1, len(report_data[0]), num_data_cols): printlist = [[row[0]] for row in report_data] for rownr, row in enumerate(report_data): printlist[rownr].extend( row[startcol:min(startcol + num_data_cols, len(row))]) filtered = [row for row in printlist if any(row[1:])] self.htmlcols = len(filtered[0]) self.WriteHTMLReport( filtered, f, rowheader_colwidth_percent, empty_row_between_tables=empty_row_between_tables, page_break_between_tables=page_break_between_tables) # write some finishing html and close the file f.write("\n</body></html>") f.close() utils.stop_waiting_cursor( ) # now this long process is done and the cursor is back as normal if report_data: QDesktopServices.openUrl(QUrl.fromLocalFile(reportpath))
def parse(self, filenames): """ Reads the interlab :param filenames: :return: A dict like {<lablittera>: {'metadata': {'metadataheader': value, ...}, <par1_name>: {'dataheader': value, ...}}} """ all_lab_results = {} for filename in filenames: file_settings = self.parse_filesettings(filename) file_error, version, encoding, decimalsign, quotechar = file_settings if file_error: utils.pop_up_info( ru( QCoreApplication.translate( 'Interlab4Import', "Warning: The file information %s could not be read. Skipping file" )) % filename) continue with io.open(filename, 'r', encoding=encoding) as f: if quotechar: unicode_reader = csv.reader(f, dialect=csv.excel, quotechar=str(quotechar), delimiter=';') else: unicode_reader = csv.reader(f, dialect=csv.excel, delimiter=';') lab_results = {} file_error = False read_metadata_header = False parse_metadata_values = False read_data_header = False parse_data_values = False metadata_header = None data_header = None for cols in unicode_reader: if not cols: continue if cols[0].lower().startswith('#s**t'): break #cols = ru(cols, keep_containers=True) if cols[0].lower().startswith('#provadm'): parse_data_values = False parse_metadata_values = False read_data_header = False read_metadata_header = True data_header = None metadata_header = None continue if cols[0].lower().startswith('#provdat'): parse_data_values = False parse_metadata_values = False read_metadata_header = False read_data_header = True continue if read_metadata_header: metadata_header = [x.lower() for x in cols] read_metadata_header = False parse_metadata_values = True continue if parse_metadata_values: metadata = dict([(metadata_header[idx], value.lstrip(' ').rstrip(' ')) for idx, value in enumerate(cols) if value.lstrip(' ').rstrip(' ')]) lab_results.setdefault(metadata['lablittera'], {})['metadata'] = metadata continue if read_data_header: data_header = [x.lower() for x in cols] read_data_header = False parse_data_values = True continue if parse_data_values: data = dict([(data_header[idx], value.lstrip(' ').rstrip(' ')) for idx, value in enumerate(cols) if value.lstrip(' ').rstrip(' ')]) if 'mätvärdetal' in data: data['mätvärdetal'] = data['mätvärdetal'].replace( decimalsign, '.') if not 'parameter' in data: utils.pop_up_info( ru( QCoreApplication.translate( 'Interlab4Import', "WARNING: Parsing error. The parameter is missing on row %s" )) % str(cols)) continue if data['lablittera'] not in lab_results: utils.pop_up_info( ru( QCoreApplication.translate( 'Interlab4Import', "WARNING: Parsing error. Data for %s read before it's metadata." )) % data['lablittera']) file_error = True break # If two parameter with the same name exists in the report, use the highest resolution one, that is, the one with the lowest value. existing_data = lab_results[data['lablittera']].get( data['parameter'], None) if existing_data is not None: primary_data, _duplicate_data = self.compare_duplicate_parameters( data, existing_data) lab_results[data['lablittera']][ data['parameter']] = primary_data dupl_index = 1 duplicate_parname = _duplicate_data['parameter'] while duplicate_parname in lab_results[ data['lablittera']]: duplicate_translation = 'dubblett' if utils.getcurrentlocale( )[0] == 'sv_SE' else 'duplicate' duplicate_parname = '%s (%s %s)' % ( _duplicate_data['parameter'], duplicate_translation, str(dupl_index)) dupl_index += 1 else: _duplicate_data[ 'parameter'] = duplicate_parname lab_results[data['lablittera']][ _duplicate_data[ 'parameter']] = _duplicate_data continue lab_results[data['lablittera']][ data['parameter']] = data if not file_error: all_lab_results.update(lab_results) return all_lab_results