# ifndef DVO_H
# define DVO_H

# include <ohana.h>
# include <gfitsio.h>
# include <autocode.h>

# include <libdvo_astro.h>
# include <dvodb.h>

/* DVO table modes */
typedef enum {DVO_MODE_UNDEF, DVO_MODE_RAW, DVO_MODE_MEF, DVO_MODE_SPLIT, DVO_MODE_MYSQL} DVOTableMode;

/* DVO table formats */
typedef enum {
  DVO_FORMAT_UNDEF, 
  DVO_FORMAT_INTERNAL, 
  DVO_FORMAT_ELIXIR, 
  DVO_FORMAT_LONEOS, 
  DVO_FORMAT_PANSTARRS_DEV_0,
  DVO_FORMAT_PANSTARRS_DEV_1,
  DVO_FORMAT_PS1_DEV_1,
  DVO_FORMAT_PS1_DEV_2,
  DVO_FORMAT_PS1_DEV_3,
  DVO_FORMAT_PS1_REF,
  DVO_FORMAT_PS1_V1,
  DVO_FORMAT_PS1_V2,
  DVO_FORMAT_PS1_V3,
  DVO_FORMAT_PS1_V4,
} DVOTableFormat;

/* image data modes in RegImage */
typedef 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} ElixirDetrendTypes;
typedef enum {M_UNDEF = -1, M_NONE, M_MEF, M_SPLIT, M_SINGLE, M_CUBE, M_SLICE, M_MODES, N_MODE} ElixirDetrendModes;

typedef enum {DVO_CAT_OPEN_FAIL, DVO_CAT_OPEN_OK, DVO_CAT_OPEN_EMPTY} DVOCatalogOpenModes;

typedef enum {
  PROJ_NONE, // undefined
  PROJ_ZEA, // zenithal
  PROJ_ZPL, // zenithal
  PROJ_ARC, // zenithal
  PROJ_STG, // zenithal
  PROJ_SIN, // zenithal
  PROJ_TAN, // zenithal
  PROJ_TNX, // zenithal
  PROJ_DIS, // zenithal (TAN + polyterms)
  PROJ_LIN, // cartesian
  PROJ_PLY, // cartesian
  PROJ_WRP, // cartesian
  PROJ_AIT, // pseudocyl
  PROJ_GLS, // pseudocyl
  PROJ_PAR, // pseudocyl
} OhanaProjection;

typedef enum {
  PROJ_MODE_NONE,
  PROJ_MODE_CARTESIAN,
  PROJ_MODE_ZENITHAL,
  PROJ_MODE_PSEUDOCYL,
} OhanaProjectionMode;

// these are used as NAN for types of int values
typedef enum {
  NAN_S_CHAR  = 0x7f,
  NAN_U_CHAR  = 0xff,   // was NO_ERR
  NAN_S_SHORT = 0x7fff, // was NO_MAG
  NAN_U_SHORT = 0xffff, 
  NAN_S_INT   = 0x7fffffff,
  NAN_U_INT   = (signed int) 0xffffffff,
} DVO_INT_NAN;

// max path length
# define DVO_MAX_PATH 1024

/* RegImage.flag values */
# define IMREG_DIST  0x01 /* image distributed, only imregister-3.0 */

/* catalog values to be loaded */
# define LOAD_NONE 	0x00
# define LOAD_AVES 	0x01
# define LOAD_MEAS 	0x02
# define LOAD_MISS 	0x04
# define LOAD_SECF 	0x08 
# define SKIP_AVES 	0x10
# define SKIP_MEAS 	0x20
# define SKIP_MISS 	0x40
# define SKIP_SECF 	0x80

// # define LOAD_MEAS_META 0x100 -- is this used??

/* 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 */
# define PHOT_MAG 0x06  /* generic magnitude; never stored */

/* Image.code values -- these values are 32 bit (as of PS1_V1) */
typedef enum {
  ID_IMAGE_NEW            = 0x00000000,  /* no calibrations yet attempted */
  ID_IMAGE_PHOTOM_NOCAL   = 0x00000001,  /* user-set value used within relphot: ignore */
  ID_IMAGE_PHOTOM_POOR    = 0x00000002,  /* relphot says image is bad (dMcal > limit) */
  ID_IMAGE_PHOTOM_SKIP    = 0x00000004,  /* user-set value: assert that this image has bad photometry */
  ID_IMAGE_PHOTOM_FEW     = 0x00000008,  /* currently too few measurements for photometry */
  ID_IMAGE_ASTROM_NOCAL   = 0x00000010,  /* user-set value used within relastro: ignore */
  ID_IMAGE_ASTROM_POOR    = 0x00000020,  /* relastro says image is bad (dR,dD > limit) */
  ID_IMAGE_ASTROM_FAIL    = 0x00000040,  /* relastro fit diverged, fit not applied */
  ID_IMAGE_ASTROM_SKIP    = 0x00000080,  /* user-set value: assert that this image has bad astrometry */
  ID_IMAGE_ASTROM_FEW     = 0x00000100,  /* currently too few measurements for astrometry */
  ID_IMAGE_PHOTOM_UBERCAL = 0x00000200,  /* externally-supplied photometry zero point from ubercal analysis */
} DVOImageFlags;

