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,338 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from scipy import signal
|
|
3
|
+
from scipy import stats
|
|
4
|
+
import wx
|
|
5
|
+
from PYMEcs.pyme_warnings import warn
|
|
6
|
+
|
|
7
|
+
##################
|
|
8
|
+
# FRC.py
|
|
9
|
+
#
|
|
10
|
+
# Copyright Christian Soeller, 2018
|
|
11
|
+
# c.soeller@gmail.com
|
|
12
|
+
#
|
|
13
|
+
# This program is free software: you can redistribute it and/or modify
|
|
14
|
+
# it under the terms of the GNU General Public License as published by
|
|
15
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
16
|
+
# (at your option) any later version.
|
|
17
|
+
#
|
|
18
|
+
# This program is distributed in the hope that it will be useful,
|
|
19
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
20
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
21
|
+
# GNU General Public License for more details.
|
|
22
|
+
#
|
|
23
|
+
# You should have received a copy of the GNU General Public License
|
|
24
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
25
|
+
#
|
|
26
|
+
##################
|
|
27
|
+
|
|
28
|
+
# in this implementation we follow the principles as coded in the Fiji FRC plugin coded by Alex Herbert
|
|
29
|
+
# the source code is at https://c4science.ch/source/ijp-frc/browse/master/src/main/java/ch/epfl/biop/frc/FRC.java
|
|
30
|
+
# it was crucial to have some implementation to look at since not all details of the FRC approach are made
|
|
31
|
+
# clear in the FRC papers, for example that the real part of F(i0)*conj(F(i1)) is being used (although it turns out
|
|
32
|
+
# that F(i0)*conj(F(i1)) should be real given the symmetry of the Fourier Transform of real valued function)
|
|
33
|
+
|
|
34
|
+
# also the use of a tukey window is reproduced (described already in the
|
|
35
|
+
# Nieuwenhuizen et al 2013 paper)
|
|
36
|
+
|
|
37
|
+
# the half-bit line formula was copied although
|
|
38
|
+
# it would be nice to figure out how the constants where arrived at
|
|
39
|
+
# Note there is some formula in the Nat Meth paper supplementary by
|
|
40
|
+
# Nieuwenhuizen et al 2013, but that is more general and we need to
|
|
41
|
+
# figure out if this one is a version of the general formula with
|
|
42
|
+
# specific parameter settings
|
|
43
|
+
|
|
44
|
+
def sigmaline(L):
|
|
45
|
+
thresh = (0.2071 * np.sqrt(L) + 1.9102) / (1.2071 * np.sqrt(L) + 0.9102)
|
|
46
|
+
return np.minimum(thresh,1)
|
|
47
|
+
|
|
48
|
+
def tukey2d(shape,fraction=0.5):
|
|
49
|
+
try:
|
|
50
|
+
from scipy.signal import tukey
|
|
51
|
+
except ImportError:
|
|
52
|
+
from scipy.signal.windows import tukey # from some version onwards only available from the scipy.signal.windows namespace
|
|
53
|
+
|
|
54
|
+
tx = tukey(shape[0],fraction)
|
|
55
|
+
ty = tukey(shape[1],fraction)
|
|
56
|
+
|
|
57
|
+
#tY, tX = np.meshgrid(ty,tx)
|
|
58
|
+
#return tY*tX
|
|
59
|
+
|
|
60
|
+
return np.outer(tx,ty)
|
|
61
|
+
|
|
62
|
+
def spectrum_mean_over_R(pspec,vszx,vszy,binwidth=None, debug = False):
|
|
63
|
+
|
|
64
|
+
# get size N and M of x and y dims
|
|
65
|
+
N, M = pspec.shape[0:2]
|
|
66
|
+
|
|
67
|
+
# set up spatial frequency coordinates in x and y [make sure we get the sequence of the two axes right]
|
|
68
|
+
# put on meshgrid and get muR from this
|
|
69
|
+
mux = (np.arange(N) - N/2)/float(N*vszx)
|
|
70
|
+
muy = (np.arange(M) - M/2)/float(M*vszy)
|
|
71
|
+
|
|
72
|
+
muY, muX = np.meshgrid(muy,mux)
|
|
73
|
+
|
|
74
|
+
if debug:
|
|
75
|
+
print(N,M)
|
|
76
|
+
print(muX.shape)
|
|
77
|
+
|
|
78
|
+
muR = np.sqrt(muX*muX+muY*muY)
|
|
79
|
+
|
|
80
|
+
# calculate bins using the specified binwidth (with suitable default)
|
|
81
|
+
# note that it makes sense to specify binwidth in multiples of dmu
|
|
82
|
+
# with minimum of 1*dmu (i.e. min of allowed binwidth is 1)
|
|
83
|
+
K = min(N,M)
|
|
84
|
+
mumult = max(int(binwidth),1)
|
|
85
|
+
bins = mumult*np.arange(K/2/mumult)/float(K*vszx) # there would be an issue if vszx ne vszy
|
|
86
|
+
|
|
87
|
+
# calculate binned_statistics over spectrum
|
|
88
|
+
# the spectrum must be realvalued, either powerspec or real/imaginary part
|
|
89
|
+
means, binedges, bnum = stats.binned_statistic(muR.ravel(),pspec.ravel(),statistic='sum', bins=bins)
|
|
90
|
+
# return bincenters and means for each bin
|
|
91
|
+
binctrs = 0.5*(binedges[1:]+binedges[:-1])
|
|
92
|
+
return (binctrs,means)
|
|
93
|
+
|
|
94
|
+
import statsmodels.api as sm
|
|
95
|
+
lowess = sm.nonparametric.lowess
|
|
96
|
+
|
|
97
|
+
def padsquare(image,newsize=None):
|
|
98
|
+
N, M = image.shape[0:2]
|
|
99
|
+
if newsize is None:
|
|
100
|
+
newsize = max(N,M)
|
|
101
|
+
K = newsize # less typing
|
|
102
|
+
|
|
103
|
+
if N != newsize or M != newsize:
|
|
104
|
+
if N>newsize or M>newsize:
|
|
105
|
+
raise RuntimeError('trying to embed image (%d,%d) into smaller container (%d,%d)' % (N,M,newsize,newsize))
|
|
106
|
+
|
|
107
|
+
newim = np.zeros((K,K))
|
|
108
|
+
# note that these divisions need to be integer divisons as we do index arithmetic
|
|
109
|
+
startn = (K-N) // 2
|
|
110
|
+
startm = (K-M) // 2
|
|
111
|
+
newim[startn:startn+N,startm:startm+M] = image
|
|
112
|
+
return newim
|
|
113
|
+
else:
|
|
114
|
+
return image
|
|
115
|
+
|
|
116
|
+
def frc(i0,i1,vszx,vszy,muwidth = 2, zeropad = False, lowessFraction = 1/20.0):
|
|
117
|
+
|
|
118
|
+
t2d = tukey2d(i0.shape,0.25)
|
|
119
|
+
|
|
120
|
+
if zeropad:
|
|
121
|
+
im0 = padsquare(i0*t2d)
|
|
122
|
+
im1 = padsquare(i1*t2d)
|
|
123
|
+
else:
|
|
124
|
+
im0 = i0*t2d
|
|
125
|
+
im1 = i1*t2d
|
|
126
|
+
|
|
127
|
+
I0 = np.fft.fftshift(np.fft.fftn(im0))
|
|
128
|
+
I1 = np.fft.fftshift(np.fft.fftn(im1))
|
|
129
|
+
|
|
130
|
+
CC = np.real(I0 * np.conj(I1))
|
|
131
|
+
PS0 = np.abs(I0)**2
|
|
132
|
+
PS1 = np.abs(I1)**2
|
|
133
|
+
|
|
134
|
+
bcc, mcc = spectrum_mean_over_R(CC,vszx,vszy,binwidth=muwidth)
|
|
135
|
+
b0, mi0 = spectrum_mean_over_R(PS0,vszx,vszy,binwidth=muwidth)
|
|
136
|
+
b1, mi1 = spectrum_mean_over_R(PS1,vszx,vszy,binwidth=muwidth)
|
|
137
|
+
# count the number of pixels contributing to each ring
|
|
138
|
+
b2, L = spectrum_mean_over_R(np.ones(PS1.shape),vszx,vszy,binwidth=muwidth)
|
|
139
|
+
|
|
140
|
+
# in principle should check that bcc, b0, b1 have the same bin locations
|
|
141
|
+
frcv = mcc/np.sqrt(mi0*mi1)
|
|
142
|
+
|
|
143
|
+
smoothed = lowess(frcv, bcc, frac=lowessFraction, it=3, delta=0.0,
|
|
144
|
+
is_sorted=False, missing='drop', return_sorted=False)
|
|
145
|
+
|
|
146
|
+
return (bcc,frcv,smoothed,L)
|
|
147
|
+
|
|
148
|
+
def frc_from_image(image,channels,muwidth=2,zeropad=True,lowessFraction=5.0*0.01):
|
|
149
|
+
im0 = image.data_xytc[:,:,:,channels[0]].squeeze()
|
|
150
|
+
im1 = image.data_xytc[:,:,:,channels[1]].squeeze()
|
|
151
|
+
|
|
152
|
+
mdh = image.mdh
|
|
153
|
+
vx = 1e3*mdh['voxelsize.x']
|
|
154
|
+
vy = 1e3*mdh['voxelsize.y']
|
|
155
|
+
freqs,frc1,smoothed,L = frc(im0,im1,vx,vy,muwidth=2,zeropad=True,
|
|
156
|
+
lowessFraction=lowessFraction)
|
|
157
|
+
halfbit = sigmaline(L)
|
|
158
|
+
fhb = zc.zerocross1d(freqs,smoothed-halfbit)
|
|
159
|
+
f7= zc.zerocross1d(freqs,smoothed-1.0/7.0)
|
|
160
|
+
|
|
161
|
+
return (freqs,frc1,smoothed,fhb,f7,halfbit)
|
|
162
|
+
|
|
163
|
+
def frc_plot(freqs,frc1,smoothed,fhb,f7,halfbit,chanNames=['block0','block1'],
|
|
164
|
+
showGrid=True,showHalfbitThreshold=False):
|
|
165
|
+
import matplotlib.pyplot as plt
|
|
166
|
+
|
|
167
|
+
from mpl_toolkits.axes_grid1 import host_subplot
|
|
168
|
+
import mpl_toolkits.axisartist as AA
|
|
169
|
+
|
|
170
|
+
plt.figure()
|
|
171
|
+
ax = host_subplot(111, axes_class=AA.Axes)
|
|
172
|
+
ax.plot(freqs,frc1)
|
|
173
|
+
ax.plot(freqs,smoothed)
|
|
174
|
+
if showHalfbitThreshold:
|
|
175
|
+
ax.plot(freqs,halfbit)
|
|
176
|
+
ax.plot(freqs,1/7.0*np.ones(freqs.shape))
|
|
177
|
+
|
|
178
|
+
if len(f7) > 0:
|
|
179
|
+
ax.plot([f7[0],f7[0]],[0,1],'--')
|
|
180
|
+
ax.text(0.55, 0.8,'res-1/7 = %3.1f nm' % (1.0/f7[0]),horizontalalignment='left',
|
|
181
|
+
verticalalignment='center', transform=plt.gca().transAxes)
|
|
182
|
+
else:
|
|
183
|
+
ax.text(0.55, 0.8,'res-1/7 - no intercept',horizontalalignment='left',
|
|
184
|
+
verticalalignment='center', transform=plt.gca().transAxes)
|
|
185
|
+
|
|
186
|
+
if showHalfbitThreshold:
|
|
187
|
+
if len(fhb) > 0:
|
|
188
|
+
ax.plot([fhb[0],fhb[0]],[0,1],'--')
|
|
189
|
+
ax.text(0.55, 0.9,'res-halfbit = %3.1f nm' % (1.0/fhb[0]),horizontalalignment='left',
|
|
190
|
+
verticalalignment='center', transform=plt.gca().transAxes)
|
|
191
|
+
else:
|
|
192
|
+
ax.text(0.55, 0.9,'res-halfbit - no intercept',horizontalalignment='left',
|
|
193
|
+
verticalalignment='center', transform=plt.gca().transAxes)
|
|
194
|
+
|
|
195
|
+
ax.plot(freqs,np.zeros(freqs.shape),'--')
|
|
196
|
+
ax.set_xlim(0,freqs[-1])
|
|
197
|
+
ax.set_xlabel('spatial frequency (nm^-1)')
|
|
198
|
+
ax.set_ylabel('FRC values')
|
|
199
|
+
xt = np.array([10., 15, 20, 30, 40, 50, 75, 150])
|
|
200
|
+
ft = 1.0 / xt
|
|
201
|
+
|
|
202
|
+
ax2 = ax.twin() # ax2 is responsible for "top" axis and "right" axis
|
|
203
|
+
ax2.set_xticks(ft[::-1])
|
|
204
|
+
ax2.set_xticklabels(['%d' % xi for xi in xt[::-1]],rotation=90)
|
|
205
|
+
ax2.set_xlabel('resolution (nm)')
|
|
206
|
+
if showGrid:
|
|
207
|
+
ax2.grid(True)
|
|
208
|
+
|
|
209
|
+
ax2.axis["right"].major_ticklabels.set_visible(False)
|
|
210
|
+
ax2.axis["top"].major_ticklabels.set_visible(True)
|
|
211
|
+
|
|
212
|
+
plt.title("FRC for channels %s and %s" % (chanNames[0],chanNames[1]), y=1.08)
|
|
213
|
+
plt.show()
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def save_vol_mrc(data, grid_spacing, outfilename, origin=None, overwrite=False):
|
|
217
|
+
import mrcfile # will bomb unless this is installed
|
|
218
|
+
|
|
219
|
+
data = data.astype('float32')
|
|
220
|
+
with mrcfile.new(outfilename, overwrite=overwrite) as mrc:
|
|
221
|
+
mrc.set_data(data)
|
|
222
|
+
mrc.voxel_size = grid_spacing
|
|
223
|
+
if origin is not None:
|
|
224
|
+
mrc.header.origin = origin
|
|
225
|
+
mrc.update_header_from_data()
|
|
226
|
+
mrc.update_header_stats()
|
|
227
|
+
|
|
228
|
+
import PYMEcs.Analysis.zerocross as zc
|
|
229
|
+
from traits.api import HasTraits, Str, Int, CStr, List, Enum, Float, Bool
|
|
230
|
+
|
|
231
|
+
class FRCsettings(HasTraits):
|
|
232
|
+
ZeroPadding = Bool(True)
|
|
233
|
+
ShowHalfbitThreshold = Bool(False)
|
|
234
|
+
ShowGrid = Bool(True)
|
|
235
|
+
LowessSmoothingPercentage = Float(5.0)
|
|
236
|
+
|
|
237
|
+
class FRCplotter:
|
|
238
|
+
def __init__(self, dsviewer):
|
|
239
|
+
self.dsviewer = dsviewer
|
|
240
|
+
dsviewer.AddMenuItem('Experimental>Analysis', 'FRC of image pair', self.OnFRC)
|
|
241
|
+
dsviewer.AddMenuItem('Experimental>Analysis', 'save last FRC curves', self.OnFRCSave)
|
|
242
|
+
dsviewer.AddMenuItem('Experimental>Analysis', 'adjust FRC settings', self.OnFRCSettings)
|
|
243
|
+
dsviewer.AddMenuItem('Experimental>Analysis', 'save MRC volumes for FSC', self.OnFSCsave_as_MRC)
|
|
244
|
+
|
|
245
|
+
self.frcSettings = FRCsettings()
|
|
246
|
+
self.lastFRC = None
|
|
247
|
+
|
|
248
|
+
def OnFRCSettings(self, event=None):
|
|
249
|
+
if self.frcSettings.configure_traits(kind='modal'):
|
|
250
|
+
pass
|
|
251
|
+
|
|
252
|
+
def OnFRC(self, event=None):
|
|
253
|
+
from PYME.DSView.modules.coloc import ColocSettingsDialog
|
|
254
|
+
image = self.dsviewer.image
|
|
255
|
+
voxelsize = image.voxelsize
|
|
256
|
+
|
|
257
|
+
try:
|
|
258
|
+
names = image.mdh.getEntry('ChannelNames')
|
|
259
|
+
except:
|
|
260
|
+
names = ['Channel %d' % n for n in range(image.data_xytc.shape[3])]
|
|
261
|
+
|
|
262
|
+
with ColocSettingsDialog(self.dsviewer, voxelsize[0], names, show_bins=False) as dlg:
|
|
263
|
+
if dlg.ShowModal() != wx.ID_OK:
|
|
264
|
+
return
|
|
265
|
+
chans = dlg.GetChans()
|
|
266
|
+
|
|
267
|
+
chanNames = [names[chans[0]],names[chans[1]]]
|
|
268
|
+
|
|
269
|
+
freqs,frc1,smoothed,fhb,f7,halfbit = frc_from_image(image,chans,muwidth=2,
|
|
270
|
+
zeropad=self.frcSettings.ZeroPadding,
|
|
271
|
+
lowessFraction=self.frcSettings.LowessSmoothingPercentage*0.01)
|
|
272
|
+
frc_plot(freqs,frc1,smoothed,fhb,f7,halfbit,chanNames,
|
|
273
|
+
showHalfbitThreshold=self.frcSettings.ShowHalfbitThreshold,
|
|
274
|
+
showGrid=self.frcSettings.ShowGrid)
|
|
275
|
+
|
|
276
|
+
self.lastFRC = dict(frequencies=freqs,frc_curve=frc1,frc_smoothed=smoothed,frchbval=fhb,frcval=f7,frc_halfbit=halfbit)
|
|
277
|
+
|
|
278
|
+
def OnFRCSave(self, event=None):
|
|
279
|
+
if self.lastFRC is None:
|
|
280
|
+
warn("could not find data from prior FRC Plot; cannot scave, please plot first")
|
|
281
|
+
return
|
|
282
|
+
with wx.FileDialog(self.dsviewer, 'Save FRC data as ...',
|
|
283
|
+
wildcard='CSV (*.csv)|*.csv',
|
|
284
|
+
style=wx.FD_SAVE) as fdialog:
|
|
285
|
+
if fdialog.ShowModal() != wx.ID_OK:
|
|
286
|
+
return
|
|
287
|
+
else:
|
|
288
|
+
fpath = fdialog.GetPath()
|
|
289
|
+
|
|
290
|
+
lfrc = self.lastFRC
|
|
291
|
+
import pandas as pd
|
|
292
|
+
df = pd.DataFrame.from_dict(dict(freqs=lfrc['frequencies'],frc=lfrc['frc_curve'],frcsmooth=lfrc['frc_smoothed']))
|
|
293
|
+
df.to_csv(fpath,index=False)
|
|
294
|
+
|
|
295
|
+
def OnFSCsave_as_MRC(self, event=None):
|
|
296
|
+
from PYME.DSView.modules.coloc import ColocSettingsDialog
|
|
297
|
+
im = self.dsviewer.image
|
|
298
|
+
try:
|
|
299
|
+
names = im.mdh.getEntry('ChannelNames')
|
|
300
|
+
except:
|
|
301
|
+
names = ['Channel %d' % n for n in range(im.data_xyztc.shape[4])]
|
|
302
|
+
|
|
303
|
+
with ColocSettingsDialog(self.dsviewer, im.mdh.voxelsize.x, names, show_bins=False) as dlg:
|
|
304
|
+
if dlg.ShowModal() != wx.ID_OK:
|
|
305
|
+
return
|
|
306
|
+
chans = dlg.GetChans()
|
|
307
|
+
|
|
308
|
+
chanNames = [names[chans[0]],names[chans[1]]]
|
|
309
|
+
|
|
310
|
+
vol1 = im.data_xyztc[:,:,:,0,chans[0]].squeeze()
|
|
311
|
+
vol2 = im.data_xyztc[:,:,:,0,chans[1]].squeeze()
|
|
312
|
+
|
|
313
|
+
MINFLUXts = im.mdh.get('Source.MINFLUX.TimeStamp')
|
|
314
|
+
if MINFLUXts is not None:
|
|
315
|
+
defaultFiles = ["%s-%s.mrc" % (MINFLUXts,names[chans[0]]),
|
|
316
|
+
"%s-%s.mrc" % (MINFLUXts,names[chans[1]])]
|
|
317
|
+
else:
|
|
318
|
+
defaultFiles = ['','']
|
|
319
|
+
|
|
320
|
+
for i,vol in enumerate([vol1,vol2]):
|
|
321
|
+
with wx.FileDialog(self.dsviewer, 'Save channel %d as ...' % i,
|
|
322
|
+
wildcard='MRC (*.mrc)|*.mrc',
|
|
323
|
+
defaultFile=defaultFiles[i],
|
|
324
|
+
style=wx.FD_SAVE) as fdialog:
|
|
325
|
+
if fdialog.ShowModal() != wx.ID_OK:
|
|
326
|
+
return
|
|
327
|
+
fpath = fdialog.GetPath()
|
|
328
|
+
save_vol_mrc(vol.T,im.mdh.voxelsize_nm.x,fpath)
|
|
329
|
+
|
|
330
|
+
# we also write a JSON file of the metadata so that we can be sure about voxelsizes etc
|
|
331
|
+
# currently just the stem of the second MRC file name with json extension
|
|
332
|
+
from pathlib import Path
|
|
333
|
+
p = Path(fpath)
|
|
334
|
+
p.with_suffix('.json').write_text(im.mdh.to_JSON())
|
|
335
|
+
|
|
336
|
+
def Plug(dsviewer):
|
|
337
|
+
"""Plugs this module into the gui"""
|
|
338
|
+
dsviewer.frcplt = FRCplotter(dsviewer)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
logger = logging.getLogger(__file__)
|
|
3
|
+
import wx
|
|
4
|
+
import numpy as np
|
|
5
|
+
import roifile as rf # new dependency on roifile (available from pypi)
|
|
6
|
+
import skimage as ski
|
|
7
|
+
|
|
8
|
+
from PYME.DSView import ViewIm3D
|
|
9
|
+
from PYME.IO.image import ImageStack
|
|
10
|
+
|
|
11
|
+
class ImageJROItools:
|
|
12
|
+
|
|
13
|
+
def __init__(self, dsviewer):
|
|
14
|
+
self.dsviewer = dsviewer
|
|
15
|
+
dsviewer.AddMenuItem('Experimental>ROIs',
|
|
16
|
+
'Generate ROI mask from Fiji ROISet',
|
|
17
|
+
self.OnROISet,
|
|
18
|
+
helpText='Load at FIJI ROISet (e.g. ROISet.zip) and construct a ROI mask from it')
|
|
19
|
+
|
|
20
|
+
def OnROISet(self, event=None):
|
|
21
|
+
roi_filename = wx.FileSelector('Load ROI set...',
|
|
22
|
+
wildcard="ROISet files (*.zip)|*.zip|ROI files (*.roi)|*.roi",
|
|
23
|
+
flags = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
|
|
24
|
+
rois = rf.ImagejRoi.fromfile(roi_filename)
|
|
25
|
+
roimask = np.zeros(self.dsviewer.image.data_xytc.shape[0:2],dtype='int')
|
|
26
|
+
roiszx,roiszy = roimask.shape
|
|
27
|
+
counter = 1
|
|
28
|
+
for roi in rois:
|
|
29
|
+
if roi.roitype in [rf.ROI_TYPE.RECT,
|
|
30
|
+
rf.ROI_TYPE.OVAL,
|
|
31
|
+
rf.ROI_TYPE.POLYGON,
|
|
32
|
+
rf.ROI_TYPE.FREEHAND]: # this needs to be relaxed pretty soonish!
|
|
33
|
+
coords = np.round(roi.coordinates()).astype('int')
|
|
34
|
+
r = coords[:,0]
|
|
35
|
+
c = coords[:,1]
|
|
36
|
+
rr, cc = ski.draw.polygon(r, c)
|
|
37
|
+
roimask[np.clip(cc,0,roiszx-1),np.clip(rr,0,roiszy-1)] = counter
|
|
38
|
+
counter += 1
|
|
39
|
+
ROImaskImg = ImageStack(roimask, titleStub = 'ROI region mask')
|
|
40
|
+
ROImaskImg.mdh.copyEntriesFrom(self.dsviewer.image.mdh)
|
|
41
|
+
# add entries for the mask
|
|
42
|
+
ROImaskImg.mdh['ROISet'] = roi_filename
|
|
43
|
+
|
|
44
|
+
ViewIm3D(ROImaskImg, mode='visGUI', title='ROI mask',
|
|
45
|
+
glCanvas=self.dsviewer.glCanvas, parent=self.dsviewer)
|
|
46
|
+
|
|
47
|
+
def Plug(dsviewer):
|
|
48
|
+
"""Plugs this module into the gui"""
|
|
49
|
+
ImageJROItools(dsviewer)
|