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,424 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created on Fri Mar 28 15:02:50 2014
|
|
4
|
+
|
|
5
|
+
@author: David Baddeley
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
# from pylab import fftn, ifftn, fftshift, ifftshift
|
|
10
|
+
from numpy.fft import fftn, ifftn, fftshift, ifftshift
|
|
11
|
+
|
|
12
|
+
import time
|
|
13
|
+
from scipy import ndimage
|
|
14
|
+
from PYME.Acquire import eventLog
|
|
15
|
+
#from PYME.gohlke import tifffile as tif
|
|
16
|
+
|
|
17
|
+
#import Pyro.core
|
|
18
|
+
#import Pyro.naming
|
|
19
|
+
import threading
|
|
20
|
+
from PYME.misc.computerName import GetComputerName
|
|
21
|
+
|
|
22
|
+
import logging
|
|
23
|
+
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
def correlateFrames(A, B):
|
|
26
|
+
A = A.squeeze()/A.mean() - 1
|
|
27
|
+
B = B.squeeze()/B.mean() - 1
|
|
28
|
+
|
|
29
|
+
X, Y = np.mgrid[0.0:A.shape[0], 0.0:A.shape[1]]
|
|
30
|
+
|
|
31
|
+
C = ifftshift(np.abs(ifftn(fftn(A)*ifftn(B))))
|
|
32
|
+
|
|
33
|
+
Cm = C.max()
|
|
34
|
+
|
|
35
|
+
Cp = np.maximum(C - 0.5*Cm, 0)
|
|
36
|
+
Cpsum = Cp.sum()
|
|
37
|
+
|
|
38
|
+
x0 = (X*Cp).sum()/Cpsum
|
|
39
|
+
y0 = (Y*Cp).sum()/Cpsum
|
|
40
|
+
|
|
41
|
+
return x0 - A.shape[0]/2, y0 - A.shape[1]/2, Cm, Cpsum
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def correlateAndCompareFrames(A, B):
|
|
45
|
+
A = A.squeeze()/A.mean() - 1
|
|
46
|
+
B = B.squeeze()/B.mean() - 1
|
|
47
|
+
|
|
48
|
+
X, Y = np.mgrid[0.0:A.shape[0], 0.0:A.shape[1]]
|
|
49
|
+
|
|
50
|
+
C = ifftshift(np.abs(ifftn(fftn(A)*ifftn(B))))
|
|
51
|
+
|
|
52
|
+
Cm = C.max()
|
|
53
|
+
|
|
54
|
+
Cp = np.maximum(C - 0.5*Cm, 0)
|
|
55
|
+
Cpsum = Cp.sum()
|
|
56
|
+
|
|
57
|
+
x0 = (X*Cp).sum()/Cpsum
|
|
58
|
+
y0 = (Y*Cp).sum()/Cpsum
|
|
59
|
+
|
|
60
|
+
dx, dy = x0 - A.shape[0]/2, y0 - A.shape[1]/2
|
|
61
|
+
|
|
62
|
+
As = ndimage.shift(A, [-dx, -dy])
|
|
63
|
+
|
|
64
|
+
#print A.shape, As.shape
|
|
65
|
+
|
|
66
|
+
return (As -B).mean(), dx, dy
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class Correlator(object):
|
|
70
|
+
def __init__(self, scope, piezo=None, stackHalfSize = 35):
|
|
71
|
+
self.scope = scope
|
|
72
|
+
self.piezo = piezo
|
|
73
|
+
|
|
74
|
+
self.focusTolerance = .05 #how far focus can drift before we correct
|
|
75
|
+
self.deltaZ = 0.2 #z increment used for calibration
|
|
76
|
+
self.stackHalfSize = stackHalfSize
|
|
77
|
+
self.NCalibStates = 2*self.stackHalfSize + 1
|
|
78
|
+
self.calibState = 0
|
|
79
|
+
|
|
80
|
+
self.tracking = False
|
|
81
|
+
self.lockActive = False
|
|
82
|
+
|
|
83
|
+
self.lockFocus = False
|
|
84
|
+
self.logShifts = True
|
|
85
|
+
|
|
86
|
+
self._last_target_z = -1
|
|
87
|
+
#self.initialise()
|
|
88
|
+
# self.buffer = []
|
|
89
|
+
self.WantRecord = False
|
|
90
|
+
self.minDelay = 10
|
|
91
|
+
self.maxfac = 1.5e3
|
|
92
|
+
self.Zfactor = 1.0
|
|
93
|
+
self.vsznm_x = 1.0
|
|
94
|
+
self.vsznm_y = 1.0
|
|
95
|
+
self.correctionFraction = 1.0 # fraction between 0.1..1
|
|
96
|
+
|
|
97
|
+
def initialise(self):
|
|
98
|
+
d = 1.0*self.scope.frameWrangler.currentFrame.squeeze()
|
|
99
|
+
|
|
100
|
+
self.X, self.Y = np.mgrid[0.0:d.shape[0], 0.0:d.shape[1]]
|
|
101
|
+
# self.X -= d.shape[0]/2
|
|
102
|
+
# self.Y -= d.shape[1]/2
|
|
103
|
+
self.X -= np.ceil(d.shape[0]*0.5)
|
|
104
|
+
self.Y -= np.ceil(d.shape[1]*0.5)
|
|
105
|
+
|
|
106
|
+
#we want to discard edges after accounting for x-y drift
|
|
107
|
+
self.mask = np.ones_like(d)
|
|
108
|
+
self.mask[:10, :] = 0
|
|
109
|
+
self.mask[-10:, :] = 0
|
|
110
|
+
self.mask[:, :10] = 0
|
|
111
|
+
self.mask[:,-10:] = 0
|
|
112
|
+
|
|
113
|
+
self.calibState = 0 #completely uncalibrated
|
|
114
|
+
|
|
115
|
+
self.corrRefMax = 0
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
self.lockFocus = False
|
|
119
|
+
self.lockActive = False
|
|
120
|
+
self.logShifts = True
|
|
121
|
+
self.timeSinceLastAdjustment = 5
|
|
122
|
+
self.homePos = self.piezo.GetPos(0)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
self.history = []
|
|
126
|
+
self.historyColNames = ['time','dx_nm','dy_nm','dz_nm','corrAmplitude','corrAmpMax','piezoOffset_nm','piezoPos_um']
|
|
127
|
+
self.historyStartTime = time.time()
|
|
128
|
+
self.historyCorrections = []
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
# def setRefA(self):
|
|
132
|
+
# d = 1.0*self.scope.frameWrangler.currentFrame.squeeze()
|
|
133
|
+
# self.refA = d/d.mean() - 1
|
|
134
|
+
# self.FA = ifftn(self.refA)
|
|
135
|
+
# self.refA *= self.mask
|
|
136
|
+
|
|
137
|
+
# def setRefB(self):
|
|
138
|
+
# d = 1.0*self.scope.frameWrangler.currentFrame.squeeze()
|
|
139
|
+
# self.refB = d/d.mean() - 1
|
|
140
|
+
# self.refB *= self.mask
|
|
141
|
+
|
|
142
|
+
# def setRefC(self):
|
|
143
|
+
# d = 1.0*self.scope.frameWrangler.currentFrame.squeeze()
|
|
144
|
+
# self.refC = d/d.mean() - 1
|
|
145
|
+
# self.refC *= self.mask
|
|
146
|
+
|
|
147
|
+
# self.dz = (self.refC - self.refB).ravel()
|
|
148
|
+
# self.dzn = 2./np.dot(self.dz, self.dz)
|
|
149
|
+
|
|
150
|
+
def setRefN(self, N):
|
|
151
|
+
d = 1.0*self.scope.frameWrangler.currentFrame.squeeze()
|
|
152
|
+
ref = d/d.mean() - 1
|
|
153
|
+
self.refImages[:,:,N] = ref
|
|
154
|
+
self.calFTs[:,:,N] = ifftn(ref)
|
|
155
|
+
self.calImages[:,:,N] = ref*self.mask
|
|
156
|
+
|
|
157
|
+
#def setRefD(self):
|
|
158
|
+
# self.refD = (1.0*self.d).squeeze()/self.d.mean() - 1
|
|
159
|
+
# self.refD *= self.mask
|
|
160
|
+
|
|
161
|
+
#self.dz = (self.refC - self.refA).ravel()
|
|
162
|
+
|
|
163
|
+
def set_focus_tolerance(self, tolerance):
|
|
164
|
+
""" Set the tolerance for locking position
|
|
165
|
+
|
|
166
|
+
Parameters
|
|
167
|
+
----------
|
|
168
|
+
|
|
169
|
+
tolerance : float
|
|
170
|
+
The tolerance in um
|
|
171
|
+
"""
|
|
172
|
+
|
|
173
|
+
self.focusTolerance = tolerance
|
|
174
|
+
|
|
175
|
+
def get_focus_tolerance(self):
|
|
176
|
+
return self.focusTolerance
|
|
177
|
+
|
|
178
|
+
def set_focus_lock(self, lock=True):
|
|
179
|
+
""" Set locking on or off
|
|
180
|
+
|
|
181
|
+
Parameters
|
|
182
|
+
----------
|
|
183
|
+
|
|
184
|
+
lock : bool
|
|
185
|
+
whether the lock should be on
|
|
186
|
+
"""
|
|
187
|
+
|
|
188
|
+
self.lockFocus = lock
|
|
189
|
+
|
|
190
|
+
def get_focus_lock(self):
|
|
191
|
+
return self.lockFocus
|
|
192
|
+
|
|
193
|
+
def get_history(self, length=1000):
|
|
194
|
+
try:
|
|
195
|
+
return self.history[-length:]
|
|
196
|
+
except AttributeError:
|
|
197
|
+
return []
|
|
198
|
+
|
|
199
|
+
def get_calibration_state(self):
|
|
200
|
+
""" Returns the current calibration state as a tuple:
|
|
201
|
+
|
|
202
|
+
(currentState, numStates)
|
|
203
|
+
|
|
204
|
+
calibration is complete when currentState == numStates.
|
|
205
|
+
"""
|
|
206
|
+
|
|
207
|
+
return self.calibState, self.NCalibStates
|
|
208
|
+
|
|
209
|
+
def is_tracking(self):
|
|
210
|
+
return self.tracking
|
|
211
|
+
|
|
212
|
+
def get_offset(self):
|
|
213
|
+
return self.piezo.GetOffset()
|
|
214
|
+
|
|
215
|
+
def set_offset(self, offset):
|
|
216
|
+
self.piezo.SetOffset(offset)
|
|
217
|
+
|
|
218
|
+
def compare(self):
|
|
219
|
+
d = 1.0*self.scope.frameWrangler.currentFrame.squeeze()
|
|
220
|
+
dm = d/d.mean() - 1
|
|
221
|
+
|
|
222
|
+
#where is the piezo suppposed to be
|
|
223
|
+
#nomPos = self.piezo.GetPos(0)
|
|
224
|
+
nomPos = self.piezo.GetTargetPos(0)
|
|
225
|
+
|
|
226
|
+
#find closest calibration position
|
|
227
|
+
posInd = np.argmin(np.abs(nomPos - self.calPositions))
|
|
228
|
+
|
|
229
|
+
#dz = float('inf')
|
|
230
|
+
#count = 0
|
|
231
|
+
#while np.abs(dz) > 0.5*self.deltaZ and count < 1:
|
|
232
|
+
# count += 1
|
|
233
|
+
|
|
234
|
+
#retrieve calibration information at this location
|
|
235
|
+
calPos = self.calPositions[posInd]
|
|
236
|
+
FA = self.calFTs[:,:,posInd]
|
|
237
|
+
refA = self.calImages[:,:,posInd]
|
|
238
|
+
|
|
239
|
+
ddz = self.dz[:,posInd]
|
|
240
|
+
dzn = self.dzn[posInd]
|
|
241
|
+
|
|
242
|
+
#what is the offset between our target position and the calibration position
|
|
243
|
+
posDelta = nomPos - calPos
|
|
244
|
+
|
|
245
|
+
#print('%s' % [nomPos, posInd, calPos, posDelta])
|
|
246
|
+
|
|
247
|
+
#find x-y drift
|
|
248
|
+
C = ifftshift(np.abs(ifftn(fftn(dm)*FA)))
|
|
249
|
+
|
|
250
|
+
Cm = C.max()
|
|
251
|
+
|
|
252
|
+
Cp = np.maximum(C - 0.5*Cm, 0)
|
|
253
|
+
Cpsum = Cp.sum()
|
|
254
|
+
|
|
255
|
+
dx = (self.X*Cp).sum()/Cpsum
|
|
256
|
+
dy = (self.Y*Cp).sum()/Cpsum
|
|
257
|
+
|
|
258
|
+
ds = ndimage.shift(dm, [-dx, -dy])*self.mask
|
|
259
|
+
|
|
260
|
+
#print A.shape, As.shape
|
|
261
|
+
|
|
262
|
+
self.ds_A = (ds - refA)
|
|
263
|
+
|
|
264
|
+
#calculate z offset between actual position and calibration position
|
|
265
|
+
dz = self.Zfactor*self.deltaZ*np.dot(self.ds_A.ravel(), ddz)*dzn
|
|
266
|
+
|
|
267
|
+
#posInd += np.round(dz / self.deltaZ)
|
|
268
|
+
#posInd = int(np.clip(posInd, 0, self.NCalibStates))
|
|
269
|
+
|
|
270
|
+
# print count, dz
|
|
271
|
+
|
|
272
|
+
#add the offset back to determine how far we are from the target position
|
|
273
|
+
dz = dz - posDelta
|
|
274
|
+
|
|
275
|
+
# if 1000*np.abs((dz + posDelta))>200 and self.WantRecord:
|
|
276
|
+
#dz = np.median(self.buffer)
|
|
277
|
+
# tif.imsave('C:\\Users\\Lab-test\\Desktop\\peakimage.tif', d)
|
|
278
|
+
# np.savetxt('C:\\Users\\Lab-test\\Desktop\\parameter.txt', self.buffer[-1])
|
|
279
|
+
#np.savetxt('C:\\Users\\Lab-test\\Desktop\\posDelta.txt', posDelta)
|
|
280
|
+
# self.WantRecord = False
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
#return dx, dy, dz + posDelta, Cm, dz, nomPos, posInd, calPos, posDelta
|
|
284
|
+
|
|
285
|
+
# TODO: check if dx and dy in nm works or if this gives issues down the line!
|
|
286
|
+
# UNITS: currently, dx & dy are in nm, dz in um -> make consistent?
|
|
287
|
+
return dx*self.vsznm_x, dy*self.vsznm_y, dz, Cm, dz, nomPos, posInd, calPos, posDelta
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def tick(self, **kwargs):
|
|
291
|
+
targetZ = self.piezo.GetTargetPos(0)
|
|
292
|
+
|
|
293
|
+
if not 'mask' in dir(self) or not self.scope.frameWrangler.currentFrame.shape[:2] == self.mask.shape[:2]:
|
|
294
|
+
self.initialise()
|
|
295
|
+
|
|
296
|
+
#called on a new frame becoming available
|
|
297
|
+
if self.calibState == 0:
|
|
298
|
+
#print "cal init"
|
|
299
|
+
#redefine our positions for the calibration
|
|
300
|
+
self.homePos = self.piezo.GetPos(0)
|
|
301
|
+
self.calPositions = self.homePos + self.deltaZ*np.arange(-float(self.stackHalfSize), float(self.stackHalfSize + 1))
|
|
302
|
+
self.NCalibStates = len(self.calPositions)
|
|
303
|
+
|
|
304
|
+
self.refImages = np.zeros(self.mask.shape[:2] + (self.NCalibStates,))
|
|
305
|
+
self.calImages = np.zeros(self.mask.shape[:2] + (self.NCalibStates,))
|
|
306
|
+
self.calFTs = np.zeros(self.mask.shape[:2] + (self.NCalibStates,), dtype='complex64')
|
|
307
|
+
|
|
308
|
+
self.piezo.MoveTo(0, self.calPositions[0])
|
|
309
|
+
|
|
310
|
+
#self.piezo.SetOffset(0)
|
|
311
|
+
self.calibState += .5
|
|
312
|
+
elif self.calibState < self.NCalibStates:
|
|
313
|
+
# print "cal proceed"
|
|
314
|
+
if (self.calibState % 1) == 0:
|
|
315
|
+
#full step - record current image and move on to next position
|
|
316
|
+
self.setRefN(int(self.calibState - 1))
|
|
317
|
+
self.piezo.MoveTo(0, self.calPositions[int(self.calibState)])
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
#increment our calibration state
|
|
321
|
+
self.calibState += 0.5
|
|
322
|
+
|
|
323
|
+
elif (self.calibState == self.NCalibStates):
|
|
324
|
+
# print "cal finishing"
|
|
325
|
+
self.setRefN(int(self.calibState - 1))
|
|
326
|
+
|
|
327
|
+
#perform final bit of calibration - calcuate gradient between steps
|
|
328
|
+
#self.dz = (self.refC - self.refB).ravel()
|
|
329
|
+
#self.dzn = 2./np.dot(self.dz, self.dz)
|
|
330
|
+
self.dz = np.gradient(self.calImages)[2].reshape(-1, self.NCalibStates)
|
|
331
|
+
self.dzn = np.hstack([1./np.dot(self.dz[:,i], self.dz[:,i]) for i in range(self.NCalibStates)])
|
|
332
|
+
|
|
333
|
+
self.piezo.MoveTo(0, self.homePos)
|
|
334
|
+
|
|
335
|
+
#reset our history log
|
|
336
|
+
self.history = []
|
|
337
|
+
self.historyCorrections = []
|
|
338
|
+
self.historyStartTime = time.time()
|
|
339
|
+
|
|
340
|
+
self.calibState += 1
|
|
341
|
+
|
|
342
|
+
elif (self.calibState > self.NCalibStates) and np.allclose(self._last_target_z, targetZ):
|
|
343
|
+
# print "fully calibrated"
|
|
344
|
+
dx, dy, dz, cCoeff, dzcorr, nomPos, posInd, calPos, posDelta = self.compare()
|
|
345
|
+
|
|
346
|
+
self.corrRefMax = max(self.corrRefMax, cCoeff)
|
|
347
|
+
|
|
348
|
+
#print dx, dy, dz
|
|
349
|
+
|
|
350
|
+
#FIXME: logging shouldn't call piezo.GetOffset() etc ... for performance reasons
|
|
351
|
+
# all history logged distances should now be in units of nm
|
|
352
|
+
|
|
353
|
+
# note that eventLog.logEvent injects into this instance of PYMEAcquire which runs the drift tracking
|
|
354
|
+
# this does not inject into the data acquired by the primary PYMEAcquire instance which are all done by the
|
|
355
|
+
# offset piezo and happen via the REST server communication
|
|
356
|
+
# as such, we need to modify the REST server methods to enable passing other parameters, e.g. the
|
|
357
|
+
# correlation strength
|
|
358
|
+
#
|
|
359
|
+
# it may be possible to achieve this via subclassing from offsetPiezoREST.OffsetPiezo and
|
|
360
|
+
# offsetPiezoREST.OffsetPiezoClient, for example by introducing a new method on both server and client
|
|
361
|
+
# Question: can we do it from within here? Probably more likely new module for offsetPiezoREST subclass
|
|
362
|
+
# and use in init file for driftracking
|
|
363
|
+
self.history.append((time.time(), dx, dy, 1e3*dz, cCoeff, self.corrRefMax, 1e3*self.piezo.GetOffset(), self.piezo.GetPos(0)))
|
|
364
|
+
eventLog.logEvent('PYME2ShiftMeasure', '%3.4f, %3.4f, %3.4f' % (dx, dy, dz))
|
|
365
|
+
|
|
366
|
+
self.latestPosData = [posInd, calPos, posDelta]
|
|
367
|
+
|
|
368
|
+
self.lockActive = self.lockFocus and (cCoeff > .5*self.corrRefMax)
|
|
369
|
+
if self.lockActive:
|
|
370
|
+
if abs(self.piezo.GetOffset()) > 20.0: # made >20 um of corrections - drop focus lock!
|
|
371
|
+
self.lockFocus = False
|
|
372
|
+
logger.info("focus lock released")
|
|
373
|
+
if abs(dz) > self.focusTolerance and self.timeSinceLastAdjustment >= self.minDelay:
|
|
374
|
+
zcorr = self.piezo.GetOffset() - self.correctionFraction*dz
|
|
375
|
+
if zcorr < - self.maxfac*self.focusTolerance:
|
|
376
|
+
zcorr = - self.maxfac*self.focusTolerance
|
|
377
|
+
if zcorr > self.maxfac*self.focusTolerance:
|
|
378
|
+
zcorr = self.maxfac*self.focusTolerance
|
|
379
|
+
self.piezo.SetOffset(zcorr)
|
|
380
|
+
|
|
381
|
+
#FIXME: this shouldn't be needed as it is logged during LogShifts anyway
|
|
382
|
+
self.piezo.LogFocusCorrection(zcorr) #inject offset changing into 'Events'
|
|
383
|
+
eventLog.logEvent('PYME2UpdateOffset', '%3.4f' % (zcorr))
|
|
384
|
+
|
|
385
|
+
self.historyCorrections.append((time.time(), dz))
|
|
386
|
+
self.timeSinceLastAdjustment = 0
|
|
387
|
+
else:
|
|
388
|
+
self.timeSinceLastAdjustment += 1
|
|
389
|
+
|
|
390
|
+
if self.logShifts:
|
|
391
|
+
if hasattr(self.piezo, 'LogShiftsCorrelAmp'):
|
|
392
|
+
self.piezo.LogShiftsCorrelAmp(dx, dy, dz, self.lockActive, coramp=cCoeff/self.corrRefMax)
|
|
393
|
+
else:
|
|
394
|
+
self.piezo.LogShifts(dx, dy, dz, self.lockActive)
|
|
395
|
+
|
|
396
|
+
self._last_target_z = targetZ
|
|
397
|
+
|
|
398
|
+
def reCalibrate(self):
|
|
399
|
+
self.calibState = 0
|
|
400
|
+
self.corrRefMax = 0
|
|
401
|
+
self.lockActive = False
|
|
402
|
+
|
|
403
|
+
def register(self):
|
|
404
|
+
#self.scope.frameWrangler.WantFrameGroupNotification.append(self.tick)
|
|
405
|
+
self.scope.frameWrangler.onFrameGroup.connect(self.tick)
|
|
406
|
+
self.tracking = True
|
|
407
|
+
|
|
408
|
+
def deregister(self):
|
|
409
|
+
#self.scope.frameWrangler.WantFrameGroupNotification.remove(self.tick)
|
|
410
|
+
self.scope.frameWrangler.onFrameGroup.disconnect(self.tick)
|
|
411
|
+
self.tracking = False
|
|
412
|
+
|
|
413
|
+
# def setRefs(self, piezo):
|
|
414
|
+
# time.sleep(0.5)
|
|
415
|
+
# p = piezo.GetPos()
|
|
416
|
+
# self.setRefA()
|
|
417
|
+
# piezo.MoveTo(0, p -.2)
|
|
418
|
+
# time.sleep(0.5)
|
|
419
|
+
# self.setRefB()
|
|
420
|
+
# piezo.MoveTo(0,p +.2)
|
|
421
|
+
# time.sleep(0.5)
|
|
422
|
+
# self.setRefC()
|
|
423
|
+
# piezo.MoveTo(0, p)
|
|
424
|
+
|