<EOL>key = '<STR_LIT>'.join([c if c in '<STR_LIT>' else '<STR_LIT>' for c in mem_level])<EOL>if key not in ['<STR_LIT:h>','<STR_LIT>','<STR_LIT:m>','<STR_LIT>','<STR_LIT:m>', '<STR_LIT:l>']:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>mem_levels = {  '<STR_LIT:h>':     [np.float64, np.float64],<EOL>'<STR_LIT>': [np.float64, np.float32],<EOL>'<STR_LIT:m>':   [np.float32, np.float32],<EOL>'<STR_LIT>':  [np.float32, np.float16],<EOL>'<STR_LIT:l>':      [np.float16, np.float16]<EOL>}<EOL>hi_lvl, lo_lvl = mem_levels[key]<EOL>cat_lvls = {'<STR_LIT>':lo_lvl,<EOL>'<STR_LIT>':hi_lvl,<EOL>'<STR_LIT>':lo_lvl<EOL>}  <EOL>self.image.float_precision = hi_lvl<EOL>self.image.image = self.image.image.astype(lo_lvl)<EOL>self.set_image(self.image)<EOL>for cat in cat_lvls.keys():<EOL><INDENT>obj = self.get(cat)<EOL>if hasattr(obj, '<STR_LIT>'):<EOL><INDENT>for c in obj.comps:<EOL><INDENT>c.float_precision = lo_lvl<EOL><DEDENT><DEDENT>else:<EOL><INDENT>obj.float_precision = lo_lvl<EOL><DEDENT><DEDENT>self._model = self._model.astype(hi_lvl)<EOL>self._residuals = self._model.astype(hi_lvl)<EOL>self.reset()<EOL>

Sets the memory usage level of the state.

Parameters
----------
mem_level : string
    Can be set to one of:
        * hi      : all mem's are np.float64
        * med-hi  : image, platonic are float32, rest are float64
        * med     : all mem's are float32
        * med-lo  : image, platonic are float16, rest float32
        * lo      : all are float16, which is bad for accuracy.

Notes
-----
Right now the PSF is not affected by the mem-level changes, which is
OK for mem but it means that self._model, self._residuals are always
float64, which can be a chunk of mem.


def norm(field, vmin=<NUM_LIT:0>, vmax=<NUM_LIT:255>):

field = <NUM_LIT:255>*np.clip(field, <NUM_LIT:0>, <NUM_LIT:1>)<EOL>field = field.astype('<STR_LIT>')<EOL>return field<EOL>

Truncates field to 0,1; then normalizes to a uin8 on [0,255]


es, pp = field.split('<STR_LIT:->')  <EOL>if pp == '<STR_LIT>':<EOL><INDENT>o = state.get('<STR_LIT>')<EOL>if isinstance(o, peri.comp.comp.ComponentCollection):<EOL><INDENT>wts = <NUM_LIT:0>*o.get()[state.inner]<EOL>for c in o.comps:<EOL><INDENT>if isinstance(c, peri.comp.objs.PlatonicSpheresCollection):<EOL><INDENT>wts += c.get()[state.inner]<EOL><DEDENT><DEDENT><DEDENT>else:<EOL><INDENT>wts = o.get()[state.inner]<EOL><DEDENT><DEDENT>elif pp == '<STR_LIT>':<EOL><INDENT>wts = state.get('<STR_LIT>').get()[state.inner]<EOL><DEDENT>else:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>if es == '<STR_LIT>':<EOL><INDENT>out = (<NUM_LIT:1>-state.data) * (wts > <NUM_LIT>)<EOL><DEDENT>elif es == '<STR_LIT>':<EOL><INDENT>out = wts<EOL><DEDENT>else:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>return norm(clip(roll(out)))<EOL>

Given a state, extracts a field. Extracted value depends on the value
of field:
    'exp-particles' : The inverted data in the regions of the particles,
            zeros otherwise -- i.e. particles + noise.
    'exp-platonic'  : Same as above, but nonzero in the region of the
            entire platonic image -- i.e. platonic + noise.
    'sim-particles' : Just the particles image; no noise from the data.
    'sim-platonic'  : Just the platonic image; no noise from the data.


def volume_render(field, outfile, maxopacity=<NUM_LIT:1.0>, cmap='<STR_LIT>',<EOL>size=<NUM_LIT>, elevation=<NUM_LIT>, azimuth=<NUM_LIT>, bkg=(<NUM_LIT:0.0>, <NUM_LIT:0.0>, <NUM_LIT:0.0>),<EOL>opacitycut=<NUM_LIT>, offscreen=False, rayfunction='<STR_LIT>'):

sh = field.shape<EOL>dataImporter = vtk.vtkImageImport()<EOL>dataImporter.SetDataScalarTypeToUnsignedChar()<EOL>data_string = field.tostring()<EOL>dataImporter.SetNumberOfScalarComponents(<NUM_LIT:1>)<EOL>dataImporter.CopyImportVoidPointer(data_string, len(data_string))<EOL>dataImporter.SetDataExtent(<NUM_LIT:0>, sh[<NUM_LIT:2>]-<NUM_LIT:1>, <NUM_LIT:0>, sh[<NUM_LIT:1>]-<NUM_LIT:1>, <NUM_LIT:0>, sh[<NUM_LIT:0>]-<NUM_LIT:1>)<EOL>dataImporter.SetWholeExtent(<NUM_LIT:0>, sh[<NUM_LIT:2>]-<NUM_LIT:1>, <NUM_LIT:0>, sh[<NUM_LIT:1>]-<NUM_LIT:1>, <NUM_LIT:0>, sh[<NUM_LIT:0>]-<NUM_LIT:1>)<EOL>alphaChannelFunc = vtk.vtkPiecewiseFunction()<EOL>alphaChannelFunc.AddPoint(<NUM_LIT:0>, <NUM_LIT:0.0>)<EOL>alphaChannelFunc.AddPoint(int(<NUM_LIT:255>*opacitycut), maxopacity)<EOL>volumeProperty = vtk.vtkVolumeProperty()<EOL>colorFunc = cmap2colorfunc(cmap)<EOL>volumeProperty.SetColor(colorFunc)<EOL>volumeProperty.SetScalarOpacity(alphaChannelFunc)<EOL>volumeMapper = vtk.vtkVolumeRayCastMapper()<EOL>if rayfunction == '<STR_LIT>':<EOL><INDENT>comp = vtk.vtkVolumeRayCastMIPFunction()<EOL>comp.SetMaximizeMethodToOpacity()<EOL><DEDENT>elif rayfunction == '<STR_LIT>':<EOL><INDENT>comp = vtk.vtkVolumeRayCastCompositeFunction()<EOL><DEDENT>elif rayfunction == '<STR_LIT>':<EOL><INDENT>comp = vtk.vtkVolumeRayCastIsosurfaceFunction()<EOL>comp.SetIsoValue(maxopacity/<NUM_LIT:2>)<EOL><DEDENT>else:<EOL><INDENT>comp = vtk.vtkVolumeRayCastIsosurfaceFunction()<EOL><DEDENT>volumeMapper.SetSampleDistance(<NUM_LIT:0.1>)<EOL>volumeMapper.SetVolumeRayCastFunction(comp)<EOL>if rayfunction == '<STR_LIT>':<EOL><INDENT>volumeMapper = vtk.vtkSmartVolumeMapper()<EOL><DEDENT>volumeMapper.SetInputConnection(dataImporter.GetOutputPort())<EOL>volume = vtk.vtkVolume()<EOL>volume.SetMapper(volumeMapper)<EOL>volume.SetProperty(volumeProperty)<EOL>light = vtk.vtkLight()<EOL>light.SetLightType(vtk.VTK_LIGHT_TYPE_HEADLIGHT)<EOL>light.SetIntensity(<NUM_LIT>)<EOL>light.SwitchOn()<EOL>renderer = vtk.vtkRenderer()<EOL>renderWin = vtk.vtkRenderWindow()<EOL>renderWin.AddRenderer(renderer)<EOL>renderWin.SetOffScreenRendering(<NUM_LIT:1>);<EOL>if not hasattr(size, '<STR_LIT>'):<EOL><INDENT>size = (size, size)<EOL><DEDENT>renderer.AddVolume(volume)<EOL>renderer.AddLight(light)<EOL>renderer.SetBackground(*bkg)<EOL>renderWin.SetSize(*size)<EOL>if offscreen:<EOL><INDENT>renderWin.SetOffScreenRendering(<NUM_LIT:1>)<EOL><DEDENT>def exitCheck(obj, event):<EOL><INDENT>if obj.GetEventPending() != <NUM_LIT:0>:<EOL><INDENT>obj.SetAbortRender(<NUM_LIT:1>)<EOL><DEDENT><DEDENT>renderWin.AddObserver("<STR_LIT>", exitCheck)<EOL>renderInteractor = vtk.vtkRenderWindowInteractor()<EOL>renderInteractor.Initialize()<EOL>renderWin.Render()<EOL>renderInteractor.Start()<EOL>writer = vtk.vtkPNGWriter()<EOL>w2i = vtk.vtkWindowToImageFilter()<EOL>w2i.SetInput(renderWin)<EOL>writer.SetInputConnection(w2i.GetOutputPort())<EOL>renderWin.Render()<EOL>ac = renderer.GetActiveCamera()<EOL>ac.Elevation(elevation)<EOL>ac.Azimuth(azimuth)<EOL>renderer.ResetCameraClippingRange()<EOL>renderWin.Render()<EOL>w2i.Modified()<EOL>writer.SetFileName(outfile)<EOL>writer.Write()<EOL>

Uses vtk to make render an image of a field, with control over the
camera angle and colormap.

Input Parameters
----------------
    field : np.ndarray
        3D array of the field to render.
    outfile : string
        The save name of the image.
    maxopacity : Float
        Default is 1.0
    cmap : matplotlib colormap string
        Passed to cmap2colorfunc. Default is bone.
    size : 2-element list-like of ints or Int
        The size of the final rendered image.
    elevation : Numeric
        The elevation of the camera angle, in degrees. Default is 45
    azimuth : Numeric
        The azimuth of the camera angle, in degrees. Default is 45
    bkg : Tuple of floats
        3-element tuple of floats on [0,1] of the background image color.
        Default is (0., 0., 0.).


def make_clean_figure(figsize, remove_tooltips=False, remove_keybindings=False):

tooltip = mpl.rcParams['<STR_LIT>']<EOL>if remove_tooltips:<EOL><INDENT>mpl.rcParams['<STR_LIT>'] = '<STR_LIT:None>'<EOL><DEDENT>fig = pl.figure(figsize=figsize)<EOL>mpl.rcParams['<STR_LIT>'] = tooltip<EOL>if remove_keybindings:<EOL><INDENT>fig.canvas.mpl_disconnect(fig.canvas.manager.key_press_handler_id)<EOL><DEDENT>return fig<EOL>

Makes a `matplotlib.pyplot.Figure` without tooltips or keybindings

Parameters
----------
figsize : tuple
    Figsize as passed to `matplotlib.pyplot.figure`
remove_tooltips, remove_keybindings : bool
    Set to True to remove the tooltips bar or any key bindings,
    respectively. Default is False

Returns
-------
fig : `matplotlib.pyplot.Figure`


def __init__(self, state, size=<NUM_LIT:8>, cmap_abs='<STR_LIT>', cmap_diff='<STR_LIT>',<EOL>incsize=<NUM_LIT>, orientation=None, vrange_img=<NUM_LIT:1.0>, vrange_diff=<NUM_LIT:0.1>):

self.incsize = incsize<EOL>self.modes = ['<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>']<EOL>self.mode = self.modes[<NUM_LIT:0>]<EOL>self.insets = ['<STR_LIT>']<EOL>self.inset = '<STR_LIT:none>'<EOL>self.views = ['<STR_LIT>', '<STR_LIT>', '<STR_LIT>']<EOL>self.view = self.views[<NUM_LIT:0>]<EOL>self.modifiers = ['<STR_LIT:none>', '<STR_LIT>']<EOL>self.modifier = self.modifiers[<NUM_LIT:0>]<EOL>self.components = [<EOL>c.category for c in state.comps if isinstance(c.get(), np.ndarray)<EOL>]<EOL>self.component = self.components[<NUM_LIT:0>]<EOL>self.state = state<EOL>self.cmap_abs = cmap_abs<EOL>self.cmap_diff = cmap_diff<EOL>self.vrange_img = vrange_img<EOL>self.vrange_diff = vrange_diff<EOL>self.state.set_tile(self.state.oshape)<EOL>z,y,x = [float(i) for i in self.state.data.shape]<EOL>w = float(x + z)<EOL>h = float(y + z)<EOL>orientation = orientation or ('<STR_LIT>' if w/h < <NUM_LIT> else '<STR_LIT>')<EOL>if orientation == '<STR_LIT>' or orientation == '<STR_LIT:h>':<EOL><INDENT>self.fig = make_clean_figure(figsize=(<NUM_LIT:2>*size*w/h, size),<EOL>remove_keybindings=True)<EOL>Sx, Sy, xoff, yoff = <NUM_LIT:0.5>, <NUM_LIT:1.0>, <NUM_LIT:0.5>, <NUM_LIT:0.0><EOL><DEDENT>elif orientation == '<STR_LIT>' or orientation == '<STR_LIT:v>':<EOL><INDENT>self.fig = make_clean_figure(figsize=(<NUM_LIT:2>*size*w/h, size),<EOL>remove_keybindings=True)<EOL>Sx, Sy, xoff, yoff = <NUM_LIT:1.0>, <NUM_LIT:0.5>, <NUM_LIT:0.0>, <NUM_LIT:0.5><EOL><DEDENT>else:<EOL><INDENT>raise AttributeError("<STR_LIT>")<EOL><DEDENT>self.gl = {}<EOL>self.gl['<STR_LIT>'] = self.fig.add_axes((Sx*<NUM_LIT:0.0>, yoff+Sy*(<NUM_LIT:1>-y/h), Sx*x/w,     Sy*y/h))<EOL>self.gl['<STR_LIT>'] = self.fig.add_axes((Sx*<NUM_LIT:0.0>, yoff+Sy*<NUM_LIT:0.0>,     Sx*x/w,     Sy*(<NUM_LIT:1>-y/h)))<EOL>self.gl['<STR_LIT>'] = self.fig.add_axes((Sx*x/w, yoff+Sy*(<NUM_LIT:1>-y/h), Sx*(<NUM_LIT:1>-x/w), Sy*y/h))<EOL>self.gl['<STR_LIT>'] = self.fig.add_axes((Sx*x/w, yoff+Sy*<NUM_LIT:0.0>,     Sx*(<NUM_LIT:1>-x/w), Sy*(<NUM_LIT:1>-y/h)))<EOL>self.gr = {}<EOL>self.gr['<STR_LIT>'] = self.fig.add_axes((xoff+Sx*<NUM_LIT:0.0>, Sy*(<NUM_LIT:1>-y/h), Sx*x/w,     Sy*y/h))<EOL>self.gr['<STR_LIT>'] = self.fig.add_axes((xoff+Sx*<NUM_LIT:0.0>, Sy*<NUM_LIT:0.0>,     Sx*x/w,     Sy*(<NUM_LIT:1>-y/h)))<EOL>self.gr['<STR_LIT>'] = self.fig.add_axes((xoff+Sx*x/w, Sy*(<NUM_LIT:1>-y/h), Sx*(<NUM_LIT:1>-x/w), Sy*y/h))<EOL>self.gr['<STR_LIT>'] = self.fig.add_axes((xoff+Sx*x/w, Sy*<NUM_LIT:0.0>,     Sx*(<NUM_LIT:1>-x/w), Sy*(<NUM_LIT:1>-y/h)))<EOL>self.slices = (np.array(self.state.data.shape)/<NUM_LIT:2>).astype('<STR_LIT:int>')<EOL>self._grab = None<EOL>self.set_field()<EOL>self.draw()<EOL>self.register_events()<EOL>

An interactive viewer for states for a model in 3D. Can work with
any 3D state with a set of components. This viewer relies heavily on
hotkeys. The various modes that can be accessed are by pressing
these keys:

    'Q' : switch between 'model', 'residual', and 'component' views
    'A' : add particle mode (click position to add)
    'R' : remove particle mode (click position to remove)
    'E' : optimize particle (click particle to optimize)
    'W' : switch to fourier views
    'V' : switch to view mode (click window to move view)
    'C' : If in 'component' views, cycles through components

