--- source_files: - Common/DTS.Common.Serialization/SliceRaw/SliceRaw.File.IDasTimestampHeader.cs - Common/DTS.Common.Serialization/SliceRaw/SliceRaw.File.Reader.BadCrcException.cs - Common/DTS.Common.Serialization/SliceRaw/SliceRaw.File.Reader.MissingFileException.cs - Common/DTS.Common.Serialization/SliceRaw/SliceRaw.File.Reader.TooManyFilesException.cs - Common/DTS.Common.Serialization/SliceRaw/SliceRaw.File.PersistentChannel.NotInitializedException.cs - Common/DTS.Common.Serialization/SliceRaw/SliceRaw.File.PersistentChannel.IsInitializingException.cs - Common/DTS.Common.Serialization/SliceRaw/SliceRaw.File.PersistentChannel.DataTooBigForArrayException.cs - Common/DTS.Common.Serialization/SliceRaw/SliceRaw.File.PersistentChannel.AlreadyInitializedException.cs - Common/DTS.Common.Serialization/SliceRaw/SliceRaw.File.PersistentChannel.DependencyNotInitializedException.cs - Common/DTS.Common.Serialization/SliceRaw/SliceRaw.File.BinaryDasTimestampHeader.cs - Common/DTS.Common.Serialization/SliceRaw/SliceRaw.File.PersistentEuChannel.cs - Common/DTS.Common.Serialization/SliceRaw/SliceRaw.File.IChannelHeader.cs - Common/DTS.Common.Serialization/SliceRaw/ModifyChannel.cs - Common/DTS.Common.Serialization/SliceRaw/SliceRaw.File.BinaryChannelHeader.cs generated_at: "2026-04-16T03:38:20.120884+00:00" model: "Qwen/Qwen3-Coder-Next-FP8" schema_version: 1 sha256: "880f258a855611f2" --- # SliceRaw Serialization Module Documentation ## 1. Purpose This module provides serialization and deserialization support for binary channel data files used in the DTS SLICE data acquisition system. It defines core interfaces (`IDasTimestampHeader`, `IChannelHeader`) and concrete implementations (`BinaryDasTimestampHeader`, `BinaryChannelHeader`) for structured header metadata, along with supporting classes for reading files (`File.Reader`), managing persistent channel data (`File.PersistentChannel`), and converting raw ADC samples to engineering units (`File.PersistentEuChannel`). The module enables robust handling of binary `.chn` files containing time-series sample data, including calibration metadata, trigger information, and unit conversion parameters. ## 2. Public Interface ### Interfaces #### `IDasTimestampHeader` - `uint MagicKey { get; set; }` Magic number identifying the binary file type. - `uint HeaderVersionNumber { get; set; }` Version number of the header format. - `ulong OffsetOfSampleDataStart { get; set; }` Byte offset from file start to the beginning of sample data. - `ulong NumberOfSamples { get; set; }` Total number of samples in the file. - `uint NumberOfBitsPerSample { get; set; }` Bit depth per sample (e.g., 16, 24, 32). - `uint Crc32 { get; }` CRC16 (despite property name) checksum of header fields. #### `IChannelHeader` - `uint MagicKey { get; set; }` Magic number identifying the binary channel file type. - `uint HeaderVersionNumber { get; set; }` Version number of the channel header format. - `ulong OffsetOfSampleDataStart { get; set; }` Byte offset from file start to sample data. - `ulong NumberOfSamples { get; set; }` Total number of samples. - `uint NumberOfBitsPerSample { get; set; }` Bit depth per sample. - `uint AreSamplesSigned { get; set; }` Flag indicating if samples are signed integers. - `double SampleRate { get; set; }` Sample rate in Hz. - `ushort NumberOfTriggers { get; set; }` Number of triggers recorded. - `ulong[] TriggerSampleNumbers { get; set; }` Array of sample indices where triggers occurred. - `int TriggerAdjustmentSamples { get; set; }` Adjustment count for trigger backdating. - `int PreTestZeroLevelCounts { get; set; }` Zero-level ADC counts before testing. - `int RemovedADC { get; set; }` ADC offset removed during hardware zeroing. - `double Excitation { get; set; }` Excitation voltage applied to the channel. - `int ZeroMvInADC { get; set; }` ADC value when 0mV is injected. - `int WindowAverageADC { get; set; }` Average ADC over zero window. - `int OriginalOffsetADC { get; set; }` Initial ADC offset. - `int PreTestDiagnosticsLevelCounts { get; set; }` Diagnostics level counts before testing. - `double PreTestNoisePercentageOfFullScale { get; set; }` Pre-test noise as % of full scale. - `int PostTestZeroLevelCounts { get; set; }` Zero-level ADC counts after testing. - `int PostTestDiagnosticsLevelCounts { get; set; }` Diagnostics level counts after testing. - `int DataZeroLevelCounts { get; set; }` Zero-level ADC counts in data. - `double ScaleFactorMv { get; set; }` Scale factor in mV. - `double MvPerEu { get; set; }` Sensitivity in mV per engineering unit. - `ushort EuFieldLengthWithTerminator { get; set; }` Length of engineering unit string including null terminator. - `char[] EngineeringUnit { get; set; }` Engineering unit string (e.g., 'V', 'Pa'). - `char[] IsoCode { get; set; }` ISO unit code. - `uint Crc32 { get; }` CRC16 checksum of header fields. ### Concrete Header Classes #### `BinaryDasTimestampHeader` - `static uint RequiredMagicKey => 0xF15363C2` Required magic key for timestamp headers. - `static uint CurrentVersionNumber => 0x01` Current header version. - `static List KnownHeaderVersionNumbers => new List(new uint[] { 0x01 })` Supported header versions. - Implements `IDasTimestampHeader` interface. #### `BinaryChannelHeader` - `static uint RequiredMagicKey => 0x2C36351F` Required magic key for channel headers. - `static uint CurrentVersionNumber => 0x04` Current header version. - `static List KnownHeaderVersionNumbers => new List(new uint[] { 0x01, 0x02, 0x03, 0x04 })` Supported header versions. - `uint UnpaddedEuStringPaddedEuLengthCrc32 { get; }` CRC16 using unpadded EU string but padded EU length field. - `uint UnpaddedEuCrc32 { get; }` CRC16 using unpadded EU string and calculated length. - Implements `IChannelHeader` interface. ### Exception Classes #### `File.Reader.BadCrcException` - `BadCrcException()` Default constructor. - `BadCrcException(string msg)` Constructor with message. - `BadCrcException(string msg, Exception innerEx)` Constructor with message and inner exception. #### `File.Reader.MissingFileException` - `MissingFileException()` Default constructor. - `MissingFileException(string msg)` Constructor with message. - `MissingFileException(string msg, Exception innerEx)` Constructor with message and inner exception. #### `File.Reader.TooManyFilesException` - `TooManyFilesException()` Default constructor. - `TooManyFilesException(string msg)` Constructor with message. - `TooManyFilesException(string msg, Exception innerEx)` Constructor with message and inner exception. #### `File.PersistentChannel.NotInitializedException` - `NotInitializedException()` Default constructor. - `NotInitializedException(string msg)` Constructor with message. - `NotInitializedException(string msg, Exception innerEx)` Constructor with message and inner exception. #### `File.PersistentChannel.IsInitializingException` - `IsInitializingException()` Default constructor. - `IsInitializingException(string msg)` Constructor with message. - `IsInitializingException(string msg, Exception innerEx)` Constructor with message and inner exception. #### `File.PersistentChannel.DataTooBigForArrayException` - `DataTooBigForArrayException()` Default constructor. - `DataTooBigForArrayException(string msg)` Constructor with message. - `DataTooBigForArrayException(string msg, Exception innerEx)` Constructor with message and inner exception. #### `File.PersistentChannel.AlreadyInitializedException` - `AlreadyInitializedException()` Default constructor. - `AlreadyInitializedException(string msg)` Constructor with message. - `AlreadyInitializedException(string msg, Exception innerEx)` Constructor with message and inner exception. #### `File.PersistentChannel.DependencyNotInitializedException` - `DependencyNotInitializedException()` Default constructor. - `DependencyNotInitializedException(string msg)` Constructor with message. - `DependencyNotInitializedException(string msg, Exception innerEx)` Constructor with message and inner exception. ### Other Public Types #### `PersistentEuChannel` - `PersistentEuChannel(PersistentChannel persistentChannel, DataScaler scaler)` Wraps a `PersistentChannel` and converts raw samples to engineering units. - `PersistentChannel BasePersistentChannel { get; set; }` Underlying raw channel. - `DataScaler EuDataScaler { get; set; }` Converter from ADC to EU. - `double this[ulong i] { get; }` Read-only indexer returning EU value at index `i`. - `long Length { get; }` Number of samples (same as `BasePersistentChannel.Length`). - `void Dispose()` Disposes underlying channel. #### `ModifyChannel` (WinForms UI) - `File.PersistentChannel ChannelToModify { set; }` Sets the channel to be modified via UI. - Public UI form for editing channel header metadata. ## 3. Invariants - **Magic Key Validation**: `BinaryDasTimestampHeader` requires `MagicKey == 0xF15363C2`; `BinaryChannelHeader` requires `MagicKey == 0x2C36351F`. Headers with incorrect magic keys are invalid. - **Header Versioning**: `BinaryDasTimestampHeader` supports only version `0x01`. `BinaryChannelHeader` supports versions `0x01` through `0x04`. Version-specific fields are conditionally included in CRC calculation based on `HeaderVersionNumber`. - **CRC Calculation Invariants**: - CRC is computed over a byte array built from header fields in a specific order. - For `BinaryChannelHeader`, version-specific fields (`RemovedADC`, `Excitation`, `TriggerAdjustmentSamples`, etc.) are included only if `HeaderVersionNumber >=` corresponding version constant. - EU string padding behavior affects CRC: three CRC variants exist (`Crc32`, `UnpaddedEuCrc32`, `UnpaddedEuStringPaddedEuLengthCrc32`) with different padding rules. - Data arrays are padded to even byte count before CRC calculation. - **PersistentChannel Initialization**: - Properties may only be set once (`AlreadyInitializedException` thrown on reassignment). - Accessing properties during initialization throws `IsInitializingException`. - Accessing uninitialized properties throws `NotInitializedException`. - Dependencies must be initialized first; otherwise `DependencyNotInitializedException` is thrown. - **Array Size Limitation**: Attempting to load data exceeding `int.MaxValue` bytes throws `DataTooBigForArrayException`. ## 4. Dependencies ### Internal Dependencies - `DTS.Common.Utilities.Logging.APILogger` Used for logging (commented out in CRC calculation code). - `DTS.Common.Utilities.Logging.Exceptional` Base class for header classes (indicated by `: Exceptional`). - `DTS.Common.DAS.Concepts.DataScaler` Used by `PersistentEuChannel` for unit conversion. - `DTS.Common.Utils.Utils.Math_DoCRC16Step` CRC calculation helper (despite property name, CRC16 is used, not CRC32). ### External Dependencies - `System` (Core .NET types) - `System.Collections.Generic` - `System.Text` - `System.Windows.Forms` (for `ModifyChannel` UI form) - `DTS.Common.DAS.Concepts` (for `DataScaler`) - `DTS.Common.Utilities.DotNetProgrammingConstructs` (for `Property` wrapper) ### Inferred Usage - `File.Reader` class (not shown in source but referenced in exception files) likely handles file I/O and header parsing. - `File.PersistentChannel` (not shown) likely implements `IChannelHeader` and manages raw sample data. - `ModifyChannel` form suggests integration with desktop UI for header editing. ## 5. Gotchas - **CRC Name Mismatch**: Properties named `Crc32` actually compute CRC16 (16-bit), not CRC32. This is evident from `Math_DoCRC16Step` usage and `ushort crc` variable. - **EU String Padding Ambiguity**: CRC calculation has three variants with different EU string padding rules: - `Crc32`: Uses original EU string (with padding if odd length). - `UnpaddedEuCrc32`: Strips leading/trailing whitespace before padding. - `UnpaddedEuStringPaddedEuLengthCrc32`: Strips padding but uses original `EuFieldLengthWithTerminator` value (including potential +1 bug). - **Header Version Field Inclusion**: CRC calculation conditionally includes fields based on `HeaderVersionNumber`. For example: - `RemovedADC` included only if `HeaderVersionNumber >= 2` - `Excitation`, `TriggerAdjustmentSamples`, etc., included only if `HeaderVersionNumber >= 3` - `WindowAverageADC` included only if `HeaderVersionNumber >= 4` - **`EuFieldLengthWithTerminator` Bug Tolerance**: CRC calculation accommodates a known bug where `EuFieldLengthWithTerminator` is stored as `actual_length + 1`. Logic checks if `EuFieldLengthWithTerminator > EngineeringUnit.Length + 1` to detect this. - **`TriggerSampleNumbers` Array Handling**: `ModifyChannel` UI only edits the first trigger sample (`TriggerSampleNumbers[0]`), ignoring additional triggers. - **Read-Only `PersistentEuChannel` Indexer**: Setting values via `PersistentEuChannel[i] = value` throws `NotSupportedException`, even though the indexer has a setter. - **Partial Class Structure**: Classes like `File`, `Reader`, and `PersistentChannel` are declared as `partial`, implying implementation is split across multiple files not included in this documentation set. Behavior of `File.Reader` and `File.PersistentChannel` cannot be fully inferred. - **Missing File Exception Handling**: `MissingFileException` is thrown when a file is not found, but exact conditions (e.g., during `File.Reader` construction) are not visible in source. - **No Public Constructor Visibility**: Constructors for `File.Reader` and `File.PersistentChannel` are not shown, making initialization patterns unclear. - **No Documentation for `StampCrc()`**: `ModifyChannel.btnWrite_Click` calls `_channel.StampCrc()`, but this method is not defined in the provided source.