/*****************************************************************************
******************************************************************************
**<AUTO>
**
** FILE:	diag.c
**
**<HTML>
**	This file contains C functions perform diagnostics for target
**	selection.
**</HTML>
**</AUTO>
**
**
** ENVIRONMENT:
**	ANSI C.
**
******************************************************************************
******************************************************************************
*/
#include <dervish.h>
#include "taDiag.h"
#include "taCalibObj.h"
#include "arTargetType.h"
#include "arObjectStatus.h"

/*****************************************************************************
******************************************************************************
**<AUTO EXTRACT>
**
** ROUTINE:	taDiagNew
**
**<HTML>
**	Allocate and initialize a TA_DIAG structure.
**</HTML>
**</AUTO>
******************************************************************************
******************************************************************************
*/
TA_DIAG*
taDiagNew()
{
  int i;
  TA_DIAG *diag = NULL;

  /* Allocate the space */
  diag = shMalloc(sizeof(TA_DIAG));

  /* Initialize areas */
  diag->scanlineArea = 0.;
  diag->goodScanlineArea = 0.;
  diag->holeScanlineArea = 0.;
  diag->stripeArea = 0.;
  diag->goodStripeArea = 0.;
  diag->holeStripeArea = 0.;
 
  /* Initialize simple counts */
  diag->nPrim = 0;
  diag->nScanline = 0;
  diag->nPrimTargets = 0;
  diag->nScanlineTargets = 0;
  diag->nPrimGalaxy = 0;
  diag->nScanlineGalaxy = 0;
  diag->nPrimQSO = 0;
  diag->nScanlineQSO = 0;
  diag->nPrimROSAT = 0;
  diag->nScanlineROSAT = 0;
  diag->nPrimStar = 0;
  diag->nScanlineStar = 0;
  diag->nPrimSerendipity = 0;
  diag->nScanlineSerendipity = 0;
  for (i = 0; i < 32; i++)
    {
      diag->nPrimPrimType[i] = 0;
      diag->nScanlinePrimType[i] = 0;
      diag->nPrimSecType[i] = 0;
      diag->nScanlineSecType[i] = 0;
    }
  diag->nPrimBRG = 0;
  diag->nScanlineBRG = 0;

  /* Initialize USNO matching stuff */
  diag->usnoAllHist = NULL;
  diag->usnoMatchedHist = NULL;
  diag->usnoStarDistanceHist = NULL;
  diag->usnoStarAngleHist = NULL;
  diag->usnoGalDistanceHist = NULL;
  diag->usnoGalAngleHist = NULL;

  /* Return the new structure */
  return diag;
}

/*****************************************************************************
******************************************************************************
**<AUTO EXTRACT>
**
** ROUTINE:	taDiagDel
**
**<HTML>
**	Delete a TA_DIAG structure.
**</HTML>
**</AUTO>
******************************************************************************
******************************************************************************
*/
void
taDiagDel(TA_DIAG* diag)
{
  if (diag->usnoAllHist != NULL) shHgDel(diag->usnoAllHist);
  if (diag->usnoMatchedHist != NULL) shHgDel(diag->usnoMatchedHist);
  if (diag->usnoStarDistanceHist != NULL) shHgDel(diag->usnoStarDistanceHist);
  if (diag->usnoStarAngleHist != NULL) shHgDel(diag->usnoStarAngleHist);
  if (diag->usnoGalDistanceHist != NULL) shHgDel(diag->usnoGalDistanceHist);
  if (diag->usnoGalAngleHist != NULL) shHgDel(diag->usnoGalAngleHist);
  shFree(diag);
}

