#ifndef amdms_H
#define amdms_H

/* the following constants represent AMBER specific limits */
#define amdmsMAX_TELS                     3 /* 2 or 3 telescopes are used */
#define amdmsMAX_TRAINS                   3 /* 2 or 3 delay lines are used */
#define amdmsMAX_COLS                     5 /* number of subwindow columns */
#define amdmsMAX_ROWS                     3 /* number of subwindow rows */
#define amdmsMAX_REGIONS                  (amdmsMAX_COLS*amdmsMAX_ROWS)
#define amdmsMAX_COLNAME_LEN              17
#define amdmsMAX_TARTYP_LEN               4
#define amdmsMAX_BTBL_COLS                32

#define amdmsGOOD_PIXEL                   1.0
#define amdmsBAD_PIXEL                    0.0

#define amdmsFIT_DATA_BIAS_ROW            0
#define amdmsFIT_DATA_SATURATION_ROW      1
#define amdmsFIT_CHI_SQR_ROW              2
#define amdmsFIT_ABS_DIST_SQR_ROW         3
#define amdmsFIT_REL_DIST_SQR_ROW         4
#define amdmsFIT_LOWER_LIMIT_ROW          5
#define amdmsFIT_UPPER_LIMIT_ROW          6
#define amdmsFIT_A0_ROW                   7
#define amdmsFIT_A0_STDEV_ROW             8
#define amdmsFIT_A1_ROW                   9
#define amdmsFIT_A1_STDEV_ROW             10
#define amdmsFIT_A2_ROW                   11
#define amdmsFIT_A2_STDEV_ROW             12
#define amdmsFIT_NROWS                    (amdmsFIT_A2_STDEV_ROW + 1)

#define amdmsPIXEL_STAT_MEAN_ROW          0
#define amdmsPIXEL_STAT_VAR_ROW           1
#define amdmsPIXEL_STAT_NROWS             (amdmsPIXEL_STAT_VAR_ROW + 1)

#define amdmsPIXEL_BIAS_ROW               0
#define amdmsPIXEL_BIAS_NROWS             (amdmsPIXEL_BIAS_ROW + 1)

#define amdmsBAD_PIXEL_ROW                0
#define amdmsBAD_PIXEL_NROWS              (amdmsBAD_PIXEL_ROW + 1)

#define amdmsFLATFIELD_ROW                0
#define amdmsFLATFIELD_NROWS              (amdmsFLATFIELD_ROW + 1)
#define amdmsFLATFIELD_FIT_NROWS          (amdmsFIT_A0_STDEV_ROW + 1)

#define amdmsCONVERSION_FACTOR_ROW        0
#define amdmsCONVERSION_FACTOR_NROWS      (amdmsCONVERSION_FACTOR_ROW + 1)
#define amdmsCONVERSION_FACTOR_FIT_NROWS  (amdmsFIT_A0_STDEV_ROW + 1)

#define amdmsREADOUT_NOISE_ROW            0
#define amdmsREADOUT_NOISE_NROWS          (amdmsREADOUT_NOISE_ROW + 1)

#define amdmsPHOTON_NOISE_ROW             0
#define amdmsPHOTON_NOISE_NROWS           (amdmsPHOTON_NOISE_ROW + 1)

#define amdmsNONLINEARITY_LIMIT_ROW       0
#define amdmsNONLINEARITY_A0_ROW          1
#define amdmsNONLINEARITY_A1_ROW          2
#define amdmsNONLINEARITY_DEGREE          2
#define amdmsNONLINEARITY_NROWS           (amdmsNONLINEARITY_A0_ROW + amdmsNONLINEARITY_DEGREE)
#define amdmsNONLINEARITY_FIT_NROWS       (amdmsFIT_A2_STDEV_ROW + 1)

#define amdmsPTC_NROWS                    (amdmsFIT_A1_STDEV_ROW + 1)

#define amdmsFFT_DATA_ROW                 0
#define amdmsFFT_NROWS                    (amdmsFFT_DATA_ROW + 1)

#define amdmsFUZZY_DATA_ROW               0
#define amdmsFUZZY_NROWS                  (amdmsFUZZY_DATA_ROW + 1)

#define amdmsPARTICLE_EVENT_FIRST_IMG_ROW 0
#define amdmsPARTICLE_EVENT_LAST_IMG_ROW  1
#define amdmsPARTICLE_EVENT_NROWS         (amdmsPARTICLE_EVENT_LAST_IMG_ROW + 1)

#define amdmsELECTRONIC_BIAS_ROW          0
#define amdmsELECTRONIC_BIAS_NROWS        (amdmsELECTRONIC_BIAS_ROW + 1)

