/** @file psastroOneChipGrid.c
 *
 *  @brief 
 *
 *  @ingroup libpsastro
 *
 *  @author IfA
 *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
 *  @date $Date: 2009-02-07 02:03:34 $
 *  Copyright 2009 Institute for Astronomy, University of Hawaii
 */

# include "psastroInternal.h"

# define REQUIRED_RECIPE_VALUE(VALUE, NAME, TYPE)\
  VALUE = psMetadataLookup##TYPE (&status, recipe, NAME); \
  if (!status) { \
   psAbort ("Failed to find %s in recipe", NAME); }

bool psastroOneChipGrid (pmFPA *fpa, pmChip *chip, psArray *refstars, psArray *rawstars, psMetadata *recipe, psMetadata *updates) {

    bool status;
    pmAstromStats *stats = NULL;

    // do we need to get a rough initial match?
    REQUIRED_RECIPE_VALUE (bool gridSearch, "PSASTRO.GRID.SEARCH", Bool);
    if (!gridSearch) return true;

    // do we need to get a rough initial match?
    REQUIRED_RECIPE_VALUE (int maxNstar, "PSASTRO.GRID.NSTAR.MAX", S32);

    // generate the bright subset of maxNstar entries (note: rawstars is sorted by S/N)
    psArray *gridStars = psArrayAlloc (PS_MIN (maxNstar, rawstars->n));
    for (int i = 0; (i < maxNstar) && (i < rawstars->n); i++) {
	gridStars->data[i] = psMemIncrRefCounter (rawstars->data[i]);
    }

    psLogMsg ("psastro", 3, "grid search using %ld raw vs %ld ref stars\n", gridStars->n, refstars->n);

    // find initial offset / rotation / scale
    pmAstromStats *gridStats = pmAstromGridMatch (gridStars, refstars, recipe);
    if (gridStats == NULL) {
	psLogMsg ("psastro", 3, "failed to find a grid match solution\n");
	psFree (gridStars);
	return false;
    }
    psLogMsg ("psastro", 3, "basic grid search result - offset: %f,%f pixels, rotation: %f deg\n", gridStats->offset.x, gridStats->offset.y, DEG_RAD*gridStats->angle);

    // tweak the position by finding peak of matches stars
    stats = pmAstromGridTweak (gridStars, refstars, recipe, gridStats);
    if (stats == NULL) {
	psLogMsg ("psastro", 3, "failed to measure tweaked grid solution\n");
	psFree (gridStats);
	psFree (gridStars);
	return false;
    }
    psLogMsg ("psastro", 3, "tweak grid search result - offset: %f,%f pixels, rotation: %f deg\n", stats->offset.x, stats->offset.y, DEG_RAD*stats->angle);

    // adjust the chip.toFPA terms only
    pmAstromGridApply (chip->toFPA, stats);
    psastroUpdateChipToFPA (fpa, chip); // updates PSASTRO.RAWSTARS and PSASTRO.REFSTARS
    psFree (gridStats);
    psFree (gridStars);
    psFree (stats);

    return true;
}
