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
PYMEcs/IO/NPC.py
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
from PYMEcs.pyme_warnings import warn
|
|
2
|
+
import pickle
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
import logging
|
|
5
|
+
|
|
6
|
+
logger = logging.getLogger(__name__)
|
|
7
|
+
|
|
8
|
+
def load_NPC_set(fname, ts=None, foreshortening=None, version=None):
|
|
9
|
+
with open(fname,'rb') as fi:
|
|
10
|
+
npcs=pickle.load(fi)
|
|
11
|
+
fpath = Path(fname)
|
|
12
|
+
if ts is not None and ts not in fpath.stem:
|
|
13
|
+
warn("MINFLUX time stamp not in NPC dataset filename; check correct filename chosen: %s vs %s" %
|
|
14
|
+
(ts,fpath.stem))
|
|
15
|
+
|
|
16
|
+
if foreshortening is not None:
|
|
17
|
+
try:
|
|
18
|
+
npc_foreshortening = npcs.foreshortening
|
|
19
|
+
except AttributeError:
|
|
20
|
+
npc_foreshortening = 1.0
|
|
21
|
+
|
|
22
|
+
if abs(npc_foreshortening-foreshortening) >= 0.01:
|
|
23
|
+
warn("NPC foreshortening is %.2f while dataset foreshortening is %.2f, check this is compatible" %
|
|
24
|
+
(npc_foreshortening,foreshortening))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
if version is not None:
|
|
28
|
+
pass # here add version checking logic
|
|
29
|
+
|
|
30
|
+
return npcs
|
|
31
|
+
|
|
32
|
+
def save_NPC_set(npcs,fname):
|
|
33
|
+
with open(fname, "wb") as file:
|
|
34
|
+
pickle.dump(npcs,file)
|
|
35
|
+
|
|
36
|
+
def findNPCset(pipeline,return_mod=False,warnings=True):
|
|
37
|
+
from PYMEcs.recipes.localisations import NPCAnalysisInput
|
|
38
|
+
# note a "manually" created or loaded NPCset in pipeline.npcs attribute takes precedence over loaded via NPCAnalysisInput module
|
|
39
|
+
if pipeline is not None and 'npcs' in dir(pipeline) and pipeline.npcs is not None and not return_mod:
|
|
40
|
+
return pipeline.npcs
|
|
41
|
+
if pipeline is None:
|
|
42
|
+
return None
|
|
43
|
+
dsname = None
|
|
44
|
+
hideNPC = False
|
|
45
|
+
# search/check for instance
|
|
46
|
+
for mod in pipeline.recipe.modules:
|
|
47
|
+
if isinstance(mod,NPCAnalysisInput):
|
|
48
|
+
dsname = mod.output
|
|
49
|
+
hideNPC = mod.NPC_hide
|
|
50
|
+
module = mod
|
|
51
|
+
break
|
|
52
|
+
if hideNPC: # the module is deliberately hiding the NPCset associated with it
|
|
53
|
+
if warnings:
|
|
54
|
+
warn("NPCset has been marked as hidden in NPCAnalysisInput output, assuming this is deliberate")
|
|
55
|
+
return None
|
|
56
|
+
if dsname is None:
|
|
57
|
+
if warnings:
|
|
58
|
+
warn("we rely on npc analysis being present in a datasource generated by the NPCAnalysisInput module. Can't find such a datasource, aborting...")
|
|
59
|
+
return None
|
|
60
|
+
logger.debug("found NPCAnalysisInput module")
|
|
61
|
+
if return_mod:
|
|
62
|
+
return module
|
|
63
|
+
npc_set_container = pipeline.dataSources[dsname].mdh.get('Processing.NPCAnalysisInput.npcs_filtered')
|
|
64
|
+
if not mod.filter_npcs or npc_set_container is None: # if not filtering or no filtered set available try the unfiltered npc set
|
|
65
|
+
npc_set_container = pipeline.dataSources[dsname].mdh.get('Processing.NPCAnalysisInput.npcs')
|
|
66
|
+
logger.debug("trying to retrieve unfiltered NPCSet")
|
|
67
|
+
else:
|
|
68
|
+
logger.debug("found filtered NPCSet")
|
|
69
|
+
if npc_set_container is None: # we get here if there is still no npc set available
|
|
70
|
+
# this warning cannot be masked as this case should not happen unless something is broken (either bug or not used as intended)
|
|
71
|
+
warn(("found no NPCset container in metadata of datasource '%s' generated by NPCAnalysisInput module.\n\n" % dsname)
|
|
72
|
+
+ "Did you already load a pickled NPC analysis file with the module?\n\naborting..." )
|
|
73
|
+
return None
|
|
74
|
+
|
|
75
|
+
return npc_set_container.get_npcset()
|
|
76
|
+
|
|
77
|
+
from packaging.version import Version # this allows us to do simpler comparisons
|
|
78
|
+
def check_npcset_version(npcset,target_version,mode='minimum version'):
|
|
79
|
+
version = None
|
|
80
|
+
try:
|
|
81
|
+
version = npcset.version()
|
|
82
|
+
except AttributeError:
|
|
83
|
+
pass
|
|
84
|
+
if version is None: # older version, use some heuristics
|
|
85
|
+
if 'n_bysegments' not in dir (npcset):
|
|
86
|
+
version = Version('0.1')
|
|
87
|
+
elif npcset.n_bysegments() is None: # this can also happen with newer version when not yet fitted, but then we should not have loaded this as a saved object
|
|
88
|
+
version = Version('0.1')
|
|
89
|
+
else:
|
|
90
|
+
version = Version('0.9')
|
|
91
|
+
|
|
92
|
+
if mode == 'return_version':
|
|
93
|
+
return version
|
|
94
|
+
|
|
95
|
+
if not isinstance(version,Version):
|
|
96
|
+
try:
|
|
97
|
+
version = Version(version)
|
|
98
|
+
except:
|
|
99
|
+
warn("cannot convert version expression '%s' to Version object, giving up and returning True, perhaps tell CS" % version)
|
|
100
|
+
return True
|
|
101
|
+
|
|
102
|
+
if not isinstance(target_version,Version):
|
|
103
|
+
try:
|
|
104
|
+
target_version = Version(target_version)
|
|
105
|
+
except:
|
|
106
|
+
warn("cannot convert version expression '%s' to Version object, giving up and returning True, perhaps tell CS" % target_version)
|
|
107
|
+
return True
|
|
108
|
+
|
|
109
|
+
if mode == 'minimum version':
|
|
110
|
+
return version >= target_version
|
|
111
|
+
elif mode == 'exact version':
|
|
112
|
+
return version == target_version
|
|
113
|
+
else: # we have checked for mode return_version above, so should be ok by not testing here
|
|
114
|
+
raise RuntimeError("unknown mode %s requested" % (mode))
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
|
PYMEcs/IO/__init__.py
ADDED
|
File without changes
|
PYMEcs/IO/darkTimes.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import csv
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
def saveDarkTimesCSV(objectIDs,dts,filename):
|
|
5
|
+
with open( filename, 'w') as outfile:
|
|
6
|
+
writer = csv.writer( outfile )
|
|
7
|
+
for id, darktimes in zip(objectIDs,dts):
|
|
8
|
+
writer.writerow([id]+darktimes.tolist())
|
|
9
|
+
|
|
10
|
+
def readDarkTimesCSV(filename):
|
|
11
|
+
with open( filename, 'r') as infile:
|
|
12
|
+
reader = csv.reader( infile )
|
|
13
|
+
objectIDs = []
|
|
14
|
+
dts = []
|
|
15
|
+
for row in reader:
|
|
16
|
+
objectIDs.append(int(row[0]))
|
|
17
|
+
dt = np.array(row[1:],dtype='f')
|
|
18
|
+
dts.append(dt)
|
|
19
|
+
return (objectIDs,dts)
|
PYMEcs/IO/picasso.py
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pandas as pd
|
|
3
|
+
import yaml
|
|
4
|
+
import math
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
def picasso2pyme(locs,mdh):
|
|
8
|
+
try:
|
|
9
|
+
nmperpix = mdh['Camera.Pixelsize']
|
|
10
|
+
except KeyError:
|
|
11
|
+
nmperpix = mdh['Pixelsize']
|
|
12
|
+
|
|
13
|
+
pyme = {}
|
|
14
|
+
pyme['x'] = locs['x']*nmperpix
|
|
15
|
+
pyme['y'] = locs['y']*nmperpix
|
|
16
|
+
pyme['sig'] = locs['sx']*nmperpix
|
|
17
|
+
pyme['nPhotons'] = locs['photons']
|
|
18
|
+
pyme['error_x'] = locs['lpx']*nmperpix
|
|
19
|
+
pyme['error_y'] = locs['lpy']*nmperpix
|
|
20
|
+
pyme['t'] = locs['frame']
|
|
21
|
+
pyme['A'] = locs['photons']/(2*math.pi)/(locs['sx']**2) # this is from the PYME kinmodels formula - check
|
|
22
|
+
if 'z' in locs.keys():
|
|
23
|
+
pyme['z'] = locs['z'] # from astigmatoc data z should already be scaled to nm?
|
|
24
|
+
return pyme
|
|
25
|
+
|
|
26
|
+
def struc_from_mdh(mdh):
|
|
27
|
+
if mdh is None or 'Structure.HandleStruct' not in mdh.keys():
|
|
28
|
+
return None
|
|
29
|
+
struc = {}
|
|
30
|
+
nmperpix = float(mdh['Camera.Pixelsize'])
|
|
31
|
+
npixels = float(mdh['Camera.Image Size'])
|
|
32
|
+
for key in ('HandleStruct','HandleEx'):
|
|
33
|
+
struc[key] = np.array([float(i) for i in mdh["Structure.%s" % key].split(',')],dtype='i')
|
|
34
|
+
offshalfpix = 0.5 # half a pixel offset seems to be required (origin in middle of pixel?)
|
|
35
|
+
for key in ['HandleX']:
|
|
36
|
+
struc[key] = np.array([(float(i)-offshalfpix)*nmperpix for i in mdh["Structure.%s" % key].split(',')])
|
|
37
|
+
# for a reason not quite clear to me yet the Y coordinates need mirroring
|
|
38
|
+
for key in ['HandleY']:
|
|
39
|
+
struc[key] = np.array([(npixels-float(i)-offshalfpix)*nmperpix for i in mdh["Structure.%s" % key].split(',')])
|
|
40
|
+
return struc
|
|
41
|
+
|
|
42
|
+
def parse_dicts(dicts):
|
|
43
|
+
import re
|
|
44
|
+
mdh = None
|
|
45
|
+
strucmdh = None
|
|
46
|
+
for d in dicts:
|
|
47
|
+
if any (re.match('pixelsize',key,re.I) for key in d.keys()):
|
|
48
|
+
mdh = d
|
|
49
|
+
for d in dicts:
|
|
50
|
+
if any (re.match('Structure',key,re.I) for key in d.keys()):
|
|
51
|
+
strucmdh = d
|
|
52
|
+
return (mdh,strucmdh)
|
|
53
|
+
|
|
54
|
+
def read_picasso_hdf(name):
|
|
55
|
+
locs = pd.read_hdf(name,'locs')
|
|
56
|
+
basename, file_extension = os.path.splitext(name)
|
|
57
|
+
with open(basename+'.yaml') as file:
|
|
58
|
+
finf = list(yaml.load_all(file, Loader=yaml.FullLoader))
|
|
59
|
+
mdh, strucmdh = parse_dicts(finf)
|
|
60
|
+
pymedf = pd.DataFrame(picasso2pyme(locs,mdh))
|
|
61
|
+
struc = struc_from_mdh(strucmdh)
|
|
62
|
+
return pymedf, mdh, struc
|
|
63
|
+
|
|
64
|
+
def pymedf2csv(pymedf,filename):
|
|
65
|
+
cols = ['A','x','y','t','sig','error_x','error_y','nPhotons']
|
|
66
|
+
pymedf.to_csv(filename,columns=cols,index=False)
|
|
67
|
+
|
|
68
|
+
def pymedf2ds(pymedf):
|
|
69
|
+
from PYME.IO.tabular import DictSource
|
|
70
|
+
pymedict={}
|
|
71
|
+
for key in pymedf.keys():
|
|
72
|
+
pymedict[key] = pymedf[key].values
|
|
73
|
+
ds = DictSource(pymedict)
|
|
74
|
+
return ds
|
|
75
|
+
|
|
76
|
+
import skimage.morphology as morph
|
|
77
|
+
from PYME.IO.image import ImageStack
|
|
78
|
+
#from PYME.IO.MetaDataHandler import NestedClassMDHandler
|
|
79
|
+
|
|
80
|
+
def picasso_structure_mask(inputim,struc,dilations=2,
|
|
81
|
+
dilationselem=np.ones((5,5),dtype='float32')):
|
|
82
|
+
ox = inputim.mdh['Origin.x']
|
|
83
|
+
oy = inputim.mdh['Origin.y']
|
|
84
|
+
vxsz = 1e3*inputim.mdh['voxelsize.x']
|
|
85
|
+
|
|
86
|
+
mask0 = np.zeros(inputim.data.shape[0:2],dtype='float32')
|
|
87
|
+
labels = []
|
|
88
|
+
nsites = []
|
|
89
|
+
cxa = []
|
|
90
|
+
cya = []
|
|
91
|
+
|
|
92
|
+
for label in range(0,int(struc['HandleStruct'].max()+1)):
|
|
93
|
+
strucn = struc['HandleStruct'] == label
|
|
94
|
+
newim = np.zeros(inputim.data.shape[0:2],dtype='float32')
|
|
95
|
+
strucx = ((struc['HandleX'][strucn]) - ox) / vxsz
|
|
96
|
+
strucy = ((struc['HandleY'][strucn]) - oy) / vxsz
|
|
97
|
+
cx = struc['HandleX'][strucn].mean()
|
|
98
|
+
cy = struc['HandleY'][strucn].mean()
|
|
99
|
+
cxi = np.rint(strucx.mean()).astype('int') # integer centroid x
|
|
100
|
+
cyi = np.rint(strucy.mean()).astype('int') # integer centroid y
|
|
101
|
+
labels.append(label+1)
|
|
102
|
+
nsites.append(strucx.size)
|
|
103
|
+
cxa.append(cx)
|
|
104
|
+
cya.append(cy)
|
|
105
|
+
ind = (strucx < newim.shape[0])*(strucy < newim.shape[1])*(strucx >= 0)*(strucy >= 0)
|
|
106
|
+
if np.any(ind):
|
|
107
|
+
newim[strucx[ind].astype('i'),strucy[ind].astype('i')] = 1.0
|
|
108
|
+
newim2 = morph.convex_hull_image(newim)
|
|
109
|
+
for i in range(dilations):
|
|
110
|
+
newim2 = morph.binary_dilation(newim2,selem=dilationselem)
|
|
111
|
+
mask0[newim2 > 0.5] = label+1
|
|
112
|
+
|
|
113
|
+
sitesdf = pd.DataFrame(list(zip(labels, nsites, cxa, cya)),
|
|
114
|
+
columns =['Label', 'NSites', 'CentroidX', 'CentroidY'])
|
|
115
|
+
return ImageStack(mask0, mdh=inputim.mdh), sitesdf
|
|
116
|
+
|
|
117
|
+
# same as the routine above but everything is done in a small ROI that is then inserted into the
|
|
118
|
+
# full size image; this speeds everything up considerably, mostly as hoped
|
|
119
|
+
def picasso_structure_mask_roi(inputim,struc,dilations=2,
|
|
120
|
+
dilationselem=np.ones((5,5),dtype='float32'),roisize=20):
|
|
121
|
+
ox = inputim.mdh['Origin.x']
|
|
122
|
+
oy = inputim.mdh['Origin.y']
|
|
123
|
+
vxsz = 1e3*inputim.mdh['voxelsize.x']
|
|
124
|
+
|
|
125
|
+
mask0 = np.zeros(inputim.data.shape[0:2],dtype='float32')
|
|
126
|
+
labels = []
|
|
127
|
+
nsites = []
|
|
128
|
+
cxa = []
|
|
129
|
+
cya = []
|
|
130
|
+
|
|
131
|
+
rszh = roisize
|
|
132
|
+
xroi = np.arange(0,2*rszh+1,dtype='int')
|
|
133
|
+
yroi = np.arange(0,2*rszh+1,dtype='int')
|
|
134
|
+
xroi2 = np.outer(xroi,np.ones(2*rszh+1,dtype='i'))
|
|
135
|
+
yroi2 = np.outer(np.ones(2*rszh+1,dtype='i'),yroi)
|
|
136
|
+
|
|
137
|
+
for label in range(0,int(struc['HandleStruct'].max()+1)):
|
|
138
|
+
strucn = struc['HandleStruct'] == label
|
|
139
|
+
strucx = ((struc['HandleX'][strucn]) - ox) / vxsz
|
|
140
|
+
strucy = ((struc['HandleY'][strucn]) - oy) / vxsz
|
|
141
|
+
cx = struc['HandleX'][strucn].mean()
|
|
142
|
+
cy = struc['HandleY'][strucn].mean()
|
|
143
|
+
cxi = np.rint(strucx.mean()).astype('int') # integer centroid x
|
|
144
|
+
cyi = np.rint(strucy.mean()).astype('int') # integer centroid y
|
|
145
|
+
labels.append(label+1)
|
|
146
|
+
nsites.append(strucx.size)
|
|
147
|
+
cxa.append(cx)
|
|
148
|
+
cya.append(cy)
|
|
149
|
+
# make empty small ROI
|
|
150
|
+
roinew = np.zeros((2*rszh+1,2*rszh+1),dtype='f')
|
|
151
|
+
# transform coordinates to the ROI coordinate system
|
|
152
|
+
# the ROI is centered on the structure centroid (cxi,cyi)
|
|
153
|
+
roisx = strucx - (cxi-rszh)
|
|
154
|
+
roisy = strucy - (cyi-rszh)
|
|
155
|
+
# set pixels corresponding to structure to 1
|
|
156
|
+
roinew[roisx.astype('i'),roisy.astype('i')] = 1.0
|
|
157
|
+
# convex hull of structure + dilations
|
|
158
|
+
roi2 = morph.convex_hull_image(roinew)
|
|
159
|
+
for i in range(dilations):
|
|
160
|
+
roi2 = morph.binary_dilation(roi2,selem=dilationselem)
|
|
161
|
+
# transform ROI coordinates to full image coordiante system
|
|
162
|
+
x2 = xroi2 + (cxi-rszh)
|
|
163
|
+
y2 = yroi2 + (cyi-rszh)
|
|
164
|
+
# restrict to non-zero pixels
|
|
165
|
+
mask = roi2 > 0.5
|
|
166
|
+
x2m = x2[mask]
|
|
167
|
+
y2m = y2[mask]
|
|
168
|
+
# check which of these non-zero pixels are within the full image bounds
|
|
169
|
+
valid = (x2m < mask0.shape[0])*(y2m < mask0.shape[1])*(x2m >= 0)*(y2m >= 0)
|
|
170
|
+
if np.any(valid):
|
|
171
|
+
mask0[x2[mask][valid],y2[mask][valid]] = label+1 # set to label of that structure
|
|
172
|
+
|
|
173
|
+
sitesdf = pd.DataFrame(list(zip(labels, nsites, cxa, cya)),
|
|
174
|
+
columns =['Label', 'NSites', 'CentroidX', 'CentroidY'])
|
|
175
|
+
return ImageStack(mask0, mdh=inputim.mdh), sitesdf
|
|
176
|
+
|
|
177
|
+
# import skimage.morphology as morph
|
|
178
|
+
|
|
179
|
+
# dilations=2
|
|
180
|
+
# dilationselem=np.ones((5,5),dtype='i')
|
|
181
|
+
|
|
182
|
+
# strucx = np.array([200,210,220,200,210])
|
|
183
|
+
# strucy = np.array([100,100,100,110,110])
|
|
184
|
+
|
|
185
|
+
# cx = np.round(strucx.mean()).astype('i')
|
|
186
|
+
# cy = np.round(strucy.mean()).astype('i')
|
|
187
|
+
|
|
188
|
+
# mask0 = np.zeros((256,256),dtype='f')
|
|
189
|
+
|
|
190
|
+
# rszh = 20
|
|
191
|
+
|
|
192
|
+
# # initialisation
|
|
193
|
+
# xroi = np.arange(0,2*rszh+1,dtype='int')
|
|
194
|
+
# yroi = np.arange(0,2*rszh+1,dtype='int')
|
|
195
|
+
# xroi2 = np.outer(xroi,np.ones(2*rszh+1,dtype='i'))
|
|
196
|
+
# yroi2 = np.outer(np.ones(2*rszh+1,dtype='i'),yroi)
|
|
197
|
+
|
|
198
|
+
# # this is done in each loop
|
|
199
|
+
# roinew = np.zeros((2*rszh+1,2*rszh+1),dtype='f')
|
|
200
|
+
|
|
201
|
+
# roisx = strucx - (cx-rszh)
|
|
202
|
+
# roisy = strucy - (cy-rszh)
|
|
203
|
+
|
|
204
|
+
# roinew[roisx.astype('i'),roisy.astype('i')] = 1.0
|
|
205
|
+
# roi2 = morph.convex_hull_image(roinew)
|
|
206
|
+
# for i in range(dilations):
|
|
207
|
+
# roi2 = morph.binary_dilation(roi2,selem=dilationselem)
|
|
208
|
+
|
|
209
|
+
# x2 = xroi2 + (cx-rszh)
|
|
210
|
+
# y2 = yroi2 + (cy-rszh)
|
|
211
|
+
|
|
212
|
+
# mask = roi2 > 0.5
|
|
213
|
+
|
|
214
|
+
# x2m = x2[mask]
|
|
215
|
+
# y2m = y2[mask]
|
|
216
|
+
|
|
217
|
+
# valid = (x2m < mask0.shape[0])*(y2m < mask0.shape[1])*(x2m >= 0)*(y2m >= 0)
|
|
218
|
+
|
|
219
|
+
# mask0[x2[mask][valid],y2[mask][valid]] = roi2[xroi2[mask][valid],yroi2[mask][valid]]
|
PYMEcs/IO/tabular.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from PYMEcs.Analysis.fitDarkTimes import TabularRecArrayWrap
|
|
2
|
+
import pandas as pd
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
# we should probably add this to a module like PYMEcs.IO.tabular
|
|
6
|
+
def tabularFromCSV(csvname):
|
|
7
|
+
df = pd.DataFrame.from_csv(csvname)
|
|
8
|
+
rec = df.to_records()
|
|
9
|
+
tb = TabularRecArrayWrap(rec)
|
|
10
|
+
return tb
|
|
11
|
+
|
PYMEcs/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import PYMEcs.Analysis.stackTracker as st
|
|
2
|
+
from PYMEcs.misc.guiMsgBoxes import Warn
|
|
3
|
+
|
|
4
|
+
from traits.api import HasTraits, Str, Int, CStr, List, Enum, Float, Bool
|
|
5
|
+
|
|
6
|
+
class CalcZfConfig(HasTraits):
|
|
7
|
+
offsetFromCenter = Int(0)
|
|
8
|
+
planesToUse = Int(11)
|
|
9
|
+
|
|
10
|
+
from PYME.DSView.modules._base import Plugin
|
|
11
|
+
class CalcZf(Plugin):
|
|
12
|
+
def __init__(self, dsviewer):
|
|
13
|
+
Plugin.__init__(self, dsviewer)
|
|
14
|
+
self.czfconf = CalcZfConfig()
|
|
15
|
+
|
|
16
|
+
dsviewer.AddMenuItem('Experimental', "Calculate z-factor", self.OnCalcZf)
|
|
17
|
+
dsviewer.AddMenuItem('Experimental', "z-factor calculation settings", self.OnCalcZfSettings)
|
|
18
|
+
|
|
19
|
+
def OnCalcZfSettings(self, event):
|
|
20
|
+
self.czfconf.configure_traits(kind='modal')
|
|
21
|
+
|
|
22
|
+
def OnCalcZf(self, event):
|
|
23
|
+
# first a few checks that the data set is suitable
|
|
24
|
+
# do we need further checks?
|
|
25
|
+
from math import isclose
|
|
26
|
+
if not isclose(self.dsviewer.image.voxelsize_nm.z,50.0,abs_tol=1.0):
|
|
27
|
+
Warn(self.dsviewer,'z voxelsize needs to be 50 nm, is %.1f nm' % self.dsviewer.image.voxelsize_nm.z)
|
|
28
|
+
return
|
|
29
|
+
|
|
30
|
+
use_zszh = self.czfconf.planesToUse // 2
|
|
31
|
+
offset = self.czfconf.offsetFromCenter
|
|
32
|
+
need_planes = 2*use_zszh+1 + abs(offset)
|
|
33
|
+
|
|
34
|
+
zsz = self.dsviewer.image.data_xyztc.shape[2]
|
|
35
|
+
zszh = zsz // 2
|
|
36
|
+
if 2*zszh+1 != zsz:
|
|
37
|
+
Warn(self.dsviewer,'z dimension size should be odd number, is %d' % zsz)
|
|
38
|
+
return
|
|
39
|
+
if zsz < need_planes:
|
|
40
|
+
Warn(self.dsviewer,'need at least %d planes, stack has %d planes' % (need_planes,zsz))
|
|
41
|
+
return
|
|
42
|
+
|
|
43
|
+
dataset = self.dsviewer.image.data_xyztc[:,:,zszh+offset-use_zszh:zszh+offset+use_zszh+1,0,0].squeeze()
|
|
44
|
+
|
|
45
|
+
tstack = st.initialise_data(dataset,4,self.dsviewer.image.voxelsize_nm)
|
|
46
|
+
dxnm,dynm,dznm = st.get_shifts_from_stackobject(tstack)
|
|
47
|
+
|
|
48
|
+
st.fit_and_plot_zf(dxnm,dynm,dznm,tstack)
|
|
49
|
+
|
|
50
|
+
def Plug(dsviewer):
|
|
51
|
+
return CalcZf(dsviewer)
|