Пример #1
0
        /// <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]);
        }
Пример #2
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]);
        }
Пример #3
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));
        }
Пример #4
0
            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);
                            }
                        }
                    }
                }
            }
Пример #5
0
        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);
                    }
                }
            }
        }