IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

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

updates from trunk

Location:
branches/simtest_nebulous_branches
Files:
23 edited
2 copied

Legend:

Unmodified
Added
Removed
  • branches/simtest_nebulous_branches

  • branches/simtest_nebulous_branches/ppSub/src

    • Property svn:ignore
      •  

        old new  
        1313ppSubErrorCodes.c
        1414ppSubVersionDefinitions.h
         15ppSubConvolve
  • branches/simtest_nebulous_branches/ppSub/src/Makefile.am

    r24862 r27840  
    1 bin_PROGRAMS = ppSub ppSubKernel
     1bin_PROGRAMS = ppSub ppSubKernel ppSubConvolve
    22
    33if HAVE_SVNVERSION
     
    3434        ppSubData.c                     \
    3535        ppSubErrorCodes.c               \
     36        ppSubExit.c                     \
    3637        ppSubFiles.c                    \
    3738        ppSubLoop.c                     \
     
    5354ppSubKernel_SOURCES =           \
    5455        ppSubKernel.c
     56
     57ppSubConvolve_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(PPSTATS_CFLAGS) $(PSPHOT_CFLAGS) $(PPSUB_CFLAGS)
     58ppSubConvolve_LDFLAGS  = $(PSLIB_LIBS)   $(PSMODULE_LIBS)   $(PPSTATS_LIBS)   $(PSPHOT_LIBS)   $(PPSUB_LIBS)
     59
     60ppSubConvolve_SOURCES =         \
     61        ppSubConvolve.c         \
     62        ppSubExit.c             \
     63        ppSubVersion.c
    5564
    5665noinst_HEADERS = \
  • branches/simtest_nebulous_branches/ppSub/src/ppSub.c

    r23753 r27840  
    2424int main(int argc, char *argv[])
    2525{
    26     psExit exitValue = PS_EXIT_SUCCESS; // Exit value
     26    psLibInit(NULL);
    2727    psTimerStart("ppSub");
    28     psLibInit(NULL);
     28
     29    pmErrorRegister();
     30    ppSubErrorRegister();
     31    psphotErrorRegister();
    2932
    3033    ppSubData *data = NULL;             // Processing data
    3134    pmConfig *config = pmConfigRead(&argc, argv, PPSUB_RECIPE); // Configuration
    3235    if (!config) {
    33         psErrorStackPrint(stderr, "Error reading configuration.");
    34         exitValue = PS_EXIT_CONFIG_ERROR;
    3536        goto die;
    3637    }
     
    3940
    4041    if (!pmModelClassInit()) {
    41         psErrorStackPrint(stderr, "Error initialising model classes.\n");
    42         exitValue = PS_EXIT_PROG_ERROR;
     42        psError(PPSUB_ERR_PROG, false, "Unable to initialise model classes.");
    4343        psFree(config);
    4444        goto die;
     
    4646
    4747    if (!psphotInit()) {
    48         psErrorStackPrint(stderr, "Error initialising psphot.\n");
    49         exitValue = PS_EXIT_PROG_ERROR;
     48        psError(PPSUB_ERR_PROG, false, "Error initialising psphot.");
    5049        psFree(config);
    5150        goto die;
     
    5554
    5655    if (!ppSubArguments(argc, argv, data)) {
    57         psErrorStackPrint(stderr, "Error reading arguments.\n");
    58         exitValue = PS_EXIT_CONFIG_ERROR;
     56        psError(psErrorCodeLast(), false, "Error reading arguments.");
    5957        goto die;
    6058    }
    6159
    6260    if (!ppSubCamera(data)) {
    63         psErrorStackPrint(stderr, "Error setting up camera.\n");
    64         exitValue = PS_EXIT_CONFIG_ERROR;
    6561        goto die;
    6662    }
    6763
    6864    if (!ppSubLoop(data)) {
    69         psErrorStackPrint(stderr, "Error performing subtraction.\n");
    70         exitValue = PS_EXIT_SYS_ERROR;
    7165        goto die;
    7266    }
    7367
    7468 die:
    75     psTrace("ppSub", 1, "Finished at %f sec\n", psTimerMark("ppSub"));
    76     psTimerStop();
     69    {
     70        psExit exitValue = ppSubExitCode(PS_EXIT_SUCCESS); // Exit code
    7771
    78     psFree(data);
     72        if (data && data->stats && data->statsFile) {
     73            psString stats = psMetadataConfigFormat(data->stats); // Statistics to output
     74            if (!stats || strlen(stats) == 0) {
     75                psError(PPSUB_ERR_IO, false, "Unable to format statistics file");
     76            } else if (fprintf(data->statsFile, "%s", stats) != strlen(stats)) {
     77                psError(PPSUB_ERR_IO, true, "Unable to write statistics file");
     78            }
     79            psFree(stats);
     80            if (fclose(data->statsFile) == EOF) {
     81                psError(PPSUB_ERR_IO, true, "Unable to close statistics file");
     82            }
     83            data->statsFile = NULL;
     84            pmConfigRunFilenameAddWrite(data->config, "STATS", data->statsName);
     85            exitValue = ppSubExitCode(exitValue);
     86        }
    7987
    80     pmVisualClose(); //close plot windows, if -visual is set
    81     pmModelClassCleanup();
    82     pmConfigDone();
    83     psLibFinalize();
     88        if (config && !ppSubFilesIterateUp(config, PPSUB_FILES_ALL)) {
     89            psError(psErrorCodeLast(), false, "Unable to close files.");
     90            exitValue = ppSubExitCode(exitValue);
     91            pmFPAfileFreeSetStrict(false);
     92        }
    8493
    85     exit(exitValue);
     94        if (data) {
     95            psString dump_file = psMetadataLookupStr(NULL, data->config->arguments, "-dumpconfig");
     96            if (dump_file) {
     97                if (!pmConfigDump(data->config, dump_file)) {
     98                    psError(PPSUB_ERR_IO, false, "Unable to dump configuration.");
     99                    exitValue = ppSubExitCode(exitValue);
     100                }
     101            }
     102            psFree(data);
     103        }
     104
     105        psTrace("ppSub", 1, "Finished at %f sec\n", psTimerMark("ppSub"));
     106        psTimerStop();
     107
     108        pmVisualClose(); //close plot windows, if -visual is set
     109        pmModelClassCleanup();
     110        pmConfigDone();
     111        psLibFinalize();
     112
     113        exitValue = ppSubExitCode(exitValue);
     114        exit(exitValue);
     115    }
    86116}
  • branches/simtest_nebulous_branches/ppSub/src/ppSub.h

    r24862 r27840  
    4545    bool photometry;                    // Perform photometry?
    4646    bool inverse;                       // Output inverse subtraction as well?
     47    bool saveInConv;                    // Save convolved input?
     48    bool saveRefConv;                   // Save convolved reference?
    4749    psString stamps;                    // Stamps file
    4850    pmPSF *psf;                         // Point Spread Function
     
    152154    );
    153155
     156/// Generate JPEG images
     157bool ppSubResidualSampleJpeg(pmConfig *config);
     158
    154159/// Generate inverse subtraction
    155160bool ppSubReadoutInverse(pmConfig *config // Configuration
     
    160165bool psMetadataCopySingle(psMetadata *target, psMetadata *source, const char *name);
    161166
     167bool ppSubCopyPSF (pmFPAfile *output, pmFPAfile *input, pmFPAview *view);
     168
     169/// Return appropriate exit code
     170psExit ppSubExitCode(psExit exitValue   // Current exit value
     171    );
     172
    162173///@}
    163174#endif
  • branches/simtest_nebulous_branches/ppSub/src/ppSubArguments.c

    r24833 r27840  
    8686    psMetadataAddS32(arguments, PS_LIST_TAIL, "-convolve", 0, "Image to convolve [1 or 2]", 0);
    8787    psMetadataAddBool(arguments, PS_LIST_TAIL, "-photometry", 0, "Perform photometry?", NULL);
    88     psMetadataAddBool(arguments, PS_LIST_TAIL, "-inverse", 0, "Generate inverse subtractions?", NULL);
     88    psMetadataAddF32(arguments, PS_LIST_TAIL, "-zp", 0, "Zero point for photometry", NAN);
     89    psMetadataAddBool(arguments, PS_LIST_TAIL, "-inverse", 0, "Generate inverse subtractions?", false);
     90    psMetadataAddBool(arguments, PS_LIST_TAIL, "-save-inconv", 0, "Save input convolved images?", false);
     91    psMetadataAddBool(arguments, PS_LIST_TAIL, "-save-refconv", 0, "Save reference convolved images?", false);
    8992    psMetadataAddBool(arguments, PS_LIST_TAIL, "-visual", 0, "Show diagnostic plots", NULL);
    9093
     
    140143    if (data->statsName && strlen(data->statsName) > 0) {
    141144        psString resolved = pmConfigConvertFilename(data->statsName, config, true, true); // Resolved filename
     145        if (!resolved) {
     146            psError(psErrorCodeLast(), false, "Unable to resolve statistics file: %s", data->statsName);
     147            return false;
     148        }
    142149        data->statsFile = fopen(resolved, "w");
    143150        if (!data->statsFile) {
     
    149156    }
    150157
     158    data->saveInConv = psMetadataLookupBool(NULL, arguments, "-save-inconv");
     159    data->saveRefConv = psMetadataLookupBool(NULL, arguments, "-save-refconv");
     160
    151161    if (psMetadataLookupBool(NULL, arguments, "-visual")) {
    152162        pmVisualSetVisual(true);
     
    156166    if (threads > 0) {
    157167        if (!psThreadPoolInit(threads)) {
    158             psError(PS_ERR_UNKNOWN, false, "Unable to setup %d threads", threads);
     168            psError(psErrorCodeLast(), false, "Unable to setup %d threads", threads);
    159169            return false;
    160170        }
  • branches/simtest_nebulous_branches/ppSub/src/ppSubBackground.c

    r23740 r27840  
    4242    if (!modelRO) {
    4343        // Create the background model
    44         if (!psphotModelBackground(config, view, "PPSUB.OUTPUT")) {
    45             psError(PS_ERR_UNKNOWN, false, "Unable to model background");
     44        if (!psphotModelBackgroundReadoutFileIndex(config, view, "PPSUB.OUTPUT", 0)) {
     45            psError(psErrorCodeLast(), false, "Unable to model background");
    4646            psFree(view);
    4747            return false;
     
    5050        modelRO = pmFPAfileThisReadout(config->files, view, "PSPHOT.BACKMDL");
    5151        if (!modelRO) {
    52             psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find background model");
     52            psError(psErrorCodeLast(), false, "Unable to find background model");
    5353            psFree(view);
    5454            return false;
  • branches/simtest_nebulous_branches/ppSub/src/ppSubCamera.c

    r24261 r27840  
    2323
    2424// Define an input file
    25 static pmFPAfile *defineInputFile(pmConfig *config,// Configuration
     25static pmFPAfile *defineInputFile(bool *success,
     26                                  pmConfig *config,// Configuration
    2627                                  pmFPAfile *bind,    // File to which to bind, or NULL
    2728                                  char *filerule,     // Name of file rule
     
    3233    bool status;
    3334
    34     // look for the file on the RUN metadata
    35     pmFPAfile *file = pmFPAfileDefineFromRun(&status, bind, config, filerule); // File to return
     35    *success = false;
     36
     37    pmFPAfile *file = NULL;
     38
     39    // look for the file on the argument list
     40    if (bind) {
     41        file = pmFPAfileBindFromArgs(&status, bind, config, filerule, argname);
     42    } else {
     43        file = pmFPAfileDefineFromArgs(&status, config, filerule, argname);
     44    }
     45
    3646    if (!status) {
    37         psError(PS_ERR_UNKNOWN, false, "Failed to load file definition for %s", filerule);
    38         return NULL;
     47        psError(psErrorCodeLast(), false, "Failed to load file definition for %s", filerule);
     48        return false;
    3949    }
    4050    if (!file) {
    41         // look for the file on the argument list
    42         if (bind) {
    43             file = pmFPAfileBindFromArgs(&status, bind, config, filerule, argname);
    44         } else {
    45             file = pmFPAfileDefineFromArgs(&status, config, filerule, argname);
    46         }
     51        // look for the file on the RUN metadata
     52        file = pmFPAfileDefineFromRun(&status, bind, config, filerule); // File to return
    4753        if (!status) {
    48             psError(PS_ERR_UNKNOWN, false, "Failed to load file definition for %s", filerule);
    49             return false;
     54            psError(psErrorCodeLast(), false, "Failed to load file definition for %s", filerule);
     55            return NULL;
    5056        }
    5157    }
    5258
    5359    if (!file) {
     60        // no file defined
     61        *success = true;
    5462        return NULL;
    5563    }
    5664
    5765    if (file->type != fileType) {
    58         psError(PS_ERR_UNKNOWN, true, "%s is not of type %s", filerule, pmFPAfileStringFromType(fileType));
    59         return NULL;
    60     }
    61 
     66        psError(PPSUB_ERR_CONFIG, true, "%s is not of type %s", filerule, pmFPAfileStringFromType(fileType));
     67        return NULL;
     68    }
     69
     70    *success = true;
    6271    return file;
    6372}
     
    7584        pmFPAfileDefineOutput(config, template->fpa, filerule);
    7685    if (!file) {
    77         psError(PS_ERR_IO, false, _("Unable to generate output file from %s"), filerule);
     86        psError(psErrorCodeLast(), false, _("Unable to generate output file from %s"), filerule);
    7887        return NULL;
    7988    }
    8089    if (file->type != fileType) {
    81         psError(PS_ERR_IO, true, "%s is not of type %s", filerule, pmFPAfileStringFromType(fileType));
     90        psError(PPSUB_ERR_CONFIG, true, "%s is not of type %s", filerule, pmFPAfileStringFromType(fileType));
    8291        return NULL;
    8392    }
     
    92101                                 pmFPAfile *bind,    // File to which to bind, or NULL
    93102                                 char *filerule,     // Name of file rule
     103                                 const char *argname,   // Argument name for file
    94104                                 pmFPAfileType fileType // Type of file
    95105    )
     
    98108
    99109    // look for the file on the RUN metadata
    100     pmFPAfile *file = pmFPAfileDefineFromRun(&status, bind, config, filerule); // File to return
     110    pmFPAfile *file = pmFPAfileDefineFromRun(&status, NULL, config, filerule); // File to return
    101111    if (!status) {
    102         psError(PS_ERR_UNKNOWN, false, "Failed to load file definition for %s", filerule);
     112        psError(psErrorCodeLast(), false, "Failed to load file definition for %s", filerule);
     113        return NULL;
     114    }
     115    file = pmFPAfileBindFromArgs(&status, bind, config, filerule, argname);
     116    if (!status) {
     117        psError(psErrorCodeLast(), false, "Failed to load file definition for %s", filerule);
    103118        return NULL;
    104119    }
     
    112127        file = pmFPAfileDefineOutput(config, bind ? bind->fpa : NULL, filerule);
    113128        if (!status) {
    114             psError(PS_ERR_UNKNOWN, false, "Failed to load file definition for %s", filerule);
     129            psError(psErrorCodeLast(), false, "Failed to load file definition for %s", filerule);
    115130            return false;
    116131        }
     
    126141
    127142    if (file->type != fileType) {
    128         psError(PS_ERR_UNKNOWN, true, "%s is not of type %s", filerule, pmFPAfileStringFromType(fileType));
     143        psError(PPSUB_ERR_CONFIG, true, "%s is not of type %s", filerule, pmFPAfileStringFromType(fileType));
    129144        return NULL;
    130145    }
     
    136151bool ppSubCamera(ppSubData *data)
    137152{
     153    bool success = true;
     154
    138155    psAssert(data, "Require processing data");
    139156    pmConfig *config = data->config;
     
    141158
    142159    // Input image
    143     pmFPAfile *input = defineInputFile(config, NULL, "PPSUB.INPUT", "INPUT", PM_FPA_FILE_IMAGE);
    144     if (!input) {
    145         psError(PS_ERR_IO, false, "Failed to build FPA from PPSUB.INPUT");
    146         return false;
    147     }
    148     defineInputFile(config, input, "PPSUB.INPUT.MASK", "INPUT.MASK", PM_FPA_FILE_MASK);
    149     pmFPAfile *inVar = defineInputFile(config, input, "PPSUB.INPUT.VARIANCE", "INPUT.VARIANCE",
    150                                        PM_FPA_FILE_VARIANCE);
    151     defineInputFile(config, NULL, "PPSUB.INPUT.SOURCES", "INPUT.SOURCES", PM_FPA_FILE_CMF);
     160    pmFPAfile *input = defineInputFile(&success, config, NULL, "PPSUB.INPUT", "INPUT", PM_FPA_FILE_IMAGE);
     161    if (!success) {
     162        psError(psErrorCodeLast(), false, "Failed to build FPA from PPSUB.INPUT");
     163        return false;
     164    }
     165
     166    defineInputFile(&success, config, input, "PPSUB.INPUT.MASK", "INPUT.MASK", PM_FPA_FILE_MASK);
     167    if (!success) {
     168        psError(psErrorCodeLast(), false, "Failed to build FPA from PPSUB.INPUT.MASK");
     169        return false;
     170    }
     171
     172    pmFPAfile *inVar = defineInputFile(&success, config, input, "PPSUB.INPUT.VARIANCE", "INPUT.VARIANCE", PM_FPA_FILE_VARIANCE);
     173    if (!success) {
     174        psError(psErrorCodeLast(), false, "Failed to build FPA from PPSUB.INPUT.VARIANCE");
     175        return false;
     176    }
     177
     178    defineInputFile(&success, config, NULL, "PPSUB.INPUT.SOURCES", "INPUT.SOURCES", PM_FPA_FILE_CMF);
     179    if (!success) {
     180        psError(psErrorCodeLast(), false, "Failed to build FPA from PPSUB.INPUT.SOURCES");
     181        return false;
     182    }
    152183
    153184    // Reference image
    154     pmFPAfile *ref = defineInputFile(config, NULL, "PPSUB.REF", "REF", PM_FPA_FILE_IMAGE);
    155     if (!ref) {
    156         psError(PS_ERR_IO, false, "Failed to build FPA from PPSUB.REF");
    157         return false;
    158     }
    159     defineInputFile(config, ref, "PPSUB.REF.MASK", "REF.MASK", PM_FPA_FILE_MASK);
    160     pmFPAfile *refVar = defineInputFile(config, ref, "PPSUB.REF.VARIANCE", "REF.VARIANCE",
    161                                         PM_FPA_FILE_VARIANCE);
    162     defineInputFile(config, NULL, "PPSUB.REF.SOURCES", "REF.SOURCES", PM_FPA_FILE_CMF);
    163 
     185    pmFPAfile *ref = defineInputFile(&success, config, NULL, "PPSUB.REF", "REF", PM_FPA_FILE_IMAGE);
     186    if (!success) {
     187        psError(psErrorCodeLast(), false, "Failed to build FPA from PPSUB.REF");
     188        return false;
     189    }
     190
     191    defineInputFile(&success, config, ref, "PPSUB.REF.MASK", "REF.MASK", PM_FPA_FILE_MASK);
     192    if (!success) {
     193        psError(psErrorCodeLast(), false, "Failed to build FPA from PPSUB.REF.MASK");
     194        return false;
     195    }
     196
     197    pmFPAfile *refVar = defineInputFile(&success, config, ref, "PPSUB.REF.VARIANCE", "REF.VARIANCE", PM_FPA_FILE_VARIANCE);
     198    if (!success) {
     199        psError(psErrorCodeLast(), false, "Failed to build FPA from PPSUB.REF.VARIANCE");
     200        return false;
     201    }
     202
     203    defineInputFile(&success, config, NULL, "PPSUB.REF.SOURCES", "REF.SOURCES", PM_FPA_FILE_CMF);
     204    if (!success) {
     205        psError(psErrorCodeLast(), false, "Failed to build FPA from PPSUB.REF.SOURCES");
     206        return false;
     207    }
    164208
    165209    // Now that the camera has been determined, we can read the recipe
    166210    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPSUB_RECIPE); // Recipe for ppSim
    167211    if (!recipe) {
    168         psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find recipe %s", PPSUB_RECIPE);
     212        psError(PPSUB_ERR_CONFIG, false, "Unable to find recipe %s", PPSUB_RECIPE);
    169213        return false;
    170214    }
     
    180224    data->inverse = psMetadataLookupBool(NULL, recipe, "INVERSE");
    181225    data->photometry = psMetadataLookupBool(NULL, recipe, "PHOTOMETRY");
    182 
    183     bool mdok;                          // Status of MD lookup
    184     bool saveConv = psMetadataLookupBool(&mdok, recipe, "SAVE.CONVOLVED"); // Save convolved images?
    185226
    186227    // Convolved input image
     
    189230                                             PM_FPA_FILE_MASK);
    190231    if (!inConvImage || !inConvMask) {
    191         psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
    192         return false;
    193     }
    194     if (saveConv) {
    195         inConvImage->save = true;
    196         inConvMask->save = true;
    197     }
     232        psError(psErrorCodeLast(), false, "Unable to define output files");
     233        return false;
     234    }
     235    inConvImage->save = data->saveInConv;
     236    inConvMask->save = data->saveInConv;
    198237    if (inVar) {
    199238        pmFPAfile *inConvVar = defineOutputFile(config, inConvImage, false, "PPSUB.INPUT.CONV.VARIANCE",
    200239                                                PM_FPA_FILE_VARIANCE);
    201240        if (!inConvVar) {
    202             psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
    203             return false;
    204         }
    205         if (saveConv) {
    206             inConvVar->save = true;
    207         }
     241            psError(psErrorCodeLast(), false, "Unable to define output files");
     242            return false;
     243        }
     244        inConvVar->save = data->saveInConv;
    208245    }
    209246
     
    213250                                              PM_FPA_FILE_MASK);
    214251    if (!refConvImage || !refConvMask) {
    215         psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
    216         return false;
    217     }
    218     if (saveConv) {
    219         refConvImage->save = true;
    220         refConvMask->save = true;
    221     }
     252        psError(psErrorCodeLast(), false, "Unable to define output files");
     253        return false;
     254    }
     255    refConvImage->save = data->saveRefConv;
     256    refConvMask->save = data->saveRefConv;
    222257    if (refVar) {
    223258        pmFPAfile *refConvVar = defineOutputFile(config, refConvImage, false, "PPSUB.REF.CONV.VARIANCE",
    224259                                                 PM_FPA_FILE_VARIANCE);
    225260        if (!refConvVar) {
    226             psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
    227             return false;
    228         }
    229         if (saveConv) {
    230             refConvVar->save = true;
    231         }
     261            psError(psErrorCodeLast(), false, "Unable to define output files");
     262            return false;
     263        }
     264        refConvVar->save = data->saveRefConv;
    232265    }
    233266
     
    236269    pmFPAfile *outMask = defineOutputFile(config, output, false, "PPSUB.OUTPUT.MASK", PM_FPA_FILE_MASK);
    237270    if (!output || !outMask) {
    238         psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
     271        psError(psErrorCodeLast(), false, "Unable to define output files");
    239272        return false;
    240273    }
     
    245278                                             PM_FPA_FILE_VARIANCE);
    246279        if (!outVar) {
    247             psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
     280            psError(psErrorCodeLast(), false, "Unable to define output files");
    248281            return false;
    249282        }
     
    258291                                              PM_FPA_FILE_MASK);
    259292        if (!inverse || !invMask) {
    260             psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
     293            psError(psErrorCodeLast(), false, "Unable to define output files");
    261294            return false;
    262295        }
     
    267300                                                 PM_FPA_FILE_VARIANCE);
    268301            if (!invVar) {
    269                 psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
     302                psError(psErrorCodeLast(), false, "Unable to define output files");
    270303                return false;
    271304            }
     
    278311    pmFPAfile *jpeg1 = pmFPAfileDefineOutput(config, NULL, "PPSUB.OUTPUT.JPEG1");
    279312    if (!jpeg1) {
    280         psError(PS_ERR_IO, false, _("Unable to generate output file from PPSUB.OUTPUT.JPEG1"));
     313        psError(psErrorCodeLast(), false, _("Unable to generate output file from PPSUB.OUTPUT.JPEG1"));
    281314        return false;
    282315    }
    283316    if (jpeg1->type != PM_FPA_FILE_JPEG) {
    284         psError(PS_ERR_IO, true, "PPSUB.OUTPUT.JPEG1 is not of type JPEG");
     317        psError(psErrorCodeLast(), true, "PPSUB.OUTPUT.JPEG1 is not of type JPEG");
    285318        return false;
    286319    }
     
    288321    pmFPAfile *jpeg2 = pmFPAfileDefineOutput(config, NULL, "PPSUB.OUTPUT.JPEG2");
    289322    if (!jpeg2) {
    290         psError(PS_ERR_IO, false, _("Unable to generate output file from PPSUB.OUTPUT.JPEG2"));
     323        psError(psErrorCodeLast(), false, _("Unable to generate output file from PPSUB.OUTPUT.JPEG2"));
    291324        return false;
    292325    }
    293326    if (jpeg2->type != PM_FPA_FILE_JPEG) {
    294         psError(PS_ERR_IO, true, "PPSUB.OUTPUT.JPEG2 is not of type JPEG");
     327        psError(psErrorCodeLast(), true, "PPSUB.OUTPUT.JPEG2 is not of type JPEG");
    295328        return false;
    296329    }
    297330    jpeg2->save = true;
    298331
     332    // Output residual JPEG
     333    pmFPAfile *jpeg3 = pmFPAfileDefineOutput(config, NULL, "PPSUB.OUTPUT.RESID.JPEG");
     334    if (!jpeg3) {
     335        psError(psErrorCodeLast(), false, _("Unable to generate output file from PPSUB.OUTPUT.RESID.JPEG"));
     336        return false;
     337    }
     338    if (jpeg3->type != PM_FPA_FILE_JPEG) {
     339        psError(psErrorCodeLast(), true, "PPSUB.OUTPUT.RESID.JPEG is not of type JPEG");
     340        return false;
     341    }
     342    jpeg3->save = true;
     343
    299344    // Output subtraction kernel
    300     pmFPAfile *kernel = defineCalcFile(config, output, "PPSUB.OUTPUT.KERNELS", PM_FPA_FILE_SUBKERNEL);
     345    pmFPAfile *kernel = defineCalcFile(config, output, "PPSUB.OUTPUT.KERNELS", "KERNEL",
     346                                       PM_FPA_FILE_SUBKERNEL);
    301347    if (!kernel) {
    302348        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to define file PPSUB.OUTPUT.KERNELS");
     
    305351
    306352    // psPhot input
    307     if (data->photometry) {
     353    if (data->photometry || 1) {
    308354        psphotModelClassInit();        // load implementation-specific models
    309355
    310356        pmFPAfile *psphot = pmFPAfileDefineFromFPA(config, output->fpa, 1, 1, "PSPHOT.INPUT");
    311357        if (!psphot) {
    312             psError(PS_ERR_IO, false, "Failed to build FPA from PSPHOT.INPUT");
     358            psError(psErrorCodeLast(), false, "Failed to build FPA from PSPHOT.INPUT");
    313359            return false;
    314360        }
    315361        if (psphot->type != PM_FPA_FILE_IMAGE) {
    316             psError(PS_ERR_IO, true, "PSPHOT.INPUT is not of type IMAGE");
    317             return false;
    318         }
     362            psError(psErrorCodeLast(), true, "PSPHOT.INPUT is not of type IMAGE");
     363            return false;
     364        }
     365        // specify the number of psphot input images
     366        psMetadataAddS32 (config->arguments, PS_LIST_TAIL, "PSPHOT.INPUT.NUM", PS_META_REPLACE, "number of inputs", 1);
    319367        pmFPAfileActivate(config->files, false, "PSPHOT.INPUT");
    320368
    321         // Internal-ish file for getting the PSF from the minuend
    322         pmFPAfile *psf = pmFPAfileDefineOutputFromFile(config, psphot, "PSPHOT.PSF.LOAD");
     369        // Internal file for getting the PSF from the minuend
     370        pmFPAfile *psf = pmFPAfileDefineFromFPA(config, output->fpa, 1, 1, "PSPHOT.PSF.LOAD");
    323371        if (!psf) {
    324             psError(PS_ERR_IO, false, "Failed to build FPA from PSPHOT.PSF.LOAD");
     372            psError(psErrorCodeLast(), false, "Failed to build FPA from PSPHOT.PSF.LOAD");
    325373            return false;
    326374        }
    327375        if (psf->type != PM_FPA_FILE_PSF) {
    328             psError(PS_ERR_IO, true, "PSPHOT.PSF.LOAD is not of type PSF");
     376            psError(psErrorCodeLast(), true, "PSPHOT.PSF.LOAD is not of type PSF");
    329377            return false;
    330378        }
     
    332380
    333381        if (!psphotDefineFiles(config, psphot)) {
    334             psError(PS_ERR_UNKNOWN, false, "Unable to set up psphot files.");
     382            psError(psErrorCodeLast(), false, "Unable to set up psphot files.");
    335383            return false;
    336384        }
     
    343391                                                 PM_FPA_FILE_CMF);
    344392        if (!outSources) {
    345             psError(PS_ERR_UNKNOWN, false, "Unable to set up output source file.");
     393            psError(psErrorCodeLast(), false, "Unable to set up output source file.");
    346394            return false;
    347395        }
     
    352400                                                     PM_FPA_FILE_CMF);
    353401            if (!invSources) {
    354                 psError(PS_ERR_UNKNOWN, false, "Unable to set up inverse source file.");
     402                psError(psErrorCodeLast(), false, "Unable to set up inverse source file.");
    355403                return false;
    356404            }
  • branches/simtest_nebulous_branches/ppSub/src/ppSubData.c

    r23753 r27840  
    1313static void subDataFree(ppSubData *data)
    1414{
    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         pmConfigRunFilenameAddWrite(data->config, "STATS", data->statsName);
    25     }
     15    psAssert(!data->statsFile, "Statistics file still open.");
    2616    psFree(data->statsName);
    2717    psFree(data->stamps);
     
    2919    psFree(data->stats);
    3020
    31     psString dump_file = psMetadataLookupStr(NULL, data->config->arguments, "-dumpconfig");
    32     if (dump_file) {
    33         pmConfigDump(data->config, dump_file);
    34     }
    3521    psFree(data->config);
    3622
     
    4733    data->photometry = false;
    4834    data->inverse = false;
     35    data->saveInConv = false;
     36    data->saveRefConv = false;
    4937    data->stamps = NULL;
    5038    data->psf = NULL;
  • branches/simtest_nebulous_branches/ppSub/src/ppSubDefineOutput.c

    r23740 r27840  
    5151    bool mdok;                          // Status of MD lookup
    5252    psMetadata *analysis = inConv->analysis; // Analysis metadata with kernel information
    53     pmSubtractionKernels *kernels = psMetadataLookupPtr(&mdok, analysis,
    54                                                         PM_SUBTRACTION_ANALYSIS_KERNEL); // Subtraction kernel
     53    pmHDU *hdu = pmHDUFromCell(inConv->parent);
     54    pmSubtractionKernels *kernels = psMetadataLookupPtr(&mdok, analysis, PM_SUBTRACTION_ANALYSIS_KERNEL); // Subtraction kernel
     55
    5556    if (!kernels) {
     57        hdu = pmHDUFromCell(refConv->parent);
    5658        analysis = refConv->analysis;
    5759        kernels = psMetadataLookupPtr(&mdok, analysis, PM_SUBTRACTION_ANALYSIS_KERNEL);
    5860    }
    5961    if (!kernels) {
    60         psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find SUBTRACTION.KERNEL");
     62        psError(PPSUB_ERR_UNKNOWN, true, "Unable to find SUBTRACTION.KERNEL");
    6163        psFree(outRO);
    6264        return false;
    6365    }
    64     psMetadataAddStr(outHDU->header, PS_LIST_TAIL, "PPSUB.KERNEL", 0, "Subtraction kernel",
    65                      kernels->description);
     66    psAssert (hdu, "unable to find HDU");
     67    psMetadataAddStr(outHDU->header, PS_LIST_TAIL, "PPSUB.KERNEL", 0, "Subtraction kernel", kernels->description);
     68    outHDU->header = psMetadataCopy(outHDU->header, hdu->header);
    6669
    6770    // Add additional data to the header
  • branches/simtest_nebulous_branches/ppSub/src/ppSubErrorCodes.dat

    r23740 r27840  
    1010DATA                    Problem in data values
    1111NO_OVERLAP              No overlap between input and skycell
     12PROG                    Programming error
  • branches/simtest_nebulous_branches/ppSub/src/ppSubFiles.c

    r23740 r27840  
    2323// Subtraction files
    2424static const char *subFiles[] = { "PPSUB.OUTPUT", "PPSUB.OUTPUT.MASK", "PPSUB.OUTPUT.VARIANCE",
    25                                   "PPSUB.OUTPUT.JPEG1", "PPSUB.OUTPUT.JPEG2",
     25                                  "PPSUB.OUTPUT.JPEG1", "PPSUB.OUTPUT.JPEG2", "PPSUB.OUTPUT.RESID.JPEG",
    2626                                  NULL };
    2727
     
    183183    }
    184184
     185    psFree(view);
     186
     187    // Disable writing of data now that we've written things out
     188    if (files & PPSUB_FILES_CONV) {
     189        pmFPAview *view = ppSubViewReadout(); // View to readout
     190        {
     191            pmReadout *ro = pmFPAfileThisReadout(config->files, view, "PPSUB.INPUT.CONV");
     192            if (ro) {
     193                ro->data_exists = ro->parent->data_exists = ro->parent->parent->data_exists = false;
     194            }
     195        }
     196        {
     197            pmReadout *ro = pmFPAfileThisReadout(config->files, view, "PPSUB.REF.CONV");
     198            if (ro) {
     199                ro->data_exists = ro->parent->data_exists = ro->parent->parent->data_exists = false;
     200            }
     201        }
     202        psFree(view);
     203    }
     204    if (files & PPSUB_FILES_SUB) {
     205        pmFPAview *view = ppSubViewReadout(); // View to readout
     206        pmReadout *ro = pmFPAfileThisReadout(config->files, view, "PPSUB.OUTPUT");
     207        if (ro) {
     208            ro->data_exists = ro->parent->data_exists = ro->parent->parent->data_exists = false;
     209        }
     210        psFree(view);
     211    }
     212    // Disable writing of data now that we've written things out
     213    if (files & PPSUB_FILES_INV) {
     214        pmFPAview *view = ppSubViewReadout(); // View to readout
     215        pmReadout *ro = pmFPAfileThisReadout(config->files, view, "PPSUB.INVERSE");
     216        if (ro) {
     217            ro->data_exists = ro->parent->data_exists = ro->parent->parent->data_exists = false;
     218        }
     219        psFree(view);
     220    }
     221
    185222    ppSubFilesActivate(config, PPSUB_FILES_ALL, false);
    186223
  • branches/simtest_nebulous_branches/ppSub/src/ppSubLoop.c

    r24862 r27840  
    2727
    2828    pmConfigCamerasCull(config, NULL);
    29     pmConfigRecipesCull(config, "PPSUB,PPSTATS,PSPHOT,MASKS,JPEG");
     29    pmConfigRecipesCull(config, "PPSUB,PPSTATS,PSPHOT,PSASTRO,MASKS,JPEG");
    3030
    3131
     
    4343
    4444    if (!ppSubSetMasks(config)) {
    45         psError(PS_ERR_UNKNOWN, false, "Unable to set masks.");
     45        psError(psErrorCodeLast(), false, "Unable to set masks.");
    4646        return false;
    4747    }
    4848
    4949    if (!ppSubMatchPSFs(data)) {
    50         psError(PS_ERR_UNKNOWN, false, "Unable to match PSFs.");
     50        psError(psErrorCodeLast(), false, "Unable to match PSFs.");
    5151        return false;
    5252    }
     
    5555        return true;
    5656    }
     57    // generate the residual stamp grid for visualization
     58    if (!ppSubResidualSampleJpeg(config)) {
     59        psError(psErrorCodeLast(), false, "Unable to update.");
     60        return false;
     61    }
    5762
    5863    psMetadataAddF32(data->stats, PS_LIST_TAIL, "TIME_MATCH", 0, "Time to match PSFs",
     
    6671
    6772    if (!ppSubLowThreshold(data)) {
    68         psError(PS_ERR_UNKNOWN, false, "Unable to threshold images.");
     73        psError(psErrorCodeLast(), false, "Unable to threshold images.");
    6974        return false;
    7075    }
     
    7782
    7883    if (!ppSubDefineOutput("PPSUB.OUTPUT", config)) {
    79         psError(PS_ERR_UNKNOWN, false, "Unable to define output.");
     84        psError(psErrorCodeLast(), false, "Unable to define output.");
    8085        return false;
    8186    }
    8287
    8388    if (!data->quality && !ppSubMakePSF(data)) {
    84         psError(PS_ERR_UNKNOWN, false, "Unable to generate PSF.");
    85         return false;
     89        psError(psErrorCodeLast(), false, "Unable to generate PSF.");
     90        return false;
     91    }
     92
     93    // Now we've got a PSF, blow away detections in case they're confused with real output detections
     94    {
     95        pmFPAview *view = ppSubViewReadout(); // View to readout
     96        pmReadout *out = pmFPAfileThisReadout(config->files, view, "PPSUB.OUTPUT");
     97        if (psMetadataLookup(out->analysis, "PSPHOT.DETECTIONS")) {
     98            psMetadataRemoveKey(out->analysis, "PSPHOT.DETECTIONS");
     99        }
     100        psFree(view);
    86101    }
    87102
    88103    if (!ppSubReadoutSubtract(config)) {
    89         psError(PS_ERR_UNKNOWN, false, "Unable to subtract images.");
     104        psError(psErrorCodeLast(), false, "Unable to subtract images.");
    90105        return false;
    91106    }
     
    99114    // Higher order background subtraction using psphot
    100115    if (!ppSubBackground(config)) {
    101         psError(PS_ERR_UNKNOWN, false, "Unable to subtract background.");
     116        psError(psErrorCodeLast(), false, "Unable to subtract background.");
    102117        return false;
    103118    }
     
    105120    // Perform Variance correction (rescale within a modest range)
    106121    if (!ppSubVarianceRescale(config)) {
    107         psError(PS_ERR_UNKNOWN, false, "Unable to rescale variance.");
     122        psError(psErrorCodeLast(), false, "Unable to rescale variance.");
    108123        return false;
    109124    }
     
    115130
    116131    if (!data->quality && !ppSubReadoutPhotometry("PPSUB.OUTPUT", data)) {
    117         psError(PS_ERR_UNKNOWN, false, "Unable to perform photometry.");
     132        psError(psErrorCodeLast(), false, "Unable to perform photometry.");
    118133        return false;
    119134    }
     
    126141    // Perform statistics on the cell
    127142    if (!ppSubReadoutStats(data)) {
    128         psError(PS_ERR_UNKNOWN, false, "Unable to collect statistics");
    129         return false;
    130     }
    131 
     143        psError(psErrorCodeLast(), false, "Unable to collect statistics");
     144        return false;
     145    }
     146
     147    // generate the binned image used to write the jpeg
    132148    if (!ppSubReadoutJpeg(config)) {
    133         psError(PS_ERR_UNKNOWN, false, "Unable to update.");
     149        psError(psErrorCodeLast(), false, "Unable to update.");
    134150        return false;
    135151    }
     
    143159
    144160        if (data->inverse && !ppSubDefineOutput("PPSUB.INVERSE", config)) {
    145             psError(PS_ERR_UNKNOWN, false, "Unable to define inverse.");
     161            psError(psErrorCodeLast(), false, "Unable to define inverse.");
    146162            return false;
    147163        }
    148164
    149165        if (!ppSubReadoutInverse(config)) {
    150             psError(PS_ERR_UNKNOWN, false, "Unable to invert images.");
     166            psError(psErrorCodeLast(), false, "Unable to invert images.");
    151167            return false;
    152168        }
     
    164180
    165181        if (!data->quality && !ppSubReadoutPhotometry("PPSUB.INVERSE", data)) {
    166             psError(PS_ERR_UNKNOWN, false, "Unable to perform photometry.");
     182            psError(psErrorCodeLast(), false, "Unable to perform photometry.");
    167183            return false;
    168184        }
  • branches/simtest_nebulous_branches/ppSub/src/ppSubMakePSF.c

    r23763 r27840  
    2121
    2222#include "ppSub.h"
     23
     24psArray *ppSubSelectPSFSources(psArray *sources);
    2325
    2426bool ppSubMakePSF(ppSubData *data)
     
    5759    pmFPAfile *photFile = psMetadataLookupPtr(&mdok, config->files, "PSPHOT.INPUT"); // Photometry file
    5860    if (!pmFPACopy(photFile->fpa, minuendFile->fpa)) {
    59         psError(PS_ERR_UNKNOWN, false, "Unable to copy FPA for photometry");
     61        psError(PPSUB_ERR_CONFIG, false, "Unable to copy FPA for photometry");
    6062        psFree(view);
    6163        return false;
    6264    }
     65
    6366    pmReadout *photRO = pmFPAviewThisReadout(view, photFile->fpa); // Readout to photometer
    64     if (psMetadataLookup(photRO->analysis, "PSPHOT.SOURCES")) {
    65         psMetadataRemoveKey(photRO->analysis, "PSPHOT.SOURCES");
     67
     68    // we need to remove any existing PSPHOT.DETECTIONS (why not do this in psphot?)
     69    if (psMetadataLookup(photRO->analysis, "PSPHOT.DETECTIONS")) {
     70        psMetadataRemoveKey(photRO->analysis, "PSPHOT.DETECTIONS");
    6671    }
     72    if (psMetadataLookup(photRO->parent->parent->analysis, "PSPHOT.PSF")) {
     73        psMetadataRemoveKey(photRO->parent->parent->analysis, "PSPHOT.PSF");
     74    }
     75
     76# ifdef TESTING
     77    // XXX for testing, dump these images:
     78    psphotSaveImage (NULL, photRO->image, "findpsf.im.fits");
     79    psphotSaveImage (NULL, photRO->variance, "findpsf.wt.fits");
     80    psphotSaveImage (NULL, photRO->mask, "findpsf.mk.fits");
     81# endif
    6782
    6883    // Extract the loaded sources from the associated readout, and generate PSF
    6984    // Here, we assume the image is background-subtracted
    70     psArray *sources = psMetadataLookupPtr(&mdok, minuend->analysis, "PSPHOT.SOURCES");
    71     if (!psphotReadoutFindPSF(config, view, sources)) {
     85    pmDetections *detections = psMetadataLookupPtr(&mdok, minuend->analysis, "PSPHOT.DETECTIONS");
     86    if (!detections || !detections->allSources) {
     87        psError(PPSUB_ERR_CONFIG, true, "No sources from which to determine PSF.");
     88        return false;
     89    }
     90    psArray *sources = detections->allSources;
     91
     92    // XXX filter sources?  limit the total number and return only brighter objects?
     93    // use flags to toss totally bogus entries?
     94    psArray *goodSources = ppSubSelectPSFSources (sources);
     95    if (!psphotReadoutFindPSF(config, view, goodSources)) {
    7296        // This is likely a data quality issue
    7397        // XXX Split into multiple cases using error codes?
     
    76100        ppSubDataQuality(data, PSPHOT_ERR_PSF, PPSUB_FILES_PHOT_SUB | PPSUB_FILES_PHOT_INV);
    77101        psFree(view);
     102        psFree(goodSources);
    78103        return true;
     104    }
     105
     106    // save the resulting PSF information on the pmFPAfile PSPHOT.PSF.LOAD
     107    pmFPAfile *psfFile = psMetadataLookupPtr(&mdok, config->files, "PSPHOT.PSF.LOAD"); // PSF file
     108    if (!ppSubCopyPSF(psfFile, photFile, view)) {
     109        psErrorStackPrint(stderr, "PSF was not generated");
     110        psWarning("PSF was not generated --- suspect bad data quality.");
     111        ppSubDataQuality(data, psErrorCodeLast(), PPSUB_FILES_PHOT_SUB | PPSUB_FILES_PHOT_INV);
    79112    }
    80113
     
    82115    psMetadataRemoveKey(photRO->analysis, "PSPHOT.HEADER");
    83116
    84     if (!data->quality) {
    85         data->psf = psMemIncrRefCounter(psMetadataLookupPtr(NULL, photRO->parent->parent->analysis,
    86                                                             "PSPHOT.PSF"));
    87     }
    88 
     117    psFree(goodSources);
    89118    psFree(view);
    90119
    91120    return true;
    92121}
     122
     123bool ppSubCopyPSF(pmFPAfile *output, pmFPAfile *input, pmFPAview *view)
     124{
     125    pmChip *inputChip   = pmFPAviewThisChip(view, input->fpa); // Chip with PSF info
     126    pmChip *outputChip  = pmFPAviewThisChip(view, output->fpa); // Chip to store PSF info
     127
     128    pmReadout *inputRO  = pmFPAviewThisReadout(view, input->fpa); // Readout with PSF info
     129    pmReadout *outputRO = pmFPAviewThisReadout(view, output->fpa); // Readout to store PSF info
     130
     131    if (!outputRO) {
     132        pmCell *outputCell  = pmFPAviewThisCell(view, output->fpa);
     133        outputRO = pmReadoutAlloc(outputCell);
     134        outputRO->image = psMemIncrRefCounter(inputRO->image);
     135    }
     136
     137    // Copy the PSF-related data
     138    psMetadataIterator *iter = psMetadataIteratorAlloc(inputRO->analysis, PS_LIST_HEAD, "^PSF\\.CLUMP.*");
     139    psMetadataItem *item;               // Item from iteration
     140    while ((item = psMetadataGetAndIncrement(iter))) {
     141        psMetadataAddItem(outputRO->analysis, item, PS_LIST_TAIL, PS_META_REPLACE);
     142    }
     143    psFree(iter);
     144
     145    // copy the PSF model data
     146    pmPSF *psf = psMetadataLookupPtr(NULL, inputChip->analysis, "PSPHOT.PSF"); // PSF for photometry
     147    if (!psf) {
     148        psErrorStackPrint(stderr, "No PSF available");
     149        return false;
     150    }
     151
     152    psMetadataAddPtr(outputChip->analysis, PS_LIST_TAIL, "PSPHOT.PSF", PS_DATA_UNKNOWN | PS_META_REPLACE,
     153                     "PSF from ppSubMakePSF", psf);
     154
     155    return true;
     156}
     157
     158
     159// XXX hardwired MAX for now
     160# define MAX_NPSF 500
     161
     162psArray *ppSubSelectPSFSources(psArray *sources){
     163
     164    sources = psArraySort (sources, pmSourceSortBySN);
     165
     166    psArray *subset = psArrayAllocEmpty(MAX_NPSF);
     167
     168    int nPSF = 0;
     169    for (int i = 0; (nPSF < MAX_NPSF) && (i < sources->n); i++) {
     170
     171        pmSource *source = sources->data[i];
     172        if (!source) continue;
     173
     174        // skip non-astronomical objects (very likely defects)
     175        if (source->type == PM_SOURCE_TYPE_DEFECT) continue;
     176        if (source->type == PM_SOURCE_TYPE_SATURATED) continue;
     177        if (source->mode & PM_SOURCE_MODE_SATSTAR) continue;
     178
     179        psArrayAdd (subset, 100, source);
     180        nPSF++;
     181    }
     182
     183    return subset;
     184}
  • branches/simtest_nebulous_branches/ppSub/src/ppSubMatchPSFs.c

    r24862 r27840  
    1818#include <pslib.h>
    1919#include <psmodules.h>
     20#include <psphot.h>
    2021
    2122#include "ppSub.h"
     23
     24#define COVAR_FRAC 0.01                 // Truncation fraction for covariance matrix
    2225
    2326// Normalise a region on an image
     
    3740}
    3841
     42// Measure the PSF for an image
     43static float subImagePSF(ppSubData *data, // Processing data
     44                         const pmReadout *ro, // Readout for which to measure PSF
     45                         psArray *sources     // Sources with positions at which to measure PSF
     46    )
     47{
     48    psAssert(data, "Require processing data");
     49    pmConfig *config = data->config;    // Configuration
     50    psAssert(config, "Require configuration");
     51
     52    psAssert(ro, "Need readout");
     53    psAssert(sources, "Need sources.");
     54
     55    pmFPAfile *photFile = psMetadataLookupPtr(NULL, config->files, "PSPHOT.INPUT"); // Photometry file
     56    psAssert(photFile, "Need photometry file.");
     57    if (!pmFPACopy(photFile->fpa, ro->parent->parent->parent)) {
     58        psError(PPSUB_ERR_CONFIG, false, "Unable to copy FPA for photometry");
     59        return false;
     60    }
     61
     62    pmFPAview *view = ppSubViewReadout(); // View to readout
     63    pmReadout *photRO = pmFPAviewThisReadout(view, photFile->fpa); // Readout to photometer
     64
     65    if (psMetadataLookup(photRO->analysis, "PSPHOT.DETECTIONS")) {
     66        psMetadataRemoveKey(photRO->analysis, "PSPHOT.DETECTIONS");
     67    }
     68    if (psMetadataLookup(photRO->parent->parent->analysis, "PSPHOT.PSF")) {
     69        psMetadataRemoveKey(photRO->parent->parent->analysis, "PSPHOT.PSF");
     70    }
     71
     72    // Extract the loaded sources from the associated readout, and generate PSF
     73    // Here, we assume the image is background-subtracted
     74    if (!psphotReadoutFindPSF(config, view, sources)) {
     75        psErrorStackPrint(stderr, "Unable to determine PSF");
     76        psWarning("Unable to determine PSF.");
     77        psFree(view);
     78        return true;
     79    }
     80
     81    psFree(view);
     82
     83    psMetadata *header = psMetadataLookupMetadata(NULL, photRO->analysis, "PSPHOT.HEADER");
     84    psAssert(header, "Require header.");
     85    float fwhm = psMetadataLookupF32(NULL, header, "FWHM_MAJ");
     86
     87    if (psMetadataLookup(photRO->analysis, "PSPHOT.DETECTIONS")) {
     88        psMetadataRemoveKey(photRO->analysis, "PSPHOT.DETECTIONS");
     89    }
     90    if (psMetadataLookup(photRO->parent->parent->analysis, "PSPHOT.PSF")) {
     91        psMetadataRemoveKey(photRO->parent->parent->analysis, "PSPHOT.PSF");
     92    }
     93
     94    return fwhm;
     95}
     96
     97// Scale the kernel parameters according to the PSFs
     98static bool subScaleKernel(ppSubData *data, // Processing data
     99                           psVector *kernelWidths, // Widths for kernel
     100                           int *kernelSize,        // Size of kernel
     101                           int *stampSize          // Size of stamps (footprint)
     102    )
     103{
     104    psAssert(data, "Require processing data");
     105    pmConfig *config = data->config;    // Configuration
     106    psAssert(config, "Require configuration");
     107
     108    // Nothing to do if pre-calculated kernel exists
     109    pmFPAview *view = ppSubViewReadout(); // View to readout
     110    pmReadout *kernelRO = pmFPAfileThisReadout(config->files, view, "PPSUB.OUTPUT.KERNELS"); // RO with kernel
     111    if (kernelRO) {
     112        psFree(view);
     113        return true;
     114    }
     115
     116    // Look up recipe values
     117    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPSUB_RECIPE); // Recipe for ppSim
     118    psAssert(recipe, "We checked this earlier, so it should be here.");
     119    if (!psMetadataLookupBool(NULL, recipe, "SCALE")) {
     120        // No scaling requested
     121        psFree(view);
     122        return true;
     123    }
     124
     125    // Input images
     126    pmReadout *inRO = pmFPAfileThisReadout(config->files, view, "PPSUB.INPUT"); // Input readout
     127    pmReadout *refRO = pmFPAfileThisReadout(config->files, view, "PPSUB.REF"); // Reference readout
     128
     129    // Input sources
     130    pmReadout *inSourceRO = pmFPAfileThisReadout(config->files, view, "PPSUB.INPUT.SOURCES");
     131    pmReadout *refSourceRO = pmFPAfileThisReadout(config->files, view, "PPSUB.REF.SOURCES");
     132    if (!inSourceRO || !refSourceRO) {
     133        psWarning("Unable to scale kernel, since no sources were provided.");
     134        return true;
     135    }
     136
     137    pmDetections *inDetections = psMetadataLookupPtr(NULL, inSourceRO->analysis, "PSPHOT.DETECTIONS"); // Input sources
     138    pmDetections *refDetections = psMetadataLookupPtr(NULL, refSourceRO->analysis, "PSPHOT.DETECTIONS"); // Ref sources
     139
     140    psFree(view);
     141
     142    if (!inDetections || !refDetections) {
     143        psWarning("Unable to scale kernel, since no sources were provided.");
     144        return true;
     145    }
     146
     147    psArray *inSources = inDetections->allSources;
     148    psAssert (inSources, "missing inSources?");
     149
     150    psArray *refSources = refDetections->allSources;
     151    psAssert (refSources, "missing refSources?");
     152
     153    float inFWHM = psMetadataLookupF32(NULL, inRO->parent->parent->concepts, "CHIP.SEEING"); // FWHM for input
     154    if (!isfinite(inFWHM) || inFWHM == 0.0) {
     155        inFWHM = subImagePSF(data, inRO, inSources);
     156    }
     157    float refFWHM = psMetadataLookupF32(NULL, refRO->parent->parent->concepts, "CHIP.SEEING"); // FWHM for ref
     158    if (!isfinite(refFWHM) || refFWHM == 0.0) {
     159        refFWHM = subImagePSF(data, refRO, refSources);
     160    }
     161    psLogMsg("ppSub", PS_LOG_INFO, "Input FWHM: %f\nReference FWHM: %f\n", inFWHM, refFWHM);
     162    if (!isfinite(inFWHM) || !isfinite(refFWHM)) {
     163        psWarning("Unable to scale kernel, since unable to measure PSFs.");
     164        return true;
     165    }
     166
     167    float scaleRef = psMetadataLookupF32(NULL, recipe, "SCALE.REF"); // Reference for scaling
     168    float scaleMin = psMetadataLookupF32(NULL, recipe, "SCALE.MIN"); // Minimum for scaling
     169    float scaleMax = psMetadataLookupF32(NULL, recipe, "SCALE.MAX"); // Maximum for scaling
     170    if (!isfinite(scaleRef) || !isfinite(scaleMin) || !isfinite(scaleMax)) {
     171        psError(PPSUB_ERR_ARGUMENTS, false,
     172                "Scale parameters (SCALE.REF=%f, SCALE.MIN=%f, SCALE.MAX=%f) not set in recipe.",
     173                scaleRef, scaleMin, scaleMax);
     174        return false;
     175    }
     176
     177    if (!pmSubtractionParamsScale(kernelSize, stampSize, kernelWidths, inFWHM, refFWHM,
     178                                  scaleRef, scaleMin, scaleMax)) {
     179        psError(PPSUB_ERR_DATA, false, "Unable to scale parameters.");
     180        return false;
     181    }
     182
     183    return true;
     184}
     185
    39186
    40187bool ppSubMatchPSFs(ppSubData *data)
     
    71218    pmReadout *kernelRO = pmFPAfileThisReadout(config->files, view, "PPSUB.OUTPUT.KERNELS"); // RO with kernel
    72219
    73     psFree(view);
    74 
    75220    // Sources in image, used for stamps: these must be loaded from previous analysis stages
    76221    pmReadout *inSourceRO = pmFPAfileThisReadout(config->files, view, "PPSUB.INPUT.SOURCES");
    77222    pmReadout *refSourceRO = pmFPAfileThisReadout(config->files, view, "PPSUB.REF.SOURCES");
    78     psArray *inSources = inSourceRO ? psMetadataLookupPtr(&mdok, inSourceRO->analysis, "PSPHOT.SOURCES") :
    79         NULL; // Source list from input image
    80     psArray *refSources = refSourceRO ? psMetadataLookupPtr(&mdok, refSourceRO->analysis, "PSPHOT.SOURCES") :
    81         NULL ; // Source list from reference image
    82 
    83     psArray *sources = NULL;            // Merged list of sources
    84     if (inSources && refSources) {
     223
     224    pmDetections *inDetections  = inSourceRO  ? psMetadataLookupPtr(&mdok, inSourceRO->analysis,  "PSPHOT.DETECTIONS") : NULL; // Input sources
     225    pmDetections *refDetections = refSourceRO ? psMetadataLookupPtr(&mdok, refSourceRO->analysis, "PSPHOT.DETECTIONS") : NULL; // Ref sources
     226
     227    psFree(view);
     228
     229    pmDetections *detections = NULL;    // Merged detection set
     230    if (inDetections && refDetections) {
     231        psArray *inSources  = inDetections->allSources;
     232        psArray *refSources = refDetections->allSources;
     233
     234        psAssert (inSources, "missing in sources?");
     235        psAssert (refSources, "missing ref sources?");
     236
     237        detections = pmDetectionsAlloc();
    85238        float radius = psMetadataLookupF32(NULL, recipe, "SOURCE.RADIUS"); // Matching radius
    86239        psArray *lists = psArrayAlloc(2); // Source lists
    87240        lists->data[0] = psMemIncrRefCounter(inSources);
    88241        lists->data[1] = psMemIncrRefCounter(refSources);
    89         sources = pmSourceMatchMerge(lists, radius);
     242        detections->allSources = pmSourceMatchMerge(lists, radius);
    90243        psFree(lists);
    91         if (!sources) {
    92             psError(PS_ERR_UNKNOWN, false, "Unable to merge source lists");
     244        if (!detections->allSources) {
     245            psError(PPSUB_ERR_DATA, false, "Unable to merge source lists");
     246            psFree(detections);
    93247            return false;
    94248        }
    95     } else if (inSources) {
    96         sources = psMemIncrRefCounter(inSources);
    97     } else if (refSources) {
    98         sources = psMemIncrRefCounter(refSources);
    99     }
    100 
    101     psMetadataAddArray(inConv->analysis, PS_LIST_TAIL, "PSPHOT.SOURCES", PS_META_REPLACE,
    102                        "Merged source list", sources);
    103     psMetadataAddArray(refConv->analysis, PS_LIST_TAIL, "PSPHOT.SOURCES", PS_META_REPLACE,
    104                        "Merged source list", sources);
    105     psFree(sources);                    // Drop reference
     249    }
     250    if (!detections && inDetections) {
     251        detections = psMemIncrRefCounter(inDetections);
     252    }
     253    if (!detections && refDetections) {
     254        detections = psMemIncrRefCounter(refDetections);
     255    }
     256
     257    psMetadataAddPtr(inConv->analysis,  PS_LIST_TAIL, "PSPHOT.DETECTIONS", PS_META_REPLACE | PS_DATA_UNKNOWN, "Merged source list", detections);
     258    psMetadataAddPtr(refConv->analysis, PS_LIST_TAIL, "PSPHOT.DETECTIONS", PS_META_REPLACE | PS_DATA_UNKNOWN, "Merged source list", detections);
     259    psFree(detections);                    // Drop reference
    106260
    107261    int footprint = psMetadataLookupS32(NULL, recipe, "STAMP.FOOTPRINT"); // Stamp half-size
     
    115269    pmSubtractionKernelsType type = pmSubtractionKernelsTypeFromString(typeStr); // Type of kernel
    116270    if (type == PM_SUBTRACTION_KERNEL_NONE) {
    117         psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unrecognised kernel type: %s", typeStr);
     271        psError(PPSUB_ERR_ARGUMENTS, true, "Unrecognised kernel type: %s", typeStr);
    118272        return false;
    119273    }
     
    130284    int iter = psMetadataLookupS32(NULL, recipe, "ITER"); // Rejection iterations
    131285    float rej = psMetadataLookupF32(NULL, recipe, "REJ"); // Rejection threshold
    132     float sys = psMetadataLookupF32(NULL, recipe, "SYS"); // Relative systematic error in kernel
     286    float kernelErr = psMetadataLookupF32(NULL, recipe, "KERNEL.ERR"); // Relative systematic error in kernel
     287    float normFrac = psMetadataLookupF32(NULL, recipe, "NORM.FRAC"); // Fraction of window for normalisn windw
     288    float sysErr = psMetadataLookupF32(NULL, recipe, "SYS.ERR"); // Relative systematic error in images
     289    float skyErr = psMetadataLookupF32(NULL, recipe, "SKY.ERR"); // Additional error in sky
     290    float covarFrac = psMetadataLookupF32(NULL, recipe, "COVAR.FRAC"); // Fraction for covariance calculation
    133291
    134292    float badFrac = psMetadataLookupF32(NULL, recipe, "BADFRAC"); // Maximum bad fraction
     
    168326            break;
    169327          default:
    170             psErrorStackPrint(stderr, "Invalid value for -convolve");
     328            psError(PPSUB_ERR_ARGUMENTS, false, "Invalid value for -convolve");
    171329            return false;
    172330        }
    173331    }
    174332
     333    if (!subScaleKernel(data, widths, &size, &footprint)) {
     334        psError(PPSUB_ERR_DATA, false, "Unable to scale kernel parameters");
     335        return false;
     336    }
     337
    175338    int threads = psMetadataLookupS32(NULL, config->arguments, "-threads"); // Number of threads
    176339    if (threads > 0) {
    177         pmSubtractionThreadsInit(inRO, refRO);
    178     }
     340        pmSubtractionThreadsInit();
     341    }
     342
     343    if (inRO->covariance) {
     344        psImageCovarianceTruncate(inRO->covariance, COVAR_FRAC);
     345    }
     346    if (refRO->covariance) {
     347        psImageCovarianceTruncate(refRO->covariance, COVAR_FRAC);
     348    }
     349
     350    // Data doesn't exist until it's created in pmSubtraction...
     351    inConv->data_exists = inConv->parent->data_exists = inConv->parent->parent->data_exists = false;
     352    refConv->data_exists = refConv->parent->data_exists = refConv->parent->parent->data_exists = false;
    179353
    180354    // Match the PSFs
     
    182356    if (kernelRO) {
    183357        success = pmSubtractionMatchPrecalc(inConv, refConv, inRO, refRO, kernelRO->analysis,
    184                                             stride, sys, maskVal, maskBad, maskPoor, poorFrac, badFrac);
     358                                            stride, kernelErr, covarFrac, maskVal, maskBad, maskPoor,
     359                                            poorFrac, badFrac);
    185360    } else {
    186361        success = pmSubtractionMatch(inConv, refConv, inRO, refRO, footprint, stride, regionSize,
    187                                      spacing, threshold, sources, data->stamps, type, size, order,
    188                                      widths, orders, inner, ringsOrder, binning, penalty, optimum,
    189                                      optWidths, optOrder, optThresh, iter, rej, sys, maskVal,
    190                                      maskBad, maskPoor, poorFrac, badFrac, subMode);
    191     }
     362                                     spacing, threshold, detections ? detections->allSources : NULL,
     363                                     data->stamps, type, size, order, widths, orders, inner, ringsOrder,
     364                                     binning, penalty, optimum, optWidths, optOrder, optThresh, iter, rej,
     365                                     normFrac, sysErr, skyErr, kernelErr, covarFrac,
     366                                     maskVal, maskBad, maskPoor, poorFrac, badFrac, subMode);
     367    }
     368
     369# ifdef TESTING
     370    // XXX for testing
     371    psphotSaveImage (NULL, refRO->image,    "refRO.im.fits");
     372    psphotSaveImage (NULL, refRO->variance, "refRO.wt.fits");
     373    psphotSaveImage (NULL, refRO->mask,     "refRO.mk.fits");
     374
     375    psphotSaveImage (NULL, inRO->image,    "inRO.im.fits");
     376    psphotSaveImage (NULL, inRO->variance, "inRO.wt.fits");
     377    psphotSaveImage (NULL, inRO->mask,     "inRO.mk.fits");
     378
     379    psphotSaveImage (NULL, inConv->image,    "inConv.im.fits");
     380    psphotSaveImage (NULL, inConv->variance, "inConv.wt.fits");
     381    psphotSaveImage (NULL, inConv->mask,     "inConv.mk.fits");
     382
     383    psphotSaveImage (NULL, refConv->image,    "refConv.im.fits");
     384    psphotSaveImage (NULL, refConv->variance, "refConv.wt.fits");
     385    psphotSaveImage (NULL, refConv->mask,     "refConv.mk.fits");
     386# endif
    192387
    193388    psFree(optWidths);
    194     pmSubtractionThreadsFinalize(inRO, refRO);
     389    pmSubtractionThreadsFinalize();
    195390
    196391    if (!success) {
     
    207402            return true;
    208403        } else {
    209             psError(PS_ERR_UNKNOWN, false, "Unable to match images.");
     404            psError(PPSUB_ERR_DATA, false, "Unable to match images.");
    210405            return false;
    211406        }
     
    260455    pmConceptsCopyFPA(refConv->parent->parent->parent, refRO->parent->parent->parent, true, true);
    261456
    262     psImageCovarianceTransfer(inConv->variance, inConv->covariance);
    263     psImageCovarianceTransfer(refConv->variance, refConv->covariance);
     457    if (inConv->covariance) {
     458        psImageCovarianceTruncate(inConv->covariance, COVAR_FRAC);
     459    }
     460    if (refConv->covariance) {
     461        psImageCovarianceTruncate(refConv->covariance, COVAR_FRAC);
     462    }
     463
     464    if (inConv->variance) {
     465        psImageCovarianceTransfer(inConv->variance, inConv->covariance);
     466    }
     467    if (refConv->variance) {
     468        psImageCovarianceTransfer(refConv->variance, refConv->covariance);
     469    }
    264470
    265471    return true;
  • branches/simtest_nebulous_branches/ppSub/src/ppSubReadoutInverse.c

    r24255 r27840  
    2020    invRO->variance = psMemIncrRefCounter(outRO->variance);
    2121    invRO->covariance = psMemIncrRefCounter(outRO->covariance);
     22    invRO->analysis = psMetadataCopy(invRO->analysis, outRO->analysis);
    2223
    2324    invRO->data_exists = invRO->parent->data_exists = invRO->parent->parent->data_exists = true;
     
    3435    pmHDU *invHDU = invFPA->hdu;          // Inverse HDU
    3536    if (!pmAstromWriteWCS(invHDU->header, outFPA, outChip, WCS_TOLERANCE)) {
    36         psError(PS_ERR_UNKNOWN, false, "Unable to write WCS astrometry to PPSUB.INVERSE.");
     37        psError(psErrorCodeLast(), false, "Unable to write WCS astrometry to PPSUB.INVERSE.");
    3738        return false;
    3839    }
    3940    // Read from newly written astrometry so that it exists in the "inverse" FPA (for sources)
    4041    if (!pmAstromReadWCS(invFPA, invChip, invHDU->header, 1.0)) {
    41         psError(PS_ERR_UNKNOWN, false, "Unable to read WCS astrometry.");
     42        psError(psErrorCodeLast(), false, "Unable to read WCS astrometry.");
    4243        return false;
    4344    }
  • branches/simtest_nebulous_branches/ppSub/src/ppSubReadoutJpeg.c

    r23740 r27840  
    3333    pmReadout *ro1 = pmReadoutAlloc(cell1), *ro2 = pmReadoutAlloc(cell2); // Binned readouts
    3434    if (!pmReadoutRebin(ro1, outRO, maskBad, bin1, bin1)) {
    35         psError(PS_ERR_UNKNOWN, false, "Unable to bin output (1st binning)");
     35        psError(PPSUB_ERR_DATA, false, "Unable to bin output (1st binning)");
    3636        psFree(ro1);
    3737        psFree(ro2);
     
    3939    }
    4040    if (!pmReadoutRebin(ro2, ro1, 0, bin2, bin2)) {
    41         psError(PS_ERR_UNKNOWN, false, "Unable to bin output (2nd binning)");
     41        psError(PPSUB_ERR_DATA, false, "Unable to bin output (2nd binning)");
    4242        psFree(ro1);
    4343        psFree(ro2);
     
    4949    return true;
    5050}
     51
     52bool ppSubResidualSampleJpeg(pmConfig *config)
     53{
     54    return true;
     55
     56    pmFPAview *view = ppSubViewReadout(); // View to readout
     57
     58    // we save sample difference stamps on the convolved image readout->analysis metadata
     59    pmReadout *inConv = pmFPAfileThisReadout(config->files, view, "PPSUB.INPUT.CONV"); // Input convolved
     60
     61    psArray *samples = psArrayAllocEmpty(16); // Array of sample stamp images
     62
     63    // we may have multiple entries with the same name; pull them off into a separate array:
     64    psString regex = NULL;          // Regular expression
     65    psStringAppend(&regex, "^%s$", "SUBTRACTION.SAMPLE.STAMP.SET");
     66    psMetadataIterator *iter = psMetadataIteratorAlloc(inConv->analysis, PS_LIST_HEAD, regex); // Iterator
     67    psFree(regex);
     68
     69    psMetadataItem *item = NULL;// Item from iteration
     70    while ((item = psMetadataGetAndIncrement(iter))) {
     71        assert(item->type == PS_DATA_ARRAY);
     72        psArray *sampleStamps = item->data.V;
     73        samples = psArrayAdd(samples, 16, sampleStamps);
     74    }
     75    psFree(iter);
     76    psAssert (samples, "no sample stamps?");
     77    psAssert (samples->n, "no sample stamps?");
     78
     79    // get the kernel sizes
     80    psArray *kernels = samples->data[0];
     81    psAssert (kernels, "no valid kernel?");
     82    psAssert (kernels->n, "no valid kernel?");
     83
     84    psImage *kernel = kernels->data[0];
     85    psAssert (kernel, "missing valid kernel?");
     86
     87    int DX = kernel->numCols;
     88    int DY = kernel->numRows;
     89
     90    // each array contains up to 9 sample stamps.  generate an image mosaicking these together in 3x3 blocks.
     91    int innerBorder = 1;
     92    int outerBorder = 2;
     93    int NXblock = sqrt(samples->n);
     94    int NYblock = samples->n / NXblock;
     95    if (samples->n % NXblock) NYblock ++;
     96
     97    int NXpix = NXblock * (3 * (DX + innerBorder) + outerBorder);
     98    int NYpix = NYblock * (3 * (DY + innerBorder) + outerBorder);
     99
     100    // output cell
     101    pmCell *cell = pmFPAfileThisCell(config->files, view, "PPSUB.OUTPUT.RESID.JPEG");
     102    pmReadout *readout = pmReadoutAlloc(cell);
     103    readout->image = psImageAlloc(NXpix, NYpix, PS_TYPE_F32);
     104
     105    cell->data_exists = true;
     106    cell->parent->data_exists = true;
     107
     108    psImageInit (readout->image, 0.0);
     109
     110    for (int i = 0; i < samples->n; i++) {
     111
     112        int xBlock = i % NXblock;
     113        int yBlock = i / NYblock;
     114
     115        psArray *kernels = samples->data[i];
     116
     117        for (int j = 0; j < kernels->n; j++) {
     118
     119            psImage *kernel = kernels->data[j];
     120
     121            int xSub = j % 3;
     122            int ySub = j / 3;
     123
     124            int xPix = xBlock * (3 * (DX + innerBorder) + outerBorder) + xSub * (DX + innerBorder);
     125            int yPix = yBlock * (3 * (DX + innerBorder) + outerBorder) + ySub * (DY + innerBorder);
     126
     127            for (int y = 0; y < kernel->numRows; y++) {
     128                for (int x = 0; x < kernel->numCols; x++) {
     129                    readout->image->data.F32[y + yPix][x + xPix] = kernel->data.F32[y][x];
     130                }
     131            }
     132        }
     133    }
     134
     135    {
     136        psFits *fits = psFitsOpen ("resid.stamps.fits", "w");
     137        psFitsWriteImage (fits, NULL, readout->image, 0, NULL);
     138        psFitsClose (fits);
     139    }
     140
     141    return true;
     142}
  • branches/simtest_nebulous_branches/ppSub/src/ppSubReadoutPhotometry.c

    r24932 r27840  
    2424bool ppSubReadoutPhotometry(const char *name, ppSubData *data)
    2525{
     26    bool mdok = false;
     27
    2628    psAssert(data, "Require processing data");
    2729    pmConfig *config = data->config;    // Configuration
     
    4244    }
    4345
    44     // The PSF (measured in ppSubMakePSF) is stored on the chip->analysis of PSPHOT.INPUT
    45     // In order to use an incoming PSF, it must be stored on the chip->analysis of PSPHOT.PSF.LOAD
     46    // select the view of interest
    4647    pmFPAview *view = ppSubViewReadout(); // View to readout
    47     pmChip *psfInputChip = pmFPAfileThisChip(config->files, view, "PSPHOT.INPUT"); // Chip with PSF
    48     psAssert (psfInputChip, "should have been generated for ppSubMakePSF");
    49     pmChip *psfLoadChip = pmFPAfileThisChip(config->files, view, "PSPHOT.PSF.LOAD"); // Chip to have PSF
    50     psAssert (psfLoadChip, "PSPHOT.PSF.LOAD should have been defined in ppSubCamera");
    51     pmPSF *psf = psMetadataLookupPtr(NULL, psfInputChip->analysis, "PSPHOT.PSF"); // PSF for photometry
    52     if (!psf) {
    53         psErrorStackPrint(stderr, "No PSF available");
    54         psWarning("No PSF available --- suspect bad data quality.");
    55         ppSubDataQuality(data, psErrorCodeLast(), PPSUB_FILES_PHOT_SUB | PPSUB_FILES_PHOT_INV);
    56         return true;
    57     }
    58     psMetadataAddPtr(psfLoadChip->analysis, PS_LIST_TAIL, "PSPHOT.PSF", PS_DATA_UNKNOWN | PS_META_REPLACE,
    59                      "PSF from ppSubMakePSF", psf);
    60 
    61     bool mdok = false;
    6248
    6349    // psphotReadoutMinimal performs the photometry analysis on PSPHOT.INPUT; we need to move
    64     // around the pointers so PSPHOT.INPUT corresponds to the output image; previously, it was
    65     // equivalent to the minuend image.
    66     pmReadout *inRO = pmFPAfileThisReadout(config->files, view, name); // Readout with image and sources
    67     if (psMetadataLookup(inRO->analysis, "PSPHOT.SOURCES")) {
    68         psMetadataRemoveKey(inRO->analysis, "PSPHOT.SOURCES");
    69     }
    70 
     50    // around the pointers so PSPHOT.INPUT corresponds to the output image of interest (on one
     51    // pass this is the subtraction image, in another it is negative of the subtraction
    7152    pmFPAfile *photFile = psMetadataLookupPtr(&mdok, config->files, "PSPHOT.INPUT"); // Photometry file
    7253    pmFPAfile *inFile = psMetadataLookupPtr(&mdok, config->files, name); // Input file
    7354    if (!pmFPACopy(photFile->fpa, inFile->fpa)) {
    74         psError(PS_ERR_UNKNOWN, false, "Unable to copy FPA for photometry");
     55        psError(PPSUB_ERR_CONFIG, false, "Unable to copy FPA for photometry");
    7556        psFree(view);
    7657        return false;
    7758    }
     59
     60    // drop references to PSPHOT.DETECTIONS on both of these  (why is this needed for both??)
    7861    pmReadout *photRO = pmFPAviewThisReadout(view, photFile->fpa); // Readout to photometer
    79     if (psMetadataLookup(photRO->analysis, "PSPHOT.SOURCES")) {
    80         psMetadataRemoveKey(photRO->analysis, "PSPHOT.SOURCES");
     62    if (psMetadataLookup(photRO->analysis, "PSPHOT.DETECTIONS")) {
     63        psMetadataRemoveKey(photRO->analysis, "PSPHOT.DETECTIONS");
     64    }
     65    pmReadout *inRO = pmFPAfileThisReadout(config->files, view, name); // Readout with image and sources
     66    if (psMetadataLookup(inRO->analysis, "PSPHOT.DETECTIONS")) {
     67        psMetadataRemoveKey(inRO->analysis, "PSPHOT.DETECTIONS");
    8168    }
    8269
    83     psMetadataAddPtr(photRO->parent->parent->analysis, PS_LIST_TAIL, "PSPHOT.PSF",
    84                      PS_META_REPLACE | PS_DATA_UNKNOWN, "Point-spread function", data->psf);
     70    // grab the PSF information from the pmFPAfile PSPHOT.PSF.LOAD
     71    pmFPAfile *psfFile = psMetadataLookupPtr(&mdok, config->files, "PSPHOT.PSF.LOAD"); // PSF file
     72    ppSubCopyPSF (photFile, psfFile, view);
    8573
    86     psFree(photRO->analysis);
    87     photRO->analysis = psMetadataAlloc();
     74    // psphotSaveImage (photFile->fpa->hdu->header, photRO->image, "findsrc.im.fits");
     75    // psphotSaveImage (photFile->fpa->hdu->header, photRO->variance, "findsrc.wt.fits");
     76    // psphotSaveImage (photFile->fpa->hdu->header, photRO->mask, "findsrc.mk.fits");
     77
     78    // erase the overlays from a previous psphot-related step
     79    if (pmVisualIsVisual()) {
     80        //      psphotVisualEraseOverlays (1, "all");
     81    }
    8882
    8983    if (!psphotReadoutMinimal(config, view)) {
     
    9690
    9791    // If no sources were found, there's no error,  but we want to trigger 'bad quality'
    98     psArray *sources = psMetadataLookupPtr(NULL, photRO->analysis, "PSPHOT.SOURCES"); // Sources
    99     if (!sources) {
     92    pmDetections *detections = psMetadataLookupPtr(NULL, photRO->analysis, "PSPHOT.DETECTIONS"); // Sources
     93    if (!detections) {
    10094        ppSubDataQuality(data, PSPHOT_ERR_DATA, PPSUB_FILES_PHOT_SUB | PPSUB_FILES_PHOT_INV);
    10195    }
     96    psArray *sources = detections->allSources;
     97    psAssert (sources, "missing sources?");
    10298
    10399    if (data->stats) {
     
    114110
    115111    if (!data->quality) {
    116         if (!psMetadataCopySingle(inRO->analysis, photRO->analysis, "PSPHOT.SOURCES")) {
    117             psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to copy PSPHOT.SOURCES");
     112        if (!psMetadataCopySingle(inRO->analysis, photRO->analysis, "PSPHOT.DETECTIONS")) {
     113            psError(PPSUB_ERR_PROG, false, "Unable to copy PSPHOT.DETECTIONS");
    118114            return false;
    119115        }
    120116        if (!psMetadataCopySingle(inRO->analysis, photRO->analysis, "PSPHOT.HEADER")) {
    121             psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to copy PSPHOT.HEADER");
     117            psError(PPSUB_ERR_PROG, false, "Unable to copy PSPHOT.HEADER");
    122118            return false;
     119        }
     120        if (!psMetadataCopySingle(inRO->analysis, photRO->analysis, PM_DETEFF_ANALYSIS)) {
     121            psError(PPSUB_ERR_PROG, false, "Unable to copy Detection Efficiency");
     122            return false;
     123        }
     124
     125        // Ensure photometry information is put in the header
     126        pmHDU *hdu = pmHDUFromReadout(inRO); // HDU for readout
     127        if (hdu) {
     128            psMetadata *photHeader = psMetadataLookupMetadata(NULL, inRO->analysis, "PSPHOT.HEADER"); // Header
     129            hdu->header = psMetadataCopy(hdu->header, photHeader);
    123130        }
    124131    }
     
    130137}
    131138
    132 
    133 
    134 
    135 
    136139#ifdef TESTING
    137140    // Record data about sources: not everything gets into the output CMF files
    138141    {
    139142        pmReadout *photRO = pmFPAviewThisReadout(view, photFile->fpa); // Readout with the sources
    140         psArray *sources = psMetadataLookupPtr(NULL, photRO->analysis, "PSPHOT.SOURCES"); // Sources
     143        pmDetections *detections = psMetadataLookupPtr(NULL, photRO->analysis, "PSPHOT.DETECTIONS"); // Sources
     144        psArray *sources = detections->allSources;
    141145        FILE *sourceFile = fopen("sources.dat", "w"); // File for sources
    142146        fprintf(sourceFile,
  • branches/simtest_nebulous_branches/ppSub/src/ppSubReadoutStats.c

    r23939 r27840  
    2323    pmFPAfile *output = psMetadataLookupPtr(NULL, config->files, "PPSUB.OUTPUT"); // Output file
    2424    if (!output) {
    25         psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find file PPSUB.OUTPUT.\n");
     25        psError(PPSUB_ERR_PROG, true, "Unable to find file PPSUB.OUTPUT.\n");
    2626        return false;
    2727    }
  • branches/simtest_nebulous_branches/ppSub/src/ppSubReadoutSubtract.c

    r24862 r27840  
    7171    pmFPA *outFPA = outFile->fpa;       // Output FPA
    7272    if (!pmConceptsCopyFPA(outFPA, inFPA, true, true)) {
    73         psError(PS_ERR_UNKNOWN, false, "Unable to copy concepts from input to output.");
     73        psError(PPSUB_ERR_CONFIG, false, "Unable to copy concepts from input to output.");
    7474        psFree(outRO);
    7575        psFree(view);
     
    8484    psFree(view);
    8585    if (!outHDU || !inHDU) {
    86         psError(PS_ERR_UNKNOWN, false, "Unable to find HDU at FPA level to copy astrometry.");
     86        psError(PPSUB_ERR_PROG, true, "Unable to find HDU at FPA level to copy astrometry.");
    8787        return false;
    8888    }
    8989    if (!pmAstromReadWCS(outFPA, outChip, inHDU->header, 1.0)) {
    90         psError(PS_ERR_UNKNOWN, false, "Unable to read WCS astrometry from input FPA.");
     90        psError(psErrorCodeLast(), false, "Unable to read WCS astrometry from input FPA.");
    9191        return false;
    9292    }
    9393    if (!pmAstromWriteWCS(outHDU->header, outFPA, outChip, WCS_TOLERANCE)) {
    94         psError(PS_ERR_UNKNOWN, false, "Unable to write WCS astrometry to output FPA.");
     94        psError(psErrorCodeLast(), false, "Unable to write WCS astrometry to output FPA.");
    9595        return false;
    9696    }
  • branches/simtest_nebulous_branches/ppSub/src/ppSubSetMasks.c

    r23740 r27840  
    2828    psImageMaskType maskValue, markValue; // Mask values
    2929    if (!pmConfigMaskSetBits(&maskValue, &markValue, config)) {
    30         psError(PS_ERR_UNKNOWN, false, "Unable to determine mask value.");
     30        psError(PPSUB_ERR_CONFIG, false, "Unable to determine mask value.");
    3131        return false;
    3232    }
    3333
    3434    // Set the mask bits needed by psphot (in psphot recipe)
    35     psphotSetMaskRecipe (config, maskValue, markValue);
     35    psphotSetMaskRecipe(config, maskValue, markValue);
    3636
    3737    // Look up recipe values
     
    7979    // Mask the NAN values
    8080    if (!pmReadoutMaskNonfinite(inRO, satValue)) {
    81         psError(PS_ERR_UNKNOWN, false, "Unable to mask non-finite pixels in input.");
     81        psError(PPSUB_ERR_DATA, false, "Unable to mask non-finite pixels in input.");
    8282        return false;
    8383    }
    8484    if (!pmReadoutMaskNonfinite(refRO, satValue)) {
    85         psError(PS_ERR_UNKNOWN, false, "Unable to mask non-finite pixels in reference.");
     85        psError(PPSUB_ERR_DATA, false, "Unable to mask non-finite pixels in reference.");
    8686        return false;
    8787    }
     
    9494    psImageInterpolateMode interpMode = psImageInterpolateModeFromString(interpModeStr); // Interp
    9595    if (interpMode == PS_INTERPOLATE_NONE) {
    96         psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Unknown interpolation mode: %s", interpModeStr);
     96        psError(PPSUB_ERR_CONFIG, false, "Unknown interpolation mode: %s", interpModeStr);
    9797        return false;
    9898    }
     
    104104    // Interpolate over bad pixels, so the bad pixels don't explode
    105105    if (!pmReadoutInterpolateBadPixels(inRO, maskVal, interpMode, poorFrac, maskPoor, maskBad)) {
    106         psError(PS_ERR_UNKNOWN, false, "Unable to interpolate bad pixels for input image.");
     106        psError(PPSUB_ERR_DATA, false, "Unable to interpolate bad pixels for input image.");
    107107        return false;
    108108    }
    109109    if (!pmReadoutInterpolateBadPixels(refRO, maskVal, interpMode, poorFrac, maskPoor, maskBad)) {
    110         psError(PS_ERR_UNKNOWN, false, "Unable to interpolate bad pixels for reference image.");
     110        psError(PPSUB_ERR_DATA, false, "Unable to interpolate bad pixels for reference image.");
    111111        return false;
    112112    }
  • branches/simtest_nebulous_branches/ppSub/src/ppSubThreshold.c

    r24862 r27840  
    2727    psImageMaskType maskIgnore,         // Ignore pixels with this mask
    2828    psImageMaskType maskThresh,         // Give pixels this mask if below threshold
     29    psRegion *region,                   // Region of interest
    2930    const char *description             // Description of image
    3031    )
     
    3738    psImage *image = ro->image;         // Image
    3839    psImage *mask = ro->mask;           // Mask
    39     int numCols = ro->image->numCols, numRows = ro->image->numRows; // Size of image
     40
     41    psImage *subImage = psImageSubset(image, *region); // Image with region of interest
     42    psImage *subMask = psImageSubset(mask, *region);  // Maks with region of interest
    4043
    4144    psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV); // Statistics
    4245    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS);                               // Random number generator
    43     if (!psImageBackground(stats, NULL, image, mask, maskIgnore, rng)) {
    44         psError(PS_ERR_UNKNOWN, false, "Unable to determine threshold.");
     46    if (!psImageBackground(stats, NULL, subImage, subMask, maskIgnore, rng)) {
     47        psError(PPSUB_ERR_DATA, false, "Unable to determine threshold.");
    4548        psFree(rng);
    4649        psFree(stats);
     
    4952    psFree(rng);
    5053
     54    psFree(subImage);
     55    psFree(subMask);
     56
    5157    float threshold = stats->robustMedian - thresh * stats->robustStdev; // Threshold below which to clip
    5258    psFree(stats);
    5359    psLogMsg("ppSub", PS_LOG_INFO, "Masking pixels below %f in %s", threshold, description);
    5460
    55     for (int y = 0; y < numRows; y++) {
    56         for (int x = 0; x < numCols; x++) {
     61    for (int y = region->y0; y < region->y1; y++) {
     62        for (int x = region->x0; x < region->x1; x++) {
    5763            if (mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & maskIgnore) {
    5864                continue;
     
    9197    pmReadout *in = pmFPAfileThisReadout(config->files, view, "PPSUB.INPUT.CONV"); // Input image
    9298    if (!in) {
    93         psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find readout.");
    94         return false;
    95     }
    96     if (!lowThreshold(in, thresh, maskVal, maskThresh, "input convolved image")) {
    97         psError(PS_ERR_UNKNOWN, false, "Unable to threshold input image.");
     99        psError(PPSUB_ERR_UNKNOWN, false, "Unable to find readout.");
    98100        return false;
    99101    }
     
    101103    pmReadout *ref = pmFPAfileThisReadout(config->files, view, "PPSUB.REF.CONV"); // Reference image
    102104    if (!ref) {
    103         psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find readout.");
     105        psError(PPSUB_ERR_UNKNOWN, false, "Unable to find readout.");
    104106        return false;
    105107    }
    106     if (!lowThreshold(ref, thresh, maskVal, maskThresh, "reference convolved image")) {
    107         psError(PS_ERR_UNKNOWN, false, "Unable to threshold input image.");
    108         return false;
     108
     109    psMetadataIterator *regIter = psMetadataIteratorAlloc(in->analysis, PS_LIST_HEAD,
     110                                                          "^" PM_SUBTRACTION_ANALYSIS_REGION "$");
     111    psMetadataItem *regItem;        // Item with region
     112    while ((regItem = psMetadataGetAndIncrement(regIter))) {
     113        psAssert(regItem->type == PS_DATA_REGION && regItem->data.V, "Expect region type");
     114        psRegion *region = regItem->data.V; // Region of interest
     115        if (!lowThreshold(in, thresh, maskVal, maskThresh, region, "input convolved image")) {
     116            psError(psErrorCodeLast(), false, "Unable to threshold input image.");
     117            return false;
     118        }
     119        if (!lowThreshold(ref, thresh, maskVal, maskThresh, region, "reference convolved image")) {
     120            psError(psErrorCodeLast(), false, "Unable to threshold input image.");
     121            return false;
     122        }
    109123    }
     124    psFree(regIter);
    110125
    111126    psFree(view);
  • branches/simtest_nebulous_branches/ppSub/src/ppSubVarianceRescale.c

    r24672 r27840  
    2828    bool mdok; // Status of metadata lookups
    2929
    30     psMetadata *ppSubRecipe = psMetadataLookupPtr(NULL, config->recipes, PPSUB_RECIPE); // Recipe for ppSub
    31     psAssert(ppSubRecipe, "Need PPSUB recipe");
     30    psMetadata *recipe = psMetadataLookupPtr(NULL, config->recipes, PPSUB_RECIPE); // Recipe for ppSub
     31    psAssert(recipe, "Need PPSUB recipe");
    3232
    33     if (!psMetadataLookupBool(&mdok, ppSubRecipe, "VARIANCE.RESCALE")) return true;
     33    if (!psMetadataLookupBool(&mdok, recipe, "RENORM")) return true;
     34
     35    int num = psMetadataLookupS32(&mdok, recipe, "RENORM.NUM");
     36    if (!mdok) {
     37        psError(PPSUB_ERR_ARGUMENTS, true, "RENORM.NUM is not set in the recipe");
     38        return false;
     39    }
     40    float minValid = psMetadataLookupF32(&mdok, recipe, "RENORM.MIN");
     41    if (!mdok) {
     42        psError(PPSUB_ERR_ARGUMENTS, true, "RENORM.MIN is not set in the recipe");
     43        return false;
     44    }
     45    float maxValid = psMetadataLookupF32(&mdok, recipe, "RENORM.MAX");
     46    if (!mdok) {
     47        psError(PPSUB_ERR_ARGUMENTS, true, "RENORM.MAX is not set in the recipe");
     48        return false;
     49    }
    3450
    3551    psImageMaskType maskBad = pmConfigMaskGet("BLANK", config); // Bits to mask
    3652
    3753    pmFPAview *view = ppSubViewReadout(); // View to readout
    38     pmReadout *outRO = pmFPAfileThisReadout(config->files, view, "PPSUB.OUTPUT"); // Output image
     54    pmReadout *readout = pmFPAfileThisReadout(config->files, view, "PPSUB.OUTPUT"); // Output image
    3955
    40     psImage *image    = outRO->image;    // Image of interest
    41     psImage *variance = outRO->variance; // Variance image
    42     psImage *mask     = outRO->mask;     // Mask of interest
    43 
    44     psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS);
    45 
    46     psLogMsg("psLib.psImageBackground", PS_LOG_DETAIL, "Generating the signal-to-noise image");
    47 
    48     // generate an image representing the signal/noise:
    49     psImage *SN = psImageCopy (NULL, outRO->image, PS_TYPE_F32);
    50 
    51     int nx = image->numCols; // Size of image
    52     int ny = image->numRows; // Size of image
    53 
    54     for (int y = 0; y < ny; y++) {
    55         for (int x = 0; x < nx; x++) {
    56             if (mask && mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & maskBad) {
    57                 SN->data.F32[y][x] = 0.0;
    58                 continue;
    59             }
    60             if (!isfinite(image->data.F32[y][x])) {
    61                 SN->data.F32[y][x] = 0.0;
    62                 continue;
    63             }
    64             if (!isfinite(variance->data.F32[y][x]) || (variance->data.F32[y][x] < 0.0)) {
    65                 SN->data.F32[y][x] = 0.0;
    66                 continue;
    67             }
    68             SN->data.F32[y][x] = image->data.F32[y][x] / sqrt(variance->data.F32[y][x]);
    69         }
     56    if (!readout->variance) {
     57        // Nothing to renormalise
     58        psWarning("Renormalisation of the variance requested, but no variance provided.");
     59        return true;
    7060    }
    7161
    72     // these should not be chosen by the user: only a ROBUST version makes sense
    73     psStats *stats = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);
    74 
    75     int Nsubset = psMetadataLookupS32(&mdok, ppSubRecipe, "VARIANCE.RESCALE.NSAMPLE");
    76     psAssert (mdok, "missing VARIANCE.RESCALE.NSAMPLE in ppSub recipe");
    77    
    78     const int Npixels = nx*ny; // Total number of pixels
    79     Nsubset = PS_MIN(Nsubset, Npixels); // Number of pixels in subset
    80     psLogMsg("psLib.psImageBackground", PS_LOG_DETAIL, "Searching for %d pixels in S/N image", Nsubset);
    81 
    82     psVector *values = psVectorAllocEmpty(Nsubset, PS_TYPE_F32); // Vector containing subsample
    83 
    84     // Minimum and maximum values
    85     float min = +PS_MAX_F32;
    86     float max = -PS_MAX_F32;
    87 
    88     // select a subset of the image pixels to measure the stats
    89     long n = 0;                         // Number of actual pixels in subset
    90     if (Nsubset >= Npixels) {
    91         // if we have an image smaller than Nsubset, just loop over the image pixels
    92         for (int iy = 0; iy < ny; iy++) {
    93             for (int ix = 0; ix < nx; ix++) {
    94                 if (!isfinite(image->data.F32[iy][ix]) || (mask && mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & maskBad)) {
    95                     continue;
    96                 }
    97 
    98                 float value = SN->data.F32[iy][ix];
    99                 min = PS_MIN(value, min);
    100                 max = PS_MAX(value, max);
    101                 values->data.F32[n] = value;
    102                 n++;
    103             }
    104         }
    105     } else {
    106         for (long i = 0; i < Nsubset; i++) {
    107             double frnd = psRandomUniform(rng);
    108             int pixel = Npixels * frnd;
    109             int ix = pixel % nx;
    110             int iy = pixel / nx;
    111 
    112             if (!isfinite(image->data.F32[iy][ix]) || (mask && mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & maskBad)) {
    113                 continue;
    114             }
    115 
    116             float value = SN->data.F32[iy][ix];
    117             min = PS_MIN(value, min);
    118             max = PS_MAX(value, max);
    119             values->data.F32[n] = value;
    120             n++;
    121         }
    122     }
    123     if (n < 0.01*Nsubset) {
    124         psLogMsg("psLib.psImageBackground", PS_LOG_DETAIL, "Unable to measure image background: too few data points (%ld)", n);
    125         psFree(values);
    126         return false;
    127     }
    128     values->n = n;
    129     psFree (SN);
    130 
    131     psLogMsg("psLib.psImageBackground", PS_LOG_DETAIL, "Using for %ld pixels in S/N image", values->n);
    132 
    133     if (!psVectorStats (stats, values, NULL, NULL, 0)) {
    134         if (psTraceGetLevel("psLib.imageops") >= 5) {
    135             FILE *f = fopen ("vector.dat", "w");
    136             int fd = fileno(f);
    137             p_psVectorPrint (fd, values, "values");
    138             fclose (f);
    139         }
    140         psError(PS_ERR_UNKNOWN, false, "Unable to measure statistics for image background "
    141                 "(%dx%d, (row0,col0) = (%d,%d)",
    142                 image->numRows, image->numCols, image->row0, image->col0);
    143         psFree(values);
    144         return false;
    145     }
    146     if (psTraceGetLevel("psLib.imageops") >= 6) {
    147         FILE *f = fopen ("vector.dat", "w");
    148         int fd = fileno(f);
    149         p_psVectorPrint (fd, values, "values");
    150         fclose (f);
    151     }
    152     psFree (values);
    153     psLogMsg ("ppSub", PS_LOG_INFO, "background stdev %f\n", stats->robustStdev);
    154 
    155     float minValid = psMetadataLookupF32(&mdok, ppSubRecipe, "VARIANCE.RESCALE.MIN.VALID");
    156     psAssert (mdok, "missing VARIANCE.RESCALE.MIN.VALID in ppSub recipe");
    157 
    158     float maxValid = psMetadataLookupF32(&mdok, ppSubRecipe, "VARIANCE.RESCALE.MAX.VALID");
    159     psAssert (mdok, "missing VARIANCE.RESCALE.MAX.VALID in ppSub recipe");
    160 
    161     psLogMsg("psLib.psImageBackground", PS_LOG_DETAIL, "Stdev of S/N image: %f (mean: %f)", stats->robustStdev, stats->robustMedian);
    162 
    163     // valid range of correction; 0.66 to 1.5 (skip if in range 0.98 to 1.02)
    164     if ((stats->robustStdev < minValid) || (stats->robustStdev > maxValid)) {
    165         psWarning ("background stdev (%f) is out of allowed range; not correcting\n", stats->robustStdev);
    166         // XXX set quality to poor
    167         psFree (stats);
    168         return true;
    169     }
    170 
    171     // valid range of correction; 0.66 to 1.5 (skip if in range 0.98 to 1.02)
    172     // if ((stats->robustStdev > 0.98) && (stats->robustStdev > 1.02)) {
    173     //  psLogMsg ("ppSub", PS_LOG_INFO, "background stdev (%f) is close to 1.0; do not modify variance\n", stats->robustStdev);
    174     //  // XXX set quality to poor
    175     //  psFree (stats);
    176     //  return true;
    177     // }
    178 
    179     float varianceFactor = PS_SQR(stats->robustStdev);
    180     psLogMsg ("ppSub", PS_LOG_INFO, "background stdev is not 1.0: multiplying variance by %f\n", varianceFactor);
    181     for (int y = 0; y < ny; y++) {
    182         for (int x = 0; x < nx; x++) {
    183             if (mask && mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & maskBad) {
    184                 continue;
    185             }
    186             if (!isfinite(image->data.F32[y][x])) {
    187                 continue;
    188             }
    189             if (!isfinite(variance->data.F32[y][x]) || (variance->data.F32[y][x] < 0.0)) {
    190                 continue;
    191             }
    192             variance->data.F32[y][x] *= varianceFactor;
    193         }
    194     }
    195 
    196     pmFPA *outFPA = outRO->parent->parent->parent;
    197     pmHDU *outHDU = outFPA->hdu;        // Output HDU
    198 
    199     char history[80];
    200     snprintf (history, 80, "Rescaled variance by %6.4f (stdev by %6.4f)", varianceFactor, stats->robustStdev);
    201     psMetadataAddStr(outHDU->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, NULL, history);
    202 
    203     psFree (stats);
    204     return true;
     62    return pmReadoutVarianceRenormalise(readout, maskBad, num, minValid, maxValid);
    20563}
Note: See TracChangeset for help on using the changeset viewer.