Exemplo n.º 1
0
def _fit_2d_gaussian(subimage, implementation='agpy'):
    """
    Fit 2D Gaussian to a 5x5 pixel area. This is a function internal to
    pflib that abstracts away the specific methods used to fit.

    See fit_psf for the description of the 2D Gaussian model,
    parameters, and return values.

    Arguments:
        subimage: 5x5 Numpy array of pixels to fit.
        algorithm: The name of the fitter to use. Currently, only agpy
            is supported.

    Returns:
        (h_0, w_0, H, A, sigma_h, sigma_w, theta, fit_img)
    """
    assert subimage.shape[0] == 5 and subimage.shape[1] == 5
    if implementation != 'agpy':
        raise NotImplementedError("Currently, only agpy is supported.")
    #agpy.gaussfit parameters --
    #(H(eight), A(mplitude), h_0, w_0, sigma_h, sigma_w, theta)
    #initial fitting parameters based on emperical eyeball shufti
    ((H, A, h_0, w_0, sigma_h, sigma_w, theta), fit_img) = \
                agpy.gaussfit(subimage,
                              params=(np.mean(subimage), np.amax(subimage),
                                      2.5, 2.5, 1, 1, 0),
                              return_all=False,
                              limitedmin=[True] * 7,
                              limitedmax=[False, False, True, True, True, True,
                                          True],
                              minpars=np.array([0.00,
                                                (np.amax(subimage) -
                                                 np.mean(subimage)) / 3.0,
                                                2.00, 2.00, 0.75, 0.75, 0.00]),
                              maxpars=np.array([0.00, 0.00, 3.00, 3.00, 2.00,
                                                2.00, 360.00]),
                              returnfitimage=True)
    return (h_0, w_0, H, A, sigma_h, sigma_w, theta, fit_img)
Exemplo n.º 2
0
def _fit_2d_gaussian(subimage, implementation='agpy'):
    """
    Fit 2D Gaussian to a 5x5 pixel area. This is a function internal to
    pflib that abstracts away the specific methods used to fit.

    See fit_psf for the description of the 2D Gaussian model,
    parameters, and return values.

    Arguments:
        subimage: 5x5 Numpy array of pixels to fit.
        algorithm: The name of the fitter to use. Currently, only agpy
            is supported.

    Returns:
        (h_0, w_0, H, A, sigma_h, sigma_w, theta, fit_img)
    """
    assert subimage.shape[0] == 5 and subimage.shape[1] == 5
    if implementation != 'agpy':
        raise NotImplementedError("Currently, only agpy is supported.")
    #agpy.gaussfit parameters --
    #(H(eight), A(mplitude), h_0, w_0, sigma_h, sigma_w, theta)
    #initial fitting parameters based on emperical eyeball shufti
    ((H, A, h_0, w_0, sigma_h, sigma_w, theta), fit_img) = \
                agpy.gaussfit(subimage,
                              params=(np.mean(subimage), np.amax(subimage),
                                      2.5, 2.5, 1, 1, 0),
                              return_all=False,
                              limitedmin=[True] * 7,
                              limitedmax=[False, False, True, True, True, True,
                                          True],
                              minpars=np.array([0.00,
                                                (np.amax(subimage) -
                                                 np.mean(subimage)) / 3.0,
                                                2.00, 2.00, 0.75, 0.75, 0.00]),
                              maxpars=np.array([0.00, 0.00, 3.00, 3.00, 2.00,
                                                2.00, 360.00]),
                              returnfitimage=True)
    return (h_0, w_0, H, A, sigma_h, sigma_w, theta, fit_img)
