예제 #1
0
def test_image_reconstruction_rgb_missing_metadata(rgb_alignment_image_data):
    # no metadata
    reference_image, warped_image, description, bit_depth = rgb_alignment_image_data
    with pytest.warns(
        UserWarning, match="File does not contain metadata. Only raw data is available"
    ):
        fake_tiff = TiffStack(
            MockTiffFile(
                data=[warped_image], times=make_frame_times(1), description="", bit_depth=16
            ),
            align_requested=True,
        )

    # missing alignment matrices
    for label in ("Alignment red channel", "Channel 0 alignment"):
        if label in description:
            removed = description.pop(label)
            break
    with pytest.warns(
        UserWarning, match="File does not contain alignment matrices. Only raw data is available"
    ):
        fake_tiff = TiffStack(
            MockTiffFile(
                data=[warped_image],
                times=make_frame_times(1),
                description=json.dumps(description),
                bit_depth=16,
            ),
            align_requested=True,
        )

    description[label] = removed  # reset fixture
예제 #2
0
def test_plotting(rgb_alignment_image_data):
    reference_image, warped_image, description, bit_depth = rgb_alignment_image_data
    fake_tiff = TiffStack(
        MockTiffFile(
            data=[warped_image] * 2,
            times=make_frame_times(2),
            description=json.dumps(description),
            bit_depth=16,
        ),
        align_requested=True,
    )
    stack = CorrelatedStack.from_dataset(fake_tiff)

    stack.plot(channel="blue", frame=0)
    ref_image = stack._get_frame(0)._get_plot_data(channel="blue")
    image = plt.gca().get_images()[0]
    np.testing.assert_allclose(image.get_array(), ref_image)
    plt.close()

    stack.plot(channel="rgb", frame=0)
    ref_image = stack._get_frame(0)._get_plot_data(channel="rgb")
    image = plt.gca().get_images()[0]
    np.testing.assert_allclose(image.get_array(), ref_image)
    plt.close()

    with pytest.raises(IndexError, match="Frame index out of range"):
        stack.plot(channel="blue", frame=4)

    with pytest.raises(IndexError, match="Frame index out of range"):
        stack.plot(channel="blue", frame=-1)
예제 #3
0
def make_mock_stack():
    spot_coordinates = ((25, 25), (50, 50))
    warp_parameters = {
        "red_warp_parameters": {
            "Tx": 0,
            "Ty": 0,
            "theta": 0
        },
        "blue_warp_parameters": {
            "Tx": 0,
            "Ty": 0,
            "theta": 0
        },
    }
    _, image, description, bit_depth = make_alignment_image_data(
        spot_coordinates,
        version=2,
        bit_depth=16,
        camera="wt",
        **warp_parameters)

    tiff = TiffStack(
        MockTiffFile(
            data=[image, image, image],
            times=[["10", "18"], ["20", "28"], ["30", "38"]],
            description=json.dumps(description),
            bit_depth=bit_depth,
        ),
        align_requested=True,
    )

    return CorrelatedStack.from_dataset(tiff)
예제 #4
0
def test_deprecate_raw():
    fake_tiff = TiffStack(MockTiffFile(data=[np.ones((5, 4, 3))],
                                       times=make_frame_times(1)),
                          align_requested=False)
    stack = CorrelatedStack.from_dataset(fake_tiff)

    with pytest.deprecated_call():
        stack.raw
예제 #5
0
 def make_stack(data, description, bit_depth):
     tiff = TiffStack(
         MockTiffFile(
             data=[data],
             times=make_frame_times(1),
             description=json.dumps(description),
             bit_depth=bit_depth,
         ),
         align_requested=True,
     )
     return CorrelatedStack.from_dataset(tiff)
