300 lines
15 KiB
Markdown
300 lines
15 KiB
Markdown
|
|
---
|
||
|
|
source_files:
|
||
|
|
- Common/DTS.CommonCore/Classes/DTS.Viewer/TestMetadata/TestMetadata.cs
|
||
|
|
- Common/DTS.CommonCore/Classes/DTS.Viewer/TestMetadata/TestGraphs.cs
|
||
|
|
- Common/DTS.CommonCore/Classes/DTS.Viewer/TestMetadata/TestSetupMetadata.cs
|
||
|
|
- Common/DTS.CommonCore/Classes/DTS.Viewer/TestMetadata/TestRunMetadata.cs
|
||
|
|
- Common/DTS.CommonCore/Classes/DTS.Viewer/TestMetadata/TestSummary.cs
|
||
|
|
- Common/DTS.CommonCore/Classes/DTS.Viewer/TestMetadata/TestModule.cs
|
||
|
|
- Common/DTS.CommonCore/Classes/DTS.Viewer/TestMetadata/TestChannel.cs
|
||
|
|
- Common/DTS.CommonCore/Classes/DTS.Viewer/TestMetadata/TestMetadataList.cs
|
||
|
|
generated_at: "2026-04-16T02:42:52.937741+00:00"
|
||
|
|
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||
|
|
schema_version: 1
|
||
|
|
sha256: "c38901448183a71b"
|
||
|
|
---
|
||
|
|
|
||
|
|
# Documentation: TestMetadata Module
|
||
|
|
|
||
|
|
## 1. Purpose
|
||
|
|
|
||
|
|
This module provides data structures and parsing logic for loading, representing, and managing test metadata from XML-based `.dts` files in the DTS Viewer system. It defines core domain models (`TestMetadata`, `TestRunMetadata`, `TestSetupMetadata`, `TestModule`, `TestChannel`, `TestGraphs`, `TestSummary`) that encapsulate test configuration, hardware setup, channel definitions, and summary information. The `TestMetadataList` class is responsible for deserializing XML metadata files into strongly-typed objects and constructing `TestSummary` instances for UI consumption, including timestamp resolution using PTP1588 timing data when available.
|
||
|
|
|
||
|
|
## 2. Public Interface
|
||
|
|
|
||
|
|
### `TestMetadataList`
|
||
|
|
|
||
|
|
#### `GetTestSummaryListAsync(IBaseViewModel parent, string path, string file, string pattern = "")`
|
||
|
|
- **Behavior**: Asynchronous wrapper (currently synchronous implementation) that returns an `ObservableCollection<ITestSummary>` by parsing `.dts` files in the specified directory. Uses `pattern` to filter files (default: `.dts`). Requires `parent` for view model hierarchy.
|
||
|
|
|
||
|
|
#### `GetTestSummaryList(IBaseViewModel parent, string path, string file = "", string pattern = "")`
|
||
|
|
- **Behavior**: Synchronously returns an `ObservableCollection<ITestSummary>` by parsing `.dts` files. Uses `parent` to set `TestSummary.Parent`.
|
||
|
|
|
||
|
|
#### `GetTestSummaryList(string path, string file = "", string pattern = "")`
|
||
|
|
- **Behavior**: Same as above but without a `parent` parameter (used when parent is not applicable or set later).
|
||
|
|
|
||
|
|
#### `GetTestMetadataList(XDocument xDoc, string path, string file)`
|
||
|
|
- **Behavior**: Parses an `XDocument` (loaded `.dts` XML) into a `List<ITestMetadata>`. Handles channel array initialization and publishes errors via `IEventAggregator` on failure. Returns empty list on exception.
|
||
|
|
|
||
|
|
### `TestMetadata`
|
||
|
|
|
||
|
|
- **Properties**:
|
||
|
|
- `ITestRunMetadata TestRun { get; set; }`
|
||
|
|
- `ITestSetupMetadata TestSetup { get; set; }`
|
||
|
|
- **Behavior**: Simple container for test run and setup metadata.
|
||
|
|
|
||
|
|
### `TestRunMetadata`
|
||
|
|
|
||
|
|
- **Properties**:
|
||
|
|
- `string Name { get; set; }` — Logical test name (from XML `@Id` attribute).
|
||
|
|
- `string Id { get; set; }` — File name without extension (derived from `@FilePath`).
|
||
|
|
- `string Description { get; set; }`
|
||
|
|
- `bool InlineSerializedData { get; set; }`
|
||
|
|
- `string TestGuid { get; set; }`
|
||
|
|
- `int FaultFlags { get; set; }`
|
||
|
|
- `string Software { get; set; }`
|
||
|
|
- `string SoftwareVersion { get; set; }`
|
||
|
|
- `string DataType { get; set; }`
|
||
|
|
- `DateTime FileDate { get; set; }`
|
||
|
|
- `string FilePath { get; set; }`
|
||
|
|
- `List<ITestModule> Modules { get; set; }`
|
||
|
|
- `List<ITestChannel> Channels { get; set; }`
|
||
|
|
- `List<ITestChannel> CalculatedChannels { get; set; }`
|
||
|
|
- `bool IsSelected { get; set; }`
|
||
|
|
- **Events**:
|
||
|
|
- `event PropertyChangedEventHandler PropertyChanged` — Implements `INotifyPropertyChanged`.
|
||
|
|
|
||
|
|
### `TestSetupMetadata`
|
||
|
|
|
||
|
|
- **Properties**:
|
||
|
|
- `string SetupName { get; set; }`
|
||
|
|
- `DateTime TimeStamp { get; set; }`
|
||
|
|
- `List<ITestGraphs> TestGraphs { get; set; }`
|
||
|
|
- `CalibrationBehaviors CalibrationBehavior { get; set; }`
|
||
|
|
|
||
|
|
### `TestGraphs`
|
||
|
|
|
||
|
|
- **Properties**:
|
||
|
|
- `string Name { get; set; }`
|
||
|
|
- `string HardwareChannelName { get; set; }`
|
||
|
|
- `List<string> ChannelIds { get; set; }`
|
||
|
|
- `List<ITestChannel> Channels { get; set; }`
|
||
|
|
|
||
|
|
### `TestModule`
|
||
|
|
|
||
|
|
- **Properties**:
|
||
|
|
- `string SerialNumber { get; set; }`
|
||
|
|
- `string BaseSerialNumber { get; set; }`
|
||
|
|
- `int AaFilterRateHz { get; set; }`
|
||
|
|
- `int Number { get; set; }`
|
||
|
|
- `int NumberOfSamples { get; set; }`
|
||
|
|
- `int UnsubsampledNumberOfSamples { get; set; }`
|
||
|
|
- `double RequestedPostTriggerSeconds { get; set; }`
|
||
|
|
- `double RequestedPreTriggerSeconds { get; set; }`
|
||
|
|
- `double PostTriggerSeconds { get; set; }`
|
||
|
|
- `double PreTriggerSeconds { get; set; }`
|
||
|
|
- `string RecordingMode { get; set; }`
|
||
|
|
- `int SampleRateHz { get; set; }`
|
||
|
|
- `int StartRecordSampleNumber { get; set; }`
|
||
|
|
- `int NumberOfChannels { get; set; }`
|
||
|
|
- `bool InlineSerializedData { get; set; }`
|
||
|
|
- `int StartRecordTimestampSec { get; set; }`
|
||
|
|
- `int StartRecordTimestampNanoSec { get; set; }`
|
||
|
|
- `int TriggerTimestampSec { get; set; }`
|
||
|
|
- `int TriggerTimestampNanoSec { get; set; }`
|
||
|
|
- `List<ulong> TriggerSampleNumbers { get; set; }` — *Always empty* (see *Gotchas*).
|
||
|
|
- `bool PTPMasterSync { get; set; }`
|
||
|
|
- `int TiltSensorAxisX/Y/ZDegreesPre/Post { get; set; }`
|
||
|
|
- `int TemperatureLocation1/2/3/4Pre/Post { get; set; }`
|
||
|
|
- `List<ITestChannel> Channels { get; set; }`
|
||
|
|
- `List<ITestChannel> CalculatedChannels { get; set; }`
|
||
|
|
- `bool IsSelected { get; set; }`
|
||
|
|
- **Events**:
|
||
|
|
- `event PropertyChangedEventHandler PropertyChanged`
|
||
|
|
|
||
|
|
### `TestChannel`
|
||
|
|
|
||
|
|
- **Properties**:
|
||
|
|
- `string Group { get; set; }`
|
||
|
|
- `string SubGroup { get; set; }`
|
||
|
|
- `bool IsGraphChannel { get; set; }`
|
||
|
|
- `string GraphName { get; set; }`
|
||
|
|
- `string TestId { get; set; }`
|
||
|
|
- `string TestSetupName { get; set; }`
|
||
|
|
- `string ModuleSerialNumber { get; set; }`
|
||
|
|
- `string SerialNumber { get; set; }`
|
||
|
|
- `string ChannelId { get; set; }`
|
||
|
|
- `string ChannelDisplayName { get; set; }`
|
||
|
|
- `string Description { get; set; }`
|
||
|
|
- `string IsoCode { get; set; }`
|
||
|
|
- `string IsoChannelName { get; set; }`
|
||
|
|
- `string UserCode { get; set; }`
|
||
|
|
- `string UserChannelName { get; set; }`
|
||
|
|
- `string ChannelGroupName { get; set; }`
|
||
|
|
- `string ChannelType { get; set; }`
|
||
|
|
- `bool IsCalculatedChannel { get; set; }`
|
||
|
|
- `int Number { get; set; }`
|
||
|
|
- `string DigitalMultiplier { get; set; }`
|
||
|
|
- `string DigitalMode { get; set; }`
|
||
|
|
- `DateTime Start { get; set; }`
|
||
|
|
- `string Bridge { get; set; }`
|
||
|
|
- `double BridgeResistanceOhms { get; set; }`
|
||
|
|
- `double ZeroPoint { get; set; }`
|
||
|
|
- `string ChannelDescriptionString { get; set; }`
|
||
|
|
- `string ChannelName2 { get; set; }`
|
||
|
|
- `string HardwareChannelName { get; set; }`
|
||
|
|
- `double DesiredRange { get; set; }`
|
||
|
|
- `double ActualMaxRangeEu { get; set; }`
|
||
|
|
- `double ActualMinRangeEu { get; set; }`
|
||
|
|
- `double ActualMaxRangeAdc { get; set; }` — Always `short.MaxValue`
|
||
|
|
- `double ActualMinRangeAdc { get; set; }` — Always `short.MinValue`
|
||
|
|
- `double ActualMaxRangeMv { get; set; }`
|
||
|
|
- `double ActualMinRangeMv { get; set; }`
|
||
|
|
- `double Sensitivity { get; set; }`
|
||
|
|
- `string SoftwareFilter { get; set; }`
|
||
|
|
- `bool ProportionalToExcitation { get; set; }`
|
||
|
|
- `bool IsInverted { get; set; }`
|
||
|
|
- `string LinearizationFormula { get; set; }`
|
||
|
|
- `bool IsSubsampled { get; set; }`
|
||
|
|
- `int AbsoluteDisplayOrder { get; set; }`
|
||
|
|
- `DateTime LastCalibrationDate { get; set; }`
|
||
|
|
- `string SensorId { get; set; }`
|
||
|
|
- `int OffsetToleranceLowMv { get; set; }`
|
||
|
|
- `int OffsetToleranceHighMv { get; set; }`
|
||
|
|
- `int DataFlag { get; set; }`
|
||
|
|
- `string ExcitationVoltage { get; set; }`
|
||
|
|
- `string Eu { get; set; }`
|
||
|
|
- `bool CalSignalEnabled { get; set; }`
|
||
|
|
- `bool ShuntEnabled { get; set; }`
|
||
|
|
- `bool VoltageInsertionCheckEnabled { get; set; }`
|
||
|
|
- `bool RemoveOffset { get; set; }`
|
||
|
|
- `string ZeroMethod { get; set; }`
|
||
|
|
- `double ZeroAverageWindowBegin { get; set; }`
|
||
|
|
- `double ZeroAverageWindowEnd { get; set; }`
|
||
|
|
- `int InitialEu { get; set; }`
|
||
|
|
- `string InitialOffset { get; set; }`
|
||
|
|
- `int UnsubsampledSampleRateHz { get; set; }`
|
||
|
|
- `double MeasuredShuntDeflectionMv { get; set; }`
|
||
|
|
- `double TargetShuntDeflectionMv { get; set; }`
|
||
|
|
- `double MeasuredExcitationVoltage { get; set; }`
|
||
|
|
- `double FactoryExcitationVoltage { get; set; }`
|
||
|
|
- `double TimeOfFirstSample { get; set; }`
|
||
|
|
- `double Multiplier { get; set; }`
|
||
|
|
- `double UserOffsetEu { get; set; }`
|
||
|
|
- `int UnitConversion { get; set; }`
|
||
|
|
- `bool AtCapacity { get; set; }`
|
||
|
|
- `int CapacityOutputIsBasedOn { get; set; }`
|
||
|
|
- `string SourceChannelNumber { get; set; }`
|
||
|
|
- `string SourceModuleNumber { get; set; }`
|
||
|
|
- `string SourceModuleSerialNumber { get; set; }`
|
||
|
|
- `string Calculation { get; set; }`
|
||
|
|
- `int SampleRateHz { get; set; }`
|
||
|
|
- `string SensitivityUnits { get; set; }`
|
||
|
|
- `int SensorCapacity { get; set; }`
|
||
|
|
- `string SensorPolarity { get; set; }`
|
||
|
|
- `int ChannelNumber { get; set; }`
|
||
|
|
- `string BinaryFileName { get; set; }`
|
||
|
|
- `string BinaryFilePath { get; set; }`
|
||
|
|
- `double Xmax { get; set; }`
|
||
|
|
- `double Xmin { get; set; }`
|
||
|
|
- `int SequentialNumbers { get; set; }`
|
||
|
|
- `ITestSetupMetadata ParentTestSetup { get; set; }`
|
||
|
|
- `ITestModule ParentModule { get; set; }`
|
||
|
|
- `IBaseViewModel Parent { get; set; }`
|
||
|
|
- `Color ChannelColor { get; set; }`
|
||
|
|
- `string ErrorMessage { get; set; }`
|
||
|
|
- `bool IsError { get; set; }`
|
||
|
|
- `Color? ErrorColor { get; set; }` — Derived from `IsError`.
|
||
|
|
- `bool IsLocked { get; set; }`
|
||
|
|
- `bool CanLock { get; set; }`
|
||
|
|
- `bool CanSelectChannel { get; set; }`
|
||
|
|
- `bool IsExpanded { get; set; }`
|
||
|
|
- `bool IsSelected { get; set; }`
|
||
|
|
- `double MinADC/MaxADC/AveADC/StdDevADC/T0ADC { get; set; }`
|
||
|
|
- `double MinMV/MaxMV/AveMV/StdDevMV/T0MV { get; set; }`
|
||
|
|
- `double MinEU/MaxEU/AveEU/StdDevEU/T0EU { get; set; }`
|
||
|
|
- `double MinY/MaxY/AveY/StdDevY/T0Value { get; set; }`
|
||
|
|
- **Methods**:
|
||
|
|
- `void SetChannelDescriptionAndDisplayName(string channelDescription)` — Sets `ChannelDescriptionString` and `ChannelDisplayName`.
|
||
|
|
- `ITestChannel Copy()` — Shallow copy via `MemberwiseClone()`.
|
||
|
|
- `override string ToString()` — Returns `ChannelDescriptionString` or `"N/A"` if test-specific embedded.
|
||
|
|
- **Events**:
|
||
|
|
- `event PropertyChangedEventHandler PropertyChanged` — Inherited from `BasePropertyChanged`.
|
||
|
|
|
||
|
|
### `TestSummary`
|
||
|
|
|
||
|
|
- **Properties**:
|
||
|
|
- `string Id { get; set; }` — Concatenation of `TestRun.Id` and event number from `FilePath`.
|
||
|
|
- `string SetupName { get; set; }`
|
||
|
|
- `string Description { get; set; }`
|
||
|
|
- `int ChannelCount { get; set; }`
|
||
|
|
- `DateTime FileDate { get; set; }`
|
||
|
|
- `DateTime TimeStamp { get; set; }` — Derived from module PTP timestamps if valid, else `TestSetup.TimeStamp`.
|
||
|
|
- `string DataType { get; set; }`
|
||
|
|
- `bool IsSelected { get; set; }`
|
||
|
|
- `List<ITestGraphs> Graphs { get; set; }`
|
||
|
|
- `List<ITestChannel> Channels { get; set; }`
|
||
|
|
- `List<ITestChannel> CalculatedChannels { get; set; }`
|
||
|
|
- `IBaseViewModel Parent { get; set; }`
|
||
|
|
- `CalibrationBehaviors CalibrationBehavior { get; set; }` — Default: `NonLinearIfAvailable`.
|
||
|
|
- `ITestMetadata TestMetadata { get; set; }`
|
||
|
|
- **Commands**:
|
||
|
|
- `DelegateCommand IsSelectedCommand { get; }` — Toggles selection and updates `Parent.SelectedTestSummaryList`.
|
||
|
|
- **Methods**:
|
||
|
|
- `void SelectionChanged()` — Adds/removes `this` from `Parent.SelectedTestSummaryList` and calls `PublishSelectedTestSummaryList()` on parent.
|
||
|
|
- `void OnPropertyChanged(string propertyName)` — Raises `PropertyChanged`.
|
||
|
|
- **Events**:
|
||
|
|
- `event PropertyChangedEventHandler PropertyChanged`
|
||
|
|
- **Constants**:
|
||
|
|
- `public const string ROI_SUFFIX = @"_ROI Period";`
|
||
|
|
|
||
|
|
## 3. Invariants
|
||
|
|
|
||
|
|
- **`TestMetadata`**: Must contain non-null `TestRun` and `TestSetup` references after successful parsing.
|
||
|
|
- **`TestRunMetadata.Channels` and `TestRunMetadata.CalculatedChannels`**: Initialized as empty lists during parsing if missing in XML.
|
||
|
|
- **`TestModule.TriggerSampleNumbers`**: Always initialized as an empty list; never populated (see *Gotchas*).
|
||
|
|
- **`TestChannel.ChannelId`**: If missing or `-1` in XML, defaults to `m.GetHashCode().ToString()` (non-deterministic).
|
||
|
|
- **`TestChannel.HardwareChannelName`**: For calculated channels, always set to `"N/A"` (via `Strings.Strings.Table_NA`).
|
||
|
|
- **`TestChannel.SerialNumber`**: For calculated channels, always set to `"N/A"`.
|
||
|
|
- **`TestSummary.TimeStamp`**: Falls back to `TestSetup.TimeStamp` if PTP timestamps are invalid or unavailable.
|
||
|
|
- **`TestSummary.Id`**: Always includes event number extracted from `FilePath` via `ParseEventNumber`.
|
||
|
|
- **`TestChannel.IsCalculatedChannel`**: Must be `true` for channels loaded via `LoadTestCalculatedChannels`.
|
||
|
|
- **`TestSummary.IsSelected`**: Setter enforces selection logic via `SelectionChanged()` and `Parent` interaction.
|
||
|
|
|
||
|
|
## 4. Dependencies
|
||
|
|
|
||
|
|
### Internal Dependencies (from source):
|
||
|
|
- **Interfaces**:
|
||
|
|
- `DTS.Common.Interface.ITestMetadata`, `ITestRunMetadata`, `ITestSetupMetadata`, `ITestGraphs`, `ITestModule`, `ITestChannel`, `ITestSummary`, `IBaseViewModel`, `IGraphMainViewModel`
|
||
|
|
- **Enums**:
|
||
|
|
- `DTS.Common.Enums.Sensors.CalibrationBehaviors`
|
||
|
|
- **Utilities**:
|
||
|
|
- `DTS.Common.XMLUtils.TestMetadataXml`
|
||
|
|
- `DTS.Common.Base.BasePropertyChanged`
|
||
|
|
- `DTS.Common.Constants.EventNumber`
|
||
|
|
- `DTS.Common.Utils.TestUtils`, `PTP1588Timestamps`
|
||
|
|
- `DTS.Common.XMLUtils.TestMetadataFields`, `TestSetupMetadataFields`, `TestGraphsFields`, `TestModuleFields`, `TestChannelFields`
|
||
|
|
- `DTS.Common.Strings.Strings`
|
||
|
|
- **Prism Framework**:
|
||
|
|
- `Microsoft.Practices.Prism.Commands.DelegateCommand`
|
||
|
|
- `Microsoft.Practices.Prism.Events.IEventAggregator`, `Events.PageErrorEvent`
|
||
|
|
- `Microsoft.Practices.ServiceLocation.ServiceLocator`
|
||
|
|
|
||
|
|
### External Dependencies:
|
||
|
|
- `System.Xml.Linq`
|
||
|
|
- `System.Collections.ObjectModel`
|
||
|
|
- `System.ComponentModel`
|
||
|
|
- `System.Windows.Media` (for `Color`)
|
||
|
|
|
||
|
|
### Inferred Consumers:
|
||
|
|
- UI view models (`ITestSummaryListViewModel`, `IGraphMainViewModel`) that interact with `TestSummary` and `TestChannel`.
|
||
|
|
- XML loading utilities (`TestMetadataXml`) for parsing `.dts` files.
|
||
|
|
- Event aggregation system for error reporting.
|
||
|
|
|
||
|
|
## 5. Gotchas
|
||
|
|
|
||
|
|
- **`TestModule.TriggerSampleNumbers` is always empty**: The `LoadTriggerSampleNumbers` method ignores its input and returns `new List<ulong>()`. This field is likely unused or deprecated.
|
||
|
|
- **Non-deterministic `ChannelId` for missing IDs**: If `ChannelId` attribute is missing or `-1`, `m.GetHashCode().ToString()` is used, which is not stable across runs or app restarts.
|
||
|
|
- **Calculated channel data loss**: For calculated channels, many fields (e.g., `IsoCode`, `IsoChannelName`, `UserCode`, `UserChannelName`, `HardwareChannelName`, `SerialNumber`) are hardcoded to `"N/A"`. Some fields like `FactoryExcitationVoltage` and `TimeOfFirstSample` are incorrectly assigned values from unrelated attributes (e.g., `UnsubsampledSampleRateHz` → `FactoryExcitationVoltage`).
|
||
|
|
- **`TestRunMetadata.Id` vs `Name` confusion**: `Id` is derived from file name (`Path.GetFileNameWithoutExtension(FilePath)`), while `Name` comes from XML `@Id` attribute. This may be counterintuitive.
|
||
|
|
- **`TestSummary.TimeStamp` fallback behavior**: Uses `TestSetup.TimeStamp`
|