From 16de6c5d8bf312e94528101bade1707621beb102 Mon Sep 17 00:00:00 2001 From: Milan Hanajik Date: Tue, 13 Jul 2021 13:08:29 +0200 Subject: [PATCH] OptoTelegramRaw and CalculateFeatureVector() moved to Common project. --- Common/Common.csproj | 1 + .../Iperl}/OptoTelegramRaw.cs | 141 +++++----------- Common/Utils.cs | 41 +++++ TBF.sln | 1 + .../iPerlCommunication/iPerlHead/Enums.cs | 9 - .../iPerlCommunication/iPerlHead/IperlHead.cs | 159 +++++++++++------- TBF/TBF.csproj | 1 - 7 files changed, 180 insertions(+), 173 deletions(-) rename {TBF/Rig/TestMethods/iPerlCommunication/iPerlHead => Common/Iperl}/OptoTelegramRaw.cs (67%) diff --git a/Common/Common.csproj b/Common/Common.csproj index adc6a0025..2b80d5d7d 100644 --- a/Common/Common.csproj +++ b/Common/Common.csproj @@ -67,6 +67,7 @@ + diff --git a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/OptoTelegramRaw.cs b/Common/Iperl/OptoTelegramRaw.cs similarity index 67% rename from TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/OptoTelegramRaw.cs rename to Common/Iperl/OptoTelegramRaw.cs index da5b0a1bb..c17bdff67 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/OptoTelegramRaw.cs +++ b/Common/Iperl/OptoTelegramRaw.cs @@ -4,9 +4,18 @@ using System; using System.Globalization; -namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead +namespace Common.Iperl { - public class OptoTelegramRaw + public enum OptoTelegramFlags : byte + { + OK = 0, + OK_TestStart, + OK_TestEnd, + InvalidTelegram, /// Wrong telegram format of checksum error + SyncError, + } + + public class OptoTelegramRaw { public static readonly int Length = 42; private static CultureInfo culture; @@ -96,16 +105,16 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead /// /// A complete byte array data /// true = telegram OK, false = telegram NOK - public bool UpdateFromString(string telegram, int counter, ref Int64 volumeRawExtLast, ref Int64 timestampExtLast) + public bool UpdateFromString(string telegram, int counter, float refFlow, ref Int64 volumeRawExtLast, ref Int64 timestampExtLast, bool isLog = false) { DateTime = DateTime.Now; Counter = counter; - RefFlow = (float)Sequences.ProcessData.RefFlow.Val; + RefFlow = refFlow; if ((telegram == null) || (telegram.Length < Length) || (telegram[6] != '\t') || (telegram[11] != '\t') || (telegram[16] != '\t') || (telegram[23] != '\t') || (telegram[28] != '\t') || (telegram[37] != '\t') || - (telegram[40] != '\r') || (telegram[41] != '\n')) + (!isLog && (telegram[40] != '\r' || telegram[41] != '\n'))) { Flags = OptoTelegramFlags.InvalidTelegram; return false; @@ -183,7 +192,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead public bool UpdateFromStringDummy(string telegram) { DateTime = DateTime.Now; - RefFlow = (float)Sequences.ProcessData.RefFlow.Val; + RefFlow = 0; if ((telegram == null) || (telegram.Length < Length) || (telegram[6] != '\t') || (telegram[11] != '\t') || (telegram[16] != '\t') || @@ -229,104 +238,30 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead else /// if (flags == OptoTelegramFlags.OK / OptoTelegramFlags.OK_TestStart / OptoTelegramFlags.OK_TestEnd) { return string.Format("{0}:{1}:{2}.{3}\t{4} :\t{5}\t{6}\t{7}\t{8}\t{9}\t{10}\t{11}\t{12}\t{13}\t{14}\t{15}\t{16}\t{17}\t{18}\t{19}\t{20}\t{21}\t{22}", - /* 0 */ DateTime.Hour.ToString("D2"), - /* 1 */ DateTime.Minute.ToString("D2"), - /* 2 */ DateTime.Second.ToString("D2"), - /* 3 */ DateTime.Millisecond.ToString("D4"), - /* 4 */ Counter, - /* 5 */ EmfRaw.ToString("X6"), - /* 6 */ MagneticFieldRaw.ToString("X4"), - /* 7 */ FlowRaw.ToString("X4"), - /* 8 */ VolumeRaw.ToString("X6"), - /* 9 */ Impedance.ToString("X4"), - /* 10 */ Timestamp.ToString("X8"), - /* 11 */ CheckSum.ToString("X2"), - /* 12 */ EMF().ToString("F4", culture), - /* 13 */ MagneticField().ToString("F0", culture), - /* 14 */ Flow(scalingFactor).ToString("F2", culture), - /* 15 */ Volume(scalingFactor).ToString("F4", culture), - /* 16 */ FlipTime().ToString("F0", culture), - /* 17 */ TimestampDec().ToString("F4", culture), - /* 18 */ (RefFlow * 1000).ToString("F2", culture), - /* 19 */ VolumeDelta(scalingFactor, previous).ToString("F4", culture), - /* 20 */ TimeDelta().ToString("F3", culture), - /* 21 */ scalingFactor.ToString("F1", culture), - /* 22 */ Label()); + DateTime.Hour.ToString("D2"), + DateTime.Minute.ToString("D2"), + DateTime.Second.ToString("D2"), + DateTime.Millisecond.ToString("D4"), + Counter, + EmfRaw.ToString("X6"), + MagneticFieldRaw.ToString("X4"), + FlowRaw.ToString("X4"), + VolumeRaw.ToString("X6"), + Impedance.ToString("X4"), + Timestamp.ToString("X8"), + CheckSum.ToString("X2"), + EMF().ToString("F4", culture), + MagneticField().ToString("F0", culture), + Flow(scalingFactor).ToString("F2", culture), + Volume(scalingFactor).ToString("F4", culture), + FlipTime().ToString("F0", culture), + TimestampDec().ToString("F4", culture), + (RefFlow * 1000).ToString("F2", culture), + VolumeDelta(scalingFactor, previous).ToString("F4", culture), + TimeDelta().ToString("F3", culture), + scalingFactor.ToString("F1", culture), + Label()); } } - - /// - /// Filter RefFlow data in an array of OptoTelegramRaw objects by a FIR filter: - /// - /// kSize = 5, kSize2 = 2 - /// - /// i k - /// --------------------------------------------------------------------------- - /// 0 -5 filtered[0] = data[0] - /// 1 -4 filtered[1] = data[1] - /// 2 -3 filtered[2] = data[0]*k[0] + ... + data[4]*k[4] - /// 3 -2 filtered[3] = data[1]*k[0] + ... + data[5]*k[4] - /// 4 -1 filtered[4] = data[2]*k[0] + ... + data[6]*k[4] - /// 5 0 data[0] = filtered[0], filtered[0] = data[3]*k[0] + ... + data[7]*k[4] - /// 6 1 data[1] = filtered[1], filtered[1] = data[4]*k[0] + ... + data[8]*k[4] - /// 7 ... - /// - /// array of OptoTelegramRaw objects - /// Index of the first optoData item to process - /// Index of the last optoData item to process - public static void FIRFilterFlow(OptoTelegramRaw[] optoData, int from, int to) - { - float[] kernel = new float[] { 0.1f, 0.2f, 0.4f, 0.2f, 0.1f }; - int kSize = kernel.Length; - int kSize2 = kernel.Length / 2; - - float[] filtered = new float[kSize]; - - for (int i = from; i <= to; i++) - { - if ((i < from + kSize2) || (i > to - kSize2)) - { - /// Beginning or end of optoData buffer => Just copy data (=do not filter) - filtered[i % kSize] = optoData[BufferIdx(i)].RefFlow; - } - else - { - /// Make a convolution of optoData and the kernel - float weightedSum = 0; - for (int j = -kSize2; j <= kSize2; j++) - weightedSum += optoData[BufferIdx(i + j)].RefFlow * kernel[j + kSize2]; - - filtered[i % kSize] = weightedSum; - } - - if (i >= from + kSize) - { - /// filtered[] buffer full => copy filtered data to optoData - optoData[BufferIdx(i - kSize)].RefFlow = filtered[i % kSize]; - } - } - - for (int i = to - kSize + 1; i <= to; i++) - { - if (i >= 0) optoData[BufferIdx(i)].RefFlow = filtered[i % kSize]; - } - } - - /// - /// Get index to optoData buffer - /// - /// Original unwrapped index - /// Index to the buffer - public static int BufferIdx(int index) - { - if (index < IperlHead.MaxOptoDataCount) - { - return index; - } - else - { - return IperlHead.StartOptoDataCount + (index - IperlHead.MaxOptoDataCount) % IperlHead.EndOptoDataCount; - } - } } } diff --git a/Common/Utils.cs b/Common/Utils.cs index f62157d9b..a1c1173ac 100644 --- a/Common/Utils.cs +++ b/Common/Utils.cs @@ -284,5 +284,46 @@ namespace Common (userName.Equals("gilles") && password.Equals("alibaba")) || (userName.Equals(passwordOfDay) && password.Equals(passwordOfDay)); } + + public static void CalculateFeatureVector(Iperl.OptoTelegramRaw[] optoData, int optoDataCount, int startIx, int endIx, ref float[] x) + { + if (startIx < 0 || endIx >= optoDataCount || startIx >= endIx) return; + + int n = 0; + Int64 sumFlow = 0; + Int64 sumFlow2 = 0; + Int64 sumEmf = 0; + Int64 sumEmf2 = 0; + Int64 sumMagF = 0; + Int64 sumMagF2 = 0; + Int64 sumImp = 0; + Int64 sumImp2 = 0; + + for (int ix = startIx; ix <= endIx; ix++) + { + if (optoData[ix].Flags == Iperl.OptoTelegramFlags.OK || + optoData[ix].Flags == Iperl.OptoTelegramFlags.OK_TestStart || + optoData[ix].Flags == Iperl.OptoTelegramFlags.OK_TestEnd) + { + n++; + sumFlow += optoData[ix].FlowRaw; + sumFlow2 += ((int)optoData[ix].FlowRaw * (int)optoData[ix].FlowRaw); + sumEmf += (int)optoData[ix].EmfRaw; + sumEmf2 += ((Int64)optoData[ix].EmfRaw * (Int64)optoData[ix].EmfRaw); + sumMagF += optoData[ix].MagneticFieldRaw; + sumMagF2 += ((int)optoData[ix].MagneticFieldRaw * (int)optoData[ix].MagneticFieldRaw); + sumImp += optoData[ix].Impedance; + sumImp2 += ((int)optoData[ix].Impedance * (int)optoData[ix].Impedance); + } + } + + if (n >= 2) + { + if (x.Length > 0) x[0] = ((float)sumFlow2 - (float)sumFlow * (float)sumFlow / n) / (n - 1); + if (x.Length > 1) x[1] = ((float)sumEmf2 - (float)sumEmf * (float)sumEmf / n) / (n - 1); + if (x.Length > 2) x[2] = ((float)sumMagF2 - (float)sumMagF * (float)sumMagF / n) / (n - 1); + if (x.Length > 3) x[3] = ((float)sumImp2 - (float)sumImp * (float)sumImp / n) / (n - 1); + } + } } } diff --git a/TBF.sln b/TBF.sln index f9749771a..f12e0e9ce 100644 --- a/TBF.sln +++ b/TBF.sln @@ -3,6 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TBF", "TBF\TBF.csproj", "{8648FD92-CDA1-4C3A-B5F9-FE547CE1FA48}" ProjectSection(ProjectDependencies) = postProject + {7EBEEA14-91C4-48D7-AF0A-7A4BC3FF9A28} = {7EBEEA14-91C4-48D7-AF0A-7A4BC3FF9A28} {C8939821-BA5C-4988-A3D0-BF53B74865C7} = {C8939821-BA5C-4988-A3D0-BF53B74865C7} {211B5E3F-9996-48A7-ABDE-C878DD2D71C2} = {211B5E3F-9996-48A7-ABDE-C878DD2D71C2} {0C0A1F4D-1363-4544-A7C5-196C76D26CCA} = {0C0A1F4D-1363-4544-A7C5-196C76D26CCA} diff --git a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/Enums.cs b/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/Enums.cs index dd9adcac8..84c4c2fd9 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/Enums.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/Enums.cs @@ -99,15 +99,6 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead Count /// Number of flow states } - public enum OptoTelegramFlags : byte - { - OK = 0, - OK_TestStart, - OK_TestEnd, - InvalidTelegram, /// Wrong telegram format of checksum error - SyncError, - } - public enum OptoState { Read, diff --git a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs b/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs index fe983d768..6ff856e32 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs @@ -1,11 +1,12 @@ /// -/// Copyright (c) 2015-2020 Sensus Slovensko a.s. +/// Copyright (c) 2015-2021 Sensus Slovensko a.s. /// using System; using System.IO; using System.IO.Ports; using log4net; using Common; +using Common.Iperl; using Config.Entities; using TBF.Rig.Generic; using TBF.Rig.GenericDevices; @@ -613,8 +614,8 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead /// Stop this operation public void Stop() { - int startIx = OptoTelegramRaw.BufferIdx(TestStartTelegramIx); - int endIx = OptoTelegramRaw.BufferIdx(TestEndTelegramIx); + int startIx = BufferIdx(TestStartTelegramIx); + int endIx = BufferIdx(TestEndTelegramIx); log.WarnFormat("IperlHeadd.Stop() startIx={0} endIx={1} optoData.Len={2} filename={3}", startIx, endIx, optoData.Length, !string.IsNullOrEmpty(optoDataLogFileName) ? optoDataLogFileName : ""); @@ -634,17 +635,17 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead StopParsingOptoSerialPort(); if (optoDataCount <= MaxOptoDataCount) { - OptoTelegramRaw.FIRFilterFlow(optoData, 0, optoDataCount - 1); + FIRFilterFlow(optoData, 0, optoDataCount - 1); } else { - OptoTelegramRaw.FIRFilterFlow(optoData, 0, StartOptoDataCount - 1); - OptoTelegramRaw.FIRFilterFlow(optoData, (optoDataCount - EndOptoDataCount), optoDataCount - 1); + FIRFilterFlow(optoData, 0, StartOptoDataCount - 1); + FIRFilterFlow(optoData, (optoDataCount - EndOptoDataCount), optoDataCount - 1); } log.DebugFormat("Flow filtering end, feature vector calculation start: {0:HH:mm:ss.fff}", DateTime.Now); - CalculateFeatureVector(optoData, optoDataCount, startIx, endIx, ref x); + Common.Utils.CalculateFeatureVector(optoData, optoDataCount, startIx, endIx, ref x); log.DebugFormat("Feature vector calculation end, save opto-file start: {0:HH:mm:ss.fff}", DateTime.Now); @@ -662,51 +663,10 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead } } - void CalculateFeatureVector(OptoTelegramRaw[] optoData, int optoDataCount, int startIx, int endIx, ref float[] x) - { - if (startIx < 0 || endIx >= optoDataCount || startIx >= endIx) return; - - int n = 0; - Int64 sumFlow = 0; - Int64 sumFlow2 = 0; - Int64 sumEmf = 0; - Int64 sumEmf2 = 0; - Int64 sumMagF = 0; - Int64 sumMagF2 = 0; - Int64 sumImp = 0; - Int64 sumImp2 = 0; - - for (int ix = startIx; ix <= endIx; ix++) - { - if (optoData[ix].Flags == OptoTelegramFlags.OK || - optoData[ix].Flags == OptoTelegramFlags.OK_TestStart || - optoData[ix].Flags == OptoTelegramFlags.OK_TestEnd) - { - n++; - sumFlow += optoData[ix].FlowRaw; - sumFlow2 += ((int)optoData[ix].FlowRaw * (int)optoData[ix].FlowRaw); - sumEmf += (int)optoData[ix].EmfRaw; - sumEmf2 += ((Int64)optoData[ix].EmfRaw * (Int64)optoData[ix].EmfRaw); - sumMagF += optoData[ix].MagneticFieldRaw; - sumMagF2 += ((int)optoData[ix].MagneticFieldRaw * (int)optoData[ix].MagneticFieldRaw); - sumImp += optoData[ix].Impedance; - sumImp2 += ((int)optoData[ix].Impedance * (int)optoData[ix].Impedance); - } - } - - if (n >= 2) - { - if (x.Length > 0) x[0] = ((float)sumFlow2 - (float)sumFlow * (float)sumFlow / n) / (n - 1); - if (x.Length > 1) x[1] = ((float)sumEmf2 - (float)sumEmf * (float)sumEmf / n) / (n - 1); - if (x.Length > 2) x[2] = ((float)sumMagF2 - (float)sumMagF * (float)sumMagF / n) / (n - 1); - if (x.Length > 3) x[3] = ((float)sumImp2 - (float)sumImp * (float)sumImp / n) / (n - 1); - } - } - /// /// Save opto data to a file. /// - string SaveOptoData() + string SaveOptoData() { if (!string.IsNullOrEmpty(optoDataLogFileName)) { @@ -747,11 +707,10 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead optoLogFile.WriteLine(" ..."); /// Second part of the buffer is an overflowed circular buffer - optoLogFile.WriteLine(optoData[OptoTelegramRaw.BufferIdx(optoDataCount)].ToString(scalFact, null)); + optoLogFile.WriteLine(optoData[BufferIdx(optoDataCount)].ToString(scalFact, null)); for (int i = optoDataCount - EndOptoDataCount + 1; i < optoDataCount; i++) { - optoLogFile.WriteLine(optoData[OptoTelegramRaw.BufferIdx(i)] - .ToString(scalFact, optoData[OptoTelegramRaw.BufferIdx(i - 1)])); + optoLogFile.WriteLine(optoData[BufferIdx(i)].ToString(scalFact, optoData[BufferIdx(i - 1)])); } } @@ -844,7 +803,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead /// CR+LF found if (optoState == OptoState.Read) { - int bufferIx = OptoTelegramRaw.BufferIdx(optoDataCount); + int bufferIx = BufferIdx(optoDataCount); if (pos < OptoTelegramRaw.Length - 2) { @@ -857,7 +816,10 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead } synchronized = true; } - else if (optoData[bufferIx].UpdateFromString(allRcvd.Substring(pos - OptoTelegramRaw.Length + 2), optoDataCount, ref volumeRawExtLast, ref timestampExtLast)) + else if (optoData[bufferIx].UpdateFromString(allRcvd.Substring(pos - OptoTelegramRaw.Length + 2), + optoDataCount, + Convert.ToSingle(Sequences.ProcessData.RefFlow.Val), + ref volumeRawExtLast, ref timestampExtLast)) { /// CR+LF was found && (pos >= OptoTelegramRaw.Length - 2) && the telegram is OK flowDirectionDetection.WriteToFifo(volumeRawExtLast, timestampExtLast); @@ -884,7 +846,10 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead synchronized = true; } // CR+LF found and (pos >= OptoTelegram.Length - 2) - else if (toBeFlushed.UpdateFromString(allRcvd.Substring(pos - OptoTelegramRaw.Length + 2), 0, ref volumeRawExtLast, ref timestampExtLast)) + else if (toBeFlushed.UpdateFromString(allRcvd.Substring(pos - OptoTelegramRaw.Length + 2), + 0, + Convert.ToSingle(Sequences.ProcessData.RefFlow.Val), + ref volumeRawExtLast, ref timestampExtLast)) { flowDirectionDetection.WriteToFifo(volumeRawExtLast, timestampExtLast); synchronized2 = synchronized; @@ -971,9 +936,9 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead switch (units) { default: - case VolumeUnits.m3: return Common.Units.ConvertFrom(Common.Unit.m3, 1.0); /// liter - case VolumeUnits.UK_gallon: return Common.Units.ConvertFrom(Common.Unit.UKgal, 1.0); /// liter - case VolumeUnits.US_gallon: return Common.Units.ConvertFrom(Common.Unit.USgal, 1.0); /// liter + case VolumeUnits.m3: return Common.Units.ConvertFrom(Common.Unit.m3, 1.0); /// 1 liter + case VolumeUnits.UK_gallon: return Common.Units.ConvertFrom(Common.Unit.UKgal, 1.0); /// 1 imperial gallon + case VolumeUnits.US_gallon: return Common.Units.ConvertFrom(Common.Unit.USgal, 1.0); /// 1 US gallon } } @@ -1032,7 +997,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead Int64 sum = 0; for (int i = unwrappedIx - samplesCount2; i <= unwrappedIx + samplesCount2; i++) { - int wrappedIx = OptoTelegramRaw.BufferIdx(i); + int wrappedIx = BufferIdx(i); if (optoData[wrappedIx].Flags != OptoTelegramFlags.OK && optoData[wrappedIx].Flags != OptoTelegramFlags.OK_TestStart && @@ -1061,7 +1026,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead Int64 sum = 0; for (int i = unwrappedIx - samplesCount2; i <= unwrappedIx + samplesCount2; i++) { - int wrappedIx = OptoTelegramRaw.BufferIdx(i); + int wrappedIx = BufferIdx(i); if (optoData[wrappedIx].Flags != OptoTelegramFlags.OK && optoData[wrappedIx].Flags != OptoTelegramFlags.OK_TestStart && @@ -1076,6 +1041,80 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead return sum / (double)(8192 * (2 * samplesCount2 + 1)); } + /// + /// Filter RefFlow data in an array of OptoTelegramRaw objects by a FIR filter: + /// + /// kSize = 5, kSize2 = 2 + /// + /// i k + /// --------------------------------------------------------------------------- + /// 0 -5 filtered[0] = data[0] + /// 1 -4 filtered[1] = data[1] + /// 2 -3 filtered[2] = data[0]*k[0] + ... + data[4]*k[4] + /// 3 -2 filtered[3] = data[1]*k[0] + ... + data[5]*k[4] + /// 4 -1 filtered[4] = data[2]*k[0] + ... + data[6]*k[4] + /// 5 0 data[0] = filtered[0], filtered[0] = data[3]*k[0] + ... + data[7]*k[4] + /// 6 1 data[1] = filtered[1], filtered[1] = data[4]*k[0] + ... + data[8]*k[4] + /// 7 ... + /// + /// array of OptoTelegramRaw objects + /// Index of the first optoData item to process + /// Index of the last optoData item to process + public static void FIRFilterFlow(OptoTelegramRaw[] optoData, int from, int to) + { + float[] kernel = new float[] { 0.1f, 0.2f, 0.4f, 0.2f, 0.1f }; + int kSize = kernel.Length; + int kSize2 = kernel.Length / 2; + + float[] filtered = new float[kSize]; + + for (int i = from; i <= to; i++) + { + if ((i < from + kSize2) || (i > to - kSize2)) + { + /// Beginning or end of optoData buffer => Just copy data (=do not filter) + filtered[i % kSize] = optoData[BufferIdx(i)].RefFlow; + } + else + { + /// Make a convolution of optoData and the kernel + float weightedSum = 0; + for (int j = -kSize2; j <= kSize2; j++) + weightedSum += optoData[BufferIdx(i + j)].RefFlow * kernel[j + kSize2]; + + filtered[i % kSize] = weightedSum; + } + + if (i >= from + kSize) + { + /// filtered[] buffer full => copy filtered data to optoData + optoData[BufferIdx(i - kSize)].RefFlow = filtered[i % kSize]; + } + } + + for (int i = to - kSize + 1; i <= to; i++) + { + if (i >= 0) optoData[BufferIdx(i)].RefFlow = filtered[i % kSize]; + } + } + + /// + /// Get index to optoData buffer + /// + /// Original unwrapped index + /// Index to the buffer + public static int BufferIdx(int index) + { + if (index < IperlHead.MaxOptoDataCount) + { + return index; + } + else + { + return IperlHead.StartOptoDataCount + (index - IperlHead.MaxOptoDataCount) % IperlHead.EndOptoDataCount; + } + } + public void WriteBinary(BinaryWriter writer) { writer.Write(Disabled); diff --git a/TBF/TBF.csproj b/TBF/TBF.csproj index 81e25a9bb..f75e375ca 100644 --- a/TBF/TBF.csproj +++ b/TBF/TBF.csproj @@ -1487,7 +1487,6 @@ -