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,86 @@
---
source_files:
- Common/DTS.Common.Serialization/Control/DAS/IFilterable.cs
- Common/DTS.Common.Serialization/Control/DAS/IFilter.cs
generated_at: "2026-04-16T03:41:25.272025+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "d1bb42983adadb6c"
---
# DAS
## Documentation: `IFilterable` and `IFilter` Interfaces
---
### 1. **Purpose**
This module defines core interfaces (`IFilterable` and `IFilter`) for managing and applying signal filters to channel data within the DTS Slice Control DAS (Data Acquisition System) framework. It enables consumers to query available filters, set a current filter, optionally cache filter results for performance, and retrieve filtered data in specified display units. The interfaces serve as abstractions for channel filtering logic—likely implemented by concrete classes representing physical or logical channel groups in the control system.
---
### 2. **Public Interface**
#### `IFilterable` Interface
*Namespace:* `DTS.Slice.Control.DAS.Channel`
| Member | Signature | Description |
|--------|-----------|-------------|
| `UseFilterCaching` | `bool UseFilterCaching { get; set; }` | Enables or disables caching of previously computed filtered results. |
| `AvailableFilters` | `List<IFilter> AvailableFilters { get; }` | Returns a list of filters that can be applied to this object. |
| `CurrentFilter` | `IFilter CurrentFilter { get; set; }` | Gets or sets the filter currently applied to data requests. |
| `GetDataFilteredBy` | `double[] GetDataFilteredBy(IFilter filter, Event.Module.Channel.DataDisplayUnits displayUnits)` | Returns filtered data for the specified `filter` and `displayUnits`. |
#### `IFilter` Interface
*Namespace:* `DTS.Slice.Control.DAS.Channel`
| Member | Signature | Description |
|--------|-----------|-------------|
| `Name` | `string Name { get; }` | Returns a human-readable name/description of the filter. |
| `IsCfc` | `bool IsCfc { get; }` | Indicates whether the filter represents a cardinal CFC (Cycle Count Filter) value. |
| `Type` | `ChannelFilter Type { get; }` | Returns the filters type (e.g., low-pass, high-pass), represented by the `ChannelFilter` enum (not shown in source). |
| `CutoffFrequencyHz` | `double CutoffFrequencyHz { get; }` | Returns the cutoff frequency (in Hz) used by the filter. |
| `Apply` (1) | `double[] Apply(Event.Module.Channel input, Event.Module.Channel.DataDisplayUnits displayUnits, bool bUseLegacyTDCSofwareFilterAdjustment)` | Applies the filter to channel data, converting to `displayUnits`. The `bUseLegacyTDCSofwareFilterAdjustment` flag adjusts output one sample to the right for backward compatibility with legacy TDC software. |
| `Apply` (2) | `double[] Apply(double[] data, double sampleRate, bool bUseLegacyTDCSoftwareFilterAdjustment)` | Applies the filter to raw numeric data (assumed to be in base units), given the `sampleRate`. Same legacy adjustment flag applies. |
| `ToBaseString` | `string ToBaseString()` | Returns the base name of the filter (e.g., `"LowPass"`), without any decoration (e.g., no suffix like `" (10 Hz)"`). |
> **Note**: The `Apply` methods are overloaded: one accepts an `Event.Module.Channel` object (likely containing metadata and raw data), and the other accepts raw `double[]` data plus `sampleRate`.
---
### 3. **Invariants**
- `AvailableFilters` must be non-null and immutable in the sense that its contents should not change during the lifetime of the `IFilterable` instance (though the list itself may be recreated on each access).
- `CurrentFilter` must be either `null` or one of the items in `AvailableFilters`.
- `GetDataFilteredBy` must return data consistent with the specified `filter` and `displayUnits`, and must not mutate the underlying channel data.
- `IsCfc` and `Type` must be consistent: if `IsCfc` is `true`, then `Type` likely corresponds to a CFC-specific `ChannelFilter` value (exact mapping not specified in source).
- The `bUseLegacyTDCSofwareFilterAdjustment` parameter in `Apply` controls sample alignment: when `true`, output is shifted one sample to the right (i.e., delayed by one sample period) to preserve legacy behavior.
---
### 4. **Dependencies**
#### Dependencies *of* this module:
- `System.Collections.Generic` (`List<T>`)
- `DTS.Common.Utilities` (namespace referenced, but no types used directly in interface definitions)
- `Event.Module.Channel` (used in `Apply` signatures; type not shown, but assumed to contain raw channel data and metadata)
- `Event.Module.Channel.DataDisplayUnits` (enum or type defining unit conversion options; not shown)
#### Dependencies *on* this module:
- Any class implementing `IFilterable` (e.g., channel or group implementations) must provide filtering capabilities.
- Any class implementing `IFilter` must define concrete filtering logic (e.g., `LowPassFilter`, `HighPassFilter`, `CfcFilter`).
- Likely used by higher-level components in `DTS.Slice.Control.DAS` or `DTS.Slice.Control.CAS` namespaces (inferred from commented-out base interface in `IFilterable`).
---
### 5. **Gotchas**
- **Typo in parameter name**: In `GetDataFilteredBy`, the parameter `filter` is documented as `DTS.Slice.Control.CAS.Channel.IFilter`, but the actual interface is `DTS.Slice.Control.DAS.Channel.IFilter`. This may indicate outdated documentation or namespace refactoring.
- **Typo in flag name**: `bUseLegacyTDCSofwareFilterAdjustment` is misspelled as `Sofware` (missing 't') in one `Apply` signature (`Apply` overload 1), but correctly spelled as `TDCSoftware` in the second overload. This inconsistency may cause confusion or errors in code generation or reflection-based usage.
- **No explicit thread-safety guarantees**: Neither interface documents thread-safety; concurrent access to `CurrentFilter`, `UseFilterCaching`, or `Apply` may require external synchronization.
- **Caching behavior unspecified**: While `UseFilterCaching` toggles caching, the caching strategy (e.g., cache key, eviction policy, scope) is not defined here—implementation-specific.
- **`ToBaseString()` vs `ToString()`**: The comment implies `ToString()` is overridden elsewhere (likely in concrete implementations) to include metadata (e.g., `"LowPass (10 Hz)"`), while `ToBaseString()` returns the base name only. Consumers must be aware of this distinction when displaying filter names.
> **None identified from source alone.**
> *(Note: The above gotchas are inferred from inconsistencies in naming and documentation; no behavioral quirks beyond those are evident from the interfaces themselves.)*

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).