/* Measure.flags values -- these values are 32 bit (as of PS1_V1) */
typedef enum {
  ID_MEAS_NOCAL          = 0x00000001,  // detection ignored for this analysis (photcode, time range) -- internal only 
  ID_MEAS_POOR_PHOTOM    = 0x00000002,  // detection is photometry outlier					     	  
  ID_MEAS_SKIP_PHOTOM    = 0x00000004,  // detection was ignored for photometry measurement			     	  
  ID_MEAS_AREA           = 0x00000008,  // detection near image edge						     
  ID_MEAS_POOR_ASTROM    = 0x00000010,  // detection is astrometry outlier					     	  
  ID_MEAS_SKIP_ASTROM    = 0x00000020,  // detection was ignored for astrometry measurement			     	  
  ID_MEAS_USED_OBJ       = 0x00000040,  // detection was used during update objects  
  ID_MEAS_USED_CHIP      = 0x00000080,  // detection was used during update chips (XXX this probably does not make it into the db)
  ID_MEAS_BLEND_MEAS     = 0x00000100,  // detection is within radius of multiple objects 
  ID_MEAS_BLEND_OBJ      = 0x00000200,  // multiple detections within radius of object 
  ID_MEAS_UNDEF_3        = 0x00000400,  // unused 
  ID_MEAS_UNDEF_4        = 0x00000800,  // unused 
  ID_MEAS_BLEND_MEAS_X   = 0x00001000,  // detection is within radius of multiple objects across catalogs		     
  ID_MEAS_ARTIFACT       = 0x00002000,  // detection is thought to be non-astronomical				     
  ID_MEAS_SYNTH_MAG      = 0x00004000,  // magnitude is synthetic
  ID_MEAS_PHOTOM_UBERCAL = 0x00008000,  // externally-supplied zero point from ubercal analysis
  ID_MEAS_STACK_PRIMARY  = 0x00010000,  // this stack measurement is in the primary skycell
  ID_MEAS_STACK_PHOT_SRC = 0x00020000,  // this measurement supplied the stack photometry
} DVOMeasureFlags;

// XXX we used these names previously in markstar: replace with ID_MEAS_ARTIFACT
// # define ID_MEAS_TRAIL        0x2000
// # define ID_MEAS_GHOST        0x4000

/* some subtle distinctions between the blend flags:
   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.
*/

/* Average.flags values -- these values are 32 bit (as of PS1_V1) */
typedef enum {
  ID_STAR_FEW       = 0x00000001, // used within relphot: skip star
  ID_STAR_POOR      = 0x00000002, // used within relphot: skip star
  ID_PROPER         = 0x00000400, // star with large proper motion
  ID_TRANSIENT      = 0x00001000, // is this mutually exclusive with USNO?
  ID_VARIABLE       = 0x00002000, // not currently set?
  ID_ASTEROID       = 0x00002000, // identified with an asteroid
  ID_BAD_OBJECT     = 0x00004000, // if all measurements are bad, set this bit
  ID_MOVING         = 0x00008000, // is a moving object
  ID_ROCK           = 0x0000a000, // 0x8000 + 0x2000
  ID_GHOST          = 0x0000c001, // 0x8000 + 0x4000 + 0x0001
  ID_TRAIL          = 0x0000c002, // 0x8000 + 0x4000 + 0x0002
  ID_BLEED          = 0x0000c003, // 0x8000 + 0x4000 + 0x0003
  ID_COSMIC         = 0x0000c004, // 0x8000 + 0x4000 + 0x0004
  ID_STAR_FIT_AVE   = 0x00010000, // average position fitted
  ID_STAR_FIT_PM    = 0x00020000, // proper motion fitted
  ID_STAR_FIT_PAR   = 0x00040000, // parallax fitted
  ID_STAR_USE_AVE   = 0x00080000, // average position used (not PM or PAR)
  ID_STAR_USE_PM    = 0x00100000, // proper motion used (not AVE or PAR)
  ID_STAR_USE_PAR   = 0x00200000, // parallax used (not AVE or PM)
  ID_STAR_NO_ASTROM = 0x00400000, // mean astrometry could not be measured
  ID_OBJ_EXT        = 0x01000000, // extended in our data (eg, PS)
  ID_OBJ_EXT_ALT    = 0x02000000, // extended in external data (eg, 2MASS)
  ID_OBJ_GOOD       = 0x04000000, // good-quality measurement in our data (eg,PS)
  ID_OBJ_GOOD_ALT   = 0x08000000, // good-quality measurement in  external data (eg, 2MASS)
  ID_OBJ_GOOD_STACK = 0x10000000, // good-quality object in the stack (> 1 good stack)
  ID_OBJ_SUSPECT_STACK = 0x20000000, // suspect object in the stack (> 1 good or suspect stack, < 2 good)
  ID_OBJ_BAD_STACK  = 0x40000000, // good-quality object in the stack (> 1 good stack)
} DVOAverageFlags;

/* Secfilt.flags values -- these values are 32 bit (as of PS1_V1) */
typedef enum {
  ID_SECF_STAR_FEW    	= 0x00000001, // used within relphot: skip star
  ID_SECF_STAR_POOR   	= 0x00000002, // used within relphot: skip star
  ID_SECF_USE_SYNTH   	= 0x00000004, // synthetic photometry used in average measurement
  ID_SECF_USE_UBERCAL 	= 0x00000008, // synthetic photometry used in average measurement
  ID_SECF_HAS_PS1     	= 0x00000010, // PS1 photometry used in average measurement
  ID_SECF_HAS_STACK   	= 0x00000020, // PS1 stack photometry exists
  ID_PHOTOM_PASS_0    	= 0x00000100, // average magnitude calculated in 0th pass
  ID_PHOTOM_PASS_1    	= 0x00000200, // average magnitude calculated in 1th pass
  ID_PHOTOM_PASS_2    	= 0x00000400, // average magnitude calculated in 2th pass
  ID_PHOTOM_PASS_3    	= 0x00000800, // average magnitude calculated in 3th pass
  ID_PHOTOM_PASS_4    	= 0x00001000, // average magnitude calculated in 4th pass
  ID_PSPS_OBJ_EXT     	= 0x00002000, // In PSPS ID_SECF_OBJ_EXT is moved here so it fits within 16 bits
  ID_SECF_STACK_PRIMARY = 0x00004000, // PS1 stack photometry comes from primary skycell
  ID_SECF_OBJ_EXT       = 0x01000000, // extended in this band
} DVOSecfiltFlags;

