/*
 S.F.Sanchez (08.08.2003)
*/


#include <stdlib.h>
#include <stdio.h>
#include <ctype.h> //For Type check
#include <string.h> //For String manipulation
#include <math.h> //For Math functions


#include "my_math.h"
#include "my_struct.h"


#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#endif

#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 1
#endif

#define PARAMETERS 3
#define MAX_MODELS 2000

//double gsersic(double x, double sig, double I_m, double r_m. double beta);

int copy_modpar(struct MODPAR *newpar, struct MODPAR *modpar, int n_mod);
int add_rand_modpar(struct MODPAR *modpar, int n_mod);

double poly_n(double x, double a[], int na) {
    int i;
    double t = x;      
    double Yi = 0;
    for (i=0;i<na;i++) {
	Yi+=a[i]*pow(t,i);
    }
    return Yi;
}


double gauss1d(double x, double I_m,double r_m, double fondo) {
      double t = x;
      double e1 = exp(-0.5*pow((t-r_m)/fondo,2));
      double Yi = I_m * e1;
      return Yi;
}

//double vel_model(double r, double theta, double v_sys, double amp, double pa, double i) {
double vel_model(double x, double y,double x_c, double y_c, double A, double v_sys, double pa, double incl, double c0, double p) {
    double r;
  double vel=0;
  double CT;
  double v_rot;
  double xr,yr;
  
  xr=(x-x_c)*cos(pa)+(y-y_c)*sin(pa);
  yr=(x-x_c)*sin(pa)-(y-y_c)*cos(pa);

  r=pow((pow(xr,2)+pow((yr)/cos(incl),2)),0.5);
  if (r>0) {
    CT=((-1)*(x-x_c)*sin(pa)+(y-y_c)*cos(pa))/(pow((pow(xr,2)+pow(yr,2)),0.5));
      //      v_rot=(A*r)/pow((r*r+c0*c0),p*0.5);
      //      v_rot=(2*A/3.1416)*abs(atan(abs(c0*r-p)));      
      v_rot=(2*A/3.1416)*((atan((c0*r-p))));
      //      $CT=1;
      vel=v_sys+v_rot*CT*sin(incl);
  } else {
      vel=v_sys;
  }
  return vel;
}


//	    flux_tmp=Im*exp(-0.5*pow((r/r_m),2));
/*
double mgauss(double r, double I_m, double r_m, double rad) {
    double dx=0.25;
    double sum=0.0;
    double norm;
    int i,n;
    norm=(I_m/(2*3.14159*pow(sig,2)));
    n=floor(3*sig/dx);
    for (i=-n;i<n;i++) {
	sum=+(exp(-0.5*pow((i*dx/sig),2)-pow(((x-i*dx)/r_m),beta)));
    }
    sum=sum*norm;
    return sum;
}
*/

double gsersic(double x, double sig, double I_m, double r_m, double beta) {
    double dx=0.25;
    double sum=0.0;
    double norm;
    int i,n;
    norm=(I_m/(2*3.14159*pow(sig,2)));
    n=floor(3*sig/dx);
    for (i=-n;i<n;i++) {
	sum=+(exp(-0.5*pow((i*dx/sig),2)-pow(((x-i*dx)/r_m),beta)));
    }
    sum=sum*norm;
//    printf("%g %g %g\n",x,sum,norm);
    return sum;
}


