gratinglab 0.1.7__tar.gz → 0.1.9__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.
- {gratinglab-0.1.7 → gratinglab-0.1.9}/PKG-INFO +96 -15
- gratinglab-0.1.7/src/gratinglab.egg-info/PKG-INFO → gratinglab-0.1.9/README.md +88 -51
- {gratinglab-0.1.7 → gratinglab-0.1.9}/pyproject.toml +35 -3
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/__init__.py +1 -1
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/app.py +1 -1
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/icon.py +1 -1
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/core/processing.py +26 -8
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/gui/icon.py +1 -1
- gratinglab-0.1.9/src/gratinglab/metrology/wiki/flattening.md +245 -0
- gratinglab-0.1.7/README.md → gratinglab-0.1.9/src/gratinglab.egg-info/PKG-INFO +132 -12
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab.egg-info/SOURCES.txt +1 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab.egg-info/requires.txt +6 -1
- gratinglab-0.1.9/tests/test_changelog.py +34 -0
- gratinglab-0.1.7/src/gratinglab/metrology/wiki/flattening.md +0 -109
- {gratinglab-0.1.7 → gratinglab-0.1.9}/LICENSE +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/setup.cfg +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/checks.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/compare.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/convergence.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/geometry.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/__init__.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/diagram.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/diagram3d.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/docs.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/integral_options.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/mathtext.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/orders.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/provenance.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/qt/__init__.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/qt/gc_guard.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/qt/geometry_panel.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/qt/geometry_tab.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/qt/integral_tab.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/qt/main_window.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/qt/profile_plot_panel.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/qt/scalar_tab.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/qt/scene3d_panel.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/qt/setup_tab.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/qt/sizing.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/qt/theory_viewer.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/qt/worker.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/richtext.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/scalar_options.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/gui/state.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/illumination.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/io/__init__.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/io/boundary.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/io/efficiency_table.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/io/ggp.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/materials/__init__.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/materials/data/SOURCES.md +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/materials/fresnel.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/materials/optical.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/materials/refractiveindex.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/__init__.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/analyzer.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/boundary/__init__.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/boundary/average.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/boundary/pipeline.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/boundary/swaths.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/cli.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/config.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/core/__init__.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/core/analysis.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/core/image_flatten.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/core/tip.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/data/__init__.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/data/aggregation.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/gui/__init__.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/gui/qt/__init__.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/gui/qt/app.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/gui/qt/boundary_view.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/gui/qt/canvas.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/gui/qt/efficiency_dialog.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/gui/qt/import_view.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/gui/qt/main_window.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/gui/qt/swath_dialog.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/gui/qt/wiki_view.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/gui/qt/worker.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/gui/state.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/io/__init__.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/io/file_io.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/io/metrics.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/io/spm.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/settings.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/stats/__init__.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/stats/analysis.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/stats/icc.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/visualization/__init__.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/visualization/diagnostics.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/visualization/profiles.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/visualization/statistics.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/wiki/__init__.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/wiki/facet-fitting.md +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/wiki/file-formats.md +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/wiki/icc-correction.md +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/wiki/overview.md +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/wiki/reading-outputs.md +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/wiki/row-groups.md +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/wiki/swath-statistics.md +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/wiki/tip-correction.md +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/metrology/workflows.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/problem.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/profiles.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/resolution.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/result.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/solvers/__init__.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/solvers/base.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/solvers/integral/__init__.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/solvers/integral/_boundary.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/solvers/integral/_core.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/solvers/integral/_finite.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/solvers/integral/_greens.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/solvers/integral/_kernels.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/solvers/integral/_nystrom.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab/solvers/scalar.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab.egg-info/dependency_links.txt +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab.egg-info/entry_points.txt +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/src/gratinglab.egg-info/top_level.txt +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_checks.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_compare.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_convergence.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_cross_method.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_efficiency_table.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_fresnel.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_geometry.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_ggp.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_gui_diagram.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_gui_diagram3d.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_gui_docs.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_gui_integral_options.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_gui_mathtext.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_gui_orders.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_gui_provenance.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_gui_qt.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_gui_richtext.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_gui_scalar_options.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_gui_state.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_illumination.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_integral_core.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_integral_corpus.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_integral_finite.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_integral_greens.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_integral_kernels.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_integral_operators.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_integral_solver.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_io_boundary.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_materials.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_perturbation.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_profiles.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_refractiveindex.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_resolution.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_result.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_scalar.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_solver_conformance.py +0 -0
- {gratinglab-0.1.7 → gratinglab-0.1.9}/tests/test_solver_progress.py +0 -0
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gratinglab
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.9
|
|
4
4
|
Summary: Open platform for diffraction grating groove metrology and efficiency analysis
|
|
5
5
|
Author: Jake McCoy
|
|
6
6
|
License: BSD-3-Clause
|
|
7
7
|
Project-URL: Homepage, https://github.com/jamccoy/gratinglab
|
|
8
|
-
|
|
8
|
+
Project-URL: Changelog, https://github.com/jamccoy/gratinglab/blob/master/CHANGELOG.md
|
|
9
|
+
Keywords: diffraction,grating,diffraction grating,diffraction efficiency,optics,rcwa,integral method,spectroscopy,afm,metrology,blaze,groove profile,ultraviolet,infrared,x-ray
|
|
9
10
|
Classifier: Development Status :: 2 - Pre-Alpha
|
|
10
11
|
Classifier: Intended Audience :: Science/Research
|
|
11
12
|
Classifier: License :: OSI Approved :: BSD License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
12
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
13
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
14
16
|
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
15
19
|
Requires-Python: >=3.11
|
|
16
20
|
Description-Content-Type: text/markdown
|
|
17
21
|
License-File: LICENSE
|
|
@@ -27,7 +31,8 @@ Requires-Dist: pandas>=2.1; extra == "dev"
|
|
|
27
31
|
Requires-Dist: ruff>=0.16; extra == "dev"
|
|
28
32
|
Provides-Extra: gui
|
|
29
33
|
Requires-Dist: matplotlib>=3.8; extra == "gui"
|
|
30
|
-
Requires-Dist: PySide6-Essentials
|
|
34
|
+
Requires-Dist: PySide6-Essentials!=6.12.0,>=6.7; python_version < "3.12" and extra == "gui"
|
|
35
|
+
Requires-Dist: PySide6-Essentials>=6.7; python_version >= "3.12" and extra == "gui"
|
|
31
36
|
Requires-Dist: endstation[qt]>=0.2.2; extra == "gui"
|
|
32
37
|
Provides-Extra: metrology
|
|
33
38
|
Requires-Dist: matplotlib>=3.9; extra == "metrology"
|
|
@@ -44,7 +49,7 @@ Dynamic: license-file
|
|
|
44
49
|
[](https://github.com/jamccoy/gratinglab/actions/workflows/test.yml)
|
|
45
50
|
[](https://github.com/jamccoy/gratinglab/blob/master/LICENSE)
|
|
46
51
|
|
|
47
|
-
**[PyPI](https://pypi.org/project/gratinglab/)** · **[Documentation](https://github.com/jamccoy/gratinglab/wiki)** · **[Releases](https://github.com/jamccoy/gratinglab/releases)** · **[Issues](https://github.com/jamccoy/gratinglab/issues)**
|
|
52
|
+
**[PyPI](https://pypi.org/project/gratinglab/)** · **[Documentation](https://github.com/jamccoy/gratinglab/wiki)** · **[Changelog](https://github.com/jamccoy/gratinglab/blob/master/CHANGELOG.md)** · **[Releases](https://github.com/jamccoy/gratinglab/releases)** · **[Issues](https://github.com/jamccoy/gratinglab/issues)**
|
|
48
53
|
|
|
49
54
|
gratinglab is a Python package for measuring the groove profiles of diffraction
|
|
50
55
|
gratings from atomic force microscope (AFM) scans and for computing the diffraction
|
|
@@ -225,12 +230,14 @@ does not install one. A subpackage that needs an optional extra names it when it
|
|
|
225
230
|
missing, instead of failing with a bare `ModuleNotFoundError`.
|
|
226
231
|
|
|
227
232
|
Apart from numpy, scipy and pydantic, the only dependency is
|
|
228
|
-
[endstation](https://
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
233
|
+
**[endstation](https://pypi.org/project/endstation/)**
|
|
234
|
+
([source](https://github.com/jamccoy/endstation)), a library of shared components for
|
|
235
|
+
desktop scientific applications by the same author, which gratinglab is built on.
|
|
236
|
+
gratinglab uses its guards for optional extras (the messages described above), form
|
|
237
|
+
validation, Qt layout sizing, test helpers, and the tools that build the icon and the
|
|
238
|
+
macOS application and publish the wiki. The core of endstation has no dependencies of
|
|
239
|
+
its own, so it adds nothing to a solver-only install; its Qt components are installed
|
|
240
|
+
only with the `gui` extra.
|
|
234
241
|
|
|
235
242
|
### Where the measurement data lives
|
|
236
243
|
|
|
@@ -293,9 +300,14 @@ contributed backend appears in the window once it is registered.
|
|
|
293
300
|
|
|
294
301
|
The Help menu contains the theory pages, rendered with typeset equations and tables.
|
|
295
302
|
|
|
296
|
-
A macOS `.app` can be built with `python tools/
|
|
297
|
-
|
|
298
|
-
`
|
|
303
|
+
A macOS `.app` can be built for either window with `python tools/apps.py bundle --app
|
|
304
|
+
gratinglab` (or `--app metrology`), on macOS 13 or later, the minimum supported by the
|
|
305
|
+
PySide6 wheels. `--dest ~/Applications` puts it where Finder will list it. The bundle
|
|
306
|
+
is a stub that execs the console script in this checkout's virtualenv rather than a
|
|
307
|
+
frozen application, so it is not portable to another machine; `python tools/apps.py
|
|
308
|
+
check --app gratinglab` reports when that virtualenv has moved, which is the one
|
|
309
|
+
failure a bundle cannot show from the outside. `python tools/apps.py icon --app
|
|
310
|
+
gratinglab` regenerates the icon from the artwork in `gratinglab.gui.icon`.
|
|
299
311
|
|
|
300
312
|
## Documentation
|
|
301
313
|
|
|
@@ -367,6 +379,75 @@ The test suite relies on three practices in particular:
|
|
|
367
379
|
.venv/bin/mutmut run
|
|
368
380
|
```
|
|
369
381
|
|
|
370
|
-
## License
|
|
382
|
+
## License, copyright and reuse
|
|
371
383
|
|
|
372
|
-
|
|
384
|
+
gratinglab is released under the
|
|
385
|
+
[BSD 3-Clause License](https://github.com/jamccoy/gratinglab/blob/master/LICENSE),
|
|
386
|
+
copyright (c) 2026 Jake McCoy. What follows is a plain summary for convenience; the
|
|
387
|
+
`LICENSE` file is what governs, and nothing here is legal advice.
|
|
388
|
+
|
|
389
|
+
**What you may do.** Use, modify and redistribute the code, in source or binary form,
|
|
390
|
+
for any purpose, including commercial use and inside closed-source work. There is no
|
|
391
|
+
copyleft obligation: software that imports gratinglab does not become BSD-licensed,
|
|
392
|
+
and you are not required to publish your modifications.
|
|
393
|
+
|
|
394
|
+
**What you must do.** Retain the copyright notice, the list of conditions and the
|
|
395
|
+
disclaimer when you redistribute — in the source for a source distribution, and in the
|
|
396
|
+
documentation or other accompanying materials for a binary one. The third clause
|
|
397
|
+
separately forbids using the author's or contributors' names to endorse or promote a
|
|
398
|
+
derived product without prior written permission.
|
|
399
|
+
|
|
400
|
+
**What you do not get.** The software is provided as is, without warranty of any kind,
|
|
401
|
+
and the author is not liable for any use of it. That disclaimer carries more weight
|
|
402
|
+
here than it does for most packages, because the efficiency solvers are experimental
|
|
403
|
+
(see Status): a number this software produces is evidence to be checked against
|
|
404
|
+
another method, not a result to be relied on because a computer printed it.
|
|
405
|
+
|
|
406
|
+
Contributions are accepted under the same licence. A pull request is taken as agreement
|
|
407
|
+
that the contribution may be distributed under BSD-3-Clause.
|
|
408
|
+
|
|
409
|
+
### Citing it
|
|
410
|
+
|
|
411
|
+
[`CITATION.cff`](https://github.com/jamccoy/gratinglab/blob/master/CITATION.cff) is
|
|
412
|
+
the citation of record, and GitHub's "Cite this repository" renders it as BibTeX or
|
|
413
|
+
APA. It names the version, which is checked against `gratinglab.__version__` on every
|
|
414
|
+
release, so a citation generated from it points at the code that produced the number
|
|
415
|
+
rather than at whatever is current. If a result depends on a solver backend or on an
|
|
416
|
+
optical constant table, cite those too: the method's own reference is in
|
|
417
|
+
[`docs/references.md`](https://github.com/jamccoy/gratinglab/blob/master/docs/references.md),
|
|
418
|
+
and `Provenance` records what a run actually used.
|
|
419
|
+
|
|
420
|
+
### The licences you inherit by installing it
|
|
421
|
+
|
|
422
|
+
| Installed with | Package | Licence |
|
|
423
|
+
|---|---|---|
|
|
424
|
+
| core | numpy, scipy | BSD-3-Clause |
|
|
425
|
+
| core | pydantic | MIT |
|
|
426
|
+
| core | [endstation](https://pypi.org/project/endstation/) | BSD-3-Clause |
|
|
427
|
+
| `[gui]`, `[metrology]` | matplotlib | PSF-based, BSD-compatible |
|
|
428
|
+
| `[gui]` | PySide6-Essentials | LGPL-3.0 |
|
|
429
|
+
| `[refractiveindex]` | PyYAML | MIT |
|
|
430
|
+
|
|
431
|
+
A solver-only install is permissive throughout. The `gui` extra is the one worth
|
|
432
|
+
knowing about: Qt for Python is LGPL-3.0, which is the reason this project depends on
|
|
433
|
+
PySide6 and not on PyQt6, whose licence is GPL and would reach your own code.
|
|
434
|
+
Importing an LGPL library dynamically does not change the licence of what you write,
|
|
435
|
+
but redistributing a bundled application that ships Qt inside it brings LGPL
|
|
436
|
+
obligations for that component — chiefly your users' right to substitute their own
|
|
437
|
+
build of it. Running the window yourself, or installing either extra from PyPI, raises
|
|
438
|
+
no such question.
|
|
439
|
+
|
|
440
|
+
### What this licence does not cover
|
|
441
|
+
|
|
442
|
+
**Optical constant tables.** None are distributed with the package, and a table you
|
|
443
|
+
add is governed by the terms of whoever published it, not by this licence. CXRO and
|
|
444
|
+
refractiveindex.info each state their own, and a table exported from another program
|
|
445
|
+
carries whatever that program's terms attach to it.
|
|
446
|
+
[`SOURCES.md`](https://github.com/jamccoy/gratinglab/blob/master/src/gratinglab/materials/data/SOURCES.md)
|
|
447
|
+
records where each kind comes from and why none ships here.
|
|
448
|
+
|
|
449
|
+
**Measurement data.** AFM scans and the reference efficiency corpus are the research
|
|
450
|
+
group's data and are deliberately absent from the repository, as described above under
|
|
451
|
+
Install. The code is open; the measurements it was validated against are not ours to
|
|
452
|
+
publish, and the documentation says which results are therefore not reproducible from
|
|
453
|
+
a bare clone.
|
|
@@ -1,42 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: gratinglab
|
|
3
|
-
Version: 0.1.7
|
|
4
|
-
Summary: Open platform for diffraction grating groove metrology and efficiency analysis
|
|
5
|
-
Author: Jake McCoy
|
|
6
|
-
License: BSD-3-Clause
|
|
7
|
-
Project-URL: Homepage, https://github.com/jamccoy/gratinglab
|
|
8
|
-
Keywords: diffraction,grating,efficiency,rcwa,x-ray,spectroscopy,afm,metrology,blaze,pcgrate
|
|
9
|
-
Classifier: Development Status :: 2 - Pre-Alpha
|
|
10
|
-
Classifier: Intended Audience :: Science/Research
|
|
11
|
-
Classifier: License :: OSI Approved :: BSD License
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
-
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
15
|
-
Requires-Python: >=3.11
|
|
16
|
-
Description-Content-Type: text/markdown
|
|
17
|
-
License-File: LICENSE
|
|
18
|
-
Requires-Dist: numpy>=1.26
|
|
19
|
-
Requires-Dist: scipy>=1.11
|
|
20
|
-
Requires-Dist: pydantic>=2.6
|
|
21
|
-
Requires-Dist: endstation>=0.2.2
|
|
22
|
-
Provides-Extra: dev
|
|
23
|
-
Requires-Dist: pytest>=7; extra == "dev"
|
|
24
|
-
Requires-Dist: pytest-qt>=4.5; extra == "dev"
|
|
25
|
-
Requires-Dist: matplotlib>=3.8; extra == "dev"
|
|
26
|
-
Requires-Dist: pandas>=2.1; extra == "dev"
|
|
27
|
-
Requires-Dist: ruff>=0.16; extra == "dev"
|
|
28
|
-
Provides-Extra: gui
|
|
29
|
-
Requires-Dist: matplotlib>=3.8; extra == "gui"
|
|
30
|
-
Requires-Dist: PySide6-Essentials>=6.7; extra == "gui"
|
|
31
|
-
Requires-Dist: endstation[qt]>=0.2.2; extra == "gui"
|
|
32
|
-
Provides-Extra: metrology
|
|
33
|
-
Requires-Dist: matplotlib>=3.9; extra == "metrology"
|
|
34
|
-
Provides-Extra: refractiveindex
|
|
35
|
-
Requires-Dist: pyyaml>=6; extra == "refractiveindex"
|
|
36
|
-
Provides-Extra: mut
|
|
37
|
-
Requires-Dist: mutmut<3.3,>=3.2; extra == "mut"
|
|
38
|
-
Dynamic: license-file
|
|
39
|
-
|
|
40
1
|
# gratinglab
|
|
41
2
|
|
|
42
3
|
[](https://pypi.org/project/gratinglab/)
|
|
@@ -44,7 +5,7 @@ Dynamic: license-file
|
|
|
44
5
|
[](https://github.com/jamccoy/gratinglab/actions/workflows/test.yml)
|
|
45
6
|
[](https://github.com/jamccoy/gratinglab/blob/master/LICENSE)
|
|
46
7
|
|
|
47
|
-
**[PyPI](https://pypi.org/project/gratinglab/)** · **[Documentation](https://github.com/jamccoy/gratinglab/wiki)** · **[Releases](https://github.com/jamccoy/gratinglab/releases)** · **[Issues](https://github.com/jamccoy/gratinglab/issues)**
|
|
8
|
+
**[PyPI](https://pypi.org/project/gratinglab/)** · **[Documentation](https://github.com/jamccoy/gratinglab/wiki)** · **[Changelog](https://github.com/jamccoy/gratinglab/blob/master/CHANGELOG.md)** · **[Releases](https://github.com/jamccoy/gratinglab/releases)** · **[Issues](https://github.com/jamccoy/gratinglab/issues)**
|
|
48
9
|
|
|
49
10
|
gratinglab is a Python package for measuring the groove profiles of diffraction
|
|
50
11
|
gratings from atomic force microscope (AFM) scans and for computing the diffraction
|
|
@@ -225,12 +186,14 @@ does not install one. A subpackage that needs an optional extra names it when it
|
|
|
225
186
|
missing, instead of failing with a bare `ModuleNotFoundError`.
|
|
226
187
|
|
|
227
188
|
Apart from numpy, scipy and pydantic, the only dependency is
|
|
228
|
-
[endstation](https://
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
189
|
+
**[endstation](https://pypi.org/project/endstation/)**
|
|
190
|
+
([source](https://github.com/jamccoy/endstation)), a library of shared components for
|
|
191
|
+
desktop scientific applications by the same author, which gratinglab is built on.
|
|
192
|
+
gratinglab uses its guards for optional extras (the messages described above), form
|
|
193
|
+
validation, Qt layout sizing, test helpers, and the tools that build the icon and the
|
|
194
|
+
macOS application and publish the wiki. The core of endstation has no dependencies of
|
|
195
|
+
its own, so it adds nothing to a solver-only install; its Qt components are installed
|
|
196
|
+
only with the `gui` extra.
|
|
234
197
|
|
|
235
198
|
### Where the measurement data lives
|
|
236
199
|
|
|
@@ -293,9 +256,14 @@ contributed backend appears in the window once it is registered.
|
|
|
293
256
|
|
|
294
257
|
The Help menu contains the theory pages, rendered with typeset equations and tables.
|
|
295
258
|
|
|
296
|
-
A macOS `.app` can be built with `python tools/
|
|
297
|
-
|
|
298
|
-
`
|
|
259
|
+
A macOS `.app` can be built for either window with `python tools/apps.py bundle --app
|
|
260
|
+
gratinglab` (or `--app metrology`), on macOS 13 or later, the minimum supported by the
|
|
261
|
+
PySide6 wheels. `--dest ~/Applications` puts it where Finder will list it. The bundle
|
|
262
|
+
is a stub that execs the console script in this checkout's virtualenv rather than a
|
|
263
|
+
frozen application, so it is not portable to another machine; `python tools/apps.py
|
|
264
|
+
check --app gratinglab` reports when that virtualenv has moved, which is the one
|
|
265
|
+
failure a bundle cannot show from the outside. `python tools/apps.py icon --app
|
|
266
|
+
gratinglab` regenerates the icon from the artwork in `gratinglab.gui.icon`.
|
|
299
267
|
|
|
300
268
|
## Documentation
|
|
301
269
|
|
|
@@ -367,6 +335,75 @@ The test suite relies on three practices in particular:
|
|
|
367
335
|
.venv/bin/mutmut run
|
|
368
336
|
```
|
|
369
337
|
|
|
370
|
-
## License
|
|
338
|
+
## License, copyright and reuse
|
|
339
|
+
|
|
340
|
+
gratinglab is released under the
|
|
341
|
+
[BSD 3-Clause License](https://github.com/jamccoy/gratinglab/blob/master/LICENSE),
|
|
342
|
+
copyright (c) 2026 Jake McCoy. What follows is a plain summary for convenience; the
|
|
343
|
+
`LICENSE` file is what governs, and nothing here is legal advice.
|
|
344
|
+
|
|
345
|
+
**What you may do.** Use, modify and redistribute the code, in source or binary form,
|
|
346
|
+
for any purpose, including commercial use and inside closed-source work. There is no
|
|
347
|
+
copyleft obligation: software that imports gratinglab does not become BSD-licensed,
|
|
348
|
+
and you are not required to publish your modifications.
|
|
349
|
+
|
|
350
|
+
**What you must do.** Retain the copyright notice, the list of conditions and the
|
|
351
|
+
disclaimer when you redistribute — in the source for a source distribution, and in the
|
|
352
|
+
documentation or other accompanying materials for a binary one. The third clause
|
|
353
|
+
separately forbids using the author's or contributors' names to endorse or promote a
|
|
354
|
+
derived product without prior written permission.
|
|
355
|
+
|
|
356
|
+
**What you do not get.** The software is provided as is, without warranty of any kind,
|
|
357
|
+
and the author is not liable for any use of it. That disclaimer carries more weight
|
|
358
|
+
here than it does for most packages, because the efficiency solvers are experimental
|
|
359
|
+
(see Status): a number this software produces is evidence to be checked against
|
|
360
|
+
another method, not a result to be relied on because a computer printed it.
|
|
361
|
+
|
|
362
|
+
Contributions are accepted under the same licence. A pull request is taken as agreement
|
|
363
|
+
that the contribution may be distributed under BSD-3-Clause.
|
|
364
|
+
|
|
365
|
+
### Citing it
|
|
366
|
+
|
|
367
|
+
[`CITATION.cff`](https://github.com/jamccoy/gratinglab/blob/master/CITATION.cff) is
|
|
368
|
+
the citation of record, and GitHub's "Cite this repository" renders it as BibTeX or
|
|
369
|
+
APA. It names the version, which is checked against `gratinglab.__version__` on every
|
|
370
|
+
release, so a citation generated from it points at the code that produced the number
|
|
371
|
+
rather than at whatever is current. If a result depends on a solver backend or on an
|
|
372
|
+
optical constant table, cite those too: the method's own reference is in
|
|
373
|
+
[`docs/references.md`](https://github.com/jamccoy/gratinglab/blob/master/docs/references.md),
|
|
374
|
+
and `Provenance` records what a run actually used.
|
|
375
|
+
|
|
376
|
+
### The licences you inherit by installing it
|
|
377
|
+
|
|
378
|
+
| Installed with | Package | Licence |
|
|
379
|
+
|---|---|---|
|
|
380
|
+
| core | numpy, scipy | BSD-3-Clause |
|
|
381
|
+
| core | pydantic | MIT |
|
|
382
|
+
| core | [endstation](https://pypi.org/project/endstation/) | BSD-3-Clause |
|
|
383
|
+
| `[gui]`, `[metrology]` | matplotlib | PSF-based, BSD-compatible |
|
|
384
|
+
| `[gui]` | PySide6-Essentials | LGPL-3.0 |
|
|
385
|
+
| `[refractiveindex]` | PyYAML | MIT |
|
|
386
|
+
|
|
387
|
+
A solver-only install is permissive throughout. The `gui` extra is the one worth
|
|
388
|
+
knowing about: Qt for Python is LGPL-3.0, which is the reason this project depends on
|
|
389
|
+
PySide6 and not on PyQt6, whose licence is GPL and would reach your own code.
|
|
390
|
+
Importing an LGPL library dynamically does not change the licence of what you write,
|
|
391
|
+
but redistributing a bundled application that ships Qt inside it brings LGPL
|
|
392
|
+
obligations for that component — chiefly your users' right to substitute their own
|
|
393
|
+
build of it. Running the window yourself, or installing either extra from PyPI, raises
|
|
394
|
+
no such question.
|
|
395
|
+
|
|
396
|
+
### What this licence does not cover
|
|
397
|
+
|
|
398
|
+
**Optical constant tables.** None are distributed with the package, and a table you
|
|
399
|
+
add is governed by the terms of whoever published it, not by this licence. CXRO and
|
|
400
|
+
refractiveindex.info each state their own, and a table exported from another program
|
|
401
|
+
carries whatever that program's terms attach to it.
|
|
402
|
+
[`SOURCES.md`](https://github.com/jamccoy/gratinglab/blob/master/src/gratinglab/materials/data/SOURCES.md)
|
|
403
|
+
records where each kind comes from and why none ships here.
|
|
371
404
|
|
|
372
|
-
|
|
405
|
+
**Measurement data.** AFM scans and the reference efficiency corpus are the research
|
|
406
|
+
group's data and are deliberately absent from the repository, as described above under
|
|
407
|
+
Install. The code is open; the measurements it was validated against are not ours to
|
|
408
|
+
publish, and the documentation says which results are therefore not reproducible from
|
|
409
|
+
a bare clone.
|
|
@@ -14,15 +14,33 @@ readme = "README.md"
|
|
|
14
14
|
requires-python = ">=3.11"
|
|
15
15
|
license = { text = "BSD-3-Clause" }
|
|
16
16
|
authors = [{ name = "Jake McCoy" }]
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
# Wavelength-neutral on purpose. The off-plane work this package grew out of is
|
|
18
|
+
# soft x-ray, and that band is still named, but nothing in the solvers or the
|
|
19
|
+
# metrology assumes one: the grating equation carries no band, and the
|
|
20
|
+
# materials layer reads CXRO x-ray tables and refractiveindex.info
|
|
21
|
+
# ultraviolet-to-infrared tables alike. Leading with "x-ray" told a reader the
|
|
22
|
+
# in-plane half of the package was not meant for them.
|
|
23
|
+
#
|
|
24
|
+
# "pcgrate" is deliberately absent. It is a program this project validates
|
|
25
|
+
# against, not a feature of this one, and a search for it should not land here.
|
|
26
|
+
keywords = ["diffraction", "grating", "diffraction grating", "diffraction efficiency",
|
|
27
|
+
"optics", "rcwa", "integral method", "spectroscopy", "afm", "metrology",
|
|
28
|
+
"blaze", "groove profile", "ultraviolet", "infrared", "x-ray"]
|
|
29
|
+
# Only classifiers from the trove list, which PyPI rejects uploads over. Note
|
|
30
|
+
# that there is no `Topic :: Scientific/Engineering :: Optics`; Physics is the
|
|
31
|
+
# nearest, with Information Analysis for the metrology and Visualization for
|
|
32
|
+
# the windows. No Qt environment classifier: a classifier cannot be made
|
|
33
|
+
# conditional on an extra, and a default install pulls no toolkit at all.
|
|
19
34
|
classifiers = [
|
|
20
35
|
"Development Status :: 2 - Pre-Alpha",
|
|
21
36
|
"Intended Audience :: Science/Research",
|
|
22
37
|
"License :: OSI Approved :: BSD License",
|
|
38
|
+
"Operating System :: OS Independent",
|
|
23
39
|
"Programming Language :: Python :: 3.11",
|
|
24
40
|
"Programming Language :: Python :: 3.12",
|
|
25
41
|
"Topic :: Scientific/Engineering :: Physics",
|
|
42
|
+
"Topic :: Scientific/Engineering :: Information Analysis",
|
|
43
|
+
"Topic :: Scientific/Engineering :: Visualization",
|
|
26
44
|
]
|
|
27
45
|
dependencies = [
|
|
28
46
|
"numpy>=1.26",
|
|
@@ -48,7 +66,20 @@ dev = ["pytest>=7", "pytest-qt>=4.5", "matplotlib>=3.8", "pandas>=2.1", "ruff>=0
|
|
|
48
66
|
#
|
|
49
67
|
# PySide6 (LGPLv3) rather than PyQt6 (GPL): this package is BSD-3, and an
|
|
50
68
|
# optional dynamically-linked dependency keeps it that way.
|
|
51
|
-
|
|
69
|
+
#
|
|
70
|
+
# PySide6 6.12.0 on Python 3.11 aborts the interpreter at exit (Fatal Python
|
|
71
|
+
# error: bool_dealloc) after heavy GUI use: it releases a reference to True or
|
|
72
|
+
# False that it does not own, which on 3.11 eventually frees the object during
|
|
73
|
+
# finalization. On 3.12 and later True and False are immortal and the bug is
|
|
74
|
+
# harmless. Measured in CI on 2026-10-22: 6.9.3, 6.10.3 and 6.11.2 passed twice
|
|
75
|
+
# each and 6.12.0 crashed twice. Only that release is excluded, and only on 3.11,
|
|
76
|
+
# so a fixed 6.12.x is taken as soon as it exists.
|
|
77
|
+
gui = [
|
|
78
|
+
"matplotlib>=3.8",
|
|
79
|
+
"PySide6-Essentials>=6.7,!=6.12.0; python_version < '3.12'",
|
|
80
|
+
"PySide6-Essentials>=6.7; python_version >= '3.12'",
|
|
81
|
+
"endstation[qt]>=0.2.2",
|
|
82
|
+
]
|
|
52
83
|
# Groove metrology: reading AFM scans and averaging them into a boundary
|
|
53
84
|
# profile. An extra for the same reason the GUI is one -- `pip install
|
|
54
85
|
# gratinglab` must stay numpy/scipy/pydantic, so a solver-only user never
|
|
@@ -76,6 +107,7 @@ gratinglab-metrology = "gratinglab.metrology.cli:main"
|
|
|
76
107
|
|
|
77
108
|
[project.urls]
|
|
78
109
|
Homepage = "https://github.com/jamccoy/gratinglab"
|
|
110
|
+
Changelog = "https://github.com/jamccoy/gratinglab/blob/master/CHANGELOG.md"
|
|
79
111
|
|
|
80
112
|
# Solver backends register here. A backend may live in its own distribution.
|
|
81
113
|
[project.entry-points."gratinglab.solvers"]
|
|
@@ -21,7 +21,7 @@ from .illumination import Illumination, Polarization
|
|
|
21
21
|
from .resolution import ResolvingPower, resolving_power
|
|
22
22
|
from .result import EfficiencyScan, OrderEfficiency, Provenance
|
|
23
23
|
|
|
24
|
-
__version__ = "0.1.
|
|
24
|
+
__version__ = "0.1.9"
|
|
25
25
|
|
|
26
26
|
__all__ = [
|
|
27
27
|
"Illumination",
|
|
@@ -58,7 +58,7 @@ def _bring_to_front(window) -> None:
|
|
|
58
58
|
The fallback was therefore a `subprocess.run` on every launch, wrapped in
|
|
59
59
|
a bare `except`, which did nothing in the one case it was written for, and
|
|
60
60
|
it has been removed. The supported way to bring the window forward when
|
|
61
|
-
starting from a shell is to launch the bundle, which `tools/
|
|
61
|
+
starting from a shell is to launch the bundle, which `tools/apps.py bundle`
|
|
62
62
|
builds and the README describes.
|
|
63
63
|
"""
|
|
64
64
|
window.raise_()
|
|
@@ -9,7 +9,7 @@ is what this software computes. It uses a few thick elements so that it
|
|
|
9
9
|
remains legible at 16 px, the size at which icons most often become
|
|
10
10
|
unreadable.
|
|
11
11
|
|
|
12
|
-
``tools/
|
|
12
|
+
``tools/apps.py icon`` turns this into a macOS ``.icns``.
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
@@ -186,7 +186,9 @@ def flatten_profile(x, y, method='linear', poly_order=2, exclude_edges=0.0,
|
|
|
186
186
|
Parameters:
|
|
187
187
|
method: 'linear', 'polynomial', 'groove_peaks', or 'level_grooves'
|
|
188
188
|
poly_order: polynomial order (for 'polynomial' and 'level_grooves' methods)
|
|
189
|
-
exclude_edges: fraction of data to exclude from edges (0.0 to 0.5)
|
|
189
|
+
exclude_edges: fraction of data to exclude from edges (0.0 to 0.5).
|
|
190
|
+
For 'level_grooves' it is skipped, with a warning, when excluding
|
|
191
|
+
the edges would leave too few features to fit the requested order.
|
|
190
192
|
feature: for 'level_grooves': 'peaks', 'troughs', or 'both'
|
|
191
193
|
period_nm: estimated period for finding grooves (for 'level_grooves')
|
|
192
194
|
|
|
@@ -262,13 +264,29 @@ def flatten_profile(x, y, method='linear', poly_order=2, exclude_edges=0.0,
|
|
|
262
264
|
x_min = x[0] + exclude_edges * (x[-1] - x[0])
|
|
263
265
|
x_max = x[-1] - exclude_edges * (x[-1] - x[0])
|
|
264
266
|
mask = (feature_x >= x_min) & (feature_x <= x_max)
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
267
|
+
kept = int(np.count_nonzero(mask))
|
|
268
|
+
# Edge exclusion is meant to improve the fit, so it must not be
|
|
269
|
+
# allowed to starve it. This used to keep the remnant and fit
|
|
270
|
+
# that while printing "using all": with two features left and a
|
|
271
|
+
# quadratic asked for, the background was rank-deficient and
|
|
272
|
+
# still looked like a fit.
|
|
273
|
+
if kept >= poly_order + 1:
|
|
274
|
+
feature_x = feature_x[mask]
|
|
275
|
+
feature_y = feature_y[mask]
|
|
276
|
+
else:
|
|
277
|
+
print(f" Warning: edge exclusion leaves {kept} feature(s), "
|
|
278
|
+
f"too few for a degree-{poly_order} background; "
|
|
279
|
+
"using all of them")
|
|
280
|
+
|
|
281
|
+
# A degree-k polynomial needs k+1 points to be determined. Reaching
|
|
282
|
+
# here guarantees two, so the order is reduced rather than letting
|
|
283
|
+
# polyfit return a rank-deficient answer behind a RankWarning.
|
|
284
|
+
order = min(poly_order, len(feature_x) - 1)
|
|
285
|
+
if order < poly_order:
|
|
286
|
+
print(f" Warning: {len(feature_x)} feature(s) support only a "
|
|
287
|
+
f"degree-{order} background, not degree-{poly_order}")
|
|
288
|
+
|
|
289
|
+
poly_coeffs = np.polyfit(feature_x, feature_y, order)
|
|
272
290
|
background = np.polyval(poly_coeffs, x)
|
|
273
291
|
else:
|
|
274
292
|
raise ValueError(f"Unknown flattening method: {method}")
|
|
@@ -19,7 +19,7 @@ importing ``gratinglab.metrology.gui`` must stay cheap, since that is what
|
|
|
19
19
|
raises the friendly "PySide6 is an optional extra" message.
|
|
20
20
|
``tests/test_gui_boundary.py`` checks it.
|
|
21
21
|
|
|
22
|
-
``tools/
|
|
22
|
+
``tools/apps.py icon`` turns this into a macOS ``.icns``.
|
|
23
23
|
"""
|
|
24
24
|
|
|
25
25
|
from __future__ import annotations
|