IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Sep 19, 2014, 4:05:27 PM (12 years ago)
Author:
eugene
Message:

merge changes from trunk

Location:
branches/eam_branches/ps2-tc3-20130727
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ps2-tc3-20130727

  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects

    • Property svn:ignore
      •  

        old new  
        1515pmSourceIO_CMF_PS1_SV1.c
        1616pmSourceIO_CMF_PS1_SV2.c
         17pmSourceIO_CMF_PS1_SV3.c
         18pmSourceIO_CMF_PS1_SV4.c
        1719pmSourceIO_CMF_PS1_DV1.c
        1820pmSourceIO_CMF_PS1_DV2.c
        1921pmSourceIO_CMF_PS1_DV3.c
         22pmSourceIO_CMF_PS1_DV4.c
        2023
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceIO_CFF.c

    r36680 r37403  
    3737#include "pmMoments.h"
    3838#include "pmModelFuncs.h"
     39#include "pmModelClass.h"
    3940#include "pmModel.h"
    4041#include "pmModelUtils.h"
    41 #include "pmModelClass.h"
    4242#include "pmSourceMasks.h"
    4343#include "pmSourceExtendedPars.h"
     
    5353#include "pmSourceOutputs.h"
    5454
    55 // read in a readout from the fits file
    56 psArray *pmSourcesRead_CFF (psFits *fits, psMetadata *header)
     55// read in sources readout from a cff fits file
     56psArray *pmSourcesRead_CFF (psFits *fits, psMetadata *header, psMetadata *recipe)
    5757{
    5858    PS_ASSERT_PTR_NON_NULL(fits, false);
     
    7575    PS_ASSERT_INT_NONNEGATIVE(modelType, NULL);
    7676
     77    pmModelType sersicModelType = pmModelClassGetType("PS_MODEL_SERSIC");
     78    pmModelType devModelType    = pmModelClassGetType("PS_MODEL_DEV");
     79
     80    psString modelForce = psMetadataLookupStr(&status, recipe, "EXT_MODEL_TYPE_FORCE");
     81    psF32 forceDevSersicMin = NAN;
     82    bool forceAll = false;
     83    int modelTypeForce = 0;
     84    if (!strcmp(modelForce, "ALL")) {
     85        forceAll = true;
     86    } else if (!strcmp(modelForce, "PS_MODEL_SERSIC")) {
     87        modelTypeForce = sersicModelType;
     88        forceDevSersicMin = psMetadataLookupF32(&status, recipe, "EXT_MODEL_FORCE_DEV_SERSIC_MIN");
     89    } else {
     90        modelTypeForce = pmModelClassGetType(modelForce);
     91        PS_ASSERT_INT_NONNEGATIVE(modelTypeForce, NULL);
     92    }
     93
     94    // skip extended model types for likely stars
     95    // max value of KronMag - psfMag to keep ...
     96    psF32 starCut = psMetadataLookupF32(&status, recipe, "EXT_MODEL_FORCE_MAGDIFF_MAX");
     97    if (!status) {
     98        starCut = 0;
     99    }
     100    // ... unless SN is less than this value
     101    psF32 SNMinForCut = psMetadataLookupF32(&status, recipe, "EXT_MODEL_FORCE_CUT_SN_MIN");
     102    if (!status) {
     103        SNMinForCut = 10;
     104    }
     105
    77106    // We get the size of the table, and allocate the array of sources first because the table
    78107    // is large and ephemeral --- when the table gets blown away, whatever is allocated after
    79108    // the table is read blocks the free.  In fact, it's better to read the table row by row.
    80     long numSources = psFitsTableSize(fits); // Number of sources in table
    81     psArray *sources = psArrayAlloc(numSources); // Array of sources, to return
    82 
    83     // convert the table to the pmSource entriesa
    84     for (int i = 0; i < numSources; i++) {
     109    long numRows = psFitsTableSize(fits); // Number of rows in table
     110    psArray *sources = psArrayAllocEmpty(numRows); // Array of sources, to return
     111
     112    // convert the table to the pmSource entries
     113    pmSource *source = NULL;
     114    for (int i = 0; i < numRows; i++) {
    85115        psMetadata *row = psFitsReadTableRow(fits, i); // Table row
    86116        if (!row) {
     
    108138        float kronRadius = psMetadataLookupF32 (&status, row, "KRON_RADIUS");
    109139        float petRadius  = psMetadataLookupF32 (&status, row, "PETRO_RADIUS");
     140        float SN         = psMetadataLookupF32 (&status, row, "SN");
    110141        bool fitGalaxy   = psMetadataLookupU8 (&status, row, "FIT_GALAXY");
    111142        bool psfStar     = psMetadataLookupU8 (&status, row, "PSF_STAR");
     
    114145        float Rminor     = psMetadataLookupF32 (&status, row, "R_MINOR");
    115146        float theta      = psMetadataLookupF32 (&status, row, "THETA");
     147        float chisq      = psMetadataLookupF32 (&status, row, "CHISQ");
     148        float nDOF       = psMetadataLookupF32 (&status, row, "NDOF");
     149        float magDiff    = psMetadataLookupF32 (&status, row, "MAG_DIFF");
     150        psS16 modelFlags = psMetadataLookupS32 (&status, row, "MODEL_FLAGS");
    116151
    117152        int   galaxyModelType = psMetadataLookupS32(&status, row, "MODEL_TYPE");
    118         if (status) {
     153        if (status && galaxyModelType >= 0) {
    119154            galaxyModelType = pmModelClassGetLocalType(galaxyModelType);
    120155        } else {
     
    123158        float Sindex     = psMetadataLookupF32 (&status, row, "INDEX"); // Should this be PAR_07 not sersic index
    124159
    125         pmSource *source = pmSourceAlloc ();
    126         pmModel *model = pmModelAlloc (modelType);
    127         source->modelPSF  = model;
    128 //        RoughClass wants source type to be unknown
    129 //        source->type = PM_SOURCE_TYPE_STAR; // XXX this should be added to the flags
    130         source->type = PM_SOURCE_TYPE_UNKNOWN;
    131 
    132         // XXX we can set this in general, but for a specific image, we need to weed out SATSTARS and
    133         // stars that are masked
    134         if (psfStar) {
    135             source->tmpFlags |= PM_SOURCE_TMPF_CANDIDATE_PSFSTAR;
    136         }
    137 
    138         // NOTE: A SEGV here because "model" is NULL is probably caused by not initialising the models.
    139         psF32 *PAR = model->params->data.F32;
    140         psF32 *dPAR = model->dparams->data.F32;
    141 
    142         source->seq       = ID;
    143         PAR[PM_PAR_XPOS]  = X;
    144         PAR[PM_PAR_YPOS]  = Y;
    145 
    146         dPAR[PM_PAR_XPOS] = 0.0;
    147         dPAR[PM_PAR_YPOS] = 0.0;
    148 
    149         PAR[PM_PAR_SKY]   = 0.0;
    150         dPAR[PM_PAR_SKY]  = 0.0;
    151 
    152         PAR[PM_PAR_I0]    = 1.0;
    153         dPAR[PM_PAR_I0]   = 0.0;
    154 
    155         source->sky       = PAR[PM_PAR_SKY];
    156         source->skyErr    = dPAR[PM_PAR_SKY];
    157 
    158         source->psfMag    = 0.0;
    159         source->psfMagErr = 0.0;
    160         source->apMag     = 0.0;
    161         source->apRadius  = apRadius;
    162 
    163         // we generate a somewhat fake PSF model here --
    164         // in most (all?) contexts, we will replace this with a measured psf model
    165         // elsewhere
    166         axes.major        = 1.0;
    167         axes.minor        = 1.0;
    168         axes.theta        = 0.0;
    169         pmPSF_AxesToModel (PAR, axes, modelType);
    170 
    171         // peak->detValue, rawFlux, smoothFlux are all set to the flux argument which is counts per second
    172         source->peak      = pmPeakAlloc(X, Y, flux, PM_PEAK_LONE);
    173         source->peak->xf  = X; // pmPeakAlloc converts X,Y to int, so reset here
    174         source->peak->yf  = Y; // pmPeakAlloc converts X,Y to int, so reset here
    175         source->peak->dx  = 0.0;
    176         source->peak->dy  = 0.0;
    177 
    178         source->moments = pmMomentsAlloc ();
    179         source->moments->Mx = X;
    180         source->moments->My = Y;
    181         source->moments->Mrf = kronRadius * 0.4; // kronRadius is 2.5 * first radial moment
    182 
    183         // Don't mark the moments as measured because that causes many fields to be left blank.
    184         // The moments code knows not to change the position or the Mrf for external sources
    185         // source->tmpFlags |= PM_SOURCE_TMPF_MOMENTS_MEASURED;
    186 
    187         if (isfinite(petRadius)) {
    188             source->extpars = pmSourceExtendedParsAlloc ();
    189             source->extpars->petrosianRadius = petRadius;
    190         }
    191 
     160        if (!source || ID != source->seq) {
     161            if (source) {
     162                psArrayAdd (sources, 1, source);
     163                psFree(source);
     164            }
     165            source = pmSourceAlloc ();
     166            pmModel *model = pmModelAlloc (modelType);
     167            source->modelPSF  = model;
     168            //        RoughClass wants source type to be unknown
     169            //        source->type = PM_SOURCE_TYPE_STAR; // XXX this should be added to the flags
     170            source->type = PM_SOURCE_TYPE_UNKNOWN;
     171
     172            // XXX we can set this in general, but for a specific image, we need to weed out SATSTARS and
     173            // stars that are masked
     174            if (psfStar) {
     175                source->tmpFlags |= PM_SOURCE_TMPF_CANDIDATE_PSFSTAR;
     176            }
     177
     178            // NOTE: A SEGV here because "model" is NULL is probably caused by not initialising the models.
     179            psF32 *PAR = model->params->data.F32;
     180            psF32 *dPAR = model->dparams->data.F32;
     181
     182            source->seq       = ID;
     183
     184            PAR[PM_PAR_XPOS]  = X;
     185            PAR[PM_PAR_YPOS]  = Y;
     186
     187            dPAR[PM_PAR_XPOS] = 0.0;
     188            dPAR[PM_PAR_YPOS] = 0.0;
     189
     190            PAR[PM_PAR_SKY]   = 0.0;
     191            dPAR[PM_PAR_SKY]  = 0.0;
     192
     193            PAR[PM_PAR_I0]    = 1.0;
     194            dPAR[PM_PAR_I0]   = 0.0;
     195
     196            source->sky       = PAR[PM_PAR_SKY];
     197            source->skyErr    = dPAR[PM_PAR_SKY];
     198
     199            source->psfMag    = 0.0;
     200            source->psfMagErr = 0.0;
     201            source->apMag     = 0.0;
     202            source->apRadius  = apRadius;
     203
     204            // we generate a somewhat fake PSF model here --
     205            // in most (all?) contexts, we will replace this with a measured psf model
     206            // elsewhere
     207            axes.major        = 1.0;
     208            axes.minor        = 1.0;
     209            axes.theta        = 0.0;
     210            pmPSF_AxesToModel (PAR, axes, model->class->useReff);
     211
     212            // peak->detValue, rawFlux, smoothFlux are all set to the flux argument which is counts per second
     213            source->peak      = pmPeakAlloc(X, Y, flux, PM_PEAK_LONE);
     214            source->peak->xf  = X; // pmPeakAlloc converts X,Y to int, so reset here
     215            source->peak->yf  = Y; // pmPeakAlloc converts X,Y to int, so reset here
     216            source->peak->dx  = 0.0;
     217            source->peak->dy  = 0.0;
     218
     219            source->extSN     = SN;
     220
     221            source->moments = pmMomentsAlloc ();
     222            source->moments->Mx = X;
     223            source->moments->My = Y;
     224            source->moments->Mrf = kronRadius * 0.4; // kronRadius is 2.5 * first radial moment
     225
     226            // Don't mark the moments as measured because that causes many fields to be left blank.
     227            // The moments code knows not to change the position or the Mrf for external sources
     228            // source->tmpFlags |= PM_SOURCE_TMPF_MOMENTS_MEASURED;
     229
     230            if (isfinite(petRadius)) {
     231                source->extpars = pmSourceExtendedParsAlloc ();
     232                source->extpars->petrosianRadius = petRadius;
     233            }
     234
     235        }
     236        bool saveExtModelParams = false;
    192237        if (fitGalaxy && galaxyModelType >= 0) {
    193             source->modelFits = psArrayAllocEmpty (1);
    194             pmModel *model = pmModelAlloc(galaxyModelType);
    195             psF32 *xPAR = model->params->data.F32;
    196 
    197             xPAR[PM_PAR_SKY]  = 0.0;
    198             xPAR[PM_PAR_I0]   = 1.0;
    199             xPAR[PM_PAR_XPOS] = X;
     238            // skip likely stars
     239            if (magDiff < starCut || SN < SNMinForCut) {
     240                if (forceAll) {
     241                    saveExtModelParams = true;
     242                } else if (galaxyModelType == modelTypeForce) {
     243                    // This is the model type that we are looking for
     244                    // proceed
     245                    saveExtModelParams = true;
     246                } else if (modelTypeForce == sersicModelType && galaxyModelType == devModelType) {
     247                    // We're doing sersic models, if sersic index is greater than the recipe's minimum index
     248                    // do dev model as well
     249                    if (isfinite(forceDevSersicMin) || Sindex >= forceDevSersicMin) {
     250                        saveExtModelParams = true;
     251                    }
     252                } else {
     253                    // not interested in this model
     254                }
     255            }
     256        }
     257
     258        if (saveExtModelParams) {
     259            if (!source->modelFits) {
     260                source->modelFits = psArrayAllocEmpty (1);
     261            }
     262            pmModel *model = pmModelAlloc(galaxyModelType);
     263            psF32 *xPAR = model->params->data.F32;
     264
     265            xPAR[PM_PAR_SKY]  = 0.0;
     266            xPAR[PM_PAR_I0]   = 1.0;
     267            xPAR[PM_PAR_XPOS] = X;
    200268            xPAR[PM_PAR_YPOS] = Y;
    201269           
     
    205273            galaxyAxes.theta = theta * PS_RAD_DEG;
    206274
    207             pmPSF_AxesToModel (xPAR, galaxyAxes, galaxyModelType);
     275            pmPSF_AxesToModel (xPAR, galaxyAxes, model->class->useReff);
    208276            if (model->params->n > 7) {
    209277                xPAR[PM_PAR_7] = 0.5 / Sindex;
    210278            }
    211279
     280            model->chisq = chisq;
     281            model->nDOF = nDOF;
     282            model->flags = modelFlags;
     283
    212284            psArrayAdd (source->modelFits, 1, model);
    213285
    214 #ifdef notyet
    215             // XXX: set source->modelEXT to this model and flag as extended so that we have a better
    216             // shot at subtracting extended sources?
    217 
    218             // This doesn't work right. Need to do some more work to flesh out the model before it can be
    219             // used in subtaction. Better idea might be to do 2 passes in psphotFullForceReadout to
    220             // First find the best extended models and then do everything else.
    221             source->modelEXT = psMemIncrRefCounter(model);
    222             // is this safe? (no see above)
    223             source->type = PM_SOURCE_TYPE_EXTENDED;
    224             source->mode |= PM_SOURCE_MODE_EXTMODEL;
    225 #endif
    226 
    227286            psFree (model);
    228287        }
    229288
    230         sources->data[i] = source;
    231289        psFree(row);
     290    }
     291    if (source) {
     292        // close out last source
     293        psArrayAdd (sources, 1, source);
     294        psFree(source);
    232295    }
    233296
     
    250313
    251314    pmModelType sersicModelType = pmModelClassGetType("PS_MODEL_SERSIC");
     315    pmModelType devModelType    = pmModelClassGetType("PS_MODEL_DEV");
     316    pmModelType selectedModelType = -1;
     317    bool chooseBest = false;
     318    bool chooseAll = false;
    252319
    253320    psString modelToChoose = psMetadataLookupStr(&mdok, recipe, "EXT_MODEL_TYPE_FOR_CFF");
    254     pmModelType selectedModelType = -1;
     321
    255322    if (mdok && modelToChoose != NULL) {
    256         if (strcmp(modelToChoose, "BEST")) {
     323        if (!strcmp(modelToChoose, "BEST")) {
     324            chooseBest = true;
     325        } else if (!strcmp(modelToChoose, "ALL")) {
     326            chooseAll = true;
     327        } else if (strcmp(modelToChoose, "PS_MODEL_SERSIC")) {
     328            // We have selected a model type other than Sersic.
     329            // Save it's type for use below.  Sersic is handled specially
    257330            selectedModelType = pmModelClassGetType(modelToChoose);
    258331        }
    259332    }
     333
     334    // minimum sersic index to force devModel
     335    psF32 sersicMinDev = psMetadataLookupF32(&mdok, recipe, "EXT_MODEL_FORCE_DEV_SERSIC_MIN");
     336    if (!mdok) {
     337        sersicMinDev = NAN;
     338    }
     339
     340    sources = psArraySort (sources, pmSourceSortBySeq);
    260341
    261342    for (int i = 0; i < sources->n; i++) {
     
    263344        pmSource *source = thisSource->parent ? thisSource->parent : thisSource;
    264345
    265         psF32 xPos, yPos, flux, rMajor, rMinor, theta;
    266         psS32 modelType = 0;
     346        #define MAX_ROWS_PER_SRC 10
     347        psF32 xPos[MAX_ROWS_PER_SRC], yPos[MAX_ROWS_PER_SRC], flux[MAX_ROWS_PER_SRC];
     348        psF32 rMajor[MAX_ROWS_PER_SRC], rMinor[MAX_ROWS_PER_SRC], theta[MAX_ROWS_PER_SRC];
     349        psF32 chisq[MAX_ROWS_PER_SRC], nDOF[MAX_ROWS_PER_SRC];
     350        psS32 modelFlags[MAX_ROWS_PER_SRC];
     351        psS32 modelType[MAX_ROWS_PER_SRC];
     352        psF32 sersicIndex = NAN;
    267353        bool fitGalaxy = false;
    268354        bool psfStar = (source->mode & PM_SOURCE_MODE_PSFSTAR) ? true : false;
    269         psF32 sersicIndex = 0;
    270         // For now only perform galaxy fits on extended objects
    271         if (source->modelEXT == NULL) {
    272             pmModel *model = source->modelPSF;
    273             if (model == NULL) continue;
    274             psF32 *PAR = model->params->data.F32;
    275             if (!isfinite(PAR[PM_PAR_SXX]) || !isfinite(PAR[PM_PAR_SYY])  || !isfinite(PAR[PM_PAR_SXY]) ||
    276                 !isfinite(source->psfFlux)) {
    277                 continue;
    278             }
    279 
    280             xPos = model->params->data.F32[PM_PAR_XPOS];
    281             yPos = model->params->data.F32[PM_PAR_YPOS];
    282             flux = source->psfFlux;
    283             rMajor = 0;
    284             rMinor = 0;
    285             theta = 0;
    286         } else {
    287             //   Find the model with the selected type. If selected type is -1 choose the one selected ad
    288             //   modelEXT which was the best
    289             int iModel = -1;
    290             if (source->modelEXT) {
    291                 pmModelType ext_model_type =  selectedModelType != -1  ? selectedModelType : source->modelEXT->type;
     355        int n_rows = 0;
     356
     357        psF32 kronFlux = source->moments->KronFlux;
     358        psF32 SN = NAN;
     359        psF32 magDiff = NAN;
     360        if (isfinite(kronFlux) && isfinite(source->moments->KronFluxErr) && isfinite(source->psfMag)) {
     361            SN = kronFlux/source->moments->KronFluxErr;
     362            // kronMag - psfMag for use as star/glaxy separator
     363            magDiff = -2.5 * log10(kronFlux) - source->psfMag ;
     364        }
     365
     366        // start with psf model
     367        pmModel *model = source->modelPSF;
     368        if (model == NULL) continue;
     369        psF32 *PAR = model->params->data.F32;
     370        if (!isfinite(PAR[PM_PAR_SXX]) || !isfinite(PAR[PM_PAR_SYY])  || !isfinite(PAR[PM_PAR_SXY]) ||
     371            !isfinite(source->psfFlux)) {
     372            continue;
     373        }
     374
     375        // save the PSF model parameters for each object as the first entry
     376        xPos[0] = model->params->data.F32[PM_PAR_XPOS];
     377        yPos[0] = model->params->data.F32[PM_PAR_YPOS];
     378        flux[0] = source->psfFlux;
     379        rMajor[0] = 0;
     380        rMinor[0] = 0;
     381        theta[0] = 0;
     382        modelType[0] = -1;
     383        sersicIndex = NAN;
     384        chisq[0] = NAN;
     385        nDOF[0] = NAN;
     386        modelFlags[0] = 0;
     387        n_rows ++;
     388
     389        if (source->modelFits != NULL) {
     390            // figure out which models to use based on recipe paramters
     391            if (chooseAll) {
     392                // Save parameters for all valid extended models
     393
     394                // but make sure we aren't going to overflow our arrays
     395                assert (source->modelFits->n < MAX_ROWS_PER_SRC);
     396
    292397                for (int j=0; j<source->modelFits->n; j++) {
    293                     pmModel *aModel = source->modelFits->data[j];
    294                     if (aModel->type == ext_model_type) {
    295                         iModel = j;
    296                         break;
     398                    pmModel *model = source->modelFits->data[j];
     399                    psF32 *PAR = model->params->data.F32;
     400
     401                    if (isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SYY])  && isfinite(PAR[PM_PAR_SXY]) &&
     402                        isfinite(model->mag)) {
     403
     404                        xPos[n_rows] = PAR[PM_PAR_XPOS];
     405                        yPos[n_rows] = PAR[PM_PAR_YPOS];
     406
     407                        psEllipseAxes axes = pmPSF_ModelToAxes (PAR, model->class->useReff);
     408                        rMajor[n_rows] = axes.major;
     409                        rMinor[n_rows] = axes.minor;
     410                        theta[n_rows]  = axes.theta*PS_DEG_RAD;
     411                        flux[n_rows] = pow(10.0, -0.4*model->mag);
     412                        modelType[n_rows] = model->type;
     413                        chisq[n_rows] = model->chisq;
     414                        nDOF[n_rows] = model->nDOF;
     415                        modelFlags[n_rows] = model->flags;
     416                        fitGalaxy = true;
     417                        if (model->params->n == 8) {
     418                            // this will save the sersic index in all models but that might
     419                            // be useful
     420                            sersicIndex = 0.5 / PAR[PM_PAR_7];
     421                        } else {
     422                            sersicIndex = NAN;
     423                        }
     424
     425                        n_rows++;
     426                    }
     427                }
     428            } else {
     429                int jModelSersic = -1;
     430                int jModelDev = -1;
     431                int jModelSelected = -1;
     432                psF32 minChisq = NAN;
     433                for (int j=0; j<source->modelFits->n; j++) {
     434                    pmModel *model = source->modelFits->data[j];
     435                    if (chooseBest) {
     436                        // choose the model with lowest chisq
     437                        if (isfinite(model->chisq) && (!isfinite(minChisq) || model->chisq < minChisq)) {
     438                            jModelSelected = j;
     439                            minChisq = model->chisq;
     440                        }
     441                    } else {
     442                        // find the index of models of interest
     443                        if (model->type == selectedModelType) {
     444                            jModelSelected = j;
     445                        } else if (model->type == sersicModelType) {
     446                            jModelSersic = j;
     447                        } else if (model->type == devModelType) {
     448                            jModelDev = j;
     449                        }
     450                    }
     451                }
     452                if (jModelSelected >= 0 || jModelSersic >= 0) {
     453                    // If a specific non-sersic model we take paramers from that one.
     454                    // Otherwise we do the sersic model.
     455                    pmModel *model = jModelSelected >= 0 ? source->modelFits->data[jModelSelected] :
     456                                                           source->modelFits->data[jModelSersic];
     457                    psF32 *PAR = model->params->data.F32;
     458
     459                    if (isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SYY])  && isfinite(PAR[PM_PAR_SXY]) &&
     460                        isfinite(model->mag)) {
     461
     462                        xPos[0] = PAR[PM_PAR_XPOS];
     463                        yPos[0] = PAR[PM_PAR_YPOS];
     464
     465                        psEllipseAxes axes = pmPSF_ModelToAxes (PAR, model->class->useReff);
     466                        rMajor[0] = axes.major;
     467                        rMinor[0] = axes.minor;
     468                        theta[0]  = axes.theta*PS_DEG_RAD;
     469                        flux[0] = pow(10.0, -0.4*model->mag);
     470                        modelType[0] = model->type;
     471                        chisq[0] = model->chisq;
     472                        nDOF[0] = model->nDOF;
     473                        modelFlags[0] = model->flags;
     474                        fitGalaxy = true;
     475                        if (model->type == sersicModelType) {
     476                            PS_ASSERT_FLOAT_LARGER_THAN(PAR[PM_PAR_7], 0.0, false);
     477                            sersicIndex = 0.5 / PAR[PM_PAR_7];
     478                        }
     479
     480                        n_rows = 1;
     481
     482                        // Unless a specific non-sersic model type was selected do dev model for sources with
     483                        // sersic index above the recipe limit.
     484                        if (jModelSelected == -1 && jModelDev >= 0 && isfinite(sersicMinDev) &&
     485                            sersicIndex > sersicMinDev) {
     486
     487                            model = source->modelFits->data[jModelDev];
     488                            if (isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SYY])  && isfinite(PAR[PM_PAR_SXY]) &&
     489                                isfinite(model->mag)) {
     490
     491                                xPos[1] = PAR[PM_PAR_XPOS];
     492                                yPos[1] = PAR[PM_PAR_YPOS];
     493
     494                                psEllipseAxes axes = pmPSF_ModelToAxes (PAR, model->class->useReff);
     495                                rMajor[1] = axes.major;
     496                                rMinor[1] = axes.minor;
     497                                theta[1]  = axes.theta*PS_DEG_RAD;
     498                                flux[1] = pow(10.0, -0.4*model->mag);
     499                                modelType[1] = model->type;
     500                                sersicIndex = NAN;
     501                                chisq[1] = model->chisq;
     502                                nDOF[1] = model->nDOF;
     503                                modelFlags[1] = model->flags;
     504                                n_rows = 2;
     505                            }
     506                        }
    297507                    }
    298508                }
    299509            }
    300             if (iModel == -1) {
    301                 // Can this happen? perhaps if model type is qgauss (extended but below s/n for model fits?
    302                 // XXX: Should this be an assert?
    303                 continue;
    304             }
    305             pmModel *model = source->modelFits->data[iModel];
    306             psF32 *PAR = model->params->data.F32;
    307             xPos = PAR[PM_PAR_XPOS];
    308             yPos = PAR[PM_PAR_YPOS];
    309             if (model->type == pmModelClassGetType("PS_MODEL_TRAIL")) {
    310                 // XXX: do we need to handle this type
    311                 continue;
    312             } else {
    313                 if (!isfinite(PAR[PM_PAR_SXX]) || !isfinite(PAR[PM_PAR_SYY])  || !isfinite(PAR[PM_PAR_SXY]) ||
    314                     !isfinite(model->mag)) {
    315                     // bad model
    316                     continue;
    317                 }
    318                 psEllipseAxes axes = pmPSF_ModelToAxes (PAR, model->type);
    319                 rMajor = axes.major;
    320                 rMinor = axes.minor;
    321                 theta  = axes.theta*PS_DEG_RAD;
    322                 flux = pow(10.0, -0.4*model->mag);
    323                 fitGalaxy = true;
    324             }
    325             modelType = model->type;
    326             if (modelType == sersicModelType) {
    327                 PS_ASSERT_FLOAT_LARGER_THAN(PAR[PM_PAR_7], 0.0, false);
    328                 sersicIndex = 0.5 / PAR[PM_PAR_7];
    329             }
    330         }
    331         psMetadata *row = psMetadataAlloc();
    332         psMetadataAddU32 (row, PS_LIST_TAIL, "ID",         0,   "IPP detection identifier",  source->seq);
    333         psMetadataAddF32 (row, PS_LIST_TAIL, "X",                0, "x coordinate",          xPos);
    334         psMetadataAddF32 (row, PS_LIST_TAIL, "Y",                0, "y coordinate",          yPos);
    335         psMetadataAddF32 (row, PS_LIST_TAIL, "FLUX",             0, "flux per second",       flux/exptime);
    336         psMetadataAddF32 (row, PS_LIST_TAIL, "AP_RADIUS",        0, "aperture radius",       source->apRadius);
    337         psMetadataAddF32 (row, PS_LIST_TAIL, "KRON_RADIUS",      0, "Kron radius",           source->moments->Mrf * 2.5);
    338         psMetadataAddF32 (row, PS_LIST_TAIL, "PETRO_RADIUS",     0, "Petrosian Radius",      source->extpars ? source->extpars->petrosianRadius : NAN);
    339         psMetadataAddBool (row, PS_LIST_TAIL, "FIT_GALAXY",      0, "source has xfit",       fitGalaxy);
    340         psMetadataAddBool (row, PS_LIST_TAIL, "PSF_STAR",        0, "source was psf star",   psfStar);
    341         psMetadataAddF32 (row, PS_LIST_TAIL, "R_MAJOR",          0, "radius of major axis",  rMajor);
    342         psMetadataAddF32 (row, PS_LIST_TAIL, "R_MINOR",          0, "radius of minor axis",  rMinor);
    343         psMetadataAddF32 (row, PS_LIST_TAIL, "THETA",            0, "theta",                 theta);
    344         psMetadataAddS32 (row, PS_LIST_TAIL, "MODEL_TYPE",       0, "model type",            modelType);
    345         psMetadataAddF32 (row, PS_LIST_TAIL, "INDEX",            0, "sersic index",          sersicIndex);
    346 
    347         psArrayAdd(table, 100, row);
    348         psFree(row);
     510        }
     511
     512        for (int j = 0; j < n_rows; j++) {
     513            psMetadata *row = psMetadataAlloc();
     514            psMetadataAddU32 (row, PS_LIST_TAIL, "ID",         0,   "IPP detection identifier",  source->seq);
     515            psMetadataAddF32 (row, PS_LIST_TAIL, "X",                0, "x coordinate",          xPos[j]);
     516            psMetadataAddF32 (row, PS_LIST_TAIL, "Y",                0, "y coordinate",          yPos[j]);
     517            psMetadataAddF32 (row, PS_LIST_TAIL, "FLUX",             0, "flux per second",       flux[j]/exptime);
     518            psMetadataAddF32 (row, PS_LIST_TAIL, "SN",               0, "kron flux signal to noise", SN);
     519            psMetadataAddF32 (row, PS_LIST_TAIL, "MAG_DIFF",         0, "psf mag - kron mag",    magDiff);
     520            psMetadataAddF32 (row, PS_LIST_TAIL, "AP_RADIUS",        0, "aperture radius",       source->apRadius);
     521            psMetadataAddF32 (row, PS_LIST_TAIL, "KRON_RADIUS",      0, "Kron radius",           source->moments->Mrf * 2.5);
     522            psMetadataAddF32 (row, PS_LIST_TAIL, "PETRO_RADIUS",     0, "Petrosian Radius",      source->extpars ? source->extpars->petrosianRadius : NAN);
     523            psMetadataAddBool (row, PS_LIST_TAIL, "FIT_GALAXY",      0, "source has xfit",       fitGalaxy);
     524            psMetadataAddBool (row, PS_LIST_TAIL, "PSF_STAR",        0, "source was psf star",   psfStar);
     525            psMetadataAddF32 (row, PS_LIST_TAIL, "R_MAJOR",          0, "radius of major axis",  rMajor[j]);
     526            psMetadataAddF32 (row, PS_LIST_TAIL, "R_MINOR",          0, "radius of minor axis",  rMinor[j]);
     527            psMetadataAddF32 (row, PS_LIST_TAIL, "THETA",            0, "theta",                 theta[j]);
     528            psMetadataAddS32 (row, PS_LIST_TAIL, "MODEL_TYPE",       0, "model type",            modelType[j]);
     529            psMetadataAddF32 (row, PS_LIST_TAIL, "INDEX",            0, "sersic index",          sersicIndex);
     530            psMetadataAddF32 (row, PS_LIST_TAIL, "CHISQ",            0, "chisq",                 chisq[j]);
     531            psMetadataAddF32 (row, PS_LIST_TAIL, "NDOF",             0, "n degrees of freedom",  nDOF[j]);
     532            psMetadataAddS32 (row, PS_LIST_TAIL, "MODEL_FLAGS",      0, "model flags",           modelFlags[j]);
     533
     534            psArrayAdd(table, 100, row);
     535            psFree(row);
     536        }
    349537    }
    350538
Note: See TracChangeset for help on using the changeset viewer.