PYME-extra 1.0.4.post0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- PYMEcs/Acquire/Actions/__init__.py +0 -0
- PYMEcs/Acquire/Actions/custom.py +167 -0
- PYMEcs/Acquire/Hardware/LPthreadedSimple.py +248 -0
- PYMEcs/Acquire/Hardware/LPthreadedSimpleSim.py +246 -0
- PYMEcs/Acquire/Hardware/NikonTiFlaskServer.py +45 -0
- PYMEcs/Acquire/Hardware/NikonTiFlaskServerT.py +59 -0
- PYMEcs/Acquire/Hardware/NikonTiRESTClient.py +73 -0
- PYMEcs/Acquire/Hardware/NikonTiSim.py +35 -0
- PYMEcs/Acquire/Hardware/__init__.py +0 -0
- PYMEcs/Acquire/Hardware/driftTrackGUI.py +329 -0
- PYMEcs/Acquire/Hardware/driftTrackGUI_n.py +472 -0
- PYMEcs/Acquire/Hardware/driftTracking.py +424 -0
- PYMEcs/Acquire/Hardware/driftTracking_n.py +433 -0
- PYMEcs/Acquire/Hardware/fakeCamX.py +15 -0
- PYMEcs/Acquire/Hardware/offsetPiezoRESTCorrelLog.py +38 -0
- PYMEcs/Acquire/__init__.py +0 -0
- PYMEcs/Analysis/MBMcollection.py +552 -0
- PYMEcs/Analysis/MINFLUX.py +280 -0
- PYMEcs/Analysis/MapUtils.py +77 -0
- PYMEcs/Analysis/NPC.py +1176 -0
- PYMEcs/Analysis/Paraflux.py +218 -0
- PYMEcs/Analysis/Simpler.py +81 -0
- PYMEcs/Analysis/Sofi.py +140 -0
- PYMEcs/Analysis/__init__.py +0 -0
- PYMEcs/Analysis/decSofi.py +211 -0
- PYMEcs/Analysis/eventProperties.py +50 -0
- PYMEcs/Analysis/fitDarkTimes.py +569 -0
- PYMEcs/Analysis/objectVolumes.py +20 -0
- PYMEcs/Analysis/offlineTracker.py +130 -0
- PYMEcs/Analysis/stackTracker.py +180 -0
- PYMEcs/Analysis/timeSeries.py +63 -0
- PYMEcs/Analysis/trackFiducials.py +186 -0
- PYMEcs/Analysis/zerocross.py +91 -0
- PYMEcs/IO/MINFLUX.py +851 -0
- PYMEcs/IO/NPC.py +117 -0
- PYMEcs/IO/__init__.py +0 -0
- PYMEcs/IO/darkTimes.py +19 -0
- PYMEcs/IO/picasso.py +219 -0
- PYMEcs/IO/tabular.py +11 -0
- PYMEcs/__init__.py +0 -0
- PYMEcs/experimental/CalcZfactor.py +51 -0
- PYMEcs/experimental/FRC.py +338 -0
- PYMEcs/experimental/ImageJROItools.py +49 -0
- PYMEcs/experimental/MINFLUX.py +1537 -0
- PYMEcs/experimental/NPCcalcLM.py +560 -0
- PYMEcs/experimental/Simpler.py +369 -0
- PYMEcs/experimental/Sofi.py +78 -0
- PYMEcs/experimental/__init__.py +0 -0
- PYMEcs/experimental/binEventProperty.py +187 -0
- PYMEcs/experimental/chaining.py +23 -0
- PYMEcs/experimental/clusterTrack.py +179 -0
- PYMEcs/experimental/combine_maps.py +104 -0
- PYMEcs/experimental/eventProcessing.py +93 -0
- PYMEcs/experimental/fiducials.py +323 -0
- PYMEcs/experimental/fiducialsNew.py +402 -0
- PYMEcs/experimental/mapTools.py +271 -0
- PYMEcs/experimental/meas2DplotDh5view.py +107 -0
- PYMEcs/experimental/mortensen.py +131 -0
- PYMEcs/experimental/ncsDenoise.py +158 -0
- PYMEcs/experimental/onTimes.py +295 -0
- PYMEcs/experimental/procPoints.py +77 -0
- PYMEcs/experimental/pyme2caml.py +73 -0
- PYMEcs/experimental/qPAINT.py +965 -0
- PYMEcs/experimental/randMap.py +188 -0
- PYMEcs/experimental/regExtraCmaps.py +11 -0
- PYMEcs/experimental/selectROIfilterTable.py +72 -0
- PYMEcs/experimental/showErrs.py +51 -0
- PYMEcs/experimental/showErrsDh5view.py +58 -0
- PYMEcs/experimental/showShiftMap.py +56 -0
- PYMEcs/experimental/snrEvents.py +188 -0
- PYMEcs/experimental/specLabeling.py +51 -0
- PYMEcs/experimental/splitRender.py +246 -0
- PYMEcs/experimental/testChannelByName.py +36 -0
- PYMEcs/experimental/timedSpecies.py +28 -0
- PYMEcs/experimental/utils.py +31 -0
- PYMEcs/misc/ExtraCmaps.py +177 -0
- PYMEcs/misc/__init__.py +0 -0
- PYMEcs/misc/configUtils.py +169 -0
- PYMEcs/misc/guiMsgBoxes.py +27 -0
- PYMEcs/misc/mapUtils.py +230 -0
- PYMEcs/misc/matplotlib.py +136 -0
- PYMEcs/misc/rectsFromSVG.py +182 -0
- PYMEcs/misc/shellutils.py +1110 -0
- PYMEcs/misc/utils.py +205 -0
- PYMEcs/misc/versionCheck.py +20 -0
- PYMEcs/misc/zcInfo.py +90 -0
- PYMEcs/pyme_warnings.py +4 -0
- PYMEcs/recipes/__init__.py +0 -0
- PYMEcs/recipes/base.py +75 -0
- PYMEcs/recipes/localisations.py +2380 -0
- PYMEcs/recipes/manipulate_yaml.py +83 -0
- PYMEcs/recipes/output.py +177 -0
- PYMEcs/recipes/processing.py +247 -0
- PYMEcs/recipes/simpler.py +290 -0
- PYMEcs/version.py +2 -0
- pyme_extra-1.0.4.post0.dist-info/METADATA +114 -0
- pyme_extra-1.0.4.post0.dist-info/RECORD +101 -0
- pyme_extra-1.0.4.post0.dist-info/WHEEL +5 -0
- pyme_extra-1.0.4.post0.dist-info/entry_points.txt +3 -0
- pyme_extra-1.0.4.post0.dist-info/licenses/LICENSE +674 -0
- pyme_extra-1.0.4.post0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
from traitsui.api import View, Item, Group
|
|
2
|
+
from traitsui.menu import OKButton, CancelButton, OKCancelButtons
|
|
3
|
+
from traits.api import HasTraits, Str, Int, CStr, List, Enum, Float, Bool
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
#from PYME.DSView.dsviewer import View3D
|
|
7
|
+
#from PYME.IO.MetaDataHandler import NestedClassMDHandler
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
import wx
|
|
11
|
+
|
|
12
|
+
def rendHistw(x,y, imageBounds, pixelSize, weights=None):
|
|
13
|
+
X = np.arange(imageBounds.x0, imageBounds.x1 + 1.01*pixelSize, pixelSize)
|
|
14
|
+
Y = np.arange(imageBounds.y0, imageBounds.y1 + 1.01*pixelSize, pixelSize)
|
|
15
|
+
|
|
16
|
+
im, edx, edy = np.histogram2d(x,y, bins=(X,Y), weights=weights)
|
|
17
|
+
|
|
18
|
+
return im
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
from PYME.LMVis.renderers import ColourRenderer
|
|
22
|
+
class BackgroundHistogramRenderer(ColourRenderer):
|
|
23
|
+
"""2D background histogram rendering"""
|
|
24
|
+
|
|
25
|
+
name = 'Histogram Background'
|
|
26
|
+
mode = 'histogram'
|
|
27
|
+
|
|
28
|
+
def genIm(self, settings, imb, mdh):
|
|
29
|
+
im_hist = rendHistw(self.colourFilter['x'],self.colourFilter['y'], imb, settings['pixelSize'])
|
|
30
|
+
im_background = rendHistw(self.colourFilter['x'],self.colourFilter['y'], imb, settings['pixelSize'],
|
|
31
|
+
weights=self.colourFilter['fitResults_background'])
|
|
32
|
+
Inds = im_hist > 0
|
|
33
|
+
im_bgmean = np.zeros_like(im_background)
|
|
34
|
+
im_bgmean[Inds] = im_background[Inds]/im_hist[Inds]
|
|
35
|
+
|
|
36
|
+
return im_bgmean
|
|
37
|
+
|
|
38
|
+
def voxelsize_mdh(pixelsize_nm):
|
|
39
|
+
from PYME.IO.MetaDataHandler import NestedClassMDHandler
|
|
40
|
+
|
|
41
|
+
mdh = NestedClassMDHandler()
|
|
42
|
+
|
|
43
|
+
#voxelsize
|
|
44
|
+
mdh.setEntry('voxelsize.x',1e-3*pixelsize_nm)
|
|
45
|
+
mdh.setEntry('voxelsize.y',1e-3*pixelsize_nm)
|
|
46
|
+
mdh.setEntry('voxelsize.z',0.2)
|
|
47
|
+
mdh.setEntry('voxelsize.units','um')
|
|
48
|
+
|
|
49
|
+
return mdh
|
|
50
|
+
|
|
51
|
+
class InterpolChoice(HasTraits):
|
|
52
|
+
InterpolationMethod = Enum(['Splines','Radial Basis functions','Constraint Model'])
|
|
53
|
+
|
|
54
|
+
import wx
|
|
55
|
+
#import deClump
|
|
56
|
+
#from pylab import *
|
|
57
|
+
#import numpy as np
|
|
58
|
+
|
|
59
|
+
class simplerFilterDialog(wx.Dialog):
|
|
60
|
+
def __init__(self, *args, **kwargs):
|
|
61
|
+
wx.Dialog.__init__(self, *args, **kwargs)
|
|
62
|
+
|
|
63
|
+
vsizer = wx.BoxSizer(wx.VERTICAL)
|
|
64
|
+
|
|
65
|
+
hsizer = wx.BoxSizer(wx.HORIZONTAL)
|
|
66
|
+
|
|
67
|
+
hsizer.Add(wx.StaticText(self, -1, 'Clump Radius: '), 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5)
|
|
68
|
+
|
|
69
|
+
self.tClumpRadMult = wx.TextCtrl(self, -1, '2.0', size=[30,-1])
|
|
70
|
+
hsizer.Add(self.tClumpRadMult, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5)
|
|
71
|
+
|
|
72
|
+
hsizer.Add(wx.StaticText(self, -1, 'X'), 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5)
|
|
73
|
+
|
|
74
|
+
self.cClumpRadVar = wx.Choice(self, -1, choices=['1.0', 'error_x'])
|
|
75
|
+
self.cClumpRadVar.SetSelection(1)
|
|
76
|
+
hsizer.Add(self.cClumpRadVar,1, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5)
|
|
77
|
+
|
|
78
|
+
vsizer.Add(hsizer, 0, wx.ALL, 5)
|
|
79
|
+
|
|
80
|
+
hsizer = wx.BoxSizer(wx.HORIZONTAL)
|
|
81
|
+
hsizer.Add(wx.StaticText(self, -1, 'Minimum Clump Size (post filter): '), 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5)
|
|
82
|
+
|
|
83
|
+
self.tClumpMin = wx.TextCtrl(self, -1, '3')
|
|
84
|
+
hsizer.Add(self.tClumpMin,1, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5)
|
|
85
|
+
|
|
86
|
+
vsizer.Add(hsizer, 0, wx.ALL, 5)
|
|
87
|
+
|
|
88
|
+
btSizer = wx.StdDialogButtonSizer()
|
|
89
|
+
|
|
90
|
+
btn = wx.Button(self, wx.ID_OK)
|
|
91
|
+
btn.SetDefault()
|
|
92
|
+
|
|
93
|
+
btSizer.AddButton(btn)
|
|
94
|
+
|
|
95
|
+
btn = wx.Button(self, wx.ID_CANCEL)
|
|
96
|
+
|
|
97
|
+
btSizer.AddButton(btn)
|
|
98
|
+
|
|
99
|
+
btSizer.Realize()
|
|
100
|
+
|
|
101
|
+
vsizer.Add(btSizer, 0, wx.ALL, 5)
|
|
102
|
+
|
|
103
|
+
self.SetSizerAndFit(vsizer)
|
|
104
|
+
|
|
105
|
+
def GetClumpRadiusMultiplier(self):
|
|
106
|
+
return float(self.tClumpRadMult.GetValue())
|
|
107
|
+
|
|
108
|
+
def GetClumpRadiusVariable(self):
|
|
109
|
+
return self.cClumpRadVar.GetStringSelection()
|
|
110
|
+
|
|
111
|
+
def GetClumpMinSize(self):
|
|
112
|
+
return int(self.tClumpMin.GetValue())
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
# things still to add
|
|
117
|
+
# - done - "Filter events for SIMPLER": choose clump radius and min clumpsize interactively
|
|
118
|
+
# - new function to calculate N0 from data background
|
|
119
|
+
# - done - new function to insert SIMPLERzgenerator
|
|
120
|
+
# - add error estimates for SIMPLER (combination of formula and/or stddev) -> do in recipe module
|
|
121
|
+
class SIMPLER():
|
|
122
|
+
def __init__(self, visFr):
|
|
123
|
+
self.visFr = visFr
|
|
124
|
+
self.intMeth = InterpolChoice()
|
|
125
|
+
# pass visFr = None in constructor to avoid autogenerated menu entry
|
|
126
|
+
self.bgrend = BackgroundHistogramRenderer(visFr=None,pipeline=visFr.pipeline,mainWind=visFr)
|
|
127
|
+
# note we need to set the visFr posthoc so that rendering works as expected
|
|
128
|
+
self.bgrend.visFr = visFr
|
|
129
|
+
|
|
130
|
+
# entries to set N0
|
|
131
|
+
visFr.AddMenuItem('Experimental>SIMPLER', "Set N0 from Image Map", self.OnN0FromImage)
|
|
132
|
+
visFr.AddMenuItem('Experimental>SIMPLER', "Set N0 from Interpolation Map", self.OnN0FromIinterpolationField)
|
|
133
|
+
visFr.AddMenuItem('Experimental>SIMPLER', itemType='separator')
|
|
134
|
+
# entries for next steps in SIMPLER calculations
|
|
135
|
+
visFr.AddMenuItem('Experimental>SIMPLER', "Filter events for SIMPLER", self.OnFilterSIMPLER)
|
|
136
|
+
visFr.AddMenuItem('Experimental>SIMPLER', "Generate z estimates with SIMPLER", self.OnGenerateZSIMPLER)
|
|
137
|
+
visFr.AddMenuItem('Experimental>SIMPLER', itemType='separator')
|
|
138
|
+
# entries for N0 generation/interpolation
|
|
139
|
+
visFr.AddMenuItem('Experimental>SIMPLER', "Calculate Cluster modes for N0 (from origami)", self.OnModesN0SIMPLER)
|
|
140
|
+
visFr.AddMenuItem('Experimental>SIMPLER', "Interpolate N0 Map", self.OnInterpolateN0Field)
|
|
141
|
+
visFr.AddMenuItem('Experimental>SIMPLER', "Generate N0 Image Map from Background", self.bgrend.GenerateGUI)
|
|
142
|
+
visFr.AddMenuItem('Experimental>SIMPLER', itemType='separator')
|
|
143
|
+
# entries for showing N0, can also be used to save resulting image for later setting N0 by image
|
|
144
|
+
visFr.AddMenuItem('Experimental>SIMPLER', "Show N0 Map from N0 Interpolation file", self.OnShowN0Map)
|
|
145
|
+
|
|
146
|
+
def OnFilterSIMPLER(self, event):
|
|
147
|
+
from PYME.recipes.tablefilters import FilterTable
|
|
148
|
+
from PYME.recipes.tracking import FindClumps
|
|
149
|
+
recipe = self.visFr.pipeline.recipe
|
|
150
|
+
pipeline = self.visFr.pipeline
|
|
151
|
+
|
|
152
|
+
dlg = simplerFilterDialog(None)
|
|
153
|
+
ret = dlg.ShowModal()
|
|
154
|
+
if ret == wx.ID_OK:
|
|
155
|
+
minClumpSizePostFilt = dlg.GetClumpMinSize() + 2 # since 2 events are removed for edges
|
|
156
|
+
clumpName = recipe.new_output_name('with_clumps')
|
|
157
|
+
simplerName = recipe.new_output_name('simpler_filtered')
|
|
158
|
+
recipe.add_modules_and_execute([FindClumps(recipe, inputName=pipeline.selectedDataSourceKey,
|
|
159
|
+
outputName=clumpName,
|
|
160
|
+
timeWindow=0,
|
|
161
|
+
clumpRadiusVariable=dlg.GetClumpRadiusVariable(),
|
|
162
|
+
clumpRadiusScale=dlg.GetClumpRadiusMultiplier()),
|
|
163
|
+
FilterTable(recipe, inputName=clumpName,
|
|
164
|
+
outputName=simplerName,
|
|
165
|
+
filters={'clumpEdge' : [-0.1,0.1],
|
|
166
|
+
'clumpSize' : [minClumpSizePostFilt-0.5,1e5]})])
|
|
167
|
+
self.visFr.pipeline.selectDataSource(simplerName)
|
|
168
|
+
|
|
169
|
+
dlg.Destroy()
|
|
170
|
+
|
|
171
|
+
def OnGenerateZSIMPLER(self, event):
|
|
172
|
+
from PYMEcs.recipes.simpler import SIMPLERzgenerator
|
|
173
|
+
recipe = self.visFr.pipeline.recipe
|
|
174
|
+
pipeline = self.visFr.pipeline
|
|
175
|
+
|
|
176
|
+
szg = SIMPLERzgenerator(recipe,inputName='simpler_filtered',outputName='with_simpler_z')
|
|
177
|
+
if szg.configure_traits(kind='modal'):
|
|
178
|
+
recipe.add_modules_and_execute([szg])
|
|
179
|
+
self.visFr.pipeline.selectDataSource(szg.outputName)
|
|
180
|
+
|
|
181
|
+
def OnN0FromIinterpolationField(self, event):
|
|
182
|
+
from PYMEcs.recipes.simpler import N0FromInterpolationMap
|
|
183
|
+
recipe = self.visFr.pipeline.recipe
|
|
184
|
+
pipeline = self.visFr.pipeline
|
|
185
|
+
|
|
186
|
+
n0i = N0FromInterpolationMap(recipe,inputName=pipeline.selectedDataSourceKey,
|
|
187
|
+
outputName=recipe.new_output_name('with_N0'))
|
|
188
|
+
if n0i.configure_traits(kind='modal'):
|
|
189
|
+
recipe.add_modules_and_execute([n0i])
|
|
190
|
+
self.visFr.pipeline.selectDataSource(n0i.outputName)
|
|
191
|
+
|
|
192
|
+
def OnModesN0SIMPLER(self, event):
|
|
193
|
+
# what we have to do here:
|
|
194
|
+
# DBSCANclustering (currently use minClumpSize: 40, searchRadius: 35.0
|
|
195
|
+
# filter out clumpID 0 (not clustered)
|
|
196
|
+
# follow that by simpler.ClusterModes to determine modes of objects recognised as origami clusters
|
|
197
|
+
from PYMEcs.recipes.simpler import ClusterModes
|
|
198
|
+
from PYME.recipes import localisations, tablefilters
|
|
199
|
+
recipe = self.visFr.pipeline.recipe
|
|
200
|
+
pipeline = self.visFr.pipeline
|
|
201
|
+
recipe.add_modules_and_execute([localisations.DBSCANClustering(inputName='simpler_filtered',outputName='dbscanClumped',
|
|
202
|
+
minClumpSize=40,searchRadius=35.0),
|
|
203
|
+
tablefilters.FilterTable(inputName='dbscanClumped',outputName='validClusters',
|
|
204
|
+
filters={'dbscanClumpID':[0.5, 10000.0]}),
|
|
205
|
+
ClusterModes(inputName='validClusters',outputName='with_clusterModes')])
|
|
206
|
+
pipeline.selectDataSource('with_clusterModes')
|
|
207
|
+
|
|
208
|
+
def OnInterpolateN0Field(self, event):
|
|
209
|
+
from PYME.Analysis.points import twoColour
|
|
210
|
+
from PYME.DSView import View3D
|
|
211
|
+
from scipy.interpolate import Rbf, SmoothBivariateSpline
|
|
212
|
+
|
|
213
|
+
if not self.intMeth.configure_traits(kind='modal'):
|
|
214
|
+
return # do nothing
|
|
215
|
+
|
|
216
|
+
p = self.visFr.pipeline
|
|
217
|
+
|
|
218
|
+
idu,idx = np.unique(p['dbscanClumpID'],return_index=True)
|
|
219
|
+
ccx = p['clusterCentroid_x'][idx]
|
|
220
|
+
ccy = p['clusterCentroid_y'][idx]
|
|
221
|
+
cm = p['clusterMode'][idx]
|
|
222
|
+
cme = p['clusterModeError'][idx]
|
|
223
|
+
|
|
224
|
+
wonky = twoColour.findWonkyVectors(ccx, ccy, cm, cm, tol=2.0*cme.mean())
|
|
225
|
+
good = wonky == 0
|
|
226
|
+
cmn2 = 0.01*(cm-cm.mean())
|
|
227
|
+
cme2 = 0.01*cme
|
|
228
|
+
|
|
229
|
+
pixelsize = 100.0
|
|
230
|
+
x0=ccx.min()
|
|
231
|
+
x1=ccx.max()
|
|
232
|
+
y0=ccy.min()
|
|
233
|
+
y1=ccy.max()
|
|
234
|
+
nx = int((x1-x0)/pixelsize)
|
|
235
|
+
xn = x0+pixelsize*np.arange(nx+1)
|
|
236
|
+
ny = int((y1-y0)/pixelsize)
|
|
237
|
+
yn = y0+pixelsize*np.arange(ny+1)
|
|
238
|
+
xv,yv = np.meshgrid(xn,yn,indexing='ij')
|
|
239
|
+
|
|
240
|
+
if self.intMeth.InterpolationMethod == 'Splines':
|
|
241
|
+
spm = SmoothBivariateSpline(ccx[good], ccy[good], cm[good], 1./cme[good],bbox=[x0,x1,y0,y1])
|
|
242
|
+
#n0map = 100.0*spms(xv,yv,grid=False)+cm.mean()
|
|
243
|
+
n0map = spm(xv,yv,grid=False)
|
|
244
|
+
elif self.intMeth.InterpolationMethod == 'Radial Basis functions':
|
|
245
|
+
spm = Rbf(ccx[good], ccy[good], cm[good], epsilon=1)
|
|
246
|
+
n0map = spm(xv,yv)
|
|
247
|
+
elif self.intMeth.InterpolationMethod == 'Constraint Model':
|
|
248
|
+
spm = twoColour.lin3Model(ccx[good],ccy[good],cm[good],cme[good]**2)
|
|
249
|
+
# n0map = 100.0*spm(xv,yv)+cm.mean()
|
|
250
|
+
n0map = spm(xv,yv)
|
|
251
|
+
|
|
252
|
+
from PYME.IO.MetaDataHandler import origin_nm
|
|
253
|
+
origin = origin_nm(p.mdh)
|
|
254
|
+
origin_img = [origin[0]+xn[0], origin[1]+yn[0], origin[2]]
|
|
255
|
+
|
|
256
|
+
mdh=voxelsize_mdh(pixelsize)
|
|
257
|
+
mdh['ImageBounds.x0'] = xn[0]
|
|
258
|
+
mdh['ImageBounds.y0'] = yn[0]
|
|
259
|
+
mdh['ImageBounds.x1'] = xn[-1] + pixelsize
|
|
260
|
+
mdh['ImageBounds.y1'] = yn[-1] + pixelsize
|
|
261
|
+
mdh['ImageBounds.z0'] = 0
|
|
262
|
+
mdh['ImageBounds.z1'] = 0
|
|
263
|
+
mdh['Origin.x'] = origin_img[0]
|
|
264
|
+
mdh['Origin.y'] = origin_img[1]
|
|
265
|
+
mdh['Origin.z'] = 0
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
View3D(n0map, titleStub='Interpolated N0 - Method %s' % (self.intMeth.InterpolationMethod),
|
|
269
|
+
glCanvas=self.visFr.glCanvas, parent=self.visFr, mdh=mdh)
|
|
270
|
+
|
|
271
|
+
from six.moves import cPickle
|
|
272
|
+
bbox = [x0,x1,y0,y1]
|
|
273
|
+
fdialog = wx.FileDialog(None, 'Save N0 map as ...',
|
|
274
|
+
wildcard='N0 map file (*.n0m)|*.n0m',
|
|
275
|
+
style=wx.FD_SAVE)
|
|
276
|
+
succ = fdialog.ShowModal()
|
|
277
|
+
if (succ == wx.ID_OK):
|
|
278
|
+
fpath = fdialog.GetPath()
|
|
279
|
+
#save as a pickle containing the data and voxelsize
|
|
280
|
+
|
|
281
|
+
fid = open(fpath, 'wb')
|
|
282
|
+
cPickle.dump((spm,bbox,origin_img), fid, 2)
|
|
283
|
+
fid.close()
|
|
284
|
+
|
|
285
|
+
def OnShowN0Map(self, event):
|
|
286
|
+
from six.moves import cPickle
|
|
287
|
+
fdialog = wx.FileDialog(None, 'Please select N0 map to use ...',
|
|
288
|
+
wildcard='N0 map file (*.n0m)|*.n0m', style=wx.FD_OPEN)
|
|
289
|
+
succ = fdialog.ShowModal()
|
|
290
|
+
if (succ == wx.ID_OK):
|
|
291
|
+
nmFilename = fdialog.GetPath()
|
|
292
|
+
with open(nmFilename, 'rb') as fid:
|
|
293
|
+
n0m,bb,origin = cPickle.load(fid)
|
|
294
|
+
pixelsize = 100.0
|
|
295
|
+
x0,x1,y0,y1 = bb
|
|
296
|
+
nx = int((x1-x0)/pixelsize)
|
|
297
|
+
xn = x0+pixelsize*np.arange(nx+1)
|
|
298
|
+
ny = int((y1-y0)/pixelsize)
|
|
299
|
+
yn = y0+pixelsize*np.arange(ny+1)
|
|
300
|
+
xv,yv = np.meshgrid(xn,yn,indexing='ij')
|
|
301
|
+
|
|
302
|
+
mdh=voxelsize_mdh(pixelsize)
|
|
303
|
+
mdh['ImageBounds.x0'] = xn[0]
|
|
304
|
+
mdh['ImageBounds.y0'] = yn[0]
|
|
305
|
+
mdh['ImageBounds.x1'] = xn[-1] + pixelsize
|
|
306
|
+
mdh['ImageBounds.y1'] = yn[-1] + pixelsize
|
|
307
|
+
mdh['ImageBounds.z0'] = 0
|
|
308
|
+
mdh['ImageBounds.z1'] = 0
|
|
309
|
+
mdh['Origin.x'] = origin[0]
|
|
310
|
+
mdh['Origin.y'] = origin[1]
|
|
311
|
+
mdh['Origin.z'] = 0
|
|
312
|
+
|
|
313
|
+
from PYME.DSView import View3D
|
|
314
|
+
try:
|
|
315
|
+
n0map = n0m(xv,yv)
|
|
316
|
+
except ValueError:
|
|
317
|
+
n0map = n0m(xv,yv,grid=False)
|
|
318
|
+
|
|
319
|
+
View3D(n0map, titleStub='N0 Map', mdh=mdh,
|
|
320
|
+
glCanvas=self.visFr.glCanvas, parent=self.visFr)
|
|
321
|
+
|
|
322
|
+
def OnN0FromImage(self, event):
|
|
323
|
+
"""
|
|
324
|
+
|
|
325
|
+
Function to propagate N0 values from an image (or stack of images) to localizations within the pipeline.
|
|
326
|
+
Localizations in the same area (or volume) of image. ImageStack values will be given the N0 value from
|
|
327
|
+
corresponding values. The ImageStack containing the values is selected through the GUI.
|
|
328
|
+
|
|
329
|
+
Parameters
|
|
330
|
+
----------
|
|
331
|
+
event: GUI event
|
|
332
|
+
|
|
333
|
+
Returns
|
|
334
|
+
-------
|
|
335
|
+
Nothing, but adds N0 column to the pipeline
|
|
336
|
+
N0: N0 values from image, mapped to each localization within that label
|
|
337
|
+
"""
|
|
338
|
+
|
|
339
|
+
from PYME.IO import image
|
|
340
|
+
from PYMEcs.recipes.simpler import N0FromImage
|
|
341
|
+
#from PYME.Analysis.points import objectMeasure
|
|
342
|
+
|
|
343
|
+
visFr = self.visFr
|
|
344
|
+
pipeline = visFr.pipeline
|
|
345
|
+
recipe = pipeline.recipe
|
|
346
|
+
|
|
347
|
+
dlg = wx.SingleChoiceDialog(
|
|
348
|
+
None, 'choose the image which contains N0 values', 'Set N0',
|
|
349
|
+
list(image.openImages.keys()),
|
|
350
|
+
wx.CHOICEDLG_STYLE
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
if dlg.ShowModal() == wx.ID_OK:
|
|
354
|
+
img_name = dlg.GetStringSelection()
|
|
355
|
+
img = image.openImages[img_name]
|
|
356
|
+
|
|
357
|
+
recipe.namespace[img_name] = img
|
|
358
|
+
|
|
359
|
+
output_name = recipe.new_output_name('with_N0')
|
|
360
|
+
mod = N0FromImage(recipe, inputName=pipeline.selectedDataSourceKey,inputImage=img_name,
|
|
361
|
+
outputName=output_name,value_key_name='N0')
|
|
362
|
+
if mod.configure_traits(kind='modal'):
|
|
363
|
+
recipe.add_modules_and_execute([mod,])
|
|
364
|
+
pipeline.selectDataSource(mod.outputName)
|
|
365
|
+
|
|
366
|
+
dlg.Destroy()
|
|
367
|
+
|
|
368
|
+
def Plug(visFr):
|
|
369
|
+
return SIMPLER(visFr)
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
from traits.api import HasTraits, Str, Int, CStr, List, Enum, Float, Bool
|
|
2
|
+
from traitsui.api import View, Item, Group
|
|
3
|
+
from traitsui.menu import OKButton, CancelButton, OKCancelButtons
|
|
4
|
+
from PYME.DSView.dsviewer import View3D
|
|
5
|
+
from PYME.IO.MetaDataHandler import NestedClassMDHandler
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
from PYMEcs.Analysis.Sofi import calcCorrelates, calcCorrelatesI
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
# plugin interface to David's SOFI code
|
|
12
|
+
# current version allows integer zooming but no interface yet to calcCorrelatesZ
|
|
13
|
+
# this may better be addressed once the SOFI code data model modernisation has been considered
|
|
14
|
+
|
|
15
|
+
class SOFIconfig(HasTraits):
|
|
16
|
+
numberOfOrders = Int(3) # so far I have not seen to much reason to include higher orders
|
|
17
|
+
startAtFrame = Int(50)
|
|
18
|
+
stopAtFrame = Int(sys.maxsize)
|
|
19
|
+
filterHalfWidth = Int(25)
|
|
20
|
+
useZooming = Bool(False)
|
|
21
|
+
zoomFactor = Int(1)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
from PYME.DSView.modules._base import Plugin
|
|
25
|
+
class SOFIengine(Plugin):
|
|
26
|
+
def __init__(self, dsviewer):
|
|
27
|
+
Plugin.__init__(self, dsviewer)
|
|
28
|
+
self.sconf = SOFIconfig(stopAtFrame=self.dsviewer.image.data.shape[2])
|
|
29
|
+
|
|
30
|
+
dsviewer.AddMenuItem('Experimental>Sofi', "Calculate SOFI moments", self.OnCalcSofi)
|
|
31
|
+
|
|
32
|
+
def OnCalcSofi(self, event):
|
|
33
|
+
if not self.sconf.configure_traits(kind='modal'):
|
|
34
|
+
return
|
|
35
|
+
sc = self.sconf
|
|
36
|
+
data = self.dsviewer.image.data # need to check how to best switch to new data model
|
|
37
|
+
if sc.useZooming:
|
|
38
|
+
# note: we need to modify result voxel sizes if zooming!
|
|
39
|
+
corrs, means = calcCorrelatesI(data,
|
|
40
|
+
nOrders=sc.numberOfOrders,
|
|
41
|
+
zoom=sc.zoomFactor,
|
|
42
|
+
startAt=sc.startAtFrame,
|
|
43
|
+
stopAt=sc.stopAtFrame,
|
|
44
|
+
filtHalfWidth=sc.filterHalfWidth)
|
|
45
|
+
else:
|
|
46
|
+
corrs, means = calcCorrelates(data,
|
|
47
|
+
nOrders=sc.numberOfOrders,
|
|
48
|
+
startAt=sc.startAtFrame,
|
|
49
|
+
stopAt=sc.stopAtFrame,
|
|
50
|
+
filtHalfWidth=sc.filterHalfWidth)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
cmdh = NestedClassMDHandler(self.dsviewer.image.mdh)
|
|
54
|
+
cmdh['SofiProcessing.StartFrame'] = sc.startAtFrame
|
|
55
|
+
cmdh['SofiProcessing.StopFrame'] = sc.stopAtFrame
|
|
56
|
+
cmdh['SofiProcessing.FilterHalfWidth'] = sc.filterHalfWidth
|
|
57
|
+
cmdh['SofiProcessing.NumberOfOrders'] = sc.numberOfOrders
|
|
58
|
+
cmdh['SofiProcessing.Mode'] = 'moments'
|
|
59
|
+
if sc.useZooming: # is this the right way to handle voxel sizes? more suitable API interface available?
|
|
60
|
+
cmdh['voxelsize.x'] = self.dsviewer.image.mdh['voxelsize.x'] / float(sc.zoomFactor)
|
|
61
|
+
cmdh['voxelsize.y'] = self.dsviewer.image.mdh['voxelsize.y'] / float(sc.zoomFactor)
|
|
62
|
+
cmdh['SofiProcessing.ZoomFactor'] = sc.zoomFactor
|
|
63
|
+
|
|
64
|
+
mmdh = NestedClassMDHandler(self.dsviewer.image.mdh)
|
|
65
|
+
mmdh['SofiProcessing.StartFrame'] = sc.startAtFrame
|
|
66
|
+
mmdh['SofiProcessing.StopFrame'] = sc.stopAtFrame
|
|
67
|
+
mmdh['SofiProcessing.Mode'] = 'mean'
|
|
68
|
+
if sc.useZooming:
|
|
69
|
+
mmdh['voxelsize.x'] = self.dsviewer.image.mdh['voxelsize.x'] / float(sc.zoomFactor)
|
|
70
|
+
mmdh['voxelsize.y'] = self.dsviewer.image.mdh['voxelsize.y'] / float(sc.zoomFactor)
|
|
71
|
+
mmdh['SofiProcessing.ZoomFactor'] = sc.zoomFactor
|
|
72
|
+
|
|
73
|
+
View3D(corrs, titleStub='SOFI correlates', mdh=cmdh)
|
|
74
|
+
View3D(means, titleStub='Data mean', mdh=mmdh)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def Plug(dsviewer):
|
|
78
|
+
return SOFIengine(dsviewer)
|
|
File without changes
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import matplotlib.pyplot as plt
|
|
3
|
+
import wx
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
logger = logging.getLogger(__file__)
|
|
7
|
+
|
|
8
|
+
from traits.api import HasTraits, Str, Int, CStr, List, Enum, Float
|
|
9
|
+
from traitsui.api import View, Item, Group
|
|
10
|
+
from traitsui.menu import OKButton, CancelButton, OKCancelButtons
|
|
11
|
+
|
|
12
|
+
from PYME.DSView.dsviewer import ViewIm3D, ImageStack
|
|
13
|
+
|
|
14
|
+
class propertyChoice(HasTraits):
|
|
15
|
+
clist = List([])
|
|
16
|
+
EventProperty = Enum(values='clist')
|
|
17
|
+
BinByProperty = Enum(values='clist')
|
|
18
|
+
BinWidth = Float(100.0)
|
|
19
|
+
|
|
20
|
+
traits_view = View(Group(Item(name = 'EventProperty'),
|
|
21
|
+
Item(name = 'BinByProperty'),
|
|
22
|
+
Item('_'),
|
|
23
|
+
Item(name = 'BinWidth'),
|
|
24
|
+
label = 'Select Properties and Binning',
|
|
25
|
+
show_border = True),
|
|
26
|
+
buttons = OKCancelButtons)
|
|
27
|
+
|
|
28
|
+
def add_channels(self,chans):
|
|
29
|
+
for chan in chans:
|
|
30
|
+
if chan not in self.clist:
|
|
31
|
+
self.clist.append(chan)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class propertyChoice2D(HasTraits):
|
|
35
|
+
clist = List([])
|
|
36
|
+
EventProperty = Enum(values='clist')
|
|
37
|
+
BinWidth = Float(200.0)
|
|
38
|
+
StatsType = CStr('median')
|
|
39
|
+
|
|
40
|
+
traits_view = View(Group(Item(name = 'EventProperty'),
|
|
41
|
+
Item('_'),
|
|
42
|
+
Item(name = 'BinWidth'),
|
|
43
|
+
Item(name = 'StatsType'),
|
|
44
|
+
label = 'Select Properties and Binning',
|
|
45
|
+
show_border = True),
|
|
46
|
+
buttons = OKCancelButtons)
|
|
47
|
+
|
|
48
|
+
def add_channels(self,chans):
|
|
49
|
+
for chan in chans:
|
|
50
|
+
if chan not in self.clist:
|
|
51
|
+
self.clist.append(chan)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class PropertyBinning:
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
"""
|
|
58
|
+
def __init__(self, visFr):
|
|
59
|
+
self.visFr = visFr
|
|
60
|
+
self.pipeline = visFr.pipeline
|
|
61
|
+
|
|
62
|
+
visFr.AddMenuItem('Experimental>Event Processing',
|
|
63
|
+
'Bin Event Property by coordinate',
|
|
64
|
+
self.OnBinProperty,
|
|
65
|
+
helpText='Bin average an event property, e.g. background, as a function of another property, e.g. x')
|
|
66
|
+
|
|
67
|
+
visFr.AddMenuItem('Experimental>Event Processing',
|
|
68
|
+
'Bin Event Property in 2D',
|
|
69
|
+
self.OnBin2DProperty,
|
|
70
|
+
helpText='Bin average an event property, e.g. background, as a function of x and y coordinates')
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def OnBinProperty(self, event=None):
|
|
74
|
+
# these are the defaults
|
|
75
|
+
avProperty = 'nPhotons'
|
|
76
|
+
byProperty = 'x'
|
|
77
|
+
binwidth = 100
|
|
78
|
+
|
|
79
|
+
# traitsui dialog to set the event properties etc
|
|
80
|
+
pChoice = propertyChoice()
|
|
81
|
+
pChoice.add_channels(sorted(self.pipeline.keys()))
|
|
82
|
+
# select defaults if these event properties exist
|
|
83
|
+
if avProperty in pChoice.clist:
|
|
84
|
+
pChoice.EventProperty = avProperty
|
|
85
|
+
if byProperty in pChoice.clist:
|
|
86
|
+
pChoice.BinByProperty = byProperty
|
|
87
|
+
|
|
88
|
+
if pChoice.configure_traits(kind='modal'):
|
|
89
|
+
avProperty = pChoice.EventProperty
|
|
90
|
+
byProperty = pChoice.BinByProperty
|
|
91
|
+
binwidth = pChoice.BinWidth
|
|
92
|
+
else:
|
|
93
|
+
return
|
|
94
|
+
|
|
95
|
+
avp = self.pipeline[avProperty]
|
|
96
|
+
byp = self.pipeline[byProperty]
|
|
97
|
+
|
|
98
|
+
bypmin = byp.min()
|
|
99
|
+
bypmax = byp.max()
|
|
100
|
+
nbins = int((bypmax-bypmin)/binwidth)
|
|
101
|
+
bins = bypmin + np.arange(nbins+1)*binwidth
|
|
102
|
+
|
|
103
|
+
binctrs = 0.5*(bins[0:-1]+bins[1:])
|
|
104
|
+
|
|
105
|
+
avbin, abins = np.histogram(byp, bins=bins, weights=avp)
|
|
106
|
+
bybin, bybins = np.histogram(byp, bins=bins)
|
|
107
|
+
|
|
108
|
+
good = bybin > 0
|
|
109
|
+
bad = bybin <= 0
|
|
110
|
+
|
|
111
|
+
avmean = np.zeros_like(avbin,dtype='float64')
|
|
112
|
+
avmean[good] = avbin[good]/bybin[good]
|
|
113
|
+
avmean[bad] = np.nan
|
|
114
|
+
|
|
115
|
+
# direct matplotlib plotting scrapped for ImageStack approach
|
|
116
|
+
# which allows saving of data
|
|
117
|
+
#plt.figure()
|
|
118
|
+
#plt.plot(binctrs, avmean)
|
|
119
|
+
#plt.xlabel(byProperty)
|
|
120
|
+
#plt.ylabel('mean of %s' % avProperty)
|
|
121
|
+
|
|
122
|
+
plots = []
|
|
123
|
+
plots.append(avmean.reshape(-1, 1,1))
|
|
124
|
+
|
|
125
|
+
im = ImageStack(plots, titleStub='mean of %s' % avProperty)
|
|
126
|
+
im.xvals = binctrs
|
|
127
|
+
im.xlabel = byProperty
|
|
128
|
+
|
|
129
|
+
im.ylabel = 'mean of %s' % avProperty
|
|
130
|
+
im.defaultExt = '*.txt'
|
|
131
|
+
|
|
132
|
+
im.mdh['voxelsize.x'] = binwidth
|
|
133
|
+
im.mdh['ChannelNames'] = [avProperty]
|
|
134
|
+
im.mdh['Profile.XValues'] = im.xvals
|
|
135
|
+
im.mdh['Profile.XLabel'] = im.xlabel
|
|
136
|
+
im.mdh['Profile.YLabel'] = im.ylabel
|
|
137
|
+
|
|
138
|
+
im.mdh['OriginalImage'] = self.pipeline.filename
|
|
139
|
+
|
|
140
|
+
ViewIm3D(im, mode='graph', parent=wx.GetTopLevelParent(self.visFr))
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def OnBin2DProperty(self, event=None):
|
|
144
|
+
from scipy.stats import binned_statistic_2d
|
|
145
|
+
# these are the defaults
|
|
146
|
+
avProperty = 'nPhotons'
|
|
147
|
+
binwidth = 200 # 200 nm default
|
|
148
|
+
|
|
149
|
+
# traitsui dialog to set the event properties etc
|
|
150
|
+
pChoice = propertyChoice2D()
|
|
151
|
+
pChoice.add_channels(sorted(self.pipeline.keys()))
|
|
152
|
+
# select defaults if these event properties exist
|
|
153
|
+
if avProperty in pChoice.clist:
|
|
154
|
+
pChoice.EventProperty = avProperty
|
|
155
|
+
|
|
156
|
+
if pChoice.configure_traits(kind='modal'):
|
|
157
|
+
avProperty = pChoice.EventProperty
|
|
158
|
+
binwidth = pChoice.BinWidth
|
|
159
|
+
else:
|
|
160
|
+
return
|
|
161
|
+
|
|
162
|
+
avp = self.pipeline[avProperty]
|
|
163
|
+
x = self.pipeline['x']
|
|
164
|
+
y = self.pipeline['y']
|
|
165
|
+
xmin = x.min()
|
|
166
|
+
xmax = x.max()
|
|
167
|
+
ymin = y.min()
|
|
168
|
+
ymax = y.max()
|
|
169
|
+
|
|
170
|
+
nbinsx = int((xmax-xmin)/binwidth)
|
|
171
|
+
xbins = xmin + np.arange(nbinsx+1)*binwidth
|
|
172
|
+
nbinsy = int((ymax-ymin)/binwidth)
|
|
173
|
+
ybins = ymin + np.arange(nbinsy+1)*binwidth
|
|
174
|
+
|
|
175
|
+
propstats, x_edge, y_edge, binno = binned_statistic_2d(x,y,avp,statistic=pChoice.StatsType,bins=(xbins,ybins))
|
|
176
|
+
propstats[np.isnan(propstats)] = 0.0 # we replacenans with zeros (for now)
|
|
177
|
+
|
|
178
|
+
imps = ImageStack(propstats, titleStub = '%s Map' % avProperty)
|
|
179
|
+
imps.mdh.setEntry('voxelsize.x',1e-3*binwidth)
|
|
180
|
+
imps.mdh.setEntry('voxelsize.y',1e-3*binwidth)
|
|
181
|
+
|
|
182
|
+
ViewIm3D(imps)
|
|
183
|
+
|
|
184
|
+
def Plug(visFr):
|
|
185
|
+
"""Plugs this module into the gui"""
|
|
186
|
+
visFr.propBin = PropertyBinning(visFr)
|
|
187
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
class ParticleTracker2:
|
|
4
|
+
def __init__(self, visFr):
|
|
5
|
+
self.visFr = visFr
|
|
6
|
+
|
|
7
|
+
visFr.AddMenuItem('Experimental>Deprecated>Chaining', "Clump consecutive appearances", self.OnCoalesce)
|
|
8
|
+
|
|
9
|
+
def OnCoalesce(self, event):
|
|
10
|
+
from PYMEcs.recipes import localisations
|
|
11
|
+
recipe = self.visFr.pipeline.recipe
|
|
12
|
+
|
|
13
|
+
from PYMEcs.misc.utils import unique_name
|
|
14
|
+
outputName = unique_name('coalesced',self.visFr.pipeline.dataSources.keys())
|
|
15
|
+
recipe.add_module(localisations.MergeClumpsTperiod(recipe, inputName='with_clumps', outputName=outputName))
|
|
16
|
+
|
|
17
|
+
recipe.execute()
|
|
18
|
+
self.visFr.pipeline.selectDataSource(outputName)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def Plug(visFr):
|
|
22
|
+
"""Plugs this module into the gui"""
|
|
23
|
+
ParticleTracker2(visFr)
|