IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Apr 11, 2010, 5:08:29 PM (16 years ago)
Author:
eugene
Message:

updates to support psphotStack

Location:
trunk/psphot
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/psphot

  • trunk/psphot/src

    • Property svn:ignore
      •  

        old new  
        2121psphotForced
        2222psphotMakePSF
         23psphotStack
  • trunk/psphot/src/psphotFitSourcesLinearStack.c

    r27547 r27657  
    11# include "psphotInternal.h"
     2// XXX need array of covar factors for each image
     3// XXX define the 'good' / 'bad' flags?
    24
    3 // for now, let's store the detections on the readout->analysis for each readout
    4 bool psphotFitSourcesLinearStack (pmConfig *config, const pmFPAview *view, bool final)
    5 {
    6     bool status = true;
     5# define COVAR_FACTOR 1.0
    76
    8     int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
    9     psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
    10 
    11     // loop over the available readouts
    12     for (int i = 0; i < num; i++) {
    13         if (!psphotFitSourcesLinearReadoutStack (config, view, "PSPHOT.INPUT", i, final)) {
    14             psError (PSPHOT_ERR_CONFIG, false, "failed to fit sources (linear) for PSPHOT.INPUT entry %d", i);
    15             return false;
    16         }
    17     }
    18     return true;
    19 }
    20 
    21 bool psphotFitSourcesLinearReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, bool final) {
     7bool psphotFitSourcesLinearStack (pmConfig *config, psArray *objects, bool final) {
    228
    239    bool status;
    24     float x;
    25     float y;
    2610    float f;
    27     // float r;
    2811
    2912    // select the appropriate recipe information
    3013    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
    3114    assert (recipe);
    32 
    33     // find the currently selected readout
    34     pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest
    35     psAssert (file, "missing file?");
    36 
    37     pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
    38     psAssert (readout, "missing readout?");
    39 
    40     pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
    41     psAssert (detections, "missing detections?");
    42 
    43     psArray *sources = detections->allSources;
    44     psAssert (sources, "missing sources?");
    45 
    46     if (!sources->n) {
    47         psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping linear fit");
    48         return true;
    49     }
    50 
    51     pmPSF *psf = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.PSF");
    52     psAssert (sources, "missing psf?");
    5315
    5416    psTimerStart ("psphot.linear");
     
    6527    maskVal |= markVal;
    6628
    67     // source analysis is done in spatial order
    68     sources = psArraySort (sources, pmSourceSortByY);
     29    // analysis is done in spatial order (to speed up overlap search)
     30    // sort by first element in each source list
     31    objects = psArraySort (objects, pmPhotObjSortByX);
    6932
    7033    // storage array for fitSources
    71     psArray *fitSources = psArrayAllocEmpty (sources->n);
     34    psArray *fitSources = psArrayAllocEmpty (objects->n);
    7235
    73     // option to limit analysis to a specific region
    74     char *region = psMetadataLookupStr (&status, recipe, "ANALYSIS_REGION");
    75     psRegion AnalysisRegion = psRegionFromString (region);
    76     AnalysisRegion = psRegionForImage (readout->image, AnalysisRegion);
    77     if (psRegionIsNaN (AnalysisRegion)) psAbort("analysis region mis-defined");
     36    bool CONSTANT_PHOTOMETRIC_WEIGHTS = psMetadataLookupBool(&status, recipe, "CONSTANT_PHOTOMETRIC_WEIGHTS");
     37    psAssert (status, "You must provide a value for the BOOL recipe CONSTANT_PHOTOMETRIC_WEIGHTS");
    7838
    79     bool CONSTANT_PHOTOMETRIC_WEIGHTS =
    80         psMetadataLookupBool(&status, recipe, "CONSTANT_PHOTOMETRIC_WEIGHTS");
    81     if (!status) {
    82         psAbort("You must provide a value for the BOOL recipe CONSTANT_PHOTOMETRIC_WEIGHTS");
    83     }
    84     int SKY_FIT_ORDER = psMetadataLookupS32(&status, recipe, "SKY_FIT_ORDER");
    85     if (!status) {
    86         SKY_FIT_ORDER = 0;
    87     }
    88     bool SKY_FIT_LINEAR = psMetadataLookupBool(&status, recipe, "SKY_FIT_LINEAR");
    89     if (!status) {
    90         SKY_FIT_LINEAR = false;
    91     }
    92 
    93     // XXX test: choose a larger-than expected radius:
    94     float covarFactor = psImageCovarianceFactorForAperture(readout->covariance, 10.0); // Covariance matrix
    95     psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "covariance factor: %f\n", covarFactor);
    96 
    97     // XXX do not apply covarFactor for the moment...
    98     // covarFactor = 1.0;
     39    // XXX store a local static array of covar factors for each of the images (by image ID)
     40    // float covarFactor = psImageCovarianceFactorForAperture(readout->covariance, 10.0); // Covariance matrix
     41    // psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "covariance factor: %f\n", covarFactor);
    9942
    10043    // select the sources which will be used for the fitting analysis
     
    10447        if (!object->sources) continue;
    10548
    106         // check an element of the group to see if we should use it
    107         if (!object->flags & PM_PHOT_OBJ_BAD) continue;
     49        // XXX check an element of the group to see if we should use it
     50        // if (!object->flags & PM_PHOT_OBJ_BAD) continue;
    10851
    10952        for (int j = 0; j < object->sources->n; j++) {
     
    12366        }
    12467    }
    125     psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "built fitSources: %f sec (%ld objects)\n", psTimerMark ("psphot.linear"), sources->n);
     68    psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "built fitSources: %f sec (%ld objects)\n", psTimerMark ("psphot.linear"), objects->n);
    12669
    12770    if (fitSources->n == 0) {
     
    14386
    14487        // diagonal elements of the sparse matrix (auto-cross-product)
    145         f = pmSourceModelDotModel (SRCi, SRCi, CONSTANT_PHOTOMETRIC_WEIGHTS, covarFactor);
     88        f = pmSourceModelDotModel (SRCi, SRCi, CONSTANT_PHOTOMETRIC_WEIGHTS, COVAR_FACTOR);
    14689        psSparseMatrixElement (sparse, i, i, f);
    14790
    14891        // the formal error depends on the weighting scheme
    14992        if (CONSTANT_PHOTOMETRIC_WEIGHTS) {
    150             float var = pmSourceModelDotModel (SRCi, SRCi, false, covarFactor);
     93            float var = pmSourceModelDotModel (SRCi, SRCi, false, COVAR_FACTOR);
    15194            errors->data.F32[i] = 1.0 / sqrt(var);
    15295        } else {
     
    15598
    15699        // find the image x model value
    157         f = pmSourceDataDotModel (SRCi, SRCi, CONSTANT_PHOTOMETRIC_WEIGHTS, covarFactor);
     100        f = pmSourceDataDotModel (SRCi, SRCi, CONSTANT_PHOTOMETRIC_WEIGHTS, COVAR_FACTOR);
    158101        psSparseVectorElement (sparse, i, f);
    159102
     
    162105            pmSource *SRCj = fitSources->data[j];
    163106
    164             // XXX I need to know if this source is on the same image as SRCi --
    165             if (!sameImge) { continue; }
     107            // we only need to generate dot terms for source on the same image
     108            if (SRCj->imageID != SRCi->imageID) { continue; }
    166109
    167110            // skip over disjoint source images, break after last possible overlap
    168             if (SRCi->pixels->row0 + SRCi->pixels->numRows < SRCj->pixels->row0) break;
    169             if (SRCj->pixels->row0 + SRCj->pixels->numRows < SRCi->pixels->row0) continue;
    170             if (SRCi->pixels->col0 + SRCi->pixels->numCols < SRCj->pixels->col0) continue;
    171             if (SRCj->pixels->col0 + SRCj->pixels->numCols < SRCi->pixels->col0) continue;
     111            if (SRCj->pixels->row0 + SRCj->pixels->numRows < SRCi->pixels->row0) continue;  // source(i) is above source(j)
     112            if (SRCi->pixels->row0 + SRCi->pixels->numRows < SRCj->pixels->row0) continue;  // source(i) is below source(j)
     113            if (SRCj->pixels->col0 + SRCj->pixels->numCols < SRCi->pixels->col0) continue;  // source(i) is right of source(j)
     114            if (SRCi->pixels->col0 + SRCi->pixels->numCols < SRCj->pixels->col0) break;     // source(i) is left of source(j) [no other source(j) can overlap source(i)]
    172115
    173116            // got an overlap; calculate cross-product and add to output array
    174             f = pmSourceModelDotModel (SRCi, SRCj, CONSTANT_PHOTOMETRIC_WEIGHTS, covarFactor);
     117            f = pmSourceModelDotModel (SRCi, SRCj, CONSTANT_PHOTOMETRIC_WEIGHTS, COVAR_FACTOR);
    175118            psSparseMatrixElement (sparse, j, i, f);
    176119        }
     
    190133    psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "solve matrix: %f sec (%d elements)\n", psTimerMark ("psphot.linear"), sparse->Nelem);
    191134
    192     // XXXX **** philosophical question:
    193     // we measure bright objects in three passes: 1) linear fit; 2) non-linear fit; 3) linear fit:
    194     // should retain the chisq and errors from the intermediate non-linear fit?
    195     // the non-linear fit provides better values for the position errors, and for
    196     // extended sources, the shape errors
    197 
    198135    // adjust I0 for fitSources and subtract
    199136    for (int i = 0; i < fitSources->n; i++) {
     
    208145        model->params->data.F32[PM_PAR_I0] = norm->data.F32[i];
    209146        model->dparams->data.F32[PM_PAR_I0] = errors->data.F32[i];
    210         // XXX is the value of 'errors' modified by the sky fit?
    211147
    212148        // subtract object
     
    221157        if (source->mode & PM_SOURCE_MODE_NONLINEAR_FIT) continue;
    222158        pmModel *model = pmSourceGetModel (NULL, source);
    223         pmSourceChisq (model, source->pixels, source->maskObj, source->variance, maskVal, covarFactor);
     159        pmSourceChisq (model, source->pixels, source->maskObj, source->variance, maskVal, COVAR_FACTOR);
    224160    }
    225161    psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "get chisqs: %f sec (%d elements)\n", psTimerMark ("psphot.linear"), sparse->Nelem);
     
    229165    psFree (fitSources);
    230166    psFree (norm);
    231     psFree (skyfit);
    232167    psFree (errors);
    233     psFree (border);
    234168
    235169    psLogMsg ("psphot.ensemble", PS_LOG_INFO, "measure ensemble of PSFs: %f sec\n", psTimerMark ("psphot.linear"));
    236 
    237     psphotVisualShowResidualImage (readout);
    238     psphotVisualPlotChisq (sources);
    239     // psphotVisualShowFlags (sources);
    240 
    241     // We have to place this visualization here because the models are not realized until
    242     // psphotGuessModels or fitted until psphotFitSourcesLinear.
    243     psphotVisualShowPSFStars (recipe, psf, sources);
    244170
    245171    return true;
    246172}
    247173
    248 // XXX do we need this?
    249 // XXX disallow the simultaneous sky fit and remove this code...
     174// sort by X (ascending)
     175int pmPhotObjSortByX (const void **a, const void **b)
     176{
     177    pmPhotObj *objA = *(pmPhotObj **)a;
     178    pmPhotObj *objB = *(pmPhotObj **)b;
    250179
    251 // Calculate the weight terms for the sky fit component of the matrix.  This function operates
    252 // on the pixels which correspond to all of the sources of interest.  These elements fill in
    253 // the border matrix components in the sparse matrix equation.
    254 static bool SetBorderMatrixElements (psSparseBorder *border, pmReadout *readout, psArray *sources, bool constant_weights, int SKY_FIT_ORDER, psImageMaskType markVal) {
     180    psF32 fA = objA->x;
     181    psF32 fB = objB->x;
    255182
    256     // generate the image-wide weight terms
    257     // turn on MARK for all image pixels
    258     psRegion fullArray = psRegionSet (0, 0, 0, 0);
    259     fullArray = psRegionForImage (readout->mask, fullArray);
    260     psImageMaskRegion (readout->mask, fullArray, "OR", markVal);
    261 
    262     // turn off MARK for all object pixels
    263     for (int i = 0; i < sources->n; i++) {
    264         pmSource *source = sources->data[i];
    265         pmModel *model = pmSourceGetModel (NULL, source);
    266         if (model == NULL) continue;
    267         float x = model->params->data.F32[PM_PAR_XPOS];
    268         float y = model->params->data.F32[PM_PAR_YPOS];
    269         psImageMaskCircle (source->maskView, x, y, model->fitRadius, "AND", PS_NOT_IMAGE_MASK(markVal));
    270     }
    271 
    272     // accumulate the image statistics from the masked regions
    273     psF32 **image  = readout->image->data.F32;
    274     psF32 **variance = readout->variance->data.F32;
    275     psImageMaskType  **mask   = readout->mask->data.PS_TYPE_IMAGE_MASK_DATA;
    276 
    277     double w, x, y, x2, xy, y2, xc, yc, wt, f, fo, fx, fy;
    278     w = x = y = x2 = xy = y2 = fo = fx = fy = 0;
    279 
    280     int col0 = readout->image->col0;
    281     int row0 = readout->image->row0;
    282 
    283     for (int j = 0; j < readout->image->numRows; j++) {
    284         for (int i = 0; i < readout->image->numCols; i++) {
    285             if (mask[j][i]) continue;
    286             if (constant_weights) {
    287                 wt = 1.0;
    288             } else {
    289                 wt = variance[j][i];
    290             }
    291             f = image[j][i];
    292             w   += 1/wt;
    293             fo  += f/wt;
    294             if (SKY_FIT_ORDER == 0) continue;
    295 
    296             xc  = i + col0;
    297             yc  = j + row0;
    298             x  +=    xc/wt;
    299             y  +=    yc/wt;
    300             x2 += xc*xc/wt;
    301             xy += xc*yc/wt;
    302             y2 += yc*yc/wt;
    303             fx +=  f*xc/wt;
    304             fy +=  f*yc/wt;
    305         }
    306     }
    307 
    308     // turn off MARK for all image pixels
    309     psImageMaskRegion (readout->mask, fullArray, "AND", PS_NOT_IMAGE_MASK(markVal));
    310 
    311     // set the Border T elements
    312     psSparseBorderElementG (border, 0, fo);
    313     psSparseBorderElementT (border, 0, 0, w);
    314     if (SKY_FIT_ORDER > 0) {
    315         psSparseBorderElementG (border, 0, fx);
    316         psSparseBorderElementG (border, 0, fy);
    317         psSparseBorderElementT (border, 1, 0, x);
    318         psSparseBorderElementT (border, 2, 0, y);
    319         psSparseBorderElementT (border, 0, 1, x);
    320         psSparseBorderElementT (border, 1, 1, x2);
    321         psSparseBorderElementT (border, 2, 1, xy);
    322         psSparseBorderElementT (border, 0, 2, y);
    323         psSparseBorderElementT (border, 1, 2, xy);
    324         psSparseBorderElementT (border, 2, 2, y2);
    325     }
    326 
    327     return true;
     183    psF32 diff = fA - fB;
     184    if (diff > FLT_EPSILON) return (+1);
     185    if (diff < FLT_EPSILON) return (-1);
     186    return (0);
    328187}
Note: See TracChangeset for help on using the changeset viewer.