/** @file tst_pmFlatField.c
 *
 *  @brief Contains the tests for pmSubtractBias.c:
 *
 * test00: This code will subtract full bias frames from the input image.
 * test01: Multiple overscan regions, calculate a scalar statistic for
 *  each, then subtract from the input image.
 * test02: Calculate a column overscan vector and subtract it from each
 *  column in the input image.
 * test03: Calculate a row overscan vector and subtract it from each
 *  row in the input image.
 *
 *
 *  @author GLG, MHPCC
 *
 *  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
 *  @date $Date: 2004-10-15 02:15:34 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
 */

#include "psTest.h"
#include "pslib.h"
#include "pmSubtractBias.h"
static int test00(void);
static int test01(void);
static int test02(void);
static int test03(void);
testDescription tests[] = {
                              {test00, 000, "pmSubtractBias", 0, false},
                              {test01, 000, "pmSubtractBias", 0, false},
                              {test02, 000, "pmSubtractBias", 0, false},
                              {test03, 000, "pmSubtractBias", 0, false},
                              {NULL}
                          };


int main(int argc, char* argv[])
{
    return !runTestSuite(stderr, "Test Point Driver", tests, argc, argv);
}

#define NUM_ROWS 4
#define NUM_COLS 4
int doSubtractBiasFullFrame(int numCols, int numRows)
{
    int i;
    int j;
    float actual;
    float expect;
    int testStatus = 0;
    psImage *tmpImage1 = psImageAlloc(numCols, numRows, PS_TYPE_F32);
    psImage *tmpImage2 = psImageAlloc(numCols, numRows, PS_TYPE_F32);
    psReadout *myReadout = psReadoutAlloc(numCols, numRows, tmpImage1);
    psReadout *myBias = psReadoutAlloc(numCols, numRows, tmpImage2);

    for (i=0;i<numRows;i++) {
        for (j=0;j<numCols;j++) {
            myReadout->image->data.F32[i][j] = (float) (i + j);
            myBias->image->data.F32[i][j] = 1.0;
        }
    }

    myReadout = pmSubtractBias(myReadout, NULL, NULL, PM_OVERSCAN_NONE, NULL,
                               0, PM_FIT_NONE, myBias);

    for (i=0;i<numRows;i++) {
        for (j=0;j<numCols;j++) {
            expect = ((float) (i + j)) - 1.0;
            actual = myReadout->image->data.F32[i][j];
            if (FLT_EPSILON < fabs(expect - actual)) {
                printf("ERROR: image[%d][%d] is %f, should be %f\n", i, j, actual, expect);
                testStatus = 1;
            }
        }
    }


    psFree(myReadout);
    psFree(myBias);
    return(testStatus);
}


int test00( void )
{
    int testStatus = 0;

    testStatus |= doSubtractBiasFullFrame(1, 1);
    testStatus |= doSubtractBiasFullFrame(NUM_COLS, 1);
    testStatus |= doSubtractBiasFullFrame(1, NUM_ROWS);
    testStatus |= doSubtractBiasFullFrame(NUM_COLS, NUM_ROWS);

    return(testStatus);
}

int doSubtractFullOverscans(int numCols, int numRows)
{
    int i;
    int j;
    float actual;
    float expect;
    int testStatus = 0;
    psImage *tmpImage1 = psImageAlloc(numCols, numRows, PS_TYPE_F32);
    psImage *tmpImage2 = psImageAlloc(numCols, numRows, PS_TYPE_F32);
    psImage *tmpImage3 = psImageAlloc(numCols, numRows, PS_TYPE_F32);
    psImage *tmpImage4 = psImageAlloc(numCols, numRows, PS_TYPE_F32);
    psReadout *myReadout = psReadoutAlloc(numCols, numRows, tmpImage1);
    psList *list;
    psStats *stat = psStatsAlloc(PS_STAT_SAMPLE_MEAN);

    for (i=0;i<numRows;i++) {
        for (j=0;j<numCols;j++) {
            myReadout->image->data.F32[i][j] = (float) (i + j);
            tmpImage2->data.F32[i][j] = 3.0;
            tmpImage3->data.F32[i][j] = 4.0;
            tmpImage4->data.F32[i][j] = 5.0;
        }
    }
    list = psListAlloc(tmpImage2);
    psListAdd(list, PS_LIST_HEAD, tmpImage3);
    psListAdd(list, PS_LIST_HEAD, tmpImage4);

    myReadout = pmSubtractBias(myReadout, NULL, list, PM_OVERSCAN_ALL, stat,
                               0, PM_FIT_NONE, NULL);

    for (i=0;i<numRows;i++) {
        for (j=0;j<numCols;j++) {
            expect = ((float) (i + j)) - 12.0;
            actual = myReadout->image->data.F32[i][j];
            if (FLT_EPSILON < fabs(expect - actual)) {
                printf("ERROR: image[%d][%d] is %f, should be %f\n", i, j, actual, expect);
                testStatus = 1;
            }
        }
    }


    psFree(myReadout);
    psFree(tmpImage2);
    psFree(tmpImage3);
    psFree(tmpImage4);
    psFree(stat);
    psFree(list);

    return(testStatus);
}

int test01( void )
{
    int testStatus = 0;

    testStatus |= doSubtractFullOverscans(1, 1);
    testStatus |= doSubtractFullOverscans(1, NUM_ROWS);
    testStatus |= doSubtractFullOverscans(NUM_COLS, 1);
    testStatus |= doSubtractFullOverscans(NUM_COLS, NUM_ROWS);

    return(testStatus);
}

