Introduction to 4D Calculated Indicators

A calculated indicator has its readings calculated using a formula, rather than entered manually, for example. With the 4D Analytics functionality, the calculations you develop can use readings from both 4D and non-4D indicators as inputs.
This overview of calculated indicators covers the following topics:

Formulas in Stored Procedures

You can enter the formula for a calculated indicator in APM as a VB.NET or C# script. However, if you need a complicated calculation requiring extensive or complex processing, you can use a stored procedure. At run-time, the indicator is recalculated when the calculation engine processes it.
When calculated, the value of the inputs are fed to the stored procedure. The stored procedure must return either a number or a string, and this value is used to create the reading for the indicator. If a calculation fails, a reading is still created, but it is flagged as “Invalid” and the appropriate reason for the invalid reading is noted.
When defining the indicator, provide the name of the stored procedure and calculation inputs with names that correspond to the parameters used in the procedure. A calculation input and its parameters must use the same data type, and the procedure must include a return parameter that is either a string or number. You can create calculation inputs for stored procedures as you would for a VB.NET or C# script, except that the inputs cannot use the array aggregation type.
Note: When using Date and DateTime data types, be aware that the Date type uses the enterprise time zone, and the DateTime type uses Coordinated Universal Time (UTC).

Formulas in VB.NET and C# Scripts

You can create a formula for a calculation based on three types of information:
Calculation inputs: data from another numeric 4D indicator; data from the current calculated indicator; or data derived from an APM object (for example, a count of work orders or the dates when indicator readings were entered)
Mathematical functions: such as add, subtract, multiply, or divide
Constants: a fixed value used in the calculation
For example, a calculation for determining the average of three indicator values might be:

Calculation Inputs

A calculation input is a variable used in a calculation that represents data from the system. This data can be from two types of sources:
Based on indicator reading(s): data from an asset indicator
Based on a filter: data derived from one or more APM objects (for example, the total number of work orders based on a selected work type)
The name of the calculation input is used as a placeholder in the formula entered for a calculated or performance indicator.
TOP

Indicator Reading-Based Inputs

Indicator reading-based inputs use the indicator readings from numeric 4D indicators (for example, pressure or temperature).

Using the Current (Calculated) Indicator as an Input

You can include the current value of the current indicator as an input to its own calculation. The value of the input is its most recent reading. However, unlike other inputs when a new value for the current indicator is calculated, this will not cause the calculation to be triggered again.

Aggregating Indicator-Based Inputs

An aggregate calculation input is one in which the values of several readings from the same indicator are aggregated or combined to determine a value for the input. For example, you could define an aggregate input to use the average value of the indicator’s last five readings.
You can specify the number of readings to use in three ways:
When the calculation is evaluated, at least one reading must be selected for the input. If no reading is available (for example no reading was entered for the time period specified), a new value for the indicator cannot be calculated. In addition, readings that have been marked as “incorrect” are ignored.

Filter-Based Calculation Inputs

A filter-based calculation input defines a set of filtering criteria that, when evaluated, results in a value. The value can be a count of the items that satisfy the filtering criteria or it can be an aggregate of an attribute that belongs to the object being filtered or to some other object related to it through a join-path.

Count-Type Inputs

When evaluated, a count-type input results in a simple count of all the objects that satisfy a set of filtering criteria. As an example, consider a formula to calculate the percentage of work orders completed within the last 30 days that were planned to be complete:
Percentage = (Number of completed work orders where the planned completion date was in the last month) ÷ (Total number of work orders where the planned completion date was in the last month) x 100
In this formula, the two inputs to this calculation are:
Each of these inputs can be defined as a count of work orders that satisfy a set of filtering criteria. For example, the filtering criteria to determine the value for the first input (that is, number of completed work orders in the last 30 days) might be:

Aggregating Filter-Based Inputs

Aggregate-type calculation inputs apply an aggregation type to one of the attributes that belong to the object being selected or to one of its related objects.
As an example of an aggregate-type input, consider a performance indicator designed to measure the average cost of work orders completed within the last 30 days. In this case, the formula could consist of a single input with the following criteria:
The same result could also be achieved using a more complex formula with a different aggregate type:
Average cost = (Sum of the actual costs of work orders closed in the last 30 days) ÷ (Count of work orders closed in the last 30 days)
TOP

