Skip to content

Commit 9be4348

Browse files
authored
Merge pull request #68 from PyAutoLabs/claude/howtolens-tutorial-restructure-f19y9d
Restructure the lecture series: point sources + formalism lectures, chaining into chapter 2, pixelizations as chapter 3, new Scaling Up Lensing chapter 4
2 parents 4ff3135 + 208af74 commit 9be4348

238 files changed

Lines changed: 20623 additions & 4221 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

AGENTS.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@ canonical, agent-agnostic instructions for this repo.
88
## Repository Structure
99

1010
- `scripts/` — Runnable Python tutorial scripts:
11-
- `chapter_1_introduction/` — Grids, profiles, galaxies, ray-tracing, data, fitting
12-
- `chapter_2_lens_modeling/` — Non-linear searches, Bayesian inference, lens modeling
13-
- `chapter_3_search_chaining/` — Search chaining, prior passing, automated pipelines
14-
- `chapter_4_pixelizations/` — Pixelized source reconstruction, inversions, regularization
11+
- `chapter_1_introduction/` — Grids, profiles, galaxies, ray-tracing, point sources, the lensing
12+
formalism, data, fitting
13+
- `chapter_2_lens_modeling/` — Non-linear searches, Bayesian inference, lens modeling, search
14+
chaining, prior passing, automated pipelines
15+
- `chapter_3_pixelizations/` — Pixelized source reconstruction, inversions, regularization, the
16+
Bayesian formalism
17+
- `chapter_4_scaling_up_lensing/` — Extra galaxies, multi-galaxy lenses, scaling relations, group
18+
and cluster scales, weak lensing
1519
- `chapter_optional/` — Alternative searches and advanced topics
1620
- `simulator/` — Simulator scripts that generate the tutorial datasets at runtime
1721
- `notebooks/` — Jupyter versions, generated from `scripts/` (do not edit directly)

README.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,14 @@ they are concise and assume the concepts taught in **HowToLens** as background.
2121
## Chapters
2222

2323
- `chapter_1_introduction` — An introduction to strong gravitational lensing and **PyAutoLens**: grids, light
24-
and mass profiles, galaxies, ray-tracing, simulated imaging data, and fitting.
24+
and mass profiles, galaxies, ray-tracing, point sources, the lensing formalism, simulated imaging data,
25+
and fitting.
2526
- `chapter_2_lens_modeling` — Bayesian inference, non-linear searches, and how to fit a lens model to CCD
26-
imaging data with **PyAutoLens**.
27-
- `chapter_3_search_chaining`Chaining multiple non-linear searches together to build automated lens
28-
modeling pipelines for complex systems.
29-
- `chapter_4_pixelizations`Pixelized source reconstructions (inversions) for sources with irregular
30-
morphologies.
27+
imaging data with **PyAutoLens**, ending with search chaining and automated pipelines.
28+
- `chapter_3_pixelizations`Pixelized source reconstructions (inversions) for sources with irregular
29+
morphologies, including the Bayesian formalism underpinning them.
30+
- `chapter_4_scaling_up_lensing`Scaling lens modeling up beyond a single lens galaxy: extra galaxies,
31+
multi-galaxy lenses, scaling relations, group and cluster scales, and weak lensing.
3132
- `chapter_optional` — Optional tutorials on alternative non-linear searches and other advanced topics.
3233

3334
**HowToLens** currently sits at four chapters. Each chapter will take around a day to work through.

config/build/no_run.yaml

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,3 @@
2525
# permanent skips — every mega-run surfaces them with a loud warning
2626
# banner. Investigate the failure, fix the underlying bug, and remove
2727
# the NEEDS_FIX marker.
28-
29-
- tutorial_5_borders # NEEDS_FIX 2026-08-04 - cap-induced, not a mask problem:
30-
# fails only under PYAUTO_SMALL_DATASETS (IndexError: index 371 out of bounds
31-
# for axis 0 with size 272) and passes on the same dataset files without the
32-
# cap. Hardcoded pix/border indices outrun the capped mesh. Fix by decoupling
33-
# the indices (or the mesh shape) from dataset resolution, as HowToGalaxy
34-
# chapter_4 tutorial_3 did, then remove this entry.