#define amdmsDARK_CURRENT_NROWS           (amdmsFIT_A1_STDEV_ROW + 1)

#define amdmsHISTOGRAM_ROW                0
#define amdmsHISTOGRAM_NROWS              (amdmsHISTOGRAM_ROW + 1)

#define amdmsMAX_INPUTS    128
#define amdmsMAX_OUTPUTS   32
#define amdmsMAX_NAME_LEN  256
#define amdmsMAX_STRIPES   16
#define amdmsMAX_LIMITS    21   /* depends on the number of USE_ flags */

#define amdmsABS_LOWER_LIMIT    1
#define amdmsABS_EQUAL_LIMIT    2
#define amdmsABS_UPPER_LIMIT    3
#define amdmsREL_LOWER_LIMIT    4
#define amdmsREL_EQUAL_LIMIT    5
#define amdmsREL_UPPER_LIMIT    6
#define amdmsSIGMA_LOWER_LIMIT  7
#define amdmsSIGMA_EQUAL_LIMIT  8
#define amdmsSIGMA_UPPER_LIMIT  9

#define amdmsUSE_NOTHING           0
#define amdmsUSE_PS_MEAN_PIXEL     (1 << 0)
#define amdmsUSE_PS_VAR_PIXEL      (1 << 1)
#define amdmsUSE_PIXEL_BIAS        (1 << 2)
#define amdmsUSE_FLATFIELD         (1 << 3)
#define amdmsUSE_BAD_PIXEL         (1 << 4)
#define amdmsUSE_CONVERSION_FACTOR (1 << 5)
#define amdmsUSE_READOUT_NOISE     (1 << 6)
#define amdmsUSE_PHOTON_NOISE      (1 << 7)
#define amdmsUSE_DATA_BIAS         (1 << 8)
#define amdmsUSE_DATA_SATURATION   (1 << 9)
#define amdmsUSE_FIT_CHI_SQR       (1 << 10)
#define amdmsUSE_FIT_ABS_DIST_SQR  (1 << 11)
#define amdmsUSE_FIT_REL_DIST_SQR  (1 << 12)
#define amdmsUSE_FIT_LOWER_LIMIT   (1 << 13)
#define amdmsUSE_FIT_UPPER_LIMIT   (1 << 14)
#define amdmsUSE_FIT_A0            (1 << 15)
#define amdmsUSE_FIT_A0_STDEV      (1 << 16)
#define amdmsUSE_FIT_A1            (1 << 17)
#define amdmsUSE_FIT_A1_STDEV      (1 << 18)
#define amdmsUSE_FIT_A2            (1 << 19)
#define amdmsUSE_FIT_A2_STDEV      (1 << 20)

#define amdmsNO_CORRECTION               0
#define amdmsELECTRONIC_BIAS_CORRECTION  (1 << 0)
#define amdmsPIXEL_BIAS_CORRECTION       (1 << 1)
#define amdmsGLOBAL_BIAS_CORRECTION      (1 << 2)
#define amdmsROW_OFFSET_CORRECTION       (1 << 3)
#define amdmsFLATFIELD_CORRECTION        (1 << 4)
#define amdmsNONLINEARITY_CORRECTION     (1 << 5)
#define amdmsBAD_PIXEL_CORRECTION        (1 << 6)

#define amdmsDEFAULT_IN_FORMAT   amdmsCUBE_FORMAT
#define amdmsDEFAULT_OUT_FORMAT  amdmsCUBE_FORMAT
#define amdmsDEFAULT_MAP_FORMAT  amdmsCUBE_FORMAT

/* completion code */
typedef enum {amdmsFAILURE, amdmsSUCCESS} amdmsCOMPL;

/* boolean data type */
typedef enum {amdmsFALSE, amdmsTRUE} amdmsBOOL;

/* severity */
typedef enum {
  amdmsDEBUG, amdmsINFO, amdmsNOTICE, amdmsWARNING, amdmsERROR, amdmsFATAL
} amdmsSEVERITY;


/****************************************************************/
/* structure for storing error messages                         */
/****************************************************************/
typedef struct {
  char           timeStamp[32]; /* time stamp as a string       */
  amdmsSEVERITY  severity;      /* severity (see amdmsSEVERITY) */
  const char    *locFile;       /* filename                     */
  int            locLine;       /* line number in file          */
  char           text[1024];    /* additional formatted text    */
} amdmsEVENT;
/****************************************************************/


typedef float amdmsPIXEL;


/***********************************************************/
/* algorithm for electronic bias compensation              */
/***********************************************************/
typedef enum {
  amdmsEBA_MAP,            /* use a electronic bias map    */
  amdmsEBA_SIMPLE_EXP1D,   /* use a exponential curve      */
  amdmsEBA_SIMPLE_SMOOTH1D /* smooth the pixel row offsets */
} amdmsEBIAS_ALGO;
/***********************************************************/