Parameters:
-----------
state : `peri.states.State` object
    The state object to look at

size : float
    Relative window size, this is based on matplotlib.figure(figsize)
    and has some units which I don't understand.

cmap_abs : string
    Colormap to use for the one sided scales such as data and model

cmap_dff : string
    Colormap to use for difference images, such as residuals

orientation : one of ['h', 'v', 'horizontal', 'vertical']
    The orientation of the two views

vrange_img : float
    vmax for imshow for absolute images

vrange_diff : float
    vmax - vmin for imshow for difference images


def __init__(self, field, onesided=True, vmin=None, vmax=None, cmap=None,<EOL>dohist=False, fourier=False, tooltips=False, size=<NUM_LIT:8>):

self.vmin = vmin<EOL>self.vmax = vmax<EOL>self.field = field<EOL>self.onesided = onesided<EOL>self.dohist = dohist<EOL>self.fourier = fourier<EOL>if cmap is not None:<EOL><INDENT>self.cmap = cmap<EOL><DEDENT>else:<EOL><INDENT>self.cmap = '<STR_LIT>' if self.onesided else '<STR_LIT>'<EOL><DEDENT>z,y,x = [float(i) for i in self.field.shape]<EOL>w = float(x + z)<EOL>h = float(y + z)<EOL>self.fig = make_clean_figure(<EOL>figsize=(size * w/h, size), remove_tooltips=not tooltips,<EOL>remove_keybindings=True)<EOL>self.g = {}<EOL>self.g['<STR_LIT>'] = self.fig.add_axes((<NUM_LIT:0.0>, <NUM_LIT:1>-y/h, x/w,   y/h))<EOL>self.g['<STR_LIT>'] = self.fig.add_axes((<NUM_LIT:0.0>, <NUM_LIT:0.0>,   x/w,   <NUM_LIT:1>-y/h))<EOL>self.g['<STR_LIT>'] = self.fig.add_axes((x/w, <NUM_LIT:1>-y/h, <NUM_LIT:1>-x/w, y/h))<EOL>self.g['<STR_LIT>'] = self.fig.add_axes((x/w, <NUM_LIT:0.0>,   <NUM_LIT:1>-x/w, <NUM_LIT:1>-y/h))<EOL>self.slices = (np.array(self.field.shape)/<NUM_LIT:2>).astype('<STR_LIT:int>')<EOL>if self.fourier:<EOL><INDENT>self.field = np.fft.fftshift(np.fft.fftn(self.field))<EOL><DEDENT>self.draw()<EOL>self.register_events()<EOL>

Easy interactive viewing of 3D ndarray with view selection.

Navigate in 3D by clicking on the three panels which are slices
through the array at a given position.

Parameters
----------
field : np.ndarray
    The field to view
onesided : bool, optional
    Whether to use the default one-sided or two-sided colormap.
    Over-ridden by cmap. Default is True
vmin, vmax : numeric, optional
    The min, max colorbar range, as passed to the matplotlib
    colormap. Default is the (min, max) of the data.
cmap : {None, valid matplotlib colormap}, optional
    Use to directly a specific colormap, e.g. `'bone'`. If None
    selects `'bone' if onesided else 'RdBu'`. Default is None
dohist : bool, optional
    Set to True to include a histogram of `field` in an
    additional panel. Default is False
fourier : bool, optional
    Set to True to view the Fourier transform of field. Default
    is False
tooltips : bool, optional
    Whether to include the tooltips bar on the figure. Default
    is False
size : numeric, optional
    The rough figure size of the viewer; the actual size is re-
    scaled based on the field's size. Default is 8


def __init__(self, image, pos, viewrad=None, cmap='<STR_LIT>', part_col=<EOL>[<NUM_LIT:0.>, <NUM_LIT:1.>, <NUM_LIT:1.>, <NUM_LIT:1.>], **kwargs):

<EOL>self.image = image.copy()<EOL>self.pos = pos<EOL>if viewrad is None:<EOL><INDENT>self.viewrad = <NUM_LIT><EOL><DEDENT>else:<EOL><INDENT>self.viewrad = viewrad<EOL><DEDENT>self.mode = '<STR_LIT>'<EOL>super(OrthoPrefeature, self).__init__(image, cmap=cmap, **kwargs)<EOL>if self.vmin is None:<EOL><INDENT>self.vmin = image.min()<EOL><DEDENT>if self.vmax is None:<EOL><INDENT>self.vmax = image.max()<EOL><DEDENT>if type(self.cmap) == str:<EOL><INDENT>self._cmap = mpl.cm.get_cmap(self.cmap)<EOL><DEDENT>else:  <EOL><INDENT>self._cmap = self.cmap<EOL><DEDENT>self.particle_field = np.zeros(image.shape, dtype='<STR_LIT:float>')<EOL>self.part_col = part_col<EOL>self._draw_im()<EOL>self.update_particle_field(poses=None)<EOL>self.update_field()<EOL>self.draw()<EOL>

Interactive viewing of a 3D featured image, to examine the quality of
initial featuring.

There are 3 modes of the viewer, accessed by pressing these keys:
 * 'V' : switch to view mode (click window to move view)
 * 'A' : add particle mode (click position to add)
 * 'R' : remove particle mode (click position to remove)
The viewer starts in view mode.
The complete list of particle positions is stored in ``self.pos``

Parameters
----------
im : numpy.ndarray
    The image to check pre-featuring on.
pos : [N,3] numpy.ndarray
    The initial guess for the particle positions, in pixel units
viewrad : Float or None, optional.
    The width of the particles to plot. Default is 2.
cmap : String, optional
    A valid matplotlib colormap. Default is `'Greys_r'`.s
part_col : list-like, optional
    Color of the particles.... RGBA. Default is cyan.
**kwargs : All keyword args to OrthoViewer....


def _particle_func(self, coords, pos, wid):

dx, dy, dz = [c - p for c,p in zip(coords, pos)]<EOL>dr2 = dx*dx + dy*dy + dz*dz<EOL>return np.exp(-dr2/(<NUM_LIT:2>*wid*wid))<EOL>

Draws a gaussian, range is (0,1]. Coords = [3,n]


m = np.clip(self.particle_field, <NUM_LIT:0>, <NUM_LIT:1>)<EOL>part_color = np.zeros(self._image.shape)<EOL>for a in range(<NUM_LIT:4>): part_color[:,:,:,a] = self.part_col[a]<EOL>self.field = np.zeros(self._image.shape)<EOL>for a in range(<NUM_LIT:4>):<EOL><INDENT>self.field[:,:,:,a] = m*part_color[:,:,:,a] + (<NUM_LIT:1>-m) * self._image[:,:,:,a]<EOL><DEDENT>


<EOL>dp = self.pos - p<EOL>dist2 = (dp*dp).sum(axis=<NUM_LIT:1>)<EOL>ind = dist2.argmin()<EOL>rp = self.pos[ind].copy()<EOL>self.pos = np.delete(self.pos, ind, axis=<NUM_LIT:0>)<EOL>return rp<EOL>

removes the closest particle in self.pos to ``p``


at = AnchoredText(label, loc=<NUM_LIT:2>, prop=dict(size=size), frameon=True)<EOL>at.patch.set_boxstyle("<STR_LIT>")<EOL>axis.add_artist(at)<EOL>


pl.close('<STR_LIT:all>')<EOL>slicez = int(round(z.mean()))<EOL>slicex = s.image.shape[<NUM_LIT:2>]//<NUM_LIT:2><EOL>slicer1 = np.s_[slicez,s.pad:-s.pad,s.pad:-s.pad]<EOL>slicer2 = np.s_[s.pad:-s.pad,s.pad:-s.pad,slicex]<EOL>center = (slicez, s.image.shape[<NUM_LIT:1>]//<NUM_LIT:2>, slicex)<EOL>fig = pl.figure(figsize=(factor*<NUM_LIT>,factor*<NUM_LIT:10>))<EOL>gs1 = ImageGrid(fig, rect=[<NUM_LIT:0.0>, <NUM_LIT>, <NUM_LIT:1.0>, <NUM_LIT>], nrows_ncols=(<NUM_LIT:1>,<NUM_LIT:3>),<EOL>axes_pad=<NUM_LIT:0.1>)<EOL>ax_real = gs1[<NUM_LIT:0>]<EOL>ax_fake = gs1[<NUM_LIT:1>]<EOL>ax_diff = gs1[<NUM_LIT:2>]<EOL>diff = s.get_model_image() - s.image<EOL>ax_real.imshow(s.image[slicer1], cmap=pl.cm.bone_r)<EOL>ax_real.set_xticks([])<EOL>ax_real.set_yticks([])<EOL>ax_real.set_title("<STR_LIT>", fontsize=<NUM_LIT>)<EOL>ax_fake.imshow(s.get_model_image()[slicer1], cmap=pl.cm.bone_r)<EOL>ax_fake.set_xticks([])<EOL>ax_fake.set_yticks([])<EOL>ax_fake.set_title("<STR_LIT>", fontsize=<NUM_LIT>)<EOL>ax_diff.imshow(diff[slicer1], cmap=pl.cm.RdBu, vmin=-<NUM_LIT:0.1>, vmax=<NUM_LIT:0.1>)<EOL>ax_diff.set_xticks([])<EOL>ax_diff.set_yticks([])<EOL>ax_diff.set_title("<STR_LIT>", fontsize=<NUM_LIT>)<EOL>gs2 = ImageGrid(fig, rect=[<NUM_LIT:0.1>, <NUM_LIT:0.0>, <NUM_LIT>, <NUM_LIT>], nrows_ncols=(<NUM_LIT:3>,<NUM_LIT:2>),<EOL>axes_pad=<NUM_LIT:0.1>)<EOL>ax_plt1 = fig.add_subplot(gs2[<NUM_LIT:0>])<EOL>ax_plt2 = fig.add_subplot(gs2[<NUM_LIT:1>])<EOL>ax_ilm1 = fig.add_subplot(gs2[<NUM_LIT:2>])<EOL>ax_ilm2 = fig.add_subplot(gs2[<NUM_LIT:3>])<EOL>ax_psf1 = fig.add_subplot(gs2[<NUM_LIT:4>])<EOL>ax_psf2 = fig.add_subplot(gs2[<NUM_LIT:5>])<EOL>c = int(z.mean()), int(y.mean())+s.pad, int(x.mean())+s.pad<EOL>if s.image.shape[<NUM_LIT:0>] > <NUM_LIT:2>*s.image.shape[<NUM_LIT:1>]//<NUM_LIT:3>:<EOL><INDENT>w = s.image.shape[<NUM_LIT:2>] - <NUM_LIT:2>*s.pad<EOL>h = <NUM_LIT:2>*w//<NUM_LIT:3><EOL><DEDENT>else:<EOL><INDENT>h = s.image.shape[<NUM_LIT:0>] - <NUM_LIT:2>*s.pad<EOL>w = <NUM_LIT:3>*h//<NUM_LIT:2><EOL><DEDENT>w,h = w//<NUM_LIT:2>, h//<NUM_LIT:2><EOL>xyslice = np.s_[slicez, c[<NUM_LIT:1>]-h:c[<NUM_LIT:1>]+h, c[<NUM_LIT:2>]-w:c[<NUM_LIT:2>]+w]<EOL>yzslice = np.s_[c[<NUM_LIT:0>]-h:c[<NUM_LIT:0>]+h, c[<NUM_LIT:1>]-w:c[<NUM_LIT:1>]+w, slicex]<EOL>ax_plt1.imshow(<NUM_LIT:1>-s.obj.get_field()[xyslice], cmap=pl.cm.bone_r, vmin=<NUM_LIT:0>, vmax=<NUM_LIT:1>)<EOL>ax_plt1.set_xticks([])<EOL>ax_plt1.set_yticks([])<EOL>ax_plt1.set_ylabel("<STR_LIT>", fontsize=<NUM_LIT>)<EOL>ax_plt1.set_title("<STR_LIT>", fontsize=<NUM_LIT>)<EOL>ax_plt2.imshow(<NUM_LIT:1>-s._platonic_image()[yzslice], cmap=pl.cm.bone_r, vmin=<NUM_LIT:0>, vmax=<NUM_LIT:1>)<EOL>ax_plt2.set_xticks([])<EOL>ax_plt2.set_yticks([])<EOL>ax_plt2.set_title("<STR_LIT>", fontsize=<NUM_LIT>)<EOL>ax_ilm1.imshow(s.ilm.get_field()[xyslice], cmap=pl.cm.bone_r)<EOL>ax_ilm1.set_xticks([])<EOL>ax_ilm1.set_yticks([])<EOL>ax_ilm1.set_ylabel("<STR_LIT>", fontsize=<NUM_LIT>)<EOL>ax_ilm2.imshow(s.ilm.get_field()[yzslice], cmap=pl.cm.bone_r)<EOL>ax_ilm2.set_xticks([])<EOL>ax_ilm2.set_yticks([])<EOL>t = s.ilm.get_field().copy()<EOL>t *= <NUM_LIT:0><EOL>t[c] = <NUM_LIT:1><EOL>s.psf.set_tile(util.Tile(t.shape))<EOL>psf = (s.psf.execute(t)+<NUM_LIT>)**<NUM_LIT:0.1><EOL>ax_psf1.imshow(psf[xyslice], cmap=pl.cm.bone)<EOL>ax_psf1.set_xticks([])<EOL>ax_psf1.set_yticks([])<EOL>ax_psf1.set_ylabel("<STR_LIT>", fontsize=<NUM_LIT>)<EOL>ax_psf2.imshow(psf[yzslice], cmap=pl.cm.bone)<EOL>ax_psf2.set_xticks([])<EOL>ax_psf2.set_yticks([])<EOL>ax_zoom = fig.add_axes([<NUM_LIT>, <NUM_LIT>, <NUM_LIT>, <NUM_LIT>])<EOL>im = s.image[slicer1]<EOL>sh = np.array(im.shape)<EOL>cx = x.mean()<EOL>cy = y.mean()<EOL>extent = [<NUM_LIT:0>,sh[<NUM_LIT:0>],<NUM_LIT:0>,sh[<NUM_LIT:1>]]<EOL>ax_zoom.set_xticks([])<EOL>ax_zoom.set_yticks([])<EOL>ax_zoom.imshow(im, extent=extent, cmap=pl.cm.bone_r)<EOL>ax_zoom.set_xlim(cx-<NUM_LIT:12>, cx+<NUM_LIT:12>)<EOL>ax_zoom.set_ylim(cy-<NUM_LIT:12>, cy+<NUM_LIT:12>)<EOL>ax_zoom.set_title("<STR_LIT>", fontsize=<NUM_LIT>)<EOL>ax_zoom.hexbin(x,y, gridsize=<NUM_LIT:32>, mincnt=<NUM_LIT:0>, cmap=pl.cm.hot)<EOL>zoom1 = zoomed_inset_axes(ax_zoom, <NUM_LIT:30>, loc=<NUM_LIT:3>)<EOL>zoom1.imshow(im, extent=extent, cmap=pl.cm.bone_r)<EOL>zoom1.set_xlim(cx-<NUM_LIT:1.0>/<NUM_LIT:6>, cx+<NUM_LIT:1.0>/<NUM_LIT:6>)<EOL>zoom1.set_ylim(cy-<NUM_LIT:1.0>/<NUM_LIT:6>, cy+<NUM_LIT:1.0>/<NUM_LIT:6>)<EOL>zoom1.hexbin(x,y,gridsize=<NUM_LIT:32>, mincnt=<NUM_LIT:5>, cmap=pl.cm.hot)<EOL>zoom1.set_xticks([])<EOL>zoom1.set_yticks([])<EOL>zoom1.hlines(cy-<NUM_LIT:1.0>/<NUM_LIT:6> + <NUM_LIT:1.0>/<NUM_LIT:32>, cx-<NUM_LIT:1.0>/<NUM_LIT:6>+<NUM_LIT>, cx-<NUM_LIT:1.0>/<NUM_LIT:6>+<NUM_LIT>+<NUM_LIT>, lw=<NUM_LIT:3>)<EOL>zoom1.text(cx-<NUM_LIT:1.0>/<NUM_LIT:6> + <NUM_LIT:1.0>/<NUM_LIT>, cy-<NUM_LIT:1.0>/<NUM_LIT:6>+<NUM_LIT>, '<STR_LIT>')<EOL>mark_inset(ax_zoom, zoom1, loc1=<NUM_LIT:2>, loc2=<NUM_LIT:4>, fc="<STR_LIT:none>", ec="<STR_LIT>")<EOL>

