def transform(
     cls,
     image: Image,
     arguments: dict,
     callback_function: Optional[Callable[[str, int],
                                          None]] = None) -> Image:
     keys = [x for x in arguments if x.startswith("scale")]
     keys_order = Image.axis_order.lower()
     scale_factor = [1.0] * len(keys_order)
     if len(keys) == 1 and keys[0] == "scale":
         for letter in image.get_dimension_letters().lower():
             scale_factor[keys_order.index(letter)] = arguments["scale"]
         spacing = [x / arguments["scale"] for x in image.spacing]
     else:
         # assume that all keys are in format scale_{}
         for key in keys:
             letter = key[-1]
             scale_factor[keys_order.index(letter)] = arguments[key]
         spacing = [
             x / arguments[f"scale_{y}"]
             for x, y in zip(image.spacing,
                             image.get_dimension_letters().lower())
         ]
     array = zoom(image.get_data(), scale_factor, mode="mirror")
     if image.mask is not None:
         mask = zoom(image.mask, scale_factor[:-1], mode="mirror")
     else:
         mask = None
     return image.substitute(data=array, image_spacing=spacing, mask=mask)
Exemple #2
0
 def test_mask_property_combinations(self, dilate, radius, fill_holes,
                                     max_holes_size, save_components,
                                     clip_to_mask, reversed_mask, old_mask):
     mask = np.zeros((1, 6, 6, 15), dtype=np.uint8)
     im = Image(data=mask.copy(),
                image_spacing=(3, 1, 1),
                file_path="",
                axes_order="TZYX")
     mask[:, 1:-1, 1:-1, 2:5] = 1
     mask[:, 2:-2, 2:-2, 3:4] = 0
     mask[:, 1:-1, 1:-1, 6:9] = 2
     mask[:, 2:-2, 2:-2, 7:8] = 0
     mask[:, 1:-1, 1:-1, 10:13] = 3
     mask[:, 2:-2, 2:-2, 11:12] = 0
     mask = im.fit_mask_to_image(mask)
     assert np.all(np.unique(mask.flat) == [0, 1, 2, 3])
     _old_mask = np.zeros(mask.shape,
                          dtype=mask.dtype) if old_mask else None
     mp = MaskProperty(
         dilate=dilate,
         dilate_radius=radius,
         fill_holes=fill_holes,
         max_holes_size=max_holes_size,
         save_components=save_components,
         clip_to_mask=clip_to_mask,
         reversed_mask=reversed_mask,
     )
     mask1 = calculate_mask(mp,
                            mask,
                            _old_mask,
                            im.spacing,
                            time_axis=im.time_pos)
     assert mask1.shape == mask.shape
Exemple #3
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
    segmentation = np.zeros(data.shape, dtype=np.uint8)
    segmentation[data == 70] = 1
    segmentation[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,
        },
    }
    segmentation = image.fit_array_to_image(segmentation.squeeze())
    return ProjectTuple(
        file_path="test_data.tiff",
        image=image,
        roi=segmentation,
        additional_layers={"denoised image": AdditionalLayerDescription(data=segmentation, layer_type="layer")},
        mask=mask,
        algorithm_parameters=algorithm_parameters,
    )
def save_components(
    image: Image,
    components: list,
    segmentation: np.ndarray,
    dir_path: str,
    segmentation_info: typing.Optional[SegmentationInfo] = None,
    range_changed=None,
    step_changed=None,
):
    if range_changed is None:
        range_changed = empty_fun
    if step_changed is None:
        step_changed = empty_fun

    segmentation = image.fit_array_to_image(segmentation)

    if segmentation_info is None:
        segmentation_info = SegmentationInfo(segmentation)
    os.makedirs(dir_path, exist_ok=True)

    file_name = os.path.splitext(os.path.basename(image.file_path))[0]
    range_changed(0, 2 * len(components))
    for i in components:
        slices = segmentation_info.bound_info[i].get_slices()
        cut_segmentation = segmentation[tuple(slices)]
        cut_image = image.cut_image(slices)
        im = cut_image.cut_image(cut_segmentation == i, replace_mask=True)
        # print(f"[run] {im}")
        ImageWriter.save(
            im, os.path.join(dir_path, f"{file_name}_component{i}.tif"))
        step_changed(2 * i + 1)
        ImageWriter.save_mask(
            im, os.path.join(dir_path, f"{file_name}_component{i}_mask.tif"))
        step_changed(2 * i + 2)
