Overview
The PyAutoFit Aggregator loads modeling results at scale (3000+ strong lenses in Euclid work, building csv/fits/png catalogues) and is too slow, with unclear scaling drivers — is it the number of results, samples per result, or model complexity? This task builds a fast profiling harness in autofit_workspace_test that mocks realistic output folders without running samplers, then uses it to measure and fix the low-hanging performance fruit in autofit/aggregator/. The long-unused sqlite database build path is explicitly a follow-up task, not part of these PRs.
Plan
- Build a synthetic-results generator in
autofit_workspace_test that fabricates realistic aggregator output directories (metadata, model, samples csv, summaries, optional images/zips) parameterised by number of results, samples per result, and model dimensionality — thousands of mock results in seconds.
- Add a profiling grid runner that times each loading pathway separately (
from_directory scan, iteration, values("samples_summary"), values("samples"), query, a csv_make-style catalogue loop) and emits a table + JSON, so scaling behaviour is explicit.
- Use the harness to identify and fix low-hanging fruit in
PyAutoFit's aggregator (candidates already identified — see detailed plan), each change behaviour-preserving and measured before/after.
- Later phase (blocked): extend
autolens_workspace_test with lens-specific profiling once viz-render-gallery frees that repo.
- Follow-up task (separate prompt/issue): exercise and assess the sqlite database build/write path (
autofit/database/).
Detailed implementation plan
Work Classification
Both (library + workspace).
Worktree root
~/Code/PyAutoLabs-wt/aggregator-profiling/ (created by start_library)
Affected Repositories
- PyAutoFit (primary)
- autofit_workspace_test
- autolens_workspace_test (later phase — currently claimed by viz-render-gallery, not claimed now)
Branch Survey
| Repository |
Current Branch |
Dirty? |
| ./PyAutoFit |
main |
clean |
| ./autofit_workspace_test |
main |
clean |
| ./autolens_workspace_test |
main (repo claimed by viz-render-gallery) |
clean |
Suggested branch: feature/aggregator-profiling
Implementation Steps
Phase A — profiling harness (autofit_workspace_test, new scripts/profiling/aggregator/):
mock_results.py — writes synthetic search-output directories the real Aggregator accepts: metadata, .completed, files/model.json, files/samples.csv + files/samples_info.json, files/samples_summary.json, files/search.json, optional latent/, optional dummy image/*.png + files/*.fits, optional .zip packaging. Parameterised by n_results, n_samples, model dimensionality (nested af.Model/af.Collection for realistic path lengths). Build one template result via real af serialization (formats never drift), then stamp N copies with per-result tweaks.
profile_aggregator.py — grid runner over (n_results × n_samples × model_dims) timing each stage with time.perf_counter: Aggregator.from_directory (cold + completed_only), iteration/len, values("samples_summary"), values("samples"), values("model"), a query() predicate, and a csv_make-style summary loop (mirroring autolens_workspace/scripts/guides/results/workflow/csv_make.py). Emits printed table + JSON.
- Ensure mock-output and profiling-result dirs are gitignored; do not add to
smoke_tests.txt.
Phase B — speedups (PyAutoFit, each measured before/after on grids like N∈{10,100,1000,3000}, samples∈{100,1k,10k}, dims∈{5,20,50}):
autofit/aggregator/aggregator.py::unzip_directory — currently an unconditional full os.walk + zip handling on every from_directory, followed by a second full walk for the scan. Skip zip handling when there are no zips; merge into a single traversal.
autofit/aggregator/search_output.py::AbstractSearchOutput.value() — currently materialises all four suffix lists (jsons/pickles/arrays/fits), each doing rglob over files/ and image/ → 8 sweeps per SearchOutput to fetch one file. Resolve the requested name from one cached directory listing.
SearchOutput.__init__ — eager metadata open/parse per result at scan time; make lazy or fold into the scan walk.
samples_summary path — avoid forcing full model/samples.csv loads where a summary-only read suffices.
- Unit tests in
test_autofit/aggregator/ (numpy-only); full pytest test_autofit/ before ship.
Phase C — later, blocked: lens-level profiling in autolens_workspace_test (ImagingAgg/FitImagingAgg, workflow csv/fits/png makers) once viz-render-gallery ships.
Phase D — follow-up (separate issue): exercise autofit/database/ build/scrape (database/aggregator/scrape.py, session writes) via the harness's mock outputs; fix cheap bugs; written assessment if deep.
Key Files
PyAutoFit/autofit/aggregator/aggregator.py — from_directory, unzip_directory
PyAutoFit/autofit/aggregator/search_output.py — AbstractSearchOutput.value, SearchOutput.__init__, _load_samples
PyAutoFit/autofit/aggregator/file_output.py — FileOutput/JSONOutput load costs
autofit_workspace_test/scripts/profiling/aggregator/ — new harness package
autolens_workspace/scripts/guides/results/workflow/csv_make.py — reference for the catalogue-loop profile (read-only)
Verification
- Harness: 100 results × 1k samples grid completes in seconds–minutes; real
Aggregator loads mock dirs identically to real output (spot-check values("samples_summary"), samples, query).
- Speedups:
pytest test_autofit/ green; before/after harness numbers quoted in the PR; the 3000-result case shows the from_directory + values wins explicitly.
Original Prompt
Click to expand starting prompt
The PyAutoFit Aggregator is used to load and inspection modeling results, including workflow variants
for .fits, .csv and .png files.
It is used heavily in /mnt/c/Users/Jammy/Science/euclid, where it was often loading results for 3000+ strong lenses
and making the catalogue of csv, fits, png files.
There are many variants of how to load results, aggregators may be skipped for small numbers of lenses, whereas
an sqlite database can be built for large sets (albeit I havent done this in a while and it may be buggy).
A good run through of loadin gresults in all the different ways is at autolens_workspace/scripts/guides/results
The goals of this task are the following:
-
Extend autofit_workspace_test and autolens_workspace_test to have the tools required to profile the speed of the aggregator
in different models, for differnt models and really work out "where does it scale poorly", "when is it too
slow to do sciecne", "is it model complexity, number of sampels or something else whjich sl;ows it down?". Ideally,
This will create output folders that mock real results, but it will do so in a fast way which does not run actual
samplers or do anything that is to slow.
-
Use these profiling tools to begin speeding up the existing Aggregators and other ways of loading reults, basically
target the low hanging fruit for now.
-
dont work on sqlite database builds on 1 or 2, but then do a follow upw here you use this functionality,
inevitably encounter and fix bugs for its use, and assess the code which writes directly to the sqlite database,
which has not been used in a long time and I'm sure is buggy. If its hard to fix dont bother, but its good to work out where its at.
Overview
The PyAutoFit
Aggregatorloads modeling results at scale (3000+ strong lenses in Euclid work, building csv/fits/png catalogues) and is too slow, with unclear scaling drivers — is it the number of results, samples per result, or model complexity? This task builds a fast profiling harness inautofit_workspace_testthat mocks realistic output folders without running samplers, then uses it to measure and fix the low-hanging performance fruit inautofit/aggregator/. The long-unused sqlite database build path is explicitly a follow-up task, not part of these PRs.Plan
autofit_workspace_testthat fabricates realistic aggregator output directories (metadata, model, samples csv, summaries, optional images/zips) parameterised by number of results, samples per result, and model dimensionality — thousands of mock results in seconds.from_directoryscan, iteration,values("samples_summary"),values("samples"),query, a csv_make-style catalogue loop) and emits a table + JSON, so scaling behaviour is explicit.PyAutoFit's aggregator (candidates already identified — see detailed plan), each change behaviour-preserving and measured before/after.autolens_workspace_testwith lens-specific profiling once viz-render-gallery frees that repo.autofit/database/).Detailed implementation plan
Work Classification
Both (library + workspace).
Worktree root
~/Code/PyAutoLabs-wt/aggregator-profiling/(created by start_library)Affected Repositories
Branch Survey
Suggested branch:
feature/aggregator-profilingImplementation Steps
Phase A — profiling harness (autofit_workspace_test, new
scripts/profiling/aggregator/):mock_results.py— writes synthetic search-output directories the realAggregatoraccepts:metadata,.completed,files/model.json,files/samples.csv+files/samples_info.json,files/samples_summary.json,files/search.json, optionallatent/, optional dummyimage/*.png+files/*.fits, optional.zippackaging. Parameterised byn_results,n_samples, model dimensionality (nestedaf.Model/af.Collectionfor realistic path lengths). Build one template result via realafserialization (formats never drift), then stamp N copies with per-result tweaks.profile_aggregator.py— grid runner over (n_results × n_samples × model_dims) timing each stage withtime.perf_counter:Aggregator.from_directory(cold +completed_only), iteration/len,values("samples_summary"),values("samples"),values("model"), aquery()predicate, and a csv_make-style summary loop (mirroringautolens_workspace/scripts/guides/results/workflow/csv_make.py). Emits printed table + JSON.smoke_tests.txt.Phase B — speedups (PyAutoFit, each measured before/after on grids like N∈{10,100,1000,3000}, samples∈{100,1k,10k}, dims∈{5,20,50}):
autofit/aggregator/aggregator.py::unzip_directory— currently an unconditional fullos.walk+ zip handling on everyfrom_directory, followed by a second full walk for the scan. Skip zip handling when there are no zips; merge into a single traversal.autofit/aggregator/search_output.py::AbstractSearchOutput.value()— currently materialises all four suffix lists (jsons/pickles/arrays/fits), each doingrgloboverfiles/andimage/→ 8 sweeps per SearchOutput to fetch one file. Resolve the requested name from one cached directory listing.SearchOutput.__init__— eagermetadataopen/parse per result at scan time; make lazy or fold into the scan walk.samples_summarypath — avoid forcing fullmodel/samples.csvloads where a summary-only read suffices.test_autofit/aggregator/(numpy-only); fullpytest test_autofit/before ship.Phase C — later, blocked: lens-level profiling in
autolens_workspace_test(ImagingAgg/FitImagingAgg, workflow csv/fits/png makers) once viz-render-gallery ships.Phase D — follow-up (separate issue): exercise
autofit/database/build/scrape (database/aggregator/scrape.py, session writes) via the harness's mock outputs; fix cheap bugs; written assessment if deep.Key Files
PyAutoFit/autofit/aggregator/aggregator.py—from_directory,unzip_directoryPyAutoFit/autofit/aggregator/search_output.py—AbstractSearchOutput.value,SearchOutput.__init__,_load_samplesPyAutoFit/autofit/aggregator/file_output.py—FileOutput/JSONOutputload costsautofit_workspace_test/scripts/profiling/aggregator/— new harness packageautolens_workspace/scripts/guides/results/workflow/csv_make.py— reference for the catalogue-loop profile (read-only)Verification
Aggregatorloads mock dirs identically to real output (spot-checkvalues("samples_summary"),samples,query).pytest test_autofit/green; before/after harness numbers quoted in the PR; the 3000-result case shows thefrom_directory+valueswins explicitly.Original Prompt
Click to expand starting prompt
The PyAutoFit Aggregator is used to load and inspection modeling results, including workflow variants
for .fits, .csv and .png files.
It is used heavily in /mnt/c/Users/Jammy/Science/euclid, where it was often loading results for 3000+ strong lenses
and making the catalogue of csv, fits, png files.
There are many variants of how to load results, aggregators may be skipped for small numbers of lenses, whereas
an sqlite database can be built for large sets (albeit I havent done this in a while and it may be buggy).
A good run through of loadin gresults in all the different ways is at autolens_workspace/scripts/guides/results
The goals of this task are the following:
Extend autofit_workspace_test and autolens_workspace_test to have the tools required to profile the speed of the aggregator
in different models, for differnt models and really work out "where does it scale poorly", "when is it too
slow to do sciecne", "is it model complexity, number of sampels or something else whjich sl;ows it down?". Ideally,
This will create output folders that mock real results, but it will do so in a fast way which does not run actual
samplers or do anything that is to slow.
Use these profiling tools to begin speeding up the existing Aggregators and other ways of loading reults, basically
target the low hanging fruit for now.
dont work on sqlite database builds on 1 or 2, but then do a follow upw here you use this functionality,
inevitably encounter and fix bugs for its use, and assess the code which writes directly to the sqlite database,
which has not been used in a long time and I'm sure is buggy. If its hard to fix dont bother, but its good to work out where its at.