IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 25407


Ignore:
Timestamp:
Sep 15, 2009, 4:03:13 PM (17 years ago)
Author:
eugene
Message:

updates from trunk

Location:
branches/eam_branches/20090715/psModules/src
Files:
26 edited
2 copied

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/20090715/psModules/src/astrom/pmAstrometryWCS.c

    r24052 r25407  
    289289    // test the CDELTi varient
    290290    if (pcKeys) {
     291        wcs->wcsCDkeys = 0;
    291292        wcs->cdelt1 = psMetadataLookupF64 (&status, header, "CDELT1");
    292293        wcs->cdelt2 = psMetadataLookupF64 (&status, header, "CDELT2");
     
    334335    // test the CDi_j varient
    335336    if (cdKeys) {
     337        wcs->wcsCDkeys = 1;
     338
    336339        wcs->trans->x->coeff[1][0] = psMetadataLookupF64 (&status, header, "CD1_1"); // == PC1_1
    337340        wcs->trans->x->coeff[0][1] = psMetadataLookupF64 (&status, header, "CD1_2"); // == PC1_2
     
    375378    // XXX make it optional to write out CDi_j terms, or other versions
    376379    // apply CDELT1,2 (degrees / pixel) to yield PCi,j terms of order unity
    377     double cdelt1 = wcs->cdelt1;
    378     double cdelt2 = wcs->cdelt2;
    379     psMetadataAddF64 (header, PS_LIST_TAIL, "CDELT1", PS_META_REPLACE, "", cdelt1);
    380     psMetadataAddF64 (header, PS_LIST_TAIL, "CDELT2", PS_META_REPLACE, "", cdelt2);
    381 
    382     // test the PC00i00j varient:
    383     psMetadataAddF64 (header, PS_LIST_TAIL, "PC001001", PS_META_REPLACE, "", wcs->trans->x->coeff[1][0] / cdelt1); // == PC1_1
    384     psMetadataAddF64 (header, PS_LIST_TAIL, "PC001002", PS_META_REPLACE, "", wcs->trans->x->coeff[0][1] / cdelt2); // == PC1_2
    385     psMetadataAddF64 (header, PS_LIST_TAIL, "PC002001", PS_META_REPLACE, "", wcs->trans->y->coeff[1][0] / cdelt1); // == PC2_1
    386     psMetadataAddF64 (header, PS_LIST_TAIL, "PC002002", PS_META_REPLACE, "", wcs->trans->y->coeff[0][1] / cdelt2); // == PC2_2
    387 
    388     // Elixir-style polynomial terms
    389     // XXX currently, Elixir/DVO cannot accept mixed orders
    390     // XXX need to respect the masks
    391     // XXX is wcs->cdelt1,2 always consistent?
    392     int fitOrder = wcs->trans->x->nX;
    393     if (fitOrder > 1) {
     380    if (!(wcs->wcsCDkeys)) {
     381
     382      double cdelt1 = wcs->cdelt1;
     383      double cdelt2 = wcs->cdelt2;
     384      psMetadataAddF64 (header, PS_LIST_TAIL, "CDELT1", PS_META_REPLACE, "", cdelt1);
     385      psMetadataAddF64 (header, PS_LIST_TAIL, "CDELT2", PS_META_REPLACE, "", cdelt2);
     386     
     387      // test the PC00i00j varient:
     388      psMetadataAddF64 (header, PS_LIST_TAIL, "PC001001", PS_META_REPLACE, "", wcs->trans->x->coeff[1][0] / cdelt1); // == PC1_1
     389      psMetadataAddF64 (header, PS_LIST_TAIL, "PC001002", PS_META_REPLACE, "", wcs->trans->x->coeff[0][1] / cdelt2); // == PC1_2
     390      psMetadataAddF64 (header, PS_LIST_TAIL, "PC002001", PS_META_REPLACE, "", wcs->trans->y->coeff[1][0] / cdelt1); // == PC2_1
     391      psMetadataAddF64 (header, PS_LIST_TAIL, "PC002002", PS_META_REPLACE, "", wcs->trans->y->coeff[0][1] / cdelt2); // == PC2_2
     392     
     393      // Elixir-style polynomial terms
     394      // XXX currently, Elixir/DVO cannot accept mixed orders
     395      // XXX need to respect the masks
     396      // XXX is wcs->cdelt1,2 always consistent?
     397      int fitOrder = wcs->trans->x->nX;
     398      if (fitOrder > 1) {
    394399        for (int i = 0; i <= fitOrder; i++) {
    395             for (int j = 0; j <= fitOrder; j++) {
    396                 if (i + j < 2)
    397                     continue;
    398                 if (i + j > fitOrder)
    399                     continue;
    400                 sprintf (name, "PCA1X%1dY%1d", i, j);
    401                 psMetadataAddF64 (header, PS_LIST_TAIL, name, PS_META_REPLACE, "", wcs->trans->x->coeff[i][j] / pow(cdelt1, i) / pow(cdelt2, j));
    402                 sprintf (name, "PCA2X%1dY%1d", i, j);
    403                 psMetadataAddF64 (header, PS_LIST_TAIL, name, PS_META_REPLACE, "", wcs->trans->y->coeff[i][j] / pow(cdelt1, i) / pow(cdelt2, j));
    404             }
     400          for (int j = 0; j <= fitOrder; j++) {
     401            if (i + j < 2)
     402              continue;
     403            if (i + j > fitOrder)
     404              continue;
     405            sprintf (name, "PCA1X%1dY%1d", i, j);
     406            psMetadataAddF64 (header, PS_LIST_TAIL, name, PS_META_REPLACE, "", wcs->trans->x->coeff[i][j] / pow(cdelt1, i) / pow(cdelt2, j));
     407            sprintf (name, "PCA2X%1dY%1d", i, j);
     408            psMetadataAddF64 (header, PS_LIST_TAIL, name, PS_META_REPLACE, "", wcs->trans->y->coeff[i][j] / pow(cdelt1, i) / pow(cdelt2, j));
     409          }
    405410        }
    406411        psMetadataAddS32 (header, PS_LIST_TAIL, "NPLYTERM", PS_META_REPLACE, "", fitOrder);
    407     }
    408 
    409     // remove any existing 'CDi_j style' wcs keywords
    410     if (psMetadataLookup(header, "CD1_1")) {
     412      }
     413     
     414      // remove any existing 'CDi_j style' wcs keywords
     415      if (psMetadataLookup(header, "CD1_1")) {
    411416        psMetadataRemoveKey(header, "CD1_1");
    412417        psMetadataRemoveKey(header, "CD1_2");
    413418        psMetadataRemoveKey(header, "CD2_1");
    414419        psMetadataRemoveKey(header, "CD2_2");
     420      }
     421    }
     422    if (wcs->wcsCDkeys) {
     423
     424      psMetadataAddF64 (header, PS_LIST_TAIL, "CD1_1", PS_META_REPLACE, "", wcs->trans->x->coeff[1][0]);
     425      psMetadataAddF64 (header, PS_LIST_TAIL, "CD1_2", PS_META_REPLACE, "", wcs->trans->x->coeff[0][1]);
     426      psMetadataAddF64 (header, PS_LIST_TAIL, "CD2_1", PS_META_REPLACE, "", wcs->trans->y->coeff[1][0]);
     427      psMetadataAddF64 (header, PS_LIST_TAIL, "CD2_2", PS_META_REPLACE, "", wcs->trans->y->coeff[0][1]);
     428
     429      if (psMetadataLookup(header, "PC001001")) {
     430        psMetadataRemoveKey(header, "PC001001");
     431        psMetadataRemoveKey(header, "PC001002");
     432        psMetadataRemoveKey(header, "PC002001");
     433        psMetadataRemoveKey(header, "PC002002");
     434      }
    415435    }
    416436
     
    535555        fpa->toSky->R -= 2.0*M_PI;
    536556
     557    fpa->wcsCDkeys = wcs->wcsCDkeys;
     558
    537559    psTrace ("psastro", 5, "toFPA: %f %f  (%f,%f),(%f,%f)\n",
    538560             chip->toFPA->x->coeff[0][0], chip->toFPA->y->coeff[0][0],
     
    682704    wcs->cdelt2 = hypot (wcs->trans->y->coeff[1][0], wcs->trans->y->coeff[0][1]);
    683705
     706    wcs->wcsCDkeys = fpa->wcsCDkeys;
    684707    psFree (toTPA);
    685708
     
    922945    wcs->trans = psPlaneTransformAlloc (nXorder, nYorder);
    923946    wcs->toSky = NULL;
     947    wcs->wcsCDkeys = 0;
    924948
    925949    memset (wcs->ctype1, 0, PM_ASTROM_WCS_TYPE_SIZE);
  • branches/eam_branches/20090715/psModules/src/astrom/pmAstrometryWCS.h

    r24766 r25407  
    2323    double crpix1, crpix2;
    2424    double cdelt1, cdelt2;
     25    bool wcsCDkeys;
    2526    psProjection *toSky;
    2627    psPlaneTransform *trans;
  • branches/eam_branches/20090715/psModules/src/camera/pmFPA.h

    r21363 r25407  
    4848    psPlaneTransform *toTPA;  ///< Transformation from focal plane to tangent plane, or NULL
    4949    psProjection *toSky;         ///< Projection from tangent plane to sky, or NULL
     50    bool wcsCDkeys;
    5051    // Information
    5152    psMetadata *concepts;               ///< FPA-level concepts
  • branches/eam_branches/20090715/psModules/src/camera/pmFPAMaskWeight.c

    r24767 r25407  
    111111        // psError(PS_ERR_IO, true, "CELL.SATURATION is not set --- unable to set mask.\n");
    112112        // return false;
    113         psWarning("CELL.SATURATION is not set --- completely masking cell.\n");
    114         saturation = NAN;
     113        psWarning("CELL.SATURATION is not set --- completely masking cell.\n");
     114        saturation = NAN;
    115115    }
    116116    float bad = psMetadataLookupF32(&mdok, cell->concepts, "CELL.BAD"); // Bad level
     
    118118        // psError(PS_ERR_IO, true, "CELL.BAD is not set --- unable to set mask.\n");
    119119        // return false;
    120         psWarning("CELL.BAD is not set --- completely masking cell.\n");
    121         bad = NAN;
     120        psWarning("CELL.BAD is not set --- completely masking cell.\n");
     121        bad = NAN;
    122122    }
    123123    psTrace("psModules.camera", 5, "Saturation: %f, bad: %f\n", saturation, bad);
    124124
    125     // if CELL.GAIN or CELL.READNOISE are not set, then the variance will be set to NAN; 
     125    // if CELL.GAIN or CELL.READNOISE are not set, then the variance will be set to NAN;
    126126    // in this case, we have to set the mask as well
    127127    float gain = psMetadataLookupF32(&mdok, cell->concepts, "CELL.GAIN"); // Cell gain
     
    140140    // completely mask if SATURATION or BAD are invalid
    141141    if (isnan(saturation) || isnan(bad) || isnan(gain) || isnan(readnoise)) {
    142         psImageInit(mask, badMask);
    143         return true;
     142        psImageInit(mask, badMask);
     143        return true;
    144144    }
    145145
     
    230230        // return false;
    231231        psWarning("CELL.GAIN is not set --- setting variance to NAN\n");
    232         gain = NAN;
     232        gain = NAN;
    233233    }
    234234    float readnoise = psMetadataLookupF32(&mdok, cell->concepts, "CELL.READNOISE"); // Cell read noise
     
    237237        // return false;
    238238        psWarning("CELL.READNOISE is not set --- setting variance to NAN\n");
    239         readnoise = NAN;
     239        readnoise = NAN;
    240240    }
    241241    // if we have a non-NAN readnoise, then we need to ensure it has been updated (not necessary if NAN)
     
    248248    if (isnan(gain) || isnan(readnoise)) {
    249249        if (!readout->variance) {
    250             // generate the image if needed
     250            // generate the image if needed
    251251            readout->variance = psImageAlloc(readout->image->numCols, readout->image->numRows, PS_TYPE_F32);
    252252        }
    253         // XXX need to set the mask, if defined
     253        // XXX need to set the mask, if defined
    254254        psImageInit(readout->variance, NAN);
    255         return true;
     255        return true;
    256256    }
    257257
     
    262262
    263263        // a negative variance is non-sensical. if the image value drops below 1, the variance must be 1.
    264         // XXX this calculation is wrong: limit is 1 e-, but this is in DN
     264        // XXX this calculation is wrong: limit is 1 e-, but this is in DN
    265265        readout->variance = (psImage*)psUnaryOp(readout->variance, readout->variance, "abs");
    266266        readout->variance = (psImage*)psBinaryOp(readout->variance, readout->variance, "max",
     
    276276    // apply a supplied readnoise map (NOTE: in DN, not electrons):
    277277    if (noiseMap) {
    278         psImage *rdVar = (psImage*)psBinaryOp(NULL, (const psPtr) noiseMap, "*", (const psPtr) noiseMap);
    279         readout->variance = (psImage*)psBinaryOp(readout->variance, readout->variance, "+", rdVar);
    280         psFree (rdVar);
     278        psImage *rdVar = (psImage*)psBinaryOp(NULL, (const psPtr) noiseMap, "*", (const psPtr) noiseMap);
     279        readout->variance = (psImage*)psBinaryOp(readout->variance, readout->variance, "+", rdVar);
     280        psFree (rdVar);
    281281    } else {
    282         readout->variance = (psImage*)psBinaryOp(readout->variance, readout->variance, "+", psScalarAlloc(readnoise*readnoise/gain/gain, PS_TYPE_F32));
     282        readout->variance = (psImage*)psBinaryOp(readout->variance, readout->variance, "+", psScalarAlloc(readnoise*readnoise/gain/gain, PS_TYPE_F32));
    283283    }
    284284
     
    362362
    363363
    364 bool pmReadoutVarianceRenormPixels(const pmReadout *readout, psImageMaskType maskVal,
    365                                  psStatsOptions meanStat, psStatsOptions stdevStat, psRandom *rng)
     364bool pmReadoutVarianceRenormalise(const pmReadout *readout, psImageMaskType maskVal,
     365                                  int sample, float minValid, float maxValid)
    366366{
    367367    PM_ASSERT_READOUT_NON_NULL(readout, false);
     
    371371    psImage *image = readout->image, *mask = readout->mask, *variance = readout->variance; // Readout parts
    372372
    373     if (!psMemIncrRefCounter(rng)) {
    374         rng = psRandomAlloc(PS_RANDOM_TAUS);
    375     }
    376 
    377     psStats *varianceStats = psStatsAlloc(meanStat);// Statistics for mean
    378     if (!psImageBackground(varianceStats, NULL, variance, mask, maskVal, rng)) {
    379         psError(PS_ERR_UNKNOWN, false, "Unable to measure mean variance for image");
    380         psFree(varianceStats);
    381         psFree(rng);
    382         return false;
    383     }
    384     float meanVariance = varianceStats->robustMedian; // Mean variance
    385     psFree(varianceStats);
    386 
    387     psStats *imageStats = psStatsAlloc(stdevStat);// Statistics for mean
    388     if (!psImageBackground(imageStats, NULL, image, mask, maskVal, rng)) {
    389         psError(PS_ERR_UNKNOWN, false, "Unable to measure stdev of image");
    390         psFree(imageStats);
    391         psFree(rng);
    392         return false;
    393     }
    394     float stdevImage = imageStats->robustStdev; // Standard deviation of image
    395     psFree(imageStats);
    396     psFree(rng);
    397 
    398     float correction = PS_SQR(stdevImage) / meanVariance; // Correction to take variance to what it should be
    399     psLogMsg("psModules.camera", PS_LOG_INFO, "Renormalising variance map by %f", correction);
    400     psBinaryOp(variance, variance, "*", psScalarAlloc(correction, PS_TYPE_F32));
    401 
    402     return true;
    403 }
    404 
    405 
    406 bool pmReadoutVarianceRenormPhot(const pmReadout *readout, psImageMaskType maskVal, int num, float width,
    407                                psStatsOptions meanStat, psStatsOptions stdevStat, psRandom *rng)
    408 {
    409     PM_ASSERT_READOUT_NON_NULL(readout, false);
    410     PM_ASSERT_READOUT_IMAGE(readout, false);
    411     PM_ASSERT_READOUT_VARIANCE(readout, false);
    412 
    413     if (!psMemIncrRefCounter(rng)) {
    414         rng = psRandomAlloc(PS_RANDOM_TAUS);
    415     }
    416 
    417     psImage *image = readout->image, *mask = readout->mask, *variance = readout->variance; // Readout images
    418 
    419     // Measure background
    420     psStats *bgStats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);// Statistics for background
    421     if (!psImageBackground(bgStats, NULL, image, mask, maskVal, rng)) {
    422         psError(PS_ERR_UNKNOWN, false, "Unable to measure background for image");
    423         psFree(bgStats);
    424         psFree(rng);
    425         return false;
    426     }
    427     float bgMean = bgStats->robustMedian; // Background level
    428     float bgNoise = bgStats->robustStdev; // Background standard deviation
    429     psFree(bgStats);
    430     psTrace("psModules.camera", 5, "Background is %f +/- %f\n", bgMean, bgNoise);
    431 
    432 
    433     // Construct kernels for flux measurement
    434     // We use N(0,width) and N(0,width/sqrt(2)) kernels, following psphotSignificanceImage.
    435     float sigFactor = 4.0 * M_PI * PS_SQR(width); // Factor for conversion from im/wt ratio to significance
    436     int size = RENORM_NUM_SIGMA, fullSize = 2 * size + 1; // Half-size and full size of Gaussian
    437     psVector *gauss = psVectorAlloc(fullSize, PS_TYPE_F32); // Gaussian for weighting
    438     psVector *gauss2 = psVectorAlloc(fullSize, PS_TYPE_F32); // Gaussian squared
    439     for (int i = 0, x = -size; i < fullSize; i++, x++) {
    440         gauss->data.F32[i] = expf(-0.5 * PS_SQR(x) / PS_SQR(width));
    441         gauss2->data.F32[i] = expf(-PS_SQR(x) / PS_SQR(width));
    442     }
    443 
    444     // Size of image
    445     int numCols = image->numCols, numRows = image->numRows; // Size of images
    446     int xSize = numCols - fullSize, ySize = numRows - fullSize; // Size of consideration
    447     int xOffset = size, yOffset = size;       // Offset to region of consideration
    448 
    449     // Measure fluxes
    450     float peakFlux = RENORM_PEAK * bgNoise;     // Peak flux for fake sources
    451     psVector *noise = psVectorAlloc(num, PS_TYPE_F32); // Measurements of the noise
    452     psVector *source = psVectorAlloc(num, PS_TYPE_F32); // Measurements of fake sources
    453     psVector *guess = psVectorAlloc(num, PS_TYPE_F32); // Guess at significance
    454     psVector *photMask = psVectorAlloc(num, PS_TYPE_VECTOR_MASK); // Mask for fluxes
    455     for (int i = 0; i < num; i++) {
    456         // Coordinates of interest
    457         int xPix = psRandomUniform(rng) * xSize + xOffset + 0.5;
    458         int yPix = psRandomUniform(rng) * ySize + yOffset + 0.5;
    459         psAssert(xPix - size >= 0 && xPix + size < numCols &&
    460                  yPix - size >= 0 && yPix + size < numRows,
    461                  "Bad pixel position: %d,%d", xPix, yPix);
    462 
    463         // Weighted aperture photometry
    464         // This has the same effect as smoothing the image by the window function
    465         float sumNoise = 0.0;       // Sum for noise measurement
    466         float sumSource = 0.0;      // Sum for source measurement
    467         float sumVariance = 0.0;      // Sum for variance measurement
    468         float sumGauss = 0.0, sumGauss2 = 0.0; // Sums of Gaussian kernels
    469         for (int v = 0, y = yPix - size; v < fullSize; v++, y++) {
    470             float xSumNoise = 0.0;  // Sum for noise measurement in x
    471             float xSumSource = 0.0; // Sum for source measurement in x
    472             float xSumVariance = 0.0; // Sum for variance measurement in x
    473             float xSumGauss = 0.0, xSumGauss2 = 0.0; // Sums of Gaussian kernels in x
    474             float yGauss = gauss->data.F32[v]; // Value of Gaussian in y
    475             for (int u = 0, x = xPix - size; u < fullSize; u++, x++) {
    476                 if (mask && mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & maskVal) {
     373    int numCols = image->numCols, numRows = image->numRows; // Size of image
     374    int numPix = numCols * numRows;                         // Number of pixels
     375    int num = PS_MAX(sample, numPix);                       // Number we care about
     376    psVector *signoise = psVectorAllocEmpty(num, PS_TYPE_F32);   // Signal-to-noise values
     377
     378    if (num >= numPix) {
     379        // We have an image smaller than Nsubset, so just loop over the image pixels
     380        int index = 0;                  // Index for vector
     381        for (int y = 0; y < numRows; y++) {
     382            for (int x = 0; x < numCols; x++) {
     383                if ((mask && mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & maskVal) ||
     384                    !isfinite(image->data.F32[y][x]) || !isfinite(variance->data.F32[y][x])) {
    477385                    continue;
    478386                }
    479                 float value = image->data.F32[y][x] - bgMean; // Value of image
    480                 float xGauss = gauss->data.F32[u]; // Value of Gaussian in x
    481                 float xGauss2 = gauss2->data.F32[u]; // Value of Gaussian^2 in x
    482                 xSumNoise += value * xGauss;
    483                 xSumSource += (value + peakFlux * xGauss * yGauss) * xGauss;
    484                 xSumVariance += variance->data.F32[y][x] * xGauss2;
    485                 xSumGauss += xGauss;
    486                 xSumGauss2 += xGauss2;
    487             }
    488             float yGauss2 = gauss2->data.F32[v]; // Value of Gaussian^2 in y
    489             sumNoise += xSumNoise * yGauss;
    490             sumSource += xSumSource * yGauss;
    491             sumVariance += xSumVariance * yGauss2;
    492             sumGauss += xSumGauss * yGauss;
    493             sumGauss2 += xSumGauss2 * yGauss2;
    494         }
    495 
    496         photMask->data.PS_TYPE_VECTOR_MASK_DATA[i] = ((isfinite(sumNoise) && isfinite(sumSource) &&
    497                                                 isfinite(sumVariance) && sumGauss > 0 && sumGauss2 > 0) ?
    498                                                0 : 0xFF);
    499 
    500         float smoothImageNoise = sumNoise / sumGauss; // Value of smoothed image pixel for noise
    501         float smoothImageSource = sumSource / sumGauss; // Value of smoothed image pixel for source
    502         float smoothVariance = sumVariance / sumGauss2; // Value of smoothed variance pixel
    503 
    504         noise->data.F32[i] = smoothImageNoise;
    505         source->data.F32[i] = smoothImageSource;
    506         guess->data.F32[i] = (sumSource > 0) ? sigFactor * PS_SQR(smoothImageSource) / smoothVariance : 0.0;
    507         psTrace("psModules.camera", 10, "Flux %d (%d,%d): %f, %f, %f\n",
    508                 i, xPix, yPix, smoothImageNoise, smoothImageSource, smoothVariance);
    509     }
    510     psFree(gauss);
    511     psFree(gauss2);
    512     psFree(rng);
    513 
    514     // Standard deviation of fluxes gives us the real significance
    515     psStats *stdevStats = psStatsAlloc(stdevStat); // Statistics
    516     if (!psVectorStats(stdevStats, noise, NULL, photMask, 0xFF)) {
    517         psError(PS_ERR_UNKNOWN, false, "Unable to measure standard deviation of fluxes");
    518         psFree(stdevStats);
    519         psFree(noise);
    520         psFree(source);
    521         psFree(guess);
    522         psFree(photMask);
     387
     388                signoise->data.F32[index] = image->data.F32[y][x] / sqrtf(variance->data.F32[y][x]);
     389                index++;
     390            }
     391        }
     392        signoise->n = index;
     393    } else {
     394        psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS); // Random number generator
     395        int index = 0;                  // Index for vector
     396        for (long i = 0; i < num; i++) {
     397            // Pixel coordinates
     398            int pixel = numPix * psRandomUniform(rng);
     399            int x = pixel % numCols;
     400            int y = pixel / numCols;
     401
     402            if ((mask && mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & maskVal) ||
     403                !isfinite(image->data.F32[y][x]) || !isfinite(variance->data.F32[y][x])) {
     404                continue;
     405            }
     406
     407            signoise->data.F32[index] = image->data.F32[y][x] / sqrtf(variance->data.F32[y][x]);
     408            index++;
     409        }
     410        signoise->n = index;
     411        psFree(rng);
     412    }
     413
     414    psStats *stats = psStatsAlloc(PS_STAT_ROBUST_STDEV); // Statistics
     415
     416    if (!psVectorStats(stats, signoise, NULL, NULL, 0)) {
     417        psError(PS_ERR_UNKNOWN, false, "Unable to measure statistics on S/N image");
     418        psFree(signoise);
    523419        return false;
    524420    }
    525     float stdev = psStatsGetValue(stdevStats, stdevStat); // Standard deviation of fluxes
    526     psFree(stdevStats);
    527     psFree(noise);
    528     psTrace("psModules.camera", 5, "Standard deviation of fluxes is %f\n", stdev);
    529 
    530     // Ratio of measured significance to guessed significance
    531     psVector *ratio = psVectorAlloc(num, PS_TYPE_F32); // Ratio of measured to guess
    532     for (int i = 0; i < num; i++) {
    533         float measuredSig = PS_SQR(source->data.F32[i] / stdev); // Measured significance
    534         ratio->data.F32[i] = measuredSig / guess->data.F32[i];
    535         if (guess->data.F32[i] <= 0.0 || source->data.F32[i] <= 0.0 || !isfinite(ratio->data.F32[i])) {
    536             photMask->data.PS_TYPE_VECTOR_MASK_DATA[i] = 0xFF;
    537         }
    538         psTrace("psModules.camera", 9, "Ratio %d: %f, %f, %f\n",
    539                 i, guess->data.F32[i], measuredSig, ratio->data.F32[i]);
    540     }
    541     psFree(source);
    542     psFree(guess);
    543 
    544     psStats *meanStats = psStatsAlloc(meanStat | stdevStat); // Statistics
    545     if (!psVectorStats(meanStats, ratio, NULL, photMask, 0xFF)) {
    546         psError(PS_ERR_UNKNOWN, false, "Unable to measure mean ratio");
    547         psFree(meanStats);
    548         psFree(ratio);
    549         psFree(photMask);
    550         return false;
    551     }
    552     float meanRatio = psStatsGetValue(meanStats, meanStat); // Mean ratio
    553     psTrace("psModules.camera", 5, "Mean significance ratio is %f +/- %f\n",
    554             meanRatio, psStatsGetValue(meanStats, stdevStat));
    555     psFree(meanStats);
    556     psFree(ratio);
    557     psFree(photMask);
    558 
    559     psLogMsg("psModules.camera", PS_LOG_INFO, "Renormalising variance map by %f", meanRatio);
    560     psBinaryOp(variance, variance, "*", psScalarAlloc(meanRatio, PS_TYPE_F32));
     421    psFree(signoise);
     422
     423    float covar = sqrtf(psImageCovarianceFactor(readout->covariance)); // Covariance factor
     424    float correction = stats->robustStdev / covar; // Correction factor
     425    psFree(stats);
     426    psLogMsg("psModules.camera", PS_LOG_DETAIL, "Variance renormalisation factor is %f", correction);
     427
     428    // Check valid range of correction factor
     429    if ((isfinite(minValid) && correction < minValid) || (isfinite(maxValid) && correction > maxValid)) {
     430        psWarning("Variance renormalisation is outside valid range: %f vs %f:%f --- no correction made",
     431                  correction, minValid, maxValid);
     432        return true;
     433    }
     434
     435    psBinaryOp(variance, variance, "*", psScalarAlloc(PS_SQR(correction), PS_TYPE_F32));
     436
     437    pmHDU *hdu = pmHDUFromReadout(readout); // HDU for readout
     438    if (hdu)  {
     439        psString history = NULL;
     440        psStringAppend(&history, "Rescaled variance by %6.4f (stdev by %6.4f)",
     441                       PS_SQR(correction), correction);
     442        psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, NULL, history);
     443        psFree(history);
     444    }
    561445
    562446    return true;
    563447}
    564448
    565 
    566 bool pmReadoutVarianceRenorm(const pmReadout *readout, psImageMaskType maskVal, psStatsOptions meanStat,
    567                            psStatsOptions stdevStat, int width, psRandom *rng)
    568 {
    569     PM_ASSERT_READOUT_NON_NULL(readout, false);
    570     PM_ASSERT_READOUT_IMAGE(readout, false);
    571     PM_ASSERT_READOUT_VARIANCE(readout, false);
    572     PS_ASSERT_INT_POSITIVE(width, false);
    573 
    574     if (!psMemIncrRefCounter(rng)) {
    575         rng = psRandomAlloc(PS_RANDOM_TAUS);
    576     }
    577 
    578     psImage *image = readout->image, *mask = readout->mask, *variance = readout->variance; // Readout images
    579     int numCols = image->numCols, numRows = image->numRows; // Size of images
    580     int xNum = numCols / width + 1, yNum = numRows / width + 1; // Number of renormalisation regions
    581     float xSize = numCols / (float)xNum, ySize = numRows / (float)yNum; // Size of renormalisation regions
    582 
    583     psStats *meanStats = psStatsAlloc(meanStat), *stdevStats = psStatsAlloc(stdevStat); // Statistics
    584     psVector *buffer = NULL;
    585 
    586     for (int j = 0; j < yNum; j++) {
    587         // Bounds in y
    588         int yMin = j * ySize;
    589         int yMax = (j + 1) * ySize;
    590         for (int i = 0; i < xNum; i++) {
    591             // Bounds in x
    592             int xMin = i * xSize;
    593             int xMax = (i + 1) * xSize;
    594 
    595             psRegion region = psRegionSet(xMin, xMax, yMin, yMax); // Region of interest
    596             psImage *subImage = psImageSubset(image, region); // Sub-image of the image pixels
    597             psImage *subVariance = psImageSubset(variance, region); // Sub image of the variance pixels
    598             psImage *subMask = mask ? psImageSubset(mask, region) : NULL; // Sub-image of the mask pixels
    599 
    600             if (!psImageBackground(stdevStats, &buffer, subImage, subMask, maskVal, rng) ||
    601                 !psImageBackground(meanStats, &buffer, subVariance, subMask, maskVal, rng)) {
    602                 // Nothing we can do about it, but don't want to keel over and die, so do our best to flag it.
    603                 psString regionStr = psRegionToString(region); // String with region
    604                 psWarning("Unable to measure statistics over %s", regionStr);
    605                 psFree(regionStr);
    606                 psErrorClear();
    607                 psImageInit(subVariance, NAN);
    608                 if (subMask) {
    609                     psImageInit(subMask, maskVal);
    610                 }
    611             } else {
    612                 double meanVar = psStatsGetValue(meanStats, meanStat); // Mean of variance map
    613                 double stdev = psStatsGetValue(stdevStats, stdevStat); // Standard deviation of image
    614                 psTrace("psModules.camera", 3,
    615                         "Region [%d:%d,%d:%d] has variance %lf, but mean of variance map is %lf\n",
    616                         xMin, xMax, yMin, yMax, PS_SQR(stdev), meanVar);
    617                 psBinaryOp(subVariance, subVariance, "*", psScalarAlloc(PS_SQR(stdev) / meanVar, PS_TYPE_F32));
    618             }
    619 
    620             psFree(subImage);
    621             psFree(subVariance);
    622             psFree(subMask);
    623         }
    624     }
    625     psFree(meanStats);
    626     psFree(stdevStats);
    627     psFree(rng);
    628     psFree(buffer);
    629 
    630     return true;
    631 }
    632449
    633450
  • branches/eam_branches/20090715/psModules/src/camera/pmFPAMaskWeight.h

    r24483 r25407  
    1515/// @addtogroup Camera Camera Layout
    1616/// @{
    17 
    18 #if 0
    19 /// Pixel mask values
    20 typedef enum {
    21     PM_MASK_CLEAR    = 0x00,            ///< The pixel is not masked
    22     PM_MASK_BLANK    = 0x01,            ///< The pixel is blank or has no (valid) data
    23     PM_MASK_FLAT     = 0x02,            ///< The pixel is non-positive in the flat-field
    24     PM_MASK_DETECTOR = 0x02,            ///< The detector pixel is bad (e.g., bad column, charge trap)
    25     PM_MASK_SAT      = 0x04,            ///< The pixel is saturated in the image of interest
    26     PM_MASK_BAD      = 0x04,            ///< The pixel is low in the image of interest
    27     PM_MASK_RANGE    = 0x04,            ///< The pixel is out of range in the image of interest
    28     PM_MASK_CR       = 0x08,            ///< The pixel is probably a CR
    29     PM_MASK_SPARE1   = 0x10,            ///< Spare mask value
    30     PM_MASK_SPARE2   = 0x20,            ///< Spare mask value
    31     PM_MASK_SUSPECT  = 0x40,            ///< The pixel is suspected of being bad, but may not be
    32     PM_MASK_MARK     = 0x80,            ///< The pixel is marked as temporarily ignored
    33 } pmMaskValue;
    34 #define PM_MASK_MARK 0x80            ///< The pixel is marked as temporarily ignored
    35 #define PM_MASK_SAT  0x04            ///< The pixel is saturated in the image of interest
    36 #endif
    3717
    3818/// Set a temporary readout mask using CELL.SATURATION and CELL.BAD
     
    5434/// can't be generated.
    5535bool pmReadoutSetVariance(pmReadout *readout, ///< Readout for which to set variance
    56                           const psImage *noiseMap, ///< 2D image of the read noise in DN
     36                          const psImage *noiseMap, ///< 2D image of the read noise in DN
    5737                          bool poisson    ///< Include poisson variance (in addition to read noise)?
    5838    );
     
    7353/// with HDU entry).  This is intended for most operations.
    7454bool pmReadoutGenerateVariance(pmReadout *readout, ///< Readout for which to generate variance
    75                           const psImage *noiseMap, ///< 2D image of the read noise in DN
     55                          const psImage *noiseMap, ///< 2D image of the read noise in DN
    7656                               bool poisson    ///< Include poisson variance (in addition to read noise)?
    7757    );
     
    8363                                   psImageMaskType sat, ///< Mask value to give saturated pixels
    8464                                   psImageMaskType bad, ///< Mask value to give bad (low) pixels
    85                                    const psImage *noiseMap, ///< 2D image of the read noise in DN
     65                                   const psImage *noiseMap, ///< 2D image of the read noise in DN
    8666                                   bool poisson ///< Include poisson variance (in addition to read noise)?
    8767    );
     
    9373                                psImageMaskType sat, ///< Mask value to give saturated pixels
    9474                                psImageMaskType bad, ///< Mask value to give bad (low) pixels
    95                                 const psImage *noiseMap, ///< 2D image of the read noise in DN
     75                                const psImage *noiseMap, ///< 2D image of the read noise in DN
    9676                                bool poisson ///< Include poisson variance (in addition to read noise)?
    9777    );
     
    10080///
    10181/// The variance map is adjusted so that the mean matches the actual pixel variance in the image
    102 bool pmReadoutVarianceRenormPixels(
    103     const pmReadout *readout,           ///< Readout to normalise
    104     psImageMaskType maskVal,                 ///< Value to mask
    105     psStatsOptions meanStat,            ///< Statistic to measure the mean (of the variance map)
    106     psStatsOptions stdevStat,           ///< Statistic to measure the stdev (of the image)
    107     psRandom *rng                       ///< Random number generator
    108     );
    109 
    110 /// Renormalise the variance map to match the actual photometry variance
    111 ///
    112 /// The variance map is adjusted so that the actual significance of fake sources matches the
    113 /// guestimated significance
    114 bool pmReadoutVarianceRenormPhot(
     82bool pmReadoutVarianceRenormalise(
    11583    const pmReadout *readout,           ///< Readout to normalise
    11684    psImageMaskType maskVal,            ///< Value to mask
    117     int num,                            ///< Number of instances to measure over the image
    118     float width,                        ///< Photometry width
    119     psStatsOptions meanStat,            ///< Statistic to measure the mean
    120     psStatsOptions stdevStat,           ///< Statistic to measure the stdev
    121     psRandom *rng                       ///< Random number generator
    122     );
    123 
    124 /// Renormalise the variance map to match the actual variance
    125 ///
    126 /// The variance in the image is measured in patches, and the variance map is adjusted so that the mean for
    127 /// that patch corresponds.
    128 bool pmReadoutVarianceRenorm(const pmReadout *readout, // Readout to normalise
    129                              psImageMaskType maskVal, // Value to mask
    130                              psStatsOptions meanStat, // Statistic to measure the mean (of the variance map)
    131                              psStatsOptions stdevStat, // Statistic to measure the stdev (of the image)
    132                              int width,   // Width of patch (pixels)
    133                              psRandom *rng // Random number generator (for sub-sampling images)
     85    int sample,                         ///< Sample size
     86    float minValid,                     ///< Minimum valid renormalisation, or NAN
     87    float maxValid                      ///< Maximum valid renormalisation, or NAN
    13488    );
    13589
  • branches/eam_branches/20090715/psModules/src/camera/pmFPAMosaic.c

    r21363 r25407  
    740740static bool chipMosaic(psImage **mosaicImage, // The mosaic image, to be returned
    741741                       psImage **mosaicMask, // The mosaic mask, to be returned
    742                        psImage **mosaicVariances, // The mosaic variances, to be returned
     742                       psImage **mosaicVariance, // The mosaic variance, to be returned
    743743                       int *xBinChip, int *yBinChip, // The binning in x and y, to be returned
    744744                       const pmChip *chip, // Chip to mosaic
     
    749749    assert(mosaicImage);
    750750    assert(mosaicMask);
    751     assert(mosaicVariances);
     751    assert(mosaicVariance);
    752752    assert(xBinChip);
    753753    assert(yBinChip);
     
    826826    if (allGood) {
    827827        *mosaicImage = imageMosaic(images, xFlip, yFlip, xBin, yBin, *xBinChip, *yBinChip, x0, y0, BLANK_VALUE);
    828         *mosaicVariances = imageMosaic(variances, xFlip, yFlip, xBin, yBin, *xBinChip, *yBinChip, x0, y0, BLANK_VALUE);
     828        *mosaicVariance = imageMosaic(variances, xFlip, yFlip, xBin, yBin, *xBinChip, *yBinChip, x0, y0, BLANK_VALUE);
    829829        *mosaicMask = imageMosaic(masks, xFlip, yFlip, xBin, yBin, *xBinChip, *yBinChip, x0, y0, blank);
    830830    }
     
    847847static bool fpaMosaic(psImage **mosaicImage, // The mosaic image, to be returned
    848848                      psImage **mosaicMask, // The mosaic mask, to be returned
    849                       psImage **mosaicVariances, // The mosaic variances, to be returned
     849                      psImage **mosaicVariance, // The mosaic variance, to be returned
    850850                      int *xBinFPA, int *yBinFPA, // The binning in x and y, to be returned
    851851                      const pmFPA *fpa,  // FPA to mosaic
     
    857857    assert(mosaicImage);
    858858    assert(mosaicMask);
    859     assert(mosaicVariances);
     859    assert(mosaicVariance);
    860860    assert(xBinFPA);
    861861    assert(yBinFPA);
     
    960960    if (allGood) {
    961961        *mosaicImage = imageMosaic(images, xFlip, yFlip, xBin, yBin, *xBinFPA, *yBinFPA, x0, y0, BLANK_VALUE);
    962         *mosaicVariances = imageMosaic(variances, xFlip, yFlip, xBin, yBin, *xBinFPA, *yBinFPA, x0, y0, BLANK_VALUE);
     962        *mosaicVariance = imageMosaic(variances, xFlip, yFlip, xBin, yBin, *xBinFPA, *yBinFPA, x0, y0, BLANK_VALUE);
    963963        *mosaicMask = imageMosaic(masks, xFlip, yFlip, xBin, yBin, *xBinFPA, *yBinFPA, x0, y0, blank);
    964964    }
     
    10251025    psImage *mosaicImage   = NULL;      // The mosaic image
    10261026    psImage *mosaicMask    = NULL;      // The mosaic mask
    1027     psImage *mosaicVariances = NULL;      // The mosaic variances
     1027    psImage *mosaicVariance = NULL;      // The mosaic variances
    10281028
    10291029    // Find the HDU
     
    10521052        }
    10531053        if (hdu->variances) {
    1054             mosaicVariances = psImageSubset(hdu->variances->data[0], bounds);
    1055             if (!mosaicVariances) {
     1054            mosaicVariance = psImageSubset(hdu->variances->data[0], bounds);
     1055            if (!mosaicVariance) {
    10561056                psError(PS_ERR_UNKNOWN, false, "Unable to select variance pixels.\n");
    10571057                return false;
     
    10611061        // Case 2 --- we need to mosaic by cut and paste
    10621062        psTrace("psModules.camera", 1, "Case 2 mosaicking: cut and paste.\n");
    1063         if (!chipMosaic(&mosaicImage, &mosaicMask, &mosaicVariances, &xBin, &yBin, source, targetCell, blank)) {
     1063        if (!chipMosaic(&mosaicImage, &mosaicMask, &mosaicVariance, &xBin, &yBin, source, targetCell, blank)) {
    10641064            psError(PS_ERR_UNKNOWN, false, "Unable to mosaic cells.\n");
    10651065            return false;
     
    10691069    }
    10701070    psTrace("psModules.camera", 1, "xBin,yBin: %d,%d\n", xBin, yBin);
     1071
    10711072
    10721073    // Set the concepts for the target cell
     
    10901091    target->parent->concepts = psMetadataCopy(target->parent->concepts, source->parent->concepts); // FPA lvl
    10911092
     1093    // Average the covariances
     1094    psList *covariances = psListAlloc(NULL); // Input covariance matrices
     1095    for (int i = 0; i < source->cells->n; i++) {
     1096        pmCell *cell = source->cells->data[i]; // Cell of interest
     1097        if (!cell || !cell->data_exists) {
     1098            continue;
     1099        }
     1100        pmReadout *ro = cell->readouts->data[0]; // Readout of interest
     1101        if (!ro || !ro->covariance) {
     1102            continue;
     1103        }
     1104        psListAdd(covariances, PS_LIST_TAIL, ro->covariance);
     1105    }
     1106    psKernel *mosaicCovariance = NULL;  // Covariance for mosaic
     1107    if (psListLength(covariances) > 0) {
     1108        psArray *covarArray = psListToArray(covariances); // Array with covariances
     1109        mosaicCovariance = psImageCovarianceAverage(covarArray);
     1110        psFree(covarArray);
     1111    }
     1112    psFree(covariances);
     1113
    10921114    // Now make a new readout to go in the target cell
    10931115    pmReadout *newReadout = pmReadoutAlloc(targetCell); // New readout
    10941116    newReadout->image  = mosaicImage;
    10951117    newReadout->mask   = mosaicMask;
    1096     newReadout->variance = mosaicVariances;
     1118    newReadout->variance = mosaicVariance;
     1119    newReadout->covariance = mosaicCovariance;
    10971120    psFree(newReadout);                 // Drop reference
    10981121
     
    13341357    target->concepts = psMetadataCopy(target->concepts, source->concepts);
    13351358
     1359    // Average the covariances
     1360    psList *covariances = psListAlloc(NULL); // Input covariance matrices
     1361    for (int i = 0; i < covariances->n; i++) {
     1362        pmChip *chip = chips->data[i];  // Chip of interest
     1363        if (!chip || !chip->data_exists) {
     1364            continue;
     1365        }
     1366        psArray *cells = chip->cells;   // Cells in chip
     1367        for (long j = 0; j < cells->n; j++) {
     1368            pmCell *cell = cells->data[i]; // Cell of interest
     1369            if (!cell || !cell->data_exists) {
     1370                continue;
     1371            }
     1372            pmReadout *ro = cell->readouts->data[0]; // Readout of interest
     1373            if (!ro || !ro->covariance) {
     1374                continue;
     1375            }
     1376            psListAdd(covariances, PS_LIST_TAIL, ro->covariance);
     1377        }
     1378    }
     1379    psKernel *mosaicCovariances = NULL; // Covariance for mosaic
     1380    if (psListLength(covariances) > 0) {
     1381        psArray *covarArray = psListToArray(covariances); // Array with covariances
     1382        mosaicCovariances = psImageCovarianceAverage(covarArray);
     1383        psFree(covarArray);
     1384    }
     1385    psFree(covariances);
     1386
    13361387    // Now make a new readout to go in the new cell
    13371388    pmReadout *newReadout = pmReadoutAlloc(targetCell); // New readout
     
    13391390    newReadout->mask   = mosaicMask;
    13401391    newReadout->variance = mosaicVariances;
     1392    newReadout->covariance = mosaicCovariances;
    13411393    psFree(newReadout);                 // Drop reference
    13421394
  • branches/eam_branches/20090715/psModules/src/camera/pmReadoutFake.c

    r23960 r25407  
    2828#define MODEL_TYPE "PS_MODEL_RGAUSS"    // Type of model to use
    2929#define MAX_AXIS_RATIO 20.0             // Maximum axis ratio for PSF model
    30 #define SOURCE_MASK (PM_SOURCE_MODE_DEFECT | PM_SOURCE_MODE_CR_LIMIT) // Mask to apply to input sources
    3130#define MODEL_MASK (PM_MODEL_STATUS_NONCONVERGE | PM_MODEL_STATUS_OFFIMAGE | \
    3231                    PM_MODEL_STATUS_BADARGS | PM_MODEL_STATUS_LIMITS) // Mask to apply to models
     
    5049}
    5150
    52 bool pmReadoutFakeFromSources(pmReadout *readout, int numCols, int numRows, const psArray *sources,
    53                               const psVector *xOffset, const psVector *yOffset, const pmPSF *psf,
    54                               float minFlux, int radius, bool circularise, bool normalisePeak)
     51
     52bool pmReadoutFakeFromVectors(pmReadout *readout, int numCols, int numRows,
     53                              const psVector *x, const psVector *y, const psVector *mag,
     54                              const psVector *xOffset, const psVector *yOffset,
     55                              const pmPSF *psf, float minFlux, int radius,
     56                              bool circularise, bool normalisePeak)
    5557{
    5658    PS_ASSERT_PTR_NON_NULL(readout, false);
    5759    PS_ASSERT_INT_LARGER_THAN(numCols, 0, false);
    5860    PS_ASSERT_INT_LARGER_THAN(numRows, 0, false);
    59     PS_ASSERT_ARRAY_NON_NULL(sources, false);
    60 
     61    PS_ASSERT_VECTOR_NON_NULL(x, false);
     62    PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F32, false);
     63    PS_ASSERT_VECTOR_NON_NULL(y, false);
     64    PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F32, false);
     65    PS_ASSERT_VECTORS_SIZE_EQUAL(y, x, false);
     66    PS_ASSERT_VECTOR_NON_NULL(mag, false);
     67    PS_ASSERT_VECTOR_TYPE(mag, PS_TYPE_F32, false);
     68    PS_ASSERT_VECTORS_SIZE_EQUAL(mag, x, false);
     69    long numSources = x->n;              // Number of sources
    6170    if (xOffset || yOffset) {
    6271        PS_ASSERT_VECTOR_NON_NULL(xOffset, false);
     
    6473        PS_ASSERT_VECTORS_SIZE_EQUAL(xOffset, yOffset, false);
    6574        PS_ASSERT_VECTOR_TYPE(xOffset, PS_TYPE_S32, false);
    66         PS_ASSERT_VECTOR_TYPE_EQUAL(xOffset, yOffset, false);
    67         if (xOffset->n != sources->n) {
     75        PS_ASSERT_VECTOR_TYPE(yOffset, PS_TYPE_S32, false);
     76        if (xOffset->n != numSources) {
    6877            psError(PS_ERR_BAD_PARAMETER_SIZE, true,
    6978                    "Number of offset vectors (%ld) and sources (%ld) doesn't match",
    70                     xOffset->n, sources->n);
     79                    xOffset->n, numSources);
    7180            return false;
    7281        }
    7382    }
    7483    PS_ASSERT_PTR_NON_NULL(psf, false);
    75     if (radius > 0 && isfinite(minFlux) && minFlux > 0.0) {
    76         psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Cannot define both minimum flux and fixed radius.");
    77         return false;
    78     }
    7984
    8085    readout->image = psImageRecycle(readout->image, numCols, numRows, PS_TYPE_F32);
    8186    psImageInit(readout->image, 0);
    8287
    83     int numSources = sources->n;          // Number of stars
    84     for (int i = 0; i < numSources; i++) {
    85         pmSource *source = sources->data[i]; // Source of interest
    86         if (!source) {
    87             continue;
    88         }
    89         if (source->mode & SOURCE_MASK) {
    90             continue;
    91         }
    92         if (!isfinite(source->psfMag)) {
    93             continue;
    94         }
    95         float x, y;                     // Coordinates of source
    96         if (source->modelPSF) {
    97             x = source->modelPSF->params->data.F32[PM_PAR_XPOS];
    98             y = source->modelPSF->params->data.F32[PM_PAR_YPOS];
    99         } else {
    100             x = source->peak->xf;
    101             y = source->peak->yf;
    102         }
    103 
    104         float flux = powf(10.0, -0.4 * source->psfMag); // Flux of source
     88    for (long i = 0; i < numSources; i++) {
     89        float flux = powf(10.0, -0.4 * mag->data.F32[i]); // Flux of source
     90        float xSrc = x->data.F32[i], ySrc = y->data.F32[i]; // Coordinates of source
    10591
    10692        if (normalisePeak) {
    10793            // Normalise flux
    108             pmModel *normModel = pmModelFromPSFforXY(psf, x, y, 1.0); // Model for normalisation
     94            pmModel *normModel = pmModelFromPSFforXY(psf, xSrc, ySrc, 1.0); // Model for normalisation
    10995            if (!normModel || (normModel->flags & MODEL_MASK)) {
    11096                psFree(normModel);
     
    121107        }
    122108
    123         pmModel *fakeModel = pmModelFromPSFforXY(psf, x, y, flux);
     109        pmModel *fakeModel = pmModelFromPSFforXY(psf, xSrc, ySrc, flux);
    124110        if (!fakeModel || (fakeModel->flags & MODEL_MASK)) {
    125111            psFree(fakeModel);
     
    137123
    138124        pmSource *fakeSource = pmSourceAlloc(); // Fake source to generate
    139         fakeSource->peak = pmPeakAlloc(x, y, fakeModel->params->data.F32[PM_PAR_I0], PM_PEAK_LONE);
    140         float fakeRadius = radius > 0 ? radius :
    141             PS_MAX(1.0, fakeModel->modelRadius(fakeModel->params, minFlux)); // Radius of fake source
     125        fakeSource->peak = pmPeakAlloc(xSrc, ySrc, fakeModel->params->data.F32[PM_PAR_I0], PM_PEAK_LONE);
     126        float fakeRadius = 1.0;         // Radius of fake source
     127        if (isfinite(minFlux)) {
     128            fakeRadius = PS_MAX(fakeRadius, fakeModel->modelRadius(fakeModel->params, minFlux));
     129        }
     130        if (radius > 0) {
     131            fakeRadius = PS_MAX(fakeRadius, radius);
     132        }
    142133
    143134        if (xOffset) {
    144             if (!pmSourceDefinePixels(fakeSource, readout, x + xOffset->data.S32[i],
    145                                       y + yOffset->data.S32[i], fakeRadius)) {
     135            if (!pmSourceDefinePixels(fakeSource, readout, xSrc + xOffset->data.S32[i],
     136                                      ySrc + yOffset->data.S32[i], fakeRadius)) {
    146137                psErrorClear();
    147138                continue;
     
    153144            }
    154145        } else {
    155             if (!pmSourceDefinePixels(fakeSource, readout, x, y, fakeRadius)) {
     146            if (!pmSourceDefinePixels(fakeSource, readout, xSrc, ySrc, fakeRadius)) {
    156147                psErrorClear();
    157148                continue;
     
    168159    return true;
    169160}
     161
     162
     163bool pmReadoutFakeFromSources(pmReadout *readout, int numCols, int numRows, const psArray *sources,
     164                              pmSourceMode sourceMask, const psVector *xOffset, const psVector *yOffset,
     165                              const pmPSF *psf, float minFlux, int radius,
     166                              bool circularise, bool normalisePeak)
     167{
     168    PS_ASSERT_ARRAY_NON_NULL(sources, false);
     169
     170    int numSources = sources->n;          // Number of stars
     171    psVector *x = psVectorAllocEmpty(numSources, PS_TYPE_F32);
     172    psVector *y = psVectorAllocEmpty(numSources, PS_TYPE_F32);
     173    psVector *mag = psVectorAllocEmpty(numSources, PS_TYPE_F32);
     174
     175    int numGood = 0;                    // Number of good sources
     176    for (int i = 0; i < numSources; i++) {
     177        pmSource *source = sources->data[i]; // Source of interest
     178        if (!source) {
     179            continue;
     180        }
     181        if (source->mode & sourceMask) {
     182            continue;
     183        }
     184        if (!isfinite(source->psfMag)) {
     185            continue;
     186        }
     187        float xSrc, ySrc;                     // Coordinates of source
     188        if (source->modelPSF) {
     189            xSrc = source->modelPSF->params->data.F32[PM_PAR_XPOS];
     190            ySrc = source->modelPSF->params->data.F32[PM_PAR_YPOS];
     191        } else {
     192            xSrc = source->peak->xf;
     193            ySrc = source->peak->yf;
     194        }
     195
     196        x->data.F32[numGood] = xSrc;
     197        y->data.F32[numGood] = ySrc;
     198        mag->data.F32[numGood] = source->psfMag;
     199        numGood++;
     200    }
     201    x->n = numGood;
     202    y->n = numGood;
     203    mag->n = numGood;
     204
     205    bool status = pmReadoutFakeFromVectors(readout, numCols, numRows, x, y, mag, xOffset, yOffset, psf,
     206                                           minFlux, radius, circularise, normalisePeak);
     207    psFree(x);
     208    psFree(y);
     209    psFree(mag);
     210
     211    return status;
     212}
  • branches/eam_branches/20090715/psModules/src/camera/pmReadoutFake.h

    r20999 r25407  
    1111#include <pmTrend2D.h>
    1212#include <pmPSF.h>
     13#include <pmSourceMasks.h>
     14
     15/// Generate a fake readout from vectors
     16bool pmReadoutFakeFromVectors(pmReadout *readout, ///< Output readout
     17                              int numCols, int numRows, ///< Dimension of image
     18                              const psVector *x, const psVector *y, ///< Source coordinates
     19                              const psVector *mag, ///< Source magnitudes
     20                              const psVector *xOffset, ///< x offsets for sources (source -> img), or NULL
     21                              const psVector *yOffset, ///< y offsets for sources (source -> img), or NULL
     22                              const pmPSF *psf, ///< PSF for sources
     23                              float minFlux, ///< Minimum flux to bother about; for setting source radius
     24                              int radius, ///< Fixed radius for sources
     25                              bool circularise, ///< Circularise PSF model?
     26                              bool normalisePeak ///< Normalise the peak value?
     27    );
    1328
    1429/// Generate a fake readout from an array of sources
    15 bool pmReadoutFakeFromSources(pmReadout *readout, ///< Output readout, or NULL
     30bool pmReadoutFakeFromSources(pmReadout *readout, ///< Output readout
    1631                              int numCols, int numRows, ///< Dimension of image
    1732                              const psArray *sources, ///< Array of pmSource
     33                              pmSourceMode sourceMask, ///< Mask for sources
    1834                              const psVector *xOffset, ///< x offsets for sources (source -> img), or NULL
    1935                              const psVector *yOffset, ///< y offsets for sources (source -> img), or NULL
  • branches/eam_branches/20090715/psModules/src/concepts/pmConcepts.c

    r24777 r25407  
    377377        conceptRegisterS32("CELL.XWINDOW", "Start of cell window (pixels)",p_pmConceptParse_Positions,p_pmConceptFormat_Positions, NULL, true, PM_FPA_LEVEL_CELL);
    378378        conceptRegisterS32("CELL.YWINDOW", "Start of cell window (pixels)",p_pmConceptParse_Positions,p_pmConceptFormat_Positions, NULL, true, PM_FPA_LEVEL_CELL);
    379         conceptRegisterF32("CELL.VARFACTOR", "Variance factor for conversion from large to small scales", NULL, NULL, NULL, true, PM_FPA_LEVEL_CELL);
    380379
    381380        // CELL.TRIMSEC
     
    485484        concept[length - 1] = '\0';
    486485
    487         // special variants:
    488         if (!strcmp(concept, "FPA.DATE")) {
    489           psTime *fpaTime = psMetadataLookupPtr(NULL, fpa->concepts, "FPA.TIME");
    490           if (!fpaTime) {
    491             psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Missing concept FPA.TIME needed for FPA.DATE");
    492             psFree(string);
    493             return NULL;
    494           }
    495           psString dateTimeString = psTimeToISO(fpaTime); // String representation
    496           psList *dateTime = psStringSplit(dateTimeString, "T", true);
    497           psFree(dateTimeString);
    498           psString dateString = psMemIncrRefCounter(psListGet(dateTime, PS_LIST_HEAD)); // The date string
    499           psFree (dateTime);
    500 
    501           if (!psStringSubstitute(&string, dateString, "{FPA.DATE}")) {
    502               psError(PS_ERR_UNKNOWN, false, "Unable to replace concept %s", concept);
    503               psFree(string);
    504               psFree(dateString);
    505               return NULL;
    506           }
    507           psFree (dateString);
    508           continue;
    509         }
     486        // special variants:
     487        if (!strcmp(concept, "FPA.DATE")) {
     488          psTime *fpaTime = psMetadataLookupPtr(NULL, fpa->concepts, "FPA.TIME");
     489          if (!fpaTime) {
     490            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Missing concept FPA.TIME needed for FPA.DATE");
     491            psFree(string);
     492            return NULL;
     493          }
     494          psString dateTimeString = psTimeToISO(fpaTime); // String representation
     495          psList *dateTime = psStringSplit(dateTimeString, "T", true);
     496          psFree(dateTimeString);
     497          psString dateString = psMemIncrRefCounter(psListGet(dateTime, PS_LIST_HEAD)); // The date string
     498          psFree (dateTime);
     499
     500          if (!psStringSubstitute(&string, dateString, "{FPA.DATE}")) {
     501              psError(PS_ERR_UNKNOWN, false, "Unable to replace concept %s", concept);
     502              psFree(string);
     503              psFree(dateString);
     504              return NULL;
     505          }
     506          psFree (dateString);
     507          continue;
     508        }
    510509
    511510        psTrace("psModules.concepts", 7, "Interpolating concept %s", concept);
  • branches/eam_branches/20090715/psModules/src/concepts/pmConceptsStandard.c

    r24419 r25407  
    429429        }
    430430
    431         psString ra = psMetadataLookupStr(&mdok, formats, "FPA.RA"); // Format for RA
    432         psString dec = psMetadataLookupStr(&mdok, formats, "FPA.DEC"); // Format for Dec
    433         if (ra && strcasecmp(ra, "HOURS") == 0 && dec && strcasecmp(dec, "DEGREES") == 0) {
    434             sexagesimal = true;
     431        if (strcmp(concept->name, "FPA.RA") == 0 || strcmp(concept->name, "FPA.DEC") == 0) {
     432            psString ra = psMetadataLookupStr(&mdok, formats, "FPA.RA"); // Format for RA
     433            psString dec = psMetadataLookupStr(&mdok, formats, "FPA.DEC"); // Format for Dec
     434            if (ra && strcasecmp(ra, "HOURS") == 0 && dec && strcasecmp(dec, "DEGREES") == 0) {
     435                sexagesimal = true;
     436            }
    435437        }
    436438    } else {
     
    450452        small = 3600.0 * coords;
    451453        small = (float)((int)(small * 1000.0)) / 1000.0;
    452         if (negative) {
    453             big *= -1;
    454         }
    455454        psString coordString = NULL;        // String with the coordinates in sexagesimal format
    456         psStringAppend(&coordString, "%d:%02d:%06.3f", big, medium, small);
     455        psStringAppend(&coordString, "%s%02d:%02d:%06.3f",
     456                       negative ? "-" : (strcmp(concept->name, "FPA.DEC") == 0 ? "+" : ""),
     457                       big, medium, small);
    457458        coordItem = psMetadataItemAllocStr(concept->name, concept->comment, coordString);
    458459        psFree(coordString);
  • branches/eam_branches/20090715/psModules/src/imcombine/pmPSFEnvelope.c

    r24622 r25407  
    124124        pmResiduals *resid = psf->residuals;// PSF residuals
    125125        psf->residuals = NULL;
    126         if (!pmReadoutFakeFromSources(fakeRO, fakeSize, fakeSize, fakes, xOffset, yOffset, psf,
     126        if (!pmReadoutFakeFromSources(fakeRO, fakeSize, fakeSize, fakes, 0, xOffset, yOffset, psf,
    127127                                      NAN, radius, true, true)) {
    128128            psError(PS_ERR_UNKNOWN, false, "Unable to generate fake readout.");
     
    298298        }
    299299
    300         // measure the source moments: tophat windowing, no pixel S/N cutoff
     300        // measure the source moments: tophat windowing, no pixel S/N cutoff
    301301        if (!pmSourceMoments(source, maxRadius, 0.0, 1.0)) {
    302302            // Can't do anything about it; limp along as best we can
  • branches/eam_branches/20090715/psModules/src/imcombine/pmStack.c

    r23775 r25407  
    3030#define PIXEL_LIST_BUFFER 100           // Number of entries to add to pixel list at a time
    3131#define PIXEL_MAP_BUFFER 2              // Number of entries to add to pixel map at a time
    32 #define ADD_VARIANCE                    // Allow additional variance (besides variance factor)?
     32//#define ADD_VARIANCE                    // Allow additional variance (besides variance factor)?
    3333#define NUM_DIRECT_STDEV 5              // For less than this number of values, measure stdev directly
    3434
  • branches/eam_branches/20090715/psModules/src/imcombine/pmSubtraction.c

    r24298 r25407  
    733733
    734734int pmSubtractionRejectStamps(pmSubtractionKernels *kernels, pmSubtractionStampList *stamps,
    735                               const psVector *deviations, psImage *subMask, float sigmaRej, int footprint)
     735                              const psVector *deviations, psImage *subMask, float sigmaRej)
    736736{
    737737    PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, false);
     
    821821    ds9num++;
    822822
     823    int footprint = stamps->footprint;  // Half-size of stamp region of interest
    823824    int numRejected = 0;                // Number of stamps rejected
    824825    int numGood = 0;                    // Number of good stamps
     
    956957    PS_ASSERT_FLOAT_WITHIN_RANGE(y, -1.0, 1.0, NULL);
    957958
    958     psArray *images = psArrayAlloc(solution->n - 1); // Images of each kernel to return
    959     psVector *fakeSolution = psVectorAlloc(solution->n, PS_TYPE_F64); // Fake solution vector
     959    psArray *images = psArrayAlloc(kernels->solution1->n - 1); // Images of each kernel to return
     960    psVector *fakeSolution = psVectorAlloc(kernels->solution1->n, PS_TYPE_F64); // Fake solution vector
    960961    psVectorInit(fakeSolution, 0.0);
    961962
    962     for (int i = 0; i < solution->n - 1; i++) {
    963         fakeSolution->data.F64[i] = solution->data.F64[i];
     963    for (int i = 0; i < kernels->solution1->n - 1; i++) {
     964        fakeSolution->data.F64[i] = kernels->solution1->data.F64[i];
    964965        images->data[i] = pmSubtractionKernelImage(kernels, x, y, wantDual);
    965966        fakeSolution->data.F64[i] = 0.0;
  • branches/eam_branches/20090715/psModules/src/imcombine/pmSubtraction.h

    r21363 r25407  
    6868                              const psVector *deviations, ///< Deviations for each stamp
    6969                              psImage *subMask, ///< Subtraction mask
    70                               float sigmaRej, ///< Number of RMS deviations above zero at which to reject
    71                               int footprint ///< Half-size of stamp
     70                              float sigmaRej ///< Number of RMS deviations above zero at which to reject
    7271    );
    7372
     
    9493
    9594/// Generate images of the convolution kernel elements
    96 psArray *pmSubtractionKernelSolutions(const psVector *solution, ///< Solution vector
    97                                       const pmSubtractionKernels *kernels, ///< Kernel parameters
    98                                       float x, float y ///< Normalised position [-1,1] for images
     95psArray *pmSubtractionKernelSolutions(const pmSubtractionKernels *kernels, ///< Kernel parameters
     96                                      float x, float y, ///< Normalised position [-1,1] for images
     97                                      bool wantDual ///< Calculate for the dual kernel?
    9998    );
     99
    100100
    101101/// Execute a thread job to convolve a patch of the image
  • branches/eam_branches/20090715/psModules/src/imcombine/pmSubtractionAnalysis.c

    r23780 r25407  
    1717
    1818
    19 bool pmSubtractionAnalysis(psMetadata *analysis, pmSubtractionKernels *kernels, psRegion *region,
     19bool pmSubtractionAnalysis(psMetadata *analysis, psMetadata *header,
     20                           pmSubtractionKernels *kernels, psRegion *region,
    2021                           int numCols, int numRows)
    2122{
    22     if (analysis) {
    23         PS_ASSERT_METADATA_NON_NULL(analysis, false);
    24     }
     23    PS_ASSERT_METADATA_NON_NULL(analysis, false);
     24    PS_ASSERT_METADATA_NON_NULL(header, false);
    2525    PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, false);
    2626    PM_ASSERT_SUBTRACTION_KERNELS_SOLUTION(kernels, false);
     
    3838                         PS_DATA_REGION | PS_META_DUPLICATE_OK,
    3939                         "Region over which subtraction was performed", subRegion);
     40
     41        psString string = psRegionToString(*subRegion);
    4042        psFree(subRegion);
     43
     44        psMetadataAddStr(header, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_REGION, PS_META_DUPLICATE_OK,
     45                         "Region over which subtraction was performed", string);
     46        psFree(string);
    4147    }
    4248
     
    4551                     PS_DATA_UNKNOWN | PS_META_DUPLICATE_OK, "Subtraction kernels", kernels);
    4652    psMetadataAddS32(analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_MODE,
    47                      PS_META_DUPLICATE_OK, "Subtraction kernels", kernels->mode);
     53                     PS_META_DUPLICATE_OK, "Subtraction mode", kernels->mode);
     54    psMetadataAddS32(header, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_MODE,
     55                     PS_META_DUPLICATE_OK, "Subtraction mode", kernels->mode);
    4856
    4957    // Realisations of kernel
     
    113121    {
    114122        psMetadata *header = psMetadataAlloc(); // Header
    115         for (int i = 0; i < solution->n; i++) {
     123        for (int i = 0; i < kernels->solution1->n; i++) {
    116124            psString name = NULL;       // Header keyword
    117125            psStringAppend(&name, "SOLN%04d", i);
    118             psMetadataAddF64(header, PS_LIST_TAIL, name, 0, NULL, solution->data.F64[i]);
     126            psMetadataAddF64(header, PS_LIST_TAIL, name, 0, NULL, kernels->solution1->data.F64[i]);
    119127            psFree(name);
    120128        }
    121         psArray *kernelImages = pmSubtractionKernelSolutions(solution, kernels, 0.0, 0.0);
     129        psArray *kernelImages = pmSubtractionKernelSolutions(kernels, 0.0, 0.0, false);
    122130        psFits *kernelFile = psFitsOpen("kernels.fits", "w");
    123131        (void)psFitsWriteImageCube(kernelFile, header, kernelImages, NULL);
     
    128136#endif
    129137
    130 
    131     // Set the variance factors
    132     float vf1 = 1.0, vf2 = 1.0;         // Variance factors for each image
    133     switch (kernels->mode) {
    134       case PM_SUBTRACTION_MODE_1:
    135         vf1 = pmSubtractionVarianceFactor(kernels, 0.5, 0.5, false);
    136         break;
    137       case PM_SUBTRACTION_MODE_2:
    138         vf2 = pmSubtractionVarianceFactor(kernels, 0.5, 0.5, false);
    139         break;
    140       case PM_SUBTRACTION_MODE_DUAL:
    141         vf1 = pmSubtractionVarianceFactor(kernels, 0.5, 0.5, false);
    142         vf2 = pmSubtractionVarianceFactor(kernels, 0.5, 0.5, true);
    143         break;
    144       default:
    145         psAbort("Invalid subtraction mode: %x", kernels->mode);
    146     }
    147 
    148     // Weight by the area
    149     if (region) {
    150         float norm = (region->x1 - region->x0 + 1) * (region->y1 - region->y0 + 1) / (numCols * numRows);
    151         vf1 *= norm;
    152         vf2 *= norm;
    153     }
    154 
    155     // Update the variance factor
    156 #define UPDATE_VARFACTOR(VF, ANALYSIS) { \
    157     psMetadataItem *vfItem = psMetadataLookup(analysis, ANALYSIS); \
    158     if (vfItem) { \
    159         psAssert(vfItem->type == PS_TYPE_F32, "Should be the type we said."); \
    160         vfItem->data.F32 += VF; \
    161     } else { \
    162         psMetadataAddF32(analysis, PS_LIST_TAIL, ANALYSIS, 0, "Variance factor weighted by the area", VF); \
    163     } \
    164 }
    165 
    166     UPDATE_VARFACTOR(vf1, PM_SUBTRACTION_ANALYSIS_VARFACTOR_1);
    167     UPDATE_VARFACTOR(vf2, PM_SUBTRACTION_ANALYSIS_VARFACTOR_2);
    168138
    169139    // Kernel shape
     
    201171        psFree(image);
    202172
    203         psMetadataItem *item = psMetadataLookup(analysis, PM_SUBTRACTION_ANALYSIS_DECONV_MAX); // Previous
    204         if (item) {
    205             item->data.F32 = PS_MAX(item->data.F32, max);
    206         } else {
    207             psMetadataAddF32(analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_DECONV_MAX, 0,
    208                              "Maximum deconvolution fraction", max);
     173        {
     174            psMetadataItem *item = psMetadataLookup(analysis, PM_SUBTRACTION_ANALYSIS_DECONV_MAX); // Previous
     175            if (item) {
     176                max = item->data.F32 = PS_MAX(item->data.F32, max);
     177            } else {
     178                psMetadataAddF32(analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_DECONV_MAX, 0,
     179                                 "Maximum deconvolution fraction", max);
     180            }
     181        }
     182
     183        {
     184            psMetadataItem *item = psMetadataLookup(header, PM_SUBTRACTION_ANALYSIS_DECONV_MAX); // Previous
     185            if (item) {
     186                item->data.F32 = max;
     187            } else {
     188                psMetadataAddF32(header, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_DECONV_MAX, 0,
     189                                 "Maximum deconvolution fraction", max);
     190            }
    209191        }
    210192    }
     
    254236        psMetadataAddF32(analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_MYY,
    255237                         PS_META_DUPLICATE_OK, "Moment in yy", m02);
     238
     239        psMetadataAddF32(header, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_NORM,
     240                         PS_META_DUPLICATE_OK, "Normalisation", m00);
     241        psMetadataAddF32(header, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_MX,
     242                         PS_META_DUPLICATE_OK, "Moment in x", m10);
     243        psMetadataAddF32(header, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_MY,
     244                         PS_META_DUPLICATE_OK, "Moment in y", m01);
     245        psMetadataAddF32(header, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_MXX,
     246                         PS_META_DUPLICATE_OK, "Moment in xx", m20);
     247        psMetadataAddF32(header, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_MXY,
     248                         PS_META_DUPLICATE_OK, "Moment in xy", m11);
     249        psMetadataAddF32(header, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_MYY,
     250                         PS_META_DUPLICATE_OK, "Moment in yy", m02);
    256251    }
    257252
     
    263258
    264259        psMetadataAddF32(analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_BGDIFF,
     260                         PS_META_DUPLICATE_OK, "Background difference", bg);
     261        psMetadataAddF32(header, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_BGDIFF,
    265262                         PS_META_DUPLICATE_OK, "Background difference", bg);
    266263        psFree(polyValues);
     
    275272        psMetadataAddF32(analysis, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_DEV_RMS, 0, "RMS stamp deviation",
    276273                         kernels->rms);
     274
     275        psMetadataAddS32(header, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_STAMPS, 0, "Number of stamps",
     276                         kernels->numStamps);
     277        psMetadataAddF32(header, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_DEV_MEAN, 0, "Mean stamp deviation",
     278                         kernels->mean);
     279        psMetadataAddF32(header, PS_LIST_TAIL, PM_SUBTRACTION_ANALYSIS_DEV_RMS, 0, "RMS stamp deviation",
     280                         kernels->rms);
    277281    }
    278282
  • branches/eam_branches/20090715/psModules/src/imcombine/pmSubtractionAnalysis.h

    r21149 r25407  
    2727bool pmSubtractionAnalysis(
    2828    psMetadata *analysis,               ///< Metadata container for QA information
     29    psMetadata *header,                 ///< Metadata container for QA information to put in header
    2930    pmSubtractionKernels *kernels,      ///< Kernels
    3031    psRegion *region,                   ///< Region for subtraction
  • branches/eam_branches/20090715/psModules/src/imcombine/pmSubtractionKernels.c

    r24296 r25407  
    765765    return PM_SUBTRACTION_KERNEL_NONE;
    766766}
     767
     768pmSubtractionKernels *pmSubtractionKernelsCopy(const pmSubtractionKernels *in)
     769{
     770    PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(in, NULL);
     771
     772    pmSubtractionKernels *out = psAlloc(sizeof(pmSubtractionKernels)); // Kernels, to return
     773    psMemSetDeallocator(out, (psFreeFunc)subtractionKernelsFree);
     774
     775    out->type = in->type;
     776    out->description = psMemIncrRefCounter(in->description);
     777    out->num = in->num;
     778    out->u = psMemIncrRefCounter(in->u);
     779    out->v = psMemIncrRefCounter(in->v);
     780    out->widths = psMemIncrRefCounter(in->widths);
     781    out->preCalc = psMemIncrRefCounter(in->preCalc);
     782    out->penalty = in->penalty;
     783    out->penalties = psMemIncrRefCounter(in->penalties);
     784    out->uStop = psMemIncrRefCounter(in->uStop);
     785    out->vStop = psMemIncrRefCounter(in->vStop);
     786    out->size = in->size;
     787    out->inner = in->inner;
     788    out->spatialOrder = in->spatialOrder;
     789    out->bgOrder = in->bgOrder;
     790    out->mode = in->mode;
     791    out->numCols = in->numCols;
     792    out->numRows = in->numRows;
     793    out->solution1 = in->solution1 ? psVectorCopy(NULL, in->solution1, PS_TYPE_F64) : NULL;
     794    out->solution2 = in->solution2 ? psVectorCopy(NULL, in->solution2, PS_TYPE_F64) : NULL;
     795
     796    return out;
     797}
  • branches/eam_branches/20090715/psModules/src/imcombine/pmSubtractionKernels.h

    r20049 r25407  
    203203    );
    204204
     205/// Copy kernels
     206///
     207/// A deep copy is performed on the solution only; the other components are merely pointers.
     208pmSubtractionKernels *pmSubtractionKernelsCopy(
     209    const pmSubtractionKernels *in      // Kernels to copy
     210    );
     211
    205212
    206213#endif
  • branches/eam_branches/20090715/psModules/src/imcombine/pmSubtractionMatch.c

    r24292 r25407  
    1010#include "pmHDU.h"
    1111#include "pmFPA.h"
     12#include "pmHDUUtils.h"
    1213#include "pmSubtractionParams.h"
    1314#include "pmSubtractionKernels.h"
     
    5859
    5960
    60 static bool getStamps(pmSubtractionStampList **stamps, // Stamps to read
    61                       const pmReadout *ro1, // Readout 1
    62                       const pmReadout *ro2, // Readout 2
    63                       const psImage *subMask, // Mask for subtraction, or NULL
    64                       psImage *variance,  // Variance map
    65                       const psRegion *region, // Region of interest, or NULL
    66                       float thresh1,  // Threshold for stamp finding on readout 1
    67                       float thresh2,  // Threshold for stamp finding on readout 2
    68                       float stampSpacing, // Spacing between stamps
    69                       int size,         // Kernel half-size
    70                       int footprint,     // Convolution footprint for stamps
    71                       pmSubtractionMode mode // Mode for subtraction
     61static bool subtractionGetStamps(pmSubtractionStampList **stamps, // Stamps to read
     62                                 const pmReadout *ro1, // Readout 1
     63                                 const pmReadout *ro2, // Readout 2
     64                                 const psImage *subMask, // Mask for subtraction, or NULL
     65                                 psImage *variance,  // Variance map
     66                                 const psRegion *region, // Region of interest, or NULL
     67                                 float thresh1,  // Threshold for stamp finding on readout 1
     68                                 float thresh2,  // Threshold for stamp finding on readout 2
     69                                 float stampSpacing, // Spacing between stamps
     70                                 int size,         // Kernel half-size
     71                                 int footprint,     // Convolution footprint for stamps
     72                                 pmSubtractionMode mode // Mode for subtraction
    7273    )
    7374{
     
    163164}
    164165
     166static void subtractionAnalysisUpdate(pmReadout *conv1, pmReadout *conv2, // Convolved images
     167                                      const psMetadata *analysis, // Analysis metadata
     168                                      const psMetadata *header // Header metadata
     169    )
     170{
     171    if (conv1) {
     172        conv1->analysis = psMetadataCopy(conv1->analysis, analysis);
     173    }
     174    if (conv2) {
     175        conv2->analysis = psMetadataCopy(conv2->analysis, analysis);
     176    }
     177
     178    if (conv1 && conv1->parent) {
     179        pmHDU *hdu = pmHDUFromCell(conv1->parent);
     180        if (hdu) {
     181            hdu->header = psMetadataCopy(hdu->header, header);
     182        }
     183    }
     184    if (conv2 && conv2->parent) {
     185        pmHDU *hdu = pmHDUFromCell(conv2->parent);
     186        if (hdu) {
     187            hdu->header = psMetadataCopy(hdu->header, header);
     188        }
     189    }
     190
     191    return;
     192}
    165193
    166194
     
    253281
    254282    psMetadata *outAnalysis = psMetadataAlloc(); // Output analysis values
     283    psMetadata *outHeader = psMetadataAlloc(); // Output header values
    255284
    256285    psTrace("psModules.imcombine", 2, "Convolving...\n");
     
    259288        psRegion *region = regions->data[i]; // Region of interest
    260289
    261         if (!pmSubtractionAnalysis(outAnalysis, kernel, region, ro1->image->numCols, ro1->image->numRows)) {
     290        if (!pmSubtractionAnalysis(outAnalysis, outHeader, kernel, region,
     291                                   ro1->image->numCols, ro1->image->numRows)) {
    262292            psError(PS_ERR_UNKNOWN, false, "Unable to generate QA data");
    263293            psFree(outAnalysis);
     294            psFree(outHeader);
    264295            psFree(subMask);
    265296            psFree(kernels);
     
    272303            psError(PS_ERR_UNKNOWN, false, "Unable to convolve image.");
    273304            psFree(outAnalysis);
     305            psFree(outHeader);
    274306            psFree(subMask);
    275307            psFree(kernels);
     
    283315    psFree(regions);
    284316
    285     if (conv1) {
    286         psMetadataCopy(conv1->analysis, outAnalysis);
    287     }
    288     if (conv2) {
    289         psMetadataCopy(conv2->analysis, outAnalysis);
    290     }
     317    subtractionAnalysisUpdate(conv1, conv2, outAnalysis, outHeader);
    291318    psFree(outAnalysis);
     319    psFree(outHeader);
    292320
    293321    return true;
     
    369397    pmSubtractionKernels *kernels = NULL; // Kernel basis functions
    370398    psMetadata *analysis = psMetadataAlloc(); // QA data
     399    psMetadata *header = psMetadataAlloc(); // QA data for header
    371400
    372401    int numCols = ro1->image->numCols, numRows = ro1->image->numRows; // Image dimensions
     
    442471            // We get the stamps here; we will also attempt to get stamps at the first iteration, but it
    443472            // doesn't matter.
    444             if (!getStamps(&stamps, ro1, ro2, subMask, variance, NULL, stampThresh1, stampThresh2,
     473            if (!subtractionGetStamps(&stamps, ro1, ro2, subMask, variance, NULL, stampThresh1, stampThresh2,
    445474                           stampSpacing, size, footprint, subMode)) {
    446475                goto MATCH_ERROR;
    447476            }
    448477
     478
     479            // Define kernel basis functions
     480            if (optimum && (type == PM_SUBTRACTION_KERNEL_ISIS || type == PM_SUBTRACTION_KERNEL_GUNK)) {
     481                kernels = pmSubtractionKernelsOptimumISIS(type, size, inner, spatialOrder, optFWHMs, optOrder,
     482                                                          stamps, footprint, optThreshold, penalty, subMode);
     483                if (!kernels) {
     484                    psErrorClear();
     485                    psWarning("Unable to derive optimum ISIS kernel --- switching to default.");
     486                }
     487            }
     488            if (kernels == NULL) {
     489                // Not an ISIS/GUNK kernel, or the optimum kernel search failed
     490                kernels = pmSubtractionKernelsGenerate(type, size, spatialOrder, isisWidths, isisOrders,
     491                                                       inner, binning, ringsOrder, penalty, subMode);
     492            }
     493
     494            memCheck("kernels");
     495
    449496            if (subMode == PM_SUBTRACTION_MODE_UNSURE) {
     497#if 0
    450498                // Get backgrounds
    451499                psStats *bgStats = psStatsAlloc(BG_STAT); // Statistics for background
     
    469517
    470518                pmSubtractionMode newMode = pmSubtractionOrder(stamps, bg1, bg2); // Subtraction mode to use
     519#endif
     520                pmSubtractionMode newMode = pmSubtractionBestMode(&stamps, &kernels, subMask, rej);
    471521                switch (newMode) {
    472522                  case PM_SUBTRACTION_MODE_1:
     
    483533            }
    484534
    485             // Define kernel basis functions
    486             if (optimum && (type == PM_SUBTRACTION_KERNEL_ISIS || type == PM_SUBTRACTION_KERNEL_GUNK)) {
    487                 kernels = pmSubtractionKernelsOptimumISIS(type, size, inner, spatialOrder, optFWHMs, optOrder,
    488                                                           stamps, footprint, optThreshold, penalty, subMode);
    489                 if (!kernels) {
    490                     psErrorClear();
    491                     psWarning("Unable to derive optimum ISIS kernel --- switching to default.");
    492                 }
    493             }
    494             if (kernels == NULL) {
    495                 // Not an ISIS/GUNK kernel, or the optimum kernel search failed
    496                 kernels = pmSubtractionKernelsGenerate(type, size, spatialOrder, isisWidths, isisOrders,
    497                                                        inner, binning, ringsOrder, penalty, subMode);
    498             }
    499 
    500             memCheck("kernels");
    501 
    502535            int numRejected = -1;       // Number of rejected stamps in each iteration
    503536            for (int k = 0; k < iter && numRejected != 0; k++) {
    504537                psLogMsg("psModules.imcombine", PS_LOG_INFO, "Iteration %d.", k);
    505538
    506                 if (!getStamps(&stamps, ro1, ro2, subMask, variance, region, stampThresh1, stampThresh2,
    507                                stampSpacing, size, footprint, subMode)) {
     539                if (!subtractionGetStamps(&stamps, ro1, ro2, subMask, variance, region,
     540                                          stampThresh1, stampThresh2, stampSpacing,
     541                                          size, footprint, subMode)) {
    508542                    goto MATCH_ERROR;
    509543                }
     
    535569
    536570                psTrace("psModules.imcombine", 3, "Rejecting stamps...\n");
    537                 numRejected = pmSubtractionRejectStamps(kernels, stamps, deviations, subMask, rej, footprint);
     571                numRejected = pmSubtractionRejectStamps(kernels, stamps, deviations, subMask, rej);
    538572                if (numRejected < 0) {
    539573                    psError(PS_ERR_UNKNOWN, false, "Unable to reject stamps.");
     
    557591                    goto MATCH_ERROR;
    558592                }
    559                 pmSubtractionRejectStamps(kernels, stamps, deviations, subMask, NAN, footprint);
     593                pmSubtractionRejectStamps(kernels, stamps, deviations, subMask, NAN);
    560594                psFree(deviations);
    561595            }
     
    565599            memCheck("solution");
    566600
    567             if (!pmSubtractionAnalysis(analysis, kernels, region, numCols, numRows)) {
     601            if (!pmSubtractionAnalysis(analysis, header, kernels, region, numCols, numRows)) {
    568602                psError(PS_ERR_UNKNOWN, false, "Unable to generate QA data");
    569603                goto MATCH_ERROR;
     
    601635    memCheck("convolution");
    602636
    603     if (conv1) {
    604         psMetadataCopy(conv1->analysis, analysis);
    605     }
    606     if (conv2) {
    607         psMetadataCopy(conv2->analysis, analysis);
    608     }
     637    subtractionAnalysisUpdate(conv1, conv2, analysis, header);
    609638    psFree(analysis);
     639    psFree(header);
    610640
    611641#ifdef TESTING
     
    629659MATCH_ERROR:
    630660    psFree(analysis);
     661    psFree(header);
    631662    psFree(region);
    632663    psFree(regionString);
     
    842873    return mode;
    843874}
     875
     876
     877// Test a subtraction mode by performing a single iteration
     878static bool subtractionModeTest(pmSubtractionStampList *stamps, // Stamps to use to find best mode
     879                                pmSubtractionKernels *kernels, // Kernel description
     880                                const char *description, // Description for trace
     881                                psImage *subMask,  // Subtraction mask
     882                                float rej               // Rejection threshold
     883                                )
     884{
     885    assert(stamps);
     886    assert(kernels);
     887
     888    psTrace("psModules.imcombine", 3, "Calculating %s equation...\n", description);
     889    if (!pmSubtractionCalculateEquation(stamps, kernels)) {
     890        psError(PS_ERR_UNKNOWN, false, "Unable to calculate least-squares equation.");
     891        return false;
     892    }
     893
     894    psTrace("psModules.imcombine", 3, "Solving %s equation...\n", description);
     895    if (!pmSubtractionSolveEquation(kernels, stamps)) {
     896        psError(PS_ERR_UNKNOWN, false, "Unable to calculate least-squares equation.");
     897        return false;
     898    }
     899
     900    psTrace("psModules.imcombine", 3, "Calculate %s deviations...\n", description);
     901    psVector *deviations = pmSubtractionCalculateDeviations(stamps, kernels); // Stamp deviations
     902    if (!deviations) {
     903        psError(PS_ERR_UNKNOWN, false, "Unable to calculate deviations.");
     904        return false;
     905    }
     906
     907    psTrace("psModules.imcombine", 3, "Rejecting %s stamps...\n", description);
     908    long numRejected = pmSubtractionRejectStamps(kernels, stamps, deviations, subMask, rej);
     909    if (numRejected < 0) {
     910        psError(PS_ERR_UNKNOWN, false, "Unable to reject stamps.");
     911        psFree(deviations);
     912        return false;
     913    }
     914    psFree(deviations);
     915
     916    if (numRejected > 0) {
     917        // Allow re-fit with reduced stamps set
     918        psTrace("psModules.imcombine", 3, "Resolving %s equation...\n", description);
     919        if (!pmSubtractionSolveEquation(kernels, stamps)) {
     920            psError(PS_ERR_UNKNOWN, false, "Unable to calculate least-squares equation.");
     921            return false;
     922        }
     923        psTrace("psModules.imcombine", 3, "Recalculate %s deviations...\n", description);
     924        psVector *deviations = pmSubtractionCalculateDeviations(stamps, kernels); // Stamp deviations
     925        if (!deviations) {
     926            psError(PS_ERR_UNKNOWN, false, "Unable to calculate deviations.");
     927            return false;
     928        }
     929        psTrace("psModules.imcombine", 3, "Measuring %s quality...\n", description);
     930        long numRejected = pmSubtractionRejectStamps(kernels, stamps, deviations, subMask, NAN);
     931        if (numRejected < 0) {
     932            psError(PS_ERR_UNKNOWN, false, "Unable to reject stamps.");
     933            psFree(deviations);
     934            return false;
     935        }
     936        psFree(deviations);
     937    }
     938
     939    return true;
     940}
     941
     942
     943pmSubtractionMode pmSubtractionBestMode(pmSubtractionStampList **stamps, pmSubtractionKernels **kernels,
     944                                        const psImage *subMask, float rej)
     945{
     946    PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(*stamps, PM_SUBTRACTION_MODE_ERR);
     947    PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(*kernels, PM_SUBTRACTION_MODE_ERR);
     948
     949    // Copies of the inputs
     950    pmSubtractionStampList *stamps1 = pmSubtractionStampListCopy(*stamps);
     951    pmSubtractionKernels *kernels1 = pmSubtractionKernelsCopy(*kernels);
     952    psImage *subMask1 = psImageCopy(NULL, subMask, subMask->type.type);
     953    kernels1->mode = PM_SUBTRACTION_MODE_1;
     954
     955    if (!subtractionModeTest(stamps1, kernels1, "convolve 1", subMask1, rej)) {
     956        psError(PS_ERR_UNKNOWN, false, "Unable to test subtraction with convolution of image 1");
     957        psFree(stamps1);
     958        psFree(kernels1);
     959        psFree(subMask1);
     960        return PM_SUBTRACTION_MODE_ERR;
     961    }
     962    psFree(subMask1);
     963
     964    // Copies of the inputs
     965    pmSubtractionStampList *stamps2 = pmSubtractionStampListCopy(*stamps);
     966    pmSubtractionKernels *kernels2 = pmSubtractionKernelsCopy(*kernels);
     967    psImage *subMask2 = psImageCopy(NULL, subMask, subMask->type.type);
     968    kernels2->mode = PM_SUBTRACTION_MODE_2;
     969
     970    if (!subtractionModeTest(stamps2, kernels2, "convolve 2", subMask2, rej)) {
     971        psError(PS_ERR_UNKNOWN, false, "Unable to test subtraction with convolution of image 2");
     972        psFree(stamps2);
     973        psFree(kernels2);
     974        psFree(subMask2);
     975        psFree(stamps1);
     976        psFree(kernels1);
     977        return PM_SUBTRACTION_MODE_ERR;
     978    }
     979    psFree(subMask2);
     980
     981
     982    pmSubtractionStampList *bestStamps = NULL; // Best choice for stamps
     983    pmSubtractionKernels *bestKernels = NULL; // Best choice for kernels
     984    psLogMsg("psModules.imcombine", PS_LOG_INFO,
     985             "Image 1: %f +/- %f from %d stamps\nImage 2: %f +/- %f from %d stamps\n",
     986             kernels1->mean, kernels1->rms, kernels1->numStamps,
     987             kernels2->mean, kernels2->rms, kernels2->numStamps);
     988
     989    if (kernels1->mean < kernels2->mean) {
     990        bestStamps = stamps1;
     991        bestKernels = kernels1;
     992    } else {
     993        bestStamps = stamps2;
     994        bestKernels = kernels2;
     995    }
     996
     997    psFree(*stamps);
     998    psFree(*kernels);
     999    *stamps = psMemIncrRefCounter(bestStamps);
     1000    *kernels = psMemIncrRefCounter(bestKernels);
     1001
     1002    psFree(stamps1);
     1003    psFree(stamps2);
     1004    psFree(kernels1);
     1005    psFree(kernels2);
     1006
     1007    return bestKernels->mode;
     1008}
     1009
  • branches/eam_branches/20090715/psModules/src/imcombine/pmSubtractionMatch.h

    r23308 r25407  
    8383    );
    8484
     85/// Determine best subtraction mode to use
     86///
     87/// Subtractions are attempted each way, and the mode with the lower residual is taken to be the best
     88pmSubtractionMode pmSubtractionBestMode(
     89    pmSubtractionStampList **stamps,    ///< Stamps to use for solution
     90    pmSubtractionKernels **kernels,     ///< Kernels to use for solution
     91    const psImage *subMask,             ///< Subtraction mask
     92    float rej                           ///< Rejection threshold for stamps
     93    );
    8594
    8695#endif
  • branches/eam_branches/20090715/psModules/src/imcombine/pmSubtractionStamps.c

    r24066 r25407  
    225225}
    226226
     227pmSubtractionStampList *pmSubtractionStampListCopy(const pmSubtractionStampList *in)
     228{
     229    PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(in, NULL);
     230
     231    pmSubtractionStampList *out = psAlloc(sizeof(pmSubtractionStampList)); // Copied stamp list to return
     232    psMemSetDeallocator(out, (psFreeFunc)subtractionStampListFree);
     233
     234    int num = out->num = in->num;       // Number of stamps
     235    out->stamps = psArrayAlloc(num);
     236    out->regions = psArrayAlloc(num);
     237    out->x = NULL;
     238    out->y = NULL;
     239    out->flux = NULL;
     240    out->footprint = in->footprint;
     241
     242    for (int i = 0; i < num; i++) {
     243        psRegion *inRegion = in->regions->data[i]; // Input region
     244        out->regions->data[i] = psRegionAlloc(inRegion->x0, inRegion->x1, inRegion->y0, inRegion->y1);
     245
     246        pmSubtractionStamp *inStamp = in->stamps->data[i]; // Input stamp
     247        pmSubtractionStamp *outStamp = psAlloc(sizeof(pmSubtractionStamp));
     248        psMemSetDeallocator(outStamp, (psFreeFunc)subtractionStampFree);
     249        outStamp->x = inStamp->x;
     250        outStamp->y = inStamp->y;
     251        outStamp->flux = inStamp->flux;
     252        outStamp->xNorm = inStamp->xNorm;
     253        outStamp->yNorm = inStamp->yNorm;
     254        outStamp->status = inStamp->status;
     255
     256        outStamp->image1 = inStamp->image1 ? psKernelCopy(inStamp->image1) : NULL;
     257        outStamp->image2 = inStamp->image2 ? psKernelCopy(inStamp->image2) : NULL;
     258        outStamp->variance = inStamp->variance ? psKernelCopy(inStamp->variance) : NULL;
     259
     260        if (inStamp->convolutions1) {
     261            int size = inStamp->convolutions1->n; // Size of array
     262            outStamp->convolutions1 = psArrayAlloc(size);
     263            for (int j = 0; j < size; j++) {
     264                psKernel *conv = inStamp->convolutions1->data[j]; // Convolution
     265                outStamp->convolutions1->data[j] = conv ? psKernelCopy(conv) : NULL;
     266            }
     267        } else {
     268            outStamp->convolutions1 = NULL;
     269        }
     270        if (inStamp->convolutions2) {
     271            int size = inStamp->convolutions2->n; // Size of array
     272            outStamp->convolutions2 = psArrayAlloc(size);
     273            for (int j = 0; j < size; j++) {
     274                psKernel *conv = inStamp->convolutions2->data[j]; // Convolution
     275                outStamp->convolutions2->data[j] = conv ? psKernelCopy(conv) : NULL;
     276            }
     277        } else {
     278            outStamp->convolutions2 = NULL;
     279        }
     280
     281        outStamp->matrix1 = inStamp->matrix1 ? psImageCopy(NULL, inStamp->matrix1, PS_TYPE_F64) : NULL;
     282        outStamp->matrix2 = inStamp->matrix2 ? psImageCopy(NULL, inStamp->matrix2, PS_TYPE_F64) : NULL;
     283        outStamp->matrixX = inStamp->matrixX ? psImageCopy(NULL, inStamp->matrixX, PS_TYPE_F64) : NULL;
     284        outStamp->vector1 = inStamp->vector1 ? psVectorCopy(NULL, inStamp->vector1, PS_TYPE_F64) : NULL;
     285        outStamp->vector2 = inStamp->vector2 ? psVectorCopy(NULL, inStamp->vector2, PS_TYPE_F64) : NULL;
     286
     287        out->stamps->data[i] = outStamp;
     288    }
     289
     290    return out;
     291}
     292
    227293pmSubtractionStamp *pmSubtractionStampAlloc(void)
    228294{
  • branches/eam_branches/20090715/psModules/src/imcombine/pmSubtractionStamps.h

    r23937 r25407  
    5252    } \
    5353}
     54
     55/// Copy a list of stamps
     56///
     57/// A deep copy is performed of the stamp list and the component stamps
     58pmSubtractionStampList *pmSubtractionStampListCopy(
     59    const pmSubtractionStampList *in    // Stamp list to copy
     60    );
     61
    5462
    5563/// A stamp for image subtraction
  • branches/eam_branches/20090715/psModules/src/objects/Makefile.am

    r25022 r25407  
    5353        pmGrowthCurveGenerate.c \
    5454        pmGrowthCurve.c \
    55         pmSourceMatch.c
     55        pmSourceMatch.c \
     56        pmDetEff.c
    5657
    5758EXTRA_DIST = \
     
    9091        pmTrend2D.h \
    9192        pmGrowthCurve.h \
    92         pmSourceMatch.h
     93        pmSourceMatch.h \
     94        pmDetEff.h
    9395
    9496CLEANFILES = *~
  • branches/eam_branches/20090715/psModules/src/objects/pmSourceIO.c

    r24694 r25407  
    4242#include "pmSource.h"
    4343#include "pmModelClass.h"
     44#include "pmDetEff.h"
    4445#include "pmSourceIO.h"
    4546
    4647#define BLANK_HEADERS "BLANK.HEADERS"   // Name of metadata in camera configuration containing header names
    4748                                        // for putting values into a blank PHU
     49
     50// lookup the EXTNAME values used for table data and image header segments
     51static bool sourceExtensions(psString *headname, // Extension name for header
     52                             psString *dataname, // Extension name for data
     53                             psString *deteffname, // Extension name for detection efficiency
     54                             psString *xsrcname, // Extension name for extended sources
     55                             psString *xfitname, // Extension name for extended fits
     56                             const pmFPAfile *file, // File of interest
     57                             const pmFPAview *view // View to level of interest
     58                             )
     59{
     60    bool status;                        // Status of MD lookup
     61
     62    // Menu of EXTNAME rules
     63    psMetadata *menu = psMetadataLookupMetadata(&status, file->camera, "EXTNAME.RULES");
     64    if (!menu) {
     65        psError(PS_ERR_UNKNOWN, true, "missing EXTNAME.RULES in camera.config");
     66        return false;
     67    }
     68
     69    // EXTNAME for image header
     70    if (headname) {
     71        const char *rule = psMetadataLookupStr(&status, menu, "CMF.HEAD");
     72        if (!rule) {
     73            psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.HEAD in EXTNAME.RULES in camera.config");
     74            return false;
     75        }
     76        *headname = pmFPAfileNameFromRule(rule, file, view);
     77    }
     78
     79    // EXTNAME for table data
     80    if (dataname) {
     81        const char *rule = psMetadataLookupStr(&status, menu, "CMF.DATA");
     82        if (!rule) {
     83            psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.DATA in EXTNAME.RULES in camera.config");
     84            return false;
     85        }
     86        *dataname = pmFPAfileNameFromRule(rule, file, view);
     87    }
     88
     89    // EXTNAME for detection efficiency
     90    if (deteffname) {
     91        const char *rule = psMetadataLookupStr(&status, menu, "CMF.DETEFF");
     92        if (!rule) {
     93            psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.DETEFF in EXTNAME.RULES in camera.config");
     94            return false;
     95        }
     96        *deteffname = pmFPAfileNameFromRule(rule, file, view);
     97    }
     98
     99    // EXTNAME for extended source data table
     100    if (xsrcname) {
     101        const char *rule = psMetadataLookupStr(&status, menu, "CMF.XSRC");
     102        if (!rule) {
     103            psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.XSRC in EXTNAME.RULES in camera.config");
     104            return false;
     105        }
     106        *xsrcname = pmFPAfileNameFromRule (rule, file, view);
     107    }
     108
     109    if (xfitname) {
     110        // EXTNAME for extended source data table
     111        const char *rule = psMetadataLookupStr(&status, menu, "CMF.XFIT");
     112        if (!rule) {
     113            psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.XFIT in EXTNAME.RULES in camera.config");
     114            return false;
     115        }
     116        *xfitname = pmFPAfileNameFromRule (rule, file, view);
     117    }
     118
     119    return true;
     120}
     121
    48122
    49123// translations between psphot object types and dophot object types
     
    271345
    272346    char *exttype  = NULL;
    273     char *dataname = NULL;
    274     char *xsrcname = NULL;
    275     char *xfitname = NULL;
    276     char *headname = NULL;
    277347
    278348    // if sources is NULL, write out an empty table
     
    354424
    355425        // define the EXTNAME values for the different data segments:
    356         {
    357             // lookup the EXTNAME values used for table data and image header segments
    358             char *rule = NULL;
    359 
    360             // Menu of EXTNAME rules
    361             psMetadata *menu = psMetadataLookupMetadata(&status, file->camera, "EXTNAME.RULES");
    362             if (!menu) {
    363                 psError(PS_ERR_UNKNOWN, true, "missing EXTNAME.RULES in camera.config");
    364                 return false;
    365             }
    366 
    367             // EXTNAME for image header
    368             rule = psMetadataLookupStr(&status, menu, "CMF.HEAD");
    369             if (!rule) {
    370                 psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.HEAD in EXTNAME.RULES in camera.config");
    371                 return false;
    372             }
    373             headname = pmFPAfileNameFromRule (rule, file, view);
    374 
    375             // EXTNAME for table data
    376             rule = psMetadataLookupStr(&status, menu, "CMF.DATA");
    377             if (!rule) {
    378                 psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.DATA in EXTNAME.RULES in camera.config");
    379                 return false;
    380             }
    381             dataname = pmFPAfileNameFromRule (rule, file, view);
    382 
    383             if (XSRC_OUTPUT) {
    384               // EXTNAME for extended source data table
    385               rule = psMetadataLookupStr(&status, menu, "CMF.XSRC");
    386               if (!rule) {
    387                 psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.XSRC in EXTNAME.RULES in camera.config");
    388                 return false;
    389               }
    390               xsrcname = pmFPAfileNameFromRule (rule, file, view);
    391             }
    392             if (XFIT_OUTPUT) {
    393               // EXTNAME for extended source data table
    394               rule = psMetadataLookupStr(&status, menu, "CMF.XFIT");
    395               if (!rule) {
    396                 psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.XFIT in EXTNAME.RULES in camera.config");
    397                 return false;
    398               }
    399               xfitname = pmFPAfileNameFromRule (rule, file, view);
    400             }
     426        psString headname = NULL;
     427        psString dataname = NULL;
     428        psString deteffname = NULL;
     429        psString xsrcname = NULL;
     430        psString xfitname = NULL;
     431        if (!sourceExtensions(&headname, &dataname, &deteffname, XSRC_OUTPUT ? &xsrcname : NULL,
     432                              XFIT_OUTPUT ? &xfitname : NULL, file, view)) {
     433            return false;
    401434        }
    402435
     
    480513
    481514            // XXX these are case-sensitive since the EXTYPE is case-sensitive
    482             status = false;
     515            status = true;
    483516            if (!strcmp (exttype, "SMPDATA")) {
    484                 status = pmSourcesWrite_SMPDATA (file->fits, sources, file->header, outhead, dataname);
     517                status &= pmSourcesWrite_SMPDATA (file->fits, sources, file->header, outhead, dataname);
    485518            }
    486519            if (!strcmp (exttype, "PS1_DEV_0")) {
    487                 status = pmSourcesWrite_PS1_DEV_0 (file->fits, sources, file->header, outhead, dataname);
     520                status &= pmSourcesWrite_PS1_DEV_0 (file->fits, sources, file->header, outhead, dataname);
    488521            }
    489522            if (!strcmp (exttype, "PS1_DEV_1")) {
    490                 status = pmSourcesWrite_PS1_DEV_1 (file->fits, sources, file->header, outhead, dataname);
     523                status &= pmSourcesWrite_PS1_DEV_1 (file->fits, sources, file->header, outhead, dataname);
    491524            }
    492525            if (!strcmp (exttype, "PS1_CAL_0")) {
    493                 status = pmSourcesWrite_PS1_CAL_0 (file->fits, readout, sources, file->header, outhead, dataname);
     526                status &= pmSourcesWrite_PS1_CAL_0 (file->fits, readout, sources, file->header, outhead, dataname);
    494527            }
    495528            if (!strcmp (exttype, "PS1_V1")) {
    496                 status = pmSourcesWrite_CMF_PS1_V1 (file->fits, readout, sources, file->header, outhead, dataname);
     529                status &= pmSourcesWrite_CMF_PS1_V1 (file->fits, readout, sources, file->header, outhead, dataname);
    497530            }
    498531            if (!strcmp (exttype, "PS1_V2")) {
    499                 status = pmSourcesWrite_CMF_PS1_V2 (file->fits, readout, sources, file->header, outhead, dataname);
    500             }
     532                status &= pmSourcesWrite_CMF_PS1_V2 (file->fits, readout, sources, file->header, outhead, dataname);
     533            }
     534
     535            if (deteffname) {
     536                status &= pmReadoutWriteDetEff(file->fits, readout, outhead, deteffname);
     537            }
     538
    501539            if (xsrcname) {
    502540              if (!strcmp (exttype, "PS1_DEV_1")) {
    503                   status = pmSourcesWrite_PS1_DEV_1_XSRC (file->fits, sources, xsrcname, recipe);
     541                  status &= pmSourcesWrite_PS1_DEV_1_XSRC (file->fits, sources, xsrcname, recipe);
    504542              }
    505543              if (!strcmp (exttype, "PS1_CAL_0")) {
    506                   status = pmSourcesWrite_PS1_CAL_0_XSRC (file->fits, readout, sources, file->header, xsrcname, recipe);
     544                  status &= pmSourcesWrite_PS1_CAL_0_XSRC (file->fits, readout, sources, file->header, xsrcname, recipe);
    507545              }
    508546              if (!strcmp (exttype, "PS1_V1")) {
    509                   status = pmSourcesWrite_CMF_PS1_V1_XSRC (file->fits, sources, xsrcname, recipe);
     547                  status &= pmSourcesWrite_CMF_PS1_V1_XSRC (file->fits, sources, xsrcname, recipe);
    510548              }
    511549              if (!strcmp (exttype, "PS1_V2")) {
    512                   status = pmSourcesWrite_CMF_PS1_V2_XSRC (file->fits, sources, xsrcname, recipe);
     550                  status &= pmSourcesWrite_CMF_PS1_V2_XSRC (file->fits, sources, xsrcname, recipe);
    513551              }
    514552            }
    515553            if (xfitname) {
    516554              if (!strcmp (exttype, "PS1_DEV_1")) {
    517                   status = pmSourcesWrite_PS1_DEV_1_XFIT (file->fits, sources, xfitname);
     555                  status &= pmSourcesWrite_PS1_DEV_1_XFIT (file->fits, sources, xfitname);
    518556              }
    519557              if (!strcmp (exttype, "PS1_CAL_0")) {
    520                   status = pmSourcesWrite_PS1_CAL_0_XFIT (file->fits, readout, sources, file->header, xfitname);
     558                  status &= pmSourcesWrite_PS1_CAL_0_XFIT (file->fits, readout, sources, file->header, xfitname);
    521559              }
    522560              if (!strcmp (exttype, "PS1_V1")) {
    523                   status = pmSourcesWrite_CMF_PS1_V1_XFIT (file->fits, sources, xfitname);
     561                  status &= pmSourcesWrite_CMF_PS1_V1_XFIT (file->fits, sources, xfitname);
    524562              }
    525563              if (!strcmp (exttype, "PS1_V2")) {
    526                   status = pmSourcesWrite_CMF_PS1_V2_XFIT (file->fits, sources, xfitname);
     564                  status &= pmSourcesWrite_CMF_PS1_V2_XFIT (file->fits, sources, xfitname);
    527565              }
    528566            }
     
    572610    // not needed if only one chip
    573611    if (file->fpa->chips->n == 1) {
    574         pmSourceIO_WriteMatchedRefs (file->fits, file->fpa, config);
    575         return true;
     612        pmSourceIO_WriteMatchedRefs (file->fits, file->fpa, config);
     613        return true;
    576614    }
    577615
     
    885923        hdu = pmFPAviewThisHDU (view, file->fpa);
    886924
    887         // lookup the EXTNAME values used for table data and image header segments
    888         char *rule = NULL;
    889         // Menu of EXTNAME rules
    890         psMetadata *menu = psMetadataLookupMetadata(&status, file->camera, "EXTNAME.RULES");
    891         if (!menu) {
    892             psError(PS_ERR_UNKNOWN, true, "missing EXTNAME.RULES in camera.config");
    893             return false;
    894         }
    895         // EXTNAME for image header
    896         rule = psMetadataLookupStr(&status, menu, "CMF.HEAD");
    897         if (!rule) {
    898             psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.HEAD in EXTNAME.RULES in camera.config");
    899             return false;
    900         }
    901         char *headname = pmFPAfileNameFromRule (rule, file, view);
    902         // EXTNAME for table data
    903         rule = psMetadataLookupStr(&status, menu, "CMF.DATA");
    904         if (!rule) {
    905             psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.DATA in EXTNAME.RULES in camera.config");
    906             return false;
    907         }
    908         char *dataname = pmFPAfileNameFromRule (rule, file, view);
     925        // define the EXTNAME values for the different data segments:
     926        psString headname = NULL;
     927        psString dataname = NULL;
     928        psString deteffname = NULL;
     929        if (!sourceExtensions(&headname, &dataname, &deteffname, NULL, NULL, file, view)) {
     930            return false;
     931        }
    909932
    910933        // advance to the IMAGE HEADER extension
     
    958981                sources = pmSourcesRead_CMF_PS1_V2 (file->fits, hdu->header);
    959982            }
     983
     984            if (!pmReadoutReadDetEff(file->fits, readout, deteffname)) {
     985                psError(PS_ERR_IO, false, "Unable to read detection efficiency");
     986                return false;
     987            }
    960988        }
    961989
     
    10701098}
    10711099
    1072    
     1100
  • branches/eam_branches/20090715/psModules/src/objects/pmSourceMatch.c

    r24262 r25407  
    221221        } else {
    222222            // Match with the master list
    223             psTree *tree = psTreePlant(2, SOURCES_MAX_LEAF, xMaster, yMaster); // kd Tree with sources
     223            psTree *tree = psTreePlant(2, SOURCES_MAX_LEAF, PS_TREE_EUCLIDEAN, xMaster, yMaster); // kd Tree
    224224            long numMatch = 0;          // Number of matches
    225225
  • branches/eam_branches/20090715/psModules/src/psmodules.h

    r25022 r25407  
    133133#include <pmSourceVisual.h>
    134134#include <pmSourceMatch.h>
     135#include <pmDetEff.h>
    135136
    136137// The following headers are from random locations, here because they cross bounds
Note: See TracChangeset for help on using the changeset viewer.