/* * 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 { /// /// /// ISO-style representation of a test channel. /// /// public class Channel : Exceptional { /// /// Get/set the data zero offset of the data (in EU). /// public double DataZeroOffsetEu { get { if (!_DataZeroOffsetEu.IsValueInitialized) { return 0; } return _DataZeroOffsetEu.Value; } set => _DataZeroOffsetEu.Value = value; } private readonly Property _DataZeroOffsetEu = new Property( typeof(File).Namespace + ".Iso.File.Test.Channel.DataZeroOffsetEu", 0, false ); /// /// Get/set the number associated with this test object. /// 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 _TestObjectNumber = new Property( typeof(File).Namespace + ".Iso.File.Test.Channel.TestObjectNumber", 0, false ); /// /// Get/set the indicating whether or not errors occurred in /// the capture of this channel data. /// public bool ErrorsOccurred { get { if (!_ErrorsOccurred.IsValueInitialized) { return false; } return _ErrorsOccurred.Value; } set => _ErrorsOccurred.Value = value; } private readonly Property _ErrorsOccurred = new Property( typeof(File).Namespace + ".Iso.File.Test.Channel.ErrorsOccurred", false, false ); /// /// Get/set the name of the channel. /// 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 _Name = new Property( typeof(File).Namespace + ".Iso.File.Test.Channel.Name", null, false ); /// /// Get/set the laboratory code for the channel. /// 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 _LaboratoryCode = new Property( typeof(File).Namespace + ".Iso.File.Test.Channel.LaboratoryCode", null, false ); /// /// Get/set the customer code for the channel. /// 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 _CustomerCode = new Property( typeof(File).Namespace + ".Iso.File.Test.Channel.CustomerCode", null, false ); /// /// Get/set the code for the channel. /// 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 _Code = new Property( typeof(File).Namespace + ".Iso.File.Test.Channel.Code", null, false ); /// /// Get/set the location for the channel. /// public string Location { get { if (!_Location.IsValueInitialized) { return "????"; } return _Location.Value; } set => _Location.Value = value; } private const string LocationLabel = "Location"; private readonly Property _Location = new Property( typeof(File).Namespace + ".Iso.File.Test.Channel.Location", "????", true ); /// /// Get/set the location for the channel. /// public string Dimension { get { if (!_Dimension.IsValueInitialized) { return null; } return _Dimension.Value; } set => _Dimension.Value = value; } private const string DimensionLabel = "Dimension"; private readonly Property _Dimension = new Property( typeof(File).Namespace + ".Iso.File.Test.Channel.Dimension", null, false ); /// /// Get/set the direction for the channel. /// public string Direction { get { if (!_Direction.IsValueInitialized) { return null; } return _Direction.Value; } set => _Direction.Value = value; } private const string DirectionLabel = "Direction"; private readonly Property _Direction = new Property( typeof(File).Namespace + ".Iso.File.Test.Channel.Direction", null, false ); /// /// Get/set the list of s for this test. /// public List ExtraProperties { get => _ExtraProperties.Value; set => _ExtraProperties.Value = value; } private readonly Property> _ExtraProperties = new Property>( typeof(File).Namespace + ".Iso.File.Test.Channel.ExtraProperties", new List(), true ); /// /// Get/set the for the channel. /// public ChannelFilter FilterClass { get { if (!_FilterClass.IsValueInitialized) { return ChannelFilter.Unfiltered; } return _FilterClass.Value; } set => _FilterClass.Value = value; } private readonly Property _FilterClass = new Property( typeof(File).Namespace + ".Iso.File.Test.Channel.FilterClass", ChannelFilter.Unfiltered, false ); /// /// Get/set the for the channel. /// 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 _ChannelFrequencyClass = new Property( typeof(File).Namespace + ".Iso.File.Test.Channel.ChannelFrequencyClass", null, false ); /// /// Get/set the unit for the channel. /// public string Unit { get { if (!_Unit.IsValueInitialized) { return null; } return _Unit.Value; } set => _Unit.Value = value; } private const string UnitLabel = "Unit"; private readonly Property _Unit = new Property( typeof(File).Namespace + ".Iso.File.Test.Channel.Unit", null, false ); /// /// Get/set the reference system for the channel. /// 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 _ReferenceSystem = new Property( typeof(File).Namespace + ".Iso.File.Test.Channel.ReferenceSystem", null, false ); /// /// Get/set the transducer type for the channel. /// 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 _TransducerType = new Property( typeof(File).Namespace + ".Iso.File.Test.Channel.TransducerType", null, false ); /// /// Get/set the transducer id (sensor serial number) for the channel. /// 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 _TransducerId = new Property( typeof(File).Namespace + ".Iso.File.Test.Channel.TransducerId", null, false ); /// /// Get/set the pre-filter type for the channel. /// 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 _PrefilterType = new Property( typeof(File).Namespace + ".Iso.File.Test.Channel.PrefilterType", null, false ); /// /// Get/set the cut-off frequency value for the channel. /// 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 _CutOffFrequency = new Property( 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"; /// /// Get/set the sampling interval for the Test. /// this is the max sample rate between all channels /// public double SamplingIntervalTest { get { if (!_SamplingIntervalTest.IsValueInitialized) { return 0D; } return _SamplingIntervalTest.Value; } set => _SamplingIntervalTest.Value = value; } private readonly Property _SamplingIntervalTest = new Property( typeof(File).Namespace + ".Iso.File.Test.Channel.SamplingIntervalTest", 0.0, false ); /// /// Get/set the sampling interval for the channel. /// 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 _SamplingInterval = new Property( typeof(File).Namespace + ".Iso.File.Test.Channel.SamplingInterval", 0.0, false ); /// /// Get/set the bit resolution for the channel. /// 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 _BitResolution = new Property( typeof(File).Namespace + ".Iso.File.Test.Channel.BitResolution", 0, false ); /// /// Get/set this channel's comment . /// public string Comments { get { if (!_Comments.IsValueInitialized) { return null; } return _Comments.Value; } set => _Comments.Value = value; } private readonly Property _Comments = new Property( typeof(File).Namespace + ".Iso.File.Test.Channel.Comments", null, false ); /// /// Get/set the time of first sample for the channel. /// 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 _TimeOfFirstSample = new Property( typeof(File).Namespace + ".Iso.File.Test.Channel.TimeOfFirstSample", 0.0, false ); /// /// Get/set the number of samples on the channel. /// 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 + "\"" : ""), ex); } } } private const string NumberOfSamplesLabel = "Number of samples"; /// /// Get/set this channel's offset post test . /// 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 _OffsetPostTest = new Property( 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"; /// /// Get/set the first global maximum for the channel. /// 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 + "\"" : ""), 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; /// /// Get/set the time of maximum value for the channel. /// 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; /// /// Get/set the first global minimum for the channel. /// 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 + "\"" : ""), 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; /// /// Get/set the time of minimum value for the channel. /// 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; /// /// Get/set the time of minimum value for the channel. /// 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; /// /// Get/set the time of minimum value for the channel. /// 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 _Samples = new Property( typeof(File).Namespace + ".Iso.File.Test.Channel.Samples", null, false ); /// /// Generate a string representation for this object. /// /// /// /// A representation of this object. /// /// 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); } } } } } }