IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Feb 17, 2006, 7:13:42 AM (20 years ago)
Author:
magnier
Message:

bulk merge of eam_rel9_p0 onto this branch

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/rel10_ifa/psModules/src/imcombine/pmReadoutCombine.c

    r6325 r6448  
    55 *  @author GLG, MHPCC
    66 *
    7  *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
    8  *  @date $Date: 2006-02-06 21:03:25 $
     7 *  @version $Revision: 1.5.4.1 $ $Name: not supported by cvs2svn $
     8 *  @date $Date: 2006-02-17 17:13:41 $
    99 *
    1010 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    3636}
    3737
     38static void pmCombineParamsFree (pmCombineParams *params)
     39{
     40
     41    if (params == NULL)
     42        return;
     43
     44    psFree (params->stats);
     45    return;
     46}
     47
     48pmCombineParams *pmCombineParamsAlloc (psStatsOptions statsOptions)
     49{
     50
     51    pmCombineParams *params = psAlloc (sizeof(pmCombineParams));
     52    psMemSetDeallocator(params, (psFreeFunc) pmCombineParamsFree);
     53
     54    params->stats = psStatsAlloc (statsOptions);
     55    params->maskVal = 0;
     56    params->fracHigh = 0.25;
     57    params->fracHigh = 0.25;
     58    params->nKeep = 3;
     59
     60    return (params);
     61}
     62
    3863/******************************************************************************
    3964XXX: Must add support for S16 and S32 types.  F32 currently supported.
    4065 *****************************************************************************/
    4166psImage *pmReadoutCombine(psImage *output,
    42                           const psList *inputs,
    43                           psCombineParams *params,
     67                          const psArray *inputs,
    4468                          const psVector *zero,
    4569                          const psVector *scale,
     70                          pmCombineParams *params,
    4671                          bool applyZeroScale,
    4772                          psF32 gain,
    4873                          psF32 readnoise)
     74{
     75    PS_ASSERT_PTR_NON_NULL(inputs, NULL);
     76    PS_ASSERT_PTR_NON_NULL(params, NULL);
     77    PS_ASSERT_PTR_NON_NULL(params->stats, NULL);
     78    if (zero != NULL) {
     79        PS_ASSERT_VECTOR_TYPE(zero, PS_TYPE_F32, NULL);
     80        //        PS_ASSERT_VECTOR_TYPE_S16_S32_F32(zero, NULL);
     81    }
     82    if (scale != NULL) {
     83        PS_ASSERT_VECTOR_TYPE(scale, PS_TYPE_F32, NULL);
     84        //        PS_ASSERT_VECTOR_TYPE_S16_S32_F32(scale, NULL);
     85    }
     86    if ((zero != NULL) && (scale != NULL)) {
     87        PS_ASSERT_VECTOR_TYPE_EQUAL(zero, scale, NULL);
     88        // PS_ASSERT_VECTOR_TYPE_S16_S32_F32(scale, NULL);
     89    }
     90
     91    psStats *stats = params->stats;
     92    psS32 maxInputCols = 0;
     93    psS32 maxInputRows = 0;
     94    psS32 minInputCols = PS_MAX_S32;
     95    psS32 minInputRows = PS_MAX_S32;
     96    pmReadout *tmpReadout = NULL;
     97    psS32 tmpI;
     98    psElemType outputType = PS_TYPE_F32;
     99
     100    if (DetermineNumBits(stats->options) != 1) {
     101        psError(PS_ERR_UNKNOWN, true,
     102                "Multiple statistical options have been requested.  Returning NULL.\n");
     103        return(NULL);
     104    }
     105
     106    // We step through each readout in the input image list.  If any readout is
     107    // NULL, empty, or has the wrong type, we generate an error and return
     108    // NULL.  We determine how big of an output image is needed to combine
     109    // these input images.  We do this by taking the
     110    //     max(readout->col0 + readout->numCols + image->col0 + image->numCols)
     111    //     max(readout->row0 + readout->numRows + image->row0 + image->numRows)
     112    //
     113    for (int i = 0; i < inputs->n; i++) {
     114        tmpReadout = inputs->data[i];
     115        PS_ASSERT_READOUT_NON_NULL(tmpReadout, output);
     116        PS_ASSERT_READOUT_NON_EMPTY(tmpReadout, output);
     117        PS_ASSERT_READOUT_TYPE(tmpReadout, PS_TYPE_F32, output);
     118
     119        minInputRows = PS_MIN(minInputRows, (tmpReadout->row0 + tmpReadout->image->row0));
     120        tmpI = tmpReadout->row0 +
     121               tmpReadout->image->row0 +
     122               tmpReadout->image->numRows;
     123        maxInputRows = PS_MAX(maxInputRows, tmpI);
     124
     125        minInputCols = PS_MIN(minInputCols, (tmpReadout->col0 + tmpReadout->image->col0));
     126        tmpI = tmpReadout->col0 +
     127               tmpReadout->image->col0 +
     128               tmpReadout->image->numCols;
     129        maxInputCols = PS_MAX(maxInputCols, tmpI);
     130    }
     131
     132    // We ensure that the zero vector is of the proper size.
     133    if (zero != NULL) {
     134        PS_ASSERT_VECTOR_TYPE(zero, PS_TYPE_F32, NULL);
     135        if (zero->n < inputs->n) {
     136            psError(PS_ERR_UNKNOWN, true, "zero vector has incorrect size (%d).  Returning NULL.\n", zero->n);
     137            return(NULL);
     138        } else if (zero->n > inputs->n) {
     139            // XXX EAM : abort on this condition? is probably an error
     140            psLogMsg(__func__, PS_LOG_WARN,
     141                     "WARNING: the zero vector too many elements (%d)\n", zero->n);
     142        }
     143    }
     144
     145    // We ensure that the scale vector is of the proper size.
     146    if (scale != NULL) {
     147        PS_ASSERT_VECTOR_TYPE(scale, PS_TYPE_F32, NULL);
     148        if (scale->n < inputs->n) {
     149            psError(PS_ERR_UNKNOWN, true, "scale vector has incorrect size (%d).  Returning NULL.\n", scale->n);
     150            return(NULL);
     151        } else if (scale->n > inputs->n) {
     152            // XXX EAM : abort on this condition? is probably an error
     153            psLogMsg(__func__, PS_LOG_WARN,
     154                     "WARNING: the scale vector has too many elements (%d)\n", scale->n);
     155        }
     156    }
     157
     158    // At this point, the following variables have been computed:
     159    // maxInputRows: the largest input row value, in output image space.
     160    // maxInputCols: the largest input column value, in output image space.
     161    // minInputRows: the smallest input row value, in output image space.
     162    // minInputCols: the smallest input column value, in output image space.
     163    //
     164    if (output == NULL) {
     165        output = psImageAlloc(maxInputCols-minInputCols, maxInputRows-minInputRows, outputType);
     166        *(psS32 *) &(output->col0) = minInputCols;
     167        *(psS32 *) &(output->row0) = minInputRows;
     168    } else {
     169
     170        // XXX EAM : recycle the existing output image?  why would we care about the existing pixels?
     171        PS_ASSERT_IMAGE_TYPE(output, PS_TYPE_F32, NULL);
     172        if (((output->col0 + output->numCols) < maxInputCols) ||
     173                ((output->row0 + output->numRows) < maxInputRows)) {
     174            psError(PS_ERR_UNKNOWN, true,
     175                    "Output image (%d, %d) is too small to hold combined images.  Returning NULL.\n",
     176                    output->row0 + output->numRows,
     177                    output->col0 + output->numCols);
     178            return(NULL);
     179        }
     180
     181        // reset output origin using logic of above
     182        *(psS32 *) &(output->col0) = minInputCols;
     183        *(psS32 *) &(output->row0) = minInputRows;
     184    }
     185
     186    psVector *tmpPixels     = psVectorAlloc(inputs->n, PS_TYPE_F32);
     187    psVector *tmpPixelsKeep = psVectorAlloc(inputs->n, PS_TYPE_F32);
     188    psVector *outRowLower   = psVectorAlloc(inputs->n, PS_TYPE_U32);
     189    psVector *outRowUpper   = psVectorAlloc(inputs->n, PS_TYPE_U32);
     190    psVector *outColLower   = psVectorAlloc(inputs->n, PS_TYPE_U32);
     191    psVector *outColUpper   = psVectorAlloc(inputs->n, PS_TYPE_U32);
     192
     193    // For each input readout, we store the min/max pixel indices for that readout, in detector coordinates,
     194    // in the psVectors (outRowLower, outColLower, outRowUpper, outColUpper).
     195    for (int i = 0; i < inputs->n; i++) {
     196        tmpReadout = (pmReadout *) inputs->data[i];
     197        outRowLower->data.U32[i] = tmpReadout->row0 + tmpReadout->image->row0;
     198        outColLower->data.U32[i] = tmpReadout->col0 + tmpReadout->image->col0;
     199        outRowUpper->data.U32[i] = tmpReadout->row0 +
     200                                   tmpReadout->image->row0 +
     201                                   tmpReadout->image->numRows;
     202        outColUpper->data.U32[i] = tmpReadout->col0 +
     203                                   tmpReadout->image->col0 +
     204                                   tmpReadout->image->numCols;
     205    }
     206
     207    // We loop through each pixel in the output image.  We loop through each
     208    // input readout.  We determine if that output pixel is contained in the
     209    // image from that readout.  If so, we save it in psVector tmpPixels.
     210    // If not, we set a mask for that element in tmpPixels.  Then, we mask off
     211    // pixels not between fracLow and fracHigh.  Then we call the vector
     212    // stats routine on those pixels/mask.  Then we set the output pixel value
     213    // to the result of the stats call.
     214
     215    int nx, ny;
     216    int nKeep, nMin;
     217    float keepFrac = 1.0 - params->fracLow - params->fracHigh;
     218    float value = 0;
     219    psF32 *saveVector = tmpPixelsKeep->data.F32;
     220
     221    for (int j = output->row0; j < (output->row0 + output->numRows) ; j++) {
     222        if (j % 10 == 0)
     223            fprintf (stderr, ".");
     224        for (int i = output->col0; i < (output->col0 + output->numCols) ; i++) {
     225            int nPix = 0;
     226            for (int r = 0; r < inputs->n; r++) {
     227                tmpReadout = (pmReadout *) inputs->data[r];
     228
     229                // psTrace (__func__, 6, "[%d][%d]: [%d][%d] to [%d][%d]\n", i, j, outColLower->data.U32[r], outRowLower->data.U32[r], outColUpper->data.U32[r], outRowUpper->data.U32[r]);
     230                if (i <  outColLower->data.U32[r])
     231                    continue;
     232                if (i >= outColUpper->data.U32[r])
     233                    continue;
     234                if (j <  outRowLower->data.U32[r])
     235                    continue;
     236                if (j >= outRowUpper->data.U32[r])
     237                    continue;
     238
     239                nx = i - (tmpReadout->col0 + tmpReadout->image->col0);
     240                ny = j - (tmpReadout->row0 + tmpReadout->image->row0);
     241
     242                if (tmpReadout->mask != NULL) {
     243                    if (tmpReadout->mask->data.U8[ny][nx] && params->maskVal)
     244                        continue;
     245                }
     246
     247                tmpPixels->data.F32[nPix] = tmpReadout->image->data.F32[ny][nx];
     248                // psTrace (__func__, 6, "readout[%d], image [%d][%d] is %f\n", r, i, j, tmpPixels->data.F32[nPix]);
     249                nPix ++;
     250            }
     251            tmpPixels->n = nPix;
     252
     253            // are there enough valid pixels to apply fracLow,fracHigh?
     254            nKeep = nPix * keepFrac;
     255            if (nKeep >= params->nKeep) {
     256                psVectorSort (tmpPixels, tmpPixels);
     257                nMin = nPix * params->fracLow;
     258                tmpPixelsKeep->data.F32 = &tmpPixels->data.F32[nMin];
     259                tmpPixelsKeep->n = nKeep;
     260            } else {
     261                tmpPixelsKeep->data.F32 = tmpPixels->data.F32;
     262                tmpPixelsKeep->n = nPix;
     263            }
     264
     265            // tmpPixelsKeep is already sorted.  sample mean and median are very easy
     266            if (stats->options & PS_STAT_SAMPLE_MEAN) {
     267                value = 0;
     268                for (int r = 0; r < tmpPixelsKeep->n; r++) {
     269                    value += tmpPixelsKeep->data.F32[r];
     270                }
     271                if (tmpPixelsKeep->n == 0) {
     272                    value = 0;
     273                } else {
     274                    value = value / tmpPixelsKeep->n;
     275                }
     276            }
     277            if (stats->options & PS_STAT_SAMPLE_MEDIAN) {
     278                int r = tmpPixelsKeep->n / 2;
     279                if (tmpPixelsKeep->n == 0) {
     280                    value = 0;
     281                    goto got_value;
     282                }
     283                if (tmpPixelsKeep->n % 2 == 1) {
     284                    int r = 0.5*tmpPixelsKeep->n;
     285                    value = tmpPixelsKeep->data.F32[r];
     286                    goto got_value;
     287                }
     288                if (tmpPixelsKeep->n % 2 == 0) {
     289                    value = 0.5*(tmpPixelsKeep->data.F32[r] +
     290                                 tmpPixelsKeep->data.F32[r-1]);
     291                    goto got_value;
     292                }
     293            }
     294got_value:
     295            output->data.F32[j-output->row0][i-output->col0] = value;
     296        }
     297    }
     298    tmpPixelsKeep->data.F32 = saveVector;
     299
     300    psFree(tmpPixels);
     301    psFree(tmpPixelsKeep);
     302    psFree(outRowLower);
     303    psFree(outRowUpper);
     304    psFree(outColLower);
     305    psFree(outColUpper);
     306
     307    return(output);
     308}
     309
     310/******************************************************************************
     311XXX: Must add support for S16 and S32 types.  F32 currently supported.
     312 *****************************************************************************/
     313psImage *pmReadoutCombine_OLD(psImage *output,
     314                              const psList *inputs,
     315                              pmCombineParams *params,
     316                              const psVector *zero,
     317                              const psVector *scale,
     318                              bool applyZeroScale,
     319                              psF32 gain,
     320                              psF32 readnoise)
    49321{
    50322    PS_ASSERT_PTR_NON_NULL(inputs, NULL);
     
    410682    psRegion minRegion;
    411683    psRegion maxRegion;
    412     psStats *minStats = psStatsAlloc(PS_STAT_FITTED_MEAN);
    413     psStats *maxStats = psStatsAlloc(PS_STAT_FITTED_MEAN);
     684    psStats *minStats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN);
     685    psStats *maxStats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN);
    414686    psStats *diffStats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN);
    415687    psVector *diffs = psVectorAlloc(fringePoints->n, PS_TYPE_F32);
     
    445717        }
    446718
    447         fp->midValue = 0.5 * (maxStats->fittedMean + minStats->fittedMean);
    448         fp->delta = maxStats->fittedMean - minStats->fittedMean;
     719        fp->midValue = 0.5 * (maxStats->robustMedian + minStats->robustMedian);
     720        fp->delta = maxStats->robustMedian - minStats->robustMedian;
    449721        diffs->data.F32[i] = fp->delta;
    450722    }
     
    455727    psFree(diffs);
    456728    if (diffStats == NULL) {
    457         psError(PS_ERR_UNKNOWN, true, "Could not determine fitted median of the differences.\n");
     729        psError(PS_ERR_UNKNOWN, true, "Could not determine robust median of the differences.\n");
    458730        return(NULL);
    459731    }
     
    461733}
    462734
    463 
    464 
    465 /**
    466  *
    467  * The input array fluxLevels consists of Ni vectors, one per mosaic image.
    468  * Each vector consists of Nj elements, each a measurement of the input
    469  * flat-field image flux levels. All of these vectors must be constructed with
    470  * the same number of elements, or the function will return an error. If a chip
    471  * is missing from a particular image, that element should be set to NaN. The
    472  * vector chipGains supplies initial guesses for the chip gains. If the vector
    473  * contains the values 0.0 or NaN for any of the elements, the gain is set to the
    474  * mean of the valid values. If the vector length does not match the number of
    475  * chips, an warning is raised, all chip gain guesses will be set to 1.0, and the
    476  * vector length modified to match the number of chips defined by the supplied
    477  * fluxLevels. The sourceFlux input vector must be allocated (not NULL), but the
    478  * routine will set the vector length to the number of source images regardless
    479  * of the initial state of the vector. All vectors used by this function must be
    480  * of type PS_DATA_F64.
    481  *
    482  
    483 fluxLevels(i, j): for each flat field image i, this psArray contains a vector
    484 with an elemenmt for each chip j.  So, fluxLevels(i, j) corresponds to the
    485 measured flux M_(i, j) for flat image i, chip j.
    486  
    487 chipGains[]: has j elements, one for each chip.
    488  
    489  
    490 They have the observed flux levels for each chip of each image.  They want to
    491 solve for the actual flux levels and the gain of each chip.
    492  
    493 Okay, they want to solve for source fluxes and chip gains.
    494  
    495  *
    496  */
    497 bool pmFlatNormalization(
    498     psVector *sourceFlux,
    499     psVector *chipGains,
    500     psArray *fluxLevels)
    501 {
    502     PS_ASSERT_PTR_NON_NULL(fluxLevels, false);
    503     psS32 numImages = fluxLevels->n;
    504     psS32 numChips = ((psVector *) fluxLevels->data[0])->n;
    505     for (psS32 i = 0 ; i < numImages ; i++) {
    506         psVector *tmpVec = (psVector *) fluxLevels->data[i];
    507         PS_ASSERT_VECTOR_NON_NULL(tmpVec, false);
    508         PS_ASSERT_VECTOR_TYPE(tmpVec, PS_TYPE_F64, false);
    509         PS_ASSERT_VECTOR_SIZE(tmpVec, numChips, false);
    510     }
    511 
    512     //
    513     // Ensure that *localChipGains points to a vector of the same length as numImages.
    514     //
    515     PS_ASSERT_PTR_NON_NULL(chipGains, false);
    516     PS_ASSERT_VECTOR_TYPE(chipGains, PS_TYPE_F64, false);
    517     psVector *localChipGains = chipGains;
    518     if (numChips != chipGains->n) {
    519         psLogMsg(__func__, PS_LOG_WARN, "WARNING: the chipGains vector length does not match the number of chips.\n");
    520         localChipGains = psVectorAlloc(numChips, PS_TYPE_F64);
    521         psBool rc = psVectorInit(localChipGains, 1.0);
    522         if (rc == false) {
    523             printf("XXX: gen error\n");
    524         }
    525     }
    526 
    527     //
    528     // If the chipGains vector contains the values 0.0 or NaN for any of the elements,
    529     // the gain is set to the mean of the valid values.
    530     //
    531     psBool meanFlag = false;
    532     psVector *chipGainsMask = psVectorAlloc(chipGains->n, PS_TYPE_U8);
    533     for (psS32 i = 0 ; i < chipGains->n ; i++) {
    534         if ((fabs(chipGains->data.F64[i]) < FLT_EPSILON) ||
    535                 (isnan(chipGains->data.F64[i]))) {
    536             chipGainsMask->data.U8[i] = 1;
    537             meanFlag = true;
    538         }
    539     }
    540     // Must calculate the mean.
    541     if (meanFlag == true) {
    542         psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
    543         stats = psVectorStats(stats, chipGains, NULL, chipGainsMask, 1);
    544         if (stats == NULL) {
    545             printf("XXX: gen error\n");
    546         }
    547         psF64 mean;
    548         psBool rc = p_psGetStatValue(stats, &mean);
    549         if (rc == false) {
    550             printf("XXX: gen error\n");
    551         }
    552         // Set the gain to this mean for chips with a gain of 0.0 or NAN
    553 
    554         for (psS32 i = 0 ; i < chipGains->n ; i++) {
    555             if ((fabs(chipGains->data.F64[i]) < FLT_EPSILON) ||
    556                     (isnan(chipGains->data.F64[i]))) {
    557                 chipGains->data.F64[i] = mean;
    558             }
    559         }
    560     }
    561 
    562     //
    563     // Assert that sourceFlux is non-NULL, correct type, correct size.
    564     //
    565     PS_ASSERT_PTR_NON_NULL(sourceFlux, false);
    566     PS_ASSERT_VECTOR_TYPE(sourceFlux, PS_TYPE_F64, false);
    567     psVectorRealloc(sourceFlux, numImages);
    568 
    569     //    psFree(psVector);
    570     if (numImages != chipGains->n) {
    571         psFree(localChipGains);
    572     }
    573 
    574     return(true);
    575 }
Note: See TracChangeset for help on using the changeset viewer.