Esempio n. 1
0
 def roi(self, val: Union[np.ndarray, ROIInfo]):
     if val is None:
         self._roi_info = ROIInfo(val)
         self._additional_layers = {}
         self.roi_clean.emit()
         return
     try:
         if isinstance(val, np.ndarray):
             self._roi_info = ROIInfo(self.image.fit_array_to_image(val))
         else:
             self._roi_info = val.fit_to_image(self.image)
     except ValueError:
         raise ValueError(ROI_NOT_FIT)
     self._additional_layers = {}
     self.roi_changed.emit(self._roi_info)
Esempio n. 2
0
class ImageInfo:
    image: Image
    layers: List[NapariImage]
    filter_info: List[Tuple[NoiseFilterType,
                            float]] = field(default_factory=list)
    mask: Optional[Labels] = None
    mask_array: Optional[np.ndarray] = None
    roi: Optional[Labels] = None
    roi_info: ROIInfo = field(default_factory=lambda: ROIInfo(None))
    roi_count: int = 0

    def coords_in(self, coords: Union[List[int], np.ndarray]) -> bool:
        if not self.layers:
            return False
        fst_layer = self.layers[0]
        moved_coords = self.translated_coords(coords)
        return np.all(moved_coords >= 0) and np.all(
            moved_coords < fst_layer.data.shape)

    def translated_coords(self, coords: Union[List[int],
                                              np.ndarray]) -> np.ndarray:
        if not self.layers:
            return np.array(coords)
        fst_layer = self.layers[0]
        return np.subtract(coords, fst_layer.translate_grid).astype(np.int)
Esempio n. 3
0
 def __init__(self):
     super().__init__()
     self._image: Optional[Image] = None
     self._image_path = ""
     self._roi_info = ROIInfo(None)
     self._additional_layers = {}
     self._parent: Optional[QWidget] = None
Esempio n. 4
0
class ProjectInfoBase(Protocol):
    """
    This is base protocol for Project Information.

    :ivar str ~.file_path: path to current preceded file
    :ivar Image ~.image: project image
    :ivar numpy.ndarray ~.segmentation: numpy array representing current project ROI
    :ivar SegmentationInfo ~.segmentation_info: segmentation metadata
    :ivar Optional[numpy.ndarray] ~.mask: mask used in project
    :ivar str errors: information about problems with current project
    """

    file_path: str
    image: Image
    roi: np.ndarray
    roi_info: ROIInfo = ROIInfo(None)
    mask: Optional[np.ndarray]
    errors: str = ""

    def get_raw_copy(self):
        """
        Create copy with only image
        """
        raise NotImplementedError

    def get_raw_mask_copy(self):
        raise NotImplementedError

    def is_raw(self):
        raise NotImplementedError

    def is_masked(self):
        raise NotImplementedError
Esempio n. 5
0
    def _set_roi_info(self,
                      new_roi_info: ROIInfo,
                      save_chosen=True,
                      list_of_components=None,
                      segmentation_parameters=None):
        if list_of_components is None:
            list_of_components = []
        if segmentation_parameters is None:
            segmentation_parameters = defaultdict(lambda: None)
        state = self.get_project_info()
        try:
            new_roi_info = new_roi_info.fit_to_image(self.image)
        except ValueError:
            raise ValueError("ROI do not fit to image")
        if save_chosen:
            state2 = self.transform_state(state, new_roi_info,
                                          segmentation_parameters,
                                          list_of_components, save_chosen)
            self.chosen_components_widget.set_chose(
                list(sorted(state2.roi_extraction_parameters.keys())),
                state2.selected_components)
            self.roi = state2.roi_info
            self.components_parameters_dict = state2.roi_extraction_parameters
        else:
            selected_parameters = {
                i: segmentation_parameters[i]
                for i in new_roi_info.bound_info
            }

            self.chosen_components_widget.set_chose(
                list(sorted(selected_parameters.keys())), list_of_components)
            self.roi = new_roi_info
            self.components_parameters_dict = segmentation_parameters
