gratinglab 0.2.7__tar.gz → 0.2.8__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.7/src/gratinglab.egg-info → gratinglab-0.2.8}/PKG-INFO +12 -4
- {gratinglab-0.2.7 → gratinglab-0.2.8}/README.md +11 -3
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/__init__.py +1 -1
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/integral_options.py +90 -41
- gratinglab-0.2.8/src/gratinglab/metrology/io/sem.py +603 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/problem.py +8 -2
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/profiles.py +337 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/scalar.py +12 -8
- {gratinglab-0.2.7 → gratinglab-0.2.8/src/gratinglab.egg-info}/PKG-INFO +12 -4
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab.egg-info/SOURCES.txt +1 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_integral_options.py +42 -18
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_measured.py +28 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_profiles.py +145 -1
- {gratinglab-0.2.7 → gratinglab-0.2.8}/LICENSE +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/pyproject.toml +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/setup.cfg +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/checks.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/compare.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/convergence.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/geometry.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/__init__.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/app.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/cmethod_options.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/comparison.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/diagram.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/diagram3d.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/docs.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/efficiency_plot.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/icon.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/launcher.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/mathtext.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/orders.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/provenance.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/__init__.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/cmethod_tab.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/compare_tab.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/geometry_panel.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/geometry_tab.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/integral_tab.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/launcher.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/main_window.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/profile_plot_panel.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/rcwa_tab.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/scalar_tab.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/scene3d_panel.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/setup_tab.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/sizing.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/theming.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/theory_viewer.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/worker.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/rcwa_options.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/richtext.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/scalar_options.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/state.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/theme.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/illumination.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/io/__init__.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/io/boundary.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/io/efficiency_table.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/io/ggp.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/materials/__init__.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/materials/data/SOURCES.md +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/materials/fresnel.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/materials/optical.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/materials/refractiveindex.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/measured.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/__init__.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/analyzer.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/boundary/__init__.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/boundary/average.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/boundary/pipeline.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/boundary/swaths.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/cli.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/config.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/core/__init__.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/core/analysis.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/core/image_flatten.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/core/orientation.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/core/processing.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/core/region_mask.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/core/scars.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/core/tip.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/data/__init__.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/data/aggregation.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/__init__.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/icon.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/qt/__init__.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/qt/app.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/qt/boundary_view.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/qt/canvas.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/qt/efficiency_dialog.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/qt/import_view.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/qt/layout.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/qt/main_window.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/qt/swath_dialog.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/qt/wiki_view.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/qt/worker.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/state.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/io/__init__.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/io/file_io.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/io/ibw.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/io/metrics.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/io/spm.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/settings.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/stats/__init__.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/stats/analysis.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/stats/icc.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/visualization/__init__.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/visualization/diagnostics.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/visualization/profiles.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/visualization/statistics.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/wiki/__init__.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/wiki/facet-fitting.md +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/wiki/file-formats.md +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/wiki/flattening.md +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/wiki/groove-orientation.md +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/wiki/icc-correction.md +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/wiki/overview.md +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/wiki/reading-outputs.md +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/wiki/row-groups.md +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/wiki/scars-and-masking.md +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/wiki/swath-statistics.md +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/wiki/tip-correction.md +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/workflows.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/resolution.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/result.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/__init__.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/_conditioning.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/_execution.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/base.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/cmethod/__init__.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/cmethod/_core.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/cmethod/_series.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/integral/__init__.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/integral/_boundary.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/integral/_core.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/integral/_finite.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/integral/_greens.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/integral/_kernels.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/integral/_nystrom.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/rcwa/__init__.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/rcwa/_core.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/rcwa/_stack.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab.egg-info/dependency_links.txt +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab.egg-info/entry_points.txt +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab.egg-info/requires.txt +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab.egg-info/top_level.txt +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_changelog.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_checks.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_cmethod.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_compare.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_conditioning.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_convergence.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_cross_method.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_efficiency_table.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_four_way.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_fresnel.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_geometry.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_ggp.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_cmethod_options.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_cmethod_tab.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_compare_tab.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_diagram.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_diagram3d.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_docs.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_launcher.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_mathtext.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_orders.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_provenance.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_qt.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_rcwa_options.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_richtext.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_scalar_options.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_state.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_theme.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_illumination.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_integral_core.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_integral_corpus.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_integral_finite.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_integral_graded.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_integral_greens.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_integral_kernels.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_integral_operators.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_integral_solver.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_io_boundary.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_materials.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_perturbation.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_rayleigh_anomaly.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_rcwa.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_rcwa_benchmarks.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_refractiveindex.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_resolution.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_result.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_scalar.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_solver_conformance.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_solver_execution.py +0 -0
- {gratinglab-0.2.7 → gratinglab-0.2.8}/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.8
|
|
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
|
|
@@ -135,9 +135,17 @@ groove varies between horizontal swaths of the scan. It can also undo the broade
|
|
|
135
135
|
introduced by the AFM tip where the tip reached the surface, and it marks the regions
|
|
136
136
|
the tip could not reach instead of estimating them.
|
|
137
137
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
It also reads Zeiss SmartSEM electron micrographs (`metrology.io.sem`), with the
|
|
139
|
+
instrument's own pixel size, stage tilt and foreshortening. A cross-section is the
|
|
140
|
+
one groove measurement with no tip to correct for, and the only one that can see an
|
|
141
|
+
undercut or measure the width of a crest. Tracing a groove off a micrograph into a
|
|
142
|
+
profile is not written yet.
|
|
143
|
+
|
|
144
|
+
The efficiency side comprises the problem specification, the groove profiles
|
|
145
|
+
(blazed, lamellar, sinusoidal, trapezoidal with a sidewall angle and corner radius,
|
|
146
|
+
and any measured profile), the solvers, the comparison and convergence harnesses,
|
|
147
|
+
the materials layer, and a calculation of the resolving power implied by the number
|
|
148
|
+
of grooves measured.
|
|
141
149
|
|
|
142
150
|
The aim is gratings in general: reflection and transmission, metallic and
|
|
143
151
|
dielectric, bare and coated, from X-rays to the infrared. Every mount between the
|
|
@@ -90,9 +90,17 @@ groove varies between horizontal swaths of the scan. It can also undo the broade
|
|
|
90
90
|
introduced by the AFM tip where the tip reached the surface, and it marks the regions
|
|
91
91
|
the tip could not reach instead of estimating them.
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
It also reads Zeiss SmartSEM electron micrographs (`metrology.io.sem`), with the
|
|
94
|
+
instrument's own pixel size, stage tilt and foreshortening. A cross-section is the
|
|
95
|
+
one groove measurement with no tip to correct for, and the only one that can see an
|
|
96
|
+
undercut or measure the width of a crest. Tracing a groove off a micrograph into a
|
|
97
|
+
profile is not written yet.
|
|
98
|
+
|
|
99
|
+
The efficiency side comprises the problem specification, the groove profiles
|
|
100
|
+
(blazed, lamellar, sinusoidal, trapezoidal with a sidewall angle and corner radius,
|
|
101
|
+
and any measured profile), the solvers, the comparison and convergence harnesses,
|
|
102
|
+
the materials layer, and a calculation of the resolving power implied by the number
|
|
103
|
+
of grooves measured.
|
|
96
104
|
|
|
97
105
|
The aim is gratings in general: reflection and transmission, metallic and
|
|
98
106
|
dielectric, bare and coated, from X-rays to the infrared. Every mount between the
|
|
@@ -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.8"
|
|
26
26
|
|
|
27
27
|
__all__ = [
|
|
28
28
|
"Illumination",
|
|
@@ -28,6 +28,7 @@ solver's own check for nodes too close to separate is applied here too.
|
|
|
28
28
|
from __future__ import annotations
|
|
29
29
|
|
|
30
30
|
from dataclasses import dataclass, replace
|
|
31
|
+
from collections.abc import Callable
|
|
31
32
|
from typing import Any
|
|
32
33
|
|
|
33
34
|
import numpy as np
|
|
@@ -158,10 +159,55 @@ def build_options(
|
|
|
158
159
|
arc_length = (
|
|
159
160
|
problem.profile.boundary(_ARC_SAMPLES).arc_length * problem.period
|
|
160
161
|
)
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
162
|
+
material = None
|
|
163
|
+
if form.conductivity == "tabulated":
|
|
164
|
+
# Sequential prerequisites, not parallel checks: there is no index to
|
|
165
|
+
# range-check without a material, and no metal-side floor without an
|
|
166
|
+
# index. So these short-circuit rather than accumulating.
|
|
167
|
+
name, indices, error = _tabulated_index(problem, wavelengths)
|
|
168
|
+
if error is not None:
|
|
169
|
+
raise FormErrors((error,))
|
|
170
|
+
assert name is not None and indices is not None
|
|
171
|
+
material = (name, indices)
|
|
172
|
+
|
|
173
|
+
def floor_at(count: int) -> tuple[int, Callable[[int], str]]:
|
|
174
|
+
"""The floor a mesh of ``count`` nodes imposes, and its message.
|
|
175
|
+
|
|
176
|
+
The floor is set by the coarsest spacing. On the equal-arc mesh that
|
|
177
|
+
is the mean, arc_length / P, so the floor does not depend on ``count``;
|
|
178
|
+
a graded mesh is built here exactly as the solver will build it, since
|
|
179
|
+
its coarsest spacing depends on P. The message takes the count to
|
|
180
|
+
quote, which `_first_passing` may raise above this floor.
|
|
181
|
+
"""
|
|
182
|
+
resolution_length = arc_length
|
|
183
|
+
if grading:
|
|
184
|
+
mesh = physical_boundary(problem, count, grading=grading)
|
|
185
|
+
if mesh.graded:
|
|
186
|
+
resolution_length = mesh.resolution_length
|
|
187
|
+
reduced = float(wavelengths.min()) / illumination.sin_gamma
|
|
188
|
+
needed = int(np.ceil(_POINTS_PER_WAVELENGTH * resolution_length / reduced))
|
|
189
|
+
|
|
190
|
+
def message(quote: int) -> str:
|
|
191
|
+
return (
|
|
192
|
+
f"needs at least {quote} to give "
|
|
193
|
+
f"{_POINTS_PER_WAVELENGTH:g} nodes per transverse "
|
|
194
|
+
f"wavelength ({reduced:.4g} nm) along the "
|
|
195
|
+
f"{arc_length:.4g} nm boundary"
|
|
196
|
+
+ (", where the graded mesh's coarsest spacing sets the floor"
|
|
197
|
+
if resolution_length != arc_length else "")
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
if material is not None:
|
|
201
|
+
metal_needed, metal_message = _metal_floor(
|
|
202
|
+
*material, illumination, wavelengths, resolution_length
|
|
203
|
+
)
|
|
204
|
+
# One error on one field: whichever side of the boundary binds
|
|
205
|
+
# harder. Reporting both would put two messages on
|
|
206
|
+
# `boundary_points` that a single number answers.
|
|
207
|
+
if metal_needed > needed:
|
|
208
|
+
return metal_needed, metal_message
|
|
209
|
+
return needed, message
|
|
210
|
+
|
|
165
211
|
if grading:
|
|
166
212
|
try:
|
|
167
213
|
mesh = physical_boundary(problem, int(points), grading=grading)
|
|
@@ -176,38 +222,11 @@ def build_options(
|
|
|
176
222
|
"can separate on this groove; choose a lower order (4 is "
|
|
177
223
|
"recommended) or fewer points.",
|
|
178
224
|
),))
|
|
179
|
-
if mesh.graded:
|
|
180
|
-
resolution_length = mesh.resolution_length
|
|
181
|
-
reduced = float(wavelengths.min()) / illumination.sin_gamma
|
|
182
|
-
needed = int(np.ceil(_POINTS_PER_WAVELENGTH * resolution_length / reduced))
|
|
183
|
-
message = (
|
|
184
|
-
f"needs at least {needed} to give "
|
|
185
|
-
f"{_POINTS_PER_WAVELENGTH:g} nodes per transverse "
|
|
186
|
-
f"wavelength ({reduced:.4g} nm) along the "
|
|
187
|
-
f"{arc_length:.4g} nm boundary"
|
|
188
|
-
+ (", where the graded mesh's coarsest spacing sets the floor"
|
|
189
|
-
if resolution_length != arc_length else "")
|
|
190
|
-
)
|
|
191
|
-
|
|
192
|
-
if form.conductivity == "tabulated":
|
|
193
|
-
# Sequential prerequisites, not parallel checks: there is no index to
|
|
194
|
-
# range-check without a material, and no metal-side floor without an
|
|
195
|
-
# index. So these short-circuit rather than accumulating.
|
|
196
|
-
name, indices, error = _tabulated_index(problem, wavelengths)
|
|
197
|
-
if error is not None:
|
|
198
|
-
raise FormErrors((error,))
|
|
199
|
-
assert name is not None and indices is not None
|
|
200
|
-
metal_needed, metal_message = _metal_floor(
|
|
201
|
-
name, indices, illumination, wavelengths, resolution_length
|
|
202
|
-
)
|
|
203
|
-
# One error on one field: whichever side of the boundary binds harder.
|
|
204
|
-
# Reporting both would put two messages on `boundary_points` that a
|
|
205
|
-
# single number answers.
|
|
206
|
-
if metal_needed > needed:
|
|
207
|
-
needed, message = metal_needed, metal_message
|
|
208
225
|
|
|
226
|
+
needed, message = floor_at(int(points))
|
|
209
227
|
if points < needed:
|
|
210
|
-
|
|
228
|
+
quote = _first_passing(floor_at, needed) if grading else needed
|
|
229
|
+
raise FormErrors((FieldError("boundary_points", message(quote)),))
|
|
211
230
|
|
|
212
231
|
return {
|
|
213
232
|
"boundary_points": int(points),
|
|
@@ -270,7 +289,7 @@ def _metal_floor(
|
|
|
270
289
|
illumination: Illumination,
|
|
271
290
|
wavelengths: NDArray[np.float64],
|
|
272
291
|
arc_length: float,
|
|
273
|
-
) -> tuple[int, str]:
|
|
292
|
+
) -> tuple[int, Callable[[int], str]]:
|
|
274
293
|
"""The mesh floor the material side imposes, and what to say about it.
|
|
275
294
|
|
|
276
295
|
It uses the same formula as the solver's own guard, so the two numbers
|
|
@@ -283,9 +302,39 @@ def _metal_floor(
|
|
|
283
302
|
factors = np.abs(np.sqrt(indices**2 - cos_gamma**2))
|
|
284
303
|
reduced = float((wavelengths / factors).min())
|
|
285
304
|
needed = int(np.ceil(_POINTS_PER_WAVELENGTH * arc_length / reduced))
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
305
|
+
|
|
306
|
+
def message(quote: int) -> str:
|
|
307
|
+
return (
|
|
308
|
+
f"needs at least {quote} with coating {name}: the field inside a "
|
|
309
|
+
f"conductive material oscillates and decays on the scale lambda/|n| "
|
|
310
|
+
f"({reduced:.4g} nm here), and the mesh must resolve it along the "
|
|
311
|
+
f'{arc_length:.4g} nm boundary. Raise it, or use conductivity="perfect".'
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
return needed, message
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
#: How far above the first estimate `_first_passing` looks. The graded floor
|
|
318
|
+
#: moves by a node or two between neighbouring counts, so this is generous.
|
|
319
|
+
_FLOOR_SEARCH = 64
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def _first_passing(floor_at: Callable, estimate: int) -> int:
|
|
323
|
+
"""The smallest count from ``estimate`` up that clears its own floor.
|
|
324
|
+
|
|
325
|
+
On a graded mesh the floor depends on the count, because the coarsest
|
|
326
|
+
spacing moves with it, so the floor computed at the count typed is not the
|
|
327
|
+
floor at the count it names. Quoting it as it stood was one short at the
|
|
328
|
+
floor: at 32 points the default blaze said "at least 208", and 208 then
|
|
329
|
+
said 209. Searching upward makes the quoted number one the form accepts.
|
|
330
|
+
A count whose mesh cannot be built is skipped. If none clears within
|
|
331
|
+
``_FLOOR_SEARCH``, the estimate is returned, which is no worse than before.
|
|
332
|
+
"""
|
|
333
|
+
for count in range(estimate, estimate + _FLOOR_SEARCH):
|
|
334
|
+
try:
|
|
335
|
+
needed, _ = floor_at(count)
|
|
336
|
+
except ValueError:
|
|
337
|
+
continue
|
|
338
|
+
if needed <= count:
|
|
339
|
+
return count
|
|
340
|
+
return estimate
|