autoarray 2026.9.27.2__tar.gz → 2026.10.2.1__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 (276) hide show
  1. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/.claude/hooks/session-start.sh +8 -8
  2. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/PKG-INFO +1 -1
  3. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/__init__.py +2 -1
  4. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/config/general.yaml +1 -1
  5. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/dataset/abstract/dataset.py +10 -1
  6. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/dataset/imaging/dataset.py +56 -3
  7. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/dataset/interferometer/dataset.py +437 -34
  8. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/dataset/plot/interferometer_plots.py +78 -4
  9. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/fit/fit_interferometer.py +135 -1
  10. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/fit/plot/fit_interferometer_plots.py +108 -0
  11. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/inversion/abstract.py +19 -1
  12. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/inversion/dataset_interface.py +20 -0
  13. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/inversion/imaging/abstract.py +1 -1
  14. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/inversion/interferometer/abstract.py +63 -8
  15. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/inversion/interferometer/inversion_interferometer_util.py +612 -1
  16. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/inversion/interferometer/sparse.py +10 -0
  17. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/inversion/inversion_util.py +3 -1
  18. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/plot/inversion_plots.py +28 -8
  19. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/settings.py +5 -1
  20. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/util/jax_nnls.py +83 -42
  21. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/.claude/hooks/end-at-deliverable.sh +0 -0
  22. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/.claude/settings.json +0 -0
  23. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/.gitattributes +0 -0
  24. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  25. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  26. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/.github/copilot-instructions.md +0 -0
  27. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/.github/workflows/main.yml +0 -0
  28. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/.url_check_allowlist.txt +0 -0
  29. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/AGENTS.md +0 -0
  30. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/AI_POLICY.md +0 -0
  31. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/CLAUDE.md +0 -0
  32. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/CONTRIBUTING.md +0 -0
  33. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/LICENSE +0 -0
  34. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/MANIFEST.in +0 -0
  35. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/README.md +0 -0
  36. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/abstract_ndarray.py +0 -0
  37. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/config/.gitignore +0 -0
  38. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/config/README.md +0 -0
  39. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/config/logging.yaml +0 -0
  40. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/config/visualize/README.md +0 -0
  41. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/config/visualize/general.yaml +0 -0
  42. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/config/visualize/plots.yaml +0 -0
  43. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/dataset/__init__.py +0 -0
  44. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/dataset/abstract/__init__.py +0 -0
  45. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/dataset/dataset_model.py +0 -0
  46. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/dataset/grids.py +0 -0
  47. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/dataset/imaging/__init__.py +0 -0
  48. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/dataset/imaging/simulator.py +0 -0
  49. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/dataset/interferometer/__init__.py +0 -0
  50. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/dataset/interferometer/simulator.py +0 -0
  51. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/dataset/mock/__init__.py +0 -0
  52. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/dataset/mock/mock_dataset.py +0 -0
  53. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/dataset/plot/__init__.py +0 -0
  54. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/dataset/plot/imaging_plots.py +0 -0
  55. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/dataset/preprocess.py +0 -0
  56. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/exc.py +0 -0
  57. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/fit/__init__.py +0 -0
  58. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/fit/fit_dataset.py +0 -0
  59. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/fit/fit_imaging.py +0 -0
  60. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/fit/fit_util.py +0 -0
  61. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/fit/mock/__init__.py +0 -0
  62. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/fit/mock/mock_fit_imaging.py +0 -0
  63. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/fit/mock/mock_fit_interferometer.py +0 -0
  64. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/fit/plot/__init__.py +0 -0
  65. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/fit/plot/fit_imaging_plots.py +0 -0
  66. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/fixtures.py +0 -0
  67. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/geometry/__init__.py +0 -0
  68. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/geometry/abstract_2d.py +0 -0
  69. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/geometry/geometry_1d.py +0 -0
  70. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/geometry/geometry_2d.py +0 -0
  71. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/geometry/geometry_2d_irregular.py +0 -0
  72. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/geometry/geometry_util.py +0 -0
  73. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/__init__.py +0 -0
  74. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/inversion/__init__.py +0 -0
  75. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/inversion/factory.py +0 -0
  76. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/inversion/imaging/__init__.py +0 -0
  77. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/inversion/imaging/inversion_imaging_util.py +0 -0
  78. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/inversion/imaging/mapping.py +0 -0
  79. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/inversion/imaging/sparse.py +0 -0
  80. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/inversion/imaging_numba/__init__.py +0 -0
  81. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/inversion/imaging_numba/inversion_imaging_numba_util.py +0 -0
  82. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/inversion/imaging_numba/sparse.py +0 -0
  83. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/inversion/interferometer/__init__.py +0 -0
  84. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/inversion/interferometer/mapping.py +0 -0
  85. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/inversion/interferometer_numba/__init__.py +0 -0
  86. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/inversion/interferometer_numba/inversion_interferometer_numba_util.py +0 -0
  87. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/inversion/interferometer_numba/sparse.py +0 -0
  88. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/inversion/nnls_memo.py +0 -0
  89. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/linear_obj/__init__.py +0 -0
  90. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/linear_obj/func_list.py +0 -0
  91. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/linear_obj/linear_obj.py +0 -0
  92. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/linear_obj/neighbors.py +0 -0
  93. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/linear_obj/unique_mappings.py +0 -0
  94. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mappers/__init__.py +0 -0
  95. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mappers/abstract.py +0 -0
  96. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mappers/mapper_numba_util.py +0 -0
  97. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mappers/mapper_util.py +0 -0
  98. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mappings/__init__.py +0 -0
  99. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mappings/mapping.py +0 -0
  100. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/__init__.py +0 -0
  101. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/border_relocator.py +0 -0
  102. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/image_mesh/__init__.py +0 -0
  103. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/image_mesh/abstract.py +0 -0
  104. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/image_mesh/abstract_weighted.py +0 -0
  105. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/image_mesh/hilbert.py +0 -0
  106. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/image_mesh/kmeans.py +0 -0
  107. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/image_mesh/overlay.py +0 -0
  108. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/interpolator/__init__.py +0 -0
  109. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/interpolator/abstract.py +0 -0
  110. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/interpolator/delaunay.py +0 -0
  111. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/interpolator/knn.py +0 -0
  112. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/interpolator/rectangular.py +0 -0
  113. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/interpolator/rectangular_uniform.py +0 -0
  114. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/interpolator/sibson.py +0 -0
  115. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/mesh/__init__.py +0 -0
  116. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/mesh/abstract.py +0 -0
  117. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/mesh/delaunay.py +0 -0
  118. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/mesh/delaunay_nn.py +0 -0
  119. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/mesh/knn.py +0 -0
  120. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/mesh/rectangular_bilinear_adapt_density.py +0 -0
  121. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/mesh/rectangular_bilinear_adapt_image.py +0 -0
  122. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/mesh/rectangular_rtu_adapt_density.py +0 -0
  123. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/mesh/rectangular_rtu_adapt_image.py +0 -0
  124. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/mesh/rectangular_uniform.py +0 -0
  125. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/mesh_geometry/__init__.py +0 -0
  126. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/mesh_geometry/abstract.py +0 -0
  127. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/mesh_geometry/delaunay.py +0 -0
  128. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mesh/mesh_geometry/rectangular.py +0 -0
  129. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mock/__init__.py +0 -0
  130. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mock/mock_image_mesh.py +0 -0
  131. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mock/mock_interpolator.py +0 -0
  132. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mock/mock_inversion.py +0 -0
  133. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mock/mock_inversion_imaging.py +0 -0
  134. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mock/mock_inversion_interferometer.py +0 -0
  135. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mock/mock_linear_obj.py +0 -0
  136. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mock/mock_linear_obj_func_list.py +0 -0
  137. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mock/mock_mapper.py +0 -0
  138. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mock/mock_mesh.py +0 -0
  139. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mock/mock_pixelization.py +0 -0
  140. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/mock/mock_regularization.py +0 -0
  141. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/pixelization.py +0 -0
  142. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/plot/__init__.py +0 -0
  143. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/plot/mapper_plots.py +0 -0
  144. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/regularization/__init__.py +0 -0
  145. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/regularization/abstract.py +0 -0
  146. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/regularization/adapt.py +0 -0
  147. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/regularization/adapt_power.py +0 -0
  148. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/regularization/adapt_split.py +0 -0
  149. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/regularization/adapt_split_power.py +0 -0
  150. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/regularization/adapt_split_zeroth.py +0 -0
  151. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/regularization/adapt_split_zeroth_power.py +0 -0
  152. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/regularization/brightness_zeroth.py +0 -0
  153. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/regularization/constant.py +0 -0
  154. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/regularization/constant_split.py +0 -0
  155. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/regularization/constant_zeroth.py +0 -0
  156. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/regularization/curvature_mask.py +0 -0
  157. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/regularization/exponential_kernel.py +0 -0
  158. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/regularization/fourth_order_mask.py +0 -0
  159. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/regularization/gaussian_kernel.py +0 -0
  160. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/regularization/matern_adapt_kernel.py +0 -0
  161. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/regularization/matern_adapt_power_kernel.py +0 -0
  162. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/regularization/matern_kernel.py +0 -0
  163. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/regularization/regularization_util.py +0 -0
  164. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/inversion/regularization/zeroth.py +0 -0
  165. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/layout/__init__.py +0 -0
  166. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/layout/layout.py +0 -0
  167. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/layout/layout_util.py +0 -0
  168. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/layout/region.py +0 -0
  169. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/mask/__init__.py +0 -0
  170. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/mask/abstract_mask.py +0 -0
  171. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/mask/derive/__init__.py +0 -0
  172. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/mask/derive/grid_1d.py +0 -0
  173. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/mask/derive/grid_2d.py +0 -0
  174. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/mask/derive/indexes_2d.py +0 -0
  175. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/mask/derive/mask_1d.py +0 -0
  176. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/mask/derive/mask_2d.py +0 -0
  177. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/mask/derive/zoom_2d.py +0 -0
  178. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/mask/mask_1d.py +0 -0
  179. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/mask/mask_1d_util.py +0 -0
  180. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/mask/mask_2d.py +0 -0
  181. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/mask/mask_2d_util.py +0 -0
  182. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/mask/mock/__init__.py +0 -0
  183. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/mask/mock/mock_mask.py +0 -0
  184. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/mock.py +0 -0
  185. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/numba_util.py +0 -0
  186. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/operators/__init__.py +0 -0
  187. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/operators/coarse_interp_util.py +0 -0
  188. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/operators/contour.py +0 -0
  189. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/operators/convolver.py +0 -0
  190. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/operators/derivative_util.py +0 -0
  191. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/operators/interp_2d.py +0 -0
  192. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/operators/mock/__init__.py +0 -0
  193. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/operators/mock/mock_psf.py +0 -0
  194. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/operators/over_sampling/__init__.py +0 -0
  195. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/operators/over_sampling/decorator.py +0 -0
  196. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/operators/over_sampling/over_sample_util.py +0 -0
  197. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/operators/over_sampling/over_sampler.py +0 -0
  198. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/operators/transformer.py +0 -0
  199. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/operators/transformer_util.py +0 -0
  200. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/plot/__init__.py +0 -0
  201. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/plot/array.py +0 -0
  202. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/plot/grid.py +0 -0
  203. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/plot/inversion.py +0 -0
  204. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/plot/output.py +0 -0
  205. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/plot/segmentdata.py +0 -0
  206. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/plot/utils.py +0 -0
  207. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/plot/yx.py +0 -0
  208. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/preloads/__init__.py +0 -0
  209. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/preloads/abstract.py +0 -0
  210. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/preloads/imaging.py +0 -0
  211. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/preloads/interferometer.py +0 -0
  212. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/__init__.py +0 -0
  213. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/abstract_structure.py +0 -0
  214. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/arrays/__init__.py +0 -0
  215. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/arrays/array_1d_util.py +0 -0
  216. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/arrays/array_2d_util.py +0 -0
  217. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/arrays/irregular.py +0 -0
  218. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/arrays/rgb.py +0 -0
  219. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/arrays/uniform_1d.py +0 -0
  220. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/arrays/uniform_2d.py +0 -0
  221. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/decorators/__init__.py +0 -0
  222. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/decorators/abstract.py +0 -0
  223. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/decorators/to_array.py +0 -0
  224. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/decorators/to_grid.py +0 -0
  225. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/decorators/to_vector_yx.py +0 -0
  226. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/decorators/transform.py +0 -0
  227. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/grids/__init__.py +0 -0
  228. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/grids/grid_1d_util.py +0 -0
  229. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/grids/grid_2d_util.py +0 -0
  230. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/grids/irregular_2d.py +0 -0
  231. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/grids/sparse_2d_util.py +0 -0
  232. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/grids/uniform_1d.py +0 -0
  233. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/grids/uniform_2d.py +0 -0
  234. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/header.py +0 -0
  235. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/mock/__init__.py +0 -0
  236. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/mock/mock_decorators.py +0 -0
  237. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/mock/mock_grid.py +0 -0
  238. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/plot/__init__.py +0 -0
  239. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/plot/structure_plots.py +0 -0
  240. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/triangles/__init__.py +0 -0
  241. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/triangles/abstract.py +0 -0
  242. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/triangles/array.py +0 -0
  243. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/triangles/array_np.py +0 -0
  244. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/triangles/coordinate_array.py +0 -0
  245. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/triangles/coordinate_array_np.py +0 -0
  246. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/triangles/shape.py +0 -0
  247. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/vectors/__init__.py +0 -0
  248. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/vectors/abstract.py +0 -0
  249. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/vectors/irregular.py +0 -0
  250. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/vectors/uniform.py +0 -0
  251. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/structures/visibilities.py +0 -0
  252. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/type.py +0 -0
  253. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/util/__init__.py +0 -0
  254. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/util/cholesky_funcs.py +0 -0
  255. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/util/dataset_util.py +0 -0
  256. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/util/fnnls.py +0 -0
  257. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/util/jax_active_set.py +0 -0
  258. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/util/misc_util.py +0 -0
  259. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray/validate.py +0 -0
  260. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/autoarray.egg-info/SOURCES.txt +0 -0
  261. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/docs/Makefile +0 -0
  262. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/docs/agents/jax_and_decorators.md +0 -0
  263. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/docs/conf.py +0 -0
  264. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/docs/index.md +0 -0
  265. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/docs/make.bat +0 -0
  266. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/files/cdf_audit.md +0 -0
  267. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/files/ghost_peak.png +0 -0
  268. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/files/ghost_peak_experiment.py +0 -0
  269. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/files/ghost_peak_findings.md +0 -0
  270. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/files/pca_rotation.png +0 -0
  271. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/files/pca_rotation_experiment.py +0 -0
  272. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/llms.txt +0 -0
  273. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/pyproject.toml +0 -0
  274. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/readthedocs.yml +0 -0
  275. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/setup.cfg +0 -0
  276. {autoarray-2026.9.27.2 → autoarray-2026.10.2.1}/setup.py +0 -0