Using Numeric and Non-Numeric Data Types as Inputs

You can include data other than indicator readings as an input to a calculation. For example, you might want to use an indicator reading’s collection date in a calculation so that you can determine the length of time that has elapsed between two readings.
Note: Users who want to use inputs other than indicator readings as calculation inputs should have a basic understanding of object-oriented modeling concepts, as well as knowledge of the APM object model as it relates to indicator readings.
If your input is based on an indicator reading, you can select any eligible attribute (field) on the Indicator Reading class itself or on any class that is related to it through a single-cardinality relationship. For example, you could select an attribute on the asset that owns the indicator. You can select attributes from classes related through a single-cardinality relationship:
The following graphic illustrates examples of classes related to the indicator reading class:
Similarly, for filter-type inputs, you can select any eligible attribute from the class you are filtering or from any class related to it through a single-cardinality relationship.
Eligible attributes on which inputs can be based are:
For more information on relationships and attributes, see Relationship Types and Data Types. To learn more about the APM object model, see Object Model Overview.

Aggregation Types

The supported aggregation types are:
Note: The array aggregation type is not supported for indicators that are calculated using a stored procedure.

Array Aggregation

An array is an aggregation type that allows you to work with a list of values. It is required for inputs that are based on non-numeric data such as strings and dates. These types of data cannot be aggregated using any of the other aggregation types (that is, sum, mean, average, maximum, minimum, and difference), which are all intended to be used with numeric data only. While the array aggregation type is typically used to handle non-numeric data, you can also use it with traditional numeric inputs.
The system interprets an array-type input as a numbered list of elements. The data type of the elements in the list is determined by the type of attribute on which you have based the input. For example, if the input is based on an indicator reading’s Date collected attribute, the array consists of a list of dates.
VB.NET and C# scripting lets you work with the individual elements of the array. As an example, consider an input to a calculation that is based on the last three readings for an indicator and that is defined to return an array of dates based on the indicator reading’s Date collected attribute. Using VB.NET or C#, you can subtract the 3rd date in the array from the first date in the array and thus calculate the number of days between these readings. This would allow you, for example, to calculate the gas consumption on a vehicle (for example, miles per gallon) or the rate of rise in oil consumption.
Because the order of the elements in the array is often important, when you select the Array aggregation type you can also optionally specify the way the elements of the array are ordered. For example, in an array of indicator reading values, you can specify that the readings be ordered by the Date Collected attribute. When sorted, the elements of an array are presented in ascending sequence. You can only specify one sort criterion.
TOP

First Aggregation Type

The First aggregation type allows you to select the first element in a selection list. For example, you could use this aggregation type on an input that needs to return the Collection date of the first reading entered this month.
When you select the First aggregation type, the order of the elements in your selection list is important. It is therefore necessary that you also specify ordering information. For example, if you want the input to be the Collection date of first reading entered this month, then you will need to sort the readings in ascending order based on collection date.

Last Aggregation Type

The Last aggregation type is the opposite of the First aggregation type in that it allows you to select the last element is a sorted list. For example, you could use it to retrieve the value of the last reading entered in the previous month.
TOP

How Calculation Inputs are Used in VB.NET and C# Scripts

For numeric data, including numeric indicator readings and numeric data types, the system substitutes the value part of the data into the calculation string as a float. This means that the unit of measure portion of the data is ignored. For example, if a temperature indicator’s most recent reading was 10 degrees Celsius, the value that is substituted for the input is 10.
Inputs based on non-numeric data types are inserted into the calculation as follows:
 
TOP

Units of Measure

