Libchil: A C library for reading and processing Chilbolton-format radar data

This library provides functions for the reading and processing of Chilbolton-format radar data. You can either use the low-level functions (as used by makesum and chilinfo) or the high-level functions (as used by chilplot, chil2a, chil2nc and loadchil. The high-level interface interprets the command-line arguments and processes the data accordingly. The high-level functions are all provided in the source file libchil/chil_api.c. Suppose you wish to write a program to convert Chilbolton-format radar data into another format, then the general outline of your program (which is shared by src/chil2a.c, src/chil2nc.c and plot/chilplot.cpp) would be something like:


#include <chil.h>

int
main(int argc, char **argv)
{
  /* The `ChilboltonData' structure contains the state information 
   * as well as the radar data itself. */

  ChilboltonData data;
  int status;

  /* If we are running in an embedded environment (e.g. a mex file)
   * then it may not be possible to use the normal C-library calls to
   * calloc(), free() and fprintf(stderr, ...). For this reason the
   * functions
   *   CHILCalloc(size_t nelems, size_t elsize), 
   *   CHILFree(void *ptr), and 
   *   CHILPrintf(const char *format, ...) 
   * are used instead. They can be redefined in the following way: */

  CHILSetCallocFunction(my_calloc_function);
  CHILSetFreeFunction(my_free_function);
  CHILSetPrintfFunction(my_printf_function);

  /* Here we decide what to use for no signal. By default -999 is
   * used. */

  CHILSetNoSignalValue(MY_NO_SIGNAL_VALUE);

  /* Interpret the command-line arguments as processing directives.
   * Any unrecognised arguments are ignored. This function also opens the
   * first radar file and positions it ready to read the first ray. */

  status = CHILInit(argc, argv, &data);

  /* If fewer than 2 arguments (including the command itself), show
   * usage information */

  if (argc < 2)
    {
      CHILUsage(&data);
      CHILOptions(&data);

      /* If there are any additional command-line arguments provided 
       * by this program then describe them here. */

      exit(0);
    }

  /* If there are any additional command-line arguments provided only 
   * by this program then search the argument list for them here. */

  /* If the CHILInit() function is able to open the first (or only)
   * radar file without any problems then it will return CHIL_OK. */

  if (status == CHIL_OK)
    {
      while (1)
        {
	  /* The following deals with empty scans, which can lead
          to CHILFetchRay() returning CHIL_ENDOFBLOCK more than once. */

	  int failures = 0, maxfailures = 10;

	  while ((status = CHILFetchRay(&data)) != CHIL_OK)
	    {
	      if (status != CHIL_ENDOFBLOCK) {
		break;
	      }
	      if ((++failures) == maxfailures)
	        {
		   CHILPrintf("Aborting: %d failed calls to CHILFetchRay - empty scans?\n");
		   break;
		}
	    }
	  if (status != CHIL_OK)
	    {
	      break;
	    }

          /* We have read the first ray of a new block of data, which for 
           * scanning data is a single scan, and for cloud data is a
           * single day. We can use the information in the substructures
           * data.chil_file, data.raster_info and data.ray to prepare
           * to write our output data (open the output file or something).
           */

          do
            {
              /* In the data.ray structure we have our processed data and
               * at this point should convert it to the new format and write
               * it out. */
            }
          while ((status = CHILFetchRay(&data)) == CHIL_OK);

          /* The CHILFetchRay() function has returned either 
           * CHIL_ENDOFBLOCK or CHIL_ENDOFDATA. Either way we need to
           * close the current output file here. */

          /* If CHILFetchRay() returned CHIL_ENDOFDATA then we have no
           * more data left and can exit from the program. */

          if (status == CHIL_ENDOFDATA)
            {
              break;
	    }

          /* Otherwise subsequent calls to CHILFetchRay() will return
           * rays from the next block. */

        }

      /* Finally we deallocate any dynamically-allocated data and issue
       * any delayed warnings. */
      CHILEnd(&data);

    }
  else {

    /* The CHILInit() function has failed to read any data. It will
     * announce on standard error what the problem was, but we may 
     * wish to add any tips to the user here. */

    CHILPrintf("Run with no options for more information\n");
    exit(1);
  }

  /* Program completed successfully. */

  exit(0);
}