Exemplo n.º 3
0
def fit_peaks(images, image_tuples=None, correlation_matrix=None,
              median_diameter=5, r_2_threshold=0.5, c_std=4,
              consolidation_radius_sq=4**2, child_number=0,
              child_priority_increment=0, silent=False):
    """
    The core function of the algorithm. In each image, finds all peaks and
    evaluates their resemblance to a Gaussian PSF model.
    """
    #renice
    os.nice(child_priority_increment)
    #generate empty image metadata tuples if empty
    if image_tuples is None:
        if not silent:
            logging.info('pflib.fit_peaks child number ' + str(child_number) +
                         ': no image_tuples metadata passed, using empty ' + 
                         'tuples')
        image_tuples = [() for t in images]
    elif len(image_tuples) != len(images):
        if not silent:
            logging.info('pflib.fit_peaks child number ' + str(child_number) +
            ': number of image metadata tuples does not match number of ' +
            'images, using empty tuples')
        image_tuples = [() for t in images]
    #perform squareroot just this once for the entire function call
    consolidation_box = np.ceil(math.sqrt(consolidation_radius_sq))
    #copy images to prevent tampering with originals by any function called
    images = [np.copy(image).astype(np.int64) for image in images]
    images_s3 = images
    if not silent:
        logging.info("pflib.fit_peaks child number " + str(child_number) +
                     ": copied images")
        sys.stdout.flush()
    #TODO:the following line does not check that images remain within bounds as
    #spalttiefpass and gaussian may increase positive values
    #subtract median filter
    images_s3 = \
      [np.subtract(image, np.minimum(spf.median_filter(image, median_diameter),
                                     image))
       for image in images_s3]
    if not silent:
        logging.info("pflib.fit_peaks child number " + str(child_number) +
                     ": applied median filter")
        sys.stdout.flush()
    #perform correlation
    if correlation_matrix is not None:
        images_s3 = [np.maximum(scipy.signal.correlate(image,
                                                       correlation_matrix,
                                                       mode='same'),
                                np.zeros_like(image)).astype(np.int64)
                     for image in images]
        #if not silent:
           # logging.info("pflib.fit_peaks child number " + str(child_number) +
            #             ": applied correlation filter")
            #sys.stdout.flush()
    consolidated_peak_stack = [[] for image in images]
    for i, image in enumerate(images_s3):
        start_time = time.clock()
        #number of fit attempts
        fit_counter = 0
        #no dictionary comprehensions in python 2.6 :(
        #pixel_bins = {(h,w): [] for h in range(image.shape[0])
        #                        for w in range(image.shape[1])}
        #pixel_bins = dict([((h,w), []) for h in range(image.shape[0])
        #                               for w in range(image.shape[1])])
        pixel_bins = [[[] for w in range(image.shape[1])]
                          for h in range(image.shape[0])]
        #threshold beneath which a pixel needs not to be checked
        candidate_threshold = np.mean(image) + c_std * np.std(image)
        for h, w in itertools.product(range(image.shape[0]),
                                      range(image.shape[1])):
            #keep track of progress within each image
            peak_time = time.clock()
            if (not 1 < h < image.shape[0] - 2 or
                not 1 < w < image.shape[1] - 2):
                continue
            if image[h, w] < candidate_threshold:
                continue
            fit_counter = fit_counter + 1
            subimage = images[i][h - 2:h + 3, w - 2:w + 3]
            #agpy.gaussfit parameters --
            #(height, amplitude, x, y, width_x, width_y, rota)
            ((fit, fit_err), fit_image) = \
                     agpy.gaussfit(subimage,
                                   params=(np.mean(subimage),
                                           np.amax(subimage),
                                           2.5, 2.5, 1, 1, 0),
                                   return_all=True,
                                   limitedmin = [True] * 7,
                                   limitedmax = [False, False,
                                                 True, True, True, True, True],
                                   minpars=np.array([0.00,
                                                     (np.amax(subimage) -
                                                      np.mean(subimage)) / 3.0,
                                                     2.00, 2.00, 0.75, 0.75,
                                                     0.00]),
                                   maxpars=np.array([0.00, 0.00, 3.00, 3.00,
                                                     2.00, 2.00, 360.00]),
                                   returnfitimage=True)
            #rmse
            rmse = math.sqrt(
                         sum([(subimage[x,y] - fit_image[x,y])**2
                              for x,y in itertools.product(range(5),range(5))])
                         / 9.0)
            #coefficient of determination r**2
            r_2 = (1.0 -
                        sum(np.reshape((subimage - fit_image)**2, -1)) /
                        sum((np.reshape(subimage, -1) - np.mean(subimage))**2))
            if r_2 < r_2_threshold:
                continue
            #Illumina S/N = 
            #([peak pixel] - [mean of 16 outer edge pixels]) /
            #    (std[16 outer pixels])
            op = [subimage[x, y]
                      for x in range(subimage.shape[0])
                          for y in range(subimage.shape[1])
                              if x == 0 or
                                 x == subimage.shape[0] - 1 or
                                 y == 0 or
                                 y == subimage.shape[1] - 1]
            s_n = (np.amax(subimage) - np.mean(op)) / np.std(op)
            #peak fitting result tuple
            #(0  1  2--  3------  4-------  5--------  6---  7--, 8--)
            #(h, w, fit, fit_err, subimage, fit_image, rmse, r_2, s_n)
            #agpy.gaussfit parameters --
            # 0-----  1--------  2  3  4------  5------  6---
            #(height, amplitude, x, y, width_x, width_y, rota)
            peak = (fit[2] + h - 2, fit[3] + w - 2, fit, fit_err, subimage,
                    fit_image, rmse, r_2, s_n)
            #for all fits, consolidate them into the best one within a radius;
            #check peaks in the consolidated peak stack
            #default is that this is a new peak
            if not (0 <= peak[0] <= image.shape[0] and
                    0 <= peak[1] <= image.shape[1]):
                continue
            (pixel_bins[int(np.around(peak[0]))]
                       [int(np.around(peak[1]))].append(peak))
            if (not silent
                and
                (h + w) % int(image.shape[0] * image.shape[1] / 1000) == 0):
                logging.info("pflib.fitpeaks child number " +
                             str(child_number) +
                             ": done fitting at h,w " + str((h,w)) + " in " +
                             str(time.clock() - peak_time) + " sec; layer " +
                             str(i) + ' of ' + str(len(images_s3)) +
                             "; cumulative time " +
                             str(time.clock() - start_time) +
                             "; fit_counter " + str(fit_counter))
                sys.stdout.flush()
        consolidation_time = time.clock()
        for h, w in itertools.product(range(image.shape[0]),
                                      range(image.shape[1])):
            if pixel_bins[h][w]:
                pixel_bins[h][w] = max(pixel_bins[h][w],
                                       key=lambda x: x[7])
            else:
                pixel_bins[h][w] = None
        for h, w in itertools.product(range(image.shape[0]),
                                      range(image.shape[1])):
            if not pixel_bins[h][w]:
                continue
            local_max = True
            for j, q in itertools.product(
                        range(int(max(h - consolidation_box - 2, 0)),
                              int(min(h + consolidation_box + 3,
                                  image.shape[0]))),
                        range(int(max(w - consolidation_box - 2, 0)),
                              int(min(w + consolidation_box + 3,
                                  image.shape[1])))):
                if not pixel_bins[j][q] or (j == h and q == w):
                    continue
                if ((pixel_bins[j][q][0] - pixel_bins[h][w][0])**2 +
                    (pixel_bins[j][q][1] - pixel_bins[h][w][1])**2 <
                    consolidation_radius_sq):
                    if pixel_bins[j][q][7] < pixel_bins[h][w][7]:
                        pixel_bins[j][q] = None
                    else:
                        local_max = False
            if not local_max:
                pixel_bins[h][w] = None
        consolidated_peak_stack[i] = \
                         (image_tuples[i],
                          [pixel_bins[h][w]
                           for h, w in itertools.product(range(image.shape[0]),
                                                         range(image.shape[1]))
                           if pixel_bins[h][w]])
        if not silent:
            logging.info("pflib.fit_peaks child number " + str(child_number) +
                         ": consolidation accomplished in " +
                         str(time.clock() - consolidation_time) + " sec; " +
                         str(len(consolidated_peak_stack[i][1])) +
                         " peaks remaining of " + str(fit_counter) +
                         " fit_counter")
        if not silent:
            logging.info("pflib.fit_peaks child number " + str(child_number) +
                         ": image " + str(i + 1) + " of " +
                         str(len(images_s3)) + " processed in " +
                         str(time.clock() - start_time) + " sec;" +
                         " fit_counter " + str(fit_counter))
    return consolidated_peak_stack