csawyer

DisplayDigits Exposed in AF 2018 / AF SDK 2.10

Blog Post created by csawyer Employee on Jun 18, 2018

The 2.10 release of AF SDK unveiled DisplayDigits as a property you can investigate and set on an AF DataReference. Let’s do a quick investigation of what this property entails.

 

Further, there is a new .DisplayValue() method on the AFValue object for rendering single and double-precision floating point numbers.

 

What DisplayDigits Is

DisplayDigits is a setting that you can place on floating-point number tags to convey how much precision you wish to be displayed on-screen by downstream applications.

 

pse_example.png

Valid settings are any integer number from -20 up to 10.

 

What it’s used for

Most of your floating-point data will be expressed either in 32-bit or 64-bit floating point numbers. This allows for a large variety of decimal expression with varying degrees of precision. Controlling what precision you get back is what DisplayDigits is for.

Numerical precision

Consider the floating-point data types in the PI Data Archive…

TypeFloat16Float32Float64
MinimumZero of tag1.175494351 E-382.2250738585072014 E-308
MaximumSpan of tag3.402823466 E +381.7976931348623158 E +308
Exponent-8 bits11 bits
Mantissa-23 bits52 bits
Accuracyn/a7 digits15 digits

Floating point datatypes make a representation of a decimal number with relative increasing levels of precision given the number of bits used.1

Let’s experiment:

The SINUSOID tag on your Data Archive by default is stored as a 32-bit floating-point number. Let’s investigate what all the possible DisplayDigits settings exposed in AF SDK reveal.

First you will need to use an AF Database and set an attribute to the SINUSOID tag on your PI Data Archive. The DisplayDigits property hangs off the AFAttribute class and not off of PIPoint.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OSIsoft.AF;
using OSIsoft.AF.Asset;
using OSIsoft.AF.Data;
using OSIsoft.AF.PI;


namespace DisplayDigitsExample
{
    class Program
    {
        static void Main(string[] args)
        {


            // Let's get the server
            PISystems pisystems = new PISystems();


            // Get an injection well asset
            AFElement well = pisystems["CLSAF"].Databases["TransformedWells"]
                .Elements["Injection Wells By Contractor"]
                .Elements["Paisano Transmission And Service Inc"]
                .Elements["Site1.F100_IW01"];


            // Get the line pressure
            AFAttribute linepressure = well.Attributes["Line Pressure"];
            
            Console.WriteLine($"Line Pressure uses PI tag {linepressure.DataReference.ConfigString}");
            Console.WriteLine($"Present Value: {linepressure.GetValue().ValueAsSingle()}");
            Console.WriteLine($"Display Digits Setting: {linepressure.DisplayDigits}");


            // Display all the DisplayDigits settings for this PI value
            for (int i = 10; i >= -20; i--)
            {
                Console.WriteLine($"Value with DisplayDigits Set to {i}: {linepressure.GetValue().DisplayValue(i, null, true)}");
            }


            Console.ReadLine();


        }
    }
}

 

Here's the same example in VB.Net...

 

Imports OSIsoft.AF
Imports OSIsoft.AF.Data


Module Module1
    Sub Main()
        Dim piServers = New PISystems


        Dim wellsDB = piServers("CLSAF").Databases("TransformedWells")


        Dim well = wellsDB.Elements("Injection Wells By Contractor") _
            .Elements("Paisano Transmission And Service Inc") _
            .Elements("Site1.F100_IW01")


        Dim linePressure = well.Attributes("Line Pressure")


        Console.WriteLine("Line pressure uses PItag " & linePressure.DataReference.ConfigString)
        Console.WriteLine("Present value: " & linePressure.GetValue().ValueAsSingle())
        Console.WriteLine("Display Digits Setting: " & linePressure.DisplayDigits)


        For i = 10 To -20 Step -1
            Console.WriteLine($"Value with DisplayDigits Set to {i}: {linePressure.GetValue().DisplayValue(i, Nothing, True)}")
        Next
        Console.ReadLine()
    End Sub
End Module

 

This yields the following:

img

 

So what’s with the negative and positive DisplayDigits?

After you run some example code against floating point data you have you will notice how DisplayDigits applies zero-padding and rounding.

Positive DisplayDigits settings will force a floating point number to be returned with a fixed number of digits to the right of the decimal point, up to 10 and include padding zeroes (0) where necessary.

If the number is more significant than what you specificed then the number may be rounded or truncated. For instance, if the value stored is 63.90804 but DisplayDigits is set at 2, the number is returned back as 63.91

A negative DisplayDigits setting instead determines the number of significant digits to display, with no zero padding.  If a rounding occurs the number of digits displayed may be less than the setting.

Why do I see more digits when I inspect .Value than when I use -7 or -15 DisplayDigits?

Floating point types are inherently imprecise as it’s a reflection on how your CPU represents floating-point values, given that the binary representation of the number is likely to not be exact.

That’s why you should use the new DisplayValue() method that’s been added to the AFValue object.

Footnotes

1 The PI Data Archive uses 32-bit single precision and 64-bit double precision as well as 16-bit

Outcomes