/*** general dvo structures (internal use only / not IO) ***/

/* FITS DB structure */
typedef struct {
  FILE  *f;
  char  *filename;
  double timeout;
  Header header;
  Matrix matrix;
  Header theader;
  FTable ftable;
  VTable vtable;
  int    dbstate;
  char   lockstate;
  char   mode;          /* what data storage mode is used for disk file? */
  char   format;        /* what data format is used for disk file? */
  char   virtual;       /* is table in ftable or vtable? */
  char   swapped;       /* is table in internal byte-order? */
} FITS_DB;

/* the basic HST GSC layout corresponds to a depth of 3 */
# define SKY_DEPTH_HST 3

/* SkyRegion : better implementation than GSCRegion */
typedef struct {
  off_t Nregions;
  char **filename;
  SkyRegion *regions;
  char hosts[80];
} SkyTable;

typedef struct {
  off_t Nregions;
  int ownElements; 				  /* does this list own filename, regions? */
  char **filename;
  SkyRegion **regions;
  char hosts[80];
} SkyList;

typedef struct {
  off_t Nimage;
  FlatCorrectionImage *image;
  off_t Ncorr;
  int *IDtoSeq;
  FlatCorrection *corr;
  float ***offset; // the correction images represented as a set of arrays (same sequence as *image)
  int Nseason;
  e_time *tstart;
  e_time *tstop;
} FlatCorrectionTable;

/* definitions for parallel dvo host information 
   XXX : need better names (safer namespace)
*/

typedef enum {
  DATA_ON_TGT  = 0x01,
  DATA_ON_BCK  = 0x02,
  DATA_USE_BCK = 0x04,

  DATA_COPY_FAILURE = 0x80,
} SkyTableDataFlags;

typedef enum {
  HOST_STDIN = 0,
  HOST_STDOUT = 1,
  HOST_STDERR = 2,
} HostInfoIOfd;

typedef struct {
  char *hostname;	      // name of remote machine
  char *pathname;	      // name of directory for this machine's data
  char *results;	      // name of file machine's result data
  int hostID;		      // remove machine ID in SkyTable
  int stdio[3]; 	      // fd's for communication with the remote host
  int pid;		      // remote process ID
  int status;		      // job exit status
  IOBuffer stdout;
  IOBuffer stderr;
} HostInfo;

typedef struct {
  int Nhosts;
  HostInfo *hosts;
  short *index;
} HostTable;

// A RegionHost processes data for some region in parallel with other regions
typedef struct RegionHostInfo {
  double Rmin;	      // (Rmin,Rmax),(Dmin,Dmax) arehard RA,DEC boundaries of the 
  double Rmax;	      // region for which each host is responsible.  A given host
  double Dmin;	      // calibrates the images for which the fiducial point (center) 
  double Dmax;	      // lands in the region, and all objects in the region

  double RminCat;      // (RminCat,RmaxCat),(DminCat,DmaxCat) are the region for which 
  double RmaxCat;      // the catalogs need to be loaded : this is the outer bounds
  double DminCat;      // of the region containing all images completely
  double DmaxCat;

  char *hostname;

  int hostID;		      // remove machine ID in SkyTable
  int stdio[3]; 	      // fd's for communication with the remote host
  int pid;		      // remote process ID
  int status;
  IOBuffer stdout;
  IOBuffer stderr;

  off_t Nimage;
  off_t NIMAGE;
  Image *image;
  off_t *imseq;

  int *neighbors;	      // list of neighbor index values
  int Nneighbors;	      // number of neighbors
  char isNeighbor;	      // TRUE if I am a neighbor to the current region host
} RegionHostInfo;

typedef struct {
  double Rmin;
  double Rmax;
  double Dmin;
  double Dmax;

  int Nhosts;
  RegionHostInfo *hosts;
  short *index;
} RegionHostTable;

// special-case function:
CMF_PS1_V2 *gfits_table_get_CMF_PS1_V1_Alt (FTable *ftable, off_t *Ndata, char *swapped);
CMF_PS1_SV1 *gfits_table_get_CMF_PS1_SV1_Alt (FTable *ftable, off_t *Ndata, char *swapped);

// another special case : does not match byte-boundaries
# include "cmf-ps1-dv3.h"

typedef struct {
  int Ncode;					  // number of photcodes
  int Nsecfilt;					  // number of average magnitudes
  int hashcode[0x10000];		  // index from photcode value to sequence
  int hashNsec[0x10000];		  // index from photcode value to Nsec seq
  int codeNsec[0x10000];		  // index from Nsec seq to photcode value
  PhotCode *code;
} PhotCodeData;

typedef enum {
  DVO_TV_MEASURE = 0x01,
  DVO_TV_AVERAGE = 0x02,
} DVOTinyValueMode;

# define BOUNDARY_TREE_NAME_LENGTH 128

