--- 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`)** 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`)** 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` 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`, `IWriter`, event handlers (`BeginEventHandler`, `EndEventHandler`, `TickEventHandler`, `ErrorEventHandler`, `CancelEventHandler`, `CancelRequested`). - **`DTS.Common.Enums.Sensors`**: `SensorConstants` (e.g., `BridgeType.IEPE`, `BridgeType.DigitalInput`). - **`DTS.Common.Utilities`**: `DescriptionAttributeCoder`. - **`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).