Beispiel #1
0
    def OnMeasureClusters(self, event=None):
        """

        Calculates various measures for clusters using PYME.recipes.localisations.MeasureClusters

        Parameters
        ----------
        labelsKey: pipeline key to access array of label assignments. Measurements will be calculated for each label.


        """
        from PYME.recipes import localisations
        from PYME.recipes.base import ModuleCollection

        # build a recipe programatically
        measrec = ModuleCollection()

        measrec.add_module(
            localisations.MeasureClusters3D(measrec,
                                            inputName='input',
                                            labelsKey='dbscanClustered',
                                            outputName='output'))

        measrec.namespace['input'] = self.pipeline.output
        #configure parameters
        if not measrec.configure_traits(view=measrec.pipeline_view,
                                        kind='modal'):
            return  # handle cancel

        # run recipe
        meas = measrec.execute()

        # For now, don't make this a data source, as that requires (for multicolor) clearing the pipeline mappings.
        self.clusterMeasures.append(meas)
    def _on_ensemble_test(self, event=None):
        from PYME.recipes.base import ModuleCollection
        from PYME.IO.FileUtils import nameUtils
        from nep_fitting.recipe_modules import nep_fits
        from nep_fitting import reports
        from PYME.IO.ragged import RaggedCache
        import webbrowser

        rec = ModuleCollection()

        rec.add_module(
            nep_fits.TestEnsembleParameters(
                rec,
                inputName='line_profiles',
                fit_type=list(profile_fitters.ensemble_fitters.keys())[0],
                hold_ensemble_parameter_constant=False,
                outputName='output'))

        # populate namespace with current profiles
        rec.namespace['line_profiles'] = RaggedCache(
            self._line_profile_handler.get_line_profiles())
        if not rec.configure_traits(view=rec.pipeline_view, kind='modal'):
            return  # handle cancel

        res = rec.execute()

        # generate report
        context = {
            #'ensemble_parameters': res.mdh['TestEnsembleParameters.EnsembleTestValues'],  # note this is a dict
            'results':
            res,
            'filename':
            self._dsviewer.image.filename,
            'fittype':
            res.mdh['TestEnsembleParameters.FitType'],
            'img_schematic':
            reports.img_as_strb64(
                reports.get_schematic(
                    res.mdh['TestEnsembleParameters.FitType']))
        }
        handler_names = self._line_profile_handler.get_image_names()
        if (len(handler_names) == 1) and (handler_names[0] == self.image_name):
            # if there's only a single image, include it in the report
            context['img_data'] = reports.img_as_strb64(
                self._dsviewer.view.GrabPNGToBuffer())

        fdialog = wx.FileDialog(
            None,
            'Save report as ...',
            wildcard='html (*.html)|*.html',
            style=wx.FD_SAVE,
            defaultDir=nameUtils.genShiftFieldDirectoryPath())
        succ = fdialog.ShowModal()
        if (succ == wx.ID_OK):
            fpath = os.path.splitext(fdialog.GetPath())[0] + '.html'
            reports.generate_and_save(fpath,
                                      context,
                                      template_name='ensemble_test.html')

            webbrowser.open('file://' + fpath, 2)
Beispiel #3
0
    def OnClustersInTime(self, event=None):
        #FIXME - this would probably be better in an addon module outside of the core project
        from PYME.recipes import localisations
        from PYME.recipes.base import ModuleCollection
        import matplotlib.pyplot as plt

        # build a recipe programatically
        rec = ModuleCollection()

        # split input according to colour channel selected
        rec.add_module(localisations.ExtractTableChannel(rec, inputName='input', outputName='chan0',
                                                              channel='chan0'))

        rec.add_module(localisations.ClusterCountVsImagingTime(rec, inputName='chan0', stepSize=3000, outputName='output'))


        rec.namespace['input'] = self.pipeline.output #do before configuring so that we already have the channel names populated
        #configure parameters
        if not rec.configure_traits(view=rec.pipeline_view, kind='modal'):
            return #handle cancel

        incrementedClumps = rec.execute()

        plt.figure()
        plt.scatter(incrementedClumps['t'], incrementedClumps['N_labelsWithLowMinPoints'],
                    label=('clusters with Npoints > %i' % rec.modules[-1].lowerMinPtsPerCluster), c='b', marker='s')
        plt.scatter(incrementedClumps['t'], incrementedClumps['N_labelsWithHighMinPoints'],
                    label=('clusters with Npoints > %i' % rec.modules[-1].higherMinPtsPerCluster), c='g', marker='o')

        plt.legend(loc=4, scatterpoints=1)
        plt.xlabel('Number of frames included')
        plt.ylabel('Number of Clusters')
