/* $Id: fors_cpl_wcs-test.c,v 1.2 2008-02-07 14:41:21 cizzo Exp $
 *
 * This file is part of the ESO Common Pipeline Library
 * Copyright (C) 2001-2004 European Southern Observatory
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/*
 * $Author: cizzo $
 * $Date: 2008-02-07 14:41:21 $
 * $Revision: 1.2 $
 * $Name: not supported by cvs2svn $
 */

#ifdef HAVE_WCS

/*----------------------------------------------------------------------------
                                   Includes
 ----------------------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <float.h>

#include <cpl_wcs.h>
#include <cpl.h>
//#include "cpl_tools.h"

#define NSK 2
#define NDK 13
#define NIK 3



#define fors_cpl_test(bool) \
  ((bool) ? (cpl_msg_debug(__FILE__, \
     "OK in line %d (CPL-error state: '%s' in %s): %s",__LINE__, \
       cpl_error_get_message(), cpl_error_get_where(), #bool), 0) \
    : (cpl_msg_error(__FILE__, \
     "Failure in line %d (CPL-error state: '%s' in %s): %s",__LINE__, \
       cpl_error_get_message(), cpl_error_get_where(), #bool), 1))





static const char *skeys[NSK] = {"CTYPE1", "CTYPE2"};

static const char *dkeys[NDK] = {"CRVAL1", "CRVAL2", "CRPIX1", "CRPIX2", 
				 "CD1_1", "CD1_2", "CD2_1", "CD2_2", "PV2_1",
				 "PV2_2", "PV2_3", "PV2_4", "PV2_5"};
static const char *ikeys[NIK] = {"NAXIS","NAXIS1","NAXIS2"};


static const char *svals[NSK] = {"RA---ZPN", "DEC--ZPN"};
static const double dvals[NDK] = {5.57368333333, -72.0576388889, 5401.6, 6860.8,
				  5.81347849634012E-21, 9.49444444444444E-05,
				  -9.49444444444444E-05, -5.81347849634012E-21,
				  1.0, 0.0, 42.0, 0.0, 0.0};
static const int ivals[NIK] = {2, 2048, 2048};

#define NP 2
static double physin[2*NP] = {1024.0, 1024.0, 1025.0, 1023.0};

static double worldout[2*NP] = {3.825029720, -71.636524754,
				3.824722171, -71.636616487};
static double stdcout[2] = {-0.554171733, 0.415628800};


static double worldin[2] = {3.824875946, -71.636570620};
static double physout[2] = {1024.5, 1023.5};


int main (void) {
    cpl_boolean is_debug;
    int i,nfail;
    cpl_propertylist *pl;
    cpl_wcs *wcs;
    cpl_matrix *from,*to;
    cpl_array *status;
    double d1,d2;

    /* Initialise */

    cpl_init(CPL_INIT_DEFAULT);
    cpl_msg_set_level(CPL_MSG_WARNING);
    cpl_msg_set_level_from_env();
    cpl_msg_set_domain_off();
    is_debug = cpl_msg_get_level() <= CPL_MSG_DEBUG ? TRUE : FALSE;

    /* Read in all the WCS properties, except for NAXIS? entries*/

    pl = cpl_propertylist_new();
    for (i = 0; i < NSK; i++) 
	cpl_propertylist_append_string(pl,skeys[i],svals[i]);
    for (i = 0; i < NDK; i++) 
	cpl_propertylist_append_double(pl,dkeys[i],dvals[i]);

    /* Now test cpl_wcs_new_from_propertylist to make sure we get the
       correct errors */

    nfail = 0;
    wcs = cpl_wcs_new_from_propertylist(NULL);
    nfail += fors_cpl_test(cpl_error_get_code() == CPL_ERROR_NULL_INPUT);
    nfail += fors_cpl_test(wcs == NULL);
    cpl_error_reset();
    if (wcs != NULL)
	cpl_wcs_delete(wcs);
    wcs = cpl_wcs_new_from_propertylist(pl);
    nfail += fors_cpl_test(cpl_error_get_code() == CPL_ERROR_NONE);
    nfail += fors_cpl_test(wcs != NULL);
    cpl_error_reset();
    if (wcs != NULL)
	cpl_wcs_delete(wcs);

    /* OK, now insert the rest of the propertylist */

    for (i = 0; i < NIK; i++) 
	cpl_propertylist_append_int(pl,ikeys[i],ivals[i]);

    /* Get a wcs structure */

    wcs = cpl_wcs_new_from_propertylist(pl);
    nfail += fors_cpl_test(wcs != NULL);
    cpl_propertylist_delete(pl);

    /* Test cpl_wcs_convert to see if we get the correct error messages */

    nfail += fors_cpl_test(cpl_wcs_convert(NULL,NULL,&to,&status,
				      CPL_WCS_PHYS2WORLD) == CPL_ERROR_NULL_INPUT);
    cpl_error_reset();
    nfail += fors_cpl_test(cpl_wcs_convert(wcs,NULL,&to,&status,
				      CPL_WCS_PHYS2WORLD) == CPL_ERROR_NULL_INPUT);
    cpl_error_reset();

    /* Ok, do a conversion of physical to world coordinates */

    cpl_msg_info("","Transform physical -> world (2 points)");
    from = cpl_matrix_wrap(NP,2,physin);
    cpl_wcs_convert(wcs,from,&to,&status,CPL_WCS_PHYS2WORLD);
    nfail += (cpl_error_get_code() != CPL_ERROR_NONE);
    cpl_error_reset();
    cpl_matrix_unwrap(from);
    
    /* Test the output values. The status should all be 0. The output matrix
       is compared to predifined world coordinate values */

    for (i = 0; i < NP; i++)
        nfail += fors_cpl_test(cpl_array_get_data_int(status)[i] == 0);
    d1 = fabs(worldout[0] - cpl_matrix_get(to,0,0));
    d2 = fabs(worldout[1] - cpl_matrix_get(to,0,1));
    cpl_msg_info("","phys1,phys2:   %15.9f %15.9f",physin[0],physin[1]);
    cpl_msg_info("","world1,world2: %15.9f %15.9f",worldout[0],worldout[1]);
    cpl_msg_info("","calc1,calc2:   %15.9f %15.9f",cpl_matrix_get(to,0,0),
	    cpl_matrix_get(to,0,1));
    cpl_msg_info("","diff1,diff2:   %15.9f %15.9f",d1,d2);
    cpl_msg_info("","status:        %d",(cpl_array_get_data_int(status)[0]));
    nfail += fors_cpl_test(d1 < 1.0e-6);
    nfail += fors_cpl_test(d2 < 1.0e-6);
    d1 = fabs(worldout[2] - cpl_matrix_get(to,1,0));
    d2 = fabs(worldout[3] - cpl_matrix_get(to,1,1));
    cpl_msg_info("","phys1,phys2:   %15.9f %15.9f",physin[2],physin[3]);
    cpl_msg_info("","world1,world2: %15.9f %15.9f",worldout[2],worldout[3]);
    cpl_msg_info("","calc1,calc2:   %15.9f %15.9f",cpl_matrix_get(to,1,0),
	    cpl_matrix_get(to,1,1));
    cpl_msg_info("","diff1,diff2:   %15.9f %15.9f",d1,d2);
    cpl_msg_info("","status:        %d",
		 (cpl_array_get_data_int(status)[1]));
    nfail += fors_cpl_test(d1 < 1.0e-6);
    nfail += fors_cpl_test(d2 < 1.0e-6);
    cpl_matrix_delete(to);
    cpl_array_delete(status);

    /* Do world to physical conversion */

    cpl_msg_info("","Transform world -> physical");
    from = cpl_matrix_wrap(1,2,worldin);
