Exemple #1
0
    def __init__(self, image_data=None, interpolation_order=3):
        super(self.__class__, self).__init__()
        self.image = image_data
        self.interpolation_order = interpolation_order

        if self.image is not None:
            self.mdh = NestedClassMDHandler(self.image.mdh)
        else:
            self.mdh = None
Exemple #2
0
    def mdh(self):
        mdh = NestedClassMDHandler(self._mdh)
        mdh['Pyramid.Depth'] = self.depth
        mdh['Pyramid.NTilesX'] = self.n_tiles_x
        mdh['Pyramid.NTilesY'] = self.n_tiles_y
        mdh['Pyramid.PixelsX'] = self.n_tiles_x * self.tile_size
        mdh['Pyramid.PixelsY'] = self.n_tiles_y * self.tile_size

        return mdh
    def __init__(self,
                 storage_directory,
                 pyramid_tile_size=256,
                 mdh=None,
                 n_tiles_x=0,
                 n_tiles_y=0,
                 depth=0,
                 x0=0,
                 y0=0,
                 pixel_size=1,
                 backend=PZFTileIO):

        if isinstance(storage_directory, tempfile.TemporaryDirectory):
            # If the storage directory is a temporary directory, keep a reference and cleanup the directory when we delete the pyramid
            # used to support transitory pyramids.
            self._temp_directory = storage_directory
            storage_directory = storage_directory.name

        if unifiedIO.is_cluster_uri(storage_directory):
            assert (backend == ClusterPZFTileIO)

            storage_directory, _ = unifiedIO.split_cluster_url(
                storage_directory)

        self.base_dir = storage_directory
        self.tile_size = pyramid_tile_size

        self.pyramid_valid = False

        self._mdh = NestedClassMDHandler(mdh)
        self._mdh['Pyramid.TileSize'] = self.tile_size

        self.n_tiles_x = n_tiles_x
        self.n_tiles_y = n_tiles_y
        self.depth = depth

        self.x0 = x0
        self.y0 = y0
        self.pixel_size = pixel_size
        # TODO - should we be re-assigning these on load, not just when we create a new pyramid?
        self._mdh['Pyramid.x0'] = x0
        self._mdh['Pyramid.y0'] = y0
        self._mdh['Pyramid.PixelSize'] = pixel_size

        if (not os.path.exists(self.base_dir)) and (not backend
                                                    == ClusterPZFTileIO):
            os.makedirs(self.base_dir)

        #self._tilecache = TileCache()

        if backend is None:
            backend = infer_tileio_backend(self.base_dir)

        self._imgs = backend(base_dir=self.base_dir, suff='img')
        self._acc = backend(base_dir=self.base_dir, suff='acc')
        self._occ = backend(base_dir=self.base_dir, suff='occ')
    def OnGenEvents(self, event):
        from PYME.simulation import locify
        #from PYME.Acquire.Hardware.Simulator import wormlike2
        from PYME.IO import tabular
        from PYME.IO.image import ImageBounds
        # import pylab
        import matplotlib.pyplot as plt
        
        #wc = wormlike2.wormlikeChain(100)
        
        pipeline = self.visFr.pipeline
        pipeline.filename='Simulation'

        plt.figure()
        plt.plot(self.xp, self.yp, 'x') #, lw=2)
        if isinstance(self.source, WormlikeSource):
            plt.plot(self.xp, self.yp, lw=2)

        if self.mode == 'STORM':
            res = locify.eventify(self.xp, self.yp, self.meanIntensity, self.meanDuration, self.backgroundIntensity,
                                  self.meanEventNumber, self.scaleFactor, self.meanTime, z=self.zp)
        else:
            res = locify.eventify2(self.xp, self.yp, self.meanIntensity, self.meanDuration, self.backgroundIntensity,
                                  self.meanEventNumber, self.scaleFactor, self.meanTime, z=self.zp)
        
        plt.plot(res['fitResults']['x0'],res['fitResults']['y0'], '+')

        ds = tabular.MappingFilter(tabular.FitResultsSource(res))
        
        if isinstance(self.source, ImageSource):
            pipeline.imageBounds = image.openImages[self.source.image].imgBounds
        else:
            pipeline.imageBounds = ImageBounds.estimateFromSource(ds)
            
        pipeline.addDataSource('Generated Points', ds)
        pipeline.selectDataSource('Generated Points')

        from PYME.IO.MetaDataHandler import NestedClassMDHandler
        pipeline.mdh = NestedClassMDHandler()
        pipeline.mdh['Camera.ElectronsPerCount'] = 1
        pipeline.mdh['Camera.TrueEMGain'] = 1
        pipeline.mdh['Camera.CycleTime'] = 1
        pipeline.mdh['voxelsize.x'] = .110

        try:
            pipeline.filterKeys.pop('sig')
        except:
            pass

        pipeline.Rebuild()
        if len(self.visFr.layers) < 1:
            self.visFr.add_pointcloud_layer() #TODO - move this logic so that layer added automatically when datasource is added?
        #self.visFr.CreateFoldPanel()
        self.visFr.SetFit()
Exemple #5
0
def nPhotons(fitMod,fr,mdh,psfname=None,nmax=100,progressBar=None,updateStep=100):
    mdh2 = NestedClassMDHandler(mdh)
    if psfname is not None:
        mdh2['PSFFile'] = psfname
    npoints = min(fr.shape[0],nmax)
    nph = np.zeros((npoints))
    us = int(updateStep)
    for i in range(npoints):
        nph[i] = get_photons(genFitImage(fitMod,fr[i],mdh2,psfname=None), mdh2)
        if (progressBar is not None) and ((i % us) == 0):
            progressBar.Update(100.0*i/float(npoints))
            wx.Yield()
    return nph
Exemple #6
0
    def rebuild(self, event=None):
        self.tree.DeleteRoot()

        self.root = self.tree.AddRoot("Metadata")
        self.tree.SetItemText(self.root, "root", 0)

        nmdh = NestedClassMDHandler(self.mdh)
        self.addEntries(nmdh, self.root)

        if wx.__version__ > '4':
            self.tree.ExpandAll()  #self.root)
        else:
            self.tree.ExpandAll(self.root)
