# include <ohana.h>
# include <dvo.h>
# include <kapa.h>
# include <signal.h>
# include <pthread.h>

/* # define GRID_V1 */
# define GRID_V2
# define NO_IMAGE -100

# define ID_SECF_STACK_PRIMARY 0x00004000

# define NBOOTSTRAP 100

# ifndef MAX_INT
# define MAX_INT 2147483647
# endif

// choose off_t or int depending on full-scale relphot analysis resources
// # define IDX_T off_t
# define IDX_T int 

typedef struct {
  int minID;
  int maxID;
  int *index;
  int Nindex;
  int NINDEX;
} myIndexType;

typedef enum {
  STAGE_CHIP  = 0x01,
  STAGE_WARP  = 0x02,
  STAGE_STACK = 0x04,
} RelphotStages;

typedef enum {
  MODE_ERROR = 0,
  UPDATE_IMAGES,
  UPDATE_AVERAGES,
  PARALLEL_REGIONS,
  PARALLEL_IMAGES,
  APPLY_OFFSETS,
  SYNTH_PHOT,
} RelphotMode;

typedef enum {
    MODE_NONE   = 0,
    MODE_LOAD   = 1,
    MODE_UPDATE = 2,
    MODE_UPDATE_OBJECTS = 3,
    MODE_SYNTH_PHOT = 4,
} ModeType;

// NOTE: this is only used in special cases where we limit photcode ranges
typedef enum {
  PS1_none, 
  PS1_g = 1, 
  PS1_r = 2, 
  PS1_i = 3, 
  PS1_z = 4, 
  PS1_y = 5,
  PS1_w = 6,
} PS1filters;

typedef struct {
  Header PHU;
  Header header[5]; // grizy (matches Nsec in photcodes)
  Matrix matrix[5];
  Coords coords;
  int Nx;
  int Ny;
} SynthZeroPoints;

typedef struct {
  unsigned int start;
  unsigned int stop;
  short photcode;
  float Mcal;
  float dMcal;
  float dMsys;
  unsigned short nFitPhotom;
  short Xm;
  float secz;
  float ubercalDist;
  unsigned int flags;
  char skipCal;		      // if TRUE, this mosaic is incomplete and should not be calibrated
  Coords coords;
} Mosaic; 

typedef enum {
  STATS_NONE, 
  STATS_MEAN, 
  STATS_MEDIAN, 
  STATS_WT_MEAN, 
  STATS_INNER_MEAN, 
  STATS_INNER_WTMEAN, 
  STATS_CHI_INNER_MEAN, 
  STATS_CHI_INNER_WTMEAN
} ListStatsMode;

typedef struct {
  double median;
  double mean;
  double sigma;
  double error;
  double chisq;
  double min;
  double max;
  double Upper80;
  double Lower20;
  double total;
  int    Nmeas;
  ListStatsMode statmode;
} StatType;

typedef struct {
  double *flxlist;           // list of measure.mag values for a given star
  double *errlist;	      // mag errors for a star
  double *wgtlist;	      // weights to use for mean mags
  int    *ranking;	      // weights to use for mean mags
  int    *measSeq;	      // weights to use for mean mags
  int    *msklist;	      // mask modifications
  int     Nlist;

  double *values;
  double *wtvals;
  double *wtlist;
  double *ykeep;
  double *dykeep;
  double *wtkeep;
  double *ysample;
  double *dysample;
  double *wtsample;
  double *bvalue;

} StatDataSet;

