NSFopen 2.2.2__tar.gz → 2.2.4__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.
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/__init__.py +9 -5
- nsfopen-2.2.4/NSFopen/_version.py +1 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Force_Spectroscopy/Force_Spectroscopy.py +40 -23
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/process/__init__.py +2 -1
- nsfopen-2.2.4/NSFopen/process/colormaps.py +71 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/process/process.py +220 -187
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/read/read.py +3 -6
- {nsfopen-2.2.2 → nsfopen-2.2.4/NSFopen.egg-info}/PKG-INFO +1 -1
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen.egg-info/SOURCES.txt +1 -0
- {nsfopen-2.2.2/NSFopen.egg-info → nsfopen-2.2.4}/PKG-INFO +1 -1
- nsfopen-2.2.2/NSFopen/_version.py +0 -1
- {nsfopen-2.2.2 → nsfopen-2.2.4}/LICENSE +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Calculate_Roughness/Calculate_Roughness.html +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Calculate_Roughness/Calculate_Roughness.ipynb +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Calculate_Roughness/Calculate_Roughness.py +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Calculate_Roughness/__pycache__/Calculate_Roughness.cpython-310.pyc +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Calculate_Roughness/sapphire.nid +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Force_Spectroscopy/Force_Spectroscopy.html +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Force_Spectroscopy/Force_Spectroscopy.ipynb +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Force_Spectroscopy/spectroscopy.nid +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Lateral_Force/Lateral Force Processing.html +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Lateral_Force/Lateral Force Processing.ipynb +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Lateral_Force/Lateral Force Processing.py +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Lateral_Force/SBS-PMMA.nid +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Plane_Removal/Plane_Removal.html +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Plane_Removal/Plane_Removal.ipynb +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Plane_Removal/Plane_Removal.py +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Plane_Removal/circles.nid +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Plane_Removal/circles_holes.nid +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Plane_Removal/grid.nid +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Plane_Removal/squares_holes.nid +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Plotting_Data/MoS2.nid +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Plotting_Data/Plotting Data.html +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Plotting_Data/Plotting Data.ipynb +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Plotting_Data/Plotting Data.py +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Sharpen_Image/Sharpen Image.html +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Sharpen_Image/Sharpen Image.ipynb +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Sharpen_Image/Sharpen Image.py +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Sharpen_Image/grid.nid +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Sharpen_Image/img.jpg +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Spring_Constant/Spring_Constant.html +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Spring_Constant/Spring_Constant.ipynb +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Spring_Constant/Spring_Constant.py +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Spring_Constant/__pycache__/Spring_Constant.cpython-310.pyc +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Spring_Constant/__pycache__/__init__.cpython-310.pyc +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Spring_Constant/sader.py +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Spring_Constant/thermal.nid +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Spring_Constant/thermal.png +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/read/__init__.py +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/read/read_beta.py +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen.egg-info/dependency_links.txt +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen.egg-info/entry_points.txt +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen.egg-info/not-zip-safe +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen.egg-info/requires.txt +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen.egg-info/top_level.txt +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/README.md +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/pyproject.toml +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/setup.cfg +0 -0
- {nsfopen-2.2.2 → nsfopen-2.2.4}/setup.py +0 -0
|
@@ -4,22 +4,26 @@ License - MIT"""
|
|
|
4
4
|
|
|
5
5
|
import os
|
|
6
6
|
import pathlib
|
|
7
|
-
from .
|
|
7
|
+
from ._version import __version__
|
|
8
|
+
|
|
9
|
+
from .read import read
|
|
10
|
+
|
|
11
|
+
# from . process import process
|
|
8
12
|
|
|
9
|
-
from . read import read
|
|
10
|
-
from . process import process
|
|
11
13
|
|
|
12
14
|
def package_path() -> pathlib.Path:
|
|
13
15
|
return pathlib.Path(os.path.dirname(os.path.abspath(__file__)))
|
|
14
16
|
|
|
17
|
+
|
|
15
18
|
def example_path() -> pathlib.Path:
|
|
16
19
|
return package_path() / "example"
|
|
17
20
|
|
|
18
|
-
|
|
21
|
+
|
|
22
|
+
def help():
|
|
19
23
|
print("Nanosurf NID and NHF file reader:")
|
|
20
24
|
print("-------------------------------")
|
|
21
25
|
print(f"Installed version: {__version__}")
|
|
22
26
|
print("\nExamples are stored here:")
|
|
23
27
|
print(example_path())
|
|
24
28
|
for example in os.listdir(example_path()):
|
|
25
|
-
print(f" {example}")
|
|
29
|
+
print(f" {example}")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.2.4"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env python
|
|
2
2
|
# coding: utf-8
|
|
3
3
|
|
|
4
|
-
# ## This script demonstrates how to open a Nanosurf Force Spectroscopy map and analyze the data using the DMT contact mechanics model
|
|
4
|
+
# ## This script demonstrates how to open a Nanosurf Force Spectroscopy map and analyze the data using the DMT contact mechanics model
|
|
5
5
|
|
|
6
6
|
# In[1]:
|
|
7
7
|
|
|
@@ -16,23 +16,27 @@ from scipy.optimize import curve_fit
|
|
|
16
16
|
|
|
17
17
|
from glob import glob
|
|
18
18
|
|
|
19
|
-
filename =
|
|
20
|
-
filename_large =
|
|
19
|
+
filename = "spectroscopy.nid"
|
|
20
|
+
filename_large = "spectroscopy_large.nid"
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
# In[2]:
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
# If USE_LARGE_MAP is True, then it will use the larger force-curve map, downloading if not already locally available
|
|
26
|
+
# If USE_LARGE_MAP is True, then it will use the larger force-curve map, downloading if not already locally available
|
|
27
27
|
USE_LARGE_MAP = False
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
# In[3]:
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
if USE_LARGE_MAP and filename_large not in glob(
|
|
33
|
+
if USE_LARGE_MAP and filename_large not in glob("*nid"):
|
|
34
34
|
import urllib.request
|
|
35
|
-
|
|
35
|
+
|
|
36
|
+
urllib.request.urlretrieve(
|
|
37
|
+
"https://www.dropbox.com/s/knzuh588g0uvjfi/spectroscopy_large.nid?dl=1",
|
|
38
|
+
filename_large,
|
|
39
|
+
)
|
|
36
40
|
filename = filename_large
|
|
37
41
|
elif USE_LARGE_MAP:
|
|
38
42
|
filename = filename_large
|
|
@@ -47,20 +51,28 @@ data = afm.data
|
|
|
47
51
|
param = afm.param
|
|
48
52
|
|
|
49
53
|
# probe
|
|
50
|
-
k = param.Tip.Prop0[
|
|
51
|
-
sens = param.Tip.Sensitivity[
|
|
54
|
+
k = param.Tip.Prop0["Value"] # spring constant
|
|
55
|
+
sens = param.Tip.Sensitivity["Value"] # deflection sensitivity (if needed)
|
|
52
56
|
|
|
53
57
|
radius = 10e-9 # tip radius
|
|
54
58
|
nu = 0.35 # Poisson ratio (between 0.35 and 0.5)
|
|
55
59
|
|
|
56
|
-
|
|
57
|
-
|
|
60
|
+
direction = "Backward" # Forward or Backward modulation
|
|
61
|
+
|
|
62
|
+
spec_backward = data["Spec"][
|
|
63
|
+
direction
|
|
64
|
+
] # for DMT model we will use backward modulation
|
|
65
|
+
d = spec_backward["Deflection"] # force channel
|
|
58
66
|
|
|
59
67
|
z_signal = list(spec_backward.index)
|
|
60
|
-
z_chans = [
|
|
68
|
+
z_chans = [
|
|
69
|
+
"Z-Axis Sensor",
|
|
70
|
+
"Z-AxisSensor",
|
|
71
|
+
"Z-Axis",
|
|
72
|
+
] # depending on system, Z-Axis channel may be labeled differently
|
|
61
73
|
available_chan = [i for i in z_signal if i in z_chans][0]
|
|
62
74
|
|
|
63
|
-
z = data[
|
|
75
|
+
z = data["Spec"][direction][available_chan] # Z-axis data
|
|
64
76
|
|
|
65
77
|
sz = int(param.Spec.maps[4]) # Map size
|
|
66
78
|
|
|
@@ -72,6 +84,7 @@ extent = param.Spec.maps[:4] # X and Y physical dimensions of map
|
|
|
72
84
|
|
|
73
85
|
## Functions
|
|
74
86
|
|
|
87
|
+
|
|
75
88
|
# corrects for any baseline tilt
|
|
76
89
|
def baseline_correct(x, y, degree=1, start=0, end=0.5):
|
|
77
90
|
i0 = int(np.floor(len(x) * start))
|
|
@@ -90,14 +103,15 @@ def baseline_correct(x, y, degree=1, start=0, end=0.5):
|
|
|
90
103
|
def DMT(x, *param):
|
|
91
104
|
elast, depth, wadh = param
|
|
92
105
|
|
|
93
|
-
scale = 4
|
|
106
|
+
scale = 4.0 / 3.0 * elast * np.sqrt(radius) / (1 - nu**2)
|
|
94
107
|
x = x - depth
|
|
95
|
-
y = scale * np.sign(x) * np.abs(x)**(3
|
|
108
|
+
y = scale * np.sign(x) * np.abs(x) ** (3.0 / 2.0) - wadh
|
|
96
109
|
return y
|
|
97
110
|
|
|
98
111
|
|
|
99
112
|
def DMTfit(*args, maxForce=np.Inf):
|
|
100
113
|
import time
|
|
114
|
+
|
|
101
115
|
t = time.time()
|
|
102
116
|
# args are: [separation, load (force)]
|
|
103
117
|
if not isinstance(args[0], list):
|
|
@@ -108,7 +122,7 @@ def DMTfit(*args, maxForce=np.Inf):
|
|
|
108
122
|
# x = x - y / spring_constant # separation
|
|
109
123
|
lenY = int(np.floor(len(y) * 0.8))
|
|
110
124
|
a = min(y[lenY:]) # adhesion
|
|
111
|
-
|
|
125
|
+
|
|
112
126
|
i0 = np.where(y == a)[0][0] # contact point estimator index
|
|
113
127
|
i1 = np.where(y > maxForce)[0] # max force index
|
|
114
128
|
|
|
@@ -118,13 +132,15 @@ def DMTfit(*args, maxForce=np.Inf):
|
|
|
118
132
|
i1 = i1[0]
|
|
119
133
|
|
|
120
134
|
try:
|
|
121
|
-
coeff, var_matrix = curve_fit(
|
|
135
|
+
coeff, var_matrix = curve_fit(
|
|
136
|
+
DMT, x[i0:i1], y[i0:i1], p0=[1e9, x[i0], -a]
|
|
137
|
+
)
|
|
122
138
|
except RuntimeError:
|
|
123
139
|
E.append(np.nan)
|
|
124
140
|
else:
|
|
125
141
|
E.append(max(coeff[0], 0))
|
|
126
142
|
|
|
127
|
-
print(
|
|
143
|
+
print("Elapsed Time: %3.2f sec\n" % (time.time() - t))
|
|
128
144
|
return np.array(E), (coeff, i0, i1)
|
|
129
145
|
|
|
130
146
|
|
|
@@ -135,7 +151,7 @@ def DMTfit(*args, maxForce=np.Inf):
|
|
|
135
151
|
dd = [baseline_correct(z_, d_, start=0.5, end=0.8) for z_, d_ in zip(z, d)]
|
|
136
152
|
|
|
137
153
|
# separation
|
|
138
|
-
zz = [zz - dd/k for dd, zz in zip(dd, z)]
|
|
154
|
+
zz = [zz - dd / k for dd, zz in zip(dd, z)]
|
|
139
155
|
|
|
140
156
|
# elastic modulus
|
|
141
157
|
Eb, _ = DMTfit(zz, dd)
|
|
@@ -159,14 +175,16 @@ Adh = toMap(adh, sz)
|
|
|
159
175
|
# In[7]:
|
|
160
176
|
|
|
161
177
|
|
|
162
|
-
fig, ax = plt.subplots(
|
|
178
|
+
fig, ax = plt.subplots(
|
|
179
|
+
2, 2, figsize=(10, 8), gridspec_kw={"height_ratios": [2, 1]}, dpi=300
|
|
180
|
+
)
|
|
163
181
|
fig.tight_layout(w_pad=8.0, h_pad=1.0)
|
|
164
182
|
|
|
165
183
|
im = ax.copy()
|
|
166
184
|
|
|
167
185
|
cmap = "afmhot" # colormap
|
|
168
|
-
xlbl =
|
|
169
|
-
ylbl =
|
|
186
|
+
xlbl = "X [$\mu$m]"
|
|
187
|
+
ylbl = "Y [$\mu$m]"
|
|
170
188
|
zlbl = ["Young's Modulus [GPa]", "Adhesion [nN]"]
|
|
171
189
|
|
|
172
190
|
im[0, 0] = ax[0, 0].imshow(Ebim)
|
|
@@ -182,8 +200,7 @@ for i in range(2):
|
|
|
182
200
|
cb.set_label(zlbl[i])
|
|
183
201
|
|
|
184
202
|
ax[0, i].set(xlabel=xlbl, ylabel=ylbl)
|
|
185
|
-
ax[1, i].set(xlabel=zlbl[i], ylabel=
|
|
203
|
+
ax[1, i].set(xlabel=zlbl[i], ylabel="Counts")
|
|
186
204
|
|
|
187
205
|
|
|
188
206
|
plt.show()
|
|
189
|
-
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created on Thu May 23 13:04:53 2024
|
|
4
|
+
|
|
5
|
+
@author: nelson
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
import pandas as pd
|
|
10
|
+
import os
|
|
11
|
+
|
|
12
|
+
from matplotlib.colors import LinearSegmentedColormap
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class colors:
|
|
16
|
+
def __init__(self, name=None, gwy_dir=None, **kwargs):
|
|
17
|
+
self.name = name
|
|
18
|
+
self.gwy_dir = gwy_dir
|
|
19
|
+
if not gwy_dir:
|
|
20
|
+
self.gwy_dir = (
|
|
21
|
+
"C:\\Program Files\\Gwyddion\\share\\gwyddion\\gradients\\"
|
|
22
|
+
)
|
|
23
|
+
custom = ["BlueBlackRed"]
|
|
24
|
+
gwy_list = os.listdir(self.gwy_dir)
|
|
25
|
+
|
|
26
|
+
cmaps = {}
|
|
27
|
+
cmaps["Custom"] = custom
|
|
28
|
+
cmaps["Gwyddion"] = gwy_list
|
|
29
|
+
|
|
30
|
+
if name in gwy_list:
|
|
31
|
+
cmap = self.gwy_cmap()
|
|
32
|
+
elif name in custom:
|
|
33
|
+
cmap = self.custom()
|
|
34
|
+
else:
|
|
35
|
+
print("Name Not Found\n")
|
|
36
|
+
print("Use one of the following choices:\n")
|
|
37
|
+
print({x for v in cmaps.values() for x in v})
|
|
38
|
+
cmap = []
|
|
39
|
+
self.cmap = cmap
|
|
40
|
+
self.cmap_list = cmaps
|
|
41
|
+
|
|
42
|
+
def gwy_cmap(self):
|
|
43
|
+
cmap = pd.read_csv(
|
|
44
|
+
self.gwy_dir + self.name,
|
|
45
|
+
sep=" ",
|
|
46
|
+
header=None,
|
|
47
|
+
skiprows=1,
|
|
48
|
+
index_col=0,
|
|
49
|
+
)
|
|
50
|
+
nodes = cmap.index.values
|
|
51
|
+
colors = cmap.values
|
|
52
|
+
|
|
53
|
+
return LinearSegmentedColormap.from_list(
|
|
54
|
+
self.name, list(zip(nodes, colors))
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
def custom(self):
|
|
58
|
+
if self.name == "BlueBlackRed":
|
|
59
|
+
# Blue-Black-Red
|
|
60
|
+
start = np.array(
|
|
61
|
+
[0.6196078431372549, 0.792156862745098, 0.8823529411764706]
|
|
62
|
+
)
|
|
63
|
+
mid = np.array([0, 0, 0])
|
|
64
|
+
end = np.array(
|
|
65
|
+
[0.9882352941176471, 0.5725490196078431, 0.4470588235294118]
|
|
66
|
+
)
|
|
67
|
+
nodes = [0, 0.5, 1]
|
|
68
|
+
|
|
69
|
+
return LinearSegmentedColormap.from_list(
|
|
70
|
+
self.name, list(zip(nodes, [start, mid, end]))
|
|
71
|
+
)
|
|
@@ -11,7 +11,7 @@ import matplotlib.pyplot as plt
|
|
|
11
11
|
from mpl_toolkits.mplot3d import Axes3D
|
|
12
12
|
from matplotlib.ticker import LinearLocator, FormatStrFormatter
|
|
13
13
|
from matplotlib import cm
|
|
14
|
-
from scipy.ndimage import gaussian_filter,median_filter
|
|
14
|
+
from scipy.ndimage import gaussian_filter, median_filter
|
|
15
15
|
from sklearn.impute import KNNImputer
|
|
16
16
|
from scipy import stats
|
|
17
17
|
|
|
@@ -20,24 +20,26 @@ import scipy.stats as ss
|
|
|
20
20
|
import os, sys
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
class process
|
|
23
|
+
class process:
|
|
24
24
|
def __init__(self, filename):
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
afm = read(filename)
|
|
27
27
|
self.data = afm.data
|
|
28
28
|
self.param = afm.param
|
|
29
29
|
|
|
30
|
-
def flatten(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
def flatten(
|
|
31
|
+
self,
|
|
32
|
+
order=1,
|
|
33
|
+
direction="Forward",
|
|
34
|
+
channel="Z-Axis",
|
|
35
|
+
mask=[],
|
|
36
|
+
inplace=True,
|
|
37
|
+
):
|
|
38
|
+
"""Flattens an image using a nth-order polynomial
|
|
39
|
+
|
|
38
40
|
Parameters
|
|
39
41
|
----------
|
|
40
|
-
|
|
42
|
+
|
|
41
43
|
order : int, default 1
|
|
42
44
|
Order of the polynomial
|
|
43
45
|
direction : {'Forward','Backward'}, defulat 'Forward'
|
|
@@ -47,14 +49,14 @@ class process():
|
|
|
47
49
|
mask : boolean array
|
|
48
50
|
Mask where True values are ignored in the input array
|
|
49
51
|
inplace : boolean, default True
|
|
50
|
-
|
|
52
|
+
|
|
51
53
|
Return
|
|
52
54
|
------
|
|
53
55
|
array or None
|
|
54
56
|
Flattened image or None if inplace=True
|
|
55
|
-
|
|
57
|
+
|
|
56
58
|
"""
|
|
57
|
-
data_out = self.data[
|
|
59
|
+
data_out = self.data["Image"][direction][channel]
|
|
58
60
|
data_in = data_out.copy()
|
|
59
61
|
data_in = np.array(data_in, dtype=float)
|
|
60
62
|
x = np.arange(data_in.shape[1])
|
|
@@ -67,83 +69,83 @@ class process():
|
|
|
67
69
|
y = np.polyval(p, x)
|
|
68
70
|
data_out[idx] = out - y
|
|
69
71
|
if inplace:
|
|
70
|
-
self.data[
|
|
72
|
+
self.data["Image"].loc[direction, channel] = data_out
|
|
71
73
|
return None
|
|
72
74
|
else:
|
|
73
75
|
return data_out
|
|
74
|
-
|
|
75
|
-
def plane_level(self,
|
|
76
|
-
|
|
77
|
-
channel='Z-Axis',
|
|
78
|
-
inplace=True):
|
|
79
|
-
data_out = self.data['Image'][direction][channel]
|
|
76
|
+
|
|
77
|
+
def plane_level(self, direction="Forward", channel="Z-Axis", inplace=True):
|
|
78
|
+
data_out = self.data["Image"][direction][channel]
|
|
80
79
|
data_in = data_out.copy()
|
|
81
80
|
data_in = np.array(data_in, dtype=float)
|
|
82
|
-
|
|
81
|
+
|
|
83
82
|
# x_size = self.param.X.range[0] * 1e6
|
|
84
83
|
# y_size = self.param.Y.range[0] * 1e6
|
|
85
84
|
|
|
86
85
|
# xs = np.linspace(0,x_size,data_in.shape[0])
|
|
87
86
|
# ys = np.linspace(0,y_size,data_in.shape[1])
|
|
88
|
-
|
|
89
|
-
xs = np.arange(0,data_in.shape[0])
|
|
90
|
-
ys = np.arange(0,data_in.shape[1])
|
|
91
|
-
xs,ys = np.meshgrid(xs,ys)
|
|
87
|
+
|
|
88
|
+
xs = np.arange(0, data_in.shape[0])
|
|
89
|
+
ys = np.arange(0, data_in.shape[1])
|
|
90
|
+
xs, ys = np.meshgrid(xs, ys)
|
|
92
91
|
ones = np.ones(xs.shape)
|
|
93
92
|
|
|
94
|
-
reshape =
|
|
93
|
+
reshape = lambda x: np.reshape(x, (len(x) ** 2, 1))
|
|
95
94
|
|
|
96
|
-
A = np.matrix(np.hstack([reshape(xs),reshape(ys),reshape(ones)]))
|
|
95
|
+
A = np.matrix(np.hstack([reshape(xs), reshape(ys), reshape(ones)]))
|
|
97
96
|
b = np.matrix(reshape(data_in))
|
|
98
97
|
|
|
99
98
|
fit = (A.T * A).I * A.T * b
|
|
100
|
-
plane = np.reshape(A*fit,data_in.shape)
|
|
101
|
-
data_out-=plane
|
|
99
|
+
plane = np.reshape(A * fit, data_in.shape)
|
|
100
|
+
data_out -= plane
|
|
102
101
|
if inplace:
|
|
103
|
-
self.data[
|
|
102
|
+
self.data["Image"].loc[direction, channel] = data_out
|
|
104
103
|
return None
|
|
105
104
|
else:
|
|
106
105
|
return data_out
|
|
107
|
-
|
|
108
|
-
def remove_outliers(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
106
|
+
|
|
107
|
+
def remove_outliers(
|
|
108
|
+
self,
|
|
109
|
+
direction="Forward",
|
|
110
|
+
channel="Z-Axis",
|
|
111
|
+
q=0.01,
|
|
112
|
+
neighbors=5,
|
|
113
|
+
inplace=True,
|
|
114
|
+
):
|
|
115
|
+
data_out = self.data["Image"][direction][channel]
|
|
115
116
|
data_in = data_out.copy()
|
|
116
117
|
data_in = np.array(data_in, dtype=float)
|
|
117
|
-
|
|
118
|
-
if isinstance(q,list):
|
|
119
|
-
q0,q1=q
|
|
118
|
+
|
|
119
|
+
if isinstance(q, list):
|
|
120
|
+
q0, q1 = q
|
|
120
121
|
else:
|
|
121
|
-
q0=q1=q
|
|
122
|
-
|
|
123
|
-
value = np.quantile(data_in,q=[q0,1-q1])
|
|
124
|
-
mask = (data_in<value[0]) | (data_in>value[1])
|
|
125
|
-
data_in[mask]=np.nan
|
|
122
|
+
q0 = q1 = q
|
|
123
|
+
|
|
124
|
+
value = np.quantile(data_in, q=[q0, 1 - q1])
|
|
125
|
+
mask = (data_in < value[0]) | (data_in > value[1])
|
|
126
|
+
data_in[mask] = np.nan
|
|
126
127
|
|
|
127
|
-
data_out=KNNImputer(n_neighbors=neighbors).fit_transform(data_in)
|
|
128
|
+
data_out = KNNImputer(n_neighbors=neighbors).fit_transform(data_in)
|
|
128
129
|
if inplace:
|
|
129
|
-
self.data[
|
|
130
|
+
self.data["Image"].loc[direction, channel] = data_out
|
|
130
131
|
return None
|
|
131
132
|
else:
|
|
132
133
|
return data_out
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
134
|
+
|
|
135
|
+
def denoise(
|
|
136
|
+
self,
|
|
137
|
+
direction="Forward",
|
|
138
|
+
channel="Z-Axis",
|
|
139
|
+
function="gaussian",
|
|
140
|
+
size=5,
|
|
141
|
+
inplace=True,
|
|
142
|
+
**kwargs,
|
|
143
|
+
):
|
|
144
|
+
"""Applies a 2D filter to an image.
|
|
145
|
+
|
|
144
146
|
Parameters
|
|
145
147
|
----------
|
|
146
|
-
|
|
148
|
+
|
|
147
149
|
direction: {'Forward','Backward'}, default 'Forward'
|
|
148
150
|
Scan direction to use
|
|
149
151
|
channel: string, default 'Z-Axis'
|
|
@@ -156,41 +158,42 @@ class process():
|
|
|
156
158
|
Whether to modify the input array or create new one
|
|
157
159
|
**kwargs:
|
|
158
160
|
Passed to filters
|
|
159
|
-
|
|
161
|
+
|
|
160
162
|
Return
|
|
161
163
|
------
|
|
162
164
|
array or None
|
|
163
165
|
Filtered image or None if inplace=True
|
|
164
|
-
|
|
166
|
+
|
|
165
167
|
"""
|
|
166
|
-
data_in = self.data[
|
|
167
|
-
if function ==
|
|
168
|
+
data_in = self.data["Image"][direction][channel]
|
|
169
|
+
if function == "median":
|
|
168
170
|
data_out = median_filter(data_in, size=size, **kwargs)
|
|
169
171
|
else:
|
|
170
172
|
data_out = gaussian_filter(data_in, sigma=size, **kwargs)
|
|
171
173
|
if inplace:
|
|
172
|
-
self.data[
|
|
174
|
+
self.data["Image"].loc[direction, channel] = data_out
|
|
173
175
|
return None
|
|
174
176
|
else:
|
|
175
177
|
return data_out
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
178
|
+
|
|
179
|
+
def image(
|
|
180
|
+
self,
|
|
181
|
+
direction="Forward",
|
|
182
|
+
channel="Z-Axis",
|
|
183
|
+
scale=1e9,
|
|
184
|
+
cmap=cm.afmhot,
|
|
185
|
+
cbar=None,
|
|
186
|
+
fontsize=10,
|
|
187
|
+
scalebar=None,
|
|
188
|
+
theme="light",
|
|
189
|
+
title="XXX",
|
|
190
|
+
**kwargs,
|
|
191
|
+
):
|
|
192
|
+
"""Plots an AFM image
|
|
193
|
+
|
|
191
194
|
Parameters
|
|
192
195
|
----------
|
|
193
|
-
|
|
196
|
+
|
|
194
197
|
direction: {'Forward','Backward'}, default 'Forward'
|
|
195
198
|
Scan direction to use
|
|
196
199
|
channel: string, default 'Z-Axis'
|
|
@@ -211,126 +214,142 @@ class process():
|
|
|
211
214
|
Use either 'light' or 'dark' theme
|
|
212
215
|
**kwargs:
|
|
213
216
|
Passed to matplotlib imshow
|
|
214
|
-
|
|
217
|
+
|
|
215
218
|
Return
|
|
216
219
|
------
|
|
217
220
|
figure
|
|
218
221
|
matplotlib figure object
|
|
219
|
-
|
|
222
|
+
|
|
220
223
|
"""
|
|
221
|
-
d = np.array(
|
|
222
|
-
|
|
224
|
+
d = np.array(
|
|
225
|
+
self.data["Image"][direction][channel] * scale, dtype=float
|
|
226
|
+
)
|
|
227
|
+
if hasattr(self.param, "X"):
|
|
223
228
|
x = self.param.X.range[0] * 1e6
|
|
224
229
|
y = self.param.Y.range[0] * 1e6
|
|
225
|
-
|
|
230
|
+
elif hasattr(self.param, "image_size_x"):
|
|
226
231
|
x = self.param.image_size_x * 1e6
|
|
227
232
|
y = self.param.image_size_y * 1e6
|
|
228
|
-
|
|
233
|
+
else:
|
|
234
|
+
x, y = self.param.rect_axis_range
|
|
235
|
+
x *= 1e6
|
|
236
|
+
y *= 1e6
|
|
237
|
+
|
|
229
238
|
fig = plt.figure(dpi=300)
|
|
230
239
|
|
|
231
|
-
if theme==
|
|
232
|
-
color =
|
|
240
|
+
if theme == "light":
|
|
241
|
+
color = "k"
|
|
233
242
|
else:
|
|
234
|
-
color=
|
|
235
|
-
fig.patch.set_facecolor(
|
|
243
|
+
color = "w"
|
|
244
|
+
fig.patch.set_facecolor("k")
|
|
236
245
|
|
|
237
|
-
im = plt.imshow(
|
|
246
|
+
im = plt.imshow(
|
|
247
|
+
d, extent=(0, x, 0, y), cmap=cmap, origin="lower", **kwargs
|
|
248
|
+
)
|
|
238
249
|
|
|
239
250
|
for spine in im.axes.spines.values():
|
|
240
|
-
spine.set_edgecolor(color)
|
|
251
|
+
spine.set_edgecolor(color)
|
|
241
252
|
|
|
242
253
|
if scalebar:
|
|
243
|
-
if isinstance(scalebar,dict):
|
|
244
|
-
dx = scalebar[
|
|
245
|
-
c = scalebar[
|
|
254
|
+
if isinstance(scalebar, dict):
|
|
255
|
+
dx = scalebar["length"]
|
|
256
|
+
c = scalebar["color"]
|
|
246
257
|
else:
|
|
247
258
|
dx = np.round(x / 5)
|
|
248
|
-
c =
|
|
259
|
+
c = "k"
|
|
249
260
|
|
|
250
261
|
pad = y * 0.05
|
|
251
262
|
plt.plot([x - dx - pad, x - pad], [pad, pad], linewidth=5, color=c)
|
|
252
|
-
txt = plt.text(
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
263
|
+
txt = plt.text(
|
|
264
|
+
x - pad - dx / 2,
|
|
265
|
+
pad + x * 0.03,
|
|
266
|
+
f"%i $\mu$m" % dx,
|
|
267
|
+
horizontalalignment="center",
|
|
268
|
+
fontsize=fontsize,
|
|
269
|
+
color=c,
|
|
270
|
+
)
|
|
271
|
+
if dx < 1:
|
|
272
|
+
txt.set_text(f"%i nm" % (dx * 1e3))
|
|
258
273
|
plt.xticks([])
|
|
259
274
|
plt.yticks([])
|
|
260
275
|
else:
|
|
261
|
-
plt.xlabel(
|
|
262
|
-
plt.ylabel(
|
|
276
|
+
plt.xlabel("X $[\mu{}$m]", fontsize=fontsize, color=color)
|
|
277
|
+
plt.ylabel("Y $[\mu{}$m]", fontsize=fontsize, color=color)
|
|
263
278
|
plt.xticks(fontsize=fontsize, color=color)
|
|
264
279
|
plt.yticks(fontsize=fontsize, color=color)
|
|
265
280
|
im.axes.tick_params(color=color, labelcolor=color)
|
|
266
|
-
if title==
|
|
267
|
-
title = f
|
|
268
|
-
plt.title(title,fontsize=fontsize, color=color)
|
|
281
|
+
if title == "XXX":
|
|
282
|
+
title = f"{channel} - {direction}"
|
|
283
|
+
plt.title(title, fontsize=fontsize, color=color)
|
|
269
284
|
if cbar:
|
|
270
285
|
cb = plt.colorbar(pad=0.02)
|
|
271
|
-
cb.set_label(label=cbar,size=fontsize, color=color)
|
|
286
|
+
cb.set_label(label=cbar, size=fontsize, color=color)
|
|
272
287
|
cb.ax.tick_params(labelsize=fontsize, color=color)
|
|
273
288
|
cb.ax.yaxis.set_tick_params(color=color)
|
|
274
289
|
cb.outline.set_edgecolor(color)
|
|
275
|
-
plt.setp(plt.getp(cb.ax.axes,
|
|
276
|
-
|
|
290
|
+
plt.setp(plt.getp(cb.ax.axes, "yticklabels"), color=color)
|
|
291
|
+
|
|
277
292
|
return fig
|
|
278
|
-
|
|
279
|
-
def hist(
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
293
|
+
|
|
294
|
+
def hist(
|
|
295
|
+
self,
|
|
296
|
+
direction="Forward",
|
|
297
|
+
channel="Z-Axis",
|
|
298
|
+
bins="sqrt",
|
|
299
|
+
scale=1e9,
|
|
300
|
+
cmap=cm.afmhot,
|
|
301
|
+
xlabel="Z-Axis [nm]",
|
|
302
|
+
fontsize=10,
|
|
303
|
+
density=False,
|
|
304
|
+
theme="light",
|
|
305
|
+
**kwargs,
|
|
306
|
+
):
|
|
307
|
+
|
|
308
|
+
data = np.array(
|
|
309
|
+
self.data["Image"][direction][channel] * scale, dtype=float
|
|
310
|
+
).reshape(-1)
|
|
311
|
+
if isinstance(bins, str):
|
|
312
|
+
bins = n_bins(data, method=bins)
|
|
313
|
+
|
|
295
314
|
fig = plt.figure(dpi=300)
|
|
296
|
-
|
|
297
|
-
if theme==
|
|
298
|
-
color =
|
|
299
|
-
c_bg =
|
|
315
|
+
|
|
316
|
+
if theme == "light":
|
|
317
|
+
color = "k"
|
|
318
|
+
c_bg = "w"
|
|
300
319
|
else:
|
|
301
|
-
color=
|
|
302
|
-
c_bg =
|
|
320
|
+
color = "w"
|
|
321
|
+
c_bg = "k"
|
|
303
322
|
fig.patch.set_facecolor(c_bg)
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
323
|
+
|
|
324
|
+
n, edge, patches = plt.hist(
|
|
325
|
+
data, bins=bins, density=density, color="green", **kwargs
|
|
326
|
+
)
|
|
307
327
|
bin_centers = 0.5 * (edge[:-1] + edge[1:])
|
|
308
|
-
|
|
328
|
+
|
|
309
329
|
col = bin_centers - min(bin_centers)
|
|
310
330
|
col /= max(col)
|
|
311
|
-
|
|
331
|
+
|
|
312
332
|
for c, p in zip(col, patches):
|
|
313
|
-
plt.setp(p,
|
|
314
|
-
|
|
333
|
+
plt.setp(p, "facecolor", cmap(c))
|
|
334
|
+
|
|
315
335
|
im = plt.gca()
|
|
316
336
|
for spine in im.axes.spines.values():
|
|
317
|
-
spine.set_edgecolor(color)
|
|
318
|
-
|
|
319
|
-
plt.xlabel(xlabel,fontsize=fontsize, color=color)
|
|
337
|
+
spine.set_edgecolor(color)
|
|
338
|
+
|
|
339
|
+
plt.xlabel(xlabel, fontsize=fontsize, color=color)
|
|
320
340
|
if density:
|
|
321
|
-
ylabel=
|
|
341
|
+
ylabel = "$\\rho$"
|
|
322
342
|
else:
|
|
323
|
-
ylabel=
|
|
324
|
-
plt.ylabel(ylabel,fontsize=fontsize, color=color)
|
|
343
|
+
ylabel = "Counts"
|
|
344
|
+
plt.ylabel(ylabel, fontsize=fontsize, color=color)
|
|
325
345
|
plt.xticks(fontsize=fontsize, color=color)
|
|
326
346
|
plt.yticks(fontsize=fontsize, color=color)
|
|
327
347
|
im.axes.tick_params(color=color, labelcolor=color)
|
|
328
|
-
|
|
348
|
+
|
|
329
349
|
im.get_children()[-1].set_facecolor(c_bg)
|
|
330
|
-
|
|
350
|
+
|
|
331
351
|
return fig
|
|
332
|
-
|
|
333
|
-
|
|
352
|
+
|
|
334
353
|
# def surf(self,
|
|
335
354
|
# direction='Forward',
|
|
336
355
|
# channel='Z-Axis',
|
|
@@ -374,11 +393,11 @@ class process():
|
|
|
374
393
|
def stats(self):
|
|
375
394
|
# definition of central moment
|
|
376
395
|
def Mu(x, i):
|
|
377
|
-
return np.mean((x-x.mean())**i)
|
|
396
|
+
return np.mean((x - x.mean()) ** i)
|
|
378
397
|
|
|
379
398
|
# mean deviation
|
|
380
399
|
def Sa_(x):
|
|
381
|
-
return np.mean(np.abs(x-x.mean()))
|
|
400
|
+
return np.mean(np.abs(x - x.mean()))
|
|
382
401
|
|
|
383
402
|
# RMS deviation
|
|
384
403
|
def Sq_(x):
|
|
@@ -386,74 +405,88 @@ class process():
|
|
|
386
405
|
|
|
387
406
|
# Skew
|
|
388
407
|
def skew_(x):
|
|
389
|
-
return Mu(x, 3)/Mu(x, 2)**(3
|
|
408
|
+
return Mu(x, 3) / Mu(x, 2) ** (3.0 / 2.0)
|
|
390
409
|
|
|
391
410
|
# Kurtosis
|
|
392
411
|
def kurt_(x):
|
|
393
|
-
return Mu(x, 4)/Mu(x, 2)**2 - 3
|
|
394
|
-
|
|
412
|
+
return Mu(x, 4) / Mu(x, 2) ** 2 - 3
|
|
395
413
|
|
|
396
414
|
# stat=[]
|
|
397
415
|
func = [Sa_, Sq_, skew_, kurt_, np.min, np.max]
|
|
398
|
-
fname = [
|
|
416
|
+
fname = ["Sa", "Sq", "Ssk", "Sku", "Min", "Max"]
|
|
399
417
|
stats = {}
|
|
400
418
|
# cnames = []
|
|
401
|
-
for d0, _ in self.data[
|
|
419
|
+
for d0, _ in self.data["Image"].groupby(level=0):
|
|
402
420
|
s = {}
|
|
403
|
-
for d1, df in self.data[
|
|
421
|
+
for d1, df in self.data["Image"].groupby(level=1):
|
|
404
422
|
# cnames.append([d0, d1])
|
|
405
423
|
s[d1] = {s: f(df[d0][d1]) for s, f in zip(fname, func)}
|
|
406
424
|
stats[d0] = s
|
|
407
425
|
|
|
408
426
|
return toPandaDF(stats).unstack(level=0)
|
|
409
|
-
|
|
427
|
+
|
|
410
428
|
|
|
411
429
|
def toPandaDF(user_dict):
|
|
412
|
-
df = pd.DataFrame.from_dict(
|
|
413
|
-
|
|
414
|
-
|
|
430
|
+
df = pd.DataFrame.from_dict(
|
|
431
|
+
{
|
|
432
|
+
(i, j): user_dict[i][j]
|
|
433
|
+
for i in user_dict.keys()
|
|
434
|
+
for j in user_dict[i].keys()
|
|
435
|
+
},
|
|
436
|
+
orient="index",
|
|
437
|
+
).transpose()
|
|
415
438
|
return df
|
|
416
439
|
|
|
417
440
|
|
|
418
|
-
def n_bins(x,method=
|
|
441
|
+
def n_bins(x, method="sqrt"):
|
|
419
442
|
n = len(x)
|
|
420
|
-
if method==
|
|
421
|
-
h = 2*stats.iqr(x)/np.cbrt(n)
|
|
422
|
-
k = int(np.ceil((max(x)-min(x))/h))
|
|
423
|
-
elif method==
|
|
443
|
+
if method == "freedman": # freedman-diaconis rule
|
|
444
|
+
h = 2 * stats.iqr(x) / np.cbrt(n)
|
|
445
|
+
k = int(np.ceil((max(x) - min(x)) / h))
|
|
446
|
+
elif method == "rice":
|
|
424
447
|
k = int(np.ceil(2 * np.cbrt(n)))
|
|
425
|
-
elif method==
|
|
426
|
-
k = int(np.ceil(np.log2(n))+1)
|
|
427
|
-
elif method==
|
|
448
|
+
elif method == "sturges":
|
|
449
|
+
k = int(np.ceil(np.log2(n)) + 1)
|
|
450
|
+
elif method == "doane":
|
|
428
451
|
g = stats.skew(x)
|
|
429
|
-
sigma = np.sqrt(6*(n-2)/((n+1)*(n+3)))
|
|
430
|
-
k = int(1 + np.log2(n)+np.log2(1+np.abs(g)/sigma))
|
|
431
|
-
elif method==
|
|
432
|
-
k = np.quantile(x,np.arange(0,1.01,0.025))
|
|
452
|
+
sigma = np.sqrt(6 * (n - 2) / ((n + 1) * (n + 3)))
|
|
453
|
+
k = int(1 + np.log2(n) + np.log2(1 + np.abs(g) / sigma))
|
|
454
|
+
elif method == "quantile":
|
|
455
|
+
k = np.quantile(x, np.arange(0, 1.01, 0.025))
|
|
433
456
|
else:
|
|
434
457
|
k = int(np.ceil(np.sqrt(n)))
|
|
435
458
|
return k
|
|
436
459
|
|
|
437
460
|
|
|
438
461
|
if __name__ == "__main__":
|
|
439
|
-
file=
|
|
440
|
-
|
|
462
|
+
file = "..\\example\\Calculate_Roughness\\sapphire.nid"
|
|
463
|
+
from colormaps import colors
|
|
464
|
+
|
|
465
|
+
cmap = colors("Sky").cmap
|
|
466
|
+
|
|
441
467
|
# fig = plt.figure(dpi=300)
|
|
442
468
|
afm = process(file)
|
|
443
469
|
|
|
444
|
-
chan =
|
|
445
|
-
|
|
470
|
+
chan = "Z-Axis"
|
|
471
|
+
|
|
446
472
|
afm.flatten(channel=chan)
|
|
447
473
|
|
|
448
474
|
rms_roughness = afm.stats().Forward[chan].Sq
|
|
449
475
|
z = afm.data.Image.Forward[chan]
|
|
450
|
-
mask = z > 2*rms_roughness
|
|
476
|
+
mask = z > 2 * rms_roughness
|
|
451
477
|
afm.plane_level()
|
|
452
478
|
afm.flatten(channel=chan, mask=mask)
|
|
453
|
-
fig = afm.image(
|
|
479
|
+
fig = afm.image(
|
|
480
|
+
cbar="Z [nm]",
|
|
481
|
+
title="",
|
|
482
|
+
channel=chan,
|
|
483
|
+
scalebar={"color": "w", "length": 0.25},
|
|
484
|
+
scale=1e9,
|
|
485
|
+
theme="dark",
|
|
486
|
+
cmap=cmap,
|
|
487
|
+
)
|
|
454
488
|
plt.show()
|
|
455
|
-
|
|
456
|
-
afm.hist(scale=1e12,xlabel='Height [pm]',theme='dark')
|
|
457
|
-
|
|
458
489
|
|
|
459
|
-
|
|
490
|
+
afm.hist(scale=1e12, xlabel="Height [pm]", theme="dark", cmap=cmap)
|
|
491
|
+
|
|
492
|
+
print("Average Roughness: %3.2f pm" % (rms_roughness * 1e12))
|
|
@@ -224,7 +224,8 @@ class nid_read:
|
|
|
224
224
|
key = "DataSet\\Calibration\\Scanhead"
|
|
225
225
|
if key in header:
|
|
226
226
|
sens = from_array(key, "In5")
|
|
227
|
-
|
|
227
|
+
max_defl = from_array(key, "In0")
|
|
228
|
+
cantilever["Sensitivity"] = {"Value": sens / max_defl, "Unit": "m"}
|
|
228
229
|
|
|
229
230
|
mapTable = {}
|
|
230
231
|
key = "DataSet\\SpecInfos"
|
|
@@ -641,10 +642,6 @@ def checkFileType(filename, cla):
|
|
|
641
642
|
|
|
642
643
|
if __name__ == "__main__":
|
|
643
644
|
# filename='..//example//Plane_Removal//circles.nid'
|
|
644
|
-
filename = "
|
|
645
|
-
afm = read(filename, verbose=True)
|
|
646
|
-
print(afm.param)
|
|
647
|
-
|
|
648
|
-
filename = "new.nhf"
|
|
645
|
+
filename = "atomic_lattice.nid"
|
|
649
646
|
afm = read(filename, verbose=True)
|
|
650
647
|
print(afm.param)
|
|
@@ -50,6 +50,7 @@ NSFopen/example/Spring_Constant/thermal.png
|
|
|
50
50
|
NSFopen/example/Spring_Constant/__pycache__/Spring_Constant.cpython-310.pyc
|
|
51
51
|
NSFopen/example/Spring_Constant/__pycache__/__init__.cpython-310.pyc
|
|
52
52
|
NSFopen/process/__init__.py
|
|
53
|
+
NSFopen/process/colormaps.py
|
|
53
54
|
NSFopen/process/process.py
|
|
54
55
|
NSFopen/read/__init__.py
|
|
55
56
|
NSFopen/read/read.py
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "2.2.2"
|
|
File without changes
|
{nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Calculate_Roughness/Calculate_Roughness.html
RENAMED
|
File without changes
|
{nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Calculate_Roughness/Calculate_Roughness.ipynb
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Lateral_Force/Lateral Force Processing.ipynb
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nsfopen-2.2.2 → nsfopen-2.2.4}/NSFopen/example/Spring_Constant/__pycache__/__init__.cpython-310.pyc
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|