/***********************************************************************/
/* direction for projecting pixels                                     */
/***********************************************************************/
typedef enum {
  amdmsNO_PROJ,         /* no projection                               */
  amdmsHOROZONTAL_PROJ, /* mean values are calculated per pixel line   */
  amdmsVERTICAL_PROJ    /* mean values are calculated per pixel column */
} amdmsPROJ_MODE;
/***********************************************************************/


/************************************************************/
/* algorithm for conversion factor calculation              */
/************************************************************/
typedef enum {
  amdmsCFA_AMBER,        /* (old) algorithm used for AMBER  */
  amdmsCFA_GLOBAL_LINE,  /* a straight line with all values */
  amdmsCFA_CENTRAL_LINE, /* use only the central part       */
  amdmsCFA_LOCAL_PAIRS   /* use pairs of pixel              */
} amdmsCF_ALGO;
/************************************************************/


/*********************************************************/
/* content definition for a 2-d histogram axis           */
/*********************************************************/
typedef enum {
  amdmsHC_EXPTIME,    /* use the exposure time as value  */
  amdmsHC_MEAN,       /* use the mean intensity as value */
  amdmsHC_VARIANCE,   /* use the variance as value       */
  amdmsHC_NOISE       /* use the noise as value          */
} amdmsHISTO_CONTENT;
/*********************************************************/


/**********************************************************/
/* axis scaling definition                                */
/**********************************************************/
typedef enum {
  amdmsHS_LINEAR, /* use a linear scaling for an axis     */
  amdmsHS_SQRT,   /* use a sqare root scaling for an axis */
  amdmsHS_LOG     /* use a logarithmic scaling            */
} amdmsHISTO_SCALE;
/**********************************************************/


/**********************************************************************/
/* file content definition                                            */
/**********************************************************************/
typedef enum {
  amdmsUNKNOWN_CONTENT,               /* unknown                      */
  amdmsIMAGING_DETECTOR_CONTENT,      /* subwindow/region setup       */
  amdmsIMAGING_DATA_CONTENT,          /* imaging data (images)        */
  amdmsAMBER_WAVE_CONTENT,            /* AMBER wavelength mapping     */
  amdmsPIXEL_STAT_CONTENT,            /* pixel flux mean and variance */
  amdmsPIXEL_BIAS_CONTENT,            /* pixel bias map               */
  amdmsBAD_PIXEL_CONTENT,             /* bad pixel map                */
  amdmsFLATFIELD_CONTENT,             /* flatfield map                */
  amdmsFLATFIELD_FIT_CONTENT,         /* flatfield fit                */
  amdmsCONVERSION_FACTOR_CONTENT,     /* conversion factor [e-/DU]    */
  amdmsREADOUT_NOISE_CONTENT,         /* readout noise [e-]           */
  amdmsPHOTON_NOISE_CONTENT,          /* pixel noise as photon noise  */
  amdmsNONLINEARITY_CONTENT,          /* nonlinearity coeefficients   */
  amdmsNONLINEARITY_FIT_CONTENT,      /* nonlinearity fit             */
  amdmsPTC_CONTENT,                   /* photon transfer curve fit    */
  amdmsFFT_CONTENT,                   /* fast fourier transform       */
  amdmsFUZZY_CONTENT,                 /* fuzzy bad pixel map counter  */
  amdmsPARTICLE_EVENT_CONTENT,        /* particle events              */
  amdmsELECTRONIC_BIAS_CONTENT,       /* electronic bias map          */
  amdmsDARK_CURRENT_CONTENT,          /* dark current map (line)      */
  amdmsHISTOGRAM_CONTENT              /* 2-d histogram                */
} amdmsFITS_CONTENT;
/**********************************************************************/


/***************************************************/
/* file format definition                          */
/***************************************************/
typedef enum {
  amdmsUNKNOWN_FORMAT, /* unknown                  */
  amdmsCUBE_FORMAT,    /* FITS image or cube       */
  amdmsTABLE_FORMAT,   /* FITS binary table        */
  amdmsC40_FORMAT,     /* speckle C40/Astro format */
  amdmsIXON_FORMAT,    /* iXon camera format       */
  amdmsSCAM_FORMAT,    /* Sensicam camera format   */
  amdmsJPEG_FORMAT,    /* JPEG image format        */
  amdmsTEXT_FORMAT     /* ASCII text format        */
} amdmsFITS_FORMAT;
/***************************************************/


