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.
Files changed (101) hide show
  1. PYMEcs/Acquire/Actions/__init__.py +0 -0
  2. PYMEcs/Acquire/Actions/custom.py +167 -0
  3. PYMEcs/Acquire/Hardware/LPthreadedSimple.py +248 -0
  4. PYMEcs/Acquire/Hardware/LPthreadedSimpleSim.py +246 -0
  5. PYMEcs/Acquire/Hardware/NikonTiFlaskServer.py +45 -0
  6. PYMEcs/Acquire/Hardware/NikonTiFlaskServerT.py +59 -0
  7. PYMEcs/Acquire/Hardware/NikonTiRESTClient.py +73 -0
  8. PYMEcs/Acquire/Hardware/NikonTiSim.py +35 -0
  9. PYMEcs/Acquire/Hardware/__init__.py +0 -0
  10. PYMEcs/Acquire/Hardware/driftTrackGUI.py +329 -0
  11. PYMEcs/Acquire/Hardware/driftTrackGUI_n.py +472 -0
  12. PYMEcs/Acquire/Hardware/driftTracking.py +424 -0
  13. PYMEcs/Acquire/Hardware/driftTracking_n.py +433 -0
  14. PYMEcs/Acquire/Hardware/fakeCamX.py +15 -0
  15. PYMEcs/Acquire/Hardware/offsetPiezoRESTCorrelLog.py +38 -0
  16. PYMEcs/Acquire/__init__.py +0 -0
  17. PYMEcs/Analysis/MBMcollection.py +552 -0
  18. PYMEcs/Analysis/MINFLUX.py +280 -0
  19. PYMEcs/Analysis/MapUtils.py +77 -0
  20. PYMEcs/Analysis/NPC.py +1176 -0
  21. PYMEcs/Analysis/Paraflux.py +218 -0
  22. PYMEcs/Analysis/Simpler.py +81 -0
  23. PYMEcs/Analysis/Sofi.py +140 -0
  24. PYMEcs/Analysis/__init__.py +0 -0
  25. PYMEcs/Analysis/decSofi.py +211 -0
  26. PYMEcs/Analysis/eventProperties.py +50 -0
  27. PYMEcs/Analysis/fitDarkTimes.py +569 -0
  28. PYMEcs/Analysis/objectVolumes.py +20 -0
  29. PYMEcs/Analysis/offlineTracker.py +130 -0
  30. PYMEcs/Analysis/stackTracker.py +180 -0
  31. PYMEcs/Analysis/timeSeries.py +63 -0
  32. PYMEcs/Analysis/trackFiducials.py +186 -0
  33. PYMEcs/Analysis/zerocross.py +91 -0
  34. PYMEcs/IO/MINFLUX.py +851 -0
  35. PYMEcs/IO/NPC.py +117 -0
  36. PYMEcs/IO/__init__.py +0 -0
  37. PYMEcs/IO/darkTimes.py +19 -0
  38. PYMEcs/IO/picasso.py +219 -0
  39. PYMEcs/IO/tabular.py +11 -0
  40. PYMEcs/__init__.py +0 -0
  41. PYMEcs/experimental/CalcZfactor.py +51 -0
  42. PYMEcs/experimental/FRC.py +338 -0
  43. PYMEcs/experimental/ImageJROItools.py +49 -0
  44. PYMEcs/experimental/MINFLUX.py +1537 -0
  45. PYMEcs/experimental/NPCcalcLM.py +560 -0
  46. PYMEcs/experimental/Simpler.py +369 -0
  47. PYMEcs/experimental/Sofi.py +78 -0
  48. PYMEcs/experimental/__init__.py +0 -0
  49. PYMEcs/experimental/binEventProperty.py +187 -0
  50. PYMEcs/experimental/chaining.py +23 -0
  51. PYMEcs/experimental/clusterTrack.py +179 -0
  52. PYMEcs/experimental/combine_maps.py +104 -0
  53. PYMEcs/experimental/eventProcessing.py +93 -0
  54. PYMEcs/experimental/fiducials.py +323 -0
  55. PYMEcs/experimental/fiducialsNew.py +402 -0
  56. PYMEcs/experimental/mapTools.py +271 -0
  57. PYMEcs/experimental/meas2DplotDh5view.py +107 -0
  58. PYMEcs/experimental/mortensen.py +131 -0
  59. PYMEcs/experimental/ncsDenoise.py +158 -0
  60. PYMEcs/experimental/onTimes.py +295 -0
  61. PYMEcs/experimental/procPoints.py +77 -0
  62. PYMEcs/experimental/pyme2caml.py +73 -0
  63. PYMEcs/experimental/qPAINT.py +965 -0
  64. PYMEcs/experimental/randMap.py +188 -0
  65. PYMEcs/experimental/regExtraCmaps.py +11 -0
  66. PYMEcs/experimental/selectROIfilterTable.py +72 -0
  67. PYMEcs/experimental/showErrs.py +51 -0
  68. PYMEcs/experimental/showErrsDh5view.py +58 -0
  69. PYMEcs/experimental/showShiftMap.py +56 -0
  70. PYMEcs/experimental/snrEvents.py +188 -0
  71. PYMEcs/experimental/specLabeling.py +51 -0
  72. PYMEcs/experimental/splitRender.py +246 -0
  73. PYMEcs/experimental/testChannelByName.py +36 -0
  74. PYMEcs/experimental/timedSpecies.py +28 -0
  75. PYMEcs/experimental/utils.py +31 -0
  76. PYMEcs/misc/ExtraCmaps.py +177 -0
  77. PYMEcs/misc/__init__.py +0 -0
  78. PYMEcs/misc/configUtils.py +169 -0
  79. PYMEcs/misc/guiMsgBoxes.py +27 -0
  80. PYMEcs/misc/mapUtils.py +230 -0
  81. PYMEcs/misc/matplotlib.py +136 -0
  82. PYMEcs/misc/rectsFromSVG.py +182 -0
  83. PYMEcs/misc/shellutils.py +1110 -0
  84. PYMEcs/misc/utils.py +205 -0
  85. PYMEcs/misc/versionCheck.py +20 -0
  86. PYMEcs/misc/zcInfo.py +90 -0
  87. PYMEcs/pyme_warnings.py +4 -0
  88. PYMEcs/recipes/__init__.py +0 -0
  89. PYMEcs/recipes/base.py +75 -0
  90. PYMEcs/recipes/localisations.py +2380 -0
  91. PYMEcs/recipes/manipulate_yaml.py +83 -0
  92. PYMEcs/recipes/output.py +177 -0
  93. PYMEcs/recipes/processing.py +247 -0
  94. PYMEcs/recipes/simpler.py +290 -0
  95. PYMEcs/version.py +2 -0
  96. pyme_extra-1.0.4.post0.dist-info/METADATA +114 -0
  97. pyme_extra-1.0.4.post0.dist-info/RECORD +101 -0
  98. pyme_extra-1.0.4.post0.dist-info/WHEEL +5 -0
  99. pyme_extra-1.0.4.post0.dist-info/entry_points.txt +3 -0
  100. pyme_extra-1.0.4.post0.dist-info/licenses/LICENSE +674 -0
  101. pyme_extra-1.0.4.post0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,402 @@
