gratinglab 0.2.2__tar.gz → 0.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gratinglab-0.2.2/src/gratinglab.egg-info → gratinglab-0.2.4}/PKG-INFO +9 -7
- {gratinglab-0.2.2 → gratinglab-0.2.4}/README.md +8 -6
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/__init__.py +1 -1
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/theme.py +22 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/gui/qt/boundary_view.py +11 -20
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/gui/qt/canvas.py +18 -13
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/gui/qt/efficiency_dialog.py +3 -2
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/gui/qt/import_view.py +11 -21
- gratinglab-0.2.4/src/gratinglab/metrology/gui/qt/layout.py +46 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/gui/qt/main_window.py +3 -16
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/gui/qt/swath_dialog.py +3 -2
- {gratinglab-0.2.2 → gratinglab-0.2.4/src/gratinglab.egg-info}/PKG-INFO +9 -7
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab.egg-info/SOURCES.txt +1 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/LICENSE +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/pyproject.toml +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/setup.cfg +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/checks.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/compare.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/convergence.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/geometry.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/__init__.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/app.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/cmethod_options.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/diagram.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/diagram3d.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/docs.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/efficiency_plot.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/icon.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/integral_options.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/launcher.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/mathtext.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/orders.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/provenance.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/qt/__init__.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/qt/cmethod_tab.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/qt/geometry_panel.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/qt/geometry_tab.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/qt/integral_tab.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/qt/launcher.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/qt/main_window.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/qt/profile_plot_panel.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/qt/rcwa_tab.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/qt/scalar_tab.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/qt/scene3d_panel.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/qt/setup_tab.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/qt/sizing.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/qt/theming.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/qt/theory_viewer.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/qt/worker.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/rcwa_options.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/richtext.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/scalar_options.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/gui/state.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/illumination.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/io/__init__.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/io/boundary.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/io/efficiency_table.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/io/ggp.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/materials/__init__.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/materials/data/SOURCES.md +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/materials/fresnel.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/materials/optical.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/materials/refractiveindex.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/measured.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/__init__.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/analyzer.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/boundary/__init__.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/boundary/average.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/boundary/pipeline.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/boundary/swaths.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/cli.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/config.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/core/__init__.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/core/analysis.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/core/image_flatten.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/core/orientation.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/core/processing.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/core/region_mask.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/core/scars.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/core/tip.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/data/__init__.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/data/aggregation.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/gui/__init__.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/gui/icon.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/gui/qt/__init__.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/gui/qt/app.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/gui/qt/wiki_view.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/gui/qt/worker.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/gui/state.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/io/__init__.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/io/file_io.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/io/ibw.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/io/metrics.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/io/spm.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/settings.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/stats/__init__.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/stats/analysis.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/stats/icc.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/visualization/__init__.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/visualization/diagnostics.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/visualization/profiles.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/visualization/statistics.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/wiki/__init__.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/wiki/facet-fitting.md +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/wiki/file-formats.md +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/wiki/flattening.md +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/wiki/groove-orientation.md +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/wiki/icc-correction.md +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/wiki/overview.md +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/wiki/reading-outputs.md +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/wiki/row-groups.md +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/wiki/scars-and-masking.md +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/wiki/swath-statistics.md +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/wiki/tip-correction.md +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/metrology/workflows.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/problem.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/profiles.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/resolution.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/result.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/solvers/__init__.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/solvers/_conditioning.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/solvers/_execution.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/solvers/base.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/solvers/cmethod/__init__.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/solvers/cmethod/_core.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/solvers/cmethod/_series.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/solvers/integral/__init__.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/solvers/integral/_boundary.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/solvers/integral/_core.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/solvers/integral/_finite.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/solvers/integral/_greens.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/solvers/integral/_kernels.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/solvers/integral/_nystrom.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/solvers/rcwa/__init__.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/solvers/rcwa/_core.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/solvers/rcwa/_stack.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab/solvers/scalar.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab.egg-info/dependency_links.txt +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab.egg-info/entry_points.txt +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab.egg-info/requires.txt +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/src/gratinglab.egg-info/top_level.txt +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_changelog.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_checks.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_cmethod.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_compare.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_conditioning.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_convergence.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_cross_method.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_efficiency_table.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_fresnel.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_geometry.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_ggp.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_gui_cmethod_options.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_gui_cmethod_tab.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_gui_diagram.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_gui_diagram3d.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_gui_docs.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_gui_integral_options.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_gui_launcher.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_gui_mathtext.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_gui_orders.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_gui_provenance.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_gui_qt.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_gui_rcwa_options.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_gui_richtext.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_gui_scalar_options.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_gui_state.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_gui_theme.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_illumination.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_integral_core.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_integral_corpus.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_integral_finite.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_integral_graded.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_integral_greens.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_integral_kernels.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_integral_operators.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_integral_solver.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_io_boundary.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_materials.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_measured.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_perturbation.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_profiles.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_rayleigh_anomaly.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_rcwa.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_rcwa_benchmarks.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_refractiveindex.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_resolution.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_result.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_scalar.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_solver_conformance.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_solver_execution.py +0 -0
- {gratinglab-0.2.2 → gratinglab-0.2.4}/tests/test_solver_progress.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.4
|
|
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
|
|
@@ -110,8 +110,10 @@ convergence harnesses and the materials layer work end to end. They are checked
|
|
|
110
110
|
against closed-form results, published benchmark tables, energy balance and
|
|
111
111
|
reciprocity, but remain experimental until they have been used on real problems.
|
|
112
112
|
Efficiencies are absolute when a coating is named, using an optical constant table
|
|
113
|
-
supplied by the user (see Install).
|
|
114
|
-
|
|
113
|
+
supplied by the user (see Install). Since 0.2.0 two more rigorous backends sit
|
|
114
|
+
beside them, both written in-house and both experimental: a rigorous coupled-wave
|
|
115
|
+
analysis (RCWA), which also models coated gratings through conformal layers, and
|
|
116
|
+
the C-method (Chandezon). Each has a tab in the efficiency window since 0.2.1.
|
|
115
117
|
|
|
116
118
|
## Scope
|
|
117
119
|
|
|
@@ -136,8 +138,8 @@ grazing incidence (γ of a degree or two), the soft X-ray spectroscopy regime th
|
|
|
136
138
|
project began with, where the integral method is the established approach and
|
|
137
139
|
general-purpose RCWA codes are least reliable. `Illumination.classical`,
|
|
138
140
|
`Illumination.conical(theta, phi)` and `Illumination.offplane(graze, azimuth)` all
|
|
139
|
-
build the same object, and
|
|
140
|
-
(
|
|
141
|
+
build the same object, and every solver accepts any of them. Which method serves which regime, and what is not yet covered
|
|
142
|
+
(multilayer stacks checked against an independent code, for one), is mapped in
|
|
141
143
|
[`docs/roadmap.md`](https://github.com/jamccoy/gratinglab/blob/master/docs/roadmap.md#regimes-and-the-methods-that-serve-them).
|
|
142
144
|
|
|
143
145
|
The method backends, in order of development:
|
|
@@ -146,8 +148,8 @@ The method backends, in order of development:
|
|
|
146
148
|
|---|---|
|
|
147
149
|
| Scalar (Kirchhoff, x-ray blaze form) | experimental; checked against closed-form results |
|
|
148
150
|
| Integral method (boundary integral, conical, undercut-capable) | experimental; perfect and finite conductivity (`conductivity="tabulated"`, Goray & Schmidt 2010), absolute efficiencies with the absorbed fraction recorded; a corner-graded mesh for profiles with corners (`corner_grading=4`), under either boundary condition; checked against published benchmark tables (Maystre & Popov; Goray & Schmidt), energy balance and reciprocity |
|
|
149
|
-
| RCWA (in-plane, conical, off-plane; Li factorization, S-matrix, layer stacks) |
|
|
150
|
-
| C-method (Chandezon) |
|
|
151
|
+
| RCWA (in-plane, conical, off-plane; Li factorization, S-matrix, layer stacks) | experimental, since 0.2.0; lamellar gratings exact and other profiles staircased, transmitted orders, and coatings through conformal layers (`Problem.layers`); checked against Fresnel, the Airy film formula, reciprocity, the integral solver, and published lamellar values (Granet; Lalanne & Hugonin; Gralak; Goray & Schmidt's conical tables). Not yet checked: staircase accuracy in metallic TM, and layers of a second material against an independent code |
|
|
152
|
+
| C-method (Chandezon) | experimental, since 0.2.0; perfect conductor in any mount, and one interface into an absorbing or lossless material, conical and coupled; checked against Goray & Schmidt's Table 3, Fresnel and the integral solver. Refuses vertical facets and undercuts; converges slowly on sawtooth corners, and loses precision at high truncation on profiles deeper than about half the period, both reported in provenance. No coatings |
|
|
151
153
|
|
|
152
154
|
The comparison harness also accepts an efficiency table already computed by an
|
|
153
155
|
external program as one of its methods, so that comparison plots can be made without
|
|
@@ -65,8 +65,10 @@ convergence harnesses and the materials layer work end to end. They are checked
|
|
|
65
65
|
against closed-form results, published benchmark tables, energy balance and
|
|
66
66
|
reciprocity, but remain experimental until they have been used on real problems.
|
|
67
67
|
Efficiencies are absolute when a coating is named, using an optical constant table
|
|
68
|
-
supplied by the user (see Install).
|
|
69
|
-
|
|
68
|
+
supplied by the user (see Install). Since 0.2.0 two more rigorous backends sit
|
|
69
|
+
beside them, both written in-house and both experimental: a rigorous coupled-wave
|
|
70
|
+
analysis (RCWA), which also models coated gratings through conformal layers, and
|
|
71
|
+
the C-method (Chandezon). Each has a tab in the efficiency window since 0.2.1.
|
|
70
72
|
|
|
71
73
|
## Scope
|
|
72
74
|
|
|
@@ -91,8 +93,8 @@ grazing incidence (γ of a degree or two), the soft X-ray spectroscopy regime th
|
|
|
91
93
|
project began with, where the integral method is the established approach and
|
|
92
94
|
general-purpose RCWA codes are least reliable. `Illumination.classical`,
|
|
93
95
|
`Illumination.conical(theta, phi)` and `Illumination.offplane(graze, azimuth)` all
|
|
94
|
-
build the same object, and
|
|
95
|
-
(
|
|
96
|
+
build the same object, and every solver accepts any of them. Which method serves which regime, and what is not yet covered
|
|
97
|
+
(multilayer stacks checked against an independent code, for one), is mapped in
|
|
96
98
|
[`docs/roadmap.md`](https://github.com/jamccoy/gratinglab/blob/master/docs/roadmap.md#regimes-and-the-methods-that-serve-them).
|
|
97
99
|
|
|
98
100
|
The method backends, in order of development:
|
|
@@ -101,8 +103,8 @@ The method backends, in order of development:
|
|
|
101
103
|
|---|---|
|
|
102
104
|
| Scalar (Kirchhoff, x-ray blaze form) | experimental; checked against closed-form results |
|
|
103
105
|
| Integral method (boundary integral, conical, undercut-capable) | experimental; perfect and finite conductivity (`conductivity="tabulated"`, Goray & Schmidt 2010), absolute efficiencies with the absorbed fraction recorded; a corner-graded mesh for profiles with corners (`corner_grading=4`), under either boundary condition; checked against published benchmark tables (Maystre & Popov; Goray & Schmidt), energy balance and reciprocity |
|
|
104
|
-
| RCWA (in-plane, conical, off-plane; Li factorization, S-matrix, layer stacks) |
|
|
105
|
-
| C-method (Chandezon) |
|
|
106
|
+
| RCWA (in-plane, conical, off-plane; Li factorization, S-matrix, layer stacks) | experimental, since 0.2.0; lamellar gratings exact and other profiles staircased, transmitted orders, and coatings through conformal layers (`Problem.layers`); checked against Fresnel, the Airy film formula, reciprocity, the integral solver, and published lamellar values (Granet; Lalanne & Hugonin; Gralak; Goray & Schmidt's conical tables). Not yet checked: staircase accuracy in metallic TM, and layers of a second material against an independent code |
|
|
107
|
+
| C-method (Chandezon) | experimental, since 0.2.0; perfect conductor in any mount, and one interface into an absorbing or lossless material, conical and coupled; checked against Goray & Schmidt's Table 3, Fresnel and the integral solver. Refuses vertical facets and undercuts; converges slowly on sawtooth corners, and loses precision at high truncation on profiles deeper than about half the period, both reported in provenance. No coatings |
|
|
106
108
|
|
|
107
109
|
The comparison harness also accepts an efficiency table already computed by an
|
|
108
110
|
external program as one of its methods, so that comparison plots can be made without
|
|
@@ -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.4"
|
|
26
26
|
|
|
27
27
|
__all__ = [
|
|
28
28
|
"Illumination",
|
|
@@ -37,6 +37,7 @@ __all__ = [
|
|
|
37
37
|
"order_colors",
|
|
38
38
|
"provenance_colors",
|
|
39
39
|
"rc_params",
|
|
40
|
+
"set_titles",
|
|
40
41
|
"style_axes",
|
|
41
42
|
"style_figure",
|
|
42
43
|
]
|
|
@@ -308,6 +309,27 @@ def style_axes(axes, theme: Theme) -> None:
|
|
|
308
309
|
axis.line.set_color(theme.ink)
|
|
309
310
|
|
|
310
311
|
|
|
312
|
+
#: Plot titles: what the panel is, at this size and weight, left-aligned.
|
|
313
|
+
TITLE_SIZE = 11
|
|
314
|
+
TITLE_WEIGHT = "semibold"
|
|
315
|
+
#: The figures a panel reports beside its title, smaller and in ``muted``.
|
|
316
|
+
DETAIL_SIZE = 9
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
def set_titles(axes, title: str, detail: str | None = None, theme: Theme | None = None) -> None:
|
|
320
|
+
"""Title a panel: its name on the left, the numbers it reports on the right.
|
|
321
|
+
|
|
322
|
+
One style for every plot, so a title says what the panel is and never has
|
|
323
|
+
to carry a measurement, a setting or an explanation on a second line. The
|
|
324
|
+
detail is where those go, quieter than the title. Pass ``theme`` from a
|
|
325
|
+
caller that has one; otherwise the plain ``LIGHT`` colours are used.
|
|
326
|
+
"""
|
|
327
|
+
theme = theme or LIGHT
|
|
328
|
+
axes.set_title(title, loc="left", fontsize=TITLE_SIZE, fontweight=TITLE_WEIGHT,
|
|
329
|
+
color=theme.ink)
|
|
330
|
+
axes.set_title(detail or "", loc="right", fontsize=DETAIL_SIZE, color=theme.muted)
|
|
331
|
+
|
|
332
|
+
|
|
311
333
|
def style_figure(figure, theme: Theme) -> None:
|
|
312
334
|
"""Restyle an existing figure and every axes on it."""
|
|
313
335
|
figure.set_facecolor(theme.figure)
|
|
@@ -21,14 +21,16 @@ import os
|
|
|
21
21
|
from . import * # noqa: F401,F403 - sets QT_API before matplotlib's shim loads
|
|
22
22
|
|
|
23
23
|
from PySide6.QtWidgets import (
|
|
24
|
-
QCheckBox, QFileDialog,
|
|
25
|
-
QMessageBox, QPushButton,
|
|
24
|
+
QCheckBox, QFileDialog, QGroupBox, QHBoxLayout, QLabel,
|
|
25
|
+
QMessageBox, QPushButton, QSpinBox, QVBoxLayout, QWidget,
|
|
26
26
|
)
|
|
27
27
|
from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg as FigureCanvas
|
|
28
28
|
from matplotlib.figure import Figure
|
|
29
29
|
|
|
30
30
|
from gratinglab.gui.qt import theming
|
|
31
|
-
from gratinglab.gui.theme import style_figure
|
|
31
|
+
from gratinglab.gui.theme import set_titles, style_figure
|
|
32
|
+
|
|
33
|
+
from .layout import controls_beside
|
|
32
34
|
|
|
33
35
|
from ...boundary import build_boundary_profile
|
|
34
36
|
from ...core.tip import format_angles
|
|
@@ -65,7 +67,6 @@ class BoundaryView(QWidget):
|
|
|
65
67
|
root.setSpacing(8)
|
|
66
68
|
|
|
67
69
|
left = QWidget()
|
|
68
|
-
left.setFixedWidth(272)
|
|
69
70
|
column = QVBoxLayout(left)
|
|
70
71
|
column.setContentsMargins(0, 0, 0, 0)
|
|
71
72
|
column.setSpacing(8)
|
|
@@ -73,23 +74,12 @@ class BoundaryView(QWidget):
|
|
|
73
74
|
column.addWidget(self._build_metrics_group())
|
|
74
75
|
column.addStretch()
|
|
75
76
|
|
|
76
|
-
scroll = QScrollArea()
|
|
77
|
-
scroll.setWidget(left)
|
|
78
|
-
scroll.setWidgetResizable(True)
|
|
79
|
-
scroll.setFixedWidth(292)
|
|
80
|
-
scroll.setFrameShape(QFrame.NoFrame)
|
|
81
|
-
|
|
82
77
|
self.figure = Figure(figsize=(8, 6), tight_layout=True)
|
|
83
78
|
self.canvas = FigureCanvas(self.figure)
|
|
84
79
|
self._show_placeholder()
|
|
85
80
|
theming.subscribe(self._on_theme)
|
|
86
81
|
|
|
87
|
-
root.addWidget(
|
|
88
|
-
divider = QFrame()
|
|
89
|
-
divider.setFrameShape(QFrame.VLine)
|
|
90
|
-
divider.setFrameShadow(QFrame.Sunken)
|
|
91
|
-
root.addWidget(divider)
|
|
92
|
-
root.addWidget(self.canvas, stretch=1)
|
|
82
|
+
root.addWidget(controls_beside(left, self.canvas), stretch=1)
|
|
93
83
|
|
|
94
84
|
def _build_export_group(self):
|
|
95
85
|
group = QGroupBox("Boundary profile")
|
|
@@ -327,7 +317,8 @@ class BoundaryView(QWidget):
|
|
|
327
317
|
alpha=0.8 if dark else 0.6)
|
|
328
318
|
avg_ax.set_xlabel("Position (nm)", fontsize=10)
|
|
329
319
|
avg_ax.set_ylabel("Height (nm)", fontsize=10)
|
|
330
|
-
avg_ax
|
|
320
|
+
set_titles(avg_ax, "Averaged groove", f"{p.n_used} grooves",
|
|
321
|
+
theming.current())
|
|
331
322
|
avg_ax.legend(fontsize=8)
|
|
332
323
|
avg_ax.grid(True, alpha=0.3)
|
|
333
324
|
|
|
@@ -336,9 +327,9 @@ class BoundaryView(QWidget):
|
|
|
336
327
|
norm_ax.axhline(0, color=theming.current().ink, linestyle='--', linewidth=0.5)
|
|
337
328
|
norm_ax.set_xlabel("Normalised position (0 to 1 = one period)", fontsize=10)
|
|
338
329
|
norm_ax.set_ylabel("Height (fraction of period)", fontsize=10)
|
|
339
|
-
norm_ax
|
|
340
|
-
|
|
341
|
-
|
|
330
|
+
set_titles(norm_ax, "Exported profile",
|
|
331
|
+
f"{len(p.x_norm)} points, depth {p.metrics['groove_depth']:.4f} "
|
|
332
|
+
"of period", theming.current())
|
|
342
333
|
norm_ax.grid(True, alpha=0.3)
|
|
343
334
|
|
|
344
335
|
self.canvas.draw()
|
|
@@ -17,7 +17,7 @@ from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg as FigureCanvas
|
|
|
17
17
|
from matplotlib.figure import Figure
|
|
18
18
|
|
|
19
19
|
from gratinglab.gui.qt import theming
|
|
20
|
-
from gratinglab.gui.theme import style_figure
|
|
20
|
+
from gratinglab.gui.theme import set_titles, style_figure
|
|
21
21
|
|
|
22
22
|
__all__ = ["PlotCanvas"]
|
|
23
23
|
|
|
@@ -71,7 +71,8 @@ class PlotCanvas(FigureCanvas):
|
|
|
71
71
|
ax.plot(disp_um, profile_nm, color='steelblue', linewidth=1.0)
|
|
72
72
|
ax.set_xlabel("Position (µm)", fontsize=11)
|
|
73
73
|
ax.set_ylabel("Height (nm)", fontsize=11)
|
|
74
|
-
ax
|
|
74
|
+
set_titles(ax, "Raw profile", f"scan width {scan_size_um:.3f} µm",
|
|
75
|
+
theming.current())
|
|
75
76
|
ax.grid(True, alpha=0.3)
|
|
76
77
|
self.draw()
|
|
77
78
|
|
|
@@ -84,7 +85,8 @@ class PlotCanvas(FigureCanvas):
|
|
|
84
85
|
self.fig.colorbar(im, ax=ax, label='Height (nm)')
|
|
85
86
|
ax.set_xlabel("X (µm)", fontsize=11)
|
|
86
87
|
ax.set_ylabel("Scan line", fontsize=11)
|
|
87
|
-
ax
|
|
88
|
+
set_titles(ax, "Topography", f"{data.shape[0]} scan lines",
|
|
89
|
+
theming.current())
|
|
88
90
|
self.draw()
|
|
89
91
|
|
|
90
92
|
@_remembered
|
|
@@ -102,9 +104,9 @@ class PlotCanvas(FigureCanvas):
|
|
|
102
104
|
linewidth=1.8, label=f'Mean (n={n_groups})', zorder=5)
|
|
103
105
|
ax.set_xlabel("Position (µm)", fontsize=11)
|
|
104
106
|
ax.set_ylabel("Height (nm)", fontsize=11)
|
|
105
|
-
ax
|
|
106
|
-
|
|
107
|
-
|
|
107
|
+
set_titles(ax, "Row-group profiles",
|
|
108
|
+
f"{n_groups} groups of {group_info['rows_per_group']} rows, "
|
|
109
|
+
f"scan width {scan_size_um:.3f} µm", theming.current())
|
|
108
110
|
ax.legend(fontsize=10)
|
|
109
111
|
ax.grid(True, alpha=0.3)
|
|
110
112
|
|
|
@@ -140,7 +142,8 @@ class PlotCanvas(FigureCanvas):
|
|
|
140
142
|
|
|
141
143
|
ax.set_xlabel("Position (µm)", fontsize=11)
|
|
142
144
|
ax.set_ylabel("Height (nm)", fontsize=11)
|
|
143
|
-
ax
|
|
145
|
+
set_titles(ax, "Groove detection", f"{len(centers)} grooves",
|
|
146
|
+
theming.current())
|
|
144
147
|
ax.legend(fontsize=9)
|
|
145
148
|
ax.grid(True, alpha=0.3)
|
|
146
149
|
self.draw()
|
|
@@ -160,8 +163,8 @@ class PlotCanvas(FigureCanvas):
|
|
|
160
163
|
label=f'Mean {mean:.2f}°')
|
|
161
164
|
ax1.set_xlabel("Blaze angle (°)", fontsize=10)
|
|
162
165
|
ax1.set_ylabel("Count", fontsize=10)
|
|
163
|
-
ax1
|
|
164
|
-
|
|
166
|
+
set_titles(ax1, "Distribution",
|
|
167
|
+
f"N = {len(angles)}, σ = {result['std_angle']:.2f}°", theming.current())
|
|
165
168
|
ax1.legend(fontsize=9)
|
|
166
169
|
ax1.grid(True, alpha=0.3)
|
|
167
170
|
|
|
@@ -169,16 +172,18 @@ class PlotCanvas(FigureCanvas):
|
|
|
169
172
|
ax2.hist(r2, bins=20, edgecolor=theming.current().ink, alpha=0.75, color='seagreen')
|
|
170
173
|
ax2.set_xlabel("Fit R²", fontsize=10)
|
|
171
174
|
ax2.set_ylabel("Count", fontsize=10)
|
|
172
|
-
ax2
|
|
175
|
+
set_titles(ax2, "Fit quality", f"worst R² {np.nanmin(r2):.4f}",
|
|
176
|
+
theming.current())
|
|
173
177
|
ax2.grid(True, alpha=0.3)
|
|
174
178
|
|
|
175
179
|
widths = np.array([q.get('blaze_width_nm', np.nan) for q in quality])
|
|
176
180
|
ax3.plot(widths, angles, 'o', markersize=4, alpha=0.45, color='darkorange')
|
|
177
181
|
ax3.set_xlabel("Blaze facet width (nm)", fontsize=10)
|
|
178
182
|
ax3.set_ylabel("Blaze angle (°)", fontsize=10)
|
|
179
|
-
ax3
|
|
180
|
-
|
|
183
|
+
set_titles(ax3, "Angle against facet width", "narrow facets fit poorly",
|
|
184
|
+
theming.current())
|
|
181
185
|
ax3.grid(True, alpha=0.3)
|
|
182
186
|
|
|
183
|
-
self.fig.suptitle(f"Blaze angle {mean:.2f}° ± {sem:.3f}° (SEM)",
|
|
187
|
+
self.fig.suptitle(f"Blaze angle {mean:.2f}° ± {sem:.3f}° (SEM)",
|
|
188
|
+
x=0.01, ha="left", fontsize=12, fontweight="semibold")
|
|
184
189
|
self.draw()
|
|
@@ -36,7 +36,7 @@ from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg as FigureCanvas
|
|
|
36
36
|
from matplotlib.figure import Figure
|
|
37
37
|
|
|
38
38
|
from gratinglab.gui.qt import theming
|
|
39
|
-
from gratinglab.gui.theme import style_figure
|
|
39
|
+
from gratinglab.gui.theme import set_titles, style_figure
|
|
40
40
|
|
|
41
41
|
from gratinglab import materials
|
|
42
42
|
from gratinglab.illumination import Illumination
|
|
@@ -286,7 +286,8 @@ class EfficiencyDialog(QDialog):
|
|
|
286
286
|
|
|
287
287
|
axes.set_xlabel("Wavelength (nm)")
|
|
288
288
|
axes.set_ylabel("Absolute efficiency")
|
|
289
|
-
axes
|
|
289
|
+
set_titles(axes, "Measured groove",
|
|
290
|
+
f"period {self._profile.period_nm:.2f} nm", theming.current())
|
|
290
291
|
axes.grid(True, alpha=0.3)
|
|
291
292
|
axes.set_ylim(bottom=0)
|
|
292
293
|
if carried:
|
|
@@ -22,14 +22,16 @@ from . import * # noqa: F401,F403 - sets QT_API before matplotlib's shim loads
|
|
|
22
22
|
import numpy as np
|
|
23
23
|
from PySide6.QtCore import Signal
|
|
24
24
|
from PySide6.QtWidgets import (
|
|
25
|
-
QApplication, QComboBox, QDoubleSpinBox, QFileDialog,
|
|
26
|
-
QHBoxLayout, QLabel, QPushButton,
|
|
25
|
+
QApplication, QComboBox, QDoubleSpinBox, QFileDialog, QGroupBox,
|
|
26
|
+
QHBoxLayout, QLabel, QPushButton, QSpinBox, QVBoxLayout, QWidget,
|
|
27
27
|
)
|
|
28
28
|
from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg as FigureCanvas
|
|
29
29
|
from matplotlib.figure import Figure
|
|
30
30
|
|
|
31
31
|
from gratinglab.gui.qt import theming
|
|
32
|
-
from gratinglab.gui.theme import style_figure
|
|
32
|
+
from gratinglab.gui.theme import set_titles, style_figure
|
|
33
|
+
|
|
34
|
+
from .layout import controls_beside
|
|
33
35
|
from matplotlib.patches import Rectangle
|
|
34
36
|
from matplotlib.widgets import RectangleSelector
|
|
35
37
|
|
|
@@ -96,7 +98,6 @@ class ImportView(QWidget):
|
|
|
96
98
|
root.setSpacing(8)
|
|
97
99
|
|
|
98
100
|
left = QWidget()
|
|
99
|
-
left.setFixedWidth(272)
|
|
100
101
|
column = QVBoxLayout(left)
|
|
101
102
|
column.setContentsMargins(0, 0, 0, 0)
|
|
102
103
|
column.setSpacing(8)
|
|
@@ -106,23 +107,12 @@ class ImportView(QWidget):
|
|
|
106
107
|
column.addWidget(self._build_profile_group())
|
|
107
108
|
column.addStretch()
|
|
108
109
|
|
|
109
|
-
scroll = QScrollArea()
|
|
110
|
-
scroll.setWidget(left)
|
|
111
|
-
scroll.setWidgetResizable(True)
|
|
112
|
-
scroll.setFixedWidth(292)
|
|
113
|
-
scroll.setFrameShape(QFrame.NoFrame)
|
|
114
|
-
|
|
115
110
|
self.figure = Figure(figsize=(8, 6), tight_layout=True)
|
|
116
111
|
self.canvas = FigureCanvas(self.figure)
|
|
117
112
|
self._show_placeholder()
|
|
118
113
|
theming.subscribe(self._on_theme)
|
|
119
114
|
|
|
120
|
-
root.addWidget(
|
|
121
|
-
divider = QFrame()
|
|
122
|
-
divider.setFrameShape(QFrame.VLine)
|
|
123
|
-
divider.setFrameShadow(QFrame.Sunken)
|
|
124
|
-
root.addWidget(divider)
|
|
125
|
-
root.addWidget(self.canvas, stretch=1)
|
|
115
|
+
root.addWidget(controls_beside(left, self.canvas), stretch=1)
|
|
126
116
|
|
|
127
117
|
def _build_file_group(self):
|
|
128
118
|
group = QGroupBox("File")
|
|
@@ -574,8 +564,8 @@ class ImportView(QWidget):
|
|
|
574
564
|
minspanx=0, minspany=0, spancoords='data', interactive=False,
|
|
575
565
|
props=dict(facecolor='crimson', edgecolor='crimson', alpha=0.25,
|
|
576
566
|
fill=True))
|
|
577
|
-
image_ax
|
|
578
|
-
|
|
567
|
+
set_titles(image_ax, "Image flattening",
|
|
568
|
+
self.image_method_combo.currentText(), theming.current())
|
|
579
569
|
|
|
580
570
|
try:
|
|
581
571
|
x_um, profile_nm = raw_data(self._flat, self._scan_size)
|
|
@@ -606,9 +596,9 @@ class ImportView(QWidget):
|
|
|
606
596
|
linewidth=1.0, label='After flattening')
|
|
607
597
|
profile_ax.set_xlabel("Position (µm)", fontsize=10)
|
|
608
598
|
profile_ax.set_ylabel("Height (nm)", fontsize=10)
|
|
609
|
-
profile_ax
|
|
610
|
-
|
|
611
|
-
|
|
599
|
+
set_titles(profile_ax, "Profile flattening",
|
|
600
|
+
f"{self.profile_method_combo.currentText()}, removes "
|
|
601
|
+
f"{np.ptp(background):.1f} nm of background", theming.current())
|
|
612
602
|
profile_ax.legend(fontsize=8)
|
|
613
603
|
profile_ax.grid(True, alpha=0.3)
|
|
614
604
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""
|
|
2
|
+
The controls-and-plot layout every AFM tab shares.
|
|
3
|
+
|
|
4
|
+
Each tab was a fixed 272 px column of controls in a 292 px scroll area beside
|
|
5
|
+
its plot, so long labels were crammed and nothing could be widened. A splitter
|
|
6
|
+
replaces that: the column starts wide enough for its contents, cannot be
|
|
7
|
+
dragged narrower than its widest control needs, and gives the plot every pixel
|
|
8
|
+
the window gains.
|
|
9
|
+
"""
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from . import * # noqa: F401,F403 - sets QT_API before matplotlib's shim loads
|
|
13
|
+
|
|
14
|
+
from PySide6.QtCore import Qt
|
|
15
|
+
from PySide6.QtWidgets import QFrame, QScrollArea, QSplitter, QWidget
|
|
16
|
+
|
|
17
|
+
__all__ = ["controls_beside", "MIN_CONTROLS_WIDTH", "START_CONTROLS_WIDTH"]
|
|
18
|
+
|
|
19
|
+
#: Narrower than this and the group boxes' labels start to wrap mid-word.
|
|
20
|
+
MIN_CONTROLS_WIDTH = 260
|
|
21
|
+
#: Where the column starts, unless its contents ask for more.
|
|
22
|
+
START_CONTROLS_WIDTH = 320
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def controls_beside(controls: QWidget, plot: QWidget) -> QSplitter:
|
|
26
|
+
"""A splitter holding the scrolling ``controls`` column and the ``plot``."""
|
|
27
|
+
scroll = QScrollArea()
|
|
28
|
+
scroll.setWidget(controls)
|
|
29
|
+
scroll.setWidgetResizable(True)
|
|
30
|
+
scroll.setFrameShape(QFrame.NoFrame)
|
|
31
|
+
# Width is the splitter's to decide; only the height should ever scroll.
|
|
32
|
+
scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
|
33
|
+
|
|
34
|
+
gutter = scroll.verticalScrollBar().sizeHint().width()
|
|
35
|
+
floor = max(MIN_CONTROLS_WIDTH, controls.minimumSizeHint().width() + gutter)
|
|
36
|
+
scroll.setMinimumWidth(floor)
|
|
37
|
+
|
|
38
|
+
splitter = QSplitter(Qt.Horizontal)
|
|
39
|
+
splitter.setChildrenCollapsible(False)
|
|
40
|
+
splitter.addWidget(scroll)
|
|
41
|
+
splitter.addWidget(plot)
|
|
42
|
+
splitter.setStretchFactor(0, 0)
|
|
43
|
+
splitter.setStretchFactor(1, 1)
|
|
44
|
+
start = max(START_CONTROLS_WIDTH, floor)
|
|
45
|
+
splitter.setSizes([start, max(1, 4 * start)])
|
|
46
|
+
return splitter
|
|
@@ -18,9 +18,7 @@ from endstation.qt.tokens import StaleGuard
|
|
|
18
18
|
from PySide6.QtCore import Qt, QThread, Signal
|
|
19
19
|
from PySide6.QtGui import QFont
|
|
20
20
|
from PySide6.QtWidgets import (
|
|
21
|
-
QCheckBox, QComboBox, QDoubleSpinBox,
|
|
22
|
-
QGroupBox, QHBoxLayout, QLabel, QMainWindow, QPushButton, QScrollArea,
|
|
23
|
-
QSpinBox, QStatusBar, QTabWidget, QVBoxLayout, QWidget,
|
|
21
|
+
QCheckBox, QComboBox, QDoubleSpinBox, QGroupBox, QHBoxLayout, QLabel, QMainWindow, QPushButton, QSpinBox, QStatusBar, QTabWidget, QVBoxLayout, QWidget,
|
|
24
22
|
)
|
|
25
23
|
from matplotlib.backends.backend_qtagg import NavigationToolbar2QT as NavigationToolbar
|
|
26
24
|
|
|
@@ -28,6 +26,7 @@ from ...core.processing import raw_data, raw_data_multi_group
|
|
|
28
26
|
from ...core.tip import TIP_PRESETS, VALID_TIP_CORRECTIONS, format_angles
|
|
29
27
|
from ...settings import (AnalysisSettings, MAX_FACET_TRIM, VALID_BLAZE_SIDES)
|
|
30
28
|
from ..state import FormState, build, summarize_result
|
|
29
|
+
from .layout import controls_beside
|
|
31
30
|
from .canvas import PlotCanvas
|
|
32
31
|
from .boundary_view import BoundaryView
|
|
33
32
|
from .import_view import ImportView
|
|
@@ -107,7 +106,6 @@ class MainWindow(QMainWindow):
|
|
|
107
106
|
root.setSpacing(8)
|
|
108
107
|
|
|
109
108
|
left = QWidget()
|
|
110
|
-
left.setFixedWidth(272)
|
|
111
109
|
left_layout = QVBoxLayout(left)
|
|
112
110
|
left_layout.setContentsMargins(0, 0, 0, 0)
|
|
113
111
|
left_layout.setSpacing(8)
|
|
@@ -115,12 +113,6 @@ class MainWindow(QMainWindow):
|
|
|
115
113
|
left_layout.addWidget(self._build_view_group())
|
|
116
114
|
left_layout.addStretch()
|
|
117
115
|
|
|
118
|
-
scroll = QScrollArea()
|
|
119
|
-
scroll.setWidget(left)
|
|
120
|
-
scroll.setWidgetResizable(True)
|
|
121
|
-
scroll.setFixedWidth(292)
|
|
122
|
-
scroll.setFrameShape(QFrame.NoFrame)
|
|
123
|
-
|
|
124
116
|
right = QWidget()
|
|
125
117
|
right_layout = QVBoxLayout(right)
|
|
126
118
|
right_layout.setContentsMargins(0, 0, 0, 0)
|
|
@@ -129,12 +121,7 @@ class MainWindow(QMainWindow):
|
|
|
129
121
|
right_layout.addWidget(self.canvas, stretch=1)
|
|
130
122
|
right_layout.addWidget(self._build_results_panel())
|
|
131
123
|
|
|
132
|
-
root.addWidget(
|
|
133
|
-
divider = QFrame()
|
|
134
|
-
divider.setFrameShape(QFrame.VLine)
|
|
135
|
-
divider.setFrameShadow(QFrame.Sunken)
|
|
136
|
-
root.addWidget(divider)
|
|
137
|
-
root.addWidget(right, stretch=1)
|
|
124
|
+
root.addWidget(controls_beside(left, right), stretch=1)
|
|
138
125
|
|
|
139
126
|
self.tabs.addTab(central, "Analysis")
|
|
140
127
|
|
|
@@ -23,7 +23,7 @@ from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg as FigureCanvas
|
|
|
23
23
|
from matplotlib.figure import Figure
|
|
24
24
|
|
|
25
25
|
from gratinglab.gui.qt import theming
|
|
26
|
-
from gratinglab.gui.theme import style_figure
|
|
26
|
+
from gratinglab.gui.theme import set_titles, style_figure
|
|
27
27
|
|
|
28
28
|
from ...boundary import swath_statistics
|
|
29
29
|
from ...config import RESULTS_DIR
|
|
@@ -144,7 +144,8 @@ class SwathDialog(QDialog):
|
|
|
144
144
|
shapes.plot(s.t, s.whole.y_norm, color=theming.current().ink, lw=1.4, ls="--", label="whole scan")
|
|
145
145
|
shapes.set_xlabel("position (fraction of period)")
|
|
146
146
|
shapes.set_ylabel("height (fraction of period)")
|
|
147
|
-
shapes
|
|
147
|
+
set_titles(shapes, "Groove shape by swath",
|
|
148
|
+
f"{s.n_swaths} swaths, coloured top to bottom", theming.current())
|
|
148
149
|
shapes.legend(loc="best", fontsize=8)
|
|
149
150
|
|
|
150
151
|
centre = [(a + b - 1) / 2 for a, b in s.row_ranges]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gratinglab
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
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
|
|
@@ -110,8 +110,10 @@ convergence harnesses and the materials layer work end to end. They are checked
|
|
|
110
110
|
against closed-form results, published benchmark tables, energy balance and
|
|
111
111
|
reciprocity, but remain experimental until they have been used on real problems.
|
|
112
112
|
Efficiencies are absolute when a coating is named, using an optical constant table
|
|
113
|
-
supplied by the user (see Install).
|
|
114
|
-
|
|
113
|
+
supplied by the user (see Install). Since 0.2.0 two more rigorous backends sit
|
|
114
|
+
beside them, both written in-house and both experimental: a rigorous coupled-wave
|
|
115
|
+
analysis (RCWA), which also models coated gratings through conformal layers, and
|
|
116
|
+
the C-method (Chandezon). Each has a tab in the efficiency window since 0.2.1.
|
|
115
117
|
|
|
116
118
|
## Scope
|
|
117
119
|
|
|
@@ -136,8 +138,8 @@ grazing incidence (γ of a degree or two), the soft X-ray spectroscopy regime th
|
|
|
136
138
|
project began with, where the integral method is the established approach and
|
|
137
139
|
general-purpose RCWA codes are least reliable. `Illumination.classical`,
|
|
138
140
|
`Illumination.conical(theta, phi)` and `Illumination.offplane(graze, azimuth)` all
|
|
139
|
-
build the same object, and
|
|
140
|
-
(
|
|
141
|
+
build the same object, and every solver accepts any of them. Which method serves which regime, and what is not yet covered
|
|
142
|
+
(multilayer stacks checked against an independent code, for one), is mapped in
|
|
141
143
|
[`docs/roadmap.md`](https://github.com/jamccoy/gratinglab/blob/master/docs/roadmap.md#regimes-and-the-methods-that-serve-them).
|
|
142
144
|
|
|
143
145
|
The method backends, in order of development:
|
|
@@ -146,8 +148,8 @@ The method backends, in order of development:
|
|
|
146
148
|
|---|---|
|
|
147
149
|
| Scalar (Kirchhoff, x-ray blaze form) | experimental; checked against closed-form results |
|
|
148
150
|
| Integral method (boundary integral, conical, undercut-capable) | experimental; perfect and finite conductivity (`conductivity="tabulated"`, Goray & Schmidt 2010), absolute efficiencies with the absorbed fraction recorded; a corner-graded mesh for profiles with corners (`corner_grading=4`), under either boundary condition; checked against published benchmark tables (Maystre & Popov; Goray & Schmidt), energy balance and reciprocity |
|
|
149
|
-
| RCWA (in-plane, conical, off-plane; Li factorization, S-matrix, layer stacks) |
|
|
150
|
-
| C-method (Chandezon) |
|
|
151
|
+
| RCWA (in-plane, conical, off-plane; Li factorization, S-matrix, layer stacks) | experimental, since 0.2.0; lamellar gratings exact and other profiles staircased, transmitted orders, and coatings through conformal layers (`Problem.layers`); checked against Fresnel, the Airy film formula, reciprocity, the integral solver, and published lamellar values (Granet; Lalanne & Hugonin; Gralak; Goray & Schmidt's conical tables). Not yet checked: staircase accuracy in metallic TM, and layers of a second material against an independent code |
|
|
152
|
+
| C-method (Chandezon) | experimental, since 0.2.0; perfect conductor in any mount, and one interface into an absorbing or lossless material, conical and coupled; checked against Goray & Schmidt's Table 3, Fresnel and the integral solver. Refuses vertical facets and undercuts; converges slowly on sawtooth corners, and loses precision at high truncation on profiles deeper than about half the period, both reported in provenance. No coatings |
|
|
151
153
|
|
|
152
154
|
The comparison harness also accepts an efficiency table already computed by an
|
|
153
155
|
external program as one of its methods, so that comparison plots can be made without
|
|
@@ -90,6 +90,7 @@ src/gratinglab/metrology/gui/qt/boundary_view.py
|
|
|
90
90
|
src/gratinglab/metrology/gui/qt/canvas.py
|
|
91
91
|
src/gratinglab/metrology/gui/qt/efficiency_dialog.py
|
|
92
92
|
src/gratinglab/metrology/gui/qt/import_view.py
|
|
93
|
+
src/gratinglab/metrology/gui/qt/layout.py
|
|
93
94
|
src/gratinglab/metrology/gui/qt/main_window.py
|
|
94
95
|
src/gratinglab/metrology/gui/qt/swath_dialog.py
|
|
95
96
|
src/gratinglab/metrology/gui/qt/wiki_view.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|