-
Notifications
You must be signed in to change notification settings - Fork 11
Description
Summary
Add a unit conversion feature allowing users to convert axis units on signals (X/Y) and images (X/Y/Z) through a dedicated dialog with predefined unit categories and custom conversion support.
Motivation
Currently, DataLab stores axis units as free-form strings (xunit, yunit, zunit) with no semantic meaning. When users need to convert units (e.g., wavelength from nm to µm, time from s to ms), they must:
- Manually apply a calibration (
a*x + b) via the existing calibration dialog - Separately edit the unit string through the object properties editor
This two-step workflow is error-prone and unintuitive. A dedicated unit conversion feature would streamline this into a single operation.
Scope
In scope
- New "Convert units..." action in the
Processing > Axis transformationsubmenu for both Signal and Image panels - Conversion dialog with:
- Axis selector (X, Y for signals; X, Y, Z for images)
- Predefined unit categories with conversion factors (see below)
- Custom conversion mode (user-defined factor and target unit string)
- Preview of the conversion factor to be applied
- Predefined unit categories:
- Length: nm, µm, mm, cm, m, km, in, ft
- Time: ns, µs, ms, s, min, h
- Frequency: Hz, kHz, MHz, GHz, THz
- Wavelength/Energy (spectroscopy): nm ↔ µm ↔ cm⁻¹ ↔ eV ↔ THz
- Angle: rad, deg, mrad
- Automatic data scaling: Multiply/divide axis data by the appropriate conversion factor
- Automatic unit string update: Replace the unit string on the target axis
- (Optional) Enhance existing calibration dialog: Add "source unit" / "target unit" fields to
XYCalibrateParam/XYZCalibrateParamso that calibration also updates the unit string
Out of scope
- Integration with external unit libraries (pint, astropy.units)
- Automatic unit propagation across all processing functions
- Dimensional analysis or unit compatibility checks on operations
- Unit-aware arithmetic (e.g., warning when adding signals with different units)
Proposed Implementation
Architecture
The implementation follows the standard DataLab/Sigima pattern:
- Sigima layer (
sigima.proc): Computation function + parameter class - DataLab layer: Processor registration + menu action
Sigima: Unit conversion engine
New module: sigima/proc/common/units.py (or extend existing calibration modules)
# Unit registry: category → {unit_name: factor_to_base_unit}
UNIT_CATEGORIES = {
"Length": {"nm": 1e-9, "µm": 1e-6, "mm": 1e-3, "cm": 1e-2, "m": 1.0, "km": 1e3, "in": 0.0254, "ft": 0.3048},
"Time": {"ns": 1e-9, "µs": 1e-6, "ms": 1e-3, "s": 1.0, "min": 60.0, "h": 3600.0},
"Frequency": {"Hz": 1.0, "kHz": 1e3, "MHz": 1e6, "GHz": 1e9, "THz": 1e12},
"Angle": {"rad": 1.0, "deg": 0.017453292519943, "mrad": 1e-3},
# Spectroscopy: non-linear conversions handled separately
}Parameter class: ConvertUnitsParam
axis: Choice (X / Y / Z)category: Choice (Length / Time / Frequency / Angle / Spectroscopy / Custom)source_unit: Auto-detected from current object or user-selectedtarget_unit: User-selected from categorycustom_factor: Float (only for Custom mode)custom_unit: String (only for Custom mode)
Computation function: convert_units(src, p) → dst
- Computes conversion factor from source → target
- Scales axis data accordingly
- Updates unit string on the result object
- Handles spectroscopy non-linear conversions (e.g., nm → cm⁻¹ requires
1e7 / x)
DataLab: Registration
- Register as
1_to_1in bothSignalProcessorandImageProcessor - Add to
Processing > Axis transformationsubmenu - Icon: existing or new unit-related icon
UX Flow
- User selects one or more signal/image objects
Processing > Axis transformation > Convert units...- Dialog opens:
- Axis: X / Y (or X / Y / Z for images)
- Current unit is auto-filled from the object's
xunit/yunit/zunit - Category dropdown → filters available source/target units
- If current unit matches a known unit → auto-selects category and source
- If not → defaults to "Custom" mode
- Target unit dropdown (filtered by category)
- Preview: shows the conversion factor (e.g., "×1000" or "÷1e-6")
- User confirms → conversion applied to all selected objects (1-to-1 pattern)
Acceptance Criteria
- "Convert units..." action available in
Processing > Axis transformationfor both Signal and Image panels - Predefined conversions work correctly for all listed unit categories (linear)
- Spectroscopy conversions (non-linear: nm ↔ cm⁻¹ ↔ eV) work correctly
- Custom conversion mode allows arbitrary factor + unit string
- Unit string is automatically updated on the converted axis
- Current unit is auto-detected and pre-filled in the dialog
- Works with multi-object selection (applied independently to each, 1-to-1 pattern)
- Uncertainties (dx/dy) are scaled appropriately when present
- Unit tests cover all predefined categories and edge cases
- UI strings are internationalized (
_()wrapped) - French translations provided
Technical Notes
- For linear conversions (most categories), the factor is simply
source_factor / target_factor - For spectroscopy (wavelength ↔ wavenumber ↔ energy ↔ frequency), conversions are non-linear and require transforming the data values (e.g.,
wavenumber_cm⁻¹ = 1e7 / wavelength_nm). This also reverses the X-axis ordering. - The existing
TIME_UNIT_FACTORSinsigima/objects/signal/constants.pyandFreqUnitsinsigima/objects/signal/creation.pycould be consolidated into the new unit registry. - Consider reusing the same unit registry for the FFT/IFFT unit propagation (currently hardcoded
"s"→"Hz")
Related Existing Features
- Linear calibration (
Processing > Axis transformation > Linear calibration...) - Polynomial calibration (Image panel)
- FFT/IFFT automatic unit swapping (
"s" ↔ "Hz") - Transpose (swaps X/Y units)