def generate_uniform_map(source):
    logger.warning('Simulating uniform maps - use with care')

    sensorSize = get_sensor_size(source.mdh)

    mfull, vefull, mapmdh = insert_into_full_map(None,
                                                 None,
                                                 source.mdh,
                                                 sensor_size=sensorSize)
    mapmdh['CameraMap.Uniform'] = True

    mmd = NestedClassMDHandler(mapmdh)
    mmd['CameraMap.Type'] = 'mean'
    mmd['CameraMap.Units'] = 'ADU'

    vmd = NestedClassMDHandler(mapmdh)
    vmd['CameraMap.Type'] = 'variance'
    vmd['CameraMap.Units'] = 'electrons^2'

    im_dark = ImageStack(mfull, mdh=mmd)
    im_variance = ImageStack(vefull, mdh=vmd)

    return im_dark, im_variance
Exemple #8
0
def get_psf():
    from PYME.IO.image import ImageStack
    from PYME.IO.MetaDataHandler import NestedClassMDHandler

    mdh = NestedClassMDHandler()
    mdh['ImageType'] = 'PSF'
    mdh['voxelsize.x'] = dx / 1e3
    mdh['voxelsize.y'] = dy / 1e3
    mdh['voxelsize.z'] = dz / 1e3

    im = ImageStack(data=[c for c in interpModel_by_chan if not c is None],
                    mdh=mdh,
                    titleStub='Simulated PSF')

    return im
Exemple #9
0
    def OnProcPoints(self, event=None):
        try:
            points = self.dsviewer.view.points
        except AttributeError:
            Warn(None, 'no object locations found')
            return

        if len(self.dsviewer.view.points) < 1:
            Warn(None, 'object location list empty')
            return

        if not self.procPtsSel.configure_traits(kind='modal'):
            return

        xp = np.rint(self.dsviewer.view.points[:, 0])
        yp = np.rint(self.dsviewer.view.points[:, 1])

        mindistnm = self.procPtsSel.minimal_distance_in_nm  # make this an option
        mindistpix = mindistnm / (1e3 * self.dsviewer.image.mdh.voxelsize.x)
        # here we need some code to remove points with NND < mindist
        xd = np.subtract.outer(xp, xp)
        yd = np.subtract.outer(yp, yp)
        d = np.sqrt(xd**2 + yd**2)
        np.fill_diagonal(d, 1e6)
        dmin = d.min(0)
        xp2 = xp[dmin >= mindistpix]
        yp2 = yp[dmin >= mindistpix]

        imd = np.zeros(self.dsviewer.image.data.shape[0:2])
        imd[xp2.astype('i'), yp2.astype('i')] = 1
        sigma = self.procPtsSel.sigma_for_Gaussian_blur  # in future may make this a config parameter
        imf = gaussian_filter(imd, sigma)

        im = ImageStack(imf, titleStub='object positions')
        mdh2 = NestedClassMDHandler(self.dsviewer.image.mdh)
        im.mdh.copyEntriesFrom(mdh2)

        if self.dsviewer.mode == 'visGUI':
            mode = 'visGUI'
        else:
            mode = 'lite'

        dv = ViewIm3D(im,
                      mode=mode,
                      glCanvas=self.dsviewer.glCanvas,
                      parent=wx.GetTopLevelParent(self.dsviewer))
def prefillSampleData(parent):
    #global currentSlide
    global slideMD

    dlg = SampleInfoDialog(parent, acquiring=False)
    slideMD = NestedClassMDHandler(
    )  # provide a new clean copy - otherwise we keep unset fields from last run

    if dlg.ShowModal() == wx.ID_OK:
        dlg.PopulateMetadata(slideMD, False)
        # print slideMD
        print('bar')
        print((dlg.slide))
        currentSlide[0] = dlg.slide
        print(currentSlide)
    else:
        currentSlide[0] = None

    dlg.Destroy()
Exemple #11
0
    def execute(self, namespace):
        from PYME.Analysis.points import spherical_harmonics
        from PYME.IO.MetaDataHandler import NestedClassMDHandler

        inp = namespace[self.inputName]
        mapped = tabular.MappingFilter(inp)

        rep = namespace[self.inputSphericalHarmonics]

        center = rep.mdh['Processing.SphericalHarmonicShell.Centre']
        z_scale = rep.mdh['Processing.SphericalHarmonicShell.ZScale']
        x0, y0, z0 = center

        # calculate theta, phi, and rad for each localization in the pipeline
        theta, phi, datRad = spherical_harmonics.cart2sph(
            inp['x'] - x0, inp['y'] - y0, (inp['z'] - z0) / z_scale)
        # additionally calculate the cartesian distance
        min_distance, nearest_point_on_shell = spherical_harmonics.distance_to_surface(
            [inp['x'], inp['y'], inp['z']],
            center,
            rep['modes'],
            rep['coefficients'],
            z_scale=z_scale)
        mapped.addColumn(self.input_name_r, datRad)
        mapped.addColumn(self.input_name_theta, theta)
        mapped.addColumn(self.input_name_phi, phi)
        mapped.addColumn(
            self.input_name_r_norm,
            datRad / spherical_harmonics.reconstruct_from_modes(
                rep['modes'], rep['coefficients'], theta, phi))
        mapped.addColumn(self.input_name_distance_to_shell, min_distance)

        try:
            # note that copying overwrites shared fields
            mapped.mdh = NestedClassMDHandler(rep.mdh)
            mapped.mdh.copyEntriesFrom(inp.mdh)
        except AttributeError:
            pass

        namespace[self.outputName] = mapped
