/*
** The HAE to HEEQ transformation is given by the matrix
**
** 	S2 = <theta0,Z>*<i,X>*<Omega,Z>
**
** where the rotation angle theta0 is the the longitude of the Sun's
** central meridian, i is the the inclination of the Sun's equator and
** Omega is the the ecliptic longitude of the ascending node of the Sun's
** equator. This transformation comprises a rotation in the plane of the
** ecliptic from the First Point of Aries to the ascending node of the
** solar equator, then a rotation from the plane of the ecliptic to the 
** plane of the equator and finally a rotation in the plane of the solar
** equator from the ascending node to the central meridian. 
**
** Implemented by Kristi Keller on 2/2/2004
*/
void
mat_S2(const double et, Mat mat)
{
  Mat mat_tmp;
  double Omega = 73.6667+0.013958*(MJD(et)+3242)/365.25;
  double theta0 = atand(cosd(7.25) * tand(lambda0(et)-Omega));
  double angle_1 = lambda0(et)-Omega;
  angle_1=fmod(angle_1,360.0);
  if (angle_1 < 0.0) angle_1+=360.0;

  theta0=fmod(theta0,360.0);
  if (theta0 < 0.0) theta0+=360.0;
  if (angle_1 < 180.0) {
      if (theta0 < 180.0) theta0+=180.0;
       }
  if (angle_1 > 180.0) {
      if (theta0 > 180.0) theta0-=180.0;
       }
  hapgood_matrix(theta0, Z, mat);

  hapgood_matrix(7.25, X, mat_tmp);
  mat_times_mat(mat, mat_tmp, mat);

  hapgood_matrix(Omega, Z, mat_tmp);
  mat_times_mat(mat, mat_tmp, mat);
}
Exemple #2
0
/***********************************************************************//**
 * @brief Cartesian-to-spherical deprojection
 *
 * @param[in] nx X vector length.
 * @param[in] ny Y vector length (0=no replication).
 * @param[in] sxy Input vector step.
 * @param[in] spt Output vector step.
 * @param[in] x Vector of projected x coordinates.
 * @param[in] y Vector of projected y coordinates.
 * @param[out] phi Longitude of the projected point in native spherical
 *                 coordinates [deg].
 * @param[out] theta Latitude of the projected point in native spherical
 *                   coordinates [deg].
 * @param[out] stat Status return value for each vector element (always 0)
 *
 * Deproject Cartesian (x,y) coordinates in the plane of projection to native
 * spherical coordinates (phi,theta).
 *
 * This method has been adapted from the wcslib function prj.c::carx2s().
 * The interface follows very closely that of wcslib. In contrast to the
 * wcslib routine, however, the method assumes that the projection has been
 * setup previsouly (as this will be done by the constructor).
 ***************************************************************************/
