/*
****************************************************************************
******************************************************************************
**<AUTO>
**
** FILE:	quasars.c
**
**<HTML>
**	This file contains C functions to select spectroscopic targets for
**	the Quasars Working Group.
**</HTML>
**</AUTO>
**
**
** ENVIRONMENT:
**	ANSI C.
**
******************************************************************************
******************************************************************************
*/
#include "astrotools.h"
#include "taCalibObj.h"
#include "taQuasars.h"
#include "arTargetType.h"
#include "arDetectionFlag.h"
#include "arObjectStatus.h"
#include "arObjectType.h"

/****** DEFINE parameters we use to diagnose various image problems *****/

/* if INTERP_CETNER flag is set, add errInterCenter in the error term in the
relavant band */

#define errInterpCenter 0.25

/* We will delete objects with i-z < izMin, in order to delete some bad blends
from moving objects, it's a place holder now, waiting for RHL to fix some PHOTO
problem */

#define  izMin      -3.70

/* we will delete objects with i < iBright for the moment, due to a known
problem with PHOTO when dealing with removal of cosmic rays for bright stars */

#define  iBright    15.0
#define  iBrightInterp 16.5

/* maximum speed for non-moving object */
#define maxV 0.2
#define maxVSig 3


/**** DEFINE parameters we use to cut various regions in the color space ****/

/* This is a place holder to deal with the asymmetric error at faint
end, it will eventually disappear or into para file */

#define  bigNsigerrors 8.00
#define  minDetect 0.12

/* We will drop the A star region,  with u-g between ugminAstar and ugmaxAstar
(reddening corrected), and g-r between grminAstar and grmaxAstar, 
   and include objects in midZ region, with u-g between ugminMidz and ugmaxMidz
   and g-r between grminMidz and grmaxMidz
*/
#define  ugMinAstar 0.9
#define  ugMaxAstar 1.5
#define  grMaxAstar 0.00
#define  grMinAstar -0.35
#define  ugMinMidz  0.9
#define  ugMaxMidz  1.5
#define  grMinMidz  0.00
#define  grMaxMidz  0.20
#define  ugMinMidz2 0.65
#define  ugMaxMidz2 0.9
#define  grMinMidz2 0.00
#define  grMaxMidz2 0.20
#define  minMidzDist 0.30

/* cut out WD region */

/* WD cut suggested by GTR, and we will use the WD2 cut */

#define ugMinWD -0.5
#define ugMaxWD  0.85
#define grMinWD -0.8
#define grMaxWD -0.4
#define riMinWD -0.6
#define riMaxWD -0.3

#define grMinWD2 -0.8
#define grMaxWD2 -0.2
#define riMinWD2 -0.6
#define riMaxWD2 -0.2
#define izMinWD2 -1.0
#define izMaxWD2 -0.0

/* cut out WD + M star region */
#define grMinWM 0.0
#define grMaxWM 1.6
#define riMinWM 0.6
#define riMaxWM 2.0
#define rErrMaxWM 0.2

/* cut out faint UVX quasars selected as HIZ */
#define ugMaxFaint 0.9
#define grMaxFaint 0.8

/* galaxy region cut : this is the BCG region on the color-color diagram,
which we require minGalSig*4 sigma out of stellar locus */
#define grMinGal 1.5
#define grMaxGal 2.0
#define riMinGal 0.4
#define riMaxGal 0.7
#define minGalSig 1.   

int determineCapSkirt(double l,double b, double limdensity) {
  
  /* Based on Galactic position,
     determine if object is in cap or skirt 
     for now we do a simple b cut 
     */
  double density;

  if (b<20) b=20.;
  atStarCountsFind(l,b,20,&density);
  if (density < limdensity) {
    return 1; 	/* cap */
  } else {
    return 0;	/* skirt */
  }
  
}

static double limitcorrection(double luptitude, double error, double nsigma) {

#ifdef NOTDEF
     double counts, countserr, newluptitude, newluptitudeerr;
     atLupInvert(luptitude, error, &counts, &countserr);
     atLupApply(counts+nsigma*countserr, countserr, &newluptitude, &newluptitudeerr);
     return luptitude-newluptitude;
#endif

   double corr;
   if (error<10.0) {
      corr = 2.5*log10(1.0 + nsigma*(pow(10.,error/2.5)-1.0) + 0.00001);
   } else {
      corr = 2.5*(log10(nsigma) + error/2.5);
   }
   return corr;

}