Exemple #12
0
    def OnExtractMultiviewPSF(self, event):
        if (len(self.PSFLocs) > 0):
            from PYME.Analysis.PSFEst import extractImages

            psfROISize = [int(s) for s in self.tPSFROI.GetValue().split(',')]
            psfBlur = [float(s) for s in self.tPSFBlur.GetValue().split(',')]

            psfs = []

            for chnum in range(self.image.data.shape[3]):
                alignZ = (chnum > 0) and self.cbAlignZ.GetValue()
                #always align the first channel

                psf, offsets = extractImages.getPSF3D(
                    self.image.data[:, :, :, chnum],
                    self.PSFLocs,
                    psfROISize,
                    psfBlur,
                    centreZ=alignZ,
                    expand_z=self.cbExpandROI.GetValue())

                if self.cbBackgroundCorrect.GetValue():
                    #widefield image - do special background subtraction
                    psf = extractImages.backgroundCorrectPSFWF(psf)

                psfs.append(psf)

            from PYME.DSView.dsviewer import ImageStack, ViewIm3D
            from PYME.IO.MetaDataHandler import NestedClassMDHandler

            mdh = NestedClassMDHandler(self.image.mdh)
            self.write_metadata(mdh, 'Multiview')
            mdh['ImageType'] = 'PSF'

            im = ImageStack(data=psfs, mdh=mdh, titleStub='Extracted PSF')
            im.defaultExt = '*.tif'  #we want to save as PSF by default
            ViewIm3D(im,
                     mode='psf',
                     parent=wx.GetTopLevelParent(self.dsviewer))
Exemple #13
0
    def __init__(self,
                 storage_directory,
                 pyramid_tile_size=256,
                 mdh=None,
                 n_tiles_x=0,
                 n_tiles_y=0,
                 depth=0,
                 x0=0,
                 y0=0,
                 pixel_size=1):
        self.base_dir = storage_directory
        self.tile_size = pyramid_tile_size

        self.pyramid_valid = False

        self._mdh = NestedClassMDHandler(mdh)
        self._mdh['Pyramid.TileSize'] = self.tile_size

        self.n_tiles_x = n_tiles_x
        self.n_tiles_y = n_tiles_y
        self.depth = depth

        self.x0 = x0
        self.y0 = y0
        self.pixel_size = pixel_size
        # TODO - should we be re-assigning these on load, not just when we create a new pyramid?
        self._mdh['Pyramid.x0'] = x0
        self._mdh['Pyramid.y0'] = y0
        self._mdh['Pyramid.PixelSize'] = pixel_size

        if not os.path.exists(self.base_dir):
            os.makedirs(self.base_dir)

        #self._tilecache = TileCache()

        self._imgs = PZFTileIO(base_dir=self.base_dir, suff='img')
        self._acc = PZFTileIO(base_dir=self.base_dir, suff='acc')
        self._occ = PZFTileIO(base_dir=self.base_dir, suff='occ')
    def OnGenEvents(self, event):
        from PYME.simulation import locify
        #from PYME.Acquire.Hardware.Simulator import wormlike2
        from PYME.IO import tabular
        from PYME.IO.image import ImageBounds
        # import pylab
        import matplotlib.pyplot as plt

        #wc = wormlike2.wormlikeChain(100)

        pipeline = self.visFr.pipeline
        pipeline.filename = 'Simulation'

        plt.figure()
        plt.plot(self.xp, self.yp, 'x')  #, lw=2)
        if isinstance(self.source, WormlikeSource):
            plt.plot(self.xp, self.yp, lw=2)

        if self.mode == 'STORM':
            res = locify.eventify(self.xp,
                                  self.yp,
                                  self.meanIntensity,
                                  self.meanDuration,
                                  self.backgroundIntensity,
                                  self.meanEventNumber,
                                  self.scaleFactor,
                                  self.meanTime,
                                  z=self.zp)
        else:
            res = locify.eventify2(self.xp,
                                   self.yp,
                                   self.meanIntensity,
                                   self.meanDuration,
                                   self.backgroundIntensity,
                                   self.meanEventNumber,
                                   self.scaleFactor,
                                   self.meanTime,
                                   z=self.zp)

        plt.plot(res['fitResults']['x0'], res['fitResults']['y0'], '+')

        ds = tabular.MappingFilter(tabular.FitResultsSource(res))

        try:
            # some data sources (current ImageSource) have image bound info. Use this if available
            # this could fail on either an AttributeError (if the data source doesn't implement bounds
            # or another error if something fails in get_bounds(). Only catch the AttributeError, as we have
            # should not be handling other errors here.
            pipeline.imageBounds = self.source.get_bounds()
        except AttributeError:
            pipeline.imageBounds = ImageBounds.estimateFromSource(ds)

        pipeline.addDataSource('Generated Points', ds)
        pipeline.selectDataSource('Generated Points')

        from PYME.IO.MetaDataHandler import NestedClassMDHandler
        pipeline.mdh = NestedClassMDHandler()
        pipeline.mdh['Camera.ElectronsPerCount'] = 1
        pipeline.mdh['Camera.TrueEMGain'] = 1
        pipeline.mdh['Camera.CycleTime'] = 1
        pipeline.mdh['voxelsize.x'] = .110
        # some info about the parameters
        pipeline.mdh['GeneratedPoints.MeanIntensity'] = self.meanIntensity
        pipeline.mdh['GeneratedPoints.MeanDuration'] = self.meanDuration
        pipeline.mdh['GeneratedPoints.MeanEventNumber'] = self.meanEventNumber
        pipeline.mdh[
            'GeneratedPoints.BackgroundIntensity'] = self.backgroundIntensity
        pipeline.mdh['GeneratedPoints.ScaleFactor'] = self.scaleFactor
        pipeline.mdh['GeneratedPoints.MeanTime'] = self.meanTime
        pipeline.mdh['GeneratedPoints.Mode'] = self.mode
        # the source info
        self.source.genMetaData(pipeline.mdh)

        try:
            pipeline.filterKeys.pop('sig')
        except:
            pass

        pipeline.Rebuild()
        if len(self.visFr.layers) < 1:
            self.visFr.add_pointcloud_layer(
            )  #TODO - move this logic so that layer added automatically when datasource is added?
        #self.visFr.CreateFoldPanel()
        self.visFr.SetFit()
