178 lines
9.5 KiB
Markdown
178 lines
9.5 KiB
Markdown
|
|
---
|
||
|
|
source_files:
|
||
|
|
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.AddCalculatedChannel/ViewModel/AddCalculatedChannelViewModel.cs
|
||
|
|
generated_at: "2026-04-16T11:21:00.745415+00:00"
|
||
|
|
model: "zai-org/GLM-5-FP8"
|
||
|
|
schema_version: 1
|
||
|
|
sha256: "5cfd5d272102b3bf"
|
||
|
|
---
|
||
|
|
|
||
|
|
# Documentation: AddCalculatedChannelViewModel
|
||
|
|
|
||
|
|
## 1. Purpose
|
||
|
|
|
||
|
|
This module provides a ViewModel for the "Add Calculated Channel" feature in the DTS Viewer application. It enables users to create derived data channels from existing test data by applying mathematical transformations (integrals, derivatives, trigonometric functions) or specialized biomechanical calculations (HIC, 3D IR-Tracc, Resultant). The ViewModel manages channel selection UI state, validates user inputs, orchestrates the calculated channel creation via `CalculatedChannelCreator`, and persists changes back to `.dts` test files.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 2. Public Interface
|
||
|
|
|
||
|
|
### Public Properties
|
||
|
|
|
||
|
|
| Property | Type | Description |
|
||
|
|
|----------|------|-------------|
|
||
|
|
| `View` | `IBaseView` | The associated view instance. |
|
||
|
|
| `Parent` | `IBaseViewModel` | Reference to the parent ViewModel. |
|
||
|
|
| `ContextSearchRegion` | `object` | Placeholder for context search region. |
|
||
|
|
| `NotificationRequest` | `InteractionRequest<Notification>` | Raises notification dialogs. |
|
||
|
|
| `ConfirmationRequest` | `InteractionRequest<Confirmation>` | Raises confirmation dialogs. |
|
||
|
|
| `HeaderInfo` | `string` | Returns `"AddCalculatedChannelRegion"`. |
|
||
|
|
| `IsBusy` | `bool` | **Throws `NotImplementedException`** on get/set. |
|
||
|
|
| `IsDirty` | `bool` | **Throws `NotImplementedException`** on get. |
|
||
|
|
| `IsAddCalculatedChannelIncluded` | `bool` | Feature inclusion flag. |
|
||
|
|
| `IncludeGroupNameInISOExport` | `bool` | Controls ISO export formatting. |
|
||
|
|
| `DefaultDTSEncoding` | `int` | Encoding code page for DTS file operations. |
|
||
|
|
| `ChannelName` | `string` | Name for the new calculated channel. |
|
||
|
|
| `ChannelDescription` | `string` | Auto-generated description based on selected calculation and channels. |
|
||
|
|
| `IsoCode` | `string` | ISO code for the channel (defaults to `"NONE"`). |
|
||
|
|
| `SingleChannelSelectorVisibility` | `bool` | Controls visibility for single-channel selection UI. |
|
||
|
|
| `HICChannelSelectorVisibility` | `bool` | Controls visibility for HIC channel selection UI. |
|
||
|
|
| `MultipleChannelSelectorVisibility` | `bool` | Controls visibility for multi-channel selection UI. |
|
||
|
|
| `ThreeDIRTRACCVisibility` | `bool` | Controls visibility for 3D IR-Tracc selection UI. |
|
||
|
|
| `CalculationList` | `CalculationHelper[]` | Lazy-initialized list of available calculations. |
|
||
|
|
| `SelectedCalculation` | `CalculationHelper` | Currently selected calculation type. |
|
||
|
|
| `ChannelList` | `ObservableCollection<ITestChannel>` | All available input channels. |
|
||
|
|
| `ChannelListObjects` | `ObservableCollection<ChannelHelper>` | Wrapped channel objects with `IsIncluded` selection state. |
|
||
|
|
| `AvailableHICChannels` | `ChannelHelper[]` | Channels with acceleration units valid for HIC calculation. |
|
||
|
|
| `HICAccelerationX/Y/Z` | `ChannelHelper` | Selected X/Y/Z acceleration channels for HIC. |
|
||
|
|
| `HICLength` | `int` | HIC calculation length (default: 16). |
|
||
|
|
| `SourceChannel` | `ITestChannel` | Selected source channel for single-channel calculations. |
|
||
|
|
| `IRTraccChannelList` | `ObservableCollection<ChannelHelper>` | Valid IR-Tracc channels. |
|
||
|
|
| `IRTraccChannel` | `ChannelHelper` | Selected IR-Tracc channel. |
|
||
|
|
| `Pot1ChannelList/Pot2ChannelList` | `ObservableCollection<ChannelHelper>` | Valid potentiometer channels. |
|
||
|
|
| `Pot1Channel/Pot2Channel` | `ChannelHelper` | Selected potentiometer channels. |
|
||
|
|
|
||
|
|
### Public Commands
|
||
|
|
|
||
|
|
| Command | Handler | Description |
|
||
|
|
|---------|---------|-------------|
|
||
|
|
| `AddCalculatedChannelCommand` | `AddCalculatedChannel(object obj)` | Validates inputs, creates calculated channel(s), and saves to `.dts` file. |
|
||
|
|
|
||
|
|
### Public Methods
|
||
|
|
|
||
|
|
| Method | Signature | Description |
|
||
|
|
|--------|-----------|-------------|
|
||
|
|
| `PublishChanges` | `void PublishChanges()` | **Not implemented** (contains commented-out `NotImplementedException`). |
|
||
|
|
| `Initialize` | `void Initialize()` | Calls `Initialize(null)`. |
|
||
|
|
| `Initialize` | `void Initialize(object parameter)` | Sets `Parent` from parameter and subscribes to events. |
|
||
|
|
| `Activated` | `void Activated()` | Resets UI state: sets default source channel, ISO code, calculation, and channel name. |
|
||
|
|
| `Cleanup` | `void Cleanup()` | Empty implementation. |
|
||
|
|
| `Validate` | `bool Validate(ref List<string> errors, ref List<string> warnings, bool displayWindow)` | Validates channel name and calculation-specific requirements. |
|
||
|
|
|
||
|
|
### Public Enums
|
||
|
|
|
||
|
|
#### `Calculation`
|
||
|
|
Defines available calculation types with `Description` attributes for display:
|
||
|
|
|
||
|
|
| Value | Description |
|
||
|
|
|-------|-------------|
|
||
|
|
| `Integral = 0` | "Integral" |
|
||
|
|
| `DoubleIntegral = 1` | "Double Integral" |
|
||
|
|
| `Derivative = 2` | "Derivative" |
|
||
|
|
| `Sin = 3` | "Sin" |
|
||
|
|
| `Cos = 4` | "Cos" |
|
||
|
|
| `ThreeDIRTracc = 5` | "3D IR-Tracc" |
|
||
|
|
| `SUM = 6` | "SUM" |
|
||
|
|
| `AVE = 7` | "Average" |
|
||
|
|
| `ThreeDIRTraccAbdomen = 8` | "3D IR-TRACC Abdomen" |
|
||
|
|
| `ThreeDIRTraccLowerThorax = 9` | "3D IR-TRACC Lower Thorax" |
|
||
|
|
| `Resultant = 10` | "Resultant" |
|
||
|
|
| `HIC = 11` | "HIC" |
|
||
|
|
|
||
|
|
### Public Nested Classes
|
||
|
|
|
||
|
|
#### `ChannelHelper : BasePropertyChanged`
|
||
|
|
Wraps `ITestChannel` for UI binding with `DisplayName` formatting based on `IsoViewModeStatic.ViewMode` and `IsIncluded` selection state.
|
||
|
|
|
||
|
|
#### `CalculationHelper`
|
||
|
|
Wraps a `Calculation` enum value with localized string display via `StringResources.ResourceManager.GetString("CALCULATION_" + MyCalculation)`.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 3. Invariants
|
||
|
|
|
||
|
|
1. **Channel Name Validation**: `ValidateChannelName()` returns `true` only if `ChannelName` is not null or empty.
|
||
|
|
|
||
|
|
2. **HIC Calculation Requirements**: `ValidateHIC()` requires all three acceleration channels (`HICAccelerationX`, `HICAccelerationY`, `HICAccelerationZ`) to be non-null.
|
||
|
|
|
||
|
|
3. **Resultant Calculation Requirements**: `ValidateResultant()` requires:
|
||
|
|
- At least one channel with `IsIncluded == true`
|
||
|
|
- All included channels must have matching `SensitivityUnits`
|
||
|
|
- All included channels must have matching `SampleRateHz`
|
||
|
|
|
||
|
|
4. **Display Order**: New calculated channels are assigned `maxDisplayOrder + 1` from existing channels.
|
||
|
|
|
||
|
|
5. **Channel Uniqueness**: `ChannelList` excludes duplicate channels by `ChannelId` during population.
|
||
|
|
|
||
|
|
6. **IR-Tracc Channel Filtering**: Channels appear in `IRTraccChannelList` only if:
|
||
|
|
- `ChannelType` is `Test.Module.AnalogInputChannel`
|
||
|
|
- `LinearizationFormula` is valid per `LinearizationFormula.IsValid()`
|
||
|
|
- `ZeroMethod` equals `ZeroMethodType.None`
|
||
|
|
- `ZeroPoint != 0`
|
||
|
|
- `FactoryExcitationVoltage != 0`
|
||
|
|
|
||
|
|
7. **Potentiometer Channel Filtering**: Channels appear in `Pot1ChannelList`/`Pot2ChannelList` only if:
|
||
|
|
- `ChannelType` is `Test.Module.AnalogInputChannel`
|
||
|
|
- `Eu` is `"deg"` or `"deg-ang"` (case-insensitive, trimmed)
|
||
|
|
- `ZeroMethod` equals `ZeroMethodType.None`
|
||
|
|
- `FactoryExcitationVoltage != 0`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 4. Dependencies
|
||
|
|
|
||
|
|
### This Module Depends On
|
||
|
|
- `DTS.Common` - Constants, utilities
|
||
|
|
- `DTS.Common.Base` - `BaseViewModel<T>`, `BasePropertyChanged`
|
||
|
|
- `DTS.Common.Classes.Viewer.Commands` - `RelayCommand`
|
||
|
|
- `DTS.Common.DAS.Concepts` - Data concepts
|
||
|
|
- `DTS.Common.Enums.Sensors` - `ZeroMethodType`
|
||
|
|
- `DTS.Common.Events` - Event types (`RaiseNotification`, `TestSummaryChangeNotification`, `PageErrorEvent`, `SetSaveButton`, `RefreshTestRequestEvent`)
|
||
|
|
- `DTS.Common.Interactivity` - `InteractionRequest<T>`, `Notification`, `Confirmation`
|
||
|
|
- `DTS.Common.Interface` - `IAddCalculatedChannelViewModel`, `IBaseView`, `IBaseViewModel`, `ITestChannel`
|
||
|
|
- `DTS.Common.Utilities.Logging` - `APILogger`
|
||
|
|
- `DTS.Common.Utils` - `Utils` class for channel info loading
|
||
|
|
- `DTS.Slice.Control` - Slice control functionality
|
||
|
|
- `DTS.Viewer.AddCalculatedChannel.Model` - Model types (inferred)
|
||
|
|
- `DTS.Serialization` - `Test`, `TestSetup`, `SliceRaw.File`
|
||
|
|
- `Prism.Events` - `IEventAggregator`
|
||
|
|
- `Prism.Regions` - `IRegionManager`
|
||
|
|
- `Unity` - `IUnityContainer`
|
||
|
|
|
||
|
|
### Events Subscribed
|
||
|
|
- `RaiseNotification` → `OnRaiseNotification`
|
||
|
|
- `TestSummaryChangeNotification` → `OnTestSummaryChanged`
|
||
|
|
|
||
|
|
### Events Published
|
||
|
|
- `RaiseNotification`
|
||
|
|
- `PageErrorEvent`
|
||
|
|
- `SetSaveButton`
|
||
|
|
- `RefreshTestRequestEvent`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 5. Gotchas
|
||
|
|
|
||
|
|
1. **`IsBusy` and `IsDirty` Throw Exceptions**: Both properties throw `NotImplementedException`. Code paths that access these will fail at runtime.
|
||
|
|
|
||
|
|
2. **HIC Save Button Logic Appears Inverted**: In `UpdateSaveButtonVisibility()`, the HIC case sets `IsUsable = true` when acceleration channels are **null** and `IsUsable = false` when they are **not null**. This contradicts the validation logic in `ValidateHIC()` which requires non-null channels. This appears to be a bug.
|
||
|
|
|
||
|
|
3. **File Backup Behavior**: The `.dts` backup file (with `BACKUP_FILE_EXTENSION`) is created only if one doesn't already exist. The backup is deleted after successful save only if it was created during that save operation.
|
||
|
|
|
||
|
|
4. **Hardcoded Thread.Sleep**: A `Thread.Sleep(10)` exists after file writing in `AddCalculatedChannel()`. Purpose is unclear from source alone.
|
||
|
|
|
||
|
|
5. **Lazy Channel Loading**: In `OnTestSummaryChanged()`, if `ts.Channels.FirstOrDefault() == null`, channels are loaded on-demand via `Utils.SetChannelInfo()`. This side effect may not be obvious to callers.
|
||
|
|
|
||
|
|
6. **Duplicate Calculated Channel Handling**: `AddCalculatedChannelToTest()` silently overwrites existing calculated channels with matching `ChannelId` by removing the duplicate before adding the new one. A log message is generated but no user confirmation is requested.
|
||
|
|
|
||
|
|
7. **`PublishChanges()` Not Implemented**: The method body contains only a commented-out `NotImplementedException`. It is unclear if this is intentional or incomplete.
|