summaryrefslogtreecommitdiffstats
path: root/docs/api.rst
diff options
context:
space:
mode:
authorMatthias Vogelgesang <matthias.vogelgesang@kit.edu>2014-07-11 11:06:28 +0200
committerMatthias Vogelgesang <matthias.vogelgesang@kit.edu>2014-07-11 11:06:28 +0200
commitf82414cc075c224cff42ebf5ade7c77a16ddb9cd (patch)
treedb87e9284be4d1ee8a39300c2647e30e609c3a53 /docs/api.rst
parent97c66c2aee58370044b6444251266d7177caab9e (diff)
downloadlibuca-f82414cc075c224cff42ebf5ade7c77a16ddb9cd.tar.gz
libuca-f82414cc075c224cff42ebf5ade7c77a16ddb9cd.tar.bz2
libuca-f82414cc075c224cff42ebf5ade7c77a16ddb9cd.tar.xz
libuca-f82414cc075c224cff42ebf5ade7c77a16ddb9cd.zip
Split up the manual
Diffstat (limited to 'docs/api.rst')
-rw-r--r--docs/api.rst211
1 files changed, 211 insertions, 0 deletions
diff --git a/docs/api.rst b/docs/api.rst
new file mode 100644
index 0000000..8bb26b9
--- /dev/null
+++ b/docs/api.rst
@@ -0,0 +1,211 @@
+Application Programming Interface
+=================================
+
+In the introduction we had a quick glance over the basic API used to communicate
+with a camera. Now we will go into more detail and explain required background
+to understand the execution model.
+
+
+Instantiating cameras
+---------------------
+
+We have already seen how to instantiate a camera object from a name. If
+you have more than one camera connected to a machine, you will most
+likely want the user decide which to use. To do so, you can enumerate
+all camera strings with ``uca_plugin_manager_get_available_cameras``::
+
+ GList *types;
+
+ types = uca_camera_get_available_cameras (manager);
+
+ for (GList *it = g_list_first; it != NULL; it = g_list_next (it))
+ g_print ("%s\n", (gchar *) it->data);
+
+ /* free the strings and the list */
+ g_list_foreach (types, (GFunc) g_free, NULL);
+ g_list_free (types);
+
+
+Errors
+------
+
+All public API functions take a location of a pointer to a ``GError``
+structure as a last argument. You can pass in a ``NULL`` value, in which
+case you cannot be notified about exceptional behavior. On the other
+hand, if you pass in a pointer to a ``GError``, it must be initialized
+with ``NULL`` so that you do not accidentally overwrite and miss an
+error occurred earlier.
+
+Read more about ``GError``\ s in the official GLib
+`documentation <http://developer.gnome.org/glib/stable/glib-Error-Reporting.html>`__.
+
+
+Recording
+---------
+
+Recording frames is independent of actually grabbing them and is started
+with ``uca_camera_start_recording``. You should always stop the
+recording with ``ufo_camera_stop_recording`` when you finished. When the
+recording has started, you can grab frames synchronously as described
+earlier. In this mode, a block to ``uca_camera_grab`` blocks until a
+frame is read from the camera. Grabbing might block indefinitely, when
+the camera is not functioning correctly or it is not triggered
+automatically.
+
+
+Triggering
+----------
+
+``libuca`` supports three trigger modes through the "trigger-mode"
+property:
+
+1. ``UCA_CAMERA_TRIGGER_AUTO``: Exposure is triggered by the camera
+ itself.
+2. ``UCA_CAMERA_TRIGGER_INTERNAL``: Exposure is triggered via software.
+3. ``UCA_CAMERA_TRIGGER_EXTERNAL``: Exposure is triggered by an external
+ hardware mechanism.
+
+With ``UCA_CAMERA_TRIGGER_INTERNAL`` you have to trigger with
+``uca_camera_trigger``::
+
+ /* thread A */
+ g_object_set (G_OBJECT (camera),
+ "trigger-mode", UCA_CAMERA_TRIGGER_INTERNAL,
+ NULL);
+
+ uca_camera_start_recording (camera, NULL);
+ uca_camera_grab (camera, &buffer, NULL);
+ uca_camera_stop_recording (camera, NULL);
+
+ /* thread B */
+ uca_camera_trigger (camera, NULL);
+
+
+Grabbing frames asynchronously
+------------------------------
+
+In some applications, it might make sense to setup asynchronous frame
+acquisition, for which you will not be blocked by a call to ``libuca``::
+
+ static void
+ callback (gpointer buffer, gpointer user_data)
+ {
+ /*
+ * Do something useful with the buffer and the string we have got.
+ */
+ }
+
+ static void
+ setup_async (UcaCamera *camera)
+ {
+ gchar *s = g_strdup ("lorem ipsum");
+
+ g_object_set (G_OBJECT (camera),
+ "transfer-asynchronously", TRUE,
+ NULL);
+
+ uca_camera_set_grab_func (camera, callback, s);
+ uca_camera_start_recording (camera, NULL);
+
+ /*
+ * We will return here and `callback` will be called for each newo
+ * new frame.
+ */
+ }
+
+
+Bindings
+--------
+
+.. highlight:: python
+
+Since version 1.1, libuca generates GObject introspection meta data if
+``g-ir-scanner`` and ``g-ir-compiler`` can be found. When the XML
+description ``Uca-x.y.gir`` and the typelib ``Uca-x.y.typelib`` are
+installed, GI-aware languages can access libuca and create and modify
+cameras, for example in Python::
+
+ from gi.repository import Uca
+
+ pm = Uca.PluginManager()
+
+ # List all cameras
+ print(pm.get_available_cameras())
+
+ # Load a camera
+ cam = pm.get_camerav('pco', [])
+
+ # You can read and write properties in two ways
+ cam.set_properties(exposure_time=0.05)
+ cam.props.roi_width = 1024
+
+Note, that the naming of classes and properties depends on the GI
+implementation of the target language. For example with Python, the
+namespace prefix ``uca_`` becomes the module name ``Uca`` and dashes
+separating property names become underscores.
+
+Integration with Numpy is relatively straightforward. The most important
+thing is to get the data pointer from a Numpy array to pass it to
+``uca_camera_grab``::
+
+ import numpy as np
+
+ def create_array_from(camera):
+ """Create a suitably sized Numpy array and return it together with the
+ arrays data pointer"""
+ bits = camera.props.sensor_bitdepth
+ dtype = np.uint16 if bits > 8 else np.uint8
+ a = np.zeros((cam.props.roi_height, cam.props.roi_width), dtype=dtype)
+ return a, a.__array_interface__['data'][0]
+
+ # Suppose 'camera' is a already available, you would get the camera data like
+ # this:
+ a, buf = create_array_from(camera)
+ camera.start_recording()
+ camera.grab(buf)
+
+ # Now data is in 'a' and we can use Numpy functions on it
+ print(np.mean(a))
+
+ camera.stop_recording()
+
+
+Integrating new cameras
+=======================
+
+A new camera is integrated by
+`sub-classing <http://developer.gnome.org/gobject/stable/howto-gobject.html>`__
+``UcaCamera`` and implement all virtual methods. The simplest way is to
+take the ``mock`` camera and rename all occurences. Note, that if you
+class is going to be called ``FooBar``, the upper case variant is
+``FOO_BAR`` and the lower case variant is ``foo_bar``.
+
+In order to fully implement a camera, you need to override at least the
+following virtual methods:
+
+- ``start_recording``: Take suitable actions so that a subsequent call
+ to ``grab`` delivers an image or blocks until one is exposed.
+- ``stop_recording``: Stop recording so that subsequent calls to
+ ``grab`` fail.
+- ``grab``: Return an image from the camera or block until one is
+ ready.
+
+
+Asynchronous operation
+----------------------
+
+When the camera supports asynchronous acquisition and announces it with
+a true boolean value for ``"transfer-asynchronously"``, a mechanism must
+be setup up during ``start_recording`` so that for each new frame the
+grab func callback is called.
+
+
+Cameras with internal memory
+----------------------------
+
+Cameras such as the pco.dimax record into their own on-board memory
+rather than streaming directly to the host PC. In this case, both
+``start_recording`` and ``stop_recording`` initiate and end acquisition
+to the on-board memory. To initiate a data transfer, the host calls
+``start_readout`` which must be suitably implemented. The actual data
+transfer happens either with ``grab`` or asynchronously.