// BoundaryTree is a structure to describe the 3pi RINGS skycell boundaries in terms of lines of constant (RA,DEC)
// the structure is flexible for a variety of RINGS-like tessellations, but is not appropriate for the LOCAL style tess
typedef struct {
  int FixedGridDEC;	      // is the DEC sequence linear?
  int FixedGridRA;	      // in the RA sequence in a zone linear?

  double DEC_origin;
  double DEC_offset;

  int Nzone;
  double *RA_origin;
  double *RA_offset;
  double *DEC_min;
  double *DEC_max;
  double *DEC_min_raw;
  double *DEC_max_raw;

  int *Nband;
  int *NBAND;

  double   **ra; // RA of projection cell center
  double  **dec; // DEC of projection cell center
  int    **cell; // zone,band -> proj cell sequence
  int    **projID; // zone,band -> proj cell ID
  char  ***name; // projection cell name
  
  int NX_SUB;
  int NY_SUB;
  double dPix;

  double **Xo;
  double **Yo;
  int **dX;
  int **dY;
} BoundaryTree;

typedef enum { TESS_NONE, TESS_LOCAL, TESS_RINGS } TessType;

// TessellationTable is a structure to describe the parameters of a set of "tessellations"
// (these are not strictly tessellations but projection sets as only the non-local
// versions can cover the full sky).  For LOCAL projection cells, the structure describes
// the boundaries of a SINGLE projection cell with Nx * Ny skycells and includes some
// basic parameters (not used by the fullsky, eg RINGS, tessellations)
typedef struct {
  double Rmin; // this tessellation is valid only for RA >= Rmin
  double Rmax; // this tessellation is valid only for RA <  Rmax
  double Dmin; // this tessellation is valid only for DEC >= Dmin
  double Dmax; // this tessellation is valid only for DEC <  Dmax

  double Xo;
  double Yo;
  double Ro;
  double Do;
  double dPix;
  int dX;
  int dY;

  int NX_SUB;
  int NY_SUB;

  char *basename;
  int Nbasename;
  int projectIDoff;
  int skycellIDoff;

  TessType type; // 
  BoundaryTree *tree;
} TessellationTable;

// a reduced-subset structure for relphot
typedef struct {
  double         R;
  double         D;
  unsigned short Nmeasure;
  int            measureOffset;
  uint32_t       flags;
  int            catID;
  int            objID;
  int            nOwn;
} AverageTiny;

// a reduced-subset structure for relphot & relastro
typedef struct {
  float          dR;
  float          dD;
  float          M;
  float          Mcal;
  float          dM;
  float          airmass;
  float          Xccd;
  float          Yccd;
  float          Xfix;
  float          Yfix;
  float          dt;
  int   	 t;
  unsigned int   averef;
  unsigned int   imageID;
  unsigned int   dbFlags;
  unsigned int   photFlags;
  int            catID; // unsigned int?
  unsigned short photcode;
  short          dXccd;
  short          dYccd;
  short          dRsys;
  char           myDet;
} MeasureTiny;

/** STRUCT DEFINITION **/
typedef struct {
  double           R;                    // RA (decimal degrees )
  double           D;                    // DEC (decimal degrees )
  float            dR;                   // RA error (arcsec)
  float            dD;                   // DEC error (arcsec)
  float            uR;                   // RA*cos(D) proper-motion (arcsec/year)
  float            uD;                   // DEC proper-motion (arcsec/year)
  float            duR;                  // RA*cos(D) p-m error (arcsec/year)
  float            duD;                  // DEC p-m error (arcsec/year)
  float            P;                    // parallax (arcsec)
  float            dP;                   // parallax error (arcsec)
  float            ChiSqAve;             // astrometry analysis chisq
  float            ChiSqPM;              // astrometry analysis chisq
  float            ChiSqPar;             // astrometry analysis chisq
  int              Tmean;                // mean epoch (PM,PAR ref) (unix time seconds)
  int              Trange;               // mean epoch (PM,PAR ref) (unix time seconds)
  float            Xp;                   // unused
  unsigned short   Npos;                 // number of detections used for astrometry
  unsigned short   Nmeasure;             // number of psf measurements
  unsigned short   Nmissing;             // number of missings
  unsigned short   Nextend;              // number of extended measurements
  uint32_t         measureOffset;        // offset to first psf measurement
  uint32_t         missingOffset;        // offset to first missing obs
  uint32_t         extendOffset;         // offset to first extended measurement
  uint32_t         flags;                // average object flags (star; ghost; etc)
  uint32_t         photFlagsUpper;       // upper bit of 2 bit summary of per-measure photflags
  uint32_t         photFlagsLower;       // lower bit of 2 bit summary of per-measure photflags
  unsigned int     objID;                // unique ID for object in table
  unsigned int     catID;                // unique ID for table in which object was first realized
  uint64_t         extID;                // external ID for object (eg PSPS objID)
} Average_PS1_V4alt;

Average_PS1_V4alt *gfits_table_get_Average_PS1_V4alt (FTable *table, off_t *Ndata, char *swapped);
Average *Average_PS1_V4alt_ToInternal (Average_PS1_V4alt *in, off_t Nvalues);

