--- source_files: - DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Graph/Model/TestDataSeries.cs - DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Graph/Model/TestDataSeriesModel.cs generated_at: "2026-04-16T13:52:27.037806+00:00" model: "zai-org/GLM-5-FP8" schema_version: 1 sha256: "1630e6f30be700ba" --- # Documentation: DTS.Viewer.Graph Module - Test Data Series Models ## 1. Purpose This module provides the data models for representing and transforming test channel data into graphable series within the DTS Viewer application. `TestDataSeries` serves as the primary data transfer object holding channel metadata, X/Y coordinate arrays, statistical calculations, and visualization properties. `TestDataSeriesModel` acts as a factory/processor that reads raw binary channel data, applies transformations (including FFT and PSD calculations), and populates `TestDataSeries` instances for display. The module supports three data modes: regular time-series, FFT (Fast Fourier Transform), and PSD (Power Spectral Density) with configurable windowing and filtering. --- ## 2. Public Interface ### TestDataSeries Class **Namespace:** `DTS.Viewer.Graph.Model` **Inherits:** `Common.Base.BasePropertyChanged` **Implements:** `ITestDataSeries` #### Properties | Property | Type | Description | |----------|------|-------------| | `HIC` | `bool` | Indicates if Head Injury Criteria data is present. | | `HICValue` | `string` | Formatted HIC value. | | `T1Time`, `T2Time` | `string` | T1/T2 timestamp strings for HIC calculations. | | `TestGroup` | `string` | Test group identifier. | | `TestId` | `string` | Unique test identifier. | | `TestSetupName` | `string` | Name of the test setup configuration. | | `ChannelId` | `string` | Channel identifier. | | `Xvalue` | `double[]` | X-axis data array (time or frequency). | | `Yvalue` | `double[]` | Y-axis data array (amplitude, magnitude, or PSD). | | `GraphColor` | `Brush` | WPF brush for graph rendering. Internally stored as `byte[]` for thread-safety. | | `IsSaved` | `bool` | Get-only property indicating save state. | | `HardwareChannel` | `string` | Hardware channel name. | | `GroupName` | `string` | Channel group name. | | `SWAAF` | `string` | Software anti-aliasing filter setting. | | `Bridge` | `string` | Bridge type identifier. | | `HWAAF` | `string` | Hardware anti-aliasing filter rate. | | `SampleRate` | `string` | Sample rate in Hz. | | `ISOCode`, `ISOChannelName` | `string` | ISO channel identification. | | `UserCode`, `UserChannelName` | `string` | User-defined channel identification. | | `ChannelName` | `string` | Display channel name. | | `Description` | `string` | Channel description. | | `SensorSN` | `string` | Sensor serial number. | | `SensorSNDisplay` | `string` | Get-only; returns `"N/A"` if `SensorSN` is test-specific embedded, otherwise returns `SensorSN`. | | `EngineeringUnits` | `string` | Engineering units string. | | `Excitation` | `string` | Excitation voltage. | | `Polarity` | `string` | Sensor polarity. | | `MinY`, `MaxY`, `AvgY`, `StdDevY` | `string` | Statistical values formatted as strings, default to `Strings.Table_NA`. | | `PeakMagnitude` | `double` | Peak magnitude of frequencies (valid only when `FFT` is true). | | `PeakFrequency` | `double` | Frequency of highest magnitude (valid only when `FFT` is true). | | `GRMS` | `double` | Root-mean-squared acceleration (calculated for PSD results). | | `FFT` | `bool` | Indicates whether series contains FFT-transformed data. | | `T0EUValue` | `string` | T0 value string. | | `RecordingMode` | `string` | Recording mode description. | #### Methods ```csharp public void SetStatsFromYValues() ``` Calculates and sets `AvgY`, `StdDevY`, `MinY`, `MaxY` from internal `Yvalue` array. Uses `"G5"` format for string conversion. ```csharp public void SetStatsFromYValues(double[] values) ``` Overload that calculates statistics from a provided `double[]` array. Handles null/empty arrays by setting all stats to `Table_NA`. ```csharp public void SetStatsFromChannel(ITestChannel channel) ``` Sets statistics from pre-calculated values on an `ITestChannel` instance (properties: `MinY`, `MaxY`, `AveY`, `StdDevY`, `T0Value`). --- ### TestDataSeriesModel Class **Namespace:** `DTS.Viewer.Graph` **Implements:** `IBaseModel` #### Properties | Property | Type | Description | |----------|------|-------------| | `Parent` | `IGraphViewModel` | Parent view model reference. | | `_eventAggregator` | `IEventAggregator` | Prism event aggregator for publishing progress events. | | `ErrorMessage` | `string` | Error message with `PropertyChanged` notification. | | `IsSaved` | `bool` | Get-only property. | #### Methods ```csharp public Task GetTestDataAsync(ITestChannel channel, IChartOptionsModel chartOptions, bool bVolts, IPSDReportSettingsModel psdSettings = null) ``` Async wrapper returning `GetTestData()`. **Warning:** Lacks `await` operators and runs synchronously (per compiler warning CS1998). ```csharp public Task> GetTestDataAsync(List channels, IChartOptionsModel chartOptions, bool bVolts, IPSDReportSettingsModel psdSettings = null) ``` Async wrapper for multiple channels. Includes envelope channel if `psdSettings.ShowEnvelope` is true. ```csharp public List GetTestData(List channels, IChartOptionsModel chartOptions, bool bVolts, IPSDReportSettingsModel psdSettings = null) ``` Synchronously processes multiple channels. Throws `Exception` with context on `OutOfDataException` or other failures. Logs failures via `APILogger.Log()`. ```csharp public ITestDataSeries GetTestData(ITestChannel channel, IChartOptionsModel chartOptions, bool bVolts, IPSDReportSettingsModel psdSettings = null) ``` Returns `AddTestChannelToChart()` result. ```csharp public TestDataSeries AddTestChannelToChart(ITestChannel channel, IChartOptionsModel chartOptions, bool bVolts, IPSDReportSettingsModel psdSettings = null) ``` **Primary processing method.** Reads binary channel data via `Serialization.SliceRaw.File.Reader.ReadChannelsBinaryData()`, applies transformations based on `chartOptions.UnitType`: - **FFT mode** (`ChartUnitTypeEnum.FFT` with null `psdSettings`): Sets `FFT=true`, populates `PeakFrequency`, `PeakMagnitude`. - **Regular mode** (null `psdSettings`): Time-series data with optional HIC calculation. - **PSD mode** (non-null `psdSettings`): Applies data trimming, windowing (Hanning, Hamming, Blackman, BlackmanHarris, FlatTop, Rectangle), optional low/high pass filtering via `Exocortex.DSP`, and Welch PSD transform via `FftSharp.Transform.PSD_Welch()`. Returns `null` if `channel.ErrorMessage` is not empty. --- ## 3. Invariants 1. **Array Initialization**: `Xvalue` and `Yvalue` are never null; they default to `new double[0]`. 2. **GraphColor Thread-Safety**: `GraphColor` getter creates a new `SolidColorBrush` on each call. The underlying color is stored as a 4-byte array (`[A, R, G, B]`) to enable cross-thread access. 3. **FFT/PSD Filter Bypass**: When `chartOptions.UnitType` is `FFT` or `PSD`, `channel.SoftwareFilter` is forcibly set to `"none"` before reading data. 4. **Statistics Default**: `MinY`, `MaxY`, `AvgY` default to `Strings.Table_NA` (not empty string). 5. **PSD Data Length**: PSD processing resizes input arrays to the nearest enclosing power of 2 via `Utils.GetEnclosingPower2()`. 6. **Frequency Array First Element**: In PSD mode, `freq[0]` is explicitly set to `1` after calculation. 7. **IEPE Bridge Excitation**: Channels with `Bridge == "IEPE"` display `"---"` for excitation instead of measured voltage. --- ## 4. Dependencies ### This Module Depends On: - `DTS.Common.Base` - `BasePropertyChanged` base class - `DTS.Common.Enums.Sensors` - `SensorConstants` for bridge type detection - `DTS.Common.Enums.Viewer` - `ChartUnitTypeEnum`, `TimeUnitTypeEnum`, window/filter enums - `DTS.Common.Enums.DASFactory` - `DFConstantsAndEnums.RecordingMode` - `DTS.Common.Interface` - `ITestDataSeries`, `ITestChannel`, `IGraphViewModel`, `IChartOptionsModel`, `IBaseModel`, `IPSDReportSettingsModel` - `DTS.Common.Strings` - Localized string constants (`Table_NA`, `Envelope`, etc.) - `DTS.Common.Utils` - `Utils.GetEnclosingPower2()` - `DTS.Common.Utilities` - `RecordingModeExtensions` - `DTS.Common.Utilities.Logging` - `APILogger` - `DTS.Common.Converters` - `EnumDescriptionTypeConverter` - `DTS.Common.Events` - `GraphChannelReadCalcProgressChangedEvent`, `GraphChannelReadCalcProgressChangedEventArgs` - `DTS.Common.Exceptions` - `OutOfDataException` - `Prism.Events` - `IEventAggregator` - `System.Windows.Media` - `Brush`, `SolidColorBrush`, `Color`, `Colors` - `FftSharp` - `Transform.PSD_Welch()`, `Transform.FFTfreq()`, `WindowType`, `WindowAveragingType` - `Exocortex.DSP` - `PassFilter.LowPass()`, `PassFilter.HighPass()`, `PassFilterType` - `Serialization.SliceRaw.File.Reader` - `ReadChannelsBinaryData()` (external/unclear origin) ### Dependents (Inferred): - Any view or view model that displays graph data and implements `IGraphViewModel` - PSD report generation components --- ## 5. Gotchas 1. **Async Methods Are Not Async**: Both `GetTestDataAsync` overloads are marked `async` but contain no `await` operators. They execute synchronously despite the method signature. Compiler warning CS1998 is suppressed with pragmas. 2. **GraphColor Allocation on Every Access**: The `GraphColor` getter instantiates a new `SolidColorBrush` on every call. Frequent access in UI binding scenarios may cause unnecessary allocations. 3. **T0EUValue Naming Misnomer**: Per source comment: *"this is the T0 value regardless of units ... it's not really EU but since it's already in use I'm not going to change it"*. The property name is misleading. 4. **PSD Envelope Requires Non-Empty Input**: `GetEnvelopeChannel()` returns an empty `TestDataSeries` if input list is null or empty, without any error indication. 5. **Channel Error Short-Circuit**: `AddTestChannelToChart()` returns `null` (not an exception) if `channel.ErrorMessage` is non-empty, which may cause null reference exceptions in callers not expecting null. 6. **Digital Channel Detection String Comparison**: Digital channels are detected via `channel.Bridge.StartsWith(SensorConstants.BridgeType.DigitalInput.ToString())`. This relies on `ToString()` matching the enum name exactly. 7. **GRMS Calculation Edge Case**: `CalculateGRMS()` uses `N.EqualsDigitPrecision(-1, 1)` for a special case. The method `EqualsDigitPrecision` is not defined in the provided source—its behavior is unclear. 8. **Frequency Array Mutation**: In PSD mode, `freq[0] = 1` mutates the array returned from `FftSharp.Transform.FFTfreq()`. This may affect any other consumers of that array if it's shared.