# 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,
} 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_UNDEF_5        = 0x00004000,  // unused 
  ID_MEAS_PHOTOM_UBERCAL = 0x00008000,  // externally-supplied zero point from ubercal analysis
} 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_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)
} 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_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_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;

// 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);

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;

// XXX DROP? // a reduced-subset structure for relastro
// XXX DROP? typedef struct {
// XXX DROP?   double         R;
// XXX DROP?   double         D;
// XXX DROP?   unsigned short Nmeasure;
// XXX DROP?   int            measureOffset;
// XXX DROP?   uint32_t       flags;
// XXX DROP?   int            catID;
// XXX DROP? } AverageTinyAstro;

// a reduced-subset structure for relphot
typedef struct {
  double         R;
  double         D;
  unsigned short Nmeasure;
  int            measureOffset;
  uint32_t       flags;
  int            catID;
} 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          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;
} MeasureTiny;

/* 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;

} 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 PhotAper (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 PhotXm (PhotCode *code, Average *average, SecFilt *secfilt);
float PhotdM (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);

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_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);
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   *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_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);

# endif // DVO_H

