--- source_files: - DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.TestModification/Model/Enums.cs - DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.TestModification/Model/TestModificationModel.cs - DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.TestModification/Model/TestModelManipulation.cs generated_at: "2026-04-16T11:09:33.877186+00:00" model: "zai-org/GLM-5-FP8" schema_version: 1 sha256: "1e3214665d63bf12" --- # Test Modification Module Documentation ## 1. Purpose This module provides functionality for modifying test data within the DTS Viewer application. It manages the state of user-initiated modifications to channel parameters (sensitivity, EU multiplier/offset, T0 timing, line fit, software filters, data flags, and descriptions) and handles the persistence of these changes to both `.dts` metadata files and binary `.chn` channel files. The module supports backup/restore operations to allow reverting modifications and maintains change tracking to indicate which properties have been modified from their original values. --- ## 2. Public Interface ### Enums.cs #### `Keys` Enum ```csharp public enum Keys { ApplyShiftT0ModsTestOnly // System Setting for whether to restrict "Shift T0" test modifications to "Test" only. } ``` - Defines a configuration key for controlling T0 modification behavior. --- ### TestModificationModel.cs #### `TestModificationModel` Class Implements `ITestModificationModel`. A model class that tracks modification state for a selected test channel. **Calibration Properties:** | Property | Type | Description | |----------|------|-------------| | `CalDate` | `string` | Returns calibration date as short date string, or empty if `Cal` is null. | | `ModifyDate` | `string` | Returns modify date/time string, or empty if `Cal` is null. | | `CalSensitivity` | `double` | Gets/sets sensitivity from first calibration record. Returns `double.NaN` if unavailable. | | `ProportionalToExcitation` | `bool` | Returns whether calibration is proportional to excitation. | | `ShowSensorCal` | `bool` | Returns true if `Cal` and `Sensor` are non-null and calibration is not non-linear. | | `NonLinear` | `bool` | Returns whether calibration is non-linear. | | `Cal` | `ISensorCalDbRecord` | The latest calibration record for the channel. | | `Sensor` | `ISensorDbRecord` | The sensor corresponding to the channel. | **Channel Selection & Modification Tracking:** | Property | Type | Description | |----------|------|-------------| | `SelectedChannel` | `ITestChannel` | The currently selected test channel. | | `Description` | `string` | Channel description string. | | `IsModifiedDescription` | `bool` | True if `Description` differs from `SelectedChannel.ChannelDescriptionString`. | | `EuMultiplier` | `double` | EU multiplier value. | | `IsModifiedEuMultiplier` | `bool` | True if `EuMultiplier` differs from `SelectedChannel.Multiplier`. | | `EuOffset` | `double` | EU offset value. | | `IsModifiedEuOffset` | `bool` | True if `EuOffset` differs from `SelectedChannel.UserOffsetEu`. | | `T0` | `double` | T0 timing offset (in ms). | | `IsModifiedT0` | `bool` | True if `T0` is not 0. | | `T1` | `double` | Line fit start point (in ms). | | `T2` | `double` | Line fit end point (in ms). | | `IsModifiedLineFit` | `bool` | True if `T1` or `T2` is not 0. | | `Sensitivity` | `double` | Sensitivity value. | | `IsModifiedSensitivity` | `bool` | True if `Sensitivity` differs from `SelectedChannel.Sensitivity`. | | `SelectedFilter` | `IFilterClass` | Selected software filter (defaults to `FilterClassType.Unfiltered`). | | `IsModifiedFilter` | `bool` | True if `SelectedFilter` differs from channel's software filter. | | `SelectedDataFlag` | `DataFlag` | Selected data flag. | | `IsModifiedDataFlag` | `bool` | True if `SelectedDataFlag` differs from channel's data flag. | | `IsModified` | `bool` | Aggregate flag indicating any modification exists and `SelectedChannel` is not null. | **Control Enable/Disable Properties:** | Property | Type | Default | |----------|------|---------| | `EnableSensitivityControl` | `bool` | `true` | | `EnableLineFitControl` | `bool` | `true` | | `EnableEUOffsetControl` | `bool` | `true` | | `EnableEUMultiplierControl` | `bool` | `true` | | `EnableFilterControl` | `bool` | `true` | | `EnableDescriptionControl` | `bool` | `true` | | `IsDataFlagEnabled` | `bool` | `true` | | `IsT0Enabled` | `bool` | `true` | **T0 Mode Properties:** | Property | Type | Description | |----------|------|-------------| | `T0Mode` | `T0Mode` | Gets/sets T0 mode (`Test` or `DAS`). When `IsT0ModeTestOnly` is true, setter forces value to `T0Mode.Test`. | | `IsT0ModeTestOnly` | `bool` | When true, restricts T0 mode to `Test` only. | **Other Properties:** | Property | Type | Description | |----------|------|-------------| | `Parent` | `ITestModificationViewModel` | Reference to parent view model. | | `IsSaved` | `bool` | Property exists but has no implementation visible. | **Methods:** ```csharp public bool ValidateT0() ``` - Validates that T0 falls within the dataset's time range (between start and end times). - Returns `true` if `SelectedChannel` or `SelectedChannel.ParentModule` is null. - Calculates valid range from `StartRecordSampleNumber`, `TriggerSampleNumbers[0]`, `NumberOfSamples`, and `SampleRateHz`. ```csharp public void OnPropertyChanged(string propertyName) ``` - Raises `PropertyChanged` event. - Updates `IsModified` aggregate flag when non-IsModified properties change. - Calls `Parent?.PublishChanges()`. **Commands:** ```csharp public DelegateCommand UpdateDatabaseCommand ``` - Executes `UpdateDatabaseMethod()` which delegates to `Parent.UpdateDatabaseMethod()`. --- ### TestModelManipulation.cs #### `TestModelManipulation` Class Static utility class for file-based test modification operations. **Constants:** | Constant | Value | Description | |----------|-------|-------------| | `UNUSED_START_TIME` | `0` | Placeholder for test serialization. | | `UNUSED_DATA_COLLECTION_LENGTH` | `0` | Placeholder for test serialization. | | `BackupHeaderExtension` | `".header.bak"` | Extension for header-only backups. | | `BackupFileExtension` | `".bak"` | Extension for full file backups. | **Public Methods:** ```csharp public static void UndoAllModification(ITestModificationModel model) ``` - Reverts all modifications by restoring `.dts` and all `.chn` files from backups. - Publishes `ChannelsModificationNotification`, `RefreshTestRequestEvent`, and `TestModificationEvent`. ```csharp public static bool BackupExists(ITestModificationModel model) ``` - Returns true if either `.dts.bak` or `.chn.bak` files exist for the selected channel. ```csharp public static bool SaveModification(ITestModificationModel model, bool useISOCodeFilterMapping, bool bUseZeroForUnfiltered) ``` - Persists all modifications to disk. - Handles T0 changes (applying to test or DAS based on `T0Mode`). - Handles filter changes with optional ISO code mapping. - Handles sensitivity, EU multiplier/offset, description, data flag, and line fit changes. - Publishes `TestModificationEvent` on completion. ```csharp public static bool SaveModificationDataFlag(ITestModificationModel model) ``` - Saves only data flag modifications. - Publishes `ChannelsModificationNotification` and repopulates model from channel. ```csharp public static void ApplyLineFit(ITestModificationModel model, Test.Module.Channel channel) ``` - Applies linear interpolation between sample indices derived from `T1` and `T2`. - Backs up channel file (full backup, not header-only). - Modifies ADC data in place using straight-line fit between two points. ```csharp public static void PreviewLineFit(ITestModificationModel model) ``` - Publishes `ChannelsModificationLineFitNotification` with calculated start/end indices for UI preview without disk modification. ```csharp public static void UndoModification(ITestModificationModel model) ``` - Reverts in-memory changes by repopulating from channel. - Publishes `ChannelsModificationNotification`. ```csharp public static void PopulateFromChannel(ITestModificationModel model) ``` - Initializes model properties from `SelectedChannel` values. - Resets `T0`, `T1`, `T2` to 0. --- ## 3. Invariants 1. **Calibration Record Access**: `CalSensitivity` getter assumes `Cal.Records.Records[0]` exists if the collection is non-null and non-empty. No bounds checking beyond length > 0. 2. **Modification Flag Consistency**: `IsModified` is always `false` when `SelectedChannel` is null, regardless of other modification flags. 3. **T0Mode Restriction**: When `IsT0ModeTestOnly` is `true`, the `T0Mode` setter always forces the value to `T0Mode.Test`, ignoring the provided value. 4. **Backup File Semantics**: Backup files (`.bak`) represent the **original** unmodified files. If a backup exists, it is never overwritten by subsequent backup operations. 5. **Line Fit Index Ordering**: `ApplyLineFit` automatically swaps start/end indices if `startIndex > endIndex`. 6. **T0 Validation Range**: `ValidateT0()` calculates time range assuming `TriggerSampleNumbers[0]` exists (no bounds check on the list). 7. **Channel Matching**: `SaveModification` matches channels by both `ChannelId` AND `BinaryFileName` suffix for most operations (except T0 modifications which apply more broadly). --- ## 4. Dependencies ### Imports (This module depends on): **From TestModificationModel.cs:** - `DTS.Common` - Common utilities - `DTS.Common.Classes.Sensors` - Sensor classes - `DTS.Common.Enums.Sensors` - Sensor enums - `DTS.Common.Interface` - Common interfaces - `DTS.Common.Interface.Sensors` - Sensor interfaces - `DTS.Common.Interface.Sensors.SoftwareFilters` - Filter interfaces - `DTS.SensorDB` - Sensor database interfaces (`ISensorCalDbRecord`, `ISensorDbRecord`) - `Prism.Commands` - `DelegateCommand` **From TestModelManipulation.cs:** - `DTS.Common` - Common utilities - `DTS.Common.Classes.Sensors` - Sensor classes - `DTS.Common.Events` - Event types (`TestModificationEvent`, `TestModificationArgs`, `ChannelsModificationNotification`, `ChannelsModificationLineFitNotification`, `LineFitArgs`, `RefreshTestRequestEvent`) - `DTS.Common.Interface` - `ITestChannel` - `DTS.Common.Settings` - `SettingsDB` - `DTS.Common.Utilities.Logging` - `APILogger` - `DTS.Serialization` - Serialization utilities (`Serialization.SliceRaw.File`) - `Prism.Ioc` - `ContainerLocator` - `Prism.Events` - `IEventAggregator` ### External Type References (Interfaces expected from elsewhere): - `ITestModificationModel` - Interface implemented by `TestModificationModel` - `ITestModificationViewModel` - Parent view model interface - `ITestChannel` - Test channel interface - `ISensorCalDbRecord` - Calibration database record - `ISensorDbRecord` - Sensor database record - `IFilterClass` / `FilterClass` - Software filter abstraction - `T0Mode` - Enum for T0 modification scope - `DataFlag` - Enum for data flags - `Test.Module.Channel` / `Test.Module.AnalogInputChannel` - Channel types from serialization - `Test` / `TestSetup` - Test structure types --- ## 5. Gotchas 1. **Namespace Mismatch**: `TestModificationModel.cs` is declared in namespace `DTS.Viewer.ChartOptions.Model` despite residing in `DTS.Viewer.TestModification/Model/`. This may cause confusion when locating the class. 2. **IsSaved Property**: The `IsSaved` property has a getter but no visible setter or backing field implementation. Its behavior is unclear from source alone. 3. **T0 Mode DAS Logic**: In `SaveModification`, when `T0Mode == T0Mode.DAS`, T0 changes are applied to modules that **do not** contain the selected channel but share the same `BaseSerialNumber` as the module that does. This could affect more channels than expected. 4. **Line Fit Data Type**: `ApplyLineFit` casts ADC data to `short` after floating-point interpolation, which could cause precision loss or overflow for extreme values. 5. **Thread.Sleep in File Writing**: `WriteDTSFileChanges` includes `System.Threading.Thread.Sleep(10)` after writing the DTS file. The reason for this delay is not documented in source. 6. **Backup Strategy Selection**: `BackupChannelIfNeeded` uses header-only backup for sensitivity/T0/filter changes (when `useISOCodeFilterMapping` is true), but full backup for line fit. This is a performance optimization but means different modification types have different restore behaviors. 7. **FilterClassType Default**: `SelectedFilter` defaults to `FilterClassType.Unfiltered`, but the source does not show the definition of `FilterClassType` enum. 8. **PropertyChanged Event Naming**: `RebindCalProperties` raises events with string property names rather than using `nameof()` operator, which could lead to runtime errors if property names change.