This commit is contained in:
2026-04-17 14:55:32 -04:00
commit bc3ac1d4c9
18017 changed files with 4371742 additions and 0 deletions

View File

@@ -0,0 +1,857 @@
/*
* Iso.File.Test.Channel.cs
*
* Copyright © 2009
* Diversified Technical Systems, Inc.
* All Rights Reserved
*/
using System;
using System.Collections.Generic;
using System.Text;
using DTS.Common.Enums;
using DTS.Common.Utilities;
using DTS.Common.Utilities.DotNetProgrammingConstructs;
using DTS.Common.Utils;
namespace DTS.Serialization.Iso
{
// *** Iso.File.cs ***
public partial class File
{
// *** Iso.File.Test.cs ***
public partial class Test
{ ///
/// <summary>
/// ISO-style representation of a test channel.
/// </summary>
///
public class Channel : Exceptional
{
/// <summary>
/// Get/set the data zero offset of the data (in EU).
/// </summary>
public double DataZeroOffsetEu
{
get
{
if (!_DataZeroOffsetEu.IsValueInitialized) { return 0; }
return _DataZeroOffsetEu.Value;
}
set => _DataZeroOffsetEu.Value = value;
}
private readonly Property<double> _DataZeroOffsetEu
= new Property<double>(
typeof(File).Namespace + ".Iso.File.Test.Channel.DataZeroOffsetEu",
0,
false
);
/// <summary>
/// Get/set the <see cref="int"/> number associated with this test object.
/// </summary>
public int TestObjectNumber
{
get
{
if (!_TestObjectNumber.IsValueInitialized) { return 0; }
return _TestObjectNumber.Value;
}
set => _TestObjectNumber.Value = value;
}
private const string TestObjectNumberLabel = "Test object number";
private readonly Property<int> _TestObjectNumber
= new Property<int>(
typeof(File).Namespace + ".Iso.File.Test.Channel.TestObjectNumber",
0,
false
);
/// <summary>
/// Get/set the <see cref="bool"/> indicating whether or not errors occurred in
/// the capture of this channel data.
/// </summary>
public bool ErrorsOccurred
{
get
{
if (!_ErrorsOccurred.IsValueInitialized) { return false; }
return _ErrorsOccurred.Value;
}
set => _ErrorsOccurred.Value = value;
}
private readonly Property<bool> _ErrorsOccurred
= new Property<bool>(
typeof(File).Namespace + ".Iso.File.Test.Channel.ErrorsOccurred",
false,
false
);
/// <summary>
/// Get/set the <see cref="string"/> name of the channel.
/// </summary>
public string Name
{
get
{
if (!_Name.IsValueInitialized) { return null; }
return _Name.Value;
}
set => _Name.Value = value;
}
private const string NameLabel = "Name of the channel";
private readonly Property<string> _Name
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Channel.Name",
null,
false
);
/// <summary>
/// Get/set the laboratory code <see cref="string"/> for the channel.
/// </summary>
public string LaboratoryCode
{
get
{
if (!_LaboratoryCode.IsValueInitialized) { return null; }
return _LaboratoryCode.Value;
}
set => _LaboratoryCode.Value = value;
}
private const string LaboratoryCodeLabel = "Laboratory channel code";
private readonly Property<string> _LaboratoryCode
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Channel.LaboratoryCode",
null,
false
);
/// <summary>
/// Get/set the customer code <see cref="string"/> for the channel.
/// </summary>
public string CustomerCode
{
get
{
if (!_CustomerCode.IsValueInitialized) { return null; }
return _CustomerCode.Value;
}
set => _CustomerCode.Value = value;
}
private const string CustomerCodeLabel = "Customer channel code";
private readonly Property<string> _CustomerCode
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Channel.CustomerCode",
null,
false
);
/// <summary>
/// Get/set the code <see cref="string"/> for the channel.
/// </summary>
public string Code
{
get
{
if (!_Code.IsValueInitialized) { return null; }
return _Code.Value;
}
set => _Code.Value = value;
}
private const string CodeLabel = "Channel code";
private readonly Property<string> _Code
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Channel.Code",
null,
false
);
/// <summary>
/// Get/set the location <see cref="string"/> for the channel.
/// </summary>
public string Location
{
get
{
if (!_Location.IsValueInitialized) { return "????"; }
return _Location.Value;
}
set => _Location.Value = value;
}
private const string LocationLabel = "Location";
private readonly Property<string> _Location
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Channel.Location",
"????",
true
);
/// <summary>
/// Get/set the location <see cref="string"/> for the channel.
/// </summary>
public string Dimension
{
get
{
if (!_Dimension.IsValueInitialized) { return null; }
return _Dimension.Value;
}
set => _Dimension.Value = value;
}
private const string DimensionLabel = "Dimension";
private readonly Property<string> _Dimension
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Channel.Dimension",
null,
false
);
/// <summary>
/// Get/set the direction <see cref="string"/> for the channel.
/// </summary>
public string Direction
{
get
{
if (!_Direction.IsValueInitialized) { return null; }
return _Direction.Value;
}
set => _Direction.Value = value;
}
private const string DirectionLabel = "Direction";
private readonly Property<string> _Direction
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Channel.Direction",
null,
false
);
/// <summary>
/// Get/set the list of <see cref="ExtraProperty"/>s for this test.
/// </summary>
public List<ExtraProperty> ExtraProperties
{
get => _ExtraProperties.Value;
set => _ExtraProperties.Value = value;
}
private readonly Property<List<ExtraProperty>> _ExtraProperties
= new Property<List<ExtraProperty>>(
typeof(File).Namespace + ".Iso.File.Test.Channel.ExtraProperties",
new List<ExtraProperty>(),
true
);
/// <summary>
/// Get/set the <see cref="ChannelFilter"/> for the channel.
/// </summary>
public ChannelFilter FilterClass
{
get
{
if (!_FilterClass.IsValueInitialized) { return ChannelFilter.Unfiltered; }
return _FilterClass.Value;
}
set => _FilterClass.Value = value;
}
private readonly Property<ChannelFilter> _FilterClass
= new Property<ChannelFilter>(
typeof(File).Namespace + ".Iso.File.Test.Channel.FilterClass",
ChannelFilter.Unfiltered,
false
);
/// <summary>
/// Get/set the <see cref="string"/> for the channel.
/// </summary>
public string ChannelFrequencyClass
{
get
{
if (!_ChannelFrequencyClass.IsValueInitialized) { return null; }
return _ChannelFrequencyClass.Value;
}
set => _ChannelFrequencyClass.Value = value;
}
private const string FrequencyClassLabel = "Channel frequency class";
private readonly Property<string> _ChannelFrequencyClass
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Channel.ChannelFrequencyClass",
null,
false
);
/// <summary>
/// Get/set the unit <see cref="string"/> for the channel.
/// </summary>
public string Unit
{
get
{
if (!_Unit.IsValueInitialized) { return null; }
return _Unit.Value;
}
set => _Unit.Value = value;
}
private const string UnitLabel = "Unit";
private readonly Property<string> _Unit
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Channel.Unit",
null,
false
);
/// <summary>
/// Get/set the reference system <see cref="string"/> for the channel.
/// </summary>
public string ReferenceSystem
{
get
{
if (!_ReferenceSystem.IsValueInitialized) { return null; }
return _ReferenceSystem.Value;
}
set => _ReferenceSystem.Value = value;
}
private const string ReferenceSystemLabel = "Reference system";
private readonly Property<string> _ReferenceSystem
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Channel.ReferenceSystem",
null,
false
);
/// <summary>
/// Get/set the transducer type <see cref="string"/> for the channel.
/// </summary>
public string TransducerType
{
get
{
if (!_TransducerType.IsValueInitialized) { return null; }
return _TransducerType.Value;
}
set => _TransducerType.Value = value;
}
private const string TransducerTypeLabel = "Transducer type";
private readonly Property<string> _TransducerType
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Channel.TransducerType",
null,
false
);
/// <summary>
/// Get/set the transducer id (sensor serial number) <see cref="string"/> for the channel.
/// </summary>
public string TransducerId
{
get
{
if (!_TransducerId.IsValueInitialized) { return null; }
return _TransducerId.Value;
}
set => _TransducerId.Value = value;
}
private const string TransducerIdLabel = "Transducer id";
private readonly Property<string> _TransducerId
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Channel.TransducerId",
null,
false
);
/// <summary>
/// Get/set the pre-filter type <see cref="string"/> for the channel.
/// </summary>
public string PrefilterType
{
get
{
if (!_PrefilterType.IsValueInitialized) { return null; }
return _PrefilterType.Value;
}
set => _PrefilterType.Value = value;
}
private const string PrefilterTypeLabel = "Pre-filter type";
private readonly Property<string> _PrefilterType
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Channel.PrefilterType",
null,
false
);
/// <summary>
/// Get/set the <see cref="double"/> cut-off frequency value for the channel.
/// </summary>
public double CutOffFrequency
{
get
{
if (!_CutOffFrequency.IsValueInitialized) { return 0D; }
return _CutOffFrequency.Value;
}
set => _CutOffFrequency.Value = value;
}
private const string CutOffFrequencyLabel = "Cut off frequency";
private readonly Property<double> _CutOffFrequency
= new Property<double>(
typeof(File).Namespace + ".Iso.File.Test.Channel.CutOffFrequency",
0.0,
false
);
public bool IsDigitalInput { get; set; }
public bool IsSquib { get; set; }
public double AmplitudeClass { get; set; }
private const string AmplitudeClassLabel = "Channel amplitude class";
private const string ReferenceChannelLabel = "Reference channel";
private const string ReferenceChannelNameLabel = "Reference channel name";
private const string DataSourceLabel = "Data source";
private const string DataStatusLabel = "Data status";
/// <summary>
/// Get/set the <see cref="double"/> sampling interval for the Test.
/// this is the max sample rate between all channels
/// </summary>
public double SamplingIntervalTest
{
get
{
if (!_SamplingIntervalTest.IsValueInitialized) { return 0D; }
return _SamplingIntervalTest.Value;
}
set => _SamplingIntervalTest.Value = value;
}
private readonly Property<double> _SamplingIntervalTest
= new Property<double>(
typeof(File).Namespace + ".Iso.File.Test.Channel.SamplingIntervalTest",
0.0,
false
);
/// <summary>
/// Get/set the <see cref="double"/> sampling interval for the channel.
/// </summary>
public double SamplingInterval
{
get
{
if (!_SamplingInterval.IsValueInitialized) { return 0D; }
return _SamplingInterval.Value;
}
set => _SamplingInterval.Value = value;
}
private const string SamplingIntervalLabel = "Sampling interval";
private readonly Property<double> _SamplingInterval
= new Property<double>(
typeof(File).Namespace + ".Iso.File.Test.Channel.SamplingInterval",
0.0,
false
);
/// <summary>
/// Get/set the <see cref="int"/> bit resolution for the channel.
/// </summary>
public int BitResolution
{
get
{
if (!_BitResolution.IsValueInitialized) { return 0; }
return _BitResolution.Value;
}
set => _BitResolution.Value = value;
}
private const string BitResolutionLabel = "Bit resolution";
private readonly Property<int> _BitResolution
= new Property<int>(
typeof(File).Namespace + ".Iso.File.Test.Channel.BitResolution",
0,
false
);
/// <summary>
/// Get/set this channel's comment <see cref="string"/>.
/// </summary>
public string Comments
{
get
{
if (!_Comments.IsValueInitialized) { return null; }
return _Comments.Value;
}
set => _Comments.Value = value;
}
private readonly Property<string> _Comments
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Channel.Comments",
null,
false
);
/// <summary>
/// Get/set the <see cref="double"/> time of first sample for the channel.
/// </summary>
public double TimeOfFirstSample
{
get
{
if (!_TimeOfFirstSample.IsValueInitialized) { return 0D; }
return _TimeOfFirstSample.Value;
}
set => _TimeOfFirstSample.Value = value;
}
private const string TimeOfFirstSampleLabel = "Time of first sample";
private readonly Property<double> _TimeOfFirstSample
= new Property<double>(
typeof(File).Namespace + ".Iso.File.Test.Channel.TimeOfFirstSample",
0.0,
false
);
/// <summary>
/// Get/set the <see cref="int"/> number of samples on the channel.
/// </summary>
public ulong NumberOfSamples
{
get
{
try
{
return Convert.ToUInt64(Samples.Data.Length);
}
catch (System.Exception ex)
{
throw new Exception("encountered problem getting number of samples for channel " + (_Name.IsInitialized && null != Name ? "\"" + Name + "\"" : "<NULL>"), ex);
}
}
}
private const string NumberOfSamplesLabel = "Number of samples";
/// <summary>
/// Get/set this channel's offset post test <see cref="string"/>.
/// </summary>
public double OffsetPostTest
{
get
{
if (!_OffsetPostTest.IsValueInitialized) { return 0D; }
return _OffsetPostTest.Value;
}
set => _OffsetPostTest.Value = value;
}
private const string OffsetPostTestLabel = "Offset post test";
private readonly Property<double> _OffsetPostTest
= new Property<double>(
typeof(File).Namespace + ".Iso.File.Test.Channel.OffsetPostTest",
0.0,
false
);
private const string TransducerNatFreqLabel = "Transducer natural frequency";
private const string TransducerDampRatioLabel = "Transducer damping ratio";
/// <summary>
/// Get/set the <see cref="double"/> first global maximum for the channel.
/// </summary>
public double FirstGlobalMaximum
{
get
{
try
{
if (_IsFirstGlobalMaximumValueInitialized)
return _FirstGlobalMaximumValue;
long firstMaxIndex = 0;
long maxIndex = 0;
var firstMax = double.NaN;
if (Samples != null)
{
firstMaxIndex = (Samples.Data.Length > 0) ? Samples.Data.Length - 1 : 0;
maxIndex = Samples.Data.Length;
firstMax = Samples.Data[firstMaxIndex - 1];
}
// xxx For some reason the memory mapped class is painfully slow when
// traversed in reverse, so we're going from the front. Also, indexing
// the last item causes problems, so for the moment we're stopping
// one item short.
for (long i = 0; i < maxIndex - 1; i++)
{
if (firstMax < Samples.Data[i])
{
firstMax = Samples.Data[i];
firstMaxIndex = i;
}
}
_FirstGlobalMaximumValue = firstMax - DataZeroOffsetEu;
_FirstGlobalMaximumValueIndex = firstMaxIndex;
_IsFirstGlobalMaximumValueInitialized = true;
return _FirstGlobalMaximumValue;
}
catch (System.Exception ex)
{
throw new Exception("encountered problem getting first global maximum on channel " + (_Name.IsInitialized && null != Name ? "\"" + Name + "\"" : "<NULL>"), ex);
}
}
set
{
_FirstGlobalMaximumValue = value;
_IsFirstGlobalMaximumValueInitialized = true;
}
}
private const string FirstGlobalMaximumLabel = "First global maximum";
private double _FirstGlobalMaximumValue = 0.0;
private long _FirstGlobalMaximumValueIndex = 0;
private bool _IsFirstGlobalMaximumValueInitialized = false;
/// <summary>
/// Get/set the <see cref="double"/> time of maximum value for the channel.
/// </summary>
public double TimeOfMaximumValue
{
get
{
try
{
if (!_IsTimeOfMaximumValueInitialized)
{
_TimeOfMaximumValue = TimeOfFirstSample + SamplingInterval * _FirstGlobalMaximumValueIndex;
_IsTimeOfMaximumValueInitialized = true;
}
return _TimeOfMaximumValue;
}
catch (System.Exception ex)
{
throw new Exception("encountered problem getting time of maximum value", ex);
}
}
}
private const string TimeOfMaximumValueLabel = "Time of maximum value";
private double _TimeOfMaximumValue = 0.0;
private bool _IsTimeOfMaximumValueInitialized = false;
/// <summary>
/// Get/set the <see cref="double"/> first global minimum for the channel.
/// </summary>
public double FirstGlobalMinimum
{
get
{
try
{
if (_IsFirstGlobalMinimumValueInitialized)
return _FirstGlobalMinimumValue;
long firstMinIndex = 0;
var firstMin = double.NaN;
if (Samples != null)
{
firstMinIndex = Samples.Data.Length > 0 ? Samples.Data.Length - 1 : 0;
firstMin = Samples.Data[firstMinIndex - 1];
}
// xxx correct these indicies. Have to go from front to back, also --
// for some reason the memory mapping is painfully slow when the array
// is traversed in reverse.
for (var i = firstMinIndex - 1; i >= 0; i--)
{
if (firstMin > Samples.Data[i])
{
firstMin = Samples.Data[i];
firstMinIndex = i;
}
}
_FirstGlobalMinimumValue = firstMin - DataZeroOffsetEu;
_FirstGlobalMinimumValueIndex = firstMinIndex;
_IsFirstGlobalMinimumValueInitialized = true;
return _FirstGlobalMinimumValue;
}
catch (System.Exception ex)
{
throw new Exception("encountered problem getting first global minimum on channel " + (_Name.IsInitialized && null != Name ? "\"" + Name + "\"" : "<NULL>"), ex);
}
}
set
{
_FirstGlobalMinimumValue = value;
_IsFirstGlobalMinimumValueInitialized = true;
}
}
private const string FirstGlobalMinimumLabel = "First global minimum";
private double _FirstGlobalMinimumValue = 0.0;
private long _FirstGlobalMinimumValueIndex = 0;
private bool _IsFirstGlobalMinimumValueInitialized = false;
/// <summary>
/// Get/set the <see cref="double"/> time of minimum value for the channel.
/// </summary>
public double TimeOfMinimumValue
{
get
{
try
{
if (!_IsTimeOfMinimumValueInitialized)
{
_TimeOfMinimumValue = TimeOfFirstSample + SamplingInterval * _FirstGlobalMinimumValueIndex;
_IsTimeOfMinimumValueInitialized = true;
}
return _TimeOfMinimumValue;
}
catch (System.Exception ex)
{
throw new Exception("encountered problem getting time of minimum value", ex);
}
}
}
private const string TimeOfMinimumValueLabel = "Time of minimum value";
private double _TimeOfMinimumValue = 0.0;
private bool _IsTimeOfMinimumValueInitialized = false;
/// <summary>
/// Get/set the <see cref="double"/> time of minimum value for the channel.
/// </summary>
public double StartOffsetInterval
{
get
{
try
{
return _StartOffsetInterval;
}
catch (System.Exception ex)
{
throw new Exception("encountered problem getting start offset interval", ex);
}
}
set => _StartOffsetInterval = value;
}
private const string StartOffsetIntervalLabel = "Start offset interval";
private double _StartOffsetInterval = 0.0;
/// <summary>
/// Get/set the <see cref="double"/> time of minimum value for the channel.
/// </summary>
public double EndOffsetInterval
{
get
{
try
{
return _EndOffsetInterval;
}
catch (System.Exception ex)
{
throw new Exception("encountered problem getting start offset interval", ex);
}
}
set => _EndOffsetInterval = value;
}
private const string EndOffsetIntervalLabel = "End offset interval";
private double _EndOffsetInterval = 0.0;
public FilteredData Samples
{
get
{
if (!_Samples.IsValueInitialized) { return null; }
return _Samples.Value;
}
set => _Samples.Value = value;
}
private readonly Property<FilteredData> _Samples
= new Property<FilteredData>(
typeof(File).Namespace + ".Iso.File.Test.Channel.Samples",
null,
false
);
/// <summary>
/// Generate a string representation for this object.
/// </summary>
///
/// <returns>
/// A <see cref="string"/> representation of this object.
/// </returns>
///
public override string ToString()
{
try
{
var builder = new StringBuilder();
string line = null;
builder.Append(TestObjectNumberLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => TestObjectNumber.ToString())) + (null != line ? Eol : ""));
builder.Append(NameLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => IsSquib ? Name.ReplaceStrings(Common.Constants.ExportNameFilters, StringReplacementMode.Last) : Name)) + (null != line ? Eol : "")); //17650: sanitize name output for certain exports
builder.Append(LaboratoryCodeLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => LaboratoryCode)) + (null != line ? Eol : ""));
builder.Append(CustomerCodeLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => CustomerCode)) + (null != line ? Eol : ""));
builder.Append(CodeLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Code)) + (null != line ? Eol : ""));
builder.Append(LocationLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Location)) + (null != line ? Eol : ""));
builder.Append(DimensionLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Dimension)) + (null != line ? Eol : ""));
builder.Append(DirectionLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Direction)) + (null != line ? Eol : ""));
builder.Append(FrequencyClassLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => ChannelFrequencyClass)) + (null != line ? Eol : ""));
builder.Append(UnitLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Unit)) + (null != line ? Eol : ""));
builder.Append(ReferenceSystemLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => ReferenceSystem)) + (null != line ? Eol : ""));
builder.Append(TransducerTypeLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => TransducerType)) + (null != line ? Eol : ""));
builder.Append(TransducerIdLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => IsSquib ? TransducerId.ReplaceStrings(Common.Constants.ExportNameFilters, StringReplacementMode.Last) : TransducerId)) + (null != line ? Eol : "")); //17650: sanitize name/id output for certain exports
builder.Append(PrefilterTypeLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => IsDigitalInput ? "NOVALUE" : PrefilterType)) + (null != line ? Eol : ""));
builder.Append(CutOffFrequencyLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => IsDigitalInput ? "NOVALUE" : CutOffFrequency.ToString())) + (null != line ? Eol : ""));
builder.Append(AmplitudeClassLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => AmplitudeClass.ToString())) + (null != line ? Eol : ""));
builder.Append(ReferenceChannelLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => "implicit")) + (null != line ? Eol : ""));
builder.Append(ReferenceChannelNameLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => "NOVALUE")) + (null != line ? Eol : ""));
builder.Append(DataSourceLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => "transducer")) + (null != line ? Eol : ""));
builder.Append(DataStatusLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => "ok")) + (null != line ? Eol : ""));
//14247 Data resampled using linear interpolation to the highest sample rate in the test looks incorrect?
//we put in the test sample interval rather than the channel, since we will not be exporting at the channel's rate
builder.Append(SamplingIntervalLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => SamplingIntervalTest.ToString("F6", System.Globalization.CultureInfo.InvariantCulture.NumberFormat))) + (null != line ? Eol : ""));
builder.Append(BitResolutionLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => BitResolution.ToString())) + (null != line ? Eol : ""));
builder.Append(CommentsLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Comments)) + (null != line ? Eol : ""));
builder.Append(TimeOfFirstSampleLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => TimeOfFirstSample.ToString())) + (null != line ? Eol : ""));
builder.Append(NumberOfSamplesLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => NumberOfSamples.ToString())) + (null != line ? Eol : ""));
builder.Append(OffsetPostTestLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => OffsetPostTest.ToString())) + (null != line ? Eol : ""));
builder.Append(TransducerNatFreqLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => "NOVALUE")) + (null != line ? Eol : ""));
builder.Append(TransducerDampRatioLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => "NOVALUE")) + (null != line ? Eol : ""));
builder.Append(FirstGlobalMaximumLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => FirstGlobalMaximum.ToString("F6", System.Globalization.CultureInfo.InvariantCulture.NumberFormat))) + (null != line ? Eol : ""));
builder.Append(TimeOfMaximumValueLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => TimeOfMaximumValue.ToString("F6", System.Globalization.CultureInfo.InvariantCulture.NumberFormat))) + (null != line ? Eol : ""));
builder.Append(FirstGlobalMinimumLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => FirstGlobalMinimum.ToString("F6", System.Globalization.CultureInfo.InvariantCulture.NumberFormat))) + (null != line ? Eol : ""));
builder.Append(TimeOfMinimumValueLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => TimeOfMinimumValue.ToString("F6", System.Globalization.CultureInfo.InvariantCulture.NumberFormat))) + (null != line ? Eol : ""));
builder.Append(StartOffsetIntervalLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => StartOffsetInterval.ToString("F6", System.Globalization.CultureInfo.InvariantCulture.NumberFormat))) + (null != line ? Eol : ""));
builder.Append(EndOffsetIntervalLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => EndOffsetInterval.ToString("F6", System.Globalization.CultureInfo.InvariantCulture.NumberFormat))) + (null != line ? Eol : ""));
foreach (var exp in ExtraProperties)
{
builder.Append(exp.Key.PadRight(SeparatorOffset) + Separator + (line = exp.Value) + (null != line ? Eol : ""));
}
return builder.ToString();
}
catch (System.Exception ex)
{
throw new Exception("encountered problem generating string representation for " + GetType().FullName, ex);
}
}
}
}
}
}

