using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Text; using ScottPlot; using Xylem.Common.CommonCore.Consts; using Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords; using Xylem.Common.Logic.ProductionOrderCore.TestResults; using Xylem.Common.Metrology.Measurements; namespace CordoPlot { public class PlotCalibrationRecord : CalibrationRecord { public PlotCalibrationRecord(CalibrationRecord c, int linenr) { base.AccuVolumeRaw = c.AccuVolumeRaw; base.AmplitudeDownV = c.AmplitudeDownV; base.AmplitudeUpV = c.AmplitudeUpV; base.Channel = c.Channel; base.Crc = c.Crc; base.DecodedTime = c.DecodedTime; base.DeltaTimeOfFlightS = c.DeltaTimeOfFlightS; base.DeltaVolumeQm = c.DeltaVolumeQm; base.DeltaVolumeRaw = c.DeltaVolumeRaw; base.FlowRateCmPh = c.FlowRateCmPh; base.ForwardVolumeCm = c.ForwardVolumeCm; base.IsValid = c.IsValid; base.NegativeReverseVolumeCm = c.NegativeReverseVolumeCm; base.OverflowTimeS = c.OverflowTimeS; base.OverflowVolumeCm = c.OverflowVolumeCm; base.PulseWidthRatioDown = c.PulseWidthRatioDown; base.PulseWidthRatioUp = c.PulseWidthRatioUp; base.RawDeltaTimeOfFlight = c.RawDeltaTimeOfFlight; base.RawTotalTimeOfFlight = c.RawTotalTimeOfFlight; base.ReceivedTime = c.ReceivedTime; base.SampleIntervalS = c.SampleIntervalS; base.SyncMarkRecord = c.SyncMarkRecord; base.TemperatureDegC = c.TemperatureDegC; base.TemperaturePowFactor = c.TemperaturePowFactor; base.TemperatureRaw = c.TemperatureRaw; base.TimeS = c.TimeS; base.TotalTimeOfFlightS = c.TotalTimeOfFlightS; base.Validation = c.Validation; base.VolumeCm = c.VolumeCm; base.VolumeFactorRawToQm = c.VolumeFactorRawToQm; base.VolumeScaleRawPerMl = c.VolumeScaleRawPerMl; LineNummer = linenr; } public int LineNummer { get; set; } } public class PlotFlowTestRecord : FlowTestRecord { public PlotFlowTestRecord(FlowTestRecord c, int linenr) { base.Channel = 0; base.Crc = c.Crc; base.DecodedTime = c.DecodedTime; base.FlowRateCmPh = c.FlowRateCmPh; base.ForwardVolumeCm = c.ForwardVolumeCm; base.IsValid = c.IsValid; base.NegativeReverseVolumeCm = c.NegativeReverseVolumeCm; base.OverflowTimeS = c.OverflowTimeS; base.OverflowVolumeCm = c.OverflowVolumeCm; base.ReceivedTime = c.ReceivedTime; base.SyncMarkRecord = c.SyncMarkRecord; base.TimeS = c.TimeS; base.VolumeCm = c.VolumeCm; LineNummer = linenr; } public int LineNummer { get; set; } } public class PlotResult { public List VolumeLine = new List(); public List ScaleLine = new List(); public List GP30Erros = new List(); public List TestMarks = new List(); public List TofLine = new List(); public List AmplitudeUpVLine = new List(); public List AmplitudeDownVLine = new List(); public Color Color { get; internal set; } public void ScaleUp(List MaxSacle) { if (VolumeLine.Count < MaxSacle.Count) { for (int i = VolumeLine.Count; i < MaxSacle.Count; i++) { VolumeLine.Add(double.NaN); ScaleLine.Add(MaxSacle[i]); } } } } public class TestPointResult { public int? Chnl { get; internal set; } = null; public int TestNr { get; internal set; } public List measurementRecords = new List(); } public class PlotableTestResults : TestResults { private List> ListOfRecords = new List>(); private List testPointResults = new List(); public PlotableTestResults() { } public System.String FileName { get; set; } public System.Boolean HasResults { get; internal set; } = false; public DataTable DisplayData { get; internal set; } public DataTable ChlData1 { get; internal set; } public DataTable ChlData2 { get; internal set; } public DataTable ChlData3 { get; internal set; } public bool PrepExprtDataPoints() { DisplayData = new DataTable("DisplayData"); DisplayData.Columns.Add("TestNr", typeof(int)); DisplayData.Columns.Add("FlowTargetQmh", typeof(double)); DisplayData.Columns.Add("FlowrateQmh", typeof(double)); DisplayData.Columns.Add("VolumeQm", typeof(double)); DisplayData.Columns.Add("Info", typeof(string)); DisplayData.Columns.Add("CALC!DurationS", typeof(double)); DisplayData.Columns.Add("ReceivedTimeUtc", typeof(DateTimeOffset)); DisplayData.Columns.Add("VolumeCm", typeof(double)); DisplayData.Columns.Add("OverflowVolumeCm", typeof(double)); DisplayData.Columns.Add("TimeS", typeof(double)); DisplayData.Columns.Add("OverflowTimeS", typeof(double)); DisplayData.Columns.Add("CRC", typeof(ushort)); DisplayData.Columns.Add("IsValid", typeof(bool)); DisplayData.Columns.Add("DecodedTimeUtc", typeof(DateTimeOffset)); DisplayData.Columns.Add("SyncMarkRecord", typeof(SyncMarkRecord)); DisplayData.Columns.Add("CALC!VolumenDiffFromStartQm", typeof(double)); DisplayData.Columns.Add("CALC!FlowrateFromStartQmH", typeof(double)); DisplayData.Columns.Add("CALC!ShortFlowrateQmH", typeof(double)); ChlData1 = new DataTable("ChlData1"); ChlData2 = new DataTable("ChlData2"); ChlData3 = new DataTable("ChlData3"); foreach (var item in testPointResults.Where(f => f.Chnl == 0)) { FlowTestRecord firstRecord = null; FlowTestRecord prevRecord = null; foreach (var raw in item.measurementRecords) { if (raw is FlowTestRecord ftr) { if (firstRecord == null) { firstRecord = ftr; prevRecord = ftr; DisplayData.Rows.Add( item.TestNr + 1, this.Details[item.TestNr].FlowTargetQmh, this.Details[item.TestNr].FlowrateQmh, this.Details[item.TestNr].VolumeQm, this.Details[item.TestNr].Info, 0, ftr.ReceivedTime, ftr.VolumeCm, ftr.OverflowVolumeCm, ftr.TimeS, ftr.OverflowTimeS, ftr.Crc, ftr.IsValid, ftr.DecodedTime, ftr.SyncMarkRecord, 0, 0, 0 ); } else { var volDiffStart = ftr.VolumeCm - firstRecord.VolumeCm; var volDiffprev = ftr.VolumeCm - prevRecord.VolumeCm; var timeDiffStart = ftr.TimeS - firstRecord.TimeS; var timeDiffprev = ftr.TimeS - prevRecord.TimeS; var ts = (ftr.ReceivedTime - firstRecord.ReceivedTime).TotalSeconds; DisplayData.Rows.Add( item.TestNr + 1, this.Details[item.TestNr].FlowTargetQmh, this.Details[item.TestNr].FlowrateQmh, this.Details[item.TestNr].VolumeQm, this.Details[item.TestNr].Info, ts, ftr.ReceivedTime, ftr.VolumeCm, ftr.OverflowVolumeCm, ftr.TimeS, ftr.OverflowTimeS, ftr.Crc, ftr.IsValid, ftr.DecodedTime, ftr.SyncMarkRecord, volDiffStart, (volDiffStart / timeDiffStart) * 3600, (volDiffprev / timeDiffprev) * 3600 ); prevRecord = ftr; } } } } for (int i = 1; i <= 3; i++) { var lCounter = 0; DataTable dtChnl = ChlData3; if (i == 1) { dtChnl = ChlData1; } else if (i == 2) { dtChnl = ChlData2; } else if (i == 2) { dtChnl = ChlData3; } dtChnl.Columns.Add("TestNr", typeof(int)); dtChnl.Columns.Add("FlowTargetQmh", typeof(double)); dtChnl.Columns.Add("FlowrateQmh", typeof(double)); dtChnl.Columns.Add("VolumeQm", typeof(double)); dtChnl.Columns.Add("Info", typeof(string)); dtChnl.Columns.Add("CALC!DurationS", typeof(double)); dtChnl.Columns.Add("ReceivedTimeUtc", typeof(DateTimeOffset)); dtChnl.Columns.Add("Validation", typeof(ushort)); dtChnl.Columns.Add("TotalTimeOfFlightS", typeof(double)); dtChnl.Columns.Add("DeltaTimeOfFlightS", typeof(double)); dtChnl.Columns.Add("RawTotalTimeOfFlight", typeof(int)); dtChnl.Columns.Add("RawDeltaTimeOfFlight", typeof(int)); dtChnl.Columns.Add("VolumeScaleRawPerMl", typeof(double)); dtChnl.Columns.Add("VolumeFactorRawToQm", typeof(double)); dtChnl.Columns.Add("DeltaVolumeRaw", typeof(double)); dtChnl.Columns.Add("DeltaVolumeQm", typeof(double)); dtChnl.Columns.Add("AccuVolumeRaw", typeof(double)); dtChnl.Columns.Add("SampleIntervalS", typeof(double)); dtChnl.Columns.Add("AmplitudeUpV", typeof(double)); dtChnl.Columns.Add("AmplitudeDownV", typeof(double)); dtChnl.Columns.Add("PulseWidthRatioUp", typeof(double)); dtChnl.Columns.Add("PulseWidthRatioDown", typeof(double)); dtChnl.Columns.Add("TemperatureRaw", typeof(double)); dtChnl.Columns.Add("TemperaturePowFactor", typeof(double)); dtChnl.Columns.Add("TemperatureDegC", typeof(double)); dtChnl.Columns.Add("CALC!VolumenDiffFromStart", typeof(double)); dtChnl.Columns.Add("CALC!FlowrateFromStart", typeof(double)); dtChnl.Columns.Add("CALC!ShortFlowrate", typeof(double)); foreach (var item in testPointResults.Where(f => f.Chnl == i)) { CalibrationRecord firstRecord = null; CalibrationRecord prevRecord = null; foreach (var raw in item.measurementRecords) { if (raw is CalibrationRecord ftr) { if (firstRecord == null) { firstRecord = ftr; prevRecord = ftr; dtChnl.Rows.Add(item.TestNr + 1, this.Details[item.TestNr].FlowTargetQmh, this.Details[item.TestNr].FlowrateQmh, this.Details[item.TestNr].VolumeQm, this.Details[item.TestNr].Info, 0.0, ftr.ReceivedTime, ftr.Validation, ftr.TotalTimeOfFlightS, ftr.DeltaTimeOfFlightS, ftr.RawTotalTimeOfFlight, ftr.RawDeltaTimeOfFlight, ftr.VolumeScaleRawPerMl, ftr.VolumeFactorRawToQm, ftr.DeltaVolumeRaw, ftr.DeltaVolumeQm, ftr.AccuVolumeRaw, ftr.SampleIntervalS, ftr.AmplitudeUpV, ftr.AmplitudeDownV, ftr.PulseWidthRatioUp, ftr.PulseWidthRatioDown, ftr.TemperatureRaw, ftr.TemperaturePowFactor, ftr.TemperatureDegC, 0, 0, 0 ); } else { var volDiffStart = ftr.VolumeCm - firstRecord.VolumeCm; var volDiffprev = ftr.VolumeCm - prevRecord.VolumeCm; var timeDiffStart = ftr.TimeS - firstRecord.TimeS; var timeDiffprev = ftr.TimeS - prevRecord.TimeS; var ts = (ftr.ReceivedTime - firstRecord.ReceivedTime).TotalSeconds; dtChnl.Rows.Add(item.TestNr + 1, this.Details[item.TestNr].FlowTargetQmh, this.Details[item.TestNr].FlowrateQmh, this.Details[item.TestNr].VolumeQm, this.Details[item.TestNr].Info, ts, ftr.ReceivedTime, ftr.Validation, ftr.TotalTimeOfFlightS, ftr.DeltaTimeOfFlightS, ftr.RawTotalTimeOfFlight, ftr.RawDeltaTimeOfFlight, ftr.VolumeScaleRawPerMl, ftr.VolumeFactorRawToQm, ftr.DeltaVolumeRaw, ftr.DeltaVolumeQm, ftr.AccuVolumeRaw, ftr.SampleIntervalS, ftr.AmplitudeUpV, ftr.AmplitudeDownV, ftr.PulseWidthRatioUp, ftr.PulseWidthRatioDown, ftr.TemperatureRaw, ftr.TemperaturePowFactor, ftr.TemperatureDegC, volDiffStart, (volDiffStart / timeDiffStart) * 3600, (volDiffprev / timeDiffprev) * 3600 ); prevRecord = ftr; } } } } } return true; } public bool MapDataPoints(List> listOfRecords) { ListOfRecords = listOfRecords; var CurrentTestPoint = 0; var CurrentChnl = -1; var testPointLocked = false; //14787 foreach (var allChnlItems in this.ListOfRecords) { var intiVol = 0.0; CurrentChnl = CurrentChnl + 1;//29586 CurrentTestPoint = 0; testPointLocked = false; foreach (var item in allChnlItems) { if (!testPointLocked && item.GetDataSyncMark() == Xylem.Common.CommonCore.Consts.SyncMarkRecord.SyncStart) { testPointLocked = true; testPointResults.Add(new TestPointResult()); testPointResults.Last().Chnl = CurrentChnl; testPointResults.Last().TestNr = CurrentTestPoint; CurrentTestPoint = CurrentTestPoint + 1; } if (testPointLocked) { testPointResults.Last().measurementRecords.Add(item); if (item.GetDataSyncMark() == Xylem.Common.CommonCore.Consts.SyncMarkRecord.SyncEnd) { testPointLocked = false; } } } } return true; } public PlotResult Plot(int Chnl, int? TestNr = null) { // var results = testPointResults.Where(t => t.Chnl == Chnl && (!TestNr.HasValue || t.TestNr == TestNr.Value)); List VolumeLine = new List(); double LastVolOrig = 0; List ScaleLine = new List(); List GP30Erros = new List(); List TestMarks = new List(); List TofLines = new List(); List AmplitudeUpVLines = new List(); List AmplitudeDownVLines = new List(); var linecounter = 0; var counter = 0; var intiVol = 0.0; var currentTestNr = -1; foreach (var lines in results) { counter = 0; foreach (var line in lines.measurementRecords) { if (lines.TestNr != currentTestNr) { TestMarks.Add(line.GetTimeS()); currentTestNr = lines.TestNr; intiVol = 0.0; LastVolOrig = line.GetVolumeCm(); } ScaleLine.Add(line.GetTimeS()); if (line is PlotCalibrationRecord cal) { GP30Erros.Add(cal.Validation); TofLines.Add(cal.TotalTimeOfFlightS); AmplitudeUpVLines.Add(cal.AmplitudeUpV); AmplitudeDownVLines.Add(cal.AmplitudeDownV); //VolumeLine.Add(cal.LineNummer); } else if (line is PlotFlowTestRecord disp) { //VolumeLine.Add(disp.LineNummer); } if (!VolumeLine.Any()) { VolumeLine.Add(0); LastVolOrig = line.GetVolumeCm(); intiVol = 0; } else { var addVol = line.GetVolumeCm() - LastVolOrig; var dutOverflowVolumeCm = line.GetOverflowVolumeCm(); //an overflow is detected when absolute volume difference is higher than 1/2 of the OverflowVolumeCm if (intiVol != 0 && Math.Abs(addVol) > (0.5 * dutOverflowVolumeCm)) { //if the overflow has been detected the end volume is higher than the start volume //indicates the negative flow direction if (addVol < 0) { //negative overflow intiVol += dutOverflowVolumeCm; //LoggerMeasurement.Info($"Slot:{Slot}, Channel: {IntermediateRecord.GetChannel()} - has negative overflow. currentVolumeQm ({currentVolumeQm}) - lastVolumeQm ({lastVolumeQm}). current accuOverflowVolume is {_accuDutOverflowVolumeCm}"); } else { //positive overflow intiVol += dutOverflowVolumeCm; //LoggerMeasurement.Info($"Slot:{Slot}, Channel: {IntermediateRecord.GetChannel()} - has positive overflow. currentVolumeQm ({currentVolumeQm}) - lastVolumeQm ({lastVolumeQm}). current accuOverflowVolume is {_accuDutOverflowVolumeCm}"); } } intiVol += addVol; LastVolOrig = line.GetVolumeCm(); VolumeLine.Add(intiVol); } counter = counter + 1; } linecounter = 1 + linecounter; } return new PlotResult() { VolumeLine = VolumeLine, ScaleLine = ScaleLine, GP30Erros = GP30Erros, TestMarks = TestMarks, TofLine = TofLines, AmplitudeUpVLine = AmplitudeUpVLines, AmplitudeDownVLine = AmplitudeDownVLines }; } } }