Exemple #1
0
/* Test harness routine, which contains test quadratic data, invokes
   mpfit() */
int testquadfit()
{
  double x[] = {-1.7237128E+00,1.8712276E+00,-9.6608055E-01,
		-2.8394297E-01,1.3416969E+00,1.3757038E+00,
		-1.3703436E+00,4.2581975E-02,-1.4970151E-01,
		8.2065094E-01};
  double y[] = {2.3095947E+01,2.6449392E+01,1.0204468E+01,
		5.40507,1.5787588E+01,1.6520903E+01,
		1.5971818E+01,4.7668524E+00,4.9337711E+00,
		8.7348375E+00};
  double ey[10];
  double p[] = {1.0, 1.0, 1.0};        /* Initial conditions */             
  double pactual[] = {4.7, 0.0, 6.2};  /* Actual values used to make data */
  double perror[3];		       /* Returned parameter errors */      
  int i;
  struct vars_struct v;
  int status;
  mp_result result;

  memset(&result,0,sizeof(result));          /* Zero results structure */
  result.xerror = perror;	                                      
  for (i=0; i<10; i++) ey[i] = 0.2;       /* Data errors */           

  v.x = x;
  v.y = y;
  v.ey = ey;

  /* Call fitting function for 10 data points and 3 parameters */
  status = mpfit(quadfunc, 10, 3, p, 0, 0, (void *) &v, &result);

  printf("*** testquadfit status = %d\n", status);
  printresult(p, pactual, &result);

  return 0;
}
Exemple #2
0
/* Test harness routine, which contains test data, invokes mpfit() */
int testfit()
{
	int j, k = 0;
	FILE *data;
	FILE *output;
	data = fopen("Compiled_Data.txt", "r");
	output = fopen("Constants.ini", "w");
	int n;
	fscanf(data, "%d", &n);
	double p[4];
	double x[820][2];
	double y[820];

	for (j = 0; j < n; j++)
	{
		fscanf(data, "%lf", &p[j]);
	}
	while (fscanf(data, "%lf,%lf,%lf", &x[k][0], &x[k][1], &y[k]) != EOF)
	{
		k++;
	}

	int i;
	struct vars_struct v;
	int status;
	mp_result result;
	mp_par constraints[4];

	memset(&result, 0, sizeof(result));       /* Zero results structure and parameter constraints */
	memset(constraints, 0, sizeof(constraints));
	for (i = 0; i < n / 2; i++)
	{
		constraints[2 * i].limited[0] = 1;
		constraints[2 * i].limited[1] = 1;
		constraints[2 * i].limits[0] = 0.0;
		constraints[2 * i].limits[1] = 100.0;
	}

	v.x = x;
	v.y = y;

	/* Call fitting function for 820 data points and 4 (n) parameters */
	status = mpfit(statfunc, 820, n, p, constraints, 0, (void *)&v, &result);

	fprintf(output, "*** testfit status = %d (Editing this file is not recommended)\n", status);
	for(i = 0; i < n; i++)
	{
		if (i % 2 == 0)
		{
			fprintf(output, "Maximum %d = %lf\n", i / 2, p[i]);
		} else
		{
			fprintf(output, "Weight %d = %lf\n", i / 2, p[i]);
		}
	}
	//printresult(p, &result);

	return 0;
}
Exemple #3
0
/* Test harness routine, which contains test gaussian-peak data 

   Example of fixing two parameter

   Commented example of how to put boundary constraints
*/
int testgaussfix()
{
  double x[] = {-1.7237128E+00,1.8712276E+00,-9.6608055E-01,
		-2.8394297E-01,1.3416969E+00,1.3757038E+00,
		-1.3703436E+00,4.2581975E-02,-1.4970151E-01,
		8.2065094E-01};
  double y[] = {-4.4494256E-02,8.7324673E-01,7.4443483E-01,
		4.7631559E+00,1.7187297E-01,1.1639182E-01,
		1.5646480E+00,5.2322268E+00,4.2543168E+00,
		6.2792623E-01};
  double ey[10];
  double p[] = {0.0, 1.0, 0.0, 0.1};       /* Initial conditions */            
  double pactual[] = {0.0, 4.70, 0.0, 0.5};/* Actual values used to make data*/
  double perror[4];			   /* Returned parameter errors */     
  mp_par pars[4];			   /* Parameter constraints */         
  int i;
  struct vars_struct v;
  int status;
  mp_result result;

  memset(&result,0,sizeof(result));  /* Zero results structure */
  result.xerror = perror;

  memset(pars,0,sizeof(pars));    /* Initialize constraint structure */
  pars[0].fixed = 1;              /* Fix parameters 0 and 2 */
  pars[2].fixed = 1;

  /* How to put limits on a parameter.  In this case, parameter 3 is
     limited to be between -0.3 and +0.2.
  pars[3].limited[0] = 0;    
  pars[3].limited[1] = 1;
  pars[3].limits[0] = -0.3;
  pars[3].limits[1] = +0.2;
  */

  for (i=0; i<10; i++) ey[i] = 0.5;

  v.x = x;
  v.y = y;
  v.ey = ey;

  /* Call fitting function for 10 data points and 4 parameters (2
     parameters fixed) */
  status = mpfit(gaussfunc, 10, 4, p, pars, 0, (void *) &v, &result);

  printf("*** testgaussfix status = %d\n", status);
  printresult(p, pactual, &result);

  return 0;
}
Exemple #4
0
int mp_nllsqfit(
    real *xdat,       /*  x[ndat][xdim]   or   x(xdim,ndat)   */
    int xdim,         /*  */
    real *ydat,       /*  y[ndat] */
    real *wdat,       /*  w[ndat] */
    real *ddat,       /*  d[ndat] */
    int ndat,         /*  */
    real *fpar,       /*  f[npar] */
    real *epar,       /*  e[npar] */
    int *mpar,        /*  m[npar] */
    int npar,         /*  */
    real tol,         /* tolerance to convergence */
    int its,          /* # iterations */
    real lab,         /* (small) mixing parameter (0 for linear) */
    rproc f,          /*  f */
    iproc df)         /*  df/da */
{
  float *x, *y, *sig, **covar, **alpha;
  float *a, chisq, ochisq, lamda, fac;
  int i, k, itst, *ia;
  int itc = 0;
  mp_config  *config = NULL;
  mp_par *pars = NULL;
  void *private_data = NULL;
  mp_result result;

  if (npar > MAXPAR) error("MAXPAR too small for npar");
  if (xdim > MAXPAR) error("MAXPAR too small for xdim");


  if (xdim != 1) error("mp_nllsqfit: cannot deal with xdim=%d",xdim);

  old_f = f;   /* mpfit only uses f, doesn't need df */

  mpfit(my_func, ndat, npar,
	xdat, pars, config, private_data, 
	&result);


  /* to be called as follows: */
  // funct(m,n,x,fvec,dvec,priv);

  return 0;                       /* return number of iterations */
}
Exemple #5
0
/* Test harness routine, which contains test data, invokes mpfit() */
int testlinfit()
{
  double x[] = {-1.7237128E+00,1.8712276E+00,-9.6608055E-01,
		-2.8394297E-01,1.3416969E+00,1.3757038E+00,
		-1.3703436E+00,4.2581975E-02,-1.4970151E-01,
		8.2065094E-01};
  double y[] = {1.9000429E-01,6.5807428E+00,1.4582725E+00,
		2.7270851E+00,5.5969253E+00,5.6249280E+00,
		0.787615,3.2599759E+00,2.9771762E+00,
		4.5936475E+00};
  double ey[10];
  /*      y = a - b*x    */
  /*              a    b */
  double p[2] = {1.0, 1.0};           /* Parameter initial conditions */
  double pactual[2] = {3.20, 1.78};   /* Actual values used to make data */
  double perror[2];                   /* Returned parameter errors */      
  int i;
  struct vars_struct v;
  int status;
  mp_result result;

  memset(&result,0,sizeof(result));       /* Zero results structure */
  result.xerror = perror;
  for (i=0; i<10; i++) ey[i] = 0.07;   /* Data errors */           

  v.x = x;
  v.y = y;
  v.ey = ey;

  /* Call fitting function for 10 data points and 2 parameters */
  status = mpfit(linfunc, 10, 2, p, 0, 0, (void *) &v, &result);

  printf("*** testlinfit status = %d\n", status);
  printresult(p, pactual, &result);

  return 0;
}
Exemple #6
0
do_line()
{
    real *x, *y, *dx, *dy, *dz;
    int i,j, mwt;
    real chi2,q,siga,sigb, sigma, d, sa, sb;
    real cov00, cov01, cov11, sumsq;
    real r, prob, z;
    void fit(), pearsn();

    if (nxcol < 1) error("nxcol=%d",nxcol);
    if (nycol < 1) error("nycol=%d",nycol);
    x = xcol[0].dat;
    y = ycol[0].dat;
    dx = (dxcolnr>0 ? dxcol.dat : NULL);
    dy = (dycolnr>0 ? dycol.dat : NULL);

#if HAVE_GSL
    if (dx) error("Cannot use GSL with errors in X column");
    gsl_fit_linear (x, 1, y, 1, npt, &b, &a, 
		    &cov00, &cov01, &cov11, &sumsq);
    printf("y=ax+b:  a=%g b=%g  cov00,01,11=%g %g %g   sumsq=%g\n",
	     a,b, cov00,cov01,cov11, sumsq);

    if (dy) {
      for (i=0; i<npt; i++)
	dy[i] = 1/(dy[i]*dy[i]);
      gsl_fit_wlinear (x, 1, dy, 1, y, 1, npt, &b, &a, 
		    &cov00, &cov01, &cov11, &chi2);
      printf("y=ax+b:  a=%g b=%g  cov00,01,11=%g %g %g   chi^2=%g\n",
	     a,b, cov00,cov01,cov11, chi2);

    }
#else

    if (dx) {
#if defined(TESTNR)
      warning("new FITEXY method");
      dz = (real *) allocate(npt*sizeof(real));
      for (i=0; i<npt; i++) dz[i] = 0.0;

      fitexy(x,y,npt,dx,dy,&b,&a,&sigb,&siga,&chi2,&q);
      printf("fitexy(x,y,dx,dy)    a=%g   b=%g  %g %g\n",b,a,sigb,siga);
      fitexy(x,y,npt,dz,dy,&a,&b,&siga,&sigb,&chi2,&q);
      printf("fitexy(x,y, 0,dy)    a=%g   b=%g  %g %g\n",a,b,siga,sigb);
      fitexy(x,y,npt,dx,dz,&a,&b,&siga,&sigb,&chi2,&q);
      printf("fitexy(x,y,dx, 0)    a=%g   b=%g  %g %g\n",a,b,siga,sigb);
      fit   (x,y,npt,dy, 1,&a,&b,&siga,&sigb,&chi2,&q);
      printf("fit   (x,y, 0,dy)    a=%g   b=%g  %g %g\n",a,b,siga,sigb);
      fit   (y,x,npt,dx, 1,&a,&b,&siga,&sigb,&chi2,&q);
      printf("fit   (y,x, 0,dx)    a=%g   b=%g  %g %g\n",a,b,siga,sigb);

      sa=sqrt(siga*siga+sqr(sigb*(a/b)))/b;
      sb=sigb/(b*b);
      printf("FITEXY: %11.6f %11.6f %11.6f %11.6f %11.6f %11.6f\n",
	     -a/b,1.0/b,sa,sb,chi2,q); 
#elif defined(TESTMP)
      struct vars_struct v;      /* private data for mpfit() */
      int status;
      mp_result result;
      double p[2] = {1.0, 1.0};
      double perror[2];

      warning("MPFIT method; mode mpfit=%d",mpfit_mode);

      bzero(&result,sizeof(result));
      result.xerror = perror;

      v.x = xcol[0].dat;
      v.y = ycol[0].dat;
      v.ex = dxcol.dat;
      v.ey = dycol.dat;
      v.mode = mpfit_mode;
      
      status = mpfit(linfitex, npt, 2, p, 0, 0, (void *) &v, &result);
      dprintf(1,"*** mpfit status = %d\n", status);

      printf("  CHI-SQUARE = %f    (%d DOF)\n", 
	     result.bestnorm, result.nfunc-result.nfree);
      printf("        NPAR = %d\n", result.npar);
      printf("       NFREE = %d\n", result.nfree);
      printf("     NPEGGED = %d\n", result.npegged);
      printf("       NITER = %d\n", result.niter);
      printf("        NFEV = %d\n", result.nfev);
      printf("\n");
      for (i=0; i<result.npar; i++) {
	printf("  P[%d] = %f +/- %f\n", 
	       i, p[i], result.xerror[i]);
      }
#else
      error("no dycol= implemented yet");
#endif
    } else {

      for(mwt=0;mwt<=1;mwt++) {

#if 1
	if (mwt>0 && nsigma>0) {
	  fit(x,y,npt,dy,0,&b,&a,&sigb,&siga,&chi2,&q);
	} else {
	  if (mwt>0 && dycolnr==0)
	    continue;             
	  fit(x,y,npt,dy,mwt,&b,&a,&sigb,&siga,&chi2,&q);
	}
#else
	if (mwt==0)
	  fit(x,y,npt,dy,mwt,&b,&a,&sigb,&siga,&chi2,&q);
	else
	  myfit(x,y,npt,dy,mwt,&b,&a,&sigb,&siga,&chi2,&q);
#endif
	dprintf(2,"\n");
	dprintf (1,"Fit:   y=ax+b\n");
	if (mwt == 0)
	  dprintf(1,"Ignoring standard deviations\n");
	else
	  dprintf(1,"Including standard deviation\n");
	printf("%12s %9.6f %18s %9.6f \n",
	       "a  =  ",a,"uncertainty:",siga);
	printf("%12s %9.6f %18s %9.6f \n",
	       "b  =  ",b,"uncertainty:",sigb);

	printf("%12s %9.6f %18s %9.6f \n",
	       "x0 =  ",-b/a,"uncertainty:",sqrt(sqr(sigb/a)+sqr(siga*b/(a*a))));
	printf("%12s %9.6f %18s %9.6f \n",
	       "y0 =  ",b,"uncertainty:",sigb);

	printf("%19s %14.6f \n","chi-squared: ",chi2);
	printf("%23s %10.6f %s\n","goodness-of-fit: ",q,
	       q==1 ? "(no Y errors supplied [dycol=])" : "");
      
	pearsn(x, y, npt, &r, &prob, &z);
      
	printf("%9s %g\n","r: ",r);
	printf("%12s %g\n","prob: ",prob);
	printf("%9s %g\n","z: ",z);
      
	if (mwt==0 && nsigma>0) {                
	  sigma = 0.0;
	  for(i=0; i<npt; i++)
	    sigma += sqr(y[i] - a*x[i] - b);
	  sigma /= (real) npt;
	  sigma = nsigma * sqrt(sigma);   /* critical distance */
	
	  for(i=0, j=0; i<npt; i++) {     /* loop over points */
	    d = ABS(y[i] - a*x[i] - b);
	    if (d > sigma) continue;
	    x[j] = x[i];                  /* shift them over */
	    y[j] = y[i];
	    if (dy) dy[j] = dy[i];
	    j++;
	  }
	  dprintf(0,"%d/%d points outside %g*sigma (%g)\n",
		  npt-j,npt,nsigma,sigma);
	  npt = j;
	}
      } /* mwt */
    } /* dxcol */
    
    if (outstr) write_data(outstr);
#endif
}
int DoIt(){
 
    /* Variable declarations */

    /* Generic use variables */

    int i,j,k,l,n;								/* Generic loop counters */

    /* DRMS/JSOC variables */

	char *harpnum,*time_range;					/* SHARPs ID and time range from module_args[] */
	double umb_sig, pen_sig;					/* Cutoffs for sunspots */
	int num_divs;								/* Number of divisions to break a data strip into for trend removal */
	char *drms_query;							/* The DRMS query we are going to send */
	int num_query_chars;						/* Number of characters in total query for malloc definition */
	CmdParams_t *params=&cmdparams;				/* For the module_args stuff */
	DRMS_RecordSet_t *drms_ids;					/* Holds the id structure of the records */
	DRMS_Record_t *drms_record;					/* Holds specific record information */
	DRMS_Segment_t *drms_segment;				/* Segment information */
	int drms_status;							/* Status variable */
	int num_records;							/* Number of records and variables to get the segment locations we need */
	
	/* cfitsio-related variables */

    fitsfile *v_ptr,*i_ptr,*c_ptr;		/* Pointers for FITS files */
    fitsfile *info_ptr;		
    int v_status,i_status,c_status;		/* Status checker for opening files */
    int info_status;					
    int hdu_pos,num_hdus;				/* HDU number and location */
    int needed_hdu;						/* The HDU we want to be on */
    int any_nulls;						/* Nonzero if there are null values in data */
    char i_filename[DRMS_MAXPATHLEN+1],v_filename[DRMS_MAXPATHLEN+1];		/* Containers for the filenames */
	char c_filename[DRMS_MAXPATHLEN+1],info_filename[DRMS_MAXPATHLEN+1];
	double nulval;							/* Container for what null values in data should be set to */
	long l_nulval;

    /* Needed FITS keywords */

    int naxis1,naxis2,naxis;			/* Length of axes */
    double crpix1,crpix2;				/* SHARPs CRPIX is the center of the Sun relative to the lower left of the patch (fortranL 1,1) */
    double imcrpix1,imcrpix2;			/* SHARPs IMCRPIX is the center of the Sun in full plate coordinates (fortran) */
    double cdelt1,cdelt2;				/* HMI pixel sizes in as */    double blank;						/* Values of bad data */
    double crota2,crln_obs,crlt_obs;	/* Rotation, carrington observer location */
    double dsun_obs,rsun_obs;			/* Distance to and radius of the sun, observed at t_obs */
    double obs_vr,obs_vw,obs_vn;		/* Satellite velocity keywords */
    TIME t_obs;							/* Observation time, ZULU */
    char **t_obs_s;						/* String version of observation time */
    long *quality;						/* Data quality keyword */
    
    /* Data-related variables */
    
    double **vlos_dat, **inc_dat;			/* Data arrays, size defined once naxis1/2 are known */
    double **con_dat;
    long **info_dat;
    double *v_pixel_strip;					/* Strip of pixels read from the field data */
    double *i_pixel_strip;					/* Strip of pixels read from the inclination data */
    double *c_pixel_strip;					/* Strip of pixels read from the continuum data */
    long *info_pixel_strip;					/* Strip of pixels read from the continuum data */
    long fpixel[2];							/* Holds the location of pixel to be read */
    LONGLONG nelements;						/* Number of elements in a strip to be read (naxis2) */
    FILE *outptr,*bad_outptr;				/* Pointer to the outfile */
    char outfile_name[25];					/* Name of the outfile */
    char bad_outfile_name[24];				/* Name of the outfile for bad quality*/
    
    /* Variables related to the actual task */
    
    double rscx,rscy;				/* Disk center, plate coordinates */
    double rllx,rlly;				/* Disk center, patch coordinates */
    double rpllx,rplly;				/* Lower left of patch, plate coordinates */
    double **radius;				/* Array to hold where the Sun's boundaries are, column major order */
	double umb,pen;					/* Intensity cutoffs for the umbra and penumbra */
    double num_good;				/* The number of nonzero continuum values in a sunspot region */
    double mu;						/* Angle from solar center */
    double rsun_pix,xx,yy,r;		/* Variables associated with radial boundaries */
    long *t_secs;					/* T_OBS time converted to seconds since UNIX epoch */
    double *umb_p_vel,*umb_n_vel;	/* Umbral LOS velocities */
    double *pen_p_vel,*pen_n_vel;	/* Penumbral LOS velocities */
    double umb_p_counter,umb_n_counter;	/* Counters for averages */
    double pen_p_counter,pen_n_counter;
    double vr,vn,vw,vt;				/* Various LOS velocities due to satellite motion and solar rotation */
    double vlos;					/* VLOS after removing all of the satellite motion and solar rotation */
    double **y_axis;				/* Array to be looped over wrt naxis2 to remove trends */
    double **y_error;				/* Error on y axis, taken as 1 */
    double **x_axis;				/* Array to be looped over that holds naxis1 information for fitting */
    double x,y;						/* Pixel location on the solar disk */
    double ttx,tty,tx,ty,zz;		/* Intermediate variables for coordinate conversions */
    double lat,lon;					/* Carrington coordinate latitude and longitude */
    double p,t;						/* Spherical phi and theta coordinates */
	int noaa_ar;					/* Active region number */
	mp_result result;				/* Fitting result structure */
	mp_config config;				/* Configuration options for fitting structure */
	double perror[2];				/* Error on fitting coefficients */
	double fit_params[2];			/* Fitting coefficients */
	struct vars_struct v;			/* Private data, shared between main and functions */
	int fit_status;					/* Fitting returned status */
	int inv_len;					/* Interval length for breaking data up */
	
       
    /* Initialise variables that need it */

    drms_status=0;
    
	memset(&result,0,sizeof(result));
	memset(&config,0,sizeof(config));
	
	/* Set the error stuff for cmfit */
	
	result.xerror=perror;
	
	/* Set the default options for cmfit */
	
	config.ftol=1.49012e-08;
	config.xtol=1.49012e-08;
	config.gtol=0.0;
	config.maxfev=0;
    
	/* Grab values from module_args[] */

	harpnum=strdup(params_get_str(params,"harpnum"));
	time_range=strdup(params_get_str(params,"time_range"));
	umb_sig=params_get_double(params,"umb_sig");
	pen_sig=params_get_double(params,"pen_sig");
	num_divs=params_get_int(params,"num_divs");
	
	/* Now we start the main program. The rough layout is as follows: 
	   
	   1. Query drms. Based on what we learn, either exit or grab what we need from it.
	   2. Loop through the files, calculate field stuff.
	   3. Print out a table of values at the end.				   */
	
	/* Forge the DRMS query. */
	
	num_query_chars=16+strlen(harpnum);		/* hmi.sharp_720s[] is 16 characters */
	
	if (time_range!="[]"){
		
		num_query_chars+=strlen(time_range);
		
	}
	
	drms_query=calloc(num_query_chars,sizeof(char));
	strcat(drms_query,"hmi.sharp_720s[");
	strcat(drms_query,harpnum);
	strcat(drms_query,"]");
	
	if (time_range!="[]"){
	
		strcat(drms_query,time_range);
		
	}
	
	/* Query DRMS for the records. */
	
	printf("Querying DRMS. This may take some time.\n");
	
	if (!(drms_ids=drms_open_records(drms_env,drms_query,&drms_status))){
		
		printf("No record sets match your criteria. Check your SHARPs ID and your time range.\n");
		drms_close_records(drms_ids,DRMS_FREE_RECORD);
		free(drms_query);
		return 0;
		
	}

	free(drms_query);

	num_records=drms_ids->n;
	printf("%d records match. Checking to make sure we have the needed data segments.\n",num_records);

	drms_record=drms_ids->records[0];

	if (!(drms_segment_lookup(drms_record,"vlos_mag"))){
		
		printf("vlos_mag segment not present! Exiting.\n");
		drms_close_records(drms_ids,DRMS_FREE_RECORD);
		return 0;
	
	}

	if (!(drms_segment_lookup(drms_record,"inclination"))){
		
		printf("Inclination segment not present! Exiting.\n");
		drms_close_records(drms_ids,DRMS_FREE_RECORD);
		return 0;
	
	}

	if (!(drms_segment_lookup(drms_record,"continuum"))){
		
		printf("Continuum segment not present! Exiting.\n");
		drms_close_records(drms_ids,DRMS_FREE_RECORD);
		return 0;
	
	}

	if (!(drms_segment_lookup(drms_record,"info_map"))){
		
		printf("Info_map segment not present! Exiting.\n");
		drms_close_records(drms_ids,DRMS_FREE_RECORD);
		return 0;

	}

	/* Now we can start. We loop over all records, get the keyword information we need, get the data, and then calculate. */
	
	/* First set the size of some of the pointers that are intended to be arrays. */
	
	/* Time-related arrays */
	
	t_secs=malloc(num_records*sizeof(long));
	t_obs_s=malloc(num_records*sizeof(char *));
	
	for (i=0;i<num_records;i++){
		
		t_obs_s[i]=malloc(T_OBS_LENGTH*sizeof(char));
		
	}
	
	/* Data-related arrays */
	
	umb_p_vel=malloc(num_records*sizeof(double));
	pen_p_vel=malloc(num_records*sizeof(double));
	umb_n_vel=malloc(num_records*sizeof(double));
	pen_n_vel=malloc(num_records*sizeof(double));

	/* Record quality */
	
	quality=malloc(num_records*sizeof(long));
	
	for (k=0;k<num_records;k++){ 

		drms_record=drms_ids->records[k];
		
		/* Check to see if we have data for a particular observation time */
		
		if (!(t_obs=drms_getkey_time(drms_record,"T_OBS",&drms_status))){
					
			printf("Keyword %s not present! Exiting.\n","T_OBS");
			drms_close_records(drms_ids,DRMS_FREE_RECORD);
			return 0;
		
		}
		
		if (time_is_invalid(t_obs)){
			
			printf("Bad record, skipping.\n");
			
		} else {
			
			if (k == 0){
				
				/* Get active region number for pregame info */
			
				if (!(noaa_ar=drms_getkey_int(drms_record,"NOAA_AR",&drms_status))){
					
					printf("Keyword %s not present! Exiting.\n","NOAA_AR");
					drms_close_records(drms_ids,DRMS_FREE_RECORD);
					return 0;
		
				}
				
				/* Create data output filename */
			
				sprintf(outfile_name,"AR%d.fvlos-output.dat",noaa_ar);
				sprintf(bad_outfile_name,"AR%d.bad-quality.dat",noaa_ar);
							
				/* Print out some stats before we run */
			
				printf("Pre-analysis details:\n");
				printf("Analyzing: HARP Number: %s\t NOAA AR: %d\n",harpnum,noaa_ar);
				printf("Output file: %s\n",outfile_name);
			
				if (time_range == "[]\0"){
				
					printf("We are covering the entire data set.\n");
			
				} else {
				
					printf("Time range: %s\n",time_range);
			
				}

				printf("\n\n");	
			}
			
			printf("Processing record %d of %d.\n",k+1,num_records);
		
			/* Fill keywords */
			
			if (!(quality[k]=drms_getkey_longlong(drms_record,"QUALITY",&drms_status))){
			
				quality[k]=0;
		
			}
	
			if (!(crpix1=drms_getkey_double(drms_record,"CRPIX1",&drms_status))){
			
				printf("Keyword %s not present! Exiting.\n","CRPIX1");
				drms_close_records(drms_ids,DRMS_FREE_RECORD);
				return 0;
		
			}
			
			if (!(crpix2=drms_getkey_double(drms_record,"CRPIX2",&drms_status))){
					
				printf("Keyword %s not present! Exiting.\n","CRPIX2");
				drms_close_records(drms_ids,DRMS_FREE_RECORD);
				return 0;
		
			}
		
		
			if (!(cdelt1=drms_getkey_double(drms_record,"CDELT1",&drms_status))){
					
				printf("Keyword %s not present! Exiting.\n","CDELT1");
				drms_close_records(drms_ids,DRMS_FREE_RECORD);
				return 0;
		
			}
			
			if (!(cdelt2=drms_getkey_double(drms_record,"CDELT2",&drms_status))){
					
				printf("Keyword %s not present! Exiting.\n","CDELT2");
				drms_close_records(drms_ids,DRMS_FREE_RECORD);
				return 0;
		
			}
		
			if (!(imcrpix1=drms_getkey_double(drms_record,"IMCRPIX1",&drms_status))){
					
				printf("Keyword %s not present! Exiting.\n","IMCRPIX1");
				drms_close_records(drms_ids,DRMS_FREE_RECORD);
				return 0;
		
			}
		
			if (!(imcrpix2=drms_getkey_double(drms_record,"IMCRPIX2",&drms_status))){
					
				printf("Keyword %s not present! Exiting.\n","IMCRPIX2");
				drms_close_records(drms_ids,DRMS_FREE_RECORD);
				return 0;
		
			}
		
			if (!(rsun_obs=drms_getkey_double(drms_record,"RSUN_OBS",&drms_status))){
					
				printf("Keyword %s not present! Exiting.\n","RSUN_OBS");
				drms_close_records(drms_ids,DRMS_FREE_RECORD);
				return 0;
		
			}

			if (!(dsun_obs=drms_getkey_double(drms_record,"DSUN_OBS",&drms_status))){
					
				printf("Keyword %s not present! Exiting.\n","DSUN_OBS");
				drms_close_records(drms_ids,DRMS_FREE_RECORD);
				return 0;
		
			}
			
			if (!(obs_vr=drms_getkey_double(drms_record,"OBS_VR",&drms_status))){
					
				printf("Keyword %s not present! Exiting.\n","OBS_VR");
				drms_close_records(drms_ids,DRMS_FREE_RECORD);
				return 0;
		
			}

			if (!(obs_vn=drms_getkey_double(drms_record,"OBS_VN",&drms_status))){
					
				printf("Keyword %s not present! Exiting.\n","OBS_VN");
				drms_close_records(drms_ids,DRMS_FREE_RECORD);
				return 0;
		
			}
			
			if (!(obs_vw=drms_getkey_double(drms_record,"OBS_VW",&drms_status))){
					
				printf("Keyword %s not present! Exiting.\n","OBS_VW");
				drms_close_records(drms_ids,DRMS_FREE_RECORD);
				return 0;
		
			}

			if (!(crota2=drms_getkey_double(drms_record,"CROTA2",&drms_status))){
					
				printf("Keyword %s not present! Exiting.\n","CROTA2");
				drms_close_records(drms_ids,DRMS_FREE_RECORD);
				return 0;
		
			}
		
			if (!(crln_obs=drms_getkey_double(drms_record,"CRLN_OBS",&drms_status))){
					
				printf("Keyword %s not present! Exiting.\n","CRLN_OBS");
				drms_close_records(drms_ids,DRMS_FREE_RECORD);
				return 0;
		
			}
		
			if (!(crlt_obs=drms_getkey_double(drms_record,"CRLT_OBS",&drms_status))){
					
				printf("Keyword %s not present! Exiting.\n","CRLT_OBS");
				drms_close_records(drms_ids,DRMS_FREE_RECORD);
				return 0;
		
			}

			if (!(blank=drms_getkey_double(drms_record,"BLANK",&drms_status))){
					
				printf("Keyword %s not present! Exiting.\n","BLANK");
				drms_close_records(drms_ids,DRMS_FREE_RECORD);
				return 0;
		
			}
		
			sprint_ut(t_obs_s[k],t_obs);		/* Convert to string */
		
			printf(" Checking quality.\n");
			
			if (quality[k] == 0){
		
				/* Ok, now we get the file locations for the data from DRMS. Originally I attempted
				* to pull the data directly from DRMS but there were vague free() and malloc() issues
				* possibly due to icc and multithreading, or library problems. */
		
				if (!(drms_segment=drms_segment_lookup(drms_record,"vlos_mag"))){
			
					printf("Problem opening the vlos_mag segment! Exiting.\n");
					drms_close_records(drms_ids,DRMS_FREE_RECORD);
					return 0;
			
				}
		
				drms_segment_filename(drms_segment,v_filename);
			
				if (!(drms_segment=drms_segment_lookup(drms_record,"continuum"))){
				
					printf("Problem opening the continuum segment! Exiting.\n");
					drms_close_records(drms_ids,DRMS_FREE_RECORD);
					return 0;
			
				}
		
				drms_segment_filename(drms_segment,c_filename);
			
				/* naxis1 and naxis2 we get from segment information */
		
				naxis1=(int)drms_segment->axis[0];
				naxis2=(int)drms_segment->axis[1];
		
				if (!(drms_segment=drms_segment_lookup(drms_record,"inclination"))){
			
					printf("Problem opening the inclination segment! Exiting.\n");
					drms_close_records(drms_ids,DRMS_FREE_RECORD);
					return 0;
			
				}
		
				drms_segment_filename(drms_segment,i_filename);
			
				if (!(drms_segment=drms_segment_lookup(drms_record,"info_map"))){
			
					printf("Problem opening the info_map segment! Exiting.\n");
					drms_close_records(drms_ids,DRMS_FREE_RECORD);
					return 0;
			
				}
			
				drms_segment_filename(drms_segment,info_filename);
			
				printf(" Opening FITs files.\n");
		
				/* Now open the FITS files and get to work. */
	
				v_status=0;
				i_status=0;
				c_status=0;
				info_status=0;
				any_nulls=0;

				if (fits_open_file(&v_ptr,v_filename,READONLY,&v_status)){
				
					printf("Cannot open %s! Exiting.\n",v_filename);
					exit(0);

				}

				if (fits_open_file(&i_ptr,i_filename,READONLY,&i_status)){
				
					printf("Cannot open %s! Exiting.\n",i_filename);
					fits_close_file(i_ptr,&i_status);
					exit(0);

				}
			
				if (fits_open_file(&c_ptr,c_filename,READONLY,&c_status)){
				
					printf("Cannot open %s! Exiting.\n",c_filename);
					fits_close_file(c_ptr,&c_status);
					exit(0);

				}
			
				if (fits_open_file(&info_ptr,info_filename,READONLY,&info_status)){
				
					printf("Cannot open %s! Exiting.\n",info_filename);
					fits_close_file(info_ptr,&info_status);
					exit(0);

				}
				
				
				/* Walk through the HDUs until we get to one with NAXIS=2 */

				/* Number of headers and which one we are on */

				fits_get_num_hdus(v_ptr,&num_hdus,&v_status);
				fits_get_hdu_num(v_ptr,&hdu_pos);

				/* Find the one with two naxes */

				naxis=0;

				for (i=1;i<=num_hdus;i++){
				
					fits_movabs_hdu(v_ptr,i,NULL,&v_status);
					fits_read_key(v_ptr,TINT,"NAXIS",&naxis,NULL,&v_status);
				
					if (naxis == 2){
	
						needed_hdu=i;
	
					}
				}


				/* Set all to the needed HDU */

				if (naxis == 0){
		
					printf("HDU problems: can't find one with the required number of axes.\n");
					fits_close_file(v_ptr,&v_status);
					fits_close_file(i_ptr,&i_status);
					fits_close_file(c_ptr,&c_status);
					fits_close_file(info_ptr,&info_status);
					exit(0);

				} else {

					fits_movabs_hdu(v_ptr,needed_hdu,NULL,&v_status);
					fits_movabs_hdu(i_ptr,needed_hdu,NULL,&i_status);
					fits_movabs_hdu(c_ptr,needed_hdu,NULL,&c_status);
					fits_movabs_hdu(info_ptr,needed_hdu,NULL,&info_status);

				}


				/* Now set some definite boundaries on arrays to help with memory usage. Arrays are called as con_dat[y][x]. */
				
				inv_len=naxis1/num_divs;
				
				vlos_dat=malloc(naxis2*sizeof(double *));
				inc_dat=malloc(naxis2*sizeof(double *));
				con_dat=malloc(naxis2*sizeof(double *));
				radius=malloc(naxis2*sizeof(double *));
				info_dat=malloc(naxis2*sizeof(long *));
				y_axis=malloc(num_divs*sizeof(double *));
				y_error=malloc(num_divs*sizeof(double *));
				x_axis=malloc(num_divs*sizeof(double *));
			
				v_pixel_strip=calloc(naxis1,sizeof(double));
				i_pixel_strip=calloc(naxis1,sizeof(double));
				c_pixel_strip=calloc(naxis1,sizeof(double));
				info_pixel_strip=calloc(naxis1,sizeof(long));
	
				for (j=0;j<naxis2;j++){
		
					vlos_dat[j]=calloc(naxis1,sizeof(double));
					inc_dat[j]=calloc(naxis1,sizeof(double));
					con_dat[j]=calloc(naxis1,sizeof(double));
					radius[j]=calloc(naxis1,sizeof(double));
					info_dat[j]=calloc(naxis1,sizeof(long));
		
				}
				
				for (j=0;j<(num_divs-1);j++){
					
					x_axis[j]=calloc((inv_len),sizeof(double));
					y_axis[j]=calloc((inv_len),sizeof(double));
					y_error[j]=calloc((inv_len),sizeof(double));
					
				}
				
				x_axis[num_divs-1]=calloc((inv_len + naxis1%num_divs),sizeof(double));
				y_axis[num_divs-1]=calloc((inv_len + naxis1%num_divs),sizeof(double));
				y_error[num_divs-1]=calloc((inv_len + naxis1%num_divs),sizeof(double));
				
				/* Next, put data in the arrays, clear out blank values and NaNs from the data */
	
				fpixel[0]=1;		/* cfitsio uses fortran reference instead of c when accessing data */
				nelements=naxis1;
				nulval=0;
				l_nulval=0;
				any_nulls=0;
    
				for (j=0;j<naxis2;j++){
		
					fpixel[1]=j+1;	/* Add 1 to account for fortran FITS indexing */
					fits_read_pix(v_ptr,TDOUBLE,fpixel,nelements,&nulval,v_pixel_strip,&any_nulls,&v_status);
					fits_read_pix(i_ptr,TDOUBLE,fpixel,nelements,&nulval,i_pixel_strip,&any_nulls,&i_status);
					fits_read_pix(c_ptr,TDOUBLE,fpixel,nelements,&nulval,c_pixel_strip,&any_nulls,&c_status);
					fits_read_pix(info_ptr,TLONG,fpixel,nelements,&l_nulval,info_pixel_strip,&any_nulls,&info_status);
		
					for (i=0;i<naxis1;i++){
			
						/* Kill blank values if present, if not assign to the correct place in array */
			
						if (v_pixel_strip[i] == blank){
				
							vlos_dat[j][i]=0.0;
					
						} else {
				
							vlos_dat[j][i]=v_pixel_strip[i];
			
						}
			
						if (i_pixel_strip[i] == blank){
				
							inc_dat[j][i]=0.0;
				
						} else {
					
							inc_dat[j][i]=i_pixel_strip[i];
			
						}

						if (c_pixel_strip[i] == blank){
				
							con_dat[j][i]=0.0;
			
						} else {
					
							con_dat[j][i]=c_pixel_strip[i];
			
						}
					
						info_dat[j][i]=info_pixel_strip[i];
					
					}
				}
				
		
				printf(" Analyzing data.\n");
	
				/* Coordinate variable definitions for future use. See the declaration section */
				/* at the front of the code to understand what these refer to. */
	
				rscx=(imcrpix1-1.0);
				rscy=(imcrpix2-1.0);
				rllx=(crpix1-1.0);
				rlly=(crpix2-1.0);
				rpllx=(rscx-rllx);
				rplly=(rscy-rlly);
	
				/* Fill the radius array, handle limb darkening */
	
				rsun_pix=rsun_obs/cdelt1;
	
				for (i=0;i<naxis1;i++){
		
					for (j=0;j<naxis2;j++){
			
						xx=(double)i-rllx;
						yy=(double)j-rlly;
						r=sqrt(xx*xx+yy*yy);
				
						if (r <= rsun_pix){
				
							radius[j][i]=r;
							mu=sqrt(1-pow(r/rsun_pix,2.0));
							con_dat[j][i]=con_dat[j][i]/limb_darken(mu);
					
						}
					}
				}
			
				/* Determine if we actually have an active region here. */
			
				spotbounds(con_dat,naxis1,naxis2,&umb,&pen,umb_sig,pen_sig);
			
				num_good=0;
	
				for (i=0;i<naxis1;i++){
		
					for (j=0;j<naxis2;j++){
		
						if ((radius[j][i] > 0)&&(con_dat[j][i] <= pen)&&(con_dat[j][i] > 0)){
				
							num_good++;
			
						}
					}
				}
	
				/* Now find the average LOS velocities. */
			
				umb_p_vel[k]=0;
				pen_p_vel[k]=0;
				umb_n_vel[k]=0;
				pen_n_vel[k]=0;
				
				umb_p_counter=0.0;
				umb_n_counter=0.0;
				pen_p_counter=0.0;
				pen_n_counter=0.0;
			
				if (num_good > 0){
					
					/* We're going to do these loops twice - first to remove any satellite and differential 
					 * rotation effects, then again to fit and remove trends. */
			
					/* First the satellite motion and the differential rotation */
			
					for (i=0;i<naxis1;i++){
				
						for (j=0;j<naxis2;j++){
							
							if ((radius[j][i] > 0)&&(good_pixel(info_dat[j][i]))){
								
								/* Get the pixel location in HPL coordinates */
							
								x=rpllx+(double)i;
								y=rplly+(double)j;
								
								/* Stonyhurst/carrington needed for photospheric velocity calcs */
							
								pixel2hpl(x,y,crota2,imcrpix1,imcrpix2,cdelt1,cdelt2,&tx,&ty);	
								hpl2stony(tx,ty,dsun_obs,crln_obs,crlt_obs,&lat,&lon);
								
								/* Photospheric rotation removal */
								
								vt=v_t(lat,0,0,0)*along_phi(t,p,dsun_obs); /*0's are for default coefficients */
							
								/* Convert to spherical with no rotation to account for sat orientation and handle LOS stuff */
							
								pixel2hpl(x,y,0.0,imcrpix1,imcrpix2,cdelt1,cdelt2,&tx,&ty);
								hpl2hpc(tx,ty,&ttx,&tty);
								hpc2hcc(ttx,tty,dsun_obs,&xx,&yy,&zz);
								hcc2sphere(xx,yy,zz,&t,&p);
							
								/* LOS satellite velocity components */
							
								vr=obs_vr*along_obs(t,p,dsun_obs);
								vn=obs_vn*along_north(t,p,dsun_obs);
								vw=obs_vw*along_west(t,p,dsun_obs);
								
								/* vlos after removing all of the doppler effects. The 
								 * division by 100 is to convert cm/s to m/s. */
								
								vlos_dat[j][i]=(vlos_dat[j][i]/100)-vr-vn-vw-vt;
								
							}
						}
					}
					
					/* Next we fit a function across x, not including points that would be in a sunspot or off-disk points.
					 * Then we subtract this trend from the remaining data. */
					 
					for (j=0;j<naxis2;j++){
				
						/* Fill the arrays along x */
				
						for (i=0;i<num_divs;i++){
							
							if (i < (num_divs-1)){
								
								/* There are a total of num_divs segments in a data strip.
								 * To handle remainders when determining how many points to 
								 * place in a segment, we first do the remainderless ones.
								 * The last may or may not have a remainder, but that's where
								 * one would go if it did, so we do it separately. */
							
								for (l=0;l<inv_len;l++){
									
									n=i*inv_len+l;
									y_error[i][l]=1;
									x_axis[i][l]=(double)n;
									
							
									if ((radius[j][n] > 0)&&(con_dat[j][n] > pen)&&(good_pixel(info_dat[j][n]))){
								
										y_axis[i][l]=vlos_dat[j][n];
								
									} else {
								
										y_axis[i][l]=0.0;
								
									}
						
								}
								
							} else {
								
								/* Handle the one that might have a remainder */
								
								for (l=0;l<(inv_len + naxis1%num_divs);l++){
									
									n=(num_divs-1)*inv_len+l;
									y_error[num_divs-1][l]=1;
									x_axis[num_divs-1][l]=(double)n;
									
							
									if ((radius[j][n] > 0)&&(con_dat[j][n] > pen)&&(good_pixel(info_dat[j][n]))){
								
										y_axis[num_divs-1][l]=vlos_dat[j][n];
								
									} else {
								
										y_axis[num_divs-1][l]=0.0;
								
									}
						
								}
								
							}
							
						}
						
						/* Now we fit, but in strips determined by num_divs */
						
						for (i=0;i<num_divs;i++){
							
							if (i < (num_divs-1)){
									
								v.x=x_axis[i];
								v.y=y_axis[i];
								v.ey=y_error[i];
	
								fit_status=mpfit(fit_me,inv_len,2,fit_params,0,&config,(void *)&v,&result);
								
								for (l=0;l<inv_len;l++){
									
									n=i*inv_len+l;
									vlos_dat[j][n]=vlos_dat[j][n]-(fit_params[0]*x_axis[i][l]+fit_params[1]);	/* Subtract trend */
									
								}
								
							} else {
								
								v.x=x_axis[num_divs-1];
								v.y=y_axis[num_divs-1];
								v.ey=y_error[num_divs-1];
	
								fit_status=mpfit(fit_me,inv_len + naxis1%num_divs,2,fit_params,0,&config,(void *)&v,&result);
							
								for (l=0;l<(inv_len + naxis1%num_divs);l++){
									
									n=(num_divs-1)*inv_len+l;
									vlos_dat[j][n]=vlos_dat[j][n]-(fit_params[0]*x_axis[num_divs-1][l]+fit_params[1]);	/* Subtract trend */
									
								}
								
							}
						}	
								
					}
					
					/* Finally, we have a clean data set. Now get to work on it. */
					 
					 
					for (i=0;i<naxis1;i++){
				
						for (j=0;j<naxis2;j++){
							
							if ((radius[j][i] > 0)&&(con_dat[j][i] < pen)&&(good_pixel(info_dat[j][i]))){
						
								/* "Positive" sunspot polarities. */
								
								vlos=vlos_dat[j][i];
							
								if (inc_dat[j][i] < 90){
								
									if (con_dat[j][i] <= umb){
									
										umb_p_vel[k]+=vlos;
										umb_p_counter++;
								
									}
								
									if (con_dat[j][i] > umb){
									
										pen_p_vel[k]+=vlos;
										pen_p_counter++;
									
									}
								
					
								}
					
								/* "Negative" sunspot polarities. */
					
								if (inc_dat[j][i] > 90){
							
								
									if (con_dat[j][i] <= umb){
									
										umb_n_vel[k]+=vlos;
										umb_n_counter++;
								
									}
								
									if (con_dat[j][i] > umb){
									
										pen_n_vel[k]+=vlos;
										pen_n_counter++;
									
									}
					
								}
							
							}
						}
					}
				
				}
				
				if (umb_p_counter > 0){
					
					umb_p_vel[k]/=umb_p_counter;
					
				} else {
					
					umb_p_vel[k]=0;
					
				}
			
				if (umb_n_counter > 0){
					
					umb_n_vel[k]/=umb_n_counter;
					
				} else {
					
					umb_n_vel[k]=0;
					
				}
				
				if (pen_p_counter > 0){
					
					pen_p_vel[k]/=pen_p_counter;
					
				} else {
					
					pen_p_vel[k]=0;
					
				}

				if (pen_n_counter > 0){
					
					pen_n_vel[k]/=pen_n_counter;
					
				} else {
					
					pen_n_vel[k]=0;
					
				}
				
			
				/* Free up dynamic arrays and close the files for the next iteration. */
				
				for (i=0;i<naxis2;i++){
				
					free(vlos_dat[i]);
					free(inc_dat[i]);
					free(con_dat[i]);
					free(radius[i]);
					free(info_dat[i]);
					
				}
				
				free(vlos_dat);
				free(inc_dat);
				free(con_dat);
				free(radius);
				free(info_dat);
				
				
				free(v_pixel_strip);
				free(i_pixel_strip);
				free(c_pixel_strip);
				free(info_pixel_strip);
				
				free(x_axis);
				free(y_axis);
				free(y_error);
			
				fits_close_file(v_ptr,&v_status);
				fits_close_file(i_ptr,&i_status);
				fits_close_file(c_ptr,&c_status);
				fits_close_file(info_ptr,&info_status);

			}
	
		}
	
		printf(" Completed run %d of %d.\n",k+1,num_records);
		
	}
	
	/* Output the results to a text file. */
	
	/* First, convert t_obs to a more reasonable product. */
	
	for (i=0;i<num_records;i++){			
	
		t_secs[i]=isotime(t_obs_s[i]);

	}

	printf("Writing to file %s.\n",outfile_name);
	
	outptr=fopen(outfile_name,"w");
	bad_outptr=fopen(bad_outfile_name,"w");
	
	fprintf(outptr,"Active Region: %d\tVelocities are in m/s, fvlos is scaled to remove limb effects.\n",noaa_ar);
	fprintf(outptr,"Full UT Time            time(s)  vlos pumb  vlos ppen  vlos numb  vlos npen\n");
	fprintf(outptr,"----------------------  -------  ---------  ---------  ---------  ---------\n");

	fprintf(bad_outptr,"Active Region: AR%d\n",noaa_ar);
	fprintf(bad_outptr,"Full UT Time            quality  time(s)  number\n");
	fprintf(bad_outptr,"----------------------  -------  -------  ------\n");
	
	for (i=0;i<num_records;i++){
		
		/* Make times relative to the first recorded one. */
		
		if (quality[i] == 0){
		
			fprintf(outptr,"%s  %7ld  %6.2lf  %6.2lf  %6.2lf  %6.2lf\n",t_obs_s[i],t_secs[i]-t_secs[0],umb_p_vel[i],pen_p_vel[i],umb_n_vel[i],pen_n_vel[i]);
		
		} else {
			
			fprintf(bad_outptr,"%s  0x%08lX  %7ld  %d\n",t_obs_s[i],quality[i],t_secs[i],i+1);		
		
		}

	}
	
	fclose(outptr);
	fclose(bad_outptr);
	
	printf("Done!\n");
	
	/* Free memory associated with dynamic arrays. */

	free(t_secs);
	free(t_obs_s);
	
	free(umb_p_vel);
	free(pen_p_vel);
	free(umb_n_vel);
	free(pen_n_vel);
	
	free(quality);
	
	
	/* Close the drms records connection */
	
	drms_close_records(drms_ids,DRMS_FREE_RECORD);
    
	/* Done! */
    
	return 0;
}
Exemple #8
0
int fit_peak (struct params* p, double *freq, double *amp, double *width, double*** pol, double delta_nu, double delta_k, int nnu, int ntheta, int k)
{
	int ii, ij, ik, mpreturn;
	double *param, *xerror;
	mp_par *bounds;
	mp_result *mpres2;
	mp_config *mpconf;
	struct kslice sub;

	param = (double*) malloc(4*sizeof(double));
	param[0] = *freq;
	param[1] = *amp;
	param[2] = *width;
	param[3] = (*amp)*0.1;

	mpres2 = (mp_result*) calloc(1,sizeof(mp_result));
	mpconf = (mp_config*) calloc(1, sizeof(mp_config));

	/* Load subsection data */
	sub.par = p;
	sub.start = (param[0] - 1.0*param[2])/delta_nu;
	sub.end = (param[0] + 1.0*param[2])/delta_nu;
	if (sub.start < 0) sub.start = 0;
	if (sub.end >= nnu) sub.end = nnu-1;
	sub.ntheta = ntheta;
	sub.delta_nu = delta_nu;
	sub.k = (k+1)*delta_k;
	sub.data = malloc((sub.end-sub.start+1)*sizeof(double*));
	for (ii=sub.start; ii<=sub.end; ii++)
	{
		sub.data[ii-sub.start] = malloc(ntheta*sizeof(double));
		for (ik=0; ik<ntheta; ik++)
		{
			sub.data[ii-sub.start][ik] = pol[ii][k][ik];
		}
	}

	bounds = malloc(4*sizeof(mp_par));
	xerror = calloc(4, sizeof(double));

	for (ii=0; ii<4; ii++)
	{
		bounds[ii].fixed = 0;
		bounds[ii].side = 0;
		bounds[ii].deriv_debug = 0;
		bounds[ii].relstep = 0.0;
		bounds[ii].step = 0.0;
		bounds[ii].limited[0] = bounds[ii].limited[1] = 0;
	}
	bounds[0].limited[0] = bounds[0].limited[1] = 1;
	bounds[0].limits[0] = sub.start*delta_nu;
	bounds[0].limits[1] = sub.end*delta_nu;
	bounds[1].limited[0] = 1;
	bounds[1].limits[0] = 0.0;
	bounds[2].limited[0] = bounds[2].limited[1] = 1;
	bounds[2].limits[0] = param[2]/2.;
	bounds[2].limits[1] = param[2]*2.;
	bounds[3].limited[0] = 1;
	bounds[3].limited[1] = 0;
	bounds[3].limits[0] = 0.0;

	mpconf->ftol = 1e-8;
	mpconf->xtol = 1e-4;
	mpconf->gtol = 1e-8;
	mpconf->covtol = 1e-10;
	mpconf->maxiter = 200;
	mpconf->nofinitecheck = 1;

	mpres2->xerror = xerror;
	mpreturn = 1;
	mpreturn = mpfit(&funk_single, ntheta*(sub.end-sub.start+1), 4, 
					param, bounds, mpconf, &sub, mpres2);
	*freq = param[0];
	*amp = param[1]+param[3];/**20.;*param[0];*/
	*width = param[2];

	FILE *fp;
	double den;
	fp = fopen("debug2", "w");
	for (ii=sub.start; ii<=sub.end; ii++)
	{
		for (ij=0; ij<ntheta; ij++)
		{
		den = ii*delta_nu - *freq;
		den = den*den + (*width)*(*width)/4.0;
		fprintf(fp, "%f\t%f\t%f\n", ii*delta_nu, param[3]+(*amp)*(*width)/(2.0*den), sub.data[ii-sub.start][ij]);
		}
	}
	fclose(fp);

	free(param);
	free(bounds);
	free(xerror);
	free(mpres2);
	free(mpconf);
	for (ii=sub.start; ii<=sub.end; ii++)
	{
		free(sub.data[ii-sub.start]);
	}
	free(sub.data);

	return 0;
}