1
+ import numpy as np
2
+ import matplotlib.pyplot as plt
3
+
4
+ import logging
5
+ logger = logging.getLogger(__file__)
6
+
7
+ # interpolate the key from the source to the selected datasource of the pipeline
8
+ def finterpDS(pipeline,sourcep,key):
9
+ tsource, idx = np.unique(sourcep['t'], return_index=True)
10
+ fsource = sourcep[key][idx]
11
+ fDS = np.interp(pipeline.selectedDataSource['t'], tsource, fsource)
12
+ return fDS
13
+
14
+ def zshift(t,data,navg=50):
15
+ ti,idx = np.unique(t.astype('int'),return_index=True)
16
+ di = data[idx]
17
+ nm = min(navg,di.shape[0])
18
+ offset = di[0:nm].mean()
19
+ return data - offset
20
+
21
+ from traits.api import HasTraits, Str, Int, CStr, List, Enum, Float
22
+ #from traitsui.api import View, Item, Group
23
+ #from traitsui.menu import OKButton, CancelButton, OKCancelButtons
24
+
25
+ class SetZPars(HasTraits):
26
+ scaleFactor = Float(-1e3)
27
+ shiftFrames = Int(0)
28
+
29
+ class FiducialTracker:
30
+ """
31
+
32
+ """
33
+ def __init__(self, visFr):
34
+ self.visFr = visFr
35
+ self.pipeline = visFr.pipeline
36
+
37
+ visFr.AddMenuItem('Experimental>Deprecated>Fiducials', 'Add mean fiducial track', self.OnFiducialTrack,
38
+ helpText='Add mean fiducial track')
39
+ visFr.AddMenuItem('Experimental>Deprecated>Fiducials', 'New DS with mean fiducial track applied',
40
+ self.OnFiducialCorrectDS,
41
+ helpText='Apply mean fiducial track')
42
+ visFr.AddMenuItem('Experimental>Deprecated>Fiducials', "Plot Fiducial Track", self.OnPlotFiducial,
43
+ helpText='Plot mean fiducial tracks for all available dims')
44
+ visFr.AddMenuItem('Experimental>Deprecated>Fiducials', "Set Z Parameters", self.OnSetZPars,
45
+ helpText='Set shift and scale parameters for driftz track')
46
+ visFr.AddMenuItem('Experimental>Deprecated>Fiducials', "Set Z drift (from aligned driftz)", self.OnSetZDrift,
47
+ helpText='Set Z drift compensation from scaled and aligned driftz track')
48
+ visFr.AddMenuItem('Experimental>Deprecated>Fiducials', "Clear Z driftz mapping", self.clearDriftZ,
49
+ helpText='Remove Z drift mapping by popping any mapping for z')
50
+ visFr.AddMenuItem('Experimental>Deprecated>Fiducials', "Diagnose Fiducials", lambda e: self.fiducial_diagnosis(),
51
+ helpText='Diagnose quality of fiducial correction')
52
+ visFr.AddMenuItem('Experimental>Deprecated>Fiducials', "Compare fiducial and drift", self.fiducialvsdrift,
53
+ helpText='Compare fiducial and drift information')
54
+ visFr.AddMenuItem('Experimental>Corrections',"Fiducial - extract fiducial track and correct datasource",
55
+ self.OnFiducialCorrectNew,
56
+ helpText='faster tracking by inserting FiducialTrack and FiducialApplyFromFiducials modules')
57
+
58
+ self.scaleFactor = -1e3
59
+ self.shiftFrames = 0
60
+ self.zeroAlignFrames = 200
61
+ self.zDrift = None
62
+
63
+
64
+ def OnFiducialCorrectNew(self, event=None):
65
+ from PYMEcs.recipes import localisations
66
+ recipe = self.pipeline.recipe
67
+ # change defaults back to median filter
68
+ ftrack = localisations.FiducialTrack(recipe, inputName='Fiducials',
69
+ filterMethod='Median',
70
+ outputName='fiducialAdded')
71
+ if not ftrack.configure_traits(kind='modal'):
72
+ return
73
+ recipe.add_module(ftrack)
74
+ recipe.add_module(localisations.FiducialApplyFromFiducials(recipe, inputData=self.pipeline.selectedDataSourceKey,
75
+ inputFiducials='fiducialAdded',
76
+ outputName='fiducialApplied',
77
+ outputFiducials='corrected_fiducials'))
78
+ recipe.execute()
79
+ self.pipeline.selectDataSource('fiducialApplied')
80
+
81
+ def OnFiducialTrack(self, event=None):
82
+ """
83
+
84
+ """
85
+ from PYMEcs.recipes import localisations
86
+
87
+ if False:
88
+ fTracker = localisations.FiducialTrack(filterMethod = 'Gaussian')
89
+ if fTracker.configure_traits(kind='modal'):
90
+ # we call this with the pipeline to allow filtering etc
91
+ namespace = {fTracker.inputName: self.pipeline}
92
+ fTracker.execute(namespace)
93
+
94
+ # the fiducial needs to be entered for the whole data source
95
+ # otherwise we have an issue that fiducial data is not available
96
+ # when filters are changed; this makes the code a bit ugly
97
+ ds = namespace[fTracker.outputName]
98
+ for fiducial in ['fiducial_%s' % dim for dim in ['x','y','z']]:
99
+ if fiducial in ds.keys():
100
+ self.pipeline.selectedDataSource.addColumn(fiducial,
101
+ finterpDS(self.pipeline,
102
+ ds,
103
+ fiducial))
104
+ pds = self.pipeline.selectedDataSource
105
+ isfid = np.zeros(len(pds['x']), dtype='i')
106
+ isfid[self.pipeline.filter.Index] = ds['isFiducial']
107
+ pds.addColumn('isFiducial',isfid)
108
+ else:
109
+ recipe = self.pipeline.recipe
110
+ recipe.add_module(localisations.FiducialTrack(recipe, inputName=self.pipeline.selectedDataSourceKey,
111
+ outputName='with_fiducial'))
112
+ recipe.execute()
113
+ self.pipeline.selectDataSource('with_fiducial')
114
+
115
+ def OnFiducialCorrectDS(self, event=None):
116
+ """
117
+
118
+ """
119
+ from PYMEcs.recipes.localisations import FiducialApply
120
+ recipe = self.pipeline.recipe
121
+ recipe.add_module(FiducialApply(recipe, inputName='with_fiducial',
122
+ outputName='corrected_from_fiducial'))
123
+ recipe.execute()
124
+ self.pipeline.selectDataSource('corrected_from_fiducial')
125
+
126
+ #self.visFr.RefreshView()
127
+ #self.visFr.CreateFoldPanel()
128
+
129
+
130
+ def OnPlotFiducial(self, event):
131
+ import PYMEnf.DriftCorrection.compactFit as cf
132
+
133
+ pipeline = self.visFr.pipeline
134
+ t = pipeline['t']
135
+ x = pipeline['fiducial_x']
136
+ y = pipeline['fiducial_y']
137
+ z = pipeline['fiducial_z']
138
+
139
+ tu,idx = np.unique(t.astype('int'), return_index=True)
140
+ xu = x[idx]
141
+ yu = y[idx]
142
+ zu = z[idx]
143
+
144
+ hasdp = True
145
+ try:
146
+ driftPane = self.visFr.driftPane
147
+ except:
148
+ hasdp = False
149
+
150
+ import matplotlib.pyplot as plt
151
+ plt.figure()
152
+ plt.plot(tu, xu, label='x')
153
+ plt.plot(tu, yu, label='y')
154
+ plt.plot(tu, zu, label='z')
155
+ if hasdp:
156
+ if 'driftx' in driftPane.dp.driftExprX:
157
+ indepVars = { 't': t, 'driftx': pipeline['driftx'], 'drifty': pipeline['drifty'] }
158
+ dx,dy,tt = cf.xyDriftCurves(driftPane.dp.driftCorrFcn,driftPane.dp.driftCorrParams,indepVars,t)
159
+ plt.plot(tt,-zshift(tt,dx), '--', label='x-drift')
160
+ plt.plot(tt,-zshift(tt,dy), '--', label='y-drift')
161
+ ti = np.arange(tt.min(),tt.max(),dtype=t.dtype)
162
+ tu,iu = np.unique(t,return_index=True)
163
+ dzi = zshift(ti,np.interp(ti,tu,pipeline['driftz'][iu]),navg=self.zeroAlignFrames)
164
+ dzir = self.scaleFactor*np.roll(dzi,self.shiftFrames)
165
+ self.zDrift = [ti, dzir]
166
+ plt.plot(ti, dzir, '--', label='z-drift')
167
+ plt.legend()
168
+
169
+
170
+ def OnSetZPars(self, event=None):
171
+ setPar = SetZPars(scaleFactor=self.scaleFactor,shiftFrames=self.shiftFrames,zeroAlignFrames = self.zeroAlignFrames)
172
+ if setPar.configure_traits(kind='modal'):
173
+ self.scaleFactor = setPar.scaleFactor
174
+ self.shiftFrames = setPar.shiftFrames
175
+ self.zeroAlignFrames = setPar.zeroAlignFrames
176
+
177
+
178
+ def OnSetZDrift(self, event=None):
179
+ if self.zDrift is None:
180
+ logger.error('No zDrift found - cannot correct drift')
181
+ return
182
+ t, dz = self.zDrift
183
+ self.visFr.pipeline.mapping.dz = np.interp(self.visFr.pipeline.mapping['t'], t, dz)
184
+ self.visFr.pipeline.mapping.setMapping('z', 'z - dz')
185
+
186
+ self.visFr.pipeline.ClearGenerated()
187
+
188
+ def clearDriftZ(self, event=None):
189
+ try:
190
+ self.visFr.pipeline.mapping.mappings.pop('z')
191
+ except KeyError:
192
+ pass
193
+
194
+ self.visFr.pipeline.ClearGenerated()
195
+
196
+
197
+ def fiducial_diagnosis(self):
198
+ import numpy as np
199
+ import matplotlib.pyplot as plt
200
+ from PYME.Analysis.points.fiducials import FILTER_FUNCS
201
+ pipeline = self.pipeline
202
+
203
+ fids = pipeline.dataSources['corrected_fiducials']
204
+ if 'clumpIndex' in fids.keys():
205
+ ci = fids['clumpIndex']
206
+
207
+ #cis = np.arange(1, ci.max())
208
+
209
+ #clump_lengths = [(ci == c).sum() for c in cis]
210
+
211
+ #largest_clump = ci == cis[np.argmax(clump_lengths)]
212
+
213
+ #x_c = fids['x'][largest_clump]
214
+ #y_c = fids['y'][largest_clump]
215
+
216
+ f1 = plt.figure()
217
+ a1 = plt.axes()
218
+ plt.title('Y residuals')
219
+ plt.grid()
220
+ f2 = plt.figure()
221
+ plt.title('X residuuals')
222
+ a2 = plt.axes()
223
+ plt.grid()
224
+ f3 = plt.figure()
225
+ plt.title('Z residuuals')
226
+ a3 = plt.axes()
227
+ plt.grid()
228
+
229
+ sel_ids = np.unique(fids['fiducialID'])
230
+ for pos in range(sel_ids.shape[0]):
231
+ a1.text(-250, pos * 50, "%d" % sel_ids[pos])
232
+ a2.text(-250, pos * 50, "%d" % sel_ids[pos])
233
+ a3.text(-250, pos * 150, "%d" % sel_ids[pos])
234
+
235
+ for i in range(1, ci.max()+1):
236
+ mask = fids['clumpIndex'] == i
237
+ if mask.sum() > 0:
238
+ f_id = fids['fiducialID'][mask][0]
239
+ pos = np.where(sel_ids==f_id)[0][0] # position in set of selected ids
240
+
241
+ fid_m = fids['fiducialID'] == f_id
242
+
243
+ ym = fids['y'][fid_m].mean()
244
+ xm = fids['x'][fid_m].mean()
245
+ zm = fids['z'][fid_m].mean()
246
+
247
+ # also plot a filtered version to see the trend in the noisy trace
248
+ yfilt = FILTER_FUNCS['Median'](fids['t'][mask],{'y':fids['y'][mask]},13)
249
+ xfilt = FILTER_FUNCS['Median'](fids['t'][mask],{'x':fids['x'][mask]},13)
250
+ zfilt = FILTER_FUNCS['Median'](fids['t'][mask],{'z':fids['z'][mask]},13)
251
+
252
+ a1.plot(fids['t'][mask], fids['y'][mask] - ym + pos * 50,
253
+ color=plt.cm.hsv( (i % 20.0)/20.))
254
+ a1.plot(fids['t'][mask], yfilt['y'] - ym + pos * 50, '--',
255
+ color='#b0b0b0', alpha=0.7)
256
+
257
+ a2.plot(fids['t'][mask], fids['x'][mask] - xm + pos * 50,
258
+ color=plt.cm.hsv((i % 20.0) / 20.))
259
+ a2.plot(fids['t'][mask], xfilt['x'] - xm + pos * 50, '--',
260
+ color='#b0b0b0', alpha=0.7)
261
+
262
+ a3.plot(fids['t'][mask], fids['z'][mask] - zm + pos * 150,
263
+ color=plt.cm.hsv((i % 20.0) / 20.))
264
+ a3.plot(fids['t'][mask], zfilt['z'] - zm + pos * 150, '--',
265
+ color='#b0b0b0', alpha=0.7)
266
+
267
+ else:
268
+ # stuff to do when no clumpIndex
269
+ f1 = plt.figure()
270
+ a1 = plt.axes()
271
+ plt.title('Y residuals')
272
+ plt.grid()
273
+ f2 = plt.figure()
274
+ plt.title('X residuuals')
275
+ a2 = plt.axes()
276
+ plt.grid()
277
+ f3 = plt.figure()
278
+ plt.title('Z residuuals')
279
+ a3 = plt.axes()
280
+ plt.grid()
281
+
282
+ ym = fids['y'].mean()
283
+ xm = fids['x'].mean()
284
+ zm = fids['z'].mean()
285
+
286
+ # also plot a filtered version to see the trend in the noisy trace
287
+ yfilt = FILTER_FUNCS['Median'](fids['t'],{'y':fids['y']},13)
288
+ xfilt = FILTER_FUNCS['Median'](fids['t'],{'x':fids['x']},13)
289
+ zfilt = FILTER_FUNCS['Median'](fids['t'],{'z':fids['z']},13)
290
+
291
+ a1.plot(fids['t'], fids['y'] - ym)
292
+ a1.plot(fids['t'], yfilt['y'] - ym, '--',
293
+ color='#b0b0b0', alpha=0.7)
294
+
295
+ a2.plot(fids['t'], fids['x'] - xm)
296
+ a2.plot(fids['t'], xfilt['x'] - xm, '--',
297
+ color='#b0b0b0', alpha=0.7)
298
+
299
+ a3.plot(fids['t'], fids['z'] - zm)
300
+ a3.plot(fids['t'], zfilt['z'] - zm, '--',
301
+ color='#b0b0b0', alpha=0.7)
302
+
303
+ # plot the trace derived from the fiducials
304
+ tuq, idx = np.unique(fids['t'], return_index=True)
305
+ fidz = fids['fiducial_z'][idx]
306
+ fidy = fids['fiducial_y'][idx]
307
+ fidx = fids['fiducial_x'][idx]
308
+ plt.figure()
309
+ plt.subplot(311)
310
+ plt.plot(tuq, -fidz, label = 'fiducial z')
311
+ plt.title('Fiducial z')
312
+ plt.subplot(312)
313
+ plt.plot(tuq, -fidx, label = 'fiducial x')
314
+ plt.title('Fiducial x')
315
+ plt.subplot(313)
316
+ plt.plot(tuq, -fidy, label = 'fiducial y')
317
+ plt.title('Fiducial y')
318
+
319
+
320
+ def fiducialvsdrift(self, event=None):
321
+ from PYMEcs.misc.guiMsgBoxes import Warn
322
+ from scipy.optimize import leastsq
323
+ import PYMEcs.misc.shellutils as su
324
+
325
+ dfunc = lambda p, v: -100.0*p[0]*v[0]-100.0*p[1]*v[1]
326
+ efunc = lambda p, fx, fy, dx, dy: np.append(fx-dfunc(p[:2],[dx,dy]),
327
+ fy-dfunc(p[2:],[dx,dy]))
328
+ zfunc = lambda p, dz: p[0]*dz + p[1]
329
+ ezfunc = lambda p, fz, dz: fz-zfunc(p,dz)
330
+
331
+ pipeline = self.pipeline
332
+ if 'corrected_fiducials' not in pipeline.dataSources:
333
+ Warn(self.visFr,"no 'corrected_fiducials' data source")
334
+ return
335
+
336
+ if 'driftx' not in pipeline.keys():
337
+ Warn(self.visFr,"no 'driftx' property")
338
+ return
339
+
340
+ fids = pipeline.dataSources['corrected_fiducials']
341
+
342
+ tuq, idx = np.unique(fids['t'], return_index=True)
343
+ fidz = fids['fiducial_z'][idx]
344
+ fidy = fids['fiducial_y'][idx]
345
+ fidx = fids['fiducial_x'][idx]
346
+
347
+ # what do we do when these do not exist?
348
+ # answer: we may have to interpolate onto the times from the normal pipeline -> check that approach
349
+
350
+ tup, idxp = np.unique(pipeline['t'], return_index=True)
351
+ dxp = pipeline['driftx'][idxp]
352
+ dyp = pipeline['drifty'][idxp]
353
+ dzp = pipeline['driftz'][idxp]
354
+
355
+ dx = np.interp(tuq, tup, dxp)
356
+ dy = np.interp(tuq, tup, dyp)
357
+ dz = np.interp(tuq, tup, dzp)
358
+
359
+ #dy = fids['drifty'][idx]
360
+ #dx = fids['driftx'][idx]
361
+
362
+ fx = su.zs(fidx)
363
+ fy = su.zs(fidy)
364
+ fz = su.zs(fidz)
365
+
366
+ dxx = su.zs(dx)
367
+ dyy = su.zs(dy)
368
+ p,suc = leastsq(efunc,np.zeros(4),args=(fx,fy,dxx,dyy))
369
+
370
+ pz,sucz = leastsq(ezfunc,[-1e3,0],args=(fz,dz))
371
+
372
+ plt.figure()
373
+ plt.plot(tuq,fx,label='fiducial x')
374
+ plt.plot(tuq,dfunc(p[:2],[dxx,dyy]),label='best fit x drift')
375
+
376
+ plt.plot(tuq,fy,label='fiducial y')
377
+ plt.plot(tuq,dfunc(p[2:],[dxx,dyy]),label='best fit y drift')
378
+ plt.legend()
379
+ plt.xlabel('Time (frames)')
380
+ plt.ylabel('Drift (nm)')
381
+ plt.title("Best fit params (a11 %.2f,a12 %.2f,a21 %.2f,a22 %.2f): " % tuple(p.tolist()))
382
+
383
+ plt.figure()
384
+ plt.plot(tuq,fz,label='fiducial z')
385
+ plt.plot(tuq,zfunc(pz,dz),label='best fit z drift')
386
+ plt.legend()
387
+ plt.xlabel('Time (frames)')
388
+ plt.ylabel('Drift (nm)')
389
+ plt.title("Best fit parameters (zfactor %.2f, zoffs %.2f): " % tuple(pz.tolist()))
390
+
391
+ plt.figure()
392
+ plt.plot(tuq,fx-dfunc(p[:2],[dxx,dyy]),label='x difference')
393
+ plt.plot(tuq,fy-dfunc(p[2:],[dxx,dyy])+50,label='y difference (+50 nm offset)')
394
+ plt.plot(tuq,fz-zfunc(pz,dz)+100,label='z difference (+100 nm offset)')
395
+ plt.legend()
396
+ plt.xlabel('Time (frames)')
397
+ plt.ylabel('Drift (nm)')
398
+ plt.grid()
399
+
400
+ def Plug(visFr):
401
+ """Plugs this module into the gui"""
402
+ FiducialTracker(visFr)
@@ -0,0 +1,271 @@
1
+ import wx
2
+ from wx.lib.dialogs import ScrolledMessageDialog
3
+
4
+ from PYME.localization.remFitBuf import CameraInfoManager
5
+ import PYME.Analysis.gen_sCMOS_maps as gmaps
6
+ from PYME.IO.MetaDataHandler import NestedClassMDHandler
7
+ from PYME.IO.image import ImageStack
8
+ from PYME.DSView import ViewIm3D
9
+ import numpy as np
10
+
11
+ from PYMEcs.misc.mapUtils import defaultCalibrationDir,defaultMapName,installedCams,install_map,\
12
+ checkAndInstallMap,installMapsFrom,getInstalledMapList,check_mapexists,mk_compositeMap,\
13
+ addMap2composite,export_mapFromComposite,_getDefaultMap,get_dark_default,get_variance_default,\
14
+ get_flatfield_default
15
+
16
+ import logging
17
+ logger = logging.getLogger(__name__)
18
+
19
+ # FUNCTIONAILITY that would be good to add
20
+ # - check all installed maps for sanity etc
21
+ # - install a single map file (rather than whole directory)
22
+ # - force option for install maps commands
23
+ # generally: better API for map functions than current ones in
24
+ # PYME.Analysis.gen_sCMOS_maps
25
+ # CameraInfoManager in PYME.localization.remFitBuf
26
+
27
+
28
+
29
+ from traits.api import HasTraits, Str, Int, CStr, List, Enum, Float
30
+ from traitsui.api import View, Item, Group
31
+ from traitsui.menu import OKButton, CancelButton, OKCancelButtons
32
+
33
+ from PYMEcs.misc.guiMsgBoxes import Warn
34
+
35
+ class cameraChoice(HasTraits):
36
+ _clist = List([])
37
+ Camera = Enum(values='_clist')
38
+
39
+ traits_view = View(Group(Item(name = 'Camera'),
40
+ label = 'Select Camera',
41
+ show_border = True),
42
+ buttons = OKCancelButtons)
43
+
44
+ def add_cams(self,camlist):
45
+ for cam in camlist:
46
+ if cam not in self._clist:
47
+ self._clist.append(cam)
48
+
49
+ class meanVarianceCalc(HasTraits):
50
+ Start = Int(0)
51
+ End = Int(-1)
52
+
53
+
54
+ class mapTools:
55
+ """
56
+ GUI class to supply various map tools
57
+ """
58
+ def __init__(self, dsviewer):
59
+ self.dsviewer = dsviewer
60
+ self.do = dsviewer.do
61
+ self.image = dsviewer.image
62
+ self.ci = CameraInfoManager()
63
+ self.loadedMaps = {}
64
+
65
+ dsviewer.AddMenuItem('Experimental>Map Tools',
66
+ 'Convert current frame to photo-electron counts',
67
+ self.OnPhotonConvert)
68
+ dsviewer.AddMenuItem('Experimental>Map Tools',
69
+ 'Calculate Mean and Variance of frame sequence',
70
+ self.OnMeanVariance)
71
+ dsviewer.AddMenuItem('Experimental>Map Tools',
72
+ 'Show dark map',
73
+ self.OnShowDark)
74
+ dsviewer.AddMenuItem('Experimental>Map Tools',
75
+ 'Show variance map',
76
+ self.OnShowVariance)
77
+ dsviewer.AddMenuItem('Experimental>Map Tools',
78
+ 'Show flatfield map',
79
+ self.OnShowFlatField)
80
+ dsviewer.AddMenuItem('Experimental>Map Tools',
81
+ 'List installed maps',
82
+ self.OnListMaps)
83
+ dsviewer.AddMenuItem('Experimental>Map Tools',
84
+ 'Install maps to system calibration directory',
85
+ self.OnInstallMapsToSystem)
86
+ dsviewer.AddMenuItem('Experimental>Map Tools',
87
+ 'Copy maps from system to user directory',
88
+ self.OnCopyMapsToUserDir)
89
+
90
+
91
+ def getMapSafely(self, type='dark'):
92
+ try:
93
+ mdh = self.dsviewer.LMAnalyser.analysisController.analysisMDH
94
+ except AttributeError:
95
+ mdh = self.image.mdh
96
+ try:
97
+ theMap = self.ci.getDarkMap(mdh)
98
+ self.loadedMaps[type] = mdh
99
+ except IOError:
100
+ logger.exception('Dark map specified but not found, falling back on defaults')
101
+ (theMap,mdh2) = _getDefaultMap(self.ci,mdh,type,return_loadedmdh=True)
102
+ self.loadedMaps[type] = mdh2
103
+ return theMap
104
+
105
+
106
+ def showMap(self, type='dark'):
107
+ mdh2 = NestedClassMDHandler(self.image.mdh)
108
+ # # overwrite the map location with default maps if exist
109
+ # if check_mapexists(mdh2,type=type) is None:
110
+ # Warn(None,'no suitable map in default location')
111
+ # return
112
+
113
+ check_mapexists(mdh2,type=type)
114
+
115
+ theMap = self.getMapSafely(type)
116
+ twoDMap = np.ones(self.image.data.shape[0:2])*theMap # promote to 2D if necessary
117
+
118
+ im = ImageStack(twoDMap, titleStub = '%s Map' % type.capitalize())
119
+ im.mdh.copyEntriesFrom(mdh2)
120
+
121
+ if self.dsviewer.mode == 'visGUI':
122
+ mode = 'visGUI'
123
+ else:
124
+ mode = 'lite'
125
+
126
+ dv = ViewIm3D(im, mode=mode, glCanvas=self.dsviewer.glCanvas, parent=wx.GetTopLevelParent(self.dsviewer))
127
+
128
+
129
+ def OnShowDark(self, event=None):
130
+ self.showMap(type='dark')
131
+
132
+ def OnShowVariance(self, event=None):
133
+ self.showMap(type='variance')
134
+
135
+ def OnShowFlatField(self, event=None):
136
+ self.showMap(type='flatfield')
137
+
138
+ def OnMeanVariance(self, event=None):
139
+ mvChoice = meanVarianceCalc(End=self.image.data.shape[2]-1)
140
+ if not mvChoice.configure_traits(kind='modal'):
141
+ return
142
+
143
+ m, v = gmaps._meanvards(self.image.data,start=mvChoice.Start,end=mvChoice.End)
144
+ mmdh = NestedClassMDHandler(self.image.mdh)
145
+ mmdh.setEntry('Analysis.name', 'mean-variance')
146
+ mmdh.setEntry('Analysis.start', mvChoice.Start)
147
+ mmdh.setEntry('Analysis.end', mvChoice.End)
148
+ mmdh.setEntry('Analysis.resultname', 'mean')
149
+ mmdh.setEntry('Analysis.units', 'ADU')
150
+
151
+ imm = ImageStack(m, mdh=mmdh, titleStub = 'Mean')
152
+
153
+ vmdh = NestedClassMDHandler(mmdh)
154
+ vmdh.setEntry('Analysis.resultname', 'variance')
155
+ vmdh.setEntry('Analysis.units', 'ADU^2')
156
+
157
+ imv = ImageStack(v, mdh=vmdh, titleStub = 'Variance')
158
+
159
+ if self.dsviewer.mode == 'visGUI':
160
+ mode = 'visGUI'
161
+ else:
162
+ mode = 'lite'
163
+
164
+ dv = ViewIm3D(imm, mode=mode, glCanvas=self.dsviewer.glCanvas,
165
+ parent=wx.GetTopLevelParent(self.dsviewer))
166
+ dv = ViewIm3D(imv, mode=mode, glCanvas=self.dsviewer.glCanvas,
167
+ parent=wx.GetTopLevelParent(self.dsviewer))
168
+
169
+ def OnPhotonConvert(self, event=None):
170
+
171
+ # we try color channel 0; should only be done on monochrome anyway
172
+ curFrame = self.image.data[:,:, self.do.zp, 0].squeeze()
173
+
174
+ # this makes a new metadata structure that copies all entries from the argument
175
+ mdh2 = NestedClassMDHandler(self.image.mdh)
176
+ # some old files do not have a camera serialname
177
+ # fake one, which ensures no map is found and we get uniform maps
178
+ try:
179
+ t = mdh2['Camera.SerialNumber']
180
+ except AttributeError:
181
+ mdh2['Camera.SerialNumber'] = 'XXXXX'
182
+
183
+ # overwrite the map location with default maps if exist
184
+ check_mapexists(mdh2,type='dark')
185
+ check_mapexists(mdh2,type='flatfield')
186
+
187
+ #darkf = self.ci.getDarkMap(mdh2)
188
+ darkf = self.getMapSafely(type='dark')
189
+ corrFrame = float(mdh2['Camera.ElectronsPerCount'])*self.ci.correctImage(mdh2, curFrame)/mdh2.getEntry('Camera.TrueEMGain')
190
+
191
+ im = ImageStack(corrFrame, titleStub = 'Frame %d in photoelectron units' % self.do.zp)
192
+ im.mdh.copyEntriesFrom(mdh2)
193
+ im.mdh['Parent'] = self.image.filename
194
+ im.mdh['Units'] = 'PhotoElectrons'
195
+ im.mdh['Camera.ElectronsPerCount'] = 1.0
196
+ im.mdh['Camera.TrueEMGain'] = 1.0
197
+ im.mdh['Camera.ADOffset'] = 0
198
+
199
+ if self.dsviewer.mode == 'visGUI':
200
+ mode = 'visGUI'
201
+ else:
202
+ mode = 'lite'
203
+
204
+ dv = ViewIm3D(im, mode=mode, glCanvas=self.dsviewer.glCanvas, parent=wx.GetTopLevelParent(self.dsviewer))
205
+
206
+
207
+ def OnListMaps(self, event=None):
208
+
209
+ maps = getInstalledMapList()
210
+ if len(maps) > 0:
211
+ dlg = ScrolledMessageDialog(self.dsviewer, "\n".join(maps), "Installed maps", size=(900,400),
212
+ style=wx.RESIZE_BORDER | wx.DEFAULT_DIALOG_STYLE )
213
+ dlg.ShowModal()
214
+ dlg.Destroy()
215
+ else:
216
+ Warn(None,'no suitable maps found')
217
+
218
+
219
+ def OnInstallMapsToSystem(self, event=None):
220
+ instmsg = 'Install maps from user directory...'
221
+ fdialog = wx.DirDialog(None, instmsg,
222
+ style=wx.DD_DEFAULT_STYLE|wx.DD_DIR_MUST_EXIST|wx.DD_CHANGE_DIR)
223
+
224
+ if fdialog.ShowModal() == wx.ID_OK:
225
+ dirSelection = fdialog.GetPath().encode()
226
+ fdialog.Destroy()
227
+ else:
228
+ fdialog.Destroy()
229
+ return
230
+
231
+ inst, msg = installMapsFrom(dirSelection, calibrationDir=defaultCalibrationDir)
232
+
233
+ dlg = ScrolledMessageDialog(self.dsviewer, msg, instmsg, size=(900,400),
234
+ style=wx.RESIZE_BORDER | wx.DEFAULT_DIALOG_STYLE )
235
+ dlg.ShowModal()
236
+ dlg.Destroy()
237
+
238
+
239
+ def OnCopyMapsToUserDir(self, event=None):
240
+ import os
241
+ instmsg = 'Copy maps to user directory...'
242
+ cdict = {os.path.basename(camdir) : camdir for camdir in installedCams()}
243
+ cdict['All Cameras'] = defaultCalibrationDir
244
+
245
+ cChoice = cameraChoice()
246
+ cChoice.add_cams(sorted(cdict.keys()))
247
+ if not cChoice.configure_traits(kind='modal'):
248
+ return
249
+ camdir = cdict[cChoice.Camera]
250
+
251
+ fdialog = wx.DirDialog(None, instmsg,
252
+ style=wx.DD_DEFAULT_STYLE|wx.DD_DIR_MUST_EXIST|wx.DD_CHANGE_DIR)
253
+
254
+ if fdialog.ShowModal() == wx.ID_OK:
255
+ dirSelection = fdialog.GetPath().encode()
256
+ fdialog.Destroy()
257
+ else:
258
+ fdialog.Destroy()
259
+ return
260
+
261
+ inst, msg = installMapsFrom(camdir, calibrationDir=dirSelection)
262
+
263
+ dlg = ScrolledMessageDialog(self.dsviewer, msg, instmsg, size=(900,400),
264
+ style=wx.RESIZE_BORDER | wx.DEFAULT_DIALOG_STYLE )
265
+ dlg.ShowModal()
266
+ dlg.Destroy()
267
+
268
+
269
+
270
+ def Plug(dsviewer):
271
+ dsviewer.mapTool = mapTools(dsviewer)