Example #1
0
def opt_lm(s):
    opt.do_levmarq(s, s.params[1:])

    fig = pl.figure()
    pl.plot(s._xpts, s.data, 'o', label='Data')
    pl.plot(s._xpts, s.model, '-', label='Model')
    pl.xlabel(r"$x$")
    pl.ylabel(r"$y$")
    pl.legend(loc='best')
    pl.title("Best fit model")
Example #2
0
def rattle_and_fit(s):
    # grab the original values
    values = np.array(s.values).copy()

    # update the model with random parameters then optimize back
    s.update(s.params, values + np.random.randn(len(values)))
    opt.do_levmarq(s, s.params, run_length=12)

    # calculate the crb for all parameters
    crb = s.crb()

    # print a table comparing inferred values
    print(' {:^6s} += {:^5s} | {:^8s}'.format('Fit', 'CRB', 'Actual'))
    print('-' * 27)
    for v0, c, v1 in zip(s.values, crb, values):
        print('{:7.3f} += {:4.3f} | {:7.3f}'.format(v0, c, v1))
Example #3
0
def locate_spheres(image,
                   feature_rad,
                   dofilter=False,
                   order=(3, 3, 3),
                   trim_edge=True,
                   **kwargs):
    """
    Get an initial featuring of sphere positions in an image.

    Parameters
    -----------
    image : :class:`peri.util.Image` object
        Image object which defines the image file as well as the region.

    feature_rad : float
        Radius of objects to find, in pixels. This is a featuring radius
        and not a real radius, so a better value is frequently smaller
        than the real radius (half the actual radius is good). If ``use_tp``
        is True, then the twice ``feature_rad`` is passed as trackpy's
        ``diameter`` keyword.

    dofilter : boolean, optional
        Whether to remove the background before featuring. Doing so can
        often greatly increase the success of initial featuring and
        decrease later optimization time. Filtering functions by fitting
        the image to a low-order polynomial and featuring the residuals.
        In doing so, this will change the mean intensity of the featured
        image and hence the good value of ``minmass`` will change when
        ``dofilter`` is True. Default is False.

    order : 3-element tuple, optional
        If `dofilter`, the 2+1D Leg Poly approximation to the background
        illumination field. Default is (3,3,3).

    Other Parameters
    ----------------
    invert : boolean, optional
        Whether to invert the image for featuring. Set to True if the
        image is dark particles on a bright background. Default is True
    minmass : Float or None, optional
        The minimum mass/masscut of a particle. Default is None, which
        calculates internally.
    use_tp : Bool, optional
        Whether or not to use trackpy. Default is False, since trackpy
        cuts out particles at the edge.

    Returns
    --------
    positions : np.ndarray [N,3]
        Positions of the particles in order (z,y,x) in image pixel units.

    Notes
    -----
    Optionally filters the image by fitting the image I(x,y,z) to a
    polynomial, then subtracts this fitted intensity variation and uses
    centroid methods to find the particles.
    """
    # We just want a smoothed field model of the image so that the residuals
    # are simply the particles without other complications
    m = models.SmoothFieldModel()
    I = ilms.LegendrePoly2P1D(order=order, constval=image.get_image().mean())
    s = states.ImageState(image, [I], pad=0, mdl=m)
    if dofilter:
        opt.do_levmarq(s, s.params)
    pos = addsub.feature_guess(s, feature_rad, trim_edge=trim_edge,
                               **kwargs)[0]
    return pos
Example #4
0
from peri.comp import ilms, objs, exactpsf, comp
import peri.opt.optimize as opt

from peri.viz.interaction import *  # OrthoViewer & OrthoManipulator

# We start with featuring just a background image
# This image was taken with no sample, i.e. we're just measuring dark current
im_bkg = util.RawImage('./bkg_test.tif')  # located in the scripts folder

# First we try with just a constant background
bkg_const = ilms.LegendrePoly3D(order=(1, 1, 1))
# Since we're just fitting a blank image, we don't need a psf at first, so we
# use the simplest model for the state: a SmoothFieldModel, which has just
# returns the illumination field:
st = states.ImageState(im_bkg, [bkg_const], mdl=models.SmoothFieldModel())
opt.do_levmarq(st, st.params)


# Since there's not a whole lot to see in this image, looking at the
# OrthoViewer or OrthoManipulator doesn't provide a lot of insight. Instead,
# we look at plots of the residuals along certain axes. We'll do this several
# times so I'll make a function:
def plot_averaged_residuals(st):
    plt.figure(figsize=[15, 6])
    for i in xrange(3):
        plt.subplot(1, 3, 1 + i)
        mean_ax = tuple({0, 1, 2} - {i})  # which 2 directions to average over
        plt.plot(st.residuals.mean(axis=mean_ax))
        plt.title('{}-averaged'.format(['$xy$', '$xz$', '$yz$'][i]),
                  fontsize='large')
