def fit_spheroid_shape_pearson(img, msk, diameter_a, diameter_c, phi, intensity, wavelength, pixel_size, detector_distance, full_output=False,  x0=0, y0=0, detector_adu_photon=1, detector_quantum_efficiency=1, material='water', rmax=None, downsampling=1, do_brute_evals=0, maxfev=1000, do_photon_counting=False, deltab=0.5, force_prolate=True):
    """
    Fit the shape of a spheroid using pearson correlation.

    """
    Xmc, Ymc, img, msk = _prepare_for_fitting(img, msk, x0, y0, rmax, downsampling, detector_adu_photon, do_photon_counting, pixel_size, detector_distance)
    diameter = (diameter_a**2*diameter_c)**(1/3.)
    S   = sphere_model_convert_intensity_to_scaling(intensity, diameter, wavelength, pixel_size, detector_distance, detector_quantum_efficiency, 1, material)
    size    = lambda d: sphere_model_convert_diameter_to_size(d, wavelength, pixel_size, detector_distance)
    I_fit_m = lambda da,dc,p: I_spheroid_diffraction(S,Xmc,Ymc,size(da),size(dc),0.,p)
    def E_fit_m(p):
        if not (img[msk].std() and I_fit_m(p[0],p[1],p[2]).std()): return numpy.ones(len(p))
        else: return 1-scipy.stats.pearsonr(I_fit_m(p[0],p[1],p[2]),img[msk])[0]*numpy.ones(len(p))
    
    # Start with brute force with a sensible range
    # We'll assume at least 20x oversampling
    if do_brute_evals:
        dmin = sphere_model_convert_size_to_diameter(1./(downsampling*img.shape[0]), wavelength, pixel_size, detector_distance)
        dmax = dmin*downsampling*img.shape[0]/20
        pmin = 0.
        pmax = numpy.pi
        Ns = do_brute_evals
        diameter = scipy.optimize.brute(E_fit_m, [(dmin, dmax),(dmin,dmax),(pmin,pmax)], Ns=Ns)[0]

    # End with least square
    p0 = numpy.array([diameter_a,diameter_c,phi])
    p, cov, infodict, mesg, ier = leastsq(E_fit_m, p0, maxfev=maxfev, xtol=1e-5, full_output=True)
    [diameter_a, diameter_c, phi] = p
    diameter_a = abs(diameter_a)
    diameter_c = abs(diameter_c)
    phi = phi % numpy.pi
    
    if force_prolate and diameter_a > diameter_c:
        return fit_spheroid_shape_pearson(img, msk, diameter_c, diameter_a, phi+numpy.pi/2., intensity, wavelength, pixel_size, detector_distance, full_output,
                                          x0, y0, detector_adu_photon, detector_quantum_efficiency, material, rmax, downsampling, do_brute_evals, maxfev, do_photon_counting, deltab)
    
    # Reduced Chi-squared and standard error
    chisquared = ((I_fit_m(diameter_a, diameter_c, phi) - img[msk])**2).sum()/(img.shape[0]*img.shape[1] - 1)
    if cov is not None:
        pcov = cov[0,0]*chisquared
    else:
        pcov = None
    
    if full_output:
        infodict['error'] = chisquared
        infodict['pcov'] = pcov
        return diameter_a, diameter_c, phi, infodict
    else:
        return diameter_a, diameter_c, phi