/* This returns -1 (error), 0 (not in locus), or 1 (in locus) */
static int colorselectqso (TA_CALIB_OBJ *obj, float mag[5], float err[5], int *ta, AR_OBJECT_TYPE type, double lowzlimit[5], TA_QUASARS_LOCUS locusarray, int hizflag, int *closestpoint, double *ellipsedist) {

    double color[4], var[4], covar[3];
    int zero;
    double err0;
    int colorindex, inlocus;
    int tmpflag1, tmpflag2;
    double object_k,object_l,object_m;
    int dummyclosestpoint=-1;
    double dummyellipsedist=-1;

    /* Calculate the colors and errors */
    /* TODO: document the meaning of variance, covariance arrays */
    /* The constants ATQU_UNKNOWN and ATQU_*_LIMIT are defined in
  	astrotools include files */
    for (colorindex = 0; colorindex<4; colorindex++) {
      color[colorindex] = (double) (mag[colorindex] - mag[colorindex+1]);
  
      /* If both magnitudes are detected */ 
      tmpflag1 = obj->detection[ta[colorindex]].flags;
      tmpflag2 = obj->detection[ta[colorindex+1]].flags;
      if ((tmpflag1&(AR_DFLAG_BINNED1))&&(tmpflag2&(AR_DFLAG_BINNED1))) {
        var[colorindex] = err[colorindex]*err[colorindex] + err[colorindex+1]*err[colorindex+1];
        if (colorindex<3) covar[colorindex] = -err[colorindex+1]*err[colorindex+1];
      } else {
        if (colorindex<3) covar[colorindex] = 0;
        /* If bluer magnitude in color is fainter than the plate limit */
        if (!(tmpflag1&(AR_DFLAG_BINNED1))) {
          /* If redder magnitude in color is fainter than the plate limit */
          if (!(tmpflag2&(AR_DFLAG_BINNED1))) {
	    var[colorindex] = ATQU_UNKNOWN;
          } else {
	    var[colorindex] = ATQU_LOWER_LIMIT;
            if (mag[colorindex]<lowzlimit[colorindex]) {
	      color[colorindex] -= limitcorrection(mag[colorindex], err[colorindex], locusarray.nsigmaerrors);
            } else {
	      color[colorindex] = (lowzlimit[colorindex] - limitcorrection(mag[colorindex], err[colorindex], locusarray.nsigmaerrors)) - mag[colorindex+1];
            }
/*
            if (hizflag&&(colorindex==1)) {
              printf("lower limit: %g %g %g -> %g\n", mag[colorindex], err[colorindex], locusarray.nsigmaerrors, limitcorrection(mag[colorindex], err[colorindex], locusarray.nsigmaerrors));
            }
*/
          }
        } else { /* Redder magnitude is fainter than the plate limit*/
            var[colorindex] = ATQU_UPPER_LIMIT;
            if (mag[colorindex+1]<lowzlimit[colorindex+1]) {
	      color[colorindex] += limitcorrection(mag[colorindex+1], err[colorindex+1], locusarray.nsigmaerrors);
            } else {
              color[colorindex] = mag[colorindex] - (lowzlimit[colorindex+1]-limitcorrection(mag[colorindex+1], err[colorindex+1], locusarray.nsigmaerrors));
            }
            /* printf("upper limit: %g %g %g -> %g", mag[colorindex+1], err[colorindex+1], locusarray.nsigmaerrors, limitcorrection(mag[colorindex+1], err[colorindex+1], locusarray.nsigmaerrors)); */
        }
      }
    }

    if (hizflag) {zero=1;} else {zero=0;}

    /* Is the object in the stellar locus? */
    inlocus = atQuLocusRemove(locusarray.lxl, locusarray.lyl, locusarray.lzl,
			locusarray.lkhatx, locusarray.lkhaty,
			locusarray.lkhatz, locusarray.la,
			locusarray.lb, locusarray.theta, locusarray.npts, 
			color[zero], color[zero+1], color[zero+2], var[zero], covar[zero], 0, var[zero+1],
			covar[zero+1], var[zero+2], locusarray.mink, locusarray.minkdist, 
			locusarray.maxk, locusarray.maxkdist, 
			locusarray.nsigmaerrors,closestpoint,ellipsedist);
    /* A return value of -1 means none of the colors are known, so don't select it */
    if (inlocus==-1) {inlocus = 1;}
    if (hizflag&&(inlocus==0)) {
       /*printf("hizcand: %g %g %g %g %g %g %g %g\n", color[zero], color[zero+1], color[zero+2], var[zero], covar[zero], var[zero+1],covar[zero+1], var[zero+2]);
       printf("maginfo: %g %g %g %g %g\n", mag[0], mag[1], mag[2], mag[3], mag[4]);*/
    }
      
    if (inlocus==0) {
      for (colorindex=0; colorindex<4; colorindex++) {
      /*printf("color: %d, limitcorrection: %6.3g, var: %6.3g, mag: %6.3g, color: %6.3g, err: %6.3g\n", colorindex, limitcorrection, var[colorindex], mag[colorindex], color[colorindex], err[colorindex]);*/
      }
    }

    if (!hizflag) {

    /* Here, k is the distance along the locus, l is the distance along the wider axis of the locus
       cross section, and m is the distance along the narrower axis if the locus cross section */
    atQuLocusKlmFromXyz(locusarray.lxl, locusarray.lyl, locusarray.lzl,
		locusarray.lkhatx, locusarray.lkhaty, locusarray.lkhatz,
		locusarray.theta, locusarray.npts, color[0], color[1], color[2],
		&object_k, &object_l, &object_m);

    /* If l>=0 (source is on the galaxy side of the locus) and source is not a point source, don't target it */
    if (type!=6 /* && object_l>0 */ &&
	 (object_k>locusarray.galaxyklimit || color[1] > 1)) {inlocus = 1;}
      
    /* for a star on the wrong side of the stellar locus, try again */
    if(type==6 && object_l>=0 && object_k>locusarray.galaxyklimit&&inlocus==0) {

      /* Redo locus calculation with the bigger errors */
      inlocus = atQuLocusRemove(locusarray.lxl, locusarray.lyl, locusarray.lzl,
			locusarray.lkhatx, locusarray.lkhaty,
			locusarray.lkhatz, locusarray.la,
			locusarray.lb, locusarray.theta,
			locusarray.npts, color[0], color[1], color[2], var[0], covar[0], 0, var[1],
			covar[1], var[2], locusarray.mink, 
			locusarray.minkdist, locusarray.maxk,
			locusarray.maxkdist, bigNsigerrors, 
			&dummyclosestpoint, &dummyellipsedist);
      /* A return value of -1 means none of the colors are known, so don't select it */
      if (inlocus==-1) {inlocus = 1;}

    } /* End checking point sources in galaxy side of locus */

    } /* End eliminating galaxies in ugri */

    return inlocus;

}

