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,27 @@
1
+ import wx
2
+
3
+ # a few simple message box utility functions
4
+
5
+ def YesNo(parent, question, caption = 'Yes or no?'):
6
+ dlg = wx.MessageDialog(parent, question, caption, wx.YES_NO | wx.ICON_QUESTION)
7
+ result = dlg.ShowModal() == wx.ID_YES
8
+ dlg.Destroy()
9
+ return result
10
+
11
+
12
+ def Info(parent, message, caption = 'Python Microscopy Environment'):
13
+ dlg = wx.MessageDialog(parent, message, caption, wx.OK | wx.ICON_INFORMATION)
14
+ dlg.ShowModal()
15
+ dlg.Destroy()
16
+
17
+
18
+ def Warn(parent, message, caption = 'Warning!'):
19
+ dlg = wx.MessageDialog(parent, message, caption, wx.OK | wx.ICON_WARNING)
20
+ dlg.ShowModal()
21
+ dlg.Destroy()
22
+
23
+
24
+ def Error(parent, message, caption = 'Error!'):
25
+ dlg = wx.MessageDialog(parent, message, caption, wx.OK | wx.ICON_ERROR)
26
+ dlg.ShowModal()
27
+ dlg.Destroy()
@@ -0,0 +1,230 @@
1
+ from PYME.localization.remFitBuf import CameraInfoManager
2
+ import PYME.Analysis.gen_sCMOS_maps as gmaps
3
+ from PYME.IO.MetaDataHandler import NestedClassMDHandler
4
+ from PYME.IO.image import ImageStack
5
+ from PYME.DSView import ViewIm3D
6
+ from PYME.IO.FileUtils import nameUtils
7
+ import numpy as np
8
+
9
+ import logging
10
+ logger = logging.getLogger(__name__)
11
+
12
+ defaultCalibrationDir = nameUtils.getCalibrationDir('',create=False)
13
+
14
+ def defaultMapName(source, createPath=False, calibrationDir=defaultCalibrationDir):
15
+ resname = source.mdh.getOrDefault('Analysis.resultname',None)
16
+ if resname is None:
17
+ return None
18
+
19
+ if resname == 'mean':
20
+ if source.mdh.getOrDefault('Analysis.FlatField',False):
21
+ maptype = 'flatfield'
22
+ else:
23
+ maptype = 'dark'
24
+ else:
25
+ maptype = 'variance'
26
+
27
+ mapname = gmaps.mkDefaultPath(maptype, source.mdh, create=createPath, calibrationDir=calibrationDir)
28
+ return mapname
29
+
30
+ # return a list of existing camera directories that have tif files inside (assuming these are camera maps)
31
+ def installedCams(calibrationDir=defaultCalibrationDir):
32
+ from glob import glob
33
+ import os
34
+
35
+ camdirs = []
36
+ for (dirpath, dirnames, filenames) in os.walk(calibrationDir):
37
+ camdirs.extend(dirnames)
38
+ break
39
+ fulldirs = [os.path.join(calibrationDir,cdir) for cdir in camdirs]
40
+ validdirs = [cdir for cdir in fulldirs if glob(os.path.join(cdir, '*.tif'))]
41
+
42
+ return validdirs
43
+
44
+
45
+ # source passed as PYME ImageStack
46
+ def install_map(source, calibrationDir=defaultCalibrationDir):
47
+ """Installs a map file to a calibration directory. By default uses the system claibration directory."""
48
+
49
+ import os
50
+ if source.mdh.getOrDefault('Analysis.name', '') != 'mean-variance':
51
+ msg = 'map %s, Analysis.name is not equal to "mean-variance" - probably not a map' % source.filename
52
+ return msg
53
+
54
+ validROIHeight = source.mdh.getOrDefault('Analysis.valid.ROIHeight',
55
+ source.mdh['Camera.ROIHeight'])
56
+ validROIWidth = source.mdh.getOrDefault('Analysis.valid.ROIWidth',
57
+ source.mdh['Camera.ROIWidth'])
58
+ if not (validROIHeight == source.mdh['Camera.ROIHeight']
59
+ and validROIWidth == source.mdh['Camera.ROIWidth']):
60
+ msg = 'Partial (ROI based) maps cannot be installed to a calibration directory'
61
+ return msg
62
+
63
+ if source.mdh.getOrDefault('Analysis.isuniform', False):
64
+ msg = 'Uniform maps cannot be installed to ba calibration directory'
65
+ return msg
66
+
67
+ if source.mdh['Analysis.resultname'] == 'mean':
68
+ if source.mdh.getOrDefault('Analysis.FlatField',False):
69
+ maptype = 'flatfield'
70
+ else:
71
+ maptype = 'dark'
72
+ else:
73
+ maptype = 'variance'
74
+
75
+ mapname = gmaps.mkDefaultPath(maptype, source.mdh, create=True, calibrationDir=calibrationDir)
76
+ if os.path.isfile(mapname):
77
+ msg = 'map %s exists, not overwriting' % mapname
78
+ return msg
79
+
80
+ source.Save(filename=mapname)
81
+ return None
82
+
83
+ # attempt to install a map in a calibration dir but check a few things
84
+ # 1) does it have the .tif extension?
85
+ # 2) can it be opened as a tiffstack
86
+ # 3) if all ok so far pass on to install_map which does additional checks; note that
87
+ # this function does not overwrite existing maps at the destination
88
+ def checkAndInstallMap(mapf, calibrationDir=defaultCalibrationDir):
89
+ import os
90
+ inst = 0
91
+
92
+ ext = os.path.splitext(mapf)[-1].lower()
93
+ if ext != ".tif":
94
+ msg = 'asked to install %s, not a tif extension' % mapf
95
+ return (inst, msg)
96
+ try:
97
+ source = ImageStack(filename=mapf)
98
+ except:
99
+ msg = 'asked to install %s, could not open as PYME ImageStack, not a map?' % mapf
100
+ return (inst, msg)
101
+
102
+ msg = install_map(source, calibrationDir=calibrationDir)
103
+ if msg is None:
104
+ msg = 'installed map %s in default location' % mapf
105
+ msg += "\n\t-> %s" % defaultMapName(source, calibrationDir=calibrationDir)
106
+ inst = 1
107
+
108
+ return (inst, msg)
109
+
110
+
111
+ # install maps, potentially several
112
+ # if fromfile is a directory attempt to install all maps below that directory
113
+ # if fromfile is a file, attempt to install that single file
114
+ def installMapsFrom(fromfile, calibrationDir=defaultCalibrationDir):
115
+ from glob import glob
116
+ import os
117
+
118
+ msgs = []
119
+ ntotal = 0
120
+ if os.path.isdir(fromfile):
121
+ # this is a directory, walk it
122
+ msgs.append("Installing maps from directory %s -> %s Folder\n" % (fromfile,calibrationDir))
123
+ mapfiles = [y for x in os.walk(fromfile) for y in glob(os.path.join(x[0], '*.tif'))]
124
+ for mapf in mapfiles:
125
+ ninst, msg = checkAndInstallMap(mapf, calibrationDir=calibrationDir)
126
+ ntotal += ninst
127
+ msgs.append(msg)
128
+ else:
129
+ ninst, msg = checkAndInstallMap(fromfile, calibrationDir=calibrationDir)
130
+ ntotal = 1
131
+ msgs.append(msg)
132
+ msgs.append("\ninstalled %d maps" % ntotal)
133
+ return ntotal, "\n".join(msgs)
134
+
135
+
136
+ def getInstalledMapList():
137
+ from glob import glob
138
+ import os
139
+ rootdir = defaultCalibrationDir
140
+ result = [y for x in os.walk(rootdir) for y in glob(os.path.join(x[0], '*.tif'))]
141
+
142
+ return result
143
+
144
+
145
+ def check_mapexists(mdh, type = 'dark'):
146
+ import os
147
+ if type == 'dark':
148
+ id = 'Camera.DarkMapID'
149
+ elif type == 'variance':
150
+ id = 'Camera.VarianceMapID'
151
+ elif type == 'flatfield':
152
+ id = 'Camera.FlatfieldMapID'
153
+ else:
154
+ raise RuntimeError('unknown map type %s' % type)
155
+
156
+
157
+ mPath = mdh.getOrDefault(id,'')
158
+ defPath = gmaps.mkDefaultPath(type,mdh,create=False)
159
+ if os.path.exists(mPath):
160
+ return mPath
161
+ elif os.path.exists(defPath):
162
+ mdh[id] = defPath
163
+ return defPath
164
+ else:
165
+ mdh[id] = ''
166
+ return None
167
+
168
+ def mk_compositeMap(sourcemap):
169
+ # make new composite map using sourcemap to populate
170
+ # check source is a map
171
+ # composite map has first channel with map data, second channel is mask where map is valid
172
+ # returns composite map (identified by its metadata)
173
+ pass
174
+
175
+ def addMap2composite(map,compMap):
176
+ # insert map according to valid ROI into composite map
177
+ # update the valid channel accordingly
178
+ # possibly perform a number of checks
179
+ pass
180
+
181
+ def export_mapFromComposite(compMap):
182
+ # export a normal map from the composite map
183
+ # in the exported map we set the valid ROI to the whole chip area
184
+ # return as image?
185
+ pass
186
+
187
+ import os
188
+
189
+ def _getDefaultMap(ci,mdh,maptype = 'dark', return_loadedmdh = False):
190
+ # logic: try map in default calibration dir first
191
+ # if not present just return default value
192
+ mapname = gmaps.mkDefaultPath(maptype, mdh, create=False)
193
+ mdh2 = NestedClassMDHandler(mdh)
194
+ logger.debug("checking map file %s" % mapname)
195
+
196
+ if maptype == 'dark':
197
+ id = 'Camera.DarkMapID'
198
+ elif maptype == 'variance':
199
+ id = 'Camera.VarianceMapID'
200
+ elif maptype == 'flatfield':
201
+ id = 'Camera.FlatfieldMapID'
202
+ else:
203
+ raise RuntimeError('unknown map type %s' % type)
204
+
205
+ if os.path.isfile(mapname):
206
+ mdh2[id] = mapname
207
+ else:
208
+ mdh2[id] = ''
209
+ logger.debug("map file %s does not exist" % mapname)
210
+
211
+ if maptype == 'dark':
212
+ theMap = ci.getDarkMap(mdh2)
213
+ elif maptype == 'variance':
214
+ theMap = ci.getVarianceMap(mdh2)
215
+ elif maptype == 'flatfield':
216
+ theMap = ci.getFlatfieldMap(mdh2)
217
+
218
+ if return_loadedmdh:
219
+ return (theMap,mdh2)
220
+ else:
221
+ return theMap
222
+
223
+ def get_dark_default(ci,mdh):
224
+ return _getDefaultMap(ci,mdh,maptype = 'dark')
225
+
226
+ def get_variance_default(ci,mdh):
227
+ return _getDefaultMap(ci,mdh,maptype = 'variance')
228
+
229
+ def get_flatfield_default(ci,mdh):
230
+ return _getDefaultMap(ci,mdh,maptype = 'flatfield')
@@ -0,0 +1,136 @@
1
+ import matplotlib.pyplot as plt
2
+ import numpy as np
3
+ from numbers import Number
4
+
5
+ def figuredefaults(fontsize=10,linewidth=1.5):
6
+ plt.rcParams['axes.linewidth'] = linewidth
7
+ plt.rcParams['xtick.major.width'] = linewidth
8
+ plt.rcParams['ytick.major.width'] = linewidth
9
+ plt.rcParams['font.family']='arial'
10
+ plt.rcParams['font.size'] = fontsize
11
+ plt.rcParams['svg.fonttype'] = 'none'
12
+
13
+ def boxswarmplot(df,width=0.4,annotate_means=False,annotate_medians=False,showmeans=True,
14
+ meanprops=None,ax=None,swarmsize=7,swarmalpha=None,format="%.1f",
15
+ showpoints=True,strip=False,**kwargs):
16
+ import seaborn as sns
17
+ if meanprops is None:
18
+ meanprops={'marker':'o',
19
+ 'markerfacecolor':'white',
20
+ 'markeredgecolor':'black',
21
+ 'markersize':'8'}
22
+ flierprops = dict(marker='.', markerfacecolor='none', markersize=0, linestyle='none')
23
+ colours = ['#72a4cdff'] * df.shape[1]
24
+ bp = sns.boxplot(df,boxprops={'facecolor': 'none'},width=width,showmeans=showmeans,meanprops=meanprops,ax=ax,flierprops=flierprops,**kwargs)
25
+ if showpoints:
26
+ if strip:
27
+ sns.stripplot(df,size=swarmsize,palette=colours,ax=ax,alpha=swarmalpha)
28
+ else:
29
+ sns.swarmplot(df,size=swarmsize,palette=colours,ax=ax,alpha=swarmalpha)
30
+ if annotate_medians:
31
+ meds = df.median().values
32
+ for i,xtick in enumerate(bp.get_xticks()):
33
+ bp.text(xtick-0.5*width-0.1,meds[i],format % meds[i],
34
+ horizontalalignment='center',verticalalignment='center',
35
+ size='x-small',color='black',weight='semibold')
36
+ if annotate_means:
37
+ means = df.mean().values
38
+ for i,xtick in enumerate(bp.get_xticks()):
39
+ bp.text(xtick+0.5*width+0.1,means[i],format % means[i],
40
+ horizontalalignment='center',verticalalignment='center',
41
+ size='x-small',color='g',weight='semibold')
42
+ return bp
43
+
44
+ def violinswarmplot(df,width=0.8,annotate_means=False,annotate_medians=False,
45
+ ax=None,swarmsize=7,swarmalpha=None,format="%.1f",strip=False,
46
+ annotate_width=0.4,showpoints=True,**kwargs):
47
+ import seaborn as sns
48
+ vp = sns.violinplot(df, ax=ax, color="0.95", width=width, **kwargs)
49
+ colours = ['#72a4cdff'] * df.shape[1]
50
+ if showpoints:
51
+ if strip:
52
+ sns.stripplot(df,size=swarmsize,palette=colours,ax=ax,alpha=swarmalpha, jitter=True, zorder=1)
53
+ else:
54
+ sns.swarmplot(df,size=swarmsize,palette=colours,ax=ax,alpha=swarmalpha, zorder=1)
55
+
56
+ if annotate_medians:
57
+ meds = df.median().values
58
+ for i,xtick in enumerate(vp.get_xticks()):
59
+ vp.text(xtick-0.5*annotate_width-0.1,meds[i],format % meds[i],
60
+ horizontalalignment='center',verticalalignment='center',
61
+ size='x-small',color='black',weight='semibold')
62
+ if annotate_means:
63
+ means = df.mean().values
64
+ for i,xtick in enumerate(vp.get_xticks()):
65
+ vp.text(xtick+0.5*annotate_width+0.1,means[i],format % means[i],
66
+ horizontalalignment='center',verticalalignment='center',
67
+ size='x-small',color='g',weight='semibold')
68
+ return vp
69
+
70
+
71
+ # deprecated
72
+ def _scattered_boxplot(ax, x, notch=None, sym=None, vert=None, whis=None, positions=None,
73
+ widths=None, patch_artist=None, bootstrap=None, usermedians=None, conf_intervals=None,
74
+ meanline=None, showmeans=None, showcaps=None, showbox=None,
75
+ showfliers="unif", hide_points_within_whiskers=False,
76
+ boxprops=None, labels=None, flierprops=None, medianprops=None, meanprops=None,
77
+ capprops=None, whiskerprops=None, manage_ticks=True, autorange=False, zorder=None, *, data=None):
78
+ if showfliers=="classic":
79
+ classic_fliers=True
80
+ else:
81
+ classic_fliers=False
82
+ bp_dict = ax.boxplot(x, notch=notch, sym=sym, vert=vert, whis=whis, positions=positions, widths=widths,
83
+ patch_artist=patch_artist, bootstrap=bootstrap, usermedians=usermedians,
84
+ conf_intervals=conf_intervals, meanline=meanline, showmeans=showmeans, showcaps=showcaps, showbox=showbox,
85
+ showfliers=classic_fliers,
86
+ boxprops=boxprops, labels=labels, flierprops=flierprops, medianprops=medianprops, meanprops=meanprops,
87
+ capprops=capprops, whiskerprops=whiskerprops, manage_ticks=manage_ticks, autorange=autorange, zorder=zorder,data=data)
88
+ N=len(x)
89
+ datashape_message = ("List of boxplot statistics and `{0}` "
90
+ "values must have same the length")
91
+ # check position
92
+ if positions is None:
93
+ positions = list(np.ones_like(x))
94
+ elif len(positions) != N:
95
+ raise ValueError(datashape_message.format("positions"))
96
+
97
+ positions = np.array(positions)
98
+ if len(positions) > 0 and not isinstance(positions[0], Number):
99
+ raise TypeError("positions should be an iterable of numbers")
100
+
101
+ # width
102
+ if widths is None:
103
+ widths = [np.clip(0.15 * np.ptp(positions), 0.15, 0.5)] * N
104
+ elif np.isscalar(widths):
105
+ widths = [widths] * N
106
+ elif len(widths) != N:
107
+ raise ValueError(datashape_message.format("widths"))
108
+
109
+ if hide_points_within_whiskers:
110
+ import matplotlib.cbook as cbook
111
+ from matplotlib import rcParams
112
+ if whis is None:
113
+ whis = rcParams['boxplot.whiskers']
114
+ if bootstrap is None:
115
+ bootstrap = rcParams['boxplot.bootstrap']
116
+ bxpstats = cbook.boxplot_stats(x, whis=whis, bootstrap=bootstrap,
117
+ labels=labels, autorange=autorange)
118
+ for i in range(N):
119
+ if hide_points_within_whiskers:
120
+ xi=bxpstats[i]['fliers']
121
+ else:
122
+ xi=x[i]
123
+ if showfliers=="unif":
124
+ jitter=np.random.uniform(-widths[i]*0.2,widths[i]*0.2,size=np.size(xi))
125
+ elif showfliers=="normal":
126
+ jitter=np.random.normal(loc=0.0, scale=widths[i]*0.1,size=np.size(xi))
127
+ elif showfliers==False or showfliers=="classic":
128
+ return
129
+ else:
130
+ raise NotImplementedError("showfliers='"+str(showfliers)+"' is not implemented. You can choose from 'unif', 'normal', 'classic' and False")
131
+
132
+ ax.scatter(positions[i]+jitter,xi,alpha=0.2,marker="o", facecolors='none', edgecolors="k")
133
+
134
+ return bp_dict
135
+
136
+ # setattr(plt.Axes, "scattered_boxplot", scattered_boxplot)
@@ -0,0 +1,182 @@
1
+ # code for coordinate algebra, specifically rotations given by the `rotation` transform
2
+
3
+ import numpy as np
4
+ import matplotlib.pyplot as plt
5
+
6
+ def vlen(v):
7
+ return np.sqrt(v[0]**2+v[1]**2)
8
+
9
+ def rmat_ang(angle):
10
+ theta = np.radians(-angle)
11
+ # note: tests suggest that for the svg angle we use the *negative* angle for this matrix
12
+ c, s = np.cos(theta), np.sin(theta)
13
+ R = np.array(((c, -s), (s, c)))
14
+ return R
15
+
16
+ def vec(x,y):
17
+ return np.array((x,y))
18
+
19
+ def transform_rot(x,y,angle):
20
+ return vec(x,y).dot(rmat_ang(angle))
21
+
22
+ # the code below parses out the rectangles from an SVG
23
+ # all other elements are ignored
24
+ # for the identified rectangles the code obtains the revelant parameters by retrieveal
25
+ # and string conversion to float
26
+
27
+ import re
28
+
29
+ # NOTE: the argument 'svg' is assumed to be a parsed svg file
30
+ # obtained with something like
31
+ #
32
+ # import xml.etree.ElementTree as ET
33
+ # svg = ET.parse('RyR-pattern-simulation-Ashagri14-Fig1.svg')
34
+ def find_svgrects(svg):
35
+ root = svg.getroot()
36
+ group = root.find('{http://www.w3.org/2000/svg}g')
37
+ rects = group.findall('{http://www.w3.org/2000/svg}rect')
38
+ return rects
39
+
40
+ def parse_rect(rect):
41
+ # ['style', 'id', 'width', 'height', 'x', 'y', 'transform']
42
+ prect = {}
43
+ for key in ['width', 'height', 'x', 'y']:
44
+ prect[key] = float(rect.get(key))
45
+ for key in ['style', 'id']:
46
+ prect[key] = rect.get(key)
47
+ if rect.get('transform') is not None:
48
+ m = re.search('^rotate\(([-+]*[\d.]+)\)',rect.get('transform'))
49
+ if m:
50
+ prect['rot_angle'] = float(m.group(1))
51
+ return prect
52
+
53
+ def parse_rects(rects):
54
+ return [parse_rect(rect) for rect in rects]
55
+
56
+ # code to display parsed rectangles via matplotlib
57
+ # we need this to check that things work as anticipated
58
+
59
+ from matplotlib.collections import PatchCollection
60
+ from matplotlib.patches import Rectangle
61
+
62
+ def transformed_rect(prect):
63
+ angle = prect.get('rot_angle',0)
64
+ r_origin = list(transform_rot(prect['x'],prect['y'],angle))
65
+ return Rectangle(r_origin, prect['width'], prect['height'], angle=angle)
66
+
67
+ def make_matplotrects(prects):
68
+ mprects = [transformed_rect(prect) for prect in prects]
69
+ return mprects
70
+
71
+ def plot_rects(ax,matplotrects,alpha=1.0):
72
+ # Create patch collection with specified colour/alpha
73
+ pc = PatchCollection(matplotrects, facecolor='r', alpha=alpha,
74
+ edgecolor='black',linewidth=1.0)
75
+
76
+ # Add collection to axes
77
+ ax.add_collection(pc,autolim=True)
78
+
79
+ # try to fix axes limits
80
+ # this does not seem to work as unticipated
81
+ # fine to ignore for now (because it does nothing)...
82
+ ax._unstale_viewLim()
83
+ datalim = pc.get_datalim(ax.transData)
84
+ print(datalim.get_points())
85
+ points = datalim.get_points()
86
+ if not np.isinf(datalim.minpos).all():
87
+ # By definition, if minpos (minimum positive value) is set
88
+ # (i.e., non-inf), then min(points) <= minpos <= max(points),
89
+ # and minpos would be superfluous. However, we add minpos to
90
+ # the call so that self.dataLim will update its own minpos.
91
+ # This ensures that log scales see the correct minimum.
92
+ points = np.concatenate([points, [datalim.minpos]])
93
+ ax.update_datalim(points)
94
+ return points
95
+
96
+ # function to scale everything to be accurate in nm
97
+ # below we assume that rectangles should be 27 nm x 27 nm
98
+ def scale(prect,factor):
99
+ srect = prect.copy()
100
+ for key in ['width', 'height', 'x', 'y']:
101
+ srect[key] = prect[key]*factor
102
+ return srect
103
+
104
+ # code to get label points from scaled prect
105
+ def points_from_sprect(sprect,mode='default'):
106
+ angle = sprect.get('rot_angle',0)
107
+ origin = transform_rot(sprect['x'],sprect['y'],angle)
108
+ if mode == 'default':
109
+ corner_points = np.array([[3.5,3.5], [23.5,3.5], [23.5, 23.5], [3.5, 23.5]]) # anti-clock wise
110
+ elif mode == 'RyR-T1366':
111
+ corner_points = np.array([[6,5], [21.6,6.6], [20.2,22.5], [4.8,20.5]])
112
+ elif mode == 'RyR-T2023':
113
+ corner_points = np.array([[4.6,12.0], [15.5,4.8], [22.5,15.2], [11.9,22.5]])
114
+ elif mode == 'RyR-D4365':
115
+ corner_points = np.array([[2,13.2],[13.9,2.2],[25.3,14.0],[13.3,25.2]])
116
+
117
+ else:
118
+ raise RuntimeError('unknow RyR corner mode %s requested' % (mode))
119
+ # first rotate corner points
120
+ R = rmat_ang(sprect.get('rot_angle',0))
121
+ cpsr = corner_points[:,None,:].dot(R).squeeze()
122
+ # now shift corner points to the origin of this rect
123
+ scpsr = cpsr + origin[None,:]
124
+ return scpsr
125
+
126
+ # functions to pick points and rotate point sets for generating clusters etc
127
+
128
+ from numpy.random import default_rng
129
+ rng = default_rng()
130
+
131
+ def random_pick(size,p):
132
+ return rng.random(size) < p
133
+
134
+ def rotpts(pts,angle):
135
+ rotpts = []
136
+ for ptnum in range(pts.shape[0]):
137
+ rx,ry = transform_rot(pts[ptnum,0],pts[ptnum,1],angle)
138
+ rotpts.append([rx,ry])
139
+ return np.array(rotpts)
140
+
141
+ def ctrorigin(pts):
142
+ mxy = pts.mean(axis=0)
143
+ return pts - mxy[None,:]
144
+
145
+ def shftpts(pts,x,y):
146
+ return pts + np.array([x,y])[None,:]
147
+
148
+ def pickpts(pts,prob):
149
+ picked = random_pick(pts.shape[0],prob)
150
+
151
+ return pts[picked,:]
152
+
153
+ def mergeClusterlist(clist):
154
+ clusters = clist[0].copy()
155
+ for c in clist[1:]:
156
+ clusters = np.append(clusters,c,axis = 0)
157
+ return clusters
158
+
159
+ import pandas as pd
160
+ def pts2df(pts):
161
+ pymedct = {'x' : pts[:,0], 'y' : pts[:,1], 'z' : np.zeros((pts.shape[0])), 't' : np.ones((pts.shape[0]))}
162
+ pymedf = pd.DataFrame.from_dict(pymedct)
163
+ return pymedf
164
+
165
+ def pymedf_add_err(pymedf,locerr=2.0): # error in nm
166
+ errdf = pymedf.copy()
167
+ nrows = errdf.shape[0]
168
+ errdf['x'] += locerr*np.random.normal(size=nrows)
169
+ errdf['y'] += locerr*np.random.normal(size=nrows)
170
+ errdf['z'] += locerr*np.random.normal(size=nrows)
171
+ errdf['error_x'] = locerr*np.ones((nrows))
172
+ errdf['error_y'] = locerr*np.ones((nrows))
173
+ errdf['error_z'] = locerr*np.ones((nrows))
174
+
175
+ return errdf
176
+
177
+ def datasourcePick2df(ds,prob):
178
+ picked = random_pick(ds['x'].size,prob)
179
+ pymedct = {}
180
+ for key in ['x','y','z','error_x','error_y','error_z','t']:
181
+ pymedct[key] = ds[key][picked]
182
+ return pd.DataFrame.from_dict(pymedct)