536 lines
22 KiB
C#
536 lines
22 KiB
C#
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<double> VolumeLine = new List<double>();
|
|
public List<double> ScaleLine = new List<double>();
|
|
public List<double> GP30Erros = new List<double>();
|
|
public List<double> TestMarks = new List<double>();
|
|
public List<double> TofLine = new List<double>();
|
|
public List<double> AmplitudeUpVLine = new List<double>();
|
|
public List<double> AmplitudeDownVLine = new List<double>();
|
|
|
|
public Color Color { get; internal set; }
|
|
|
|
public void ScaleUp(List<double> 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<IMeasurementRecord> measurementRecords = new List<IMeasurementRecord>();
|
|
|
|
|
|
}
|
|
public class PlotableTestResults : TestResults
|
|
{
|
|
private List<List<IMeasurementRecord>> ListOfRecords = new List<List<IMeasurementRecord>>();
|
|
private List<TestPointResult> testPointResults = new List<TestPointResult>();
|
|
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<List<IMeasurementRecord>> 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<double> VolumeLine = new List<double>();
|
|
|
|
double LastVolOrig = 0;
|
|
List<double> ScaleLine = new List<double>();
|
|
List<double> GP30Erros = new List<double>();
|
|
List<double> TestMarks = new List<double>();
|
|
List<double> TofLines = new List<double>();
|
|
List<double> AmplitudeUpVLines = new List<double>();
|
|
List<double> AmplitudeDownVLines = new List<double>();
|
|
|
|
|
|
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 };
|
|
|
|
}
|
|
}
|
|
|
|
|
|
}
|