/*****************************************************************************
******************************************************************************
**<AUTO EXTRACT>
**
** ROUTINE:	taQuasarsTargetSelect
**
**<HTML>
**	Set the appropriate bit in the primary target bit mask for each
**	Quasars Working Group target selection criterion this object
**	satisfies.  This routine is responsible for setting the following
**	bits:
**	<menu>
**	<li> AR_TARGET_QSO_HIZ
**	<li> AR_TARGET_QSO_CAP
**	<li> AR_TARGET_QSO_SKIRT
**	<li> AR_TARGET_QSO_FIRST_CAP
**	<li> AR_TARGET_QSO_FIRST_SKIRT
**	<li> AR_TARGET_QSO_FAINT
**	</menu>
**	It is assumed that the above bits are unset on entry, although other
**	bits may be set.
**	<P>
**	This routine returns the priority of the quasar candidate, in the
**	range 0-255.  On error, -1 is returned.  Zero means it should not 
**	be targetted.  We would like to give the same priority (200) to all 
**	QSO targets except FIRST QSO targets which are selected as being 
**	on a line between two FIRST sources.  The latter type of QSO 
**	receives lower priority (100).  In the future the lower priority
**	will be replaced by a range of priority.
**</HTML>
**
**</AUTO>
******************************************************************************
*******************************************************************************/
int
taQuasarsTargetSelect(TA_CALIB_OBJ *obj,
		      /* MOD: calibrated object to test */
		      const TA_QUASARS_PARAMS *params
		      /* IN: tunable parameters*/)
{
  
  float mag[5],err[5];
  double syserr[5];
  double lowzlimit[5];
  /* double object_k,object_l,object_m; */
  int colorindex;
  /* double limitcorrection; */
  int capobject, inlocus, index, tmpflag,tmpflag2;
  int ImageProb=0, badCol=0;
  int ta[5], det[5];
  int priority=0;
  float fseed, random, deltamag;
  int closestpoint;	/* added for debugging purposes - not used to target */
  double ellipsedist;	/* added for debugging purposes - not used to target */
	
/**** temp output ****/
  FILE *ftmp;
  int i,nchild;
  int intercenter, intercenterI;


/**** ----  ****/


  /* First, look at the flags to see if this is an object we might
     like to select */
  
  if (obj->objc_flags&(AR_DFLAG_BRIGHT|AR_DFLAG_EDGE|AR_DFLAG_SATUR)) {
    return 0;
  }
  
  /* Do not select things which are blended but not deblended */
  if ((obj->objc_flags & AR_DFLAG_BLENDED) /*  && !(obj->objc_flags & AR_DFLAG_NODEBLEND) */ ) return 0;

  

  /* Get magnitudes with reddening applied */
  ta[0] = TA_U;
  ta[1] = TA_G;
  ta[2] = TA_R;
  ta[3] = TA_I;
  ta[4] = TA_Z;

  /* Schlegel says that the error in the reddening correction is
	15% of the value, which is what is coded.  It may be that
	since the errors in different filters are correlated
	that we now overestimate the errors in colors. */
  for (colorindex=0; colorindex<5; colorindex++) {
    mag[colorindex] = obj->detection[ta[colorindex]].psfCounts.val-obj->reddening[ta[colorindex]]; 
    err[colorindex] = sqrt(obj->detection[ta[colorindex]].psfCounts.err*obj->detection[ta[colorindex]].psfCounts.err 
      + 0.15*0.15*obj->reddening[ta[colorindex]]*obj->reddening[ta[colorindex]]);
  }
  

  /* disregard moving objects */
  if((obj->objc_flags2 & AR_DFLAG2_DEBLENDED_AS_MOVING) )
       return 0;

  if( !(obj->objc_flags2 & AR_DFLAG2_BAD_MOVING_FIT) &&
    ( (fabs(obj->rowv.val) > maxV ) && (fabs(obj->rowv.val)/obj->rowv.err > maxVSig) || 
      (fabs(obj->colv.val) > maxV ) && (fabs(obj->colv.val)/obj->colv.err > maxVSig)) )
	return 0;


 if((obj->objc_flags  & AR_DFLAG_CHILD)!=0) nchild=1;
        else nchild=0;

  intercenter=0;
  intercenterI=0;

  /*****  identify objects with image problems *****/

  /* if object is a child and has PEAKCENTER or NOTCHECKED flags in high S/N band,
	there must be a problem of deblending */

  for (colorindex=0; colorindex<5; colorindex++) {
      tmpflag=obj->detection[ta[colorindex]].flags;
      tmpflag2=obj->detection[ta[colorindex]].flags2;
      if (tmpflag & AR_DFLAG_BINNED1) det[colorindex]=1;
		else det[colorindex]=0;
      if(mag[colorindex]<23 && err[colorindex]<minDetect) {
          if(nchild == 1)  
	    if (!(tmpflag & AR_DFLAG_BINNED1)||(tmpflag&(AR_DFLAG_PEAKCENTER|AR_DFLAG_NOTCHECKED))) ImageProb=1;
    	}

   /* if object has INTERP_CENTER flag in one of the high S/N band, add error
	by errInterpCenter */

      if((tmpflag2 & AR_DFLAG2_INTERP_CENTER) && det[colorindex]==1)
	{
	err[colorindex] = sqrt ( err[colorindex] * err[colorindex] + errInterpCenter * errInterpCenter);
	intercenter=1;
	if(colorindex==3) intercenterI=1;
	}
  }

  /* delete object brighter than iBright, too bright for the spectrograph */
  if (mag[3] < iBright) return 0;

  /* if object is brightter than iBrightInterp, and has INTERP_CENTER in i' 
	it is typically an image problem */
  if (mag[3] < iBrightInterp && intercenterI == 1) ImageProb=1;


  /* disregard objects with i-z < izMin seems to get rid of some bad deblended
	children, in particular in the case of close pairs */
  if (mag[3]- mag[4] < izMin) ImageProb=1;

  /* delete three bad places on the CCD:

	camCol == 5 && olc<1032 && colc>1018
	camCol == 2 && colc<1461 && colc>1451
	camCol == 2 && colc>1382 && colc < 1388
  */

 if(obj->camCol == 5 && obj->objc_colc.val < 1032 && obj->objc_colc.val > 1018) ImageProb=1;

/*
 if(obj->camCol == 2 && obj->objc_colc.val < 1461 && obj->objc_colc.val > 1451) ImageProb=1;
 if(obj->camCol == 2 && obj->objc_colc.val < 1388 && obj->objc_colc.val > 1382) ImageProb=1;
 */

  /* add systematic errors */


  syserr[0]=params->SYSUERR;
  syserr[1]=params->SYSGERR;
  syserr[2]=params->SYSRERR;
  syserr[3]=params->SYSIERR;
  syserr[4]=params->SYSZERR;


  for (colorindex=0; colorindex<5; colorindex++) {
    err[colorindex]=sqrt(err[colorindex]*err[colorindex]+syserr[colorindex]*syserr[colorindex]);
  }
  

  lowzlimit[0] = params->LOWZULIMIT;
  lowzlimit[1] = params->LOWZGLIMIT;
  lowzlimit[2] = params->LOWZRLIMIT;
  lowzlimit[3] = params->LOWZILIMIT;
  lowzlimit[4] = params->LOWZZLIMIT;

  /* Find out if the object is in the CAP or SKIRT */
  capobject = determineCapSkirt(obj->l,obj->b,params->CAPSTARS);
  
  /* Calculate a small random increase in the magnitude limit for this
	object.  Note that we use the same random magnitude increase
	for FIRST selection and color selection */

  /* currently params->magnitudeFuzz=0, so no fuzz */

  fseed = obj->objc_rowc.val * obj->objc_colc.val;
  random = smaRAND(fseed);	/* Seed the random number generator */
  random = smaRAND(0.0);	/* 2nd call to fuzz the magnitude limit */
  deltamag = params->magnitudeFuzz*random;

  /* FIRST MATCH */
  /* If the source is matched to a FIRST source, then firstMatch is 1.
	If it is on a line adjoining two first sourced, then 
	firstMatch > 1.  firstDelta tells you how far the first source
	position (or line between first sources) is from the optical
	object. 

     NOTE: We do not flag first sources fainter than the spectroscopic
	limits for finding FIRST QSOs.  People could still find these
	by looking at the firstMatch flag. */
  /* TODO: Add range of priority for the firstMatch>1 candidates */

  if (obj->objc_type==6) { 		/* Stellar objects only */

    if (obj->firstMatch > 0) {
      /* CAP */
      if (capobject && (mag[3] < params->CAPILIMIT + deltamag)) {
        obj->primTarget |= AR_TARGET_QSO_FIRST_CAP;
        if (obj->firstMatch > 1) {priority = 100;} else {priority = 200;}
      }
      /* SKIRT */
      if (!capobject && (mag[3] < params->SKIRTFIRSTILIMIT + deltamag)) {
        obj->primTarget |= AR_TARGET_QSO_FIRST_SKIRT;
        if (obj->firstMatch > 1) {priority = 100;} else {priority = 200;}
      }
    }

  }

/*** If this object has any image problem, do not select it has a color outlier  this
is after the FIRST selection  ****/

  if(ImageProb==1) return 0;

  /* If object is in the CAP */
  if (capobject) {

    /* Find the index of the locus array corresponding to i magnitude of object */
    index = 0;
    while (params->caplocusmaglimits[index]<mag[3]&&index<params->capnloci) index++;
    index--;
    if (index<0||index>=params->capnloci) {printf ("Locus error\n"); return -1;}

    inlocus = colorselectqso(obj, mag, err, ta, obj->objc_type, lowzlimit,
                params->caplocusarray[index], 0, &closestpoint, &ellipsedist);
    /* printf ("%d, %d, %g\n", inlocus, closestpoint, ellipsedist); */
    if (inlocus<0) return -1;

/* if  the object is in A star region, inlocus = 0 ,
   if   i < CAPLIMIT and the object is in midZ region, inlocus = 1,
   it is again a place holder, which will become parameters */

   if (mag[0] - mag[1] > ugMinAstar && mag[0] - mag[1] < ugMaxAstar &&
       mag[1] - mag[2] > grMinAstar && mag[1] - mag[2] < grMaxAstar  &&
	mag[3] < params->CAPILIMIT + deltamag)
         inlocus = 1;

   if (mag[0] - mag[1] > ugMinMidz  && mag[0] - mag[1] < ugMaxMidz  &&
       mag[1] - mag[2] > grMinMidz  && mag[1] - mag[2] < grMaxMidz  &&
       ellipsedist > minMidzDist &&
       mag[3] < params->CAPILIMIT + deltamag )
          inlocus = 0;

   if (mag[0] - mag[1] > ugMinMidz2  && mag[0] - mag[1] < ugMaxMidz2  &&
       mag[1] - mag[2] > grMinMidz2  && mag[1] - mag[2] < grMaxMidz2  &&
       ellipsedist > minMidzDist &&
       mag[3] < params->SKIRTILIMIT + deltamag )
          inlocus = 0;

/* cut out objects in WD region, in W+M region */

/*
   if (mag[0] - mag[1] > ugMinWD && mag[0] - mag[1] < ugMaxWD  &&
       mag[1] - mag[2] > grMinWD && mag[1] - mag[2] < grMaxWD  &&
       mag[2] - mag[3] > riMinWD && mag[2] - mag[3] < riMaxWD  &&
       mag[3] < params->CAPILIMIT + deltamag)
         inlocus = 1;
*/

   if (mag[1] - mag[2] > grMinWD2 && mag[1] - mag[2] < grMaxWD2  &&
       mag[2] - mag[3] > riMinWD2 && mag[2] - mag[3] < riMaxWD2  &&
       mag[3] - mag[4] > izMinWD2 && mag[3] - mag[4] < izMaxWD2  &&
       mag[3] < params->CAPILIMIT + deltamag)
         inlocus = 1;

   if (mag[1] - mag[2] > grMinWM && mag[1] - mag[2] < grMaxWM  &&
       mag[2] - mag[3] > riMinWM && mag[2] - mag[3] < riMaxWM  &&
       err[2] < rErrMaxWM &&
       mag[3] < params->CAPILIMIT + deltamag)
         inlocus = 1;

      
    /* If i' is brighter than the plate limit in the cap. */

	/* if the object has u-g color indicating it in the z>4 region,
	     the magnitude limit is HIZILIMIT */

    if (mag[3] < params->CAPILIMIT + deltamag    || 
     (mag[3] < params-> HIZILIMIT + deltamag && mag[0] - mag[1] > ugMaxAstar)) {
      /* Set the target flag */
      if (!inlocus) {obj->primTarget |= AR_TARGET_QSO_CAP; priority = 200;

/* tmp output 
  		ftmp=fopen("q745","a");
		fprintf(ftmp,"%d %d %d %d %d %d %d ",obj->run, obj->camCol, obj->fieldId, obj->id, obj->objc_type, nchild,intercenter);
		for(i=0; i<5; ++i)
			fprintf(ftmp, "%5.2f %5.2f ",mag[i],err[i]);
		fprintf(ftmp," 1 %6.3f\n",ellipsedist); 
		fclose(ftmp);
		ftmp=fopen("q745_flag","a");
		fprintf(ftmp,"%d %d %d %d ", obj->run, obj->camCol, obj->fieldId, obj->id);
		for(i=0; i<5; ++i)
			fprintf(ftmp,"%d %d ",obj->detection[i].flags,obj->detection[i].flags2);
		fprintf(ftmp,"\n");
		fclose(ftmp); 
*/

         }
    } else {
      /* Set a target flag, but do not target the object */
      if (!inlocus) {obj->primTarget |= AR_TARGET_QSO_FAINT;}
    }
  } else {
    /* If object is not in CAP, but rather is in the SKIRT */

    /* Find the index of the locus array corresponding to i magnitude of object */
    index = 0;
    while (params->skirtlocusmaglimits[index]<mag[3]&&index<params->skirtnloci) index++;
    index--;
    if (index<0||index>=params->skirtnloci) {printf ("Locus error\n"); return -1;}

    inlocus = colorselectqso(obj, mag, err, ta, obj->objc_type, lowzlimit, 
		params->skirtlocusarray[index], 0, &closestpoint, &ellipsedist);
    /* printf ("%d, %d, %g\n", inlocus, closestpoint, ellipsedist); */
    if (inlocus<0) return -1;
    /*if (inlocus==0) {printf("id %d\n", obj->id);}*/

/* if  the object is in A star region, inlocus = 0 , 
   if   i < SKIRTILIMIT and the object is in midZ region, inlocus = 1, 
   it is again a place holder, which will become parameters */

   if (mag[0] - mag[1] > ugMinAstar && mag[0] - mag[1] < ugMaxAstar &&
       mag[1] - mag[2] > grMinAstar && mag[1] - mag[2] < grMaxAstar  &&
	mag[3] < params->SKIRTILIMIT + deltamag) 
	 inlocus = 1;

   if (mag[0] - mag[1] > ugMinMidz  && mag[0] - mag[1] < ugMaxMidz  &&
       mag[1] - mag[2] > grMinMidz  && mag[1] - mag[2] < grMaxMidz  &&
       ellipsedist > minMidzDist &&
       mag[3] < params->SKIRTILIMIT + deltamag )
	  inlocus = 0;

   if (mag[0] - mag[1] > ugMinMidz2  && mag[0] - mag[1] < ugMaxMidz2  &&
       mag[1] - mag[2] > grMinMidz2  && mag[1] - mag[2] < grMaxMidz2  &&
       ellipsedist > minMidzDist &&
       mag[3] < params->SKIRTILIMIT + deltamag )
          inlocus = 0;
    
/* cut out objects in WD region, in W+M region */

/*
   if (mag[0] - mag[1] > ugMinWD && mag[0] - mag[1] < ugMaxWD  &&
       mag[1] - mag[2] > grMinWD && mag[1] - mag[2] < grMaxWD  &&
       mag[2] - mag[3] > riMinWD && mag[2] - mag[3] < riMaxWD  &&
       mag[3] < params->SKIRTILIMIT + deltamag)
         inlocus = 1;
*/

   if (mag[1] - mag[2] > grMinWD2 && mag[1] - mag[2] < grMaxWD2  &&
       mag[2] - mag[3] > riMinWD2 && mag[2] - mag[3] < riMaxWD2  &&
       mag[3] - mag[4] > izMinWD2 && mag[3] - mag[4] < izMaxWD2  &&
       mag[3] < params->CAPILIMIT + deltamag)
         inlocus = 1;

   if (mag[1] - mag[2] > grMinWM && mag[1] - mag[2] < grMaxWM  &&
       mag[2] - mag[3] > riMinWM && mag[2] - mag[3] < riMaxWM  &&
       err[2] < rErrMaxWM &&
       mag[3] < params->SKIRTILIMIT + deltamag)
         inlocus = 1;

/* select target brighter than SKIRTILIMIT; as well as brighter
than HIZILIMIT for objects with u-g > ugMaxAstar, i.e. z_est > 3 */

    if (mag[3] < params->SKIRTILIMIT + deltamag ||
     (mag[3] < params-> HIZILIMIT + deltamag && mag[0] - mag[1] > ugMaxAstar)) {
      /* Set the target flag */
      if (!inlocus) {obj->primTarget |= AR_TARGET_QSO_SKIRT; priority = 200;

/* tmp output  
                ftmp=fopen("q745","a");
                fprintf(ftmp,"%d %d %d %d %d %d %d ",obj->run, obj->camCol, obj->fieldId, obj->id, obj->objc_type, nchild, intercenter);
                for(i=0; i<5; ++i)
                        fprintf(ftmp, "%5.2f %5.2f ",mag[i],err[i]);
                fprintf(ftmp,"2 %6.3f\n", ellipsedist);
		fclose(ftmp);
                ftmp=fopen("q745_flag","a");
                fprintf(ftmp,"%d %d %d %d ", obj->run, obj->camCol, obj->fieldId, obj->id);
                for(i=0; i<5; ++i)
                        fprintf(ftmp,"%d %d ",obj->detection[i].flags,obj->detection[i].flags2);
                fprintf(ftmp,"\n");
                fclose(ftmp);
*/

	}
    } else {
      /* Set the target flag, but do not target the object */
      if (!inlocus) {obj->primTarget |= AR_TARGET_QSO_FAINT;}
    }
  }
  
  /* Look for hiz objects (this is tiled hiz - not the fishing expedition) */
  /* Find the index of the locus array corresponding to i magnitude of object */
  index = 0;
  while (params->hizlocusmaglimits[index]<mag[3]&&index<params->hiznloci) index++;
  index--;
  if (index<0||index>=params->hiznloci) {printf ("Locus error\n"); return -1;}

  /*printf("%d %6.3g %6.3g %6.3g %6.3g %6.3g %6.3g %6.3g %6.3g %6.3g %d\n", params->hiznloci,params->hizlocusarray[0].lxl[0],params->hizlocusarray[0].lyl[0],params->hizlocusarray[0].lzl[0],params->hizlocusarray[0].lkhatx[0],params->hizlocusarray[0].lkhaty[0],params->hizlocusarray[0].lkhatz[0],params->hizlocusarray[0].la[0],params->hizlocusarray[0].lb[0],params->hizlocusarray[0].theta[0],params->hizlocusarray[0].npts);*/

  inlocus = colorselectqso(obj, mag, err, ta, obj->objc_type, lowzlimit,
                params->hizlocusarray[index], 1, &closestpoint, &ellipsedist);
  if (inlocus<0) return -1;
      
  /* If i' is brighter than the hiz plate limit. */

  random = smaRAND(0.0);        /* 2nd call to fuzz the magnitude limit */
  deltamag = params->magnitudeFuzz*random;

  if (mag[3] < params->HIZILIMIT + deltamag) {

	/* cut out objects in WD region, in W+M region */

/*
  	if (mag[0] - mag[1] > ugMinWD && mag[0] - mag[1] < ugMaxWD  &&
            mag[1] - mag[2] > grMinWD && mag[1] - mag[2] < grMaxWD  &&
       	    mag[2] - mag[3] > riMinWD && mag[2] - mag[3] < riMaxWD ) 
       		  inlocus = 1;
*/


       if (mag[1] - mag[2] > grMinWD2 && mag[1] - mag[2] < grMaxWD2  &&
           mag[2] - mag[3] > riMinWD2 && mag[2] - mag[3] < riMaxWD2  &&
           mag[3] - mag[4] > izMinWD2 && mag[3] - mag[4] < izMaxWD2 )
            	 inlocus = 1;

       	if (mag[1] - mag[2] > grMinWM && mag[1] - mag[2] < grMaxWM  &&
       	    mag[2] - mag[3] > riMinWM && mag[2] - mag[3] < riMaxWM  && 
       	    err[2] < rErrMaxWM )
       		  inlocus = 1;

	/* cut out faint UVX quasars selected as HIZ */
	if (det[0] == 1 && det[1] == 1 && mag[0] - mag[1] < ugMaxFaint &&
	                   det[2] == 1 && mag[1] - mag[2] < ugMaxFaint)
		  inlocus = 1;

	/* if in z=0.4 galaxy region, increase to 5 sigma */

	if (det[1] == 1 && det[2] == 1 && mag[1] - mag[2] > grMinGal && mag[1] - mag [2] < grMaxGal &&
	    det[2] == 1 && det[3] == 1 && mag[2] - mag[3] > riMinGal && mag[2] - mag [3] < riMaxGal &&
	    ellipsedist < minGalSig ) 
		  inlocus = 1;


    /* Set the target flag */
    if (!inlocus && obj->objc_type == 6) {obj->primTarget |= AR_TARGET_QSO_HIZ; priority = 200;

/* tmp output 
                ftmp=fopen("q745","a");
                fprintf(ftmp,"%d %d %d %d %d %d %d ",obj->run, obj->camCol, obj->fieldId, obj->id, obj->objc_type, nchild,intercenter);
                for(i=0; i<5; ++i)
                        fprintf(ftmp, "%5.2f %5.2f ",mag[i],err[i]);
                fprintf(ftmp,"3 %6.3f\n", ellipsedist);
		fclose(ftmp);
                ftmp=fopen("q745_flag","a");
                fprintf(ftmp,"%d %d %d %d ", obj->run, obj->camCol, obj->fieldId, obj->id);
                for(i=0; i<5; ++i)
                        fprintf(ftmp,"%d %d ",obj->detection[i].flags,obj->detection[i].flags2);
                fprintf(ftmp,"\n");
                fclose(ftmp);
*/

	}
  } else {
    /* Set a target flag, but do not target the object */
    if (!inlocus && obj->objc_type == 6) {obj->primTarget |= AR_TARGET_QSO_FAINT;}
  }

  /* Successful return */
  return priority;

}