@@ -130,14 +130,14 @@ marked_root() {
130
130
  # A directory counts as a workspace root if it holds an organ checkout. Any
131
131
  # organ: a remote session may hold exactly one, and it is still a root.
132
132
  holds_an_organ() {
133
- [ -d "$1/PyAutoMind" ] || [ -d "$1/PyAutoBrain" ] || [ -d "$1/PyAutoHeart" ] \
134
- || [ -d "$1/PyAutoHands" ] || [ -d "$1/PyAutoMemory" ] || [ -d "$1/PyAutoGut" ] \
135
- || [ -d "$1/PyAutoNerves" ] || [ -d "$1/PyAutoCortex" ] || [ -d "$1/PyAutoEyes" ] \
136
- || [ -d "$1/organs/PyAutoMind" ] \
137
- || [ -d "$1/organs/PyAutoBrain" ] || [ -d "$1/organs/PyAutoHeart" ] \
138
- || [ -d "$1/organs/PyAutoHands" ] || [ -d "$1/organs/PyAutoMemory" ] \
139
- || [ -d "$1/organs/PyAutoGut" ] || [ -d "$1/organs/PyAutoNerves" ] \
140
- || [ -d "$1/organs/PyAutoCortex" ] || [ -d "$1/organs/PyAutoEyes" ]
133
+ [ -d "$1/PyAutoBrain" ] || [ -d "$1/PyAutoMind" ] || [ -d "$1/PyAutoCortex" ] \
134
+ || [ -d "$1/PyAutoMemory" ] || [ -d "$1/PyAutoEyes" ] || [ -d "$1/PyAutoHeart" ] \
135
+ || [ -d "$1/PyAutoHands" ] || [ -d "$1/PyAutoNerves" ] || [ -d "$1/PyAutoGut" ] \
136
+ || [ -d "$1/organs/PyAutoBrain" ] || [ -d "$1/organs/PyAutoMind" ] \
137
+ || [ -d "$1/organs/PyAutoCortex" ] || [ -d "$1/organs/PyAutoMemory" ] \
138
+ || [ -d "$1/organs/PyAutoEyes" ] || [ -d "$1/organs/PyAutoHeart" ] \
139
+ || [ -d "$1/organs/PyAutoHands" ] || [ -d "$1/organs/PyAutoNerves" ] \
140
+ || [ -d "$1/organs/PyAutoGut" ]
141
141
  }
142
142
 
143
143
  # Assigns WORKSPACE_ROOT and WORKSPACE_ROOT_REASON rather than printing: one
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: autoarray
3
- Version: 2026.9.27.2
3
+ Version: 2026.10.2.1
4
4
  Summary: PyAuto Data Structures
5
5
  Author-email: James Nightingale <James.Nightingale@newcastle.ac.uk>, Richard Hayes <richard@rghsoftware.co.uk>
6
6
  License: MIT
@@ -53,6 +53,7 @@ from .inversion.inversion.interferometer.sparse import (
53
53
  from .inversion.inversion.interferometer.mapping import InversionInterferometerMapping
54
54
  from .inversion.inversion.interferometer.inversion_interferometer_util import (
55
55
  InterferometerSparseOperator,
56
+ SparseTerms,
56
57
  )
57
58
  from .inversion.linear_obj.linear_obj import LinearObj
58
59
  from .inversion.linear_obj.func_list import AbstractLinearObjFuncList
@@ -111,7 +112,7 @@ conf.instance.register(__file__)
111
112
  # Last manual sync of the source stamp. Release wheels are stamped at build
112
113
  # time and the git tag is the release truth — deliberately never bumped per
113
114
  # release (PyAutoBuild#118/#120).
114
- __version__ = "2026.9.27.2"
115
+ __version__ = "2026.10.2.1"
115
116
 
116
117
  # ---------------------------------------------------------------------------
117
118
  # Public re-export of the autonerves configuration / serialization surface.
@@ -8,7 +8,7 @@ inversion:
8
8
  use_border_relocator: false # If True, by default a pixelization's border is used to relocate all pixels outside its border to the border.
9
9
  nnls_jacobi_preconditioning: true # If True (default), the curvature matrix passed to jaxnnls.solve_nnls_primal is Jacobi-preconditioned (D Q D y = D q, x = D y). Fixes NaN backward-pass gradients on ill-conditioned Q and roughly halves forward solve time. Set False to restore the raw unpreconditioned solve.
10
10
  nnls_target_kappa: 1.0e-11 # Central-path relaxation parameter passed to jaxnnls.solve_nnls_primal. Larger values smooth the relaxed-KKT backward pass and prevent NaN gradients on ill-conditioned Q; smaller values tighten the primal solve. Verified finite gradients across all MGE/rectangular/delaunay pipelines (imaging + interferometer) with scale invariance over 5 orders of magnitude in noise. jaxnnls's own default (1e-3) is too aggressive for the backward pass. The relaxed solve must start from an iterate whose complementarity s*z is not far above this value; the "raw" no-mapper mode polishes its forward iterate to ensure that (PyAutoArray#573).
11
- nnls_preconditioning_no_mapper: raw # How the JAX positive-only PDIP solve scales inversions with NO mapper (linear light profiles / MGE only). "raw" (default) runs the forward solve on the un-preconditioned system with a data-scaled KKT tolerance (1e-2 * n * eps * max(1, max|data_vector|)) and keeps the Jacobi-space relaxed-KKT gradient, whose relaxed solve starts from the forward iterate polished by <= 10 tight warm-started PDIP iterations on the Jacobi system (without the polish the loose forward tolerance leaves s*z far above nnls_target_kappa and the relaxed solve diverged to NaN gradients on 4/16 jax_grad/mge.py points, PyAutoArray#573); "jacobi" uses the Jacobi-preconditioned solve. Jacobi scaling of signal-free MGE columns (diagonal = the no-regularization floor) made the PDIP dual diverge on 14/48 SLaM source_lp[1] points (PyAutoArray#571). Inversions with a mapper always use jacobi; the NumPy path is unaffected.
11
+ nnls_preconditioning_no_mapper: raw # How the JAX positive-only PDIP solve scales inversions with NO mapper (linear light profiles / MGE only). "raw" (default) runs the forward solve on the un-preconditioned system with a data-scaled KKT tolerance (1e-2 * n * eps * max(1, max|data_vector|)), polishes that iterate with <= 10 tight warm-started PDIP iterations on the Jacobi system and returns the polished iterate (the loose tolerance also judges complementarity, so unpolished it left 11.5 % of the fnnls flux on inactive columns of the euclid vis_lp system; polished <= 3.3e-4 over 81 corpus systems, ~5 extra iterations, PyAutoArray#594), and keeps the Jacobi-space relaxed-KKT gradient started from the same polished point (without the polish the relaxed solve diverged to NaN gradients on 4/16 jax_grad/mge.py points, PyAutoArray#573); "jacobi" uses the Jacobi-preconditioned solve. Jacobi scaling of signal-free MGE columns (diagonal = the no-regularization floor) made the PDIP dual diverge on 14/48 SLaM source_lp[1] points (PyAutoArray#571). Inversions with a mapper always use jacobi; the NumPy path is unaffected.
12
12
  nnls_warm_start_memo: true # If True (default), the NumPy/numba positive-only (fnnls) solve warm-starts its active set from the previous likelihood evaluation's passive set, cutting active-set iterations on successive sampler evaluations. The NNLS optimum is unique so the reconstruction is unchanged. On by default as of PyAutoArray#498, measured on the euclid+hst Delaunay-1250 fiducial (9.9x / 4.0x fewer active-set iterations on successive evaluations, reconstruction unchanged). Set false, or AUTOARRAY_NNLS_WARM_START=0, to disable. JAX path unaffected.
13
13
  nnls_warm_start_error_tolerance: 1.5 # Relative quality guard on a warm-start memo seed. Each memo entry remembers the error fraction of the most recent dense-sign-started solve for that key; a seeded solve whose own error fraction exceeds this multiple of that reference is dropped, so the next solve restarts from the dense-sign start and refreshes the reference. Default 1.5 sits above the worst seed/dense error-fraction ratio seen in the PyAutoArray#498 32-cell robustness matrix (1.42), so it is protective against unmeasured regimes rather than flapping. Any non-finite or non-positive value (e.g. .inf) disables the guard. NumPy/numba fnnls path only.
14
14
  positive_only_solver: pdip # Which solver the JAX (xp=jnp) positive-only reconstruction uses. "pdip" (default) is the jaxnnls interior-point solve; "certified" is the certified active-set solve (budgeted masked-Cholesky passes that stop once the KKT conditions certify, exact implicit gradient, PDIP fallback), measured 1.2-2.6x faster on source-only inversions (PyAutoArray#566). Applied only to mapper-only JAX inversions (MGE / linear light profiles keep PDIP); the NumPy path always uses fnnls. Opt-in until the batched (vmap) policy is measured.
@@ -94,7 +94,12 @@ class AbstractDataset:
94
94
 
95
95
  self.noise_covariance_matrix = noise_covariance_matrix
96
96
 
97
- if noise_map is None:
97
+ # An array-free dataset (e.g. `Interferometer.from_stream`) carries neither data nor a
98
+ # noise-map: everything its likelihood needs was reduced into a sparse operator
99
+ # upstream, so there is no diagonal to take and nothing to check.
100
+ if noise_map is None and data is None and noise_covariance_matrix is None:
101
+ pass
102
+ elif noise_map is None:
98
103
  try:
99
104
  noise_map = Array2D.no_mask(
100
105
  values=np.diag(noise_covariance_matrix),
@@ -174,6 +179,10 @@ class AbstractDataset:
174
179
  """
175
180
  The 1D size of the dataset data array after masking, i.e. the number of unmasked pixels.
176
181
  """
182
+ # An array-free dataset has no data array; the mask's slim size is not a substitute
183
+ # (for an interferometer the data is visibilities, not image pixels).
184
+ if self.data is None:
185
+ return None
177
186
  return self.data.shape_slim
178
187
 
179
188
  @property
@@ -61,6 +61,36 @@ def _validate_convolve_over_sample_size(
61
61
  )
62
62
 
63
63
 
64
+ _SPARSE_OPERATOR_CONVOLVE_OVER_SAMPLE_SIZE_ERROR = (
65
+ "The sparse linear algebra formalism precomputes PSF products at "
66
+ "image resolution and is incompatible with an oversampled PSF "
67
+ "(convolve_over_sample_size > 1)."
68
+ )
69
+
70
+
71
+ def _warn_sparse_operator_discarded(sparse_operator, method_name: str) -> None:
72
+ """
73
+ Log a warning when a dataset rebuild discards an attached sparse operator.
74
+
75
+ The sparse operator precomputes PSF products of every pair of masked noise-map
76
+ values, so it is invalidated by any change to the mask or noise-map. Rebuilds
77
+ which make such changes (e.g. `apply_mask`, `apply_noise_scaling`) therefore do
78
+ not carry it, and the returned dataset falls back to the (slower) mapping matrix
79
+ formalism unless the operator is re-applied. This warning stops that fallback
80
+ from happening silently.
81
+ """
82
+ if sparse_operator is None:
83
+ return
84
+
85
+ logger.warning(
86
+ f"IMAGING - {method_name} changes the mask or noise-map, which invalidates the "
87
+ f"sparse operator attached to this dataset, so it has been discarded. Pixelized "
88
+ f"reconstructions will use the slower mapping matrix formalism unless the sparse "
89
+ f"operator is re-applied (via apply_sparse_operator() or "
90
+ f"apply_sparse_operator_cpu()) as the last dataset operation."
91
+ )
92
+
93
+
64
94
  class Imaging(AbstractDataset):
65
95
  def __init__(
66
96
  self,
@@ -439,6 +469,10 @@ class Imaging(AbstractDataset):
439
469
  values=self.over_sample_size_pixelization.native, mask=mask
440
470
  )
441
471
 
472
+ _warn_sparse_operator_discarded(
473
+ sparse_operator=self.sparse_operator, method_name="apply_mask"
474
+ )
475
+
442
476
  dataset = Imaging(
443
477
  data=data,
444
478
  noise_map=noise_map,
@@ -520,6 +554,10 @@ class Imaging(AbstractDataset):
520
554
 
521
555
  noise_map = Array2D(values=noise_map, mask=self.data.mask)
522
556
 
557
+ _warn_sparse_operator_discarded(
558
+ sparse_operator=self.sparse_operator, method_name="apply_noise_scaling"
559
+ )
560
+
523
561
  dataset = Imaging(
524
562
  data=data,
525
563
  noise_map=noise_map,
@@ -527,6 +565,8 @@ class Imaging(AbstractDataset):
527
565
  noise_covariance_matrix=self.noise_covariance_matrix,
528
566
  over_sample_size_lp=self.over_sample_size_lp,
529
567
  over_sample_size_pixelization=self.over_sample_size_pixelization,
568
+ convolve_over_sample_size_lp=self.convolve_over_sample_size_lp,
569
+ convolve_over_sample_size_pixelization=self.convolve_over_sample_size_pixelization,
530
570
  check_noise_map=False,
531
571
  )
532
572
 
@@ -551,6 +591,10 @@ class Imaging(AbstractDataset):
551
591
  This function resets the cached properties so that the new over sampling is used in the grid and grid
552
592
  pixelization.
553
593
 
594
+ The `noise_covariance_matrix` and any attached `sparse_operator` are carried over, as neither depends on
595
+ the over sampling (the sparse operator depends only on the noise-map, PSF kernel and mask). This means
596
+ `apply_sparse_operator()` / `apply_sparse_operator_cpu()` may be called before or after this method.
597
+
554
598
  Parameters
555
599
  ----------
556
600
  over_sample_size_lp
@@ -566,12 +610,14 @@ class Imaging(AbstractDataset):
566
610
  data=self.data,
567
611
  noise_map=self.noise_map,
568
612
  psf=self.psf,
613
+ noise_covariance_matrix=self.noise_covariance_matrix,
569
614
  over_sample_size_lp=over_sample_size_lp or self.over_sample_size_lp,
570
615
  over_sample_size_pixelization=over_sample_size_pixelization
571
616
  or self.over_sample_size_pixelization,
572
617
  convolve_over_sample_size_lp=self.convolve_over_sample_size_lp,
573
618
  convolve_over_sample_size_pixelization=self.convolve_over_sample_size_pixelization,
574
619
  check_noise_map=False,
620
+ sparse_operator=self.sparse_operator,
575
621
  )
576
622
 
577
623
  return dataset
@@ -620,9 +666,7 @@ class Imaging(AbstractDataset):
620
666
 
621
667
  if self.psf is not None and self.psf.convolve_over_sample_size > 1:
622
668
  raise exc.DatasetException(
623
- "The sparse linear algebra formalism precomputes PSF products at "
624
- "image resolution and is incompatible with an oversampled PSF "
625
- "(convolve_over_sample_size > 1)."
669
+ _SPARSE_OPERATOR_CONVOLVE_OVER_SAMPLE_SIZE_ERROR
626
670
  )
627
671
 
628
672
  logger.info(
@@ -645,6 +689,8 @@ class Imaging(AbstractDataset):
645
689
  noise_covariance_matrix=self.noise_covariance_matrix,
646
690
  over_sample_size_lp=self.over_sample_size_lp,
647
691
  over_sample_size_pixelization=self.over_sample_size_pixelization,
692
+ convolve_over_sample_size_lp=self.convolve_over_sample_size_lp,
693
+ convolve_over_sample_size_pixelization=self.convolve_over_sample_size_pixelization,
648
694
  check_noise_map=False,
649
695
  sparse_operator=sparse_operator,
650
696
  )
@@ -668,6 +714,11 @@ class Imaging(AbstractDataset):
668
714
  A new `Imaging` dataset with a precomputed Numba-based sparse operator attached,
669
715
  enabling efficient pixelized source reconstruction on CPU hardware.
670
716
  """
717
+ if self.psf is not None and self.psf.convolve_over_sample_size > 1:
718
+ raise exc.DatasetException(
719
+ _SPARSE_OPERATOR_CONVOLVE_OVER_SAMPLE_SIZE_ERROR
720
+ )
721
+
671
722
  try:
672
723
  import numba
673
724
  except ModuleNotFoundError:
@@ -711,6 +762,8 @@ class Imaging(AbstractDataset):
711
762
  noise_covariance_matrix=self.noise_covariance_matrix,
712
763
  over_sample_size_lp=self.over_sample_size_lp,
713
764
  over_sample_size_pixelization=self.over_sample_size_pixelization,
765
+ convolve_over_sample_size_lp=self.convolve_over_sample_size_lp,
766
+ convolve_over_sample_size_pixelization=self.convolve_over_sample_size_pixelization,
714
767
  check_noise_map=False,
715
768
  sparse_operator=sparse_operator,
716
769
  )