private int GetPhaseID(GSF.PQDIF.Logical.Phase phase) { if ((object)m_phaseLookup == null) { m_phaseLookup = new DataContextLookup <string, Phase>(m_dbAdapterContainer.GetAdapter <MeterInfoDataContext>(), ph => ph.Name); } return(m_phaseLookup.GetOrAdd(phase.ToString(), name => new Phase() { Name = name, Description = name }).ID); }
private double GetLineVoltage(Line line, PQDPhase phase) { PQDPhase[] lnPhases = { PQDPhase.AN, PQDPhase.BN, PQDPhase.CN, PQDPhase.LineToNeutralAverage }; double lineVoltage = line.VoltageKV; if (lnPhases.Contains(phase)) { lineVoltage /= Math.Sqrt(3.0D); } return(lineVoltage * 1000.0D); }
private Disturbance ToDisturbance(DataSeries rms, Range <int> range, Phase phase) { Disturbance disturbance = new Disturbance(); disturbance.EventType = m_eventType; disturbance.Phase = phase; disturbance.StartIndex = range.Start; disturbance.EndIndex = range.End; disturbance.StartTime = rms[range.Start].Time; disturbance.EndTime = rms[range.End].Time; disturbance.Magnitude = GetMagnitude(rms.ToSubSeries(range.Start, range.End)); disturbance.PerUnitMagnitude = disturbance.Magnitude / rms.SeriesInfo.Channel.PerUnitValue.GetValueOrDefault(); return(disturbance); }
private Disturbance ToDisturbance(DataSeries rms, Range <int> range, Phase phase) { double nominalValue = rms.SeriesInfo.Channel.PerUnitValue ?? GetLineVoltage(rms); Disturbance disturbance = new Disturbance(); disturbance.EventType = m_eventType; disturbance.Phase = phase; disturbance.StartIndex = range.Start; disturbance.EndIndex = range.End; disturbance.StartTime = rms[range.Start].Time; disturbance.EndTime = rms[range.End].Time; disturbance.Magnitude = GetMagnitude(rms.ToSubSeries(range.Start, range.End)); disturbance.PerUnitMagnitude = disturbance.Magnitude / nominalValue; return(disturbance); }
private void ProcessSnapshots(double systemFrequency, DataSeries waveForm, Phase phase) { if (waveForm == null) { return; } waveForm.SeriesInfo.ConnectionFactory = () => new AdoDataConnection("systemSettings"); int samplesPerCycle = Transform.CalculateSamplesPerCycle(waveForm.SampleRate, systemFrequency); int numCycles = (int)Math.Floor((double)waveForm.DataPoints.Count / samplesPerCycle); int numPoints = numCycles * samplesPerCycle; double[] points = waveForm.DataPoints.Select(x => x.Value / numPoints).Take(numPoints).ToArray(); double[] frequencyScale = Fourier.FrequencyScale(points.Length, systemFrequency * samplesPerCycle); Complex[] result = FFT(points); Dictionary <string, PhasorResult> dict = new Dictionary <string, PhasorResult>(); for (int i = 0; i < result.Length; i++) { if (frequencyScale[i] <= 0 || frequencyScale[i] % systemFrequency != 0) { continue; } int harmonic = (int)frequencyScale[i] / (int)systemFrequency; if (harmonic <= 0) { continue; } dict.Add($"H{harmonic}", new PhasorResult() { Angle = result[i].Phase * 180 / Math.PI, Magnitude = result[i].Magnitude * 2 / Math.Sqrt(2) }); } Snapshots.Add(waveForm.SeriesInfo.Channel, JsonConvert.SerializeObject(dict, Formatting.None)); //using (StreamWriter sw = new StreamWriter(waveForm.SeriesInfo.Channel.Meter.Name + waveForm.SeriesInfo.Channel.MeasurementType.Name + phase.ToString() + "snapshottest.txt")) //{ // sw.Write(JsonConvert.SerializeObject(dict, Formatting.Indented)); //} }
private Disturbance ToDisturbance(DataSeries rms, Range<int> range, Phase phase) { Disturbance disturbance = new Disturbance(); disturbance.EventType = m_eventType; disturbance.Phase = phase; disturbance.StartIndex = range.Start; disturbance.EndIndex = range.End; disturbance.StartTime = rms[range.Start].Time; disturbance.EndTime = rms[range.End].Time; disturbance.Magnitude = GetMagnitude(rms.ToSubSeries(range.Start, range.End)); disturbance.PerUnitMagnitude = disturbance.Magnitude / rms.SeriesInfo.Channel.PerUnitValue.GetValueOrDefault(); return disturbance; }
private IEnumerable <Disturbance> DetectTransients(DataSeries waveform, Phase phase) { if (waveform == null) { return(Enumerable.Empty <Disturbance>()); } // Obtain a list of time gaps in the waveform List <int> gapIndexes = Enumerable.Range(0, waveform.DataPoints.Count - 1) .Where(index => { DataPoint p1 = waveform[index]; DataPoint p2 = waveform[index + 1]; double cycleDiff = (p2.Time - p1.Time).TotalSeconds * SystemFrequency; // Detect gaps larger than a quarter cycle. // Tolerance of 0.000062 calculated // assuming 3.999 samples per cycle return(cycleDiff > 0.250062); }) .ToList(); double sampleRate = waveform.SampleRate; int samplesPerCycle = Transform.CalculateSamplesPerCycle(waveform.SampleRate, SystemFrequency); double nominalVoltage = waveform.SeriesInfo.Channel.Line.VoltageKV * 1000.0D; if (IsLineToNeutral(waveform.SeriesInfo.Channel.Phase.Name)) { nominalVoltage /= Math.Sqrt(3.0D); } double thresholdValue = nominalVoltage * TransientThreshold / 100; List <Disturbance> disturbances = new List <Disturbance>(); List <int> detections = Enumerable.Range(0, waveform.DataPoints.Count) .Select(index => new { P1 = index - samplesPerCycle, P2 = index, P3 = index + samplesPerCycle }) .Where(obj => obj.P1 >= 0 && obj.P3 < waveform.DataPoints.Count) .Where(obj => !gapIndexes.Any(index => obj.P1 <= index && index < obj.P3)) .Where(obj => { double p1 = waveform[obj.P1].Value; double p2 = waveform[obj.P2].Value; double p3 = waveform[obj.P3].Value; double p1Diff = Math.Abs(p2 - p1); double p3Diff = Math.Abs(p2 - p3); return(p1Diff >= thresholdValue && p3Diff >= thresholdValue); }) .Select(obj => obj.P2) .ToList(); IEnumerable <Range <int> > ranges = detections .Zip(detections.Skip(1), (p1, p2) => new Range <int>(p1, p2)) .Where(range => range.End - range.Start < samplesPerCycle); return(Range <int> .MergeAllOverlapping(ranges) .Select(range => { DataSeries subSeries = waveform.ToSubSeries(range.Start, range.End); double max = Math.Abs(subSeries.Maximum); double min = Math.Abs(subSeries.Minimum); double peak = Math.Max(max, min); return new Disturbance() { EventType = EventClassification.Transient, Phase = phase, StartIndex = range.Start, EndIndex = range.End, StartTime = waveform[range.Start].Time, EndTime = waveform[range.End].Time, Magnitude = peak, PerUnitMagnitude = peak / nominalVoltage }; }) .ToList()); }