Hop atlas home · Overview · Changelog · Architecture · Adding_Data · Introgression · Ribbon · Dosage · Phylogeny · Bundle · Ingest · Ingest_Gbs · Ingest_Wgs · Ingest_Grasdi · Ingest_Rnaseq · Ingest_Assembly

Rendered from hop_atlas/components/BUNDLE.md (2026-10-13)

Self-contained bundle of the introgression atlas (zip): how to make one

Status: living document, started 2026-10-13. The bundled content is tentative, like everything served. Tool: hop_atlas/tools/package_atlas_bundle.py (template and scripts in hop_atlas/tools/bundle_assets/). Why (PI, 2026-10-13): "take the current introgression atlas (and all its companion pages), put it into a zip file with all the requisite data and a new CLAUDE.md describing what it is, how it was built, how it's designed/organized, and how to set it up/tear it down", then "build a packaging script for building that zip file". The first bundle was made by hand on 2026-10-13 (/data2/hop_data/hop_atlas_export/hop_introgression_atlas_2026-10-13/); the tool repeats exactly those steps.

Short answer

python3 hop_atlas/tools/package_atlas_bundle.py --dry-run                       # sizes, disk needed vs free; writes nothing
python3 hop_atlas/tools/package_atlas_bundle.py --smoke                         # default: introgression + phylogeny, today's name
python3 hop_atlas/tools/package_atlas_bundle.py --name hop_introgression_atlas_2026-10-13b --include phylogeny --smoke

Options

Option Default Meaning
--out-dir /data2/hop_data/hop_atlas_export where the folder and zip are written
--name hop_introgression_atlas_<today> bundle folder and zip name (also the top folder inside the zip)
--include phylogeny extra components, comma-separated: phylogeny, structural_atlas (ribbon, ~1 GB), dosage_atlas (~0.3 GB). The introgression atlas is always included
--smoke off serve the finished bundle with its own serve.sh on a free port, load the main pages in headless Chromium, report page errors, failed requests and HTTP >= 400, then stop it with stop.sh
--keep-unpacked (always) accepted for clarity; the unpacked folder is always kept, because the project forbids scripted deletion
--dry-run off print source sizes and the disk check only

What it does (the steps of the hand-made bundle)

  1. Copy the served pages from scratch_plots/ with every symlink dereferenced (shutil.copytree(symlinks=False)), so the data on /data and /data2 (lineage/, subev/, subevc/, wgsv/, frames/, detail/, detail_mr/, the phylogeny folder) comes along. Excluded by name: *.bak* (deploy backups), .server*, __pycache__.
  2. Drift check: the introgression atlas is snapshotted (top-level files, small data folders, symlink targets) before and after the copy. If another session deployed during the copy, the tool stops, writes INCOMPLETE.txt into the folder and asks for a re-run under a new name.
  3. Docs and nav bar. hop_atlas/www/docs/ (the rendered docs) is copied as served. The bundle's hop_atlas/nav.js is the live www/nav.js with its entry list filtered to the bundled components (home and Docs always kept; home relabelled "Hop atlas (bundle)"). The filter reads the live list, so a new nav entry is handled without editing the tool.
  4. Landing page, server and scripts. site/index.html lists the bundled components. server/nocache_server.py is the :8900 server. serve.sh and stop.sh come from bundle_assets/; stop.sh kills the pid in server.pid and then empties the file (no rm).
  5. Build record (build_record/): README, CHANGELOG, ARCHITECTURE, ADDING_DATA, the guides of the bundled components and this guide, ingest/ (runbooks and the manifest pipeline), cohorts/ (cohort manifests), evidence/ (badge-page prose), INTROGRESSION_ATLAS_TECHNICAL.md, methods/per_frame_ancestry_README.md and tools/ (without __pycache__ or backups).
  6. CLAUDE.md from bundle_assets/CLAUDE.template.md, with every number computed from the copied data at packaging time:
  7. date, source commit, total size and file count;
  8. rows per cohort and assay (multires/atlas_samples_5Mb.json) and the opt-in datasets (multires/atlas_samples_5Mb.<dataset>.json);
  9. the haplotype-resolution levels present (lineage/atlas_lineage_5Mb.json levels + wgsv/);
  10. the references with calls (frames/frames.json, has_data);
  11. the patch markers found in index.html and *.js, each mapped to the script that inserts it (table MARKERS in the tool; a marker without an entry is reported as "source not recorded" and printed as a warning);
  12. folder sizes, and what is excluded. The tool stops if a placeholder is left unfilled. Edit the template (not the generated file) to change the prose.
  13. MANIFEST.tsv (path relative to the bundle folder, bytes, md5) for every file except the manifest itself, server.pid and server.log. Then the zip: Python zipfile, ZIP_DEFLATED level 6, allowZip64, written as <name>.zip.part and renamed when complete; testzip() and the entry count are checked. (There is no zip binary on this machine.)
  14. Smoke test (--smoke): landing page, Docs, the atlas (default, ?sample=cordifolius|KR, two non-21110M references), the Badges page, the OSU paternity page and each included component. It needs the browser libraries described in hop_atlas/README.md ("Running the browser tests"); the tool sets the variables itself.

Differences from the hand-made bundle of 2026-10-13

The hand-made bundle was made at 14:39, before the 16:58 Reference-selector deploy, so a bundle made today differs in content as well as in a few deliberate choices: - Content: the served atlas now has frames/ + frames.js (per-reference calls) and the lifted geometry stripped from atlas_data.json and multires/atlas_native_*.json. - MANIFEST.tsv now covers the whole bundle (paths relative to the bundle folder) instead of site/ only; the check in CLAUDE.md reads it that way. - Build record adds components/BUNDLE.md, ingest/ASSEMBLY.md, ingest/SAAZ_EXCLUSIONS.md, ingest/pipeline/, cohorts/ and methods/per_frame_ancestry_README.md, and drops tools/__pycache__ (the hand-made copy included it). - CLAUDE.md is generated, so its tables (cohorts, levels, references, markers, sizes) match the bundled data exactly; the hand-made one listed fewer markers (no lin, ped, o18, o08-preset, frames) and described the old "Display coordinates" control.

Proof run (2026-10-13 17:31)

package_atlas_bundle.py --name hop_introgression_atlas_2026-10-13b --include phylogeny --smoke → /data2/hop_data/hop_atlas_export/hop_introgression_atlas_2026-10-13b{,.zip} (zip 6,050,170,081 bytes, 37,859 entries, testzip OK; log package_2026-10-13b.log next to it). Smoke: 9/9 pages clean (landing, Docs, atlas default, ?sample=cordifolius|KR, ?ref=saaz_hap1, ?ref=hl1012_hap1, Badges, OSU paternity, Phylogeny; no page errors, failed requests or HTTP >= 400). The bundle nav is byte-identical to the hand-made one.

Compared with the hand-made bundle (site files, by md5): no file lost; 23 new (frames/ 21 + frames.js from the 16:58 Reference deploy, docs/BUNDLE.html); 21 changed, all explained: index.html, atlas_data.json and multires/atlas_native_*.json (the 16:58 deploy stripped the lifted geometry), 14 rendered docs (re-rendered after today's doc update), the landing page (bundle name). Build record: + cohorts/, ingest/{ASSEMBLY,SAAZ_EXCLUSIONS}.md, ingest/pipeline/, methods/, components/BUNDLE.md, the frames and packaging tools; − tools/__pycache__.

Gaps