Esempio n. 6
0
def analysis_project() -> ProjectTuple:
    data = np.zeros((1, 50, 100, 100, 1), dtype=np.uint16)
    data[0, 10:40, 10:40, 10:90] = 50
    data[0, 10:40, 50:90, 10:90] = 50
    data[0, 15:35, 15:35, 15:85] = 70
    data[0, 15:35, 55:85, 15:85] = 60
    data[0, 10:40, 40:50, 10:90] = 40
    image = Image(
        data, (10 / UNIT_SCALE[Units.nm.value], 5 / UNIT_SCALE[Units.nm.value], 5 / UNIT_SCALE[Units.nm.value]), ""
    )
    mask = data[0, ..., 0] > 0
    roi = np.zeros(data.shape, dtype=np.uint8)
    roi[data == 70] = 1
    roi[data == 60] = 2
    algorithm_parameters = {
        "algorithm_name": "Lower Threshold",
        "values": {
            "threshold": 60,
            "channel": 0,
            "noise_filtering": {"name": "None", "values": {}},
            "minimum_size": 10,
            "side_connection": False,
        },
    }
    roi_info = ROIInfo(roi.squeeze()).fit_to_image(image)
    return ProjectTuple(
        file_path="test_data.tiff",
        image=image,
        roi_info=roi_info,
        additional_layers={"denoised image": AdditionalLayerDescription(data=roi, layer_type="layer")},
        mask=mask,
        algorithm_parameters=algorithm_parameters,
    )
Esempio n. 7
0
 def compare_action(self):
     if self.compare_btn.text() == "Compare":
         self._settings.set_segmentation_to_compare(self._settings.roi_info)
         self.compare_btn.setText("Remove")
     else:
         self._settings.set_segmentation_to_compare(ROIInfo(None))
         self.compare_btn.setText("Compare")
Esempio n. 8
0
    def test_multiple_components(self, comp_num):
        data = np.zeros((10 * comp_num, 10), dtype=np.uint8)
        for i in range(comp_num):
            data[i * 10 + 2:i * 10 + 8, 2:8] = i + 1
        si = ROIInfo(data)
        assert len(si.bound_info) == comp_num
        assert set(si.bound_info.keys()) == set(range(1, comp_num + 1))
        for i in range(comp_num):
            assert np.all(si.bound_info[i + 1].lower == [i * 10 + 2, 2])
            assert np.all(si.bound_info[i + 1].upper == [i * 10 + 7, 7])
        assert len(si.sizes) == comp_num + 1
        assert np.all(si.sizes[1:] == 36)

        data[-1, 8] = 1
        si = ROIInfo(data)
        assert np.all(si.bound_info[1].lower == 2)
        assert np.all(si.bound_info[1].upper == [10 * comp_num - 1, 8])
Esempio n. 9
0
 def get_roi_info_and_mask(self) -> Tuple[ROIInfo, Optional[np.ndarray]]:
     self.arrays.seek(0)
     seg = np.load(self.arrays)
     self.arrays.seek(0)
     alternative = {name: array for name, array in seg.items() if name not in {"roi", "mask"}}
     roi_info = ROIInfo(seg["roi"], annotations=self.annotations, alternative=alternative)
     mask = seg["mask"] if "mask" in seg else None
     return roi_info, mask
Esempio n. 10
0
 def test_more_dims(self, dims):
     si = ROIInfo(np.ones((10, ) * dims, dtype=np.uint8))
     assert len(si.bound_info[1].lower) == dims
     assert len(si.bound_info[1].upper) == dims
     assert np.all(si.bound_info[1].lower == 0)
     assert np.all(si.bound_info[1].upper == 9)
     assert len(si.sizes) == 2
     assert np.all(si.sizes == [0, 10**dims])
Esempio n. 11
0
def stack_segmentation1(stack_image: MaskProjectTuple, mask_segmentation_parameters):
    data = np.zeros([20, 40, 40], dtype=np.uint8)
    for i, (x, y) in enumerate(itertools.product([0, 20], repeat=2), start=1):
        data[1:-1, x + 2 : x + 18, y + 2 : y + 18] = i
    data = ROIInfo(stack_image.image.fit_array_to_image(data))
    parameters = {i: deepcopy(mask_segmentation_parameters) for i in range(1, 5)}
    return dataclasses.replace(
        stack_image, roi_info=data, roi_extraction_parameters=parameters, selected_components=[1, 3]
    )
