Skip to content

Center image pixels on their Sigima coordinates - #73

Merged
PierreRaybaut merged 3 commits into
developfrom
fix/image-viewer-pixel-centers
Oct 25, 2026
Merged

PierreRaybaut merged 3 commits into
developfrom
fix/image-viewer-pixel-centers

Conversation

@PierreRaybaut

Copy link
Copy Markdown
Contributor

Closes #69

Summary

Sigima and DataLab desktop define x0/y0 as the center of the first pixel (axis_to_physical(i) = x0 + i·dx), but the image viewers drew the first pixel from x0/y0 as its upper-left corner. Everything shown in physical coordinates (ROIs, analysis results, crosshair, stats rectangle, hover read-out) was therefore half a pixel off the pixels used by the computations. Example of the issue: a 4×4 image with x0 = y0 = 0 now spans [-0.5, 3.5] with pixel centers at 0…3.

  • Shared axis helpers (src/utils/pixelCenters.ts): axisToFloatIndex / axisToPhysical mirror Sigima's axis_to_float_indices / axis_to_physical (extrapolation included), plus pixelEdges, imageExtent, imageCenter (Sigima xc/yc), pixelIndexAt and pixelRangeOverlapping, for uniform and non-uniform images. No other code converts between pixels and physical coordinates on its own anymore.
  • Raster geometry (imageLod.ts, imageRaster.ts): ImageGeometry.x0/y0 are pixel centers; the bitmap starts at x0 + (i0 − ½)·dx. The placement fields are renamed x/y (Plotly layout-image names) to avoid the center/corner confusion, and a single rasterLayoutImage helper replaces three copies.
  • Image viewer: extent, hover value (closest pixel center), cross-sections (index, abscissae, axis ranges) and stats. Cross-sections and stats now also work on non-uniform images; stats keep DataLab desktop's rule (every pixel the rectangle covers, even partly), now based on the real pixel edges.
  • Spatial and thumbnail views, processing preview: extent and hover read-out likewise (non-uniform images included in the spatial hover).
  • Default ROIs / erase area / ROI panel bounds: centered on the pixel grid of the image.
  • ROI grid preview: the TypeScript replica had not followed Sigima 1.4 (grid laid out from x0, no pixel snapping). It now matches generate_image_grid_roi (grid over the outer pixel edges, whole-pixel cells, empty cells kept), and a zero translation is no longer read as the default.
  • Decimated payloads (spatial view, processing preview source): x0' = x0 + (dx' − dx)/2 keeps the exact physical extent, so previews overlay the full-resolution image exactly.
  • binSearchCell is removed (replaced by pixelIndexAt), along with its tests, which were ported to the new helpers.
  • Changelog entry.

Out of scope: Distribute on grid / Reset positions keep the desktop behavior (they align first-pixel centers). The profile dialog already followed the convention (#70).

Validation

  • vitest: 931 passed. New tests cover the helpers (issue example, calibrated and non-uniform images), LOD placement, ImagePlot (bitmap placement, hover value, stats, non-uniform cross-section), the spatial-view hover, and the ROI grid preview against reference values computed with Sigima. The new ImagePlot tests fail on develop.
  • pytest: 530 passed (the decimation test now asserts the exact outer edges); ruff clean.
  • tsc, eslint, prettier clean; npm run build within the bundle budget.
  • Playwright (chromium, Sigima 1.4 wheel built from 3af8228): image-lod, multi-image-spatial, image-roi-drag, image-pan (9 passed).
  • Browser check on the issue's 4×4 example: the bitmap spans [-0.5, 3.5], a ROI [-0.5, 1.5] lands on pixel edges, and hovering (0.6, 0.4) reads pixel (1, 0).

Note: small images are drawn smoothed by the browser when zoomed in (no image-rendering: pixelated on the main viewer's layout image, unlike the thumbnails). This existed before this PR and is not changed here.

Sigima and DataLab desktop define x0/y0 as the center of the first
pixel, but the image viewers drew it from x0/y0 as its upper-left
corner, so everything shown in physical coordinates (ROIs, analysis
results, crosshair, stats rectangle) was half a pixel off the pixels
used by the computations.

- shared axis helpers (pixelCenters.ts) mirroring Sigima's
  axis_to_float_indices / axis_to_physical, with pixel edges, image
  extent and center, pixel lookup and covered pixel ranges, for uniform
  and non-uniform images;
- the LOD raster geometry follows the pixel-center convention; the
  bitmap placement is named after Plotly's layout-image x/y and shared
  by the single-image, spatial and processing preview plots;
- image viewer: extent, hover value, cross-sections and stats use the
  helpers (cross-sections and stats now also work on non-uniform
  images; stats keep the covered-pixel rule of DataLab desktop);
- spatial and thumbnail views: extent and hover read-out likewise;
- default ROIs, erase area and ROI panel bounds use the image extent
  and the center of its pixel grid;
- decimated image payloads keep the exact physical extent of the image.

Refs #69

Assisted-by: Claude Opus 5.5
The live preview of "Create ROI grid..." replicated the former
generate_image_grid_roi, laid out from x0 (the first pixel center) and
not snapped to pixels, so it no longer matched the regions of interest
created by Sigima 1.4. The replica now lays the grid over the outer
edges of the pixels (bin edges for non-uniform images), makes each cell
of the pixels whose centers lie in it and draws each rectangle to the
outer edges of its pixels; empty cells are kept, as in Sigima, and a
zero translation is no longer read as the default.

The new test checks the preview against reference values computed with
Sigima.

Refs #69

Assisted-by: Claude Opus 5.5
@PierreRaybaut
PierreRaybaut merged commit 992f423 into develop Oct 25, 2026
9 checks passed
@PierreRaybaut
PierreRaybaut deleted the fix/image-viewer-pixel-centers branch October 25, 2026 14:59
@PierreRaybaut
PierreRaybaut restored the fix/image-viewer-pixel-centers branch October 25, 2026 15:02
@PierreRaybaut
PierreRaybaut deleted the fix/image-viewer-pixel-centers branch October 25, 2026 15:02
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.

Image viewer: pixels drawn half a pixel off Sigima coordinates (x0 = corner instead of pixel center)

1 participant