Exemple #15
0
    def execute(self, namespace):
        from PYME.Analysis.points import twoColour
        from PYME.Analysis.points import multiview
        from PYME.IO.MetaDataHandler import NestedClassMDHandler

        inp = namespace[self.input_name]

        try:  # make sure we're looking at multiview data
            n_chan = inp.mdh['Multiview.NumROIs']
        except AttributeError:
            raise AttributeError('multiview metadata is missing or incomplete')

        # sort in frame order
        I = inp['tIndex'].argsort()
        x_sort, y_sort = inp['x'][I], inp['y'][I]
        chan_sort = inp['multiviewChannel'][I]

        clump_id, keep = multiview.pair_molecules(
            inp['tIndex'][I],
            x_sort,
            y_sort,
            chan_sort,
            self.search_radius_nm * np.ones_like(x_sort),
            appear_in=np.arange(n_chan),
            n_frame_sep=inp['tIndex'].max(),
            pix_size_nm=1e3 * inp.mdh['voxelsize.x'])

        # only look at the clumps which showed up in all channels
        x = x_sort[keep]
        y = y_sort[keep]
        chan = chan_sort[keep]
        clump_id = clump_id[keep]

        # Generate raw shift vectors (map of displacements between channels) for each channel
        mol_list = np.unique(clump_id)
        n_mols = len(mol_list)

        dx = np.zeros((n_chan - 1, n_mols))
        dy = np.zeros_like(dx)
        dx_err = np.zeros_like(dx)
        dy_err = np.zeros_like(dx)
        x_clump, y_clump, x_std, y_std, x_shifted, y_shifted = [], [], [], [], [], []

        shift_map_dtype = [
            ('mx', '<f4'),
            ('mx2', '<f4'),
            ('mx3', '<f4'),  # x terms
            ('my', '<f4'),
            ('my2', '<f4'),
            ('my3', '<f4'),  # y terms
            ('mxy', '<f4'),
            ('mx2y', '<f4'),
            ('mxy2', '<f4'),  # cross terms
            ('x0', '<f4')
        ]  # 0th order shift

        shift_maps = np.zeros(2 * (n_chan - 1), dtype=shift_map_dtype)
        mdh = NestedClassMDHandler(inp.mdh)
        mdh['Multiview.shift_map.legend'] = {}

        for ii in range(n_chan):
            chan_mask = (chan == ii)
            x_chan = np.zeros(n_mols)
            y_chan = np.zeros(n_mols)
            x_chan_std = np.zeros(n_mols)
            y_chan_std = np.zeros(n_mols)

            for ind in range(n_mols):
                # merge clumps within channels
                clump_mask = np.where(
                    np.logical_and(chan_mask, clump_id == mol_list[ind]))
                x_chan[ind] = x[clump_mask].mean()
                y_chan[ind] = y[clump_mask].mean()
                x_chan_std[ind] = x[clump_mask].std()
                y_chan_std[ind] = y[clump_mask].std()

            x_clump.append(x_chan)
            y_clump.append(y_chan)
            x_std.append(x_chan_std)
            y_std.append(y_chan_std)

            if ii > 0:
                dx[ii - 1, :] = x_clump[0] - x_clump[ii]
                dy[ii - 1, :] = y_clump[0] - y_clump[ii]
                dx_err[ii - 1, :] = np.sqrt(x_std[ii]**2 + x_std[0]**2)
                dy_err[ii - 1, :] = np.sqrt(y_std[ii]**2 + y_std[0]**2)
                # generate shiftmap between ii-th channel and the 0th channel
                dxx, dyy, spx, spy, good = twoColour.genShiftVectorFieldQ(
                    x_clump[0], y_clump[0], dx[ii - 1, :], dy[ii - 1, :],
                    dx_err[ii - 1, :], dy_err[ii - 1, :])
                # store shiftmaps in structured array
                mdh['Multiview.shift_map.legend']['Chan0%s.X' %
                                                  ii] = 2 * (ii - 1)
                mdh['Multiview.shift_map.legend']['Chan0%s.Y' %
                                                  ii] = 2 * (ii - 1) + 1
                for ki in range(len(shift_map_dtype)):
                    k = shift_map_dtype[ki][0]
                    shift_maps[2 * (ii - 1)][k] = spx.__getattribute__(k)
                    shift_maps[2 * (ii - 1) + 1][k] = spy.__getattribute__(k)

                # shift_maps['Chan0%s.X' % ii], shift_maps['Chan0%s.Y' % ii] = spx.__dict__, spy.__dict__

        mdh['Multiview.shift_map.model'] = '.'.join(
            [spx.__class__.__module__, spx.__class__.__name__])

        namespace[self.output_name] = tabular.RecArraySource(shift_maps)
        namespace[self.output_name].mdh = mdh
Exemple #16
0
    def __init__(self, parent, mdh, editable=True, refreshable=True):
        self.mdh = mdh
        wx.Panel.__init__(self, parent, -1)
        #self.Bind(wx.EVT_SIZE, self.OnSize)

        sizer1 = wx.BoxSizer(wx.VERTICAL)

        self.tree = MyTreeListCtrl(
            self,
            -1,
            style=wx.TR_DEFAULT_STYLE
            #| wx.TR_HAS_BUTTONS
            #| wx.TR_TWIST_BUTTONS
            #| wx.TR_ROW_LINES
            | wx.TR_EDIT_LABELS
            #| wx.TR_COLUMN_LINES
            #| wx.TR_NO_LINES
            | wx.TR_FULL_ROW_HIGHLIGHT)

        # create some columns
        self.tree.AddColumn("Entry")
        self.tree.AddColumn("Value")

        self.tree.SetMainColumn(0)  # the one with the tree in it...
        self.tree.SetColumnWidth(0, 300)
        self.tree.SetColumnWidth(1, 300)

        self.root = self.tree.AddRoot("Metadata")
        self.tree.SetItemText(self.root, "root", 0)

        self.paths = {}

        nmdh = NestedClassMDHandler(mdh)
        self.addEntries(nmdh, self.root)

        if editable:
            self.editableCols = [1]
        else:
            self.editableCols = []

        #entryNames = self.mdh.getEntryNames()