View File

@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DTS.Common.Utilities;
using DTS.Common.Utilities.DotNetProgrammingConstructs;
namespace DTS.Serialization.Iso
{
// *** Iso.File.cs ***
public partial class File
{
// *** Iso.File.Test.cs ***
public partial class Test
{
///
/// <summary>
/// ISO-style representation of a custom property.
/// </summary>
///
public class ExtraProperty : Exceptional
{
public ExtraProperty(string key, string value)
{
_Key.Value = key;
_Value.Value = value;
}
/// <summary>
/// Get/set the <see cref="string"/> key of the property.
/// </summary>
public string Key
{
get
{
if (!_Key.IsValueInitialized)
{
return null;
}
return _Key.Value;
}
set => _Key.Value = value;
}
private readonly Property<string> _Key
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.ExtraProperty.Key",
null,
false
);
/// <summary>
/// Get/set the <see cref="string"/> Value of the property.
/// </summary>
public string Value
{
get
{
if (!_Value.IsValueInitialized)
{
return null;
}
return _Value.Value;
}
set => _Value.Value = value;
}
private readonly Property<string> _Value
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.ExtraProperty.Value",
null,
false
);
}
}
}
}

View File

@@ -0,0 +1,441 @@
/*
* Iso.File.Test.Object.cs
*
* Copyright © 2009
* Diversified Technical Systems, Inc.
* All Rights Reserved
*/
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DTS.Common.Utilities;
using DTS.Common.Utilities.DotNetProgrammingConstructs;
namespace DTS.Serialization.Iso
{
// *** see Iso.File.cs ***
public partial class File
{
// *** see Iso.File.Test.cs ***
public partial class Test
{
/// <summary>
/// Representation of an ISO file test object.
/// </summary>
public class Object : Exceptional
{
/// <summary>
/// Get/set this ISO file test object's comment <see cref="string"/>.
/// </summary>
public string[] Comments
{
get => _Comments.Value;
set => _Comments.Value = value;
}
private readonly Property<string[]> _Comments
= new Property<string[]>(
typeof(File).Namespace + ".Iso.File.Test.Object.Comments",
null,
false
);
/// <summary>
/// Get/set this ISO file test object's name <see cref="int"/>.
/// </summary>
public string Name
{
get => _Name.Value;
set => _Name.Value = value;
}
private const string NameLabel = "Name of test object #";
private readonly Property<string> _Name
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Object.Name",
null,
false
);
/// <summary>
/// Get/set this ISO file test object's type <see cref="int"/>.
/// </summary>
public string Type
{
get => _Type.Value;
set => _Type.Value = value;
}
private const string TypeLabel = "Type of test object #";
private readonly Property<string> _Type
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Object.Type",
null,
false
);
/// <summary>
/// Get/set this ISO file test object's number <see cref="string"/>.
/// </summary>
public string Number
{
get => _Number.Value;
set => _Number.Value = value;
}
private const string NumberLabel = "Ref. number of test object #";
private readonly Property<string> _Number
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Object.Number",
null,
false
);
/// <summary>
/// Get/set this ISO file test object's number <see cref="string"/>.
/// </summary>
public int MmeNumber
{
get => _MmeNumber.Value;
set => _MmeNumber.Value = value;
}
private readonly Property<int> _MmeNumber
= new Property<int>(
typeof(File).Namespace + ".Iso.File.Test.Object.MmeNumber",
-1,
false
);
/// <summary>
/// Get/set this ISO file test object's <see cref="double"/> velocity value.
/// </summary>
public string Velocity
{
get => _Velocity.Value;
set => _Velocity.Value = value;
}
private const string VelocityLabel = "Velocity test object #";
private readonly Property<string> _Velocity
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Object.Velocity",
"0.0",
false
);
/// <summary>
/// Get/set this ISO file test object's <see cref="double"/> mass value.
/// </summary>
public string Mass
{
get => _Mass.Value;
set => _Mass.Value = value;
}
private const string MassLabel = "Mass test object #";
private readonly Property<string> _Mass
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Object.Mass",
"",
false
);
public string TestObject
{
get => _TestObject.Value;
set => _TestObject.Value = value;
}
private const string TestObjectLabel = "Test Object #";
private readonly Property<string> _TestObject =
new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Object.TestObject",
"",
false
);
/// <summary>
/// Get/set this ISO file test object's <see cref="int"/> position code.
/// </summary>
public string Position
{
get => _Position.Value;
set => _Position.Value = value;
}
private const string PositionLabel = "Driver position object #";
private readonly Property<string> _Position
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Object.Position",
"?",
false
);
/// <summary>
/// Get/set this ISO file test object's impact side <see cref="string"/> representation.
/// </summary>
public string TestObjectImpactSide
{
get => _TestObjectImpactSide.Value;
set => _TestObjectImpactSide.Value = value;
}
private const string TestObjectImpactSideLabel = "Impact side test object #";
private readonly Property<string> _TestObjectImpactSide
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Object.ImpactSide",
null,
false
);
/// <summary>
/// Get/set this ISO file test object's class <see cref="string"/>.
/// </summary>
public string Class
{
get => _Class.Value;
set => _Class.Value = value;
}
private const string ClassLabel = "Class of test object #";
private readonly Property<string> _Class
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Object.Class",
null,
false
);
/// <summary>
/// Get/set this ISO file's test object code <see cref="string"/>.
/// </summary>
public string Code
{
get => _Code.Value;
set => _Code.Value = value;
}
private const string CodeLabel = "Code of test object #";
private readonly Property<string> _Code
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Object.Code",
null,
false
);
/// <summary>
/// Get/set this ISO file's test object offset <see cref="string"/>.
/// </summary>
public string Offset
{
get => _Offset.Value;
set => _Offset.Value = value;
}
private const string OffsetLabel = ".Offset #";
private readonly Property<string> _Offset
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Object.Offset",
null,
false
);
/// <summary>
/// Get/set this ISO file's test object barrier width <see cref="string"/>.
/// </summary>
public string BarrierWidth
{
get => _BarrierWidth.Value;
set => _BarrierWidth.Value = value;
}
private const string BarrierWidthLabel = ".Barrier width #";
private readonly Property<string> _BarrierWidth
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Object.BarrierWidth",
null,
false
);
/// <summary>
/// Get/set this ISO file's test object barrier height <see cref="string"/>.
/// </summary>
public string BarrierHeight
{
get => _BarrierHeight.Value;
set => _BarrierHeight.Value = value;
}
private const string BarrierHeightLabel = ".Barrier height #";
private readonly Property<string> _BarrierHeight
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Object.BarrierHeight",
null,
false
);
/// <summary>
/// Get/set this ISO file's test object yaw angle <see cref="string"/>.
/// </summary>
public string YawAngle
{
get => _YawAngle.Value;
set => _YawAngle.Value = value;
}
private const string YawAngleLabel = ".Yaw angle #";
private readonly Property<string> _YawAngle
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Object.YawAngle",
null,
false
);
/// <summary>
/// Get/set this ISO file's test object reference system <see cref="string"/>.
/// </summary>
public string ReferenceSystem
{
get => _ReferenceSystem.Value;
set => _ReferenceSystem.Value = value;
}
private const string ReferenceSystemLabel = ".Reference system #";
private readonly Property<string> _ReferenceSystem
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Object.ReferenceSystem",
null,
false
);
/// <summary>
/// Get/set this ISO file's test object Origin X <see cref="string"/>.
/// </summary>
public string OriginX
{
get => _OriginX.Value;
set => _OriginX.Value = value;
}
private const string OriginXLabel = ".Origin X #";
private readonly Property<string> _OriginX
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Object.OriginX",
null,
false
);
/// <summary>
/// Get/set this ISO file's test object Origin Y <see cref="string"/>.
/// </summary>
public string OriginY
{
get => _OriginY.Value;
set => _OriginY.Value = value;
}
private const string OriginYLabel = ".Origin Y #";
private readonly Property<string> _OriginY
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Object.OriginY",
null,
false
);
/// <summary>
/// Get/set this ISO file's test object Origin Z <see cref="string"/>.
/// </summary>
public string OriginZ
{
get => _OriginZ.Value;
set => _OriginZ.Value = value;
}
private const string OriginZLabel = ".Origin Z #";
private readonly Property<string> _OriginZ
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Object.OriginZ",
null,
false
);
/// <summary>
/// Get/set this ISO file's test object Number of Loadcells <see cref="string"/>.
/// </summary>
public string NumberOfLoadcells
{
get => _NumberOfLoadcells.Value;
set => _NumberOfLoadcells.Value = value;
}
private const string NumberOfLoadcellsLabel = ".Number of loadcells #";
private readonly Property<string> _NumberOfLoadcells
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Test.Object.NumberOfLoadcells",
null,
false
);
/// <summary>
/// Get/set the list of <see cref="ExtraProperty"/>s for this test.
/// </summary>
public List<ExtraProperty> ExtraProperties
{
get => _ExtraProperties.Value;
set => _ExtraProperties.Value = value;
}
private readonly Property<List<ExtraProperty>> _ExtraProperties
= new Property<List<ExtraProperty>>(
typeof(File).Namespace + ".Iso.File.Test.Object.ExtraProperties",
new List<ExtraProperty>(),
true
);
/// <summary>
/// Generate a string representation for this object.
/// </summary>
///
/// <returns>
/// A <see cref="string"/> representation of this object.
/// </returns>
///
public override string ToString()
{
try
{
var builder = new StringBuilder();
string line = null;
var PositionCode = Position;
var TestObjectImpactSideCode = TestObjectImpactSide;
if (Position.ToUpper() != "NOVALUE")
{
PositionCode = Position.Substring(0, Position.IndexOf('-') - 1);
}
if ((TestObjectImpactSide.ToUpper() != "NOVALUE") && (TestObjectImpactSide != string.Empty))
{
TestObjectImpactSideCode = TestObjectImpactSide.Substring(0, TestObjectImpactSide.IndexOf('-') - 1);
}
foreach (var comment in Comments)
{
builder.Append(CommentsLabel.Replace("#", MmeNumber.ToString()).PadRight(SeparatorOffset) + Separator + (line = comment) + (null != line ? Eol : ""));
}
if (Comments.Any() && (Comments.Last() != string.Empty))
{
builder.Append(CommentsLabel.Replace("#", MmeNumber.ToString()).PadRight(SeparatorOffset) + Separator + (line = string.Empty) + (null != line ? Eol : ""));
}
builder.Append(NameLabel.Replace("#", MmeNumber.ToString()).PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Name)) + (null != line ? Eol : ""));
builder.Append(VelocityLabel.Replace("#", MmeNumber.ToString()).PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Velocity)) + (null != line ? Eol : ""));
builder.Append(MassLabel.Replace("#", MmeNumber.ToString()).PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Mass)) + (null != line ? Eol : ""));
builder.Append(PositionLabel.Replace("#", MmeNumber.ToString()).PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => PositionCode)) + (null != line ? Eol : ""));
builder.Append(TestObjectImpactSideLabel.Replace("#", MmeNumber.ToString()).PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => TestObjectImpactSideCode)) + (null != line ? Eol : ""));
builder.Append(TypeLabel.Replace("#", MmeNumber.ToString()).PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Type)) + (null != line ? Eol : ""));
builder.Append(ClassLabel.Replace("#", MmeNumber.ToString()).PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Class)) + (null != line ? Eol : ""));
builder.Append(CodeLabel.Replace("#", MmeNumber.ToString()).PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Code)) + (null != line ? Eol : ""));
builder.Append(NumberLabel.Replace("#", MmeNumber.ToString()).PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Number)) + (null != line ? Eol : ""));
builder.Append(OffsetLabel.Replace("#", MmeNumber.ToString()).PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Offset)) + (null != line ? Eol : ""));
if (Type == "B")
{
builder.Append(BarrierWidthLabel.Replace("#", MmeNumber.ToString()).PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => BarrierWidth)) + (null != line ? Eol : ""));
builder.Append(BarrierHeightLabel.Replace("#", MmeNumber.ToString()).PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => BarrierHeight)) + (null != line ? Eol : ""));
builder.Append(YawAngleLabel.Replace("#", MmeNumber.ToString()).PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => YawAngle)) + (null != line ? Eol : ""));
builder.Append(ReferenceSystemLabel.Replace("#", MmeNumber.ToString()).PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => ReferenceSystem)) + (null != line ? Eol : ""));
builder.Append(OriginXLabel.Replace("#", MmeNumber.ToString()).PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => OriginX)) + (null != line ? Eol : ""));
builder.Append(OriginYLabel.Replace("#", MmeNumber.ToString()).PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => OriginY)) + (null != line ? Eol : ""));
builder.Append(OriginZLabel.Replace("#", MmeNumber.ToString()).PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => OriginZ)) + (null != line ? Eol : ""));
builder.Append(NumberOfLoadcellsLabel.Replace("#", MmeNumber.ToString()).PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => NumberOfLoadcells)) + (null != line ? Eol : ""));
}
return builder.ToString();
}
catch (System.Exception ex)
{
throw new Exception("encountered problem generating string representation for " + GetType().FullName, ex);
}
}
}
}
}
}

