/// <summary> /// ToDataSeries /// </summary> /// <param name="faultCurve"></param> /// <returns></returns> private DataSeries ToDataSeries(FaultCurve faultCurve) { DataGroup dataGroup = new DataGroup(); dataGroup.FromData(faultCurve.Data); return(dataGroup[0]); }
/// <summary> /// ToDataSeries /// </summary> /// <param name="faultCurve"></param> /// <returns></returns> private DataSeries ToDataSeries(FaultCurve faultCurve) { DataGroup dataGroup = new DataGroup(); dataGroup.FromData(new List <byte[]>(1) { faultCurve.Data }); return(dataGroup[0]); }
private KeyValuePair <string, FlotSeries> QueryFaultDistanceData(int faultCurveID, Meter meter) { FaultCurve faultCurve = m_dataContext.Table <FaultCurve>().QueryRecordWhere("ID = {0}", faultCurveID); DataGroup dataGroup = ToDataGroup(meter, faultCurve.Data); FlotSeries flotSeries = new FlotSeries() { ChannelID = 0, ChannelName = faultCurve.Algorithm, ChannelDescription = faultCurve.Algorithm, MeasurementCharacteristic = "FaultCurve", MeasurementType = "FaultCurve", Phase = "None", SeriesType = "None", DataPoints = dataGroup.DataSeries[0].DataPoints.Select(dataPoint => new double[] { dataPoint.Time.Subtract(m_epoch).TotalMilliseconds, dataPoint.Value }).ToList(), ChartLabel = faultCurve.Algorithm }; return(new KeyValuePair <string, FlotSeries> (faultCurve.Algorithm, flotSeries)); }
public void SummarizeFault() { using (AdoDataConnection connection = MeterDataSet.CreateDbConnection()) { TableOperations <Event> eventTable = new TableOperations <Event>(connection); TableOperations <SegmentType> segmentTypeTable = new TableOperations <SegmentType>(connection); TableOperations <openXDA.Model.FaultGroup> faultGroupTable = new TableOperations <openXDA.Model.FaultGroup>(connection); TableOperations <FaultSegment> faultSegmentTable = new TableOperations <FaultSegment>(connection); TableOperations <FaultSummary> faultSummaryTable = new TableOperations <FaultSummary>(connection); Event evt = eventTable.GetEvent(MeterDataSet.FileGroup, DataGroup); SegmentType faultSegmentType = segmentTypeTable.GetOrAdd("Fault"); // Create a fault group row for the whole group of faults if (FaultGroup.FaultDetectionLogicResult != false || FaultGroup.FaultValidationLogicResult != false) { faultGroupTable.AddNewRecord(CreateFaultGroup(evt.ID, FaultGroup)); } for (int faultIndex = 0; faultIndex < FaultGroup.Faults.Count; faultIndex++) { Fault fault = FaultGroup.Faults[faultIndex]; // Create a fault segment for the fault itself faultSegmentTable.AddNewRecord(CreateFaultSegment(evt.ID, fault, faultSegmentType)); // Create fault segments for each fault type found within the fault foreach (Fault.Segment segment in fault.Segments) { string segmentTypeName = string.Format("{0} Fault", segment.FaultType).Replace("ABC", "3-Phase"); SegmentType segmentType = segmentTypeTable.GetOrAdd(segmentTypeName); faultSegmentTable.AddNewRecord(CreateFaultSegment(evt.ID, segment, segmentType)); } // Create the fault summary rows for this fault foreach (FaultSummary faultSummary in CreateFaultSummaries(evt.ID, faultIndex + 1, fault)) { faultSummaryTable.AddNewRecord(faultSummary); } } // Generate fault curves for each algorithm used to analyze the fault TableOperations <FaultCurve> faultCurveTable = new TableOperations <FaultCurve>(connection); TableOperations <FaultCurveStatistic> faultCurveStatisticTable = new TableOperations <FaultCurveStatistic>(connection); if (FaultGroup.Faults.Any()) { for (int i = 0; i < FaultGroup.Faults[0].Curves.Count; i++) { FaultCurve faultCurve = CreateFaultCurve(evt.ID, i); faultCurveTable.AddNewRecord(faultCurve); faultCurve.ID = connection.ExecuteScalar <int>("SELECT @@IDENTITY"); for (int faultIndex = 0; faultIndex < FaultGroup.Faults.Count; faultIndex++) { Fault fault = FaultGroup.Faults[faultIndex]; if (fault.Curves[i].Series.DataPoints.Count == 0) { continue; } FaultCurveStatistic faultCurveStatistic = new FaultCurveStatistic() { FaultCurveID = faultCurve.ID, FaultNumber = faultIndex + 1, Maximum = ToDbFloat(fault.Curves[i].Maximum), Minimum = ToDbFloat(fault.Curves[i].Minimum), Average = ToDbFloat(fault.Curves[i].Average), StandardDeviation = ToDbFloat(fault.Curves[i].StandardDeviation) }; faultCurveStatisticTable.AddNewRecord(faultCurveStatistic); } } } } }
public override void Execute(MeterDataSet meterDataSet) { // Get a time range for querying each system event that contains events in this meter data set SystemEventResource systemEventResource = meterDataSet.GetResource <SystemEventResource>(); List <SystemEventResource.SystemEvent> systemEvents = systemEventResource.SystemEvents; if (systemEvents.Count == 0) { return; } using (AdoDataConnection connection = meterDataSet.CreateDbConnection()) { TableOperations <openXDA.Model.Line> lineTable = new TableOperations <openXDA.Model.Line>(connection); TableOperations <AssetLocation> meterLocationLineTable = new TableOperations <AssetLocation>(connection); TableOperations <Event> eventTable = new TableOperations <Event>(connection); TableOperations <DoubleEndedFaultDistance> doubleEndedFaultDistanceTable = new TableOperations <DoubleEndedFaultDistance>(connection); TableOperations <FaultCurve> faultCurveTable = new TableOperations <FaultCurve>(connection); List <MappingNode> processedMappingNodes = new List <MappingNode>(); foreach (SystemEventResource.SystemEvent systemEvent in systemEvents) { // Get the full collection of events from the database that comprise the system event that overlaps this time range List <Event> dbSystemEvent = eventTable.GetSystemEvent(systemEvent.StartTime, systemEvent.EndTime, m_timeTolerance); foreach (IGrouping <int, Event> lineGrouping in dbSystemEvent.GroupBy(evt => evt.AssetID)) { // Make sure this line connects two known meter locations int meterLocationCount = meterLocationLineTable.QueryRecordCountWhere("AssetID = {0}", lineGrouping.Key); if (meterLocationCount != 2) { continue; } // Determine the length of the line double lineLength = lineTable .QueryRecordsWhere("ID = {0}", lineGrouping.Key) .Select(line => { line.ConnectionFactory = meterDataSet.CreateDbConnection; return(line.Path[0].Length); }) .DefaultIfEmpty(double.NaN) .First(); if (double.IsNaN(lineLength)) { continue; } // Determine the nominal impedance of the line ComplexNumber nominalImpedance = new ComplexNumber( lineTable.QueryRecordsWhere("ID = {0}", lineGrouping.Key).Select(line => { line.ConnectionFactory = meterDataSet.CreateDbConnection; return(line.Path[0].R1); }).FirstOrDefault(), lineTable.QueryRecordsWhere("ID = {0}", lineGrouping.Key).Select(line => { line.ConnectionFactory = meterDataSet.CreateDbConnection; return(line.Path[0].X1); }).FirstOrDefault()); if (!nominalImpedance.AllAssigned) { continue; } int leftEventID = 0; int rightEventID = 0; VICycleDataGroup leftCycleDataGroup = null; VICycleDataGroup rightCycleDataGroup = null; // Attempt to match faults during this system event that occurred // on one end of the line with faults that occurred during this // system even on the other end of the line List <Mapping> mappings = GetMappings(connection, lineGrouping); foreach (Mapping mapping in mappings) { if (mapping.Left.FaultType == FaultType.None || mapping.Right.FaultType == FaultType.None) { continue; } // Get the cycle data for each of the two mapped faults if (mapping.Left.Fault.EventID != leftEventID) { leftEventID = mapping.Left.Fault.EventID; leftCycleDataGroup = GetCycleData(connection, leftEventID); } if (mapping.Right.Fault.EventID != rightEventID) { rightEventID = mapping.Right.Fault.EventID; rightCycleDataGroup = GetCycleData(connection, rightEventID); } if (leftCycleDataGroup == null || rightCycleDataGroup == null) { continue; } if (leftCycleDataGroup.IA == null || leftCycleDataGroup.IB == null || leftCycleDataGroup.IC == null) { continue; } if (rightCycleDataGroup.IA == null || rightCycleDataGroup.IB == null || rightCycleDataGroup.IC == null) { continue; } // Make sure double-ended distance has not already been calculated and entered into the database RecordRestriction recordRestriction = new RecordRestriction("LocalFaultSummaryID = {0}", mapping.Left.Fault.ID) | new RecordRestriction("RemoteFaultSummaryID = {0}", mapping.Left.Fault.ID) | new RecordRestriction("LocalFaultSummaryID = {0}", mapping.Right.Fault.ID) | new RecordRestriction("RemoteFaultSummaryID = {0}", mapping.Right.Fault.ID); if (doubleEndedFaultDistanceTable.QueryRecordCount(recordRestriction) > 0) { continue; } // Initialize the mappings with additional data needed for double-ended fault location mapping.Left.Initialize(connection, leftCycleDataGroup, m_systemFrequency); mapping.Right.Initialize(connection, rightCycleDataGroup, m_systemFrequency); // Execute the double-ended fault location algorithm ExecuteFaultLocationAlgorithm(lineLength, nominalImpedance, mapping.Left, mapping.Right); ExecuteFaultLocationAlgorithm(lineLength, nominalImpedance, mapping.Right, mapping.Left); try { // Create rows in the DoubleEndedFaultDistance table DoubleEndedFaultDistance leftDistance = CreateDoubleEndedFaultDistance(lineLength, mapping.Left, mapping.Right); DoubleEndedFaultDistance rightDistance = CreateDoubleEndedFaultDistance(lineLength, mapping.Right, mapping.Left); doubleEndedFaultDistanceTable.AddNewRecord(leftDistance); doubleEndedFaultDistanceTable.AddNewRecord(rightDistance); // Add these nodes to the collection of processed mapping nodes processedMappingNodes.Add(mapping.Left); processedMappingNodes.Add(mapping.Right); } catch (Exception ex) { // Ignore errors regarding unique key constraints // which can occur as a result of a race condition bool isUniqueViolation = ExceptionHandler.IsUniqueViolation(ex); if (!isUniqueViolation) { throw; } } } } // Create a row in the FaultCurve table for every event that now has double-ended fault distance curves foreach (IGrouping <int, MappingNode> grouping in processedMappingNodes.GroupBy(node => node.Fault.EventID)) { FaultCurve faultCurve = CreateFaultCurve(connection, grouping); faultCurveTable.AddNewRecord(faultCurve); } } } }