986 lines
53 KiB
C#
986 lines
53 KiB
C#
|
|
/*
|
|||
|
|
* HDF.File.Writer.cs
|
|||
|
|
*
|
|||
|
|
* Copyright © 2017
|
|||
|
|
* Diversified Technical Systems, Inc.
|
|||
|
|
* All Rights Reserved
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.IO;
|
|||
|
|
using System.Linq;
|
|||
|
|
using System.Runtime.InteropServices;
|
|||
|
|
using System.Threading.Tasks;
|
|||
|
|
using DTS.Common.Enums.Sensors;
|
|||
|
|
using DTS.Common.Utilities.Logging;
|
|||
|
|
using HDF.PInvoke;
|
|||
|
|
|
|||
|
|
namespace DTS.Serialization.HDF
|
|||
|
|
{
|
|||
|
|
public partial class File
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// implementation of the Serialization.File.Writer class for HDF5
|
|||
|
|
/// https://en.wikipedia.org/wiki/Hierarchical_Data_Format
|
|||
|
|
/// http://fogbugz/fogbugz/default.asp?9166
|
|||
|
|
/// </summary>
|
|||
|
|
public class Writer : Writer<File>, IWriter<Test>
|
|||
|
|
{
|
|||
|
|
#region properties
|
|||
|
|
/// <summary>
|
|||
|
|
/// the owning file that controls this writer
|
|||
|
|
/// </summary>
|
|||
|
|
internal File WriterParent { get; private set; }
|
|||
|
|
/// <summary>
|
|||
|
|
/// controls whether to export ADC or not
|
|||
|
|
/// </summary>
|
|||
|
|
public bool ExportADC { get; set; }
|
|||
|
|
/// <summary>
|
|||
|
|
/// controls whether to export EU or not
|
|||
|
|
/// </summary>
|
|||
|
|
public bool ExportEU { get; set; }
|
|||
|
|
/// <summary>
|
|||
|
|
/// controls whether to export MV or not
|
|||
|
|
/// </summary>
|
|||
|
|
public bool ExportMV { get; set; }
|
|||
|
|
/// <summary>
|
|||
|
|
/// controls whether to export logs or not
|
|||
|
|
/// </summary>
|
|||
|
|
public bool ExportLogs { get; set; }
|
|||
|
|
/// <summary>
|
|||
|
|
/// controls whether to export reports or not
|
|||
|
|
/// </summary>
|
|||
|
|
public bool ExportReports { get; set; }
|
|||
|
|
/// <summary>
|
|||
|
|
/// controls whether to export setups or not
|
|||
|
|
/// </summary>
|
|||
|
|
public bool ExportSetup { get; set; }
|
|||
|
|
|
|||
|
|
public bool ExportDTSFile { get; set; }
|
|||
|
|
|
|||
|
|
public string CustomerName { get; set; }
|
|||
|
|
|
|||
|
|
public string TestEngineerName { get; set; }
|
|||
|
|
public string LabName { get; set; }
|
|||
|
|
public bool IsWiamanData { get; set; }
|
|||
|
|
public Dictionary<string, string> ISOToFineLocation3 { get; set; }
|
|||
|
|
public Dictionary<string, string> ISOToPhysicalDimension { get; set; }
|
|||
|
|
public Dictionary<string, string> ISOToPosition { get; set; }
|
|||
|
|
public Dictionary<string, string> ISOToTransducerMainLocation { get; set; }
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region enums and constants
|
|||
|
|
/// <summary>
|
|||
|
|
/// common locations where we can fail an HDF interface call
|
|||
|
|
/// </summary>
|
|||
|
|
public enum ErrorLocation
|
|||
|
|
{
|
|||
|
|
File,
|
|||
|
|
Group,
|
|||
|
|
SubGroup,
|
|||
|
|
DataSpace,
|
|||
|
|
DataSet,
|
|||
|
|
Write
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// every 1000 samples update progress
|
|||
|
|
/// </summary>
|
|||
|
|
private const int UPDATE_INTERVAL = 1000;
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region methods
|
|||
|
|
/// <summary>
|
|||
|
|
/// writes out test to given path
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="pathname"></param>
|
|||
|
|
/// <param name="id"></param>
|
|||
|
|
/// <param name="test"></param>
|
|||
|
|
/// <param name="bFiltering"></param>
|
|||
|
|
/// <param name="includeGroupNameInISOExport"></param>
|
|||
|
|
public void Write(string pathname, string id, Test test, bool bFiltering, bool includeGroupNameInISOExport, double minStartTime, int dataCollectionLength)
|
|||
|
|
{
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// returns a datascaler for the given channel
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="currentAnalogChannel"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
private Common.DAS.Concepts.DataScaler GetDataScaler(Test.Module.AnalogInputChannel currentAnalogChannel)
|
|||
|
|
{
|
|||
|
|
var scaler = new Common.DAS.Concepts.DataScaler
|
|||
|
|
{
|
|||
|
|
IsInverted = currentAnalogChannel.IsInverted,
|
|||
|
|
IEPE = currentAnalogChannel.Bridge == SensorConstants.BridgeType.IEPE,
|
|||
|
|
UnitConversion = currentAnalogChannel.UnitConversion,
|
|||
|
|
BasedOnOutputAtCapacity = currentAnalogChannel.AtCapacity,
|
|||
|
|
CapacityOutputIsBasedOn = currentAnalogChannel.CapacityOutputIsBasedOn,
|
|||
|
|
SensitivityUnits = currentAnalogChannel.SensitivityUnits,
|
|||
|
|
Multiplier = currentAnalogChannel.Multiplier,
|
|||
|
|
UserOffsetEU = currentAnalogChannel.UserOffsetEU
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
scaler.SetLinearizationFormula(currentAnalogChannel.LinearizationFormula);
|
|||
|
|
scaler.SetScaleFactorMv(currentAnalogChannel.Data.ScaleFactorMv);
|
|||
|
|
scaler.SetScaleFactorEU(currentAnalogChannel.Data.ScaleFactorEU);
|
|||
|
|
scaler.SetUseEUScaleFactors(currentAnalogChannel.Data.UseEUScaleFactors);
|
|||
|
|
scaler.SetMvPerEu(currentAnalogChannel.Data.MvPerEu);
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
scaler.SetInitialOffset(currentAnalogChannel.InitialOffset);
|
|||
|
|
scaler.ZeroMethodType = currentAnalogChannel.ZeroMethod;
|
|||
|
|
scaler.SetRemovedADC(currentAnalogChannel.RemovedADC);
|
|||
|
|
scaler.SetRemovedInternalADC(currentAnalogChannel.RemovedInternalADC);
|
|||
|
|
scaler.SetDataZeroLevelADC(currentAnalogChannel.DataZeroLevelAdc);
|
|||
|
|
scaler.SetZeroMvInADC(currentAnalogChannel.ZeroMvInADC);
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
//note the window average is the average over time when the average is not in your dataset
|
|||
|
|
//sliceware is the only software that sets this currently
|
|||
|
|
scaler.SetWindowAverageADC(currentAnalogChannel.WindowAverageADC);
|
|||
|
|
}
|
|||
|
|
catch (System.Exception ex)
|
|||
|
|
{
|
|||
|
|
APILogger.Log("WindowAverageADC failed to set", ex);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (System.Exception ex)
|
|||
|
|
{
|
|||
|
|
APILogger.Log("Failed to set parameters on scaler", ex);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
scaler.NominalExcitationVoltage = currentAnalogChannel.ExcitationVoltage;
|
|||
|
|
if (currentAnalogChannel.MeasuredExcitationVoltageValid)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
scaler.MeasuredExcitationVoltage = currentAnalogChannel.MeasuredExcitationVoltage;
|
|||
|
|
}
|
|||
|
|
catch (System.Exception ex)
|
|||
|
|
{
|
|||
|
|
APILogger.Log("failed to get measured excitation voltage", ex);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (currentAnalogChannel.FactoryExcitationVoltageValid)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
scaler.FactoryExcitationVoltage = currentAnalogChannel.FactoryExcitationVoltage;
|
|||
|
|
}
|
|||
|
|
catch (System.Exception ex)
|
|||
|
|
{
|
|||
|
|
APILogger.Log("failed to get factory excitation", ex);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
scaler.ProportionalToExcitation = currentAnalogChannel.ProportionalToExcitation;
|
|||
|
|
return scaler;
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// checks the API return status and throws an exception if the status is not successful
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="status"></param>
|
|||
|
|
/// <param name="location"></param>
|
|||
|
|
// ReSharper disable once UnusedParameter.Local
|
|||
|
|
private void CheckStatus(long status, ErrorLocation location)
|
|||
|
|
{
|
|||
|
|
if (status < 0)
|
|||
|
|
{
|
|||
|
|
throw new System.Exception(location.ToString());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private const bool ATTRIBUTE_STRING_DATATYPE_ONLY = true;
|
|||
|
|
|
|||
|
|
private object H5WriteLock = new object();
|
|||
|
|
/// <summary>
|
|||
|
|
/// creates a string attribute attached to the given location
|
|||
|
|
/// returns false if it failed
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="objectId">object to attach attributes to</param>
|
|||
|
|
/// <param name="attributeName">attribute name</param>
|
|||
|
|
/// <param name="attributeValue">attribute value</param>
|
|||
|
|
/// <returns>success or failure</returns>
|
|||
|
|
private void CreateStringAttribute(long objectId, string attributeName, string attributeValue)
|
|||
|
|
{
|
|||
|
|
if (string.IsNullOrWhiteSpace(attributeName))
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (string.IsNullOrWhiteSpace(attributeValue))
|
|||
|
|
{
|
|||
|
|
attributeValue = string.Empty;
|
|||
|
|
}
|
|||
|
|
long attributeSpace = 0;
|
|||
|
|
long stringId = 0;
|
|||
|
|
long attributeId = 0;
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
long result;
|
|||
|
|
IntPtr stringToHGlobalAnsi = new IntPtr();
|
|||
|
|
lock (H5WriteLock)
|
|||
|
|
{
|
|||
|
|
attributeSpace = H5S.create(H5S.class_t.SCALAR);
|
|||
|
|
stringId = H5T.copy(H5T.C_S1);
|
|||
|
|
H5T.set_size(stringId, new IntPtr(attributeValue.Length));
|
|||
|
|
attributeId = H5A.create(objectId, attributeName, stringId, attributeSpace);
|
|||
|
|
|
|||
|
|
stringToHGlobalAnsi = Marshal.StringToHGlobalAnsi(attributeValue);
|
|||
|
|
|
|||
|
|
|
|||
|
|
result = H5A.write(attributeId, stringId, stringToHGlobalAnsi);
|
|||
|
|
}
|
|||
|
|
Marshal.FreeHGlobal(stringToHGlobalAnsi);
|
|||
|
|
CheckStatus(result, ErrorLocation.Write);
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
APILogger.Log("failed to write string attribute:", attributeName, attributeValue, ex);
|
|||
|
|
}
|
|||
|
|
finally
|
|||
|
|
{
|
|||
|
|
if (attributeId != 0) H5A.close(attributeId);
|
|||
|
|
if (stringId != 0) H5T.close(stringId);
|
|||
|
|
if (attributeSpace != 0) H5S.close(attributeSpace);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// creates an integer attribute attached to the given location
|
|||
|
|
/// returns false if failed
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="objectId"></param>
|
|||
|
|
/// <param name="title"></param>
|
|||
|
|
/// <param name="value"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
private void CreateIntAttribute(long objectId, string title, int value)
|
|||
|
|
{
|
|||
|
|
if (ATTRIBUTE_STRING_DATATYPE_ONLY)
|
|||
|
|
{
|
|||
|
|
CreateStringAttribute(objectId, title, value.ToString());
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Creates a ulong attribute attached to the given location
|
|||
|
|
/// returns false if fails
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="objectId"></param>
|
|||
|
|
/// <param name="title"></param>
|
|||
|
|
/// <param name="value"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
private void CreateUlongAttribute(long objectId, string title, ulong value)
|
|||
|
|
{
|
|||
|
|
if (ATTRIBUTE_STRING_DATATYPE_ONLY)
|
|||
|
|
{
|
|||
|
|
CreateStringAttribute(objectId, title, value.ToString());
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// creates a double attribute attached to the given location
|
|||
|
|
/// returns false if fails
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="objectId"></param>
|
|||
|
|
/// <param name="title"></param>
|
|||
|
|
/// <param name="value"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
private void CreateDoubleAttribute(long objectId, string title, double value)
|
|||
|
|
{
|
|||
|
|
if (ATTRIBUTE_STRING_DATATYPE_ONLY)
|
|||
|
|
{
|
|||
|
|
CreateStringAttribute(objectId, title, value.ToString());
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// includes all files in the directory (if it exists) in the HDF
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="binaryPath">source path for files</param>
|
|||
|
|
/// <param name="folder">name of the folder</param>
|
|||
|
|
/// <param name="hdfObjectId">HDF object to attach folder to</param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
private void AddDirectoryIfExists(string binaryPath, string folder, long hdfObjectId, string fileExtension)
|
|||
|
|
{
|
|||
|
|
var directoryInfo = new DirectoryInfo(binaryPath);
|
|||
|
|
if (directoryInfo.Parent != null)
|
|||
|
|
{
|
|||
|
|
if (directoryInfo.Parent.Parent != null)
|
|||
|
|
{
|
|||
|
|
if (directoryInfo.Parent.Parent.Parent != null)
|
|||
|
|
{
|
|||
|
|
var rootDirectory = directoryInfo.Parent.Parent.Parent.FullName;
|
|||
|
|
|
|||
|
|
var sourceDirectory = Path.Combine(rootDirectory, folder);
|
|||
|
|
if (!Directory.Exists(sourceDirectory))
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
var files = Directory.GetFiles(sourceDirectory, fileExtension);
|
|||
|
|
if (!files.Any())
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
//create group
|
|||
|
|
var key = $"/Files/{folder}";
|
|||
|
|
var subgroup = H5G.create(hdfObjectId, key);
|
|||
|
|
|
|||
|
|
foreach (var sFile in files)
|
|||
|
|
{
|
|||
|
|
var fi = new FileInfo(sFile);
|
|||
|
|
var bytes = System.IO.File.ReadAllBytes(sFile);
|
|||
|
|
|
|||
|
|
var dataspace = H5S.create_simple(1, new[] { Convert.ToUInt64(bytes.Length) }, null);
|
|||
|
|
|
|||
|
|
var dataset = H5D.create(subgroup, $"{key}/{fi.Name}",
|
|||
|
|
H5T.NATIVE_UCHAR, dataspace);
|
|||
|
|
|
|||
|
|
var intPtr = Marshal.AllocHGlobal(bytes.Length);
|
|||
|
|
|
|||
|
|
for (var i = 0; i < bytes.Length; i++)
|
|||
|
|
{
|
|||
|
|
Marshal.WriteByte(intPtr, i, bytes[i]);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var mid1 = H5S.create_simple(1, new[] { Convert.ToUInt64(bytes.Length) }, null);
|
|||
|
|
H5D.write(dataset, H5T.NATIVE_UCHAR, mid1, dataspace,
|
|||
|
|
H5P.DEFAULT, intPtr);
|
|||
|
|
|
|||
|
|
Marshal.FreeHGlobal(intPtr);
|
|||
|
|
H5D.close(dataset);
|
|||
|
|
H5S.close(mid1);
|
|||
|
|
H5S.close(dataspace);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
H5G.close(subgroup);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private object _updateProgressLock = new object();
|
|||
|
|
private double _curProg = 0;
|
|||
|
|
/// <summary>
|
|||
|
|
/// updates the progress if possible
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="dValue"></param>
|
|||
|
|
/// <param name="tickEventHandler"></param>
|
|||
|
|
private void UpdateProgress(double dValue, TickEventHandler tickEventHandler)
|
|||
|
|
{
|
|||
|
|
if (dValue <= _curProg) { return; }
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
_curProg = dValue;
|
|||
|
|
}
|
|||
|
|
lock (_updateProgressLock)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
tickEventHandler?.Invoke(this, _curProg);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// returns the total number of steps in the export
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="test"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
private int ComputeNumberOfSteps(Test test)
|
|||
|
|
{
|
|||
|
|
var totalSteps = 0;
|
|||
|
|
if (ExportEU)
|
|||
|
|
{
|
|||
|
|
totalSteps += test.Channels.Count;
|
|||
|
|
}
|
|||
|
|
if (ExportADC)
|
|||
|
|
{
|
|||
|
|
totalSteps += test.Channels.Count;
|
|||
|
|
}
|
|||
|
|
if (ExportMV)
|
|||
|
|
{
|
|||
|
|
totalSteps += test.Channels.Count;
|
|||
|
|
}
|
|||
|
|
if (ExportLogs)
|
|||
|
|
{
|
|||
|
|
totalSteps++;
|
|||
|
|
}
|
|||
|
|
if (ExportSetup)
|
|||
|
|
{
|
|||
|
|
totalSteps++;
|
|||
|
|
}
|
|||
|
|
if (ExportReports)
|
|||
|
|
{
|
|||
|
|
totalSteps++;
|
|||
|
|
}
|
|||
|
|
if (ExportDTSFile)
|
|||
|
|
{
|
|||
|
|
totalSteps++;
|
|||
|
|
}
|
|||
|
|
return totalSteps;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
private const string EU_DATASET_GROUP_NAME = "/Datasets_EU";
|
|||
|
|
private const string ADC_DATASET_GROUP_NAME = "/Datasets";
|
|||
|
|
private const string MV_DATASET_GROUP_NAME = "/Datasets_MV";
|
|||
|
|
public string ExtensionPrefix { get; set; } = string.Empty;
|
|||
|
|
/// <summary>
|
|||
|
|
/// writes out test to given path
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="pathname"></param>
|
|||
|
|
/// <param name="id"></param>
|
|||
|
|
/// <param name="dataFolder"></param>
|
|||
|
|
/// <param name="test"></param>
|
|||
|
|
/// <param name="bFiltering"></param>
|
|||
|
|
/// <param name="includeGroupNameInISOExport"></param>
|
|||
|
|
/// <param name="fd"></param>
|
|||
|
|
/// <param name="tmChannel"></param>
|
|||
|
|
/// <param name="channelNumber"></param>
|
|||
|
|
/// <param name="beginEventHandler"></param>
|
|||
|
|
/// <param name="cancelEventHandler"></param>
|
|||
|
|
/// <param name="endEventHandler"></param>
|
|||
|
|
/// <param name="tickEventHandler"></param>
|
|||
|
|
/// <param name="errorEventHandler"></param>
|
|||
|
|
/// <param name="cancelRequested"></param>
|
|||
|
|
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)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
beginEventHandler?.Invoke(this, 100);
|
|||
|
|
|
|||
|
|
var filename = Path.Combine(pathname, $"{id}_{LabName}_1of1{(ExtensionPrefix ?? "")}.h5");
|
|||
|
|
var fileInfo = new FileInfo(filename);
|
|||
|
|
if (!System.IO.Directory.Exists(fileInfo.DirectoryName))
|
|||
|
|
{
|
|||
|
|
System.IO.Directory.CreateDirectory(fileInfo.DirectoryName);
|
|||
|
|
}
|
|||
|
|
var fileid = H5F.create(fileInfo.FullName, H5F.ACC_TRUNC);
|
|||
|
|
CheckStatus(fileid, ErrorLocation.File);
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
var totalSteps = ComputeNumberOfSteps(test);
|
|||
|
|
var stepsCompleted = 0D;
|
|||
|
|
_curProg = 0D;
|
|||
|
|
|
|||
|
|
|
|||
|
|
//include binary files if requested
|
|||
|
|
var groupid2 = H5G.create(fileid, "/Files");
|
|||
|
|
CheckStatus(groupid2, ErrorLocation.Group);
|
|||
|
|
if (ExportLogs)
|
|||
|
|
{
|
|||
|
|
AddDirectoryIfExists(pathname, "Logs", fileid, "*.*");
|
|||
|
|
stepsCompleted++;
|
|||
|
|
UpdateProgress(100D * stepsCompleted / totalSteps, tickEventHandler);
|
|||
|
|
}
|
|||
|
|
if (ExportSetup)
|
|||
|
|
{
|
|||
|
|
AddDirectoryIfExists(pathname, "SETUP", fileid, "*.*");
|
|||
|
|
stepsCompleted++;
|
|||
|
|
UpdateProgress(100D * stepsCompleted / totalSteps, tickEventHandler);
|
|||
|
|
}
|
|||
|
|
if (ExportReports)
|
|||
|
|
{
|
|||
|
|
AddDirectoryIfExists(pathname, "Reports", fileid, "*.*");
|
|||
|
|
stepsCompleted++;
|
|||
|
|
UpdateProgress(100D * stepsCompleted / totalSteps, tickEventHandler);
|
|||
|
|
}
|
|||
|
|
if (ExportDTSFile)
|
|||
|
|
{
|
|||
|
|
var dataDir = Path.GetFileName(dataFolder);
|
|||
|
|
AddDirectoryIfExists(pathname, string.Concat("Binary\\", dataDir), fileid, "*.dts");
|
|||
|
|
stepsCompleted++;
|
|||
|
|
UpdateProgress(100D * stepsCompleted / totalSteps, tickEventHandler);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!ExportEU && !ExportADC && !ExportMV) return;
|
|||
|
|
|
|||
|
|
if (ExportEU)
|
|||
|
|
{
|
|||
|
|
CreateDataset(fileid, HDF_DATASET_TYPE.EU, test, ref stepsCompleted, totalSteps, tickEventHandler, id);
|
|||
|
|
}
|
|||
|
|
if (ExportADC)
|
|||
|
|
{
|
|||
|
|
CreateDataset(fileid, HDF_DATASET_TYPE.ADC, test, ref stepsCompleted, totalSteps, tickEventHandler, id);
|
|||
|
|
}
|
|||
|
|
if (ExportMV)
|
|||
|
|
{
|
|||
|
|
CreateDataset(fileid, HDF_DATASET_TYPE.MV, test, ref stepsCompleted, totalSteps, tickEventHandler, id);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
H5G.close(groupid2);
|
|||
|
|
H5F.close(fileid);
|
|||
|
|
}
|
|||
|
|
catch (System.Exception ex)
|
|||
|
|
{
|
|||
|
|
APILogger.Log("encountered problem writing HDF test files", ex);
|
|||
|
|
errorEventHandler?.Invoke(this, ex);
|
|||
|
|
}
|
|||
|
|
finally
|
|||
|
|
{
|
|||
|
|
tickEventHandler?.Invoke(this, 100D);
|
|||
|
|
endEventHandler?.Invoke(this);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private enum HDF_DATASET_TYPE
|
|||
|
|
{
|
|||
|
|
EU,
|
|||
|
|
ADC,
|
|||
|
|
MV
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static string GetDataSetName(HDF_DATASET_TYPE datasetType)
|
|||
|
|
{
|
|||
|
|
switch (datasetType)
|
|||
|
|
{
|
|||
|
|
case HDF_DATASET_TYPE.ADC:
|
|||
|
|
return ADC_DATASET_GROUP_NAME;
|
|||
|
|
case HDF_DATASET_TYPE.MV:
|
|||
|
|
return MV_DATASET_GROUP_NAME;
|
|||
|
|
default:
|
|||
|
|
//case HDF_DATASET_TYPE.EU:
|
|||
|
|
return EU_DATASET_GROUP_NAME;
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private const double HDF_EXPORT_VERSION = 7.0D;
|
|||
|
|
|
|||
|
|
private void CreateDataset(long fileid, HDF_DATASET_TYPE datasetType,
|
|||
|
|
Test test, ref double stepsCompletedRef, int totalSteps, TickEventHandler tickEventHandler,
|
|||
|
|
string testID)
|
|||
|
|
{
|
|||
|
|
var stepsCompleted = stepsCompletedRef;
|
|||
|
|
var datasetGroupName = GetDataSetName(datasetType);
|
|||
|
|
var groupid = H5G.create(fileid, datasetGroupName);
|
|||
|
|
CheckStatus(groupid, ErrorLocation.Group);
|
|||
|
|
|
|||
|
|
//include test level attributes
|
|||
|
|
CreateStringAttribute(groupid, "TestName", test.Id);
|
|||
|
|
CreateStringAttribute(groupid, "Description", test.Description);
|
|||
|
|
CreateStringAttribute(groupid, "TestID", testID);
|
|||
|
|
CreateStringAttribute(groupid, "SoftwareVersion", test.SoftwareVersion);
|
|||
|
|
CreateDoubleAttribute(groupid, "HDFExportVersion", HDF_EXPORT_VERSION);
|
|||
|
|
CreateIntAttribute(groupid, "FaultFlag", Convert.ToInt32(test.FaultFlags));
|
|||
|
|
CreateIntAttribute(groupid, "ExtendedFaultFlag1", Convert.ToInt32(test.ExtendedFaultFlags1));
|
|||
|
|
CreateIntAttribute(groupid, "ExtendedFaultFlag2", Convert.ToInt32(test.ExtendedFaultFlags2));
|
|||
|
|
CreateIntAttribute(groupid, "ExtendedFaultFlag3", Convert.ToInt32(test.ExtendedFaultFlags3));
|
|||
|
|
CreateIntAttribute(groupid, "ExtendedFaultFlag4", Convert.ToInt32(test.ExtendedFaultFlags4));
|
|||
|
|
|
|||
|
|
var machineName = Environment.MachineName;
|
|||
|
|
//these are all variables that will be used below as we go through channels
|
|||
|
|
//we declare them out here to just avoid the creation/cleanup overhead
|
|||
|
|
|
|||
|
|
|
|||
|
|
test.Channels.Sort((a, b) => { return a.AbsoluteDisplayOrder.CompareTo(b.AbsoluteDisplayOrder); });
|
|||
|
|
//go through all the channels, and include whatever data is requested
|
|||
|
|
//http://manuscript.dts.local/f/cases/16463/HDF-export-runs-very-slowly
|
|||
|
|
// now runs through list in parallel
|
|||
|
|
Parallel.ForEach(test.Channels, testChannel =>
|
|||
|
|
{
|
|||
|
|
int length, offset;
|
|||
|
|
int status;
|
|||
|
|
short iTemp;
|
|||
|
|
IntPtr intPtr;
|
|||
|
|
byte[] bytes;
|
|||
|
|
var aic = testChannel as Test.Module.AnalogInputChannel;
|
|||
|
|
double dTemp;
|
|||
|
|
long mid1, dataspace, subgroup, dataset;
|
|||
|
|
//for now ignore the channel if it's not an analoginputchannel, this probably includes everything except maybe the calculated channels ...
|
|||
|
|
if (null == aic)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var ds = GetDataScaler(aic);
|
|||
|
|
|
|||
|
|
var channelName2 = aic.ChannelName2.Replace('/', '_');
|
|||
|
|
//this will be the root key for the channel data
|
|||
|
|
//the root key ends in the channel's name
|
|||
|
|
var key = string.Format("{2}/{1}: {0}", channelName2, (1 + aic.AbsoluteDisplayOrder).ToString("0000"), datasetGroupName);
|
|||
|
|
|
|||
|
|
subgroup = H5G.create(fileid, key);
|
|||
|
|
CheckStatus(subgroup, ErrorLocation.SubGroup);
|
|||
|
|
#region subgroup_Attributes
|
|||
|
|
var numOfSamples = aic.ParentModule.NumberOfSamples;
|
|||
|
|
CreateUlongAttribute(subgroup, "NumberOfSamples", numOfSamples);
|
|||
|
|
var aaFilterRateHz = aic.ParentModule.AaFilterRateHz;
|
|||
|
|
CreateDoubleAttribute(subgroup, "AAFilterRateHz", aaFilterRateHz);
|
|||
|
|
var sampleRateHz = aic.ParentModule.SampleRateHz;
|
|||
|
|
CreateDoubleAttribute(subgroup, "SampleRateHz", sampleRateHz);
|
|||
|
|
CreateDoubleAttribute(subgroup, "RequestedPreTriggerSeconds",
|
|||
|
|
aic.ParentModule.RequestedPreTriggerSeconds);
|
|||
|
|
CreateDoubleAttribute(subgroup, "RequestedPostTriggerSeconds",
|
|||
|
|
aic.ParentModule.RequestedPostTriggerSeconds);
|
|||
|
|
CreateStringAttribute(subgroup, "RecordingMode", aic.ParentModule.RecordingMode.ToString());
|
|||
|
|
CreateDoubleAttribute(subgroup, "PreTriggerSeconds", aic.ParentModule.PreTriggerSeconds);
|
|||
|
|
CreateDoubleAttribute(subgroup, "PostTriggerSeconds", aic.ParentModule.PostTriggerSeconds);
|
|||
|
|
CreateUlongAttribute(subgroup, "StartRecordSampleNumber",
|
|||
|
|
aic.ParentModule.StartRecordSampleNumber);
|
|||
|
|
CreateStringAttribute(subgroup, "Bridge", aic.Bridge.ToString());
|
|||
|
|
CreateDoubleAttribute(subgroup, "BridgeResistanceOhms", aic.BridgeResistanceOhms);
|
|||
|
|
CreateStringAttribute(subgroup, "ChannelDescription", aic.ChannelDescriptionString);
|
|||
|
|
CreateStringAttribute(subgroup, "ChannelName", channelName2);
|
|||
|
|
CreateStringAttribute(subgroup, "SerialNumber", aic.SerialNumber);
|
|||
|
|
CreateStringAttribute(subgroup, "HardwareChannel", aic.HardwareChannelName);
|
|||
|
|
CreateDoubleAttribute(subgroup, "DesiredRange", aic.DesiredRange);
|
|||
|
|
CreateDoubleAttribute(subgroup, "Sensitivity", aic.Sensitivity);
|
|||
|
|
CreateStringAttribute(subgroup, "SoftwareFilter", aic.SoftwareFilter);
|
|||
|
|
CreateIntAttribute(subgroup, "ProportionalToExcitation", aic.ProportionalToExcitation ? 1 : 0);
|
|||
|
|
CreateIntAttribute(subgroup, "IsInverted", aic.IsInverted ? 1 : 0);
|
|||
|
|
CreateStringAttribute(subgroup, "AbsoluteDisplayOrder", aic.AbsoluteDisplayOrder.ToString("0000"));
|
|||
|
|
var lastCalibrationDate = aic.LastCalibrationDate.ToShortDateString();
|
|||
|
|
CreateStringAttribute(subgroup, "LastCalibrationDate", lastCalibrationDate);
|
|||
|
|
//CreateStringAttribute(subgroup, "SensorId", aic.SensorID);
|
|||
|
|
CreateStringAttribute(subgroup, "ExcitationVoltage", aic.ExcitationVoltage.ToString());
|
|||
|
|
var factoryExcitationVoltage = aic.FactoryExcitationVoltage;
|
|||
|
|
CreateDoubleAttribute(subgroup, "FactoryExcitationVoltage", factoryExcitationVoltage);
|
|||
|
|
CreateDoubleAttribute(subgroup, "MeasuredExcitationVoltage", aic.MeasuredExcitationVoltage);
|
|||
|
|
var engineeringUnits = aic.EngineeringUnits.TrimEnd(' ');
|
|||
|
|
CreateStringAttribute(subgroup, "EngineeringUnits", engineeringUnits);
|
|||
|
|
CreateDoubleAttribute(subgroup, "TimeOfSampleZeroSeconds", aic.TimeOfFirstSampleSec);
|
|||
|
|
var triggerSampleNumber = aic.ParentModule.TriggerSampleNumbers[0];
|
|||
|
|
CreateDoubleAttribute(subgroup, "TriggerSampleNumber", triggerSampleNumber);
|
|||
|
|
var dStartTime = (aic.ParentModule.StartRecordSampleNumber / (double)aic.ParentModule.SampleRateHz) * 1000D;
|
|||
|
|
if (aic.ParentModule.TriggerSampleNumbers.Count > 0)
|
|||
|
|
{
|
|||
|
|
dStartTime -= (aic.ParentModule.TriggerSampleNumbers[0] / (double)aic.ParentModule.SampleRateHz) * 1000D;
|
|||
|
|
}
|
|||
|
|
CreateDoubleAttribute(subgroup, "TimeOfFirstSampleSeconds", dStartTime);
|
|||
|
|
var scaleFactorMv = ds.GetScaleFactorMv();
|
|||
|
|
CreateDoubleAttribute(subgroup, "ScaleFactorMv", scaleFactorMv);
|
|||
|
|
var scaleFactorADC = ds.GetAdcToEuScalingFactor();
|
|||
|
|
CreateDoubleAttribute(subgroup, "ScaleFactorADC", scaleFactorADC);
|
|||
|
|
var offsetADC = ds.GetDataZeroLevelADC();
|
|||
|
|
CreateDoubleAttribute(subgroup, "DataZeroLevelADC", offsetADC);
|
|||
|
|
|
|||
|
|
|
|||
|
|
#region WIAMan Attributes
|
|||
|
|
//Begin Time Required Negative milliseconds from first data point to reference time (e.g. -500.0)
|
|||
|
|
//Data Count Required The number of data points in the dataset (e.g. 750001)
|
|||
|
|
//Description Required The name of the channel (e.g. "1:" or "Channel 1 - Head AX")
|
|||
|
|
//Reference Index Required The index of the data point of the trigger (e.g. 256000)
|
|||
|
|
//Reference Time Required The time of The data point at The reference index, in The format yyyy-MM-dd HH:mm:ss.SSSSSSSS (e.g. 2017-02-01 20:44:48.95126555)
|
|||
|
|
//Sampling Rate Required The sampling rate in kHz (e.g. 500.0)
|
|||
|
|
//Scale Factor Required The factor to convert between raw and engineering units (e.g. .00031397038667400326)
|
|||
|
|
//Scale Offset Required The offset for conversion between units (e.g. 0.0)
|
|||
|
|
//Type Required Must be set to BTSXPeriodicXScalableYDataset
|
|||
|
|
//X Description Required e.g. Time(ms)
|
|||
|
|
//Y Description Required e.g. Volts
|
|||
|
|
//X Engineering Units Required e.g. ms
|
|||
|
|
//Y Engineering Units Required e.g. Volts
|
|||
|
|
//Anthropomorphic Label Desired Serial number of the ATD
|
|||
|
|
//Calibration Excitation Desired (excitation used in calibrating transducer for that channel)
|
|||
|
|
//Cutoff Frequency Desired (the cutoff frequency set on this channel)
|
|||
|
|
//DAQ Serial Number Desired Serial number of the DAS
|
|||
|
|
//DSP Version Desired (firmware of DAS, used mainly for diagnostics)
|
|||
|
|
//Director Desired (meta data, Test Director in charge of test event)
|
|||
|
|
//End Time Desired (this can be calculated used end index and sampling rate and gps time)
|
|||
|
|
//Excitation Voltage Desired (used to calculate scale factor, not needed if scale factor is already a parameter)
|
|||
|
|
//GF/Sens. Desired (used to calculate scale factor, not needed if scale factor is already a parameter)
|
|||
|
|
//Gage Factor Units Desired (used to calculate scale factor, not needed if scale factor is already a parameter)
|
|||
|
|
//Gain Desired Total set gain (not calibrated gain) mainly for diagnostics, ScaleFactor should already have factored this in
|
|||
|
|
//Internal Trigger Level 0 Desired Mainly for diagnostics later if there is a problem
|
|||
|
|
//Location Desired (meta data, event location)
|
|||
|
|
//Master Trigger Desired Mainly for diagnostics later if there is a problem
|
|||
|
|
//Number of Datasets Desired (total channels collected in this H5 file)
|
|||
|
|
//Operator Desired (meta data, person who is sitting at the computer)
|
|||
|
|
//Round Desired Name of this current test
|
|||
|
|
//Slope Value 0 Desired Trigger Slope (Positive, Negative, Absolute) Mainly for diagnostics later if there is a problem
|
|||
|
|
//calibrationDate Desired Calibration date of the transducer (when was it calibrated)
|
|||
|
|
//calibrationFactor Desired Counts->voltage factor. Should be accounted for in ScaleFactor, here for diagnostics
|
|||
|
|
//pog Desired post gain (set value of post-gain, here for diagnostics)
|
|||
|
|
//prg Desired pre gain (set value of pre-gain, here for diagnostics)
|
|||
|
|
|
|||
|
|
CreateDoubleAttribute(subgroup, "Begin Time", aic.TimeOfFirstSampleSec * 1000.0D);
|
|||
|
|
CreateUlongAttribute(subgroup, "Data Count", numOfSamples);
|
|||
|
|
CreateStringAttribute(subgroup, "Description", $"{(1 + aic.AbsoluteDisplayOrder).ToString("0000")}:");
|
|||
|
|
CreateDoubleAttribute(subgroup, "Reference Index", Math.Abs(aic.ParentModule.RequestedPreTriggerSeconds * sampleRateHz));
|
|||
|
|
var refTime = new DateTime(1970, 1, 1).AddSeconds(aic.ParentModule.TriggerTimestampSec);
|
|||
|
|
refTime = refTime.AddMilliseconds((aic.ParentModule.TriggerTimestampNanoSec) / 1000000);
|
|||
|
|
CreateStringAttribute(subgroup, "Reference Time", refTime.ToString("yyyy-MM-dd HH:mm:ss.fff") + ((aic.ParentModule.TriggerTimestampNanoSec) % 1000000).ToString("000000"));
|
|||
|
|
CreateDoubleAttribute(subgroup, "Sampling Rate", sampleRateHz / 1000D);
|
|||
|
|
CreateDoubleAttribute(subgroup, "Scale Factor", scaleFactorADC);
|
|||
|
|
CreateDoubleAttribute(subgroup, "Scale Offset", offsetADC);
|
|||
|
|
CreateStringAttribute(subgroup, "Type", "BTSXPeriodicXScalableYDataset");
|
|||
|
|
CreateStringAttribute(subgroup, "X Description", "Time (ms)");
|
|||
|
|
CreateStringAttribute(subgroup, "Y Description", engineeringUnits);
|
|||
|
|
CreateStringAttribute(subgroup, "X Engineering Units", "ms");
|
|||
|
|
CreateStringAttribute(subgroup, "Y Engineering Units", engineeringUnits);
|
|||
|
|
CreateDoubleAttribute(subgroup, "Calibration Excitation", factoryExcitationVoltage);
|
|||
|
|
CreateDoubleAttribute(subgroup, "Cutoff Frequency", aaFilterRateHz);
|
|||
|
|
CreateStringAttribute(subgroup, "DAQ Serial Number", aic.ParentModule.SerialNumber);
|
|||
|
|
CreateStringAttribute(subgroup, "Round", testID);
|
|||
|
|
CreateStringAttribute(subgroup, "calibrationDate", lastCalibrationDate);
|
|||
|
|
CreateDoubleAttribute(subgroup, "calibrationFactor", scaleFactorMv);
|
|||
|
|
CreateStringAttribute(subgroup, "Anthropomorphic Label", $"{ISOToFineLocation3[aic.IsoCode]} SN {aic.ChannelGroupName}");
|
|||
|
|
CreateStringAttribute(subgroup, "Director", CustomerName);
|
|||
|
|
CreateStringAttribute(subgroup, "Operator", TestEngineerName);
|
|||
|
|
CreateStringAttribute(subgroup, "Location", LabName);
|
|||
|
|
CreateStringAttribute(subgroup, "ComputerName", machineName);
|
|||
|
|
CreateStringAttribute(subgroup, "Input Mode", "TRANSDUCER");
|
|||
|
|
CreateStringAttribute(subgroup, "Channel Label:Optional", $"{ISOToPosition[aic.IsoCode]}, {channelName2.Replace(" ", ", ")}");
|
|||
|
|
CreateStringAttribute(subgroup, "Channel Label:Modifier", "Anthropomorphic");
|
|||
|
|
CreateStringAttribute(subgroup, "Channel Label:Category", ISOToPhysicalDimension[aic.IsoCode]);
|
|||
|
|
CreateStringAttribute(subgroup, "Channel Label:Units", engineeringUnits);
|
|||
|
|
CreateStringAttribute(subgroup, "TI:Serial Number", aic.SerialNumber);
|
|||
|
|
CreateStringAttribute(subgroup, "TI:Manufacturer", aic.Manufacturer);
|
|||
|
|
CreateStringAttribute(subgroup, "TI:Model", aic.Model);
|
|||
|
|
CreateDoubleAttribute(subgroup, "Expected Peak Signal", aic.DesiredRange);
|
|||
|
|
CreateDoubleAttribute(subgroup, "GF/Sens.", aic.Sensitivity);
|
|||
|
|
CreateStringAttribute(subgroup, "Gage Factor Type", "Sensitivity");
|
|||
|
|
CreateStringAttribute(subgroup, "Gage Factor Units", string.Concat(engineeringUnits, "/mv"));
|
|||
|
|
CreateStringAttribute(subgroup, "Gage Calibration Due Date", aic.LastCalibrationDate.AddYears(1).ToString("yyyy-MM-dd HH:mm:ss.fff"));
|
|||
|
|
CreateDoubleAttribute(subgroup, "Gage Calibration Excitation", DTS.Common.DAS.Concepts.Test.Module.Channel.Sensor.GetExcitationVoltageMagnitudeFromEnum(aic.ExcitationVoltage));
|
|||
|
|
CreateStringAttribute(subgroup, "Is WIAMan Data", (IsWiamanData ? "TRUE" : "FALSE"));
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region S6Attributes
|
|||
|
|
Test.Module parentDbModule = null;
|
|||
|
|
if (aic.HardwareChannelName.Contains(":"))
|
|||
|
|
{
|
|||
|
|
var parentDBSN = aic.HardwareChannelName.Trim(new char[] { '[', ']' }).Split(':').FirstOrDefault();
|
|||
|
|
if (!string.IsNullOrEmpty(parentDBSN))
|
|||
|
|
{
|
|||
|
|
parentDbModule = test.Modules.Where(x => x.SerialNumber == parentDBSN).ToList().FirstOrDefault();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
CreateStringAttribute(subgroup, "SystemID", aic.ParentModule.SystemID);
|
|||
|
|
CreateStringAttribute(subgroup, "SystemLocation", aic.ParentModule.SystemLocation);
|
|||
|
|
CreateDoubleAttribute(subgroup, "TargetAxisX", aic.ParentModule.TargetAxisX);
|
|||
|
|
CreateDoubleAttribute(subgroup, "TargetAxisY", aic.ParentModule.TargetAxisY);
|
|||
|
|
CreateDoubleAttribute(subgroup, "TargetAxisZ", aic.ParentModule.TargetAxisZ);
|
|||
|
|
CreateDoubleAttribute(subgroup, "TiltSensorAxisXDegreesPre", aic.ParentModule.TiltSensorAxisXDegreesPre);
|
|||
|
|
CreateDoubleAttribute(subgroup, "TiltSensorAxisYDegreesPre", aic.ParentModule.TiltSensorAxisYDegreesPre);
|
|||
|
|
CreateDoubleAttribute(subgroup, "TiltSensorAxisZDegreesPre", aic.ParentModule.TiltSensorAxisZDegreesPre);
|
|||
|
|
CreateDoubleAttribute(subgroup, "TiltSensorAxisXDegreesPost", aic.ParentModule.TiltSensorAxisXDegreesPost);
|
|||
|
|
CreateDoubleAttribute(subgroup, "TiltSensorAxisYDegreesPost", aic.ParentModule.TiltSensorAxisYDegreesPost);
|
|||
|
|
CreateDoubleAttribute(subgroup, "TiltSensorAxisZDegreesPost", aic.ParentModule.TiltSensorAxisZDegreesPost);
|
|||
|
|
if (null != parentDbModule)
|
|||
|
|
{
|
|||
|
|
CreateDoubleAttribute(subgroup, "TemperatureLocation1Pre", parentDbModule.TemperatureLocation1Pre);
|
|||
|
|
CreateDoubleAttribute(subgroup, "TemperatureLocation2Pre", parentDbModule.TemperatureLocation2Pre);
|
|||
|
|
CreateDoubleAttribute(subgroup, "TemperatureLocation3Pre", parentDbModule.TemperatureLocation3Pre);
|
|||
|
|
CreateDoubleAttribute(subgroup, "TemperatureLocation4Pre", parentDbModule.TemperatureLocation4Pre);
|
|||
|
|
CreateDoubleAttribute(subgroup, "TemperatureLocation1Post", parentDbModule.TemperatureLocation1Post);
|
|||
|
|
CreateDoubleAttribute(subgroup, "TemperatureLocation2Post", parentDbModule.TemperatureLocation2Post);
|
|||
|
|
CreateDoubleAttribute(subgroup, "TemperatureLocation3Post", parentDbModule.TemperatureLocation3Post);
|
|||
|
|
CreateDoubleAttribute(subgroup, "TemperatureLocation4Post", parentDbModule.TemperatureLocation4Post);
|
|||
|
|
}
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
dataspace = H5S.create_simple(1, new[] { aic.ParentModule.NumberOfSamples },
|
|||
|
|
null);
|
|||
|
|
CheckStatus(dataspace, ErrorLocation.DataSpace);
|
|||
|
|
length = Convert.ToInt32(aic.ParentModule.NumberOfSamples);
|
|||
|
|
|
|||
|
|
int iSampleIdx;
|
|||
|
|
|
|||
|
|
//http://manuscript.dts.local/f/cases/16463/HDF-export-runs-very-slowly
|
|||
|
|
// Grab all the data from the HDD at once
|
|||
|
|
var allData = aic.PersistentChannelInfo.Data;
|
|||
|
|
|
|||
|
|
switch (datasetType)
|
|||
|
|
{
|
|||
|
|
case HDF_DATASET_TYPE.ADC:
|
|||
|
|
{
|
|||
|
|
dataset = H5D.create(subgroup, string.Format("{0}: Strain_RawYData", (1 + aic.AbsoluteDisplayOrder).ToString("0000")), H5T.NATIVE_SHORT,
|
|||
|
|
dataspace);
|
|||
|
|
CheckStatus(dataset, ErrorLocation.DataSet);
|
|||
|
|
intPtr = Marshal.AllocHGlobal(length * sizeof(Int16));
|
|||
|
|
offset = 0;
|
|||
|
|
for (iSampleIdx = 0; iSampleIdx < length; iSampleIdx++)
|
|||
|
|
{
|
|||
|
|
//since we are using 100 as our ticks in our update, so every UPDATE_INTERVAL update with the status
|
|||
|
|
if (0 == iSampleIdx % UPDATE_INTERVAL)
|
|||
|
|
{
|
|||
|
|
UpdateProgress(
|
|||
|
|
100D * (stepsCompleted + iSampleIdx / (double)length) / totalSteps,
|
|||
|
|
tickEventHandler);
|
|||
|
|
}
|
|||
|
|
iTemp = allData[iSampleIdx];
|
|||
|
|
bytes = BitConverter.GetBytes(iTemp);
|
|||
|
|
foreach (var b in bytes)
|
|||
|
|
{
|
|||
|
|
Marshal.WriteByte(intPtr, offset, b);
|
|||
|
|
offset++;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
mid1 = H5S.create_simple(1, new[] { aic.ParentModule.NumberOfSamples }, null);
|
|||
|
|
CheckStatus(mid1, ErrorLocation.DataSpace);
|
|||
|
|
status = H5D.write(dataset, H5T.NATIVE_SHORT, mid1, dataspace,
|
|||
|
|
H5P.DEFAULT, intPtr);
|
|||
|
|
CheckStatus(status, ErrorLocation.Write);
|
|||
|
|
|
|||
|
|
H5D.close(dataset);
|
|||
|
|
H5S.close(mid1);
|
|||
|
|
Marshal.FreeHGlobal(intPtr);
|
|||
|
|
stepsCompleted++;
|
|||
|
|
UpdateProgress(100D * stepsCompleted / totalSteps, tickEventHandler);
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case HDF_DATASET_TYPE.MV:
|
|||
|
|
{
|
|||
|
|
dataset = H5D.create(subgroup, string.Format("{0}: Strain_RawYData", (1 + aic.AbsoluteDisplayOrder).ToString("0000")), H5T.NATIVE_DOUBLE,
|
|||
|
|
dataspace);
|
|||
|
|
CheckStatus(dataset, ErrorLocation.DataSet);
|
|||
|
|
mid1 = H5S.create_simple(1, new[] { aic.ParentModule.NumberOfSamples }, null);
|
|||
|
|
CheckStatus(mid1, ErrorLocation.DataSpace);
|
|||
|
|
intPtr = Marshal.AllocHGlobal(length * sizeof(double));
|
|||
|
|
offset = 0;
|
|||
|
|
for (iSampleIdx = 0; iSampleIdx < length; iSampleIdx++)
|
|||
|
|
{
|
|||
|
|
if (0 == iSampleIdx % UPDATE_INTERVAL)
|
|||
|
|
{
|
|||
|
|
UpdateProgress(
|
|||
|
|
100D * (stepsCompleted + iSampleIdx / (double)length) / totalSteps,
|
|||
|
|
tickEventHandler);
|
|||
|
|
}
|
|||
|
|
dTemp = ds.GetMv(allData[iSampleIdx]);
|
|||
|
|
bytes = BitConverter.GetBytes(dTemp);
|
|||
|
|
foreach (var b in bytes)
|
|||
|
|
{
|
|||
|
|
Marshal.WriteByte(intPtr, offset, b);
|
|||
|
|
offset++;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
status = H5D.write(dataset, H5T.NATIVE_DOUBLE, mid1, dataspace,
|
|||
|
|
H5P.DEFAULT, intPtr);
|
|||
|
|
CheckStatus(status, ErrorLocation.Write);
|
|||
|
|
Marshal.FreeHGlobal(intPtr);
|
|||
|
|
H5D.close(dataset);
|
|||
|
|
H5S.close(mid1);
|
|||
|
|
stepsCompleted++;
|
|||
|
|
UpdateProgress(100D * stepsCompleted / totalSteps, tickEventHandler);
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case HDF_DATASET_TYPE.EU:
|
|||
|
|
{
|
|||
|
|
dataset = H5D.create(subgroup, string.Format("{0}: Strain_RawYData", (1 + aic.AbsoluteDisplayOrder).ToString("0000")), H5T.NATIVE_DOUBLE,
|
|||
|
|
dataspace);
|
|||
|
|
CheckStatus(dataset, ErrorLocation.DataSet);
|
|||
|
|
mid1 = H5S.create_simple(1, new[] { aic.ParentModule.NumberOfSamples }, null);
|
|||
|
|
CheckStatus(mid1, ErrorLocation.DataSpace);
|
|||
|
|
intPtr = Marshal.AllocHGlobal(length * sizeof(double));
|
|||
|
|
offset = 0;
|
|||
|
|
for (iSampleIdx = 0; iSampleIdx < length; iSampleIdx++)
|
|||
|
|
{
|
|||
|
|
if (0 == iSampleIdx % UPDATE_INTERVAL)
|
|||
|
|
{
|
|||
|
|
UpdateProgress(
|
|||
|
|
100D * (stepsCompleted + iSampleIdx / (double)length) / totalSteps,
|
|||
|
|
tickEventHandler);
|
|||
|
|
}
|
|||
|
|
dTemp = ds.GetEU(allData[iSampleIdx]);
|
|||
|
|
bytes = BitConverter.GetBytes(dTemp);
|
|||
|
|
foreach (var b in bytes)
|
|||
|
|
{
|
|||
|
|
Marshal.WriteByte(intPtr, offset, b);
|
|||
|
|
offset++;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
status = H5D.write(dataset, H5T.NATIVE_DOUBLE, mid1, dataspace,
|
|||
|
|
H5P.DEFAULT, intPtr);
|
|||
|
|
CheckStatus(status, ErrorLocation.Write);
|
|||
|
|
Marshal.FreeHGlobal(intPtr);
|
|||
|
|
H5D.close(dataset);
|
|||
|
|
H5S.close(mid1);
|
|||
|
|
stepsCompleted++;
|
|||
|
|
UpdateProgress(100D * stepsCompleted / totalSteps, tickEventHandler);
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
H5S.close(dataspace);
|
|||
|
|
H5G.close(subgroup);
|
|||
|
|
aic.PersistentChannelInfo.UnSet();
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
|
|||
|
|
H5G.close(groupid);
|
|||
|
|
}
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// constructs the writer with a given file and encoding
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="fileType"></param>
|
|||
|
|
/// <param name="encoding"></param>
|
|||
|
|
internal Writer(File fileType, int encoding)
|
|||
|
|
: base(fileType, encoding)
|
|||
|
|
{
|
|||
|
|
ExportADC = true;
|
|||
|
|
ExportEU = true;
|
|||
|
|
ExportMV = true;
|
|||
|
|
ExportLogs = true;
|
|||
|
|
ExportReports = true;
|
|||
|
|
ExportSetup = true;
|
|||
|
|
WriterParent = fileType;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// initializes the writer
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="pathname"></param>
|
|||
|
|
/// <param name="id"></param>
|
|||
|
|
/// <param name="dataFolder"></param>
|
|||
|
|
/// <param name="test"></param>
|
|||
|
|
/// <param name="bFiltering"></param>
|
|||
|
|
/// <param name="includeGroupNameInISOExport"></param>
|
|||
|
|
/// <param name="fd"></param>
|
|||
|
|
/// <param name="tmChannel"></param>
|
|||
|
|
/// <param name="channelNumber"></param>
|
|||
|
|
/// <param name="beginEventHandler"></param>
|
|||
|
|
/// <param name="cancelEventHandler"></param>
|
|||
|
|
/// <param name="endEventHandler"></param>
|
|||
|
|
/// <param name="tickEventHandler"></param>
|
|||
|
|
/// <param name="errorEventHandler"></param>
|
|||
|
|
/// <param name="cancelRequested"></param>
|
|||
|
|
public void Initialize(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)
|
|||
|
|
{
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|