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,59 @@
|
|
|
1
|
+
from flask import Flask, request, jsonify, make_response
|
|
2
|
+
from http import HTTPStatus
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
def create_app(mode='simulated'):
|
|
6
|
+
# create and configure the app
|
|
7
|
+
app = Flask(__name__)
|
|
8
|
+
|
|
9
|
+
if mode == 'simulated':
|
|
10
|
+
from PYMEcs.Acquire.Hardware.LPthreadedSimpleSim import LPThread
|
|
11
|
+
else:
|
|
12
|
+
from PYMEcs.Acquire.Hardware.LPthreadedSimple import LPThread
|
|
13
|
+
|
|
14
|
+
# so that we can see which thread processes the various messages, commands
|
|
15
|
+
logging.basicConfig(level=logging.DEBUG,
|
|
16
|
+
format='(%(threadName)-9s) %(message)s',)
|
|
17
|
+
|
|
18
|
+
lpt = LPThread(name='NikonTiThread')
|
|
19
|
+
lpt.start()
|
|
20
|
+
|
|
21
|
+
@app.get("/names")
|
|
22
|
+
def get_names():
|
|
23
|
+
status, names = lpt.run_command('GetNames')
|
|
24
|
+
return jsonify(names)
|
|
25
|
+
|
|
26
|
+
@app.get("/port")
|
|
27
|
+
def get_port():
|
|
28
|
+
status, port = lpt.run_command('GetPort')
|
|
29
|
+
response = make_response(port, status)
|
|
30
|
+
response.mimetype = "text/plain"
|
|
31
|
+
return response
|
|
32
|
+
|
|
33
|
+
@app.put("/port")
|
|
34
|
+
def set_port():
|
|
35
|
+
port = request.get_data().decode("utf-8")
|
|
36
|
+
status = lpt.run_command('SetPort',port)
|
|
37
|
+
return port, status
|
|
38
|
+
|
|
39
|
+
@app.get("/position")
|
|
40
|
+
def get_position():
|
|
41
|
+
status, pos = lpt.run_command('GetPosition')
|
|
42
|
+
response = make_response(str(pos), status)
|
|
43
|
+
response.mimetype = "text/plain"
|
|
44
|
+
return response
|
|
45
|
+
|
|
46
|
+
@app.put("/position")
|
|
47
|
+
def set_position():
|
|
48
|
+
pos = int(request.get_data().decode("utf-8"))
|
|
49
|
+
status = lpt.run_command('SetPosition',pos)
|
|
50
|
+
return str(pos), status
|
|
51
|
+
|
|
52
|
+
return app
|
|
53
|
+
|
|
54
|
+
if __name__ == '__main__':
|
|
55
|
+
app.run(threaded=False, processes=1)
|
|
56
|
+
|
|
57
|
+
# invoke from the command line as, for example:
|
|
58
|
+
#
|
|
59
|
+
# flask --app 'PYMEcs.Acquire.Hardware.NikonTiFlaskServerT:create_app(mode="production")' --debug run
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
from urllib.parse import urljoin
|
|
3
|
+
import logging
|
|
4
|
+
from http import HTTPStatus
|
|
5
|
+
from PYMEcs.Acquire.Hardware.NikonTiSim import LightPath as TiLightPath
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
# by basing it on the simulator we inherit the "generic" methods, i.e.
|
|
10
|
+
# ProvideMetadata, OnChange and Poll
|
|
11
|
+
# which are required for the functional object when used with
|
|
12
|
+
# PYMEAcquire
|
|
13
|
+
class LPClient(TiLightPath):
|
|
14
|
+
def __init__(self, url="http://127.0.0.1:5000", timeout=15):
|
|
15
|
+
self.url = url
|
|
16
|
+
self.timeout = timeout
|
|
17
|
+
self.wantChangeNotification = []
|
|
18
|
+
|
|
19
|
+
self.names = self.GetNames() # execute the method once and then keep the values cached
|
|
20
|
+
self.lastPosition = self.GetPosition() # initialise here as later used in Poll method
|
|
21
|
+
|
|
22
|
+
def GetPosition(self):
|
|
23
|
+
response = requests.get(urljoin(self.url,'position'),timeout=self.timeout)
|
|
24
|
+
if response.status_code == HTTPStatus.OK:
|
|
25
|
+
position = int(response.content.decode())
|
|
26
|
+
return position
|
|
27
|
+
else:
|
|
28
|
+
logger.warn("HTTP response error: got status %d" % response.status_code)
|
|
29
|
+
return None
|
|
30
|
+
|
|
31
|
+
def SetPosition(self,position):
|
|
32
|
+
response = requests.put(urljoin(self.url,'position'),data=str(position),timeout=self.timeout)
|
|
33
|
+
if response.status_code == HTTPStatus.OK:
|
|
34
|
+
newpos = int(response.content.decode())
|
|
35
|
+
if newpos != position:
|
|
36
|
+
logger.warn("asked for position '%d' but got position '%s'" % (newpos,position))
|
|
37
|
+
self.lastPosition = newpos # update so that OnChange works ok
|
|
38
|
+
self.OnChange()
|
|
39
|
+
else:
|
|
40
|
+
logger.warn("HTTP response error: got status %d" % response.status_code)
|
|
41
|
+
|
|
42
|
+
def GetPort(self):
|
|
43
|
+
response = requests.get(urljoin(self.url,'port'),timeout=self.timeout)
|
|
44
|
+
if response.status_code == HTTPStatus.OK:
|
|
45
|
+
port = response.content.decode()
|
|
46
|
+
return port
|
|
47
|
+
else:
|
|
48
|
+
logger.warn("HTTP response error: got status %d" % response.status_code)
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
def SetPort(self,port):
|
|
52
|
+
if port in self.names:
|
|
53
|
+
response = requests.put(urljoin(self.url,'port'),data=port,timeout=self.timeout)
|
|
54
|
+
if response.status_code == HTTPStatus.OK:
|
|
55
|
+
newport = response.content.decode()
|
|
56
|
+
if newport != port:
|
|
57
|
+
logger.warn("asked for port '%s' but got port '%s'" % (newport,port))
|
|
58
|
+
self.lastPosition = self.GetPosition() # update so that OnChange works ok
|
|
59
|
+
self.OnChange()
|
|
60
|
+
else:
|
|
61
|
+
logger.warn("HTTP response error: got status %d" % response.status_code)
|
|
62
|
+
else:
|
|
63
|
+
logger.warn("Asking for unknown port '%s', ignoring" % port)
|
|
64
|
+
|
|
65
|
+
def GetNames(self):
|
|
66
|
+
response = requests.get(urljoin(self.url,"names"),timeout=self.timeout)
|
|
67
|
+
if response.status_code == HTTPStatus.OK:
|
|
68
|
+
names = response.json()
|
|
69
|
+
return names
|
|
70
|
+
else:
|
|
71
|
+
logger.warn("HTTP response error: got status %d" % response.status_code)
|
|
72
|
+
return None
|
|
73
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
class LightPath:
|
|
2
|
+
def __init__(self, names = ['EYE', 'L100', 'R100', 'L80']):
|
|
3
|
+
self.simulatedPosition = 1
|
|
4
|
+
self.names = names
|
|
5
|
+
self.wantChangeNotification = []
|
|
6
|
+
|
|
7
|
+
self.lastPosition = self.GetPosition()
|
|
8
|
+
|
|
9
|
+
def SetPosition(self, pos):
|
|
10
|
+
self.simulatedPosition = (pos + 1)
|
|
11
|
+
self.lastPosition = pos
|
|
12
|
+
self.OnChange()
|
|
13
|
+
|
|
14
|
+
def GetPosition(self):
|
|
15
|
+
return int(self.simulatedPosition) - 1
|
|
16
|
+
|
|
17
|
+
def SetPort(self, port):
|
|
18
|
+
self.SetPosition(self.names.index(port))
|
|
19
|
+
self.OnChange()
|
|
20
|
+
|
|
21
|
+
def GetPort(self):
|
|
22
|
+
return self.names[self.GetPosition()]
|
|
23
|
+
|
|
24
|
+
def ProvideMetadata(self,mdh):
|
|
25
|
+
mdh.setEntry('NikonTi.LightPath', self.GetPort())
|
|
26
|
+
|
|
27
|
+
def OnChange(self):
|
|
28
|
+
for a in self.wantChangeNotification:
|
|
29
|
+
a()
|
|
30
|
+
|
|
31
|
+
def Poll(self):
|
|
32
|
+
pos = self.GetPosition()
|
|
33
|
+
if not self.lastPosition == pos:
|
|
34
|
+
self.lastPosition = pos
|
|
35
|
+
self.OnChange()
|
|
File without changes
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
#!/usr/bin/python
|
|
2
|
+
|
|
3
|
+
##################
|
|
4
|
+
# <filename>.py
|
|
5
|
+
#
|
|
6
|
+
# Copyright David Baddeley, 2012
|
|
7
|
+
# d.baddeley@auckland.ac.nz
|
|
8
|
+
#
|
|
9
|
+
# This file may NOT be distributed without express permision from David Baddeley
|
|
10
|
+
#
|
|
11
|
+
##################
|
|
12
|
+
import wx
|
|
13
|
+
|
|
14
|
+
import numpy as np
|
|
15
|
+
from PYME.contrib.wxPlotPanel import PlotPanel
|
|
16
|
+
from PYME.IO import MetaDataHandler
|
|
17
|
+
from PYME.DSView import dsviewer as dsviewer
|
|
18
|
+
import PYME.IO.image as im
|
|
19
|
+
|
|
20
|
+
from PYMEcs.misc.guiMsgBoxes import Info, Warn
|
|
21
|
+
|
|
22
|
+
import os
|
|
23
|
+
|
|
24
|
+
import logging
|
|
25
|
+
logger = logging.getLogger(__name__)
|
|
26
|
+
|
|
27
|
+
class TrackerPlotPanel(PlotPanel):
|
|
28
|
+
# import matplotlib.pyplot as plt # not needed if we use object based method for tight_layout
|
|
29
|
+
def __init__(self, parent, driftTracker, *args, **kwargs):
|
|
30
|
+
self.dt = driftTracker
|
|
31
|
+
PlotPanel.__init__(self, parent, *args, **kwargs)
|
|
32
|
+
|
|
33
|
+
# add 5th suplot
|
|
34
|
+
# replace 4th plot with offset and
|
|
35
|
+
# new 5th subplot for z-pos (how calculated, z-nominal + dz?, remove offset)
|
|
36
|
+
def draw(self):
|
|
37
|
+
if self.IsShownOnScreen():
|
|
38
|
+
if not hasattr( self, 'subplotxy' ):
|
|
39
|
+
self.subplotxy = self.figure.add_subplot( 411 )
|
|
40
|
+
self.subplotz = self.figure.add_subplot( 412 )
|
|
41
|
+
self.subploto = self.figure.add_subplot( 413 )
|
|
42
|
+
self.subplotc = self.figure.add_subplot(414)
|
|
43
|
+
# hopefully this sets it always for this fig, see https://matplotlib.org/stable/tutorials/intermediate/tight_layout_guide.html
|
|
44
|
+
self.figure.set_tight_layout(True)
|
|
45
|
+
# plt.tight_layout() # can we call as object oriented? do we need to call each time plotted?
|
|
46
|
+
|
|
47
|
+
try:
|
|
48
|
+
t, dx, dy, dz, corr, corrmax, poffset, pos = np.array(self.dt.get_history(1000)).T
|
|
49
|
+
except ValueError:
|
|
50
|
+
do_plot = False
|
|
51
|
+
else:
|
|
52
|
+
do_plot = True
|
|
53
|
+
|
|
54
|
+
if do_plot:
|
|
55
|
+
# note: we now assume that all history values that are distances are provided in nm
|
|
56
|
+
# this SHOULD match the conventions in driftTracking.py
|
|
57
|
+
|
|
58
|
+
# a few reused variables
|
|
59
|
+
tolnm = 1e3*self.dt.get_focus_tolerance()
|
|
60
|
+
tdelta = t - self.dt.historyStartTime
|
|
61
|
+
trange = [tdelta.min(), tdelta.max()]
|
|
62
|
+
|
|
63
|
+
self.subplotxy.cla()
|
|
64
|
+
self.subplotxy.plot(tdelta, dx, 'r')
|
|
65
|
+
self.subplotxy.plot(tdelta, dy, 'g')
|
|
66
|
+
self.subplotxy.set_ylabel('dx/dy (r/g) [nm]')
|
|
67
|
+
self.subplotxy.set_xlim(*trange)
|
|
68
|
+
|
|
69
|
+
self.subplotz.cla()
|
|
70
|
+
self.subplotz.plot(tdelta, dz, 'b')
|
|
71
|
+
self.subplotz.plot([tdelta[0],tdelta[-1]],[tolnm,tolnm], 'g--')
|
|
72
|
+
self.subplotz.plot([tdelta[0],tdelta[-1]],[-tolnm,-tolnm], 'g--')
|
|
73
|
+
self.subplotz.set_ylabel('dz [nm]')
|
|
74
|
+
self.subplotz.set_xlim(*trange)
|
|
75
|
+
|
|
76
|
+
self.subploto.cla()
|
|
77
|
+
self.subploto.plot(tdelta, poffset, 'm')
|
|
78
|
+
self.subploto.set_ylabel('offs [nm]')
|
|
79
|
+
self.subploto.set_xlim(*trange)
|
|
80
|
+
|
|
81
|
+
self.subplotc.cla()
|
|
82
|
+
self.subplotc.plot(tdelta, corr/corrmax, 'r')
|
|
83
|
+
self.subplotc.set_ylabel('C/C_m')
|
|
84
|
+
self.subplotc.set_xlim(*trange)
|
|
85
|
+
self.subplotc.set_xlabel('Time (s)')
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
#except:
|
|
90
|
+
# pass
|
|
91
|
+
|
|
92
|
+
#self.subplot.set_xlim(0, 512)
|
|
93
|
+
#self.subplot.set_ylim(0, 256)
|
|
94
|
+
|
|
95
|
+
self.canvas.draw()
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
# add controls for lastAdjustment
|
|
100
|
+
class DriftTrackingControl(wx.Panel):
|
|
101
|
+
def __init__(self, parent, driftTracker, winid=-1, showPlots=True):
|
|
102
|
+
# begin wxGlade: MyFrame1.__init__
|
|
103
|
+
#kwds["style"] = wx.DEFAULT_FRAME_STYLE
|
|
104
|
+
wx.Panel.__init__(self, parent, winid)
|
|
105
|
+
self.dt = driftTracker
|
|
106
|
+
self.plotInterval = 10
|
|
107
|
+
self.showPlots = showPlots
|
|
108
|
+
|
|
109
|
+
sizer_1 = wx.BoxSizer(wx.VERTICAL)
|
|
110
|
+
hsizer = wx.BoxSizer(wx.HORIZONTAL)
|
|
111
|
+
|
|
112
|
+
self.cbTrack = wx.CheckBox(self, -1, 'Track')
|
|
113
|
+
hsizer.Add(self.cbTrack, 0, wx.ALL, 2)
|
|
114
|
+
self.cbTrack.Bind(wx.EVT_CHECKBOX, self.OnCBTrack)
|
|
115
|
+
self.cbLock = wx.CheckBox(self, -1, 'Lock')
|
|
116
|
+
self.cbLock.Bind(wx.EVT_CHECKBOX, self.OnCBLock)
|
|
117
|
+
hsizer.Add(self.cbLock, 0, wx.ALL, 2)
|
|
118
|
+
self.bSaveHist = wx.Button(self, -1, 'Save History')
|
|
119
|
+
hsizer.Add(self.bSaveHist, 0, wx.ALL, 2)
|
|
120
|
+
self.bSaveHist.Bind(wx.EVT_BUTTON, self.OnBSaveHist)
|
|
121
|
+
self.cbLockActive = wx.CheckBox(self, -1, 'Lock Active')
|
|
122
|
+
self.cbLockActive.Enable(False)
|
|
123
|
+
hsizer.Add(self.cbLockActive, 0, wx.ALL, 2)
|
|
124
|
+
sizer_1.Add(hsizer, 0, wx.EXPAND, 0)
|
|
125
|
+
|
|
126
|
+
hsizer = wx.BoxSizer(wx.HORIZONTAL)
|
|
127
|
+
self.bSetPostion = wx.Button(self, -1, 'Set focus to current')
|
|
128
|
+
hsizer.Add(self.bSetPostion, 0, wx.ALL, 2)
|
|
129
|
+
self.bSetPostion.Bind(wx.EVT_BUTTON, self.OnBSetPostion)
|
|
130
|
+
self.bSaveCalib = wx.Button(self, -1, 'Save Cal')
|
|
131
|
+
hsizer.Add(self.bSaveCalib, 0, wx.ALL, 2)
|
|
132
|
+
self.bSaveCalib.Bind(wx.EVT_BUTTON, self.OnBSaveCalib)
|
|
133
|
+
sizer_1.Add(hsizer, 0, wx.EXPAND, 0)
|
|
134
|
+
|
|
135
|
+
hsizer = wx.BoxSizer(wx.HORIZONTAL)
|
|
136
|
+
hsizer.Add(wx.StaticText(self, -1, "Calibration:"), 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 2)
|
|
137
|
+
self.gCalib = wx.Gauge(self, -1, 11)
|
|
138
|
+
hsizer.Add(self.gCalib, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 2)
|
|
139
|
+
sizer_1.Add(hsizer, 0, wx.EXPAND, 0)
|
|
140
|
+
|
|
141
|
+
hsizer = wx.BoxSizer(wx.HORIZONTAL)
|
|
142
|
+
hsizer.Add(wx.StaticText(self, -1, "Tolerance [nm]:"), 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 2)
|
|
143
|
+
self.tTolerance = wx.TextCtrl(self, -1, '%3.0f'% (1e3*self.dt.get_focus_tolerance()), size=[30,-1])
|
|
144
|
+
hsizer.Add(self.tTolerance, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 2)
|
|
145
|
+
self.bSetTolerance = wx.Button(self, -1, 'Set', style=wx.BU_EXACTFIT)
|
|
146
|
+
hsizer.Add(self.bSetTolerance, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 2)
|
|
147
|
+
self.bSetTolerance.Bind(wx.EVT_BUTTON, self.OnBSetTolerance)
|
|
148
|
+
sizer_1.Add(hsizer,0, wx.EXPAND, 0)
|
|
149
|
+
|
|
150
|
+
hsizer = wx.BoxSizer(wx.HORIZONTAL)
|
|
151
|
+
hsizer.Add(wx.StaticText(self, -1, "Z-factor:"), 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 2)
|
|
152
|
+
self.tZfactor = wx.TextCtrl(self, -1, '%3.1f'% self.dt.Zfactor, size=[30,-1])
|
|
153
|
+
hsizer.Add(self.tZfactor, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 2)
|
|
154
|
+
self.bSetZfactor = wx.Button(self, -1, 'Set', style=wx.BU_EXACTFIT)
|
|
155
|
+
hsizer.Add(self.bSetZfactor, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 2)
|
|
156
|
+
self.bSetZfactor.Bind(wx.EVT_BUTTON, self.OnBSetZfactor)
|
|
157
|
+
sizer_1.Add(hsizer,0, wx.EXPAND, 0)
|
|
158
|
+
|
|
159
|
+
hsizer = wx.BoxSizer(wx.HORIZONTAL)
|
|
160
|
+
hsizer.Add(wx.StaticText(self, -1, "Correction fraction (0.1..1):"), 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 2)
|
|
161
|
+
self.tFraction = wx.TextCtrl(self, -1, '%3.1f'% self.dt.correctionFraction, size=[30,-1])
|
|
162
|
+
hsizer.Add(self.tFraction, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 2)
|
|
163
|
+
self.bSetFraction = wx.Button(self, -1, 'Set', style=wx.BU_EXACTFIT)
|
|
164
|
+
hsizer.Add(self.bSetFraction, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 2)
|
|
165
|
+
self.bSetFraction.Bind(wx.EVT_BUTTON, self.OnBSetFraction)
|
|
166
|
+
sizer_1.Add(hsizer,0, wx.EXPAND, 0)
|
|
167
|
+
|
|
168
|
+
hsizer = wx.BoxSizer(wx.HORIZONTAL)
|
|
169
|
+
hsizer.Add(wx.StaticText(self, -1, "feedback delay [frames]:"), 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 2)
|
|
170
|
+
self.tMinDelay = wx.TextCtrl(self, -1, '%d' % (self.dt.minDelay), size=[30,-1])
|
|
171
|
+
hsizer.Add(self.tMinDelay, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 2)
|
|
172
|
+
self.bSetMinDelay = wx.Button(self, -1, 'Set', style=wx.BU_EXACTFIT)
|
|
173
|
+
hsizer.Add(self.bSetMinDelay, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 2)
|
|
174
|
+
self.bSetMinDelay.Bind(wx.EVT_BUTTON, self.OnBSetMinDelay)
|
|
175
|
+
sizer_1.Add(hsizer,0, wx.EXPAND, 0)
|
|
176
|
+
|
|
177
|
+
hsizer = wx.BoxSizer(wx.HORIZONTAL)
|
|
178
|
+
hsizer.Add(wx.StaticText(self, -1, "Plot Interval [frames]:"), 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 2)
|
|
179
|
+
self.tPlotInterval = wx.TextCtrl(self, -1, '%d' % (self.plotInterval), size=[30,-1])
|
|
180
|
+
hsizer.Add(self.tPlotInterval, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 2)
|
|
181
|
+
self.bSetPlotInterval = wx.Button(self, -1, 'Set', style=wx.BU_EXACTFIT)
|
|
182
|
+
hsizer.Add(self.bSetPlotInterval, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 2)
|
|
183
|
+
self.bSetPlotInterval.Bind(wx.EVT_BUTTON, self.OnBSetPlotInterval)
|
|
184
|
+
sizer_1.Add(hsizer,0, wx.EXPAND, 0)
|
|
185
|
+
|
|
186
|
+
hsizer = wx.BoxSizer(wx.HORIZONTAL)
|
|
187
|
+
self.stError = wx.StaticText(self, -1, 'Error:\n\n', size=[200,-1])
|
|
188
|
+
cfont = self.stError.GetFont()
|
|
189
|
+
font = wx.Font(cfont.GetPointSize(), wx.TELETYPE, wx.NORMAL, wx.NORMAL)
|
|
190
|
+
self.stError.SetFont(font)
|
|
191
|
+
hsizer.Add(self.stError, 0, wx.ALL, 2)
|
|
192
|
+
sizer_1.Add(hsizer,0, wx.EXPAND, 0)
|
|
193
|
+
|
|
194
|
+
if self.showPlots:
|
|
195
|
+
self.trackPlot = TrackerPlotPanel(self, self.dt, size=[300, 500])
|
|
196
|
+
|
|
197
|
+
#hsizer.Add(self.stError, 0, wx.ALL, 2)
|
|
198
|
+
sizer_1.Add(self.trackPlot,0, wx.EXPAND, 0)
|
|
199
|
+
|
|
200
|
+
self.SetAutoLayout(1)
|
|
201
|
+
self.SetSizer(sizer_1)
|
|
202
|
+
sizer_1.Fit(self)
|
|
203
|
+
sizer_1.SetSizeHints(self)
|
|
204
|
+
self.Layout()
|
|
205
|
+
# end wxGlade
|
|
206
|
+
|
|
207
|
+
self.getMdh() # we should be able to use the metadata to look up pixel sizes?
|
|
208
|
+
# we pass this down to the drifttracker but could also do this only in driftTrackGUI when plotting?
|
|
209
|
+
# but seems preferable to keep this at the lower level as we then have the nm info in the events that are stored with data
|
|
210
|
+
self.dt.vsznm_x = self.mdh.voxelsize_nm.x
|
|
211
|
+
self.dt.vsznm_y = self.mdh.voxelsize_nm.y
|
|
212
|
+
|
|
213
|
+
def OnCBTrack(self, event):
|
|
214
|
+
#print self.cbTrack.GetValue()
|
|
215
|
+
if self.cbTrack.GetValue():
|
|
216
|
+
self.dt.register()
|
|
217
|
+
else:
|
|
218
|
+
self.dt.deregister()
|
|
219
|
+
|
|
220
|
+
def OnBSetPostion(self, event):
|
|
221
|
+
self.dt.reCalibrate()
|
|
222
|
+
|
|
223
|
+
def OnBSaveCalib(self, event):
|
|
224
|
+
if not hasattr(self.dt, 'calibState') or (self.dt.calibState < self.dt.NCalibStates):
|
|
225
|
+
Warn(self,"not calibrated")
|
|
226
|
+
else:
|
|
227
|
+
self.showCalImages()
|
|
228
|
+
|
|
229
|
+
def getMdh(self):
|
|
230
|
+
# this methods gets us the cam metadata to check pixel sizes etc
|
|
231
|
+
# metadata handling
|
|
232
|
+
mdh = MetaDataHandler.NestedClassMDHandler()
|
|
233
|
+
# loop over all providers of metadata
|
|
234
|
+
for mdgen in MetaDataHandler.provideStartMetadata:
|
|
235
|
+
mdgen(mdh)
|
|
236
|
+
|
|
237
|
+
self.mdh = mdh
|
|
238
|
+
|
|
239
|
+
def showCalImages(self):
|
|
240
|
+
import numpy as np
|
|
241
|
+
import time
|
|
242
|
+
|
|
243
|
+
#metadata handling
|
|
244
|
+
mdh = MetaDataHandler.NestedClassMDHandler()
|
|
245
|
+
mdh.setEntry('StartTime', time.time())
|
|
246
|
+
mdh.setEntry('AcquisitionType', 'Stack')
|
|
247
|
+
|
|
248
|
+
#loop over all providers of metadata
|
|
249
|
+
for mdgen in MetaDataHandler.provideStartMetadata:
|
|
250
|
+
mdgen(mdh)
|
|
251
|
+
mdh.setEntry('CalibrationPositions',self.dt.calPositions)
|
|
252
|
+
|
|
253
|
+
im = dsviewer.ImageStack(data = self.dt.refImages, mdh = mdh, titleStub='Unsaved Image')
|
|
254
|
+
if not im.mode == 'graph':
|
|
255
|
+
im.mode = 'lite'
|
|
256
|
+
|
|
257
|
+
#print im.mode
|
|
258
|
+
dvf = dsviewer.DSViewFrame(im, mode= im.mode, size=(500, 500))
|
|
259
|
+
dvf.SetSize((500,500))
|
|
260
|
+
dvf.Show()
|
|
261
|
+
|
|
262
|
+
def OnBSaveHist(self, event):
|
|
263
|
+
if not hasattr(self.dt, 'history') or (len(self.dt.history) <= 0):
|
|
264
|
+
Warn(self,"no history")
|
|
265
|
+
else:
|
|
266
|
+
dlg = wx.FileDialog(self, message="Save file as...",
|
|
267
|
+
defaultFile='history.txt',
|
|
268
|
+
wildcard='txt File (*.txt)|*.txt',
|
|
269
|
+
style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
|
|
270
|
+
|
|
271
|
+
if dlg.ShowModal() == wx.ID_OK:
|
|
272
|
+
historyfn = dlg.GetPath()
|
|
273
|
+
np.savetxt(historyfn, self.dt.history, header=' '.join(self.dt.historyColNames))
|
|
274
|
+
# Info(self,"history saved")
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def OnBSetTolerance(self, event):
|
|
278
|
+
self.dt.set_focus_tolerance(float(self.tTolerance.GetValue())/1e3)
|
|
279
|
+
|
|
280
|
+
def OnBSetZfactor(self, event):
|
|
281
|
+
self.dt.Zfactor = float(self.tZfactor.GetValue())
|
|
282
|
+
|
|
283
|
+
def OnBSetFraction(self, event):
|
|
284
|
+
fraction = float(self.tZfactor.GetValue())
|
|
285
|
+
if fraction < 0.1:
|
|
286
|
+
fraction = 0.1
|
|
287
|
+
if fraction > 1.0:
|
|
288
|
+
fraction = 1.0
|
|
289
|
+
self.dt.correctionFraction = fraction
|
|
290
|
+
|
|
291
|
+
def OnBSetMinDelay(self, event):
|
|
292
|
+
self.dt.minDelay = int(self.tMinDelay.GetValue())
|
|
293
|
+
|
|
294
|
+
def OnBSetPlotInterval(self, event):
|
|
295
|
+
self.plotInterval = int(self.tPlotInterval.GetValue())
|
|
296
|
+
|
|
297
|
+
def OnCBLock(self, event):
|
|
298
|
+
self.dt.set_focus_lock(self.cbLock.GetValue())
|
|
299
|
+
|
|
300
|
+
def refresh(self):
|
|
301
|
+
try:
|
|
302
|
+
calibState, NStates = self.dt.get_calibration_state()
|
|
303
|
+
self.gCalib.SetRange(int(NStates + 1))
|
|
304
|
+
self.gCalib.SetValue(int(calibState))
|
|
305
|
+
|
|
306
|
+
try:
|
|
307
|
+
t, dx, dy, dz, corr, corrmax,poffset,pos = self.dt.get_history(1)[-1]
|
|
308
|
+
posInd = self.dt.latestPosData[0]
|
|
309
|
+
self.stError.SetLabel(("Error: x = %s nm y = %s nm " +
|
|
310
|
+
"z = %s nm\nnoffs = %s nm c/cm = %4.2f posInd = %d") %
|
|
311
|
+
("{:>+3.2f}".format(dx), "{:>+3.2f}".format(dy),
|
|
312
|
+
"{:>+3.1f}".format(dz), "{:>+6.1f}".format(poffset),
|
|
313
|
+
corr/corrmax, posInd))
|
|
314
|
+
|
|
315
|
+
except IndexError:
|
|
316
|
+
pass
|
|
317
|
+
|
|
318
|
+
self.cbLock.SetValue(self.dt.get_focus_lock())
|
|
319
|
+
self.cbTrack.SetValue(self.dt.is_tracking())
|
|
320
|
+
self.cbLockActive.SetValue(self.dt.lockActive)
|
|
321
|
+
|
|
322
|
+
if (len(self.dt.get_history(0)) > 0) and (len(self.dt.get_history(0)) % self.plotInterval == 0) and self.showPlots:
|
|
323
|
+
self.trackPlot.draw()
|
|
324
|
+
except AttributeError:
|
|
325
|
+
logger.exception('error in refresh')
|
|
326
|
+
pass
|
|
327
|
+
except IndexError:
|
|
328
|
+
logger.exception('error in refresh')
|
|
329
|
+
pass
|