typedef struct {
  int Nfew;
  int Ncode;
  int Nsys;
  int Nbad;
  int Ncal;
  int Nmos;
  int Ngrid;

  // NOTE: the following arrays are (possibly) pre-allocated and carried down to each
  // thread.  The psfData are used in all relphot analyses; the others are only used on
  // the final output steps.

  int Nsecfilt;

  StatDataSet  *psfData; // one is allocated for each primary (average) photcode
  StatDataSet *aperData;
  StatDataSet *kronData;

  double *psfqf_list;	      // psfqf for all filters
  double *psfqfperf_list;     // psfqfperf for all filters
  double *stargal_list;	      // stargal for all filters
  uint32_t *photflag_list;      // photflags for all filters

  int Nstargal;
  int Nphotflags;

  int 	*havePS1;	   // this secfilt has synthetic mags
  int 	*haveSYN;	   // this secfilt has synthetic mags
  int 	*measSYN;	   // this measurement is the synthetic mag for this secfilt
  int 	*needSYN;	   // this secfilt mag should use synthetic mags
  float *minSYN;	   // minimum synthetic mag below which synthetic should be forced
  
  float *psfQfMax;	      // max psfQf value for this secfilt
  float *psfQfPerfMax;	      // max psfQfperf value for this secfilt 

  int *Nmeas;		      // count of PS1 exposure (chip) measurements for this secfilt
  int *NmeasGood;	      // count of PS1 exposure (chip) measurements for this secfilt
  int *Next;		      // count of PS1 exposure (chip) measurements for this secfilt
  int *NexpPS1;		      // count of PS1 exposure (chip) measurements for this secfilt
  int *haveUbercal;	      // does this secfilt have any ubercal data?

  int *tessID;		      // tess,proj,skycell to use for warp and diff analysis
  int *projID;
  int *skycellID;

  float *minUbercalDist;

  StatType psfstats;
  StatType apstats;
  StatType kronstats;
} SetMrelInfo;

typedef struct {
  float M;
  float dM;
  float Mchisq;
  int Nsec;
  unsigned int objID;
  unsigned int catID;
  int photcode;
} MeanMag;

typedef struct {
  float Mcal;
  float dMcal;
  float dMagSys;
  short Xm;
  int nFitPhotom;
  int flags;
  unsigned int imageID;
  short ubercalDist;
} ImageMag;

typedef struct {
  AverageTiny *average;	      // array of (minimal) average data
  MeasureTiny *measure;	      // array of (minimal) measure data 
  SecFilt     *secfilt;	      // array of secfilt data (matched to average by Nsecfilt)
  off_t       Naverage;
  off_t       Nmeasure;
} BrightCatalog;

typedef struct {
  float Mcal;
  float dMcal;
  unsigned int imageID;
  unsigned int photom_map_id;
  unsigned int flags;
  int tessID;
  int projID;
  int skycellID;
  unsigned int tzero;
  unsigned char trate;
  short ubercalDist;
} ImageSubset;

typedef struct {
  Catalog *catalog;	      // array of catalogs generated
  int NCATALOG;		      // number of catalogs allocated
  int Ncatalog;		      // number of catalogs generated
  int Nsecfilt;		      // number of catalogs generated
  off_t *NAVERAGE; 	      // allocated Averages per catalog
  off_t *NMEASURE;	      // allocated Measures per catalog
  int   *index;		      // lookup table catID -> catalog[i]
  int   *catIDs;	      // lookup table catID <- catalog[i]
  int    maxID;		      // max catID value to date
} CatalogSplitter;

/* global variables set in parameter file */
# define DVO_MAX_PATH 1024
char   ImageCat[DVO_MAX_PATH];
char   ImageTemplate[DVO_MAX_PATH];
char   CatTemplate[DVO_MAX_PATH];
char   GSCFILE[DVO_MAX_PATH];
char  *CATDIR;
char   CATMODE[16];    /* raw, mef, split, mysql */
char   CATFORMAT[16];  /* internal, elixir, loneos, panstarrs */
char   CameraConfig[DVO_MAX_PATH];
char   CAMERA[64];    /* eg, gpc1 */
char   SKY_TABLE[DVO_MAX_PATH];
int    SKY_DEPTH;  /** XXX EAM : depth of catalog tables, fix usage */
char  *SYNTH_ZERO_POINTS;

// globals for parallel region operations
char  *REGION_FILE;
char  *IMAGE_TABLE;
int    REGION_HOST_ID;

int          HOST_ID;
char        *HOSTDIR;
char        *IMAGES;
char        *BCATALOG;
char        *BOUNDARY_TREE;
ModeType     MODE;

char        *BOUNDARY_TREE;

// XXX deprecate int SET_MREL_VERSION;
int IS_DIFF_DB;

