/*****************************************************************************
******************************************************************************
**<AUTO>
**
** FILE:	galaxies.c
**
**<HTML>
**	This file contains C functions to select spectroscopic targets for
**	the Galaxies Working Group.
**
**    The Galaxy Working Group criteria document is at
**         http://www.astro.princeton.edu:81/documents/galaxy_selection.ps
**
**    Strawman TCL code implementation of Galaxy TS.  Richmond, Annis 10/30/96
**    C implementation of TCL code by Munn, Yanny 8/20/1997
**    Extensive updates by Strauss, Weinberg, Narayanan, Annis, week of 1/25/99
**    BRG rewrite, Annis, April 1999
**    BRG rewrite II, Annis, August 1999
**    Modifications to main galaxy sample selection by Narayanan & Weinberg,
**    12/15/99 -- changing star-galaxy separation and saturation handling.
**
**</HTML>
**</AUTO>
**
**
** ENVIRONMENT:
**	ANSI C.
**
******************************************************************************
******************************************************************************
*/
#include <dervish.h>
#include "taCalibObj.h"
#include "taGalaxies.h"
#include "arTargetType.h"
#include "arDetectionFlag.h"
#include "arObjectStatus.h"
#include "arObjectType.h"
#include <math.h>

/*****************************************************************************
******************************************************************************
**<AUTO EXTRACT>
**
** ROUTINE:	taGalaxiesTargetSelect
**
**<HTML>
**	Set the appropriate bit in the primary target bit mask for each
**	Galaxies Working Group target selection criterion this object
**	satisfies.  This routine is responsible for setting the following
**	bits:
**	<menu>
**	<li> AR_TARGET_GALAXY
**	<li> AR_TARGET_GALAXY_BIG
**	<li> AR_TARGET_GALAXY_BRIGHT_CORE
**	<li> AR_TARGET_GALAXY_RED
**	<li> AR_TARGET_GALAXY_REDII
**	</menu>
**	It is assumed that the above bits are unset on entry, although other
**	bits may be set.
**</HTML>
**
** RETURNS:
**	-1	error
**	0	not a target by any criteria
**	1-255	is a target by one or more criteria --- priority returned
**		(higher number = higher priority)
**
**</AUTO>
******************************************************************************
******************************************************************************
*/
int
taGalaxiesTargetSelect(TA_CALIB_OBJ *obj,
		       /* MOD: calibrated object to test */
		       const TA_GALAXIES_PARAMS *params
		       /* IN: tunable parameters*/
		       )
{
  int priority = 0;     /* targeting priority (initialize for a non-target) */
  int i;		/* filter indexer */
  float petroMag2;      /* Petrosian Magnitude in r' band */
  float deredMag;       /* reddening corrected petrosian magnitudes */
  int objFlags ;	/* r-band object flags */
  int objFlags2 ;	/* r-band object flags2, contains SATUR_CENTER */

  float halfLightRad;   /* petroR50 */
  float petSB;          /* mean petrosian surface brightness within half Light
			   Radius, i.e within petroR50 */
  float petSB_deltaskycut_LSB; /* For petSB >= this value, select objects only
				  if deltasky < deltaskycut */
 
  float fieldsky,objsky; /* Global field sky, and object local sky,
			    both must be in luptitudes/arcsec^2 */
  int gooddeltasky_LSB;  
  float deltasky_LSB;  
  float deltaskycut_LSB; 
  float deRed_mg;
  float deRed_mr;
  float deRed_mi;
  float deRed_gr;
  float deRed_ri;
  float deRed_r;
  float cperp;		/* perp/parallel to galaxy color locus at z < 0.4 */
  float cpar;		/* in g-r vs r-i plots */
  float cp_inter;	/* cperp intercept */	
  float cp_slope;	/* cpar slope */

  float deredFiberMag;  /* de-reddened 3" magnitude */
  float gFiberMag;  /* Measured 3" Fiber magnitude in g band*/
  float rFiberMag;  /* Measured 3" Fiber magnitude in r band*/
  float iFiberMag;  /* Measured 3" Fiber magnitude in i band*/
  float gFiberMagbright;  /* Fiber magnitude in g band*/
  float rFiberMagbright;  /* Measured 3" Fiber magnitude in r band*/
  float iFiberMagbright;  /* Measured 3" Fiber magnitude in i band*/

  float petmag_smallbright; 
  float R50_smallbright;  /* Reject if (petroMag < petmag_smallbright) 
			     *AND* (halfLightRad < R50_smallbright) */

  float row;		/* object row */
  float col;		/* object column */

  float star_gal_magdiff;    /* If (PSFMAG-BEST_MODEL_MAG) > star_gal_magdiff, 
			      object is a galaxy. */
  float star_gal_magdiff_fuzz; /* Fuzz in star_gal_magdiff */

  float brg_star_gal_magdiff1;    /* BRG Cut I star/gal separation threshold */
  float brg_star_gal_magdiff2;    /* BRG CutII star/gal separation threshold */

  float psf_model_magdiff;   /* psf - model magnitude of object */

  float pet_mag_limit;       /* mag limit of main sample */
  float pet_SB_limit;        /* sb limit of main sample */
  float random;              /* Output of smaRAND */
  float fseed;               /* Seed for the random number generator */

  float fseed1, fseed2, fseed3, fseed4; /* Used in generating fseed */

  int rejReason; /* reason for rejecting a galaxy
                    1 = undetected in r   2 = saturated center in r'
                    3 = edge flag         4 = bright
                    5 = blended           6 = failed SB limit
                    7 = stellar, PSF-MODEL < star_gal_magdiff    
                    8 = Small, Bright objects, mostly stars
		    9 = failed mag limit
		    10 = Too bright a FiberMag, one of g, r, i < 15
			20 = undetected in i'
			21 = satur_center in g' or i'
			22 = somthing wrong with mag
			23 = colors too noisy
			24 = strange g-r color
		    	25 = star
		    	26 = failed both cuts
		    	27 = failed both cuts
                  */
  int accReason; /* reason for accepting galaxy
		    -1 = LSB galaxy  (both GALAXY and GALAXY_BIG are set)
		    -2 = normal(HSB) (only GALAXY is set)
		    -3 = bright core (only GALAXY_BRIGHT_CORE is set)
			-4 = BRG via I
			-5 = BRG via II
		  */
  static int subsample; 
  static int icall=0;	     /* changed after first call */
  static int diagReject ;    /* write diagnostics for all rejected objects
                              * that have rejReason <= diagReject */
  static int diagAccept ;    /* write diagnostics for all accepted objects */
  static FILE *fp,*fp1 ;     /* diagnostic file pointers */

  float dra,ddec;           /* write out the RA and dec for accepted 
				objects to diagAccept.out */

  /* on 1st call, open files for writing accept and reject diagnostics */

  if(icall==0)
    {
      diagReject=params->diagReject ;
      diagAccept=params->diagAccept ;
      if (diagReject)  fp=fopen("diagReject.out","w") ;
      if (diagAccept)  fp1=fopen("diagAccept.out","w") ;
      
    }
  icall++;
  
    /* Stop rejection diagnostics after 10000 objects 
     Note that there is no such limit on diaganostics of accepted
     objects. i.e if diagAccept = 1, all accepted objects are output */

  if (icall>10000 && (diagReject))  {
    fprintf(stderr,"\n taGalaxiesTargetSelect> more than 10000 objects, \
		closing diagnostic files\n") ;
    if (diagReject) close(fp) ;
    diagReject=0 ;
  }

 /*
 ****************************************************************************
 *
 * 	Prolog: cuts applied for all objects
 *		later there will be separate sections for main and BRG
 *
 *****************************************************************************
 */

 /*
  * In the prolog (where cuts apply to both regular galaxies
  * and red galaxies), we reject objects by returning without setting any
  * flags.  We write diagnostics if rejReason <= diagReject. 
  *
  */

  objFlags  = obj->detection[TA_R].flags ;	/* just to save space */
  objFlags2 = obj->detection[TA_R].flags2 ;	/* to get SATUR_CENTER */

 /* These will be set to real values later, but they get written out to
  * diagnostic files for objects rejected in early going, so we set them
  * to some values so as not to output garbage.
  */

  pet_mag_limit= params->pet_mag_limit;
  pet_SB_limit = params->pet_SB_limit;
  petSB=0.0 ;

    /* 1) Reject objects undetected in r
       They are not detected in any of BINNED1, BINNED2 and BINNED4 
       images in r */

  if (!((objFlags & AR_DFLAG_BINNED1) | (objFlags & AR_DFLAG_BINNED2) | (objFlags & AR_DFLAG_BINNED4)))  {
    rejReason=1 ;
    if (diagReject && rejReason <= diagReject) {
      taGalaxiesLog (fp, obj, pet_mag_limit, petSB, pet_SB_limit, 0, 0, 0, rejReason);
    }
    return priority ;
  }

  /* Reject saturated center objects - Note that we do not reject all 
     saturated objects since we do not want to reject good galaxies blended 
     with saturated stars */

/*  if ((objFlags2 &  AR_DFLAG2_SATUR_CENTER))  { */

  /* As of now reject, if SATUR. 
     TODO: Check if SATUR_CENTER is a  better flag to use 

     03/31/00 - VKN
     As of 03/31/00, photo does not subtract diffraction spikes of bright 
     stars. Hence, many of the objects with SATURATED flag set, but not
     SATUR_CENTER set turn out to be these diffraction spikes.
     Therefore, as of now, reject all SATURATED objects. 
     If diffraction spikes are handled correctly by a later version of
     photo, we should test if SATUR_CENTER is a better flag to use.
*/

  /* 2) Reject objects that have SATURATED pixels in r band */

  if ((objFlags &  AR_DFLAG_SATUR))  {
    rejReason=2 ;
    if (diagReject && rejReason <= diagReject) {
      taGalaxiesLog (fp, obj, pet_mag_limit, petSB, pet_SB_limit, 0, 0, 0, rejReason);
    }
    return priority ;
  }

  /* 3) Reject bright objects, since these should reappear as faint objects */

  if ((objFlags & AR_DFLAG_BRIGHT))  {
    rejReason=4 ;
    if (diagReject && rejReason <= diagReject) {
      taGalaxiesLog (fp, obj, pet_mag_limit, petSB, pet_SB_limit, 0, 0, 0, rejReason);
    }
    return priority ;
  }

  /* 4) Reject blended object unless it has NODEBLEND set or is a child */

  if ((objFlags & AR_DFLAG_BLENDED) & !((objFlags & AR_DFLAG_NODEBLEND) | (objFlags & AR_DFLAG_CHILD))) {
    rejReason=5 ;
    if (diagReject && rejReason <= diagReject) {
      taGalaxiesLog (fp, obj, pet_mag_limit, petSB, pet_SB_limit, 0, 0, 0, rejReason);
    }
    return priority ;
  }

  /* 5) Reject small, bright  objects - They are dangerous spectroscopic
     targets, and are almost certainly stars.  */

  /* Note that the petroCounts are in magnitudes and petroR50 is in
     arcseconds */

  petroMag2 = obj->detection[TA_R].petroCounts.val;
  halfLightRad = obj->detection[TA_R].petroR50.val;

  /* Note that some objects with NOPETRO and PETROFAINT set have
     halfLightRad = 0, we want to reject these objects also, since
     we take log of this when we compute petroSB */

  petmag_smallbright = params->petmag_smallbright;
  R50_smallbright = params->R50_smallbright;

  if(((petroMag2 < petmag_smallbright) && (halfLightRad < R50_smallbright)) || (halfLightRad <= 0.)){
    rejReason=8 ;
    if (diagReject && rejReason <= diagReject) {
      taGalaxiesLog (fp, obj, pet_mag_limit, petSB, pet_SB_limit, 0, 0, 0, rejReason);
    }
    return priority ;
  }

  /* 6) Reject objects with measured FiberMag (uncorrected for reddening)
     in g, r, i < 15. These are too
     bright to get spectra of, and are dangerous spectroscopic targets */
  
  gFiberMag = obj->detection[TA_G].fiberCounts.val;
  rFiberMag = obj->detection[TA_R].fiberCounts.val;
  iFiberMag = obj->detection[TA_I].fiberCounts.val;

  gFiberMagbright = params->gFiberMagbright;
  rFiberMagbright = params->rFiberMagbright;
  iFiberMagbright = params->iFiberMagbright;

  if((gFiberMag<gFiberMagbright) || (rFiberMag<rFiberMagbright) ||(iFiberMag<iFiberMagbright)){
    rejReason = 10 ;
    if (diagReject && rejReason <= diagReject) {
      taGalaxiesLog (fp, obj, pet_mag_limit, petSB, pet_SB_limit, gFiberMag, rFiberMag, iFiberMag, rejReason);
    }
    return priority ;
  }    

    /* 7) Accept big galaxies
     08/03/00 - VKN:
     Leave this in for this target selection run, but once we have 
     LSB info. from (delta_sky), use this flag to denote the LSBs chosen
     using delta_sky cut 

     09/01/00 - VKN
     Use the GALAXY_BIG flag to select LSB galaxies with 
     petSB_deltaskycut_LSB  < petSB < pet_SB_limit . 
     Move this section to the MAIN galaxy section*/

/* IF THE LSB SECTION USES GALAXY_BIG CORRECTLY, REMOVE THIS 
   TEST 

   if(obj->detection[TA_R].petroR90.val > params->rbig)  {
    obj->primTarget |= AR_TARGET_GALAXY_BIG;
    priority = 1;  
    if (diagAccept) {
      accReason = -1;
      taGalaxiesLog (fp1, obj, pet_mag_limit, petSB, pet_SB_limit, 0, 0, 0, accReason);
    }
    return priority ;
  }
*/

 /*
 ****************************************************************************
 *
 *	Main galaxy section
 *
 *****************************************************************************
 */

  /* 
     Apply star/galaxy separation. Note that the star/galaxy
     separation is applied  in r'-band only.
     This star/galaxy separation is used only in the main galaxy sample.
     BRGs can use a different star/galaxy separation threshold.
     
     Objects are classified as non-stellar if 
     (psfmag - best-fit-model-mag) > star_gal_magdiff 
     */


  /* Do a star/galaxy separation including  fuzz*random #(<1) */

  /* Generate seed for random number generator as follows:

     rem(x) = (x-floor(x))
     
     fseed = rem(rem(row) + rem(col) + rem(100.*petroMag2)/100. + 
             rem(100.*halfLightRad))

     This algorithm keeps sufficient number of post-decimal digits
     to prevent striping in the plot of x_{n} v/s x_{n+1}
   */

  fseed1 = obj->objc_rowc.val;
  fseed2 = obj->objc_colc.val;
  fseed3 = obj->detection[TA_R].petroCounts.val;
  fseed4 = obj->detection[TA_R].petroR50.val;

  fseed1 = (fseed1 - floor(fseed1));
  fseed2 = (fseed2 - floor(fseed2));

  fseed3 = (100.*fseed3 - floor(100.*fseed3));
  fseed4 =   (100.*fseed4 - floor(100.*fseed4));

  fseed = (fseed1 + fseed2 + fseed3/100. + fseed4);

  /* Be sure seed is positive */
  
  if(fseed < 0)fseed = -fseed;

  /* Seed = post-decimal numbers of this fseed */

  fseed = (fseed - floor(fseed));

  /* Reject object if it fails star/galaxy separation with fuzz */

  random = smaRAND(fseed);	/* Seed the random number generator */
  random = smaRAND(0.0);	/* 2nd call to fuzz star_gal_magdiff */

  psf_model_magdiff = obj->detection[TA_R].psfCounts.val - 
                      obj->detection[TA_R].counts_model.val;

  star_gal_magdiff = params->star_gal_magdiff + 
                     params->star_gal_magdiff_fuzz*random;	

  if (psf_model_magdiff < star_gal_magdiff){
    rejReason=7 ;
  }
  if (rejReason == 7 && diagReject && rejReason <= diagReject) {
      taGalaxiesLog (fp, obj, pet_mag_limit, petSB, pet_SB_limit, 0, 0, 0, rejReason);
  }

  /* If instead, we choose to use Photo's star/galaxy separation in the
     r' band, (i., use type2 ==3), the following code is useful */

/*  if(obj->detection[TA_R].type != AR_OBJECT_TYPE_GALAXY){
       rejReason=7 ;
  } 
  if (rejReason == 7 && diagReject && rejReason <= diagReject) {
      taGalaxiesLog (fp, obj, pet_mag_limit, petSB, pet_SB_limit, 0, 0, 0, rejReason);
    }
  */

 /* 
  * We have flagged stars using our star/galaxy separation algorithm.
  If object is not a star, proceed with main galaxy target selection.
  Note that BRG can use a different star galaxy separation (algorithm is the
  same, but the threshold can be different).
  Hence, even if object is classified as a star now, the object
  is still processed by the BRG selection algorithm
  On to selecting the galaxy sample
  *
  */

  /* Now we switch to nested if clauses instead of returns, because objects
   * rejected for one reason (e.g., failing magnitude limit) can come back
   * in another guise (e.g., as red galaxies).
   */

  /* Apply reddening correction */
  deredMag = obj->detection[TA_R].petroCounts.val - obj->reddening[TA_R];
  
  /* the basic magnitude cut for galaxy selection */
  
  random=smaRAND(0.0);	/* 3rd call to fuzz pet_mag_limit */
  pet_mag_limit = params->pet_mag_limit +
                  params->pet_mag_limit_fuzz*random ;
  
  if (rejReason != 7) {   /* if not a star */
    /* Note the lower limit on deredMag; to guard against (-)ve Luptitudes.*/
     if (deredMag <= pet_mag_limit && deredMag > 0) {
    
      /* Compute half-light surface brightness (denoted petSB, which is
       * perhaps mildly misleading).
       */
       halfLightRad = obj->detection[TA_R].petroR50.val;
       petSB = deredMag + 2.5*log10(2*3.14159*halfLightRad*halfLightRad);
  
       random=smaRAND(0.0);	/* 4th call to fuzz pet_SB_limit */
       pet_SB_limit = params->pet_SB_limit +
                   params->pet_SB_limit_fuzz*random;

       petSB_deltaskycut_LSB = params->petSB_deltaskycut_LSB;

       /* If petSB<=petSB_deltaskycut_LSB && petSB<=pet_SB_limit,
	  set it as a normal(HSB) galaxy 
	  The double comparison in setting GALAXY leaves ambiguous the 
	  relative values of petSB_deltaskycut_LSB and pet_SB_limit, 
	  i.e. either one can be higher than the other without failure.
	  */

       /* (a) Normal., i.e high surface brightness galaxy */

       if (petSB <= pet_SB_limit && petSB <= petSB_deltaskycut_LSB) {
	   obj->primTarget |= AR_TARGET_GALAXY;
           priority = 1; 	
           if (diagAccept) { /* write out selected galaxies */
	     dra=obj->ra ;
	     ddec=obj->dec ;
	     accReason = -2;
      	     taGalaxiesLog (fp1, obj, pet_mag_limit, petSB, pet_SB_limit, dra, ddec, 0, accReason);
           }
       } else  {  	

	 /* (b) Check whether the object is a bright core galaxy */           

	   deredFiberMag = obj->detection[TA_R].fiberCounts.val - 
                        obj->reddening[TA_R];

	   /* Again, guard against negative Luptitudes.*/

	   if (deredFiberMag < params->mag3arcsec_limit && deredFiberMag > 0) {
	       obj->primTarget |= AR_TARGET_GALAXY_BRIGHT_CORE;
	       priority = 1;  

	       if (diagAccept) { /* write out selected galaxies */
		 dra=obj->ra ;
		 ddec=obj->dec ;
		 accReason = -3;
		 taGalaxiesLog (fp1, obj, pet_mag_limit, petSB, pet_SB_limit, dra, ddec, deredFiberMag, accReason);
	       }

	     }
	     
	   else {
	     /* (c) can it be an LSB galaxy in the range
	      petSB_deltaskycut_LSB < petSB < pet_SB_limit? */

	     deltaskycut_LSB = params->deltaskycut_LSB;

	     fieldsky = obj->field->sky_frames_sub[2];
	     objsky   = obj->detection[TA_R].sky.val;
	     deltasky_LSB = fieldsky - objsky;

	     /* check that the sky values are defined properly.
		i.e not set to 0 */

	     gooddeltasky_LSB = 0;
	     if(fieldsky > 1 && objsky > 1)gooddeltasky_LSB = 1;

	     if(petSB>petSB_deltaskycut_LSB && petSB<=pet_SB_limit && 
		gooddeltasky_LSB && deltasky_LSB<=deltaskycut_LSB){
	       
	       /* This objects is an "LSB", set both the GALAXY and 
		  GALAXY_BIG flags */

	       obj->primTarget |= AR_TARGET_GALAXY;
	       obj->primTarget |= AR_TARGET_GALAXY_BIG;
	       priority = 1;   

	       if (diagAccept) { /* write out selected galaxies */
		 accReason = -1;
		 taGalaxiesLog (fp1, obj, pet_mag_limit, petSB, pet_SB_limit, fieldsky, objsky, deltasky_LSB, accReason);
	       }
	       
	     }

	     else {

	     /* failed both normal and LSB surface-brightness cuts, and the
		fibermag cut */

	       rejReason=6 ;
    	       if (diagReject && rejReason <= diagReject) {
      		   taGalaxiesLog (fp, obj, pet_mag_limit, petSB, pet_SB_limit, fieldsky, objsky, deltasky_LSB, rejReason);
    	       }
	     }

	   }
         }
     } else {		/* failed Petrosian magnitude limit */
	rejReason=9 ;
	if (diagReject && rejReason <= diagReject) {
            taGalaxiesLog (fp, obj, pet_mag_limit, petSB, pet_SB_limit, 0, 0, 0, rejReason);
	}
     }

  }
  

 /*
 ****************************************************************************
 *
 * 		The Bright Red Galaxy Section
 *
 *****************************************************************************
 */

 /*
  * reset rejReason for BRG selection 
  *	
  */
  rejReason=0; 

 /*
  * BRG star galaxy separation.
  * This is similar to MAIN s/g separation, but can potentially use 
  *  a different star_gal_magdiff threshold, if necessary
  */
  
  brg_star_gal_magdiff1 = params->brg_star_gal_magdiff1;

  /* Cut I star/gal separation */

  if (psf_model_magdiff < brg_star_gal_magdiff1){
    rejReason=25;
    if (diagReject && diagReject <= rejReason) {
      taGalaxiesLog (fp, obj, pet_mag_limit, petSB, pet_SB_limit, 0, 0, 0, rejReason);
    }
    return priority ;
  }

 /*
  * reject objects undetected in i' 
  * we have already rejected objects undetected in r' in the prolog
  */

  objFlags=obj->detection[TA_I].flags ;		/* just to save space */
  if (!((objFlags & AR_DFLAG_BINNED1) | 
	(objFlags & AR_DFLAG_BINNED2) | (objFlags & AR_DFLAG_BINNED4)))  {
    rejReason=20 ;
    if (diagReject && diagReject <= rejReason) {
      taGalaxiesLog (fp, obj, pet_mag_limit, petSB, pet_SB_limit, 0, 0, 0, rejReason);
    }
    return priority ;
  }
  objFlags2=obj->detection[TA_R].flags2 ;	/* to get SATUR_CENTER */

 /* 
  * Reject saturated center objects - r' was done in prolog
  *  
  */

  /* As of now reject, if SATUR. 
     TODO: Check if SATUR_CENTER is a  better flag to use */

  if ((  obj->detection[TA_G].flags &  AR_DFLAG_SATUR) || 
	(obj->detection[TA_I].flags &  AR_DFLAG_SATUR) )  {
    rejReason=21 ;
    if (diagReject && rejReason <= diagReject) {
      taGalaxiesLog (fp, obj, pet_mag_limit, petSB, pet_SB_limit, 0, 0, 0, rejReason);
    }
    return priority ;
  }

  /* 
   * cut to guard against negative Luptitudes, notably the -1000's
   *
   */
   if (obj->detection[TA_R].petroCounts.val < 0  ||
       obj->detection[TA_G].counts_model.val < 0 ||
       obj->detection[TA_R].counts_model.val < 0 ||
       obj->detection[TA_I].counts_model.val < 0 ) {
	rejReason= 22;
	if (diagReject && diagReject <= rejReason) {
	   taGalaxiesLog (fp, obj, obj->detection[TA_R].petroCounts.val, 
		obj->detection[TA_R].petroCounts.val, 22.0, 0, 0, 0, rejReason);
	}
	return priority ;
   }

  /* 
   * eliminate noisy colors
   *		Dec 1999: it is thought these are made irrelevent by the SB cut
   *
   */
   if (obj->detection[TA_G].counts_model.err > params->brg_g_error ||
       obj->detection[TA_R].counts_model.err > params->brg_r_error ||
       obj->detection[TA_I].counts_model.err > params->brg_i_error ) {
	rejReason= 23;
	deRed_r = 0;
	deRed_gr = 0;
	if (diagReject && diagReject <= rejReason) {
	   taGalaxiesLog (fp, obj, deRed_r, deRed_gr, pet_mag_limit, 0, 0, 0, rejReason);
	}
	return priority ;
   }

  /* 
   * Construct dereddened target selection quantities
   *
   */
   deRed_r = obj->detection[TA_R].petroCounts.val-obj->reddening[TA_R];
   deRed_mg = obj->detection[TA_G].counts_model.val-obj->reddening[TA_G];
   deRed_mr = obj->detection[TA_R].counts_model.val-obj->reddening[TA_R];
   deRed_mi = obj->detection[TA_I].counts_model.val-obj->reddening[TA_I];
   deRed_gr = deRed_mg-deRed_mr;
   deRed_ri = deRed_mr-deRed_mi;
   halfLightRad = obj->detection[TA_R].petroR50.val;
   petSB = deRed_r +  2.5*log10(2*3.14159*halfLightRad*halfLightRad);


  /* 
   * Construct quantities parallel and perpindicular to the galaxy locus
   *
   */
   cp_inter = params->brg_cperp_inter;
   cp_slope = params->brg_cpar_slope;
   cperp = deRed_ri - deRed_gr/params->brg_cperp_gr_slope - cp_inter;
   cpar = cp_slope*deRed_gr + 
	(1-cp_slope)*(deRed_ri - cp_inter)*params->brg_cperp_gr_slope ;

 /*
  * Reject things in the main survey if Main has done so
  *	
  */
  if (deRed_r < params->pet_mag_limit && 
	     !(	obj->primTarget & AR_TARGET_GALAXY ||
		obj->primTarget & AR_TARGET_GALAXY_BIG ||
		obj->primTarget & AR_TARGET_GALAXY_BRIGHT_CORE ) ) {
    rejReason=26 ;
    
    if (diagReject && diagReject <= rejReason) {
      taGalaxiesLog (fp, obj, pet_mag_limit, petSB, pet_SB_limit, fieldsky, objsky, deltasky_LSB, rejReason);
    }
    return priority ;
  }
  /* 
   * Eliminate strange colors
   * Dec 1999: it is thought these are made irrelevent by the SB cut
   *
   */
   if (deRed_gr > params->brg_gr_red || deRed_ri > params->brg_ri_red) { 
        rejReason= 23;
        if (diagReject && diagReject <= rejReason) {
           taGalaxiesLog (fp, obj, deRed_r, deRed_gr, deRed_ri, 0, 0, 0, rejReason);
        }
        return priority ;
   }

  /* 
   * Prepare to do sub sampling if necessary
   *
   */
   subsample = params->brg_subsample ;

  /* 
   * Cut I: to z = 0.37
   *
   */

   if (    deRed_r < params->brg_I_mag && 
	   deRed_r < params->brg_I_inter + (cpar/params->brg_I_slope) && 
	   fabs(cperp) < params->brg_I_cperp &&
	   petSB < params->brg_I_sb ) {
        random = smaRAND(0.0);	
	if ( !subsample || 
		(subsample && random < 1.00*params->brg_sample_factor))  { 
	   obj->primTarget |= AR_TARGET_GALAXY_RED;
	   priority = 1;  /*TODO: set all priorities to one */
           if (diagAccept) {
	      accReason = -4;
              taGalaxiesLog (fp1, obj, deRed_r, deRed_gr, deRed_ri, cperp, cpar, petSB, accReason);
	   }
	}
	return priority;
   }

  /* 
   * Cut II: past z = 0.37
   *
   */

    brg_star_gal_magdiff2 = params->brg_star_gal_magdiff2;

  /* Cut II star/gal separation -- We assume that Cut II has a
   a more stringent star/gal separation threshold compared to Cut I. i.e
   brg_star_gal_magdiff2 > brg_star_gal_magdiff1. So, if
   psf_model_magdiff < brg_star_gal_magdiff1, we reject this object
   in Cut I itself, and exit */

  if (psf_model_magdiff < brg_star_gal_magdiff2){
    rejReason=25;
    if (diagReject && diagReject <= rejReason) {
      taGalaxiesLog (fp, obj, pet_mag_limit, petSB, pet_SB_limit, 0, 0, 0, rejReason);
    }
    return priority ;
  }


   if (    deRed_r < params->brg_II_mag && 
	   cperp > params->brg_II_inter - deRed_gr/params->brg_II_slope &&
	   deRed_gr > params->brg_II_gr + deRed_ri*params->brg_II_gr_slope &&
	   petSB < params->brg_II_sb ) {
        random = smaRAND(0.0);	
	if ( !subsample || 
		(subsample && random < 1.00*params->brg_sample_factor))  { 
	   if ( ! (obj->primTarget & AR_TARGET_GALAXY_RED) ) {
	   	obj->primTarget |= AR_TARGET_GALAXY_RED_II;
	   }
	   obj->primTarget |= AR_TARGET_GALAXY_RED;
	   priority = 1;  /*TODO: set all priorities to one */
           if (diagAccept) {
	      accReason = -5;
              taGalaxiesLog (fp1, obj, deRed_r, deRed_gr, deRed_ri, cperp, cpar, petSB, accReason);
	   }
	}
	return priority;
   }

/* if made it to here, the object has not made it into the BRG selections.
 * reject it generically */
   rejReason= 27;
   if (diagReject && diagReject <= rejReason) {
           taGalaxiesLog (fp, obj, deRed_r, deRed_gr, deRed_ri, cperp, cpar, petSB, rejReason);
   }
   return priority;

}

