def peakFinder(self, no_bg_image): # Mask the image so that peaks are only found in the AOI. masked_image = no_bg_image * self.peak_mask # Identify local maxima in the masked image. [new_peaks, self.taken] = utilC.findLocalMaxima(masked_image, self.taken, self.cur_threshold, self.find_max_radius, self.margin) # Fill in initial values for peak height, background and sigma. new_peaks = utilC.initializePeaks(new_peaks, # The new peaks. self.image, # The original image. self.background, # The current estimate of the background. self.sigma, # The starting sigma value. self.z_value) # The starting z value. return new_peaks
def peakFinder(self, no_bg_image): # Mask the image so that peaks are only found in the AOI. masked_image = no_bg_image * self.peak_mask # Identify local maxima in the masked image. [new_peaks, self.taken] = util_c.findLocalMaxima(masked_image, self.taken, self.cur_threshold, self.find_max_radius, self.margin) # Fill in initial values for peak height, background and sigma. new_peaks = util_c.initializePeaks( new_peaks, # The new peaks. self.image, # The original image. self.background, # The current estimate of the background. self.sigma, # The starting sigma value. self.z_value) # The starting z value. return new_peaks
def peakFinder(self, image): # Calculate convolved image, this is where the background subtraction happens. smooth_image = self.smoother.smoothImage(image, self.sigma) # Mask the image so that peaks are only found in the AOI. masked_image = smooth_image * self.peak_mask # Identify local maxima in the masked image. [new_peaks, self.taken] = utilC.findLocalMaxima(masked_image, self.taken, self.cur_threshold, self.find_max_radius, self.margin) # Fill in initial values for peak height, background and sigma. new_peaks = utilC.initializePeaks( new_peaks, # The new peaks. self.image, # The original image. self.background, # The current estimate of the background. self.sigma, # The starting sigma value. self.z_value) # The starting z value. return new_peaks
def peakFinder(self, image): # Calculate convolved image, this is where the background subtraction happens. smooth_image = self.smoother.smoothImage(image, self.sigma) # Mask the image so that peaks are only found in the AOI. masked_image = smooth_image * self.peak_mask # Identify local maxima in the masked image. [new_peaks, self.taken] = utilC.findLocalMaxima( masked_image, self.taken, self.cur_threshold, self.find_max_radius, self.margin ) # Fill in initial values for peak height, background and sigma. new_peaks = utilC.initializePeaks( new_peaks, # The new peaks. self.image, # The original image. self.background, # The current estimate of the background. self.sigma, # The starting sigma value. self.z_value, ) # The starting z value. return new_peaks
def peakFinder(self, no_bg_image): """ This method does the actual peak finding. Override this if you want to change the peak finding behaviour. """ # Mask the image so that peaks are only found in the AOI. masked_image = no_bg_image * self.peak_mask # Identify local maxima in the masked image. [new_peaks, self.taken] = utilC.findLocalMaxima(masked_image, self.taken, self.cur_threshold, self.find_max_radius, self.margin) # Fill in initial values for peak height, background and sigma. new_peaks = utilC.initializePeaks( new_peaks, # The new peaks. self.image, # The original image. self.background, # The current estimate of the background. self.sigma, # The starting sigma value. self.z_value) # The starting z value. return new_peaks
def peakFinder(self, no_bg_image): all_new_peaks = None save_convolution = False if save_convolution: print("making image") tif = tifffile.TiffWriter("image.tif") tif.save(self.image.astype(numpy.uint16) + 100) tif.save(no_bg_image.astype(numpy.uint16) + 100) tif.save(self.background.astype(numpy.uint16) + 100) # # Find peaks in image convolved with the PSF at different z values. # for i in range(len(self.mfilter)): height_rescale = self.height_rescale[i] mfilter = self.mfilter[i] taken = self.taken[i] z_value = self.z_value[i] # Smooth image with gaussian filter. smooth_image = mfilter.convolve(no_bg_image) if save_convolution: tif.save(smooth_image.astype(numpy.uint16) + 100) # Mask the image so that peaks are only found in the AOI. masked_image = smooth_image * self.peak_mask # Identify local maxima in the masked image. [new_peaks, taken] = utilC.findLocalMaxima(masked_image, taken, self.cur_threshold, self.find_max_radius, self.margin) # # Fill in initial values for peak height, background and sigma. # # FIXME: We just add the smoothed image and the background together # as a hack so that we can still use the initializePeaks() # function. # new_peaks = utilC.initializePeaks(new_peaks, # The new peaks. smooth_image + self.background, # Smooth image + background. self.background, # The current estimate of the background. self.sigma, # The starting sigma value. z_value) # The starting z value. # Correct initial peak heights. h_index = utilC.getHeightIndex() new_peaks[:,h_index] = new_peaks[:,h_index] * height_rescale if all_new_peaks is None: all_new_peaks = new_peaks else: all_new_peaks = numpy.append(all_new_peaks, new_peaks, axis = 0) if save_convolution: tif.close() # # Remove the dimmer of two peaks with similar x,y values but different z values. # if (len(self.mfilter) > 1): if False: print("before", all_new_peaks.shape) for i in range(all_new_peaks.shape[0]): print(all_new_peaks[i,:]) print("") all_new_peaks = utilC.removeClosePeaks(all_new_peaks, self.find_max_radius, self.find_max_radius) if False: print("after", all_new_peaks.shape) for i in range(all_new_peaks.shape[0]): print(all_new_peaks[i,:]) print("") return all_new_peaks
def peakFinder(self, fit_images): """ This method does the actual peak finding. We are assuming that Poisson statistics applies, so if we have a good estimate of the background and foreground then we can predict the significance of a foreground value with reasonable accuracy. """ # # Calculate (estimated) background variance for each plane. # # The estimated background and variance should both be > 0.0, # or there is going to be trouble. # bg_variances = [] # Save fit images for debugging purposes. if self.check_mode: with tifffile.TiffWriter("fit_images.tif") as tf: for fi in fit_images: tf.save(numpy.transpose(fi.astype(numpy.float32))) # Iterate over z values. for i in range(len(self.vfilters)): bg_variance = numpy.zeros(fit_images[0].shape) # Iterate over channels / planes. for j in range(len(self.vfilters[i])): # Convolve fit image + background with the appropriate variance filter. # # I believe that this is correct, the variance of the weighted average # of a (independent) Poisson processes is calculated using the square of # the weights. # conv_var = self.vfilters[i][j].convolve(fit_images[j] + self.backgrounds[j]) # Transform variance to the channel 0 frame. if self.atrans[j] is None: bg_variance += conv_var else: bg_variance += self.atrans[j].transform(conv_var) bg_variances.append(bg_variance + self.variances[i]) # Check for problematic values. if self.check_mode: for bg in bg_variances: mask = (bg <= 0.0) if (numpy.sum(mask) > 0): print( "Warning! 0.0 / negative values detected in background variance." ) # Save results if needed for debugging purposes. if self.check_mode: with tifffile.TiffWriter("variances.tif") as tf: for bg in bg_variances: tf.save(numpy.transpose(bg.astype(numpy.float32))) # # Calculate foreground for each z plane. # fg_averages = [ ] # This is the average foreground across all the planes for each z value. foregrounds = [] # This is the foreground for each plane and z value. # Iterate over z values. for i in range(len(self.mfilters)): foreground = numpy.zeros(fit_images[0].shape) foregrounds.append([]) # Iterate over channels / planes. for j in range(len(self.mfilters[i])): # Convolve image / background with the appropriate PSF. conv_fg = self.mfilters[i][j].convolve(self.images[j] - fit_images[j] - self.backgrounds[j]) # Store convolved image in foregrounds. foregrounds[i].append(conv_fg) # Transform image to the channel 0 frame. if self.atrans[j] is None: foreground += conv_fg else: foreground += self.atrans[j].transform(conv_fg) fg_averages.append(foreground) # Normalize average foreground by background standard deviation. fg_bg_ratios = [] for i in range(len(fg_averages)): fg_bg_ratios.append(fg_averages[i] / numpy.sqrt(bg_variances[i])) # Save results if needed for debugging purposes. if self.check_mode: with tifffile.TiffWriter("foregrounds.tif") as tf: for fg in fg_averages: tf.save(numpy.transpose(fg.astype(numpy.float32))) with tifffile.TiffWriter("fg_bg_ratio.tif") as tf: for fg_bg_ratio in fg_bg_ratios: tf.save(numpy.transpose(fg_bg_ratio.astype(numpy.float32))) # # At each z value, find peaks in foreground image normalized # by the background standard deviation. # all_new_peaks = None zero_array = numpy.zeros(fg_bg_ratios[0].shape) for i in range(len(self.mfilters)): # # Mask the image so that peaks are only found in the AOI. Ideally the # this mask should probably be adjusted to limit analysis to only # the regions of the image where there is data from every channel / plane. # masked_image = fg_bg_ratios[i] * self.peak_mask # Identify local maxima in the masked image. [new_peaks, taken] = utilC.findLocalMaxima(masked_image, self.taken[i], self.cur_threshold, self.find_max_radius, self.margin) # # Initialize peaks with normalized height value. We'll split these # later into peaks for each plane, and at that point the height, # background and z values will be corrected. # # Note: Sigma is irrelevant for fitting, but it needs to be some non-zero number. # new_peaks = utilC.initializePeaks( new_peaks, # The new peaks. masked_image, # Use SNR as height, corrected later for fitting. zero_array, # Zero for now, corrected later for fitting. self.sigma, # The starting sigma value. i) # Index of the z-plane, the actual z value is added later. # Add to all peaks accumulator. if all_new_peaks is None: all_new_peaks = new_peaks else: all_new_peaks = numpy.append(all_new_peaks, new_peaks, axis=0) # # If there are multiple peaks with similar x,y but in different # planes, use the one with the highest normalized value. # # FIXME: If the planes are far enough apart in z we should allow # peaks with a similar x,y. # if (len(self.mfilters) > 1): all_new_peaks = utilC.removeClosePeaks(all_new_peaks, self.find_max_radius, self.find_max_radius) # # Split into a peak/localization for each image plane. # # Note that the peaks array is expected to have all the peaks # for the first plane first, then all the peaks for the second # plane, etc.. With the same number of peaks per plane. # # This is how you would access the same peak in different channels: # # ch0) all_new_peaks[0 * n_peaks + peak_number] # ch1) all_new_peaks[1 * n_peaks + peak_number] # etc.. # all_new_peaks = self.mpu.splitPeaks(all_new_peaks) # # Remove peaks with members in one or more channels that are # outside of the image. # all_new_peaks = self.mpu.filterPeaks( all_new_peaks, self.mpu.badPeakMask(all_new_peaks)) # Initialize background values. mpUtilC.initializeBackground(all_new_peaks, self.backgrounds) # Need to do this before z initialization as we are using the # z value to index into the foregrounds array. mpUtilC.initializeHeight(all_new_peaks, foregrounds, self.height_rescale) # Replace z index with the z value used as the initial guess # for fitting. mpUtilC.initializeZ(all_new_peaks, self.z_values) if False: pp = 3 if (all_new_peaks.shape[0] > pp): for i in range(pp): print("Peak", i) self.mpu.prettyPrintPeak(all_new_peaks, i) print("") return all_new_peaks