def calculate_pipeline(image: Image, mask: typing.Optional[np.ndarray],
                       pipeline: SegmentationPipeline, report_fun):
    history = []
    report_fun("max", 2 * len(pipeline.mask_history) + 1)
    for i, el in enumerate(pipeline.mask_history):
        result, _ = calculate_segmentation_step(el.segmentation, image, mask)
        segmentation = image.fit_array_to_image(result.roi)
        report_fun("step", 2 * i + 1)
        new_mask = calculate_mask(
            mask_description=el.mask_property,
            segmentation=segmentation,
            old_mask=mask,
            spacing=image.spacing,
            time_axis=image.time_pos,
        )
        segmentation_parameters = {
            "algorithm_name": el.segmentation.name,
            "values": el.segmentation.values
        }
        history.append(
            HistoryElement.create(segmentation, mask, segmentation_parameters,
                                  el.mask_property))
        report_fun("step", 2 * i + 2)
        mask = image.fit_array_to_image(new_mask)
    result, text = calculate_segmentation_step(pipeline.segmentation, image,
                                               mask)
    report_fun("step", 2 * len(pipeline.mask_history) + 1)
    return PipelineResult(result.roi, result.additional_layers, mask, history,
                          text)
Exemple #6
0
 def test_merge_fail(self):
     image1 = Image(data=np.zeros((4, 10, 10), dtype=np.uint8),
                    axes_order="ZXY",
                    image_spacing=(1, 1, 1))
     image2 = Image(data=np.zeros((3, 10, 10), dtype=np.uint8),
                    axes_order="ZXY",
                    image_spacing=(1, 1, 1))
     with pytest.raises(ValueError):
         image1.merge(image2, "C")
Exemple #7
0
 def test_channels(self, tmp_path, qtbot):
     settings = BaseSettings(tmp_path)
     assert not settings.has_channels
     assert settings.channels == 0
     settings.image = Image(np.zeros((10, 10, 2), dtype=np.uint8), (1, 1), axes_order="XYC")
     assert settings.has_channels
     assert settings.channels == 2
     settings.image = Image(np.zeros((10, 10, 1), dtype=np.uint8), (1, 1), axes_order="XYC")
     assert not settings.has_channels
     assert settings.channels == 1
Exemple #8
0
 def test_reorder_axes(self):
     fixed_array = self.image_class.reorder_axes(np.zeros((10, 20)),
                                                 axes="XY")
     assert fixed_array.shape == self.image_shape((10, 20), "XY")
     fixed_image = self.image_class(np.zeros((10, 20)),
                                    image_spacing=(1, 1, 1),
                                    axes_order="XY")
     assert fixed_image.shape == self.image_shape((10, 20), "XY")
     with pytest.raises(ValueError):
         Image.reorder_axes(np.zeros((10, 20)), axes="XYZ")
Exemple #9
0
 def test_merge_chanel(self, chanel_mark, check_dtype):
     image1 = Image(data=np.zeros((3, 10, 10), dtype=np.uint8),
                    axes_order="ZXY",
                    image_spacing=(1, 1, 1))
     image2 = Image(data=np.ones((3, 10, 10), dtype=check_dtype),
                    axes_order="ZXY",
                    image_spacing=(1, 1, 1))
     res_image = image1.merge(image2, chanel_mark)
     assert res_image.channels == 2
     assert np.all(res_image.get_channel(0) == 0)
     assert np.all(res_image.get_channel(1) == 1)
     assert res_image.dtype == check_dtype
Exemple #10
0
 def test_different_axes_order(self):
     image1 = Image(data=np.zeros((3, 10, 10), dtype=np.uint8),
                    axes_order="ZXY",
                    image_spacing=(1, 1, 1))
     image2 = ChangeChannelPosImage(data=np.zeros((3, 10, 10),
                                                  dtype=np.uint8),
                                    axes_order="ZXY",
                                    image_spacing=(1, 1, 1))
     res_image = image1.merge(image2, "C")
     assert res_image.channels == 2
     assert isinstance(res_image, Image)
     assert isinstance(image2.merge(image1, "C"), ChangeChannelPosImage)
Exemple #11
0
 def test_verify_image(self):
     assert BaseSettings.verify_image(Image(np.zeros((10, 10, 2), dtype=np.uint8), (1, 1), axes_order="XYC"))
     with pytest.raises(SwapTimeStackException):
         BaseSettings.verify_image(
             Image(np.zeros((2, 10, 10), dtype=np.uint8), (1, 1, 1), axes_order="TXY"), silent=False
         )
     im = BaseSettings.verify_image(Image(np.zeros((2, 10, 10), dtype=np.uint8), (1, 1, 1), axes_order="TXY"))
     assert not im.is_time
     assert im.times == 1
     assert im.is_stack
     assert im.layers == 2
     with pytest.raises(TimeAndStackException):
         BaseSettings.verify_image(Image(np.zeros((2, 2, 10, 10), dtype=np.uint8), (1, 1, 1), axes_order="TZXY"))