void GWcsSTG::prj_x2s(int nx, int ny, int sxy, int spt, 
                      const double* x, const double* y,
                      double* phi, double* theta, int* stat) const
{
    // Initialize projection if required
    if (!m_prjset)
        prj_set();

    // Set value replication length mx,my
    int mx;
    int my;
    if (ny > 0) {
        mx = nx;
        my = ny;
    } 
    else {
        mx = 1;
        my = 1;
        ny = nx;
    }
    
    // Do x dependence
    const double* xp     = x;
    int           rowoff = 0;
    int           rowlen = nx * spt;
    for (int ix = 0; ix < nx; ++ix, rowoff += spt, xp += sxy) {
        double  xj   = *xp + m_x0;
        double* phip = phi + rowoff;
        for (int iy = 0; iy < my; ++iy, phip += rowlen)
            *phip = xj;
    }

    // Do y dependence
    const double* yp     = y;
    double*       phip   = phi;
    double*       thetap = theta;
    int*          statp  = stat;
    for (int iy = 0; iy < ny; ++iy, yp += sxy) {
        double yj  = *yp + m_y0;
        double yj2 = yj*yj;
        for (int ix = 0; ix < mx; ++ix, phip += spt, thetap += spt) {
            double xj = *phip;
            double r  = sqrt(xj*xj + yj2);
            if (r == 0.0)
                *phip = 0.0;
            else
                *phip = atan2d(xj, -yj);
            *thetap    = 90.0 - 2.0*atand(r*m_w[1]);
            *(statp++) = 0;
        }
    }

    // Return
    return;
}
Exemple #3
0
void geodtgc(int iopt,double *gdlat,double *gdlon,
             double *grho,double *glat,
			 double *glon,double *del) {

   double a=6378.16;
   double f=1.0/298.25;
   double b,e2;

   b=a*(1.0-f);
   e2=(a*a)/(b*b)-1;
   if (iopt>0) {
     *glat=atand( (b*b)/(a*a)*tand(*gdlat));
     *glon=*gdlon;
     if (*glon > 180) *glon=*glon-360;
   } else {
     *gdlat=atand( (a*a)/(b*b)*tand(*glat));
     *gdlon=*glon;
   }
   *grho=a/sqrt(1.0+e2*sind(*glat)*sind(*glat));
   *del=*gdlat-*glat;
}
Exemple #4
0
void fldpnth_gs(double gdlat,double gdlon,double psi,double bore,
			 double fh,double r,double *frho,double *flat,
	                 double *flon) {

  double rrad,rlat,rlon,del;
  double tan_azi,azi,rel,xel,fhx,xal,rrho,ral,xh;
  double dum,dum1,dum2,dum3;
  double frad;  
 
  if (fh<=150) xh=fh;
  else {
    if (r<=300) xh=115;
    else if ((r>300) && (r<500)) xh=(r-300)/200*(fh-115)+115;
    else xh=fh;
  }

  if (r<150) xh=(r/150.0)*115.0;
  geodtgc(1,&gdlat,&gdlon,&rrad,&rlat,&rlon,&del);
  rrho=rrad;
  frad=rrad;
 

  do {
    *frho=frad+xh;
  
    rel=asind( ((*frho**frho) - (rrad*rrad) - (r*r)) / (2*rrad*r));
    xel=rel;
    if (((cosd(psi)*cosd(psi))-(sind(xel)*sind(xel)))<0) tan_azi=1e32;
      else tan_azi=sqrt( (sind(psi)*sind(psi))/
                ((cosd(psi)*cosd(psi))-(sind(xel)*sind(xel))));
    if (psi>0) azi=atand(tan_azi)*1.0;
      else azi=atand(tan_azi)*-1.0;
    xal=azi+bore;
    geocnvrt(gdlat,gdlon,xal,xel,&ral,&dum);

    fldpnt(rrho,rlat,rlon,ral,rel,r,frho,flat,flon);
    geodtgc(-1,&dum1,&dum2,&frad,flat,flon,&dum3);
    fhx=*frho-frad; 
  } while(fabs(fhx-xh) > 0.5);
} 
Exemple #5
0
/***********************************************************************//**
 * @brief Cartesian-to-spherical deprojection
 *
 * @param[in] nx X vector length.
 * @param[in] ny Y vector length (0=no replication).
 * @param[in] sxy Input vector step.
 * @param[in] spt Output vector step.
 * @param[in] x Vector of projected x coordinates.
 * @param[in] y Vector of projected y coordinates.
 * @param[out] phi Longitude of the projected point in native spherical
 *                 coordinates [deg].
 * @param[out] theta Latitude of the projected point in native spherical
 *                   coordinates [deg].
 * @param[out] stat Status return value for each vector element (always 0)
 *
 * Deproject Cartesian (x,y) coordinates in the plane of projection to native
 * spherical coordinates (phi,theta).
 *
 * This method has been adapted from the wcslib function prj.c::merx2s().
 * The interface follows very closely that of wcslib. In contrast to the
 * wcslib routine, however, the method assumes that the projection has been
 * setup previsouly (as this will be done by the constructor).
 ***************************************************************************/
