/* This file defines the library functions available to external programs.  It must be included
 * by programs which are compiled against psphot functions.
 */

#ifndef PSPHOT_H
#define PSPHOT_H

#include <psmodules.h>
#include "psphotErrorCodes.h"

#define PSPHOT_RECIPE "PSPHOT" // Name of the recipe to use

#define PSPHOT_RECIPE_PSF_FAKE_ALLOW "PSF.FAKE.ALLOW" // Name for recipe component permitting fake PSFs

// top-level psphot functions
const char     *psphotCVSName(void);
psString        psphotVersion(void);
psString        psphotSource(void);
psString        psphotVersionLong(void);
bool            psphotVersionHeader(psMetadata *header);
bool            psphotVersionHeaderFull(psMetadata *header);
void            psphotVersionPrint(void);

bool            psphotModelTest (pmConfig *config, const pmFPAview *view, psMetadata *recipe);
bool            psphotInit ();
bool            psphotReadout (pmConfig *config, const pmFPAview *view);
bool            psphotReadoutFindPSF(pmConfig *config, const pmFPAview *view, psArray *inSources);
bool            psphotReadoutKnownSources(pmConfig *config, const pmFPAview *view, psArray *inSources);
bool            psphotReadoutMinimal(pmConfig *config, const pmFPAview *view);

bool            psphotReadoutCleanup (pmConfig *config, pmReadout *readout, psMetadata *recipe, pmDetections *detections, pmPSF *psf, psArray *sources);
bool            psphotDefineFiles (pmConfig *config, pmFPAfile *input);
bool            psphotSetMaskBits (pmConfig *config);
bool            psphotSetMaskRecipe (pmConfig *config, psImageMaskType maskValue, psImageMaskType markValue);

// XXX test functions
psArray        *psphotFakeSources ();

// psphotReadout functions
bool            psphotModelBackground (pmConfig *config, const pmFPAview *view, const char *filename);
bool            psphotSubtractBackground (pmConfig *config, const pmFPAview *view, const char *filename) ;
pmDetections   *psphotFindDetections (pmDetections *detections, pmReadout *readout, psMetadata *recipe);

bool            psphotRoughClass (pmReadout *readout, psArray *sources, psMetadata *recipe, const bool findPsfClump);
bool            psphotBasicDeblend (psArray *sources, psMetadata *recipe);
pmPSF          *psphotChoosePSF (pmReadout *readout, psArray *sources, psMetadata *recipe);
bool            psphotPSFstats (pmReadout *readout, psMetadata *recipe, pmPSF *psf);
bool            psphotMomentsStats (pmReadout *readout, psMetadata *recipe, psArray *sources);
bool            psphotFitSourcesLinear (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf, bool final);
bool            psphotReplaceUnfitSources (psArray *sources, psImageMaskType maskVal);

bool            psphotReplaceAllSources (psArray *sources, psMetadata *recipe);
bool            psphotRemoveAllSources (psArray *sources, psMetadata *recipe);

bool            psphotBlendFit (pmConfig *config, pmReadout *readout, psArray *sources, pmPSF *psf);
bool            psphotBlendFit_Threaded (psThreadJob *job);

psArray        *psphotSourceStats (pmConfig *config, pmReadout *readout, pmDetections *detections);
bool            psphotSourceStats_Threaded (psThreadJob *job);

bool            psphotGuessModels (pmConfig *config, pmReadout *readout, psArray *sources, pmPSF *psf);
bool            psphotGuessModel_Threaded (psThreadJob *job);

bool            psphotMagnitudes (pmConfig *config, pmReadout *readout, const pmFPAview *view, psArray *sources, pmPSF *psf);
bool            psphotMagnitudes_Threaded (psThreadJob *job);

bool            psphotPSFWeights(pmConfig *config, pmReadout *readout, const pmFPAview *view, psArray *sources);
bool            psphotPSFWeights_Threaded (psThreadJob *job);

bool            psphotApResid (pmConfig *config, pmReadout *readout, psArray *sources, pmPSF *psf);
bool            psphotApResidMags_Threaded (psThreadJob *job);

bool            psphotSkyReplace (pmConfig *config, const pmFPAview *view);
bool            psphotExtendedSourceAnalysis (pmReadout *readout, psArray *sources, psMetadata *recipe);
bool            psphotExtendedSourceFits (pmReadout *readout, psArray *sources, psMetadata *recipe);

// thread-related:
bool            psphotSetThreads ();
bool            psphotChooseCellSizes (int *Cx, int *Cy, pmReadout *readout, int nThreads);
bool            psphotCoordToCell (int *group, int *cell, float x, float y, int Cx, int Cy);
psArray        *psphotAssignSources (int Cx, int Cy, psArray *sources);

// used by psphotFindDetections
psImage        *psphotSignificanceImage (pmReadout *readout, psMetadata *recipe, const int pass, psImageMaskType maskVal);
psArray        *psphotFindPeaks (psImage *significance, pmReadout *readout, psMetadata *recipe, const float threshold, const int nMax);
bool            psphotFindFootprints (pmDetections *detections, psImage *significance, pmReadout *readout, psMetadata *recipe, const int pass, psImageMaskType maskVal);
psErrorCode     psphotCullPeaks(const psImage *img, const psImage *weight, const psMetadata *recipe, psArray *footprints);

