Skip to content

feat(project)!: biahub project CLI; segment and track no longer project - #424

Merged
ieivanov merged 20 commits into
mainfrom
feat/project-cli
Oct 23, 2026
Merged

ieivanov merged 20 commits into
mainfrom
feat/project-cli

Conversation

@ieivanov

@ieivanov ieivanov commented Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator

What

Closes #362: the projected plate is the DCA companion store that issue asks for (every assembled channel, Z=1, the source's T/C/Y/X), written by the pipeline beside the assembled plate as <N>-assemble/<DATASET>_proj.zarr, with the projection method, Z selection and focus plane per timepoint recorded in each position's biahub-project metadata. Pyramid levels (#359), labels and tracks.geff per FOV (#360/#361, via #413) and the dca metadata and normalization statistics (#357/#358) stay with their issues. The per-timepoint focus record is also the focus metadata #400 asks for.

A new biahub project command turns a 3D plate into a 2D (Z=1) plate with one projection per output channel, and takes over all Z selection and projection from segment and track. Planned ahead of #413, which then writes labels into the plate track reads (the projected plate for A549) and can drop its plane-placement helpers (tracked_z_window / write_tracking_labels).

biahub project

Config (settings/example_project_settings.yml):

channels:                      # one entry per OUTPUT channel, in output order
  membrane_prediction:
    method: max                # whole stack
  nuclei_prediction:
    method: max
    z: {start: 10, stop: 50, step: 2}          # absolute, half-open
  GFP:
    method: sum
    z: {center: 30, below: 10, above: 11}      # planes 20 .. 40
  RFP:
    method: mean
    z: {center: focus, below: 20, above: 40}   # the A549 60-plane window
  mCherry:
    method: slice
    z: {center: 42}
  Phase3D:
    method: slice
    z: {center: focus}
focus:                         # required with center: focus; FocusSettings subclass
  channel: Phase3D
  per: fov                     # fov (median over T) | timepoint
  center_crop_xy: [800, 800]
  na_det: 1.35
  lambda_ill: 0.5