Exemple #12
0
 def test_load_files(self, part_settings, qtbot, monkeypatch, tmp_path):
     widget = MultipleFileWidget(
         part_settings, {LoadStackImage.get_name(): LoadStackImage})
     qtbot.add_widget(widget)
     for i in range(5):
         ImageWriter.save(
             Image(np.random.random((10, 10)),
                   image_spacing=(1, 1),
                   axes_order="XY"), tmp_path / f"img_{i}.tif")
     file_list = [[[str(tmp_path / f"img_{i}.tif")],
                   LoadStackImage.get_name()] for i in range(5)]
     load_property = LoadProperty(
         [str(tmp_path / f"img_{i}.tif") for i in range(5)],
         LoadStackImage.get_name(), LoadStackImage)
     with qtbot.waitSignal(widget._add_state,
                           check_params_cb=self.check_load_files):
         widget.execute_load_files(load_property, lambda x, y: True,
                                   lambda x: True)
     assert widget.file_view.topLevelItemCount() == 5
     assert part_settings.get_last_files_multiple() == file_list
     widget.file_view.clear()
     widget.state_dict.clear()
     widget.file_list.clear()
     monkeypatch.setattr(MultipleLoadDialog, "exec_", lambda x: True)
     monkeypatch.setattr(MultipleLoadDialog, "get_result",
                         lambda x: load_property)
     with qtbot.waitSignal(widget._add_state,
                           check_params_cb=self.check_load_files):
         widget.load_files()
     assert widget.file_view.topLevelItemCount() == 5
     assert part_settings.get_last_files_multiple() == file_list
     part_settings.dump()
     part_settings.load()
     assert part_settings.get_last_files_multiple() == file_list
Exemple #13
0
    def __init__(self,
                 image: Image,
                 transform_dict: Dict[str, TransformBase] = None):
        super().__init__()
        if transform_dict is None:
            transform_dict = image_transform_dict
        self.choose = QComboBox()
        self.stacked = QStackedWidget()
        for key, val in transform_dict.items():
            self.choose.addItem(key)
            initial_values = val.calculate_initial(image)
            form_widget = FormWidget(
                val.get_fields_per_dimension(image.get_dimension_letters()),
                initial_values)
            self.stacked.addWidget(form_widget)

        self.choose.currentIndexChanged.connect(self.stacked.setCurrentIndex)

        self.cancel_btn = QPushButton("Cancel")
        self.cancel_btn.clicked.connect(self.reject)

        self.process_btn = QPushButton("Process")
        self.process_btn.clicked.connect(self.process)
        self.transform_dict = transform_dict
        self.result_val: ImageAdjustTuple = None

        layout = QGridLayout()
        layout.addWidget(self.choose, 0, 0, 1, 3)
        layout.addWidget(self.stacked, 1, 0, 1, 3)
        layout.addWidget(self.cancel_btn, 2, 0)
        layout.addWidget(self.process_btn, 2, 2)
        self.setLayout(layout)
Exemple #14
0
def napari_write_image(path: str, data: Any, meta: dict) -> Optional[str]:
    ext = os.path.splitext(path)[1]
    if not isinstance(data, numpy.ndarray) or ext not in {
            ".tiff", ".tif", ".TIFF", ".TIF"
    }:
        return
    scale_shift = min(data.ndim, 3)
    axes = "TZXY"
    channel_names = [meta["name"]]
    if data.shape[-1] < 6:
        axes += "C"
        scale_shift -= 1
        channel_names = [
            f'{meta["name"]} {i}' for i in range(1, data.shape[-1] + 1)
        ]
    image = Image(
        data,
        numpy.divide(meta["scale"], DEFAULT_SCALE_FACTOR)[-scale_shift:],
        axes_order=axes[-data.ndim:],
        channel_names=channel_names,
        shift=numpy.divide(meta["translate"],
                           DEFAULT_SCALE_FACTOR)[-scale_shift:],
        name="Image",
    )
    ImageWriter.save(image, path)
    return path