View File

@@ -0,0 +1,571 @@
/*
* Iso.File.Test.cs
*
* Copyright © 2009
* Diversified Technical Systems, Inc.
* All Rights Reserved
*/
using System;
using System.Collections.Generic;
using System.Text;
using DTS.Common.Utilities;
using DTS.Common.Utilities.DotNetProgrammingConstructs;
namespace DTS.Serialization.Iso
{
// *** see Iso.File.cs ***
public partial class File
{ ///
/// <summary>
/// ISO-style representation of a test.
/// </summary>
///
public partial class Test : Exceptional
{
/// <summary>
/// Get the data format edition number <see cref="string"/> of the file format generated by this object.
/// </summary>
public string DataFormatEditionNumber
{
get => _DataFormatEditionNumber.Value;
set => _DataFormatEditionNumber.Value = value;
}
public const string DataFormatEditionNumberLabel = "Data format edition number";
private readonly Property<string> _DataFormatEditionNumber
= new Property<string>(
typeof(File).Namespace + ".Iso.File.DataFormatEditionNumber",
"1.6",
true
);
/// <summary>
/// Get/set the laboratory name <see cref="string"/> for this test.
/// </summary>
public string LaboratoryName
{
get => _LaboratoryName.Value;
set => _LaboratoryName.Value = value;
}
private const string LaboratoryNameLabel = "Laboratory name";
private readonly Property<string> _LaboratoryName
= new Property<string>(
typeof(File).Namespace + ".Iso.File.LaboratoryName",
null,
false
);
/// <summary>
/// Get/set the laboratory contact name <see cref="string"/> for this test.
/// </summary>
public string LaboratoryContactName
{
get => _LaboratoryContactName.Value;
set => _LaboratoryContactName.Value = value;
}
private const string LaboratoryContactNameLabel = "Laboratory contact name";
private readonly Property<string> _LaboratoryContactName
= new Property<string>(
typeof(File).Namespace + ".Iso.File.LaboratoryContactName",
null,
false
);
/// <summary>
/// Get/set the laboratory contact phone <see cref="string"/> for this test.
/// </summary>
public string LaboratoryContactPhone
{
get => _LaboratoryContactPhone.Value;
set => _LaboratoryContactPhone.Value = value;
}
private const string LaboratoryContactPhoneLabel = "Laboratory contact phone";
private readonly Property<string> _LaboratoryContactPhone
= new Property<string>(
typeof(File).Namespace + ".Iso.File.LaboratoryContactPhone",
null,
false
);
/// <summary>
/// Get/set the laboratory contact fax <see cref="string"/> for this test.
/// </summary>
public string LaboratoryContactFax
{
get => _LaboratoryContactFax.Value;
set => _LaboratoryContactFax.Value = value;
}
private const string LaboratoryContactFaxLabel = "Laboratory contact fax";
private readonly Property<string> _LaboratoryContactFax
= new Property<string>(
typeof(File).Namespace + ".Iso.File.LaboratoryContactFax",
null,
false
);
/// <summary>
/// Get/set the laboratory contact email <see cref="string"/> for this test.
/// </summary>
public string LaboratoryContactEmail
{
get => _LaboratoryContactEmail.Value;
set => _LaboratoryContactEmail.Value = value;
}
private const string LaboratoryContactEmailLabel = "Laboratory contact email";
private readonly Property<string> _LaboratoryContactEmail
= new Property<string>(
typeof(File).Namespace + ".Iso.File.LaboratoryContactEmail",
null,
false
);
/// <summary>
/// Get/set the laboratory test reference number <see cref="string"/> for this test.
/// </summary>
public string LaboratoryTestReferenceNumber
{
get => _LaboratoryTestReferenceNumber.Value;
set => _LaboratoryTestReferenceNumber.Value = value;
}
private const string LaboratoryTestReferenceNumberLabel = "Laboratory test ref. number";
private readonly Property<string> _LaboratoryTestReferenceNumber
= new Property<string>(
typeof(File).Namespace + ".Iso.File.LaboratoryTestReferenceNumber",
null,
false
);
/// <summary>
/// Get/set the laboratory project reference number <see cref="string"/> for this test.
/// </summary>
public string LaboratoryProjectReferenceNumber
{
get => _LaboratoryProjectReferenceNumber.Value;
set => _LaboratoryProjectReferenceNumber.Value = value;
}
private const string LaboratoryProjectReferenceNumberLabel = ".Laboratory project ref. num"; //The leading "." means it's additional to the standard
private readonly Property<string> _LaboratoryProjectReferenceNumber
= new Property<string>(
typeof(File).Namespace + ".Iso.File.LaboratoryProjectReferenceNumber",
null,
false
);
/// <summary>
/// Get/set the customer name <see cref="string"/> for this test.
/// </summary>
public string CustomerName
{
get => _CustomerName.Value;
set => _CustomerName.Value = value;
}
private const string CustomerNameLabel = "Customer name";
private readonly Property<string> _CustomerName
= new Property<string>(
typeof(File).Namespace + ".Iso.File.CustomerName",
null,
false
);
/// <summary>
/// Get/set the customer test reference number <see cref="string"/> for this test.
/// </summary>
public string CustomerTestReferenceNumber
{
get => _CustomerTestReferenceNumber.Value;
set => _CustomerTestReferenceNumber.Value = value;
}
private const string CustomerTestReferenceNumberLabel = "Customer test ref. number";
private readonly Property<string> _CustomerTestReferenceNumber
= new Property<string>(
typeof(File).Namespace + ".Iso.File.CustomerTestReferenceNumber",
null,
false
);
/// <summary>
/// Get/set the customer project reference number <see cref="string"/> for this test.
/// </summary>
public string CustomerProjectReferenceNumber
{
get => _CustomerProjectReferenceNumber.Value;
set => _CustomerProjectReferenceNumber.Value = value;
}
private const string CustomerProjectReferenceNumberLabel = "Customer project ref. number";
private readonly Property<string> _CustomerProjectReferenceNumber
= new Property<string>(
typeof(File).Namespace + ".Iso.File.CustomerProjectReferenceNumber",
null,
false
);
/// <summary>
/// Get/set customer order number <see cref="string"/> for the current test.
/// </summary>
public string CustomerOrderNumber
{
get => _CustomerOrderNumber.Value;
set => _CustomerOrderNumber.Value = value;
}
private const string CustomerOrderNumberLabel = "Customer order number";
private readonly Property<string> _CustomerOrderNumber
= new Property<string>(
typeof(File).Namespace + ".Iso.File.CustomerOrderNumber",
null,
false
);
/// <summary>
/// Get/set customer cost unit <see cref="string"/> for this test.
/// </summary>
public string CustomerCostUnit
{
get => _CustomerCostUnit.Value;
set => _CustomerCostUnit.Value = value;
}
private const string CustomerCostUnitLabel = "Customer cost unit";
private readonly Property<string> _CustomerCostUnit
= new Property<string>(
typeof(File).Namespace + ".Iso.File.CustomerCostUnit",
null,
false
);
/// <summary>
/// Get/set the Test engineer name <see cref="string"/> for this test.
/// </summary>
public string TestEngineerName
{
get => _TestEngineerName.Value;
set => _TestEngineerName.Value = value;
}
private const string TestEngineerNameLabel = "Customer test engineer name";
private readonly Property<string> _TestEngineerName
= new Property<string>(
typeof(File).Namespace + ".Iso.File.CustomerTestEngineerName",
null,
false
);
/// <summary>
/// Get/set the Test engineer phone <see cref="string"/> for this test.
/// </summary>
public string TestEngineerPhone
{
get => _TestEngineerPhone.Value;
set => _TestEngineerPhone.Value = value;
}
private const string TestEngineerPhoneLabel = "Customer test engineer phone";
private readonly Property<string> _TestEngineerPhone
= new Property<string>(
typeof(File).Namespace + ".Iso.File.CustomerTestEngineerPhone",
null,
false
);
/// <summary>
/// Get/set the Test engineer fax <see cref="string"/> for this test.
/// </summary>
public string TestEngineerFax
{
get => _TestEngineerFax.Value;
set => _TestEngineerFax.Value = value;
}
private const string TestEngineerFaxLabel = "Customer test engineer fax";
private readonly Property<string> _TestEngineerFax
= new Property<string>(
typeof(File).Namespace + ".Iso.File.CustomerTestEngineerFax",
null,
false
);
/// <summary>
/// Get/set the Test engineer email <see cref="string"/> for this test.
/// </summary>
public string TestEngineerEmail
{
get => _TestEngineerEmail.Value;
set => _TestEngineerEmail.Value = value;
}
private const string TestEngineerEmailLabel = "Customer test engineer email";
private readonly Property<string> _TestEngineerEmail
= new Property<string>(
typeof(File).Namespace + ".Iso.File.CustomerTestEngineerEmail",
null,
false
);
/// <summary>
/// Get/set the title <see cref="string"/> for this test.
/// </summary>
public string Title
{
get => _Title.Value;
set => _Title.Value = value;
}
private const string TitleLabel = "Title";
private readonly Property<string> _Title
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Title",
null,
false
);
/// <summary>
/// Get/set the number of media <see cref="string"/> representation for this test.
/// </summary>
public string NumberOfMedia
{
get => _NumberOfMedia.Value;
set => _NumberOfMedia.Value = value;
}
private const string NumberOfMediaLabel = "Medium No./number of media";
private readonly Property<string> _NumberOfMedia
= new Property<string>(
typeof(File).Namespace + ".Iso.File.NumberOfMedia",
"1/1",
true
);
/// <summary>
/// Get/set the timestamp <see cref="string"/> for this test.
/// </summary>
public string Timestamp
{
get => _Timestamp.Value;
set => _Timestamp.Value = value;
}
private const string TimestampLabel = "Timestamp";
private readonly Property<string> _Timestamp
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Timestamp",
// 14967 DateTime stamp not complete in ISO export
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
true
);
/// <summary>
/// Get/set this ISO file test's comment <see cref="string"/>.
/// </summary>
public string TestComment
{
get => _Comments.Value;
set => _Comments.Value = value;
}
protected const string CommentsLabel = "Comments";
private readonly Property<string> _Comments
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Comments",
null,
false
);
/// <summary>
/// Get/set the type <see cref="string"/> for this test.
/// </summary>
public string Type
{
get => _Type.Value;
set => _Type.Value = value;
}
private const string TypeLabel = "Type of the test";
private readonly Property<string> _Type
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Type",
null,
false
);
/// <summary>
/// Get/set the date <see cref="System.DateTime"/> for this test.
/// </summary>
public DateTime Date
{
get => _Date.Value;
set => _Date.Value = value;
}
private const string DateLabel = "Date of the test";
private readonly Property<DateTime> _Date
= new Property<DateTime>(
typeof(File).Namespace + ".Iso.File.Date",
DateTime.Now,
false
);
/// <summary>
/// Get/set the subtype <see cref="string"/> for this test.
/// </summary>
public string Subtype
{
get => _Subtype.Value;
set => _Subtype.Value = value;
}
private const string SubtypeLabel = "Subtype of the test";
private readonly Property<string> _Subtype
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Subtype",
null,
false
);
/// <summary>
/// Get/set the regulation <see cref="string"/> for this test.
/// </summary>
public string Regulation
{
get => _Regulation.Value;
set => _Regulation.Value = value;
}
private const string RegulationLabel = "Regulation";
private readonly Property<string> _Regulation
= new Property<string>(
typeof(File).Namespace + ".Iso.File.Regulation",
null,
false
);
/// <summary>
/// Get/set the <see cref="double"/> reference temperature value for this test.
/// </summary>
public string ReferenceTemperature
{
get => _ReferenceTemperature.Value;
set => _ReferenceTemperature.Value = value;
}
private const string ReferenceTemperatureLabel = "Reference temperature";
private readonly Property<string> _ReferenceTemperature
= new Property<string>(
typeof(File).Namespace + ".Iso.File.ReferenceTemperature",
null,
false
);
// [DefaultValue( "90.0" )] -- all values should have
/// <summary>
/// Get/set the <see cref="double"/> relative air humdity value for this test.
/// </summary>
public string RelativeAirHumidity
{
get => _RelativeAirHumidity.Value;
set => _RelativeAirHumidity.Value = value;
}
private const string RelativeAirHumidityLabel = "Relative air humidity";
private readonly Property<string> _RelativeAirHumidity
= new Property<string>(
typeof(File).Namespace + ".Iso.File.RelativeAirHumidity",
null,
false
);
/// <summary>
/// Get the <see cref="int"/> number of test objects in this test.
/// </summary>
public int NumberOfTestObjects => Objects.Count;
private const string NumberOfTestObjectsLabel = "Number of test objects";
/// <summary>
/// Get/set the <see cref="DTS.Serialization.Iso.File.Test.Object"/>s for this test.
/// </summary>
public List<Object> Objects
{
get => _Objects.Value;
set => _Objects.Value = value;
}
private readonly Property<List<Object>> _Objects
= new Property<List<Object>>(
typeof(File).Namespace + ".Iso.File.Test.Objects",
new List<Object>(),
true
);
/// <summary>
/// Get/set the list of <see cref="DTS.Serialization.Iso.File.Test.Channel"/>s for this test.
/// </summary>
public List<Channel> Channels
{
get => _Channels.Value;
set => _Channels.Value = value;
}
private readonly Property<List<Channel>> _Channels
= new Property<List<Channel>>(
typeof(File).Namespace + ".Iso.File.Channels",
new List<Channel>(),
true
);
/// <summary>
/// Get/set the list of <see cref="ExtraProperty"/>s for this test.
/// </summary>
public List<ExtraProperty> ExtraProperties
{
get => _ExtraProperties.Value;
set => _ExtraProperties.Value = value;
}
private readonly Property<List<ExtraProperty>> _ExtraProperties
= new Property<List<ExtraProperty>>(
typeof(File).Namespace + ".Iso.File.ExtraProperties",
new List<ExtraProperty>(),
true
);
/// <summary>
/// Generate a <see cref="string"/> representation for this instance.
/// </summary>
///
/// <returns>
/// A <see cref="string"/> representation of this instance.
/// </returns>
///
public override string ToString()
{
try
{
var builder = new StringBuilder();
string line = null;
builder.Append(DataFormatEditionNumberLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => DataFormatEditionNumber)) + (null != line ? Eol : ""));
builder.Append(LaboratoryNameLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => LaboratoryName)) + (null != line ? Eol : ""));
builder.Append(LaboratoryContactNameLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => LaboratoryContactName)) + (null != line ? Eol : ""));
builder.Append(LaboratoryContactPhoneLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => LaboratoryContactPhone)) + (null != line ? Eol : ""));
builder.Append(LaboratoryContactFaxLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => LaboratoryContactFax)) + (null != line ? Eol : ""));
builder.Append(LaboratoryContactEmailLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => LaboratoryContactEmail)) + (null != line ? Eol : ""));
builder.Append(LaboratoryTestReferenceNumberLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => LaboratoryTestReferenceNumber)) + (null != line ? Eol : ""));
builder.Append(LaboratoryProjectReferenceNumberLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => LaboratoryProjectReferenceNumber)) + (null != line ? Eol : ""));
builder.Append(CustomerNameLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => CustomerName)) + (null != line ? Eol : ""));
builder.Append(CustomerTestReferenceNumberLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => CustomerTestReferenceNumber)) + (null != line ? Eol : ""));
builder.Append(CustomerProjectReferenceNumberLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => CustomerProjectReferenceNumber)) + (null != line ? Eol : ""));
builder.Append(CustomerOrderNumberLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => CustomerOrderNumber)) + (null != line ? Eol : ""));
builder.Append(CustomerCostUnitLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => CustomerCostUnit)) + (null != line ? Eol : ""));
builder.Append(TestEngineerNameLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => TestEngineerName)) + (null != line ? Eol : ""));
builder.Append(TestEngineerPhoneLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => TestEngineerPhone)) + (null != line ? Eol : ""));
builder.Append(TestEngineerFaxLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => TestEngineerFax)) + (null != line ? Eol : ""));
builder.Append(TestEngineerEmailLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => TestEngineerEmail)) + (null != line ? Eol : ""));
builder.Append(TitleLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Title)) + (null != line ? Eol : ""));
builder.Append(NumberOfMediaLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => NumberOfMedia)) + (null != line ? Eol : ""));
builder.Append(TimestampLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Timestamp)) + (null != line ? Eol : ""));
builder.Append(CommentsLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => TestComment)) + (null != line ? Eol : ""));
builder.Append(TypeLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Type)) + (null != line ? Eol : ""));
builder.Append(ReferenceTemperatureLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => ReferenceTemperature.ToString())) + (null != line ? Eol : ""));
builder.Append(RelativeAirHumidityLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => RelativeAirHumidity.ToString())) + (null != line ? Eol : ""));
builder.Append(DateLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Date.ToString("yyyy-MM-dd"))) + (null != line ? Eol : ""));
builder.Append(RegulationLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Regulation)) + (null != line ? Eol : ""));
builder.Append(SubtypeLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => Subtype)) + (null != line ? Eol : ""));
foreach (var exp in ExtraProperties)
{
builder.Append(exp.Key.PadRight(SeparatorOffset) + Separator + (line = exp.Value) + (null != line ? Eol : ""));
}
builder.Append(NumberOfTestObjectsLabel.PadRight(SeparatorOffset) + Separator + (line = GetFieldString(() => NumberOfTestObjects.ToString())) + (null != line ? Eol : ""));
return builder.ToString();
}
catch (System.Exception ex)
{
throw new Exception("encountered problem generating string representation for " + GetType().FullName, ex);
}
}
}
}
}