double model(double x, double y, struct MODPAR *modpar, int n_mod) {
    int k,j;
    double flux_tmp,flux;
    double *a;
    double x_c,y_c,pre_pa,pa,q;
    double Im,r_m,beta;
    double xp,yp,r;
    double c;
    double sig;
    int nnx;


    double v_rot,v_sys,incl,R,A,c0,p;

    flux=0;
    for (k=0;k<n_mod;k++) {
	x_c=modpar[k].a[1];
	y_c=modpar[k].a[2];
	Im=modpar[k].a[3];
	r_m=modpar[k].a[4];
	beta=modpar[k].a[5];
	pre_pa=modpar[k].a[6];
	pa=(3.14159/180.0)*modpar[k].a[6];
	while (pa>2*3.14159) {
	    pa-=2*3.14159;
	}
	while (pa<0) {
	    pa+=2*3.14159;
	}
	q=modpar[k].a[7];
/*
 * NOTE: 17.02.04
 * This parameter measures the 
 * BOX/DISKY structure.
 *
 * It is complex to handle. I would consider to take it out
 * and add it to a pure Moffat parameters.
 */

	c=modpar[k].a[8];
	sig=modpar[k].a[9];
//	v_rot=modpar[k].a[3];
	A=modpar[k].a[3];
	v_sys=modpar[k].a[4];
	incl=(3.14159/180.0)*modpar[k].a[5];
	c0=modpar[k].a[7];
	p=modpar[k].a[8];

	xp=(x-x_c)*cos(pa)+(y-y_c)*sin(pa);
	yp=(y-y_c)*cos(pa)-(x-x_c)*sin(pa);
	if (q==0) {
	    r=pow((pow(xp,(c+2))+pow(yp,(c+2))),1/(c+2));
	} else {
	    r=pow((pow(xp,(c+2))+pow(yp/q,(c+2))),1/(c+2));
	}

	if(strcmp(modpar[k].model, "gauss1d") == 0)
//	    flux_tmp=10.0;
	    gauss1d(x,modpar[k].a[2],modpar[k].a[1],modpar[k].a[3]);
	else if(strcmp(modpar[k].model, "moffat") == 0)
	    flux_tmp=Im/(pow((1+pow((r/r_m),2)),beta));
	else if(strcmp(modpar[k].model, "gauss") == 0)
	    flux_tmp=Im*exp(-0.5*pow((r/r_m),2));
//	    flux_tmp=gauss1d(r,Im,r_m,0);
//Im*exp(-pow((r/(2*r_m)),2));
	else if(strcmp(modpar[k].model, "disk") == 0)
	    flux_tmp=Im*exp(-(r/r_m));
	else if(strcmp(modpar[k].model, "sersic") == 0)
	    flux_tmp=Im*exp(-pow((r/r_m),beta));
	else if(strcmp(modpar[k].model, "vauc") == 0)
	    flux_tmp=Im*exp(-pow((r/r_m),0.25));
	else if(strcmp(modpar[k].model, "gsersic") == 0)
	    flux_tmp=gsersic(r,sig,Im,r_m,beta);
	else if(strcmp(modpar[k].model, "rot_cur") == 0)
	    flux_tmp=vel_model(x,y,x_c,y_c,A,v_sys,pa,incl,c0,p);
	else if(strcmp(modpar[k].model, "back") == 0)
	    flux_tmp=Im;
	else if(strcmp(modpar[k].model, "backp") == 0)
	  flux_tmp=modpar[k].a[0]+modpar[k].a[1]*x+modpar[k].a[2]*y+modpar[k].a[3]*pow(x,2)+modpar[k].a[4]*pow(y,2)+modpar[k].a[5]*x*y+modpar[k].a[6]*pow(y,2)+modpar[k].a[7]*pow(x,3)+modpar[k].a[8]*pow(y*x,3);
	else if (strcmp(modpar[k].model, "poly1d") == 0) {
	    fflush(stdout);
	    for (j=1;j<9;j++) {
		flux_tmp+=modpar[k].a[j]*pow(x,j-1);
	    }
	} else {
	    flux_tmp=0.0;
	}
	flux+=flux_tmp;
    }

    //printf("(%f,%f,%f,%f,%f,%f,%f,%f,%f,%f)\n",x,y,x_c,y_c,xp,yp,r,Im,r_m,flux);
/*
    if (flux!=flux) {
	flux=0;
    }
*/
    return flux;
}


double dmodel(double x, double y, struct MODPAR *modpar, int n_mod, int i_d) {
    int i,k,j;
    double flux1,flux2,flux;
    double d;
    double *a;
    int ndim;
    struct MODPAR newpar1[n_mod];
    struct MODPAR newpar2[n_mod];
    copy_modpar(newpar1,modpar,n_mod);
    copy_modpar(newpar2,modpar,n_mod);
    read_modpar(a,modpar,n_mod,&ndim);
    i=0;
    for (k=0;k<n_mod;k++) {
	for(j=1;j<=modpar[k].na;j++) {
	    if (modpar[k].ia[j]==1) {
		if (modpar[k].fixa[j]==-1) {
		    if (i==i_d) {

			d=fabs(0.1*newpar2[k].a[j]);
			if (d<0.01) {
			  d=0.01;
			}
			newpar2[k].a[j]+=(0.5*d);
			newpar1[k].a[j]-=(0.5*d);

/*
			d=fabs(0.0001*newpar2[k].a[j]);
			newpar2[k].a[j]+=0.001;
			newpar1[k].a[j]-=0.001;
*/
		    }
		    i++;
		}
	    }
	}
    }
    flux1=model(x,y,newpar1,n_mod);
    flux2=model(x,y,newpar2,n_mod);
    flux=(flux2-flux1)/d;
    return flux;
}



