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,246 @@
|
|
|
1
|
+
from PYME.LMVis.renderers import TriangleRenderer, renderMetadataProviders
|
|
2
|
+
from PYME.IO.image import GeneratedImage, ImageBounds
|
|
3
|
+
# from PYME.LMVis import visHelpers
|
|
4
|
+
from PYME.LMVis import statusLog
|
|
5
|
+
# from PYME.IO import tabular
|
|
6
|
+
|
|
7
|
+
from PYME.IO import MetaDataHandler
|
|
8
|
+
import numpy as np
|
|
9
|
+
|
|
10
|
+
from PYMEcs.misc.guiMsgBoxes import Warn
|
|
11
|
+
|
|
12
|
+
from traits.api import HasTraits, Str, Int, CStr, List, Enum, Float, Bool
|
|
13
|
+
from traitsui.api import View, Item, Group
|
|
14
|
+
from traitsui.menu import OKButton, CancelButton, OKCancelButtons
|
|
15
|
+
|
|
16
|
+
class TimeBlock(HasTraits):
|
|
17
|
+
TimeBlockSize = Int(100)
|
|
18
|
+
Colour = Enum(values='clist')
|
|
19
|
+
PixelSize_in_nm = Float(5.0)
|
|
20
|
+
JitterFactor = Float(5.0)
|
|
21
|
+
SamplesToAverage = Int(40)
|
|
22
|
+
|
|
23
|
+
clist = List([])
|
|
24
|
+
|
|
25
|
+
traits_view = View(Group(Item(name = 'TimeBlockSize'),
|
|
26
|
+
Item(name = 'Colour'),
|
|
27
|
+
Item(name = 'PixelSize_in_nm'),
|
|
28
|
+
Item(name = 'JitterFactor'),
|
|
29
|
+
Item(name = 'SamplesToAverage')),
|
|
30
|
+
title = 'Select',
|
|
31
|
+
buttons = OKCancelButtons
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
def add_keys(self,chans):
|
|
35
|
+
for chan in chans:
|
|
36
|
+
if chan not in self.clist:
|
|
37
|
+
self.clist.append(chan)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class SplitRenderer(TriangleRenderer):
|
|
41
|
+
"""A renderer that specialises the TriangleRenderer to generate two images
|
|
42
|
+
by splitting the events into two groups. It does not iterate over colour channels but rather will do
|
|
43
|
+
a single colour which must be selected prior to calling this renderer.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
# def __init__(self, visFr, pipeline, mainWind = None, splitSettings = None):
|
|
47
|
+
# super(SplitRenderer, self).__init__(visFr, pipeline, mainWind)
|
|
48
|
+
# self.splitSettings = splitSettings
|
|
49
|
+
|
|
50
|
+
def Generate(self, settings, splitSettings):
|
|
51
|
+
mdh = MetaDataHandler.NestedClassMDHandler()
|
|
52
|
+
mdh['Rendering.Method'] = self.name
|
|
53
|
+
if 'imageID' in self.pipeline.mdh.getEntryNames():
|
|
54
|
+
mdh['Rendering.SourceImageID'] = self.pipeline.mdh['imageID']
|
|
55
|
+
mdh['Rendering.SourceFilename'] = getattr(self.pipeline, 'filename', '')
|
|
56
|
+
mdh['Rendering.NEventsRendered'] = len(self.pipeline[self.pipeline.keys()[0]]) # in future good to use colourfilter for per channel info?
|
|
57
|
+
mdh.Source = MetaDataHandler.NestedClassMDHandler(self.pipeline.mdh)
|
|
58
|
+
|
|
59
|
+
if splitSettings is not None:
|
|
60
|
+
for key in splitSettings:
|
|
61
|
+
mdh['Rendering.SplitSettings.%s' % key] = splitSettings[key]
|
|
62
|
+
|
|
63
|
+
for cb in renderMetadataProviders:
|
|
64
|
+
cb(mdh)
|
|
65
|
+
|
|
66
|
+
pixelSize = settings['pixelSize']
|
|
67
|
+
|
|
68
|
+
status = statusLog.StatusLogger('Generating %s Image ...' % self.name)
|
|
69
|
+
|
|
70
|
+
imb = self._getImBounds(*settings.get('zBounds', [None, None]))
|
|
71
|
+
|
|
72
|
+
#record the pixel origin in nm from the corner of the camera for futrue overlays
|
|
73
|
+
if 'Source.Camera.ROIPosX' in mdh.getEntryNames():
|
|
74
|
+
#a rendered image with information about the source ROI
|
|
75
|
+
voxx, voxy = 1e3 * mdh['Source.voxelsize.x'], 1e3 * mdh['Source.voxelsize.y']
|
|
76
|
+
|
|
77
|
+
ox = (mdh['Source.Camera.ROIPosX'] - 1) * voxx + imb.x0
|
|
78
|
+
oy = (mdh['Source.Camera.ROIPosY'] - 1) * voxy + imb.y0
|
|
79
|
+
if 'Source.Positioning.PIFoc' in mdh.getEntryNames():
|
|
80
|
+
oz = mdh['Source.Positioning.PIFoc'] * 1e3
|
|
81
|
+
else:
|
|
82
|
+
oz = imb.z0
|
|
83
|
+
else:
|
|
84
|
+
ox = imb.x0
|
|
85
|
+
oy = imb.y0
|
|
86
|
+
oz = imb.z0
|
|
87
|
+
|
|
88
|
+
mdh['Origin.x'] = ox
|
|
89
|
+
mdh['Origin.y'] = oy
|
|
90
|
+
mdh['Origin.z'] = oz
|
|
91
|
+
|
|
92
|
+
colours = settings['colours']
|
|
93
|
+
curCol = self.colourFilter.currentColour
|
|
94
|
+
if curCol is None:
|
|
95
|
+
colnames = ['Everything_even','Everything_odd']
|
|
96
|
+
else:
|
|
97
|
+
colnames = ['%s_even' % curCol,'%s_odd' % curCol]
|
|
98
|
+
|
|
99
|
+
try:
|
|
100
|
+
oldBlock = self.pipeline.filterKeys['timeBlock']
|
|
101
|
+
except (KeyError, AttributeError):
|
|
102
|
+
oldBlock = None
|
|
103
|
+
|
|
104
|
+
ims = []
|
|
105
|
+
|
|
106
|
+
for filter in [(-0.1,0.5),(0.5,1.5)]:
|
|
107
|
+
self.pipeline.filterKeys['timeBlock'] = filter
|
|
108
|
+
self.pipeline.Rebuild()
|
|
109
|
+
ims.append(np.atleast_3d(self.genIm(settings, imb, mdh)))
|
|
110
|
+
|
|
111
|
+
# needs to reset timeBlock in some fashion
|
|
112
|
+
if oldBlock is None:
|
|
113
|
+
del self.pipeline.filterKeys['timeBlock']
|
|
114
|
+
else:
|
|
115
|
+
self.pipeline.filterKeys['timeBlock'] = oldBlock
|
|
116
|
+
self.pipeline.Rebuild()
|
|
117
|
+
|
|
118
|
+
return GeneratedImage(ims, imb, pixelSize, settings['zSliceThickness'], colnames, mdh=mdh)
|
|
119
|
+
|
|
120
|
+
def GenerateGUI(self, event=None, renderSettings=None, splitSettings=None):
|
|
121
|
+
import wx
|
|
122
|
+
from PYME.LMVis import genImageDialog
|
|
123
|
+
from PYME.DSView import ViewIm3D
|
|
124
|
+
|
|
125
|
+
if renderSettings is None:
|
|
126
|
+
jitVars = ['1.0']
|
|
127
|
+
jitVars += self.colourFilter.keys()
|
|
128
|
+
|
|
129
|
+
self.genMeas = self.pipeline.GeneratedMeasures.keys()
|
|
130
|
+
if not 'neighbourDistances' in self.genMeas:
|
|
131
|
+
self.genMeas.append('neighbourDistances')
|
|
132
|
+
|
|
133
|
+
if not 'neighbourErrorMin' in self.genMeas:
|
|
134
|
+
self.genMeas.append('neighbourErrorMin')
|
|
135
|
+
|
|
136
|
+
jitVars += self.genMeas
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
if 'z' in self.pipeline.keys():
|
|
140
|
+
zvals = self.pipeline['z']
|
|
141
|
+
else:
|
|
142
|
+
zvals = None
|
|
143
|
+
|
|
144
|
+
dlg = genImageDialog.GenImageDialog(self.mainWind, mode=self.mode,
|
|
145
|
+
defaultPixelSize=self._defaultPixelSize,
|
|
146
|
+
colours=self.colourFilter.getColourChans(),
|
|
147
|
+
zvals = zvals,
|
|
148
|
+
jitterVariables = jitVars,
|
|
149
|
+
jitterVarDefault=self._getDefaultJitVar(jitVars),
|
|
150
|
+
jitterVarDefaultZ=self._getDefaultZJitVar(jitVars))
|
|
151
|
+
ret = dlg.ShowModal()
|
|
152
|
+
generateSettings = dlg.get_settings()
|
|
153
|
+
else:
|
|
154
|
+
ret = wx.ID_OK
|
|
155
|
+
generateSettings = {
|
|
156
|
+
'pixelSize' : renderSettings['PixelSize'],
|
|
157
|
+
'jitterVariable' : 'neighbourDistances',
|
|
158
|
+
'jitterScale' : renderSettings['JitterFactor'],
|
|
159
|
+
'jitterVariableZ' : None,
|
|
160
|
+
'jitterScaleZ' : None,
|
|
161
|
+
'MCProbability' : 1.0,
|
|
162
|
+
'numSamples' : renderSettings['SamplesToAverage'],
|
|
163
|
+
'colours' : None,
|
|
164
|
+
'zBounds' : [None,None],
|
|
165
|
+
'zSliceThickness' : 200,
|
|
166
|
+
'softRender' : True
|
|
167
|
+
}
|
|
168
|
+
if ret == wx.ID_OK:
|
|
169
|
+
im = self.Generate(generateSettings,splitSettings=splitSettings)
|
|
170
|
+
imfc = ViewIm3D(im, mode='visGUI', title='Generated %s - %3.1fnm bins' % (self.name, im.pixelSize),
|
|
171
|
+
glCanvas=self.visFr.glCanvas, parent=self.mainWind)
|
|
172
|
+
else:
|
|
173
|
+
imfc = None
|
|
174
|
+
|
|
175
|
+
dlg.Destroy()
|
|
176
|
+
return imfc
|
|
177
|
+
|
|
178
|
+
class splitRenderPlugin:
|
|
179
|
+
def __init__(self, visFr):
|
|
180
|
+
self.visFr = visFr
|
|
181
|
+
self.pipeline = visFr.pipeline
|
|
182
|
+
self.renderer = SplitRenderer(visFr, visFr.pipeline)
|
|
183
|
+
self.splitSettings = {
|
|
184
|
+
'BlockSize' : 100,
|
|
185
|
+
'Colour' : 'Everything',
|
|
186
|
+
'Mode' : 'TimeBlock'}
|
|
187
|
+
self.renderSettings = {
|
|
188
|
+
'PixelSize' : 5,
|
|
189
|
+
'JitterFactor' : 1.0,
|
|
190
|
+
'SamplesToAverage' : 40}
|
|
191
|
+
|
|
192
|
+
visFr.AddMenuItem('Experimental>Deprecated>Rendering',
|
|
193
|
+
'Split Render by Time Blocks',
|
|
194
|
+
self.deprecated, # self.OnSplitRender,
|
|
195
|
+
helpText='this renders a 2 channel image with events split by time blocks that can be used to evaluate the FRC; for multi-colour images the correct colour needs to be selected')
|
|
196
|
+
|
|
197
|
+
def deprecated(self,event=None):
|
|
198
|
+
Warn(self.visFr, 'use Extras>Split by timeblocks for FRC instead',
|
|
199
|
+
caption = 'Function disabled!')
|
|
200
|
+
|
|
201
|
+
def addTimeBlock(self):
|
|
202
|
+
spSet = self.splitSettings
|
|
203
|
+
rSet = self.renderSettings
|
|
204
|
+
tb = TimeBlock(TimeBlockSize=spSet['BlockSize'],
|
|
205
|
+
PixelSize_in_nm = rSet['PixelSize'],
|
|
206
|
+
JitterFactor = rSet['JitterFactor'],
|
|
207
|
+
SamplesToAverage = rSet['SamplesToAverage'])
|
|
208
|
+
tb.add_keys(['Everything']+self.pipeline.colourFilter.getColourChans())
|
|
209
|
+
tb.Colour = 'Everything'
|
|
210
|
+
|
|
211
|
+
if tb.configure_traits(kind='modal'):
|
|
212
|
+
psd = self.pipeline.selectedDataSource
|
|
213
|
+
blockSel = np.mod((psd['t']/tb.TimeBlockSize).astype('int'),2)
|
|
214
|
+
|
|
215
|
+
spSet['BlockSize'] = tb.TimeBlockSize # remember choices
|
|
216
|
+
spSet['Colour'] = tb.Colour
|
|
217
|
+
rSet['PixelSize'] = tb.PixelSize_in_nm
|
|
218
|
+
rSet['JitterFactor'] = tb.JitterFactor
|
|
219
|
+
rSet['SamplesToAverage'] = tb.SamplesToAverage
|
|
220
|
+
self.pipeline.selectedDataSource.addColumn('timeBlock',blockSel)
|
|
221
|
+
self.pipeline.Rebuild()
|
|
222
|
+
return True
|
|
223
|
+
else:
|
|
224
|
+
return False
|
|
225
|
+
|
|
226
|
+
def OnSplitRender(self,event=None):
|
|
227
|
+
if not self.addTimeBlock():
|
|
228
|
+
return
|
|
229
|
+
oldCol = self.pipeline.colourFilter.currentColour
|
|
230
|
+
if self.splitSettings['Colour'] == 'Everything':
|
|
231
|
+
cChoice = None
|
|
232
|
+
else:
|
|
233
|
+
cChoice = self.splitSettings['Colour']
|
|
234
|
+
|
|
235
|
+
if oldCol != cChoice:
|
|
236
|
+
self.pipeline.colourFilter.setColour(cChoice)
|
|
237
|
+
self.renderer.GenerateGUI(renderSettings=self.renderSettings,
|
|
238
|
+
splitSettings=self.splitSettings)
|
|
239
|
+
if oldCol != cChoice:
|
|
240
|
+
self.pipeline.colourFilter.setColour(oldCol)
|
|
241
|
+
self.pipeline.Rebuild()
|
|
242
|
+
|
|
243
|
+
def Plug(visFr):
|
|
244
|
+
'''Plugs this module into the gui'''
|
|
245
|
+
# disable this function for now
|
|
246
|
+
visFr.splitRender = splitRenderPlugin(visFr)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
logger = logging.getLogger(__file__)
|
|
3
|
+
import wx
|
|
4
|
+
|
|
5
|
+
from PYMEcs.recipes.base import ExtractChannelByName
|
|
6
|
+
|
|
7
|
+
def Msg(parent, message, caption = 'Message'):
|
|
8
|
+
dlg = wx.MessageDialog(parent, message, caption, wx.OK)
|
|
9
|
+
dlg.ShowModal()
|
|
10
|
+
dlg.Destroy()
|
|
11
|
+
|
|
12
|
+
class TestChannelByName:
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
"""
|
|
16
|
+
def __init__(self, dsviewer):
|
|
17
|
+
self.dsviewer = dsviewer
|
|
18
|
+
self.ec = ExtractChannelByName()
|
|
19
|
+
dsviewer.AddMenuItem('Experimental>Misc',
|
|
20
|
+
'Test Channel Name Matching by RegEx',
|
|
21
|
+
self.OnMatch,
|
|
22
|
+
helpText='test the regex matching of the ExtracChannelByName module')
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def OnMatch(self, event=None):
|
|
26
|
+
if not self.ec.configure_traits(kind='modal'):
|
|
27
|
+
return
|
|
28
|
+
mdh = self.dsviewer.image.mdh
|
|
29
|
+
channelNames = mdh.getOrDefault('ChannelNames',[])
|
|
30
|
+
matches = self.ec._matchChannels(channelNames)
|
|
31
|
+
Msg(None,"ChannelNames: \n\t%s\n\nMatches :\n \t%s" % (channelNames, [channelNames[i] for i in matches]))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def Plug(dsviewer):
|
|
35
|
+
"""Plugs this module into the gui"""
|
|
36
|
+
dsviewer.tChanByName = TestChannelByName(dsviewer)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
class TimedSpecies:
|
|
2
|
+
def __init__(self, visFr):
|
|
3
|
+
self.visFr = visFr
|
|
4
|
+
self.pipeline = visFr.pipeline
|
|
5
|
+
|
|
6
|
+
visFr.AddMenuItem('Experimental>Deprecated', "Sequential Imaging - Timed species assignment",self.OnTimedSpecies)
|
|
7
|
+
|
|
8
|
+
def OnTimedSpecies(self,event):
|
|
9
|
+
from PYMEcs.recipes import localisations
|
|
10
|
+
recipe = self.pipeline.recipe
|
|
11
|
+
tsm = localisations.TimedSpecies(recipe,
|
|
12
|
+
inputName=self.pipeline.selectedDataSourceKey,
|
|
13
|
+
outputName='timedSpecies')
|
|
14
|
+
# configure first as subsequent reconfigs could be slow due to
|
|
15
|
+
# recalculations happening as you type
|
|
16
|
+
# if you cancel at this stage you will abort this recipe being
|
|
17
|
+
# inserted and executed
|
|
18
|
+
if not tsm.configure_traits(kind='modal'):
|
|
19
|
+
return
|
|
20
|
+
recipe.add_module(tsm)
|
|
21
|
+
recipe.execute()
|
|
22
|
+
|
|
23
|
+
self.pipeline.selectDataSource('timedSpecies')
|
|
24
|
+
self.pipeline.Rebuild()
|
|
25
|
+
|
|
26
|
+
def Plug(visFr):
|
|
27
|
+
'''Plugs this module into the gui'''
|
|
28
|
+
visFr.timedSpecies = TimedSpecies(visFr)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
logger = logging.getLogger(__file__)
|
|
3
|
+
import wx
|
|
4
|
+
|
|
5
|
+
class dsviewerUtils:
|
|
6
|
+
def __init__(self, dsviewer):
|
|
7
|
+
self.dsviewer = dsviewer
|
|
8
|
+
dsviewer.AddMenuItem('Experimental>Utils',
|
|
9
|
+
'Save recipe from metadata',
|
|
10
|
+
self.OnSaveRecipeFromMDH,
|
|
11
|
+
helpText='try to save a recipe as yaml from image metadata')
|
|
12
|
+
|
|
13
|
+
def OnSaveRecipeFromMDH(self, event=None):
|
|
14
|
+
with wx.FileDialog(self.dsviewer, "Choose recipe file name", wildcard='YAML (*.yaml)|*.yaml',
|
|
15
|
+
style=wx.FD_SAVE) as dialog:
|
|
16
|
+
|
|
17
|
+
if dialog.ShowModal() == wx.ID_CANCEL:
|
|
18
|
+
return
|
|
19
|
+
|
|
20
|
+
filename = dialog.GetPath()
|
|
21
|
+
|
|
22
|
+
from PYMEcs.misc.utils import recipe_from_mdh
|
|
23
|
+
recipe = recipe_from_mdh(self.dsviewer.image.mdh)
|
|
24
|
+
if recipe is not None:
|
|
25
|
+
with open(filename,"w") as fi:
|
|
26
|
+
print(recipe,file=fi)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def Plug(dsviewer):
|
|
30
|
+
"""Plugs this module into the gui"""
|
|
31
|
+
dsviewerUtils(dsviewer)
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import matplotlib.colors as mcol
|
|
2
|
+
import matplotlib.pyplot as plt
|
|
3
|
+
import numpy as np
|
|
4
|
+
import pylab
|
|
5
|
+
from PYME.misc.colormaps import cm
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def r(rgb):
|
|
9
|
+
return rgb[0]
|
|
10
|
+
|
|
11
|
+
def g(rgb):
|
|
12
|
+
return rgb[1]
|
|
13
|
+
|
|
14
|
+
def b(rgb):
|
|
15
|
+
return rgb[2]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def hot_overflow(underflowcol = 'magenta', overflowcol = 'lime', percentage=5):
|
|
19
|
+
if percentage < 1:
|
|
20
|
+
percentage = 1
|
|
21
|
+
if percentage > 15:
|
|
22
|
+
percentage = 15
|
|
23
|
+
|
|
24
|
+
ucolrgb = mcol.hex2color(mcol.cnames[underflowcol])
|
|
25
|
+
ocolrgb = mcol.hex2color(mcol.cnames[overflowcol])
|
|
26
|
+
p = 0.01 * percentage
|
|
27
|
+
|
|
28
|
+
# edited from hot_data in matplotlib
|
|
29
|
+
hot_data = {'red': [(0, r(ucolrgb), r(ucolrgb)),
|
|
30
|
+
(p, r(ucolrgb), 0.0416),
|
|
31
|
+
(0.365079, 1.000000, 1.000000),
|
|
32
|
+
(1.0-p, 1.0, r(ocolrgb)),
|
|
33
|
+
(1.0, r(ocolrgb), r(ocolrgb))],
|
|
34
|
+
'green': [(0, g(ucolrgb), g(ucolrgb)),
|
|
35
|
+
(p, g(ucolrgb), 0.),
|
|
36
|
+
(0.365079, 0.000000, 0.000000),
|
|
37
|
+
(0.746032, 1.000000, 1.000000),
|
|
38
|
+
(1.0-p, 1.0, g(ocolrgb)),
|
|
39
|
+
(1.0, g(ocolrgb), g(ocolrgb))],
|
|
40
|
+
'blue': [(0, b(ucolrgb), b(ucolrgb)),
|
|
41
|
+
(p, b(ucolrgb), 0.),
|
|
42
|
+
(0.746032, 0.000000, 0.000000),
|
|
43
|
+
(1.0-p, 1.0, b(ocolrgb)),
|
|
44
|
+
(1.0, b(ocolrgb), b(ocolrgb))]}
|
|
45
|
+
|
|
46
|
+
cm_hot2 = mcol.LinearSegmentedColormap('hot_overflow', hot_data)
|
|
47
|
+
return cm_hot2
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def grey_overflow(underflowcol = 'magenta', overflowcol = 'lime', percentage=5, greystart=0.1):
|
|
51
|
+
if percentage < 1:
|
|
52
|
+
percentage = 1
|
|
53
|
+
if percentage > 15:
|
|
54
|
+
percentage = 15
|
|
55
|
+
|
|
56
|
+
ucolrgb = mcol.hex2color(mcol.cnames[underflowcol])
|
|
57
|
+
ocolrgb = mcol.hex2color(mcol.cnames[overflowcol])
|
|
58
|
+
p = 0.01 * percentage
|
|
59
|
+
|
|
60
|
+
grey_data = {'red': [(0, r(ucolrgb), r(ucolrgb)),
|
|
61
|
+
(p, r(ucolrgb), greystart),
|
|
62
|
+
(1.0-p, 1.0, r(ocolrgb)),
|
|
63
|
+
(1.0, r(ocolrgb), r(ocolrgb))],
|
|
64
|
+
'green': [(0, g(ucolrgb), g(ucolrgb)),
|
|
65
|
+
(p, g(ucolrgb), greystart),
|
|
66
|
+
(1.0-p, 1.0, g(ocolrgb)),
|
|
67
|
+
(1.0, g(ocolrgb), g(ocolrgb))],
|
|
68
|
+
'blue': [(0, b(ucolrgb), b(ucolrgb)),
|
|
69
|
+
(p, b(ucolrgb), greystart),
|
|
70
|
+
(1.0-p, 1.0, b(ocolrgb)),
|
|
71
|
+
(1.0, b(ocolrgb), b(ocolrgb))]}
|
|
72
|
+
|
|
73
|
+
cm_grey2 = mcol.LinearSegmentedColormap('grey_overflow', grey_data)
|
|
74
|
+
return cm_grey2
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def grey_overflow2(underflowcol = 'magenta', overflowcol = 'lime', percentage=5):
|
|
78
|
+
if percentage < 1:
|
|
79
|
+
percentage = 1
|
|
80
|
+
if percentage > 30:
|
|
81
|
+
percentage = 30
|
|
82
|
+
clist = [(0,mcol.cnames[underflowcol]),
|
|
83
|
+
# (0.01*percentage,mcol.cnames['dimgrey']),
|
|
84
|
+
(0.01*percentage,(0.15,0.15,0.15)),
|
|
85
|
+
(1.0-0.01*percentage,mcol.cnames['white']),
|
|
86
|
+
(1.0,mcol.cnames[overflowcol])]
|
|
87
|
+
|
|
88
|
+
return mcol.LinearSegmentedColormap.from_list('grey_overflow2',clist)
|
|
89
|
+
|
|
90
|
+
# this function needs some work
|
|
91
|
+
def overflow_wrap(cmapname, underflowcol = 'magenta', overflowcol = 'lime', percentage=5):
|
|
92
|
+
cmap = pylab.get_cmap(cmapname)
|
|
93
|
+
if percentage < 0:
|
|
94
|
+
percentage = 0
|
|
95
|
+
if percentage > 10:
|
|
96
|
+
percentage = 10
|
|
97
|
+
p = 0.01*percentage
|
|
98
|
+
def mymap(c):
|
|
99
|
+
ret = cmap(c)
|
|
100
|
+
if c < p:
|
|
101
|
+
return colors.hex2color(colors.cnames[underflowcol])
|
|
102
|
+
elif c > 1.0-p:
|
|
103
|
+
return colors.hex2color(colors.cnames[overflowcol])
|
|
104
|
+
else:
|
|
105
|
+
return cmap(c/(1.0-2*p)+p)
|
|
106
|
+
|
|
107
|
+
mymap.name = cmap.name + '_overflow'
|
|
108
|
+
return mymap
|
|
109
|
+
|
|
110
|
+
# FIJI inspired colour maps
|
|
111
|
+
|
|
112
|
+
# cyan hot (for pylab devide all values by 255.0)
|
|
113
|
+
# red: 0 0, 170 0, 255 255
|
|
114
|
+
# green: 0 0, 170 255, 255, 255
|
|
115
|
+
# blue: 0 0, 85, 255, 255 255
|
|
116
|
+
|
|
117
|
+
# cb_skyblue
|
|
118
|
+
# red: 0 0, 255 85
|
|
119
|
+
# green: 0 0, 255 180
|
|
120
|
+
# blue: 0 0, 255 232
|
|
121
|
+
|
|
122
|
+
# generate a 3-tupel for continuous colour and normalise to 0..1
|
|
123
|
+
def contc(x,y):
|
|
124
|
+
return (x/255.0,y/255.0,y/255.0)
|
|
125
|
+
|
|
126
|
+
cyan_hot_d = {
|
|
127
|
+
'red' : [contc(0,0),contc(170,0),contc(255,255)],
|
|
128
|
+
'green' : [contc(0,0),contc(170,255),contc(255,255)],
|
|
129
|
+
'blue' : [contc(0,0),contc(85,255),contc(255,255)]
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
cb_skyblue_d = {
|
|
133
|
+
'red' : [contc(0,0),contc(255,85)],
|
|
134
|
+
'green' : [contc(0,0),contc(255,180)],
|
|
135
|
+
'blue' : [contc(0,0),contc(255,232)]
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
cb_skyblue2_d = {
|
|
139
|
+
'red' : [contc(0,0),contc(200,85),contc(255,255)],
|
|
140
|
+
'green' : [contc(0,0),contc(200,180),contc(255,255)],
|
|
141
|
+
'blue' : [contc(0,0),contc(200,232),contc(255,255)]
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
cm_ch = mcol.LinearSegmentedColormap('cyan_hot',cyan_hot_d)
|
|
145
|
+
cm_cbskb = mcol.LinearSegmentedColormap('cb_skyblue',cb_skyblue_d)
|
|
146
|
+
cm_cbskb2 = mcol.LinearSegmentedColormap('cb_skyblue2',cb_skyblue2_d)
|
|
147
|
+
|
|
148
|
+
cm.update({cmap.name: cmap for cmap in [cm_ch,cm_cbskb,cm_cbskb2,hot_overflow(overflowcol='cyan',percentage=2.5)]})
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
############################
|
|
152
|
+
### if colorcet is installed
|
|
153
|
+
### register a few cms
|
|
154
|
+
############################
|
|
155
|
+
try:
|
|
156
|
+
import colorcet as cc
|
|
157
|
+
has_colorcet = True
|
|
158
|
+
except ImportError:
|
|
159
|
+
has_colorcet = False
|
|
160
|
+
|
|
161
|
+
if has_colorcet:
|
|
162
|
+
cm.update({'cet_fire':cc.m_fire,
|
|
163
|
+
'cet_coolwarm': cc.m_coolwarm,
|
|
164
|
+
'cet_bmw': cc.m_bmw,
|
|
165
|
+
'cet_bmy': cc.m_bmy})
|
|
166
|
+
|
|
167
|
+
def main():
|
|
168
|
+
import numpy as np
|
|
169
|
+
a=np.outer(np.arange(0,1,0.01),np.ones(10))
|
|
170
|
+
# cm1 = grey_overflow()
|
|
171
|
+
# cm1 = grey_overflow2(percentage=2)
|
|
172
|
+
cm1 = hot_overflow(overflowcol='cyan')
|
|
173
|
+
# cm1 = overflow_wrap('jet')
|
|
174
|
+
plt.imshow(a,aspect='auto',cmap=cm1,origin="lower")
|
|
175
|
+
|
|
176
|
+
if __name__ == "__main__":
|
|
177
|
+
main()
|
PYMEcs/misc/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
from PYME import config
|
|
2
|
+
import os
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
DSVIEWER_PLUGINS = \
|
|
6
|
+
'''
|
|
7
|
+
PYMEcs.experimental.showErrsDh5view
|
|
8
|
+
PYMEcs.experimental.mapTools
|
|
9
|
+
PYMEcs.experimental.meas2DplotDh5view
|
|
10
|
+
PYMEcs.experimental.testChannelByName
|
|
11
|
+
PYMEcs.experimental.FRC
|
|
12
|
+
PYMEcs.experimental.regExtraCmaps
|
|
13
|
+
PYMEcs.experimental.procPoints
|
|
14
|
+
PYMEcs.experimental.combine_maps
|
|
15
|
+
PYMEcs.experimental.Sofi
|
|
16
|
+
PYMEcs.experimental.CalcZfactor
|
|
17
|
+
PYMEcs.experimental.ImageJROItools
|
|
18
|
+
'''
|
|
19
|
+
|
|
20
|
+
VISGUI_PLUGINS = \
|
|
21
|
+
'''
|
|
22
|
+
PYMEcs.experimental.clusterTrack
|
|
23
|
+
PYMEcs.experimental.fiducials
|
|
24
|
+
PYMEcs.experimental.fiducialsNew
|
|
25
|
+
PYMEcs.experimental.qPAINT
|
|
26
|
+
PYMEcs.experimental.showErrs
|
|
27
|
+
PYMEcs.experimental.showShiftMap
|
|
28
|
+
PYMEcs.experimental.binEventProperty
|
|
29
|
+
PYMEcs.experimental.onTimes
|
|
30
|
+
PYMEcs.experimental.snrEvents
|
|
31
|
+
PYMEcs.experimental.randMap
|
|
32
|
+
PYMEcs.experimental.mortensen
|
|
33
|
+
PYMEcs.experimental.splitRender
|
|
34
|
+
PYMEcs.experimental.timedSpecies
|
|
35
|
+
PYMEcs.experimental.chaining
|
|
36
|
+
PYMEcs.experimental.specLabeling
|
|
37
|
+
PYMEcs.experimental.selectROIfilterTable
|
|
38
|
+
PYMEcs.experimental.regExtraCmaps
|
|
39
|
+
PYMEcs.experimental.pyme2caml
|
|
40
|
+
PYMEcs.experimental.Simpler
|
|
41
|
+
PYMEcs.experimental.MINFLUX
|
|
42
|
+
PYMEcs.experimental.eventProcessing
|
|
43
|
+
PYMEcs.experimental.NPCcalcLM
|
|
44
|
+
'''
|
|
45
|
+
|
|
46
|
+
RECIPES = \
|
|
47
|
+
'''
|
|
48
|
+
PYMEcs.recipes.processing
|
|
49
|
+
PYMEcs.recipes.output
|
|
50
|
+
PYMEcs.recipes.base
|
|
51
|
+
PYMEcs.recipes.localisations
|
|
52
|
+
PYMEcs.recipes.simpler
|
|
53
|
+
'''
|
|
54
|
+
|
|
55
|
+
def get_legacy_scripts_dir():
|
|
56
|
+
return os.path.join(os.path.dirname(config.__file__), 'Acquire/Scripts')
|
|
57
|
+
|
|
58
|
+
# this tries to replicate what config.get_init_filename does
|
|
59
|
+
# if the config function were changed we would need to change this one as well
|
|
60
|
+
def get_init_directories_to_search():
|
|
61
|
+
directories_to_search = [os.path.join(conf_dir, 'init_scripts') for conf_dir in config.config_dirs]
|
|
62
|
+
|
|
63
|
+
extra_conf_dir = config.config.get('PYMEAcquire-extra_init_dir')
|
|
64
|
+
if not extra_conf_dir is None:
|
|
65
|
+
directories_to_search.insert(0, extra_conf_dir)
|
|
66
|
+
|
|
67
|
+
directories_to_search.insert(0,get_legacy_scripts_dir())
|
|
68
|
+
|
|
69
|
+
return directories_to_search
|
|
70
|
+
|
|
71
|
+
def list_config_dirs():
|
|
72
|
+
print('List of configuration directories:')
|
|
73
|
+
for dir in config.config_dirs:
|
|
74
|
+
print(dir)
|
|
75
|
+
|
|
76
|
+
def install_plugins():
|
|
77
|
+
# options parsing
|
|
78
|
+
import argparse
|
|
79
|
+
from pathlib import Path
|
|
80
|
+
|
|
81
|
+
logging.basicConfig(level=logging.INFO)
|
|
82
|
+
op = argparse.ArgumentParser(description='install PYME-extra plugins')
|
|
83
|
+
op.add_argument('-u','--user', action='store_true',
|
|
84
|
+
help='install plugin info to user config directory')
|
|
85
|
+
op.add_argument('--dry-run',action="store_true",
|
|
86
|
+
help='just process options and merely show what would be done')
|
|
87
|
+
|
|
88
|
+
args = op.parse_args()
|
|
89
|
+
if args.user:
|
|
90
|
+
installdir = Path(config.user_config_dir)
|
|
91
|
+
else:
|
|
92
|
+
installdir = Path(config.dist_config_directory)
|
|
93
|
+
|
|
94
|
+
recfile = installdir / 'plugins' / 'recipes' / 'PYMEcsRecipePlugins.txt'
|
|
95
|
+
visguifile = installdir / 'plugins' / 'visgui' / 'PYMEcsVisguiPlugins.txt'
|
|
96
|
+
dsviewerfile = installdir / 'plugins' / 'dsviewer' / 'PYMEcsDsviewerPlugins.txt'
|
|
97
|
+
|
|
98
|
+
logging.info("will install recipes to\n\t%s" % recfile)
|
|
99
|
+
logging.info("will install visgui plugins to\n\t%s" % visguifile)
|
|
100
|
+
logging.info("will install dsviewer plugins to\n\t%s" % dsviewerfile)
|
|
101
|
+
|
|
102
|
+
if args.dry_run:
|
|
103
|
+
logging.info("dry run, aborting...")
|
|
104
|
+
import sys
|
|
105
|
+
sys.exit(0)
|
|
106
|
+
|
|
107
|
+
recfile.write_text(RECIPES)
|
|
108
|
+
visguifile.write_text(VISGUI_PLUGINS)
|
|
109
|
+
dsviewerfile.write_text(DSVIEWER_PLUGINS)
|
|
110
|
+
|
|
111
|
+
logging.info("\nPYME-extra recipes and plugins have been registered...")
|
|
112
|
+
|
|
113
|
+
def main():
|
|
114
|
+
import sys
|
|
115
|
+
import argparse
|
|
116
|
+
import pprint
|
|
117
|
+
|
|
118
|
+
# options parsing
|
|
119
|
+
op = argparse.ArgumentParser(description='inspect PYME config files and settings.')
|
|
120
|
+
op.add_argument('--initdirs', action='store_true',
|
|
121
|
+
help='list directories searched for init files')
|
|
122
|
+
op.add_argument('-p','--parameters', action='store_true',
|
|
123
|
+
help='print configuration parameters', dest='config_params')
|
|
124
|
+
op.add_argument('-d','--directories', action='store_true',
|
|
125
|
+
help='print configuration directories')
|
|
126
|
+
op.add_argument('--protocols', action='store_true',
|
|
127
|
+
help='print custom protols found')
|
|
128
|
+
op.add_argument('-i','--initfile', default=None,
|
|
129
|
+
help='locate init file and if found print full path')
|
|
130
|
+
|
|
131
|
+
args = op.parse_args()
|
|
132
|
+
|
|
133
|
+
if args.initdirs:
|
|
134
|
+
print('List of directories searched for init scripts, legacy path included:')
|
|
135
|
+
for dir in get_init_directories_to_search():
|
|
136
|
+
print(dir)
|
|
137
|
+
sys.exit(0)
|
|
138
|
+
|
|
139
|
+
if args.directories:
|
|
140
|
+
list_config_dirs()
|
|
141
|
+
sys.exit(0)
|
|
142
|
+
|
|
143
|
+
if args.config_params:
|
|
144
|
+
print('List of configuration parameters:')
|
|
145
|
+
for par in config.config.keys():
|
|
146
|
+
print('%s : %s' % (par,config.config[par]))
|
|
147
|
+
sys.exit(0)
|
|
148
|
+
|
|
149
|
+
if args.protocols:
|
|
150
|
+
prots = config.get_custom_protocols()
|
|
151
|
+
print('Custom Protocols:')
|
|
152
|
+
pprint.pprint(prots)
|
|
153
|
+
sys.exit(0)
|
|
154
|
+
|
|
155
|
+
if args.initfile is not None:
|
|
156
|
+
inipath = config.get_init_filename(args.initfile, get_legacy_scripts_dir())
|
|
157
|
+
if inipath is None:
|
|
158
|
+
print("Initialisation file %s was not found" % args.initfile)
|
|
159
|
+
else:
|
|
160
|
+
print("Initialisation file %s was resolved as %s" %
|
|
161
|
+
(args.initfile,os.path.abspath(inipath)))
|
|
162
|
+
sys.exit(0)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
# if we got here carry out a default action
|
|
166
|
+
list_config_dirs()
|
|
167
|
+
|
|
168
|
+
if __name__ == "__main__":
|
|
169
|
+
main()
|