void taGalaxiesLog (
	FILE *fp,
	TA_CALIB_OBJ *obj, 
	float val1,
	float val2,
	float val3,
	float val4,
	float val5,
	float val6,
	int reason
)
{
	if (val4 == 0) { val4 = obj->detection[TA_R].psfCounts.val; } 
	if (val5 == 0) { val5 = obj->detection[TA_R].fiberCounts.val; } 
	if (val6 == 0) { val6 = obj->detection[TA_R].fiberCounts.val; } 
	fprintf(fp,"%2d %4d %2d %3d %4d %8.3f %8.3f %6.3f %5.3f %6.3f %6.3f %6.3f %6.3f %6.2f %6.2f %6.2f %6.3f %6.3f %5d %2d %12.7f %12.7f\n",
	reason,
        obj->run, obj->camCol,		
	obj->field->field, obj->id, 
	obj->objc_rowc.val,obj->objc_colc.val,
	obj->detection[TA_R].petroCounts.val,
	obj->reddening[TA_R],
	val1, val2, val3, val4, val5, val6,
	obj->detection[TA_R].petroRad.val,
	obj->detection[TA_R].petroR50.val,
	obj->detection[TA_R].petroR90.val,
	obj->run,
	obj->camCol,
	obj->ra,
	obj->dec);

      }