int write_out_file(char config[80],struct MODPAR *modpar, int n_mod, char *flag);

int write_model_res(char config[80], int n, float *w, float *y, float *y_mod, float *y_res, float *y_cont, char *flag);


int write_error_par(double **covar, struct MODPAR *modpar, int n_mod);

int write_only_error_par(double **covar, struct MODPAR *modpar, int n_mod);

int read_data(char* filename, struct IMG *img_out) {
    FILE *fichero;
    float temp_float;    
    int count_f,n,i,temp_int;
    struct IMG img;
    printf("Reading data...\n");
    n=0;
    if ((fichero=fopen(filename,"r"))==NULL) {
	printf("Error opening file: %s\n",filename);
	return(-1);
    } else {
	while( fscanf(fichero, "%f", &temp_float) != EOF) {	       			   
	    count_f++;
	if (count_f>3) {
	    count_f=0;
	    n++;
	}
	}
    }
    rewind(fichero);

    img.nx= n;
    img.x= (double *)malloc(n*sizeof(double));  
    img.y= (double *)malloc(n*sizeof(double));  
    img.flux= (double *)malloc(n*sizeof(double));  
    img.sigma= (double *)malloc(n*sizeof(double));  



    for(i=0;i<n;i++) {
	fscanf(fichero, "%d", &temp_int);
	fscanf(fichero, "%f", &temp_float);
	img.x[i]=temp_float;
	fscanf(fichero, "%f", &temp_float);
	img.y[i]=temp_float;
//	img.y[i]=1.0;
	fscanf(fichero, "%f", &temp_float);
	img.flux[i]=temp_float;
	img.sigma[i]=sqrt(fabs(temp_float));
	if (img.sigma[i]==0) {
	    img.sigma[i]=1.0;
	}
    }
    printf("File readed\n");

    *img_out=img;
    return(0);
}


int read_data_5(char* filename, struct IMG *img_out) {
    FILE *fichero;
    float temp_float;    
    int count_f,n,i,temp_int;
    struct IMG img;
    printf("Reading data...\n");
    n=0;
    if ((fichero=fopen(filename,"r"))==NULL) {
	printf("Error opening file: %s\n",filename);
	return(-1);
    } else {
	while( fscanf(fichero, "%f", &temp_float) != EOF) {	       			   
	    count_f++;
	if (count_f>4) {
	    count_f=0;
	    n++;
	}
	}
    }
    rewind(fichero);

    img.nx= n;
    img.x= (double *)malloc(n*sizeof(double));  
    img.y= (double *)malloc(n*sizeof(double));  
    img.flux= (double *)malloc(n*sizeof(double));  
    img.sigma= (double *)malloc(n*sizeof(double));  



    for(i=0;i<n;i++) {
	fscanf(fichero, "%d", &temp_int);
	fscanf(fichero, "%f", &temp_float);
	img.x[i]=temp_float;
	fscanf(fichero, "%f", &temp_float);
	img.y[i]=temp_float;
//	img.y[i]=1.0;
	fscanf(fichero, "%f", &temp_float);
	img.flux[i]=temp_float;
	fscanf(fichero, "%f", &temp_float);
	img.sigma[i]=temp_float;
	if (img.sigma[i]==0) {
	    img.sigma[i]=0.1;
	}
    }
    printf("File readed\n");

    *img_out=img;
    return(0);
}


int write_data(char* filename, struct IMG img_out, char *flag) {
    int k,i,j;
    FILE *fichero;
    printf("OUT File : %s\n",filename);
    if ((fichero=fopen(filename,flag))==NULL) {
	printf("Error opening file: %s\n",filename);
	return(-1);
    } else {    
	for (k=0;k<img_out.nx;k++) {
	    fprintf(fichero,"%d %f %f %f\n",k+1,img_out.x[k],img_out.y[k],img_out.flux[k]);
	}
    }
    fclose(fichero);


    return(0);
}


