C-Munipack library (API)¶
The C-Munipack library provides an extensive set of functions with a simple application programming interface (API) for reduction of images carried out by a CCD or DSLR cameras, aimed at observation of variable stars.
The library has been developed as a part of the C-Munipack software. See the project home page for more information about the project and other interfaces.
Sample program¶
The following text describes implementation of a very simple application, which performs photometry of a single CCD frame using functions from the C-Munipack library. It is supposed, that you have got the C-Munipack library and its headers installed.
The source code
Let’s start - make a new project in your favorite IDE and make a big mug of coffee for yourself. First of all, we need to include some standard headers:
#include <stdio>
#include <stdlib>
The declarations from the C-Munipack library are sorted into several header files, but all we need to include just one header file, which in turn includes all other public header files:
#include <cmunipack>
We will use command-line arguments to specify name of an input CCD frame and name
of an output file. Because of this, our declaration of the main
function looks
like this:
int main(int argc, char *argv[])
{
CmpackPhot *lc;
The lc
variable is called a context. The context stores the configuration parameters
and keeps internal data used during photometry process. It allows a caller
to process multiple frames in different threads without interference between each
other. The context is a trick that makes all functions from the library re-entrant;
you can safely call functions from different threads without any synchronization
or locking features provided that those threads uses different contexts. There are two
exceptions to that rule. The initialization routine must be called before any other
call from the C-Munipack library and the clean-up routine must be called as the last
call.
At the beginning of our sample program, we call the initialization routine:
/* Library initialization */
cmpack_init();
The next piece of code checks the command line parameters. This demo expects two parameters, the first one is a name of an input file with a source frame, the second one is a name of an output file:
/* Command line checking */
if (argc!=3) {
fprintf(stderr, "Syntax: test <ccd frame> <photometry file>");
return 1;
}
Before we do any real work, we need to create a new photometry context. This is
a opaque data structure that keeps the configuration parameters required to perform
a photometry on a frame. The context is created by calling the cmpack_phot_init
routine. This function creates a new photometry context, sets all parameters to
default values, sets the reference counter to one. A pointer to the context is
returned. The caller becomes an owner of the context and when we don’t need it
anymore, we should release the reference by calling the cmpack_phot_free
function which decrements the reference counter and destroys the context.
Let’s set up at least two most important configuration parameters – the filter half-width and the detection threshold. We let all other parameter to the default values.
/* Create context */
lc = cmpack_phot_init();
cmpack_phot_set_fwhm(lc, 2.5);
cmpack_phot_set_thresh(lc, 4.0);
Now everything is ready to do a real work. The photometry is executed by calling
the cmpack_phot
, which takes the context as its first parameter, the names
of the input and output files as the second and third parameter. The fourth parameter
is NULL.
cmpack_phot(lc, argv[1], argv[2], NULL);
Before we finish the program, we should destroy our reference to the photometry context and since this is the last reference, the context and all data that are stored within the context is destroyed as well.
/* Destroy context */
cmpack_unref(lc);
Before terminating the program, you should call the library clean-up function.
/* Library cleanup */
cmpack_cleanup();
return 0;
}
Compiling and linking
The C-Munipack library comes with a configuration file for pkg-config. If your system supports pkg-config, this is the easiest way how to pass all options that are necessary to compile and link an application against the C-Munipack library.
Otherwise, you have to set up all the options on the command line. Here is an example that builds our source code on Debian 4 using the gcc compiler.
gcc main.c -I -lcmunipack-1.2 -lexpat -lcfitsio -lm
Memory allocation¶
In the C-Munipack library, all dynamic memory allocation are performed by means of a group of routines which correspond to the C standard library memory handling function.
When you build your own application using the C-Munipack library, please
check the API Reference to make sure when the caller is responsible to free
the allocated memory blocks. To do so, you have to call the cmpack_free
routine, otherwise, the behavior of the program is unpredictable.
Detecting memory leaks
When the C-Munipack library is compiled with _DEBUG
symbol defined, the
memory handling function keep track of blocks allocated on the heap. When the
application calls the cmpack_clean
routine, the list of blocks that
are still allocated is printed to the standard output. This feature is designed
to detect memory blocks that were allocated but not freed.
Detecting out-of-block modifications
When the C-Munipack library is compiled with _DEBUG
symbol defined, the
memory handling function check for out-of-block modifications. When a memory
block is requested, the function allocates 8 bytes more and writes a 4 bytes
of constant data at the beginning of the block and 4 bytes of constant data
at the end of the block. The function returns a pointer of a memory after
the first four bytes, so from caller’s perspective, everything is transparent.
When a memory block is freed or reallocated, the program checks if the leading and trailing data were not modified. In such case, an assertion is issued to stop execution of the program.
Objects and reference counting¶
Most of the structures that are published by the C-Munipack library are opaque. They can be referenced by pointers, but their internal structure and content can be accessed only by calling appropriate functions. This slows down an execution of the resulting program, but provides a compatibility of binary code that were dynamically compiled against the library.
To help binding into other languages, the structures contain reference counters reference counting that can be incremented and decremented and when the last reference to a structure is lost, the structure is freed automatically. For each structure that support reference counting, there are two functions:
A function that has the reference
suffix increments the reference counter
of an object given as an argument. Its return value is a copy of the argument.
A function that has the free
suffix decrements the reference counter of an
object given as an argument and when the reference counter reaches zero it
destroys the object and frees allocated memory.
Initialization and clean-up¶
The library initialization routine cmpack_init
must be called prior to
any other call to the library. It initializes the static data and when the library
was compiled with _DEBUG
symbol defined, the data required by the memory leak detection
is also initialized.
The library initialization routine cmpack_cleanup
can be called before
the program terminates, though it is not necessary, if you don’t care about memory
leaks, which is a bad idea in general. The clean-up code releases any memory allocated
in static data. When the library was compiled with _DEBUG
symbol defined, it prints
out to the standard output a report about any memory blocks that were allocated but
not freed. Please note that only memory blocks that were handled by library’s
allocation/free routines are threated by the leak detector.
Thread safety¶
Functions from the C-Munipack library are re-entrant. It means, that you can call them from different threads without any external synchronization and locking if they are called on different data. The data that are used inside a function call are stored on a stack, the data that are passed between function calls are stored in an memory allocated on a heap, called a context.
On the other hand, functions from the library are not thread-safe. When you call a function on the same context (data) from two threads at the same time, the behavior of the program and the results are unpredictable.
For example, it is safe to perform a photometry on two frames in two threads simultaneously, but you have to make two photometry contexts (instances of CmpackPhot type).
There are two exceptions to this rule, the library initialization routine cmpack_init
and the clean-up routine cmpack_cleanup
. These routines are not re-entrant
nor thread-safe.