Esempio n. 12
0
 def test_mask(self, mask_prop):
     mask = np.zeros((10, 10), dtype=np.uint8)
     mask[1:-1, 1:-1] = 2
     mask2 = np.copy(mask)
     mask2[2:-2, 2:-2] = 4
     roi_info = ROIInfo(mask2)
     elem = HistoryElement.create(roi_info, mask, {}, mask_prop)
     roi_info2, mask2 = elem.get_roi_info_and_mask()
     assert np.all(mask == mask2)
     assert np.all(roi_info.roi == roi_info2.roi)
Esempio n. 13
0
 def test_set_roi(self, qtbot, part_settings, image):
     prop = ChannelProperty(part_settings, "test")
     viewer = ResultImageView(part_settings, prop, "test")
     qtbot.add_widget(prop)
     qtbot.add_widget(viewer)
     viewer.show()
     part_settings.image = image
     roi = ROIInfo((image.get_channel(0) > 0).astype(np.uint8))
     roi = roi.fit_to_image(image)
     viewer.set_roi(roi, image)
     QCoreApplication.processEvents()
     assert not viewer.roi_alternative_select.isVisible()
     assert viewer.label1.isVisible()
     assert viewer.label2.isVisible()
     assert viewer.opacity.isVisible()
     assert viewer.only_border.isVisible()
     assert not viewer.roi_alternative_select.isVisible()
     assert viewer.any_roi()
     assert not viewer.available_alternatives()
     viewer.hide()
Esempio n. 14
0
 def test_create(self, mask_prop):
     roi_info = ROIInfo(np.zeros((10, 10), dtype=np.uint8))
     elem = HistoryElement.create(roi_info, None, {}, mask_prop)
     assert elem.mask_property == mask_prop
     assert elem.roi_extraction_parameters == {}
     param = {"a": 1, "b": 2}
     elem2 = HistoryElement.create(roi_info, None, param, mask_prop)
     assert elem2.roi_extraction_parameters == param
     roi_info2, mask = elem2.get_roi_info_and_mask()
     assert np.all(roi_info2.roi == 0)
     assert mask is None
Esempio n. 15
0
    def image(self, value: Image):
        if value is None:
            return
        self._image = value
        if value.file_path is not None:
            self.image_changed[str].emit(value.file_path)
        self._image_changed()
        self._roi_info = ROIInfo(None)

        self.image_changed.emit(self._image)
        self.image_changed[int].emit(self._image.channels)
Esempio n. 16
0
 def test_annotations(self, mask_prop):
     data = np.zeros((10, 10), dtype=np.uint8)
     data[1:5, 1:5] = 1
     data[5:-1, 1:5] = 2
     data[1:5, 5:-1] = 3
     data[5:-1, 5:-1] = 4
     annotations = {1: "a", 2: "b", 3: "c", 4: "d"}
     roi_info = ROIInfo(data, annotations=annotations)
     elem = HistoryElement.create(roi_info, None, {}, mask_prop)
     roi_info2, mask2 = elem.get_roi_info_and_mask()
     assert mask2 is None
     assert np.all(roi_info2.roi == roi_info.roi)
Esempio n. 17
0
 def test_simple(self, num):
     data = np.zeros((10, 10), dtype=np.uint8)
     data[2:8, 2:8] = num
     si = ROIInfo(data)
     assert len(si.bound_info) == 1
     assert num in si.bound_info
     assert isinstance(si.bound_info[num], BoundInfo)
     assert np.all(si.bound_info[num].lower == [2, 2])
     assert np.all(si.bound_info[num].upper == [7, 7])
     assert len(si.sizes) == num + 1
     assert np.all(si.sizes[1:num] == 0)
     assert si.sizes[num] == 36
Esempio n. 18
0
 def test_update_alternatives(self, base_settings, image_view, tmp_path):
     roi = np.ones(base_settings.image.get_channel(0).shape, dtype=np.uint8)
     roi[..., 1, 1] = 0
     base_settings.roi = ROIInfo(
         roi,
         alternative={"test": np.ones(roi.shape, dtype=np.uint8) - roi})
     image_view.update_roi_border()
     assert np.all(image_view.image_info[str(tmp_path /
                                             "test2.tiff")].roi.data == roi)
     image_view.roi_alternative_selection = "test"
     image_view.update_roi_border()
     assert np.all(image_view.image_info[str(tmp_path /
                                             "test2.tiff")].roi.data != roi)
