118 lines
11 KiB
Markdown
118 lines
11 KiB
Markdown
|
|
---
|
||
|
|
source_files:
|
||
|
|
- Common/DTS.Common.Serialization/TDM/File.cs
|
||
|
|
- Common/DTS.Common.Serialization/TDM/TDMParameterDlg.cs
|
||
|
|
- Common/DTS.Common.Serialization/TDM/Writer.cs
|
||
|
|
- Common/DTS.Common.Serialization/TDM/TestHeader.cs
|
||
|
|
- Common/DTS.Common.Serialization/TDM/TDMParameterDlg.Designer.cs
|
||
|
|
- Common/DTS.Common.Serialization/TDM/ChannelHeader.cs
|
||
|
|
generated_at: "2026-04-16T03:39:24.855976+00:00"
|
||
|
|
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||
|
|
schema_version: 1
|
||
|
|
sha256: "3ac6639dcd230dd5"
|
||
|
|
---
|
||
|
|
|
||
|
|
# TDM Serialization Module Documentation
|
||
|
|
|
||
|
|
## 1. Purpose
|
||
|
|
|
||
|
|
This module provides serialization support for exporting test data to the TDM (Test Data Manager) CSV format, specifically targeting the CFC1000 specification. It enables conversion of internal `Test` objects into structured CSV files containing test metadata, channel headers, and sampled data, with support for time-range filtering (start/stop), subsampling, and optional filtering. The module exists to interface with external tools or systems (e.g., TTS, TEMA, TDAS) that consume TDM-formatted data, ensuring compatibility through precise adherence to the expected file structure and field semantics.
|
||
|
|
|
||
|
|
## 2. Public Interface
|
||
|
|
|
||
|
|
### `DTS.Serialization.TDM.File`
|
||
|
|
- **`File()`**
|
||
|
|
Constructor. Initializes the file type with the fixed format name `"TDM CFC1000"` (passed to `base("TDM CFC1000")`).
|
||
|
|
- **`Exporter` (property, `IWriter<Test>`)**
|
||
|
|
Returns a lazily-initialized `Writer` instance configured with this `File` instance and `DefaultEncoding`. Sets the `Start` and `Stop` properties on the writer before returning.
|
||
|
|
- **`Start` (property, `double`)**
|
||
|
|
Gets/sets the start time (in seconds) for export filtering.
|
||
|
|
- **`Stop` (property, `double`)**
|
||
|
|
Gets/sets the stop time (in seconds) for export filtering.
|
||
|
|
|
||
|
|
### `DTS.Serialization.TDM.Writer`
|
||
|
|
- **`Writer(File fileType, int encoding)`** *(internal constructor)*
|
||
|
|
Initializes the writer with the specified `File` type and encoding.
|
||
|
|
- **`AllowTTSExportFiltering` (property, `bool`, default `false`)**
|
||
|
|
Controls whether filtered data export is enabled.
|
||
|
|
- **`Start`, `Stop` (properties, `double`)**
|
||
|
|
Get/set the time range (in seconds) to export. Rounded to 3 decimal places internally during `Write`.
|
||
|
|
- **`FilteredData` (property, `List<FilteredData>`)**
|
||
|
|
Holds precomputed filtered data (used when `AllowTTSExportFiltering` is `true`).
|
||
|
|
- **`Test` (property, `Test`)**
|
||
|
|
The test object being exported.
|
||
|
|
- **`IncrementLevel` (property, `ulong`, read-only)**
|
||
|
|
Controls granularity of progress updates during export (set dynamically based on estimated sample count).
|
||
|
|
- **`SubSampleInterval` (property, `ushort`)**
|
||
|
|
Subsampling factor applied during export.
|
||
|
|
- **`ExtensionPrefix` (property, `string`, default `""`)**
|
||
|
|
Optional string appended to the output filename before `.csv`.
|
||
|
|
- **`Write(string pathname, string id, string dataFolder, Test target, bool bFiltering, bool includeGroupNameInISOExport, FilteredData fd, Test.Module.Channel tmChannel, int channelNumber, BeginEventHandler, CancelEventHandler, EndEventHandler, TickEventHandler, ErrorEventHandler, CancelRequested, double minStartTime, int dataCollectionLength)`**
|
||
|
|
Primary export method. Serializes the `Test` to a CSV file at `pathname`. Performs rounding of `Start`/`Stop` to 3 decimal places, computes progress increments, and invokes `DoExport`. Notable: `pathname` is used as a directory; the actual file path is `Path.Combine(pathname, Test.Id)` with optional suffixes.
|
||
|
|
- **`DoExport(bool bFiltered, string pathname, double start, double stop, bool allowTTSFilteredExport)`** *(private)*
|
||
|
|
Core export logic: constructs the output filename, opens a `StreamWriter` with UTF-8 encoding (or fallback), and writes test header, channel header, and channel data via `TestHeader.WriteTestHeader`, `ChannelHeader.WriteChannelHeaderToString`, and `ChannelData.GenerateChannelData`/`WriteChannelData`.
|
||
|
|
- **`Initialize(...)`**
|
||
|
|
Empty stub method (no-op). Present to satisfy `IWriter<Test>` interface but performs no initialization.
|
||
|
|
|
||
|
|
### `DTS.Serialization.TDM.TestHeader`
|
||
|
|
- **`WriteTestHeader(Writer writer, TextWriter tw, bool bFiltered, UInt16 subSampleInterval, ulong numSamples, int preTriggerSamples)`**
|
||
|
|
Writes the test header section to the CSV. Includes test ID, impact parameters (hardcoded to 0), date/time, device sections (dummies, barriers, groups), sample counts, sample rate, channel count, and description. Device section writing is partially implemented (dummies use `UserValue3` from first channel; barriers/groups are written as blank lines).
|
||
|
|
|
||
|
|
### `DTS.Serialization.TDM.ChannelHeader`
|
||
|
|
- **`WriteChannelHeaderToString(Writer writer, TextWriter tw, bool bFiltered, double start, double end)`**
|
||
|
|
Writes the channel header section (15 lines) to the CSV. For each non-squib-voltage channel, populates fields: DAS name, capacity, engineering units, sensor SN, sensitivity, excitation, min/max values (computed over requested range), Toyota calc fields (hardcoded), knee point (from `SoftwareFilter`), data flag, channel code, and channel description. Squib voltage channels are skipped.
|
||
|
|
|
||
|
|
### `DTS.Serialization.TDM.TDMParameterDlg`
|
||
|
|
- **`TDMParameterDlg(string testName, double testStart, double testEnd)`**
|
||
|
|
Constructor. Initializes the dialog with test metadata. Sets default location to `TDMFolder` setting + `{testName}.csv`. Sets `tbStart`/`tbStop` text to either provided values (converted to ms) or user defaults, enforcing min/max constraints from `testStart`/`testEnd`.
|
||
|
|
- **`FileName` (property, `string`)**
|
||
|
|
Gets the selected output file path from `tbLocation.Text`.
|
||
|
|
- **`Start` (property, `double`)**
|
||
|
|
Gets the parsed start time in **seconds** (value in `tbStart` is in ms, divided by 1000).
|
||
|
|
- **`Stop` (property, `double`)**
|
||
|
|
Gets the parsed stop time in **seconds** (value in `tbStop` is in ms, divided by 1000).
|
||
|
|
- **`btnBrowse_Click`**
|
||
|
|
Opens a `SaveFileDialog` to select the output `.csv` file.
|
||
|
|
- **`btnOK_Click`**
|
||
|
|
Validates inputs: parses `tbStart`/`tbStop` as doubles, checks `Stop > Start`, ensures values are within `[testStart*1000, testEnd*1000]` ms range, saves settings, and sets `DialogResult = OK`.
|
||
|
|
- **`btnCancel_Click`**
|
||
|
|
Sets `DialogResult = Cancel` and closes the dialog.
|
||
|
|
|
||
|
|
## 3. Invariants
|
||
|
|
|
||
|
|
- **File format**: Output is always a `.csv` file named `{Test.Id}[optional suffix].csv`.
|
||
|
|
- **Time units**: `Start`/`Stop` in `File`, `Writer`, and `TDMParameterDlg` properties are in **seconds**, except `TDMParameterDlg` UI fields (`tbStart`, `tbStop`) which display and parse values in **milliseconds**.
|
||
|
|
- **Rounding**: `Start` and `Stop` passed to `DoExport` are rounded to 3 decimal places (milliseconds precision) before use.
|
||
|
|
- **Channel filtering**: Squib voltage channels (`IsSquibVoltage() == true`) are excluded from channel header and data export.
|
||
|
|
- **Sample bounds**: Exported sample indices are clamped to `[StartRecordSampleNumber, StartRecordSampleNumber + NumberOfSamples)` per module. Invalid ranges are silently adjusted.
|
||
|
|
- **Encoding**: Output uses UTF-8 with BOM by default; falls back to `Encoding.Default` on encoding errors.
|
||
|
|
- **Device section constraints**: `TestHeader` enforces `MAX_DEVICE_LINES = 23` total device lines (dummies, barriers, groups), with specific max counts (`MAX_DUMMY_DISPLAY=16`, `MAX_BARRIER_DISPLAY=3`, `MAX_OLD_GROUP_LINES=4`). Device lists are padded with empty lines to fill allocated space.
|
||
|
|
- **Progress reporting**: `IncrementLevel` is dynamically set to `10`, `1000`, or `10000` based on estimated sample count to ensure progress ticks fit within `uint` limits.
|
||
|
|
|
||
|
|
## 4. Dependencies
|
||
|
|
|
||
|
|
### Internal Dependencies
|
||
|
|
- **`DTS.Common.DAS.Concepts`**: Provides `Test`, `Test.Module`, `Test.Module.Channel`, `Test.Module.AnalogInputChannel`, `FilteredData`, `DataScaler`.
|
||
|
|
- **`DTS.Common.Utilities.Logging`**: Provides `APILogger`.
|
||
|
|
- **`DTS.Common.Serialization`**: Base classes `Serialization.File`, `Serialization.File.Writer<File>`, `IWriter<Test>`, event handlers (`BeginEventHandler`, `EndEventHandler`, `TickEventHandler`, `ErrorEventHandler`, `CancelEventHandler`, `CancelRequested`).
|
||
|
|
- **`DTS.Common.Enums.Sensors`**: `SensorConstants` (e.g., `BridgeType.IEPE`, `BridgeType.DigitalInput`).
|
||
|
|
- **`DTS.Common.Utilities`**: `DescriptionAttributeCoder<T>`.
|
||
|
|
- **`System`**: Core types (`System.IO`, `System.Text`, `System.Linq`, `System.Globalization`).
|
||
|
|
- **`System.Windows.Forms`**: Used by `TDMParameterDlg` (`Form`, `SaveFileDialog`, `ErrorProvider`, `TableLayoutPanel`, `Button`, `TextBox`, `Label`).
|
||
|
|
|
||
|
|
### External Dependencies
|
||
|
|
- **Settings**: Relies on `Properties.Settings1.Default.TDMFolder`, `DefaultStart`, `DefaultStop`.
|
||
|
|
- **File system**: Requires write access to the output directory.
|
||
|
|
|
||
|
|
## 5. Gotchas
|
||
|
|
|
||
|
|
- **Time unit confusion**: `TDMParameterDlg` UI uses milliseconds, but `File.Start`/`Stop` and `Writer.Start`/`Stop` use seconds. Conversion is handled only in `TDMParameterDlg`'s `Start`/`Stop` properties (divide ms by 1000).
|
||
|
|
- **Rounding hack**: `Start`/`Stop` are rounded to 3 decimal places in `Writer.Write` to mitigate floating-point precision issues from SLICE/TDAS download discrepancies. This may alter user-specified ranges slightly.
|
||
|
|
- **Sample index calculation**: `ChannelHeader.WriteChannelHeaderToString` computes sample indices using `TriggerSampleNumbers[0]` and `StartRecordSampleNumber`. If these values are inconsistent across modules, sample ranges may be misaligned.
|
||
|
|
- **Device section underutilization**: `TestHeader.WriteDeviceSection` writes dummies/barrriers/groups but often leaves many lines blank (e.g., dummies use only `UserValue3` from first channel; barriers/groups are hardcoded to 0 count). This is noted as "not completely implemented equivalent to TDM".
|
||
|
|
- **Squib channel handling**: Squib voltage channels are skipped entirely in export. Squib channels (non-voltage) are included but with hardcoded capacity (`10`) and sensitivity (`1`).
|
||
|
|
- **Min/max calculation**: `ChannelHeader.WriteChannelHeaderToString` computes min/max over the requested `start`/`end` range. If the range extends beyond available data, `IndexOutOfRangeException` is caught and logged, but min/max may be incomplete.
|
||
|
|
- **Encoding fallback**: If `DefaultEncoding` is invalid, `Encoding.Default` is used silently (after logging), which may cause non-ASCII characters to be mangled.
|
||
|
|
- **No-op `Initialize`**: The `Writer.Initialize` method is present but empty. Any initialization logic must be done elsewhere (e.g., in `Write`).
|
||
|
|
- **Hardcoded values**: Several fields are hardcoded (e.g., impact speed/weight = 0, capacity for squib = 10, cable multiplier = 1, excitation for digital = 1V). These may not match all TDM variants.
|
||
|
|
- **Filename construction**: Output filename is `Path.Combine(pathname, Test.Id)`, where `pathname` is treated as a directory. If `pathname` is a file path, behavior is undefined (likely creates nested path).
|