Python Binding (PyCPL)

The PyCPL is a library that creates the Python bindings for C++ library CppCPL. The bindings are created using pybind11 tool. For more information about pybind11, see here.

The resulting Python package is PyCPL and contains the binding of the main objects defined in the CppCPL library. Additional binding can be added on request based on the needs of instruments.

The binding of CPL based recipes and objects enables the integration of CPL with the Python ecosystem that includes many libraries, frameworks and tools. This may complement very well the image processing activities specially in the area of scientific computing or plotting libraries like matplotlib.

alternate text

Python also provides interactivity, for instance by using Jupyter console where users can quickly verify visually the outcome of the image processing algorithms.

alternate text

Error Handling

The errors produced in CPL or CLIPM and captured in exceptions by library CppCPL. These errors are reported in Python as RuntimeError. The exception message will contain the location of the CPL or CLIPM error when this information is available, see the example below.

import pycpl

""" Creating empty image object """
image = pycpl.image()

# This should generate a RuntimeError because image has not been allocated yet.
stat = pycpl.image_stat(image)
stat.Mean()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RuntimeError: Error executing statistics - cplerr: cpl_image_stats.c:232 errmsg:Null input data

PyCPL Constants

C/C++ Constant

Binding

CLIPM_ALIGN_SHIFT

pycpl.CLIPM_ALIGN_SHIFT

CLIPM_ALIGN_SCALE

pycpl.CLIPM_ALIGN_SCALE

CLIPM_ALIGN_ROTATE

pycpl.CLIPM_ALIGN_ROTATE

CLIPM_ALIGN_FREE

pycpl.CLIPM_ALIGN_FREE

CLIPM_ALIGN_ROBUST

pycpl.CLIPM_ALIGN_ROBUST

PyCPL Enumerations

C/C++ Class Name

Binding

cpl_type

pycpl.cpl_type

Supported values:

  • CPL_TYPE_FLOAT

  • CPL_TYPE_DOUBLE

  • CPL_TYPE_INT

  • CPL_TYPE_SHORT

cpl_io_type

pycpl.cpl_io_type

Supported values:

  • CPL_IO_CREATE

  • CPL_IO_EXTEND

  • CPL_IO_APPEND

  • CPL_IO_DEFAULT

PyCPL Classes

The pycpl module provides the binding of the following classes:

C++ Class Name

Binding

odp::Image

pycpl.image

odp::Matrix

pycpl.matrix

odp::Array

pycpl.array

odp::Mask

pycpl.mask

odp::ImageStatistics

pycpl.image_stat

odp::Recipe

pycpl.recipe

odp::CenterGauss

pycpl.center_gauss

odp::Iqe

pycpl.iqe

odp::SlitPos

pycpl.slitpos

odp::ImageCube

pycpl.imagecube

Buffer Protocol

This is a cool feature of pybind11 that enables to expose the data of a C++ structure into a python. This allows to have an easy exchange of data between numpy arrays and CPL objects.

""" creating a numpy array from a cpl image """
image = pycpl.image()
image.Load(str(image_path), 0,0, pycpl.cpl_type.CPL_TYPE_FLOAT)
image_data = np.array(image, copy=False)

""" Creating a new matrix from a numpy vector """
ref = np.array([[366,430, 67, 283, 210, 207,354,348,360,425],
                   [91, 323, 275,275, 257, 311,341,452,216,424]]).astype(np.float64)
matrix = pycpl.matrix(ref)

Testing

The PyCPL library provides a set of unit tests implemented with Python unit tests. Tests can be executed as follow:

$ cd ifw-hl/odp/pycpl
$ waf test --alltests

Examples

Fake Star

import pycpl

""" Creates a dummy gaussian star """
NORM_STAR = 1000000.0
percent = 1
image = pycpl.image(512,512, pycpl.cpl_type.CPL_TYPE_FLOAT)
image.FillNoise(100,200)
star = pycpl.image(512,512, pycpl.cpl_type.CPL_TYPE_FLOAT)
norm = NORM_STAR * (percent * percent);
sigma = 512 * (percent / 100.0);
half = 512 / 2.0;

star.FillGaussian(half,half, norm, sigma, sigma)
image += star

Image Centroiding

import pycpl

""" Creates a dummy gaussian star """
NORM_STAR = 1000000.0
percent = 1
image = pycpl.image(512,512, pycpl.cpl_type.CPL_TYPE_FLOAT)
image.FillNoise(100,200)
star = pycpl.image(512,512, pycpl.cpl_type.CPL_TYPE_FLOAT)
norm = NORM_STAR * (percent * percent)
sigma = 512 * (percent / 100.0)
half = 512 / 2.0
star.FillGaussian(half,half, norm, sigma, sigma)
""" added dummy star to the background image """
image += star
center_gauss = pycpl.center_gauss();
recipe = pycpl.recipe()
""" computes center gauss """
recipe.CenterGauss(image, 1, 1, 512, 512, center_gauss, 1)
print(center_gauss.Center())

Instrument Extensions

Instruments can extend the ODP by creating new CPL based recipes or reusing existing ones from the Instrument DRS. Once these routines exists, Python bindings can be defined following the same mechanism used by ODP. There is already a template module implemented for the VLT (xxclipm) that was intended to implement instrument specific image processing algorithms. The following figure shows the possible phases to extend the ODP component.

alternate text