/**************************************************/
/* data type definition                           */
/**************************************************/
typedef enum {
  amdmsUNKNOWN_TYPE, /* unknown                   */
  amdmsBYTE_TYPE,    /* byte (8 bit integer)      */
  amdmsSHORT_TYPE,   /* short (16 bit integer)    */
  amdmsINT_TYPE,     /* int (32 bit integer)      */
  amdmsLONG_TYPE,    /* long (32/64 bit integer)  */
  amdmsFLOAT_TYPE,   /* float (32 bit)            */
  amdmsDOUBLE_TYPE,  /* double (64 bit)           */
  amdmsSTRING_TYPE   /* char * (arbitrary length) */
} amdmsFITS_TYPE;
/**************************************************/


/*************************************************************/
/* define which data should be imported from C40 data        */
/*************************************************************/
typedef enum {
  amdmsREAD_DIFFERENCE_IMAGE, /* import the difference image */
  amdmsREAD_FIRST_READ,       /* import the first read       */
  amdmsREAD_SECOND_READ       /* import the second read      */
} amdmsREAD_TYPE;
/*************************************************************/


/*******************************************************/
/* 2-dimensional image (pixel array)                   */
/*******************************************************/
typedef struct {
  int         nx;    /* image width                    */
  int         ny;    /* image height                   */
  double      index; /* image index value (from input) */
  amdmsPIXEL *data;  /* image data                     */
} amdmsDATA;
/*******************************************************/


/**********************************************/
/* file flags                                 */
/**********************************************/
typedef struct {
  amdmsFITS_CONTENT content : 8; /* content   */
  amdmsFITS_FORMAT  format  : 8; /* format    */
  amdmsFITS_TYPE    type    : 8; /* data type */
} amdmsFITS_FLAGS;
/**********************************************/


/****************************************************/
/* list of fits file names including flags          */
/****************************************************/
typedef struct {
  amdmsFITS_FLAGS   defFlags; /* default fits flags */
  int               nNames;   /* number of names    */
  char            **names;    /* list of names      */
  amdmsFITS_FLAGS  *flags;    /* list of flags      */
} amdmsFILE_LIST;
/****************************************************/


/********************************************************/
/* region definition (rectangular subwindow)            */
/********************************************************/
typedef struct {
  int      x;       /* first pixel column of the region */
  int      y;       /* first pixel row of the region    */
  int      width;   /* width of the region              */
  int      height;  /* height of the region             */
  int      offset;  /* offset into data array           */
  int      size;    /* number of pixels in region       */
} amdmsREGION;
/********************************************************/


/************************************************************************/
/* specification of one particle event                                  */
/************************************************************************/
typedef struct {
  int         idx;        /* pixel index                                */
  int         x;          /* x coordinate                               */
  int         y;          /* y coordinate                               */
  amdmsBOOL   isBad;      /* flag if pixel is a bad pixel               */
  amdmsBOOL   isPE;       /* flag if pixel is a detected particle event */
  amdmsBOOL   isUpToDate; /* flag if mean and variance is up to date    */
  int         nextPE;     /* index of next PE (ring structure)          */
  int         prevPE;     /* index of previous PE (ring structure)      */
  int         start;      /* first affected image number                */
  int         end;        /* last affected image number                 */
  float       mean;       /* new flux mean                              */
  float       var;        /* new flux variance                          */
  amdmsPIXEL *values;     /* flux data for this pixel                   */
} amdmsPARTICLE_EVENT;
/************************************************************************/


/*********************************************************************/
/* particle event setup                                              */
/*********************************************************************/
typedef struct {
  amdmsBOOL            peFlag;  /* flag if PE detection is requested */
  float                peLimit; /* variance limit for PE detection   */
  int                  nPE;     /* number of particle events         */
  int                  nSPE;    /* number of single particle events  */
  int                  nValues; /* number of values for each pixel   */
  amdmsPARTICLE_EVENT *pes;     /* array of particle events          */
} amdmsPARTICLE_EVENT_SETUP;
/*********************************************************************/


/**************************************************/
/* setup for one stripe                           */
/**************************************************/
typedef struct {
  int    pos;   /* stripe border (left or bottom) */
  int    size;  /* stripe size (width or height)  */
  int    flags; /* stripe flags (amdmsUSE_...)    */
} amdmsSTRIPE;
/**************************************************/


/*************************************************************************/
/* stripe setup (horizontal and vertical stripes, regions as defaults)   */
/*************************************************************************/
typedef struct {
  int         nHStripes;                 /* number of horizontal stripes */
  amdmsSTRIPE hStripes[amdmsMAX_STRIPES];/* horizontal stripes           */
  int         nVStripes;                 /* number of vertical stripes   */
  amdmsSTRIPE vStripes[amdmsMAX_STRIPES];/* vertical stripes             */
} amdmsSTRIPE_SETUP;
/*************************************************************************/


