Changeset 27876
- Timestamp:
- May 6, 2010, 8:02:38 PM (16 years ago)
- Location:
- branches/eam_branches/psphot.20100506
- Files:
-
- 2 added
- 10 edited
-
doc/stack.txt (modified) (1 diff)
-
src/Makefile.am (modified) (1 diff)
-
src/psphot.h (modified) (1 diff)
-
src/psphotErrorCodes.dat (modified) (1 diff)
-
src/psphotSetMaskBits.c (modified) (1 diff)
-
src/psphotStackArguments.c (modified) (3 diffs)
-
src/psphotStackImageLoop.c (modified) (4 diffs)
-
src/psphotStackMatchPSFs.c (modified) (4 diffs)
-
src/psphotStackMatchPSFsPrepare.c (added)
-
src/psphotStackMatchPSFsUtils.c (modified) (12 diffs)
-
src/psphotStackOptions.c (added)
-
src/psphotStackParseCamera.c (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/psphot.20100506/doc/stack.txt
r27848 r27876 1 2 20100506: 3 4 we may load RAW and/or CNV images. 5 6 * options->convolve: 7 * if only one of RAW or CNV exists, convolve it to match target PSF 8 * if both exist, convolve desired one 9 10 * if matching PSF exists, use it (unless told to re-measure) 11 12 * output goes to OUT (which is then used by psphot analysis routines) 13 14 * detect 15 16 * if (RAW) ? RAW : OUT 17 18 * 19 1 20 2 21 20100503: -
branches/eam_branches/psphot.20100506/src/Makefile.am
r27819 r27876 95 95 psphotFitSourcesLinearStack.c \ 96 96 psphotSourceMatch.c \ 97 psphotStackMatchPSFs.c \ 98 psphotStackMatchPSFsUtils.c \ 97 99 psphotCleanup.c 98 100 -
branches/eam_branches/psphot.20100506/src/psphot.h
r27819 r27876 367 367 int pmPhotObjSortByX (const void **a, const void **b); 368 368 369 /// Options for stacking process 370 typedef struct { 371 // Setup 372 373 int num; // Number of inputs 374 bool convolve; // Convolve images? 375 // psArray *convImages, *convMasks, *convVariances; // Filenames for the temporary convolved images 376 377 // bool matchZPs; // Adjust relative fluxes based on transparency analysis? 378 // bool photometry; // Perform photometry? 379 // psMetadata *stats; // Statistics for output 380 // FILE *statsFile; // File to which to write statistics 381 // psArray *origImages, *origMasks, *origVariances; // Filenames of the original images 382 // psArray *origCovars; // Original covariances matrices 383 // int quality; // Bad data quality flag 384 385 // Prepare 386 pmPSF *psf; // Target PSF 387 psVector *inputSeeing; // Input seeing FWHMs 388 psVector *inputMask; // Mask for inputs 389 390 float targetSeeing; // Target seeing FWHM 391 psArray *sourceLists; // Individual lists of sources for matching 392 psVector *norm; // Normalisation for each image 393 psArray *psfs; 394 395 // psVector *exposures; // Exposure times 396 // float sumExposure; // Sum of exposure times 397 // float zp; // Zero point for output 398 // psVector *inputMask; // Mask for inputs 399 // psArray *sources; // Matched sources 400 401 // Convolve 402 psArray *kernels; // PSF-matching kernels --- required in the stacking 403 psArray *regions; // PSF-matching regions --- required in the stacking 404 psVector *matchChi2; // chi^2 for stamps from matching 405 psVector *weightings; // Combination weightings for images (1/noise^2) 406 // psArray *cells; // Cells for convolved images --- a handle for reading again 407 // int numCols, numRows; // Size of image 408 // psArray *convCovars; // Convolved covariance matrices 409 410 // Combine initial 411 // pmReadout *outRO; // Output readout 412 // pmReadout *expRO; // Exposure readout 413 // psArray *inspect; // Array of arrays of pixels to inspect 414 415 // Rejection 416 // psArray *rejected; // Rejected pixels 417 } psphotStackOptions; 418 419 /*** psphotStackMatchPSF prototypes ***/ 420 bool psphotStackMatchPSFs (pmConfig *config, const pmFPAview *view); 421 bool psphotStackMatchPSFsReadout (pmConfig *config, const pmFPAview *view, psphotStackOptions *options, int index); 422 423 // psphotStackMatchPSFsUtils 424 psVector *SetOptWidths (bool *optimum, psMetadata *recipe); 425 pmReadout *makeFakeReadout(pmConfig *config, pmReadout *raw, psArray *sources, pmPSF *psf, psImageMaskType maskVal, int fullSize); 426 bool rescaleData(pmReadout *readout, pmConfig *config, psphotStackOptions *options, int index); 427 bool renormKernel(pmReadout *readout, psphotStackOptions *options, int index); 428 bool saveMatchData (pmReadout *readout, psphotStackOptions *options, int index); 429 bool matchKernel(pmConfig *config, pmReadout *cnv, pmReadout *raw, psphotStackOptions *options, int index); 430 bool dumpImageDiff(pmReadout *readoutConv, pmReadout *readoutFake, pmReadout *readoutRef, int index, char *rootname); 431 bool dumpImage(pmReadout *readoutOut, pmReadout *readoutRef, int index, char *rootname); 432 bool loadKernel (pmConfig *config, pmReadout *readoutCnv, psphotStackOptions *options, int index); 433 bool stackRenormaliseReadout(const pmConfig *config, pmReadout *readout); 434 psImage *stackBackgroundModel(pmReadout *ro, const pmConfig *config); 435 psArray *stackSourcesFilter(psArray *sources, int exclusion); 436 void coordsFromSource(float *x, float *y, const pmSource *source); 437 bool readImage(psImage **target, const char *name, const pmConfig *config); 438 369 439 #endif -
branches/eam_branches/psphot.20100506/src/psphotErrorCodes.dat
r27002 r27876 11 11 APERTURE Problem with aperture photometry 12 12 SKY Problem in sky determination 13 IO Problem in data I/O 13 14 # these errors correspond to standard exit conditions 14 15 ARGUMENTS Incorrect arguments -
branches/eam_branches/psphot.20100506/src/psphotSetMaskBits.c
r21254 r27876 37 37 return true; 38 38 } 39 40 // XXX should these be in config->analysis or somewhere else besides 'recipe'? -
branches/eam_branches/psphot.20100506/src/psphotStackArguments.c
r27657 r27876 11 11 if (psArgumentGet(argc, argv, "-help")) writeHelpInfo(stdout); 12 12 if (psArgumentGet(argc, argv, "-h")) writeHelpInfo(stdout); 13 14 if (psArgumentGet(argc, argv, "-template")) dumpTemplate(); 13 15 14 16 // load config data from default locations … … 84 86 "\n" 85 87 "where INPUTS.mdc contains various METADATAs, each with:\n" 86 "\tIMAGE(STR): Image filename\n" 87 "\tMASK(STR): Mask filename\n" 88 "\tVARIANCE(STR): Variance map filename\n" 88 "\tIMAGE : Image filename\n" 89 "\tMASK : Mask filename\n" 90 "\tVARIANCE : Variance map filename\n" 91 "(use -template to generate a sample input.mdc file)\n" 89 92 "OUTROOT is the 'root name' for output files\n" 90 93 "\n" … … 144 147 } 145 148 149 static void dumpTemplate(void) { 150 151 fprintf (stdout, "# this line is required for multiple INPUT blocks to be accepted\n"); 152 fprintf (stdout, "INPUT MULTI\n\n"); 153 154 fprintf (stdout, "# copy and repeat the following block as needed (one per input image set)\n"); 155 fprintf (stdout, "# either RAW (unconvolved) or CNV (convolved) input images are required\n"); 156 fprintf (stdout, "# if both are supplied, by default RAW is used for detection, CNV is convolved (further) to match target PSF\n"); 157 fprintf (stdout, "# if MASK or VARIANCE images are not supplied, they will be generated\n"); 158 fprintf (stdout, "# if MASK or VARIANCE images are not supplied, they will be generated\n"); 159 fprintf (stdout, "# PSF may be supplied for the convolution target\n"); 160 fprintf (stdout, "INPUT METADATA\n"); 161 fprintf (stdout, " RAW:IMAGE STR file.im.fits # signal image filename\n"); 162 fprintf (stdout, " RAW:MASK STR file.mk.fits # mask image filename\n"); 163 fprintf (stdout, " RAW:VARIANCE STR file.wt.fits # variance image filename\n"); 164 fprintf (stdout, " RAW:PSF STR file.psf.fits # psf from input unconvolved image\n"); 165 166 fprintf (stdout, " CNV:IMAGE STR file.im.fits # signal image filename\n"); 167 fprintf (stdout, " CNV:MASK STR file.mk.fits # mask image filename\n"); 168 fprintf (stdout, " CNV:VARIANCE STR file.wt.fits # variance image filename\n"); 169 fprintf (stdout, " CNV:PSF STR file.psf.fits # psf from input convolved image\n"); 170 171 fprintf (stdout, " SOURCES STR file.cmf # measured source positions\n"); 172 fprintf (stdout, "END\n"); 173 174 psLibFinalize(); 175 exit(PS_EXIT_SUCCESS); 176 } -
branches/eam_branches/psphot.20100506/src/psphotStackImageLoop.c
r27848 r27876 14 14 pmReadout *readout; 15 15 16 pmFPAfile *input = psMetadataLookupPtr (&status, config->files, "PSPHOT.INPUT"); 17 if (!status) { 16 pmFPAfile *inputRaw = psMetadataLookupPtr (&status, config->files, "PSPHOT.STACK.INPUT.RAW"); 17 pmFPAfile *inputCnv = psMetadataLookupPtr (&status, config->files, "PSPHOT.STACK.INPUT.CNV"); 18 19 pmFPAfile *input = inputRaw ? inputRaw : inputCnv; 20 21 if (!input) { 18 22 psError(PSPHOT_ERR_PROG, false, "Can't find input data!"); 19 23 return false; … … 29 33 psLogMsg ("psphot", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process); 30 34 if (! chip->process || ! chip->file_exists) { continue; } 31 if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE ("failed input for Chip in psphotStack.");35 // if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE ("failed input for Chip in psphotStack."); 32 36 33 37 // there is now only a single chip (multiple readouts?). loop over it and process 34 38 while ((cell = pmFPAviewNextCell (view, input->fpa, 1)) != NULL) { 35 39 psLogMsg ("psphot", 5, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process); 36 if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE ("failed input for Cell in psphotStack.");40 // if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE ("failed input for Cell in psphotStack."); 37 41 38 42 // process each of the readouts … … 41 45 if (! readout->data_exists) { continue; } 42 46 43 # if (0) 44 // uncomment to generate matched psfs 47 // PSF matching 45 48 if (!psphotStackMatchPSFs (config, view)) { 46 49 psError(psErrorCodeLast(), false, "failure in psphotStackMatchPSFs for chip %d, cell %d, readout %d\n", view->chip, view->cell, view->readout); … … 48 51 return false; 49 52 } 50 # endif51 53 52 54 // XXX for now, we assume there is only a single chip in the PHU: -
branches/eam_branches/psphot.20100506/src/psphotStackMatchPSFs.c
r27850 r27876 1 1 # include "psphotInternal.h" 2 2 3 bool psphotStackMatchPSFs (pmConfig *config, const pmFPAview *view , bool firstPass)3 bool psphotStackMatchPSFs (pmConfig *config, const pmFPAview *view) 4 4 { 5 5 bool status = true; 6 7 psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "PSPHOT"); 8 psAssert(recipe, "We've thrown an error on this before."); 6 9 7 10 int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM"); 8 11 psAssert (status, "programming error: must define PSPHOT.INPUT.NUM"); 9 12 10 // loop over the available readouts 13 // 'options' carries info needed to perform the stack matching 14 psphotStackOptions *options = psphotStackOptionsAlloc(num); 15 16 options->convolve = psMetadataLookupBool (&status, recipe, "PSPHOT.STACK.MATCH.PSF"); 17 psAssert (status, "PSPHOT.STACK.MATCH.PSF not in recipe"); 18 19 if (options->convolve) { 20 char *convolveSource = psMetadataLookupStr (&status, recipe, "PSPHOT.STACK.MATCH.PSF.SOURCE"); 21 options->convolveSource = psphotStackConvolveSourceFromString (convolveSource); 22 if (options->convolveSource == PSPHOT_CNV_SRC_NONE) { 23 psError (PSPHOT_ERR_CONFIG, true, "stack convolution source not defined in recipe"); 24 return false; 25 } 26 } 27 28 // loop over the available readouts (ignore chisq image) 11 29 for (int i = 0; i < num; i++) { 12 if (!psphotStackMatchPSFsReadout (config, view, i)) { 30 if (!psphotStackMatchPSFsPrepare (config, view, options, i)) { 31 psError (PSPHOT_ERR_CONFIG, false, "failed to set PSF matching options for entry %d", i); 32 return false; 33 } 34 } 35 36 // Generate target PSF 37 if (options->convolve) { 38 options->psf = ppStackPSF(config, options->numCols, options->numRows, options->psfs, options->inputMask); 39 if (!options->psf) { 40 psError(psErrorCodeLast(), false, "Unable to determine output PSF."); 41 return false; 42 } 43 psMetadataAddPtr(config->arguments, PS_LIST_TAIL, "PSF.TARGET", PS_DATA_UNKNOWN, "Target PSF for stack", options->psf); 44 options->targetSeeing = pmPSFtoFWHM(options->psf, 0.5 * options->numCols, 0.5 * options->numRows); // FWHM for target 45 psLogMsg("psphotStack", PS_LOG_INFO, "Target seeing FWHM: %f\n", options->targetSeeing); 46 47 // XXX is this needed to supply the psf to psphot?? 48 // pmChip *outChip = pmFPAfileThisChip(config->files, view, "PPSTACK.TARGET.PSF"); // Output chip 49 // psMetadataAddPtr(outChip->analysis, PS_LIST_TAIL, "PSPHOT.PSF", PS_DATA_UNKNOWN, "Target PSF", options->psf); 50 // outChip->data_exists = true; 51 } 52 53 // loop over the available readouts (ignore chisq image) 54 for (int i = 0; i < num; i++) { 55 if (!psphotStackMatchPSFsReadout (config, view, options, i)) { 13 56 psError (PSPHOT_ERR_CONFIG, false, "failed to find initial detections for PSPHOT.INPUT entry %d", i); 14 57 return false; … … 19 62 20 63 // convolve the image to match desired PSF 21 bool psphotStackMatchPSFsReadout (pmConfig *config, const pmFPAview *view, int index) { 22 23 bool status; 24 int pass; 25 float NSIGMA_PEAK = 25.0; 26 int NMAX = 0; 64 bool psphotStackMatchPSFsReadout (pmConfig *config, const pmFPAview *view, psphotStackOptions *options, int index) { 27 65 28 66 // find the currently selected readout 29 pmFPAfile *fileRaw = pmFPAfileSelectSingle(config->files, "PSPHOT. INPUT", index); // File of interest67 pmFPAfile *fileRaw = pmFPAfileSelectSingle(config->files, "PSPHOT.STACK.INPUT.RAW", index); // File of interest 30 68 psAssert (fileRaw, "missing file?"); 31 69 32 pmFPAfile *fileCnv = pmFPAfileSelectSingle(config->files, "PSPHOT. INPUT.CONV", index); // File of interest70 pmFPAfile *fileCnv = pmFPAfileSelectSingle(config->files, "PSPHOT.STACK.INPUT.CNV", index); // File of interest 33 71 psAssert (fileCnv, "missing file?"); 34 72 … … 39 77 psAssert (readoutCnv, "missing readout?"); 40 78 41 // user-defined masks to test for good/bad pixels (build from recipe list if not yet set) 42 psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels 43 psAssert (maskVal, "missing mask value?"); 44 45 /***** set up recipe options *****/ 46 47 psMetadata *stackRecipe = psMetadataLookupMetadata(NULL, config->recipes, PPSTACK_RECIPE); // ppStack recipe 48 psAssert(stackRecipe, "We've thrown an error on this before."); 49 50 // Look up appropriate values from the ppSub recipe 51 psMetadata *subRecipe = psMetadataLookupMetadata(NULL, config->recipes, "PPSUB"); // PPSUB recipe 52 psAssert(subRecipe, "recipe missing"); 53 54 int size = psMetadataLookupS32(NULL, subRecipe, "KERNEL.SIZE"); // Kernel half-size 55 56 float deconvLimit = psMetadataLookupF32(NULL, stackRecipe, "DECONV.LIMIT"); // Limit on deconvolution fraction 57 58 psString maskValStr = psMetadataLookupStr(NULL, subRecipe, "MASK.VAL"); // Name of bits to mask going in 59 psImageMaskType maskVal = pmConfigMaskGet(maskValStr, config); // Bits to mask going in to pmSubtractionMatch 60 psString maskPoorStr = psMetadataLookupStr(NULL, stackRecipe, "MASK.POOR"); // Name of bits to mask for poor 61 psImageMaskType maskPoor = pmConfigMaskGet(maskPoorStr, config); // Bits to mask for poor pixels 62 psString maskBadStr = psMetadataLookupStr(NULL, stackRecipe, "MASK.BAD"); // Name of bits to mask for bad 63 psImageMaskType maskBad = pmConfigMaskGet(maskBadStr, config); // Bits to mask for bad pixels 64 65 bool mdok; // Status of MD lookup 66 float penalty = psMetadataLookupF32(NULL, subRecipe, "PENALTY"); // Penalty for wideness 67 int threads = psMetadataLookupS32(NULL, config->arguments, "-threads"); // Number of threads 68 69 if (!pmReadoutMaskNonfinite(readout, maskVal)) { 79 // set NAN pixels to 'SAT' 80 psImageMaskType maskVal = pmConfigMaskGet("SAT", config); 81 if (!pmReadoutMaskNonfinite(readoutRaw, maskVal)) { 70 82 psError(psErrorCodeLast(), false, "Unable to mask non-finite pixels in readout."); 71 83 return false; … … 74 86 // Image Matching (PSFs or just flux) 75 87 if (options->convolve) { 76 // Full match of PSFs 77 pmReadout *conv = pmReadoutAlloc(NULL); // Conv readout, for holding results temporarily 78 79 // Read previously produced kernel 80 if (psMetadataLookupBool(NULL, config->arguments, "PPSTACK.DEBUG.STACK")) { 81 loadKernel(); 82 } else { 83 matchKernel(); 84 } // !DEBUG.STACK 85 86 saveMatchData(); 87 88 saveChiSquare(); 89 90 renormKernel(); 91 92 // Reject image completely if the maximum deconvolution fraction exceeds the limit 93 float deconv = psMetadataLookupF32(NULL, conv->analysis, PM_SUBTRACTION_ANALYSIS_DECONV_MAX); // Max deconvolution fraction 94 if (deconv > deconvLimit) { 95 psWarning("Maximum deconvolution fraction (%f) exceeds limit (%f) --- rejecting image %d\n", deconv, deconvLimit, index); 96 psFree(conv); 97 return NULL; 98 } 99 100 readout->analysis = psMetadataCopy(readout->analysis, conv->analysis); 101 102 psFree(conv); 88 matchKernel(config, readoutCnv, readoutRaw, options, index); 89 saveMatchData(readoutCnv, options, index); 90 // renormKernel(readoutCnv, options, index); 103 91 } else { 104 // only match the flux 105 float norm = powf(10.0, -0.4 * options->norm->data.F32[index]); // Normalisation 106 psBinaryOp(readout->image, readout->image, "*", psScalarAlloc(norm, PS_TYPE_F32)); 107 psBinaryOp(readout->variance, readout->variance, "*", psScalarAlloc(PS_SQR(norm), PS_TYPE_F32)); 92 // only match the flux (NO! not for multi-filter, at least!) 93 // XXX do not generate readoutCnv in this case? 94 // float norm = powf(10.0, -0.4 * options->norm->data.F32[index]); // Normalisation 95 // psBinaryOp(readoutRaw->image, readoutRaw->image, "*", psScalarAlloc(norm, PS_TYPE_F32)); 96 // psBinaryOp(readoutRaw->variance, readoutRaw->variance, "*", psScalarAlloc(PS_SQR(norm), PS_TYPE_F32)); 108 97 } 109 98 110 // Ensure the background value is zero 111 psStats *bg = psStatsAlloc(PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV); // Statistics for background 112 psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS); // Random number generator 113 if (!psImageBackground(bg, NULL, readout->image, readout->mask, maskVal | maskBad, rng)) { 114 psWarning("Can't measure background for image."); 115 psErrorClear(); 116 } else { 117 if (!psMetadataLookupBool(NULL, config->arguments, "PPSTACK.SKIP.BG.SUB")) { 118 psLogMsg("ppStack", PS_LOG_INFO, "Correcting convolved image background by %lf (+/- %lf)", 119 psStatsGetValue(bg, PS_STAT_ROBUST_MEDIAN), psStatsGetValue(bg, PS_STAT_ROBUST_STDEV)); 120 (void)psBinaryOp(readout->image, readout->image, "-", 121 psScalarAlloc(psStatsGetValue(bg, PS_STAT_ROBUST_MEDIAN), PS_TYPE_F32)); 122 } 123 } 99 rescaleData(readoutCnv, config, options, index); 124 100 125 if (!stackRenormaliseReadout(config, readout)) { 126 psFree(rng); 127 psFree(bg); 128 return false; 129 } 130 131 // Measure the variance level for the weighting 132 if (psMetadataLookupBool(NULL, stackRecipe, "WEIGHTS")) { 133 if (!psImageBackground(bg, NULL, readout->variance, readout->mask, maskVal | maskBad, rng)) { 134 psError(PPSTACK_ERR_DATA, false, "Can't measure mean variance for image."); 135 psFree(rng); 136 psFree(bg); 137 return false; 138 } 139 options->weightings->data.F32[index] = 1.0 / (psStatsGetValue(bg, PS_STAT_ROBUST_MEDIAN) * psImageCovarianceFactor(readout->covariance)); 140 } else { 141 options->weightings->data.F32[index] = 1.0; 142 } 143 psLogMsg("ppStack", PS_LOG_INFO, "Weighting for image %d is %f\n", 144 index, options->weightings->data.F32[index]); 145 146 psFree(rng); 147 psFree(bg); 148 149 dumpImage3(); 101 dumpImage(readoutCnv, readoutRaw, index, "convolved"); 150 102 151 103 return true; 152 104 } 105 106 107 # if (0) 108 // Read previously produced kernel 109 if (psMetadataLookupBool(NULL, config->arguments, "PPSTACK.DEBUG.STACK")) { 110 loadKernel(config, readoutCnv, options, index); 111 } else { 112 matchKernel(config, readoutCnv, readoutRaw, options, index); 113 } 114 # endif -
branches/eam_branches/psphot.20100506/src/psphotStackMatchPSFsUtils.c
r27850 r27876 1 /***** defines *****/ 2 3 #define ARRAY_BUFFER 16 // Number to add to array at a time 4 #define MAG_IGNORE 50 // Ignore magnitudes fainter than this --- they're not real! 5 #define FAKE_SIZE 1 // Size of fake convolution kernel 6 #define SOURCE_MASK (PM_SOURCE_MODE_FAIL | PM_SOURCE_MODE_DEFECT | PM_SOURCE_MODE_SATURATED | PM_SOURCE_MODE_CR_LIMIT | PM_SOURCE_MODE_EXT_LIMIT) // Mask to apply to input sources 7 #define NOISE_FRACTION 0.01 // Set minimum flux to this fraction of noise 8 #define COVAR_FRAC 0.01 // Truncation fraction for covariance matrix 1 # include "psphotInternal.h" 2 # define ARRAY_BUFFER 16 // Number to add to array at a time 9 3 10 4 // XXX better name … … 18 12 psFree(resolved); 19 13 if (!fits) { 20 psError(P PSTACK_ERR_IO, false, "Unable to open previously produced image: %s", name);14 psError(PSPHOT_ERR_IO, false, "Unable to open previously produced image: %s", name); 21 15 return false; 22 16 } 23 17 psImage *image = psFitsReadImage(fits, psRegionSet(0,0,0,0), 0); // Image of interest 24 18 if (!image) { 25 psError(P PSTACK_ERR_IO, false, "Unable to read previously produced image: %s", name);19 psError(PSPHOT_ERR_IO, false, "Unable to read previously produced image: %s", name); 26 20 psFitsClose(fits); 27 21 return false; … … 52 46 53 47 psArray *stackSourcesFilter(psArray *sources, // Source list to filter 54 int exclusion // Exclusion zone, pixels48 int exclusion // Exclusion zone, pixels 55 49 ) 56 50 { … … 90 84 91 85 long numWithin = psTreeWithin(tree, coords, exclusion); // Number within exclusion zone 92 psTrace("p pStack", 9, "Source at %.0lf,%.0lf has %ld sources in exclusion zone",86 psTrace("psphotStack", 9, "Source at %.0lf,%.0lf has %ld sources in exclusion zone", 93 87 coords->data.F64[0], coords->data.F64[1], numWithin); 94 88 if (numWithin == 1) { … … 104 98 psFree(y); 105 99 106 psLogMsg("p pStack", PS_LOG_INFO, "Filtered out %d of %d sources", numFiltered, numGood);100 psLogMsg("psphotStack", PS_LOG_INFO, "Filtered out %d of %d sources", numFiltered, numGood); 107 101 108 102 return filtered; … … 111 105 // Add background into the fake image 112 106 // Based on ppSubBackground() 113 staticpsImage *stackBackgroundModel(pmReadout *ro, // Readout for which to generate background model107 psImage *stackBackgroundModel(pmReadout *ro, // Readout for which to generate background model 114 108 const pmConfig *config // Configuration 115 109 ) … … 121 115 int numCols = image->numCols, numRows = image->numRows; // Size of image 122 116 123 psMetadata *ppStackRecipe = psMetadataLookupPtr(NULL, config->recipes, PPSTACK_RECIPE);117 psMetadata *ppStackRecipe = psMetadataLookupPtr(NULL, config->recipes, "PPSTACK"); 124 118 psAssert(ppStackRecipe, "Need PPSTACK recipe"); 125 psMetadata *psphotRecipe = psMetadataLookupPtr(NULL, config->recipes, PSPHOT_RECIPE);119 psMetadata *psphotRecipe = psMetadataLookupPtr(NULL, config->recipes, "PSPHOT"); 126 120 psAssert(psphotRecipe, "Need PSPHOT recipe"); 127 121 … … 138 132 psImage *unbinned = psImageAlloc(numCols, numRows, PS_TYPE_F32); // Unbinned background model 139 133 if (!psImageUnbin(unbinned, binned, binning)) { 140 psError(P PSTACK_ERR_DATA, false, "Unable to unbin background model");134 psError(PSPHOT_ERR_DATA, false, "Unable to unbin background model"); 141 135 psFree(binned); 142 136 psFree(unbinned); … … 153 147 ) 154 148 { 155 #if 1156 149 bool mdok; // Status of metadata lookups 157 150 158 psMetadata *recipe = psMetadataLookupPtr(NULL, config->recipes, PPSTACK_RECIPE); // Recipe for ppStack151 psMetadata *recipe = psMetadataLookupPtr(NULL, config->recipes, "PPSTACK"); // Recipe for ppStack 159 152 psAssert(recipe, "Need PPSTACK recipe"); 160 153 … … 163 156 int num = psMetadataLookupS32(&mdok, recipe, "RENORM.NUM"); 164 157 if (!mdok) { 165 psError(P PSTACK_ERR_CONFIG, true, "RENORM.NUM is not set in the recipe");158 psError(PSPHOT_ERR_CONFIG, true, "RENORM.NUM is not set in the recipe"); 166 159 return false; 167 160 } 168 161 float minValid = psMetadataLookupF32(&mdok, recipe, "RENORM.MIN"); 169 162 if (!mdok) { 170 psError(P PSTACK_ERR_CONFIG, true, "RENORM.MIN is not set in the recipe");163 psError(PSPHOT_ERR_CONFIG, true, "RENORM.MIN is not set in the recipe"); 171 164 return false; 172 165 } 173 166 float maxValid = psMetadataLookupF32(&mdok, recipe, "RENORM.MAX"); 174 167 if (!mdok) { 175 psError(P PSTACK_ERR_CONFIG, true, "RENORM.MAX is not set in the recipe");168 psError(PSPHOT_ERR_CONFIG, true, "RENORM.MAX is not set in the recipe"); 176 169 return false; 177 170 } … … 181 174 psImageCovarianceTransfer(readout->variance, readout->covariance); 182 175 return pmReadoutVarianceRenormalise(readout, maskBad, num, minValid, maxValid); 183 #else184 return true;185 #endif186 176 } 187 177 … … 190 180 // It implicitly assumes the output root name is the same between invocations. 191 181 192 bool loadKernel () { 193 pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PPSTACK.CONV.KERNEL", index); 194 psAssert(file, "Require file"); 195 196 pmFPAview *view = pmFPAviewAlloc(0); // View to readout of interest 197 view->chip = view->cell = view->readout = 0; 198 psString filename = pmFPAfileNameFromRule(file->filerule, file, view); // Filename of interest 199 200 // Read convolution kernel 201 psString resolved = pmConfigConvertFilename(filename, config, false, false); // Resolved filename 202 psFree(filename); 203 psFits *fits = psFitsOpen(resolved, "r"); // FITS file for subtraction kernel 204 psFree(resolved); 205 if (!fits || !pmReadoutReadSubtractionKernels(conv, fits)) { 206 psError(PPSTACK_ERR_IO, false, "Unable to read previously produced kernel"); 207 psFitsClose(fits); 208 return false; 209 } 210 psFitsClose(fits); 211 212 if (!readImage(&readout->image, options->convImages->data[index], config) || 213 !readImage(&readout->mask, options->convMasks->data[index], config) || 214 !readImage(&readout->variance, options->convVariances->data[index], config)) { 215 psError(PPSTACK_ERR_IO, false, "Unable to read previously produced image."); 216 return false; 217 } 218 219 psRegion *region = psMetadataLookupPtr(NULL, conv->analysis, 220 PM_SUBTRACTION_ANALYSIS_REGION); // Convolution region 221 pmSubtractionKernels *kernels = psMetadataLookupPtr(NULL, conv->analysis, 222 PM_SUBTRACTION_ANALYSIS_KERNEL); 223 224 pmSubtractionAnalysis(conv->analysis, NULL, kernels, region, 225 readout->image->numCols, readout->image->numRows); 226 227 psKernel *kernel = pmSubtractionKernel(kernels, 0.0, 0.0, false); // Convolution kernel 228 bool oldThreads = psImageCovarianceSetThreads(true); // Old thread setting 229 psKernel *covar = psImageCovarianceCalculate(kernel, readout->covariance); // Covariance matrix 230 psImageCovarianceSetThreads(oldThreads); 231 psFree(readout->covariance); 232 readout->covariance = covar; 233 psFree(kernel); 234 } 235 236 bool dumpImage() { 237 // XXX should be optional 238 { 239 pmHDU *hdu = pmHDUFromCell(readout->parent); 240 psString name = NULL; 241 psStringAppend(&name, "fake_%03d.fits", index); 242 pmStackVisualPlotTestImage(fake->image, name); 243 psFits *fits = psFitsOpen(name, "w"); 244 psFree(name); 245 psFitsWriteImage(fits, hdu->header, fake->image, 0, NULL); 246 psFitsClose(fits); 247 } 248 { 249 pmHDU *hdu = pmHDUFromCell(readout->parent); 250 psString name = NULL; 251 psStringAppend(&name, "real_%03d.fits", index); 252 pmStackVisualPlotTestImage(readout->image, name); 253 psFits *fits = psFitsOpen(name, "w"); 254 psFree(name); 255 psFitsWriteImage(fits, hdu->header, readout->image, 0, NULL); 256 psFitsClose(fits); 257 } 258 } 259 260 bool dumpImage2() { 261 // XXX should be optional 262 263 { 264 pmHDU *hdu = pmHDUFromCell(readout->parent); 265 psString name = NULL; 266 psStringAppend(&name, "conv_%03d.fits", index); 267 pmStackVisualPlotTestImage(conv->image, name); 268 psFits *fits = psFitsOpen(name, "w"); 269 psFree(name); 270 psFitsWriteImage(fits, hdu->header, conv->image, 0, NULL); 271 psFitsClose(fits); 272 } 273 { 274 pmHDU *hdu = pmHDUFromCell(readout->parent); 275 psString name = NULL; 276 psStringAppend(&name, "diff_%03d.fits", index); 277 pmStackVisualPlotTestImage(fake->image, name); 278 psFits *fits = psFitsOpen(name, "w"); 279 psFree(name); 280 psBinaryOp(fake->image, conv->image, "-", fake->image); 281 psFitsWriteImage(fits, hdu->header, fake->image, 0, NULL); 282 psFitsClose(fits); 283 } 284 } 285 286 bool dumpImage3() 182 bool loadKernel (pmConfig *config, pmReadout *readoutCnv, psphotStackOptions *options, int index) { 183 184 // Read the convolution kernel from the saved file 185 pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PPSTACK.CONV.KERNEL", index); 186 psAssert(file, "Require file"); 187 188 pmFPAview *view = pmFPAviewAlloc(0); // View to readout of interest 189 view->chip = view->cell = view->readout = 0; 190 psString filename = pmFPAfileNameFromRule(file->filerule, file, view); // Filename of interest 191 192 // Read convolution kernel data 193 psString resolved = pmConfigConvertFilename(filename, config, false, false); // Resolved filename 194 psFree(filename); 195 psFits *fits = psFitsOpen(resolved, "r"); // FITS file for subtraction kernel 196 psFree(resolved); 197 if (!fits || !pmReadoutReadSubtractionKernels(readoutCnv, fits)) { 198 psError(PSPHOT_ERR_IO, false, "Unable to read previously produced kernel"); 199 psFitsClose(fits); 200 return false; 201 } 202 psFitsClose(fits); 203 204 // read the convolved pixels (image, mask, variance) -- names are pre-defined 205 if (!readImage(&readoutCnv->image, options->convImages->data[index], config) || 206 !readImage(&readoutCnv->mask, options->convMasks->data[index], config) || 207 !readImage(&readoutCnv->variance, options->convVariances->data[index], config)) { 208 psError(PSPHOT_ERR_IO, false, "Unable to read previously produced image."); 209 return false; 210 } 211 212 // XXX ??? not sure what is happening here -- consult Paul 213 psRegion *region = psMetadataLookupPtr(NULL, readoutCnv->analysis, PM_SUBTRACTION_ANALYSIS_REGION); // Convolution region 214 pmSubtractionKernels *kernels = psMetadataLookupPtr(NULL, readoutCnv->analysis, PM_SUBTRACTION_ANALYSIS_KERNEL); 215 216 pmSubtractionAnalysis(readoutCnv->analysis, NULL, kernels, region, readoutCnv->image->numCols, readoutCnv->image->numRows); 217 218 psKernel *kernel = pmSubtractionKernel(kernels, 0.0, 0.0, false); // Convolution kernel 219 220 // update the covariance matrix 221 // XXX why is this needed if we have correctly read the saved data? 222 bool oldThreads = psImageCovarianceSetThreads(true); // Old thread setting 223 psKernel *covar = psImageCovarianceCalculate(kernel, readoutCnv->covariance); // Covariance matrix 224 psImageCovarianceSetThreads(oldThreads); 225 psFree(readoutCnv->covariance); 226 readoutCnv->covariance = covar; 227 psFree(kernel); 228 return true; 229 } 230 231 bool dumpImage(pmReadout *readoutOut, pmReadout *readoutRef, int index, char *rootname) { 232 233 pmHDU *hdu = pmHDUFromCell(readoutRef->parent); 234 psString name = NULL; 235 psStringAppend(&name, "%s_%03d.fits", rootname, index); 236 pmStackVisualPlotTestImage(readoutOut->image, name); 237 psFits *fits = psFitsOpen(name, "w"); 238 psFree(name); 239 psFitsWriteImage(fits, hdu->header, readoutOut->image, 0, NULL); 240 psFitsClose(fits); 241 return true; 242 } 243 244 bool dumpImageDiff(pmReadout *readoutConv, pmReadout *readoutFake, pmReadout *readoutRef, int index, char *rootname) { 245 246 pmHDU *hdu = pmHDUFromCell(readoutRef->parent); 247 psString name = NULL; 248 psStringAppend(&name, "%s_%03d.fits", rootname, index); 249 pmStackVisualPlotTestImage(readoutFake->image, name); 250 psFits *fits = psFitsOpen(name, "w"); 251 psFree(name); 252 psBinaryOp(readoutFake->image, readoutConv->image, "-", readoutFake->image); 253 psFitsWriteImage(fits, hdu->header, readoutFake->image, 0, NULL); 254 psFitsClose(fits); 255 return true; 256 } 257 258 // perform the bulk of the PSF-matching 259 bool matchKernel(pmConfig *config, pmReadout *readoutCnv, pmReadout *readoutRaw, psphotStackOptions *options, int index) { 260 261 bool mdok; 262 263 psAssert(options->psf, "Require target PSF"); 264 psAssert(options->sourceLists && options->sourceLists->data[index], "Require source list"); 265 266 psMetadata *stackRecipe = psMetadataLookupMetadata(NULL, config->recipes, "PPSTACK"); // ppStack recipe 267 psAssert(stackRecipe, "We've thrown an error on this before."); 268 269 // Look up appropriate values from the ppSub recipe 270 psMetadata *subRecipe = psMetadataLookupMetadata(NULL, config->recipes, "PPSUB"); // PPSUB recipe 271 psAssert(subRecipe, "recipe missing"); 272 273 psString maskValStr = psMetadataLookupStr(NULL, subRecipe, "MASK.VAL"); // Name of bits to mask going in 274 psString maskPoorStr = psMetadataLookupStr(NULL, stackRecipe, "MASK.POOR"); // Name of bits to mask for poor 275 psString maskBadStr = psMetadataLookupStr(NULL, stackRecipe, "MASK.BAD"); // Name of bits to mask for bad 276 277 psImageMaskType maskVal = pmConfigMaskGet(maskValStr, config); // Bits to mask going in to pmSubtractionMatch 278 psImageMaskType maskPoor = pmConfigMaskGet(maskPoorStr, config); // Bits to mask for poor pixels 279 psImageMaskType maskBad = pmConfigMaskGet(maskBadStr, config); // Bits to mask for bad pixels 280 281 float penalty = psMetadataLookupF32(NULL, subRecipe, "PENALTY"); // Penalty for wideness 282 int threads = psMetadataLookupS32(NULL, config->arguments, "-threads"); // Number of threads 283 284 int order = psMetadataLookupS32(NULL, subRecipe, "SPATIAL.ORDER"); // Spatial polynomial order 285 float regionSize = psMetadataLookupF32(NULL, subRecipe, "REGION.SIZE"); // Size of iso-kernel regs 286 float spacing = psMetadataLookupF32(NULL, subRecipe, "STAMP.SPACING"); // Typical stamp spacing 287 288 int footprint = psMetadataLookupS32(NULL, subRecipe, "STAMP.FOOTPRINT"); // Stamp half-size 289 int size = psMetadataLookupS32(NULL, subRecipe, "KERNEL.SIZE"); // Kernel half-size 290 291 float threshold = psMetadataLookupF32(NULL, subRecipe, "STAMP.THRESHOLD"); // Threshold for stmps 292 int stride = psMetadataLookupS32(NULL, subRecipe, "STRIDE"); // Size of convolution patches 293 int iter = psMetadataLookupS32(NULL, subRecipe, "ITER"); // Rejection iterations 294 float rej = psMetadataLookupF32(NULL, subRecipe, "REJ"); // Rejection threshold 295 float kernelError = psMetadataLookupF32(NULL, subRecipe, "KERNEL.ERR"); // Relative systematic error in kernel 296 float normFrac = psMetadataLookupF32(NULL, subRecipe, "NORM.FRAC"); // Fraction of window for normalisn windw 297 float sysError = psMetadataLookupF32(NULL, subRecipe, "SYS.ERR"); // Relative systematic error in images 298 float skyErr = psMetadataLookupF32(NULL, subRecipe, "SKY.ERR"); // Additional error in sky 299 float covarFrac = psMetadataLookupF32(NULL, subRecipe, "COVAR.FRAC"); // Fraction for covariance calculation 300 301 const char *typeStr = psMetadataLookupStr(NULL, subRecipe, "KERNEL.TYPE"); // Kernel type 302 pmSubtractionKernelsType type = pmSubtractionKernelsTypeFromString(typeStr); // Kernel type 303 psVector *widths = psMetadataLookupPtr(NULL, subRecipe, "ISIS.WIDTHS"); // ISIS Gaussian widths 304 psVector *orders = psMetadataLookupPtr(NULL, subRecipe, "ISIS.ORDERS"); // ISIS Polynomial orders 305 int inner = psMetadataLookupS32(NULL, subRecipe, "INNER"); // Inner radius 306 int ringsOrder = psMetadataLookupS32(NULL, subRecipe, "RINGS.ORDER"); // RINGS polynomial order 307 int binning = psMetadataLookupS32(NULL, subRecipe, "SPAM.BINNING"); // Binning for SPAM kernel 308 float badFrac = psMetadataLookupF32(NULL, subRecipe, "BADFRAC"); // Maximum bad fraction 309 float optThresh = psMetadataLookupF32(&mdok, subRecipe, "OPTIMUM.TOL"); // Tolerance for search 310 int optOrder = psMetadataLookupS32(&mdok, subRecipe, "OPTIMUM.ORDER"); // Order for search 311 float poorFrac = psMetadataLookupF32(&mdok, subRecipe, "POOR.FRACTION"); // Fraction for "poor" 312 313 bool scale = psMetadataLookupBool(NULL, subRecipe, "SCALE"); // Scale kernel parameters? 314 float scaleRef = psMetadataLookupF32(NULL, subRecipe, "SCALE.REF"); // Reference for scaling 315 float scaleMin = psMetadataLookupF32(NULL, subRecipe, "SCALE.MIN"); // Minimum for scaling 316 float scaleMax = psMetadataLookupF32(NULL, subRecipe, "SCALE.MAX"); // Maximum for scaling 317 if (!isfinite(scaleRef) || !isfinite(scaleMin) || !isfinite(scaleMax)) { 318 psError(PSPHOT_ERR_CONFIG, false, 319 "Scale parameters (SCALE.REF=%f, SCALE.MIN=%f, SCALE.MAX=%f) not set in PPSUB recipe.", 320 scaleRef, scaleMin, scaleMax); 321 return false; 322 } 323 324 // These values are specified specifically for stacking 325 const char *stampsName = psMetadataLookupStr(NULL, config->arguments, "STAMPS");// Stamps filename 326 327 psVector *widthsCopy = NULL; 328 psVector *optWidths = NULL; 329 pmReadout *fake = NULL; 330 psArray *stampSources = NULL; 331 332 bool optimum = false; 333 optWidths = SetOptWidths(&optimum, subRecipe); // Vector with FWHMs for optimum search 334 335 // For the sake of stamps, remove nearby sources 336 stampSources = stackSourcesFilter(options->sourceLists->data[index], footprint); // Filtered list of sources 337 338 fake = makeFakeReadout(config, readoutRaw, stampSources, options->psf, maskVal | maskBad, footprint + size); 339 if (!fake) goto escape; 340 341 dumpImage(fake, readoutRaw, index, "fake"); 342 dumpImage(readoutRaw, readoutRaw, index, "real"); 343 344 if (threads) pmSubtractionThreadsInit(); 345 346 // Do the image matching 347 pmSubtractionKernels *kernel = psMetadataLookupPtr(&mdok, readoutRaw->analysis, PM_SUBTRACTION_ANALYSIS_KERNEL); // Conv kernel 348 if (kernel) { 349 if (!pmSubtractionMatchPrecalc(NULL, readoutCnv, fake, readoutRaw, readoutRaw->analysis, stride, kernelError, covarFrac, maskVal, maskBad, maskPoor, poorFrac, badFrac)) { 350 psError(psErrorCodeLast(), false, "Unable to convolve images."); 351 goto escape; 352 } 353 } else { 354 // Scale the input parameters 355 widthsCopy = psVectorCopy(NULL, widths, PS_TYPE_F32); // Copy of kernel widths 356 if (scale && !pmSubtractionParamsScale(&size, &footprint, widthsCopy, options->inputSeeing->data.F32[index], options->targetSeeing, scaleRef, scaleMin, scaleMax)) { 357 psError(psErrorCodeLast(), false, "Unable to scale kernel parameters"); 358 goto escape; 359 } 360 361 if (!pmSubtractionMatch(NULL, readoutCnv, fake, readoutRaw, footprint, stride, regionSize, spacing, threshold, stampSources, stampsName, type, size, order, widthsCopy, orders, inner, ringsOrder, binning, penalty, optimum, optWidths, optOrder, optThresh, iter, rej, normFrac, sysError, skyErr, kernelError, covarFrac, maskVal, maskBad, maskPoor, poorFrac, badFrac, PM_SUBTRACTION_MODE_2)) { 362 psError(psErrorCodeLast(), false, "Unable to match images."); 363 goto escape; 364 } 365 } 366 367 // Reject image completely if the maximum deconvolution fraction exceeds the limit 368 float deconvLimit = psMetadataLookupF32(NULL, stackRecipe, "DECONV.LIMIT"); // Limit on deconvolution fraction 369 float deconv = psMetadataLookupF32(NULL, readoutCnv->analysis, PM_SUBTRACTION_ANALYSIS_DECONV_MAX); // Max deconvolution fraction 370 if (deconv > deconvLimit) { 371 psWarning("Maximum deconvolution fraction (%f) exceeds limit (%f) --- rejecting image %d\n", deconv, deconvLimit, index); 372 goto escape; 373 } 374 375 dumpImage(readoutCnv, readoutRaw, index, "conv"); 376 dumpImageDiff(readoutCnv, fake, readoutRaw, index, "diff"); 377 378 psFree(fake); 379 psFree(optWidths); 380 psFree(stampSources); 381 psFree(widthsCopy); 382 pmSubtractionThreadsFinalize(); 383 return true; 384 385 escape: 386 psFree(fake); 387 psFree(optWidths); 388 psFree(stampSources); 389 psFree(widthsCopy); 390 pmSubtractionThreadsFinalize(); 391 return false; 392 } 393 394 // Extract the regions and solutions used in the image matching 395 // This stops them from being freed when we iterate back up the FPA 396 // Record the chi-square value 397 // XXX this function may not be needed for psphotStack 398 bool saveMatchData (pmReadout *readout, psphotStackOptions *options, int index) { 399 400 psArray *regions = options->regions->data[index] = psArrayAllocEmpty(ARRAY_BUFFER); // Match regions 287 401 { 288 pmHDU *hdu = pmHDUFromCell(readout->parent); 289 psString name = NULL; 290 psStringAppend(&name, "convolved_%03d.fits", index); 291 pmStackVisualPlotTestImage(readout->image, name); 292 psFits *fits = psFitsOpen(name, "w"); 293 psFree(name); 294 psFitsWriteImage(fits, hdu->header, readout->image, 0, NULL); 295 psFitsClose(fits); 296 } 297 298 bool matchKernel() { 299 // Normal operations here 300 psAssert(options->psf, "Require target PSF"); 301 psAssert(options->sourceLists && options->sourceLists->data[index], "Require source list"); 302 303 int order = psMetadataLookupS32(NULL, subRecipe, "SPATIAL.ORDER"); // Spatial polynomial order 304 float regionSize = psMetadataLookupF32(NULL, subRecipe, "REGION.SIZE"); // Size of iso-kernel regs 305 float spacing = psMetadataLookupF32(NULL, subRecipe, "STAMP.SPACING"); // Typical stamp spacing 306 int footprint = psMetadataLookupS32(NULL, subRecipe, "STAMP.FOOTPRINT"); // Stamp half-size 307 float threshold = psMetadataLookupF32(NULL, subRecipe, "STAMP.THRESHOLD"); // Threshold for stmps 308 int stride = psMetadataLookupS32(NULL, subRecipe, "STRIDE"); // Size of convolution patches 309 int iter = psMetadataLookupS32(NULL, subRecipe, "ITER"); // Rejection iterations 310 float rej = psMetadataLookupF32(NULL, subRecipe, "REJ"); // Rejection threshold 311 float kernelError = psMetadataLookupF32(NULL, subRecipe, "KERNEL.ERR"); // Relative systematic error in kernel 312 float normFrac = psMetadataLookupF32(NULL, subRecipe, "NORM.FRAC"); // Fraction of window for normalisn windw 313 float sysError = psMetadataLookupF32(NULL, subRecipe, "SYS.ERR"); // Relative systematic error in images 314 float skyErr = psMetadataLookupF32(NULL, subRecipe, "SKY.ERR"); // Additional error in sky 315 float covarFrac = psMetadataLookupF32(NULL, subRecipe, "COVAR.FRAC"); // Fraction for covariance calculation 316 317 const char *typeStr = psMetadataLookupStr(NULL, subRecipe, "KERNEL.TYPE"); // Kernel type 318 pmSubtractionKernelsType type = pmSubtractionKernelsTypeFromString(typeStr); // Kernel type 319 psVector *widths = psMetadataLookupPtr(NULL, subRecipe, "ISIS.WIDTHS"); // ISIS Gaussian widths 320 psVector *orders = psMetadataLookupPtr(NULL, subRecipe, "ISIS.ORDERS"); // ISIS Polynomial orders 321 int inner = psMetadataLookupS32(NULL, subRecipe, "INNER"); // Inner radius 322 int ringsOrder = psMetadataLookupS32(NULL, subRecipe, "RINGS.ORDER"); // RINGS polynomial order 323 int binning = psMetadataLookupS32(NULL, subRecipe, "SPAM.BINNING"); // Binning for SPAM kernel 324 float badFrac = psMetadataLookupF32(NULL, subRecipe, "BADFRAC"); // Maximum bad fraction 325 bool optimum = psMetadataLookupBool(&mdok, subRecipe, "OPTIMUM"); // Derive optimum parameters? 326 float optMin = psMetadataLookupF32(&mdok, subRecipe, "OPTIMUM.MIN"); // Minimum width for search 327 float optMax = psMetadataLookupF32(&mdok, subRecipe, "OPTIMUM.MAX"); // Maximum width for search 328 float optStep = psMetadataLookupF32(&mdok, subRecipe, "OPTIMUM.STEP"); // Step for search 329 float optThresh = psMetadataLookupF32(&mdok, subRecipe, "OPTIMUM.TOL"); // Tolerance for search 330 int optOrder = psMetadataLookupS32(&mdok, subRecipe, "OPTIMUM.ORDER"); // Order for search 331 float poorFrac = psMetadataLookupF32(&mdok, subRecipe, "POOR.FRACTION"); // Fraction for "poor" 332 333 bool scale = psMetadataLookupBool(NULL, subRecipe, "SCALE"); // Scale kernel parameters? 334 float scaleRef = psMetadataLookupF32(NULL, subRecipe, "SCALE.REF"); // Reference for scaling 335 float scaleMin = psMetadataLookupF32(NULL, subRecipe, "SCALE.MIN"); // Minimum for scaling 336 float scaleMax = psMetadataLookupF32(NULL, subRecipe, "SCALE.MAX"); // Maximum for scaling 337 if (!isfinite(scaleRef) || !isfinite(scaleMin) || !isfinite(scaleMax)) { 338 psError(PPSTACK_ERR_CONFIG, false, 339 "Scale parameters (SCALE.REF=%f, SCALE.MIN=%f, SCALE.MAX=%f) not set in PPSUB recipe.", 340 scaleRef, scaleMin, scaleMax); 341 return false; 342 } 343 344 345 // These values are specified specifically for stacking 346 const char *stampsName = psMetadataLookupStr(NULL, config->arguments, "STAMPS");// Stamps filename 347 348 psVector *optWidths = NULL; // Vector with FWHMs for optimum search 349 if (optimum) { 350 optWidths = psVectorCreate(optWidths, optMin, optMax, optStep, PS_TYPE_F32); 351 } 352 353 pmReadout *fake = pmReadoutAlloc(NULL); // Fake readout with target PSF 354 355 psStats *bg = psStatsAlloc(PS_STAT_ROBUST_STDEV); // Statistics for background 356 psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS); // Random number generator 357 if (!psImageBackground(bg, NULL, readout->image, readout->mask, maskVal | maskBad, rng)) { 358 psError(PPSTACK_ERR_DATA, false, "Can't measure background for image."); 359 psFree(fake); 360 psFree(optWidths); 361 psFree(conv); 362 psFree(bg); 363 psFree(rng); 364 return false; 365 } 366 float minFlux = NOISE_FRACTION * bg->robustStdev; // Minimum flux level for fake image 402 psString regex = NULL; // Regular expression 403 psStringAppend(®ex, "^%s$", PM_SUBTRACTION_ANALYSIS_REGION); 404 psMetadataIterator *iter = psMetadataIteratorAlloc(readout->analysis, PS_LIST_HEAD, regex); 405 psFree(regex); 406 psMetadataItem *item = NULL;// Item from iteration 407 while ((item = psMetadataGetAndIncrement(iter))) { 408 assert(item->type == PS_DATA_REGION); 409 regions = psArrayAdd(regions, ARRAY_BUFFER, item->data.V); 410 } 411 psFree(iter); 412 } 413 414 psArray *kernels = options->kernels->data[index] = psArrayAllocEmpty(ARRAY_BUFFER); // Match kernels 415 { 416 psString regex = NULL; // Regular expression 417 psStringAppend(®ex, "^%s$", PM_SUBTRACTION_ANALYSIS_KERNEL); 418 psMetadataIterator *iter = psMetadataIteratorAlloc(readout->analysis, PS_LIST_HEAD, regex); 419 psFree(regex); 420 psMetadataItem *item = NULL;// Item from iteration 421 while ((item = psMetadataGetAndIncrement(iter))) { 422 assert(item->type == PS_DATA_UNKNOWN); 423 pmSubtractionKernels *kernel = item->data.V; // Kernel used in subtraction 424 kernels = psArrayAdd(kernels, ARRAY_BUFFER, kernel); 425 } 426 psFree(iter); 427 } 428 psAssert((regions)->n == (kernels)->n, "Number of match regions and kernels should match"); 429 430 // Record chi^2 431 { 432 double sum = 0.0; // Sum of chi^2 433 int num = 0; // Number of measurements of chi^2 434 psString regex = NULL; // Regular expression 435 psStringAppend(®ex, "^%s$", PM_SUBTRACTION_ANALYSIS_KERNEL); 436 psMetadataIterator *iter = psMetadataIteratorAlloc(readout->analysis, PS_LIST_HEAD, regex); 437 psFree(regex); 438 psMetadataItem *item = NULL;// Item from iteration 439 while ((item = psMetadataGetAndIncrement(iter))) { 440 assert(item->type == PS_DATA_UNKNOWN); 441 pmSubtractionKernels *kernels = item->data.V; // Convolution kernels 442 sum += kernels->mean; 443 num++; 444 } 445 psFree(iter); 446 options->matchChi2->data.F32[index] = sum / (psImageCovarianceFactor(readout->covariance) * num); 447 } 448 449 return true; 450 } 451 452 // Kernel normalisation for convolved readout 453 bool renormKernel(pmReadout *readout, psphotStackOptions *options, int index) { 454 455 double sum = 0.0; // Sum of chi^2 456 int num = 0; // Number of measurements of chi^2 457 psString regex = NULL; // Regular expression 458 psStringAppend(®ex, "^%s$", PM_SUBTRACTION_ANALYSIS_NORM); 459 psMetadataIterator *iter = psMetadataIteratorAlloc(readout->analysis, PS_LIST_HEAD, regex); 460 psFree(regex); 461 psMetadataItem *item = NULL;// Item from iteration 462 while ((item = psMetadataGetAndIncrement(iter))) { 463 assert(item->type == PS_TYPE_F32); 464 float norm = item->data.F32; // Normalisation 465 sum += norm; 466 num++; 467 } 468 psFree(iter); 469 float conv = sum/num; // Mean normalisation from convolution 470 float stars = powf(10.0, -0.4 * options->norm->data.F32[index]); // Normalisation from stars 471 float renorm = stars / conv; // Renormalisation to apply 472 psLogMsg("psphotStack", PS_LOG_INFO, "Renormalising image %d by %f (kernel: %f, stars: %f)\n", index, renorm, conv, stars); 473 474 psBinaryOp(readout->image, readout->image, "*", psScalarAlloc(renorm, PS_TYPE_F32)); 475 psBinaryOp(readout->variance, readout->variance, "*", psScalarAlloc(PS_SQR(renorm), PS_TYPE_F32)); 476 return true; 477 } 478 479 // adjust scaling for readout (remove background, ..., determine weighting) 480 bool rescaleData(pmReadout *readout, pmConfig *config, psphotStackOptions *options, int index) { 481 482 psMetadata *stackRecipe = psMetadataLookupMetadata(NULL, config->recipes, "PPSTACK"); // ppStack recipe 483 psAssert(stackRecipe, "We've thrown an error on this before."); 484 485 // Look up appropriate values from the ppSub recipe 486 psMetadata *subRecipe = psMetadataLookupMetadata(NULL, config->recipes, "PPSUB"); // PPSUB recipe 487 psAssert(subRecipe, "recipe missing"); 488 489 psString maskValStr = psMetadataLookupStr(NULL, subRecipe, "MASK.VAL"); // Name of bits to mask going in 490 psString maskBadStr = psMetadataLookupStr(NULL, stackRecipe, "MASK.BAD"); // Name of bits to mask for bad 491 492 psImageMaskType maskVal = pmConfigMaskGet(maskValStr, config); // Bits to mask going in to pmSubtractionMatch 493 psImageMaskType maskBad = pmConfigMaskGet(maskBadStr, config); // Bits to mask for bad pixels 494 495 // Ensure the background value is zero 496 psStats *bg = psStatsAlloc(PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV); // Statistics for background 497 psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS); // Random number generator 498 499 // XXX why is this in config->arguments and not recipe? 500 if (!psMetadataLookupBool(NULL, config->arguments, "PPSTACK.SKIP.BG.SUB")) { 501 if (!psImageBackground(bg, NULL, readout->image, readout->mask, maskVal | maskBad, rng)) { 502 psAbort("Can't measure background for image."); 503 // XXX we used to clear error: why is this acceptable? psErrorClear(); 504 } 505 506 float value = psStatsGetValue(bg, PS_STAT_ROBUST_MEDIAN); 507 float stdev = psStatsGetValue(bg, PS_STAT_ROBUST_STDEV); 508 509 psLogMsg("psphotStack", PS_LOG_INFO, "Correcting convolved image background by %lf (+/- %lf)", value, stdev); 510 psBinaryOp(readout->image, readout->image, "-", psScalarAlloc(value, PS_TYPE_F32)); 511 } 512 513 if (!stackRenormaliseReadout(config, readout)) { 514 psFree(rng); 515 psFree(bg); 516 return false; 517 } 518 519 // Measure the variance level for the weighting 520 if (psMetadataLookupBool(NULL, stackRecipe, "WEIGHTS")) { 521 if (!psImageBackground(bg, NULL, readout->variance, readout->mask, maskVal | maskBad, rng)) { 522 psError(PSPHOT_ERR_DATA, false, "Can't measure mean variance for image."); 367 523 psFree(rng); 368 524 psFree(bg); 369 370 // For the sake of stamps, remove nearby sources 371 psArray *stampSources = stackSourcesFilter(options->sourceLists->data[index], 372 footprint); // Filtered list of sources 373 374 bool oldThreads = pmReadoutFakeThreads(true); // Old threading state 375 if (!pmReadoutFakeFromSources(fake, readout->image->numCols, readout->image->numRows, 376 stampSources, SOURCE_MASK, NULL, NULL, options->psf, 377 minFlux, footprint + size, false, true)) { 378 psError(PPSTACK_ERR_DATA, false, "Unable to generate fake image with target PSF."); 379 psFree(fake); 380 psFree(optWidths); 381 psFree(conv); 382 return false; 383 } 384 pmReadoutFakeThreads(oldThreads); 385 386 fake->mask = psImageCopy(NULL, readout->mask, PS_TYPE_IMAGE_MASK); 387 388 // Add the background into the target image 389 psImage *bgImage = stackBackgroundModel(readout, config); // Image of background 390 psBinaryOp(fake->image, fake->image, "+", bgImage); 391 psFree(bgImage); 392 393 dumpImage(); 394 395 if (threads > 0) { 396 pmSubtractionThreadsInit(); 397 } 398 399 // Do the image matching 400 pmSubtractionKernels *kernel = psMetadataLookupPtr(&mdok, readout->analysis, PM_SUBTRACTION_ANALYSIS_KERNEL); // Conv kernel 401 if (kernel) { 402 if (!pmSubtractionMatchPrecalc(NULL, conv, fake, readout, readout->analysis, 403 stride, kernelError, covarFrac, maskVal, maskBad, maskPoor, 404 poorFrac, badFrac)) { 405 psError(psErrorCodeLast(), false, "Unable to convolve images."); 406 psFree(fake); 407 psFree(optWidths); 408 psFree(stampSources); 409 psFree(conv); 410 if (threads > 0) { 411 pmSubtractionThreadsFinalize(); 412 } 413 return false; 414 } 415 } else { 416 // Scale the input parameters 417 psVector *widthsCopy = psVectorCopy(NULL, widths, PS_TYPE_F32); // Copy of kernel widths 418 if (scale && !pmSubtractionParamsScale(&size, &footprint, widthsCopy, 419 options->inputSeeing->data.F32[index], 420 options->targetSeeing, scaleRef, scaleMin, scaleMax)) { 421 psError(psErrorCodeLast(), false, "Unable to scale kernel parameters"); 422 psFree(fake); 423 psFree(optWidths); 424 psFree(stampSources); 425 psFree(conv); 426 psFree(widthsCopy); 427 if (threads > 0) { 428 pmSubtractionThreadsFinalize(); 429 } 430 return false; 431 } 432 433 if (!pmSubtractionMatch(NULL, conv, fake, readout, footprint, stride, regionSize, spacing, 434 threshold, stampSources, stampsName, type, size, order, widthsCopy, 435 orders, inner, ringsOrder, binning, penalty, 436 optimum, optWidths, optOrder, optThresh, iter, rej, normFrac, 437 sysError, skyErr, kernelError, covarFrac, maskVal, maskBad, maskPoor, 438 poorFrac, badFrac, PM_SUBTRACTION_MODE_2)) { 439 psError(psErrorCodeLast(), false, "Unable to match images."); 440 psFree(fake); 441 psFree(optWidths); 442 psFree(stampSources); 443 psFree(conv); 444 psFree(widthsCopy); 445 if (threads > 0) { 446 pmSubtractionThreadsFinalize(); 447 } 448 return false; 449 } 450 psFree(widthsCopy); 451 } 452 453 dumpImage2(); 454 455 psFree(fake); 456 psFree(optWidths); 457 psFree(stampSources); 458 459 if (threads > 0) { 460 pmSubtractionThreadsFinalize(); 461 } 462 463 // Replace original images with convolved 464 psFree(readout->image); 465 psFree(readout->mask); 466 psFree(readout->variance); 467 psFree(readout->covariance); 468 readout->image = psMemIncrRefCounter(conv->image); 469 readout->mask = psMemIncrRefCounter(conv->mask); 470 readout->variance = psMemIncrRefCounter(conv->variance); 471 readout->covariance = psImageCovarianceTruncate(conv->covariance, COVAR_FRAC); 472 473 } 474 475 bool saveMatchData () { 476 // Extract the regions and solutions used in the image matching 477 // This stops them from being freed when we iterate back up the FPA 478 psArray *regions = options->regions->data[index] = psArrayAllocEmpty(ARRAY_BUFFER); // Match regions 479 { 480 psString regex = NULL; // Regular expression 481 psStringAppend(®ex, "^%s$", PM_SUBTRACTION_ANALYSIS_REGION); 482 psMetadataIterator *iter = psMetadataIteratorAlloc(conv->analysis, PS_LIST_HEAD, regex); 483 psFree(regex); 484 psMetadataItem *item = NULL;// Item from iteration 485 while ((item = psMetadataGetAndIncrement(iter))) { 486 assert(item->type == PS_DATA_REGION); 487 regions = psArrayAdd(regions, ARRAY_BUFFER, item->data.V); 488 } 489 psFree(iter); 525 return false; 490 526 } 491 psArray *kernels = options->kernels->data[index] = psArrayAllocEmpty(ARRAY_BUFFER); // Match kernels 492 { 493 psString regex = NULL; // Regular expression 494 psStringAppend(®ex, "^%s$", PM_SUBTRACTION_ANALYSIS_KERNEL); 495 psMetadataIterator *iter = psMetadataIteratorAlloc(conv->analysis, PS_LIST_HEAD, regex); 496 psFree(regex); 497 psMetadataItem *item = NULL;// Item from iteration 498 while ((item = psMetadataGetAndIncrement(iter))) { 499 assert(item->type == PS_DATA_UNKNOWN); 500 pmSubtractionKernels *kernel = item->data.V; // Kernel used in subtraction 501 kernels = psArrayAdd(kernels, ARRAY_BUFFER, kernel); 502 } 503 psFree(iter); 504 } 505 psAssert((regions)->n == (kernels)->n, "Number of match regions and kernels should match"); 506 } 507 508 bool saveChiSquare() { 509 // Record chi^2 510 { 511 double sum = 0.0; // Sum of chi^2 512 int num = 0; // Number of measurements of chi^2 513 psString regex = NULL; // Regular expression 514 psStringAppend(®ex, "^%s$", PM_SUBTRACTION_ANALYSIS_KERNEL); 515 psMetadataIterator *iter = psMetadataIteratorAlloc(conv->analysis, PS_LIST_HEAD, regex); 516 psFree(regex); 517 psMetadataItem *item = NULL;// Item from iteration 518 while ((item = psMetadataGetAndIncrement(iter))) { 519 assert(item->type == PS_DATA_UNKNOWN); 520 pmSubtractionKernels *kernels = item->data.V; // Convolution kernels 521 sum += kernels->mean; 522 num++; 523 } 524 psFree(iter); 525 options->matchChi2->data.F32[index] = sum / (psImageCovarianceFactor(readout->covariance) * num); 526 } 527 528 } 529 530 bool renormKernel() { 531 // Kernel normalisation 532 { 533 double sum = 0.0; // Sum of chi^2 534 int num = 0; // Number of measurements of chi^2 535 psString regex = NULL; // Regular expression 536 psStringAppend(®ex, "^%s$", PM_SUBTRACTION_ANALYSIS_NORM); 537 psMetadataIterator *iter = psMetadataIteratorAlloc(conv->analysis, PS_LIST_HEAD, regex); 538 psFree(regex); 539 psMetadataItem *item = NULL;// Item from iteration 540 while ((item = psMetadataGetAndIncrement(iter))) { 541 assert(item->type == PS_TYPE_F32); 542 float norm = item->data.F32; // Normalisation 543 sum += norm; 544 num++; 545 } 546 psFree(iter); 547 float conv = sum/num; // Mean normalisation from convolution 548 float stars = powf(10.0, -0.4 * options->norm->data.F32[index]); // Normalisation from stars 549 float renorm = stars / conv; // Renormalisation to apply 550 psLogMsg("ppStack", PS_LOG_INFO, "Renormalising image %d by %f (kernel: %f, stars: %f)\n", 551 index, renorm, conv, stars); 552 psBinaryOp(readout->image, readout->image, "*", psScalarAlloc(renorm, PS_TYPE_F32)); 553 psBinaryOp(readout->variance, readout->variance, "*", psScalarAlloc(PS_SQR(renorm), PS_TYPE_F32)); 554 } 555 556 } 527 options->weightings->data.F32[index] = 1.0 / (psStatsGetValue(bg, PS_STAT_ROBUST_MEDIAN) * psImageCovarianceFactor(readout->covariance)); 528 } else { 529 options->weightings->data.F32[index] = 1.0; 530 } 531 psLogMsg("psphotStack", PS_LOG_INFO, "Weighting for image %d is %f\n", index, options->weightings->data.F32[index]); 532 533 psFree(rng); 534 psFree(bg); 535 return true; 536 } 537 538 # define NOISE_FRACTION 0.01 // Set minimum flux to this fraction of noise 539 # define SOURCE_MASK (PM_SOURCE_MODE_FAIL | PM_SOURCE_MODE_DEFECT | PM_SOURCE_MODE_SATURATED | PM_SOURCE_MODE_CR_LIMIT | PM_SOURCE_MODE_EXT_LIMIT) // Mask to apply to input sources 540 541 // generate a fake readout against which to PSF match 542 pmReadout *makeFakeReadout(pmConfig *config, pmReadout *readoutRaw, psArray *sources, pmPSF *psf, psImageMaskType maskVal, int fullSize) { 543 544 pmReadout *fake = pmReadoutAlloc(NULL); // Fake readout with target PSF 545 546 psStats *bg = psStatsAlloc(PS_STAT_ROBUST_STDEV); // Statistics for background 547 psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS); // Random number generator 548 if (!psImageBackground(bg, NULL, readoutRaw->image, readoutRaw->mask, maskVal, rng)) { 549 psError(PSPHOT_ERR_DATA, false, "Can't measure background for image."); 550 psFree(fake); 551 psFree(bg); 552 psFree(rng); 553 return NULL; 554 } 555 float minFlux = NOISE_FRACTION * bg->robustStdev; // Minimum flux level for fake image 556 psFree(rng); 557 psFree(bg); 558 559 bool oldThreads = pmReadoutFakeThreads(true); // Old threading state 560 if (!pmReadoutFakeFromSources(fake, readoutRaw->image->numCols, readoutRaw->image->numRows, sources, SOURCE_MASK, NULL, NULL, psf, minFlux, fullSize, false, true)) { 561 psError(PSPHOT_ERR_DATA, false, "Unable to generate fake image with target PSF."); 562 psFree(fake); 563 return NULL; 564 } 565 pmReadoutFakeThreads(oldThreads); 566 567 fake->mask = psImageCopy(NULL, readoutRaw->mask, PS_TYPE_IMAGE_MASK); 568 569 // Add the background into the target image 570 psImage *bgImage = stackBackgroundModel(readoutRaw, config); // Image of background 571 psBinaryOp(fake->image, fake->image, "+", bgImage); 572 psFree(bgImage); 573 574 return fake; 575 } 576 577 // set the widths 578 psVector *SetOptWidths (bool *optimum, psMetadata *recipe) { 579 580 bool status; 581 582 *optimum = psMetadataLookupBool(&status, recipe, "OPTIMUM"); // Derive optimum parameters? 583 psAssert (status, "missing recipe value %s", "OPTIMUM"); 584 585 psVector *optWidths = NULL; // Vector with FWHMs for optimum search 586 587 if (*optimum) { 588 float optMin = psMetadataLookupF32(&status, recipe, "OPTIMUM.MIN"); // Minimum width for search 589 psAssert (status, "missing recipe value %s", "OPTIMUM.MIN"); 590 591 float optMax = psMetadataLookupF32(&status, recipe, "OPTIMUM.MAX"); // Maximum width for search 592 psAssert (status, "missing recipe value %s", "OPTIMUM.MAX"); 593 594 float optStep = psMetadataLookupF32(&status, recipe, "OPTIMUM.STEP"); // Step for search 595 psAssert (status, "missing recipe value %s", "OPTIMUM.STEP"); 596 597 optWidths = psVectorCreate(optWidths, optMin, optMax, optStep, PS_TYPE_F32); 598 } 599 600 return optWidths; 601 } -
branches/eam_branches/psphot.20100506/src/psphotStackParseCamera.c
r27657 r27876 25 25 psMetadata *input = item->data.md; // The input metadata of interest 26 26 27 // look for 'IMAGE', 'MASK', 'VARIANCE' in folder (only 'IMAGE' is required) 28 29 psString image = psMetadataLookupStr(NULL, input, "IMAGE"); // Name of image 30 if (!image || strlen(image) == 0) { 31 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Component %s lacks IMAGE of type STR", item->name); 27 pmFPAfile *rawInputFile = NULL; 28 pmFPAfile *cnvInputFile = NULL; 29 30 // RAW (unconvolved) input data (RAW:IMAGE, RAW:MASK, RAW:VARIANCE, RAW:PSF) 31 psString rawImage = psMetadataLookupStr(NULL, input, "RAW:IMAGE"); // Name of image 32 if (rawImage && strlen(rawImage) > 0) { 33 pmFPAfile *rawInputFile = defineFile(config, NULL, "PSPHOT.STACK.INPUT.RAW", rawImage, PM_FPA_FILE_IMAGE); // File for image 34 if (!rawInputFile) { 35 psError(PS_ERR_UNKNOWN, false, "Unable to define file from image %d (%s)", i, rawImage); 36 return false; 37 } 38 psString mask = psMetadataLookupStr(&status, input, "RAW:MASK"); // Name of mask 39 if (mask && strlen(mask) > 0) { 40 if (!defineFile(config, rawInputFile, "PSPHOT.STACK.MASK.RAW", mask, PM_FPA_FILE_MASK)) { 41 psError(PS_ERR_UNKNOWN, false, "Unable to define file from mask %d (%s)", i, mask); 42 return false; 43 } 44 } 45 psString variance = psMetadataLookupStr(&status, input, "RAW:VARIANCE"); // Name of variance map 46 if (variance && strlen(variance) > 0) { 47 if (!defineFile(config, rawInputFile, "PSPHOT.STACK.VARIANCE.RAW", variance, PM_FPA_FILE_VARIANCE)) { 48 psError(PS_ERR_UNKNOWN, false, "Unable to define file from variance %d (%s)", i, variance); 49 return false; 50 } 51 } 52 psString psf = psMetadataLookupStr(&status, input, "RAW:PSF"); // Name of mask 53 if (psf && strlen(psf) > 0) { 54 if (!defineFile(config, rawInputFile, "PSPHOT.STACK.PSF.RAW", psf, PM_FPA_FILE_PSF)) { 55 psError(PS_ERR_UNKNOWN, false, "Unable to define file from psf %d (%s)", i, psf); 56 return false; 57 } 58 } 59 } 60 61 // CNV (convolved) input data (CNV:IMAGE, CNV:MASK, CNV:VARIANCE, CNV:PSF) 62 psString cnvImage = psMetadataLookupStr(NULL, input, "CNV:IMAGE"); // Name of image 63 if (cnvImage && strlen(cnvImage) > 0) { 64 pmFPAfile *cnvInputFile = defineFile(config, NULL, "PSPHOT.STACK.INPUT.CNV", cnvImage, PM_FPA_FILE_IMAGE); // File for image 65 if (!cnvInputFile) { 66 psError(PS_ERR_UNKNOWN, false, "Unable to define file from image %d (%s)", i, cnvImage); 67 return false; 68 } 69 psString mask = psMetadataLookupStr(&status, input, "CNV:MASK"); // Name of mask 70 if (mask && strlen(mask) > 0) { 71 if (!defineFile(config, cnvInputFile, "PSPHOT.STACK.MASK.CNV", mask, PM_FPA_FILE_MASK)) { 72 psError(PS_ERR_UNKNOWN, false, "Unable to define file from mask %d (%s)", i, mask); 73 return false; 74 } 75 } 76 psString variance = psMetadataLookupStr(&status, input, "CNV:VARIANCE"); // Name of variance map 77 if (variance && strlen(variance) > 0) { 78 if (!defineFile(config, cnvInputFile, "PSPHOT.STACK.VARIANCE.CNV", variance, PM_FPA_FILE_VARIANCE)) { 79 psError(PS_ERR_UNKNOWN, false, "Unable to define file from variance %d (%s)", i, variance); 80 return false; 81 } 82 } 83 psString psf = psMetadataLookupStr(&status, input, "CNV:PSF"); // Name of mask 84 if (psf && strlen(psf) > 0) { 85 if (!defineFile(config, cnvInputFile, "PSPHOT.STACK.PSF.CNV", psf, PM_FPA_FILE_PSF)) { 86 psError(PS_ERR_UNKNOWN, false, "Unable to define file from psf %d (%s)", i, psf); 87 return false; 88 } 89 } 90 } 91 92 if (!rawInputFile && !cnvInputFile) { 93 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Component %s (%d) lacks IMAGE of type STR", item->name, i); 32 94 return false; 33 95 } 34 pmFPAfile *imageFile = defineFile(config, NULL, "PSPHOT.INPUT", image, PM_FPA_FILE_IMAGE); // File for image 35 if (!imageFile) { 36 psError(PS_ERR_UNKNOWN, false, "Unable to define file from image %d (%s)", i, image); 37 return false; 38 } 39 40 psString mask = psMetadataLookupStr(&status, input, "MASK"); // Name of mask 41 if (mask && strlen(mask) > 0) { 42 if (!defineFile(config, imageFile, "PSPHOT.MASK", mask, PM_FPA_FILE_MASK)) { 43 psError(PS_ERR_UNKNOWN, false, "Unable to define file from mask %d (%s)", i, mask); 44 return false; 45 } 46 } 47 48 psString variance = psMetadataLookupStr(&status, input, "VARIANCE"); // Name of variance map 49 if (variance && strlen(variance) > 0) { 50 if (!defineFile(config, imageFile, "PSPHOT.VARIANCE", variance, PM_FPA_FILE_VARIANCE)) { 51 psError(PS_ERR_UNKNOWN, false, "Unable to define file from variance %d (%s)", i, variance); 52 return false; 53 } 54 } 55 // the output sources are carried on the input->fpa structures 56 pmFPAfile *outsources = pmFPAfileDefineOutputFromFile (config, imageFile, "PSPHOT.STACK.OUTPUT"); 57 if (!outsources) { 58 psError(PSPHOT_ERR_CONFIG, false, "Cannot find a rule for PSPHOT.STACK.OUTPUT"); 59 return false; 60 } 61 outsources->save = true; 62 outsources->fileID = i; // this is used to generate output names 96 97 psString sources = psMetadataLookupStr(&status, input, "SOURCES"); // Name of mask 98 pmFPAfile *srcInputFile = rawInputFile ? rawInputFile : cnvInputFile; 99 if (sources && strlen(sources) > 0) { 100 if (!defineFile(config, srcInputFile, "PSPHOT.STACK.SOURCES.CNV", sources, PM_FPA_FILE_CMF)) { 101 psError(PS_ERR_UNKNOWN, false, "Unable to define file from sources %d (%s)", i, sources); 102 return false; 103 } 104 } 105 106 // generate an pmFPAimage for the output convolved image 107 // XXX output of these files should be optional 108 { 109 pmFPAfile *outputImage = pmFPAfileDefineOutput(config, NULL, "PSPHOT.STACK.OUTPUT.IMAGE"); 110 if (!outputImage) { 111 psError(PSPHOT_ERR_CONFIG, false, "Trouble defining PSPHOT.STACK.OUTPUT.IMAGE"); 112 return false; 113 } 114 outputImage->save = true; 115 outsources->fileID = i; // this is used to generate output names 116 117 pmFPAfile *outputMask = pmFPAfileDefineOutput(config, outputImage->fpa, "PSPHOT.STACK.OUTPUT.MASK"); 118 if (!outputMask) { 119 psError(PS_ERR_IO, false, _("Unable to generate output file from PSPHOT.STACK.OUTPUT.MASK")); 120 return NULL; 121 } 122 if (outputMask->type != PM_FPA_FILE_MASK) { 123 psError(PS_ERR_IO, true, "PSPHOT.STACK.OUTPUT.MASK is not of type MASK"); 124 return NULL; 125 } 126 outputMask->save = true; 127 128 pmFPAfile *outputVariance = pmFPAfileDefineOutput(config, outputImage->fpa, "PSPHOT.STACK.OUTPUT.VARIANCE"); 129 if (!outputVariance) { 130 psError(PS_ERR_IO, false, _("Unable to generate output file from PSPHOT.STACK.OUTPUT.VARIANCE")); 131 return NULL; 132 } 133 if (outputVariance->type != PM_FPA_FILE_VARIANCE) { 134 psError(PS_ERR_IO, true, "PSPHOT.STACK.OUTPUT.VARIANCE is not of type VARIANCE"); 135 return NULL; 136 } 137 outputVariance->save = true; 138 139 // the output sources are carried on the outputImage->fpa structures 140 pmFPAfile *outsources = pmFPAfileDefineOutputFromFile (config, outputImage, "PSPHOT.STACK.OUTPUT"); 141 if (!outsources) { 142 psError(PSPHOT_ERR_CONFIG, false, "Cannot find a rule for PSPHOT.STACK.OUTPUT"); 143 return false; 144 } 145 outsources->save = true; 146 outsources->fileID = i; // this is used to generate output names 147 } 63 148 } 64 149 psMetadataRemoveKey(config->arguments, "FILENAMES"); … … 71 156 72 157 // generate an pmFPAimage for the chisqImage 73 pmFPAfile *chisqImage = pmFPAfileDefineOutput(config, NULL, "PSPHOT.CHISQ.IMAGE"); 74 if (!chisqImage) { 75 psError(PSPHOT_ERR_CONFIG, false, "Trouble defining PSPHOT.CHISQ.IMAGE"); 76 return false; 77 } 78 chisqImage->save = true; 79 80 pmFPAfile *chisqMask = pmFPAfileDefineOutput(config, chisqImage->fpa, "PSPHOT.CHISQ.MASK"); 81 if (!chisqMask) { 82 psError(PS_ERR_IO, false, _("Unable to generate output file from PSPHOT.CHISQ.MASK")); 83 return NULL; 84 } 85 if (chisqMask->type != PM_FPA_FILE_MASK) { 86 psError(PS_ERR_IO, true, "PSPHOT.CHISQ.MASK is not of type MASK"); 87 return NULL; 88 } 89 chisqMask->save = true; 90 91 pmFPAfile *chisqVariance = pmFPAfileDefineOutput(config, chisqImage->fpa, "PSPHOT.CHISQ.VARIANCE"); 92 if (!chisqVariance) { 93 psError(PS_ERR_IO, false, _("Unable to generate output file from PSPHOT.CHISQ.VARIANCE")); 94 return NULL; 95 } 96 if (chisqVariance->type != PM_FPA_FILE_VARIANCE) { 97 psError(PS_ERR_IO, true, "PSPHOT.CHISQ.VARIANCE is not of type VARIANCE"); 98 return NULL; 99 } 100 chisqVariance->save = true; 101 102 # if (0) 103 // define the additional input/output files associated with psphot 104 // XXX figure out which files are needed by psphotStack 105 if (false && !psphotDefineFiles (config, input)) { 106 psError(PSPHOT_ERR_CONFIG, false, "Trouble defining the additional input/output files"); 107 return false; 108 } 109 # endif 158 // XXX output of these files should be optional 159 { 160 pmFPAfile *chisqImage = pmFPAfileDefineOutput(config, NULL, "PSPHOT.CHISQ.IMAGE"); 161 if (!chisqImage) { 162 psError(PSPHOT_ERR_CONFIG, false, "Trouble defining PSPHOT.CHISQ.IMAGE"); 163 return false; 164 } 165 chisqImage->save = true; 166 167 pmFPAfile *chisqMask = pmFPAfileDefineOutput(config, chisqImage->fpa, "PSPHOT.CHISQ.MASK"); 168 if (!chisqMask) { 169 psError(PS_ERR_IO, false, _("Unable to generate output file from PSPHOT.CHISQ.MASK")); 170 return NULL; 171 } 172 if (chisqMask->type != PM_FPA_FILE_MASK) { 173 psError(PS_ERR_IO, true, "PSPHOT.CHISQ.MASK is not of type MASK"); 174 return NULL; 175 } 176 chisqMask->save = true; 177 178 pmFPAfile *chisqVariance = pmFPAfileDefineOutput(config, chisqImage->fpa, "PSPHOT.CHISQ.VARIANCE"); 179 if (!chisqVariance) { 180 psError(PS_ERR_IO, false, _("Unable to generate output file from PSPHOT.CHISQ.VARIANCE")); 181 return NULL; 182 } 183 if (chisqVariance->type != PM_FPA_FILE_VARIANCE) { 184 psError(PS_ERR_IO, true, "PSPHOT.CHISQ.VARIANCE is not of type VARIANCE"); 185 return NULL; 186 } 187 chisqVariance->save = true; 188 } 110 189 111 190 psTrace("psphot", 1, "Done with psphotStackParseCamera...\n"); … … 145 224 } 146 225 226 227 /*** 228 * 229 * psphotStack : 230 231 * * inputs: 232 * * unconvolved images 233 * * raw convolved images 234 * * psfs (unconvolved or convolved?) 235 * * sources 236 237 * optionally convolve the unconvolved or the raw inputs 238 * optionally perform no convolutions 239 * optionally save the psf-matched images 240 241 */ 242 243 244 # if (0) 245 // define the additional input/output files associated with psphot 246 // XXX figure out which files are needed by psphotStack 247 if (false && !psphotDefineFiles (config, input)) { 248 psError(PSPHOT_ERR_CONFIG, false, "Trouble defining the additional input/output files"); 249 return false; 250 } 251 # endif 252
Note:
See TracChangeset
for help on using the changeset viewer.