#        for k in nmdh.__dict__.keys():
#            #txt = "Item %d" % x
#            child = self.tree.AppendItem(self.root, k)
#            self.tree.SetItemText(child, txt + "(c1)", 1)

        if wx.__version__ > '4':
            self.tree.ExpandAll()  #self.root)
        else:
            self.tree.ExpandAll(self.root)

        #self.tree.GetMainWindow().Bind(wx.EVT_LEFT_DOWN, self.OnRightDown)
        self.tree.GetMainWindow().Bind(wx.EVT_LEFT_UP, self.OnRightUp)
        self.tree.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnEndEdit)
        self.tree.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.OnBeginEdit)
        #self.tree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnActivate)

        sizer1.Add(self.tree, 1, wx.EXPAND, 0)

        if refreshable:
            bRefresh = wx.Button(self, -1, 'Refresh')
            bRefresh.Bind(wx.EVT_BUTTON, self.rebuild)

            sizer1.Add(bRefresh, 0, wx.ALL | wx.ALIGN_RIGHT, 5)

        self.SetSizerAndFit(sizer1)
Exemple #17
0
def main():
    logging.basicConfig(
    )  # without it got 'No handlers could be found for logger...'

    defaultSensorSize = (
        2048, 2048
    )  # we currently assume this is correct but could be chosen based
    # on camera model in meta data TODO - add CCD size to camera metadata
    darkthreshold = 1e4  # this really should depend on the gain mode (12bit vs 16 bit etc)
    variancethreshold = 300**2  # again this is currently picked fairly arbitrarily
    blemishvariance = 1e8

    # options parsing
    op = argparse.ArgumentParser(
        description='generate offset and variance maps from darkseries.')
    op.add_argument('filename',
                    metavar='filename',
                    nargs='?',
                    default=None,
                    help='filename of the darkframe series')
    op.add_argument('-s',
                    '--start',
                    type=int,
                    default=0,
                    help='start frame to use')
    op.add_argument('-e',
                    '--end',
                    type=int,
                    default=-1,
                    help='end frame to use')
    op.add_argument('-u',
                    '--uniform',
                    action='store_true',
                    help='make uniform map using metadata info')
    op.add_argument(
        '-i',
        '--install',
        action='store_true',
        help='install map in default location - the filename argument is a map'
    )
    op.add_argument(
        '-d',
        '--dir',
        metavar='destdir',
        default=None,
        help='destination directory (default is PYME calibration path)')
    op.add_argument('-l',
                    '--list',
                    action='store_true',
                    help='list all maps in default location')
    op.add_argument('-p',
                    '--prefix',
                    metavar='prefix',
                    default='',
                    help='prefix for dark/variance map filenames')

    args = op.parse_args()

    if args.list:
        listCalibrationDirs()
        sys.exit(0)

    # body of script
    filename = args.filename
    prefix = args.prefix

    if filename is None:
        op.error('need a file name if -l or --list not requested')

    if args.install:
        #copy the map to the default maps directory
        install_map(filename)
        sys.exit(0)

    logger.info('Opening image series...')
    source = ImageStack(filename=filename)

    start = args.start
    end = args.end
    if end < 0:
        end = int(source.dataSource.getNumSlices() + end)

    # pre-checks before calculations to minimise the pain
    sensorSize = list(defaultSensorSize)
    try:
        sensorSize[0] = source.mdh['Camera.SensorWidth']
    except AttributeError:
        logger.warning('no valid sensor width in metadata - using default %d' %
                       sensorSize[0])
    try:
        sensorSize[1] = source.mdh['Camera.SensorHeight']
    except AttributeError:
        logger.warning(
            'no valid sensor height in metadata - using default %d' %
            sensorSize[1])

    if not ((source.mdh['Camera.ROIWidth'] == sensorSize[0]) and
            (source.mdh['Camera.ROIHeight'] == sensorSize[1])):
        logger.warning(
            'Generating a map from data with ROI set. Use with EXTREME caution.\nMaps should be calculated from the whole chip.'
        )

        if args.dir is None:
            logger.error(
                'Maps with an ROI set cannot be stored to the default map directory\nPlease specify an output directory.'
            )
            sys.exit(-1)

    logger.info('Calculating mean and variance...')

    m, ve = (None, None)
    if not args.uniform:
        m, v = _meanvards(source.dataSource, start=start, end=end)
        eperADU = source.mdh['Camera.ElectronsPerCount']
        ve = v * eperADU * eperADU
        # occasionally the cameras seem to have completely unusable pixels
        # one example was dark being 65535 (i.e. max value for 16 bit)
        if m.max() > darkthreshold:
            ve[m > darkthreshold] = blemishvariance
        if ve.max() > variancethreshold:
            ve[ve > variancethreshold] = blemishvariance
        nbad = np.sum((m > darkthreshold) * (ve > variancethreshold))
    else:
        logger.warning('Simulating uniform maps - use with care')
        nbad = 0

        if args.dir is None:
            logger.error(
                'Uniform maps cannot be stored to the default map directory\nPlease specify an output directory.'
            )
            sys.exit(-1)

    # if the uniform flag is set, then m and ve are passed as None
    # which makes sure that just the uniform defaults from meta data are used
    mfull, vefull, basemdh = insert_into_full_map(m,
                                                  ve,
                                                  source.mdh,
                                                  sensor_size=sensorSize)

    logger.info('Saving results...')

    if args.dir is None:
        logger.info('installing in standard location...')
        mname = mkDefaultPath('dark', source.mdh)
        vname = mkDefaultPath('variance', source.mdh)
    else:
        mname = mkDestPath(args.dir, prefix + 'dark', source.mdh)
        vname = mkDestPath(args.dir, prefix + 'variance', source.mdh)

    logger.info('dark map -> %s...' % mname)
    logger.info('var  map -> %s...' % vname)

    commonMD = NestedClassMDHandler()
    commonMD.setEntry('Analysis.name', 'mean-variance')
    commonMD.setEntry('Analysis.start', start)
    commonMD.setEntry('Analysis.end', end)
    commonMD.setEntry('Analysis.SourceFilename', filename)
    commonMD.setEntry('Analysis.darkThreshold', darkthreshold)
    commonMD.setEntry('Analysis.varianceThreshold', variancethreshold)
    commonMD.setEntry('Analysis.blemishVariance', blemishvariance)
    commonMD.setEntry('Analysis.NBadPixels', nbad)

    if args.uniform:
        commonMD.setEntry('Analysis.isuniform', True)

    mmd = NestedClassMDHandler(basemdh)
    mmd.copyEntriesFrom(commonMD)
    mmd.setEntry('Analysis.resultname', 'mean')
    mmd.setEntry('Analysis.units', 'ADU')

    vmd = NestedClassMDHandler(basemdh)
    vmd.copyEntriesFrom(commonMD)
    vmd.setEntry('Analysis.resultname', 'variance')
    vmd.setEntry('Analysis.units', 'electrons^2')

    ImageStack(mfull, mdh=mmd).Save(filename=mname)
    ImageStack(vefull, mdh=vmd).Save(filename=vname)
