IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 18011


Ignore:
Timestamp:
Jun 8, 2008, 4:03:31 PM (18 years ago)
Author:
eugene
Message:

update from changes on eam_branch_20080511 : adding photometry of fake sources, force photometry; major cleanups

Location:
trunk/ppSim
Files:
10 added
23 edited

Legend:

Unmodified
Added
Removed
  • trunk/ppSim/configure.ac

    r14186 r18011  
    1717AC_SYS_LARGEFILE
    1818
    19 PKG_CHECK_MODULES([PSLIB], [pslib >= 1.0.0])
     19PKG_CHECK_MODULES([PSLIB],    [pslib >= 1.0.0])
    2020PKG_CHECK_MODULES([PSMODULE], [psmodules >= 1.0.0])
    21 PKG_CHECK_MODULES([PSASTRO], [psastro >= 0.9.0])
     21PKG_CHECK_MODULES([PSPHOT],   [psphot >= 0.8.0])
     22PKG_CHECK_MODULES([PSASTRO],  [psastro >= 0.9.0])
    2223
    2324IPP_STDOPTS
  • trunk/ppSim/notes.txt

    r14657 r18011  
     1
     2
     32008.05.17
     4
     5  pmFPAfiles used in ppSim:
     6
     7  PPSIM.INPUT : an input image loaded by ppSim; the simulated features
     8                may be added to this image.  In fact, the features are
     9                generated in the output image, and the two images are
     10                added (as images) together.
     11
     12  PPSIM.OUTPUT  : the output image.  this file is used for the main
     13                  ppSimLoop function
     14
     15  PPSIM.CHIP    : chip-mosaiced version of the output image.  only
     16                  generated if photometry is requested.  Is this
     17                  actually used as an output image?
     18
     19  PPSIM.REAL.SOURCES : real sources loaded by PPSIM.  these sources
     20                       are subtracted from the image before testing
     21                       for the detectability of the fake sources and
     22                       before measuring the flux of fake or forced
     23                       soures.  They should be the sources measured in
     24                       a previous psphot run, though any input list
     25                       could be used.  Results are very ill-defined if
     26                       the sources do not correspond to actual image
     27                       sources!
     28
     29  PSPHOT.PSF.LOAD : input PSF model used to measure the input sources
     30
     31  PPSIM.SOURCES : output fake sources (injected fake sources with real values)
     32  PPSIM.FAKE.SOURCES : output fake photometry (measured photometry for all fake sources)
     33  PPSIM.FORCE.SOURCES : output force photometry
     34 
     35  ** used within psphot functions:
     36  PSPHOT.BACKMDL : model background generated by psphotModelBackground
     37  PSPHOT.BACKMDL.STDEV : model background error generated by psphotModelBackground
     38  PSPHOT.BACKGND : full-scale model background generated by psphotSubtractBackground
     39  PSPHOT.BACKSUB : background-subtracted image
     40
     412008.05.15
     42
     43  For fake and force photometry, we need to load the known existing
     44  sources, then perform a complete linear fit solution to the complete
     45  set of both real (known) sources plus the fake and/or forced
     46  photometry positions (as PSFs).  The fake and forced photometry
     47  positions need to be measured independently.  This provides the real
     48  photometry for these sources ** in the presence of the other real
     49  sources **.  In order to test the detectability of the fake sources
     50  (or the forced sources, for that matter), we need to generate the
     51  smoothed detection image, and determine the peak value at the
     52  positions of the sources. 
     53
     54  ppSimPhotomReadout outline:
     55
     56  * we have three source lists (loaded before the function is called):
     57    * realSources : these are loaded from a CMF-style file (or equiv)
     58    * fakeSources : these are defined internally, and need a link from
     59                    the input fake source to the measured fake source
     60    * forceSources : these are loaded from a DVO database via getstar
     61
     62  * we require a supplied PSF
     63
     64  * need to subtract the background (before or after subtracting the
     65    sources?)
     66
     67  * subtract the real sources
     68  * model the background
     69  * build the detection image
     70  * measure the detectability of the fake and force sources
     71  * replace the real sources
     72
     73  * merge real + fake sources
     74  * linear fit to merged source list
     75  * replace the sources (make 'no-subtract' option?)
     76
     77  * merge real + forced sources
     78  * linear fit to merged source list
     79  * replace the sources (make 'no-subtract' option?)
     80
     81
    182
    283ppSim development work still needed:
  • trunk/ppSim/src/Makefile.am

    r16500 r18011  
    11bin_PROGRAMS = ppSim ppSimSequence
    22
    3 ppSim_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(PSASTRO_CFLAGS) $(ppSim_CFLAGS)
    4 ppSim_LDFLAGS = $(PSLIB_LIBS) $(PSMODULE_LIBS) $(PSASTRO_LIBS)
     3ppSim_CPPFLAGS = $(PSLIB_CFLAGS) $(PSMODULE_CFLAGS) $(PSPHOT_CFLAGS) $(PSASTRO_CFLAGS) $(ppSim_CFLAGS)
     4ppSim_LDFLAGS = $(PSLIB_LIBS) $(PSMODULE_LIBS) $(PSPHOT_LIBS) $(PSASTRO_LIBS)
    55ppSim_SOURCES = \
    6         ppSim.c                 \
    7         ppSimArguments.c        \
    8         ppSimCreate.c           \
    9         ppSimLoadStars.c        \
    10         ppSimMakeStars.c        \
    11         ppSimMakeGalaxies.c     \
    12         ppSimMakeBiassec.c      \
    13         ppSimMakeBias.c         \
    14         ppSimMakeDark.c         \
    15         ppSimMakeSky.c          \
    16         ppSimInsertStars.c      \
    17         ppSimInsertGalaxies.c   \
    18         ppSimAddOverscan.c      \
    19         ppSimAddNoise.c         \
    20         ppSimSaturate.c         \
    21         ppSimBounds.c           \
    22         ppSimStars.c            \
    23         ppSimSetPSF.c           \
    24         ppSimUtils.c            \
    25         ppSimLoop.c             \
     6        ppSim.c                   \
     7        ppSimArguments.c          \
     8        ppSimCreate.c             \
     9        ppSimLoadStars.c          \
     10        ppSimMakeStars.c          \
     11        ppSimMakeGalaxies.c       \
     12        ppSimMakeBiassec.c        \
     13        ppSimMakeBias.c           \
     14        ppSimMakeDark.c           \
     15        ppSimMakeSky.c            \
     16        ppSimInsertStars.c        \
     17        ppSimInsertGalaxies.c     \
     18        ppSimAddOverscan.c        \
     19        ppSimAddNoise.c           \
     20        ppSimSaturate.c           \
     21        ppSimBounds.c             \
     22        ppSimStars.c              \
     23        ppSimSetPSF.c             \
     24        ppSimUtils.c              \
     25        ppSimLoop.c               \
     26        ppSimLoadSpots.c          \
     27        ppSimPhotom.c             \
     28        ppSimPhotomReadoutFake.c  \
     29        ppSimPhotomReadoutForce.c \
     30        ppSimPhotomFiles.c        \
     31        ppSimLoadForceSources.c   \
     32        ppSimMergeReadouts.c      \
     33        ppSimDetections.c         \
     34        ppSimMergeSources.c       \
     35        ppSimMosaicChip.c         \
     36        ppSimRandomGaussian.c     \
    2637        ppSimBadPixels.c
    2738
  • trunk/ppSim/src/ppSim.c

    r17615 r18011  
    11# include "ppSim.h"
     2
     3int failure (pmConfig *config, psExit status, char *message) {
     4    ppSimRandomGaussianFree ();
     5    psErrorStackPrint(stderr, message);
     6    psFree(config);
     7    pmModelClassCleanup();
     8    psLibFinalize();
     9    exit (status);
     10}
    211
    312int main(int argc, char *argv[])
     
    817    pmConfig *config = pmConfigRead(&argc, argv, PPSIM_RECIPE); // Configuration
    918    if (!config) {
    10         psErrorStackPrint(stderr, "Unable to read configurations.");
    11         exit(PS_EXIT_CONFIG_ERROR);
     19        failure (config, PS_EXIT_CONFIG_ERROR, "Unable to read configurations.");
    1220    }
    1321
    14     ppSimArguments(argc, argv, config);
     22    if (!ppSimArguments(argc, argv, config)) {
     23        failure (config, PS_EXIT_CONFIG_ERROR, "Error parsing command-line arguments");
     24    }
    1525
    1626    if (!ppSimCreate(config)) {
    17         psErrorStackPrint(stderr, "Unable to create output file.");
    18         psFree(config);
    19         exit(PS_EXIT_CONFIG_ERROR);
     27        failure (config, PS_EXIT_CONFIG_ERROR, "Unable to create output file.");
    2028    }
    2129
    2230    if (!ppSimLoop(config)) {
    23         psErrorStackPrint(stderr, "Unable to generate data.");
    24         psFree(config);
    25         exit(PS_EXIT_SYS_ERROR);
     31        failure (config, PS_EXIT_SYS_ERROR, "Unable to generate data.");
    2632    }
    2733
     34    ppSimRandomGaussianFree ();
    2835    psFree(config);
    2936    pmModelClassCleanup();
     
    3239    psLibFinalize();
    3340
    34     return PS_EXIT_SUCCESS;
     41    exit (PS_EXIT_SUCCESS);
    3542}
  • trunk/ppSim/src/ppSim.h

    r17557 r18011  
    1313#include <psmodules.h>
    1414#include <psastro.h>
     15#include <psphot.h>
    1516
    1617#define PPSIM_RECIPE "PPSIM"
    17 #define OUTPUT_FILE "PPSIM.OUTPUT"
     18// #define OUTPUT_FILE "PPSIM.OUTPUT"
    1819
    1920// Compare a value with minimum and maximum values, replacing where required.
    20 #define COMPARE(VALUE,MIN,MAX) { \
    21         if (VALUE < MIN) { MIN = VALUE; } \
    22         if (VALUE > MAX) { MAX = VALUE; } \
     21#define COMPARE(VALUE,MIN,MAX) {                \
     22        if (VALUE < MIN) { MIN = VALUE; }       \
     23        if (VALUE > MAX) { MAX = VALUE; }       \
    2324    }
    2425
     
    7071
    7172/// Parse command-line arguments
    72 void ppSimArguments(int argc, char *argv[], ///< Command-line arguments
     73bool ppSimArguments(int argc, char **argv, ///< Command-line arguments
    7374                    pmConfig *config ///< Configuration
    74                     );
     75    );
    7576
    7677/// Create output file
     
    7879/// Returns a borrowed pointer to the FPA file.
    7980pmFPAfile *ppSimCreate(pmConfig *config ///< Configuration
    80                        );
     81    );
    8182
    8283// Return bounds of a chip, based on the concepts
    8384psRegion *ppSimChipBounds(const pmChip *chip, // Chip for which to determine size
    8485                          pmFPAview *view // View for chip
    85                           );
     86    );
    8687
    8788// Return bounds of an FPA, based on the concepts
    8889psRegion *ppSimFPABounds(const pmFPA *fpa       // FPA for which to determine size
    89                          );
     90    );
    9091
    9192/// Loop over the output file, generating simulated data
    9293bool ppSimLoop(pmConfig *config ///< Configuration
    93                  );
     94    );
    9495
    9596psVector *ppSimMakeBiassec (pmCell *cell, pmConfig *config);
    96 psVector *ppSimMakeBias (pmReadout *readout, pmConfig *config, const psRandom *rng) ;
     97psVector *ppSimMakeBias (bool *status, pmReadout *readout, pmConfig *config, const psRandom *rng) ;
    9798bool ppSimMakeDark (pmReadout *readout, pmConfig *config);
    9899bool ppSimMakeSky (pmReadout *readout, psImage *expCorr, ppSimType type, pmConfig *config);
     100
     101bool ppSimLoadSpots (pmFPA *fpa, pmConfig *config);
    99102
    100103bool ppSimLoadStars (psArray *stars, pmFPA *fpa, pmConfig *config);
     
    127130bool ppSimInsertGalaxies (pmReadout *readout, psImage *expCorr, psArray *galaxies, pmConfig *config);
    128131
     132bool ppSimMosaicChip(pmConfig *config, const psMaskType blankMask, const pmFPAview *view,
     133                     const char *outFile, const char *inFile);
     134
     135bool ppSimPhotom (pmConfig *config, pmFPAview *view);
     136
     137
    129138/// Add bad pixels to an image
    130139bool ppSimBadPixels(pmReadout *readout, ///< Readout for which to generate bad pixels
     
    139148float ppSimMagToFlux (float mag, float zp);
    140149
     150float ppSimArgToRecipeF32(bool *status,
     151                          psMetadata *options,    // Target to which to add value
     152                          const char *recipeName, // Name for value in the recipe
     153                          psMetadata *arguments,  // Command-line arguments
     154                          const char *argName    // Argument name in the command-line arguments
     155    );
     156
     157int ppSimArgToRecipeS32(bool *status,
     158                        psMetadata *options,    // Target to which to add value
     159                        const char *recipeName, // Name for value in the recipe
     160                        psMetadata *arguments,  // Command-line arguments
     161                        const char *argName      // Argument name in the command-line arguments
     162    );
     163
     164char *ppSimArgToRecipeStr(bool *status,
     165                          psMetadata *options,    // Target to which to add value
     166                          const char *recipeName, // Name for value in the recipe
     167                          psMetadata *arguments,  // Command-line arguments
     168                          const char *argName    // Argument name in the command-line arguments
     169    );
     170
     171bool ppSimArgToRecipeBool(bool *status,
     172                          psMetadata *options,    // Target to which to add value
     173                          const char *recipeName, // Name for value in the recipe
     174                          psMetadata *arguments,  // Command-line arguments
     175                          const char *argName       // Argument name in the command-line arguments
     176    );
     177
     178ppSimType ppSimTypeFromString (char *typeStr);
     179char *ppSimTypeToString (ppSimType type);
     180
     181float ppSimGetZeroPoint (psMetadata *recipe, char *filter);
     182
     183bool ppSimMergeReadouts (pmConfig *config, pmFPAview *view);
     184
     185double ppSimRandomGaussian (const psRandom *rnd, double mean, double sigma);
     186double ppSimRandomGaussianNorm (const psRandom *rnd);
     187void ppSimRandomGaussianFree();
     188
     189bool ppSimPhotomFiles (pmConfig *config, pmFPAfile *fakeFile, pmFPAfile *forceFile);
     190
     191bool ppSimPhotomReadoutFake(pmConfig *config, const pmFPAview *view);
     192bool ppSimPhotomReadoutForce(pmConfig *config, const pmFPAview *view);
     193
     194psArray *ppSimLoadForceSources(pmConfig *config, const pmFPAview *view);
     195bool ppSimDetections (psImage *significance, psMetadata *recipe, psArray *sources);
     196psArray *ppSimMergeSources (psArray *in1, psArray *in2);
     197
     198psArray *ppSimSelectSources (pmConfig *config, const pmFPAview *view, const char *filename);
     199bool ppSimDefinePixels (psArray *sources, pmReadout *readout, psMetadata *recipe);
     200
    141201#endif
  • trunk/ppSim/src/ppSimAddNoise.c

    r14657 r18011  
    3232            // (generate a static array with the cumulative distribution, use the
    3333            // random number to select a bin from the histogram)
    34             signal->data.F32[y][x] += sqrtf(variance->data.F32[y][x]) * psRandomGaussian(rng);
     34            signal->data.F32[y][x] += sqrtf(variance->data.F32[y][x]) * ppSimRandomGaussianNorm(rng);
    3535            signal->data.F32[y][x] /= gain; // Converting to ADU
    3636        }
  • trunk/ppSim/src/ppSimAddOverscan.c

    r14657 r18011  
    44
    55    bool mdok;
     6
     7    // skip this step if we did not generate a bias level
     8    if (biasCols == NULL) return true;
     9    if (biasRows == NULL) return true;
    610
    711    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPSIM_RECIPE); // Recipe
  • trunk/ppSim/src/ppSimArguments.c

    r17557 r18011  
    1 #include "ppSim.h"
     1# include "ppSim.h"
    22
    33// Print usage information and die
     
    1818}
    1919
    20 // Get a value from the command-line arguments and add it to recipe options
    21 bool valueArgRecipe(psMetadata *options,    // Target to which to add value
    22                     const char *recipeName, // Name for value in the recipe
    23                     psMetadata *arguments,  // Command-line arguments
    24                     const char *argName     // Argument name in the command-line arguments
    25     )
     20// this function supplements the RECIPE:OPTIONS folder with command-line options
     21bool ppSimArguments(int argc, char **argv, pmConfig *config)
    2622{
    27     bool status;                                                    // Status of MD lookup
    28     float value = psMetadataLookupF32(&status, arguments, argName); // Value of interest
    29     if (isnan(value)) return true;
    30     status = psMetadataAddF32(options, PS_LIST_TAIL, recipeName, 0, NULL, value);
    31     return status;
    32 }
    33 
    34 // this function supplements the RECIPE:OPTIONS folder with command-line options
    35 void ppSimArguments(int argc, char *argv[], pmConfig *config)
    36 {
    37     bool mdok;                          // Status of MD lookup
     23    bool status;
    3824
    3925    assert(config);
    4026
    41     // save the following command-line options in the arguments structure
     27    // save the following command-line options in the arguments structure.  these will later be
     28    // parsed and moved to the config->recipes:PPSIM_RECIPE folder
     29
    4230    psMetadata *arguments = psMetadataAlloc(); // Command-line arguments
    43     psMetadataAddStr(arguments, PS_LIST_TAIL, "-format", 0, "Camera format name", NULL);
    44     psMetadataAddStr(arguments, PS_LIST_TAIL, "-type", 0, "Exposure type (BIAS|DARK|FLAT|OBJECT)", NULL);
    45     psMetadataAddStr(arguments, PS_LIST_TAIL, "-filter", 0, "Filter name", NULL);
    46     psMetadataAddF32(arguments, PS_LIST_TAIL, "-exptime", 0, "Exposure time (s)", NAN);
    47     psMetadataAddF32(arguments, PS_LIST_TAIL, "-biaslevel", 0, "Bias level (e)", NAN);
    48     psMetadataAddF32(arguments, PS_LIST_TAIL, "-biasrange", 0, "Bias range (e)", NAN);
    49     psMetadataAddF32(arguments, PS_LIST_TAIL, "-darkrate", 0, "Dark rate (e/s)", NAN);
    50     psMetadataAddF32(arguments, PS_LIST_TAIL, "-flatsigma", 0, "Flat sigma", NAN);
    51     psMetadataAddF32(arguments, PS_LIST_TAIL, "-flatrate", 0, "Flat rate (e/s)", NAN);
    52     psMetadataAddF32(arguments, PS_LIST_TAIL, "-shuttertime", 0, "Shutter time (s)", NAN);
    53     psMetadataAddF32(arguments, PS_LIST_TAIL, "-skyrate", 0, "Sky rate (e/s)", NAN);
    54     psMetadataAddF32(arguments, PS_LIST_TAIL, "-skymags", 0, "Sky brightness in mags / square arcsec", NAN);
    55     psMetadataAddF32(arguments, PS_LIST_TAIL, "-ra", 0, "RA (degrees)", NAN);
    56     psMetadataAddF32(arguments, PS_LIST_TAIL, "-dec", 0, "Dec (degrees)", NAN);
    57     psMetadataAddF32(arguments, PS_LIST_TAIL, "-pa", 0, "Position angle (degrees)", NAN);
    58     psMetadataAddF32(arguments, PS_LIST_TAIL, "-scale", 0, "Plate scale (arcsec/pixel)", NAN);
    59     psMetadataAddF32(arguments, PS_LIST_TAIL, "-zp", 0, "Photometric zero point", NAN);
    60     psMetadataAddF32(arguments, PS_LIST_TAIL, "-seeing", 0, "Seeing FWHM (arcsec)", NAN);
    61     psMetadataAddF32(arguments, PS_LIST_TAIL, "-starslum", 0, "Fake star luminosity function slope", NAN);
    62     psMetadataAddF32(arguments, PS_LIST_TAIL, "-starsmag", 0, "Brightest magnitude for fake stars", NAN);
    63     psMetadataAddF32(arguments, PS_LIST_TAIL, "-starsdensity", 0, "Density of fake stars at magnitude", NAN);
    64     psMetadataAddStr(arguments, PS_LIST_TAIL, "-psfclass", 0, "Type of PSF model", NULL);
    65     psMetadataAddStr(arguments, PS_LIST_TAIL, "-galmodel", 0, "Type of Galaxy model", NULL);
    66     psMetadataAddS32(arguments, PS_LIST_TAIL, "-bin", 0, "Binning in x and y", 1);
     31    psMetadataAddStr(arguments,  PS_LIST_TAIL, "-format", 0, "Camera format name", NULL);
     32    psMetadataAddStr(arguments,  PS_LIST_TAIL, "-type", 0, "Exposure type (BIAS|DARK|FLAT|OBJECT)", NULL);
     33    psMetadataAddStr(arguments,  PS_LIST_TAIL, "-filter", 0, "Filter name", NULL);
     34    psMetadataAddF32(arguments,  PS_LIST_TAIL, "-exptime", 0, "Exposure time (s)", NAN);
     35    psMetadataAddF32(arguments,  PS_LIST_TAIL, "-biaslevel", 0, "Bias level (e)", NAN);
     36    psMetadataAddF32(arguments,  PS_LIST_TAIL, "-biasrange", 0, "Bias range (e)", NAN);
     37    psMetadataAddF32(arguments,  PS_LIST_TAIL, "-darkrate", 0, "Dark rate (e/s)", NAN);
     38    psMetadataAddF32(arguments,  PS_LIST_TAIL, "-flatsigma", 0, "Flat sigma", NAN);
     39    psMetadataAddF32(arguments,  PS_LIST_TAIL, "-flatrate", 0, "Flat rate (e/s)", NAN);
     40    psMetadataAddF32(arguments,  PS_LIST_TAIL, "-shuttertime", 0, "Shutter time (s)", NAN);
     41    psMetadataAddF32(arguments,  PS_LIST_TAIL, "-skyrate", 0, "Sky rate (e/s)", NAN);
     42    psMetadataAddF32(arguments,  PS_LIST_TAIL, "-skymags", 0, "Sky brightness in mags / square arcsec", NAN);
     43    psMetadataAddF32(arguments,  PS_LIST_TAIL, "-ra", 0, "RA (degrees)", NAN);
     44    psMetadataAddF32(arguments,  PS_LIST_TAIL, "-dec", 0, "Dec (degrees)", NAN);
     45    psMetadataAddF32(arguments,  PS_LIST_TAIL, "-pa", 0, "Position angle (degrees)", NAN);
     46    psMetadataAddF32(arguments,  PS_LIST_TAIL, "-scale", 0, "Plate scale (arcsec/pixel)", NAN);
     47    psMetadataAddF32(arguments,  PS_LIST_TAIL, "-zp", 0, "Photometric zero point", NAN);
     48    psMetadataAddF32(arguments,  PS_LIST_TAIL, "-seeing", 0, "Seeing FWHM (arcsec)", NAN);
     49    psMetadataAddF32(arguments,  PS_LIST_TAIL, "-starslum", 0, "Fake star luminosity function slope", NAN);
     50    psMetadataAddF32(arguments,  PS_LIST_TAIL, "-starsmag", 0, "Brightest magnitude for fake stars", NAN);
     51    psMetadataAddF32(arguments,  PS_LIST_TAIL, "-starsdensity", 0, "Density of fake stars at magnitude", NAN);
     52    psMetadataAddStr(arguments,  PS_LIST_TAIL, "-psfclass", 0, "Type of PSF model", NULL);
     53    psMetadataAddStr(arguments,  PS_LIST_TAIL, "-galmodel", 0, "Type of Galaxy model", NULL);
     54    psMetadataAddS32(arguments,  PS_LIST_TAIL, "-bin", 0, "Binning in x and y", 1);
     55    psMetadataAddBool(arguments, PS_LIST_TAIL, "+photom", 0, "Perform photometry on fake sources", false);
    6756
    6857    if (psArgumentGet (argc, argv, "-h")) { usage(argv[0], arguments, config); }
     
    7160
    7261    pmConfigFileSetsMD (config->arguments, &argc, argv, "PSPHOT.PSF", "-psf", "-psflist");
    73 
    74     // only one of -camera and -file is needed
    75     bool status = pmConfigFileSetsMD (config->arguments, &argc, argv, "INPUT", "-file", "-list");
    76     if (!config->camera && !status) {
    77         psErrorStackPrint(stderr, "A camera name (-camera NAME) or an image (-file NAME) must be specified");
    78         exit(PS_EXIT_CONFIG_ERROR);
     62    if (psErrorCodeLast () != PS_ERR_NONE) { psAbort ("problem with -psf or -psflist option"); }
     63
     64    pmConfigFileSetsMD (config->arguments, &argc, argv, "INPUT.SOURCES", "-cmf", "-cmflist");
     65    if (psErrorCodeLast () != PS_ERR_NONE) { psAbort ("problem with -cmf or -cmflist option"); }
     66
     67    // Only one of -camera and -file is needed or allowed.  The -camera option would have been
     68    // already parsed by pmConfigRead in ppSim.c and resulted in a value for config->camera
     69    bool loadImage = pmConfigFileSetsMD (config->arguments, &argc, argv, "INPUT", "-input", "-inputlist");
     70    if (!config->camera && !loadImage) {
     71        psError(PS_ERR_IO, true, "A camera name (-camera NAME) or an input image (-input NAME) must be specified");
     72        psFree(arguments);
     73        return false;
     74    }
     75    if (config->camera && loadImage) {
     76        psError(PS_ERR_IO, true, "Only one of (-camera NAME) and (-file NAME) may be specified");
     77        psFree(arguments);
     78        return false;
    7979    }
    8080
    8181    if (!psArgumentParse(arguments, &argc, argv)) {
    82         exit(PS_EXIT_CONFIG_ERROR);
     82        psError(PS_ERR_IO, false, "error in command-line arguments");
     83        psFree(arguments);
     84        return false;
    8385    }
    8486
    8587    if (argc != 2) {
    86         psErrorStackPrint(stderr, "Missing output filename");
    87         exit(PS_EXIT_CONFIG_ERROR);
     88        psError(PS_ERR_IO, true, "Missing output filename");
     89        psFree(arguments);
     90        return false;
     91    }
     92
     93    // output filename
     94    psMetadataAddStr(config->arguments, PS_LIST_TAIL, "OUTPUT", 0, "Name of the output image", argv[1]);
     95
     96    // save the additional recipe values based on command-line options. These options override
     97    // the PPSIM recipe values loaded from recipe files
     98    psMetadata *options = pmConfigRecipeOptions (config, PPSIM_RECIPE);
     99    if (!options) {
     100        psError(PS_ERR_IO, false, "Unable to find recipe options for %s", PPSIM_RECIPE);
     101        psFree(arguments);
     102        return false;
     103    }
     104
     105    // these arguments may be used whether the input image is created or loaded
     106    ppSimArgToRecipeF32(&status, options, "STARS.LUM",     arguments, "-starslum");
     107    ppSimArgToRecipeF32(&status, options, "STARS.MAG",     arguments, "-starsmag");
     108    ppSimArgToRecipeF32(&status, options, "STARS.DENSITY", arguments, "-starsdensity");
     109    ppSimArgToRecipeBool(&status, options, "PHOTOM",        arguments, "+photom");
     110
     111    // if we are loading the input image (not creating it), then we can skip the remaining arguments
     112    if (loadImage) {
     113        // if we are supplying an input image, it is so we may supply fake stars; force it to
     114        // be treated as an OBJECT image.
     115        psMetadataAddStr(options, PS_LIST_TAIL, "IMAGE.TYPE", 0, "Exposure type", "OBJECT");
     116
     117        // check for these options as well
     118        ppSimArgToRecipeStr(&status, options, "PSF.MODEL",    arguments, "-psfclass"); // PSF model class
     119        ppSimArgToRecipeStr(&status, options, "GALAXY.MODEL", arguments, "-galmodel"); // Galaxy model name
     120
     121        // 'seeing' is not required: we can load a psf-model instead; but if not, it is allowed
     122        ppSimArgToRecipeF32(&status, options, "SEEING", arguments, "-seeing"); // seeing (FWHM in arcsec)
     123
     124        // 'scale' is not required: we can use the WCS instead; but if not, it is allowed
     125        ppSimArgToRecipeF32(&status, options, "PIXEL.SCALE", arguments, "-scale"); // Plate scale
     126
     127        // XXX we need to be more flexible: get this from the input image header or WCS
     128        float ra0     = psMetadataLookupF32(NULL, arguments, "-ra"); // Right Ascension of boresight
     129        float dec0    = psMetadataLookupF32(NULL, arguments, "-dec"); // Declination of boresight
     130        psMetadataAddF32(options, PS_LIST_TAIL, "RA", 0, "Boresight RA (radians)", ra0 * M_PI / 180.0);
     131        psMetadataAddF32(options, PS_LIST_TAIL, "DEC", 0, "Boresight Declination (radians)", dec0 * M_PI / 180.0);
     132
     133        psFree (arguments);
     134        return true;
    88135    }
    89136
     
    96143        psMetadata *formats = psMetadataLookupMetadata(NULL, config->camera, "FORMATS"); // The camera formats
    97144        if (!formats) {
    98             psErrorStackPrint(stderr, "Unable to find FORMATS in camera configuration.");
     145            psError(PS_ERR_IO, false, "Unable to find FORMATS in camera configuration.");
    99146            psFree(arguments);
    100             psFree(config);
    101             exit(PS_EXIT_CONFIG_ERROR);
     147            return false;
    102148        }
    103149        psMetadata *format = psMetadataLookupMetadata(NULL, formats, formatName); // Format of interest
    104150        if (!format) {
    105             psErrorStackPrint(stderr, "Unable to find format %s in camera FORMATS.", formatName);
     151            psError(PS_ERR_IO, false, "Unable to find format %s in camera FORMATS.", formatName);
    106152            psFree(arguments);
    107             psFree(config);
    108             exit(PS_EXIT_CONFIG_ERROR);
     153            return false;
    109154        }
    110155        config->format = psMemIncrRefCounter(format);
    111156    }
    112157
    113     // specify the type of simulated image to produce
    114     // XXX this should not be required if we supplied INPUT
    115     const char *typeStr = psMetadataLookupStr(NULL, arguments, "-type"); // Exposure type
    116     if (!typeStr) {
    117         psErrorStackPrint(stderr, "An exposure type must be specified using -type");
    118         exit(PS_EXIT_CONFIG_ERROR);
    119     }
    120     ppSimType type = PPSIM_TYPE_NONE;   // Type to simulate
    121     if (strcasecmp(typeStr, "BIAS") == 0) {
    122         type = PPSIM_TYPE_BIAS;
    123     } else if (strcasecmp(typeStr, "DARK") == 0) {
    124         type = PPSIM_TYPE_DARK;
    125     } else if (strcasecmp(typeStr, "FLAT") == 0) {
    126         type = PPSIM_TYPE_FLAT;
    127     } else if (strcasecmp(typeStr, "OBJECT") == 0) {
    128         type = PPSIM_TYPE_OBJECT;
     158    char *typeStr = ppSimArgToRecipeStr (&status, options, "IMAGE.TYPE", arguments, "-type"); // Requested exposure type
     159    if (typeStr == NULL) {
     160        psError(PS_ERR_IO, false, "An exposure type must be specified using -type");
     161        psFree(arguments);
     162        return false;
     163    }
     164    ppSimType type = ppSimTypeFromString (typeStr);
     165
     166    ppSimArgToRecipeStr(&status, options, "FILTER", arguments, "-filter"); // Filter name
     167
     168    // set the exposure time
     169    if (type == PPSIM_TYPE_BIAS) {
     170        psMetadataAddF32(options, PS_LIST_TAIL, "EXPTIME", 0, "Exposure time (s)", 0.0);
    129171    } else {
    130         psErrorStackPrint(stderr, "Unrecognised exposure type: %s", typeStr);
    131         exit(PS_EXIT_CONFIG_ERROR);
    132     }
    133     assert(type != PPSIM_TYPE_NONE);
    134     psMetadataAddS32(config->arguments, PS_LIST_TAIL, "TYPE", 0, "Exposure type", type);
    135 
    136     const char *filter = psMetadataLookupStr(NULL, arguments, "-filter"); // Filter name
    137     psMetadataAddStr(config->arguments, PS_LIST_TAIL, "FILTER", 0, "Filter name", filter);
    138 
    139     // save the following additional recipe values based on command-line options
    140     // these options override the PPSIM recipe values loaded from recipe files
    141     psMetadata *options = pmConfigRecipeOptions (config, PPSIM_RECIPE);
    142     if (!options) {
    143         psErrorStackPrint(stderr, "Unable to find recipe options for %s", PPSIM_RECIPE);
    144         psFree(arguments);
    145         psFree(config);
    146         exit(PS_EXIT_CONFIG_ERROR);
    147     }
    148 
    149     float expTime;
    150     if (type == PPSIM_TYPE_BIAS) {
    151         expTime = 0.0;
    152     } else {
    153         expTime = psMetadataLookupF32(NULL, arguments, "-exptime"); // Exposure time
    154         if (isnan(expTime)) {
    155             psErrorStackPrint(stderr, "The exposure time must be specified using -exptime");
    156             exit(PS_EXIT_CONFIG_ERROR);
    157         }
    158     }
    159     psMetadataAddF32(options, PS_LIST_TAIL, "EXPTIME", 0, "Exposure time (s)", expTime);
     172        ppSimArgToRecipeF32(&status, options, "EXPTIME", arguments, "-exptime");
     173        if (!status) {
     174            psError(PS_ERR_IO, false, "The exposure time must be specified using -exptime");
     175            psFree(arguments);
     176            return false;
     177        }
     178    }
    160179
    161180    // these values all get moved from arguments to RECIPE:OPTIONS
    162     valueArgRecipe(options, "BIAS.LEVEL",    arguments, "-biaslevel");
    163     valueArgRecipe(options, "BIAS.RANGE",    arguments, "-biasrange");
    164     valueArgRecipe(options, "DARK.RATE",     arguments, "-darkrate");
    165     valueArgRecipe(options, "FLAT.SIGMA",    arguments, "-flatsigma");
    166     valueArgRecipe(options, "FLAT.RATE",     arguments, "-flatrate");
    167     valueArgRecipe(options, "SHUTTER.TIME",  arguments, "-shuttertime");
    168     valueArgRecipe(options, "SKY.RATE",      arguments, "-skyrate");
    169     valueArgRecipe(options, "STARS.LUM",     arguments, "-starslum");
    170     valueArgRecipe(options, "STARS.MAG",     arguments, "-starsmag");
    171     valueArgRecipe(options, "STARS.DENSITY", arguments, "-starsdensity");
    172 
    173     psMetadata *recipe = psMetadataLookupMetadata(&mdok, config->recipes, PPSIM_RECIPE); // Recipe
    174 
    175     int biasOrder = psMetadataLookupS32(&mdok, recipe, "BIAS.ORDER"); // Overscan polynomial order
    176     if (!mdok) {
    177         psWarning("BIAS.ORDER(S32) is not set in the recipe %s --- assuming %d", PPSIM_RECIPE, biasOrder);
    178     }
    179     psMetadataAddS32(options, PS_LIST_TAIL, "BIAS.ORDER", 0, "Overscan polynomial order", biasOrder);
    180 
    181     int binning = psMetadataLookupS32(NULL, arguments, "-bin"); // Binning in x and y
    182     if (binning <= 0) {
    183         psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Binning (%d) is non-positive.", binning);
    184         exit(PS_EXIT_CONFIG_ERROR);
    185     }
    186     psMetadataAddS32(config->arguments, PS_LIST_TAIL, "BINNING", 0, "Binning in x and y", binning);
    187 
    188     psMetadataAddStr(config->arguments, PS_LIST_TAIL, "OUTPUT", 0, "Name of the output image", argv[1]);
     181    ppSimArgToRecipeF32(&status,  options, "BIAS.LEVEL",    arguments, "-biaslevel");
     182    ppSimArgToRecipeF32(&status,  options, "BIAS.RANGE",    arguments, "-biasrange");
     183    ppSimArgToRecipeF32(&status,  options, "DARK.RATE",     arguments, "-darkrate");
     184    ppSimArgToRecipeF32(&status,  options, "FLAT.SIGMA",    arguments, "-flatsigma");
     185    ppSimArgToRecipeF32(&status,  options, "FLAT.RATE",     arguments, "-flatrate");
     186    ppSimArgToRecipeF32(&status,  options, "SHUTTER.TIME",  arguments, "-shuttertime");
     187    ppSimArgToRecipeF32(&status,  options, "SKY.RATE",      arguments, "-skyrate");
     188    ppSimArgToRecipeS32(&status,  options, "BINNING",       arguments, "-bin");
    189189
    190190    if (type == PPSIM_TYPE_OBJECT) {
     
    197197        // XXX scale and zp should be supplied by the config file (allow override, but this is camera-dependent)
    198198        if (isnan(ra0) || isnan(dec0) || isnan(pa) || isnan(seeing)) {
    199             psErrorStackPrint(stderr, "-ra, -dec, -pa, -scale, -zp, -seeing must be specified for OBJECT type");
    200             exit(PS_EXIT_CONFIG_ERROR);
    201         }
    202 
    203         float zp = psMetadataLookupF32(NULL, arguments, "-zp"); // Zero point
    204         if (isnan(zp)) {
    205             // use the filter to get the zeropoint from the recipe
    206             psMetadataItem *zpItem = psMetadataLookup (recipe, "ZEROPTS");
    207             // check that item is multi...
    208            
    209             psArray *entries = psListToArray (zpItem->data.list);
    210          
    211             // search for matching filter
    212             for (int i = 0; i < entries->n; i++) {
    213                 psMetadataItem *item = entries->data[i];
    214                 psMetadata *entry = item->data.V;
    215 
    216                 char *filterName = psMetadataLookupStr (&status, entry, "FILTER");
    217                 assert (filterName);
    218 
    219                 if (strcmp(filterName, filter)) continue;
    220 
    221                 zp = psMetadataLookupF32 (&status, entry, "ZERO_PT");
    222                 assert (status);
    223                 break;
    224             }
    225             psFree (entries);
    226         }
    227 
    228         float scale   = psMetadataLookupF32(NULL, arguments, "-scale"); // Plate scale
    229         if (isnan(scale)) {
    230             scale = psMetadataLookupF32 (&status, recipe, "PIXEL.SCALE");
    231         }
    232 
    233         float skymags = psMetadataLookupF32(NULL, arguments, "-skymags"); // Position angle
    234         if (isnan(skymags)) {
    235             skymags = psMetadataLookupF32 (&status, recipe, "SKY.MAGS");
    236         }
    237 
     199            psError(PS_ERR_IO, false, "-ra, -dec, -pa, -scale, -zp, -seeing must be specified for OBJECT type");
     200            psFree(arguments);
     201            return false;
     202        }
     203
     204        ppSimArgToRecipeF32(&status, options, "PIXEL.SCALE", arguments, "-scale"); // Plate scale (arcsec / pixel)
     205        ppSimArgToRecipeF32(&status, options, "SKY.MAGS", arguments, "-skymags"); // Plate scale
     206        ppSimArgToRecipeStr(&status, options, "PSF.MODEL",    arguments, "-psfclass"); // PSF model class
     207        ppSimArgToRecipeStr(&status, options, "GALAXY.MODEL", arguments, "-galmodel"); // Galaxy model name
     208
     209        // the user supplies FWHM in arcsec; here we convert to Sigma in pixels
     210        psMetadataAddF32(options, PS_LIST_TAIL, "SEEING", 0, "Seeing FWHM (arcsec)", seeing);
    238211        psMetadataAddF32(options, PS_LIST_TAIL, "RA", 0, "Boresight RA (radians)", ra0 * M_PI / 180.0);
    239212        psMetadataAddF32(options, PS_LIST_TAIL, "DEC", 0, "Boresight Declination (radians)", dec0 * M_PI / 180.0);
    240213        psMetadataAddF32(options, PS_LIST_TAIL, "PA", 0, "Boresight position angle (radians)",pa * M_PI / 180.0);
    241214
    242         // the user supplies FWHM in arcsec; here we convert to Sigma in pixels
    243         psMetadataAddF32(options, PS_LIST_TAIL, "SEEING", 0, "Seeing SIGMA (pixels)", seeing / 2.0 / sqrt(2.0 * log(2.0)) / scale);
    244 
    245         psMetadataAddF32(options, PS_LIST_TAIL, "SCALE", 0, "Plate scale (arcsec/pix)", scale);
    246         psMetadataAddF32(options, PS_LIST_TAIL, "ZEROPOINT", 0, "Photometric zeropoint", zp);
    247         psMetadataAddF32(options, PS_LIST_TAIL, "SKY.MAGS", 0, "sky surface brightness", skymags);
    248 
    249         const char *psfClass = psMetadataLookupStr(NULL, arguments, "-psfclass"); // PSF model class
    250         psMetadataAddStr(config->arguments, PS_LIST_TAIL, "PSF.MODEL", 0, "PSF model class", psfClass);
    251 
    252         const char *galModel = psMetadataLookupStr(NULL, arguments, "-galmodel"); // Galaxy model name
    253         psMetadataAddStr(config->arguments, PS_LIST_TAIL, "GALAXY.MODEL", 0, "Galaxy model", galModel);
     215        ppSimArgToRecipeF32(&status, options, "ZEROPOINT", arguments, "-zp"); // Zero point
    254216    }
    255217
    256218    psFree(arguments);
    257     return;
     219    return true;
    258220}
    259221
     
    262224   PSPHOT.PSF
    263225   INPUT
    264    TYPE
    265    FILTER
    266    BIAS.ORDER
    267    BINNING
    268226   OUTPUT
    269    PSF.MODEL
    270    GALAXY.MODEL
    271 
    272    all othr values should come from the recipe
     227
     228   all other values should come from the recipe
    273229*/
  • trunk/ppSim/src/ppSimCreate.c

    r17915 r18011  
    11# include "ppSim.h"
    2 
    3 // XXX this function forces us to define the camera (on the command line) and format (via the
    4 // PPSIM.OUTPUT entry).  In this case, we need to set config->format,formatName based on these
    5 // values.  This will be a problem when we want to load an input image (in order to add fake
    6 // stars).  We will need to add some logic in ppSimArguments to distinguish the cases of 1)
    7 // input image and 2) specified camera
    82
    93pmFPAfile *ppSimCreate(pmConfig *config)
    104{
     5    PS_ASSERT_PTR_NON_NULL(config, NULL);
     6
    117    bool status;
    12     bool simImage = false;
    13     PS_ASSERT_PTR_NON_NULL(config, NULL);
    148    pmFPA *fpa = NULL;
    159
    1610    // the input image defines the camera.  if it is not supplied, the user must have
    1711    // supplied a camera and other metadata on the command line
    18     pmFPAfile *input = pmFPAfileDefineFromArgs (&status, config, "PPIMAGE.INPUT", "INPUT");
     12    pmFPAfile *input = pmFPAfileDefineFromArgs (&status, config, "PPSIM.INPUT", "INPUT");
    1913    if (!input) {
    20         // if we have not specified the camera already, we need to interpolate the recipes associated with this camera, and read other command-line recipes
    21         if (!pmConfigReadRecipes(config, PM_RECIPE_SOURCE_CL)) {
    22             psError(PS_ERR_IO, false, "Error merging recipes from camera config for %s", config->cameraName);
    23             return NULL;
    24         }
    25 
    26         simImage = true;
    27         fpa = pmFPAConstruct(config->camera, config->cameraName); // FPA to contain the observation
    28         if (!fpa) {
    29             psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to construct an FPA from camera configuration.");
    30             return NULL;
    31         }
    32 
     14        // if we have not specified the camera already, we need to interpolate the recipes associated with this camera, and read other command-line recipes
     15        if (!pmConfigReadRecipes(config, PM_RECIPE_SOURCE_CL)) {
     16            psError(PS_ERR_IO, false, "Error merging recipes from camera config for %s", config->cameraName);
     17            return NULL;
     18        }
    3319    } else {
    34         simImage = false;
    35         if (input->type != PM_FPA_FILE_IMAGE) {
    36             psError(PS_ERR_IO, true, "PPIMAGE.INPUT is not of type IMAGE");
    37             return NULL;
    38         }
    39         fpa = input->fpa;
    40     }
    41 
    42     // define the output image file
    43     pmFPAfile *file = pmFPAfileDefineOutput(config, fpa, OUTPUT_FILE);
    44     if (!file) {
    45         psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to create output file from %s.  "
    46                 "Did you forget to specify the format?", OUTPUT_FILE);
    47         return NULL;
    48     }
    49     if (file->type != PM_FPA_FILE_IMAGE) {
    50         psError(PS_ERR_BAD_PARAMETER_TYPE, true, "%s type is not IMAGE", OUTPUT_FILE);
    51         psFree(fpa);
    52         psFree(file);
    53         return NULL;
    54     }
    55     file->save = true;
    56 
    57     config->format = psMemIncrRefCounter (file->format);
    58     config->formatName = psStringCopy (file->formatName);
    59 
    60     // have we supplied a psf model?
    61     if (psMetadataLookupPtr(NULL, config->arguments, "PSPHOT.PSF")) {
    62         bool status = false;
    63 
    64         // tie the psf file to the chipMosaic
    65         pmFPAfileBindFromArgs(&status, file, config, "PSPHOT.PSF.LOAD", "PSPHOT.PSF");
    66         if (!status) {
    67             psError(PS_ERR_UNKNOWN, false, "Failed to find/build PSPHOT.PSF.LOAD");
    68             psFree(fpa);
    69             psFree(file);
    70             return NULL;
    71         }
    72     }
    73 
    74     // XXX only invoke this code for OBJECT types of images
     20        // If an image is supplied, we still generate a fake image and merge them together downstream
     21        // (otherwise, we get the variance wrong).
     22        if (input->type != PM_FPA_FILE_IMAGE) {
     23            psError(PS_ERR_IO, true, "PPSIM.INPUT is not of type IMAGE");
     24            return NULL;
     25        }
     26    }
     27
     28    // generate the fpa structure used by the output camera (determined from INPUT or specified)
     29    assert (config->camera);
     30    fpa = pmFPAConstruct(config->camera, config->cameraName); // FPA to contain the observation
     31    if (!fpa) {
     32        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to construct an FPA from camera configuration.");
     33        return NULL;
     34    }
     35
     36    // define the output image file -- this is the basis for the ppSimLoop
     37    pmFPAfile *output = pmFPAfileDefineOutput(config, fpa, "PPSIM.OUTPUT");
     38    if (!output) {
     39        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to create output file from PPSIM.OUTPUT. Did you forget to specify the format?");
     40        return NULL;
     41    }
     42    if (output->type != PM_FPA_FILE_IMAGE) {
     43        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "PPSIM.OUTPUT type is not IMAGE");
     44        psFree(fpa);
     45        return NULL;
     46    }
     47    // XXX we should not require the output image to be written
     48    output->save = true;
     49
     50    config->format = psMemIncrRefCounter (output->format);
     51    config->formatName = psStringCopy (output->formatName);
     52
     53    // the recipe is now fully realized for the desired camera
     54    psMetadata *recipe = psMetadataLookupMetadata(&status, config->recipes, PPSIM_RECIPE); // Recipe
     55
     56    char *typeStr = psMetadataLookupStr(NULL, recipe, "IMAGE.TYPE"); // Type of image to simulate
     57    ppSimType type = ppSimTypeFromString (typeStr); // Type of image to simulate
     58
     59    if (type == PPSIM_TYPE_OBJECT) {
     60        // adjust the seeing by the scale
     61        float seeing = psMetadataLookupF32(&status, recipe, "SEEING");
     62        if (isnan(seeing)) {
     63            psError(PS_ERR_BAD_PARAMETER_TYPE, true, "seeing is not defined");
     64            psFree(fpa);
     65            return NULL;
     66        }
     67        float scale = psMetadataLookupF32(&status, recipe, "PIXEL.SCALE");
     68        if (isnan(scale)) {
     69            psError(PS_ERR_BAD_PARAMETER_TYPE, true, "pixel scale is not defined");
     70            psFree(fpa);
     71            return NULL;
     72        }
     73        psMetadataAddF32(recipe, PS_LIST_TAIL, "SEEING", PS_META_REPLACE, "Seeing SIGMA (pixels)", seeing / 2.0 / sqrt(2.0 * log(2.0)) / scale);
     74
     75        // if we have been supplied an input image, but no ra & dec, use the input image values
     76        if (input) {
     77            float ra = psMetadataLookupF32(&status, recipe, "RA");
     78            if (isnan(ra)) {
     79                ra = psMetadataLookupF64(&status, input->fpa->concepts, "FPA.RA");
     80                psMetadataAddF32(recipe, PS_LIST_TAIL, "RA", PS_META_REPLACE, "ra (radians)", ra);
     81            }
     82            float dec = psMetadataLookupF32(&status, recipe, "DEC");
     83            if (isnan(dec)) {
     84                dec = psMetadataLookupF64(&status, input->fpa->concepts, "FPA.DEC");
     85                psMetadataAddF32(recipe, PS_LIST_TAIL, "DEC", PS_META_REPLACE, "dec (radians)", dec);
     86            }
     87        }
     88    }
     89
     90    if ((type == PPSIM_TYPE_OBJECT) || (type == PPSIM_TYPE_FLAT)) {
     91        // determine the zeropoint from the filter
     92        float zp = psMetadataLookupF32(&status, recipe, "ZEROPOINT");
     93        if (isnan(zp)) {
     94            char *filter = psMetadataLookupStr(&status, recipe, "FILTER");
     95            float zp = ppSimGetZeroPoint (recipe, filter);
     96            psMetadataAddF32(recipe, PS_LIST_TAIL, "ZEROPOINT", PS_META_REPLACE, "Photometric zeropoint", zp);
     97        }
     98    }
     99
     100    // For photometry, we operate on the chip-mosaicked image.  we create a copy of the mosaicked
     101    // image for psphot so we can write out a clean image
     102    bool doPhotom = psMetadataLookupBool(&status, recipe, "PHOTOM"); // Density of fakes
     103    if (doPhotom) {
     104
     105        // XXX at the moment, we can perform photometry on the fake sources and the forced
     106        // photometry positions, but not one or the other.  Also, we only support photometry in
     107        // the context of an image previously analysed by psphot.  Add support for:
     108        // * photometry of a pure fake image (requires peak detection and psf creation)
     109        // * photometry of forced source positions without fake image (this might work, it just
     110        // requires not generating any fake features).
     111
     112        if (!input) {
     113            psError(PS_ERR_UNKNOWN, false, "input image not found; currently required for photometry");
     114            return NULL;
     115        }
     116
     117        // we need a chip image if we perform photometry (is it necessary to build it if we don't use it?)
     118        pmFPAfile *fakeImage = pmFPAfileDefineChipMosaic(config, output->fpa, "PPSIM.FAKE.CHIP");
     119        if (!fakeImage) {
     120            psError(PS_ERR_IO, false, _("Unable to generate new file from PPSIM.FAKE.CHIP"));
     121            psFree(fpa);
     122            return NULL;
     123        }
     124        if (fakeImage->type != PM_FPA_FILE_IMAGE) {
     125            psError(PS_ERR_IO, true, "PPSIM.FAKE.CHIP is not of type IMAGE");
     126            psFree(fpa);
     127            return NULL;
     128        }
     129
     130        // we need a chip image if we perform photometry (is it necessary to build it if we don't use it?)
     131        pmFPAfile *forceImage = NULL;
     132        if (input) {
     133            forceImage = pmFPAfileDefineChipMosaic(config, input->fpa, "PPSIM.FORCE.CHIP");
     134            if (!forceImage) {
     135                psError(PS_ERR_IO, false, _("Unable to generate new file from PPSIM.FORCE.CHIP"));
     136                psFree(fpa);
     137                return NULL;
     138            }
     139            if (forceImage->type != PM_FPA_FILE_IMAGE) {
     140                psError(PS_ERR_IO, true, "PPSIM.FORCE.CHIP is not of type IMAGE");
     141                psFree(fpa);
     142                return NULL;
     143            }
     144        }
     145
     146        // define associated psphot input/output files
     147        if (!ppSimPhotomFiles (config, fakeImage, forceImage)) {
     148            psError(PSPHOT_ERR_CONFIG, false, "Trouble defining the additional input/output files for psphot");
     149            psFree(fpa);
     150            return NULL;
     151        }
     152    } else {
     153        // have we supplied a psf model?  this happens in ppSimPhotomFiles if we request a photometry
     154        // analysis.  however, even if we do not, a psf model may be used to generate the fake
     155        // sources.
     156        if (psMetadataLookupPtr(NULL, config->arguments, "PSPHOT.PSF")) {
     157            // tie the psf file to the chipMosaic
     158            pmFPAfileBindFromArgs(&status, output, config, "PSPHOT.PSF.LOAD", "PSPHOT.PSF");
     159            if (!status) {
     160                psError(PS_ERR_UNKNOWN, false, "Failed to find/build PSPHOT.PSF.LOAD");
     161                psFree(fpa);
     162                return NULL;
     163            }
     164        }
     165    }
     166
    75167    // PPSIM.SOURCES carries the constructed, fake sources with their true parameters
    76     pmFPAfile *simSources = pmFPAfileDefineOutput (config, file->fpa, "PPSIM.SOURCES");
     168    // XXX only invoke this code for OBJECT types of images?
     169    pmFPAfile *simSources = pmFPAfileDefineOutput (config, output->fpa, "PPSIM.SOURCES");
    77170    if (!simSources) {
    78         psError(PS_ERR_UNKNOWN, false, "Cannot find a rule for PPSIM.SOURCES");
    79         return false;
     171        psError(PS_ERR_UNKNOWN, false, "Cannot find a rule for PPSIM.SOURCES");
     172        return false;
    80173    }
    81174    simSources->save = true;
    82175
    83     // if we have loaded an input image, we do not need to populate the fpa
    84     if (!simImage) {
    85         return file;
    86     }
    87 
    88     pmFPALevel phuLevel = pmFPAPHULevel(file->format); // Level at which PHU goes
     176    // if we have loaded an input image, we derive certain values from the image, if possible
     177    if (input) {
     178        // we need to extract certain metadata from the image and populate the recipe.
     179        // or else we need to set the fpa concepts based on the recipe options...
     180
     181        psMetadata *recipe = psMetadataLookupMetadata(&status, config->recipes, PPSIM_RECIPE); // Recipe
     182
     183        ppSimArgToRecipeF32(&status, recipe, "EXPTIME", input->fpa->concepts, "FPA.EXPOSURE");
     184        char *filter = ppSimArgToRecipeStr(&status, recipe, "FILTER", input->fpa->concepts, "FPA.FILTER");
     185
     186        float zp = ppSimGetZeroPoint (recipe, filter);
     187        psMetadataAddF32(recipe, PS_LIST_TAIL, "ZEROPOINT", PS_META_REPLACE, "Photometric zeropoint", zp);
     188    }
     189
     190    pmFPALevel phuLevel = pmFPAPHULevel(output->format); // Level at which PHU goes
    89191
    90192    pmFPAview *view = pmFPAviewAlloc(0);// View for current level
    91193
    92194    if (phuLevel == PM_FPA_LEVEL_FPA) {
    93         if (!pmFPAAddSourceFromView(fpa, "Simulation", view, file->format)) {
    94             psError(PS_ERR_UNKNOWN, false, "Unable to add PHU to FPA.");
    95             psFree(fpa);
    96             psFree(view);
    97             psFree(file);
    98             return NULL;
    99         }
     195        if (!pmFPAAddSourceFromView(fpa, "Simulation", view, output->format)) {
     196            psError(PS_ERR_UNKNOWN, false, "Unable to add PHU to FPA.");
     197            psFree(fpa);
     198            psFree(view);
     199            return NULL;
     200        }
    100201    }
    101202
    102203    pmChip *chip;                       // Chip from FPA
    103204    while ((chip = pmFPAviewNextChip(view, fpa, 1))) {
    104         if (phuLevel == PM_FPA_LEVEL_CHIP) {
    105             if (!pmFPAAddSourceFromView(fpa, "Simulation", view, file->format)) {
    106                 psError(PS_ERR_UNKNOWN, false, "Unable to add PHU to FPA.");
    107                 psFree(fpa);
    108                 psFree(view);
    109                 psFree(file);
    110                 return NULL;
    111             }
    112         }
    113 
    114         pmCell *cell;                   // Cell from chip
    115         while ((cell = pmFPAviewNextCell(view, fpa, 1))) {
    116             if (phuLevel == PM_FPA_LEVEL_CELL) {
    117                 if (!pmFPAAddSourceFromView(fpa, "Simulation", view, file->format)) {
    118                     psError(PS_ERR_UNKNOWN, false, "Unable to add PHU to FPA.");
    119                     psFree(fpa);
    120                     psFree(view);
    121                     psFree(file);
    122                     return NULL;
    123                 }
    124             }
    125         }
     205        if (phuLevel == PM_FPA_LEVEL_CHIP) {
     206            if (!pmFPAAddSourceFromView(fpa, "Simulation", view, output->format)) {
     207                psError(PS_ERR_UNKNOWN, false, "Unable to add PHU to FPA.");
     208                psFree(fpa);
     209                psFree(view);
     210                return NULL;
     211            }
     212        }
     213
     214        pmCell *cell;                   // Cell from chip
     215        while ((cell = pmFPAviewNextCell(view, fpa, 1))) {
     216            if (phuLevel == PM_FPA_LEVEL_CELL) {
     217                if (!pmFPAAddSourceFromView(fpa, "Simulation", view, output->format)) {
     218                    psError(PS_ERR_UNKNOWN, false, "Unable to add PHU to FPA.");
     219                    psFree(fpa);
     220                    psFree(view);
     221                    return NULL;
     222                }
     223            }
     224        }
    126225    }
    127226
     
    129228    psFree(view);
    130229
    131     return file;
     230    return output;
    132231}
  • trunk/ppSim/src/ppSimInsertGalaxies.c

    r17557 r18011  
    1010   
    1111    if (!galaxies->n) { return true; }
    12 
    13     // XXX is this needed?
    14     // pmFPAfile *simSources = psMetadataLookupPtr(NULL, config->files, "PPSIM.SOURCES"); // Output sources
    1512
    1613    pmCell *cell = readout->parent;
     
    3835    if (isnan(skyRate)) {
    3936        float zp      = psMetadataLookupF32(&mdok, recipe, "ZEROPOINT"); assert (mdok);
    40         float scale   = psMetadataLookupF32(&mdok, recipe, "SCALE");    assert (mdok);
     37        float scale   = psMetadataLookupF32(&mdok, recipe, "PIXEL.SCALE"); assert (mdok);
    4138        float skyMags = psMetadataLookupF32(&mdok, recipe, "SKY.MAGS");  assert (mdok);
    4239        skyRate = scale * scale * ppSimMagToFlux (skyMags, zp);
     
    5653    int yParityCell = psMetadataLookupS32(NULL, cell->concepts, "CELL.YPARITY");
    5754
    58     int binning = psMetadataLookupS32(NULL, config->arguments, "BINNING"); // Binning in x and y
     55    int binning = psMetadataLookupS32(NULL, recipe, "BINNING"); // Binning in x and y
    5956
    6057    // determine the galaxy model
    61     char *modelName = psMetadataLookupStr(&mdok, config->arguments, "GALAXY.MODEL"); // galaxy model name
     58    char *modelName = psMetadataLookupStr(&mdok, recipe, "GALAXY.MODEL"); // galaxy model name
    6259    if (modelName == NULL) {
    6360        modelName = defaultModel;
  • trunk/ppSim/src/ppSimInsertStars.c

    r17557 r18011  
    1515
    1616    if (!stars->n) { return true; }
    17 
    18     // XXX is this needed?
    19     // pmFPAfile *simSources = psMetadataLookupPtr(NULL, config->files, "PPSIM.SOURCES"); // Output sources
    2017
    2118    pmCell *cell = readout->parent;
     
    4340    if (isnan(skyRate)) {
    4441        float zp      = psMetadataLookupF32(&mdok, recipe, "ZEROPOINT"); assert (mdok);
    45         float scale   = psMetadataLookupF32(&mdok, recipe, "SCALE");     assert (mdok);
     42        float scale   = psMetadataLookupF32(&mdok, recipe, "PIXEL.SCALE");     assert (mdok);
    4643        float skyMags = psMetadataLookupF32(&mdok, recipe, "SKY.MAGS");  assert (mdok);
    4744        skyRate = scale * scale * ppSimMagToFlux (skyMags, zp);
     
    6158    int yParityCell = psMetadataLookupS32(NULL, cell->concepts, "CELL.YPARITY");
    6259
    63     int binning = psMetadataLookupS32(NULL, config->arguments, "BINNING"); // Binning in x and y
     60    int binning = psMetadataLookupS32(NULL, recipe, "BINNING"); // Binning in x and y
    6461
    6562    pmPSF *psf = psMetadataLookupPtr (&mdok, chip->analysis, "PSPHOT.PSF");
     
    117114        source->errMag = sqrt(Area*PS_SQR(roughNoise) + flux) / flux;
    118115
    119         // XXX add the sources to a source array
    120 
    121116        // insert the source flux in the image
    122117        pmSourceAddWithOffset (source, PM_MODEL_OP_FULL, 0xff, dX, dY);
    123         psArrayAdd (sources, 100,source);
    124         psFree(source);                 // Drop reference
     118        pmSourceAddWithOffset (source, PM_MODEL_OP_FULL | PM_MODEL_OP_NOISE, 0xff, dX, dY);
    125119
    126120        // Blow away the image parts of the source, which makes the memory explode
     
    132126        RESET(source->psfFlux);
    133127        RESET(source->blends);
     128
     129        // add the sources to the source array
     130        psArrayAdd (sources, 100,source);
     131        psFree(source);                 // Drop reference
    134132    }
    135133
    136     // NOTE: readout must be part of the pmFPAfile named "PPSIM.OUTPUT"
    137     psMetadataAdd (readout->analysis, PS_LIST_TAIL, "PSPHOT.SOURCES", PS_DATA_ARRAY, "psphot sources", sources);
     134    // NOTE: the pmFPAfile "PPSIM.OUTPUT" points at these sources
     135    psMetadataAdd (readout->analysis, PS_LIST_TAIL, "PSPHOT.SOURCES", PS_DATA_ARRAY, "fake sources", sources);
    138136    psFree(sources);
    139137
     
    141139    return true;
    142140}
    143 
  • trunk/ppSim/src/ppSimLoadSpots.c

    r17628 r18011  
    1 #include "ppSim.h"
     1# include "ppSim.h"
    22
     3// Load the relevant forced-photometry positions for this field.  This function does not determine
     4// the pixel coordinates, merely the celestial coordinates for sources in the general vicinity.  The
     5// sources are saved on the fpa->analysis metadata as FORCED.SPOTS.  We always create an entry; it
     6// will be empty if no sources were selected or forced photometry is not desired.
    37bool ppSimLoadSpots (pmFPA *fpa, pmConfig *config) {
    48
    5     bool mdok;
    6     assert (stars);
     9    bool status;
    710
    8     psMetadata *recipe = psMetadataLookupMetadata(&mdok, config->recipes, PPSIM_RECIPE); // Recipe
    911
    10     bool forcedPhot = psMetadataLookupBool(&mdok, recipe, "FORCED.PHOT"); // Density of fakes
    11     if (!forcedPhot) return true;
     12    psMetadata *recipe = psMetadataLookupMetadata(&status, config->recipes, PPSIM_RECIPE); // Recipe
    1213
    13     // Read catalogue stars using psastro
    14     // XXX probably need to modify this...
     14    bool forcedPhot = psMetadataLookupBool(&status, recipe, "FORCED.PHOT"); // Density of fakes
     15    if (!forcedPhot) {
     16        psArray *spots = psArrayAllocEmpty (1);
     17        psMetadataAddArray (fpa->analysis, PS_LIST_TAIL, "FORCED.SPOTS", PS_META_REPLACE, "forced photometry positions", spots);
     18        psFree (spots); // free the extra (local) reference; a copy remains on fpa->analysis
     19        return true;
     20    }
     21
     22    // We read the catalogue stars using psastroLoadRefstars
    1523    psMetadata *astroRecipe = psMetadataLookupPtr(NULL, config->recipes, PSASTRO_RECIPE);
    1624    if (!astroRecipe) {
    1725        psError(PSASTRO_ERR_CONFIG, false, "Can't find recipe %s", PSASTRO_RECIPE);
    18         return NULL;
     26        return false;
    1927    }
     28
     29    float ra0     = psMetadataLookupF32(NULL, recipe, "RA");        // Boresight RA (radians)
     30    float dec0    = psMetadataLookupF32(NULL, recipe, "DEC");       // Boresight Dec (radians)
     31    float scale   = psMetadataLookupF32(NULL, recipe, "PIXEL.SCALE") * M_PI / 3600.0 / 180.0; // Plate scale (radians/pixel)
     32
     33    if (isnan(ra0) || isnan(dec0)) {
     34        psError(PS_ERR_UNKNOWN, false, "image boresite coords not defined.");
     35        return false;
     36    }
     37
     38    char *catdir = psMetadataLookupStr(NULL, recipe, "FORCED.CATDIR");
    2039
    2140    // Size of FPA
     
    2443    psFree(bounds);
    2544
    26     float x0fpa = 0.5*(bounds->x0 + bounds->x1);
    27     float y0fpa = 0.5*(bounds->y0 + bounds->y1);
     45    // modify the PSASTRO recipe to use the values desired for FORCED.PHOT.  we can use a view on
     46    // the PSASTRO recipe because we are not calling psastro elsewhere in this program.  XXX need to
     47    // use the WCS to define the overlap region
     48    psMetadataAddStr(astroRecipe, PS_LIST_TAIL, "DVO.CATDIR",  PS_META_REPLACE, "", catdir);
     49    psMetadataAddF32(astroRecipe, PS_LIST_TAIL, "RA_MIN",  PS_META_REPLACE, "", ra0 - radius);
     50    psMetadataAddF32(astroRecipe, PS_LIST_TAIL, "RA_MAX",  PS_META_REPLACE, "", ra0 + radius);
     51    psMetadataAddF32(astroRecipe, PS_LIST_TAIL, "DEC_MIN", PS_META_REPLACE, "", dec0 - radius);
     52    psMetadataAddF32(astroRecipe, PS_LIST_TAIL, "DEC_MAX", PS_META_REPLACE, "", dec0 + radius);
     53   
     54    // tell psastroLoadRefstars to ignore photcode and maglim
     55    psMetadataAddStr(astroRecipe, PS_LIST_TAIL, "DVO.GETSTAR.PHOTCODE",  PS_META_REPLACE, "", "NONE");
     56    psMetadataAddF32(astroRecipe, PS_LIST_TAIL, "DVO.GETSTAR.MAG.MAX",  PS_META_REPLACE, "", NAN);
    2857
    29     // XXX need to use the WCS to define the overlap region
    30     psMetadataAdd(astroRecipe, PS_LIST_TAIL, "RA_MIN",  PS_DATA_F32 | PS_META_REPLACE, "", ra0 - radius);
    31     psMetadataAdd(astroRecipe, PS_LIST_TAIL, "RA_MAX",  PS_DATA_F32 | PS_META_REPLACE, "", ra0 + radius);
    32     psMetadataAdd(astroRecipe, PS_LIST_TAIL, "DEC_MIN", PS_DATA_F32 | PS_META_REPLACE, "", dec0 - radius);
    33     psMetadataAdd(astroRecipe, PS_LIST_TAIL, "DEC_MAX", PS_DATA_F32 | PS_META_REPLACE, "", dec0 + radius);
    34     psArray *refStars = psastroLoadRefstars(config);
    35     if (!refStars || refStars->n == 0) {
     58    // load refstars from the catalog
     59    psArray *spots = psastroLoadRefstars(config);
     60    if (!spots || spots->n == 0) {
    3661        psError(PS_ERR_UNKNOWN, false, "Unable to find reference stars.");
    37         psFree(refStars);
    38         return NULL;
     62        psFree(spots);
     63        return false;
    3964    }
    40     psLogMsg("ppSim", PS_LOG_INFO, "Adding %ld reference stars", refStars->n);
     65    psLogMsg("ppSim", PS_LOG_INFO, "Adding %ld reference stars", spots->n);
    4166
    42     // convert the pmAstromObj sources to the storage format used by the CMF files
     67    psMetadataAddArray (fpa->analysis, PS_LIST_TAIL, "FORCED.SPOTS", PS_META_REPLACE, "forced photometry positions", spots);
     68    psFree (spots); // free the extra (local) reference; a copy remains on fpa->analysis
    4369
    44     long oldSize = stars->n;
    45     stars = psArrayRealloc (stars, refStars->n);
    46 
    47     // Conversion loop
    48     for (long i = 0; i < refStars->n; i++) {
    49         ppSimStar *star = ppSimStarAlloc ();
    50 
    51         pmAstromObj *ref = refStars->data[i]; // Reference star
    52         star->ra  = ref->sky->r; // RA of star
    53         star->dec = ref->sky->d; // Dec of star
    54         star->mag = ref->Mag;       // Magnitude of star
    55 
    56         // Apply rotation, make FPA center of boresite
    57         // convert the ra,dec to x,y using examples in psastro.
    58         // star->x = cos(pa) * xi - sin(pa) * eta + x0fpa;
    59         // star->y = sin(pa) * xi + cos(pa) * eta + y0fpa;
    60 
    61         stars->data[oldSize + i] = star;
    62 
    63         psTrace("ppSim", 10, "Adding catalogue star: %.1f,%.1f --> %.2f\n", star->x, star->y, star->flux);
    64     }
    65 
    66     // XXX these need to be saved on PSPHOT.INPUT.CMF
    6770    return true;
    6871}
  • trunk/ppSim/src/ppSimLoadStars.c

    r17557 r18011  
    1 #include "ppSim.h"
     1# include "ppSim.h"
    22
    33bool ppSimLoadStars (psArray *stars, pmFPA *fpa, pmConfig *config) {
     
    1818    }
    1919
    20     // XXX push these into the recipe in ppSimArguments()
     20    // relevant metadata
    2121    float zp      = psMetadataLookupF32(NULL, recipe, "ZEROPOINT"); // Photometric zero point
    2222    float ra0     = psMetadataLookupF32(NULL, recipe, "RA");        // Boresight RA (radians)
     
    2424    float pa      = psMetadataLookupF32(NULL, recipe, "PA");        // Position angle (radians)
    2525    float seeing  = psMetadataLookupF32(NULL, recipe, "SEEING");    // Seeing SIGMA (pixels)
    26     float scale   = psMetadataLookupF32(NULL, recipe, "SCALE") * M_PI / 3600.0 / 180.0; // Plate scale (radians/pixel)
     26    float scale   = psMetadataLookupF32(NULL, recipe, "PIXEL.SCALE") * M_PI / 3600.0 / 180.0; // Plate scale (radians/pixel)
    2727    float expTime = psMetadataLookupF32(NULL, recipe, "EXPTIME");   // Exposure time (sec)
    2828
     
    4040    psMetadataAdd(astroRecipe, PS_LIST_TAIL, "DEC_MAX", PS_DATA_F32 | PS_META_REPLACE, "", dec0 + radius);
    4141    psArray *refStars = psastroLoadRefstars(config);
    42     if (!refStars || refStars->n == 0) {
     42    if (!refStars) {
    4343        psError(PS_ERR_UNKNOWN, false, "Unable to find reference stars.");
    4444        psFree(refStars);
  • trunk/ppSim/src/ppSimLoop.c

    r15482 r18011  
    11#include "ppSim.h"
     2
     3# define ESCAPE(CODE,MSG) { \
     4  psError(CODE, false, MSG); \
     5  psFree (rng); \
     6  return false; }
    27
    38bool ppSimLoop(pmConfig *config)
    49{
     10    bool status;
     11
     12    // XXX if we are supplying a PSF, then we should use that to specify the seeing.
     13    // we will need to force the psf to be loaded here (deactivate everyone, activate psf, load
     14    // it, then calculate seeing as appropriate).
     15
    516    PS_ASSERT_PTR_NON_NULL(config, PS_EXIT_PROG_ERROR);
    617
    7     pmFPAfile *file = psMetadataLookupPtr(NULL, config->files, OUTPUT_FILE); // Output file
     18    // in this program, we are looping over the output image, rather than the input as in ppImage
     19    pmFPAfile *file = psMetadataLookupPtr(NULL, config->files, "PPSIM.OUTPUT"); // Output file
    820    assert(file);
     21
    922    pmFPA *fpa = file->fpa;             // FPA for file
    1023    assert(fpa);
    1124
    12     ppSimType type = psMetadataLookupS32(NULL, config->arguments, "TYPE"); // Type of image to simulate
     25    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPSIM_RECIPE); // Recipe
    1326
    1427    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0); // Random number generator
    1528
    16     int binning = psMetadataLookupS32(NULL, config->arguments, "BINNING"); // Binning in x and y
    17 
    18     // Load catalogue stars
     29    char *typeStr = psMetadataLookupStr(NULL, recipe, "IMAGE.TYPE"); // Type of image to simulate
     30    ppSimType type = ppSimTypeFromString (typeStr); // Type of image to simulate
     31    int binning = psMetadataLookupS32(NULL, recipe, "BINNING"); // Binning in x and y
     32
    1933    psArray *stars = psArrayAllocEmpty (1);
    20     if (type == PPSIM_TYPE_OBJECT) {
    21         ppSimLoadStars (stars, fpa, config);
    22     }
    23 
    24     // Add random stars
    25     if (type == PPSIM_TYPE_OBJECT) {
    26         ppSimMakeStars (stars, fpa, config, rng);
    27     }
    28 
    29     // Add random galaxies
    3034    psArray *galaxies = psArrayAllocEmpty (1);
    3135    if (type == PPSIM_TYPE_OBJECT) {
    32         ppSimMakeGalaxies (galaxies, fpa, config, rng);
     36        // Load forced-photometry positions (these are placed on fpa->analysis for use in ppSimPhotomReadout)
     37        if (!ppSimLoadSpots (fpa, config)) ESCAPE (PS_ERR_UNKNOWN, "failed to load forced-photometry spots");
     38
     39        // Load catalogue stars
     40        if (!ppSimLoadStars (stars, fpa, config)) ESCAPE (PS_ERR_UNKNOWN, "failed to load catalog stars");
     41
     42        // Add random stars
     43        if (!ppSimMakeStars (stars, fpa, config, rng)) ESCAPE (PS_ERR_UNKNOWN, "failed to make random stars");
     44
     45        // Add random galaxies
     46        if (!ppSimMakeGalaxies (galaxies, fpa, config, rng)) ESCAPE (PS_ERR_UNKNOWN, "failed to make random galaxies");
    3347    }
    3448
     
    4660
    4761    ppSimUpdateConceptsFPA (fpa, config);
     62    if (fpa->hdu) { // XXX only do this if there is no INPUT image
     63        if (!ppSimInitHeader(config, fpa, NULL, NULL)) ESCAPE (PS_ERR_UNKNOWN, "problem setting output header");
     64    }
    4865
    4966    pmChip *chip;                       // Chip from FPA
     
    98115            psVector *biasCols = ppSimMakeBiassec (cell, config);
    99116
    100             for (int i = 0; i < cell->readouts->n; i++) {
    101 
    102                 pmReadout *readout = cell->readouts->data[i];
    103                 assert (readout);
     117            pmReadout *readout;
     118            while ((readout = pmFPAviewNextReadout (view, fpa, 1))) {
    104119
    105120                // if we have not read in a weight or generated a fake image above, we need to
     
    117132                }
    118133
    119                 psVector *biasRows = ppSimMakeBias (readout, config, rng);
     134                psVector *biasRows = ppSimMakeBias (&status, readout, config, rng);
     135                if (!status) ESCAPE (PS_ERR_UNKNOWN, "problem generating dark structure");
    120136                if (type == PPSIM_TYPE_BIAS) goto done;
    121137
    122                 ppSimMakeDark (readout, config);
     138                if (!ppSimMakeDark (readout, config)) ESCAPE (PS_ERR_UNKNOWN, "problem generating dark structure");
    123139                if (type == PPSIM_TYPE_DARK) goto done;
    124140
    125                 ppSimMakeSky (readout, expCorr, type, config);
     141                if (!ppSimMakeSky (readout, expCorr, type, config)) ESCAPE (PS_ERR_UNKNOWN, "problem generating sky background");
    126142                if (type == PPSIM_TYPE_FLAT) goto done;
    127143
    128144                if (type == PPSIM_TYPE_OBJECT) {
    129                     ppSimInsertStars (readout, expCorr, stars, config);
     145                    if (!ppSimInsertStars (readout, expCorr, stars, config)) ESCAPE (PS_ERR_UNKNOWN, "problem inserting stars");
    130146                }
    131147
    132148                if (type == PPSIM_TYPE_OBJECT) {
    133                     ppSimInsertGalaxies (readout, expCorr, galaxies, config);
     149                    if (!ppSimInsertGalaxies (readout, expCorr, galaxies, config)) ESCAPE (PS_ERR_UNKNOWN, "problem inserting galaxies");
    134150                }
    135151
     
    137153
    138154            done:
    139                 ppSimAddNoise(readout->image, readout->weight, cell, config, rng);
    140                 ppSimSaturate(readout, config);
    141 
    142                 ppSimBadPixels(readout, config, rng);
    143 
    144                 ppSimAddOverscan (readout, config, biasCols, biasRows, rng);
     155                if (!ppSimAddNoise(readout->image, readout->weight, cell, config, rng)) ESCAPE (PS_ERR_UNKNOWN, "problem adding noise");
     156                if (!ppSimSaturate(readout, config)) ESCAPE (PS_ERR_UNKNOWN, "problem setting saturation levels");
     157
     158                if (!ppSimBadPixels(readout, config, rng)) ESCAPE (PS_ERR_UNKNOWN, "problem adding bad pixels");
     159
     160                if (!ppSimAddOverscan (readout, config, biasCols, biasRows, rng)) ESCAPE (PS_ERR_UNKNOWN, "problem adding overscan region");
    145161                psFree(biasRows);
    146162
     
    148164                readout->parent->data_exists = true;
    149165                readout->parent->parent->data_exists = true;
     166
     167                // if there is an input image, merge it with the simulated image
     168                if (!ppSimMergeReadouts (config, view)) ESCAPE (PS_ERR_UNKNOWN, "problem merging input image with simulated image");
    150169            }
    151170            psFree(biasCols);
    152171
    153             ppSimUpdateConceptsCell (cell, config);
     172            if (!ppSimUpdateConceptsCell (cell, config)) ESCAPE (PS_ERR_UNKNOWN, "problem updating cell concepts");
    154173
    155174            if (cell->hdu) {
    156                 ppSimInitHeader(config, NULL, NULL, cell);
     175                // XXX only do this if there is no INPUT image?
     176                if (!ppSimInitHeader(config, NULL, NULL, cell)) ESCAPE (PS_ERR_UNKNOWN, "problem setting output header");
    157177            }
    158178
     
    166186        }
    167187
     188        // XXX why no UpdateConceptsChip??
     189
    168190        if (chip->hdu) {
    169             ppSimInitHeader(config, NULL, chip, NULL);
    170         }
     191            // XXX only do this if there is no INPUT image
     192            if (!ppSimInitHeader(config, NULL, chip, NULL)) ESCAPE (PS_ERR_UNKNOWN, "problem setting output header");
     193        }
     194
     195        // we perform photometry on the readouts of this chip in the output
     196        if (!ppSimPhotom (config, view)) ESCAPE (PS_ERR_UNKNOWN, "problem performing photometry");
    171197
    172198        if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
     
    174200            psFree(rng);
    175201            psFree(view);
    176             // return PS_EXIT_SYS_ERROR;
    177202            return false;
    178203        }
    179 
    180204    }
    181205
    182206    psFree(stars);
    183207    psFree(galaxies);
    184 
    185     if (fpa->hdu) {
    186         ppSimInitHeader(config, fpa, NULL, NULL);
    187     }
    188208
    189209    if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
     
    191211        psFree(rng);
    192212        psFree(view);
    193         // return PS_EXIT_SYS_ERROR;
    194213        return false;
    195214    }
  • trunk/ppSim/src/ppSimMakeBias.c

    r17557 r18011  
    11# include "ppSim.h"
    22
    3 psVector *ppSimMakeBias (pmReadout *readout, pmConfig *config, const psRandom *rng) {
     3psVector *ppSimMakeBias (bool *status, pmReadout *readout, pmConfig *config, const psRandom *rng) {
    44
    55    bool mdok;
     6
     7    if (status) *status = true;
    68
    79    pmCell *cell = readout->parent;
    810
    911    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPSIM_RECIPE); // Recipe
     12
     13    bool bias = psMetadataLookupBool(&mdok, recipe, "BIAS"); // Generate a Bias?
     14    if (!bias) return NULL;
    1015
    1116    float biasLevel = psMetadataLookupF32(NULL, recipe, "BIAS.LEVEL"); // Bias level
     
    1924        if (!mdok) {
    2025            psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Unable to find READNOISE in recipe.");
     26            *status = false;
    2127            return NULL;
    2228        }
  • trunk/ppSim/src/ppSimMakeBiassec.c

    r14463 r18011  
    66
    77    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPSIM_RECIPE); // Recipe
     8
     9    bool bias = psMetadataLookupBool(&mdok, recipe, "BIAS"); // Generate a Bias?
     10    if (!bias) return NULL;
    811
    912    psList *biassec = psMetadataLookupPtr(NULL, cell->concepts, "CELL.BIASSEC"); // Bias regions
  • trunk/ppSim/src/ppSimMakeDark.c

    r17557 r18011  
    1111    psMetadata *recipe = psMetadataLookupMetadata(&mdok, config->recipes, PPSIM_RECIPE); // Recipe
    1212
    13     float darkRate = psMetadataLookupF32(NULL, recipe, "DARK.RATE"); // Dark rate
    14     float expTime  = psMetadataLookupF32(NULL, recipe, "EXPTIME"); // Exposure time
     13    bool dark = psMetadataLookupBool(&mdok, recipe, "DARK"); // Generate a DARK?
     14    if (!dark) return true;
     15
     16    float darkRate = psMetadataLookupF32(&mdok, recipe, "DARK.RATE"); // Dark rate
     17    if (isnan(darkRate)) {
     18      psError(PS_ERR_UNKNOWN, false, "missing DARK.RATE\n");
     19      return false;
     20    }
     21
     22    float expTime  = psMetadataLookupF32(&mdok, recipe, "EXPTIME"); // Exposure time
     23    if (isnan(expTime)) {
     24      psError(PS_ERR_UNKNOWN, false, "missing EXPTIME\n");
     25      return false;
     26    }
     27
     28    psTrace("ppSim", 6, "darkRate: %f, expTime: %f\n", darkRate, expTime);
    1529
    1630    for (int y = 0; y < signal->numRows; y++) {
  • trunk/ppSim/src/ppSimMakeGalaxies.c

    r17557 r18011  
    99
    1010    bool galaxyFake = psMetadataLookupBool(&mdok, recipe, "GALAXY.FAKE"); // Density of fakes
    11     if (!galaxyFake) return NULL;
     11    if (!galaxyFake) return true;
    1212
    1313    float galaxyLum       = psMetadataLookupF32(&mdok, recipe, "GALAXY.LUM"); // Galaxy luminosity func slope
     
    3535    float zp              = psMetadataLookupF32(&mdok, recipe, "ZEROPOINT"); // Photometric zero point
    3636    float seeing          = psMetadataLookupF32(&mdok, recipe, "SEEING"); // Seeing sigma (pix)
    37     float scale           = psMetadataLookupF32(&mdok, recipe, "SCALE") * M_PI / 3600.0 / 180.0; // Plate scale (radians/pixel)
     37    float scale           = psMetadataLookupF32(&mdok, recipe, "PIXEL.SCALE") * M_PI / 3600.0 / 180.0; // Plate scale (radians/pixel)
    3838    float skyRate         = psMetadataLookupF32(&mdok, recipe, "SKY.RATE"); // Sky rate
    3939    if (isnan(skyRate)) {
     
    4242    }
    4343
    44     if (galaxyDensity <= 0) return NULL;
     44    if (galaxyDensity <= 0) return true;
    4545
    4646    // Size of FPA
     
    6666        psLogMsg("ppSim", PS_LOG_INFO,
    6767                 "Image noise is above brightest random galaxy --- no random galaxy added.");
    68         return NULL;
     68        return true;
    6969    }
    7070
     
    138138        }
    139139    }
    140     return galaxies;
     140    return true;
    141141}
  • trunk/ppSim/src/ppSimMakeSky.c

    r17557 r18011  
    11# include "ppSim.h"
    22
    3 // XXX add bounds to the inputs?
     3// this function sets the skyRate to a value for the night sky (SKY.RATE or SKY.MAGS) or for a
     4// flat-field image (FLAT.RATE).  Include a shutter correction and a scattered light source
     5
    46bool ppSimMakeSky (pmReadout *readout, psImage *expCorr, ppSimType type, pmConfig *config) {
    57
     
    1517    psMetadata *recipe = psMetadataLookupMetadata(&status, config->recipes, PPSIM_RECIPE); // Recipe
    1618
    17     float expTime     = psMetadataLookupF32(&status, recipe, "EXPTIME"); // Exposure time
    18     float flatSigma   = psMetadataLookupF32(&status, recipe, "FLAT.SIGMA"); // Flat-field coefficient
    19     float flatRate    = psMetadataLookupF32(&status, recipe, "FLAT.RATE"); // Flat-field rate
    20     float shutterTime = psMetadataLookupF32(&status, recipe, "SHUTTER.TIME"); // Shutter time
    21     float skyRate     = psMetadataLookupF32(&status, recipe, "SKY.RATE"); // Sky rate
    22     if (isnan(skyRate)) {
    23         float zp      = psMetadataLookupF32(&status, recipe, "ZEROPOINT"); assert (status);
    24         float scale   = psMetadataLookupF32(&status, recipe, "SCALE");     assert (status);
    25         float skyMags = psMetadataLookupF32(&status, recipe, "SKY.MAGS");  assert (status);
     19    bool sky  = psMetadataLookupBool(&status, recipe, "SKY"); // Generate a SKY flux?
     20    bool flat = psMetadataLookupBool(&status, recipe, "FLAT"); // Apply flat-field term?
     21 
     22    float expTime      = psMetadataLookupF32(&status, recipe, "EXPTIME"); // Exposure time
     23
     24    float flatSigma    = psMetadataLookupF32(&status, recipe, "FLAT.SIGMA"); // Flat-field coefficient
     25    float flatRate     = psMetadataLookupF32(&status, recipe, "FLAT.RATE"); // Flat-field rate
     26    float shutterTime  = psMetadataLookupF32(&status, recipe, "SHUTTER.TIME"); // Shutter time
     27    float scatterFrac  = psMetadataLookupF32(&status, recipe, "SCATTER.FRAC"); // scattered light fraction (max)
     28    float skyRate      = psMetadataLookupF32(&status, recipe, "SKY.RATE"); // Sky rate
     29    float skyMags      = psMetadataLookupF32(&status, recipe, "SKY.MAGS");  assert (status);
     30    if (!isnan(skyMags)) {
     31        float zp       = psMetadataLookupF32(&status, recipe, "ZEROPOINT"); assert (status);
     32        float scale    = psMetadataLookupF32(&status, recipe, "PIXEL.SCALE"); assert (status);
    2633        skyRate = scale * scale * ppSimMagToFlux (skyMags, zp);
     34    }
     35    if (type == PPSIM_TYPE_FLAT) {
     36      skyRate = flatRate;
    2737    }
    2838
     
    3747    int yParityCell   = psMetadataLookupS32(&status, cell->concepts, "CELL.YPARITY");
    3848
    39     int binning = psMetadataLookupS32(NULL, config->arguments, "BINNING"); // Binning in x and y
     49    int binning = psMetadataLookupS32(NULL, recipe, "BINNING"); // Binning in x and y
    4050
    4151    // Size of FPA
    4252    psRegion *bounds = ppSimFPABounds (fpa);
     53    int dXfpa = bounds->x1 - bounds->x0;
     54    int dYfpa = bounds->y1 - bounds->y0;
    4355
    4456    // Correct chip offsets so that boresight is in the middle of the FPA
    45     x0Chip -= 0.5 * (bounds->x1 - bounds->x0);
    46     y0Chip -= 0.5 * (bounds->y1 - bounds->y0);
     57    x0Chip -= 0.5 * dXfpa;
     58    y0Chip -= 0.5 * dYfpa;
    4759
    4860    for (int y = 0; y < signal->numRows; y++) {
     
    5870            float realExpTime = expTime + shutterTime * (xFPA + yFPA + 2.0) / 4.0;
    5971
    60             // Gaussian flat-field over the FPA
    61             float flatValue = expf(-0.5 / PS_SQR(flatSigma) * (PS_SQR(yFPA) + PS_SQR(xFPA))) /
    62                 flatSigma / sqrtf(2.0 * M_PI);
     72            // Gaussian flat-field over the FPA with flatValue = 1.0 at the field center
     73            float flatValue = 1.0;
     74            if (flat) {
     75                // we make the flat-field have a response of 1.0 at the field center (like a vignetting)
     76                flatValue = expf(-0.5 / PS_SQR(flatSigma) * (PS_SQR(yFPA) + PS_SQR(xFPA)));
     77            }
    6378
    64             if (type == PPSIM_TYPE_FLAT) {
    65                 float flatFlux = flatRate * flatValue * realExpTime; // Flux from flat-field
    66                 signal->data.F32[y][x] += flatFlux;
    67                 variance->data.F32[y][x] += flatFlux;
    68                 continue;
    69             }
     79            float scatterRate = 0.0;
    7080
    71             expCorr->data.F32[y][x] = realExpTime / expTime;
     81            if (sky) {
     82              // add a scattered light term to the flat-field images (no
     83              if (type == PPSIM_TYPE_FLAT) {
     84                float xF = 2.0*(xFPA / dXfpa) - 1.0;
     85                scatterRate = scatterFrac * PS_SQR(xF);
     86              }
    7287
    73             // Sky background
    74             float skyFlux = skyRate * flatValue * realExpTime; // Flux from sky
    75             signal->data.F32[y][x] += skyFlux;
    76             variance->data.F32[y][x] += skyFlux;
     88              // Sky background
     89              float skyFlux = (skyRate * (flatValue + scatterRate)) * realExpTime; // Flux from sky
     90              signal->data.F32[y][x] += skyFlux;
     91              variance->data.F32[y][x] += skyFlux;
     92            }
     93
     94            // used later to modify the star and galaxy photometry
     95            if (expCorr) {
     96              expCorr->data.F32[y][x] = realExpTime / expTime;
     97            }
    7798
    7899            // TO DO: Add fringes
  • trunk/ppSim/src/ppSimMakeStars.c

    r17616 r18011  
    11# include "ppSim.h"
     2
     3# define ESCAPE(MSG) { \
     4  psError(PS_ERR_BAD_PARAMETER_VALUE, true, MSG); \
     5  return false; }
    26
    37bool ppSimMakeStars(psArray *stars, pmFPA *fpa, pmConfig *config, const psRandom *rng) {
     
    2327    float zp           = psMetadataLookupF32(&status, recipe, "ZEROPOINT"); // Photometric zero point
    2428    float seeing       = psMetadataLookupF32(&status, recipe, "SEEING"); // Seeing SIGMA (pixels)
    25     float scale        = psMetadataLookupF32(&status, recipe, "SCALE") * M_PI / 3600.0 / 180.0; // Plate scale (radians/pixel)
     29    float scale        = psMetadataLookupF32(&status, recipe, "PIXEL.SCALE") * M_PI / 3600.0 / 180.0; // Plate scale (radians/pixel)
     30
     31    if (isnan(darkRate)) darkRate = 0.0;
     32    if (isnan(expTime))  ESCAPE("EXPTIME is not defined");
     33    if (isnan(zp))       ESCAPE("ZEROPOINT is not defined");
     34    if (isnan(seeing))   ESCAPE("SEEING is not defined");
     35    if (isnan(scale))    ESCAPE("PIXEL.SCALE is not defined");
    2636
    2737    bool flatLum       = psMetadataLookupBool(&status,recipe, "STARS.FLAT.LUM"); // were real stars generated?
     
    4757        refMag = psMetadataLookupF32(&status, fpa->concepts, "STARS.REAL.MAG.PEAK"); // Star brightest magnitude
    4858        refSum = psMetadataLookupF32(&status, fpa->concepts, "STARS.REAL.SUM.PEAK"); // Star brightest magnitude
    49         assert (status);
     59
     60        // if we tried and failed to load reference stars, set more artificial limits
     61        if (!status) {
     62            refMag = brightMag;
     63            refSum = 1;
     64        }
    5065    } else {
    5166        refMag = brightMag;
  • trunk/ppSim/src/ppSimPhotom.c

    r17628 r18011  
    88    pmReadout *readout;
    99
     10    psMetadata *recipe = psMetadataLookupMetadata(&status, config->recipes, PPSIM_RECIPE); // Recipe
     11
     12    bool doPhotom = psMetadataLookupBool(&status, recipe, "PHOTOM"); // Density of fakes
     13    if (!doPhotom) return true;
     14   
    1015    psphotModelClassInit ();
    1116
    12     // find or define a pmFPAfile PSPHOT.INPUT
    13     pmFPAfile *input = psMetadataLookupPtr (&status, config->files, "PSPHOT.INPUT");
     17    int blankMask = 0;          // XXX not sure what this should be set to...
     18    ppSimMosaicChip(config, blankMask, view, "PPSIM.FORCE.CHIP", "PPSIM.INPUT");
     19    ppSimMosaicChip(config, blankMask, view, "PPSIM.FAKE.CHIP", "PPSIM.OUTPUT");
     20
     21    // use PPSIM.FAKE.CHIP as the base since it is guaranteed to exist (derived from PPSIM.OUTPUT)
     22    pmFPAfile *input = psMetadataLookupPtr (&status, config->files, "PPSIM.FAKE.CHIP");
    1423    if (!status) {
    15         psError(PSPHOT_ERR_CONFIG, false, "PSPHOT.INPUT I/O file is not defined");
     24        psError(PSPHOT_ERR_CONFIG, false, "PPSIM.FAKE.CHIP I/O file is not defined");
    1625        return false;
    1726    }
    1827
    19     // we make a new copy of the output chip to keep psphot from modifying the output image
    20     // XXX is this needed for ppSim? (yes, unless we do not do photometry and make a simulated image)
    21     pmChip *oldChip = pmFPAviewThisChip (view, input->src);
    22     pmChip *newChip = pmFPAviewThisChip (view, input->fpa);
    23     pmChipCopy (newChip, oldChip);
     28    // XXX If we want to be able to write out both the positive and residual images, we will
     29    // need to define an additional pmFPAfile container, and then make a copy as is done for
     30    // PPIMAGE.CHIP -> PSPHOT.INPUT in ppImage.  At the moment, PPSIM.CHIP will write out the
     31    // mosaicked image with the sources subtracted.
     32
     33    // XXX if input -> PSPHOT.INPUT, which is tied to PPSIM.CHIP with pmFPAfileDefineFromFile,
     34    // then the following code creates the chip copy:
     35    // pmChip *oldChip = pmFPAviewThisChip (view, input->src);
     36    // pmChip *newChip = pmFPAviewThisChip (view, input->fpa);
     37    // pmChipCopy (newChip, oldChip);
    2438
    2539    // iterate over the cells and readout for this chip
     
    3347
    3448            // run the actual photometry analysis
    35             if (!psphotReadout (config, view)) {
     49            if (!ppSimPhotomReadoutFake (config, view)) {
    3650                psError(psErrorCodeLast(), false, "failure in psphotReadout for chip %d, cell %d, readout %d\n", view->chip, view->cell, view->readout);
    3751                return false;
    3852            }
     53            if (!ppSimPhotomReadoutForce (config, view)) {
     54                psError(psErrorCodeLast(), false, "failure in psphotReadout for chip %d, cell %d, readout %d\n", view->chip, view->cell, view->readout);
     55                return false;
     56            }
     57            // ppSimDetectionLimits (config, view);
    3958        }
    4059    }
  • trunk/ppSim/src/ppSimSetPSF.c

    r17557 r18011  
    2121    float seeing   = psMetadataLookupF32(&status, recipe, "SEEING"); // Seeing SIGMA (pixels)
    2222
    23     char *psfModelName = psMetadataLookupStr(&status, config->arguments, "PSF.MODEL"); // Name of PSF model
     23    char *psfModelName = psMetadataLookupStr(&status, recipe, "PSF.MODEL"); // Name of PSF model
    2424    if (psfModelName == NULL) {
    2525        psfModelName = defaultModel;
  • trunk/ppSim/src/ppSimUtils.c

    r17557 r18011  
    1515    float dec0  = psMetadataLookupF32(NULL, recipe, "DEC"); // Boresight Dec (radians)
    1616    float pa    = psMetadataLookupF32(NULL, recipe, "PA");  // Position angle (radians)
    17     float scale = psMetadataLookupF32(NULL, recipe, "SCALE"); // plate scale in arcsec / pixel
     17    float scale = psMetadataLookupF32(NULL, recipe, "PIXEL.SCALE"); // plate scale in arcsec / pixel
    1818    scale *= M_PI / 3600.0 / 180.0; // convert plate scale to radians/pixel
    1919
    20     int binning = psMetadataLookupS32(NULL, config->arguments, "BINNING"); // Binning in x and y
     20    int binning = psMetadataLookupS32(NULL, recipe, "BINNING"); // Binning in x and y
    2121
    2222    float x0 = 0.0, y0 = 0.0;
     
    9595}
    9696
     97char *ppSimTypeToString (ppSimType type) {
     98
     99    char *typeStr;
     100
     101    switch (type) {
     102      case PPSIM_TYPE_BIAS:   typeStr = psStringCopy ("BIAS");   break;
     103      case PPSIM_TYPE_DARK:   typeStr = psStringCopy ("DARK");   break;
     104      case PPSIM_TYPE_FLAT:   typeStr = psStringCopy ("FLAT");   break;
     105      case PPSIM_TYPE_OBJECT: typeStr = psStringCopy ("OBJECT"); break;
     106      default:
     107        psAbort("Should never get here.");
     108    }
     109    return (typeStr);
     110}
     111
     112ppSimType ppSimTypeFromString (char *typeStr) {
     113
     114    if (!strcasecmp (typeStr, "BIAS"))   return PPSIM_TYPE_BIAS;
     115    if (!strcasecmp (typeStr, "DARK"))   return PPSIM_TYPE_DARK;
     116    if (!strcasecmp (typeStr, "FLAT"))   return PPSIM_TYPE_FLAT;
     117    if (!strcasecmp (typeStr, "OBJECT")) return PPSIM_TYPE_OBJECT;
     118    psAbort("Should never get here.");
     119}
     120
    97121bool ppSimUpdateConceptsFPA (pmFPA *fpa, pmConfig *config) {
    98122
     
    103127    float expTime = psMetadataLookupF32(NULL, recipe, "EXPTIME"); // Exposure time
    104128
    105     const char *filter = psMetadataLookupStr(NULL, config->arguments, "FILTER"); // Filter name
     129    const char *filter = psMetadataLookupStr(NULL, recipe, "FILTER"); // Filter name
    106130    if (!filter) {
    107131        filter = "NONE";
    108132    }
    109133
    110     ppSimType type = psMetadataLookupS32(NULL, config->arguments, "TYPE"); // Type of image to simulate
    111 
    112     // Update FPA concepts
    113     const char *typeStr;                // Exposure type String
    114     switch (type) {
    115       case PPSIM_TYPE_BIAS:   typeStr = "BIAS";   break;
    116       case PPSIM_TYPE_DARK:   typeStr = "DARK";   break;
    117       case PPSIM_TYPE_FLAT:   typeStr = "FLAT";   break;
    118       case PPSIM_TYPE_OBJECT: typeStr = "OBJECT"; break;
    119       default:
    120         psAbort("Should never get here.");
    121     }
    122 
    123     psMetadataAddStr(fpa->concepts, PS_LIST_TAIL, "FPA.OBSTYPE", PS_META_REPLACE,
    124                      "Observation type", typeStr);
    125     psMetadataAddStr(fpa->concepts, PS_LIST_TAIL, "FPA.OBJECT", PS_META_REPLACE,
    126                      "Observation name", typeStr);
    127     psMetadataAddF32(fpa->concepts, PS_LIST_TAIL, "FPA.EXPTIME", PS_META_REPLACE,
    128                      "Exposure time (sec)", expTime);
     134    char *typeStr = psMetadataLookupStr(NULL, recipe, "IMAGE.TYPE"); // Type of image to simulate
     135
     136    psMetadataAddStr(fpa->concepts, PS_LIST_TAIL, "FPA.OBSTYPE", PS_META_REPLACE, "Observation type", typeStr);
     137    psMetadataAddStr(fpa->concepts, PS_LIST_TAIL, "FPA.OBJECT", PS_META_REPLACE, "Observation name", typeStr);
     138    psMetadataAddF32(fpa->concepts, PS_LIST_TAIL, "FPA.EXPOSURE", PS_META_REPLACE, "Exposure time (sec)", expTime);
    129139    psMetadataAddStr(fpa->concepts, PS_LIST_TAIL, "FPA.FILTERID", PS_META_REPLACE, "Filter name", filter);
    130140    psMetadataAddStr(fpa->concepts, PS_LIST_TAIL, "FPA.FILTER", PS_META_REPLACE, "Filter name", filter);
     
    139149    psMetadata *recipe = psMetadataLookupMetadata(&mdok, config->recipes, PPSIM_RECIPE); // Recipe
    140150
    141     int binning = psMetadataLookupS32(NULL, config->arguments, "BINNING"); // Binning in x and y
     151    int binning = psMetadataLookupS32(NULL, recipe, "BINNING"); // Binning in x and y
    142152    float expTime = psMetadataLookupF32(NULL, recipe, "EXPTIME"); // Exposure time
    143153
     
    153163    return true;
    154164}
     165
     166bool ppSimRecipeValidation (pmConfig *config) {
     167
     168    bool status;
     169
     170    psMetadata *recipe = psMetadataLookupMetadata(&status, config->recipes, PPSIM_RECIPE); // Recipe
     171
     172    int binning = psMetadataLookupS32(&status, recipe, "BINNING"); // Binning in x and y
     173    if (binning <= 0) {
     174        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Binning (%d) is non-positive.", binning);
     175        exit(PS_EXIT_CONFIG_ERROR);
     176    }
     177    return true;
     178}
     179
     180// Get a value from the command-line arguments and add it to recipe options
     181float ppSimArgToRecipeF32(bool *status,
     182                          psMetadata *options,    // Target to which to add value
     183                          const char *recipeName, // Name for value in the recipe
     184                          psMetadata *arguments,  // Command-line arguments
     185                          const char *argName       // Argument name in the command-line arguments
     186    )
     187{
     188    bool myStatus;
     189    float value = psMetadataLookupF32(&myStatus, arguments, argName); // Value of interest
     190    if (status) { *status = myStatus; }
     191    if (isnan(value)) return value;
     192
     193    psMetadataAddF32(options, PS_LIST_TAIL, recipeName, PS_META_REPLACE, NULL, value);
     194    return value;
     195}
     196
     197// Get a value from the command-line arguments and add it to recipe options
     198int ppSimArgToRecipeS32(bool *status,
     199                        psMetadata *options,    // Target to which to add value
     200                        const char *recipeName, // Name for value in the recipe
     201                        psMetadata *arguments,  // Command-line arguments
     202                        const char *argName         // Argument name in the command-line arguments
     203    )
     204{
     205    bool myStatus;
     206    int value = psMetadataLookupS32(&myStatus, arguments, argName); // Value of interest
     207    if (status) { *status = myStatus; }
     208
     209    psMetadataAddS32(options, PS_LIST_TAIL, recipeName, PS_META_REPLACE, NULL, value);
     210    return value;
     211}
     212
     213// Get a value from the command-line arguments and add it to recipe options
     214bool ppSimArgToRecipeBool(bool *status,
     215                          psMetadata *options,    // Target to which to add value
     216                          const char *recipeName, // Name for value in the recipe
     217                          psMetadata *arguments,  // Command-line arguments
     218                          const char *argName       // Argument name in the command-line arguments
     219    )
     220{
     221    bool myStatus;
     222    bool value = psMetadataLookupS32(&myStatus, arguments, argName); // Value of interest
     223    if (status) { *status = myStatus; }
     224
     225    psMetadataAddBool(options, PS_LIST_TAIL, recipeName, PS_META_REPLACE, NULL, value);
     226    return value;
     227}
     228
     229// Get a value from the command-line arguments and add it to recipe options
     230char *ppSimArgToRecipeStr(bool *status,
     231                          psMetadata *options,    // Target to which to add value
     232                          const char *recipeName, // Name for value in the recipe
     233                          psMetadata *arguments,  // Command-line arguments
     234                          const char *argName       // Argument name in the command-line arguments
     235    )
     236{
     237    bool myStatus;
     238
     239    char *value = psMetadataLookupStr(&myStatus, arguments, argName); // Value of interest
     240    if (status) {
     241        *status = myStatus;
     242    }
     243    psMetadataAddStr(options, PS_LIST_TAIL, recipeName, PS_META_REPLACE, NULL, value);
     244    return value;
     245}
     246
     247float ppSimGetZeroPoint (psMetadata *recipe, char *filter) {
     248
     249    bool mdok;
     250    float zp;
     251
     252    // use the filter to get the zeropoint from the recipe
     253    psMetadataItem *zpItem = psMetadataLookup (recipe, "ZEROPTS");
     254    // check that item is multi...
     255           
     256    psArray *entries = psListToArray (zpItem->data.list);
     257         
     258    // search for matching filter
     259    for (int i = 0; i < entries->n; i++) {
     260        psMetadataItem *item = entries->data[i];
     261        psMetadata *entry = item->data.V;
     262
     263        char *filterName = psMetadataLookupStr (&mdok, entry, "FILTER");
     264        assert (filterName);
     265
     266        if (strcmp(filterName, filter)) continue;
     267
     268        zp = psMetadataLookupF32 (&mdok, entry, "ZERO_PT");
     269        assert (mdok);
     270        psFree (entries);
     271        return zp;
     272    }
     273    psFree (entries);
     274    return NAN;
     275}
     276
     277psArray *ppSimSelectSources (pmConfig *config, const pmFPAview *view, const char *filename) {
     278
     279    pmReadout *readout = pmFPAfileThisReadout (config->files, view, filename);
     280    PS_ASSERT_PTR_NON_NULL (readout, NULL);
     281
     282    psArray *sources = psMetadataLookupPtr (NULL, readout->analysis, "PSPHOT.SOURCES");
     283    return sources;
     284}
     285
     286bool ppSimDefinePixels (psArray *sources, pmReadout *readout, psMetadata *recipe) {
     287
     288    bool status;
     289
     290    float OUTER = psMetadataLookupF32 (&status, recipe, "SKY_OUTER_RADIUS");
     291    if (!status) return NULL;
     292
     293    for (int i = 0; i < sources->n; i++) {
     294        pmSource *source = sources->data[i];
     295
     296        // allocate image, weight, mask arrays for each peak (square of radius OUTER)
     297        pmSourceDefinePixels (source, readout, source->peak->x, source->peak->y, OUTER);
     298    }
     299    return true;
     300}
     301
Note: See TracChangeset for help on using the changeset viewer.