def test_ome_read(self, data_test_dir): # error in tifffile image1 = TiffImageReader.read_image(os.path.join(data_test_dir, "test_lsm2.tif")) image2 = TiffImageReader.read_image(os.path.join(data_test_dir, "test_lsm.tif")) data = np.load(os.path.join(data_test_dir, "test_lsm.npy")) assert np.all(image1.get_data() == data) assert np.all(image2.get_data() == data) assert np.all(image1.get_data() == image2.get_data())
def select_window(args): if args.gui == "roi_analysis" or args.mf: from PartSeg import plugins plugins.register() from PartSeg._roi_analysis.main_window import MainWindow title = f"{APP_NAME} {ANALYSIS_NAME}" if args.image: image = TiffImageReader.read_image(args.image, args.mask) MainWindow = partial(MainWindow, initial_image=image) wind = MainWindow(title=title) if args.batch: wind.main_menu.batch_window() elif args.gui == "roi_mask": from PartSeg import plugins plugins.register() from PartSeg._roi_mask.main_window import MainWindow title = f"{APP_NAME} {MASK_NAME}" if args.image: image = TiffImageReader.read_image(args.image) MainWindow = partial(MainWindow, initial_image=image) wind = MainWindow(title=title) else: from PartSeg._launcher.main_window import MainWindow title = f"{APP_NAME} Launcher" wind = MainWindow(title=title) return wind
def test_read_with_mask(self, data_test_dir): image = TiffImageReader.read_image( os.path.join(data_test_dir, "stack1_components", "stack1_component1.tif"), os.path.join(data_test_dir, "stack1_components", "stack1_component1_mask.tif"), ) assert isinstance(image, Image) with pytest.raises(ValueError): TiffImageReader.read_image( os.path.join(data_test_dir, "stack1_components", "stack1_component1.tif"), os.path.join(data_test_dir, "stack1_components", "stack1_component2_mask.tif"), )
def run(self): if self.module != "": from .. import plugins plugins.register() main_window_module = importlib.import_module(self.module) main_window: BaseMainWindow = main_window_module.MainWindow settings: BaseSettings = main_window.get_setting_class()(main_window_module.CONFIG_FOLDER) self.errors = settings.load() reader = TiffImageReader() im = reader.read(main_window.initial_image_path) im.file_path = "" self.result = partial(main_window, settings=settings, initial_image=im)
class ImageReaderThread(ProgressTread): """ thread for reading files. Useful for reading from disc """ image_read_finish = Signal(Image) def __init__(self, file_path=None, mask_path=None): super().__init__() self.reader = TiffImageReader(self.info_function) self.file_path = file_path self.mask_path = mask_path self.image = None def set_path(self, file_path, mask_path=None): self.file_path = file_path self.mask_path = mask_path def run(self): if self.file_path is None: return try: self.image = self.reader.read(self.file_path, self.mask_path) self.image_read_finish.emit(self.image) except Exception as e: self.error_signal.emit(e)
def step_load_mask(self, operation: MaskMapper, children: List[CalculationTree]): """ Load mask using mask mapper (mask can be defined with suffix, substitution, or file with mapping saved, then iterate over ``children`` nodes. :param MaskMapper operation: operation to perform :param List[CalculationTree] children: list of nodes to iterate over with applied mask """ mask_path = operation.get_mask_path(self.calculation.file_path) if mask_path == "": raise ValueError("Empty path to mask.") with tifffile.TiffFile(mask_path) as mask_file: mask = mask_file.asarray() mask = TiffImageReader.update_array_shape( mask, mask_file.series[0].axes)[..., 0] mask = (mask > 0).astype(np.uint8) try: mask = self.image.fit_array_to_image(mask)[0] # TODO fix this time bug fix except ValueError: raise ValueError("Mask do not fit to given image") old_mask = self.mask self.mask = mask self.iterate_over(children) self.mask = old_mask
def test_profile_execute(self, data_test_dir): profile_path = os.path.join(data_test_dir, "segment_profile_test.json") # noinspection PyBroadException try: data = UpdateLoadedMetadataAnalysis.load_json_data(profile_path) assert check_loaded_dict(data) except Exception: # pylint: disable=W0703 pytest.fail("Fail in loading profile") return image = TiffImageReader.read_image( os.path.join(data_test_dir, "stack1_components", "stack1_component5.tif"), os.path.join(data_test_dir, "stack1_components", "stack1_component5_mask.tif"), ) val: ROIExtractionProfile for val in data.values(): algorithm: ROIExtractionAlgorithm = analysis_algorithm_dict[ val.algorithm]() algorithm.set_image(image) algorithm.set_mask(image.mask.squeeze()) algorithm.set_parameters(**val.values) result = algorithm.calculation_run(empty) assert np.max(result.roi) == 2
def test_image_view_integration_filter(self, qtbot, tmp_path, filter_value): settings = BaseSettings(tmp_path) ch_property = ChannelProperty(settings, "test") image_view = ImageView(settings, ch_property, "test") # image_view.show() qtbot.addWidget(image_view) qtbot.addWidget(ch_property) image = TiffImageReader.read_image( PartSegData.segmentation_analysis_default_image) with qtbot.waitSignal(image_view.image_added, timeout=10**6): settings.image = image image_view.channel_control.set_active(1) def check_parameters(name, index): return name == "test" and index == 1 if filter_value is NoiseFilterType.No: with qtbot.waitSignal( image_view.channel_control.coloring_update ), qtbot.waitSignal(image_view.channel_control.change_channel, check_params_cb=check_parameters): ch_property.use_filter.setCurrentEnum(NoiseFilterType.Gauss) with qtbot.waitSignal( image_view.channel_control.coloring_update), qtbot.waitSignal( image_view.channel_control.change_channel, check_params_cb=check_parameters): ch_property.use_filter.setCurrentEnum(filter_value) image4 = image_view.viewer_widget.screenshot() assert (filter_value != NoiseFilterType.No and np.any(image4 != 255)) or (filter_value == NoiseFilterType.No and np.any(image4 == 255))
def test_one_file(self, data_test_dir): plan = self.create_calculation_plan() process = CalculationProcess() file_path = os.path.join(data_test_dir, "stack1_components", "stack1_component5.tif") calc = MocksCalculation(file_path) process.calculation = calc process.image = TiffImageReader.read_image(file_path) process.iterate_over(plan.execution_tree) assert len(process.measurement[0]) == 3
def load( cls, load_locations: typing.List[typing.Union[str, BytesIO, Path]], range_changed: typing.Callable[[int, int], typing.Any] = None, step_changed: typing.Callable[[int], typing.Any] = None, metadata: typing.Optional[dict] = None, ) -> typing.Union[ProjectInfoBase, typing.List[ProjectInfoBase]]: image = TiffImageReader.read_image(load_locations[0]) segmentation = image.get_channel(0) return MaskProjectTuple( file_path=load_locations[0], image=None, segmentation=segmentation, segmentation_parameters=defaultdict(lambda: None), )
def test_save(self, tmp_path): data = np.zeros((1, 10, 20, 30, 3), np.uint8) data[..., :10, 0] = 2 data[..., :10, 1] = 20 data[..., :10, 2] = 9 image = self.image_class(data, (10**-6, 10**-6, 10**-6), "", axes_order="TZYXC") mask = np.zeros((10, 20, 30), np.uint8) mask[..., 2:12] = 1 image.set_mask(mask, "ZYX") ImageWriter.save(image, os.path.join(tmp_path, "img.tif")) ImageWriter.save_mask(image, os.path.join(tmp_path, "img_mask.tif")) read_image: Image = TiffImageReader.read_image( os.path.join(tmp_path, "img.tif"), os.path.join(tmp_path, "img_mask.tif")) assert read_image.get_um_spacing() == (1, 1, 1) assert len(read_image.get_ranges()) == 3 assert read_image.get_ranges() == [(0, 2), (0, 20), (0, 9)]
def test_image_view_integration(self, qtbot, tmp_path): settings = BaseSettings(tmp_path) channel_property = ChannelProperty(settings, "test") image_view = ImageView(settings, channel_property, "test") qtbot.addWidget(channel_property) qtbot.addWidget(image_view) color_list = PColormapList(settings, ["test"]) qtbot.addWidget(color_list) image = TiffImageReader.read_image( PartSegData.segmentation_analysis_default_image) with qtbot.wait_signal(image_view.image_added, timeout=10**6): settings.image = image color_list.refresh() assert image_view.channel_control.channels_count == image.channels assert len(color_list.blocked()) == image.channels block_count = 0 for el in settings.colormap_dict.keys(): widget = color_list.get_colormap_widget(el) assert widget.is_checked or el not in starting_colors if not widget.checked.isEnabled(): block_count += 1 assert block_count == image.channels image_view.channel_control.change_selected_color(0, "Grayscale") assert len(color_list.blocked()) == image.channels assert "Grayscale" in color_list.blocked() color_list.refresh() assert color_list.get_colormap_widget( "Grayscale").checked.isEnabled() is False # this lines test if after refresh of widget checkbox stays checkable block_count = 0 for el in settings.colormap_dict.keys(): widget = color_list.get_colormap_widget(el) assert widget.is_checked or el not in starting_colors if not widget.checked.isEnabled(): block_count += 1 assert block_count == image.channels
def main(): if len(sys.argv) > 1 and sys.argv[1] == "_test": _test_imports() return parser = CustomParser("PartSeg") parser.add_argument( "--multiprocessing-fork", dest="mf", action="store_true", help=argparse.SUPPRESS ) # Windows bug fix sp = parser.add_subparsers() sp_a = sp.add_parser("roi_analysis", help="Starts GUI for segmentation analysis") sp_s = sp.add_parser("mask_segmentation", help="Starts GUI for segmentation") parser.set_defaults(gui="launcher") sp_a.set_defaults(gui="roi_analysis") sp_s.set_defaults(gui="roi_mask") sp_a.add_argument("image", nargs="?", help="image to read on begin", default="") sp_a.add_argument("mask", nargs="?", help="mask to read on begin", default=None) sp_a.add_argument("--batch", action="store_true", help=argparse.SUPPRESS) sp_s.add_argument("image", nargs="?", help="image to read on begin", default="") argv = [x for x in sys.argv[1:] if not (x.startswith("parent") or x.startswith("pipe"))] args = parser.parse_args(argv) # print(args) logging.basicConfig(level=logging.INFO) CustomApplication.setAttribute(Qt.AA_EnableHighDpiScaling) my_app = CustomApplication(sys.argv, name="PartSeg", icon=os.path.join(icons_dir, "icon.png")) my_app.check_release() my_app.aboutToQuit.connect(wait_for_workers_to_quit) QFontDatabase.addApplicationFont(os.path.join(font_dir, "Symbola.ttf")) if args.gui == "roi_analysis" or args.mf: from PartSeg import plugins plugins.register() from PartSeg._roi_analysis.main_window import MainWindow title = f"{APP_NAME} {ANALYSIS_NAME}" if args.image: image = TiffImageReader.read_image(args.image, args.mask) MainWindow = partial(MainWindow, initial_image=image) wind = MainWindow(title=title) if args.batch: wind.main_menu.batch_window() elif args.gui == "roi_mask": from PartSeg import plugins plugins.register() from PartSeg._roi_mask.main_window import MainWindow title = f"{APP_NAME} {MASK_NAME}" if args.image: image = TiffImageReader.read_image(args.image) MainWindow = partial(MainWindow, initial_image=image) wind = MainWindow(title=title) else: from PartSeg._launcher.main_window import MainWindow title = f"{APP_NAME} Launcher" wind = MainWindow(title=title) wind.show() rc = my_app.exec_() del wind del my_app sys.exit(rc)
def test_set_spacing(self): reader = TiffImageReader() reader.set_default_spacing((11, 12, 13)) assert reader.default_spacing == (11, 12, 13) reader.set_default_spacing((5, 7)) assert reader.default_spacing == (10 ** -6, 5, 7)
def test_decode_int(self): assert TiffImageReader.decode_int(0) == [0, 0, 0, 0] assert TiffImageReader.decode_int(15) == [0, 0, 0, 15] assert TiffImageReader.decode_int(3 + 7 * 256 + 11 * 256 ** 2 + 13 * 256 ** 3) == [13, 11, 7, 3]
def test_image_view_integration(self, qtbot, tmp_path): settings = BaseSettings(tmp_path) ch_property = ChannelProperty(settings, "test") image_view = ImageView(settings, ch_property, "test") # image_view.show() qtbot.addWidget(image_view) qtbot.addWidget(ch_property) image = TiffImageReader.read_image( PartSegData.segmentation_analysis_default_image) with qtbot.waitSignals( [settings.image_changed, image_view.image_added], timeout=10**6): settings.image = image channels_num = image.channels assert image_view.channel_control.channels_count == channels_num image_view.viewer_widget.screenshot() image1 = image_view.viewer_widget.canvas.render() assert np.any(image1 != 255) image_view.channel_control.set_active(1) ch_property.minimum_value.setValue(100) ch_property.maximum_value.setValue(10000) ch_property.filter_radius.setValue(0.5) image2 = image_view.viewer_widget.canvas.render() assert np.any(image2 != 255) assert np.all(image1 == image2) def check_parameters(name, index): return name == "test" and index == 1 # Test fixed range with qtbot.waitSignal( image_view.channel_control.coloring_update), qtbot.waitSignal( image_view.channel_control.change_channel, check_params_cb=check_parameters): ch_property.fixed.setChecked(True) image1 = image_view.viewer_widget.canvas.render() assert np.any(image1 != 255) with qtbot.waitSignal( image_view.channel_control.coloring_update), qtbot.waitSignal( image_view.channel_control.change_channel, check_params_cb=check_parameters): ch_property.minimum_value.setValue(20) image2 = image_view.viewer_widget.canvas.render() assert np.any(image2 != 255) assert np.any(image1 != image2) with qtbot.waitSignal( image_view.channel_control.coloring_update), qtbot.waitSignal( image_view.channel_control.change_channel, check_params_cb=check_parameters): ch_property.maximum_value.setValue(11000) image3 = image_view.viewer_widget.screenshot() assert np.any(image3 != 255) assert np.any(image2 != image3) assert np.any(image1 != image3) with qtbot.waitSignal( image_view.channel_control.coloring_update), qtbot.waitSignal( image_view.channel_control.change_channel, check_params_cb=check_parameters): ch_property.fixed.setChecked(False) image1 = image_view.viewer_widget.screenshot() assert np.any(image1 != 255) assert np.any(image1 != image2) assert np.any(image1 != image3) # Test gauss with qtbot.waitSignal( image_view.channel_control.coloring_update), qtbot.waitSignal( image_view.channel_control.change_channel, check_params_cb=check_parameters): ch_property.use_filter.set_value(NoiseFilterType.Gauss) image4 = image_view.viewer_widget.screenshot() assert np.any(image4 != 255) assert np.any(image1 != image4) assert np.any(image2 != image4) assert np.any(image3 != image4) with qtbot.waitSignal( image_view.channel_control.coloring_update), qtbot.waitSignal( image_view.channel_control.change_channel, check_params_cb=check_parameters): ch_property.filter_radius.setValue(1) image5 = image_view.viewer_widget.screenshot() assert np.any(image5 != 255) assert np.any(image1 != image5) assert np.any(image2 != image5) assert np.any(image3 != image5) assert np.any(image4 != image5) # Test gauss and fixed range ch_property.minimum_value.setValue(100) ch_property.maximum_value.setValue(10000) with qtbot.waitSignal( image_view.channel_control.coloring_update), qtbot.waitSignal( image_view.channel_control.change_channel, check_params_cb=check_parameters): ch_property.fixed.setChecked(True) image1 = image_view.viewer_widget.screenshot() with qtbot.waitSignal( image_view.channel_control.coloring_update), qtbot.waitSignal( image_view.channel_control.change_channel, check_params_cb=check_parameters): ch_property.minimum_value.setValue(10) image2 = image_view.viewer_widget.screenshot() assert np.any(image2 != 255) assert np.any(image1 != image2) with qtbot.waitSignal( image_view.channel_control.coloring_update), qtbot.waitSignal( image_view.channel_control.change_channel, check_params_cb=check_parameters): ch_property.maximum_value.setValue(11000) image3 = image_view.viewer_widget.screenshot() assert np.any(image3 != 255) assert np.any(image2 != image3) assert np.any(image1 != image3) with qtbot.waitSignal( image_view.channel_control.coloring_update), qtbot.waitSignal( image_view.channel_control.change_channel, check_params_cb=check_parameters): ch_property.fixed.setChecked(False) image1 = image_view.viewer_widget.screenshot() assert np.any(image1 != 255) assert np.any(image1 != image2) assert np.any(image1 != image3)
def test_tiff_image_read(self): image = TiffImageReader.read_image(PartSegData.segmentation_mask_default_image) assert isinstance(image, Image)
def __init__(self, file_path=None, mask_path=None): super().__init__() self.reader = TiffImageReader(self.info_function) self.file_path = file_path self.mask_path = mask_path self.image = None
def __init__(self, config_folder=CONFIG_FOLDER, title="PartSeg", settings=None, signal_fun=None, initial_image=None): super().__init__(config_folder, title, settings, load_functions.load_dict, signal_fun) self.channel_info = "result_image" self.files_num = 2 self.setMinimumWidth(600) # thi isinstance is only for hinting in IDE assert isinstance(self.settings, PartSettings) # nosec self.main_menu = MainMenu(self.settings, self) self.channel_control2 = ChannelProperty(self.settings, start_name="result_image") self.raw_image = CompareImageView(self.settings, self.channel_control2, "raw_image") self.measurements = MeasurementWidget(self.settings) self.left_stack = StackedWidgetWithSelector() self.left_stack.addWidget(self.raw_image, "Image") self.left_stack.addWidget(self.measurements, "Measurements") self.result_image = ResultImageView(self.settings, self.channel_control2, "result_image") self.color_bar = ColorBar(self.settings, [self.raw_image, self.result_image]) self.info_text = QLabel() self.info_text.setMinimumHeight(25) self.raw_image.text_info_change.connect(self.info_text.setText) self.result_image.text_info_change.connect(self.info_text.setText) self.synchronize_tool = SynchronizeView(self.raw_image, self.result_image, self) self.options_panel = Options(self.settings, self.channel_control2, self.raw_image, self.synchronize_tool) # self.main_menu.image_loaded.connect(self.image_read) self.settings.image_changed.connect(self.image_read) self.advanced_window = SegAdvancedWindow(self.settings, reload_list=[self.reload]) self.batch_window = None # BatchWindow(self.settings) self.multiple_files = MultipleFileWidget(self.settings, load_functions.load_dict, True) self.multiple_files.setVisible( self.settings.get("multiple_files_widget", False)) if initial_image is None: reader = TiffImageReader() im = reader.read(self.initial_image_path) im.file_path = "" self.settings.image = im elif initial_image is not False: self.settings.image = initial_image icon = QIcon(os.path.join(PartSegData.icons_dir, "icon.png")) self.setWindowIcon(icon) menu_bar = self.menuBar() file_menu = menu_bar.addMenu("File") file_menu.addAction("&Open").triggered.connect( self.main_menu.load_data) file_menu.addMenu(self.recent_file_menu) file_menu.addAction("&Save").triggered.connect( self.main_menu.save_file) file_menu.addAction("Batch processing").triggered.connect( self.main_menu.batch_window) view_menu = menu_bar.addMenu("View") view_menu.addAction("Settings and Measurement").triggered.connect( self.main_menu.advanced_window_show) view_menu.addAction("Additional output").triggered.connect( self.additional_layers_show) view_menu.addAction("Additional output with data").triggered.connect( lambda: self.additional_layers_show(True)) view_menu.addAction("Napari viewer").triggered.connect( self.napari_viewer_show) view_menu.addAction("Toggle Multiple Files").triggered.connect( self.toggle_multiple_files) view_menu.addAction("Toggle left panel").triggered.connect( self.toggle_left_panel) view_menu.addAction("Toggle console").triggered.connect( self._toggle_console) action = view_menu.addAction("Screenshot right panel") action.triggered.connect(self.screenshot(self.result_image)) action.setShortcut(QKeySequence.Print) view_menu.addAction("Screenshot left panel").triggered.connect( self.screenshot(self.raw_image)) image_menu = menu_bar.addMenu("Image operations") image_menu.addAction("Image adjustment").triggered.connect( self.image_adjust_exec) image_menu.addAction("Mask manager").triggered.connect( self.main_menu.mask_manager) help_menu = menu_bar.addMenu("Help") help_menu.addAction("State directory").triggered.connect( self.show_settings_directory) help_menu.addAction("About").triggered.connect(self.show_about_dialog) layout = QGridLayout() layout.setSpacing(0) info_layout = QHBoxLayout() info_layout.addWidget(self.left_stack.selector) info_layout.addWidget(self.options_panel.compare_btn) info_layout.addWidget(self.info_text, 1, Qt.AlignHCenter) image_layout = EqualColumnLayout() image_layout.addWidget(self.left_stack) image_layout.addWidget(self.result_image) layout.setSpacing(0) layout.addWidget(self.main_menu, 0, 0, 1, 3) layout.addLayout(info_layout, 3, 1, 1, 2) layout.addWidget(self.multiple_files, 2, 0) layout.addWidget(self.color_bar, 2, 1) layout.addLayout(image_layout, 2, 2, 1, 1) layout.addWidget(self.options_panel, 0, 3, 3, 1) layout.setColumnStretch(2, 1) widget = QWidget() widget.setLayout(layout) self.setCentralWidget(widget) with suppress(KeyError): geometry = self.settings.get_from_profile("main_window_geometry") self.restoreGeometry(QByteArray.fromHex(bytes(geometry, "ascii")))
def __init__(self, config_folder=CONFIG_FOLDER, title="PartSeg", settings=None, signal_fun=None, initial_image=None): super().__init__(config_folder, title, settings, io_functions.load_dict, signal_fun) self.channel_info = "channelcontrol" self.channel_control = ChannelProperty(self.settings, start_name="channelcontrol") self.image_view = StackImageView(self.settings, self.channel_control, name="channelcontrol") self.image_view.setMinimumWidth(450) self.info_text = QLabel() self.info_text.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Preferred) self.image_view.text_info_change.connect(self.info_text.setText) self.options_panel = Options(self.settings, self.image_view) self.main_menu = MainMenu(self.settings, self) self.main_menu.image_loaded.connect(self.image_read) self.settings.image_changed.connect(self.image_read) self.color_bar = ColorBar(self.settings, self.image_view) self.multiple_files = MultipleFileWidget(self.settings, io_functions.load_dict) self.multiple_files.setVisible( self.options_panel.image_properties.multiple_files.isChecked()) self.options_panel.algorithm_options.batch_process.multiple_result.connect( partial(self.multiple_files.save_state_action, custom_name=False)) icon = QIcon(os.path.join(PartSegData.icons_dir, "icon_stack.png")) self.setWindowIcon(icon) menu_bar = self.menuBar() file_menu = menu_bar.addMenu("File") file_menu.addAction("&Open").triggered.connect( self.main_menu.load_image) file_menu.addMenu(self.recent_file_menu) file_menu.addAction("&Save segmentation").triggered.connect( self.main_menu.save_segmentation) file_menu.addAction("&Save components").triggered.connect( self.main_menu.save_result) view_menu = menu_bar.addMenu("View") view_menu.addAction("Settings and Measurement").triggered.connect( self.main_menu.show_advanced_window) view_menu.addAction("Additional output").triggered.connect( self.additional_layers_show) view_menu.addAction("Additional output with data").triggered.connect( lambda: self.additional_layers_show(True)) view_menu.addAction("Napari viewer").triggered.connect( self.napari_viewer_show) view_menu.addAction("Toggle Multiple Files").triggered.connect( self.toggle_multiple_files) view_menu.addAction("Toggle console").triggered.connect( self._toggle_console) action = view_menu.addAction("Screenshot") action.triggered.connect(self.screenshot(self.image_view)) action.setShortcut(QKeySequence.Print) image_menu = menu_bar.addMenu("Image operations") image_menu.addAction("Image adjustment").triggered.connect( self.image_adjust_exec) help_menu = menu_bar.addMenu("Help") help_menu.addAction("State directory").triggered.connect( self.show_settings_directory) help_menu.addAction("About").triggered.connect(self.show_about_dialog) layout = QVBoxLayout() layout.addWidget(self.main_menu) sub_layout = QHBoxLayout() sub2_layout = QVBoxLayout() sub3_layout = QVBoxLayout() sub_layout.addWidget(self.multiple_files) sub_layout.addWidget(self.color_bar, 0) sub3_layout.addWidget(self.image_view, 1) sub3_layout.addWidget(self.info_text, 0) sub2_layout.addWidget(self.options_panel, 1) sub2_layout.addWidget(self.channel_control, 0) sub_layout.addLayout(sub3_layout, 1) sub_layout.addLayout(sub2_layout, 0) layout.addLayout(sub_layout) self.widget = QWidget() self.widget.setLayout(layout) self.setCentralWidget(self.widget) if initial_image is None: reader = TiffImageReader() im = reader.read(self.initial_image_path) im.file_path = "" self.settings.image = im elif initial_image is not False: self.settings.image = initial_image with suppress(KeyError): geometry = self.settings.get_from_profile("main_window_geometry") self.restoreGeometry(QByteArray.fromHex(bytes(geometry, "ascii")))