void GWcsMER::prj_x2s(int nx, int ny, int sxy, int spt, 
                      const double* x, const double* y,
                      double* phi, double* theta, int* stat) const
{
    // Initialize projection if required
    if (!m_prjset) {
        prj_set();
    }

    // Set value replication length mx,my
    int mx;
    int my;
    if (ny > 0) {
        mx = nx;
        my = ny;
    } 
    else {
        mx = 1;
        my = 1;
        ny = nx;
    }
    
    // Do x dependence
    const double* xp     = x;
    int           rowoff = 0;
    int           rowlen = nx * spt;
    for (int ix = 0; ix < nx; ++ix, rowoff += spt, xp += sxy) {
        double  s    = m_w[1] * (*xp + m_x0);
        double* phip = phi + rowoff;
        for (int iy = 0; iy < my; ++iy, phip += rowlen) {
            *phip = s;
        }
    }

    // Do y dependence
    const double* yp     = y;
    double*       thetap = theta;
    int*          statp  = stat;
    for (int iy = 0; iy < ny; ++iy, yp += sxy) {
        double t = 2.0 * atand(std::exp((*yp + m_y0)/m_r0)) - 90.0;
        for (int ix = 0; ix < mx; ++ix, thetap += spt) {
            *thetap    = t;
            *(statp++) = 0;
        }
    }

    // Return
    return;
}
Exemple #6
0
void geocnvrt(double gdlat,double gdlon,
			  double xal,double xel,double *ral,double *rel) {

  double kxg,kyg,kzg,kxr,kyr,kzr;
  double rrad,rlat,rlon,del;

  kxg=cosd(xel)*sind(xal);
  kyg=cosd(xel)*cosd(xal);
  kzg=sind(xel);
  geodtgc(1,&gdlat,&gdlon,&rrad,&rlat,&rlon,&del);
  kxr=kxg;
  kyr=kyg*cosd(del)+kzg*sind(del);
  kzr=-kyg*sind(del)+kzg*cosd(del);

  *ral=atan2d(kxr,kyr);
  *rel=atand(kzr/sqrt((kxr*kxr)+(kyr*kyr)));
}
void scan_to_latlon(meta_parameters *meta,
        double x, double y, double z,
        double *lat_d, double *lon, double *height)
{
  double qlat, qlon;
  double lat,radius;
  vector pos;
  meta_projection *proj = meta->projection;

  if (z != 0.0) {
    // height correction applies directly to y (range direction)
    double line, samp;
    line = (y-proj->startY)/proj->perY - meta->general->start_line;
    samp = (x-proj->startX)/proj->perX - meta->general->start_sample;
    double sr = meta_get_slant(meta,line,samp);
    double er = proj->param.atct.rlocal;
    double ht = meta_get_sat_height(meta,line,samp);
    double cos_ang = (sr*sr + er*er - ht*ht)/(2.0*sr*er);
    if (cos_ang > 1) cos_ang = 1;
    if (cos_ang < -1) cos_ang = -1;
    double incid = PI-acos(cos_ang);
    x += z*tan(PI/2-incid);
  }

  if (meta->sar->look_direction=='R')
    qlat = -x/proj->param.atct.rlocal; /* Right looking sar */
  else
    qlat =  x/proj->param.atct.rlocal; /* Left looking sar */
  qlon = y/(proj->param.atct.rlocal*cos(qlat));

  sph2cart(proj->param.atct.rlocal, qlat, qlon, &pos);

  rotate_z(&pos,-proj->param.atct.alpha3);
  rotate_y(&pos,-proj->param.atct.alpha2);
  rotate_z(&pos,-proj->param.atct.alpha1);

  cart2sph(pos,&radius,&lat,lon);
  *lon *= R2D;
  lat *= R2D;
  *lat_d = atand(tand(lat) / (1-ecc2(proj->re_minor,proj->re_major)));
  *height = z;  // FIXME: Do we need to correct the height at all?
}
Exemple #8
0
int main (int argc, char *argv[]){
	if (argc != 2){
		printf("Give a parameter file.\n");
		exit(1);
	}
	int SpaceGrp;
	double LatC[6], wl, Lsd, MaxRingRad;
	char *ParamFN;
    FILE *fileParam;
    ParamFN = argv[1];
    char aline[1000];
    fileParam = fopen(ParamFN,"r");
    char *str, dummy[1000];
    int LowNr;
    while (fgets(aline,1000,fileParam)!=NULL){
        str = "SpaceGroup ";
        LowNr = strncmp(aline,str,strlen(str));
        if (LowNr==0){
            sscanf(aline,"%s %d", dummy, &SpaceGrp);
            continue;
        }
        str = "LatticeConstant ";
        LowNr = strncmp(aline,str,strlen(str));
        if (LowNr==0){
            sscanf(aline,"%s %lf %lf %lf %lf %lf %lf", dummy, &LatC[0],
					&LatC[1], &LatC[2], &LatC[3], &LatC[4], &LatC[5]);
            continue;
        }
        str = "LatticeParameter ";
        LowNr = strncmp(aline,str,strlen(str));
        if (LowNr==0){
            sscanf(aline,"%s %lf %lf %lf %lf %lf %lf", dummy, &LatC[0],
					&LatC[1], &LatC[2], &LatC[3], &LatC[4], &LatC[5]);
            continue;
        }
        str = "Wavelength ";
        LowNr = strncmp(aline,str,strlen(str));
        if (LowNr==0){
            sscanf(aline,"%s %lf", dummy, &wl);
            continue;
        }
        str = "Lsd ";
        LowNr = strncmp(aline,str,strlen(str));
        if (LowNr==0){
            sscanf(aline,"%s %lf", dummy, &Lsd);
            continue;
        }
        str = "MaxRingRad ";
        LowNr = strncmp(aline,str,strlen(str));
        if (LowNr==0){
            sscanf(aline,"%s %lf", dummy, &MaxRingRad);
            continue;
        }
	}
	printf("%f %f %f %d %f %f %f %f %f %f\n",wl,Lsd,MaxRingRad,SpaceGrp,LatC[0],LatC[1],LatC[2],LatC[3],LatC[4],LatC[5]);
	int h, k, l, iList, restriction, M, i, j;
	int Minh, Mink, Minl;
	int CCMx_PL[9], deterCCMx_LP = 0;
	double Epsilon = 0.0001;
	int Families[50000][3];
	T_SgInfo *SgInfo;
	char SgName[200]; 
	int F_Convention='A';
	const T_TabSgName *tsgn; 
	
	printf("Generating hkl's\n");
	if((SgInfo = (T_SgInfo *)malloc(sizeof(T_SgInfo)))==NULL){
		printf("Unable to allocate SgInfo\n");
		printf("Aborting\n");
		exit(1);
	}
	SgInfo->GenOption = 0;
	SgInfo->MaxList   = 192;
	if((SgInfo->ListSeitzMx = (T_RTMx*)malloc(SgInfo->MaxList * sizeof(T_RTMx)))==NULL){
		printf("Unable to allocate (SgInfo.ListSeitzMx\n");
		printf("Aborting\n");
		exit(1);
	}
	SgInfo->ListRotMxInfo = NULL;
	InitSgInfo(SgInfo);
	sprintf(SgName,"%d",SpaceGrp);
	tsgn = FindTabSgNameEntry(SgName, F_Convention);
	if (tsgn == NULL){
		printf("Error: Unknown Space Group Symbol\n");
		printf("Aborting\n");
		exit(1);
	}
	sprintf(SgName,"%s",tsgn->HallSymbol);
	SgInfo->TabSgName = tsgn;
	if (tsgn) SgInfo->GenOption = 1;
	{
		int pos_hsym;
		pos_hsym = ParseHallSymbol(SgName, SgInfo);
		
		if (SgError != NULL) {
			printf("Error: Unknown Space Group Symbol\n");
			printf("Aborting\n");
			exit(1);
		}
	}
	if(CompleteSgInfo(SgInfo)!=0) {
		printf("Error in Complete\n");
		printf("Aborting\n");
		exit(1);
	}
	if (SgInfo->LatticeInfo->Code != 'P')
	{
		deterCCMx_LP = deterRotMx(SgInfo->CCMx_LP);
		InverseRotMx(SgInfo->CCMx_LP, CCMx_PL);
		if (deterCCMx_LP < 1) {
			printf("deterCMM failed.\n");
			return 0;
		}
	}
	int Maxh, Maxk, Maxl;
	int nrFilled=0;
	Maxh = 10;
	Maxk = 10;
	Maxl = 10;
	SetListMin_hkl(SgInfo, Maxk, Maxl, &Minh, &Mink, &Minl);
	printf("Will go from %d to %d in h; %d to %d in k; %d to %d in l.\n",Minh, Maxh, Mink, Maxk, Minl, Maxl);
	for (h = Minh; h <= Maxh; h++){
		for (k = Mink; k <= Maxk; k++){
			for (l = Minl; l <= Maxl; l++){
				if (h==0 && k==0 && l==0){
					continue;
				}
				iList = IsSysAbsent_hkl(SgInfo, h, k, l, &restriction);
				if (SgError != NULL) {
					printf("IsSysAbsent_hkl failed.\n");
					return 0;
				}
				if (iList == 0){
					if ((iList = IsSuppressed_hkl(SgInfo, Minh, Mink, Minl,
						Maxk, Maxl, h, k, l)) != 0) {/* Suppressed reflections */
					} else {
						//printf("New plane.\n");
						T_Eq_hkl Eq_hkl;
						M = BuildEq_hkl(SgInfo, &Eq_hkl, h, k, l);
						if (SgError != NULL){
							return 0;
						}
						for (i=0;i<Eq_hkl.N;i++){
							for (j=-1;j<=1;j+=2){
								//printf("%d %d %d\n",Eq_hkl.h[i]*j,Eq_hkl.k[i]*j,Eq_hkl.l[i]*j);
								Families[nrFilled][0] = Eq_hkl.h[i]*j;
								Families[nrFilled][1] = Eq_hkl.k[i]*j;
								Families[nrFilled][2] = Eq_hkl.l[i]*j;
								nrFilled++;
							}
						}
					}
				}
			}
		}
	}
	int AreDuplicates[50000];
	double **UniquePlanes;
	UniquePlanes = allocMatrix(50000,3);
	for (i=0;i<50000;i++) AreDuplicates[i] = 0;
	int nrPlanes=0;
	for (i=0;i<nrFilled-1;i++){
		if (AreDuplicates[i] == 1){
			continue;
		}
		for (j=i+1;j<nrFilled;j++){
			if (Families[i][0] == Families[j][0] && 
				Families[i][1] == Families[j][1] && 
				Families[i][2] == Families[j][2] &&
				AreDuplicates[j] == 0){
					AreDuplicates[j] = 1;
			}
		}
		UniquePlanes[nrPlanes][0] = (double)Families[i][0];
		UniquePlanes[nrPlanes][1] = (double)Families[i][1];
		UniquePlanes[nrPlanes][2] = (double)Families[i][2];
		nrPlanes++;
	}
	double **hkls;
	hkls = allocMatrix(nrPlanes,12);
	CorrectHKLsLatC(LatC,UniquePlanes,nrPlanes,hkls);
	SortFunc(nrPlanes,11,hkls,3,-1);
	double DsMin = wl/(2*sind((atand(MaxRingRad/Lsd))/2));
	for (i=0;i<nrPlanes;i++){
		if (hkls[i][3] < DsMin){
			nrPlanes = i;
			break;
		}
	}
	int RingNr = 1;
	double DsTemp = hkls[0][3];
	hkls[0][4] = 1;
	hkls[0][8] = asind(wl/(2*(hkls[0][3])));
	hkls[0][9] = hkls[0][8]*2;
	hkls[0][10] = Lsd*tand(hkls[0][9]);
	for (i=1;i<nrPlanes;i++){
		if (fabs(hkls[i][3] - DsTemp) < Epsilon){
			hkls[i][4] = RingNr;
		}else{
			DsTemp = hkls[i][3];
			RingNr++;
			hkls[i][4] = RingNr;
		}
		hkls[i][8] = asind(wl/(2*(hkls[i][3])));
		hkls[i][9] = hkls[i][8]*2;
		hkls[i][10] = Lsd*tand(hkls[i][9]);
	}
	char *fn = "hkls.csv";
	FILE *fp;
	fp = fopen(fn,"w");
	fprintf(fp,"h k l D-spacing RingNr\n");
	for (i=0;i<nrPlanes;i++){
		fprintf(fp,"%.0f %.0f %.0f %f %.0f %f %f %f %f %f %f\n",hkls[i][0],
			hkls[i][1],hkls[i][2],hkls[i][3],hkls[i][4],
			hkls[i][5],hkls[i][6],hkls[i][7],hkls[i][8],
			hkls[i][9],hkls[i][10]);
	}
}
Exemple #9
0
int spcx2s(
  struct spcprm *spc,
  int nx,
  int sx,
  int sspec,
  const double x[],
  double spec[],
  int stat[])