llms-full.txt

Lines changed: 70 additions & 49 deletions
Large diffs are not rendered by default.

llms.txt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ analysis?" below).
2626

2727
- **Chapter 1 — Introduction** → [scripts/chapter_1_introduction/](scripts/chapter_1_introduction/): Lensing from first principles: grids & galaxies, ray tracing, simulating data, and fitting data. The conceptual foundation everything else builds on.
2828
- **Chapter 2 — Lens Modeling** → [scripts/chapter_2_lens_modeling/](scripts/chapter_2_lens_modeling/): How to fit a lens model to data with a non-linear search — parameter spaces, priors, dealing with failure, linear light profiles, masking, and reading results.
29-
- **Chapter 3 — Search Chaining** → [scripts/chapter_3_search_chaining/](scripts/chapter_3_search_chaining/): Breaking a hard fit into a sequence of searches (prior passing), multi-galaxy lenses, complex sources, and an introduction to the SLaM pipelines.
30-
- **Chapter 4 — Pixelizations** → [scripts/chapter_4_pixelizations/](scripts/chapter_4_pixelizations/): Reconstructing the source on a pixel-grid instead of with light profiles — mappers, inversions, Bayesian regularization, borders, and adaptive meshes.
29+
- **Chapter 3 — Pixelizations** → [scripts/chapter_3_pixelizations/](scripts/chapter_3_pixelizations/): Reconstructing the source on a pixel-grid instead of with light profiles — mappers, inversions, Bayesian regularization, the Bayesian formalism, borders, and adaptive meshes.
30+
- **Chapter 4 — Scaling Up Lensing** → [scripts/chapter_4_scaling_up_lensing/](scripts/chapter_4_scaling_up_lensing/): Beyond a single lens galaxy — extra galaxies, multi-galaxy lenses, scaling relations, group and cluster scales, and weak lensing.
3131

3232
## I want to understand…
3333

@@ -37,8 +37,9 @@ analysis?" below).
3737
- **How does a non-linear search find a model?** → [scripts/chapter_2_lens_modeling/tutorial_1_non_linear_search.py](scripts/chapter_2_lens_modeling/tutorial_1_non_linear_search.py): Parameter space, priors, nested sampling with Nautilus.
3838
- **My fit found a wrong (local-maxima) solution — what do I do?** → [scripts/chapter_2_lens_modeling/tutorial_4_dealing_with_failure.py](scripts/chapter_2_lens_modeling/tutorial_4_dealing_with_failure.py): Prior tuning, simplifying the model, and other escapes from local maxima.
3939
- **What are linear light profiles / MGE?** → [scripts/chapter_2_lens_modeling/tutorial_5_linear_profiles.py](scripts/chapter_2_lens_modeling/tutorial_5_linear_profiles.py): Solving intensities linearly; the Multi-Gaussian Expansion basis.
40-
- **How do I chain searches / what is SLaM?** → [scripts/chapter_3_search_chaining/tutorial_1_search_chaining.py](scripts/chapter_3_search_chaining/tutorial_1_search_chaining.py) then [scripts/chapter_3_search_chaining/tutorial_6_slam.py](scripts/chapter_3_search_chaining/tutorial_6_slam.py).
41-
- **How do I reconstruct a complex source on a pixel grid?** → [scripts/chapter_4_pixelizations/tutorial_1_pixelizations.py](scripts/chapter_4_pixelizations/tutorial_1_pixelizations.py) through [tutorial_4_bayesian_regularization.py](scripts/chapter_4_pixelizations/tutorial_4_bayesian_regularization.py).
40+
- **How do I chain searches / what is SLaM?** → [scripts/chapter_2_lens_modeling/tutorial_9_search_chaining.py](scripts/chapter_2_lens_modeling/tutorial_9_search_chaining.py) then [scripts/chapter_2_lens_modeling/tutorial_11_slam.py](scripts/chapter_2_lens_modeling/tutorial_11_slam.py).
41+
- **How do I reconstruct a complex source on a pixel grid?** → [scripts/chapter_3_pixelizations/tutorial_1_pixelizations.py](scripts/chapter_3_pixelizations/tutorial_1_pixelizations.py) through [tutorial_4_bayesian_regularization.py](scripts/chapter_3_pixelizations/tutorial_4_bayesian_regularization.py).
42+
- **How do I model lenses with many galaxies, groups, clusters or weak lensing?** → [scripts/chapter_4_scaling_up_lensing/tutorial_1_extra_galaxies.py](scripts/chapter_4_scaling_up_lensing/tutorial_1_extra_galaxies.py) through [tutorial_6_weak_lensing.py](scripts/chapter_4_scaling_up_lensing/tutorial_6_weak_lensing.py).
4243

