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')
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)
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 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)
def _make_dummy_cell(centre=(0., 0., 0.), z_scale=1.): # make cube x = np.array([1, 1, 1, -1, -1, -1, 1, -1], dtype=float) y = np.array([1, 1, -1, 1, -1, 1, -1, -1], dtype=float) z = np.array([1, -1, 1, 1, 1, -1, -1, -1], dtype=float) # shift things x += centre[0] y += centre[1] z += centre[2] inp = {'x': x, 'y': y, 'z': z} recipe = ModuleCollection() recipe.namespace['input'] = inp shell_module = SphericalHarmonicShell(recipe, input_name='input', z_scale=z_scale, max_m_mode=5, n_iterations=2, init_tolerance=0.3, output_name='output') recipe.add_module(shell_module) recipe.execute() return recipe.namespace['output']
def OnScatterByID(self, event): from PYMEcs.recipes import localisations from PYME.recipes.base import ModuleCollection rec = ModuleCollection() ScatterbyID = localisations.ScatterbyID(rec) rec.namespace = {ScatterbyID.inputName: self.pipeline} if ScatterbyID.configure_traits(kind='modal'): # we call this with the pipeline to allow filtering etc ScatterbyID.execute(rec.namespace)
def OnQindexRatio(self, event): from PYMEcs.recipes import localisations from PYME.recipes.base import ModuleCollection rec = ModuleCollection() QIRatio = localisations.QindexRatio(rec) # we call this with the pipeline to allow filtering etc rec.namespace = {QIRatio.inputName: self.pipeline} if QIRatio.configure_traits(kind='modal'): QIRatio.execute(rec.namespace) self.pipeline.addColumn(QIRatio.qIndexRatio, rec.namespace[QIRatio.outputName][QIRatio.qIndexRatio])
def on_calculate_frc_from_images(self, event=None): from fsc.plugins.recipes.fsc import CalculateFRCFromImages from PYME.recipes.base import ModuleCollection recipe = ModuleCollection() frc = CalculateFRCFromImages(recipe) if frc.configure_traits(kind='modal'): recipe.add_module(frc) recipe.execute() print(recipe.namespace[frc.output_frc_dict])
def __init__(self, filename=None, visFr=None): self.filter = None self.mapping = None self.colourFilter = None self.events = None self.recipe = ModuleCollection(execute_on_invalidation=True) self.recipe.recipe_executed.connect(self.Rebuild) self.selectedDataSourceKey = None self.filterKeys = { 'error_x': (0, 30), 'error_y': (0, 30), 'A': (5, 20000), 'sig': (95, 200) } self.blobSettings = BlobSettings() self.objects = None self.imageBounds = ImageBounds(0, 0, 0, 0) self.mdh = MetaDataHandler.NestedClassMDHandler() self.Triangles = None self.edb = None self.Quads = None self.GeneratedMeasures = {} self.QTGoalPixelSize = 5 self._extra_chan_num = 0 self.filesToClose = [] self.ev_mappings = {} #define a signal which a GUI can hook if the pipeline is rebuilt (i.e. the output changes) self.onRebuild = dispatch.Signal() #a cached list of our keys to be used to decide whether to fire a keys changed signal self._keys = None #define a signal which can be hooked if the pipeline keys have changed self.onKeysChanged = dispatch.Signal() self.ready = False #self.visFr = visFr if not filename is None: self.OpenFile(filename)
def OnSaveToOMERO(self, wx_event=None): from pyme_omero.recipe_modules import omero_upload from PYME.recipes.base import ModuleCollection import os context = dict(file_stub=os.path.splitext( os.path.split(self.image.filename)[-1])[0]) rec = ModuleCollection() rec.namespace['input'] = self.image uploader = omero_upload.ImageUpload(rec, input_image='input') if uploader.configure_traits(kind='modal', view=uploader.no_localization_view): uploader.save(rec.namespace, context)
def test_stats_by_frame(): recipe = ModuleCollection() test_length = 10 x, y = np.meshgrid(range(test_length), range(test_length)) mask = x > test_length / 2 # mask out everything but 6, 7, 8, 9 # check 2D recipe.namespace['input'] = ImageStack(data=x) recipe.namespace['mask'] = ImageStack(data=mask) stats_mod = processing.StatisticsByFrame(input_name='input', mask='mask', output_name='output') recipe.add_module(stats_mod) stats = recipe.execute() # check results assert len(stats['mean']) == 1 assert stats['mean'] == 7.5 # test 3D with 2D mask recipe.namespace.clear() x3, y3, z3 = np.meshgrid(range(test_length), range(test_length), range(test_length)) recipe.namespace['input'] = ImageStack(data=z3) # reuse the same mask from before, which will now take the right 4 columns at each slice recipe.namespace['mask'] = ImageStack(data=mask) stats = recipe.execute() # check results np.testing.assert_array_almost_equal(stats['mean'], range(test_length)) # test 3D with 3D mask mask = x3 > test_length / 2 recipe.namespace['mask'] = ImageStack(data=mask) stats = recipe.execute() # check results np.testing.assert_array_almost_equal( stats['mean'], np.ma.masked_array(z3, mask=~(x3 > test_length / 2)).mean(axis=(0, 1))) # test no mask stats_mod.mask = '' stats = recipe.execute() np.testing.assert_array_almost_equal(stats['mean'], np.mean(z3, axis=(0, 1)))
def test_queue_acquisitions(): from PYME.IO.tabular import DictSource from PYME.recipes.base import ModuleCollection import numpy as np import time action_manager.paused = True d = DictSource({'x': np.arange(10), 'y': np.arange(10)}) rec = ModuleCollection() rec.namespace['input'] = d spool_settings = {'extra_metadata' : {'Sample.Well': '{file_stub}'}} rec.add_module(acquisition.QueueAcquisitions(rec, spool_settings=spool_settings)) rec.save(context={'file_stub': 'A1'}) time.sleep(1) task = action_manager.actionQueue.get_nowait() assert 'A1' == task[1]._then.params['extra_metadata']['Sample.Well']
def test_upload(): rec = ModuleCollection() im = ImageStack(data=np.reshape(np.random.randint(0, 100, (25, 25)), (25, 25, 1, 1)), haveGUI=False) fake_locs = DictSource( dict(x=np.random.rand(5), y=np.random.rand(5), t=np.random.randint(0, 10, 5))) rec.namespace['test'] = im rec.namespace['fake_locs'] = fake_locs rec.add_module( RGBImageUpload( rec, inputName='test', omero_dataset='pyme-omero-testing', input_localization_attachments={'fake_locs': 'test.hdf'})) rec.execute() rec.save(context={'file_stub': 'test'})
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 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
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')
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)