User's Guide \textbf{Defining and Testing Operational State Conditions in the Data Monitor Tool} \textbf{Abstract} This document is a user's guide to defining and testing Operational State Conditions (OSCs) in the Data Monitor Tool (DMT) background environment. It is assumed the reader knows the rudiments of creating a background monitor in the DMT using the \texttt{DatEnv} class.
\textbf{Features}
- \texttt{include} directive to include standard pre-defined conditions, \textit{e.g.} one can \texttt{include} the configuration that is currently used by a running monitor, such as \texttt{LockLoss}, and thus use the same conditions the monitor is using.
- Ability to combine multiple conditions into one compound condition using Boolean logic.
- Ability to read parameter values from EPICS channels, giving real-time control of parameters.
- Access to values that are being monitored via the OSC object itself. (For instantaneous values, only one datapoint from all the data in the time stride is returned.)
- Optional parameters need not be specified in configuration file: default values are pre-defined.
- Inline comments
\textbf{Introduction} Before undertaking an analysis, one often needs to specify required interferometer or environment conditions. For example, before looking for instability in the Recycling Mirror (RM) servo, one would likely require both that servo and the Beam Splitter (BS) servo to be locked. One might also want Wave Front Sensing (WFS) to be engaged. In another analysis, one might require the laser intensity to exceed a threshold or require seismic motion to fall below a ceiling. To allow for flexible and comprehensive setting of conditions, one would also like to specify Boolean combinations of conditions. For example
Cond_1 = RM servo locked Cond_2 = BS servo locked Cond_3 = Cond_1 & Cond_2The OSC tool has been written to support convenient defining and run-time checking of such conditions. Definitions are made via a text configuration file. A handful of preliminary ``standard'' conditions (e.g., ``\texttt{Arm_locked}'' and ``\texttt{LVEA_quiet}'') have been provided in a sample configuration file. It is expected that many more such standard conditions will be defined and refined as physicists gain more experience with his and future datasets. Definitions for useful conditions should be sent to the author (\texttt{dwchin@umich.edu}) for incorporation into a public repository.
\textbfQuick Sample of Code Before detailing how to use the OSC tool, let's first get a flavor of it with a stripped-down sample of code. The following code defines conditions and checks them in real time:
// During initialization: osclist.readConfig("osc_sample.config"); // As each time interval of data (e.g., 1-second frame) is read: if ( osclist.satisfied("LVEA_quiet") ) { // Do some analysis.... }One can also loop through \textit{all} OSCs defined in a configuration file using an iterator:
// During initialization: osclist.readConfig("osc_sample.config"); // As each time interval of data is read: OperStateCondList::iterator iter = osclist.begin(); for (; iter != osclist.end(); ++iter) { // print out value being monitored. (does NOT work for meta-OSCs) cout << "'" << (*iter).first << "': watched value = " << (*iter).second->watchedQuantity() << endl; if ((*iter).second->satisfied() == true) cout << "'" << (*iter).first << "'\tsatisfied" << endl; else cout << "'" << (*iter).first << "'\t\tNOT satisfied" << endl; }This scrap of code assumes that the monitor class has been written with \texttt{DatEnv} as a base class, and \texttt{osclist} is a member \texttt{OperStateCondList} object.The \texttt{readConfig()} call is made in the monitor's constructor. The \texttt{satisfied()} call is made from the monitor's \texttt{ProcessData} method. The configuration file might look like:
# A comment x_quiet rmsrange "H0:PEM-LVEA_SEISX" lo=0. hi=2000. y_quiet rmsrange "H0:PEM-LVEA_SEISY" lo=0. hi=2000. z_quiet rmsrange "H0:PEM-LVEA_SEISZ" lo=0. hi=2000. LVEA_quiet boolean "x_quiet & y_quiet & z_quiet" # a comment # in general, lines look like the following, where # "OscName", osc_type, "paramname" are case-insensitive, # i.e. FooBar, fOObAR and foobar are all equivalent names OscName osc_type "channel_name" paramname=paramvalue ...The first three conditions have the names ``\texttt{x_quiet}'', ``\texttt{y_quiet}'' and ``\texttt{z_quiet}''. Each is of type \texttt{rmsrange} which means the data channel with the specified name must have an RMS value between the minimum and maximum values specified (0. and 2000. in each case). The fourth condition is Boolean, in this case the logical AND of the first three conditions.
Fields are separated by spaces or tabs. Valid condition names must begin with an alphabetic character and contain only alphanumeric characters, ``_'' (underscore), or ``:'' (colon). Condition names are case-insensitive, \textit{i.e.} \texttt{FooBar}, \texttt{fOObAR}, and \texttt{foobar} are all equivalent. For \texttt{boolean} conditions, spaces are not required in the Boolean expression. The bitmasks can be specified in decimal, octal, and hexadecimal format: octal numbers are denoted by a leading ``0'' (zero) and hexadecimal numbers are denoted by a leading ``0x'' (zero x).
\textbf{Other Directives} There are other directives that can be specified in the configuration file which are not directly involved in defining OSCs.
\texttt{\textbf{include}}
- \textbf{Effect:} Similar to ``\texttt{#include}'' for the C preprocessor, it includes other configuration files in line. If the file is not found, a warning message is printed and the directive is ignored: processing continues.
- \textbf{Syntax:} There are two ways of using the \texttt{include} directive:
- \texttt{include "otherFile.conf"} includes a configuration file in the same directory as the current file
- \texttt{include <otherFile.conf>} includes a configuration file from the directory given by the environment variable \texttt{DMTPARS}. If the environment variable is not set, a warning message is printed and the directive is ignored: processing continues.
\texttt{\textbf{ignore}}
- \textbf{Effect:} Deletes the named OSC from the \texttt{OperStateCondList}.
- \textbf{Syntax:} \texttt{ignore "previouslyDefinedOSCname"}
\texttt{\textbf{ignoreallexcept}}
- \textbf{Effect:} Ignores all OSCs that depend on data channels with names beginning with the given prefix.
- \textbf{Syntax:} \texttt{ignoreallexcept "H1:LSC"}
- \textbf{Note:} This can be dangerous, especially if you have dependencies on OSCs that you do not name. The only way to do that would be to write your own code in your monitor. Wouldn't it be nice to have regular expressions?
\texttt{\textbf{debuglevel}}
- \textbf{Effect:} Sets the debug level of the \texttt{OperStateCondList}.
- \textbf{Syntax:} \texttt{debuglevel 2} -- the argument must be an integer. Only values
make sense, though negative values do not cause an error.
\texttt{\textbf{stride}}
- \textbf{Effect:} Sets the time stride of the \texttt{Dacc} data accessor object associated with the \texttt{OperStateCondList}.
- \textbf{Syntax:} \texttt{stride 2} -- the argument must be an integer. Only values
make sense, though non-positive values do not cause an error.
- \textbf{Note:} To ensure that the stride that is set from the configuration file is in effect, the \texttt{Dacc::setStride()} method must \textit{not} be used.
\textbf{Conditions} The following list of OSC types are expected to expand with future releases of the OSC tool.
There are two types of OSCs: atomic OSCs, and meta-OSCs. The atomic OSCs specify conditions on the data stream, whereas the meta-OSCs specify conditions on other OSCs. Each OSC has some number of parameters which specify the details of the condition, \textit{e.g.} threshold, frequency band, etc.
The atomic OSCs require a channel name in the configuration file definition, while the meta-OSCs require another OSC name in the definition. The OSC upon which a meta-OSC acts must have been defined before the meta-OSC.
Some classes of OSCs have parameters which others do not, \textit{e.g.} OSCs which place conditions on each sample in the time-series data have a \texttt{fraction} parameter which specifies the minimum fraction of data that must satisfy the condition for the OSC to be satisfied. The \texttt{fraction} parameter would make sense for something like \texttt{valueabove} but not for something like \texttt{meanabove}.
Some parameters are \textit{optional}, meaning that they need not be specified explicitly in the configuration file. If a parameter is optional it always has some default value.
If a line defining an OSC in the configuration file contains parameters that are not part of that OSC or meta-OSC, an undefined error may result.
\textbf{Condition Names} All conditions must be named. Legal names must begin with an alphabetic character and may consist of letters, numbers, underscores and colons. Names are \textit{case-insensitive}.
\textbf{Common Parameters} This is a list of names of parameters which are used for more than on OSC type. Note that
is to be interpreted as the limit of the computer representation of the appropriate data type. A \textit{stride} corresponds to one Frame of data. (FIXME)
\texttt{\textbf{fraction}}
- \textbf{Definition:} Specifies the fraction of the time-series data that must satisfy the condition for the OSC to be satisfied
- \textbf{OSCs:} \texttt{valueabove}, \texttt{valuebelow}, \texttt{ valuerange}, \texttt{bitand}, \texttt{bitnand}, \texttt{bitor}, \texttt{ bitnor}
- \textbf{Optional:} Yes
- \textbf{Data type:} Floating point
- \textbf{Legal values:}
Zero means that the OSC is satisfied if at least one data point satisfies the condition
- \textbf{Default value:}
![]()
\texttt{\textbf{hold}}
- \textbf{Definition:} Specifies the number of additional strides for which to hold the \texttt{OSC.satisfied()} at True.
- \textbf{OSCs:} \texttt{transitup}, \texttt{transitdown}
- \textbf{Optional:} Yes
- \textbf{Data type:} Integer
- \textbf{Legal values:}
The OSC will always be true for at least one (1) stride, and will be held True for an additional \texttt{hold} stride.
- \textbf{Default value:}
![]()
\texttt{\textbf{dead}}
- \textbf{Definition:} Specifies the number of strides beyond the end of a \texttt{hold} period for which the OSC cannot be True
- \textbf{OSCs:} \texttt{transitup}, \texttt{transitdown}
- \textbf{Optional:} Yes
- \textbf{Data type:} Integer
- \textbf{Legal values:}
The OSC will be held False for \texttt{dead} strides
- \textbf{Default value:}
![]()
\texttt{\textbf{threshold}}
- \textbf{Definition:} Specifies an amplitude threshold for \texttt{*above}, and \texttt{*below}, and a change threshold for \texttt{*rise}, and \texttt{*fall} OSCs
- \textbf{OSCs:} \texttt{valueabove}, \texttt{valuebelow}, \texttt{meanabove}, \texttt{meanbelow}, \texttt{rmsabove}, \texttt{rmsbelow}, \texttt{abspowerabove}, \texttt{abspowerbelow}, \texttt{abspowerrise}, \texttt{abspowerfall}, \texttt{abspowergain}, \texttt{fractpowerabove}, \texttt{fractpowerbelow}
- \textbf{Optional:} No
- \textbf{Data type:} Floating point
- \textbf{Legal values:}
![]()
- \textbf{Default value:} N/A
\texttt{\textbf{nstrides}}
- \textbf{Definition:} Specifies the number of strides over which an average is to be computed
- \textbf{OSCs:} \texttt{abspowerrise}, \texttt{abspowerfall}, \texttt{abspowergain}, \texttt{meanrise}, \texttt{meanfall}
- \textbf{Optional:} Yes
- \textbf{Data type:} Integer
- \textbf{Legal values:}
![]()
- \textbf{Default value:} 1
\texttt{\textbf{lo}}
- \textbf{Definition:} Specifies the lower limit for \texttt{*range} OSCs. OSC will be satisfied if \texttt{fraction} of data lies between lower and upper limits (see \texttt{hi})
- \textbf{OSCs:} \texttt{valuerange}, \texttt{meanrange}, \texttt{rmsrange}, \texttt{fractpowerrange}
- \textbf{Optional:} No
- \textbf{Data type:} Floating point
- \textbf{Legal values:}
![]()
- \textbf{Default value:} N/A
\texttt{\textbf{hi}}
- \textbf{Definition:} Specifies the upper limit for \texttt{*range} OSCs. OSC will be satisfied if \texttt{fraction} of data lies between lower and upper limits (see \texttt{lo})
- \textbf{OSCs:} \texttt{valuerange}, \texttt{meanrange}, \texttt{rmsrange}, \texttt{fractpowerrange}
- \textbf{Optional:} No
- \textbf{Data type:} Floating point
- \textbf{Legal values:}
![]()
- \textbf{Default value:} N/A
\texttt{\textbf{freqlo}}
- \textbf{Definition:} Specifies the lower frequency limit for OSCs which depend on the power spectrum.
- \textbf{OSCs:} \texttt{abspowerabove}, \texttt{abspowerbelow}, \texttt{abspowerrange}, \texttt{abspowerrise}, \texttt{abspowerfall}, \texttt{abspowergain}, \texttt{fractpowerabove}, \texttt{fractpowerbelow}, \texttt{fractpowerrange}
- \textbf{Optional:} No
- \textbf{Data type:} Floating point
- \textbf{Legal values:}
![]()
- \textbf{Default value:} N/A
\texttt{\textbf{freqhi}}
- \textbf{Definition:} Specifies the upper frequency limit for OSCs which depend on the power spectrum.
- \textbf{OSCs:} \texttt{abspowerabove}, \texttt{abspowerbelow}, \texttt{abspowerrange}, \texttt{abspowerrise}, \texttt{abspowerfall}, \texttt{abspowergain}, \texttt{fractpowerabove}, \texttt{fractpowerbelow}, \texttt{fractpowerrange}
- \textbf{Optional:} No
- \textbf{Data type:} Floating point
- \textbf{Legal values:}
![]()
- \textbf{Default value:} N/A
\texttt{\textbf{mask}}
- \textbf{Definition:} The bit mask with which to operate on the data.
- \textbf{OSCs:} \texttt{bitand}, \texttt{bitnand}, \texttt{bitor}, \texttt{ bitnor}
- \textbf{Optional:} No
- \textbf{Data type:} Integer. (May be specified in octal or hexadecimal format: octal has a leading ``0'' (zero) and hexadecimal has a leading ``0x'' (zero x).)
\textbf{Atomic OSCs} These OSCs act on the time-series data in channels, and hence require a channel name in their definition, \textit{e.g.}:
X_arm_locked meanabove "H2:LSC-AS_I" threshold=17.3\textit{NOTE:} The power in the \texttt{power*} OSCs is really band-limited RMS.
\texttt{\textbf{valueabove}}
- \textbf{True when:} \texttt{fraction} of data samples are greater than \texttt{threshold}
- \textbf{Parameters:} \texttt{fraction}, \texttt{threshold}
\texttt{\textbf{valuebelow}}
- \textbf{True when:} \texttt{fraction} of data samples are less than \texttt{threshold}
- \textbf{Parameters:} \texttt{fraction}, \texttt{threshold}
\texttt{\textbf{valuerange}}
- \textbf{True when:} \texttt{fraction} of data samples in the interval
and < \texttt{hi}
- \textbf{Parameters:} \texttt{fraction}, \texttt{lo}, \texttt{hi}
\texttt{\textbf{meanabove}}
- \textbf{True when:} mean of data is greater than \texttt{threshold}
- \textbf{Parameters:} \texttt{threshold}
\texttt{\textbf{meanbelow}}
- \textbf{True when:} mean of data is less than \texttt{threshold}
- \textbf{Parameters:} \texttt{threshold}
\texttt{\textbf{meanrange}}
- \textbf{True when:} mean of data is in the interval
![]()
- \textbf{Parameters:} \texttt{lo}, \texttt{hi}
\texttt{\textbf{meanrise}}
- \textbf{True when:} mean of data has increased by an amount > \texttt{threshold} over \texttt{nstrides} strides
- \textbf{Parameters:} \texttt{threshold}, \texttt{nstrides}
\texttt{\textbf{meanfall}}
- \textbf{True when:} mean of data has decreased by an amount > \texttt{threshold} over \texttt{nstrides} strides
- \textbf{Parameters:} \texttt{threshold}, \texttt{nstrides}
\texttt{\textbf{rmsabove}}
- \textbf{True when:} RMS (full bandwidth) of data is greater than \texttt{threshold}
- \textbf{Parameters:} \texttt{threshold}
\texttt{\textbf{rmsbelow}}
- \textbf{True when:} RMS (full bandwidth) of data is less than \texttt{threshold}
- \textbf{Parameters:} \texttt{threshold}
\texttt{\textbf{rmsrange}}
- \textbf{True when:} RMS (full bandwidth) of data is in the interval
![]()
- \textbf{Parameters:} \texttt{lo}, \texttt{hi}
\texttt{\textbf{bitand}}
- \textbf{True when:} bitwise AND of \texttt{fraction} of data with \texttt{mask} is equal to \texttt{mask}
- \textbf{Parameters:} \texttt{mask}, \texttt{fraction}
- \textbf{Note:} \texttt{mask} may be specied in octal (leading \texttt{0}) or hexadecimal (leading \texttt{0x}), \textit{e.g.} 0123 is decimal 83, 0xff is decimal 255
\texttt{\textbf{bitnand}}
- \textbf{True when:} bitwise AND of \texttt{fraction} of data with \texttt{ mask} not equal to \texttt{mask}
- \textbf{Parameters:} \texttt{mask}, \texttt{fraction}
- \textbf{Note:} \texttt{mask} may be specied in octal (leading \texttt{0}) or hexadecimal (leading \texttt{0x}), \textit{e.g.} 0123 is decimal 83, 0xff is decimal 255
\texttt{\textbf{bitor}}
- \textbf{True when:} bitwise AND of \texttt{fraction} of data with \texttt{ mask} is not equal to 0
- \textbf{Parameters:} \texttt{mask}, \texttt{fraction}
- \textbf{Note:} \texttt{mask} may be specied in octal (leading \texttt{0}) or hexadecimal (leading \texttt{0x}), \textit{e.g.} 0123 is decimal 83, 0xff is decimal 255
\texttt{\textbf{bitnor}}
- \textbf{True when:} bitwise AND of \texttt{fraction} of data with \texttt{ mask} is equal to 0
- \textbf{Parameters:} \texttt{mask}, \texttt{fraction}
- \textbf{Note:} \texttt{mask} may be specied in octal (leading \texttt{0}) or hexadecimal (leading \texttt{0x}), \textit{e.g.} 0123 is decimal 83, 0xff is decimal 255
\texttt{\textbf{abspowerabove}}
- \textbf{True when:} power in frequency range \texttt{freqlo} and \texttt{freqhi} is above \texttt{threshold}
- \textbf{Parameters:} \texttt{freqlo}, \texttt{freqhi}, \texttt{threshold}
- \textbf{Note:} \textit{Power} in this and all the \texttt{power} OSCs is defined to be the mean square value of the PSD (computed by calling \texttt{FSpectrum::getSum()} for the frequency range specified) multiplied by the frequency range. This power is the square of the RMS that is plotted in the DTT Fourier Tools. This number is independent of stride (length of time series used to compute PSD).
\texttt{\textbf{abspowerbelow}}
- \textbf{True when:} power in frequency range \texttt{freqlo} and \texttt{freqhi} is below \texttt{threshold}
- \textbf{Parameters:} \texttt{freqlo}, \texttt{freqhi}, \texttt{threshold}
- \textbf{Note:} \textit{Power} in this and all the \texttt{power} OSCs is defined to be the mean square value of the PSD (computed by calling \texttt{FSpectrum::getSum()} for the frequency range specified) multiplied by the frequency range. This number is independent of stride (length of time series used to compute PSD).
\texttt{\textbf{abspowerrange}}
- \textbf{True when:} power in frequency range \texttt{freqlo} and \texttt{freqhi} is between \texttt{lo} and \texttt{hi}
- \textbf{Parameters:} \texttt{freqlo}, \texttt{freqhi}, \texttt{lo}, \texttt{hi}
- \textbf{Note:} \textit{Power} in this and all the \texttt{power} OSCs is defined to be the mean square value of the PSD (computed by calling \texttt{FSpectrum::getSum()} for the frequency range specified) multiplied by the frequency range. This power is the square of the RMS that is plotted in the DTT Fourier Tools. This number is independent of stride (length of time series used to compute PSD).
\texttt{\textbf{abspowerrise}}
- \textbf{True when:} power in frequency range
has risen by an amount
\texttt{threshold} over \texttt{nstrides} strides
- \textbf{Parameters:} \texttt{freqlo}, \texttt{freqhi}, \texttt{threshold}, \texttt{nstrides}
- \textbf{Note:} \textit{Power} in this and all the \texttt{power} OSCs is defined to be the mean square value of the PSD (computed by calling \texttt{FSpectrum::getSum()} for the frequency range specified) multiplied by the frequency range. This power is the square of the RMS that is plotted in the DTT Fourier Tools. This number is independent of stride (length of time series used to compute PSD).
\texttt{\textbf{abspowerfall}}
- \textbf{True when:} power in frequency range
has fallen by an amount
\texttt{threshold} over \texttt{nstrides} strides
- \textbf{Parameters:} \texttt{freqlo}, \texttt{freqhi}, \texttt{threshold}, \texttt{nstrides}
- \textbf{Note:} \textit{Power} in this and all the \texttt{power} OSCs is defined to be the mean square value of the PSD (computed by calling \texttt{FSpectrum::getSum()} for the frequency range specified) multiplied by the frequency range. This power is the square of the RMS that is plotted in the DTT Fourier Tools. This number is independent of stride (length of time series used to compute PSD).
\texttt{\textbf{abspowergain}}
- \textbf{True when:} Depends on value of \texttt{threshold}. If \texttt{threshold} > 1, True when power in frequency range
is changing by a factor
\texttt{threshold} over \texttt{nstrides} strides. If \texttt{threshold} < 1, True when power in frequency range is changing by a factor
\texttt{threshold} over \texttt{nstrides} strides.
- \textbf{Parameters:} \texttt{freqlo}, \texttt{freqhi}, \texttt{threshold}, \texttt{nstrides}
- \textbf{Note:} \textit{Power} in this and all the \texttt{power} OSCs is defined to be the mean square value of the PSD (computed by calling \texttt{FSpectrum::getSum()} for the frequency range specified) multiplied by the frequency range. This power is the square of the RMS that is plotted in the DTT Fourier Tools. This number is independent of stride (length of time series used to compute PSD).
\texttt{\textbf{fractpowerabove}}
- \textbf{True when:} fractional power in frequency range
is above \texttt{threshold}
- \textbf{Parameters:} \texttt{freqlo}, \texttt{freqhi}, \texttt{threshold}
- \textbf{Note:} \textit{Fractional power} is defined to be the ratio of power in the frequency range requested to the full-band power. \textit{Power} in this and all the \texttt{power} OSCs is defined to be the mean square value of the PSD (computed by calling \texttt{FSpectrum::getSum()} for the frequency range specified) multiplied by the frequency range. This power is the square of the RMS that is plotted in the DTT Fourier Tools. This number is independent of stride (length of time series used to compute PSD).
\texttt{\textbf{fractpowerbelow}}
- \textbf{True when:} fractional power in frequency range
is below \texttt{threshold}
- \textbf{Parameters:} \texttt{freqlo}, \texttt{freqhi}, \texttt{threshold}
- \textbf{Note:} \textit{Fractional power} is defined to be the ratio of power in the frequency range requested to the full-band power. \textit{Power} in this and all the \texttt{power} OSCs is defined to be the mean square value of the PSD (computed by calling \texttt{FSpectrum::getSum()} for the frequency range specified) multiplied by the frequency range. This power is the square of the RMS that is plotted in the DTT Fourier Tools. This number is independent of stride (length of time series used to compute PSD).
\texttt{\textbf{fractpowerrange}}
- \textbf{True when:} fractional power in frequency range
is between \texttt{lo} and \texttt{hi}
- \textbf{Parameters:} \texttt{freqlo}, \texttt{freqhi}, \texttt{lo}, \texttt{hi}
- \textbf{Note:} \textit{Fractional power} is defined to be the ratio of power in the frequency range requested to the full-band power. \textit{Power} in this and all the \texttt{power} OSCs is defined to be the mean square value of the PSD (computed by calling \texttt{FSpectrum::getSum()} for the frequency range specified) multiplied by the frequency range. This power is the square of the RMS that is plotted in the DTT Fourier Tools. This number is independent of stride (length of time series used to compute PSD).
\texttt{\textbf{fractpowerrise}}
- \textbf{True when:} fractional power in frequency range
has risen by an amount
\texttt{threshold} over \texttt{nstrides} strides
- \textbf{Parameters:} \texttt{freqlo}, \texttt{freqhi}, \texttt{threshold}, \texttt{nstrides}
- \textbf{Note:} \textit{Fractional power} is defined to be the ratio of power in the frequency range requested to the full-band power. \textit{Power} in this and all the \texttt{power} OSCs is defined to be the mean square value of the PSD (computed by calling \texttt{FSpectrum::getSum()} for the frequency range specified) multiplied by the frequency range. This power is the square of the RMS that is plotted in the DTT Fourier Tools. This number is independent of stride (length of time series used to compute PSD).
\texttt{\textbf{fractpowerfall}}
- \textbf{True when:} fractional power in frequency range
has fallen by an amount
\texttt{threshold} over \texttt{nstrides} strides
- \textbf{Parameters:} \texttt{freqlo}, \texttt{freqhi}, \texttt{threshold}, \texttt{nstrides}
- \textbf{Note:} \textit{Fractional power} is defined to be the ratio of power in the frequency range requested to the full-band power. \textit{Power} in this and all the \texttt{power} OSCs is defined to be the mean square value of the PSD (computed by calling \texttt{FSpectrum::getSum()} for the frequency range specified) multiplied by the frequency range. This power is the square of the RMS that is plotted in the DTT Fourier Tools. This number is independent of stride (length of time series used to compute PSD).
\textbf{Meta-OSCs} \texttt{\textbf{boolean}}
- \textbf{True when:} Boolean expression of OSCs evaluates to True
- \textbf{Parameters:} none
- \textbf{Example:}\texttt{Both_arms_locked boolean "X_arm_locked \& Y_arm_locked"}
- \textbf{Notes:} Boolean expressions use previously defined OSC names as Boolean variables. Operators supported are: \texttt{!} (NOT), \texttt{\&} (AND), \texttt{|} (OR). Precedence rules follow those of standard logic. Parentheses may be used to make precedence explicit. (Ignore backslashes above in the HTML version of this manual.)
\texttt{\textbf{transitup}}
- \textbf{True when:} given OSC changes from False to True
- \textbf{Parameters:} \texttt{hold}, \texttt{dead}
- \textbf{Example:} \texttt{X_arm_lock_acquired transitup "X_arm_locked" hold=0}
- \textbf{Notes:} This meta-OSC is held True for \texttt{hold} + 1 strides
\texttt{\textbf{transitdown}}
- \textbf{True when:} given OSC changes from True to False
- \textbf{Parameters:} \texttt{hold}, \texttt{dead}
- \textbf{Example:} \texttt{X_arm_lock_lost transitdown "X_arm_locked" hold=0}
- \textbf{Notes:} This meta-OSC is held True for \texttt{hold} + 1 strides
The bitwise conditions merit further explanation. The \texttt{bitand} and \texttt{bitnand} conditions refer to whether \textit{every} bit in the bitmask has corresponds to a bit in the data channel value. The \texttt{ bitor} and \texttt{bitnor} conditions refer to whether \textit{at least one} of the bits in the bitmask has a corresponding bit in the data channel value. Hence for bit masks with only one bit turned on, the \texttt{and} and \texttt{or} conditions are identical.
\texttt{transitup} and \texttt{transitdown} are conditions on other OSCs. \texttt{transitup} becomes True and is held True for
strides whenever the named OSC changes state from False to True, where
is the hold duration parameter. \texttt{transitdown} works in a similar way, except that it becomes True when the named OSC goes from True to False. The \texttt{dead} parameter prevents \texttt{transitup} and \texttt{ transitdown} conditions from becoming True again for an interval of \texttt{dead} strides after the end of the \texttt{hold} period.
One cannot yet define OSCs in code, only via a configuration file.
\textbf{Other Features} The \texttt{OperStateCond} objects have some features worth noting:
- All the \textit{directive}s that are legal in a configuration file have a corresponding method.
- All atomic OSCs have a \texttt{watchedQuantity()} method which returns the most recent \texttt{double} value of the quantity being monitored, \textit{e.g} the mean value for a \textt{mean*} condition, the power for a \texttt{power*} condition.
\textbf{FIXME: Old Stuff} The following spectral power conditions (meant for detecting transients, including servo instabilities) require specifying a minimum and maximum frequency for the range of computed power. The power is normalized so that its sum from zero to the Nyquist frequency equals the mean square value of the corresponding time series. Conditions on fractional power refer to the fraction of total power in the specified frequency range. Only parameters additional to the min/max frequencies are listed in the following table.
The ``mag'' and ``demag'' conditions refer to fractional changes in power over a given frequency range, independent of the absolute power level and of power in other frequency ranges. Normally, the scale factor used for ``mag'' should be greater than one and that used for ``demag'' less than one. The ``any'' and ``ave'' modifiers have similar meanings as for power rises and falls, except that for ``any'' the instantaneous rate threshold is taken as (scale factor)**(1 / number of time intervals). The number of time intervals N must be a positive integer. For ``ave'' conditions, at least N+1 time consecutive intervals must be examined before the condition can be satisfied.
Provision for these various ways of defining power changes has been made for flexibility. Very stable channels with nearly constant total power may be well suited to conditions based on absolute power. Channels with time-dependent total power but stable spectral shape may be well suited to conditions on fractional power. Channels with variations in total power and spectral shape may be best suited to conditions on power magnification scale factors.
\textbf{Checking conditions} If an OSC has been defined during initialization, then one can check whether it is satisfied during a given time interval with a call to the \texttt{satisfied()} method. \textit{e.g.}:
if (osclist.satisfied("oscname")) // send a triggerThe \texttt{OperStateCondList} class inherits from a \texttt{hash_map<const string, osc::OperStateCond*, osc::hash<const string> >}, so all the methods that a \texttt{hash_map} has are available. (See SGI's documentation for the Standard Template Library at \texttt{http://www.sgi.com/tech/stl/}.) So, for instance, one can loop through all defined conditions:
// As each time interval of data is read: OperStateCondList::iterator iter = osclist.begin(); for (; iter != osclist.end(); ++iter) { if ((*iter).second->satisfied() == true) cout << "'" << (*iter).first << "'\tsatisfied" << endl; else cout << "'" << (*iter).first << "'\t\tNOT satisfied" << endl; }\textbf{Other Facilities} In addition to the \texttt{OperStateCondList} class, a helper class called \texttt{TSWindow} is also available. \texttt{TSWindow} represents a time series with at most
elements. It is typically used as a ``window'' on a time series that is to be presented to the DMT Viewer. For a relatively simple example, see the source code for the \texttt{LockLoss} monitor: \texttt{~dmt/cvs/dmt/src/monitors/LockLoss}. To add a datapoint to a \texttt{TSWindow} object, use the \texttt{append()} method.
\newpage
\textbf{Hacker's Guide} \textbf{Big picture from the end-user standpoint} We want to have various Operational State Conditions, encapsulated by the class \texttt{OperStateCond} (and abbreviated OSC for the rest of this document), which specify conditions which may or may not be satisfied by the data stream in \textit{one (1)} channel.
Then, for the user, there is a \texttt{hash_map} of standard OSCs, \textit{e.g.} \texttt{valueabove} and \texttt{meanbelow}, indexed by the user-specified names defined in a configuration file. This is so that the user can refer to specific OSCs.
Each OSC has none or some parameters associated with it, \textit{e.g.} \texttt{valueabove} has two parameters, one of which is its \texttt{threshold}: if the data in the channel ever goes above that threshold value, the OSC is said to be ``satisfied'' (the \texttt{satisfied()} member function).
Each parameter has a name, \textit{e.g.} \texttt{threshold}, and a datatype, \textit{e.g.} \texttt{double}.
This code will read a configuration file specifying the various OSCs and the corresponding parameter values. Each OSC must be given a unique name, a string of alphanumeric characters beginning with an alphabetic character.
The reason for naming each OSC is so that each OSC maybe referred to later in a configuration file and used in meta-OSCs. Since each OSC.\texttt{satisfied()} returns a \texttt{boolean}, one may now define a Boolean OSC to say something like ``True if CHAN1 has valueabove 2.3 AND CHAN2 has meanbelow 4.2''.
Rather than having to manually type in the names of each OSC into the monitor code, we define the \texttt{OperStateCondList} class, which, despite its name, is not a linked-list but a \texttt{hash_map}, \textit{ i.e.} a dictionary that associates a pointer to an \texttt{OperStateCond} object with a string (the user-defined name of the OSC, specified in the configuration file). Making \texttt{OperStateCondList} a \texttt{ hash_map} means that we may iterate over all defined OSCs:
OperStateCondList mOSClist; OperStateCondList::iterator iter = mOSClist.begin(); for (; iter != mOSClist.end(); ++iter) if ((*iter).second->satisfied()) // generate and send a trigger to the MetaDBNotice that this still does not obviate the need for \texttt{ OperStateCondList::satisfied(const char *oscname)} since the user might want to test for a particular OSC, and the method was defined in a previous incarnation of this code. Another way of accessing particular OSCs is to use the fact that it's a \texttt{hash_map} (which is actually what \texttt{OperStateCondList::satisfied()} does):
OperStateCondList mOSClist; mOSClist.readConfig("configfile.conf"); if (mOSClist["my_condition"]->satisfied()) cout << "my_condition is satisfied" << endl; else cout << "my_condition is NOT satisfied" << endl;
\textbf{Big picture from the programmer's standpoint} This is more info for one who wishes to modify the OperStateCondList code. If you read the above, you will see a very striking resemblance between OSCs and the basic datatypes of a programming language. In a programming language, we may define variables of different datatypes; in the OperStateCondList system, we may define OSCs of different OSC types (like \texttt{valueabove}).
And then, the Boolean OSCs are just a Boolean expression of previously defined OSCs. So, this really becomes a small language, and hence the scanning, tokenizing and parsing objects associated with the Boolean OSC. (See \texttt{osc/boolean/*.hh}.)
\texttt{boolean}, \texttt{transitup}, and \texttt{transitdown} OSCs are really meta-OSCs, \textit{i.e.} they define conditions on other OSCs. So, to know whether the OSCs they refer to are satisfied, they need to get a pointer to the \texttt{OperStateCondList} that contains them.
To make the evaluation of the Boolean expression a little more efficient, we convert the infix form of the Boolean expression, \textit{ e.g.} \texttt{Locklost \& PSLglitch}, to Reverse Polish Notation (RPN), and in the process verify the correctness of the expression. RPN is quicker to evaluate since it simplifies putting the running value in a stack.
To make evaluations for the other conditions a little more efficient, we store a short history of two \texttt{satisfied()} values: the value for the current stride, and the value for the previous stride. Some OSCs depend on more than just the previous stride, so they have their own private data members defined for storing this data.
Now, for a larger overview. And let's do this in a top-down way, with a very large grain.
We've already seen that \texttt{OperStateCondList} is a \texttt{ hash_map<const string, OperStateCond*>}.
Any new types of OSCs that are to be written will have to inherit from \texttt{OperStateCond}: it is a base class that provides data and functions that all OSCs need.
\texttt{OperStateCondList} also contains (`has a' relationship) information about the various basic OSC types. This information is stored in \texttt{osc::TypeInfoMap mTypeInfoMap}. (See \texttt{ OSCListMisc.hh}.)
\texttt{osc::typeInfoMap} is a \texttt{hash_map<const string, TypeInfo>}, \textit{i.e.} it's a dictionary that relates a \texttt{TypeInfo} object to a \texttt{const string} (which is the name of that type, \textit{e.g.} \texttt{ valueabove}).
The \texttt{TypeInfo} class contains information about the OSC type. It does this by containing a sorted map of parameter types: \texttt{typedef map<const string, tseriesType_t> ParamTypeMap}. \texttt{tseriesType_t} is defined in \texttt{namespace osc} and is an enumeration of the various ``atomic'' data types that may be contained in a \texttt{TSeries}. The indexing key for \texttt{ParamTypeMap} is the name of the parameter, \textit{e.g.} \texttt{mParamTypeMap["threshold"]} would be a \texttt{DOUBLE}.
In summary, let ``*'' mean ``has a'', and ``>'' mean ``is a''.
OperStateCondList > hash_map of OperStateCond*, indexed by user-defined names of OSCs * TypeInfoMap, containing information about the basic types OperStateCond > a base class from which actual OSCs will inherit * a bunch of stuff. See OperStateCond.hh and misc.hh TypeInfoMap > hash_map of TypeInfo, indexed by names of types * ParamInfoMap, containing information about the parameters associated with this type of OSC ParamInfoMap > hash_map of ParamInfo, indexed by names of parametersThe \texttt{ParamInfoMap} and \texttt{TypeInfoMap} are initialized in \texttt{OperStateCondList}'s constructor. Since this data should be common to all instances of \texttt{OperStateCondList}, one would like this to be a static data member, but unfortunately it is almost impossible to initialize a complex data structure such as this at compile time.
Now, how do the OSCs store the values of their parameters? Since these parameters may be of different types, and they may be read from an Epics channel, we can't just store them as simple values. We use a template class (just because I don't know how to do something like the \texttt{Param} class in DMT: see \texttt{osc/Param.hh}). For now, we only have \texttt{int} and \texttt{double} parameters, so each \texttt{OperStateCond} object has two \texttt{hash_map}s: one for integer parameters (\texttt{mIntParams}) and one for doubles (\texttt{mDblParams}). These two \texttt{hash_map}s are indexed by the names of the parameters. The value of a parameter may be retrieved by, \textit{e.g.}:
mDblParams["threshold"].value()\textbf{How to Add New OSC Types} Look in the \texttt{osc} subdirectory. You'll create a new class that inherits from \texttt{OperStateCond}. Look at the others for examples. You'll have to initialize the object's \texttt{ParamInfoMap} in the \texttt{OperStateCondList} constructor, and then enter that into \texttt{OperStateCondList}'s \texttt{TypeInfoMap}. You will need to add a section that actually adds a new OSC to the \texttt{hash_map} (around line no. 612 and onwards). You may need to write sections to parse the config file line for your new OSC, though it's quite unlikely unless you have a new type of parameter (\textit{e.g} a complex number) that behaves very differently from the types that already exist. \texttt{OperStateCondList::parseAtomicParams()} is the method that parses config file lines for OSCs. The \texttt{transit*} conditions have config line parsing written inline in the constructor of \texttt{OperStateCondList}. Only the \texttt{boolean} OSC type has its own parser since it's a bit of a trick to parse a Boolean expression.
alphabetic index hierarchy of classes
Please send questions and comments to zweizig_j@ligo.caltech.edu
generated by doc++