When you create a calculation that has inputs with different units of measure, you must account for the differences in the formula. For example:
Unlike Integers, Floats, and Base currency amounts that consist of a single numeric value, the other numeric data types (that is, Durations, Quantities, Prices, and Currency amounts) are compound data types. In addition to their numeric value, they also have a unit of measure (as in the case of Durations and Quantities), a currency (as in the case of Currency amounts), or both (as in the case of Prices).
For these compound types, only the numeric portion of the value is used in the calculation. For example, if the sum of the estimated duration of a group of work orders is 20 hours, the value of the input that is used in the calculation will be 20. The unit of measure (UOM) component (hours) is ignored. The unit of measure must, therefore, be taken into account as part of the formula.
When you select the unit of measure (UOM) for the indicator, the system assumes that the value resulting from your calculation is in the selected UOM. When you create a calculation that has inputs with different UOMs from the indicator, you must account for the differences in the formula. For example, if you create a calculation with the result in “eaches”, but the indicator is expressed in “dozens”, you must divide the result of your calculation by 12.
In addition, the attribute’s value for each instance that meets the selection criteria can be expressed in a different unit of measure or currency. For example, the Estimated Duration on one work order might be expressed in days, while on another it could be in hours. For this reason, when aggregating the value in a compound attribute, you must also identify the unit of measure or currency in which the aggregated value should be expressed. For example, when aggregating the value in a duration attribute such as the Estimated Duration example, you would have to specify whether the resulting value should be expressed in hours, days, or weeks.
Therefore, using the same example:
In addition, for Quantities and Prices, only values with units of measure from the same unit of measure category are included in the aggregate value. In other words, if you specify that the result should be expressed in the meters unit of measure, which is in the Length unit of measure category, only values expressed in units of measure from that category (for example, yards, feet) are included in the aggregate value.
In a similar way, in the case of Currency Amounts and Prices, only values having the same currency value are included in the aggregate value.
TOP

Integers and Averages

Integers are whole numbers and as such do not include fractions or decimals. Integers are used in a few places in the APM system. When working with calculations that include integers, remember that the result are expressed in a whole number. When using the Average aggregation type with integers, the system does not round the result but truncates the resulting value to a whole number.
For example, to calculate the average number of tasks in a group of work orders, you might create the following calculation input:
AvWorkOrderTasksPerWO =
If you have the following data
the result of the calculation [(6+1+1)/3 = 2.6667] is truncated to an integer (2).
If you need to have the result of a calculation include fractions, you can use the Sum aggregation type instead and then divide by the number of the objects being averaged. Using the same example, you would instead create two calculation inputs:
You calculation would then be:
NumberWorkOrderTasks/NumberWorkOrders
The result would be 2.6667.

Units of Measure

The unit of measure (UOM) selected for the calculation also affects your result. For example, if the UOM for the indicator described above is “each”, no decimal places are expressed. In the first calculation, the result would be expressed as 2. In the second calculation, the result will be rounded to 3.
To have a result with decimal places, select a unit of measure set up to express one or more decimal places. If necessary, you can have your system administrator create an appropriate unit of measure using the DTA Editor utility.
TOP

Functions in VB.NET and C# Scripts

A function is a series of VB.NET or C# statements that return a value. You can use functions to create a calculation for a calculated indicator or asset health calculation that includes logical operators such as IF, AND, OR, and so on. For example, you could do this if you want a calculation that includes an IF THEN statement.
 
Note: To create a calculation using a function, you should be familiar with VB.NET or C# scripting.
For example:

VB.NET

If A > B Then
return A
Else
return B
End if

C#

if (A > B)
{
return A;
]
else
[
return B;
}
Where A and B are the argument names.
A function returns a value by assigning a value to the function’s name in one or more statements of the procedure. The return data type of a function is always a Variant.

Calculation Inputs and Argument Names

In order for a function to work, the calculation input names defined for the indicator must match the arguments named in the function. Therefore, in this example you must also define calculation inputs named “A” and “B”. This is similar to entering a regular calculation expression.
When you define a calculation for an indicator without functions, the system processes the calculation by wrapping your expression in a function statement. For example, if your calculation is A / B, the system processes it as:
A / B
When you create a calculation by defining your own function, the system behaves similarly: in the first line of the statement the system inserts your calculation input names as arguments for the function. This means that you can leave the arguments for the function blank. However, for your own record-keeping, you will probably want to enter the argument names anyway.
Note: Your calculation input names must match the names of the arguments used in the function.
TOP

