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,187 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Graph/Model/TestDataSeries.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Graph/Model/TestDataSeriesModel.cs
generated_at: "2026-04-16T13:52:27.037806+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "1630e6f30be700ba"
---
# Documentation: DTS.Viewer.Graph Module - Test Data Series Models
## 1. Purpose
This module provides the data models for representing and transforming test channel data into graphable series within the DTS Viewer application. `TestDataSeries` serves as the primary data transfer object holding channel metadata, X/Y coordinate arrays, statistical calculations, and visualization properties. `TestDataSeriesModel` acts as a factory/processor that reads raw binary channel data, applies transformations (including FFT and PSD calculations), and populates `TestDataSeries` instances for display. The module supports three data modes: regular time-series, FFT (Fast Fourier Transform), and PSD (Power Spectral Density) with configurable windowing and filtering.
---
## 2. Public Interface
### TestDataSeries Class
**Namespace:** `DTS.Viewer.Graph.Model`
**Inherits:** `Common.Base.BasePropertyChanged`
**Implements:** `ITestDataSeries`
#### Properties
| Property | Type | Description |
|----------|------|-------------|
| `HIC` | `bool` | Indicates if Head Injury Criteria data is present. |
| `HICValue` | `string` | Formatted HIC value. |
| `T1Time`, `T2Time` | `string` | T1/T2 timestamp strings for HIC calculations. |
| `TestGroup` | `string` | Test group identifier. |
| `TestId` | `string` | Unique test identifier. |
| `TestSetupName` | `string` | Name of the test setup configuration. |
| `ChannelId` | `string` | Channel identifier. |
| `Xvalue` | `double[]` | X-axis data array (time or frequency). |
| `Yvalue` | `double[]` | Y-axis data array (amplitude, magnitude, or PSD). |
| `GraphColor` | `Brush` | WPF brush for graph rendering. Internally stored as `byte[]` for thread-safety. |
| `IsSaved` | `bool` | Get-only property indicating save state. |
| `HardwareChannel` | `string` | Hardware channel name. |
| `GroupName` | `string` | Channel group name. |
| `SWAAF` | `string` | Software anti-aliasing filter setting. |
| `Bridge` | `string` | Bridge type identifier. |
| `HWAAF` | `string` | Hardware anti-aliasing filter rate. |
| `SampleRate` | `string` | Sample rate in Hz. |
| `ISOCode`, `ISOChannelName` | `string` | ISO channel identification. |
| `UserCode`, `UserChannelName` | `string` | User-defined channel identification. |
| `ChannelName` | `string` | Display channel name. |
| `Description` | `string` | Channel description. |
| `SensorSN` | `string` | Sensor serial number. |
| `SensorSNDisplay` | `string` | Get-only; returns `"N/A"` if `SensorSN` is test-specific embedded, otherwise returns `SensorSN`. |
| `EngineeringUnits` | `string` | Engineering units string. |
| `Excitation` | `string` | Excitation voltage. |
| `Polarity` | `string` | Sensor polarity. |
| `MinY`, `MaxY`, `AvgY`, `StdDevY` | `string` | Statistical values formatted as strings, default to `Strings.Table_NA`. |
| `PeakMagnitude` | `double` | Peak magnitude of frequencies (valid only when `FFT` is true). |
| `PeakFrequency` | `double` | Frequency of highest magnitude (valid only when `FFT` is true). |
| `GRMS` | `double` | Root-mean-squared acceleration (calculated for PSD results). |
| `FFT` | `bool` | Indicates whether series contains FFT-transformed data. |
| `T0EUValue` | `string` | T0 value string. |
| `RecordingMode` | `string` | Recording mode description. |
#### Methods
```csharp
public void SetStatsFromYValues()
```
Calculates and sets `AvgY`, `StdDevY`, `MinY`, `MaxY` from internal `Yvalue` array. Uses `"G5"` format for string conversion.
```csharp
public void SetStatsFromYValues(double[] values)
```
Overload that calculates statistics from a provided `double[]` array. Handles null/empty arrays by setting all stats to `Table_NA`.
```csharp
public void SetStatsFromChannel(ITestChannel channel)
```
Sets statistics from pre-calculated values on an `ITestChannel` instance (properties: `MinY`, `MaxY`, `AveY`, `StdDevY`, `T0Value`).
---
### TestDataSeriesModel Class
**Namespace:** `DTS.Viewer.Graph`
**Implements:** `IBaseModel`
#### Properties
| Property | Type | Description |
|----------|------|-------------|
| `Parent` | `IGraphViewModel` | Parent view model reference. |
| `_eventAggregator` | `IEventAggregator` | Prism event aggregator for publishing progress events. |
| `ErrorMessage` | `string` | Error message with `PropertyChanged` notification. |
| `IsSaved` | `bool` | Get-only property. |
#### Methods
```csharp
public Task<ITestDataSeries> GetTestDataAsync(ITestChannel channel, IChartOptionsModel chartOptions, bool bVolts, IPSDReportSettingsModel psdSettings = null)
```
Async wrapper returning `GetTestData()`. **Warning:** Lacks `await` operators and runs synchronously (per compiler warning CS1998).
```csharp
public Task<List<ITestDataSeries>> GetTestDataAsync(List<ITestChannel> channels, IChartOptionsModel chartOptions, bool bVolts, IPSDReportSettingsModel psdSettings = null)
```
Async wrapper for multiple channels. Includes envelope channel if `psdSettings.ShowEnvelope` is true.
```csharp
public List<ITestDataSeries> GetTestData(List<ITestChannel> channels, IChartOptionsModel chartOptions, bool bVolts, IPSDReportSettingsModel psdSettings = null)
```
Synchronously processes multiple channels. Throws `Exception` with context on `OutOfDataException` or other failures. Logs failures via `APILogger.Log()`.
```csharp
public ITestDataSeries GetTestData(ITestChannel channel, IChartOptionsModel chartOptions, bool bVolts, IPSDReportSettingsModel psdSettings = null)
```
Returns `AddTestChannelToChart()` result.
```csharp
public TestDataSeries AddTestChannelToChart(ITestChannel channel, IChartOptionsModel chartOptions, bool bVolts, IPSDReportSettingsModel psdSettings = null)
```
**Primary processing method.** Reads binary channel data via `Serialization.SliceRaw.File.Reader.ReadChannelsBinaryData()`, applies transformations based on `chartOptions.UnitType`:
- **FFT mode** (`ChartUnitTypeEnum.FFT` with null `psdSettings`): Sets `FFT=true`, populates `PeakFrequency`, `PeakMagnitude`.
- **Regular mode** (null `psdSettings`): Time-series data with optional HIC calculation.
- **PSD mode** (non-null `psdSettings`): Applies data trimming, windowing (Hanning, Hamming, Blackman, BlackmanHarris, FlatTop, Rectangle), optional low/high pass filtering via `Exocortex.DSP`, and Welch PSD transform via `FftSharp.Transform.PSD_Welch()`.
Returns `null` if `channel.ErrorMessage` is not empty.
---
## 3. Invariants
1. **Array Initialization**: `Xvalue` and `Yvalue` are never null; they default to `new double[0]`.
2. **GraphColor Thread-Safety**: `GraphColor` getter creates a new `SolidColorBrush` on each call. The underlying color is stored as a 4-byte array (`[A, R, G, B]`) to enable cross-thread access.
3. **FFT/PSD Filter Bypass**: When `chartOptions.UnitType` is `FFT` or `PSD`, `channel.SoftwareFilter` is forcibly set to `"none"` before reading data.
4. **Statistics Default**: `MinY`, `MaxY`, `AvgY` default to `Strings.Table_NA` (not empty string).
5. **PSD Data Length**: PSD processing resizes input arrays to the nearest enclosing power of 2 via `Utils.GetEnclosingPower2()`.
6. **Frequency Array First Element**: In PSD mode, `freq[0]` is explicitly set to `1` after calculation.
7. **IEPE Bridge Excitation**: Channels with `Bridge == "IEPE"` display `"---"` for excitation instead of measured voltage.
---
## 4. Dependencies
### This Module Depends On:
- `DTS.Common.Base` - `BasePropertyChanged` base class
- `DTS.Common.Enums.Sensors` - `SensorConstants` for bridge type detection
- `DTS.Common.Enums.Viewer` - `ChartUnitTypeEnum`, `TimeUnitTypeEnum`, window/filter enums
- `DTS.Common.Enums.DASFactory` - `DFConstantsAndEnums.RecordingMode`
- `DTS.Common.Interface` - `ITestDataSeries`, `ITestChannel`, `IGraphViewModel`, `IChartOptionsModel`, `IBaseModel`, `IPSDReportSettingsModel`
- `DTS.Common.Strings` - Localized string constants (`Table_NA`, `Envelope`, etc.)
- `DTS.Common.Utils` - `Utils.GetEnclosingPower2()`
- `DTS.Common.Utilities` - `RecordingModeExtensions`
- `DTS.Common.Utilities.Logging` - `APILogger`
- `DTS.Common.Converters` - `EnumDescriptionTypeConverter`
- `DTS.Common.Events` - `GraphChannelReadCalcProgressChangedEvent`, `GraphChannelReadCalcProgressChangedEventArgs`
- `DTS.Common.Exceptions` - `OutOfDataException`
- `Prism.Events` - `IEventAggregator`
- `System.Windows.Media` - `Brush`, `SolidColorBrush`, `Color`, `Colors`
- `FftSharp` - `Transform.PSD_Welch()`, `Transform.FFTfreq()`, `WindowType`, `WindowAveragingType`
- `Exocortex.DSP` - `PassFilter.LowPass()`, `PassFilter.HighPass()`, `PassFilterType`
- `Serialization.SliceRaw.File.Reader` - `ReadChannelsBinaryData()` (external/unclear origin)
### Dependents (Inferred):
- Any view or view model that displays graph data and implements `IGraphViewModel`
- PSD report generation components
---
## 5. Gotchas
1. **Async Methods Are Not Async**: Both `GetTestDataAsync` overloads are marked `async` but contain no `await` operators. They execute synchronously despite the method signature. Compiler warning CS1998 is suppressed with pragmas.
2. **GraphColor Allocation on Every Access**: The `GraphColor` getter instantiates a new `SolidColorBrush` on every call. Frequent access in UI binding scenarios may cause unnecessary allocations.
3. **T0EUValue Naming Misnomer**: Per source comment: *"this is the T0 value regardless of units ... it's not really EU but since it's already in use I'm not going to change it"*. The property name is misleading.
4. **PSD Envelope Requires Non-Empty Input**: `GetEnvelopeChannel()` returns an empty `TestDataSeries` if input list is null or empty, without any error indication.
5. **Channel Error Short-Circuit**: `AddTestChannelToChart()` returns `null` (not an exception) if `channel.ErrorMessage` is non-empty, which may cause null reference exceptions in callers not expecting null.
6. **Digital Channel Detection String Comparison**: Digital channels are detected via `channel.Bridge.StartsWith(SensorConstants.BridgeType.DigitalInput.ToString())`. This relies on `ToString()` matching the enum name exactly.
7. **GRMS Calculation Edge Case**: `CalculateGRMS()` uses `N.EqualsDigitPrecision(-1, 1)` for a special case. The method `EqualsDigitPrecision` is not defined in the provided source—its behavior is unclear.
8. **Frequency Array Mutation**: In PSD mode, `freq[0] = 1` mutates the array returned from `FftSharp.Transform.FFTfreq()`. This may affect any other consumers of that array if it's shared.