Beispiel #4
0
    def OnPairwiseDistanceHistogram(self, event=None):
        from PYME.recipes import tablefilters, localisations, measurement
        from PYME.recipes.base import ModuleCollection
        import matplotlib.pyplot as plt

        # build a recipe programatically
        distogram = ModuleCollection()

        # split input according to colour channels selected
        distogram.add_module(localisations.ExtractTableChannel(distogram, inputName='input', outputName='chan0',
                                                              channel='chan0'))
        distogram.add_module(localisations.ExtractTableChannel(distogram, inputName='input', outputName='chan1',
                                                              channel='chan0'))

        # Histogram
        distogram.add_module(measurement.PairwiseDistanceHistogram(distogram, inputPositions='chan0',
                                                                   inputPositions2='chan1', outputName='output'))

        distogram.namespace['input'] = self.pipeline.output #do before configuring so that we already have the channel names populated
        #configure parameters
        if not distogram.configure_traits(view=distogram.pipeline_view, kind='modal'):
            return #handle cancel
        selectedChans = (distogram.modules[-1].inputPositions, distogram.modules[-1].inputPositions2)
        #run recipe
        distances = distogram.execute()

        binsz = (distances['bins'][1] - distances['bins'][0])
        self.pairwiseDistances[selectedChans] = {'counts': np.array(distances['counts']),
                                                        'bins': np.array(distances['bins'] + 0.5*binsz)}

        plt.figure()
        plt.bar(self.pairwiseDistances[selectedChans]['bins'] - 0.5*binsz,
                self.pairwiseDistances[selectedChans]['counts'], width=binsz)
Beispiel #5
0
    def _on_ensemble_fit(self, event=None):
        from PYME.recipes.base import ModuleCollection
        from nep_fitting.core import profile_fitters
        from PYME.IO.ragged import RaggedCache

        rec = ModuleCollection()

        rec.add_module(
            profile_fitters.EnsembleFitROIs(
                rec,
                inputName='ROIs',
                fit_type='LorentzianConvolvedSolidSphere_ensemblePSF',
                hold_ensemble_parameter_constant=False,
                outputName='output'))

        # populate namespace with current profiles
        rec.namespace['ROIs'] = RaggedCache(self._region_handler.get_rois())
        if not rec.configure_traits(view=rec.pipeline_view, kind='modal'):
            return  # handle cancel

        res = rec.execute()
    def OnSaveTif(self, wx_event=None):
        from pyme_omero.recipe_modules import omero_upload
        import os
        from PYME.recipes.base import ModuleCollection
        from PYME.recipes.localisations import DensityMapping

        input_dir, file_stub = os.path.split(self.pipeline.filename)
        file_stub, ext = os.path.splitext(file_stub)
        context = dict(file_stub=file_stub, input_dir=input_dir)

        rec = ModuleCollection()  # build new recipe but point to old namespace
        rec.namespace = self.pipeline.recipe.namespace
        rec.add_module(
            DensityMapping(
                rec,
                inputLocalizations=self.pipeline.selectedDataSourceKey,
                outputImage='thumbnail_rendering'))
        rec.add_module(
            omero_upload.ImageUpload(rec, input_image='thumbnail_rendering'))
        if rec.configure_traits(view=rec.pipeline_view, kind='modal'):
            rec.execute()
            rec.save(context)
    def _on_fit(self, event=None):
        from PYME.recipes.base import ModuleCollection
        from nep_fitting.recipe_modules import nep_fits
        from PYME.IO.ragged import RaggedCache
        from PYME.IO.FileUtils import nameUtils
        import webbrowser
        from nep_fitting import reports

        rec = ModuleCollection()

        rec.add_module(
            nep_fits.FitProfiles(
                rec,
                inputName='line_profiles',
                fit_type=list(profile_fitters.non_ensemble_fitters.keys())[0],
                outputName='output'))

        # populate namespace with current profiles
        rec.namespace['line_profiles'] = RaggedCache(
            self._line_profile_handler.get_line_profiles())
        if not rec.configure_traits(view=rec.pipeline_view, kind='modal'):
            return  # handle cancel

        res = rec.execute()

        fdialog = wx.FileDialog(
            None,
            'Save results as ...',
            wildcard='hdf (*.hdf)|*.hdf',
            style=wx.FD_SAVE,
            defaultDir=nameUtils.genShiftFieldDirectoryPath(
            ))  # , defaultFile=defFile)
        succ = fdialog.ShowModal()
        if (succ == wx.ID_OK):
            base_path = os.path.splitext(fdialog.GetPath())[0]

            res.to_hdf(
                base_path + '.hdf', tablename='profile_fits'
            )  # table name changed to avoid conflicts with standard fit data

            fitter = rec.modules[
                0].fitter  # TODO - move plot_results out from class so we don't have to hack like this
            profile_dir = base_path + '/'
            os.mkdir(profile_dir)
            fitter.plot_results(profile_dir)

            htmlfn = base_path + '.html'

            context = {
                'results':
                res,
                'filename':
                self._dsviewer.image.filename,
                'fittype':
                res.mdh['FitProfiles.FitType'],
                'img_schematic':
                reports.img_as_strb64(
                    reports.get_schematic(res.mdh['FitProfiles.FitType']))
            }
            handler_names = self._line_profile_handler.get_image_names()
            if (len(handler_names) == 1) and (handler_names[0]
                                              == self.image_name):
                # if there's only a single image, include it in the report
                context['img_data'] = reports.img_as_strb64(
                    self._dsviewer.view.GrabPNGToBuffer())

            reports.generate_and_save(htmlfn,
                                      context,
                                      template_name='single_data.html')

            webbrowser.open('file://' + htmlfn, 2)