//    cpl_matrix_dump(from, stdout);
    cpl_wcs_convert(wcs,from,&to,&status,CPL_WCS_WORLD2PHYS);
    nfail += (cpl_error_get_code() != CPL_ERROR_NONE);
    cpl_error_reset();
    cpl_matrix_unwrap(from);
    
    /* Test the output values again */

    nfail += fors_cpl_test(cpl_array_get_data_int(status)[0] == 0);
    d1 = fabs(physout[0] - cpl_matrix_get(to,0,0));
    d2 = fabs(physout[1] - cpl_matrix_get(to,0,1));
    cpl_msg_info("","world1,world2: %15.9f %15.9f",worldin[0],worldin[1]);
    cpl_msg_info("","phys1,phys2:   %15.9f %15.9f",physout[0],physout[1]);
    cpl_msg_info("","calc1,calc2:   %15.9f %15.9f",cpl_matrix_get(to,0,0),
	    cpl_matrix_get(to,0,1));
    cpl_msg_info("","diff1,diff2:   %15.9f %15.9f",d1,d2);
    cpl_msg_info("","status:        %d",(cpl_array_get_data_int(status)[0]));
    nfail += fors_cpl_test(d1 < 2.5e-4);
    nfail += fors_cpl_test(d2 < 2.5e-4);
    cpl_matrix_delete(to);
    cpl_array_delete(status);

    /* Do physical to standard */

    cpl_msg_info("","Transform physical -> standard");
    from = cpl_matrix_wrap(1,2,physin);