View File

@@ -0,0 +1,82 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Graph/Properties/AssemblyInfo.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Graph/Properties/Annotations.cs
generated_at: "2026-04-16T13:52:16.308869+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "530eff79443974f8"
---
# Module Documentation: DTS.Viewer.Graph Properties
## 1. Purpose
This module component provides assembly-level configuration and static analysis support for the `DTS.Viewer.Graph` assembly. `AssemblyInfo.cs` establishes the assembly's identity, version (1.0.0.0), and COM visibility settings. `Annotations.cs` defines a comprehensive suite of custom attributes (sourced from JetBrains) used to enhance code inspection, nullability analysis, and framework-specific validations (ASP.NET MVC, Razor, XAML) within the codebase, enabling deeper static analysis without requiring external dependencies.
## 2. Public Interface
### Assembly Metadata (AssemblyInfo.cs)
These attributes configure the compiled assembly `DTS.Viewer.Graph.dll`.
* **`AssemblyTitle`**: Set to `"Graph"`.
* **`AssemblyProduct`**: Set to `"Graph"`.
* **`AssemblyVersion`**: Set to `"1.0.0.0"`.
* **`AssemblyFileVersion`**: Set to `"1.0.0.0"`.
* **`Guid`**: Set to `"61261c58-c32e-4dea-a87a-d7f956f28b4d"`.
* **`ComVisible`**: Set to `false`.
### Code Annotations (Annotations.cs)
The following attributes are defined in the `DTS.Viewer.Graph.Annotations` namespace. They are intended for use by static analysis tools (e.g., ReSharper, Rider) and the compiler.
**Nullability & Contracts:**
* **`CanBeNullAttribute`**: Indicates a value might be `null`.
* **`NotNullAttribute`**: Indicates a value should never be `null`.
* **`ItemNotNullAttribute`**: Indicates collection items or `Task.Result` are not `null`.
* **`ItemCanBeNullAttribute`**: Indicates collection items or `Task.Result` might be `null`.
* **`ContractAnnotationAttribute`**: Defines method input/output contracts (e.g., `null => halt`).
* **`PureAttribute`**: Marks a method as having no observable side effects.
**Usage & Visibility:**
* **`PublicAPIAttribute`**: Marks a type/member as part of the public API, preventing "unused" warnings.
* **`UsedImplicitlyAttribute`**: Indicates a symbol is used via reflection or external means.
* **`MeansImplicitUseAttribute`**: Applied to other attributes to indicate that targets should be considered "used".
* **`BaseTypeRequiredAttribute`**: Enforces that a type marked with a specific attribute must inherit from a specific base type.
**Method Behavior:**
* **`StringFormatMethodAttribute`**: Marks a method parameter as a format string (e.g., for `string.Format` validation).
* **`NotifyPropertyChangedInvocatorAttribute`**: Marks a method as raising the `PropertyChanged` event.
* **`InstantHandleAttribute`**: Indicates a delegate parameter is executed during the method call.
* **`MustUseReturnValueAttribute`**: Warns if the method's return value is ignored.
* **`CollectionAccessAttribute`**: Describes how a method modifies a collection (Read, Modify, Update).
* **`AssertionMethodAttribute` / `AssertionConditionAttribute`**: Marks methods that halt execution based on conditions (e.g., assertion methods).
**Framework Specific (ASP.NET, Razor, XAML):**
* **`AspMvcActionAttribute`, `AspMvcControllerAttribute`, `AspMvcViewAttribute`**: Assist in resolving MVC references.
* **`RazorSectionAttribute`, `RazorImportNamespaceAttribute`**: Assist in Razor view analysis.
* **`XamlItemsControlAttribute`, `XamlItemBindingOfItemsControlAttribute`**: Assist in XAML `DataContext` resolution.
**Miscellaneous:**
* **`SourceTemplateAttribute`**: Marks an extension method as a source template for code completion.
* **`MacroAttribute`**: Defines macros for source template parameters.
* **`NoReorderAttribute`**: Prevents code cleanup tools from reordering members.
## 3. Invariants
* **COM Visibility:** The assembly is explicitly configured with `ComVisible(false)`, ensuring types are not exposed to COM by default.
* **Version Consistency:** The `AssemblyVersion` and `AssemblyFileVersion` are both strictly defined as `1.0.0.0`.
* **Attribute Usage:** All annotation attributes are strictly constrained by `AttributeUsage` attributes. For example, `PureAttribute` can only target `Method`s, while `CanBeNullAttribute` can target methods, parameters, properties, delegates, fields, events, classes, interfaces, and generic parameters.
* **Licensing:** The `Annotations.cs` file is explicitly licensed under the MIT License (Copyright 2016 JetBrains), requiring the license notice to be preserved in copies.
## 4. Dependencies
* **System Dependencies:**
* `System.Reflection`
* `System.Runtime.CompilerServices`
* `System.Runtime.InteropServices`
* `System`
* **Tooling Dependencies:** The annotations in `Annotations.cs` are designed to be consumed by JetBrains static analysis tools (ReSharper, Rider). They have no runtime impact on the application logic itself.
* **Consumers:** This module is a foundational block for the `DTS.Viewer.Graph` project. Other projects referencing `DTS.Viewer.Graph` may utilize these annotations if exposed publicly, though they are primarily for internal analysis.
## 5. Gotchas
* **Obsolete Assertion Attribute:** The `TerminatesProgramAttribute` is marked `[Obsolete("Use [ContractAnnotation('=> halt')] instead")]`. Developers should avoid using this attribute in new code and prefer `ContractAnnotationAttribute`.
* **Hardcoded Version:** The version `1.0.0.0` is hardcoded in `AssemblyInfo.cs`. If this project uses CI/CD pipelines that typically auto-increment versions or use MSBuild properties (e.g., `1.0.*`), this file overrides that behavior, potentially requiring manual updates for new releases.
* **Duplicate Annotations:** The `Annotations.cs` file is a standard "copy-paste" of JetBrains annotations. If other modules in the solution (e.g., `DTS.Viewer.Core`) also include this file, there may be duplicate attribute definitions if namespaces are not carefully managed or if the `global` namespace is used, though here they are safely scoped to `DTS.Viewer.Graph.Annotations`.
* **Empty Description:** The `AssemblyDescription` attribute is an empty string, offering no metadata regarding the specific functionality of the Graph module.

