Showing results for 
Search instead for 
Did you mean: 

Working with Results of StatBlockCalc

I'm trying to work with the results of a call to StatBlockCalc to several channels and was hoping to do it efficiently without creating a new channel. The script I'm trying to create would ideally do the following:

  • Determine a subset of rows to analyze that are a given number of rows apart, for instance every 720 rows (1,721,1442,2163, etc)
  • Calculate the mean value for this subset of rows for each channel in a channel group (could vary from 10-20 channels)
  • Put the result in a vector variable so that I could access each channels mean value (i.e. meanVector(3) would access the mean value for the third channel)

I need to call this several times for different subsets of rows (in my case 720 times) such that each subset looks like:

  • 1, 721, 1442, 2163, ...
  • 2, 722, 1443, 2164, ...
  • 3, 723, 1444, 2165, ...
  • ...
  • 719, 1441, 2162, ...

So I'd prefer not to have to create 720 new channels and then delete them or call StatBlockCalc 720 times for each channel.


My current code that just makes new channels (but is slow) looks like:


For iLoop1 = 1 to 720
      'sRows is a function of iLoop1  
      Call StatBlockCalc("Channel", sRows, ChnList)
      sMeanChn = "[" & iAvgIndex & "]/ArithmeticMean"
      Set oMeanChn = Data.GetChannel(sMeanChn)
      'Do something with oMeanChn

I tried using the solution in this post: http://forums.ni.com/t5/forums/v3_1/forumtopicpage/board-id/60/thread-id/10442/page/1, but it seems the only way the ResultStatArithMean property is created is if the rows are set to "1-"


Is there any way that I can avoid creating and deleting 720 channels?

0 Kudos
Message 1 of 6

Hi meatballosaurus,


At the bottom of that link you mentioned there is a long list of the global variables populated every time the StatBlockCalc() command is run.  You just need to read out the value from, say, the StatArithMean variable and save it to the target array variable you want to fill.


Brad Turpin

DIAdem Product Support Engineer

National Instruments

0 Kudos
Message 2 of 6

I realized I never got back to this and have just been making due with my slow solution up to this point, but I'd really like to speed this up.


I don't think the solution Brad suggested works unless I call the StatBlockCalc command for each channel (right now I only need to call it once per subset of rows for x number of channels).


Quick background on the raw data: I have several channels of data recorded relative to an engine crankshaft encoder. Each channel contains up to 300 engine cycles of data in 0.5 degree resolution (this number could change) and 360 degrees per cycle. What I'm trying to accomplish is getting a single cycle average for each channel. For now lets assume I have 3 channels and each channel contains 3 cycles of data. Ultimately, this is kind of what I'm trying to achieve (unless there is an even faster way:

    StatSel(6) = "Yes"                                      ' Arith. mean
    '------------ Result Storage ------------
    StatResChn       = 0              'v1g - Changed from 1 to 0
    StatResChnNames  = 0
    StatResChnNameFormat= "NameName"
    StatClipCopy     = 1              'v1g - Changed from 0 to 1
    StatClipValue    = 0
    StatFormat       = ""
    sRows = ""

    Dim aStats()
    ReDim aStats(iChnCount)

    'Loop through each 0.5 degree of engine cycle, average all 3 cycles for each channel
    For iLoop1 = 1 to (720) 'Real code has a variable instead of 720
      'This creates the subset of rows for each engine cycle position 
      'In this example it creates a subset for 3 cycles, but in the real code it is
      'dynamic and is a function of the total number of cycles
      sRows = iLoop1 & "," & (720+iLoop1) & "," & (1440+iLoop1)

      ' When iLoop1 = 1, this averages the 3 cycles for each channel at crank angle position 0.0 degrees
      ' When iLoop1 = 2, this averages the 3 cycles for each channel at crank angle position 0.5 degrees
      Call StatBlockCalc("Channel", sRows, "'[1]/HS_P_CYL1' - '[1]/HS_P_CYL3'")

      'This next part is what I can't figure out and is non-functioning code
      'CycleAvg_HS_P_CYL1(iLoop1) = StatBlockCalc result for channel 1
      'CycleAvg_HS_P_CYL2(iLoop1) = StatBlockCalc result for channel 2
      'CycleAvg_HS_P_CYL3(iLoop1) = StatBlockCalc result for channel 2
    Next 'engine crankshaft position

Based on this example, my current code ends up creating 720 channels of length 3 and subsequently immediately deletes them. (most of my data would result in creatation/deleting channels that are 300 points in length)

I believe Brads solution would require me to have 3*720 total calls to StatBlockCalc (instead of 1*720 calls) but not require creating/deleting channels. (most of my data would require 15*720 or 15*1440 calls to StatBlockCalc)


0 Kudos
Message 3 of 6

Hi Brad_Turpin, 

I'm currently doing the same thing but I'd like to write the global variables directly to an existing channel appending the new variable to the end of the channel each time I run the routine.

What command will write a single value to a channel?



0 Kudos
Message 4 of 6

Hi meatballosaurus,


You're right that accessing the statistical calculation results with the global variable approach only works if you call the StatBlockCalc() command once for each channel.  I don't actually think the performance difference will be that large between 1 StatBlockCalc() command over N channels vs. N StatBlockCalc() commands over 1 channel each.  But certainly the latter approach will require more lines of code.  I can only think of these two options, though.  Either write new channels with the results of all N channels in them, or call StatBlockCalc() N times and read off the statistical results from the global variables each time.


A couple of DIAdem versions ago, a new command and global variable approach was introduced which was designed to make working with this situation easier, but it does not change this choice-- you still have these two options, it's just a little easier to parametrize which statistical values to calculate now.


Brad Turpin

DIAdem Product Support Engineer

National Instruments

0 Kudos
Message 5 of 6

Hi Dave,


If you already have the channel in the Data Portal, you just need to grab the channel object for it to a variable, then you can assign the new statistical value to the end, like this:

Set Group = Data.Root.ChannelGroups(GroupNameOrIndex)
Set Channel = Group.Channels(ChanNameOrIndex)
Row = Channel.Size + 1
Channel.Values(Row) = StatArithMean

If you need to first create the channel and/or its parent group, this is what it looks like:

Set Group = Data.Root.ChannelGroups.Add(GroupName)
Set Channel = Group.Channels.Add(ChanName, DataTypeChnFloat64)
Row = Channel.Size + 1
Channel.Values(Row) = StatArithMean

The channel will automatically expand in size as you assign new values to rows that didn't have values previously.


Brad Turpin

DIAdem Product Support Engineer

National Instruments

0 Kudos
Message 6 of 6