def table_ilms(): np.random.seed(11) s = create_image() lilms = [ ilms.LegendrePoly2P1D(shape=s.ilm.shape, order=(1, 1, 1)), ilms.LegendrePoly2P1D(shape=s.ilm.shape, order=(3, 3, 3)), ilms.BarnesStreakLegPoly2P1DX3(shape=s.ilm.shape, order=(1, 1, 1), npts=(10, 5)), ilms.BarnesStreakLegPoly2P1DX3(shape=s.ilm.shape, order=(1, 1, 2), npts=(30, 10)), ilms.BarnesStreakLegPoly2P1DX3(shape=s.ilm.shape, order=s.ilm.order, npts=(30, 10, 5)), ] names = [ r'Legendre 2+1D (0,0,0)', r'Legendre 2+1D (2,2,2)', r'Barnes (10, 5) $N_z=1$', r'Barnes (30, 10) $N_z=2$', r'Barnes (30, 10, 5) $N_z=3$', ] def vary_func(s, data): s.set_ilm(data) return table(s, lilms, names, vary_func)
def makestate(im, pos, rad, slab=None, mem_level='hi'): """ Workhorse for creating & optimizing states with an initial centroid guess. This is an example function that works for a particular microscope. For your own microscope, you'll need to change particulars such as the psf type and the orders of the background and illumination. Parameters ---------- im : :class:`~peri.util.RawImage` A RawImage of the data. pos : [N,3] element numpy.ndarray. The initial guess for the N particle positions. rad : N element numpy.ndarray. The initial guess for the N particle radii. slab : :class:`peri.comp.objs.Slab` or None, optional If not None, a slab corresponding to that in the image. Default is None. mem_level : {'lo', 'med-lo', 'med', 'med-hi', 'hi'}, optional A valid memory level for the state to control the memory overhead at the expense of accuracy. Default is `'hi'` Returns ------- :class:`~peri.states.ImageState` An ImageState with a linked z-scale, a ConfocalImageModel, and all the necessary components with orders at which are useful for my particular test case. """ if slab is not None: o = comp.ComponentCollection( [ objs.PlatonicSpheresCollection(pos, rad, zscale=zscale), slab ], category='obj' ) else: o = objs.PlatonicSpheresCollection(pos, rad, zscale=zscale) p = exactpsf.FixedSSChebLinePSF() npts, iorder = _calc_ilm_order(im.get_image().shape) i = ilms.BarnesStreakLegPoly2P1D(npts=npts, zorder=iorder) b = ilms.LegendrePoly2P1D(order=(9 ,3, 5), category='bkg') c = comp.GlobalScalar('offset', 0.0) s = states.ImageState(im, [o, i, b, c, p]) runner.link_zscale(s) if mem_level != 'hi': s.set_mem_level(mem_level) opt.do_levmarq(s, ['ilm-scale'], max_iter=1, run_length=6, max_mem=1e4) return s
def create_img(): """Creates an image, as a `peri.util.Image`, which is similar to the image in the tutorial""" # 1. particles + coverslip rad = 0.5 * np.random.randn(POS.shape[0]) + 4.5 # 4.5 +- 0.5 px particles part = objs.PlatonicSpheresCollection(POS, rad, zscale=0.89) slab = objs.Slab(zpos=4.92, angles=(-4.7e-3, -7.3e-4)) objects = comp.ComponentCollection([part, slab], category='obj') # 2. psf, ilm p = exactpsf.FixedSSChebLinePSF(kfki=1.07, zslab=-29.3, alpha=1.17, n2n1=0.98, sigkf=-0.33, zscale=0.89, laser_wavelength=0.45) i = ilms.BarnesStreakLegPoly2P1D(npts=(16,10,8,4), zorder=8) b = ilms.LegendrePoly2P1D(order=(7,2,2), category='bkg') off = comp.GlobalScalar(name='offset', value=-2.11) mdl = models.ConfocalImageModel() st = states.ImageState(util.NullImage(shape=[48,64,64]), [objects, p, i, b, off], mdl=mdl, model_as_data=True) b.update(b.params, BKGVALS) i.update(i.params, ILMVALS) im = st.model + np.random.randn(*st.model.shape) * 0.03 return util.Image(im)
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
def do_fit(im, order=(15, 5, 5), maxcalls=50): ilm = ilms.LegendrePoly2P1D(im.shape, order=order) ilm.params[-order[-1]] = 1 ilm.from_data(im, maxcalls=maxcalls) ilm.initialize() return ilm
# We need to add a background. In principle, we could be use the same bkg # that worked for our blank image. However, in practice this doesn't work so # well, leaving noticeable residuals in z (try it!). The reason for this is # that the point-spread function has very long, power-law tails. While the psf # describes the image of a point fairly well, when the psf is integrated over # the entire area of the coverslip these tails become very long, too long to # capture with a reasonably-sized numerical psf. To account for this, we do # some minor analytical calculations and realize that the effect of the long- # tails of the psf when convolved with a slab looks like a background that # varies slowly in z. Thus, to account for some of the long-tails in the psf, # we use a background which varies in z. Since this z-dependence won't couple # with the dark-current xy dependence in our detector, we can split this out # as bkg = f(x,y) + g(z), like so: bkg = ilms.LegendrePoly2P1D(order=(7, 3, 5), category='bkg', operation='+') # This detail is important not so much for its effect on the reconstruction # of this blank image, but for what it illustrates -- while it is practically # impossible to implement an exact generative model, careful thinking can allow # for a model that is almost equivalent to the exact answer. To answer how # much this approximation matters for measuring particle properties in an, # we could generate an image with a more exact representation of these psf # long tails and then fit it with our more approximate model. # Incidentally, while the support of our psf is finite, it's quite large -- # 35 pixels in z, or 44% of the image in z! If we wanted, we could increase # this by changing the ``support_size`` keyword when calling # exactpsf.FixedSSChebLinePSF. # Finally, we create an offset: off = comp.GlobalScalar('offset', 0.0)
from peri.comp import objs coverslip = objs.Slab(zpos=6) particle_positions = numpy.load('../../Downloads/particle-positions.npy') particle_radii = 5.0 particles = objs.PlatonicSpheresCollection(particle_positions, particle_radii) from peri.comp import comp objects = comp.ComponentCollection([particles, coverslip], category='obj') from peri.comp import ilms illumination = ilms.BarnesStreakLegPoly2P1D(npts=(16, 10, 8, 4), zorder=8) background = ilms.LegendrePoly2P1D(order=(7, 2, 2), category='bkg') offset = comp.GlobalScalar(name='offset', value=0.) from peri.comp import exactpsf point_spread_function = exactpsf.FixedSSChebLinePSF() from peri import models model = models.ConfocalImageModel() print(model) from peri import states
def table(): s = create_image(identity=True) lpoly = [0.0, 0.0, 0.01, 0.05, 0.10] dnames = ['0.0', '0.0', '0.01', '0.05', '0.10'] lilms = [ ilms.LegendrePoly2P1D(shape=s.ilm.shape, order=(1, 1, 1)), ilms.LegendrePoly2P1D(shape=s.ilm.shape, order=(3, 3, 3)), ilms.BarnesStreakLegPoly2P1DX3(shape=s.ilm.shape, order=(1, 1, 1), npts=(10, 5)), ilms.BarnesStreakLegPoly2P1DX3(shape=s.ilm.shape, order=(1, 1, 2), npts=(30, 10)), ilms.BarnesStreakLegPoly2P1DX3(shape=s.ilm.shape, order=s.ilm.order, npts=(30, 10, 5)), ] lnames = [ r'Legendre 2+1D (0,0,0)', r'Legendre 2+1D (2,2,2)', r'Barnes (10, 5), $N_z=1$', r'Barnes (30, 10), $N_z=2$', r'Barnes (30, 10, 5), $N_z=3$', ] lpsfs = [ psfs.IdentityPSF(shape=s.psf.shape, params=np.array([0.0])), psfs.AnisotropicGaussian(shape=s.psf.shape, params=(2.0, 1.0, 3.0)), psfs.Gaussian4DLegPoly(shape=s.psf.shape, order=(3, 3, 3)), exactpsf.FixedSSChebLinePSF( shape=s.psf.shape, zrange=(0, s.psf.shape[0]), cheb_degree=3, cheb_evals=6, support_size=FIXEDSS, zslab=10., cutoffval=1. / 255, measurement_iterations=3, ), exactpsf.FixedSSChebLinePSF( shape=s.psf.shape, zrange=(0, s.psf.shape[0]), cheb_degree=6, cheb_evals=8, support_size=FIXEDSS, zslab=10., cutoffval=1. / 255, measurement_iterations=3, ), ] pnames = [ r'Identity', r'Gaussian$(x,y)$', r'Gaussian$(x,y,z,z^{\prime})$', r'Cheby linescan (3,6)', r'Cheby linescan (6,8)', ] results = OrderedDict() for i in xrange(len(lpoly)): print dnames[i], lnames[i], pnames[i] poly = lpoly[i] ilm = lilms[i] psf = lpsfs[i] s = create_image(polydispersity=poly) s.set_ilm(ilm) s.set_psf(psf) if isinstance(s.ilm, ilms.BarnesStreakLegPoly2P1DX3): s.ilm.randomize_parameters(ptp=0.4, vmax=1.0, fourier=False) s.reset() s.model_to_true_image() pos1 = trackpy(s) pos0 = s.obj.pos.copy() s.obj.set_pos_rad(pos1, s.obj.rad.mean() * np.ones(pos1.shape[0])) s.reset() slicer = s.get_difference_image().shape[0] / 2 results[i] = ( dnames[i], lnames[i], pnames[i], s.get_difference_image()[slicer].copy(), pos0, pos1, ) return results
from peri import states, util, models from peri.comp import psfs, objs, ilms, GlobalScalar, ComponentCollection from peri.test import nbody import peri.opt.optimize as opt import peri.opt.addsubtract as addsub im = util.NullImage(shape=(32, ) * 3) pos, rad, tile = nbody.create_configuration(3, im.tile) P = ComponentCollection( [objs.PlatonicSpheresCollection(pos, rad), objs.Slab(2)], category='obj') H = psfs.AnisotropicGaussian() I = ilms.BarnesStreakLegPoly2P1D(npts=(25, 13, 3), zorder=2, local_updates=False) B = ilms.LegendrePoly2P1D(order=(3, 1, 1), category='bkg', constval=0.01) C = GlobalScalar('offset', 0.0) I.randomize_parameters() s = states.ImageState(im, [B, I, H, P, C], pad=16, model_as_data=True)