Beispiel #8
0
    def OnPairwiseDistanceHistogram(self, event=None):
        from PYME.recipes import tablefilters, localisations, measurement
        from PYME.recipes.base import ModuleCollection
        import matplotlib.pyplot as plt
        import wx
        import os

        # build a recipe programatically
        distogram = ModuleCollection()

        # split input according to colour channels selected
        distogram.add_module(
            localisations.ExtractTableChannel(distogram,
                                              inputName='input',
                                              outputName='chan0',
                                              channel='chan0'))
        distogram.add_module(
            localisations.ExtractTableChannel(distogram,
                                              inputName='input',
                                              outputName='chan1',
                                              channel='chan0'))

        # Histogram
        distogram.add_module(
            measurement.PairwiseDistanceHistogram(distogram,
                                                  inputPositions='chan0',
                                                  inputPositions2='chan1',
                                                  outputName='output'))

        distogram.namespace[
            'input'] = self.pipeline.output  #do before configuring so that we already have the channel names populated
        #configure parameters
        if not distogram.configure_traits(view=distogram.pipeline_view,
                                          kind='modal'):
            return  #handle cancel
        selectedChans = (distogram.modules[-1].inputPositions,
                         distogram.modules[-1].inputPositions2)
        #run recipe
        distances = distogram.execute()

        binsz = (distances['bins'][1] - distances['bins'][0])
        self.pairwiseDistances[selectedChans] = {
            'counts': np.array(distances['counts']),
            'bins': np.array(distances['bins'] + 0.5 * binsz)
        }

        plt.figure()
        plt.bar(self.pairwiseDistances[selectedChans]['bins'] - 0.5 * binsz,
                self.pairwiseDistances[selectedChans]['counts'],
                width=binsz)

        hist_dlg = wx.FileDialog(
            None,
            message="Save histogram as csv...",
            #  defaultDir=os.getcwd(),
            defaultFile='disthist_{}.csv'.format(
                os.path.basename(self.pipeline.filename)),
            wildcard='CSV (*.csv)|*.csv',
            style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)

        if hist_dlg.ShowModal() == wx.ID_OK:
            histfn = hist_dlg.GetPath()
            np.savetxt(histfn,
                       np.vstack([
                           self.pairwiseDistances[selectedChans]['bins'] -
                           0.5 * binsz,
                           self.pairwiseDistances[selectedChans]['counts']
                       ]).T,
                       delimiter=',',
                       header='Bins [nm],Counts')
