Reglib: the Regions Programming Interface

Summary

This document contains a description of the programming interface for spatial region filtering of FITS images.

Introduction to the Regions Programming Interface

To create a regions application, you need to include the regions.h definitions file in your code:
  #include <regions.h>
You then call regions subroutines and functions to filter data using DS9/JS9/Funtools region specifiers. The OpenRegions() function is used to open a regions specification for filtering:
  Regions reg = OpenRegions(char *cards, char *region_string, char *mode);
where cards is a string containing the FITS cards for the current image, and region_string is the region specifier. The mode string is reserved for future use and can be set to NULL;

Once a region specification has been opened, you can call FilterRegions() to return an array of region mask segments for the specified image section:

  got =  FilterRegions(Regions reg, int x0, int x1, int y0, int y1, int block, RegionsMask *mask, int *nreg);

When all processing is done, can call CloseRegions() to release all region resources:

  CloseRegions(reg);

Your program must be linked against the standard cfitsio FITS-access library, the libregions.a library, and the math library. The following libraries also might be required on your system:

  -ldl  # for linking dynamic objects

Thus, on a Linux system using gcc, you would generally use the following link line:

  gcc -o foo foo.c -lregions -L[path_to_cfitsio] -lcfitsio -ldl -lm
Note that after configure has built a Makefile on your platform, the required "extra" libraries (aside from -lm, which always is required) are specified in that file's EXTRA_LIBS variable;
  egrep ^EXTRA_LIBS Makefile
  EXTRA_LIBS =	 -L/Users/foo/cfitsio -lcfitsio -ldl -lm
So in the above case, the link line would be:
  gcc -o foo foo.c -lregions -L/Users/foo/cfitsio -lcfitsio -ldl -lm
This information is contained in the regions.pc file.

OpenRegions - open a regions filter

  #include <regions.h>

  Regions OpenRegions(char *cards, char *regions, char *mode);

The OpenRegions() routine opens a spatial region specifier for filtering. The first argument is a string containing the FITS header cards. These cards are used to gather WCS and other information about the file whose image data will be filtered. If you are using the cfitsio library, the card string can be retrieved with the fits_convert_hdr2str() call. A NULL can safely be passed if there is no WCS information associated with the data.

The second argument is the spatial region specifier. This can be one or more regions:

  circle(512,512,10); -box(400,400,20,40,15)

  fk5;circle(345.2926,58.879817,151.99998");circle(344.86479,59.014261,223.99998")
or it can be an include file containing regions:
  @ds9.reg

The third argument is a string containing mode specifiers. At the moment, mode is only used for debugging and should be set to NULL.

The OpenRegions() call analyzes the input spatial region specification and generates a spatial region filter that is then compiled on the fly. Ordinarily, the filter is compiled and linked to produce a slave program, which is then started up as slave process of your application. The FilterRegions() call sends section information to the slave program, which returns a region mask, i.e. an array of valid region segments to be used by your application.

Although not often used, it is worth noting that the REGIONS_PTYPE environment variable offer options on how to build the region filter:

process or p (the default)
The filter is compiled and linked against the regions library (which must therefore be accessible in the original install directory) to produce a slave program.
dynamic or d (not much faster than process)
The filter is compiled and linked against the regions library to produce a dynamic shared object, which is loaded into the regions program and executed as a subroutine. Extensive testing has shown that, contrary to expectations, this method is no faster than using a slave process.
contained or c (fool-proof but slower to compile)
The filter and all supporting region code is compiled and linked without reference to an external regions library to produce a slave program. This method takes slightly more time to compile the full region filtering code. It is used by programs such as DS9, which do not have access to the regions library.

By default, process is generally used for all compilers. However, the filter-building algorithm will check for required external files and will use contained if any are missing.

The returned Regions handle is an opaque handle that will be used in subsequent region library calls.

FilterRegions - return an image mask of valid region segments

  #include <regions.h>

  int FilterRegions(Regions reg, int x0, int x1, int y0, int y1, int block, RegionsMask *mask, int *nreg);

The FilterRegions() routine sends an image section to the filter slave process, and retrieves a region mask, i.e. an array of valid region segments that can used by your application to filter the image data.

The first argument is the Region handle returned by OpenRegions(). The next 5 arguments specify the image section in which to calculate the mask. The section value should match the section of the image contained in your image data array, at the specified block factor. However, in keeping with FITS conventions, the section limits are one-indexed, so that the whole image at block 1 is specified by: 1, xdim, 1, ydim, 1.

The slave process (or dynamic object call) returns the region mask in the seventh (mask) argument. The mask an array of RegionMask structs, each element of which has the form:

  typedef struct regmasks {
    int region;
    int y;
    int xstart, xstop;
  } *RegionsMask, RegionsMaskRec;
The y, xstart, and xstop elements are one-indexed, and xstop is the last valid element (not the first invalid element). This mask should be freed when no longer needed.

If not specified as NULL, the eighth argument (nreg) returns the number of include regions in the mask. This is useful for allocating arrays of the correct size when processing regions individually.

Finally, the FilterRegions() function returns the number of segments in the mask, so that they can be accessed in this way:

  int i, nmask, nreg;
  RegionsMask mask;
  nmask = FilterRegions(reg, x0, x1, y0, y1, block, &mask, &nreg);
  for(i=0; i<nmask; i++){
    fprintf(stdout, "#%d: region=%d y=%d, x=%d,%d\n", 
    i, mask[i].region, mask[i].y, mask[i].xstart, mask[i].xstop);
  }

As a more complete example, consider the case where dbuf contains the image data for the specified section. After calling FilterRegions(), area and cts arrays can be allocated based on the number of include regions. The counts and area in each region then can be calculated in this way:

  double *cnts;
  int i, j, nmask, nreg, *area;
  nmask = FilterRegions(reg, x0, x1, y0, y1, block, &mask, &nreg);
  cnts = (double *)calloc(nreg, sizeof(double));
  area = (int *)calloc(nreg, sizeof(int));
  for(i=0; i<nmask; i++){
    area[masks[i].region-1] += masks[i].xstop - masks[i].xstart + 1;
    for(j=masks[i].xstart-1; j<=masks[i].xstop-1; j++){
      cnts[masks[i].region-1] += dbuf[j];
    }
  }

CloseRegions - release region filter resources

  #include <regions.h>

  int CloseRegions(Regions reg);

The FilterRegions() routine releases all resources associated with this spatial region filter. If the processing ptype is process or contained, (i.e. a slave process is used to perform the filtering), it will also close the slave process. In this case, the returned status will be the completion status of the slave processes. If the processing ptype is dynamic, the dynamic object is released and the return status is from the dlclose() call.


Other pages of interest:
Last updated: August 9, 2015