Cycle V2.0: Realtime Cycle Averaging

Contents

    0: Introduction
    1: Definitions
       1.1: Triggers
       1.2: Regions
       1.3: Averages
       1.4: Rate
       1.5: Discard
    2: Implementations
    3: Invocation

0: Introduction

Cycle is a little language useful for performing calculations relative to instrument operating cycles. Its function is to average data over specified regions. Regions are defined relative to specific Triggers, and Triggers can be defined based on any data available in the data stream.

Cycle is implemented as a preprocessor for TMC. It has a fairly small command set. The output is code to calculate various data over various time regions. Unlike the previous version, the current version does not accept general TMC commands, so code to manipulate the calculated averages must be placed in another file.

1: Definitions

A Cycle program contains definitions for Triggers, Regions and Averages. A Rate must also be specified. The usable products are TMC variables which represent averages of specific input values over the specified regions.

1.1: Triggers

Regions are defined with respect to specific Triggers. The Trigger will define a reference point in time against which the limits of the Regions will be measured.

A Trigger is specified by name and with a "start condition", an optional "prestart condition":

        Trigger <NAME> {
          Start: <Expr>;
          [Prestart: <Expr>;]
          <Regions>
        }
The <Expr>s are any TMC logical expression. If no Prestart condition is specified, the logical negation of the Start condition is used. The Trigger becomes valid after the Prestart condition is met (evaluates to be true) when the Start condition is met. For example, in the definition:
        Trigger CycleA {
          Start: (DStt0 & 4) != 0;
          ...
        }
in order for Trigger CycleA to become valid, first the condition !((DStt0 & 4) != 0) must be met, then the condition (DStt0 & 4) != 0 must be met.

1.2: Regions

Within a Trigger definition, we can define Regions. A Region can be defined in two ways: by specifying one or more time intervals relative to the Trigger time or by specifying explicit expressions.
        <Regions> ::= <Region>*
        <Region> ::= Region <REGION_NAME> <RegionParams> ';'
        <RegionParams> ::= <Intervals> / <Exprs>

        <Intervals> ::= <Interval> // ','
        <Interval> ::= <Left> <Number> ',' <Number> <Right>
        <Left> ::= '(' / '['
        <Right> ::= ')' / ']'

        <Exprs> ::= [ '=' Expr [ ':' Expr [ ':' Expr ] ] ]
Intervals are specified using the standard mathematical notation for real-number intervals. For example, (3,5] represents time elapsed since the trigger of greater than 3 seconds and less than or equal to 5 seconds. All <Number>s listed in a Region definition must be non-negative and monotonically increasing. (SNAFU allows regions to be defined prior to the trigger, but realtime constraints make this extremely difficult here.) If multiple intervals are specified for a single region, they must be separated by commas and arranged in increasing order. For example:
        Region FG [0.25, 1.625], (3.5, 7.0 ];
Defines a Region named "FG" beginning 0.25 seconds after the Trigger and ending 1.625 seconds after the Trigger as well as times greater than 3.5 seconds and less than or equal to 7 seconds.

The explicit expressions give greater flexibility in the definition of regions, since they may allow regions which are not of a fixed width or fixed delay relative to the trigger. You may list 0, 1, 2 or 3 expressions to define a region. The expressions represent "Inside" points, "Before" points and "After" points. Data points occuring at times when the Inside expression is true will be entered into the average. The region will be considered complete, the average evaluated and the sums reset whenever the Before or After expressions are true.

It is legal (and reasonable) to have one time evaluate as being both "Before" and "Inside"; this is the case for a time interval starting at 0. At T==0, the Before condition is true, so any outstanding average is completed and evaluated, then since the Inside condition is also true, the current data point is entered in as the first value in the next average bin. In this way, it is possible to average data over the entire Trigger region without skipping any data points. (This can be specified as a Region with no intervals and no expressions, e.g.: Region All;)

For reasons that will become apparent shortly, Region names are best kept short.

Only one Region of a given name should be defined with respect to a single Trigger, but additional regions of the same name may be defined with respect to other Triggers.

1.3: Averages

Now that we have Triggers and Regions defined, we can specify what to average over that regions:
        <Average> ::= Average [Raw] <AvgVarList> Over <RegionList> ;
For each variable specified, an average is calculated for every occurance within the specified Regions. The result is stored in a new variable named by combining the variable's name with the Region's name. For example:
        Average DetA, DetB Over FG;
will average DetA and DetB over the Region FG and define outputs DetA_FG and DetB_FG which represent the respective averages over that region.

Averaging will be performed on converted data unless the 'Raw' keyword is specified.

1.4: Rate

One additional detail is required in a Cycle program; you must specify the rate at which the region limits will be tested. This is usually the rate of your highest-rate data. (I wish TMC had an automatic way to determine this, but it doesn't at this time -N). The rate may either be specified in Hz or as the name of a TM datum of the desired rate. If no rate is specified, the rate of the Minor Frame Counter (MFCtr) is used. This should usually be a good choice, but not always.
        <Rate> ::= Rate <Integer> Hz;
        <Rate> ::= Rate <Integer> / <Integer> Hz;
        <Rate> ::= Rate <Name>;
For example:
        Rate 8 Hz;
        Rate DetA;

1.4: Discard

It is sometimes convenient to throw out certain data values prior to averaging. This can be done using the syntax:
        <Discard> ::= Discard <VarList> ( if / unless )  <Expr>
For example:
        Discard DetA, DetB if (CtStat & 0x8000);
Another approach may be introduced soon.

2: Implementations

Once all your definitions are in place, you can begin writing expressions using the derived averages. This is accomplished by defining the averages in a .cyc file, then referencing them in other files.

One very useful feature is that multiple Regions can be defined with the same name relative to different Triggers. This would be used, for example, when an instrument has different cycle lengths which can be determined by a status value at the beginning of the cycle:

        Trigger Long {
          Start: (DStt0 & 1) && SolSW == 1;
          Region FG [ 0.25 7.75 ];
          Region BG ( 8.25 15.75 ];
        }

        Trigger Short {
          Start: (DStt0 & 1) && SolSW == 2;
          Region FG [ 0.25 3.75 ];
          Region BG ( 4.25 7.75 ];
        }

        Average DetA, DetB Over FG, BG;
These could then be referenced in a .tmc file:
        double DiffA, DiffB;
        Invalidate DiffA;
        Invalidate DiffB;
        
        { DiffA = DetA_FG - DetA_BG;
          validate DiffA; }
        { DiffB = DetB_FG - DetB_BG;
          validate DiffB; }
In this example, the difference of the foreground and background averages are calculated for both the short cycle and the long cycle.

3: Invocation

Within the ARP/DAS/appgen environment, Cycle program files have names ending in ".cyc". appgen handles the invocation of the Cycle preprocessor automatically. This is certainly the recommended method of invocation.

During alpha and beta testing of version 2, additional commands must be placed into the .spec file below the "%%":

        CYCLE=cycle > $@

Return to Manuals Guide


last updated: Fri May 7 15:14:06 2004 webmaster@huarp.harvard.edu
Copyright 2004 by the President and Fellows of Harvard College