10 Replies Latest reply on Sep 5, 2016 12:39 PM by v.alves

    Any method that implements compression/exception in AFSDK for AFValues?

    Jerome Lefebvre

      I am implementing a program that computes some forecasts values that will be written to the PI Data Archive when a trigger is raised.

      As there is time between when the forecast is computed and written to the data archive, to speed things up at write time, I am trying to apply compression and exception to the data in the code as opposed to letting the data archive do it.

      As anybody written such an algorithm before I try my hands at doing so?

       

      Something like:

      static AFValues compressExceptData(AFValues vals, float compressionDeviation, float exceptionDeviation)

        • Re: Any method that implements compression/exception in AFSDK for AFValues?
          gregor

          Hi Jerome,

           

          For compression, you can use PI Buffer Subsystem. For future data PI Points by default have compression set to off, so you need to turn it on.

          I wouldn't know any AF SDK method which can be used to apply exception but you can easily write your own function. You use your current snapshot as the initial value and calculate the upper and lower boundary based on excdev or excdevpercent and span. Now you process each snapshot candidate, ordered forward in time, against the upper and lower boundary. If it falls outside, the snapshot candidate becomes the new snapshot, otherwise you discard it. Please be sure to re-calculate the boundaries with every new snapshot.

          3 of 3 people found this helpful
          • Re: Any method that implements compression/exception in AFSDK for AFValues?
            Rick Davin

            Interesting topic, Jerome. And timely.  I have a customer that's writing an interface to PI and he wants to perform an exception test on his end before sending data to the Data Archive, where he will let the Data Archive worry about compression.

             

            To be a well-rounded solution, I would think one would not just look at the PICommonPointAttribute.ExceptionDeviation field but also the ExceptionMinimum and ExceptionMaximum fields as well, which means one must inspect not  just the Value but the Timestamp too.

            2 of 2 people found this helpful
              • Re: Any method that implements compression/exception in AFSDK for AFValues?
                Jerome Lefebvre

                Here is my first quick version of the exception algorithm.

                NOT A FULL IMPLEMENTATION OF EXCEPTION TESTING, NOT HAS BEEN TESTED. DO NOT USE THIS CODE.

                 

                        static AFValues applyException(AFValues vals)
                        {
                            PIPoint tag = vals.PIPoint;
                            tag.LoadAttributes(new string[] { PICommonPointAttributes.ExceptionMinimum, PICommonPointAttributes.ExceptionMaximum, PICommonPointAttributes.ExceptionDeviation});
                            var a = tag.GetAttribute(PICommonPointAttributes.ExceptionMinimum);
                            UInt16 exceptMin = (UInt16)tag.GetAttribute(PICommonPointAttributes.ExceptionMinimum);
                            UInt32 exceptMax = (UInt32)tag.GetAttribute(PICommonPointAttributes.ExceptionMaximum);
                            Single exceptDev = (Single)tag.GetAttribute(PICommonPointAttributes.ExceptionDeviation);
                            AFValues keptValues = new AFValues();
                
                
                            // The first value is considered as the "archive value"
                            keptValues.Add(vals[0]);
                            // Also possible to grab the snapshot value and use that instead.
                            // tag.CurrentValue();
                            
                            AFValue lastKeptValue = vals[0];
                            foreach(AFValue val in vals.Skip(1)) {
                                bool outsideDeadBand = Math.Abs(keptValues[keptValues.Count - 1].ValueAsDouble() - val.ValueAsDouble()) > exceptDev;
                                bool tooSlow = (keptValues[keptValues.Count - 1].Timestamp.UtcSeconds - val.Timestamp.UtcSeconds) > exceptMax;
                                bool tooQuick = (keptValues[keptValues.Count - 1].Timestamp.UtcSeconds - val.Timestamp.UtcSeconds) < exceptMin;
                                if (tooSlow || (!tooQuick && outsideDeadBand))
                                    keptValues.Add(val);
                            }
                            return keptValues;
                        }
                
                3 of 3 people found this helpful