/** STRUCT DEFINITION **/
typedef struct {
  float            dR;                   // RA offset (arcsec)
  float            dD;                   // DEC offset (arcsec)
  float            M;                    // catalog mag (mag)
  float            Mcal;                 // image cal mag (mag)
  float            Map;                  // aperture mag (mag)
  float            Mkron;                // kron magnitude (mag)
  float            dMkron;               // kron magnitude error (mag)
  float            dM;                   // mag error (mag)
  float            dMcal;                // systematic calibration error (mag)
  float            dt;                   // exposure time (2.5*log(exptime))
  float            FluxPSF;              // flux from psf fit (counts/sec?)
  float            dFluxPSF;             // error on psf flux (counts/sec?)
  float            FluxKron;             // flux from kron ap (counts/sec?)
  float            dFluxKron;            // error on kron flux (counts/sec?)
  float            airmass;              // (airmass - 1) (airmass)
  float            az;                   // telescope azimuth
  float            Xccd;                 // X coord on chip (raw value) (pixels)
  float            Yccd;                 // Y coord on chip (raw value) (pixels)
  float            Sky;                  // local estimate of sky flux (counts/sec)
  float            dSky;                 // local estimate of sky flux (counts/sec)
  int              t;                    // time in seconds (UNIX)
  unsigned int     averef;               // reference to average entry      
  unsigned int     detID;                // detection ID
  unsigned int     imageID;              // reference to DVO image ID
  unsigned int     objID;                // unique ID for object in table
  unsigned int     catID;                // unique ID for table in which object was first realized
  uint64_t         extID;                // external ID (eg PSPS detID)
  float            psfQF;                // psf coverage/quality factor
  float            psfQFperf;            // psf coverage / quality factor (all mask bits)
  float            psfChisq;             // psf fit chisq
  int              psfNdof;              // psf degrees of freedom
  int              psfNpix;              // psf number of pixels
  float            crNsigma;             // Nsigma deviation towards CR
  float            extNsigma;            // Nsigma deviation towards EXT
  short            FWx;                  // object fwhm major axis (1/100 of pixels)
  short            FWy;                  // object fwhm minor axis (1/100 of pixels )
  short            theta;                // angle wrt ccd X dir ((0xffff/360) deg)
  short            Mxx;                  // second moments in pixel coords (1/100 of pixels)
  short            Mxy;                  // second moments in pixel coords (1/100 of pixels)
  short            Myy;                  // second moments in pixel coords (1/100 of pixels)
  unsigned short   t_msec;               // time fraction of second (milliseconds)
  unsigned short   photcode;             // photcode
  short            dXccd;                // X coord error on chip (1/100 of pixels)
  short            dYccd;                // Y coord error on chip (1/100 of pixels)
  short            dRsys;                // systematic error from astrom (1/100 of pixels)
  short            posangle;             // position angle sky to chip ((0xffff/360) deg)
  float            pltscale;             // plate scale (arcsec/pixel)
  unsigned int     dbFlags;              // flags supplied by analysis in database
  unsigned int     photFlags;            // flags supplied by photometry program
} Measure_PS1_V4alt;

Measure_PS1_V4alt *gfits_table_get_Measure_PS1_V4alt (FTable *table, off_t *Ndata, char *swapped);
Measure *Measure_PS1_V4alt_ToInternal (Measure_PS1_V4alt *in, off_t Nvalues);

/* a catalog contains this data */
typedef struct Catalog {
  char *filename;			/* catalog file */
  FILE *f;  				/* file descriptor */
  Header  header;

  /* data in the catalog file */
  Average *average;
  Measure *measure; 
  Missing *missing; 
  SecFilt *secfilt;

  int Nsecfilt;  /* number of secfilt entries for each average entry */
  off_t Naverage,   Nmeasure,   Nmissing,   Nsecf_mem;  /* current number of each component in memory */
  off_t Naves_disk, Nmeas_disk, Nmiss_disk, Nsecf_disk; /* current number of each component on disk */
  off_t Naves_off,  Nmeas_off,  Nmiss_off,  Nsecf_off;  /* index of first loaded data value */

  // note that we use these for the full-sky relphot analysis
  AverageTiny *averageT;
  MeasureTiny *measureT; 

  /* the Nsecf_* values above are number of table rows (eg, Naverage*Nsecfilt) */

  /* note the different counting for Nsecfilt:
     number of secfilt rows on disk is: Nave_disk * Nsecfilt
     number of secfilt rows in mem  is: Naverage * Nsecfilt
     *** that is just silly, and bad: convert to using Nsec_mem, Nsec_disk, Nsec_off.
     *** unless we always require the secfilt and average entries to be loaded sychronously.
     */

  /* pointers to split data files */
  struct Catalog *measure_catalog;		/* measure catalog data (split) */
  struct Catalog *missing_catalog;		/* missing catalog data (split) */
  struct Catalog *secfilt_catalog;		/* secfilt catalog data (split) */

  unsigned int objID;
  unsigned int catID;

  /* extra catalog information */
  char lockmode;
  char catmode;				/* storage mode (raw, mef, split, mysql) */
  char catformat;			/* storage format (elixir, panstarrs, etc) */
  char catflags;				/* choices to be loaded */
  char sorted;				/* is measure table average-sorted? */
  
  /* pointers for data manipulation */
  off_t *found;
  off_t *image;
  off_t *mosaic;
  float *X;
  float *Y;
  int   *nOwn; // relastro uses this to count owned detections per object

} Catalog;

/*** prototypes ***/

/* in gfits_db.c */
int   gfits_db_init                PROTO((FITS_DB *db));
int   gfits_db_create              PROTO((FITS_DB *db));
int   gfits_db_lock                PROTO((FITS_DB *db, char *filename));
int   gfits_db_load                PROTO((FITS_DB *db));
int   gfits_db_load_segment        PROTO((FITS_DB *db, off_t start, off_t Nrows));
int   gfits_db_save                PROTO((FITS_DB *db));
int   gfits_db_update              PROTO((FITS_DB *db));
int   gfits_db_close               PROTO((FITS_DB *db));
int   gfits_db_free                PROTO((FITS_DB *db));

/* in coords.c, using libautocode/def/coords.d */
int  XY_to_LM (double *L, double *M, double x,  double y,   Coords *coords);
int  LM_to_XY (double *x,  double *y,   double L, double M, Coords *coords);
int  RD_to_LM (double *L, double *M, double ra,  double dec,   Coords *coords);
int  LM_to_RD (double *ra, double *dec,   double L, double M, Coords *coords);
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);
OhanaProjection GetProjection (char *ctype);
int SetProjection (char *ctype, OhanaProjection proj);
OhanaProjectionMode GetProjectionMode (OhanaProjection proj);

