-
Notifications
You must be signed in to change notification settings - Fork 0
/
BlobTEMmp.py
212 lines (143 loc) · 5.47 KB
/
BlobTEMmp.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
"""
This script includes a multiprocess routine that decreases runtime by half by running the
blob detection in parallel (2 parallel processes, 1 for each core in the macbook).
Unfortunately the python CPU Pool.map function only allows passing one argument to each
process, so the program had to be divided up in an awkward manner. It will be an issue if
there are an odd number of list elements in each mapped function call.
It is possible to get around this using partial functions but I'm still learning how that
works.
Running this on the macbook there is a decreases for single process to two processes of
990.4 seconds to 509.5 seconds.
"""
# Load modules
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import os
import time
import warnings
import multiprocessing as mp
from scipy.ndimage import gaussian_filter
from scipy.stats import mode
from math import sqrt
from skimage import data, io, filters, measure, segmentation, morphology
from skimage import img_as_ubyte, img_as_float
from skimage.color import rgb2gray
from skimage.morphology import reconstruction
from skimage.feature import blob_dog, blob_log, blob_doh
#--------------------------------------------------------------------------------------
def agtemblob(image):
"""
Laplacian of gaussian blob detection for TEM images
"""
org = image[4:-256,4:-4]
with warnings.catch_warnings():
warnings.simplefilter("ignore")
warnings.warn("user", UserWarning)
igray = img_as_ubyte(rgb2gray(org))
iinv = np.invert(igray)
igaus = img_as_float(iinv)
igaus = gaussian_filter(igaus, 1)
h = 0.5
sd = igaus - h
msk = igaus
dilat = reconstruction(sd, msk, method='dilation')
hdome = igaus - dilat
kwargs = {}
kwargs['threshold'] = 0.01
kwargs['overlap'] = 0.4
kwargs['min_sigma'] = 25
kwargs['max_sigma'] = 50
kwargs['num_sigma'] = 25
calib = 500/(969-26)
blobs = blob_log(hdome, **kwargs)
diam = 2*sqrt(2)*blobs[:,-1]
npdiam = calib*diam
return(npdiam)
#--------------------------------------------------------------------------------------
def autemblob(image):
"""
Laplacian of gaussian blob detection for TEM images
"""
org = image[4:-256,4:-4]
with warnings.catch_warnings():
warnings.simplefilter("ignore")
warnings.warn("user", UserWarning)
igray = img_as_ubyte(rgb2gray(org))
iinv = np.invert(igray)
igaus = img_as_float(iinv)
igaus = gaussian_filter(igaus, 1)
h = 0.5
sd = igaus - h
msk = igaus
dilat = reconstruction(sd, msk, method='dilation')
hdome = igaus - dilat
kwargs = {}
kwargs['threshold'] = 0.01
kwargs['overlap'] = 0.4
kwargs['min_sigma'] = 18
kwargs['max_sigma'] = 30
kwargs['num_sigma'] = 12
calib = 200/(777-23)
blobs = blob_log(hdome, **kwargs)
diam = 2*sqrt(2)*blobs[:,-1]
npdiam = calib*diam
return(npdiam)
#--------------------------------------------------------------------------------------
def plotresults(agdia, audia):
plt.ion()
plt.rc('font', size='18')
bins = range(10,80,2)
fig, axes = plt.subplots(1,2, figsize=(16,6))
for a,title,sample,c in zip(axes, ('AuNP','AgNP'),
(audia, agdia), ['CornflowerBlue','IndianRed']):
a.set_xlabel('Diameter (nm)')
a.set_ylabel('Number of particles')
a.set_title(title)
_, _, _ = a.hist(sample, bins=bins, color=c)
#--------------------------------------------------------------------------------------
def statresults(agdia, audia):
# Statistical report
dfinal = pd.DataFrame([[len(audia)],[len(agdia)]],
columns=['Total particles counted'], index=['AuNP','AgNP'])
dfinal['Mean Diameter (nm)'] = np.round([np.mean(audia),np.mean(agdia)],1)
dfinal['Median Diameter (nm)'] = np.round([np.median(audia),np.median(agdia)],1)
dfinal['Mode Diameter (nm)'] = np.round([mode(audia.tolist())[0],
mode(agdia.tolist())[0]],1)
return dfinal
#--------------------------------------------------------------------------------------
if __name__ == '__main__':
# Select directory where files are stored
rdir = '/Volumes/TRANSFER/TEM/2015-10-15 - AuNP and AgNP/'
files = os.listdir(rdir)
# Sort out non images '*.tif'
srtf = [f for f in files if '.tif' in f]
# Not all files are useful due to shifting magnification scales, must manually input
manf = ['AgNP-01.tif','AgNP-02.tif','AgNP-03.tif','AgNP-04.tif','AgNP-05.tif']
manf.extend(['AgNP-06.tif','AgNP-07.tif','AgNP-11.tif','AgNP-12.tif'])
manf.extend(['AuNP-02.tif','AuNP-03.tif','AuNP-05.tif','AuNP-06.tif','AuNP-07.tif'])
manf.extend(['AuNP-08.tif','AuNP-09.tif','AuNP-10.tif'])
# Check all files are input correctly to prevent errors during runtime
# presnt = all(f in srtf for f in manf)
# print('Any typos in manual input file names:', str(not presnt))
# typo = all('Au' in s or 'Ag' in s for s in manf)
# print('Any typos in original file names:', str(not typo))
# Start timer to monitor program run time
startTime = time.time()
# Break up list of files into Au or Ag because map only passes one argument
agimages = [io.imread(rdir+f) for f in manf if 'Ag' in f]
auimages = [io.imread(rdir+f) for f in manf if 'Au' in f]
# Two process version
with mp.Pool(processes=2) as pool:
agres = pool.map(agtemblob, agimages, 1)
aures = pool.map(autemblob, auimages, 1)
# Serial or single process version
# agres = list(map(agtemblob, agimages))
# aures = list(map(autemblob, auimages))
agdia = np.concatenate(agres)
audia = np.concatenate(aures)
# Print elapsed time
print('')
print('Elapsed time:', round(time.time()-startTime,1), 'seconds')
plotresults(agdia, audia)
print(statresults(agdia, audia))