IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 23740 for trunk/ppSub


Ignore:
Timestamp:
Apr 7, 2009, 4:50:25 PM (17 years ago)
Author:
Paul Price
Message:

Merging branches/pap from r23739 onto trunk. No conflicts, ppSub builds fine.

Location:
trunk
Files:
20 edited
7 copied

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/ppSub

  • trunk/ppSub/configure.ac

    r21038 r23740  
    2323PKG_CHECK_MODULES([PSPHOT], [psphot >= 0.9.0])
    2424
     25AC_PATH_PROG([ERRORCODES], [psParseErrorCodes], [missing])
     26if test "$ERRORCODES" = "missing" ; then
     27  AC_MSG_ERROR([psParseErrorCodes is required])
     28fi
     29
    2530dnl Set CFLAGS for build
    2631IPP_STDOPTS
  • trunk/ppSub/src

    • Property svn:ignore
      •  

        old new  
        1010stamp-h1
        1111ppSubKernel
         12ppSubErrorCodes.h
         13ppSubErrorCodes.c
  • trunk/ppSub/src/Makefile.am

    r23688 r23740  
    1313ppSub_LDFLAGS  = $(PSLIB_LIBS)   $(PSMODULE_LIBS)   $(PPSTATS_LIBS)   $(PSPHOT_LIBS)   $(PPSUB_LIBS)
    1414
    15 ppSub_SOURCES =                  \
    16         ppSub.c                  \
    17         ppSubArguments.c         \
    18         ppSubVersion.c           \
    19         ppSubBackground.c        \
    20         ppSubCamera.c            \
    21         ppSubData.c              \
    22         ppSubLoop.c              \
    23         ppSubReadout.c           \
    24         ppSubDefineOutput.c      \
    25         ppSubExtras.c            \
    26         ppSubMakePSF.c           \
    27         ppSubMatchPSFs.c         \
    28         ppSubReadoutPhotometry.c \
    29         ppSubReadoutSubtract.c   \
    30         ppSubReadoutUpdate.c     \
    31         ppSubSetMasks.c          \
    32         ppSubReadoutRenorm.c     \
     15ppSub_SOURCES =                         \
     16        ppSub.c                         \
     17        ppSubArguments.c                \
     18        ppSubVersion.c                  \
     19        ppSubBackground.c               \
     20        ppSubCamera.c                   \
     21        ppSubData.c                     \
     22        ppSubErrorCodes.c               \
     23        ppSubFiles.c                    \
     24        ppSubLoop.c                     \
     25        ppSubDefineOutput.c             \
     26        ppSubExtras.c                   \
     27        ppSubMakePSF.c                  \
     28        ppSubMatchPSFs.c                \
     29        ppSubReadoutInverse.c           \
     30        ppSubReadoutJpeg.c              \
     31        ppSubReadoutPhotometry.c        \
     32        ppSubReadoutStats.c             \
     33        ppSubReadoutSubtract.c          \
     34        ppSubSetMasks.c                 \
     35        ppSubReadoutRenorm.c            \
    3336        ppSubVarianceFactors.c
    3437
     
    4245        ppSub.h
    4346
     47
     48### Error codes.
     49BUILT_SOURCES = ppSubErrorCodes.h ppSubErrorCodes.c
     50CLEANFILES = ppSubErrorCodes.h ppSubErrorCodes.c
     51
     52ppSubErrorCodes.h : ppSubErrorCodes.dat ppSubErrorCodes.h.in
     53        $(ERRORCODES) --data=ppSubErrorCodes.dat --outdir=. ppSubErrorCodes.h
     54
     55ppSubErrorCodes.c : ppSubErrorCodes.dat ppSubErrorCodes.c.in ppSubErrorCodes.h
     56        $(ERRORCODES) --data=ppSubErrorCodes.dat --outdir=. ppSubErrorCodes.c
     57
     58
    4459clean-local:
    4560        -rm -f TAGS
     
    4863tags:
    4964        etags `find . -name \*.[ch] -print`
    50 
  • trunk/ppSub/src/ppSub.c

    r23242 r23740  
    2828    psLibInit(NULL);
    2929
     30    ppSubData *data = NULL;             // Processing data
    3031    pmConfig *config = pmConfigRead(&argc, argv, PPSUB_RECIPE); // Configuration
    3132    if (!config) {
     
    4950    }
    5051
    51     if (!ppSubArgumentsSetup(argc, argv, config)) {
     52    data = ppSubDataAlloc(); // Processing data
     53
     54    if (!ppSubArguments(argc, argv, config, data)) {
    5255        psErrorStackPrint(stderr, "Error reading arguments.\n");
    5356        exitValue = PS_EXIT_CONFIG_ERROR;
     
    5558    }
    5659
    57     if (!ppSubCamera(config)) {
     60    if (!ppSubCamera(config, data)) {
    5861        psErrorStackPrint(stderr, "Error setting up camera.\n");
    5962        exitValue = PS_EXIT_CONFIG_ERROR;
     
    6164    }
    6265
    63     if (!ppSubArgumentsParse(config)) {
    64         psErrorStackPrint(stderr, "Error reading arguments.\n");
    65         exitValue = PS_EXIT_CONFIG_ERROR;
    66         goto die;
    67     }
    68 
    69     if (!ppSubLoop(config)) {
     66    if (!ppSubLoop(config, data)) {
    7067        psErrorStackPrint(stderr, "Error performing subtraction.\n");
    7168        exitValue = PS_EXIT_SYS_ERROR;
     
    7774    psTimerStop();
    7875
     76    psFree(data);
     77    psFree(config);
     78
    7979    pmVisualClose(); //close plot windows, if -visual is set
    80     psFree(config);
    8180    pmModelClassCleanup();
    8281    pmConfigDone();
  • trunk/ppSub/src/ppSub.h

    r23688 r23740  
    1414#define PP_SUB_H
    1515
     16#include <stdio.h>
    1617#include <pslib.h>
    1718#include <psmodules.h>
     19
     20#include "ppSubErrorCodes.h"
    1821
    1922/// @addtogroup ppSub
     
    2427// Output files, for activation/deactivation
    2528typedef enum {
    26     PPSUB_FILES_IMAGE = 0x01,           // Image files
    27     PPSUB_FILES_PHOT  = 0x02,           // Photometry files
    28     PPSUB_FILES_ALL   = 0xFF,           // All files
     29    PPSUB_FILES_INPUT    = 0x01,        // Input files
     30    PPSUB_FILES_CONV     = 0x02,        // Convolved files (output)
     31    PPSUB_FILES_SUB      = 0x04,        // Subtracted files (output)
     32    PPSUB_FILES_INV      = 0x08,        // Inverse subtracted files (output)
     33    PPSUB_FILES_PSF      = 0x10,        // PSF files (output)
     34    PPSUB_FILES_PHOT_SUB = 0x20,        // Subtraction photometry files (output)
     35    PPSUB_FILES_PHOT_INV = 0x40,        // Inverse subtraction photometry files (output)
     36    PPSUB_FILES_PHOT     = 0x80,        // General photometry files (internal)
     37    PPSUB_FILES_ALL      = 0xFF,        // All files
    2938} ppSubFiles;
    3039
    3140/// Data for processing
    3241typedef struct {
    33     psErrorCode quality;                /// Quality code; 0 for no problem
    34     psMetadata *stats;                  /// Statistics
     42    psErrorCode quality;                // Quality code; 0 for no problem
     43    bool photometry;                    // Perform photometry?
     44    bool inverse;                       // Output inverse subtraction as well?
     45    psString stamps;                    // Stamps file
     46    pmPSF *psf;                         // Point Spread Function
     47    FILE *statsFile;                    // Statistics file
     48    psMetadata *stats;                  // Statistics
    3549} ppSubData;
    3650
     
    3953
    4054/// Setup the arguments parsing
    41 bool ppSubArgumentsSetup(int argc, char *argv[], ///< Command-line arguments
    42                          pmConfig *config    ///< Configuration
    43     );
    44 
    45 /// Parse the arguments
    46 bool ppSubArgumentsParse(pmConfig *config ///< Configuration
     55bool ppSubArguments(int argc, char *argv[], ///< Command-line arguments
     56                    pmConfig *config, ///< Configuration
     57                    ppSubData *data ///< Processing data
    4758    );
    4859
    4960/// Parse the camera input
    50 bool ppSubCamera(pmConfig *config       ///< Configuration
     61bool ppSubCamera(pmConfig *config,      ///< Configuration
     62                 ppSubData *data        ///< Processing data
    5163    );
    5264
    5365/// Loop over the FPA hierarchy
    54 bool ppSubLoop(pmConfig *config         ///< Configuration
     66bool ppSubLoop(pmConfig *config,        ///< Configuration
     67               ppSubData *data          ///< Processing data
    5568    );
    5669
    5770/// Perform PSF-matched image subtraction on the readout
    5871bool ppSubReadout(pmConfig *config,     ///< Configuration
    59                   ppSubData *data,      ///< Processing data
    60                   const pmFPAview *view ///< View of readout to subtract
     72                  ppSubData *data       ///< Processing data
    6173    );
    6274
    6375/// Generate (if needed) and set or update the masks for input and reference images
    64 bool ppSubSetMasks(pmConfig *config,     ///< Configuration
    65                    const pmFPAview *view ///< View of active readout
     76bool ppSubSetMasks(pmConfig *config     ///< Configuration
    6677    );
    6778
    6879/// Generate the PSF-matching kernel and convolve the images as needed.  Most of this function involves
    6980/// looking up the parameters in the recipe and supplying them to the function pmSubtractionMatch()
    70 bool ppSubMatchPSFs(pmConfig *config,    ///< Configuration
    71                     ppSubData *data,    ///< Processing data
    72                     const pmFPAview *view ///< View of active readout
     81bool ppSubMatchPSFs(pmConfig *config,   ///< Configuration
     82                    ppSubData *data     ///< Processing data
    7383    );
    7484
    7585/// Generate the output readout and pass the kernel info to the header
    76 bool ppSubDefineOutput(pmConfig *config, ///< Configuration
    77                        const pmFPAview *view ///< View of active readout
     86bool ppSubDefineOutput(const char *name,///< Name of output to define
     87                       pmConfig *config ///< Configuration
    7888    );
    7989
    8090/// Photometry stage 1: measure the PSF from the minuend image
    81 bool ppSubMakePSF(pmConfig *config,       ///< Configuration
    82                   ppSubData *data,    ///< Processing data
    83                   const pmFPAview *view ///< View of active readout
     91bool ppSubMakePSF(pmConfig *config,     ///< Configuration
     92                  ppSubData *data       ///< Processing data
    8493    );
    8594
    8695/// Perform the actual image subtraction, update output concepts
    87 bool ppSubReadoutSubtract(pmConfig *config,       ///< Configuration
    88                           const pmFPAview *view ///< View of active readout
     96bool ppSubReadoutSubtract(pmConfig *config ///< Configuration
    8997    );
    9098
    9199
    92100/// Photometry stage 2: find and measure sources on the subtracted image
    93 bool ppSubReadoutPhotometry(pmConfig *config,     ///< Configuration
    94                             ppSubData *data,    ///< Processing data
    95                             const pmFPAview *view ///< View of active readout
     101bool ppSubReadoutPhotometry(const char *name, ///< Name of file to photometer
     102                            pmConfig *config, ///< Configuration
     103                            ppSubData *data ///< Processing data
    96104    );
    97105
    98106/// Renormalize, update headers and generate JPEGs
    99107bool ppSubReadoutUpdate(pmConfig *config, ///< Configuration
    100                         ppSubData *data,    ///< Processing data
    101                         const pmFPAview *view ///< View of active readout
     108                        ppSubData *data ///< Processing data
    102109    );
    103110
    104111/// Higher-order background subtraction
    105 bool ppSubBackground(pmConfig *config,  ///< Configuration
    106                      const pmFPAview *view ///< View to readout
     112bool ppSubBackground(pmConfig *config   ///< Configuration
    107113    );
    108114
     
    121127    );
    122128
     129
     130/// Activate or deactivate files
     131void ppSubFilesActivate(pmConfig *config, // Configuration
     132                        ppSubFiles files, // File to activate/deactivate
     133                        bool state      // Activation state
     134    );
     135
     136/// Generate a view suitable for a readout
     137///
     138/// Assumes we're working with skycells
     139pmFPAview *ppSubViewReadout(void);
     140
     141/// Iterate down the FPA hierarchy, opening files
     142bool ppSubFilesIterateDown(pmConfig *config, // Configuration
     143                           ppSubFiles files // Files to open
     144    );
     145
     146/// Iterate up the FPA hierarchy, closing files
     147bool ppSubFilesIterateUp(pmConfig *config, // Configuration
     148                         ppSubFiles files // Files to open
     149    );
     150
     151/// Collect statistics
     152bool ppSubReadoutStats(pmConfig *config,// Configuration
     153                       ppSubData *data  // Processing data
     154    );
     155
     156/// Generate JPEG images
     157bool ppSubReadoutJpeg(pmConfig *config  // Configuration
     158    );
     159
     160/// Generate inverse subtraction
     161bool ppSubReadoutInverse(pmConfig *config // Configuration
     162    );
     163
     164
    123165// Copy every instance of a single keyword from one metadata to another
    124166bool psMetadataCopySingle(psMetadata *target, psMetadata *source, const char *name);
  • trunk/ppSub/src/ppSubArguments.c

    r23402 r23740  
    4141}
    4242
    43 // Get a float-point value from the command-line or recipe, and add it to the arguments
    44 #define VALUE_ARG_RECIPE_FLOAT(ARGNAME, RECIPENAME, TYPE) { \
    45     ps##TYPE value = psMetadataLookup##TYPE(NULL, config->arguments, ARGNAME); \
    46     if (isnan(value)) { \
    47         bool mdok; \
    48         value = psMetadataLookup##TYPE(&mdok, recipe, RECIPENAME); \
    49         if (!mdok) { \
    50             psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unable to find %s in recipe %s", \
    51                 RECIPENAME, PPSUB_RECIPE); \
    52             goto ERROR; \
    53         } \
    54     } \
    55     psMetadataAdd##TYPE(recipe, PS_LIST_TAIL, RECIPENAME, PS_META_REPLACE, NULL, value); \
    56 }
    57 
    58 // Get an integer value from the command-line or recipe, and add it to the arguments
    59 #define VALUE_ARG_RECIPE_INT(ARGNAME, RECIPENAME, TYPE, UNSET) { \
    60     ps##TYPE value = psMetadataLookup##TYPE(NULL, config->arguments, ARGNAME); \
    61     if (value == UNSET) { \
    62         bool mdok; \
    63         value = psMetadataLookup##TYPE(&mdok, recipe, RECIPENAME); \
    64         if (!mdok) { \
    65             psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unable to find %s in recipe %s", \
    66                 RECIPENAME, PPSUB_RECIPE); \
    67             goto ERROR; \
    68         } \
    69     } \
    70     psMetadataAdd##TYPE(recipe, PS_LIST_TAIL, RECIPENAME, PS_META_REPLACE, NULL, value); \
    71 }
    72 
    73 /**
    74  * Get a string value from the command-line and add it to the target
    75  */
    76 static bool valueArgStr(psMetadata *arguments, // Command-line arguments
    77                         const char *argName, // Argument name in the command-line arguments
    78                         const char *mdName, // Name for value in the metadata
    79                         psMetadata *target // Target metadata to which to add value
    80                         )
    81 {
    82     psString value = psMetadataLookupStr(NULL, arguments, argName); // Value of interest
    83     if (value && strlen(value) > 0) {
    84         return psMetadataAddStr(target, PS_LIST_TAIL, mdName, PS_META_REPLACE, NULL, value);
    85     }
    86     return false;
    87 }
    88 
    89 /**
    90  * Get a string value from the command-line or recipe and add it to the target
    91  */
    92 static bool valueArgRecipeStr(psMetadata *arguments, // Command-line arguments
    93                               psMetadata *recipe, // Recipe
    94                               const char *argName, // Argument name in the command-line arguments
    95                               const char *mdName, // Name for value in the metadata and recipe
    96                               psMetadata *target // Target metadata to which to add value
    97                               )
    98 {
    99     bool mdok;                          // Status of MD lookup
    100     psString value = psMetadataLookupStr(&mdok, arguments, argName); // Value of interest
    101     if (!value) {
    102         value = psMetadataLookupStr(&mdok, recipe, mdName);
    103         if (!value) {
    104             psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unable to find %s in recipe %s",
    105                     mdName, PPSUB_RECIPE);
    106             return false;
    107         }
    108     }
    109     return psMetadataAddStr(target, PS_LIST_TAIL, mdName, PS_META_REPLACE, NULL, value);
    110 }
    111 
    112 /**
    113  * Get a vector from the command-line or recipe, and add it to the target
    114  */
    115 static bool vectorArgRecipe(psMetadata *arguments, // Command-line arguments
    116                             const char *argName, // Argument name in the command-line arguments
    117                             const psMetadata *recipe, // Recipe
    118                             const char *recipeName, // Name for value in the recipe
    119                             psMetadata *target, // Target to which to add value
    120                             psElemType type // Type for vector
    121     )
    122 {
    123     psVector *vector;                   // Vector
    124     psString string = psMetadataLookupStr(NULL, arguments, argName); // String from arguments
    125     if (string) {
    126         psArray *array = psStringSplitArray(string, ", ", false); // Array of strings
    127         vector = psVectorAlloc(array->n, type);
    128         for (int i = 0; i < array->n; i++) {
    129             const char *subString = array->data[i]; // String with a value
    130             char *end;                  // Ptr to end of string parsed
    131 
    132             switch (type) {
    133               case PS_TYPE_F32:
    134                 vector->data.F32[i] = strtof(subString, &end);
    135                 break;
    136               case PS_TYPE_S32: {
    137                   long value = strtol(subString, &end, 10);
    138                   if (value > PS_MAX_S32 || value < PS_MIN_S32) {
    139                       psError(PS_ERR_BAD_PARAMETER_VALUE, true,
    140                               "%s list includes value beyond S32 representation: %s",
    141                               argName, string);
    142                       psFree(vector);
    143                       return false;
    144                   }
    145                   vector->data.S32[i] = value;
    146                   break;
    147               }
    148               default:
    149                 psAbort("Unsupported type: %x\n", type);
    150             }
    151             if (end == subString) {
    152                 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unable to decipher %s list: %s",
    153                         argName, string);
    154                 psFree(vector);
    155                 return false;
    156             }
    157         }
    158         psFree(array);
    159     } else {
    160         vector = psMetadataLookupPtr(NULL, recipe, recipeName);
    161         if (!psMemCheckVector(vector) || vector->type.type != type) {
    162             psError(PS_ERR_BAD_PARAMETER_TYPE, false, "%s in recipe %s is not a vector of type F32.",
    163                     recipeName, PPSUB_RECIPE);
    164             return false;
    165         }
    166         psMemIncrRefCounter(vector);
    167     }
    168 
    169     psMetadataAddVector(target, PS_LIST_TAIL, recipeName, PS_META_REPLACE, NULL, vector);
    170     psFree(vector);                     // Drop reference
    171 
    172     return true;
    173 }
    174 
    17543/**
    17644 * Add a single filename to the arguments as an array, so that it can be used with pmFPAfileBindFromArgs, etc
     
    18957}
    19058
    191 bool ppSubArgumentsSetup(int argc, char *argv[], pmConfig *config)
     59bool ppSubArguments(int argc, char *argv[], pmConfig *config, ppSubData *data)
    19260{
    193     //    int argnum;                         // Argument Number
    19461    assert(config);
    195 
    196     psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPSUB_RECIPE); // Recipe for ppSim
    197     if (!recipe) {
    198         psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find recipe %s", PPSUB_RECIPE);
    199         return false;
    200     }
    201 
    20262
    20363    psMetadata *arguments = config->arguments; // Command-line arguments
     
    21272    psMetadataAddStr(arguments, PS_LIST_TAIL, "-kernel", 0, "Precalculated kernel to apply", NULL);
    21373    psMetadataAddStr(arguments, PS_LIST_TAIL, "-stats", 0, "Statistics file", NULL);
    214     psMetadataAddF32(arguments, PS_LIST_TAIL, "-region", 0, "Size of iso-kernel region", NAN);
    215     psMetadataAddS32(arguments, PS_LIST_TAIL, "-size", 0, "Kernel half-size (pixels)", 0);
    216     psMetadataAddS32(arguments, PS_LIST_TAIL, "-order", 0, "Spatial polynomial order", -1);
    217     psMetadataAddStr(arguments, PS_LIST_TAIL, "-type", 0,
    218                      "Kernel type (ISIS|POIS|SPAM|FRIES|GUNK|RINGS)", NULL);
    219     psMetadataAddF32(arguments, PS_LIST_TAIL, "-penalty", 0, "Penalty for wideness", NAN);
    220     psMetadataAddStr(arguments, PS_LIST_TAIL, "-isis-widths", 0,
    221                      "ISIS Gaussian FWHMs (comma-separated)", NULL);
    222     psMetadataAddStr(arguments, PS_LIST_TAIL, "-isis-orders", 0,
    223                      "ISIS polynomial orders (comma-separated)", NULL);
    224     psMetadataAddS32(arguments, PS_LIST_TAIL, "-rings-order", 0, "RINGS polynomial order", -1);
    225     psMetadataAddS32(arguments, PS_LIST_TAIL, "-inner", 0, "SPAM and FRIES inner radius", -1);
    226     psMetadataAddS32(arguments, PS_LIST_TAIL, "-spam-binning", 0, "SPAM kernel binning", 0);
    227     psMetadataAddF32(arguments, PS_LIST_TAIL, "-spacing", 0, "Typical stamp spacing (pixels)", NAN);
    228     psMetadataAddS32(arguments, PS_LIST_TAIL, "-footprint", 0, "Stamp footprint half-size (pixels)", -1);
    229     psMetadataAddF32(arguments, PS_LIST_TAIL, "-source-radius", 0, "Source matching radius (pixels)", NAN);
    230     psMetadataAddS32(arguments, PS_LIST_TAIL, "-stride", 0, "Size of convolution patches (pixels)", -1);
    231     psMetadataAddF32(arguments, PS_LIST_TAIL, "-threshold", 0, "Minimum threshold for stamps (ADU)", NAN);
    232     psMetadataAddS32(arguments, PS_LIST_TAIL, "-iter", 0, "Number of rejection iterations", -1);
    233     psMetadataAddF32(arguments, PS_LIST_TAIL, "-rej", 0, "Rejection thresold (sigma)", NAN);
    234     psMetadataAddF32(arguments, PS_LIST_TAIL, "-sys", 0, "Relative systematic error in kernel", NAN);
    235     psMetadataAddImageMask(arguments,  PS_LIST_TAIL, "-mask-bad", 0, "Mask value for bad pixels", 0);
    236     psMetadataAddImageMask(arguments,  PS_LIST_TAIL, "-mask-poor", 0, "Mask value for poor pixels", 0);
    237     psMetadataAddF32(arguments,  PS_LIST_TAIL, "-poor-frac", 0, "Fraction of variance for poor pixels", NAN);
    238     psMetadataAddF32(arguments, PS_LIST_TAIL, "-badfrac", 0, "Maximum fraction of bad pixels to accept", 1.0);
    239     psMetadataAddBool(arguments,  PS_LIST_TAIL, "-reverse", 0, "Reverse sense of subtraction?", false);
    240     psMetadataAddBool(arguments,  PS_LIST_TAIL, "-generate-mask", 0, "Generate mask if not supplied?", false);
    241     psMetadataAddStr(arguments,  PS_LIST_TAIL, "-stamps", 0,
    242                      "Stamps filename; file has x,y on each line", NULL);
    243     psMetadataAddBool(arguments, PS_LIST_TAIL, "-opt", 0,
    244                       "Derive optimum parameters for ISIS kernels?", false);
    245     psMetadataAddF32(arguments, PS_LIST_TAIL, "-opt-min", 0, "Minimum value for optimum kernel search", NAN);
    246     psMetadataAddF32(arguments, PS_LIST_TAIL, "-opt-max", 0, "Minimum value for optimum kernel search", NAN);
    247     psMetadataAddF32(arguments, PS_LIST_TAIL, "-opt-step", 0, "Step value for optimum kernel search", NAN);
    248     psMetadataAddF32(arguments, PS_LIST_TAIL, "-opt-tol", 0, "Tolerance for optimum kernel search", NAN);
    249     psMetadataAddS32(arguments, PS_LIST_TAIL, "-opt-order", 0, "Maximum order for optimum kernel search", -1);
    250     psMetadataAddBool(arguments, PS_LIST_TAIL, "-dual", 0, "Dual convolution", false);
    251     psMetadataAddBool(arguments, PS_LIST_TAIL, "-photometry", 0, "Perform photometry?", false);
     74    psMetadataAddStr(arguments,  PS_LIST_TAIL, "-stamps", 0, "Stamps filename; x,y on each line", NULL);
    25275    psMetadataAddS32(arguments, PS_LIST_TAIL, "-threads", 0, "Number of threads", 0);
    253     psMetadataAddS32(arguments, PS_LIST_TAIL, "-bin1", 0, "Binning factor for first level", 0);
    254     psMetadataAddS32(arguments, PS_LIST_TAIL, "-bin2", 0, "Binning factor for second level", 0);
    25576    psMetadataAddStr(arguments, PS_LIST_TAIL, "-dumpconfig", 0, "file to dump configuration to", NULL);
     77    psMetadataAddBool(arguments, PS_LIST_TAIL, "-photometry", 0, "Perform photometry?", NULL);
     78    psMetadataAddBool(arguments, PS_LIST_TAIL, "-inverse", 0, "Generate inverse subtractions?", NULL);
    25679    psMetadataAddBool(arguments, PS_LIST_TAIL, "-visual", 0, "Show diagnostic plots", NULL);
    25780
     
    302125    }
    303126
    304     if (psMetadataLookupBool(NULL, arguments, "-photometry")) {
    305         psMetadataAddBool(recipe, PS_LIST_TAIL, "PHOTOMETRY", PS_META_REPLACE, "Perform photometry?", true);
    306     }
     127    data->stamps = psMemIncrRefCounter(psMetadataLookupStr(NULL, arguments, "-stamps"));
    307128
    308     return true;
    309 }
    310 
    311 bool ppSubArgumentsParse(pmConfig *config)
    312 {
    313     assert(config);
    314 
    315     psMetadata *arguments = config->arguments; // Command-line arguments
    316 
    317     valueArgStr(arguments, "-stats",  "STATS",  arguments);
    318     valueArgStr(arguments, "-stamps", "STAMPS", arguments);
    319 
    320     psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPSUB_RECIPE); // Recipe for ppSim
    321     if (!recipe) {
    322         psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find recipe %s", PPSUB_RECIPE);
    323         goto ERROR;
    324     }
    325 
    326     VALUE_ARG_RECIPE_FLOAT("-region",        "REGION.SIZE",     F32);
    327     VALUE_ARG_RECIPE_INT("-size",            "KERNEL.SIZE",     S32, 0);
    328     VALUE_ARG_RECIPE_INT("-order",           "SPATIAL.ORDER",   S32, -1);
    329     VALUE_ARG_RECIPE_FLOAT("-spacing",       "STAMP.SPACING",   F32);
    330     VALUE_ARG_RECIPE_INT("-rings-order",     "RINGS.ORDER",     S32, -1);
    331     VALUE_ARG_RECIPE_INT("-inner",           "INNER",           S32, -1);
    332     VALUE_ARG_RECIPE_INT("-spam-binning",    "SPAM.BINNING",    S32, 0);
    333     VALUE_ARG_RECIPE_INT("-footprint",       "STAMP.FOOTPRINT", S32, -1);
    334     VALUE_ARG_RECIPE_FLOAT("-source-radius", "SOURCE.RADIUS",   F32);
    335     VALUE_ARG_RECIPE_INT("-stride",          "STRIDE",          S32, -1);
    336     VALUE_ARG_RECIPE_FLOAT("-threshold",     "STAMP.THRESHOLD", F32);
    337     VALUE_ARG_RECIPE_INT("-iter",            "ITER",            S32, -1);
    338     VALUE_ARG_RECIPE_FLOAT("-rej",           "REJ",             F32);
    339     VALUE_ARG_RECIPE_FLOAT("-sys",           "SYS",             F32);
    340     VALUE_ARG_RECIPE_FLOAT("-badfrac",       "BADFRAC",         F32);
    341     VALUE_ARG_RECIPE_FLOAT("-penalty",       "PENALTY",         F32);
    342     VALUE_ARG_RECIPE_FLOAT("-poor-frac",     "POOR.FRACTION",   F32);
    343     VALUE_ARG_RECIPE_INT("-bin1",            "BIN1",            S32, 0);
    344     VALUE_ARG_RECIPE_INT("-bin2",            "BIN2",            S32, 0);
    345 
    346     valueArgRecipeStr(arguments, recipe, "-mask-in",   "MASK.IN",  recipe);
    347     valueArgRecipeStr(arguments, recipe, "-mask-bad",  "MASK.BAD",  recipe);
    348     valueArgRecipeStr(arguments, recipe, "-mask-poor", "MASK.POOR", recipe);
    349 
    350     vectorArgRecipe(arguments, "-isis-widths", recipe, "ISIS.WIDTHS", recipe, PS_TYPE_F32);
    351     vectorArgRecipe(arguments, "-isis-orders", recipe, "ISIS.ORDERS", recipe, PS_TYPE_S32);
    352 
    353     psVector *widths = psMetadataLookupPtr(NULL, recipe, "ISIS.WIDTHS"); // ISIS Gaussian widths
    354     psVector *orders = psMetadataLookupPtr(NULL, recipe, "ISIS.ORDERS"); // ISIS Polynomial orders
    355     if (widths->n != orders->n) {
    356         psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Size of vectors for ISIS widths and orders do not match.");
    357         goto ERROR;
    358     }
    359 
    360     if (psMetadataLookupBool(NULL, arguments, "-opt") || psMetadataLookupBool(NULL, recipe, "OPTIMUM")) {
    361         psMetadataAddBool(recipe, PS_LIST_TAIL, "OPTIMUM", PS_META_REPLACE,
    362                           "Derive optimum parameters for ISIS kernels?", true);
    363         VALUE_ARG_RECIPE_FLOAT("-opt-min", "OPTIMUM.MIN",   F32);
    364         VALUE_ARG_RECIPE_FLOAT("-opt-max", "OPTIMUM.MAX",   F32);
    365         VALUE_ARG_RECIPE_FLOAT("-opt-step","OPTIMUM.STEP",  F32);
    366         VALUE_ARG_RECIPE_FLOAT("-opt-tol", "OPTIMUM.TOL",   F32);
    367         VALUE_ARG_RECIPE_INT("-opt-order", "OPTIMUM.ORDER", S32, -1);
    368     }
    369 
    370     psMetadataAddBool(arguments, PS_LIST_TAIL, "REVERSE", 0, "Reverse sense of subtraction",
    371                       psMetadataLookupBool(NULL, arguments, "-reverse"));
    372     psMetadataAddBool(recipe, PS_LIST_TAIL, "MASK.GENERATE", PS_META_REPLACE, "Generate mask if not supplied",
    373                       psMetadataLookupBool(NULL, arguments, "-generate-mask"));
    374     psMetadataAddBool(recipe, PS_LIST_TAIL, "DUAL", PS_META_REPLACE, "Dual convolution?",
    375                       psMetadataLookupBool(NULL, arguments, "-dual"));
    376 
    377     // Need to update this because it could have been overwritten by the camera's own recipe
    378     if (psMetadataLookupBool(NULL, arguments, "-photometry")) {
    379         psMetadataAddBool(recipe, PS_LIST_TAIL, "PHOTOMETRY", PS_META_REPLACE, "Perform photometry?", true);
     129    const char *statsName = psMetadataLookupStr(NULL, arguments, "-stats"); // Filename for statistics
     130    if (statsName && strlen(statsName) > 0) {
     131        psString resolved = pmConfigConvertFilename(statsName, config, true, true); // Resolved filename
     132        data->statsFile = fopen(resolved, "w");
     133        if (!data->statsFile) {
     134            psError(PS_ERR_IO, true, "Unable to open statistics file %s for writing.\n", resolved);
     135            psFree(resolved);
     136            return false;
     137        }
     138        psFree(resolved);
    380139    }
    381140
     
    384143    }
    385144
    386     // Translate the kernel type
    387     psString type = psMetadataLookupStr(NULL, arguments, "-type"); // Name of kernel type
    388     if (!type || strlen(type) == 0) {
    389         type = psMetadataLookupStr(NULL, recipe, "KERNEL.TYPE");
    390         if (!type || strlen(type) == 0) {
    391             psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Unable to find KERNEL.TYPE specified.");
    392             goto ERROR;
    393         }
    394     }
    395     psMetadataAddStr(recipe, PS_LIST_TAIL, "KERNEL.TYPE", PS_META_REPLACE, "Type of kernel", type);
    396 
    397     psTrace("ppSub", 1, "Done reading command-line arguments\n");
    398 
    399     // XXX move this to ppSubArguments
    400     int threads = psMetadataLookupS32(NULL, config->arguments, "-threads"); // Number of threads
     145    int threads = psMetadataLookupS32(NULL, arguments, "-threads"); // Number of threads
    401146    if (threads > 0) {
    402147        if (!psThreadPoolInit(threads)) {
     
    406151    }
    407152
     153    psTrace("ppSub", 1, "Done reading command-line arguments\n");
     154
    408155    return true;
    409 
    410 ERROR:
    411     return false;
    412156}
  • trunk/ppSub/src/ppSubBackground.c

    r23287 r23740  
    2222#include "ppSub.h"
    2323
    24 bool ppSubBackground(pmConfig *config, const pmFPAview *view)
     24bool ppSubBackground(pmConfig *config)
    2525{
    2626    psAssert(config, "Require configuration");
    27     psAssert(view, "Require view");
    2827
    2928    bool mdok; // Status of metadata lookups
     
    3635    psImageMaskType maskBad = pmConfigMaskGet("BLANK", config); // Bits to mask
    3736
     37    pmFPAview *view = ppSubViewReadout(); // View to readout
    3838    pmReadout *outRO = pmFPAfileThisReadout(config->files, view, "PPSUB.OUTPUT"); // Output image
    3939    pmReadout *modelRO = pmFPAfileThisReadout(config->files, view, "PSPHOT.BACKMDL"); // Background model
     
    4444        if (!psphotModelBackground(config, view, "PPSUB.OUTPUT")) {
    4545            psError(PS_ERR_UNKNOWN, false, "Unable to model background");
     46            psFree(view);
    4647            return false;
    4748        }
     
    5051        if (!modelRO) {
    5152            psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find background model");
     53            psFree(view);
    5254            return false;
    5355        }
    5456    }
     57    psFree(view);
     58
    5559    psImageBinning *binning = psMetadataLookupPtr(&mdok, modelRO->analysis,
    5660                                                  "PSPHOT.BACKGROUND.BINNING"); // Binning for model
  • trunk/ppSub/src/ppSubCamera.c

    r23688 r23740  
    134134
    135135
    136 bool ppSubCamera(pmConfig *config)
     136bool ppSubCamera(pmConfig *config, ppSubData *data)
    137137{
    138138    psAssert(config, "Require configuration");
     
    147147    pmFPAfile *inVar = defineInputFile(config, input, "PPSUB.INPUT.VARIANCE", "INPUT.VARIANCE",
    148148                                       PM_FPA_FILE_VARIANCE);
    149     defineInputFile(config, input, "PPSUB.INPUT.SOURCES", "INPUT.SOURCES", PM_FPA_FILE_CMF);
     149    defineInputFile(config, NULL, "PPSUB.INPUT.SOURCES", "INPUT.SOURCES", PM_FPA_FILE_CMF);
    150150
    151151    // Reference image
     
    158158    pmFPAfile *refVar = defineInputFile(config, ref, "PPSUB.REF.VARIANCE", "REF.VARIANCE",
    159159                                        PM_FPA_FILE_VARIANCE);
    160     defineInputFile(config, ref, "PPSUB.REF.SOURCES", "REF.SOURCES", PM_FPA_FILE_CMF);
    161 
    162 
    163     // Output image
    164     pmFPAfile *output = defineOutputFile(config, input, true, "PPSUB.OUTPUT", PM_FPA_FILE_IMAGE);
    165     pmFPAfile *outMask = defineOutputFile(config, output, false, "PPSUB.OUTPUT.MASK", PM_FPA_FILE_MASK);
    166     if (!output || !outMask) {
    167         psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
    168         return false;
    169     }
    170     output->save = true;
    171     outMask->save = true;
    172     pmFPAfile *outVar = NULL;
    173     if (inVar && refVar) {
    174         outVar = defineOutputFile(config, output, false, "PPSUB.OUTPUT.VARIANCE", PM_FPA_FILE_VARIANCE);
    175         if (!outVar) {
    176             psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
    177             return false;
    178         }
    179         outVar->save = true;
    180     }
     160    defineInputFile(config, NULL, "PPSUB.REF.SOURCES", "REF.SOURCES", PM_FPA_FILE_CMF);
    181161
    182162
     
    216196
    217197
     198    // Now that the camera has been determined, we can read the recipe
     199    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPSUB_RECIPE); // Recipe for ppSim
     200    if (!recipe) {
     201        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find recipe %s", PPSUB_RECIPE);
     202        return false;
     203    }
     204    if (psMetadataLookupBool(NULL, config->arguments, "-photometry")) {
     205        psMetadataAddBool(recipe, PS_LIST_TAIL, "PHOTOMETRY", PS_META_REPLACE,
     206                          "Perform photometry?", true);
     207    }
     208    if (psMetadataLookupBool(NULL, config->arguments, "-inverse")) {
     209        psMetadataAddBool(recipe, PS_LIST_TAIL, "INVERSE", PS_META_REPLACE,
     210                          "Generate inverse subtractions?", true);
     211    }
     212
     213    data->inverse = psMetadataLookupBool(NULL, recipe, "INVERSE");
     214    data->photometry = psMetadataLookupBool(NULL, recipe, "PHOTOMETRY");
     215
     216
     217    // Output image
     218    pmFPAfile *output = defineOutputFile(config, inConvImage, true, "PPSUB.OUTPUT", PM_FPA_FILE_IMAGE);
     219    pmFPAfile *outMask = defineOutputFile(config, output, false, "PPSUB.OUTPUT.MASK", PM_FPA_FILE_MASK);
     220    if (!output || !outMask) {
     221        psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
     222        return false;
     223    }
     224    output->save = true;
     225    outMask->save = true;
     226    if (inVar && refVar) {
     227        pmFPAfile *outVar = defineOutputFile(config, output, false, "PPSUB.OUTPUT.VARIANCE",
     228                                             PM_FPA_FILE_VARIANCE);
     229        if (!outVar) {
     230            psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
     231            return false;
     232        }
     233        outVar->save = true;
     234    }
     235
     236    pmFPAfile *inverse = NULL;          // Inverse output image
     237    if (data->inverse) {
     238        // Inverse output image
     239        inverse = defineOutputFile(config, output, true, "PPSUB.INVERSE", PM_FPA_FILE_IMAGE);
     240        pmFPAfile *invMask = defineOutputFile(config, inverse, false, "PPSUB.INVERSE.MASK",
     241                                              PM_FPA_FILE_MASK);
     242        if (!inverse || !invMask) {
     243            psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
     244            return false;
     245        }
     246        inverse->save = true;
     247        invMask->save = true;
     248        if (inVar && refVar) {
     249            pmFPAfile *invVar = defineOutputFile(config, inverse, false, "PPSUB.INVERSE.VARIANCE",
     250                                                 PM_FPA_FILE_VARIANCE);
     251            if (!invVar) {
     252                psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
     253                return false;
     254            }
     255            invVar->save = true;
     256        }
     257    }
     258
     259
    218260    // Output JPEGs
    219261    pmFPAfile *jpeg1 = pmFPAfileDefineOutput(config, NULL, "PPSUB.OUTPUT.JPEG1");
     
    245287    }
    246288
    247     psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPSUB_RECIPE); // Recipe for ppSim
    248     if (!recipe) {
    249         psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find recipe %s", PPSUB_RECIPE);
    250         return false;
    251     }
    252 
    253289    // psPhot input
    254     if (psMetadataLookupBool(NULL, recipe, "PHOTOMETRY")) {
     290    if (data->photometry) {
    255291        psphotModelClassInit();        // load implementation-specific models
    256 
    257         // Internal-ish file for getting the PSF from the minuend
    258         pmFPAfile *psf = pmFPAfileDefineOutputFromFile(config, output, "PSPHOT.PSF.LOAD");
    259         if (!psf) {
    260             psError(PS_ERR_IO, false, "Failed to build FPA from PSPHOT.PSF.LOAD");
    261             return false;
    262         }
    263         if (psf->type != PM_FPA_FILE_PSF) {
    264             psError(PS_ERR_IO, true, "PSPHOT.PSF.LOAD is not of type PSF");
    265             return false;
    266         }
    267         pmFPAfileActivate(config->files, false, "PSPHOT.PSF.LOAD");
    268292
    269293        pmFPAfile *psphot = pmFPAfileDefineFromFPA(config, output->fpa, 1, 1, "PSPHOT.INPUT");
     
    276300            return false;
    277301        }
     302        pmFPAfileActivate(config->files, false, "PSPHOT.INPUT");
     303
     304        // Internal-ish file for getting the PSF from the minuend
     305        pmFPAfile *psf = pmFPAfileDefineOutputFromFile(config, psphot, "PSPHOT.PSF.LOAD");
     306        if (!psf) {
     307            psError(PS_ERR_IO, false, "Failed to build FPA from PSPHOT.PSF.LOAD");
     308            return false;
     309        }
     310        if (psf->type != PM_FPA_FILE_PSF) {
     311            psError(PS_ERR_IO, true, "PSPHOT.PSF.LOAD is not of type PSF");
     312            return false;
     313        }
     314        pmFPAfileActivate(config->files, false, "PSPHOT.PSF.LOAD");
    278315
    279316        if (!psphotDefineFiles(config, psphot)) {
     
    281318            return false;
    282319        }
     320
     321        // Deactivate psphot output sources --- we want to define output source files of our own
     322        pmFPAfile *psphotOutput = pmFPAfileSelectSingle(config->files, "PSPHOT.OUTPUT", 0);
     323        psphotOutput->save = false;
     324
     325        pmFPAfile *outSources = defineOutputFile(config, output, false, "PPSUB.OUTPUT.SOURCES",
     326                                                 PM_FPA_FILE_CMF);
     327        if (!outSources) {
     328            psError(PS_ERR_UNKNOWN, false, "Unable to set up output source file.");
     329            return false;
     330        }
     331        outSources->save = true;
     332
     333        if (data->inverse) {
     334            pmFPAfile *invSources = defineOutputFile(config, inverse, false, "PPSUB.INVERSE.SOURCES",
     335                                                     PM_FPA_FILE_CMF);
     336            if (!invSources) {
     337                psError(PS_ERR_UNKNOWN, false, "Unable to set up inverse source file.");
     338                return false;
     339            }
     340            invSources->save = true;
     341        }
    283342    }
    284343
  • trunk/ppSub/src/ppSubData.c

    r23688 r23740  
    1111
    1212
    13 // Image files to activate/deactivate
    14 static const char *imageFiles[] = { "PPSUB.OUTPUT", "PPSUB.OUTPUT.MASK", "PPSUB.OUTPUT.VARIANCE",
    15                                     "PPSUB.OUTPUT.KERNELS", "PPSUB.OUTPUT.JPEG1", "PPSUB.OUTPUT.JPEG2",
    16                                     "PPSUB.INPUT.CONV", "PPSUB.INPUT.CONV.MASK", "PPSUB.INPUT.CONV.VARIANCE",
    17                                     "PPSUB.REF.CONV", "PPSUB.REF.CONV.MASK", "PPSUB.REF.CONV.VARIANCE",
    18                                     NULL };
    19 
    20 
    21 
    22 static void subOptionsFree(ppSubData *options)
     13static void subDataFree(ppSubData *data)
    2314{
    24     psFree(options->stats);
     15    if (data->statsFile) {
     16        psString stats = psMetadataConfigFormat(data->stats); // Statistics to output
     17        if (!stats || strlen(stats) == 0) {
     18            psWarning("Unable to generate statistics file.");
     19        } else {
     20            fprintf(data->statsFile, "%s", stats);
     21        }
     22        psFree(stats);
     23        fclose(data->statsFile);
     24    }
     25    psFree(data->stamps);
     26    psFree(data->psf);
     27    psFree(data->stats);
    2528    return;
    2629}
     
    2831ppSubData *ppSubDataAlloc(void)
    2932{
    30     ppSubData *options = psAlloc(sizeof(ppSubData)); // Processing data, to return
    31     psMemSetDeallocator(options, (psFreeFunc)subOptionsFree);
     33    ppSubData *data = psAlloc(sizeof(ppSubData)); // Processing data, to return
     34    psMemSetDeallocator(data, (psFreeFunc)subDataFree);
    3235
    33     options->quality = 0;
    34     options->stats = psMetadataAlloc();
    35     psMetadataAddS32(options->stats, PS_LIST_TAIL, "QUALITY", 0, "Data quality", 0);
     36    data->quality = 0;
     37    data->photometry = false;
     38    data->inverse = false;
     39    data->stamps = NULL;
     40    data->psf = NULL;
     41    data->statsFile = NULL;
     42    data->stats = psMetadataAlloc();
     43    psMetadataAddS32(data->stats, PS_LIST_TAIL, "QUALITY", 0, "Data quality", 0);
    3644
    37     return options;
     45    return data;
    3846}
    3947
     
    4957    }
    5058
    51     if (files & PPSUB_FILES_IMAGE) {
    52         for (int i = 0; imageFiles[i]; i++) {
    53             pmFPAfileActivate(config->files, imageFiles[i], false);
    54         }
    55     }
    56     if (files & PPSUB_FILES_PHOT) {
    57         psphotFilesActivate(config, false);
    58     }
     59    ppSubFilesActivate(config, files, false);
    5960
    6061    psErrorClear();
  • trunk/ppSub/src/ppSubDefineOutput.c

    r23403 r23740  
    2121#include "ppSub.h"
    2222
    23 bool ppSubDefineOutput(pmConfig *config, const pmFPAview *view)
     23bool ppSubDefineOutput(const char *name, pmConfig *config)
    2424{
     25    psAssert(name, "Require name");
    2526    psAssert(config, "Require configuration");
    26     psAssert(view, "Require view");
    2727
    28     pmCell *outCell = pmFPAfileThisCell(config->files, view, "PPSUB.OUTPUT"); // Output cell
     28    pmFPAview *view = ppSubViewReadout(); // View to readout
     29    pmCell *outCell = pmFPAfileThisCell(config->files, view, name); // Output cell
    2930    pmFPA *outFPA = outCell->parent->parent; // Output FPA
    30     pmHDU *outHDU = outFPA->hdu; // Output HDU
     31    pmHDU *outHDU = outFPA->hdu;        // Output HDU
    3132    if (!outHDU->header) {
    3233        outHDU->header = psMetadataAlloc();
    3334    }
    3435
    35     // generate an output readout (first check if it's already there by virtue of kernels)
    36     pmReadout *outRO = pmFPAfileThisReadout(config->files, view, "PPSUB.OUTPUT.KERNELS"); // RO with kernel
    37     if (!outRO) {
    38         outRO = pmReadoutAlloc(outCell); // Output readout: subtraction
     36    // The output readout may already be present if we read in the convolution kernel
     37    pmReadout *outRO = NULL;            // Output readout
     38    if (outCell->readouts && outCell->readouts->n > 0 && outCell->readouts->data[0]) {
     39        outRO = psMemIncrRefCounter(outCell->readouts->data[0]);
     40    } else {
     41        outRO = pmReadoutAlloc(outCell);
    3942    }
    4043
    41     // convolved input images
     44    // Convolved input images
    4245    pmReadout *inConv = pmFPAfileThisReadout(config->files, view, "PPSUB.INPUT.CONV"); // Input readout
    4346    pmReadout *refConv = pmFPAfileThisReadout(config->files, view, "PPSUB.REF.CONV"); // Reference readout
     47    psFree(view);
    4448
    4549    // Add kernel descrption to header.
     
    5559    if (!kernels) {
    5660        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find SUBTRACTION.KERNEL");
    57         psFree(inConv);
    58         psFree(refConv);
    5961        psFree(outRO);
    6062        return false;
     
    6365                     kernels->description);
    6466
     67    // Add additional data to the header
     68    pmFPAfile *refFile = psMetadataLookupPtr(NULL, config->files, "PPSUB.REF"); // Reference file
     69    pmFPAfile *inFile = psMetadataLookupPtr(NULL, config->files, "PPSUB.INPUT"); // Input file
     70    psMetadataAddStr(outHDU->header, PS_LIST_TAIL, "PPSUB.REFERENCE", 0,
     71                     "Subtraction reference", refFile->filename);
     72    psMetadataAddStr(outHDU->header, PS_LIST_TAIL, "PPSUB.INPUT", 0,
     73                     "Subtraction input", inFile->filename);
     74    ppSubVersionHeader(outHDU->header);
     75
     76
    6577    outRO->analysis = psMetadataCopy(outRO->analysis, analysis);
    6678
    67 #ifdef TESTING
    68     {
    69         psImage *kernelImage = psMetadataLookupPtr(&mdok, analysis,
    70                                                    "SUBTRACTION.KERNEL.IMAGE"); // Image of kernel
    71         psFits *fits = psFitsOpen("kernel.fits", "w");
    72         psFitsWriteImage(fits, NULL, kernelImage, 0, NULL);
    73         psFitsClose(fits);
    74     }
    75 #endif
     79    psFree(outRO);
    7680
    7781    return true;
  • trunk/ppSub/src/ppSubLoop.c

    r23688 r23740  
    1717#include <pslib.h>
    1818#include <psmodules.h>
    19 #include <ppStats.h>
    2019
    2120#include "ppSub.h"
    2221
    23 bool ppSubLoop(pmConfig *config)
     22bool ppSubLoop(pmConfig *config, ppSubData *data)
    2423{
    2524    psAssert(config, "Require configuration.");
     
    2827    pmConfigRecipesCull(config, "PPSUB,PPSTATS,PSPHOT,MASKS,JPEG");
    2928
    30     ppSubData *data = ppSubDataAlloc(); // Processing data
    3129
    32     bool mdok;                          // Status of MD lookup
    33     const char *statsName = psMetadataLookupStr(&mdok, config->arguments, "STATS"); // Filename for statistics
    34     FILE *statsFile = NULL;             // File stream for statistics
    35     if (statsName && strlen(statsName) > 0) {
    36         psString resolved = pmConfigConvertFilename(statsName, config, true, true); // Resolved filename
    37         statsFile = fopen(resolved, "w");
    38         if (!statsFile) {
    39             psError(PS_ERR_IO, true, "Unable to open statistics file %s for writing.\n", resolved);
    40             psFree(resolved);
    41             goto ERROR;
    42         }
    43         psFree(resolved);
     30    pmFPAfile *input = psMetadataLookupPtr(NULL, config->files, "PPSUB.INPUT");
     31    pmFPAfile *reference = psMetadataLookupPtr(NULL, config->files, "PPSUB.REF");
     32    pmFPAfile *output = psMetadataLookupPtr(NULL, config->files, "PPSUB.OUTPUT");
     33    psAssert(input && reference && output, "Require files");
     34
     35    if (!ppSubFilesIterateDown(config, PPSUB_FILES_INPUT | PPSUB_FILES_CONV)) {
     36        psError(PPSUB_ERR_IO, false, "Unable to load files.");
     37        return false;
    4438    }
    4539
    46     pmFPAfile *input = psMetadataLookupPtr(NULL, config->files, "PPSUB.INPUT");
    47     if (!input) {
    48         psError(PS_ERR_UNEXPECTED_NULL, false, "Can't find input data!\n");
    49         goto ERROR;
     40    psTimerStart("PPSUB_MATCH");
     41
     42    if (!ppSubSetMasks(config)) {
     43        psError(PS_ERR_UNKNOWN, false, "Unable to set masks.");
     44        return false;
    5045    }
    5146
    52     pmFPAfile *reference = psMetadataLookupPtr(NULL, config->files, "PPSUB.REF");
    53     if (!reference) {
    54         psError(PS_ERR_UNEXPECTED_NULL, false, "Can't find reference data!\n");
    55         goto ERROR;
     47    if (!ppSubMatchPSFs(config, data)) {
     48        psError(PS_ERR_UNKNOWN, false, "Unable to match PSFs.");
     49        return false;
     50    }
     51    if (data->quality) {
     52        // Can't do anything at all
     53        return true;
    5654    }
    5755
    58     pmFPAfile *output = psMetadataLookupPtr(NULL, config->files, "PPSUB.OUTPUT");
    59     if (!output) {
    60         psError(PS_ERR_UNEXPECTED_NULL, false, "Can't find output data!\n");
    61         goto ERROR;
     56    psMetadataAddF32(data->stats, PS_LIST_TAIL, "TIME_MATCH", 0, "Time to match PSFs",
     57                     psTimerClear("PPSUB_MATCH"));
     58
     59    // Close input files
     60    if (!ppSubFilesIterateUp(config, PPSUB_FILES_INPUT)) {
     61        psError(PPSUB_ERR_IO, false, "Unable to close input files.");
     62        return false;
    6263    }
    6364
    64     pmFPAview *view = pmFPAviewAlloc(0); // Pointer into FPA hierarchy
    65 
    66     // Iterate over the FPA hierarchy
    67     if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
    68         goto ERROR;
     65    // Set up subtraction files
     66    if (!ppSubFilesIterateDown(config, PPSUB_FILES_SUB)) {
     67        psError(PPSUB_ERR_IO, false, "Unable to set up subtraction files.");
     68        return false;
    6969    }
    7070
    71     pmChip *inChip;                    // Input chip of interest
    72     while ((inChip = pmFPAviewNextChip(view, input->fpa, 1)) != NULL) {
    73         pmChip *refChip = pmFPAviewThisChip(view, reference->fpa); // Reference chip of interest
    74         if ((!inChip->file_exists && refChip->file_exists) ||
    75             (inChip->file_exists && !refChip->file_exists)) {
    76             psError(PS_ERR_BAD_PARAMETER_VALUE, true, "FPA format discrepency between input and reference");
    77             psFree(view);
    78             goto ERROR;
     71    if (!ppSubDefineOutput("PPSUB.OUTPUT", config)) {
     72        psError(PS_ERR_UNKNOWN, false, "Unable to define output.");
     73        return false;
     74    }
     75
     76    if (!data->quality && !ppSubMakePSF(config, data)) {
     77        psError(PS_ERR_UNKNOWN, false, "Unable to generate PSF.");
     78        return false;
     79    }
     80
     81    if (!ppSubReadoutSubtract(config)) {
     82        psError(PS_ERR_UNKNOWN, false, "Unable to subtract images.");
     83        return false;
     84    }
     85
     86    // Close convolved files
     87    if (!ppSubFilesIterateUp(config, PPSUB_FILES_PSF | PPSUB_FILES_CONV)) {
     88        psError(PPSUB_ERR_IO, false, "Unable to close input files.");
     89        return false;
     90    }
     91
     92    // Higher order background subtraction using psphot
     93    if (!ppSubBackground(config)) {
     94        psError(PS_ERR_UNKNOWN, false, "Unable to subtract background.");
     95        return false;
     96    }
     97
     98    if (!ppSubFilesIterateDown(config, PPSUB_FILES_PHOT_SUB)) {
     99        psError(PPSUB_ERR_IO, false, "Unable to set up photometry files.");
     100        return false;
     101    }
     102
     103    if (!data->quality && !ppSubReadoutPhotometry("PPSUB.OUTPUT", config, data)) {
     104        psError(PS_ERR_UNKNOWN, false, "Unable to perform photometry.");
     105        return false;
     106    }
     107
     108    if (!ppSubFilesIterateUp(config, PPSUB_FILES_PHOT_SUB)) {
     109        psError(PPSUB_ERR_IO, false, "Unable to set up photometry files.");
     110        return false;
     111    }
     112
     113    // Perform statistics on the cell
     114    if (!ppSubReadoutStats(config, data)) {
     115        psError(PS_ERR_UNKNOWN, false, "Unable to collect statistics");
     116        return false;
     117    }
     118
     119    if (!ppSubReadoutJpeg(config)) {
     120        psError(PS_ERR_UNKNOWN, false, "Unable to update.");
     121        return false;
     122    }
     123
     124    if (data->inverse) {
     125        // Set up inverse subtraction files
     126        if (!ppSubFilesIterateDown(config, PPSUB_FILES_INV)) {
     127            psError(PPSUB_ERR_IO, false, "Unable to set up inverse files.");
     128            return false;
    79129        }
    80130
    81         if (!inChip->file_exists) {
    82             continue;
     131        if (data->inverse && !ppSubDefineOutput("PPSUB.INVERSE", config)) {
     132            psError(PS_ERR_UNKNOWN, false, "Unable to define inverse.");
     133            return false;
    83134        }
    84135
    85         if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
    86             goto ERROR;
     136        if (!ppSubReadoutInverse(config)) {
     137            psError(PS_ERR_UNKNOWN, false, "Unable to invert images.");
     138            return false;
    87139        }
    88140
    89         pmCell *inCell;                // Cell of interest
    90         while ((inCell = pmFPAviewNextCell(view, input->fpa, 1)) != NULL) {
    91             pmCell *refCell = pmFPAviewThisCell(view, reference->fpa); // Reference cell of interest
    92             if ((!inCell->file_exists && refCell->file_exists) ||
    93                 (inCell->file_exists && !refCell->file_exists)) {
    94                 psError(PS_ERR_BAD_PARAMETER_VALUE, true,
    95                         "FPA format discrepency between input and reference");
    96                 psFree(view);
    97                 goto ERROR;
    98             }
    99             if (!inCell->file_exists) {
    100                 continue;
    101             }
    102             if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
    103                 goto ERROR;
    104             }
    105 
    106             pmReadout *inRO;           // Readin of interest
    107             while ((inRO = pmFPAviewNextReadout(view, input->fpa, 1))) {
    108                 if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
    109                     goto ERROR;
    110                 }
    111                 pmReadout *refRO = pmFPAviewThisReadout(view, reference->fpa);// Reference readout of interest
    112                 if (!refRO || (!inRO->data_exists && refRO->data_exists) ||
    113                     (inRO->data_exists && !refRO->data_exists)) {
    114                     psError(PS_ERR_BAD_PARAMETER_VALUE, true,
    115                             "FPA format discrepency between input and reference");
    116                     psFree(view);
    117                     goto ERROR;
    118                 }
    119                 if (!inRO->data_exists) {
    120                     continue;
    121                 }
    122 
    123                 // Perform the analysis
    124                 if (!ppSubReadout(config, data, view)) {
    125                     psError(PS_ERR_UNKNOWN, false, "Unable to subtract images.\n");
    126                     goto ERROR;
    127                 }
    128 
    129                 if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
    130                     goto ERROR;
    131                 }
    132             }
    133 
    134             // Perform statistics on the cell
    135             if (statsFile) {
    136                 pmFPAfile *output = psMetadataLookupPtr(NULL, config->files, "PPSUB.OUTPUT"); // Output file
    137                 if (!output) {
    138                     psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find file PPSUB.OUTPUT.\n");
    139                     goto ERROR;
    140                 }
    141                 psImageMaskType maskValue = pmConfigMaskGet("MASK.VALUE", config);
    142                 ppStatsFPA(data->stats, output->fpa, view, maskValue, config);
    143             }
    144 
    145             if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
    146                 goto ERROR;
    147             }
     141        // Close subtraction files and open inverse photometry files
     142        if (!ppSubFilesIterateUp(config, PPSUB_FILES_SUB)) {
     143            psError(PPSUB_ERR_IO, false, "Unable to close subtraction files.");
     144            return false;
    148145        }
    149146
    150         if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
    151             goto ERROR;
     147        if (!ppSubFilesIterateDown(config, PPSUB_FILES_PHOT_INV)) {
     148            psError(PPSUB_ERR_IO, false, "Unable to set up inverse files.");
     149            return false;
     150        }
     151
     152        if (!data->quality && !ppSubReadoutPhotometry("PPSUB.INVERSE", config, data)) {
     153            psError(PS_ERR_UNKNOWN, false, "Unable to perform photometry.");
     154            return false;
     155        }
     156
     157        // Close inverse subtraction files
     158        if (!ppSubFilesIterateUp(config, PPSUB_FILES_INV | PPSUB_FILES_PHOT_INV)) {
     159            psError(PPSUB_ERR_IO, false, "Unable to close subtraction files.");
     160            return false;
     161        }
     162    } else {
     163        // Close subtraction files
     164        if (!ppSubFilesIterateUp(config, PPSUB_FILES_SUB)) {
     165            psError(PPSUB_ERR_IO, false, "Unable to close subtraction files.");
     166            return false;
    152167        }
    153168    }
    154169
    155     if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
    156         goto ERROR;
    157     }
    158 
    159     psFree(view);
    160 
    161     // Write out summary statistics
    162     if (statsFile) {
    163         psMetadataAddF32(data->stats, PS_LIST_TAIL, "TIME_SUB", 0, "Time for subtraction completion",
    164                          psTimerMark("ppSub"));
    165 
    166         const char *statsMDC = psMetadataConfigFormat(data->stats);
    167         if (!statsMDC || strlen(statsMDC) == 0) {
    168             psWarning("Unable to generate statistics MDC file.\n");
    169         } else {
    170             fprintf(statsFile, "%s", statsMDC);
    171         }
    172         psFree((void *)statsMDC);
    173         fclose(statsFile);
    174     }
    175 
    176     psString dump_file = psMetadataLookupStr(&mdok, config->arguments, "-dumpconfig");
     170    psString dump_file = psMetadataLookupStr(NULL, config->arguments, "-dumpconfig");
    177171    if (dump_file) {
    178172        pmFPAfile *input = psMetadataLookupPtr(NULL, config->files, "PPSUB.INPUT"); // Input file
     
    180174    }
    181175
    182     psFree(data);
    183176    return true;
    184 
    185 ERROR:
    186     psFree(data);
    187     return false;
    188177}
  • trunk/ppSub/src/ppSubMakePSF.c

    r23688 r23740  
    2222#include "ppSub.h"
    2323
    24 bool ppSubMakePSF(pmConfig *config, ppSubData *data, const pmFPAview *view)
     24bool ppSubMakePSF(pmConfig *config, ppSubData *data)
    2525{
    2626    psAssert(config, "Require configuration");
    27     psAssert(view, "Require view");
     27
     28    if (!data->photometry) {
     29        return true;
     30    }
    2831
    2932    psTimerStart("PPSUB_PHOT");
     
    4447    pmReadout *minuend = NULL;          // Image that will be positive following subtraction
    4548    pmFPAfile *minuendFile = NULL;      // File for minuend image
     49    pmFPAview *view = ppSubViewReadout(); // View to readout
    4650    if (reverse) {
    4751        minuend = pmFPAfileThisReadout(config->files, view, "PPSUB.REF.CONV");
     
    5357
    5458#if 1
     59    pmFPAfile *photFile = psMetadataLookupPtr(&mdok, config->files, "PSPHOT.INPUT"); // Photometry file
     60#if 0
     61    pmReadout *photRO = pmFPAviewThisReadout(view, photFile->fpa); // Readout to photometer
    5562    pmReadout *template = minuend;
    56     pmFPAfile *photFile = psMetadataLookupPtr(&mdok, config->files, "PSPHOT.INPUT"); // Photometry file
    57     pmReadout *photRO = pmFPAviewThisReadout(view, photFile->fpa); // Readout to photometer
    5863    if (!photRO) {
    5964        pmCell *cell = pmFPAviewThisCell(view, photFile->fpa); // Cell to photometer
     
    7479    }
    7580#else
     81    if (!pmFPACopy(photFile->fpa, minuendFile->fpa)) {
     82        psError(PS_ERR_UNKNOWN, false, "Unable to copy FPA for photometry");
     83        psFree(view);
     84        return false;
     85    }
     86    pmReadout *photRO = pmFPAviewThisReadout(view, photFile->fpa); // Readout to photometer
     87    if (psMetadataLookup(photRO->analysis, "PSPHOT.SOURCES")) {
     88        psMetadataRemoveKey(photRO->analysis, "PSPHOT.SOURCES");
     89    }
     90#endif
     91
     92
     93#else
    7694    // Supply the minuend pmFPAfile to psphot as PSPHOT.INPUT:
    7795    psMetadataAddPtr(config->files, PS_LIST_TAIL, "PSPHOT.INPUT", PS_DATA_UNKNOWN | PS_META_REPLACE,
     
    87105        psErrorStackPrint(stderr, "Unable to determine PSF");
    88106        psWarning("Unable to determine PSF --- suspect bad data quality.");
    89         ppSubDataQuality(config, data, PSPHOT_ERR_PSF, PPSUB_FILES_PHOT);
     107        ppSubDataQuality(config, data, PSPHOT_ERR_PSF, PPSUB_FILES_PHOT_SUB | PPSUB_FILES_PHOT_INV);
     108        psFree(view);
    90109        return true;
    91110    }
     
    93112    // Record the FWHM in the output header
    94113    pmReadout *outRO = pmFPAfileThisReadout(config->files, view, "PPSUB.OUTPUT"); // Output readout
     114    psFree(view);
    95115    pmHDU *hdu = pmHDUFromCell(outRO->parent); // HDU with header
    96116    psMetadataItemSupplement(hdu->header, psphotRecipe, "FWHM_MAJ");
     
    100120    psMetadataRemoveKey(photRO->analysis, "PSPHOT.HEADER");
    101121
     122    data->psf = psMemIncrRefCounter(psMetadataLookupPtr(NULL, photRO->parent->parent->analysis,
     123                                                        "PSPHOT.PSF"));
     124
    102125    return true;
    103126}
  • trunk/ppSub/src/ppSubMatchPSFs.c

    r23688 r23740  
    2222#include "ppSub.h"
    2323
    24 bool ppSubMatchPSFs(pmConfig *config, ppSubData *data, const pmFPAview *view)
     24bool ppSubMatchPSFs(pmConfig *config, ppSubData *data)
    2525{
    2626    psAssert(config, "Require configuration");
    27     psAssert(view, "Require view");
    2827
    2928    // Look up recipe values
    3029    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPSUB_RECIPE); // Recipe for ppSim
    3130    psAssert(recipe, "We checked this earlier, so it should be here.");
     31
     32    pmFPAview *view = ppSubViewReadout(); // View to readout
    3233
    3334    // Input images
     
    5253    pmReadout *kernelRO = pmFPAfileThisReadout(config->files, view, "PPSUB.OUTPUT.KERNELS"); // RO with kernel
    5354
     55    psFree(view);
     56
    5457    // Sources in image, used for stamps: these must be loaded from previous analysis stages
    55     psArray *inSources = psMetadataLookupPtr(&mdok, inRO->analysis, "PSPHOT.SOURCES"); // Input source list
    56     psArray *refSources = psMetadataLookupPtr(&mdok, refRO->analysis, "PSPHOT.SOURCES"); // Ref source list
     58    pmReadout *inSourceRO = pmFPAfileThisReadout(config->files, view, "PPSUB.INPUT.SOURCES");
     59    pmReadout *refSourceRO = pmFPAfileThisReadout(config->files, view, "PPSUB.REF.SOURCES");
     60    psArray *inSources = psMetadataLookupPtr(&mdok, inSourceRO->analysis, "PSPHOT.SOURCES"); // Source list
     61    psArray *refSources = psMetadataLookupPtr(&mdok, refSourceRO->analysis, "PSPHOT.SOURCES"); // Source list
    5762
    5863    psArray *sources = NULL;            // Merged list of sources
  • trunk/ppSub/src/ppSubReadout.c

    r23688 r23740  
    2121#include "ppSub.h"
    2222
    23 bool ppSubReadout(pmConfig *config, ppSubData *data, const pmFPAview *view)
     23bool ppSubReadout(const char *name, bool reverse, pmConfig *config, ppSubData *data, const pmFPAview *view)
    2424{
    25     psTimerStart("PPSUB_MATCH");
     25    psAssert(name, "Require name");
     26    psAssert(config, "Require configuration");
     27    psAssert(data, "Require data");
     28    psAssert(view, "Require view");
    2629
    27     if (!ppSubSetMasks(config, view)) {
    28         psError(PS_ERR_UNKNOWN, false, "Unable to set masks.");
    29         return false;
    30     }
    31 
    32     if (!ppSubMatchPSFs(config, data, view)) {
    33         psError(PS_ERR_UNKNOWN, false, "Unable to match PSFs.");
    34         return false;
    35     } else if (data->quality) {
    36         // Can't do anything at all
    37         return true;
    38     }
    39 
    40     if (!ppSubDefineOutput(config, view)) {
     30    if (!ppSubDefineOutput(name, config, data, view)) {
    4131        psError(PS_ERR_UNKNOWN, false, "Unable to define output.");
    4232        return false;
    4333    }
    4434
    45     if (!data->quality && !ppSubMakePSF(config, data, view)) {
     35    if (!data->quality && !ppSubMakePSF(name, config, data, view)) {
    4636        psError(PS_ERR_UNKNOWN, false, "Unable to generate PSF.");
    4737        return false;
    4838    }
    4939
    50     if (!ppSubReadoutSubtract(config, view)) {
     40    if (!ppSubReadoutSubtract(name, reverse, config, view)) {
    5141        psError(PS_ERR_UNKNOWN, false, "Unable to subtract images.");
    5242        return false;
     
    5444
    5545    // Higher order background subtraction using psphot
    56     if (!ppSubBackground(config, view)) {
     46    if (!ppSubBackground(name, config, view)) {
    5747        psError(PS_ERR_UNKNOWN, false, "Unable to subtract background.");
    5848        return false;
    5949    }
    6050
    61     if (!data->quality && !ppSubReadoutPhotometry(config, data, view)) {
     51    if (!data->quality && data->!ppSubReadoutPhotometry(name, config, data, view)) {
    6252        psError(PS_ERR_UNKNOWN, false, "Unable to perform photometry.");
    6353        return false;
    6454    }
    6555
    66     if (!ppSubReadoutUpdate(config, data, view)) {
     56    if (!ppSubReadoutUpdate(name, config, data, view)) {
    6757        psError(PS_ERR_UNKNOWN, false, "Unable to update.");
    6858        return false;
    6959    }
    7060
     61
     62
     63
    7164    return true;
    7265}
  • trunk/ppSub/src/ppSubReadoutPhotometry.c

    r23688 r23740  
    2222#include "ppSub.h"
    2323
    24 bool ppSubReadoutPhotometry (pmConfig *config, ppSubData *data, const pmFPAview *view)
     24bool ppSubReadoutPhotometry(const char *name, pmConfig *config, ppSubData *data)
    2525{
    2626    psAssert(config, "Require configuration");
    27     psAssert(view, "Require view");
     27
     28    if (!data->photometry) {
     29        return false;
     30    }
    2831
    2932    // Look up recipe values
     
    3942    // The PSF (measured in ppSubMakePSF) is stored on the chip->analysis of PSPHOT.INPUT
    4043    // In order to use an incoming PSF, it must be stored on the chip->analysis of PSPHOT.PSF.LOAD
     44    pmFPAview *view = ppSubViewReadout(); // View to readout
    4145    pmChip *psfInputChip = pmFPAfileThisChip(config->files, view, "PSPHOT.INPUT"); // Chip with PSF
    4246    psAssert (psfInputChip, "should have been generated for ppSubMakePSF");
     
    4751        psErrorStackPrint(stderr, "No PSF available");
    4852        psWarning("No PSF available --- suspect bad data quality.");
    49         ppSubDataQuality(config, data, psErrorCodeLast(), PPSUB_FILES_PHOT);
     53        ppSubDataQuality(config, data, psErrorCodeLast(), PPSUB_FILES_PHOT_SUB | PPSUB_FILES_PHOT_INV);
    5054        return true;
    5155    }
     
    5862    // around the pointers so PSPHOT.INPUT corresponds to the output image; previously, it was
    5963    // equivalent to the minuend image.
    60     pmFPAfile *outputFile = psMetadataLookupPtr(&mdok, config->files, "PPSUB.OUTPUT"); // Output file
    61     pmReadout *outRO = pmFPAviewThisReadout(view, outputFile->fpa); // Readout with the sources
     64    pmReadout *inRO = pmFPAfileThisReadout(config->files, view, name); // Readout with image and sources
    6265
    63     // XXX possibly rename this to PPSUB.RESID?
    6466    pmFPAfile *photFile = psMetadataLookupPtr(&mdok, config->files, "PSPHOT.INPUT"); // Photometry file
    6567    pmReadout *photRO = pmFPAviewThisReadout(view, photFile->fpa); // Readout to photometer
     
    6870        photRO = pmReadoutAlloc(cell); // Output readout: subtraction
    6971    }
    70     photRO->image = psImageCopy(photRO->image, outRO->image, PS_TYPE_F32);
    71     if (outRO->variance) {
    72         photRO->variance = psImageCopy(photRO->variance, outRO->variance, PS_TYPE_F32);
     72    photRO->image = psImageCopy(photRO->image, inRO->image, PS_TYPE_F32);
     73    if (inRO->variance) {
     74        photRO->variance = psImageCopy(photRO->variance, inRO->variance, PS_TYPE_F32);
    7375    } else {
    7476        psFree(photRO->variance);
    7577        photRO->variance = NULL;
    7678    }
    77     if (outRO->mask) {
    78         photRO->mask = psImageCopy(photRO->mask, outRO->mask, PS_TYPE_IMAGE_MASK);
     79    if (inRO->mask) {
     80        photRO->mask = psImageCopy(photRO->mask, inRO->mask, PS_TYPE_IMAGE_MASK);
    7981    } else {
    8082        psFree(photRO->mask);
    8183        photRO->mask = NULL;
    8284    }
     85    psMetadataAddPtr(photRO->parent->parent->analysis, PS_LIST_TAIL, "PSPHOT.PSF",
     86                     PS_META_REPLACE | PS_DATA_UNKNOWN, "Point-spread function", data->psf);
     87
     88    psFree(photRO->analysis);
     89    photRO->analysis = psMetadataAlloc();
    8390
    8491    if (!psphotReadoutMinimal(config, view)) {
     
    8794        psErrorStackPrint(stderr, "Unable to perform photometry on image");
    8895        psWarning("Unable to perform photometry on image --- suspect bad data quality.");
    89         ppSubDataQuality(config, data, psErrorCodeLast(), PPSUB_FILES_PHOT);
     96        ppSubDataQuality(config, data, psErrorCodeLast(), PPSUB_FILES_PHOT_SUB | PPSUB_FILES_PHOT_INV);
    9097    }
    9198
    92     photRO->data_exists = true;
    93     photRO->parent->data_exists = true;
    94     photRO->parent->parent->data_exists = true;
     99    if (!data->quality && !psMetadataCopySingle(inRO->analysis, photRO->analysis, "PSPHOT.SOURCES")) {
     100        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to copy PSPHOT.SOURCES");
     101        return false;
     102    }
    95103
    96104    if (data->stats) {
    97105        psArray *sources = psMetadataLookupPtr(NULL, photRO->analysis, "PSPHOT.SOURCES"); // Sources
    98         psMetadataAddS32(data->stats, PS_LIST_TAIL, "NUM_SOURCES", 0, "Number of sources detected",
    99                          sources ? sources->n : 0);
    100         psMetadataAddF32(data->stats, PS_LIST_TAIL, "TIME_PHOT", 0, "Time to do photometry",
    101                          psTimerClear("PPSUB_PHOT"));
     106        bool mdok;
     107        int numSources = psMetadataLookupS32(&mdok, data->stats, "NUM_SOURCES"); // Number of sources
     108        numSources += sources ? sources->n : 0;
     109        psMetadataAddS32(data->stats, PS_LIST_TAIL, "NUM_SOURCES", PS_META_REPLACE,
     110                         "Total number of sources detected", numSources);
     111        float newTime = psTimerClear("PPSUB_PHOT"); // Time for photometry
     112        float oldTime = psMetadataLookupF32(&mdok, data->stats, "TIME_PHOT"); // Previous time for photometry
     113        psMetadataAddF32(data->stats, PS_LIST_TAIL, "TIME_PHOT", PS_META_REPLACE, "Time to do photometry",
     114                         isfinite(oldTime) ? oldTime + newTime : newTime);
    102115    }
    103116
  • trunk/ppSub/src/ppSubReadoutSubtract.c

    r23642 r23740  
    2323#define WCS_TOLERANCE 0.001             // Tolerance for WCS
    2424
    25 bool ppSubReadoutSubtract(pmConfig *config, const pmFPAview *view)
     25bool ppSubReadoutSubtract(pmConfig *config)
    2626{
    2727    psAssert(config, "Require configuration");
    28     psAssert(view, "Require view");
    29 
    3028
    3129    // Look up recipe values
     
    3533
    3634    bool reverse = psMetadataLookupBool(&mdok, config->arguments, "REVERSE"); // Reverse sense of subtraction?
     35
     36    pmFPAview *view = ppSubViewReadout(); // View to readout
    3737
    3838    // Subtraction is: minuend - subtrahend
     
    9191        psError(PS_ERR_UNKNOWN, false, "Unable to copy concepts from input to output.");
    9292        psFree(outRO);
     93        psFree(view);
    9394        return false;
    9495    }
     
    99100    pmHDU *outHDU = outFPA->hdu;        // Output HDU
    100101    pmChip *outChip = pmFPAfileThisChip(config->files, view, "PPSUB.OUTPUT"); // Output chip
     102    psFree(view);
    101103    if (!outHDU || !inHDU) {
    102104        psError(PS_ERR_UNKNOWN, false, "Unable to find HDU at FPA level to copy astrometry.");
  • trunk/ppSub/src/ppSubReadoutUpdate.c

    r23688 r23740  
    2020
    2121#include "ppSub.h"
    22 
    23 bool ppSubReadoutUpdate(pmConfig *config, ppSubData *data, const pmFPAview *view)
    24 {
    25     psAssert(config, "Require configuration");
    26     psAssert(view, "Require view");
    27 
    28     bool mdok = false;                  // Status of MD lookup
    29 
    30     // Look up recipe values
    31     psMetadata *recipe = psMetadataLookupMetadata(&mdok, config->recipes, PPSUB_RECIPE); // Recipe for ppSim
    32     psAssert(recipe, "We checked this earlier, so it should be here.");
    33 
    34     pmFPAfile *outFile = psMetadataLookupPtr(&mdok, config->files, "PPSUB.OUTPUT"); // Output file
    35     pmReadout *outRO = pmFPAfileThisReadout(config->files, view, "PPSUB.OUTPUT"); // Output image
    36     pmFPA *outFPA = outFile->fpa;       // Output FPA
    37     pmHDU *outHDU = outFPA->hdu;        // Output HDU
    38 
    39     // Add additional data to the header
    40     pmFPAfile *refFile = psMetadataLookupPtr(NULL, config->files, "PPSUB.REF"); // Reference file
    41     pmFPAfile *inFile = psMetadataLookupPtr(NULL, config->files, "PPSUB.INPUT"); // Input file
    42     psMetadataAddStr(outHDU->header, PS_LIST_TAIL, "PPSUB.REFERENCE", 0,
    43                      "Subtraction reference", refFile->filename);
    44     psMetadataAddStr(outHDU->header, PS_LIST_TAIL, "PPSUB.INPUT", 0,
    45                      "Subtraction input", inFile->filename);
    46     ppSubVersionHeader(outHDU->header);
    47 
    48     // Statistics on the matching
    49     if (data->stats) {
    50         psMetadataCopySingle(data->stats, outRO->analysis, PM_SUBTRACTION_ANALYSIS_MODE);
    51         psMetadataCopySingle(data->stats, outRO->analysis, PM_SUBTRACTION_ANALYSIS_STAMPS);
    52         psMetadataCopySingle(data->stats, outRO->analysis, PM_SUBTRACTION_ANALYSIS_DEV_MEAN);
    53         psMetadataCopySingle(data->stats, outRO->analysis, PM_SUBTRACTION_ANALYSIS_DEV_RMS);
    54         psMetadataCopySingle(data->stats, outRO->analysis, PM_SUBTRACTION_ANALYSIS_NORM);
    55         psMetadataCopySingle(data->stats, outRO->analysis, PM_SUBTRACTION_ANALYSIS_BGDIFF);
    56         psMetadataCopySingle(data->stats, outRO->analysis, PM_SUBTRACTION_ANALYSIS_MX);
    57         psMetadataCopySingle(data->stats, outRO->analysis, PM_SUBTRACTION_ANALYSIS_MY);
    58         psMetadataCopySingle(data->stats, outRO->analysis, PM_SUBTRACTION_ANALYSIS_MXX);
    59         psMetadataCopySingle(data->stats, outRO->analysis, PM_SUBTRACTION_ANALYSIS_MXY);
    60         psMetadataCopySingle(data->stats, outRO->analysis, PM_SUBTRACTION_ANALYSIS_MYY);
    61 
    62         psMetadataAddF32(data->stats, PS_LIST_TAIL, "TIME_MATCH", 0, "Time to match PSFs",
    63                          psTimerClear("PPSUB_MATCH"));
    64     }
    65 
    66     // Generate binned JPEGs
    67     {
    68         psImageMaskType maskBad = pmConfigMaskGet("BLANK", config); // Bits to mask for bad pixels
    69 
    70         int bin1 = psMetadataLookupS32(NULL, recipe, "BIN1"); // First binning level
    71         int bin2 = psMetadataLookupS32(NULL, recipe, "BIN2"); // Second binning level
    72 
    73         // Target cells
    74         pmCell *cell1 = pmFPAfileThisCell(config->files, view, "PPSUB.OUTPUT.JPEG1"); // Rebinned cell once
    75         pmCell *cell2 = pmFPAfileThisCell(config->files, view, "PPSUB.OUTPUT.JPEG2"); // Rebinned cell twice
    76 
    77         pmReadout *ro1 = pmReadoutAlloc(cell1), *ro2 = pmReadoutAlloc(cell2); // Binned readouts
    78         if (!pmReadoutRebin(ro1, outRO, maskBad, bin1, bin1)) {
    79             psError(PS_ERR_UNKNOWN, false, "Unable to bin output (1st binning)");
    80             psFree(ro1);
    81             psFree(ro2);
    82             return false;
    83         }
    84         if (!pmReadoutRebin(ro2, ro1, 0, bin2, bin2)) {
    85             psError(PS_ERR_UNKNOWN, false, "Unable to bin output (2nd binning)");
    86             psFree(ro1);
    87             psFree(ro2);
    88             return false;
    89         }
    90         psFree(ro1);
    91         psFree(ro2);
    92     }
    93 
    94 #ifdef TESTING
    95     // Significance image
    96     {
    97         psImage *sig = (psImage*)psBinaryOp(NULL, outRO->image, "*", outRO->image);
    98         psBinaryOp(sig, sig, "/", outRO->variance);
    99         psFits *fits = psFitsOpen("significance.fits", "w");
    100         psFitsWriteImage(fits, NULL, sig, 0, NULL);
    101         psFitsClose(fits);
    102         psFree(sig);
    103     }
    104 #endif
    105 
    106     return true;
    107 }
  • trunk/ppSub/src/ppSubSetMasks.c

    r23535 r23740  
    2222#include "ppSub.h"
    2323
    24 bool ppSubSetMasks(pmConfig *config, const pmFPAview *view)
     24bool ppSubSetMasks(pmConfig *config)
    2525{
    2626    psAssert(config, "Require configuration");
    27     psAssert(view, "Require view");
    2827
    2928    psImageMaskType maskValue, markValue; // Mask values
     
    5049    psAssert(lowValue, "LOW or BAD must be non-zero");
    5150
    52     // input images
     51    // Input images
     52    pmFPAview *view = ppSubViewReadout(); // View to readout
    5353    pmReadout *inRO = pmFPAfileThisReadout(config->files, view, "PPSUB.INPUT"); // Input readout
    5454    pmReadout *refRO = pmFPAfileThisReadout(config->files, view, "PPSUB.REF"); // Reference readout
Note: See TracChangeset for help on using the changeset viewer.