def fit_spheroid_intensity_pixelwise(img, msk, diameter_a, diameter_c, phi, intensity, wavelength, pixel_size, detector_distance, full_output=False, x0=0, y0=0, detector_adu_photon=1, detector_quantum_efficiency=1, material='water', rmax=None, downsampling=1, maxfev=1000, do_photon_counting=False):
    """
    Fit the intensity [J / m^2] on a spheroid to diffraction data using least square optimization.
    The cost function is defined as a pixelwise comparison between model and data.

    usage:
    ======
    intensity       = fit_spheroid_intensity(img, msk, diameter_a, diameter_c, phi, intensity, pixel_size, detector_distance)
    intensity, info = fit_spheroid_intensity(img, msk, diameter_a, diameter_c, phi, intensity, pixel_size, detector_distance, full_output=True)
    intensity, info = fit_spheroid_intensity(img, msk, diameter_a, diameter_c, phi, intensity, pixel_size, detector_distance, full_output=True, x0=0, y0=0, adup=1, queff=1, material='water', rmax=None, downsampling=1, maxfev=1000)

    Parameters:
    ===========
    ...

    """
    Xmc, Ymc, img, msk = _prepare_for_fitting(img, msk, x0, y0, rmax, downsampling, detector_adu_photon, do_photon_counting, pixel_size, detector_distance)
    size_a = sphere_model_convert_diameter_to_size(diameter_a, wavelength, pixel_size, detector_distance)
    size_c = sphere_model_convert_diameter_to_size(diameter_c, wavelength, pixel_size, detector_distance)
    diameter = (diameter_a**2*diameter_c)**(1/3.)
    scaling = lambda i: sphere_model_convert_intensity_to_scaling(i, diameter, wavelength, pixel_size, detector_distance, detector_quantum_efficiency, 1, material)
    I_fit_m = lambda i: I_spheroid_diffraction(scaling(i),Xmc,Ymc,size_a,size_c,0.,phi)
    E_fit_m = lambda i: I_fit_m(i) - img[msk]
    #print(E_fit_m(intensity))

    if len(img[msk]):
        [intensity], cov, infodict, mesg, ier = leastsq(E_fit_m, intensity, maxfev=maxfev, xtol=1e-3, full_output=True)
        # Reduced Chi-squared and standard error
        chisquared = (E_fit_m(intensity)**2).sum()/(img.shape[0]*img.shape[1] - 1)
        if cov is not None:
            pcov = cov[0,0]*chisquared
        else:
            pcov = None
    else:
        infodict={}
        pcov = None
        chisquared = 0
        
    if full_output:
        infodict['error'] = chisquared
        infodict['pcov'] = pcov
        return intensity, infodict
    else:
        return intensity
def fit_full_spheroid_model(img, msk, diameter_a, diameter_c, phi, intensity, wavelength, pixel_size, detector_distance, full_output=False, x0=0, y0=0, detector_adu_photon=1., detector_quantum_efficiency=1., material='water', rmax=None, downsampling=1, maxfev=1000, deltab=0.2, do_photon_counting=False,n=1):
    diameter_a = max(diameter_a, 1.E-9)
    diameter_c = max(diameter_c, 1.E-9)
    #intensity = max(intensity,1.)
    #x0 = min(x0, img.shape[1])
    #y0 = min(y0, img.shape[0])
    for i in range(n):
        Xm, Ym, img, msk = _prepare_for_fitting(img, msk, x0, y0, rmax, downsampling, detector_adu_photon, do_photon_counting, pixel_size, detector_distance)
        size = lambda d: sphere_model_convert_diameter_to_size(d, wavelength, pixel_size, detector_distance)
        d = lambda da,dc: (da**2*dc)**(1/3.)
        scaling = lambda i,da,dc: sphere_model_convert_intensity_to_scaling(i, d(da,dc), wavelength, pixel_size, detector_distance, detector_quantum_efficiency, 1, material)
        I_fit_m = lambda dx,dy,da,dc,p,i: I_spheroid_diffraction(scaling(i,da,dc), Xm-dx, Ym-dy, size(da), size(dc), 0., p)
        E_fit_m = lambda p: I_fit_m(p[0],p[1],p[2],p[3],p[4],p[5]) - img[msk]
        p0 = numpy.array([0,0,diameter_a,diameter_c,phi,intensity])
        x0_bound = (None, None)
        y0_bound = (None, None)
        d_a_bound  = ((1-deltab)*diameter_a, (1+deltab)*diameter_a)
        d_c_bound  = ((1-deltab)*diameter_c, (1+deltab)*diameter_c)
        p_bound = (None, None)
        i_bound  = (None, None)
        bounds   = numpy.array([x0_bound, y0_bound , d_a_bound, d_c_bound, p_bound, i_bound])
        p, cov, info, mesg, ier = spimage.leastsqbound(E_fit_m, p0, maxfev=maxfev, xtol=1e-5, full_output=True, bounds=bounds)
        [dx0, dy0, diameter_a, diameter_c, phi, intensity] = p
        diameter_a = abs(diameter_a)
        diameter_c = abs(diameter_c)
        x0 += dx0
        y0 += dy0
        phi = phi % numpy.pi
        if (numpy.isfinite(p) == False).sum() > 0:
            break

    # Reduced Chi-squared and standard errors
    chisquared = (E_fit_m(p)**2).sum()/(img.shape[0]*img.shape[1] - len(p))
    #print(cov)
    if cov is not None:
        pcov = numpy.diag(cov)*chisquared
    else:
        pcov = numpy.array(len(p)*[None])
    if full_output:
        info["error"] = chisquared
        info["pcov"]  = pcov
        return x0, y0, diameter_a, diameter_c, phi, intensity, info
    else:
        return x0, y0, diameter_a, diameter_c, phi, intensity