Example #5
0
def add_subtract(st,
                 max_iter=7,
                 max_npart='calc',
                 max_mem=2e8,
                 always_check_remove=False,
                 **kwargs):
    """
    Automatically adds and subtracts missing & extra particles.

    Operates by removing bad particles then adding missing particles on
    repeat, until either no particles are added/removed or after `max_iter`
    attempts.

    Parameters
    ----------
    st: :class:`peri.states.State`
        The state to add and subtract particles to.
    max_iter : Int, optional
        The maximum number of add-subtract loops to use. Default is 7.
        Terminates after either max_iter loops or when nothing has changed.
    max_npart : Int or 'calc', optional
        The maximum number of particles to add before optimizing the non-psf
        globals. Default is ``'calc'``, which uses 5% of the initial number
        of particles.
    max_mem : Int, optional
        The maximum memory to use for optimization after adding max_npart
        particles. Default is 2e8.
    always_check_remove : Bool, optional
        Set to True to always check whether to remove particles. If ``False``,
        only checks for removal while particles were removed on the previous
        attempt. Default is False.

    Other Parameters
    ----------------
    invert : Bool, optional
        ``True`` if the particles are dark on a bright background, ``False``
        if they are bright on a dark background. Default is ``True``.
    min_rad : Float, optional
        Particles with radius below ``min_rad`` are automatically deleted.
        Default is ``'calc'`` = median rad - 25* radius std.
    max_rad : Float, optional
        Particles with radius above ``max_rad`` are automatically deleted.
        Default is ``'calc'`` = median rad + 15* radius std, but you should
        change this for your particle sizes.

    min_edge_dist : Float, optional
        Particles closer to the edge of the padded image than this are
        automatically deleted. Default is 2.0.
    check_rad_cutoff : 2-element float list.
        Particles with ``radii < check_rad_cutoff[0]`` or ``> check...[1]``
        are checked if they should be deleted (not automatic). Default is
        ``[3.5, 15]``.
    check_outside_im : Bool, optional
        Set to True to check whether to delete particles whose positions are
        outside the un-padded image.

    rad : Float, optional
        The initial radius for added particles; added particles radii are
        not fit until the end of ``add_subtract``. Default is ``'calc'``,
        which uses the median radii of active particles.

    tries : Int, optional
        The number of particles to attempt to remove or add, per iteration.
        Default is 50.

    im_change_frac : Float, optional
        How good the change in error needs to be relative to the change in
        the difference image. Default is 0.2; i.e. if the error does not
        decrease by 20% of the change in the difference image, do not add
        the particle.

    min_derr : Float, optional
        The minimum change in the state's error to keep a particle in the
        image. Default is ``'3sig'`` which uses ``3*st.sigma``.

    do_opt : Bool, optional
        Set to False to avoid optimizing particle positions after adding.
    minmass : Float, optional
        The minimum mass for a particle to be identified as a feature,
        as used by trackpy. Defaults to a decent guess.

    use_tp : Bool, optional
        Set to True to use trackpy to find missing particles inside the
        image. Not recommended since trackpy deliberately cuts out particles
        at the edge of the image. Default is ``False``.

    Returns
    -------
    total_changed : Int
        The total number of adds and subtracts done on the data. Not the
        same as ``changed_inds.size`` since the same particle or particle
        index can be added/subtracted multiple times.
    added_positions : [N_added,3] numpy.ndarray
        The positions of particles that have been added at any point in the
        add-subtract cycle.
    removed_positions : [N_added,3] numpy.ndarray
        The positions of particles that have been removed at any point in
        the add-subtract cycle.

    Notes
    ------
    Occasionally after the intial featuring a cluster of particles is
    featured as 1 big particle. To fix these mistakes, it helps to set
    max_rad to a physical value. This removes the big particle and allows
    it to be re-featured by (several passes of) the adds.

    The added/removed positions returned are whether or not the position
    has been added or removed ever. It's possible that a position is
    added, then removed during a later iteration.
    """
    if max_npart == 'calc':
        max_npart = 0.05 * st.obj_get_positions().shape[0]

    total_changed = 0
    _change_since_opt = 0
    removed_poses = []
    added_poses0 = []
    added_poses = []

    nr = 1  # Check removal on the first loop
    for _ in range(max_iter):
        if (nr != 0) or (always_check_remove):
            nr, rposes = remove_bad_particles(st, **kwargs)
        na, aposes = add_missing_particles(st, **kwargs)
        current_changed = na + nr
        removed_poses.extend(rposes)
        added_poses0.extend(aposes)
        total_changed += current_changed
        _change_since_opt += current_changed
        if current_changed == 0:
            break
        elif _change_since_opt > max_npart:
            _change_since_opt *= 0
            CLOG.info('Start add_subtract optimization.')
            opt.do_levmarq(st,
                           opt.name_globals(
                               st, remove_params=st.get('psf').params),
                           max_iter=1,
                           run_length=4,
                           num_eig_dirs=3,
                           max_mem=max_mem,
                           eig_update_frequency=2,
                           rz_order=0,
                           use_accel=True)
            CLOG.info('After optimization:\t{:.6}'.format(st.error))

    # Optimize the added particles' radii:
    for p in added_poses0:
        i = st.obj_closest_particle(p)
        opt.do_levmarq_particles(st, np.array([i]), max_iter=2, damping=0.3)
        added_poses.append(st.obj_get_positions()[i])
    return total_changed, np.array(removed_poses), np.array(added_poses)