Beispiel #9
0
    def OnFindMixedClusters(self, event=None):
        """
        FindMixedClusters first uses DBSCAN clustering on two color channels separately for denoising purposes, then
        after having removed noisy points, DBSCAN is run again on both channels combined, and the fraction of clumps
        containing both colors is determined.
        """
        from PYME.recipes import tablefilters, localisations
        from PYME.recipes.base import ModuleCollection
        import wx

        chans = self.pipeline.colourFilter.getColourChans()
        nchan = len(chans)
        if nchan < 2:
            raise RuntimeError(
                'FindMixedClusters requires at least two color channels')
        else:
            selectedChans = [0, 1]

        #rad_dlg = wx.NumberEntryDialog(None, 'Search Radius For Core Points', 'rad [nm]', 'rad [nm]', 125, 0, 9e9)
        #rad_dlg.ShowModal()
        searchRadius = 125.0  #rad_dlg.GetValue()
        #minPt_dlg = wx.NumberEntryDialog(None, 'Minimum Points To Be Core Point', 'min pts', 'min pts', 3, 0, 9e9)
        #minPt_dlg.ShowModal()
        minClumpSize = 3  #minPt_dlg.GetValue()

        #build a recipe programatically
        rec = ModuleCollection()
        #split input according to colour channels
        rec.add_module(
            localisations.ExtractTableChannel(rec,
                                              inputName='input',
                                              outputName='chan0',
                                              channel=chans[0]))
        rec.add_module(
            localisations.ExtractTableChannel(rec,
                                              inputName='input',
                                              outputName='chan1',
                                              channel=chans[1]))

        #clump each channel
        rec.add_module(
            localisations.DBSCANClustering(rec,
                                           inputName='chan0',
                                           outputName='chan0_clumped',
                                           searchRadius=searchRadius,
                                           minClumpSize=minClumpSize))
        rec.add_module(
            localisations.DBSCANClustering(rec,
                                           inputName='chan1',
                                           outputName='chan1_clumped',
                                           searchRadius=searchRadius,
                                           minClumpSize=minClumpSize))

        #filter unclumped points
        rec.add_module(
            tablefilters.FilterTable(
                rec,
                inputName='chan0_clumped',
                outputName='chan0_cleaned',
                filters={'dbscanClumpID': [.5, sys.maxsize]}))
        rec.add_module(
            tablefilters.FilterTable(
                rec,
                inputName='chan1_clumped',
                outputName='chan1_cleaned',
                filters={'dbscanClumpID': [.5, sys.maxsize]}))

        #rejoin cleaned datasets
        rec.add_module(
            tablefilters.ConcatenateTables(rec,
                                           inputName0='chan0_cleaned',
                                           inputName1='chan1_cleaned',
                                           outputName='joined'))

        #clump on cleaded and rejoined data
        rec.add_module(
            localisations.DBSCANClustering(rec,
                                           inputName='joined',
                                           outputName='output',
                                           searchRadius=searchRadius,
                                           minClumpSize=minClumpSize))

        rec.namespace[
            'input'] = self.pipeline.output  #do it before configuring so that we already have the channe; names populated
        if not rec.configure_traits(view=rec.pipeline_view, kind='modal'):
            return  #handle cancel

        #run recipe
        joined_clumps = rec.execute()

        joined_clump_IDs = np.unique(joined_clumps['dbscanClumpID'])
        joined_clump_IDs = joined_clump_IDs[joined_clump_IDs >
                                            .5]  #reject unclumped points

        chan0_clump_IDs = np.unique(
            joined_clumps['dbscanClumpID'][joined_clumps['concatSource'] < .5])
        chan0_clump_IDs = chan0_clump_IDs[chan0_clump_IDs > .5]

        chan1_clump_IDs = np.unique(
            joined_clumps['dbscanClumpID'][joined_clumps['concatSource'] > .5])
        chan1_clump_IDs = chan1_clump_IDs[chan1_clump_IDs > .5]

        both_chans_IDS = [c for c in chan0_clump_IDs if c in chan1_clump_IDs]

        n_total_clumps = len(joined_clump_IDs)

        print('Total clumps: %i' % n_total_clumps)
        c0Ratio = float(len(chan0_clump_IDs)) / n_total_clumps
        print('fraction clumps with channel %i present: %f' %
              (selectedChans[0], c0Ratio))
        self.colocalizationRatios['Channel%iin%i%i' %
                                  (selectedChans[0], selectedChans[0],
                                   selectedChans[1])] = c0Ratio

        c1Ratio = float(len(chan1_clump_IDs)) / n_total_clumps
        print('fraction clumps with channel %i present: %f' %
              (selectedChans[1], c1Ratio))
        self.colocalizationRatios['Channel%iin%i%i' %
                                  (selectedChans[1], selectedChans[0],
                                   selectedChans[1])] = c1Ratio

        bothChanRatio = float(len(both_chans_IDS)) / n_total_clumps
        print('fraction of clumps with both channel %i and %i present: %f' %
              (selectedChans[0], selectedChans[1], bothChanRatio))
        self.colocalizationRatios['mixedClumps%i%i' %
                                  tuple(selectedChans)] = bothChanRatio

        self._rec = rec