Files
ADAndor/documentation/pluginDoc.html
2008-09-18 20:20:18 +00:00

1504 lines
49 KiB
HTML
Executable File

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>areaDetector Plugins</title>
</head>
<body>
<center>
<h1>
areaDetector Plugins</h1>
<h2>
September 5, 2008</h2>
<h2>
Mark Rivers</h2>
<h2>
University of Chicago</h2>
</center>
<br />
<center>
<h2>
Contents</h2>
</center>
<ul>
<li><a href="#Overview">Overview</a></li>
<li><a href="#NDPluginDriver">NDPluginDriver</a></li>
<li><a href="#NDPluginStdArrays">NDPluginStdArrays</a>
<ul>
<li><a href="#NDPluginStdArraysConfiguration">Configuration</a></li>
<li><a href="#IDLClient">IDL Display Client</a></li>
</ul>
</li>
<li><a href="#NDPluginFile">NDPluginFile</a>
<ul>
<li><a href="#NDPluginFileConfiguration">Configuration</a></li>
</ul>
</li>
<li><a href="#NDPluginROI">NDPluginROI</a>
<ul>
<li><a href="#NDPluginROIConfiguration">Configuration</a></li>
</ul>
</li>
</ul>
<center>
<h2 id="Overview">
Overview</h2>
</center>
<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), and select regions-of-interest (NDPluginROI). 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, 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, 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. In particular 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.</li>
</ul>
<center>
<h2 id="NDPluginDriver">
NDPluginDriver</h2>
</center>
<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, the drvUser method, and one or more of the write(Int32, Float64, Octet) methods. The NDPluginDriver
public interface is defined in NDPluginDriver.h as follows:
</p>
<pre>class NDPluginDriver : public asynNDArrayDriver {
public:
NDPluginDriver(const char *portName, int queueSize, int blockingCallbacks,
const char *NDArrayPort, int NDArrayAddr, int maxAddr, int paramTableSize,
int maxBuffers, size_t maxMemory, int interfaceMask, int interruptMask);
/* These are the methods that we override from asynNDArrayDriver */
virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
virtual asynStatus writeOctet(asynUser *pasynUser, const char *value, size_t maxChars,
size_t *nActual);
virtual asynStatus readInt32Array(asynUser *pasynUser, epicsInt32 *value,
size_t nElements, size_t *nIn);
virtual asynStatus drvUserCreate(asynUser *pasynUser, const char *drvInfo,
const char **pptypeName, size_t *psize);
/* These are the methods that are new to this class */
virtual void processCallbacks(NDArray *pArray);
virtual void driverCallback(asynUser *pasynUser, void *genericPointer);
virtual void processTask(void);
virtual asynStatus setArrayInterrupt(int connect);
virtual asynStatus connectToArrayPort(void);
int createFileName(int maxChars, char *fullFileName);
...
}
</pre>
<p>
The methods of the NDPluginDriver class are:
</p>
<ul>
<li><code>NDPluginDriver</code> This is the constructor for the class. All parameters
except queueSize, blockingCallbacks, NDArrayPort, and NDArrayAddr are just passed
to the constructor for asynNDArrayDriver. NDArrayPort and NDArrayAddr, and blockingCallbacks
are the initial values for the NDPluginDriverArrayPort, NDPluginDriverArrayAddr
and NDPluginDriverBlockingCallbacks parameters described in the table below.</li>
<li><code>drvUserCreate</code> This method returns one of the enum values for the
parameters defined in NDPluginDriver.h if the driverInfo field matches one the strings
defined in that file. Derived classes will typically provide an implementation of
drvUserCreate() that searches for parameters that are unique to that plugin. If
a parameter is not matched, then NDPluginDriver->drvUserCreate() will be called
to see if it is a standard plugin parameter (defined in NDPluginDriver.h).</li>
<li><code>processCallbacks</code> This method is called each time a driver calls the
plugin with a new NDArray object. Derived classes typically call this base class
method, which handles some bookkeeping chores, and then they perform whatever operations
are specific to that plugin.</li>
<li><code>createFileName</code> This is a convenience function that constructs a complete
file name in the ADFullFileName parameter from the ADFilePath, ADFileName, ADFileNumber,
and ADFileTemplate parameters.</li>
</ul>
<p>
NDPluginDriver defines parameters that all plugin drivers should implement if possible.
These parameters are defined by enum values 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.
</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>
Enum name</th>
<th>
asyn interface</th>
<th>
Access</th>
<th>
Description</th>
<th>
drvUser string</th>
<th>
EPICS record name</th>
<th>
EPICS record type</th>
</tr>
<tr>
<td align="CENTER" colspan="7,">
<b>asyn NDArray driver doing callbacks</b></td>
</tr>
<tr>
<td>
NDPluginDriverArrayPort</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>
NDPluginDriverArrayAddr</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>Callback enable, minimum time, and statistics</b></td>
</tr>
<tr>
<td>
NDPluginDriverEnableCallbacks</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>
NDPluginDriverMinCallbackTime</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>
NDPluginDriverArrayCounter</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>
NDPluginDriverDroppedArrays</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>
NDPluginDriverNDimensions</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>
NDPluginDriverDimensions</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>
NDPluginDriverDataType</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>
NDPluginDriverUniqueId</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>
NDPluginDriverTimeStamp</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>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>
<center>
<h2>
&nbsp;</h2>
<h2>
NDPluginStdArrays</h2>
</center>
<p>
NDPluginStdArrays inherits from NDPluginDriver. NDPluginStdArrays converts the NDArray
data from a callback into the 1-dimensional arrays supported by the standard asyn
array interfaces, i.e. asyn[Int8, Int16, Int32, Float32, Float64]Array. These interfaces
are supported by the EPICS waveform record using standard asyn device support. This
plugin is thus the tool for converting the NDArray data produced by asynNDArrayDriver
drivers into a form that can be accessed by EPICS. Because this plugin inherits
from NDPluginDriver it also provides additional information on the array data (e.g.
number of dimensions and dimension data described above) that are made available
as EPICS PVs so that clients can correctly interpret the array data. The NDPluginStdArrays
public interface is defined in NDPluginStdArrays.h as follows:</p>
<pre>class NDPluginStdArrays : public NDPluginDriver {
public:
NDPluginStdArrays(const char *portName, int queueSize, int blockingCallbacks,
const char *NDArrayPort, int NDArrayAddr,
size_t maxMemory);
/* These methods override the virtual methods in the base class */
void processCallbacks(NDArray *pArray);
virtual asynStatus readInt8Array(asynUser *pasynUser, epicsInt8 *value,
size_t nElements, size_t *nIn);
virtual asynStatus readInt16Array(asynUser *pasynUser, epicsInt16 *value,
size_t nElements, size_t *nIn);
virtual asynStatus readInt32Array(asynUser *pasynUser, epicsInt32 *value,
size_t nElements, size_t *nIn);
virtual asynStatus readFloat32Array(asynUser *pasynUser, epicsFloat32 *value,
size_t nElements, size_t *nIn);
virtual asynStatus readFloat64Array(asynUser *pasynUser, epicsFloat64 *value,
size_t nElements, size_t *nIn);
asynStatus drvUserCreate(asynUser *pasynUser, const char *drvInfo,
const char **pptypeName, size_t *psize);
...
}
</pre>
<p>
NDPluginStdArrays defines the following parameters. It also implements all of the
standard plugin parameters from NDPlugDriver listed above. The EPICS database NDStdArrays.template
provides access to these parameters, listed in the following table.
</p>
<table border="1" cellpadding="2" cellspacing="2" style="text-align: left">
<tbody>
<tr>
<td align="CENTER" colspan="7,">
<b>Parameter Definitions in NDPluginStdArrays.h and EPICS Record Definitions in NDStdArrays.template</b></td>
</tr>
<tr>
<th>
Enum name</th>
<th>
asyn interface</th>
<th>
Access</th>
<th>
Description</th>
<th>
drvUser string</th>
<th>
EPICS record name</th>
<th>
EPICS record type</th>
</tr>
<tr>
<td>
NDPluginStdArraysData</td>
<td>
asyn[Int8, Int16, Int32, Float32, Float64]Array</td>
<td>
r/o</td>
<td>
Array data as a 1-D array, possibly converted in data type from that in the NDArray
object to the specific asyn interface.</td>
<td>
STD_ARRAY_DATA</td>
<td>
$(P)$(R)ArrayData</td>
<td>
waveform</td>
</tr>
</tbody>
</table>
<p>
If the array data contains more than 16,000 bytes then in order for EPICS clients
to receive this data they must be built with EPICS R3.14 (not R3.13), and the environment
variable EPICS_CA_MAX_ARRAY_BYTES on both the EPICS IOC computer and EPICS client
computer must be set to a value at least as large as the array size in bytes.</p>
<p>
The following is the MEDM screen that provides access to the parameters in NDPluginDriver.h
and NDPluginStdArrays.h through records in NDPluginBase.template and NDStdArrays.template.
This is the MEDM screen that is normally used to control the display of images via
EPICS channel access.
</p>
<center>
<img alt="NDStdArrays.png" src="NDStdArrays.png" />
</center>
<h3 id="NDPluginStdArraysConfiguration">
Configuration</h3>
<p>
The NDPluginStdArrays plugin is created with the following command, either from
C/C++ or from the EPICS IOC shell.
</p>
<pre>drvNDStdArraysConfigure(const char *portName, int queueSize, int blockingCallbacks,
const char *NDArrayPort, int NDArrayAddr, size_t maxMemory)
</pre>
<table border="1" cellpadding="2" cellspacing="2" style="text-align: left">
<tr>
<th>
Argument</th>
<th>
Description</th>
</tr>
<tr>
<td>
<code>portName</code></td>
<td>
The name of the asyn port for this plugin.
</td>
</tr>
<tr>
<td>
<code>queueSize</code></td>
<td>
The maximum number of NDArray objects that can be queued for processing. Passed
to the NDPluginDriver base class constructor.
</td>
</tr>
<tr>
<td>
<code>blockingCallbacks</code></td>
<td>
Flag controlling whether callbacks block. Passed to the NDPluginDriver base class
constructor.
</td>
</tr>
<tr>
<td>
<code>NDArrayPort</code></td>
<td>
The name of the asyn port of the driver that will provide the NDArray data. Passed
to the NDPluginDriver base class constructor.
</td>
</tr>
<tr>
<td>
<code>NDArrayAddr</code></td>
<td>
The asyn addr of the asyn port of the driver that will provide the NDArray data.
Passed to the NDPluginDriver base class constructor.
</td>
</tr>
<tr>
<td>
<code>maxMemory</code></td>
<td>
Maximum number of bytes of memory to be allocated from the NDArrayPool. Passed to
the constructor for the NDPluginDriver base class. The NDStdArrays plugin allocates
2 NDArray objects, so this should be at least twice the size of the largest NDArray
to be used.</td>
</tr>
</table>
<br />
<h3 id="IDLClient">
IDL Image Display Client</h3>
<p>
There is an IDL program called <code>epics_ad_display</code> that can be used to
display 2-dimensional ArrayData that the NDStdArrays plugin sends to EPICS. This
IDL client is available as source code (which requires an IDL license), and also
as a pre-built IDL .sav file that can be run for free under the IDL Virtual Machine.
This IDL program can run on any machine that IDL runs on, and that has the ezcaIDL
shareable library built for it. This includes Windows, Linux, Solaris, and Mac.
<code>epics_ad_display</code> is included in the <a href="http://cars.uchicago.edu/software/IDL/imaging.html">
CARS IDL imaging software.</a>
</p>
<p>
The control window for <code>epics_ad_display</code> is shown below. It has fields
to input the base name of the EPICS PVs with the image data. The client uses the
</p>
<center>
<h3>
Main window for IDL epics_ad_display</h3>
<img alt="pilatusROI_EPICS_ImageDisplay.png" src="pilatusROI_EPICS_ImageDisplay.png" /></center>
<p>
<code>epics_ad_display</code> uses the routine <a href="http://cars.uchicago.edu/software/IDL/imaging_routines.html#IMAGE_DISPLAY">
image_display.pro</a> to display the images. This routine displays row and column
profiles as the cursor is moved. It allows changing the color lookup tables, and
zooming in and out with the left and right mouse buttons. The following is an example
of <code>image_display</code> displaying a Pilatus image with an Fe55 source in
front of the detector.</p>
<center>
<h3>
IDL image_display with Fe55 radioactive source</h3>
<img alt="pilatusROI_IDL_ImageDisplay.png" src="pilatus_IDL_ImageDisplay.png" /></center>
<br />
<center>
<h2 id="NDPluginFile">
&nbsp;</h2>
<h2>
&nbsp;</h2>
<h2>
NDPluginFile</h2>
</center>
<p>
NDPluginFile inherits from NDPluginDriver. NDPluginFile saves the NDArray data from
a callback to a disk file. This plugin currently saves data in the <a href="http://www.unidata.ucar.edu/software/netcdf">
netCDF</a> file format, which is a portable self-describing binary file format
supported by <a href="http://www.unidata.ucar.edu/">UniData</a> at <a href="http://www.ucar.edu/">
UCAR (University Corporation for Atmospheric Research).</a> Additional file formats,
such as TIFF and HDF may be supported in the future.
</p>
<p>
The NDArray callback data can be written to disk in 1 of 3 modes:
</p>
<ol>
<li>Single mode. In this mode each NDArray callback results in a separate disk file.</li>
<li>Capture mode. In this mode a memory buffer is allocated before saving begins.
Callback arrays are placed into this buffer, and when capture stops the file is
written to disk. This mode limits the number of frames that can be saved, because
they all must fit in a memory buffer. It is the fastest mode, with the least probability
of dropping arrays, because no disk I/O is required while capture is in progress.</li>
<li>Stream mode. In this mode the data are written to a single disk file, with each
frame being appended to the file without closing it. It is intermediate in speed
between single mode and capture mode, but unlike capture mode it is not limited
by available memory in the number of arrays that can be saved.</li>
</ol>
<p>
The NDPluginFile public interface is defined in NDPluginFile.h as follows:
</p>
<pre>/* Note that the file format enum must agree with the mbbo/mbbi records in the NDFile.template file */
typedef enum {
NDFileFormatNetCDF,
} NDPluginFileFormat_t;
typedef enum {
NDPluginFileModeSingle,
NDPluginFileModeCapture,
NDPluginFileModeStream
} NDPluginFileMode_t;
...
class NDPluginFile : public NDPluginDriver {
public:
NDPluginFile(const char *portName, int queueSize, int blockingCallbacks,
const char *NDArrayPort, int NDArrayAddr);
/* These methods override those in the base class */
void processCallbacks(NDArray *pArray);
asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
asynStatus writeNDArray(asynUser *pasynUser, void *genericPointer);
asynStatus drvUserCreate(asynUser *pasynUser, const char *drvInfo,
const char **pptypeName, size_t *psize);
...
}
</pre>
<p>
NDPluginFile also supports all of the file saving parameters defined in ADStdDriverParams.h
described above, e.g.ADFilePath, ADFileName, etc. Thus, the same interface that
is used for saving files directly in a driver are used for this plugin.
</p>
<p>
The following is the MEDM screen that provides access to the parameters in NDPluginDriver.h
and NDPluginFile.h through records in NDPluginBase.template and NDFile.template.
This is the MEDM screen that is used to control the saving of images to disk for
drivers that do not support saving files to disk themselves.
</p>
<center>
<img alt="NDStdArrays.png" src="NDStdArrays.png" />
</center>
<h3 id="NDPluginFileConfiguration">
Configuration</h3>
<p>
The NDPluginFile plugin is created with the following command, either from C/C++
or from the EPICS IOC shell.
</p>
<pre>drvNDFileConfigure(const char *portName, int queueSize, int blockingCallbacks,
const char *NDArrayPort, int NDArrayAddr)
</pre>
<table border="1" cellpadding="2" cellspacing="2" style="text-align: left">
<tr>
<th>
Argument</th>
<th>
Description</th>
</tr>
<tr>
<td>
<code>portName</code></td>
<td>
The name of the asyn port for this plugin.
</td>
</tr>
<tr>
<td>
<code>queueSize</code></td>
<td>
The maximum number of NDArray objects that can be queued for processing. Passed
to the NDPluginDriver base class constructor.
</td>
</tr>
<tr>
<td>
<code>blockingCallbacks</code></td>
<td>
Flag controlling whether callbacks block. Passed to the NDPluginDriver base class
constructor.
</td>
</tr>
<tr>
<td>
<code>NDArrayPort</code></td>
<td>
The name of the asyn port of the driver that will provide the NDArray data. Passed
to the NDPluginDriver base class constructor.
</td>
</tr>
<tr>
<td>
<code>NDArrayAddr</code></td>
<td>
The asyn addr of the asyn port of the driver that will provide the NDArray data.
Passed to the NDPluginDriver base class constructor.
</td>
</tr>
</table>
<br />
<center>
<img alt="NDFile.png" src="NDFile.png" />
</center>
<center>
<h2 id="NDPluginROI">
NDPluginRI</h2>
</center>
<p>
NDPluginROI inherits from NDPluginDriver. NDPluginROI selects one or more rectangular
"Regions-Of-Interest" (ROIs) from the NDArray callback data. The maximum number
of ROIs is defined when the plugin is created. Each ROI can be any size, from a
single array element to the entire array. NDPluginROI does 3 things with these ROIs:
</p>
<ol>
<li>Computes statistics, e.g. mean, maximum, minimum, total value, net (background
subtracted) value</li>
<li>Computes a histogram of the values (e.g. number of pixels versus intensity per
pixel)</li>
<li>Exports the ROI as a new NDArray object. In this regard NDPluginROI is different
from the NDPluginStdArrays and NDPluginFile plugins because it is both a <b>recipient</b>
of callbacks (as they are) and a <b>source</b> of NDArray callbacks, as a driver
is. This means that the NDPluginStdArrays and NDPluginFile plugins can be connected
to an NDPluginROI plugin, in which case they will save or display the selected ROI
rather than the full detector driver data.</li>
</ol>
<p>
Each NDPluginROI can handle any number of ROIs. The maximum number of ROIs that
the plugin can support is defined when the plugin is created. Several ROI plugins
could be created for a single detector driver to increase the number of threads
running in parallel, maximizing the use of multiple CPU cores. Individual ROIs are
addressed through the asyn interfaces by the asyn "addr" field in the asynUser structure.
Note that while the NDPluginROI should be N-dimensional, the definition of the ROI
is currently limited to 2-D. This limitation will be removed in a future release.
</p>
<p>
The NDPluginROI public interface is defined in NDPluginROI.h as follows:
</p>
<pre>class NDPluginROI : public NDPluginDriver {
public:
NDPluginROI(const char *portName, int queueSize, int blockingCallbacks,
const char *NDArrayPort, int NDArrayAddr, int maxROIs, size_t maxMemory);
/* These methods override the virtual methods in the base class */
void processCallbacks(NDArray *pArray);
asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
asynStatus drvUserCreate(asynUser *pasynUser, const char *drvInfo,
const char **pptypeName, size_t *psize);
/* These methods are unique to this class */
asynStatus readFloat64Array(asynUser *pasynUser, epicsFloat64 *value,
size_t nelements, size_t *nIn);
</pre>
<p>
The readFloat64Array method is used to read the histogram data for the ROI.
</p>
<p>
NDPluginROI.h defines the following parameters that are global to all ROIs for a
plugin. It also implements all of the standard plugin parameters from NDPlugDriver
listed above. The EPICS database NDROI.template provide access to these parameters,
listed in the following table.
</p>
<table border="1" cellpadding="2" cellspacing="2" style="text-align: left">
<tbody>
<tr>
<td align="CENTER" colspan="7,">
<b>Parameter Definitions in NDPluginROI.h and EPICS Record Definitions in NDROI.template</b></td>
</tr>
<tr>
<th>
Enum name</th>
<th>
asyn interface</th>
<th>
Access</th>
<th>
Description</th>
<th>
drvUser string</th>
<th>
EPICS record name</th>
<th>
EPICS record type</th>
</tr>
<tr>
<td>
NDPluginROIHighlight</td>
<td>
asynInt32</td>
<td>
r/w</td>
<td>
Flag to indicate if the borders of ROIs should be highlighted (0=No, 1=Yes). If
set then all ROIs will be highlighted in all other ROIs where they overlap. One
common use of this is to set the first ROI to be the entire detector, and then the
location of all other ROIs will be visible when the first ROI is displayed. The
highlighting is done by replacing the border pixels with the maximum value of the
data in that ROI. Statistics are computed before the highlighting is done.</td>
<td>
HIGHLIGHT</td>
<td>
$(P)$(R)Highlight<br />
$(P)$(R)Highlight_RBV</td>
<td>
bo<br />
bi</td>
</tr>
</tbody>
</table>
<p>
NDPluginROI.h defines the following parameters that are specific to each individual
ROI in the plugin. The EPICS database NDROIN.template provide access to these parameters,
listed in the following table. The pasynUser-&gtaddr is used to control which ROI
is being addressed.
</p>
<table border="1" cellpadding="2" cellspacing="2" style="text-align: left">
<tbody>
<tr>
<td align="CENTER" colspan="7,">
<b>Parameter Definitions in NDPluginROI.h and EPICS Record Definitions in NDROIN.template</b></td>
</tr>
<tr>
<th>
Enum name</th>
<th>
asyn interface</th>
<th>
Access</th>
<th>
Description</th>
<th>
drvUser string</th>
<th>
EPICS record name</th>
<th>
EPICS record type</th>
</tr>
<tr>
<td>
NDPluginROIName</td>
<td>
asynOctet</td>
<td>
r/w</td>
<td>
Name of this ROI</td>
<td>
NAME</td>
<td>
$(P)$(R)Name<br />
$(P)$(R)Name_RBV</td>
<td>
stringout<br />
stringin</td>
</tr>
<tr>
<td>
NDPluginROIUse</td>
<td>
asynInt32</td>
<td>
r/w</td>
<td>
Flag to control whether this ROI is used (0=No, 1=Yes). Not using an ROI reduces
CPU load.</td>
<td>
USE</td>
<td>
$(P)$(R)Use<br />
$(P)$(R)Use_RBV</td>
<td>
bo<br />
bi</td>
</tr>
<tr>
<td align="CENTER" colspan="7,">
<b>ROI definition</b></td>
</tr>
<tr>
<td>
NDPluginROIDim0Bin</td>
<td>
asynInt32</td>
<td>
r/w</td>
<td>
Binning in the X direction</td>
<td>
DIM0_BIN</td>
<td>
$(P)$(R)BinX<br />
$(P)$(R)BinX_RBV</td>
<td>
longout<br />
longin</td>
</tr>
<tr>
<td>
NDPluginROIDim1Bin</td>
<td>
asynInt32</td>
<td>
r/w</td>
<td>
Binning in the Y direction</td>
<td>
DIM1_BIN</td>
<td>
$(P)$(R)BinY<br />
$(P)$(R)BinY_RBV</td>
<td>
longout<br />
longin</td>
</tr>
<tr>
<td>
NDPluginROIDim0Min</td>
<td>
asynInt32</td>
<td>
r/w</td>
<td>
First pixel in the ROI in the X direction.
<br />
0 is the first pixel in the array.</td>
<td>
DIM0_MIN</td>
<td>
$(P)$(R)MinX<br />
$(P)$(R)MinX_RBV</td>
<td>
longout<br />
longin</td>
</tr>
<tr>
<td>
NDPluginROIDim1Min</td>
<td>
asynInt32</td>
<td>
r/w</td>
<td>
First pixel in the ROI in the Y direction.<br />
0 is the first pixel in the array.</td>
<td>
DIM1_MIN</td>
<td>
$(P)$(R)MinY<br />
$(P)$(R)MinY_RBV</td>
<td>
longout<br />
longin</td>
</tr>
<tr>
<td>
NDPluginROIDim0Size</td>
<td>
asynInt32</td>
<td>
r/w</td>
<td>
Size of the ROI in the X direction</td>
<td>
DIM0_SIZE</td>
<td>
$(P)$(R)SizeX<br />
$(P)$(R)SizeX_RBV</td>
<td>
longout<br />
longin</td>
</tr>
<tr>
<td>
NDPluginROIDim0Size</td>
<td>
asynInt32</td>
<td>
r/w</td>
<td>
Size of ROI in the Y direction</td>
<td>
DIM1_SIZE</td>
<td>
$(P)$(R)SizeY<br />
$(P)$(R)SizeY_RBV</td>
<td>
longout<br />
longin</td>
</tr>
<tr>
<td>
NDPluginROIDim0Reverse</td>
<td>
asynInt32</td>
<td>
r/w</td>
<td>
Reverse ROI in the X direction<br />
(0=No, 1=Yes)</td>
<td>
DIM0_REVERSE</td>
<td>
$(P)$(R)ReverseX<br />
$(P)$(R)ReverseX_RBV</td>
<td>
longout<br />
longin</td>
</tr>
<tr>
<td>
NDPluginROIDim0Reverse</td>
<td>
asynInt32</td>
<td>
r/w</td>
<td>
Reverse ROI in the Y direction<br />
(0=No, 1=Yes)</td>
<td>
DIM1_REVERSE</td>
<td>
$(P)$(R)ReverseY<br />
$(P)$(R)ReverseY_RBV</td>
<td>
longout<br />
longin</td>
</tr>
<tr>
<td>
NDPluginROIDataType</td>
<td>
asynInt32</td>
<td>
r/w</td>
<td>
Data type of the ROI (NDDataType_t). This can be different from the data type of
the NDArray callback data.</td>
<td>
DATA_TYPE</td>
<td>
$(P)$(R)DataType<br />
$(P)$(R)DataType_RBV</td>
<td>
mbbo<br />
mbbi</td>
</tr>
<tr>
<td>
NDPluginROIBgdWidth</td>
<td>
asynInt32</td>
<td>
r/w</td>
<td>
Width of the background in pixels to use when computing net counts. 0=no background
subtraction, so the net counts is the same as the total counts.</td>
<td>
BGD_WIDTH</td>
<td>
$(P)$(R)BgdWidth<br />
$(P)$(R)BgdWidth_RBV</td>
<td>
longout<br />
longin</td>
</tr>
<tr>
<td>
ADImageSizeX</td>
<td>
asynInt32</td>
<td>
r/o</td>
<td>
Size of the ROI data in the X direction</td>
<td>
IMAGE_SIZE_X</td>
<td>
$(P)$(R)ImageSizeX_RBV</td>
<td>
longin</td>
</tr>
<tr>
<td>
ADImageSizeY</td>
<td>
asynInt32</td>
<td>
r/o</td>
<td>
Size of the ROI data in the Y direction</td>
<td>
IMAGE_SIZE_Y</td>
<td>
$(P)$(R)ImageSizeY_RBV</td>
<td>
longin</td>
</tr>
<tr>
<td align="CENTER" colspan="7,">
<b>ROI statistics</b></td>
</tr>
<tr>
<td>
NDPluginROIComputeStatistics</td>
<td>
asynInt32</td>
<td>
r/w</td>
<td>
Flag to control whether to compute statistics for this ROI (0=No, 1=Yes). Not computing
statistics reduces CPU load.</td>
<td>
COMPUTE_STATISTICS</td>
<td>
$(P)$(R)ComputeStatistics<br />
$(P)$(R)ComputeStatistics_RBV</td>
<td>
bo<br />
bi</td>
</tr>
<tr>
<td>
NDPluginROIMinValue</td>
<td>
asynFloat64</td>
<td>
r/o</td>
<td>
Minimum value in any element in the ROI</td>
<td>
MIN_VALUE</td>
<td>
$(P)$(R)MinValue_RBV</td>
<td>
ai</td>
</tr>
<tr>
<td>
NDPluginROIMaxValue</td>
<td>
asynFloat64</td>
<td>
r/o</td>
<td>
Maximum value in any element in the ROI</td>
<td>
MAX_VALUE</td>
<td>
$(P)$(R)MaxValue_RBV</td>
<td>
ai</td>
</tr>
<tr>
<td>
NDPluginROIMeanValue</td>
<td>
asynFloat64</td>
<td>
r/o</td>
<td>
Mean value in the ROI</td>
<td>
MEAN_VALUE</td>
<td>
$(P)$(R)MeanValue_RBV</td>
<td>
ai</td>
</tr>
<tr>
<td>
NDPluginROITotal</td>
<td>
asynFloat64</td>
<td>
r/o</td>
<td>
Sum (total) of all elements in the ROI</td>
<td>
TOTAL</td>
<td>
$(P)$(R)Total_RBV</td>
<td>
ai</td>
</tr>
<tr>
<td>
NDPluginROINet</td>
<td>
asynFloat64</td>
<td>
r/o</td>
<td>
Net (background subtracted) total of all elements in the ROI. The background is
calculated by determining the average counts per array element in a border around
the ROI border of width NDPluginROIBgdWidth. This average background counts per
element is then subtracted from all elements inside the ROI.</td>
<td>
NET</td>
<td>
$(P)$(R)Net_RBV</td>
<td>
ai</td>
</tr>
<tr>
<td align="CENTER" colspan="7,">
<b>ROI histogram</b></td>
</tr>
<tr>
<td>
NDPluginROIComputeHistogram</td>
<td>
asynInt32</td>
<td>
r/w</td>
<td>
Flag to control whether to compute the histogram for this ROI (0=No, 1=Yes). Not
computing the histogram reduces CPU load.</td>
<td>
COMPUTE_HISTOGRAM</td>
<td>
$(P)$(R)ComputeHistogram<br />
$(P)$(R)ComputeHistogram_RBV</td>
<td>
bo<br />
bi</td>
</tr>
<tr>
<td>
NDPluginROIHistSize</td>
<td>
asynInt32</td>
<td>
r/w</td>
<td>
Number of elements (bins) in the histogram</td>
<td>
HIST_SIZE</td>
<td>
$(P)$(R)HistSize<br />
$(P)$(R)HistSize_RBV</td>
<td>
longout<br />
longin</td>
</tr>
<tr>
<td>
NDPluginROIHistMin</td>
<td>
asynFloat64</td>
<td>
r/w</td>
<td>
Minimum value for the histogram. All values less than or equal to this will be in
the first bin of the histogram.</td>
<td>
HIST_MIN</td>
<td>
$(P)$(R)HistMin<br />
$(P)$(R)HistMin_RBV</td>
<td>
ao<br />
ai</td>
</tr>
<tr>
<td>
NDPluginROIHistMax</td>
<td>
asynFloat64</td>
<td>
r/w</td>
<td>
Maximum value for the histogram. All values greater than or equal to this will be
in the last bin of the histogram.</td>
<td>
HIST_MAX</td>
<td>
$(P)$(R)HistMax<br />
$(P)$(R)HistMax_RBV</td>
<td>
ao<br />
ai</td>
</tr>
<tr>
<td>
NDPluginROIHistEntropy</td>
<td>
asynFloat64</td>
<td>
r/o</td>
<td>
Entropy of the image. This is a measure of the sharpness of the histogram, and is
often a useful figure of merit for determining sharpness of focus, etc. It is defined
as -SUM(BIN[i]*log(BIN[i]), where the sum is over the number of bins in the histogram
and BIN[i] is the number of elements in bin i.</td>
<td>
HIST_ENTROPY</td>
<td>
$(P)$(R)HistEntropy_RBV</td>
<td>
ai</td>
</tr>
<tr>
<td>
NDPluginROIHistArray</td>
<td>
asynFloat64Array</td>
<td>
r/o</td>
<td>
Histogram array, i.e. counts in each histogram bin.</td>
<td>
HIST_ARRAY</td>
<td>
$(P)$(R)Histogram_RBV</td>
<td>
waveform</td>
</tr>
</tbody>
</table>
<h3 id="H3_1">
Configuration</h3>
<p>
The NDPluginROI plugin is created with the following command, either from C/C++
or from the EPICS IOC shell.
</p>
<pre>drvNDROIConfigure(const char *portName, int queueSize, int blockingCallbacks,
const char *NDArrayPort, int NDArrayAddr, int maxROIs,
size_t maxMemory)
</pre>
<table border="1" cellpadding="2" cellspacing="2" style="text-align: left">
<tr>
<th>
Argument</th>
<th>
Description</th>
</tr>
<tr>
<td>
<code>portName</code></td>
<td>
The name of the asyn port for this plugin.
</td>
</tr>
<tr>
<td>
<code>queueSize</code></td>
<td>
The maximum number of NDArray objects that can be queued for processing. Passed
to the NDPluginDriver base class constructor.
</td>
</tr>
<tr>
<td>
<code>blockingCallbacks</code></td>
<td>
Flag controlling whether callbacks block. Passed to the NDPluginDriver base class
constructor.
</td>
</tr>
<tr>
<td>
<code>NDArrayPort</code></td>
<td>
The name of the asyn port of the driver that will provide the NDArray data. Passed
to the NDPluginDriver base class constructor.
</td>
</tr>
<tr>
<td>
<code>NDArrayAddr</code></td>
<td>
The asyn addr of the asyn port of the driver that will provide the NDArray data.
Passed to the NDPluginDriver base class constructor.
</td>
</tr>
<tr>
<td>
<code>maxROIs</code></td>
<td>
Maximum number of ROIs that this plugin will support.
</td>
</tr>
<tr>
<td>
<code>maxMemory</code></td>
<td>
Maximum number of bytes of memory to be allocated from the NDArrayPool. Passed to
the constructor for the NDPluginDriver base class. The NDPluginROI plugin allocates
one NDArray object for each ROI, so this should be at least maxROIs times the size
of the largest NDArray to be used.</td>
</tr>
</table>
<p>
The following is the MEDM screen that provides access to the parameters in NDPluginDriver.h
and NDPluginROI.h through records in NDPluginBase.template and NDROI.template. This
is the MEDM screen that is used to control the behavior of the ROI plugin, but not
the individual ROIs.
</p>
<center>
<img alt="NDROI.png" src="NDROI.png" />
</center>
<p>
The following is the MEDM screen that provides access to the parameters for in NDPluginROI.h
through records in NDROIN.template. This is the MEDM screen that is used to control
the behavior of a specific ROI.
<br />
</p>
<center>
<img alt="NDROIN.png" src="NDROIN.png" />
</center>
<p>
The following is another MEDM screen that provides access to the parameters for
in NDPluginROI.h through records in NDROIN.template. This is the MEDM screen that
is used to control the most commonly used properties of 8 ROIs.
</p>
<center>
<img alt="NDROI8.png" src="NDROI8.png" />
</center>
<p>
The following is an IDL epics_ad_display screen illustrating the highlighting of
ROIs. In this example the ROIs defined are those in the 8 ROI display above. The
NDPluginStdArrays driver has been configured to be receiving its NDArray callbacks
from the first ROI (which is defined to be the entire detector array), and the NDPluginROIHighlight
flag is set to Yes.
</p>
<center>
<img alt="ROI_outlines.png" src="ROI_outlines.png" /></center>
</body>
</html>