Exemple #4
0
def fit_spheroid_shape_pearson(img,
                               msk,
                               diameter_a,
                               diameter_c,
                               phi,
                               intensity,
                               wavelength,
                               pixel_size,
                               detector_distance,
                               full_output=False,
                               x0=0,
                               y0=0,
                               detector_adu_photon=1,
                               detector_quantum_efficiency=1,
                               material='water',
                               rmax=None,
                               downsampling=1,
                               do_brute_evals=0,
                               maxfev=1000,
                               do_photon_counting=False,
                               deltab=0.5,
                               force_prolate=True):
    """
    Fit the shape of a spheroid using pearson correlation.

    """
    Xmc, Ymc, img, msk = _prepare_for_fitting(img, msk, x0, y0, rmax,
                                              downsampling,
                                              detector_adu_photon,
                                              do_photon_counting, pixel_size,
                                              detector_distance)
    diameter = (diameter_a**2 * diameter_c)**(1 / 3.)
    S = sphere_model_convert_intensity_to_scaling(intensity, diameter,
                                                  wavelength, pixel_size,
                                                  detector_distance,
                                                  detector_quantum_efficiency,
                                                  1, material)
    size = lambda d: sphere_model_convert_diameter_to_size(
        d, wavelength, pixel_size, detector_distance)
    I_fit_m = lambda da, dc, p: I_spheroid_diffraction(S, Xmc, Ymc, size(da),
                                                       size(dc), 0., p)

    def E_fit_m(p):
        if not (img[msk].std() and I_fit_m(p[0], p[1], p[2]).std()):
            return numpy.ones(len(p))
        else:
            return 1 - scipy.stats.pearsonr(I_fit_m(p[0], p[1], p[2]),
                                            img[msk])[0] * numpy.ones(len(p))

    # Start with brute force with a sensible range
    # We'll assume at least 20x oversampling
    if do_brute_evals:
        dmin = sphere_model_convert_size_to_diameter(
            1. / (downsampling * img.shape[0]), wavelength, pixel_size,
            detector_distance)
        dmax = dmin * downsampling * img.shape[0] / 20
        pmin = 0.
        pmax = numpy.pi
        Ns = do_brute_evals
        diameter = scipy.optimize.brute(E_fit_m, [(dmin, dmax), (dmin, dmax),
                                                  (pmin, pmax)],
                                        Ns=Ns)[0]

    # End with least square
    p0 = numpy.array([diameter_a, diameter_c, phi])
    p, cov, infodict, mesg, ier = leastsq(E_fit_m,
                                          p0,
                                          maxfev=maxfev,
                                          xtol=1e-5,
                                          full_output=True)
    [diameter_a, diameter_c, phi] = p
    diameter_a = abs(diameter_a)
    diameter_c = abs(diameter_c)
    phi = phi % numpy.pi

    if force_prolate and diameter_a > diameter_c:
        return fit_spheroid_shape_pearson(
            img, msk, diameter_c, diameter_a, phi + numpy.pi / 2., intensity,
            wavelength, pixel_size, detector_distance, full_output, x0, y0,
            detector_adu_photon, detector_quantum_efficiency, material, rmax,
            downsampling, do_brute_evals, maxfev, do_photon_counting, deltab)

    # Reduced Chi-squared and standard error
    chisquared = ((I_fit_m(diameter_a, diameter_c, phi) - img[msk])**
                  2).sum() / (img.shape[0] * img.shape[1] - 1)
    if cov is not None:
        pcov = cov[0, 0] * chisquared
    else:
        pcov = None

    if full_output:
        infodict['error'] = chisquared
        infodict['pcov'] = pcov
        return diameter_a, diameter_c, phi, infodict
    else:
        return diameter_a, diameter_c, phi
