bbregenzer

Further Uses of "Rollups Without Rollups"

Blog Post created by bbregenzer on Oct 16, 2020

Earlier today, I read this very interesting blog by Jerome (go read it!), and it got me thinking about how else the suggested methods could be useful.  With Jerome Lefebvre's method, we can get counts of child elements in particular states without adding a bunch of extra attributes to the child elements, but I have often heard a couple of questions that extend this idea:

  1. How can I get a sum of attribute x values (e.g., volumes, power, etc.) for child elements that are in a particular state indicated by attribute y (e.g., status, product name, etc.)?  The conditional or filtered rollup.
  2. How can I get a list of child elements that are in a particular state, not just a count, into an attribute value for visualization or reporting?

With these two questions in mind, I jumped into PSE and started experimenting.  In the past, my testing with arrays in analyses was often stymied by the lack of functions for arrays (e.g., being able to add or multiply corresponding values in two arrays or perform a dot product).  Jerome’s method of using an index array helped unlocked that for me.

 

Below are some approaches that can answer the two questions posed above, but let me say up front, Jerome and I both tested our methods on a small number of elements (four), and in my case, only triggering once per minute.  My guess is these array-based methods aren’t as efficient as normal rollup analyses, so test carefully before implementing, especially before scaling out to large numbers of elements.

 

Question1:

Let’s start at the end first and then go about explaining it:

  • Lines 1-5 are explained in Jerome’s blog (really, go read it!).
  • Line 6 is used to check which elements are in the Auto state and map the True/False result to a 1/0.
  • Line 7 is where the magic really happens; using the index array (Line 3), we go through each entry in the IsAuto 1/0 array (line 6) and multiply it by the corresponding entry in the attribute value array (line 4); basically, we are zeroing out the values coming from child elements that aren’t in the Auto state.  Note: this isn’t a fully original idea as it expands upon another interesting blog from Jerome (I know; the guy is good).
  • Line 8 is where we get our desired final value by applying the Total function to sum up the values in the array from Line 7.

To help illustrate, here is a numeric example (orange font shows how the filtering for Auto gets applied):

vChildCount [1]

4

vLastNVals [2]

[96.37,99.157,86.398,18.173]

v1ToN [3]

[1,2,3,4]

vChildVals [4]

[78.976,78.976,78.976,78.976]

vModes [5]

[Cascade,Prog-Auto,Auto,Auto]

vAutoTrue [6]

[0,0,1,1]

vAutoValues [7]

[0,0,78.976,78.976]

vAutoValSum [8]

157.95

Notes: Like in Jerome’s rollup example, the same final result can be achieved by adding additional attributes to the child elements. For this example, analysis attributes that use an expression like:
If ‘Mode’ = “Auto” Then ‘Tag Value’ Else 0
would be appropriate. These “filtered” attributes could then be summed at the parent level with a rollup analysis. But as Jerome mentioned, this starts to add up when you want to do this for multiple states.

Question 2:

Again, let’s start at the end:

  • Lines 1-7 are affectively the same, the main differences being:
    • Line 5 grabs the values of string builder attributes holding the names of the child elements instead of numeric attributes that we want to sum.
    • Line 7 is much the same calculation as before, but here we return an array that holds the indices of elements in the state Auto and a zero otherwise.
  • Line 8 trims the array to get rid of the zero values so only the indices of the Auto elements remain.
  • Line 9 applies the array of auto element indices (Line 8) to the array of element names (Line 5) to return an array that only holds the names of elements in the Auto state.
  • Line 10 converts the array of names (Line 9) to a string value so it can be written to an output attribute (some checking for empty arrays is also included).

The result data for two examples look like the following:

 

Run1

Run2

vChildCount [1]

4

4

vLastNVals [2]

[24.223,3.7947,0.76475,14.358]

[24.223,3.7947,0.76475,14.358]

v1ToN [3]

[1,2,3,4]

[1,2,3,4]

vChildNames [4]

[Element1,Element2,Element3,Element4]

[Element1,Element2,Element3,Element4]

vModes [5]

[Prog-Auto,Auto,Program,Auto]

[Cascade,Cascade,Manual,Prog-Auto]

vAutoTrue [6]

[0,1,0,1]

[0,0,0,0]

vAutoIndex [7]

[0,2,0,4]

[0,0,0,0]

vAutoIndFilt [8]

[2,4]

[]

vChildInAuto [9]

[Element2,Element4]

[]

vChildInAutoStr [10]

[Element2, Element4]

None

Notes: I can’t think of way to accomplish this with rollup analyses since they can’t act on strings, but for visualization purposes, you could produce similar lists, with no need for additional attributes or analyses in AF, in PI Vision and PI DataLink by using Collections with attribute filters and the Asset Filter Search, respectively.

I could see this approach being modified to address the “tell me which element is producing the rollup min/max value” use case as well, but I haven’t had a chance to test it.

 

Note about both cases: scheduling can be a bit tricky if you want event triggered scheduling since you can’t trigger on the arrays themselves.  You’ll have to get one or more input attributes that update at the desired times/frequency into variables in the analysis.

 

Well, if you got this far, I hope you think it was worth it.  If you have any comments or ideas or come up with your own use case/extension, please post below, and as always, thanks for your time!

Outcomes