IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 36472


Ignore:
Timestamp:
Feb 4, 2014, 6:18:10 AM (12 years ago)
Author:
eugene
Message:

make new tess table code actually build

Location:
branches/eam_branches/ipp-20131211/Ohana/src
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ipp-20131211/Ohana/src/addstar/src/findskycell.c

    r36471 r36472  
    2424
    2525int mktree (char *treefile, char *catdir);
     26int mklocal (char *treefile, char *catdir);
    2627int apply_tree (char *treefile, char *datafile);
    2728
     
    478479int mklocal (char *treefile, char *catdir) {
    479480
    480   int i, j, zone, band, status;
     481  int i, status;
    481482  FITS_DB db;
    482483  Image *image;
     
    509510 
    510511  // generate an empty BoundaryTree
    511   TessallationBoundary *tess = NULL;
    512   ALLOCATE (tess, TessallationBoundary, Nimage);
     512  int Ntess = Nimage;
     513  TessellationTable *tess = NULL;
     514  ALLOCATE (tess, TessellationTable, Ntess);
    513515 
    514516  // find the RA,DEC of the image centers & assign to cells
    515   for (i = 0; i < Nimage; i++) {
     517  for (i = 0; i < Ntess; i++) {
    516518    // user supplied values, do not try to derive from Image.dat
    517519    tess[i].NX_SUB = NX_SUB;
     
    523525    XY_to_RD (&ra, &dec, x, y, &image[i].coords);
    524526
    525     tess[i].ra  = ra;
    526     tess[i].dec = dec;
     527    tess[i].Ro  = ra;
     528    tess[i].Do = dec;
    527529    tess[i].Xo  = x;
    528530    tess[i].Yo  = y;
     
    563565
    564566    // XXX I don't really want to do the work of discovering the rule...
    565     memcpy (tess[i].basename, BASENAME);
    566567    tess[i].Nbasename = strlen(BASENAME);
     568    tess[i].basename = strcreate(BASENAME);
    567569
    568570    tess[i].projectIDoff = projectIDoff;
     
    570572  }
    571573
    572   BoundaryTreeSave (treefile, &tree);
     574  TessellationTableSave (treefile, tess, Ntess);
    573575
    574576  return TRUE;
  • branches/eam_branches/ipp-20131211/Ohana/src/libdvo/Makefile

    r35416 r36472  
    107107$(SRC)/convert.$(ARCH).o                \
    108108$(SRC)/HostTable.$(ARCH).o              \
    109 $(SRC)/BoundaryTree.$(ARCH).o
    110 
     109$(SRC)/BoundaryTree.$(ARCH).o           \
     110$(SRC)/TessellationTable.$(ARCH).o
    111111
    112112# $(SRC)/dvo_convert_panstarrs.$(ARCH).o
  • branches/eam_branches/ipp-20131211/Ohana/src/libdvo/include/dvo.h

    r36471 r36472  
    346346typedef enum { TESS_NONE, TESS_LOCAL, TESS_RINGS } TessType;
    347347
    348 // TessallationTable is a structure to describe the parameters of a set of "tessellations"
     348// TessellationTable is a structure to describe the parameters of a set of "tessellations"
    349349// (these are not strictly tessellations but projection sets as only the non-local
    350350// versions can cover the full sky).  For LOCAL projection cells, the structure describes
     
    368368  int NY_SUB;
    369369
     370  char *basename;
     371  int Nbasename;
     372  int projectIDoff;
     373  int skycellIDoff;
     374
    370375  TessType type; //
    371376  BoundaryTree *tree;
    372 } TessallationTable;
     377} TessellationTable;
    373378
    374379// a reduced-subset structure for relphot
     
    794799int free_tiny_values (Catalog *catalog);
    795800
     801BoundaryTree *BoundaryTreeLoad(char *filename);
     802BoundaryTree *BoundaryTreeRead(Header *headerPHU, Header *headerZone, FILE *f);
     803
     804int BoundaryTreeSave(char *filename, BoundaryTree *tree);
     805int BoundaryTreeWrite(FILE *f, BoundaryTree *tree);
     806
    796807int BoundaryTreeCellCoords (BoundaryTree *tree, int *zone, int *band, double ra, double dec);
    797 int BoundaryTreeSave(char *filename, BoundaryTree *tree);
    798 BoundaryTree *BoundaryTreeLoad(char *filename);
    799808int BoundaryTreeProjection (double *x, double *y, double r, double d, BoundaryTree *tree, int zone, int band);
     809
     810TessellationTable *TessellationTableLoad(char *filename, int *Ntess);
     811int TessellationTableSave(char *filename, TessellationTable *tess, int Ntess);
    800812
    801813void dvo_average_init (Average *average);
  • branches/eam_branches/ipp-20131211/Ohana/src/libdvo/src/BoundaryTree.c

    r35755 r36472  
    11# include "dvo.h"
    22
    3 # define GET_COLUMN_NEW(OUT,NAME,TYPE)                                  \
    4   TYPE *OUT = gfits_get_bintable_column_data (&theader, &ftable, NAME, type, &Nrow, &Ncol); \
     3# define GET_COLUMN_NEW(HEADER,FTABLE,OUT,NAME,TYPE)                            \
     4  TYPE *OUT = gfits_get_bintable_column_data (HEADER, FTABLE, NAME, type, &Nrow, &Ncol); \
    55  myAssert (!strcmp(type, #TYPE), "wrong column type");
    66
    7 # define GET_COLUMN_RAW(OUT,NAME,TYPE)                                  \
    8   OUT = gfits_get_bintable_column_data (&theader, &ftable, NAME, type, &Nrow, &Ncol); \
     7# define GET_COLUMN_RAW(HEADER,FTABLE,OUT,NAME,TYPE)                    \
     8  OUT = gfits_get_bintable_column_data (HEADER, FTABLE, NAME, type, &Nrow, &Ncol); \
    99  myAssert (!strcmp(type, #TYPE), "wrong column type");
    1010
     
    1212
    1313BoundaryTree *BoundaryTreeLoad(char *filename) {
     14
     15  Header header;
     16  Header theader;
     17  Matrix matrix;
     18
     19  header.buffer = NULL;
     20  matrix.buffer = NULL;
     21  theader.buffer = NULL;
     22  BoundaryTree *tree = NULL;
     23
     24  FILE *f = fopen (filename, "r");
     25  if (!f) {
     26    fprintf (stderr, "ERROR: cannot open boundary tree file %s\n", filename);
     27    return NULL;
     28  }
     29
     30  /* load in PHU segment (ignore) */
     31  if (!gfits_fread_header (f, &header)) {
     32    if (DEBUG) fprintf (stderr, "can't read boundary tree header\n");
     33    goto escape;
     34  }
     35  if (!gfits_fread_matrix (f, &matrix, &header)) {
     36    if (DEBUG) fprintf (stderr, "can't read boundary tree matrix\n");
     37    goto escape;
     38  }
     39
     40  // load data for this header
     41  if (!gfits_load_header (f, &theader)) {
     42    if (DEBUG) fprintf (stderr, "can't read boundary tree zone table header\n");
     43    goto escape;
     44  }
     45
     46  tree = BoundaryTreeRead (&header, &theader, f);
     47
     48escape:
     49
     50  gfits_free_header (&theader);
     51  gfits_free_header (&header);
     52  gfits_free_matrix (&matrix);
     53  fclose (f);
     54
     55  return tree;
     56}
     57
     58// assume we are pointing at the relevant table portion
     59BoundaryTree *BoundaryTreeRead(Header *headerPHU, Header *headerZone, FILE *f) {
    1460
    1561  int i, j, nz, nb, Ncol;
    1662  off_t Nrow;
    1763  char type[16];
    18   Header header;
    19   Header theader;
    20   Matrix matrix;
    21   FTable ftable;
    22 
    23   header.buffer = NULL;
    24   matrix.buffer = NULL;
    25   ftable.buffer = NULL;
    26   theader.buffer = NULL;
     64
     65  FTable ftableZone;
     66
     67  Header headerCell;
     68  FTable ftableCell;
     69
     70  ftableZone.buffer = NULL;
     71  ftableCell.buffer = NULL;
     72  headerCell.buffer = NULL;
     73
     74  // we must have already read in the Zone table header section
     75  ftableZone.header =  headerZone;
     76  ftableCell.header = &headerCell;
     77
    2778  BoundaryTree *tree = NULL;
    2879
    29   FILE *f = fopen (filename, "r");
    30   if (!f) {
    31     fprintf (stderr, "ERROR: cannot open image subset file %s\n", filename);
    32     return NULL;
    33   }
    34 
    35   /* load in PHU segment (ignore) */
    36   if (!gfits_fread_header (f, &header)) {
    37     if (DEBUG) fprintf (stderr, "can't read image subset header\n");
    38     goto escape;
    39   }
    40   if (!gfits_fread_matrix (f, &matrix, &header)) {
    41     if (DEBUG) fprintf (stderr, "can't read image subset matrix\n");
    42     goto escape;
    43   }
    44 
    4580  ALLOCATE (tree, BoundaryTree, 1);
    4681
    47   gfits_scan (&header, "DEC_ORI", "%lf", 1, &tree->DEC_origin);
    48   gfits_scan (&header, "DEC_OFF", "%lf", 1, &tree->DEC_offset);
    49 
    50   gfits_scan (&header, "NX_SUB", "%d", 1, &tree->NX_SUB);
    51   gfits_scan (&header, "NY_SUB", "%d", 1, &tree->NY_SUB);
    52   gfits_scan (&header, "PIXSCALE", "%lf", 1, &tree->dPix);
    53 
    54   ftable.header = &theader;
     82  // we need to read the boundary tree parameters from the correct header
     83  // put them in the PHU header in any case?
     84  gfits_scan (headerPHU, "DEC_ORI",  "%lf", 1, &tree->DEC_origin);
     85  gfits_scan (headerPHU, "DEC_OFF",  "%lf", 1, &tree->DEC_offset);
     86  gfits_scan (headerPHU, "NX_SUB",   "%d",  1, &tree->NX_SUB);
     87  gfits_scan (headerPHU, "NY_SUB",   "%d",  1, &tree->NY_SUB);
     88  gfits_scan (headerPHU, "PIXSCALE", "%lf", 1, &tree->dPix);
    5589
    5690  /*** zone information table ***/
    57   {
    58     // load data for this header
    59     if (!gfits_load_header (f, &theader)) goto escape;
    60 
    61     // read the fits table bytes
    62     if (!gfits_fread_ftable_data (f, &ftable, FALSE)) goto escape;
     91
     92  // read the fits table bytes
     93  if (!gfits_fread_ftable_data (f, &ftableZone, FALSE)) goto escape;
    6394 
    64     // need to create and assign to flat-field correction
    65     GET_COLUMN_RAW(tree->Nband,       "NBAND",           int);
    66     GET_COLUMN_RAW(tree->RA_origin,   "RA_ORIGIN",   double);
    67     GET_COLUMN_RAW(tree->RA_offset,   "RA_OFFSET",   double);
    68     GET_COLUMN_RAW(tree->DEC_min  ,   "DEC_MIN",     double);
    69     GET_COLUMN_RAW(tree->DEC_max  ,   "DEC_MAX",     double);
    70     GET_COLUMN_RAW(tree->DEC_min_raw, "DEC_MIN_RAW", double);
    71     GET_COLUMN_RAW(tree->DEC_max_raw, "DEC_MAX_RAW", double);
    72     gfits_free_header (&theader);
    73     gfits_free_table  (&ftable);
    74 
    75     fprintf (stderr, "loaded data for %lld zones\n", (long long) Nrow);
    76     tree->Nzone = Nrow;
    77 
    78     // allocate the storage arrays
    79     ALLOCATE (tree->ra,   double *, tree->Nzone);
    80     ALLOCATE (tree->dec,  double *, tree->Nzone);
    81     ALLOCATE (tree->Xo,   double *, tree->Nzone);
    82     ALLOCATE (tree->Yo,   double *, tree->Nzone);
    83     ALLOCATE (tree->dX,      int *, tree->Nzone);
    84     ALLOCATE (tree->dY,      int *, tree->Nzone);
    85     ALLOCATE (tree->cell,    int *, tree->Nzone);
    86     ALLOCATE (tree->projID,  int *, tree->Nzone);
    87     ALLOCATE (tree->name,  char **, tree->Nzone);
    88     for (i = 0; i < tree->Nzone; i++) {
    89       ALLOCATE (tree->ra[i],   double, tree->Nband[i]);
    90       ALLOCATE (tree->dec[i],  double, tree->Nband[i]);
    91       ALLOCATE (tree->Xo[i],   double, tree->Nband[i]);
    92       ALLOCATE (tree->Yo[i],   double, tree->Nband[i]);
    93       ALLOCATE (tree->dX[i],      int, tree->Nband[i]);
    94       ALLOCATE (tree->dY[i],      int, tree->Nband[i]);
    95       ALLOCATE (tree->cell[i],    int, tree->Nband[i]);
    96       ALLOCATE (tree->projID[i],  int, tree->Nband[i]);
    97       ALLOCATE (tree->name[i], char *, tree->Nband[i]);
    98       for (j = 0; j < tree->Nband[i]; j++) {
    99         ALLOCATE (tree->name[i][j], char, BOUNDARY_TREE_NAME_LENGTH);
    100       }
     95  // need to create and assign to flat-field correction
     96  GET_COLUMN_RAW(headerZone, &ftableZone, tree->Nband,       "NBAND",       int);
     97  GET_COLUMN_RAW(headerZone, &ftableZone, tree->RA_origin,   "RA_ORIGIN",   double);
     98  GET_COLUMN_RAW(headerZone, &ftableZone, tree->RA_offset,   "RA_OFFSET",   double);
     99  GET_COLUMN_RAW(headerZone, &ftableZone, tree->DEC_min  ,   "DEC_MIN",     double);
     100  GET_COLUMN_RAW(headerZone, &ftableZone, tree->DEC_max  ,   "DEC_MAX",     double);
     101  GET_COLUMN_RAW(headerZone, &ftableZone, tree->DEC_min_raw, "DEC_MIN_RAW", double);
     102  GET_COLUMN_RAW(headerZone, &ftableZone, tree->DEC_max_raw, "DEC_MAX_RAW", double);
     103  gfits_free_table  (&ftableZone);
     104
     105  fprintf (stderr, "loaded data for %lld zones\n", (long long) Nrow);
     106  tree->Nzone = Nrow;
     107
     108  // allocate the storage arrays
     109  ALLOCATE (tree->ra,   double *, tree->Nzone);
     110  ALLOCATE (tree->dec,  double *, tree->Nzone);
     111  ALLOCATE (tree->Xo,   double *, tree->Nzone);
     112  ALLOCATE (tree->Yo,   double *, tree->Nzone);
     113  ALLOCATE (tree->dX,      int *, tree->Nzone);
     114  ALLOCATE (tree->dY,      int *, tree->Nzone);
     115  ALLOCATE (tree->cell,    int *, tree->Nzone);
     116  ALLOCATE (tree->projID,  int *, tree->Nzone);
     117  ALLOCATE (tree->name,  char **, tree->Nzone);
     118  for (i = 0; i < tree->Nzone; i++) {
     119    ALLOCATE (tree->ra[i],   double, tree->Nband[i]);
     120    ALLOCATE (tree->dec[i],  double, tree->Nband[i]);
     121    ALLOCATE (tree->Xo[i],   double, tree->Nband[i]);
     122    ALLOCATE (tree->Yo[i],   double, tree->Nband[i]);
     123    ALLOCATE (tree->dX[i],      int, tree->Nband[i]);
     124    ALLOCATE (tree->dY[i],      int, tree->Nband[i]);
     125    ALLOCATE (tree->cell[i],    int, tree->Nband[i]);
     126    ALLOCATE (tree->projID[i],  int, tree->Nband[i]);
     127    ALLOCATE (tree->name[i], char *, tree->Nband[i]);
     128    for (j = 0; j < tree->Nband[i]; j++) {
     129      ALLOCATE (tree->name[i][j], char, BOUNDARY_TREE_NAME_LENGTH);
    101130    }
    102131  }
    103132
    104133  /*** cell information table ***/
    105   {
    106     // load data for this header
    107     if (!gfits_load_header (f, &theader)) goto escape;
    108 
    109     // read the fits table bytes
    110     if (!gfits_fread_ftable_data (f, &ftable, FALSE)) goto escape;
     134
     135  // load data for this header
     136  if (!gfits_load_header (f, &headerCell)) goto escape;
     137
     138  // read the fits table bytes
     139  if (!gfits_fread_ftable_data (f, &ftableCell, FALSE)) goto escape;
    111140 
    112     // need to create and assign to flat-field correction
    113     GET_COLUMN_NEW(R,     "RA",          double);
    114     GET_COLUMN_NEW(D,     "DEC",         double);
    115     GET_COLUMN_NEW(zone,  "ZONE",        int);
    116     GET_COLUMN_NEW(band,  "BAND",        int);
    117     GET_COLUMN_NEW(index, "INDEX",       int);
    118     GET_COLUMN_NEW(Xo,    "X_CENT",      double);
    119     GET_COLUMN_NEW(Yo,    "Y_CENT",      double);
    120     GET_COLUMN_NEW(dX,    "X_GRID",      int);
    121     GET_COLUMN_NEW(dY,    "Y_GRID",      int);
    122     GET_COLUMN_NEW(name,  "NAME",        char); // XXX how is this done?
    123     gfits_free_header (&theader);
    124     gfits_free_table  (&ftable);
    125     fprintf (stderr, "loaded data for %lld cells\n", (long long) Nrow);
    126 
    127     // assign the storage arrays
    128     for (i = 0; i < Nrow; i++) {
    129       nz = zone[i];
    130       nb = band[i];
    131       tree->ra[nz][nb] = R[i];
    132       tree->dec[nz][nb] = D[i];
    133       tree->Xo[nz][nb] = Xo[i];
    134       tree->Yo[nz][nb] = Yo[i];
    135       tree->dX[nz][nb] = dX[i];
    136       tree->dY[nz][nb] = dY[i];
    137       tree->cell[nz][nb] = i; // XXX ?
    138       memcpy(tree->name[nz][nb], &name[i*BOUNDARY_TREE_NAME_LENGTH], BOUNDARY_TREE_NAME_LENGTH);
    139       // XXX parse out the ID from the name (skycell.NNNN)
    140       tree->projID[nz][nb] = atoi(&tree->name[nz][nb][8]);
    141     }
    142 
    143     free (R     );
    144     free (D     );
    145     free (zone  );
    146     free (band  );
    147     free (Xo    );
    148     free (Yo    );
    149     free (dX    );
    150     free (dY    );
    151     free (index );
    152     free (name  );
    153   }
    154 
    155   gfits_free_header (&header);
    156   gfits_free_matrix (&matrix);
    157   fclose (f);
     141  // need to create and assign to flat-field correction
     142  GET_COLUMN_NEW(&headerCell, &ftableCell, R,     "RA",          double);
     143  GET_COLUMN_NEW(&headerCell, &ftableCell, D,     "DEC",         double);
     144  GET_COLUMN_NEW(&headerCell, &ftableCell, zone,  "ZONE",        int);
     145  GET_COLUMN_NEW(&headerCell, &ftableCell, band,  "BAND",        int);
     146  GET_COLUMN_NEW(&headerCell, &ftableCell, index, "INDEX",       int);
     147  GET_COLUMN_NEW(&headerCell, &ftableCell, Xo,    "X_CENT",      double);
     148  GET_COLUMN_NEW(&headerCell, &ftableCell, Yo,    "Y_CENT",      double);
     149  GET_COLUMN_NEW(&headerCell, &ftableCell, dX,    "X_GRID",      int);
     150  GET_COLUMN_NEW(&headerCell, &ftableCell, dY,    "Y_GRID",      int);
     151  GET_COLUMN_NEW(&headerCell, &ftableCell, name,  "NAME",        char); // XXX how is this done?
     152  gfits_free_header (&headerCell);
     153  gfits_free_table  (&ftableCell);
     154
     155  fprintf (stderr, "loaded data for %lld cells\n", (long long) Nrow);
     156
     157  // assign the storage arrays
     158  for (i = 0; i < Nrow; i++) {
     159    nz = zone[i];
     160    nb = band[i];
     161    tree->ra[nz][nb] = R[i];
     162    tree->dec[nz][nb] = D[i];
     163    tree->Xo[nz][nb] = Xo[i];
     164    tree->Yo[nz][nb] = Yo[i];
     165    tree->dX[nz][nb] = dX[i];
     166    tree->dY[nz][nb] = dY[i];
     167    tree->cell[nz][nb] = i; // XXX ?
     168    memcpy(tree->name[nz][nb], &name[i*BOUNDARY_TREE_NAME_LENGTH], BOUNDARY_TREE_NAME_LENGTH);
     169    // XXX parse out the ID from the name (skycell.NNNN)
     170    tree->projID[nz][nb] = atoi(&tree->name[nz][nb][8]);
     171  }
     172
     173  free (R     );
     174  free (D     );
     175  free (zone  );
     176  free (band  );
     177  free (Xo    );
     178  free (Yo    );
     179  free (dX    );
     180  free (dY    );
     181  free (index );
     182  free (name  );
    158183
    159184  return tree;
    160185
    161186escape:
    162   gfits_free_header (&header);
    163   gfits_free_matrix (&matrix);
    164   gfits_free_header (&theader);
    165   gfits_free_table  (&ftable);
     187  gfits_free_header (&headerCell);
     188  gfits_free_table  (&ftableCell);
     189  gfits_free_table  (&ftableZone);
    166190  if (tree) free (tree);
    167191
    168   fclose (f);
    169192  return NULL;
    170193}
     
    173196int BoundaryTreeSave(char *filename, BoundaryTree *tree) {
    174197
    175   int i, nz, nb;
    176198  Header header;
    177   Header theader;
    178199  Matrix matrix;
    179   FTable ftable;
    180200
    181201  gfits_init_header (&header);
     
    202222  gfits_free_header (&header);
    203223  gfits_free_matrix (&matrix);
     224
     225  BoundaryTreeWrite (f, tree);
     226  fclose (f);
     227
     228  return TRUE;
     229}
     230
     231int BoundaryTreeWrite(FILE *f, BoundaryTree *tree) {
     232
     233  int i, nz, nb;
     234  Header theader;
     235  FTable ftable;
    204236
    205237  /*** zone information table ***/
  • branches/eam_branches/ipp-20131211/Ohana/src/libdvo/src/TessellationTable.c

    r36471 r36472  
    1111# define DEBUG 0
    1212
    13 TessellationTable *TessellationTableLoad(char *filename) {
    14 
    15   int i, j, nz, nb, Ncol;
     13// backwards compatible load : if the first table is a BoundaryTree, not a TessellationTable, just load that.
     14TessellationTable *TessellationTableLoad(char *filename, int *Ntess) {
     15
     16  int i, Ncol;
    1617  off_t Nrow;
    1718  char type[16];
     
    2627  theader.buffer = NULL;
    2728  TessellationTable *tess = NULL;
     29  *Ntess = 0;
    2830
    2931  FILE *f = fopen (filename, "r");
     
    4345  }
    4446
    45   ALLOCATE (tess, TessellationTable, 1);
    46 
    4747  ftable.header = &theader;
    4848
    49   /*** zone information table ***/
    50   {
    51     // load data for this header
    52     if (!gfits_load_header (f, &theader)) goto escape;
    53 
    54     // read the fits table bytes
    55     if (!gfits_fread_ftable_data (f, &ftable, FALSE)) goto escape;
     49  // load data for this header
     50  if (!gfits_load_header (f, &theader)) goto escape;
     51
     52  // what kind of table have I just read (if any!)
     53  char extname[64];
     54  gfits_scan (&theader, "EXTNAME", "%s", 1, extname);
     55
     56  // is this a BoundaryTree?  if so, it must be stand-alone: load just that and generate a
     57  // containing TessellationTable.
     58  if (!strcmp(extname, "ZONE_DATA")) {
     59    BoundaryTree *tree = BoundaryTreeRead (&header, &theader, f);
     60    gfits_free_header (&theader);
     61    gfits_free_header (&header);
     62    gfits_free_matrix (&matrix);
     63    fclose (f);
     64   
     65    ALLOCATE (tess, TessellationTable, 1);
     66    tess[0].tree = tree;
     67    tess[0].type = TESS_RINGS;
     68    *Ntess = 1;
     69    return tess;
     70  }
     71 
     72  if (strcmp(extname, "TESS_DATA")) {
     73    fprintf (stderr, "header is neither ZONE_DATA nor TESS_DATA, problem with file\n");
     74    goto escape;
     75  }
     76
     77  // read the fits table bytes
     78  if (!gfits_fread_ftable_data (f, &ftable, FALSE)) goto escape;
    5679 
    57     // need to create and assign to flat-field correction
    58     GET_COLUMN_RAW(tess->Nband,       "NBAND",           int);
    59     GET_COLUMN_RAW(tess->RA_origin,   "RA_ORIGIN",   double);
    60     GET_COLUMN_RAW(tess->RA_offset,   "RA_OFFSET",   double);
    61     GET_COLUMN_RAW(tess->DEC_min  ,   "DEC_MIN",     double);
    62     GET_COLUMN_RAW(tess->DEC_max  ,   "DEC_MAX",     double);
    63     GET_COLUMN_RAW(tess->DEC_min_raw, "DEC_MIN_RAW", double);
    64     GET_COLUMN_RAW(tess->DEC_max_raw, "DEC_MAX_RAW", double);
     80  // need to create and assign to flat-field correction
     81  GET_COLUMN_NEW(Ro,     "RA",     double);
     82  GET_COLUMN_NEW(Do,     "DEC",    double);
     83  GET_COLUMN_NEW(Xo,     "X_CENT", double);
     84  GET_COLUMN_NEW(Yo,     "Y_CENT", double);
     85  GET_COLUMN_NEW(dX,     "X_GRID", int);
     86  GET_COLUMN_NEW(dY,     "Y_GRID", int);
     87  GET_COLUMN_NEW(Rmin,   "R_MIN",  double);
     88  GET_COLUMN_NEW(Rmax,   "R_MIN",  double);
     89  GET_COLUMN_NEW(Dmin,   "D_MIN",  double);
     90  GET_COLUMN_NEW(Dmax,   "D_MAX",  double);
     91  GET_COLUMN_NEW(dPix,   "SCALE",  double);
     92  GET_COLUMN_NEW(NX_SUB, "NX_SUB", int);
     93  GET_COLUMN_NEW(NY_SUB, "NY_SUB", int);
     94
     95  *Ntess = Nrow;
     96  ALLOCATE (tess, TessellationTable, *Ntess);
     97  for (i = 0; i < *Ntess; i++) {
     98    tess[i].Ro     = Ro[i]    ;
     99    tess[i].Do     = Do[i]    ;
     100    tess[i].Xo     = Xo[i]    ;
     101    tess[i].Yo     = Yo[i]    ;
     102    tess[i].dX     = dX[i]    ;
     103    tess[i].dY     = dY[i]    ;
     104    tess[i].Rmin   = Rmin[i]  ;
     105    tess[i].Rmax   = Rmax[i]  ;
     106    tess[i].Dmin   = Dmin[i]  ;
     107    tess[i].Dmax   = Dmax[i]  ;
     108    tess[i].dPix   = dPix[i]  ;
     109    tess[i].NX_SUB = NX_SUB[i];
     110    tess[i].NY_SUB = NY_SUB[i];
     111    tess[i].type   = TESS_LOCAL;
     112    tess[i].tree   = NULL;
     113  }
     114
     115  free(Ro    );
     116  free(Do    );
     117  free(Xo    );
     118  free(Yo    );
     119  free(dX    );
     120  free(dY    );
     121  free(Rmin  );
     122  free(Rmax  );
     123  free(Dmin  );
     124  free(Dmax  );
     125  free(dPix  );
     126  free(NX_SUB);
     127  free(NY_SUB);
     128
     129  gfits_free_header (&theader);
     130  gfits_free_table  (&ftable);
     131
     132  // fprintf (stderr, "loaded data for %lld projection cell\n", (long long) *Ntess);
     133
     134  /*** check for a RINGS entry ***/
     135
     136  // load data for this header, or exit
     137  if (!gfits_load_header (f, &theader))  {
     138    return tess;
     139  }
     140
     141  // what kind of table have I just read (if any!)
     142  gfits_scan (&theader, "EXTNAME", "%s", 1, extname);
     143
     144  // is this a BoundaryTree?  if so, it must be stand-alone: load just that and generate a
     145  // containing TessellationTable.
     146  if (!strcmp(extname, "ZONE_DATA")) {
     147    BoundaryTree *tree = BoundaryTreeRead (&header, &theader, f);
    65148    gfits_free_header (&theader);
    66     gfits_free_table  (&ftable);
    67 
    68     fprintf (stderr, "loaded data for %lld zones\n", (long long) Nrow);
    69     tess->Nzone = Nrow;
    70 
    71     // allocate the storage arrays
    72     ALLOCATE (tess->ra,   double *, tess->Nzone);
    73     ALLOCATE (tess->dec,  double *, tess->Nzone);
    74     ALLOCATE (tess->Xo,   double *, tess->Nzone);
    75     ALLOCATE (tess->Yo,   double *, tess->Nzone);
    76     ALLOCATE (tess->dX,      int *, tess->Nzone);
    77     ALLOCATE (tess->dY,      int *, tess->Nzone);
    78     ALLOCATE (tess->cell,    int *, tess->Nzone);
    79     ALLOCATE (tess->projID,  int *, tess->Nzone);
    80     ALLOCATE (tess->name,  char **, tess->Nzone);
    81     for (i = 0; i < tess->Nzone; i++) {
    82       ALLOCATE (tess->ra[i],   double, tess->Nband[i]);
    83       ALLOCATE (tess->dec[i],  double, tess->Nband[i]);
    84       ALLOCATE (tess->Xo[i],   double, tess->Nband[i]);
    85       ALLOCATE (tess->Yo[i],   double, tess->Nband[i]);
    86       ALLOCATE (tess->dX[i],      int, tess->Nband[i]);
    87       ALLOCATE (tess->dY[i],      int, tess->Nband[i]);
    88       ALLOCATE (tess->cell[i],    int, tess->Nband[i]);
    89       ALLOCATE (tess->projID[i],  int, tess->Nband[i]);
    90       ALLOCATE (tess->name[i], char *, tess->Nband[i]);
    91       for (j = 0; j < tess->Nband[i]; j++) {
    92         ALLOCATE (tess->name[i][j], char, BOUNDARY_TESS_NAME_LENGTH);
    93       }
    94     }
    95   }
    96 
    97   /*** cell information table ***/
    98   {
    99     // load data for this header
    100     if (!gfits_load_header (f, &theader)) goto escape;
    101 
    102     // read the fits table bytes
    103     if (!gfits_fread_ftable_data (f, &ftable, FALSE)) goto escape;
    104  
    105     // need to create and assign to flat-field correction
    106     GET_COLUMN_NEW(R,     "RA",          double);
    107     GET_COLUMN_NEW(D,     "DEC",         double);
    108     GET_COLUMN_NEW(zone,  "ZONE",        int);
    109     GET_COLUMN_NEW(band,  "BAND",        int);
    110     GET_COLUMN_NEW(index, "INDEX",       int);
    111     GET_COLUMN_NEW(Xo,    "X_CENT",      double);
    112     GET_COLUMN_NEW(Yo,    "Y_CENT",      double);
    113     GET_COLUMN_NEW(dX,    "X_GRID",      int);
    114     GET_COLUMN_NEW(dY,    "Y_GRID",      int);
    115     GET_COLUMN_NEW(name,  "NAME",        char); // XXX how is this done?
    116     gfits_free_header (&theader);
    117     gfits_free_table  (&ftable);
    118     fprintf (stderr, "loaded data for %lld cells\n", (long long) Nrow);
    119 
    120     // assign the storage arrays
    121     for (i = 0; i < Nrow; i++) {
    122       nz = zone[i];
    123       nb = band[i];
    124       tess->ra[nz][nb] = R[i];
    125       tess->dec[nz][nb] = D[i];
    126       tess->Xo[nz][nb] = Xo[i];
    127       tess->Yo[nz][nb] = Yo[i];
    128       tess->dX[nz][nb] = dX[i];
    129       tess->dY[nz][nb] = dY[i];
    130       tess->cell[nz][nb] = i; // XXX ?
    131       memcpy(tess->name[nz][nb], &name[i*BOUNDARY_TESS_NAME_LENGTH], BOUNDARY_TESS_NAME_LENGTH);
    132       // XXX parse out the ID from the name (skycell.NNNN)
    133       tess->projID[nz][nb] = atoi(&tess->name[nz][nb][8]);
    134     }
    135 
    136     free (R     );
    137     free (D     );
    138     free (zone  );
    139     free (band  );
    140     free (Xo    );
    141     free (Yo    );
    142     free (dX    );
    143     free (dY    );
    144     free (index );
    145     free (name  );
    146   }
    147 
     149    gfits_free_header (&header);
     150    gfits_free_matrix (&matrix);
     151    fclose (f);
     152   
     153    (*Ntess) ++;
     154    REALLOCATE (tess, TessellationTable, *Ntess);
     155    tess[(*Ntess - 1)].tree = tree;
     156    tess[(*Ntess - 1)].type = TESS_RINGS;
     157    return tess;
     158  }
     159 
     160  gfits_free_header (&theader);
    148161  gfits_free_header (&header);
    149162  gfits_free_matrix (&matrix);
     
    163176}
    164177
    165 // we are passed a TessellationTable structure, write it to a FITS table (3 ext)
    166 int TessellationTableSave(char *filename, TessellationTable *tess) {
    167 
    168   int i, nz, nb;
     178// we are passed a TessellationTable structure, write it to a FITS table.
     179// if one of the tess entries is a RINGS tessellation, write it as a boundary tree
     180int TessellationTableSave(char *filename, TessellationTable *tess, int Ntess) {
     181
     182  int i;
    169183  Header header;
    170   Header theader;
    171184  Matrix matrix;
    172   FTable ftable;
    173185
    174186  gfits_init_header (&header);
     
    183195  }
    184196
    185   // we need some information in the header to define the layout
    186   gfits_modify (&header, "DEC_ORI", "%lf", 1, tess->DEC_origin);
    187   gfits_modify (&header, "DEC_OFF", "%lf", 1, tess->DEC_offset);
    188 
    189   gfits_modify (&header, "NX_SUB", "%d", 1, tess->NX_SUB);
    190   gfits_modify (&header, "NY_SUB", "%d", 1, tess->NY_SUB);
    191   gfits_modify (&header, "PIXSCALE", "%lf", 1, tess->dPix);
     197  // find the RINGS tessellation (if present)
     198  BoundaryTree *rings = NULL;
     199  for (i = 0; i < Ntess; i++) {
     200    if (tess[i].type == TESS_LOCAL) continue;
     201    if (tess[i].type != TESS_RINGS) continue;
     202    rings = tess[i].tree;
     203  }
     204
     205  // if we have a RINGS entry, we need to save some information in the header to define the layout
     206  if (rings) {
     207    gfits_modify (&header, "DEC_ORI", "%lf", 1, rings->DEC_origin);
     208    gfits_modify (&header, "DEC_OFF", "%lf", 1, rings->DEC_offset);
     209
     210    gfits_modify (&header, "NX_SUB", "%d", 1, rings->NX_SUB);
     211    gfits_modify (&header, "NY_SUB", "%d", 1, rings->NY_SUB);
     212    gfits_modify (&header, "PIXSCALE", "%lf", 1, rings->dPix);
     213  }
    192214
    193215  gfits_fwrite_header  (f, &header);
     
    196218  gfits_free_matrix (&matrix);
    197219
    198   /*** zone information table ***/
    199   {
    200     gfits_create_table_header (&theader, "BINTABLE", "ZONE_DATA");
    201 
    202     gfits_define_bintable_column (&theader, "J", "ZONE",        "zone sequence number", "none", 1.0, 0.0);
    203     gfits_define_bintable_column (&theader, "J", "NBAND",       "number of cells in each zone", "none", 1.0, 0.0);
    204     gfits_define_bintable_column (&theader, "D", "RA_ORIGIN",   "origin of ra cell sequence", "degree", 1.0, 0.0);
    205     gfits_define_bintable_column (&theader, "D", "RA_OFFSET",   "offset per cell of ra cell sequence", "degree/cell", 1.0, 0.0);
    206     gfits_define_bintable_column (&theader, "D", "DEC_MIN",     "min dec for zone", "degree", 1.0, 0.0);
    207     gfits_define_bintable_column (&theader, "D", "DEC_MAX",     "max dec for zone", "degree", 1.0, 0.0);
    208     gfits_define_bintable_column (&theader, "D", "DEC_MIN_RAW", "min dec for zone", "degree", 1.0, 0.0);
    209     gfits_define_bintable_column (&theader, "D", "DEC_MAX_RAW", "max dec for zone", "degree", 1.0, 0.0);
    210 
    211     // generate the output array that carries the data
    212     gfits_create_table (&theader, &ftable);
    213 
    214     // create intermediate storage arrays
    215     int *zone = NULL; ALLOCATE (zone,  int, tess->Nzone);
    216 
    217     // assign the storage arrays
    218     for (i = 0; i < tess->Nzone; i++) {
    219       zone[i] = i;
    220     }
    221 
    222     // add the columns to the output array
    223     gfits_set_bintable_column (&theader, &ftable, "ZONE",        zone,              tess->Nzone);
    224     gfits_set_bintable_column (&theader, &ftable, "NBAND",       tess->Nband,       tess->Nzone);
    225     gfits_set_bintable_column (&theader, &ftable, "RA_ORIGIN",   tess->RA_origin,   tess->Nzone);
    226     gfits_set_bintable_column (&theader, &ftable, "RA_OFFSET",   tess->RA_offset,   tess->Nzone);
    227     gfits_set_bintable_column (&theader, &ftable, "DEC_MIN",     tess->DEC_min,     tess->Nzone);
    228     gfits_set_bintable_column (&theader, &ftable, "DEC_MAX",     tess->DEC_max,     tess->Nzone);
    229     gfits_set_bintable_column (&theader, &ftable, "DEC_MIN_RAW", tess->DEC_min_raw, tess->Nzone);
    230     gfits_set_bintable_column (&theader, &ftable, "DEC_MAX_RAW", tess->DEC_max_raw, tess->Nzone);
    231     free (zone);
    232 
    233     gfits_fwrite_Theader (f, &theader);
    234     gfits_fwrite_table (f, &ftable);
    235     gfits_free_header (&theader);
    236     gfits_free_table (&ftable);
    237   }
    238 
    239   /*** cell information table ***/
    240   {
    241     gfits_create_table_header (&theader, "BINTABLE", "CELL_DATA");
    242 
    243     char fmt[16];
    244     snprintf (fmt, 16, "%dA", BOUNDARY_TESS_NAME_LENGTH);
    245     gfits_define_bintable_column (&theader, "D", "RA",   "ra (J2000) of cell center", "degree", 1.0, 0.0);
    246     gfits_define_bintable_column (&theader, "D", "DEC",  "dec (J2000) of cell center", "degree", 1.0, 0.0);
    247     gfits_define_bintable_column (&theader, "J", "ZONE", "zone sequence number", "none", 1.0, 0.0);
    248     gfits_define_bintable_column (&theader, "J", "BAND", "band sequence number", "none", 1.0, 0.0);
    249     gfits_define_bintable_column (&theader, "J", "INDEX","cell index", "none", 1.0, 0.0);
    250     gfits_define_bintable_column (&theader, "D", "X_CENT", "projection cell center pixel", "none", 1.0, 0.0);
    251     gfits_define_bintable_column (&theader, "D", "Y_CENT", "projection cell center pixel", "none", 1.0, 0.0);
    252     gfits_define_bintable_column (&theader, "J", "X_GRID", "skycell grid spacing", "none", 1.0, 0.0);
    253     gfits_define_bintable_column (&theader, "J", "Y_GRID", "skycell grid spacing", "none", 1.0, 0.0);
    254     gfits_define_bintable_column (&theader, fmt, "NAME", "cell name", "none", 1.0, 0.0);
    255 
    256     // generate the output array that carries the data
    257     gfits_create_table (&theader, &ftable);
    258 
    259     int Ncell = 0;
    260     for (i = 0; i < tess->Nzone; i++) {
    261       Ncell += tess->Nband[i];
    262     }
    263 
    264     // create intermediate storage arrays
    265     // NOTE: we have to unroll the 2D arrays in tess into 1D arrays
    266     double *R             ; ALLOCATE (R,     double, Ncell);
    267     double *D             ; ALLOCATE (D,     double, Ncell);
    268     int    *zone          ; ALLOCATE (zone,  int,    Ncell);
    269     int    *band          ; ALLOCATE (band,  int,    Ncell);
    270     int    *index         ; ALLOCATE (index, int,    Ncell);
    271     double *Xo            ; ALLOCATE (Xo,    double, Ncell);
    272     double *Yo            ; ALLOCATE (Yo,    double, Ncell);
    273     int    *dX            ; ALLOCATE (dX,    int,    Ncell);
    274     int    *dY            ; ALLOCATE (dY,    int,    Ncell);
    275     char   *name          ; ALLOCATE (name,  char,   Ncell*BOUNDARY_TESS_NAME_LENGTH);
    276 
    277     // NOTE: a table column of characters must be fixed width, and is passed as a
    278     // contiguous array of Nchar * Nrow values
    279 
    280     // assign the storage arrays
    281     i = 0;
    282     for (nz = 0; nz < tess->Nzone; nz++) {
    283       for (nb = 0; nb < tess->Nband[nz]; nb++) {
    284         R[i]     = tess->ra[nz][nb];
    285         D[i]     = tess->dec[nz][nb];
    286         Xo[i]    = tess->Xo[nz][nb];
    287         Yo[i]    = tess->Yo[nz][nb];
    288         dX[i]    = tess->dX[nz][nb];
    289         dY[i]    = tess->dY[nz][nb];
    290         zone[i]  = nz;
    291         band[i]  = nb;
    292         index[i] = i; // or tess->cells[nz][nb] ?
    293         memcpy(&name[i*BOUNDARY_TESS_NAME_LENGTH], tess->name[nz][nb], BOUNDARY_TESS_NAME_LENGTH);
    294         i++;
    295       }
    296     }
    297 
    298     // add the columns to the output array
    299     gfits_set_bintable_column (&theader, &ftable, "RA",    R,     Ncell);
    300     gfits_set_bintable_column (&theader, &ftable, "DEC",   D,     Ncell);
    301     gfits_set_bintable_column (&theader, &ftable, "ZONE",  zone,  Ncell);
    302     gfits_set_bintable_column (&theader, &ftable, "BAND",  band,  Ncell);
    303     gfits_set_bintable_column (&theader, &ftable, "INDEX", index, Ncell);
    304     gfits_set_bintable_column (&theader, &ftable, "X_CENT", Xo,   Ncell);
    305     gfits_set_bintable_column (&theader, &ftable, "Y_CENT", Yo,   Ncell);
    306     gfits_set_bintable_column (&theader, &ftable, "X_GRID", dX,   Ncell);
    307     gfits_set_bintable_column (&theader, &ftable, "Y_GRID", dY,   Ncell);
    308     gfits_set_bintable_column (&theader, &ftable, "NAME",  name,  Ncell);
    309 
    310     free (R     );
    311     free (D     );
    312     free (zone  );
    313     free (band  );
    314     free (index );
    315     free (Xo    );
    316     free (Yo    );
    317     free (dX    );
    318     free (dY    );
    319     free (name  );
    320 
    321     gfits_fwrite_Theader (f, &theader);
    322     gfits_fwrite_table  (f, &ftable);
    323     gfits_free_header (&theader);
    324     gfits_free_table (&ftable);
    325   }
     220  /** LOCAL tessellation table info **/
     221  Header theader;
     222  FTable ftable;
     223
     224  gfits_create_table_header (&theader, "BINTABLE", "TESS_DATA");
     225
     226  gfits_define_bintable_column (&theader, "D", "RA",     "ra (J2000) of cell center", "degree", 1.0, 0.0);
     227  gfits_define_bintable_column (&theader, "D", "DEC",    "dec (J2000) of cell center", "degree", 1.0, 0.0);
     228  gfits_define_bintable_column (&theader, "D", "X_CENT", "projection cell center pixel", "none", 1.0, 0.0);
     229  gfits_define_bintable_column (&theader, "D", "Y_CENT", "projection cell center pixel", "none", 1.0, 0.0);
     230  gfits_define_bintable_column (&theader, "J", "X_GRID", "skycell grid spacing", "none", 1.0, 0.0);
     231  gfits_define_bintable_column (&theader, "J", "Y_GRID", "skycell grid spacing", "none", 1.0, 0.0);
     232  gfits_define_bintable_column (&theader, "D", "R_MIN",  "RA limit (lower)", "none", 1.0, 0.0);
     233  gfits_define_bintable_column (&theader, "D", "R_MAX",  "RA limit (upper)", "none", 1.0, 0.0);
     234  gfits_define_bintable_column (&theader, "D", "D_MIN",  "DEC limit (lower)", "none", 1.0, 0.0);
     235  gfits_define_bintable_column (&theader, "D", "D_MAX",  "DEC limit (upper)", "none", 1.0, 0.0);
     236  gfits_define_bintable_column (&theader, "D", "SCALE",  "pixel scale for projection cell", "none", 1.0, 0.0);
     237  gfits_define_bintable_column (&theader, "J", "NX_SUB", "skycell subdivision in x", "none", 1.0, 0.0);
     238  gfits_define_bintable_column (&theader, "J", "NY_SUB", "skycell subdivision in y", "none", 1.0, 0.0);
     239
     240  // generate the output array that carries the data
     241  gfits_create_table (&theader, &ftable);
     242 
     243  int Nout = (rings == NULL) ? Ntess : Ntess - 1;
     244
     245  // create intermediate storage arrays
     246  // NOTE: we have to unroll the 2D arrays in tess into 1D arrays
     247  double *Ro            ; ALLOCATE (Ro    ,    double, Nout);
     248  double *Do            ; ALLOCATE (Do    ,    double, Nout);
     249  double *Xo            ; ALLOCATE (Xo    ,    double, Nout);
     250  double *Yo            ; ALLOCATE (Yo    ,    double, Nout);
     251  int    *dX            ; ALLOCATE (dX    ,    int,    Nout);
     252  int    *dY            ; ALLOCATE (dY    ,    int,    Nout);
     253  double *Rmin          ; ALLOCATE (Rmin  ,    double, Nout);
     254  double *Rmax          ; ALLOCATE (Rmax  ,    double, Nout);
     255  double *Dmin          ; ALLOCATE (Dmin  ,    double, Nout);
     256  double *Dmax          ; ALLOCATE (Dmax  ,    double, Nout);
     257  double *dPix          ; ALLOCATE (dPix  ,    double, Nout);
     258  int    *NX_SUB        ; ALLOCATE (NX_SUB,    int,    Nout);
     259  int    *NY_SUB        ; ALLOCATE (NY_SUB,    int,    Nout);
     260
     261  // assign the storage arrays
     262  int N = 0;
     263  for (i = 0; i < Ntess; i++) {
     264    if (tess->type != TESS_LOCAL) continue;
     265    Ro[N]     = tess[i].Ro;
     266    Do[N]     = tess[i].Do;
     267    Xo[N]     = tess[i].Xo;
     268    Yo[N]     = tess[i].Yo;
     269    dX[N]     = tess[i].dX;
     270    dY[N]     = tess[i].dY;
     271    Rmin[N]   = tess[i].Rmin;
     272    Rmax[N]   = tess[i].Rmax;
     273    Dmin[N]   = tess[i].Dmin;
     274    Dmax[N]   = tess[i].Dmax;
     275    dPix[N]   = tess[i].dPix;
     276    NX_SUB[N] = tess[i].NX_SUB;
     277    NY_SUB[N] = tess[i].NY_SUB;
     278    N++;
     279  }
     280
     281  // add the columns to the output array
     282  gfits_set_bintable_column (&theader, &ftable, "RA",     Ro,     Nout);
     283  gfits_set_bintable_column (&theader, &ftable, "DEC",    Do,     Nout);
     284  gfits_set_bintable_column (&theader, &ftable, "X_CENT", Xo,     Nout);
     285  gfits_set_bintable_column (&theader, &ftable, "Y_CENT", Yo,     Nout);
     286  gfits_set_bintable_column (&theader, &ftable, "X_GRID", dX,     Nout);
     287  gfits_set_bintable_column (&theader, &ftable, "Y_GRID", dY,     Nout);
     288  gfits_set_bintable_column (&theader, &ftable, "R_MIN",  Rmin,   Nout);
     289  gfits_set_bintable_column (&theader, &ftable, "R_MAX",  Rmax,   Nout);
     290  gfits_set_bintable_column (&theader, &ftable, "D_MIN",  Dmin,   Nout);
     291  gfits_set_bintable_column (&theader, &ftable, "D_MAX",  Dmax,   Nout);
     292  gfits_set_bintable_column (&theader, &ftable, "SCALE",  dPix,   Nout);
     293  gfits_set_bintable_column (&theader, &ftable, "NX_SUB", NX_SUB, Nout);
     294  gfits_set_bintable_column (&theader, &ftable, "NY_SUB", NY_SUB, Nout);
     295
     296  free (Ro    );
     297  free (Do    );
     298  free (Xo    );
     299  free (Yo    );
     300  free (dX    );
     301  free (dY    );
     302  free (Rmin  );
     303  free (Rmax  );
     304  free (Dmin  );
     305  free (Dmax  );
     306  free (dPix  );
     307  free (NX_SUB);
     308  free (NY_SUB);
     309
     310  gfits_fwrite_Theader (f, &theader);
     311  gfits_fwrite_table  (f, &ftable);
     312  gfits_free_header (&theader);
     313  gfits_free_table (&ftable);
     314
     315  if (rings) {
     316    BoundaryTreeWrite(f, rings);
     317  }
     318
     319  fclose (f);
     320
    326321  return TRUE;
    327322}
    328 
    329 
Note: See TracChangeset for help on using the changeset viewer.