View File

@@ -0,0 +1,150 @@
---
source_files:
- Common/DTS.Common.Serialization/Control/Event/Module/ReviewableDasSerialNumberAttribute.cs
- Common/DTS.Common.Serialization/Control/Event/Module/ReviewableAttribute.cs
- Common/DTS.Common.Serialization/Control/Event/Module/ReviewableSampleRateAttribute.cs
- Common/DTS.Common.Serialization/Control/Event/Module/Module.cs
generated_at: "2026-04-16T03:41:50.953091+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "ac685bc8f1311025"
---
# Documentation: `DTS.Slice.Control.Event.Module.ReviewableAttribute` and Related Classes
## 1. Purpose
This module provides a framework for defining *reviewable attributes*—read-only, human-readable metadata properties attached to a specific `Event.Module` instance—that can be used during test review or reporting workflows. Specifically, it defines an abstract base class `ReviewableAttribute` and several concrete subclasses (e.g., `ReviewableDasSerialNumberAttribute`, `ReviewableSampleRateAttribute`, `ReviewableHardwareFrequencyAttribute`, `ReviewableTestDescriptionAttribute`) that expose module-level data (such as DAS serial number, sample rate, hardware anti-aliasing filter rate, and test description) in a standardized, reviewable format. These attributes are intended to be consumed by downstream review UIs or export tools that need to display or validate module-level metadata.
## 2. Public Interface
### `ReviewableAttribute` (Abstract Base Class)
- **Namespace**: `DTS.Slice.Control.Event.Module`
- **Inherits from**: `Slice.Control.ReviewableAttribute` (external type, not shown in provided sources)
- **Purpose**: Base class for all reviewable attributes attached to a `Module`.
#### Constructors
- `protected ReviewableAttribute(string name, DetermineValueString calculateValue)`
- **Parameters**:
- `name`: `string` The display name of the attribute.
- `calculateValue`: `DetermineValueString` A delegate (function pointer) that returns the attributes value as a `string`.
- **Behavior**: Initializes the base class with the provided name and value calculation delegate. This is the *only* constructor intended for use by subclasses.
- `public ReviewableAttribute(Event.Module module)` *(non-functional)*
- **Behavior**: Throws a `NotImplementedException` wrapped in a `Module.ReviewableAttribute.Exception`. This constructor exists only to enforce that subclasses must use the parameterized constructor.
#### Nested Exception Type
- `public class Exception : Exception`
- **Purpose**: Custom exception type used internally by `ReviewableAttribute` for constructor failures.
---
### `ReviewableDasSerialNumberAttribute`
- **Namespace**: `DTS.Slice.Control.Event.Module`
- **Inherits from**: `ReviewableAttribute`
- **Purpose**: Exposes the DAS serial number of the parent `Module`.
#### Constructor
- `public ReviewableDasSerialNumberAttribute(Event.Module module)`
- **Parameters**:
- `module`: `Event.Module` The module to which this attribute is attached.
- **Behavior**: Calls the base constructor with:
- `name = "DAS Serial Number"`
- `calculateValue = () => module.DasSerialNumber`
- **Result**: The attributes value is the string value of `module.DasSerialNumber`.
---
### `ReviewableSampleRateAttribute`
- **Namespace**: `DTS.Slice.Control.Event.Module`
- **Inherits from**: `ReviewableAttribute`
- **Purpose**: Exposes the sample rate of the module, formatted with thousand separators.
#### Constructor
- `public ReviewableSampleRateAttribute(Event.Module module)`
- **Parameters**:
- `module`: `Event.Module`
- **Behavior**: Calls base constructor with:
- `name = "Sample Rate"`
- `calculateValue = () => module.SampleRateHz.ToString("N")`
- **Result**: The attributes value is `module.SampleRateHz.ToString("N")` (e.g., `"10,000.00"`).
---
### `ReviewableTestDescriptionAttribute`
- **Namespace**: `DTS.Slice.Control.Event.Module`
- **Inherits from**: `ReviewableAttribute`
- **Purpose**: Exposes the description of the *parent event* (not the module itself).
#### Constructor
- `public ReviewableTestDescriptionAttribute(Event.Module module)`
- **Parameters**:
- `module`: `Event.Module`
- **Behavior**: Calls base constructor with:
- `name = "Test Description"`
- `calculateValue = () => module.ParentEvent.Description`
- **Result**: The attributes value is `module.ParentEvent.Description`.
---
### `ReviewableHardwareFrequencyAttribute`
- **Namespace**: `DTS.Slice.Control.Event.Module`
- **Inherits from**: `ReviewableAttribute`
- **Purpose**: Exposes the hardware anti-aliasing filter rate, formatted to two decimal places.
#### Constructor
- `public ReviewableHardwareFrequencyAttribute(Event.Module module)`
- **Parameters**:
- `module`: `Event.Module`
- **Behavior**: Calls base constructor with:
- `name = "HW AAF"`
- `calculateValue = () => module.AaFilterRateHz.ToString("N2")`
- **Result**: The attributes value is `module.AaFilterRateHz.ToString("N2")` (e.g., `"5,000.00"`).
---
## 3. Invariants
- **Attribute Name Consistency**: Each subclass hardcodes its `name` in the base constructor call. The names used are:
- `"DAS Serial Number"`
- `"Sample Rate"`
- `"Test Description"`
- `"HW AAF"`
- **Value Calculation Must Not Be Null**: The `calculateValue` delegate passed to the base constructor must return a non-null `string`. If `module.DasSerialNumber`, `module.SampleRateHz`, etc., are `null` or `0`, the `ToString()` call may produce `"0"` or empty string, but no validation is performed.
- **Parent Module Must Be Non-null**: The `module` parameter passed to any subclass constructor must be non-null; otherwise, dereferencing `module.DasSerialNumber`, `module.SampleRateHz`, etc., will throw `NullReferenceException`.
- **No Runtime Validation**: There is no validation in the constructors or elsewhere to ensure the attribute name or value format conforms to any external schema—only formatting is applied via `ToString()`.
## 4. Dependencies
### Dependencies *of* this module:
- **`DTS.Slice.Control.Event.Module`** (`Module.cs`): Provides the `Module` class whose properties (`DasSerialNumber`, `SampleRateHz`, `AaFilterRateHz`, `ParentEvent.Description`) are accessed by the attribute subclasses.
- **`DTS.Slice.Control.ReviewableAttribute`** (external): Base class for `ReviewableAttribute`. Its `DetermineValueString` delegate type is assumed to be defined there.
- **`DTS.Utilities`**: Used only for logging (not directly used in these files, but imported).
- **`System`**: Standard .NET types (`string`, `delegate`, `Exception`, etc.).
### Dependencies *on* this module:
- **Unknown from source alone**: No direct callers are visible in the provided files. However, the naming and structure suggest this is used by a review/reporting subsystem (e.g., UI or export tool) that instantiates these attributes and calls into the base `ReviewableAttribute` API (e.g., to retrieve `Name` and `Value`).
## 5. Gotchas
- **Misleading XML Comments**: `ReviewableSampleRateAttribute` and `ReviewableHardwareFrequencyAttribute` are documented as “A reviewable filter frequency attribute attached to a specific channel.” — but they are attached to a `Module`, not a `Channel`. This is likely copy-paste error in comments.
- **`ReviewableTestDescriptionAttribute` accesses `ParentEvent.Description`**, not `module.Description`. This may be intentional (e.g., to avoid duplication if description is event-level), but its non-obvious and could cause confusion.
- **`ReviewableAttribute` constructor with `module` parameter is non-functional**: The constructor throws `NotImplementedException`. Subclasses *must* use the `protected` constructor with `name` and `calculateValue`. This is a safeguard, but could mislead developers into thinking the single-parameter constructor is usable.
- **No `ToString()` formatting validation**: If `module.SampleRateHz` or `module.AaFilterRateHz` is `NaN` or `Infinity`, `ToString("N")` or `ToString("N2")` may produce `"NaN"`, `"Infinity"`, or `"Infinity"`—which may not be desired for review displays.
- **`StartRecordTimestampNanoSec` bug in `FromDtsSerializationTestModule`**: In `Module.cs`, line `TriggerTimestampNanoSec = that.StartRecordTimestampNanoSec;` appears to be a typo (should be `that.TriggerTimestampNanoSec`). While not directly in this module, it suggests potential data inconsistency risk in related code.
- **No `Equals`/`GetHashCode` override in `ReviewableAttribute` subclasses**: Since these are likely used as keys or in collections, lack of value-based equality may cause subtle bugs. However, this is not evident from the source alone—no usage patterns are shown.
> **Note**: No usage of `ReviewableAttribute` beyond construction is visible in the provided files. The actual mechanism for invoking `calculateValue` (e.g., via a public `Value` property inherited from `Slice.Control.ReviewableAttribute`) is not documented here and must be assumed from the base class.

