def export_pipeline(self): exp = ExportDialog(self._settings.segmentation_pipelines, ProfileDictViewer) if not exp.exec_(): return dial = QFileDialog(self, "Export pipeline segment") dial.setFileMode(QFileDialog.AnyFile) dial.setAcceptMode(QFileDialog.AcceptSave) dial.setDirectory(self._settings.get("io.save_directory", "")) dial.setNameFilter("Segment pipeline (*.json)") dial.setDefaultSuffix("json") dial.selectFile("segment_pipeline.json") dial.setHistory(dial.history() + self._settings.get_path_history()) if dial.exec_(): file_path = dial.selectedFiles()[0] data = { x: self._settings.segmentation_pipelines[x] for x in exp.get_export_list() } with open(file_path, "w") as ff: json.dump(data, ff, cls=self._settings.json_encoder_class, indent=2) self._settings.set("io.save_directory", os.path.dirname(file_path)) self._settings.add_path_history(os.path.dirname(file_path))
def export_plans(self): choose = ExportDialog(self.settings.batch_plans, PlanPreview) if not choose.exec_(): return dial = QFileDialog(self, "Export calculation plans") dial.setFileMode(QFileDialog.AnyFile) dial.setAcceptMode(QFileDialog.AcceptSave) dial.setDirectory( dial.setDirectory( self.settings.get("io.batch_plan_directory", str(Path.home())))) dial.setNameFilter("Calculation plans (*.json)") dial.setDefaultSuffix("json") dial.selectFile("calculation_plans.json") dial.setHistory(dial.history() + self.settings.get_path_history()) if dial.exec_(): file_path = str(dial.selectedFiles()[0]) self.settings.set("io.batch_plan_directory", os.path.dirname(file_path)) self.settings.add_path_history(os.path.dirname(file_path)) data = { x: self.settings.batch_plans[x] for x in choose.get_export_list() } with open(file_path, "w") as ff: json.dump(data, ff, cls=self.settings.json_encoder_class, indent=2)
def export_measurement_profiles(self): exp = ExportDialog(self.settings.measurement_profiles, StringViewer) if not exp.exec_(): return dial = QFileDialog(self, "Export settings profiles") dial.setDirectory(self.settings.get("io.export_directory", "")) dial.setFileMode(QFileDialog.AnyFile) dial.setAcceptMode(QFileDialog.AcceptSave) dial.setNameFilter("measurement profile (*.json)") dial.setDefaultSuffix("json") dial.selectFile("measurements_profile.json") if dial.exec_(): file_path = str(dial.selectedFiles()[0]) self.settings.set("io.export_directory", file_path) data = { x: self.settings.measurement_profiles[x] for x in exp.get_export_list() } with open(file_path, "w") as ff: json.dump(data, ff, cls=self.settings.json_encoder_class, indent=2) self.settings.set("io.save_directory", os.path.dirname(file_path))
def import_profiles(self): dial = QFileDialog(self, "Import profile segment") dial.setFileMode(QFileDialog.ExistingFile) dial.setAcceptMode(QFileDialog.AcceptOpen) dial.setDirectory( self._settings.get("io.save_directory", str(Path.home()))) dial.setNameFilter("Segment profile (*.json)") dial.setHistory(dial.history() + self._settings.get_path_history()) if dial.exec_(): file_path = dial.selectedFiles()[0] save_dir = os.path.dirname(file_path) self._settings.set("io.save_directory", save_dir) self._settings.add_path_history(save_dir) profs, err = self._settings.load_part(file_path) if err: QMessageBox.warning( self, "Import error", "error during importing, part of data were filtered.") profiles_dict = self._settings.segmentation_profiles imp = ImportDialog(profs, profiles_dict, ProfileDictViewer) if not imp.exec_(): return for original_name, final_name in imp.get_import_list(): profiles_dict[final_name] = profs[original_name] self._settings.dump() self.update_profile_list()
def select_file(self): dial = QFileDialog() dial.setFileMode(QFileDialog.ExistingFile) dial.setAcceptMode(QFileDialog.AcceptOpen) if dial.exec_(): self.first_text.setText(dial.selectedFiles()[0])
def folder_dialog(self, *args, **kwargs): dialog = QFileDialog(self) if not self._is_file_dialog_opened: # set the initial directory to HOME dialog.setDirectory(os.path.expanduser("~")) self._is_file_dialog_opened = True dir_name = None dialog.setWindowTitle("Open .edi Directory...") dialog.setFileMode(QFileDialog.DirectoryOnly) while dir_name is None: if dialog.exec_() == QDialog.Accepted: dir_name = dialog.selectedFiles()[0] dir_name = str(dir_name) file_list = [ os.path.join(dir_name, edi) for edi in os.listdir(dir_name) if edi.endswith("edi") ] if not file_list: # empty list QMessageBox.information( self, "NOTE", "Directory does not contain any .edi file, please select again." ) dir_name = None # will read again else: self._progress_bar.setMaximumValue(len(file_list)) self._progress_bar.onStart() self._add_files(file_list, os.path.basename(dir_name)) self._update_tree_view() self._progress_bar.onFinished() else: break
def import_plans(self): dial = QFileDialog(self, "Import calculation plans") dial.setFileMode(QFileDialog.ExistingFile) dial.setAcceptMode(QFileDialog.AcceptOpen) dial.setDirectory( self.settings.get("io.open_directory", str(Path.home()))) dial.setNameFilter("Calculation plans (*.json)") dial.setDefaultSuffix("json") dial.setHistory(dial.history() + self.settings.get_path_history()) if dial.exec_(): file_path = dial.selectedFiles()[0] plans, err = self.settings.load_part(file_path) self.settings.set("io.batch_plan_directory", os.path.dirname(file_path)) self.settings.add_path_history(os.path.dirname(file_path)) if err: QMessageBox.warning( self, "Import error", "error during importing, part of data were filtered.") choose = ImportDialog(plans, self.settings.batch_plans, PlanPreview) if choose.exec_(): for original_name, final_name in choose.get_import_list(): self.settings.batch_plans[final_name] = plans[ original_name] self.update_plan_list()
def select_manual_output_folder(self): # _current_folder = self.main_window.current_folder dlg = QFileDialog(parent=self.main_window, caption="Select or Define Output Directory") dlg.setFileMode(QFileDialog.Directory) if dlg.exec_(): output_folder_name = str(dlg.selectedFiles()[0]) self.main_window.autonom_ui.manual_output_folder_field.setText(output_folder_name)
def open_a_file_dialog(parent=None, default_suffix=None, directory=None, file_filter=None, accept_mode=None, file_mode=None): """ Open a dialog asking for a file location and name to and return it :param parent: QWidget; The parent QWidget of the created dialog :param default_suffix: String; The default suffix to be passed :param directory: String; Directory to which the dialog will open :param file_filter: String; The filter name and file type e.g. "Python files (*.py)" :param accept_mode: enum AcceptMode; Defines the AcceptMode of the dialog, check QFileDialog Class for details :param file_mode: enum FileMode; Defines the FileMode of the dialog, check QFileDialog Class for details :return: String; The filename that was selected, it is possible to return a directory so look out for that """ global _LAST_SAVE_DIRECTORY dialog = QFileDialog(parent) # It is the intention to only save the user's last used directory until workbench is restarted similar to other # applications (VSCode, Gedit etc) if _LAST_SAVE_DIRECTORY is not None and directory is None: dialog.setDirectory(_LAST_SAVE_DIRECTORY) elif directory is not None: dialog.setDirectory(directory) else: dialog.setDirectory(os.path.expanduser("~")) if file_filter is not None: dialog.setFilter(QDir.Files) dialog.setNameFilter(file_filter) if default_suffix is not None: dialog.setDefaultSuffix(default_suffix) if file_mode is not None: dialog.setFileMode(file_mode) if accept_mode is not None: dialog.setAcceptMode(accept_mode) # Connect the actual filename setter dialog.fileSelected.connect(_set_last_save) # Wait for dialog to finish before allowing continuation of code if dialog.exec_() == QDialog.Rejected: return None filename = _LAST_SAVE_DIRECTORY # Make sure that the _LAST_SAVE_DIRECTORY is set as a directory if _LAST_SAVE_DIRECTORY is not None and not os.path.isdir( _LAST_SAVE_DIRECTORY): # Remove the file for last directory _LAST_SAVE_DIRECTORY = os.path.dirname( os.path.abspath(_LAST_SAVE_DIRECTORY)) return filename
def choose_data_prefix(self): dial = QFileDialog() dial.setAcceptMode(QFileDialog.AcceptOpen) dial.setFileMode(QFileDialog.Directory) dial.setDirectory(self.base_prefix.text()) dial.setHistory(dial.history() + self.settings.get_path_history()) if dial.exec_(): dir_path = str(dial.selectedFiles()[0]) self.base_prefix.setText(dir_path)
def select_directory(self): dial = QFileDialog(self, "Select directory") dial.setDirectory( self.settings.get("io.batch_directory", self.settings.get("io.load_image_directory", str(Path.home()))) ) dial.setFileMode(QFileDialog.Directory) if dial.exec_(): self.paths_input.setText(dial.selectedFiles()[0]) self.settings.set("io.batch_directory", str(dial.selectedFiles()[0]))
def choose_result_prefix(self): dial = QFileDialog() dial.setOption(QFileDialog.DontUseNativeDialog, True) dial.setAcceptMode(QFileDialog.AcceptOpen) dial.setFileMode(QFileDialog.Directory) dial.setDirectory(self.result_prefix.text()) dial.setHistory(dial.history() + self.settings.get_path_history()) if dial.exec_(): dir_path = str(dial.selectedFiles()[0]) self.result_prefix.setText(dir_path)
def mapping_dialog(): dial = QFileDialog(self, "Select file") dial.setHistory(dial.history() + self.settings.get_path_history()) base_path = str(self.base_prefix.text()).strip() if base_path != "": dial.setDirectory(base_path) dial.setFileMode(QFileDialog.ExistingFile) if dial.exec_(): path = str(dial.selectedFiles()) self.mask_path_list[i].setText(path) file_mapper: MaskFile = self.mask_mapper_list[pos] file_mapper.set_map_path(path)
def open_a_file_dialog(parent=None, default_suffix=None, directory=None, file_filter=None, accept_mode=None, file_mode=None): """ Open a dialog asking for a file location and name to and return it :param parent: QWidget; The parent QWidget of the created dialog :param default_suffix: String; The default suffix to be passed :param directory: String; Directory to which the dialog will open :param file_filter: String; The filter name and file type e.g. "Python files (*.py)" :param accept_mode: enum AcceptMode; Defines the AcceptMode of the dialog, check QFileDialog Class for details :param file_mode: enum FileMode; Defines the FileMode of the dialog, check QFileDialog Class for details :return: String; The filename that was selected, it is possible to return a directory so look out for that """ global _LAST_SAVE_DIRECTORY dialog = QFileDialog(parent) # It is the intention to only save the user's last used directory until workbench is restarted similar to other # applications (VSCode, Gedit etc) if _LAST_SAVE_DIRECTORY is not None and directory is None: dialog.setDirectory(_LAST_SAVE_DIRECTORY) elif directory is not None: dialog.setDirectory(directory) else: dialog.setDirectory(os.path.expanduser("~")) if file_filter is not None: dialog.setFilter(QDir.Files) dialog.setNameFilter(file_filter) if default_suffix is not None: dialog.setDefaultSuffix(default_suffix) if file_mode is not None: dialog.setFileMode(file_mode) if accept_mode is not None: dialog.setAcceptMode(accept_mode) # Connect the actual filename setter dialog.fileSelected.connect(_set_last_save) # Wait for dialog to finish before allowing continuation of code if dialog.exec_() == QDialog.Rejected: return None filename = _LAST_SAVE_DIRECTORY # Make sure that the _LAST_SAVE_DIRECTORY is set as a directory if _LAST_SAVE_DIRECTORY is not None and not os.path.isdir(_LAST_SAVE_DIRECTORY): # Remove the file for last directory _LAST_SAVE_DIRECTORY = os.path.dirname(os.path.abspath(_LAST_SAVE_DIRECTORY)) return filename
def select_files(self): dial = QFileDialog(self, "Select files") dial.setDirectory( self.settings.get("io.batch_directory", self.settings.get("io.load_image_directory", str(Path.home()))) ) dial.setFileMode(QFileDialog.ExistingFiles) if dial.exec_(): self.settings.set("io.batch_directory", os.path.dirname(str(dial.selectedFiles()[0]))) new_paths = sorted(set(map(str, dial.selectedFiles())) - self.files_to_proceed) for path in new_paths: self.selected_files.addItem(FileListItem(path)) self.files_to_proceed.update(new_paths) self.file_list_changed.emit(self.files_to_proceed)
def stl_dialog(self): dialog = QFileDialog(self) dialog.setWindowTitle('Open STL Tool file') dialog.setNameFilter('(*.stl)') filename = None if dialog.exec_() == QDialog.Accepted: filename = dialog.selectedFiles() if filename: self.setFilename(filename[0]) else: self.clearFilename()
def showSelectProjectDialog(parent: QWidget = None) -> Optional[Path]: dialog = QFileDialog(parent, Qt.Dialog) dialog.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.Dialog) dialog.setAcceptMode(QFileDialog.AcceptSave) dialog.setLabelText(QFileDialog.LookIn, "Select project folder") dialog.setFileMode(QFileDialog.Directory) dialog.setOption(QFileDialog.ShowDirsOnly, True) dialog.setViewMode(QFileDialog.Detail) dialog.setDirectory(QDir.homePath()) if dialog.exec_(): paths = dialog.selectedFiles() assert len(paths) == 1 path = Path(paths[0]) return path
def file_dialog(self, *args, **kwargs): dialog = QFileDialog(self) if not self._is_file_dialog_opened: # set the initial directory to HOME dialog.setDirectory(os.path.expanduser("~")) self._is_file_dialog_opened = True dialog.setWindowTitle('Open .edi Files...') dialog.setNameFilter('.edi files (*.edi)') dialog.setFileMode(QFileDialog.ExistingFiles) if dialog.exec_() == QDialog.Accepted: file_list = dialog.selectedFiles() self._progress_bar.setMaximumValue(len(file_list)) self._progress_bar.onStart() self._add_files(file_list, DEFAULT_GROUP_NAME) self._update_tree_view() self._progress_bar.onFinished()
def _export_shape_file(self, *args, **kwargs): # show files msg = QMessageBox() msg.setIcon(QMessageBox.Information) msg.setText("You are about to create shape files.") msg.setInformativeText( "Please select an output directory after click \"OK\"\n" "For the list of .edi files (stations) included in the creation, please click \"Show Details\"" ) msg.setWindowTitle("Note") msg.setDetailedText("\n".join([ "{station} ({fn})".format( station=station, fn=self._file_handler.station2ref(station)) for station in self._station_viewer.selected_stations ])) msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) if msg.exec_() == QMessageBox.Ok: dialog = QFileDialog(self) dir_name = None dialog.setWindowTitle("Selecting Output Directory ...") dialog.setFileMode(QFileDialog.DirectoryOnly) while dir_name is None: if dialog.exec_() == QDialog.Accepted: dir_name = dialog.selectedFiles()[0] dir_name = str(dir_name) if not os.path.isdir(dir_name): QMessageBox.information( self, "NOTE", "Please select a directory to save the created shape files." ) dir_name = None # will read again else: break if dir_name is not None: collect = EdiCollection(mt_objs=[ self._file_handler.get_MT_obj( self._file_handler.station2ref(station)) for station in self._station_viewer.selected_stations ]) collect.create_mt_station_gdf(dir_name) QMessageBox.information(self, "Creation Completed", "Output written to %s" % dir_name) webbrowser.open(dir_name)
def select_files(self): dial = QFileDialog(self, "Select files") dial.setDirectory( self.settings.get( "io.batch_directory", self.settings.get("io.load_image_directory", str(Path.home())))) dial.setFileMode(QFileDialog.ExistingFiles) if dial.exec_(): self.settings.set("io.batch_directory", os.path.dirname(str(dial.selectedFiles()[0]))) new_paths = sorted( set(map(str, dial.selectedFiles())) - self.files_to_proceed) for path in new_paths: size = os.stat(path).st_size size = float(size) / (1024**2) lwi = QListWidgetItem("{:s} ({:.2f} MB)".format(path, size)) lwi.setTextAlignment(Qt.AlignRight) self.selected_files.addItem(lwi) self.files_to_proceed.update(new_paths) self.file_list_changed.emit(self.files_to_proceed)
def import_measurement_profiles(self): dial = QFileDialog(self, "Import settings profiles") dial.setDirectory(self.settings.get("io.export_directory", "")) dial.setFileMode(QFileDialog.ExistingFile) dial.setNameFilter("measurement profile (*.json)") if dial.exec_(): file_path = str(dial.selectedFiles()[0]) self.settings.set("io.export_directory", file_path) stat, err = self.settings.load_part(file_path) if err: QMessageBox.warning( self, "Import error", "error during importing, part of data were filtered.") measurement_dict = self.settings.measurement_profiles imp = ImportDialog(stat, measurement_dict, StringViewer) if not imp.exec_(): return for original_name, final_name in imp.get_import_list(): measurement_dict[final_name] = stat[original_name] self.profile_list.clear() self.profile_list.addItems(list(sorted(measurement_dict.keys()))) self.settings.dump()
def run_opensbml(self, filenames=None, goto=None, word='', editorwindow=None, processevents=True): """Prompt the user to load a SBML file, translate to antimony, and display in a new window""" editor = self.main.editor editor0 = editor.get_current_editor() if editor0 is not None: position0 = editor0.get_position('cursor') filename0 = editor.get_current_filename() else: position0, filename0 = None, None if not filenames: # Recent files action action = editor.sender() if isinstance(action, QAction): filenames = from_qvariant(action.data(), to_text_string) if not filenames: basedir = getcwd() if editor.edit_filetypes is None: editor.edit_filetypes = get_edit_filetypes() if editor.edit_filters is None: editor.edit_filters = get_edit_filters() c_fname = editor.get_current_filename() if c_fname is not None and c_fname != editor.TEMPFILE_PATH: basedir = os.path.dirname(c_fname) editor.redirect_stdio.emit(False) parent_widget = editor.get_current_editorstack() if filename0 is not None: selectedfilter = get_filter(editor.edit_filetypes, os.path.splitext(filename0)[1]) else: selectedfilter = '' if not running_under_pytest(): customfilters = 'SBML files (*.sbml *.xml);;All files (*.*)' filenames, _sf = getopenfilenames( parent_widget, _("Open SBML file"), basedir, customfilters, selectedfilter=selectedfilter, options=QFileDialog.HideNameFilterDetails) else: # Use a Qt (i.e. scriptable) dialog for pytest dialog = QFileDialog(parent_widget, _("Open SBML file"), options=QFileDialog.DontUseNativeDialog) if dialog.exec_(): filenames = dialog.selectedFiles() editor.redirect_stdio.emit(True) if filenames: filenames = [os.path.normpath(fname) for fname in filenames] else: return focus_widget = QApplication.focusWidget() if editor.dockwidget and\ (not editor.dockwidget.isAncestorOf(focus_widget)\ and not isinstance(focus_widget, CodeEditor)): editor.dockwidget.setVisible(True) editor.dockwidget.setFocus() editor.dockwidget.raise_() def _convert(fname): fname = os.path.abspath(encoding.to_unicode_from_fs(fname)) if os.name == 'nt' and len(fname) >= 2 and fname[1] == ':': fname = fname[0].upper() + fname[1:] return fname if hasattr(filenames, 'replaceInStrings'): # This is a QStringList instance (PyQt API #1), converting to list: filenames = list(filenames) if not isinstance(filenames, list): filenames = [_convert(filenames)] else: filenames = [_convert(fname) for fname in list(filenames)] if isinstance(goto, int): goto = [goto] elif goto is not None and len(goto) != len(filenames): goto = None for index, filename in enumerate(filenames): p = re.compile('(.xml$|.sbml$)') pythonfile = p.sub('_antimony.py', filename) if (pythonfile == filename): pythonfile = filename + "_antimony.py" # -- Do not open an already opened file current_editor = editor.set_current_filename( pythonfile, editorwindow) if current_editor is None: # -- Not a valid filename: if not os.path.isfile(filename): continue # -- current_es = editor.get_current_editorstack(editorwindow) # Creating the editor widget in the first editorstack (the one # that can't be destroyed), then cloning this editor widget in # all other editorstacks: finfo, newname = self.load_and_translate( filename, pythonfile, editor) finfo.path = editor.main.get_spyder_pythonpath() editor._clone_file_everywhere(finfo) current_editor = current_es.set_current_filename(newname) current_es.analyze_script() if goto is not None: # 'word' is assumed to be None as well current_editor.go_to_line(goto[index], word=word) position = current_editor.get_position('cursor') editor.cursor_moved(filename0, position0, filename, position) if (current_editor is not None): current_editor.clearFocus() current_editor.setFocus() current_editor.window().raise_() if processevents: QApplication.processEvents()
class VMainWindow(VMainWindowBaseClass, Ui_VMainWindowClass): # str, DataFrame, DataType data_selected = Signal(str, object, object) predicted_data_selected = Signal(dict) ground_truth_data_selected = Signal(dict) image_data_selected = Signal([str, list], [str]) file_loaded = Signal(object) def __init__(self): super(VMainWindow, self).__init__() self.setupUi(self) self._widget_setup() self._signals_setup() def __enter__(self): return self def __exit__(self, *args, **kwargs): try: self.controller.cleanup() except AttributeError: pass def _widget_setup(self): self._error_dialog = VErrorMessageBox(self) self._file_dialog = QFileDialog(self, self.tr('Open File'), '') self._file_dialog.setOption(QFileDialog.DontUseNativeDialog) # type(self.marker_options_groupbox) -> widgets.VMarkerOptionsGroupBox self.marker_options_groupbox.add_widget( 'Predicted', DataType.PREDICTED) self.marker_options_groupbox.add_widget( 'Ground Truth', DataType.GROUND_TRUTH) shapes = (Shape.CIRCLE, Shape.DIAMOND) icons = (QIcon(r':/circle'), QIcon(r':/diamond')) for widget in self.marker_options_groupbox.widgets.values(): for icon, shape in zip(icons, shapes): widget.add_marker_shape(shape, icon) scene = VGraphicsScene() self.graphics_view.setScene(scene) self.controller = Controller(scene, self.tables_tab_widget, self.marker_options_groupbox) def _signals_setup(self) -> None: self.action_open_ground_truth.triggered.connect( lambda: self.open(DataType.GROUND_TRUTH)) self.action_open_predicted.triggered.connect( lambda: self.open(DataType.PREDICTED)) self.action_open_image.triggered.connect( lambda: self.open(DataType.IMAGE)) self.graphics_view_scrollbar.value_changed[int].connect( self.controller.set_index) self.file_loaded[object].connect(self.marker_options_groupbox.enable) self.file_loaded[object].connect( lambda d: self.menu_open_data.setEnabled(True) if d & DataType.IMAGE else None) def _parse_filename(self, filelist: Sequence[str], dtype: DataType) -> str: """ Checks for errors in the list of filenames, i.e if list is empty, or if list has more than one filename. If the list passes the checks, we proceed to load the file. For now, we reject TIFF files because loading TIFF images is not implemented. """ def create_error_dialog(message): self._error_dialog.message = message self._error_dialog.exec_() if len(filelist) > 1: return create_error_dialog( '{} files were selected '.format(len(filelist)) + 'but we can only load one file at a time.') elif len(filelist) == 0: return create_error_dialog('No files were selected.') else: filename = filelist[0] # temporary to reject loaded tif images because loading them # hasn't been implemented yet print('***parsing filename***') filename_ext = splitext(filename)[-1] if filename_ext in EXTENSIONS[DataType.TIFF_IMAGE][0]: create_error_dialog('tiff files not yet supported.') return '' else: return filename def open(self, dtype: DataType) -> None: """ Opens a QDialog in which the user selects an HDF5 or TIFF file. """ # we must first create a properly-formated regexp string for the # 'filter' argument of the 'setNameFilter' method in our already- # instantiated but not shown QDialog. extensions = OrderedDict(zip(FILETYPES[dtype], EXTENSIONS[dtype])) ext = [[''] + list(ext) for ext in extensions.values()] extlist = [self.tr(k) + " (" + ' *'.join(e) + ")" for k, e in zip(extensions, ext)] filter_ = ';;'.join(extlist) # example filter_ string: # Tiff Files (*.tif, *.tiff, *.ome.tif);;HDF5 Files (*.h5, *.hdf5, *.hf5, *.hd5) self._file_dialog.setNameFilter(filter_) # closing the QDialog returns an enum, either "Accepted" or "Rejected" # depending on whether the "Ok" or "Cancel" button was pressed, # respectively result = self._file_dialog.exec_() if result == QFileDialog.Accepted: filename = self._parse_filename( self._file_dialog.selectedFiles(), dtype) if filename: self.open_inspection_widget(filename, dtype) def open_inspection_widget(self, filename: str, dtype: DataType): list_widget_columns = ['name', 'directory'] ground_truth_titles = OrderedDict( [('Ground Truth Coordinates', list_widget_columns)]) predicted_titles = OrderedDict( [('Predicted Coordinates', list_widget_columns), ('Probabilities', list_widget_columns)]) image_titles = OrderedDict( [('Images', list_widget_columns)]) list_widget_args = EnumDict([ (DataType.GROUND_TRUTH, ground_truth_titles), (DataType.PREDICTED, predicted_titles), (DataType.HDF_IMAGE, image_titles)]) args = list_widget_args[dtype][0] dialog = make_dialog(filename, args, dtype) result = dialog.exec_() if result == QFileDialog.Accepted: self.load(filename, dtype, dialog.get_data('directory')) def load(self, filename: str, dtype: DataType, handles: DataFrame): if dtype & DataType.HDF_IMAGE: req = HDF5Request1D(filename, handles, axis=0) self.graphics_view_scrollbar.setEnabled(True) elif dtype & DataType.DATA: req = HDF5Request2D(filename, handles) else: raise NotImplementedError('Loading {} not yet implemented.'.format(dtype)) print(filename) print(dtype) print(handles) source = HDF5DataSource(filename, req) self.controller.set_datasource(source, dtype) self.graphics_view_scrollbar.setMaximum(len(source) - 1) self.file_loaded.emit(dtype) @Slot() def save(self): pass @Slot() def save_as(self): pass @Slot() def quit(self): sys.exit(0)
class ExportDialog(QDialog): def __init__(self, parent=None): QDialog.__init__(self, parent) self.ui = Ui_Dialog_Export() self.ui.setupUi(self) self._fig = None # setup file types for frmt in IMAGE_FORMATS: self.ui.comboBox_fileType.addItem("{0[1]} (.{0[0]})".format(frmt)) self._file_name_changed() # select the default format # setup directory and dir dialog self._dir_dialog = QFileDialog(self) # self._dir_dialog.setDirectory(os.path.expanduser("~")) self._dir_dialog.setFileMode(QFileDialog.DirectoryOnly) self._dir_dialog.setWindowTitle("Save to ...") self.ui.comboBox_directory.addItem(os.path.expanduser("~")) self.ui.pushButton_browse.clicked.connect(self._browse) self._dir_validator = DirectoryValidator() self.ui.comboBox_directory.lineEdit().setValidator(self._dir_validator) # file name self.ui.comboBox_fileName.currentIndexChanged.connect( self._file_name_changed) # file type self.ui.comboBox_fileType.currentIndexChanged.connect( self._file_type_changed) # cancel button self.ui.pushButton_cancel.clicked.connect(self._cancel_button_clicked) # export button self.ui.pushButton_export.clicked.connect(self._export_button_clicked) # preview button self.ui.pushButton_preview.clicked.connect( self._preview_button_clicked) # dpi self.ui.spinBox_dpi.valueChanged.connect(self._dpi_changed) # inches self.ui.doubleSpinBox_width_inches.valueChanged.connect( self._width_inches_changed) self.ui.doubleSpinBox_height_inches.valueChanged.connect( self._height_inches_changed) # pixels self.ui.spinBox_width_pixels.valueChanged.connect( self._width_pixels_changed) self.ui.spinBox_height_pixels.valueChanged.connect( self._height_pixels_changed) # message box for when the file already exist self._msg_box = QMessageBox(self) self._msg_box.setWindowTitle("Export...") self._msg_box_button_overwrite = self._msg_box.addButton( self.tr("Overwrite"), QMessageBox.AcceptRole) self._msg_box_button_save_as = self._msg_box.addButton( self.tr("Save As"), QMessageBox.ActionRole) self._msg_box_button_cancel = self._msg_box.addButton( QMessageBox.Cancel) self._msg_box.setDefaultButton(self._msg_box_button_save_as) _orientation = ['portrait', 'landscape'] _no_alpha_channel_formats = ('jpg', 'jpeg') # ("png", "gif", "psd") def _dpi_changed(self, dpi): self.ui.doubleSpinBox_height_inches.blockSignals(True) self.ui.doubleSpinBox_width_inches.blockSignals(True) self.ui.spinBox_height_pixels.setValue( self.ui.doubleSpinBox_height_inches.value() * dpi) self.ui.spinBox_width_pixels.setValue( self.ui.doubleSpinBox_width_inches.value() * dpi) self.ui.doubleSpinBox_height_inches.blockSignals(False) self.ui.doubleSpinBox_width_inches.blockSignals(False) def _width_pixels_changed(self, width): self.ui.doubleSpinBox_width_inches.blockSignals(True) new_width_inches = width / float(self.ui.spinBox_dpi.value()) self.ui.doubleSpinBox_width_inches.setValue(new_width_inches) self.ui.doubleSpinBox_width_inches.blockSignals(False) def _height_pixels_changed(self, height): self.ui.doubleSpinBox_height_inches.blockSignals(True) new_height_inches = height / float(self.ui.spinBox_dpi.value()) self.ui.doubleSpinBox_height_inches.setValue(new_height_inches) self.ui.doubleSpinBox_height_inches.blockSignals(False) def _width_inches_changed(self, width): self.ui.spinBox_width_pixels.blockSignals(True) self.ui.spinBox_width_pixels.setValue(width * self.ui.spinBox_dpi.value()) self.ui.spinBox_width_pixels.blockSignals(False) def _height_inches_changed(self, height): self.ui.spinBox_height_pixels.blockSignals(True) self.ui.spinBox_height_pixels.setValue(height * self.ui.spinBox_dpi.value()) self.ui.spinBox_height_pixels.blockSignals(False) def _cancel_button_clicked(self, b): self.reject() def _export_button_clicked(self, b): self.accept() def _preview_button_clicked(self): if self._fig: # set figures self._fig.set_size_inches(self.get_size_inches_width(), self.get_size_inches_height()) params = self.get_savefig_params() self._fig.set_dpi(params['dpi']) self._fig.set_tight_layout(True if params['bbox_inches'] == 'tight' else False) canvas = FigureCanvas(self._fig) canvas.show() # dialog preview_dialog = PreviewDialog(self, self._fig) preview_dialog.exec_() def _file_type_changed(self, *args, **kwargs): index = self.ui.comboBox_fileType.currentIndex() ext, _ = IMAGE_FORMATS[index] filename = str(self.ui.comboBox_fileName.currentText()) filename, _ = os.path.splitext(filename) if ext in self._no_alpha_channel_formats: # enable transparent if the format supports self.ui.checkBox_transparent.setEnabled(False) else: self.ui.checkBox_transparent.setEnabled(True) # update file name filename = "%s.%s" % (filename, ext) index = self.ui.comboBox_fileName.findText(filename) if index == -1: self.ui.comboBox_fileName.addItem(filename) self.ui.comboBox_fileName.setCurrentIndex( index if index >= 0 else self.ui.comboBox_fileName. findText(filename)) def _file_name_changed(self, *args, **kwargs): filename = str(self.ui.comboBox_fileName.currentText()) filename, extension = os.path.splitext(filename) extension = extension[1:] # get ride of . # check if the extension is supported index = [ i for i, (ext, dsc) in enumerate(IMAGE_FORMATS) if ext == extension ] if index: self.ui.comboBox_fileType.setCurrentIndex(index[0]) elif extension: # no extension pass else: # extension not supported: pass def _browse(self, *args, **kwargs): if self._dir_dialog.exec_() == QDialog.Accepted: dirs = self._dir_dialog.selectedFiles( ) # behave differently in pyqt4 and pyqt5 directory = str(dirs[0] if dirs else self._dir_dialog.directory(). absolutePath()) # this makes the behave the same # update directory index = self.ui.comboBox_directory.findText(directory) if index == -1: self.ui.comboBox_directory.addItem(directory) self.ui.comboBox_directory.setCurrentIndex( index if index >= 0 else self.ui.comboBox_directory. findText(directory)) def export_to_file(self, fig): self._fig = fig respawn = True while respawn: respawn = False self.ui.spinBox_dpi.setValue(fig.get_dpi()) self.ui.doubleSpinBox_width_inches.setValue(fig.get_figwidth()) self.ui.doubleSpinBox_height_inches.setValue(fig.get_figheight()) response = self.exec_() if response == QDialog.Accepted: # saving files fname = self.get_save_file_name() if os.path.exists(fname): new_name = generate_unique_file_name(fname) self._show_file_exist_message(fname, new_name) if self._msg_box.clickedButton( ) == self._msg_box_button_cancel: respawn = True continue elif self._msg_box.clickedButton( ) == self._msg_box_button_save_as: fname = new_name # save_as else: pass # use the original name to overwrite params = self.get_savefig_params() # change size fig.set_size_inches(self.get_size_inches_width(), self.get_size_inches_height()) try: fig.savefig(fname, **params) except IOError as err: if 'RGBA' in err.message: # if the problem is RGBA as the alpha channel is not supported in the selected format # save to png then save as basename = os.path.basename(fname) tmp_dir = tempfile.gettempdir() filename, ext = os.path.splitext(basename) png_file = filename + ".png" final_format = params['format'] params['format'] = 'png' new_fname = os.path.join(tmp_dir, png_file) fig.savefig(new_fname, **params) with Image.open(new_fname) as im: rgb_im = im.convert('RGB') # make sure the fname is ended with the right extension fname, _ = os.path.splitext(fname) fname += "." + final_format rgb_im.save(fname) else: raise err if self.ui.checkBox_open_after_export.isChecked(): # open with the system default application, this should work on all platforms webbrowser.open(fname) return fname # elif response == QtGu def get_size_inches_width(self): return self.ui.doubleSpinBox_width_inches.value() def get_size_inches_height(self): return self.ui.doubleSpinBox_height_inches.value() def _show_file_exist_message(self, fname, new_name): self._msg_box.setText( "<p>File \"{0}\" already exists. Do you want to overwrite the existing, or save to \"{1}\" instead?<\p>" .format(fname, new_name)) self._msg_box.exec_() def get_save_file_name(self): name = os.path.join(str(self.ui.comboBox_directory.currentText()), str(self.ui.comboBox_fileName.currentText())) return os.path.normpath(name) def get_savefig_params(self): params = { 'dpi': self.ui.spinBox_dpi.value(), 'orientation': self.get_orientation(), 'format': self.get_file_format()[0], 'transparent': self.get_transparent(), 'bbox_inches': self.get_bbox_inches() } return params def get_transparent(self): return self.ui.checkBox_transparent.isEnabled( ) and self.ui.checkBox_transparent.isChecked() def get_file_format(self): return IMAGE_FORMATS[self.ui.comboBox_fileType.currentIndex()] def get_bbox_inches(self): return 'tight' if self.ui.checkBox_tightBbox.isChecked() else None def get_orientation(self): return self._orientation[self.ui.comboBox_orientation.currentIndex()] def keyPressEvent(self, event): """Capture and ignore all key press events. This is used so that return key event does not trigger any button from the dialog. We need to allow the return key to be used in filters in the widget.""" if event.key() == QtCore.Qt.Key_Escape: # call reject if Escape is pressed. self.reject() pass
class ExportDialogModEm(QWizard): def __init__(self, parent=None): QWizard.__init__(self, parent) self.ui = Ui_Wizard_esport_modem() self.ui.setupUi(self) self._logger = MtPyLog.get_mtpy_logger(self.__class__.__name__) # setup gui # self.setWindowTitle("ModEM input file generator") # add math label self._math_label_sign_impedances = MathTextLabel( self, self._math_label_sign_text.format( "+" if self.ui.radioButton_impedance_sign_plus.isChecked() else "-" ) ) self.ui.horizontalLayout_sign_impedance.addWidget(self._math_label_sign_impedances) self._math_label_sign_vertical = MathTextLabel( self, self._math_label_sign_text.format( "+" if self.ui.radioButton_vertical_sign_plus.isChecked() else "-" ) ) self.ui.horizontalLayout_sign_vertical.addWidget(self._math_label_sign_vertical) # add math formulae of each error type self._math_label_elbert = MathTextLabel( self, "$E_{egbert}=e_Z\\times |Z_{xy}\\times Z_{yx}|^\\frac{1}{2}$", ) self.ui.verticalLayout_error_types.addWidget(self._math_label_elbert) self._math_label_mean = MathTextLabel(self, "$E_{mean} = e_Z\\times mean(|Z_{xy}, Z_{yx}|)$") self._math_label_mean.setHidden(True) self.ui.verticalLayout_error_types.addWidget(self._math_label_mean) self._math_label_eigen = MathTextLabel(self, "$E_{eigen} = e_Z\\times eigenvalues(Z)$") self._math_label_eigen.setHidden(True) self.ui.verticalLayout_error_types.addWidget(self._math_label_eigen) self._math_label_median = MathTextLabel(self, "$E_{median} = e_Z\\times median(|Z_{xx},Z_{xy},Z_{yx},Z_{yy}|)$") self._math_label_median.setHidden(True) self.ui.verticalLayout_error_types.addWidget(self._math_label_median) self._math_label_error_type_note = MathTextLabel(self, "where $E$ is the error and $e$ is the error value (z).") self.ui.verticalLayout_error_types.addWidget(self._math_label_error_type_note) # add period selection self._period_select_ui = FrequencySelection( self.ui.wizardPage_period, show_period=True, show_frequency=False, allow_range_select=True, select_multiple=True ) self._period_select_ui.ui.checkBox_show_existing.setChecked(True) self._period_select_ui.setEnabled(False) self._period_select_ui.setHidden(True) self.ui.wizardPage_period.layout().addWidget(self._period_select_ui) self._period_select_from_file_ui = FrequencySelectionFromFile(self.ui.wizardPage_period) self._period_select_from_file_ui.setEnabled(False) self._period_select_from_file_ui.setHidden(True) self.ui.wizardPage_period.layout().addWidget(self._period_select_from_file_ui) # add rotation self._rotation_ui = Rotation(self.ui.wizardPage_data) self._rotation_ui.setTitle('Data Rotation Angle') self.ui.horizontalLayout_data.addWidget(self._rotation_ui) self._mesh_rotation_ui = Rotation(self.ui.wizardPage_mesh) self._mesh_rotation_ui.setTitle('Mesh Rotation Angle') self.ui.gridLayout_mesh.addWidget(self._mesh_rotation_ui) # hide error percents self._component_error_type_z_changed() # hide bottom in vertical mesh as it is not used in mesh gen self.ui.doubleSpinBox_bottom.hide() self.ui.label_bottom.hide() # epsg self.ui.comboBox_epsg.addItems( [str(epsg) for epsg in sorted(epsg_dict.keys())] ) # set validators self._double_validator = QDoubleValidator(-np.inf, np.inf, 1000) self._double_validator.setNotation(QDoubleValidator.ScientificNotation) self.ui.lineEdit_resistivity_init.setValidator(self._double_validator) self.ui.lineEdit_resistivity_air.setValidator(self._double_validator) self.ui.lineEdit_resistivity_sea.setValidator(self._double_validator) self._file_validator = FileValidator() self.ui.comboBox_topography_file.lineEdit().setValidator(self._file_validator) self.ui.comboBox_topography_file.lineEdit().setMaxLength(256) self._dir_validator = DirectoryValidator() self.ui.comboBox_directory.lineEdit().setValidator(self._dir_validator) # setup directory and dir dialog self._dir_dialog = QFileDialog(self) # self._dir_dialog.setDirectory(os.path.expanduser("~")) self.ui.comboBox_directory.addItem(os.path.expanduser("~")) self._update_full_output() # set maximum # self.ui.spinBox_cell_num_ew.setMaximum(0xFFFFFFFF) # self.ui.spinBox_cell_num_ns.setMaximum(0xFFFFFFFF) # tooltip for error types for index, tooltip in enumerate(self._error_type_z_tool_tip): self.ui.comboBox_error_type_z.setItemData(index, tooltip, QtCore.Qt.ToolTipRole) self.ui.comboBox_error_type_zxx.setItemData(index, tooltip, QtCore.Qt.ToolTipRole) self.ui.comboBox_error_type_zxy.setItemData(index, tooltip, QtCore.Qt.ToolTipRole) self.ui.comboBox_error_type_zyx.setItemData(index, tooltip, QtCore.Qt.ToolTipRole) self.ui.comboBox_error_type_zyy.setItemData(index, tooltip, QtCore.Qt.ToolTipRole) # hide parts self.ui.groupBox_component_error_types.setHidden(True) self.ui.label_component_error_types.setHidden(True) # connect signals self.ui.radioButton_impedance_sign_plus.toggled.connect( lambda is_checked: self._math_label_sign_impedances.set_math_text( self._math_label_sign_text.format("+" if is_checked else "-")) ) self.ui.radioButton_vertical_sign_plus.toggled.connect( lambda is_checked: self._math_label_sign_vertical.set_math_text( self._math_label_sign_text.format("+" if is_checked else "-") ) ) self.ui.radioButton_impedance_full.toggled.connect(self._impedance_full_toggled) self.ui.radioButton_impedance_off_diagonal.toggled.connect(self._impedance_off_diagonal_toggled) self.ui.radioButton_impedance_none.toggled.connect(self._impedance_none_toggled) self.ui.radioButton_vertical_full.toggled.connect(self._vertical_full_toggled) self.ui.comboBox_error_type_z.currentIndexChanged.connect(self._error_type_z_changed) for component in self._impedance_components: combobox = getattr(self.ui, 'comboBox_error_type_{}'.format(component)) checkbox = getattr(self.ui, 'checkBox_{}'.format(component)) combobox.currentIndexChanged.connect(self._component_error_type_z_changed) checkbox.toggled.connect(self._error_component_checkbox_toggled(combobox)) self.ui.comboBox_output_name.currentIndexChanged.connect(self._update_full_output) self.ui.comboBox_output_name.lineEdit().editingFinished.connect(self._output_name_changed) self.ui.comboBox_output_name.editTextChanged.connect(self._update_full_output) self.ui.comboBox_directory.currentIndexChanged.connect(self._update_full_output) self.ui.comboBox_directory.lineEdit().editingFinished.connect(self._output_dir_changed) self.ui.comboBox_directory.editTextChanged.connect(self._update_full_output) self.ui.pushButton_browse.clicked.connect(self._browse) # self.ui.doubleSpinBox_target_depth.valueChanged.connect(self._target_depth_changed) self.ui.doubleSpinBox_target_depth.lineEdit().editingFinished.connect(self._target_depth_changed) self.ui.doubleSpinBox_bottom.lineEdit().editingFinished.connect(self._bottom_changed) # self.ui.doubleSpinBox_bottom.valueChanged.connect(self._bottom_changed) # self.ui.comboBox_topography_file.currentIndexChanged.connect() self.ui.comboBox_topography_file.lineEdit().editingFinished.connect( self._topography_file_changed ) self.ui.pushButton_browse_topography_file.clicked.connect(self._browse_topography_file) self.ui.pushButton_test.clicked.connect(self._test_button_clicked) self.ui.checkBox_cell_num_ew.stateChanged.connect( lambda p_int: self.ui.spinBox_cell_num_ew.setEnabled(p_int != 0) ) self.ui.checkBox_cell_num_ns.stateChanged.connect( lambda p_int: self.ui.spinBox_cell_num_ns.setEnabled(p_int != 0) ) self.ui.checkBox_component_error_types.setEnabled(False) # disabled due to missing implementations todo implement this option in modem.Data self.ui.checkBox_component_error_types.toggled.connect(self._component_error_type_toggled) self.ui.radioButton_select_period_percent.toggled.connect( lambda checked: self.ui.doubleSpinBox_select_period_percent.setEnabled(checked)) self.ui.radioButton_select_period.toggled.connect( lambda checked: self._period_select_ui.setEnabled(checked)) self.ui.radioButton_select_period.toggled.connect( lambda checked: self._period_select_ui.setHidden(not checked)) self.ui.radioButton_select_by_file.toggled.connect( lambda checked: self._period_select_from_file_ui.setEnabled(checked)) self.ui.radioButton_select_by_file.toggled.connect( lambda checked: self._period_select_from_file_ui.setHidden(not checked)) # register fields self.ui.wizardPage_output.registerField('output_path*', self.ui.lineEdit_full_output) self.ui.wizardPage_topography.registerField('topography_file*', self.ui.comboBox_topography_file) self.ui.wizardPage_topography.registerField('sea_resistivity', self.ui.lineEdit_resistivity_sea) self.ui.wizardPage_topography.registerField('air_resistivity', self.ui.lineEdit_resistivity_air) # attribute self._mt_objs = None self._progress_bar = ProgressBar() _impedance_components = ['zxx', 'zxy', 'zyx', 'zyy'] _vertical_components = ['tx', 'ty'] _math_label_sign_text = "$exp({}i\\omega t)$" _error_type_z = [ 'egbert', # 0 'mean_od', # 1 'eigen', # 2 'median', # 3 ] _error_type_z_tool_tip = [ 'sets error to the value of Error Egbert * sqrt(abs(zxy*zyx), see Egbert & Kelbert', 'sets error to error_value_z * mean([Zxy, Zyx]) (non zeros)', 'sets error to error_value_z * eigenvalues(Z[ii])', 'sets error to error_value_z * median([Zxx, Zxy, Zyx, Zyy]) (non zeros)' ] _error_type_tipper = [ 'abs', 'floor' ] def _component_error_type_toggled(self, is_checked): self.ui.label_component_error_types.setHidden(not is_checked) self.ui.groupBox_component_error_types.setHidden(not is_checked) def _target_depth_changed(self, *args): value = self.ui.doubleSpinBox_target_depth.value() # target depth has too be at least as deep as the bottom if self.ui.doubleSpinBox_bottom.value() < value: self.ui.doubleSpinBox_bottom.setValue(value) def _bottom_changed(self, *args): value = self.ui.doubleSpinBox_bottom.value() # bottom as to be at least at least as deep as the target depth if self.ui.doubleSpinBox_target_depth.value() > value: self.ui.doubleSpinBox_target_depth.setValue(value) def _impedance_full_toggled(self, checked): if checked: for comp in self._impedance_components: checkbox = getattr(self.ui, 'checkBox_{}'.format(comp)) checkbox.setEnabled(True) self.ui.radioButton_vertical_none.setEnabled(True) self.ui.groupBox_sign_impedance.setEnabled(True) def _impedance_off_diagonal_toggled(self, checked): if checked: for comp in self._impedance_components: checkbox = getattr(self.ui, 'checkBox_{}'.format(comp)) checkbox.setEnabled(comp == 'zxy' or comp == 'zyx') self.ui.radioButton_vertical_none.setEnabled(True) self.ui.groupBox_sign_impedance.setEnabled(True) def _impedance_none_toggled(self, checked): if checked: for comp in self._impedance_components: checkbox = getattr(self.ui, 'checkBox_{}'.format(comp)) checkbox.setEnabled(False) self.ui.radioButton_vertical_none.setEnabled(False) self.ui.groupBox_sign_impedance.setEnabled(False) def _vertical_full_toggled(self, checked): self.ui.doubleSpinBox_error_value_tipper.setEnabled(checked) self.ui.radioButton_impedance_none.setEnabled(checked) self.ui.groupBox_sign_vertical.setEnabled(checked) def _error_component_checkbox_toggled(self, combobox): def _checkbox_toggled(checked): combobox.setEnabled(checked) self._component_error_type_z_changed() return _checkbox_toggled def _component_error_type_z_changed(self, error_type_index=-1): # types = {self.ui.comboBox_error_type_z.currentIndex()} # for component in self._impedance_components: # combobox = getattr(self.ui, 'comboBox_error_type_{}'.format(component)) # if combobox.isEnabled(): # types.add(combobox.currentIndex()) # # hidden = bool(0 not in types) # self.ui.label_error_floor.setHidden(hidden) # self.ui.doubleSpinBox_error_floor.setHidden(hidden) # hidden = bool(2 not in types and 3 not in types) # self.ui.label_error_egbert.setHidden(hidden) # self.ui.doubleSpinBox_error_egbert.setHidden(hidden) # self._math_label_elbert.setHidden(hidden) # hidden = bool(1 not in types) # self.ui.label_error_value.setHidden(hidden) # self.ui.doubleSpinBox_error_value.setHidden(hidden) pass # todo re-enable after the sub-type for each component is implemented def _error_type_z_changed(self, error_type_index): # sync the component error types with default # for component in self._impedance_components: # combobox = getattr(self.ui, 'comboBox_error_type_{}'.format(component)) # if not combobox.isEnabled(): # combobox.blockSignals(True) # combobox.setCurrentIndex(error_type_index) # combobox.blockSignals(False) # self._component_error_type_z_changed() pass # todo re-enable after the sub-type for each component is implemented self._math_label_elbert.setHidden(error_type_index != 0) self._math_label_mean.setHidden(error_type_index != 1) self._math_label_eigen.setHidden(error_type_index != 2) self._math_label_median.setHidden(error_type_index != 3) def _output_name_changed(self, *args, **kwargs): output_name = str(self.ui.comboBox_output_name.currentText()) index = self.ui.comboBox_output_name.findText(output_name) if index == -1: self.ui.comboBox_output_name.addItem(output_name) self.ui.comboBox_output_name.setCurrentIndex( index if index >= 0 else self.ui.comboBox_output_name.findText(output_name) ) def _output_dir_changed(self, *args, **kwargs): directory = str(self.ui.comboBox_directory.currentText()) directory = os.path.normpath(directory) # update directory index = self.ui.comboBox_directory.findText(directory) if index == -1: self.ui.comboBox_directory.addItem(directory) self.ui.comboBox_directory.setCurrentIndex(index if index >= 0 else self.ui.comboBox_directory.findText(directory)) def _update_full_output(self, *args, **kwargs): directory = str(self.ui.comboBox_directory.currentText()) output_name = str(self.ui.comboBox_output_name.currentText()) full_output = os.path.normpath(os.path.join(directory, output_name)) self.ui.lineEdit_full_output.setText(full_output) def _browse(self, *args, **kwargs): self._dir_dialog.setFileMode(QFileDialog.DirectoryOnly) self._dir_dialog.setWindowTitle("Save to ...") if self._dir_dialog.exec_() == QDialog.Accepted: directory = str(self._dir_dialog.selectedFiles()[0]) self.ui.comboBox_directory.setEditText(directory) self._output_dir_changed() def _topography_file_changed(self, *args, **kwargs): topo_file = str(self.ui.comboBox_topography_file.currentText()) topo_file = os.path.normpath(topo_file) # update index = self.ui.comboBox_topography_file.findText(topo_file) if index == -1: self.ui.comboBox_topography_file.addItem(topo_file) self.ui.comboBox_topography_file.setCurrentIndex( index if index >= 0 else self.ui.comboBox_topography_file.findText(topo_file) ) def _browse_topography_file(self, *args, **kwargs): self._dir_dialog.setFileMode(QFileDialog.AnyFile) self._dir_dialog.setWindowTitle("Find Topography File...") if self._dir_dialog.exec_() == QDialog.Accepted: file_path = str(self._dir_dialog.selectedFiles()[0]) self.ui.comboBox_topography_file.setEditText(file_path) self._topography_file_changed() def _test_button_clicked(self, *args, **kwargs): self.export_data(True) def set_data(self, mt_objs): self._mt_objs = mt_objs self._period_select_ui.set_data(self._mt_objs) self._period_select_from_file_ui.set_data(self._mt_objs) self.ui.listWidget_edi_files.clear() for mt_obj in mt_objs: self.ui.listWidget_edi_files.addItem("{mt.station} ({mt.fn})".format(mt=mt_obj)) def get_inversion_mode(self): if self.ui.radioButton_impedance_full.isChecked(): return '1' if self.ui.radioButton_vertical_full.isChecked() else '2' elif self.ui.radioButton_impedance_off_diagonal.isChecked(): return '3' if self.ui.radioButton_vertical_full.isChecked() else '4' else: return '5' def _get_error_type_z(self): type = self._error_type_z[self.ui.comboBox_error_type_z.currentIndex()] if self.ui.checkBox_error_type_z_floor.isChecked(): type += "_floor" return type def get_data_kwargs(self): kwargs = { 'error_type_z': self._get_error_type_z(), 'error_value_z': self.ui.doubleSpinBox_error_value_z.value(), 'error_type_tipper': self._error_type_tipper[self.ui.comboBox_error_type_tipper.currentIndex()], 'error_value_tipper': self.ui.doubleSpinBox_error_value_tipper.value() / 100., 'save_path': self.get_save_file_path(), 'format': '1' if self.ui.radioButton_format_1.isChecked() else '2', 'rotation_angle': self._rotation_ui.get_rotation_in_degree(), 'model_epsg': self.get_epsg(), 'inv_mode': self.get_inversion_mode() } # comp_error_type if any( [getattr(self.ui, 'comboBox_error_type_{}'.format(component)).isEnabled() for component in self._impedance_components] ): kwargs['comp_error_type'] = dict( [ ( component, self._error_type_z[ getattr(self.ui, 'comboBox_error_type_{}'.format(component)).currentIndex() ] ) for component in self._impedance_components if getattr(self.ui, 'comboBox_error_type_{}'.format(component)).isEnabled() ] ) # wave signs if self.ui.groupBox_sign_impedance.isEnabled(): kwargs['wave_sign_impedance'] = '+' if self.ui.radioButton_impedance_sign_plus.isChecked() \ else '-' if self.ui.groupBox_sign_vertical.isEnabled(): kwargs['wave_sign_tipper'] = '+' if self.ui.radioButton_vertical_sign_plus.isChecked() \ else '-' # units kwargs['units'] = '[mV/km]/[nT]' if self.ui.radioButton_unit_mvkmnt.isChecked() \ else '[V/m]/[T]' if self.ui.radioButton_unit_vmt.isChecked() \ else 'Ohm' return kwargs def get_model_kwargs(self): kwargs = { 'save_path': self.get_save_file_path(), 'cell_size_east': self.ui.doubleSpinBox_cell_size_east.value(), 'cell_size_north': self.ui.doubleSpinBox_cell_szie_north.value(), 'pad_east': self.ui.spinBox_pad_east.value(), 'pad_north': self.ui.spinBox_pad_north.value(), 'pad_z': self.ui.spinBox_pad_z.value(), 'pad_stretch_h': self.ui.doubleSpinBox_pad_stretch_h.value(), 'pad_stretch_v': self.ui.doubleSpinBox_pad_stretch_v.value(), 'z1_layer': self.ui.doubleSpinBox_z1_thickness.value(), 'z_target_depth': self.ui.doubleSpinBox_target_depth.value(), 'z_bottom': self.ui.doubleSpinBox_bottom.value(), 'n_layers': self.ui.spinBox_num_layers.value(), 'n_air_layers': self.ui.spinBox_num_air_layers.value(), 'res_model': self.get_initial_resistivity(), 'mesh_rotation_angle': self._mesh_rotation_ui.get_rotation_in_degree(), 'cell_number_ew': self.ui.spinBox_cell_num_ew.value() if self.ui.checkBox_cell_num_ew.isChecked() else None, 'cell_number_ns': self.ui.spinBox_cell_num_ns.value() if self.ui.checkBox_cell_num_ns.isChecked() else None } return kwargs def get_save_file_path(self): return str(self.ui.lineEdit_full_output.text()) def get_initial_resistivity(self): return float(str(self.ui.lineEdit_resistivity_init.text())) def get_air_resistivity(self): return float(str(self.ui.lineEdit_resistivity_air.text())) def get_sea_resistivity(self): return float(str(self.ui.lineEdit_resistivity_sea.text())) def get_topography_2_mesh_args(self): kwargs = { 'topography_file': str(self.ui.comboBox_topography_file.currentText()), 'topography_array': None, 'interp_method': 'nearest' if self.ui.radioButton_interpo_method_nearest.isChecked() else 'linear' if self.ui.radioButton_interpo_method_linear.isChecked() else 'cubic', 'air_resistivity': self.get_air_resistivity(), 'sea_resistivity': self.get_sea_resistivity() } return kwargs def get_covariance_kwargs(self): kwargs = { 'smoothing_east': self.ui.doubleSpinBox_smoothing_east.value(), 'smoothing_north': self.ui.doubleSpinBox_smoothing_north.value(), 'smoothing_z': self.ui.doubleSpinBox_smoothing_z.value(), 'smoothing_num': self.ui.spinBox_smoothing_number.value(), 'save_path': self.get_save_file_path() } return kwargs def get_select_period_kwargs(self): period_list = None if self.ui.radioButton_select_period.isChecked(): period_list = self._period_select_ui.get_frequencies() elif self.ui.radioButton_select_by_file.isChecked(): period_list = self._period_select_from_file_ui.get_selected_periods() elif self.ui.radioButton_select_by_decade.isChecked(): period_list = [] unique_periods = set() for mt in self._mt_objs: unique_periods.update(1. /mt.Z.freq) unique_periods = np.array(sorted(list(unique_periods), reverse=True)) num = self.ui.spinBox_num_per_decade.value() decade_min = 10. ** int(np.log(unique_periods[0])) decade_max = decade_min * 10. while unique_periods[-1] < decade_min: # todo this block of code can be more efficient indexes = np.where((unique_periods <= decade_max) & (unique_periods > decade_min))[0] if len(indexes) < num: self._logger.warn("Selecting {} periods per decade, but there is only {} in [{},{}]".format(num, len(indexes), decade_min, decade_max)) else: # sample n np.random.shuffle(indexes) indexes = indexes[0:num] period_list += list(unique_periods[indexes]) decade_max = decade_min decade_min /= 10. kwargs = { 'period_list': period_list, 'percentage': self.ui.doubleSpinBox_select_period_percent.value() } return kwargs def get_epsg(self): return int(str(self.ui.comboBox_epsg.currentText())) def export_data(self, test=False): if self._mt_objs is None: return # self._progress_bar.progressbar.setRange(0, 1) self._progress_bar.progressbar.setRange(0, 0) self._progress_bar.onStart() self._update_full_output() worker = ModEMWorker( self, show=test, edi_list=[mt_obj.fn for mt_obj in self._mt_objs], select_period_kwargs=self.get_select_period_kwargs(), data_kwargs=self.get_data_kwargs(), mesh_kwargs=self.get_model_kwargs(), topo_args=self.get_topography_2_mesh_args(), covariance_kwargs=self.get_covariance_kwargs() ) if test: worker.figure_updated.connect(self._show_figure) self._progress_bar.setWindowTitle( 'Testing ModEM Data...' if test else 'Generating ModEM Data...' ) # worker.started.connect(self._progress_bar.onStart) # worker.finished.connect(self._progress_bar.onFinished) worker.status_updated.connect(self._update_progress_bar_text) worker.export_error.connect(self._export_error) # self._plot_opened.connect(worker.pause) # worker.start() # worker.wait() worker.run() # clean up worker.deleteLater() if self.ui.checkBox_open_output_dir.isChecked(): webbrowser.open(self.get_save_file_path()) self._progress_bar.onFinished() self._progress_bar.progressbar.setRange(0, 1) # _plot_opened = pyqtSignal(bool) def _update_progress_bar_text(self, text): self._progress_bar.incrementValue() self._progress_bar.updateIndicatorText(text) def _show_figure(self, string, fig): # self._plot_opened.emit(True) # print "plot_opened" preview_dialog = PreviewDialog(None, fig) preview_dialog.setWindowTitle(string) preview_dialog.exec_() preview_dialog.deleteLater() # self._plot_opened.emit(False) def _export_error(self, message): QMessageBox.critical(self, 'Export Error', message, QMessageBox.Close)
def openDirDialog(self): dialog = QFileDialog(self) dialog.setFileMode(QFileDialog.DirectoryOnly) if dialog.exec_(): directory = dialog.selectedFiles()[0] self.openDir(directory)