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,188 @@
1
+ import numpy as np
2
+ from traits.api import HasTraits, Str, Int, CStr, List, Enum, Float, Bool
3
+ from traitsui.api import View, Item, Group
4
+ from traitsui.menu import OKButton, CancelButton, OKCancelButtons
5
+
6
+ class ChannelSelector(HasTraits):
7
+ clist = List([])
8
+ Channel = Enum(values='clist')
9
+
10
+ traits_view = View(Group(Item(name = 'Channel')),
11
+ title = 'Select Channel',
12
+ buttons = OKCancelButtons
13
+ )
14
+
15
+ def add_keys(self,chans):
16
+ for chan in chans:
17
+ if chan not in self.clist:
18
+ self.clist.append(chan)
19
+
20
+
21
+ class TimeSelector(HasTraits):
22
+ clist = List([])
23
+ Channel = Enum(values='clist')
24
+ FromTime = Float()
25
+ ToTime = Float()
26
+ FilterEvents = Bool(False)
27
+
28
+ traits_view = View(Group(Item(name = 'Channel'),
29
+ Item(name = 'FromTime'),
30
+ Item(name = 'ToTime'),
31
+ Item(name = 'FilterEvents')),
32
+ title = 'Select Channel',
33
+ buttons = OKCancelButtons
34
+ )
35
+
36
+ def add_keys(self,chans):
37
+ for chan in chans:
38
+ if chan not in self.clist:
39
+ self.clist.append(chan)
40
+
41
+
42
+ class TimeBlock(HasTraits):
43
+ BlockSize = Int(100)
44
+
45
+
46
+ class ExtraColumns:
47
+ """
48
+
49
+ """
50
+ def __init__(self, visFr):
51
+ self.visFr = visFr
52
+ self.pipeline = visFr.pipeline
53
+
54
+ visFr.AddMenuItem('Experimental>Deprecated>ExtraColumns',
55
+ 'Add random value column',
56
+ self.OnRandMap,
57
+ helpText='the added random value column can be used to select a fraction of all events')
58
+ visFr.AddMenuItem('Experimental>Deprecated>ExtraColumns',
59
+ 'Add time block choice column',
60
+ self.OnTimeBlocks,
61
+ helpText='the added column can be used to select blocks of frames as even or odd numbered blocks')
62
+ visFr.AddMenuItem('Experimental>Deprecated>ExtraColumns',
63
+ 'Select 50% of events from even numbered time blocks - EVEN',
64
+ self.OnSelectTB1,
65
+ helpText='select half of all events for FRC - even numbered time blocks')
66
+ visFr.AddMenuItem('Experimental>Deprecated>ExtraColumns',
67
+ 'Select 50% of events from from odd numbered time blocks - ODD',
68
+ self.OnSelectTB2,
69
+ helpText='select half of all events for FRC - second half')
70
+ visFr.AddMenuItem('Experimental>Deprecated>ExtraColumns',
71
+ 'Select 50% of events from random value column - half 1',
72
+ self.OnSelectHalf1,
73
+ helpText='select half of all events for FRC - first half')
74
+ visFr.AddMenuItem('Experimental>Deprecated>ExtraColumns',
75
+ 'Select 50% of events from random value column - half 2',
76
+ self.OnSelectHalf2,
77
+ helpText='select half of all events for FRC - second half')
78
+ visFr.AddMenuItem('Experimental>Deprecated>ExtraColumns',
79
+ 'Add channel based time selection column',
80
+ self.OnTimeSelectChannel,
81
+ helpText='the added column can be used to select a time window of events of a specific colour, filter tsel_channel in range (0.5,2)')
82
+ visFr.AddMenuItem('Experimental>Deprecated>ExtraColumns',
83
+ 'Add channel based random fraction selection column',
84
+ self.OnRandomSelectChannel,
85
+ helpText='the added column can be used to select a fraction of events of a specific colour by random sub-sampling, filter rand_channel in range (-.1,fraction)')
86
+
87
+ def OnRandMap(self, event=None):
88
+ self.pipeline.selectedDataSource.setMapping('randVal','0*x+np.random.rand(x.size)')
89
+ self.pipeline.Rebuild()
90
+
91
+ def OnTimeBlocks(self, event=None):
92
+ tb = TimeBlock()
93
+ if tb.configure_traits(kind='modal'):
94
+ psd = self.pipeline.selectedDataSource
95
+ blockSel = np.mod((psd['t']/tb.BlockSize).astype('int'),2)
96
+ # self.pipeline.selectedDataSource.setMapping('timeBlock',"np.mod((t/%d).astype('int'),2)" % tb.BlockSize)
97
+ self.pipeline.selectedDataSource.addColumn('timeBlock',blockSel)
98
+ self.pipeline.Rebuild()
99
+
100
+ def OnSelectTB1(self, event=None):
101
+ if 'timeBlock' not in self.pipeline.keys():
102
+ print('Need randVal property, call "Add random value column" first')
103
+ return
104
+
105
+ self.pipeline.filterKeys['timeBlock'] = (-0.1,0.5)
106
+ self.pipeline.Rebuild()
107
+ self.visFr.CreateFoldPanel()
108
+
109
+ def OnSelectTB2(self, event=None):
110
+ if 'timeBlock' not in self.pipeline.keys():
111
+ print('Need randVal property, call "Add random value column" first')
112
+ return
113
+
114
+ self.pipeline.filterKeys['timeBlock'] = (0.5,1.5)
115
+ self.pipeline.Rebuild()
116
+ self.visFr.CreateFoldPanel()
117
+
118
+
119
+ def OnSelectHalf1(self, event=None):
120
+ if 'randVal' not in self.pipeline.keys():
121
+ print('Need randVal property, call "Add random value column" first')
122
+ return
123
+
124
+ self.pipeline.filterKeys['randVal'] = (-0.1,0.4999)
125
+ self.pipeline.Rebuild()
126
+ self.visFr.CreateFoldPanel()
127
+
128
+ def OnSelectHalf2(self, event=None):
129
+ if 'randVal' not in self.pipeline.keys():
130
+ print('Need randVal property, call "Add random value column" first')
131
+ return
132
+
133
+ self.pipeline.filterKeys['randVal'] = (0.5,1.1)
134
+ self.pipeline.Rebuild()
135
+ self.visFr.CreateFoldPanel()
136
+
137
+ def OnTimeSelectChannel(self, event=None):
138
+ pipeline = self.pipeline
139
+ if pipeline.selectedDataSource is None:
140
+ return
141
+ if len(pipeline.colourFilter.getColourChans()) < 1:
142
+ return
143
+ timeSelector = TimeSelector()
144
+ timeSelector.add_keys(pipeline.colourFilter.getColourChans())
145
+ if timeSelector.configure_traits(kind='modal'):
146
+ psd = pipeline.selectedDataSource
147
+ tall = np.ones_like(psd['x'], dtype='float')
148
+ tsel = (psd['t'] >= timeSelector.FromTime) * (psd['t'] <= timeSelector.ToTime)
149
+
150
+ dispColor = pipeline.colourFilter.currentColour
151
+ pipeline.colourFilter.setColour(timeSelector.Channel)
152
+ idx = pipeline.filter.Index.copy()
153
+ idx[idx] = pipeline.colourFilter.index
154
+ tall[idx] = tsel[idx]
155
+ pipeline.colourFilter.setColour(dispColor)
156
+ pipeline.selectedDataSource.addColumn('tselect_%s' % timeSelector.Channel,tall)
157
+ if timeSelector.FilterEvents:
158
+ self.pipeline.filterKeys['tselect_%s' % timeSelector.Channel] = (0.5,2.0)
159
+ pipeline.Rebuild()
160
+ self.visFr.CreateFoldPanel()
161
+
162
+ def OnRandomSelectChannel(self, event=None):
163
+ pipeline = self.pipeline
164
+ if pipeline.selectedDataSource is None:
165
+ return
166
+ if len(pipeline.colourFilter.getColourChans()) < 1:
167
+ return
168
+ chanSelector = ChannelSelector()
169
+ chanSelector.add_keys(pipeline.colourFilter.getColourChans())
170
+ if chanSelector.configure_traits(kind='modal'):
171
+ psd = pipeline.selectedDataSource
172
+ eall = np.zeros_like(psd['x'], dtype='float')
173
+ erand = np.random.rand(eall.size)
174
+
175
+ dispColor = pipeline.colourFilter.currentColour
176
+ pipeline.colourFilter.setColour(chanSelector.Channel)
177
+ idx = pipeline.filter.Index.copy()
178
+ idx[idx] = pipeline.colourFilter.index
179
+ eall[idx] = erand[idx]
180
+ pipeline.colourFilter.setColour(dispColor)
181
+ pipeline.selectedDataSource.addColumn('rand_%s' % chanSelector.Channel,eall)
182
+ pipeline.Rebuild()
183
+ self.visFr.CreateFoldPanel()
184
+
185
+
186
+ def Plug(visFr):
187
+ '''Plugs this module into the gui'''
188
+ visFr.extraCols = ExtraColumns(visFr)
@@ -0,0 +1,11 @@
1
+ import PYMEcs.misc.ExtraCmaps
2
+
3
+ # this module hijacks the plugin system to run colour map registration
4
+ # at startup of visgui, dsviewer
5
+
6
+ # I am exploring the alternative option to do this via the startup console script
7
+ # which has the advantage of doing this at startup for dsviewer which is an issue otherwise
8
+
9
+ def Plug(arg):
10
+ # registerCmaps()
11
+ pass
@@ -0,0 +1,72 @@
1
+ import numpy as np
2
+ from PYME.recipes.tablefilters import FilterTable
3
+ import wx
4
+
5
+ def selectWithDialog(choices, message='select image from list', caption='Selection'):
6
+ dlg = wx.SingleChoiceDialog(None, message, caption, choices, wx.CHOICEDLG_STYLE)
7
+ if dlg.ShowModal() == wx.ID_OK:
8
+ item = dlg.GetStringSelection()
9
+ else:
10
+ item = None
11
+ dlg.Destroy()
12
+ return item
13
+
14
+
15
+ class SelectROIFT:
16
+ def __init__(self, visFr):
17
+ self.visFr = visFr
18
+
19
+ visFr.AddMenuItem('Experimental>View', "Add ROI FilterTable module from selection", self.OnSelROIFT)
20
+ visFr.AddMenuItem('Experimental>View', "Add ROI FilterTable module from image", self.OnImROIFT)
21
+
22
+ def OnSelROIFT(self, event):
23
+ try:
24
+ #old glcanvas
25
+ x0, y0 = self.visFr.glCanvas.selectionStart[0:2]
26
+ x1, y1 = self.visFr.glCanvas.selectionFinish[0:2]
27
+ except AttributeError:
28
+ #new glcanvas
29
+ x0, y0 = self.visFr.glCanvas.selectionSettings.start[0:2]
30
+ x1, y1 = self.visFr.glCanvas.selectionSettings.finish[0:2]
31
+
32
+ filters = {}
33
+ filters['x'] = [float(min(x0, x1)), float(max(x0, x1))] # must ensure all values are eventually scalars to avoid issue with recipe yaml output
34
+ filters['y'] = [float(min(y0, y1)), float(max(y0, y1))] # ditto
35
+
36
+ recipe = self.visFr.pipeline.recipe
37
+ ftable = FilterTable(recipe, inputName=self.visFr.pipeline.selectedDataSourceKey,
38
+ outputName='selectedROI', filters=filters)
39
+ if not ftable.configure_traits(kind='modal'):
40
+ return
41
+
42
+ recipe.add_module(ftable)
43
+ recipe.execute()
44
+
45
+ def OnImROIFT(self, event):
46
+ from PYME.DSView import dsviewer
47
+ selection = selectWithDialog(list(dsviewer.openViewers.keys()))
48
+ if selection is not None:
49
+ img = dsviewer.openViewers[selection].image
50
+ else:
51
+ return
52
+ if img.mdh.getOrDefault('Filter.Keys',None) is None:
53
+ logger.debug('no Filter.Keys in image metadata')
54
+ return
55
+
56
+ filters = {}
57
+ filters['x'] = list(img.mdh['Filter.Keys']['x'])
58
+ filters['y'] = list(img.mdh['Filter.Keys']['y'])
59
+
60
+ recipe = self.visFr.pipeline.recipe
61
+ ftable = FilterTable(recipe, inputName=self.visFr.pipeline.selectedDataSourceKey,
62
+ outputName='selectedROI', filters=filters)
63
+ if not ftable.configure_traits(kind='modal'):
64
+ return
65
+
66
+ recipe.add_module(ftable)
67
+ recipe.execute()
68
+
69
+
70
+ def Plug(visFr):
71
+ """Plugs this module into the gui"""
72
+ SelectROIFT(visFr)
@@ -0,0 +1,51 @@
1
+ import wx
2
+ from wx.lib.dialogs import ScrolledMessageDialog
3
+ from PYMEcs.misc.guiMsgBoxes import Warn
4
+
5
+ def isDarwin():
6
+ import os
7
+ from sys import platform
8
+ return platform == "darwin"
9
+
10
+ class ShowErr:
11
+ """
12
+
13
+ """
14
+ def __init__(self, visFr):
15
+ self.visFr = visFr
16
+ self.txtwin = None
17
+ visFr.AddMenuItem('Experimental', 'Errors in scrolled message dialog\tCtrl+E', self.OnErrScrolledDialog)
18
+
19
+ def getLogFileName(self, pidoffset = -1):
20
+ import os
21
+ pid = int(os.getpid()) + pidoffset
22
+ return os.path.join('/tmp','visgui-%d.tmp' % pid)
23
+
24
+ def OnErrScrolledDialog(self, event=None):
25
+ if not isDarwin():
26
+ Warn(None,'aborting: functionality only available on mac','Error')
27
+ return
28
+
29
+ ok = False
30
+ import os.path
31
+ fname = self.getLogFileName(pidoffset = -1)
32
+ if os.path.isfile(fname):
33
+ ok = True
34
+ else:
35
+ fname = self.getLogFileName(pidoffset = 0)
36
+ if os.path.isfile(fname):
37
+ ok = True
38
+ else:
39
+ Warn(None,'aborting: cannot find log file, tried %s and %s' % (self.getLogFileName(pidoffset = -1),
40
+ self.getLogFileName(pidoffset = 0)))
41
+ if ok:
42
+ with open(fname,"r") as f:
43
+ txt = "\n".join(f.readlines())
44
+ dlg = ScrolledMessageDialog(self.visFr, txt, "VisGUI Error Output", size=(900,400),
45
+ style=wx.RESIZE_BORDER | wx.DEFAULT_DIALOG_STYLE )
46
+ dlg.ShowModal()
47
+ dlg.Destroy()
48
+
49
+ def Plug(visFr):
50
+ """Plugs this module into the gui"""
51
+ visFr.showErr = ShowErr(visFr)
@@ -0,0 +1,58 @@
1
+ import wx
2
+ from wx.lib.dialogs import ScrolledMessageDialog
3
+ from PYMEcs.misc.guiMsgBoxes import Warn
4
+
5
+ from PYMEcs.misc.versionCheck import PYMEversionCheck
6
+ try:
7
+ from PYME.DSView.modules._base import Plugin
8
+ except ImportError:
9
+ PYMEversionCheck('PluginClass')
10
+
11
+ def isDarwin():
12
+ import os
13
+ from sys import platform
14
+ return platform == "darwin"
15
+
16
+ class ShowErr(Plugin):
17
+ """
18
+
19
+ """
20
+ def __init__(self, dsviewer):
21
+
22
+ Plugin.__init__(self, dsviewer)
23
+
24
+ self.txtwin = None
25
+ dsviewer.AddMenuItem('Experimental', 'Errors in scrolled message dialog\tCtrl+E', self.OnErrScrolledDialog)
26
+
27
+ def getLogFileName(self, pidoffset = -1):
28
+ import os
29
+ pid = int(os.getpid()) + pidoffset
30
+ return os.path.join('/tmp','dh5view-%d.tmp' % pid)
31
+
32
+ def OnErrScrolledDialog(self, event=None):
33
+ if not isDarwin():
34
+ Warn(None,'aborting: functionality only available on mac','Error')
35
+ return
36
+ ok = False
37
+ import os.path
38
+ fname = self.getLogFileName(pidoffset = -1)
39
+ if os.path.isfile(fname):
40
+ ok = True
41
+ else:
42
+ fname = self.getLogFileName(pidoffset = 0)
43
+ if os.path.isfile(fname):
44
+ ok = True
45
+ else:
46
+ Warn(None,'aborting: cannot find log file, tried %s and %s' % (self.getLogFileName(pidoffset = -1),
47
+ self.getLogFileName(pidoffset = 0)))
48
+ if ok:
49
+ with open(fname,"r") as f:
50
+ txt = "\n".join(f.readlines())
51
+ dlg = ScrolledMessageDialog(self.dsviewer, txt, "VisGUI Error Output", size=(900,400),
52
+ style=wx.RESIZE_BORDER | wx.DEFAULT_DIALOG_STYLE )
53
+ dlg.ShowModal()
54
+ dlg.Destroy()
55
+
56
+ def Plug(dsviewer):
57
+ """Plugs this module into the gui"""
58
+ return ShowErr(dsviewer)
@@ -0,0 +1,56 @@
1
+ import numpy as np
2
+ import logging
3
+ logger = logging.getLogger(__file__)
4
+
5
+ # note: to turn this into a standalone shiftmap display tool, add code to open a shiftfield:
6
+ # import PYME.Acquire.Hardware.splitter as sp
7
+ # dx2,dy2 = sp.LoadShiftField(h5file_or_sf_file)
8
+ #
9
+ # if it is purely a shiftfield file then we have to supply some additional info, e.g. voxelsizes
10
+ # and ROI size for the splitter
11
+
12
+ class ShowMap:
13
+ """
14
+
15
+ """
16
+ def __init__(self, visFr):
17
+ self.visFr = visFr
18
+ self.pipeline = visFr.pipeline
19
+
20
+ visFr.AddMenuItem('Experimental>ShiftMap', 'Show Shiftmap', self.OnShowShiftMap,
21
+ helpText='Show a shiftmap from metadata info')
22
+ visFr.AddMenuItem('Experimental>ShiftMap', 'Shiftmap as image', self.OnShiftMapAsImage,
23
+ helpText='Show a shiftmap from metadata info and display as image')
24
+
25
+ def OnShowShiftMap(self, event=None):
26
+ from PYME.Analysis.points import twoColour, twoColourPlot
27
+ mdh = self.pipeline.mdh
28
+ vs = [mdh['voxelsize.x']*1e3, mdh['voxelsize.y']*1e3, mdh['voxelsize.z']*1e3]
29
+ dx = mdh.getEntry('chroma.dx')
30
+ dy = mdh.getEntry('chroma.dy')
31
+
32
+ shape = mdh['Splitter.Channel0ROI'][2:]
33
+
34
+ twoColourPlot.PlotShiftField2(dx,dy,shape,vs)
35
+
36
+ def OnShiftMapAsImage(self, event=None):
37
+ mdh = self.pipeline.mdh
38
+ voxelsize = [mdh['voxelsize.x']*1e3, mdh['voxelsize.y']*1e3, mdh['voxelsize.z']*1e3]
39
+ spx = mdh.getEntry('chroma.dx')
40
+ spy = mdh.getEntry('chroma.dy')
41
+
42
+ shape = mdh['Splitter.Channel0ROI'][2:]
43
+ xi, yi = np.meshgrid(np.arange(0, shape[0]*voxelsize[0], 100), np.arange(0, shape[1]*voxelsize[1], 100))
44
+ xin = xi.ravel()
45
+ yin = yi.ravel()
46
+ dx = spx.ev(xin[:], yin[:]).reshape(xi.shape)
47
+ dy = spy.ev(xin[:], yin[:]).reshape(xi.shape)
48
+
49
+ from PYME.DSView.dsviewer import View3D
50
+ image = np.stack([dx[::-1, :],dy[::-1, :]],axis=-1)
51
+ View3D(image, parent=self.visFr, titleStub='ShiftMap')
52
+
53
+ def Plug(visFr):
54
+ """Plugs this module into the gui"""
55
+ visFr.showShiftMap = ShowMap(visFr)
56
+
@@ -0,0 +1,188 @@
1
+ import numpy as np
2
+ from PYMEcs.misc.guiMsgBoxes import Warn
3
+ import wx
4
+ import os
5
+
6
+ def populate_fresults_wholep(fitMod,pipeline,bgzero=True):
7
+ r = np.zeros(pipeline['x'].size, fitMod.fresultdtype)
8
+ for k in pipeline.keys():
9
+ f = k.split('_')
10
+ if len(f) == 1:
11
+ try:
12
+ r[f[0]] = pipeline[k]
13
+ except ValueError:
14
+ pass
15
+ elif len(f) == 2:
16
+ try:
17
+ r[f[0]][f[1]] = pipeline[k]
18
+ except ValueError:
19
+ pass
20
+ elif len(f) == 3:
21
+ try:
22
+ r[f[0]][f[1]][f[2]] = pipeline[k]
23
+ except ValueError:
24
+ pass
25
+ else:
26
+ raise RuntimeError('more fields than expected: %d' % len(f))
27
+
28
+ if bgzero:
29
+ r['fitResults']['bg'] = 0
30
+ r['fitResults']['br'] = 0
31
+
32
+ return r
33
+
34
+
35
+ from PYME.IO.MetaDataHandler import NestedClassMDHandler
36
+ def genFitImage(fitMod,fr,mdh,psfname=None):
37
+ mdh2 = NestedClassMDHandler(mdh)
38
+ if psfname is not None:
39
+ mdh2['PSFFile'] = psfname
40
+ fitim = fitMod.genFitImage(fr,mdh2)
41
+
42
+ return fitim
43
+
44
+ def get_photons(fitim,mdh):
45
+ nph = fitim.sum()*mdh.getEntry('Camera.ElectronsPerCount')/mdh.getEntry('Camera.TrueEMGain')
46
+ return nph
47
+
48
+
49
+ def nPhotons(fitMod,fr,mdh,psfname=None,nmax=100,progressBar=None,updateStep=100):
50
+ mdh2 = NestedClassMDHandler(mdh)
51
+ if psfname is not None:
52
+ mdh2['PSFFile'] = psfname
53
+ npoints = min(fr.shape[0],nmax)
54
+ nph = np.zeros((npoints))
55
+ us = int(updateStep)
56
+ for i in range(npoints):
57
+ nph[i] = get_photons(genFitImage(fitMod,fr[i],mdh2,psfname=None), mdh2)
58
+ if (progressBar is not None) and ((i % us) == 0):
59
+ progressBar.Update(100.0*i/float(npoints))
60
+ wx.Yield()
61
+ return nph
62
+
63
+
64
+ # you may need a lot more imports depending what functionality your require in your plugin
65
+ class SNRcalculator:
66
+ """
67
+ A plugin, very simple to demonstrate the concept. Also providing a simple
68
+ measure of some kind of SNR, the formula used is probably debatable.
69
+ For example, low background estimates cause very high SNRs which may or may not
70
+ be reasonable given the uncertainty in determining the background etc
71
+ """
72
+ def __init__(self, visFr):
73
+ self.visFr = visFr
74
+ self.pipeline = visFr.pipeline
75
+
76
+ visFr.AddMenuItem('Experimental>ExtraColumns', 'Add SNR property', self.OnAddSNR,
77
+ helpText='Add an event property that provides some measure of SNR for events (from background and amplitude)')
78
+ visFr.AddMenuItem('Experimental>Biplane', 'Add Biplane nPhotons', self.OnAddnphBPlane,
79
+ helpText='Add nPhotons for Biplane fitting')
80
+ visFr.AddMenuItem('Experimental>Biplane', 'Plot Biplane zErrors', self.OnPlotErrBPlane,
81
+ helpText='Plot Biplane fitting z-errors')
82
+
83
+
84
+ def OnAddSNR(self, event=None):
85
+ """
86
+ this function adds an 'SNR' property to events - there could be some discussion how that is actually best calculated
87
+ """
88
+ from PYMEcs.recipes import localisations
89
+
90
+ if False: # this way does not make a special recipe module but uses the generic Mapping module and adds a few columns
91
+ from PYME.IO import tabular
92
+ from PYME.recipes import tablefilters
93
+ # the original formula was very adhoc
94
+ # we have now changed to a different way
95
+ # here we use an approach derived from a formula from Tang et al,
96
+ # Scientific Reports | 5:11073 | DOi: 10.1038/srep11073
97
+ mdh = self.pipeline.mdh
98
+ pipeline = self.pipeline
99
+ # there is an issue if we don't have the nPhotons property FIXME!
100
+ nph = self.pipeline['nPhotons']
101
+ bgraw = self.pipeline['fitResults_background']
102
+ bgph = np.clip((bgraw)*mdh['Camera.ElectronsPerCount']/mdh.getEntry('Camera.TrueEMGain'),1,None)
103
+
104
+ npixroi = (2*mdh.getOrDefault('Analysis.ROISize',5) + 1)**2
105
+ snr = 1.0/npixroi * np.clip(nph,0,None)/np.sqrt(bgph)
106
+ #dirty copy of the pipeline output
107
+
108
+ recipe = pipeline.recipe
109
+ mapp = tablefilters.Mapping(recipe,inputName=pipeline.selectedDataSourceKey,
110
+ outputName='snr')
111
+ recipe.add_module(mapp)
112
+ recipe.execute()
113
+
114
+ snrmap = recipe.namespace['snr']
115
+ snrmap.addColumn('SNR', snr)
116
+ snrmap.addColumn('backgroundPhotons',bgph)
117
+
118
+ else:
119
+ recipe = self.pipeline.recipe
120
+ snr = localisations.SnrCalculation(recipe,inputName=self.pipeline.selectedDataSourceKey,
121
+ outputName='snr')
122
+ recipe.add_module(snr)
123
+ recipe.execute()
124
+
125
+ self.pipeline.selectDataSource('snr')
126
+
127
+ self.pipeline.Rebuild()
128
+ #self.visFr.CreateFoldPanel() # we should not need this anymore
129
+
130
+
131
+ def OnAddnphBPlane(self, event=None):
132
+ """
133
+ this function adds nPhoton property to events for biplane
134
+ """
135
+ fdialog = wx.FileDialog(None, 'Please select PSF to use ...',
136
+ #defaultDir=os.path.split(self.image.filename)[0],
137
+ wildcard='PSF Files|*.psf|TIFF files|*.tif', style=wx.FD_OPEN)
138
+ succ = fdialog.ShowModal()
139
+ if (succ == wx.ID_OK):
140
+ psfn = filename = fdialog.GetPath()
141
+ mdh = self.pipeline.mdh
142
+ pipeline = self.pipeline
143
+ if mdh.getEntry('Analysis.FitModule') not in ['SplitterFitInterpBNR']:
144
+ Warn('Plugin works only for Biplane analysis')
145
+ return
146
+ fitMod = __import__('PYME.localization.FitFactories.' +
147
+ self.pipeline.mdh.getEntry('Analysis.FitModule'),
148
+ fromlist=['PYME', 'localization', 'FitFactories'])
149
+ fr = populate_fresults_wholep(fitMod, pipeline)
150
+ progress = wx.ProgressDialog("calculating photon numbers",
151
+ "calculating...", maximum=100, parent=None,
152
+ style=wx.PD_SMOOTH|wx.PD_AUTO_HIDE)
153
+ nph = nPhotons(fitMod, fr, mdh, psfname=psfn, nmax=1e6,
154
+ progressBar=progress, updateStep = 100)
155
+ progress.Destroy()
156
+ self.pipeline.addColumn('nPhotons', nph)
157
+ self.pipeline.addColumn('fitResults_background', pipeline['fitResults_bg']+pipeline['fitResults_br'])
158
+ self.pipeline.addColumn('sig',float(137.0)+np.zeros_like(pipeline['x'])) # this one is a straight kludge for mortensenError
159
+ self.pipeline.Rebuild()
160
+ self.visFr.CreateFoldPanel()
161
+
162
+
163
+ def OnPlotErrBPlane(self, event=None):
164
+ mdh = self.pipeline.mdh
165
+ pipeline = self.pipeline
166
+ if mdh.getEntry('Analysis.FitModule') not in ['SplitterFitInterpBNR']:
167
+ Warn('Plugin works only for Biplane analysis')
168
+ return
169
+ bgraw = pipeline['fitResults_bg']+pipeline['fitResults_br']
170
+ bgph = bgraw * pipeline.mdh.getEntry('Camera.ElectronsPerCount')/pipeline.mdh.getEntry('Camera.TrueEMGain')
171
+
172
+ import matplotlib.pyplot as plt
173
+ plt.figure()
174
+ plt.scatter(pipeline['nPhotons'],pipeline['fitError_z0'],s=10,c=bgph)
175
+ plt.colorbar()
176
+ plt.xlim(0,None)
177
+ plt.xlabel('Photons')
178
+ plt.ylabel('z error (nm)')
179
+
180
+ # example use after adding the nPhotons entry:
181
+ # def bg(pipeline):
182
+ # return (pipeline['fitResults_bg']+pipeline['fitResults_br'])*pipeline.mdh.getEntry('Camera.ElectronsPerCount')/pipeline.mdh.getEntry('Camera.TrueEMGain')
183
+ # scatter(pipeline['nPhotons'],pipeline['fitError_z0'],s=10,c=bg(pipeline))
184
+ # colorbar()
185
+
186
+ def Plug(visFr):
187
+ """Plugs this module into the gui"""
188
+ visFr.snrCalc = SNRcalculator(visFr)
@@ -0,0 +1,51 @@
1
+ import numpy as np
2
+ from PYMEcs.recipes.localisations import ClusterTimeRange, ValidClumps
3
+ from PYME.recipes.tablefilters import FilterTable
4
+ from PYME.recipes.localisations import DBSCANClustering
5
+
6
+ class SpecLabeling:
7
+ def __init__(self, visFr):
8
+ self.visFr = visFr
9
+
10
+ visFr.AddMenuItem('Experimental>Corrections', "Filter specific labeling (DNA-PAINT)", self.OnSpecFilter)
11
+ visFr.AddMenuItem('Experimental>Corrections', "Apply specific labeling to non-clumped data (DNA-PAINT)", self.OnSpecFilterNC)
12
+
13
+ def OnSpecFilter(self, event):
14
+ from PYMEcs.recipes import localisations
15
+ recipe = self.visFr.pipeline.recipe
16
+ bigLimit = 1e6 # size for filters big enough to capture everything
17
+
18
+ # check 'coalesced' is available
19
+ recipe.add_module(DBSCANClustering(recipe,inputName='coalesced', outputName='dbscanClustered', columns=['x', 'y'],
20
+ searchRadius=50, minClumpSize=3, clumpColumnName='dbscanClumpID'))
21
+ filters={'dbscanClumpID' : [0.5,1e6]}
22
+ recipe.add_module(FilterTable(recipe, inputName='dbscanClustered',
23
+ outputName='validCluster', filters={'dbscanClumpID' : [0.5,bigLimit]}))
24
+
25
+ recipe.add_module(ClusterTimeRange(recipe, inputName='validCluster',
26
+ outputName='withTrange', IDkey='dbscanClumpID'))
27
+ recipe.add_module(FilterTable(recipe, inputName='withTrange',
28
+ outputName='specLabeling', filters={'trange' : [2500,bigLimit]}))
29
+
30
+ recipe.execute()
31
+ self.visFr.pipeline.selectDataSource('specLabeling')
32
+
33
+
34
+ def OnSpecFilterNC(self, event):
35
+ from PYMEcs.recipes import localisations
36
+ recipe = self.visFr.pipeline.recipe
37
+
38
+ recipe.add_module(ValidClumps(inputName='with_clumps',
39
+ inputValid='specLabeling',
40
+ outputName='with_validClumps'))
41
+ recipe.add_module(FilterTable(recipe, inputName='with_validClumps',
42
+ outputName='specLabelingNC', filters={'validID' : [0.5,1.5]}))
43
+ recipe.add_module(FilterTable(recipe, inputName='with_validClumps',
44
+ outputName='nonSpecNC', filters={'validID' : [-0.5,0.5]}))
45
+ recipe.execute()
46
+ self.visFr.pipeline.selectDataSource('specLabelingNC')
47
+
48
+
49
+ def Plug(visFr):
50
+ """Plugs this module into the gui"""
51
+ SpecLabeling(visFr)