/***************************************************************************/
/* specification for calibration                                           */
/***************************************************************************/
typedef struct {
  int              detNX;         /* detector width in pixels (512)        */
  int              detNY;         /* detector height in pixels (512)       */
  /***** compensation specification (input) ********************************/
  int              corrFlag;      /* flags for requested compensations     */
  /***** detector calibration maps (input) *********************************/
  amdmsFILE_LIST   mapFiles;      /* list of filenames                     */
  /***** shielded area for 1/f noise compensation (input) ******************/
  int              saWinX;        /* left border                           */
  int              saWinWidth;    /* width                                 */
  int              saWinY;        /* bottom border                         */
  int              saWinHeight;   /* height                                */
  int              saGaussHeight; /* number of used pixel lines            */
  float            saGaussSigma;  /* sigma for vertical gauss profile      */
  /***** bad pixel interpolation (input) ***********************************/
  int              bpiRadius;     /* radius of area used for interpolation */
  amdmsPIXEL       bpiSigma;      /* digma for gauss profile               */
  amdmsPIXEL      *bpiWeights;    /* array of calculated weights           */
  /***** bad pixel map *****************************************************/
  amdmsDATA        bpmData;       /* flagged pixels                        */
  int              nGoodPixels;   /* number of good pixels                 */
  /***** electronic bias map (input) ***************************************/
  amdmsDATA        ebmData;       /* individual electronic bias            */
  /***** pixel bias map (input) ********************************************/
  amdmsDATA        pbmData;       /* individual pixel bias                 */
  /***** flatfield map (input) *********************************************/
  amdmsDATA        ffmData;       /* individual pixel gain                 */
  /***** nonlinearity map (input) ******************************************/
  amdmsDATA        nlmDataLimit;  /* flux limit                            */
  amdmsDATA        nlmDataA0;     /* parameter for gain                    */
  amdmsDATA        nlmDataA1;     /* parameter for curvature               */
  /***** particle event map (input) ****************************************/
  amdmsDATA        pemDataFI;     /* number of first affected image        */
  amdmsDATA        pemDataLI;     /* number of last affected image         */
  /***** detector offset (calculated) **************************************/
  amdmsPIXEL       globalBias;    /* global bias for current image         */
  /***** row offset (1/f noise) (calculated) *******************************/
  amdmsPIXEL      *rowOffsets;    /* row offsets for current image         */
  int             *rowGood;       /* number of goob pixels for each row    */
  amdmsPIXEL      *rowWeight;     /* ???                                   */
  amdmsPIXEL      *rowSum;        /* ???                                   */
  /***** electronic bias parameters ****************************************/
  amdmsEBIAS_ALGO  ebAlgo;        /* algorithm to use for compensation     */
  double          *ebX;           /* ???                                   */
  double          *ebY;           /* ???                                   */
  double          *ebYe;          /* ???                                   */
} amdmsCALIBRATION_SETUP;
/***************************************************************************/


/***************************************************************/
/* specification for data filtering                            */
/***************************************************************/
typedef struct {
  /***** images of interest (input) ****************************/
  amdmsBOOL ioiFlag;   /* flag if image range is specified     */
  int       ioiFrom;   /* number of the first image            */
  int       ioiTo;     /* number of the last image (including) */
  /***** area of interest (input) ******************************/
  amdmsBOOL aoiFlag;   /* flag is image area is specified      */
  int       aoiX;      /* left border of image area            */
  int       aoiY;      /* bottom border of image area          */
  int       aoiWidth;  /* width of image area                  */
  int       aoiHeight; /* height of image area                 */
  /***** pixel of interest (input) *****************************/
  amdmsBOOL poiFlag;   /* flag if pixel position is specified  */
  int       poiX;      /* x position                           */
  int       poiY;      /* y position                           */
} amdmsDATA_FILTER_SETUP;
/***************************************************************/


/**********************************************************/
/* limit definition for the bad pixel map generation      */
/**********************************************************/
typedef struct {
  int        flag;  /* flag (amdmsUSE_XXX)                */
  int        type;  /* type of the limit (amdmsXXX_LIMIT) */
  amdmsPIXEL value; /* limit value                        */
  amdmsPIXEL ref;   /* reference value for fuzzy approach */
} amdmsLIMIT;
/**********************************************************/


/*******************************************************************/
/* specification for the bad pixel map limits                      */
/*******************************************************************/
typedef struct {
  int         nLimits;                 /* number of defined limits */
  amdmsLIMIT  limits[amdmsMAX_LIMITS]; /* list of defined limits   */
} amdmsLIMIT_SETUP;
/*******************************************************************/