View File

@@ -0,0 +1,81 @@
---
source_files:
- Common/DTS.Common.Serialization/Control/Event/Module/AnalogInputChannel/ReviewableShuntDeflectionAttribute.cs
- Common/DTS.Common.Serialization/Control/Event/Module/AnalogInputChannel/ReviewableFilterFrequencyAttribute.cs
- Common/DTS.Common.Serialization/Control/Event/Module/AnalogInputChannel/ReviewableIsoCodeAttribute.cs
- Common/DTS.Common.Serialization/Control/Event/Module/AnalogInputChannel/ReviewableDescriptionAttribute.cs
- Common/DTS.Common.Serialization/Control/Event/Module/AnalogInputChannel/ReviewableSerialNumberAttribute.cs
- Common/DTS.Common.Serialization/Control/Event/Module/AnalogInputChannel/ReviewableUnitsAttribute.cs
- Common/DTS.Common.Serialization/Control/Event/Module/AnalogInputChannel/ReviewableMinMaxEuAttribute.cs
- Common/DTS.Common.Serialization/Control/Event/Module/AnalogInputChannel/ReviewableCfcAttribute.cs
- Common/DTS.Common.Serialization/Control/Event/Module/AnalogInputChannel/ReviewableTargetShuntDeflectionAttribute.cs
- Common/DTS.Common.Serialization/Control/Event/Module/AnalogInputChannel/ReviewableMeasuredShuntDeflectionAttribute.cs
- Common/DTS.Common.Serialization/Control/Event/Module/AnalogInputChannel/ReviewableShuntDeflectionPercentageAttribute.cs
generated_at: "2026-04-16T03:42:18.353896+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "b040e834d4537e76"
---
# `DTS.Slice.Control.Event.Module.AnalogInputChannel.ReviewableAttribute` Implementations
## 1. Purpose
This module provides a set of concrete `ReviewableAttribute` subclasses used to expose specific channel metadata and calibration-related values for review in the DTS Slice control/event system. Each attribute encapsulates a named, human-readable property of an `AnalogInputChannel` (e.g., serial number, filter settings, shunt calibration metrics), formatted as a string via a delegate. These attributes are intended for use in UI review workflows or audit logs where static or quasi-static channel configuration and calibration state must be presented consistently.
## 2. Public Interface
All classes inherit from `Slice.Control.Event.Module.Channel.ReviewableAttribute`. Each constructor accepts a single `Event.Module.Channel` parameter and passes a display name and a `Func<string>` to the base constructor.
| Class | Constructor | Display Name | Behavior |
|-------|-------------|--------------|----------|
| `ReviewableShuntDeflectionAttribute` | `ReviewableShuntDeflectionAttribute(Channel)` | `"Shunt Deflection (mV)"` | Returns `channel.MeasuredShuntDeflectionMv.ToString("F1")`. Requires `channel` to implement `DTS.DAS.Concepts.DAS.Channel.IShuntAware`. |
| `ReviewableFilterFrequencyAttribute` | `ReviewableFilterFrequencyAttribute(Channel)` | `"Filter Frequency"` | Returns `(int)(channel.CurrentFilter as SaeJ211Filter).CutoffFrequencyHz.ToString("N")`. Requires `channel.CurrentFilter` to be a `SaeJ211Filter`. |
| `ReviewableIsoCodeAttribute` | `ReviewableIsoCodeAttribute(Channel)` | `"ISO Code"` | Returns `(channel as AnalogInputChannel).IsoCode.ToString()`. Requires `channel` to be an `AnalogInputChannel`. |
| `ReviewableDescriptionAttribute` | `ReviewableDescriptionAttribute(Channel)` | `"Description"` | Returns `channel.ChannelDescriptionString`. |
| `ReviewableSerialNumberAttribute` | `ReviewableSerialNumberAttribute(Channel)` | `"Serial Number"` | Returns `(channel as AnalogInputChannel).SerialNumber.ToString()`. Requires `channel` to be an `AnalogInputChannel`. |
| `ReviewableUnitsAttribute` | `ReviewableUnitsAttribute(Channel)` | `"Units"` | Returns `channel.EngineeringUnits.ToString()`. Requires `channel` to implement `DTS.DAS.Concepts.DAS.Channel.IEngineeringUnitAware`. |
| `ReviewableMinMaxEuAttribute` | `ReviewableMinMaxEuAttribute(Channel)` | `"Max/Min (EU)"` | Returns `channel.DataMaxFilteredEu.ToString("F1") + "/" + channel.DataMinFilteredEu.ToString("F1")`. |
| `ReviewableCfcAttribute` | `ReviewableCfcAttribute(Channel)` | `"CFC"` | Returns `"N/A"` if `channel.CurrentFilter.Type == ChannelFilter.AdHoc`; otherwise returns `(new CfcValueAttributeCoder()).DecodeAttributeValue((channel.CurrentFilter as SaeJ211Filter).Type).ToString()`. Requires `channel.CurrentFilter` to be a `SaeJ211Filter`. |
| `ReviewableTargetShuntDeflectionAttribute` | `ReviewableTargetShuntDeflectionAttribute(Channel)` | `"Target Shunt Deflection (mV)"` | Returns `channel.TargetShuntDeflectionMv.ToString("F1")`. Requires `channel` to implement `IShuntAware`. |
| `ReviewableTargetCalSignalAttribute` | `ReviewableTargetCalSignalAttribute(Channel)` | `"Target Calibration Signal (mV)"` | Returns `channel.TargetCalSignalMv.ToString("F1")`. Requires `channel` to implement `DTS.DAS.Concepts.DAS.Channel.ICalSignalAware`. |
| `ReviewableMeasuredShuntDeflectionAttribute` | `ReviewableMeasuredShuntDeflectionAttribute(Channel)` | `"Measured Shunt Deflection (mV)"` | Returns `channel.MeasuredShuntDeflectionMv.ToString("F1")`. Requires `channel` to implement `IShuntAware`. |
| `ReviewableMeasuredCalSignalAttribute` | `ReviewableMeasuredCalSignalAttribute(Channel)` | `"Measured Calibration Signal (mV)"` | Returns `channel.MeasuredCalSignalMv.ToString("F1")`. Requires `channel` to implement `ICalSignalAware`. |
| `ReviewableShuntDeflectionPercentageAttribute` | `ReviewableShuntDeflectionPercentageAttribute(Channel)` | `"Shunt Error (%)"` | Returns `100.0 * (MeasuredShuntDeflectionMv - TargetShuntDeflectionMv) / TargetShuntDeflectionMv.ToString("F1")`. Requires `channel` to implement `IShuntAware`. |
| `ReviewableCalSignalPercentageAttribute` | `ReviewableCalSignalPercentageAttribute(Channel)` | `"Calibration Signal Error (%)"` | Returns `100.0 * (MeasuredCalSignalMv - TargetCalSignalMv) / TargetCalSignalMv.ToString("F1")`. Requires `channel` to implement `ICalSignalAware`. |
## 3. Invariants
- **All attributes are read-only**: Each attributes value is computed on-demand via a delegate passed to the base class; no internal state is stored beyond the delegate capture.
- **Type assumptions**: Each attribute assumes the `channel` parameter supports specific interfaces or concrete types:
- `IShuntAware` for shunt-related attributes (`ReviewableShuntDeflectionAttribute`, `ReviewableTargetShuntDeflectionAttribute`, `ReviewableMeasuredShuntDeflectionAttribute`, `ReviewableShuntDeflectionPercentageAttribute`).
- `ICalSignalAware` for calibration signal attributes (`ReviewableTargetCalSignalAttribute`, `ReviewableMeasuredCalSignalAttribute`, `ReviewableCalSignalPercentageAttribute`).
- `IEngineeringUnitAware` for `ReviewableUnitsAttribute`.
- `SaeJ211Filter` for `ReviewableFilterFrequencyAttribute` and `ReviewableCfcAttribute`.
- `AnalogInputChannel` (via `as`) for `ReviewableIsoCodeAttribute` and `ReviewableSerialNumberAttribute`.
- **Null-safety**: None of the attributes perform explicit null checks. If `channel` is `null`, or if the required interface/type cast fails (e.g., `channel.CurrentFilter` is not a `SaeJ211Filter`), a `NullReferenceException` or `InvalidCastException` will occur at evaluation time.
- **Formatting consistency**: All numeric values are formatted with `"F1"` (1 decimal place) or `"N"` (thousands separator, no decimals) as shown.
## 4. Dependencies
### Internal Dependencies (from source):
- `DTS.Slice.Control.Event.Module.Channel.ReviewableAttribute` (base class, not shown but referenced).
- `DTS.DAS.Concepts.DAS.Channel.IShuntAware`, `ICalSignalAware`, `IEngineeringUnitAware` (interfaces).
- `DTS.DAS.Concepts.DAS.Channel.SaeJ211Filter`, `ChannelFilter` (types).
- `DTS.Utilities.CfcValueAttributeCoder` (used in `ReviewableCfcAttribute`).
- `DTS.Slice.Control.Event.Module.AnalogInputChannel` (namespace context and partial class definitions).
### External Dependencies:
- `System` (core runtime).
- `DTS.Utilities` (assembly reference required for `CfcValueAttributeCoder` and `SaeJ211Filter`).
### Inferred Usage:
- These attributes are likely instantiated and collected by a higher-level component that iterates over `AnalogInputChannel` instances and exposes their reviewable metadata (e.g., for calibration reports or UI inspection panels). The repeated pattern suggests a factory or registration mechanism exists elsewhere (not visible here).
## 5. Gotchas
- **Ambiguous naming**: `ReviewableShuntDeflectionAttribute` (in first file) and `ReviewableMeasuredShuntDeflectionAttribute` (in later file) have identical implementation logic and display names. This duplication is likely unintentional or legacy; only one should be used, or naming should be clarified (e.g., “Shunt Deflection (mV)” vs. “Measured Shunt Deflection (mV)”).
- **Missing null guards**: All attributes assume `channel` is non-null and implements required interfaces. A cast failure (e.g., `channel as DTS.DAS.Concepts.DAS.Channel.IShuntAware` returning `null`) will cause a `NullReferenceException` at delegate invocation time, not construction.
- **`ReviewableCfcAttribute` logic**: The commented-out line suggests a previous implementation using `CfcValueAttributeCoder.DecodeAttributeValue` directly, but the current version adds a special case for `ChannelFilter.AdHoc`. This implies that `AdHoc` filters may not have a valid `Type` for decoding, and the attribute must handle this explicitly.
- **`ReviewableFilterFrequencyAttribute` casts `channel.CurrentFilter` to `SaeJ211Filter` without checking**: If `CurrentFilter` is not a `SaeJ211Filter`, this will throw `InvalidCastException`.
- **`ReviewableIsoCodeAttribute` comment is incorrect**: Its summary says “serial number attribute” but the class name and implementation clearly indicate its for ISO code. Likely copy-paste error in documentation.
- **No validation of division-by-zero**: In `ReviewableShuntDeflectionPercentageAttribute` and `ReviewableCalSignalPercentageAttribute`, if `TargetShuntDeflectionMv` or `TargetCalSignalMv` is zero, a `DivideByZeroException` will occur.

