Feedback

C# - SwingingDoorAlgorithmus (vereinfacht)

Veröffentlicht von am 03.07.2016
(0 Bewertungen)
Problem: Beim WPF-Chart-Control dauert die Aktualisierung bei > 1000 Datenpunkten sehr lange.
Lösung: Reduzierung redundanter Datenpunkte im Pre-Processing durch Anwendung des SwingingDoorAlgorithmus.

Dieser Algorithmus ist verlustbehaftet und eignet sich daher nur bedingt zur Datenreduzierung in einer Datenbank (PI-Server). Bei der optischen Darstellung der Daten in einem Chart fallen die fehlenden Datenpunkte nicht auf, da alle notwendigen Stützpunkte, je nach Toleranz-Einstellung, erhalten bleiben.

Beispielaufruf:


SDA.SwingingDoorAlgorithmus.ExMax = new TimeSpan(24, 0, 0);
SDA.SwingingDoorAlgorithmus.ExDev = .2f;

SDA.SwingingDoorAlgorithmus.CompMax = new TimeSpan(24, 0, 0);
SDA.SwingingDoorAlgorithmus.sMax = 0.2f;
SDA.SwingingDoorAlgorithmus.sMin = 0.2f;

SDA.SwingingDoorAlgorithmus.data_reduction(ref valTemperatur);
SDA.SwingingDoorAlgorithmus.data_reduction(ref valLuft);
SDA.SwingingDoorAlgorithmus.data_reduction(ref valWind);
SDA.SwingingDoorAlgorithmus.data_reduction(ref valRegen);
GFU-Schulungen  [Anzeige]

ASP.NET Core und Angular Komplett für .NET-Entwickler

Sie  lernen in drei (3) Tagen wie man mit  ASP.NET Core und den Technologien  MVC, Entity Framework, WebAPI und  Razor professionelle sowie moderne  Web-Anwendungsarchitekturen aufbaut.  Die Schulung ist der perfekte  Einstieg um insbesondere datengetriebene  und präsentationsorientierte  Applikationen auf Basis der robusten und  skalierbaren ASP.NET Core  Plattform zu erstellen. Nach der Veranstaltung kennen Sie die Konzepte von Angular und können Angular in neue und bestehende ASP.NET-Anwendungen einsetzen.

ASP.NET 2.0 und 3.5

Dieser Kurs vermittelt Ihnen alle Erweiterungen von Microsoft ASP.NET 2.0. Zu diesen zählen u. a. Data Bindung, Master Pages, und Security.

namespace SDA
{
    /// <summary>
    /// Reducing redundant data points
    /// </summary>
    public class SwingingDoorAlgorithmus
    {
        /// <summary>
        /// Exception Max - max time of empty values between 2 reprorted values
        /// </summary>
        public static TimeSpan ExMax = new TimeSpan(24,0,0);
        /// <summary>
        /// Slope Max - max time of empty values between 2 reprorted values
        /// </summary>
        public static TimeSpan CompMax = new TimeSpan(24, 0, 0);
        /// <summary>
        /// Exception Dev - max deviation from the snapshot-value
        /// </summary>
        public static float ExDev = 1.0f;
        /// <summary>
        /// Slope - min deviation from the snapshot-value
        /// </summary>
        public static float sMin = 1.0f;
        /// <summary>
        /// Slope - max deviation from the snapshot-value
        /// </summary>
        public static float sMax = 1.0f;
        /// <summary>
        /// Compression activated (true/false)
        /// </summary>
        public static bool compression = true;

