IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 42842


Ignore:
Timestamp:
May 9, 2025, 11:21:40 AM (14 months ago)
Author:
eugene
Message:

add psphotFindFeatures; enable forced-photometry between cameras; do NOT skip negative-flux sources in full-force photometry; make PSF residual component generation more robust: IRLS vs median; exclude pixels with poor values (scaled value > 1.5, relative to normalized PSF); exclude pixels with too few inputs (<5); allow PSF clump to use clipped stats or robust stats

Location:
trunk/psphot
Files:
17 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/psphot

  • trunk/psphot/src/Makefile.am

    r38386 r42842  
    247247        psphotSetNFrames.c             \
    248248        psphotSourceMemory.c           \
     249        psphotFindFeatures.c           \
    249250        psphotChipParams.c              \
    250251        psphotGalaxyParams.c
  • trunk/psphot/src/psphot.h

    r42088 r42842  
    592592extern bool psphotINpsphotStack;
    593593
     594bool psphotFindFeatures (pmReadout *readout, psArray *sources);
     595
    594596
    595597#endif
  • trunk/psphot/src/psphotArguments.c

    r36375 r42842  
    9797}
    9898
     99void psphotSaveConfig (pmConfig *config);
     100
    99101pmConfig *psphotArguments(int argc, char **argv) {
    100102
     
    244246    psMetadataAddStr (config->arguments, PS_LIST_TAIL, "OUTPUT", 0, "", argv[1]);
    245247
     248    // save a copy for deep retrieval
     249    psphotSaveConfig (config);
     250
    246251    psTrace("psphot", 1, "Done with psphotArguments...\n");
    247252    return (config);
  • trunk/psphot/src/psphotCheckStarDistribution.c

    r30624 r42842  
    8989        if (source->type != PM_SOURCE_TYPE_STAR) continue;
    9090
     91        // XXX for a test, do not include faint sources
     92        // EAM XXX : make this optional and default to all
     93        if (source->moments->SN < 20) continue;
     94
    9195        float x = source->peak->xf;
    9296        float y = source->peak->yf;
  • trunk/psphot/src/psphotChoosePSF.c

    r42380 r42842  
    114114    options->psfTrendNy = psMetadataLookupS32 (&status, recipe, "PSF.TREND.NY");
    115115    assert (status);
     116
     117    // fit the PSF star positions during PSF model analysis (default false)
     118    options->fitPSFstarCoords = psMetadataLookupBool (&status, recipe, "PSF_FIT_STAR_COORDS");
     119    if (!status) {
     120      options->fitPSFstarCoords = false;
     121    }
    116122
    117123    // get the fixed PSF fit radius
  • trunk/psphot/src/psphotDefineFiles.c

    r36375 r42842  
    11# include "psphotInternal.h"
     2pmConfig *pmConfigMakeTemp (pmConfig *config);
    23
    34bool psphotINpsphotStack = false;
     
    143144    }
    144145
     146    // Use a temporary config for the source files, keeping the main user, site,
     147    // system, files, arguments entries.  This allows the sources to be from a
     148    // different camera than the input image.  NOTE: there is no check that these two
     149    // images match in terms of size, pixel scale, etc. That is up to the user.
     150    // The temporary config structure has PSCAMERA entries removed from the SKYCELL rules
     151    // to allow forced photometry between cameras.
     152   
     153    pmConfig *srcconfig = pmConfigMakeTemp(config);
     154
    145155    if (psMetadataLookupPtr(NULL, config->arguments, "SRC")) {
    146         if (!pmFPAfileDefineFromArgs (&status, config, "PSPHOT.INPUT.CMF", "SRC")) {
     156        if (!pmFPAfileDefineFromArgs (&status, srcconfig, "PSPHOT.INPUT.CMF", "SRC")) {
    147157            psError(PSPHOT_ERR_CONFIG, false, "Failed to find/build PSPHOT.INPUT.CMF");
    148158            return status;
     
    151161
    152162    if (psMetadataLookupPtr(NULL, config->arguments, "FORCE")) {
    153         if (!pmFPAfileDefineFromArgs (&status, config, "PSPHOT.INPUT.CFF", "FORCE")) {
     163        if (!pmFPAfileDefineFromArgs (&status, srcconfig, "PSPHOT.INPUT.CFF", "FORCE")) {
    154164            psError(PSPHOT_ERR_CONFIG, false, "Failed to find/build PSPHOT.INPUT.CFF");
    155165            return status;
     
    160170        // XXX cannot use pmFPAfileDefineFromArgs: this is explicitly a FITS-based I/O function
    161171        // supply the attach the
    162         if (!psphotLoadSRCTEXT(input->fpa, config)) {
     172        if (!psphotLoadSRCTEXT(input->fpa, srcconfig)) {
    163173            psError(PSPHOT_ERR_CONFIG, false, "Failed to load PSPHOT.INPUT.TEXT");
    164174            return status;
     
    167177
    168178    if (psMetadataLookupPtr(NULL, config->arguments, "PSPHOT.PSF")) {
    169         pmFPAfileBindFromArgs(&status, input, config, "PSPHOT.PSF.LOAD", "PSPHOT.PSF");
     179        pmFPAfileBindFromArgs(&status, input, srcconfig, "PSPHOT.PSF.LOAD", "PSPHOT.PSF");
    170180        if (!status) {
    171181            psError(PSPHOT_ERR_CONFIG, false, "Failed to find/build PSPHOT.PSF.LOAD");
     
    173183        }
    174184    }
     185
     186    psFree (srcconfig);
    175187
    176188    // XXX add in example PSF image thumbnails
     
    214226    return rule;
    215227}
     228
     229pmConfig *pmConfigMakeTemp (pmConfig *config) {
     230    pmConfig *altconfig = pmConfigAlloc();
     231
     232    // these are NULL on pmConfigAlloc
     233    altconfig->user   = psMemIncrRefCounter(config->user);   // inherit from primary camera
     234    altconfig->site   = psMemIncrRefCounter(config->site);   // inherit from primary camera
     235
     236    psFree (altconfig->system);
     237    altconfig->system = psMetadataCopy(NULL, config->system); // container for camera-specific recipe values (to be dropped)
     238
     239    psFree (altconfig->files);
     240    altconfig->files  = psMemIncrRefCounter(config->files); // inherit from primary camera
     241
     242    psFree (altconfig->arguments);
     243    altconfig->arguments = psMemIncrRefCounter(config->arguments); // inherit from primary camera
     244
     245    psFree (altconfig->recipes);
     246    altconfig->recipes = psMetadataCopy(NULL, config->recipes); // container for camera-specific recipe values (to be dropped)
     247
     248    // remove PSCAMERA entries from *-SKYCELL cameras.  This allows skycell images from
     249    // one camera to match those of another camera.  XXX Make this optional to force
     250    // matching cameras if desired?
     251    bool mdok = false;
     252    psMetadata *cameras = psMetadataLookupMetadata(&mdok, altconfig->system, "CAMERAS");
     253    psAssert(cameras, "missing cameras in system config info");
     254   
     255    // iterate over the cameras and find ones with names like _*-SKYCELLS
     256    // psMetadataIterator *camerasIter = psMetadataIteratorAlloc(cameras, PS_LIST_HEAD, "^_.+-SKYCELL$");
     257    psMetadataIterator *camerasIter = psMetadataIteratorAlloc(cameras, PS_LIST_HEAD, NULL);
     258    psAssert(camerasIter, "unable to generate iterator?");
     259
     260    psMetadataItem *camerasItem = NULL; // Item from the metadata
     261    while ((camerasItem = psMetadataGetAndIncrement(camerasIter))) {
     262      psAssert(camerasItem->type == PS_DATA_METADATA, "camerasItem has invalid type");
     263     
     264      char *name = camerasItem->name;
     265      psAssert (name, "NULL name for item");
     266
     267      int nameLen = strlen(name);
     268      if (name[0] != '_') continue;
     269      if (nameLen <= 9) continue;
     270      char *p = &name[nameLen - 8];
     271      if (strcmp(p, "-SKYCELL")) continue;
     272
     273      // remove PSCAMERA entries from *-SKYCELL cameras
     274      psMetadata *formats = psMetadataLookupMetadata(&mdok, camerasItem->data.md, "FORMATS"); // List of formats
     275      psAssert (formats, "missing FORMATS in camera.config ");
     276
     277      psMetadata *format = psMetadataLookupMetadata(&mdok, formats, "SKYCELL"); // one true format for skycells
     278      psAssert (format, "missing SKYCELL metaformat for -SKYCELL entry ");
     279
     280      psMetadata *rule = psMetadataLookupMetadata(&mdok, format, "RULE"); // one true format for skycells
     281      psAssert (rule, "missing RULE in SKYCELL metaformat for -SKYCELL entry ");
     282
     283      psString pscamera = psMetadataLookupStr(&mdok, rule, "PSCAMERA"); // one true format for skycells
     284      if (!pscamera) continue; // already removed, or never supplied
     285
     286      psMetadataRemoveKey (rule, "PSCAMERA"); // allow any camera skycell to match
     287    }
     288    psFree (camerasIter);
     289
     290    return (altconfig);
     291}
     292
  • trunk/psphot/src/psphotFullForceArguments.c

    r37941 r42842  
    33static void usage(const char *program, psMetadata *arg, pmConfig *config, int exitCode);
    44static void writeHelpInfo(const char* program, pmConfig* config, FILE* ofile);
     5void psphotSaveConfig (pmConfig *config);
    56
    67pmConfig *psphotFullForceArguments(int argc, char **argv) {
     
    111112    // output position is fixed
    112113    psMetadataAddStr (config->arguments, PS_LIST_TAIL, "OUTPUT", 0, "", argv[1]);
     114
     115    psphotSaveConfig (config);
    113116
    114117    psTrace("psphot", 1, "Done with psphotFullForceArguments...\n");
  • trunk/psphot/src/psphotFullForceReadout.c

    r42487 r42842  
    121121      // linear fit to include all sources (subtract again)
    122122      // NOTE : apply to ALL sources (extended + psf)
    123       psphotFitSourcesLinear (config, view, filerule, true, true); // pass 2 (detections->allSources)
     123      // do NOT skip negative-flux sources (last arg = false)
     124      psphotFitSourcesLinear (config, view, filerule, true, false); // pass 2 (detections->allSources)
    124125    }
    125126
  • trunk/psphot/src/psphotFullForceSummary.c

    r40809 r42842  
    322322    int numCols = psMetadataLookupS32(&status, input->fpa->hdu->header, "IMNAXIS1");
    323323    int numRows = psMetadataLookupS32(&status, input->fpa->hdu->header, "IMNAXIS2");
     324    char *photcode   = psMetadataLookupStr(&status, input->fpa->hdu->header, "PHOTCODE");
     325//    char *filter     = psMetadataLookupStr(&status, input->fpa->hdu->header, "FPA.FILTER");
     326//    char *telescope  = psMetadataLookupStr(&status, input->fpa->hdu->header, "FPA.TELESCOPE");
     327//    char *instrument = psMetadataLookupStr(&status, input->fpa->hdu->header, "FPA.INSTRUMENT");
     328//    char *detector   = psMetadataLookupStr(&status, input->fpa->hdu->header, "FPA.DETECTOR");
     329
    324330    psMetadataAddS32(output->fpa->hdu->header, PS_LIST_TAIL, "IMNAXIS1", PS_META_REPLACE, "", numCols);
    325331    psMetadataAddS32(output->fpa->hdu->header, PS_LIST_TAIL, "IMNAXIS2", PS_META_REPLACE, "", numRows);
    326 
     332    psMetadataAddStr(output->fpa->hdu->header, PS_LIST_TAIL, "PHOTCODE", PS_META_REPLACE, "", photcode);
     333
     334    // XXX EAM 20240204 : these are added to the header psMetadata but do not make it out to the file header?
     335    // psMetadataAddStr(output->fpa->hdu->header, PS_LIST_TAIL, "FPA.FILTER", PS_META_REPLACE, "", filter);
     336    // psMetadataAddStr(output->fpa->hdu->header, PS_LIST_TAIL, "FPA.TELESCOPE", PS_META_REPLACE, "", telescope);
     337    // psMetadataAddStr(output->fpa->hdu->header, PS_LIST_TAIL, "FPA.INSTRUMENT", PS_META_REPLACE, "", instrument);
     338    // psMetadataAddStr(output->fpa->hdu->header, PS_LIST_TAIL, "FPA.DETECTOR", PS_META_REPLACE, "", detector);
     339   
    327340    // XXX: Also add psphot version information
    328341
  • trunk/psphot/src/psphotFullForceSummaryReadout.c

    r40809 r42842  
    4545        outputReadout = pmReadoutAlloc(outputCell);
    4646    }
     47
     48    // this requires the readout to exist -- and does not work
     49    // psphotAddPhotcode (config, view, "PSPHOT.FULLFORCE.OUTPUT");
    4750
    4851    // Get the exposure parameters for the output from recipe and set them on the output
  • trunk/psphot/src/psphotMakeResiduals.c

    r35559 r42842  
    11# include "psphotInternal.h"
     2pmConfig *psphotGetConfig ();
     3bool _psphotSaveCube (char *basename, char *extname, psArray *cube);
    24
    35# define RESIDUAL_SOFTENING 0.005
     
    9395    psVector *yC = psVectorAllocEmpty (100, PS_TYPE_F32);
    9496
     97# define TESTRESID 0
     98# if (TESTRESID)
     99    psArray *sourceRawCube = psArrayAllocEmpty (1);
     100    psArray *sourceSigCube = psArrayAllocEmpty (1);
     101    psArray *sourceVarCube = psArrayAllocEmpty (1);
     102    psArray *sourceMskCube = psArrayAllocEmpty (1);
     103
     104    psImage *refImage = NULL;
     105# endif
     106
    95107    // build (DATA - MODEL) [an image] for each psf star
    96108    psArray *input = psArrayAllocEmpty (100);
     
    108120        psImage *mask     = psImageCopy (NULL, source->maskView ? source->maskView : source->maskObj,  PS_TYPE_IMAGE_MASK);
    109121        psImage *variance = psImageCopy (NULL, source->variance ? source->variance : source->pixels,   PS_TYPE_F32);
     122
     123# if (TESTRESID)
     124        psImage *tmpImage = psImageCopy(NULL, image, PS_TYPE_F32);
     125        if (refImage == NULL) {
     126          refImage = tmpImage;
     127          psArrayAdd (sourceRawCube, 1, tmpImage);
     128        } else {
     129          if (tmpImage->numCols != refImage->numCols) {
     130            fprintf (stderr, "mismatched image sizes (%d : %f, %f)\n", i, model->params->data.F32[PM_PAR_XPOS], model->params->data.F32[PM_PAR_YPOS]);
     131            continue;
     132          }
     133          if (tmpImage->numRows != refImage->numRows) {
     134            fprintf (stderr, "mismatched image sizes (%d : %f, %f)\n", i, model->params->data.F32[PM_PAR_XPOS], model->params->data.F32[PM_PAR_YPOS]);
     135            continue;
     136          }
     137          psArrayAdd (sourceRawCube, 1, tmpImage);
     138          psFree (tmpImage);
     139        }
     140# endif
     141
    110142        pmModelSub (image, mask, model, PM_MODEL_OP_FUNC, maskVal);
    111143
     
    114146        psBinaryOp (image, image, "/", psScalarAlloc(Io, PS_TYPE_F32));
    115147        psBinaryOp (variance, variance, "/", psScalarAlloc(Io*Io, PS_TYPE_F32));
     148
     149# if (TESTRESID)
     150        psArrayAdd (sourceSigCube, 1, image);
     151        psArrayAdd (sourceVarCube, 1, variance);
     152        psArrayAdd (sourceMskCube, 1, mask);
     153# endif
    116154
    117155        // we interpolate the image and variance - include the mask or not?
     
    142180    psImageInit (resid->mask, 0);
    143181
     182
     183# if (TESTRESID)
     184    psArray *inputSigCube = psArrayAllocEmpty (1);
     185    psArray *inputVarCube = psArrayAllocEmpty (1);
     186    psArray *inputMskCube = psArrayAllocEmpty (1);
     187
     188    // below, we are generating the residual images with interpolation
     189    // to save these in an output cube, I need to generate place-holder images here
     190    for (int i = 0; i < input->n; i++) {
     191      psImage *inputSig = psImageAlloc (resid->Ro->numCols, resid->Ro->numRows, PS_TYPE_F32);
     192      psImage *inputVar = psImageAlloc (resid->Ro->numCols, resid->Ro->numRows, PS_TYPE_F32);
     193      psImage *inputMsk = psImageAlloc (resid->Ro->numCols, resid->Ro->numRows, PS_TYPE_IMAGE_MASK);
     194
     195      psImageInit (inputSig, NAN);
     196      psImageInit (inputVar, NAN);
     197      psImageInit (inputMsk, 0);
     198
     199      psArrayAdd (inputSigCube, 1, inputSig);
     200      psArrayAdd (inputVarCube, 1, inputVar);
     201      psArrayAdd (inputMskCube, 1, inputMsk);
     202
     203      // XXX free these here, right?
     204      psFree (inputSig);
     205      psFree (inputVar);
     206      psFree (inputMsk);
     207    }
     208# endif
     209
    144210    // x(resid) = (x(image) - Xo)*xBin + xCenter
    145211
     
    148214    psVector *fmasks  = psVectorAlloc (input->n, PS_TYPE_VECTOR_MASK);
    149215
    150     // statistic to use to determine baseline for clipping
    151     psStats *fluxClip     = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);
    152     psStats *fluxClipDef  = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);
    153216    // statistic to use to determine output flux
    154217    // XXX make API to convert statOption for MEAN/MEDIAN in to corresponding STDEV?
     
    156219    psStats *fluxStatsDef = psStatsAlloc (statOption | PS_STAT_SAMPLE_STDEV);
    157220
     221    // use this for the IRLS fitting below (defines niter)
     222    psStats *statsIRLS = psStatsAlloc(PS_STAT_CLIPPED_MEAN); statsIRLS->clipIter = 10; // max number of iterations
     223    psPolynomial2D *polyIRLS = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, 1, 1);
     224
    158225    // Use psF64 to minimize overflow problems?
    159226    psImage *A = psImageAlloc(3, 3, PS_TYPE_F64); // Least-squares matrix
     
    166233
    167234            int nGoodPixel = 0;              // pixel is off the image
     235
     236            // skip pixels outside of the requested radius
     237            float radius = hypot((ox - 0.5*resid->Ro->numCols), (oy - 0.5*resid->Ro->numRows));
     238            if (radius > radiusMax) {
     239              resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = 1;
     240              continue;
     241            }
    168242
    169243            // build the vector of data values for this output pixel
     
    194268                    nGoodPixel ++;
    195269                }
     270
     271# if (TESTRESID)
     272                psImage *inputSig = inputSigCube->data[i]; inputSig->data.F32[oy][ox] = flux;
     273                psImage *inputVar = inputVarCube->data[i]; inputVar->data.F32[oy][ox] = flux;
     274                psImage *inputMsk = inputMskCube->data[i]; inputMsk->data.PS_TYPE_IMAGE_MASK_DATA[oy][ox] = fmasks->data.PS_TYPE_VECTOR_MASK_DATA[i];
     275# endif
    196276            }
     277
     278            if (nGoodPixel < 0.05*input->n) {
     279              fprintf (stderr, "warning: %d, %d : residual pixel with few input pixels: %d vs %d\n", ox, oy, nGoodPixel, (int) input->n);
     280            }
    197281
    198282            // skip pixels with insufficient data
     
    207291
    208292            // measure the robust median to determine a baseline reference value
    209             *fluxClip = *fluxClipDef;
     293            psStats *fluxClip = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV);
    210294            if (!psVectorStats (fluxClip, fluxes, NULL, fmasks, fmaskVal)) {
    211295                psError(PSPHOT_ERR_CONFIG, false, "Error calculating residual stats");
     296                psFree (fluxClip);
    212297                return false;
    213298            }
    214             if (isnan(fluxClip->robustMedian)) {
     299            if (isnan(fluxClip->sampleMedian)) {
    215300                resid->Ro->data.F32[oy][ox] = 0.0;
    216301                resid->Rx->data.F32[oy][ox] = 0.0;
    217302                resid->Ry->data.F32[oy][ox] = 0.0;
    218303                resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = badMask;
     304                psFree (fluxClip);
    219305                continue;
     306            }
     307
     308            if (fabs(fluxClip->sampleMedian) > 1.5) {
     309              fprintf (stderr, "warning: %d, %d : residual pixel has funny initial median value: %f\n", ox, oy, fluxClip->sampleMedian);
    220310            }
    221311
     
    223313            int nKeep = 0;
    224314            for (int i = 0; i < fluxes->n; i++) {
    225                 float delta = fluxes->data.F32[i] - fluxClip->robustMedian;
     315                float delta = fluxes->data.F32[i] - fluxClip->sampleMedian;
    226316                float sigma = sqrt (dfluxes->data.F32[i]);
    227317                float swing = fabs(delta) / sigma;
     
    233323                if (!fmasks->data.PS_TYPE_VECTOR_MASK_DATA[i]) nKeep++;
    234324            }
     325            psFree (fluxClip);
     326
     327            if (nKeep < 5) {
     328              fprintf (stderr, "warning: %d, %d : residual pixel with few good pixels: %d vs %d\n", ox, oy, nKeep, (int) input->n);
     329            }
    235330
    236331            if (SPATIAL_ORDER == 0) {
     
    242337                }
    243338
    244                 float radius = hypot((ox - 0.5*resid->Ro->numCols), (oy - 0.5*resid->Ro->numRows));
    245                 if (radius > radiusMax) {
    246                   resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = 1;
    247                   continue;
    248                 }
     339                resid->Rx->data.F32[oy][ox] = resid->Ry->data.F32[oy][ox] = 0.0;
    249340
    250341                resid->Ro->data.F32[oy][ox] = psStatsGetValue(fluxStats, statOption);
    251                 resid->Rx->data.F32[oy][ox] = resid->Ry->data.F32[oy][ox] = 0.0;
    252 
    253342                if (isnan(resid->Ro->data.F32[oy][ox])) {
    254343                    resid->Ro->data.F32[oy][ox] = 0.0;
    255                     resid->Rx->data.F32[oy][ox] = 0.0;
    256                     resid->Ry->data.F32[oy][ox] = 0.0;
    257344                    resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = badMask;
    258345                    continue;
     
    265352                assert (SPATIAL_ORDER == 1);
    266353
    267                 float radius = hypot((ox - 0.5*resid->Ro->numCols), (oy - 0.5*resid->Ro->numRows));
    268                 if (radius > radiusMax) {
    269                   resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = 1;
    270                   continue;
    271                 }
    272 
    273                 psImageInit(A, 0.0);
    274                 psVectorInit(B, 0.0);
    275                 for (int i = 0; i < fluxes->n; i++) {
    276                     if (fmasks->data.PS_TYPE_VECTOR_MASK_DATA[i]) continue;
    277                     B->data.F64[0] += fluxes->data.F32[i]/dfluxes->data.F32[i];
    278                     B->data.F64[1] += fluxes->data.F32[i]*xC->data.F32[i]/dfluxes->data.F32[i];
    279                     B->data.F64[2] += fluxes->data.F32[i]*yC->data.F32[i]/dfluxes->data.F32[i];
    280 
    281                     A->data.F64[0][0] += 1.0/dfluxes->data.F32[i];
    282                     A->data.F64[1][0] += xC->data.F32[i]/dfluxes->data.F32[i];
    283                     A->data.F64[2][0] += yC->data.F32[i]/dfluxes->data.F32[i];
    284 
    285                     A->data.F64[1][1] += PS_SQR(xC->data.F32[i])/dfluxes->data.F32[i];
    286                     A->data.F64[2][2] += PS_SQR(yC->data.F32[i])/dfluxes->data.F32[i];
    287                     A->data.F64[1][2] += xC->data.F32[i]*yC->data.F32[i]/dfluxes->data.F32[i];
    288                 }
    289 
    290                 A->data.F64[0][1] = A->data.F64[1][0];
    291                 A->data.F64[0][2] = A->data.F64[2][0];
    292                 A->data.F64[2][1] = A->data.F64[1][2];
    293 
    294                 if (!psMatrixGJSolve(A, B)) {
    295                     resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = 1;
    296                     psWarning("Singular matrix solving for (y,x) = (%d,%d)'s residuals, masking", oy, ox);
    297                     continue;
    298                 }
    299 
    300                 resid->Ro->data.F32[oy][ox] = B->data.F64[0];
    301                 resid->Rx->data.F32[oy][ox] = B->data.F64[1];
    302                 resid->Ry->data.F32[oy][ox] = B->data.F64[2];
    303 
    304                 float dRo = sqrt(A->data.F32[0][0]);
     354                // we have the following vectors to describe this pixel:
     355                // fluxes, dfluxes, fmasks, xC, yC
     356
     357                psVectorIRLSFitPolynomial2D (polyIRLS, statsIRLS, fmasks, fmaskVal, fluxes, dfluxes, xC, yC);
     358
     359                resid->Ro->data.F32[oy][ox] = polyIRLS->coeff[0][0];
     360                resid->Rx->data.F32[oy][ox] = polyIRLS->coeff[1][0];
     361                resid->Ry->data.F32[oy][ox] = polyIRLS->coeff[0][1];
     362
     363                // is the error well-defined?
     364                float dRo = polyIRLS->coeffErr[0][0];
     365
     366                if (fabs(resid->Ro->data.F32[oy][ox]) > 1.5) {
     367                  fprintf (stderr, "warning: %d, %d : residual pixel has funny fit value: %f\n", ox, oy, resid->Ro->data.F32[oy][ox]);
     368                }
    305369
    306370                if (fabs(resid->Ro->data.F32[oy][ox]) < pixelSN*dRo/sqrt(nKeep)) {
     371                  // fprintf (stderr, "mask : %d, %d : %f +/- %f (%f for %d) : %d\n", ox, oy, resid->Ro->data.F32[oy][ox], dRo, dRo/sqrt(nKeep), nKeep, resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox]);
    307372                  resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = 1;
    308373                  resid->Ro->data.F32[oy][ox] = 0.0;
    309374                  resid->Rx->data.F32[oy][ox] = 0.0;
    310375                  resid->Ry->data.F32[oy][ox] = 0.0;
    311                 }
     376                } else {
     377                  // fprintf (stderr, "keep : %d, %d : %f +/- %f (%f for %d) : %d\n", ox, oy, resid->Ro->data.F32[oy][ox], dRo, dRo/sqrt(nKeep), nKeep, resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox]);
     378                }
    312379            }
    313380        }
    314381    }
     382
     383# if (TESTRESID)
     384
     385    pmConfig *config = psphotGetConfig();
     386    char *output = psMetadataLookupStr (&status, config->arguments, "OUTPUT");
     387   
     388    // XXX // save the star coordinate vectors
     389    // XXX
     390    // XXX psString filename = NULL;
     391    // XXX psStringAppend (&filename, "%s.instar.dat", output);
     392
     393    char filename[1024];
     394    sprintf (filename, "%s.instar.dat", output);
     395   
     396    FILE *fout = fopen (filename, "w");
     397    for (int i = 0; i < xC->n; i++) {
     398      fprintf (fout, "%d %f %f\n", i, xC->data.F32[i], yC->data.F32[i]);
     399    }
     400    fclose (fout);
     401
     402    _psphotSaveCube (output, "raw.raw.fits", sourceRawCube);
     403    _psphotSaveCube (output, "sig.raw.fits", sourceSigCube);
     404    _psphotSaveCube (output, "var.raw.fits", sourceVarCube);
     405    _psphotSaveCube (output, "msk.raw.fits", sourceMskCube);
     406
     407    _psphotSaveCube (output, "sig.fits", inputSigCube);
     408    _psphotSaveCube (output, "var.fits", inputVarCube);
     409    _psphotSaveCube (output, "msk.fits", inputMskCube);
     410
     411    psFree (sourceRawCube);
     412    psFree (sourceSigCube);
     413    psFree (sourceVarCube);
     414    psFree (sourceMskCube);
     415
     416    psFree (inputSigCube);
     417    psFree (inputVarCube);
     418    psFree (inputMskCube);
     419
     420# endif
    315421
    316422    psFree (A);
     
    329435    psFree (fluxStats);
    330436    psFree (fluxStatsDef);
    331     psFree (fluxClip);
    332     psFree (fluxClipDef);
    333437
    334438    if (resid != NULL && psTraceGetLevel("psphot") > 5) {
     
    340444    }
    341445
     446    psFree (statsIRLS);
     447    psFree (polyIRLS);
     448
    342449    psf->residuals = resid;
    343450    return (resid != NULL) ? true : false;
    344451}
     452
     453bool _psphotSaveCube (char *basename, char *extname, psArray *cube) {
     454
     455    psString filename = NULL;
     456    psStringAppend (&filename, "%s.%s", basename, extname);
     457
     458    psFits *fits = psFitsOpen (filename, "w");
     459    if (!psFitsWriteImageCube (fits, NULL, cube, NULL)) {
     460      fprintf (stderr, "failed to write the cube %s\n", filename);
     461    }
     462    psFitsClose (fits);
     463
     464    psFree (filename);
     465
     466    return true;
     467}
  • trunk/psphot/src/psphotMaskReadout.c

    r34293 r42842  
    5858            return false;
    5959        }
     60    }
     61
     62    // XXX test to repair variance
     63    if (true) {
     64      psImage *im = readout->image;
     65      psImage *wt = readout->variance;
     66      float maxVar = 0;
     67      // find the max value
     68      for (int j = 0; j < im->numRows; j++) {
     69        for (int i = 0; i < im->numCols; i++) {
     70            if (!isfinite(wt->data.F32[j][i])) continue;
     71            maxVar = PS_MAX (wt->data.F32[j][i], maxVar);
     72        }
     73      }
     74      // set pixels with nan variance and non-nan image to maxVar
     75      for (int j = 0; j < im->numRows; j++) {
     76        for (int i = 0; i < im->numCols; i++) {
     77            if (!isfinite(im->data.F32[j][i])) continue;
     78            if (isfinite(wt->data.F32[j][i])) continue;
     79            wt->data.F32[j][i] = maxVar;
     80        }
     81      }
    6082    }
    6183
  • trunk/psphot/src/psphotOutput.c

    r37590 r42842  
    11# include "psphotInternal.h"
     2
     3pmConfig *staticConfig = NULL;
     4
     5void psphotSaveConfig (pmConfig *config) {
     6  staticConfig = config;
     7}
     8
     9pmConfig *psphotGetConfig () {
     10  return staticConfig;
     11}
    212
    313// convert filerule to filerule.NUM and look up in the config->arguments metadata
  • trunk/psphot/src/psphotRoughClass.c

    r36375 r42842  
    198198        }
    199199
    200         psfClump = pmSourcePSFClump (NULL, region, sources, PSF_SN_LIM, PSF_CLUMP_GRID_SCALE, MOMENTS_SX_MAX, MOMENTS_SY_MAX, MOMENTS_SX_MIN, MOMENTS_SY_MIN, MOMENTS_AR_MAX);
     200        // use clipped stats or robust stats to define the clump
     201        bool PSF_CLUMP_USE_CLIPPED_STATS = psMetadataLookupF32(&status, recipe, "PSF_CLUMP_USE_CLIPPED_STATS");
     202        if (!status) { PSF_CLUMP_USE_CLIPPED_STATS = true; }
     203
     204        psfClump = pmSourcePSFClump (NULL, region, sources, PSF_SN_LIM, PSF_CLUMP_GRID_SCALE, MOMENTS_SX_MAX, MOMENTS_SY_MAX, MOMENTS_SX_MIN, MOMENTS_SY_MIN, MOMENTS_AR_MAX, PSF_CLUMP_USE_CLIPPED_STATS);
    201205
    202206        psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.X",  PS_META_REPLACE, "psf clump center", psfClump.X);
  • trunk/psphot/src/psphotSourceStats.c

    r41359 r42842  
    120120        source->moments = pmMomentsAlloc();
    121121
     122        // XXX can this ever be set at this point? (we just allocated the source and moments)
    122123        if (source->mode & PM_SOURCE_MODE_MOMENTS_FAILURE) {
    123124            fprintf (stderr, "moment failure\n");
     
    144145
    145146    if (setWindow) {
     147        // identify sources on lines, drop from MomentsWindow analysis
     148        psphotFindFeatures (readout, sources);
     149
    146150        if (!psphotSetMomentsWindow(recipe, readout->analysis, sources, maskVal)) {
    147151            psError(PS_ERR_UNEXPECTED_NULL, false, "Failed to determine Moments Window!");
     
    503507    }
    504508
     509    // use clipped stats or robust stats to define the clump
     510    bool PSF_CLUMP_USE_CLIPPED_STATS = psMetadataLookupF32(&status, recipe, "PSF_CLUMP_USE_CLIPPED_STATS");
     511    if (!status) { PSF_CLUMP_USE_CLIPPED_STATS = true; }
     512
    505513    // when we set the window, we are not attempting to measure spatial variations; we can use a somewhat higher S/N limit
    506514    // since we are using all sources (true?)
     
    539547    sources = psArraySort (sources, pmSourceSortByFlux);
    540548
     549    // generate an array of the sources which we want to use for this analysis
     550    // XXX move max source number to config
     551    psArray *sourceSubset = psArrayAllocEmpty (100);
     552    for (int i = 0; (i < sources->n) && (i < 400); i++) {
     553
     554        pmSource *source = sources->data[i];
     555
     556        // skip faint sources for moments measurement
     557        if (sqrt(source->peak->detValue) < MIN_SN) continue;
     558
     559        // skip sources on lines
     560        if (source->mode2 & PM_SOURCE_MODE2_ON_LINE) continue;
     561        psArrayAdd (sourceSubset, 100, source);
     562    }
     563
    541564    // loop over radii:
    542565    for (int i = 0; i < nsigma; i++) {
    543 
    544         // XXX move max source number to config
    545         for (int j = 0; (j < sources->n) && (j < 400); j++) {
    546 
    547             pmSource *source = sources->data[j];
     566        for (int j = 0; j < sourceSubset->n; j++) {
     567            pmSource *source = sourceSubset->data[j];
    548568            psAssert (source->moments, "force moments to exist");
    549569            source->moments->nPixels = 0;
     
    565585          sprintf (name, "moments.v%d.dat", i);
    566586          FILE *fout = fopen (name, "w");
    567           for (int j = 0; j < sources->n; j++) {
    568             pmSource *source = sources->data[j];
     587          for (int j = 0; j < sourceSubset->n; j++) {
     588            pmSource *source = sourceSubset->data[j];
    569589            psAssert (source->moments, "force moments to exist");
    570590            source->moments->nPixels = 0;
     
    581601
    582602        // determine the PSF parameters from the source moment values
    583         pmPSFClump psfClump = pmSourcePSFClump (NULL, NULL, sources, PSF_SN_LIM, PSF_CLUMP_GRID_SCALE, MOMENTS_SX_MAX, MOMENTS_SY_MAX, MOMENTS_SX_MIN, MOMENTS_SY_MIN, MOMENTS_AR_MAX);
     603        pmPSFClump psfClump = pmSourcePSFClump (NULL, NULL, sourceSubset, PSF_SN_LIM, PSF_CLUMP_GRID_SCALE, MOMENTS_SX_MAX, MOMENTS_SY_MAX, MOMENTS_SX_MIN, MOMENTS_SY_MIN, MOMENTS_AR_MAX, PSF_CLUMP_USE_CLIPPED_STATS);
    584604        psLogMsg ("psphot", 3, "sigma guess (pix) %.1f, nStars: %d of %d in clump, nSigma: %5.2f, X,  Y: %f, %f (%f, %f)\n", sigma[i], psfClump.nStars, psfClump.nTotal, psfClump.nSigma, psfClump.X, psfClump.Y, sqrt(psfClump.X) / sigma[i], sqrt(psfClump.Y) / sigma[i]);
    585605
    586         Rmin[i] = pmSourceMinKronRadius(sources, PSF_SN_LIM);
     606        Rmin[i] = pmSourceMinKronRadius(sourceSubset, PSF_SN_LIM);
    587607
    588608#if 0
     
    600620        psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DY", PS_META_REPLACE, "psf clump center", psfClump.dY);
    601621        if (pmVisualTestLevel("psphot.moments.full", 2)) {
    602             psphotVisualPlotMoments (recipe, analysis, sources);
     622            psphotVisualPlotMoments (recipe, analysis, sourceSubset);
    603623        }
    604624#endif
     
    608628        Sout[i] = (Nout[i] == 0) ? NAN : sqrt(0.5*(psfClump.X + psfClump.Y)) / sigma[i];
    609629    }
     630
     631    psFree (sourceSubset);
    610632
    611633    // we are looking for sigma for which Sout = 0.65 (or some other value)
  • trunk/psphot/src/psphotVisual.c

    r36863 r42842  
    298298    bool status = false;
    299299    pmFPAfile *file = psMetadataLookupPtr (&status, config->files, "PSPHOT.BACKGND");
     300    if (!file) return false;
    300301
    301302    pmReadout *backgnd = READOUT_OR_INTERNAL(view, file);
     
    394395
    395396    psArray *peaks = detections->peaks;
     397    if (!peaks) return false;
    396398
    397399    // note: this uses the Ohana allocation tools:
Note: See TracChangeset for help on using the changeset viewer.