Function Examples

Using a String in a Calculation

In this example, the value of a numeric indicator is calculated using a different formula, depending on the value of a input (called StringInput). This calculation has two inputs:
If the value of StringInput is “Normal”, then the value of the indicator is set to the value of Input1. On the other hand, if the value of StringInput is “Squeaking”, then the value for the indicator is set to twice the value of Input1. Finally, if the value of StringInput is “Worn out”, then the value of the indicator is set to three times the value of Input1.
For example:

VB.NET

If StringInput = “Normal” Then
Return Input1
Elseif StringInput = “Squeaking” Then
Return Input1 * 2
Elseif StringInput = “Worn Out” Then
Return Input1 * 3
End If
Return 0

C#

if (StringInput == “Normal”)
{
return Input1;
}
else if (StringInput == “Squeaking”)
{
return Input1*2;
}
else if (StringInput == “Worn Out” Then
{
return Input1*3;
}
return 0;

Using an Enumerated Attribute in a Calculation

In this example, the value of a numeric indicator is calculated based on the Active Status of an asset. The Active Status is an enumerated attribute that has two possible values:
When referring to an enumerated value in the calculation string, you can use either the enumerated value’s integer or its corresponding constant (for example, c_Active). Constants are defined for you in the box above the calculation. In either case, you do not need to use quotation marks. The calculation has the four following inputs:
Note: Because StatusInput is a reading-based input, the indicator used to create the input must have at least one reading entered for the input to have a value.
This calculation does the following: If the asset status is c_Active, then the value of the calculated indicator is determined by adding together the value of Input2 and Input3. Otherwise, the indicator’s value is equal to what it is presently (that is, Input4).
For example:

VB.NET

’if the asset status is Active, calculate a value, otherwise don’t
If StatusInput = c_Active Then
Return Input2 + Input3
Else
Return Input4
’Input4 is the current value
End if

C#

//if the asset status is Active calculate a value, otherwise don’t
if (StatusInput == c_Active)
{
return Input2 + Input3;
}
else
{
return Input4;
//Input4 is the current value
}
 
TOP

Using a Boolean Attribute in a Calculation

Using a Boolean attribute in a calculation is the same as using an enumerated attribute. The only difference is that Boolean attributes can only have two values (that is, True or False).
In this example, the value of a numeric indicator is calculated based on the setting of a boolean attribute. If the Boolean’s value is True, then the value of the calculated indicator is determined by adding together the value of Input 2 and Input3. Otherwise, the indicator’s value is equal to what it is presently (that is, Input4).
The calculation has the four following inputs:
For example:

VB.NET

’if the “Has an alarm” Boolean is True calculate a value, otherwise don’t
If Input1 = True Then
Return Input2 + Input3
Else
Return Input4
’Input4 is the current value
End If

C#

//If the “Has an alarm” Boolean is True calculate a value, otherwise don’t
if (Input1 == true)
{
return Input2 + Input3;
}
else
{
return Input4;
//Input4 is the current value
}
 

Using an Array in a Calculation

The calculation in this example has two input numeric inputs. They are:
This function calculates the weighted average of the three values in the array if the value of the AverageType input is “c_WeightedAverage”. Otherwise, it calculates the average in the normal way.
For example:

VB.NET

If AvgType = c_WeightedAverage Then
Return (ArrayImp(0)*3 + ArrayImp(1)*2 + ArrayImp(2))/6;
Else
Return (ArrayImp(0) + ArrayImp(1) + ArrayImp(2))/3;
End If

C#

If (avgType == c_WeightedAverage)
{
return (ArrayImp[0]*3 + ArrayImp[1]*2 + ArrayImp[2])/6;
}
else
{
return (ArrayImp[0] + ArrayImp[1] + ArrayImp[2])/3;
}

Number of Values in an Array

If you do not know how many values will be in the array, use the Lbound and Ubound functions in the array. For example, if the array contains readings taken over the last weeks, you might not know in advance how many readings are in the array.
The following example shows how to use these functions. In this example, there is one calculation input called InputArray, which is an array of indicator readings.
For example:

VB.NET

If ReadingsList.Length = 0 Then
Return 0
End If
 
Dim total As Integer = 0
Dim divisor As Double = 0
For i As Integer =0 To ReadingsList.Length - 1
total = total + (i + 1) * ReadingsList(i)
divisor = divisor + (i + 1)
Next
Return total/divisor

C#

if (ReadingsList.Length == 0)
{
return 0;
}
 
double total = 0;
double divisor = 0;
for (int i = 0; i <= ReadingsList.Length -1;i++)
{
total = total + (i +1) * (double)ReadingsList[i];
divisor = divisor + (i + 1);
}
return total/divisor;
 
TOP

Using a Date Attribute in a Calculation

In this calculation, two reading-based inputs from the same indicator are used to calculate the rate of rise of that indicator based on its last 10 readings. The two inputs are:
This calculation takes the difference in reading values and divides it by the number of days that have elapsed between the first and 10th reading. To do this, it first declares a variable called DateDelta. The value of this variable is then set by subtracting the first date in the array from the last one, which results in the number of days. Next, the value of the ReadingDifference input is divided by the value in the DateDelta variable.
For example:

VB.NET

Dim DateDelta As TimeSpan = DateArray(9) - DateArray(0)
Return ReadingDifference/Date.Delta.TotalDays

C#

TimeSpan DateDelta = DateArray[9] - DateArray[0];
return ReadingDifference/DateDelta.TotalDays;

Required Proximity

Required proximity is a setting that prevents APM from processing a calculation when indicator readings used in the calculation are out of date. For example, you can say that all of the indicator readings included in the rule must have been collected within 1 day of each other.

What Happens When a Calculation Fails?

Using advanced calculation features can increase the likelihood that errors will occur when defining calculations. For example, a single typographical error in the calculation string for a descriptive indicator could result in an undefined value for the indicator.
If a calculation produces an undefined value, the system displays a message and produces an indicator reading. This reading is flagged as invalid (that is, incorrect) and does not appear in graphs, and so on. The indicator’s last valid reading remains its “current” reading.
As with normal calculated readings, you can look at the values for each of the inputs that were used in the calculation, which should help you to determine the source of the error (for example, divide by zero, unexpected value, typographical error, and so on).

Calculation Failures

The following lists various causes for calculation failures. The system creates a reading and flags it as incorrect in each of these situations.
Divide by zero: This situation occurs when the calculation contains an input that is used in the calculation as a divisor and the current value of the input is equal to zero.
Null input: This situation occurs when one of the inputs in the calculation evaluates to null (no value). This can happen for several reasons, for example:
Note: You can tell the system to allow null values on individual calculation inputs. If you select to allow a null value in a calculation, you might want to account for this possibility in the VB.NET or C# script in your calculation.
Calculation string error: This situation occurs when the calculation string itself is flawed. This can happen, for instance, when the calculation expression contains Boolean logic that does not properly deal with every value that an input can have.
However, there are other situations in which a calculated indicator is prompted to recalculate, but the calculation does not occur:
Indicator’s asset is non-operational: If the asset that owns the calculated indicator is in a non-operational state, the indicator is not recalculated if a new reading is entered for one of its inputs and that input’s indicator belongs to a different asset. However, if the input’s indicator belongs to the same asset, the indicator is recalculated.
The reason for this difference in behavior is: In the first case, to prevent the unintentional recalculation of an indicator on a dormant piece of equipment. In the second case, the assumption is that if readings are intentionally being entered for other indicators on the same piece of equipment, then it’s reasonable to expect that the calculated indicator’s value should also be updated even though the equipment is not being used.
Inputs are outside the required proximity: This setting is only applicable when a calculation uses more than one indicator reading-based calculation input. This rule does not apply to filter-based calculation inputs. With required proximity, you can specify the length of time within which all readings must have been collected in order for APM to evaluate the rule or calculation. If any of the indicators fall outside of the required time period, APM does not evaluate the calculation.
These two situations are not considered calculation failures. Therefore, no reading is produced when they arise.