Esempio n. 19
0
 def perform_roi_info_history_test(
     self, project, save_path, mask_property, save_method: Type[SaveBase], load_method: Type[LoadBase]
 ):
     alt1 = np.copy(project.roi_info.roi)
     alt1[alt1 > 0] += 3
     roi_info = ROIInfo(
         roi=project.roi_info.roi, annotations={i: f"a{i}" for i in range(1, 5)}, alternative={"test": alt1}
     )
     history = []
     for i in range(3):
         alt2 = np.copy(alt1)
         alt2[alt2 > 0] = i + 5
         roi_info2 = ROIInfo(
             roi=project.roi_info.roi,
             annotations={i: f"a{i}_{j}" for j in range(1, 5)},
             alternative={f"test{i}": alt2},
         )
         history.append(
             HistoryElement.create(
                 roi_info2, alt1, {"algorithm_name": f"task_{i}", "values": {"a": 1}}, mask_property
             )
         )
     proj = dataclasses.replace(project, roi_info=roi_info, history=history)
     save_method.save(save_path / "data.tgz", proj, SaveROI.get_default_values())
     proj2: ProjectInfoBase = load_method.load([save_path / "data.tgz"])
     assert np.all(proj2.roi_info.roi == project.roi_info.roi)
     assert set(proj2.roi_info.annotations) == {1, 2, 3, 4}
     assert proj2.roi_info.annotations == {i: f"a{i}" for i in range(1, 5)}
     assert "test" in proj2.roi_info.alternative
     assert np.all(proj2.roi_info.alternative["test"] == alt1)
     assert len(proj2.history) == 3
     for i in range(3):
         roi_info3, mask2 = proj2.history[i].get_roi_info_and_mask()
         assert np.all(mask2 == alt1)
         assert set(roi_info3.alternative) == {f"test{i}"}
         assert np.all(roi_info3.alternative[f"test{i}"][alt1 > 0] == i + 5)
         assert np.all(roi_info3.alternative[f"test{i}"][alt1 == 0] == 0)
         assert roi_info3.annotations == {i: f"a{i}_{j}" for j in range(1, 5)}
         assert proj2.history[i].roi_extraction_parameters == {"algorithm_name": f"task_{i}", "values": {"a": 1}}
Esempio n. 20
0
def test_compare_view(part_settings, image2, qtbot):
    prop = ChannelProperty(part_settings, "test")
    view = CompareImageView(part_settings, prop, "test")
    qtbot.add_widget(prop)
    qtbot.add_widget(view)
    part_settings.image = image2

    roi = np.ones(image2.get_channel(0).shape, dtype=np.uint8)

    assert view.image_info[str(image2.file_path)].roi is None
    part_settings.roi = roi
    assert view.image_info[str(image2.file_path)].roi is None
    part_settings.set_segmentation_to_compare(ROIInfo(roi))
    assert view.image_info[str(image2.file_path)].roi is not None
Esempio n. 21
0
 def perform_roi_info_test(self, project, save_path, save_method: Type[SaveBase], load_method: Type[LoadBase]):
     alt1 = np.copy(project.roi_info.roi)
     alt1[alt1 > 0] += 3
     roi_info = ROIInfo(
         roi=project.roi_info.roi, annotations={i: f"a{i}" for i in range(1, 5)}, alternative={"test": alt1}
     )
     proj = dataclasses.replace(project, roi_info=roi_info)
     save_method.save(save_path / "data.tgz", proj, SaveROI.get_default_values())
     proj2 = load_method.load([save_path / "data.tgz"])
     assert np.all(proj2.roi_info.roi == project.roi_info.roi)
     assert set(proj2.roi_info.annotations) == {1, 2, 3, 4}
     assert proj2.roi_info.annotations == {i: f"a{i}" for i in range(1, 5)}
     assert "test" in proj2.roi_info.alternative
     assert np.all(proj2.roi_info.alternative["test"] == alt1)
Esempio n. 22
0
 def prev_mask(self):
     history: HistoryElement = self.settings.history_pop()
     history.arrays.seek(0)
     seg = np.load(history.arrays)
     history.arrays.seek(0)
     # TODO Check me
     # self.settings.roi = seg["segmentation"]
     self.settings._set_roi_info(  # pylint: disable=W0212
         ROIInfo(seg["segmentation"]),
         False,
         history.roi_extraction_parameters["selected"],
         history.roi_extraction_parameters["parameters"],
     )
     self.settings.mask = seg["mask"] if "mask" in seg else None
     self.close()