double MAG_LIM;
double SIGMA_LIM;
double IMAGE_SCATTER;
double IMAGE_OFFSET;
double STAR_SCATTER;
double STAR_CHISQ;
double MIN_ERROR;
double IMFIT_SYS_SIGMA_LIM;
double CLOUD_TOLERANCE;

int    PARALLEL;
int    PARALLEL_MANUAL;
int    PARALLEL_SERIAL;
char  *MANUAL_UNIQUER;

int    PARALLEL_REGIONS_MANUAL;

int    NTHREADS;

int    VERBOSE;
int    VERBOSE2;
int    VERBOSE_IMAGE;
int    MOSAIC_ZEROPT;

int    TEST_IMAGE1;
int    TEST_IMAGE2;

int    NLOOP;
int    NGRID;
int    RESET;
int    RESET_ZEROPTS;
int    REPAIR_WARPS;
int    PRESERVE_PS1;
int    UPDATE;
int    SAVE_IMAGE_UPDATES;
int    PLOTSTUFF;
int    SAVEPLOT;
int    SHOW_PARAMS;
char   MOSAICNAME[256];
char   STATMODE[32];
int    STAR_BAD;
int    MEAS_BAD;
int    STAR_TOOFEW;
int    GRID_TOOFEW;
int    IMAGE_TOOFEW;
double IMAGE_GOOD_FRACTION;
int    IMAGE_BAD;
int    FREEZE_IMAGES;
int    FREEZE_MOSAICS;
int    CALIBRATE_STACKS_AND_WARPS;
int    USE_GRID;
int    KEEP_UBERCAL;
char  *OUTROOT;
char  *UPDATE_CATFORMAT;
int    PLOTDELAY;
int    UpdateAverages;
int    ApplyOffsets;
int    SyntheticPhotometry;

char  *PhotcodeList;

int    RELPHOT_GRID_X;
int    RELPHOT_GRID_Y;
int    RELPHOT_GRID_BINNING;

int      *photseclist;
int      Nphotcodes;
PhotCode **photcodes;
// int            PhotSec;
// int            PhotNsec;

PhotCode      *refPhotcode;

int MaxDensityUse;
double MaxDensityValue;

int AreaSelect;
double AreaXmin, AreaXmax, AreaYmin, AreaYmax;

int ImagSelect;
double ImagMin, ImagMax;

int DophotSelect, DophotValue;

double  PlotMmin, PlotMmax, PlotdMmin, PlotdMmax;
enum {black, white, red, orange, yellow, green, blue, indigo, violet};

int TimeSelect;
time_t TSTART, TSTOP;

SkyRegion UserPatch;
char *UserCatalog;

int USE_ALL_IMAGES;
int USE_BASIC_CHECK;
int USE_FULL_OVERLAP;

RelphotStages STAGES;

# ifdef GRID_V1
int setGridMeasure (off_t meas, int cat, double X, double Y);
# endif

# ifdef GRID_V2
int setGridMeasure (off_t meas, int cat, double X, double Y, int ccdnum);
# endif

/*** relphot prototypes ***/
void          ConfigInit          PROTO((int *argc, char **argv));
void          GetConfig           PROTO((char *config, char *field, char *format, int N, void *ptr));
char         *GetPhotnamebyCode   PROTO((PhotCodeData *photcodes, int code));
void          InterpolateGrid     PROTO((float *buffer, int Nx, int Ny, Coords *ccd, Coords *gcoords));
off_t        *SelectRefMosaic     PROTO((Mosaic **refmosaic, off_t *Nimage));
RelphotMode   args                PROTO((int argc, char **argv));
int           args_client         PROTO((int argc, char **argv));
int           bcatalog            PROTO((Catalog *subcatalog, Catalog *catalog, int Ncat));
void          clean_images        PROTO((void));
void          clean_measures      PROTO((Catalog *catalog, int Ncatalog, int final, FlatCorrectionTable *flatcorr));
void          clean_mosaics       PROTO((void));
void          clean_stars         PROTO((Catalog *catalog, int Ncatalog));
int           corner_check        PROTO((double *x1, double *y1, double *x2, double *y2));
void          dumpGrid            PROTO((void));
void          dump_grid           PROTO((void)); 
int           edge_check          PROTO((double *x1, double *y1, double *x2, double *y2));
void          findImages          PROTO((Catalog *catalog, int Ncatalog, int doImageList));
int           findMosaics         PROTO((Catalog *catalog, int Ncatalog, int doMosaicList));

