This Julia package implements an
interface to some
Andor cameras via the Andor Software
Development Kit (SDK). As of version 3.13 of the SDK, the Neo, Zyla,
Apogee and iStar-SCMOS Andor cameras should be supported. The
AndorCameras
package has been tested on under Linux on the Zyla (USB-3
connected) camera, I am interested in feedback about other models.
This document describes:
-
the standard interface which implements all the methods specified by the
ScientificCameras
interface; -
the advanced interface which provides access to all Andor cameras features and commands;
-
the installation of the
AndorCameras
package.
To use the AndorCameras
package, just write:
using AndorCameras
which provides all the methods specified by the
ScientificCameras
interface.
This interface is fully documented
here and summarized below.
You may also want to:
using AndorCameras.Features
to use the advanced interface.
To open an Andor camera:
cam = open(AndorCameras.Camera, dev)
with dev
the device number (0
is the first device). To figure out how many
Andor devices are available:
AndorCameras.getnumberofdevices()
To disconnect a camera from the hardware:
close(cam)
Note that this is automatically done when the camera instance is claimed by the garbage collector.
A region of interest (ROI) may be selected by:
setroi!(cam, [[xsub, ysub,] xoff, yoff,] width, height)
where xsub
and ysub
are the dimensions of the macro-pixels (in pixels and
both assumed to be 1
if not specified), xoff
and yoff
are the offsets of
the ROI relative to the sensor (in pixels and both assumed to be 0
if not
specified), width
and height
are the dimensions of the ROI (in
macro-pixels).
Macro-pixels are blocks of xsub
by ysub
pixels when rebinning the pixels
of the sensor.
In the Andor SDK documentation, the rebinning features are
AOIHBin
and AOIVBin
, the offsets (plus one) are AOILeft
and AOITop
and
the dimensions of the ROI are AOIWidth
and AOIHeight
.
To query the current ROI call:
roi = getroi(cam)
and to reset the ROI to use the full sensor with no rebinning, call:
resetroi!(cam)
The full dimensions (in pixels) of the sensor are retrieved by:
fullwidth = getfullwidth(cam)
fullheight = getfullheight(cam)
or by:
fullwidth, fullheight = getfullsize(cam)
The setspeed!
method let you choose the frame rate (fps
in Hz) and the
exposure time (exp
in seconds) for the captured images:
setspeed!(cam, fps, exp)
To retrieve the actual values of these parameters:
fps, exp = getspeed(cam)
To acquire a single image (with the current settings):
img = read(cam)
which yield an image in the form of a 2D Julia array. To acquire a sequence of
n
images:
imgs = read(cam, n)
which yields a vector of images: imgs[1]
, imgs[2]
, ..., imgs[n]
. The
returned images are Julia 2D arrays of same dimensions as the selected region
of interest (ROI) and whose element type is derived from the pixel format of
the camera as given by:
getcapturebitstype(cam)
You may specify another element type, say T
, for the acquired images:
img = read(cam, T)
or
imgs = read(cam, T, n)
but there may be restrictions.
The read
methods have the following keywords:
-
Use keyword
skip
to specify a number of images to skip. -
Use keyword
timeout
to specify the maximum amount of time (in seconds) to wait for acquisition to complete. If acquisition takes longer than this time, aScientificCameras.TimeoutError
is thrown unless keywordtruncate
istrue
(see below). The default timeout is computed from the acquisition rate and the total number of images. -
When reading a sequence of images, keyword
truncate
may be settrue
to print a warning and return a truncated sequence instead of throwing an exception in case of timeout. -
Keyword
quiet
can be settrue
to suppress the printing of warning messages (see above).
Continuous acquisition (and processing) of images is typically done by:
start(cam, nbufs) # start continuous acquisition with `nbufs` cyclic buffers
while ! finished()
img, ticks = wait(cam, sec) # wait for next image, not longer than `sec` seconds
... # process the image
release(cam) # release the processed image
end
stop(cam) # stop acquisition
where it is assumed that finished()
returns true
when to stop and false
otherwise. Above, img
is a 2D Julia array with the last captured image and
ticks
is the corresponding timestamp in seconds. Releasing the captured
image with release(cam)
when it has been processed is intended to recycle the
image buffer for another acquisition. When the returned image is independent
from the corresponding capture buffer, release(cam)
does nothing. It is
nevertheless good practice to call this method when the captured image is no
longer needed because the code is more likely to work with no changes with
another camera.
You may specify another element type, say T
, for the captured images:
start(cam, T, nbufs)
This section describes advanced use of the interface to Andor cameras provided
by the AndorCameras
module. This may be useful to perform specific
configuration or actions not covered by the general interface. Dealing with
all the features of Andor cameras is greatly simplified by the
provided Julia interface.
The constants defined in atcore.h
are available in Julia, for instance
AndorCameras.AT_SUCCESS
. All constants are prefixed with AT_
and may be
imported by:
using AndorCameras.Constants
so that you just have to write AT_SUCCESS
instead of
AndorCameras.AT_SUCCESS
.
Andor cameras have features whose value can be retrieved or set using the array index syntax:
cam[key]
cam[key] = val
where cam
is the camera instance, key
is the considered feature and val
its value. Here key
can be something like AndorCameras.SensorWidth
or
just SensorWidth
if you have imported all defined features by:
using AndorCameras.Features
For instance:
using AndorCameras.Features
sensorwidth = cam[SensorWidth]
sensorheight = cam[SensorHeight]
yields the full dimensions of the sensor of camera cam
.
The names of the constants defining the existing features closely follow the Andor Software Development Kit documentation. This documentation should be consulted to figure out the supported features and their meaning. If specific features are missing, it is easy to define new ones.
Julia AndorCameras
module takes care of the different kind of features
depending on the type of their values: integer, floating-point, string,
boolean or enumerated. Enumerated features can take integer or string
values, they are described below. There are also
command features which have no value but are used to send
commands to the camera.
To query whether a specific feature is implemented, or whether it is readable, writable or read-only, do one of:
isimplemented(cam, key)
isreadable(cam, key)
iswritable(cam, key)
isreadonly(cam, key)
Integer and floating-point features may have restrictions on the allowed range of values. The minimum and maximum allowed values can be retrieved by:
minimum(cam, key)
maximum(cam, key)
A string representation of feature key
is obtained by:
repr(key)
An enumerated feature can only have a limited number of predefined values.
These values can be set by an integer index or by their name. Assuming
cam
is the camera instance:
cam[key] = idx
or:
cam[key] = str
with key
the enumerated feature, e.g. PixelEncoding
, idx
and str
the index and the name of the chosen value. The following expression:
cam[key]
yields the current index of the enumerated feature. Note that enumeration
indices start at 1
(as do indices in Julia). The minimum and maximum
indices are respectively given by:
minimum(cam, key)
maximum(cam, key)
the former always yields 1
for an enumerated feature.
To retrieve the string representation of the value an enumerated feature, do one of:
repr(cam, key)
repr(cam, key, idx)
which respectively yield the string representation of the current value of the enumerated feature and of the value at a given index.
To query whether a given index is available or implemented for an enumerated feature, call respectively:
isavailable(cam, key, idx)
isimplemented(cam, key, idx)
Command features (e.g. AcquisitionStart
) are used to identify a specific
command to send to the camera. These features have no values. To send the
commmand cmd
to the camera cam
, you just have to:
send(cam, cmd)
If specific features are not predefined by the AndorCameras
package, you may
define them at run-time provided their name and type is known. For instance:
boolkey = AndorCameras.BooleanFeature("SomeBooleanFeature")
intkey = AndorCameras.IntegerFeature("SomeIntegerFeature")
enumkey = AndorCameras.EnumeratedFeature("SomeEnumeratedFeature")
fltkey = AndorCameras.FloatingPointFeature("SomeFloatingPointFeature")
strkey = AndorCameras.StringFeature("SomeStringFeature")
would define 5 features of 5 different types given their names. These features can be used as any others. For instance:
cam[boolkey] = false
If performance and readability are not an issue, a feature may be defined on the fly. For instance:
cam[AndorCameras.BooleanFeature("SomeBooleanFeature")] = false
The easiest way to install AndorCameras
is via the Julia registry
EmmtRegistry
:
using Pkg
pkg"registry add https://github.com/emmt/EmmtRegistry"
pkg"add AndorCameras"
pkg"build AndorCameras"
The build process assumes that Andor Software Development Kit
(SDK) has
been installed in the usual directory /usr/local/andor
for Linux or
C:/Program Files/AndorSDK3
for Windows (read the end of this section if you
have installed the SDK elsewhere).
If Andor SDK is not installed in the usual directory, you can define the
AT_DIR
, AT_INCDIR
and/or AT_LIBDIR
environment variables before building
AndorCameras
. These variables are used as follows:
-
AT_DIR
is the directory where the Andor SDK has been installed. If this environment variable is not defined, it is assumed to be/usr/local/andor
for Linux orC:/Program Files/AndorSDK3
for Windows. -
AT_INCDIR
is the directory containing the Andor SDK header fileatcore.h
. If this environment variable is not defined, the header file is searched in directories$AT_DIR/include
and$AT_DIR
(in that order). -
AT_LIBDIR
is the directory containing the Andor SDK library (libatcore.so
on Linux,atcore.dll
on Windows). If this environment variable is not defined, the library is searched in directories$AT_DIR/lib
and$AT_DIR
(in that order).
For instance id Andor SDK has been installed in /opt/andor
, you can define
the AT_DIR
environment variable in Julia by:
ENV["AT_DIR"] = "/opt/andor"
before building AndorCamera
:
using Pkg
pkg"build AndorCameras"