Esempio n. 23
0
 def test_transform_state_simple(self, stack_image):
     roi = np.zeros(stack_image.image.get_channel(0).shape, dtype=np.uint8)
     roi[0, 1, 2:-2, 2:-2] = 1
     roi[0, 2, 2:-2, 2:-2] = 2
     roi[0, 3, 2:-2, 2:-2] = 3
     roi_info = ROIInfo(roi).fit_to_image(stack_image.image)
     roi_extraction_parameters = defaultdict(lambda: ROIExtractionProfile("aa", "aa", {1: "aa"}))
     new_state = StackSettings.transform_state(
         state=stack_image,
         new_roi_info=roi_info,
         new_roi_extraction_parameters=roi_extraction_parameters,
         list_of_components=[2],
     )
     assert len(new_state.roi_extraction_parameters) == 3
     assert new_state.selected_components == [2]
Esempio n. 24
0
def napari_write_labels(path: str, data: Any, meta: dict) -> Optional[str]:
    if not isinstance(data, numpy.ndarray):
        return
    ext = os.path.splitext(path)[1]
    if ext in SaveROI.get_extensions():
        project = MaskProjectTuple(file_path="",
                                   image=None,
                                   roi_info=ROIInfo(data))
        SaveROI.save(path,
                     project,
                     parameters={
                         "spacing":
                         numpy.divide(meta["scale"], DEFAULT_SCALE_FACTOR)[-3:]
                     })
        return path
Esempio n. 25
0
    def set_segmentation_result(self, result: SegmentationResult):
        if result.info_text and self._parent is not None:
            QMessageBox().information(self._parent, "Algorithm info", result.info_text)

        self._additional_layers = result.additional_layers
        self.last_executed_algorithm = result.parameters.algorithm
        self.set(f"algorithms.{result.parameters.algorithm}", result.parameters.values)
        try:
            roi = self.image.fit_array_to_image(result.roi)
            alternative_list = {
                k: self.image.fit_array_to_image(v) for k, v in result.alternative_representation.items()
            }
        except ValueError:
            raise ValueError("roi do not fit to image")
        self._roi_info = ROIInfo(roi, result.roi_annotation, alternative_list)
        self.roi_changed.emit(self._roi_info)
Esempio n. 26
0
    def save(
        cls,
        save_location: typing.Union[str, BytesIO, Path],
        project_info: ProjectTuple,
        parameters: dict,
        range_changed=None,
        step_changed=None,
    ):
        if not os.path.exists(save_location):
            os.makedirs(save_location)
        if not os.path.isdir(save_location):
            raise OSError("save location exist and is not a directory")
        parameters = deepcopy(parameters)
        if parameters["clip"]:
            points = np.nonzero(project_info.roi_info.roi)
            lower_bound = np.min(points, axis=1)
            lower_bound = np.max([lower_bound - 3, [0, 0, 0]], axis=0)
            upper_bound = np.max(points, axis=1)
            upper_bound = np.max(
                [upper_bound + 3,
                 np.array(project_info.roi_info.roi) - 1],
                axis=0)
            cut_area = tuple(
                slice(x, y) for x, y in zip(lower_bound, upper_bound))
            # WARNING time
            image = project_info.image.cut_image((slice(None), ) + cut_area)
            roi_info = ROIInfo(project_info.roi_info.roi[cut_area])

            mask = project_info.mask[cut_area] if project_info.mask else None
            project_info = dataclasses.replace(project_info,
                                               image=image,
                                               roi_info=roi_info,
                                               mask=mask)
            parameters["clip"] = False

        parameters.update({"separated_objects": False})
        SaveCmap.save(os.path.join(save_location, "density.cmap"),
                      project_info, parameters, range_changed, step_changed)
        parameters.update({"separated_objects": True})
        SaveCmap.save(os.path.join(save_location, "density.cmap"),
                      project_info, parameters, range_changed, step_changed)
        SaveROIAsTIFF.save(os.path.join(save_location, "segmentation.tiff"),
                           project_info, {}, range_changed, step_changed)
        SaveROIAsNumpy.save(os.path.join(save_location, "segmentation.npy"),
                            project_info, {}, range_changed, step_changed)
