IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 21166


Ignore:
Timestamp:
Jan 24, 2009, 10:54:29 AM (17 years ago)
Author:
eugene
Message:

clean up threading model for psphotGuessModel (defined standard way to split sources into regions); extending the threading to psphotMagnitudes, psphotApReset, psphotBlendFit, psphotSourceStats

Location:
trunk/psphot/src
Files:
1 added
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/psphot/src/Makefile.am

    r20411 r21166  
    7979        psphotMakeFluxScale.c          \
    8080        psphotCheckStarDistribution.c  \
     81        psphotThreadTools.c            \
    8182        psphotAddNoise.c
    8283
  • trunk/psphot/src/psphot.h

    r21108 r21166  
    1212
    1313#define PSPHOT_RECIPE_PSF_FAKE_ALLOW "PSF.FAKE.ALLOW" // Name for recipe component permitting fake PSFs
    14 
    15 typedef struct {
    16     pmReadout *readout;
    17     psArray *sources;
    18     pmPSF *psf;
    19     psRegion *region;
    20     psMaskType maskVal;
    21     psMaskType markVal;
    22 } psphotGuessModelForRegionArgs;
    2314
    2415// top-level psphot functions
     
    4334pmDetections   *psphotFindDetections (pmDetections *detections, pmReadout *readout, psMetadata *recipe);
    4435
    45 psArray        *psphotSourceStats (pmReadout *readout, psMetadata *recipe, pmDetections *detections);
    4636bool            psphotRoughClass (pmReadout *readout, psArray *sources, psMetadata *recipe, const bool findPsfClump);
    4737bool            psphotBasicDeblend (psArray *sources, psMetadata *recipe);
     
    5040bool            psphotMomentsStats (pmReadout *readout, psMetadata *recipe, psArray *sources);
    5141bool            psphotFitSourcesLinear (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf, bool final);
    52 bool            psphotGuessModels (pmConfig *config, pmReadout *readout, psArray *sources, pmPSF *psf);
    53 bool            psphotGuessModelForRegion (psphotGuessModelForRegionArgs *args);
    54 bool            psphotBlendFit (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf);
    5542bool            psphotReplaceUnfitSources (psArray *sources, psMaskType maskVal);
    5643bool            psphotReplaceAllSources (psArray *sources, psMetadata *recipe);
    5744bool            psphotRemoveAllSources (psArray *sources, psMetadata *recipe);
    58 bool            psphotApResid (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf);
    59 bool            psphotMagnitudes (pmConfig *config, const pmFPAview *view, psArray *sources, psMetadata *recipe, pmPSF *psf);
     45
     46bool            psphotBlendFit (pmConfig *config, pmReadout *readout, psArray *sources, pmPSF *psf);
     47bool            psphotBlendFit_Threaded (psThreadJob *job);
     48
     49psArray        *psphotSourceStats (pmConfig *config, pmReadout *readout, pmDetections *detections);
     50bool            psphotSourceStats_Threaded (psThreadJob *job);
     51
     52bool            psphotGuessModels (pmConfig *config, pmReadout *readout, psArray *sources, pmPSF *psf);
     53bool            psphotGuessModel_Threaded (psThreadJob *job);
     54
     55bool            psphotMagnitudes (pmConfig *config, pmReadout *readout, const pmFPAview *view, psArray *sources, pmPSF *psf);
     56bool            psphotMagnitudes_Threaded (psThreadJob *job);
     57
     58bool            psphotApResid (pmConfig *config, pmReadout *readout, psArray *sources, pmPSF *psf);
     59bool            psphotApResidMags_Threaded (psThreadJob *job);
     60
    6061bool            psphotSkyReplace (pmConfig *config, const pmFPAview *view);
    6162bool            psphotExtendedSourceAnalysis (pmReadout *readout, psArray *sources, psMetadata *recipe);
    6263bool            psphotExtendedSourceFits (pmReadout *readout, psArray *sources, psMetadata *recipe);
     64
     65// thread-related:
    6366bool            psphotSetThreads ();
     67bool            psphotChooseCellSizes (int *Cx, int *Cy, pmReadout *readout, int nThreads);
     68bool            psphotCoordToCell (int *group, int *cell, float x, float y, int Cx, int Cy);
     69psArray        *psphotAssignSources (int Cx, int Cy, psArray *sources);
    6470
    6571// used by psphotFindDetections
  • trunk/psphot/src/psphotApResid.c

    r21080 r21166  
    44// measure the aperture residual statistics and 2D variations
    55
    6 bool psphotApResid (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf)
     6bool psphotApResid (pmConfig *config, pmReadout *readout, psArray *sources, pmPSF *psf)
    77{
    88    int Nfail = 0;
     
    1313    pmSource *source;
    1414
    15     PS_ASSERT_PTR_NON_NULL(psf, false);
     15    PS_ASSERT_PTR_NON_NULL(config, false);
    1616    PS_ASSERT_PTR_NON_NULL(readout, false);
    1717    PS_ASSERT_PTR_NON_NULL(sources, false);
    18     PS_ASSERT_PTR_NON_NULL(recipe, false);
     18    PS_ASSERT_PTR_NON_NULL(psf, false);
    1919
    2020    psTimerStart ("psphot.apresid");
     21
     22    // select the appropriate recipe information
     23    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     24    assert (recipe);
     25
     26    // determine the number of allowed threads
     27    int nThreads = psMetadataLookupS32(&status, config->arguments, "NTHREADS"); // Number of threads
     28    if (!status) {
     29        nThreads = 0;
     30    }
     31    // nThreads = 0; // XXX until testing is complete, do not thread this function
    2132
    2233    bool measureAptrend = psMetadataLookupBool (&status, recipe, "MEASURE.APTREND");
     
    7081    pmSourceMagnitudesInit (recipe);
    7182
     83    // threaded measurement of the source magnitudes
     84    // choose Cx, Cy (see psphotThreadTools.c for overview of the concepts)
     85    int Cx = 1, Cy = 1;
     86    psphotChooseCellSizes (&Cx, &Cy, readout, nThreads);
     87
     88    psArray *cellGroups = psphotAssignSources (Cx, Cy, sources);
     89
     90    for (int i = 0; i < cellGroups->n; i++) {
     91
     92        psArray *cells = cellGroups->data[i];
     93
     94        for (int j = 0; j < cells->n; j++) {
     95
     96            // allocate a job -- if threads are not defined, this just runs the job
     97            psThreadJob *job = psThreadJobAlloc ("PSPHOT_APRESID_MAGS");
     98
     99            psArrayAdd(job->args, 1, cells->data[j]); // sources
     100            psArrayAdd(job->args, 1, psf);
     101            PS_ARRAY_ADD_SCALAR(job->args, photMode, PS_TYPE_S32);
     102            PS_ARRAY_ADD_SCALAR(job->args, maskVal,  PS_TYPE_U8); // XXX change this to use abstract mask type info
     103
     104            PS_ARRAY_ADD_SCALAR(job->args, 0,        PS_TYPE_S32); // this is used as a return value for Nskip
     105            PS_ARRAY_ADD_SCALAR(job->args, 0,        PS_TYPE_S32); // this is used as a return value for Nfail
     106
     107            if (!psThreadJobAddPending(job)) {
     108                psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     109                psFree (job);
     110                return false;
     111            }
     112            psFree(job);
     113
     114        }
     115
     116        // wait for the threads to finish and manage results
     117        if (!psThreadPoolWait (false)) {
     118            psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     119            return false;
     120        }
     121
     122        // we have only supplied one type of job, so we can assume the types here
     123        psThreadJob *job = NULL;
     124        while ((job = psThreadJobGetDone()) != NULL) {
     125            if (job->args->n < 1) {
     126                fprintf (stderr, "error with job\n");
     127            } else {
     128                psScalar *scalar = NULL;
     129                scalar = job->args->data[4];
     130                Nskip += scalar->data.S32;
     131                scalar = job->args->data[5];
     132                Nfail += scalar->data.S32;
     133            }
     134            psFree(job);
     135        }
     136    }
     137
     138    psFree (cellGroups);
     139
     140    // gather the stats to assess the aperture residuals
    72141    psVector *mask    = psVectorAllocEmpty (300, PS_TYPE_U8);
    73142    psVector *mag     = psVectorAllocEmpty (300, PS_TYPE_F32);
     
    78147    Npsf = 0;
    79148
    80     // select all good PM_SOURCE_TYPE_STAR entries
    81149    for (int i = 0; i < sources->n; i++) {
    82150        source = sources->data[i];
     
    89157        if (source->mode &  PM_SOURCE_MODE_POOR) SKIPSTAR ("POOR STAR");
    90158
    91         // get growth-corrected, apTrend-uncorrected magnitudes in scaled apertures
    92         // will fail if below S/N threshold or model is missing
    93         if (!pmSourceMagnitudes (source, psf, photMode, maskVal)) {
    94             Nskip ++;
    95             psTrace ("psphot", 3, "skip : bad source mag");
    96             continue;
    97         }
    98 
    99159        if (!isfinite(source->apMag) || !isfinite(source->psfMag)) {
    100             Nfail ++;
    101             psTrace ("psphot", 3, "fail : nan mags : %f %f", source->apMag, source->psfMag);
    102160            continue;
    103161        }
     
    206264
    207265    psLogMsg ("psphot.apresid", PS_LOG_DETAIL, "aperture residual: %f +/- %f\n", psf->ApResid, psf->dApResid);
    208     psLogMsg ("psphot.apresid", PS_LOG_INFO, "measure full-frame aperture residuals for: %f sec\n", psTimerMark ("psphot.apresid"));
     266    psLogMsg ("psphot.apresid", PS_LOG_INFO, "measure full-frame aperture residuals for %d sources: %f sec\n", Npsf, psTimerMark ("psphot.apresid"));
    209267
    210268    psFree (mag);
     
    392450}
    393451
     452bool psphotApResidMags_Threaded (psThreadJob *job) {
     453
     454    int Nskip = 0;
     455    int Nfail = 0;
     456
     457    psScalar *scalar = NULL;
     458
     459    psArray *sources                = job->args->data[0];
     460    pmPSF *psf                      = job->args->data[1];
     461    pmSourcePhotometryMode photMode = PS_SCALAR_VALUE(job->args->data[2],S32);
     462    psMaskType maskVal              = PS_SCALAR_VALUE(job->args->data[3],U8);
     463
     464    for (int i = 0; i < sources->n; i++) {
     465        pmSource *source = (pmSource *) sources->data[i];
     466
     467        if (source->type != PM_SOURCE_TYPE_STAR) SKIPSTAR ("NOT STAR");
     468        if (source->mode &  PM_SOURCE_MODE_SATSTAR) SKIPSTAR ("SATSTAR");
     469        if (source->mode &  PM_SOURCE_MODE_BLEND) SKIPSTAR ("BLEND");
     470        if (source->mode &  PM_SOURCE_MODE_FAIL) SKIPSTAR ("FAIL STAR");
     471        if (source->mode &  PM_SOURCE_MODE_POOR) SKIPSTAR ("POOR STAR");
     472
     473        if (!pmSourceMagnitudes (source, psf, photMode, maskVal)) {
     474            Nskip ++;
     475            psTrace ("psphot", 3, "skip : bad source mag");
     476            continue;
     477        }
     478
     479        if (!isfinite(source->apMag) || !isfinite(source->psfMag)) {
     480            Nfail ++;
     481            psTrace ("psphot", 3, "fail : nan mags : %f %f", source->apMag, source->psfMag);
     482            continue;
     483        }
     484    }
     485
     486    // change the value of a scalar on the array (wrap this and put it in psArray.h)
     487    scalar = job->args->data[4];
     488    scalar->data.S32 = Nskip;
     489
     490    scalar = job->args->data[5];
     491    scalar->data.S32 = Nfail;
     492
     493    return true;
     494}
  • trunk/psphot/src/psphotArguments.c

    r20642 r21166  
    3838
    3939        // create the thread pool with number of desired threads, supplying our thread launcher function
    40         // XXX need to determine the number of threads from the config data
    4140        psThreadPoolInit (nThreads);
    4241    }
  • trunk/psphot/src/psphotBlendFit.c

    r20453 r21166  
    22
    33// XXX I don't like this name
    4 bool psphotBlendFit (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf) {
     4bool psphotBlendFit (pmConfig *config, pmReadout *readout, psArray *sources, pmPSF *psf) {
    55
    66    int Nfit = 0;
     
    1212    psTimerStart ("psphot.fit.nonlinear");
    1313
     14    // select the appropriate recipe information
     15    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     16    assert (recipe);
     17
     18    // determine the number of allowed threads
     19    int nThreads = psMetadataLookupS32(&status, config->arguments, "NTHREADS"); // Number of threads
     20    if (!status) {
     21        nThreads = 0;
     22    }
     23    // nThreads = 0; // XXX until testing is complete, do not thread this function
     24
     25    psphotInitLimitsPSF (recipe, readout);
     26    psphotInitLimitsEXT (recipe);
     27    psphotInitRadiusPSF (recipe, psf->type);
     28
     29    // starts the timer, sets up the array of fitSets
     30    psphotFitInit (nThreads);
     31
     32    // source analysis is done in S/N order (brightest first)
     33    sources = psArraySort (sources, pmSourceSortBySN);
     34
     35    // choose Cx, Cy (see psphotThreadTools.c for overview of the concepts)
     36    int Cx = 1, Cy = 1;
     37    psphotChooseCellSizes (&Cx, &Cy, readout, nThreads);
     38
     39    psArray *cellGroups = psphotAssignSources (Cx, Cy, sources);
     40
     41    fprintf (stderr, "starting with %ld sources\n", sources->n);
     42
     43    for (int i = 0; i < cellGroups->n; i++) {
     44
     45        psArray *cells = cellGroups->data[i];
     46
     47        for (int j = 0; j < cells->n; j++) {
     48
     49            // allocate a job -- if threads are not defined, this just runs the job
     50            psThreadJob *job = psThreadJobAlloc ("PSPHOT_BLEND_FIT");
     51            psArray *newSources = psArrayAllocEmpty(16);
     52
     53            psArrayAdd(job->args, 1, readout);
     54            psArrayAdd(job->args, 1, recipe);
     55            psArrayAdd(job->args, 1, cells->data[j]); // sources
     56            psArrayAdd(job->args, 1, psf);
     57            psArrayAdd(job->args, 1, newSources); // return for new sources
     58            psFree (newSources);
     59
     60            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nfit
     61            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Npsf
     62            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Next
     63            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nfail
     64
     65            if (!psThreadJobAddPending(job)) {
     66                psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     67                psFree (job);
     68                return NULL;
     69            }
     70            psFree(job);
     71
     72        }
     73
     74        // wait for the threads to finish and manage results
     75        if (!psThreadPoolWait (false)) {
     76            psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     77            return NULL;
     78        }
     79
     80        // we have only supplied one type of job, so we can assume the types here
     81        psThreadJob *job = NULL;
     82        while ((job = psThreadJobGetDone()) != NULL) {
     83            if (job->args->n < 1) {
     84                fprintf (stderr, "error with job\n");
     85            } else {
     86                psScalar *scalar = NULL;
     87                scalar = job->args->data[5];
     88                Nfit += scalar->data.S32;
     89                scalar = job->args->data[6];
     90                Npsf += scalar->data.S32;
     91                scalar = job->args->data[7];
     92                Next += scalar->data.S32;
     93                scalar = job->args->data[8];
     94                Nfail += scalar->data.S32;
     95
     96                // add these back onto sources
     97                psArray *newSources = job->args->data[4];
     98                for (int j = 0; j < newSources->n; j++) {
     99                    psArrayAdd (sources, 16, newSources->data[j]);
     100                }
     101            }
     102            psFree(job);
     103        }
     104    }
     105    psFree (cellGroups);
     106
     107    if (psTraceGetLevel("psphot") >= 6) {
     108      psphotSaveImage (NULL, readout->image,  "image.v2.fits");
     109    }
     110
     111    psLogMsg ("psphot.psphotBlendFit", PS_LOG_INFO, "fit models: %f sec for %d objects (%d psf, %d ext, %d failed, %ld skipped)\n", psTimerMark ("psphot.fit.nonlinear"), Nfit, Npsf, Next, Nfail, sources->n - Nfit);
     112
     113    psphotVisualShowResidualImage (readout);
     114    psphotVisualShowFlags (sources);
     115
     116    return true;
     117}
     118
     119bool psphotBlendFit_Threaded (psThreadJob *job) {
     120
     121    bool status = false;
     122    int Nfit = 0;
     123    int Npsf = 0;
     124    int Next = 0;
     125    int Nfail = 0;
     126    psScalar *scalar = NULL;
     127
     128    pmReadout *readout  = job->args->data[0];
     129    psMetadata *recipe  = job->args->data[1];
     130    psArray *sources    = job->args->data[2];
     131    pmPSF *psf          = job->args->data[3];
     132    psArray *newSources = job->args->data[4];
     133
    14134    // bit-masks to test for good/bad pixels
    15135    psMaskType maskVal = psMetadataLookupU8(&status, recipe, "MASK.PSPHOT");
     
    23143    maskVal |= markVal;
    24144
    25     // source analysis is done in S/N order (brightest first)
    26     sources = psArraySort (sources, pmSourceSortBySN);
    27 
    28145    // S/N limit to perform full non-linear fits
    29146    float FIT_SN_LIM = psMetadataLookupF32 (&status, recipe, "FULL_FIT_SN_LIM");
    30 
    31     psphotInitLimitsPSF (recipe, readout);
    32     psphotInitLimitsEXT (recipe);
    33     psphotInitRadiusPSF (recipe, psf->type);
    34 
    35     psphotFitInit ();
    36147
    37148    // option to limit analysis to a specific region
     
    41152
    42153    for (int i = 0; i < sources->n; i++) {
    43         // if (i%100 == 0) psphotFitSummary ();
    44 
    45154        pmSource *source = sources->data[i];
    46155
     
    57166        if (source->peak->SN < FIT_SN_LIM) continue;
    58167
    59         // XXX this should use peak?
     168        // exclude sources outside optional analysis region
    60169        if (source->peak->xf < AnalysisRegion.x0) continue;
    61170        if (source->peak->yf < AnalysisRegion.y0) continue;
     
    66175        if (source->modelPSF == NULL) continue;
    67176
    68         // skip sources which are insignificant flux?
     177        // skip sources which are insignificant flux?
     178        // XXX this is somewhat ad-hoc
    69179        if (source->modelPSF->params->data.F32[1] < 0.1) {
    70180            psTrace ("psphot", 5, "skipping near-zero source: %f, %f : %f\n",
     
    81191        Nfit ++;
    82192
    83         // XXX TEST
    84         // if ((fabs(source->peak->x - 1202) < 2) && (fabs(source->peak->y - 1065) < 2)) {
    85         // psTraceSetLevel ("psLib.math.psMinimizeLMChi2", 6);
    86         // }
    87 
    88         // try fitting PSFs, then try extended sources
    89         // these functions subtract the resulting fitted source (XXX and update the modelFlux?)
    90         // XXX re-consider conditions under which the source has EXT fit:
    91         // I should try EXT if the source size measurement says it is large
     193        // try fitting PSFs or extended sources depending on source->mode
     194        // these functions subtract the resulting fitted source
    92195        if (source->mode & PM_SOURCE_MODE_EXT_LIMIT) {
    93             if (psphotFitBlob (readout, source, sources, psf, maskVal, markVal)) {
     196            if (psphotFitBlob (readout, source, newSources, psf, maskVal, markVal)) {
    94197                source->type = PM_SOURCE_TYPE_EXTENDED;
    95198                psTrace ("psphot", 5, "source at %7.1f, %7.1f is ext", source->peak->xf, source->peak->yf);
     
    115218    }
    116219
    117     if (psTraceGetLevel("psphot") >= 6) {
    118       psphotSaveImage (NULL, readout->image,  "image.v2.fits");
    119     }
    120 
    121     psLogMsg ("psphot.psphotBlendFit", PS_LOG_INFO, "fit models: %f sec for %d objects (%d psf, %d ext, %d failed, %ld skipped)\n", psTimerMark ("psphot.fit.nonlinear"), Nfit, Npsf, Next, Nfail, sources->n - Nfit);
    122 
    123     psphotVisualShowResidualImage (readout);
    124     psphotVisualShowFlags (sources);
     220    // change the value of a scalar on the array (wrap this and put it in psArray.h)
     221    scalar = job->args->data[5];
     222    scalar->data.S32 = Nfit;
     223
     224    scalar = job->args->data[6];
     225    scalar->data.S32 = Npsf;
     226
     227    scalar = job->args->data[7];
     228    scalar->data.S32 = Next;
     229
     230    scalar = job->args->data[8];
     231    scalar->data.S32 = Nfail;
    125232
    126233    return true;
  • trunk/psphot/src/psphotCleanup.c

    r20411 r21166  
    1212    pmConceptsDone ();
    1313    pmConfigDone ();
     14    pmSourceFitSetDone ();
    1415    // fprintf (stderr, "found %d leaks at %s\n", psMemCheckLeaks (0, NULL, NULL, false), "psphot");
    1516    fprintf (stderr, "found %d leaks at %s\n", psMemCheckLeaks (0, NULL, stdout, false), "psphot");
  • trunk/psphot/src/psphotGuessModels.c

    r20453 r21166  
    11# include "psphotInternal.h"
    22
    3 bool psphotChooseCellSizes (int *Cx, int *Cy, pmReadout *readout, int nThreads);
    4 psphotGuessModelForRegionArgs *psphotGuessModelForRegionArgsAlloc();
    5 bool psphotGuessModelForRegion (psphotGuessModelForRegionArgs *args);
     3// XXX : the threading here is not great.  this may be due to blocks between elements, but
     4// the selection of the objects in a cell is not optimal.  To fix:
     5// 1) define the boundaries of the cells up front
     6// 2) loop over the sources once and associate them with their cell
     7// 3) define the threaded function to work with sources for a given cell
    68
    79// A guess for when the moments aren't available
     
    2022}
    2123
    22 # define NFILL 4
    23 
    2424// construct an initial PSF model for each object
    2525bool psphotGuessModels (pmConfig *config, pmReadout *readout, psArray *sources, pmPSF *psf) {
     
    3333    assert (recipe);
    3434
    35     // int nThreads = psMetadataLookupS32(&status, config->arguments, "NTHREADS"); // Number of threads
    36     // if (!status) {
    37     // nThreads = 0;
    38     // }
    39     int nThreads = 0;
     35    // determine the number of allowed threads
     36    int nThreads = psMetadataLookupS32(&status, config->arguments, "NTHREADS"); // Number of threads
     37    if (!status) {
     38        nThreads = 0;
     39    }
     40    // nThreads = 0; // XXX until testing is complete, do not thread this function
    4041
    4142    // bit-masks to test for good/bad pixels
     
    5354    psphotInitRadiusPSF (recipe, psf->type);
    5455
    55     // the strategy here is to divide the image into 2x2 blocks of cells and cycle through
    56     // the four discontiguous sets of cells, threading all within a set and blocking between
    57     // sets
    58 
    59     // we divide the image region into 2*2 blocks of size Nx*Ny, the image will have
    60     // Cx*Cy blocks so that (2Nx)Cx = numCols, (2Ny)Cy = numRows.  We want to choose Cx and
    61     // Cy so that (2Nx)Cx * (2Ny)Cy = 4 * NFILL * nThreads -- each of the four sets of cells
    62     // has enough cells to allow NFILL cells for each thread (to better distribute heavy and
    63     // light load cells
    64    
    65     // choose Cx, Cy:
     56    // choose Cx, Cy (see psphotThreadTools.c for overview of the concepts)
    6657    int Cx = 1, Cy = 1;
    6758    psphotChooseCellSizes (&Cx, &Cy, readout, nThreads);
    6859
    69     // the array runs from readout->image->col0 to readout->image->col0 + readout->image->numCols
    70     int Xo = readout->image->col0;
    71     int Yo = readout->image->row0;
    72     int Nx = readout->image->numCols / (2*Cx);
    73     int Ny = readout->image->numRows / (2*Cy);
    74 
    75     // we can thread all of the cells within a set, but need to block between sets
    76     for (int jy = 0; jy < 2; jy++) {
    77         for (int jx = 0; jx < 2; jx++) {
    78 
    79             // generate jobs for all of the Cx*Cy cells in this set
    80             for (int ix = 0; ix < Cx; ix++) {
    81                 for (int iy = 0; iy < Cy; iy++) {
    82                
    83                     int x0 = (2*ix + jx)*Nx + Xo;
    84                     int x1 = x0 + Nx;
    85 
    86                     int y0 = (2*iy + jy)*Ny + Yo;
    87                     int y1 = y0 + Ny;
    88 
    89                     if (readout->image->numCols + Xo - x1 < Nx) {
    90                         x1 = readout->image->numCols + Xo;
    91                     }
    92                     if (readout->image->numRows + Yo - y1 < Ny) {
    93                         y1 = readout->image->numRows + Yo;
    94                     }
    95 
    96                     // fprintf (stderr, "launch %d,%d - %d,%d\n", x0, y0, x1, y1);
    97                    
    98                     psRegion *cellRegion = psRegionAlloc (x0, x1, y0, y1);
    99                     *cellRegion = psRegionForImage (readout->image, *cellRegion);
    100                     // if we got the math above right, this should be a NOP
    101                                                                              
    102                     psphotGuessModelForRegionArgs *args = psphotGuessModelForRegionArgsAlloc();
    103                     args->readout = psMemIncrRefCounter(readout);
    104                     args->sources = psMemIncrRefCounter(sources);
    105                     args->psf     = psMemIncrRefCounter(psf);
    106                     args->region  = psMemIncrRefCounter(cellRegion);
    107 
    108                     args->maskVal = maskVal;
    109                     args->markVal = markVal;
    110 
    111                     // allocate a job -- if threads are not defined, this just runs the job
    112                     psThreadJob *job = psThreadJobAlloc ("PSPHOT_GUESS_MODEL");
    113                     psArrayAdd(job->args, 1, args);
    114                     if (!psThreadJobAddPending(job)) {
    115                         psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
    116                         return false;
    117                     }
    118                     psFree(cellRegion);
    119                     psFree(job);
    120                     psFree(args);
    121                 }
    122             }
    123 
    124             // wait for the threads to finish and manage results
    125             // wait here for the threaded jobs to finish
    126             // fprintf (stderr, "wait for threads (%d, %d)\n", jx, jy);
    127             if (!psThreadPoolWait (false)) {
     60    psArray *cellGroups = psphotAssignSources (Cx, Cy, sources);
     61
     62    for (int i = 0; i < cellGroups->n; i++) {
     63
     64        psArray *cells = cellGroups->data[i];
     65
     66        for (int j = 0; j < cells->n; j++) {
     67
     68            // allocate a job -- if threads are not defined, this just runs the job
     69            psThreadJob *job = psThreadJobAlloc ("PSPHOT_GUESS_MODEL");
     70            psArrayAdd(job->args, 1, readout);
     71            psArrayAdd(job->args, 1, cells->data[j]); // sources
     72            psArrayAdd(job->args, 1, psf);
     73
     74            // XXX change these to use abstract mask type info
     75            PS_ARRAY_ADD_SCALAR(job->args, maskVal,  PS_TYPE_U8);
     76            PS_ARRAY_ADD_SCALAR(job->args, markVal,  PS_TYPE_U8);
     77
     78            if (!psThreadJobAddPending(job)) {
    12879                psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     80                psFree (job);
    12981                return false;
    13082            }
    131 
    132             // we have only supplied one type of job, so we can assume the types here
    133             psThreadJob *job = NULL;
    134             while ((job = psThreadJobGetDone()) != NULL) {
    135                 // we have no returned data from this operation
    136                 if (job->args->n < 1) {
    137                     fprintf (stderr, "error with job\n");
    138                 }
    139                 psFree(job);
    140             }
    141         }
    142     }
    143    
     83            psFree(job);
     84        }
     85
     86        // wait for the threads to finish and manage results
     87        // wait here for the threaded jobs to finish
     88        // fprintf (stderr, "wait for threads (%d, %d)\n", jx, jy);
     89        if (!psThreadPoolWait (false)) {
     90            psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     91            return false;
     92        }
     93
     94        // we have only supplied one type of job, so we can assume the types here
     95        psThreadJob *job = NULL;
     96        while ((job = psThreadJobGetDone()) != NULL) {
     97            // we have no returned data from this operation
     98            if (job->args->n < 1) {
     99                fprintf (stderr, "error with job\n");
     100            }
     101            psFree(job);
     102        }
     103    }
     104
     105    // XXX check that all sources that should have models
     106    int nMiss = 0;
     107    for (int i = 0; i < sources->n; i++) {
     108
     109        pmSource *source = sources->data[i];
     110        if (source->mode & PM_SOURCE_MODE_EXT_LIMIT) {
     111            source->mode &= ~PM_SOURCE_MODE_EXT_LIMIT;
     112            continue;
     113        }
     114
     115        nMiss ++;
     116    }
     117    psLogMsg ("psphot.models", 4, "failed to build models for %d objects\n", nMiss);
     118
     119    psFree (cellGroups);
     120
    144121    psLogMsg ("psphot.models", 4, "built models for %ld objects: %f sec\n", sources->n, psTimerMark ("psphot.models"));
    145122    return true;
    146123}
    147124
    148 static void psphotGuessModelForRegionArgsFree(psphotGuessModelForRegionArgs *args)
    149 {
    150     psFree(args->readout);
    151     psFree(args->sources);
    152     psFree(args->psf);
    153     psFree(args->region);
    154     return;
    155 }
    156 
    157 psphotGuessModelForRegionArgs *psphotGuessModelForRegionArgsAlloc()
    158 {
    159     psphotGuessModelForRegionArgs *args = psAlloc(sizeof(psphotGuessModelForRegionArgs));
    160     psMemSetDeallocator(args, (psFreeFunc)psphotGuessModelForRegionArgsFree);
    161 
    162     args->readout = NULL;
    163     args->sources = NULL;
    164     args->psf = NULL;
    165     args->region = NULL;
    166 
    167     args->maskVal = 0;
    168     args->markVal = 0;
    169     return args;
    170 }
    171 
    172125// construct models only for sources in the specified region
    173 bool psphotGuessModelForRegion (psphotGuessModelForRegionArgs *args) {
    174 
    175     pmReadout *readout = args->readout;
    176     psArray *sources = args->sources;
    177     pmPSF *psf = args->psf;
    178     psRegion *region = args->region;
    179     psMaskType maskVal = args->maskVal;
    180     psMaskType markVal = args->markVal;
     126bool psphotGuessModel_Threaded (psThreadJob *job) {
     127
     128    pmReadout *readout = job->args->data[0];
     129    psArray *sources   = job->args->data[1];
     130    pmPSF *psf         = job->args->data[2];
     131   
     132    psMaskType maskVal = PS_SCALAR_VALUE(job->args->data[3],U8);
     133    psMaskType markVal = PS_SCALAR_VALUE(job->args->data[4],U8);
    181134
    182135    int nSrc = 0;
     
    184137    for (int i = 0; i < sources->n; i++) {
    185138        pmSource *source = sources->data[i];
     139
     140        // XXXX this is just for a test: use this to mark sources for which the model is measured
     141        // check later that all are used.
     142        source->mode |= PM_SOURCE_MODE_EXT_LIMIT;
    186143
    187144        // skip non-astronomical objects (very likely defects)
     
    189146        if (source->type == PM_SOURCE_TYPE_SATURATED) continue;
    190147        if (!source->peak) continue;
    191 
    192         if (source->peak->xf <  region->x0) continue;
    193         if (source->peak->yf <  region->y0) continue;
    194         if (source->peak->xf >= region->x1) continue;
    195         if (source->peak->yf >= region->y1) continue;
    196148
    197149        nSrc ++;
     
    256208    }
    257209
    258     // fprintf (stderr, "%d for region %lf,%lf - %lf,%lf\n", nSrc, region->x0, region->y0, region->x1, region->y1);
    259210    return true;
    260211}
    261212
    262 bool psphotChooseCellSizes (int *Cx, int *Cy, pmReadout *readout, int nThreads) {
    263 
    264     int nCells = nThreads * NFILL; // number of cells in a single set
    265     int C = sqrt(nCells) + 0.5;
    266    
    267     // we need to assign Cx and Cy based on the dimensionality of the image
    268     // crude way to find most evenly balanced factors of nCells:
    269     for (int i = C; i >= 1; i--) {
    270         int C1 = nCells / C;
    271         int C2 = nCells / C1;
    272         if (C1*C2 != nCells) continue;
    273 
    274         if (readout->image->numRows > readout->image->numCols) {
    275             *Cx = PS_MAX (C1, C2);
    276             *Cy = PS_MIN (C1, C2);
    277         } else {
    278             *Cx = PS_MAX (C1, C2);
    279             *Cy = PS_MIN (C1, C2);
    280         }
    281         return true;
    282     }
    283     *Cx = 1;
    284     *Cy = 1;
    285 
    286     return true;
    287 }
  • trunk/psphot/src/psphotMagnitudes.c

    r20453 r21166  
    11# include "psphotInternal.h"
    22
    3 bool psphotMagnitudes(pmConfig *config, const pmFPAview *view, psArray *sources, psMetadata *recipe, pmPSF *psf) {
     3bool psphotMagnitudes(pmConfig *config, pmReadout *readout, const pmFPAview *view, psArray *sources, pmPSF *psf) {
    44
    55    bool status = false;
     
    77
    88    psTimerStart ("psphot.mags");
     9
     10    // select the appropriate recipe information
     11    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     12    assert (recipe);
     13
     14    // determine the number of allowed threads
     15    int nThreads = psMetadataLookupS32(&status, config->arguments, "NTHREADS"); // Number of threads
     16    if (!status) {
     17        nThreads = 0;
     18    }
     19    // nThreads = 0; // XXX until testing is complete, do not thread this function
    920
    1021    pmReadout *backModel = psphotSelectBackground (config, view);
     
    4051    if (INTERPOLATE_AP) photMode |= PM_SOURCE_PHOT_INTERP;
    4152
     53    // choose Cx, Cy (see psphotThreadTools.c for overview of the concepts)
     54    int Cx = 1, Cy = 1;
     55    psphotChooseCellSizes (&Cx, &Cy, readout, nThreads);
     56
     57    psArray *cellGroups = psphotAssignSources (Cx, Cy, sources);
     58
     59    for (int i = 0; i < cellGroups->n; i++) {
     60
     61        psArray *cells = cellGroups->data[i];
     62
     63        for (int j = 0; j < cells->n; j++) {
     64
     65            // allocate a job -- if threads are not defined, this just runs the job
     66            psThreadJob *job = psThreadJobAlloc ("PSPHOT_MAGNITUDES");
     67
     68            psArrayAdd(job->args, 1, cells->data[j]); // sources
     69            psArrayAdd(job->args, 1, psf);
     70            psArrayAdd(job->args, 1, binning);
     71            psArrayAdd(job->args, 1, backModel);
     72            psArrayAdd(job->args, 1, backStdev);
     73
     74            PS_ARRAY_ADD_SCALAR(job->args, photMode, PS_TYPE_S32);
     75            PS_ARRAY_ADD_SCALAR(job->args, maskVal,  PS_TYPE_U8); // XXX change this to use abstract mask type info
     76            PS_ARRAY_ADD_SCALAR(job->args, 0,        PS_TYPE_S32); // this is used as a return value for nAp
     77
     78            if (!psThreadJobAddPending(job)) {
     79                psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     80                psFree (job);
     81                return false;
     82            }
     83            psFree(job);
     84
     85        }
     86
     87        // wait for the threads to finish and manage results
     88        if (!psThreadPoolWait (false)) {
     89            psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     90            return false;
     91        }
     92
     93        // we have only supplied one type of job, so we can assume the types here
     94        psThreadJob *job = NULL;
     95        while ((job = psThreadJobGetDone()) != NULL) {
     96            if (job->args->n < 1) {
     97                fprintf (stderr, "error with job\n");
     98            } else {
     99                psScalar *scalar = job->args->data[7];
     100                Nap += scalar->data.S32;
     101            }
     102            psFree(job);
     103        }
     104    }
     105
     106    psFree (cellGroups);
     107
     108    psLogMsg ("psphot.magnitudes", PS_LOG_DETAIL, "measure magnitudes : %f sec for %ld objects (%d with apertures)\n", psTimerMark ("psphot.mags"), sources->n, Nap);
     109    return true;
     110}
     111
     112bool psphotMagnitudes_Threaded (psThreadJob *job) {
     113
     114    bool status;
     115    int Nap = 0;
     116
     117    psArray *sources                = job->args->data[0];
     118    pmPSF *psf                      = job->args->data[1];
     119    psImageBinning *binning         = job->args->data[2];
     120    pmReadout *backModel            = job->args->data[3];
     121    pmReadout *backStdev            = job->args->data[4];
     122    pmSourcePhotometryMode photMode = PS_SCALAR_VALUE(job->args->data[5],S32);
     123    psMaskType maskVal              = PS_SCALAR_VALUE(job->args->data[6],U8);
     124
    42125    for (int i = 0; i < sources->n; i++) {
    43126        pmSource *source = (pmSource *) sources->data[i];
     
    47130        source->sky = psImageUnbinPixel(source->peak->x, source->peak->y, backModel->image, binning);
    48131        if (isnan(source->sky) && false) {
    49           psError(PSPHOT_ERR_SKY, false, "Setting pmSource.sky");
    50           psErrorStackPrint(NULL, " ");
    51           psErrorClear();
     132            psLogMsg ("psphot.magnitudes", PS_LOG_DETAIL, "error setting pmSource.sky");
    52133        }
    53134
    54135        source->skyErr = psImageUnbinPixel(source->peak->x, source->peak->y, backStdev->image, binning);
    55136        if (isnan(source->skyErr) && false) {
    56           psError(PSPHOT_ERR_SKY, false, "Setting pmSource.sky");
    57           psErrorStackPrint(NULL, " ");
    58           psErrorClear();
     137            psLogMsg ("psphot.magnitudes", PS_LOG_DETAIL, "error setting pmSource.skyErr");
    59138        }
    60139    }
    61140
    62     psLogMsg ("psphot.magnitudes", PS_LOG_DETAIL, "measure magnitudes : %f sec for %ld objects (%d with apertures)\n", psTimerMark ("psphot.mags"), sources->n, Nap);
     141    // change the value of a scalar on the array (wrap this and put it in psArray.h)
     142    psScalar *scalar = job->args->data[7];
     143    scalar->data.S32 = Nap;
     144
    63145    return true;
    64146}
    65 
    66 // XXX add in a measurement of the bright and faint completeness values
    67 // XXX push these into the recipe
  • trunk/psphot/src/psphotReadout.c

    r20829 r21166  
    7979
    8080    // construct sources and measure basic stats
    81     psArray *sources = psphotSourceStats (readout, recipe, detections);
     81    psArray *sources = psphotSourceStats (config, readout, detections);
    8282    if (!sources) return false;
    8383    if (!strcasecmp (breakPt, "PEAKS")) {
     
    178178
    179179    // non-linear PSF and EXT fit to brighter sources
    180     psphotBlendFit (readout, sources, recipe, psf);
     180    psphotBlendFit (config, readout, sources, psf);
    181181
    182182    // replace all sources
     
    207207
    208208    // define new sources based on only the new peaks
    209     psArray *newSources = psphotSourceStats (readout, recipe, detections);
     209    psArray *newSources = psphotSourceStats (config, readout, detections);
    210210
    211211    // set source type
     
    243243
    244244    // measure aperture photometry corrections
    245     if (!psphotApResid (readout, sources, recipe, psf)) {
     245    if (!psphotApResid (config, readout, sources, psf)) {
    246246        psLogMsg ("psphot", 3, "failed on psphotApResid");
    247247        return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
     
    249249
    250250    // calculate source magnitudes
    251     psphotMagnitudes(config, view, sources, recipe, psf);
     251    psphotMagnitudes(config, readout, view, sources, psf);
    252252
    253253    // replace failed sources?
  • trunk/psphot/src/psphotReadoutFindPSF.c

    r20337 r21166  
    3737
    3838    // construct sources and measure basic stats (moments, local sky)
    39     psArray *sources = psphotSourceStats(readout, recipe, detections);
     39    psArray *sources = psphotSourceStats(config, readout, detections);
    4040    if (!sources) return false;
    4141
  • trunk/psphot/src/psphotSetThreads.c

    r20411 r21166  
    11# include "psphot.h"
    2 
    3 // each thread runs this function, starting a new job when it finished with an old one
    4 // it is called with a (void *) pointer to its own thread pointer
    5 bool psphotThread_psphotGuessModel(psThreadJob *job)
    6 {
    7     psphotGuessModelForRegionArgs *args = job->args->data[0];
    8     bool status = psphotGuessModelForRegion (args);
    9     return status;
    10 }
    112
    123bool psphotSetThreads () {
     
    145    psThreadTask *task = NULL;
    156
    16     task = psThreadTaskAlloc("PSPHOT_GUESS_MODEL", 1);
    17     task->function = &psphotThread_psphotGuessModel;
     7    task = psThreadTaskAlloc("PSPHOT_GUESS_MODEL", 5);
     8    task->function = &psphotGuessModel_Threaded;
     9    psThreadTaskAdd(task);
     10    psFree(task);
     11
     12    task = psThreadTaskAlloc("PSPHOT_MAGNITUDES", 8);
     13    task->function = &psphotMagnitudes_Threaded;
     14    psThreadTaskAdd(task);
     15    psFree(task);
     16
     17    task = psThreadTaskAlloc("PSPHOT_APRESID_MAGS", 6);
     18    task->function = &psphotApResidMags_Threaded;
     19    psThreadTaskAdd(task);
     20    psFree(task);
     21
     22    task = psThreadTaskAlloc("PSPHOT_SOURCE_STATS", 4);
     23    task->function = &psphotSourceStats_Threaded;
     24    psThreadTaskAdd(task);
     25    psFree(task);
     26
     27    task = psThreadTaskAlloc("PSPHOT_BLEND_FIT", 9);
     28    task->function = &psphotBlendFit_Threaded;
    1829    psThreadTaskAdd(task);
    1930    psFree(task);
  • trunk/psphot/src/psphotSourceFits.c

    r19881 r21166  
    99static int NfitEXT = 0;
    1010
    11 bool psphotFitInit () {
     11bool psphotFitInit (int nThreads) {
    1212    psTimerStart ("psphot.fits");
     13    pmSourceFitSetInit (nThreads);
    1314    return true;
    1415}
     
    207208}
    208209
    209 bool psphotFitBlob (pmReadout *readout, pmSource *source, psArray *sources, pmPSF *psf, psMaskType maskVal, psMaskType markVal) {
     210bool psphotFitBlob (pmReadout *readout, pmSource *source, psArray *newSources, pmPSF *psf, psMaskType maskVal, psMaskType markVal) {
    210211
    211212    bool okEXT, okDBL;
     
    310311    psTrace ("psphot", 5, "blob as DBL: %f %f\n", ONE->params->data.F32[PM_PAR_XPOS], ONE->params->data.F32[PM_PAR_YPOS]);
    311312
    312     psArrayAdd (sources, 100, newSrc);
     313    psArrayAdd (newSources, 100, newSrc);
    313314    psFree (newSrc);
    314315    psFree (DBL);
  • trunk/psphot/src/psphotSourceStats.c

    r20453 r21166  
    11# include "psphotInternal.h"
    22
    3 psArray *psphotSourceStats (pmReadout *readout, psMetadata *recipe, pmDetections *detections)
    4 {
    5     bool     status = false;
     3psArray *psphotSourceStats (pmConfig *config, pmReadout *readout, pmDetections *detections) {
     4
     5    bool status = false;
    66    psArray *sources = NULL;
    7     float BIG_RADIUS;
    87
    98    psTimerStart ("psphot.stats");
    109
    11     // bit-masks to test for good/bad pixels
    12     psMaskType maskVal = psMetadataLookupU8(&status, recipe, "MASK.PSPHOT");
    13     assert (maskVal);
    14 
    15     // bit-mask to mark pixels not used in analysis
    16     psMaskType markVal = psMetadataLookupU8(&status, recipe, "MARK.PSPHOT");
    17     assert (markVal);
    18 
    19     // maskVal is used to test for rejected pixels, and must include markVal
    20     maskVal |= markVal;
     10    // select the appropriate recipe information
     11    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     12    assert (recipe);
     13
     14    // determine the number of allowed threads
     15    int nThreads = psMetadataLookupS32(&status, config->arguments, "NTHREADS"); // Number of threads
     16    if (!status) {
     17        nThreads = 0;
     18    }
     19    // nThreads = 0; // XXX until testing is complete, do not thread this function
    2120
    2221    // determine properties (sky, moments) of initial sources
    23     float INNER    = psMetadataLookupF32 (&status, recipe, "SKY_INNER_RADIUS");
    24     if (!status) return NULL;
    2522    float OUTER    = psMetadataLookupF32 (&status, recipe, "SKY_OUTER_RADIUS");
    26     if (!status) return NULL;
    27     float RADIUS   = psMetadataLookupF32 (&status, recipe, "PSF_MOMENTS_RADIUS");
    28     if (!status) return NULL;
    29     float MIN_SN   = psMetadataLookupF32 (&status, recipe, "MOMENTS_SN_MIN");
    3023    if (!status) return NULL;
    3124    char *breakPt  = psMetadataLookupStr (&status, recipe, "BREAK_POINT");
     
    3831    }
    3932
     33    // generate the array of sources, define the associated pixel
    4034    sources = psArrayAllocEmpty (peaks->n);
    4135
     36    for (int i = 0; i < peaks->n; i++) {
     37
     38        pmPeak *peak = peaks->data[i];
     39        if (peak->assigned) continue;
     40
     41        // create a new source
     42        pmSource *source = pmSourceAlloc();
     43
     44        // add the peak
     45        source->peak = psMemIncrRefCounter(peak);
     46
     47        // allocate space for moments
     48        source->moments = pmMomentsAlloc();
     49
     50        // allocate image, weight, mask arrays for each peak (square of radius OUTER)
     51        pmSourceDefinePixels (source, readout, source->peak->x, source->peak->y, OUTER);
     52
     53        peak->assigned = true;
     54        psArrayAdd (sources, 100, source);
     55        psFree (source);
     56    }
     57
     58    if (!strcasecmp (breakPt, "PEAKS")) {
     59        psLogMsg ("psphot", PS_LOG_INFO, "%ld sources : %f sec\n", sources->n, psTimerMark ("psphot.stats"));
     60        psLogMsg ("psphot", PS_LOG_INFO, "break point PEAKS, skipping MOMENTS\n");
     61        psphotVisualShowMoments (sources);
     62        return sources;
     63    }
     64
     65    // threaded measurement of the source magnitudes
    4266    int Nfail = 0;
    4367    int Nmoments = 0;
    44     for (int i = 0; i < peaks->n; i++) {
    45 
    46         pmPeak *peak = peaks->data[i];
    47         if (peak->assigned) continue;
    48 
    49         // create a new source, add peak
    50         pmSource *source = pmSourceAlloc();
    51         source->peak = psMemIncrRefCounter(peak);
    52 
    53         // allocate image, weight, mask arrays for each peak (square of radius OUTER)
    54         pmSourceDefinePixels (source, readout, source->peak->x, source->peak->y, OUTER);
    55         if (!strcasecmp (breakPt, "PEAKS")) {
    56             peak->assigned = true;
    57             psArrayAdd (sources, 100, source);
    58             psFree (source);
    59             continue;
    60         }
     68
     69    // choose Cx, Cy (see psphotThreadTools.c for overview of the concepts)
     70    int Cx = 1, Cy = 1;
     71    psphotChooseCellSizes (&Cx, &Cy, readout, nThreads);
     72
     73    psArray *cellGroups = psphotAssignSources (Cx, Cy, sources);
     74
     75    for (int i = 0; i < cellGroups->n; i++) {
     76
     77        psArray *cells = cellGroups->data[i];
     78
     79        for (int j = 0; j < cells->n; j++) {
     80
     81            // allocate a job -- if threads are not defined, this just runs the job
     82            psThreadJob *job = psThreadJobAlloc ("PSPHOT_SOURCE_STATS");
     83
     84            psArrayAdd(job->args, 1, cells->data[j]); // sources
     85            psArrayAdd(job->args, 1, recipe);
     86            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nmoments
     87            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nfail
     88
     89            if (!psThreadJobAddPending(job)) {
     90                psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     91                psFree (job);
     92                return NULL;
     93            }
     94            psFree(job);
     95
     96        }
     97
     98        // wait for the threads to finish and manage results
     99        if (!psThreadPoolWait (false)) {
     100            psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     101            return NULL;
     102        }
     103
     104        // we have only supplied one type of job, so we can assume the types here
     105        psThreadJob *job = NULL;
     106        while ((job = psThreadJobGetDone()) != NULL) {
     107            if (job->args->n < 1) {
     108                fprintf (stderr, "error with job\n");
     109            } else {
     110                psScalar *scalar = NULL;
     111                scalar = job->args->data[2];
     112                Nmoments += scalar->data.S32;
     113                scalar = job->args->data[3];
     114                Nfail += scalar->data.S32;
     115            }
     116            psFree(job);
     117        }
     118    }
     119
     120    psFree (cellGroups);
     121
     122    psLogMsg ("psphot", PS_LOG_INFO, "%ld sources, %d moments, %d failed: %f sec\n", sources->n, Nmoments, Nfail, psTimerMark ("psphot.stats"));
     123
     124    psphotVisualShowMoments (sources);
     125
     126    return (sources);
     127}
     128
     129bool psphotSourceStats_Threaded (psThreadJob *job) {
     130
     131    bool status = false;
     132    float BIG_RADIUS;
     133    psScalar *scalar = NULL;
     134
     135    psArray *sources                = job->args->data[0];
     136    psMetadata *recipe              = job->args->data[1];
     137
     138    float INNER    = psMetadataLookupF32 (&status, recipe, "SKY_INNER_RADIUS");
     139    if (!status) return false;
     140    float MIN_SN   = psMetadataLookupF32 (&status, recipe, "MOMENTS_SN_MIN");
     141    if (!status) return false;
     142    float RADIUS   = psMetadataLookupF32 (&status, recipe, "PSF_MOMENTS_RADIUS");
     143    if (!status) return false;
     144
     145    // bit-masks to test for good/bad pixels
     146    psMaskType maskVal = psMetadataLookupU8(&status, recipe, "MASK.PSPHOT");
     147    assert (maskVal);
     148
     149    // bit-mask to mark pixels not used in analysis
     150    psMaskType markVal = psMetadataLookupU8(&status, recipe, "MARK.PSPHOT");
     151    assert (markVal);
     152
     153    // maskVal is used to test for rejected pixels, and must include markVal
     154    maskVal |= markVal;
     155
     156    // threaded measurement of the sources moments
     157    int Nfail = 0;
     158    int Nmoments = 0;
     159    for (int i = 0; i < sources->n; i++) {
     160        pmSource *source = sources->data[i];
    61161
    62162        // skip faint sources for moments measurement
    63163        if (source->peak->SN < MIN_SN) {
    64             peak->assigned = true;
    65             psArrayAdd (sources, 100, source);
    66             psFree (source);
    67164            continue;
    68165        }
     
    72169        status = pmSourceLocalSky (source, PS_STAT_SAMPLE_MEDIAN, INNER, maskVal, markVal);
    73170        if (!status) {
    74           psFree (source);
    75           Nfail ++;
    76           psErrorClear();
    77           continue;
     171            psErrorClear(); // XXX re-consider the errors raised here
     172            Nfail ++;
     173            continue;
    78174        }
    79175
     
    82178        status = pmSourceLocalSkyVariance (source, PS_STAT_SAMPLE_MEDIAN, INNER, maskVal, markVal);
    83179        if (!status) {
    84           psFree (source);
    85           Nfail ++;
    86           psErrorClear();
    87           continue;
     180            Nfail ++;
     181            psErrorClear();
     182            continue;
    88183        }
    89184
     
    91186        status = pmSourceMoments (source, RADIUS);
    92187        if (status) {
    93             // add to the source array
    94             peak->assigned = true;
    95             psArrayAdd (sources, 100, source);
    96             psFree (source);
    97188            Nmoments ++;
    98189            continue;
     
    105196        status = pmSourceMoments (source, BIG_RADIUS);
    106197        if (status) {
    107             // add to the source array
    108             peak->assigned = true;
    109             psArrayAdd (sources, 100, source);
    110             psFree (source);
    111198            Nmoments ++;
    112199            continue;
    113200        }
    114201
    115         psFree (source);
    116202        Nfail ++;
    117203        psErrorClear();
     
    119205    }
    120206
    121     psLogMsg ("psphot", PS_LOG_INFO, "%ld sources, %d moments, %d failed: %f sec\n", sources->n, Nmoments, Nfail, psTimerMark ("psphot.stats"));
    122 
    123     psphotVisualShowMoments (sources);
    124 
    125     return (sources);
     207    // change the value of a scalar on the array (wrap this and put it in psArray.h)
     208    scalar = job->args->data[2];
     209    scalar->data.S32 = Nmoments;
     210
     211    scalar = job->args->data[3];
     212    scalar->data.S32 = Nfail;
     213   
     214    return true;
    126215}
    127 
    128 // XXX EAM : filter out bad peaks (eg, no valid pixels available for sky)
Note: See TracChangeset for help on using the changeset viewer.