IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 35563


Ignore:
Timestamp:
May 9, 2013, 12:26:48 PM (13 years ago)
Author:
eugene
Message:

major upgrades to pswarp to enable skycell warp -> chip

Location:
trunk/pswarp
Files:
1 deleted
14 edited
14 copied

Legend:

Unmodified
Added
Removed
  • trunk/pswarp/src/Makefile.am

    r28043 r35563  
    2828        pswarp.c                        \
    2929        pswarpArguments.c               \
    30         pswarpExit.c                    \
     30        pswarpExitCode.c                \
    3131        pswarpLoop.c                    \
     32        pswarpLoopBackground.c          \
     33        pswarpCleanup.c                 \
     34        pswarpStatsFile.c               \
    3235        pswarpDefine.c                  \
    33         pswarpDefineSkycell.c           \
     36        pswarpDefineBackground.c        \
     37        pswarpDefineSkycell.c           \
     38        pswarpDefineLayout.c            \
    3439        pswarpErrorCodes.c              \
     40        pswarpLoadAstrometry.c          \
     41        pswarpMakePSF.c                 \
    3542        pswarpMapGrid.c                 \
    3643        pswarpMaskStats.c               \
    3744        pswarpMatchRange.c              \
     45        pswarpOverlaps.c                \
     46        pswarpOptions.c                 \
    3847        pswarpParseCamera.c             \
    3948        pswarpPixelsLit.c               \
     
    4352        pswarpTransformSources.c        \
    4453        pswarpTransformTile.c           \
     54        pswarpUpdateStatistics.c        \
     55        pswarpUpdateMetadata.c          \
    4556        pswarpVersion.c                 \
    4657        pswarpFiles.c
  • trunk/pswarp/src/pswarp.c

    r34800 r35563  
    1212
    1313#include "pswarp.h"
    14 #include "pswarpFileNames.h"
    1514
    1615int main (int argc, char **argv)
     
    2221    psphotInit();
    2322
    24     const char *statsName = NULL;       // Filename for statistics
    25     psMetadata *stats = NULL;           // Container for statistics
    26     FILE *statsFile = NULL;             // File stream for statistics
    27 
    2823    pmConfig *config = pswarpArguments(argc, argv);
    2924    if (!config) {
    30         goto DIE;
     25        pswarpCleanup(config, NULL);
    3126    }
     27
     28    pswarpStatsFile *statsFile = pswarpStatsFileOpen (config);
    3229
    3330    pswarpVersionPrint();
     
    3532    // load identify the data sources
    3633    if (!pswarpParseCamera(config)) {
    37         goto DIE;
     34        pswarpCleanup(config, statsFile);
    3835    }
    3936
    4037    if (!pswarpOptions(config)) {
    41         goto DIE;
     38        pswarpCleanup(config, statsFile);
    4239    }
    4340
    44     // load the skycell layout information
    45     if (!pswarpDefine(config)) {
    46         goto DIE;
    47     }
    48     if (psMetadataLookupBool(NULL,config->arguments,"BACKGROUND.MODEL")) {
    49       if (!pswarpDefineBackground(config)) {
    50         goto DIE;
    51       }
     41    // load the input & output astrometry, find the output overlaps, generate the output pixels
     42    if (!pswarpDefineLayout(config)) {
     43        pswarpCleanup(config, statsFile);
    5244    }
    5345
    54     // Open the statistics file
    55     bool mdok;                          ///< Status of MD lookup
    56     statsName = psMetadataLookupStr(&mdok, config->arguments, "STATS"); ///< Filename for statistics
    57     if (mdok && statsName && strlen(statsName) > 0) {
    58         psString resolved = pmConfigConvertFilename(statsName, config, true, true);
    59         statsFile = fopen(resolved, "w");
    60         if (!statsFile) {
    61             psError(PS_ERR_IO, true, "Unable to open statistics file %s for writing.\n", resolved);
    62             psFree(resolved);
    63             goto DIE;
    64         }
    65         psFree(resolved);
    66         stats = psMetadataAlloc();
    67         psMetadataAddS32(stats, PS_LIST_TAIL, "QUALITY", 0, "No problems", 0);
     46    // load input pixels & and warp
     47    if (!pswarpLoop(config, statsFile->md)) {
     48        pswarpCleanup(config, statsFile);
    6849    }
    6950
    70     // load and warp
    71     if (!pswarpLoop(config, stats)) {
    72         goto DIE;
    73     }
    74     if (psMetadataLookupBool(NULL,config->arguments,"BACKGROUND.MODEL")) {
    75       if (!pswarpLoopBackground(config, stats)) {
    76         fprintf(stderr,"Dying!\n");
    77         goto DIE;
    78       }
     51    // load input pixels & and warp
     52    if (!pswarpLoopBackground(config, statsFile->md)) {
     53        pswarpCleanup(config, statsFile);
    7954    }
    8055
     56    // output and free
     57    // NOTE: pswarpCleanup calls exit
    8158    psLogMsg("pswarp", PS_LOG_INFO, "complete pswarp run: %f sec\n", psTimerMark("pswarp"));
    82 
    83 DIE:
    84     {
    85         psExit exitValue = pswarpExitCode(PS_EXIT_SUCCESS); // Exit code
    86 
    87         // Ensure everything is written out, at every level
    88         pswarpFileActivation(config, detectorFiles, true);
    89         pswarpFileActivation(config, skycellFiles, true);
    90         pswarpFileActivation(config, photFiles, true);
    91         pswarpFileActivation(config, independentFiles, true);
    92         if (!pswarpIOChecksAfter(config)) {
    93             psError(psErrorCodeLast(), false, "Unable to write files.");
    94             exitValue = pswarpExitCode(exitValue);
    95             pmFPAfileFreeSetStrict(false);
    96         }
    97 
    98         // Write out summary statistics
    99         if (stats && statsFile) {
    100             psMetadataAddF32(stats, PS_LIST_TAIL, "DT_WARP", 0, "Time for warp completion",
    101                              psTimerMark("pswarp"));
    102 
    103             const char *statsMDC = psMetadataConfigFormat(stats);
    104             if (!statsMDC) {
    105                 psError(psErrorCodeLast(), false, "Unable to get statistics file.");
    106                 exitValue = pswarpExitCode(exitValue);
    107             }
    108             psFree(stats);
    109             if (fprintf(statsFile, "%s", statsMDC) != strlen(statsMDC)) {
    110                 psError(PSWARP_ERR_IO, true, "Unable to write statistics file.");
    111                 exitValue = pswarpExitCode(exitValue);
    112             }
    113             psFree(statsMDC);
    114             if (fclose(statsFile) == EOF) {
    115                 psError(PSWARP_ERR_IO, true, "Unable to close statistics file.");
    116                 exitValue = pswarpExitCode(exitValue);
    117             }
    118             pmConfigRunFilenameAddWrite(config, "STATS", statsName);
    119         }
    120 
    121         // Dump configuration
    122         psString dump_file = psMetadataLookupStr(&mdok, config->arguments, "DUMP_CONFIG");
    123         if (dump_file) {
    124             if (!pmConfigDump(config, dump_file)) {
    125                 psError(psErrorCodeLast(), false, "Unable to dump configuration");
    126                 exitValue = pswarpExitCode(exitValue);
    127             }
    128         }
    129 
    130         psThreadPoolFinalize();
    131         psMemCheckCorruption(stderr, true);
    132 
    133         psFree(config);
    134 
    135         psTimerStop();
    136         pmVisualClose();
    137         pmModelClassCleanup();
    138         pmConceptsDone();
    139         pmConfigDone();
    140         psLibFinalize();
    141 
    142         exitValue = pswarpExitCode(exitValue);
    143         return exitValue;
    144     }
     59    pswarpCleanup(config, statsFile);
    14560}
  • trunk/pswarp/src/pswarp.h

    r34800 r35563  
    2222#include <psmodules.h>
    2323#include <psphot.h>
     24#include <ppStats.h>
    2425
    2526#define THREADED 1
     
    7879} pswarpTransformTileArgs;
    7980
     81typedef struct {
     82    FILE *f;                            // File stream for statistics
     83    char *name;                         // Filename for statistics
     84    psMetadata *md;                     // Container for statistics
     85} pswarpStatsFile;
     86
    8087pswarpTransformTileArgs *pswarpTransformTileArgsAlloc(void);
    8188bool pswarpTransformTile (pswarpTransformTileArgs *args);
     
    8895bool pswarpDefineBackground (pmConfig *config);
    8996bool pswarpLoop (pmConfig *config, psMetadata *stats);
     97bool pswarpLoopSkycell (pmConfig *config, psMetadata *stats);
    9098bool pswarpLoopBackground (pmConfig *config, psMetadata *stats);
    9199psExit pswarpExitCode(psExit exitValue);
    92 bool pswarpTransformReadout (pmReadout *output, pmReadout *input, pmConfig *config);
     100bool pswarpTransformReadout (pmReadout *output, pmReadout *input, pmConfig *config, bool backgroundWarp);
    93101bool pswarpTransformSources(pmReadout *output, pmReadout *input, pmConfig *config);
    94102
     
    160168    );
    161169
     170pswarpStatsFile *pswarpStatsFileAlloc ();
     171pswarpStatsFile *pswarpStatsFileOpen (pmConfig *config);
     172bool pswarpStatsFileSave (pmConfig *config, pswarpStatsFile *statsFile);
     173
     174// cleanup memory and exit
     175void pswarpCleanup (pmConfig *config, pswarpStatsFile *statsFile) PS_ATTR_NORETURN;
     176
     177// load the astrometry header info and generate the tranformations
     178bool pswarpDefineLayout (pmConfig *config);
     179
     180// XXX function for testing
     181bool pswarpDumpOutput (pmConfig *config);
     182
     183// structure to describe approximate bounds for each fpa element (eg, chip)
     184// P,Q are a locally linear projection
     185typedef struct {
     186    psVector *Pmin;
     187    psVector *Pmax;
     188    psVector *Qmin;
     189    psVector *Qmax;
     190} pswarpBounds;
     191
     192bool pswarpFindOverlap (pmFPA *input, pmFPA *output, pswarpBounds *src, pswarpBounds *tgt);
     193psProjection *pswarpLocalFrame (pmFPA *fpa);
     194pswarpBounds *pswarpMakeBounds (pmFPA *fpa, psProjection *frame);
     195bool pswarpBoundsAppend(pswarpBounds *bounds, float Pmin, float Pmax, float Qmin, float Qmax);
     196pswarpBounds *pswarpBoundsAlloc();
     197
     198bool pswarpLoadAstrometry (pmFPAfile *target, pmFPAfile *astrom, pmConfig *config);
     199
     200bool pswarpTransformToTarget (pmFPA *output, pmReadout *input, pmConfig *config, bool backgroundWarp);
     201bool pswarpMakePSF (pmConfig *config, pmFPAfile *output, psMetadata *stats);
     202bool pswarpUpdateStatistics (pmFPA *output, psMetadata *stats, pmFPA *input, pmFPA *astrom, pmConfig *config);
     203bool pswarpUpdateMetadata (pmFPA *output, pmFPA *skycell, pmFPA *input, pmFPA *astrom, pmConfig *config, bool fullImage);
     204
     205// XXX functions in pswarpParseCamera
     206
     207bool AddStringAsArray (psMetadata *md, char *string, char *name);
     208
     209pmFPAfile *pswarpDefineInputFile(pmConfig *config,// Configuration
     210                                 pmFPAfile *bind,    // File to which to bind, or NULL
     211                                 char *filerule,     // Name of file rule
     212                                 char *argname,      // Argument name
     213                                 pmFPAfileType fileType // Type of file
     214  );
     215
     216bool pswarpParseSingleInput (pmConfig *config);
     217bool pswarpParseMultiInput (pmConfig *config, psMetadata *fileListMD);
     218
     219bool pswarpModifyChipAstrom (pmConfig *config, pmFPAview *view, pmChip *chip, pmFPAfile *astrom, bool bilevelAstrometry, double xBin, double yBin);
     220bool pswarpGetInputScales (double *xBin, double *yBin, pmConfig *config, pmFPAview *view, pmChip *chip);
  • trunk/pswarp/src/pswarpArguments.c

    r34800 r35563  
    1212
    1313# include "pswarp.h"
    14 # include <glob.h>
    15 
    1614
    1715static void usage (void) {
    18     fprintf(stderr, "USAGE: pswarp [-file image(s)] [-list imagelist] [options] (output) (skycell)\n");
     16    fprintf(stderr, "USAGE: pswarp [-input input.mdc] [-file image(s)] [-list imagelist] [options] (output) (skycell)\n");
    1917    fprintf(stderr, "  options:\n");
     18    fprintf(stderr, "    [-input input.mdc] : input image information in a metadata file\n");
     19    fprintf(stderr, "    [-file input.fits[,input.fits]] : input image to be warped\n");
    2020    fprintf(stderr, "    [-astrom astrom.cmp] : provide an alternative astrometry calibration\n");
    2121    fprintf(stderr, "    [-mask mask.fits] : provide a corresponding mask image\n");
     
    2424    exit(PS_EXIT_CONFIG_ERROR);
    2525}
    26 
    2726
    2827pmConfig *pswarpArguments (int argc, char **argv) {
     
    5554    }
    5655
     56    // XXX move to the single group below?
    5757    pmConfigFileSetsMD(config->arguments, &argc, argv, "ASTROM",   "-astrom", "-astromlist");
    5858
    59     {
    60         int arg;                        ///< Argument Number
    61         if ((arg = psArgumentGet(argc, argv, "-psphot-visual"))) {
    62             psArgumentRemove(arg, &argc, argv);
    63             pmVisualSetVisual(true);
    64         }
     59    // turn on psphot visualization
     60    if ((N = psArgumentGet(argc, argv, "-psphot-visual"))) {
     61        psArgumentRemove(N, &argc, argv);
     62        pmVisualSetVisual(true);
    6563    }
    6664
     
    8381    pswarpSetThreads();
    8482
    85     pmConfigFileSetsMD (config->arguments, &argc, argv, "INPUT", "-file", "-list");
    86     pmConfigFileSetsMD (config->arguments, &argc, argv, "MASK", "-mask", "-masklist");
    87     pmConfigFileSetsMD (config->arguments, &argc, argv, "VARIANCE", "-variance", "-variancelist");
    88     pmConfigFileSetsMD (config->arguments, &argc, argv, "BACKGROUND", "-background", "-bkglist");
     83    // there are three mutually exclusive ways of providing the input
     84    // 1) supply -file (filename) [-mask .. -variance ..] on the command line
     85    // 2) supply -input (input.mdc) on the command line
     86    // 3) load inputs from RUN config info
     87
     88    // below, we check first for -file then for -input.  failure to find either implies use of
     89    // the configuration metadata file.
     90
     91    bool singleInput = pmConfigFileSetsMD (config->arguments, &argc, argv, "INPUT", "-file", "-list");
     92    if (singleInput) {
     93        if (psArgumentGet(argc, argv, "-input")) {
     94            psErrorStackPrint(stderr, "error in arguments : -input and -file / -list are mutually exclusive");
     95            exit(PS_EXIT_CONFIG_ERROR);
     96        }       
     97        pmConfigFileSetsMD (config->arguments, &argc, argv, "MASK", "-mask", "-masklist");
     98        pmConfigFileSetsMD (config->arguments, &argc, argv, "VARIANCE", "-variance", "-variancelist");
     99        pmConfigFileSetsMD (config->arguments, &argc, argv, "BACKGROUND", "-background", "-bkglist");
     100    } else {
     101        // find the input data file (an mdc file)
     102        if ((N = psArgumentGet(argc, argv, "-input"))) {
     103            if (argc <= N+1) {
     104                psErrorStackPrint(stderr, "Expected to see 1 more argument; saw %d", argc - 1);
     105                exit(PS_EXIT_CONFIG_ERROR);
     106            }
     107            psArgumentRemove(N, &argc, argv);
     108
     109            unsigned int numBad = 0;                     // Number of bad lines
     110            psMetadata *inputs = psMetadataConfigRead(NULL, &numBad, argv[N], false); // Input file info
     111            if (!inputs || numBad > 0) {
     112                psErrorStackPrint(stderr, "Unable to cleanly read MDC file with inputs.");
     113                exit(PS_EXIT_CONFIG_ERROR);
     114            }
     115            psMetadataAddMetadata(config->arguments, PS_LIST_TAIL, "INPUTS", 0, "Metadata with input details", inputs);
     116            psFree(inputs);
     117
     118            psArgumentRemove(N, &argc, argv);
     119        }
     120    }
     121    if (argc != 3) {
     122        usage();
     123    }
     124    if (psErrorCodeLast() != PS_ERR_NONE) {
     125        psErrorStackPrint(stderr, "error in arguments");
     126        exit(PS_EXIT_CONFIG_ERROR);
     127    }
    89128   
    90     if (argc != 3) {
    91         usage();
    92     }
    93 
    94 
    95129    psArray *array;
    96130
     
    107141    return config;
    108142}
    109 
    110 /**
    111  * Parse the recipe and format into the arguments
    112  */
    113 bool pswarpOptions(pmConfig *config)
    114 {
    115     // Select the appropriate recipe
    116     psMetadata *recipe  = psMetadataLookupPtr(NULL, config->recipes, PSWARP_RECIPE);
    117     if (!recipe) {
    118         psError(PSWARP_ERR_CONFIG, true, "Can't find %s recipe!\n", PSWARP_RECIPE);
    119         return false;
    120     }
    121 
    122     // Get grid size
    123     bool status;                        ///< Status of MD lookup
    124     int nGridX = psMetadataLookupS32(&status, recipe, "GRID.NX");
    125     if (!status || nGridX <= 0) {
    126         nGridX = 128;
    127         psWarning("GRID.NX is not set in the recipe --- defaulting to %d", nGridX);
    128     }
    129     int nGridY = psMetadataLookupS32(&status, recipe, "GRID.NY");
    130     if (!status) {
    131         nGridY = 128;
    132         psWarning("GRID.NY is not set in the recipe --- defaulting to %d", nGridY);
    133     }
    134 
    135     // Get interpolation mode
    136     const char *name = psMetadataLookupStr (&status, recipe, "INTERPOLATION.MODE"); ///< Name of interp mode
    137     if (!name) {
    138         name = "BILINEAR";
    139         psLogMsg("pswarp", 3, "defaulting to %s interpolation", name);
    140     }
    141     psImageInterpolateMode interpolationMode = psImageInterpolateModeFromString(name); ///< Mode for interp.
    142     if (interpolationMode == PS_INTERPOLATE_NONE) {
    143         interpolationMode = PS_INTERPOLATE_BILINEAR;
    144         psLogMsg ("pswarp", 3,
    145                   "Unknown interpolation mode %s, defaulting to bilinear interpolation\n", name);
    146         name = "BILINEAR";
    147     }
    148 
    149     int numKernels = psMetadataLookupS32(&status, recipe, "INTERPOLATION.NUM");
    150     if (!status) {
    151         numKernels = 0;
    152         psWarning("INTERPOLATION.NUM is not set in the recipe --- defaulting to %d", numKernels);
    153     }
    154 
    155     float poorFrac = psMetadataLookupF32(&status, recipe, "POOR.FRAC"); ///< Frac of bad flux for a "poor"
    156     if (!status) {
    157         poorFrac = 0.0;
    158         psWarning("POOR.FRAC is not set in the %s recipe --- defaulting to %f.", PSWARP_RECIPE, poorFrac);
    159     }
    160 
    161     bool PSF = psMetadataLookupBool(&status, recipe, "PSF"); ///< Generate a PSF model?
    162     if (!status) {
    163         PSF = true;
    164         psWarning("PSF is not set in the %s recipe --- defaulting to TRUE.", PSWARP_RECIPE);
    165     }
    166 
    167     bool doBKG = psMetadataLookupBool(&status,recipe, "BACKGROUND.MODEL"); ///< Generate the warped background model?
    168     if (!status) {
    169       doBKG = false;
    170       psWarning("BACKGROUND.MODEL is not set in the %s recipe -- defaulting to FALSE.", PSWARP_RECIPE);
    171     }
    172     int bkgXgrid = psMetadataLookupS32(&status,recipe, "BKG.XGRID"); ///< Xsize of background model
    173     if (!status) {
    174       bkgXgrid = 10;
    175       psWarning("BKG.XGRID is not set in the %s recipe -- defaultint to %d.",PSWARP_RECIPE,bkgXgrid);
    176     }
    177     int bkgYgrid = psMetadataLookupS32(&status,recipe, "BKG.YGRID"); ///< Xsize of background model
    178     if (!status) {
    179       bkgYgrid = 10;
    180       psWarning("BKG.YGRID is not set in the %s recipe -- defaultint to %d.",PSWARP_RECIPE,bkgYgrid);
    181     }
    182 
    183    
    184     // Set recipe values in the recipe (since we've possibly altered some)
    185     psMetadataAddS32(recipe, PS_LIST_TAIL, "GRID.NX", PS_META_REPLACE,
    186                      "Iso-astrom grid spacing in x", nGridX);
    187     psMetadataAddS32(recipe, PS_LIST_TAIL, "GRID.NY", PS_META_REPLACE,
    188                      "Iso-astrom grid spacing in y", nGridY);
    189     psMetadataAddStr(recipe, PS_LIST_TAIL, "INTERPOLATION.MODE", PS_META_REPLACE,
    190                      "Interpolation mode", name);
    191     psMetadataAddS32(recipe, PS_LIST_TAIL, "INTERPOLATION.NUM", PS_META_REPLACE,
    192                      "Interpolation pre-calculated kernels", numKernels);
    193     psMetadataAddF32(recipe, PS_LIST_TAIL, "POOR.FRAC", PS_META_REPLACE,
    194                      "Fraction of bad flux for a pixel to be marked as poor", poorFrac);
    195     psMetadataAddBool(recipe, PS_LIST_TAIL, "PSF", PS_META_REPLACE, "Generate a PSF Model?", PSF);
    196     psMetadataAddBool(recipe, PS_LIST_TAIL, "BACKGROUND.MODEL", PS_META_REPLACE, "Generate the warped background model?", doBKG);
    197     psMetadataAddS32(recipe, PS_LIST_TAIL, "BKG.XGRID", PS_META_REPLACE, "Xsize of background model", bkgXgrid);
    198     psMetadataAddS32(recipe, PS_LIST_TAIL, "BKG.YGRID", PS_META_REPLACE, "Ysize of background model", bkgYgrid);
    199    
    200    
    201     // Set recipe values in the arguments
    202     psMetadataAddS32(config->arguments, PS_LIST_TAIL, "GRID.NX", 0,
    203                      "Iso-astrom grid spacing in x", nGridX);
    204     psMetadataAddS32(config->arguments, PS_LIST_TAIL, "GRID.NY", 0,
    205                      "Iso-astrom grid spacing in y", nGridY);
    206     psMetadataAddS32(config->arguments, PS_LIST_TAIL, "INTERPOLATION.MODE", 0,
    207                      "Interpolation mode", interpolationMode);
    208     psMetadataAddS32(config->arguments, PS_LIST_TAIL, "INTERPOLATION.NUM", 0,
    209                      "Interpolation pre-calculated kernels", numKernels);
    210     psMetadataAddF32(config->arguments, PS_LIST_TAIL, "POOR.FRAC", 0,
    211                      "Fraction of bad flux for a pixel to be marked as poor", poorFrac);
    212     psMetadataAddBool(config->arguments, PS_LIST_TAIL, "PSF", PS_META_REPLACE, "Generate a PSF Model?", PSF);
    213     psMetadataAddBool(config->arguments, PS_LIST_TAIL, "BACKGROUND.MODEL", PS_META_REPLACE, "Generate the warped background model?", doBKG);
    214     psMetadataAddS32(config->arguments, PS_LIST_TAIL, "BKG.XGRID", PS_META_REPLACE, "Xsize of background model", bkgXgrid);
    215     psMetadataAddS32(config->arguments, PS_LIST_TAIL, "BKG.YGRID", PS_META_REPLACE, "Ysize of background model", bkgYgrid);
    216 
    217     psTrace("pswarp", 1, "Done with pswarpArguments...\n");
    218 
    219     return (config);
    220 }
  • trunk/pswarp/src/pswarpDefine.c

    r34800 r35563  
    11/** @file pswarpDefine.c
    22 *
    3  *  @brief
    4  *
     3 *  @brief generates the output images
    54 *  @ingroup pswarp
    65 *
     
    1312# include "pswarp.h"
    1413
    15 /**
    16  * loads the skycell metadata
    17  */
    1814bool pswarpDefine (pmConfig *config) {
    1915
     
    4238    }
    4339   
    44     // open the full skycell file; no need to defer different depths. only load the header data
    45     pmFPAview *view = pmFPAviewAlloc (0);
    46     pmFPAfileOpen (skycell, view, config);
     40    // Read the output astrometry
     41    // XXX this section loops over the input skycell to load the header info
     42    {
     43        pmFPAview *view = pmFPAviewAlloc(0);
    4744
    48     // Read header and create target
    49     {
    50         if (!pmFPAReadHeaderSet(skycell->fpa, skycell->fits, config)) {
    51             psError(psErrorCodeLast(), false, "Unable to read headers for skycell.");
    52             psFree(view);
    53             return false;
    54         }
    55         view->chip = 0;
    56         view->cell = 0;
    57         view->readout = 0;
    58         pmCell *source = pmFPAfileThisCell(config->files, view, "PSWARP.SKYCELL"); ///< Source cell
    59         pmHDU *hdu = pmHDUFromCell(source); ///< HDU for source
    60         if (!hdu || !hdu->header) {
    61             psError(PM_ERR_PROG, false, "Unable to find header for sky cell.");
    62             psFree(view);
    63             return false;
    64         }
    65         int numCols = psMetadataLookupS32(NULL, hdu->header, "NAXIS1"); ///< Number of columns
    66         int numRows = psMetadataLookupS32(NULL, hdu->header, "NAXIS2"); ///< Number of rows
    67         if ((numCols == 0) || (numRows == 0)) {
    68             psError(PSWARP_ERR_DATA, false, "skycell has invalid dimensions %d x %d", numCols, numRows);
    69             psFree(view);
    70             return false;
    71         }
     45        pmChip *chip;
     46        if (!pmFPAfileRead (skycell, view, config)) {
     47            psError(PS_ERR_IO, false, "failed READ at FPA %s", skycell->name);
     48            psFree(view);
     49            return false;
     50        }
     51        while ((chip = pmFPAviewNextChip (view, skycell->fpa, 1)) != NULL) {
     52            psTrace ("pswarp", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
     53            if (!chip->process || !chip->file_exists) { continue; }
     54            if (!pmFPAfileRead (skycell, view, config)) {
     55                psError(psErrorCodeLast(), false, "failed READ at CHIP %s", skycell->name);
     56                psFree(view);
     57                return false;
     58            }
     59            pmCell *cell;
     60            while ((cell = pmFPAviewNextCell (view, skycell->fpa, 1)) != NULL) {
     61                psTrace ("pswarp", 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
     62                if (!cell->process || !cell->file_exists) { continue; }
     63                if (!pmFPAfileRead (skycell, view, config)) {
     64                    psError(psErrorCodeLast(), false, "failed READ at CELL %s", skycell->name);
     65                    psFree(view);
     66                    return false;
     67                }
     68                if (!pmFPAfileClose(skycell, view)) {
     69                    psError(psErrorCodeLast(), false, "failed CLOSE at CELL %s", skycell->name);
     70                    psFree (view);
     71                    return false;
     72                }
    7273
    73         pmCell *target = pmFPAviewThisCell(view, output->fpa); ///< Target cell
    74         pmReadout *readout = pmReadoutAlloc(target); ///< Target readout
    75         readout->image = psImageAlloc(numCols, numRows, PS_TYPE_F32);
    76         psImageInit(readout->image, NAN);
    77         psFree(readout);                // Drop reference
    78 
    79         bool status = false;
    80         psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.XBIN");
    81         psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.YBIN");
    82         psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.XSIZE");
    83         psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.YSIZE");
    84         psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.XPARITY");
    85         psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.YPARITY");
    86         psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.X0");
    87         psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.Y0");
    88 
    89        
     74                // we've got the output astrom header
     75                pmHDU *hdu = pmHDUFromCell(cell); ///< HDU for source
     76                if (!hdu || !hdu->header) {
     77                    psError(PM_ERR_PROG, false, "Unable to find header for sky cell.");
     78                    psFree(view);
     79                    return false;
     80                }
     81                int numCols = psMetadataLookupS32(NULL, hdu->header, "NAXIS1"); ///< Number of columns
     82                int numRows = psMetadataLookupS32(NULL, hdu->header, "NAXIS2"); ///< Number of rows
     83                if ((numCols == 0) || (numRows == 0)) {
     84                    psError(PSWARP_ERR_DATA, false, "skycell has invalid dimensions %d x %d", numCols, numRows);
     85                    psFree(view);
     86                    return false;
     87                }
     88               
     89                // XXX generate the output pixels
     90                pmCell *target = pmFPAviewThisCell(view, output->fpa); ///< Target cell
     91                pmReadout *readout = pmReadoutAlloc(target); ///< Target readout
     92                readout->image = psImageAlloc(numCols, numRows, PS_TYPE_F32);
     93                psImageInit(readout->image, NAN);
     94                psFree(readout);                // Drop reference
     95               
     96                bool status = false;
     97                psMetadataItemSupplement(&status, target->concepts, cell->concepts, "CELL.XBIN");
     98                psMetadataItemSupplement(&status, target->concepts, cell->concepts, "CELL.YBIN");
     99                psMetadataItemSupplement(&status, target->concepts, cell->concepts, "CELL.XSIZE");
     100                psMetadataItemSupplement(&status, target->concepts, cell->concepts, "CELL.YSIZE");
     101                psMetadataItemSupplement(&status, target->concepts, cell->concepts, "CELL.XPARITY");
     102                psMetadataItemSupplement(&status, target->concepts, cell->concepts, "CELL.YPARITY");
     103                psMetadataItemSupplement(&status, target->concepts, cell->concepts, "CELL.X0");
     104                psMetadataItemSupplement(&status, target->concepts, cell->concepts, "CELL.Y0");
     105            }
     106            if (!pmFPAfileClose(skycell, view)) {
     107                psError(psErrorCodeLast(), false, "failed CLOSE at CHIP %s", skycell->name);
     108                psFree (view);
     109                return false;
     110            }
     111        }
     112        if (!pmFPAfileClose(skycell, view)) {
     113            psError(psErrorCodeLast(), false, "failed CLOSE at FPA %s", skycell->name);
     114            psFree (view);
     115            return false;
     116        }
     117        psFree(view);
    90118    }
    91119
    92     // XXX this is not a sufficient test
     120    // the section below converts the header astrometry info (in skycell) to the pmFPA
     121    // astrometry structures, saving them on the output fpa structure.
     122
     123    // XXX this block should be modified to loop over all chips
     124
     125    pmFPAview *view = pmFPAviewAlloc (0);
    93126    view->chip = 0;
    94127    view->cell = 0;
     
    134167}
    135168
    136 bool pswarpDefineBackground (pmConfig *config) {
    137 
    138     // load the PSWARP recipe
    139     psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, PSWARP_RECIPE);
    140     if (!recipe) {
    141         psError(PSWARP_ERR_CONFIG, true, "Can't find PSWARP recipe!\n");
    142         return false;
    143     }
    144 
    145     // select the input data sources
    146     pmFPAfile *skycell = psMetadataLookupPtr (NULL, config->files, "PSWARP.SKYCELL");
    147     if (!skycell) {
    148         psError(PSWARP_ERR_CONFIG, false, "Can't find skycell data!\n");
    149         return false;
    150     }
    151     pmFPAfile *output = psMetadataLookupPtr(NULL, config->files, "PSWARP.OUTPUT.BKGMODEL");
    152     if (!output) {
    153         psError(PSWARP_ERR_CONFIG, false, "Can't find output data!\n");
    154         return false;
    155     }
    156     pmFPAfile *input = psMetadataLookupPtr(NULL, config->files, "PSWARP.INPUT");
    157     if (!input) {
    158         psError(PSWARP_ERR_CONFIG, false, "Can't find input data!\n");
    159         return false;
    160     }
    161    
    162     // open the full skycell file; no need to defer different depths. only load the header data
    163     pmFPAview *view = pmFPAviewAlloc (0);
    164     pmFPAfileOpen (skycell, view, config);
    165 
    166     // Read header and create target
    167     {
    168         if (!pmFPAReadHeaderSet(skycell->fpa, skycell->fits, config)) {
    169             psError(psErrorCodeLast(), false, "Unable to read headers for skycell.");
    170             psFree(view);
    171             return false;
    172         }
    173         view->chip = 0;
    174         view->cell = 0;
    175         view->readout = 0;
    176         pmCell *source = pmFPAfileThisCell(config->files, view, "PSWARP.SKYCELL"); ///< Source cell
    177         pmHDU *hdu = pmHDUFromCell(source); ///< HDU for source
    178         if (!hdu || !hdu->header) {
    179             psError(PM_ERR_PROG, false, "Unable to find header for sky cell.");
    180             psFree(view);
    181             return false;
    182         }
    183         int numCols = psMetadataLookupS32(NULL, hdu->header, "NAXIS1"); ///< Number of columns
    184         int numRows = psMetadataLookupS32(NULL, hdu->header, "NAXIS2"); ///< Number of rows
    185         if ((numCols == 0) || (numRows == 0)) {
    186             psError(PSWARP_ERR_DATA, false, "skycell has invalid dimensions %d x %d", numCols, numRows);
    187             psFree(view);
    188             return false;
    189         }
    190 
    191         pmCell *target = pmFPAviewThisCell(view, output->fpa); ///< Target cell
    192         pmReadout *readout = pmReadoutAlloc(target); ///< Target readout
    193         readout->image = psImageAlloc(numCols / output->xBin, numRows / output->yBin, PS_TYPE_F32);
    194         psImageInit(readout->image, NAN);
    195         psFree(readout);                // Drop reference
    196 
    197         bool status = false;
    198         psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.XBIN");
    199         psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.YBIN");
    200 /*      psMetadataAddS32(target->concepts,PS_LIST_TAIL,"CELL.XBIN",PS_META_REPLACE,"",output->xBin); */
    201 /*      psMetadataAddS32(target->concepts,PS_LIST_TAIL,"CELL.YBIN",PS_META_REPLACE,"",output->yBin); */
    202         psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.XSIZE");
    203         psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.YSIZE");
    204 /*      psMetadataAddS32(target->concepts,PS_LIST_TAIL,"CELL.XSIZE",PS_META_REPLACE,"",numCols / output->xBin); */
    205 /*      psMetadataAddS32(target->concepts,PS_LIST_TAIL,"CELL.YSIZE",PS_META_REPLACE,"",numRows / output->yBin); */
    206         psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.XPARITY");
    207         psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.YPARITY");
    208         psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.X0");
    209         psMetadataItemSupplement(&status, target->concepts, source->concepts, "CELL.Y0");
    210 
    211        
    212     }
    213 
    214     // XXX this is not a sufficient test
    215     view->chip = 0;
    216     view->cell = 0;
    217     view->readout = -1;
    218     pmHDU *phu = pmFPAviewThisPHU(view, skycell->fpa); ///< Skycell PHU
    219     pmHDU *hdu = pmFPAviewThisHDU(view, skycell->fpa); ///< Skycell header
    220 
    221     pmAstromWCS *WCS = pmAstromWCSfromHeader(hdu->header);
    222 
    223     double cd1f = 1.0 * output->xBin;
    224     double cd2f = 1.0 * output->yBin;
    225    
    226     WCS->crpix1 = WCS->crpix1 / cd1f;
    227     WCS->crpix2 = WCS->crpix2 / cd2f;
    228    
    229     WCS->cdelt1 *= cd1f;
    230     WCS->cdelt2 *= cd2f;
    231 
    232     WCS->trans->x->coeff[1][0] *= cd1f;
    233     WCS->trans->x->coeff[0][1] *= cd2f;
    234     WCS->trans->y->coeff[1][0] *= cd1f;
    235     WCS->trans->y->coeff[0][1] *= cd2f;
    236    
    237    
    238     pmAstromWCStoHeader (hdu->header,WCS);
    239 
    240     bool bilevelAstrometry = false;
    241     if (phu) {
    242         char *ctype = psMetadataLookupStr(NULL, phu->header, "CTYPE1");
    243         if (ctype) {
    244             bilevelAstrometry = !strcmp(&ctype[4], "-DIS");
    245         }
    246     }
    247 
    248     // We read from the skycell into the output.  i.e., the output receives the desired astrometry.
    249     pmChip *outputChip = pmFPAviewThisChip(view, output->fpa); ///< Chip in the output
    250     if (bilevelAstrometry) {
    251         if (!pmAstromReadBilevelMosaic(output->fpa, phu->header)) {
    252             psError(psErrorCodeLast(), false, "Unable to read bilevel mosaic astrometry for skycell.");
    253             psFree(view);
    254             return false;
    255         }
    256         if (!pmAstromReadBilevelChip(outputChip, hdu->header)) {
    257             psError(psErrorCodeLast(), false, "Unable to read bilevel chip astrometry for skycell.");
    258             psFree(view);
    259             return false;
    260         }
    261     } else {
    262         // we use a default FPA pixel scale of 1.0
    263       if (!pmAstromReadWCS(output->fpa, outputChip, hdu->header, 1.0)) {
    264             psError(psErrorCodeLast(), false, "Unable to read WCS astrometry for skycell.");
    265             psFree(view);
    266             return false;
    267         }
    268     }
    269 
    270    
    271     view->chip = view->cell = view->readout = -1;
    272     pmFPAAddSourceFromView(output->fpa, view, output->format);
    273 
    274 
    275     psFree (view);
    276     return true;
    277 }
  • trunk/pswarp/src/pswarpDefineSkycell.c

    r27096 r35563  
    7373    psFitsClose(fits);
    7474
    75     // We need to force the format for the skycell to be equivalent to SIMPLE.  Determine
    76     // the current format from the header; Determine camera if not specified already
    77     // XXX EAM : this operation should be defined as a pmConfig function (pmConfigCopy?)
    78     skyConfig = pmConfigAlloc();
    79     skyConfig->user = psMemIncrRefCounter(config->user);
    80     skyConfig->system = psMemIncrRefCounter(config->system);
     75    { // this bit is unique to pswarpDefineSkycell:
    8176
    82     psFree (skyConfig->files);
    83     skyConfig->files = psMemIncrRefCounter(config->files);
    84     psFree (skyConfig->arguments);
    85     skyConfig->arguments = psMemIncrRefCounter(config->arguments);
     77      // We need to force the format for the skycell to be equivalent to SIMPLE.  Determine
     78      // the current format from the header; Determine camera if not specified already
     79      // XXX EAM : this operation should be defined as a pmConfig function (pmConfigCopy?)
     80      skyConfig = pmConfigAlloc();
     81      skyConfig->user = psMemIncrRefCounter(config->user);
     82      skyConfig->system = psMemIncrRefCounter(config->system);
     83
     84      psFree (skyConfig->files);
     85      skyConfig->files = psMemIncrRefCounter(config->files);
     86      psFree (skyConfig->arguments);
     87      skyConfig->arguments = psMemIncrRefCounter(config->arguments);
     88    }
    8689
    8790    format = pmConfigCameraFormatFromHeader (NULL, NULL, NULL, skyConfig, phu, false);
     
    9497
    9598    // Record the camera name of the skycell, so we can save its configuration
    96     psMetadataAddStr(config->arguments, PS_LIST_TAIL, "SKYCELL.CAMERA", 0, "Name of camera for skycell",
    97                     skyConfig->cameraName);
     99    // XXX this can be put outside of the f
     100    psMetadataAddStr(config->arguments, PS_LIST_TAIL, "SKYCELL.CAMERA", 0, "Name of camera for skycell", skyConfig->cameraName);
    98101
    99102    // build the template fpa, set up the basic view
  • trunk/pswarp/src/pswarpLoop.c

    r34800 r35563  
    11/** @file pswarpLoop.c
    22 *
    3  *  @brief
    4  *
     3 *  @brief main processing loop for pswarp
    54 *  @ingroup pswarp
    65 *
     
    1211
    1312#include "pswarp.h"
    14 #include <ppStats.h>
    15 #include "pswarpFileNames.h"            // Lists of file rules used at different stages
    1613
    17 #define WCS_NONLIN_TOL 0.001            // Non-linear tolerance for header WCS
    18 #define TESTING 0                       // Testing output?
    19 
    20 
    21 
    22 // Loop over the inputs, warp them to the output skycell and then write out the output.
     14// Loop over the inputs, warp them to the output skycell and then update metadata
    2315bool pswarpLoop(pmConfig *config, psMetadata *stats)
    2416{
    25     bool status;
    26     bool mdok;                          // Status of MD lookup
    27 
    28     const char *skyCamera = psMetadataLookupStr(NULL, config->arguments,
    29                                                 "SKYCELL.CAMERA");  // Name of camera for skycell
    30     pmConfigCamerasCull(config, skyCamera);
    31     pmConfigRecipesCull(config, "PSWARP,PPSTATS,PSPHOT,PSASTRO,MASKS,JPEG");
    3217
    3318    // load the recipe
     19    bool status = false;
    3420    psMetadata *recipe = psMetadataLookupPtr (&status, config->recipes, PSWARP_RECIPE);
    3521    if (!recipe) {
     
    3824    }
    3925
    40     if (!pswarpSetMaskBits(config)) {
    41         psError(psErrorCodeLast(), false, "failed to set mask bits");
    42         return NULL;
    43     }
    44 
    45     // output mask bits
    46     psImageMaskType maskValue = psMetadataLookupImageMask(&status, recipe, "MASK.OUTPUT");
    47     psAssert (status, "MASK.OUTPUT was not defined");
    48 
    4926    // select the input data sources
    50     pmFPAfile *input = psMetadataLookupPtr(NULL, config->files, "PSWARP.INPUT");
    51     if (!input) {
    52         psError(PSWARP_ERR_CONFIG, true, "Can't find input data!\n");
     27    pmFPAfile *output = psMetadataLookupPtr(&status, config->files, "PSWARP.OUTPUT");
     28    if (!output) {
     29        psError(PSWARP_ERR_CONFIG, true, "Can't find output data!\n");
    5330        return false;
    5431    }
    5532
    5633    // use the external astrometry source if supplied
    57     pmFPAfile *astrom = psMetadataLookupPtr(NULL, config->files, "PSWARP.ASTROM");
    58     if (!astrom) {
    59         astrom = input;
    60     }
    61 
    62     if (astrom->camera != input->camera) {
    63         psError(PSWARP_ERR_DATA, true, "Input camera and astrometry camera do not match.");
     34    pmFPAfile *skycell = psMetadataLookupPtr(&status, config->files, "PSWARP.SKYCELL");
     35    if (!skycell) {
     36        psError(PSWARP_ERR_DATA, true, "Cannot find output astrometry.");
    6437        return false;
    6538    }
    6639
    67     // select the output readout
    6840    pmFPAview *view = pmFPAviewAlloc(0);
    69     view->chip = 0;
    70     view->cell = 0;
    71     view->readout = 0;
    72     pmReadout *output = pmFPAfileThisReadout(config->files, view, "PSWARP.OUTPUT");
    73     if (!output) {
    74         psError(PSWARP_ERR_CONFIG, true, "Can't find output data!\n");
     41
     42    int nInputs = psMetadataLookupS32(&status, config->arguments, "NUM_INPUTS");
     43    if (!status) {
     44        psError(PSWARP_ERR_DATA, true, "number of inputs is not defined (programming error)");
    7545        return false;
    7646    }
    77     psFree (view);
    7847
     48    // load in the input pixel data (ex. background model)
     49    pmFPAfileActivate(config->files, false, NULL);
     50    pmFPAfileActivate(config->files, true, "PSWARP.INPUT");
     51    pmFPAfileActivate(config->files, true, "PSWARP.MASK");
     52    pmFPAfileActivate(config->files, true, "PSWARP.VARIANCE");
    7953
    80     // Turn all skycell files on to generate them, and then turn them off for the loop over the input images
    81     // the input, which is in a different format.
    82     {
    83         pswarpFileActivation(config, detectorFiles, false);
    84         pswarpFileActivation(config, photFiles, false);
    85         pswarpFileActivation(config, independentFiles, false);
    86         pswarpFileActivation(config, skycellFiles, true);
    87         if (!pswarpIOChecksBefore(config)) {
    88             psError(psErrorCodeLast(), false, "Unable to read files.");
    89             goto DONE;
    90         }
    91         pswarpFileActivation(config, skycellFiles, false);
     54    // We re-activate the CMF load so we can transform the sources as well as the pixels.
     55    // We only need to read in these if the astrometry source is CMF.
     56    pmFPAfileActivate(config->files, true, "PSWARP.ASTROM");
     57
     58    // loop over this section once per input group
     59    for (int i = 0; i < nInputs; i++) {
     60        // select the input data sources
     61        pmFPAfile *input = pmFPAfileSelectSingle(config->files, "PSWARP.INPUT", i);
     62        if (!input) {
     63            psError(PSWARP_ERR_CONFIG, true, "Can't find input data!\n");
     64            return false;
     65        }
     66
     67        // select the input data sources
     68        pmFPAfile *astrom = pmFPAfileSelectSingle(config->files, "PSWARP.ASTROM", i);
     69        if (!astrom) {
     70            astrom = input;
     71        }
     72
     73        pmFPAviewReset (view);
     74
     75        // files associated with the science image
     76        if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) {
     77            psError(psErrorCodeLast(), false, "Unable to read files.");
     78            goto FAIL;
     79        }
     80
     81        // *** main transformation block
     82        // *** this section loops over the input chips/cells and reads them one at a time
     83        // *** the output chips/cells are filled where appropriate, but not yet written to disk
     84        pmChip *chip;
     85        while ((chip = pmFPAviewNextChip (view, input->fpa, 1)) != NULL) {
     86            psTrace ("pswarp", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
     87            if (!chip->process || !chip->file_exists) { continue; }
     88            if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) {
     89                psError(psErrorCodeLast(), false, "Unable to read files.");
     90                goto FAIL;
     91            }
     92
     93            pmCell *cell;
     94            while ((cell = pmFPAviewNextCell (view, input->fpa, 1)) != NULL) {
     95                psTrace ("pswarp", 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
     96                if (!cell->process || !cell->file_exists) { continue; }
     97                if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) {
     98                    psError(psErrorCodeLast(), false, "Unable to read files.");
     99                    goto FAIL;
     100                }
     101
     102                // process each of the readouts
     103                pmReadout *readout;
     104                while ((readout = pmFPAviewNextReadout(view, input->fpa, 1)) != NULL) {
     105                    if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
     106                        psError(psErrorCodeLast(), false, "Unable to read files.");
     107                        goto FAIL;
     108                    }
     109                    if (!readout->data_exists) {
     110                        continue;
     111                    }
     112
     113                    // Copy the detections from the astrometry carrier to the input, so they can be accessed by
     114                    // pswarpTransformReadout
     115                    if (astrom != input) {
     116                        pmReadout *astromRO = pmFPAviewThisReadout(view, astrom->fpa); // Readout for astrometry
     117                        pmDetections *detections = psMetadataLookupPtr(&status, astromRO->analysis, "PSPHOT.DETECTIONS"); // Sources from astrometry
     118                        if (detections) {
     119                            psMetadataAddPtr(readout->analysis, PS_LIST_TAIL, "PSPHOT.DETECTIONS", PS_DATA_ARRAY, "Sources from input astrometry", detections);
     120                        }
     121                    }
     122
     123                    pswarpTransformToTarget(output->fpa, readout, config, false);
     124               
     125                    if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
     126                        psError(psErrorCodeLast(), false, "Unable to write files.");
     127                        goto FAIL;
     128                    }
     129                }
     130                if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
     131                    psError(psErrorCodeLast(), false, "Unable to write files.");
     132                    goto FAIL;
     133                }
     134            }
     135            if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
     136                psError(psErrorCodeLast(), false, "Unable to write files.");
     137                goto FAIL;
     138            }
     139        }
     140        if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
     141            psError(psErrorCodeLast(), false, "Unable to write files.");
     142            goto FAIL;
     143        }
     144
     145        if (!pswarpUpdateStatistics (output->fpa, stats, input->fpa, astrom->fpa, config)) {
     146            psError(psErrorCodeLast(), false, "problem generating statistics.");
     147            goto FAIL;
     148        }
     149        if (!pswarpUpdateMetadata (output->fpa, skycell->fpa, input->fpa, astrom->fpa, config, true)) {
     150            psError(psErrorCodeLast(), false, "problem generating statistics.");
     151            goto FAIL;
     152        }
    92153    }
    93154
    94     // Read the input astrometry
    95     // XXX rather than use the activations here, this should just explicitly loop over the desired filerule
    96     {
    97         pmFPAfileActivate(config->files, true, "PSWARP.ASTROM");
    98 
    99         pmChip *chip;
    100         pmFPAview *view = pmFPAviewAlloc(0);
    101         if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
    102             psError(psErrorCodeLast(), false, "Unable to read files.");
    103             goto DONE;
    104         }
    105         while ((chip = pmFPAviewNextChip (view, input->fpa, 1)) != NULL) {
    106             psTrace ("pswarp", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
    107             if (!chip->process || !chip->file_exists) { continue; }
    108             if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
    109                 psError(psErrorCodeLast(), false, "Unable to read files.");
    110                 goto DONE;
    111             }
    112             pmCell *cell;
    113             while ((cell = pmFPAviewNextCell (view, input->fpa, 1)) != NULL) {
    114                 psTrace ("pswarp", 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
    115                 if (!cell->process || !cell->file_exists) { continue; }
    116                 if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE) ||
    117                     !pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
    118                     psError(psErrorCodeLast(), false, "Unable to read files.");
    119                     goto DONE;
    120                 }
    121             }
    122             if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
    123                 psError(psErrorCodeLast(), false, "Unable to write files.");
    124                 goto DONE;
    125             }
    126         }
    127         if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
    128             psError(psErrorCodeLast(), false, "Unable to write files.");
    129             goto DONE;
    130         }
    131         psFree(view);
    132 
    133         pswarpFileActivation(config, detectorFiles, true);
    134         pmFPAfileActivate(config->files, false, "PSWARP.ASTROM");
     155    if (!pswarpMakePSF (config, output, stats)) {
     156      psError(psErrorCodeLast(), false, "problem generating PSF.");
     157      goto FAIL;
    135158    }
    136159
    137     // Turn on the source output --- we need to get rid of these so that we can measure the PSF
    138     pmFPAfileActivate(config->files, true, "PSWARP.OUTPUT.SOURCES");
     160    psFree(view);
     161    return true;
    139162
    140     // Don't care about the skycell anymore --- we've read it, and that's all we need to do.
    141     pmFPAfileActivate(config->files, false, "PSWARP.SKYCELL");
    142     view = pmFPAviewAlloc(0);
     163 FAIL:
     164    psFree (view);
     165    return false;
     166}
    143167
    144     // find the FPA phu
    145     bool bilevelAstrometry = false;
    146     pmHDU *phu = pmFPAviewThisPHU(view, astrom->fpa);
    147     if (phu) {
    148         char *ctype = psMetadataLookupStr(NULL, phu->header, "CTYPE1");
    149         if (ctype) {
    150             bilevelAstrometry = !strcmp (&ctype[4], "-DIS");
    151         }
    152     }
    153     if (bilevelAstrometry) {
    154         if (!pmAstromReadBilevelMosaic(input->fpa, phu->header)) {
    155             psError(psErrorCodeLast(), false, "Unable to read bilevel mosaic astrometry for input FPA.");
    156             psFree(view);
    157             psFree(stats);
    158             goto DONE;
    159         }
    160     }
     168// once the output fpa elements have been built, loop over the fpa and generate stats
     169// for each readout
     170bool pswarpTransformToTarget (pmFPA *output, pmReadout *input, pmConfig *config, bool backgroundWarp)  {
    161171
    162     psList *cells = psListAlloc(NULL);  // List of cells, for concepts averaging
    163 
    164     // files associated with the science image
    165     if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) {
    166         psError(psErrorCodeLast(), false, "Unable to read files.");
    167         goto DONE;
    168     }
    169 
     172    pmFPAview *view = pmFPAviewAlloc(0);
     173   
    170174    pmChip *chip;
    171     while ((chip = pmFPAviewNextChip (view, input->fpa, 1)) != NULL) {
     175    while ((chip = pmFPAviewNextChip (view, output, 1)) != NULL) {
    172176        psTrace ("pswarp", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
    173177        if (!chip->process || !chip->file_exists) { continue; }
    174         if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) {
    175             psError(psErrorCodeLast(), false, "Unable to read files.");
    176             goto DONE;
    177         }
    178178
    179         // read WCS data from the corresponding header
    180         pmHDU *hdu = pmFPAviewThisHDU (view, astrom->fpa);
    181 
    182        
    183         if (bilevelAstrometry) {
    184             if (!pmAstromReadBilevelChip (chip, hdu->header)) {
    185                 psError(psErrorCodeLast(), false, "Unable to read bilevel chip astrometry for input FPA.");
    186                 psFree(view);
    187                 psFree(stats);
    188                 goto DONE;
    189             }
    190         } else {
    191             // we use a default FPA pixel scale of 1.0
    192             if (!pmAstromReadWCS (input->fpa, chip, hdu->header, 1.0)) {
    193                 psError(psErrorCodeLast(), false, "Unable to read WCS astrometry for input FPA.");
    194                 psFree(view);
    195                 psFree(stats);
    196                 goto DONE;
    197             }
    198         }
    199        
    200179        pmCell *cell;
    201         while ((cell = pmFPAviewNextCell (view, input->fpa, 1)) != NULL) {
     180        while ((cell = pmFPAviewNextCell (view, output, 1)) != NULL) {
    202181            psTrace ("pswarp", 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
    203182            if (!cell->process || !cell->file_exists) { continue; }
    204             if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) {
    205                 psError(psErrorCodeLast(), false, "Unable to read files.");
    206                 goto DONE;
    207             }
    208 
    209             psListAdd(cells, PS_LIST_TAIL, cell);
    210183
    211184            // process each of the readouts
    212185            pmReadout *readout;
    213             while ((readout = pmFPAviewNextReadout(view, input->fpa, 1)) != NULL) {
    214                 if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
    215                     psError(psErrorCodeLast(), false, "Unable to read files.");
    216                     goto DONE;
    217                 }
    218                 if (!readout->data_exists) {
    219                     continue;
    220                 }
    221 
    222                 // Copy the detections from the astrometry carrier to the input, so they can be accessed by
    223                 // pswarpTransformReadout
    224                 pmReadout *astromRO = pmFPAviewThisReadout(view, astrom->fpa); // Readout for astrometry
    225                 pmDetections *detections = psMetadataLookupPtr(&mdok, astromRO->analysis, "PSPHOT.DETECTIONS"); // Sources from astrometry
    226                 if (detections) {
    227                     psMetadataAddPtr(readout->analysis, PS_LIST_TAIL, "PSPHOT.DETECTIONS", PS_DATA_ARRAY, "Sources from input astrometry", detections);
    228                 }
    229 
    230                 pswarpTransformReadout(output, readout, config);
    231                
    232                 if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
    233                     psError(psErrorCodeLast(), false, "Unable to write files.");
    234                     goto DONE;
    235                 }
    236             }
    237             if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
    238                 psError(psErrorCodeLast(), false, "Unable to write files.");
    239                 goto DONE;
    240             }
    241         }
    242         if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
    243             psError(psErrorCodeLast(), false, "Unable to write files.");
    244             goto DONE;
    245         }
     186            while ((readout = pmFPAviewNextReadout(view, output, 1)) != NULL) {
     187                pswarpTransformReadout (readout, input, config, backgroundWarp);
     188            }
     189        }
    246190    }
    247 
    248     if (!output->data_exists) {
    249         psWarning("No overlap between input and skycell.");
    250         if (stats) {
    251             psMetadataAddS32(stats, PS_LIST_TAIL, "QUALITY", PS_META_REPLACE,
    252                              "No overlap between input and skycell", PSWARP_ERR_NO_OVERLAP);
    253         }
    254         psphotFilesActivate(config, false);
    255         psFree(cells);
    256         psFree(view);
    257         goto DONE;
    258     }
    259    
    260     pmCell *outCell = output->parent;   ///< Output cell
    261     pmChip *outChip = outCell->parent;  ///< Output chip
    262     pmFPA *outFPA = outChip->parent;    ///< Output FP
    263 
    264     if (!pswarpPixelsLit(output, stats, config)) {
    265         psError(psErrorCodeLast(), false, "Unable to calculate pixel regions.");
    266         psFree(cells);
    267         psFree(view);
    268         goto DONE;
    269     }
    270     bool doStats = psMetadataLookupBool(&mdok,recipe,"MASK.STATS");
    271     if (doStats) {
    272       if (!pswarpMaskStats(output, stats, config)) {
    273         psError(psErrorCodeLast(), false, "Unable to calculate mask stats.");
    274         psFree(cells);
    275         psFree(view);
    276         goto DONE;
    277       }
    278     }
    279     // Set covariance matrix for output
    280     {
    281         psList *covariances = psMetadataLookupPtr(&mdok, output->analysis,
    282                                                   PSWARP_ANALYSIS_COVARIANCES); // Covariance matrices
    283         psAssert(covariances, "Should be there");
    284         psArray *covars = psListToArray(covariances); // Array of covariance matrices
    285         psKernel *covar = psImageCovarianceAverage(covars);
    286         psFree(covars);
    287         psMetadataRemoveKey(output->analysis, PSWARP_ANALYSIS_COVARIANCES);
    288 
    289         // Correct covariance matrix scale for the mean (square root of the) Jacobian
    290         double jacobian = psMetadataLookupF64(NULL, output->analysis, PSWARP_ANALYSIS_JACOBIAN); // Jacobian
    291         int goodPixels = psMetadataLookupS32(NULL, output->analysis, PSWARP_ANALYSIS_GOODPIX);   // Good pixels
    292         jacobian /= goodPixels;
    293         output->covariance = psImageCovarianceScale(covar, jacobian);
    294         psFree(covar);
    295 
    296         if (output->variance) {
    297             psImageCovarianceTransfer(output->variance, output->covariance);
    298         }
    299     }
    300 
    301     if (!pmConceptsAverageCells(outCell, cells, NULL, NULL, false)) {
    302         psError(psErrorCodeLast(), false, "Unable to average cell concepts.");
    303         psFree(stats);
    304         psFree(cells);
    305         psFree(view);
    306         goto DONE;
    307     }
    308     psFree(cells);
    309 
    310     psRegion *trimsec = psMetadataLookupPtr(NULL, outCell->concepts, "CELL.TRIMSEC"); ///< Trim section
    311     trimsec->x0 = trimsec->x1 = trimsec->y0 = trimsec->y1 = 0; ///< All pixels
    312 
    313     if (!psMetadataCopy(outFPA->concepts, input->fpa->concepts)) {
    314         psError(psErrorCodeLast(), false, "Unable to copy FPA concepts from input to output.");
    315         psFree(stats);
    316         psFree(view);
    317         goto DONE;
    318     }
    319 
    320     // Update ZP from the astrometry
    321     {
    322         psMetadataItem *item = psMetadataLookup(outFPA->concepts, "FPA.ZP");
    323         item->data.F32 = psMetadataLookupF32(NULL, astrom->fpa->concepts, "FPA.ZP");
    324     }
    325 
    326     pmHDU *hdu = outFPA->hdu;           ///< HDU for the output warped image
    327 
    328     // Copy header from target
    329     {
    330         pmFPAview *skyView = pmFPAviewAlloc(0); ///< View into skycell
    331         skyView->chip = skyView->cell = 0;
    332         pmCell *cell = pmFPAfileThisCell(config->files, skyView, "PSWARP.SKYCELL"); // Skycell cell
    333         psFree(skyView);
    334         pmHDU *skyHDU = pmHDUFromCell(cell); ///< HDU
    335         if (!skyHDU) {
    336             psError(PSWARP_ERR_DATA, false, "Unable to find skycell HDU.");
    337             psFree(view);
    338             goto DONE;
    339         }
    340         hdu->header = psMetadataCopy(hdu->header, skyHDU->header);
    341     }
    342 
    343     pswarpVersionHeader(hdu->header);
    344    
    345     if (!pmAstromWriteWCS(hdu->header, outFPA, outChip, WCS_NONLIN_TOL)) {
    346         psError(psErrorCodeLast(), false, "Unable to generate WCS header.");
    347         psFree(stats);
    348         goto DONE;
    349     }
    350 
    351     if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
    352         psError(psErrorCodeLast(), false, "Unable to write files.");
    353         goto DONE;
    354     }
    355 
    356     // Done with the detector side of things
    357     pswarpFileActivation(config, detectorFiles, false);
    358     pswarpFileActivation(config, independentFiles, false);
    359 
    360 
    361     // We need a new PSF model for the warped frame.  It would be good to generate this analytically, but
    362     // that's going to be tricky.  We have a list of sources, so we use those to redetermine the PSF model.
    363 
    364     if (psMetadataLookupBool(&mdok, recipe, "PSF")) {
    365         pswarpFileActivation(config, photFiles, true);
    366         if (!pswarpIOChecksBefore(config)) {
    367             psError(psErrorCodeLast(), false, "Unable to read files.");
    368             goto DONE;
    369         }
    370 
    371         // supply the readout and fpa of interest to psphot
    372         pmFPAfile *photFile = psMetadataLookupPtr(NULL, config->files, "PSPHOT.INPUT");
    373         pmFPACopy(photFile->fpa, outFPA);
    374 
    375         pmFPAview *view = pmFPAviewAlloc(0); ///< View into skycell
    376         view->chip = view->cell = view->readout = 0;
    377 
    378         // grab the sources of interest from the storage location (pmFPAfile PSPHOT.INPUT.CMF)
    379         psArray *sources = psphotLoadPSFSources (config, view);
    380         if (!sources) {
    381             psError(psErrorCodeLast(), false, "No sources supplied to measure PSF");
    382             goto DONE;
    383         }
    384 
    385         pmModelClassSetLimits(PM_MODEL_LIMITS_STRICT);
    386 
    387         // measure the PSF using these sources
    388         if (!psphotReadoutFindPSF(config, view, "PSPHOT.INPUT", sources)) {
    389             // This is likely a data quality issue
    390             // XXX Split into multiple cases using error codes?
    391             psErrorStackPrint(stderr, "Unable to determine PSF");
    392             psWarning("Unable to determine PSF --- suspect bad data quality.");
    393             if (stats && psMetadataLookupS32(NULL, stats, "QUALITY") == 0) {
    394                 psMetadataAddS32(stats, PS_LIST_TAIL, "QUALITY", PS_META_REPLACE,
    395                                  "Unable to determine PSF", psErrorCodeLast());
    396             }
    397             psErrorClear();
    398             psphotFilesActivate(config, false);
    399         }
    400 
    401         // Ensure seeing is carried over
    402         pmChip *photChip = pmFPAviewThisChip(view, photFile->fpa);                 // Chip with seeing
    403         psMetadataItem *item = psMetadataLookup(outChip->concepts, "CHIP.SEEING"); // Concept with seeing
    404         item->data.F32 = psMetadataLookupF32(NULL, photChip->concepts, "CHIP.SEEING");
    405 
    406 // XXX EAM : put this in a visualization function
    407 #if (TESTING)
    408         {
    409             #define PSF_SIZE 20         ///< Half-size of PSF
    410             #define PSF_FLUX 10000      ///< Central flux for PSF
    411             pmChip *photChip = pmFPAviewThisChip(view, photFile->fpa);
    412             pmPSF *psf = psMetadataLookupPtr(NULL, photChip->analysis, "PSPHOT.PSF");
    413             psImage *image = psImageAlloc(2 * PSF_SIZE + 1, 2 * PSF_SIZE + 1, PS_TYPE_F32);
    414             psImageInit(image, 0);
    415             pmModel *model = pmModelFromPSFforXY(psf, PSF_SIZE, PSF_SIZE, PSF_FLUX);
    416             pmModelAdd(image, NULL, model, PM_MODEL_OP_FULL, 0);
    417             psFree(model);
    418             psFits *fits = psFitsOpen("psf.fits", "w");
    419             psFitsWriteImage(fits, NULL, image, 0, NULL);
    420             psFitsClose(fits);
    421             psFree(image);
    422         }
    423 #endif
    424 
    425         psFree(view);
    426     }
    427 
    428     // Perform statistics on the output image
    429     if (stats) {
    430         if (!ppStatsFPA(stats, output->parent->parent->parent, view, maskValue, config)) {
    431             psWarning("Unable to perform statistics on warped image.");
    432         }
    433     }
    434    
    435 
    436     // Add MD5 information for readout
    437     const char *chipName = psMetadataLookupStr(NULL, output->parent->parent->concepts, "CHIP.NAME");
    438     const char *cellName = psMetadataLookupStr(NULL, output->parent->concepts, "CELL.NAME");
    439     psString headerName = NULL; ///< Header name for MD5
    440     psStringAppend(&headerName, "MD5_%s_%s_%d", chipName, cellName, view->readout);
    441     psVector *md5 = psImageMD5(output->image); ///< md5 hash
    442     psString md5string = psMD5toString(md5); ///< String
    443     psFree(md5);
    444     psMetadataAddStr(hdu->header, PS_LIST_TAIL, headerName, PS_META_REPLACE,
    445                      "Image MD5", md5string);
    446     psFree(md5string);
    447     psFree(headerName);
    448     psFree(view);
    449 
    450  DONE:
    451 
    452191    return true;
    453192}
    454193
    455 // Loop over the inputs, warp them to the output skycell and then write out the output.
    456 bool pswarpLoopBackground(pmConfig *config, psMetadata *stats)
    457 {
    458     bool status;
    459     bool mdok;                          // Status of MD lookup
    460     const char *skyCamera = psMetadataLookupStr(NULL, config->arguments,
    461                                                 "SKYCELL.CAMERA");  // Name of camera for skycell
    462     pmConfigCamerasCull(config, skyCamera);
    463     pmConfigRecipesCull(config, "PSWARP,PPSTATS,PSPHOT,PSASTRO,MASKS,JPEG");
    464 
    465     // load the recipe
    466     psMetadata *recipe = psMetadataLookupPtr (&status, config->recipes, PSWARP_RECIPE);
    467     if (!recipe) {
    468         psError(PSWARP_ERR_CONFIG, false, "missing recipe %s", PSWARP_RECIPE);
    469         return false;
    470     }
    471 
    472     if (!pswarpSetMaskBits(config)) {
    473         psError(psErrorCodeLast(), false, "failed to set mask bits");
    474         return NULL;
    475     }
    476 
    477     // select the input data sources
    478     pmFPAfile *input = psMetadataLookupPtr(NULL, config->files, "PSWARP.BKGMODEL");
    479     if (!input) {
    480         psError(PSWARP_ERR_CONFIG, true, "Can't find input data!\n");
    481         return false;
    482     }
    483 
    484     // use the external astrometry source if supplied
    485     pmFPAfile *astrom = psMetadataLookupPtr(NULL, config->files, "PSWARP.ASTROM");
    486     if (!astrom) {
    487         astrom = input;
    488     }
    489 
    490     if (astrom->camera != input->camera) {
    491         psError(PSWARP_ERR_DATA, true, "Input camera and astrometry camera do not match.");
    492         return false;
    493     }
    494 
    495     // select the output readout
    496     pmFPAview *view = pmFPAviewAlloc(0);
    497     view->chip = 0;
    498     view->cell = 0;
    499     view->readout = 0;
    500     pmReadout *output = pmFPAfileThisReadout(config->files, view, "PSWARP.OUTPUT.BKGMODEL");
    501     if (!output) {
    502         psError(PSWARP_ERR_CONFIG, true, "Can't find output background data!\n");
    503         return false;
    504     }
    505     psFree (view);
    506     // Turn all skycell files on to generate them, and then turn them off for the loop over the input images
    507     // the input, which is in a different format.
    508     {
    509         pswarpFileActivation(config, detectorFiles, false);
    510         pswarpFileActivation(config, photFiles, false);
    511         pswarpFileActivation(config, independentFiles, false);
    512         pswarpFileActivation(config, skycellFiles, true);
    513         if (!pswarpIOChecksBefore(config)) {
    514             psError(psErrorCodeLast(), false, "Unable to read files.");
    515             goto DONE;
    516         }
    517         pswarpFileActivation(config, skycellFiles, false);
    518     }
    519     // Read the input astrometry
    520     // XXX rather than use the activations here, this should just explicitly loop over the desired filerule
    521     {
    522 
    523       pmFPAfileActivate(config->files, true, "PSWARP.ASTROM");
    524 
    525         pmChip *chip;
    526         pmFPAview *view = pmFPAviewAlloc(0);
    527         if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
    528             psError(psErrorCodeLast(), false, "Unable to read files.");
    529             goto DONE;
    530         }
    531 
    532         while ((chip = pmFPAviewNextChip (view, input->fpa, 1)) != NULL) {
    533 #if 0
    534           // This needs to be removed because otherwise it throws an error of duplicate PSPHOT.DETECTIONS.
    535             if (!chip->process || !chip->file_exists) { continue; }
    536             if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
    537                 psError(psErrorCodeLast(), false, "Unable to read files.");
    538                 goto DONE;
    539             }
    540 #endif
    541             pmCell *cell;
    542             while ((cell = pmFPAviewNextCell (view, input->fpa, 1)) != NULL) {
    543               psTrace ("pswarp", 4, "ACell %d: %x %x %d\n", view->cell, cell->file_exists, cell->process,psErrorCodeLast());
    544                 if (!cell->process || !cell->file_exists) { continue; }
    545                 if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE) ||
    546                     !pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
    547                     psError(psErrorCodeLast(), false, "Unable to read files.");
    548                     goto DONE;
    549                 }
    550             }
    551             if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
    552                 psError(psErrorCodeLast(), false, "Unable to write files.");
    553                 goto DONE;
    554             }
    555         }
    556         if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
    557             psError(psErrorCodeLast(), false, "Unable to write files.");
    558             goto DONE;
    559         }
    560         psFree(view);
    561         pswarpFileActivation(config, detectorFiles, true);
    562         pmFPAfileActivate(config->files, false, "PSWARP.ASTROM");
    563     }
    564 
    565     // Don't care about the skycell anymore --- we've read it, and that's all we need to do.
    566     pmFPAfileActivate(config->files, false, "PSWARP.SKYCELL");
    567     view = pmFPAviewAlloc(0);
    568 
    569     // find the FPA phu
    570     bool bilevelAstrometry = false;
    571     pmHDU *phu = pmFPAviewThisPHU(view, astrom->fpa);
    572 
    573     //    pmAstromWCS *WCSF = pmAstromWCSfromHeader(phu->header);
    574    
    575     if (phu) {
    576         char *ctype = psMetadataLookupStr(NULL, phu->header, "CTYPE1");
    577         if (ctype) {
    578             bilevelAstrometry = !strcmp (&ctype[4], "-DIS");
    579         }
    580     }
    581     if (bilevelAstrometry) {
    582         if (!pmAstromReadBilevelMosaic(input->fpa, phu->header)) {
    583             psError(psErrorCodeLast(), false, "Unable to read bilevel mosaic astrometry for input FPA.");
    584             psFree(view);
    585             psFree(stats);
    586             goto DONE;
    587         }
    588     }
    589 
    590     psList *cells = psListAlloc(NULL);  // List of cells, for concepts averaging
    591 
    592     // files associated with the science image
    593     if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) {
    594         psError(psErrorCodeLast(), false, "Unable to read files.");
    595         goto DONE;
    596     }
    597     pmChip *chip;
    598     while ((chip = pmFPAviewNextChip (view, input->fpa, 1)) != NULL) {
    599         psTrace ("pswarp", 4, "DChip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
    600         if (!chip->process || !chip->file_exists) { continue; }
    601         if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) {
    602             psError(psErrorCodeLast(), false, "Unable to read files.");
    603             goto DONE;
    604         }
    605 
    606         // Pull information from the header of the background files so we can use it to set values.
    607         pmHDU *hdu = pmFPAviewThisHDU(view,input->fpa);
    608         psMetadata *header = hdu->header;
    609        
    610         int IMAXIS1 = psMetadataLookupS32(NULL,header,"IMNAXIS1");
    611         int IMAXIS2 = psMetadataLookupS32(NULL,header,"IMNAXIS2");
    612         int NAXIS1 = psMetadataLookupS32(NULL,header,"NAXIS1");
    613         int NAXIS2 = psMetadataLookupS32(NULL,header,"NAXIS2");
    614         char *CCDSUM = psMetadataLookupStr(NULL,header,"CCDSUM");
    615         int CCDSUM1 = atoi(strtok(CCDSUM," "));
    616         int CCDSUM2 = atoi(strtok(NULL," "));
    617        
    618         psMetadataAddF32(config->arguments,PS_LIST_TAIL,"BKG_WARP_XOFFSET", PS_META_REPLACE,
    619                          "xoffset for background model data", (NAXIS1 * CCDSUM1 - IMAXIS1) / (2.0 * CCDSUM1));
    620         psMetadataAddF32(config->arguments,PS_LIST_TAIL,"BKG_WARP_YOFFSET", PS_META_REPLACE,
    621                          "yoffset for background model data", (NAXIS2 * CCDSUM2 - IMAXIS2) / (2.0 * CCDSUM2));
    622         psTrace("pswarp",5,"%d %d %d %d %d %d %g %g %d %d",
    623                 psMetadataLookupS32(NULL,header,"IMNAXIS1"),
    624                 psMetadataLookupS32(NULL,header,"IMNAXIS2"),
    625                 psMetadataLookupS32(NULL,header,"NAXIS1"),
    626                 psMetadataLookupS32(NULL,header,"NAXIS2"),
    627                 CCDSUM1,CCDSUM2,
    628                 psMetadataLookupF32(NULL,config->arguments,"BKG_WARP_XOFFSET"),
    629                 psMetadataLookupF32(NULL,config->arguments,"BKG_WARP_YOFFSET"),
    630                 psMetadataLookupS32(NULL,config->arguments,"BKG.XGRID"),
    631                 psMetadataLookupS32(NULL,config->arguments,"BKG.YGRID"));
    632        
    633        
    634         // read WCS data from the corresponding header
    635         hdu = pmFPAviewThisHDU (view, astrom->fpa);
    636 
    637         pmAstromWCS *WCS = pmAstromWCSfromHeader(hdu->header);
    638 
    639         double cd1f = (1.0 * CCDSUM1);// * (1.0 * psMetadataLookupS32(NULL,config->arguments,"BKG.XGRID"));
    640         double cd2f = (1.0 * CCDSUM2);// * (1.0 * psMetadataLookupS32(NULL,config->arguments,"BKG.YGRID"));
    641 
    642         WCS->cdelt1 *= cd1f;
    643         WCS->cdelt2 *= cd2f;
    644         WCS->crpix1 = WCS->crpix1 / cd1f;
    645         WCS->crpix2 = WCS->crpix2 / cd2f;
    646 
    647         // WCS->trans->x->nX/nY
    648         for (int q = 0; q <= WCS->trans->x->nX; q++) {
    649           for (int r = 0; r <= WCS->trans->x->nY; r++) {
    650             WCS->trans->x->coeff[q][r] *= pow(cd1f,q) * pow(cd2f,r);
    651           }
    652         }
    653         for (int q = 0; q <= WCS->trans->y->nX; q++) {
    654           for (int r = 0; r <= WCS->trans->y->nY; r++) {
    655             WCS->trans->y->coeff[q][r] *= pow(cd1f,q) * pow(cd2f,r);
    656           }
    657         }
    658         pmAstromWCStoHeader (hdu->header,WCS);
    659        
    660         if (bilevelAstrometry) {
    661             if (!pmAstromReadBilevelChip (chip, hdu->header)) {
    662                 psError(psErrorCodeLast(), false, "Unable to read bilevel chip astrometry for input FPA.");
    663                 psFree(view);
    664                 psFree(stats);
    665                 goto DONE;
    666             }
    667         } else {
    668             // we use a default FPA pixel scale of 1.0
    669             if (!pmAstromReadWCS (astrom->fpa, chip, hdu->header, 1.0)) {
    670                 psError(psErrorCodeLast(), false, "Unable to read WCS astrometry for input FPA.");
    671                 psFree(view);
    672                 psFree(stats);
    673                 goto DONE;
    674             }
    675         }
    676         // Modify structure here.
    677 
    678        
    679         pmCell *cell;
    680         while ((cell = pmFPAviewNextCell (view, input->fpa, 1)) != NULL) {
    681             psTrace ("pswarp", 4, "DCell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
    682             if (!cell->process || !cell->file_exists) { continue; }
    683             if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) {
    684                 psError(psErrorCodeLast(), false, "Unable to read files.");
    685                 goto DONE;
    686             }
    687 
    688             psListAdd(cells, PS_LIST_TAIL, cell);
    689 
    690             // process each of the readouts
    691             pmReadout *readout;
    692             while ((readout = pmFPAviewNextReadout(view, input->fpa, 1)) != NULL) {
    693                 if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
    694                     psError(psErrorCodeLast(), false, "Unable to read files.");
    695                     goto DONE;
    696                 }
    697                 if (!readout->data_exists) {
    698                     continue;
    699                 }
    700 
    701                 for (int x = 0; x < readout->image->numCols; x++) {
    702                   for (int y = 0; y < readout->image->numRows; y++) {
    703                     readout->image->data.F32[y][x] = readout->image->data.F32[y][x] * (cd1f * cd2f) /
    704                       (psMetadataLookupS32(&mdok,config->arguments,"BKG.XGRID") *
    705                        psMetadataLookupS32(&mdok,config->arguments,"BKG.YGRID"));
    706                   }
    707                 }
    708                
    709                 psMetadataAddS32(config->arguments,PS_LIST_TAIL, "INTERPOLATION.MODE", PS_META_REPLACE, "", 8);
    710 
    711                 psMetadataAddBool(config->arguments,PS_LIST_TAIL, "BACKGROUND_WARPING", PS_META_REPLACE, "", true);
    712                 pswarpTransformReadout(output, readout, config);
    713                 psMetadataAddBool(config->arguments,PS_LIST_TAIL, "BACKGROUND_WARPING", PS_META_REPLACE, "", false);
    714 
    715                 if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
    716                     psError(psErrorCodeLast(), false, "Unable to write files.");
    717                     goto DONE;
    718                 }
    719             }
    720             if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
    721                 psError(psErrorCodeLast(), false, "Unable to write files.");
    722                 goto DONE;
    723             }
    724         }
    725         if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
    726             psError(psErrorCodeLast(), false, "Unable to write files.");
    727             goto DONE;
    728         }
    729     }
    730     if (!output->data_exists) {
    731         psWarning("No overlap between input and skycell.");
    732         psphotFilesActivate(config, false);
    733         psFree(cells);
    734         psFree(view);
    735         goto DONE;
    736     }
    737     pmCell *outCell = output->parent;   ///< Output cell
    738     pmChip *outChip = outCell->parent;  ///< Output chip
    739     pmFPA *outFPA = outChip->parent;    ///< Output FP
    740 
    741 /*     if (!pswarpPixelsLit(output, stats, config)) { */
    742 /*         psError(psErrorCodeLast(), false, "Unable to calculate pixel regions."); */
    743 /*         psFree(cells); */
    744 /*         psFree(view); */
    745 /*         goto DONE; */
    746 /*     } */
    747     psRegion *trimsec = psMetadataLookupPtr(NULL, outCell->concepts, "CELL.TRIMSEC"); ///< Trim section
    748     trimsec->x0 = trimsec->x1 = trimsec->y0 = trimsec->y1 = 0; ///< All pixels
    749 
    750     if (!psMetadataCopy(outFPA->concepts, input->fpa->concepts)) {
    751         psError(psErrorCodeLast(), false, "Unable to copy FPA concepts from input to output.");
    752         psFree(stats);
    753         psFree(view);
    754         goto DONE;
    755     }
    756 
    757     pmHDU *hdu = outFPA->hdu;           ///< HDU for the output warped image
    758 
    759     // Copy header from target
    760     {
    761         pmFPAview *skyView = pmFPAviewAlloc(0); ///< View into skycell
    762         skyView->chip = skyView->cell = 0;
    763         pmCell *cell = pmFPAfileThisCell(config->files, skyView, "PSWARP.SKYCELL"); // Skycell cell
    764         psFree(skyView);
    765         pmHDU *skyHDU = pmHDUFromCell(cell); ///< HDU
    766         if (!skyHDU) {
    767             psError(PSWARP_ERR_DATA, false, "Unable to find skycell HDU.");
    768             psFree(view);
    769             goto DONE;
    770         }
    771         hdu->header = psMetadataCopy(hdu->header, skyHDU->header);
    772     }
    773     pswarpVersionHeader(hdu->header);
    774    
    775     if (!pmAstromWriteWCS(hdu->header, outFPA, outChip, WCS_NONLIN_TOL)) {
    776         psError(psErrorCodeLast(), false, "Unable to generate WCS header.");
    777         psFree(stats);
    778         goto DONE;
    779     }
    780     if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
    781         psError(psErrorCodeLast(), false, "Unable to write files.");
    782         goto DONE;
    783     }
    784     // Done with the detector side of things
    785     pswarpFileActivation(config, detectorFiles, false);
    786     pswarpFileActivation(config, independentFiles, false);
    787 
    788 
    789     // Add MD5 information for readout
    790     const char *chipName = psMetadataLookupStr(NULL, output->parent->parent->concepts, "CHIP.NAME");
    791     const char *cellName = psMetadataLookupStr(NULL, output->parent->concepts, "CELL.NAME");
    792     psString headerName = NULL; ///< Header name for MD5
    793     psStringAppend(&headerName, "MD5_%s_%s_%d", chipName, cellName, view->readout);
    794     psVector *md5 = psImageMD5(output->image); ///< md5 hash
    795     psString md5string = psMD5toString(md5); ///< String
    796     psFree(md5);
    797     psMetadataAddStr(hdu->header, PS_LIST_TAIL, headerName, PS_META_REPLACE,
    798                      "Image MD5", md5string);
    799     psFree(md5string);
    800     psFree(headerName);
    801     psFree(view);
    802  DONE:
    803 
    804     return true;
    805 }
  • trunk/pswarp/src/pswarpMaskStats.c

    r28130 r35563  
    11#include "pswarp.h"
    2 #include <ppStats.h>
    32
    43bool pswarpMaskStats(const pmReadout *readout, psMetadata *stats, const pmConfig *config)
     
    3130                              dynamicMaskVal,advisoryMaskVal)) {
    3231    psError(PS_ERR_UNKNOWN, false, "Unable to calculate masks for readout.");
    33     return(false);
     32    return false;
    3433  }
    35   psMetadataAddS32(stats, PS_LIST_TAIL,"MASKFRAC_NPIX", 0,
    36                    "Number of valid pixels", Npix_valid);
    37   psMetadataAddF32(stats,PS_LIST_TAIL, "MASKFRAC_STATIC", 0,
    38                    "Fraction of pixels statically masked", (float) Npix_static / Npix_valid);
    39   psMetadataAddF32(stats,PS_LIST_TAIL, "MASKFRAC_DYNAMIC", 0,
    40                    "Fraction of pixels dynamically masked", (float) Npix_dynamic / Npix_valid);
    41   psMetadataAddF32(stats,PS_LIST_TAIL, "MASKFRAC_MAGIC", 0,
    42                    "Fraction of pixels magically masked", (float) Npix_magic / Npix_valid);
    43   psMetadataAddF32(stats,PS_LIST_TAIL, "MASKFRAC_ADVISORY", 0,
    44                    "Fraction of pixels masked as an advisory", (float) Npix_advisory / Npix_valid);
    45   return(true);
     34
     35  // XXX with multiple inputs (eg, output stacks -> exposure), these only represent the last input
     36  psMetadataAddS32(stats, PS_LIST_TAIL,"MASKFRAC_NPIX",     PS_META_REPLACE, "Number of valid pixels", Npix_valid);
     37  psMetadataAddF32(stats,PS_LIST_TAIL, "MASKFRAC_STATIC",   PS_META_REPLACE, "Fraction of pixels statically masked", (float) Npix_static / Npix_valid);
     38  psMetadataAddF32(stats,PS_LIST_TAIL, "MASKFRAC_DYNAMIC",  PS_META_REPLACE, "Fraction of pixels dynamically masked", (float) Npix_dynamic / Npix_valid);
     39  psMetadataAddF32(stats,PS_LIST_TAIL, "MASKFRAC_MAGIC",    PS_META_REPLACE, "Fraction of pixels magically masked", (float) Npix_magic / Npix_valid);
     40  psMetadataAddF32(stats,PS_LIST_TAIL, "MASKFRAC_ADVISORY", PS_META_REPLACE, "Fraction of pixels masked as an advisory", (float) Npix_advisory / Npix_valid);
     41  return true;
    4642}
  • trunk/pswarp/src/pswarpMatchRange.c

    r21323 r35563  
    115115    psPlaneTransformApply (srcFP, fpaSrc->fromTPA, srcTP);
    116116    psPlaneTransformApply (srcPix, chipSrc->fromFPA, srcFP);
    117     fprintf (stderr, "-> %f,%f ", srcPix->x, srcPix->y);
     117    fprintf (stderr, "-> %f,%f\n", srcPix->x, srcPix->y);
    118118# endif
    119119
  • trunk/pswarp/src/pswarpParseCamera.c

    r34800 r35563  
    1313#include "pswarp.h"
    1414
    15 // Define an input file
    16 static pmFPAfile *defineInputFile(pmConfig *config,// Configuration
    17                                   pmFPAfile *bind,    // File to which to bind, or NULL
    18                                   char *filerule,     // Name of file rule
    19                                   char *argname,      // Argument name
    20                                   pmFPAfileType fileType // Type of file
    21     )
    22 {
    23     bool status;
    24 
    25     pmFPAfile *file = NULL;
    26     // look for the file on the argument list
    27     if (bind) {
    28         file = pmFPAfileBindFromArgs(&status, bind, config, filerule, argname);
    29     } else {
    30         file = pmFPAfileDefineFromArgs(&status, config, filerule, argname);
    31     }
    32     if (!status) {
    33         psError(psErrorCodeLast(), false, "Failed to load file definition for %s", filerule);
    34         return false;
    35     }
    36     if (!file) {
    37         // look for the file on the RUN metadata
    38         file = pmFPAfileDefineFromRun(&status, bind, config, filerule); // File to return
    39         if (!status) {
    40             psError(psErrorCodeLast(), false, "Failed to load file definition for %s", filerule);
    41             return NULL;
    42         }
    43     }
    44 
    45     if (!file) {
    46         return NULL;
    47     }
    48 
    49     if (file->type != fileType) {
    50         psError(PSWARP_ERR_CONFIG, true, "%s is not of type %s", filerule, pmFPAfileStringFromType(fileType));
    51         return NULL;
    52     }
    53 
    54     return file;
    55 }
    56 
    57 
    58 
     15static bool foundAstrom = false;
     16static bool foundVariance = false;
     17static bool foundBackground = false;
    5918
    6019bool pswarpParseCamera(pmConfig *config)
    6120{
    6221    psAssert(config, "Require configuration");
    63     bool mdok;                          // Status of MD lookup
    64 
    65     // The input image(s) is required: it defines the camera
    66     pmFPAfile *input = defineInputFile(config, NULL, "PSWARP.INPUT", "INPUT", PM_FPA_FILE_IMAGE);
    67     if (!input) {
    68         psError(psErrorCodeLast(), false, "Failed to build FPA from PSWARP.INPUT");
    69         return false;
    70     }
    71 
    72     pmFPAfile *astrom = defineInputFile(config, NULL, "PSWARP.ASTROM", "ASTROM", PM_FPA_FILE_CMF);
    73     psLogMsg("pswarp", PS_LOG_INFO, "Astrometry source: %s", astrom ? "supplied" : "header");
    74 
    75     pmFPAfile *inMask = defineInputFile(config, input, "PSWARP.MASK", "MASK", PM_FPA_FILE_MASK);
    76     if (!inMask) {
    77         psLogMsg("pswarp", PS_LOG_INFO, "No mask supplied");
    78     }
    79 
    80     pmFPAfile *inVariance = defineInputFile(config, input, "PSWARP.VARIANCE", "VARIANCE",
    81                                             PM_FPA_FILE_VARIANCE);
    82     if (!inVariance) {
    83         psLogMsg("pswarp", PS_LOG_INFO, "No variance supplied");
    84     }
    85 
    86     pmFPAfile *inBackground = defineInputFile(config, NULL, "PSWARP.BKGMODEL", "BACKGROUND",
    87                                               PM_FPA_FILE_IMAGE);
    88     if (!inBackground) {
    89       psLogMsg("pswarp", PS_LOG_INFO, "No background models supplied");
    90     }
    91    
     22    bool status;                          // Status of MD lookup
     23
     24    // *** parse the input information (either from -file or from -input)
     25
     26    // if INPUTS exists, we have a metadata file to provide input, variance, mask, etc
     27    psMetadata *inputFile = psMetadataLookupPtr(&status, config->arguments, "INPUTS");
     28    if (inputFile) {
     29        if (!pswarpParseMultiInput (config, inputFile)) {
     30            psError(PSWARP_ERR_CONFIG, false, "failed to parse multi-input file");
     31            return false;
     32        }
     33    } else {
     34        if (!pswarpParseSingleInput (config)) {
     35            psError(PSWARP_ERR_CONFIG, false, "failed to parse multi-input file");
     36            return false;
     37        }
     38    }
     39
     40    // once we have read the input mask headers (if any), we can use that to set the mask bits
     41    if (!pswarpSetMaskBits(config)) {
     42        psError(psErrorCodeLast(), false, "failed to set mask bits");
     43        return false;
     44    }
     45
     46    // *** parse the output information (output target, output astrometry [skycell])
     47
    9248    // The input skycell is a required argument: it defines the output image
    93     // XXX we may need a different skycell structure here
     49    pmConfig *skyConfig = NULL;
    9450    pmFPAfile *skycell = NULL;
    95     pmConfig *skyConfig = NULL;
    96     bool status = pswarpDefineSkycell(&skycell, &skyConfig, config, "PSWARP.SKYCELL", "SKYCELL");
    97     if (!status) {
    98         psError(psErrorCodeLast(), false, "Failed to build FPA from PSWARP.SKYCELL");
    99         return false;
    100     }
     51
     52    skycell = pmFPAfileDefineNewConfig(&status, &skyConfig, config, "PSWARP.SKYCELL", "SKYCELL");
     53    if (!status || !skycell) {
     54      psError(psErrorCodeLast(), false, "Failed to build FPA from PSWARP.SKYCELL");
     55      return false;
     56      }
     57    psMetadataAddStr(config->arguments, PS_LIST_TAIL, "SKYCELL.CAMERA", 0, "Name of camera for skycell", skyConfig->cameraName);
    10158    psFree(skyConfig);
    10259
     
    10764    }
    10865
     66    // use the skycell camera or the input camera?
     67    bool useInputCamera = !strcmp (skycell->cameraName, "SIMPLE");
     68
    10969    // The output skycell
    110     pmFPAfile *output = pmFPAfileDefineSkycell(config, NULL, "PSWARP.OUTPUT");
     70    pmFPAfile *output = useInputCamera ?
     71        pmFPAfileDefineSkycell(config, NULL, "PSWARP.OUTPUT") :
     72        pmFPAfileDefineOutputForFormat(config, NULL, "PSWARP.OUTPUT", skycell->cameraName, skycell->formatName);
    11173    if (!output) {
    11274        psError(psErrorCodeLast(), false, "Failed to build FPA from PSWARP.OUTPUT");
     
    11476    }
    11577    output->save = true;
    116 
    117     pmFPAfile *outMask = pmFPAfileDefineSkycell(config, output->fpa, "PSWARP.OUTPUT.MASK");
     78    pmFPAAddSourceFromFormat(output->fpa, output->format); // ** builds the HDUs, is this OK?
     79
     80    pmFPAfile *outMask = useInputCamera ?
     81        pmFPAfileDefineSkycell(config, output->fpa, "PSWARP.OUTPUT.MASK"):
     82        pmFPAfileDefineOutputForFormat(config, output->fpa, "PSWARP.OUTPUT.MASK", skycell->cameraName, skycell->formatName);
    11883    if (!outMask) {
    11984        psError(psErrorCodeLast(), false, "Failed to build FPA from PSWARP.OUTPUT.MASK");
     
    12287    outMask->save = true;
    12388
    124     if (inVariance) {
    125         pmFPAfile *outVariance = pmFPAfileDefineSkycell(config, output->fpa, "PSWARP.OUTPUT.VARIANCE");
     89    // only create an output variance in we supply an input variance
     90    if (foundVariance) {
     91        pmFPAfile *outVariance = useInputCamera ?
     92            pmFPAfileDefineSkycell(config, output->fpa, "PSWARP.OUTPUT.VARIANCE"):
     93            pmFPAfileDefineOutputForFormat(config, output->fpa, "PSWARP.OUTPUT.VARIANCE", skycell->cameraName, skycell->formatName);
    12694        if (!outVariance) {
    12795            psError(psErrorCodeLast(), false, "Failed to build FPA from PSWARP.OUTPUT.VARIANCE");
     
    13199    }
    132100
    133     if (astrom && psMetadataLookupBool(&mdok, recipe, "SOURCES")) {
    134         pmFPAfile *outSources = pmFPAfileDefineSkycell(config, output->fpa, "PSWARP.OUTPUT.SOURCES");
     101    // XXX we assume input sources come from the input astrom description, but this need not be true (we could define an input sources file)
     102    if (foundAstrom && psMetadataLookupBool(&status, recipe, "SOURCES")) {
     103        pmFPAfile *outSources = useInputCamera ?
     104            pmFPAfileDefineSkycell(config, output->fpa, "PSWARP.OUTPUT.SOURCES"):
     105            pmFPAfileDefineOutputForFormat(config, output->fpa, "PSWARP.OUTPUT.SOURCES", skycell->cameraName, skycell->formatName);
    135106        if (!outSources) {
    136107            psError(psErrorCodeLast(), false, "Failed to build FPA from PSWARP.OUTPUT.SOURCES");
     
    140111    }
    141112
    142     if (inBackground && psMetadataLookupBool(&mdok, recipe, "BACKGROUND.MODEL")) {
    143       pmFPAfile *outBackground = pmFPAfileDefineSkycell(config, NULL, "PSWARP.OUTPUT.BKGMODEL");
    144 /*       pmFPAfile *outBackground = pmFPAfileDefineFromFPA(config,output->fpa, */
    145 /*                                                      psMetadataLookupS32(&mdok,recipe,"BKG.XGRID"), */
    146 /*                                                      psMetadataLookupS32(&mdok,recipe,"BKG.YGRID"), */
    147 /*                                                      "PSWARP.OUTPUT.BKGMODEL"); */
    148       outBackground->xBin = psMetadataLookupS32(&mdok, recipe, "BKG.XGRID");
    149       outBackground->yBin = psMetadataLookupS32(&mdok, recipe, "BKG.YGRID");
    150      
    151       if (!outBackground) {
    152         psError(psErrorCodeLast(), false, "Failed to build FPA from PSWARP.OUTPUT.BKGMODEL");
    153         return false;
    154       }
    155       outBackground->save = true;
    156     }
    157    
    158     if (psMetadataLookupBool(&mdok, recipe, "PSF")) {
    159         // This file, PSPHOT.INPUT, is just used as a carrier; output files (eg, PSPHOT.RESID) are defined by
    160         // psphotDefineFiles
    161         pmFPAfile *psphotInput = pmFPAfileDefineSkycell(config, NULL, "PSPHOT.INPUT");
     113    // only create an output background if an input background is supplied
     114    if (foundBackground && psMetadataLookupBool(&status, recipe, "BACKGROUND.MODEL")) {
     115        // pmFPAfile *outBackground = pmFPAfileDefineSkycell(config, NULL, "PSWARP.OUTPUT.BKGMODEL");
     116        pmFPAfile *outBackground = useInputCamera ?
     117            pmFPAfileDefineSkycell(config, NULL, "PSWARP.OUTPUT.BKGMODEL"):
     118            pmFPAfileDefineOutputForFormat(config, NULL, "PSWARP.OUTPUT.BKGMODEL", skycell->cameraName, skycell->formatName);
     119        if (!outBackground) {
     120            psError(psErrorCodeLast(), false, "Failed to build FPA from PSWARP.OUTPUT.BKGMODEL");
     121            return false;
     122        }
     123        outBackground->xBin = psMetadataLookupS32(&status, recipe, "BKG.XGRID");
     124        outBackground->yBin = psMetadataLookupS32(&status, recipe, "BKG.YGRID");
     125        outBackground->save = true;
     126        pmFPAAddSourceFromFormat(outBackground->fpa, outBackground->format); // ** builds the HDUs, is this OK?
     127    }
     128
     129    if (psMetadataLookupBool(&status, recipe, "PSF")) {
     130        // This file, PSPHOT.INPUT, is just used as a carrier; output files (eg, PSPHOT.RESID) are defined by psphotDefineFiles
     131        pmFPAfile *psphotInput = useInputCamera ?
     132            pmFPAfileDefineSkycell(config, NULL, "PSPHOT.INPUT"):
     133            pmFPAfileDefineOutputForFormat(config, NULL, "PSPHOT.INPUT", skycell->cameraName, skycell->formatName);
    162134        if (!psphotInput) {
    163135            psError(psErrorCodeLast(), false, _("Unable to generate output file from PSPHOT.INPUT"));
     
    165137        }
    166138        psphotInput->src = psMemIncrRefCounter(output->fpa);
    167         // specify the number of psphot input images
     139        pmFPAAddSourceFromFormat(psphotInput->fpa, psphotInput->format); // ** builds the HDUs, is this OK?
     140
     141        // specify the number of psphot input images (psphotReadout loops over all input images)
    168142        psMetadataAddS32 (config->arguments, PS_LIST_TAIL, "PSPHOT.INPUT.NUM", PS_META_REPLACE, "number of inputs", 1);
    169143
    170         pmFPAfile *psphotInSources = pmFPAfileDefineSkycell(config, output->fpa, "PSPHOT.INPUT.CMF");
     144        // the input sources (read from the input astrometry file) are transformed (in pswarpLoop) to the readout->analysis
     145        // entries of the output file PSWARP.OUTPUT.SOURCES, associated with the main output pmFPAfile PSWARP.OUTPUT
     146
     147        // the PSPHOT.INPUT.CMF is used to supply those sources to psphot (specifically psphotLoadPSFSources). 
     148
     149        // pmFPAfile *psphotInSources = pmFPAfileDefineSkycell(config, output->fpa, "PSPHOT.INPUT.CMF");
     150        pmFPAfile *psphotInSources = useInputCamera ?
     151            pmFPAfileDefineSkycell(config, output->fpa, "PSPHOT.INPUT.CMF"):
     152            pmFPAfileDefineOutputForFormat(config, output->fpa, "PSPHOT.INPUT.CMF", skycell->cameraName, skycell->formatName);
    171153        if (!psphotInSources) {
    172154            psError(psErrorCodeLast(), false, _("Unable to generate output file from PSPHOT.INPUT.CMF"));
     
    195177        psphotSources->save = false;
    196178    }
     179 
     180    // only keep the necessary (output) camera configs and relevant recipes
     181    const char *skyCamera = psMetadataLookupStr(NULL, config->arguments, "SKYCELL.CAMERA");
     182    pmConfigCamerasCull(config, skyCamera);
     183    pmConfigRecipesCull(config, "PSWARP,PPSTATS,PSPHOT,PSASTRO,MASKS,JPEG");
     184
     185    psTrace("pswarp", 1, "Done with pswarpParseCamera...\n");
     186    return true;
     187}
     188
     189bool pswarpParseSingleInput (pmConfig *config) {
     190
     191    // The input image(s) is required: it defines the camera
     192    pmFPAfile *input = pswarpDefineInputFile(config, NULL, "PSWARP.INPUT", "INPUT", PM_FPA_FILE_IMAGE);
     193    if (!input) {
     194        psError(psErrorCodeLast(), false, "Failed to build FPA from PSWARP.INPUT");
     195        return false;
     196    }
     197
     198    // Define the input astrometry file(s) (may be either WCS or CMF)
     199    bool status = false;
     200    pmFPAfile *astrom = pmFPAfileDefineFromArgs(&status, config, "PSWARP.ASTROM", "ASTROM");
     201    if (!astrom) {
     202        // look for the file on the RUN metadata
     203        astrom = pmFPAfileDefineFromRun(&status, NULL, config, "PSWARP.ASTROM"); // File to return
     204        if (!status) {
     205            psLogMsg("pswarp", PS_LOG_INFO, "Failed to load file definition for %s", "PSWARP.ASTROM");
     206        }
     207    }
     208    if (astrom) {
     209        if ((astrom->type != PM_FPA_FILE_CMF) && (astrom->type != PM_FPA_FILE_WCS)) {
     210            psLogMsg("pswarp", PS_LOG_INFO, "%s is neither CMF nor WCS", "PSWARP.ASTROM");
     211            // XXX raise an error here??
     212        } else {
     213            foundAstrom = true;
     214        }
     215    }
     216    psLogMsg("pswarp", PS_LOG_INFO, "Astrometry source: %s", astrom ? "supplied" : "header");
     217
     218    // Define the input mask file(s)
     219    pmFPAfile *inMask = pswarpDefineInputFile(config, input, "PSWARP.MASK", "MASK", PM_FPA_FILE_MASK);
     220    if (!inMask) {
     221        psLogMsg("pswarp", PS_LOG_INFO, "No mask supplied");
     222    }
     223
     224    // Define the input variance file(s)
     225    pmFPAfile *inVariance = pswarpDefineInputFile(config, input, "PSWARP.VARIANCE", "VARIANCE", PM_FPA_FILE_VARIANCE);
     226    if (inVariance) {
     227        foundVariance = true;
     228    } else {
     229        psLogMsg("pswarp", PS_LOG_INFO, "No variance supplied");
     230    }
     231
     232    pmFPAfile *inBackground = pswarpDefineInputFile(config, NULL, "PSWARP.BKGMODEL", "BACKGROUND", PM_FPA_FILE_IMAGE);
     233    if (inBackground) {
     234        foundBackground = true;
     235    } else {
     236      // cannot do the background model if an input is not supplied.
     237      psMetadataAddBool (config->arguments, PS_LIST_TAIL, "BACKGROUND.MODEL", PS_META_REPLACE, "no input background supplied", false);
     238      psLogMsg("pswarp", PS_LOG_INFO, "No background models supplied");
     239    }
    197240
    198241    // Chip selection: turn on only the chips specified
    199     char *chipLine = psMetadataLookupStr(&mdok, config->arguments, "CHIP_SELECTIONS");
    200     if (mdok) {
     242    char *chipLine = psMetadataLookupStr(&status, config->arguments, "CHIP_SELECTIONS");
     243    if (status) {
    201244        psArray *chips = psStringSplitArray (chipLine, ",", false);
    202245        if (chips->n > 0) {
     
    213256    }
    214257
    215     psTrace("pswarp", 1, "Done with pswarpParseCamera...\n");
     258    psMetadataAddS32(config->arguments, PS_LIST_TAIL, "NUM_INPUTS", PS_META_REPLACE, "input file sets", 1);
    216259    return true;
    217260}
     261
     262// read input file information from a metadata file
     263// XXX for now, in the multi-input format, we disable PSF, BACKGROUND, and CHIP_SELECTIONS
     264bool pswarpParseMultiInput (pmConfig *config, psMetadata *fileListMD) {
     265
     266    // the multi-input file consists of a set of metadata blocks, each with entries
     267    // for INPUT and (possibly) ASTROM, MASK, VARIANCE, ???
     268
     269    bool status = false;
     270
     271    for (int i = 0; i < fileListMD->list->n; i++) {
     272        psMetadataItem *item = psMetadataGet(fileListMD, i);
     273        if (item->type != PS_DATA_METADATA) {
     274            psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Component %s of the input metadata is not of type METADATA", item->name);
     275            return false;
     276        }
     277
     278        // next input metadata block of interest
     279        psMetadata *fileBlockMD = item->data.md;
     280
     281        psString inputName = psMetadataLookupStr(&status, fileBlockMD, "INPUT"); // Name of image
     282        if (!inputName || !strlen(inputName)) {
     283            psError(PS_ERR_UNKNOWN, false, "input file not found in metadata block %d (%s)", i, item->name);
     284            return false;
     285        }
     286        AddStringAsArray (config->arguments, inputName, "FILENAMES");
     287
     288        pmFPAfile *input = pswarpDefineInputFile (config, NULL, "PSWARP.INPUT", "FILENAMES", PM_FPA_FILE_IMAGE);
     289        if (!input) {
     290            psError(psErrorCodeLast(), false, "Failed to build FPA from PSWARP.INPUT");
     291            return false;
     292        }
     293
     294        psString astromName = psMetadataLookupStr(&status, fileBlockMD, "ASTROM"); // Name of astrom file
     295        if (astromName && strlen(astromName)) {
     296            AddStringAsArray (config->arguments, astromName, "FILENAMES");
     297
     298            pmFPAfile *astrom = pmFPAfileDefineFromArgs (&status, config, "PSWARP.ASTROM", "FILENAMES");
     299            if (!status) {
     300                psLogMsg("pswarp", PS_LOG_INFO, "Failed to load file definition for %s", "PSWARP.ASTROM");
     301            }
     302            if (astrom) {
     303                if ((astrom->type != PM_FPA_FILE_CMF) && (astrom->type != PM_FPA_FILE_WCS)) {
     304                    psLogMsg("pswarp", PS_LOG_INFO, "%s is neither CMF nor WCS", "PSWARP.ASTROM");
     305                } else {
     306                    foundAstrom = true;
     307                }
     308            }
     309            psLogMsg("pswarp", PS_LOG_INFO, "Astrometry source: %s", astrom ? "supplied" : "header");
     310        }
     311
     312        pmFPAfile *mask = NULL;
     313        psString maskName = psMetadataLookupStr(&status, fileBlockMD, "MASK"); // Name of mask
     314        if (maskName && strlen(maskName)) {
     315            AddStringAsArray (config->arguments, maskName, "FILENAMES");
     316
     317            mask = pswarpDefineInputFile (config, input, "PSWARP.MASK", "FILENAMES", PM_FPA_FILE_MASK);
     318        }
     319        if (!mask) {
     320            psLogMsg("pswarp", PS_LOG_INFO, "No mask supplied");
     321        }
     322
     323        pmFPAfile *variance = NULL;
     324        psString varianceName = psMetadataLookupStr(&status, fileBlockMD, "VARIANCE"); // Name of variance
     325        if (varianceName && strlen(varianceName)) {
     326            AddStringAsArray (config->arguments, varianceName, "FILENAMES");
     327
     328            variance = pswarpDefineInputFile (config, input, "PSWARP.VARIANCE", "FILENAMES", PM_FPA_FILE_VARIANCE);
     329        }
     330        if (variance) {
     331            foundVariance = true;
     332        } else {
     333            psLogMsg("pswarp", PS_LOG_INFO, "No variance supplied");
     334        }
     335
     336        // XXX for now we do not have an option to supply a background model set in multi input mode
     337        psMetadataAddBool (config->arguments, PS_LIST_TAIL, "BACKGROUND.MODEL", PS_META_REPLACE, "no input background supplied", false);
     338    }
     339
     340    psMetadataAddS32(config->arguments, PS_LIST_TAIL, "NUM_INPUTS", PS_META_REPLACE, "input file sets", fileListMD->list->n);
     341    return true;
     342}
     343
     344// Define an input file based on name in config->arguments or config RUN block
     345pmFPAfile *pswarpDefineInputFile(pmConfig *config,// Configuration
     346                                 pmFPAfile *bind,    // File to which to bind, or NULL
     347                                 char *filerule,     // Name of file rule
     348                                 char *argname,      // Argument name
     349                                 pmFPAfileType fileType // Type of file
     350    )
     351{
     352    bool status;
     353
     354    pmFPAfile *file = NULL;
     355    // look for the file on the argument list
     356    if (bind) {
     357        file = pmFPAfileBindFromArgs(&status, bind, config, filerule, argname);
     358    } else {
     359        file = pmFPAfileDefineFromArgs(&status, config, filerule, argname);
     360    }
     361    if (!status) {
     362        psError(psErrorCodeLast(), false, "Failed to load file definition for %s", filerule);
     363        return false;
     364    }
     365    if (!file) {
     366        // look for the file on the RUN metadata
     367        file = pmFPAfileDefineFromRun(&status, bind, config, filerule); // File to return
     368        if (!status) {
     369            psError(psErrorCodeLast(), false, "Failed to load file definition for %s", filerule);
     370            return NULL;
     371        }
     372    }
     373
     374    if (!file) {
     375        return NULL;
     376    }
     377
     378    if (file->type != fileType) {
     379        psError(PSWARP_ERR_CONFIG, true, "%s is not of type %s", filerule, pmFPAfileStringFromType(fileType));
     380        return NULL;
     381    }
     382
     383    return file;
     384}
     385
     386bool AddStringAsArray (psMetadata *md, char *string, char *name) {
     387
     388    psArray *dummy = psArrayAlloc(1);   // Dummy array of filenames for this FPA
     389    dummy->data[0] = psStringCopy(string);
     390
     391    psMetadataAddArray(md, PS_LIST_TAIL, name, PS_META_REPLACE, "string added as array", dummy);
     392    psFree(dummy);
     393    return true;
     394}
     395
  • trunk/pswarp/src/pswarpPixelsLit.c

    r23688 r35563  
    6464    for (int y = 0; y < numRows; y++) {
    6565        for (int x = 0; x < numCols; x++) {
    66             if (!(mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & maskValue)) {
    67                 if (y > yMax) {
    68                     yMax = y;
    69                 }
    70                 if (y < yMin) {
    71                     yMin = y;
    72                 }
    73                 if (x > xMax) {
    74                     xMax = x;
    75                 }
    76                 if (x < xMin) {
    77                     xMin = x;
    78                 }
    79             }
     66            if (mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & maskValue) { continue; }
     67            xMin = PS_MIN (xMin, x);
     68            xMax = PS_MAX (xMax, x);
     69            yMin = PS_MIN (yMin, y);
     70            yMax = PS_MAX (yMax, y);
    8071        }
    8172    }
    8273
    8374    if (stats) {
    84         psMetadataAddS32(stats, PS_LIST_TAIL, "RANGE.XMIN", 0, "Minimum valid x value", xMin);
    85         psMetadataAddS32(stats, PS_LIST_TAIL, "RANGE.XMAX", 0, "Maximum valid x value", xMax);
    86         psMetadataAddS32(stats, PS_LIST_TAIL, "RANGE.YMIN", 0, "Minimum valid y value", yMin);
    87         psMetadataAddS32(stats, PS_LIST_TAIL, "RANGE.YMAX", 0, "Maximum valid y value", yMax);
     75        // XXX with multiple inputs (eg, output stacks -> exposure), these only represent the last input
     76        psMetadataAddS32(stats, PS_LIST_TAIL, "RANGE.XMIN", PS_META_REPLACE, "Minimum valid x value", xMin);
     77        psMetadataAddS32(stats, PS_LIST_TAIL, "RANGE.XMAX", PS_META_REPLACE, "Maximum valid x value", xMax);
     78        psMetadataAddS32(stats, PS_LIST_TAIL, "RANGE.YMIN", PS_META_REPLACE, "Minimum valid y value", yMin);
     79        psMetadataAddS32(stats, PS_LIST_TAIL, "RANGE.YMAX", PS_META_REPLACE, "Maximum valid y value", yMax);
    8880    }
    8981
  • trunk/pswarp/src/pswarpTransformReadout.c

    r34800 r35563  
    1616 * NOTE: in this function, the coordinates are transformed from the OUTPUT to the INPUT
    1717 */
    18 bool pswarpTransformReadout(pmReadout *output, pmReadout *input, pmConfig *config)
     18bool pswarpTransformReadout(pmReadout *output, pmReadout *input, pmConfig *config, bool backgroundWarp)
    1919{
    2020    // XXX this implementation currently ignores the use of the region
     
    5252    }
    5353
    54     // XXX unused int nThreads = psMetadataLookupS32(&mdok, config->arguments, "NTHREADS"); // Number of threads
    55     // XXX unused if (!mdok) {
    56     // XXX unused     nThreads = 0;
    57     // XXX unused }
    5854    float poorFrac = psMetadataLookupF32(NULL, config->arguments, "POOR.FRAC"); ///< Flux fraction for "poor"
    5955
     
    6157    // output coordinates to input coordinates
    6258    pswarpMapGrid *grid = pswarpMapGridFromImage(input, output, nGridX, nGridY);
    63     //    if (psMetadataLookupBool(NULL,config->arguments,"BACKGROUND_WARPING")) {
    6459   
    6560    // XXX optionally modify the grid based on this result and force the maxError < XXX
     
    117112    psAssert (xGridMax < grid->nXpts, "xGridMax too big\n");
    118113    psAssert (yGridMax < grid->nYpts, "yGridMax too big\n");
     114
     115    // fprintf (stderr, "warp %d,%d - %d,%d\n", xGridMin, yGridMin, xGridMax, yGridMax);
    119116
    120117    // create jobs and supply them to the threads
     
    132129            args->goodPixels = 0;
    133130
    134             if (psMetadataLookupBool(NULL,config->arguments,"BACKGROUND_WARPING")) {
     131            if (backgroundWarp) {
    135132              args->background_warping = true;
    136133              args->offset_x = psMetadataLookupF32(NULL,config->arguments,"BKG_WARP_XOFFSET");
    137134              args->offset_y = psMetadataLookupF32(NULL,config->arguments,"BKG_WARP_YOFFSET");
    138135            }
    139 
    140136           
    141137            // allocate a job
     
    210206    psFree(interp);
    211207
    212     if (goodPixels > 0 && psMetadataLookupBool(&mdok, recipe, "SOURCES")) {
    213       if (!psMetadataLookupBool(NULL,config->arguments,"BACKGROUND_WARPING")) {
    214         if (!pswarpTransformSources(output, input, config)) {
    215           psError(psErrorCodeLast(), false, "Unable to interpolate image.");
    216           return false;
     208    if (goodPixels > 0 && !backgroundWarp && psMetadataLookupBool(&mdok, recipe, "SOURCES")) {
     209        if (!pswarpTransformSources(output, input, config)) {
     210            psError(psErrorCodeLast(), false, "Unable to transform sources.");
     211            return false;
    217212        }
    218       }
    219213    }
    220214
  • trunk/pswarp/src/pswarpTransformTile.c

    r34800 r35563  
    8989
    9090    for (int y = yMin; y < yMax; y++) {
     91
     92      int yOut = y - outRow0; ///< Position on output image
     93
    9194        for (int x = xMin; x < xMax; x++) {
    9295            // Only transform those pixels requested
     
    9497                continue;
    9598            }
     99
     100            int xOut = x - outCol0;
     101
     102            // XXX the existing image may already have valid data -- probably should keep
     103            // the best, but for the moment, just keep the pixel which is not NAN
     104            if (isfinite(outImageData[yOut][xOut])) continue;
     105
    96106            // pswarpMapApply converts the output coordinate (x,y) to the input coordinate.
    97107            // both are in the parent frames of the input and output images.
     
    127137            }
    128138
    129             int xOut = x - outCol0, yOut = y - outRow0; ///< Position on output image
    130 
    131139            if (outImageData) {
    132                 outImageData[yOut][xOut] = imageValue * jacobian;
     140              // XXX TEST outImageData[yOut][xOut] = value;
     141              outImageData[yOut][xOut] = imageValue * jacobian;
    133142            }
    134143            if (outVarData) {
  • trunk/pswarp/src/pswarpVersion.c

    r28043 r35563  
    1313#include <config.h>
    1414#endif
    15 
    16 #include <stdio.h>
    17 #include <pslib.h>
    18 #include <psmodules.h>
    19 #include <psphot.h>
    20 #include <ppStats.h>
    2115
    2216#include "pswarp.h"
Note: See TracChangeset for help on using the changeset viewer.