private IEnumerable <Disturbance> DetectTransients(VIDataGroup viDataGroup) { IEnumerable <Disturbance> vaTransients = DetectTransients(viDataGroup.VA, Phase.AN); IEnumerable <Disturbance> vbTransients = DetectTransients(viDataGroup.VB, Phase.BN); IEnumerable <Disturbance> vcTransients = DetectTransients(viDataGroup.VC, Phase.CN); IEnumerable <Disturbance> vabTransients = DetectTransients(viDataGroup.VAB, Phase.AB); IEnumerable <Disturbance> vbcTransients = DetectTransients(viDataGroup.VBC, Phase.BC); IEnumerable <Disturbance> vcaTransients = DetectTransients(viDataGroup.VCA, Phase.CA); List <Disturbance> transientList = vaTransients.Concat(vbTransients).Concat(vcTransients).Concat(vabTransients).Concat(vbcTransients).Concat(vcaTransients).ToList(); Disturbance worst = null; foreach (Disturbance transiet in transientList) { if ((object)worst == null || transiet.PerUnitMagnitude > worst.PerUnitMagnitude) { worst = transiet; } worst = worst.Clone(); worst.Phase = Phase.Worst; } if (worst != null) { transientList.Add(worst); } return(transientList); }
private void FindAllRestrikes(CycleDataResource cycleDataResource) { for (int i = 0; i < cycleDataResource.DataGroups.Count; i++) { DataGroup dataGroup = cycleDataResource.DataGroups[i]; VIDataGroup viDataGroup = cycleDataResource.VIDataGroups[i]; DataSeries ia = viDataGroup.IA; DataSeries ib = viDataGroup.IB; DataSeries ic = viDataGroup.IC; IEnumerable <Restrike> iaRestrikes = FindRestrikes(ia) .Select(index => new Restrike(Phase.AN, index)); IEnumerable <Restrike> ibRestrikes = FindRestrikes(ib) .Select(index => new Restrike(Phase.BN, index)); IEnumerable <Restrike> icRestrikes = FindRestrikes(ic) .Select(index => new Restrike(Phase.CN, index)); List <Restrike> allRestrikes = Enumerable.Empty <Restrike>() .Concat(iaRestrikes) .Concat(ibRestrikes) .Concat(icRestrikes) .ToList(); if (allRestrikes.Any()) { RestrikeLookup.Add(dataGroup, allRestrikes); } } }
public override void Initialize(MeterDataSet meterDataSet) { DataGroupsResource dataGroupsResource = meterDataSet.GetResource <DataGroupsResource>(); CycleDataResource cycleDataResource = meterDataSet.GetResource <CycleDataResource>(); FaultDataResource faultDataResource = meterDataSet.GetResource <FaultDataResource>(); for (int i = 0; i < cycleDataResource.DataGroups.Count; i++) { DataGroup dataGroup = cycleDataResource.DataGroups[i]; VIDataGroup viDataGroup = cycleDataResource.VIDataGroups[i]; FaultGroup faultGroup; if (!faultDataResource.FaultLookup.TryGetValue(dataGroup, out faultGroup)) { faultGroup = null; } m_classifications.Add(dataGroup, Classify(meterDataSet, dataGroup, viDataGroup, faultGroup)); } foreach (DataGroup dataGroup in dataGroupsResource.DataGroups) { if (dataGroup.DataSeries.Count > 0) { continue; } m_classifications.Add(dataGroup, Classify(meterDataSet, dataGroup)); } }
public ActionResult Get(int eventID, int pixels) { using (AdoDataConnection connection = new AdoDataConnection(m_configuration["OpenXDA:ConnectionString"], m_configuration["OpenXDA:DataProviderString"])) { Event evt = new TableOperations <Event>(connection).QueryRecordWhere("ID = {0}", eventID); if (evt == null) { return(BadRequest("Must provide a valid EventID")); } Meter meter = new TableOperations <Meter>(connection).QueryRecordWhere("ID = {0}", evt.MeterID); meter.ConnectionFactory = () => new AdoDataConnection(m_configuration["OpenXDA:ConnectionString"], m_configuration["OpenXDA:DataProviderString"]); Dictionary <string, IEnumerable <double[]> > returnData = new Dictionary <string, IEnumerable <double[]> >(); DataGroupHelper dataGroupHelper = new DataGroupHelper(m_configuration, m_memoryCache); DataGroup dataGroup = dataGroupHelper.QueryDataGroup(eventID, meter);; VIDataGroup vIDataGroup = new VIDataGroup(dataGroup); double systemFrequency = connection.ExecuteScalar <double?>("SELECT Value FROM Setting WHERE Name = 'SystemFrequency'") ?? 60.0; Dictionary <string, List <double[]> > returnList = new Dictionary <string, List <double[]> >(); returnList.Add("VA", GenerateFrequency(systemFrequency, vIDataGroup.VA)); returnList.Add("VB", GenerateFrequency(systemFrequency, vIDataGroup.VB)); returnList.Add("VC", GenerateFrequency(systemFrequency, vIDataGroup.VC)); returnList.Add("Average", GenerateFrequency(systemFrequency, vIDataGroup.VC)); return(Ok(returnList)); } }
public override void Initialize(MeterDataSet meterDataSet) { MeterInfoDataContext meterInfo = m_dbAdapterContainer.GetAdapter <MeterInfoDataContext>(); DataGroupsResource dataGroupsResource = meterDataSet.GetResource <DataGroupsResource>(); Stopwatch stopwatch = new Stopwatch(); m_dataGroups = dataGroupsResource.DataGroups .Where(dataGroup => dataGroup.Classification == DataClassification.Event) .Where(dataGroup => dataGroup.SamplesPerSecond / m_systemFrequency >= 3.999D) .ToList(); Log.Info(string.Format("Found data for {0} events.", m_dataGroups.Count)); m_viDataGroups = m_dataGroups .Select(dataGroup => { VIDataGroup viDataGroup = new VIDataGroup(dataGroup); dataGroup.Add(viDataGroup.CalculateMissingCurrentChannel(meterInfo)); return(viDataGroup); }) .ToList(); Log.Info(string.Format("Calculating cycle data for all {0} events.", m_dataGroups.Count)); stopwatch.Start(); m_viCycleDataGroups = m_viDataGroups .Select(viDataGroup => Transform.ToVICycleDataGroup(viDataGroup, m_systemFrequency)) .ToList(); Log.Debug(string.Format("Cycle data calculated in {0}.", stopwatch.Elapsed)); }
private List <Fault> DetectFaults(VIDataGroup viDataGroup, VICycleDataGroup viCycleDataGroup) { List <Fault> iaFaults = DetectFaults(viDataGroup.IA, viCycleDataGroup.IA.RMS); List <Fault> ibFaults = DetectFaults(viDataGroup.IB, viCycleDataGroup.IB.RMS); List <Fault> icFaults = DetectFaults(viDataGroup.IC, viCycleDataGroup.IC.RMS); return(Merge(iaFaults, ibFaults, icFaults)); }
public static DataGroup ToDataGroup(Meter meter, List <byte[]> data) { DataGroup dataGroup = new DataGroup(); dataGroup.FromData(meter, data); VIDataGroup vIDataGroup = new VIDataGroup(dataGroup); return(vIDataGroup.ToDataGroup()); }
public override void Execute(MeterDataSet meterDataSet) { // The following logic should only apply to NEXUS meters, not DFRs if (!meterDataSet.Meter.Model.StartsWith("NEXUS")) { return; } CycleDataResource cycleDataResource = meterDataSet.GetResource <CycleDataResource>(); EventClassificationResource eventClassificationResource = meterDataSet.GetResource <EventClassificationResource>(); for (int i = 0; i < cycleDataResource.DataGroups.Count; i++) { DataGroup dataGroup = cycleDataResource.DataGroups[i]; VIDataGroup viDataGroup = cycleDataResource.VIDataGroups[i]; double llPeakNominalVoltage = dataGroup.Asset.VoltageKV * 1000.0D * Math.Sqrt(2.0D); double lnPeakNominalVoltage = llPeakNominalVoltage / Math.Sqrt(3.0D); // Nominal multipliers used for first derivative, based on: // d/dt(A*sin(w*t)) = A*w*cos(w*t) double omega = 2.0D * Math.PI * SystemFrequency; double llFactor = 1.0D / (llPeakNominalVoltage * omega); double lnFactor = 1.0D / (lnPeakNominalVoltage * omega); DataSeries[] puVoltages = { viDataGroup.VA?.Multiply(lnFactor), viDataGroup.VB?.Multiply(lnFactor), viDataGroup.VC?.Multiply(lnFactor), viDataGroup.VAB?.Multiply(llFactor), viDataGroup.VBC?.Multiply(llFactor), viDataGroup.VCA?.Multiply(llFactor) }; bool invalidVoltage = false; foreach (DataSeries voltage in puVoltages) { if (voltage == null) { continue; } List <DataPoint> dataPoints = voltage.DataPoints; invalidVoltage |= dataPoints .Zip(dataPoints.Skip(1), (p1, p2) => (p2.Value - p1.Value) / (p2.Time - p1.Time).TotalSeconds) .Any(slope => Math.Abs(slope) > Settings.MaxVoltageSlope); } if (invalidVoltage) { eventClassificationResource.Classifications[dataGroup] = EventClassification.MeterDataQuality; } } }
private void ProcessSnapshots(double systemFrequency, VIDataGroup viDataGroup) { ProcessSnapshots(systemFrequency, viDataGroup.VA, Phase.AN); ProcessSnapshots(systemFrequency, viDataGroup.IA, Phase.AN); ProcessSnapshots(systemFrequency, viDataGroup.VB, Phase.BN); ProcessSnapshots(systemFrequency, viDataGroup.IB, Phase.BN); ProcessSnapshots(systemFrequency, viDataGroup.VC, Phase.CN); ProcessSnapshots(systemFrequency, viDataGroup.IC, Phase.CN); ProcessSnapshots(systemFrequency, viDataGroup.VAB, Phase.AB); ProcessSnapshots(systemFrequency, viDataGroup.VBC, Phase.BC); ProcessSnapshots(systemFrequency, viDataGroup.VCA, Phase.CA); }
private void IdentifyBreakerOperations(DataGroup dataGroup, VIDataGroup viDataGroup, VICycleDataGroup viCycleDataGroup) { List <string> breakerNumbers = dataGroup.DataSeries .SelectMany(dataSeries => dataSeries.SeriesInfo.Channel.BreakerChannels) .Select(breakerChannel => breakerChannel.BreakerNumber) .Distinct() .ToList(); // If the breaker currents are defined for breaker-and-a-half or ring bus configurations, // skip this data group so that timing is only applied to the breaker currents if (breakerNumbers.Count > 1 && breakerNumbers.Any(num => m_breakerCurrents.Contains(num))) { return; } foreach (string breakerNumber in breakerNumbers) { double breakerSpeed = ConvertBreakerSpeed(m_dbAdapterContainer.Connection.ExecuteScalar("SELECT BreakerSpeed FROM MaximoBreaker WHERE BreakerNum = @breakerNumber", breakerNumber)); List <DataSeries> breakerDigitals = dataGroup.DataSeries .Where(dataSeries => dataSeries.SeriesInfo.Channel.MeasurementType.Name == "Digital") .Where(dataSeries => dataSeries.SeriesInfo.Channel.BreakerChannels.Any(breakerChannel => breakerChannel.BreakerNumber == breakerNumber)) .ToList(); List <DataSeries> tripCoilEnergizedChannels = breakerDigitals .Where(dataSeries => dataSeries.SeriesInfo.Channel.MeasurementCharacteristic.Name == "TCE") .ToList(); DataSeries breakerStatusChannel = breakerDigitals .FirstOrDefault(dataSeries => dataSeries.SeriesInfo.Channel.MeasurementCharacteristic.Name == "BreakerStatus"); List <XValue> breakerOperations = Range <XValue> .MergeAllOverlapping(tripCoilEnergizedChannels.SelectMany(FindTCERanges)) .Select(range => range.Start) .ToList(); foreach (XValue breakerOperation in breakerOperations) { BreakerTiming breakerTiming = new BreakerTiming(breakerOperation, breakerStatusChannel, m_systemFrequency, breakerSpeed); PhaseTiming aPhaseTiming = new PhaseTiming(viDataGroup.IA, viCycleDataGroup.IA, breakerTiming, m_systemFrequency, m_breakerSettings.OpenBreakerThreshold); PhaseTiming bPhaseTiming = new PhaseTiming(viDataGroup.IB, viCycleDataGroup.IB, breakerTiming, m_systemFrequency, m_breakerSettings.OpenBreakerThreshold); PhaseTiming cPhaseTiming = new PhaseTiming(viDataGroup.IC, viCycleDataGroup.IC, breakerTiming, m_systemFrequency, m_breakerSettings.OpenBreakerThreshold); BreakerOperationRow breakerOperationRow = GetBreakerOperationRow(breakerNumber, breakerTiming, aPhaseTiming, bPhaseTiming, cPhaseTiming); m_breakerOperations.Add(Tuple.Create(CreateEventKey(dataGroup), breakerOperationRow)); } } }
public IHttpActionResult GetEventWaveformData(EventDataJSON json) { if (json != null && json.EventID != null) { try { int eventID = int.Parse(json.EventID); using (AdoDataConnection connection = new AdoDataConnection("systemSettings")) { Event evt = new TableOperations <Event>(connection).QueryRecordWhere("ID = {0}", eventID); Meter meter = new TableOperations <Meter>(connection).QueryRecordWhere("ID = {0}", evt.MeterID); meter.ConnectionFactory = () => new AdoDataConnection("systemSettings"); List <byte[]> frequencyDomainData = ChannelData.DataFromEvent(eventID, connection); DataGroup dataGroup = new DataGroup(); dataGroup.FromData(meter, frequencyDomainData); VIDataGroup vIDataGroup = new VIDataGroup(dataGroup); dataGroup = vIDataGroup.ToDataGroup(); DataTable table = new DataTable(); table.Columns.Add("Timestamp", typeof(DateTime)); foreach (var series in dataGroup.DataSeries) { table.Columns.Add(series.SeriesInfo.Channel.MeasurementType.Name + "(" + series.SeriesInfo.Channel.Phase.Name + ")", typeof(double)); } for (int i = 0; i < dataGroup.DataSeries[0].DataPoints.Count(); ++i) { DataRow row = table.NewRow(); row["Timestamp"] = dataGroup.DataSeries[0].DataPoints[i].Time; for (int j = 1; j < table.Columns.Count; ++j) { row[table.Columns[j].ColumnName] = dataGroup.DataSeries[j - 1].DataPoints[i].Value; } table.Rows.Add(row); } return(Ok(table)); } } catch (Exception ex) { return(InternalServerError(ex)); } } else { return(BadRequest("Please provide event id")); } }
public override void Initialize(MeterDataSet meterDataSet) { DataGroupsResource dataGroupsResource = meterDataSet.GetResource <DataGroupsResource>(); VIDataGroup viDataGroup; m_dataGroups = new List <DataGroup>(); m_viDataGroups = new List <VIDataGroup>(); m_viCycleDataGroups = new List <VICycleDataGroup>(); Log.Info("Identifying events and calculating cycle data..."); foreach (DataGroup dataGroup in dataGroupsResource.DataGroups) { double samplesPerCycle; if (dataGroup.Classification != DataClassification.Event) { continue; } samplesPerCycle = Math.Round(dataGroup.SamplesPerSecond / m_systemFrequency); if (dataGroup.Samples < samplesPerCycle) { continue; } viDataGroup = new VIDataGroup(dataGroup); if (viDataGroup.DefinedVoltages != 3 || viDataGroup.DefinedCurrents < 3) { continue; } dataGroup.Add(viDataGroup.CalculateMissingCurrentChannel()); m_dataGroups.Add(dataGroup); m_viDataGroups.Add(viDataGroup); m_viCycleDataGroups.Add(ToVICycleDataGroup(dataGroup, m_systemFrequency)); } Log.Info($"Cycle data calculated for {m_dataGroups.Count} events."); }
public override void Execute(MeterDataSet meterDataSet) { CycleDataResource cycleDataResource = meterDataSet.GetResource <CycleDataResource>(); using (AdoDataConnection connection = meterDataSet.CreateDbConnection()) { TableOperations <BreakerChannel> breakerChannelTable = new TableOperations <BreakerChannel>(connection); List <int> channelsIDs = cycleDataResource.DataGroups .Where(dataGroup => dataGroup.Asset.AssetTypeID == (int)AssetType.Breaker) .SelectMany(dataGroup => dataGroup.DataSeries) .Select(dataSeries => dataSeries.SeriesInfo.ChannelID) .Distinct() .ToList(); // Look up the breaker numbers for the lines // that represent groupings of breaker current data m_breakerCurrents = new HashSet <string>(); if (channelsIDs.Count > 0) { m_breakerCurrents.UnionWith(breakerChannelTable .QueryRecordsWhere($"ChannelID IN ({string.Join(",", channelsIDs)})") .Select(breakerChannel => breakerChannel.BreakerNumber)); } FileGroup fileGroup = meterDataSet.FileGroup; for (int i = 0; i < cycleDataResource.DataGroups.Count; i++) { DataGroup dataGroup = cycleDataResource.DataGroups[i]; VIDataGroup viDataGroup = cycleDataResource.VIDataGroups[i]; VICycleDataGroup viCycleDataGroup = cycleDataResource.VICycleDataGroups[i]; IdentifyBreakerOperations(connection, fileGroup, dataGroup, viDataGroup, viCycleDataGroup); } } }
private EventClassification Classify(MeterDataSet meterDataSet, DataGroup dataGroup, VIDataGroup viDataGroup = null, FaultGroup faultGroup = null) { SnapshotDataResource snapshotDataResource = meterDataSet.GetResource <SnapshotDataResource>(); if (snapshotDataResource.IsSnapshot) { return(EventClassification.Snapshot); } if ((object)viDataGroup != null) { if (viDataGroup.DefinedNeutralVoltages == 0 && viDataGroup.DefinedLineVoltages == 0 && HasBreakerChannels(dataGroup)) { return(EventClassification.Breaker); } } if ((object)faultGroup != null) { if (faultGroup.FaultDetectionLogicResult ?? false) { return(EventClassification.Fault); } if (!faultGroup.FaultDetectionLogicResult.HasValue && m_faultLocationSettings.UseDefaultFaultDetectionLogic) { if (faultGroup.FaultValidationLogicResult && faultGroup.Faults.Any(fault => !fault.IsSuppressed && !fault.IsReclose)) { return(EventClassification.Fault); } if (faultGroup.FaultValidationLogicResult && faultGroup.Faults.Any(fault => !fault.IsSuppressed && fault.IsReclose)) { return(EventClassification.RecloseIntoFault); } } } BreakerDataResource breakerOpenResource = meterDataSet.GetResource <BreakerDataResource>(); if (breakerOpenResource.TripLookup.TryGetValue(dataGroup, out List <BreakerDataResource.Trip> trips)) { return(EventClassification.BreakerOpen); } InterruptionDataResource interruptionDataResource = meterDataSet.GetResource <InterruptionDataResource>(); SagDataResource sagDataResource = meterDataSet.GetResource <SagDataResource>(); SwellDataResource swellDataResource = meterDataSet.GetResource <SwellDataResource>(); TransientDataResource transientDataResource = meterDataSet.GetResource <TransientDataResource>(); if (interruptionDataResource.Interruptions.ContainsKey(dataGroup)) { return(EventClassification.Interruption); } if (sagDataResource.Sags.ContainsKey(dataGroup)) { return(EventClassification.Sag); } if (swellDataResource.Swells.ContainsKey(dataGroup)) { return(EventClassification.Swell); } if (transientDataResource.Transients.ContainsKey(dataGroup)) { return(EventClassification.Transient); } return(EventClassification.Other); }
private EventClassification Classify(MeterDataSet meterDataSet, DataGroup dataGroup, VIDataGroup viDataGroup, VICycleDataGroup viCycleDataGroup, FaultGroup faultGroup) { if (viDataGroup.DefinedNeutralVoltages == 0 && viDataGroup.DefinedLineVoltages == 0 && dataGroup.DataSeries.SelectMany(series => series.SeriesInfo.Channel.BreakerChannels).Any()) { return(EventClassification.Breaker); } if ((object)faultGroup != null && (faultGroup.FaultDetectionLogicResult ?? faultGroup.FaultValidationLogicResult)) { return(EventClassification.Fault); } DataSeries[] rms = { viCycleDataGroup.VA?.RMS, viCycleDataGroup.VB?.RMS, viCycleDataGroup.VC?.RMS, viCycleDataGroup.VAB?.RMS, viCycleDataGroup.VBC?.RMS, viCycleDataGroup.VCA?.RMS }; List <DataSeries> perUnitRMS = rms .Where(dataSeries => (object)dataSeries != null) .Where(dataSeries => GetPerUnitValue(dataSeries) != 0.0D) .Select(dataSeries => dataSeries.Multiply(1.0D / GetPerUnitValue(dataSeries))) .ToList(); if (HasInterruption(perUnitRMS)) { return(EventClassification.Interruption); } if (HasSag(perUnitRMS)) { return(EventClassification.Sag); } if (HasSwell(perUnitRMS)) { return(EventClassification.Swell); } return(EventClassification.Other); }
public void ExportToPQDS(Stream returnStream, NameValueCollection requestParameters) { int eventID = int.Parse(requestParameters["eventID"]); using (AdoDataConnection connection = new AdoDataConnection("dbOpenXDA")) { Event evt = (new TableOperations <Event>(connection)).QueryRecordWhere("ID = {0}", eventID); Meter meter = new TableOperations <Meter>(connection).QueryRecordWhere("ID = {0}", evt.MeterID); meter.ConnectionFactory = () => new AdoDataConnection("dbOpenXDA"); // only get Single Voltage and Single Current Data for This.... List <PQDS.DataSeries> data = new List <PQDS.DataSeries>(); List <PQDS.MetaDataTag> metaData = new List <PQDS.MetaDataTag>(); VIDataGroup dataGroup = new VIDataGroup(OpenSEEController.QueryDataGroup(evt.ID, meter)); if (dataGroup.VA != null) { data.Add(PQDSSeries(dataGroup.VA, "va")); } if (dataGroup.VB != null) { data.Add(PQDSSeries(dataGroup.VB, "vb")); } if (dataGroup.VC != null) { data.Add(PQDSSeries(dataGroup.VC, "vc")); } if (dataGroup.IA != null) { data.Add(PQDSSeries(dataGroup.IA, "ia")); } if (dataGroup.IB != null) { data.Add(PQDSSeries(dataGroup.IB, "ib")); } if (dataGroup.IC != null) { data.Add(PQDSSeries(dataGroup.IC, "ic")); } if (dataGroup.IR != null) { data.Add(PQDSSeries(dataGroup.IR, "in")); } if (data.Count() == 0) { return; } // Add MetaData Information metaData = PQDSMetaData(evt, meter); PQDS.PQDSFile file = new PQDS.PQDSFile(metaData, data, evt.StartTime); using (StreamWriter writer = new StreamWriter(returnStream)) { file.WriteToStream(writer); } } }
private double?CalcVoltagePeak(VIDataGroup viDataGroup) => Enumerable.Empty <DataSeries[]>() .Concat(new[] { new[] { viDataGroup.VA, viDataGroup.VB, viDataGroup.VC } }) .Concat(new[] { new[] { viDataGroup.VAB, viDataGroup.VBC, viDataGroup.VCA } }) .Where(voltageGrouping => voltageGrouping.Any(waveform => waveform != null)) .Select(CalcPeak) .FirstOrDefault();
private BreakerRestrike ProcessRestrike(BreakerDataResource.Restrike restrike, Phase phase, Event evt, VIDataGroup dataGroup) { DataSeries voltage = (phase.Name == "AN"? dataGroup.VA: (phase.Name == "BN" ? dataGroup.VB : dataGroup.VC)); DataSeries current = (phase.Name == "AN" ? dataGroup.IA : (phase.Name == "BN" ? dataGroup.IB : dataGroup.IC)); BreakerRestrike result = new BreakerRestrike(); result.EventID = evt.ID; result.PhaseID = phase.ID; result.InitialExtinguishSample = restrike.initialExtinction; result.InitialExtinguishTime = current[restrike.initialExtinction].Time; result.InitialExtinguishVoltage = voltage[restrike.initialExtinction].Value; result.RestrikeSample = restrike.restrike; result.RestrikeTime = current[restrike.restrike].Time; result.RestrikeVoltage = voltage[restrike.restrike].Value; result.RestrikeCurrentPeak = current[restrike.currentMaximum].Value; result.RestrikeVoltageDip = voltage[restrike.maximumVoltageSurpression].Value; result.TransientPeakSample = restrike.transientOverVoltage; result.TransientPeakTime = current[restrike.transientOverVoltage].Time; result.TransientPeakVoltage = voltage[restrike.transientOverVoltage].Value; result.PerUnitTransientPeakVoltage = voltage[restrike.transientOverVoltage].Value; result.FinalExtinguishSample = restrike.finalExtinction; result.FinalExtinguishTime = current[restrike.finalExtinction].Time; result.FinalExtinguishVoltage = voltage[restrike.finalExtinction].Value; result.I2t = 0.0; return(result); }
private EventClassification Classify(MeterDataSet meterDataSet, DataGroup dataGroup, VIDataGroup viDataGroup = null, FaultGroup faultGroup = null) { if ((object)viDataGroup != null) { if (viDataGroup.DefinedNeutralVoltages == 0 && viDataGroup.DefinedLineVoltages == 0 && HasBreakerChannels(dataGroup)) { return(EventClassification.Breaker); } } if ((object)faultGroup != null) { if (faultGroup.FaultDetectionLogicResult ?? false) { return(EventClassification.Fault); } if (faultGroup.FaultValidationLogicResult && faultGroup.Faults.Any(fault => !fault.IsSuppressed && !fault.IsReclose)) { return(EventClassification.Fault); } if (faultGroup.FaultValidationLogicResult && faultGroup.Faults.Any(fault => !fault.IsSuppressed && fault.IsReclose)) { return(EventClassification.RecloseIntoFault); } } InterruptionDataResource interruptionDataResource = meterDataSet.GetResource <InterruptionDataResource>(); SagDataResource sagDataResource = meterDataSet.GetResource <SagDataResource>(); SwellDataResource swellDataResource = meterDataSet.GetResource <SwellDataResource>(); if (interruptionDataResource.Interruptions.ContainsKey(dataGroup)) { return(EventClassification.Interruption); } if (sagDataResource.Sags.ContainsKey(dataGroup)) { return(EventClassification.Sag); } if (swellDataResource.Swells.ContainsKey(dataGroup)) { return(EventClassification.Swell); } return(EventClassification.Other); }
public override void Execute(MeterDataSet meterDataSet) { Meter meter; List <Series> seriesList; Dictionary <SeriesKey, Series> seriesLookup; DataSeries dataSeries; Series seriesInfo; Log.Info("Executing operation to locate meter in database..."); // Search the database for a meter definition that matches the parsed meter meter = m_meterInfo.Meters.SingleOrDefault(m => m.AssetKey == meterDataSet.Meter.AssetKey); if ((object)meter != null) { Log.Info(string.Format("Found meter {0} in database.", meter.Name)); // Get the list of series associated with the meter in the database seriesList = m_meterInfo.Series .Where(series => series.Channel.MeterID == meter.ID) .ToList(); // Match the parsed series with the ones associated with the meter in the database seriesLookup = seriesList .Where(series => string.IsNullOrEmpty(series.SourceIndexes)) .ToDictionary(GetSeriesKey); foreach (DataSeries series in meterDataSet.DataSeries) { if ((object)series.SeriesInfo == null) { continue; } if (seriesLookup.TryGetValue(GetSeriesKey(series.SeriesInfo), out seriesInfo)) { series.SeriesInfo = seriesInfo; } } // Create data series for series which // are combinations of the parsed series foreach (Series series in seriesList.Where(series => !string.IsNullOrEmpty(series.SourceIndexes))) { AddCalculatedDataSeries(meterDataSet, series); } // There may be some placeholder DataSeries objects with no data so that indexes // would be correct for calculating data series--now that we are finished // calculating data series, these need to be removed for (int i = meterDataSet.DataSeries.Count - 1; i >= 0; i--) { if ((object)meterDataSet.DataSeries[i].SeriesInfo == null) { meterDataSet.DataSeries.RemoveAt(i); } } // There may be some placeholder DataSeries objects with no data so that indexes // would be correct for calculating data series--now that we are finished // calculating data series, these need to be removed for (int i = meterDataSet.Digitals.Count - 1; i >= 0; i--) { if ((object)meterDataSet.Digitals[i].SeriesInfo == null) { meterDataSet.Digitals.RemoveAt(i); } } // Replace the parsed meter with // the one from the database meterDataSet.Meter = meter; } else { Log.Info(string.Format("No existing meter found matching meter with name {0}.", meterDataSet.Meter.Name)); // If configuration cannot be modified and existing configuration cannot be found for this meter, // throw an exception to indicate the operation could not be executed throw new InvalidOperationException("Cannot process meter - configuration does not exist"); } if (meterDataSet.FilePath.EndsWith(".pqd", StringComparison.OrdinalIgnoreCase)) { // Add channels that are not already defined in the // configuration by assuming the meter monitors only one line AddUndefinedChannels(meterDataSet); FixUpdatedChannelInfo(meterDataSet); } else { // Remove data series that were not defined in the configuration // since configuration information cannot be added for it RemoveUndefinedDataSeries(meterDataSet); } foreach (DataGroup dataGroup in meterDataSet.GetResource <DataGroupsResource>().DataGroups) { if (dataGroup.Classification != DataClassification.Event) { continue; } // Add missing current series based on IR = IA + IB + IC dataSeries = VIDataGroup.AddMissingCurrentSeries(m_meterInfo, meterDataSet.Meter, dataGroup); if ((object)dataSeries != null) { meterDataSet.DataSeries.Add(dataSeries); } } }
public override void Execute(MeterDataSet meterDataSet) { CycleDataResource cycleDataResource = meterDataSet.GetResource <CycleDataResource>(); FaultDataResource faultDataResource = meterDataSet.GetResource <FaultDataResource>(); using (AdoDataConnection connection = meterDataSet.CreateDbConnection()) { object ToDateTime2(DateTime dateTime) { using (IDbCommand command = connection.Connection.CreateCommand()) { IDbDataParameter parameter = command.CreateParameter(); parameter.DbType = DbType.DateTime2; parameter.Value = dateTime; return(parameter); } } TableOperations <Event> eventTable = new TableOperations <Event>(connection); TableOperations <EventStat> eventStatTable = new TableOperations <EventStat>(connection); for (int i = 0; i < cycleDataResource.DataGroups.Count; i++) { const string Filter = "FileGroupID = {0} AND " + "AssetID = {1} AND " + "StartTime = {2} AND " + "EndTime = {3}"; DataGroup dataGroup = cycleDataResource.DataGroups[i]; VIDataGroup viDataGroup = cycleDataResource.VIDataGroups[i]; VICycleDataGroup viCycleDataGroup = cycleDataResource.VICycleDataGroups[i]; int fileGroupID = meterDataSet.FileGroup.ID; int assetID = dataGroup.Asset.ID; object startTime = ToDateTime2(dataGroup.StartTime); object endTime = ToDateTime2(dataGroup.EndTime); Event evt = eventTable.QueryRecordWhere(Filter, fileGroupID, assetID, startTime, endTime); if (evt == null) { continue; } double?vPeak = CalcVoltagePeak(viDataGroup); double?vaMax = CalcMax(viCycleDataGroup.VA?.RMS); double?vbMax = CalcMax(viCycleDataGroup.VB?.RMS); double?vcMax = CalcMax(viCycleDataGroup.VC?.RMS); double?vabMax = CalcMax(viCycleDataGroup.VAB?.RMS); double?vbcMax = CalcMax(viCycleDataGroup.VBC?.RMS); double?vcaMax = CalcMax(viCycleDataGroup.VCA?.RMS); double?vaMin = CalcMin(viCycleDataGroup.VA?.RMS); double?vbMin = CalcMin(viCycleDataGroup.VB?.RMS); double?vcMin = CalcMin(viCycleDataGroup.VC?.RMS); double?vabMin = CalcMin(viCycleDataGroup.VAB?.RMS); double?vbcMin = CalcMin(viCycleDataGroup.VBC?.RMS); double?vcaMin = CalcMin(viCycleDataGroup.VCA?.RMS); double?iPeak = CalcPeak(new[] { viDataGroup.IA, viDataGroup.IB, viDataGroup.IC }); double?iaMax = CalcMax(viCycleDataGroup.IA?.RMS); double?ibMax = CalcMax(viCycleDataGroup.IB?.RMS); double?icMax = CalcMax(viCycleDataGroup.IC?.RMS); double?ia2t = null; double?ib2t = null; double?ic2t = null; double?initialMW = CalcMW(viCycleDataGroup, true); double?finalMW = CalcMW(viCycleDataGroup, false); if (faultDataResource.FaultLookup.TryGetValue(dataGroup, out DataAnalysis.FaultGroup faultGroup)) { ia2t = CalcI2t(faultGroup, viDataGroup.IA); ib2t = CalcI2t(faultGroup, viDataGroup.IB); ic2t = CalcI2t(faultGroup, viDataGroup.IC); } int?pqviewID = null; if (meterDataSet.FilePath.Contains("\\pqview4\\events\\")) { Regex pattern = new Regex(@"^\\pqview4\\events\\PQView4 \d+\\\d+T\d+-(?<PQViewID>\d+).pqd$"); Match match = pattern.Match(meterDataSet.FilePath); string str = match.Groups["PQViewID"].Value; if (str != null) { pqviewID = int.Parse(str); } } eventStatTable.AddNewRecord(new EventStat() { EventID = evt.ID, VPeak = vPeak, VAMax = vaMax, VBMax = vbMax, VCMax = vcMax, VABMax = vabMax, VBCMax = vbcMax, VCAMax = vcaMax, VAMin = vaMin, VBMin = vbMin, VCMin = vcMin, VABMin = vabMin, VBCMin = vbcMin, VCAMin = vcaMin, IPeak = iPeak, IAMax = iaMax, IBMax = ibMax, ICMax = icMax, IA2t = ia2t, IB2t = ib2t, IC2t = ic2t, InitialMW = initialMW, FinalMW = finalMW, PQViewID = pqviewID }); } } }
private void IdentifyBreakerOperations(AdoDataConnection connection, FileGroup fileGroup, DataGroup dataGroup, VIDataGroup viDataGroup, VICycleDataGroup viCycleDataGroup) { TableOperations <Event> eventTable = new TableOperations <Event>(connection); TableOperations <BreakerChannel> breakerChannelTable = new TableOperations <BreakerChannel>(connection); TableOperations <BreakerOperation> breakerOperationTable = new TableOperations <BreakerOperation>(connection); List <int> channelIDs = dataGroup.DataSeries .Select(dataSeries => dataSeries.SeriesInfo.ChannelID) .Distinct() .ToList(); if (channelIDs.Count == 0) { return; } List <string> breakerNumbers = breakerChannelTable .QueryRecordsWhere($"ChannelID IN ({string.Join(",", channelIDs)})") .Select(breakerChannel => breakerChannel.BreakerNumber) .Distinct() .ToList(); // If the breaker currents are defined for breaker-and-a-half or ring bus configurations, // skip this data group so that timing is only applied to the breaker currents if (breakerNumbers.Count > 1 && breakerNumbers.Any(num => m_breakerCurrents.Contains(num))) { return; } Event evt = eventTable.GetEvent(fileGroup, dataGroup); if ((object)evt == null) { return; } foreach (string breakerNumber in breakerNumbers) { double breakerSpeed = connection.ExecuteScalar(double.NaN, "SELECT Speed FROM Breaker WHERE AssetKey = {0}", breakerNumber.TrimStart('0')); Func <DataSeries, bool> digitalFilter = dataSeries => { int channelID = dataSeries.SeriesInfo.ChannelID; RecordRestriction recordRestriction = new RecordRestriction("ChannelID = {0}", channelID) & new RecordRestriction("BreakerNumber = {0}", breakerNumber); int breakerChannelCount = breakerChannelTable.QueryRecordCount(recordRestriction); return(breakerChannelCount > 0); }; List <DataSeries> breakerDigitals = dataGroup.DataSeries .Where(dataSeries => dataSeries.SeriesInfo.Channel.MeasurementType.Name == "Digital") .Where(digitalFilter) .ToList(); List <DataSeries> tripCoilEnergizedChannels = breakerDigitals .Where(dataSeries => dataSeries.SeriesInfo.Channel.MeasurementCharacteristic.Name == "TCE") .ToList(); DataSeries breakerStatusChannel = breakerDigitals .FirstOrDefault(dataSeries => dataSeries.SeriesInfo.Channel.MeasurementCharacteristic.Name == "BreakerStatus"); List <XValue> tripCoilEnergizedTriggers = Range <XValue> .MergeAllOverlapping(tripCoilEnergizedChannels.SelectMany(FindTCERanges)) .Select(range => range.Start) .ToList(); foreach (XValue tripCoilEnergizedTrigger in tripCoilEnergizedTriggers) { BreakerTiming breakerTiming = new BreakerTiming(tripCoilEnergizedTrigger, breakerStatusChannel, m_systemFrequency, breakerSpeed, m_breakerSettings.MinWaitBeforeReclose); PhaseTiming aPhaseTiming = new PhaseTiming(viDataGroup.IA, viCycleDataGroup.IA, breakerTiming, m_breakerSettings, m_systemFrequency); PhaseTiming bPhaseTiming = new PhaseTiming(viDataGroup.IB, viCycleDataGroup.IB, breakerTiming, m_breakerSettings, m_systemFrequency); PhaseTiming cPhaseTiming = new PhaseTiming(viDataGroup.IC, viCycleDataGroup.IC, breakerTiming, m_breakerSettings, m_systemFrequency); BreakerOperation breakerOperation = GetBreakerOperation(connection, evt.ID, breakerNumber, breakerTiming, aPhaseTiming, bPhaseTiming, cPhaseTiming); breakerOperationTable.AddNewRecord(breakerOperation); } } }