int doSubtractFullOverscanColumns(int numCols, int numRows)
{
    int i;
    int j;
    float actual;
    float expect;
    int testStatus = 0;
    psImage *tmpImage1 = psImageAlloc(numCols, numRows, PS_TYPE_F32);
    psImage *tmpImage2 = psImageAlloc(numCols, numRows, PS_TYPE_F32);
    psImage *tmpImage3 = psImageAlloc(numCols, numRows, PS_TYPE_F32);
    psImage *tmpImage4 = psImageAlloc(numCols, numRows, PS_TYPE_F32);
    psReadout *myReadout = psReadoutAlloc(numCols, numRows, tmpImage1);
    psList *list;
    psStats *stat = psStatsAlloc(PS_STAT_SAMPLE_MEAN);

    for (i=0;i<numRows;i++) {
        for (j=0;j<numCols;j++) {
            myReadout->image->data.F32[i][j] = (float) (i + j);
            tmpImage2->data.F32[i][j] = 3.0;
            tmpImage3->data.F32[i][j] = 4.0;
            tmpImage4->data.F32[i][j] = 5.0;
        }
    }
    list = psListAlloc(tmpImage2);
    psListAdd(list, PS_LIST_HEAD, tmpImage3);
    psListAdd(list, PS_LIST_HEAD, tmpImage4);

    printPositiveTestHeader(stdout, "pmSubtractBias", "Column Overscans");

    myReadout = pmSubtractBias(myReadout, NULL, list, PM_OVERSCAN_COLUMNS, stat,
                               0, PM_FIT_NONE, NULL);

    for (i=0;i<numRows;i++) {
        for (j=0;j<numCols;j++) {
            expect = ((float) (i + j)) - 12.0;
            actual = myReadout->image->data.F32[i][j];
            if (FLT_EPSILON < fabs(expect - actual)) {
                printf("ERROR: image[%d][%d] is %f, should be %f\n", i, j, actual, expect);
                testStatus = 1;
            }
        }
    }


    psFree(myReadout);
    psFree(tmpImage2);
    psFree(tmpImage3);
    psFree(tmpImage4);
    psFree(stat);
    psFree(list);

    printFooter(stdout, "pmSubtractBias", "Column Overscans", true);
    return(testStatus);
}

int test02( void )
{
    int testStatus = 0;

    testStatus |= doSubtractFullOverscanColumns(1, 1);
    testStatus |= doSubtractFullOverscanColumns(1, NUM_ROWS);
    testStatus |= doSubtractFullOverscanColumns(NUM_COLS, 1);
    testStatus |= doSubtractFullOverscanColumns(NUM_COLS, NUM_ROWS);

    return(testStatus);
}

int doSubtractFullOverscanRows(int numCols, int numRows)
{
    int i;
    int j;
    float actual;
    float expect;
    int testStatus = 0;
    psImage *tmpImage1 = psImageAlloc(numCols, numRows, PS_TYPE_F32);
    psImage *tmpImage2 = psImageAlloc(numCols, numRows, PS_TYPE_F32);
    psImage *tmpImage3 = psImageAlloc(numCols, numRows, PS_TYPE_F32);
    psImage *tmpImage4 = psImageAlloc(numCols, numRows, PS_TYPE_F32);
    psReadout *myReadout = psReadoutAlloc(numCols, numRows, tmpImage1);
    psList *list;
    psStats *stat = psStatsAlloc(PS_STAT_SAMPLE_MEAN);

    for (i=0;i<numRows;i++) {
        for (j=0;j<numCols;j++) {
            myReadout->image->data.F32[i][j] = (float) (i + j);
            tmpImage2->data.F32[i][j] = 3.0;
            tmpImage3->data.F32[i][j] = 4.0;
            tmpImage4->data.F32[i][j] = 5.0;
        }
    }
    list = psListAlloc(tmpImage2);
    psListAdd(list, PS_LIST_HEAD, tmpImage3);
    psListAdd(list, PS_LIST_HEAD, tmpImage4);

    printPositiveTestHeader(stdout, "pmSubtractBias", "Row Overscans");

    myReadout = pmSubtractBias(myReadout, NULL, list, PM_OVERSCAN_ROWS, stat,
                               0, PM_FIT_NONE, NULL);

    for (i=0;i<numRows;i++) {
        for (j=0;j<numCols;j++) {
            expect = ((float) (i + j)) - 12.0;
            actual = myReadout->image->data.F32[i][j];
            if (FLT_EPSILON < fabs(expect - actual)) {
                printf("ERROR: image[%d][%d] is %f, should be %f\n", i, j, actual, expect);
                testStatus = 1;
            }
        }
    }


    psFree(myReadout);
    psFree(tmpImage2);
    psFree(tmpImage3);
    psFree(tmpImage4);
    psFree(stat);
    psFree(list);

    printFooter(stdout, "pmSubtractBias", "Row Overscans", true);
    return(testStatus);
}

int test03( void )
{
    int testStatus = 0;

    testStatus |= doSubtractFullOverscanRows(1, 1);
    testStatus |= doSubtractFullOverscanRows(1, NUM_ROWS);
    testStatus |= doSubtractFullOverscanRows(NUM_COLS, 1);
    testStatus |= doSubtractFullOverscanRows(NUM_COLS, NUM_ROWS);

    return(testStatus);
}