int read_modpar(double *a, struct MODPAR *modpar, int n_mod, int *ndim) {
    int k,i,j;
    i=0;
    for (k=0;k<n_mod;k++) {
	for(j=1;j<=modpar[k].na;j++) {
	    if (modpar[k].ia[j]==1) {
		if (modpar[k].fixa[j]==-1) {
		    i++;
		}
	    }
	}
    }
    a= (double *)malloc(i*sizeof(double));  
    i=0;
    for (k=0;k<n_mod;k++) {
	for(j=1;j<=modpar[k].na;j++) {
	    if (modpar[k].ia[j]==1) {
		if (modpar[k].fixa[j]==-1) {
		    a[i]=modpar[k].a[j];
		    i++;
		}
	    }
	}
    }
    *ndim=i;
    return(0);
}


int write_modpar(double *a, struct MODPAR *modpar, int n_mod, int *ndim) {
    int k,i,j;
    i=0;
    for (k=0;k<n_mod;k++) {
	for(j=1;j<=modpar[k].na;j++) {
	    if (modpar[k].ia[j]==1) {
		if (modpar[k].fixa[j]==-1) {
		    modpar[k].a[j]=a[i];
		    i++;
		} else {			    
		    modpar[k].a[j]=modpar[modpar[k].fixa[j]-1].a[j]+modpar[k].p_a[j]; 		    
		}
	    }
	}
    }
    *ndim=i;
    return(0);
}




int copy_modpar(struct MODPAR *newpar, struct MODPAR *modpar, int n_mod) {
    int k,j;
    int np=9;
    for (k=0;k<n_mod;k++) {
	
	strcpy(newpar[k].model,modpar[k].model);
	newpar[k].na=modpar[k].na;
	newpar[k].a=dvector(1,np);
	newpar[k].e_a=dvector(1,np);
	newpar[k].p_a=dvector(1,np);
	newpar[k].ia=ivector(1,np);
	newpar[k].fixa=ivector(1,np);
	for(j=1;j<=modpar[k].na;j++) {
	    newpar[k].a[j]=modpar[k].a[j];
	    newpar[k].e_a[j]=modpar[k].e_a[j];
	    newpar[k].p_a[j]=modpar[k].p_a[j];
	    newpar[k].ia[j]=modpar[k].ia[j];
	    newpar[k].fixa[j]=modpar[k].fixa[j];
	}
    }
    return(0);
}



int add_rand_modpar(struct MODPAR *modpar, int n_mod) {
    int k,j,ran;
    int np=9;
    float d,u;
    for (k=0;k<n_mod;k++) {
	for(j=1;j<=modpar[k].na;j++) {
	    if (modpar[k].ia[j]==1) {
		if (modpar[k].fixa[j]==-1) {
//		    srand(k+j);
		    ran=1+(int) (10.0*rand()/(RAND_MAX+1.0));
		    u=ran/5.0;
		    d=modpar[k].a[j]*u*pow(-1,ran);
		    modpar[k].a[j]+=d;		    
//		    printf("%f %f %f\n",d,modpar[k].a[j],u);
		}
	    }
	}
    }
    return(0);
}



int write_config(char config[80], struct MODPAR *modpar, int n_mod, int add_psf, double ssq, double min_delta_chisq, char *flag) {

  
  FILE *fichero;
  int i,k;
  int j;
  int np;
  double alamda;
  double **p_in,*y_in;
  double *p_test,*p_p_test;
  int ndim;
  double ftol;
  int nfunk;
  int niter;
  int nloop;
  
  printf("Config File : %s\n",config);
  if ((fichero=fopen(config,flag))==NULL) {
    printf("Error opening file: %s\n",config);
    return(-1);
  } else {    
    printf("File Opened...\n");
    fprintf(fichero, "%d\n", add_psf);
    fprintf(fichero, "%d\n", n_mod);
    fprintf(fichero, "%f\n", ssq);
    fprintf(fichero,"%f\n",min_delta_chisq);
    np=9;
    for(i=0;i<n_mod;i++) {
      fprintf(fichero,"%s\n",modpar[i].model); 
      for (j=0;j<np;) {
	j++;
	fprintf(fichero,"%g\t",modpar[i].a[j]); 
	fprintf(fichero,"%d\t",modpar[i].ia[j]); 	
	fprintf(fichero,"%g\t",modpar[i].p_a[j]); 	
	fprintf(fichero,"%g\t",modpar[i].p_a2[j]); 	
	fprintf(fichero,"%d\n",modpar[i].fixa[j]); 
      }
    }
  }
  fclose(fichero);
  printf("File Closed\n");
  fflush(stdout);    
  return(0);
}