Esempio n. 27
0
 def test_additional(self, mask_prop):
     data = np.zeros((10, 10), dtype=np.uint8)
     data[1:-1, 1:-1] = 2
     alternative = {}
     for i in range(4):
         alternative_array = np.copy(data)
         alternative_array[alternative_array > 0] = i + 2
         alternative[f"add{i}"] = alternative_array
     roi_info = ROIInfo(data, alternative=alternative)
     elem = HistoryElement.create(roi_info, None, {}, mask_prop)
     roi_info2, mask2 = elem.get_roi_info_and_mask()
     assert np.all(roi_info2.roi == roi_info.roi)
     assert mask2 is None
     assert len(roi_info.alternative) == 4
     assert set(roi_info.alternative) == {f"add{i}" for i in range(4)}
     for i in range(4):
         arr = roi_info.alternative[f"add{i}"]
         assert np.all(arr[arr > 0] == i + 2)
Esempio n. 28
0
def analysis_project_reversed() -> ProjectTuple:
    data = np.zeros((1, 50, 100, 100, 1), dtype=np.uint16)
    data[0, 10:40, 10:40, 10:90] = 50
    data[0, 10:40, 50:90, 10:90] = 50
    data[0, 15:35, 15:35, 15:85] = 70
    data[0, 15:35, 55:85, 15:85] = 60
    data[0, 10:40, 40:50, 10:90] = 40
    mask = data[0] > 0
    roi = np.zeros(data.shape, dtype=np.uint8)
    roi[data == 70] = 1
    roi[data == 60] = 2

    data = 100 - data
    image = Image(
        data, (10 / UNIT_SCALE[Units.nm.value], 5 / UNIT_SCALE[Units.nm.value], 5 / UNIT_SCALE[Units.nm.value]), ""
    )
    roi_info = ROIInfo(roi.squeeze()).fit_to_image(image)
    return ProjectTuple("test_data.tiff", image, roi_info=roi_info, mask=mask)
Esempio n. 29
0
    def test_image_settings(self, tmp_path, image, roi, qtbot):
        widget = base_settings.QWidget()
        qtbot.addWidget(widget)
        settings = base_settings.ImageSettings()
        settings.set_parent(widget)
        assert settings.image_spacing == ()
        assert settings.image_shape == ()
        assert settings.image_path == ""
        assert settings.channels == 0
        settings.image = image
        assert settings.image_spacing == image.spacing
        assert settings.image_path == str(tmp_path / "test.tiff")
        assert settings.image_shape == (1, 1, 10, 10, 2)
        with qtbot.waitSignal(settings.image_spacing_changed):
            settings.image_spacing = (7, 7)
        assert image.spacing == (7, 7)
        with qtbot.waitSignal(settings.image_spacing_changed):
            settings.image_spacing = (1, 8, 8)
        assert image.spacing == (8, 8)
        with pytest.raises(ValueError):
            settings.image_spacing = (6, )

        assert settings.is_image_2d()
        assert settings.has_channels
        with qtbot.waitSignal(settings.image_changed[str]):
            settings.image_path = str(tmp_path / "test2.tiff")
        assert image.file_path == str(tmp_path / "test2.tiff")

        with pytest.raises(ValueError, match="roi do not fit to image"):
            settings.roi = roi[:-2]
        with qtbot.waitSignal(settings.roi_changed):
            settings.roi = roi
        assert all(settings.sizes == [64, 18, 18])
        assert all(settings.components_mask() == [0, 1, 1])

        assert tuple(settings.roi_info.bound_info.keys()) == (1, 2)

        with qtbot.waitSignal(settings.roi_clean):
            settings.roi = None

        settings.roi = ROIInfo(roi)

        settings.image = None
        assert settings.image is not None
Esempio n. 30
0
    def test_with_roi_alternatives(self, part_settings, image2, qtbot):
        prop = ChannelProperty(part_settings, "test")
        view = ResultImageView(part_settings, prop, "test")
        qtbot.add_widget(prop)
        qtbot.add_widget(view)
        part_settings.image = image2
        view.show()

        roi = np.ones(image2.get_channel(0).shape, dtype=np.uint8)
        part_settings.roi = roi

        assert not view.roi_alternative_select.isVisible()
        part_settings.roi = ROIInfo(roi, alternative={"t1": roi, "t2": roi})
        assert view.roi_alternative_select.isVisible()
        assert view.roi_alternative_select.count() == 3

        assert view.roi_alternative_select.currentText() == "ROI"
        view.roi_alternative_select.setCurrentText("t1")

        view.hide()