NSFopen 2.3.0__tar.gz → 2.4.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.
- {nsfopen-2.3.0 → nsfopen-2.4.0}/CHANGELOG.md +40 -2
- {nsfopen-2.3.0 → nsfopen-2.4.0}/MANIFEST.in +1 -1
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/__init__.py +29 -29
- nsfopen-2.4.0/NSFopen/_version.py +1 -0
- nsfopen-2.4.0/NSFopen/example/Force_Spectroscopy/Contact_Models.py +48 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/process/__init__.py +9 -9
- nsfopen-2.4.0/NSFopen/process/colormaps.py +244 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/process/combine.py +112 -112
- nsfopen-2.4.0/NSFopen/process/contact.py +387 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/process/fitting.py +211 -211
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/process/grains.py +316 -316
- nsfopen-2.4.0/NSFopen/process/iv.py +175 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/process/measure.py +862 -862
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/process/ops.py +1278 -1278
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/process/process.py +1205 -1205
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/process/profile_iso.py +232 -232
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/process/psdfit.py +215 -215
- nsfopen-2.4.0/NSFopen/process/spectroscopy.py +1005 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/process/surface3d.py +495 -502
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/read/__init__.py +10 -10
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/read/nhf.py +687 -687
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/read/nhf_spec.py +27 -27
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/read/read.py +654 -654
- {nsfopen-2.3.0 → nsfopen-2.4.0/NSFopen.egg-info}/PKG-INFO +15 -5
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen.egg-info/SOURCES.txt +4 -59
- {nsfopen-2.3.0/NSFopen.egg-info → nsfopen-2.4.0}/PKG-INFO +15 -5
- {nsfopen-2.3.0 → nsfopen-2.4.0}/README.md +14 -4
- {nsfopen-2.3.0 → nsfopen-2.4.0}/setup.py +6 -1
- {nsfopen-2.3.0 → nsfopen-2.4.0}/tests/test_examples.py +26 -26
- {nsfopen-2.3.0 → nsfopen-2.4.0}/tests/test_nsfopen.py +711 -711
- nsfopen-2.3.0/NSFopen/_version.py +0 -1
- nsfopen-2.3.0/NSFopen/process/colormaps.py +0 -76
- nsfopen-2.3.0/NSFopen/process/gradients/BW1 +0 -11
- nsfopen-2.3.0/NSFopen/process/gradients/BW2 +0 -21
- nsfopen-2.3.0/NSFopen/process/gradients/Blend1 +0 -8
- nsfopen-2.3.0/NSFopen/process/gradients/Blend2 +0 -13
- nsfopen-2.3.0/NSFopen/process/gradients/Blue +0 -4
- nsfopen-2.3.0/NSFopen/process/gradients/Blue-Cyan +0 -5
- nsfopen-2.3.0/NSFopen/process/gradients/Blue-Violet +0 -5
- nsfopen-2.3.0/NSFopen/process/gradients/Blue-Yellow +0 -6
- nsfopen-2.3.0/NSFopen/process/gradients/Body +0 -7
- nsfopen-2.3.0/NSFopen/process/gradients/Caribbean +0 -7
- nsfopen-2.3.0/NSFopen/process/gradients/Clusters +0 -13
- nsfopen-2.3.0/NSFopen/process/gradients/Code-V +0 -14
- nsfopen-2.3.0/NSFopen/process/gradients/Cold +0 -7
- nsfopen-2.3.0/NSFopen/process/gradients/DFit +0 -15
- nsfopen-2.3.0/NSFopen/process/gradients/Digitalis +0 -8
- nsfopen-2.3.0/NSFopen/process/gradients/Gold +0 -5
- nsfopen-2.3.0/NSFopen/process/gradients/Gray-inverted +0 -3
- nsfopen-2.3.0/NSFopen/process/gradients/Green +0 -4
- nsfopen-2.3.0/NSFopen/process/gradients/Green-Cyan +0 -5
- nsfopen-2.3.0/NSFopen/process/gradients/Green-Stripes-4 +0 -17
- nsfopen-2.3.0/NSFopen/process/gradients/Green-Violet +0 -6
- nsfopen-2.3.0/NSFopen/process/gradients/Green-Yellow +0 -5
- nsfopen-2.3.0/NSFopen/process/gradients/Gwyddion.net +0 -5
- nsfopen-2.3.0/NSFopen/process/gradients/Halcyon +0 -8
- nsfopen-2.3.0/NSFopen/process/gradients/Lines +0 -23
- nsfopen-2.3.0/NSFopen/process/gradients/Maple +0 -8
- nsfopen-2.3.0/NSFopen/process/gradients/MetroPro +0 -32
- nsfopen-2.3.0/NSFopen/process/gradients/NT-MDT +0 -13
- nsfopen-2.3.0/NSFopen/process/gradients/Neon +0 -6
- nsfopen-2.3.0/NSFopen/process/gradients/Olive +0 -4
- nsfopen-2.3.0/NSFopen/process/gradients/Painbow +0 -62
- nsfopen-2.3.0/NSFopen/process/gradients/Pink +0 -4
- nsfopen-2.3.0/NSFopen/process/gradients/Plum +0 -6
- nsfopen-2.3.0/NSFopen/process/gradients/Pm3d +0 -6
- nsfopen-2.3.0/NSFopen/process/gradients/RGB-Blue +0 -3
- nsfopen-2.3.0/NSFopen/process/gradients/RGB-Green +0 -3
- nsfopen-2.3.0/NSFopen/process/gradients/RGB-Red +0 -3
- nsfopen-2.3.0/NSFopen/process/gradients/Rainbow1 +0 -10
- nsfopen-2.3.0/NSFopen/process/gradients/Rainbow2 +0 -6
- nsfopen-2.3.0/NSFopen/process/gradients/Red +0 -4
- nsfopen-2.3.0/NSFopen/process/gradients/Red-Cyan +0 -6
- nsfopen-2.3.0/NSFopen/process/gradients/Red-Stripes-5 +0 -21
- nsfopen-2.3.0/NSFopen/process/gradients/Red-Violet +0 -5
- nsfopen-2.3.0/NSFopen/process/gradients/Red-Yellow +0 -5
- nsfopen-2.3.0/NSFopen/process/gradients/Rust +0 -8
- nsfopen-2.3.0/NSFopen/process/gradients/Saw1 +0 -7
- nsfopen-2.3.0/NSFopen/process/gradients/Shame +0 -6
- nsfopen-2.3.0/NSFopen/process/gradients/Sky +0 -7
- nsfopen-2.3.0/NSFopen/process/gradients/Sm2 +0 -7
- nsfopen-2.3.0/NSFopen/process/gradients/Spectral +0 -13
- nsfopen-2.3.0/NSFopen/process/gradients/Spectral-white +0 -13
- nsfopen-2.3.0/NSFopen/process/gradients/Spring +0 -6
- nsfopen-2.3.0/NSFopen/process/gradients/Viridis +0 -14
- nsfopen-2.3.0/NSFopen/process/gradients/Warm +0 -8
- nsfopen-2.3.0/NSFopen/process/gradients/Warpp-mono +0 -13
- nsfopen-2.3.0/NSFopen/process/gradients/Warpp-spectral +0 -13
- nsfopen-2.3.0/NSFopen/process/gradients/Wyko +0 -13
- nsfopen-2.3.0/NSFopen/process/gradients/Yellow +0 -4
- nsfopen-2.3.0/NSFopen/process/gradients/Zones +0 -17
- {nsfopen-2.3.0 → nsfopen-2.4.0}/LICENSE +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Calculate_Roughness/Calculate_Roughness.html +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Calculate_Roughness/Calculate_Roughness.ipynb +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Calculate_Roughness/Calculate_Roughness.py +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Calculate_Roughness/__pycache__/Calculate_Roughness.cpython-310.pyc +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Calculate_Roughness/sapphire.nid +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Force_Spectroscopy/Force_Spectroscopy.html +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Force_Spectroscopy/Force_Spectroscopy.ipynb +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Force_Spectroscopy/Force_Spectroscopy.py +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Force_Spectroscopy/spectroscopy.nid +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Grain_Analysis/Grain_Analysis.html +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Grain_Analysis/Grain_Analysis.ipynb +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Grain_Analysis/Grain_Analysis.py +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Lateral_Force/Lateral_Force_Processing.html +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Lateral_Force/Lateral_Force_Processing.ipynb +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Lateral_Force/Lateral_Force_Processing.py +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Lateral_Force/SBS-PMMA.nid +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Plane_Removal/Plane_Removal.html +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Plane_Removal/Plane_Removal.ipynb +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Plane_Removal/Plane_Removal.py +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Plane_Removal/circles.nid +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Plane_Removal/circles_holes.nid +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Plane_Removal/grid.nid +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Plane_Removal/squares_holes.nid +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Plotting_Data/MoS2.nid +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Plotting_Data/Plotting_Data.html +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Plotting_Data/Plotting_Data.ipynb +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Plotting_Data/Plotting_Data.py +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Sharpen_Image/Sharpen_Image.html +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Sharpen_Image/Sharpen_Image.ipynb +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Sharpen_Image/Sharpen_Image.py +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Sharpen_Image/grid.nid +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Spring_Constant/Spring_Constant.html +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Spring_Constant/Spring_Constant.ipynb +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Spring_Constant/Spring_Constant.py +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Spring_Constant/__pycache__/Spring_Constant.cpython-310.pyc +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Spring_Constant/__pycache__/__init__.cpython-310.pyc +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Spring_Constant/sader.py +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Spring_Constant/thermal.nid +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen/example/Spring_Constant/thermal.png +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen.egg-info/dependency_links.txt +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen.egg-info/entry_points.txt +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen.egg-info/not-zip-safe +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen.egg-info/requires.txt +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/NSFopen.egg-info/top_level.txt +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/pyproject.toml +0 -0
- {nsfopen-2.3.0 → nsfopen-2.4.0}/setup.cfg +0 -0
|
@@ -1,6 +1,44 @@
|
|
|
1
1
|
# Change log
|
|
2
2
|
|
|
3
|
-
## 2.
|
|
3
|
+
## 2.4.0 (not yet released)
|
|
4
|
+
|
|
5
|
+
Compared to **2.3.0**.
|
|
6
|
+
|
|
7
|
+
### Force spectroscopy analysis
|
|
8
|
+
Added, in `NSFopen.process` (the calculations of the Spectroscopy page of NSSA, the NSF Surface and Spectroscopy
|
|
9
|
+
Analyzer, so a script and the program give the same numbers):
|
|
10
|
+
- `contact`: elastic contact of a tip pressed into a flat sample. Models Hertz, Sneddon (exact), DMT, JKR and
|
|
11
|
+
Oliver-Pharr; tip shapes sphere, cone, four-sided pyramid, flat cylinder punch and hyperboloid. `fit_elastic`,
|
|
12
|
+
`fit_jkr`, `fit_oliver_pharr` give the Young's modulus, reduced modulus, contact point, adhesion and the fit quality.
|
|
13
|
+
- `spectroscopy`: `SpecFile` opens the force curves and force maps of NID and NHF files. `ForceSettings` and
|
|
14
|
+
`ForceAnalysis` process them: smoothing, baseline (offset, tilt, or an interference sine with its period found),
|
|
15
|
+
contact point, indentation, adhesion, pull-off, adhesion and dissipated energy, and the model fit. `Results` has
|
|
16
|
+
statistics, maps, masks, fits of different models on different regions, a quality filter (leave out fits below an R²)
|
|
17
|
+
and CSV export. Maps can be analyzed partly (every n-th line and column, or a region).
|
|
18
|
+
- `iv`: I-V curves with dI/dV, normalized conductance, zero-bias conductance and resistance, gap and rectification.
|
|
19
|
+
|
|
20
|
+
### Color maps
|
|
21
|
+
- 12 maps are defined in `colormaps.py` (`NANOSURF`): Sky (the default for heights), Warm, Flare, Caribbean, Strata,
|
|
22
|
+
Gold, Digitalis, Neon, Plum, Cold, Spectrum and Maple, plus BlueBlackRed. `register()` adds them and their reversed
|
|
23
|
+
versions (`Sky_r`) to matplotlib; `colormap(name)` returns any of them or a matplotlib map.
|
|
24
|
+
- The 59 Gwyddion gradient files that 2.3.0 included are removed: they are GPL, NSFopen is MIT. An installed Gwyddion's
|
|
25
|
+
gradients are found on Windows, macOS and Linux (`gwyddion_dirs`, `gwyddion_gradients`, `register(gwyddion=True)`), and
|
|
26
|
+
`colors(name)` uses them when the name is not one of the 12.
|
|
27
|
+
|
|
28
|
+
### Changes that can affect existing scripts
|
|
29
|
+
| What | 2.3.0 | 2.4.0 |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| `colors(name)` with a Gwyddion name | 59 gradient files in the package | 12 maps defined in the code; `Pm3d`, `Blend2`, `Code-V` open as `Flare`, `Strata`, `Spectrum`; the others only with an installed Gwyddion or `gwy_dir=` |
|
|
32
|
+
| `colormaps.GRADIENTS` | The gradient folder | Removed |
|
|
33
|
+
|
|
34
|
+
### Examples
|
|
35
|
+
- New `Force_Spectroscopy/Contact_Models.py`: a force map fitted with `process.spectroscopy`, with statistics, the
|
|
36
|
+
quality filter, maps of the modulus and adhesion, and the stiffest curve with its fit.
|
|
37
|
+
|
|
38
|
+
### Packaging
|
|
39
|
+
- Credentials (`tokens.json`, `.env`, `*.token`) in the example folders are never packaged.
|
|
40
|
+
|
|
41
|
+
## 2.3.0 (November 2, 2026)
|
|
4
42
|
|
|
5
43
|
Compared to **2.2.4**, the latest version on PyPI (August 2024).
|
|
6
44
|
|
|
@@ -9,7 +47,7 @@ Compared to **2.2.4**, the latest version on PyPI (August 2024).
|
|
|
9
47
|
- NID files are read about 5 times faster, and line flattening is about twice as fast.
|
|
10
48
|
- NHF spectroscopy files of any size open immediately, and their curves are read when asked for.
|
|
11
49
|
- WaveMode NMA files are read, with a curve for every pixel and maps of any quantity.
|
|
12
|
-
- `process` has many new image analysis functions, brought over from the Nanosurf Surface Analyzer.
|
|
50
|
+
- `process` has many new image analysis functions, brought over from the Nanosurf Surface Analyzer (now NSSA).
|
|
13
51
|
- Figures take their units and labels from the file, can be placed in subplots, and there is a new 3D plot.
|
|
14
52
|
|
|
15
53
|
### Reading files
|
|
@@ -1 +1 @@
|
|
|
1
|
-
include CHANGELOG.md
|
|
1
|
+
include CHANGELOG.md
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
"""Package for scripting the Nanosurf control software.
|
|
2
|
-
Copyright (C) Nanosurf AG - All Rights Reserved (2021)
|
|
3
|
-
License - MIT"""
|
|
4
|
-
|
|
5
|
-
import os
|
|
6
|
-
import pathlib
|
|
7
|
-
from ._version import __version__
|
|
8
|
-
|
|
9
|
-
from .read import read
|
|
10
|
-
|
|
11
|
-
# from . process import process
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def package_path() -> pathlib.Path:
|
|
15
|
-
return pathlib.Path(os.path.dirname(os.path.abspath(__file__)))
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def example_path() -> pathlib.Path:
|
|
19
|
-
return package_path() / "example"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def help():
|
|
23
|
-
print("Nanosurf NID and NHF file reader and image analysis:")
|
|
24
|
-
print("-------------------------------")
|
|
25
|
-
print(f"Installed version: {__version__}")
|
|
26
|
-
print("\nExamples are stored here:")
|
|
27
|
-
print(example_path())
|
|
28
|
-
for example in os.listdir(example_path()):
|
|
29
|
-
print(f" {example}")
|
|
1
|
+
"""Package for scripting the Nanosurf control software.
|
|
2
|
+
Copyright (C) Nanosurf AG - All Rights Reserved (2021)
|
|
3
|
+
License - MIT"""
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import pathlib
|
|
7
|
+
from ._version import __version__
|
|
8
|
+
|
|
9
|
+
from .read import read
|
|
10
|
+
|
|
11
|
+
# from . process import process
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def package_path() -> pathlib.Path:
|
|
15
|
+
return pathlib.Path(os.path.dirname(os.path.abspath(__file__)))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def example_path() -> pathlib.Path:
|
|
19
|
+
return package_path() / "example"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def help():
|
|
23
|
+
print("Nanosurf NID and NHF file reader and image analysis:")
|
|
24
|
+
print("-------------------------------")
|
|
25
|
+
print(f"Installed version: {__version__}")
|
|
26
|
+
print("\nExamples are stored here:")
|
|
27
|
+
print(example_path())
|
|
28
|
+
for example in os.listdir(example_path()):
|
|
29
|
+
print(f" {example}")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.4.0"
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# coding: utf-8
|
|
3
|
+
""" Fitting a force map with the contact models of NSFopen.process.spectroscopy and contact (NSFopen 2.4).
|
|
4
|
+
The same calculations as the Spectroscopy page of the Nanosurf Surface Analyzer, so a script and the app give the same
|
|
5
|
+
numbers. Run it from this folder, next to spectroscopy.nid. The tip radius and Poisson ratio are assumptions: the
|
|
6
|
+
modulus scales with them, so set them for your own sample. """
|
|
7
|
+
|
|
8
|
+
import matplotlib.pyplot as plt
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
from NSFopen.process import contact, spectroscopy
|
|
12
|
+
|
|
13
|
+
spec = spectroscopy.SpecFile("spectroscopy.nid")
|
|
14
|
+
print(f"{spec.n_curves} curves, grid {spec.grid}, k = {spec.spring_constant:.4g} N/m")
|
|
15
|
+
print("Models:", ", ".join(label for key, label in contact.MODELS))
|
|
16
|
+
|
|
17
|
+
# DMT on the retract curves, spherical tip, offset and tilt removed from the first 40 % of the approach
|
|
18
|
+
settings = spectroscopy.ForceSettings(model="dmt", shape="sphere", radius=10e-9, poisson=0.35,
|
|
19
|
+
baseline="linear", baseline_from=0, baseline_to=40)
|
|
20
|
+
results = spectroscopy.ForceAnalysis(spec, settings).run()
|
|
21
|
+
results.min_r2 = 0.95 # leave out fits that do not describe their curve
|
|
22
|
+
|
|
23
|
+
for name, unit, n, mean, std, median, low, high in results.statistics():
|
|
24
|
+
print(f"{name:28s} N={n:4d} mean {spectroscopy.format_value(mean, unit):>12s} "
|
|
25
|
+
f"std {spectroscopy.format_value(std, unit):>12s}")
|
|
26
|
+
results.write_csv("spectroscopy_results.csv")
|
|
27
|
+
|
|
28
|
+
# Maps of the modulus and the adhesion (NaN: left out or not fitted)
|
|
29
|
+
fig, axes = plt.subplots(1, 2, figsize=(10, 4))
|
|
30
|
+
for ax, name in zip(axes, ("E", "adhesion force")):
|
|
31
|
+
values = results.map(name)
|
|
32
|
+
image = ax.imshow(values, origin="lower", cmap="viridis")
|
|
33
|
+
ax.set_title(f"{name} [{results.units[name]}]")
|
|
34
|
+
fig.colorbar(image, ax=ax)
|
|
35
|
+
plt.tight_layout()
|
|
36
|
+
plt.show()
|
|
37
|
+
|
|
38
|
+
# The stiffest curve with its fit: force against the indentation
|
|
39
|
+
curve = spectroscopy.ForceAnalysis(spec, settings).curve(int(np.nanargmax(results.column("E"))))
|
|
40
|
+
segment = curve.retract
|
|
41
|
+
plt.figure()
|
|
42
|
+
plt.plot((segment.delta - curve.contact_delta) * 1e9, segment.force * 1e9, label="retract")
|
|
43
|
+
plt.plot((curve.fit.fit_delta - curve.contact_delta) * 1e9, curve.fit.fit_force * 1e9, "--", label="DMT fit")
|
|
44
|
+
plt.xlabel("indentation [nm]")
|
|
45
|
+
plt.ylabel("force [nN]")
|
|
46
|
+
plt.title(f"curve {curve.index + 1}: E = {spectroscopy.format_value(curve.fit.modulus, 'Pa')}")
|
|
47
|
+
plt.legend()
|
|
48
|
+
plt.show()
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
"""
|
|
3
|
-
Created on Sat Oct 12 12:43:59 2019
|
|
4
|
-
|
|
5
|
-
@author: Edward
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from . process import process, n_bins, OpError
|
|
9
|
-
from . colormaps import colors
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created on Sat Oct 12 12:43:59 2019
|
|
4
|
+
|
|
5
|
+
@author: Edward
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from . process import process, n_bins, OpError
|
|
9
|
+
from . colormaps import colors
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
""" Color maps for AFM images.
|
|
3
|
+
|
|
4
|
+
The Nanosurf color maps are defined here as color tables (position from 0 to 1, color), so they need no data files.
|
|
5
|
+
`register()` adds them to matplotlib, after which every plotting function takes their names, e.g.
|
|
6
|
+
`plt.imshow(height, cmap="Sky")`. `colormap(name)` returns a color map by name: a Nanosurf map, "BlueBlackRed", an
|
|
7
|
+
older name (see ALIASES) or any matplotlib map.
|
|
8
|
+
|
|
9
|
+
Gradient files of Gwyddion are not part of NSFopen, but an installed Gwyddion's are found and used (Windows, macOS,
|
|
10
|
+
Linux; see gwyddion_dirs): `colors("Rainbow1").cmap`, `register(gwyddion=True)` adds them to matplotlib, and
|
|
11
|
+
`gwyddion_gradients()` lists them. A folder of gradient files can also be given: `colors(name, gwy_dir=folder)`.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import os
|
|
15
|
+
import pathlib
|
|
16
|
+
import shutil
|
|
17
|
+
import sys
|
|
18
|
+
|
|
19
|
+
from matplotlib.colors import LinearSegmentedColormap
|
|
20
|
+
|
|
21
|
+
HEIGHT = "Sky" # the default color map of height (topography) images
|
|
22
|
+
|
|
23
|
+
# name: ((position, color), ...), positions rising from 0 to 1
|
|
24
|
+
NANOSURF = {
|
|
25
|
+
"Sky": ((0, "#000000"), (0.1, "#131432"), (0.2, "#262965"), (0.3, "#38466e"), (0.4, "#4b6477"), (0.5, "#8c6f5a"),
|
|
26
|
+
(0.6, "#ca7a3f"), (0.7, "#e3a74a"), (0.8, "#fcd355"), (0.9, "#fee9ac"), (1, "#ffffff")),
|
|
27
|
+
"Warm": ((0, "#000000"), (0.05, "#17090d"), (0.1, "#30131b"), (0.15, "#4a1d29"), (0.2, "#632636"),
|
|
28
|
+
(0.25, "#7c3044"), (0.3, "#8c303f"), (0.35, "#9e2f39"), (0.4, "#b02f34"), (0.45, "#c22f2e"),
|
|
29
|
+
(0.5, "#cc4a28"), (0.55, "#d46323"), (0.6, "#de7e1d"), (0.65, "#e0951c"), (0.7, "#e1ab1c"),
|
|
30
|
+
(0.75, "#e3c01f"), (0.8, "#e5cd5f"), (0.85, "#e6dba5"), (0.9, "#e8e8e8"), (0.95, "#f4f4f4"),
|
|
31
|
+
(1, "#ffffff")),
|
|
32
|
+
"Flare": ((0, "#000000"), (0.025, "#0a0014"), (0.05, "#130029"), (0.075, "#1e0040"), (0.1, "#280055"),
|
|
33
|
+
(0.125, "#33006c"), (0.15, "#3d0081"), (0.175, "#450092"), (0.2, "#4a009d"), (0.225, "#4f00a7"),
|
|
34
|
+
(0.25, "#5400b2"), (0.275, "#5800bc"), (0.3, "#5d00c6"), (0.325, "#6200d1"), (0.35, "#6800ca"),
|
|
35
|
+
(0.375, "#7000b9"), (0.4, "#7700aa"), (0.425, "#7e009b"), (0.45, "#850089"), (0.475, "#8c007a"),
|
|
36
|
+
(0.5, "#940069"), (0.525, "#9b005a"), (0.55, "#a1004b"), (0.575, "#a90039"), (0.6, "#b0002a"),
|
|
37
|
+
(0.625, "#b80019"), (0.65, "#bf000a"), (0.675, "#c40500"), (0.7, "#c91800"), (0.725, "#ce2800"),
|
|
38
|
+
(0.75, "#d33b00"), (0.775, "#d74b00"), (0.8, "#db5b00"), (0.825, "#e06e00"), (0.85, "#e47e00"),
|
|
39
|
+
(0.875, "#e99100"), (0.9, "#eda100"), (0.925, "#f2b100"), (0.95, "#f7c400"), (0.975, "#fbd400"),
|
|
40
|
+
(1, "#ffe400")),
|
|
41
|
+
"Caribbean": ((0, "#000000"), (0.1, "#000e1c"), (0.2, "#001d39"), (0.3, "#003d58"), (0.4, "#005d78"),
|
|
42
|
+
(0.5, "#007774"), (0.6, "#009070"), (0.7, "#27ae41"), (0.8, "#4ccc13"), (0.9, "#a7e68b"),
|
|
43
|
+
(1, "#ffffff")),
|
|
44
|
+
"Strata": ((0, "#000000"), (0.025, "#030637"), (0.05, "#050c6e"), (0.075, "#061678"), (0.1, "#062071"),
|
|
45
|
+
(0.125, "#062b68"), (0.15, "#063561"), (0.175, "#063e58"), (0.2, "#064546"), (0.225, "#064b36"),
|
|
46
|
+
(0.25, "#065224"), (0.275, "#065914"), (0.3, "#065f0f"), (0.325, "#06660d"), (0.35, "#066c0b"),
|
|
47
|
+
(0.375, "#067408"), (0.4, "#0c7c07"), (0.425, "#1e890b"), (0.45, "#33970e"), (0.475, "#45a411"),
|
|
48
|
+
(0.5, "#5ab215"), (0.525, "#71bb13"), (0.55, "#8ac310"), (0.575, "#a1c30c"), (0.6, "#b1be09"),
|
|
49
|
+
(0.625, "#bdb606"), (0.65, "#bdad06"), (0.675, "#bda306"), (0.7, "#bd9806"), (0.725, "#bd8f06"),
|
|
50
|
+
(0.75, "#bd8506"), (0.775, "#bd7d06"), (0.8, "#bd7506"), (0.825, "#bd6b06"), (0.85, "#bd6406"),
|
|
51
|
+
(0.875, "#bd5e06"), (0.9, "#bd5906"), (0.925, "#bd5406"), (0.95, "#bd4f06"), (0.975, "#c88d66"),
|
|
52
|
+
(1, "#d4d4d4")),
|
|
53
|
+
"Gold": ((0, "#000000"), (0.05, "#0c0400"), (0.1, "#1a0800"), (0.15, "#270d00"), (0.2, "#351100"),
|
|
54
|
+
(0.25, "#421500"), (0.3, "#4f1900"), (0.35, "#5d2100"), (0.4, "#6c3000"), (0.45, "#7b3f00"),
|
|
55
|
+
(0.5, "#8b4f00"), (0.55, "#995d00"), (0.6, "#a86c00"), (0.65, "#b77b00"), (0.7, "#c38d0e"),
|
|
56
|
+
(0.75, "#cda021"), (0.8, "#d6b233"), (0.85, "#dfc547"), (0.9, "#e9d85a"), (0.95, "#f3ea6e"),
|
|
57
|
+
(1, "#fcfc80")),
|
|
58
|
+
"Digitalis": ((0, "#000000"), (0.05, "#14020d"), (0.1, "#2a041a"), (0.15, "#3f0628"), (0.2, "#550835"),
|
|
59
|
+
(0.25, "#6b0b43"), (0.3, "#8a204a"), (0.35, "#ab3752"), (0.4, "#cc4e59"), (0.45, "#e5655f"),
|
|
60
|
+
(0.5, "#e97961"), (0.55, "#ed8c62"), (0.6, "#f1a164"), (0.65, "#f5b566"), (0.7, "#ebc76f"),
|
|
61
|
+
(0.75, "#d7d87e"), (0.8, "#c5e78b"), (0.85, "#b8df90"), (0.9, "#acd393"), (0.95, "#d7e9cb"),
|
|
62
|
+
(1, "#ffffff")),
|
|
63
|
+
"Neon": ((0, "#a70000"), (0.05, "#a71000"), (0.1, "#a72200"), (0.15, "#a73400"), (0.2, "#a74600"),
|
|
64
|
+
(0.25, "#a75800"), (0.3, "#b87000"), (0.35, "#ca8a00"), (0.4, "#dca500"), (0.45, "#eebf00"),
|
|
65
|
+
(0.5, "#fdd800"), (0.55, "#d2da00"), (0.6, "#a3dc00"), (0.65, "#74de00"), (0.7, "#44e000"),
|
|
66
|
+
(0.75, "#18e203"), (0.8, "#13e833"), (0.85, "#0eee67"), (0.9, "#09f49b"), (0.95, "#05facf"),
|
|
67
|
+
(1, "#00ffff")),
|
|
68
|
+
"Plum": ((0, "#000000"), (0.05, "#100312"), (0.1, "#220726"), (0.15, "#340a3a"), (0.2, "#460e4e"),
|
|
69
|
+
(0.25, "#571162"), (0.3, "#5f2577"), (0.35, "#673b8e"), (0.4, "#6f50a5"), (0.45, "#7665bc"),
|
|
70
|
+
(0.5, "#7e7ad2"), (0.55, "#7181d6"), (0.6, "#6488da"), (0.65, "#568fdf"), (0.7, "#4996e3"),
|
|
71
|
+
(0.75, "#3f9ee7"), (0.8, "#63b0ec"), (0.85, "#8bc4f1"), (0.9, "#b3d8f6"), (0.95, "#daedfa"),
|
|
72
|
+
(1, "#ffffff")),
|
|
73
|
+
"Spectrum": ((0, "#05059a"), (0.05, "#0216af"), (0.1, "#002bc3"), (0.15, "#004bcf"), (0.2, "#006fd3"),
|
|
74
|
+
(0.25, "#0197d0"), (0.3, "#01b4bf"), (0.35, "#00cda9"), (0.4, "#00d17f"), (0.45, "#01d354"),
|
|
75
|
+
(0.5, "#25d527"), (0.55, "#49d600"), (0.6, "#7ada00"), (0.65, "#a8de00"), (0.7, "#d1e000"),
|
|
76
|
+
(0.75, "#ebd200"), (0.8, "#f2af01"), (0.85, "#f78b01"), (0.9, "#fb6700"), (0.95, "#f43c04"),
|
|
77
|
+
(1, "#e90e0a")),
|
|
78
|
+
"Cold": ((0, "#000000"), (0.1, "#0e1729"), (0.2, "#1d2e53"), (0.3, "#2b457c"), (0.4, "#2e568c"), (0.5, "#32689b"),
|
|
79
|
+
(0.6, "#4489af"), (0.7, "#58acc5"), (0.8, "#9fcad6"), (0.9, "#e8e8e8"), (1, "#ffffff")),
|
|
80
|
+
"Maple": ((0, "#000000"), (0.025, "#020901"), (0.05, "#031201"), (0.075, "#051d02"), (0.1, "#072603"),
|
|
81
|
+
(0.125, "#093104"), (0.15, "#0b3a04"), (0.175, "#0c4305"), (0.2, "#0e4e06"), (0.225, "#105706"),
|
|
82
|
+
(0.25, "#136107"), (0.275, "#266d09"), (0.3, "#3a780b"), (0.325, "#51850e"), (0.35, "#659010"),
|
|
83
|
+
(0.375, "#7c9d12"), (0.4, "#8fa814"), (0.425, "#a3b316"), (0.45, "#bac018"), (0.475, "#cecb1a"),
|
|
84
|
+
(0.5, "#e3d71d"), (0.525, "#e8d122"), (0.55, "#edca26"), (0.575, "#f2c32c"), (0.6, "#f7bd30"),
|
|
85
|
+
(0.625, "#fcb536"), (0.65, "#fcac3a"), (0.675, "#fda33d"), (0.7, "#fe9842"), (0.725, "#fe8f46"),
|
|
86
|
+
(0.75, "#ff864c"), (0.775, "#ff8c5d"), (0.8, "#ff926e"), (0.825, "#ff9982"), (0.85, "#ff9e93"),
|
|
87
|
+
(0.875, "#ffa7a7"), (0.9, "#ffb8b8"), (0.925, "#ffc9c9"), (0.95, "#ffdddd"), (0.975, "#ffeeee"),
|
|
88
|
+
(1, "#ffffff")),
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
BLUE_BLACK_RED = ((0.0, "#9ecae1"), (0.5, "#000000"), (1.0, "#fc9272"))
|
|
92
|
+
|
|
93
|
+
# names of earlier NSFopen versions -> today's
|
|
94
|
+
ALIASES = {"Pm3d": "Flare", "Blend2": "Strata", "Code-V": "Spectrum"}
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _build(name, stops):
|
|
98
|
+
return LinearSegmentedColormap.from_list(name, list(stops), N=256)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def names():
|
|
102
|
+
""" The names of the color maps of this module (Nanosurf maps and BlueBlackRed). """
|
|
103
|
+
return list(NANOSURF) + ["BlueBlackRed"]
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def colormap(name):
|
|
107
|
+
""" The color map of a name: a Nanosurf map, BlueBlackRed, an older name (ALIASES) or a matplotlib map. A color
|
|
108
|
+
map object is returned as it is. Raises ValueError for an unknown name. """
|
|
109
|
+
import matplotlib
|
|
110
|
+
if not isinstance(name, str):
|
|
111
|
+
return name
|
|
112
|
+
name = ALIASES.get(name, name)
|
|
113
|
+
if name in NANOSURF:
|
|
114
|
+
return _build(name, NANOSURF[name])
|
|
115
|
+
if name == "BlueBlackRed":
|
|
116
|
+
return _build(name, BLUE_BLACK_RED)
|
|
117
|
+
if name in matplotlib.colormaps:
|
|
118
|
+
return matplotlib.colormaps[name]
|
|
119
|
+
raise ValueError(f"Unknown color map '{name}': use one of {', '.join(names())} or a matplotlib name.")
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def register(gwyddion=False):
|
|
123
|
+
""" Adds the Nanosurf maps and BlueBlackRed (and their reversed versions, name + '_r') to matplotlib; with
|
|
124
|
+
gwyddion=True also the gradients of an installed Gwyddion (a name that is taken gets ' (Gwyddion)'). Returns the
|
|
125
|
+
names. Calling it again does nothing new. """
|
|
126
|
+
import matplotlib
|
|
127
|
+
out = names()
|
|
128
|
+
for name in out:
|
|
129
|
+
if name not in matplotlib.colormaps:
|
|
130
|
+
cmap = colormap(name)
|
|
131
|
+
matplotlib.colormaps.register(cmap, name=name)
|
|
132
|
+
matplotlib.colormaps.register(cmap.reversed(), name=name + "_r")
|
|
133
|
+
if gwyddion:
|
|
134
|
+
for name, path in gwyddion_gradients().items():
|
|
135
|
+
target = name if name not in matplotlib.colormaps else f"{name} (Gwyddion)"
|
|
136
|
+
if target not in matplotlib.colormaps:
|
|
137
|
+
try:
|
|
138
|
+
cmap = LinearSegmentedColormap.from_list(target, read_gradient(path), N=256)
|
|
139
|
+
except (ValueError, OSError, UnicodeError):
|
|
140
|
+
continue
|
|
141
|
+
matplotlib.colormaps.register(cmap, name=target)
|
|
142
|
+
out.append(target)
|
|
143
|
+
return out
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def gwyddion_dirs(platform=None, environ=None, home=None):
|
|
147
|
+
""" The gradient folders of an installed Gwyddion that exist, the user's own first (they win over the system ones).
|
|
148
|
+
|
|
149
|
+
Searched, after Gwyddion's documentation (resources: user folder ~/.gwyddion, on Windows %USERPROFILE%\\gwyddion;
|
|
150
|
+
system folder share/gwyddion, or $GWYDDION_DATADIR/gwyddion):
|
|
151
|
+
all $GWYDDION_DATADIR/gwyddion/gradients; next to a gwyddion program on the PATH (../share/...)
|
|
152
|
+
Windows %USERPROFILE%\\gwyddion, Documents\\gwyddion; Program Files (64 and 32 bit), %LOCALAPPDATA%\\Programs:
|
|
153
|
+
Gwyddion\\share\\gwyddion\\gradients
|
|
154
|
+
macOS ~/.gwyddion; Gwyddion.app in /Applications or ~/Applications; Homebrew, MacPorts, /usr/local
|
|
155
|
+
Linux, other ~/.gwyddion; /usr/share, /usr/local/share; Flatpak (system and user)
|
|
156
|
+
"""
|
|
157
|
+
platform = platform or sys.platform
|
|
158
|
+
environ = os.environ if environ is None else environ
|
|
159
|
+
home = pathlib.Path(home) if home else pathlib.Path.home()
|
|
160
|
+
tail = pathlib.Path("gwyddion", "gradients")
|
|
161
|
+
user, system = [], []
|
|
162
|
+
if environ.get("GWYDDION_DATADIR"):
|
|
163
|
+
system.append(pathlib.Path(environ["GWYDDION_DATADIR"]) / tail)
|
|
164
|
+
program = shutil.which("gwyddion", path=environ.get("PATH")) if environ.get("PATH") else None
|
|
165
|
+
if program:
|
|
166
|
+
system.append(pathlib.Path(program).resolve().parent.parent / "share" / tail)
|
|
167
|
+
if platform.startswith("win"):
|
|
168
|
+
profile = pathlib.Path(environ.get("USERPROFILE", home))
|
|
169
|
+
user += [profile / "gwyddion" / "gradients", profile / "Documents" / "gwyddion" / "gradients"]
|
|
170
|
+
roots = [environ.get(k) for k in ("ProgramFiles", "ProgramW6432", "ProgramFiles(x86)")]
|
|
171
|
+
roots += [str(pathlib.Path(environ["LOCALAPPDATA"]) / "Programs")] if environ.get("LOCALAPPDATA") else []
|
|
172
|
+
roots += ["C:\\Program Files", "C:\\Program Files (x86)"]
|
|
173
|
+
system += [pathlib.Path(r) / "Gwyddion" / "share" / tail for r in roots if r]
|
|
174
|
+
elif platform == "darwin":
|
|
175
|
+
user.append(home / ".gwyddion" / "gradients")
|
|
176
|
+
apps = [pathlib.Path("/Applications"), home / "Applications"]
|
|
177
|
+
system += [a / "Gwyddion.app" / "Contents" / "Resources" / "share" / tail for a in apps]
|
|
178
|
+
system += [pathlib.Path(p) / tail for p in ("/opt/homebrew/share", "/opt/local/share", "/usr/local/share")]
|
|
179
|
+
else:
|
|
180
|
+
user.append(home / ".gwyddion" / "gradients")
|
|
181
|
+
flatpak = pathlib.Path("app", "net.gwyddion.Gwyddion", "current", "active", "files", "share") / tail
|
|
182
|
+
system += [pathlib.Path(p) / tail for p in ("/usr/share", "/usr/local/share")]
|
|
183
|
+
system += [pathlib.Path("/var/lib/flatpak") / flatpak, home / ".local" / "share" / "flatpak" / flatpak]
|
|
184
|
+
found = []
|
|
185
|
+
for folder in user + system:
|
|
186
|
+
try:
|
|
187
|
+
if folder.is_dir() and folder.resolve() not in [f.resolve() for f in found]:
|
|
188
|
+
found.append(folder)
|
|
189
|
+
except OSError:
|
|
190
|
+
pass
|
|
191
|
+
return found
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def gwyddion_gradients(**kwargs):
|
|
195
|
+
""" {name: path} of the gradient files of an installed Gwyddion (gwyddion_dirs; the user's own win). """
|
|
196
|
+
out = {}
|
|
197
|
+
for folder in gwyddion_dirs(**kwargs):
|
|
198
|
+
for path in sorted(folder.iterdir()):
|
|
199
|
+
if path.is_file() and path.name not in out:
|
|
200
|
+
out[path.name] = path
|
|
201
|
+
return out
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def read_gradient(path):
|
|
205
|
+
""" [(position, (r, g, b)), ...] of a Gwyddion gradient file. """
|
|
206
|
+
lines = pathlib.Path(path).read_text(encoding="utf-8", errors="replace").splitlines()
|
|
207
|
+
if not lines or not lines[0].startswith("Gwyddion resource GwyGradient"):
|
|
208
|
+
raise ValueError(f"{path} is not a Gwyddion gradient file.")
|
|
209
|
+
rows = [[float(v) for v in line.split()] for line in lines[1:] if line.strip()]
|
|
210
|
+
return [(row[0], tuple(row[1:4])) for row in rows]
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
class colors:
|
|
214
|
+
""" A color map by name, in .cmap.
|
|
215
|
+
|
|
216
|
+
Parameters
|
|
217
|
+
----------
|
|
218
|
+
name : string
|
|
219
|
+
A Nanosurf map (NANOSURF), "BlueBlackRed", an older name (ALIASES), a matplotlib map, the name of a
|
|
220
|
+
gradient file in gwy_dir, or of a gradient of an installed Gwyddion (gwyddion_dirs)
|
|
221
|
+
gwy_dir : string, optional
|
|
222
|
+
Folder with Gwyddion gradient files (not part of NSFopen); without it an installed Gwyddion is searched
|
|
223
|
+
"""
|
|
224
|
+
|
|
225
|
+
def __init__(self, name=None, gwy_dir=None, **kwargs):
|
|
226
|
+
self.name = name
|
|
227
|
+
self.gwy_dir = pathlib.Path(gwy_dir) if gwy_dir else None
|
|
228
|
+
self.cmap_list = {"Nanosurf": list(NANOSURF), "Custom": ["BlueBlackRed"]}
|
|
229
|
+
if self.gwy_dir is not None and self.gwy_dir.is_dir():
|
|
230
|
+
files = {p.name: p for p in self.gwy_dir.iterdir() if p.is_file()}
|
|
231
|
+
else:
|
|
232
|
+
files = gwyddion_gradients()
|
|
233
|
+
if files:
|
|
234
|
+
self.cmap_list["Gwyddion"] = sorted(files, key=str.lower)
|
|
235
|
+
if name is not None and name in files and (self.gwy_dir is not None or name not in NANOSURF):
|
|
236
|
+
self.cmap = LinearSegmentedColormap.from_list(name, read_gradient(files[name]))
|
|
237
|
+
return
|
|
238
|
+
try:
|
|
239
|
+
self.cmap = colormap(name)
|
|
240
|
+
except ValueError:
|
|
241
|
+
print("Name Not Found\n")
|
|
242
|
+
print("Use one of the following choices (or any matplotlib color map):\n")
|
|
243
|
+
print(sorted({x for v in self.cmap_list.values() for x in v}, key=str.lower))
|
|
244
|
+
self.cmap = []
|