IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
May 3, 2010, 8:50:52 AM (16 years ago)
Author:
eugene
Message:

updates from trunk

Location:
branches/simtest_nebulous_branches
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • branches/simtest_nebulous_branches

  • branches/simtest_nebulous_branches/psphot

  • branches/simtest_nebulous_branches/psphot/src

    • Property svn:ignore
      •  

        old new  
        1818psphotVersionDefinitions.h
        1919psphotMomentsStudy
         20psphotPetrosianStudy
         21psphotForced
         22psphotMakePSF
         23psphotStack
  • branches/simtest_nebulous_branches/psphot/src/psphotSourceStats.c

    r24589 r27840  
    11# include "psphotInternal.h"
    22
    3 psArray *psphotSourceStats (pmConfig *config, pmReadout *readout, pmDetections *detections) {
     3// convert detections to sources and measure their basic properties (moments, local sky, sky
     4// variance) Note: this function only generates sources for the new peaks (peak->assigned).
     5// The new sources are added to any existing sources on detections->newSources.  The sources
     6// on detections->allSources are ignored.
     7bool psphotSourceStats (pmConfig *config, const pmFPAview *view, bool setWindow)
     8{
     9    bool status = true;
     10
     11    // select the appropriate recipe information
     12    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     13    psAssert (recipe, "missing recipe?");
     14
     15    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     16    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     17
     18    // loop over the available readouts
     19    for (int i = 0; i < num; i++) {
     20        if (!psphotSourceStatsReadout (config, view, "PSPHOT.INPUT", i, recipe, setWindow)) {
     21            psError (PSPHOT_ERR_CONFIG, false, "failed to find initial detections for PSPHOT.INPUT entry %d", i);
     22            return false;
     23        }
     24    }
     25    return true;
     26}
     27
     28bool psphotSourceStatsReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe, bool setWindow) {
    429
    530    bool status = false;
     
    833    psTimerStart ("psphot.stats");
    934
    10     // select the appropriate recipe information
    11     psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
    12     assert (recipe);
     35    // find the currently selected readout
     36    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest
     37    psAssert (file, "missing file?");
     38
     39    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     40    psAssert (readout, "missing readout?");
     41
     42    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     43    psAssert (detections, "missing detections?");
     44
     45    // XXX TEST:
     46    if (detections->allSources) {
     47        psphotMaskCosmicRayFootprintCheck(detections->allSources);
     48    }
     49    if (detections->newSources) {
     50        psphotMaskCosmicRayFootprintCheck(detections->newSources);
     51    }
    1352
    1453    // determine the number of allowed threads
     
    1958
    2059    // determine properties (sky, moments) of initial sources
    21     float OUTER    = psMetadataLookupF32 (&status, recipe, "SKY_OUTER_RADIUS");
    22     if (!status) return NULL;
     60    float OUTER = psMetadataLookupF32 (&status, recipe, "SKY_OUTER_RADIUS");
     61    psAssert (status, "missing SKY_OUTER_RADIUS in recipe?");
     62
     63    // XXX this seems like an arbitrary number...
     64    OUTER = PS_MAX(OUTER, 20.0); // XXX Guarantee that we can encompass the max moments radius
     65
    2366    char *breakPt  = psMetadataLookupStr (&status, recipe, "BREAK_POINT");
    24     if (!status) return NULL;
     67    psAssert (status, "missing BREAK_POINT?");
     68
     69    float INNER        = psMetadataLookupF32 (&status, recipe, "SKY_INNER_RADIUS"); psAssert (status, "missing SKY_INNER_RADIUS");
     70    float MIN_SN       = psMetadataLookupF32 (&status, recipe, "MOMENTS_SN_MIN"); psAssert (status, "missing MOMENTS_SN_MIN");
     71
     72    // bit-masks to test for good/bad pixels
     73    psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT");
     74    psAssert (maskVal, "missing MASK.PSPHOT");
     75
     76    // bit-mask to mark pixels not used in analysis
     77    psImageMaskType markVal = psMetadataLookupImageMask(&status, recipe, "MARK.PSPHOT");
     78    psAssert (markVal, "missing MARK.PSPHOT");
    2579
    2680    psArray *peaks = detections->peaks;
    2781    if (!peaks) {
    2882        psError(PS_ERR_UNEXPECTED_NULL, false, "No peaks found!");
    29         return NULL;
     83        return false;
    3084    }
    3185
    3286    // generate the array of sources, define the associated pixel
    33     sources = psArrayAllocEmpty (peaks->n);
     87    if (!detections->newSources) {
     88        detections->newSources = psArrayAllocEmpty (peaks->n);
     89    }
     90    sources = detections->newSources;
     91
     92    // if there are no peaks, we save the empty source array and return
     93    if (!peaks->n) {
     94        return true;
     95    }
    3496
    3597    for (int i = 0; i < peaks->n; i++) {
     
    40102        // create a new source
    41103        pmSource *source = pmSourceAlloc();
     104        source->imageID = index;
    42105
    43106        // add the peak
     
    53116        psArrayAdd (sources, 100, source);
    54117        psFree (source);
     118    }
     119
     120    if (!strcasecmp (breakPt, "PEAKS")) {
     121        psLogMsg ("psphot", PS_LOG_INFO, "%ld sources : %f sec\n", sources->n, psTimerMark ("psphot.stats"));
     122        psLogMsg ("psphot", PS_LOG_INFO, "break point PEAKS, skipping MOMENTS\n");
     123        psphotVisualShowMoments (sources);
     124        return true;
     125    }
     126
     127    if (setWindow) {
     128        if (!psphotSetMomentsWindow(recipe, readout->analysis, sources)) {
     129            psError(PS_ERR_UNEXPECTED_NULL, false, "Failed to determine Moments Window!");
     130            psFree(detections->newSources);
     131            return false;
     132        }
     133    }
     134
     135    // if we have measured the window, we will be saving the modified version of these recipe values on readout->analysis
     136    float SIGMA = psMetadataLookupF32 (&status, readout->analysis, "MOMENTS_GAUSS_SIGMA");
     137    if (!status) {
     138        SIGMA = psMetadataLookupF32 (&status, recipe, "MOMENTS_GAUSS_SIGMA");
     139    }
     140    float RADIUS = psMetadataLookupF32 (&status, readout->analysis, "PSF_MOMENTS_RADIUS");
     141    if (!status) {
     142        RADIUS = psMetadataLookupF32 (&status, recipe, "PSF_MOMENTS_RADIUS");
     143    }
     144
     145    // threaded measurement of the source magnitudes
     146    int Nfail = 0;
     147    int Nmoments = 0;
     148    int Nfaint = 0;
     149
     150    // choose Cx, Cy (see psphotThreadTools.c for overview of the concepts)
     151    int Cx = 1, Cy = 1;
     152    psphotChooseCellSizes (&Cx, &Cy, readout, nThreads);
     153
     154    psArray *cellGroups = psphotAssignSources (Cx, Cy, sources);
     155
     156    for (int i = 0; i < cellGroups->n; i++) {
     157
     158        psArray *cells = cellGroups->data[i];
     159
     160        for (int j = 0; j < cells->n; j++) {
     161
     162            // allocate a job -- if threads are not defined, this just runs the job
     163            psThreadJob *job = psThreadJobAlloc ("PSPHOT_SOURCE_STATS");
     164
     165            psArrayAdd(job->args, 1, cells->data[j]); // sources
     166
     167            PS_ARRAY_ADD_SCALAR(job->args, INNER,   PS_TYPE_F32);
     168            PS_ARRAY_ADD_SCALAR(job->args, MIN_SN,  PS_TYPE_F32);
     169            PS_ARRAY_ADD_SCALAR(job->args, RADIUS,  PS_TYPE_F32);
     170            PS_ARRAY_ADD_SCALAR(job->args, SIGMA,   PS_TYPE_F32);
     171
     172            PS_ARRAY_ADD_SCALAR(job->args, maskVal, PS_TYPE_IMAGE_MASK);
     173            PS_ARRAY_ADD_SCALAR(job->args, markVal, PS_TYPE_IMAGE_MASK);
     174
     175            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nmoments
     176            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nfail
     177            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nfaint
     178
     179            if (!psThreadJobAddPending(job)) {
     180                psError(PS_ERR_UNKNOWN, false, "Unable to launch thread job PSPHOT_SOURCE_STATS");
     181                psFree (job);
     182                psFree(detections->newSources);
     183                return false;
     184            }
     185            psFree(job);
     186        }
     187
     188        // wait for the threads to finish and manage results
     189        if (!psThreadPoolWait (false)) {
     190            psError(PS_ERR_UNKNOWN, false, "Failure in thread job PSPHOT_SOURCE_STATS");
     191            psFree(detections->newSources);
     192            return false;
     193        }
     194
     195        // we have only supplied one type of job, so we can assume the types here
     196        psThreadJob *job = NULL;
     197        while ((job = psThreadJobGetDone()) != NULL) {
     198            if (job->args->n < 1) {
     199                fprintf (stderr, "error with job\n");
     200            } else {
     201                psScalar *scalar = NULL;
     202                scalar = job->args->data[7];
     203                Nmoments += scalar->data.S32;
     204                scalar = job->args->data[8];
     205                Nfail += scalar->data.S32;
     206                scalar = job->args->data[9];
     207                Nfaint += scalar->data.S32;
     208            }
     209            psFree(job);
     210        }
     211    }
     212
     213    psFree (cellGroups);
     214
     215    psLogMsg ("psphot", PS_LOG_INFO, "%ld sources, %d moments, %d faint, %d failed: %f sec\n", sources->n, Nmoments, Nfaint, Nfail, psTimerMark ("psphot.stats"));
     216
     217    psphotVisualShowMoments (sources);
     218
     219    if (detections->allSources) {
     220        psphotMaskCosmicRayFootprintCheck(detections->allSources);
     221    }
     222    if (detections->newSources) {
     223        psphotMaskCosmicRayFootprintCheck(detections->newSources);
     224    }
     225
     226    return true;
     227}
     228
     229// this function is currently only called by psphotCheckExtSources
     230bool psphotSourceStatsUpdate (psArray *sources, pmConfig *config, pmReadout *readout) {
     231
     232    bool status = false;
     233
     234    psTimerStart ("psphot.stats");
     235
     236    // select the appropriate recipe information
     237    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     238    assert (recipe);
     239
     240    // determine the number of allowed threads
     241    int nThreads = psMetadataLookupS32(&status, config->arguments, "NTHREADS"); // Number of threads
     242    if (!status) {
     243        nThreads = 0;
     244    }
     245
     246    // determine properties (sky, moments) of initial sources
     247    float OUTER    = psMetadataLookupF32 (&status, recipe, "SKY_OUTER_RADIUS");
     248    if (!status) return false;
     249
     250    OUTER = PS_MAX(OUTER, 20.0); // XXX Guarantee that we can encompass the max moments radius
     251
     252    char *breakPt  = psMetadataLookupStr (&status, recipe, "BREAK_POINT");
     253    if (!status) return false;
     254
     255    for (int i = 0; i < sources->n; i++) {
     256
     257        pmSource *source = sources->data[i];
     258        if (!source->peak) continue; // XXX how can we have a peak-less source?
     259
     260        // allocate space for moments
     261        if (!source->moments) {
     262            source->moments = pmMomentsAlloc();
     263        }
     264
     265        // allocate image, weight, mask arrays for each peak (square of radius OUTER)
     266        pmSourceDefinePixels (source, readout, source->peak->x, source->peak->y, OUTER);
     267        source->peak->assigned = true;
    55268    }
    56269
     
    62275    }
    63276
     277    // XXX how else could we get the window size in?
     278    if (!psphotSetMomentsWindow(recipe, readout->analysis, sources)) {
     279        psError(PS_ERR_UNEXPECTED_NULL, false, "Failed to determine Moments Window!");
     280        return NULL;
     281    }
     282
    64283    // threaded measurement of the source magnitudes
    65284    int Nfail = 0;
     
    82301            psThreadJob *job = psThreadJobAlloc ("PSPHOT_SOURCE_STATS");
    83302
     303            // XXX: this must match the above
    84304            psArrayAdd(job->args, 1, cells->data[j]); // sources
    85305            psArrayAdd(job->args, 1, recipe);
     
    136356
    137357    psArray *sources                = job->args->data[0];
    138     psMetadata *recipe              = job->args->data[1];
    139 
    140     float INNER        = psMetadataLookupF32 (&status, recipe, "SKY_INNER_RADIUS");
    141     if (!status) return false;
    142     float MIN_SN       = psMetadataLookupF32 (&status, recipe, "MOMENTS_SN_MIN");
    143     if (!status) return false;
    144     float RADIUS       = psMetadataLookupF32 (&status, recipe, "PSF_MOMENTS_RADIUS");
    145     if (!status) return false;
    146     float MIN_PIXEL_SN = psMetadataLookupF32 (&status, recipe, "MOMENTS_MIN_PIXEL_SN");
    147     if (!status) return false;
    148     float SIGMA        = psMetadataLookupF32 (&status, recipe, "MOMENTS_GAUSS_SIGMA");
    149     if (!status) return false;
    150 
    151     // bit-masks to test for good/bad pixels
    152     psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT");
    153     assert (maskVal);
    154 
    155     // bit-mask to mark pixels not used in analysis
    156     psImageMaskType markVal = psMetadataLookupImageMask(&status, recipe, "MARK.PSPHOT");
    157     assert (markVal);
     358
     359    float INNER                     = PS_SCALAR_VALUE(job->args->data[1],F32);
     360    float MIN_SN                    = PS_SCALAR_VALUE(job->args->data[2],F32);
     361    float RADIUS                    = PS_SCALAR_VALUE(job->args->data[3],F32);
     362    float SIGMA                     = PS_SCALAR_VALUE(job->args->data[4],F32);
     363
     364    psImageMaskType maskVal         = PS_SCALAR_VALUE(job->args->data[5],PS_TYPE_IMAGE_MASK_DATA);
     365    psImageMaskType markVal         = PS_SCALAR_VALUE(job->args->data[6],PS_TYPE_IMAGE_MASK_DATA);
    158366
    159367    // maskVal is used to test for rejected pixels, and must include markVal
     
    166374    for (int i = 0; i < sources->n; i++) {
    167375        pmSource *source = sources->data[i];
     376
     377        if (source->tmpFlags & PM_SOURCE_TMPF_MOMENTS_MEASURED) continue;
     378        source->tmpFlags |= PM_SOURCE_TMPF_MOMENTS_MEASURED;
    168379
    169380        // skip faint sources for moments measurement
     
    194405        }
    195406
    196         // measure basic source moments
    197         status = pmSourceMoments (source, RADIUS, SIGMA, MIN_PIXEL_SN);
     407        // measure basic source moments (no S/N clipping on input pixels)
     408        status = pmSourceMoments (source, RADIUS, SIGMA, 0.0, maskVal);
    198409        if (status) {
    199410            Nmoments ++;
     
    205416        BIG_RADIUS = PS_MIN (INNER, 3*RADIUS);
    206417        psTrace ("psphot", 4, "retrying moments for %d, %d\n", source->peak->x, source->peak->y);
    207         status = pmSourceMoments (source, BIG_RADIUS, 3.0*SIGMA, MIN_PIXEL_SN);
     418        status = pmSourceMoments (source, BIG_RADIUS, 3.0*SIGMA, 0.0, maskVal);
    208419        if (status) {
    209420            source->mode |= PM_SOURCE_MODE_BIG_RADIUS;
     
    219430
    220431    // change the value of a scalar on the array (wrap this and put it in psArray.h)
    221     scalar = job->args->data[2];
     432    scalar = job->args->data[7];
    222433    scalar->data.S32 = Nmoments;
    223434
    224     scalar = job->args->data[3];
     435    scalar = job->args->data[8];
    225436    scalar->data.S32 = Nfail;
    226437
    227     scalar = job->args->data[4];
     438    scalar = job->args->data[9];
    228439    scalar->data.S32 = Nfaint;
    229440
     
    231442}
    232443
    233 # if (0)
    234 bool psphotSourceStats_Unthreaded (int *nfail, int *nmoments, psArray *sources, psMetadata *recipe) {
    235 
    236     bool status = false;
    237     float BIG_RADIUS;
    238 
    239     float INNER    = psMetadataLookupF32 (&status, recipe, "SKY_INNER_RADIUS");
    240     if (!status) return false;
    241     float MIN_SN   = psMetadataLookupF32 (&status, recipe, "MOMENTS_SN_MIN");
    242     if (!status) return false;
    243     float RADIUS   = psMetadataLookupF32 (&status, recipe, "PSF_MOMENTS_RADIUS");
    244     if (!status) return false;
    245 
    246     // bit-masks to test for good/bad pixels
    247     psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT");
    248     assert (maskVal);
    249 
    250     // bit-mask to mark pixels not used in analysis
    251     psImageMaskType markVal = psMetadataLookupImageMask(&status, recipe, "MARK.PSPHOT");
    252     assert (markVal);
    253 
    254     // maskVal is used to test for rejected pixels, and must include markVal
    255     maskVal |= markVal;
    256 
    257     // threaded measurement of the sources moments
    258     int Nfail = 0;
    259     int Nmoments = 0;
    260     for (int i = 0; i < sources->n; i++) {
    261         pmSource *source = sources->data[i];
    262 
    263         // skip faint sources for moments measurement
    264         if (source->peak->SN < MIN_SN) {
    265             continue;
    266         }
    267 
    268         // measure a local sky value
    269         // the local sky is now ignored; kept here for reference only
    270         status = pmSourceLocalSky (source, PS_STAT_SAMPLE_MEDIAN, INNER, maskVal, markVal);
    271         if (!status) {
    272             psErrorClear(); // XXX re-consider the errors raised here
    273             Nfail ++;
    274             continue;
    275         }
    276 
    277         // measure the local sky variance (needed if noise is not sqrt(signal))
    278         // XXX EAM : this should use ROBUST not SAMPLE median, but it is broken
    279         status = pmSourceLocalSkyVariance (source, PS_STAT_SAMPLE_MEDIAN, INNER, maskVal, markVal);
    280         if (!status) {
    281             Nfail ++;
    282             psErrorClear();
    283             continue;
    284         }
    285 
    286         // measure basic source moments
    287         status = pmSourceMoments (source, RADIUS, SIGMA, MIN_PIXEL_SN);
    288         if (status) {
    289             Nmoments ++;
    290             continue;
    291         }
    292 
    293         // if no valid pixels, or massive swing, likely saturated source,
    294         // try a much larger box
    295         BIG_RADIUS = PS_MIN (INNER, 3*RADIUS);
    296         psTrace ("psphot", 4, "retrying moments for %d, %d\n", source->peak->x, source->peak->y);
    297         status = pmSourceMoments (source, BIG_RADIUS, 3.0*SIGMA, MIN_PIXEL_SN);
    298         if (status) {
    299             Nmoments ++;
    300             continue;
    301         }
    302 
    303         Nfail ++;
    304         psErrorClear();
    305         continue;
    306     }
    307 
    308     // change the value of a scalar on the array (wrap this and put it in psArray.h)
    309     *nmoments = Nmoments;
    310     *nfail = Nfail;
    311 
     444// this function attempts to iteratively determine the best value for sigma of the moments weighting Gaussian
     445// this function modifies the recipe values MOMENTS_SX_MAX, MOMENTS_SY_MAX, and PSF_CLUMP_GRID_SCALE, used by pmSourcePSFClump
     446bool psphotSetMomentsWindow (psMetadata *recipe, psMetadata *analysis, psArray *sources) {
     447
     448    bool status;
     449
     450    float MIN_SN = psMetadataLookupF32 (&status, recipe, "MOMENTS_SN_MIN"); psAssert (status, "missing MOMENTS_SN_MIN");
     451    float PSF_SN_LIM = psMetadataLookupF32(&status, recipe, "PSF_SN_LIM"); psAssert (status, "missing PSF_SN_LIM");
     452    psF32 MOMENTS_AR_MAX = psMetadataLookupF32(&status, recipe, "MOMENTS_AR_MAX"); psAssert (status, "missing MOMENTS_AR_MAX");
     453
     454    // XXX move this to a config file?
     455    # define NSIGMA 8
     456    float sigma[NSIGMA] = {1.0, 2.0, 3.0, 4.5, 6.0, 9.0, 12.0, 18.0};
     457    float Sout[NSIGMA];
     458
     459    // this sorts by peak->SN
     460    sources = psArraySort (sources, pmSourceSortBySN);
     461
     462    // loop over radii:
     463    for (int i = 0; i < NSIGMA; i++) {
     464
     465        // XXX move max source number to config
     466        for (int j = 0; (j < sources->n) && (j < 400); j++) {
     467
     468            pmSource *source = sources->data[j];
     469            psAssert (source->moments, "force moments to exist");
     470            source->moments->nPixels = 0;
     471
     472            // skip faint sources for moments measurement
     473            if (source->peak->SN < MIN_SN) {
     474                continue;
     475            }
     476
     477            // measure basic source moments (no S/N clipping on input pixels)
     478            status = pmSourceMoments (source, 4*sigma[i], sigma[i], 0.0, 0xffff);
     479        }
     480
     481        // choose a grid scale that is a fixed fraction of the psf sigma^2
     482        float PSF_CLUMP_GRID_SCALE = 0.1*PS_SQR(sigma[i]);
     483        float MOMENTS_SX_MAX = 2.0*PS_SQR(sigma[i]);
     484        float MOMENTS_SY_MAX = 2.0*PS_SQR(sigma[i]);
     485
     486        // determine the PSF parameters from the source moment values
     487        pmPSFClump psfClump = pmSourcePSFClump (NULL, NULL, sources, PSF_SN_LIM, PSF_CLUMP_GRID_SCALE, MOMENTS_SX_MAX, MOMENTS_SY_MAX, MOMENTS_AR_MAX);
     488        psLogMsg ("psphot", 3, "radius %.1f, nStars: %d, nSigma: %5.2f, X,  Y: %f, %f (%f, %f)\n", sigma[i], psfClump.nStars, psfClump.nSigma, psfClump.X, psfClump.Y, sqrt(psfClump.X) / sigma[i], sqrt(psfClump.Y) / sigma[i]);
     489
     490        psMetadataAddS32 (analysis, PS_LIST_TAIL, "PSF.CLUMP.NREGIONS",  PS_META_REPLACE, "psf clump regions", 1);
     491        psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, "PSF.CLUMP.REGION.000");
     492        if (!regionMD) {
     493            regionMD = psMetadataAlloc();
     494            psMetadataAddMetadata (analysis, PS_LIST_TAIL, "PSF.CLUMP.REGION.000", PS_META_REPLACE, "psf clump region", regionMD);
     495            psFree (regionMD);
     496        }
     497        psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.X",  PS_META_REPLACE, "psf clump center", psfClump.X);
     498        psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.Y",  PS_META_REPLACE, "psf clump center", psfClump.Y);
     499        psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DX", PS_META_REPLACE, "psf clump center", psfClump.dX);
     500        psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DY", PS_META_REPLACE, "psf clump center", psfClump.dY);
     501
     502        psphotVisualPlotMoments (recipe, analysis, sources);
     503
     504        Sout[i] = sqrt(0.5*(psfClump.X + psfClump.Y)) / sigma[i];
     505    }
     506
     507    // we are looking for sigma for which Sout = 0.65 (or some other value)
     508    float Sigma = NAN;
     509    float minS = Sout[0];
     510    float maxS = Sout[0];
     511    for (int i = 0; i < NSIGMA; i++) {
     512        minS = PS_MIN(Sout[i], minS);
     513        maxS = PS_MAX(Sout[i], maxS);
     514    }
     515    if (minS > 0.65) Sigma = sigma[NSIGMA-1];
     516    if (maxS < 0.65) Sigma = sigma[0];
     517
     518    for (int i = 0; i < NSIGMA - 1 && isnan(Sigma); i++) {
     519        if (!isfinite(Sout[i]) || !isfinite(Sout[i+1])) continue;
     520        if ((Sout[i] > 0.65) && (Sout[i+1] > 0.65)) continue;
     521        if ((Sout[i] < 0.65) && (Sout[i+1] < 0.65)) continue;
     522        Sigma = sigma[i] + (0.65 - Sout[i])*(sigma[i+1] - sigma[i])/(Sout[i+1] - Sout[i]);
     523    }
     524    psAssert (isfinite(Sigma), "did we miss a case?");
     525
     526    // choose a grid scale that is a fixed fraction of the psf sigma^2
     527    psMetadataAddF32(analysis, PS_LIST_TAIL, "PSF_CLUMP_GRID_SCALE", PS_META_REPLACE, "clump grid", 0.1*PS_SQR(Sigma));
     528    psMetadataAddF32(analysis, PS_LIST_TAIL, "MOMENTS_SX_MAX", PS_META_REPLACE, "moments limit", 2.0*PS_SQR(Sigma));
     529    psMetadataAddF32(analysis, PS_LIST_TAIL, "MOMENTS_SY_MAX", PS_META_REPLACE, "moments limit", 2.0*PS_SQR(Sigma));
     530    psMetadataAddF32(analysis, PS_LIST_TAIL, "MOMENTS_GAUSS_SIGMA", PS_META_REPLACE, "moments limit", Sigma);
     531    psMetadataAddF32(analysis, PS_LIST_TAIL, "PSF_MOMENTS_RADIUS", PS_META_REPLACE, "moments limit", 4.0*Sigma);
     532
     533    psLogMsg ("psphot", 3, "using window function with sigma = %f\n", Sigma);
    312534    return true;
    313535}
    314 # endif
     536
     537// if we use the footprints, the output peaks list contains both old and new peaks,
     538// otherwise it only contains the new peaks.
     539
Note: See TracChangeset for help on using the changeset viewer.