insituTEM 0.1.8__tar.gz → 1.0.0__tar.gz
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.
- insitutem-1.0.0/PKG-INFO +85 -0
- insitutem-1.0.0/README.md +64 -0
- {insitutem-0.1.8 → insitutem-1.0.0}/insituTEM/insitu_DENS.py +1 -4
- {insitutem-0.1.8 → insitutem-1.0.0}/insituTEM/insitu_DP.py +1 -171
- {insitutem-0.1.8 → insitutem-1.0.0}/insituTEM/insitu_Diff.py +206 -35
- {insitutem-0.1.8 → insitutem-1.0.0}/insituTEM/insitu_EMraw.py +1 -0
- {insitutem-0.1.8 → insitutem-1.0.0}/insituTEM/insitu_IO.py +6 -5
- {insitutem-0.1.8 → insitutem-1.0.0}/insituTEM/insitu_alignment.py +1 -1
- insitutem-1.0.0/insituTEM.egg-info/PKG-INFO +85 -0
- {insitutem-0.1.8 → insitutem-1.0.0}/insituTEM.egg-info/SOURCES.txt +1 -0
- {insitutem-0.1.8 → insitutem-1.0.0}/pyproject.toml +1 -1
- insitutem-0.1.8/PKG-INFO +0 -20
- insitutem-0.1.8/insituTEM.egg-info/PKG-INFO +0 -20
- {insitutem-0.1.8 → insitutem-1.0.0}/insituTEM/__ init __.py +0 -0
- {insitutem-0.1.8 → insitutem-1.0.0}/insituTEM/insitu_Preprocess.py +0 -0
- {insitutem-0.1.8 → insitutem-1.0.0}/insituTEM.egg-info/dependency_links.txt +0 -0
- {insitutem-0.1.8 → insitutem-1.0.0}/insituTEM.egg-info/requires.txt +0 -0
- {insitutem-0.1.8 → insitutem-1.0.0}/insituTEM.egg-info/top_level.txt +0 -0
- {insitutem-0.1.8 → insitutem-1.0.0}/setup.cfg +0 -0
- {insitutem-0.1.8 → insitutem-1.0.0}/setup.py +0 -0
insitutem-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: insituTEM
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A toolbox for processing in situ TEM data
|
|
5
|
+
Requires-Python: >=3.9
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: numpy
|
|
8
|
+
Requires-Dist: scipy
|
|
9
|
+
Requires-Dist: matplotlib
|
|
10
|
+
Requires-Dist: pandas
|
|
11
|
+
Requires-Dist: tifffile
|
|
12
|
+
Requires-Dist: tqdm
|
|
13
|
+
Requires-Dist: opencv-python
|
|
14
|
+
Requires-Dist: pillow
|
|
15
|
+
Requires-Dist: scikit-image
|
|
16
|
+
Requires-Dist: moviepy
|
|
17
|
+
Requires-Dist: ncempy
|
|
18
|
+
Requires-Dist: easygui
|
|
19
|
+
Requires-Dist: pystackreg
|
|
20
|
+
Requires-Dist: pyside6
|
|
21
|
+
|
|
22
|
+
# insituTEM
|
|
23
|
+
|
|
24
|
+
Tools for preprocessing in situ TEM movies.
|
|
25
|
+
|
|
26
|
+
Author: Meng Li (mona.mengli@gmail.com; mli4@bnl.gov)
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
```bash
|
|
30
|
+
pip install insitutem-toolbox
|
|
31
|
+
```
|
|
32
|
+
## Module descriptions
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
### `insitu_IO`
|
|
36
|
+
|
|
37
|
+
in-situ TEM Toolbox - Input Output
|
|
38
|
+
|
|
39
|
+
Assembles of functions related to movie input output
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
### `insitu_Preprocess`
|
|
43
|
+
|
|
44
|
+
in-situ TEM Toolbox - PreProcess
|
|
45
|
+
|
|
46
|
+
Assembles of functions related to movie preprocess
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
### `insitu_alignment`
|
|
50
|
+
|
|
51
|
+
in-situ TEM Toolbox - Movie alignment
|
|
52
|
+
|
|
53
|
+
Assembles of functions related to movie alignment
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
### `insitu_DENS`
|
|
58
|
+
|
|
59
|
+
in-situ TEM Toolbox - DENS holder data process
|
|
60
|
+
|
|
61
|
+
Assembles of functions related to process raw data by DENS holders
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
### `insitu_DP`
|
|
66
|
+
|
|
67
|
+
in-situ TEM Toolbox - Image Data process
|
|
68
|
+
|
|
69
|
+
Assembles of functions related to movie data analysis such as plots
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
### `insitu_Diff`
|
|
74
|
+
|
|
75
|
+
in-situ TEM Toolbox - Diffraction pattern analysis
|
|
76
|
+
|
|
77
|
+
Assembles of functions related to process FFT and diffraction patterns
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
### `insitu_EMraw`
|
|
82
|
+
|
|
83
|
+
in-situ TEM Toolbox - TEM raw data conversion
|
|
84
|
+
|
|
85
|
+
Assembles of functions related to read and process raw dm4, dm3 or FEI TIA or Ceta datas.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# insituTEM
|
|
2
|
+
|
|
3
|
+
Tools for preprocessing in situ TEM movies.
|
|
4
|
+
|
|
5
|
+
Author: Meng Li (mona.mengli@gmail.com; mli4@bnl.gov)
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
```bash
|
|
9
|
+
pip install insitutem-toolbox
|
|
10
|
+
```
|
|
11
|
+
## Module descriptions
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### `insitu_IO`
|
|
15
|
+
|
|
16
|
+
in-situ TEM Toolbox - Input Output
|
|
17
|
+
|
|
18
|
+
Assembles of functions related to movie input output
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### `insitu_Preprocess`
|
|
22
|
+
|
|
23
|
+
in-situ TEM Toolbox - PreProcess
|
|
24
|
+
|
|
25
|
+
Assembles of functions related to movie preprocess
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
### `insitu_alignment`
|
|
29
|
+
|
|
30
|
+
in-situ TEM Toolbox - Movie alignment
|
|
31
|
+
|
|
32
|
+
Assembles of functions related to movie alignment
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
### `insitu_DENS`
|
|
37
|
+
|
|
38
|
+
in-situ TEM Toolbox - DENS holder data process
|
|
39
|
+
|
|
40
|
+
Assembles of functions related to process raw data by DENS holders
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
### `insitu_DP`
|
|
45
|
+
|
|
46
|
+
in-situ TEM Toolbox - Image Data process
|
|
47
|
+
|
|
48
|
+
Assembles of functions related to movie data analysis such as plots
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
### `insitu_Diff`
|
|
53
|
+
|
|
54
|
+
in-situ TEM Toolbox - Diffraction pattern analysis
|
|
55
|
+
|
|
56
|
+
Assembles of functions related to process FFT and diffraction patterns
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
### `insitu_EMraw`
|
|
61
|
+
|
|
62
|
+
in-situ TEM Toolbox - TEM raw data conversion
|
|
63
|
+
|
|
64
|
+
Assembles of functions related to read and process raw dm4, dm3 or FEI TIA or Ceta datas.
|
|
@@ -13,9 +13,6 @@ Created on Tue May 13 2025
|
|
|
13
13
|
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
|
-
"""
|
|
17
|
-
Codes for Stream data process
|
|
18
|
-
"""
|
|
19
16
|
import pandas as pd
|
|
20
17
|
|
|
21
18
|
def read_pstrace_csv(filepath):
|
|
@@ -129,7 +126,7 @@ def plot_multiple_xy(datasets, labels=None, xlabel=None, ylabel=None, title=None
|
|
|
129
126
|
plt.show()
|
|
130
127
|
|
|
131
128
|
|
|
132
|
-
|
|
129
|
+
import matplotlib.pyplot as plt
|
|
133
130
|
|
|
134
131
|
def plot_xy(df, measurement_type=None):
|
|
135
132
|
"""
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"""
|
|
3
3
|
in-situ TEM Toolbox - Data process
|
|
4
4
|
|
|
5
|
-
Assembles of functions related to
|
|
5
|
+
Assembles of functions related to data analysis for in-situ TEM experiments such as plot.
|
|
6
6
|
|
|
7
7
|
Example:
|
|
8
8
|
|
|
@@ -209,173 +209,3 @@ def readscale(path):
|
|
|
209
209
|
print("scale=",scale,"px/nm")
|
|
210
210
|
return scale
|
|
211
211
|
|
|
212
|
-
def next_power_of_2(x):
|
|
213
|
-
return 1 if x == 0 else 2**(x - 1).bit_length()
|
|
214
|
-
|
|
215
|
-
def pad_to_nearest_power_of_2(image):
|
|
216
|
-
import cv2
|
|
217
|
-
# Get original dimensions
|
|
218
|
-
h, w = image.shape
|
|
219
|
-
size=max(h,w)
|
|
220
|
-
|
|
221
|
-
# Calculate the nearest power of 2 dimensions
|
|
222
|
-
new_size = next_power_of_2(size)
|
|
223
|
-
|
|
224
|
-
# Calculate padding amounts
|
|
225
|
-
top_pad = (new_size - h) // 2
|
|
226
|
-
bottom_pad = new_size - h - top_pad
|
|
227
|
-
left_pad = (new_size - w) // 2
|
|
228
|
-
right_pad = new_size - w - left_pad
|
|
229
|
-
|
|
230
|
-
# Apply padding
|
|
231
|
-
padded_image = cv2.copyMakeBorder(
|
|
232
|
-
image,
|
|
233
|
-
top=top_pad, bottom=bottom_pad,
|
|
234
|
-
left=left_pad, right=right_pad,
|
|
235
|
-
borderType=cv2.BORDER_CONSTANT,
|
|
236
|
-
value=0 # Black color
|
|
237
|
-
)
|
|
238
|
-
|
|
239
|
-
return padded_image
|
|
240
|
-
|
|
241
|
-
def getFFT(im):
|
|
242
|
-
"""
|
|
243
|
-
Function to get FFT from grayscale image, auto pad the image to keep the image size 2^n
|
|
244
|
-
Input: grayscale image (np array)
|
|
245
|
-
Output: grayscale FFT with 2^n size, 32 bit
|
|
246
|
-
"""
|
|
247
|
-
|
|
248
|
-
pad_im=pad_to_nearest_power_of_2(im)
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
fft_image = np.fft.fft2(pad_im)
|
|
252
|
-
fft_shifted = np.fft.fftshift(fft_image)
|
|
253
|
-
fft = 20 * np.log(np.abs(fft_shifted))
|
|
254
|
-
return fft
|
|
255
|
-
|
|
256
|
-
def FFTstack(path):
|
|
257
|
-
"""
|
|
258
|
-
Function to get FFT of the stack
|
|
259
|
-
input: path of the image stack
|
|
260
|
-
output: FFT stack with 2^n size 8 bit images
|
|
261
|
-
"""
|
|
262
|
-
import tifffile
|
|
263
|
-
import tqdm
|
|
264
|
-
import cv2
|
|
265
|
-
|
|
266
|
-
stack = tifffile.imread(path)
|
|
267
|
-
nFrames,h,w = stack.shape #make sure the order of h and w!
|
|
268
|
-
pathout=path[:-4]+'_FFT.tif'
|
|
269
|
-
|
|
270
|
-
print("------------------------------------------")
|
|
271
|
-
print('Calculating FFT of each frame')
|
|
272
|
-
with tifffile.TiffWriter(pathout,bigtiff=True) as tif:
|
|
273
|
-
for i in tqdm.tqdm(range(nFrames)):
|
|
274
|
-
fr=stack[i]
|
|
275
|
-
fft=getFFT(fr)
|
|
276
|
-
#convert the 32 bit image to 8 bit
|
|
277
|
-
normalized_image = cv2.normalize(fft, None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX)
|
|
278
|
-
# Convert the normalized image to 8-bit
|
|
279
|
-
fft_8bit = np.uint8(normalized_image)
|
|
280
|
-
tif.write(fft_8bit, contiguous=True)
|
|
281
|
-
|
|
282
|
-
def FFT2Polar(fft):
|
|
283
|
-
"""
|
|
284
|
-
Function to convert FFT to polar image, y= 180˚, x= Rho
|
|
285
|
-
Input: grayscale fft image (np array)
|
|
286
|
-
"""
|
|
287
|
-
import cv2
|
|
288
|
-
#function to convert fft image to polar coordinates from the center from 0-180 deg
|
|
289
|
-
center = (fft.shape[1] // 2, fft.shape[0] // 2)
|
|
290
|
-
polar_fft = cv2.linearPolar(fft, center, center[0], cv2.WARP_FILL_OUTLIERS)
|
|
291
|
-
# polar_fft= polar_fft[:,:center[1]]
|
|
292
|
-
#resize the image to realistic size
|
|
293
|
-
resized_polar_fft = cv2.resize(polar_fft, (center[0], 360))
|
|
294
|
-
# plt.imshow(resized_polar_fft)
|
|
295
|
-
|
|
296
|
-
p_fft1=resized_polar_fft[:180,:]
|
|
297
|
-
p_fft2=resized_polar_fft[180:,:]
|
|
298
|
-
p_fft=p_fft1+p_fft2
|
|
299
|
-
return p_fft
|
|
300
|
-
|
|
301
|
-
def FFTidentify(fft,pathout,scale=1,sigmaMax=2.5,sigmaMin=2.4,thrs=0.96,sigma_ratio=10):
|
|
302
|
-
"""
|
|
303
|
-
Function to identify DPs from FFT
|
|
304
|
-
input:
|
|
305
|
-
fft: image
|
|
306
|
-
scale: scale of the original image : 1 px = XXX nm
|
|
307
|
-
parameters for blobs detection: sigmaMax, sigmaMin, thrs, sigma_ratio
|
|
308
|
-
pathout: path for output image (.tif) and csv
|
|
309
|
-
|
|
310
|
-
output:
|
|
311
|
-
idnetified image
|
|
312
|
-
indexed csv
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
"""
|
|
317
|
-
import math
|
|
318
|
-
import matplotlib.pyplot as plt
|
|
319
|
-
from scipy import ndimage
|
|
320
|
-
from skimage.feature import blob_dog, blob_log, blob_doh
|
|
321
|
-
from math import sqrt
|
|
322
|
-
from insituTEM import insitu_IO as IO
|
|
323
|
-
|
|
324
|
-
h,w = fft.shape
|
|
325
|
-
x_c=int(w/2)
|
|
326
|
-
y_c=int(h/2)
|
|
327
|
-
r=int(x_c/2)
|
|
328
|
-
if w>320:
|
|
329
|
-
fft_crop=fft[x_c-r:x_c+r,y_c-r:y_c+r]
|
|
330
|
-
image= ndimage.maximum_filter(fft_crop, size=2, mode='wrap')
|
|
331
|
-
else:
|
|
332
|
-
fft_crop = fft
|
|
333
|
-
image= ndimage.maximum_filter(fft_crop, size=3, mode='wrap')
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
blobs_dog = blob_dog(image, max_sigma=sigmaMax,min_sigma=sigmaMin, threshold=thrs,sigma_ratio=sigma_ratio,exclude_border=True)
|
|
339
|
-
blobs_dog[:, 2] = blobs_dog[:, 2] * sqrt(2)
|
|
340
|
-
|
|
341
|
-
title = 'DP detection'
|
|
342
|
-
|
|
343
|
-
fig, axes = plt.subplots(1, 2, figsize=(10, 5), sharex=True, sharey=True)
|
|
344
|
-
ax = axes.ravel()
|
|
345
|
-
|
|
346
|
-
ax[0].set_title('FFT_')
|
|
347
|
-
ax[0].imshow(fft_crop)
|
|
348
|
-
# ax[0].set_axis_off()
|
|
349
|
-
ax[1].set_title(title)
|
|
350
|
-
ax[1].imshow(image)
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
plt.tight_layout()
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
data=np.zeros((len(blobs_dog),6))
|
|
357
|
-
data[:,0]=blobs_dog[:,1]
|
|
358
|
-
data[:,1]=blobs_dog[:,0]
|
|
359
|
-
|
|
360
|
-
for j in range(len(blobs_dog)):
|
|
361
|
-
y=data[j,1]-r
|
|
362
|
-
x=data[j,0]-r
|
|
363
|
-
|
|
364
|
-
data[j,2]=math.sqrt(x**2+y**2)
|
|
365
|
-
# if data[j,2] < 10:
|
|
366
|
-
# data[j,2]=0
|
|
367
|
-
# theta = 0
|
|
368
|
-
# else:
|
|
369
|
-
# theta=math.atan(y/x)
|
|
370
|
-
theta=math.atan(y/x)
|
|
371
|
-
data[j,3]=math.degrees(theta)
|
|
372
|
-
|
|
373
|
-
data[:,4]=data[:,2]*scale
|
|
374
|
-
data[:,5]=1/data[:,4]
|
|
375
|
-
|
|
376
|
-
plt.scatter(data[:,0],data[:,1],marker='+',color='red')
|
|
377
|
-
for i, (x_i, y_i) in enumerate(zip(data[:,0],data[:,1])):
|
|
378
|
-
plt.annotate(str(i+1), (x_i, y_i), textcoords="offset points", xytext=(0,10), ha='center',color='white')
|
|
379
|
-
pathoutcsv=pathout[:-4]+'.csv'
|
|
380
|
-
IO.writeCSV(pathoutcsv,data,fmt='%1.3f')
|
|
381
|
-
plt.savefig(pathout)
|
|
@@ -20,23 +20,194 @@ import math
|
|
|
20
20
|
|
|
21
21
|
# import pandas as pd
|
|
22
22
|
|
|
23
|
+
def next_power_of_2(x):
|
|
24
|
+
return 1 if x == 0 else 2**(x - 1).bit_length()
|
|
25
|
+
|
|
26
|
+
def pad_to_nearest_power_of_2(image):
|
|
27
|
+
import cv2
|
|
28
|
+
# Get original dimensions
|
|
29
|
+
h, w = image.shape
|
|
30
|
+
size=max(h,w)
|
|
31
|
+
|
|
32
|
+
# Calculate the nearest power of 2 dimensions
|
|
33
|
+
new_size = next_power_of_2(size)
|
|
34
|
+
|
|
35
|
+
# Calculate padding amounts
|
|
36
|
+
top_pad = (new_size - h) // 2
|
|
37
|
+
bottom_pad = new_size - h - top_pad
|
|
38
|
+
left_pad = (new_size - w) // 2
|
|
39
|
+
right_pad = new_size - w - left_pad
|
|
40
|
+
|
|
41
|
+
# Apply padding
|
|
42
|
+
padded_image = cv2.copyMakeBorder(
|
|
43
|
+
image,
|
|
44
|
+
top=top_pad, bottom=bottom_pad,
|
|
45
|
+
left=left_pad, right=right_pad,
|
|
46
|
+
borderType=cv2.BORDER_CONSTANT,
|
|
47
|
+
value=0 # Black color
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
return padded_image
|
|
51
|
+
|
|
23
52
|
def getFFT(im):
|
|
24
53
|
"""
|
|
25
|
-
Function to
|
|
26
|
-
|
|
27
|
-
|
|
54
|
+
Function to get FFT from grayscale image, auto pad the image to keep the image size 2^n
|
|
55
|
+
Input: grayscale image (np array)
|
|
56
|
+
Output: grayscale FFT with 2^n size, 32 bit
|
|
28
57
|
"""
|
|
29
|
-
# Get the original dimensions of the image
|
|
30
|
-
h, w = im.shape
|
|
31
58
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
59
|
+
pad_im=pad_to_nearest_power_of_2(im)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
fft_image = np.fft.fft2(pad_im)
|
|
35
63
|
fft_shifted = np.fft.fftshift(fft_image)
|
|
36
|
-
fft = 20 * np.log(np.abs(fft_shifted)
|
|
37
|
-
|
|
64
|
+
fft = 20 * np.log(np.abs(fft_shifted))
|
|
38
65
|
return fft
|
|
39
66
|
|
|
67
|
+
def FFTstack(path):
|
|
68
|
+
"""
|
|
69
|
+
Function to get FFT of the stack
|
|
70
|
+
input: path of the image stack
|
|
71
|
+
output: FFT stack with 2^n size 8 bit images
|
|
72
|
+
"""
|
|
73
|
+
import tifffile
|
|
74
|
+
import tqdm
|
|
75
|
+
import cv2
|
|
76
|
+
|
|
77
|
+
stack = tifffile.imread(path)
|
|
78
|
+
nFrames,h,w = stack.shape #make sure the order of h and w!
|
|
79
|
+
pathout=path[:-4]+'_FFT.tif'
|
|
80
|
+
|
|
81
|
+
print("------------------------------------------")
|
|
82
|
+
print('Calculating FFT of each frame')
|
|
83
|
+
with tifffile.TiffWriter(pathout,bigtiff=True) as tif:
|
|
84
|
+
for i in tqdm.tqdm(range(nFrames)):
|
|
85
|
+
fr=stack[i]
|
|
86
|
+
fft=getFFT(fr)
|
|
87
|
+
#convert the 32 bit image to 8 bit
|
|
88
|
+
normalized_image = cv2.normalize(fft, None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX)
|
|
89
|
+
# Convert the normalized image to 8-bit
|
|
90
|
+
fft_8bit = np.uint8(normalized_image)
|
|
91
|
+
tif.write(fft_8bit, contiguous=True)
|
|
92
|
+
|
|
93
|
+
def FFT2Polar(fft):
|
|
94
|
+
"""
|
|
95
|
+
Function to convert FFT to polar image, y= 180˚, x= Rho
|
|
96
|
+
Input: grayscale fft image (np array)
|
|
97
|
+
"""
|
|
98
|
+
import cv2
|
|
99
|
+
#function to convert fft image to polar coordinates from the center from 0-180 deg
|
|
100
|
+
center = (fft.shape[1] // 2, fft.shape[0] // 2)
|
|
101
|
+
polar_fft = cv2.linearPolar(fft, center, center[0], cv2.WARP_FILL_OUTLIERS)
|
|
102
|
+
# polar_fft= polar_fft[:,:center[1]]
|
|
103
|
+
#resize the image to realistic size
|
|
104
|
+
resized_polar_fft = cv2.resize(polar_fft, (center[0], 360))
|
|
105
|
+
# plt.imshow(resized_polar_fft)
|
|
106
|
+
|
|
107
|
+
p_fft1=resized_polar_fft[:180,:]
|
|
108
|
+
p_fft2=resized_polar_fft[180:,:]
|
|
109
|
+
p_fft=p_fft1+p_fft2
|
|
110
|
+
return p_fft
|
|
111
|
+
|
|
112
|
+
def FFTidentify(fft,pathout,scale=1,sigmaMax=2.5,sigmaMin=2.4,thrs=0.96,sigma_ratio=10):
|
|
113
|
+
"""
|
|
114
|
+
Function to identify DPs from FFT
|
|
115
|
+
input:
|
|
116
|
+
fft: image
|
|
117
|
+
scale: scale of the original image : 1 px = XXX nm
|
|
118
|
+
parameters for blobs detection: sigmaMax, sigmaMin, thrs, sigma_ratio
|
|
119
|
+
pathout: path for output image (.tif) and csv
|
|
120
|
+
|
|
121
|
+
output:
|
|
122
|
+
idnetified image
|
|
123
|
+
indexed csv
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
"""
|
|
128
|
+
import math
|
|
129
|
+
import matplotlib.pyplot as plt
|
|
130
|
+
from scipy import ndimage
|
|
131
|
+
from skimage.feature import blob_dog, blob_log, blob_doh
|
|
132
|
+
from math import sqrt
|
|
133
|
+
from insituTEM import insitu_IO as IO
|
|
134
|
+
|
|
135
|
+
h,w = fft.shape
|
|
136
|
+
x_c=int(w/2)
|
|
137
|
+
y_c=int(h/2)
|
|
138
|
+
r=int(x_c/2)
|
|
139
|
+
if w>320:
|
|
140
|
+
fft_crop=fft[x_c-r:x_c+r,y_c-r:y_c+r]
|
|
141
|
+
image= ndimage.maximum_filter(fft_crop, size=2, mode='wrap')
|
|
142
|
+
else:
|
|
143
|
+
fft_crop = fft
|
|
144
|
+
image= ndimage.maximum_filter(fft_crop, size=3, mode='wrap')
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
blobs_dog = blob_dog(image, max_sigma=sigmaMax,min_sigma=sigmaMin, threshold=thrs,sigma_ratio=sigma_ratio,exclude_border=True)
|
|
150
|
+
blobs_dog[:, 2] = blobs_dog[:, 2] * sqrt(2)
|
|
151
|
+
|
|
152
|
+
title = 'DP detection'
|
|
153
|
+
|
|
154
|
+
fig, axes = plt.subplots(1, 2, figsize=(10, 5), sharex=True, sharey=True)
|
|
155
|
+
ax = axes.ravel()
|
|
156
|
+
|
|
157
|
+
ax[0].set_title('FFT_')
|
|
158
|
+
ax[0].imshow(fft_crop)
|
|
159
|
+
# ax[0].set_axis_off()
|
|
160
|
+
ax[1].set_title(title)
|
|
161
|
+
ax[1].imshow(image)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
plt.tight_layout()
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
data=np.zeros((len(blobs_dog),6))
|
|
168
|
+
data[:,0]=blobs_dog[:,1]
|
|
169
|
+
data[:,1]=blobs_dog[:,0]
|
|
170
|
+
|
|
171
|
+
for j in range(len(blobs_dog)):
|
|
172
|
+
y=data[j,1]-r
|
|
173
|
+
x=data[j,0]-r
|
|
174
|
+
|
|
175
|
+
data[j,2]=math.sqrt(x**2+y**2)
|
|
176
|
+
# if data[j,2] < 10:
|
|
177
|
+
# data[j,2]=0
|
|
178
|
+
# theta = 0
|
|
179
|
+
# else:
|
|
180
|
+
# theta=math.atan(y/x)
|
|
181
|
+
theta=math.atan(y/x)
|
|
182
|
+
data[j,3]=math.degrees(theta)
|
|
183
|
+
|
|
184
|
+
data[:,4]=data[:,2]*scale
|
|
185
|
+
data[:,5]=1/data[:,4]
|
|
186
|
+
|
|
187
|
+
plt.scatter(data[:,0],data[:,1],marker='+',color='red')
|
|
188
|
+
for i, (x_i, y_i) in enumerate(zip(data[:,0],data[:,1])):
|
|
189
|
+
plt.annotate(str(i+1), (x_i, y_i), textcoords="offset points", xytext=(0,10), ha='center',color='white')
|
|
190
|
+
pathoutcsv=pathout[:-4]+'.csv'
|
|
191
|
+
IO.writeCSV(pathoutcsv,data,fmt='%1.3f')
|
|
192
|
+
plt.savefig(pathout)
|
|
193
|
+
|
|
194
|
+
# def getFFT(im):
|
|
195
|
+
# """
|
|
196
|
+
# Function to calculate FFT of the image
|
|
197
|
+
# input: im- np array of image data
|
|
198
|
+
# output: fft image
|
|
199
|
+
# """
|
|
200
|
+
# # Get the original dimensions of the image
|
|
201
|
+
# h, w = im.shape
|
|
202
|
+
|
|
203
|
+
# size = min(h,w) #in case h w don't match
|
|
204
|
+
# im_crop=im[:size,:size] #crop image
|
|
205
|
+
# fft_image = np.fft.fft2(im_crop)
|
|
206
|
+
# fft_shifted = np.fft.fftshift(fft_image)
|
|
207
|
+
# fft = 20 * np.log(np.abs(fft_shifted) + 1e-10) # Add small constant to avoid log(0)
|
|
208
|
+
|
|
209
|
+
# return fft
|
|
210
|
+
|
|
40
211
|
def spotFFT(fft, sigmaMax=2.5, sigmaMin=2.45, sigma_ratio=20, thrs=0.98, R_tol=2, fftfilter=3, tolerance=5, display=True):
|
|
41
212
|
"""
|
|
42
213
|
Function to get diffraction spot positions in FFT
|
|
@@ -332,28 +503,28 @@ def maskedFFT(image,mask):
|
|
|
332
503
|
return fft_image, masked_image
|
|
333
504
|
|
|
334
505
|
|
|
335
|
-
def FFTstack(stackpath,ndfilersize=3,fps=15):
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
506
|
+
# def FFTstack(stackpath,ndfilersize=3,fps=15):
|
|
507
|
+
# import tqdm
|
|
508
|
+
# from scipy import ndimage
|
|
509
|
+
# import tifffile
|
|
510
|
+
# from insituTEM import insitu_IO as IO
|
|
511
|
+
# """
|
|
512
|
+
# Apply FFT to the entire stack.
|
|
513
|
+
# """
|
|
514
|
+
# pathout=stackpath[:-4]+'_FFT.tif'
|
|
515
|
+
# stack =tifffile.imread(stackpath)
|
|
516
|
+
|
|
517
|
+
# nFrames, h,w = stack.shape
|
|
518
|
+
# print("------------------------------------------")
|
|
519
|
+
# print("Getting FFT to the stack:")
|
|
520
|
+
# with tifffile.TiffWriter(pathout,bigtiff=True) as tif:
|
|
521
|
+
# for i in tqdm.tqdm(range(nFrames)):
|
|
522
|
+
# fr=stack[i]
|
|
523
|
+
# fft=Diff.getFFT(fr)
|
|
524
|
+
# if ndfilersize!=0:
|
|
525
|
+
# fft = ndimage.maximum_filter(fft, size=ndfilersize, mode='wrap')
|
|
526
|
+
# fft_image=cv2.normalize(fft, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8U)
|
|
527
|
+
# tif.write(fft_image, contiguous=True)
|
|
528
|
+
# IO.tiff2avi(pathout,fps=15)
|
|
529
|
+
|
|
530
|
+
# print("Conversion done!")
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"""
|
|
3
3
|
in-situ TEM Toolbox - Input Output
|
|
4
4
|
|
|
5
|
-
Assembles of functions related to movie input output
|
|
5
|
+
Assembles of functions related to movie input output and format conversion.
|
|
6
6
|
|
|
7
7
|
Example:
|
|
8
8
|
|
|
@@ -10,7 +10,7 @@ Example:
|
|
|
10
10
|
IO.f2tif(path,1)
|
|
11
11
|
|
|
12
12
|
Created on Tue Jun 11 10:25:25 2019
|
|
13
|
-
@author:
|
|
13
|
+
@author: Meng Li
|
|
14
14
|
Update 20200303:
|
|
15
15
|
Add stroke to scalebar and text
|
|
16
16
|
"""
|
|
@@ -20,7 +20,7 @@ import cv2
|
|
|
20
20
|
import tifffile
|
|
21
21
|
import tqdm #not necessary just provides a progress bar and timer
|
|
22
22
|
import numpy as np
|
|
23
|
-
|
|
23
|
+
import moviepy.editor as mp
|
|
24
24
|
|
|
25
25
|
def tiff2mp4(path,fps):
|
|
26
26
|
"""
|
|
@@ -154,12 +154,12 @@ def folder2tif(path,isGray=True):
|
|
|
154
154
|
Input: path: folder path
|
|
155
155
|
Output: tif stack with the same name as the folder in the parent folder.
|
|
156
156
|
"""
|
|
157
|
+
import os
|
|
157
158
|
import tifffile
|
|
158
159
|
img_name=os.listdir(path)
|
|
159
160
|
nFrames= len(img_name)
|
|
160
161
|
pathout=path+'.tif'
|
|
161
|
-
|
|
162
|
-
video_out.write(img)
|
|
162
|
+
|
|
163
163
|
|
|
164
164
|
with tifffile.TiffWriter(pathout,bigtiff=True) as tif:
|
|
165
165
|
for i in tqdm.tqdm(range(nFrames)):
|
|
@@ -180,6 +180,7 @@ def f2gif(path,fps):
|
|
|
180
180
|
|
|
181
181
|
Output: file in the same folder named '..._cv.mp4'
|
|
182
182
|
"""
|
|
183
|
+
|
|
183
184
|
print("==============================================")
|
|
184
185
|
print("Convert file to GIF!")
|
|
185
186
|
pathout = path[:-4]+'_'+str(fps)+'.gif'
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: insituTEM
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A toolbox for processing in situ TEM data
|
|
5
|
+
Requires-Python: >=3.9
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: numpy
|
|
8
|
+
Requires-Dist: scipy
|
|
9
|
+
Requires-Dist: matplotlib
|
|
10
|
+
Requires-Dist: pandas
|
|
11
|
+
Requires-Dist: tifffile
|
|
12
|
+
Requires-Dist: tqdm
|
|
13
|
+
Requires-Dist: opencv-python
|
|
14
|
+
Requires-Dist: pillow
|
|
15
|
+
Requires-Dist: scikit-image
|
|
16
|
+
Requires-Dist: moviepy
|
|
17
|
+
Requires-Dist: ncempy
|
|
18
|
+
Requires-Dist: easygui
|
|
19
|
+
Requires-Dist: pystackreg
|
|
20
|
+
Requires-Dist: pyside6
|
|
21
|
+
|
|
22
|
+
# insituTEM
|
|
23
|
+
|
|
24
|
+
Tools for preprocessing in situ TEM movies.
|
|
25
|
+
|
|
26
|
+
Author: Meng Li (mona.mengli@gmail.com; mli4@bnl.gov)
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
```bash
|
|
30
|
+
pip install insitutem-toolbox
|
|
31
|
+
```
|
|
32
|
+
## Module descriptions
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
### `insitu_IO`
|
|
36
|
+
|
|
37
|
+
in-situ TEM Toolbox - Input Output
|
|
38
|
+
|
|
39
|
+
Assembles of functions related to movie input output
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
### `insitu_Preprocess`
|
|
43
|
+
|
|
44
|
+
in-situ TEM Toolbox - PreProcess
|
|
45
|
+
|
|
46
|
+
Assembles of functions related to movie preprocess
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
### `insitu_alignment`
|
|
50
|
+
|
|
51
|
+
in-situ TEM Toolbox - Movie alignment
|
|
52
|
+
|
|
53
|
+
Assembles of functions related to movie alignment
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
### `insitu_DENS`
|
|
58
|
+
|
|
59
|
+
in-situ TEM Toolbox - DENS holder data process
|
|
60
|
+
|
|
61
|
+
Assembles of functions related to process raw data by DENS holders
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
### `insitu_DP`
|
|
66
|
+
|
|
67
|
+
in-situ TEM Toolbox - Image Data process
|
|
68
|
+
|
|
69
|
+
Assembles of functions related to movie data analysis such as plots
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
### `insitu_Diff`
|
|
74
|
+
|
|
75
|
+
in-situ TEM Toolbox - Diffraction pattern analysis
|
|
76
|
+
|
|
77
|
+
Assembles of functions related to process FFT and diffraction patterns
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
### `insitu_EMraw`
|
|
82
|
+
|
|
83
|
+
in-situ TEM Toolbox - TEM raw data conversion
|
|
84
|
+
|
|
85
|
+
Assembles of functions related to read and process raw dm4, dm3 or FEI TIA or Ceta datas.
|
insitutem-0.1.8/PKG-INFO
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: insituTEM
|
|
3
|
-
Version: 0.1.8
|
|
4
|
-
Summary: A toolbox for processing in situ TEM data
|
|
5
|
-
Requires-Python: >=3.9
|
|
6
|
-
Description-Content-Type: text/markdown
|
|
7
|
-
Requires-Dist: numpy
|
|
8
|
-
Requires-Dist: scipy
|
|
9
|
-
Requires-Dist: matplotlib
|
|
10
|
-
Requires-Dist: pandas
|
|
11
|
-
Requires-Dist: tifffile
|
|
12
|
-
Requires-Dist: tqdm
|
|
13
|
-
Requires-Dist: opencv-python
|
|
14
|
-
Requires-Dist: pillow
|
|
15
|
-
Requires-Dist: scikit-image
|
|
16
|
-
Requires-Dist: moviepy
|
|
17
|
-
Requires-Dist: ncempy
|
|
18
|
-
Requires-Dist: easygui
|
|
19
|
-
Requires-Dist: pystackreg
|
|
20
|
-
Requires-Dist: pyside6
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: insituTEM
|
|
3
|
-
Version: 0.1.8
|
|
4
|
-
Summary: A toolbox for processing in situ TEM data
|
|
5
|
-
Requires-Python: >=3.9
|
|
6
|
-
Description-Content-Type: text/markdown
|
|
7
|
-
Requires-Dist: numpy
|
|
8
|
-
Requires-Dist: scipy
|
|
9
|
-
Requires-Dist: matplotlib
|
|
10
|
-
Requires-Dist: pandas
|
|
11
|
-
Requires-Dist: tifffile
|
|
12
|
-
Requires-Dist: tqdm
|
|
13
|
-
Requires-Dist: opencv-python
|
|
14
|
-
Requires-Dist: pillow
|
|
15
|
-
Requires-Dist: scikit-image
|
|
16
|
-
Requires-Dist: moviepy
|
|
17
|
-
Requires-Dist: ncempy
|
|
18
|
-
Requires-Dist: easygui
|
|
19
|
-
Requires-Dist: pystackreg
|
|
20
|
-
Requires-Dist: pyside6
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|