4344
## Ready for real analysis?
4445

markdown/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ Every page below is the corresponding example script **fully executed**, rendere
55
- [Tutorial 0: Visualization](chapter_1_introduction/tutorial_0_visualization.md) — from `scripts/chapter_1_introduction/tutorial_0_visualization.py`
66
- [HowToLens: Introduction](chapter_1_introduction/tutorial_1_grids_and_galaxies.md) — from `scripts/chapter_1_introduction/tutorial_1_grids_and_galaxies.py`
77
- [Tutorial 2: Ray Tracing](chapter_1_introduction/tutorial_2_ray_tracing.md) — from `scripts/chapter_1_introduction/tutorial_2_ray_tracing.py`
8-
- [Tutorial 5: More Ray Tracing](chapter_1_introduction/tutorial_3_more_ray_tracing.md) — from `scripts/chapter_1_introduction/tutorial_3_more_ray_tracing.py`
8+
- [Tutorial 3: More Ray Tracing](chapter_1_introduction/tutorial_3_more_ray_tracing.md) — from `scripts/chapter_1_introduction/tutorial_3_more_ray_tracing.py`
99
- [Tutorial 4: Point Sources](chapter_1_introduction/tutorial_4_point_sources.md) — from `scripts/chapter_1_introduction/tutorial_4_point_sources.py`
1010
- [Tutorial 5: Lensing Formalism](chapter_1_introduction/tutorial_5_lensing_formalism.md) — from `scripts/chapter_1_introduction/tutorial_5_lensing_formalism.py`
1111
- [Tutorial 6: Data](chapter_1_introduction/tutorial_6_data.md) — from `scripts/chapter_1_introduction/tutorial_6_data.py`
1212
- [Tutorial 7: Fitting](chapter_1_introduction/tutorial_7_fitting.md) — from `scripts/chapter_1_introduction/tutorial_7_fitting.py`
13-
- [Tutorial 9: Summary](chapter_1_introduction/tutorial_8_summary.md) — from `scripts/chapter_1_introduction/tutorial_8_summary.py`
13+
- [Tutorial 8: Summary](chapter_1_introduction/tutorial_8_summary.md) — from `scripts/chapter_1_introduction/tutorial_8_summary.py`
1414

1515
These pages are regenerated manually by PyAutoHands's `generate_markdown.py` when a curated script changes.

markdown/chapter_1_introduction/tutorial_0_visualization.md

Lines changed: 62 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ clearly in your Jupyter notebook and on your computer screen.
1010

1111
__Contents__
1212