/********************************************************************/
/* setup for an axis of a 2-d histogram                             */
/********************************************************************/
typedef struct {
  amdmsHISTO_CONTENT     content; /* content to be used for an axis */
  amdmsHISTO_SCALE       scale;   /* scaling for an axis            */
  int                    steps;   /* number of steps for this axis  */
  double                 min;     /* minimum value for this axis    */
  double                 max;     /* maximum value for this axis    */
} amdmsHISTO_SETUP;
/********************************************************************/


/***************************************************************************/
/* environment for all algorithms                                          */
/***************************************************************************/
typedef struct {
  int                     detNX;     /* detector width in pixels (512)     */
  int                     detNY;     /* detector height in pixels (512)    */
  int                     nReads;    /* number of reads in input files (1) */
  amdmsBOOL               q4Flag;    /* flag if data are 4-quadrant data   */
  amdmsFILE_LIST          inFiles;   /* input files (names and flags)      */
  amdmsFILE_LIST          outFiles;  /* output files (names and flags)     */
  amdmsCALIBRATION_SETUP  calib;     /* calibration setup                  */
  amdmsSTRIPE_SETUP       stripes;   /* stripe setup                       */
  amdmsDATA_FILTER_SETUP  filter;    /* data filter setup                  */
  amdmsBOOL               allocated; /* flag if structure was allocated    */
} amdmsALGO_ENV;
/***************************************************************************/


/*********************************************************************************/
/* environment for pixel statistics                                              */
/*********************************************************************************/
typedef struct {
  amdmsALGO_ENV             env;         /* embedded basic environment           */
  float                     cf;          /* conversion factor                    */
  int                       ebNIter;     /* number of iterations for EB          */
  float                     ebLower;     /* lower limit for EB bad pixels        */
  float                     ebUpper;     /* upper limit for EB bad pixels        */
  amdmsBOOL                 ebHFlag;     /* flag if horizontal ebm is calculated */
  amdmsBOOL                 ebVFlag;     /* flag if vertical ebm is calculated   */
  amdmsBOOL                 analyzeFlag; /* flag for image analyzation           */
  amdmsBOOL                 histoFlag;   /* flag for 1-d histogram               */
  amdmsPROJ_MODE            projMode;    /* projection mode                      */
  int                      *histoData;   /* 1-d histogram                        */
  amdmsDATA                 meanPixels;  /* individual flux mean                 */
  amdmsDATA                 varPixels;   /* individual flux variance             */
  amdmsPARTICLE_EVENT_SETUP events;      /* all found particle events            */
  amdmsBOOL                 allocated;   /* flag if structure was allocated      */
} amdmsALGO_STAT_ENV;
/*********************************************************************************/


/****************************************************************************/
/* environment for bad pixel map generation                                 */
/****************************************************************************/
typedef struct {
  amdmsALGO_ENV     env;          /* embedded basic environment             */
  amdmsBOOL         nuicFlag;     /* non uniform illumination compensation  */
  int               fuzzyCount;   /* counter limit for fuzzy map generation */
  float             fuzzyLimit;   /* relative fuzzy limit                   */
  amdmsDATA         fuzzyMap;     /* cumulative fuzzy counters              */
  amdmsBOOL         winFlag;      /* flag if the neighbourhood is reference */
  int               winInnerSize; /* inner (unused) part of window          */
  int               winOuterSize; /* outer (used) part of window            */
  int               nIter;        /* number of iterations for sigma limits  */
  amdmsLIMIT_SETUP  limits;       /* limit definitions                      */
  amdmsBOOL         allocated;    /* flag if structure was allocated        */
} amdmsALGO_BAD_PIXEL_ENV;
/****************************************************************************/


