Notes on alarms formulas

Alarm conditions are provided as python like expressions, which are then calculated by the TangoEval. The TangoEval is an extended python eval.

Detail information and examples of formulas can be found int the PANIC documentation, here:

Tango names resolving

The main enhancement to the standard python eval is the direct resolving of tango objects.

If one uses a string like the following (without quotes):

some/device/name{/attribute_name}{.value/all/time/quality/delta/exception}

(items in curly brackets are optional), the TangoEval resolve the string to:

  • Tango some/device/name State, if the only device name is used,

  • An attribute value indicated by some/device/name/attribute_name, if the string provides the attribute_name,

  • An attribute property (value/all/time/quality/delta/exception), if it is provided in the string,

Please refer to this documentation

Special Keys/Macros

When providing formulas, the following special kays

  • DEVICE: Returns PyAlarm device name

  • DOMAIN, FAMILY, MEMBER: Parts of the device name

  • ALARMS: Alarms managed by this device

  • PANIC: API containing all declared alarms

  • t: time since the device was started

  • T(…): string to time

  • str2time(…): string to time

  • now, NOW(): current timestamp

  • DEVICES: instantiated devices

  • DEV(device): DeviceProxy(device)

  • NAMES(expression): Finds all attributes matching the expression and return its names.

  • CACHE: Saved values

  • PREV: Previous values

  • READ(attr): TangoEval.read_attribute(attr)

  • FIND(expression): Finds all attributes matching the expression and return its values.

  • GROUP(…)

For details, pleas look to the links to Examples provided in the PANIC documentation

Current timestamp - NOW()

Time: returns the epoch in seconds of the last value read

epoch is a date and time from which a computer measures system time

sys/tg_test/1/State.time < (now-60)
NOW()

Fig. 8 NOW()

CACHE

This will trigger alarm if ALL values in the cache are equal, it is NOT the same as Delta because it checks only the first and last values:

not (lambda l:max(l)-min(l))([v.value for v in CACHE['elin/focus/b1coil/Position']])
CACHE

Fig. 9 CACHE

String to time - T(…)

A temporal condition can be achieved using the T() macro in the formula. To re-enable it after a maintenance period:

T() < T('2020-01-09') AND (elin/v-rv/1/State != CLOSE)
T(…)

Fig. 10 T(…)

FIND

((elin/focus/b1coil/Position > 55) OR (elin/focus/b2coil/Position > 55) OR elin/focus/b3coil/Position > 55) OR (elin/focus/b4coil/Position > 55))

is equal to:

any([s.value > 55 for s in FIND(elin/focus/b*coil/Position)])
FIND()

Fig. 11 FIND()

Grouping Alarms in Formulas

The proper way of grouping the alarms

ALARM_1: just/my/tango/attribute_1
ALARM_1: just/my/tango/attribute_2

then:

ALARM_1_OR_2: ALARM_1 or ALARM_2

Example:

(((elin/v-rv/0/State != CLOSE) OR (elin/v-rv/1/State != CLOSE) OR (elin/v-rv/2/State != CLOSE) OR (elin/v-rv/3/State != CLOSE) OR (elin/v-rv/4/State != CLOSE) ) AND ((elin/focus/b1coil/Position > 55) OR (elin/focus/b2coil/Position > 55) OR (elin/focus/b3coil/Position > 55) OR (elin/focus/b4coil/Position > 55)))

is equal to:

VALVE_LINAC_TEST_ALARM:((elin/v-rv/0/State != CLOSE) OR (elin/v-rv/1/State != CLOSE) OR (elin/v-rv/2/State != CLOSE) OR (elin/v-rv/3/State != CLOSE) OR (elin/v-rv/4/State != CLOSE) )
Coil_Position_Linac_Alarm:((elin/focus/b1coil/Position > 55) OR (elin/focus/b2coil/Position > 55) OR (elin/focus/b3coil/Position > 55) OR (elin/focus/b4coil/Position > 55))
(VALVE_LINAC_TEST_ALARM AND Coil_Position_Linac_Alarm)
Grouping

Fig. 12 Grouping