/* $Id: sinfo_utl_ima_line_corr.c,v 1.3 2009/06/05 08:18:55 amodigli Exp $
 *
 * This file is part of the SINFONI Pipeline
 * Copyright (C) 2002,2003 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: amodigli $
 * $Date: 2009/06/05 08:18:55 $
 * $Revision: 1.3 $
 * $Name: sinfo-2_4_0 $
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

/*-----------------------------------------------------------------------------
                                Includes
 ----------------------------------------------------------------------------*/
#include <string.h>

/* cpl */
#include <cpl.h>

/* irplib */
#include <irplib_utils.h>

#include <sinfo_tpl_utils.h>
#include <sinfo_pfits.h>
#include <sinfo_tpl_dfs.h>
#include <sinfo_key_names.h>
#include <sinfo_pro_types.h>
#include <sinfo_functions.h>
#include <sinfo_image_ops.h>
#include <sinfo_msg.h>
#include <sinfo_error.h>
#include <sinfo_utils_wrappers.h>

/*-----------------------------------------------------------------------------
                            Functions prototypes
 ----------------------------------------------------------------------------*/

static int sinfo_utl_ima_line_corr_create(cpl_plugin *) ;
static int sinfo_utl_ima_line_corr_exec(cpl_plugin *) ;
static int sinfo_utl_ima_line_corr_destroy(cpl_plugin *) ;
static int sinfo_utl_ima_line_corr(cpl_parameterlist *, cpl_frameset *) ;

/*-----------------------------------------------------------------------------
                            Static variables
 ----------------------------------------------------------------------------*/

static char sinfo_utl_ima_line_corr_description[] =
"This recipe performs image computation.\n"
"The input files are images\n"
"their associated tags should be IMA.\n"
"The output are the images cleaned by the defect introduced by SINFONI sw\n"
"Information on relevant parameters can be found with\n"
"esorex --params sinfo_utl_ima_line_corr\n"
"esorex --help sinfo_utl_ima_line_corr\n"
"\n";

/*-----------------------------------------------------------------------------
                                Functions code
 ----------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/**
 * @defgroup sinfo_utl_ima_line_corr  Recipe to do operations on an image
 */
/*---------------------------------------------------------------------------*/

/**@{*/
/*---------------------------------------------------------------------------*/
/**
  @brief    Build the list of available plugins, for this module. 
  @param    list    the plugin list
  @return   0 if everything is ok

  This function is exported.
 */
/*---------------------------------------------------------------------------*/
int cpl_plugin_get_info(cpl_pluginlist * list)
{
    cpl_recipe  *   recipe = cpl_calloc(1, sizeof *recipe ) ;
    cpl_plugin  *   plugin = &recipe->interface ;

    cpl_plugin_init(plugin,
                    CPL_PLUGIN_API,
                    SINFONI_BINARY_VERSION,
                    CPL_PLUGIN_TYPE_RECIPE,
                    "sinfo_utl_ima_line_corr",
                    "Computes result of ima1 op ima2",
                    sinfo_utl_ima_line_corr_description,
                    "Andrea Modigliani",
                    "Andrea.Modigliani@eso.org",
                    sinfo_get_license(),
                    sinfo_utl_ima_line_corr_create,
                    sinfo_utl_ima_line_corr_exec,
                    sinfo_utl_ima_line_corr_destroy) ;

    cpl_pluginlist_append(list, plugin) ;
    
    return 0;
}

/*---------------------------------------------------------------------------*/
/**
  @brief    Setup the recipe options    
  @param    plugin  the plugin
  @return   0 if everything is ok

  Create the recipe instance and make it available to the application using 
  the interface. 
 */
/*---------------------------------------------------------------------------*/
static int sinfo_utl_ima_line_corr_create(cpl_plugin * plugin)
{
    cpl_recipe      * recipe ;
    cpl_parameter   * p ;

    /* Get the recipe out of the plugin */
    if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
        recipe = (cpl_recipe *)plugin ;
    else return -1 ;
    cpl_error_reset();
    irplib_reset();

    /* Create the parameters list in the cpl_recipe object */
    recipe->parameters = cpl_parameterlist_new() ; 

    /* Fill the parameters list */
    p = cpl_parameter_new_value("sinfoni.sinfo_utl_ima_line_corr.kappa", 
                                CPL_TYPE_INT, 
                                "Kappa sigma value", 
                                "sinfoni.sinfo_utl_ima_line_corr",18);
    cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "kappa") ;
    cpl_parameterlist_append(recipe->parameters, p) ;

     p = cpl_parameter_new_value("sinfoni.sinfo_utl_ima_line_corr.filt_rad", 
				CPL_TYPE_INT,
				"Filtering radii applied during median filter."
                                " Should be small", 
				"sinfoni.sinfo_utl_ima_line_corr",3) ;;
    cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "filt_rad") ;
    cpl_parameterlist_append(recipe->parameters, p) ;
 
    /* Return */
    return 0;
}

/*---------------------------------------------------------------------------*/
/**
  @brief    Execute the plugin instance given by the interface
  @param    plugin  the plugin
  @return   0 if everything is ok
 */
/*---------------------------------------------------------------------------*/
static int sinfo_utl_ima_line_corr_exec(cpl_plugin * plugin)
{
    cpl_recipe  *   recipe ;
     int code=0;
     cpl_errorstate initial_errorstate = cpl_errorstate_get();

    /* Get the recipe out of the plugin */
    if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
        recipe = (cpl_recipe *)plugin ;
    else return -1 ;
    cpl_error_reset();
    irplib_reset();
    code = sinfo_utl_ima_line_corr(recipe->parameters, recipe->frames) ;


    if (!cpl_errorstate_is_equal(initial_errorstate)) {                      
        /* Dump the error history since recipe execution start.                
           At this point the recipe cannot recover from the error */           
        cpl_errorstate_dump(initial_errorstate, CPL_FALSE, NULL);              
    } 

    return code ;
}