//    cpl_matrix_dump(from, stdout);

    cpl_wcs_convert(wcs,from,&to,&status,CPL_WCS_PHYS2STD);
    nfail += (cpl_error_get_code() != CPL_ERROR_NONE);
    cpl_error_reset();
    cpl_matrix_unwrap(from);

    /* Test the output values again */

    nfail += fors_cpl_test(cpl_array_get_data_int(status)[0] == 0);
    d1 = fabs(stdcout[0] - cpl_matrix_get(to,0,0));
    d2 = fabs(stdcout[1] - cpl_matrix_get(to,0,1));
    cpl_msg_info("","phys1,phys2:   %15.9f %15.9f",physin[0],physin[1]);
    cpl_msg_info("","std1,std2:     %15.9f %15.9f",stdcout[0],stdcout[1]);
    cpl_msg_info("","calc1,calc2:   %15.9f %15.9f",cpl_matrix_get(to,0,0),
	    cpl_matrix_get(to,0,1));
    cpl_msg_info("","diff1,diff2:   %15.9f %15.9f",d1,d2);
    cpl_msg_info("","status:        %d",(cpl_array_get_data_int(status)[0]));
    nfail += fors_cpl_test(d1 < 1.7e-9);
    nfail += fors_cpl_test(d2 < 1.7e-9);
    cpl_matrix_delete(to);
    cpl_array_delete(status);

    /* Do world to standard */

    cpl_msg_info("","Transform world -> standard");
    from = cpl_matrix_wrap(1,2,worldout);
//    cpl_matrix_dump(from, stdout);

    cpl_wcs_convert(wcs,from,&to,&status,CPL_WCS_WORLD2STD);
    nfail += (cpl_error_get_code() != CPL_ERROR_NONE);
    cpl_error_reset();
    cpl_matrix_unwrap(from);

    /* Test the output values again */

    nfail += fors_cpl_test(cpl_array_get_data_int(status)[0] == 0);
    d1 = fabs(stdcout[0] - cpl_matrix_get(to,0,0));
    d2 = fabs(stdcout[1] - cpl_matrix_get(to,0,1));
    cpl_msg_info("","world1,world2: %15.9f %15.9f",worldout[0],worldout[1]);
    cpl_msg_info("","std1,std2:     %15.9f %15.9f",stdcout[0],stdcout[1]);
    cpl_msg_info("","calc1,calc2:   %15.9f %15.9f",cpl_matrix_get(to,0,0),
	    cpl_matrix_get(to,0,1));
    cpl_msg_info("","diff1,diff2:   %15.9f %15.9f",d1,d2);
    cpl_msg_info("","status:        %d",(cpl_array_get_data_int(status)[0]));
    nfail += fors_cpl_test(d1 < 1.7e-9);
    nfail += fors_cpl_test(d2 < 1.7e-9);
    cpl_matrix_delete(to);
    cpl_array_delete(status);

    /* Tidy */

    cpl_wcs_delete(wcs);

    /* Are there any memory leaks (NB: this only covers CPL. Memory is 
       allocated separately by WCSLIB */

    nfail += fors_cpl_test(cpl_memory_is_empty());

    /* Did any tests fail? */

    cpl_msg_info("","%d test(s) failed",nfail);

    /* Tidy and exit */
    
    if (is_debug || !cpl_memory_is_empty())
	cpl_memory_dump();
    cpl_end();
    return(nfail);
}
    
    
#else

#include <test.h>
#include <cpl.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    TEST_INIT;
    
    cpl_msg_info(cpl_func, "WCS module not available");

    TEST_END;
}
    
#endif
	    
	



    
