168 lines · 10.0 KB · C#
RawDownload
//******************************************************************************************************//  IMeasurementExtensions.cs - Gbtc////  Copyright © 2016, Grid Protection Alliance.  All Rights Reserved.////  Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See//  the NOTICE file distributed with this work for additional information regarding copyright ownership.//  The GPA licenses this file to you under the MIT License (MIT), the "License"; you may not use this//  file except in compliance with the License. You may obtain a copy of the License at:////      http://opensource.org/licenses/MIT////  Unless agreed to in writing, the subject software distributed under the License is distributed on an//  "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the//  License for the specific language governing permissions and limitations.////  Code Modification History://  ----------------------------------------------------------------------------------------------------//  09/02/2010 - J. Ritchie Carroll//       Generated original version of source code.////****************************************************************************************************** using System;using System.Collections.Concurrent;using System.Collections.Generic;using System.Data;using System.Linq;using GSF.Collections; namespace GSF.TimeSeries{    /// <summary>    /// Defines static extension functions for <see cref="IMeasurement"/> implementations.    /// </summary>    /// <remarks>    /// These helper functions map to the previously defined corresponding properties to help with the transition of <see cref="MeasurementStateFlags"/>.    /// </remarks>    public static class IMeasurementExtensions    {        private static readonly ConcurrentDictionary<string, int> s_signalTypeIDs = new ConcurrentDictionary<string, int>();        private static readonly ConcurrentDictionary<Guid, int> s_signalTypeIDCache = new ConcurrentDictionary<Guid, int>();         /// <summary>        /// Returns <c>true</c> if <see cref="MeasurementStateFlags.BadData"/> is not set.        /// </summary>        /// <param name="measurement"><see cref="IMeasurement"/> instance to test.</param>        /// <returns><c>true</c> if <see cref="MeasurementStateFlags.BadData"/> is not set.</returns>        public static bool ValueQualityIsGood(this IMeasurement measurement) => (measurement.StateFlags & MeasurementStateFlags.BadData) == 0;         /// <summary>        /// Returns <c>true</c> if <see cref="MeasurementStateFlags.BadTime"/> is not set.        /// </summary>        /// <param name="measurement"><see cref="IMeasurement"/> instance to test.</param>        /// <returns><c>true</c> if <see cref="MeasurementStateFlags.BadTime"/> is not set.</returns>        public static bool TimestampQualityIsGood(this IMeasurement measurement) => (measurement.StateFlags & MeasurementStateFlags.BadTime) == 0;         /// <summary>        /// Gets derived quality flags from a set of source measurements.        /// </summary>        /// <param name="measurements">Source measurements.</param>        /// <returns>Derived quality flags.</returns>        public static MeasurementStateFlags DeriveQualityFlags(this IEnumerable<IMeasurement> measurements)        {            MeasurementStateFlags derivedQuality = MeasurementStateFlags.Normal;            MeasurementStateFlags[] stateFlags = measurements.Select(measurement => measurement.StateFlags).ToArray();             bool dataQualityIsBad(MeasurementStateFlags flags) => (flags & MeasurementStateFlags.BadData) > 0;            bool timeQualityIsBad(MeasurementStateFlags flags) => (flags & MeasurementStateFlags.BadTime) > 0;             if (stateFlags.Any(dataQualityIsBad))                derivedQuality |= MeasurementStateFlags.BadData;             if (stateFlags.Any(timeQualityIsBad))                derivedQuality |= MeasurementStateFlags.BadTime;             return derivedQuality;        }         /// <summary>        /// Returns <c>true</c> if <see cref="MeasurementStateFlags.DiscardedValue"/> is set.        /// </summary>        /// <param name="measurement"><see cref="IMeasurement"/> instance to test.</param>        /// <returns><c>true</c> if <see cref="MeasurementStateFlags.DiscardedValue"/> is not set.</returns>        public static bool IsDiscarded(this IMeasurement measurement) => (measurement.StateFlags & MeasurementStateFlags.DiscardedValue) > 0;         /// <summary>        /// Returns <c>true</c> if <see cref="MeasurementStateFlags.CalculatedValue"/> is set.        /// </summary>        /// <param name="measurement"><see cref="IMeasurement"/> instance to test.</param>        /// <returns><c>true</c> if <see cref="MeasurementStateFlags.CalculatedValue"/> is not set.</returns>        public static bool IsCalculated(this IMeasurement measurement) => (measurement.StateFlags & MeasurementStateFlags.CalculatedValue) > 0;         /// <summary>        /// Returns the measurement ID if defined, otherwise the run-time signal ID associated with the measurement key.        /// </summary>        /// <param name="measurement"><see cref="IMeasurement"/> instance to test.</param>        /// <returns>Measurement ID if defined, otherwise the run-time signal ID associated with the measurement key.</returns>        public static Guid RuntimeSignalID(this IMeasurement measurement) => measurement.ID;         /// <summary>        /// Returns the <see cref="MeasurementKey"/> values of a <see cref="IMeasurement"/> enumeration.        /// </summary>        /// <param name="measurements"><see cref="IMeasurement"/> enumeration to convert.</param>        /// <returns><see cref="MeasurementKey"/> values of the <see cref="IMeasurement"/> enumeration.</returns>        public static MeasurementKey[] MeasurementKeys(this IEnumerable<IMeasurement> measurements) => measurements == null ? new MeasurementKey[0] : measurements.Select(m => m.Key).ToArray();         /// <summary>        /// Gets a unique (run-time only) signal type ID for the given <paramref name="measurement"/> useful for sorting.        /// </summary>        /// <param name="measurement"><see cref="IMeasurement"/> to obtain signal type for.</param>        /// <param name="dataSource"><see cref="DataSet"/> that contains measurement metadata.</param>        /// <returns>Unique (run-time only) signal type ID for the given <paramref name="measurement"/>.</returns>        // This uses string hash code over something like item count + 1 to generate a unique run-time ID of the signal type since chances of a hash code collision        // over a small set of signal types is much smaller than the possibility of duplicates due to possible race conditions when using item count + 1        public static int GetSignalType(this IMeasurement measurement, DataSet dataSource) => s_signalTypeIDCache.GetOrAdd(measurement.ID, signalID => s_signalTypeIDs.GetOrAdd(LookupSignalType(signalID, dataSource), signalType => signalType.GetHashCode()));         /// <summary>        /// Sets the tag name for a <see cref="IMeasurement"/>.        /// </summary>        /// <param name="measurement"><see cref="IMeasurement"/> to create new <see cref="MeasurementMetadata"/> for.</param>        /// <param name="tagName">New tag name value to assign to measurement's metadata.</param>        public static void SetTagName(this IMeasurement measurement, string tagName) => measurement.Metadata = measurement.Metadata.ChangeTagName(tagName);         /// <summary>        /// Sets the associated <see cref="MeasurementKey"/> for a <see cref="IMeasurement"/>.        /// </summary>        /// <param name="measurement"><see cref="IMeasurement"/> to create new <see cref="MeasurementMetadata"/> for.</param>        /// <param name="key">New measurement key value to assign to measurement's metadata.</param>        public static void SetKey(this IMeasurement measurement, MeasurementKey key) => measurement.Metadata = measurement.Metadata.ChangeKey(key);         /// <summary>        /// Sets the adder (i.e., "b" of y = mx + b) for a <see cref="IMeasurement"/>.        /// </summary>        /// <param name="measurement"><see cref="IMeasurement"/> to create new <see cref="MeasurementMetadata"/> for.</param>        /// <param name="adder">New adder value to assign to measurement's metadata.</param>        public static void SetAdder(this IMeasurement measurement, double adder) => measurement.Metadata = measurement.Metadata.ChangeAdder(adder);         /// <summary>        /// Sets the multiplier (i.e., "m" of y = mx + b) for a <see cref="IMeasurement"/>.        /// </summary>        /// <param name="measurement"><see cref="IMeasurement"/> to create new <see cref="MeasurementMetadata"/> for.</param>        /// <param name="multiplier">New multiplier value to assign to measurement's metadata.</param>        public static void SetMultiplier(this IMeasurement measurement, double multiplier) => measurement.Metadata = measurement.Metadata.ChangeMultiplier(multiplier);         /// <summary>        /// Gets a single column of measurement data from a two dimensional data window.        /// </summary>        /// <param name="dataWindow">Target data window.</param>        /// <param name="columnIndex">Index of column to return.</param>        /// <returns>All values from <paramref name="columnIndex"/> in <paramref name="dataWindow"/>.</returns>        public static IMeasurement[] GetDataColumn(this IMeasurement[,] dataWindow, int columnIndex) => dataWindow.GetColumn(columnIndex).ToArray();         // Lookup signal type for given measurement ID        private static string LookupSignalType(Guid signalID, DataSet dataSource)        {            try            {                DataRow[] filteredRows = dataSource.Tables["ActiveMeasurements"].Select($"SignalID = '{signalID}'");                return filteredRows.Length > 0 ? filteredRows[0]["SignalType"].ToString().ToUpper().Trim() : "NONE";            }            catch            {                return "NONE";            }        }    }}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t