diff --git a/GALLERY.md b/GALLERY.md index d412231..a6f5bc9 100644 --- a/GALLERY.md +++ b/GALLERY.md @@ -2,14 +2,15 @@ -Rendered with PyAutoLens `2026.8.17.1` · 72 figures. +Rendered with PyAutoLens `2026.8.17.1` · 85 figures. Every figure below is what the PyAutoLens visualizers (`VisualizerImaging`, `VisualizerInterferometer`, `VisualizerPoint`, `VisualizerWeak`) write to a model-fit's `image/` folder, rendered on this repo's datasets with the true model. See [README.md](README.md) for how to improve one. ## Contents - [cluster](#cluster) - - [visualization](#cluster--visualization) (6 figures) + - [visualization](#cluster--visualization) (17 figures) + - [top level](#cluster--visualization--top-level) - [point_0/](#cluster--visualization--point_0) - [point_1/](#cluster--visualization--point_1) - [group](#group) @@ -38,11 +39,11 @@ Every figure below is what the PyAutoLens visualizers (`VisualizerImaging`, `Vis - [visualization](#multi_galaxy--visualization) (2 figures) - [top level](#multi_galaxy--visualization--top-level) - [point_source_image_chi_squared](#point_source_image_chi_squared) - - [visualization](#point_source_image_chi_squared--visualization) (6 figures) + - [visualization](#point_source_image_chi_squared--visualization) (7 figures) - [top level](#point_source_image_chi_squared--visualization--top-level) - [teaching/](#point_source_image_chi_squared--visualization--teaching) - [point_source_source_chi_squared](#point_source_source_chi_squared) - - [visualization](#point_source_source_chi_squared--visualization) (4 figures) + - [visualization](#point_source_source_chi_squared--visualization) (5 figures) - [top level](#point_source_source_chi_squared--visualization--top-level) - [weak](#weak) - [visualization](#weak--visualization) (2 figures) @@ -52,6 +53,28 @@ Every figure below is what the PyAutoLens visualizers (`VisualizerImaging`, `Vis ### cluster / visualization +#### cluster / visualization / top level + +##### dataset + +![dataset](scripts/cluster/images/visualization/dataset.png) + +##### fit + +![fit](scripts/cluster/images/visualization/fit.png) + +##### fit_image_with_points + +![fit_image_with_points](scripts/cluster/images/visualization/fit_image_with_points.png) + +##### fit_per_image + +![fit_per_image](scripts/cluster/images/visualization/fit_per_image.png) + +##### image_with_points + +![image_with_points](scripts/cluster/images/visualization/image_with_points.png) + #### cluster / visualization / point_0/ ##### dataset @@ -62,6 +85,18 @@ Every figure below is what the PyAutoLens visualizers (`VisualizerImaging`, `Vis ![fit](scripts/cluster/images/visualization/point_0/fit.png) +##### fit_image_with_points + +![fit_image_with_points](scripts/cluster/images/visualization/point_0/fit_image_with_points.png) + +##### fit_per_image + +![fit_per_image](scripts/cluster/images/visualization/point_0/fit_per_image.png) + +##### image_with_points + +![image_with_points](scripts/cluster/images/visualization/point_0/image_with_points.png) + ##### point_solver ![point_solver](scripts/cluster/images/visualization/point_0/point_solver.png) @@ -76,6 +111,18 @@ Every figure below is what the PyAutoLens visualizers (`VisualizerImaging`, `Vis ![fit](scripts/cluster/images/visualization/point_1/fit.png) +##### fit_image_with_points + +![fit_image_with_points](scripts/cluster/images/visualization/point_1/fit_image_with_points.png) + +##### fit_per_image + +![fit_per_image](scripts/cluster/images/visualization/point_1/fit_per_image.png) + +##### image_with_points + +![image_with_points](scripts/cluster/images/visualization/point_1/image_with_points.png) + ##### point_solver ![point_solver](scripts/cluster/images/visualization/point_1/point_solver.png) @@ -364,6 +411,10 @@ Every figure below is what the PyAutoLens visualizers (`VisualizerImaging`, `Vis ![fit_image_with_points](scripts/point_source_image_chi_squared/images/visualization/fit_image_with_points.png) +##### fit_per_image + +![fit_per_image](scripts/point_source_image_chi_squared/images/visualization/fit_per_image.png) + ##### image_with_points ![image_with_points](scripts/point_source_image_chi_squared/images/visualization/image_with_points.png) @@ -396,6 +447,10 @@ Every figure below is what the PyAutoLens visualizers (`VisualizerImaging`, `Vis ![fit_image_with_points](scripts/point_source_source_chi_squared/images/visualization/fit_image_with_points.png) +##### fit_per_image + +![fit_per_image](scripts/point_source_source_chi_squared/images/visualization/fit_per_image.png) + ##### image_with_points ![image_with_points](scripts/point_source_source_chi_squared/images/visualization/image_with_points.png) diff --git a/_viz_cli.py b/_viz_cli.py index eff6e62..f977732 100644 --- a/_viz_cli.py +++ b/_viz_cli.py @@ -99,7 +99,7 @@ def dataset_path(dataset_type: str, instrument: str) -> Path: "type": "cluster", "name": "simple", "simulator": "cluster", - "sentinel": "point_dataset_1.json", + "sentinel": "data.fits", }, "multi_dataset": { "type": "multi_dataset", @@ -178,6 +178,7 @@ def keep_dataset_and_fit( dataset_png: str = "dataset.png", fit_png: str = "fit.png", extra_pngs: tuple[str, ...] = (), + keep_dirs: tuple[str, ...] = (), ) -> list[Path]: """Reduce a visualizer's output folder to exactly ``dataset.png`` + ``fit.png``. @@ -186,7 +187,8 @@ def keep_dataset_and_fit( other file (other PNGs, FITS, CSV, JSON) and any sub-folder is deleted, so the newer domains track only the two figures. ``extra_pngs`` names further figures to keep under their own names (e.g. the point plotter's ``image_with_points.png`` and - ``fit_image_with_points.png``). Raises if any expected figure is missing. + ``fit_image_with_points.png``). ``keep_dirs`` names sub-folders to keep (e.g. the cluster + producer's per-source ``point_/`` folders). Raises if any expected figure is missing. """ image_dir = Path(image_dir) kept = [] @@ -203,6 +205,7 @@ def keep_dataset_and_fit( if not src.is_file(): raise FileNotFoundError(f"expected visualizer output {src} was not written") kept.append(src) + kept += [image_dir / name for name in keep_dirs] for p in sorted(image_dir.iterdir()): if p in kept: continue diff --git a/config/visualize/plots.yaml b/config/visualize/plots.yaml index c1318e9..81b90a8 100644 --- a/config/visualize/plots.yaml +++ b/config/visualize/plots.yaml @@ -60,10 +60,18 @@ fit_interferometer: # Settings for plots of fits to inter fits_dirty_images: true # output dirty_images.fits showing the dirty image, noise-map, model-data, resiual-map, normalized residual map and chi-squared map? point_dataset: # Settings for plots of point source datasets (e.g. PointDatasetPlotter). - subplot_dataset: true # Plot subplot containing all dataset quantities (e.g. the data, noise-map, etc.)? + subplot_dataset: true # Plot the observed positions of the dataset ("Dataset Positions", numbered images, solver extent) (dataset_point.png)? + image_with_points: true # Plot the observed image (if passed to AnalysisPoint) with the observed positions over it (image_with_points.png)? + subplot_dataset_combined: true # Multi-dataset (e.g. cluster) fits: every source's observed positions in one panel, in the top-level image folder (dataset_point.png)? + image_with_points_combined: true # Multi-dataset (e.g. cluster) fits: the observed image with every source's positions over it (image_with_points.png)? fit_point_dataset: # Settings for plots of fits to point source datasets (e.g. FitPointDatasetPlotter). + fit_per_image: true # One row per source of its residual ranking, image-plane zoom and source-plane panel (fit_per_image.png)? + fit_image_with_points: true # The observed image with observed and model positions and critical curves over it (fit_image_with_points.png)? subplot_point_solver: true # PointSolver refinement steps at the best fit (point_solver.png); off by default in the library. + subplot_fit_combined: true # Multi-dataset (e.g. cluster) fits: every source's fit in one panel, curves at each source's redshift (fit.png)? + fit_per_image_combined: true # Multi-dataset (e.g. cluster) fits: fit_per_image.png for every source, ranking range shared across sources? + fit_image_with_points_combined: true # Multi-dataset (e.g. cluster) fits: the observed image with every source's positions, model and curves (fit_image_with_points.png)? weak_dataset: # Settings for plots of weak lensing shear catalogues (e.g. PlotterWeak). subplot_dataset: true # Plot subplot containing all dataset quantities (e.g. the shear field, noise-map, etc.)? diff --git a/dataset/cluster/simple/data.fits b/dataset/cluster/simple/data.fits new file mode 100644 index 0000000..598f286 Binary files /dev/null and b/dataset/cluster/simple/data.fits differ diff --git a/gallery/viz_manifest.yaml b/gallery/viz_manifest.yaml index eb0a923..5ad4ded 100644 --- a/gallery/viz_manifest.yaml +++ b/gallery/viz_manifest.yaml @@ -8,44 +8,110 @@ rendered_with: autogalaxy: 2026.8.17.1 autoarray: 2026.8.17.1 autofit: 2026.8.17.1 -figure_count: 72 +figure_count: 85 figures: +- file: scripts/cluster/images/visualization/dataset.png + producer: scripts/cluster/visualization.py + domain: cluster + source: '' + bytes: 46044 + sha256: 33057e5dfca33bc3680c6c97be5eb49681b27fc6571a6511f1ed1cf626aea5dc +- file: scripts/cluster/images/visualization/fit.png + producer: scripts/cluster/visualization.py + domain: cluster + source: '' + bytes: 93568 + sha256: ee1c998a1616b822ea2f73c769dc2961a6a3ea64f319b96027dc656a6e4d953d +- file: scripts/cluster/images/visualization/fit_image_with_points.png + producer: scripts/cluster/visualization.py + domain: cluster + source: '' + bytes: 1583787 + sha256: fbe068f345d919dc2f221e1829d43dc25abea2e6e3464dcd9c14d44c507bfc2a +- file: scripts/cluster/images/visualization/fit_per_image.png + producer: scripts/cluster/visualization.py + domain: cluster + source: '' + bytes: 298219 + sha256: 208e1e6bc10d4f23f2c39c856e5ca4a038070d7651c9a8c16a6b596727543e8d +- file: scripts/cluster/images/visualization/image_with_points.png + producer: scripts/cluster/visualization.py + domain: cluster + source: '' + bytes: 1585001 + sha256: 43cf4ef485735a9166f7531a499c9242322034c7f54c031eb96ebcef8ab6fb8c - file: scripts/cluster/images/visualization/point_0/dataset.png producer: scripts/cluster/visualization.py domain: cluster source: point_0 - bytes: 39187 - sha256: 65b2b421786401373253a058a997f953beee6818b5bd492e93a69e4e86f046b0 + bytes: 42773 + sha256: 2993359569e579c8ff8b422e28ce2abd1a6c6175c4477410caffa1ab18b22d89 - file: scripts/cluster/images/visualization/point_0/fit.png producer: scripts/cluster/visualization.py domain: cluster source: point_0 - bytes: 155979 - sha256: 194a96de28638648ea81b47e0733fdd973f98abc69db1c1bac217ff831c7dc69 + bytes: 58399 + sha256: 68d8da40dfea98f35e9047b7a1d2f2655b6cbef569fac2cc013e6df1376ac903 +- file: scripts/cluster/images/visualization/point_0/fit_image_with_points.png + producer: scripts/cluster/visualization.py + domain: cluster + source: point_0 + bytes: 1597458 + sha256: 4e934c2bc9cb8554d36c6c0e1a26a132c4e18ffea3808f430598909f75189f83 +- file: scripts/cluster/images/visualization/point_0/fit_per_image.png + producer: scripts/cluster/visualization.py + domain: cluster + source: point_0 + bytes: 150681 + sha256: 361f5948ebfb303b12a8ae808fc01f1fa92e3df55c51513cc625bcd5882ca82f +- file: scripts/cluster/images/visualization/point_0/image_with_points.png + producer: scripts/cluster/visualization.py + domain: cluster + source: point_0 + bytes: 1594350 + sha256: f11609f6c0faa6a5ed154ae8b80e1057b36701e2dfb504890792cdb540f161b3 - file: scripts/cluster/images/visualization/point_0/point_solver.png producer: scripts/cluster/visualization.py domain: cluster source: point_0 - bytes: 646052 - sha256: b0f21b073ab19c91c629504940ecd8fb631dda85107edabfd6345c60e7fbc1b4 + bytes: 640670 + sha256: 6d04d62929fce315d9557e80de3445c8b623e239440aa8520cb43b127f1591b6 - file: scripts/cluster/images/visualization/point_1/dataset.png producer: scripts/cluster/visualization.py domain: cluster source: point_1 - bytes: 36831 - sha256: 41adea0870d20e15d7b52c040d364f74f81fa2952119e25c4dd52d12032a470f + bytes: 38471 + sha256: bec83f0aa4312eb0404f92873aa8aaced4bf011d207901b821e296d64b84d0f7 - file: scripts/cluster/images/visualization/point_1/fit.png producer: scripts/cluster/visualization.py domain: cluster source: point_1 - bytes: 194829 - sha256: 62f2ac2dede915f85571cd8d1bbd30be7e27450e94486731ff6c0b9571c026e6 + bytes: 69261 + sha256: 2bc4b5d6e683d5c4410ab319b8f71e199533d300a6c95ac8010f682b139c31a9 +- file: scripts/cluster/images/visualization/point_1/fit_image_with_points.png + producer: scripts/cluster/visualization.py + domain: cluster + source: point_1 + bytes: 1594036 + sha256: 2205d4d6b1c0f13d1ab8801dfbc917badd673d508e1968ddf37398230299b04a +- file: scripts/cluster/images/visualization/point_1/fit_per_image.png + producer: scripts/cluster/visualization.py + domain: cluster + source: point_1 + bytes: 157772 + sha256: fd1f9bedc956b26a6021797b9064f7c08da8cdd76143ce73c687aa3de1486de7 +- file: scripts/cluster/images/visualization/point_1/image_with_points.png + producer: scripts/cluster/visualization.py + domain: cluster + source: point_1 + bytes: 1594402 + sha256: 53bf0a3e7a8ae764bde2db7feda75875a6be43f0ca20465ec9d1bf34a98611c2 - file: scripts/cluster/images/visualization/point_1/point_solver.png producer: scripts/cluster/visualization.py domain: cluster source: point_1 - bytes: 631672 - sha256: 357d5dff2da880f3bd0908dba09624d2ee66d4211548f27dd79807452b153299 + bytes: 625185 + sha256: 79a8a96eead5eb2399ac70140ab5b1276df739491fceda63d49160df6815652c - file: scripts/group/images/visualization/dataset.png producer: scripts/group/visualization.py domain: group @@ -374,32 +440,38 @@ figures: producer: scripts/point_source_image_chi_squared/visualization.py domain: point_source_image_chi_squared source: '' - bytes: 38680 - sha256: ad0e575bc1d7aded073a16481b3acdfa3e964364acb01dd3d98d9663e7b9a534 + bytes: 41467 + sha256: 1b2cd9eaf2993c88d0d00e0ab5c4c8ee0341eae8f13a090e963a5fe87cb8f56f - file: scripts/point_source_image_chi_squared/images/visualization/fit.png producer: scripts/point_source_image_chi_squared/visualization.py domain: point_source_image_chi_squared source: '' - bytes: 138722 - sha256: 482203f4614a3505f2f486e3530f88278c715b364f2be2be3d71d7f1497435a1 + bytes: 69132 + sha256: ded481e0b14a8177b371678ce5de58c98be2a6262c60e57630f9d554ace80091 - file: scripts/point_source_image_chi_squared/images/visualization/fit_image_with_points.png producer: scripts/point_source_image_chi_squared/visualization.py domain: point_source_image_chi_squared source: '' - bytes: 90241 - sha256: 598066fe921e3100582c8d3007a1fdf8ee54665c73a953b932fa2aed0d0bd986 + bytes: 97161 + sha256: eb2533b6c01023877e5dbdd9485dcbc7e4444bd127c25dfe5bbfe4ccea4a3d10 +- file: scripts/point_source_image_chi_squared/images/visualization/fit_per_image.png + producer: scripts/point_source_image_chi_squared/visualization.py + domain: point_source_image_chi_squared + source: '' + bytes: 162798 + sha256: 38cd9c0ecc77ba0d8ece792aacd938cec84a61ed65a6ea0089d6511b43cd6156 - file: scripts/point_source_image_chi_squared/images/visualization/image_with_points.png producer: scripts/point_source_image_chi_squared/visualization.py domain: point_source_image_chi_squared source: '' - bytes: 66518 - sha256: 2653419882e5f55d2afe24b067e8d5c9865081aee51517dc05520a12d1787468 + bytes: 64461 + sha256: 34ba107cfea58ce794e77ce633b4b10720fa90c125c696b9e4f6ff10aee380f8 - file: scripts/point_source_image_chi_squared/images/visualization/point_solver.png producer: scripts/point_source_image_chi_squared/visualization.py domain: point_source_image_chi_squared source: '' - bytes: 809716 - sha256: 92252350649f9d7a8698a775afcbf02cc0bc0291f842b5365f7ecea0fb4ec25a + bytes: 809232 + sha256: b6a8909ff738ac83d6344d23bba9828176a0a80205aaf12c46a11b300189c70d - file: scripts/point_source_image_chi_squared/images/visualization/teaching/point_solver.png producer: scripts/point_source_image_chi_squared/visualization.py domain: point_source_image_chi_squared @@ -410,26 +482,32 @@ figures: producer: scripts/point_source_source_chi_squared/visualization.py domain: point_source_source_chi_squared source: '' - bytes: 38680 - sha256: ad0e575bc1d7aded073a16481b3acdfa3e964364acb01dd3d98d9663e7b9a534 + bytes: 41467 + sha256: 1b2cd9eaf2993c88d0d00e0ab5c4c8ee0341eae8f13a090e963a5fe87cb8f56f - file: scripts/point_source_source_chi_squared/images/visualization/fit.png producer: scripts/point_source_source_chi_squared/visualization.py domain: point_source_source_chi_squared source: '' - bytes: 196069 - sha256: 766245d8083139d16ad5ad8228351eca4e216b2bae4f269c22954845b86a4bbf + bytes: 65064 + sha256: 11544045f42623fe7a87084c7a3fa886649388705226fec73931dab820550f11 - file: scripts/point_source_source_chi_squared/images/visualization/fit_image_with_points.png producer: scripts/point_source_source_chi_squared/visualization.py domain: point_source_source_chi_squared source: '' - bytes: 87781 - sha256: c2ff686539ea88d8b5d07d15d8e8cc77e4ee64646333ed6f20cbcd5785f41717 + bytes: 97106 + sha256: f9f5fdebf0f3620dc4b8cec098953fc59ecb98a9fa9437694666b0658134d9a3 +- file: scripts/point_source_source_chi_squared/images/visualization/fit_per_image.png + producer: scripts/point_source_source_chi_squared/visualization.py + domain: point_source_source_chi_squared + source: '' + bytes: 201841 + sha256: f6c1bbb08bbdf91707e30701be4908b6b7b19497518598f02393c465f2c0d4b2 - file: scripts/point_source_source_chi_squared/images/visualization/image_with_points.png producer: scripts/point_source_source_chi_squared/visualization.py domain: point_source_source_chi_squared source: '' - bytes: 66518 - sha256: 2653419882e5f55d2afe24b067e8d5c9865081aee51517dc05520a12d1787468 + bytes: 64461 + sha256: 34ba107cfea58ce794e77ce633b4b10720fa90c125c696b9e4f6ff10aee380f8 - file: scripts/weak/images/visualization/dataset.png producer: scripts/weak/visualization.py domain: weak diff --git a/scripts/cluster/images/visualization/dataset.png b/scripts/cluster/images/visualization/dataset.png new file mode 100644 index 0000000..bcd016e Binary files /dev/null and b/scripts/cluster/images/visualization/dataset.png differ diff --git a/scripts/cluster/images/visualization/fit.png b/scripts/cluster/images/visualization/fit.png new file mode 100644 index 0000000..dabc8fa Binary files /dev/null and b/scripts/cluster/images/visualization/fit.png differ diff --git a/scripts/cluster/images/visualization/fit_image_with_points.png b/scripts/cluster/images/visualization/fit_image_with_points.png new file mode 100644 index 0000000..992d59b Binary files /dev/null and b/scripts/cluster/images/visualization/fit_image_with_points.png differ diff --git a/scripts/cluster/images/visualization/fit_per_image.png b/scripts/cluster/images/visualization/fit_per_image.png new file mode 100644 index 0000000..420c693 Binary files /dev/null and b/scripts/cluster/images/visualization/fit_per_image.png differ diff --git a/scripts/cluster/images/visualization/image_with_points.png b/scripts/cluster/images/visualization/image_with_points.png new file mode 100644 index 0000000..63460d8 Binary files /dev/null and b/scripts/cluster/images/visualization/image_with_points.png differ diff --git a/scripts/cluster/images/visualization/point_0/dataset.png b/scripts/cluster/images/visualization/point_0/dataset.png index 4fe5e66..e53b398 100644 Binary files a/scripts/cluster/images/visualization/point_0/dataset.png and b/scripts/cluster/images/visualization/point_0/dataset.png differ diff --git a/scripts/cluster/images/visualization/point_0/fit.png b/scripts/cluster/images/visualization/point_0/fit.png index 5b98a78..45b5752 100644 Binary files a/scripts/cluster/images/visualization/point_0/fit.png and b/scripts/cluster/images/visualization/point_0/fit.png differ diff --git a/scripts/cluster/images/visualization/point_0/fit_image_with_points.png b/scripts/cluster/images/visualization/point_0/fit_image_with_points.png new file mode 100644 index 0000000..857e8b2 Binary files /dev/null and b/scripts/cluster/images/visualization/point_0/fit_image_with_points.png differ diff --git a/scripts/cluster/images/visualization/point_0/fit_per_image.png b/scripts/cluster/images/visualization/point_0/fit_per_image.png new file mode 100644 index 0000000..e46baeb Binary files /dev/null and b/scripts/cluster/images/visualization/point_0/fit_per_image.png differ diff --git a/scripts/cluster/images/visualization/point_0/image_with_points.png b/scripts/cluster/images/visualization/point_0/image_with_points.png new file mode 100644 index 0000000..2fec459 Binary files /dev/null and b/scripts/cluster/images/visualization/point_0/image_with_points.png differ diff --git a/scripts/cluster/images/visualization/point_0/point_solver.png b/scripts/cluster/images/visualization/point_0/point_solver.png index 74fbb8e..4f195da 100644 Binary files a/scripts/cluster/images/visualization/point_0/point_solver.png and b/scripts/cluster/images/visualization/point_0/point_solver.png differ diff --git a/scripts/cluster/images/visualization/point_1/dataset.png b/scripts/cluster/images/visualization/point_1/dataset.png index d3c60c5..db1b922 100644 Binary files a/scripts/cluster/images/visualization/point_1/dataset.png and b/scripts/cluster/images/visualization/point_1/dataset.png differ diff --git a/scripts/cluster/images/visualization/point_1/fit.png b/scripts/cluster/images/visualization/point_1/fit.png index 90d7791..ccdb793 100644 Binary files a/scripts/cluster/images/visualization/point_1/fit.png and b/scripts/cluster/images/visualization/point_1/fit.png differ diff --git a/scripts/cluster/images/visualization/point_1/fit_image_with_points.png b/scripts/cluster/images/visualization/point_1/fit_image_with_points.png new file mode 100644 index 0000000..4e0ec90 Binary files /dev/null and b/scripts/cluster/images/visualization/point_1/fit_image_with_points.png differ diff --git a/scripts/cluster/images/visualization/point_1/fit_per_image.png b/scripts/cluster/images/visualization/point_1/fit_per_image.png new file mode 100644 index 0000000..2b0ddf7 Binary files /dev/null and b/scripts/cluster/images/visualization/point_1/fit_per_image.png differ diff --git a/scripts/cluster/images/visualization/point_1/image_with_points.png b/scripts/cluster/images/visualization/point_1/image_with_points.png new file mode 100644 index 0000000..1c9d482 Binary files /dev/null and b/scripts/cluster/images/visualization/point_1/image_with_points.png differ diff --git a/scripts/cluster/images/visualization/point_1/point_solver.png b/scripts/cluster/images/visualization/point_1/point_solver.png index fd996c2..85f8b60 100644 Binary files a/scripts/cluster/images/visualization/point_1/point_solver.png and b/scripts/cluster/images/visualization/point_1/point_solver.png differ diff --git a/scripts/cluster/visualization.py b/scripts/cluster/visualization.py index fbbfdd4..517786c 100644 --- a/scripts/cluster/visualization.py +++ b/scripts/cluster/visualization.py @@ -2,37 +2,36 @@ Visualization: Cluster ====================== -Renders the figures ``VisualizerPoint`` writes for each point-source dataset of a -multi-plane cluster fit (two point sources at z=1.0 and z=2.0 behind a cluster lens), so the -latest version of each lives in git (``GALLERY.md``). A cluster model-fit has one -``AnalysisPoint`` per point-source dataset (combined in a factor graph), each visualized -separately, so this producer calls the visualizer once per dataset. The figures are the -generic point-source plots — bespoke cluster figures are a follow-up. +Renders the figures ``VisualizerPoint`` writes during a cluster model-fit (two point sources at +z=1.0 and z=2.0 behind a multi-plane cluster lens), so the latest version of each lives in git +(``GALLERY.md``). A cluster model-fit has one ``AnalysisPoint`` per point-source dataset, +combined in a factor graph: each dataset's own figures are written to its own folder, and the +figures of every source together (where all sources are visible) to the top-level folder. Output tree (wiped at the start of every run):: scripts/cluster/images/visualization/ - point_0/dataset.png, point_0/fit.png <- PlotterPoint.dataset_point, PlotterPoint.fit_point - point_0/point_solver.png <- PlotterPoint.point_solver (the model's real - multi-plane PointSolver refining onto this - source's images, steps 0, 1, 2 and final) - point_1/dataset.png, point_1/fit.png, point_1/point_solver.png - -**Plotter, not Visualizer.** ``VisualizerPoint.visualize`` also renders the tracer and galaxy -figures this repo does not track, so this producer calls the same ``PlotterPoint`` methods the -visualizer calls (``dataset_point(solver=...)`` in ``visualize_before_fit``; -``fit_point(quick_update=True)`` and ``point_solver`` in ``visualize``), writing the figures the -visualizer would. The "Fit Positions" and point-solver panels draw the tracer's critical curves, -computed once per dataset (as the visualizer does) on a 100x100 grid covering the solver grid: for -this 15-galaxy multi-plane lens that costs ~2 min per dataset. The "Fit Source Plane" panel of -``fit.png`` draws the caustics of the point's own plane (``point_0`` is at z=1, in front of the -last plane), computed separately for a point not in the last plane. - -The point plotter writes ``dataset_point.png`` (renamed to ``dataset.png``); every other file -the visualizer writes is deleted. - -Dataset: ``dataset/cluster/simple`` (``point_0``: 5 images, ``point_1``: 2 images, 5 mas noise), -from ``scripts/misc/simulators/cluster.py``. The model is that simulator's TRUE model + dataset.png <- VisualizerPoint.visualize_before_fit_combined: + "Dataset Positions" of every source (dataset_point.png) + image_with_points.png <- every source's positions over the cluster image + fit.png <- VisualizerPoint.visualize_combined: "Fit Positions" of + every source, each source's critical curves at its own z + fit_per_image.png <- one row per source: residual ranking (range shared by + both sources) / image-plane zoom / source plane + fit_image_with_points.png <- every source's positions and curves over the image + point_0/ point_1/ <- each dataset's own figures (visualize_before_fit + + visualize): dataset.png, image_with_points.png, fit.png, + fit_per_image.png, fit_image_with_points.png and + point_solver.png (the model's real multi-plane PointSolver + refining onto this source's images) + +The per-dataset ``visualize`` also writes the tracer and galaxy figures, which this repo does +not track: they (and every other untracked file) are deleted, and ``dataset_point.png`` is +renamed ``dataset.png``. + +Dataset: ``dataset/cluster/simple`` (``point_0``: 5 images, ``point_1``: 2 images, 5 mas noise, +and ``data.fits``: the cluster image, visualization only), from +``scripts/misc/simulators/cluster.py``. The model is that simulator's TRUE model (``true_models/cluster.py``), fitted with the source-plane chi-squared (``FitPositionsSource``) the workspace cluster example uses, with free-centre point sources. @@ -68,9 +67,7 @@ def _repo_root() -> Path: import autofit as af import autolens as al -from autolens.imaging.plot.fit_imaging_plots import _compute_critical_curve_lines -from autolens.lens.plot.critical_curves import critical_curve_grid_from -from autolens.point.model.plotter import PlotterPoint +from autolens.point.model.visualizer import VisualizerPoint from _viz_cli import ensure_dataset, keep_dataset_and_fit from true_models import cluster as tm @@ -96,6 +93,16 @@ def _repo_root() -> Path: grid=tm.solver_grid(), pixel_scale_precision=0.001, magnification_threshold=0.1 ) +""" +__Cluster Image__ + +Visualization only: it is passed to every ``AnalysisPoint`` for the image-with-points figures and +never enters the point-source likelihood. +""" +image = al.Array2D.from_fits( + file_path=dataset_path / "data.fits", hdu=0, pixel_scales=tm.IMAGE_PIXEL_SCALES +) + """ __Paths__ """ @@ -107,18 +114,22 @@ def _repo_root() -> Path: scratch_root = REPO_ROOT / "output" / "visualization" / "cluster" / STEM if scratch_root.exists(): shutil.rmtree(scratch_root) +scratch_root.mkdir(parents=True) """ __Per Point-Source Dataset__ """ +analyses = [] for i in range(len(tm.SOURCE_REDSHIFTS)): dataset = al.from_json(file_path=dataset_path / f"point_dataset_{i}.json") analysis = al.AnalysisPoint( dataset=dataset, solver=solver, + image=image, fit_positions_cls=al.FitPositionsSource, use_jax=False, ) + analyses.append(analysis) point_path = image_path / dataset.name point_path.mkdir(parents=True) @@ -127,25 +138,49 @@ def _repo_root() -> Path: paths = SimpleNamespace(image_path=point_path, output_path=scratch) t0 = time.perf_counter() - plotter = PlotterPoint(image_path=paths.image_path, title_prefix=analysis.title_prefix) - plotter.dataset_point(dataset=analysis.dataset, solver=analysis.solver) - fit = analysis.fit_for_visualization(instance=instance) - ip_lines, ip_colors, sp_lines, sp_colors = _compute_critical_curve_lines( - fit.tracer, critical_curve_grid_from(dataset=fit.dataset, solver=solver) - ) - plotter.fit_point( - fit=fit, - quick_update=True, - image_plane_lines=ip_lines if ip_lines is not None else [], - image_plane_line_colors=ip_colors if ip_lines is not None else [], - source_plane_lines=sp_lines, - source_plane_line_colors=sp_colors, + VisualizerPoint.visualize_before_fit(analysis=analysis, paths=paths, model=model) + VisualizerPoint.visualize( + analysis=analysis, + paths=paths, + instance=instance, + during_analysis=False, + quick_update=False, ) - plotter.point_solver(fit=fit, image_plane_lines=ip_lines if ip_lines is not None else []) keep_dataset_and_fit( - point_path, dataset_png="dataset_point.png", extra_pngs=("point_solver.png",) + point_path, + dataset_png="dataset_point.png", + extra_pngs=( + "fit_per_image.png", + "image_with_points.png", + "fit_image_with_points.png", + "point_solver.png", + ), ) print(f"visualize [{dataset.name}]: {time.perf_counter() - t0:.1f}s") +""" +__All Sources__ + +The figures of every source together, as ``VisualizerPoint`` writes them to the top-level image +folder of a factor-graph fit. +""" +t0 = time.perf_counter() +paths = SimpleNamespace(image_path=image_path, output_path=scratch_root) +VisualizerPoint.visualize_before_fit_combined(analyses=analyses, paths=paths, model=model) +VisualizerPoint.visualize_combined( + analyses=analyses, + paths=paths, + instance=[instance] * len(analyses), + during_analysis=False, + quick_update=False, +) +keep_dataset_and_fit( + image_path, + dataset_png="dataset_point.png", + extra_pngs=("fit_per_image.png", "image_with_points.png", "fit_image_with_points.png"), + keep_dirs=tuple(analysis.dataset.name for analysis in analyses), +) +print(f"visualize [all sources]: {time.perf_counter() - t0:.1f}s") + n_png = len(list(image_path.rglob("*.png"))) print(f"Wrote {n_png} PNGs under {image_path.relative_to(REPO_ROOT)}") diff --git a/scripts/misc/simulators/cluster.py b/scripts/misc/simulators/cluster.py index e190a10..3a756a7 100644 --- a/scripts/misc/simulators/cluster.py +++ b/scripts/misc/simulators/cluster.py @@ -6,12 +6,19 @@ point sources at z=1.0 (``point_0``) and z=2.0 (``point_1``) behind a cluster lens (BCG, satellite, ten scaling-relation members and an NFW host halo) — and writes ``point_dataset_0.json``, ``point_dataset_1.json`` and ``tracer.json`` into -``dataset/cluster/simple/``. +``dataset/cluster/simple/``, plus ``data.fits``: a CCD image of the cluster (lens and member light, +the two lensed sources' arcs) over the solver extent, which the producer passes to +``AnalysisPoint(image=...)`` so the cluster ``image_with_points.png`` / +``fit_image_with_points.png`` render. The image is visualization only: it never enters the +point-source likelihood. Adapted from ``autolens_workspace/scripts/cluster/simulator.py``: same galaxies and 5 mas position noise (the workspace adds none; seeded here), solved with the NumPy ``PointSolver`` on -a coarser 400x400 @ 0.2" grid instead of the JIT-compiled 800x800 @ 0.1" one. The workspace's -1000x1000 imaging, CSV tables and PNG previews are not written (the producer fits positions). +a coarser 400x400 @ 0.2" grid instead of the JIT-compiled 800x800 @ 0.1" one. The image uses the +workspace's imaging settings (Gaussian PSF of one pixel, 300 s exposure, sky 0.1, Poisson noise, +seeded) on that same 400x400 @ 0.2" grid instead of 1000x1000 @ 0.1", so the tracked FITS stays +small; only ``data.fits`` is written (the figures need no noise-map or PSF). CSV tables and PNG +previews are not written. Usage ----- @@ -40,6 +47,7 @@ def _repo_root() -> _Path: def simulate(output_root: Path | None = None) -> Path: import autolens as al + import autolens.plot as aplt import numpy as np from true_models import cluster as tm @@ -72,6 +80,23 @@ def simulate(output_root: Path | None = None) -> Path: print(f" point_{i} (z={z}): {len(positions)} images") al.output_to_json(obj=tracer, file_path=dataset_path / "tracer.json") + + grid = al.Grid2D.uniform(shape_native=tm.IMAGE_SHAPE_NATIVE, pixel_scales=tm.IMAGE_PIXEL_SCALES) + psf = al.Convolver.from_gaussian( + shape_native=(11, 11), + sigma=tm.IMAGE_PIXEL_SCALES, + pixel_scales=tm.IMAGE_PIXEL_SCALES, + ) + simulator = al.SimulatorImaging( + exposure_time=300.0, + psf=psf, + background_sky_level=0.1, + add_poisson_noise_to_data=True, + noise_seed=1, + ) + imaging = simulator.via_tracer_from(tracer=tracer, grid=grid) + aplt.fits_imaging(dataset=imaging, data_path=dataset_path / "data.fits", overwrite=True) + print(f' data.fits: {tm.IMAGE_SHAPE_NATIVE} @ {tm.IMAGE_PIXEL_SCALES}"/px') print(f" wrote {dataset_path}") return dataset_path diff --git a/scripts/point_source_image_chi_squared/images/visualization/dataset.png b/scripts/point_source_image_chi_squared/images/visualization/dataset.png index e2138b9..0e2e226 100644 Binary files a/scripts/point_source_image_chi_squared/images/visualization/dataset.png and b/scripts/point_source_image_chi_squared/images/visualization/dataset.png differ diff --git a/scripts/point_source_image_chi_squared/images/visualization/fit.png b/scripts/point_source_image_chi_squared/images/visualization/fit.png index 49e965c..c3f4eff 100644 Binary files a/scripts/point_source_image_chi_squared/images/visualization/fit.png and b/scripts/point_source_image_chi_squared/images/visualization/fit.png differ diff --git a/scripts/point_source_image_chi_squared/images/visualization/fit_image_with_points.png b/scripts/point_source_image_chi_squared/images/visualization/fit_image_with_points.png index afb06c2..1933612 100644 Binary files a/scripts/point_source_image_chi_squared/images/visualization/fit_image_with_points.png and b/scripts/point_source_image_chi_squared/images/visualization/fit_image_with_points.png differ diff --git a/scripts/point_source_image_chi_squared/images/visualization/fit_per_image.png b/scripts/point_source_image_chi_squared/images/visualization/fit_per_image.png new file mode 100644 index 0000000..40e9b6e Binary files /dev/null and b/scripts/point_source_image_chi_squared/images/visualization/fit_per_image.png differ diff --git a/scripts/point_source_image_chi_squared/images/visualization/image_with_points.png b/scripts/point_source_image_chi_squared/images/visualization/image_with_points.png index 28becf5..a13454d 100644 Binary files a/scripts/point_source_image_chi_squared/images/visualization/image_with_points.png and b/scripts/point_source_image_chi_squared/images/visualization/image_with_points.png differ diff --git a/scripts/point_source_image_chi_squared/images/visualization/point_solver.png b/scripts/point_source_image_chi_squared/images/visualization/point_solver.png index 4a07487..19b043b 100644 Binary files a/scripts/point_source_image_chi_squared/images/visualization/point_solver.png and b/scripts/point_source_image_chi_squared/images/visualization/point_solver.png differ diff --git a/scripts/point_source_image_chi_squared/visualization.py b/scripts/point_source_image_chi_squared/visualization.py index e0b9342..2184445 100644 --- a/scripts/point_source_image_chi_squared/visualization.py +++ b/scripts/point_source_image_chi_squared/visualization.py @@ -12,8 +12,11 @@ scripts/point_source_image_chi_squared/images/visualization/ dataset.png <- visualize_before_fit (the plotter writes dataset_point.png; renamed) - fit.png <- visualize: Fit Positions + Fit Source Plane (traced positions for - context only: the image-plane chi-squared has no source-plane noise) + fit.png <- visualize: Fit Positions (observed, model at its true position, + true-length residual lines, critical curves, mass centres) + fit_per_image.png <- visualize: residual ranking (Delta/sigma) / image-plane zoom / + Fit Source Plane (traced positions for context only: the image-plane + chi-squared has no source-plane noise) image_with_points.png <- visualize_before_fit: the observed positions over ``data.fits`` (dataset only, no model) fit_image_with_points.png <- visualize: the observed positions, the model's @@ -145,6 +148,7 @@ def _repo_root() -> Path: image_path, dataset_png="dataset_point.png", extra_pngs=( + "fit_per_image.png", "image_with_points.png", "fit_image_with_points.png", "point_solver.png", diff --git a/scripts/point_source_source_chi_squared/images/visualization/dataset.png b/scripts/point_source_source_chi_squared/images/visualization/dataset.png index e2138b9..0e2e226 100644 Binary files a/scripts/point_source_source_chi_squared/images/visualization/dataset.png and b/scripts/point_source_source_chi_squared/images/visualization/dataset.png differ diff --git a/scripts/point_source_source_chi_squared/images/visualization/fit.png b/scripts/point_source_source_chi_squared/images/visualization/fit.png index 08dbc48..85c3fba 100644 Binary files a/scripts/point_source_source_chi_squared/images/visualization/fit.png and b/scripts/point_source_source_chi_squared/images/visualization/fit.png differ diff --git a/scripts/point_source_source_chi_squared/images/visualization/fit_image_with_points.png b/scripts/point_source_source_chi_squared/images/visualization/fit_image_with_points.png index afb95e6..b62d3eb 100644 Binary files a/scripts/point_source_source_chi_squared/images/visualization/fit_image_with_points.png and b/scripts/point_source_source_chi_squared/images/visualization/fit_image_with_points.png differ diff --git a/scripts/point_source_source_chi_squared/images/visualization/fit_per_image.png b/scripts/point_source_source_chi_squared/images/visualization/fit_per_image.png new file mode 100644 index 0000000..af9ee0d Binary files /dev/null and b/scripts/point_source_source_chi_squared/images/visualization/fit_per_image.png differ diff --git a/scripts/point_source_source_chi_squared/images/visualization/image_with_points.png b/scripts/point_source_source_chi_squared/images/visualization/image_with_points.png index 28becf5..a13454d 100644 Binary files a/scripts/point_source_source_chi_squared/images/visualization/image_with_points.png and b/scripts/point_source_source_chi_squared/images/visualization/image_with_points.png differ diff --git a/scripts/point_source_source_chi_squared/visualization.py b/scripts/point_source_source_chi_squared/visualization.py index 6cfbc18..e55fb50 100644 --- a/scripts/point_source_source_chi_squared/visualization.py +++ b/scripts/point_source_source_chi_squared/visualization.py @@ -2,25 +2,27 @@ Visualization: Point Source (Source-Plane Chi-Squared) ====================================================== -Renders the two figures ``VisualizerPoint`` writes for a point-source fit that uses the +Renders the figures ``VisualizerPoint`` writes for a point-source fit that uses the source-plane chi-squared (``FitPositionsSource``: the observed positions are ray-traced to the -source plane and compared with the point source's centre, magnification-weighted), so the +source plane and compared with the point source's centre, jacobian-weighted by default), so the latest version of each lives in git (``GALLERY.md``). Output tree (wiped at the start of every run):: scripts/point_source_source_chi_squared/images/visualization/ dataset.png <- visualize_before_fit (the plotter writes dataset_point.png; renamed) - fit.png <- visualize(quick_update=True): Fit Positions + Fit Source Plane (the - traced positions with the sigma/|mu| circles the magnification - chi-squared uses) + fit.png <- visualize: Fit Positions (observed positions and the critical + curves; a source-plane fit has no image-plane model positions) + fit_per_image.png <- visualize: residual ranking by the fit's own per-image + source-plane chi / image-plane zoom / Fit Source Plane (the traced + positions with the A.sigma ellipses the jacobian chi-squared uses) image_with_points.png <- visualize_before_fit: the observed positions over ``data.fits`` (dataset only, no model) - fit_image_with_points.png <- visualize(quick_update=True): the observed + fit_image_with_points.png <- visualize: the observed positions and critical curves over ``data.fits`` (a source-plane fit has no image-plane model positions) -Every other file the visualizer writes is deleted: this domain tracks only these four +Every other file the visualizer writes is deleted: this domain tracks only these five figures. Dataset: ``dataset/point_source/simple`` (four image-plane positions, 5 mas noise; shared by @@ -132,12 +134,12 @@ def _repo_root() -> Path: paths=paths, instance=model.instance_from_prior_medians(), during_analysis=False, - quick_update=True, + quick_update=False, ) keep_dataset_and_fit( image_path, dataset_png="dataset_point.png", - extra_pngs=("image_with_points.png", "fit_image_with_points.png"), + extra_pngs=("fit_per_image.png", "image_with_points.png", "fit_image_with_points.png"), ) print(f"visualize: {time.perf_counter() - t0:.1f}s") print( diff --git a/true_models/cluster.py b/true_models/cluster.py index 6761420..7212379 100644 --- a/true_models/cluster.py +++ b/true_models/cluster.py @@ -14,6 +14,10 @@ SOURCE_CENTRES = [(0.3, 0.5), (-0.8, 1.2)] POSITION_NOISE = 0.005 +# The cluster CCD image (visualization only): the solver grid's extent and sampling. +IMAGE_SHAPE_NATIVE = (400, 400) +IMAGE_PIXEL_SCALES = 0.2 + MAIN_LENS_CENTRES = [(0.0, 0.0), (10.0, 8.0)] MAIN_LENS_DPIE = [(0.0, 20.0, 330.0), (0.0, 12.0, 210.0)] # (r_core, r_cut, sigma) MAIN_LENS_SERSIC = [(1.5, 3.0, 4.0), (0.8, 1.5, 3.5)] # (intensity, effective_radius, n)