// generate the detection structure for the supplied array of sources
pmDetections   *psphotDetectionsFromSources (pmConfig *config, psArray *sources);

// used by ApResid
bool            psphotMagErrorScale (float *errorScale, float *errorFloor, psVector *dMag, psVector *dap, psVector *mask, int nGroup);
bool            psphotApResidTrend (pmReadout *readout, pmPSF *psf, int Npsf, int scale, float *errorScale, float *errorFloor, psVector *mask, psVector *xPos, psVector *yPos, psVector *apResid, psVector *dMag);

// basic support functions
void            psphotModelClassInit (void);
bool            psphotGrowthCurve (pmReadout *readout, pmPSF *psf, bool ignore, psImageMaskType maskVal);
bool            psphotSetMaskAndVariance (pmConfig *config, pmReadout *readout, psMetadata *recipe);
void            psphotSourceFreePixels (psArray *sources);

// functions to set the correct source pixels
bool            psphotInitRadiusPSF (const psMetadata *recipe, const pmModelType type);
bool            psphotCheckRadiusPSF (pmReadout *readout, pmSource *source, pmModel *model, psImageMaskType markVal);
bool            psphotCheckRadiusPSFBlend (pmReadout *readout, pmSource *source, pmModel *model, psImageMaskType markVal, float dR);
bool            psphotInitRadiusEXT (psMetadata *recipe, pmModelType type);
bool            psphotCheckRadiusEXT (pmReadout *readout, pmSource *source, pmModel *model, psImageMaskType markVal);

// output functions
bool            psphotAddPhotcode (psMetadata *recipe, pmConfig *config, const pmFPAview *view, const char *filerule);
bool            psphotDumpMoments (psMetadata *recipe, psArray *sources);
psMetadata     *psphotDefineHeader (psMetadata *recipe);
int             psphotSaveImage (psMetadata *header, psImage *image, char *filename);
bool            psphotDumpConfig (pmConfig *config);
pmReadout      *psphotSelectBackground (pmConfig *config, const pmFPAview *view);
pmReadout      *psphotSelectBackgroundStdev (pmConfig *config, const pmFPAview *view);

// PSF / DBL / EXT evaluation functions
bool            psphotEvalPSF (pmSource *source, pmModel *model);
bool            psphotEvalDBL (pmSource *source, pmModel *model);
bool            psphotEvalEXT (pmSource *source, pmModel *model);

//  functions to support the source fitting process
bool            psphotInitLimitsPSF (psMetadata *recipe, pmReadout *readout);
bool            psphotInitLimitsEXT (psMetadata *recipe);
bool            psphotFitBlend (pmReadout *readout, pmSource *source, pmPSF *psf, psImageMaskType maskVal, psImageMaskType markVal);
bool            psphotFitBlob (pmReadout *readout, pmSource *source, psArray *sources, pmPSF *psf, psImageMaskType maskVal, psImageMaskType markVal);
bool            psphotFitPSF (pmReadout *readout, pmSource *source, pmPSF *psf, psImageMaskType maskVal, psImageMaskType markVal);
pmModel        *psphotFitEXT (pmReadout *readout, pmSource *source, pmModelType modelType, psImageMaskType maskVal, psImageMaskType markVal);
psArray        *psphotFitDBL (pmReadout *readout, pmSource *source, psImageMaskType maskVal, psImageMaskType markVal);

// functions to support simultaneous multi-source fitting
bool            psphotFitSet (pmSource *oneSrc, pmModel *oneModel, char *fitset, pmSourceFitMode mode, psImageMaskType maskVal);

// plotting functions (available if libkapa is installed)
bool            psphotPlotMoments (pmConfig *config, pmFPAview *view, psArray *sources);
bool            psphotPlotPSFModel (pmConfig *config, pmFPAview *view, psArray *sources);
bool            psphotFitInit ();
bool            psphotFitSummary ();

bool            psphotMergeSources (psArray *oldSources, psArray *newSources);
bool            psphotLoadExtSources (pmConfig *config, const pmFPAview *view, psArray *sources);
psArray        *psphotLoadPSFSources (pmConfig *config, const pmFPAview *view);

pmPSF          *psphotLoadPSF (pmConfig *config, const pmFPAview *view, psMetadata *recipe);
bool            psphotSetHeaderNstars (psMetadata *recipe, psArray *sources);
bool            psphotAddNoise (pmReadout *readout, psArray *sources, psMetadata *recipe);
bool            psphotSubNoise (pmReadout *readout, psArray *sources, psMetadata *recipe);
bool            psphotAddOrSubNoise (pmReadout *readout, psArray *sources, psMetadata *recipe, bool add);
bool            psphotRadialPlot (int *kapa, const char *filename, pmSource *source);
bool            psphotSourcePlots (pmReadout *readout, psArray *sources, psMetadata *recipe);
bool            psphotMosaicSubimage (psImage *outImage, pmSource *source, int Xo, int Yo, int DX, int DY, bool normalize);