char *libdvo_version (void);

int isRegisteredMosaic (void);
off_t GetRegisteredMosaic (void);
off_t *GetChipMatch (void);
int GetMosaicCoords (Coords *coords);
int FindMosaicForImage (Image *images, off_t Nimages, off_t entry);
int FindMosaicForImage_TableSearch (Image *images, off_t Nimages, off_t entry);
int FindMosaicForImage_MatchSearch (Image *images, off_t Nimages, off_t entry);
int BuildChipMatch (Image *images, off_t Nimages);
void SetImageCorners (double *X, double *Y, Image *image);

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 *GetPhotcodebyNsec (int Nsec);
PhotCode *GetPhotcodeEquivbyCode (int code);
char     *GetPhotcodeNamebyCode (int code);

float PhotInst (Measure *measure);
float PhotCat (Measure *measure);
float PhotSys (Measure *measure, Average *average, SecFilt *secfilt);
float PhotRel (Measure *measure, Average *average, SecFilt *secfilt);
float PhotCal (Measure *thisone, Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code);
float PhotAve (PhotCode *code, Average *average, SecFilt *secfilt);
float PhotRef (PhotCode *code, Average *average, SecFilt *secfilt, Measure *measure);
float PhotAveErr (PhotCode *code, Average *average, SecFilt *secfilt);

float PhotAperInst (Measure *measure);
float PhotAperCat (Measure *measure);
float PhotAperSys (Measure *measure, Average *average, SecFilt *secfilt);
float PhotAperRel (Measure *measure, Average *average, SecFilt *secfilt);
float PhotAperCal (Measure *thisone, Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code);
float PhotAperAve (PhotCode *code, Average *average, SecFilt *secfilt);
float PhotAperRef (PhotCode *code, Average *average, SecFilt *secfilt, Measure *measure);

float PhotKronInst (Measure *measure);
float PhotKronCat (Measure *measure);
float PhotKronSys (Measure *measure, Average *average, SecFilt *secfilt);
float PhotKronRel (Measure *measure, Average *average, SecFilt *secfilt);
float PhotKronCal (Measure *thisone, Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code);
float PhotKronAve (PhotCode *code, Average *average, SecFilt *secfilt);
float PhotKronRef (PhotCode *code, Average *average, SecFilt *secfilt, Measure *measure);
float PhotKronAveErr (PhotCode *code, Average *average, SecFilt *secfilt);

float PhotXm (PhotCode *code, Average *average, SecFilt *secfilt);

float PhotZeroPoint (Measure *measure, Average *average, SecFilt *secfilt);
float PhotAveFluxPSF (PhotCode *code, Average *average, SecFilt *secfilt);
float PhotAvedFluxPSF (PhotCode *code, Average *average, SecFilt *secfilt);
float PhotAveFluxKron (PhotCode *code, Average *average, SecFilt *secfilt);
float PhotAvedFluxKron (PhotCode *code, Average *average, SecFilt *secfilt);

float PhotMstdev (PhotCode *code, Average *average, SecFilt *secfilt);
float PhotM20 (PhotCode *code, Average *average, SecFilt *secfilt);
float PhotM80 (PhotCode *code, Average *average, SecFilt *secfilt);
float PhotUCdist (PhotCode *code, Average *average, SecFilt *secfilt);
unsigned int PhotStackID (PhotCode *code, Average *average, SecFilt *secfilt);

float PhotColorForCode (Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code);
int PhotColor (Average *average, SecFilt *secfilt, Measure *measure, int c1, int c2, double *color);

float PhotInstTiny (MeasureTiny *measure);
float PhotCatTiny (MeasureTiny *measure);
float PhotAperTiny (MeasureTiny *measure);
float PhotSysTiny (MeasureTiny *measure, AverageTiny *average, SecFilt *secfilt);
float PhotRelTiny (MeasureTiny *measure, AverageTiny *average, SecFilt *secfilt);
float PhotCalTiny (MeasureTiny *thisone, AverageTiny *average, SecFilt *secfilt, MeasureTiny *measure, PhotCode *code);
float PhotAveTiny (PhotCode *code, AverageTiny *average, SecFilt *secfilt);
float PhotRefTiny (PhotCode *code, AverageTiny *average, SecFilt *secfilt, MeasureTiny *measure);
float PhotXmTiny (PhotCode *code, AverageTiny *average, SecFilt *secfilt);
float PhotdMTiny (PhotCode *code, AverageTiny *average, SecFilt *secfilt);

float PhotColorForCodeTiny (AverageTiny *average, SecFilt *secfilt, MeasureTiny *measure, PhotCode *code);
int PhotColorTiny (AverageTiny *average, SecFilt *secfilt, MeasureTiny *measure, int c1, int c2, double *color);

PhotCodeData *GetPhotcodeTable (void);
void SetPhotcodeTable (PhotCodeData *);

int *GetSecFiltMap(PhotCodeData *ouput, PhotCodeData* input);
PhotCode **ParsePhotcodeList (char *rawlist, int *nphotcodes, int needAve);

int LoadPhotcodes (char *catdir_file, char *master_file, int readwrite);
int LoadPhotcodesText (char *filename);
int LoadPhotcodesFITS (char *filename);
int SavePhotcodesText (char *filename);
int SavePhotcodesFITS (char *filename);

void PrintPhotcodeNamebyCode (FILE *f, char *format, int code);

