/***************************************************************************** ****************************************************************************** **<AUTO> ** ** FILE:	standards.c
**
**<HTML>
**	This file contains C functions to select the following targets:
**	the standards targets.
**	<li> spectrophotometric standards
**	<li> reddening standards
**	<li> guide stars
**	<li> hot stars
**	<li> blank sky fiber positions
**	</menu>
**</HTML>
**</AUTO>
**
**
** ENVIRONMENT:
**	ANSI C.
**
******************************************************************************
******************************************************************************
*/
#include <dervish.h>
#include "taCalibObj.h"
#include "taStandards.h"
#include "arTargetType.h"
#include "arDetectionFlag.h"
#include "arObjectStatus.h"
#include "arObjectType.h"



/*****************************************************************************
******************************************************************************
**<AUTO EXTRACT>
**
** ROUTINE:	taStandardsTargetSelect
**
**<HTML>
**	Set the appropriate bit in the secondary target bit mask for each
**	standards target selection criterion this object
**	satisfies.  This routine is responsible for setting the following
**	bits:
**	<menu>
**	<li> TAR_TARGET_SPECTROPHOTO_STD
**	<li> TAR_TARGET_REDDEN_STD
**	<li> TAR_TARGET_GUIDE_STAR
**	<li> TAR_TARGET_SKY
**	<li> TAR_TARGET_HOT_STD
**	</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
taStandardsTargetSelect(TA_CALIB_OBJ *obj,
			/* MOD: calibrated object to test */
			const TA_STANDARDS_PARAMS *params
			/* IN: tunable parameters */)
{
   int priority = 0;     /* targeting priority (initialize for a non-target) */
   int q_star, q_noblend, q_noedge, q_nointerp, q_moved;
   int q_goodhot, q_goodcenter, q_accept;
   float u, g, r, i, z;
   float u_c, g_c, r_c, i_c, z_c;
   float ug_c, gr_c, ri_c, iz_c;
   float ug, gr, ri, iz;
   float fdist;

   priority = 0; /* Default priority is zero for non-selected objects. */

   /* Only select objects brighter than "spectralLimit" in r-band. */
   if (obj->detection[TA_R].fiberCounts.val < params->spectralLimit) {
      /* Extract object magnitudes and colors */
      u = obj->detection[TA_U].psfCounts.val;
      g = obj->detection[TA_G].psfCounts.val;
      r = obj->detection[TA_R].psfCounts.val;
      i = obj->detection[TA_I].psfCounts.val;
      z = obj->detection[TA_Z].psfCounts.val;
      ug = u - g;
      gr = g - r;
      ri = r - i;
      iz = i - z;

      /* Define de-reddened magnitudes and colors */
      u_c = u - obj->reddening[TA_U];
      g_c = g - obj->reddening[TA_G];
      r_c = r - obj->reddening[TA_R];
      i_c = i - obj->reddening[TA_I];
      z_c = z - obj->reddening[TA_Z];
      ug_c = u_c - g_c;
      gr_c = g_c - r_c;
      ri_c = r_c - i_c;
      iz_c = i_c - z_c;

      /* Compute distance from canonical reddening standard in ugr-color space
         Choose this canonical color to be approximately that of BD+17o4708.
         The following colors will need to be adjusted once we have the proper
         zero-points in each band.
       */
      fdist = sqrt( pow(ug_c-0.80,2) + pow(gr_c-0.30,2) + pow(ri_c-0.10,2) );
      fdist = sqrt( pow(ug_c - params->FSTARug, 2)
                  + pow(gr_c - params->FSTARgr, 2)
                  + pow(ri_c - params->FSTARri, 2) );

      /* Test if a star.  Star if either of the following is true:
       * (1) Classified by PHOTO as a star.
       * (2) r < 15 mag, and radius < 1.0 arcsec.
       */
      q_star = obj->objc_type == AR_OBJECT_TYPE_STAR
       || (r < 15.0 && obj->detection[TA_R].petroRad.val < 1.0);

      /* Test for unique, isolated objects.
         Exclude BRIGHT objects since they are sibling (copies) of others.
         Exclude CHILD objects since they were blended children.
         Exclude anything with BLENDED flag set, since those were found
          to have multiple peaks by PHOTO.  PHOTO may not have deblended
          these, in which case the NO_DEBLEND flag would also be set.
          But we still do not wish to select them.
      */
      q_noblend = !(obj->objc_flags & AR_DFLAG_BRIGHT) 
               && !(obj->objc_flags & AR_DFLAG_CHILD) 
               && !(obj->objc_flags & AR_DFLAG_BLENDED); 
      /* The following code would test for objects not deblended, even if
         the BLENDED flag was set.
      */
/*
      q_noblend = !(obj->objc_flags & AR_DFLAG_BRIGHT) 
               && !(obj->objc_flags & AR_DFLAG_CHILD) 
               && (!(obj->objc_flags & AR_DFLAG_BLENDED) || 
                    ((obj->objc_flags & AR_DFLAG_BLENDED) && 
                     (obj->objc_flags & AR_DFLAG_NODEBLEND)));
*/

      /* Test for objects near edge of frame. */
      q_noedge =  !(obj->objc_flags & AR_DFLAG_EDGE);

      /* Test for objects that may have moved. */
      q_moved = !(obj->objc_flags & AR_DFLAG_MOVED);

      /* Test for objects with any interpolated pixels, due either to
         cosmic rays or bad columns on the CCD.
      */
      q_nointerp = !(obj->objc_flags & AR_DFLAG_INTERP);

      /* Test for no really bad events in u+g bands (for HOT stars).
      */
      q_goodhot = !(obj->detection[TA_U].flags & AR_DFLAG_INTERP)
               && !(obj->detection[TA_G].flags & AR_DFLAG_INTERP);

      /* Test for center being accurate:
       * It must not be saturated in at least one of griz (don't count on u).
       * It must have row and column center errors less than 0.5 pixels (0.2").
      */
      q_goodcenter = 
           ( !(obj->detection[TA_G].flags & AR_DFLAG_SATUR)
          || !(obj->detection[TA_R].flags & AR_DFLAG_SATUR)
          || !(obj->detection[TA_I].flags & AR_DFLAG_SATUR)
          || !(obj->detection[TA_Z].flags & AR_DFLAG_SATUR) )
       && obj->objc_rowc.err < 0.5
       && obj->objc_colc.err < 0.5;

      /* Combined quality test for all our objects, except
         for q_nointerp, q_goodcenter.
      */
      q_accept = q_star && q_noblend && q_noedge && q_moved;

      /* Select F-star reddending stars. De-reddened magnitudes and colors. */
      if ( g_c >= params->REDSTDgbright && g_c  < params->REDSTDgfaint
       && ug_c >= params->FSTARuglo   && ug_c < params->FSTARughi
       && gr_c >= params->FSTARgrlo   && gr_c < params->FSTARgrhi
       && gr_c >= params->FSTARugrslope * ug_c + params->FSTARugrint
       && q_accept && q_nointerp) {
         obj->secTarget |= TAR_TARGET_REDDEN_STD;

         /* Set priority based upon distance from canonical reddening std */
         priority = 100 - 100 * fdist;
         priority = priority > 0 ? priority : 1;
      }

      /* Select HOT reddending stars. De-reddened magnitudes and colors. */
      if ( g_c >= params->HOTSTARgbright && g_c  < params->HOTSTARgfaint
       && ug_c >= params->HOTSTARuglo   && ug_c < params->HOTSTARughi
       && gr_c >= params->HOTSTARgrlo   && gr_c < params->HOTSTARgrhi
       && q_accept && q_goodhot) {
         obj->secTarget |= TAR_TARGET_HOT_STD;
         priority = 1;
      }

      /* Select spectrophotometric stars. De-redden magnitudes and colors. */
      if (g_c >= params->SPECSTDgbright && g_c < params->SPECSTDgfaint
       && ug_c >= params->FSTARuglo && ug_c < params->FSTARughi
       && gr_c >= params->FSTARgrlo && gr_c < params->FSTARgrhi
       && gr_c >= params->FSTARugrslope * ug_c + params->FSTARugrint
       && q_accept && q_nointerp) {
         obj->secTarget |= TAR_TARGET_SPECTROPHOTO_STD;

         /* Set priority based upon distance from canonical reddening std */
         priority = 100 - 100 * fdist;
         priority = priority > 0 ? priority : 1;
      }

      /* Select guide stars. Do **not** de-redden magnitudes and colors.
         Note that these are the only stars we select based upon apparent
         magnitudes and colors rather than intrinsic (reddened) quantities.
      */
      if (g >= params->GUIDESTARgbright && g < params->GUIDESTARgfaint
       && ug_c >= params->GUIDESTARuglo && ug_c < params->GUIDESTARughi
       && gr_c >= params->GUIDESTARgrlo && gr_c < params->GUIDESTARgrhi
       && ri_c >= params->GUIDESTARrilo && ri_c < params->GUIDESTARrihi
       && iz_c >= params->GUIDESTARizlo && iz_c < params->GUIDESTARizhi
       && q_accept && q_goodcenter) {
         obj->secTarget |= TAR_TARGET_GUIDE_STAR;
         /* Set priority for guide stars that prefers brighter guide stars
            The priority is in the range [1,100].  */
         priority = (params->GUIDESTARgfaint - g) / 
          (params->GUIDESTARgfaint - params->GUIDESTARgbright) * 99 + 1;
      }
   }

   /* Select blank sky.  PHOTO selects 5 sky positions per frame.
      We select all of them here, and set a priority of 1 for all.
   */
   if (obj->objc_type == AR_OBJECT_TYPE_SKY) {
      obj->secTarget |= TAR_TARGET_SKY;
      priority = 1;
   }

   return priority;
}