예제 #6
0
def test_get_image():
    # grayscale image - multiple frames
    data = [np.full((2, 2), j) for j in range(3)]
    times = make_frame_times(3)

    fake_tiff = TiffStack(MockTiffFile(data, times), align_requested=False)
    stack = CorrelatedStack.from_dataset(fake_tiff)
    np.testing.assert_array_equal(np.stack(data, axis=0), stack.get_image())

    # grayscale image - single frame
    fake_tiff = TiffStack(MockTiffFile([data[0]], [times[0]]),
                          align_requested=False)
    stack = CorrelatedStack.from_dataset(fake_tiff)
    np.testing.assert_array_equal(data[0], stack.get_image())

    # RGB image - multiple frames
    rgb_data = np.stack([np.full((2, 2), j) for j in range(3)], axis=2)
    data = [rgb_data] * 3

    fake_tiff = TiffStack(MockTiffFile(data, times), align_requested=False)
    stack = CorrelatedStack.from_dataset(fake_tiff)

    for j, color in enumerate(("red", "green", "blue")):
        np.testing.assert_array_equal(stack.get_image(channel=color),
                                      j,
                                      err_msg=f"failed on {color}")
    np.testing.assert_array_equal(np.stack(data, axis=0), stack.get_image())
    np.testing.assert_array_equal(np.stack(data, axis=0),
                                  stack.get_image(channel="rgb"))

    # RGB image - multiple frames
    fake_tiff = TiffStack(MockTiffFile([data[0]], [times[0]]),
                          align_requested=False)
    stack = CorrelatedStack.from_dataset(fake_tiff)

    for j, color in enumerate(("red", "green", "blue")):
        np.testing.assert_array_equal(stack.get_image(channel=color),
                                      data[0][:, :, j],
                                      err_msg=f"failed on {color}")
    np.testing.assert_array_equal(data[0], stack.get_image())
    np.testing.assert_array_equal(data[0], stack.get_image("rgb"))
예제 #7
0
def test_no_alignment_requested(rgb_alignment_image_data):
    reference_image, warped_image, description, bit_depth = rgb_alignment_image_data
    fake_tiff = TiffStack(
        MockTiffFile(
            data=[warped_image],
            times=make_frame_times(1),
            description=json.dumps(description),
            bit_depth=16,
        ),
        align_requested=False,
    )
    stack = CorrelatedStack.from_dataset(fake_tiff)
    fr = stack._get_frame(0)
    np.testing.assert_allclose(fr.data, warped_image)
예제 #8
0
def test_stack_roi():
    first_page = np.arange(60).reshape((6, 10))
    data = np.stack([first_page + (j * 60) for j in range(3)], axis=2)
    stack_0 = TiffStack(MockTiffFile([data], times=make_frame_times(1)),
                        align_requested=False)

    # recursive cropping
    stack_1 = stack_0.with_roi([1, 7, 3, 6])
    np.testing.assert_equal(stack_1.get_frame(0).data, data[3:6, 1:7, :])

    stack_2 = stack_1.with_roi([3, 6, 0, 3])
    np.testing.assert_equal(stack_2.get_frame(0).data, data[3:6, 4:7, :])

    stack_3 = stack_2.with_roi([1, 2, 1, 2])
    np.testing.assert_equal(stack_3.get_frame(0).data, data[4:5, 5:6, :])

    # negative indices
    with pytest.raises(ValueError):
        stack_4 = stack_0.with_roi([-5, 4, 1, 2])

    # out of bounds
    with pytest.raises(ValueError):
        stack_5 = stack_0.with_roi([0, 11, 1, 2])
예제 #9
0
def test_correlated_stack(shape):
    fake_tiff = TiffStack(MockTiffFile(data=[np.ones(shape)] * 6,
                                       times=make_frame_times(6)),
                          align_requested=False)
    stack = CorrelatedStack.from_dataset(fake_tiff)

    assert stack[0].start == 10
    assert stack[1].start == 20
    assert stack[-1].start == 60
    assert stack[0].num_frames == 1

    assert stack[0].stop == 18
    assert stack[-1].stop == 68

    assert stack[1:2].stop == 28
    assert stack[1:3].stop == 38
    assert stack[1:2].num_frames == 1
    assert stack[1:3].num_frames == 2

    assert stack[3:5][0].start == 40
    assert stack[3:5][1].start == 50
    assert stack[3:5][0].num_frames == 1

    with pytest.raises(IndexError):
        stack[3:5][2]

    assert stack[2:5][1:2].start == 40
    assert stack[2:5][1:3]._get_frame(1).start == 50

    with pytest.raises(IndexError):
        stack[::2]

    with pytest.raises(IndexError):
        stack[1:2]._get_frame(1).stop

    # Integration test whether slicing from the stack object actually provides you with correct slices
    np.testing.assert_allclose(stack[2:5].start, 30)
    np.testing.assert_allclose(stack[2:5].stop, 58)

    # Test iterations
    np.testing.assert_allclose([x.start for x in stack],
                               [10, 20, 30, 40, 50, 60])
    np.testing.assert_allclose([x.start for x in stack[1:]],
                               [20, 30, 40, 50, 60])
    np.testing.assert_allclose([x.start for x in stack[:-1]],
                               [10, 20, 30, 40, 50])
    np.testing.assert_allclose([x.start for x in stack[2:4]], [30, 40])
    np.testing.assert_allclose([x.start for x in stack[2]], [30])