int GetPhotcodeCodebyName (char *name);
int GetPhotcodeEquivCodebyName (char *name);
int GetPhotcodeEquivCodebyCode (int code);
int GetPhotcodeNsec (int code);
int GetPhotcodeNsecfilt (void);
void SetZeroPoint (double ZP);
double GetZeroPoint (void);
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);

/** dvo_catalog APIs */
void dvo_catalog_init (Catalog *catalog, int complete);
void dvo_catalog_create (SkyRegion *region, Catalog *catalog);
void dvo_catalog_free (Catalog *catalog);
void dvo_catalog_free_data (Catalog *catalog);
int dvo_catalog_check (Catalog *catalog, int Nsecfilt, int extend);
int dvo_catalog_lock (Catalog *catalog, int lockmode);
int dvo_catalog_unlock (Catalog *catalog);
int dvo_catalog_load (Catalog *catalog, int VERBOSE);
int dvo_catalog_open (Catalog *catalog, SkyRegion *region, int VERBOSE, char *iomode);
int dvo_catalog_save (Catalog *catalog, char VERBOSE);
int dvo_catalog_save_complete (Catalog *catalog, char VERBOSE);
int dvo_catalog_update (Catalog *catalog, char VERBOSE);
int dvo_catalog_catformat (char *catformat);
int dvo_catalog_catmode (char *catmode);
void dvo_catalog_test (Catalog *catalog, int halt);

int dvo_catalog_backup (Catalog *catalog, int primary);
int dvo_catalog_unlink_backup (Catalog *catalog, int primary);

/* catmode-specific APIs */
int dvo_catalog_load_raw (Catalog *catalog, int VERBOSE);
int dvo_catalog_save_raw (Catalog *catalog, char VERBOSE);
int dvo_catalog_load_mef (Catalog *catalog, int VERBOSE);
int dvo_catalog_save_mef (Catalog *catalog, char VERBOSE);
int dvo_catalog_load_split (Catalog *catalog, int VERBOSE);
int dvo_catalog_save_split (Catalog *catalog, char VERBOSE);
int dvo_catalog_update_split (Catalog *catalog, char VERBOSE);
int dvo_catalog_save_split_complete (Catalog *catalog, char VERBOSE);

int dvo_catalog_load_segment (Catalog *catalog, int VERBOSE, off_t start, off_t Nrows);
int dvo_catalog_load_segment_split (Catalog *catalog, int VERBOSE, off_t start, off_t Nrows);

/*** conversion functions / I/O conversions ***/
Average *ReadRawAverage (FILE *f, off_t Naverage, char format, SecFilt **primary);
Measure *ReadRawMeasure (FILE *f, off_t Nmeasure, char format);
SecFilt *ReadRawSecFilt (FILE *f, off_t Nsecfilt, char format);
int WriteRawAverage (FILE *f, Average *average, off_t Naverage, char format, SecFilt *primary);
int WriteRawMeasure (FILE *f, Measure *measure, off_t Nmeasure, char format);
int WriteRawSecFilt (FILE *f, SecFilt *secfilt, off_t Nsecfilt, char format);

DVOTableFormat FtableGetFormat (FTable *ftable);

Average *FtableToAverage (FTable *ftable, off_t *Naverage, char *format, SecFilt **primary);
Measure *FtableToMeasure (FTable *ftable, off_t *Nmeasure, char *format);
SecFilt *FtableToSecFilt (FTable *ftable, off_t *Nsecfilt, char *format);
int      FtableToImage   (FTable *ftable, Header *theader, char *format);

int AverageToFtable (FTable *ftable, Average *average, off_t Naverage, char format, SecFilt *primary);
int MeasureToFtable (FTable *ftable, Measure *measure, off_t Nmeasure, char format);
int SecFiltToFtable (FTable *ftable, SecFilt *secfilt, off_t Nsecfilt, char format);
int ImageToFtable (FTable *ftable, Header *theader, char format);
int ImageToVtable (VTable *vtable, Header *theader, char format);

# include "loneos_defs.h"
# include "elixir_defs.h"
# include "panstarrs_dev_0_defs.h"
# include "panstarrs_dev_1_defs.h"
# include "ps1_dev_1_defs.h"
# include "ps1_dev_2_defs.h"
# include "ps1_dev_3_defs.h"
# include "ps1_v1_defs.h"
# include "ps1_v2_defs.h"
# include "ps1_v3_defs.h"
# include "ps1_v4_defs.h"
# include "ps1_ref_defs.h"

/*** DVO image db I/O Functions ***/
int dvo_image_lock (FITS_DB *db, char *filename, double timeout, int lockstate);
int dvo_image_unlock (FITS_DB *db);
int dvo_image_load (FITS_DB *db, int VERBOSE, int FORCE_READ);
int dvo_image_save (FITS_DB *db, int VERBOSE);
int dvo_image_update (FITS_DB *db, int VERBOSE);
int dvo_image_load_raw (FITS_DB *db, int VERBOSE, int FORCE_READ);
int dvo_image_update_raw (FITS_DB *db, int VERBOSE);
int dvo_image_save_raw (FITS_DB *db, int VERBOSE);
int dvo_image_addrows (FITS_DB *db, Image *new, off_t Nnew);
int dvo_image_createID (Header *header);
void dvo_image_create (FITS_DB *db, double ZeroPoint);

/* flatcorr APIs */
FlatCorrectionTable *FlatCorrectionLoad (char *filename, int VERBOSE);
int FlatCorrectionInternal(FlatCorrectionTable *flatcorrTable);
int FlatCorrectionSave (FlatCorrectionTable *flatcorrTable, char *filename);
float FlatCorrectionOffset (FlatCorrectionTable *flatcorr, int ID, int X, int Y);

