def load_reference_image(self): """ Load the reference image """ print('Plotting...') self.imagefile = find_timepoint(self.imagedir, tile=self.tile, timepoint=min( self.grid.timepoint_coords.keys())) self.image = load_image(self.imagefile) self.rows, self.cols = self.image.shape[:2]
def test_negative_index_frames(self): image_dir = self.make_image_dir(10, 64, 63) framefiles = [ p for p in sorted(image_dir.iterdir()) if p.suffix == '.tif' ] vol = image_volume.LazyImageDir(image_dir) for i in range(-len(framefiles), 0): res = vol[i] exp = load_image(framefiles[i]) np.testing.assert_allclose(res, exp)
def test_can_iterate_over_frames(self): image_dir = self.make_image_dir(10, 64, 63) framefiles = [ p for p in sorted(image_dir.iterdir()) if p.suffix == '.tif' ] vol = image_volume.LazyImageDir(image_dir) total_files = 0 for res, framefile in zip(vol, framefiles): exp = load_image(framefile) np.testing.assert_allclose(res, exp) total_files += 1 self.assertEqual(total_files, len(framefiles))
def test_can_subset_with_bounding_box_starting_negative_indices(self): image_dir = self.make_image_dir(10, 64, 63) framefiles = [ p for p in sorted(image_dir.iterdir()) if p.suffix == '.tif' ] self.assertEqual(len(framefiles), 10) vol = image_volume.LazyImageDir(image_dir) subvol = vol.crop([(-59, 55), (-53, 49)]).crop([(5, -1), (5, -1)]) self.assertEqual(subvol.shape, (10, 44, 33)) # Make sure that each individual index matches for i in range(len(framefiles)): res = subvol[i, ...] exp = load_image(framefiles[i])[10:-10, 15:-15] np.testing.assert_allclose(res, exp)
def test_frames_in_order(self): image_dir = self.make_image_dir(10, 64, 63) framefiles = [ p for p in sorted(image_dir.iterdir()) if p.suffix == '.tif' ] self.assertEqual(len(framefiles), 10) vol = image_volume.LazyImageDir(image_dir) self.assertEqual(vol.shape, (10, 64, 63)) # Make sure that each individual index matches for i in range(len(framefiles)): self.assertIn(framefiles[i], vol) res = vol[i, ...] exp = load_image(framefiles[i]) np.testing.assert_allclose(res, exp) self.assertEqual(len(vol), len(framefiles))
def ensamble_timepoint(prefix: pathlib.Path, outdir: pathlib.Path, num_detectors: int, imagefiles: List[pathlib.Path], peak_distance: int = PEAK_DISTANCE, detection_threshold: float = DETECTION_THRESHOLD, comp_type: str = COMP_TYPE, weights: Optional[List[float]] = None, exclude_border: int = EXCLUDE_BORDER): """ Ensamble a single timepoint over several detectors :param Path prefix: The relative path to write the files to :param Path outdir: The base directory to write the files to :param int num_detectors: How many detectors should be in this composite :param list[Path] imagefiles: The list of files for each image from the detectors :param int peak_distance: Distance in pixels for the composite detection :param float detection_threshold: The number between 0 and 1 for the detector cutoff :param str comp_type: Which composite method to use ('mean' or 'max') """ assert len(imagefiles) == num_detectors out_tiledir = outdir / prefix.parent out_imagefile = out_tiledir / f'{prefix.stem}_resp.png' out_trainfile = out_tiledir / f'{prefix.stem}_train.png' out_pointfile = out_tiledir / f'{prefix.stem}.csv' # Do a weird parallel mkdir because the other way is unsafe for _ in range(3): if out_imagefile.parent.is_dir(): break try: out_imagefile.parent.mkdir(parents=True, exist_ok=True) except OSError: continue # Weights for the ensamble if weights is None: weights = [1.0 for _ in imagefiles] elif isinstance(weights, (int, float)): weights = [weights for _ in imagefiles] if len(weights) != len(imagefiles): err = f'Invalid shape for weights, got {len(weights)} weights, {len(imagefiles)} images' raise ValueError(err) weights = [float(w) for w in weights] # Create a composite detection print(out_imagefile) comp_image = [] for weight, imagefile in zip(weights, imagefiles): in_image = load_image(imagefile) / 255.0 comp_image.append(in_image * weight) if comp_type == 'mean': response = np.mean(comp_image, axis=0) elif comp_type == 'max': response = np.max(comp_image, axis=0) else: raise KeyError(f'Unknown composite type: {comp_type}') # Normalize the response response[response < 0] = 0 response[response > 1] = 1 save_image(out_imagefile, response) # Create the peak detection for that composite peaks = peak_local_max(response + np.random.rand(*response.shape) * 1e-5, min_distance=int(np.ceil(peak_distance)), threshold_abs=detection_threshold, exclude_border=exclude_border) rows, cols = response.shape[:2] assert peaks.shape[1] == 2 norm_px = [px / cols for px in peaks[:, 1]] norm_py = [(1.0 - py / rows) for py in peaks[:, 0]] peak_values = response[peaks[:, 0], peaks[:, 1]] final_peaks = [(x, y) for x, y, v in zip(norm_px, norm_py, peak_values) if v > 0.01] save_point_csvfile(out_pointfile, norm_px, norm_py, peak_values, xlim=(0, 1), ylim=(0, 1)) # Finally, synthesize a training image if out_trainfile is not None: mask = convert_points_to_mask(response, final_peaks) save_image(out_trainfile, mask)
def plot_single_timepoint_mesh(self, timepoint: int): """ Plot the mesh at a single timepoint :param int timepoint: Timepoint to plot the mesh at """ # Load the image to plot over imagefile = find_timepoint(self.imagedir, tile=self.tile, timepoint=timepoint) image = load_image(imagefile) # Load the mesh to plot points = self.load_coord_mesh('image', timepoint) warp_points = self.load_coord_mesh('warp', timepoint) mesh = self.load_coord_mesh('mesh', timepoint) if len(self.perimeters) > timepoint: perimeter = self.perimeters[timepoint] else: perimeter = None rows, cols = image.shape[:2] self.timepoint_image_shapes[timepoint] = (rows, cols) # Plot the triangulation over the original image if self.tile_outdir is None: outfile = None else: outfile = f'Mesh-{self.tile}t{timepoint:03d}{self.suffix}' outfile = self.tile_outdir / 'Mesh' / outfile outfile.parent.mkdir(parents=True, exist_ok=True) with set_plot_style(self.plot_style) as style: fig, ax = plt.subplots(1, 1, figsize=self.figsize) ax.imshow(image, cmap='bone') add_meshplot(ax, points, mesh) ax.set_xlim([0, cols]) ax.set_ylim([rows, 0]) ax.set_xticks([]) ax.set_yticks([]) ax.set_aspect('equal') ax.set_axis_off() style.show(outfile, tight_layout=True) # Plot the current perimeter if perimeter is not None: if self.tile_outdir is None: outfile = None else: outfile = f'Perimeter-{self.tile}t{timepoint:03d}{self.suffix}' outfile = self.tile_outdir / 'Perimeter' / outfile outfile.parent.mkdir(parents=True, exist_ok=True) with set_plot_style(self.plot_style) as style: fig, ax = plt.subplots(1, 1, figsize=self.figsize) ax.plot(perimeter[:, 0], perimeter[:, 1], '-r') ax.imshow(image, cmap='bone') ax.set_xlim([0, cols]) ax.set_ylim([rows, 0]) ax.set_xticks([]) ax.set_yticks([]) ax.set_aspect('equal') ax.set_axis_off() style.show(outfile, tight_layout=True) # Plot the warped mesh if self.tile_outdir is None: outfile = None else: outfile = f'Warp-{self.tile}t{timepoint:03d}{self.suffix}' outfile = self.tile_outdir / 'Warp' / outfile outfile.parent.mkdir(parents=True, exist_ok=True) with set_plot_style(self.plot_style) as style: fig, ax = plt.subplots(1, 1, figsize=self.figsize) add_meshplot(ax, warp_points, mesh) ax.set_xlim([-1.1, 1.1]) ax.set_ylim([-1.1, 1.1]) ax.set_xticks([]) ax.set_yticks([]) ax.set_aspect('equal') ax.set_axis_off() style.show(outfile, tight_layout=True)