IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 34377


Ignore:
Timestamp:
Sep 2, 2012, 12:41:50 PM (14 years ago)
Author:
eugene
Message:

various functions to support satstar profiles (add, sub, add noise, get mags)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ipp-20120805/psphot/src/psphotDeblendSatstars.c

    r34369 r34377  
    1010
    1111bool psImageQuickStats (QuickStats *stats, psImage *image, psRegion region);
    12 
    13 bool  psphotTestRadialModel (pmSource *source, psVector **logRmodelOut, psVector **logFmodelOut, psVector *logFlux, psVector *logRad, float Rmax);
    14 bool  psphotTestRadialModelSub (pmSource *source, psVector *logRmodel, psVector *logFmodel, float Xo, float Yo, float Rmax, psImageMaskType maskVal);
    15 bool  psphotVisualRadialProfileSatstar (pmSource *source, psImageMaskType maskVal);
    1612float InterpolateValues (float X0, float Y0, float X1, float Y1, float X);
    17 bool  psphotVisualScaleImage (int kapaFD, psImage *inImage, psImage *inMask, const char *name, float factor, int channel);
     13bool psphotVisualScaleImage (int kapaFD, psImage *inImage, psImage *inMask, const char *name, float factor, int channel);
    1814
    1915// for now, let's store the detections on the readout->analysis for each readout
     
    4642    TBD:
    4743
    48     1) carry the radial profile out of this function (element of pmSource)
    49     2) function to replace the radial profile for a source
    50     3) recenter the profile (based)
     44    * function to replace the radial profile for a source
     45    * recenter the profile (based on cross-correlation / convolution with 1D profile)
     46
     47    * raise a bit somewhere for these super saturated stars (if they were so modeled)
     48    * consider the subtraction bit : when to raise it?
    5149
    5250 **/
     
    171169        source->mode |= PM_SOURCE_MODE_BIG_RADIUS;
    172170
     171        if (!psphotSatstarProfileModel (source, maskVal)) continue;
     172
     173        source->mode |= PM_SOURCE_MODE_SATSTAR; // yes, this source IS saturated
     174        source->mode2 |= PM_SOURCE_MODE2_SATSTAR_PROFILE; // and we have in fact subtracted the profile
     175
    173176        // XXX visualize, model, and subtract
    174         if (!psphotVisualRadialProfileSatstar (source, maskVal)) {
    175           break;
    176         }
     177        // if (!psphotVisualRadialProfileSatstar (source, maskVal)) {
     178        // break;
     179        // }
    177180
    178181        // generate radial profile, store on the source structure
     
    392395}
    393396
     397// create a model for the radial profile of a saturated star (is this actually more generic?)
     398bool psphotSatstarProfileModel (pmSource *source, psImageMaskType maskVal) {
     399
     400    // XXX user define somewhere?
     401    float Rmax = 320.0;
     402
     403    // XXX is this ever the case??
     404    bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
     405    if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     406
     407    int nPts = source->pixels->numRows * source->pixels->numCols;
     408    psVector *logR = psVectorAllocEmpty (nPts, PS_TYPE_F32);
     409    psVector *flux = psVectorAllocEmpty (nPts, PS_TYPE_F32);
     410
     411    int ng = 0;
     412
     413    // choose the best center for this profile
     414    float Xo = NAN;
     415    float Yo = NAN;
     416
     417    if (source->modelPSF) {
     418        // XXX do we ever have a PSF model for a SATSTAR?
     419        Xo = source->modelPSF->params->data.F32[PM_PAR_XPOS];
     420        Yo = source->modelPSF->params->data.F32[PM_PAR_YPOS];
     421    } else {
     422        Xo = source->moments->Mx;
     423        Yo = source->moments->My;
     424    }
     425
     426    float Xc = Xo - source->pixels->col0 - 0.5;
     427    float Yc = Yo - source->pixels->row0 - 0.5;
     428
     429    for (int iy = 0; iy < source->pixels->numRows; iy++) {
     430        for (int ix = 0; ix < source->pixels->numCols; ix++) {
     431            if ((source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & maskVal)) continue;
     432            // XXX do this faster by generating R^2 and returning 0.5*log10(R^2)?
     433            logR->data.F32[ng] = log10(hypot (ix - Xc, iy - Yc));
     434            flux->data.F32[ng] = source->pixels->data.F32[iy][ix];
     435            ng++;
     436        }
     437    }
     438    logR->n = ng;
     439    flux->n = ng;
     440
     441    // XXX do something sensible here if there are no pixels
     442
     443    // measure the radial profile
     444    psVector *logFmodel = NULL;
     445    psVector *logRmodel = NULL;
     446    psphotSatstarProfileCreate (source, &logRmodel, &logFmodel, logR, flux, Rmax);
     447   
     448    // XXX do something sensible here if the profile is crap
     449
     450    source->satstar = pmSourceSatstarAlloc();
     451    source->satstar->Xo = Xo;
     452    source->satstar->Yo = Yo;
     453    source->satstar->Rmax = Rmax;
     454    source->satstar->logFmodel = logFmodel;
     455    source->satstar->logRmodel = logRmodel;
     456
     457    // subtract the profile (false => subtract)
     458    psphotSatstarProfileOp (source, maskVal, 1.0, 0, false);
     459
     460    psFree (logR);
     461    psFree (flux);
     462
     463    return true;
     464}
     465
     466// Take logR + flux and generate radial bins logRmodelOut, logFmodelOut
     467bool psphotSatstarProfileCreate (pmSource *source, psVector **logRmodelOut, psVector **logFmodelOut, psVector *logR, psVector *flux, float Rmax) {
     468
     469  // we have log(radius) & log(flux).  find the median flux in log radial bins
     470
     471  float logRmax = log10(Rmax);
     472  float logRdel = 0.1; // XXX user-define?
     473
     474  psVector *logRmodel = psVectorAlloc (1 + (int) (logRmax / logRdel), PS_TYPE_F32);
     475  psVector *logFmodel = psVectorAlloc (1 + (int) (logRmax / logRdel), PS_TYPE_F32);
     476
     477  pmSourceRadialProfileSortPair (logR, flux);
     478
     479  psStats *fluxStats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN);
     480  psVector *fluxVals = psVectorAllocEmpty (100, PS_TYPE_F32);
     481
     482  int bin = 0;
     483  for (int i = 0; i < logRmodel->n; i++) {
     484   
     485    // bin (i) has log radius range (i*logRdel : (i+1)*logRdel)
     486    float lRmin = logRdel*(i + 0);
     487    float lRmax = logRdel*(i + 1);
     488
     489    // reset the flux vector
     490    fluxVals->n = 0;
     491    psStatsInit (fluxStats);
     492
     493    while (logR->data.F32[bin] < lRmax) {
     494      if (isfinite(flux->data.F32[bin])) {
     495          psVectorAppend (fluxVals, flux->data.F32[bin]);
     496      }
     497      bin ++;
     498    }
     499   
     500    // we have the set of fluxes for this bin; find the median values
     501   
     502    float Rmin = pow(10.0, lRmin);
     503    float Rmax = pow(10.0, lRmax);
     504
     505    float Rmean = (2.0/3.0) * (pow(Rmax, 3.0) - pow(Rmin, 3.0)) / (PS_SQR(Rmax) - PS_SQR(Rmin));
     506    logRmodel->data.F32[i] = log10(Rmean);
     507
     508    float Area = M_PI * (PS_SQR(Rmax) - PS_SQR(Rmin));
     509    if (fluxVals->n < 0.25*Area) {
     510      logFmodel->data.F32[i] = NAN;
     511      continue;
     512    }
     513   
     514    psVectorStats (fluxStats, fluxVals, NULL, NULL, 0);
     515    if (fluxStats->robustMedian > 0.0) {
     516        logFmodel->data.F32[i] = log10(fluxStats->robustMedian);
     517    } else {
     518        logFmodel->data.F32[i] = -3.0;
     519    }
     520    // fprintf (stderr, "R: %f, F: %f +/- %f\n", Rmean, fluxStats->robustMedian, fluxStats->robustStdev);
     521  }
     522
     523  // now how do i use this to subtract a model??
     524  *logRmodelOut = logRmodel;
     525  *logFmodelOut = logFmodel;
     526 
     527  // need to free stuff
     528  psFree (fluxStats);
     529  psFree (fluxVals);
     530
     531  return true;
     532}
     533
     534bool psphotSatstarProfileOp (pmSource *source, psImageMaskType maskVal, float FACTOR, pmModelOpMode mode, bool add) {
     535
     536    int alt;
     537    float logRdel = 0.1;
     538
     539    float Xc = source->satstar->Xo - source->pixels->col0 - 0.5;
     540    float Yc = source->satstar->Yo - source->pixels->row0 - 0.5;
     541    psVector *logRmodel = source->satstar->logRmodel;
     542    psVector *logFmodel = source->satstar->logFmodel;
     543
     544    for (int iy = 0; iy < source->pixels->numRows; iy++) {
     545        for (int ix = 0; ix < source->pixels->numCols; ix++) {
     546            if ((source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & maskVal)) continue;
     547
     548            float radius = hypot (ix - Xc, iy - Yc) ;
     549            float logR = log10(radius);
     550
     551            int bin = (int)(logR / logRdel);
     552
     553            // we are going to interpolate if possible, or extrapolate if necessary
     554            if (bin >= logRmodel->n - 1) bin = logRmodel->n - 1;
     555            if (bin < 0) bin = 0;
     556     
     557            // interpolate to the current radial position
     558            // XXX BIG HACK : skip nan bins for now
     559
     560            float logF0 = logFmodel->data.F32[bin];
     561            float logR0 = logRmodel->data.F32[bin];
     562            if (!isfinite(logF0)) continue;
     563   
     564            // interpolate between closest two bins if possible, extrapolate on ends
     565            if (logR < logR0) {
     566                alt = (bin > 0) ? bin - 1 : bin + 1;
     567            } else {
     568                alt = (bin < logRmodel->n - 1) ? bin + 1 : bin - 1;
     569            }
     570
     571            float logF1 = logFmodel->data.F32[alt];
     572            float logR1 = logRmodel->data.F32[alt];
     573            if (!isfinite(logF1)) continue;
     574
     575            // XXX use linear flux, not logFlux
     576            float logF = InterpolateValues (logR0, logF0, logR1, logF1, logR);
     577            float flux = pow (10.0, logF);
     578
     579            if (mode & PM_MODEL_OP_NOISE) {
     580                if (add) {
     581                    source->variance->data.F32[iy][ix] += FACTOR * flux;
     582                } else {
     583                    source->variance->data.F32[iy][ix] -= FACTOR * flux;
     584                }
     585            } else {
     586                if (add) {
     587                    source->pixels->data.F32[iy][ix] += flux;
     588                } else {
     589                    source->pixels->data.F32[iy][ix] -= flux;
     590                }
     591            }
     592        }
     593    }
     594    return true;
     595}
     596
     597// Take logR + flux and generate radial bins logRmodelOut, logFmodelOut
     598bool psphotSatstarPhotometry (pmSource *source) {
     599
     600    if (!source->satstar) return false;
     601
     602    psVector *logRmodel = source->satstar->logRmodel;
     603    psVector *logFmodel = source->satstar->logFmodel;
     604   
     605    float fluxTotal = 0.0;
     606    float logRdel = 0.1; // XXX user-define (or carry in satstar)
     607
     608    // integrate flux in radial bins
     609    for (int i = 0; i < logRmodel->n; i++) {
     610        // just add up the mean flux in each bin and multiply by the area of the bin
     611       
     612        float logF = logFmodel->data.F32[i];
     613        if (!isfinite(logF)) continue;
     614        float flux = pow(10.0, logF); // this is the mean flux per pixel (ie, surface brightness)
     615
     616        // bin (i) has log radius range (i*logRdel : (i+1)*logRdel)
     617        float lRmin = logRdel*(i + 0);
     618        float lRmax = logRdel*(i + 1);
     619
     620        float Rmin = pow(10.0, lRmin);
     621        float Rmax = pow(10.0, lRmax);
     622
     623        float Area = M_PI * (PS_SQR(Rmax) - PS_SQR(Rmin));
     624
     625        fluxTotal += flux * Area;
     626    }
     627
     628    source->psfMag    = -2.5*log10(fluxTotal);
     629    source->psfMagErr = 0.05;
     630
     631    // XXX I have no idea of a realistic error on the photometry here.  the bottom line is that
     632    // the error is totally dominated by the loss of charge due to saturation.  I am not
     633    // modeling the profile in any real detail other than to follow the radial bins. 
     634
     635    source->extMag    = NAN;
     636    source->apMag     = NAN;
     637    source->apMagRaw  = NAN;
     638    source->apFlux    = fluxTotal;
     639    source->apFluxErr = 0.05*fluxTotal;
     640
     641    return true;
     642}
     643
     644# if (0)
    394645static bool skipDisplay = false;
    395646bool psphotVisualRadialProfileSatstar (pmSource *source, psImageMaskType maskVal) {
     
    743994    return true;
    744995}
    745 
    746 bool psphotTestRadialModel (pmSource *source, psVector **logRmodelOut, psVector **logFmodelOut, psVector *logRad, psVector *logFlux, float Rmax) {
    747 
    748   // we have log(radius) & log(flux).  find the median flux in log radial bins
    749 
    750   float logRmax = log10(Rmax);
    751   float logRdel = 0.1;
    752 
    753   psVector *logRmodel = psVectorAlloc (1 + (int) (logRmax / logRdel), PS_TYPE_F32);
    754   psVector *logFmodel = psVectorAlloc (1 + (int) (logRmax / logRdel), PS_TYPE_F32);
    755 
    756   pmSourceRadialProfileSortPair (logRad, logFlux);
    757 
    758   psStats *fluxStats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN);
    759   psVector *flux = psVectorAllocEmpty (100, PS_TYPE_F32);
    760 
    761   int bin = 0;
    762   for (int i = 0; i < logRmodel->n; i++) {
    763    
    764     // bin (i) has log radius range (i*logRdel : (i+1)*logRdel)
    765     float lRmin = logRdel*(i + 0);
    766     float lRmax = logRdel*(i + 1);
    767 
    768     // reset the flux vector
    769     flux->n = 0;
    770     psStatsInit (fluxStats);
    771 
    772     while (logRad->data.F32[bin] < lRmax) {
    773       if (isfinite(logFlux->data.F32[bin])) {
    774           psVectorAppend (flux, logFlux->data.F32[bin]);
    775       }
    776       bin ++;
    777     }
    778    
    779     // we have the set of fluxes for this bin; find the median values
    780    
    781     float Rmin = pow(10.0, lRmin);
    782     float Rmax = pow(10.0, lRmax);
    783 
    784     float Rmean = (2.0/3.0) * (pow(Rmax, 3.0) - pow(Rmin, 3.0)) / (PS_SQR(Rmax) - PS_SQR(Rmin));
    785     logRmodel->data.F32[i] = log10(Rmean);
    786 
    787     float Area = M_PI * (PS_SQR(Rmax) - PS_SQR(Rmin));
    788     if (flux->n < 0.25*Area) {
    789       logFmodel->data.F32[i] = NAN;
    790       continue;
    791     }
    792    
    793     psVectorStats (fluxStats, flux, NULL, NULL, 0);
    794     if (fluxStats->robustMedian > 0.0) {
    795         logFmodel->data.F32[i] = log10(fluxStats->robustMedian);
    796     } else {
    797         logFmodel->data.F32[i] = -3.0;
    798     }
    799     // fprintf (stderr, "R: %f, F: %f +/- %f\n", Rmean, fluxStats->robustMedian, fluxStats->robustStdev);
    800   }
    801 
    802   // now how do i use this to subtract a model??
    803   *logRmodelOut = logRmodel;
    804   *logFmodelOut = logFmodel;
    805  
    806   // need to free stuff
    807   psFree (fluxStats);
    808   psFree (flux);
    809 
    810   return true;
    811 }
    812 
    813 bool psphotTestRadialModelSub (pmSource *source, psVector *logRmodel, psVector *logFmodel, float Xo, float Yo, float Rmax, psImageMaskType maskVal) {
    814 
    815     int alt;
    816   float logRdel = 0.1;
    817 
    818   for (int iy = 0; iy < source->pixels->numRows; iy++) {
    819     for (int ix = 0; ix < source->pixels->numCols; ix++) {
    820       if ((source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & maskVal)) continue;
    821 
    822       float radius = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ;
    823       float logR = log10(radius);
    824 
    825       int bin = (int)(logR / logRdel);
    826 
    827       // we are going to interpolate if possible, or extrapolate if necessary
    828       if (bin >= logRmodel->n - 1) bin = logRmodel->n - 1;
    829       if (bin < 0) bin = 0;
    830      
    831       // interpolate to the current radial position
    832       // XXX BIG HACK : skip nan bins for now
    833 
    834       float logF0 = logFmodel->data.F32[bin];
    835       float logR0 = logRmodel->data.F32[bin];
    836       if (!isfinite(logF0)) continue;
    837    
    838       // interpolate between closest two bins if possible, extrapolate on ends
    839       if (logR < logR0) {
    840           alt = (bin > 0) ? bin - 1 : bin + 1;
    841       } else {
    842           alt = (bin < logRmodel->n - 1) ? bin + 1 : bin - 1;
    843       }
    844 
    845       float logF1 = logFmodel->data.F32[alt];
    846       float logR1 = logRmodel->data.F32[alt];
    847       if (!isfinite(logF1)) continue;
    848 
    849       // XXX use linear flux, not logFlux
    850       float logF = InterpolateValues (logR0, logF0, logR1, logF1, logR);
    851       float flux = pow (10.0, logF);
    852 
    853       // float flux = InterpolateValues (logR0, logF0, logR1, logF1, logR);
    854       source->pixels->data.F32[iy][ix] -= flux;
    855     }
    856   }
    857   return true;
    858 }
     996# endif
    859997
    860998// only valid for F32
     
    9021040    return true;
    9031041}
     1042
     1043bool psphotAddOrSubSatstarsReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int fileIndex, psMetadata *recipe, bool add) {
     1044
     1045    bool status;
     1046
     1047    psTimerStart ("psphot.deblend.sat");
     1048
     1049    // find the currently selected readout
     1050    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filerule, fileIndex); // File of interest
     1051    psAssert (file, "missing file?");
     1052
     1053    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     1054    psAssert (readout, "missing readout?");
     1055
     1056    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     1057    psAssert (detections, "missing detections?");
     1058
     1059    psArray *sources = detections->allSources;
     1060    psAssert (sources, "missing sources?");
     1061
     1062    if (!sources->n) {
     1063        psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping satstar blend");
     1064        return true;
     1065    }
     1066
     1067    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
     1068    psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
     1069    assert (maskVal);
     1070
     1071    // examine sources in decreasing SN order
     1072    for (int i = 0; i < sources->n; i++) {
     1073        pmSource *source = sources->data[i];
     1074
     1075        if (!(source->mode2 & PM_SOURCE_MODE2_SATSTAR_PROFILE)) continue;
     1076
     1077        if (!psphotSatstarProfileOp (source, maskVal, 1.0, 0, add)) continue;
     1078    }
     1079
     1080    psLogMsg ("psphot", PS_LOG_DETAIL, "satstar op: %f sec\n", psTimerMark ("psphot.deblend.sat"));
     1081    return true;
     1082}
     1083
Note: See TracChangeset for help on using the changeset viewer.