View File

@@ -0,0 +1,883 @@
/*
* Iso.File.Writer.cs
*
* Copyright © 2009
* Diversified Technical Systems, Inc.
* All Rights Reserved
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using DTS.Common.Classes.Sensors;
using DTS.Common.DAS.Concepts;
using DTS.Common.DAS.Concepts.DAS.Channel;
using DTS.Common.Enums;
using DTS.Common.Enums.Sensors;
using DTS.Common.Utilities;
using DTS.Common.Utilities.Logging;
using DTS.Common.Utils;
using DTS.Serialization.Iso.Report;
namespace DTS.Serialization.Iso
{
// *** see Iso.File.cs ***
public partial class File
{
///
/// <summary>
/// Utility object for serializing <see cref="Serialization.Test"/>s to disk
/// in the ISO format.
/// </summary>
///
public class Writer : Writer<File>, IWriter<Serialization.Test>, IProgressAware
{
/// <summary>
/// whether to export the iso summary report
/// http://manuscript.dts.local/f/cases/43833/SW-Test-Summary-Report-for-data-collection-THF
/// this property is normally set by Iso.File when creating the Iso.File.Writer
/// </summary>
public bool ExportSummaryReport { get; set; } = false;
private const string VARIABLE_NAME_HEADER = "[";
private const string VARIABLE_NAME_FOOTER = "]";
/// <summary>
/// used in mme file, this is the number of channels that will be exported
/// 14226 Exports not using test obj/pos set by the group in a test when using a nonlinear sensor with a linear CAL
/// (issue #2)
/// </summary>
public int NumberOfChannels { get; set; }
private File _file = null;
public File GetFile() { return _file; }
public void SetFile(File f) { _file = f; }
///
/// <summary>
/// Initialize an instance of the Iso.File.Writer class.
/// </summary>
///
/// <param name="fileType">
/// The associated <see cref="File"/> object.
/// </param>
///
internal Writer(File fileType, int encoding, File f)
: base(fileType, encoding)
{
SetFile(f);
}
/// <summary>
/// Notify <see cref="BeginEventHandler"/> subscribers that the write
/// is starting.
/// </summary>
public event BeginEventHandler OnBegin;
/// <summary>
/// Notify <see cref="EndEventHandler"/> subscribers that the write
/// is finished.
/// </summary>
public event EndEventHandler OnEnd;
/// <summary>
/// Notify <see cref="TickEventHandler"/> subscribers that we are one
/// tick closer to write completion.
/// </summary>
public event TickEventHandler OnTick;
/// <summary>
/// notify that the writer is cancelling
/// </summary>
public event CancelEventHandler OnCancel;
/// <summary>
/// notify that the writer encountered fatal error
/// </summary>
public event ErrorEventHandler OnError;
/// <summary>
/// The number of data samples that need to be written for a "tick" to be dispatched.
/// </summary>
private int DataSamplesPerTick => 1000;
public bool UseZeroForUnfiltered { get; set; }
public bool FilteredExport { get; set; }
public bool ExportISOChannelName { get; set; }
/// <summary>
/// Return the number of data to be written per "tick".
/// </summary>
/// <param name="channel"></param>
/// <returns></returns>
private uint GetChannelTicks(Serialization.Test.Module.Channel channel)
{
try
{ //
// Most of our wait time will be spent writing data, so we need to give
// the process a little finer granularity.
//
return (uint)(channel.PersistentChannelInfo.Length / DataSamplesPerTick);
}
catch (System.Exception ex)
{
throw new Exception("encountered problem determining number of status ticks for channel " + (null != channel ? "\"" + channel.Number.ToString() + "\"" : "<NULL>"), ex);
}
}
private static readonly object ChannelLookupLock = new object();
private readonly Dictionary<string, FilteredData> _channelDictionary = new Dictionary<string, FilteredData>();
public FilteredData GetChannel(Serialization.Test.Module.Channel channel)
{
lock (ChannelLookupLock)
{
return _channelDictionary[$"{channel.ParentModule.SerialNumber}_{channel.ParentModule.Number}_{channel.Number}_{channel.ChannelDescriptionString}"];
}
}
public void AddChannel(string dasserial, int moduleNumber, int number, string description, FilteredData data)
{
lock (ChannelLookupLock)
{
_channelDictionary.Add($"{dasserial}_{moduleNumber}_{number}_{description}", data);
}
}
// xxx May be able to do the check here?
private void VerifyExportedFileWillFitOnDisk(
string testname,
string saveLocation,
CancelRequested cancelRequested)
{
try
{
ulong predictedExportSize = 0;
foreach (var sizedTestObject in FileType.TestInstance.Objects)
predictedExportSize += (ulong)sizedTestObject.ToString().Length;
var sizedChannelNumber = 1;
predictedExportSize += (ulong)("Instrumentation standard".PadRight(SeparatorOffset) + Separator + "ISO 6487 (1987) / SAE J211 (MAR95)").Length;
predictedExportSize += (ulong)("Number of channels".PadRight(SeparatorOffset) + Separator + FileType.TestInstance.Channels.Count.ToString()).Length;
int thisChannelNumber;
foreach (var channel in FileType.TestInstance.Channels)
{
if (null != cancelRequested && cancelRequested()) { break; }
if (channel.Samples != null)
{
thisChannelNumber = sizedChannelNumber++;
predictedExportSize += (ulong)channel.ToString().Length;
long numSamples = channel.Samples.Data.Length;
//this lets us do a little subsampling when predicting the export file size
var segmentLength = numSamples / 20000;
if (segmentLength < 1) { segmentLength = 1; }
for (long i = 0; i < channel.Samples.Data.Length; i += segmentLength)
{
if (null != cancelRequested && cancelRequested()) { break; }
var segmentSize = (ulong)(channel.Samples.Data[i] - channel.DataZeroOffsetEu).ToString("F6", System.Globalization.CultureInfo.InvariantCulture.NumberFormat).Length;
var nextJump = i + segmentLength > numSamples ? numSamples - i : segmentLength;
//sanity check - if numSamples is 0 for some reason we don't want a negative nextJump, we still need to count space
if (nextJump < 0) { nextJump = segmentLength; }
predictedExportSize += (ulong)nextJump * segmentSize;
}
var channelName = channel.IsSquib ? channel.Name.ReplaceStrings(Common.Constants.ExportNameFilters, StringReplacementMode.Last) : channel.Name ?? ""; //17650: sanitize name output for certain exports
predictedExportSize += (ulong)(("Name of channel " + thisChannelNumber.ToString("D3")).PadRight(SeparatorOffset) + Separator + channel.Code + " /" + channelName).Length;
}
}
predictedExportSize *= sizeof(char);
// Get the stats on available disk space.
DiskUtility.GetDiskFreeSpaceEx(saveLocation, out ulong freeBytesAvailable, out ulong totalNumberOfBytes, out ulong totalNumberOfFreeBytes);
// Do the comparison.
if (freeBytesAvailable < predictedExportSize)
{
var bytesNeeded = DiskUtility.GetHumanReadableBytes(predictedExportSize);
var bytesAvailable = DiskUtility.GetHumanReadableBytes(freeBytesAvailable);
throw new UserException("Export requires " + bytesNeeded + " but there are only " + bytesAvailable + " available on \"" + saveLocation + "\"");
}
}
catch (System.Exception ex)
{
throw new Exception("encountered problem trying to determing if ISO export of test " + (testname ?? "<NULL>") + " will fit at location " + (saveLocation ?? "<NULL>"), ex);
}
}
/// <summary>
/// Write the specified test to the specified pathname.
/// </summary>
///
/// <param name="pathname">
/// The <see cref="string"/> pathname to which the specified test should be serialized.
/// </param>
///
/// <param name="test">
/// The <see cref="Serialization.Test"/> to be written out.
/// </param>
///
public void Write(string pathname, string id, Serialization.Test test, bool bFiltering, bool includeGroupNameInISOExport, double minStartTime, int dataCollectionLength)
{
try
{
Write(pathname, id, null, test, bFiltering, includeGroupNameInISOExport, null, null, 0, null, null, null, null, null, null, minStartTime, dataCollectionLength);
}
catch (System.Exception ex)
{
throw new Exception("encountered problem non-event notified writing test", ex);
}
}
private void AssignTestObject(ref Test.Object o, Common.ISO.MMETestObjectWrapper tow)
{
o.Class = tow.ClassOfTestObject;
o.Code = tow.CodeOfTestObject;
o.Comments = tow.Comments; // string.Join("\n", tow.Comments);
o.Mass = tow.MassOfTestObject;
//o.Name = tow.Name;
o.Position = tow.DriverPosition;
o.TestObjectImpactSide = tow.ImpactSide;
o.Velocity = tow.VelocityMeterPerSecond;
}
private void ApplyISOTestChannel(ref Serialization.Test.Module.AnalogInputChannel channel, Common.ISO.TestObjectChannel toc)
{
//toc.CustomerChannelCode;
}
private uint totalWriteTicksDispatched = 0;
private uint totalWriteTicksNeeded = 0;
/// <summary>
/// populates a test object with meta data information
/// this code already existed, I just abstracted it out for easier reading
/// http://manuscript.dts.local/f/cases/13735/Need-the-ability-to-add-ISO-metadata-without-an-associated-Group
/// </summary>
/// <param name="testObject"></param>
/// <param name="testObjects"></param>
/// <param name="testObjectNumber"></param>
/// <param name="ISOTestObjectType"></param>
private void PopulateTestObject(Test.Object testObject, Common.ISO.MMETestObjectWrapper[] testObjects,
int testObjectNumber, string ISOTestObjectType)
{
testObject.Comments = testObjects[testObjectNumber].Comments;
testObject.Name = testObjects[testObjectNumber].Name;
testObject.Velocity = testObjects[testObjectNumber].VelocityMeterPerSecond;
testObject.Mass = testObjects[testObjectNumber].MassOfTestObject;
testObject.Position = testObjects[testObjectNumber].DriverPosition;
testObject.TestObjectImpactSide = testObjects[testObjectNumber].ImpactSide;
testObject.Type = ISOTestObjectType;
testObject.Class = testObjects[testObjectNumber].ClassOfTestObject;
testObject.Code = testObjects[testObjectNumber].CodeOfTestObject;
testObject.Number = testObjects[testObjectNumber].ReferenceNumberOfTestObject;
testObject.Offset = testObjects[testObjectNumber].OffsetOfTestObject;
testObject.BarrierWidth = testObjects[testObjectNumber].BarrierWidthOfTestObject;
testObject.BarrierHeight = testObjects[testObjectNumber].BarrierHeightOfTestObject;
testObject.YawAngle = testObjects[testObjectNumber].YawAngleOfTestObject;
testObject.ReferenceSystem = testObjects[testObjectNumber].ReferenceSystemOfTestObject;
testObject.OriginX = testObjects[testObjectNumber].OriginXOfTestObject;
testObject.OriginY = testObjects[testObjectNumber].OriginYOfTestObject;
testObject.OriginZ = testObjects[testObjectNumber].OriginZOfTestObject;
testObject.NumberOfLoadcells = testObjects[testObjectNumber].NumberOfLoadcellsOfTestObject;
testObject.ExtraProperties = testObjects[testObjectNumber].ExtraProperties.Select(kvp => new Test.ExtraProperty(kvp.Key, kvp.Value)).ToList();
// Assign our object number.
}
/// <summary>
/// exports a summary report to the given path based on the input test
/// </summary>
/// <param name="test"></param>
/// <param name="path"></param>
private static void ExportReport(DTS.Serialization.Test test, string path)
{
if (null == test)
{
return;
}
var summary = SummaryReport.CreateSummaryReport(test);
SummaryReport.OutputToPath(path, summary);
}
/// <summary>
/// Write the representation file/files of the specified DTS.Serialization.Test
/// at the given pathname.
/// </summary>
///
/// <param name="pathname">
/// The <see cref="string"/> pathname of the specified object's resulting file
/// representation.
/// </param>
///
/// <param name="test">
/// The <see cref="Serialization.Test"/> to be written out.
/// </param>
///
/// <param name="beginEvent">
/// <see cref="Serialization.BeginWriteEventHandler"/> delegate to be notified
/// when this object begins writing.
/// </param>
///
/// <param name="endEvent">
/// <see cref="Serialization.EndWriteEventHandler"/> delegate to be notified
/// when this object ends writing.
/// </param>
///
/// <param name="tickEvent">
/// <see cref="TickEventHandler"/> delegate to be notified
/// when this object completes a write "tick".
/// </param>
///
public void Write(string pathname,
string id,
string dataFolder,
Serialization.Test test,
bool bFiltering,
bool includeGroupNameInISOExport,
FilteredData fd,
Serialization.Test.Module.Channel tmChannel,
int channelNumber,
BeginEventHandler beginEventHandler,
CancelEventHandler cancelEventHandler,
EndEventHandler endEventHandler,
TickEventHandler tickEventHandler,
ErrorEventHandler errorEventHandler,
CancelRequested cancelRequested,
double minStartTime,
int dataCollectionLength)
{
try
{
var mmeDirectory = pathname + "\\";
var testSampleRate = test.Channels.Select(ch => ch.ParentModule.SampleRateHz).Max();
ISOChannelScale(totalWriteTicksDispatched, totalWriteTicksNeeded, tmChannel, bFiltering, fd, test.Id, includeGroupNameInISOExport, false, testSampleRate);
var testObjectNumber = 0;
var testObjects = GetFile().GetTestPlan().ISOTestObjects;
foreach (var ISOTestObjectType in testObjectChannels.Keys)
{
if (ISOTestObjectType != (tmChannel as IIsoCodeAware).IsoCode.Substring(0, 1))
{
testObjectNumber++;
continue;
}
var thisObjectChannels = testObjectChannels[ISOTestObjectType];
Test.Object testObject;
FileType.TestInstance.Objects.Add(testObject = new Test.Object());
PopulateTestObject(testObject, testObjects, testObjectNumber, ISOTestObjectType);
testObject.MmeNumber = ++testObjectNumber;
FileType.TestInstance.Channels[0].TestObjectNumber = testObject.MmeNumber;
FileType.TestInstance.Channels[0].ExtraProperties = testObject.ExtraProperties;
//FB14276: If a Iso.File.Test.Channel's Extra Property's value contains "[Test.Module.Channel Property Name]", substitute in the tmc property's value
IList<PropertyInfo> props = new List<PropertyInfo>(tmChannel.GetType().GetProperties());
var propVals = props.Select(prop => new KeyValuePair<string, string>(prop.Name, prop.GetValue(tmChannel)?.ToString())).ToList();
foreach (var exp in FileType.TestInstance.Channels[0].ExtraProperties)
{
foreach (var kvp in propVals)
{
exp.Value = exp.Value.Replace(VARIABLE_NAME_HEADER + kvp.Key + VARIABLE_NAME_FOOTER, kvp.Value);
}
}
testObject.TestObject = ISOTestObjectType; //not needed?
break; //We found what we were looking for, so no need to keep looping.
}
//add any iso test objects from groups without channels ...
foreach (var testObjectType in testObjects.Select(x => x.TypeOfTestObject))
{
var exists = FileType.TestInstance.Objects.Exists(o => o.Type == testObjectType);
if (!exists)
{
var newObject = new Test.Object();
PopulateTestObject(newObject, testObjects, testObjectNumber, testObjectType);
newObject.MmeNumber = ++testObjectNumber;
FileType.TestInstance.Objects.Add(newObject);
}
}
var channelLookup = new Dictionary<string, Common.ISO.TestObjectChannel>();
var testObjectLookkup = new Dictionary<string, Common.ISO.MMETestObjectWrapper>();
ApplyAnalogChannel(tmChannel, channelLookup);
for (var i = 0; i < FileType.TestInstance.Objects.Count; i++)
{
var o = FileType.TestInstance.Objects[i];
if (testObjectLookkup.ContainsKey(o.TestObject))
{
AssignTestObject(ref o, testObjectLookkup[o.TestObject]);
}
}
var channelDirectory = mmeDirectory + "Channel\\";
var filename = channelDirectory + id + ".chn";
APILogger.Log("writing 1 ", filename);
Encoding encoder;
try
{
encoder = FileUtils.GetEncoding(DefaultEncoding);
}
catch (System.Exception ex)
{
APILogger.Log("Problem getting encoder", ex);
encoder = Encoding.Default;
}
using (var channelsFileWriter = new StreamWriter(filename, true, encoder))
{
foreach (var channel in FileType.TestInstance.Channels)
{
using (var channelFileWriter = new StreamWriter(channelDirectory + id + "." + channelNumber.ToString("D3"), false, encoder))
{
if (null != cancelRequested && cancelRequested()) { break; }
channelFileWriter.Write(channel.ToString());
if (channel.Samples != null)
{
for (long i = 0; i < channel.Samples.Data.Length; i++) // xxx change this back!!!
{
if (null != cancelRequested && cancelRequested()) { break; }
channelFileWriter.WriteLine((channel.Samples.Data[i] - channel.DataZeroOffsetEu).ToString("F6", System.Globalization.CultureInfo.InvariantCulture.NumberFormat));
if (0 == i % DataSamplesPerTick)
{
OnTick?.Invoke(this, (double)totalWriteTicksDispatched++ / totalWriteTicksNeeded * 100);
System.Windows.Forms.Application.DoEvents();
}
}
}
channelFileWriter.Close();
var channelName = channel.IsSquib ? channel.Name.ReplaceStrings(Common.Constants.ExportNameFilters, StringReplacementMode.Last) : channel.Name ?? ""; //17650: sanitize name output for certain exports
channelsFileWriter.WriteLine(("Name of channel " + channelNumber.ToString("D3")).PadRight(SeparatorOffset) + Separator + channel.Code + " /" + channelName);
}
}
channelsFileWriter.Close();
FileType.TestInstance.Channels.Clear();
}
}
catch (System.Exception ex)
{
APILogger.Log(ex);
throw;
}
}
public void Initialize(string pathname,
string id,
string dataFolder,
Serialization.Test test,
bool bFiltering,
bool includeGroupNameInISOExport,
FilteredData fd,
Serialization.Test.Module.Channel tmChannel,
int channelNumber,
BeginEventHandler beginEventHandler,
CancelEventHandler cancelEventHandler,
EndEventHandler endEventHandler,
TickEventHandler tickEventHandler,
ErrorEventHandler errorEventHandler,
CancelRequested cancelRequested)
{
try
{
var mmeDirectory = pathname + "\\";
OnBegin += beginEventHandler;
OnTick += tickEventHandler;
OnCancel += cancelEventHandler;
OnError += errorEventHandler;
foreach (var module in test.Modules)
{
foreach (var calculatedChannel in module.CalculatedChannels)
{
totalWriteTicksNeeded++;
}
}
uint totalWriteTicksDispatched = 0;
foreach (var channel in test.Channels)
totalWriteTicksNeeded += GetChannelTicks(channel);
foreach (var module in test.Modules)
{
foreach (var calculatedChannel in module.CalculatedChannels)
{
totalWriteTicksNeeded += GetChannelTicks(calculatedChannel);
}
}
OnBegin?.Invoke(this, totalWriteTicksNeeded);
var testSampleRate = test.Channels.Select(ch => ch.ParentModule.SampleRateHz).Max();
foreach (var channel in test.Channels)
{
ISOChannelScale(totalWriteTicksDispatched, totalWriteTicksNeeded, channel, bFiltering, fd, test.Id, includeGroupNameInISOExport, true, testSampleRate);
}
foreach (var module in test.Modules)
{
foreach (var calculatedChannel in module.CalculatedChannels)
{
ISOChannelScale(totalWriteTicksDispatched, totalWriteTicksNeeded, calculatedChannel, bFiltering, fd, test.Id, includeGroupNameInISOExport, true, testSampleRate);
}
}
var testObjectNumber = 0;
var testObjects = GetFile().GetTestPlan().ISOTestObjects;
foreach (var ISOTestObjectType in testObjectChannels.Keys)
{
var thisObjectChannels = testObjectChannels[ISOTestObjectType];
Test.Object testObject;
FileType.TestInstance.Objects.Add(testObject = new Test.Object());
PopulateTestObject(testObject, testObjects, testObjectNumber, ISOTestObjectType);
// Assign our object number.
testObject.MmeNumber = ++testObjectNumber;
// Reference the associated ISO channels back to this object.
foreach (var channel in thisObjectChannels)
{
channel.TestObjectNumber = testObject.MmeNumber;
var code = new Common.ISO.IsoCode(channel.Code);
channel.ChannelFrequencyClass = code.FilterClass;
channel.Dimension = code.PhysicalDimension;
channel.Direction = code.Direction;
channel.ExtraProperties = testObject.ExtraProperties.ToList();
}
testObject.TestObject = ISOTestObjectType; //not needed?
}
//add any iso test objects from groups without channels ...
foreach (var testObjectType in testObjects.Select(x => x.TypeOfTestObject))
{
var exists = FileType.TestInstance.Objects.Exists(o => o.Type == testObjectType);
if (!exists)
{
var newObject = new Test.Object();
PopulateTestObject(newObject, testObjects, testObjectNumber, testObjectType);
newObject.MmeNumber = ++testObjectNumber;
FileType.TestInstance.Objects.Add(newObject);
}
}
var channelLookup = new Dictionary<string, Common.ISO.TestObjectChannel>();
var testObjectLookkup = new Dictionary<string, Common.ISO.MMETestObjectWrapper>();
for (var i = 0; i < test.Channels.Count; i++)
{
ApplyAnalogChannel(test.Channels[i], channelLookup);
}
foreach (var module in test.Modules)
{
foreach (var calculatedChannel in module.CalculatedChannels)
{
ApplyAnalogChannel(calculatedChannel, channelLookup);
}
}
for (var i = 0; i < FileType.TestInstance.Objects.Count; i++)
{
var o = FileType.TestInstance.Objects[i];
if (testObjectLookkup.ContainsKey(o.TestObject))
{
AssignTestObject(ref o, testObjectLookkup[o.TestObject]);
}
}
if (!Directory.Exists(mmeDirectory))
Directory.CreateDirectory(mmeDirectory);
VerifyExportedFileWillFitOnDisk(test.Id, mmeDirectory, cancelRequested);
Encoding encoder;
try
{
encoder = Common.Utils.FileUtils.GetEncoding(DefaultEncoding);
}
catch (System.Exception ex)
{
APILogger.Log("Problem getting encoder", ex);
encoder = Encoding.Default;
}
using (var fileWriter = new StreamWriter(mmeDirectory + id + TestFileExtension, false, encoder))
{
var enc = fileWriter.Encoding;
fileWriter.Write(FileType.TestInstance.ToString());
foreach (var testObject in FileType.TestInstance.Objects)
{
fileWriter.Write(testObject.ToString());
}
fileWriter.Close();
}
FileType.TestInstance.Objects.Clear();
var channelDirectory = mmeDirectory + "Channel\\";
if (!Directory.Exists(channelDirectory))
Directory.CreateDirectory(channelDirectory);
VerifyExportedFileWillFitOnDisk(test.Id, channelDirectory, cancelRequested);
var filename = channelDirectory + id + ".chn";
APILogger.Log("writing 1 ", filename);
using (var channelsFileWriter = new StreamWriter(filename, false, encoder))
{
channelsFileWriter.WriteLine("Instrumentation standard".PadRight(SeparatorOffset) + Separator + "ISO 6487 (1987) / SAE J211 (MAR95)");
channelsFileWriter.WriteLine("Number of channels".PadRight(SeparatorOffset) + Separator + NumberOfChannels.ToString());
FileType.TestInstance.Channels.Clear();
}
try
{
if (ExportSummaryReport)
{
ExportReport(test, pathname);
}
}
catch (System.Exception ex)
{
//this feature is lower priority than the rest of the export
//for now if there's an error while exporting the report, just log it
APILogger.Log(ex);
}
}
catch (System.Exception ex)
{
APILogger.Log($"encountered problem writing ISO test files", ex);
}
}
/// <summary>
/// controls whether to use desired range or actual range
/// Channel amplitude class
/// 15392 Exported CAC in the MME file is the requested CAC not the actual CAC
/// </summary>
public bool ExportActualRange { get; set; } = false;
private readonly IDictionary<string, List<Test.Channel>> testObjectChannels = new Dictionary<string, List<Test.Channel>>();
public bool UseIsoCodeFilterMapping { get; set; } = true;
private void ISOChannelScale(uint totalWriteTicksDispatched, uint totalWriteTicksNeeded, Serialization.Test.Module.Channel channel,
bool bFiltering, FilteredData fd, string testId, bool includeGroupNameInISOExport, bool initializing, double testSampleRate)
{
Test.Channel isoChannel;
FileType.TestInstance.Channels.Add(isoChannel = new Test.Channel());
isoChannel.BitResolution = 16;
isoChannel.Code = channel is IIsoCodeAware ? (channel as IIsoCodeAware).IsoCode : NoValue;
var code = new Common.ISO.IsoCode(isoChannel.Code);
isoChannel.ChannelFrequencyClass = code.FilterClass;
isoChannel.Dimension = code.PhysicalDimension;
isoChannel.Direction = code.Direction;
isoChannel.Location = code.MainLocation;
if (initializing)
{
if (!isoChannel.Code.Equals(NoValue, StringComparison.OrdinalIgnoreCase))
{ //
// Push each channel into our dictionary of ISO-object-indexable ISO channels.
//
var objectCode = isoChannel.Code.Substring(0, 1);
if (!testObjectChannels.Keys.Contains(objectCode))
testObjectChannels.Add(objectCode, new List<Test.Channel>());
testObjectChannels[objectCode].Add(isoChannel);
}
}
isoChannel.PrefilterType = "Butterworth, 5 pole"; // This will need to change for SlicePRO
if (channel is Serialization.Test.Module.AnalogInputChannel)
{
isoChannel.IsDigitalInput = (channel as Serialization.Test.Module.AnalogInputChannel).Bridge == SensorConstants.BridgeType.DigitalInput;
isoChannel.IsSquib = (channel as Serialization.Test.Module.AnalogInputChannel).Bridge == SensorConstants.BridgeType.SQUIB;
}
isoChannel.CutOffFrequency = channel.ParentModule.AaFilterRateHz;
if (ExportISOChannelName)
{
if (includeGroupNameInISOExport)
{
isoChannel.Name = channel.ChannelGroupName + ":" + channel.ChannelName2;
}
else
{
isoChannel.Name = channel.ChannelName2;
}
}
else
{
if (includeGroupNameInISOExport)
{
isoChannel.Name = channel.ChannelGroupName + ":" + channel.ChannelDescriptionString;
}
else
{
isoChannel.Name = channel.ChannelDescriptionString;
}
}
isoChannel.SamplingInterval = 1.0 / channel.ParentModule.SampleRateHz;
isoChannel.SamplingIntervalTest = 1D / testSampleRate;
var aic = channel as Serialization.Test.Module.AnalogInputChannel;
if (null != aic)
{
isoChannel.TransducerId = string.IsNullOrWhiteSpace(aic.SerialNumber) ? aic.ToString() : aic.SerialNumber;
}
if (null != channel.ParentModule.TriggerSampleNumbers && 1 >= channel.ParentModule.TriggerSampleNumbers.Count)
{
isoChannel.TimeOfFirstSample = (channel.ParentModule.StartRecordSampleNumber - (double)channel.ParentModule.TriggerSampleNumbers[0])
/ channel.ParentModule.SampleRateHz;
}
else { isoChannel.TimeOfFirstSample = 0; }
isoChannel.StartOffsetInterval = (channel as Serialization.Test.Module.AnalogInputChannel).ZeroAverageWindow.Begin;
isoChannel.EndOffsetInterval = (channel as Serialization.Test.Module.AnalogInputChannel).ZeroAverageWindow.End;
if (channel is IEngineeringUnitAware)
{
isoChannel.Unit = (channel as IEngineeringUnitAware).EngineeringUnits.TrimEnd();
if (isoChannel.Unit == "G")
{
isoChannel.Unit = "g"; //X-Crash doesn't like "G"
}
}
var scaler = new DataScaler();
scaler.IsInverted = channel is IInversionAware ? (channel as IInversionAware).IsInverted : false;
if ((channel as ILinearized).LinearizationFormula.IsValid())
{
scaler.SetLinearizationFormula((channel as ILinearized).LinearizationFormula);
}
else
{
scaler.SetLinearizationFormula(null);
}
scaler.Digital = (channel as Serialization.Test.Module.AnalogInputChannel).IsDigital();
scaler.SetDigitalMultiplier((channel as Serialization.Test.Module.AnalogInputChannel).DigitalMultiplier);
scaler.DigitalMode = (channel as Serialization.Test.Module.AnalogInputChannel).DigitalMode;
scaler.SetScaleFactorMv(channel.Data.ScaleFactorMv);
scaler.SetScaleFactorEU(channel.Data.ScaleFactorEU);
scaler.SetUseEUScaleFactors(channel.Data.UseEUScaleFactors);
scaler.UnitConversion = (channel as Serialization.Test.Module.AnalogInputChannel).UnitConversion;
scaler.BasedOnOutputAtCapacity = (channel as Serialization.Test.Module.AnalogInputChannel).AtCapacity;
scaler.CapacityOutputIsBasedOn = (channel as Serialization.Test.Module.AnalogInputChannel).CapacityOutputIsBasedOn;
scaler.SensitivityUnits = (channel as Serialization.Test.Module.AnalogInputChannel).SensitivityUnits;
scaler.Multiplier = (channel as Serialization.Test.Module.AnalogInputChannel).Multiplier;
scaler.UserOffsetEU = (channel as Serialization.Test.Module.AnalogInputChannel).UserOffsetEU;
if (channel is Serialization.Test.Module.AnalogInputChannel)
{
scaler.IEPE = (channel as Serialization.Test.Module.AnalogInputChannel).Bridge == SensorConstants.BridgeType.IEPE;
scaler.Digital = (channel as Serialization.Test.Module.AnalogInputChannel).Bridge == SensorConstants.BridgeType.DigitalInput;
}
scaler.SetMvPerEu(channel.Data.MvPerEu);
scaler.SetDataZeroLevelADC(channel.DataZeroLevelAdc);
scaler.SetRemovedADC(channel.RemovedADC);
scaler.SetRemovedInternalADC(channel.RemovedInternalADC);
scaler.SetZeroMvInADC(channel.ZeroMvInADC);
try { scaler.SetWindowAverageADC(channel.WindowAverageADC); }
catch (System.Exception) { }
if (channel is Serialization.Test.Module.AnalogInputChannel)
{
//
// Maybe these should be replaced by DTS.DAS.Concepts versions for casting? Would need to
// add excitation voltage as a concept, and proportional to excitation.
//
var analogChannel = channel as Serialization.Test.Module.AnalogInputChannel;
try { scaler.SetInitialOffset(analogChannel.InitialOffset); }
catch (System.Exception) { }
scaler.ZeroMethodType = analogChannel.ZeroMethod;
scaler.NominalExcitationVoltage = analogChannel.ExcitationVoltage;
if (analogChannel.MeasuredExcitationVoltageValid)
{
try { scaler.MeasuredExcitationVoltage = analogChannel.MeasuredExcitationVoltage; }
catch { };
}
if (analogChannel.FactoryExcitationVoltageValid)
{
try { scaler.FactoryExcitationVoltage = analogChannel.FactoryExcitationVoltage; }
catch { };
}
scaler.ProportionalToExcitation = analogChannel.ProportionalToExcitation;
isoChannel.StartOffsetInterval = analogChannel.ZeroAverageWindow.Begin;
isoChannel.EndOffsetInterval = analogChannel.ZeroAverageWindow.End;
}
// xxx Probably need to create an object for isoChannel.Samples that wraps the memory mapped data
// object and just converts the samples as they're accessed. And maybe for the data viewer, we can
// do an "is a" test on the data object and do the right thing accordingly...?
// xxx Or is there any reason why we can't just keep it short and cast it each time?
if ((channel as ILinearized).LinearizationFormula.IsValid())
{
isoChannel.DataZeroOffsetEu = 0;
}
else
{
//19038 Export data in ISO not respecting initial offset EU at mV settings.
//DataZeroOffsetEU in linear sensors should be a constant, but we can't
//just subtract GetEU(DataZeroLevelADC), normally EU= GetEU(ADC-ZeroLevelADC) but
//this overlooks and overapplies things like InitialOffsetEU, so
//EU = GetEU(ADC)-GetEU(ZeroLevelADC) is applying InitialOffset twice while
//EU = GetEU(ADC-ZeroLevelADC) only applies it once ... so don't apply any initial offset to DataZeroOfsetEU
var scaler2 = new DataScaler(scaler);
scaler2.SetInitialOffset(new InitialOffset() { Form = InitialOffsetTypes.None, EU = 0, MV = 0 });
//also close out useroffset or it will be double counted ...
//29678 ISO export does not match CSV/ Viewer output
scaler2.UserOffsetEU = 0;
isoChannel.DataZeroOffsetEu = scaler2.GetEU(channel.DataZeroLevelAdc);
}
isoChannel.Samples = fd;
isoChannel.OffsetPostTest = scaler.GetEU(channel.PreTestZeroLevelAdc); //Change this when we have post-test diagnostics
// 15392 Exported CAC in the MME file is the requested CAC not the actual CAC
if (ExportActualRange)
{
try
{
if (scaler.GetLinearizationFormula().IsValid())
{
isoChannel.AmplitudeClass = aic?.DesiredRange ?? 0;
}
else
{
var a = scaler.GetEU(short.MinValue);
var b = scaler.GetEU(short.MaxValue);
isoChannel.AmplitudeClass = Math.Abs((b - a) / 2);
}
}
catch (Exception ex)
{
APILogger.Log("Actual range unavailable for channel export", ex);
isoChannel.AmplitudeClass = aic.DesiredRange;
}
}
else
{
isoChannel.AmplitudeClass = aic.DesiredRange;
}
channel.PersistentChannelInfo.Dispose();
}
private void ApplyAnalogChannel(Serialization.Test.Module.Channel channel, Dictionary<string, Common.ISO.TestObjectChannel> channelLookup)
{
if (!(channel is Serialization.Test.Module.AnalogInputChannel analogChannel)) { return; }
if (channelLookup.ContainsKey(analogChannel.SerialNumber))
{
ApplyISOTestChannel(ref analogChannel, channelLookup[analogChannel.SerialNumber]);
}
}
}
}
}

View File

@@ -0,0 +1,294 @@
/*
* Iso.File.cs
*
* Copyright © 2009
* Diversified Technical Systems, Inc.
* All Rights Reserved
*/
using System;
using System.Linq;
using DTS.Common.Utilities.DotNetProgrammingConstructs;
using DTS.Serialization.Iso.Report;
// ISO implementation items:
// ------------------------
// * Do properly dynamically-presented/not-there-at-all comments.
// * Comments.txt file.
// * Progress reporting.
namespace DTS.Serialization.Iso
{
public partial class File
: Serialization.File,
IWritable<Test>
{
/// <summary>
/// Whether to export a summary report with the iso export
/// http://manuscript.dts.local/f/cases/43833/SW-Test-Summary-Report-for-data-collection-THF
/// </summary>
public bool ExportSummaryReport { get; set; } = false;
private readonly Common.ISO.TestPlan _testPlan = null;
public Common.ISO.TestPlan GetTestPlan() { return _testPlan; }
///
/// <summary>
/// Initialize an instance of the Iso.File class.
/// </summary>
///
public File(Common.ISO.TestPlan testplan)
: base("ISO")
{
_testPlan = testplan;
}
public bool UseZeroForUnfiltered { get; set; } = false;
/// <summary>
/// when true forces the isocode for filter to by determined by the software filter for the channel
/// </summary>
public bool UseIsoCodeFilterMapping { get; set; }
public bool FilteredExport { get; set; } = false;
public bool ExportISOChannelName { get; set; } = false;
public void AddChannel(string dasserial, int moduleNumber, int number, string description, FilteredData data)
{
(Exporter as Writer).AddChannel(dasserial, moduleNumber, number, description, data);
}
public void ApplyTestPlan(Serialization.Test test)
{
foreach (Common.ISO.TestPlan.IsoFields field in Enum.GetValues(typeof(Common.ISO.TestPlan.IsoFields)))
{
var value = GetTestPlan().GetField(field);
switch (field)
{
case Common.ISO.TestPlan.IsoFields.CustName:
break;
case Common.ISO.TestPlan.IsoFields.CustomerCostUnit:
TestInstance.CustomerCostUnit = value;
break;
case Common.ISO.TestPlan.IsoFields.CustomerName:
TestInstance.CustomerName = value;
break;
case Common.ISO.TestPlan.IsoFields.CustomerOrderNumber:
TestInstance.CustomerOrderNumber = value;
break;
case Common.ISO.TestPlan.IsoFields.CustomerProjectReferenceNumber:
TestInstance.CustomerProjectReferenceNumber = value;
break;
case Common.ISO.TestPlan.IsoFields.TEName:
break;
case Common.ISO.TestPlan.IsoFields.TestEngineerEmail:
TestInstance.TestEngineerEmail = value;
break;
case Common.ISO.TestPlan.IsoFields.TestEngineerFax:
TestInstance.TestEngineerFax = value;
break;
case Common.ISO.TestPlan.IsoFields.TestEngineerName:
TestInstance.TestEngineerName = value;
break;
case Common.ISO.TestPlan.IsoFields.TestEngineerPhone:
TestInstance.TestEngineerPhone = value;
break;
case Common.ISO.TestPlan.IsoFields.CustomerTestReferenceNumber:
TestInstance.CustomerTestReferenceNumber = value;
break;
case Common.ISO.TestPlan.IsoFields.Date:
if (DateTime.TryParse(value, out var temp))
{
TestInstance.Date = temp;
}
else
{
TestInstance.Date = test.InceptionDate;
}
break;
case Common.ISO.TestPlan.IsoFields.ExtraProperties:
TestInstance.ExtraProperties = GetTestPlan().ExtraProperties.Select(kvp => new Test.ExtraProperty(kvp.Key, kvp.Value)).ToList();
break;
case Common.ISO.TestPlan.IsoFields.LabName:
break;
case Common.ISO.TestPlan.IsoFields.LaboratoryContactEmail:
TestInstance.LaboratoryContactEmail = value;
break;
case Common.ISO.TestPlan.IsoFields.LaboratoryContactFax:
TestInstance.LaboratoryContactFax = value;
break;
case Common.ISO.TestPlan.IsoFields.LaboratoryContactName:
TestInstance.LaboratoryContactName = value;
break;
case Common.ISO.TestPlan.IsoFields.LaboratoryContactPhone:
TestInstance.LaboratoryContactPhone = value;
break;
case Common.ISO.TestPlan.IsoFields.LaboratoryName:
TestInstance.LaboratoryName = value;
break;
case Common.ISO.TestPlan.IsoFields.LaboratoryTestReferenceNumber:
TestInstance.LaboratoryTestReferenceNumber = value;
break;
case Common.ISO.TestPlan.IsoFields.LaboratoryProjectReferenceNumber:
TestInstance.LaboratoryProjectReferenceNumber = value;
break;
case Common.ISO.TestPlan.IsoFields.NumberOfMedia:
TestInstance.NumberOfMedia = value;
break;
case Common.ISO.TestPlan.IsoFields.NumberOfTestObjects:
break;
case Common.ISO.TestPlan.IsoFields.ReferenceTemperature:
TestInstance.ReferenceTemperature = value;
break;
case Common.ISO.TestPlan.IsoFields.Regulation:
TestInstance.Regulation = value;
break;
case Common.ISO.TestPlan.IsoFields.RelativeAirHumidity:
TestInstance.RelativeAirHumidity = value;
break;
case Common.ISO.TestPlan.IsoFields.Subtype:
TestInstance.Subtype = value;
break;
case Common.ISO.TestPlan.IsoFields.TestComment:
TestInstance.TestComment = value;
break;
case Common.ISO.TestPlan.IsoFields.Title:
TestInstance.Title = value == NoValue ? test.Id : value;
break;
case Common.ISO.TestPlan.IsoFields.Type:
TestInstance.Type = value;
break;
default:
throw new NotSupportedException("unsupported iso field");
}
}
}
/// <summary>
/// Get the file writer for this file type.
/// </summary>
public IWriter<Serialization.Test> Exporter
{
get
{
try
{
if (_Exporter == null)
{
var writer = new Writer(this, DefaultEncoding, this);
writer.UseZeroForUnfiltered = UseZeroForUnfiltered;
writer.UseIsoCodeFilterMapping = UseIsoCodeFilterMapping;
writer.FilteredExport = FilteredExport;
writer.ExportISOChannelName = ExportISOChannelName;
writer.ExportSummaryReport = ExportSummaryReport;
_Exporter = writer;
}
return _Exporter;
}
catch (System.Exception ex)
{
throw new Exception("encountered problem getting exporter", ex);
}
}
}
private IWriter<Serialization.Test> _Exporter = null;
/// <summary>
/// File extension for the disk entity that contains the serialized test information.
/// </summary>
public static string TestFileExtension
{
get => _TestFileExtension.Value;
private set => _TestFileExtension.Value = value;
}
private static readonly Property<string> _TestFileExtension = new Property<string>("TestFileExtension", ".mme", true);
/// <summary>
/// File extension for the disk entity that contains serialized channel information.
/// </summary>
public static string ChannelFileExtension
{
get => _ChannelFileExtension.Value;
private set => _ChannelFileExtension.Value = value;
}
private static readonly Property<string> _ChannelFileExtension = new Property<string>("ChannelFileExtension", ".chn", true);
/// <summary>
/// String representation of a value-less field.
/// </summary>
private const string NoValue = "NOVALUE";
/// <summary>
/// Line terminator to use when printing out files.
/// </summary>
private static readonly string Eol = Environment.NewLine;
/// <summary>
/// Attribute/value seperator to use when printing out files.
/// </summary>
private const string Separator = ":";
/// <summary>
/// Offset to use for attribute/value seperator when printing out files.
/// </summary>
private const int SeparatorOffset = 28;
/// <summary>
/// Delegate for extracting the value of a field in a controllable context e.g., in
/// a try/catch block.
/// </summary>
///
/// <returns>
/// The <see cref="string"/> representation of the field.
/// </returns>
///
private delegate string FieldValueStringExtractor();
/// <summary>
/// Get a string representation of the field wrapped within the extractor delegate.
/// </summary>
///
/// <param name="extractor">
/// The <see cref="DTS.Serialization.File.Iso.File.FieldValueStringExtractor"/> wrapping the
/// field to be stringified.
/// </param>
///
/// <returns>
/// A <see cref="string"/> version of the field; "NOVALUE" if the field has not been initialized.
/// </returns>
///
private static string GetFieldString(FieldValueStringExtractor extractor)
{
try
{
try
{ //
// Empty string is no value.
//
var fieldString = extractor();
return (!string.IsNullOrEmpty(fieldString) ? fieldString : NoValue);
}
catch (System.Exception)
{
return NoValue;
}
}
catch (System.Exception ex)
{
throw new Exception("encountered problem getting field string from field extractor", ex);
}
}
/// <summary>
/// Get the <see cref="Iso.File.Test"/> associated with this file.
/// </summary>
public Test TestInstance => _TestInstance.Value;
private readonly Property<Test> _TestInstance
= new Property<Test>(
typeof(Test).Namespace + ".Iso.File.TestInstance",
new Test(),
true
);
}
}

