gratinglab 0.2.0__tar.gz → 0.2.2__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.2.0/src/gratinglab.egg-info → gratinglab-0.2.2}/PKG-INFO +3 -3
- {gratinglab-0.2.0 → gratinglab-0.2.2}/pyproject.toml +8 -4
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/__init__.py +1 -1
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/convergence.py +9 -2
- gratinglab-0.2.2/src/gratinglab/gui/__init__.py +30 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/app.py +4 -12
- gratinglab-0.2.2/src/gratinglab/gui/cmethod_options.py +123 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/launcher.py +5 -13
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/qt/__init__.py +4 -5
- gratinglab-0.2.2/src/gratinglab/gui/qt/cmethod_tab.py +469 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/qt/geometry_panel.py +12 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/qt/main_window.py +37 -13
- gratinglab-0.2.2/src/gratinglab/gui/qt/rcwa_tab.py +466 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/qt/worker.py +15 -17
- gratinglab-0.2.2/src/gratinglab/gui/rcwa_options.py +164 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/state.py +62 -9
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/config.py +13 -17
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/gui/__init__.py +11 -13
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/gui/qt/__init__.py +8 -6
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/gui/qt/main_window.py +8 -7
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/wiki/__init__.py +10 -20
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/solvers/base.py +15 -1
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/solvers/cmethod/__init__.py +60 -25
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/solvers/rcwa/__init__.py +51 -20
- {gratinglab-0.2.0 → gratinglab-0.2.2/src/gratinglab.egg-info}/PKG-INFO +3 -3
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab.egg-info/SOURCES.txt +7 -1
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab.egg-info/requires.txt +2 -2
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_cmethod.py +10 -4
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_convergence.py +22 -0
- gratinglab-0.2.2/tests/test_gui_cmethod_options.py +142 -0
- gratinglab-0.2.2/tests/test_gui_cmethod_tab.py +262 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_gui_qt.py +164 -30
- gratinglab-0.2.2/tests/test_gui_rcwa_options.py +95 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_gui_state.py +37 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_solver_progress.py +27 -0
- gratinglab-0.2.0/src/gratinglab/gui/qt/gc_guard.py +0 -102
- gratinglab-0.2.0/src/gratinglab/io/__init__.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/LICENSE +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/README.md +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/setup.cfg +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/checks.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/compare.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/geometry.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/diagram.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/diagram3d.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/docs.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/efficiency_plot.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/icon.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/integral_options.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/mathtext.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/orders.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/provenance.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/qt/geometry_tab.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/qt/integral_tab.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/qt/launcher.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/qt/profile_plot_panel.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/qt/scalar_tab.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/qt/scene3d_panel.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/qt/setup_tab.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/qt/sizing.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/qt/theming.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/qt/theory_viewer.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/richtext.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/scalar_options.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/gui/theme.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/illumination.py +0 -0
- {gratinglab-0.2.0/src/gratinglab/gui → gratinglab-0.2.2/src/gratinglab/io}/__init__.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/io/boundary.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/io/efficiency_table.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/io/ggp.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/materials/__init__.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/materials/data/SOURCES.md +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/materials/fresnel.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/materials/optical.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/materials/refractiveindex.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/measured.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/__init__.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/analyzer.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/boundary/__init__.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/boundary/average.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/boundary/pipeline.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/boundary/swaths.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/cli.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/core/__init__.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/core/analysis.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/core/image_flatten.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/core/orientation.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/core/processing.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/core/region_mask.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/core/scars.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/core/tip.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/data/__init__.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/data/aggregation.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/gui/icon.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/gui/qt/app.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/gui/qt/boundary_view.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/gui/qt/canvas.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/gui/qt/efficiency_dialog.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/gui/qt/import_view.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/gui/qt/swath_dialog.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/gui/qt/wiki_view.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/gui/qt/worker.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/gui/state.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/io/__init__.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/io/file_io.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/io/ibw.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/io/metrics.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/io/spm.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/settings.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/stats/__init__.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/stats/analysis.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/stats/icc.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/visualization/__init__.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/visualization/diagnostics.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/visualization/profiles.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/visualization/statistics.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/wiki/facet-fitting.md +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/wiki/file-formats.md +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/wiki/flattening.md +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/wiki/groove-orientation.md +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/wiki/icc-correction.md +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/wiki/overview.md +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/wiki/reading-outputs.md +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/wiki/row-groups.md +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/wiki/scars-and-masking.md +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/wiki/swath-statistics.md +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/wiki/tip-correction.md +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/metrology/workflows.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/problem.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/profiles.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/resolution.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/result.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/solvers/__init__.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/solvers/_conditioning.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/solvers/_execution.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/solvers/cmethod/_core.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/solvers/cmethod/_series.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/solvers/integral/__init__.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/solvers/integral/_boundary.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/solvers/integral/_core.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/solvers/integral/_finite.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/solvers/integral/_greens.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/solvers/integral/_kernels.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/solvers/integral/_nystrom.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/solvers/rcwa/_core.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/solvers/rcwa/_stack.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab/solvers/scalar.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab.egg-info/dependency_links.txt +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab.egg-info/entry_points.txt +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/src/gratinglab.egg-info/top_level.txt +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_changelog.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_checks.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_compare.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_conditioning.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_cross_method.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_efficiency_table.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_fresnel.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_geometry.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_ggp.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_gui_diagram.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_gui_diagram3d.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_gui_docs.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_gui_integral_options.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_gui_launcher.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_gui_mathtext.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_gui_orders.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_gui_provenance.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_gui_richtext.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_gui_scalar_options.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_gui_theme.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_illumination.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_integral_core.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_integral_corpus.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_integral_finite.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_integral_graded.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_integral_greens.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_integral_kernels.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_integral_operators.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_integral_solver.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_io_boundary.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_materials.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_measured.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_perturbation.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_profiles.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_rayleigh_anomaly.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_rcwa.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_rcwa_benchmarks.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_refractiveindex.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_resolution.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_result.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_scalar.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_solver_conformance.py +0 -0
- {gratinglab-0.2.0 → gratinglab-0.2.2}/tests/test_solver_execution.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gratinglab
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Open platform for diffraction grating groove metrology and efficiency analysis
|
|
5
5
|
Author: Jake McCoy, Aditi Gangadharan
|
|
6
6
|
License: BSD-3-Clause
|
|
@@ -22,7 +22,7 @@ License-File: LICENSE
|
|
|
22
22
|
Requires-Dist: numpy>=1.26
|
|
23
23
|
Requires-Dist: scipy>=1.11
|
|
24
24
|
Requires-Dist: pydantic>=2.6
|
|
25
|
-
Requires-Dist: endstation>=0.2.
|
|
25
|
+
Requires-Dist: endstation>=0.2.6
|
|
26
26
|
Requires-Dist: threadpoolctl>=3.1
|
|
27
27
|
Provides-Extra: dev
|
|
28
28
|
Requires-Dist: pytest>=7; extra == "dev"
|
|
@@ -34,7 +34,7 @@ Provides-Extra: gui
|
|
|
34
34
|
Requires-Dist: matplotlib>=3.8; extra == "gui"
|
|
35
35
|
Requires-Dist: PySide6-Essentials!=6.12.0,>=6.7; python_version < "3.12" and extra == "gui"
|
|
36
36
|
Requires-Dist: PySide6-Essentials>=6.7; python_version >= "3.12" and extra == "gui"
|
|
37
|
-
Requires-Dist: endstation[qt]>=0.2.
|
|
37
|
+
Requires-Dist: endstation[qt]>=0.2.6; extra == "gui"
|
|
38
38
|
Provides-Extra: metrology
|
|
39
39
|
Requires-Dist: matplotlib>=3.9; extra == "metrology"
|
|
40
40
|
Provides-Extra: refractiveindex
|
|
@@ -51,7 +51,7 @@ dependencies = [
|
|
|
51
51
|
# `dependencies = []` and has a test that fails if that stops being true,
|
|
52
52
|
# so this line adds no transitive weight -- the Qt and matplotlib parts sit
|
|
53
53
|
# behind its own extras, which our `gui` extra asks for by name.
|
|
54
|
-
"endstation>=0.2.
|
|
54
|
+
"endstation>=0.2.6",
|
|
55
55
|
# The rigorous solvers cap BLAS threads for the length of a solve
|
|
56
56
|
# (solvers/_execution.py): OpenBLAS's thread-per-core default made RCWA
|
|
57
57
|
# up to 135x slower on a busy machine, measured in benchmarks/
|
|
@@ -85,7 +85,7 @@ gui = [
|
|
|
85
85
|
"matplotlib>=3.8",
|
|
86
86
|
"PySide6-Essentials>=6.7,!=6.12.0; python_version < '3.12'",
|
|
87
87
|
"PySide6-Essentials>=6.7; python_version >= '3.12'",
|
|
88
|
-
"endstation[qt]>=0.2.
|
|
88
|
+
"endstation[qt]>=0.2.6",
|
|
89
89
|
]
|
|
90
90
|
# Groove metrology: reading AFM scans and averaging them into a boundary
|
|
91
91
|
# profile. An extra for the same reason the GUI is one -- `pip install
|
|
@@ -182,12 +182,16 @@ filterwarnings = [
|
|
|
182
182
|
"ignore:Enum value .Qt..ApplicationAttribute.AA_UseHighDpiPixmaps. is marked as deprecated:DeprecationWarning:matplotlib.backends.backend_qt",
|
|
183
183
|
# CI runs with PYTHONWARNDEFAULTENCODING=1, so any text open() here that
|
|
184
184
|
# leaves the encoding to the platform fails on every OS, not only on
|
|
185
|
-
# Windows with a non-ASCII file. These
|
|
185
|
+
# Windows with a non-ASCII file. These four are other projects' calls.
|
|
186
186
|
# numpy's savetxt touches its output with a bare open() whatever encoding
|
|
187
|
-
# it is given.
|
|
187
|
+
# it is given. threadpoolctl reads /proc/self/maps with a bare open(), so
|
|
188
|
+
# on Linux only, every rigorous solve (which caps BLAS through it) failed
|
|
189
|
+
# here: master's CI run 40624677314, both ubuntu jobs. Inert without the
|
|
190
|
+
# flag.
|
|
188
191
|
"ignore::EncodingWarning:matplotlib.font_manager",
|
|
189
192
|
"ignore::EncodingWarning:numpy.lib._npyio_impl",
|
|
190
193
|
"ignore::EncodingWarning:numpy.lib._datasource",
|
|
194
|
+
"ignore::EncodingWarning:threadpoolctl",
|
|
191
195
|
]
|
|
192
196
|
# pytest-qt would otherwise probe every binding it knows. Verified clean under
|
|
193
197
|
# `python -W error -c "import PySide6.QtWidgets"`, so `filterwarnings = error`
|
|
@@ -22,7 +22,7 @@ from .measured import MeasuredEfficiency, MeasurementProvenance
|
|
|
22
22
|
from .resolution import ResolvingPower, resolving_power
|
|
23
23
|
from .result import EfficiencyScan, OrderEfficiency, Provenance
|
|
24
24
|
|
|
25
|
-
__version__ = "0.2.
|
|
25
|
+
__version__ = "0.2.2"
|
|
26
26
|
|
|
27
27
|
__all__ = [
|
|
28
28
|
"Illumination",
|
|
@@ -201,7 +201,10 @@ def default_ladder(solver) -> tuple[int, ...]:
|
|
|
201
201
|
"""A ladder straddling the solver's own default for its accuracy knob.
|
|
202
202
|
|
|
203
203
|
The default is read from the signature and is not hardcoded, so a backend
|
|
204
|
-
that changes its default does not leave this sweeping the wrong range.
|
|
204
|
+
that changes its default does not leave this sweeping the wrong range. A
|
|
205
|
+
backend declaring an ``accuracy_ceiling`` has the ladder cut there: a sweep
|
|
206
|
+
that has not plateaued by the ceiling reports that, instead of failing on
|
|
207
|
+
a rung the solver refuses.
|
|
205
208
|
"""
|
|
206
209
|
knob = _knob_of(solver)
|
|
207
210
|
default = inspect.signature(solver.solve).parameters[knob].default
|
|
@@ -211,7 +214,11 @@ def default_ladder(solver) -> tuple[int, ...]:
|
|
|
211
214
|
f"{knob!r} ({default!r}), so a ladder cannot be inferred -- pass "
|
|
212
215
|
"`values` explicitly"
|
|
213
216
|
)
|
|
214
|
-
|
|
217
|
+
ladder = doubling_ladder(max(1, default // 2**_RUNGS_BELOW_DEFAULT), _DEFAULT_RUNGS)
|
|
218
|
+
ceiling = solver.capabilities.accuracy_ceiling
|
|
219
|
+
if ceiling is not None:
|
|
220
|
+
ladder = tuple(value for value in ladder if value <= ceiling)
|
|
221
|
+
return ladder
|
|
215
222
|
|
|
216
223
|
|
|
217
224
|
def check_convergence(
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""The desktop layer: two windows and the chooser that opens them.
|
|
2
|
+
|
|
3
|
+
Only :mod:`gratinglab.gui.qt` may import a toolkit. This module stays
|
|
4
|
+
toolkit-free so the console-script entry points, which live beside it, can
|
|
5
|
+
explain a missing PySide6 before anything tries to import it.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from endstation.optional import MissingExtra, require_extra
|
|
11
|
+
|
|
12
|
+
__all__ = ["STILL_WORKS", "exit_without_qt"]
|
|
13
|
+
|
|
14
|
+
#: What a missing toolkit leaves working. Without it, a user who wanted only
|
|
15
|
+
#: the solvers reads an absent GUI extra as a broken install.
|
|
16
|
+
STILL_WORKS = "Everything except the GUI works without it."
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def exit_without_qt() -> None:
|
|
20
|
+
"""Exit with an install instruction if PySide6 is not installed.
|
|
21
|
+
|
|
22
|
+
The check is :func:`endstation.optional.require_extra`, a ``find_spec``
|
|
23
|
+
call rather than an import. Its :class:`~endstation.optional.MissingExtra`
|
|
24
|
+
becomes ``SystemExit`` here, so a console script prints the message and
|
|
25
|
+
not a traceback naming a package the user never asked for.
|
|
26
|
+
"""
|
|
27
|
+
try:
|
|
28
|
+
require_extra("PySide6", "gui", still_works=STILL_WORKS)
|
|
29
|
+
except MissingExtra as exc:
|
|
30
|
+
raise SystemExit(str(exc)) from exc
|
|
@@ -15,22 +15,14 @@ from __future__ import annotations
|
|
|
15
15
|
|
|
16
16
|
import sys
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
gratinglab-gui needs PySide6, which this install does not have.
|
|
20
|
-
|
|
21
|
-
pip install -e ".[gui]" (from a checkout)
|
|
22
|
-
pip install gratinglab[gui] (once published)
|
|
23
|
-
|
|
24
|
-
Everything except the GUI works without it.
|
|
25
|
-
"""
|
|
18
|
+
from . import exit_without_qt
|
|
26
19
|
|
|
27
20
|
|
|
28
21
|
def _require_qt():
|
|
29
22
|
"""Import PySide6 with an explanation instead of a traceback."""
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
raise SystemExit(_QT_HELP) from exc
|
|
23
|
+
exit_without_qt()
|
|
24
|
+
from PySide6.QtWidgets import QApplication
|
|
25
|
+
|
|
34
26
|
return QApplication
|
|
35
27
|
|
|
36
28
|
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"""The C-method's own form: boundary condition, truncation, and their guards.
|
|
2
|
+
|
|
3
|
+
The third options module, written to the pattern of ``integral_options.py``:
|
|
4
|
+
its own file, its own frozen state and its own ``build_options`` raising
|
|
5
|
+
:class:`~gratinglab.gui.state.FormErrors`, and no toolkit import.
|
|
6
|
+
|
|
7
|
+
The form has two settings, because the solver has two. ``conductivity`` is
|
|
8
|
+
named and offered as the integral solver offers it, so one geometry reaches
|
|
9
|
+
either method with the same choice: ``"perfect"`` (relative efficiency, no
|
|
10
|
+
material) or ``"tabulated"`` (one interface into the coating, read per
|
|
11
|
+
wavelength, with absolute efficiency, absorption and, into a lossless
|
|
12
|
+
material, the transmitted orders). ``truncation`` is the accuracy knob: ``N``
|
|
13
|
+
harmonics either side of the centre of the propagating orders.
|
|
14
|
+
|
|
15
|
+
The guards mirror the solver's refusals so an error lands on the field that
|
|
16
|
+
caused it instead of arriving as a ValueError from the worker thread. The
|
|
17
|
+
truncation floor is not re-derived here: it is
|
|
18
|
+
:func:`gratinglab.solvers.cmethod.truncation_floor`, the function the solver
|
|
19
|
+
itself applies, so the form and the solver cannot disagree about it.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
from dataclasses import dataclass, replace
|
|
25
|
+
from typing import Any
|
|
26
|
+
|
|
27
|
+
import numpy as np
|
|
28
|
+
from numpy.typing import NDArray
|
|
29
|
+
|
|
30
|
+
from ..illumination import Illumination
|
|
31
|
+
from ..problem import Problem
|
|
32
|
+
from ..solvers.cmethod import _MAX_TRUNCATION, truncation_floor
|
|
33
|
+
from .integral_options import _tabulated_index
|
|
34
|
+
from .state import FieldError, FormErrors, _number
|
|
35
|
+
|
|
36
|
+
__all__ = [
|
|
37
|
+
"CONDUCTIVITY_MODES",
|
|
38
|
+
"CONDUCTIVITY_NOTES",
|
|
39
|
+
"CMethodOptionsState",
|
|
40
|
+
"build_options",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
#: Selectable boundary conditions, the solver's default first.
|
|
44
|
+
CONDUCTIVITY_MODES = ("perfect", "tabulated")
|
|
45
|
+
|
|
46
|
+
#: What each mode means, shown beneath the selector, for the reason
|
|
47
|
+
#: ``integral_options.CONDUCTIVITY_NOTES`` gives: a claim about the result
|
|
48
|
+
#: must not be hardcoded beside a control that can falsify it.
|
|
49
|
+
CONDUCTIVITY_NOTES = {
|
|
50
|
+
"perfect": (
|
|
51
|
+
"Perfect conductor in any mount: efficiencies are relative to a "
|
|
52
|
+
"perfect reflector and sum to 1. A coating named in the geometry "
|
|
53
|
+
"panel is not consulted (the provenance panel says so)."
|
|
54
|
+
),
|
|
55
|
+
"tabulated": (
|
|
56
|
+
"One interface into the coating named in the geometry panel, read "
|
|
57
|
+
"as a complex index at every wavelength. Efficiencies are absolute "
|
|
58
|
+
"and absorption is recorded; into a lossless material the "
|
|
59
|
+
"transmitted orders are recorded too, and R + T + A = 1 is a check."
|
|
60
|
+
),
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@dataclass(frozen=True, slots=True)
|
|
65
|
+
class CMethodOptionsState:
|
|
66
|
+
"""The C-method's own form fields, exactly as typed."""
|
|
67
|
+
|
|
68
|
+
truncation: str = "32"
|
|
69
|
+
conductivity: str = CONDUCTIVITY_MODES[0]
|
|
70
|
+
|
|
71
|
+
def with_field(self, name: str, value: Any) -> "CMethodOptionsState":
|
|
72
|
+
"""Return a copy with one field changed."""
|
|
73
|
+
return replace(self, **{name: value})
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def build_options(
|
|
77
|
+
problem: Problem,
|
|
78
|
+
illumination: Illumination,
|
|
79
|
+
wavelengths: NDArray[np.float64],
|
|
80
|
+
form: CMethodOptionsState,
|
|
81
|
+
) -> dict[str, Any]:
|
|
82
|
+
"""Parse the C-method options and check the truncation holds every order.
|
|
83
|
+
|
|
84
|
+
Raises
|
|
85
|
+
------
|
|
86
|
+
FormErrors
|
|
87
|
+
Same contract as :func:`gratinglab.gui.state.build`.
|
|
88
|
+
"""
|
|
89
|
+
errors: list[FieldError] = []
|
|
90
|
+
truncation = _number(
|
|
91
|
+
form.truncation, "truncation", errors, minimum=1, integer=True
|
|
92
|
+
)
|
|
93
|
+
if truncation is not None and truncation > _MAX_TRUNCATION:
|
|
94
|
+
errors.append(
|
|
95
|
+
FieldError(
|
|
96
|
+
"truncation",
|
|
97
|
+
f"at most {_MAX_TRUNCATION}: the eigenproblem is dense and its "
|
|
98
|
+
"cost grows as N^3, so a sweep that has not settled by then is "
|
|
99
|
+
"the answer",
|
|
100
|
+
)
|
|
101
|
+
)
|
|
102
|
+
if form.conductivity not in CONDUCTIVITY_MODES:
|
|
103
|
+
errors.append(
|
|
104
|
+
FieldError(
|
|
105
|
+
"conductivity",
|
|
106
|
+
f"must be one of {', '.join(CONDUCTIVITY_MODES)}",
|
|
107
|
+
)
|
|
108
|
+
)
|
|
109
|
+
if errors:
|
|
110
|
+
raise FormErrors(tuple(errors))
|
|
111
|
+
assert truncation is not None
|
|
112
|
+
|
|
113
|
+
indices = None
|
|
114
|
+
if form.conductivity == "tabulated":
|
|
115
|
+
_name, indices, error = _tabulated_index(problem, wavelengths)
|
|
116
|
+
if error is not None:
|
|
117
|
+
raise FormErrors((error,))
|
|
118
|
+
|
|
119
|
+
floor = truncation_floor(problem, illumination, wavelengths, indices)
|
|
120
|
+
if truncation < floor.needed:
|
|
121
|
+
raise FormErrors((FieldError("truncation", floor.message),))
|
|
122
|
+
|
|
123
|
+
return {"truncation": int(truncation), "conductivity": form.conductivity}
|
|
@@ -28,16 +28,9 @@ from __future__ import annotations
|
|
|
28
28
|
import sys
|
|
29
29
|
from dataclasses import dataclass
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
_QT_HELP = """\
|
|
34
|
-
gratinglab-app needs PySide6, which this install does not have.
|
|
35
|
-
|
|
36
|
-
pip install -e ".[gui]" (from a checkout)
|
|
37
|
-
pip install gratinglab[gui]
|
|
31
|
+
from . import exit_without_qt
|
|
38
32
|
|
|
39
|
-
|
|
40
|
-
"""
|
|
33
|
+
__all__ = ["Mode", "MODES", "mode", "main"]
|
|
41
34
|
|
|
42
35
|
|
|
43
36
|
@dataclass(frozen=True)
|
|
@@ -91,10 +84,9 @@ def mode(key: str) -> Mode:
|
|
|
91
84
|
|
|
92
85
|
def _require_qt():
|
|
93
86
|
"""Import PySide6 with an explanation instead of a traceback."""
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
raise SystemExit(_QT_HELP) from exc
|
|
87
|
+
exit_without_qt()
|
|
88
|
+
from PySide6.QtWidgets import QApplication
|
|
89
|
+
|
|
98
90
|
return QApplication
|
|
99
91
|
|
|
100
92
|
|
|
@@ -14,9 +14,8 @@ headlessly.
|
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
|
-
import os
|
|
18
|
-
|
|
19
17
|
# matplotlib's Qt shim picks a binding from sys.modules first and QT_API
|
|
20
|
-
# second. Without
|
|
21
|
-
# canvas would refuse to parent into a PySide6 window.
|
|
22
|
-
|
|
18
|
+
# second. Without QT_API, a stray PyQt5 in the environment would win and its
|
|
19
|
+
# canvas would refuse to parent into a PySide6 window. Importing endstation.qt
|
|
20
|
+
# sets it, with setdefault, before anything here imports matplotlib.
|
|
21
|
+
import endstation.qt # noqa: F401
|