View File

@@ -0,0 +1,71 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Graph/Resources/TranslateExtension.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Graph/Resources/StringResources.Designer.cs
generated_at: "2026-04-16T13:51:30.707906+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "ea967aac84c55893"
---
# Documentation: DTS.Viewer.Graph Resources
## 1. Purpose
This module provides localization support for the `DTS.Viewer.Graph` namespace. It consists of a WPF markup extension (`TranslateExtension`) for declarative XAML binding and an auto-generated resource accessor class (`StringResources`) for retrieving localized strings programmatically. The module centralizes user-facing strings related to graph operations, data filtering errors, and file export statuses (PDF/CSV).
## 2. Public Interface
### Class: `TranslateExtension`
**Namespace:** `DTS.Viewer.Graph`
**Inheritance:** `System.Windows.Markup.MarkupExtension`
This class allows XAML bindings to localized resources.
* **Constructor**
* `public TranslateExtension(string key)`: Initializes the extension with the resource key to look up.
* **Method**
* `public override object ProvideValue(IServiceProvider serviceProvider)`: Returns the localized string associated with `_key`. If the key is null or empty, it returns the constant `#stringnotfound#`. If the key is valid but no resource is found, it returns `#stringnotfound#` appended with the key name.
### Class: `StringResources`
**Namespace:** `DTS.Viewer.Graph.Resources`
**Visibility:** `internal`
A strongly-typed resource class generated by Visual Studio tools.
* **Property: `ResourceManager`** (static)
* Returns the cached `System.Resources.ResourceManager` instance for this assembly.
* **Property: `Culture`** (static)
* Gets or sets the `System.Globalization.CultureInfo` used for resource lookups.
* **Resource String Properties** (static, read-only):
* `BadDataFromCustomFilter`: Warning regarding filter class frequency exceeding sample rate bounds.
* `BadDataFromTestSetupDefaultFilter`: Warning regarding test filter results causing out-of-bounds data.
* `BadDataUnfilteredUnknown`: Error message for unviewable channel data.
* `ReadingChannelData`: Status message indicating channel data is being read.
* `SavePDFError`: Error message for PDF chart save failure.
* `SavePDFSuccess`: Success message for PDF chart save (includes format placeholders `{0}`, `{1}`, etc.).
* `SaveReportCSVError`: Error message for CSV report save failure.
* `SaveReportCSVSuccess`: Success message for CSV report save.
* `SaveReportPDFError`: Error message for PDF report save failure.
* `SaveReportPDFSuccess`: Success message for PDF report save.
## 3. Invariants
* **Null Safety:** `TranslateExtension.ProvideValue` will never return null. It guarantees a string return, defaulting to specific error constants if lookup fails.
* **Error Differentiation:** The return value distinguishes between a missing key argument (returns `#stringnotfound#`) and a valid key argument with no matching resource (returns `#stringnotfound# [key]`).
* **Resource Availability:** `StringResources` assumes the existence of a corresponding `.resx` file embedded in the assembly manifest named `"DTS.Viewer.Graph.Resources.StringResources"`.
## 4. Dependencies
* **Internal Dependencies:**
* `TranslateExtension` depends entirely on `DTS.Viewer.Graph.Resources.StringResources` for data retrieval.
* **External Dependencies:**
* `System`: Core base library.
* `System.Windows.Markup`: Required for `MarkupExtension` and `MarkupExtensionReturnTypeAttribute` (WPF specific).
* `System.Resources`: Used for `ResourceManager`.
* `System.Globalization`: Used for `CultureInfo`.
* **Dependents:**
* Unknown from source alone. However, the `MarkupExtensionReturnType` attribute implies consumption by WPF XAML parsers within the `DTS.Viewer.Graph` module.
## 5. Gotchas
* **Auto-Generated Code:** `StringResources` is a designer file (`StringResources.Designer.cs`). Manual edits to this file will be overwritten by the tooling (Visual Studio/ResGen). Changes must be made to the underlying `.resx` file.
* **Internal Visibility:** The `StringResources` class is marked `internal`. It is not accessible outside the `DTS.Viewer.Graph` assembly.
* **Silent Failure Mode:** `TranslateExtension` does not throw exceptions for missing keys. Instead, it returns the literal string `#stringnotfound#`. Developers debugging missing UI text must search for this specific string or check the output for the appended key name.
* **Hardcoded Fallback:** The fallback string `#stringnotfound#` is hardcoded in `TranslateExtension.cs` rather than being localized itself.