/* skyregion APIs */
int        SkyTableSave        	   PROTO((SkyTable *table, char *filename));
SkyTable  *SkyTableLoad        	   PROTO((char *filename, int VERBOSE));
char      *SkyTableFilename        PROTO((char *catdir));
SkyTable  *SkyTableFromGSC     	   PROTO((char *filename, int depth, int VERBOSE));
SkyTable  *SkyTableLoadOptimal 	   PROTO((char *catdir, char *SKYFILE, char *GSCFILE, int readwrite, int depth, int VERBOSE));
int        SkyTableSetDepth    	   PROTO((SkyTable *sky, int depth));
SkyList   *SkyRegionByCPT          PROTO((SkyTable *table, char *filename));
SkyList   *SkyRegionByPoint    	   PROTO((SkyTable *table, int depth, double ra, double dec));
SkyList   *SkyListByPoint      	   PROTO((SkyTable *table, double ra, double dec));
SkyList   *SkyListByRadius     	   PROTO((SkyTable *table, int depth, double RA, double DEC, double radius));
SkyList   *SkyListByPatch      	   PROTO((SkyTable *table, int depth, SkyRegion *patch));
SkyList   *SkyListByName      	   PROTO((SkyTable *table, char *name));
SkyList   *SkyListByImage      	   PROTO((SkyTable *table, int depth, Image *image));
SkyList   *SkyListByBounds     	   PROTO((SkyTable *table, int depth, double Rmin, double Rmax, double Dmin, double Dmax));
SkyList   *SkyListChildrenByBounds PROTO((SkyTable *table, int No, int depth, double Rmin, double Rmax, double Dmin, double Dmax));

int        SkyListMerge     	   PROTO((SkyList **outlist, SkyList *newlist));
int        SkyListFree             PROTO((SkyList *list));
int        SkyTableFree            PROTO((SkyTable *table));
int        SkyListSetFilenames     PROTO((SkyList *list, char *path, char *ext));
int        SkyTableSetFilenames    PROTO((SkyTable *sky, char *path, char *ext));

SkyList   *SkyRegionByPoint_List   PROTO((SkyList *inList, int depth, double ra, double dec));
SkyList   *SkyListByBounds_List    PROTO((SkyList *table, int depth, double Rmin, double Rmax, double Dmin, double Dmax));
SkyList   *SkyListChildrenByBounds_List PROTO((SkyList *table, int depth, double Rmin, double Rmax, double Dmin, double Dmax));

int set_skyregion(double Rs, double Re, double Ds, double De);
int get_skyregion (double *Rs, double *Re, double *Ds, double *De);

void dvo_set_catdir(char *catdir);
char *dvo_get_catdir();

/* dvo-specific sorting functions */
void sortave (Average *ave, off_t N);
void sort_image_subset (Image *image, off_t *subset, off_t N);
void sort_coords_index (double *X, double *Y, off_t *S, off_t N);
void sort_coords_indexonly (double *X, double *Y, off_t *S, off_t N);
void sort_IDs_indexonly (opihi_int *X, off_t *S, off_t N);
void sort_regions (SkyRegion *region, off_t N);

#ifdef MOVED_TO_LIBOHANA
int  print_error(void);
int  init_error(void);
int  push_error(char *);
#endif

// functions for parallel DVO
HostTable    *HostTableLoad (char *catdir, char *rootname);
int HostTableWaitJobs (HostTable *table, char *file, int lineno);
int HostTableWaitJobsGetIO (HostTable *table, char *file, int lineno, int VERBOSE);
int HostTableTestHost (SkyRegion *region, int hostID);

// functions to support tiny versions of Average and Measure
void CopyAverageToTiny (AverageTiny *averageT, Average *average);
void CopyMeasureToTiny (MeasureTiny *measureT, Measure *measure);
int populate_tiny_values (Catalog *catalog, DVOTinyValueMode mode);
int free_tiny_values (Catalog *catalog);

BoundaryTree *BoundaryTreeLoad(char *filename);
BoundaryTree *BoundaryTreeRead(Header *headerPHU, Header *headerZone, FILE *f);

int BoundaryTreeSave(char *filename, BoundaryTree *tree);
int BoundaryTreeWrite(FILE *f, BoundaryTree *tree);

int BoundaryTreeCellCoords (BoundaryTree *tree, int *zone, int *band, double ra, double dec);
int BoundaryTreeProjection (double *x, double *y, double r, double d, BoundaryTree *tree, int zone, int band);

TessellationTable *TessellationTableLoad(char *filename, int *Ntess);
int TessellationTableSave(char *filename, TessellationTable *tess, int Ntess);
int TessellationPrimaryCellIDs (TessellationTable *tess, int Ntess, int *tessID, int *projID, int *skycellID, double ra, double dec);
void TessellationTableInit (TessellationTable *tess, int Ntess);

void dvo_average_init (Average *average);
void dvo_averageT_init (AverageTiny *average);
void dvo_secfilt_init (SecFilt *secfilt);
void dvo_measure_init (Measure *measure);
void dvo_measureT_init (MeasureTiny *measure);

void InitRegionHosts (RegionHostInfo *hosts, int Nhosts, int NHOSTS);
void FreeRegionHosts (RegionHostInfo *hosts, int Nhosts);
void FreeRegionHostTable (RegionHostTable *table);
RegionHostTable *RegionHostTableLoad (char *catdir, char *rootname);
int RegionHostTableWaitJobs (RegionHostTable *regionHosts, char *file, int lineno);
int RegionHostTableWaitJobsGetIO (RegionHostTable *regionHosts, char *file, int lineno, int VERBOSE);
int RegionHostFindNeighbors (RegionHostTable *table, int Nhost);

# endif // DVO_H
