/* * DTS.Slice.Control.Event.Module.Channel.cs * * Copyright © 2009 * Diversified Technical Systems, Inc. * All Rights Reserved */ using System; using System.Collections.Generic; using DTS.DASLib.Service; using DTS.Common.DAS.Concepts.DAS.Channel; using DTS.Common.DAS.Concepts; using DTS.Common.DASResource; using DTS.Common.Enums; using DTS.Common.Enums.Sensors; using DTS.Common.SerializationPlus; using DTS.Common.Utilities; using DTS.Common.Utilities.DotNetProgrammingConstructs; using DTS.Common.Interface.DASFactory.Diagnostics; namespace DTS.Slice.Control { // *** see DTS.Slice.Control.Event.cs *** public partial class Event { // *** see DTS.Slice.Control.Event.Module.cs *** public partial class Module { /// /// Representation of the DTS.Slice.Control.Event.Module.Channel class. /// public abstract partial class Channel : Exceptional, IFilterable, IDisposable { public void Dispose() { } /// /// Initialize an instance of the Event.Module.Channel class. Specifically, perform initializations /// that will be required no matter what constructor parameter signature is invoked. /// private Channel() { try { //this.InitializeReviewableAttributes(this.ReviewableAttributes); } catch (System.Exception ex) { throw new Exception("encountered problem constructing channel", ex); } } /// /// Initialize an instance of the DTS.Slice.Control.Event.Module.Channel class. /// /// /// /// The that contains this channel. /// /// /// /// The unique "absolute" number of the channel with respect to all other channels /// on all other DASes in the system. /// /// protected Channel(Module parentModule, int absoluteNumber) : this() { try { var enumerabilityGrabber = new EnumerabilityAttributeCoder(); ParentModule = parentModule; AbsoluteNumber = absoluteNumber; foreach (int enumValue in Enum.GetValues(typeof(ChannelFilter))) if (enumerabilityGrabber.DecodeAttributeValue((ChannelFilter)enumValue)) AvailableFilters.Add( new SaeJ211Filter((ChannelFilter)enumValue) ); CurrentFilter = AvailableFilters[0]; } catch (System.Exception ex) { throw new Exception("encountered problem constructing " + GetType().FullName, ex); } } /// /// Initialize an instance of the DTS.Slice.Control.Event.Module.Channel class. /// /// /// /// The object with which to initialize /// this object. /// /// /// /// The that contains this channel. /// /// /// /// The unique "absolute" number of the channel with respect to all other channels /// on all other DASes in the system. /// /// public Channel(DASChannel channel, Module parentModule, int absoluteNumber) : this(parentModule, absoluteNumber) { try { // // Initialize basic channel properties with any values we can find // in the specified channel object. // Number = channel.ModuleChannelNumber; Start = channel.EventStartTime; AbsoluteDisplayOrder = channel.AbsoluteDisplayOrder; UnitConversion = channel.UnitConverision; AtCapacity = channel.AtCapacity; CapacityOutputIsBasedOn = channel.CapacityOutputIsBasedOn; SensitivityUnits = channel.SensitivityUnits; IsoChannelName = channel.IsoChannelName; UserCode = channel.UserCode; UserChannelName = channel.UserChannelName; LinearSensorCalibration = channel.LinearSensorCalibration; } catch (System.Exception ex) { throw new Exception("encountered problem constructing " + GetType().FullName, ex); } } /// /// Initialize an instance of the DTS.Slice.Control.Event.Module.Channel class. /// /// /// /// The object with which to initialize /// this object. /// /// /// /// The that contains this channel. /// /// /// /// The unique "absolute" number of the channel with respect to all other channels /// on all other DASes in the system. /// /// public Channel(Serialization.Test.Module.Channel channel, Module parentModule, int absoluteNumber) : this(parentModule, absoluteNumber) { try { // // Initialize basic channel properties with any values we can find // in the specified channel object. // AbsoluteDisplayOrder = channel.AbsoluteDisplayOrder; Multiplier = channel.Data.Multiplier; UnitConversion = channel.Data.UnitConversion; UserOffsetEU = channel.Data.UserOffsetEU; Number = channel.Number; Start = channel.Start; try { if (channel.TimeOfFirstSampleValid) { TimeOfFirstSampleSec = channel.TimeOfFirstSampleSec; } } catch { } if (channel.IsLastCalibrationDateValid) { LastCalibrationDate = channel.LastCalibrationDate; } if (channel.IsCalDueDateValid) { CalDueDate = channel.CalDueDate; } if (channel.IsSensorIDValid) { SensorID = channel.SensorID; } if (channel.IsOffsetToleranceLowMvValid) { OffsetToleranceLowMv = channel.OffsetToleranceLowMv; } if (channel.IsOffsetToleranceHighMvValid) { OffsetToleranceHighMv = channel.OffsetToleranceHighMv; } if (channel.IsUserCodeValid) { UserCode = channel.UserCode; } if (channel.IsUserChannelNameValid) { UserChannelName = channel.UserChannelName; } if (channel.IsIsoChannelNameValid) { IsoChannelName = channel.IsoChannelName; } IsSubsampled = channel.IsSubsampled; UnsubsampledSampleRateHz = channel.UnsubsampledSampleRateHz; IsSupersampled = channel.IsSupersampled; UseEUScaler = channel.Data.UseEUScaleFactors; UnsupersampledSampleRateHz = channel.UnsupersampledSampleRateHz; try { if (channel.PersistentChannelInfo == null) { UnfilteredData = channel.TDASPersistentChannelInfo; } else { UnfilteredData = channel.PersistentChannelInfo; //channel.Data; } } catch (System.Exception) { throw new System.IO.InvalidDataException("Invalid or corrupt data file, channel: " + channel.ChannelDescriptionString + " - " + channel.ChannelName2); } // xxx proposal: this.UnfilteredData = ( null != channel.PersistentChannelInfo ? channel.PersistentChannelInfo : channel.Data ); // If everything uses persistent channel info, that's going to break the data viewer completely in the short term, unless we either // change the data viewer to be clever about extracting something displayable or provide the "classic" data structure through the // "UnfilteredData" property somehow. } catch (System.IO.InvalidDataException) { throw; } catch (System.Exception ex) { throw new Exception("encountered problem constructing " + GetType().FullName, ex); } } /* /// /// Get "reviewable" (attributes that can be automatically converted to strings and displayed /// on the review tab) for this channel. /// public List ReviewableAttributes { get { return _ReviewableAttributes.Value; } private set { _ReviewableAttributes.Value = value; } } private Property> _ReviewableAttributes = new Property>( typeof(Event.Module.Channel).Namespace + ".Event.Module.Channel.ReviewableAttributes", new List(), true ); */ /* /// /// Method to allow derived classes to initialize their own reviewable attributes. /// /// /// /// The or s to be initialized. /// /// protected abstract void InitializeReviewableAttributes(List reviewableAttributes); */ /// /// Our data display unit options. /// public enum DataDisplayUnits { Adc, Mv, Eu } /// /// The that contains this channel. /// public Module ParentModule { get => _ParentModule.Value; private set => _ParentModule.Value = value; } private readonly Property _ParentModule = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.ParentModule", null, false ); /// /// Get the data scaler for this channel. /// public DataScaler Scaler => _Scaler.Value; private readonly Property _Scaler = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.Scaler", new DataScaler(), true ); /// /// Get/set the switch to enable/disable filter caching. /// public bool UseFilterCaching { //for now NEVER cache /*get { return _UseFilterCaching.Value; } set { if (false == (_UseFilterCaching.Value = value)) { // // If we disable filter caching on the fly, make sure the caches are cleared. // _Data = null; _DataEu = null; _DataMv = null; lock (previouslyFilteredDataLock) { _previouslyFilteredData.Clear(); } } }*/ get => false; set { } } /*private Property _UseFilterCaching = new Property( typeof(Event.Module.Channel).Namespace + ".Event.Module.Channel.UseFilterCaching", true, true ); */ /// /// Get/set a user-readable description of this channel object; intended to be /// the UI representation of this object. Literally, what the API channel's /// ToString method said it was. /// public string ChannelDescriptionString { get => _ChannelDescriptionString.Value; set => _ChannelDescriptionString.Value = value; } private readonly Property _ChannelDescriptionString = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.ChannelDescriptionString", null, false ); /// /// Get/set the manufacturer of this channel object's sensor. /// public string Manufacturer { get => _Manufacturer.Value; set => _Manufacturer.Value = value; } private readonly Property _Manufacturer = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.Manufacturer", null, false ); /// /// Get/set the manufacturer of this channel object's sensor. /// public string Model { get => _Model.Value; set => _Model.Value = value; } private readonly Property _Model = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.Model", null, false ); public string OriginalChannelName { get => _OriginalChannelName.Value; set => _OriginalChannelName.Value = value; } private readonly Property _OriginalChannelName = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.OriginalChannelName", "", true); public string ChannelName2 { get => _ChannelName2.Value; set => _ChannelName2.Value = value; } private readonly Property _ChannelName2 = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.ChannelName2", "", true); private readonly Property _HardwareChannelName = new Property( typeof(Channel).Name + ".Event.Module.Channel.HardwareChannelName", "", true); public string HardwareChannelName { get => _HardwareChannelName.Value; set => _HardwareChannelName.Value = value; } private readonly Property _ChannelId = new Property( typeof(Channel).Name + ".Event.Module.Channel.ChannelId", "", true); /// /// refers to a unique id for a logical channel in the test /// for now this is using TestObjectChannel.GetId() /// which is in the form of TestObjectSerial_ChannelType_ChannelId /// public string ChannelId { get => _ChannelId.Value; set => _ChannelId.Value = value; } private readonly Property _Sensor = new Property( typeof(Channel).Name + ".Event.Module.Channel.Sensor", "", true); /// /// refers to a unique sensor serial number for a logical channel in the test /// public string Sensor { get => _Sensor.Value; set => _Sensor.Value = value; } private readonly Property _ChannelGroupName = new Property( typeof(Channel).Name + ".Event.Module.Channel.ChannelGroupName", "", true); /// /// refers to the Group for a logical channel in the test /// public string ChannelGroupName { get => _ChannelGroupName.Value ?? ""; set => _ChannelGroupName.Value = value; } private readonly Property _SetupEID = new Property( typeof(Channel).Name + ".Event.Module.Channel.SetupEID", string.Empty, true); /// /// The electronic id for a channel at test setup time /// public string SetupEID { get => _SetupEID.Value ?? string.Empty; set => _SetupEID.Value = value; } private readonly Property _DataCollectionEID = new Property( typeof(Channel).Name + ".Event.Module.Channel.DataCollectionEID", string.Empty, true); /// /// the electronic id on a channel at run time /// public string DataCollectionEID { get => _DataCollectionEID.Value ?? string.Empty; set => _DataCollectionEID.Value = value; } public string UserValue1 { get => _userValue1.Value; set => _userValue1.Value = value; } private readonly Property _userValue1 = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.UserValue1", "", true); public string UserValue2 { get => _userValue2.Value; set => _userValue2.Value = value; } private readonly Property _userValue2 = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.UserValue2", "", true); public string UserValue3 { get => _userValue3.Value; set => _userValue3.Value = value; } private readonly Property _userValue3 = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.UserValue3", "", true); /// /// Get/set the channel's ordinal number within the stack. /// public int Number { get => _Number.Value; set => _Number.Value = value; } private readonly Property _Number = new Property("DTS.Control.Event.Module.Channel.Number", -1, false); /// /// Get the channel's ordinal number within the entire system. /// public int AbsoluteNumber { get => _AbsoluteNumber.Value; private set => _AbsoluteNumber.Value = value; } private readonly Property _AbsoluteNumber = new Property( typeof(Channel).FullName + ".AbsoluteNumber", -1, false ); public bool TimeOfFirstSampleSecValid => _TimeOfFirstSampleSec.IsInitialized; /// /// The time of the first sample. Will be needed if the time /// scale can't be determined by the trigger sample number (possible, as it's an unsigned /// value and an all-positive ROI that doesn't contain T0 would need it to be negative). /// public double TimeOfFirstSampleSec { get => _TimeOfFirstSampleSec.Value; set => _TimeOfFirstSampleSec.Value = value; } private readonly Property _TimeOfFirstSampleSec = new Property( typeof(Channel).FullName + ".TimeOfFirstSample", 0.0, false ); /// /// Get/set the start time for this channel. /// public DateTime Start { get => _Start.Value; set => _Start.Value = value; } private readonly Property _Start = new Property("DTS.Control.Event.Module.Channel.Start", DateTime.Now, false); public LinkedList PartialUnfilteredData = null; // Method for creating channel files directly to disk. // Change that linked list class to something that will handle this... // I think what we need to do instead is to change the class/data structure that represents // the channel data into an object that maybe double passes the reference, or derives from the // memory-mapped file objecct, but it can also have extra methods and throw an exception if we // try to access it before it's been properly initialized. /// /// Get/set the data value list for this channel. /// public List UnfilteredData { get => _UnfilteredData.Value; set { try { // Reset unfiltered data caches. _UnfilteredData.Value = value; _UnfilteredDataEu = null; _UnfilteredDataMv = null; _DataRangeAdc.UnInitialize(); //_DataRangeEu .UnInitialize( ); // *** not currently cached. //_DataRangeMv .UnInitialize( ); // *** not currently cached. // Reset filtered data caches. _Data = null; _DataEu = null; _DataMv = null; lock (previouslyFilteredDataLock) { _previouslyFilteredData.Clear(); } // Update the data count. if (value is Serialization.SliceRaw.File.PersistentChannel persistentChannel) DataCount = persistentChannel.Count; else if (value is Serialization.TDAS.File.PersistentChannel tdasPersistentChannel) DataCount = tdasPersistentChannel.Count; else DataCount = value.Count; } catch (System.Exception ex) { throw new Exception("encountered problem setting unfiltered data", ex); } } } private readonly Property> _UnfilteredData = new Property>("DTS.Control.Event.Module.Channel.Data", null, false); public List UnfilteredAlternateData { get => _UnfilteredAlternateData.Value; set { try { // Reset unfiltered data caches. _UnfilteredAlternateData.Value = value; } catch (System.Exception ex) { throw new Exception("encountered problem setting unfiltered alternate data", ex); } } } private readonly Property> _UnfilteredAlternateData = new Property>("DTS.Control.Event.Module.Channel.AlternateData", null, false); /// /// Get the filtered double-converted data for this channel. /// public List Data { get { try { if (UseFilterCaching) { if (null == _Data) return _Data = new List(GetDataFilteredBy(CurrentFilter, DataDisplayUnits.Adc)); return _Data; } return new List(GetDataFilteredBy(CurrentFilter, DataDisplayUnits.Adc)); } catch (System.Exception ex) { throw new Exception("encountered problem getting filtered data", ex); } } } private List _Data = null; /// /// Get the data count for this channel. /// public int DataCount { get; private set; } public abstract List GetUnfilteredDataEu(); public abstract List GetUnfilteredDataMV(); /// /// Get an EU-scaled version of the data . /// public List UnfilteredDataEu { get { try { // // If scaled data has yet to be computed, then compute, cache and return it. // Otherwise just return the cached version. // if (null == _UnfilteredDataEu) { if (UnfilteredData is ILargeDataAware largeDataAware) { if (!largeDataAware.IsDataArraySized) { throw new Serialization.SliceRaw.File.PersistentChannel.DataTooBigForArrayException("Data is too big to be viewed or filtered."); } } _UnfilteredDataEu = GetUnfilteredDataEu(); } return _UnfilteredDataEu; } catch (System.Exception ex) { throw new Exception("encountered problem getting EU-scaled data", ex); } } } private List _UnfilteredDataEu = null; protected List UnfilteredDataMV { get { try { // // If scaled data has yet to be computed, then compute, cache and return it. // Otherwise just return the cached version. // if (null == _UnfilteredDataMV) { if (UnfilteredData is ILargeDataAware largeDataAware) { if (!largeDataAware.IsDataArraySized) { throw new Serialization.SliceRaw.File.PersistentChannel.DataTooBigForArrayException("Data is too big to be viewed or filtered."); } } _UnfilteredDataMV = GetUnfilteredDataMV(); } return _UnfilteredDataMV; } catch (System.Exception ex) { throw new Exception("encountered problem getting EU-scaled data", ex); } } } private List _UnfilteredDataMV = null; private List _DataADC = null; public List DataADC { get { try { // // If scaled data has yet to be computed, then compute, cache and return it. // Otherwise just return the cached version. // if (null == _DataADC) { if (UnfilteredData is ILargeDataAware largeDataAware) if (!largeDataAware.IsDataArraySized) throw new Serialization.SliceRaw.File.PersistentChannel.DataTooBigForArrayException("Data is too big to be viewed or filtered."); var persistentUnfilteredData = UnfilteredData as Serialization.SliceRaw.File.PersistentChannel; //double scalingFactor = AdcToMvScalingFactor; _DataADC = new List(); var dataCount = persistentUnfilteredData.Count; for (var i = 0; i < dataCount; i++) _DataADC.Add(persistentUnfilteredData[i]); } return _DataADC; } catch (System.Exception ex) { throw new Exception("encountered problem getting ADC data", ex); } } } public virtual bool SupportsEU => true; public virtual bool SupportsADC => true; public virtual bool SupportsmV => true; /// /// Get/set the filtered EU data for this channel. /// public IList DataEu { get { try { if (UseFilterCaching) { if (null == _DataEu) return _DataEu = new List(GetDataFilteredBy(CurrentFilter, DataDisplayUnits.Eu)); return _DataEu; } return new List(GetDataFilteredBy(CurrentFilter, DataDisplayUnits.Eu)); } catch (System.Exception ex) { throw new Exception("encountered problem getting filtered EU data", ex); } } } private List _DataEu = null; /// /// Get an MV-scaled version of the data list. /// public List UnfilteredDataMv { get { try { // // If scaled data has yet to be computed, then compute, cache and return it. // Otherwise just return the cached version. // if (null == _UnfilteredDataMv) { if (UnfilteredData is ILargeDataAware largeDataAware) if (!largeDataAware.IsDataArraySized) throw new Serialization.SliceRaw.File.PersistentChannel.DataTooBigForArrayException("Data is too big to be viewed or filtered."); if (UnfilteredData is Serialization.SliceRaw.File.PersistentChannel persistentUnfilteredData) { _UnfilteredDataMv = new List(); var dataCount = persistentUnfilteredData.Count; for (var i = 0; i < dataCount; i++) { _UnfilteredDataMv.Add(Scaler.GetMv(persistentUnfilteredData[i])); } } else if (UnfilteredData is Serialization.TDAS.File.PersistentChannel tdasUnfilteredData) { _UnfilteredDataMv = new List(); var dataCount = tdasUnfilteredData.Count; for (var i = 0; i < dataCount; i++) { _UnfilteredDataMv.Add(Scaler.GetMv(tdasUnfilteredData[i])); } } } return _UnfilteredDataMv; } catch (System.Exception ex) { throw new Exception("encountered problem getting MV-scaled data", ex); } } } private List _UnfilteredDataMv = null; /// /// Get/set the filtered MV data for this channel. /// public List DataMv { get { try { if (UseFilterCaching) { if (null == _DataMv) return _DataMv = new List(GetDataFilteredBy(CurrentFilter, DataDisplayUnits.Mv)); return _DataMv; } return new List(GetDataFilteredBy(CurrentFilter, DataDisplayUnits.Mv)); } catch (System.Exception ex) { throw new Exception("encountered problem getting filtered MV data", ex); } } } private List _DataMv = null; /// /// Get/set the ADC->MV scale factor for this channel. /// public double ScaleFactorMv { get => Scaler.GetScaleFactorMv(); set { try { Scaler.SetScaleFactorMv(value); _DataEu = null; lock (previouslyFilteredDataLock) { _previouslyFilteredData.Clear(); } _UnfilteredDataEu = null; } catch (System.Exception ex) { throw new Exception("encountered problem setting " + typeof(Channel).Namespace + ".Event.Module.Channel.ScaleFactorMv property value", ex); } } } public double ScaleFactorEU { get => Scaler.GetScaleFactorEU(); set { try { Scaler.SetScaleFactorEU(value); _DataEu = null; lock (previouslyFilteredDataLock) { _previouslyFilteredData.Clear(); } _UnfilteredDataEu = null; } catch (System.Exception ex) { throw new Exception("encountered problem setting " + typeof(Channel).Namespace + ".Event.Module.Channel.ScaleFactorEU property value", ex); } } } public double UserOffsetEU { get => Scaler.UserOffsetEU; set { Scaler.UserOffsetEU = value; _DataEu = null; lock (previouslyFilteredDataLock) { _previouslyFilteredData.Clear(); } _UnfilteredDataEu = null; } } public double Multiplier { get => Scaler.Multiplier; set => Scaler.Multiplier = value; } public double UnitConversion { get => Scaler.UnitConversion; set => Scaler.UnitConversion = value; } public bool AtCapacity { get => Scaler.BasedOnOutputAtCapacity; set => Scaler.BasedOnOutputAtCapacity = value; } public double CapacityOutputIsBasedOn { get => Scaler.CapacityOutputIsBasedOn; set => Scaler.CapacityOutputIsBasedOn = value; } public SensorConstants.SensUnits SensitivityUnits { get => Scaler.SensitivityUnits; set => Scaler.SensitivityUnits = value; } /// /// Get/set the sensitivity mV/EU factor for this channel. /// public double MvPerEu { set { try { Scaler.SetMvPerEu(value); } catch (System.Exception ex) { throw new Exception("encountered problem setting " + typeof(Channel).Namespace + ".Event.Module.Channel.MvPerEu property value", ex); } } } /// /// putting this in a separate function to force that MvPerEu is not being used directly in calcuations /// /// public double GetMvPerEu() { return Scaler.GetMvPerEu(); } public double GetScaleFactorMv() { return Scaler.GetScaleFactorMv(); } /// /// Get value indicating whether or not the specified channel is configured. /// public abstract bool IsConfigured { get; set; } /// /// Get the actual available maximum Adc range based on datum bit resolution. /// public double ActualMaxRangeAdc { get { try { return short.MaxValue; } catch (System.Exception ex) { throw new Exception("encountered problem calculating actual max ADC range", ex); } } } /// /// Get the actual available minimum ADC range based on datum bit resolution. /// public double ActualMinRangeAdc { get { try { return short.MinValue; } catch (System.Exception ex) { throw new Exception("encountered problem calculating actual min ADC range", ex); } } } /// /// Get the actual available maximum EU range based on scaling factor and bit resolution. /// public abstract double ActualMaxRangeEu { get; } /// /// Get the actual available minimum EU range based on scaling factor and bit resolution. /// public abstract double ActualMinRangeEu { get; } public abstract double DesiredRangeEU { get; } public abstract double SensorCapacityEU { get; } /// /// Get the actual available maximum MV range based on scaling factor and bit resolution. /// public virtual double ActualMaxRangeMv { get { try { return (Scaler.GetAdcToMvScalingFactor() >= 0) ? Scaler.GetMv(ActualMaxRangeAdc) : Scaler.GetMv(ActualMinRangeAdc); } catch (System.Exception ex) { throw new Exception("encountered problem calculating actual max MV range", ex); } } } /// /// Get the actual available minimum MV range based on scaling factor and bit resolution. /// public virtual double ActualMinRangeMv { get { try { return (Scaler.GetAdcToMvScalingFactor() >= 0) ? Scaler.GetMv(ActualMinRangeAdc) : Scaler.GetMv(ActualMaxRangeAdc); } catch (System.Exception ex) { throw new Exception("encountered problem calculating actual min MV range", ex); } } } /// /// Compute data min and max for this channel. /// /// /// /// The data min to be populated with /// the min result of this method. /// /// /// /// The data max to be populated with /// the max result of this method. /// /// private void ComputeDataMinMaxAdc(Property dataMinAdc, Property dataMaxAdc) { try { if (UnfilteredData is Serialization.TDAS.File.PersistentChannel) //temp { ComputeTDASDataMinMaxAdc(dataMinAdc, dataMaxAdc); } else { var dataCount = (UnfilteredData is Serialization.SliceRaw.File.PersistentChannel persistentChannel) ? persistentChannel.Count // use "persistent channel" count : UnfilteredData.Count; if (dataCount <= 0) throw new Exception("channel has no data"); { // Find the max and min in raw ADC. double min, max; if (!(UnfilteredData is Serialization.SliceRaw.File.PersistentChannel data)) throw new ApplicationException("attempting to use channel data object as memory-mapped file, but it apparently is not one"); min = max = data[0]; for (var i = 1; i < dataCount; i++) { min = Math.Min(min, data[i]); max = Math.Max(max, data[i]); } dataMinAdc.Value = min; dataMaxAdc.Value = max; } } } catch (System.Exception ex) { throw new Exception("encountered problem computing channel data min/max", ex); } } private void ComputeTDASDataMinMaxAdc(Property dataMinAdc, Property dataMaxAdc) { try { var dataCount = (UnfilteredData is Serialization.TDAS.File.PersistentChannel persistentChannel) ? persistentChannel.Count // use "persistent channel" count : UnfilteredData.Count; if (dataCount <= 0) throw new Exception("channel has no data"); { // Find the max and min in raw ADC. double min, max; if (!(UnfilteredData is Serialization.TDAS.File.PersistentChannel data)) throw new ApplicationException("attempting to use channel data object as memory-mapped file, but it apparently is not one"); min = max = data[0]; for (var i = 1; i < dataCount; i++) { min = Math.Min(min, data[i]); max = Math.Max(max, data[i]); } dataMinAdc.Value = min; dataMaxAdc.Value = max; } } catch (System.Exception ex) { throw new Exception("encountered problem computing channel data min/max", ex); } } /// /// Compute the min and max values in the given data vector. /// /// /// /// Returns the minimum data value in the specified data vector. /// /// /// /// Returns the maximum data value in the specified data vector. /// /// /// /// The array of s to be scoured for min and max values. /// /// private void ComputeDataMinMax(out double dataMin, out double dataMax, double[] data) { try { if (null == data) throw new ArgumentException("cannot process null data reference"); if (data.Length <= 0) throw new ArgumentException("cannot process empty data vector"); dataMin = dataMax = data[0]; for (var i = 0; i < data.Length; i++) { dataMin = Math.Min(dataMin, data[i]); dataMax = Math.Max(dataMax, data[i]); } } catch (System.Exception ex) { throw new Exception("encountered problem computing data vector min/max", ex); } } /// /// Get the data min in ADC. /// public double DataMinAdc { get { try { if (!_DataMinAdc.IsInitialized) ComputeDataMinMaxAdc(_DataMinAdc, _DataMaxAdc); return _DataMinAdc.Value; } catch (System.Exception ex) { throw new Exception("encountered problem getting " + typeof(Channel).Namespace + ".Event.Module.Channel.DataMinAdc", ex); } } } private readonly Property _DataMinAdc = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.DataMinAdc", 0.0, false ); /// /// Get the data min in EU. /// public abstract double DataMinEu { get; } /// /// Get the data min in MV. /// public double DataMinMv => (Scaler.GetAdcToMvScalingFactor() >= 0) ? Scaler.GetMv(DataMinAdc) : Scaler.GetMv(DataMaxAdc); /// /// Get the data max in ADC. /// public double DataMaxAdc { get { try { if (!_DataMaxAdc.IsInitialized) ComputeDataMinMaxAdc(_DataMinAdc, _DataMaxAdc); return _DataMaxAdc.Value; } catch (System.Exception ex) { throw new Exception("encountered problem getting " + typeof(Channel).Namespace + ".Event.Module.Channel.DataMaxAdc", ex); } } } private readonly Property _DataMaxAdc = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.DataMaxAdc", 0.0, false ); /// /// Get the data max in EU. /// public abstract double DataMaxEu { get; } /// /// Populate the specified filter-index'd dictionaries with the min/max values for the /// specified filter setting. /// /// /// /// The -indexed Dictionary of /// data min values. /// /// /// /// The -indexed Dictionary of /// data max values. /// /// /// /// The to be applied to the the channel's data prior to /// the min/max calculation. /// /// private void PopulateFilteredMinMaxValues(IDictionary filteredMins, IDictionary filteredMaxs, ChannelFilter filter) { try { ComputeDataMinMax(out double min, out double max, CurrentFilter.Apply(this, DataDisplayUnits.Eu, Serialization.File.UseLegacyTDCSoftwareFiltering)); filteredMins[CurrentFilter.CutoffFrequencyHz] = min; filteredMaxs[CurrentFilter.CutoffFrequencyHz] = max; } catch (System.Exception ex) { throw new Exception("encountered problem propulating filtered min/max values", ex); } } /// /// Get the minimum EU data value for the current filtering. /// public double DataMinFilteredEu { get { try { if (!_DataMinFilteredEu.Keys.Contains(CurrentFilter.CutoffFrequencyHz)) PopulateFilteredMinMaxValues(_DataMinFilteredEu, _DataMaxFilteredEu, CurrentFilter.Type); return _DataMinFilteredEu[CurrentFilter.CutoffFrequencyHz]; } catch (System.Exception ex) { throw new Exception( "encountered problem getting min filtered EU on DAS: " + ((null != ParentModule && null != ParentModule.DasSerialNumber) ? ParentModule.DasSerialNumber : "") + ", Channel: " + Number.ToString(), ex ); } } } private readonly IDictionary _DataMinFilteredEu = new Dictionary(); /// /// Get the maximum EU data value for the current filtering. /// public double DataMaxFilteredEu { get { try { if (!_DataMaxFilteredEu.Keys.Contains(CurrentFilter.CutoffFrequencyHz)) PopulateFilteredMinMaxValues(_DataMinFilteredEu, _DataMaxFilteredEu, CurrentFilter.Type); return _DataMaxFilteredEu[CurrentFilter.CutoffFrequencyHz]; } catch (System.Exception ex) { throw new Exception( "encountered problem getting max filtered EU on DAS: " + ((null != ParentModule && null != ParentModule.DasSerialNumber) ? ParentModule.DasSerialNumber : "") + ", Channel: " + Number.ToString(), ex ); } } } private readonly IDictionary _DataMaxFilteredEu = new Dictionary(); /// /// Get the data max in MV. /// public double DataMaxMv => (Scaler.GetAdcToMvScalingFactor() >= 0) ? Scaler.GetMv(DataMaxAdc) : Scaler.GetMv(DataMinAdc); /// /// Get the data range of this channel in ADC. /// public double DataRangeAdc { get { try { if (!_DataRangeAdc.IsInitialized) return _DataRangeAdc.Value = DataMaxAdc - DataMinAdc; return _DataRangeAdc.Value; } catch (System.Exception ex) { throw new Exception("encountered problem getting " + typeof(Channel).Namespace + ".Event.Module.Channel.DataRangeAdc", ex); } } } private readonly Property _DataRangeAdc = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.DataRangeAdc", 0.0, false ); /// /// Get the data range in EU. /// public abstract double DataRangeEu { get; } /// /// Get the data range in MV. /// public double DataRangeMv => Math.Abs(Scaler.GetMv(DataRangeAdc)); /// /// Get the data range/2 of this channel in ADC. /// public double DataHalfRangeValueAdc { get { try { if (!_DataHalfRangeValueAdc.IsInitialized) return _DataHalfRangeValueAdc.Value = (DataMaxAdc + DataMinAdc) / 2; return _DataHalfRangeValueAdc.Value; } catch (System.Exception ex) { throw new Exception("encountered problem getting " + typeof(Channel).Namespace + ".Event.Module.Channel.DataMeanAdc", ex); } } } private readonly Property _DataHalfRangeValueAdc = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.DataHalfRangeValueAdc", 0.0, false ); /// /// Get the data range/2 in EU. /// public abstract double DataHalfRangeValueEu { get; } /// /// Get the data range/2 in MV. /// public double DataHalfRangeValueMv => Scaler.GetMv(DataHalfRangeValueAdc); /// /// Get/set noise as percentage of full scale value for this channel. /// public double NoiseAsPercentageOfFullScale { get => _NoiseAsPercentageOfFullScale.Value; set => _NoiseAsPercentageOfFullScale.Value = value; } private readonly Property _NoiseAsPercentageOfFullScale = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.NoiseAsPercentageOfFullScale", 0.0, false ); /// /// Get the pre-test zero level (in ADC). /// public short PreTestZeroLevelAdc { get => _PreTestZeroLevelAdc.Value; set => _PreTestZeroLevelAdc.Value = value; } private readonly Property _PreTestZeroLevelAdc = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.PreTestZeroLevelAdc", 0, false ); //zeroMvInADC public short ZeroMvInADC { get => _ZeroMvInADC.Value; set => _ZeroMvInADC.Value = value; } private readonly Property _ZeroMvInADC = new Property( typeof(Channel).Name + ".Event.Module.Channel.ZeroMvInADC", 0, false ); /// /// Window Average ADC is the average ADC over the zeroing window specified for the channel /// short.MinValue indicates an invalid or uninitialized value /// public short WindowAverageADC { get => _WindowAverageADC.Value; set => _WindowAverageADC.Value = value; } private readonly Property _WindowAverageADC = new Property( typeof(Channel).Name + ".Event.Module.Channel.WindowAverageADC", short.MinValue, false ); /// /// Get the pre-test zero level (in ADC). /// public double PreTestZeroLevelMv { get { if (_PreTestZeroLevelMv.IsValueInitialized) { return _PreTestZeroLevelMv.Value; } return 0D; } set => _PreTestZeroLevelMv.Value = value; } private readonly Property _PreTestZeroLevelMv = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.PreTestZeroLevelMv", 0D, true ); public int RemovedADC { get { if (_removedADC.IsValueInitialized) { return _removedADC.Value; } return 0; } set { _removedADC.Value = value; Scaler.SetRemovedADC(value); } } private readonly Property _removedADC = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.RemovedADC", 0, true ); public int RemovedInternalADC { get { if (_removedInternalADC.IsValueInitialized) { return _removedInternalADC.Value; } return 0; } set { _removedInternalADC.Value = value; Scaler.SetRemovedInternalADC(value); } } private readonly Property _removedInternalADC = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.RemovedInternalADC", 0, true ); /// /// the order of this channel among all channels when displaying channels /// AbsoluteNumber on the other hand refers to physical order /// -1 is an uninitialized value, which means channels will be sorted by AbsoluteNumber instead /// public int AbsoluteDisplayOrder { get { if (_absoluteDisplayOrder.IsValueInitialized) { return _absoluteDisplayOrder.Value; } return -1; } set => _absoluteDisplayOrder.Value = value; } private readonly Property _absoluteDisplayOrder = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.AbsoluteDisplayOrder", -1, true); /// /// Get data zero level counts. /// public abstract short DataZeroLevelAdc { get; } /// /// Get/Set channel Last Calibration Date /// public DateTime LastCalibrationDate { get => _LastCalibrationDate.Value; set => _LastCalibrationDate.Value = value; } private readonly Property _LastCalibrationDate = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.LastCalibrationDate", (DateTime)System.Data.SqlTypes.SqlDateTime.MinValue, true ); public bool IsLastCalibrationDateValid => _LastCalibrationDate.IsInitialized; /// /// Get/Set channel Last Calibration Date /// public DateTime CalDueDate { get => _CalDueDate.Value; set => _CalDueDate.Value = value; } private readonly Property _CalDueDate = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.CalDueDate", (DateTime)System.Data.SqlTypes.SqlDateTime.MinValue, true ); public bool IsCalDueDateValid => _CalDueDate.IsInitialized; public string SensorID { get => _SensorID.Value; set => _SensorID.Value = value; } private readonly Property _SensorID = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.SensorID", "", true ); public bool IsSensorIDValid => _SensorID.IsInitialized; public double OffsetToleranceLowMv { get => _offsetToleranceLowMv.Value; set => _offsetToleranceLowMv.Value = value; } private readonly Property _offsetToleranceLowMv = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.OffsetToleranceLowMv", 0D, true ); public bool IsOffsetToleranceLowMvValid => _offsetToleranceLowMv.IsInitialized; public double OffsetToleranceHighMv { get => _offsetToleranceHighMv.Value; set => _offsetToleranceHighMv.Value = value; } private readonly Property _offsetToleranceHighMv = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.OffsetToleranceHighMv", 0D, true ); public bool IsOffsetToleranceHighMvValid => _offsetToleranceHighMv.IsInitialized; public string IsoChannelName { get => _isoChannelName.Value; set => _isoChannelName.Value = value; } private readonly Property _isoChannelName = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.IsoChannelName", "", true ); public bool IsIsoChannelNameValid => _isoChannelName.IsInitialized; public string UserCode { get => _userCode.Value; set => _userCode.Value = value; } private readonly Property _userCode = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.UserCode", "", true ); public bool IsUserCodeValid => _userCode.IsInitialized; public string UserChannelName { get => _userChannelName.Value; set => _userChannelName.Value = value; } private readonly Property _userChannelName = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.UserChannelName", "", true ); public string LinearSensorCalibration { get => _linearSensorCalibration.Value; set => _linearSensorCalibration.Value = value; } private readonly Property _linearSensorCalibration = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.LinearSensorCalibration", "", true ); public bool IsUserChannelNameValid => _userChannelName.IsInitialized; /// /// Get/set channel subsample indicator. /// public bool IsSubsampled { get => _IsSubsampled.Value; set => _IsSubsampled.Value = value; } private readonly Property _IsSubsampled = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.IsSubsampled", false, true ); /// /// Get/set channel unsubsampled sample rate. /// public float UnsubsampledSampleRateHz { get => _UnsubsampledSampleRateHz.Value; set => _UnsubsampledSampleRateHz.Value = value; } private readonly Property _UnsubsampledSampleRateHz = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.UnsubsampledSampleRateHz", 0, true ); /// /// Get/set the sample rate for this test module. /// public bool IsSupersampled { get => _IsSupersampled.Value; set => _IsSupersampled.Value = value; } private readonly Property _IsSupersampled = new Property( typeof(Module).Namespace + ".Event.Module.Channel.IsSupersampled", false, false ); /// /// Get/set whether viewing and exporting this channel should use the EU Scalar. /// public bool UseEUScaler { get => _UseEUScalar.Value; set => _UseEUScalar.Value = value; } private readonly Property _UseEUScalar = new Property( typeof(Module).Namespace + ".Event.Module.Channel.UseEUScaler", false, false ); /// /// Get/set the sample rate for this test module. /// public float UnsupersampledSampleRateHz { get => _UnsupersampledSampleRateHz.Value; set => _UnsupersampledSampleRateHz.Value = value; } private readonly Property _UnsupersampledSampleRateHz = new Property( typeof(Module).Namespace + ".Event.Module.Channel.UnsupersampledSampleRateHz", 0, false ); public void ClearDataCache() { var filtering = UseFilterCaching; _Data = null; _DataEu = null; _DataMv = null; _UnfilteredDataEu = null; _DataADC = null; lock (previouslyFilteredDataLock) { _previouslyFilteredData.Clear(); } UseFilterCaching = filtering; } /// /// Create the matching Event.Module.Channel-based representation of the specified /// DTS.DASLib.Service.DASChannel-based object. /// /// /// /// The object to be represented. /// /// /// /// The that contains the created channel. /// /// /// /// The -based representation of the specified /// channel object. /// /// /// /// The unique "absolute" number of the channel with respect to all other channels /// on all other DASes in the system. /// /// public static Channel CreateChannel(DASChannel channel, Module parentModule, int absoluteNumber) { try { switch (channel.GetType().FullName) { case "DTS.DASLib.Service.AnalogInputDASChannel": return new AnalogInputChannel(channel, parentModule, absoluteNumber); case "DTS.DASLib.Service.IEPEChannel": return new IEPEInputChannel(channel, parentModule, absoluteNumber); case "DTS.DASLib.Service.OutputSquibChannel": { var osc = channel as OutputSquibChannel; var output = new SquibEventChannel(channel, parentModule, absoluteNumber); output.MeasurementType = osc.MeasurementType; output.ChannelName2 = osc.ChannelName2; if (osc.MeasurementType == SquibMeasurementType.CURRENT) { if (osc.SquibDescription.EndsWith(".1")) { var newName = osc.SquibDescription.Substring(0, osc.SquibDescription.Length - 2); newName += ".2"; output.ChannelName2 = output.ChannelName2.Replace(osc.SquibDescription, newName); } } output.ChannelId = osc.ChannelId; output.Sensor = osc.Sensor; output.SerialNumber = osc.SerialNumber; output.ChannelGroupName = osc.ChannelGroupName; return output; } case "DTS.DASLib.Service.OutputTOMDigitalChannel": { return new SquibDigitalChannel(channel, parentModule, absoluteNumber); } case "DTS.DASLib.Service.TimestampDASChannel": { return new TimestampChannel(channel, parentModule, absoluteNumber); } case "DTS.DASLib.Service.StreamInputDASChannel": { return new StreamInputChannel(channel, parentModule, absoluteNumber); } case "DTS.DASLib.Service.CANInputDASChannel": { return new CANInputChannel(channel, parentModule, absoluteNumber); } default: throw new NotImplementedException("cannot create a " + typeof(Channel).FullName + "-based representation of a " + channel.GetType().FullName + " object"); } } catch (System.Exception ex) { throw new ApplicationException("encountered problem creating channel", ex); } } /// /// Create the matching Event.Module.Channel-based representation of the specified /// DTS.DASLib.Service.DASChannel-based object. /// /// /// /// The object to be represented. /// /// /// /// The that contains the created channel. /// /// /// /// The -based representation of the specified /// channel object. /// /// /// /// The unique "absolute" number of the channel with respect to all other channels /// on all other DASes in the system. /// /// public static Channel CreateChannel(Serialization.Test.Module.Channel channel, Module parentModule, int absoluteNumber) { try { switch (channel.GetType().FullName) { case "DTS.Serialization.Test+Module+AnalogInputChannel": return new AnalogInputChannel(channel, parentModule, absoluteNumber); case "DTS.Serialization.Test+Module+CalculatedChannel": return new AnalogInputChannel(channel, parentModule, absoluteNumber); default: throw new NotImplementedException("cannot create a " + typeof(Channel).FullName + "-based representation of a " + channel.GetType().FullName + " object"); } } catch (System.IO.InvalidDataException ex2) { throw ex2; } catch (System.Exception ex) { throw new ApplicationException("encountered problem creating channel", ex); } } /// /// Set the appropriate properties in this class from the equivalent properties /// of the specified object. /// /// /// /// The object containing the /// property values to be copied. /// /// public abstract void SetPropertyValuesFrom(DASChannel dasChannel); /// /// Set the appropriate properties in this class from the equivalent properties /// of the specified object. /// /// /// /// The object containing the /// property values to be copied. /// /// public virtual void SetPropertyValuesFrom(IDiagnosticResult diagResults) { try { if (null == diagResults) throw new ArgumentNullException("cannot set property values from null " + typeof(DiagnosticsResult).FullName); ScaleFactorEU = diagResults.ScalefactorEngineeringUnitsPerADC; ScaleFactorMv = diagResults.ScalefactorMilliVoltsPerADC; if (this is AnalogInputChannel) { Scaler.IEPE = (this as AnalogInputChannel).Bridge == SensorConstants.BridgeType.IEPE; } try { if (this is AnalogInputChannel) { Scaler.Digital = (this as AnalogInputChannel).Bridge == SensorConstants.BridgeType.DigitalInput; } else { Scaler.Digital = false; } } catch (System.Exception) { } if (this is IShuntAware) { if (null != diagResults.MeasuredShuntDeflectionMv) (this as IShuntAware).MeasuredShuntDeflectionMv = (double)diagResults.MeasuredShuntDeflectionMv; if (null != diagResults.TargetShuntDeflectionMv) (this as IShuntAware).TargetShuntDeflectionMv = (double)diagResults.TargetShuntDeflectionMv; } if (this is ICalSignalAware) { if (null != diagResults.MeasuredCalSignalMv) (this as ICalSignalAware).MeasuredCalSignalMv = (double)diagResults.MeasuredCalSignalMv; if (null != diagResults.TargetCalSignalMv) (this as ICalSignalAware).TargetCalSignalMv = (double)diagResults.TargetCalSignalMv; } try { NoiseAsPercentageOfFullScale = null != diagResults.NoisePercentFullScale ? (double)diagResults.NoisePercentFullScale : 0.0; } catch (InvalidOperationException) { throw new UserException("Diagnostics service did not return a value for requested \"noise as percentage of full scale\" statistic"); } if (null != diagResults.FinalOffsetADC) { try { PreTestZeroLevelAdc = (short)diagResults.FinalOffsetADC; } catch (InvalidOperationException) { throw new UserException("Diagnostics service did not return a value for requested \"final offset\" statistic"); } } else { PreTestZeroLevelAdc = 0; } ZeroMvInADC = Convert.ToInt16(diagResults.ZeroMVInADC); WindowAverageADC = Convert.ToInt16(diagResults.WindowAverageADC); if (null != diagResults.MeasuredOffsetMilliVolts) { try { PreTestZeroLevelMv = (double)diagResults.MeasuredOffsetMilliVolts; } catch (InvalidOperationException) { /*throw new UserException( "diagnostics service did not return a value for requested \"measured offset\" statistic" ); */ PreTestZeroLevelMv = 0D; } } else { PreTestZeroLevelMv = 0D; } } catch (System.Exception ex) { throw new Exception("encountered problem setting property value from " + (null != diagResults ? diagResults.GetType().FullName : "<>") + " object", ex); } try { if (null != diagResults.RemovedOffsetADC) { RemovedADC = (short)diagResults.RemovedOffsetADC; } else { RemovedADC = 0; } } catch (System.Exception) { } } ///// ///// Get the list of available filters. ///// public List AvailableFilters => _AvailableFilters.Value; private readonly Property> _AvailableFilters = new Property>( typeof(Channel).Namespace + ".Event.Module.Channel.AvailableFilters", new List(), true ); /// /// Get/set the default filter for this channel. /// public IFilter CurrentFilter { get => _CurrentFilter.Value; set { // // Might be lots of gratuitous "changing" of filter to the same value, since // last I checked it happens every time you flip from one channel to another // in the data viewer. Anyway, if nothing has changed, don't force a reload // of the cached data. // if (_CurrentFilter.Value == null || !value.Name.Equals(_CurrentFilter.Value.Name, StringComparison.OrdinalIgnoreCase)) { // // Clear filtered data caches and set new filter value. // _Data = null; _DataEu = null; _DataMv = null; _CurrentFilter.Value = value; } } } private readonly Property _CurrentFilter = new Property(typeof(Channel).Namespace + ".Event.Module.Channel.CurrentFilter", null, true ); /// /// Get/set the default filter for this channel. /// public IFilter DefaultFilter { get => _defaultFilter.Value; set { if (_defaultFilter.Value == null || !value.Name.Equals(_defaultFilter.Value.Name, StringComparison.OrdinalIgnoreCase)) { _Data = null; _DataEu = null; _DataMv = null; _defaultFilter.Value = value; } } } private readonly Property _defaultFilter = new Property(typeof(Channel).Namespace + ".Event.Module.Channel.DefaultFilter", null, true); public string FileName { get => _FileName.Value; set => _FileName.Value = value; } private readonly Property _FileName = new Property( typeof(Channel).Namespace + ".Event.Module.Channel.FileName", "", true ); protected static readonly object DisplayUnitLock = new object(); protected static readonly object previouslyFilteredDataLock = new object(); public void UnSet() { if (null != _previouslyFilteredData) { _previouslyFilteredData.Clear(); } if (null != _DataEu) { _DataEu.Clear(); _DataEu = null; } if (null != _UnfilteredDataEu) { _UnfilteredDataEu.Clear(); _UnfilteredDataEu = null; } System.Runtime.GCSettings.LatencyMode = System.Runtime.GCLatencyMode.Batch; System.Runtime.GCSettings.LargeObjectHeapCompactionMode = System.Runtime.GCLargeObjectHeapCompactionMode.CompactOnce; GC.Collect(); } /// /// Get the channel data after filtering by the specified filter. /// /// /// /// The to be applied to the channel. /// /// /// /// The requested filtered channel data. /// /// public double[] GetDataFilteredBy(IFilter filter, DataDisplayUnits displayUnits) { try { double[] filteredData; if (UseFilterCaching) { IDictionary displayUnitData; lock (previouslyFilteredDataLock) { if (!_previouslyFilteredData.Keys.Contains(filter.Name)) _previouslyFilteredData.Add(filter.Name, new Dictionary()); // First cache key should now exist, so work it, baby! displayUnitData = _previouslyFilteredData[filter.Name]; } lock (DisplayUnitLock) { if (displayUnitData.Keys.Contains(displayUnits)) filteredData = displayUnitData[displayUnits]; else { try { displayUnitData.Add(displayUnits, filteredData = filter.Apply(this, displayUnits, Serialization.File.UseLegacyTDCSoftwareFiltering)); } catch (System.Exception ex) { throw new Exception("encountered problem adding; displayUnits " + displayUnits, ex); } } } } else filteredData = filter.Apply(this, displayUnits, Serialization.File.UseLegacyTDCSoftwareFiltering); // By hook or crook, filter data should be here. return filteredData; } catch (System.Exception ex) { throw new Exception("encountered problem getting data filtered by channel filter " + (null != filter && null != filter.Name ? "\"" + filter.Name + "\"" : ""), ex); } } private readonly IDictionary> _previouslyFilteredData = new Dictionary>(); /// /// Test the specified object for equality with this object. /// /// /// /// The to be tested for equality. /// /// /// /// true if the specified object has memeberwise equality with /// this object; false otherwise. /// /// public override bool Equals(object obj) { try { var that = obj as Channel; return null != obj && DataEquals(that.UnfilteredData) && Number.Equals(that.Number) && PreTestZeroLevelAdc.Equals(that.PreTestZeroLevelAdc) && IsSubsampled.Equals(that.IsSubsampled) && UnsubsampledSampleRateHz.Equals(that.UnsubsampledSampleRateHz) && IsSupersampled.Equals(that.IsSupersampled) && UseEUScaler.Equals(that.UseEUScaler) && UnsupersampledSampleRateHz.Equals(that.UnsupersampledSampleRateHz) && _TimeOfFirstSampleSec.IsInitialized == that._TimeOfFirstSampleSec.IsInitialized && (TimeOfFirstSampleSecValid ? TimeOfFirstSampleSec == that.TimeOfFirstSampleSec : true) && Start.ToString().Equals(that.Start.ToString()) && (ZeroMvInADC == that.ZeroMvInADC) && (WindowAverageADC == that.WindowAverageADC) && (UserCode == that.UserCode) && (IsoChannelName == that.IsoChannelName) && (UserChannelName == that.UserChannelName); } catch (System.Exception ex) { throw new Exception( string.Format( Strings.DTS_Slice_Control_Equals_ComparisonFailedString, null != obj ? "\"" + obj.ToString() + "\"" : Strings.DTS_Slice_Control_Event_Event_NullDasListString), ex); } } /// /// Test the specified object's data list for equality with this object's /// data list. /// /// /// /// The List of data objects to be compared /// for equality with this module's equivalent. /// /// /// /// true if the two lists contain equivalent-valued members; /// false otherwise. /// /// private bool DataEquals(List thoseData) { try { if (null == thoseData || Data.Count != thoseData.Count) return false; for (var i = 0; i < thoseData.Count; i++) if (!UnfilteredData[i].Equals(thoseData[i])) return false; return true; } catch (System.Exception ex) { throw new Exception(Strings.DTS_Slice_Control_Event_Module_Channel_DataEquals_ComparisonFailedString, ex); } } /// /// Return the hash code for this object. /// /// /// /// The hash code for this object. /// /// public override int GetHashCode() { try { return base.GetHashCode(); } catch (System.Exception ex) { throw new Exception("encountered problem getting has code for " + GetType().FullName, ex); } } /// /// Convert this object to a DTS.Serialization.Test.Module.Channel. /// /// /// /// A equivalent for this object. /// /// public abstract Serialization.Test.Module.Channel ToDtsSerializationTestModuleChannel(Serialization.Test.Module parentModule); /// /// Initialize this object from the specified DTS.Serialization.Test.Module.Channel. /// /// /// /// A from which to initialize this object. /// /// public abstract void FromDtsSerializationTestModuleChannel(Serialization.Test.Module.Channel that); } } } }