Index: /trunk/Ohana/src/libohana/include/convert.h
===================================================================
--- /trunk/Ohana/src/libohana/include/convert.h	(revision 3473)
+++ /trunk/Ohana/src/libohana/include/convert.h	(revision 3473)
@@ -0,0 +1,3 @@
+Measure *FixOldMeasure (OldMeasure *in, int Nvalues);
+Average *FixOldAverage (OldAverage *in, int Nvalues);
+SecFilt *FixOldSecFilt (OldSecFilt *in, int Nvalues);
Index: /trunk/Ohana/src/libohana/include/dvo.h
===================================================================
--- /trunk/Ohana/src/libohana/include/dvo.h	(revision 3473)
+++ /trunk/Ohana/src/libohana/include/dvo.h	(revision 3473)
@@ -0,0 +1,17 @@
+
+# define ELIXIR    1
+# define LONEOS    0
+# define PANSTARRS 0
+
+# if (LONEOS)
+# include <loneos.h>
+# endif
+
+# if (ELIXIR)
+# include <elixir.h>
+# endif
+
+# if (PANSTARRS)
+# include <panstarrs.h>
+# endif
+
Index: /trunk/Ohana/src/libohana/include/elixir.h
===================================================================
--- /trunk/Ohana/src/libohana/include/elixir.h	(revision 3473)
+++ /trunk/Ohana/src/libohana/include/elixir.h	(revision 3473)
@@ -0,0 +1,369 @@
+
+/*** this file uses data types which must have fixed sizes regardless 
+     of the platform.  It originally used the basic C primitives: 
+       float, double, int, short int, unsigned long int, etc.
+     this breaks under 64 bit (and probably on other systems).
+     I should define internal data types which should be set by the 
+     use of # define statements if needed.  I will cheat for now and use
+     the time_t to replace unsigned long int in this file 
+***/
+
+# ifndef ELIXIR_H
+# define ELIXIR_H
+
+# define e_time unsigned int
+
+/* image data modes in RegImage */
+enum {T_UNDEF = -1, T_NONE, T_OBJECT, T_DARK, T_BIAS, T_FLAT, T_MASK, T_FRINGE, T_SCATTER, T_MODES, T_FRINGEPTS, T_ANY, N_TYPE};
+enum {M_UNDEF = -1, M_NONE, M_MEF, M_SPLIT, M_SINGLE, M_CUBE, M_SLICE, M_MODES, N_MODE};
+
+/* convert these to enums? */
+/* RegImage.flag values */
+# define IMREG_DIST  0x01 /* image distributed, only imregister-3.0 */
+
+/* catalog values to be loaded */
+# define LOAD_AVES 0x01
+# define LOAD_MEAS 0x02
+# define LOAD_MISS 0x04
+# define LOAD_SECF 0x08
+
+/* invalid mag value */
+# define NO_MAG    0x7fff
+# define NO_ERR    0xff
+
+/* photometry code types */
+# define PHOT_PRI 0x01
+# define PHOT_SEC 0x02
+# define PHOT_DEP 0x03
+# define PHOT_REF 0x04
+# define PHOT_ALT 0x05  /* never stored, only for look-ups */
+
+/* Image.code values.  these are codes to note bad images */
+# define ID_IMAGE_NEW   0x0000  /* no nrphot attempted */
+# define ID_IMAGE_NOCAL 0x0001  /* used within nrphot to mean "don't apply fit" */
+# define ID_IMAGE_POOR  0x0002  /* relphot says image is bad */
+# define ID_IMAGE_SKIP  0x0004  /* external information image is bad */
+# define ID_IMAGE_FEW   0x0008  /* currently too few measurements for good value */
+
+/* Measure.flags values */
+# define ID_MEAS_NOCAL        0x0001
+# define ID_MEAS_POOR         0x0002
+# define ID_MEAS_SKIP         0x0004
+# define ID_MEAS_AREA         0x0008
+# define BLEND_IMAGE          0x0100 
+# define BLEND_CATALOG        0x0200
+# define BLEND_IMAGE_NEIGHBOR 0x1000
+# define ID_MEAS_TRAIL        0x2000
+# define ID_MEAS_GHOST        0x4000
+
+/* Average.code values */
+# define ID_STAR_FEW   0x0001 /* used within relphot: skip star */
+# define ID_STAR_POOR  0x0002 /* used within relphot: skip star */
+# define ID_PROPER     0x0400 /* star with large proper motion */
+# define ID_TRANSIENT  0x1000 /* is this mutually exclusive with USNO?  */
+# define ID_VARIABLE   0x2000 /* not currently set? */
+# define ID_ASTEROID   0x2000 /* identified with an asteroid */
+# define ID_BAD_OBJECT 0x4000 /* if all measurements are bad, set this bit */
+# define ID_MOVING     0x8000
+# define ID_ROCK       0xa000 /* 0x8000 + 0x2000 */
+# define ID_GHOST      0xc001 /* 0x8000 + 0x4000 + 0x0001 */
+# define ID_TRAIL      0xc002 /* 0x8000 + 0x4000 + 0x0002 */
+# define ID_BLEED      0xc003 /* 0x8000 + 0x4000 + 0x0003 */ 
+# define ID_COSMIC     0xc004 /* 0x8000 + 0x4000 + 0x0004 */ 
+
+/* 
+   BLEND_IMAGE: the star on an image is matched with more 
+      than one star in the catalog (image has worse seeing than catalog)
+   BLEND_CATALOG: the star in the catalog is matched with more 
+      than one star on the image (image has better seeing than catalog)
+   CALIBRATED: relative photometry has been performed on this measurement
+   BLEND_IMAGE_NEIGHBOR: the star on an image is matched with more 
+      than one star in the catalog, but not in the same catalog file.
+*/
+
+/************  database structures ************************************/
+
+/* structure for Image Registration Database */
+typedef struct {
+  char filename[64];
+  char pathname[128];
+  char filter[32];
+  char instrument[32];
+  char ccd;                        /* an identifier for CCD in mosaic (0 for single ccd) */
+  char mode;                       /* MEF, SINGLE, SPLIT */
+  char type;                       /* image type */
+  char flag;                       /* image status flags */
+  char seq;                        /* cube sequence number */
+  char junk[23];
+ 
+  float exptime;
+  float airmass;
+  float sky;
+  float bias;
+  float fwhm;
+
+  float telfocus;
+  float xprobe, yprobe, zprobe;
+  float dettemp;
+  float teltemp[4];
+  float rotangle;
+  float ra, dec;
+
+  e_time obstime;
+  e_time regtime;
+} RegImage;  /* 360 bytes / image */
+
+/* Detrend Database structure */
+typedef struct {
+  e_time tstart;
+  e_time tstop;
+  e_time treg;
+  float exptime;
+  int type;
+  int filter;
+  int ccd;
+  int Nentry;
+  int Norder;
+  char mode;
+  char altpath;   /* true: data on alt db paths */
+  char dummy[58]; /* for future expansion */
+  char label[64];
+  char filename[256];
+} DetReg;    /* 416 bytes */
+
+/* Instant Zeropoint structure */
+typedef struct {
+  float ZP;                   /* measured zero point */
+  float ZPo;                  /* expected zero point */
+  float dZP;                  /* error on zero point */
+  float K;                    /* airmass term used */
+  float X;                    /* color term used */
+  e_time tstart;   /* start time of observation */
+  e_time tstop;    /* end time of observation */
+  short int c1;               /* photcode for color term */
+  short int c2;               /* photcode for color term */
+  short int photcode;         /* appropriate photcode */
+  char label[64];
+  short int refcode;          /* reference photometry system */
+  int Ntime;                  /* number of measurement times */
+  int Nmeas;                  /* number of data points */
+} PhotPars;    /* 108 bytes */
+
+/* average data as stored in the LONEOS database */
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm, Nn;  /* number of measurements, missing */
+  short int Xp;               /* scatter in 1/100 arcsec (-327.67 to +327.67 valid range) */
+  short int Xm;               /* chisq for primary mag [1000*value] */
+  unsigned short int code;    /* an ID code (ie, star, ghost, satelite, etc) */
+  signed int offset;          /* offset to first measurement */
+  signed int missing;         /* offset to first missing obs */
+  short int dM;               /* formal error on pri mag   [1000*log(value)] */
+  short int Xg;               /* 'best' chisq value */
+} Average; /* 32 bytes / Average */
+
+/* data for individual measurement for each star */
+typedef struct {
+  short int dR, dD;           /* 1/100 of arcsec (-327.67 to +327.67 valid range) */
+  short int M;                /* thousandths of mag (-32.767 to 32.767 valid range) */
+  short int Mcal;             /* image cal mag, thousandths of mag (-32.767 to 32.767 valid range) */
+  short int Mgal;             /* 'galaxy' mag, thousandths of mag (-32.767 to 32.767 valid range) */
+  short int airmass;          /* (airmass - 1), thousandths of mag (-32.767 to 32.767 valid range) */
+  short int FWx;              /* object fwhm major axis - 1/100 of arcsec */
+  unsigned char dM;           /* thousandths of mag (0.000 to 0.255 valid range) */
+  unsigned char fwy, theta;   /* object fwhm minor/major axes ratio, angle wrt ccd X dir (0xff/360 deg precision) */
+  char dophot;                /* dophot type (1-9) */
+  unsigned short int source;  /* code to identify photometry source */
+  unsigned int   t;           /* time in seconds (0 - 143 years valid range) */
+  unsigned int averef;        /* reference to corresponding average entry, upper byte of Measure.average stores flags */
+  short int dt;               /* exposure time in units of 2500*log(exptime) (millimags!) */
+  unsigned short int flags;   /* 16 bit-flags for various uses */ 
+} Measure; /* 32 bytes / Measure */
+
+/* data on missing stars */
+typedef struct {
+  unsigned int   t;           /* time in seconds (0 - 143 years valid range) */
+} Missing; /* 4 byte / Missing */
+
+/* data on missing stars */
+typedef struct {
+  short int M;                /* other mags - thousandths of mag (-32.767 to 32.767 valid range) */
+  short int Xm;               /* chisq on alt mag */
+  short int dM;               /* scatter on alt mag */
+} SecFilt; /* 6 byte / SecFilt */
+
+/* the standard astrometric coordinates structure */
+typedef struct {
+  double   crval1, crval2;
+  float    crpix1, crpix2;
+  float    cdelt1, cdelt2;
+  float    pc1_1, pc1_2;
+  float    pc2_1, pc2_2;
+  float    polyterms[7][2];
+  char     ctype[15];
+  char     Npolyterms;
+} Coords;  /* 120 bytes / Coords */
+
+/* image structure for binary data storage of image data */
+typedef struct {
+  Coords         coords;            /* 120 bytes */
+  unsigned int   tzero;             /* readout time row 0 in sec (0 - 142 years valid range) */
+  unsigned int   nstar;             /* number of stars on image */
+  short int      secz;              /* thousanths of airmass (valid range -32.000 -- 32.000) */
+  short int      NX, NY;            /* dimensions of image */
+  short int      apmifit, dapmifit; /* aperture correction and error in thousandths of mag */
+  short int      source;            /* identifier for CCD (each ever used will have a unique letter) */
+  short int      Mcal;              /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      dMcal;             /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      Xm;                /* 10*log(image chi-square) */
+  char           name[32];          /* name of original image */
+  unsigned char  detection_limit;   /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  saturation_limit;  /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  cerror;            /* astrometric error: 1/50 of arcsec (0 -- 5.12 valid range) */
+  unsigned char  fwhm_x, fwhm_y;    /* PSF terms in 25*arcsec (valid range 0.0 -- 10.2" ") */
+  unsigned char  trate;             /* 10000 * scan rate in sec/pix (0 -- 0.0256 valid range, 
+				       typically 0.0146. this is used only to determine the time
+				       of the observation, not to find the coordinates.  1 byte
+				       gives 0.11 sec accuracy */
+  float          exptime;           /* exposure time, seconds */
+  char           code;              /* flag to mark an image as bad or whatever */
+  unsigned char  ccdnum;            /* mosaic CCD ID number (IMAGEID) */ 
+  char           dummy[20];         /* extra space for the future */
+  short int      order;             /* number of terms used for Mrel */
+  short int      Mx, My;
+  short int      Mxx, Mxy, Myy;
+  short int      Mxxx, Mxxy, Mxyy, Myyy;
+  short int      Mxxxx, Mxxxy, Mxxyy, Mxyyy, Myyyy;
+} Image;  /* 240 bytes / Image */
+/* Image needs to be aligned with 8-byte boundaries on Suns */
+
+/************  end of database structures ************************************/
+
+/* structure for data on a catalog region */
+typedef struct {
+  char filename[256];
+  double DEC[2], RA[2];
+} GSCRegion;
+
+typedef struct {
+  unsigned short int code;   /* code number (stored in Measure.source) */
+  char name[32];             /* name for filter combination */
+  char type;                 /* primary, secondary, dependent, reference */
+  short int C, dC, dX;       /* primary phot calibration terms (millimags) */
+  float K;                   /* secondary phot calibration terms (millimags) */
+  int  c1, c2;               /* color is average.M[c1] - average.M[c2] */
+  int  equiv;                /* this dependent filter is equivalent to equiv primary/secondary */
+  int  Nc;                   /* number of color terms */
+  float X[4];                /* color terms X[0]*mc + X[1]*mc^2 + X[2]*mc^3, etc */
+} PhotCode;
+
+typedef struct {
+  int Ncode;
+  int Nsecfilt;
+  int hashcode[0x10000];
+  int hashNsec[0x10000];
+  PhotCode *code;
+} PhotCodeData;
+
+/* a catalog contains this data */
+typedef struct {
+  /* data in the file: */
+  Average *average;
+  Measure *measure; 
+  Missing *missing; 
+  SecFilt *secfilt;
+  Header  header;
+  int Naverage, Nmeasure, Nmissing, Nsecfilt;
+  /* description of the catalog file: */
+  char *filename;
+  int lockmode;
+  FILE *f;
+  /* pointers for data manipulation */
+  int *found;
+  int *image;
+  int *mosaic;
+  float *X;
+  float *Y;
+} Catalog;
+
+/**** prototypes ****/
+
+int lock_catalog (Catalog *catalog, int lockmode);
+int unlock_catalog (Catalog *catalog);
+int load_catalog (Catalog *catalog, char mode, int VERBOSE);
+int save_catalog (Catalog *catalog, char VERBOSE);
+
+int  XY_to_RD (double *ra, double *dec, double x,  double y,   Coords *coords);
+int  RD_to_XY (double *x,  double *y,   double ra, double dec, Coords *coords);
+int  fXY_to_RD (float *ra, float *dec, double x,  double y,   Coords *coords);
+int  fRD_to_XY (float *x,  float *y,   double ra, double dec, Coords *coords);
+int  GetCoords (Coords *coords, Header *header);
+int  PutCoords (Coords *coords, Header *header);
+void RegisterMosaic (Coords *coords);
+void coords_precess (double *ra, double *dec, double in_epoch, double out_epoch);
+int FindMosaicForImage (Image *images, int Nimages, int entry);
+int FindMosaicForImage_TableSearch (Image *images, int Nimages, int entry);
+int FindMosaicForImage_MatchSearch (Image *images, int Nimages, int entry);
+int BuildChipMatch (Image *images, int Nimages);
+
+int FindMosaicForImage (Image *images, int Nimages, int entry);
+int FindMosaicForImage_TableSearch (Image *images, int Nimages, int entry);
+int FindMosaicForImage_MatchSearch (Image *images, int Nimages, int entry);
+int BuildChipMatch (Image *images, int Nimages);
+
+short int putMi (double value);
+double getMi (short int value);
+void returnMcal (Image *image, double *c);
+void assignMcal (Image *image, double *c, int order);
+double applyMcal (Image *image, double x, double y);
+double findscatter (double *X, double *Y, double *M, double *dM, int N, double *c, int order);
+
+PhotCode *GetPhotcodebyName (char *name);
+PhotCode *GetPhotcodeEquivbyName (char *name);
+PhotCode *GetPhotcodebyCode (int code);
+PhotCode *GetPhotcodeEquivbyCode (int code);
+char *GetPhotcodeNamebyCode (int code);
+
+double PhotInst (Measure *measure);
+double PhotAbs (Measure *measure);
+double PhotCat (Measure *measure);
+double PhotSys (Measure *measure, Average *average, SecFilt *secfilt);
+double PhotRel (Measure *measure, Average *average, SecFilt *secfilt);
+double PhotCal (Measure *thisone, Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code);
+double PhotAve (PhotCode *code, Average *average, SecFilt *secfilt);
+double PhotRef (PhotCode *code, Average *average, SecFilt *secfilt, Measure *measure);
+double PhotXm (PhotCode *code, Average *average, SecFilt *secfilt);
+double PhotdM (PhotCode *code, Average *average, SecFilt *secfilt);
+
+short iPhotInst (Measure *measure);
+short iPhotAbs (Measure *measure);
+short iPhotCat (Measure *measure);
+short iPhotSys (Measure *measure, Average *average, SecFilt *secfilt);
+short iPhotRel (Measure *measure, Average *average, SecFilt *secfilt);
+short iPhotCal (Measure *thisone, Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code);
+short iPhotAve (PhotCode *code, Average *average, SecFilt *secfilt);
+short iPhotRef (PhotCode *code, Average *average, SecFilt *secfilt, Measure *measure);
+short iPhotXm (PhotCode *code, Average *average, SecFilt *secfilt);
+short iPhotdM (PhotCode *code, Average *average, SecFilt *secfilt);
+
+short iPhotColor (Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code);
+int PhotColor (Average *average, SecFilt *secfilt, Measure *measure, int c1, int c2, double *color);
+
+int LoadPhotcodes (char *filename);
+int GetPhotcodeCodebyName (char *name);
+int GetPhotcodeEquivCodebyName (char *name);
+int GetPhotcodeEquivCodebyCode (int code);
+int GetPhotcodeNsec (int code);
+int GetPhotcodeNsecfilt ();
+void SetZeroPoint (double ZP);
+int *GetPhotcodeEquivList (int code, int *nlist);
+void ParseColorTerms (char *terms, float *X, int *N);
+
+int get_image_type (char *name);
+char *get_type_name (int type);
+int get_image_mode (char *name);
+char *get_mode_name (int mode);
+
+# endif
Index: /trunk/Ohana/src/libohana/include/panstarrs.h
===================================================================
--- /trunk/Ohana/src/libohana/include/panstarrs.h	(revision 3473)
+++ /trunk/Ohana/src/libohana/include/panstarrs.h	(revision 3473)
@@ -0,0 +1,360 @@
+
+# ifndef PANSTARRS_H
+# define PANSTARRS_H
+
+# define e_time unsigned int
+
+/* image data modes in RegImage */
+enum {T_UNDEF = -1, T_NONE, T_OBJECT, T_DARK, T_BIAS, T_FLAT, T_MASK, T_FRINGE, T_SCATTER, T_MODES, T_FRINGEPTS, T_ANY, N_TYPE};
+enum {M_UNDEF = -1, M_NONE, M_MEF, M_SPLIT, M_SINGLE, M_CUBE, M_SLICE, M_MODES, N_MODE};
+
+/* convert these to enums? */
+/* RegImage.flag values */
+# define IMREG_DIST  0x01 /* image distributed, only imregister-3.0 */
+
+/* catalog values to be loaded */
+# define LOAD_AVES 0x01
+# define LOAD_MEAS 0x02
+# define LOAD_MISS 0x04
+# define LOAD_SECF 0x08
+
+/* invalid mag value */
+# define NO_MAG    0x7fff
+# define NO_ERR    0xff
+
+/* photometry code types */
+# define PHOT_PRI 0x01
+# define PHOT_SEC 0x02
+# define PHOT_DEP 0x03
+# define PHOT_REF 0x04
+# define PHOT_ALT 0x05  /* never stored, only for look-ups */
+
+/* Image.code values.  these are codes to note bad images */
+# define ID_IMAGE_NEW   0x0000  /* no nrphot attempted */
+# define ID_IMAGE_NOCAL 0x0001  /* used within nrphot to mean "don't apply fit" */
+# define ID_IMAGE_POOR  0x0002  /* relphot says image is bad */
+# define ID_IMAGE_SKIP  0x0004  /* external information image is bad */
+# define ID_IMAGE_FEW   0x0008  /* currently too few measurements for good value */
+
+/* Measure.flags values */
+# define ID_MEAS_NOCAL        0x0001
+# define ID_MEAS_POOR         0x0002
+# define ID_MEAS_SKIP         0x0004
+# define ID_MEAS_AREA         0x0008
+# define BLEND_IMAGE          0x0100 
+# define BLEND_CATALOG        0x0200
+# define BLEND_IMAGE_NEIGHBOR 0x1000
+# define ID_MEAS_TRAIL        0x2000
+# define ID_MEAS_GHOST        0x4000
+
+/* Average.code values */
+# define ID_STAR_FEW   0x0001 /* used within relphot: skip star */
+# define ID_STAR_POOR  0x0002 /* used within relphot: skip star */
+# define ID_PROPER     0x0400 /* star with large proper motion */
+# define ID_TRANSIENT  0x1000 /* is this mutually exclusive with USNO?  */
+# define ID_VARIABLE   0x2000 /* not currently set? */
+# define ID_ASTEROID   0x2000 /* identified with an asteroid */
+# define ID_BAD_OBJECT 0x4000 /* if all measurements are bad, set this bit */
+# define ID_MOVING     0x8000
+# define ID_ROCK       0xa000 /* 0x8000 + 0x2000 */
+# define ID_GHOST      0xc001 /* 0x8000 + 0x4000 + 0x0001 */
+# define ID_TRAIL      0xc002 /* 0x8000 + 0x4000 + 0x0002 */
+# define ID_BLEED      0xc003 /* 0x8000 + 0x4000 + 0x0003 */ 
+# define ID_COSMIC     0xc004 /* 0x8000 + 0x4000 + 0x0004 */ 
+
+/* 
+   BLEND_IMAGE: the star on an image is matched with more 
+      than one star in the catalog (image has worse seeing than catalog)
+   BLEND_CATALOG: the star in the catalog is matched with more 
+      than one star on the image (image has better seeing than catalog)
+   CALIBRATED: relative photometry has been performed on this measurement
+   BLEND_IMAGE_NEIGHBOR: the star on an image is matched with more 
+      than one star in the catalog, but not in the same catalog file.
+*/
+
+/************  database structures ************************************/
+
+/* structure for Image Registration Database */
+typedef struct {
+  char filename[64];
+  char pathname[128];
+  char filter[32];
+  char instrument[32];
+  char ccd;                        /* an identifier for CCD in mosaic (0 for single ccd) */
+  char mode;                       /* MEF, SINGLE, SPLIT */
+  char type;                       /* image type */
+  char flag;                       /* image status flags */
+  char junk[24];
+ 
+  float exptime;
+  float airmass;
+  float sky;
+  float bias;
+  float fwhm;
+
+  float telfocus;
+  float xprobe, yprobe, zprobe;
+  float dettemp;
+  float teltemp[4];
+  float rotangle;
+  float ra, dec;
+
+  e_time obstime;
+  e_time regtime;
+} RegImage;  /* 360 bytes / image */
+
+/* Detrend Database structure */
+typedef struct {
+  e_time tstart;
+  e_time tstop;
+  e_time treg;
+  float exptime;
+  int type;
+  int filter;
+  int ccd;
+  int Nentry;
+  int Norder;
+  char mode;
+  char altpath;   /* true: data on alt db paths */
+  char dummy[58]; /* for future expansion */
+  char label[64];
+  char filename[256];
+} DetReg;    /* 416 bytes */
+
+/* Instant Zeropoint structure */
+typedef struct {
+  float ZP;                   /* measured zero point */
+  float ZPo;                  /* expected zero point */
+  float dZP;                  /* error on zero point */
+  float K;                    /* airmass term used */
+  float X;                    /* color term used */
+  e_time tstart;   /* start time of observation */
+  e_time tstop;    /* end time of observation */
+  short int c1;               /* photcode for color term */
+  short int c2;               /* photcode for color term */
+  short int photcode;         /* appropriate photcode */
+  char label[64];
+  short int refcode;          /* reference photometry system */
+  int Ntime;                  /* number of measurement times */
+  int Nmeas;                  /* number of data points */
+} PhotPars;    /* 108 bytes */
+
+/* average data as stored in the LONEOS database */
+typedef struct {
+  double R;                   /* RA  in decimal degrees */
+  double D;                   /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short Nm;          /* number of measurements */
+  unsigned short Nn;          /* number of missing */
+  short int Xp;               /* scatter in 1/100 arcsec (-327.67 to +327.67 valid range) */
+  short int Xm;               /* chisq for primary mag [1000*value] */
+  unsigned short code;        /* an ID code (ie, star, ghost, satelite, etc) */
+  signed int offset;          /* offset to first measurement */
+  signed int missing;         /* offset to first missing obs */
+  short int dM;               /* formal error on pri mag   [1000*log(value)] */
+  short int Xg;               /* 'best' chisq value */
+} Average; /* 40 bytes / Average */
+
+/* data for individual measurement for each star */
+typedef struct {
+  short int dR, dD;           /* 1/100 of arcsec (-327.67 to +327.67 valid range) */
+  short int M;                /* thousandths of mag (-32.767 to 32.767 valid range) */
+  short int Mcal;             /* image cal mag, thousandths of mag (-32.767 to 32.767 valid range) */
+  short int Mgal;             /* 'galaxy' mag, thousandths of mag (-32.767 to 32.767 valid range) */
+  short int airmass;          /* (airmass - 1), thousandths of mag (-32.767 to 32.767 valid range) */
+  short int FWx;              /* object fwhm major axis - 1/100 of arcsec */
+  unsigned char dM;           /* thousandths of mag (0.000 to 0.255 valid range) */
+  unsigned char fwy, theta;   /* object fwhm minor/major axes ratio, angle wrt ccd X dir (0xff/360 deg precision) */
+  char dophot;                /* dophot type (1-9) */
+  unsigned short int source;  /* code to identify photometry source */
+  unsigned int   t;           /* time in seconds (0 - 143 years valid range) */
+  unsigned int averef;        /* reference to corresponding average entry, upper byte of Measure.average stores flags */
+  short int dt;               /* exposure time in units of 2500*log(exptime) (millimags!) */
+  unsigned short int flags;   /* 16 bit-flags for various uses */ 
+} Measure; /* 32 bytes / Measure */
+
+/* data on missing stars */
+typedef struct {
+  unsigned int   t;           /* time in seconds (0 - 143 years valid range) */
+} Missing; /* 4 byte / Missing */
+
+/* data on missing stars */
+typedef struct {
+  short int M;                /* other mags - thousandths of mag (-32.767 to 32.767 valid range) */
+  short int Xm;               /* chisq on alt mag */
+  short int dM;               /* scatter on alt mag */
+} SecFilt; /* 6 byte / SecFilt */
+
+/* the standard astrometric coordinates structure */
+typedef struct {
+  double   crval1, crval2;
+  float    crpix1, crpix2;
+  float    cdelt1, cdelt2;
+  float    pc1_1, pc1_2;
+  float    pc2_1, pc2_2;
+  float    polyterms[7][2];
+  char     ctype[15];
+  char     Npolyterms;
+} Coords;  /* 120 bytes / Coords */
+
+/* image structure for binary data storage of image data */
+typedef struct {
+  Coords         coords;            /* 120 bytes */
+  unsigned int   tzero;             /* readout time row 0 in sec (0 - 142 years valid range) */
+  unsigned int   nstar;             /* number of stars on image */
+  short int      secz;              /* thousanths of airmass (valid range -32.000 -- 32.000) */
+  short int      NX, NY;            /* dimensions of image */
+  short int      apmifit, dapmifit; /* aperture correction and error in thousandths of mag */
+  short int      source;            /* identifier for CCD (each ever used will have a unique letter) */
+  short int      Mcal;              /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      dMcal;             /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      Xm;                /* 10*log(image chi-square) */
+  char           name[32];          /* name of original image */
+  unsigned char  detection_limit;   /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  saturation_limit;  /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  cerror;            /* astrometric error: 1/50 of arcsec (0 -- 5.12 valid range) */
+  unsigned char  fwhm_x, fwhm_y;    /* PSF terms in 25*arcsec (valid range 0.0 -- 10.2" ") */
+  unsigned char  trate;             /* 10000 * scan rate in sec/pix (0 -- 0.0256 valid range, 
+				       typically 0.0146. this is used only to determine the time
+				       of the observation, not to find the coordinates.  1 byte
+				       gives 0.11 sec accuracy */
+  float          exptime;           /* exposure time, seconds */
+  char           code;              /* flag to mark an image as bad or whatever */
+  unsigned char  ccdnum;            /* mosaic CCD ID number (IMAGEID) */ 
+  char           dummy[20];         /* extra space for the future */
+  short int      order;             /* number of terms used for Mrel */
+  short int      Mx, My;
+  short int      Mxx, Mxy, Myy;
+  short int      Mxxx, Mxxy, Mxyy, Myyy;
+  short int      Mxxxx, Mxxxy, Mxxyy, Mxyyy, Myyyy;
+} Image;  /* 240 bytes / Image */
+/* Image needs to be aligned with 8-byte boundaries on Suns */
+
+/************  end of database structures ************************************/
+
+/* structure for data on a catalog region */
+typedef struct {
+  char filename[256];
+  double DEC[2], RA[2];
+} GSCRegion;
+
+typedef struct {
+  unsigned short int code;   /* code number (stored in Measure.source) */
+  char name[32];             /* name for filter combination */
+  char type;                 /* primary, secondary, dependent, reference */
+  short int C, dC, dX;       /* primary phot calibration terms (millimags) */
+  float K;                   /* secondary phot calibration terms (millimags) */
+  int  c1, c2;               /* color is average.M[c1] - average.M[c2] */
+  int  equiv;                /* this dependent filter is equivalent to equiv primary/secondary */
+  int  Nc;                   /* number of color terms */
+  float X[4];                /* color terms X[0]*mc + X[1]*mc^2 + X[2]*mc^3, etc */
+} PhotCode;
+
+typedef struct {
+  int Ncode;
+  int Nsecfilt;
+  int hashcode[0x10000];
+  int hashNsec[0x10000];
+  PhotCode *code;
+} PhotCodeData;
+
+/* a catalog contains this data */
+typedef struct {
+  /* data in the file: */
+  Average *average;
+  Measure *measure; 
+  Missing *missing; 
+  SecFilt *secfilt;
+  Header  header;
+  int Naverage, Nmeasure, Nmissing, Nsecfilt;
+  /* description of the catalog file: */
+  char *filename;
+  int lockmode;
+  FILE *f;
+  /* pointers for data manipulation */
+  int *found;
+  int *image;
+  int *mosaic;
+  float *X;
+  float *Y;
+} Catalog;
+
+/**** prototypes ****/
+
+int lock_catalog (Catalog *catalog, int lockmode);
+int unlock_catalog (Catalog *catalog);
+int load_catalog (Catalog *catalog, char mode, int VERBOSE);
+int save_catalog (Catalog *catalog, char VERBOSE);
+
+int  XY_to_RD (double *ra, double *dec, double x,  double y,   Coords *coords);
+int  RD_to_XY (double *x,  double *y,   double ra, double dec, Coords *coords);
+int  fXY_to_RD (float *ra, float *dec, double x,  double y,   Coords *coords);
+int  fRD_to_XY (float *x,  float *y,   double ra, double dec, Coords *coords);
+int  GetCoords (Coords *coords, Header *header);
+int  PutCoords (Coords *coords, Header *header);
+void RegisterMosaic (Coords *coords);
+void coords_precess (double *ra, double *dec, double in_epoch, double out_epoch);
+int FindMosaicForImage (Image *images, int Nimages, int entry);
+int FindMosaicForImage_TableSearch (Image *images, int Nimages, int entry);
+int FindMosaicForImage_MatchSearch (Image *images, int Nimages, int entry);
+int BuildChipMatch (Image *images, int Nimages);
+
+int FindMosaicForImage (Image *images, int Nimages, int entry);
+int FindMosaicForImage_TableSearch (Image *images, int Nimages, int entry);
+int FindMosaicForImage_MatchSearch (Image *images, int Nimages, int entry);
+int BuildChipMatch (Image *images, int Nimages);
+
+short int putMi (double value);
+double getMi (short int value);
+void returnMcal (Image *image, double *c);
+void assignMcal (Image *image, double *c, int order);
+double applyMcal (Image *image, double x, double y);
+double findscatter (double *X, double *Y, double *M, double *dM, int N, double *c, int order);
+
+PhotCode *GetPhotcodebyName (char *name);
+PhotCode *GetPhotcodeEquivbyName (char *name);
+PhotCode *GetPhotcodebyCode (int code);
+PhotCode *GetPhotcodeEquivbyCode (int code);
+char *GetPhotcodeNamebyCode (int code);
+
+double PhotInst (Measure *measure);
+double PhotAbs (Measure *measure);
+double PhotCat (Measure *measure);
+double PhotSys (Measure *measure, Average *average, SecFilt *secfilt);
+double PhotRel (Measure *measure, Average *average, SecFilt *secfilt);
+double PhotCal (Measure *thisone, Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code);
+double PhotAve (PhotCode *code, Average *average, SecFilt *secfilt);
+double PhotRef (PhotCode *code, Average *average, SecFilt *secfilt, Measure *measure);
+double PhotXm (PhotCode *code, Average *average, SecFilt *secfilt);
+double PhotdM (PhotCode *code, Average *average, SecFilt *secfilt);
+
+short iPhotInst (Measure *measure);
+short iPhotAbs (Measure *measure);
+short iPhotCat (Measure *measure);
+short iPhotSys (Measure *measure, Average *average, SecFilt *secfilt);
+short iPhotRel (Measure *measure, Average *average, SecFilt *secfilt);
+short iPhotCal (Measure *thisone, Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code);
+short iPhotAve (PhotCode *code, Average *average, SecFilt *secfilt);
+short iPhotRef (PhotCode *code, Average *average, SecFilt *secfilt, Measure *measure);
+short iPhotXm (PhotCode *code, Average *average, SecFilt *secfilt);
+short iPhotdM (PhotCode *code, Average *average, SecFilt *secfilt);
+
+short iPhotColor (Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code);
+int PhotColor (Average *average, SecFilt *secfilt, Measure *measure, int c1, int c2, double *color);
+
+int LoadPhotcodes (char *filename);
+int GetPhotcodeCodebyName (char *name);
+int GetPhotcodeEquivCodebyName (char *name);
+int GetPhotcodeEquivCodebyCode (int code);
+int GetPhotcodeNsec (int code);
+int GetPhotcodeNsecfilt ();
+void SetZeroPoint (double ZP);
+int *GetPhotcodeEquivList (int code, int *nlist);
+void ParseColorTerms (char *terms, float *X, int *N);
+
+int get_image_type (char *name);
+char *get_type_name (int type);
+int get_image_mode (char *name);
+char *get_mode_name (int mode);
+
+# endif
Index: /trunk/Ohana/src/libohana/src/dvo_convert.c
===================================================================
--- /trunk/Ohana/src/libohana/src/dvo_convert.c	(revision 3473)
+++ /trunk/Ohana/src/libohana/src/dvo_convert.c	(revision 3473)
@@ -0,0 +1,261 @@
+SecFilt *FixOldSecFilt (OldSecFilt *in, int Nvalues);
+Average *FixOldAverage (OldAverage *in, int Nvalues);
+Measure *FixOldMeasure (OldMeasure *in, int Nvalues);
+
+/* the old load_catalog automatically converted
+   now we error, and require conversion by hand 
+*/
+
+/* this is (a bit) dangerous: the load function will automatically
+   convert from the old (Loneos) format to the new (CFHT) format.
+   But, if you load an old-format catalog, then save the new-format
+   version, the new file will be corrupted unless you load all four
+   data components.  Actually, 'save_catalog' assumes you've loaded
+   all four anyway, so it is not such a problem... */
+
+int load_catalog (Catalog *catalog, char mode, int VERBOSE) {
+  
+  int Nitems, nitems;
+  int i, Nmeas, Nmiss, size, ssize;
+  int NewMeasure, NewAverage, NewSecFilt;
+  FILE *f;
+  OldMeasure *tmpmeasure;
+  OldAverage *tmpaverage;
+  OldSecFilt *tmpsecfilt;
+  struct stat filestatus;
+
+  f = catalog[0].f;
+  fseek (f, 0, SEEK_SET);
+
+  /* read catalog header */
+  if (!fits_load_header (f, &catalog[0].header)) {
+    if (VERBOSE) fprintf (stderr, "catalog file does not exist: %s\n", catalog[0].filename);
+    return (FALSE);
+  }
+
+  /* this is done by the load anyway... */
+  fseek (f, catalog[0].header.size, SEEK_SET); 
+
+  /* get the components from the header */
+  catalog[0].Naverage = catalog[0].Nmeasure = catalog[0].Nmissing = catalog[0].Nsecfilt = 0;
+  if (!fits_scan (&catalog[0].header, "NSTARS",   "%d", 1, &catalog[0].Naverage)) return (FALSE);
+  if (!fits_scan (&catalog[0].header, "NMEAS",    "%d", 1, &catalog[0].Nmeasure)) return (FALSE);
+  if (!fits_scan (&catalog[0].header, "NMISS",    "%d", 1, &catalog[0].Nmissing)) return (FALSE);
+  if (!fits_scan (&catalog[0].header, "NSECFILT", "%d", 1, &catalog[0].Nsecfilt)) catalog[0].Nsecfilt = 0;
+  if (!fits_scan (&catalog[0].header, "NEWMEAS",  "%t", 1, &NewMeasure)) NewMeasure = FALSE;
+  if (!fits_scan (&catalog[0].header, "NEWAVES",  "%t", 1, &NewAverage)) NewAverage = FALSE;
+  if (!fits_scan (&catalog[0].header, "NEWSECF",  "%t", 1, &NewSecFilt)) NewSecFilt = FALSE;
+
+  /* predicted file size - for double checking data validity */
+  size = catalog[0].header.size;
+  ssize = NewAverage ? sizeof (Average) : sizeof (OldAverage);
+  size += ssize * catalog[0].Naverage;
+  ssize = NewMeasure ? sizeof (Measure) : sizeof (OldMeasure);
+  size += ssize * catalog[0].Nmeasure;
+  ssize = sizeof (Missing);
+  size += ssize * catalog[0].Nmissing;
+  ssize = NewSecFilt ? sizeof (SecFilt) : sizeof (OldSecFilt);
+  size += ssize * catalog[0].Nsecfilt * catalog[0].Naverage;
+
+  /* check that file size makes sense */
+  if (stat (catalog[0].filename, &filestatus) == -1) {
+    if (VERBOSE) fprintf (stderr, "failed to get status of catalog\n");
+    return (FALSE);
+  }
+  if (size > filestatus.st_size) {
+    if (VERBOSE) {
+      fprintf (stderr, "star catalog has inconsistent size\n");
+      ssize = NewAverage ? sizeof (Average) : sizeof (OldAverage);
+      fprintf (stderr, "average: %d = %d bytes\n", catalog[0].Naverage, catalog[0].Naverage*ssize);
+      ssize = NewMeasure ? sizeof (Measure) : sizeof (OldMeasure);
+      fprintf (stderr, "measure: %d = %d bytes\n", catalog[0].Nmeasure, catalog[0].Nmeasure*ssize);
+      ssize = sizeof (Missing);
+      fprintf (stderr, "missing: %d = %d bytes\n", catalog[0].Nmissing, catalog[0].Nmissing*ssize);
+      ssize = NewSecFilt ? sizeof (SecFilt) : sizeof (OldSecFilt);
+      fprintf (stderr, "secfilt: %d = %d bytes\n", catalog[0].Nsecfilt, catalog[0].Nsecfilt*catalog[0].Naverage*ssize);
+      fprintf (stderr, "expect: %d, found: %d\n", size, (int)filestatus.st_size);
+    }
+    return (FALSE);
+  } 
+  if (size < filestatus.st_size) {
+    if (VERBOSE) fprintf (stderr, "warning: file larger than expected\n");
+  } 
+
+  if (catalog[0].Naverage == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars yet in catalog %s\n", catalog[0].filename);
+    return (TRUE);
+  }
+
+  if (mode & LOAD_AVES) {
+    /* read average values */
+    if (NewAverage) {
+      ALLOCATE (catalog[0].average, Average, MAX (catalog[0].Naverage, 1));
+      Nitems = catalog[0].Naverage;
+      nitems = Fread (catalog[0].average, sizeof(Average), Nitems, f, "average");
+    } else {
+      ALLOCATE (tmpaverage, OldAverage, MAX (catalog[0].Naverage, 1));
+      Nitems = catalog[0].Naverage;
+      nitems = Fread (tmpaverage, sizeof(OldAverage), Nitems, f, "oldaverage");
+      catalog[0].average = FixOldAverage (tmpaverage, Nitems);
+    }
+    if (nitems != Nitems) {
+      if (VERBOSE) fprintf (stderr, "failed to read averages from catalog file %s (%d vs %d)\n", catalog[0].filename, nitems, Nitems);
+      return (FALSE);
+    }
+  } else {
+    /* skip over averages */
+    fseek (f, catalog[0].Naverage * sizeof(Average), SEEK_CUR); 
+  }    
+  
+  if (mode & LOAD_MEAS) {
+    /* read measurements */
+    if (NewMeasure) {
+      ALLOCATE (catalog[0].measure, Measure, MAX (catalog[0].Nmeasure, 1));
+      Nitems = catalog[0].Nmeasure;
+      nitems = Fread (catalog[0].measure, sizeof(Measure), Nitems, f, "measure");
+    } else {
+      ALLOCATE (tmpmeasure, OldMeasure, MAX (catalog[0].Nmeasure, 1));
+      Nitems = catalog[0].Nmeasure;
+      nitems = Fread (tmpmeasure, sizeof(OldMeasure), Nitems, f, "oldmeasure");
+      catalog[0].measure = FixOldMeasure (tmpmeasure, Nitems);
+    }
+    if (nitems != Nitems) {
+      if (VERBOSE) fprintf (stderr, "failed to read measures from catalog file %s (%d vs %d)\n", catalog[0].filename, nitems, Nitems);
+      return (FALSE);
+    }
+  } else {
+    /* skip over measures */
+    fseek (f, catalog[0].Nmeasure * sizeof(Measure), SEEK_CUR); 
+  } 
+
+  if (mode & LOAD_MISS) {
+    /* read missing */
+    ALLOCATE (catalog[0].missing, Missing, MAX (catalog[0].Nmissing, 1));
+    Nitems = catalog[0].Nmissing;
+    nitems = Fread (catalog[0].missing, sizeof(Missing), Nitems, f, "missing");
+    if (nitems != Nitems) {
+      if (VERBOSE) fprintf (stderr, "failed to read missing from catalog file %s (%d vs %d)\n", catalog[0].filename, nitems, Nitems);
+      return (FALSE);
+    }
+  } else {
+    /* skip over missings */
+    fseek (f, catalog[0].Nmissing * sizeof(Missing), SEEK_CUR); 
+  }
+  
+  if (mode & LOAD_SECF) {
+    /* read missing */
+    if (NewSecFilt) {
+      Nitems = catalog[0].Naverage * catalog[0].Nsecfilt;
+      ALLOCATE (catalog[0].secfilt, SecFilt, MAX (Nitems, 1));
+      nitems = Fread (catalog[0].secfilt, sizeof(SecFilt), Nitems, f, "secfilt");
+    } else {
+      Nitems = catalog[0].Naverage * catalog[0].Nsecfilt;
+      ALLOCATE (tmpsecfilt, OldSecFilt, MAX (Nitems, 1));
+      nitems = Fread (tmpsecfilt, sizeof(OldSecFilt), Nitems, f, "oldsecfilt");
+      catalog[0].secfilt = FixOldSecFilt (tmpsecfilt, Nitems);
+    } 
+    if (nitems != Nitems) {
+      if (VERBOSE) fprintf (stderr, "failed to read secondary filters from catalog file %s (%d vs %d)\n", catalog[0].filename, nitems, Nitems);
+      return (FALSE);
+    }
+  } else {
+    /* skip over secfilts */
+    fseek (f, catalog[0].Naverage * catalog[0].Nsecfilt * sizeof(SecFilt), SEEK_CUR); 
+  }
+
+  if (VERBOSE) fprintf (stderr, "read %d stars from catalog file %s (%d measurements, %d missing, %d secondary filters)\n", 
+	   catalog[0].Naverage, catalog[0].filename, catalog[0].Nmeasure, catalog[0].Nmissing, catalog[0].Nsecfilt);
+
+  /* check data integrity */
+  if (mode & LOAD_AVES) {
+    for (i = Nmeas = Nmiss = 0; i < catalog[0].Naverage; i++) {
+      Nmeas += catalog[0].average[i].Nm; 
+      Nmiss += catalog[0].average[i].Nn; 
+    }
+    if ((Nmeas != catalog[0].Nmeasure) || (Nmiss != catalog[0].Nmissing)) {
+      if (VERBOSE) {
+	fprintf (stderr, "****** data in catalog %s is corrupt, sums don't check\n", catalog[0].filename);
+	fprintf (stderr, "****** Nmeas: %d, %d\n", Nmeas, catalog[0].Nmeasure);
+	fprintf (stderr, "****** Nmiss: %d, %d\n", Nmiss, catalog[0].Nmissing);
+      }
+      return (FALSE);
+    }
+  }
+  return (TRUE);
+}
+
+/**** tools to convert between formats - this happens automatically in load_catalog */
+
+Measure *FixOldMeasure (OldMeasure *in, int Nvalues) {
+
+  int i;
+  Measure *out;
+
+  ALLOCATE (out, Measure, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].dR = in[i].dR;
+    out[i].dD = in[i].dD;
+    out[i].M  = in[i].M;
+    out[i].dM = in[i].dM;
+    out[i].Mcal = in[i].Mcal;
+    out[i].dophot = in[i].dophot;
+    out[i].source = in[i].source;
+    out[i].t = in[i].t;
+
+    out[i].dt = 0xffff;
+    out[i].averef = in[i].average & 0x00ffffff;
+    out[i].flags  = (in[i].average & 0xff000000) >> 24;
+  }
+
+  free (in);
+  
+  return (out);
+}
+
+Average *FixOldAverage (OldAverage *in, int Nvalues) {
+
+  int i;
+  Average *out;
+
+  ALLOCATE (out, Average, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].R       = in[i].R;      
+    out[i].D       = in[i].D;      
+    out[i].M       = in[i].M;      
+    out[i].Xp      = in[i].Xp;     
+    out[i].Xm      = in[i].Xm;     
+    out[i].Nm      = in[i].Nm;     
+    out[i].Nn      = in[i].Nn;     
+    out[i].code    = in[i].code;   
+    out[i].offset  = in[i].offset; 
+    out[i].missing = in[i].missing;
+
+    out[i].dM = 0xffff;
+  }
+
+  free (in);
+  
+  return (out);
+}
+
+SecFilt *FixOldSecFilt (OldSecFilt *in, int Nvalues) {
+
+  int i;
+  SecFilt *out;
+
+  ALLOCATE (out, SecFilt, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].M    = in[i].M;      
+    out[i].Xm   = in[i].Xm;      
+
+    out[i].dM   = 0xffff;
+  }
+
+  free (in);
+  
+  return (out);
+}
+
Index: /trunk/Ohana/src/mosastro/src/SaveResiduals.c
===================================================================
--- /trunk/Ohana/src/mosastro/src/SaveResiduals.c	(revision 3473)
+++ /trunk/Ohana/src/mosastro/src/SaveResiduals.c	(revision 3473)
@@ -0,0 +1,97 @@
+# include "mosastro.h"
+
+void SaveResiduals (FILE *f, Header *header) {
+
+  int i, j, N, Nmatch;
+  MatchData *match;
+  Matrix matrix;
+  Header theader;
+  FTable table;
+
+  header[0].extend = TRUE;
+  header[0].Naxes = 0;
+  fits_modify (header, "NAXIS",   "%d", 1, 0);
+  fits_modify (header, "EXTEND",  "%t", 1, TRUE);
+  fits_modify (header, "NEXTEND", "%d", 1, 1);
+
+  /* add in some keywords to specify the datatype & software version? */
+
+  /* create (empty) data matrix */
+  fits_create_matrix (header, &matrix);
+    
+  /* create bintable header */
+  fits_create_table_header (&theader, "BINTABLE", "MOSASTRO_RESIDUALS");
+
+  /* define bintable layout */
+  fits_define_bintable_column (&theader, "D",    "R_RAW",      "ra (raw)",             "degrees",                        1.0, 0.0); 
+  fits_define_bintable_column (&theader, "D",    "D_RAW",      "dec (raw)",            "degrees",                        1.0, 0.0); 
+  fits_define_bintable_column (&theader, "E",    "P_RAW",      "P coord (raw)",        "pixels",                         1.0, 0.0); 
+  fits_define_bintable_column (&theader, "E",    "Q_RAW",      "Q coord (raw)",        "pixels",                         1.0, 0.0); 
+  fits_define_bintable_column (&theader, "E",    "L_RAW",      "L coord (raw)",        "pixels",                         1.0, 0.0); 
+  fits_define_bintable_column (&theader, "E",    "M_RAW",      "M coord (raw)",        "pixels",                         1.0, 0.0); 
+  fits_define_bintable_column (&theader, "E",    "X_RAW",      "X coord (raw)",        "pixels",                         1.0, 0.0); 
+  fits_define_bintable_column (&theader, "E",    "Y_RAW",      "Y coord (raw)",        "pixels",                         1.0, 0.0); 
+
+  fits_define_bintable_column (&theader, "D",    "R_REF",      "ra (ref)",             "degrees",                        1.0, 0.0); 
+  fits_define_bintable_column (&theader, "D",    "D_REF",      "dec (ref)",            "degrees",                        1.0, 0.0); 
+  fits_define_bintable_column (&theader, "E",    "P_REF",      "P coord (ref)",        "pixels",                         1.0, 0.0); 
+  fits_define_bintable_column (&theader, "E",    "Q_REF",      "Q coord (ref)",        "pixels",                         1.0, 0.0); 
+  fits_define_bintable_column (&theader, "E",    "L_REF",      "L coord (ref)",        "pixels",                         1.0, 0.0); 
+  fits_define_bintable_column (&theader, "E",    "M_REF",      "M coord (ref)",        "pixels",                         1.0, 0.0); 
+  fits_define_bintable_column (&theader, "E",    "X_REF",      "X coord (ref)",        "pixels",                         1.0, 0.0); 
+  fits_define_bintable_column (&theader, "E",    "Y_REF",      "Y coord (ref)",        "pixels",                         1.0, 0.0); 
+
+  fits_define_bintable_column (&theader, "E",    "MAG_REF",    "catalog mag",          "pixels",                         1.0, 0.0); 
+  fits_define_bintable_column (&theader, "E",    "DMAG_REF",   "catalog mag err",      "pixels",                         1.0, 0.0); 
+  fits_define_bintable_column (&theader, "E",    "MAG_RAW",    "instrum mag",          "pixels",                         1.0, 0.0); 
+  fits_define_bintable_column (&theader, "E",    "DMAG_RAW",   "instrum mag err",      "pixels",                         1.0, 0.0); 
+  fits_define_bintable_column (&theader, "B",    "MASK",       "excluded from fit?",   "",                               1.0, 0.0);
+  fits_define_bintable_column (&theader, "7A",   "DUMMY",      "padding",              "",                               1.0, 0.0);
+
+  /* create table, add data values */
+  fits_create_table (&theader, &table);
+
+  /* create output data block and assign */
+  Nmatch = 0;
+  for (i = 0; i < Nchip; i++) Nmatch += chip[i].Nmatch; 
+  ALLOCATE (match, MatchData, Nmatch);
+
+  for (i = N = 0; i < Nchip; i++) {
+    for (j = 0; j < chip[i].Nmatch; j++, N++) {
+      match[N].Rraw = chip[i].raw[j].R;
+      match[N].Draw = chip[i].raw[j].D;
+      match[N].Praw = chip[i].raw[j].P;
+      match[N].Qraw = chip[i].raw[j].Q;
+      match[N].Lraw = chip[i].raw[j].L;
+      match[N].Mraw = chip[i].raw[j].M;
+      match[N].Xraw = chip[i].raw[j].X;
+      match[N].Yraw = chip[i].raw[j].Y;
+
+      match[N].Rref = chip[i].ref[j].R;
+      match[N].Dref = chip[i].ref[j].D;
+      match[N].Pref = chip[i].ref[j].P;
+      match[N].Qref = chip[i].ref[j].Q;
+      match[N].Lref = chip[i].ref[j].L;
+      match[N].Mref = chip[i].ref[j].M;
+      match[N].Xref = chip[i].ref[j].X;
+      match[N].Yref = chip[i].ref[j].Y;
+
+      match[N].Mcat   = chip[i].ref[j].Mag;
+      match[N].dMcat  = chip[i].ref[j].dMag;
+      match[N].Minst  = chip[i].raw[j].Mag;
+      match[N].dMinst = chip[i].raw[j].dMag;
+      match[N].mask   = chip[i].raw[j].mask;
+    }
+  }
+
+  /* fix byte order issues */
+  ConvertMatch (match, sizeof (MatchData), Nmatch);
+  fits_add_rows (&table, (char *) match, Nmatch, sizeof (MatchData));
+
+  fits_fwrite_header  (f, header);
+  fits_fwrite_matrix  (f, &matrix);
+  fits_fwrite_Theader (f, &theader);
+  fits_fwrite_table   (f, &table);
+  fclose (f);
+  return;
+}