void makeMosaics (Image *image, off_t Nimage, int mergeMcal);
Mosaic *getMosaicForImage (off_t im);
void setMosaicCenters (Image *image, off_t Nimage);

void set_db (FITS_DB *in);
int Shutdown (char *format, ...) OHANA_FORMAT(printf, 1, 2) ;
void TrapSignal (int sig);
void SetProtect (int mode);
int SetSignals (void);

void          freeGridBins        PROTO((int Ncatalog));
void          freeImageBins       PROTO((int Ncatalog, int doImageList));
void          freeMosaicBins      PROTO((int Ncatalog, int doMosaicList));
void          free_catalogs       PROTO((Catalog *catalog, int Ncatalog));
int           gcatalog            PROTO((Catalog *catalog, int FINAL));
Coords       *getCoords           PROTO((off_t meas, int cat));
off_t         getImageEntry       PROTO((off_t meas, int cat));

float         getMcal_alt         PROTO((off_t meas, int cat, FlatCorrectionTable *flatcorr, float Xccd, float Yccd));
float         getMcal             PROTO((off_t meas, int cat, FlatCorrectionTable *flatcorr, Catalog *catalog));
float         getMflat            PROTO((off_t meas, int cat, FlatCorrectionTable *flatcorr, Catalog *catalog));
float         getMgrid            PROTO((off_t meas, int cat));
float         getMmos             PROTO((off_t meas, int cat));
float         getMrel             PROTO((Catalog *catalog, off_t meas, int cat));
short         getUbercalDist      PROTO((off_t meas, int cat));
float         getCenterOffset     PROTO((off_t meas, int cat, Measure *measure, unsigned int *myID));
Image        *getimage            PROTO((off_t N));
Image        *getimages           PROTO((off_t *N, off_t **LineNumber));
ImageSubset  *getimages_subset    PROTO((off_t *N));
void          global_stats        PROTO((Catalog *catalog, int Ncatalog, FlatCorrectionTable *flatcorr, int nloop));
void          initGrid            PROTO((int dX, int dY));
void          initGridBins        PROTO((Catalog *catalog, int Ncatalog));
void          initImageBins       PROTO((Catalog *catalog, int Ncatalog, int doImageList));
void          initImagesSubset    PROTO((ImageSubset *input, off_t *line_number, off_t N));
void          initImages          PROTO((Image *input, off_t *LineNumber, off_t N));
void          initMosaicBins      PROTO((Catalog *catalog, int Ncatalog, int doMosaicList));
void          initMosaicGrid      PROTO((Image *image, off_t Nimage));
void          initMosaics         PROTO((Image *subset, off_t Nsubset, Image *image, char *inSubset, off_t Nimage));
void          initMrel            PROTO((Catalog *catalog, int Ncatalog));
RelphotMode   initialize          PROTO((int argc, char **argv));
void          initialize_client   PROTO((int argc, char **argv));
void          liststats_setmode   PROTO((StatType *stats, char *strmode));
int           liststats           PROTO((double *value, double *dvalue, double *wvalue, int N, StatType *stats));
int           liststats_init      PROTO((StatType *stats));
int           liststats_irls      PROTO((StatDataSet *dataset, int Npoints, StatType *stats));

Catalog      *load_catalogs       PROTO((SkyList *skylist, int *Ncatalog, int hostID, char *hostpath, char *syncfile));
Catalog      *load_catalogs_parallel PROTO((SkyList *sky, int *Ncatalog, char *syncfile));

int           load_images         PROTO((FITS_DB *db, SkyList *skylist, SkyRegion *region, int unlockImages, int UseAllImages));
Image        *select_images       PROTO((SkyList *skylist, Image *timage, off_t Ntimage, char *inSubset, off_t **LineNumber, off_t *Nimage, SkyRegion *region));

