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 transformation submenu 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 / XYZCalibrateParam so 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-selected
target_unit: User-selected from category
custom_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_1 in both SignalProcessor and ImageProcessor
- Add to
Processing > Axis transformation submenu
- 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
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_FACTORS in sigima/objects/signal/constants.py and FreqUnits in sigima/objects/signal/creation.py could 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)
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:a*x + b) via the existing calibration dialogThis two-step workflow is error-prone and unintuitive. A dedicated unit conversion feature would streamline this into a single operation.
Scope
In scope
Processing > Axis transformationsubmenu for both Signal and Image panelsXYCalibrateParam/XYZCalibrateParamso that calibration also updates the unit stringOut of scope
Proposed Implementation
Architecture
The implementation follows the standard DataLab/Sigima pattern:
sigima.proc): Computation function + parameter classSigima: Unit conversion engine
New module:
sigima/proc/common/units.py(or extend existing calibration modules)Parameter class:
ConvertUnitsParamaxis: 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) → dst1e7 / x)DataLab: Registration
1_to_1in bothSignalProcessorandImageProcessorProcessing > Axis transformationsubmenuUX Flow
Processing > Axis transformation > Convert units...xunit/yunit/zunitAcceptance Criteria
Processing > Axis transformationfor both Signal and Image panels_()wrapped)Technical Notes
source_factor / target_factorwavenumber_cm⁻¹ = 1e7 / wavelength_nm). This also reverses the X-axis ordering.TIME_UNIT_FACTORSinsigima/objects/signal/constants.pyandFreqUnitsinsigima/objects/signal/creation.pycould be consolidated into the new unit registry."s"→"Hz")Related Existing Features
Processing > Axis transformation > Linear calibration...)"s" ↔ "Hz")