#ifndef TA_CALIB_OBJ_H
#define TA_CALIB_OBJ_H

#ifdef __cplusplus
extern "C" {
#endif

#include <dervish.h>
#include <astrotools.h>
#include "arObjectType.h"
#include "arPSFStatus.h"

/* Index used for arrays over the list of filters */
#define TA_NFILTERS 5
typedef enum taFilter
{
  TA_U,				/* u' */
  TA_G,				/* g' */
  TA_R,				/* r' */
  TA_I,				/* i' */
  TA_Z				/* z' */
} TA_FILTER; /* pragma SCHEMA */

/* Floating point value plus error */
typedef struct taFloatErr
{
  float val;			/* value */
  float err;			/* rms error */
} TA_FLOAT_ERR; /* pragma SCHEMA */

/* Info for a single field */
typedef struct taFieldInfo
{
  int field;			/* Field sequence number within a run */
  float seeing[5];		/* Seeing for each frame (order ugriz,
				 * FWHM, arcsecs) */
  double mjd[5];                /* MJD(TAI) when row 0 was read for each
				 * frame (order ugriz) */
  AR_PSF_STATUS status[5];      /* PSF fit status in each filter (ugriz) */
  AR_PSF_STATUS psp_status;     /* Worst (max) PSF status of all 5 filters */
  float psf_ap_correctionErr[5]; /* Photometric error due to imperfect PSF
				 * fit (mags, order ugriz) */
  float sky_frames_sub[5];      /* Global sky value after object subtraction
				 * (luptitudes/arcsec^2, order ugriz) */
} TA_FIELD_INFO; /* pragma SCHEMA */

/* Floating point value plus error and gradiant with isophote */
typedef struct taFloatGrad
{
  float val;			/* value */
  float err;			/* rms error */
  float grad;			/* gradient in value with isophote (per mag) */
} TA_FLOAT_GRAD; /* pragma SCHEMA */

/* A calibrated detection of a survey object in a single filter */
typedef struct taDetection
{
  TA_FLOAT_ERR rowc;		/* Row center (r' coordinates, pixels) */
  TA_FLOAT_ERR colc;		/* Column center (r' coordinates, pixels) */
  TA_FLOAT_ERR sky;		/* Sky flux (luptitudes/square-arcsec) */
  TA_FLOAT_ERR psfCounts;	/* PSF mag (luptitudes) */
  TA_FLOAT_ERR fiberCounts;	/* Mag in 3 arcsec diameter fiber radius
				   (luptitudes) */
  TA_FLOAT_ERR petroCounts;	/* Petrosian mag (luptitudes) */
  TA_FLOAT_ERR petroRad;	/* Petrosian radius (arcsecs) */
  TA_FLOAT_ERR petroR50;	/* Radius with 50 percent of Petrosian light
				   (arcsecs) */
  TA_FLOAT_ERR petroR90;	/* Radius with 90 percent of Petrosian light
				   (arcsecs) */
  TA_FLOAT_ERR q;		/* Stokes Q parameter */
  TA_FLOAT_ERR u;		/* Stokes U parameter */
  TA_FLOAT_GRAD iso_rowc;	/* Isophotal row centroid (pixels) */
  TA_FLOAT_GRAD iso_colc;	/* Isophotal column centroid (pixels) */
  TA_FLOAT_GRAD iso_a;		/* Isophotal major axis (arcsecs) */
  TA_FLOAT_GRAD iso_b;		/* Isophotal minor axis (arcsecs) */
  TA_FLOAT_GRAD iso_phi;	/* Isophotal position angle (degrees) */
  TA_FLOAT_ERR r_deV;		/* DeVaucouler fit scale radius (arcsecs) */
  TA_FLOAT_ERR ab_deV;		/* DeVaucouler fit a/b */
  TA_FLOAT_ERR phi_deV;		/* DeVaucouler position angle (degrees) */
  TA_FLOAT_ERR counts_deV;	/* */
  TA_FLOAT_ERR r_exp;		/* Exponential fit scale radius (arcsecs) */
  TA_FLOAT_ERR ab_exp;		/* Exponential fit a/b */
  TA_FLOAT_ERR phi_exp;		/* Exponential position angle (degrees) */
  TA_FLOAT_ERR counts_exp;	/* */
  TA_FLOAT_ERR counts_model;	/* */
  float texture;		/* Texture parameter */
  float star_L;			/* Star likelihood */
  float exp_L;			/* Exponential disk fit likelihood */
  float deV_L;			/* DeVaucouler disk fit likelihood */
  float fracPSF;		/* Fraction of light in PSF; */
  int flags;			/* Flags */
  int flags2;			/* More flags */
  AR_OBJECT_TYPE type;		/* Object type (star, galaxy, etc) */
  int nProf;			/* Number of profile bins */
  TA_FLOAT_ERR profile[15];	/* Profile bins */
} TA_DETECTION; /* pragma SCHEMA */

/* A calibrated survey object */
typedef struct taCalibObj
{
  TA_FIELD_INFO *field;		/* Pointer to field structure for field this
				   object appears in */
  int run;                      /* Run Id */
  int camCol;                   /* Camera column */
  int rerun;                    /* Rerun number */
  int fieldId;                  /* Field Id */
  int parent;			/* Id of parent --- 0 if none */
  int id;			/* Object ID, unique within its field
				   (1 indexed) */
  int nchild;			/* */
  AR_OBJECT_TYPE objc_type;	/* Object type (star, galaxy, etc) */
  int catId;			/* Known object catalog id --- 0,0 if none */
  int objc_flags;		/* Flags */
  int objc_flags2;		/* More flags */
  TA_FLOAT_ERR objc_rowc;	/* Nominal row position (r' coordinates,
				   pixels) */
  TA_FLOAT_ERR objc_colc;	/* Nominal column position (r' coordinate,
				   pixels) */
  TA_FLOAT_ERR rowv;		/* Row-component of object's velocity
				   (deg/day) */
  TA_FLOAT_ERR colv;		/* Column-component of object's velocity
				   (deg/day) */
  int status;			/* Object status within the survey */
  double ra;			/* J2000 right ascension (r', degrees) */
  double dec;			/* J2000 declination (r', degrees) */
  double lambda;		/* Survey longitude (r', degrees) */
  double eta;			/* Survey latitude (r', degrees) */
  double l;			/* Galactic longitude (lII, r', degrees) */
  double b;			/* Galactic latgitude (bII, r', degrees) */
  float offsetRa[5];            /* */
  float offsetDec[5];           /* */
  int primTarget;		/* Primary target bit mask (science samples) */
  int secTarget;		/* Secondary target bit mask */
  float reddening[5];           /* Reddening in each filter (luptitudes) */
  int   properMotionMatch;	/* match to USNOA2.0 catalog
				 * (0=no match, 1= good match) */
  float properMotionDelta;	/* distance to USNOA2.0 catalog match (asec)*/
  float properMotion;		/* proper motion arcsec/century */
  float properMotionAngle;      /* Direction of proper motion (degrees,
				 * postive north thru east) */
  float usnoBlue;               /* Blue magnitude of matching USNOA2.0 object*/
  float usnoRed;                /* Red magnitude of matching USNOA2.0 object*/
  int   firstMatch;		/* # of FIRST sources matched (0=no match)*/
  int   firstId;                /* ID of one FIRST source matched */
  double firstLambda;           /* Survey longitude of FIRST object (deg) */
  double firstEta;              /* Survey latitude of FIRST object (deg) */
  float firstDelta;		/* distance to FIRST catalog match (arcsec) */
  float firstPeak;		/* Composite FIRST peak flux (mJy) */
  float firstInt;		/* Composite FIRST integrated flux (mJy) */
  float firstrms;		/* Composite FIRST flux error (mJy) */
  float firstmajor;		/* Composite FIRST major axis (a) (arcsec) */
  float firstminor;		/* Composite FIRST minor axis (b) (arcsec) */
  float firstpa;		/* Composite FIRST pa (arcsec) */
  int   rosatMatch;		/* ID of matching ROSAT source */
  float rosatDelta;		/* distance to center of ROSAT error
				 * circle (arcsec) */
  float rosatPosErr;            /* Error in ROSAT position (arcsecs) */
  TA_FLOAT_ERR rosatCPS;	/* ROSAT source countrate (counts/sec) */
  TA_FLOAT_ERR rosatHR1;	/* ROSAT source hardness ratio 1 */
  TA_FLOAT_ERR rosatHR2;	/* ROSAT source hardness ratio 2 */
  float rosatExt;		/* ROSAT source extent parameter */
  float rosatExtLike;           /* ROSAT extent parameter likelihood */
  float rosatDetectLike;        /* ROSAT detection likelihood */
  float rosatExposure;          /* ROSAT exposure time (seconds) */
  unsigned int priority;	/* priority */
  int  matchId[10][5];		/* match link ids(run,camCol,rerun,field,id)*/
  TA_DETECTION detection[5];	/* Inidividual filter detections (in order
				   u, g, r, i, z) */
} TA_CALIB_OBJ; /* pragma SCHEMA */

/* Photometric transformation for a single field from FCALIB */
typedef struct taPTrans
{
  int field;			/* Field */
  TA_FLOAT_ERR a[5];		/* Zero-point */
  TA_FLOAT_ERR b[5];		/* Color term */
  TA_FLOAT_ERR c[5];		/* Color * extinction term */
  TA_FLOAT_ERR k[5];		/* Extinction term */
  float dZero[5];               /* Zeropoint used by photo minus current
				 * zeropoint */
} TA_PTRANS; /* pragma SCHEMA */

/* Forward declarations */
void taGenericChainDestroy(CHAIN *ch);
TBLCOL *taCalibObjsWriteToTbl(const CHAIN *chain);
RET_CODE taCalibObjsReadFromTbl(TBLCOL *tblCol, TA_FIELD_INFO *field,
				int calibrated, CHAIN *chain);
RET_CODE taObjCalibrate(TA_CALIB_OBJ *obj, const TA_PTRANS *ptrans,
			const TRANS *trans[5], const TRANS *transPhoto[5],
			double node, double incl,
			char refFilter, double expTime, int raw);

/*
int taLCaliApply(double counts, double countsErr, double cCounts,
		 double cCountsErr, double intTime, double cIntTime,
		 double airmass, double zeropt, double extinct,
		 double colorTerm, double secColorTerm, int sign,
		 double cosmicColor, double cosmicError, double *calMag,
		 double *calMagErr, int *status);
*/
int taLCaliApply(int filterIndex, int maggies, double counts, double countsErr, double cCounts,
		 double cCountsErr, double intTime, double cIntTime,
		 double airmass, double zeropt, double extinct,
		 double colorTerm, double secColorTerm, int sign,
		 double cosmicColor, double cosmicError, double *calMag,
		 double *calMagErr, int *status);

int taGood(int flags);

#ifdef __cplusplus
}
#endif

#endif
