Detector geometry correction

Experimental. This feature is under active development. Behavior may change between releases.

Define multi-panel detector layouts (chip offsets and rotations) so that centerfinding and refinement operate in corrected panel coordinates. Geometry correction is only active when [DetectorGeometry] is present in the dataset .ini and enabled = true; otherwise COSEDA treats the detector as a single flat panel.

There is no GUI for this feature yet — define it by editing the .ini file directly.

Conceptual model

COSEDA uses a static detector reference at raw pixel (0,0):

  • Pixel-level features (e.g. peak positions) are stored in raw detector pixels.

  • Detector-level features (e.g. beam center) are defined in the detector reference frame tied to raw (0,0).

  • Panel geometry corrects pixel positions based on which panel/chip they belong to.

This lets preprocessing work in raw coordinates while enabling panel-aware corrections where needed (viewer, centerfinding/refinement internals, CrystFEL geometry export).

Reference chain

raw pixel panel correction corrected detector pixel beam-center reference lab/scattering coordinates

In practice:

  1. Start from raw pixel coordinates (x_raw, y_raw).

  2. Find which panel contains the pixel.

  3. Apply panel offset/rotation to get corrected detector coordinates.

  4. Optionally apply a global in-plane transform.

  5. Use beam center and camera geometry to derive scattering quantities.

INI definition

Add an optional [DetectorGeometry] section to the dataset INI:

[DetectorGeometry]
version = 1
enabled = true

; Coordinate convention (metadata only)
pixel_convention = center            ; center|corner
raw_origin = bottom_left
raw_x_direction = +right
raw_y_direction = +up
raw_bounds_inclusive = true

; Panel IDs (explicit list)
panels = p0000,p0100,p0001,p0101

; Units and matrix conventions (metadata only)
offset_units = pixel
matrix_order = a11,a12,a21,a22

; Optional global detector in-plane transform
global_offset = 0.0,0.0              ; pixels
global_A = 1.0,0.0,0.0,1.0

; -------- Panel definitions --------
p0000_raw_min = 0,0
p0000_raw_max = 255,255
; p0000_offset omitted -> defaults to 0,0
; p0000_A omitted -> defaults to identity

p0100_raw_min = 256,0
p0100_raw_max = 511,255
p0100_offset = 1.20,0.10
p0100_A = 0.999999,-0.0012,0.0012,0.999999

p0001_raw_min = 0,256
p0001_raw_max = 255,511
p0001_offset = 0.20,1.45
p0001_A = 0.999998,-0.0018,0.0018,0.999998

p0101_raw_min = 256,256
p0101_raw_max = 511,511
p0101_offset = 1.35,1.55
p0101_A = 0.999997,-0.0022,0.0022,0.999997

Notes

  • Panel IDs are free strings; p0000/p0100/... is valid and recommended if kept stable.

  • <panel>_offset and <panel>_A are optional — defaults are 0,0 and identity.

  • Keys are case-insensitive in INI format (e.g. p0000_A and p0000_a are equivalent).

  • Keys actively read by the implementation:

    • enabled, panels

    • global_offset, global_A

    • <panel>_raw_min, <panel>_raw_max, <panel>_offset, <panel>_A

  • The convention keys (pixel_convention, raw_origin, directions, etc.) are stored as metadata only and are not used in calculations.

Applied equations

For a raw point r = [x_raw, y_raw]ᵀ in panel i:

  • r_min_i = [raw_min_x_i, raw_min_y_i]ᵀ

  • o_i = [offset_x_i, offset_y_i]ᵀ

  • A_i = [[a11, a12], [a21, a22]]

Panel-corrected local detector coordinates:

p_local = r_min_i + o_i + A_i * (r - r_min_i)

Optional global in-plane transform:

p_global = global_offset + global_A * p_local

Points not covered by any panel pass through unchanged (identity mapping).

Required additional metadata

The following metadata must be present in the dataset for geometry-aware processing to work correctly:

  • Per-frame centers in HDF5: entry/data/center_x, entry/data/center_y

  • Pixel scale: pixels_per_meter (in [AcquisitionDetails])

  • For CrystFEL export: camera_length, camera_length_correction, acceleration_voltage, adu_per_photon