/*****************************************************************************
******************************************************************************
**<AUTO EXTRACT>
**
** ROUTINE:	taDiagUpdate
**
**<HTML>
**	Update the running diagnostics from a single object which has been
**	through target selection.
**</HTML>
**</AUTO>
******************************************************************************
******************************************************************************
*/
RET_CODE
taDiagUpdate(TA_DIAG *diag,          /* MOD: target diagnostics */
	     const TA_CALIB_OBJ *obj /* IN:  object which has been through
				      *      target selection */)
{
  int bin, i;

  /* Priority > 0 masks */
  int galaxyMask = 
    AR_TARGET_GALAXY_RED |
    AR_TARGET_GALAXY_RED_II |
    AR_TARGET_GALAXY |
    AR_TARGET_GALAXY_BIG |
    AR_TARGET_GALAXY_BRIGHT_CORE;
  int qsoMask = 
    AR_TARGET_QSO_HIZ |
    AR_TARGET_QSO_CAP |
    AR_TARGET_QSO_SKIRT |
    AR_TARGET_QSO_FIRST_CAP |
    AR_TARGET_QSO_FIRST_SKIRT;
  int rosatMask =
    AR_TARGET_ROSAT_A |
    AR_TARGET_ROSAT_B |
    AR_TARGET_ROSAT_C |
    AR_TARGET_ROSAT_D;
  int starMask =
    AR_TARGET_STAR_BHB |
    AR_TARGET_STAR_CARBON |
    AR_TARGET_STAR_BROWN_DWARF |
    AR_TARGET_STAR_SUB_DWARF |
    AR_TARGET_STAR_CATY_VAR |
    AR_TARGET_STAR_RED_DWARF |
    AR_TARGET_STAR_WHITE_DWARF |
    AR_TARGET_STAR_PN;
  int serendipityMask =
    AR_TARGET_SERENDIP_BLUE |
    AR_TARGET_SERENDIP_FIRST |
    AR_TARGET_SERENDIP_RED |
    AR_TARGET_SERENDIP_DISTANT |
    AR_TARGET_SERENDIP_MANUAL;

  /* Update simple counts */
  if (obj->status & AR_OBJECT_STATUS_PRIMARY)
    {
      diag->nPrim++;
      if (obj->primTarget != 0 && obj->priority > 0)
	diag->nPrimTargets++;
      for (i = 0; i <= 32; i++)
	{
	  if (obj->primTarget & (1 << i)) diag->nPrimPrimType[i]++;
	  if (obj->secTarget & (1 << i)) diag->nPrimSecType[i]++;
	}
      if (obj->primTarget & galaxyMask)	diag->nPrimGalaxy++;
      if (obj->primTarget & qsoMask) diag->nPrimQSO++;
      if (obj->primTarget & rosatMask) diag->nPrimROSAT++;
      if (obj->primTarget & starMask) diag->nPrimStar++;
      if (obj->primTarget & serendipityMask) diag->nPrimSerendipity++;
      if ((obj->primTarget & AR_TARGET_GALAXY_RED) &&
	  ! (obj->primTarget & (AR_TARGET_GALAXY | AR_TARGET_GALAXY_BIG |
				AR_TARGET_GALAXY_BRIGHT_CORE)))
	diag->nPrimBRG++;
    }
  if (obj->status & AR_OBJECT_STATUS_OK_SCANLINE)
    {
      diag->nScanline++;
      if (obj->primTarget != 0 && obj->priority > 0)
	diag->nScanlineTargets++;
      for (i = 0; i <= 32; i++)
	{
	  if (obj->primTarget & (1 << i)) diag->nScanlinePrimType[i]++;
	  if (obj->secTarget & (1 << i)) diag->nScanlineSecType[i]++;
	}
      if (obj->primTarget & galaxyMask)	diag->nScanlineGalaxy++;
      if (obj->primTarget & qsoMask) diag->nScanlineQSO++;
      if (obj->primTarget & rosatMask) diag->nScanlineROSAT++;
      if (obj->primTarget & starMask) diag->nScanlineStar++;
      if (obj->primTarget & serendipityMask) diag->nScanlineSerendipity++;
      if ((obj->primTarget & AR_TARGET_GALAXY_RED) &&
	  ! (obj->primTarget & (AR_TARGET_GALAXY | AR_TARGET_GALAXY_BIG |
				AR_TARGET_GALAXY_BRIGHT_CORE)))
	diag->nScanlineBRG++;
    }
    
  /* Update USNO matching statistics (based on OK_SCANLINE sample in specified
   * model g' magnitude range, stars and galaxies only) */
  if (obj->status & AR_OBJECT_STATUS_OK_SCANLINE && 
      obj->detection[1].counts_model.val > diag->usnoGMin &&
      obj->detection[1].counts_model.val < diag->usnoGMax &&
      (obj->objc_type == AR_OBJECT_TYPE_STAR ||
       obj->objc_type == AR_OBJECT_TYPE_GALAXY))
    {
      /* Update counts vs mag histogram */
      shHgFill(diag->usnoAllHist, obj->detection[1].counts_model.val, 1.);
      if (obj->properMotionMatch)
	{
	  /* Matched a USNO object.  Update matched histograms. */
	  shHgFill(diag->usnoMatchedHist, obj->detection[1].counts_model.val,
		   1.);
	  if (obj->objc_type == AR_OBJECT_TYPE_STAR)
	    {
	      shHgFill(diag->usnoStarDistanceHist, obj->properMotionDelta, 1.);
	      shHgFill(diag->usnoStarAngleHist, obj->properMotionAngle, 1.);
	    }
	  else
	    {
	      shHgFill(diag->usnoGalDistanceHist, obj->properMotionDelta, 1.);
	      shHgFill(diag->usnoGalAngleHist, obj->properMotionAngle, 1.);
	    }
	}
    }

  /* Successful return */
  return SH_SUCCESS;
}