int           main                PROTO((int argc, char **argv));
void          mark_images         PROTO((Image *image, off_t Nimage, Image *timage, off_t Ntimage));
void          matchImage          PROTO((Catalog *catalog, off_t meas, int cat, int doImageList));
void          matchMosaics        PROTO((Catalog *catalog, off_t meas, int cat, int doMosaicList));
double        opening_angle       PROTO((double x1, double y1, double x2, double y2, double x3, double y3));
void          plot_chisq          PROTO((Catalog *catalog, int Ncatalog));
void          plot_defaults       PROTO((Graphdata *graphdata));
void          plot_grid           PROTO((Catalog *catalog, FlatCorrectionTable *flatcorr));
void          plot_images         PROTO((void));
void          plot_list           PROTO((Graphdata *graphdata, double *xlist, double *ylist, int N, char *label, char *format, ...) OHANA_FORMAT(printf, 6, 7) );
void          plot_mosaic_fields  PROTO((Catalog *catalog));
void          plot_mosaics        PROTO((void));
void          plot_scatter        PROTO((Catalog *catalog, int Ncatalog, FlatCorrectionTable *flatcorr));
void          plot_star_coords    PROTO((Catalog *catalog, int Ncatalog));
void          plot_stars          PROTO((Catalog *catalog, int Ncatalog));

void          plot_list_add       PROTO((Graphdata *graphdata, double *xlist, double *ylist, int N));
int           get_graph           PROTO((int N));
int           open_graph          PROTO((int N));

void          reload_catalogs     PROTO((SkyList *skylist, FlatCorrectionTable *flatcorr, int hostID, char *hostpath));
int           reload_catalogs_parallel PROTO((SkyList *sky));
int           reload_images       PROTO((FITS_DB *db));
int           setExclusions       PROTO((Catalog *catalog, int Ncatalog, int verbose));
void          setMcal             PROTO((Catalog *catalog, int Poor, FlatCorrectionTable *flatcorr));
void          setMcalFinal        PROTO((void));
int           setMcalOutput       PROTO((Catalog *catalog, int Ncatalog, FlatCorrectionTable *flatcorr));
void          setMgrid            PROTO((Catalog *catalog, FlatCorrectionTable *flatcorr));
int           setMmos             PROTO((Catalog *catalog, int Poor, FlatCorrectionTable *flatcorr));
int           setMrel             PROTO((Catalog *catalog, int Ncatalog, FlatCorrectionTable *flatcorr));
void          setMrelFinal        PROTO((Catalog *catalog, FlatCorrectionTable *flatcorr, int simpleAverage));
int           setMrelOutput       PROTO((Catalog *catalog, int Ncatalog, FlatCorrectionTable *flatcorr));
int           setMave             PROTO((Catalog *catalog, int Ncatalog));
void          set_ZP              PROTO((double ZERO));
int           setrefcode          PROTO((Image *image, off_t Nimage)); 
void          skip_measurements   PROTO((Catalog *catalog, int pass, FlatCorrectionTable *flatcorr));
void          sortA               PROTO((double *X, int N));
void          sortB               PROTO((double *X, double *Y, int N));
void          sortC               PROTO((double *X, double *Y, double *F1, double *F2, int N));
void          sortD               PROTO((double *X, double *Y, double *Z, int N));
StatType      statsImageM         PROTO((Catalog *catalog));
StatType      statsImageN         PROTO((Catalog *catalog, FlatCorrectionTable *flatcorr));
StatType      statsImageX         PROTO((Catalog *catalog));
StatType      statsImagedM        PROTO((Catalog *catalog));
StatType      statsMosaicM        PROTO((Catalog *catalog));
StatType      statsMosaicN        PROTO((Catalog *catalog, FlatCorrectionTable *flatcorr));
StatType      statsMosaicX        PROTO((Catalog *catalog));
StatType      statsMosaicdM       PROTO((Catalog *catalog));
StatType      statsStarN          PROTO((Catalog *catalog, int Ncatalog, int Nsec, int seccode, FlatCorrectionTable *flatcorr));
StatType      statsStarS          PROTO((Catalog *catalog, int Ncatalog, int Nsec));
StatType      statsStarX          PROTO((Catalog *catalog, int Ncatalog, int Nsec));
void          wcatalog            PROTO((Catalog *catalog));
void          wimages             PROTO((void));
void          write_coords        PROTO((Header *header, Coords *coords));
int relphot_objects (SkyList *skylist, int hostID, char *hostpath);
int relphot_images (SkyList *skylist);

