IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
May 7, 2008, 10:55:21 AM (18 years ago)
Author:
eugene
Message:

fix errors with star density normalizations and flux consistency

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/ppSim/src/ppSimMakeStars.c

    r16498 r17557  
    11# include "ppSim.h"
    2 
    3 #define FAINT_FUDGE_FACTOR   0.4        // Fraction of the noise in a (boxcar) PSF for the faint limit
    4 
    52
    63bool ppSimMakeStars(psArray *stars, pmFPA *fpa, pmConfig *config, const psRandom *rng) {
    74
    8     bool mdok;
     5    bool status;
    96    assert (stars);
    107
    11     psMetadata *recipe = psMetadataLookupMetadata(&mdok, config->recipes, PPSIM_RECIPE); // Recipe
     8    psMetadata *recipe = psMetadataLookupMetadata(&status, config->recipes, PPSIM_RECIPE); // Recipe
    129
    13     bool starsFake = psMetadataLookupBool(&mdok, recipe, "STARS.FAKE"); // Density of fakes
     10    bool starsFake = psMetadataLookupBool(&status, recipe, "STARS.FAKE"); // Density of fakes
    1411    if (!starsFake) return true;
    1512
    16     float starsLum = psMetadataLookupF32(NULL, config->arguments, "STARS.LUM"); // Star luminosity func slope
    17     float starsMag = psMetadataLookupF32(NULL, config->arguments, "STARS.MAG"); // Star brightest magnitude
    18     float starsDensity = psMetadataLookupF32(NULL, config->arguments, "STARS.DENSITY"); // Density of fakes
     13    bool starsReal     = psMetadataLookupBool(&status, recipe, "STARS.REAL"); // were real stars generated?
     14    bool matchDensity  = psMetadataLookupBool(&status, recipe, "MATCH.DENSITY"); // match real star density?
    1915
    20     float darkRate = psMetadataLookupF32(NULL, config->arguments, "DARK.RATE"); // Dark rate
    21     float expTime = psMetadataLookupF32(NULL, config->arguments, "EXPTIME"); // Exposure time
     16    float starsAlpha   = psMetadataLookupF32(&status, recipe, "STARS.LUM"); // Star luminosity func slope
     17    float starsDensity = psMetadataLookupF32(&status, recipe, "STARS.DENSITY"); // Density of fakes
     18    float brightMag    = psMetadataLookupF32(&status, recipe, "STARS.MAG"); // Star brightest magnitude
     19    float nSigmaLim    = psMetadataLookupF32(&status, recipe, "STARS.SIGMA.LIM"); // significance of faintest stars
    2220
    23     float zp = psMetadataLookupF32(NULL, config->arguments, "ZEROPOINT"); // Photometric zero point
    24     float seeing = psMetadataLookupF32(NULL, config->arguments, "SEEING"); // Seeing sigma (pix)
    25     float scale = psMetadataLookupF32(NULL, config->arguments, "SCALE") * M_PI / 3600.0 / 180.0; // Plate scale (radians/pixel)
     21    float darkRate     = psMetadataLookupF32(&status, recipe, "DARK.RATE"); // Dark rate
     22    float expTime      = psMetadataLookupF32(&status, recipe, "EXPTIME"); // Exposure time
     23    float zp           = psMetadataLookupF32(&status, recipe, "ZEROPOINT"); // Photometric zero point
     24    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)
    2626
    27     float skyRate = psMetadataLookupF32(&mdok, config->arguments, "SKY.RATE"); // Sky rate
     27    float skyRate = psMetadataLookupF32(&status, recipe, "SKY.RATE"); // Sky rate
    2828    if (isnan(skyRate)) {
    29         float skyMags = psMetadataLookupF32(&mdok, config->arguments, "SKY.MAGS");  assert (mdok);
    30         skyRate = scale * scale * pow (10.0, -0.4*(skyMags - zp));
     29        float skyMags = psMetadataLookupF32(&status, recipe, "SKY.MAGS");  assert (status);
     30        skyRate = scale * scale * ppSimMagToFlux (skyMags, zp);
    3131    }
    32 
    33     if (starsDensity <= 0) return true;
    3432
    3533    // Size of FPA
     
    4038    psFree(bounds);
    4139
     40    // choose reference magnitude & density to set normalization
     41    float refMag = 0;
     42    float refSum = 0;
     43    if (starsReal && matchDensity) {
     44        refMag = psMetadataLookupF32(&status, fpa->concepts, "STARS.REAL.MAG.PEAK"); // Star brightest magnitude
     45        refSum = psMetadataLookupF32(&status, fpa->concepts, "STARS.REAL.SUM.PEAK"); // Star brightest magnitude
     46        assert (status);
     47    } else {
     48        refMag = brightMag;
     49        refSum = starsDensity * xSize * ySize * PS_SQR(scale * 180.0 / M_PI);
     50    }
     51    psTrace("ppSim", 6, "refMag: %f, refSum: %f\n", refMag, refSum);
     52
     53    if (refSum <= 0) return true;
     54
    4255    // Grabbing read noise from the recipe rather than the cell, which is a potential danger, but it
    4356    // shouldn't be too bad.
    44     float readnoise = psMetadataLookupF32(&mdok, recipe, "READNOISE"); // Default read noise
    45     if (!mdok) {
     57    float readnoise = psMetadataLookupF32(&status, recipe, "READNOISE"); // Default read noise
     58    if (!status) {
    4659        psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Unable to find READNOISE in recipe.");
    4760        psFree(bounds);
     
    5063
    5164    // Faintest and brightest (integrated) fluxes (actually fluence, since integrated) for random stars
    52     float faint = FAINT_FUDGE_FACTOR * sqrtf(PS_SQR(readnoise) + (darkRate + skyRate) * expTime) *
    53         (2.0 * sqrt(2.0 * log(2.0)) * seeing); // Faint limit is related to the noise in a (boxcar) PSF
    54     float bright = powf(10.0, -0.4 * (starsMag - zp)) * expTime; // Bright limit is specified by user as mag
    55     psTrace("ppSim", 6, "Faint limit: %f\n", faint);
    56     psTrace("ppSim", 6, "Bright limit: %f\n", bright);
    57     if (bright < faint) {
     65
     66    // faint limit is set by detection limit, in turn set by sky noise
     67    float skySigma = sqrtf(PS_SQR(readnoise) + (darkRate + skyRate) * expTime);
     68    float skyNoise = ppSimStarSkyNoise (skySigma, seeing);
     69
     70    // total flux of faintest star:
     71    float faintCounts = nSigmaLim * skyNoise;
     72    float faintMag = ppSimFluxToMag ((faintCounts / expTime), zp);
     73
     74    float brightCounts = ppSimMagToFlux (brightMag, zp) * expTime; // Bright limit is specified by user as mag
     75
     76    psTrace("ppSim", 6, "Faint limit: %f counts = %f mags\n", faintCounts, faintMag);
     77    psTrace("ppSim", 6, "Bright limit: %f counts = %f mags\n", brightCounts, brightMag);
     78    if (brightCounts < faintCounts) {
    5879        psLogMsg("ppSim", PS_LOG_INFO,
    5980                 "Image noise is above brightest random star --- no random stars added.");
     
    6182    }
    6283
    63     // Normalisation, set by the specified stellar density at the specified bright magnitude
    64     float norm = starsDensity * xSize * ySize * PS_SQR(scale * 180.0 / M_PI) /
    65         powf(bright, starsLum);
     84    // given log_10 (dN / dmag) = alpha mag + beta
     85    // or dN / dmag = No 10^(alpha mag), then:
     86    // N(m < Mo) = alpha * No * log(10.0) * 10^(alpha*Mo)
     87
     88    // XXX this needs to handle the case of a flat distribution for efficiency testing
     89
     90    // Normalization, set by the specified stellar density at the specified bright magnitude
     91    float norm = refSum / (starsAlpha * logf(10.0) * powf(10.0, (starsAlpha * refMag)));
     92    float normScale = norm * starsAlpha * logf(10.0);
    6693
    6794    // Total number of stars down to the faint flux end
    68     long num = expf(logf(norm) + starsLum * logf(faint)) + 0.5;
     95    long nTotal = normScale * powf (10.0, (starsAlpha * faintMag));
    6996
    70     psLogMsg("ppSim", PS_LOG_INFO, "Adding %ld stars down to %f mag\n",
    71              num, -2.5 * log10(faint / expTime) + zp);
     97    psLogMsg("ppSim", PS_LOG_INFO, "Adding %ld stars down to %f mag\n", nTotal, faintMag);
    7298
    7399    long oldSize = stars->n;
    74     psArrayRealloc (stars, stars->n + num);
     100    psArrayRealloc (stars, stars->n + nTotal);
    75101
    76     for (long i = 0; i < num; i++) {
     102    for (long i = 0; i < nTotal; i++) {
    77103        ppSimStar *star = ppSimStarAlloc ();
    78104
     
    81107        star->y    = psRandomUniform(rng) * ySize; // y position
    82108
    83         star->flux = expf((logf(i + 1) - logf(norm)) / starsLum); // Peak flux
    84         star->peak = star->flux / (2.0*M_PI*PS_SQR(seeing));
     109        // XXX this needs to respect the bright limit
     110        float starMag = log10((i + 1.0) / normScale) / starsAlpha;
     111       
     112        star->flux = ppSimMagToFlux (starMag, zp) * expTime;
     113        star->peak = ppSimStarFluxToPeak (star->flux, seeing);
    85114
    86115        stars->data[oldSize + i] = star;
    87116    }
    88     stars->n = oldSize + num;
     117    stars->n = oldSize + nTotal;
    89118
    90119    return true;
Note: See TracChangeset for help on using the changeset viewer.