Exemple #1
0
def test_get_centered_cutout():
    """Test getting a cutout of arbitrary size centered on the roi
    bounding box center.
    """
    rng = np.random.default_rng(1234)
    image = rng.integers(100, size=(512, 512), dtype='int16')
    width = 10
    height = 10
    x0 = 100
    y0 = 200
    mask = np.zeros((height, width), dtype=bool)
    mask[2, 4] = True
    mask[3, 6] = True
    roi = OphysROI(roi_id=1,
                   x0=x0,
                   y0=y0,
                   width=width,
                   height=height,
                   valid_roi=True,
                   mask_matrix=mask)

    cutout_size = 128
    cutout = roi.get_centered_cutout(image, cutout_size, cutout_size)
    np.testing.assert_array_equal(
        cutout,
        image[roi.bounding_box_center_y -
              cutout_size // 2:roi.bounding_box_center_y + cutout_size // 2,
              roi.bounding_box_center_x -
              cutout_size // 2:roi.bounding_box_center_x + cutout_size // 2])
Exemple #2
0
def ophys_roi_list_fixture():
    """
    List of OphysROI
    """
    output = []

    # construct an image with a bunch of connected
    # ROIs
    full_field = np.zeros((64, 64), dtype=int)
    full_field[32:49, 32:40] = 1
    full_field[20:34, 20:35] = 2
    full_field[34:38, 20:35] = 3
    full_field[32:37, 40:45] = 4
    full_field[32:37, 45:50] = 5
    full_field[10:17, 39:50] = 6
    full_field[10:17, 37:39] = 7
    full_field[5:10, 37:39] = 8
    full_field[34:46, 34:37] = 9

    for roi_id in range(1, 10, 1):
        valid = np.argwhere(full_field == roi_id)
        min_row = valid[:, 0].min()
        min_col = valid[:, 1].min()
        max_row = valid[:, 0].max()
        max_col = valid[:, 1].max()
        height = max_row-min_row+1
        width = max_col-min_col+1
        mask = np.zeros((height, width), dtype=bool)
        mask[valid[:, 0]-min_row, valid[:, 1]-min_col] = True
        roi = OphysROI(x0=int(min_col), width=int(width),
                       y0=int(min_row), height=int(height),
                       mask_matrix=mask,
                       roi_id=roi_id, valid_roi=True)
        output.append(roi)
    return output
Exemple #3
0
def test_roi_instantiation(ophys_plane_data_fixture):
    schema_dict = ophys_plane_data_fixture
    ct = 0
    for meta_pair in schema_dict['coupled_planes']:
        pair = meta_pair['planes']
        for plane in pair:
            for roi_args in plane['rois']:
                _ = OphysROI.from_schema_dict(roi_args)
                ct += 1
    assert ct == 8
Exemple #4
0
def test_get_roi_pixels():
    """
    Test method that maps a list of ROIs to a dict of pixels
    """

    roi_list = []
    expected_pixel_set = {}

    roi = OphysROI(x0=4,
                   y0=17,
                   width=5,
                   height=3,
                   mask_matrix=[[True, False, False, True, True],
                                [False, False, False, True, False],
                                [True, True, False, False, False]],
                   roi_id=0,
                   valid_roi=True)

    roi_list.append(roi)
    expected_pixel_set[0] = set([(4, 17), (7, 17), (8, 17), (7, 18), (4, 19),
                                 (5, 19)])

    roi = OphysROI(x0=9,
                   y0=7,
                   width=2,
                   height=5,
                   mask_matrix=[[False, False], [True, False], [False, True],
                                [False, False], [True, True]],
                   roi_id=1,
                   valid_roi=True)

    roi_list.append(roi)
    expected_pixel_set[1] = set([(9, 8), (10, 9), (9, 11), (10, 11)])

    result = get_roi_pixels(roi_list)

    assert len(result) == 2
    assert 0 in result
    assert 1 in result

    assert result[0] == expected_pixel_set[0]
    assert result[1] == expected_pixel_set[1]
    def from_schema_dict(cls, schema_dict):
        """
        Create an OphysPlane from a dict taken from the module's argschema

        Parameters
        ----------
        schema_dict -- a dict codifying the plane, as read from argschema, i.e.

        {  # start of ophys_experiment
         "ophys_experiment_id": ,# an int
         "motion_corrected_stack": ,  # path to h5 movie file
         "motion_border": {  # border widths
                 "x0": ,  # a float
                 "x1": ,  # a float
                 "y0": ,  # a float
                 "y1": ,  # a float
           },
           "rois": [  # list of dicts definining the ROIs for this experiment
               {  # start of individual ROI
                 "id":  ,  # an int
                 "x": ,  # an int
                 "y": ,  # an int
                 "width": ,  # an int
                 "height": ,  # an int
                 "valid_roi": ,  # boolean
                 "mask_matrix": [[]]  # 2-D array of booleans
               },  # end of individual ROI,
               {
                 "id":  ,
                 "x": ,
                 "y": ,
                 "width": ,
                 "height": ,
                 "valid_roi": ,
                 "mask_matrix": [[]]
               },
               ...
           ]
         }
        """
        roi_list = []
        for roi in schema_dict['rois']:
            roi_list.append(OphysROI.from_schema_dict(roi))

        max_path = None
        if 'maximum_projection_image_file' in schema_dict:
            max_path = schema_dict['maximum_projection_image_file']

        return cls(experiment_id=schema_dict['ophys_experiment_id'],
                   movie_path=schema_dict['motion_corrected_stack'],
                   motion_border=schema_dict['motion_border'],
                   roi_list=roi_list,
                   max_projection_path=max_path)
Exemple #6
0
def test_get_bound_box_cutout():
    """Test retrieval of a cutout of the roi bounding box.
    """
    rng = np.random.default_rng(1234)
    image = rng.integers(100, size=(512, 512), dtype='int16')
    width = 7
    height = 5
    x0 = 100
    y0 = 200
    mask = np.zeros((height, width), dtype=bool)
    mask[2, 4] = True
    mask[3, 6] = True
    roi = OphysROI(roi_id=1,
                   x0=x0,
                   y0=y0,
                   width=width,
                   height=height,
                   valid_roi=True,
                   mask_matrix=mask)

    cutout = roi.get_bounding_box_cutout(image)
    np.testing.assert_array_equal(cutout, image[y0:y0 + height, x0:x0 + width])
Exemple #7
0
def test_roi_global_pixel_set():
    width = 7
    height = 5
    mask = np.zeros((height, width), dtype=bool)
    mask[2, 4] = True
    mask[3, 6] = True
    roi = OphysROI(roi_id=1,
                   x0=100,
                   y0=200,
                   width=width,
                   height=height,
                   valid_roi=True,
                   mask_matrix=mask)
    assert roi.global_pixel_set == set([(202, 104), (203, 106)])
def example_ophys_roi_list_fixture():
    rng = np.random.default_rng(6412439)
    roi_list = []
    for ii in range(30):
        x0 = rng.integers(0, 25)
        y0 = rng.integers(0, 25)
        height = rng.integers(3, 7)
        width = rng.integers(3, 7)
        mask = rng.integers(0, 2, (height, width)).astype(bool)
        roi = OphysROI(x0=int(x0),
                       y0=int(y0),
                       height=int(height),
                       width=int(width),
                       mask_matrix=mask,
                       roi_id=ii,
                       valid_roi=True)
        roi_list.append(roi)

    return roi_list
Exemple #9
0
def extract_roi_to_ophys_roi(roi: ExtractROI) -> OphysROI:
    """
    Convert an ExtractROI to an equivalent OphysROI

    Parameters
    ----------
    ExtractROI

    Returns
    -------
    OphysROI
    """
    new_roi = OphysROI(x0=int(roi['x']),
                       y0=int(roi['y']),
                       width=int(roi['width']),
                       height=int(roi['height']),
                       mask_matrix=roi['mask'],
                       roi_id=int(roi['id']),
                       valid_roi=roi['valid'])

    return new_roi
Exemple #10
0
def test_add_roi_contour_to_img(alpha):
    """Test that add_roi_contour_to_img creates an image with
    the expected contours of the expected colors"""
    img = 100 * np.ones((64, 64, 3), dtype=int)

    height = 7
    width = 12

    mask = np.zeros((height, width), dtype=bool)
    mask[1, 5:7] = True
    mask[2, 4:8] = True
    mask[3, 3:9] = True
    mask[4, 2:10] = True
    mask[5, 3:9] = True

    bdry_pixels = set([(1, 5), (1, 6), (2, 4), (2, 7), (3, 3), (3, 8), (4, 2),
                       (4, 9), (5, 3), (5, 4), (5, 5), (5, 6), (5, 7), (5, 8)])

    roi = OphysROI(x0=20,
                   width=width,
                   y0=15,
                   height=height,
                   valid_roi=True,
                   roi_id=0,
                   mask_matrix=mask)

    color = (22, 33, 44)
    img = add_roi_contour_to_img(img, roi, color, alpha)

    for row in range(height):
        for col in range(width):
            for ic in range(3):
                if (row, col) not in bdry_pixels:
                    assert img[15 + row, 20 + col, ic] == 100
                else:
                    expected = np.round(alpha * color[ic] +
                                        (1.0 - alpha) * 100).astype(int)
                    assert img[15 + row, 20 + col, ic] == expected
def add_roi_contour_to_video(sub_video: np.ndarray,
                             origin: Tuple[int, int],
                             roi: ExtractROI,
                             roi_color: Tuple[int, int, int]) -> np.ndarray:
    """
    Add the contour of an ROI to a video

    Parameters
    ----------
    sub_video: np.ndarray
        The video as an RGB movie. Shape is (n_t, nrows, ncols, 3)

    origin: Tuple[int, int]
        global (rowmin, colmin) of the video in sub_video

    roi: ExtractROI
        The parameters of this ROI are in global coordinates,
        which is why we need origin as an argument

    roi_color: Tuple[int, int, int]
        RGB color of the ROI contour

    Returns
    -------
    sub_video: np.ndarray
        sub_video with the ROI contour

    Note:
    -----
    While it does return a np.ndarray, this method will change
    sub_video in-place
    """

    n_video_rows = sub_video.shape[1]
    n_video_cols = sub_video.shape[2]

    # construct an ROI object to get the contour mask
    # for us
    ophys_roi = OphysROI(roi_id=-1,
                         x0=roi['x'],
                         y0=roi['y'],
                         width=roi['width'],
                         height=roi['height'],
                         valid_roi=False,
                         mask_matrix=roi['mask'])

    contour_mask = ophys_roi.contour_mask
    for irow in range(contour_mask.shape[0]):
        row = irow+ophys_roi.y0-origin[0]
        if row < 0 or row >= n_video_rows:
            continue
        for icol in range(contour_mask.shape[1]):
            if not contour_mask[irow, icol]:
                continue
            col = icol+ophys_roi.x0-origin[1]
            if col < 0 or col >= n_video_cols:
                continue
            for i_color in range(3):
                sub_video[:, row, col, i_color] = roi_color[i_color]

    return sub_video
def test_roi_abut():

    height = 6
    width = 7
    mask = np.zeros((height, width), dtype=bool)
    mask[1:5, 1:6] = True

    # overlapping
    roi0 = OphysROI(x0=22,
                    y0=44,
                    height=height,
                    width=width,
                    mask_matrix=mask,
                    roi_id=0,
                    valid_roi=True)

    roi1 = OphysROI(x0=23,
                    y0=46,
                    height=height,
                    width=width,
                    mask_matrix=mask,
                    roi_id=1,
                    valid_roi=True)

    assert rois_utils.do_rois_abut(roi0, roi1, pixel_distance=1.0)

    # just touching
    roi1 = OphysROI(x0=26,
                    y0=48,
                    height=height,
                    width=width,
                    mask_matrix=mask,
                    roi_id=1,
                    valid_roi=True)

    assert rois_utils.do_rois_abut(roi0, roi1, pixel_distance=1.0)

    roi1 = OphysROI(x0=27,
                    y0=48,
                    height=height,
                    width=width,
                    mask_matrix=mask,
                    roi_id=1,
                    valid_roi=True)

    assert not rois_utils.do_rois_abut(roi0, roi1, pixel_distance=1.0)

    # they are, however, just diagonally 1 pixel away
    # from each other
    assert rois_utils.do_rois_abut(roi0, roi1, pixel_distance=np.sqrt(2))

    # gap of one pixel
    assert rois_utils.do_rois_abut(roi0, roi1, pixel_distance=2)

    roi1 = OphysROI(x0=28,
                    y0=48,
                    height=height,
                    width=width,
                    mask_matrix=mask,
                    roi_id=1,
                    valid_roi=True)

    assert not rois_utils.do_rois_abut(roi0, roi1, pixel_distance=2)
Exemple #13
0
def test_find_overlapping_roi_pairs():

    roi_list_0 = []
    roi_list_1 = []

    roi = OphysROI(x0=4,
                   y0=5,
                   width=4,
                   height=3,
                   mask_matrix=[[True, False, False, True],
                                [False, True, True, False],
                                [False, True, False, False]],
                   roi_id=0,
                   valid_roi=True)

    roi_list_0.append(roi)

    # photo-negative of roi_0
    roi = OphysROI(x0=4,
                   y0=5,
                   width=4,
                   height=3,
                   mask_matrix=[[False, True, True, False],
                                [True, False, False, True],
                                [True, False, True, True]],
                   roi_id=1,
                   valid_roi=True)

    roi_list_1.append(roi)

    # intersects one point of roi_0
    roi = OphysROI(x0=6,
                   y0=6,
                   width=2,
                   height=3,
                   mask_matrix=[[True, False], [True, True], [True, True]],
                   roi_id=2,
                   valid_roi=True)

    roi_list_1.append(roi)

    # no intersection with roi_0
    roi = OphysROI(x0=6,
                   y0=6,
                   width=2,
                   height=3,
                   mask_matrix=[[False, False], [True, True], [True, True]],
                   roi_id=3,
                   valid_roi=True)

    roi_list_1.append(roi)

    # one corner overlaps with roi_2 and roi_3
    roi = OphysROI(x0=7,
                   y0=8,
                   width=3,
                   height=4,
                   mask_matrix=[[True, True, False], [True, True, True],
                                [True, True, True], [True, True, True]],
                   roi_id=4,
                   valid_roi=True)

    roi_list_0.append(roi)

    # no overlaps
    roi = OphysROI(x0=7,
                   y0=8,
                   width=3,
                   height=4,
                   mask_matrix=[[False, False, False], [True, True, True],
                                [True, True, True], [True, True, True]],
                   roi_id=5,
                   valid_roi=True)

    roi_list_0.append(roi)

    overlap_list = find_overlapping_roi_pairs(roi_list_0, roi_list_1)

    assert len(overlap_list) == 3
    assert (0, 2, 1 / 5, 1 / 5) in overlap_list
    assert (4, 3, 1 / 11, 1 / 4) in overlap_list
    assert (4, 2, 1 / 11, 1 / 5) in overlap_list
Exemple #14
0
def test_get_img_thumbnails(x0, y0, x1, y1):
    """
    Test that, when fed two ROIs that are very distant and do not
    overlap, get_img_thumbnails returns bounds
    (xmin, xmax), (ymin, ymax) bounds that cover both ROIs
    """
    this_dir = pathlib.Path(__file__).parent.resolve()
    data_dir = this_dir / 'data/qc_plotting'

    roi0 = OphysROI(x0=x0,
                    y0=y0,
                    width=3,
                    height=4,
                    mask_matrix=[[False, False, False], [True, True, True],
                                 [True, True, True], [True, True, True]],
                    roi_id=5,
                    valid_roi=True)

    roi1 = OphysROI(x0=x1,
                    y0=y1,
                    width=3,
                    height=4,
                    mask_matrix=[[False, False, False], [True, True, True],
                                 [True, True, True], [True, True, True]],
                    roi_id=5,
                    valid_roi=True)

    img_fname = '1071738402_suite2p_maximum_projection.png'
    raw_img = PIL.Image.open(data_dir / img_fname, mode='r')
    n_rows = raw_img.size[0]
    n_cols = raw_img.size[1]
    max_img = np.array(raw_img).reshape(n_rows, n_cols)

    (img0, img1, (xmin, xmax),
     (ymin, ymax)) = get_img_thumbnails(roi0, roi1, max_img, max_img)

    mask = roi0.mask_matrix
    for ix in range(mask.shape[1]):
        xx = ix + roi0.x0
        for iy in range(mask.shape[0]):
            yy = iy + roi0.y0
            if mask[iy, ix]:
                assert yy >= ymin
                assert yy < ymax
                assert xx >= xmin
                assert xx < xmax

    mask = roi1.mask_matrix
    for ix in range(mask.shape[1]):
        xx = ix + roi1.x0
        for iy in range(mask.shape[0]):
            yy = iy + roi1.y0
            if mask[iy, ix]:
                assert yy >= ymin
                assert yy < ymax
                assert xx >= xmin
                assert xx < xmax
    assert xmin >= 0
    assert ymin >= 0
    assert xmax <= 512
    assert ymax <= 512