View File

@@ -0,0 +1,74 @@
using DTS.Common;
namespace DTS.Serialization.Iso.Report
{
/// <summary>
/// this class encapsulates a single line in the iso test summary report
/// </summary>
internal class ChannelData
{
/// <summary>
/// the number of the channel among all channels in the data
/// </summary>
public int ChannelNumber { get; set; } = 1;
/// <summary>
/// the iso code for a channel
/// </summary>
public string ISOCode { get; set; } = string.Empty;
/// <summary>
/// the name of the channel (iso channel name)
/// </summary>
public string ChannelName { get; set; } = string.Empty;
/// <summary>
/// the channel filter class for the channel (as in test setup, does not need to match exported data)
/// </summary>
public string SAEFilterClass { get; set; } = string.Empty;
/// <summary>
/// the electronic id at test setup time for the channel
/// </summary>
public string SetupEID { get; set; } = string.Empty;
/// <summary>
/// the electronic id at run test time on channel
/// </summary>
public string DataCollectionEID { get; set; } = string.Empty;
/// <summary>
/// any data flags present on channel
/// </summary>
public DataFlag DataFlag { get; set; } = DataFlag.None;
public const string NAME_OF_CHANNEL = "Name of channel";
public string GetLine()
{
return $"{NAME_OF_CHANNEL} {(1 + ChannelNumber):000} :{ISOCode} / {ChannelName} / {SAEFilterClass} / {SetupEID} / {DataCollectionEID} / {(int)DataFlag}";
}
/// <summary>
/// creates a channeldata instance given a test data channel
/// </summary>
/// <param name="channel"></param>
/// <returns></returns>
public static ChannelData CreateChannel(Test.Module.Channel channel)
{
var isoCode = string.Empty;
var isoChannelName = string.Empty;
string filter = string.Empty;
if ( channel is Test.Module.AnalogInputChannel analog)
{
isoCode = analog.IsoCode;
filter = analog.SoftwareFilter.Replace(" ", "");
isoChannelName = analog.IsoChannelName;
}
var channelData = new ChannelData()
{
ChannelName = isoChannelName,
ChannelNumber = channel.AbsoluteDisplayOrder,
DataCollectionEID = channel.DataCollectionEID,
DataFlag = (DataFlag)channel.DataFlag,
ISOCode = isoCode,
SAEFilterClass = filter,
SetupEID = channel.SetupEID
};
return channelData;
}
}
}