Exemple #15
0
 def test_load_recent(self, part_settings, qtbot, monkeypatch, tmp_path):
     widget = MultipleFileWidget(
         part_settings, {LoadStackImage.get_name(): LoadStackImage})
     qtbot.add_widget(widget)
     for i in range(5):
         ImageWriter.save(
             Image(np.random.random((10, 10)),
                   image_spacing=(1, 1),
                   axes_order="XY"), tmp_path / f"img_{i}.tif")
     file_list = [[
         [
             tmp_path / f"img_{i}.tif",
         ],
         LoadStackImage.get_name(),
     ] for i in range(5)]
     with qtbot.waitSignal(widget._add_state,
                           check_params_cb=self.check_load_files):
         widget.load_recent_fun(file_list, lambda x, y: True,
                                lambda x: True)
     assert part_settings.get_last_files_multiple() == file_list
     assert widget.file_view.topLevelItemCount() == 5
     widget.file_view.clear()
     widget.state_dict.clear()
     widget.file_list.clear()
     monkeypatch.setattr(LoadRecentFiles, "exec_", lambda x: True)
     monkeypatch.setattr(LoadRecentFiles, "get_files", lambda x: file_list)
     with qtbot.waitSignal(widget._add_state,
                           check_params_cb=self.check_load_files):
         widget.load_recent()
     assert part_settings.get_last_files_multiple() == file_list
     assert widget.file_view.topLevelItemCount() == 5
 def calculate_initial(cls, image: Image):
     min_val = min(image.spacing)
     return {
         f"scale_{l}": x / min_val
         for x, l in zip(image.spacing,
                         image.get_dimension_letters().lower())
     }
Exemple #17
0
 def verify_image(image: Image, silent=True) -> Union[Image, bool]:
     if image.is_time:
         if image.is_stack:
             raise TimeAndStackException()
         if silent:
             return image.swap_time_and_stack()
         raise SwapTimeStackException()
     return True
Exemple #18
0
def image(tmp_path):
    data = np.zeros([20, 20, 20, 2], dtype=np.uint8)
    data[10:-1, 1:-1, 1:-1, 0] = 20
    data[1:10, 1:-1, 1:-1, 1] = 20
    data[1:-1, 1:5, 1:-1, 1] = 20
    data[1:-1, -5:-1, 1:-1, 1] = 20

    return Image(data, (10 ** -3, 10 ** -3, 10 ** -3), axes_order="ZYXC", file_path=str(tmp_path / "test.tiff"))
Exemple #19
0
def image():
    data = np.zeros([20, 20, 20, 2], dtype=np.uint8)
    data[10:-1, 1:-1, 1:-1, 0] = 20
    data[1:10, 1:-1, 1:-1, 1] = 20
    data[1:-1, 1:5, 1:-1, 1] = 20
    data[1:-1, -5:-1, 1:-1, 1] = 20

    return Image(data, (10**-3, 10**-3, 10**-3), axes_order="ZYXC")
Exemple #20
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
    segmentation = np.zeros(data.shape, dtype=np.uint8)
    segmentation[data == 70] = 1
    segmentation[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]), ""
    )
    segmentation = image.fit_array_to_image(segmentation.squeeze())
    return ProjectTuple("test_data.tiff", image, segmentation, mask=mask)
Exemple #21
0
 def test_run_return_none(self, qtbot):
     algorithm = ROIExtractionAlgorithmForTest(return_none=True)
     thr = segmentation_thread.SegmentationThread(algorithm)
     image = Image(np.zeros((10, 10), dtype=np.uint8),
                   image_spacing=(1, 1),
                   axes_order="XY")
     algorithm.set_image(image)
     with qtbot.assertNotEmitted(thr.execution_done):
         thr.run()
Exemple #22
0
 def test_run(self, qtbot):
     algorithm = ROIExtractionAlgorithmForTest()
     thr = segmentation_thread.SegmentationThread(algorithm)
     image = Image(np.zeros((10, 10), dtype=np.uint8),
                   image_spacing=(1, 1),
                   axes_order="XY")
     algorithm.set_image(image)
     with qtbot.waitSignals([thr.execution_done, thr.progress_signal]):
         thr.run()
Exemple #23
0
def stack_image():
    data = np.zeros([20, 40, 40], dtype=np.uint8)
    for x, y in itertools.product([0, 20], repeat=2):
        data[1:-1, x + 2 : x + 18, y + 2 : y + 18] = 100
    for x, y in itertools.product([0, 20], repeat=2):
        data[3:-3, x + 4 : x + 16, y + 4 : y + 16] = 120
    for x, y in itertools.product([0, 20], repeat=2):
        data[5:-5, x + 6 : x + 14, y + 6 : y + 14] = 140

    return MaskProjectTuple("test_path", Image(data, (2, 1, 1), axes_order="ZYX", file_path="test_path"))