View File

@@ -0,0 +1,110 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Graph/View/GraphView.xaml.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Graph/View/TestDataView.xaml.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Graph/View/TestDataSeriesView.xaml.cs
generated_at: "2026-04-16T13:53:01.641041+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "8c5a8096c69954ca"
---
# Documentation: DTS.Viewer.Graph Views
## 1. Purpose
This module provides WPF view components for graph visualization within the DTS Viewer application. It contains three XAML code-behind classes—`GraphView`, `TestDataView`, and `TestDataSeriesView`—that implement corresponding interfaces from `DTS.Common.Interface`. The primary functionality includes rendering charts using ComponentOne WPF Chart controls and exporting test data to PDF and CSV formats with associated metadata (test setup information, gRMS tables, and PSD data).
---
## 2. Public Interface
### GraphView
**Implements:** `IGraphView`
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `public GraphView()` | Initializes the XAML component via `InitializeComponent()`. |
---
### TestDataView
**Implements:** `ITestDataView`
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `public TestDataView()` | Initializes the XAML component via `InitializeComponent()`. |
**Note:** Contains extensive commented-out code for mouse-driven zoom functionality (`MainChart_MouseLeftButtonDown`, `MainChart_MouseMove`, `MainChart_MouseLeftButtonUp`, `PerformZoom`, `DrawReversibleRectangle`), but none of this is active.
---
### TestDataSeriesView
**Implements:** `ITestDataSeriesView`
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `public TestDataSeriesView()` | Initializes the XAML component via `InitializeComponent()`. |
| SaveReportToPDF | `public bool SaveReportToPDF(string directory)` | Generates a PDF containing: test setup info, chart image, and a gRMS table with channel names, sample rates, and gRMS values. Returns `true` on success, `false` on failure. |
| SaveReportToCSV | `public bool SaveReportToCSV(string directory)` | Exports chart data to CSV format with frequency (Hz) and PSD values (EngineeringUnits²/Hz). Returns `true` on success, `false` on failure. |
| obj_DataPointChanged | `private void obj_DataPointChanged(object sender, EventArgs e)` | Event handler for data point changes. **All logic is commented out.** |
| MainChart_OnMouseWheel | `private void MainChart_OnMouseWheel(object sender, MouseWheelEventArgs e)` | Mouse wheel event handler. **All logic is commented out.** |
| MainChart_OnKeyUp | `private void MainChart_OnKeyUp(object sender, KeyEventArgs e)` | Key up event handler. **Empty implementation.** |
---
### AxisExtension (Static Extension Class)
| Member | Signature | Description |
|--------|-----------|-------------|
| GetDispMin | `public static double GetDispMin(this Axis axis)` | Calculates display minimum: `axis.ActualMin + axis.Value * (axis.ActualMax - axis.ActualMin) * (1 - axis.Scale)` |
| GetDispMax | `public static double GetDispMax(this Axis axis)` | Calculates display maximum: `axis.ActualMax - (1 - axis.Value) * (axis.ActualMax - axis.ActualMin) * (1 - axis.Scale)` |
---
## 3. Invariants
- **SaveReportToPDF**: The `directory` parameter must be non-null and non-whitespace; otherwise, a `DirectoryNotFoundException` is thrown.
- **SaveReportToCSV**: The method creates the target directory if it does not exist.
- **DataContext Requirement**: Both `SaveReportToPDF` and `SaveReportToCSV` require `MainChart.DataContext` to be castable to `TestDataSeriesViewModel` with a non-null `GraphDataSeries` property.
- **PDF Paper Size**: Determined by `System.Globalization.RegionInfo.CurrentRegion.IsMetric` — A4 for metric regions, Letter otherwise.
- **CSV Data Alignment**: The CSV export loop assumes all series in `GraphDataSeries` have `Xvalue` and `Yvalue` arrays of equal or greater length than the iteration index.
---
## 4. Dependencies
### External Dependencies (Imports)
| Namespace | Purpose |
|-----------|---------|
| `DTS.Common.Interface` | Provides `IGraphView`, `ITestDataView`, `ITestDataSeriesView` interfaces |
| `DTS.Common.Utilities.Logging` | Provides `APILogger` for logging operations |
| `DTS.Common.Utils` | Provides `FileUtils.GetEncoding()` for text encoding |
| `C1.WPF.Chart` / `C1.WPF.C1Chart` / `C1.WPF.C1Chart.Extended` | ComponentOne chart controls (`C1FlexChart`, `Axis`, `ImageFormat`) |
| `C1.WPF.Pdf` | ComponentOne PDF generation (`C1PdfDocument`, `PaperKind`, `Font`, `Pen`) |
| `System.Windows` | WPF core types (`Point`, `Rect`, `Visibility`, `MessageBox`, etc.) |
| `System.Windows.Input` | Input types (`MouseEventArgs`, `MouseWheelEventArgs`, `KeyEventArgs`, `ModifierKeys`) |
| `System.Windows.Media.Imaging` | Bitmap types (`BitmapImage`, `WriteableBitmap`) |
### Downstream Dependencies
- **Unclear from source alone** — These are view components; consumers would typically be ViewModels or other presentation-layer components that reference these views, but no direct consumers are visible in the provided source.
---
## 5. Gotchas
1. **Substantial Commented-Out Code**: Both `TestDataView` and `TestDataSeriesView` contain significant commented-out functionality (zoom/pan features, data point tracking). This suggests incomplete features or deprecated functionality that was never removed.
2. **Direct Concrete Type Cast**: `SaveReportToPDF` and `SaveReportToCSV` cast `MainChart.DataContext` directly to `TestDataSeriesViewModel` (a concrete class) rather than an interface. This tight coupling could cause runtime exceptions if the DataContext type changes.
3. **Unsafe GraphColor Cast**: In `SaveReportToPDF`, `ds.GraphColor` is cast directly to `SolidColorBrush` without null or type checking:
```csharp
pdf.FillRectangle((ds.GraphColor as System.Windows.Media.SolidColorBrush).Color, ...);
```
This will fail silently or throw if `GraphColor` is null or a different brush type.
4. **Empty Event Handlers**: `MainChart_OnKeyUp` is entirely empty, and `obj_DataPointChanged` / `MainChart_OnMouseWheel` have all logic commented out. These handlers may be wired up in XAML but do nothing.
5. **CSV Filename Suffix**: CSV files are saved with `.PSD.csv` extension, indicating Power Spectral Density data, but this is not validated against actual data content.
6. **Encoding Fallback**: `SaveReportToCSV` catches exceptions when getting encoding and falls back to `Encoding.Default`, which may produce inconsistent file encodings across different systems.