Exemple #18
0
from PYME.contrib import TextCtrlAutoComplete

#from PYME.SampleDB2 import populate #just to setup the Django environment
#from PYME.SampleDB2.samples import models

lastCreator = nameUtils.getUsername()
lastSlideRef = ''

currentSlide = [None]

WantSlideChangeNotification = []

from PYME.IO import MetaDataHandler
from PYME.IO.MetaDataHandler import NestedClassMDHandler

slideMD = NestedClassMDHandler()

if 'PYME_DATABASE_HOST' in os.environ.keys():
    dbhost = os.environ['PYME_DATABASE_HOST']
else:
    dbhost = 'dbsrv1'


class AutoWidthListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
    def __init__(self,
                 parent,
                 ID,
                 pos=wx.DefaultPosition,
                 size=wx.DefaultSize,
                 style=0):
        wx.ListCtrl.__init__(self, parent, ID, pos, size, style)
#	name = 'Andor IXon DV97'
#	ADOffset = 1100 #counts (@ T ~ -70, em gain ~ 150)
#	ReadNoise = 109.8 #electrons
#	noiseFactor = 1.41
#	electronsPerCount = 27.32
#
#
#class MetaData:
#	def __init__(self, voxSize, CCDMD = None):
#		self.voxelsize = voxSize
#		self.CCD = CCDMD
#
##FIXME - THIS SHOULD ALL BE EXTRACTED FROM LOG FILES OR THE LIKE
#TIRFDefault = MetaData(VoxelSize(0.07, 0.07, 0.2), CCDMetaDataIXonDefault())

TIRFDefault = NestedClassMDHandler()

#voxelsize
TIRFDefault.setEntry('voxelsize.x', 0.07)
TIRFDefault.setEntry('voxelsize.y', 0.07)
TIRFDefault.setEntry('voxelsize.z', 0.2)
TIRFDefault.setEntry('voxelsize.units', 'um')

#camera properties - for Andor camera - see above
#TIRFDefault.setEntry('Camera.ADOffset',1100)
TIRFDefault.setEntry('Camera.ReadNoise', 109.8)
TIRFDefault.setEntry('Camera.NoiseFactor', 1.41)
TIRFDefault.setEntry('Camera.ElectronsPerCount', 27.32)
TIRFDefault.setEntry(
    'Camera.TrueEMGain', 20
)  #mostly use gain register setting of 150 - this will hopefully be overwitten
def insert_into_full_map(dark, variance, metadata, sensor_size=(2048, 2048)):
    """

    Embeds partial-sensor camera maps into full-sized camera map by padding with basic values in metadata. Alternatively
    can be used to create boring maps to use in place of metadata scalars.

    Parameters
    ----------
    dark: ndarray or None
        darkmap for valid ROI, or None to generate a uniform, ~useless metadata map
    variance: ndarray
        variance for valid ROI, or None to generate a uniform, ~useless metadata map
    metadata: MetaDataHandler instance
        ROI informatrion and camera noise parameters to use when padding maps
    sensor_size: 2-int tuple
        x and y camera sensor size

    Returns
    -------
    full_dark: ndarray
        padded dark map
    full_var: ndarray
        padded variance map
    mdh: PYME.IO.MetadataHandler.NestedClassMDHandler
        metadata handler to be associated with full maps while maintaining information about the original/valid ROI.
    """

    mdh = NestedClassMDHandler(metadata)
    x_origin, y_origin = get_camera_roi_origin(mdh)

    if not ((x_origin == 0) and (y_origin == 0) and
            (metadata['Camera.ROIWidth'] == sensor_size[0]) and
            (metadata['Camera.ROIHeight'] == sensor_size[1])):
        mdh['CameraMap.SubROI'] = True

    mdh['CameraMap.ValidROI.ROIOriginX'] = x_origin
    mdh['CameraMap.ValidROI.ROIOriginY'] = y_origin
    mdh['CameraMap.ValidROI.ROIWidth'] = mdh['Camera.ROIWidth']
    mdh['CameraMap.ValidROI.ROIHeight'] = mdh['Camera.ROIHeight']
    mdh['Camera.ROIOriginX'], mdh['Camera.ROIOriginY'] = 0, 0
    mdh['Camera.ROIWidth'], mdh['Camera.ROIHeight'] = sensor_size
    mdh['Camera.ROI'] = (0, 0, sensor_size[0], sensor_size[1])

    if dark is not None and variance is not None:
        full_dark = mdh['Camera.ADOffset'] * np.ones(sensor_size,
                                                     dtype=dark.dtype)
        full_var = (mdh['Camera.ReadNoise']**2) * np.ones(sensor_size,
                                                          dtype=variance.dtype)

        xslice = slice(x_origin, x_origin + metadata['Camera.ROIWidth'])
        yslice = slice(y_origin, y_origin + metadata['Camera.ROIHeight'])

        full_dark[xslice, yslice] = dark
        full_var[xslice, yslice] = variance
    else:
        logger.warning('Generating uniform maps')
        full_dark = mdh['Camera.ADOffset'] * np.ones(sensor_size)
        full_var = (mdh['Camera.ReadNoise']**2) * np.ones(sensor_size)

        mdh['CamerMap.Uniform'] = True

    return full_dark, full_var, mdh
