--- 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 modules)`** Initializes an `Event` with `id`, `description`, and a list of `Module`s. - **`Event(List 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 event’s test ID. - **`string Description { get; set; }`** Gets/sets the event’s 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 Modules { get; set; }`** Gets/sets the list of `Module` objects associated with this event. - **`List 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`. - **`DasChannelAccessor DasChannels { get; private set; }`** Returns a `DasChannelAccessor` keyed by DAS ID, mapping to a `List`. - **`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 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>`** Keyed by DAS ID, maps to list of `Module`s. Used to retrieve modules by DAS. - **`DasChannelAccessor : ExceptionalDictionary>`** Keyed by DAS ID, maps to list of `Module.Channel`s. Used to retrieve channels by DAS. - **`DasModuleChannelAccessor : ExceptionalDictionary`** Keyed by DAS ID, maps to a `ModuleChannelAccessor`. Enables 3-level lookup: DAS ID → module index → channel index. - **`ChannelAccessor : ExceptionalDictionary`** Keyed by `int` (module channel number), maps to a `Module.Channel`. Used as the innermost accessor. - **`ModuleChannelAccessor : ExceptionalDictionary`** 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` 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, 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`. - **`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` - `DTS.Common.Utilities.DotNetProgrammingConstructs.Property` - `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`, `System.Guid`, `System.DateTime`, `System.Diagnostics.Debug` - `DTS.Serialization.StringResources.Strings` (for error messages) ### Inferred Usage - `EventInfoAggregate` is required for `Event(List, 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` 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).