--- source_files: - Common/DTS.Common.DAS.Concepts/Test/Module/RecordingMode.cs - Common/DTS.Common.DAS.Concepts/Test/Module/TiltAxes.cs generated_at: "2026-04-16T02:05:00.800450+00:00" model: "Qwen/Qwen3-Coder-Next-FP8" schema_version: 1 sha256: "d40daed59089dfb4" --- # Module ## Documentation: `DTS.Common.DAS.Concepts.Test.Module` --- ### 1. Purpose This module provides utility types and methods for handling tilt sensor configuration and computation within the DTS DAS (Data Acquisition System) framework. It encapsulates domain-specific concepts such as axis labeling, polarity inversion, mounting offsets, and calibration-aware conversion of raw ADC values to tilt angles in degrees. The module supports dynamic axis ordering (e.g., `IXYIZ`, `ZYX`) and ignored axes, enabling flexible tilt sensor mounting configurations. It also includes string ↔ enumeration conversion helpers and core tilt calculation logic used in calibration and real-time data processing. --- ### 2. Public Interface All public members reside within the nested `Test.Module` class. #### **`GetRecordingModeFromString(string recordingMode)`** ```csharp public static DFConstantsAndEnums.RecordingMode GetRecordingModeFromString(string recordingMode) ``` - **Behavior**: Parses the input string into a `DFConstantsAndEnums.RecordingMode` enum value using `Enum.Parse`. Throws an `Exception` (wrapping the original) if parsing fails or input is `null`. #### **`TiltAxis` class** ```csharp public class TiltAxis { public int AxisNumber { get; set; } public double CurrentTilt { get; set; } public string Label { get; set; } public int Inversion { get; set; } = 1; public bool IsIgnored { get; set; } = false; public double MountedOffset { get; set; } = 0.0; public double TargetOffset { get; set; } = 0.0; } ``` - **Purpose**: Represents a single tilt sensor axis configuration. Properties define axis identity, current measurement, label (`X`, `Y`, `Z`), inversion factor (`+1` or `-1`), ignore flag, and offset values (in degrees). #### **`TiltAxesHelper` class** ```csharp public class TiltAxesHelper { public Dictionary AxisConfigurations { get; set; } public TiltAxis AxisOne { get; set; } public TiltAxis AxisTwo { get; set; } public double LevelTolerance { get; set; } = 0.5; public TiltAxesHelper(); public TiltAxesHelper(string TiltAxes, double MountOffsetAxisOne, double MountOffsetAxisTwo, double TargetAxisOne, double TargetAxisTwo, double LevelTolerance, int AxisIgnored, bool UseForTiltCalculation); public string AxesToString(); } ``` - **Behavior**: - Default constructor initializes `AxisConfigurations` with keys `1`, `2`, `3`, each containing a new `TiltAxis`. - Parameterized constructor parses a `TiltAxes` string (e.g., `"IXIYIZ"`) to populate `AxisConfigurations[i].Label` and `Inversion`, sets `IsIgnored` for the specified axis, and assigns `AxisOne`/`AxisTwo` references to the *non-ignored* axes. - **Bug Note**: In the constructor, `AxisOne = AxisConfigurations[2];` is assigned twice when `AxisIgnored == 2` (should likely be `AxisTwo = AxisConfigurations[3];`). - `AxesToString()`: Reconstructs the orientation string from `AxisConfigurations` (e.g., `"IXIYIZ"` → `"IXIYIZ"`). #### **`TiltAxesSimple` enum** ```csharp public enum TiltAxesSimple { XYZ = 0, XZY = 1, YXZ = 2, YZX = 3, ZXY = 4, ZYX = 5 } ``` - Represents the simplified axis ordering (ignoring inversion markers `I`). #### **`SimplifyTiltAxes(TiltAxes axes)`** ```csharp public static TiltAxesSimple SimplifyTiltAxes(TiltAxes axes) ``` - **Behavior**: Strips `I` characters from `axes.ToString()` and parses the result into `TiltAxesSimple`. #### **`GetTiltAxesFromString(string tiltAxes)`** ```csharp public static TiltAxes GetTiltAxesFromString(string tiltAxes) ``` - **Behavior**: Parses the input string into a `TiltAxes` enum value using `Enum.Parse`. Throws an `Exception` (wrapping the original) on failure. #### **`GetPolaritiesFromTiltAxes(TiltAxes ta)`** ```csharp public static int[] GetPolaritiesFromTiltAxes(TiltAxes ta) ``` - **Behavior**: Returns an array of `+1` or `-1` for each axis, where `-1` corresponds to an `I` (inverted) axis in the `TiltAxes` string. #### **`GetBoolPolaritiesFromTiltAxes(TiltAxes tiltAxes)`** ```csharp public static bool[] GetBoolPolaritiesFromTiltAxes(TiltAxes tiltAxes) ``` - **Behavior**: Returns a `bool[3]` where `true` indicates an inverted axis (`I`), `false` indicates non-inverted (`P`). Iterates over the string representation, setting `rv[ax] = true` when encountering `'I'`, and increments `ax` only on non-`I` characters. #### **`TiltSensorCalAttributes` enum** ```csharp public enum TiltSensorCalAttributes { TILTSENSOR_CAL_1_GainAxis1 = 0, TILTSENSOR_CAL_2_ZeroAxis1 = 1, TILTSENSOR_CAL_3_ZeroDomAxis2PosAxis1 = 2, TILTSENSOR_CAL_4_ZeroDomAxis2NegAxis1 = 3, TILTSENSOR_CAL_5_ZeroDomAxis3PosAxis1 = 4, TILTSENSOR_CAL_6_ZeroDomAxis3NegAxis1 = 5, TILTSENSOR_CAL_7_GainAxis2 = 6, TILTSENSOR_CAL_8_ZeroAxis2 = 7, TILTSENSOR_CAL_9_ZeroDomAxis1PosAxis2 = 8, TILTSENSOR_CAL_10_ZeroDomAxis1NegAxis2 = 9, TILTSENSOR_CAL_11_ZeroDomAxis3PosAxis2 = 10, TILTSENSOR_CAL_12_ZeroDomAxis3NegAxis2 = 11, TILTSENSOR_CAL_13_GainAxis3 = 12, TILTSENSOR_CAL_14_ZeroAxis3 = 13, TILTSENSOR_CAL_15_ZeroDomAxis1PosAxis3 = 14, TILTSENSOR_CAL_16_ZeroDomAxis1NegAxis3 = 15, TILTSENSOR_CAL_17_ZeroDomAxis2PosAxis3 = 16, TILTSENSOR_CAL_18_ZeroDomAxis3NegAxis3 = 17, } ``` - Defines indices into the `tiltSensorCals` array for calibration parameters. #### **`GetTiltDegreesEU(...)` overloads** ```csharp public static double[] GetTiltDegreesEU(short[] tiltSensorADC, double[] tiltSensorCals); public static double[] GetTiltDegreesEU(short[] tiltSensorADC, double[] tiltSensorCals, TiltAxes axes, int ignoredAxis, float[] mountOffsetAxis); ``` - **Behavior**: Converts raw ADC values (`tiltSensorADC`, length ≥ 3) to tilt angles (degrees) using calibration data (`tiltSensorCals`, length ≥ 18). Returns a `double[3]` where the ignored axis is `double.NaN`, and the other two axes are computed and rounded to 3 decimal places (via `SIGNIFICANT_DIGITS = 1000`). - Uses `GetDominantTiltAxis`, `GetTiltGains`, `GetTiltZeroData`, and axis-specific scaling factors (`xFactor`, `yFactor`, `zFactor`) derived from `axes`. - Applies mounting offsets from `mountOffsetAxis[0]` and `mountOffsetAxis[1]` to the non-ignored axes. #### **`GetTiltZeroData(...)`** ```csharp public static double[] GetTiltZeroData(short[] tiltSensorADC, double[] tiltSensorCals, int dominantAxis) ``` - **Behavior**: Returns a `double[3]` of zero-point offsets. Uses base zero values (`TILTSENSOR_CAL_2/8/14`) and conditionally overrides them with dominant-axis-specific values (`TILTSENSOR_CAL_3/4`, `9/10`, `15/16`, etc.) based on the sign of `tiltSensorADC[dominantAxis]`. #### **`GetDominantTiltAxis(...)`** ```csharp public static int GetDominantTiltAxis(short[] tiltSensorADC) ``` - **Behavior**: Returns the index (`0`, `1`, or `2`) of the axis with the largest absolute ADC value. #### **`GetTiltGains(...)`** ```csharp public static double[] GetTiltGains(double[] tiltSensorCals) ``` - **Behavior**: Returns a `double[3]` of gain values (`TILTSENSOR_CAL_1/7/13`). Uses `1.0` if a gain is `0.0`. #### **`AxisLabel` enum** ```csharp public enum AxisLabel { X = 0, Y = 1, Z = 2 } ``` #### **`GetAxisLabelFromTiltAxes(...)` overloads** ```csharp public static AxisLabel[] GetAxisLabelFromTiltAxes(TiltAxes tiltAxes); public static AxisLabel[] GetAxisLabelFromTiltAxes(string tiltAxes); ``` - **Behavior**: Returns an `AxisLabel[3]` array corresponding to the non-`I` characters in the `TiltAxes` string (e.g., `"IXYIZ"` → `[Y, Z, X]`). #### **`ConvertBoolToInvertString(bool isInverted)`** ```csharp public static string ConvertBoolToInvertString(bool isInverted) ``` - **Behavior**: Returns `"I"` if `isInverted` is `true`, else `""`. #### **`GetOrientationLabelFromAxisInfo(...)`** ```csharp public static string GetOrientationLabelFromAxisInfo(string[] axisLabels, bool[] invertAxis) ``` - **Behavior**: Concatenates `invertAxis[i] ? "I" : ""` + `axisLabels[i]` for each axis (e.g., `["X","Y","Z"]`, `[true,false,false]` → `"IXYZ"`). #### **`GetTiltAxesFromAxisInfo(...)`** ```csharp public static TiltAxes GetTiltAxesFromAxisInfo(string[] axisLabels, bool[] invertAxis) ``` - **Behavior**: Calls `GetOrientationLabelFromAxisInfo`, then `GetTiltAxesFromString`. #### **`GetMountOffsetsOrTargetsFromAxisInfo(...)`** ```csharp public static float[] GetMountOffsetsOrTargetsFromAxisInfo(float[] perAxisValue, int axisToIgnore) ``` - **Behavior**: Returns a `float[2]` containing the values for the two *non-ignored* axes. `axisToIgnore` is `1`, `2`, or `3` (1-indexed). - Example: `axisToIgnore=1` → `[perAxisValue[1], perAxisValue[2]]`. --- ### 3. Invariants - **`TiltAxes` string format**: Must be 6 characters long, alternating axis label (`X`, `Y`, `Z`) and polarity (`P` or `N`). Inversion is represented by `I` (e.g., `IX`), but `I` is *not* a label—it is a polarity marker. - Valid examples: `"IXIYIZ"`, `"IXYZ"`, `"ZYX"`, `"IXZIY"`. - Invalid: `"IXIY"` (length ≠ 6), `"IXIXIX"` (repeated labels), `"IXIYIP"` (invalid polarity). - **`TiltAxesSimple` values**: Derived by removing all `I` characters from `TiltAxes.ToString()`. Must be a permutation of `"XYZ"`. - **`GetTiltDegreesEU` output**: The ignored axis is always `double.NaN`; the other two axes are rounded to 3 decimal places. - **Calibration array indexing**: `tiltSensorCals` must have ≥ 18 elements; indices correspond strictly to `TiltSensorCalAttributes`. - **`GetDominantTiltAxis`**: Uses the axis with the largest absolute value (handles negative ADCs correctly). --- ### 4. Dependencies - **Imports/Usings**: - `DTS.Common.Enums.DASFactory.DFConstantsAndEnums` (for `RecordingMode`, `TiltAxes`) - `DTS.Common.Utilities` (likely contains `DegreesFromADC`) - `System`, `System.Collections.Generic`, `System.Linq`, `System.Text`, `System.ComponentModel` - **External Types Used**: - `DFConstantsAndEnums.RecordingMode` (enum) - `DTS.Common.Enums.DASFactory.DFConstantsAndEnums.TiltAxes` (enum, defined elsewhere) - `DTS.Common.Utilities.DegreesFromADC.GetDegrees(...)` (used in `GetTiltDegreesEU`) - **Depended Upon By**: - Likely used by tilt sensor drivers, calibration tools, and data processing pipelines (e.g., `DataPRO`—per comment in `SIGNIFICANT_DIGITS`). --- ### 5. Gotchas - **Constructor Bug in `TiltAxesHelper`**: When `AxisIgnored == 2`, `AxisOne` is assigned twice (`AxisConfigurations[1]`), and `AxisTwo` is never set. Likely should be: ```csharp AxisOne = AxisConfigurations[1]; AxisTwo = AxisConfigurations[3]; // but note: AxisConfigurations is 1-indexed! ``` However, `AxisConfigurations` uses keys `1`, `2`, `3`, but `TiltAxis.AxisNumber` is not initialized in the constructor—this may cause off-by-one errors if `AxisNumber` is expected to match the dictionary key. - **`TiltAxes` Enum Values**: The source file does *not* define the `TiltAxes` enum itself (only uses it). Its members (e.g., `IXYIZ`, `ZYX`) are assumed to exist in `DFConstantsAndEnums`. The code assumes all permutations with optional `I` are valid enum values. - **`GetTiltZeroData` Logic**: Uses `dominantAxis` to select *dominant-axis-specific* zero points. This is non-trivial: zero points differ based on which axis is dominant (e.g., `ZeroDomAxis1PosAxis2` vs `ZeroDomAxis1NegAxis2`). - **`SIGNIFICANT_DIGITS = 1000`**: Hardcoded to enforce 3 decimal places (0.001 precision). This is a legacy design choice (see internal case 34373). - **`GetTiltDegreesEU` ADC Indexing**: Assumes `tiltSensorADC[0]`, `[1]`, `[2]` correspond to the physical axes *in the order they appear in the calibration array*, not the `TiltAxes` label order. The `axes` parameter only affects sign and axis assignment in the output array. - **`GetBoolPolaritiesFromTiltAxes`**: The loop increments `ax` only on non-`I` characters, so the resulting `bool[]` is *not* aligned with the original axis order if `I` is present. For `"IXYIZ"`, `rv[0]` corresponds to `Y`, `rv[1]` to `Z`, `rv[2]` to `X`—this may be counterintuitive. - **`GetPolaritiesFromTiltAxes`**: Returns `+1` for `P`, `-1` for `I`, but the mapping is based on the same non-`I`-indexed logic as `GetBoolPolaritiesFromTiltAxes`.