Exemple #21
0
    def OnExtractSplitPSF(self, event):
        if (len(self.PSFLocs) > 0):
            from PYME.Analysis.PSFEst import extractImages
            chnum = self.chChannel.GetSelection()

            psfROISize = [int(s) for s in self.tPSFROI.GetValue().split(',')]
            psfBlur = [float(s) for s in self.tPSFBlur.GetValue().split(',')]
            #print psfROISize

            psfs = []
            offsetsAllChannel = []

            #extract first channel (always aligned)
            psf, offsets = extractImages.getPSF3D(self.image.data[:, :, :,
                                                                  0].squeeze(),
                                                  self.PSFLocs,
                                                  psfROISize,
                                                  psfBlur,
                                                  centreZ=True)
            if self.chType.GetSelection() == 0:
                #widefield image - do special background subtraction
                psf = extractImages.backgroundCorrectPSFWF(psf)

            psfs.append(psf)
            offsetsAllChannel.append(offsets)
            alignZ = self.cbAlignZ.GetValue()
            z_offset = offsets[2]

            #extract subsequent channels, aligning if necessary, otherwise offsetting by the calculated offset for the first channel
            for i in range(1, self.image.data.shape[3]):
                psf, offsets = extractImages.getPSF3D(
                    self.image.data[:, :, :, i].squeeze(),
                    self.PSFLocs,
                    psfROISize,
                    psfBlur,
                    centreZ=alignZ,
                    z_offset=z_offset)

                if self.cbBackgroundCorrect.GetValue():
                    #widefield image - do special background subtraction
                    psf = extractImages.backgroundCorrectPSFWF(psf)

                psfs.append(psf)
                offsetsAllChannel.append(offsets)

            psf = numpy.concatenate(psfs, 0)
            offsetsAllChannel = numpy.asarray(offsetsAllChannel)
            offsetsAllChannel -= offsetsAllChannel[0]
            print(offsetsAllChannel)

            #            from pylab import *
            #            import cPickle
            #            imshow(psf.max(2))

            from PYME.DSView.dsviewer import ImageStack, ViewIm3D
            from PYME.IO.MetaDataHandler import NestedClassMDHandler

            mdh = NestedClassMDHandler(self.image.mdh)
            self.write_metadata(mdh, 'Split', offsetsAllChannel[:, 2])
            mdh['ImageType'] = 'PSF'

            im = ImageStack(data=psf, mdh=mdh, titleStub='Extracted PSF')
            im.defaultExt = '*.tif'  #we want to save as PSF by default
            ViewIm3D(im,
                     mode='psf',
                     parent=wx.GetTopLevelParent(self.dsviewer))
Exemple #22
0
def combine_maps(maps, return_validMap=False):
    destarr = None
    mapimgs = []
    for map in maps:
        mapimg = ImageStack(filename=map)
        mapimgs.append(mapimg)
        if destarr is None:
            mdh = NestedClassMDHandler(mapimg.mdh)
            destarr = mkdestarr(mapimg)
            validMap = np.zeros_like(destarr, dtype='int')
        else:
            checkMapCompat(mapimg, mdh)
        insertvmap(mapimg, destarr, validMap)

    mdh.setEntry('CameraMap.combinedFromMaps', maps)
    mdh.setEntry('CameraMap.ValidROI.ROIHeight',
                 mapimgs[0].mdh['Camera.SensorHeight'])
    mdh.setEntry('CameraMap.ValidROI.ROIWidth',
                 mapimgs[0].mdh['Camera.SensorWidth'])
    mdh.setEntry('CameraMap.ValidROI.ROIOriginX', 0)
    mdh.setEntry('CameraMap.ValidROI.ROIOriginY', 0)

    combinedMap = ImageStack(destarr, mdh=mdh)
    if return_validMap:
        vmdh = NestedClassMDHandler(mdh)
        vmdh.setEntry('CameraMap.ValidMask', True)
        return (combinedMap, ImageStack(validMap, mdh=vmdh))
    else:
        return combinedMap
Exemple #23
0
CHANGES = np.array([(0, 50.0 + 0.5),
                    (1, 50.001 + 0.5),
                    (801, 51.000),
                    (850, 50.600 + 0.5),
                    (1601, 52.000),
                    (1650, 51.450 + 0.5),
                    (2401, 53),
                    (2450,  52.705 + 0.5)],
                    dtype= [('frame', '<i4'), ('z', '<f8')])

TEST_DATA_SOURCE = np.arange(2500).astype([('t', '<i4')])
GROUND_TRUTH_Z = np.empty(len(TEST_DATA_SOURCE), dtype=float)
for ind in range(len(CHANGES)):
    GROUND_TRUTH_Z[CHANGES[ind]['frame']:] = CHANGES[ind]['z'] 

TEST_MDH = NestedClassMDHandler()
TEST_MDH['Camera.CycleTime'] = 0.00125
TEST_MDH['StartTime'] = 0

def test_flag_piezo_movement():
    from PYME.Analysis.piezo_movement_correction import flag_piezo_movement

    moving = flag_piezo_movement(TEST_DATA_SOURCE['t'], TEST_EVENTS, TEST_MDH)
    assert np.all(moving[np.where(np.logical_and(TEST_DATA_SOURCE['t'] >= 2401,
                                                 TEST_DATA_SOURCE['t'] < 2450))])
    assert not np.all(np.all(moving[np.where(TEST_DATA_SOURCE['t'] >= 2450)]))

def test_focus_correction():
    from PYME.Analysis.piezo_movement_correction import correct_target_positions
    corrected_focus = correct_target_positions(TEST_DATA_SOURCE['t'], TEST_EVENTS, TEST_MDH)
    np.testing.assert_array_almost_equal(GROUND_TRUTH_Z, corrected_focus)
