Calculating surface roughness¶
This notebook levels an image of sapphire and calculates its roughness: the areal parameters of ISO 25178, the height
distribution, the power spectrum, and the roughness along a single line. Run it from this folder, next to sapphire.nid.
from NSFopen.process import process
import matplotlib.pyplot as plt
afm = process("sapphire.nid")
afm.flatten(order=1) # subtract a line from every scan line
fig = afm.image(color_range="p1")
plt.show()
Surface parameters¶
statistics() returns a table with values and units. The values are in SI units. Sku follows ISO 25178, so it is 3 for
a Gaussian surface.
table = afm.statistics()
print(table)
value unit Pixels 6.553600e+04 Area 6.250000e-12 m² Mean -2.007722e-22 m Median 3.769956e-13 m Min -1.735707e-10 m Max 1.693604e-10 m Sa 3.357276e-11 m Sq 4.212310e-11 m Ssk -5.643154e-02 Sku 3.010210e+00 Sp 1.693604e-10 m Sv 1.735707e-10 m Sz 3.429311e-10 m Sdq 2.783924e-03 Sdr 3.875098e-04 % Sal 3.608897e-08 m Str 2.364388e-01 Std 1.795000e+02 ° Correlation length 8.515676e-08 m
Height distribution¶
hist returns a normal matplotlib figure, so anything can be added to it, here a box with the main parameters.
Sa, Sq, Ssk, Sku = table.loc[["Sa", "Sq", "Ssk", "Sku"], "value"]
text = "\n".join((f"RMS (Sq): {Sq * 1e12:.1f} pm", f"Mean (Sa): {Sa * 1e12:.1f} pm",
f"Skew (Ssk): {Ssk:.3f}", f"Kurtosis (Sku): {Sku:.3f}"))
print(text)
fig = afm.hist(bins=256, figsize=(6, 4))
fig.axes[0].text(0.025, 0.95, text, va="top", transform=fig.axes[0].transAxes, fontsize=8,
bbox=dict(boxstyle="round", facecolor="w", alpha=0.5))
plt.show()
RMS (Sq): 42.1 pm Mean (Sa): 33.6 pm Skew (Ssk): -0.056 Kurtosis (Sku): 3.010
Bearing curve and power spectrum¶
The bearing curve shows how much of the surface lies above each height. The power spectral density shows at which lengths the roughness sits.
fig, axes = plt.subplots(1, 2, figsize=(11, 4), layout="constrained", dpi=150)
afm.plot_bearing(ax=axes[0], title="Bearing curve")
afm.plot_psd(ax=axes[1], title="Power spectral density")
plt.show()
Roughness along a line¶
A line cut, averaged over 5 pixels across the line, with its roughness after ISO 21920. End points are in m, as on the axes of the image.
width, height = afm.size()
profile = afm.line_profile((0.1 * width, 0.5 * height), (0.9 * width, 0.5 * height), width=5)
fig, axes = plt.subplots(1, 2, figsize=(11, 4), layout="constrained", dpi=150)
afm.image(ax=axes[0], profile=profile, color_range="p1")
afm.plot_profile(profile, ax=axes[1], title="Line cut")
plt.show()
roughness = afm.profile_roughness(profile).params
for name in ("Ra", "Rq", "Rz"):
print(f"{name}: {roughness[name][0] * 1e12:.1f} pm")
Ra: 13.6 pm Rq: 16.1 pm Rz: 54.8 pm