# 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: ```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. - `_offset` and `_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` - `_raw_min`, `_raw_max`, `_offset`, `_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`