int read_config(char config[80], struct MODPAR *modpar, int *n_modpar, int *add_psf_out, double *ssq_out, double *min_delta_chisq);



void function(double x, double y, double *flux, double dp[], struct MODPAR modpar[],int n_mod,int ma);

void my_mrqcof_xy(double x[], double x1[], double y[], double sig[], int ndata, 
		  double **alpha, double beta[], double *chisq,
	    void (*funcs)(double, double, double *, double [], struct MODPAR modpar[], int n_mod), 
		  struct MODPAR modpar[], int n_mod);

void my_mrqmin_xy( double x[], double x1[], double y[], double sig[], int ndata, 
		   double **covar, double **alpha, double *chisq,
		   void (*funcs)(double, double, double *, double [], struct MODPAR modpar[], int n_mod),
		   double *alamda, struct MODPAR modpar[], int n_mod);

int print_par(struct MODPAR *modpar, int n_mod);

int main (int nargs,char* args[]){

    int niter_max=80; // put that as an imput in the config??

    struct MODPAR modpar[MAX_MODELS];
    struct MODPAR tmppar[MAX_MODELS];
    int n_mod,i;
    FILE *fichero;
    char filename[80];
    int count_f=0;
    float temp_float;
    int j;
    
    struct IMG img,mod,res;
    int add_psf;
    double ssq,min_delta_chisq,chisq;
    int n;
    double chi_sq,real_chi_sq;

    float *xp,*yp,*yp_model,*yp_res,*sigma_p;
    float r_min,r_max,y_min,y_max;




    double **covar,**alpha;
    double alamda;
    double *a;
    int ndim;
  
    
    int niter=0;
    int nloop=0;

    float bias=0.0;
  if (nargs<3) {
      printf("No arguments\n USE: data_file Config_File [BIAS]\n");
      return(0);
  } 
  if (nargs==4) {
      bias=atof(args[3]);
      if (bias<0) {
	  bias=0;
      }
  }

  
  read_data(args[1],&img);

  for (j=0;j<img.nx;j++) {
      img.sigma[j]=sqrt(pow(img.sigma[j],2)+bias);
  }
  
  res.nx=img.nx;
  res.x= (double *)malloc(img.nx*sizeof(double));  
  res.y= (double *)malloc(img.nx*sizeof(double));  
  res.flux= (double *)malloc(img.nx*sizeof(double));  
  res.sigma= (double *)malloc(img.nx*sizeof(double));  


  
  mod.nx=img.nx;
  mod.x= (double *)malloc(img.nx*sizeof(double));  
  mod.y= (double *)malloc(img.nx*sizeof(double));  
  mod.flux= (double *)malloc(img.nx*sizeof(double));  
  mod.sigma= (double *)malloc(img.nx*sizeof(double));  
  



  xp= (float *)malloc(img.nx*sizeof(float));  
  yp= (float *)malloc(img.nx*sizeof(float));  
  yp_model= (float *)malloc(img.nx*sizeof(float));  
  yp_res= (float *)malloc(img.nx*sizeof(float));  
  r_min=100000;
  r_max=-100000;
  y_min=100000;
  y_max=-100000;
  n=img.nx;
/*
  for (i=0;i<img.nx;i++) {
      xp[i]=(float)img.x[i];
      yp[i]=(float)img.flux[i];      
      if (xp[i]>r_max) r_max=xp[i];
      if (yp[i]>y_max) y_max=yp[i];
      if (xp[i]<r_min) r_min=xp[i];
      if (yp[i]<y_min) y_min=yp[i];
  }
*/
  read_config(args[2],modpar,&n_mod,&add_psf,&ssq,&min_delta_chisq);
  
  printf("Config Readed");
  fflush(stdout);


  read_modpar(a,modpar,n_mod,&ndim);
  covar=dmatrix(1,ndim+1,1,ndim+1);
  alpha=dmatrix(1,ndim+1,1,ndim+1);
  
  alamda=-1.0;
/*
  cpgopen("/xterm");
  cpgask(0);
  cpgsci(1);
  cpgslw(2);
  cpgenv(r_min,r_max,y_min,y_max,0,0);
  cpglab("Wavelength", "Intensity", "");
  cpgpt(n,xp,yp,1);  
*/
  chisq=10e6;
  chi_sq=11e6;
  printf(".\n");
  fflush(stdout);
/*
  do {
      copy_modpar(tmppar,modpar,n_mod); 
      alamda=-1.0;
      chi_sq=chisq;
      
      my_mrqmin_xy(img.x,img.y,img.flux,img.sigma,img.nx-1,covar,alpha,&chisq,&function,&alamda,modpar,n_mod);
           printf("Iter=%d Chisq=%f (%f), %f (%f)\n",niter,chisq,ssq,chi_sq-chisq,min_delta_chisq);
      niter++;
      if (chi_sq<=chisq) {
	  copy_modpar(modpar,tmppar,n_mod);
	  niter=10;
	  printf("Iter=%d Chisq=%10f, %10f10, STOP\n",niter,chisq,chi_sq-chisq);
      } else {
	  printf("Iter=%d Chisq=%10f, %10f, FIT\n",niter,chisq,chi_sq-chisq);

	  if (niter>9) {
	      add_rand_modpar(modpar,n_mod); 
	      niter=0;
	      nloop++;
	  }
	  if (nloop>4) {
	      niter=0;
	  }
      }
  }   while (((chisq>ssq)&&(fabs(chi_sq-chisq)>min_delta_chisq))||(niter<10));
*/

  while ((((chisq>ssq)&&(fabs(chi_sq-chisq)>min_delta_chisq))||(niter<4))&&(niter<niter_max)) {
      alamda=-1.0;
      chi_sq=chisq;
      copy_modpar(tmppar,modpar,n_mod); 
      my_mrqmin_xy(img.x,img.y,img.flux,img.sigma,img.nx-1,covar,alpha,&chisq,&function,&alamda,modpar,n_mod);
      printf("Iter=%d Chisq=%g (%g), %g (%g), AL=%d\n",niter,chisq,ssq,chi_sq-chisq,min_delta_chisq,alamda);
      if ((alamda==-666)||(alamda==0)) {
	  copy_modpar(modpar,tmppar,n_mod); 
      }

      niter++;
  }

//  if ((niter==4)&&(chisq==) {
  
//  }

  for (i=0;i<img.nx;i++) {
      mod.flux[i]=model(img.x[i],img.y[i],modpar,n_mod);    
      res.flux[i]=img.flux[i]-mod.flux[i];
      mod.x[i]=img.x[i];
      mod.y[i]=img.y[i];
      res.x[i]=img.x[i];
      res.y[i]=img.y[i];
  }

  write_config("out_config.fit_2D_map",modpar,n_mod,add_psf,ssq,min_delta_chisq,"w");
  write_only_error_par(covar,modpar,n_mod);
  print_par(modpar,n_mod);


  write_data("fit_2D_map.mod",mod,"w");
  write_data("fit_2D_map.res",res,"w");
  write_out_file("out.fit_2D_map",modpar,n_mod,"w");





/*
  y_min=100000;
  y_max=-100000;
  for (i=0;i<img.nx;i++) {
      yp_model[i]=model(img.x[i],img.y[i],modpar,n_mod-1);    
      yp_res[i]=yp[i]-yp_model[i];
      if (yp_res[i]>y_max) y_max=yp_res[i];
      if (yp_res[i]<y_min) y_min=yp_res[i];
  }
  cpgline(n,xp,yp_model);  
  printf("Fitted\n");
  fflush(stdout);
  real_chi_sq=chisq/(img.nx-n_mod-1);
  printf("CHI_SQ=%f\n",real_chi_sq);
  write_error_par(covar,modpar,n_mod);
  print_par(modpar,n_mod);
  cpgpage();
  cpgenv(r_min,r_max,y_min,y_max,0,0);
  cpglab("Wavelength", "\\gD Intensity", "");
  cpgpt(n,xp,yp_res,1);  

  cpgend();
*/

}