void relphot_usage (void);
void relphot_help (int argc, char **argv);

void relphot_client_usage (void);
void relphot_client_help (int argc, char **argv);

off_t getImageByID (off_t ID);

int rationalize_mosaics PROTO((Catalog *catalog, int Ncatalog));
int LimitDensityCatalog (Catalog *subcatalog, Catalog *catalog);

BrightCatalog *BrightCatalogLoad(char *filename);
int BrightCatalogSave(char *filename, BrightCatalog *catalog);
BrightCatalog *BrightCatalogMerge (Catalog *catalog, int Ncatalog);
CatalogSplitter *BrightCatalogSplitInit (int Nsecfilt);
int BrightCatalogSplitFree (CatalogSplitter *catalogs);
int BrightCatalogSplit (CatalogSplitter *catalogs, BrightCatalog *bcatalog);

int ImageSubsetSave(char *filename, ImageSubset *image, off_t Nimage);
ImageSubset *ImageSubsetLoad(char *filename, off_t *nimage);

int client_logger_init (char *dirname);
int client_logger_message (char *format,...);

int MatchImageName (off_t meas, int cat, char *name);
int MatchImageSkycellID (off_t meas, int cat, int myTessID, int myProjectionID, int mySkycellID);
int FindImageSkycellID (off_t meas, int cat, int *myTessID, int *myProjectionID, int *mySkycellID);

int load_tess (char *treefile);
void free_tess (void);
int get_tess_ids (int *tessID, int *projID, int *skycellID, double ra, double dec);
int TessellationIDsByImageName (int *tessID, int *projID, int *skycellID, char *name);

// int BoundaryTreePrimaryCell (char *primaryCellName, double ra, double dec);
// int BoundaryTreePrimaryCellIDs (int *projID, int *skycellID, double ra, double dec);

int print_measure_set_alt (Average *average, SecFilt *secfilt, Measure *measure);
int setMrel_catalog_alt (Catalog *catalog, int Nc, int isSetMrelFinal, FlatCorrectionTable *flatcorr, SetMrelInfo *results, int Nsecfilt);
int setMrelAverageExposure (Catalog *catalog, int cat, off_t ave, int Nsecfilt, int isSetMrelFinal, FlatCorrectionTable *flatcorr, SetMrelInfo *results);
int setMrelAverageStack (Catalog *catalog, int cat, off_t ave, int Nsecfilt, FlatCorrectionTable *flatcorr);
int setMrelAverageForcedWarp (Catalog *catalog, int cat, off_t ave, int Nsecfilt, FlatCorrectionTable *flatcorr, SetMrelInfo *results);

int setGlobalObjStats (Average *average, Measure *measure);

void SetMrelInfoInit (SetMrelInfo *results, int allocLists);
void SetMrelInfoFree (SetMrelInfo *results);
void SetMrelInfoReset (SetMrelInfo *results);
void SetMrelInfoResetObject (SetMrelInfo *results);

void StatDataSetFree (StatDataSet *dataset, int Nsecfilt);
StatDataSet *StatDataSetAlloc (int Nsecfilt, int Nmax);

int init_synthetic_mags ();
int add_synthetic_mags (AverageTiny *average, SecFilt *secfilt, MeasureTiny *measure, off_t *Nmeasure, off_t *Nm);

int relphot_parallel_regions (SkyTable *sky);
int relphot_parallel_images (SkyTable *sky);

int assign_images (FITS_DB *db, RegionHostTable *regionHosts);
int select_images_hostregion (RegionHostTable *hosts, Image *image, off_t Nimage);
int find_host_for_coords (RegionHostTable *regionHosts, double R, double d);
int calculate_image_bounds (Image *image, double *rmin, double *rmax, double *dmin, double *dmax, double Rmid);

int launch_region_hosts (RegionHostTable *regionHosts);

Image *ImageTableLoad(char *filename, off_t *nimage);
int ImageTableSave (char *filename, Image *images, off_t Nimages);