13-
- **Directories:** **PyAutoLens assumes** the working directory is `autolens_workspace` on your hard-disk.
13+
- **Directories:** **HowToLens** assumes the working directory is the `HowToLens` repository root on your hard-disk.
1414
- **Dataset:** Load and plot the strong lens dataset.
15+
- **Dataset Auto-Simulation:** Create the dataset via its simulator script if it is not on your hard-disk.
1516
- **Subplots:** In addition to plotting individual figures, **PyAutoLens** can plot `subplots` which show multiple.
1617
- **Plot Customization:** Does the figure display correctly on your computer screen?
1718
- **Overlays:** Overlays such as critical curves and image positions are added using the `lines=` and `positions=`.
@@ -25,27 +26,50 @@ from autolens import jax_wrapper # Sets JAX environment before other imports
2526
from autolens import setup_notebook; setup_notebook()
2627
```
2728

29+
.../PyAutoNerves/autonerves/workspace.py:206: UserWarning: Cannot verify the workspace at HowToLens/scripts/chapter_1_introduction is compatible with the installed library version (2026.7.23.1): no `version.minimum_library_version` or `version.workspace_version` key in config/general.yaml and no version.txt at the workspace root.
30+
31+
If you cloned the workspace from `main` rather than a release tag, set `version.workspace_version_check: False` in config/general.yaml to silence this warning. The `main` branch updates more frequently than library releases, so version mismatches are expected and not actionable for `main`-branch users.
32+
33+
You can also set the environment variable PYAUTO_SKIP_WORKSPACE_VERSION_CHECK=1 to disable temporarily.
34+
warnings.warn(_missing_version_warning(root, library_version))
35+
.../PyAutoNerves/autonerves/workspace.py:206: UserWarning: Cannot verify the workspace at HowToLens/scripts/chapter_1_introduction is compatible with the installed library version (2026.7.23.1): no `version.minimum_library_version` or `version.workspace_version` key in config/general.yaml and no version.txt at the workspace root.
36+
37+
If you cloned the workspace from `main` rather than a release tag, set `version.workspace_version_check: False` in config/general.yaml to silence this warning. The `main` branch updates more frequently than library releases, so version mismatches are expected and not actionable for `main`-branch users.
38+
39+
You can also set the environment variable PYAUTO_SKIP_WORKSPACE_VERSION_CHECK=1 to disable temporarily.
40+
warnings.warn(_missing_version_warning(root, library_version))
2841
Working Directory has been set to `HowToLens`
42+
.../PyAutoNerves/autonerves/workspace.py:206: UserWarning: Cannot verify the workspace at HowToLens/scripts/chapter_1_introduction is compatible with the installed library version (2026.7.23.1): no `version.minimum_library_version` or `version.workspace_version` key in config/general.yaml and no version.txt at the workspace root.
43+
44+
If you cloned the workspace from `main` rather than a release tag, set `version.workspace_version_check: False` in config/general.yaml to silence this warning. The `main` branch updates more frequently than library releases, so version mismatches are expected and not actionable for `main`-branch users.
45+
46+
You can also set the environment variable PYAUTO_SKIP_WORKSPACE_VERSION_CHECK=1 to disable temporarily.
47+
warnings.warn(_missing_version_warning(root, library_version))
48+
2949

50+
__Directories__
3051

31-
If the printed working directory does not match the workspace path on your computer, you can manually set it
32-
as follows (the example below shows the path I would use on my laptop. The code is commented out so you do not
33-
use this path in this tutorial!
52+
**HowToLens** assumes the working directory is the `HowToLens` repository root on your hard-disk, so that relative
53+
paths to `dataset/` and `output/` resolve correctly.
54+
55+
If your working directory does not match this path on your computer, you can manually set it as follows (the
56+
example below shows the path I would use on my laptop. The code is commented out so you do not use this path in
57+
this tutorial!
3458

3559

3660
```python
37-
# workspace_path = "/Users/Jammy/Code/PyAuto/autolens_workspace"
61+
# workspace_path = "/Users/Jammy/Code/PyAuto/HowToLens"
3862
# #%cd $workspace_path
3963
# print(f"Working Directory has been set to `{workspace_path}`")
4064
```
4165

4266
__Dataset__
4367

4468
The `dataset_path` specifies where the dataset is located, which is the
45-
directory `autolens_workspace/dataset/imaging/simple__no_lens_light`.
69+
directory `dataset/imaging/simple__no_lens_light` of the HowToLens repository.
4670

47-
There are many example simulated images of strong lenses in this directory that will be used throughout the
48-
**HowToLens** lectures.
71+
The simulated images of strong lenses used throughout the **HowToLens** lectures are written to the `dataset`
72+
directory at runtime by the simulator scripts in `scripts/simulator/`.
4973

5074

5175
```python
@@ -57,6 +81,31 @@ import autolens.plot as aplt
5781
dataset_path = Path("dataset") / "imaging" / "simple__no_lens_light"
5882
```
5983

84+
__Dataset Auto-Simulation__
85+
86+
If the dataset does not already exist on your system, it is created by running the corresponding
87+
simulator script. This ensures every example script can be run without manually simulating data first.
88+
89+
90+
```python
91+
if al.util.dataset.should_simulate(str(dataset_path)):
92+
import subprocess
93+
import sys
94+
95+
subprocess.run(
96+
[sys.executable, "scripts/simulator/no_lens_light.py"],
97+
check=True,
98+
)
99+
```
100+
101+
Figure(700x700)
102+
.../PyAutoArray/autoarray/operators/convolver.py:1424: UserWarning: No blurring_image provided. Only the direct image will be convolved. This may change the correctness of the PSF convolution.
103+
warnings.warn(
104+
Figure(1800x1800)
105+
Figure(1800x1800)
106+
Figure(700x700)
107+
108+
60109
We now load this dataset from .fits files and create an instance of an `Imaging` object.
61110

62111

@@ -78,7 +127,7 @@ aplt.plot_array(array=dataset.data, title="Dataset Image")
78127

79128

80129

81-
![png](tutorial_0_visualization_files/tutorial_0_visualization_9_0.png)
130+
![png](tutorial_0_visualization_files/tutorial_0_visualization_11_0.png)
82131

83132

84133

@@ -96,7 +145,7 @@ aplt.subplot_imaging_dataset(dataset=dataset)
96145

97146

98147

99-
![png](tutorial_0_visualization_files/tutorial_0_visualization_11_0.png)
148+
![png](tutorial_0_visualization_files/tutorial_0_visualization_13_0.png)
100149

101150

102151

@@ -106,7 +155,7 @@ Does the figure display correctly on your computer screen?
106155

107156
If not, the default matplotlib settings can be customized via the config files in:
108157

109-
autolens_workspace/config/visualize/
158+
config/visualize/
110159

111160
Key config entries:
112161

@@ -126,7 +175,7 @@ aplt.plot_array(array=dataset.data, title="Dataset Image (Log10)", use_log10=Tru
126175

127176

128177

129-
![png](tutorial_0_visualization_files/tutorial_0_visualization_13_0.png)
178+
![png](tutorial_0_visualization_files/tutorial_0_visualization_15_0.png)
130179

131180

132181

@@ -168,7 +217,7 @@ aplt.plot_array(
168217

169218

170219

171-
![png](tutorial_0_visualization_files/tutorial_0_visualization_15_0.png)
220+
![png](tutorial_0_visualization_files/tutorial_0_visualization_17_0.png)
172221

173222

174223

@@ -186,8 +235,3 @@ The key plotting functions you'll use are:
186235

187236
Great! Hopefully, visualization in **PyAutoLens** is displaying nicely for us to get on with the
188237
**HowToLens** lecture series.
189-
190-
191-
```python
192-
193-
```
-728 KB
Loading
-332 KB
Loading
80.1 KB
Loading

0 commit comments

Comments
 (0)