예제 #10
0
def test_slicing(shape):
    image = [np.random.poisson(10, size=shape) for _ in range(10)]
    times = make_frame_times(10)
    fake_tiff = TiffStack(MockTiffFile(data=image, times=times),
                          align_requested=False)
    stack0 = CorrelatedStack.from_dataset(fake_tiff)

    def compare_frames(original_frames, new_stack):
        assert new_stack.num_frames == len(original_frames)
        for new_frame_index, index in enumerate(original_frames):
            frame = stack0._get_frame(index).data
            new_frame = new_stack._get_frame(new_frame_index).data
            np.testing.assert_equal(frame, new_frame)

    compare_frames([0], stack0[0])  # first frame
    compare_frames([9], stack0[-1])  # last frame
    compare_frames([3], stack0[3])  # single frame
    compare_frames([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], stack0[:])  # all frames
    compare_frames([3, 4, 5], stack0[3:6])  # normal slice
    compare_frames([0, 1, 2], stack0[:3])  # from beginning
    compare_frames([6, 7, 8, 9], stack0[6:])  # until end
    compare_frames([0, 1, 2, 3, 4, 5], stack0[:-4])  # until negative index
    compare_frames([5, 6, 7], stack0[5:-2])  # mixed sign indices
    compare_frames([6, 7], stack0[-4:-2])  # negative indices slice

    compare_frames([3, 4], stack0[2:6][1:3])  # iterative slicing

    compare_frames([1, 2, 3, 4, 5, 6, 7, 8, 9],
                   stack0[1:100])  # test clamping past the end
    compare_frames([0, 1, 2, 3, 4, 5, 6, 7, 8],
                   stack0[-100:9])  # test clamping past the beginning
    compare_frames([0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
                   stack0[-100:100])  # test clamping both dirs

    # reverse slice
    with pytest.raises(NotImplementedError,
                       match="Reverse slicing is not supported"):
        stack0[5:2]

    # reverse slice, negative indices
    with pytest.raises(NotImplementedError,
                       match="Reverse slicing is not supported"):
        stack0[-1:-3]

    # empty slice
    with pytest.raises(NotImplementedError, match="Slice is empty"):
        stack0[5:5]
예제 #11
0
def test_image_reconstruction_grayscale(gray_alignment_image_data):
    reference_image, warped_image, description, bit_depth = gray_alignment_image_data
    fake_tiff = TiffStack(
        MockTiffFile(
            data=[warped_image],
            times=make_frame_times(1),
            description=json.dumps(description),
            bit_depth=8,
        ),
        align_requested=True,
    )
    stack = CorrelatedStack.from_dataset(fake_tiff)
    fr = stack._get_frame(0)

    assert not fr.is_rgb
    assert np.all(fr.data == fr.raw_data)
    np.testing.assert_allclose(fr.raw_data, fr._get_plot_data())
예제 #12
0
def test_plot_correlated_smaller_channel():
    from matplotlib.backend_bases import MouseEvent

    # Regression test for a bug where the start index was added twice. In the regression, this lead to an out of range
    # error.
    fake_tiff = TiffStack(
        MockTiffFile(
            data=[
                np.zeros((3, 3)),
                np.ones((3, 3)),
                np.ones((3, 3)) * 2,
                np.ones((3, 3)) * 3,
                np.ones((3, 3)) * 4,
                np.ones((3, 3)) * 5,
            ],
            times=make_frame_times(7, step=10),
        ),
        align_requested=False,
    )

    # Add test for when there's only a subset in terms of channel data
    cc = channel.Slice(channel.Continuous(np.arange(10, 80, 2), 30, 2), {
        "y": "mock",
        "title": "mock"
    })

    with pytest.warns(UserWarning):
        CorrelatedStack.from_dataset(fake_tiff).plot_correlated(cc)

    def mock_click(fig, data_position):
        pos = fig.axes[0].transData.transform(data_position)
        fig.canvas.callbacks.process(
            "button_press_event",
            MouseEvent("button_press_event", fig.canvas, pos[0], pos[1], 1))
        images = [
            obj for obj in mpl.pyplot.gca().get_children()
            if isinstance(obj, mpl.image.AxesImage)
        ]
        assert len(images) == 1
        return images[0].get_array()

    np.testing.assert_allclose(mock_click(mpl.pyplot.gcf(), np.array([0, 40])),
                               np.ones((3, 3)) * 2)
    np.testing.assert_allclose(
        mock_click(mpl.pyplot.gcf(), np.array([10.1e-9, 40])),
        np.ones((3, 3)) * 3)
예제 #13
0
def test_image_reconstruction_rgb_multiframe(rgb_alignment_image_data):
    reference_image, warped_image, description, bit_depth = rgb_alignment_image_data
    fake_tiff = TiffStack(
        MockTiffFile(
            data=[warped_image] * 6,
            times=make_frame_times(6, step=10),
            description=json.dumps(description),
            bit_depth=16,
        ),
        align_requested=True,
    )
    stack = CorrelatedStack.from_dataset(fake_tiff)
    fr = stack._get_frame(2)

    assert fr.is_rgb
    original_data = (reference_image / (2 ** bit_depth - 1)).astype(float)
    np.testing.assert_allclose(original_data, fr._get_plot_data(), atol=0.05)
예제 #14
0
def test_plot_correlated():
    cc = channel.Slice(channel.Continuous(np.arange(10, 80, 2), 10, 2), {
        "y": "mock",
        "title": "mock"
    })

    # Regression test for a bug where the start index was added twice. In the regression, this lead to an out of range
    # error.
    fake_tiff = TiffStack(
        MockTiffFile(
            data=[
                np.zeros((3, 3)),
                np.ones((3, 3)),
                np.ones((3, 3)) * 2,
                np.ones((3, 3)) * 3,
                np.ones((3, 3)) * 4,
                np.ones((3, 3)) * 5,
            ],
            times=make_frame_times(7, step=10),
        ),
        align_requested=False,
    )

    CorrelatedStack.from_dataset(fake_tiff)[3:5].plot_correlated(cc)
    imgs = [
        obj for obj in mpl.pyplot.gca().get_children()
        if isinstance(obj, mpl.image.AxesImage)
    ]
    assert len(imgs) == 1
    np.testing.assert_allclose(imgs[0].get_array(), np.ones((3, 3)) * 3)

    CorrelatedStack.from_dataset(fake_tiff)[3:5].plot_correlated(cc, frame=1)
    imgs = [
        obj for obj in mpl.pyplot.gca().get_children()
        if isinstance(obj, mpl.image.AxesImage)
    ]
    assert len(imgs) == 1
    np.testing.assert_allclose(imgs[0].get_array(), np.ones((3, 3)) * 4)
예제 #15
0
def test_image_reconstruction_rgb(rgb_alignment_image_data, rgb_alignment_image_data_offset):
    reference_image, warped_image, description, bit_depth = rgb_alignment_image_data
    fake_tiff = TiffStack(
        MockTiffFile(
            data=[warped_image],
            times=make_frame_times(1),
            description=json.dumps(description),
            bit_depth=16,
        ),
        align_requested=True,
    )
    stack = CorrelatedStack.from_dataset(fake_tiff)
    fr = stack._get_frame(0)

    assert fr.is_rgb
    max_signal = np.max(np.hstack([fr._get_plot_data("green"), fr._get_plot_data("red")]))
    diff = np.abs(fr._get_plot_data("green").astype(float) - fr._get_plot_data("red").astype(float))
    assert np.all(diff / max_signal < 0.05)
    max_signal = np.max(np.hstack([fr._get_plot_data("green"), fr._get_plot_data("blue")]))
    diff = np.abs(
        fr._get_plot_data("green").astype(float) - fr._get_plot_data("blue").astype(float)
    )
    assert np.all(diff / max_signal < 0.05)

    original_data = (reference_image / (2 ** bit_depth - 1)).astype(float)
    np.testing.assert_allclose(original_data, fr._get_plot_data(), atol=0.05)
    np.testing.assert_allclose(original_data / 0.5, fr._get_plot_data(vmax=0.5), atol=0.10)
    max_signal = np.max(np.hstack([reference_image[:, :, 0], fr._get_plot_data("red")]))
    diff = np.abs(reference_image[:, :, 0].astype(float) - fr._get_plot_data("red").astype(float))
    assert np.all(diff / max_signal < 0.05)

    with pytest.raises(ValueError):
        fr._get_plot_data(channel="purple")

    # test that bad alignment matrix gives high error compared to correct matrix
    bad_description = deepcopy(description)
    label = (
        "Alignment red channel"
        if "Alignment red channel" in description.keys()
        else "Channel 0 alignment"
    )
    bad_description[label][2] = 25
    fake_tiff = TiffStack(
        MockTiffFile(
            data=[warped_image],
            times=make_frame_times(1),
            description=json.dumps(bad_description),
            bit_depth=16,
        ),
        align_requested=True,
    )
    stack = CorrelatedStack.from_dataset(fake_tiff)
    fr = stack._get_frame(0)

    assert fr.is_rgb
    assert not np.allclose(original_data, fr._get_plot_data(), atol=0.05)

    reference_image, warped_image, description, bit_depth = rgb_alignment_image_data_offset
    fake_tiff = TiffStack(
        MockTiffFile(
            data=[warped_image],
            times=make_frame_times(1),
            description=json.dumps(description),
            bit_depth=16,
        ),
        align_requested=True,
    )
    stack = CorrelatedStack.from_dataset(fake_tiff)
    fr = stack._get_frame(0)

    original_data = (reference_image / (2 ** bit_depth - 1)).astype(float)
    np.testing.assert_allclose(original_data, fr._get_plot_data(), atol=0.05)
예제 #16
0
def test_name_change_from_data():
    fake_tiff = TiffStack(MockTiffFile(data=[np.ones((5, 4, 3))],
                                       times=make_frame_times(1)),
                          align_requested=False)
    with pytest.deprecated_call():
        CorrelatedStack.from_data(fake_tiff)
예제 #17
0
def test_correlation(shape):
    cc = channel.Slice(channel.Continuous(np.arange(10, 80, 2), 10, 2))

    # Test image stack without dead time
    fake_tiff = TiffStack(
        MockTiffFile(data=[np.ones(shape)] * 6,
                     times=make_frame_times(6, step=10)),
        align_requested=False,
    )
    stack = CorrelatedStack.from_dataset(fake_tiff)
    np.testing.assert_allclose(
        np.hstack([cc[x.start:x.stop].data for x in stack[2:4]]),
        np.arange(30, 50, 2))

    # Test image stack with dead time
    fake_tiff = TiffStack(MockTiffFile(data=[np.ones(shape)] * 6,
                                       times=make_frame_times(6)),
                          align_requested=False)
    stack = CorrelatedStack.from_dataset(fake_tiff)

    np.testing.assert_allclose(
        np.hstack([cc[x.start:x.stop].data for x in stack[2:4]]),
        np.hstack([np.arange(30, 38, 2),
                   np.arange(40, 48, 2)]),
    )

    # Unit test which tests whether we obtain an appropriately downsampled time series when ask for downsampling of a
    # slice based on a stack.
    ch = cc.downsampled_over(stack[0:3].frame_timestamp_ranges)
    np.testing.assert_allclose(
        ch.data,
        [
            np.mean(np.arange(10, 18, 2)),
            np.mean(np.arange(20, 28, 2)),
            np.mean(np.arange(30, 38, 2)),
        ],
    )
    np.testing.assert_allclose(ch.timestamps, [(10 + 16) / 2, (20 + 26) / 2,
                                               (30 + 36) / 2])

    ch = cc.downsampled_over(stack[1:4].frame_timestamp_ranges)
    np.testing.assert_allclose(
        ch.data,
        [
            np.mean(np.arange(20, 28, 2)),
            np.mean(np.arange(30, 38, 2)),
            np.mean(np.arange(40, 48, 2)),
        ],
    )
    np.testing.assert_allclose(ch.timestamps, [(20 + 26) / 2, (30 + 36) / 2,
                                               (40 + 46) / 2])

    with pytest.raises(TypeError):
        cc.downsampled_over(stack[1:4])

    with pytest.raises(ValueError):
        cc.downsampled_over(stack[1:4].frame_timestamp_ranges, where="up")

    with pytest.raises(AssertionError):
        cc["0ns":"20ns"].downsampled_over(stack[3:4].frame_timestamp_ranges)

    with pytest.raises(AssertionError):
        cc["40ns":"70ns"].downsampled_over(stack[0:1].frame_timestamp_ranges)

    assert stack[0]._get_frame(0).start == 10
    assert stack[1]._get_frame(0).start == 20
    assert stack[1:3]._get_frame(0).start == 20
    assert stack[1:3]._get_frame(0).start == 20
    assert stack[1:3]._get_frame(1).start == 30

    # Regression test downsampled_over losing precision due to reverting to double rather than int64.
    cc = channel.Slice(
        channel.Continuous(np.arange(10, 80, 2), 1588267266006287100, 1000))
    ch = cc.downsampled_over([(1588267266006287100, 1588267266006287120)],
                             where="left")
    assert int(ch.timestamps[0]) == 1588267266006287100