/*************************************************************************/
/* environment for pixel property map generation                         */
/*************************************************************************/
typedef struct {
  amdmsALGO_ENV     env;        /* embedded basic environment            */
  amdmsBOOL         nuicFlag;   /* non uniform illumination compensation */
  double            kADC;       /* ADC amplification                     */
  amdmsBOOL         satFlag;    /* Flag if a saturation box is specified */
  double            satWidth;   /* relative width of the saturation box  */
  double            satHeight;  /* relative height of the saturation box */
  int               nDelStart;  /* number of possible outliers (start)   */
  int               nDelMiddle; /* number of possible outliers (middle)  */
  int               nDelEnd;    /* number of possible outliers (end)     */
  amdmsCF_ALGO      cfAlgo;     /* algorithm for the conversion factor   */
  amdmsHISTO_SETUP  hX;         /* setup for the horizontal axis         */
  amdmsHISTO_SETUP  hY;         /* setup for the vertical axis           */
  int               nInputs;    /* number of input data                  */
  double           *exptimes;   /* array of all exposure times           */
  amdmsDATA        *meanPixels; /* array of all mean data                */
  amdmsDATA        *varPixels;  /* array of all variance data            */
  amdmsDATA         ffFit[amdmsFLATFIELD_FIT_NROWS];
  amdmsDATA         cfFit[amdmsCONVERSION_FACTOR_FIT_NROWS];
  amdmsDATA         nlFit[amdmsNONLINEARITY_FIT_NROWS];
  amdmsDATA         ptcFit[amdmsPTC_NROWS];
  amdmsDATA         dcFit[amdmsDARK_CURRENT_NROWS];
  amdmsDATA         cfmData;    /* conversion factor map                 */
  amdmsDATA         histoData;  /* 2-d histogram                         */
  amdmsBOOL         allocated;  /* flag if structure was allocated       */
} amdmsALGO_PROPERTIES_ENV;
/*************************************************************************/


/*************************************************************************/
/* environment for importing data into Fits files                        */
/*************************************************************************/
typedef struct {
  amdmsALGO_ENV   env;         /* embedded basic environment             */
  double          exptime;     /* exposure time in seconds               */
  int             pixelOffset; /* pixel offset which is subtracted       */
  amdmsREAD_TYPE  readType;    /* readtype (for importing C40 data)      */
  int             firstRead;   /* first read for DIFFERENCE or FIRST     */
  int             secondRead;  /* second read for DIFFERENCE or SECOND   */
  int             nImages;     /* number of images to be imported        */
  int             nReads;      /* number of reads (only for JPEG)        */
  amdmsBOOL       zoFlag;      /* zero offset flag for bad image list    */
  int             nBadImages;  /* number of bad images which are ignored */
  int            *badImages;   /* index list of bad images               */
  amdmsBOOL       allocated;   /* flag if structure was allocated        */
} amdmsALGO_IMPORT_ENV;
/*************************************************************************/


/*************************************************************************/
/* environment for exporting data into fits files                        */
/*************************************************************************/
typedef struct {
  amdmsALGO_ENV   env;         /* embedded basic environment             */
  amdmsBOOL       allocated;   /* flag if structure was allocated        */
} amdmsALGO_EXPORT_ENV;
/*************************************************************************/