Exemple #24
0
 def test_run_exception(self, qtbot):
     algorithm = ROIExtractionAlgorithmForTest(raise_=True)
     thr = segmentation_thread.SegmentationThread(algorithm)
     image = Image(np.zeros((10, 10), dtype=np.uint8),
                   image_spacing=(1, 1),
                   axes_order="XY")
     algorithm.set_image(image)
     with qtbot.assertNotEmitted(thr.execution_done), qtbot.waitSignal(
             thr.exception_occurred):
         thr.run()
Exemple #25
0
def test_image_info():
    image_info = ImageInfo(
        Image(np.zeros((10, 10)), image_spacing=(1, 1), axes_order="XY"), [])
    assert not image_info.coords_in([1, 1])
    assert np.all(image_info.translated_coords([1, 1]) == [1, 1])

    image_info.layers.append(
        NapariImage(image_info.image.get_channel(0), scale=(1, 1, 10, 10)))
    assert image_info.coords_in([0.5, 0.5, 1, 1])
    assert np.all(image_info.translated_coords([1, 1, 1, 1]) == [1, 1, 1, 1])
Exemple #26
0
    def test_base_settings_verify_image(self):
        assert base_settings.BaseSettings.verify_image(
            Image(np.zeros((10, 10)), (10, 10), axes_order="YX"))
        assert base_settings.BaseSettings.verify_image(
            Image(np.zeros((10, 10, 10)), (10, 10, 10), axes_order="ZYX"))
        with pytest.raises(base_settings.SwapTimeStackException):
            base_settings.BaseSettings.verify_image(Image(np.zeros(
                (10, 10, 10)), (10, 10, 10),
                                                          axes_order="TYX"),
                                                    silent=False)

        new_image = base_settings.BaseSettings.verify_image(Image(
            np.zeros((10, 10, 10)), (10, 10, 10), axes_order="TYX"),
                                                            silent=True)
        assert new_image.is_stack
        assert not new_image.is_time
        with pytest.raises(base_settings.TimeAndStackException):
            base_settings.BaseSettings.verify_image(Image(np.zeros(
                (2, 10, 10, 10)), (10, 10, 10),
                                                          axes_order="TZYX"),
                                                    silent=True)
def create_test_data(tmpdir):
    # for future use
    spacing = tuple(x / UNIT_SCALE[Units.nm.value] for x in (210, 70, 70))
    res = []
    for i in range(8):
        mask_data = np.zeros((10, 20, 20 + i), dtype=np.uint8)
        mask_data[1:-1, 2:-2, 2:-2] = 1
        data = np.zeros(mask_data.shape + (2, ), dtype=np.uint16)
        data[1:-1, 2:-2, 2:-2] = 15000
        data[2:-2, 3:-3, 3:7] = 33000
        data[2:-2, 3:-3, -7:-3] = 33000
        image = Image(data, spacing, "", mask=mask_data, axes_order="ZYXC")
        ImageWriter.save(image, os.path.join(str(tmpdir), f"file_{i}.tif"))
        res.append(os.path.join(str(tmpdir), f"file_{i}.tif"))
        ImageWriter.save_mask(image,
                              os.path.join(str(tmpdir), f"file_{i}_mask.tif"))
    return res
Exemple #28
0
def napari_write_labels(path: str, data: Any, meta: dict) -> Optional[str]:
    ext = os.path.splitext(path)[1]
    if not isinstance(data, numpy.ndarray) or ext not in {
            ".tiff", ".tif", ".TIFF", ".TIF"
    }:
        return
    scale_shift = min(data.ndim, 3)
    image = Image(
        data,
        numpy.divide(meta["scale"], DEFAULT_SCALE_FACTOR)[-scale_shift:],
        axes_order="TZXY"[-data.ndim:],
        channel_names=[meta["name"]],
        shift=numpy.divide(meta["translate"],
                           DEFAULT_SCALE_FACTOR)[-scale_shift:],
        name="ROI",
    )
    ImageWriter.save(image, path)
    return path
Exemple #29
0
def generate_image(viewer: Viewer, *layer_names):
    axis_order = Image.axis_order.replace("C", "")
    image_list = []
    for name in dict.fromkeys(layer_names):
        image_layer = viewer.layers[name]
        data_scale = image_layer.scale[-3:] / UNIT_SCALE[Units.nm.value]
        image_list.append(
            Image(
                image_layer.data,
                data_scale,
                axes_order=axis_order[-image_layer.data.ndim:],
                channel_names=[image_layer.name],
            ))
    res_image = image_list[0]
    for image in image_list[1:]:
        res_image = res_image.merge(image, "C")

    return res_image
Exemple #30
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)