gratinglab 0.2.0__tar.gz → 0.2.2__tar.gz

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