Skip to content

aedes_flytable_update(): selective write, NA root_duplicated, return changed rows - #11

Merged
jefferis merged 4 commits into
mainfrom
fix/flytable-update-selective-write
Aug 9, 2026
Merged

aedes_flytable_update(): selective write, NA root_duplicated, return changed rows#11
jefferis merged 4 commits into
mainfrom
fix/flytable-update-selective-write

Conversation

@jefferis

@jefferis jefferis commented Aug 9, 2026

Copy link
Copy Markdown
Member

Three related fixes to aedes_flytable_update(), found while porting this function to crantr (crant_seatable_update).

1. Only write columns that can change

The change set is computed correctly (diffing across all read columns), but the write step pushed back the whole changed row. This function only ever changes root_id, supervoxel_id and root_duplicated; point_xyz and status are read (to resolve supervoxels / compute good_status) but never modified, yet were rewritten with identical values on every touched row — including the human-curated status column. Fix narrows the payload:

mutable <- intersect(c("_id", "root_id", "supervoxel_id", "root_duplicated"),
                     names(updated))

intersect(..., names(updated)) keeps the update_dups = FALSE path correct (no root_duplicated there).

2. Treat NA root_duplicated as FALSE in the diff

The scheduled Python updater only ever sets root_duplicated to TRUE, so unchecked rows read back as NA. Diffing NA against the freshly computed logical column flagged every not-duplicated row as changed. Coerce the stored column NA -> FALSE before diffing:

rd <- as.logical(cands$root_duplicated)
rd[is.na(rd)] <- FALSE
cands$root_duplicated <- rd

Only genuine transitions (-> TRUE, or TRUE -> FALSE) are written.

3. Return what would be written

Previously returned invisible(TRUE) / invisible(FALSE). Now returns, invisibly, a list capturing both write streams so nothing is hidden:

list(updated    = toupdate,        # _id, root_id, supervoxel_id, root_duplicated (changed rows)
     serial_ids = serial_toupdate) # _id + newly assigned serial_id, or NULL

serial_ids is NULL unless serial ids were (or, under dry_run, would be) assigned — i.e. NULL in the default update.serial_ids = FALSE path. The serial_id block no longer early-returns, so the list is returned on every path.

Note: this changes the return contract (logical → list). @return doc and .Rd updated. Scripted callers branching on a truthy/FALSE return should switch to e.g. nrow(res$updated) > 0.

All internal-only; no signature changes.

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com

The change-detection diff runs across all read columns, but the update
wrote back the whole changed row -- so any row flagged for a root_id,
supervoxel_id or root_duplicated change also rewrote its status and
point_xyz cells with identical values. Narrow the write payload to
_id, root_id, supervoxel_id, root_duplicated so the human-curated
status column (and point_xyz) is never touched by this function.
Unchecked checkbox cells read back as NA, so comparing the stored
root_duplicated column against the freshly computed logical column
flagged every not-duplicated row as changed (NA vs FALSE). Coerce the
stored column NA->FALSE before diffing so only genuine transitions
(->TRUE, or TRUE->FALSE) are written.
@jefferis jefferis changed the title aedes_flytable_update(): only write columns that can change aedes_flytable_update(): selective write + NA root_duplicated handling Aug 9, 2026
Backported from crantr's crant_seatable_update(): capture the narrowed
update payload as `toupdate` and return it invisibly so callers (and
dry runs) can inspect exactly which rows/cells would change. The
serial_id block no longer early-returns FALSE, so the data frame is
returned on every path.
@jefferis jefferis changed the title aedes_flytable_update(): selective write + NA root_duplicated handling aedes_flytable_update(): selective write, NA root_duplicated, return changed rows Aug 9, 2026
Return an invisible list(updated=, serial_ids=) instead of just the
main changed-rows data frame, so the separate serial_id write stream
is no longer hidden from the return value. serial_ids is NULL unless
serial ids were (or would be) assigned.
@jefferis
jefferis merged commit 7bda6d7 into main Aug 9, 2026
2 checks passed
@jefferis
jefferis deleted the fix/flytable-update-selective-write branch August 9, 2026 10:12
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.

1 participant