14 KiB
source_files, generated_at, model, schema_version, sha256
| source_files | generated_at | model | schema_version | sha256 | ||
|---|---|---|---|---|---|---|
|
2026-04-16T03:36:32.708668+00:00 | Qwen/Qwen3-Coder-Next-FP8 | 1 | 6a62f69116272309 |
HDF
Documentation: DTS.Serialization.HDF.File
1. Purpose
This module implements a concrete serialization backend for writing test data to HDF5 files, specifically tailored for DTS’s data acquisition systems. It extends Serialization.File and implements IWritable<Test>, enabling structured export of test metadata, raw sensor data (in ADC, mV, and Engineering Units), and associated binary files (logs, reports, setup, .dts) into a hierarchical HDF5 container. The implementation is tightly coupled to DTS’s internal data models (Test, AnalogInputChannel, DataScaler) and supports WIAMan-compliant metadata and S6 system attributes for interoperability with external analysis tools.
2. Public Interface
public partial class File : Serialization.File, IWritable<Test>
-
File()
Constructor. Initializes the base class with"HDF"as the file type identifier. -
IWriter<Test> Exporter { get; }
Lazily instantiates and returns aWriterinstance, using the default encoding. Throws anExceptionwrapped around any inner exception encountered during writer creation. -
bool ExportADC { set; }
Controls whether raw ADC data is exported. Delegates to((Writer)Exporter).ExportADC. -
bool ExportEU { set; }
Controls whether engineering unit (EU) data is exported. Delegates to((Writer)Exporter).ExportEU. -
bool ExportMV { set; }
Controls whether millivolt (mV) data is exported. Delegates to((Writer)Exporter).ExportMV. -
bool ExportLogs { set; }
Controls whether log files (from/Logsdirectory) are included in the HDF5/Files/Logsgroup. Delegates to((Writer)Exporter).ExportLogs. -
bool ExportReports { set; }
Controls whether report files (from/Reportsdirectory) are included in/Files/Reports. Delegates to((Writer)Exporter).ExportReports. -
bool ExportSetup { set; }
Controls whether setup files (from/SETUPdirectory) are included in/Files/SETUP. Delegates to((Writer)Exporter).ExportSetup. -
bool ExportDTSFile { set; }
Controls whether.dtsfiles (from/Binary/{dataDir}) are included in/Files/Binary/{dataDir}. Delegates to((Writer)Exporter).ExportDTSFile. -
string CustomerName { set; }
Sets WIAMan metadata attributeDirector. Delegates to((Writer)Exporter).CustomerName. -
string TestEngineerName { set; }
Sets WIAMan metadata attributeOperator. Delegates to((Writer)Exporter).TestEngineerName. -
string LabName { set; }
Sets WIAMan metadata attributeLocation. Delegates to((Writer)Exporter).LabName. -
bool IsWiamanData { set; }
Sets WIAMan metadata attributeIs WIAMan Data. Delegates to((Writer)Exporter).IsWiamanData. -
Dictionary<string, string> ISOToFineLocation3 { set; }
Used to populate WIAMan attributeAnthropomorphic Label. Delegates to((Writer)Exporter).ISOToFineLocation3. -
Dictionary<string, string> ISOToPhysicalDimension { set; }
Used to populate WIAMan attributeChannel Label:Category. Delegates to((Writer)Exporter).ISOToPhysicalDimension. -
Dictionary<string, string> ISOToPosition { set; }
Used to populate WIAMan attributeChannel Label:Optional. Delegates to((Writer)Exporter).ISOToPosition. -
Dictionary<string, string> ISOToTransducerMainLocation { set; }
Not used in the current implementation. Delegates to((Writer)Exporter).ISOToTransducerMainLocation, but the setter is present inFilewhile the corresponding property is not declared inWriter(see Gotchas).
public class Writer : Writer<File>, IWriter<Test>
-
internal File WriterParent { get; }
Reference to the owningFileinstance. -
bool ExportADC { get; set; }
Controls ADC data export. Default:true. -
bool ExportEU { get; set; }
Controls EU data export. Default:true. -
bool ExportMV { get; set; }
Controls mV data export. Default:true. -
bool ExportLogs { get; set; }
Controls log file inclusion. Default:true. -
bool ExportReports { get; set; }
Controls report file inclusion. Default:true. -
bool ExportSetup { get; set; }
Controls setup file inclusion. Default:true. -
bool ExportDTSFile { get; set; }
Controls.dtsfile inclusion. Default:true. -
string CustomerName { get; set; }
WIAMan metadata:Director. -
string TestEngineerName { get; set; }
WIAMan metadata:Operator. -
string LabName { get; set; }
WIAMan metadata:Location. -
bool IsWiamanData { get; set; }
WIAMan metadata:Is WIAMan Data. -
Dictionary<string, string> ISOToFineLocation3 { get; set; }
Used to constructAnthropomorphic Label. -
Dictionary<string, string> ISOToPhysicalDimension { get; set; }
Used to constructChannel Label:Category. -
Dictionary<string, string> ISOToPosition { get; set; }
Used to constructChannel Label:Optional. -
Dictionary<string, string> ISOToTransducerMainLocation { get; set; }
Declared inWriterbut never used. (See Gotchas.) -
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)
Main export method. Writes theTestobject to an HDF5 file atpathname.- Creates
/Files/{folder}groups for logs, setup, reports, and.dtsfiles ifExport*flags are enabled. - Writes three dataset groups:
/Datasets_EU,/Datasets,/Datasets_MV, depending on flags. - For each
AnalogInputChannel, writes channel-specific metadata (WIAMan + S6 attributes) and raw data as datasets named{index}: Strain_RawYData. - Uses
Parallel.ForEachovertest.Channelsfor performance. - Progress is reported via
tickEventHandlerin 100-step increments. - Errors are logged via
APILoggerand propagated viaerrorEventHandler.
- Creates
-
private Common.DAS.Concepts.DataScaler GetDataScaler(Test.Module.AnalogInputChannel currentAnalogChannel)
Constructs aDataScalerfrom channel properties (e.g.,UnitConversion,Multiplier,Sensitivity,ZeroMethod,RemovedADC,MeasuredExcitationVoltage, etc.). Includes robust error handling with logging for individual scaler property assignments. -
private void CheckStatus(long status, ErrorLocation location)
Throws anExceptionwithlocation.ToString()ifstatus < 0. Used after HDF5 API calls. -
private void CreateStringAttribute(long objectId, string attributeName, string attributeValue)
Creates an HDF5 string attribute onobjectId. Handles null/empty values gracefully. UsesH5S.create,H5T.copy,H5A.create,H5A.write, andMarshal.StringToHGlobalAnsi. All handles are closed infinally. -
private void CreateIntAttribute(long objectId, string title, int value)
IfATTRIBUTE_STRING_DATATYPE_ONLYistrue(hardcoded), convertsvalueto string and delegates toCreateStringAttribute. Otherwise, would create numeric attribute (not implemented). -
private void CreateUlongAttribute(long objectId, string title, ulong value)
Same behavior asCreateIntAttribute. -
private void CreateDoubleAttribute(long objectId, string title, double value)
Same behavior asCreateIntAttribute. -
private void AddDirectoryIfExists(string binaryPath, string folder, long hdfObjectId, string fileExtension)
Adds all files matchingfileExtensionfrom a computed source directory (e.g.,root/Logs) into an HDF5 group at/Files/{folder}. Uses nestedDirectoryInfo.Parentchecks to determine root. Reads files into byte arrays and writes them as 1DNATIVE_UCHARdatasets. -
private int ComputeNumberOfSteps(Test test)
Computes total export steps based on enabled export flags and channel count. Each enabled export type contributesChannels.Countsteps; each file group (logs, setup, reports, dts) contributes 1 step. -
internal Writer(File fileType, int encoding)
Constructor. Initializes allExport*flags totrue. SetsWriterParent. -
public void Initialize(...)
Empty implementation. No initialization logic is performed.
3. Invariants
-
HDF5 file structure:
/Files/{folder}groups are created only if correspondingExport*flag istrue./Datasets,/Datasets_EU,/Datasets_MVgroups are created only ifExportADC,ExportEU, orExportMVistrue, respectively.- Each channel’s data resides under a group named
/{datasetGroup}/{index:0000}: {channelName}. - Channel data datasets are named
{index}: Strain_RawYData.
-
Data type in datasets:
- ADC:
H5T.NATIVE_SHORT(16-bit signed integer). - mV/EU:
H5T.NATIVE_DOUBLE(64-bit float).
- ADC:
-
Channel ordering:
Channels are sorted byAbsoluteDisplayOrderbefore processing. -
Progress reporting:
Progress updates occur everyUPDATE_INTERVAL = 1000samples per channel, and at group-level milestones (e.g., after each file group or dataset group is written). Final progress is always set to100Dinfinally. -
WIAMan attribute requirement:
All WIAMan attributes listed in code comments are written only ifIsWiamanDataistrue?
→ No: Attributes are written unconditionally.IsWiamanDataonly sets a string attribute"Is WIAMan Data"to"TRUE"/"FALSE". -
String attributes:
All attributes (int, double, ulong) are stored as strings ifATTRIBUTE_STRING_DATATYPE_ONLY = true(hardcoded). No numeric HDF5 attributes are created. -
Locking:
HDF5 API calls are guarded byH5WriteLock(a privateobject). Progress updates use_updateProgressLock.
4. Dependencies
Imports/Usings:
HDF.PInvoke— P/Invoke wrapper for HDF5 C library.System.Runtime.InteropServices— ForMarshal.AllocHGlobal,FreeHGlobal,StringToHGlobalAnsi.DTS.Common.Enums.Sensors— ForSensorConstants.BridgeType.DTS.Common.Utilities.Logging— ForAPILogger.System.Collections.Generic,System.IO,System.Linq,System.Threading.Tasks— Standard .NET.
Internal Dependencies:
Serialization.File— Base class (inherited).IWriter<Test>— Interface implemented.Test— Core data model (fromDTS.Serializationor similar).Test.Module,Test.Module.AnalogInputChannel,FilteredData,DataScaler— Internal DTS types.BeginEventHandler,CancelEventHandler,EndEventHandler,TickEventHandler,ErrorEventHandler,CancelRequested— Delegates for progress/cancellation.
External Dependencies:
- HDF5 library (via
HDF.PInvoke). - File system access for reading logs, setup, reports, and
.dtsfiles.
5. Gotchas
-
ISOToTransducerMainLocationis unused:
TheFileclass exposes a setter forISOToTransducerMainLocation, and theWriterclass declares a corresponding property, but the property is never referenced in the code. This is likely dead code. -
Initializemethod is empty:
TheWriter.Initialize(...)method has no implementation. All work is done inWrite(...). This may violate expectations of a two-phase initialization pattern. -
String-only attributes:
All numeric attributes (int, double, ulong) are stored as strings due toATTRIBUTE_STRING_DATATYPE_ONLY = true. This increases file size and complicates downstream parsing. -
Nested
DirectoryInfo.Parentchecks:
TheAddDirectoryIfExistsmethod uses a brittle chain ofParent.Parent.Parentto determine the root directory. This assumes a fixed directory structure and may fail if the path depth is insufficient. -
Parallel channel processing:
Channels are processed in parallel (Parallel.ForEach), but progress updates are not thread-safe beyond the_updateProgressLock. Steps completed (stepsCompleted) is incremented outside the lock, risking race conditions and incorrect progress reporting. -
Hardcoded dataset names:
All channel datasets are named{index}: Strain_RawYData, regardless of data type (ADC/mV/EU). This may cause confusion or overwriting if multiple dataset groups exist. -
No cancellation support in
Write:
AlthoughcancelRequestedis passed toWrite, it is never checked. The export runs to completion regardless of cancellation. -
Error handling is lossy:
CheckStatusthrows a genericExceptionwith only the location name (e.g.,"File"), losing the underlying HDF5 error code or message. Detailed diagnostics rely onAPILogger.Logcalls. -
Memory allocation per sample:
Data is written sample-by-sample usingMarshal.WriteBytein loops. This is inefficient compared to bulk copy (e.g.,Marshal.Copy). The comment references performance fixes, but the implementation remains suboptimal. -
No validation of
ISOTo*dictionaries:
AccessingISOToFineLocation3[aic.IsoCode]without checking for key existence will throwKeyNotFoundExceptionif the dictionary is incomplete or keys are missing. -
minStartTimeanddataCollectionLengthare unused:
These parameters appear inWritesignatures but are never used in the implementation. -
ExtensionPrefixis settable but unused:
TheExtensionPrefixproperty is defined but not used in filename construction ({id}_{LabName}_1of1{(ExtensionPrefix ?? "")}.h5), so it only affects the filename if explicitly set to a non-empty value. -
No support for digital or calculated channels:
Parallel.ForEachskips non-AnalogInputChannelinstances (if (null == aic) return;). Digital channels, calculated channels, or other channel types are silently ignored. -
Time handling assumptions:
Reference Timeis computed fromTriggerTimestampSecandTriggerTimestampNanoSec, assuming Unix epoch. No timezone or leap-second handling is evident. -
Hardcoded export version:
HDF_EXPORT_VERSION = 7.0Dis hardcoded. No version negotiation or schema evolution is apparent.