Files
ADAndor/documentation/pluginDoc.html
2012-10-01 19:30:04 +00:00

766 lines
24 KiB
HTML
Executable File

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>areaDetector Plugins</title>
<meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type" />
</head>
<body>
<div style="text-align: center">
<h1>
areaDetector Plugins</h1>
<h2>
October 1, 2012</h2>
<h2>
Mark Rivers</h2>
<h2>
University of Chicago</h2>
</div>
<h2>
Contents</h2>
<ul>
<li><a href="#Overview">Overview</a></li>
<li><a href="#NDPluginDriver">NDPluginDriver</a></li>
<li><a href="#Guidelines">Guidelines and rules for plugins</a></li>
<li><a href="#commomPlugins">commonPlugins.cmd</a></li>
<li><a href="NDPluginColorConvert.html">NDPluginColorConvert</a></li>
<li><a href="NDPluginFile.html">NDPluginFile</a></li>
<li><a href="NDPluginOverlay.html">NDPluginOverlay</a></li>
<li><a href="NDPluginProcess.html">NDPluginProcess</a></li>
<li><a href="NDPluginROI.html">NDPluginROI</a></li>
<li><a href="NDPluginStats.html">NDPluginStats</a></li>
<li><a href="NDPluginStdArrays.html">NDPluginStdArrays</a></li>
<li><a href="NDPluginTransform.html">NDPluginTransform</a></li>
</ul>
<h2 id="Overview">
Overview</h2>
<p>
A powerful feature of the <a href="areaDetectorDoc.html">areaDetector</a> module
is the concept of plugins. A plugin is code that is called by a driver that passes
NDArray data in a callback. Plugins can be used to process array data in real time.
Existing plugins convert data to standard asyn arrays (NDPluginStdArrays), save
data to disk (NDPluginFile), select regions-of-interest (NDPluginROI), and convert
color modes (NDPluginColorConvert). New plugins could be written to perform functions
like finding the centroid of a beam, etc. Once a plugin is written it will work
with any areaDetector driver. Plugins have the the following properties:
</p>
<ul>
<li>They can execute either in a blocking mode or a non-blocking mode. In the blocking
mode the callback is executed by the driver callback thread. In this mode the callback
is guaranteed to execute for each NDArray callback. However, it can slow down the
driver, and does not utilize the multi-core capability of modern CPUs. In the non-blocking
mode the driver callback simply places the NDArray data in a queue that is part
of the plugin. The plugin then executes the callback code in it own thread. It removes
NDArray data from the queue, processes it, and releases the data back to the NDArrayPool
when it is done. In the non-blocking mode some additional memory is required for
the NDArray objects that are in the queue. It is also possible to drop NDArray data
if the queue is full when a callback occurs, i.e. some callback data will not be
processed. The non-blocking mode can utilize the multi-core capabilities of modern
CPUs because each plugin is executing in its own thread. The operation of the queue
and the NDArrayPool class means that data never needs to be copied, each plugin
has a pointer to the data which will continue to be valid until the last plugin
is done with it.</li>
<li>They can be enabled or disabled at run time.</li>
<li>They can be throttled to only execute at a limited rate. This means, for example,
that a detector can be saving data to disk at full speed, but images can be posted
to EPICS at a reduced rate.</li>
<li>They can be unplugged from one driver, and plugged into another driver at run
time. For example, the NDPluginROI driver is itself a source of NDArray data callbacks,
so a file saving plugin could be unplugged from a detector driver (where it would
be saving the entire detector), and plugged into a particular ROI, where it would
just save a portion of the detector. Similarly the NDPluginColorConvert plugin is
also a source of NDArray data callbacks. A pipeline of plugins can be constructed,
for example NDPluginColorConvert-&gt;NDPluginROI-&gt;NDPluginStdArrays. Each stage
of this pipeline can be executing in its own thread, and on modern multi-core processors
each can be executing on its own core.</li>
</ul>
<h2 id="NDPluginDriver">
NDPluginDriver</h2>
<p>
NDPluginDriver inherits from <a href="areaDetectorDoc.html#asynNDArrayDriver">asynNDArrayDriver</a>.
NDPluginDriver is the class from which actual plugins are directly derived. The
NDPluginDriver class handles most of the details of processing NDArray callbacks
from the driver. Plugins derived from this class typically need to implement the
processCallbacks method, and one or more of the write(Int32, Float64, Octet) methods.
The <a href="areaDetectorDoxygenHTML/class_n_d_plugin_driver.html">NDPluginDriver
class documentation </a>describes this class in detail.
</p>
<p>
NDPluginDriver defines parameters that all plugin drivers should implement if possible.
These parameters are defined by strings (drvInfo strings in asyn) with an associated
asyn interface, and access (read-only or read-write). The EPICS database NDPluginBase.template
provides access to these standard plugin parameters, listed in the following table.
Note that to reduce the width of this table the parameter index variable names have
been split into 2 lines, but these are just a single name, for example <code>NDPluginDriverArrayPort</code>.
</p>
<table border="1" cellpadding="2" cellspacing="2" style="text-align: left">
<tbody>
<tr>
<td align="center" colspan="7,">
<b>Parameter Definitions in NDPluginDriver.h and EPICS Record Definitions in NDPluginBase.template</b>
</td>
</tr>
<tr>
<th>
Parameter index variable</th>
<th>
asyn interface</th>
<th>
Access</th>
<th>
Description</th>
<th>
drvInfo string</th>
<th>
EPICS record name</th>
<th>
EPICS record type</th>
</tr>
<tr>
<td align="center" colspan="7,">
<b>Information about this plugin</b></td>
</tr>
<tr>
<td>
NDPortNameSelf</td>
<td>
asynOctet</td>
<td>
r/o</td>
<td>
asyn port name</td>
<td>
PORT_NAME_SELF</td>
<td>
$(P)$(R)PortName_RBV</td>
<td>
stringin</td>
</tr>
<tr>
<td>
NDPluginDriver<br />
PluginType</td>
<td>
asynOctet</td>
<td>
r/o</td>
<td>
A string describing the plugin type.</td>
<td>
PLUGIN_TYPE</td>
<td>
$(P)$(R)PluginType_RBV</td>
<td>
stringin</td>
</tr>
<tr>
<td align="center" colspan="7,">
<b>asyn NDArray driver doing callbacks</b></td>
</tr>
<tr>
<td>
NDPluginDriver<br />
ArrayPort</td>
<td>
asynOctet</td>
<td>
r/w</td>
<td>
asyn port name for NDArray driver that will make callbacks to this plugin. This
port can be changed at run time, connecting the plugin to a different NDArray driver.
</td>
<td>
NDARRAY_PORT</td>
<td>
$(P)$(R)NDArrayPort<br />
(P)$(R)NDArrayPort_RBV</td>
<td>
stringout<br />
stringin</td>
</tr>
<tr>
<td>
NDPluginDriver<br />
ArrayAddr</td>
<td>
asynInt32</td>
<td>
r/w</td>
<td>
asyn port address for NDArray driver that will make callbacks to this plugin. This
address can be changed at run time, connecting the plugin to a different address
in the NDArray driver.</td>
<td>
NDARRAY_ADDR</td>
<td>
$(P)$(R)NDArrayAddress<br />
$(P)$(R)NDArrayAddress_RBV</td>
<td>
longout<br />
longin</td>
</tr>
<tr>
<td align="center" colspan="7,">
<b>Queue size and status</b></td>
</tr>
<tr>
<td>
NDPluginDriver<br />
QueueSize</td>
<td>
asynInt32</td>
<td>
r/o</td>
<td>
The total queue size for callbacks when BlockingCallbacks=0. </td>
<td>
QUEUE_SIZE</td>
<td>
$(P)$(R)QueueSize</td>
<td>
longin</td>
</tr>
<tr>
<td>
NDPluginDriver<br />
QueueFree</td>
<td>
asynInt32</td>
<td>
r/o</td>
<td>
The number of free queue elements.</td>
<td>
QUEUE_FREE</td>
<td>
$(P)$(R)QueueFree</td>
<td>
longin</td>
</tr>
<tr>
<td>
NDPluginDriver<br />
QueueUse</td>
<td>
N/A</td>
<td>
r/o</td>
<td>
The number of used queue elements.</td>
<td>
N/A</td>
<td>
$(P)$(R)QueueUse</td>
<td>
calc</td>
</tr>
<tr>
<td align="center" colspan="7,">
<b>NDArray pool size and status (only for plugins that generate NDArrays for use by
other plugins)</b></td>
</tr>
<tr>
<td>
NDPool<br />
MaxMemory</td>
<td>
asynFloat64</td>
<td>
r/o</td>
<td>
The maximum amount of NDArrayPool memory this plugin is allowed to allocate.</td>
<td>
POOL_MAX_MEMORY</td>
<td>
$(P)$(R)PoolMaxMem</td>
<td>
ai</td>
</tr>
<tr>
<td>
NDPool<br />
UsedMemory</td>
<td>
asynFloat64</td>
<td>
r/o</td>
<td>
The actual amount of NDArrayPool memory this plugin is currently using.</td>
<td>
POOL_USED_MEMORY</td>
<td>
$(P)$(R)PoolUsedMem</td>
<td>
ai</td>
</tr>
<tr>
<td>
NDPool<br />
MaxBuffers</td>
<td>
asynInt32</td>
<td>
r/o</td>
<td>
The maximum number of NDArrays this plugin is allowed to allocate.</td>
<td>
POOL_MAX_BUFFERS</td>
<td>
$(P)$(R)PoolMaxBuffers</td>
<td>
longin</td>
</tr>
<tr>
<td>
NDPool<br />
AllocBuffers</td>
<td>
asynInt32</td>
<td>
r/o</td>
<td>
The number of NDArrays this plugin has currently allocated.</td>
<td>
POOL_ALLOC_BUFFERS</td>
<td>
$(P)$(R)PoolAllocBuffers</td>
<td>
longin</td>
</tr>
<tr>
<td>
NDPool<br />
FreeBuffers</td>
<td>
asynInt32</td>
<td>
r/o</td>
<td>
The number of free NDArrays this plugin has in its NDArrayPool.</td>
<td>
POOL_FREE_BUFFERS</td>
<td>
$(P)$(R)PoolFreeBuffers</td>
<td>
longin</td>
</tr>
<tr>
<td>
N/A</td>
<td>
N.A</td>
<td>
N/A</td>
<td>
The number of used NDArrays this plugin has in its NDArrayPool. Calculated from
PoolAllocBuffers and PoolFreeBuffers.</td>
<td>
N/A</td>
<td>
$(P)$(R)PoolUsedBuffers</td>
<td>
calc</td>
</tr>
<tr>
<td align="center" colspan="7,">
<b>Callback enable, minimum time, and statistics</b></td>
</tr>
<tr>
<td>
NDPluginDriver<br />
EnableCallbacks</td>
<td>
asynInt32</td>
<td>
r/w</td>
<td>
Enable (1) or disable (0) callbacks from the driver to this plugin. If callbacks
are disabled then the plugin will normally be idle and consume no CPU resources.
</td>
<td>
ENABLE_CALLBACKS</td>
<td>
$(P)$(R)EnableCallbacks<br />
$(P)$(R)EnableCallbacks_RBV</td>
<td>
bo<br />
bi</td>
</tr>
<tr>
<td>
NDPluginDriver<br />
BlockingCallbacks</td>
<td>
asynInt32</td>
<td>
r/w</td>
<td>
0 = callbacks from the driver do not block; the NDArray data is put on a queue and
the callback processes in its own thread.
<br />
1 = callbacks from the driver block; the callback processes in the driver callback
thread.</td>
<td>
BLOCKING_CALLBACKS</td>
<td>
$(P)$(R)BlockingCallbacks<br />
$(P)$(R)BlockingCallbacks_RBV</td>
<td>
bo<br />
bi</td>
</tr>
<tr>
<td>
NDPluginDriver<br />
MinCallbackTime</td>
<td>
asynFloat64</td>
<td>
r/w</td>
<td>
The minimum time in seconds between calls to processCallbacks. Any callbacks occuring
before this minimum time has elapsed will be ignored. 0 means no minimum time, i.e.
process all callbacks.</td>
<td>
MIN_CALLBACK_TIME</td>
<td>
$(P)$(R)MinCallbackTime<br />
$(P)$(R)MinCallbackTime_RBV</td>
<td>
ao<br />
ai</td>
</tr>
<tr>
<td>
NDPluginDriver<br />
ArrayCounter</td>
<td>
asynInt32</td>
<td>
r/w</td>
<td>
Counter that increments by 1 each time an NDArray callback is processed</td>
<td>
ARRAY_COUNTER</td>
<td>
$(P)$(R)ArrayCounter<br />
$(P)$(R)ArrayCounter_RBV</td>
<td>
longout<br />
longin</td>
</tr>
<tr>
<td>
N/A</td>
<td>
N/A</td>
<td>
r/o</td>
<td>
Rate (Hz) at which ArrayCounter is incrementing. Computed in database.</td>
<td>
N/A</td>
<td>
$(P)$(R)ArrayRate_RBV</td>
<td>
calc</td>
</tr>
<tr>
<td>
NDPluginDriver<br />
DroppedArrays</td>
<td>
asynInt32</td>
<td>
r/w</td>
<td>
Counter that increments by 1 each time an NDArray callback occurs when NDPluginDriverBlockingCallbacks=0
and the plugin driver queue is full, so the callback cannot be processed.</td>
<td>
DROPPED_ARRAYS</td>
<td>
$(P)$(R)DroppedArrays<br />
$(P)$(R)DroppedArrays_RBV</td>
<td>
longout<br />
longin</td>
</tr>
<tr>
<td align="center" colspan="7,">
<b>Information about last NDArray callback data</b></td>
</tr>
<tr>
<td>
NDPluginDriver<br />
NDimensions</td>
<td>
asynInt32</td>
<td>
r/o</td>
<td>
Number of dimensions in last NDArray callback data</td>
<td>
ARRAY_NDIMENSIONS</td>
<td>
$(P)$(R)NDimensions_RBV</td>
<td>
longin</td>
</tr>
<tr>
<td>
NDPluginDriver<br />
Dimensions</td>
<td>
asynInt32Array</td>
<td>
r/o</td>
<td>
Dimensions in last NDArray callback data</td>
<td>
ARRAY_DIMENSIONS</td>
<td>
$(P)$(R)Dimensions_RBV</td>
<td>
waveform</td>
</tr>
<tr>
<td>
N/A</td>
<td>
N/A</td>
<td>
r/o</td>
<td>
First dimension of NDArray callback data</td>
<td>
N/A</td>
<td>
$(P)$(R)ArraySize0_RBV</td>
<td>
longin</td>
</tr>
<tr>
<td>
N/A</td>
<td>
N/A</td>
<td>
r/o</td>
<td>
Second dimension of NDArray callback data</td>
<td>
N/A</td>
<td>
$(P)$(R)ArraySize1_RBV</td>
<td>
longin</td>
</tr>
<tr>
<td>
N/A</td>
<td>
N/A</td>
<td>
r/o</td>
<td>
Third dimension of NDArray callback data</td>
<td>
N/A</td>
<td>
$(P)$(R)ArraySize2_RBV</td>
<td>
longin</td>
</tr>
<tr>
<td>
NDPluginDriver<br />
DataType</td>
<td>
asynInt32</td>
<td>
r/o</td>
<td>
Data type of last NDArray callback data (NDDataType_t).</td>
<td>
DATA_TYPE</td>
<td>
$(P)$(R)DataType_RBV</td>
<td>
mbbi</td>
</tr>
<tr>
<td>
NDPluginDriver<br />
ColorMode</td>
<td>
asynInt32</td>
<td>
r/o</td>
<td>
Color mode of last NDArray callback data (NDColorMode_t).</td>
<td>
COLOR_MODE</td>
<td>
$(P)$(R)ColorMode_RBV</td>
<td>
mbbi</td>
</tr>
<tr>
<td>
NDPluginDriver<br />
BayerPattern</td>
<td>
asynInt32</td>
<td>
r/o</td>
<td>
BayerPattern of last NDArray callback data (NDBayerPattern_t).</td>
<td>
BAYER_PATTERN</td>
<td>
$(P)$(R)BayerPattern_RBV</td>
<td>
mbbi</td>
</tr>
<tr>
<td>
NDPluginDriver<br />
UniqueId</td>
<td>
asynInt32</td>
<td>
r/o</td>
<td>
Unique ID number of last NDArray callback data</td>
<td>
UNIQUE_ID</td>
<td>
$(P)$(R)UniqueId_RBV</td>
<td>
longin</td>
</tr>
<tr>
<td>
NDPluginDriver<br />
TimeStamp</td>
<td>
asynFloat64</td>
<td>
r/o</td>
<td>
Time stamp number of last NDArray callback data</td>
<td>
TIME_STAMP</td>
<td>
$(P)$(R)TimeStamp_RBV</td>
<td>
ai</td>
</tr>
<tr>
<td align="center" colspan="7">
<b>Array attributes</b></td>
</tr>
<tr>
<td>
NDAttributesFile</td>
<td>
asynOctet</td>
<td>
r/w</td>
<td>
The name of an XML file defining the PVAttributes and paramAttributes to be added
to each NDArray by this plugin. The format of the XML file is described in the documentation
for <a href="areaDetectorDoxygenHTML/classasyn_n_d_array_driver.html">asynNDArrayDriver::readNDAttributesFile().</a>
</td>
<td>
ND_ATTRIBUTES_FILE</td>
<td>
$(P)$(R)NDAttributesFile</td>
<td>
waveform</td>
</tr>
<tr>
<td align="center" colspan="7,">
<b>Debugging control</b></td>
</tr>
<tr>
<td>
N/A</td>
<td>
N/A</td>
<td>
N/A</td>
<td>
asyn record to control debugging (asynTrace)</td>
<td>
N/A</td>
<td>
$(P)$(R)AsynIO</td>
<td>
asyn</td>
</tr>
</tbody>
</table>
<h2 id="Guidelines">
Guidelines and rules for plugins</h2>
<p>
The following are guidelines and rules for writing plugins</p>
<ul>
<li>Plugins will almost always implement the processCallbacks() function. This function
will be called with an NDArray pointer each time an NDArray callback occurs. This
function will normally call the NDPluginDriver::processCallbacks() base class function,
which handles tasks common to all plugins, including callbacks with information
about the array, etc.</li>
<li>Plugins will generally implement one or more of the writeInt32(), writeFloat64()
or writeOctet() functions if they need to act immediately on a new value of a parameter.
For many parameters it is normally sufficient to simply have them written to the
parameter library, and not to handle them in the writeXXX() functions. The parameters
are then retrieved from the parameter library with the getIntParam(), getDoubleParam(),
or getStringParam() function calls when they are needed.</li>
<li>If the writeInt32(), writeFloat64() or writeOctet() functions are implemented
they <b>must</b> call the base class function for parameters that they do not handle
and whose parameter index value is less than the first parameter of this class,
i.e. parameters that belong to a base class.</li>
<li>Plugins will need to call the createParam() function in their constructor if they
have additional parameters beyond those in the asynPortDriver or NDPluginDriver
base classes.</li>
<li>Plugins may <b>never</b> modify the NDArray that they receive in the processCallbacks()
function. The reason is that other plugins may be concurrently operating on the
same NDArray, since each is passed the same pointer. This means also that when getting
the attributes for this plugin that asynNDArrayDriver::getAttributes(pArray->pAttributeList)
must not be called with the NDArray passed to processCallbacks(), because that will
modify the NDArray attribute list, and hence the NDArray that other plugins are
operating on. Plugins such as NDPluginROI and NDPluginColorConvert create new NDArrays
via NDArrayPool::copy() or NDArrayPool::convert() (which copy the attributes to
the new array) and then call getAttributes(pArray->pAttributeList) with the new
array. The NDPluginFile makes a copy of the attribute list from the original NDArray
before calling getAttributes(), but does not need to make a copy of the NDArray
because it does not modify it.</li>
<li>Plugins must release their mutex by calling this->unlock() when they do time-consuming
operations. If they do not then they will not be able to queue new NDArrays callbacks
or obtain new parameter values. Obviously they must not access memory locations
that other threads could modify during this time, so they should only access local
variables, not class variables (which includes the parameter library).</li>
<li>If plugins generate new or modified NDArrays then they must call doCallbacksGenericPointer()
so that registered clients can get the values of the new arrays.</li>
</ul>
<h2 id="commonPlugins">
commonPlugins.cmd</h2>
<p>
The areaDetector iocBoot directory contains a file called commonPlugins.cmd. This
file is loaded by all of the example driver IOC startup scripts. It loads a set
of plugins which are typically useful for detectors IOCs. Each detector medm screen
has links to related displays for each of the common plugins. While this set of
plugins is often useful and sufficient, users are free to add or remove plugins
from this set for their own IOCs. New medm displays will typically need to be created
if that is done, to have the required links to related displays.</p>
<p>
The following medm screen shows the status of all of the common plugins at a glance,
with links to bring up the detailed screen for each.</p>
<div style="text-align: center">
<h3 style="text-align: center">
commonPlugins.adl</h3>
<img alt="commonPlugins.png" src="commomPlugins.png" /></div>
</body>
</html>