bool            psphotAddWithTest (pmSource *source, bool useState, psImageMaskType maskVal);
bool            psphotSubWithTest (pmSource *source, bool useState, psImageMaskType maskVal);
bool            psphotSetState (pmSource *source, bool curState, psImageMaskType maskVal);
bool            psphotDeblendSatstars (psArray *sources, psMetadata *recipe);
bool            psphotSourceSize (pmConfig *config, pmReadout *readout, psArray *sources, psMetadata *recipe, long first);

bool            psphotMakeResiduals (psArray *sources, psMetadata *recipe, pmPSF *psf, psImageMaskType maskVal);

pmModel        *psphotPSFConvModel (pmReadout *readout, pmSource *source, pmModelType modelType, psImageMaskType maskVal, psImageMaskType markVal, int psfSize);

psKernel       *psphotKernelFromPSF (pmSource *source, int nPix);

bool            psphotRadialProfile (pmSource *source, psMetadata *recipe, psImageMaskType maskVal);
bool            psphotPetrosian (pmSource *source, psMetadata *recipe, psImageMaskType maskVal);
bool            psphotIsophotal (pmSource *source, psMetadata *recipe, psImageMaskType maskVal);
bool            psphotAnnuli (pmSource *source, psMetadata *recipe, psImageMaskType maskVal);
bool            psphotKron (pmSource *source, psMetadata *recipe, psImageMaskType maskVal);

// psphotVisual functions
bool psphotVisualShowImage (pmReadout *readout);
bool psphotVisualShowBackground (pmConfig *config, const pmFPAview *view, pmReadout *readout);
bool psphotVisualShowSignificance (psImage *image);
bool psphotVisualShowPeaks (pmDetections *detections);
bool psphotVisualShowFootprints (pmDetections *detections);
bool psphotVisualShowMoments (psArray *sources);
bool psphotVisualPlotMoments (psMetadata *recipe, psArray *sources);
bool psphotVisualShowRoughClass (psArray *sources);
bool psphotVisualShowPSFStars (psMetadata *recipe, pmPSF *psf, psArray *sources);
bool psphotVisualShowSatStars (psMetadata *recipe, pmPSF *psf, psArray *sources);
bool psphotVisualShowPSFModel (pmReadout *readout, pmPSF *psf);
bool psphotVisualPlotRadialProfile (int myKapa, pmSource *source, psImageMaskType maskVal);
bool psphotVisualPlotRadialProfiles (psMetadata *recipe, psArray *sources);
bool psphotVisualShowFlags (psArray *sources);
bool psphotVisualShowSourceSize (pmReadout *readout, psArray *sources);
bool psphotVisualShowResidualImage (pmReadout *readout);
bool psphotVisualPlotApResid (psArray *sources);
bool psphotVisualPlotSourceSize (psArray *sources);

bool psphotImageQuality (psMetadata *recipe, psArray *sources);

// structures & functions to support psf-convolved model fitting

// pmPCMData : PSF Convolved Model data storage structure
typedef struct {
    psImage *model;
    psArray *dmodels;
    psImage *modelConv;
    psArray *dmodelsConv;
} pmPCMData;


// psf-convolved model fitting
bool psphotModelWithPSF_LMM (
    psMinimization *min,
    psImage *covar,
    psVector *params,
    psMinConstraint *constraint,
    pmSource *source,
    const psKernel *psf,
    psMinimizeLMChi2Func func);

psF32 psphotModelWithPSF_SetABX(
    psImage  *alpha,
    psVector *beta,
    const psVector *params,
    const psVector *paramMask,
    pmPCMData *pcm,
    const pmSource *source,
    const psKernel *psf,
    psMinimizeLMChi2Func func);

pmPCMData *pmPCMDataAlloc (
    const psVector *params,
    const psVector *paramMask,
    pmSource *source);

psImage *pmPCMDataSaveImage (pmPCMData *pcm);

int psphotKapaOpen ();
bool psphotKapaClose ();
bool psphotImageBackgroundCellHistogram (psVector *values, float mean, float sigma, int ix, int iy);
bool psphotDiagnosticPlots (const pmConfig *config, const char *name, ...);

bool psphotMakeFluxScale (psImage *image, psMetadata *recipe, pmPSF *psf);
bool psphotMakeGrowthCurve (pmReadout *readout, psMetadata *recipe, pmPSF *psf);
bool psphotDumpPSFStars (pmReadout *readout, pmPSFtry *try, float radius, psImageMaskType maskVal, psImageMaskType markVal);

bool psphotCheckStarDistribution (psArray *sources, psArray *stars, pmPSFOptions *options);
int psphotSupplementStars (psArray *stars, psArray *sources, psImageBinning *binning, int ix, int iy);


// Create a background model for a readout
// Essentially identical to psphotModelBackground, but with a more convenient API for outsiders.
psImage *psphotBackgroundModel(pmReadout *ro, // Readout for which to generate background model
                               const pmConfig *config // Configuration
    );


#endif
