def process_fov(fov: FieldOfView, codebook: Codebook) -> DecodedIntensityTable: """Process a single field of view of ISS data Parameters ---------- fov : FieldOfView the field of view to process codebook : Codebook the Codebook to use for decoding Returns ------- DecodedSpots : tabular object containing the locations of detected spots. """ # note the structure of the 5D tensor containing the raw imaging data imgs = fov.get_image(FieldOfView.PRIMARY_IMAGES) dots = fov.get_image("dots") nuclei = fov.get_image("nuclei") print("Learning Transform") learn_translation = LearnTransform.Translation(reference_stack=dots, axes=Axes.ROUND, upsampling=1000) transforms_list = learn_translation.run( imgs.reduce({Axes.CH, Axes.ZPLANE}, func="max")) print("Applying transform") warp = ApplyTransform.Warp() registered_imgs = warp.run(imgs, transforms_list=transforms_list, verbose=True) print("Filter WhiteTophat") filt = Filter.WhiteTophat(masking_radius=15, is_volume=False) filtered_imgs = filt.run(registered_imgs, verbose=True) filt.run(dots, verbose=True, in_place=True) filt.run(nuclei, verbose=True, in_place=True) print("Detecting") detector = FindSpots.BlobDetector( min_sigma=1, max_sigma=10, num_sigma=30, threshold=0.01, measurement_type='mean', ) dots_max = dots.reduce((Axes.ROUND, Axes.ZPLANE), func="max", module=FunctionSource.np) spots = detector.run(image_stack=filtered_imgs, reference_image=dots_max) print("Decoding") decoder = DecodeSpots.PerRoundMaxChannel(codebook=codebook) decoded = decoder.run(spots=spots) return decoded
def iss_pipeline(fov, codebook): primary_image = fov.get_image(starfish.FieldOfView.PRIMARY_IMAGES) # register the raw image learn_translation = LearnTransform.Translation( reference_stack=fov.get_image('dots'), axes=Axes.ROUND, upsampling=100) transforms_list = learn_translation.run( primary_image.reduce({Axes.CH, Axes.ZPLANE}, func="max")) warp = ApplyTransform.Warp() registered = warp.run(primary_image, transforms_list=transforms_list, in_place=False, verbose=True) # filter raw data masking_radius = 15 filt = Filter.WhiteTophat(masking_radius, is_volume=False) filtered = filt.run(registered, verbose=True, in_place=False) bd = FindSpots.BlobDetector( min_sigma=1, max_sigma=10, num_sigma=30, threshold=0.01, measurement_type='mean', ) # detect spots using laplacian of gaussians approach dots_max = fov.get_image('dots').reduce((Axes.ROUND, Axes.ZPLANE), func="max", module=FunctionSource.np) # locate spots in a reference image spots = bd.run(reference_image=dots_max, image_stack=filtered) # decode the pixel traces using the codebook decoder = DecodeSpots.PerRoundMaxChannel(codebook=codebook) decoded = decoder.run(spots=spots) # segment cells seg = Segment.Watershed( nuclei_threshold=.16, input_threshold=.22, min_distance=57, ) label_image = seg.run(primary_image, fov.get_image('dots')) # assign spots to cells ta = AssignTargets.Label() assigned = ta.run(label_image, decoded) return assigned, label_image
masking_radius = 15 filt = Filter.WhiteTophat(masking_radius, is_volume=False) filt.run(imgs, in_place=True) filt.run(dots, in_place=True) # register primary images to reference round learn_translation = LearnTransform.Translation(reference_stack=dots, axes=Axes.ROUND, upsampling=1000) transforms_list = learn_translation.run( imgs.reduce({Axes.CH, Axes.ZPLANE}, func="max")) warp = ApplyTransform.Warp() warp.run(imgs, transforms_list=transforms_list, in_place=True) # run blob detector on dots (reference image with every spot) bd = FindSpots.BlobDetector( min_sigma=1, max_sigma=10, num_sigma=30, threshold=0.01, measurement_type='mean', ) dots_max = dots.reduce((Axes.ROUND, Axes.ZPLANE), func="max") spots = bd.run(image_stack=imgs, reference_image=dots_max) # Decode spots with PerRoundMaxChannel from starfish.spots import DecodeSpots decoder = DecodeSpots.PerRoundMaxChannel( codebook=experiment.codebook, trace_building_strategy=TraceBuildingStrategies.EXACT_MATCH) decoded_intensities = decoder.run(spots=spots)
def decode_spots(codebook, spots): decoder = DecodeSpots.PerRoundMaxChannel(codebook=codebook) return decoder.run(spots=spots)
# EPY: START code import warnings from starfish.spots import FindSpots, DecodeSpots bd = FindSpots.BlobDetector( min_sigma=1, max_sigma=10, num_sigma=30, threshold=0.01, measurement_type='mean', ) dots_max = dots.reduce((Axes.ROUND, Axes.ZPLANE), func=FunctionSource.np("max")) spots = bd.run(image_stack=registered_imgs, reference_image=dots_max) decoder = DecodeSpots.PerRoundMaxChannel(codebook=experiment.codebook) decoded = decoder.run(spots=spots) # Besides house keeping genes, VIM and HER2 should be most highly expessed, which is consistent here. genes, counts = np.unique(decoded.loc[decoded[Features.PASSES_THRESHOLDS]][Features.TARGET], return_counts=True) table = pd.Series(counts, index=genes).sort_values(ascending=False) table # EPY: END code # EPY: START markdown ### Segment Cells and create Cell by Gene Expression Matrix # #After calling spots and decoding their gene information, cells must be segmented to assign genes to cells. This paper used a seeded watershed approach to segment the cells, which we also use here. # EPY: END markdown # EPY: START code
4. Assign genes to cells 5. Calculate area of non-stroma tissue, add up each type of gene, normalize gene density. """ gene_counts_across_fovs = [] for fov in exp.fovs(): # 1 - already completed # 2: Filter images and project Zplanes img_stack = next(exp[fov].get_images(FieldOfView.PRIMARY_IMAGES)) img_stack_f1 = ghp.run(img_stack, in_place=False) img_stack_f2 = glp.run(img_stack_f1, in_place=False) img_proj_z = img_stack_f2.reduce({Axes.ZPLANE}, func='max') # 2: Find Spots spots = SpotFinder.run(img_proj_z) decoder = DecodeSpots.SimpleLookupDecoder(codebook=codebook) decoded_intensities = decoder.run(spots=spots) # 3: path = root_path + 'ilastik/classified_fovs/' + exp_name + fov + '.tif' mask, label_image = produceMaskFromTif(path, img_stack) # 4: al = AssignTargets.Label() labeled = al.run(mask, decoded_intensities) cg = labeled.to_expression_matrix() # 5: STROMA_ID = 2 NON_STROMA_ID = 1
min_obj_area=args.small_peak_min, max_obj_area=args.small_peak_max, min_num_spots_detected=2500, is_volume=False, verbose=False) lmp_big = FindSpots.LocalMaxPeakFinder(min_distance=args.big_peak_dist, stringency=0, min_obj_area=args.big_peak_min, max_obj_area=args.big_peak_max, min_num_spots_detected=2500, is_volume=False, verbose=False) sd = Codebook.synthetic_one_hot_codebook(n_round=1, n_channel=1, n_codes=1) decoder = DecodeSpots.PerRoundMaxChannel(codebook=sd) block_dim = int(max(imarr.shape) * args.block_dim_fraction) SpotCoords = np.zeros((0, 2), dtype=np.int64) for i in range( 0, imarr.shape[-2] - 1, block_dim ): # subtracting 1 from range because starfish breaks with x or y axis size of 1 for j in range(0, imarr.shape[-1] - 1, block_dim): imgs = ImageStack.from_numpy(imarr[:, :, :, i:i + block_dim, j:j + block_dim]) imgs = bandpass.run(imgs).reduce({Axes.ZPLANE}, func="max") spots = lmp_small.run(imgs) decoded_intensities = decoder.run(spots=spots) spot_coords_small = np.stack([ decoded_intensities[Axes.Y.value], decoded_intensities[Axes.X.value] ]).T
# EPY: START code from starfish.spots import DecodeSpots, FindSpots from starfish.types import TraceBuildingStrategies lmp = FindSpots.LocalMaxPeakFinder( min_distance=6, stringency=0, min_obj_area=6, max_obj_area=600, is_volume=True ) spots = lmp.run(mp) decoder = DecodeSpots.PerRoundMaxChannel(codebook=experiment.codebook, trace_building_strategy=TraceBuildingStrategies.SEQUENTIAL) decoded_intensities = decoder.run(spots=spots) # EPY: END code # EPY: START markdown ### Compare to pySMFISH peak calls # EPY: END markdown # EPY: START markdown #The Field of view that we've used for the test data corresponds to Aldoc, imaged in round one, in position 33. We've also packaged the results from the osmFISH publication for this target to demonstrate that starfish is capable of recovering the same results. # EPY: END markdown # EPY: START code def load_results(pickle_file): with open(pickle_file, "rb") as f: return pickle.load(f)
experiment = starfish.data.allen_smFISH(use_test_data=True) image = experiment["fov_001"].get_image(FieldOfView.PRIMARY_IMAGES) bandpass = Filter.Bandpass(lshort=.5, llong=7, threshold=0.0) glp = Filter.GaussianLowPass(sigma=(1, 0, 0), is_volume=True) clip1 = Filter.Clip(p_min=50, p_max=100, level_method=Levels.SCALE_BY_CHUNK) clip2 = Filter.Clip(p_min=99, p_max=100, is_volume=True, level_method=Levels.SCALE_BY_CHUNK) tlmpf = starfish.spots.FindSpots.TrackpyLocalMaxPeakFinder( spot_diameter=5, min_mass=0.02, max_size=2, separation=7, noise_size=0.65, preprocess=False, percentile=10, verbose=True, is_volume=True, ) clip1.run(image, in_place=True) bandpass.run(image, in_place=True) glp.run(image, in_place=True) clip2.run(image, in_place=True) spots = tlmpf.run(image) # Decode spots with SimpleLookupDecoder from starfish.spots import DecodeSpots decoder = DecodeSpots.SimpleLookupDecoder(codebook=experiment.codebook) decoded_intensities = decoder.run(spots=spots)
bd = FindSpots.BlobDetector(min_sigma=1, max_sigma=8, num_sigma=10, threshold=np.percentile( np.ravel(stack.xarray.values), 95), exclude_border=2) spots = bd.run(scaled) ################################################################################################### # Decode spots # ------------ # Next, spots are decoded. There is really no good way to display 3-d spot detection in 2-d planes, # so we encourage you to grab this notebook and uncomment the below lines. from starfish.spots import DecodeSpots from starfish.types import TraceBuildingStrategies decoder = DecodeSpots.PerRoundMaxChannel( codebook=experiment.codebook, anchor_round=0, search_radius=10, trace_building_strategy=TraceBuildingStrategies.NEAREST_NEIGHBOR) decoded = decoder.run(spots=spots) decode_mask = decoded['target'] != 'nan' # %gui qt # viewer = starfish.display(stack, decoded[decode_mask], radius_multiplier=2, mask_intensities=0.1)
def find_spots(input_path, output_path, intensity_percentile=99.995, filter_width=2, small_peak_min=4, small_peak_max=100, big_peak_min=25, big_peak_max=10000, small_peak_dist=2, big_peak_dist=0.75, block_dim_fraction=0.25, spot_pad_pixels=2, keep_existing=False): """ Find and keep only spots from stitched images. """ image_stack = imageio.volread(input_path) print(image_stack.shape) thresholded_image = np.copy(image_stack) _, height, width = image_stack.shape threshold = np.percentile(thresholded_image, intensity_percentile) thresholded_image[thresholded_image > threshold] = threshold + ( np.log(thresholded_image[thresholded_image > threshold] - threshold) / np.log(1.1)).astype(thresholded_image.dtype) #May need to fiddle with the sigma parameters in each step, depending on the image. #High Pass Filter (Background Subtraction) gaussian_high_pass = Filter.GaussianHighPass(sigma=(1, filter_width, filter_width), is_volume=True) # enhance brightness of spots laplace_filter = Filter.Laplace(sigma=(0.2, 0.5, 0.5), is_volume=True) local_max_peakfinder_small = FindSpots.LocalMaxPeakFinder( min_distance=small_peak_dist, stringency=0, min_obj_area=small_peak_min, max_obj_area=small_peak_max, min_num_spots_detected=2500, is_volume=True, verbose=True) local_max_peakfinder_big = FindSpots.LocalMaxPeakFinder( min_distance=big_peak_dist, stringency=0, min_obj_area=big_peak_min, max_obj_area=big_peak_max, min_num_spots_detected=2500, is_volume=True, verbose=True) synthetic_codebook = Codebook.synthetic_one_hot_codebook(n_round=1, n_channel=1, n_codes=1) decoder = DecodeSpots.PerRoundMaxChannel(codebook=synthetic_codebook) block_dimension = int(max(thresholded_image.shape) * block_dim_fraction) spot_coordinates = np.zeros((0, 2), dtype=np.int64) # Finding spots by block_dimension x block_dimension size blocks # We skip the blocks at the edges with the - 1 (TODO: pad to full block size) for row in range(0, height - 1, block_dimension): for column in range(0, width - 1, block_dimension): # Cutout block and expand dimensions for channel and round block = thresholded_image[np.newaxis, np.newaxis, :, row:row + block_dimension, column:column + block_dimension] images = ImageStack.from_numpy(block) high_pass_filtered = gaussian_high_pass.run(images, verbose=False, in_place=False) laplace = laplace_filter.run(high_pass_filtered, in_place=False, verbose=False) small_spots = local_max_peakfinder_small.run( laplace.reduce({Axes.ZPLANE}, func="max")) decoded_intensities = decoder.run(spots=small_spots) small_spot_coords = np.stack([ decoded_intensities[Axes.Y.value], decoded_intensities[Axes.X.value] ]).T big_spots = local_max_peakfinder_big.run( laplace.reduce({Axes.ZPLANE}, func="max")) decoded_intensities = decoder.run(spots=big_spots) big_spot_coords = np.stack([ decoded_intensities[Axes.Y.value], decoded_intensities[Axes.X.value] ]).T all_spot_coords = np.vstack([small_spot_coords, big_spot_coords]) all_spot_coords += (row, column) spot_coordinates = np.vstack([spot_coordinates, all_spot_coords]) # Copying over only non-zero pixels image_spots = np.zeros((height, width), dtype=np.uint16) for spot_coordinate in spot_coordinates: spot_column, spot_row = spot_coordinate for row in range(max(0, spot_column - spot_pad_pixels), min(spot_column + spot_pad_pixels + 1, height)): for column in range(max(0, spot_row - spot_pad_pixels), min(spot_row + spot_pad_pixels + 1, width)): # Max projecting over z-stack image_spots[row, column] = image_stack[:, row, column].max(0) imageio.imsave(output_path, image_spots) return image_spots
# run blob detector on dots (reference image with every spot) bd = FindSpots.BlobDetector( min_sigma=1, max_sigma=3, num_sigma=10, threshold=0.01, measurement_type='mean', ) spots = bd.run(image_stack=imgs, reference_image=dots) # Decode spots with MetricDistance set to loose parameters from starfish.spots import DecodeSpots decoder = DecodeSpots.MetricDistance( codebook=experiment.codebook, max_distance=1, min_intensity=1, metric='euclidean', norm_order=2, trace_building_strategy=TraceBuildingStrategies.EXACT_MATCH) decoded_intensities = decoder.run(spots=spots) # Build IntensityTable with same TraceBuilder as was used in MetricDistance from starfish.core.spots.DecodeSpots.trace_builders import build_spot_traces_exact_match intensities = build_spot_traces_exact_match(spots) # Get vector magnitudes norm_intensities, vector_magnitude = experiment.codebook._normalize_features( intensities, norm_order=2) # Get distances distances = decoded_intensities.to_decoded_dataframe( ).data['distance'].to_numpy() # Plot histogram
def process_fov(field_num: int, experiment_str: str): """Process a single field of view of ISS data Parameters ---------- field_num : int the field of view to process experiment_str : int path of experiment json file Returns ------- DecodedSpots : tabular object containing the locations of detected spots. """ fov_str: str = f"fov_{int(field_num):03d}" # load experiment experiment = starfish.Experiment.from_json(experiment_str) print(f"loading fov: {fov_str}") fov = experiment[fov_str] # note the structure of the 5D tensor containing the raw imaging data imgs = fov.get_image(FieldOfView.PRIMARY_IMAGES) dots = fov.get_image("dots") nuclei = fov.get_image("nuclei") print("Learning Transform") learn_translation = LearnTransform.Translation(reference_stack=dots, axes=Axes.ROUND, upsampling=1000) transforms_list = learn_translation.run( imgs.reduce({Axes.CH, Axes.ZPLANE}, func="max")) print("Applying transform") warp = ApplyTransform.Warp() registered_imgs = warp.run(imgs, transforms_list=transforms_list, in_place=True, verbose=True) print("Filter WhiteTophat") filt = Filter.WhiteTophat(masking_radius=15, is_volume=False) filtered_imgs = filt.run(registered_imgs, verbose=True, in_place=True) filt.run(dots, verbose=True, in_place=True) filt.run(nuclei, verbose=True, in_place=True) print("Detecting") detector = FindSpots.BlobDetector( min_sigma=1, max_sigma=10, num_sigma=30, threshold=0.01, measurement_type='mean', ) dots_max_projector = Filter.Reduce((Axes.ROUND, Axes.ZPLANE), func=FunctionSource.np("max")) dots_max = dots_max_projector.run(dots) spots = detector.run(image_stack=filtered_imgs, reference_image=dots_max) decoder = DecodeSpots.PerRoundMaxChannel(codebook=experiment.codebook) decoded = decoder.run(spots=spots) df = decoded.to_decoded_dataframe() return df