{
  static const char *function = "spcx2s";

  int statP2S, status = 0, statX2P;
  double beta;
  register int ix;
  register int *statp;
  register const double *xp;
  register double *specp;
  struct wcserr **err;

  /* Initialize. */
  if (spc == 0x0) return SPCERR_NULL_POINTER;
  err = &(spc->err);

  if (spc->flag == 0) {
    if ((status = spcset(spc))) return status;
  }

  /* Convert intermediate world coordinate x to X. */
  xp = x;
  specp = spec;
  statp = stat;
  for (ix = 0; ix < nx; ix++, xp += sx, specp += sspec) {
    *specp = spc->w[1] + (*xp)*spc->w[2];
    *(statp++) = 0;
  }

  /* If X is the grism parameter then convert it to wavelength. */
  if (spc->isGrism) {
    specp = spec;
    for (ix = 0; ix < nx; ix++, specp += sspec) {
      beta = atand(*specp) + spc->w[3];
      *specp = (sind(beta) + spc->w[4]) * spc->w[5];
    }
  }

  /* Apply the non-linear step of the algorithm chain to convert the    */
  /* X-type spectral variable to P-type intermediate spectral variable. */
  if (spc->spxX2P) {
    if ((statX2P = spc->spxX2P(spc->w[0], nx, sspec, sspec, spec, spec,
                               stat))) {
      if (statX2P == SPXERR_BAD_INSPEC_COORD) {
        status = SPCERR_BAD_X;
      } else if (statX2P == SPXERR_BAD_SPEC_PARAMS) {
        return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
          "Invalid spectral parameters: Frequency or wavelength is 0");
      } else {
        return wcserr_set(SPC_ERRMSG(spc_spxerr[statX2P]));
      }
    }
  }

  /* Apply the linear step of the algorithm chain to convert P-type  */
  /* intermediate spectral variable to the required S-type variable. */
  if (spc->spxP2S) {
    if ((statP2S = spc->spxP2S(spc->w[0], nx, sspec, sspec, spec, spec,
                               stat))) {
      if (statP2S == SPXERR_BAD_INSPEC_COORD) {
        status = SPCERR_BAD_X;
      } else if (statP2S == SPXERR_BAD_SPEC_PARAMS) {
        return wcserr_set(WCSERR_SET(SPCERR_BAD_SPEC_PARAMS),
          "Invalid spectral parameters: Frequency or wavelength is 0");
      } else {
        return wcserr_set(SPC_ERRMSG(spc_spxerr[statP2S]));
      }
    }
  }

  if (status) {
    wcserr_set(SPC_ERRMSG(status));
  }
  return status;
}
Exemple #10
0
int spcx2s(
   struct spcprm *spc,
   int nx,
   int sx,
   int sspec,
   const double x[],
   double spec[],
   int stat[])

