IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

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

updates from trunk

Location:
branches/tap_branches
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/tap_branches

  • branches/tap_branches/psastro/src/psastroZeroPoint.c

    r24649 r27838  
    11/** @file psastroMosaicZeroPoint.c
    22 *
    3  *  @brief 
     3 *  @brief
    44 *
    55 *  @ingroup libpsastro
     
    1515bool psastroZeroPoint (pmConfig *config) {
    1616
     17    bool status;
    1718    float zeropt, exptime;
    1819    pmChip *chip = NULL;
     
    2324    psMetadata *recipe  = psMetadataLookupPtr (NULL, config->recipes, PSASTRO_RECIPE);
    2425    if (!recipe) {
    25         psError(PSASTRO_ERR_CONFIG, false, "Can't find PSASTRO recipe!\n");
    26         return false;
    27     }
     26        psError(PSASTRO_ERR_CONFIG, false, "Can't find PSASTRO recipe!\n");
     27        return false;
     28    }
     29
     30    // recipe options
     31    bool byExposure = psMetadataLookupBool (&status, recipe, "ZERO.POINT.BY.EXPOSURE");
    2832
    2933    // select the input data sources
    3034    pmFPAfile *input = psMetadataLookupPtr (NULL, config->files, "PSASTRO.INPUT");
    3135    if (!input) {
    32         psError(PSASTRO_ERR_CONFIG, false, "Can't find input data!\n");
    33         return false;
     36        psError(PSASTRO_ERR_CONFIG, false, "Can't find input data!\n");
     37        return false;
    3438    }
    3539    pmFPA *fpa = input->fpa;
     
    3943    // given the existing per-chip astrometry, determine matches between raw and ref stars
    4044    // is this needed? yes, if we didn't do SingleChip astrometry first
    41     if (!psastroMosaicSetMatch (fpa, recipe, 0)) {
    42         psError(PSASTRO_ERR_UNKNOWN, false, "failed to match raw and ref stars for mosaic");
    43         return false;
    44     }
     45    // if (!psastroMosaicSetMatch (fpa, recipe, 0)) {
     46    //     psError(PSASTRO_ERR_UNKNOWN, false, "failed to match raw and ref stars for mosaic");
     47    //     return false;
     48    // }
    4549
    4650    // XXX eventually: look up the photcode info from the recipe, use the ZEROPT and A_0 terms
     
    5155    // really error-out here?  or just skip?
    5256    if (!psastroZeroPointFromRecipe (&zeropt, &exptime, NULL, fpa, recipe)) {
    53         psLogMsg ("psastro", PS_LOG_INFO, "failed to load zeropt data from recipe");
    54         return false;
    55     }
     57        psLogMsg ("psastro", PS_LOG_INFO, "failed to load zeropt data from recipe");
     58        return false;
     59    }
     60
     61    // if we measure the zero point by exposure, accumulate the dMag values here:
     62    psVector *dMag = NULL;
     63
     64    float fpaZP = 0.0;                  // Average zero point
     65    int numZP = 0.0;                    // Number of measurements
    5666
    5767    // this loop selects the matched stars for all chips
     68    // XXX optionally measure zero point for entire exposure in a single statistic
    5869    while ((chip = pmFPAviewNextChip (view, fpa, 1)) != NULL) {
    5970        psTrace ("psastro", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
    6071        if (!chip->process || !chip->file_exists) { continue; }
    61         if (!chip->toFPA) { continue; }
    62 
    63         while ((cell = pmFPAviewNextCell (view, fpa, 1)) != NULL) {
     72
     73        while ((cell = pmFPAviewNextCell (view, fpa, 1)) != NULL) {
    6474            psTrace ("psastro", 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
    6575            if (!cell->process || !cell->file_exists) { continue; }
    6676
    67             // process each of the readouts
    68             // XXX there can only be one readout per chip, right?
    69             while ((readout = pmFPAviewNextReadout (view, fpa, 1)) != NULL) {
    70                 if (! readout->data_exists) { continue; }
    71 
    72                 // calculate dMag for the matched stars
    73                 psastroZeroPointReadout (readout, zeropt, exptime);
    74 
    75             }
    76         }
    77     }
     77            // process each of the readouts
     78            // XXX there can only be one readout per chip, right?
     79            while ((readout = pmFPAviewNextReadout (view, fpa, 1)) != NULL) {
     80                if (! readout->data_exists) { continue; }
     81
     82                // calculate dMag for the matched stars
     83                dMag = psastroZeroPointReadoutAccum (dMag, readout, exptime);
     84
     85                if (!byExposure) {
     86                    // calculate dMag for the matched stars just for this readout (well, chip)
     87                    psMetadata *header = psMetadataLookupMetadata (&status, readout->analysis, "PSASTRO.HEADER");
     88                    psastroZeroPointAnalysis (header, dMag, zeropt, recipe);
     89                    psFree (dMag);
     90                    dMag = NULL;
     91
     92                    float zp = psMetadataLookupF32(NULL, header, "ZPT_OBS");
     93                    if (isfinite(zp)) {
     94                        fpaZP += zp;
     95                        numZP++;
     96                    }
     97
     98
     99                }
     100            }
     101        }
     102    }
     103
     104    if (byExposure) {
     105        psMetadata *header = psMetadataLookupMetadata (&status, fpa->analysis, "PSASTRO.HEADER");
     106        if (!header) {
     107            header = psMetadataAlloc ();
     108            psMetadataAddMetadata (fpa->analysis, PS_LIST_TAIL, "PSASTRO.HEADER",  PS_META_REPLACE, "psastro header stats", header);
     109            psFree (header);
     110        }
     111        psastroZeroPointAnalysis (header, dMag, zeropt, recipe);
     112        psFree (dMag);
     113        dMag = NULL;
     114
     115        float zptObs = psMetadataLookupF32 (&status, header, "ZPT_OBS");
     116        float zptRef = psMetadataLookupF32 (&status, header, "ZPT_REF");
     117        float zptErr = psMetadataLookupF32 (&status, header, "ZPT_ERR");
     118        float zptOff = psMetadataLookupF32 (&status, header, "ZPT_OFF");
     119
     120        fpaZP = zptObs;
     121        numZP = 1;
     122
     123        // copy the zero point metadata from the fpa header to the chip headers
     124        for (int i = 0; i < fpa->chips->n; i++) {
     125            pmChip *chip = fpa->chips->data[i];
     126            if (!chip) continue;
     127            if (!chip->process) continue;
     128            if (!chip->file_exists) continue;
     129
     130            for (int j = 0; j < chip->cells->n; j++) {
     131                pmCell *cell = chip->cells->data[j];
     132                if (!cell) continue;
     133                if (!cell->process) continue;
     134                if (!cell->file_exists) continue;
     135
     136                for (int k = 0; k < cell->readouts->n; k++) {
     137                    pmReadout *readout = cell->readouts->data[k];
     138                    if (!readout) continue;
     139                    if (!readout->data_exists) continue;
     140
     141                    // calculate dMag for the matched stars just for this readout (well, chip)
     142                    psMetadata *header = psMetadataLookupMetadata (&status, readout->analysis, "PSASTRO.HEADER");
     143
     144                    psMetadataAddF32 (header, PS_LIST_TAIL, "ZPT_OBS", PS_META_REPLACE, "measured zero point",  zptObs);
     145                    psMetadataAddF32 (header, PS_LIST_TAIL, "ZPT_REF", PS_META_REPLACE, "reference zero point", zptRef);
     146                    psMetadataAddF32 (header, PS_LIST_TAIL, "ZPT_ERR", PS_META_REPLACE, "error on zero point",  zptErr);
     147                    psMetadataAddF32 (header, PS_LIST_TAIL, "ZPT_OFF", PS_META_REPLACE, "zero point offset",    zptOff);
     148                }
     149            }
     150        }
     151    }
     152
     153
     154    psMetadataItem *item = psMetadataLookup(fpa->concepts, "FPA.ZP");
     155    item->data.F32 = fpaZP / (float)numZP;
    78156
    79157    psFree (view);
     
    82160
    83161/**
    84  * we measure <dMag> and \sigma_dMag and write them to the header
     162 * accumulate the dMag values from this readout
    85163 */
    86 bool psastroZeroPointReadout(pmReadout *readout, float zeropt, float exptime) {
     164psVector *psastroZeroPointReadoutAccum(psVector *dMag, pmReadout *readout, float exptime) {
    87165
    88166    bool status;
    89167
    90168    // select the raw objects for this readout
    91     psArray *rawstars = psMetadataLookupPtr (&status, readout->analysis, "PSASTRO.RAWSTARS");
    92     if (rawstars == NULL) return false;
     169    psArray *rawstars = psMetadataLookupPtr (&status, readout->analysis, "PSASTRO.RAWSTARS.SUBSET");
     170    if (rawstars == NULL) return dMag;
    93171
    94172    // select the raw objects for this readout
    95     psArray *refstars = psMetadataLookupPtr (&status, readout->analysis, "PSASTRO.REFSTARS");
    96     if (refstars == NULL) return false;
     173    psArray *refstars = psMetadataLookupPtr (&status, readout->analysis, "PSASTRO.REFSTARS.SUBSET");
     174    if (refstars == NULL) return dMag;
    97175
    98176    psArray *matches = psMetadataLookupPtr (&status, readout->analysis, "PSASTRO.MATCH");
    99     if (matches == NULL) return false;
    100 
    101     psVector *dMag  = psVectorAllocEmpty (100, PS_TYPE_F32);
    102 
    103     int Npts = 0;
     177    if (matches == NULL) return dMag;
     178
     179    if (!dMag) {
     180        dMag  = psVectorAllocEmpty (100, PS_TYPE_F32);
     181    }
     182
    104183    for (int i = 0; i < matches->n; i++) {
    105184
     
    110189      pmAstromObj *ref = refstars->data[match->ref];
    111190
    112       dMag->data.F32[Npts] = ref->Mag - raw->Mag - 2.5*log10(exptime);
    113       psVectorExtend (dMag, 100, 1);
    114       Npts++;
    115     }
    116 
    117     psTrace ("psModules.astrom", 4, "Npts: %d\n", Npts);
    118 
    119     if (Npts < 3) {
     191      float value = ref->Mag - raw->Mag - 2.5*log10(exptime);
     192      psVectorAppend (dMag, value);
     193    }
     194    return dMag;
     195}
     196
     197bool psastroZeroPointAnalysis (psMetadata *header, psVector *dMag, float zeropt, psMetadata *recipe) {
     198
     199    // XXX make this depend on the mode?
     200    if (!dMag || dMag->n < 3) {
    120201      fprintf (stderr, "zero point NaN +/- NaN\n");
    121       psFree (dMag);
    122202      return false;
    123203    }
    124204
    125     // stats structure and mask for use in measuring the clipping statistic
    126     // this analysis has too few data points to use the robust median method
    127     psStats *stats = psStatsAlloc (PS_STAT_CLIPPED_MEAN | PS_STAT_CLIPPED_STDEV);
    128     if (!psVectorStats (stats, dMag, NULL, NULL, 0)) {
    129         psError(PS_ERR_UNKNOWN, false, "failure to measure stats");
    130         return false;
    131     }
    132     fprintf (stderr, "zero point %f +/- %f using %d stars; transparency %f\n", stats->clippedMean, stats->clippedStdev, Npts, zeropt - stats->clippedMean);
    133 
    134     psMetadata *header = psMetadataLookupMetadata (&status, readout->analysis, "PSASTRO.HEADER");
     205    bool status;
     206    bool useMean = psMetadataLookupBool (&status, recipe, "ZERO.POINT.USE.MEAN");
     207
     208    // the zero point analysis depends on the type of desired statistic.  For comparisons
     209    // against a high-quality reference catalog with a good match to the actual filter used, it
     210    // is best to use a standard clipped mean or global mean statistic.  If the reference
     211    // catalog has some unmodeled extra parameter, as is the case for the synthetic grizy
     212    // database vs PS1, then it is best to use some consistent feature in the color
     213    // distribution.
     214
     215    psStats *stats = NULL;
     216    if (useMean) {
     217        // stats structure and mask for use in measuring the clipping statistic
     218        // this analysis has too few data points to use the robust median method
     219        stats = psStatsAlloc (PS_STAT_CLIPPED_MEAN | PS_STAT_CLIPPED_STDEV);
     220        if (!psVectorStats (stats, dMag, NULL, NULL, 0)) {
     221            psError(PS_ERR_UNKNOWN, false, "failure to measure zero point by mean");
     222            return false;
     223        }
     224    } else {
     225        stats = psastroStatsPercentile (dMag, recipe);
     226        if (!stats) {
     227            psError(PS_ERR_UNKNOWN, false, "failure to measure zero point by edge");
     228            return false;
     229        }
     230    }
     231    fprintf (stderr, "zero point %f +/- %f using %ld stars; transparency %f\n", stats->clippedMean, stats->clippedStdev, dMag->n, zeropt - stats->clippedMean);
    135232
    136233    psMetadataAddF32 (header, PS_LIST_TAIL, "ZPT_OBS", PS_META_REPLACE, "measured zero point", stats->clippedMean);
    137     psMetadataAddF32 (header, PS_LIST_TAIL, "ZPT_REF", PS_META_REPLACE, "measured zero point", zeropt);
    138     psMetadataAddF32 (header, PS_LIST_TAIL, "ZPT_ERR", PS_META_REPLACE, "measured zero point", stats->clippedStdev);
    139     psMetadataAddF32 (header, PS_LIST_TAIL, "ZPT_OFF", PS_META_REPLACE, "measured zero point", zeropt - stats->clippedMean);
    140 
    141     psFree (dMag);
     234    psMetadataAddF32 (header, PS_LIST_TAIL, "ZPT_REF", PS_META_REPLACE, "reference zero point", zeropt);
     235    psMetadataAddF32 (header, PS_LIST_TAIL, "ZPT_ERR", PS_META_REPLACE, "error on zero point",  stats->clippedStdev);
     236    psMetadataAddF32 (header, PS_LIST_TAIL, "ZPT_OFF", PS_META_REPLACE, "zero point offset",    zeropt - stats->clippedMean);
     237
    142238    psFree (stats);
    143239    return true;
     240}
     241
     242#define MAG_RESOLUTION 0.0002
     243
     244// set the bin closest to the corresponding value.  if USE_END is +/- 1,
     245// out-of-range saturates on lower/upper bin REGARDLESS of actual value
     246#define PS_BIN_FOR_VALUE(RESULT, VECTOR, VALUE, USE_END) { \
     247        psVectorBinaryDisectResult result; \
     248        psScalar tmpScalar; \
     249        tmpScalar.type.type = PS_TYPE_F32; \
     250        tmpScalar.data.F32 = (VALUE); \
     251        RESULT = psVectorBinaryDisect (&result, VECTOR, &tmpScalar); \
     252        switch (result) { \
     253          case PS_BINARY_DISECT_PASS: \
     254            break; \
     255          case PS_BINARY_DISECT_OUTSIDE_RANGE: \
     256            psTrace("psastro", 6, "selected bin outside range"); \
     257            if (USE_END == -1) { RESULT = 0; } \
     258            if (USE_END == +1) { RESULT = VECTOR->n - 1; } \
     259            break; \
     260          case PS_BINARY_DISECT_INVALID_INPUT: \
     261          case PS_BINARY_DISECT_INVALID_TYPE: \
     262            psAbort ("programming error"); \
     263            break; \
     264        } }
     265
     266# define PS_BIN_INTERPOLATE(RESULT, VECTOR, BOUNDS, BIN, VALUE) { \
     267        float dX, dY, Xo, Yo, Xt; \
     268        if (BIN == BOUNDS->n - 1) { \
     269            dX = 0.5*(BOUNDS->data.F32[BIN+1] - BOUNDS->data.F32[BIN-1]); \
     270            dY = VECTOR->data.F32[BIN] - VECTOR->data.F32[BIN-1]; \
     271            Xo = 0.5*(BOUNDS->data.F32[BIN+1] + BOUNDS->data.F32[BIN]); \
     272            Yo = VECTOR->data.F32[BIN]; \
     273        } else { \
     274            dX = 0.5*(BOUNDS->data.F32[BIN+2] - BOUNDS->data.F32[BIN]); \
     275            dY = VECTOR->data.F32[BIN+1] - VECTOR->data.F32[BIN]; \
     276            Xo = 0.5*(BOUNDS->data.F32[BIN+1] + BOUNDS->data.F32[BIN]); \
     277            Yo = VECTOR->data.F32[BIN]; \
     278        } \
     279        if (dY != 0) { \
     280            Xt = (VALUE - Yo)*dX/dY + Xo; \
     281        } else { \
     282            Xt = Xo; \
     283        } \
     284        Xt = PS_MIN (BOUNDS->data.F32[BIN+1], PS_MAX(BOUNDS->data.F32[BIN], Xt)); \
     285        psTrace("psastro", 6, "(Xo, Yo, dX, dY, Xt, Yt) is (%.2f %.2f %.2f %.2f %.2f %.2f)\n", \
     286                Xo, Yo, dX, dY, Xt, VALUE); \
     287        RESULT = Xt; }
     288
     289// measure the edge of the sample at flimit
     290// return results in stats->sampleMean, sampleStdev
     291// XXX this is a misuse of psStats -- make our own structure?
     292psStats *psastroStatsPercentile (psVector *myVector, psMetadata *recipe) {
     293
     294    // search for the 'blue' edge of the dMag distribution:
     295    // the distribution is not a normal population, but instead has a broad range with fairly hard edges.
     296    // construct a histogram and look for the
     297
     298    bool status;
     299    float edgeFraction = psMetadataLookupF32 (&status, recipe, "ZERO.POINT.EDGE.FRACTION");
     300    int edgeSample = psMetadataLookupS32 (&status, recipe, "ZERO.POINT.EDGE.SAMPLE");
     301    float edgeSampleFraction = psMetadataLookupF32 (&status, recipe, "ZERO.POINT.EDGE.SAMPLE.FRACTION");
     302
     303    // stats is first used to find the data range
     304    psStats *stats = psStatsAlloc(PS_STAT_MIN | PS_STAT_MAX); // Statistics for min and max
     305    psHistogram *histogram = NULL;      // Histogram of the data
     306    psHistogram *cumulative = NULL;     // Cumulative histogram of the data
     307    float min = NAN, max = NAN;         // Mimimum and maximum values
     308
     309    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS);
     310
     311    // Get the minimum and maximum values
     312    if (!psVectorStats(stats, myVector, NULL, NULL, 0)) goto escape;
     313    min = stats->min;
     314    max = stats->max;
     315    if (isnan(min) || isnan(max)) goto escape;
     316    psTrace("psastro", 5, "Data min/max is (%.2f, %.2f)\n", min, max);
     317
     318    // If all data points have the same value, then we set the appropriate members of stats and return.
     319    if (fabs(max - min) <= FLT_EPSILON) {
     320        stats->clippedMean = min;
     321        stats->clippedStdev = NAN;
     322        stats->results |= PS_STAT_CLIPPED_MEAN;
     323        stats->results |= PS_STAT_CLIPPED_STDEV;
     324        return stats;
     325    }
     326
     327    // Define the histogram bin size.
     328    float binSize = MAG_RESOLUTION;
     329    long numBins = (max - min) / binSize; // Number of bins
     330    psTrace("psastro", 5, "Numbins is %ld\n", numBins);
     331    psTrace("psastro", 5, "Creating a robust histogram from data range (%.2f - %.2f)\n", min, max);
     332
     333    // allocate the histogram containers
     334    histogram = psHistogramAlloc(min, max, numBins);
     335    cumulative = psHistogramAlloc(min, max, numBins);
     336
     337    // find the mean value:
     338    stats->clippedMean = psastroStatsPercentileValue (histogram, cumulative, myVector, edgeFraction);
     339
     340    int nSubset = myVector->n * edgeSampleFraction;
     341    psVector *subset = psVectorAlloc (nSubset, PS_TYPE_F32);
     342
     343    float Sum = 0.0;
     344    float S2 = 0.0;
     345    for (int i = 0; i < edgeSample; i++) {
     346
     347        // generate the subset vector
     348        for (long i = 0; i < nSubset; i++) {
     349            double frnd = psRandomUniform(rng);
     350            int entry = PS_MIN(myVector->n - 1, PS_MAX(0, myVector->n * frnd));
     351
     352            subset->data.F32[i] = myVector->data.F32[entry];
     353        }
     354
     355        float value = psastroStatsPercentileValue (histogram, cumulative, subset, edgeFraction);
     356
     357        Sum += value;
     358        S2 += value*value;
     359    }
     360    psTrace("psastro", 6, "subset stats: Sum: %f, S2: %f, Npts: %d\n", Sum, S2, edgeSample);
     361
     362    stats->clippedStdev = PS_MAX (sqrt(S2 / edgeSample - PS_SQR(Sum/edgeSample)), MAG_RESOLUTION);
     363    psTrace("psastro", 5, "percentile stats %f +/- %f\n", stats->clippedMean, stats->clippedStdev);
     364
     365    stats->results |= PS_STAT_CLIPPED_MEAN;
     366    stats->results |= PS_STAT_CLIPPED_STDEV;
     367    stats->options = PS_STAT_CLIPPED_MEAN | PS_STAT_CLIPPED_STDEV;
     368
     369    // Clean up
     370    psFree(histogram);
     371    psFree(cumulative);
     372    psFree(subset);
     373    psFree(rng);
     374    return stats;
     375
     376escape:
     377    stats->clippedMean = NAN;
     378    stats->clippedStdev = NAN;
     379    stats->results |= PS_STAT_CLIPPED_MEAN;
     380    stats->results |= PS_STAT_CLIPPED_STDEV;
     381    stats->options = PS_STAT_CLIPPED_MEAN | PS_STAT_CLIPPED_STDEV;
     382
     383    psFree(histogram);
     384    psFree(cumulative);
     385
     386    return stats;
     387}
     388
     389
     390// measure the edge of the sample at flimit
     391// return results in stats->sampleMean, sampleStdev
     392// XXX this is a misuse of psStats -- make our own structure?
     393float psastroStatsPercentileValue (psHistogram *histogram, psHistogram *cumulative, psVector *myVector, float flimit) {
     394
     395    // need to initialize the histogram on each pass
     396    psVectorInit (histogram->nums, 0);
     397    if (!psVectorHistogram(histogram, myVector, NULL, NULL, 0)) {
     398        // if psVectorHistogram returns false, we have a programming error
     399        psAbort ("Unable to generate histogram for psastroZeroPointAnalysis");
     400    }
     401    if (psTraceGetLevel("psastro") >= 8) {
     402        PS_VECTOR_PRINT_F32(histogram->bounds);
     403        PS_VECTOR_PRINT_F32(histogram->nums);
     404    }
     405
     406    // Convert the specific histogram to a cumulative histogram
     407    // The cumulative histogram data points correspond to the UPPER bound value (N < Bin[i+1])
     408    cumulative->nums->data.F32[0] = histogram->nums->data.F32[0];
     409    for (long i = 1; i < histogram->nums->n; i++) {
     410        cumulative->nums->data.F32[i] = cumulative->nums->data.F32[i-1] + histogram->nums->data.F32[i];
     411        cumulative->bounds->data.F32[i-1] = histogram->bounds->data.F32[i];
     412    }
     413    if (psTraceGetLevel("psastro") >= 8) {
     414        PS_VECTOR_PRINT_F32(cumulative->bounds);
     415        PS_VECTOR_PRINT_F32(cumulative->nums);
     416    }
     417
     418    // Find the bin which contains the first data point above the limit
     419    long numBins = cumulative->nums->n;
     420    long totalDataPoints = cumulative->nums->data.F32[numBins - 1];
     421    psTrace("psastro", 6, "Total data points is %ld\n", totalDataPoints);
     422
     423    // find bin which is the lower bound of the limit value (value[bin] < f < value[bin+1]
     424    long bin;
     425    PS_BIN_FOR_VALUE(bin, cumulative->nums, flimit * totalDataPoints, 0);
     426    psTrace("psastro", 6, "The bin is %ld (%.4f to %.4f)\n", bin, cumulative->bounds->data.F32[bin], cumulative->bounds->data.F32[bin+1]);
     427
     428    // Linear interpolation to the limit value in bin units
     429    float value;
     430    PS_BIN_INTERPOLATE (value, cumulative->nums, cumulative->bounds, bin, totalDataPoints * flimit);
     431    psTrace("psastro", 6, "limit value is %f\n", value);
     432
     433    return value;
    144434}
    145435
     
    164454    if (item->type != PS_DATA_METADATA_MULTI) ESCAPE ("PHOTCODE.DATA not a multi");
    165455
    166     // PHOTCODE.DATA is a multi of metadata items 
     456    // PHOTCODE.DATA is a multi of metadata items
    167457    psListIterator *iter = psListIteratorAlloc(item->data.list, PS_LIST_HEAD, false);
    168458
    169459    psMetadataItem *refItem = NULL;
    170460    while ((refItem = psListGetAndIncrement (iter))) {
    171         if (refItem->type != PS_DATA_METADATA) ESCAPE ("PHOTCODE.DATA entry is not a metadata folder");
    172    
    173         char *refFilter = psMetadataLookupStr (&status, refItem->data.md, "FILTER");
    174         if (!status) {
    175             // psLogMsg ("psastro", PS_LOG_INFO, "a PHOTCODE.DATA recipe folder is missing FILTER");
    176             continue;
    177         }
    178 
    179         // does this entry match the current filter?
    180         if (strcmp (refFilter, filter)) continue;
    181 
    182         psLogMsg ("psastro", PS_LOG_DETAIL, "PHOTCODE.DATA found for filter %s", filter);
    183 
    184         *zeropt = psMetadataLookupF32 (&status, refItem->data.md, "ZEROPT");
    185         if (!status) {
    186             psLogMsg ("psastro", PS_LOG_INFO, "a PHOTCODE.DATA recipe folder is missing ZEROPT");
    187             continue;
    188         }
    189         if (ghostMaxMag) {
    190             *ghostMaxMag = psMetadataLookupF32 (&status, refItem->data.md, "GHOST_MAX_MAG");
    191             if (!status) {
    192                 psLogMsg ("psastro", PS_LOG_INFO, "a PHOTCODE.DATA recipe folder is missing GHOST_MAX_MAG");
    193                 continue;
    194             }
    195         }
    196         psFree (iter);
    197         return true;
     461        if (refItem->type != PS_DATA_METADATA) ESCAPE ("PHOTCODE.DATA entry is not a metadata folder");
     462
     463        char *refFilter = psMetadataLookupStr (&status, refItem->data.md, "FILTER");
     464        if (!status) {
     465            // psLogMsg ("psastro", PS_LOG_INFO, "a PHOTCODE.DATA recipe folder is missing FILTER");
     466            continue;
     467        }
     468
     469        // does this entry match the current filter?
     470        if (strcmp (refFilter, filter)) continue;
     471
     472        psLogMsg ("psastro", PS_LOG_DETAIL, "PHOTCODE.DATA found for filter %s", filter);
     473
     474        *zeropt = psMetadataLookupF32 (&status, refItem->data.md, "ZEROPT");
     475        if (!status) {
     476            psLogMsg ("psastro", PS_LOG_INFO, "a PHOTCODE.DATA recipe folder is missing ZEROPT");
     477            continue;
     478        }
     479        if (ghostMaxMag) {
     480            *ghostMaxMag = psMetadataLookupF32 (&status, refItem->data.md, "GHOST_MAX_MAG");
     481            if (!status) {
     482                psLogMsg ("psastro", PS_LOG_INFO, "a PHOTCODE.DATA recipe folder is missing GHOST_MAX_MAG");
     483                continue;
     484            }
     485        }
     486        psFree (iter);
     487        return true;
    198488    }
    199489    psFree (iter);
Note: See TracChangeset for help on using the changeset viewer.