def test_generate_props_from_mask(spot_and_mask): im_spot, mask_spot = spot_and_mask prop = regionprop.SpotRegionprop(row_idx=2, col_idx=1, label=4) bbox = [5, 10, 40, 45] bg_spot = np.zeros_like(im_spot) + 1. prop.generate_props_from_mask(im_spot, bg_spot, mask_spot, bbox) assert prop.label == 4 # Stats for dataframe assert 29 <= prop.spot_dict['centroid_row'] <= 30 assert 34 <= prop.spot_dict['centroid_col'] <= 35 assert prop.spot_dict['bbox_row_min'] == 18 assert prop.spot_dict['bbox_col_min'] == 23 assert prop.spot_dict['bbox_row_max'] == 42 assert prop.spot_dict['bbox_col_max'] == 47 assert prop.spot_dict['intensity_mean'] == np.mean(im_spot[mask_spot > 0]) assert prop.spot_dict['intensity_median'] == np.median(im_spot[mask_spot > 0]) assert prop.spot_dict['bg_mean'] == 1. assert prop.spot_dict['bg_median'] == 1. assert prop.spot_dict['od_norm'] == np.log10( 1. / prop.spot_dict['intensity_median'], ) # ROIs assert prop.image.all() == im_spot.all() assert prop.mask.all() == mask_spot.all() assert prop.masked_image.all() == (im_spot * mask_spot).all()
def test_generate_props_from_disk(spot_and_mask): im_spot, _ = spot_and_mask bg_spot = np.zeros_like(im_spot) + 0.5 prop = regionprop.SpotRegionprop(row_idx=0, col_idx=2, label=3) bbox = [5, 10, 35, 45] centroid = [25, 26] prop.generate_props_from_disk(im_spot, bg_spot, bbox, centroid) assert prop.label == 3 # Stats for dataframe assert prop.spot_dict['centroid_row'] == centroid[0] assert prop.spot_dict['centroid_col'] == centroid[1] assert prop.spot_dict['bbox_row_min'] == bbox[0] assert prop.spot_dict['bbox_col_min'] == bbox[1] assert prop.spot_dict['bbox_row_max'] == bbox[2] assert prop.spot_dict['bbox_col_max'] == bbox[3] assert prop.spot_dict['intensity_mean'] > 0 assert prop.spot_dict['intensity_median'] > 0.8 assert prop.spot_dict['intensity_median'] < 0.81 assert prop.spot_dict['bg_mean'] == 0.5 assert prop.spot_dict['bg_median'] == 0.5 assert prop.spot_dict['od_norm'] == np.log10( 0.5 / prop.spot_dict['intensity_median'], ) # ROIs assert prop.image.all() == im_spot.all() assert prop.background.all() == bg_spot.all() mask = prop.make_mask(im_spot.shape[0]) assert prop.mask.all() == mask.all() assert prop.masked_image.all() == (im_spot * mask).all()
def test_regionprop_init(): prop = regionprop.SpotRegionprop(row_idx=2, col_idx=3, label=5) assert prop.label == 5 assert prop.spot_dict['grid_row'] == 2 assert prop.spot_dict['grid_col'] == 3 assert prop.image is None assert prop.background is None assert prop.mask is None assert prop.masked_image is None
def test_compute_stats(spot_and_mask): im_spot, mask_spot = spot_and_mask prop = regionprop.SpotRegionprop(row_idx=4, col_idx=5, label=1) prop.image = im_spot prop.mask = mask_spot prop.background = np.zeros_like(im_spot) + 0.5 prop.compute_stats() assert prop.label == 1 assert prop.spot_dict['intensity_median'] < 0.3 assert prop.spot_dict['bg_median'] == 0.5 assert prop.spot_dict['od_norm'] == np.log10( 0.5 / prop.spot_dict['intensity_median'], )
def get_spot_intensity(coords, im, background, search_range=3): """ Extract signal and background intensity at each spot given the spot coordinate with the following steps: 1. crop image around each grid point 2. Segment 1 single spot from each image 3. Get median intensity, background and OD within the spot mask 4. If segmentation in 2. returns no mask, use a circular mask with average spot size as the spot mask and do 3. :param coords: list or tuple [row, col] coordinates of spots :param im: ndarray intensity image of the spots (signals) :param background: ndarray background image without spots :param float search_range: Factor of bounding box size in which to search for spots. E.g. 2 searches 2 * 2 * bbox width * bbox height :return pd.DataFrame spots_df: Dataframe containing metrics for all spots in the grid :return np.array spot_props: A SpotRegionprop object with ROIs for each spot in the grid """ # values in mm spot_width = constants.params['spot_width'] pix_size = constants.params['pixel_size'] n_rows = constants.params['rows'] n_cols = constants.params['columns'] # make spot size always odd spot_size = 2 * int(0.3 * spot_width / pix_size) + 1 bbox_width = bbox_height = spot_size # Strel disk size for spot segmentation disk_size = int(np.rint(spot_size / 2.5)) # Array of SpotRegionprop objects to hold ROIs spot_props = txt_parser.create_array(n_rows, n_cols, dtype=object) # Dataframe to hold spot metrics for the well spots_df = pd.DataFrame(columns=constants.SPOT_DF_COLS) row_col_iter = itertools.product(np.arange(n_rows), np.arange(n_cols)) for count, (row_idx, col_idx) in enumerate(row_col_iter): coord = coords[count, :] # make bounding boxes larger to account for interpolation errors spot_height = int(np.round(search_range * bbox_height)) spot_width = int(np.round(search_range * bbox_width)) # Create large bounding box around spot and segment im_spot_lg, bbox_lg = img_processing.crop_image_at_center( im=im, center=coord, height=spot_height, width=spot_width, ) mask_spot = img_processing.thresh_and_binarize( image=im_spot_lg, method='bright_spots', disk_size=disk_size, thr_percent=75, get_lcc=True, ) # Create spot and background instance spot_prop = regionprop.SpotRegionprop( row_idx=row_idx, col_idx=col_idx, label=count, ) # Mask spot should cover a certain percentage of ROI if np.mean(mask_spot) > constants.SPOT_MIN_PERCENT_AREA: # Mask detected bg_spot_lg, _ = img_processing.crop_image_at_center( im=background, center=coord, height=spot_height, width=spot_width, ) spot_prop.generate_props_from_mask( image=im_spot_lg, background=bg_spot_lg, mask=mask_spot, bbox=bbox_lg, ) else: # Crop around assumed spot size im_spot, bbox = img_processing.crop_image_at_center( im, coord, bbox_height, bbox_width, ) bg_spot, _ = img_processing.crop_image_at_center( background, coord, bbox_height, bbox_width, ) spot_prop.generate_props_from_disk( image=im_spot, background=bg_spot, bbox=bbox, centroid=coord, ) spots_df = spots_df.append(spot_prop.spot_dict, ignore_index=True) spot_props[row_idx, col_idx] = spot_prop return spots_df, spot_props
def test_make_mask(): prop = regionprop.SpotRegionprop(row_idx=1, col_idx=2, label=0) mask = prop.make_mask(51) assert mask.shape == (51, 51) assert mask[0, 0] == 0 assert mask[25, 25] == 1