This commit is contained in:
2026-04-17 14:55:32 -04:00
commit bc3ac1d4c9
18017 changed files with 4371742 additions and 0 deletions

View File

@@ -0,0 +1,230 @@
---
source_files:
- Common/DTS.Common.Serialization/Control/Event/DasModuleAccessor.cs
- Common/DTS.Common.Serialization/Control/Event/DasChannelAccessor.cs
- Common/DTS.Common.Serialization/Control/Event/ChannelAccessor.cs
- Common/DTS.Common.Serialization/Control/Event/ModuleChannelAccessor.cs
- Common/DTS.Common.Serialization/Control/Event/DasModuleChannelAccessor.cs
- Common/DTS.Common.Serialization/Control/Event/TestInformation.cs
- Common/DTS.Common.Serialization/Control/Event/Event.cs
generated_at: "2026-04-16T03:41:53.208866+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "e1ba9340d986b9b2"
---
# Documentation: `DTS.Slice.Control.Event` Accessor Classes and Related Types
## 1. Purpose
This module provides accessor objects and supporting infrastructure for navigating and manipulating event data within the DTS Slice Control system. Specifically, it defines hierarchical dictionary-based accessors (`DasModuleAccessor`, `DasChannelAccessor`, `DasModuleChannelAccessor`, `ChannelAccessor`, `ModuleChannelAccessor`) that enable lookup of modules and channels by DAS ID, module number, and channel number combinations. It also includes the core `Event` class (a partial class with multiple files), which serves as the in-memory representation of a DAS event—encapsulating test metadata, modules, channels, and derived properties such as validation flags and serialization support. The module bridges low-level DAS serialization data (e.g., `DTS.Serialization.Test`) and higher-level control logic by offering structured, type-safe access to event components.
## 2. Public Interface
All accessor classes and the `Event` class reside in the `DTS.Slice.Control` namespace and are declared as `public partial class Event`.
### `Event` Class
- **`Event()`**
Default constructor. Initializes all properties to their default values.
- **`Event(string id, string description)`**
Initializes an `Event` with the given `id` and `description`. Throws a wrapped exception on failure.
- **`Event(Test test, Test.ReportErrors reportErrors)`**
Initializes an `Event` by converting from a `DTS.Serialization.Test` object via `FromDtsSerializationTest`. Rethrows exceptions directly.
- **`Event(string id, string description, List<Module> modules)`**
Initializes an `Event` with `id`, `description`, and a list of `Module`s.
- **`Event(List<IDASCommunication> dases, EventInfoAggregate info)`**
Initializes an `Event` by aggregating configuration and channel data from a list of DAS devices (`IDASCommunication`) and `EventInfoAggregate`. Populates `Modules`, `DasModules`, `DasChannels`, and `DasModuleChannels`. Throws `UserException` for missing DAS info or configuration. Validates test ID consistency across DAS units.
- **`string Id { get; set; }`**
Gets/sets the events test ID.
- **`string Description { get; set; }`**
Gets/sets the events description.
- **`Guid Guid { get; set; }`**
Gets/sets the globally unique identifier for the event. Default is `Guid.Empty`.
- **`UInt16 FaultFlags { get; set; }`**
Gets/sets the global fault flags for the event.
- **`DateTime InceptionDate { get; private set; }`**
Gets the creation date of the event (set during construction). Defaults to `DateTime.Now`.
- **`List<Module> Modules { get; set; }`**
Gets/sets the list of `Module` objects associated with this event.
- **`List<Module.Channel> CalculatedChannels { get; set; }`**
Gets/sets the list of calculated channels.
- **`DasModuleAccessor DasModules { get; private set; }`**
Returns a `DasModuleAccessor` keyed by DAS ID (`Common.DAS.Concepts.DAS.Id`), mapping to a `List<Module>`.
- **`DasChannelAccessor DasChannels { get; private set; }`**
Returns a `DasChannelAccessor` keyed by DAS ID, mapping to a `List<Module.Channel>`.
- **`DasModuleChannelAccessor DasModuleChannels { get; private set; }`**
Returns a `DasModuleChannelAccessor` keyed by DAS ID, mapping to a `ModuleChannelAccessor`.
- **`int LastAbsoluteChannelNumberInEvent { get; }`**
Returns the highest absolute channel number across all modules and channels.
- **`bool IsTooLargeFor32BitVisualization { get; }`**
Returns `true` if the total data volume (based on `TooLargeFor32BitVisualizationBytesPerSampleThreshold`) exceeds 2GB (0x7FFFFFFF bytes).
- **`double TooLargeFor32BitVisualizationBytesPerSampleThreshold { get; private set; }`**
Threshold in bytes per sample used for 32-bit visualization size checks. Default: `2.0`.
- **`bool ContainsChannelsActiveInvalidZeroingWindows { get; }`**
Returns `true` if any channel has `ZeroMethod == AverageOverTime` and an invalid averaging window.
- **`List<Module.Channel> ChannelsWithActiveInvalidZeroingWindows { get; }`**
Returns the list of channels with active but invalid zeroing windows (e.g., window outside data range or negative indices).
- **`static string BaseSerializationDirectory { get; set; }`**
Gets/sets the base directory path for event serialization.
- **`static string GetEventSerializationDirectory(string eventId)`**
Returns the full path for the serialization directory of the given `eventId`.
- **`bool Equals(object obj)`**
Overrides `Equals` to compare `Id`, `Description`, `Guid`, `Modules`, and `FaultFlags`.
- **`int GetHashCode()`**
Overrides `GetHashCode`.
- **`Test ToDtsSerializationTest()`**
Converts this `Event` to a `DTS.Serialization.Test`. Removes unconfigured/dummy channels before serialization.
- **`void FromDtsSerializationTest(Test that, Test.ReportErrors reportErrors)`**
Populates this `Event` from a `DTS.Serialization.Test`. Re-throws `InvalidDataException` directly; wraps others.
- **`static implicit operator Test(Event sliceControlEvent)`**
Implicit conversion operator to `DTS.Serialization.Test`.
- **`static bool IsG5(IDASCommunication idas)`**
Returns `true` if the DAS serial number starts with `"5M"`.
- **`static bool IsSlice6DBModule(Module module)`**
Returns `true` if `module.Description.ToLower() == "slice6db module"`.
### Accessor Classes
- **`DasModuleAccessor : ExceptionalDictionary<Common.DAS.Concepts.DAS.Id, List<Module>>`**
Keyed by DAS ID, maps to list of `Module`s. Used to retrieve modules by DAS.
- **`DasChannelAccessor : ExceptionalDictionary<Common.DAS.Concepts.DAS.Id, List<Module.Channel>>`**
Keyed by DAS ID, maps to list of `Module.Channel`s. Used to retrieve channels by DAS.
- **`DasModuleChannelAccessor : ExceptionalDictionary<Common.DAS.Concepts.DAS.Id, ModuleChannelAccessor>`**
Keyed by DAS ID, maps to a `ModuleChannelAccessor`. Enables 3-level lookup: DAS ID → module index → channel index.
- **`ChannelAccessor : ExceptionalDictionary<int, Module.Channel>`**
Keyed by `int` (module channel number), maps to a `Module.Channel`. Used as the innermost accessor.
- **`ModuleChannelAccessor : ExceptionalDictionary<int, ChannelAccessor>`**
Keyed by `int` (module array index), maps to a `ChannelAccessor`. Enables lookup of channels by module number.
- **`TestInformation : Exceptional`** *(private)*
Holds test metadata (`Id`, `Description`) per DAS. Used internally during event construction.
### Helper Methods (in `Event`)
- **`bool IsDummyChannel(Module.Channel channel)`**
Returns `true` if `channel.ChannelDescriptionString.ToLower() == "dummy arm channel"`.
- **`bool IsTom(DASModule module)`**
Returns `true` if module is a TOM (based on serial number or channel type).
- **`void PurgeUnconfiguredChannels()`**
Removes unconfigured or dummy channels from all modules.
- **`bool IsEmptyModule(Module module)`**
Returns `true` if module has no configured/non-dummy channels.
## 3. Invariants
- **`DasModules`, `DasChannels`, `DasModuleChannels` are always initialized**
These properties are initialized in the `Property<T>` declaration with new accessor instances and are marked `readonly`/`true` (immutable reference after construction).
- **Module array indices must match list positions**
The constructor for `Event(List<IDASCommunication>, EventInfoAggregate)` asserts:
`Debug.Assert(DasModules[das.SerialNumber].Count - 1 == dasModule.ModuleArrayIndex);`
This implies modules are inserted in order, and empty slots are filled with placeholder `Module` instances.
- **Test ID must be consistent across all DAS units**
During construction, if any DAS reports a different `TestID`, an exception is thrown.
- **Channel absolute numbers are assigned sequentially**
`absoluteChannelNumber` is incremented per channel added, and `Module.Channel.AbsoluteNumber` is set during `Channel.CreateChannel`.
- **`InceptionDate` is set once at construction**
The setter is `private`, and the property is initialized with `DateTime.Now` or the serialization date.
- **`TooLargeFor32BitVisualizationBytesPerSampleThreshold` is immutable after construction**
Marked `readonly` and `true` in `Property<T>`.
- **`IsSlice6DBModule` check is case-insensitive**
Compares `module.Description.ToLower()` to `"slice6db module"`.
- **`InvalidWindowAverage` is `short.MinValue`**
Used to detect uninitialized or invalid window averages in zeroing logic.
## 4. Dependencies
### Internal Dependencies (within this module)
- `DTS.Slice.Control.Event.Module` and nested types (`Module.Channel`, `Module.AnalogInputChannel`, etc.)
- `DTS.Common.Utilities.ExceptionalDictionary<TKey, TValue>`
- `DTS.Common.Utilities.DotNetProgrammingConstructs.Property<T>`
- `DTS.Slice.Control.Event.TestInformation` (private helper)
### External Dependencies
- `DTS.Serialization.Test` (from `DTS.Serialization` namespace)
- `DTS.DASLib.Service.IDASCommunication`, `DASModule`, `DASChannel`, `EthernetTDAS`
- `DTS.Common.Utilities.Logging.APILogger`
- `System.Collections.Generic.List<T>`, `System.Guid`, `System.DateTime`, `System.Diagnostics.Debug`
- `DTS.Serialization.StringResources.Strings` (for error messages)
### Inferred Usage
- `EventInfoAggregate` is required for `Event(List<IDASCommunication>, EventInfoAggregate)` constructor.
- `Test.ReportErrors` delegate is used in `FromDtsSerializationTest`.
- Serialization infrastructure (`DTS.Serialization`) is used for round-trip conversion (`ToDtsSerializationTest`, `FromDtsSerializationTest`).
## 5. Gotchas
- **`DasModuleChannels` property key is `"DTS.Slice.Control.Event.DasModules"` (typo)**
In the `Event` constructor, the `Property<DasModuleChannelAccessor>` for `DasModuleChannels` is initialized with the key `"DTS.Slice.Control.Event.DasModules"` instead of `"DTS.Slice.Control.Event.DasModuleChannels"`. This is likely a copy-paste bug.
- **`DasModuleChannelAccessor` uses `int` keys for module/channel indices, not typed IDs**
Both `ModuleChannelAccessor` and `ChannelAccessor` use `int` keys (for module number and channel number, respectively), not strongly-typed IDs (see `xxx` comments in source). This risks confusion or errors if indices are misaligned.
- **`InceptionDate` defaults to `DateTime.Now`**
If constructed via the default constructor, `InceptionDate` reflects the current time—not the serialization time. Only the `Event(Test, ...)` constructor sets it from the `Test.InceptionDate`.
- **`IsSlice6DBModule` is case-sensitive on `"slice6db module"`**
Uses `ToLower()` for comparison, but the literal string is lowercase. If the source description varies in casing (e.g., `"Slice6DB Module"`), it may not match.
- **Zeroing window validation is complex and fragile**
`ChannelsWithActiveInvalidZeroingWindows` performs multiple checks (negative indices, window outside data range). Edge cases (e.g., empty `TriggerSampleNumbers`, zero sample rate) are not explicitly handled beyond defaulting to `0`.
- **`PurgeUnconfiguredChannels` modifies `Modules` in-place**
Called during `ToDtsSerializationTest`, this permanently removes channels. If the `Event` object is reused, data may be lost.
- **`IsDummyChannel` and `IsSlice6DBModule` use string comparisons**
Relies on literal string matching (`"dummy arm channel"`, `"slice6db module"`). No constants or enums are defined for these.
- **`IsG5` checks only serial number prefix**
Assumes `"5M"` prefix is sufficient to identify G5 devices. May be brittle if serial number formats change.
- **No thread safety**
Comments in `Event.cs` explicitly note: *"Also need to add thread protection."* and *"Can we set locks in the property accessors..."* — no synchronization is present.
- **`TestInformation` is private and not exposed**
While used internally, it is not part of the public API. Its properties (`Id`, `Description`) are not validated beyond assignment.
- **`TooLargeFor32BitVisualizationBytesPerSampleThreshold` is hardcoded to `2.0`**
The justification in comments is detailed, but the value is not configurable at runtime (only via reflection or subclassing).