chunks_czyx: null              # as in concatenate; null = iohub defaults
shards_ratio: null
  • method: max | mean | sum | slice. The plate is float32 whenever any channel uses max, mean or sum; an all-slice plate keeps the input dtype.
  • start/stop are absolute planes (half-open like concatenate's time_indices); below/above count planes around center, selecting [center - below, center + above). Selections past the stack are clipped.
  • focus subclasses the engine's FocusSettings (same criterion, crop and defaults) and adds channel and per. The focus is found once per position, in a spawned process pool sized by the job's workers (the timepoints are independent), then the record focus: {channel, per, z, z_per_t} goes into the output position's biahub-project metadata (z is the per-FOV median, null for per: timepoint; z_per_t is always the per-timepoint measurement). The projection itself runs through iohub's process_single_position, so the per-position job is the focus pre-pass followed by the shard-batched projection.
  • chunks_czyx / shards_ratio have concatenate's semantics (shard = chunks * ratio, C not sharded).
  • Unlisted input channels are dropped (the command names them); a listed channel the plate lacks fails --init. Standard CLI stack (-i -c -o -sb --cluster -m --init --resume), provenance block, preempted partition.

Segment and track

  • Segment: z_slice_2D is removed. A model without do_3D (or a stitch threshold) segments in 2D and needs a Z=1 input; a 2D model on a stack, or a 3D model on a Z=1 plate, is an error at --init. Labels take the input's Z.
  • Track: ZSlicing / z_slicing, the focus window and the implicit mean projection are removed. output_mode is checked against the input Z (2D needs Z=1, 3D needs Z>1). Z=1 inputs are squeezed, so configs need no np.mean step.
  • Old keys (z_slice_2D, z_slicing) are rejected with a message pointing at biahub project.

Nextflow

  • modules/project.nf, --project_config. The projected plate is the 2D companion of the assembled plate and is written beside it as 4-assemble/<DATASET>_proj.zarr, so project has no step directory and track stays 5-track; track reads the projected plate when project runs. The projected plate is a deliverable: cleanup removes only the shared slurm_output/ and .iohub-progress/, as for the assembled plate. Skill docs and the run template updated.
  • nextflow/configs/a549/project.yml projects every channel of a typical assembled plate under the pre-rename names: the in-focus plane of BF and Phase3D, the full-stack max of the raw fluorescence channels, and the mean of the two predictions over the 60-plane focus window (feat(nextflow): A549 track config segments a 60-plane phase-focus window #418), with the focus found per timepoint on Phase3D (Add inference-readiness preprocessing for focus and intensity metadata #400). Output layout after the Dynamic Cell Atlas array standard where a 2D float32 plate can follow it: one-frame 256 x 256 chunks (the grid the assembled and tracking stores share) and shards_ratio: [16, 1, 1, 7, 5], 16-timepoint full-frame shards (~150 MB, 30 files per position instead of 400). track.yml drops z_slicing and the np.mean step.
  • The reconstruct-with-nextflow check script validates project.yml against the assembled plate both ways and track.yml against the projected plate; the skill carries unprojected channels into the pre-run plan for the user to decide, and suggests the BF - Oblique edit in both reconstruct.yml and project.yml for the older acquisitions.

Behaviour differences vs track's old focus window

  • The focus is measured on the 800x800 centre crop (track used the full field), and the A549 config finds it per timepoint rather than once per FOV.
  • Windows are clipped, not shifted, at the stack edge: with the focus at plane 19 of 86 the window is 0..58 instead of 0..59.

Testing

  • Full suite passes; new tests/test_project_settings.py and tests/test_cli/test_project_cli.py (max/mean/sum/slice against numpy, focus per fov and per timepoint with find_focus stubbed, parallel vs serial pre-pass, dropped-channel warning, config errors at init, configured chunks/shards, resume). Segment and track tests moved to Z=1 plates and gained dimensionality-mismatch cases.
  • nextflow lint passes on mantis-v2.nf and modules/project.nf.
  • Smoke run of biahub project --cluster debug with an earlier A549 config on one position of 2026_09_25_A549_PCNA_DENV_ZIKV (91 x 86 x 1664 x 1193): Z=1 float32 plate, focus plane 19 (per-timepoint 15..22, two blank frames fall back to the middle plane and stay zero).
  • The channel check script run against the raw stores of 2026_09_08_A549_PEX3_DENV_ZIKV and 2026_08_11_A549_SEC61B_DENV flags exactly the per-dataset edits (absent mCherry entry; BF vs BF - Oblique).

Not yet done: a pipeline run with --project_config through mantis-v2.nf, and a tracking benchmark of the projected input against the previous track-side window on the TrackEdit FOVs.

🤖 Generated with Claude Code

Add `biahub project`, which turns a 3D plate into a 2D (Z=1) plate with one
projection per output channel: max, mean, sum over a Z range or a window
around a plane, or one plane (`slice`). The plane may be fixed or the in-focus
plane found with the registration engine's focus criterion (FocusSettings
subclass: centre crop, NA, wavelength), once per position (median over T) or
per timepoint. Ranges are half-open like concatenate's Z_slice and relative
to `center` when one is set, so the A549 60-plane window is
`center: focus, range: [-20, 40]`. Unlisted input channels are dropped with a
warning. The focus plane of every timepoint is recorded in the output
position's `biahub-project` metadata.

Segment and track stop selecting and projecting Z-planes. Segment loses
`z_slice_2D`: a model without do_3D segments in 2D and needs a Z=1 input.
Track loses `z_slicing` and the focus window; `output_mode` is checked
against the input Z. Both raise, pointing at `biahub project`, when a 3D
input meets a 2D request. Old keys are rejected with a migration message.

Nextflow: a project step between assemble and track (`5-project`,
`6-track` for A549); track reads the projected plate when project runs.
The A549 project config reproduces the previous tracking input (mean over
the 60-plane focus window on Phase3D), measured on the 800x800 centre crop.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
ieivanov and others added 7 commits October 19, 2026 14:40
…ill checks it

The A549 projection config lists every channel of a typical assembled plate
under the pre-rename names project sees inside the pipeline: the in-focus
plane of BF and Phase3D, the full-stack max of the raw fluorescence channels,
and the mean of the virtual-stain predictions over the 60-plane focus window.
The focus is found on Phase3D per timepoint, as biahub#400 asks for inference.
The brightfield key is `BF`, matching reconstruct.yml; the fluorescence names
and an older `BF - Oblique` are per-dataset edits.

The reconstruct-with-nextflow check script also validates project.yml both
ways (a listed channel the plate lacks is a MISS, an assembled channel the
config omits is NOT PROJECTED) and track.yml against the projected plate. The
skill carries unprojected channels into the pre-run plan for the user to
decide, runs the rename on the projected plate too, and suggests the
`BF - Oblique` edit in both reconstruct.yml and project.yml when the raw
store names it so.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…4 accumulation

NumPy already accumulates safely (float64 for integer input, pairwise float32
for float32 input), so mean and sum no longer force a float64 temporary. The
output plate is float32 whenever a channel uses max, mean or sum -- float32 in
and out is the common case -- and keeps the input dtype only when every
channel is a slice.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The focus record under the output position's biahub-project metadata is
focus: {channel, per, z, z_per_t}; the focus_ prefix repeated the block name.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
`range` meant absolute planes without a center and offsets with one. The two
forms now have their own keys: `start`/`stop` are absolute, half-open like
concatenate's time_indices; `below`/`above` count planes around `center`,
selecting [center - below, center + above), so the A549 window is
`center: focus, below: 20, above: 40`. The validator refuses mixing them.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The projected store is a deliverable like the assembled plate: cleanup
removes only its slurm_output/ and .iohub-progress/, as the wiring already
did; say so in the comment.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… shards

ProjectionSettings takes the output chunk shape and shards ratio with
concatenate's names and semantics (shard = chunks * ratio, C not sharded) and
passes them to create_empty_plate; None keeps iohub's defaults.

The A549 config, following the Dynamic Cell Atlas array standard where a 2D
float32 plate can: one-frame 256 x 256 chunks, the grid the assembled and
tracking stores share, and shards of 16 timepoints by the full frame (the
standard's T-shard floor; ~150 MB each, 30 files per position instead of 400).
iohub writes one shard's timepoints per unit, so resume is 16 frames coarse.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The focus pre-pass ran the timepoints one after another while the job's
other workers idled; with per-timepoint focus on a long timelapse it was the
serial part of the step. The timepoints are independent, so with more than
one worker they now run in a spawned ProcessPoolExecutor sized by the job's
num_workers (the count the projection itself uses), each worker reading its
own volume. One worker keeps the in-process loop.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…>_proj.zarr

The projected plate is the 2D companion of the assembled plate, not a step
of its own: the pipeline now writes it to <N>-assemble/<DATASET>_proj.zarr,
so project has no step directory and track stays 5-track. Cleanup already
covers the shared directory's slurm_output/ and .iohub-progress/; the
slurm_output README notes that a directory can hold two steps' stores. The
skill docs, run template and config comments follow.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@ieivanov
ieivanov marked this pull request as ready for review October 19, 2026 23:48
@ieivanov

Copy link
Copy Markdown
Collaborator Author

@edyoshikun @tayllatheodoro it would be great if you can just quickly read the PR description and give it a thumbs up or let me know if you have any comments.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Output reuse and resume can compromise data correctness, while memory sizing and focus provenance also need correction.

4 open issues
What changed in this PR

Adds biahub project to create Z=1 companion plates for downstream analysis, moving projection out of segmentation and tracking.

Changes:

  • Adds per-channel projections, focus selection, configuration validation and tests.
  • Requires segment and track inputs to match their configured dimensionality.
  • Integrates projection into Nextflow and updates A549 configs and run guidance.
File Description
tests/​test_segment_settings.py Tests dimensionality and removed settings.
tests/​test_project_settings.py Tests projection schema and Z selection.
tests/​test_example_settings.py Validates updated example configs.
tests/​test_cli/​test_track_cli.py Tests projected inputs and dimensionality checks.
tests/​test_cli/​test_segment_cli.py Adapts CLI tests to Z=1 inputs.
tests/​test_cli/​test_project_cli.py Covers projections, focus, storage and resume.
tests/​test_cli/​test_cli.py Checks command registration.
tests/​test_cellpose_inputs.py Tests revised Cellpose input shapes.
settings/​example_track_settings.yml Removes tracking-side projection settings.
settings/​example_segmentation_settings.yml Documents required input dimensionality.
settings/​example_project_settings.yml Provides projection configuration examples.
README.md Lists the project command.
nextflow/​modules/​segment.nf Updates input documentation comments.
nextflow/​modules/​project.nf Adds projection initialization and execution.
nextflow/​modules/​common.nf Clarifies shared log-directory documentation.
nextflow/​mantis-v2.nf Wires projection before tracking.
nextflow/​configs/​a549/​track.yml Uses projected nuclei directly.
nextflow/​configs/​a549/​segment.yml Removes plane selection; documents projected inputs.
nextflow/​configs/​a549/​project.yml Defines A549 projections and storage layout.
biahub/​track.py Removes projection and checks dimensionality.
biahub/​settings.py Adds projection schemas and migration errors.
biahub/​segment.py Matches model dimensionality to input Z.
biahub/​project.py Implements projection CLI and processing.
biahub/​cli/​main.py Registers project.
.claude/​skills/​reconstruct-with-nextflow/​templates/​run_mantis_v2.sh Enables the optional projection stage.
.claude/​skills/​reconstruct-with-nextflow/​templates/​check_qc_channels.py Checks projection and tracking channel compatibility.
.claude/​skills/​reconstruct-with-nextflow/​SKILL.md Updates planning and execution guidance.
.claude/​skills/​reconstruct-with-nextflow/​references/​datasets.md Documents companion-store locations.
.claude/​skills/​reconstruct-with-nextflow/​references/​caveats.md Updates migration and configuration guidance.

Review effort: Balanced

Comment thread biahub/project.py Resolved
Comment thread biahub/project.py Resolved
Comment thread biahub/project.py Resolved
Comment thread biahub/project.py Resolved
ieivanov and others added 5 commits October 19, 2026 17:12
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
iohub reads one timepoint's (C_read, Z, Y, X) block per worker, so the
request must grow with the listed channels: the fixed ram_multiplier of 4
gave 4 GB/CPU whether a config read 2 channels or 6, and the A549 config
(6 channels, 3.8 GiB per read, ~5-6 GiB peak) would have hit the cgroup.
ram_multiplier is now len(read_indices) + 2 (the read, the window copy and
the shard's output buffer): 6 GB/CPU for A549, unchanged for 2 channels.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Follows c8f8e78, which dumps the focus settings (minus axes) into the
biahub-project focus record next to z and z_per_t.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Numeric correctness, focus metadata preservation, configuration round trips, and shard-aware memory sizing need correction.

No open issues 🎉

4 previously missed issues

In code that hasn't changed since last review

Medium severity Promote float16 inputs before reduction

biahub/​project.py:101

Promote float16 inputs before reducing them. biahub/stitch.py:425 writes float16 plates, and these reductions return float16 before the cast runs. Summing 86 planes at intensity 1000 overflows to infinity even though 86000 fits in the float32 output; mean also loses precision by rounding to float16 first. Set an explicit reduction dtype and add float16 coverage.

Medium severity Preserve focus metadata when reinitializing completed projections

biahub/​project.py:225

Re-running project --init on a completed focus-based projection replaces biahub-project with the settings dump, removing focus.z and focus.z_per_t while leaving the projected pixels intact. The existing provenance regression test (tests/test_cli/test_init_provenance.py:99–123) establishes that create_empty_plate refreshes its own extra metadata on existing positions. Preserve the per-position focus results when the configuration is unchanged, and add a regression test for initialization of a completed projection.

Medium severity Include time-shard buffers in projection RAM estimates

biahub/​project.py:416

Include time-shard output buffers in the RAM estimate. The request ignores shards_ratio[0], although projection batches a shard's timepoints across all output channels. For float32 data shaped (512, 6, 2, 4096, 4096) with 64-timepoint shards, the estimate requests 32 GiB total, while one output batch alone occupies 24 GiB. Concurrent batches can therefore exceed the allocation. Account for the effective output batch size and dtype, and limit workers to the available batches; concatenate already accounts for time batching in its resource estimate.

Medium severity Exclude internal axes field from ProjectionSettings serialization

biahub/​settings.py:411

axes is included in model_dump(), but reject_axes rejects it on input. Saving a focus-enabled ProjectionSettings with model_to_yaml() therefore produces a configuration that biahub project cannot reload. Exclude this fixed internal field from serialization while continuing to reject explicitly supplied axes.

4 resolved since last review

Review effort: Balanced

…ition

One position of 2026_08_11 SEC61B v8 (6 channels, 86 x 1664 x 1193 float32,
5 shard units busy) peaked at 22 GB max RSS / 28 GB over the process tree,
~5-6 GiB per worker against the 6 GB/CPU requested. +4 volumes requests
7 GB/CPU there, a margin for a timelapse that keeps all 8 workers busy. The
time request (70 min for a 3.6 min run) is left as is.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
ieivanov added a commit that referenced this pull request Oct 20, 2026
…k reads

With `biahub project` (#424) 2D tracking reads the projected (Z=1) plate, so
the labels, tracks.geff and the tracks CSV are written into each position of
that plate, and the label image takes the plate's Z. The plane-placement code
(tracked_z_window, write_tracking_labels' z window, the z_window/z_index
provenance) goes away; 3D tracking without project writes into the assembled
plate as before.

The sibling filter (#415) runs before the GEFF export, which now passes the
filtered tracks table to ultrack's `to_geff(tracks_df=...)`
(royerlab/ultrack#290, pinned to the ieivanov fork until it merges), so the
GEFF, the labels and the CSV agree.

Nextflow: track reads and writes the projected plate when project runs; the
instance-count QC moves from qc.yaml to a new --qc_project_config
(a549/qc_project.yaml) on the projected plate, planned after track's init and
computed after tracking; qc.yaml is pixel metrics on the assembled store again.
The skill's check script and docs follow.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@ieivanov
ieivanov added this pull request to stack #429 October 21, 2026 00:00
@ieivanov
ieivanov requested a review from aofei-liu October 21, 2026 23:18
@aofei-liu

aofei-liu commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator

hi! thanks for tagging me! Here's a few things I caught comparing stuff to the specs:

  • not an issue at the moment, but the max setting currently writes as float32 by default, while the spec requires that the projection match the source store. not an issue for the pipeline because the source store is already float32, but maybe match dtypes instead of hardcoding float32?
  • i think we name all our stores with the suffix .ome.zarr and stores named with .zarr are implicitly passed for projection stores. i think this can either be a spec-side fix to also check stores with .zarr, or a suffix swap for stores here to be with the ome.zarr suffix. we can discuss on the PR on dynamic-cell-atlas-specs with mikala how to resolve this
  • i think currently when a focus plane is not found the center slice is recorded and the plane is recorded as not found. the spec doesn't allow for a null rn; we probably also want to fix it on that end.
  • this is a non issue if you use the nextflow version of the pipelines here (since it currently does not do this), but I think biahub's CLI technically allows you to select/project a subset of the FOVs. if the subset projection is paired with the non-subsetted store, it will fail the check on the specs that the projection matches the source.

that's all i caught for now. I'll tag you on the dca specs store as well!

@ieivanov

Copy link
Copy Markdown
Collaborator Author

@aofei-liu very helpful, thank you! I'll implement the max/float32 fix. I agree we can fix the rest on either end, depending on what makes most sense.

run_project asked for its init estimate verbatim on every retry, so a low
estimate failed all attempts with the same 137. Use retry_memory like the other
SLURM steps (fix/nextflow-retry-memory-cap carries the 244 GB cap).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@aofei-liu

Copy link
Copy Markdown
Collaborator

yeah sounds good! looks like you already pushed the fix, so hopefully we hear back on the PR in dca specs from mikala on which side to resolve the .zarr naming thing.

oh and maybe one more check that would be good to make sure you can fulfil is the shard > 1GB when array > 1GB requirement, Idk if 16 timepoints / 60 timepoints will be an issue for that check (i'd pin the validator to v0.2.10 for your checks)

ieivanov and others added 2 commits October 23, 2026 13:59
… float32

max picks an existing voxel, so promoting a max-only plate to float32
doubled its storage for nothing and would truncate uint32 labels above
2^24. A store has one dtype, so a plate with any mean/sum channel is
still float32 throughout and its max/slice channels are widened on write.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@ieivanov
ieivanov merged commit 8ee91c5 into main Oct 23, 2026
7 checks passed
@ieivanov
ieivanov deleted the feat/project-cli branch October 24, 2026 00:49
@tayllatheodoro

Copy link
Copy Markdown
Collaborator

For the record on the A549 Z projection in project.yml (mean over the 60-plane window around the Phase3D focus): we benchmarked the alternatives on our annotated A549 data, and the window mean is the right default. All rows use the same template track.yml (cellpose cpsam_v2 + ultrack + min_sibling_length: 3).

2026_04_28 (4 TrackEdit FOVs, 78 divisions; division F1, matched within 2 frames / 10 um):

projection all FOVs mock DENV predicted divisions tracks (GT 287)
window mean (this config) 0.67 0.69 0.64 104 378
window max 0.65 0.68 0.59 104 385
all planes, mean 0.63 0.65 0.58 107 396
all planes, max 0.51 0.56 0.45 139 532

2026_04_21 (5 DENV FOVs, 38 divisions from mitosis labels):

projection mitotic cells detected real divisions found predicted divisions tracks
window mean 0.95 19 81 388
window max 0.93 20 92 445
all planes, mean 0.95 19 92 422
all planes, max 0.90 20 131 643

2026_08_11 v8 (4 FOVs, no annotations, counts): max adds divisions and tracks in the infected wells (DENV divisions: window mean 91, window max 135, all-planes max 156).

  • Max is worst in infected wells: it takes the brightest value along Z, so every out-of-focus "ghost" or hallucinated VS structure becomes a full-strength object. A visual check on 08_11 agreed: the window mean shows the fewest ghost structures, all-planes max the most.
  • Window size (track-side window, mean, 2026-10-09): 40 planes scored higher on 04_28 (whose annotations were curated from a 40-plane run) but lost mitotic cells that drift in Z on independent 04_21 data (0.89 vs 0.95); 60 keeps them; 70 is no better.
  • Focus per timepoint vs per FOV (this PR's projection): equivalent on 04_28 (F1 0.67 vs 0.69); per timepoint recovers mitotic detection on 04_21 (0.95 vs 0.92), possibly because windows are clipped at the stack edge (focus near plane 17 leaves 57 planes) and the per-timepoint focus shifts with the cells.

ieivanov added a commit that referenced this pull request Oct 26, 2026
main moved segmentation out of track (#413: `biahub segment` writes labels/<model>
into the plate; track reads `labels:` and writes labels/tracks_<labels>, tracks.geff
and the CSV into it) and Z projection into `biahub project` (#424), and added
pyramids (#430). The trackers of this PR are reworked on top of that:

- tracksdata, hoct and trackastra link the instance labels of `labels:` (the
  default segmentation_method: labels) instead of running cellpose in track;
  foreground_contour and output_mode 3D are refused for them.
- hoct and trackastra read the image the labels were segmented from: the first
  channel `biahub segment` recorded in the label image's biahub-segment
  provenance, or hoct_config/trackastra_config.image_channel when set (override,
  or for a label image segment did not write). --init checks it exists.
- Their outputs follow #413: labels/<tracked_label> (5D) and the CSV. They write
  no tracks.geff yet (ultrack's export reads its own database; #441) and remove a
  stale one from an earlier run.
- hoct and trackastra request a GPU when biahub submits them; ultrack and
  tracksdata stay on the CPU partition.
- pyproject: main's track extra plus tracksdata (git), hoct and trackastra[ilp],
  with the gurobipy fork by Python version; uv.lock regenerated from main's.
- Tests and the track-with-biahub skill moved to labels written into the plate
  (project -> segment -> one track run per tracker, side by side by output_label).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
tayllatheodoro added a commit that referenced this pull request Nov 10, 2026
…the mem_nuc_contour key (#466)

debug_track.py failed at import: resolve_z_slice was removed in #424, and the
script also used z_range, the old run_ultrack signature, hardcoded dataset
paths and the stale function key biahub.cli.track.mem_nuc_contour.

The script now reads a biahub track config (-c) and one position (-i), tracks
that FOV in memory the way biahub track does (labels or foreground+contour for
ultrack; tracksdata/hoct/trackastra on the segment labels), and opens napari.
Nothing is written into the plate.

The commented example in settings/example_track_settings.yml used the same
stale key; it is now biahub.track.mem_nuc_contour.

Closes #458
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DCA: add a MIP (maximum intensity projection) companion store

4 participants