Exemplo n.º 1
0
        /// <summary>
        /// Creates a new instance of the <see cref="Cycle"/> class.
        /// </summary>
        /// <param name="startSample">The index of the start of the cycle.</param>
        /// <param name="frequency">The frequency of the measured system, in Hz.</param>
        /// <param name="waveFormData">The time-domain data to be used to calculate frequency-domain values.</param>
        public Cycle(int startSample, double frequency, MeasurementData waveFormData)
        {
            long timeStart;

            double[] timeInSeconds;
            double[] measurements;
            SineWave sineFit;

            if (startSample < 0)
            {
                throw new ArgumentOutOfRangeException("startSample");
            }

            if (startSample + waveFormData.SampleRate > waveFormData.Times.Length)
            {
                throw new ArgumentOutOfRangeException("startSample");
            }

            if (startSample + waveFormData.SampleRate > waveFormData.Measurements.Length)
            {
                throw new ArgumentOutOfRangeException("startSample");
            }

            timeStart     = waveFormData.Times[startSample];
            timeInSeconds = new double[waveFormData.SampleRate];
            measurements  = new double[waveFormData.SampleRate];

            for (int i = 0; i < waveFormData.SampleRate; i++)
            {
                timeInSeconds[i] = Ticks.ToSeconds(waveFormData.Times[i + startSample] - timeStart);
                measurements[i]  = waveFormData.Measurements[i + startSample];
            }

            sineFit = WaveFit.SineFit(measurements, timeInSeconds, frequency);

            RMS       = Math.Sqrt(measurements.Select(vi => vi * vi).Average());
            Phase     = sineFit.Phase - PiOverTwo;
            Peak      = sineFit.Amplitude;
            Frequency = frequency;

            Error = timeInSeconds
                    .Select(time => sineFit.CalculateY(time))
                    .Zip(measurements, (calc, measurement) => Math.Abs(calc - measurement))
                    .Sum();
        }
Exemplo n.º 2
0
        private static IEnumerable <DataPoint> CalculateCycleData(IEnumerable <DataPoint> waveformData)
        {
            // Organize the data into individual series
            List <List <DataPoint> > seriesList = waveformData
                                                  .GroupBy(dataPoint => dataPoint.SeriesID)
                                                  .Where(grouping => IsVIWaveform(grouping.Key))
                                                  .Select(grouping => grouping.OrderBy(dataPoint => dataPoint.Time))
                                                  .Select(grouping => grouping.ToList())
                                                  .ToList();

            double frequency = GetFrequency();

            foreach (List <DataPoint> dataSeries in seriesList)
            {
                // Get samples per cycle of the data series based on the given frequency
                int samplesPerCycle = CalculateSamplesPerCycle(dataSeries, frequency);

                // Initialize arrays of y-values and t-values for calculating cycle data
                double[] yValues = new double[samplesPerCycle];
                double[] tValues = new double[samplesPerCycle];

                // Obtain a list of time gaps in the data series
                List <int> gapIndexes = Enumerable.Range(0, dataSeries.Count - 1)
                                        .Where(index =>
                {
                    DataPoint p1     = dataSeries[index];
                    DataPoint p2     = dataSeries[index + 1];
                    double cycleDiff = (p2.Time - p1.Time).TotalSeconds * frequency;

                    // Detect gaps larger than a quarter cycle.
                    // Tolerance of 0.000062 calculated
                    // assuming 3.999 samples per cycle
                    return(cycleDiff > 0.250062);
                })
                                        .ToList();

                for (int i = 0; i <= dataSeries.Count - samplesPerCycle; i++)
                {
                    // If the cycle following i contains a data gap, do not calculate cycle data
                    if (gapIndexes.Any(index => i <= index && (i + samplesPerCycle - 1) > index))
                    {
                        continue;
                    }

                    // Use the time of the first data point in the cycle as the time of the cycle
                    DateTime cycleTime = dataSeries[i].Time;
                    double   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[i + j].Value;
                        tValues[j] = (dataSeries[i + j].Time - cycleTime).TotalSeconds;
                        sum       += yValues[j] * yValues[j];
                    }

                    // Use a curve fitting algorithm to estimate the sine wave over this cycle
                    SineWave sineFit = WaveFit.SineFit(yValues, tValues, frequency);

                    // Add data points to each of the cycle data series
                    yield return(new DataPoint()
                    {
                        SeriesID = dataSeries[0].SeriesID,
                        Characteristic = "RMS",
                        Time = cycleTime,
                        Value = Math.Sqrt(sum / samplesPerCycle)
                    });

                    yield return(new DataPoint()
                    {
                        SeriesID = dataSeries[0].SeriesID,
                        Characteristic = "AngleFund",
                        Time = cycleTime,
                        Value = sineFit.Phase
                    });

                    yield return(new DataPoint()
                    {
                        SeriesID = dataSeries[0].SeriesID,
                        Characteristic = "WaveAmplitude",
                        Time = cycleTime,
                        Value = sineFit.Amplitude
                    });

                    yield return(new DataPoint()
                    {
                        SeriesID = dataSeries[0].SeriesID,
                        Characteristic = "WaveError",
                        Time = cycleTime,

                        Value = tValues
                                .Select(sineFit.CalculateY)
                                .Zip(yValues, (estimate, value) => Math.Abs(estimate - value))
                                .Sum()
                    });
                }
            }
        }
Exemplo n.º 3
0
        public static CycleDataGroup 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];

            // Obtain a list of time gaps in the data series
            List <int> gapIndexes = Enumerable.Range(0, dataSeries.DataPoints.Count - 1)
                                    .Where(index =>
            {
                DataPoint p1     = dataSeries[index];
                DataPoint p2     = dataSeries[index + 1];
                double cycleDiff = (p2.Time - p1.Time).TotalSeconds * frequency;

                // Detect gaps larger than a quarter cycle.
                // Tolerance of 0.000062 calculated
                // assuming 3.999 samples per cycle
                return(cycleDiff > 0.250062);
            })
                                    .ToList();

            for (int i = 0; i <= dataSeries.DataPoints.Count - samplesPerCycle; i++)
            {
                // If the cycle following i contains a data gap, do not calculate cycle data
                if (gapIndexes.Any(index => i <= index && (i + samplesPerCycle - 1) > index))
                {
                    continue;
                }

                // 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(new CycleDataGroup(dataGroup));
        }
Exemplo n.º 4
0
        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);
        }