        /// <summary>
        /// Main-Methode call
        /// </summary>
        /// <param name="RawValues">ref List[KeyValuePair[DateTime, float]]</param>
        public static void data_reduction(ref List<KeyValuePair<DateTime, float>> RawValues)
        {
            if (RawValues.Count < 3) { return; }

            Exception(ref RawValues);

            if (compression)
            {
                Compression(ref RawValues);
            }
        }
        /// <summary>
        /// Reducing redundant, horizontal data points
        /// </summary>
        /// <param name="RawValues">Liste[KeyValuePair[DateTime, float]]</param>
        private static void Exception(ref List<KeyValuePair<DateTime, float>> RawValues)
        {
            //Last Saved Record
            KeyValuePair<DateTime, float> SnapShot = RawValues[0];
            //The previous record
            KeyValuePair<DateTime, float> PrevValue = RawValues[0];

            //All records except the first and until the penultimate process..
            for (int i = 1; i < RawValues.Count-2; i++)
            {
                if (RawValues[i].Key - SnapShot.Key > ExMax)
                {
                    //Time threshold has been exceeded - save DS

                    //Predecessor is now
                    PrevValue = RawValues[i];
                    //The current DS is the new Snapshot
                    SnapShot = RawValues[i];
                }
                else if (Math.Abs(RawValues[i].Value - SnapShot.Value) > ExDev)//The current record triggers Exception!
                {
                    //The current DS is the new Snapshot
                    SnapShot = RawValues[i];

                    //if the last spoked DS is not the predecessor
                    if (RawValues[i - 1].Key != PrevValue.Key)
                    {
                        //Add predecessors again
                        RawValues.Insert(i - 1, PrevValue);
                        //Index 1 position forward
                        i++;
                    }

                    //Predecessor is now current DS
                    PrevValue = RawValues[i];
                }
                else //Can be omitted..
                {
                    //Predecessor is now the current DS
                    PrevValue = RawValues[i];
                    //remove DS - Index 1 position back
                    RawValues.RemoveAt(i--);
                }
            }
        }
        /// <summary>
        /// Reducing the data points with the same tendency
        /// </summary>
        /// <param name="RawValues">Liste[KeyValuePair[DateTime, float]]</param>
        private static void Compression(ref List<KeyValuePair<DateTime, float>> RawValues)
        {

            //Last Saved Record
            KeyValuePair<DateTime, float> SnapShot = RawValues[1];
            //The previous record
            KeyValuePair<DateTime, float> PrevValue = RawValues[0];

            double ParentSlope = 0.0f;

            //All records except the first and last process..
            for (int i = 1; i < RawValues.Count-1; i++)
            {

                double slope = Slope((float)SnapShot.Key.ToOADate(), SnapShot.Value, (float)RawValues[i].Key.ToOADate(), RawValues[i].Value);

                if (double.IsNaN(slope) || double.IsInfinity(slope))
                {
                    //Ignore, move next
                }
                else if (RawValues[i].Key - SnapShot.Key > CompMax)
                {
                    //Time threshold has been exceeded - save DS

                    //Predecessor is now.. 
                    PrevValue = RawValues[i];
                    //The current DS is the new Snapshot
                    SnapShot = RawValues[i];

                    ParentSlope = slope;
                }
                else if (slope > (ParentSlope + sMax) || slope < (ParentSlope - sMin))//The current record triggers Exception!
                {
                    //The current DS is the new Snapshot
                    SnapShot = RawValues[i];

                    //If the last spoked DS is not the predecessor
                    if (RawValues[i].Key != PrevValue.Key)
                    {
                        //Add predecessors again
                        RawValues.Insert(i, PrevValue);
                        //Index 1 position forward
                        i++;
                    }

                    //Predecessor is now.. 
                    PrevValue = RawValues[i];

                    ParentSlope = slope;
                }
                else //Can be omitted..
                {
                    Debug.Print("Compressed: PS" + ParentSlope + " AS" + slope);
                    //Predecessor is now..
                    PrevValue = RawValues[i];
                    ParentSlope = slope;
                    //remove DS - Index 1 position back
                    RawValues.RemoveAt(i--);
                }
            }
        }
        /// <summary>
        /// computing trend
        /// </summary>
        /// <param name="x1">previous Timestamp</param>
        /// <param name="y1">previous Value</param>
        /// <param name="x2">Timestamp</param>
        /// <param name="y2">Value</param>
        /// <returns></returns>
        private static double Slope(double x1, double y1, double x2, double y2)
        {
            return (y2- y1) / (x2 - x1);
        }
    }
}

Kommentare zum Snippet

 

Logge dich ein, um hier zu kommentieren!