From 81151935bc5ba23e27e7a9279bfd3ea40a2b65cc Mon Sep 17 00:00:00 2001 From: Milan Hanajik Date: Wed, 19 May 2021 16:16:24 +0200 Subject: [PATCH] iPerlHead : TimeFromSamples( ), VolumeFromSamples( ), StartEndFilterSamplesCount = 20 --- .../iPerlCommunication/iPerlHead/IperlHead.cs | 111 +++++++++++++----- 1 file changed, 79 insertions(+), 32 deletions(-) diff --git a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs b/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs index bdc90706a..1a1107d56 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs @@ -19,10 +19,14 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead private static readonly ILog log = LogManager.GetLogger(typeof(IperlHead)); public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); } - +#if TURA_SPECIAL + public const int MaxOptoDataCount = 250000; +#else public const int MaxOptoDataCount = 40000; +#endif public const int StartOptoDataCount = MaxOptoDataCount / 2; public const int EndOptoDataCount = MaxOptoDataCount - StartOptoDataCount; + public const int StartEndFilterSamplesCount2 = 20; /// StartEndFilterSamplesCount = 2 * StartEndFilterSamplesCount2 + 1 readonly IperlHeadCfg iperlHeadCfg; @@ -198,7 +202,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead if (meterVolume > 1E-2) { - PositiveCounting = volumeLtrEnd > volumeLtrStart; + PositiveCounting = VolumeLtrEnd > VolumeLtrStart; UInt16 newFactor = (UInt16)((double)originalCalibrationFactor * targetVolume / meterVolume + 0.5); log.InfoFormat("Calibration factor: orig={0} new={1} V_iperl={2} V_ref={3} V_target={4}", @@ -313,13 +317,10 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead private double volumeLtr; private double volumeLtr0; - public double VolumeLtrStart { get { return volumeLtrStart; } } /// Test start volume for metrology - public double VolumeLtrEnd { get { return volumeLtrEnd; } } /// Test end volume for metrology - double volumeLtrStart; /// Test start volume for metrology - double volumeLtrEnd; /// Test end volume for metrology - double volumeLtrEnd1; /// auxiliary buffer1 to keep the end volume before test stops - double volumeLtrEnd2; /// auxiliary buffer2 to keep the end volume before test stops - double volumeLtrEnd3; /// auxiliary buffer3 to keep the end volume before test stops + /// Test start volume for metrology in liters + public double VolumeLtrStart { get { return VolumeFromSamples(optoData, optoDataCount, TestStartTelegramIx, ScalingFactor(), StartEndFilterSamplesCount2); } } + /// Test end volume for metrology in liters + public double VolumeLtrEnd { get { return VolumeFromSamples(optoData, optoDataCount, TestEndTelegramIx, ScalingFactor(), StartEndFilterSamplesCount2); } } /// /// Timestamp from the opto telegram @@ -328,23 +329,24 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead private double timestampSec; private double timestampSec0; - public bool NoSamples { get { return (timestampSecEnd - timestampSecStart) < float.Epsilon; } } - public double TimestampSecStart { get { return timestampSecStart; } } - public double TimestampSecEnd { get { return timestampSecEnd; } } - double timestampSecStart; - double timestampSecEnd; - double timestampSecEnd1; - double timestampSecEnd2; - double timestampSecEnd3; + public bool NoSamples { get { return (TimestampSecEnd - TimestampSecStart) < float.Epsilon; } } + /// Test start volume for metrology in seconds + public double TimestampSecStart { get { return TimeFromSamples(optoData, optoDataCount, TestStartTelegramIx, StartEndFilterSamplesCount2); } } + /// Test end time for metrology in seconds + public double TimestampSecEnd { get { return TimeFromSamples(optoData, optoDataCount, TestEndTelegramIx, StartEndFilterSamplesCount2); } } + + /// + /// Indices to determine centers of start / end samples + /// + public int TestStartTelegramIx; + public int TestEndTelegramIx; int endTelegramIdx1; int endTelegramIdx2; int endTelegramIdx3; int currentTelegramIx; bool startSampleAcquired; - public int TestStartTelegramIx; - public int TestEndTelegramIx; OptoTelegramRaw[] optoData; @@ -589,23 +591,11 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead { /// Take the test start sample startSampleAcquired = true; - volumeLtrStart = volumeLtr; - timestampSecStart = timestampSec; TestStartTelegramIx = currentTelegramIx; } else if (startSampleAcquired) { /// Shift data in pipelines - volumeLtrEnd = volumeLtrEnd3; - volumeLtrEnd3 = volumeLtrEnd2; - volumeLtrEnd2 = volumeLtrEnd1; - volumeLtrEnd1 = volumeLtr; - - timestampSecEnd = timestampSecEnd3; - timestampSecEnd3 = timestampSecEnd2; - timestampSecEnd2 = timestampSecEnd1; - timestampSecEnd1 = timestampSec; - TestEndTelegramIx = endTelegramIdx3; endTelegramIdx3 = endTelegramIdx2; endTelegramIdx2 = endTelegramIdx1; @@ -650,7 +640,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead { resultCode |= (int)Results.Entities.ResultCode.MissingOptoData; } - else if (volumeLtrEnd == volumeLtrStart) + else if (VolumeLtrEnd == VolumeLtrStart) { resultCode |= (int)Results.Entities.ResultCode.OptoDataWithZeroFlow; } @@ -967,6 +957,63 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead } } + /// + /// Calculate a filtered volume from data stream samples + /// + /// Samples used in calculation are centered around unwrappedIx + /// Count of samples used in calculation is 2 * smaplesCount2 + 1 + /// Filtered volume + double VolumeFromSamples(OptoTelegramRaw[] optoData, int optoDataCount, int unwrappedIx, double scalingFactor, int samplesCount2 = 0) + { + if (samplesCount2 < 0) samplesCount2 = 0; + if ((unwrappedIx - samplesCount2) < 0 || (unwrappedIx + samplesCount2) >= optoDataCount) return 0; + + Int64 sum = 0; + for (int i = unwrappedIx - samplesCount2; i <= unwrappedIx + samplesCount2; i++) + { + int wrappedIx = OptoTelegramRaw.BufferIdx(i); + + if (optoData[wrappedIx].Flags != OptoTelegramFlags.OK && + optoData[wrappedIx].Flags != OptoTelegramFlags.OK_TestStart && + optoData[wrappedIx].Flags != OptoTelegramFlags.OK_TestEnd) + { + return 0; + } + + sum += optoData[wrappedIx].VolumeRawExt; + } + + return 0.0000625 * scalingFactor * sum / (double)(2 * samplesCount2 + 1); + } + + /// + /// Calculate a filtered time from data stream samples + /// + /// Samples used in calculation are centered around unwrappedIx + /// Count of samples used in calculation is 2 * smaplesCount2 + 1 + /// Filtered time + double TimeFromSamples(OptoTelegramRaw[] optoData, int optoDataCount, int unwrappedIx, int samplesCount2 = 0) + { + if (samplesCount2 < 0) samplesCount2 = 0; + if ((unwrappedIx - samplesCount2) < 0 || (unwrappedIx + samplesCount2) >= optoDataCount) return 0; + + Int64 sum = 0; + for (int i = unwrappedIx - samplesCount2; i <= unwrappedIx + samplesCount2; i++) + { + int wrappedIx = OptoTelegramRaw.BufferIdx(i); + + if (optoData[wrappedIx].Flags != OptoTelegramFlags.OK && + optoData[wrappedIx].Flags != OptoTelegramFlags.OK_TestStart && + optoData[wrappedIx].Flags != OptoTelegramFlags.OK_TestEnd) + { + return 0; + } + + sum += optoData[wrappedIx].TimestampExt; + } + + return sum / (double)(8192 * (2 * samplesCount2 + 1)); + } public void WriteBinary(BinaryWriter writer) {