View File

@@ -0,0 +1,302 @@
---
source_files:
- Common/DTS.Common.Serialization/Control/Event/Module/Channel/DataValues.cs
- Common/DTS.Common.Serialization/Control/Event/Module/Channel/ReviewableAttribute.NotApplicableException.cs
- Common/DTS.Common.Serialization/Control/Event/Module/Channel/Filter.cs
- Common/DTS.Common.Serialization/Control/Event/Module/Channel/ChannelDefaultSaeJ211Filter.cs
- Common/DTS.Common.Serialization/Control/Event/Module/Channel/CalculatedChannel.cs
- Common/DTS.Common.Serialization/Control/Event/Module/Channel/SaeJ211Filter.cs
generated_at: "2026-04-16T03:42:34.925173+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "2400faf1f9897d63"
---
# Documentation: `DTS.Slice.Control.Event.Module.Channel` Subsystem
## 1. Purpose
This module provides core data structures and abstractions for representing and manipulating channel data within event recordings in the DTS Slice Control system. It defines the foundational types for physical channels, calculated channels, filters (including SAE J211compliant filters), and data storage mechanisms (in-memory vs. memory-mapped). The subsystem enables filtering, unit conversion, and serialization of channel data, supporting both raw sensor inputs (ADC) and derived quantities (EU, mV), as well as computed channels (e.g., integrals, derivatives, FFTs). It serves as the data model layer for event analysis and review workflows.
## 2. Public Interface
### `DataValues` class
*Defined in: `Common/DTS.Common.Serialization/Control/Event/Module/Channel/DataValues.cs`*
- **`DataValues()`**
Initializes a `DataValues` instance using in-memory storage (i.e., `UseMemoryMappedFile = false`).
- **`DataValues(bool useMemoryMappedFile)`**
Initializes a `DataValues` instance. If `useMemoryMappedFile` is `true`, the instance is configured to use memory-mapped files for data storage (intended for large datasets exceeding process memory limits).
- **`UseMemoryMappedFile: bool`**
Property controlling whether the instance uses memory-mapped files (`true`) or in-memory storage (`false`). Implemented via a `Property<bool>` wrapper.
---
### `Filter` abstract class
*Defined in: `Common/DTS.Common.Serialization/Control/Event/Module/Channel/Filter.cs`*
- **`Name: string` (abstract)**
Returns a descriptive name for the filter (e.g., `"6G"` for a 6g filter, or `"123.45Hz"` for ad hoc).
- **`IsCfc: bool` (abstract)**
Returns `true` if the filter corresponds to a defined CFC (Channel Filter Classification) value; `false` for `Unfiltered` or `AdHoc`.
- **`Type: ChannelFilter` (abstract)**
Returns the canonical `ChannelFilter` enum value representing the filter (e.g., `ChannelFilter.SixG`, `ChannelFilter.AdHoc`).
- **`CutoffFrequencyHz: double` (abstract)**
Returns the filters cutoff frequency in hertz.
- **`Apply(Channel input, DataDisplayUnits displayUnits, bool bUseLegacyTDCSoftwareFilterAdjustment): double[]` (abstract)**
Applies the filter to the unfiltered data of the specified `input` channel, returning filtered data in the requested `displayUnits` (ADC, EU, or mV). The `bUseLegacyTDCSoftwareFilterAdjustment` flag controls whether a one-sample phase shift is applied to match legacy TDC behavior (see issue #8747).
- **`Apply(double[] data, double sampleRate, bool bUseLegacyTDCSoftwareFilterAdjustment): double[]` (abstract)**
Applies the filter to a raw data array with known `sampleRate`, returning filtered data. Used when channel context is unavailable.
- **`ToBaseString(): string` (abstract)**
Returns the filters base name (e.g., `"6G"`), without any decorative prefix (e.g., `"Default (6G)"`). Distinct from `ToString()`.
---
### `SaeJ211Filter` class
*Defined in: `Common/DTS.Common.Serialization/Control/Event/Module/Channel/SaeJ211Filter.cs`*
- **`SaeJ211Filter(ChannelFilter originalType)`**
Initializes a filter for a CFC-compliant type (e.g., `ChannelFilter.SixG`). Throws `Exception` if `originalType == ChannelFilter.AdHoc`.
- **`SaeJ211Filter(double cutoffFrequencyHz)`**
Initializes an ad hoc filter with the specified cutoff frequency.
- **`SaeJ211Filter(SaeJ211Filter originalFilter)`**
Copy constructor.
- **`OriginalType: ChannelFilter`**
Stores the original filter type passed at construction (e.g., `AdHoc` for ad hoc filters). Not modifiable after construction.
- **`Type: ChannelFilter` (override)**
Returns the *effective* filter type: if `OriginalType == AdHoc`, resolves to the nearest matching CFC (or `AdHoc` if no match); otherwise returns `OriginalType`.
- **`IsCfc: bool` (override)**
Returns `true` if `Type` is neither `Unfiltered` nor `AdHoc`.
- **`CutoffFrequencyHz: double` (override)**
Returns the cutoff frequency in Hz (derived from `OriginalType` or explicitly set for ad hoc filters).
- **`IsoDescription: char`**
Returns the first character of the ISO description for `OriginalType` (e.g., `'G'` for `SixG`).
- **`Name: string` (override)**
Returns a human-readable name:
- For `AdHoc`: `"123.45Hz"`
- For CFC types: description from `DescriptionAttributeCoder<ChannelFilter>` (e.g., `"6G"`).
- **`Apply(...)` (override)**
Implements filtering using `FilterUtility`. Supports filtering from `UnfilteredData`, `UnfilteredDataEu`, or `UnfilteredDataMv` depending on `displayUnits`. Logs warnings for invalid data via `APILogger`.
- **`Parse(string serialization): Filter` (static)**
Parses a serialized filter string (e.g., `"6G"`, `"123.45Hz"`) into a `Filter` instance. Falls back to `Unfiltered` on parse failure.
- **`Equals(object obj): bool` (override)**
Case-insensitive comparison of filter names.
- **`GetHashCode(): int` (override)**
Hash code based on lowercase filter name.
- **`ToString(): string` (override)**
Returns `Name`.
- **`ToBaseString(): string` (override)**
Returns `Name`.
---
### `DefaultSaeJ211Filter` class
*Defined in: `Common/DTS.Common.Serialization/Control/Event/Module/Channel/ChannelDefaultSaeJ211Filter.cs`*
- **`DefaultSaeJ211Filter(SaeJ211Filter filter)`**
Copy constructor.
- **`DefaultSaeJ211Filter(ChannelFilter filterType)`**
Initializes with a CFC filter type.
- **`DefaultSaeJ211Filter(double adHocFrequency)`**
Initializes with an ad hoc frequency.
- **`Name: string` (override)**
Returns `"Default (" + base.Name + ")"` (e.g., `"Default (6G)"`).
- **`ToBaseString(): string` (override)**
Returns `base.Name` (e.g., `"6G"`).
- **`ToString(): string` (override)**
Returns `Name`.
---
### `CalculatedChannel` abstract class
*Defined in: `Common/DTS.Common.Serialization/Control/Event/Module/Channel/CalculatedChannel.cs`*
- **`Operation` enum**
Defines supported calculations: `Integral`, `Derivative`, `HeadInjuryCriteria`, `FFT`, `ImportedCSV`, `Resultant`, `TSR`, `Scale`, `Offset`, `Sine`, `Cosine`.
- **`CalculationType: Operation`**
Returns the operation performed by this channel.
- **`X: double[]`, `Y: double[]`**
Read-only arrays of x-axis and y-axis data points.
- **`XAxis: XUnits`**
X-axis unit type (`msec`, `sec`, `Hz`, `samples`).
- **`XUnitsString: string`**
Human-readable unit string (e.g., `"ms"`, `"Hz"`).
- **`EngineeringUnits: string`**
Y-axis engineering units (e.g., `"g"`, `"m/s"`).
- **`SupportsADC: bool` (override)**
Always `false` for calculated channels.
- **`SupportsEU: bool` (override)**
Always `true`.
- **`SupportsmV: bool` (override)**
Always `false`.
- **`ActualMaxRangeEu`, `ActualMinRangeEu`, `DataMaxEu`, `DataMinEu`, `DataRangeEu`, `DataHalfRangeValueEu` (overrides)**
Computed from `Y` data (e.g., `DataMaxEu = _y.Max()`).
- **`IsConfigured: bool` (override)**
Always `true`; setting throws `NotSupportedException`.
- **`GetUnfilteredDataEu(): List<double>` (override)**
Returns a copy of `Y`.
- **Constructors**
- `CalculatedChannel(string name, XUnits xAxis, string yAxis, double[] xValues, double[] yValues, Operation calcType, int number, Module parentModule)`
Initializes with data, axis labels, and calculation type. Sets `CurrentFilter` to `DefaultSaeJ211Filter(ChannelFilter.Unfiltered)`.
- **`ToString(): string` (override)**
Returns `ChannelDescriptionString` or `"N/A"`.
---
### Derived `CalculatedChannel` classes
*Defined in: `Common/DTS.Common.Serialization/Control/Event/Module/Channel/CalculatedChannel.cs`*
- **`FFTCalculatedChannel`**
- **`PeakFrequency: double`**
Returns the peak frequency from the FFT.
- **`IntegralCalculatedChannel`, `DerivativeCalculatedChannel`, `ScaleCalculatedChannel`, `OffsetCalculatedChannel`, `ResultantCalculatedChannel`, `AdditiveVectorCalculatedChannel`, `SineCalculatedChannel`, `CosineCalculatedChannel`**
All inherit from `CalculatedChannel` with no additional public members.
> **Note**: `HICCalculatedChannel` is commented out in source and not documented.
---
### `ReviewableAttribute.NotApplicableException` class
*Defined in: `Common/DTS.Common.Serialization/Control/Event/Module/Channel/ReviewableAttribute.NotApplicableException.cs`*
- **`NotApplicableException()`**
Default constructor.
- **`NotApplicableException(string msg)`**
Constructor with message.
- **`NotApplicableException(string msg, Exception innerEx)`**
Constructor with message and inner exception.
> Inherits from `ApplicationException`.
---
## 3. Invariants
- **`DataValues.UseMemoryMappedFile`**
Once set during construction, this flag determines the storage strategy for channel data. No runtime switching is exposed.
- **`SaeJ211Filter.OriginalType`**
Immutable after construction. `Type` may differ from `OriginalType` for ad hoc filters (resolved to nearest CFC or `AdHoc`).
- **`Filter.Type`**
For ad hoc filters (`OriginalType == AdHoc`), `Type` is computed dynamically based on `CutoffFrequencyHz` (via `ConvertFrequencyToChannelFilter`). If frequency matches a CFC enum value, `Type` becomes that CFC; otherwise remains `AdHoc`.
- **`CalculatedChannel` properties**
- `SupportsADC` and `SupportsmV` are always `false`; `SupportsEU` is always `true`.
- Range properties (`ActualMaxRangeEu`, etc.) are derived from `Y` data and may change if `Y` is modified (though `Y` is read-only via public API).
- **`Filter.Apply(...)`**
Filtering always uses `FilterUtility` with `Cfc = Type`, `AdHocFrequency = CutoffFrequencyHz`, and `SampleRate` from channel or parameter. Invalid data triggers logging and exception.
- **`Filter.Parse(...)`**
Returns `Unfiltered` filter on parse failure (not `null`).
---
## 4. Dependencies
### Internal Dependencies (from source)
- **`DTS.Common.Utilities`**
Used for `Property<T>`, logging (`APILogger`), and encoding utilities (`CfcValueAttributeCoder`, `DescriptionAttributeCoder`, `IsoDescriptionAttributeCoder`).
- **`DTS.Slice.Control.DAS.Channel`**
Referenced for `ChannelFilter` enum and `DataDisplayUnits` enum.
- **`DTS.Common.DAS.Concepts.DAS.Channel.IEngineeringUnitAware`**
Implemented by `CalculatedChannel`.
- **Serialization types**
`Serialization.SliceRaw.File.PersistentChannel`, `Serialization.TDAS.File.PersistentChannel`, `ILargeDataAware`, `Serialization.Test.Module.Channel`.
- **`DTS.Calculations.HeadInjuryCriterion.HICResult`**
Referenced in commented-out `HICCalculatedChannel` code.
- **`DTS.Common.Utilities.SaeJ211`**
Used for `FilterUtility` and related encoding.
### External Dependencies (inferred)
- **`System`**
Standard .NET types (`Exception`, `ApplicationException`, `CultureInfo`, `Enum`, etc.).
- **Windows Forms (commented)**
`System.Windows.Forms.MessageBox` appears in commented-out code (not active).
---
## 5. Gotchas
- **`DataValues` has no data storage logic**
The class only configures storage mode (`UseMemoryMappedFile`). Actual data handling is delegated to `Channel` (not shown in these files). `DataValues` is a configuration helper, not a data container.
- **`SaeJ211Filter.Type` may differ from `OriginalType`**
For ad hoc filters, `Type` resolves to the nearest CFC match. This can cause `IsCfc` to return `true` even if `OriginalType == AdHoc`.
- **`Filter.Parse(...)` silently falls back to `Unfiltered`**
On parse failure, returns `new SaeJ211Filter(ChannelFilter.Unfiltered)` instead of throwing. Callers must validate if needed.
- **`DefaultSaeJ211Filter.ToString()` vs `ToBaseString()`**
`ToString()` returns `"Default (X)"`, while `ToBaseString()` returns `"X"`. Confusing if not documented.
- **`CalculatedChannel` range properties assume non-empty `Y`**
`DataMaxEu`, `DataMinEu`, etc., use `_y.Max()`/`_y.Min()` without checking for empty data. Will throw `InvalidOperationException` if `Y` is empty.
- **`SupportsADC`/`SupportsmV` are hard-coded `false`**
Calculated channels never support raw ADC or mV; only engineering units (EU). Attempting to access `ActualMinRangeMv` throws `NotImplementedException`.
- **`CalculatedChannel` serialization methods throw `NotSupportedException`**
`FromDtsSerializationTestModuleChannel`, `ToDtsSerializationTestModuleChannel`, `SetPropertyValuesFrom(...)` all throw. Calculated channels are not serializable via these paths.
- **`Filter.Apply(...)` logs invalid data but throws**
`FilterUtility.InvalidDataDelegate` logs via `APILogger` but then throws an exception. No silent failure.
- **`ChannelFilter` enum values are used as frequencies**
CFC filters (e.g., `ChannelFilter.SixG`) are implicitly cast to `double` for frequency. This relies on enum underlying values matching CFC frequencies.
- **`IsoDescription` uses `OriginalType`**
The ISO description character is derived from `OriginalType`, not `Type`. For ad hoc filters, this may be `Unfiltered` (not meaningful).
- **`DataValues` constructor catches and rethrows as `Exception`**
Any exception during construction is wrapped in a generic `Exception` with a message like `"encountered problem constructing DTS.Slice.Control.Event.Module.Channel.DataValues"`. Original exception is preserved in `InnerException`.