Exemple #5
0
def fit_full_spheroid_model(img,
                            msk,
                            diameter_a,
                            diameter_c,
                            phi,
                            intensity,
                            wavelength,
                            pixel_size,
                            detector_distance,
                            full_output=False,
                            x0=0,
                            y0=0,
                            detector_adu_photon=1.,
                            detector_quantum_efficiency=1.,
                            material='water',
                            rmax=None,
                            downsampling=1,
                            maxfev=1000,
                            deltab=0.2,
                            do_photon_counting=False,
                            n=1):
    diameter_a = max(diameter_a, 1.E-9)
    diameter_c = max(diameter_c, 1.E-9)
    #intensity = max(intensity,1.)
    #x0 = min(x0, img.shape[1])
    #y0 = min(y0, img.shape[0])
    for i in range(n):
        Xm, Ym, img, msk = _prepare_for_fitting(img, msk, x0, y0, rmax,
                                                downsampling,
                                                detector_adu_photon,
                                                do_photon_counting, pixel_size,
                                                detector_distance)
        size = lambda d: sphere_model_convert_diameter_to_size(
            d, wavelength, pixel_size, detector_distance)
        d = lambda da, dc: (da**2 * dc)**(1 / 3.)
        scaling = lambda i, da, dc: sphere_model_convert_intensity_to_scaling(
            i, d(da, dc), wavelength, pixel_size, detector_distance,
            detector_quantum_efficiency, 1, material)
        I_fit_m = lambda dx, dy, da, dc, p, i: I_spheroid_diffraction(
            scaling(i, da, dc), Xm - dx, Ym - dy, size(da), size(dc), 0., p)
        E_fit_m = lambda p: I_fit_m(p[0], p[1], p[2], p[3], p[4], p[5]) - img[
            msk]
        p0 = numpy.array([0, 0, diameter_a, diameter_c, phi, intensity])
        x0_bound = (None, None)
        y0_bound = (None, None)
        d_a_bound = ((1 - deltab) * diameter_a, (1 + deltab) * diameter_a)
        d_c_bound = ((1 - deltab) * diameter_c, (1 + deltab) * diameter_c)
        p_bound = (None, None)
        i_bound = (None, None)
        bounds = numpy.array(
            [x0_bound, y0_bound, d_a_bound, d_c_bound, p_bound, i_bound])
        p, cov, info, mesg, ier = spimage.leastsqbound(E_fit_m,
                                                       p0,
                                                       maxfev=maxfev,
                                                       xtol=1e-5,
                                                       full_output=True,
                                                       bounds=bounds)
        [dx0, dy0, diameter_a, diameter_c, phi, intensity] = p
        diameter_a = abs(diameter_a)
        diameter_c = abs(diameter_c)
        x0 += dx0
        y0 += dy0
        phi = phi % numpy.pi
        if (numpy.isfinite(p) == False).sum() > 0:
            break

    # Reduced Chi-squared and standard errors
    chisquared = (E_fit_m(p)**2).sum() / (img.shape[0] * img.shape[1] - len(p))
    #print(cov)
    if cov is not None:
        pcov = numpy.diag(cov) * chisquared
    else:
        pcov = numpy.array(len(p) * [None])
    if full_output:
        info["error"] = chisquared
        info["pcov"] = pcov
        return x0, y0, diameter_a, diameter_c, phi, intensity, info
    else:
        return x0, y0, diameter_a, diameter_c, phi, intensity
