dde-cargo
Stimela cabs for DDFacet/Killms on both arm64 and x86-64 systems.
DDFacet is a direction-dependent radio-interferometric imager: it grids visibilities and deconvolves wide fields in facets, applying per-direction Jones terms and primary beams. killMS is its companion calibration engine, solving per-antenna, per-direction complex gains against a sky model. Together they form the imaging and direction-dependent calibration halves of the DDE loop. Release history is in CHANGELOG.md.
Cabs and images
Full parameter reference: docs/cabs.md.
| Cab | Purpose | Image |
|---|---|---|
bdsf.catalog |
Image-only override for cult-cargo's PyBDSF step | ghcr.io/tmolteno/ddfacet:v0.16.10 |
ddfacet |
Direction-dependent imager, gridder and deconvolver | ghcr.io/tmolteno/ddfacet:v0.16.10 |
killms |
Direction-dependent gain solver | ghcr.io/tmolteno/killms:v3.15.12 |
ddf_makemodel |
Build a direction catalogue from a DS9 region | ghcr.io/tmolteno/ddfacet:v0.16.10 |
ddf_makemask |
Make a FITS clean mask from a restored image | ghcr.io/tmolteno/ddfacet:v0.16.10 |
dilatemask |
Dilate a clean mask by N synthesised beams | ghcr.io/tmolteno/ddfacet:v0.16.10 |
clustercat |
Cluster sources into DD direction nodes | ghcr.io/tmolteno/ddfacet:v0.16.10 |
ddfacet-get-npix |
Compute the padded image size DDFacet needs | ghcr.io/tmolteno/ddfacet:v0.16.10 |
modelcat |
Replace BDSF catalogue fluxes with model flux | ghcr.io/tmolteno/ddfacet:v0.16.10 |
autofacet |
Derive facet centres from the DI products | ghcr.io/tmolteno/ddfacet:v0.16.10 |
snapnodes |
Snap DD nodes onto their dominant modelled source | ghcr.io/tmolteno/ddfacet:v0.16.10 |
ddfacet-memory-plan |
Suggest DDFacet memory and parallel settings | ghcr.io/tmolteno/ddfacet:v0.16.10 |
killms-memory-plan |
Suggest killMS memory and parallel settings | ghcr.io/tmolteno/killms:v3.15.12 |
All images are published for amd64 and arm64.
Install
pip install dde-cargo
Requires Python >= 3.10,< 3.15 (the same window as skarabina-cargo) and
installs stimela>=2.1.4 — every cab runs in its container, so the host needs
nothing else.
Usage
In a stimela 2 recipe, load the cabs from the installed package with
configuratt's package-include syntax. The cultcargo include must come first:
ddfacet.yml carries an image-only override for cult-cargo's bdsf.catalog
cab (the upstream image is amd64-only; these cabs redirect it to the
multi-arch ddfacet image), and stimela builds every cab at load time, so
bdsf.yml must already be loaded when ddfacet.yml merges in:
_include:
- (cultcargo):
- bdsf.yml
- (dde_cargo):
- ddfacet.yml
- ddfacet-memory-plan.yml
- killms-memory-plan.yml
then reference them from steps:
steps:
ddfacet-target:
cab: ddfacet
params:
Data.MS: mydata.ms
Output.Name: target0
killms-target:
cab: killms
params:
MSName: mydata.ms
InCol: CORRECTED_DATA
Only ddfacet.yml is essential; the memory-plan files are optional extras
(wire them ahead of a step as shown in their header comments — e.g.
ddfacet-memory-plan suggests Parallel.NCPU, Data.ChunkHours and
Selection.ChanStep for the imaging step that follows). They are
self-contained: the calibrated model and its tessellation code are inlined in
the cab's python-code command, so they need no Lib/ModelFile input and no
meerkat_imaging checkout (tests/test_sync.py keeps it that way).
Notes carried over from the upstream cab comments:
- The
autofacetcab importsauto_facet_tool/auto_facet.pyfrom the working directory, so it needs a checkout ofmeerkat_imagingbeside the recipe (stimela binds the working directory into the container). - The memory-plan cabs pin their image "to whatever the recipe uses": a recipe
with its own image var should override
image:on the cab instead of editing the package. - The DDFacet cab wraps every parset namespace (
Data,Image,Facets,Deconv, ...) as dashed CLI options (--Data-MS,--Image-NPix, ...); the killMS cab passes its flat parameter set throughkMS.py.
Publishing
Trusted publishing (OIDC) — there is no API token. The GitHub Actions
workflow .github/workflows/publish_pypi.yaml fires on a vX.Y.Z tag, builds
with uv, and publishes from the pypi environment.
Automated release
invoke release drives the tag, PyPI publish and GitHub release end to end.
See Release automation under Development for the full
task reference and prerequisites.
Manual release
- Register the pending publisher on PyPI (once):
pypi.org/manage/account/publishing
with owner
tmolteno, repositorydde-cargo, workflowpublish_pypi.yaml, environmentpypi. The workflow filename must match exactly. - Bump
versioninpyproject.toml. git commit -m "..." && git tag -a vX.Y.Z -m "..." && git push origin main --follow-tags
The workflow run appears under the repo's Actions with the pypi environment;
the publish is live at pypi.org/project/dde-cargo.
Development
uv sync --all-groups
uv run pytest # schema + generated-docs contracts
uv build # wheel + sdist into dist/
invoke --list # tasks: version, changelog, docs, release
invoke docs # regenerate docs/cabs.md
invoke docs --check # verify docs/cabs.md is current
An end-to-end smoke check (loads the cabs through stimela's real spec loader, as a recipe would):
uv run stimela run /tmp/dde-cargo-smoke.yml dde-cargo-smoke -d
with /tmp/dde-cargo-smoke.yml any recipe that _includes the package as
shown above and runs one or two of the cabs.
Where the cabs are edited: invoke sync
The cab YAMLs and schemas in dde_cargo/ are not edited in this repository.
Their source is meerkat_imaging's
cabs/ directory (where the pipeline runs and tests them):
meerkat_imaging cabs/ |
here |
|---|---|
ddfacet.yml, ddfacet_stimela_inputs_schema.yml, killms_stimela_schema.yml |
same names in dde_cargo/ |
ddfacet-memory-plan.yml, killms-memory-plan.yml (generated there from *.yml.in, tools/memplan_lib.py and memplan-model.json by tools/build-memplan-cabs.py) |
same names |
invoke sync # copy the five files from ../meerkat_imaging (MEERKAT_REPO to override)
invoke sync --check # exit 1 if dde_cargo/ differs
sync refuses when those files have uncommitted changes in meerkat_imaging (or
its generated cabs are stale), copies them, and records the meerkat_imaging
commit and the files' hashes in dde_cargo/meerkat-sync.json
(tests/test_sync.py fails if a packaged file is edited by hand). release
runs sync first.
Release automation
tasks.py is an invoke +
plumbum script that automates a release
from the sibling ../DDFacet, ../killMS and ../meerkat_imaging
repositories. It syncs the cabs from meerkat_imaging, resolves the latest
upstream release tags, verifies that the synced cabs pin exactly those
tags (it refuses, with a message, instead of rewriting a pin), and generates
the changelog from the upstream commits between the old and new tags plus
meerkat_imaging's commits to the cab files since the previously synced commit.
Prerequisites:
- the
devdependency group —uv sync --all-groupsinstallsinvokeandplumbum; uvand an authenticatedgh(the PyPI workflow uses OIDC, so no API token is involved);../DDFacetand../killMScheckouts containing theirvX.Y.Zrelease tags, and a../meerkat_imagingcheckout with the cabs committed (and their pins at those tags) — override the paths withDDFACET_REPO,KILLMS_REPOandMEERKAT_REPO;- a clean
mainbranch, with the package version not yet tagged or published.
Available tasks:
invoke --list # show the available release tasks
invoke version # package version and pinned/latest image tags
invoke changelog # print the next release's changelog section
invoke changelog --allow-same # ... even when no image tag has moved
invoke docs # regenerate docs/cabs.md
invoke docs --check # verify docs/cabs.md is current
invoke sync # copy the cabs from meerkat_imaging
invoke release --dry-run # show the complete plan; change nothing
invoke release --part patch # the real release
invoke release --part minor # ... when a cab interface changed (0.1.1 -> 0.2.0)
Use --part minor whenever a cab's inputs or outputs changed (or an input was
removed, as the memory-plan cabs' Lib/ModelFile were for 0.2.0); patch
(the default) for pin bumps and internal fixes. --allow-same releases when
nothing changed (no new pins, cabs or commits).
The release order
Normally nobody runs this by hand: meerkat_imaging's invoke release does,
after DDFacet and killMS are tagged and their images are live:
- meerkat_imaging commits its updated cab pins (and regenerated memory-plan cabs);
- it runs
invoke release --part <patch|minor> --yeshere (path:DDE_CARGO_REPO); - this release syncs the cabs, checks the pins, publishes to PyPI and creates the GitHub release, and exits non-zero unless the version is live on PyPI;
- meerkat_imaging bumps its
dde-cargo==X.Y.Zpin and makes onepins: ddfacet vA, killms vB, dde-cargo vCcommit.
invoke version reports the package version, the DDFacet/killMS tags currently
pinned by the cabs, and the latest tags in the upstream checkouts.
invoke changelog prints the section that would be inserted into
CHANGELOG.md. It groups the upstream commits per release tag (for example
v0.16.2 … v0.16.6) and notes killMS releases that are rebuilds on a new
DDFacet image.
invoke docs regenerates the cab reference from the packaged YAMLs and
docs/cab_notes.yml; invoke docs --check reports whether the checked-in
docs/cabs.md is current.
invoke release performs the complete chain:
- generates and inserts the changelog section, keeping any
[Unreleased]notes; - bumps
versioninpyproject.toml, updates the DDFacet/killMS pins in the cab YAMLs and the image table above, and regeneratesdocs/cabs.md; - refreshes
uv.lock, runs the test suite anduv build; - commits the changes, creates an annotated
vX.Y.Ztag, and pushesmainand the tag; - waits for the tag's
publish_pypi.yamlworkflow to succeed and verifies that the version is live on PyPI; - creates the GitHub release with the generated notes and the built wheel and sdist attached.
Options:
--part patch|minor|major— which part of the package version to bump (defaultpatch);--ddfacet-tag/--killms-tag— override the upstream target tags (default: the latest release tag in each checkout);--allow-same— release packaging-only changes when both images are already at the pinned tags;--fetch/--no-fetch— fetch upstream tags first (default: fetch, falling back to the local tags with a warning if the remotes are unreachable);--yes— skip the confirmation prompt;--dry-run— print the plan and generated changelog without changing, committing or publishing anything.
The script refuses to run on a dirty tree, from a branch other than main, or
when the target tag or PyPI version already exists. It never force-pushes.
Metadata
Release files for dde-cargo 0.2.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| dde_cargo-0.2.3.tar.gz | 154.4 kB | With provenance | Details for dde_cargo-0.2.3.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| dde_cargo-0.2.3-py3-none-any.whl | Python 3 | none | any | Details for dde_cargo-0.2.3-py3-none-any.whl |
Total release size: 218.5 kB
Release files / dde_cargo-0.2.3.tar.gz
| Download URL | dde_cargo-0.2.3.tar.gz |
|---|---|
| Size | 154.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e82fbd7e902b30ee66b85ffc742fff70c182eabba4ce37c3148b650a23e174a4
|
|
BLAKE2b-256 checksum How to use checksums |
b593b867291036d8df681028e67b2e04dd6d2dfd40a9dc2ef10521e200cc2c16
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logRelease files / dde_cargo-0.2.3-py3-none-any.whl
| Download URL | dde_cargo-0.2.3-py3-none-any.whl |
|---|---|
| Size | 64.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fc947563088b8191241e60579bde699f9632a416c556f4aff0a930bba46026f5
|
|
BLAKE2b-256 checksum How to use checksums |
c8ffdb760a8cb671647b708ff29cd86fc8e2f7cbed844197e1e1975d1843ac36
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logSecurity for dde-cargo 0.2.3
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for dde_cargo-0.2.3.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.