{
   int statP2S, status = 0, statX2P;
   double beta;
   register int ix;
   register int *statp;
   register const double *xp;
   register double *specp;


   /* Initialize. */
   if (spc == 0) return 1;
   if (spc->flag == 0) {
      if (spcset(spc)) return 2;
   }

   /* Convert intermediate world coordinate x to X. */
   xp = x;
   specp = spec;
   statp = stat;
   for (ix = 0; ix < nx; ix++, xp += sx, specp += sspec) {
      *specp = spc->w[1] + (*xp)*spc->w[2];
      *(statp++) = 0;
   }

   /* If X is the grism parameter then convert it to wavelength. */
   if (spc->isGrism) {
      specp = spec;
      for (ix = 0; ix < nx; ix++, specp += sspec) {
         beta = atand(*specp) + spc->w[3];
         *specp = (sind(beta) + spc->w[4]) * spc->w[5];
      }
   }

   /* Apply the non-linear step of the algorithm chain to convert the    */
   /* X-type spectral variable to P-type intermediate spectral variable. */
   if (spc->spxX2P != 0) {
      if (statX2P = spc->spxX2P(spc->w[0], nx, sspec, sspec, spec, spec,
                                stat)) {
         if (statX2P == 4) {
            status = 3;
         } else {
            return statX2P;
         }
      }
   }

   /* Apply the linear step of the algorithm chain to convert P-type  */
   /* intermediate spectral variable to the required S-type variable. */
   if (spc->spxP2S != 0) {
      if (statP2S = spc->spxP2S(spc->w[0], nx, sspec, sspec, spec, spec,
                                stat)) {
         if (statP2S == 4) {
            status = 3;
         } else {
            return statP2S;
         }
      }
   }

   return status;
}
void Fit2DPeaks(unsigned nPeaks, int NrPixelsThisRegion, double *z, int **UsefulPixels, double *MaximaValues,
				int **MaximaPositions, double *IntegratedIntensity, double *IMAX, double *YCEN, double *ZCEN, 
				double *RCens, double *EtaCens,double Ycen, double Zcen, double Thresh, int *NrPx,double *OtherInfo)
{
	unsigned n = 1 + (8*nPeaks);
	double x[n],xl[n],xu[n];
	x[0] = Thresh/2;
	xl[0] = 0;
	xu[0] = Thresh;
	int i;
	double *Rs, *Etas;
	Rs = malloc(NrPixelsThisRegion*2*sizeof(*Rs));
	Etas = malloc(NrPixelsThisRegion*2*sizeof(*Etas));
	for (i=0;i<NrPixelsThisRegion;i++){
		Rs[i] = CalcNorm2(UsefulPixels[i][0]-Ycen,UsefulPixels[i][1]-Zcen);
		Etas[i] = CalcEtaAngle(UsefulPixels[i][0]-Ycen,UsefulPixels[i][1]-Zcen);
	}
	double Width = sqrt(NrPixelsThisRegion/nPeaks);
	for (i=0;i<nPeaks;i++){
		x[(8*i)+1] = MaximaValues[i]; // Imax
		x[(8*i)+2] = CalcNorm2(MaximaPositions[i][0]-Ycen,MaximaPositions[i][1]-Zcen); //Radius
		x[(8*i)+3] = CalcEtaAngle(MaximaPositions[i][0]-Ycen,MaximaPositions[i][1]-Zcen); // Eta
		x[(8*i)+4] = 0.5; // Mu
		x[(8*i)+5] = Width; //SigmaGR
		x[(8*i)+6] = Width; //SigmaLR
		x[(8*i)+7] = atand(Width/x[(8*i)+2]); //SigmaGEta //0.5;
		x[(8*i)+8] = atand(Width/x[(8*i)+2]); //SigmaLEta //0.5;

		double dEta = rad2deg*atan(1/x[(8*i)+2]);
		xl[(8*i)+1] = MaximaValues[i]/2;
		xl[(8*i)+2] = x[(8*i)+2] - 1;
		xl[(8*i)+3] = x[(8*i)+3] - dEta;
		xl[(8*i)+4] = 0;
		xl[(8*i)+5] = 0.01;
		xl[(8*i)+6] = 0.01;
		xl[(8*i)+7] = 0.005;
		xl[(8*i)+8] = 0.005;

		xu[(8*i)+1] = MaximaValues[i]*2;
		xu[(8*i)+2] = x[(8*i)+2] + 1;
		xu[(8*i)+3] = x[(8*i)+3] + dEta;
		xu[(8*i)+4] = 1;
		xu[(8*i)+5] = 30;
		xu[(8*i)+6] = 30;
		xu[(8*i)+7] = 2;
		xu[(8*i)+8] = 2;
	}
	struct func_data f_data;
	f_data.NrPixels = NrPixelsThisRegion;
	f_data.Rs = &Rs[0];
	f_data.Etas = &Etas[0];
	f_data.z = &z[0];
	struct func_data *f_datat;
	f_datat = &f_data;
	void *trp = (struct func_data *)  f_datat;
	nlopt_opt opt;
	opt = nlopt_create(NLOPT_LN_NELDERMEAD, n);
	nlopt_set_lower_bounds(opt, xl);
	nlopt_set_upper_bounds(opt, xu);
	nlopt_set_maxtime(opt, 300);
	nlopt_set_min_objective(opt, problem_function, trp);
	double minf;
	nlopt_optimize(opt, x, &minf);
	nlopt_destroy(opt);
	for (i=0;i<nPeaks;i++){
		IMAX[i] = x[(8*i)+1];
		RCens[i] = x[(8*i)+2];
		EtaCens[i] = x[(8*i)+3];
		if (x[(8*i)+5] > x[(8*i)+6]){
			OtherInfo[2*i] = x[(8*i)+5];
		}else{
			OtherInfo[2*i] = x[(8*i)+6];
		}
		if (x[(8*i)+7] > x[(8*i)+8]){
			OtherInfo[2*i+1] = x[(8*i)+7];
		}else{
			OtherInfo[2*i+1] = x[(8*i)+8];
		}
	}
	YZ4mREta(nPeaks,RCens,EtaCens,YCEN,ZCEN);
	CalcIntegratedIntensity(nPeaks,x,Rs,Etas,NrPixelsThisRegion,IntegratedIntensity,NrPx);
	free(Rs);
	free(Etas);
}