Files
DP44/enriched-qwen3-coder-next/Common/DTS.Common.DAS.Concepts/Test/Module.md

235 lines
12 KiB
Markdown
Raw Normal View History

2026-04-17 14:55:32 -04:00
---
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<int, TiltAxis> 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`.