/*---------------------------------------------------------------------------*/
/**
  @brief    Destroy what has been created by the 'create' function
  @param    plugin  the plugin
  @return   0 if everything is ok
 */
/*---------------------------------------------------------------------------*/
static int sinfo_utl_ima_line_corr_destroy(cpl_plugin * plugin)
{
    cpl_recipe  *   recipe ;
    
    /* Get the recipe out of the plugin */
    if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
        recipe = (cpl_recipe *)plugin ;
    else return -1 ;

    cpl_parameterlist_delete(recipe->parameters) ; 
    return 0 ;
}

/*---------------------------------------------------------------------------*/
/**
  @brief    Get the command line options and execute the data reduction
  @param    parlist     the parameters list
  @param    framelist   the frames list
  @return   0 if everything is ok
 */
/*---------------------------------------------------------------------------*/
static int 
sinfo_utl_ima_line_corr( cpl_parameterlist   *   parlist, 
			 cpl_frameset        *   framelist)
{
    cpl_parameter       *   p= NULL ;
    int                     kappa=18;
    int                     filt_rad=3;
    int width=4;

    cpl_image           *   ima=NULL ;
    cpl_image           *   ima_out=NULL ;
    cpl_propertylist    *   plist=NULL ;
    cpl_frame           *   product_frame=NULL;
    cpl_frameset * raw_set=NULL;
    int i=0;
    cpl_frame * frm=NULL;
    char name_o[MAX_NAME_SIZE];
    const char* name=NULL;

    int n=0;
    sinfo_msg("Welcome to SINFONI Pipeline release %d.%d.%d",
        SINFONI_MAJOR_VERSION,SINFONI_MINOR_VERSION,SINFONI_MICRO_VERSION);

    /* HOW TO RETRIEVE INPUT PARAMETERS */
    /* --stropt */
    check_nomsg(p=cpl_parameterlist_find(parlist, 
                                         "sinfoni.sinfo_utl_ima_line_corr.kappa"));
    check_nomsg(kappa=cpl_parameter_get_int(p));

    /* --boolopt */
    check_nomsg(p=cpl_parameterlist_find(parlist,
                                         "sinfoni.sinfo_utl_ima_line_corr.filt_rad"));
    check_nomsg(filt_rad = cpl_parameter_get_int(p)) ;
  
    /* Identify the RAW and CALIB frames in the input frameset */
    check(sinfo_dfs_set_groups(framelist),
         "Cannot identify RAW and CALIB frames") ;
 
    /* HOW TO ACCESS INPUT DATA */
    n=cpl_frameset_get_size(framelist);
    if(n<1) {
      sinfo_msg_error("Empty input frame list!");
      goto cleanup ;
    }
    raw_set=cpl_frameset_new();
    ck0_nomsg(sinfo_extract_raw_frames(framelist, &raw_set));
    n=cpl_frameset_get_size(raw_set);
    if(n<1) {
      sinfo_msg_error("No raw data found in frame list!");
      goto cleanup ;
    }


    for(i=0;i<n;i++) {
      check_nomsg(frm=cpl_frameset_get_frame(raw_set,0));
      check_nomsg(name=cpl_frame_get_filename(frm));
      check_nomsg(ima=cpl_image_load(name,CPL_TYPE_FLOAT,0,0));

      check_nomsg(sinfo_image_line_corr(width,filt_rad,kappa,ima,&ima_out));

      sprintf(name_o,"%s%d%s","ima_cor",i,".fits") ;

      /* Create product frame */
      check_nomsg(product_frame = cpl_frame_new());
      check_nomsg(cpl_frame_set_filename(product_frame, name_o));
      check_nomsg(cpl_frame_set_tag(product_frame, "IMA_COR"));
      check_nomsg(cpl_frame_set_type(product_frame, CPL_FRAME_TYPE_IMAGE));
      check_nomsg(cpl_frame_set_group(product_frame, CPL_FRAME_GROUP_PRODUCT));
      check(cpl_frame_set_level(product_frame, CPL_FRAME_LEVEL_FINAL),
	    "Error while initialising the product frame") ;
    
      /* Add DataFlow keywords */
      /*
      check(cpl_dfs_setup_product_header(plist, 
					 product_frame, 
					 framelist, 
					 parlist,
					 "sinfo_utl_ima_line_corr", 
					 "SINFONI", 
					 KEY_VALUE_HPRO_DID),
	    "Problem in the product DFS-compliance") ;
      */

      /* Save the file */
      check(cpl_image_save(ima_out, 
			   name_o, 
			   CPL_BPP_IEEE_FLOAT, 
			   plist,
			   CPL_IO_DEFAULT),
	    "Could not save product");
      sinfo_free_propertylist(&plist) ;
      sinfo_free_image(&ima_out);
      sinfo_free_image(&ima);

      /* Log the saved file in the input frameset */
      check_nomsg(cpl_frameset_insert(framelist, product_frame)) ;

    }

 cleanup:
    sinfo_free_image(&ima);
    sinfo_free_image(&ima_out);
      //sinfo_free_frameset(&raw_set);


    /* This is usually freed by esorex: but what about if errors occurs?
    sinfo_free_frame(&product_frame) ;
    */


    if (cpl_error_get_code()) {
        return -1 ;
    } else {
        return 0 ;
    }

}
/**@}*/