Samples x,y,z,r are created by:
b = s.blocks_particle(#)
h = runner.sample_state(s, b, stepout=0.05, N=2000, doprint=True)
z,y,x,r = h.get_histogram().T


def examine_unexplained_noise(state, bins=<NUM_LIT:1000>, xlim=(-<NUM_LIT:10>,<NUM_LIT:10>)):

r = state.residuals<EOL>q = np.fft.fftn(r)<EOL>calc_sig = lambda x: np.sqrt(np.dot(x,x) / x.size)<EOL>rh, xr = np.histogram(r.ravel() / calc_sig(r.ravel()), bins=bins,<EOL>density=True)<EOL>bigq = np.append(q.real.ravel(), q.imag.ravel())<EOL>qh, xq = np.histogram(bigq / calc_sig(q.real.ravel()), bins=bins,<EOL>density=True)<EOL>xr = <NUM_LIT:0.5>*(xr[<NUM_LIT:1>:] + xr[:-<NUM_LIT:1>])<EOL>xq = <NUM_LIT:0.5>*(xq[<NUM_LIT:1>:] + xq[:-<NUM_LIT:1>])<EOL>gauss = lambda t : np.exp(-t*t*<NUM_LIT:0.5>) / np.sqrt(<NUM_LIT:2>*np.pi)<EOL>plt.figure(figsize=[<NUM_LIT:16>,<NUM_LIT:8>])<EOL>axes = []<EOL>for a, (x, r, lbl) in enumerate([[xr, rh, '<STR_LIT>'], [xq, qh, '<STR_LIT>']]):<EOL><INDENT>ax = plt.subplot(<NUM_LIT:1>,<NUM_LIT:2>,a+<NUM_LIT:1>)<EOL>ax.semilogy(x, r, label='<STR_LIT>')<EOL>ax.plot(x, gauss(x), label='<STR_LIT>', scalex=False, scaley=False)<EOL>ax.set_xlabel('<STR_LIT>')<EOL>ax.set_ylabel('<STR_LIT>')<EOL>ax.legend(loc='<STR_LIT>')<EOL>ax.set_title('<STR_LIT>'.format(lbl))<EOL>ax.set_xlim(xlim)<EOL>axes.append(ax)<EOL><DEDENT>return axes<EOL>

Compares a state's residuals in real and Fourier space with a Gaussian.

Point out that Fourier space should always be Gaussian and white

Parameters
----------
    state : `peri.states.State`
        The state to examine.
    bins : int or sequence of scalars or str, optional
        The number of bins in the histogram, as passed to numpy.histogram
        Default is 1000
    xlim : 2-element tuple, optional
        The range, in sigma, of the x-axis on the plot. Default (-10,10).

Returns
-------
    list
        The axes handles for the real and Fourier space subplots.


def compare_data_model_residuals(s, tile, data_vmin='<STR_LIT>', data_vmax='<STR_LIT>',<EOL>res_vmin=-<NUM_LIT:0.1>, res_vmax=<NUM_LIT:0.1>, edgepts='<STR_LIT>', do_imshow=True,<EOL>data_cmap=plt.cm.bone, res_cmap=plt.cm.RdBu):

<EOL>residuals = s.residuals[tile.slicer].squeeze()<EOL>data = s.data[tile.slicer].squeeze()<EOL>model = s.model[tile.slicer].squeeze()<EOL>if data.ndim != <NUM_LIT:2>:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>im = np.zeros([data.shape[<NUM_LIT:0>], data.shape[<NUM_LIT:1>], <NUM_LIT:4>])<EOL>if data_vmin == '<STR_LIT>':<EOL><INDENT>data_vmin = <NUM_LIT:0.5>*(data.min() + model.min())<EOL><DEDENT>if data_vmax == '<STR_LIT>':<EOL><INDENT>data_vmax = <NUM_LIT:0.5>*(data.max() + model.max())<EOL><DEDENT>upper_mask, center_mask, lower_mask = trisect_image(im.shape, edgepts)<EOL>gm = data_cmap(center_data(model, data_vmin, data_vmax))<EOL>dt = data_cmap(center_data(data, data_vmin, data_vmax))<EOL>rs = res_cmap(center_data(residuals, res_vmin, res_vmax))<EOL>for a in range(<NUM_LIT:4>):<EOL><INDENT>im[:,:,a][upper_mask] = rs[:,:,a][upper_mask]<EOL>im[:,:,a][center_mask] = gm[:,:,a][center_mask]<EOL>im[:,:,a][lower_mask] = dt[:,:,a][lower_mask]<EOL><DEDENT>if do_imshow:<EOL><INDENT>return plt.imshow(im)<EOL><DEDENT>else:<EOL><INDENT>return im<EOL><DEDENT>

Compare the data, model, and residuals of a state.

Makes an image of any 2D slice of a state that compares the data,
model, and residuals. The upper left portion of the image is the raw
data, the central portion the model, and the lower right portion the
image. Either plots the image using plt.imshow() or returns a
np.ndarray of the image pixels for later use.

Parameters
----------
    st : peri.ImageState object
        The state to plot.
    tile : peri.util.Tile object
        The slice of the image to plot. Can be any xy, xz, or yz
        projection, but it must return a valid 2D slice (the slice is
        squeezed internally).

    data_vmin : {Float, `calc`}, optional
        vmin for the imshow for the data and generative model (shared).
        Default is 'calc' = 0.5(data.min() + model.min())
    data_vmax : {Float, `calc`}, optional
        vmax for the imshow for the data and generative model (shared).
        Default is 'calc' = 0.5(data.max() + model.max())
    res_vmin : Float, optional
        vmin for the imshow for the residuals. Default is -0.1
        Default is 'calc' = 0.5(data.min() + model.min())
    res_vmax : Float, optional
        vmax for the imshow for the residuals. Default is +0.1
    edgepts : {Nested list-like, Float, 'calc'}, optional.
        The vertices of the triangles which determine the splitting of
        the image. The vertices are at (image corner, (edge, y), and
        (x,edge), where edge is the appropriate edge of the image.
            edgepts[0] : (x,y) points for the upper edge
            edgepts[1] : (x,y) points for the lower edge
        where `x` is the coordinate along the image's 0th axis and `y`
        along the images 1st axis. Default is 'calc,' which calculates
        edge points by splitting the image into 3 regions of equal
        area. If edgepts is a float scalar, calculates the edge points
        based on a constant fraction of distance from the edge.
    do_imshow : Bool
        If True, imshow's and returns the returned handle.
        If False, returns the array as a [M,N,4] array.
    data_cmap : matplotlib colormap instance
        The colormap to use for the data and model.
    res_cmap : matplotlib colormap instance
        The colormap to use for the residuals.

Returns
-------
    image : {matplotlib.pyplot.AxesImage, numpy.ndarray}
        If `do_imshow` == True, the returned handle from imshow.
        If `do_imshow` == False, an [M,N,4] np.ndarray of the image
        pixels.


im_x, im_y = np.meshgrid(np.arange(imshape[<NUM_LIT:0>]), np.arange(imshape[<NUM_LIT:1>]),<EOL>indexing='<STR_LIT>')<EOL>if np.size(edgepts) == <NUM_LIT:1>:<EOL><INDENT>f = np.sqrt(<NUM_LIT>/<NUM_LIT>) if edgepts == '<STR_LIT>' else edgepts<EOL>lower_edge = (imshape[<NUM_LIT:0>] * (<NUM_LIT:1>-f),  imshape[<NUM_LIT:1>] * f)<EOL>upper_edge = (imshape[<NUM_LIT:0>] * f,      imshape[<NUM_LIT:1>] * (<NUM_LIT:1>-f))<EOL><DEDENT>else:<EOL><INDENT>upper_edge, lower_edge = edgepts<EOL><DEDENT>lower_slope = lower_edge[<NUM_LIT:1>] / max(float(imshape[<NUM_LIT:0>] - lower_edge[<NUM_LIT:0>]), <NUM_LIT>)<EOL>upper_slope = (imshape[<NUM_LIT:1>] - upper_edge[<NUM_LIT:1>]) / float(upper_edge[<NUM_LIT:0>])<EOL>lower_intercept = -lower_slope * lower_edge[<NUM_LIT:0>]<EOL>upper_intercept = upper_edge[<NUM_LIT:1>]<EOL>lower_mask = im_y < (im_x * lower_slope + lower_intercept)<EOL>upper_mask = im_y > (im_x * upper_slope + upper_intercept)<EOL>center_mask= -(lower_mask | upper_mask)<EOL>return upper_mask, center_mask, lower_mask<EOL>

Returns 3 masks that trisect an image into 3 triangular portions.

Parameters
----------
    imshape : 2-element list-like of ints
        The shape of the image. Elements after the first 2 are ignored.

    edgepts : Nested list-like, float, or `calc`, optional.
        The vertices of the triangles which determine the splitting of
        the image. The vertices are at (image corner, (edge, y), and
        (x,edge), where edge is the appropriate edge of the image.
            edgepts[0] : (x,y) points for the upper edge
            edgepts[1] : (x,y) points for the lower edge
        where `x` is the coordinate along the image's 0th axis and `y`
        along the images 1st axis. Default is 'calc,' which calculates
        edge points by splitting the image into 3 regions of equal
        area. If edgepts is a float scalar, calculates the edge points
        based on a constant fraction of distance from the edge.

Returns
-------
    upper_mask : numpy.ndarray
        Boolean array; True in the image's upper  region.
    center_mask : numpy.ndarray
        Boolean array; True in the image's center region.
    lower_mask : numpy.ndarray
        Boolean array; True in the image's lower  region.


ans = data - vmin<EOL>ans /= (vmax - vmin)<EOL>return np.clip(ans, <NUM_LIT:0>, <NUM_LIT:1>)<EOL>

Clips data on [vmin, vmax]; then rescales to [0,1]


def sim_crb_diff(std0, std1, N=<NUM_LIT>):

a = std0*np.random.randn(N, len(std0))<EOL>b = std1*np.random.randn(N, len(std1))<EOL>return a - b<EOL>

each element of std0 should correspond with the element of std1


def crb_compare(state0, samples0, state1, samples1, crb0=None, crb1=None,<EOL>zlayer=None, xlayer=None):

s0 = state0<EOL>s1 = state1<EOL>h0 = np.array(samples0)<EOL>h1 = np.array(samples1)<EOL>slicez = zlayer or s0.image.shape[<NUM_LIT:0>]//<NUM_LIT:2><EOL>slicex = xlayer or s0.image.shape[<NUM_LIT:2>]//<NUM_LIT:2><EOL>slicer1 = np.s_[slicez,s0.pad:-s0.pad,s0.pad:-s0.pad]<EOL>slicer2 = np.s_[s0.pad:-s0.pad,s0.pad:-s0.pad,slicex]<EOL>center = (slicez, s0.image.shape[<NUM_LIT:1>]//<NUM_LIT:2>, slicex)<EOL>mu0 = h0.mean(axis=<NUM_LIT:0>)<EOL>mu1 = h1.mean(axis=<NUM_LIT:0>)<EOL>std0 = h0.std(axis=<NUM_LIT:0>)<EOL>std1 = h1.std(axis=<NUM_LIT:0>)<EOL>mask0 = (s0.state[s0.b_typ]==<NUM_LIT:1.>) & (<EOL>analyze.trim_box(s0, mu0[s0.b_pos].reshape(-<NUM_LIT:1>,<NUM_LIT:3>)))<EOL>mask1 = (s1.state[s1.b_typ]==<NUM_LIT:1.>) & (<EOL>analyze.trim_box(s1, mu1[s1.b_pos].reshape(-<NUM_LIT:1>,<NUM_LIT:3>)))<EOL>active0 = np.arange(s0.N)[mask0]<EOL>active1 = np.arange(s1.N)[mask1]<EOL>pos0 = mu0[s0.b_pos].reshape(-<NUM_LIT:1>,<NUM_LIT:3>)[active0]<EOL>pos1 = mu1[s1.b_pos].reshape(-<NUM_LIT:1>,<NUM_LIT:3>)[active1]<EOL>rad0 = mu0[s0.b_rad][active0]<EOL>rad1 = mu1[s1.b_rad][active1]<EOL>link = analyze.nearest(pos0, pos1)<EOL>dpos = pos0 - pos1[link]<EOL>drad = rad0 - rad1[link]<EOL>drift = dpos.mean(axis=<NUM_LIT:0>)<EOL>log.info('<STR_LIT>'.format(drift))<EOL>dpos -= drift<EOL>fig = pl.figure(figsize=(<NUM_LIT>,<NUM_LIT:10>))<EOL>gs0 = ImageGrid(fig, rect=[<NUM_LIT>, <NUM_LIT>, <NUM_LIT>, <NUM_LIT>], nrows_ncols=(<NUM_LIT:2>,<NUM_LIT:3>), axes_pad=<NUM_LIT:0.1>)<EOL>lbl(gs0[<NUM_LIT:0>], '<STR_LIT:A>')<EOL>for i,slicer in enumerate([slicer1, slicer2]):<EOL><INDENT>ax_real = gs0[<NUM_LIT:3>*i+<NUM_LIT:0>]<EOL>ax_fake = gs0[<NUM_LIT:3>*i+<NUM_LIT:1>]<EOL>ax_diff = gs0[<NUM_LIT:3>*i+<NUM_LIT:2>]<EOL>diff0 = s0.get_model_image() - s0.image<EOL>diff1 = s1.get_model_image() - s1.image<EOL>a = (s0.image - s1.image)<EOL>b = (s0.get_model_image() - s1.get_model_image())<EOL>c = (diff0 - diff1)<EOL>ptp = <NUM_LIT>*max([np.abs(a).max(), np.abs(b).max(), np.abs(c).max()])<EOL>cmap = pl.cm.RdBu_r<EOL>ax_real.imshow(a[slicer], cmap=cmap, vmin=-ptp, vmax=ptp)<EOL>ax_real.set_xticks([])<EOL>ax_real.set_yticks([])<EOL>ax_fake.imshow(b[slicer], cmap=cmap, vmin=-ptp, vmax=ptp)<EOL>ax_fake.set_xticks([])<EOL>ax_fake.set_yticks([])<EOL>ax_diff.imshow(c[slicer], cmap=cmap, vmin=-ptp, vmax=ptp)<EOL>ax_diff.set_xticks([])<EOL>ax_diff.set_yticks([])<EOL>if i == <NUM_LIT:0>:<EOL><INDENT>ax_real.set_title(r"<STR_LIT>", fontsize=<NUM_LIT>)<EOL>ax_fake.set_title(r"<STR_LIT>", fontsize=<NUM_LIT>)<EOL>ax_diff.set_title(r"<STR_LIT>", fontsize=<NUM_LIT>)<EOL>ax_real.set_ylabel('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>ax_real.set_ylabel('<STR_LIT>')<EOL><DEDENT><DEDENT>gs1 = GridSpec(<NUM_LIT:1>,<NUM_LIT:3>, left=<NUM_LIT>, bottom=<NUM_LIT>, right=<NUM_LIT>, top=<NUM_LIT>,<EOL>wspace=<NUM_LIT>, hspace=<NUM_LIT>)<EOL>spos0 = std0[s0.b_pos].reshape(-<NUM_LIT:1>,<NUM_LIT:3>)[active0]<EOL>spos1 = std1[s1.b_pos].reshape(-<NUM_LIT:1>,<NUM_LIT:3>)[active1]<EOL>srad0 = std0[s0.b_rad][active0]<EOL>srad1 = std1[s1.b_rad][active1]<EOL>def hist(ax, vals, bins, *args, **kwargs):<EOL><INDENT>y,x = np.histogram(vals, bins=bins)<EOL>x = (x[<NUM_LIT:1>:] + x[:-<NUM_LIT:1>])/<NUM_LIT:2><EOL>y /= len(vals)<EOL>ax.plot(x,y, *args, **kwargs)<EOL><DEDENT>def pp(ind, tarr, tsim, tcrb, var='<STR_LIT:x>'):<EOL><INDENT>bins = <NUM_LIT:10>**np.linspace(-<NUM_LIT:3>, <NUM_LIT:0.0>, <NUM_LIT:30>)<EOL>bin2 = <NUM_LIT:10>**np.linspace(-<NUM_LIT:3>, <NUM_LIT:0.0>, <NUM_LIT:100>)<EOL>bins = np.linspace(<NUM_LIT:0.0>, <NUM_LIT>, <NUM_LIT:30>)<EOL>bin2 = np.linspace(<NUM_LIT:0.0>, <NUM_LIT>, <NUM_LIT:100>)<EOL>xlim = (<NUM_LIT:0.0>, <NUM_LIT>)<EOL>ylim = (<NUM_LIT>, <NUM_LIT:30>)<EOL>ticks = ticker.FuncFormatter(lambda x, pos: '<STR_LIT>'.format(np.log10(x)))<EOL>scaler = lambda x: x <EOL>ax_crb = pl.subplot(gs1[<NUM_LIT:0>,ind])<EOL>ax_crb.hist(scaler(np.abs(tarr)), bins=bins,<EOL>normed=True, alpha=<NUM_LIT>, histtype='<STR_LIT>', lw=<NUM_LIT:1>)<EOL>ax_crb.hist(scaler(np.abs(tcrb)).ravel(), bins=bin2,<EOL>normed=True, alpha=<NUM_LIT:1.0>, histtype='<STR_LIT>', ls='<STR_LIT>', lw=<NUM_LIT>, color='<STR_LIT:k>')<EOL>ax_crb.hist(scaler(np.abs(tsim).ravel()), bins=bin2,<EOL>normed=True, alpha=<NUM_LIT:1.0>, histtype='<STR_LIT>', lw=<NUM_LIT:3>)<EOL>ax_crb.set_xlabel(r"<STR_LIT>" % (var,var), fontsize=<NUM_LIT>)<EOL>ax_crb.set_xlim(xlim)<EOL>ax_crb.grid(b=False, which='<STR_LIT>', axis='<STR_LIT>')<EOL>if ind == <NUM_LIT:0>:<EOL><INDENT>lbl(ax_crb, '<STR_LIT:B>')<EOL>ax_crb.set_ylabel(r"<STR_LIT>")<EOL><DEDENT>else:<EOL><INDENT>ax_crb.set_yticks([])<EOL><DEDENT>ax_crb.locator_params(axis='<STR_LIT:x>', nbins=<NUM_LIT:3>)<EOL><DEDENT>f,g = <NUM_LIT>, <NUM_LIT><EOL>sim = f*sim_crb_diff(spos0[:,<NUM_LIT:1>], spos1[:,<NUM_LIT:1>][link])<EOL>crb = g*sim_crb_diff(crb0[<NUM_LIT:0>][:,<NUM_LIT:1>][active0], crb1[<NUM_LIT:0>][:,<NUM_LIT:1>][active1][link])<EOL>pp(<NUM_LIT:0>, dpos[:,<NUM_LIT:1>], sim, crb, '<STR_LIT:x>')<EOL>sim = f*sim_crb_diff(spos0[:,<NUM_LIT:0>], spos1[:,<NUM_LIT:0>][link])<EOL>crb = g*sim_crb_diff(crb0[<NUM_LIT:0>][:,<NUM_LIT:0>][active0], crb1[<NUM_LIT:0>][:,<NUM_LIT:0>][active1][link])<EOL>pp(<NUM_LIT:1>, dpos[:,<NUM_LIT:0>], sim, crb, '<STR_LIT:z>')<EOL>sim = f*sim_crb_diff(srad0, srad1[link])<EOL>crb = g*sim_crb_diff(crb0[<NUM_LIT:1>][active0], crb1[<NUM_LIT:1>][active1][link])<EOL>pp(<NUM_LIT:2>, drad, sim, crb, '<STR_LIT:a>')<EOL>gs2 = GridSpec(<NUM_LIT:2>,<NUM_LIT:2>, left=<NUM_LIT>, bottom=<NUM_LIT>, right=<NUM_LIT>, top=<NUM_LIT>,<EOL>wspace=<NUM_LIT>, hspace=<NUM_LIT>)<EOL>ax_hist = pl.subplot(gs2[<NUM_LIT:0>,<NUM_LIT:0>])<EOL>ax_hist.hist(std0[s0.b_pos], bins=np.logspace(-<NUM_LIT>, <NUM_LIT:0>, <NUM_LIT:50>), alpha=<NUM_LIT>, label='<STR_LIT>', histtype='<STR_LIT>')<EOL>ax_hist.hist(std0[s0.b_rad], bins=np.logspace(-<NUM_LIT>, <NUM_LIT:0>, <NUM_LIT:50>), alpha=<NUM_LIT>, label='<STR_LIT>', histtype='<STR_LIT>')<EOL>ax_hist.set_xlim((<NUM_LIT:10>**-<NUM_LIT>, <NUM_LIT:1>))<EOL>ax_hist.semilogx()<EOL>ax_hist.set_xlabel(r"<STR_LIT>")<EOL>ax_hist.set_ylabel(r"<STR_LIT>")<EOL>ax_hist.legend(loc='<STR_LIT>')<EOL>lbl(ax_hist, '<STR_LIT:C>')<EOL>imdiff = ((s0.get_model_image() - s0.image)/s0._sigma_field)[s0.image_mask==<NUM_LIT:1.>].ravel()<EOL>mu = imdiff.mean()<EOL>x = np.linspace(-<NUM_LIT:5>,<NUM_LIT:5>,<NUM_LIT>)<EOL>ax_diff = pl.subplot(gs2[<NUM_LIT:0>,<NUM_LIT:1>])<EOL>ax_diff.plot(x, <NUM_LIT:1.0>/np.sqrt(<NUM_LIT:2>*np.pi) * np.exp(-(x-mu)**<NUM_LIT:2> / <NUM_LIT:2>), '<STR_LIT:->', alpha=<NUM_LIT>, color='<STR_LIT:k>', lw=<NUM_LIT:2>)<EOL>ax_diff.hist(imdiff, bins=<NUM_LIT:1000>, histtype='<STR_LIT>', alpha=<NUM_LIT>, normed=True)<EOL>ax_diff.semilogy()<EOL>ax_diff.set_ylabel(r"<STR_LIT>")<EOL>ax_diff.set_xlabel(r"<STR_LIT>")<EOL>ax_diff.locator_params(axis='<STR_LIT:x>', nbins=<NUM_LIT:5>)<EOL>ax_diff.grid(b=False, which='<STR_LIT>', axis='<STR_LIT:y>')<EOL>ax_diff.set_xlim(-<NUM_LIT:5>, <NUM_LIT:5>)<EOL>ax_diff.set_ylim(<NUM_LIT>, <NUM_LIT>)<EOL>lbl(ax_diff, '<STR_LIT:D>')<EOL>pos = mu0[s0.b_pos].reshape(-<NUM_LIT:1>,<NUM_LIT:3>)<EOL>rad = mu0[s0.b_rad]<EOL>mask = analyze.trim_box(s0, pos)<EOL>pos = pos[mask]<EOL>rad = rad[mask]<EOL>gx, gy = analyze.gofr(pos, rad, mu0[s0.b_zscale][<NUM_LIT:0>], resolution=<NUM_LIT>,mask_start=<NUM_LIT:0.5>)<EOL>mask = gx < <NUM_LIT:5><EOL>gx = gx[mask]<EOL>gy = gy[mask]<EOL>ax_gofr = pl.subplot(gs2[<NUM_LIT:1>,<NUM_LIT:0>])<EOL>ax_gofr.plot(gx, gy, '<STR_LIT:->', lw=<NUM_LIT:1>)<EOL>ax_gofr.set_xlabel(r"<STR_LIT>")<EOL>ax_gofr.set_ylabel(r"<STR_LIT>")<EOL>ax_gofr.locator_params(axis='<STR_LIT>', nbins=<NUM_LIT:5>)<EOL>lbl(ax_gofr, '<STR_LIT:E>')<EOL>gx, gy = analyze.gofr(pos, rad, mu0[s0.b_zscale][<NUM_LIT:0>], method='<STR_LIT>')<EOL>mask = gx < <NUM_LIT:5><EOL>gx = gx[mask]<EOL>gy = gy[mask]<EOL>gy[gy <= <NUM_LIT:0.>] = gy[gy><NUM_LIT:0>].min()<EOL>ax_gofrs = pl.subplot(gs2[<NUM_LIT:1>,<NUM_LIT:1>])<EOL>ax_gofrs.plot(gx, gy, '<STR_LIT:->', lw=<NUM_LIT:1>)<EOL>ax_gofrs.set_xlabel(r"<STR_LIT>")<EOL>ax_gofrs.set_ylabel(r"<STR_LIT>")<EOL>ax_gofrs.locator_params(axis='<STR_LIT>', nbins=<NUM_LIT:5>)<EOL>ax_gofrs.grid(b=False, which='<STR_LIT>', axis='<STR_LIT:y>')<EOL>lbl(ax_gofrs, '<STR_LIT:F>')<EOL>ylim = ax_gofrs.get_ylim()<EOL>ax_gofrs.set_ylim(gy.min(), ylim[<NUM_LIT:1>])<EOL>

To run, do:

s,h = pickle...
s1,h1 = pickle...
    i.e. /media/scratch/bamf/vacancy/vacancy_zoom-1.tif_t002.tif-featured-v2.pkl
    i.e. /media/scratch/bamf/frozen-particles/0.tif-featured-full.pkl
crb0 = diag_crb_particles(s); crb1 = diag_crb_particles(s1)
crb_compare(s,h[-25:],s1,h1[-25:], crb0, crb1)


def twoslice(field, center=None, size=<NUM_LIT>, cmap='<STR_LIT>', vmin=<NUM_LIT:0>, vmax=<NUM_LIT:1>,<EOL>orientation='<STR_LIT>', figpad=<NUM_LIT>, off=<NUM_LIT>):

center = center or [i//<NUM_LIT:2> for i in field.shape]<EOL>slices = []<EOL>for i,c in enumerate(center):<EOL><INDENT>blank = [np.s_[:]]*len(center)<EOL>blank[i] = c<EOL>slices.append(tuple(blank))<EOL><DEDENT>z,y,x = [float(i) for i in field.shape]<EOL>w = float(x + z)<EOL>h = float(y + z)<EOL>def show(field, ax, slicer, transpose=False):<EOL><INDENT>tmp = field[slicer] if not transpose else field[slicer].T<EOL>ax.imshow(<EOL>tmp, cmap=cmap, interpolation='<STR_LIT>',<EOL>vmin=vmin, vmax=vmax<EOL>)<EOL>ax.set_xticks([])<EOL>ax.set_yticks([])<EOL>ax.grid('<STR_LIT>')<EOL><DEDENT>if orientation.startswith('<STR_LIT:v>'):<EOL><INDENT>log.info('<STR_LIT>'.format(x, y, z, w, h, x/h))<EOL>r = x/h<EOL>q = y/h<EOL>f = <NUM_LIT:1> / (<NUM_LIT:1> + <NUM_LIT:3>*off)<EOL>fig = pl.figure(figsize=(size*r, size*f))<EOL>ax1 = fig.add_axes((off, f*(<NUM_LIT:1>-q)+<NUM_LIT:2>*off, f, f*q))<EOL>ax2 = fig.add_axes((off, off,           f, f*(<NUM_LIT:1>-q)))<EOL>show(field, ax1, slices[<NUM_LIT:0>])<EOL>show(field, ax2, slices[<NUM_LIT:1>])<EOL><DEDENT>else:<EOL><INDENT>r = y/w<EOL>q = x/w<EOL>f = <NUM_LIT:1> / (<NUM_LIT:1> + <NUM_LIT:3>*off)<EOL>fig = pl.figure(figsize=(size*f, size*r))<EOL>ax1 = fig.add_axes((off,    off,   f*q, f))<EOL>ax2 = fig.add_axes((<NUM_LIT:2>*off+f*q, off, f*(<NUM_LIT:1>-q), f))<EOL>show(field, ax1, slices[<NUM_LIT:0>])<EOL>show(field, ax2, slices[<NUM_LIT:2>], transpose=True)<EOL><DEDENT>return fig, ax1, ax2<EOL>

Plot two parts of the ortho view, the two sections given by ``orientation``.


def circles(st, layer, axis, ax=None, talpha=<NUM_LIT:1.0>, cedge='<STR_LIT>', cface='<STR_LIT>'):

pos = st.obj_get_positions()<EOL>rad = st.obj_get_radii()<EOL>shape = st.ishape.shape.tolist()<EOL>shape.pop(axis) <EOL>if ax is None:<EOL><INDENT>fig = plt.figure()<EOL>axisbg = '<STR_LIT>' if cface == '<STR_LIT>' else '<STR_LIT>'<EOL>sx, sy = ((<NUM_LIT:1>,shape[<NUM_LIT:1>]/float(shape[<NUM_LIT:0>])) if shape[<NUM_LIT:0>] > shape[<NUM_LIT:1>] else<EOL>(shape[<NUM_LIT:0>]/float(shape[<NUM_LIT:1>]), <NUM_LIT:1>))<EOL>ax = fig.add_axes((<NUM_LIT:0>,<NUM_LIT:0>, sx, sy), axisbg=axisbg)<EOL><DEDENT>particles = np.arange(len(pos))[np.abs(pos[:,axis] - layer) < rad]<EOL>scale = <NUM_LIT:1.0> <EOL>for i in particles:<EOL><INDENT>p = pos[i].copy()<EOL>r = <NUM_LIT:2>*np.sqrt(rad[i]**<NUM_LIT:2> - (p[axis] - layer)**<NUM_LIT:2>)<EOL>if axis==<NUM_LIT:0>:<EOL><INDENT>ix = <NUM_LIT:1>; iy = <NUM_LIT:2><EOL><DEDENT>elif axis == <NUM_LIT:1>:<EOL><INDENT>ix = <NUM_LIT:0>; iy = <NUM_LIT:2><EOL><DEDENT>elif axis==<NUM_LIT:2>:<EOL><INDENT>ix = <NUM_LIT:0>; iy = <NUM_LIT:1><EOL><DEDENT>c = Circle((p[ix]/scale, p[iy]/scale), radius=r/<NUM_LIT:2>/scale, fc=cface,<EOL>ec=cedge, alpha=talpha)<EOL>ax.add_patch(c)<EOL><DEDENT>plt.axis('<STR_LIT>') <EOL>return ax<EOL>

Plots a set of circles corresponding to a slice through the platonic
structure. Copied from twoslice_overlay with comments, standaloneness.

Inputs
------
    pos : array of particle positions; [N,3]
    rad : array of particle radii; [N]
    ax : plt.axis instance
    layer : Which layer of the slice to use.
    axis : The slice of the image, 0, 1, or 2.
    cedge : edge color
    cface : face color
    talpha : Alpha of the thing


def normalize(im, invert=False, scale=None, dtype=np.float64):

if dtype not in {np.float16, np.float32, np.float64}:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>out = im.astype('<STR_LIT:float>').copy()<EOL>scale = scale or (<NUM_LIT:0.0>, <NUM_LIT>)<EOL>l, u = (float(i) for i in scale)<EOL>out = (out - l) / (u - l)<EOL>if invert:<EOL><INDENT>out = -out + (out.max() + out.min())<EOL><DEDENT>return out.astype(dtype)<EOL>

Normalize a field to a (min, max) exposure range, default is (0, 255).
(min, max) exposure values. Invert the image if requested.


rint = np.ceil(radius).astype('<STR_LIT:int>')<EOL>t = np.arange(-rint, rint+<NUM_LIT:1>, <NUM_LIT:1>)<EOL>x,y,z = np.meshgrid(t, t, t, indexing='<STR_LIT>')<EOL>r = np.sqrt(x*x + y*y + z*z)<EOL>sphere = r < radius<EOL>return sphere<EOL>

Generates a centered boolean mask of a 3D sphere


def local_max_featuring(im, radius=<NUM_LIT>, noise_size=<NUM_LIT:1.>, bkg_size=None,<EOL>minmass=<NUM_LIT:1.>, trim_edge=False):

if radius <= <NUM_LIT:0>:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>filtered = nd.gaussian_filter(im, noise_size, mode='<STR_LIT>')<EOL>if bkg_size is None:<EOL><INDENT>bkg_size = <NUM_LIT:2>*radius<EOL><DEDENT>filtered -= nd.gaussian_filter(filtered, bkg_size, mode='<STR_LIT>')<EOL>footprint = generate_sphere(radius)<EOL>e = nd.maximum_filter(filtered, footprint=footprint)<EOL>mass_im = nd.convolve(filtered, footprint, mode='<STR_LIT>')<EOL>good_im = (e==filtered) * (mass_im > minmass)<EOL>pos = np.transpose(np.nonzero(good_im))<EOL>if trim_edge:<EOL><INDENT>good = np.all(pos > <NUM_LIT:0>, axis=<NUM_LIT:1>) & np.all(pos+<NUM_LIT:1> < im.shape, axis=<NUM_LIT:1>)<EOL>pos = pos[good, :].copy()<EOL><DEDENT>masses = mass_im[pos[:,<NUM_LIT:0>], pos[:,<NUM_LIT:1>], pos[:,<NUM_LIT:2>]].copy()<EOL>return pos, masses<EOL>

Local max featuring to identify bright spherical particles on a
    dark background.

    Parameters
    ----------
        im : numpy.ndarray
            The image to identify particles in.
        radius : Float > 0, optional
            Featuring radius of the particles. Default is 2.5
        noise_size : Float, optional
            Size of Gaussian kernel for smoothing out noise. Default is 1.
        bkg_size : Float or None, optional
            Size of the Gaussian kernel for removing long-wavelength
            background. Default is None, which gives `2 * radius`
        minmass : Float, optional
            Return only particles with a ``mass > minmass``. Default is 1.
        trim_edge : Bool, optional
            Set to True to omit particles identified exactly at the edge
            of the image. False-positive features frequently occur here
            because of the reflected bandpass featuring. Default is
            False, i.e. find particles at the edge of the image.

    Returns
    -------
        pos, mass : numpy.ndarray
            Particle positions and masses


h0, x0 = np.histogram(data.ravel(), bins=bins)<EOL>h = h0.astype('<STR_LIT:float>') / h0.sum()  <EOL>x = <NUM_LIT:0.5>*(x0[<NUM_LIT:1>:] + x0[:-<NUM_LIT:1>])  <EOL>wk = np.array([h[:i+<NUM_LIT:1>].sum() for i in range(h.size)])  <EOL>mk = np.array([sum(x[:i+<NUM_LIT:1>]*h[:i+<NUM_LIT:1>]) for i in range(h.size)])  <EOL>mt = mk[-<NUM_LIT:1>]  <EOL>sb = (mt*wk - mk)**<NUM_LIT:2> / (wk*(<NUM_LIT:1>-wk) + <NUM_LIT>)  <EOL>ind = sb.argmax()<EOL>return <NUM_LIT:0.5>*(x0[ind] + x0[ind+<NUM_LIT:1>])<EOL>

Otsu threshold on data.

Otsu thresholding [1]_is a method for selecting an intensity value
for thresholding an image into foreground and background. The sel-
ected intensity threshold maximizes the inter-class variance.

Parameters
----------
    data : numpy.ndarray
        The data to threshold
    bins : Int or numpy.ndarray, optional
        Bin edges, as passed to numpy.histogram

Returns
-------
    numpy.float
        The value of the threshold which maximizes the inter-class
        variance.

Notes
-----
    This could be generalized to more than 2 classes.
References
----------
    ..[1] N. Otsu, "A Threshold Selection Method from Gray-level
        Histograms," IEEE Trans. Syst., Man, Cybern., Syst., 9, 1,
        62-66 (1979)


def harris_feature(im, region_size=<NUM_LIT:5>, to_return='<STR_LIT>', scale=<NUM_LIT>):

ndim = im.ndim<EOL>grads = [nd.sobel(im, axis=i) for i in range(ndim)]<EOL>matrix = np.zeros((ndim, ndim) + im.shape)<EOL>for a in range(ndim):<EOL><INDENT>for b in range(ndim):<EOL><INDENT>matrix[a,b] = nd.filters.gaussian_filter(grads[a]*grads[b],<EOL>region_size)<EOL><DEDENT><DEDENT>if to_return == '<STR_LIT>':<EOL><INDENT>return matrix<EOL><DEDENT>trc = np.trace(matrix, axis1=<NUM_LIT:0>, axis2=<NUM_LIT:1>)<EOL>det = np.linalg.det(matrix.T).T<EOL>if to_return == '<STR_LIT>':<EOL><INDENT>return trc, det<EOL><DEDENT>else:<EOL><INDENT>harris = det - scale*trc*trc<EOL>return harris<EOL><DEDENT>

Harris-motivated feature detection on a d-dimensional image.

Parameters
---------
    im
    region_size
    to_return : {'harris','matrix','trace-determinant'}


def identify_slab(im, sigma=<NUM_LIT>, region_size=<NUM_LIT:10>, masscut=<NUM_LIT>, asdict=False):

<EOL>fim = nd.filters.gaussian_filter(im, sigma)<EOL>trc, det = harris_feature(fim, region_size, to_return='<STR_LIT>')<EOL>dnrm = det / (trc*trc)<EOL>trc_cut = otsu_threshold(trc)<EOL>det_cut = otsu_threshold(dnrm)<EOL>slabs = (trc > trc_cut) & (dnrm < det_cut)<EOL>labeled, nslabs = nd.label(slabs)<EOL>masses = [(labeled == i).sum() for i in range(<NUM_LIT:1>, nslabs+<NUM_LIT:1>)]<EOL>good = np.array([m > masscut for m in masses])<EOL>inds = np.nonzero(good)[<NUM_LIT:0>] + <NUM_LIT:1>  <EOL>poses = np.array(nd.measurements.center_of_mass(trc, labeled, inds))<EOL>normals = []<EOL>z = np.arange(im.shape[<NUM_LIT:0>]).reshape(-<NUM_LIT:1>,<NUM_LIT:1>,<NUM_LIT:1>).astype('<STR_LIT:float>')<EOL>y = np.arange(im.shape[<NUM_LIT:1>]).reshape(<NUM_LIT:1>,-<NUM_LIT:1>,<NUM_LIT:1>).astype('<STR_LIT:float>')<EOL>x = np.arange(im.shape[<NUM_LIT:2>]).reshape(<NUM_LIT:1>,<NUM_LIT:1>,-<NUM_LIT:1>).astype('<STR_LIT:float>')<EOL>gim = [nd.sobel(fim, axis=i) for i in range(fim.ndim)]<EOL>for i, p in zip(range(<NUM_LIT:1>, nslabs+<NUM_LIT:1>), poses):<EOL><INDENT>wts = trc * (labeled == i)<EOL>wts /= wts.sum()<EOL>zc, yc, xc = [xi-pi for xi, pi in zip([z,y,x],p.squeeze())]<EOL>cov = [[np.sum(xi*xj*wts) for xi in [zc,yc,xc]] for xj in [zc,yc,xc]]<EOL>vl, vc = np.linalg.eigh(cov)<EOL>normal = vc[:,<NUM_LIT:0>]<EOL>gn = np.sum([n*g[tuple(p.astype('<STR_LIT:int>'))] for g,n in zip(gim, normal)])<EOL>normal *= np.sign(gn)<EOL>normals.append(normal)<EOL><DEDENT>if asdict:<EOL><INDENT>get_theta = lambda n: -np.arctan2(n[<NUM_LIT:1>], -n[<NUM_LIT:0>])<EOL>get_phi = lambda n: np.arcsin(n[<NUM_LIT:2>])<EOL>return [{'<STR_LIT>':p[<NUM_LIT:0>], '<STR_LIT>':(get_theta(n), get_phi(n))}<EOL>for p, n in zip(poses, normals)]<EOL><DEDENT>else:<EOL><INDENT>return poses, np.array(normals)<EOL><DEDENT>

Identifies slabs in an image.

Functions by running a Harris-inspired edge detection on the image,
thresholding the edge, then clustering.

Parameters
----------
    im : numpy.ndarray
        3D array of the image to analyze.
    sigma : Float, optional
        Gaussian blurring kernel to remove non-slab features such as
        noise and particles. Default is 5.
    region_size : Int, optional
        The size of region for Harris corner featuring. Default is 10
    masscut : Float, optional
        The minimum number of pixels for a feature to be identified as
        a slab. Default is 1e4; should be smaller for smaller images.
    asdict : Bool, optional
        Set to True to return a list of dicts, with keys of ``'theta'``
        and ``'phi'`` as rotation angles about the x- and z- axes, and
        of ``'zpos'`` for the z-position, i.e. a list of dicts which
        can be unpacked into a :class:``peri.comp.objs.Slab``

Returns
-------
    [poses, normals] : numpy.ndarray
        The positions and normals of each slab in the image; ``poses[i]``
        and ``normals[i]`` are the ``i``th slab. Returned if ``asdict``
        is False
    [list]
        A list of dictionaries. Returned if ``asdict`` is True


to_return = <NUM_LIT>/(x+<NUM_LIT>)*j1(x) - j0(x)<EOL>to_return[x==<NUM_LIT:0>] = <NUM_LIT:0><EOL>return to_return<EOL>

A fast j2 defined in terms of other special functions


pts_hg, wts_hg = np.polynomial.hermite.hermgauss(npts*<NUM_LIT:2>)<EOL>pts_hg = pts_hg[npts:]<EOL>wts_hg = wts_hg[npts:] * np.exp(pts_hg*pts_hg)<EOL>return pts_hg, wts_hg<EOL>

Returns Hermite-Gauss quadrature points for even functions


scl = { <NUM_LIT:15>:<NUM_LIT>,<EOL><NUM_LIT:20>:<NUM_LIT>,<EOL><NUM_LIT>:<NUM_LIT>}[npts]<EOL>pts0, wts0 = np.polynomial.laguerre.laggauss(npts)<EOL>pts = np.sinh(pts0*scl)<EOL>wts = scl*wts0*np.cosh(pts0*scl)*np.exp(pts0)<EOL>return pts, wts<EOL>

Returns Gauss-Laguerre quadrature points rescaled for line scan integration

Parameters
----------
    npts : {15, 20, 25}, optional
        The number of points to

Notes
-----
    The scale is set internally as the best rescaling for a line scan
    integral; it was checked numerically for the allowed npts.
    Acceptable pts/scls/approximate line integral scan error:
    (pts,   scl  )      :         ERR
    ------------------------------------
    (15, 0.072144)      :       0.002193
    (20, 0.051532)      :       0.001498
    (25, 0.043266)      :       0.001209

    The previous HG(20) error was ~0.13ish


def f_theta(cos_theta, zint, z, n2n1=<NUM_LIT>, sph6_ab=None, **kwargs):

wvfront = (np.outer(np.ones_like(z)*zint, cos_theta) -<EOL>np.outer(zint+z, csqrt(n2n1**<NUM_LIT:2>-<NUM_LIT:1>+cos_theta**<NUM_LIT:2>)))<EOL>if (sph6_ab is not None) and (not np.isnan(sph6_ab)):<EOL><INDENT>sec2_theta = <NUM_LIT:1.0>/(cos_theta*cos_theta)<EOL>wvfront += sph6_ab * (sec2_theta-<NUM_LIT:1>)*(sec2_theta-<NUM_LIT:2>)*cos_theta<EOL><DEDENT>if wvfront.dtype == np.dtype('<STR_LIT>'):<EOL><INDENT>wvfront.imag = -np.abs(wvfront.imag)<EOL><DEDENT>return wvfront<EOL>

Returns the wavefront aberration for an aberrated, defocused lens.

Calculates the portions of the wavefront distortion due to z, theta
only, for a lens with defocus and spherical aberration induced by
coverslip mismatch. (The rho portion can be analytically integrated
to Bessels.)

Parameters
----------
    cos_theta : numpy.ndarray.
        The N values of cos(theta) at which to compute f_theta.
    zint : Float
        The position of the lens relative to the interface.
    z : numpy.ndarray
        The M z-values to compute f_theta at. `z.size` is unrelated
        to `cos_theta.size`
    n2n1: Float, optional
        The ratio of the index of the immersed medium to the optics.
        Default is 0.95
    sph6_ab : Float or None, optional
        Set sph6_ab to a nonzero value to add residual 6th-order
        spherical aberration that is proportional to sph6_ab. Default
        is None (i.e. doesn't calculate).

Returns
-------
    wvfront : numpy.ndarray
        The aberrated wavefront, as a function of theta and z.
        Shape is [z.size, cos_theta.size]


return <NUM_LIT>/(<NUM_LIT:1>+csqrt(<NUM_LIT:1>+(n2n1**<NUM_LIT:2>-<NUM_LIT:1>)*cos_theta**-<NUM_LIT:2>))<EOL>

Calculates the Fresnel reflectivity for s-polarized light incident on an
interface with index ration n2n1.

Parameters
----------
    cos_theta : Float or numpy.ndarray
        The _cosine_ of the angle of the incoming light. Float.
    n2n1 : Float, optional
        The ratio n2/n1 of the 2nd material's index n2 to the first's n1
        Default is 0.95

Returns
-------
    Float or numpy.ndarray
        The reflectivity, in the same type (ndarray or Float) and
        shape as cos_theta


return <NUM_LIT:2>*n2n1/(n2n1**<NUM_LIT:2>+csqrt(<NUM_LIT:1>-(<NUM_LIT:1>-n2n1**<NUM_LIT:2>)*cos_theta**-<NUM_LIT:2>))<EOL>

Calculates the Fresnel reflectivity for p-polarized light incident on an
interface with index ration n2n1.

Parameters
----------
    cos_theta : Float or numpy.ndarray
        The _cosine_ of the angle of the incoming light. Float.
    n2n1 : Float, optional
        The ratio n2/n1 of the 2nd material's index n2 to the first's n1
        Default is 0.95

Returns
-------
    Float or numpy.ndarray
        The reflectivity, in the same type (ndarray or Float) and
        shape as cos_theta


def get_Kprefactor(z, cos_theta, zint=<NUM_LIT>, n2n1=<NUM_LIT>, get_hdet=False,<EOL>**kwargs):

phase = f_theta(cos_theta, zint, z, n2n1=n2n1, **kwargs)<EOL>to_return = np.exp(-<NUM_LIT>*phase)<EOL>if not get_hdet:<EOL><INDENT>to_return *= np.outer(np.ones_like(z),np.sqrt(cos_theta))<EOL><DEDENT>return to_return<EOL>

Returns a prefactor in the electric field integral.

This is an internal function called by get_K. The returned prefactor
in the integrand is independent of which integral is being called;
it is a combination of the exp(1j*phase) and apodization.

Parameters
----------
    z : numpy.ndarray
        The values of z (distance along optical axis) at which to
        calculate the prefactor. Size is unrelated to the size of
        `cos_theta`
    cos_theta : numpy.ndarray
        The values of cos(theta) (i.e. position on the incoming
        focal spherical wavefront) at which to calculate the
        prefactor. Size is unrelated to the size of `z`
    zint : Float, optional
        The position of the optical interface, in units of 1/k.
        Default is 100.
    n2n1 : Float, optional
        The ratio of the index mismatch between the optics (n1) and
        the sample (n2). Default is 0.95
    get_hdet : Bool, optional
        Set to True to calculate the detection prefactor vs the
        illumination prefactor (i.e. False to include apodization).
        Default is False

Returns
-------
    numpy.ndarray
        The prefactor, of size [`z.size`, `cos_theta.size`], sampled
        at the values [`z`, `cos_theta`]


def get_K(rho, z, alpha=<NUM_LIT:1.0>, zint=<NUM_LIT>, n2n1=<NUM_LIT>, get_hdet=False, K=<NUM_LIT:1>,<EOL>Kprefactor=None, return_Kprefactor=False, npts=<NUM_LIT:20>, **kwargs):

<EOL>if type(rho) != np.ndarray or type(z) != np.ndarray or (rho.shape != z.shape):<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>pts, wts = np.polynomial.legendre.leggauss(npts)<EOL>n1n2 = <NUM_LIT:1.0>/n2n1<EOL>rr = np.ravel(rho)<EOL>zr = np.ravel(z)<EOL>cos_theta = <NUM_LIT:0.5>*(<NUM_LIT:1>-np.cos(alpha))*pts+<NUM_LIT:0.5>*(<NUM_LIT:1>+np.cos(alpha))<EOL>if Kprefactor is None:<EOL><INDENT>Kprefactor = get_Kprefactor(z, cos_theta, zint=zint,n2n1=n2n1,get_hdet=get_hdet, **kwargs)<EOL><DEDENT>if K==<NUM_LIT:1>:<EOL><INDENT>part_1 = j0(np.outer(rr,np.sqrt(<NUM_LIT:1>-cos_theta**<NUM_LIT:2>)))*np.outer(np.ones_like(rr), <NUM_LIT:0.5>*(get_taus(cos_theta,n2n1=n2n1)+get_taup(cos_theta,n2n1=n2n1)*csqrt(<NUM_LIT:1>-n1n2**<NUM_LIT:2>*(<NUM_LIT:1>-cos_theta**<NUM_LIT:2>))))<EOL>integrand = Kprefactor * part_1<EOL><DEDENT>elif K==<NUM_LIT:2>:<EOL><INDENT>part_2=j2(np.outer(rr,np.sqrt(<NUM_LIT:1>-cos_theta**<NUM_LIT:2>)))*np.outer(np.ones_like(rr),<NUM_LIT:0.5>*(get_taus(cos_theta,n2n1=n2n1)-get_taup(cos_theta,n2n1=n2n1)*csqrt(<NUM_LIT:1>-n1n2**<NUM_LIT:2>*(<NUM_LIT:1>-cos_theta**<NUM_LIT:2>))))<EOL>integrand = Kprefactor * part_2<EOL><DEDENT>elif K==<NUM_LIT:3>:<EOL><INDENT>part_3=j1(np.outer(rho,np.sqrt(<NUM_LIT:1>-cos_theta**<NUM_LIT:2>)))*np.outer(np.ones_like(rr), n1n2*get_taup(cos_theta,n2n1=n2n1)*np.sqrt(<NUM_LIT:1>-cos_theta**<NUM_LIT:2>))<EOL>integrand = Kprefactor * part_3<EOL><DEDENT>else:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>big_wts=np.outer(np.ones_like(rr), wts)<EOL>kint = (big_wts*integrand).sum(axis=<NUM_LIT:1>) * <NUM_LIT:0.5>*(<NUM_LIT:1>-np.cos(alpha))<EOL>if return_Kprefactor:<EOL><INDENT>return kint.reshape(rho.shape), Kprefactor<EOL><DEDENT>else:<EOL><INDENT>return kint.reshape(rho.shape)<EOL><DEDENT>

Calculates one of three electric field integrals.

Internal function for calculating point spread functions. Returns
one of three electric field integrals that describe the electric
field near the focus of a lens; these integrals appear in Hell's psf
calculation.

Parameters
----------
    rho : numpy.ndarray
        Rho in cylindrical coordinates, in units of 1/k.
    z : numpy.ndarray
        Z in cylindrical coordinates, in units of 1/k. `rho` and
        `z` must be the same shape

    alpha : Float, optional
        The acceptance angle of the lens, on (0,pi/2). Default is 1.
    zint : Float, optional
        The distance of the len's unaberrated focal point from the
        optical interface, in units of 1/k. Default is 100.
    n2n1 : Float, optional
        The ratio n2/n1 of the index mismatch between the sample
        (index n2) and the optical train (index n1). Must be on
        [0,inf) but should be near 1. Default is 0.95
    get_hdet : Bool, optional
        Set to True to get the detection portion of the psf; False
        to get the illumination portion of the psf. Default is True
    K : {1, 2, 3}, optional
        Which of the 3 integrals to evaluate. Default is 1
    Kprefactor : numpy.ndarray or None
        This array is calculated internally and optionally returned;
        pass it back to avoid recalculation and increase speed. Default
        is None, i.e. calculate it internally.
    return_Kprefactor : Bool, optional
        Set to True to also return the Kprefactor (parameter above)
        to speed up the calculation for the next values of K. Default
        is False
    npts : Int, optional
        The number of points to use for Gauss-Legendre quadrature of
        the integral. Default is 20, which is a good number for x,y,z
        less than 100 or so.

Returns
-------
    kint : numpy.ndarray
        The integral K_i; rho.shape numpy.array
    [, Kprefactor] : numpy.ndarray
        The prefactor that is independent of which integral is being
        calculated but does depend on the parameters; can be passed
        back to the function for speed.

Notes
-----
    npts=20 gives double precision (no difference between 20, 30, and
    doing all the integrals with scipy.quad). The integrals are only
    over the acceptance angle of the lens, so for moderate x,y,z they
    don't vary too rapidly. For x,y,z, zint large compared to 100, a
    higher npts might be necessary.


def get_hsym_asym(rho, z, get_hdet=False, include_K3_det=True, **kwargs):

K1, Kprefactor = get_K(rho, z, K=<NUM_LIT:1>, get_hdet=get_hdet, Kprefactor=None,<EOL>return_Kprefactor=True, **kwargs)<EOL>K2 = get_K(rho, z, K=<NUM_LIT:2>, get_hdet=get_hdet, Kprefactor=Kprefactor,<EOL>return_Kprefactor=False, **kwargs)<EOL>if get_hdet and not include_K3_det:<EOL><INDENT>K3 = <NUM_LIT:0>*K1<EOL><DEDENT>else:<EOL><INDENT>K3 = get_K(rho, z, K=<NUM_LIT:3>, get_hdet=get_hdet, Kprefactor=Kprefactor,<EOL>return_Kprefactor=False, **kwargs)<EOL><DEDENT>hsym = K1*K1.conj() + K2*K2.conj() + <NUM_LIT:0.5>*(K3*K3.conj())<EOL>hasym= K1*K2.conj() + K2*K1.conj() + <NUM_LIT:0.5>*(K3*K3.conj())<EOL>return hsym.real, hasym.real<EOL>

Calculates the symmetric and asymmetric portions of a confocal PSF.

Parameters
----------
    rho : numpy.ndarray
        Rho in cylindrical coordinates, in units of 1/k.
    z : numpy.ndarray
        Z in cylindrical coordinates, in units of 1/k. Must be the
        same shape as `rho`
    get_hdet : Bool, optional
        Set to True to get the detection portion of the psf; False
        to get the illumination portion of the psf. Default is True
    include_K3_det : Bool, optional.
        Flag to not calculate the `K3' component for the detection
        PSF, corresponding to (I think) a low-aperature focusing
        lens and no z-polarization of the focused light. Default
        is True, i.e. calculates the K3 component as if the focusing
        lens is high-aperture

Other Parameters
----------------
    alpha : Float, optional
        The acceptance angle of the lens, on (0,pi/2). Default is 1.
    zint : Float, optional
        The distance of the len's unaberrated focal point from the
        optical interface, in units of 1/k. Default is 100.
    n2n1 : Float, optional
        The ratio n2/n1 of the index mismatch between the sample
        (index n2) and the optical train (index n1). Must be on
        [0,inf) but should be near 1. Default is 0.95

Returns
-------
    hsym : numpy.ndarray
        `rho`.shape numpy.array of the symmetric portion of the PSF
    hasym : numpy.ndarray
        `rho`.shape numpy.array of the asymmetric portion of the PSF


def calculate_pinhole_psf(x, y, z, kfki=<NUM_LIT>, zint=<NUM_LIT>, normalize=False,<EOL>**kwargs):

rho = np.sqrt(x**<NUM_LIT:2> + y**<NUM_LIT:2>)<EOL>phi = np.arctan2(y, x)<EOL>hsym, hasym = get_hsym_asym(rho, z, zint=zint, get_hdet=False, **kwargs)<EOL>hdet, toss  = get_hsym_asym(rho*kfki, z*kfki, zint=kfki*zint, get_hdet=True, **kwargs)<EOL>if normalize:<EOL><INDENT>hasym /= hsym.sum()<EOL>hsym /= hsym.sum()<EOL>hdet /= hdet.sum()<EOL><DEDENT>return (hsym + np.cos(<NUM_LIT:2>*phi)*hasym)*hdet<EOL>

Calculates the perfect-pinhole PSF, for a set of points (x,y,z).

Parameters
-----------
    x : numpy.ndarray
        The x-coordinate of the PSF in units of 1/ the wavevector of
        the incoming light.
    y : numpy.ndarray
        The y-coordinate.
    z : numpy.ndarray
        The z-coordinate.
    kfki : Float
        The (scalar) ratio of wavevectors of the outgoing light to the
        incoming light. Default is 0.89.
    zint : Float
        The (scalar) distance from the interface, in units of
        1/k_incoming. Default is 100.0
    normalize : Bool
        Set to True to normalize the psf correctly, accounting for
        intensity variations with depth. This will give a psf that does
        not sum to 1.

Other Parameters
----------------
    alpha : Float
        The opening angle of the lens. Default is 1.
    n2n1 : Float
        The ratio of the index in the 2nd medium to that in the first.
        Default is 0.95

Returns
-------
    psf : numpy.ndarray, of shape x.shape

Comments
--------
    (1) The PSF is not necessarily centered on the z=0 pixel, since the
        calculation includes the shift.

    (2) If you want z-varying illumination of the psf then set
        normalize=True. This does the normalization by doing:
            hsym, hasym /= hsym.sum()
            hdet /= hdet.sum()
        and then calculating the psf that way. So if you want the
        intensity to be correct you need to use a large-ish array of
        roughly equally spaced points. Or do it manually by calling
        get_hsym_asym()


def get_polydisp_pts_wts(kfki, sigkf, dist_type='<STR_LIT>', nkpts=<NUM_LIT:3>):

if dist_type.lower() == '<STR_LIT>':<EOL><INDENT>pts, wts = np.polynomial.hermite.hermgauss(nkpts)<EOL>kfkipts = np.abs(kfki + sigkf*np.sqrt(<NUM_LIT:2>)*pts)<EOL><DEDENT>elif dist_type.lower() == '<STR_LIT>' or dist_type.lower() == '<STR_LIT>':<EOL><INDENT>k_scale = sigkf**<NUM_LIT:2>/kfki<EOL>associated_order = kfki**<NUM_LIT:2>/sigkf**<NUM_LIT:2> - <NUM_LIT:1><EOL>max_order=<NUM_LIT><EOL>if associated_order > max_order or associated_order < (-<NUM_LIT:1>+<NUM_LIT>):<EOL><INDENT>warnings.warn('<STR_LIT>', RuntimeWarning)<EOL>associated_order = np.clip(associated_order, -<NUM_LIT:1>+<NUM_LIT>, max_order)<EOL><DEDENT>kfkipts, wts = la_roots(nkpts, associated_order)<EOL>kfkipts *= k_scale<EOL><DEDENT>else:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>return kfkipts, wts/wts.sum()<EOL>

Calculates a set of Gauss quadrature points & weights for polydisperse
light.

Returns a list of points and weights of the final wavevector's distri-
bution, in units of the initial wavevector.

Parameters
----------
    kfki : Float
        The mean of the polydisperse outgoing wavevectors.
    sigkf : Float
        The standard dev. of the polydisperse outgoing wavevectors.
    dist_type : {`gaussian`, `gamma`}, optional
        The distribution, gaussian or gamma, of the wavevectors.
        Default is `gaussian`
    nkpts : Int, optional
        The number of quadrature points to use. Default is 3
Returns
-------
    kfkipts : numpy.ndarray
        The Gauss quadrature points at which to calculate kfki.
    wts : numpy.ndarray
        The associated Gauss quadrature weights.


def calculate_polychrome_pinhole_psf(x, y, z, normalize=False, kfki=<NUM_LIT>,<EOL>sigkf=<NUM_LIT:0.1>, zint=<NUM_LIT>, nkpts=<NUM_LIT:3>, dist_type='<STR_LIT>', **kwargs):

<EOL>kfkipts, wts = get_polydisp_pts_wts(kfki, sigkf, dist_type=dist_type,<EOL>nkpts=nkpts)<EOL>rho = np.sqrt(x**<NUM_LIT:2> + y**<NUM_LIT:2>)<EOL>phi = np.arctan2(y, x)<EOL>hsym, hasym = get_hsym_asym(rho, z, zint=zint, get_hdet=False, **kwargs)<EOL>hilm = (hsym + np.cos(<NUM_LIT:2>*phi)*hasym)<EOL>hdet_func = lambda kfki: get_hsym_asym(rho*kfki, z*kfki,<EOL>zint=kfki*zint, get_hdet=True, **kwargs)[<NUM_LIT:0>]<EOL>inner = [wts[a] * hdet_func(kfkipts[a]) for a in range(nkpts)]<EOL>hdet = np.sum(inner, axis=<NUM_LIT:0>)<EOL>if normalize:<EOL><INDENT>hilm /= hilm.sum()<EOL>hdet /= hdet.sum()<EOL><DEDENT>psf = hdet * hilm<EOL>return psf if normalize else psf / psf.sum()<EOL>

Calculates the perfect-pinhole PSF, for a set of points (x,y,z).

Parameters
-----------
    x : numpy.ndarray
        The x-coordinate of the PSF in units of 1/ the wavevector of
        the incoming light.
    y : numpy.ndarray
        The y-coordinate.
    z : numpy.ndarray
        The z-coordinate.
    kfki : Float
        The mean ratio of the outgoing light's wavevector to the incoming
        light's. Default is 0.89.
    sigkf : Float
        Standard deviation of kfki; the distribution of the light values
        will be approximately kfki +- sigkf.
    zint : Float
        The (scalar) distance from the interface, in units of
        1/k_incoming. Default is 100.0
    dist_type: The distribution type of the polychromatic light.
        Can be one of 'laguerre'/'gamma' or 'gaussian.' If 'gaussian'
        the resulting k-values are taken in absolute value. Default
        is 'gaussian.'
    normalize : Bool
        Set to True to normalize the psf correctly, accounting for
        intensity variations with depth. This will give a psf that does
        not sum to 1. Default is False.

Other Parameters
----------------
    alpha : Float
        The opening angle of the lens. Default is 1.
    n2n1 : Float
        The ratio of the index in the 2nd medium to that in the first.
        Default is 0.95

Returns
-------
    psf : numpy.ndarray, of shape x.shape

Comments
--------
    (1) The PSF is not necessarily centered on the z=0 pixel, since the
        calculation includes the shift.

    (2) If you want z-varying illumination of the psf then set
        normalize=True. This does the normalization by doing:
            hsym, hasym /= hsym.sum()
            hdet /= hdet.sum()
        and then calculating the psf that way. So if you want the
        intensity to be correct you need to use a large-ish array of
        roughly equally spaced points. Or do it manually by calling
        get_hsym_asym()


def get_psf_scalar(x, y, z, kfki=<NUM_LIT:1.>, zint=<NUM_LIT>, normalize=False, **kwargs):

rho = np.sqrt(x**<NUM_LIT:2> + y**<NUM_LIT:2>)<EOL>phi = np.arctan2(y, x)<EOL>K1 = get_K(rho, z, K=<NUM_LIT:1>,zint=zint,get_hdet=True, **kwargs)<EOL>hilm = np.real( K1*K1.conj() )<EOL>if np.abs(kfki - <NUM_LIT:1.0>) > <NUM_LIT>:<EOL><INDENT>Kdet = get_K(rho*kfki, z*kfki, K=<NUM_LIT:1>, zint=zint*kfki, get_hdet=True,<EOL>**kwargs)<EOL>hdet = np.real( Kdet*Kdet.conj() )<EOL><DEDENT>else:<EOL><INDENT>hdet = hilm.copy()<EOL><DEDENT>if normalize:<EOL><INDENT>hilm /= hsym.sum()<EOL>hdet /= hdet.sum()<EOL>psf = hilm * hdet<EOL><DEDENT>else:<EOL><INDENT>psf = hilm * hdet<EOL><DEDENT>return psf<EOL>

Calculates a scalar (non-vectorial light) approximation to a confocal PSF

The calculation is approximate, since it ignores the effects of
polarization and apodization, but should be ~3x faster.

Parameters
----------
    x : numpy.ndarray
        The x-coordinate of the PSF in units of 1/ the wavevector
        of the incoming light.
    y : numpy.ndarray
        The y-coordinate of the PSF in units of 1/ the wavevector
        of the incoming light. Must be the same shape as `x`.
    z : numpy.ndarray
        The z-coordinate of the PSF in units of 1/ the wavevector
        of the incoming light. Must be the same shape as `x`.
    kfki : Float, optional
        The ratio of wavevectors of the outgoing light to the
        incoming light. Set to 1.0 to speed up the calculation
        by another factor of 2. Default is 1.0
    zint : Float, optional
        The distance from to the optical interface, in units of
        1/k_incoming. Default is 100.
    normalize : Bool
        Set to True to normalize the psf correctly, accounting for
        intensity variations with depth. This will give a psf that does
        not sum to 1. Default is False.
    alpha : Float
        The opening angle of the lens. Default is 1.
    n2n1 : Float
        The ratio of the index in the 2nd medium to that in the first.
        Default is 0.95

Outputs:
    - psf: x.shape numpy.array.

Comments:
    (1) Note that the PSF is not necessarily centered on the z=0 pixel,
        since the calculation includes the shift.

    (2) If you want z-varying illumination of the psf then set
        normalize=True. This does the normalization by doing:
            hsym, hasym /= hsym.sum()
            hdet /= hdet.sum()
        and then calculating the psf that way. So if you want the
        intensity to be correct you need to use a large-ish array of
        roughly equally spaced points. Or do it manually by calling
        get_hsym_asym()


def calculate_linescan_ilm_psf(y,z, polar_angle=<NUM_LIT:0.>, nlpts=<NUM_LIT:1>,<EOL>pinhole_width=<NUM_LIT:1>, use_laggauss=False, **kwargs):

if use_laggauss:<EOL><INDENT>x_vals, wts = calc_pts_lag()<EOL><DEDENT>else:<EOL><INDENT>x_vals, wts = calc_pts_hg()<EOL><DEDENT>xg, yg, zg = [np.zeros( list(y.shape) + [x_vals.size] ) for a in range(<NUM_LIT:3>)]<EOL>hilm = np.zeros(xg.shape)<EOL>for a in range(x_vals.size):<EOL><INDENT>xg[...,a] = x_vals[a]<EOL>yg[...,a] = y.copy()<EOL>zg[...,a] = z.copy()<EOL><DEDENT>y_pinhole, wts_pinhole = np.polynomial.hermite.hermgauss(nlpts)<EOL>y_pinhole *= np.sqrt(<NUM_LIT:2>)*pinhole_width<EOL>wts_pinhole /= np.sqrt(np.pi)<EOL>for yp, wp in zip(y_pinhole, wts_pinhole):<EOL><INDENT>rho = np.sqrt(xg*xg + (yg-yp)*(yg-yp))<EOL>phi = np.arctan2(yg,xg)<EOL>hsym, hasym = get_hsym_asym(rho,zg,get_hdet = False, **kwargs)<EOL>hilm += wp*(hsym + np.cos(<NUM_LIT:2>*(phi-polar_angle))*hasym)<EOL><DEDENT>for a in range(x_vals.size):<EOL><INDENT>hilm[...,a] *= wts[a]<EOL><DEDENT>return hilm.sum(axis=-<NUM_LIT:1>)*<NUM_LIT><EOL>

Calculates the illumination PSF for a line-scanning confocal with the
confocal line oriented along the x direction.

Parameters
----------
    y : numpy.ndarray
        The y points (in-plane, perpendicular to the line direction)
        at which to evaluate the illumination PSF, in units of 1/k.
        Arbitrary shape.
    z : numpy.ndarray
        The z points (optical axis) at which to evaluate the illum-
        ination PSF, in units of 1/k. Must be the same shape as `y`
    polar_angle : Float, optional
        The angle of the illuminating light's polarization with
        respect to the line's orientation along x. Default is 0.
    pinhole_width : Float, optional
        The width of the geometric image of the line projected onto
        the sample, in units of 1/k. Default is 1. The perfect line
        image is assumed to be a Gaussian. If `nlpts` is set to 1,
        the line will always be of zero width.
    nlpts : Int, optional
        The number of points to use for Hermite-gauss quadrature over
        the line's width. Default is 1, corresponding to a zero-width
        line.
    use_laggauss : Bool, optional
        Set to True to use a more-accurate sinh'd Laguerre-Gauss
        quadrature for integration over the line's length (more accurate
        in the same amount of time). Default is False for backwards
        compatibility.  FIXME what did we do here?

Other Parameters
----------------
    alpha : Float, optional
        The acceptance angle of the lens, on (0,pi/2). Default is 1.
    zint : Float, optional
        The distance of the len's unaberrated focal point from the
        optical interface, in units of 1/k. Default is 100.
    n2n1 : Float, optional
        The ratio n2/n1 of the index mismatch between the sample
        (index n2) and the optical train (index n1). Must be on
        [0,inf) but should be near 1. Default is 0.95

Returns
-------
    hilm : numpy.ndarray
        The line illumination, of the same shape as y and z.


def calculate_linescan_psf(x, y, z, normalize=False, kfki=<NUM_LIT>, zint=<NUM_LIT>,<EOL>polar_angle=<NUM_LIT:0.>, wrap=True, **kwargs):

<EOL>if wrap:<EOL><INDENT>xpts = vec_to_halfvec(x)<EOL>ypts = vec_to_halfvec(y)<EOL>x3, y3, z3 = np.meshgrid(xpts, ypts, z, indexing='<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>x3,y3,z3 = np.meshgrid(x, y, z, indexing='<STR_LIT>')<EOL><DEDENT>rho3 = np.sqrt(x3*x3 + y3*y3)<EOL>if wrap:<EOL><INDENT>y2,z2 = np.meshgrid(ypts, z, indexing='<STR_LIT>')<EOL>hilm0 = calculate_linescan_ilm_psf(y2, z2, zint=zint,<EOL>polar_angle=polar_angle, **kwargs)<EOL>if ypts[<NUM_LIT:0>] == <NUM_LIT:0>:<EOL><INDENT>hilm = np.append(hilm0[-<NUM_LIT:1>:<NUM_LIT:0>:-<NUM_LIT:1>], hilm0, axis=<NUM_LIT:0>)<EOL><DEDENT>else:<EOL><INDENT>hilm = np.append(hilm0[::-<NUM_LIT:1>], hilm0, axis=<NUM_LIT:0>)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>y2,z2 = np.meshgrid(y, z, indexing='<STR_LIT>')<EOL>hilm = calculate_linescan_ilm_psf(y2, z2, zint=zint,<EOL>polar_angle=polar_angle, **kwargs)<EOL><DEDENT>if wrap:<EOL><INDENT>func = lambda *args: get_hsym_asym(rho3*kfki, z3*kfki, zint=kfki*zint,<EOL>get_hdet=True, **kwargs)[<NUM_LIT:0>]<EOL>hdet = wrap_and_calc_psf(xpts, ypts, z, func)<EOL><DEDENT>else:<EOL><INDENT>hdet, toss = get_hsym_asym(rho3*kfki, z3*kfki, zint=kfki*zint,<EOL>get_hdet=True, **kwargs)<EOL><DEDENT>if normalize:<EOL><INDENT>hilm /= hilm.sum()<EOL>hdet /= hdet.sum()<EOL><DEDENT>for a in range(x.size):<EOL><INDENT>hdet[a] *= hilm<EOL><DEDENT>return hdet if normalize else hdet / hdet.sum()<EOL>

Calculates the point spread function of a line-scanning confocal.

Make x,y,z  __1D__ numpy.arrays, with x the direction along the
scan line. (to make the calculation faster since I dont' need the line
ilm for each x).

Parameters
----------
    x : numpy.ndarray
        _One_dimensional_ array of the x grid points (along the line
        illumination) at which to evaluate the psf. In units of
        1/k_incoming.
    y : numpy.ndarray
        _One_dimensional_ array of the y grid points (in plane,
        perpendicular to the line illumination) at which to evaluate
        the psf. In units of 1/k_incoming.
    z : numpy.ndarray
        _One_dimensional_ array of the z grid points (along the
        optical axis) at which to evaluate the psf. In units of
        1/k_incoming.
    normalize : Bool, optional
        Set to True to include the effects of PSF normalization on
        the image intensity. Default is False.
    kfki : Float, optional
        The ratio of the final light's wavevector to the incoming.
        Default is 0.889
    zint : Float, optional
        The position of the optical interface, in units of 1/k_incoming
        Default is 100.
    wrap : Bool, optional
        If True, wraps the psf calculation for speed, assuming that
        the input x, y are regularly-spaced points. If x,y are not
        regularly spaced then `wrap` must be set to False. Default is True.
    polar_angle : Float, optional
        The polarization angle of the light (radians) with respect to
        the line direction (x). Default is 0.

Other Parameters
----------------
    alpha : Float
        The opening angle of the lens. Default is 1.
    n2n1 : Float
        The ratio of the index in the 2nd medium to that in the first.
        Default is 0.95

Returns
-------
    numpy.ndarray
        A 3D- numpy.array of the point-spread function. Indexing is
        psf[x,y,z]; shape is [x.size, y,size, z.size]


def calculate_polychrome_linescan_psf(x, y, z, normalize=False, kfki=<NUM_LIT>,<EOL>sigkf=<NUM_LIT:0.1>, zint=<NUM_LIT>, nkpts=<NUM_LIT:3>, dist_type='<STR_LIT>', wrap=True,<EOL>**kwargs):

kfkipts, wts = get_polydisp_pts_wts(kfki, sigkf, dist_type=dist_type,<EOL>nkpts=nkpts)<EOL>if wrap:<EOL><INDENT>xpts = vec_to_halfvec(x)<EOL>ypts = vec_to_halfvec(y)<EOL>x3, y3, z3 = np.meshgrid(xpts, ypts, z, indexing='<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>x3,y3,z3 = np.meshgrid(x, y, z, indexing='<STR_LIT>')<EOL><DEDENT>rho3 = np.sqrt(x3*x3 + y3*y3)<EOL>if wrap:<EOL><INDENT>y2,z2 = np.meshgrid(ypts, z, indexing='<STR_LIT>')<EOL>hilm0 = calculate_linescan_ilm_psf(y2, z2, zint=zint, **kwargs)<EOL>if ypts[<NUM_LIT:0>] == <NUM_LIT:0>:<EOL><INDENT>hilm = np.append(hilm0[-<NUM_LIT:1>:<NUM_LIT:0>:-<NUM_LIT:1>], hilm0, axis=<NUM_LIT:0>)<EOL><DEDENT>else:<EOL><INDENT>hilm = np.append(hilm0[::-<NUM_LIT:1>], hilm0, axis=<NUM_LIT:0>)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>y2,z2 = np.meshgrid(y, z, indexing='<STR_LIT>')<EOL>hilm = calculate_linescan_ilm_psf(y2, z2, zint=zint, **kwargs)<EOL><DEDENT>if wrap:<EOL><INDENT>func = lambda x,y,z, kfki=<NUM_LIT:1.>: get_hsym_asym(rho3*kfki, z3*kfki,<EOL>zint=kfki*zint, get_hdet=True, **kwargs)[<NUM_LIT:0>]<EOL>hdet_func = lambda kfki: wrap_and_calc_psf(xpts,ypts,z, func, kfki=kfki)<EOL><DEDENT>else:<EOL><INDENT>hdet_func = lambda kfki: get_hsym_asym(rho3*kfki, z3*kfki,<EOL>zint=kfki*zint, get_hdet=True, **kwargs)[<NUM_LIT:0>]<EOL><DEDENT>inner = [wts[a] * hdet_func(kfkipts[a]) for a in range(nkpts)]<EOL>hdet = np.sum(inner, axis=<NUM_LIT:0>)<EOL>if normalize:<EOL><INDENT>hilm /= hilm.sum()<EOL>hdet /= hdet.sum()<EOL><DEDENT>for a in range(x.size):<EOL><INDENT>hdet[a] *= hilm<EOL><DEDENT>return hdet if normalize else hdet / hdet.sum()<EOL>

Calculates the point spread function of a line-scanning confocal with
polydisperse dye emission.

Make x,y,z  __1D__ numpy.arrays, with x the direction along the
scan line. (to make the calculation faster since I dont' need the line
ilm for each x).

Parameters
----------
    x : numpy.ndarray
        _One_dimensional_ array of the x grid points (along the line
        illumination) at which to evaluate the psf. In units of
        1/k_incoming.
    y : numpy.ndarray
        _One_dimensional_ array of the y grid points (in plane,
        perpendicular to the line illumination) at which to evaluate
        the psf. In units of 1/k_incoming.
    z : numpy.ndarray
        _One_dimensional_ array of the z grid points (along the
        optical axis) at which to evaluate the psf. In units of
        1/k_incoming.
    normalize : Bool, optional
        Set to True to include the effects of PSF normalization on
        the image intensity. Default is False.
    kfki : Float, optional
        The mean of the ratio of the final light's wavevector to the
        incoming. Default is 0.889
    sigkf : Float, optional
        The standard deviation of the ratio of the final light's
        wavevector to the incoming. Default is 0.1
    zint : Float, optional
        The position of the optical interface, in units of 1/k_incoming
        Default is 100.
    dist_type : {`gaussian`, `gamma`}, optional
        The distribution of the outgoing light. If 'gaussian' the
        resulting k-values are taken in absolute value. Default
        is `gaussian`
    wrap : Bool, optional
        If True, wraps the psf calculation for speed, assuming that
        the input x, y are regularly-spaced points. If x,y are not
        regularly spaced then `wrap` must be set to False. Default is True.

Other Parameters
----------------
    polar_angle : Float, optional
        The polarization angle of the light (radians) with respect to
        the line direction (x). Default is 0.
    alpha : Float
        The opening angle of the lens. Default is 1.
    n2n1 : Float
        The ratio of the index in the 2nd medium to that in the first.
        Default is 0.95

Returns
-------
    numpy.ndarray
        A 3D- numpy.array of the point-spread function. Indexing is
        psf[x,y,z]; shape is [x.size, y,size, z.size]
Notes
-----
    Neither distribution type is perfect. If sigkf/k0 is big (>0.5ish)
    then part of the Gaussian is negative. To avoid issues an abs() is
    taken, but then the actual mean and variance are not what is
    supplied. Conversely, if sigkf/k0 is small (<0.0815), then the
    requisite associated Laguerre quadrature becomes unstable. To
    prevent this sigkf/k0 is effectively clipped to be > 0.0815.


def wrap_and_calc_psf(xpts, ypts, zpts, func, **kwargs):

<EOL>for t in [xpts,ypts,zpts]:<EOL><INDENT>if len(t.shape) != <NUM_LIT:1>:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT><DEDENT>dx = <NUM_LIT:1> if xpts[<NUM_LIT:0>]==<NUM_LIT:0> else <NUM_LIT:0><EOL>dy = <NUM_LIT:1> if ypts[<NUM_LIT:0>]==<NUM_LIT:0> else <NUM_LIT:0><EOL>xg,yg,zg = np.meshgrid(xpts,ypts,zpts, indexing='<STR_LIT>')<EOL>xs, ys, zs = [ pts.size for pts in [xpts,ypts,zpts] ]<EOL>to_return = np.zeros([<NUM_LIT:2>*xs-dx, <NUM_LIT:2>*ys-dy, zs])<EOL>up_corner_psf = func(xg,yg,zg, **kwargs)<EOL>to_return[xs-dx:,ys-dy:,:] = up_corner_psf.copy()                     <EOL>if dx == <NUM_LIT:0>:<EOL><INDENT>to_return[:xs-dx,ys-dy:,:] = up_corner_psf[::-<NUM_LIT:1>,:,:].copy()       <EOL><DEDENT>else:<EOL><INDENT>to_return[:xs-dx,ys-dy:,:] = up_corner_psf[-<NUM_LIT:1>:<NUM_LIT:0>:-<NUM_LIT:1>,:,:].copy()    <EOL><DEDENT>if dy == <NUM_LIT:0>:<EOL><INDENT>to_return[xs-dx:,:ys-dy,:] = up_corner_psf[:,::-<NUM_LIT:1>,:].copy()       <EOL><DEDENT>else:<EOL><INDENT>to_return[xs-dx:,:ys-dy,:] = up_corner_psf[:,-<NUM_LIT:1>:<NUM_LIT:0>:-<NUM_LIT:1>,:].copy()    <EOL><DEDENT>if (dx == <NUM_LIT:0>) and (dy == <NUM_LIT:0>):<EOL><INDENT>to_return[:xs-dx,:ys-dy,:] = up_corner_psf[::-<NUM_LIT:1>,::-<NUM_LIT:1>,:].copy()    <EOL><DEDENT>elif (dx == <NUM_LIT:0>) and (dy != <NUM_LIT:0>):<EOL><INDENT>to_return[:xs-dx,:ys-dy,:] = up_corner_psf[::-<NUM_LIT:1>,-<NUM_LIT:1>:<NUM_LIT:0>:-<NUM_LIT:1>,:].copy() <EOL><DEDENT>elif (dy == <NUM_LIT:0>) and (dx != <NUM_LIT:0>):<EOL><INDENT>to_return[:xs-dx,:ys-dy,:] = up_corner_psf[-<NUM_LIT:1>:<NUM_LIT:0>:-<NUM_LIT:1>,::-<NUM_LIT:1>,:].copy() <EOL><DEDENT>else: <EOL><INDENT>to_return[:xs-dx,:ys-dy,:] = up_corner_psf[-<NUM_LIT:1>:<NUM_LIT:0>:-<NUM_LIT:1>,-<NUM_LIT:1>:<NUM_LIT:0>:-<NUM_LIT:1>,:].copy()<EOL><DEDENT>return to_return<EOL>

Wraps a point-spread function in x and y.

Speeds up psf calculations by a factor of 4 for free / some broadcasting
by exploiting the x->-x, y->-y symmetry of a psf function. Pass x and y
as the positive (say) values of the coordinates at which to evaluate func,
and it will return the function sampled at [x[::-1]] + x. Note it is not
wrapped in z.

Parameters
----------
    xpts : numpy.ndarray
        1D N-element numpy.array of the x-points to evaluate func at.
    ypts : numpy.ndarray
        y-points to evaluate func at.
    zpts : numpy.ndarray
        z-points to evaluate func at.
    func : function
        The function to evaluate and wrap around. Syntax must be
        func(x,y,z, **kwargs)
    **kwargs : Any parameters passed to the function.

Outputs
-------
    to_return : numpy.ndarray
        The wrapped and calculated psf, of shape
        [2*x.size - x0, 2*y.size - y0, z.size], where x0=1 if x[0]=0, etc.

Notes
-----
The coordinates should be something like numpy.arange(start, stop, diff),
with start near 0. If x[0]==0, all of x is calcualted but only x[1:]
is wrapped (i.e. it works whether or not x[0]=0).

This doesn't work directly for a linescan psf because the illumination
portion is not like a grid. However, the illumination and detection
are already combined with wrap_and_calc in calculate_linescan_psf etc.


d = vec[<NUM_LIT:1>:] - vec[:-<NUM_LIT:1>]<EOL>if ((d/d.mean()).std() > <NUM_LIT>) or (d.mean() < <NUM_LIT:0>):<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>dx = d.mean()<EOL>lowest = np.abs(vec).min()<EOL>highest = np.abs(vec).max()<EOL>return np.arange(lowest, highest + <NUM_LIT:0.1>*dx, dx).astype(vec.dtype)<EOL>

Transforms a vector np.arange(-N, M, dx) to np.arange(min(|vec|), max(N,M),dx)]


def __init__(self, params, values, shape=None):

self.shape = shape<EOL>super(PSF, self).__init__(params, values, category='<STR_LIT>')<EOL>if self.shape:<EOL><INDENT>self.initialize()<EOL><DEDENT>

Point spread function classes must contain the following classes in order
to interface with the states class:

    get_padding_size(z) : get the psf size at certain z position
    get_params : return the parameters of the psf
    set_tile : set the current update tile size
    update : update the psf based on new parameters
    execute : apply the psf to an image


self.min_support = <NUM_LIT:0><EOL>super(IdentityPSF, self).__init__(params=['<STR_LIT>'], values=[<NUM_LIT:0>])<EOL>

Delta-function PSF; returns the field passed to execute identically.
Params is an N-element numpy.ndarray, doesn't do anything.


super(PSF4D, self).__init__(params=params, values=values, shape=shape)<EOL>

4-dimensional Point-Spread-Function (PSF) is implemented by assuming
that the there is only z-dependence of parameters (so that it can be
separated into x-y and z parts).  Therefore, we keep track of 2D FFTs
and X-Y psf functions that get convolved with FFTs.  Then, we manually
convolve in the z direction

The key variables are rpsf (2d) and kpsf (2d) which are used for the
x-y convolution.  The z-convolution cannot be cached.


pass<EOL>

Returns the x-y plane real space psf function as a function of z values.
This function does not necessarily have to be normalized, it will be
normalized in k-space layer by layer later.


pass<EOL>

Returns the z dependence of the PSF.  This section needs to be noramlized.


def __init__(self, sigmas=(<NUM_LIT>,<NUM_LIT:0.5>,<NUM_LIT:1.0>), order=(<NUM_LIT:1>,<NUM_LIT:1>,<NUM_LIT:1>),<EOL>moment_order=(<NUM_LIT:3>,<NUM_LIT:3>), error=<NUM_LIT:1.0>/<NUM_LIT:255>, zrange=<NUM_LIT>, shape=None):

self.order = order<EOL>self.morder = moment_order<EOL>self.error = error<EOL>self.zrange = float(zrange)<EOL>self.poly_coeffs = {}<EOL>self.moment_coeffs = {}<EOL>params, values = [], []<EOL>for i, o in enumerate(order):<EOL><INDENT>d = ['<STR_LIT:z>', '<STR_LIT:y>', '<STR_LIT:x>']<EOL>tparams = ['<STR_LIT>' % (d[i], j) for j in range(o)]<EOL>tvalues = [sigmas[i]] + [<NUM_LIT:0>]*(o-<NUM_LIT:1>)<EOL>params.extend(tparams)<EOL>values.extend(tvalues)<EOL>self.poly_coeffs[i] = tparams<EOL><DEDENT>for i, o in enumerate(moment_order):<EOL><INDENT>t = ['<STR_LIT>', '<STR_LIT>']<EOL>self.moment_coeffs[t[i]] = {}<EOL>for j, d in enumerate(['<STR_LIT:z>', '<STR_LIT:y>', '<STR_LIT:x>']):<EOL><INDENT>tparams = [<EOL>'<STR_LIT>' % (t[i], d, k) for k in range(o)<EOL>]<EOL>tvalues = [<NUM_LIT:0>]*(o)<EOL>params.extend(tparams)<EOL>values.extend(tvalues)<EOL>self.moment_coeffs[t[i]][j] = tparams<EOL><DEDENT><DEDENT>super(GaussianMomentExpansion, self).__init__(<EOL>shape=shape, params=params, values=values<EOL>)<EOL>

3+1D PSF that is of the form:
    (1+a*(3x-x^3) + b*(3-6*x^2+x^4))*exp(-(x/s)^2/2)
where s is sigma, the scale factor.


@memoize()<EOL><INDENT>def _skew(self, x, z, d=<NUM_LIT:0>):<DEDENT>

<EOL>kval = (np.tanh(self._poly(z, self._kurtosis_coeffs(d)))+<NUM_LIT:1>)/<NUM_LIT><EOL>bdpoly = np.array([<EOL>-<NUM_LIT>,  <NUM_LIT>, -<NUM_LIT>,<EOL>-<NUM_LIT>, <NUM_LIT>, <NUM_LIT><EOL>])<EOL>top = np.polyval(bdpoly, kval)<EOL>skew = self._poly(z, self._skew_coeffs(d))<EOL>skewval = top*(np.tanh(skew) + <NUM_LIT:1>) - top<EOL>return skewval*(<NUM_LIT:3>*x - x**<NUM_LIT:3>)<EOL>

returns the kurtosis parameter for direction d, d=0 is rho, d=1 is z


@memoize()<EOL><INDENT>def _kurtosis(self, x, z, d=<NUM_LIT:0>):<DEDENT>

val = self._poly(z, self._kurtosis_coeffs(d))<EOL>return (np.tanh(val)+<NUM_LIT:1>)/<NUM_LIT>*(<NUM_LIT:3> - <NUM_LIT:6>*x**<NUM_LIT:2> + x**<NUM_LIT:4>)<EOL>


def __init__(self, array, *args, **kwargs):

self.array = array<EOL>self.support = np.array(array.shape[<NUM_LIT:1>:])<EOL>super(FromArray, self).__init__(*args, params=['<STR_LIT>'], values=[<NUM_LIT:0>], **kwargs)<EOL>

Only thing to pass is the values of the point spread function (does not
need to be normalized) in the form of a numpy ndarray of shape

(z', z, y, x)

so if there are 50 layers in the image and the psf is at most 16 wide
then it must be shaped (50,16,16,16). The values of the psf must
be centered in this array. Hint: np.fft.fftfreq provides the correct
ordering of values for both even and odd lattices.


def __init__(self, order=(<NUM_LIT:1>,<NUM_LIT:1>,<NUM_LIT:1>), tileinfo=None, constval=None,<EOL>category='<STR_LIT>', shape=None, float_precision=np.float64):

self.shape = shape<EOL>self.order = order<EOL>self.tileinfo = tileinfo<EOL>self.category = category<EOL>c = category<EOL>if float_precision not in (np.float64, np.float32, np.float16):<EOL><INDENT>raise ValueError('<STR_LIT>' +<EOL>'<STR_LIT>')<EOL><DEDENT>self.float_precision = float_precision<EOL>params, values = [], []<EOL>self.param_term = {}<EOL>for order in product(*(range(o) for o in self.order)):<EOL><INDENT>p = c+'<STR_LIT>' % order<EOL>self.param_term[p] = order<EOL>params.append(p)<EOL>values.append(<NUM_LIT:0.0>)<EOL><DEDENT>if constval:<EOL><INDENT>values[<NUM_LIT:0>] = constval<EOL><DEDENT>super(Polynomial3D, self).__init__(<EOL>params=params, values=values, category=category<EOL>)<EOL>if self.shape:<EOL><INDENT>self.initialize()<EOL><DEDENT>

A polynomial 3D class for updating large fields of polys.

Parameters
----------
shape : `peri.util.Tile`
    shape of the field (z,y,x)

order : tuple
    number of terms in each direction

tileinfo : tuple of 2 `peri.util.Tile`
    These objects help in the transfer of fields from different
    sections of the same image to new fields. `tileinfo` is a tuple
    containing the Tile representing the entire image as well as the
    Tile representing this particular section of field. (typically
    given by `peri.rawimage.tile`)

constval : float
    The initial value of the entire field, if a constant.

float_precision : numpy float datatype
    One of numpy.float16, numpy.float32, numpy.float64; precision
    for precomputed arrays. Default is np.float64; make it 16 or 32
    to save memory.


super(LegendrePoly3D, self).__init__(*args, **kwargs)<EOL>


def __init__(self, order=(<NUM_LIT:1>,<NUM_LIT:1>,<NUM_LIT:1>), tileinfo=None, constval=None,<EOL>operation='<STR_LIT:*>', category='<STR_LIT>', shape=None,<EOL>float_precision=np.float64):

self.shape = shape<EOL>self.operation = operation<EOL>self.order = order<EOL>self.tileinfo = tileinfo<EOL>self.category = category<EOL>c = self.category<EOL>if float_precision not in (np.float64, np.float32, np.float16):<EOL><INDENT>raise ValueError('<STR_LIT>' +<EOL>'<STR_LIT>')<EOL><DEDENT>self.float_precision = float_precision<EOL>params, values = [], []<EOL>self.xy_param = {}<EOL>self.z_param = {}<EOL>for order in product(*(range(o) for o in self.order[<NUM_LIT:1>:][::-<NUM_LIT:1>])):<EOL><INDENT>p = c+'<STR_LIT>' % order<EOL>self.xy_param[p] = order<EOL>params.append(p)<EOL>values.append(<NUM_LIT:0.0>)<EOL><DEDENT>for order in range(self.order[<NUM_LIT:0>]):<EOL><INDENT>p = c+'<STR_LIT>' % order<EOL>self.z_param[p] = (order+<NUM_LIT:1>,)<EOL>params.append(p)<EOL>values.append(<NUM_LIT:0.0>)<EOL><DEDENT>Component.__init__(self, params, values, category=category)<EOL>if constval:<EOL><INDENT>self.set_values(c+'<STR_LIT>', constval)<EOL><DEDENT>if self.shape:<EOL><INDENT>self.initialize()<EOL><DEDENT>

A polynomial 2+1D class for updating large fields of polys.  The form
of these polynomials if P(x,y) () Q(z), separated in the z-direction.

Parameters
----------
shape : tuple
    shape of the field (z,y,x)

order : tuple
    number of terms in each direction

tileinfo : tuple of 2 `peri.util.Tile`
    These objects help in the transfer of fields from different
    sections of the same image to new fields. `tileinfo` is a tuple
    containing the Tile representing the entire image as well as the
    Tile representing this particular section of field. (typically
    given by `peri.rawimage.tile`)

constval : float
    The initial value of the entire field, if a constant.

operation : string
    Type of joining operation between the (x,y) and (z) poly. Can be
    either '*' or '+'

float_precision : numpy float datatype
    One of numpy.float16, numpy.float32, numpy.float64; precision
    for precomputed arrays. Default is np.float64; make it 16 or 32
    to save memory.


def __init__(self, npts=(<NUM_LIT>,<NUM_LIT:20>), zorder=<NUM_LIT:7>, op='<STR_LIT:*>', barnes_dist=<NUM_LIT>,<EOL>barnes_clip_size=<NUM_LIT:3>, local_updates=True, category='<STR_LIT>', shape=None,<EOL>float_precision=np.float64, donorm=True):

self.shape = shape<EOL>self.local_updates = local_updates<EOL>self.barnes_clip_size = barnes_clip_size<EOL>self.barnes_dist = barnes_dist<EOL>self.category = category<EOL>self.zorder = zorder<EOL>self.npts = npts<EOL>self.op = op<EOL>if float_precision not in (np.float64, np.float32, np.float16):<EOL><INDENT>raise ValueError('<STR_LIT>' +<EOL>'<STR_LIT>')<EOL><DEDENT>self.float_precision = float_precision<EOL>c = self.category<EOL>params, values = [c+'<STR_LIT>', c+'<STR_LIT>'], [<NUM_LIT:1.0>, <NUM_LIT:0.0>]<EOL>self.barnes_params, p, v = self._setup_barnes_params()<EOL>params.extend(p)<EOL>values.extend(v)<EOL>self.poly_params = {c+'<STR_LIT>' % i:i+<NUM_LIT:1> for i in range(zorder)}<EOL>params.extend(self.poly_params.keys())<EOL>values.extend([<NUM_LIT:0.0>]*len(self.poly_params))<EOL>super(BarnesPoly, self).__init__(<EOL>params=params, values=values, category=category<EOL>)<EOL>self._norm_stat = None<EOL>if self.shape:<EOL><INDENT>self.initialize()<EOL><DEDENT>

Superclass for ilms of the form Barnes * poly

Parameters
----------
shape : iterable
    size of the field in pixels, needs to be padded shape

npts : tuple of ints, optional
    Number of control points used for the Barnes interpolant b_k
    in the x-y sum. Default is (40,20)

zorder : integer
    Number of orders for the z-polynomial.

op : string
    The operation to perform between Barnes and LegPoly, '*' or '+'.

barnes_dist : float
    Fractional distance to use for the barnes interpolator

local_updates : boolean
    Whether to perform local updates on the ILM

float_precision : numpy float datatype
    One of numpy.float16, numpy.float32, numpy.float64; precision
    for precomputed arrays. Default is np.float64; make it 16 or 32
    to save memory.


raise NotImplementedError('<STR_LIT>')<EOL>

Returns a possibly-nested list barnes_params, and a flat list of
        the params and values for each of the barnes params


self.donorm = donorm<EOL>super(BarnesStreakLegPoly2P1D, self).__init__(npts=npts, zorder=zorder,<EOL>op=op, barnes_dist=barnes_dist, barnes_clip_size=barnes_clip_size,<EOL>local_updates=local_updates, category=category, shape=shape,<EOL>float_precision=float_precision)<EOL>

A Barnes interpolant. This one is of the form

.. math::
    I = \\left[1 + \\left(\\sum b_k(x) (o) L_k(y)\\right)\\right]  (1 + z q(z)) + c

where b_k are independent barnes interpolants and L_k are legendre
polynomials. q is a polynomial strictly in z. Additionally, the
operation (o) is settable.

Parameters
----------
shape : iterable
    size of the field in pixels, needs to be padded shape

npts : tuple of ints, optional
    Number of control points used for the Barnes interpolant b_k
    in the x-y sum. Default is (40,20)

zorder : integer
    Number of orders for the z-polynomial.

op : string
    The operation to perform between Barnes and LegPoly, '*' or '+'.

barnes_dist : float
    Fractional distance to use for the barnes interpolator

local_updates : boolean
    Whether to perform local updates on the ILM

float_precision : numpy float datatype
    One of numpy.float16, numpy.float32, numpy.float64; precision
    for precomputed arrays. Default is np.float64; make it 16 or 32
    to save memory.

donorm : Bool
    Whether or not to normalize the Barnes interpolation
    (compatibility patch). Use True, i.e. normalize the Barnes
    interpolant. Old version is False. Default is True.