def __init__(self, iface): QDialog.__init__(self) self.iface = iface # Set up the user interface from Designer. self.setupUi(self) self.fields_lbl = QLabel( 'Fields containing loss-based damage state probabilities') self.fields_multiselect = MultiSelectComboBox(self) self.vLayout.insertWidget(2, self.fields_lbl) self.vLayout.insertWidget(3, self.fields_multiselect) self.ok_button = self.buttonBox.button(QDialogButtonBox.Ok) approach_explanation = ( 'Aggregate: building-level recovery model as a single process\n' 'Disaggregate: Building-level recovery modelled using four' ' processes: inspection, assessment, mobilization and repair.') self.approach_cbx.addItems(['Disaggregate', 'Aggregate']) self.approach_cbx.setToolTip(approach_explanation) self.approach_lbl.setToolTip(approach_explanation) simulations_explanation = ( 'Number of damage realizations used in Monte Carlo Simulation') n_simulations = int( QSettings().value('irmt/n_simulations_per_building', 1)) self.n_simulations_sbx.setValue(n_simulations) self.n_simulations_lbl.setToolTip(simulations_explanation) self.n_simulations_sbx.setToolTip(simulations_explanation) self.save_bldg_curves_check.setChecked(False) self.populate_layers_in_combos() self.restore_state() self.set_ok_button()
def __init__(self, downloader): QDialog.__init__(self) # Set up the user interface from Designer. self.setupUi(self) self.indicator_lbl = QLabel('Select Indicators') self.indicator_multiselect = MultiSelectComboBox(self) self.scroll_area_contents.layout().addWidget(self.indicator_lbl) self.scroll_area_contents.layout().addWidget( self.indicator_multiselect) self.country_lbl = QLabel('Select Countries') self.country_multiselect = MultiSelectComboBox(self) self.scroll_area_contents.layout().addWidget(self.country_lbl) self.scroll_area_contents.layout().addWidget(self.country_multiselect) self.ok_button = self.buttonBox.button(QDialogButtonBox.Ok) self.set_ok_button() # login to platform, to be able to retrieve sv indices self.sv_downloader = downloader self.indicators_info_dict = {} with WaitCursorManager('Filling list of indicators...'): self.fill_names() with WaitCursorManager('Filling list of themes...'): self.fill_themes() with WaitCursorManager('Filling list of countries...'): self.fill_countries() self.indicator_multiselect.item_was_clicked.connect( self.update_indicator_info) self.indicator_multiselect.selection_changed.connect( self.set_ok_button) self.country_multiselect.selection_changed.connect(self.set_ok_button)
def __init__(self, iface): QDialog.__init__(self) self.iface = iface self.attr_name_user_def = False self.use_advanced = False # Set up the user interface from Designer. self.setupUi(self) self.fields_lbl = QLabel('Fields to transform') self.fields_multiselect = MultiSelectComboBox(self) hlayout = QHBoxLayout() hlayout.addWidget(self.fields_lbl) hlayout.addWidget(self.fields_multiselect) self.vertical_layout.insertLayout(1, hlayout) self.adjustSize() self.ok_button = self.buttonBox.button(QDialogButtonBox.Ok) self.fill_fields_multiselect() alg_list = list(TRANSFORMATION_ALGS.keys()) self.algorithm_cbx.addItems(alg_list) if self.algorithm_cbx.currentText() in ['RANK', 'QUADRATIC']: self.reload_variant_cbx() self.inverse_ckb.setDisabled( self.algorithm_cbx.currentText() in ['LOG10']) self.warning_lbl.hide() self.warning_lbl.setText( "<font color='red'>" "WARNING: the original attribute will be overwritten by the" " results of the transformation (it can not be undone)" "</font>") self.fields_multiselect.selection_changed.connect(self.set_ok_button) self.fields_multiselect.selection_changed.connect( self.set_new_field_editable) self.fields_multiselect.selection_changed.connect( self.update_default_fieldname) self.set_ok_button() self.set_new_field_editable()
class SelectSvVariablesDialog(QDialog, FORM_CLASS): """ Modal dialog giving to the user the possibility to select social vulnerability variables to import from the oq-platform """ def __init__(self, downloader): QDialog.__init__(self) # Set up the user interface from Designer. self.setupUi(self) self.indicator_lbl = QLabel('Select Indicators') self.indicator_multiselect = MultiSelectComboBox(self) self.scroll_area_contents.layout().addWidget(self.indicator_lbl) self.scroll_area_contents.layout().addWidget( self.indicator_multiselect) self.country_lbl = QLabel('Select Countries') self.country_multiselect = MultiSelectComboBox(self) self.scroll_area_contents.layout().addWidget(self.country_lbl) self.scroll_area_contents.layout().addWidget(self.country_multiselect) self.ok_button = self.buttonBox.button(QDialogButtonBox.Ok) self.set_ok_button() # login to platform, to be able to retrieve sv indices self.sv_downloader = downloader self.indicators_info_dict = {} with WaitCursorManager('Filling list of indicators...'): self.fill_names() with WaitCursorManager('Filling list of themes...'): self.fill_themes() with WaitCursorManager('Filling list of countries...'): self.fill_countries() self.indicator_multiselect.item_was_clicked.connect( self.update_indicator_info) self.indicator_multiselect.selection_changed.connect( self.set_ok_button) self.country_multiselect.selection_changed.connect(self.set_ok_button) @pyqtSlot(str) def on_theme_cbx_currentIndexChanged(self): theme = self.theme_cbx.currentText() with WaitCursorManager(): self.fill_subthemes(theme) @pyqtSlot() def on_filter_btn_clicked(self): with WaitCursorManager(): self.fill_names() def set_ok_button(self): self.ok_button.setEnabled( self.indicator_multiselect.selected_count() > 0 and self.country_multiselect.selected_count() > 0) def fill_themes(self): self.theme_cbx.clear() # load list of themes from the platform self.theme_cbx.addItems([None]) try: themes = self.sv_downloader.get_themes() self.theme_cbx.addItems(themes) except SvNetworkError as e: raise SvNetworkError( "Unable to download social vulnerability themes: %s" % e) # populate the subsequent combo boxes accordingly with the currently # selected item current_theme = self.theme_cbx.currentText() self.fill_subthemes(current_theme) def fill_subthemes(self, theme): self.subtheme_cbx.clear() # load list of subthemes from the platform self.subtheme_cbx.addItems([None]) if theme: try: subthemes = self.sv_downloader.get_subthemes_by_theme(theme) self.subtheme_cbx.addItems(subthemes) except SvNetworkError as e: raise SvNetworkError("Unable to download social vulnerability" " subthemes: %s" % e) def fill_names(self): self.indicator_multiselect.clear() # load list of social vulnerability variable names from the platform name_filter = self.name_filter_le.text() keywords = self.keywords_le.text() theme = self.theme_cbx.currentText() subtheme = self.subtheme_cbx.currentText() try: filter_result_dict = self.sv_downloader.get_indicators_info( name_filter, keywords, theme, subtheme) self.indicators_info_dict.update(filter_result_dict) names = sorted([ code + ': ' + filter_result_dict[code]['name'] for code in filter_result_dict ]) self.indicator_multiselect.add_unselected_items(names) except SvNetworkError as e: raise SvNetworkError( "Unable to download social vulnerability names: %s" % e) def update_indicator_info(self, text, status): if status: hint_text = text indicator_code = text.split(':')[0] indicator_info_dict = self.indicators_info_dict[indicator_code] hint_text += '\n\n' + 'Description:\n' + indicator_info_dict[ 'description'] hint_text += '\n\n' + 'Source:\n' + indicator_info_dict['source'] hint_text += ('\n\n' + 'Aggregation method:\n' + indicator_info_dict['aggregation_method']) else: hint_text = '' self.indicator_details.setText(hint_text) def fill_countries(self): # load from platform a list of countries for which socioeconomic data # are available try: countries_dict = self.sv_downloader.get_countries_info() names = sorted([ countries_dict[iso] + ' (' + iso + ')' for iso in countries_dict ]) self.country_multiselect.add_unselected_items(names) except SvNetworkError as e: raise SvNetworkError( "Unable to download the list of countries: %s" % e)
class RecoveryModelingDialog(QDialog, FORM_CLASS): """ Modal dialog to perform recovery modeling analysis. """ def __init__(self, iface): QDialog.__init__(self) self.iface = iface # Set up the user interface from Designer. self.setupUi(self) self.fields_lbl = QLabel( 'Fields containing loss-based damage state probabilities') self.fields_multiselect = MultiSelectComboBox(self) self.vLayout.insertWidget(2, self.fields_lbl) self.vLayout.insertWidget(3, self.fields_multiselect) self.ok_button = self.buttonBox.button(QDialogButtonBox.Ok) approach_explanation = ( 'Aggregate: building-level recovery model as a single process\n' 'Disaggregate: Building-level recovery modelled using four' ' processes: inspection, assessment, mobilization and repair.') self.approach_cbx.addItems(['Disaggregate', 'Aggregate']) self.approach_cbx.setToolTip(approach_explanation) self.approach_lbl.setToolTip(approach_explanation) simulations_explanation = ( 'Number of damage realizations used in Monte Carlo Simulation') n_simulations = int( QSettings().value('irmt/n_simulations_per_building', 1)) self.n_simulations_sbx.setValue(n_simulations) self.n_simulations_lbl.setToolTip(simulations_explanation) self.n_simulations_sbx.setToolTip(simulations_explanation) self.save_bldg_curves_check.setChecked(False) self.populate_layers_in_combos() self.restore_state() self.set_ok_button() def populate_layers_in_combos(self): for key, layer in \ QgsProject.instance().mapLayers().items(): if layer.type() != QgsMapLayer.VectorLayer: continue if layer.geometryType() == QgsWkbTypes.PointGeometry: self.damages_rlzs_layer_cbx.addItem(layer.name(), layer) if layer.geometryType() == QgsWkbTypes.PolygonGeometry: self.svi_layer_cbx.addItem(layer.name(), layer) # if the active layer contains points, preselect it active_layer = self.iface.activeLayer() if active_layer is not None: idx = self.damages_rlzs_layer_cbx.findData(active_layer) if idx != -1: self.damages_rlzs_layer_cbx.setCurrentIndex(idx) def restore_state(self): """ Reinstate the options based on the user's stored session info. """ mySettings = QSettings() self.output_data_dir = mySettings.value( 'irmt/recovery_output_data_dir', '') # hack for strange mac behaviour if not self.output_data_dir: self.output_data_dir = '' self.output_data_dir_le.setText(self.output_data_dir) def save_state(self): """ Store the options into the user's stored session info. """ mySettings = QSettings() mySettings.setValue('irmt/recovery_output_data_dir', self.output_data_dir_le.text()) def set_ok_button(self): self.ok_button.setEnabled( os.path.isdir(self.output_data_dir_le.text()) and self.approach_cbx.currentIndex != -1 and self.damages_rlzs_layer_cbx.currentIndex != -1) # and self.svi_layer_cbx.currentIndex != -1 # and self.svi_field_name_cbx.currentIndex != -1 # and self.zone_field_name_cbx.currentIndex != -1) @pyqtSlot(str) def on_output_data_dir_le_textChanged(self, text): self.output_data_dir = self.output_data_dir_le.text() self.set_ok_button() @pyqtSlot(str) def on_approach_cbx_currentIndexChanged(self, selected_text): # TODO: we might need to ask the user to provide the necessary files self.set_ok_button() @pyqtSlot(int) def on_damages_rlzs_layer_cbx_currentIndexChanged( self, selected_index): self.damages_rlzs_layer = self.damages_rlzs_layer_cbx.itemData( selected_index) self.fields_multiselect.clear() fill_fields_multiselect( self.fields_multiselect, self.damages_rlzs_layer) @pyqtSlot(int) def on_svi_layer_cbx_currentIndexChanged(self, selected_index): self.svi_layer = self.svi_layer_cbx.itemData(selected_index) # FIXME self.svi_field_name is temporarily ignored # reload_attrib_cbx(self.svi_field_name_cbx, self.svi_layer) reload_attrib_cbx(self.zone_field_name_cbx, self.svi_layer) @pyqtSlot() def on_output_data_dir_btn_clicked(self): default_dir = QSettings().value('irmt/output_data_dir', QDir.homePath()) path = QFileDialog.getExistingDirectory( self, self.tr('Choose output directory'), default_dir) if path: QSettings().setValue('irmt/output_data_dir', path) self.output_data_dir_le.setText(path) def calculate_community_level_recovery_curve( self, point_attrs_dict, integrate_svi=True): # Developed By: Henry Burton # Edited by: Hua Kang # Reimplemented for this plugin by: Paolo Tormene and Marco Bernasocchi # Objective: GenerateCommunityLevelRecoveryCurve # Initial date: August 26, 2016 zone_field_name = None if integrate_svi: self.svi_layer = self.svi_layer_cbx.itemData( self.svi_layer_cbx.currentIndex()) # FIXME self.svi_field_name is temporarily ignored # self.svi_field_name = self.svi_field_name_cbx.currentText() zone_field_name = self.zone_field_name_cbx.currentText() approach = self.approach_cbx.currentText() request = QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry) damages_rlzs_features = list( self.damages_rlzs_layer.getFeatures(request)) recovery = RecoveryModeling( damages_rlzs_features, approach, self.iface, self.svi_layer, self.output_data_dir, self.save_bldg_curves_check.isChecked()) probs_field_names = self.fields_multiselect.get_selected_items() for i, fieldname in enumerate(probs_field_names): probs_field_names[i] = point_attrs_dict[fieldname] zonal_damages_rlzs_probs, zonal_asset_refs = \ recovery.collect_zonal_data( probs_field_names, integrate_svi, zone_field_name) # Incorporate Napa Data to community recovery model summary_filename = os.path.join( self.output_data_dir, 'summary.csv') summary = open(summary_filename, 'w', newline='') writer = csv.writer(summary) header = ['zone_id', 'days_to_recover_95_perc', 'event_time', 'after_6_months', 'after_12_months', 'after_18_months'] writer.writerow(header) n_simulations = self.n_simulations_sbx.value() n_zones = len(zonal_damages_rlzs_probs) # for each zone, calculate a zone-level recovery function for zone_index, zone_id in enumerate( list(zonal_damages_rlzs_probs.keys()), start=1): seed = None if DEBUG: seed = 42 recovery.generate_community_level_recovery_curve( zone_id, zonal_damages_rlzs_probs, zonal_asset_refs, writer, integrate_svi, seed, n_simulations=n_simulations, n_zones=n_zones, zone_index=zone_index) summary.close() def accept(self): if self.integrate_svi_check.isChecked(): self.zone_field_name = self.zone_field_name_cbx.currentText() (point_attrs_dict, self.damages_rlzs_layer, self.zone_field_name) = add_zone_id_to_points( self.damages_rlzs_layer, self.svi_layer, self.zone_field_name) else: # the layer containing points was not modified by the zonal # aggregation, so the field names remained as the original ones point_attrs_dict = { field.name(): field.name() for field in self.damages_rlzs_layer.fields()} with WaitCursorManager('Generating recovery curves...', self.iface.messageBar()): self.calculate_community_level_recovery_curve( point_attrs_dict, self.integrate_svi_check.isChecked()) msg = 'Recovery curves have been saved to [%s]' % self.output_data_dir log_msg(msg, level='S', message_bar=self.iface.messageBar()) self.save_state() super(RecoveryModelingDialog, self).accept()
class LoadAssetRiskAsLayerDialog(LoadOutputAsLayerDialog): """ Dialog to load asset_risk from an oq-engine output, as layer """ def __init__(self, drive_engine_dlg, iface, viewer_dock, session, hostname, calc_id, output_type='asset_risk', path=None, mode=None, engine_version=None, calculation_mode=None): assert output_type == 'asset_risk' super().__init__(drive_engine_dlg, iface, viewer_dock, session, hostname, calc_id, output_type=output_type, path=path, mode=mode, engine_version=engine_version, calculation_mode=calculation_mode) self.setWindowTitle('Load Exposure/Risk as layer') log_msg( 'Extracting exposure metadata.' ' Watch progress in QGIS task bar', level='I', message_bar=self.iface.messageBar()) self.extract_npz_task = ExtractNpzTask('Extract exposure metadata', QgsTask.CanCancel, self.session, self.hostname, self.calc_id, 'exposure_metadata', self.finalize_init, self.on_extract_error) QgsApplication.taskManager().addTask(self.extract_npz_task) def finalize_init(self, extracted_npz): self.exposure_metadata = extracted_npz self.tag_names = sorted(self.exposure_metadata['tagnames']) self.exposure_categories = sorted(self.exposure_metadata['names']) self.risk_categories = sorted(self.exposure_metadata['multi_risk']) self.perils = set( [cat.rsplit('-', 1)[-1] for cat in self.risk_categories]) self.populate_out_dep_widgets() self.adjustSize() self.taxonomies_gbx.toggled.emit(False) self.tag_gbx.toggled.emit(False) self.set_ok_button() self.show() self.init_done.emit(self) def populate_out_dep_widgets(self): self.visualize_gbx = QGroupBox('Visualize') self.visualize_gbx_h_layout = QHBoxLayout() self.exposure_rbn = QRadioButton('Exposure') self.risk_rbn = QRadioButton('Risk') self.exposure_rbn.toggled.connect(self.on_visualize_changed) self.risk_rbn.toggled.connect(self.on_visualize_changed) self.visualize_gbx_h_layout.addWidget(self.exposure_rbn) self.visualize_gbx_h_layout.addWidget(self.risk_rbn) self.visualize_gbx.setLayout(self.visualize_gbx_h_layout) self.vlayout.addWidget(self.visualize_gbx) self.create_selector("peril", "Peril", filter_ckb=False, on_text_changed=self.on_peril_changed) self.peril_cbx.setDisabled(True) self.peril_lbl.setVisible(False) self.peril_cbx.setVisible(False) self.create_selector("category", "Category", filter_ckb=False) self.peril_cbx.addItems(sorted(self.perils)) self.taxonomies_gbx = QGroupBox() self.taxonomies_gbx.setTitle('Filter by taxonomy') self.taxonomies_gbx.setCheckable(True) self.taxonomies_gbx.setChecked(False) self.taxonomies_gbx_v_layout = QVBoxLayout() self.taxonomies_gbx.setLayout(self.taxonomies_gbx_v_layout) self.taxonomies_lbl = QLabel("Taxonomies") self.taxonomies_multisel = MultiSelectComboBox(self) self.taxonomies_multisel.add_unselected_items( sorted([ taxonomy for taxonomy in self.exposure_metadata['taxonomy'] if taxonomy != '?' ])) self.taxonomies_gbx_v_layout.addWidget(self.taxonomies_lbl) self.taxonomies_gbx_v_layout.addWidget(self.taxonomies_multisel) self.taxonomies_gbx.toggled[bool].connect( self.on_taxonomies_gbx_toggled) self.vlayout.addWidget(self.taxonomies_gbx) self.tag_gbx = QGroupBox() self.tag_gbx.setTitle('Filter by tag') self.tag_gbx.setCheckable(True) self.tag_gbx.setChecked(False) self.tag_gbx_v_layout = QVBoxLayout() self.tag_gbx.setLayout(self.tag_gbx_v_layout) self.tag_values_lbl = QLabel("Tag values") self.tag_values_multisel = MultiSelectComboBox(self) self.create_selector("tag", "Tag", add_to_layout=self.tag_gbx_v_layout, on_text_changed=self.on_tag_changed) self.tag_cbx.addItems([ tag_name for tag_name in self.tag_names if tag_name != 'taxonomy' ]) self.tag_gbx_v_layout.addWidget(self.tag_values_lbl) self.tag_gbx_v_layout.addWidget(self.tag_values_multisel) self.tag_gbx.toggled[bool].connect(self.on_tag_gbx_toggled) self.vlayout.addWidget(self.tag_gbx) self.higher_on_top_chk = QCheckBox('Render higher values on top') self.higher_on_top_chk.setChecked(True) self.vlayout.addWidget(self.higher_on_top_chk) self.create_zonal_layer_selector() if self.zonal_layer_path: zonal_layer = self.load_zonal_layer(self.zonal_layer_path) self.populate_zonal_layer_cbx(zonal_layer) else: self.pre_populate_zonal_layer_cbx() self.exposure_rbn.setChecked(True) def on_taxonomies_gbx_toggled(self, is_checked): for widget in self.taxonomies_gbx.findChildren(QWidget): widget.setVisible(is_checked) def on_tag_gbx_toggled(self, is_checked): for widget in self.tag_gbx.findChildren(QWidget): widget.setVisible(is_checked) def on_visualize_changed(self): self.peril_cbx.setEnabled(self.risk_rbn.isChecked()) self.peril_lbl.setVisible(self.risk_rbn.isChecked()) self.peril_cbx.setVisible(self.risk_rbn.isChecked()) if self.exposure_rbn.isChecked(): self.category_cbx.clear() self.category_cbx.addItems(self.exposure_categories) else: # 'Risk' self.peril_cbx.setCurrentIndex(0) self.peril_cbx.currentTextChanged.emit( self.peril_cbx.currentText()) def on_peril_changed(self, peril): categories = [ category.rsplit('-', 1)[0] for category in self.risk_categories if peril in category ] self.category_cbx.clear() self.category_cbx.addItems(sorted(categories)) def on_tag_changed(self, tag_name): tag_values = sorted([ value for value in self.exposure_metadata[tag_name] if value != '?' ]) self.tag_values_multisel.clear() self.tag_values_multisel.add_unselected_items(tag_values) def set_ok_button(self): self.ok_button.setEnabled(self.category_cbx.currentIndex() != -1) def build_layer_name(self, rlz_or_stat=None, **kwargs): if self.exposure_rbn.isChecked(): self.default_field_name = self.category_cbx.currentText() else: # 'Risk' self.default_field_name = "%s-%s" % ( self.category_cbx.currentText(), self.peril_cbx.currentText()) if self.exposure_rbn.isChecked(): layer_name = 'Exposure: %s' % self.category_cbx.currentText() else: # Risk layer_name = 'Risk: %s %s' % (self.peril_cbx.currentText(), self.category_cbx.currentText()) return layer_name def get_field_types(self, **kwargs): field_types = { name: self.dataset[name].dtype.char for name in self.dataset.dtype.names if name not in ['lon', 'lat'] and name not in self.tag_names } return field_types def read_npz_into_layer(self, field_types, **kwargs): with edit(self.layer): lons = self.dataset['lon'] lats = self.dataset['lat'] feats = [] for row_idx, row in enumerate(self.dataset): # add a feature feat = QgsFeature(self.layer.fields()) for field_name in field_types: value = row[field_name].item() if isinstance(value, bytes): value = value.decode('utf8') feat.setAttribute(field_name, value) feat.setGeometry( QgsGeometry.fromPointXY( QgsPointXY(lons[row_idx], lats[row_idx]))) feats.append(feat) added_ok = self.layer.addFeatures(feats) if not added_ok: msg = 'There was a problem adding features to the layer.' log_msg(msg, level='C', message_bar=self.iface.messageBar()) return self.layer def accept(self): log_msg('Loading output started. Watch progress in QGIS task bar', level='I', message_bar=self.iface.messageBar()) self.iface.layerTreeView().currentLayerChanged.disconnect( self.on_currentLayerChanged) self.hide() extract_params = self.get_extract_params() self.download_asset_risk(extract_params) def get_extract_params(self): params = {} if self.tag_gbx.isChecked(): tag_name = self.tag_cbx.currentText() params[tag_name] = self.tag_values_multisel.get_selected_items() if self.taxonomies_gbx.isChecked(): params['taxonomy'] = self.taxonomies_multisel.get_selected_items() return params def download_asset_risk(self, extract_params): self.extract_npz_task = ExtractNpzTask('Extract asset_risk', QgsTask.CanCancel, self.session, self.hostname, self.calc_id, 'asset_risk', self.on_asset_risk_downloaded, self.on_extract_error, params=extract_params) QgsApplication.taskManager().addTask(self.extract_npz_task) def on_asset_risk_downloaded(self, extracted_npz): self.npz_file = extracted_npz self.dataset = self.npz_file['array'] with WaitCursorManager('Creating layer...', self.iface.messageBar()): self.layer = self.build_layer() self.style_maps( self.layer, self.default_field_name, self.iface, self.output_type, perils=self.perils, render_higher_on_top=self.higher_on_top_chk.isChecked()) if (self.zonal_layer_cbx.currentText() and self.zonal_layer_gbx.isChecked()): self.aggregate_by_zone() else: self.loading_completed.emit(self) QDialog.accept(self)
def populate_out_dep_widgets(self): self.visualize_gbx = QGroupBox('Visualize') self.visualize_gbx_h_layout = QHBoxLayout() self.exposure_rbn = QRadioButton('Exposure') self.risk_rbn = QRadioButton('Risk') self.exposure_rbn.toggled.connect(self.on_visualize_changed) self.risk_rbn.toggled.connect(self.on_visualize_changed) self.visualize_gbx_h_layout.addWidget(self.exposure_rbn) self.visualize_gbx_h_layout.addWidget(self.risk_rbn) self.visualize_gbx.setLayout(self.visualize_gbx_h_layout) self.vlayout.addWidget(self.visualize_gbx) self.create_selector("peril", "Peril", filter_ckb=False, on_text_changed=self.on_peril_changed) self.peril_cbx.setDisabled(True) self.peril_lbl.setVisible(False) self.peril_cbx.setVisible(False) self.create_selector("category", "Category", filter_ckb=False) self.peril_cbx.addItems(sorted(self.perils)) self.taxonomies_gbx = QGroupBox() self.taxonomies_gbx.setTitle('Filter by taxonomy') self.taxonomies_gbx.setCheckable(True) self.taxonomies_gbx.setChecked(False) self.taxonomies_gbx_v_layout = QVBoxLayout() self.taxonomies_gbx.setLayout(self.taxonomies_gbx_v_layout) self.taxonomies_lbl = QLabel("Taxonomies") self.taxonomies_multisel = MultiSelectComboBox(self) self.taxonomies_multisel.add_unselected_items( sorted([ taxonomy for taxonomy in self.exposure_metadata['taxonomy'] if taxonomy != '?' ])) self.taxonomies_gbx_v_layout.addWidget(self.taxonomies_lbl) self.taxonomies_gbx_v_layout.addWidget(self.taxonomies_multisel) self.taxonomies_gbx.toggled[bool].connect( self.on_taxonomies_gbx_toggled) self.vlayout.addWidget(self.taxonomies_gbx) self.tag_gbx = QGroupBox() self.tag_gbx.setTitle('Filter by tag') self.tag_gbx.setCheckable(True) self.tag_gbx.setChecked(False) self.tag_gbx_v_layout = QVBoxLayout() self.tag_gbx.setLayout(self.tag_gbx_v_layout) self.tag_values_lbl = QLabel("Tag values") self.tag_values_multisel = MultiSelectComboBox(self) self.create_selector("tag", "Tag", add_to_layout=self.tag_gbx_v_layout, on_text_changed=self.on_tag_changed) self.tag_cbx.addItems([ tag_name for tag_name in self.tag_names if tag_name != 'taxonomy' ]) self.tag_gbx_v_layout.addWidget(self.tag_values_lbl) self.tag_gbx_v_layout.addWidget(self.tag_values_multisel) self.tag_gbx.toggled[bool].connect(self.on_tag_gbx_toggled) self.vlayout.addWidget(self.tag_gbx) self.higher_on_top_chk = QCheckBox('Render higher values on top') self.higher_on_top_chk.setChecked(True) self.vlayout.addWidget(self.higher_on_top_chk) self.create_zonal_layer_selector() if self.zonal_layer_path: zonal_layer = self.load_zonal_layer(self.zonal_layer_path) self.populate_zonal_layer_cbx(zonal_layer) else: self.pre_populate_zonal_layer_cbx() self.exposure_rbn.setChecked(True)
class TransformationDialog(QDialog, FORM_CLASS): """ Modal dialog giving to the user the possibility to transform one or multiple attributes in the active layer, using one of the available algorithms and variants. """ def __init__(self, iface): QDialog.__init__(self) self.iface = iface self.attr_name_user_def = False self.use_advanced = False # Set up the user interface from Designer. self.setupUi(self) self.fields_lbl = QLabel('Fields to transform') self.fields_multiselect = MultiSelectComboBox(self) hlayout = QHBoxLayout() hlayout.addWidget(self.fields_lbl) hlayout.addWidget(self.fields_multiselect) self.vertical_layout.insertLayout(1, hlayout) self.adjustSize() self.ok_button = self.buttonBox.button(QDialogButtonBox.Ok) self.fill_fields_multiselect() alg_list = list(TRANSFORMATION_ALGS.keys()) self.algorithm_cbx.addItems(alg_list) if self.algorithm_cbx.currentText() in ['RANK', 'QUADRATIC']: self.reload_variant_cbx() self.inverse_ckb.setDisabled( self.algorithm_cbx.currentText() in ['LOG10']) self.warning_lbl.hide() self.warning_lbl.setText( "<font color='red'>" "WARNING: the original attribute will be overwritten by the" " results of the transformation (it can not be undone)" "</font>") self.fields_multiselect.selection_changed.connect(self.set_ok_button) self.fields_multiselect.selection_changed.connect( self.set_new_field_editable) self.fields_multiselect.selection_changed.connect( self.update_default_fieldname) self.set_ok_button() self.set_new_field_editable() def set_ok_button(self): self.ok_button.setEnabled(self.fields_multiselect.selected_count() > 0) def set_new_field_editable(self): n_fields_selected = self.fields_multiselect.selected_count() self.new_field_name_lbl.setEnabled(n_fields_selected == 1) self.new_field_name_txt.setEnabled(n_fields_selected == 1) @pyqtSlot(int) def on_overwrite_ckb_stateChanged(self): overwrite_checked = self.overwrite_ckb.isChecked() self.new_field_name_lbl.setDisabled(overwrite_checked) self.new_field_name_txt.setDisabled(overwrite_checked) self.track_new_field_ckb.setDisabled(overwrite_checked) if overwrite_checked: self.attr_name_user_def = False self.warning_lbl.show() else: self.warning_lbl.hide() self.update_default_fieldname() @pyqtSlot() def on_calc_btn_clicked(self): self.close() # layer is put in editing mode. If the user clicks on ok, the field # calculator will update the layers attributes. # if the user clicks cancel, the field calculator does nothing. # the layer stays in editing mode with the use_advanced flag set. # the calling code should take care of doing layer.commitChanges() # if the flag is set to true. self.use_advanced = True self.iface.activeLayer().startEditing() self.iface.actionOpenFieldCalculator().trigger() @pyqtSlot(str) def on_algorithm_cbx_currentIndexChanged(self): self.reload_variant_cbx() self.update_default_fieldname() @pyqtSlot(str) def on_variant_cbx_currentIndexChanged(self): self.update_default_fieldname() @pyqtSlot() def on_new_field_name_txt_editingFinished(self): self.attr_name_user_def = True new_field_name = self.new_field_name_txt.text() # if the name of the new field is empty, automatically assign a name if not new_field_name: self.update_default_fieldname() @pyqtSlot(str) def on_new_field_name_txt_textEdited(self): # we assume exactly one item is in the selected list input_field_name = self._extract_field_name( self.fields_multiselect.get_selected_items()[0]) new_field_name = self.new_field_name_txt.text() # if the name of the new field is equal to the name of the input field, # automatically check the 'overwrite' checkbox (and consequently # display the warning) if new_field_name == input_field_name: self.overwrite_ckb.setChecked(True) def reload_variant_cbx(self): self.variant_cbx.clear() self.variant_cbx.setEnabled(True) if self.algorithm_cbx.currentText() == 'RANK': self.variant_cbx.addItems(RANK_VARIANTS) elif self.algorithm_cbx.currentText() == 'QUADRATIC': self.variant_cbx.addItems(QUADRATIC_VARIANTS) elif self.algorithm_cbx.currentText() == 'LOG10': self.variant_cbx.addItems(LOG10_VARIANTS) else: self.variant_cbx.setDisabled(True) self.inverse_ckb.setDisabled( self.algorithm_cbx.currentText() in ['LOG10']) def _extract_field_name(self, field_name_plus_alias): # attribute_name is something like 'ABCDEFGHIL (Readable name)' # and we want to use only the heading code return field_name_plus_alias.split('(')[0].strip() def update_default_fieldname(self): if self.fields_multiselect.selected_count() != 1: self.new_field_name_txt.setText('') self.attr_name_user_def = False return if (not self.attr_name_user_def or not self.new_field_name_txt.text()): attribute_name = self._extract_field_name( self.fields_multiselect.get_selected_items()[0]) algorithm_name = self.algorithm_cbx.currentText() variant = self.variant_cbx.currentText() inverse = self.inverse_ckb.isChecked() if self.overwrite_ckb.isChecked(): new_attr_name = attribute_name else: try: new_attr_name = ProcessLayer( self.iface.activeLayer()).transform_attribute( attribute_name, algorithm_name, variant, inverse, simulate=True) except TypeError as exc: log_msg(str(exc), level='C', message_bar=self.iface.messageBar(), exception=exc) return self.new_field_name_txt.setText(new_attr_name) self.attr_name_user_def = False def fill_fields_multiselect(self): names_plus_aliases = [] for field_idx, field in enumerate(self.iface.activeLayer().fields()): if field.typeName() in NUMERIC_FIELD_TYPES: alias = self.iface.activeLayer().attributeAlias(field_idx) if '(' in field.name(): msg = ('Please remove parentheses from the name of field' ' %s before attempting to transform it, otherwise' ' the tool will not be able to distinguish between' ' the alias and the part of the name included' ' between parentheses. For instance, you may' ' replace "(" with "[" to avoid ambiguity.' % field.name()) log_msg(msg, level='W', message_bar=self.iface.messageBar()) else: name_plus_alias = field.name() if alias: name_plus_alias += ' (%s)' % alias names_plus_aliases.append(name_plus_alias) self.fields_multiselect.add_unselected_items(names_plus_aliases)
def setUpClass(cls): cls.wdg = QWidget() cls.mscb = MultiSelectComboBox(cls.wdg)