Exemple #24
0
def insertIntoFullMap(m, ve, smdh, chipsize=(2048, 2048)):
    x0, y0 = get_camera_roi_origin(smdh)

    validROI = {
        'PosX': x0 + 1,
        'PosY': x0 + 1,
        'Width': smdh['Camera.ROIWidth'],
        'Height': smdh['Camera.ROIHeight']
    }

    bmdh = NestedClassMDHandler()
    bmdh.copyEntriesFrom(smdh)
    bmdh.setEntry('Analysis.name', 'mean-variance')
    bmdh.setEntry('Analysis.valid.ROIPosX', validROI['PosX'])
    bmdh.setEntry('Analysis.valid.ROIPosY', validROI['PosY'])
    bmdh.setEntry('Analysis.valid.ROIWidth', validROI['Width'])
    bmdh.setEntry('Analysis.valid.ROIHeight', validROI['Height'])

    bmdh['Camera.ROIOriginX'] = 0
    bmdh['Camera.ROIOriginY'] = 0
    bmdh['Camera.ROIWidth'] = chipsize[0]
    bmdh['Camera.ROIHeight'] = chipsize[1]
    bmdh['Camera.ROI'] = (0, 0, chipsize[0], chipsize[1])

    if m is None:
        mfull = np.zeros(chipsize, dtype='float64')
        vefull = np.zeros(chipsize, dtype='float64')
    else:
        mfull = np.zeros(chipsize, dtype=m.dtype)
        vefull = np.zeros(chipsize, dtype=ve.dtype)
    mfull.fill(smdh['Camera.ADOffset'])
    vefull.fill(smdh['Camera.ReadNoise']**2)

    if m is not None:
        mfull[validROI['PosX'] - 1:validROI['PosX'] - 1 + validROI['Width'],
              validROI['PosY'] - 1:validROI['PosY'] - 1 +
              validROI['Height']] = m
        vefull[validROI['PosX'] - 1:validROI['PosX'] - 1 + validROI['Width'],
               validROI['PosY'] - 1:validROI['PosY'] - 1 +
               validROI['Height']] = ve

    return mfull, vefull, bmdh
Exemple #25
0
def main():

    chipsize = (
        2048, 2048
    )  # we currently assume this is correct but could be chosen based
    # on camera model in meta data
    darkthreshold = 1e4  # this really should depend on the gain mode (12bit vs 16 bit etc)
    variancethreshold = 300**2  # again this is currently picked fairly arbitrarily
    blemishvariance = 1e8

    # options parsing
    op = argparse.ArgumentParser(
        description='generate offset and variance maps from darkseries.')
    op.add_argument('filename',
                    metavar='filename',
                    nargs='?',
                    default=None,
                    help='filename of the darkframe series')
    op.add_argument('-s',
                    '--start',
                    type=int,
                    default=0,
                    help='start frame to use')
    op.add_argument('-e',
                    '--end',
                    type=int,
                    default=-1,
                    help='end frame to use')
    op.add_argument('-u',
                    '--uniform',
                    action='store_true',
                    help='make uniform map using metadata info')
    op.add_argument(
        '-i',
        '--install',
        action='store_true',
        help='install map in default location - the filename argument is a map'
    )
    op.add_argument(
        '-d',
        '--dir',
        metavar='destdir',
        default=None,
        help='destination directory (default is PYME calibration path)')
    op.add_argument('-l',
                    '--list',
                    action='store_true',
                    help='list all maps in default location')
    args = op.parse_args()

    if args.list:
        listCalibrationDirs()
        sys.exit(0)

    # body of script
    filename = args.filename

    if filename is None:
        op.error('need a file name if -l or --list not requested')

    print('Opening image series...', file=sys.stderr)
    source = im.ImageStack(filename=filename)

    if args.install:
        if source.mdh.getOrDefault('Analysis.name', '') != 'mean-variance':
            print(
                'Analysis.name is not equal to "mean-variance" - probably not a map',
                file=sys.stderr)
            sys.exit('aborting...')

        if source.mdh['Analysis.resultname'] == 'mean':
            maptype = 'dark'
        else:
            maptype = 'variance'
        mapname = mkDefaultPath(maptype, source.mdh)
        saveasmap(source.dataSource.getSlice(0), mapname, mdh=source.mdh)
        sys.exit(0)

    start = args.start
    end = args.end
    if end < 0:
        end = int(source.dataSource.getNumSlices() + end)

    print('Calculating mean and variance...', file=sys.stderr)

    m, ve = (None, None)
    if not args.uniform:
        m, v = meanvards(source.dataSource, start=start, end=end)
        eperADU = source.mdh['Camera.ElectronsPerCount']
        ve = v * eperADU * eperADU

    # occasionally the cameras seem to have completely unusable pixels
    # one example was dark being 65535 (i.e. max value for 16 bit)
    if m.max() > darkthreshold:
        ve[m > darkthreshold] = blemishvariance
    if ve.max() > variancethreshold:
        ve[ve > variancethreshold] = blemishvariance

    nbad = np.sum((m > darkthreshold) * (ve > variancethreshold))

    # if the uniform flag is set, then m and ve are passed as None
    # which makes sure that just the uniform defaults from meta data are used
    mfull, vefull, basemdh = insertIntoFullMap(m,
                                               ve,
                                               source.mdh,
                                               chipsize=chipsize)
    #mfull, vefull, basemdh = (m, ve, source.mdh)

    print('Saving results...', file=sys.stderr)

    if args.dir is None:
        print('installing in standard location...', file=sys.stderr)
        mname = mkDefaultPath('dark', source.mdh)
        vname = mkDefaultPath('variance', source.mdh)
    else:
        mname = mkDestPath(args.dir, 'dark', source.mdh)
        vname = mkDestPath(args.dir, 'variance', source.mdh)

    print('dark map -> %s...' % mname, file=sys.stderr)
    print('var  map -> %s...' % vname, file=sys.stderr)

    commonMD = NestedClassMDHandler()
    commonMD.setEntry('Analysis.name', 'mean-variance')
    commonMD.setEntry('Analysis.start', start)
    commonMD.setEntry('Analysis.end', end)
    commonMD.setEntry('Analysis.SourceFilename', filename)
    commonMD.setEntry('Analysis.darkThreshold', darkthreshold)
    commonMD.setEntry('Analysis.varianceThreshold', variancethreshold)
    commonMD.setEntry('Analysis.blemishVariance', blemishvariance)
    commonMD.setEntry('Analysis.NBadPixels', nbad)
    if args.uniform:
        commonMD.setEntry('Analysis.isuniform', True)

    mmd = NestedClassMDHandler(basemdh)
    mmd.copyEntriesFrom(commonMD)
    mmd.setEntry('Analysis.resultname', 'mean')
    mmd.setEntry('Analysis.units', 'ADU')

    vmd = NestedClassMDHandler(basemdh)
    vmd.copyEntriesFrom(commonMD)
    vmd.setEntry('Analysis.resultname', 'variance')
    vmd.setEntry('Analysis.units', 'electrons^2')

    saveasmap(mfull, mname, mdh=mmd)
    saveasmap(vefull, vname, mdh=vmd)