#ifdef __cplusplus
extern "C" {
#endif

  void amdmsSupressLogMessages(int flag);
  void amdmsShowOnlyMessage(int flag);
  void amdmsSetSeverityLevel(amdmsSEVERITY level);
  void amdmsFatal(const char *file, int line, const char *format, ...);
  void amdmsError(const char *file, int line, const char *format, ...);
  void amdmsWarning(const char *file, int line, const char *format, ...);
  void amdmsNotice(const char *file, int line, const char *format, ...);
  void amdmsInfo(const char *file, int line, const char *format, ...);
  void amdmsDebug(const char *file, int line, const char *format, ...);
  extern int amdmsOnlyMessage;
  extern amdmsEVENT amdmsLastEvent;

  amdmsCOMPL amdmsInitData(amdmsDATA *data);
  amdmsCOMPL amdmsAllocateData(amdmsDATA *data,
			     int nx,
			     int ny);
  amdmsCOMPL amdmsFreeData(amdmsDATA *data);
  amdmsCOMPL amdmsCopyData(amdmsDATA *dst,
			 amdmsDATA *src);
  amdmsCOMPL amdmsSetData(amdmsDATA *data,
			  amdmsPIXEL value);
  amdmsCOMPL amdmsSetDataR(amdmsDATA *data,
			   int rX, int rY, int rW, int rH,
			   amdmsPIXEL value);

  amdmsCOMPL amdmsInitFileList(amdmsFILE_LIST *list,
			     amdmsFITS_FLAGS flags);
  amdmsCOMPL amdmsFreeFileList(amdmsFILE_LIST *list);
  amdmsCOMPL amdmsAddFileToList(amdmsFILE_LIST *list,
			      char *name,
			      amdmsFITS_FLAGS flags);

  amdmsCOMPL amdmsInitParticleEventSetup(amdmsPARTICLE_EVENT_SETUP *setup);
  amdmsCOMPL amdmsFreeParticleEventSetup(amdmsPARTICLE_EVENT_SETUP *setup);

  amdmsCOMPL amdmsInitStripeSetup(amdmsSTRIPE_SETUP *setup);
  amdmsCOMPL amdmsFreeStripeSetup(amdmsSTRIPE_SETUP *setup);
  amdmsCOMPL amdmsRecalcStripes(amdmsSTRIPE_SETUP *setup,
			      int nx,
			      int ny);

  amdmsCOMPL amdmsInitCalibrationSetup(amdmsCALIBRATION_SETUP *setup);
  amdmsCOMPL amdmsFreeCalibrationSetup(amdmsCALIBRATION_SETUP *setup);

  amdmsCOMPL amdmsInitDataFilterSetup(amdmsDATA_FILTER_SETUP *setup);
  amdmsCOMPL amdmsFreeDataFilterSetup(amdmsDATA_FILTER_SETUP *setup);

  amdmsCOMPL amdmsInitLimitSetup(amdmsLIMIT_SETUP *setup);
  amdmsCOMPL amdmsFreeLimitSetup(amdmsLIMIT_SETUP *setup);


  amdmsCOMPL amdmsReadAllMaps(amdmsCALIBRATION_SETUP *setup);
  amdmsCOMPL amdmsCalibrateData(amdmsCALIBRATION_SETUP *setup,
			      amdmsDATA *rawData,
			      amdmsDATA *calData);
  amdmsBOOL amdmsIsPixelValid(amdmsCALIBRATION_SETUP *setup,
			    int iImage,
			    int iPixel);
  amdmsBOOL amdmsIsPixelAffectedByPE(amdmsCALIBRATION_SETUP *setup,
				   int iImage,
				   int iPixel);
  amdmsCOMPL amdmsCalcStat(amdmsCALIBRATION_SETUP *setup,
			 amdmsDATA *data,
			 int iImage,
			 int x,
			 int y,
			 int width,
			 int height,
			 amdmsPIXEL *mean,
			 amdmsPIXEL *var);
  amdmsCOMPL amdmsCalcStatBox(amdmsCALIBRATION_SETUP *setup, amdmsDATA *data, int iImage,
			    int xLimit, int yLimit, int widthLimit, int heightLimit,
			    int xCenter, int yCenter, int innerSize, int outerSize,
			    amdmsPIXEL *mean, amdmsPIXEL *var);
  amdmsCOMPL amdmsSmoothData(amdmsCALIBRATION_SETUP *calib,
			     amdmsDATA *src,
			     amdmsDATA *dst);
  amdmsCOMPL amdmsCleanUpFlatfield(amdmsCALIBRATION_SETUP *calib,
				 amdmsSTRIPE_SETUP *stripes,
				 amdmsDATA *mean,
				 amdmsDATA *var);
  amdmsCOMPL amdmsCleanUpFlatfieldSmooth(amdmsCALIBRATION_SETUP *calib,
					 amdmsSTRIPE_SETUP *stripes,
					 amdmsDATA *mean,
					 amdmsDATA *var);

  amdmsCOMPL amdmsCreateAlgo(amdmsALGO_ENV **env);
  amdmsCOMPL amdmsDestroyAlgo(amdmsALGO_ENV **env);

  amdmsCOMPL amdmsCreateStatisticsAlgo(amdmsALGO_STAT_ENV **env);
  amdmsCOMPL amdmsDestroyStatisticsAlgo(amdmsALGO_STAT_ENV **env);
  amdmsCOMPL amdmsDoPixelStatistics(amdmsALGO_STAT_ENV *env);

  amdmsCOMPL amdmsCreateBadPixelAlgo(amdmsALGO_BAD_PIXEL_ENV **env);
  amdmsCOMPL amdmsDestroyBadPixelAlgo(amdmsALGO_BAD_PIXEL_ENV **env);
  amdmsCOMPL amdmsDoBadPixel(amdmsALGO_BAD_PIXEL_ENV *env);

  amdmsCOMPL amdmsCreatePropertiesAlgo(amdmsALGO_PROPERTIES_ENV **env);
  amdmsCOMPL amdmsDestroyPropertiesAlgo(amdmsALGO_PROPERTIES_ENV **env);
  amdmsCOMPL amdmsDoProperties(amdmsALGO_PROPERTIES_ENV *env);

  amdmsCOMPL amdmsCreateImportAlgo(amdmsALGO_IMPORT_ENV **env);
  amdmsCOMPL amdmsDestroyImportAlgo(amdmsALGO_IMPORT_ENV **env);
  amdmsCOMPL amdmsDoImport(amdmsALGO_IMPORT_ENV *env);

  amdmsCOMPL amdmsCreateExportAlgo(amdmsALGO_EXPORT_ENV **env);
  amdmsCOMPL amdmsDestroyExportAlgo(amdmsALGO_EXPORT_ENV **env);
  amdmsCOMPL amdmsDoExport(amdmsALGO_EXPORT_ENV *env);

#ifdef __cplusplus
}
#endif

#endif /* !amdms_H */