void function(double x, double y, double *flux, double dp[], struct MODPAR modpar[],int n_mod, int ma) {
    double *a;
    int ndim,j;
    *flux=model(x,y,modpar,n_mod); 
//    printf("%f,%f,%f\n",x,y,*flux);
    for (j=1;j<=ma;j++) {
	dp[j]=dmodel(x,y,modpar,n_mod,j-1); 
    }
}


int read_config(char config[80], struct MODPAR *modpar, int *n_modpar, int *add_psf_out, double *ssq_out, double *min_delta_chisq) {

  
  FILE *fichero;
  int i,k;
  int j;
  int np;
  double alamda;
  double **p_in,*y_in;
  double *p_test,*p_p_test;
  int ndim;
  double ftol;
  int nfunk;
  int niter;
  int add_psf;
  
  double ssq;
  double min_delta_chisq_in;
  double tmp_d;
  float tmp_f;

  int tmp_i;
  int aceptable;
  int n_mod;

  printf("Config File : %s\n",config);
  if ((fichero=fopen(config,"r"))==NULL) {
    printf("Error opening file: %s\n",config);
    return(-1);
  } else {    
    printf("File Opened...\n");
    fscanf(fichero, "%d", &add_psf);
    if ((add_psf!=0)&&(add_psf!=1)) {
      add_psf=0;
    }
    printf("Add PSF=%d\n",add_psf);
    fflush(stdout);
    fscanf(fichero, "%d", &n_mod);
    printf("Num. Models= %d\n",n_mod);
    fflush(stdout);
    fscanf(fichero, "%f", &tmp_f);
    ssq=(double)tmp_f;
    printf("Chisq Lim= %f\n",ssq);
    fscanf(fichero, "%f", &tmp_f);
    min_delta_chisq_in=(double)tmp_f;
    printf("Min Delta_Chisq= %f\n",min_delta_chisq_in);
    fflush(stdout);
    np=9;
    ndim=0;  
    for(i=0;i<n_mod;i++) {
      modpar[i].a=dvector(1,np);
      modpar[i].e_a=dvector(1,np);
      modpar[i].p_a=dvector(1,np);
      modpar[i].p_a2=dvector(1,np);
      modpar[i].ia=ivector(1,np);
      modpar[i].fixa=ivector(1,np);
      fscanf(fichero,"%s",modpar[i].model); 
      
      for (j=0;j<np;) {
	j++;
	fscanf(fichero,"%g",&tmp_f); 
	modpar[i].a[j]=(double)tmp_f; 
	modpar[i].e_a[j]=0.0;
	fscanf(fichero,"%d",&tmp_i); 
	modpar[i].ia[j]=tmp_i; 
	fscanf(fichero,"%g",&tmp_f); 
	modpar[i].p_a[j]=(double)tmp_f; 
	fscanf(fichero,"%g",&tmp_f); 
	modpar[i].p_a2[j]=(double)tmp_f; 
	fscanf(fichero,"%d",&tmp_i); 
	modpar[i].fixa[j]=tmp_i; 
	if (modpar[i].ia[j]==1) {
	  ndim++;
	}
      }
     
      modpar[i].ia[np]=0;
      modpar[i].na=np;    
      
    }
  }
  fclose(fichero);
  printf("File Closed\n");
  fflush(stdout);    

  
  *n_modpar=n_mod;
  *add_psf_out=add_psf;
  *ssq_out=ssq;
  *min_delta_chisq=min_delta_chisq_in;

  return(0);
}

int write_out_file(char config[80],struct MODPAR *modpar, int n_mod, char *flag) {
    int k,i,j;
    FILE *fichero;
    printf("OUT File : %s\n",config);
    if ((fichero=fopen(config,flag))==NULL) {
        printf("Error opening file: %s\n",config);
        return(-1);
    } else {
        i=1;
        fprintf(fichero,"%d ",n_mod);
        for (k=0;k<n_mod;k++) {
            fprintf(fichero,"\n%s ",modpar[k].model);
            for(j=1;j<=modpar[k].na;j++) {
//                fprintf(fichero," %f %f",modpar[k].a[j],modpar[k].p_a[j]);
                fprintf(fichero," %f %f",modpar[k].a[j],modpar[k].e_a[j]);
            }
        }
        fprintf(fichero,"\n");
    }
    fclose(fichero);
    printf("File Closed\n");
    fflush(stdout);
    return(0);
}


