/// <summary> /// Given three of the four current channels, calculates the /// missing channel based on the relationship IR = IA + IB + IC. /// </summary> /// <param name="meterInfo">Data context for accessing configuration tables in the database.</param> public DataSeries CalculateMissingCurrentChannel() { Meter meter; DataSeries missingSeries; // If the data group does not have exactly 3 channels, // then there is no missing channel or there is not // enough data to calculate the missing channel if (DefinedCurrents != 3) { return(null); } // Get the meter associated with the channels in this data group meter = (I1 ?? I2).SeriesInfo.Channel.Meter; if (m_i1Index == -1) { // Calculate I1 = IR - I2 - I3 missingSeries = IR.Add(I2.Negate()).Add(I3.Negate()); missingSeries.SeriesInfo = GetSeriesInfo(meter, m_dataGroup, "Current", "General1"); m_i1Index = m_dataGroup.DataSeries.Count; m_dataGroup.Add(missingSeries); } else if (m_i2Index == -1) { // Calculate I2 = IR - I1 - I3 missingSeries = IR.Add(I1.Negate()).Add(I3.Negate()); missingSeries.SeriesInfo = GetSeriesInfo(meter, m_dataGroup, "Current", "General2"); m_i1Index = m_dataGroup.DataSeries.Count; m_dataGroup.Add(missingSeries); } else if (m_i3Index == -1) { // Calculate I3 = IR - I1 - I2 missingSeries = IR.Add(I1.Negate()).Add(I2.Negate()); missingSeries.SeriesInfo = GetSeriesInfo(meter, m_dataGroup, "Current", "General3"); m_i1Index = m_dataGroup.DataSeries.Count; m_dataGroup.Add(missingSeries); } else { // Calculate IR = I1 + I2 + I3 missingSeries = I1.Add(I2).Add(I3); missingSeries.SeriesInfo = GetSeriesInfo(meter, m_dataGroup, "Current", "RES"); m_i1Index = m_dataGroup.DataSeries.Count; m_dataGroup.Add(missingSeries); } return(missingSeries); }
public DataGroup ToSubGroup(int startIndex, int endIndex) { DataGroup subGroup = new DataGroup(); foreach (DataSeries dataSeries in m_dataSeries) { subGroup.Add(dataSeries.ToSubSeries(startIndex, endIndex)); } return(subGroup); }
public static DataGroup Combine(params DataGroup[] dataGroups) { DataGroup combination = new DataGroup(); foreach (DataGroup dataGroup in dataGroups) { foreach (DataSeries dataSeries in dataGroup.DataSeries) { combination.Add(dataSeries); } } return(combination); }
public static DataGroup ToCycleDataGroup(DataSeries dataSeries, double frequency) { DataGroup dataGroup = new DataGroup(); DataSeries rmsSeries = new DataSeries(); DataSeries phaseSeries = new DataSeries(); DataSeries peakSeries = new DataSeries(); DataSeries errorSeries = new DataSeries(); int samplesPerCycle; double[] yValues; double[] tValues; double sum; DateTime cycleTime; SineWave sineFit; if ((object)dataSeries == null) { return(null); } // Set series info to the source series info rmsSeries.SeriesInfo = dataSeries.SeriesInfo; phaseSeries.SeriesInfo = dataSeries.SeriesInfo; peakSeries.SeriesInfo = dataSeries.SeriesInfo; errorSeries.SeriesInfo = dataSeries.SeriesInfo; // Get samples per cycle of the data series based on the given frequency samplesPerCycle = CalculateSamplesPerCycle(dataSeries, frequency); // Initialize arrays of y-values and t-values for calculating cycle data yValues = new double[samplesPerCycle]; tValues = new double[samplesPerCycle]; for (int i = 0; i <= dataSeries.DataPoints.Count - samplesPerCycle; i += samplesPerCycle) { // Use the time of the first data point in the cycle as the time of the cycle cycleTime = dataSeries.DataPoints[i].Time; sum = 0.0D; // Copy values from the original data series into the y-value and t-value arrays for (int j = 0; j < samplesPerCycle; j++) { yValues[j] = dataSeries.DataPoints[i + j].Value; tValues[j] = (dataSeries.DataPoints[i + j].Time - cycleTime).TotalSeconds; sum += yValues[j] * yValues[j]; } // Use a curve fitting algorithm to estimate the sine wave over this cycle sineFit = WaveFit.SineFit(yValues, tValues, frequency); // Add data points to each of the cycle data series rmsSeries.DataPoints.Add(new DataPoint() { Time = cycleTime, Value = Math.Sqrt(sum / samplesPerCycle) }); phaseSeries.DataPoints.Add(new DataPoint() { Time = cycleTime, Value = sineFit.Phase }); peakSeries.DataPoints.Add(new DataPoint() { Time = cycleTime, Value = sineFit.Amplitude }); errorSeries.DataPoints.Add(new DataPoint() { Time = cycleTime, Value = tValues .Select(sineFit.CalculateY) .Zip(yValues, (estimate, value) => Math.Abs(estimate - value)) .Sum() }); } // Add a series to the data group for each series of cycle data dataGroup.Add(rmsSeries); dataGroup.Add(phaseSeries); dataGroup.Add(peakSeries); dataGroup.Add(errorSeries); return(dataGroup); }