Exemple #6
0
def fit_spheroid_intensity_pixelwise(img,
                                     msk,
                                     diameter_a,
                                     diameter_c,
                                     phi,
                                     intensity,
                                     wavelength,
                                     pixel_size,
                                     detector_distance,
                                     full_output=False,
                                     x0=0,
                                     y0=0,
                                     detector_adu_photon=1,
                                     detector_quantum_efficiency=1,
                                     material='water',
                                     rmax=None,
                                     downsampling=1,
                                     maxfev=1000,
                                     do_photon_counting=False):
    """
    Fit the intensity [J / m^2] on a spheroid to diffraction data using least square optimization.
    The cost function is defined as a pixelwise comparison between model and data.

    usage:
    ======
    intensity       = fit_spheroid_intensity(img, msk, diameter_a, diameter_c, phi, intensity, pixel_size, detector_distance)
    intensity, info = fit_spheroid_intensity(img, msk, diameter_a, diameter_c, phi, intensity, pixel_size, detector_distance, full_output=True)
    intensity, info = fit_spheroid_intensity(img, msk, diameter_a, diameter_c, phi, intensity, pixel_size, detector_distance, full_output=True, x0=0, y0=0, adup=1, queff=1, material='water', rmax=None, downsampling=1, maxfev=1000)

    Parameters:
    ===========
    ...

    """
    Xmc, Ymc, img, msk = _prepare_for_fitting(img, msk, x0, y0, rmax,
                                              downsampling,
                                              detector_adu_photon,
                                              do_photon_counting, pixel_size,
                                              detector_distance)
    size_a = sphere_model_convert_diameter_to_size(diameter_a, wavelength,
                                                   pixel_size,
                                                   detector_distance)
    size_c = sphere_model_convert_diameter_to_size(diameter_c, wavelength,
                                                   pixel_size,
                                                   detector_distance)
    diameter = (diameter_a**2 * diameter_c)**(1 / 3.)
    scaling = lambda i: sphere_model_convert_intensity_to_scaling(
        i, diameter, wavelength, pixel_size, detector_distance,
        detector_quantum_efficiency, 1, material)
    I_fit_m = lambda i: I_spheroid_diffraction(scaling(i), Xmc, Ymc, size_a,
                                               size_c, 0., phi)
    E_fit_m = lambda i: I_fit_m(i) - img[msk]
    #print(E_fit_m(intensity))

    if len(img[msk]):
        [intensity], cov, infodict, mesg, ier = leastsq(E_fit_m,
                                                        intensity,
                                                        maxfev=maxfev,
                                                        xtol=1e-3,
                                                        full_output=True)
        # Reduced Chi-squared and standard error
        chisquared = (E_fit_m(intensity)**
                      2).sum() / (img.shape[0] * img.shape[1] - 1)
        if cov is not None:
            pcov = cov[0, 0] * chisquared
        else:
            pcov = None
    else:
        infodict = {}
        pcov = None
        chisquared = 0

    if full_output:
        infodict['error'] = chisquared
        infodict['pcov'] = pcov
        return intensity, infodict
    else:
        return intensity