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)
{