int indexCatalogs (Catalog *catalog, int Ncatalog);
int catID_and_objID_to_seq (int catID, int objID, int *catSeq, off_t *objSeq);
void freeCatalogIndexes (int Ncatalog);

int check_sync_file (char *filename, int nloop);
int clear_sync_file (char *filename);
int update_sync_file (char *filename, int nloop);
char *make_filename (char *dirname, char *hostname, int hostID, char *tailname);

int share_mean_mags (Catalog *catalog, int Ncatalog, RegionHostTable *regionHosts, int nloop);
int slurp_mean_mags (Catalog *catalog, int Ncatalog, RegionHostTable *regionHosts, int nloop);
int set_mean_mags (MeanMag *meanmags, AverageTiny *average, SecFilt *secfilt, int Nsec);
MeanMag *merge_mean_mags (MeanMag *target, int *ntarget, MeanMag *source, int Nsource);

MeanMag *MeanMagLoad(char *filename, off_t *nmeanmags);
int MeanMagSave(char *filename, MeanMag *meanmags, off_t Nmeanmags);

int share_image_mags (RegionHostTable *regionHosts, int nloop);
int slurp_image_mags (RegionHostTable *regionHosts, int nloop);
int set_image_mags (ImageMag *image_mags, Image *image);
ImageMag *merge_image_mags (ImageMag *target, int *ntarget, ImageMag *source, int Nsource);

ImageMag *ImageMagLoad(char *filename, off_t *nimage_mags);
int ImageMagSave(char *filename, ImageMag *image_mags, off_t Nimage_mags);

int markObjects (Catalog *catalog, int Ncatalog);

// in extra.c
int isGPC1chip  (int photcode);
int isGPC1stack (int photcode);
int isGPC1warp  (int photcode);
int isGPC1synth (int photcode);
int whichGPC1filter (int photcode);
int is2MASS (int photcode);
int isTYCHO (int photcode);

int isHSCchip  (int photcode);
int isCFHchip  (int photcode);

int magStatsByRanking (StatDataSet *dataset, StatType *stats);

int SynthZeroPointsLoad (char *filename);
SynthZeroPoints *SynthZeroPointsGet ();

int relphot_synthphot (SkyList *sky, int hostID, char *hostpath);
int relphot_synthphot_parallel (SkyList *sky);

int relphot_synthphot_catalog (Catalog *catalog, SynthZeroPoints *zpts);
int relphot_synthphot_average (Average *average, SecFilt *secfilt, Measure *measure, SynthZeroPoints *zpts);

void setMeasureRank (Catalog *catalog);
int getImageFlags (off_t meas, int cat);
int getMosaicFlags (off_t meas, int cat);

void relphot_free (SkyTable *sky, SkyList *skylist);
void freeImages (char *dbImagePtr);
void relphot_client_free (SkyTable *sky, SkyList *skylist);
void BrightCatalogFree (BrightCatalog *bcatalog);

void put_astrom_table (AstromOffsetTable *myTable);
void free_astrom_table ();

int RepairWarpMeasures (Catalog *catalog);

int FindWarpGroups (void);
int GetWarpSeq (Image *image, int obstime, unsigned short photcode, double Rave, double Dave, float X, float Y);
void FreeWarpGroups (void);

myIndexType *myIndexInit ();
int myIndexFree (myIndexType *myIndex);
int myIndexUpdateLimits (myIndexType *myIndex, int value);
int myIndexSetRange (myIndexType *myIndex);
int myIndexSetEntry (myIndexType *myIndex, int value, int entry);
int myIndexGetEntry (myIndexType *myIndex, int value);

uint64_t CreatePSPSObjectID(double ra, double dec);
uint64_t CreatePSPSStackDetectionID(int sourceID, int imageID, int detID);
uint64_t CreatePSPSDetectionID(double tobs, int ccdid, int detID);

int MakeStackIndex (void);
void FreeStackGroups (void);
int GetStackSeq (Image *image, double Rstk, double Dstk, unsigned short photcode, float X, float Y);
void sort_by_ra (double *R, double *D, int *I, int *S, int N);

void RepairWarpMeasuresOpenLogfile ();
void RepairWarpMeasuresCloseLogfile ();
