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.
Files changed (197) hide show
  1. {gratinglab-0.2.7/src/gratinglab.egg-info → gratinglab-0.2.8}/PKG-INFO +12 -4
  2. {gratinglab-0.2.7 → gratinglab-0.2.8}/README.md +11 -3
  3. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/__init__.py +1 -1
  4. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/integral_options.py +90 -41
  5. gratinglab-0.2.8/src/gratinglab/metrology/io/sem.py +603 -0
  6. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/problem.py +8 -2
  7. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/profiles.py +337 -0
  8. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/scalar.py +12 -8
  9. {gratinglab-0.2.7 → gratinglab-0.2.8/src/gratinglab.egg-info}/PKG-INFO +12 -4
  10. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab.egg-info/SOURCES.txt +1 -0
  11. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_integral_options.py +42 -18
  12. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_measured.py +28 -0
  13. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_profiles.py +145 -1
  14. {gratinglab-0.2.7 → gratinglab-0.2.8}/LICENSE +0 -0
  15. {gratinglab-0.2.7 → gratinglab-0.2.8}/pyproject.toml +0 -0
  16. {gratinglab-0.2.7 → gratinglab-0.2.8}/setup.cfg +0 -0
  17. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/checks.py +0 -0
  18. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/compare.py +0 -0
  19. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/convergence.py +0 -0
  20. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/geometry.py +0 -0
  21. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/__init__.py +0 -0
  22. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/app.py +0 -0
  23. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/cmethod_options.py +0 -0
  24. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/comparison.py +0 -0
  25. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/diagram.py +0 -0
  26. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/diagram3d.py +0 -0
  27. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/docs.py +0 -0
  28. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/efficiency_plot.py +0 -0
  29. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/icon.py +0 -0
  30. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/launcher.py +0 -0
  31. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/mathtext.py +0 -0
  32. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/orders.py +0 -0
  33. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/provenance.py +0 -0
  34. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/__init__.py +0 -0
  35. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/cmethod_tab.py +0 -0
  36. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/compare_tab.py +0 -0
  37. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/geometry_panel.py +0 -0
  38. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/geometry_tab.py +0 -0
  39. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/integral_tab.py +0 -0
  40. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/launcher.py +0 -0
  41. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/main_window.py +0 -0
  42. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/profile_plot_panel.py +0 -0
  43. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/rcwa_tab.py +0 -0
  44. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/scalar_tab.py +0 -0
  45. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/scene3d_panel.py +0 -0
  46. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/setup_tab.py +0 -0
  47. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/sizing.py +0 -0
  48. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/theming.py +0 -0
  49. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/theory_viewer.py +0 -0
  50. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/qt/worker.py +0 -0
  51. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/rcwa_options.py +0 -0
  52. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/richtext.py +0 -0
  53. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/scalar_options.py +0 -0
  54. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/state.py +0 -0
  55. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/gui/theme.py +0 -0
  56. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/illumination.py +0 -0
  57. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/io/__init__.py +0 -0
  58. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/io/boundary.py +0 -0
  59. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/io/efficiency_table.py +0 -0
  60. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/io/ggp.py +0 -0
  61. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/materials/__init__.py +0 -0
  62. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/materials/data/SOURCES.md +0 -0
  63. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/materials/fresnel.py +0 -0
  64. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/materials/optical.py +0 -0
  65. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/materials/refractiveindex.py +0 -0
  66. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/measured.py +0 -0
  67. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/__init__.py +0 -0
  68. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/analyzer.py +0 -0
  69. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/boundary/__init__.py +0 -0
  70. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/boundary/average.py +0 -0
  71. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/boundary/pipeline.py +0 -0
  72. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/boundary/swaths.py +0 -0
  73. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/cli.py +0 -0
  74. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/config.py +0 -0
  75. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/core/__init__.py +0 -0
  76. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/core/analysis.py +0 -0
  77. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/core/image_flatten.py +0 -0
  78. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/core/orientation.py +0 -0
  79. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/core/processing.py +0 -0
  80. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/core/region_mask.py +0 -0
  81. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/core/scars.py +0 -0
  82. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/core/tip.py +0 -0
  83. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/data/__init__.py +0 -0
  84. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/data/aggregation.py +0 -0
  85. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/__init__.py +0 -0
  86. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/icon.py +0 -0
  87. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/qt/__init__.py +0 -0
  88. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/qt/app.py +0 -0
  89. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/qt/boundary_view.py +0 -0
  90. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/qt/canvas.py +0 -0
  91. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/qt/efficiency_dialog.py +0 -0
  92. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/qt/import_view.py +0 -0
  93. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/qt/layout.py +0 -0
  94. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/qt/main_window.py +0 -0
  95. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/qt/swath_dialog.py +0 -0
  96. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/qt/wiki_view.py +0 -0
  97. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/qt/worker.py +0 -0
  98. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/gui/state.py +0 -0
  99. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/io/__init__.py +0 -0
  100. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/io/file_io.py +0 -0
  101. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/io/ibw.py +0 -0
  102. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/io/metrics.py +0 -0
  103. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/io/spm.py +0 -0
  104. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/settings.py +0 -0
  105. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/stats/__init__.py +0 -0
  106. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/stats/analysis.py +0 -0
  107. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/stats/icc.py +0 -0
  108. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/visualization/__init__.py +0 -0
  109. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/visualization/diagnostics.py +0 -0
  110. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/visualization/profiles.py +0 -0
  111. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/visualization/statistics.py +0 -0
  112. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/wiki/__init__.py +0 -0
  113. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/wiki/facet-fitting.md +0 -0
  114. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/wiki/file-formats.md +0 -0
  115. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/wiki/flattening.md +0 -0
  116. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/wiki/groove-orientation.md +0 -0
  117. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/wiki/icc-correction.md +0 -0
  118. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/wiki/overview.md +0 -0
  119. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/wiki/reading-outputs.md +0 -0
  120. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/wiki/row-groups.md +0 -0
  121. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/wiki/scars-and-masking.md +0 -0
  122. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/wiki/swath-statistics.md +0 -0
  123. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/wiki/tip-correction.md +0 -0
  124. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/metrology/workflows.py +0 -0
  125. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/resolution.py +0 -0
  126. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/result.py +0 -0
  127. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/__init__.py +0 -0
  128. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/_conditioning.py +0 -0
  129. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/_execution.py +0 -0
  130. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/base.py +0 -0
  131. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/cmethod/__init__.py +0 -0
  132. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/cmethod/_core.py +0 -0
  133. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/cmethod/_series.py +0 -0
  134. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/integral/__init__.py +0 -0
  135. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/integral/_boundary.py +0 -0
  136. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/integral/_core.py +0 -0
  137. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/integral/_finite.py +0 -0
  138. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/integral/_greens.py +0 -0
  139. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/integral/_kernels.py +0 -0
  140. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/integral/_nystrom.py +0 -0
  141. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/rcwa/__init__.py +0 -0
  142. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/rcwa/_core.py +0 -0
  143. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab/solvers/rcwa/_stack.py +0 -0
  144. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab.egg-info/dependency_links.txt +0 -0
  145. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab.egg-info/entry_points.txt +0 -0
  146. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab.egg-info/requires.txt +0 -0
  147. {gratinglab-0.2.7 → gratinglab-0.2.8}/src/gratinglab.egg-info/top_level.txt +0 -0
  148. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_changelog.py +0 -0
  149. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_checks.py +0 -0
  150. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_cmethod.py +0 -0
  151. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_compare.py +0 -0
  152. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_conditioning.py +0 -0
  153. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_convergence.py +0 -0
  154. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_cross_method.py +0 -0
  155. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_efficiency_table.py +0 -0
  156. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_four_way.py +0 -0
  157. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_fresnel.py +0 -0
  158. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_geometry.py +0 -0
  159. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_ggp.py +0 -0
  160. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_cmethod_options.py +0 -0
  161. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_cmethod_tab.py +0 -0
  162. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_compare_tab.py +0 -0
  163. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_diagram.py +0 -0
  164. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_diagram3d.py +0 -0
  165. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_docs.py +0 -0
  166. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_launcher.py +0 -0
  167. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_mathtext.py +0 -0
  168. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_orders.py +0 -0
  169. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_provenance.py +0 -0
  170. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_qt.py +0 -0
  171. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_rcwa_options.py +0 -0
  172. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_richtext.py +0 -0
  173. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_scalar_options.py +0 -0
  174. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_state.py +0 -0
  175. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_gui_theme.py +0 -0
  176. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_illumination.py +0 -0
  177. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_integral_core.py +0 -0
  178. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_integral_corpus.py +0 -0
  179. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_integral_finite.py +0 -0
  180. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_integral_graded.py +0 -0
  181. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_integral_greens.py +0 -0
  182. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_integral_kernels.py +0 -0
  183. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_integral_operators.py +0 -0
  184. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_integral_solver.py +0 -0
  185. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_io_boundary.py +0 -0
  186. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_materials.py +0 -0
  187. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_perturbation.py +0 -0
  188. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_rayleigh_anomaly.py +0 -0
  189. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_rcwa.py +0 -0
  190. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_rcwa_benchmarks.py +0 -0
  191. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_refractiveindex.py +0 -0
  192. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_resolution.py +0 -0
  193. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_result.py +0 -0
  194. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_scalar.py +0 -0
  195. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_solver_conformance.py +0 -0
  196. {gratinglab-0.2.7 → gratinglab-0.2.8}/tests/test_solver_execution.py +0 -0
  197. {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.7
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
- The efficiency side comprises the problem specification, the solvers, the comparison
139
- and convergence harnesses, the materials layer, and a calculation of the resolving
140
- power implied by the number of grooves measured.
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
- The efficiency side comprises the problem specification, the solvers, the comparison
94
- and convergence harnesses, the materials layer, and a calculation of the resolving
95
- power implied by the number of grooves measured.
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.7"
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
- # The floor is set by the coarsest spacing. On the equal-arc mesh that is
162
- # the mean, arc_length / P; a graded mesh is built here exactly as the
163
- # solver will build it, since its coarsest spacing depends on P.
164
- resolution_length = arc_length
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
- raise FormErrors((FieldError("boundary_points", message),))
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
- return needed, (
287
- f"needs at least {needed} with coating {name}: the field inside a "
288
- f"conductive material oscillates and decays on the scale lambda/|n| "
289
- f"({reduced:.4g} nm here), and the mesh must resolve it along the "
290
- f'{arc_length:.4g} nm boundary. Raise it, or use conductivity="perfect".'
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