--- source_files: - Common/DTS.Common.Serialization/RDF/RDF.File.cs - Common/DTS.Common.Serialization/RDF/RDF.File.Writer.cs generated_at: "2026-04-16T03:40:00.442802+00:00" model: "Qwen/Qwen3-Coder-Next-FP8" schema_version: 1 sha256: "abee1ca96445ca58" --- # RDF.File Module Documentation ## 1. Purpose This module implements serialization and deserialization logic for Toyota RDF (Rack Data Format) files—a proprietary binary file format used to export test data from DTS systems for Toyota compliance. It defines the `File` class (a concrete implementation of `Serialization.File`) that represents an RDF file and its associated metadata, and the nested `Writer` class responsible for writing test data (`Test`) to disk in the RDF format. The module supports filtering, linearization, and ISO-compliant naming conventions, and is tightly coupled with ISO test plan metadata and DAS hardware configuration. ## 2. Public Interface ### `DTS.Serialization.RDF.File` - **Constructor** `public File(Common.ISO.TestPlan plan)` Initializes a new `File` instance with the provided `TestPlan`. Calls `base("RDF")` to set the format name. - **Properties** - `public static string Extension => ".001"` Returns the fixed file extension for RDF files. - `public bool UseZeroForUnfiltered { get; set; } = false` Controls whether unfiltered data points are written as zero (instead of original ADC values) during export. - `public bool FilteredExport { get; set; } = false` Enables filtering of data during export (behavior depends on downstream `Writer` logic). - `public IWriter Exporter { get; }` Lazily constructs and returns a `Writer` instance, passing `UseZeroForUnfiltered`, `FilteredExport`, and `_testPlan` to it. Sets `Writer.WriterParent = this` to enable access to EU data. - **EU Data Accessors (override)** - `public override void SetEUData(string channelID, FilteredData fd)` Stores filtered EU data for a channel in the internal `_EUUnfilteredDataForLinearizedChannels` dictionary. - `public override FilteredData GetEUData(string channelID)` Retrieves stored EU data for a given `channelID`. ### `DTS.Serialization.RDF.File.Writer` - **Constructor** `internal Writer(File fileType, int encoding)` Internal constructor; initializes base `Writer` with the parent `File` and encoding. - **Properties** - `public File WriterParent { get; set; }` Reference to the parent `File` instance (used to access EU data). - `public TestPlan TestPlan { get; set; }` ISO `TestPlan` used for metadata (e.g., test object numbering). - `public string ExtensionPrefix { get; set; } = string.Empty` Optional prefix appended to the filename before the `.001` extension. - `public bool UseZeroForUnfiltered { get; set; }` Mirrors the parent `File.UseZeroForUnfiltered`. - `public bool FilteredExport { get; set; }` Mirrors the parent `File.FilteredExport`. - `public bool UseIsoCodeForDiadem200 { get; set; }` Unused in current implementation (commented out in usage). - **Methods** - `public void Write(string pathname, string id, Test test, bool bFiltering, bool includeGroupNameInISOExport, double minStartTime, int dataCollectionLength)` Convenience overload of `Write(...)` with simplified parameters; delegates to the full 18-parameter overload with `null` for optional event handlers and data folder. - `public void Write(string pathname, string id, string dataFolder, Test test, bool bFiltering, bool includeGroupNameInISOExport, FilteredData fd, Test.Module.Channel tmChannel, int channelNumber, BeginEventHandler beginEventHandler, CancelEventHandler cancelEventHandler, EndEventHandler endEventHandler, TickEventHandler tickEventHandler, ErrorEventHandler errorEventHandler, CancelRequested cancelRequested, double minStartTime, int dataCollectionLength)` Primary export method. - Validates/normalizes `id`: strips `" RunTest"` or `" Checkout"` suffixes if present; falls back to `test.Id` if `id` lacks these suffixes. - Truncates `id` to `MAX_TEST_NAME_LENGTH` (8 chars) implicitly via filename construction. - Writes RDF file to `{pathname}/{id}.001`. - Calls `WriteTestInfo(...)` and `WriteChannelInfo(...)` to serialize headers and data. - Handles exceptions via event handlers or rethrows. - `public void Initialize(...)` Empty stub; no-op. - `protected void WriteTestInfo(BinaryWriter fileWriter, Test test, string testId, TickEventHandler tickEventHandler, string dataFolder)` Writes an 80-byte header record containing: - `testId` (padded/truncated to 8 chars) - Number of files (hardcoded to `"1"`) - File number (`" 1"`) - Number of channels (`test.Channels.Count`, left-padded to 3 chars) - Timestamp (MM, DD, YY, HH, MM) - 53 bytes of padding. - `protected void WriteChannelInfo(BinaryWriter fileWriter, Test test, string testId, TickEventHandler tickEventHandler, string dataFolder, CancelRequested cancelRequested, string pathName, TestPlan testPlan)` Writes per-channel headers and ADC data. - Sorts channels by `AbsoluteDisplayOrder`, then by `ToString()`. - Computes homogenized time range (`dMaxStart` to `dMinEnd`) across all channels to align samples. - For each channel: - Writes channel metadata (5-char channel number, DAS channel ID, subchannel, scaling samples, pre-trigger samples, sample rate, zero level, calibration points, resolution, rack/module serials). - Conditionally writes `.lin` or `.dig` files for non-linear/digital channels. - Writes 16-bit ADC data (centered at 32767) for all samples in the homogenized range, *excluding the last 2 samples* (to match TDC RDF behavior). - Special handling for: - Squib channels (`I`/`C` suffixes). - Slice modules (channel numbering adjusted). - Digital inputs (on/off thresholding). - Non-linear channels (scaled via `nonLinearScaleFactor`). - Naturally inverted scales (e.g., SPS/SLS modules without linearization). - `private double[] GetEUData(Test.Module.Channel channel)` Retrieves EU data for `channel` via `WriterParent.GetEUData(channel.ChannelId).Data`. - `private static string GetRackSerialNumber(string serialNumber, string baseSerialNumber)` Returns last 4 chars of `serialNumber` or `baseSerialNumber`, left-padded to 5 chars; `"EMPTY"` if null/whitespace. - `private static bool IsSlice(string sn)` Returns `true` if `sn` starts with `"SPS"`, `"SPT"`, `"SPD"`, `"BA"`, `"SLT"`, `"SLS"`, or `"SLD"`. - `private bool HasNaturallyInvertedScaleFactor(Test.Module.Channel channel)` Returns `true` for SPS/SLS analog channels *without* a valid linearization formula and *not* digital. - `private static int DisplayOrderComparer(object x, object y)` Compares two `Test.Module.Channel` instances by `AbsoluteDisplayOrder`, then by `ToString()`. - `public string GetTestObjectNumber(string isocode, TestPlan plan)` Returns 1-based index of the `TestObject` in `plan.ISOTestObjects` matching the `TestObject` character from `isocode`. - **Private Helper Methods (non-public)** - `CreateLinearizedData(...)`: Writes `.lin` files with EU data (ASCII CSV). - `CreateDigitizedData(...)`: Writes `.dig` files with EU data (ASCII CSV). - `CreateLinearizedDataCSV(...)`: Writes `.csv` files for debugging (ADC, mV, EU columns). - `Create3DIRTraccDataCSV(...)`: *Commented out*; legacy debugging utility. ## 3. Invariants - **Filename constraints** - RDF files must end with `.001`. - Test name (`id`) is truncated to exactly 8 characters (via `PadRight`/`Substring` in `WriteTestInfo`). - `id` must contain `" RunTest"` or `" Checkout"` suffix to be accepted; otherwise, `test.Id` is used (per FB8419/36769). - **Data alignment** - All channels are exported with a common time range (`dMaxStart` to `dMinEnd`), ensuring identical sample counts per channel. - The last 2 samples are *always omitted* from the final binary output (to match TDC behavior), regardless of `dataCollectionLength`. - **Channel ordering** - Channels are sorted by `AbsoluteDisplayOrder` before serialization. - **ADC centering** - All ADC values are written as 16-bit unsigned integers centered at `DTS.Common.Constants.ADC_MIDPOINT` (32767). - **Calibration points** - Cal point 1 is always `+0.000E+000`. - Cal point 2 is `MidpointDeflection` (70% of `ADC_MIDPOINT`) scaled to EU, with special handling for digital inputs, squibs, and non-linear channels. ## 4. Dependencies ### Dependencies *of* this module: - `DTS.Common.ISO.TestPlan` (for test metadata, ISO code parsing, test object numbering). - `DTS.Common.DAS.Concepts.DataScaler` (for scaling ADC → mV → EU). - `DTS.Common.Enums.Sensors.SensorConstants` (for `BridgeType` constants like `DigitalInput`, `IEPE`). - `DTS.Common.Utilities.Logging.APILogger` (for exception logging). - `DTS.Serialization.Test`, `Test.Module.Channel`, `FilteredData`, `IWriter` (serialization contracts). - `System.IO`, `System.Text`, `System.Globalization` (standard .NET I/O and formatting). ### Dependencies *on* this module: - Any code requiring RDF export (e.g., test export workflows, ISO compliance tools). - Likely consumed via `File.Exporter` to serialize `Test` instances. ## 5. Gotchas - **Sample count discrepancy**: The last 2 samples are *always* omitted from the binary output (hardcoded in loops: `iPt <= endSample - 2`). This is intentional to match TDC RDF exports, but may cause off-by-two discrepancies with raw data downloads. - **Test name normalization**: `id` is *only* accepted if it ends with `" RunTest"` or `" Checkout"`; otherwise, `test.Id` is used. This may cause unexpected filename changes if `id` is not properly suffixed. - **Channel numbering quirks**: - Slice modules require manual channel offset (`+ module.Number * 3`). - Squib channels use `I`/`C` suffixes (current/indication) and require even/odd channel number adjustment. - **Naturally inverted scales**: For SPS/SLS modules *without* linearization, the ADC data is inverted (`dataPoint *= -1`) *and* `ZeroMvInADC` is negated if non-zero. This is non-obvious and may cause misalignment if not handled consistently. - **Digital input handling**: Digital channels use a threshold-based on/off conversion (5 EU per ADC step), but the logic does *not* inspect `DigitalMode` (e.g., `CCNO`, `HighToLow`)—it assumes a simple threshold. This may misrepresent edge-triggered inputs. - **EU data dependency**: `GetEUData` relies on `_EUUnfilteredDataForLinearizedChannels` being pre-populated via `SetEUData`. If not, `KeyNotFoundException` may occur. - **Unused properties**: `UseIsoCodeForDiadem200` and `ExtensionPrefix` are defined but not meaningfully used in the current implementation. - **Legacy debugging code**: `Create3DIRTraccDataCSV` is commented out but retained in source—do not assume active functionality. - **Error handling**: Exceptions during export are logged via `APILogger` *and* rethrown (or dispatched via `errorEventHandler`). This dual behavior may cause duplicate logging if handlers are registered.