View File

@@ -0,0 +1,57 @@
using System.Collections.Generic;
using System.Text;
namespace DTS.Serialization.Iso.Report
{
/// <summary>
/// this is a class to simplify outputting a summary report
/// http://manuscript.dts.local/f/cases/43495/Add-Summary-report-text-file-in-import-wizard
/// http://manuscript.dts.local/f/cases/43833/SW-Test-Summary-Report-for-data-collection-THF
/// </summary>
public class SummaryReport
{
private readonly List<ChannelData> _channels = new List<ChannelData>();
private const string NUMBER_OF_CHANNELS = "Number of channels";
public string GetLines()
{
var sb = new StringBuilder();
sb.AppendLine($"{NUMBER_OF_CHANNELS} :{_channels.Count:000} / / / / /");
foreach (var channel in _channels)
{
sb.AppendLine(channel.GetLine());
}
return sb.ToString();
}
protected void AddChannels(Test.Module.Channel[] channels)
{
foreach( var channel in channels)
{
_channels.Add(ChannelData.CreateChannel(channel));
}
_channels.Sort((a, b) => a.ChannelNumber.CompareTo(b.ChannelNumber));
}
/// <summary>
/// creates a test summary report given test data
/// </summary>
/// <param name="test"></param>
/// <returns></returns>
public static SummaryReport CreateSummaryReport(Test test)
{
var report = new SummaryReport();
report.AddChannels([.. test.Channels]);
return report;
}
/// <summary>
/// outputs to path given test setup summary
/// can throw exceptions
/// </summary>
/// <param name="path"></param>
/// <param name="summary"></param>
public static void OutputToPath(string path, SummaryReport summary)
{
System.IO.File.WriteAllText(System.IO.Path.Combine(path, "TestNo_FilterList.txt"), summary.GetLines());
}
}
}