View File

@@ -0,0 +1,123 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Graph/ViewModel/GraphViewModel.cs
generated_at: "2026-04-16T13:51:13.371255+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "cd4107fac05f80cd"
---
# GraphViewModel Documentation
## 1. Purpose
`GraphViewModel` is a ViewModel within the `DTS.Viewer.Graph` module that manages graph visualization and coordinates data series display. It serves as a mediator between parent ViewModels (`IViewerMainViewModel` or `IPSDReportMainViewModel`) and the graph rendering components, handling event-driven communication for channel selection, test summaries, and data loading progress. The class follows the MVVM pattern using Prism and Unity, providing bindable properties for UI state management and interaction requests for user notifications.
---
## 2. Public Interface
### Constructor
```csharp
public GraphViewModel(
IGraphView view,
IRegionManager regionManager,
IEventAggregator eventAggregator,
IUnityContainer unityContainer)
```
Initializes the ViewModel, sets the View's DataContext, and creates `NotificationRequest` and `ConfirmationRequest` instances.
### Public Properties
| Property | Type | Description |
|----------|------|-------------|
| `View` | `IGraphView` | The associated graph view instance. |
| `Parent` | `IBaseViewModel` (internal) | Reference to the parent ViewModel. |
| `DataSeriesView` | `ITestDataSeriesView` | The data series view used for chart rendering. |
| `NotificationRequest` | `InteractionRequest<Notification>` | Interaction request for displaying notifications. |
| `ConfirmationRequest` | `InteractionRequest<Confirmation>` | Interaction request for displaying confirmations. |
| `ContextGraphRegion` | `object` | Gets/sets the content of the `GraphRegion` on the View. |
| `MessageText` | `string` | User-facing message text. Default: `"Please select Event(s) to export data"`. |
| `MessageVisibility` | `bool` | Controls visibility of the message panel. |
| `ProgressPercent` | `double` | Progress percentage for data loading operations. Default: `0D`. |
| `ProgressText` | `string` | Progress message text. Default: `"Reading channel data..."`. |
| `ProgressVisibility` | `bool` | Controls visibility of the progress indicator. |
| `GraphInfoVisibility` | `bool` | Controls visibility of graph information. |
| `GraphVisibility` | `bool` | Computed as `!MessageVisibility`. |
| `HeaderInfo` | `string` | Returns constant `"GraphRegion"`. |
| `IsBusy` | `bool` | Busy state indicator. |
| `IsDirty` | `bool` | Always returns `false` (read-only). |
### Public Methods
```csharp
public override void Initialize()
```
Empty override; performs no initialization.
```csharp
public override void Initialize(object parameter)
```
Performs context-specific initialization based on `parameter` type:
- If `parameter` is `IViewerMainViewModel`: Calls `Subscribe()` and initializes `DataSeriesView`.
- If `parameter` is `Tuple<IBaseViewModel, string>` where `Item1` is `IPSDReportMainViewModel`: Calls `SubscribeDataSelect()` or `SubscribeResult()` based on `Item2` value, and configures chart scrollbars/actions accordingly.
---
## 3. Invariants
- **`IsDirty`** always returns `false` and cannot be modified.
- **`HeaderInfo`** always returns the string `"GraphRegion"`.
- **`GraphVisibility`** is always the logical inverse of `MessageVisibility`.
- Event handlers (`OnTestSelectedCountChanged`, `OnGraphSelectedCountChanged`, `OnGraphChannelsReadCompleted`, `OnGraphChannelReadCalcProgressChangedEvent`) check that `Parent` or `this` matches the event argument's source before processing.
- `OnGraphChannelsReadCompleted` returns early if `arg` is `null`.
- `OnGraphChannelReadCalcProgressChangedEvent` only updates `ProgressPercent` if the value is `>= 0`.
---
## 4. Dependencies
### This Module Depends On
| Namespace | Purpose |
|-----------|---------|
| `C1.WPF.C1Chart` | ComponentOne charting controls (`AxisScrollBar`). |
| `DTS.Common.Base` | Base classes (`BaseViewModel<T>`, `IBaseModel`, `IBaseViewModel`). |
| `DTS.Common.Events` | Event types: `RaiseNotification`, `GraphSelectedChannelCountNotification`, `TestSummaryCountNotification`, `TestModificationChangedEvent`, `GraphChannelsReadCompletedNotification`, `GraphChannelReadCalcProgressChangedEvent`. |
| `DTS.Common.Interactivity` | `InteractionRequest<T>`, `Notification`, `Confirmation`. |
| `DTS.Common.Interface` | `IGraphViewModel`, `ITestDataSeriesView`, `ITestDataSeriesViewModel`, `IViewerMainViewModel`, `IPSDReportMainViewModel`. |
| `Prism.Events` | `IEventAggregator`, `ThreadOption`. |
| `Prism.Regions` | `IRegionManager`. |
| `Unity` | `IUnityContainer`. |
### External Types Referenced (Not Defined Here)
- `GraphView` - Concrete view type cast in `ContextGraphRegion` property.
- `TestDataSeriesView` - Concrete data series view cast for chart configuration.
- `TestDataSeriesViewModel` - Concrete ViewModel cast for calling `SubscribePSD()`.
- `ITestModificationModel` - Parameter type for `OnTestModificationChanged`.
- Various event argument types: `TestSummaryCountNotificationArg`, `GraphSelectedChannelCountNotificationArg`, `NotificationContentEventArgs`, `GraphChannelsReadCompletedNotificationArgs`, `GraphChannelReadCalcProgressChangedEventArgs`.
---
## 5. Gotchas
1. **Member Hiding with `new` Keyword**: The class uses `new` to hide multiple base class members (`Model`, `ConfirmationRequest`, `PropertyChanged`, `OnPropertyChanged`, `IsBusy`, `IsDirty`). This can cause unexpected behavior when casting to base types.
2. **Code Duplication in Subscribe Methods**: `Subscribe()`, `SubscribeDataSelect()`, and `SubscribeResult()` have nearly identical implementations. The only difference is `Subscribe()` includes `TestModificationChangedEvent` subscription, while the others do not—but `OnTestModificationChanged` is an empty method body.
3. **Empty Event Handler**: `OnTestModificationChanged(ITestModificationModel obj)` is subscribed but contains no implementation.
4. **Concrete Type Casting**: The code casts interfaces to concrete types (`GraphView`, `TestDataSeriesView`, `TestDataSeriesViewModel`) which breaks abstraction and could cause runtime failures if implementations change:
```csharp
((AxisScrollBar)((TestDataSeriesView)DataSeriesView).MainChart.View.AxisX.ScrollBar).Visibility = ...
((TestDataSeriesView)DataSeriesView).MainChart.Actions.Clear();
((TestDataSeriesViewModel)viewModel).SubscribePSD();
```
5. **Hardcoded String Comparisons**: The `Initialize(object parameter)` method uses string literals (`"DataSelect"`, `"Graph"`) for control flow, which is fragile.
6. **Unused Private Field**: The `Model` property is set but never accessed elsewhere in the visible code.
7. **ReSharper Suppressions**: The file contains numerous ReSharper directive suppressions, suggesting known code quality issues that were disabled rather than addressed.