IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Mar 5, 2012, 5:19:48 PM (14 years ago)
Author:
mhuber
Message:

merging latest r33407 trunk changes to meh_branches/ppstack_test

Location:
branches/meh_branches/ppstack_test
Files:
3 deleted
65 edited
1 copied

Legend:

Unmodified
Added
Removed
  • branches/meh_branches/ppstack_test

  • branches/meh_branches/ppstack_test/psModules

  • branches/meh_branches/ppstack_test/psModules/src/astrom/pmAstrometryWCS.c

    r28386 r33415  
    487487
    488488    if (fpa->toSky == NULL) {
     489        psFree(fpa->toTPA);
     490        psFree(fpa->fromTPA);
    489491        fpa->toTPA = psPlaneTransformIdentity (1);
    490492        fpa->fromTPA = psPlaneTransformIdentity (1);
  • branches/meh_branches/ppstack_test/psModules/src/camera/pmReadoutFake.c

    r29004 r33415  
    5151
    5252    psF32 *params = model->params->data.F32; // Model parameters
    53     psEllipseAxes axes = pmPSF_ModelToAxes(params, MAX_AXIS_RATIO); // Ellipse axes
     53    psEllipseAxes axes = pmPSF_ModelToAxes(params, MAX_AXIS_RATIO, model->type); // Ellipse axes
    5454    // Curiously, the minor axis can be larger than the major axis, so need to check.
    5555    if (axes.major >= axes.minor) {
     
    5858        axes.major = axes.minor;
    5959    }
    60     return pmPSF_AxesToModel(params, axes);
     60    return pmPSF_AxesToModel(params, axes, model->type);
    6161}
    6262
     
    314314                }
    315315            }
    316             if (!psThreadPoolWait(true)) {
     316            if (!psThreadPoolWait(true, true)) {
    317317                psError(PS_ERR_UNKNOWN, false, "Error waiting for threads.");
    318318                psFree(groups);
  • branches/meh_branches/ppstack_test/psModules/src/concepts/pmConceptsStandard.c

    r30049 r33415  
    751751  bool has_video_cell = false;
    752752
    753   if (concept->type != PS_DATA_STRING) {
    754     psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Type for %s (%x) is not string\n",
    755             concept->name, concept->type);
    756     return NULL;
    757   }
    758 
    759   char *Vptr = strchr(concept->data.V,'V');
    760   if (Vptr) {
    761     has_video_cell = true;
     753  if (concept->type == PS_DATA_BOOL) {
     754    has_video_cell = concept->data.B;
     755  } else {
     756    if (concept->type != PS_DATA_STRING) {
     757        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Type for %s (%x) is not string\n",
     758                concept->name, concept->type);
     759        return NULL;
     760      }
     761
     762      char *Vptr = strchr(concept->data.V,'V');
     763      if (Vptr) {
     764        has_video_cell = true;
     765      }
    762766  }
    763767
  • branches/meh_branches/ppstack_test/psModules/src/detrend/pmBias.c

    r29833 r33415  
    154154    if (threaded) {
    155155        // wait here for the threaded jobs to finish
    156         if (!psThreadPoolWait(true)) {
     156        if (!psThreadPoolWait(true, true)) {
    157157            psError(PS_ERR_UNKNOWN, false, "Unable to apply bias correction.");
    158158            return false;
  • branches/meh_branches/ppstack_test/psModules/src/detrend/pmDark.c

    r28405 r33415  
    601601    if (threaded) {
    602602        // wait here for the threaded jobs to finish
    603         if (!psThreadPoolWait(true)) {
     603        if (!psThreadPoolWait(true, true)) {
    604604            psError(PS_ERR_UNKNOWN, false, "Unable to apply dark.");
    605605            psFree(orders);
  • branches/meh_branches/ppstack_test/psModules/src/detrend/pmFlatField.c

    r28405 r33415  
    161161    if (threaded) {
    162162        // wait here for the threaded jobs to finish
    163         if (!psThreadPoolWait(true)) {
     163        if (!psThreadPoolWait(true, true)) {
    164164            psError(PS_ERR_UNKNOWN, false, "Unable to flat-field image.");
    165165            return false;
  • branches/meh_branches/ppstack_test/psModules/src/detrend/pmPattern.c

    r27676 r33415  
    66
    77#include "pmPattern.h"
     8
     9#define PATTERN_ROW_BKG_FIX 1
    810
    911
     
    8991    psImageInit(corr, NAN);
    9092
     93#ifdef PATTERN_ROW_BKG_FIX
     94    // CZW: 2011-11-30
     95    // Define the vectors to hold the "x" and "y" slope trends.
     96    // Briefly, the slope trend in the y-axis is a due to variations in the 0-th order term
     97    // of the PATTERN.ROW fit between individual rows across the cell.  Similarly, the 1-st
     98    // order term of the PATTERN.ROW fit defines the trend in the x-axis (as that's what we
     99    // are fitting with PATTERN.ROW in the first place).  However, the thing we're trying to
     100    // fix with PATTERN.ROW is the detector level bias wiggles.  These should be overlaid on
     101    // the true sky level.  Therefore, simply applying the PATTERN.ROW correction will
     102    // introduce cell-to-cell sky variations as these two trends are removed.  To avoid this,
     103    // We store the 0th and 1st order values used for each row, and then fit a polynomial to
     104    // these results.  By re-adding these systematic trends back, we can remove the row-to-row
     105    // variations without improperly removing the real sky trend.
     106    psVector *yaxisData = psVectorAlloc(numRows, PS_TYPE_F32); // Data to fit to the constant term
     107    psVector *yaxisMask = psVectorAlloc(numRows, PS_TYPE_VECTOR_MASK); // Mask for rows with no fit
     108    psVector *xaxisData = psVectorAlloc(numRows, PS_TYPE_F32); // Data to fit to the linear term
     109    psVectorInit(yaxisMask, 0);
     110#endif
    91111    for (int y = 0; y < numRows; y++) {
    92112        psVectorInit(clipMask, 0);
     
    105125            // Not enough points to fit
    106126            patternMaskRow(ro, y, maskBad);
     127#ifdef PATTERN_ROW_BKG_FIX
     128            // Ignore this row in our subsequent fits, because the fit failed.
     129            yaxisMask->data.PS_TYPE_VECTOR_MASK_DATA[y] = 0xFF;
     130#endif
    107131            continue;
    108132        }
     
    111135            psErrorClear();
    112136            patternMaskRow(ro, y, maskBad);
    113             continue;
    114         }
    115 
    116         poly->coeff[0] -= background;
     137#ifdef PATTERN_ROW_BKG_FIX
     138            // Ignore this row in our subsequent fits, because the fit failed.
     139            yaxisMask->data.PS_TYPE_VECTOR_MASK_DATA[y] = 0xFF;
     140#endif
     141            continue;
     142        }
     143#ifndef PATTERN_ROW_BKG_FIX
     144        poly->coeff[0] -= background;
     145#else
     146        // Store the results we found for this row.
     147        yaxisData->data.F32[y] = poly->coeff[0];
     148        xaxisData->data.F32[y] = poly->coeff[1];
     149        psTrace("pattern",1,"%d %g %g\n",y,poly->coeff[0],poly->coeff[1]);
     150       
     151        //      yaxisData->data.F32[y] = 0.0;
     152/*      xaxisData->data.F32[y] = 0.0; */
     153       
     154#endif
    117155        memcpy(corr->data.F64[y], poly->coeff, (order + 1) * PSELEMTYPE_SIZEOF(PS_TYPE_F64));
    118156        psVector *solution = psPolynomial1DEvalVector(poly, indices); // Solution vector
     
    121159            psErrorClear();
    122160            patternMaskRow(ro, y, maskBad);
     161#ifdef PATTERN_ROW_BKG_FIX
     162            yaxisMask->data.PS_TYPE_VECTOR_MASK_DATA[y] = 0xFF;
     163#endif
    123164            continue;
    124165        }
     
    126167        for (int x = 0; x < numCols; x++) {
    127168            image->data.F32[y][x] -= solution->data.F32[x];
     169            psTrace("pattern",5,"A: %d %d %g\n",x,y,solution->data.F32[x]);
    128170        }
    129171        psFree(solution);
    130172    }
    131173
     174#ifdef PATTERN_ROW_BKG_FIX
     175    // Put the global trends back that were removed by the PATTERN.ROW correction.
     176    // Set up the indices for the polynomial
     177    psVector *yaxisIndices = psVectorAlloc(numRows, PS_TYPE_F32);
     178    norm = 2.0 / (float)numRows;
     179    for (int y = 0; y < numRows; y++) {
     180      yaxisIndices->data.F32[y] = y * norm - 1.0;
     181      psTrace("psModules.detrend.pattern",10,"%d %f %f\n",y,yaxisIndices->data.F32[y],yaxisData->data.F32[y]);
     182    }
     183
     184    // Fit the trend of the constant term, producing the y-axis global trend
     185    psStatsInit(clip);
     186    psPolynomial1D *yaxisPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 1); // Polynomial to fit.
     187    if (!psVectorClipFitPolynomial1D(yaxisPoly,clip,yaxisMask,0xFF,yaxisData, NULL, yaxisIndices)) {
     188      psWarning("Unable to fit polynomial to y-axis trend");
     189      psErrorClear();
     190      // If we've failed, we need to do something, so add back in the background level, and
     191      // expect that the final image will have background mismatches.
     192      for (int y = 0; y < numRows; y++) {
     193        for (int x = 0; x < numCols; x++) {
     194          image->data.F32[y][x] += background;
     195          corr->data.F64[y][0]  -= background;
     196        }
     197      }
     198    }
     199    else {
     200      psVector *solution = psPolynomial1DEvalVector(yaxisPoly,yaxisIndices);
     201      if (!solution) {
     202        psWarning("Unable to evaluate polynomial");
     203        psErrorClear();
     204        // If we've failed, we need to do something, so add back in the background level, and
     205        // expect that the final image will have background mismatches.
     206        for (int y = 0; y < numRows; y++) {
     207          for (int x = 0; x < numCols; x++) {
     208            image->data.F32[y][x] += background;
     209            corr->data.F64[y][0]  -= background;
     210          }
     211        }
     212      }
     213      else {
     214        for (int y = 0; y < numRows; y++) {
     215          for (int x = 0; x < numCols; x++) {
     216            image->data.F32[y][x] += solution->data.F32[y];
     217            corr->data.F64[y][0]  -= solution->data.F32[y];
     218            psTrace("pattern",5,"B: %d %d %g\n",x,y,solution->data.F32[x]);
     219          }
     220        }
     221      }
     222      psFree(solution);
     223    }     
     224
     225    // Fit the trend of the linear term, producing the x-axis global trend
     226    // We can use the same mask vector, as the same rows failed the row-fit earlier.
     227    psStatsInit(clip);
     228    psPolynomial1D *xaxisPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 1); // Polynomial to fit.
     229    if (!psVectorClipFitPolynomial1D(xaxisPoly,clip,yaxisMask,0xFF,xaxisData, NULL, yaxisIndices)) {
     230      psWarning("Unable to fit polynomial to x-axis trend");
     231      psErrorClear();
     232    }
     233    else {
     234      psVector *solution = psPolynomial1DEvalVector(xaxisPoly,yaxisIndices);
     235      if (!solution) {
     236        psWarning("Unable to evaluate polynomial");
     237        psErrorClear();
     238      }
     239      else {
     240        for (int y = 0; y < numRows; y++) {
     241          for (int x = 0; x < numCols; x++) {
     242            image->data.F32[y][x] += solution->data.F32[y] * indices->data.F32[x];
     243            corr->data.F64[y][1]  -= solution->data.F32[y] ;
     244            psTrace("pattern",5,"C: %d %d %g %g\n",x,y,solution->data.F32[x],indices->data.F32[x]);
     245          }
     246        }
     247      }
     248      psFree(solution);
     249    }
     250    psFree(yaxisPoly);
     251    psFree(xaxisPoly);
     252    psFree(yaxisIndices);
     253    psFree(yaxisMask);
     254    psFree(yaxisData);
     255    psFree(xaxisData);
     256    // End PATTERN_ROW_BKG_FIX global trend replacement
     257#endif
     258   
    132259    psMetadataAddImage(ro->analysis, PS_LIST_TAIL, PM_PATTERN_ROW_CORRECTION, PS_META_REPLACE,
    133260                       "Pattern row correction", corr);
     
    382509
    383510
     511
     512bool pmPatternContinuity(pmChip *chip, const psVector *tweak, psStatsOptions bgStat, psStatsOptions cellStat,
     513                         psImageMaskType maskVal, psImageMaskType maskBad, int edgeWidth)
     514{
     515    PS_ASSERT_PTR_NON_NULL(chip, false);
     516    PS_ASSERT_VECTOR_NON_NULL(tweak, false);
     517    PS_ASSERT_VECTOR_SIZE(tweak, chip->cells->n, false);
     518    PS_ASSERT_VECTOR_TYPE(tweak, PS_TYPE_U8, false);
     519
     520    int numCells = tweak->n;            // Number of cells
     521
     522    psVector *meanMask = psVectorAlloc(numCells, PS_TYPE_VECTOR_MASK); // Mask for means
     523    psVectorInit(meanMask, 0);
     524
     525    // Mask bits
     526    enum {
     527        PM_PATTERN_IGNORE = 0x01,       // Ignore this cell
     528        PM_PATTERN_TWEAK  = 0x02,       // Tweak this cell
     529        PM_PATTERN_ERROR  = 0x04,       // Error in calculating background
     530        PM_PATTERN_ALL    = 0xFF,       // All causes
     531    };
     532
     533    // Count number of cells to tweak
     534    int numTweak = 0;                   // Number of cells to tweak
     535    int numIgnore = 0;                  // Number of cells to ignore
     536    for (int i = 0; i < numCells; i++) {
     537        pmCell *cell = chip->cells->data[i]; // Cell of interest
     538        if (!cell || !cell->data_exists || !cell->process ||
     539            cell->readouts->n == 0 || cell->readouts->n > 1 || !cell->readouts->data[0]) {
     540            numIgnore++;
     541            meanMask->data.PS_TYPE_VECTOR_MASK_DATA[i] = PM_PATTERN_IGNORE;
     542            continue;
     543        }
     544        if (tweak->data.U8[i]) {
     545            meanMask->data.PS_TYPE_VECTOR_MASK_DATA[i] = PM_PATTERN_TWEAK;
     546            numTweak++;
     547        }
     548    }
     549    if (numTweak == 0) {
     550        // Nothing to do
     551        psFree(meanMask);
     552        return true;
     553    }
     554
     555    // Measure mean of each cell edge, and use that to determine the cell offsets.
     556
     557    psStats *bgStats = psStatsAlloc(bgStat); // Statistics on background
     558    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS); // Random number generator
     559
     560    psRegion region = {0,0,0,0};
     561
     562    /* These images hold the edge data for the OTA structure.  */
     563    psImage *A = psImageAlloc(8,8,PS_TYPE_F64); // Top edge
     564    psImage *B = psImageAlloc(8,8,PS_TYPE_F64); // Bottom edge
     565    psImage *C = psImageAlloc(8,8,PS_TYPE_F64); // Right edge
     566    psImage *D = psImageAlloc(8,8,PS_TYPE_F64); // Left edge
     567    psImageInit(A,0.0);
     568    psImageInit(B,0.0);
     569    psImageInit(C,0.0);
     570    psImageInit(D,0.0);
     571   
     572    for (int i = 0; i < numCells; i++) {
     573        if (meanMask->data.PS_TYPE_VECTOR_MASK_DATA[i] & PM_PATTERN_IGNORE) {
     574            continue;
     575        }
     576        pmCell *cell = chip->cells->data[i]; // Cell of interest
     577        pmReadout *ro = cell->readouts->data[0]; // Readout of interest
     578
     579        psStatsInit(bgStats);
     580
     581        // Convert cell iterator i into an xy coordinate on the grid of cells
     582        int y = (i % 8);
     583        int x = (i - y) / 8;
     584       
     585        for (int j = 0; j < 4; j++) {
     586          if (j == 0) {  // Region B
     587            region = psRegionSet(0,ro->image->numCols,
     588                                 0,edgeWidth);
     589          }
     590          else if (j == 1) { // Region A
     591            region = psRegionSet(0,ro->image->numCols,
     592                                 ro->image->numRows - edgeWidth,ro->image->numRows);
     593          }
     594          else if (j == 2) { // Region D
     595            region = psRegionSet(0,edgeWidth,
     596                                 0,ro->image->numRows);
     597          }
     598          else if (j == 3) { // Region C
     599            region = psRegionSet(ro->image->numCols - edgeWidth,ro->image->numCols,
     600                                 0,ro->image->numRows);
     601          }
     602          psImage *subset  = psImageSubset(ro->image,region);
     603          psImage *submask = psImageSubset(ro->mask,region);
     604
     605          if (!psImageBackground(bgStats, NULL, subset, submask, maskVal, rng)) {
     606            psWarning("Unable to measure background for cell %d on edge %d\n", i, j);
     607            psErrorClear();
     608            meanMask->data.PS_TYPE_VECTOR_MASK_DATA[i] |= PM_PATTERN_ERROR;
     609            if (j == 0)      { B->data.F64[y][x] = NAN; }
     610            else if (j == 1) { A->data.F64[y][x] = NAN; }
     611            else if (j == 2) { C->data.F64[y][x] = NAN; }
     612            else if (j == 3) { D->data.F64[y][x] = NAN; }
     613            psFree(subset);
     614            psFree(submask);
     615            continue; // Move on to next edge, as only part of this cell may be a problem
     616          }
     617 
     618          // If the returned value is zero, assume something is wrong.  Do I still need this?
     619          if (psStatsGetValue(bgStats,bgStat) < 1e-6) {
     620            if (j == 0)      { B->data.F64[y][x] = NAN; }
     621            else if (j == 1) { A->data.F64[y][x] = NAN; }
     622            else if (j == 2) { C->data.F64[y][x] = NAN; }
     623            else if (j == 3) { D->data.F64[y][x] = NAN; }
     624          }
     625          // If we have an error for this cell/edge, make sure we mask the value
     626          if (meanMask->data.PS_TYPE_VECTOR_MASK_DATA[i] & PM_PATTERN_ERROR) {
     627            if (j == 0)      { B->data.F64[y][x] = NAN; }
     628            else if (j == 1) { A->data.F64[y][x] = NAN; }
     629            else if (j == 2) { C->data.F64[y][x] = NAN; }
     630            else if (j == 3) { D->data.F64[y][x] = NAN; }
     631          }
     632          else { // Set the value to match what we got from the edge box.
     633            if (j == 0)      { B->data.F64[y][x] = psStatsGetValue(bgStats,bgStat); }
     634            else if (j == 1) { A->data.F64[y][x] = psStatsGetValue(bgStats,bgStat); }
     635            else if (j == 2) { C->data.F64[y][x] = psStatsGetValue(bgStats,bgStat); }
     636            else if (j == 3) { D->data.F64[y][x] = psStatsGetValue(bgStats,bgStat); }
     637          }
     638
     639          for (int u = 0; u < subset->numCols; u++) {
     640            for (int v = 0; v < subset->numRows; v++) {
     641              psTrace("psModules.detrend.cont",10,"BOX: %d %d (%d %d) (%d %d) %f %d",
     642                      i,j,x,y,u,v,subset->data.F32[v][u],submask->data.PS_TYPE_IMAGE_MASK_DATA[v][u]);
     643            }
     644          }       
     645         
     646          psFree(subset);
     647          psFree(submask);
     648
     649        }
     650        psTrace("psModules.detrend.cont",5, "OTA: %d (%d %d) A: %f B: %f C: %f D: %f",
     651                i,x,y,
     652                A->data.F64[y][x],B->data.F64[y][x],C->data.F64[y][x],D->data.F64[y][x]);               
     653    }
     654    psFree(bgStats);
     655    psFree(rng);
     656
     657    // We've now allocated all the edge values, so we can now minimize the offsets.
     658    // This involves solving the equation A x = b, where
     659    // A is the (64x64 for GPC1) matrix containing the edges that match for each cell
     660    // x is the solution vector
     661    // b is the combination of offsets across each cell boundary for each cell.
     662    // Below "XX" is used as the matrix A, and "solution" is used as both b and x
     663    //   (due to the way psMatrixLUSolve operates).
     664    psVector *solution = psVectorAlloc(64,PS_TYPE_F64);
     665    psImage  *XX       = psImageAlloc(64,64,PS_TYPE_F64);
     666    psVectorInit(solution,0.0);
     667    psImageInit(XX,0.0);
     668   
     669    for (int i = 0; i < numCells; i++) {
     670      // Accumulate all the possible edge differences we can for this cell.
     671      // As we do so, make a note of the correlations by incrementing the element of the matrix.
     672      int y = (i % 8);
     673      int x = (i - y) / 8;
     674      int j;
     675      double critical_value = 0.0;
     676      if (meanMask->data.PS_TYPE_VECTOR_MASK_DATA[i] & PM_PATTERN_IGNORE) {
     677        continue;
     678      }
     679      if (x + 1 < 8) {  // We have a neighbor adjacent in the +x direction
     680        j = 8 * (x + 1) + y; // Determine that neighbor's index
     681        if (fabs(C->data.F64[y][x]) > fabs(D->data.F64[y][x+1])) {
     682          critical_value = 2.0 * fabs(D->data.F64[y][x+1]);
     683        }
     684        else {
     685          critical_value = 2.0 * fabs(C->data.F64[y][x]);
     686        }
     687        if (critical_value < 25) { critical_value = 25; }
     688        psTrace("psModules.detrend.cont",5,"CmD %d %d %d %d %g %g %g", // diagnostic
     689                i,x,y,j,
     690                C->data.F64[y][x],
     691                D->data.F64[y][x+1],
     692                critical_value
     693                );
     694        if (!(meanMask->data.PS_TYPE_VECTOR_MASK_DATA[j] & PM_PATTERN_IGNORE)&&  // If there are no errors with the neighbor,
     695            (isfinite(C->data.F64[y][x]))&&(isfinite(D->data.F64[y][x+1]))&&     // and all edges have valid values,
     696            (fabs(C->data.F64[y][x] - D->data.F64[y][x+1]) < critical_value)     // and there are no large discontinuities,
     697            ) {   
     698          solution->data.F64[i] += C->data.F64[y][x] - D->data.F64[y][x+1];     // Take the difference
     699          XX->data.F64[i][i] += 1;                                              // increment our relation with ourself
     700          XX->data.F64[i][j] += -1;                                             // decrement our relation with the neighbor
     701        }
     702      }
     703      if (x - 1 > -1) { // etc.
     704        j = 8 * (x - 1) + y;
     705        if (fabs(C->data.F64[y][x-1]) > fabs(D->data.F64[y][x])) {
     706          critical_value = 2.0 * fabs(D->data.F64[y][x]);
     707        }
     708        else {
     709          critical_value = 2.0 * fabs(C->data.F64[y][x-1]);
     710        }
     711        if (critical_value < 25) { critical_value = 25; }
     712        psTrace("psModules.detrend.cont",5,"DmC %d %d %d %d %g %g %g",
     713                i,x,y,j,
     714                D->data.F64[y][x],
     715                C->data.F64[y][x-1],
     716                critical_value
     717                );
     718
     719        if (!(meanMask->data.PS_TYPE_VECTOR_MASK_DATA[j] & PM_PATTERN_IGNORE)&&
     720            (isfinite(D->data.F64[y][x]))&&(isfinite(C->data.F64[y][x-1]))&&
     721            (fabs(D->data.F64[y][x] - C->data.F64[y][x-1]) < critical_value)
     722            ) {
     723          solution->data.F64[i] += D->data.F64[y][x] - C->data.F64[y][x-1];
     724          XX->data.F64[i][i] += 1;
     725          XX->data.F64[i][j] += -1;
     726        }
     727      }
     728      if (y + 1 < 8) {
     729        j = 8 * x + (y + 1);
     730        psTrace("psModules.detrend.cont",5,"AmB %d %d %d %d %g %g",
     731                i,x,y,j,
     732                A->data.F64[y][x],
     733                B->data.F64[y+1][x]
     734                );
     735        if (fabs(A->data.F64[y][x]) > fabs(B->data.F64[y+1][x])) {
     736          critical_value = 2.0 * fabs(B->data.F64[y+1][x]);
     737        }
     738        else {
     739          critical_value = 2.0 * fabs(A->data.F64[y][x]);
     740        }
     741        if (critical_value < 25) { critical_value = 25; }
     742        if (!(meanMask->data.PS_TYPE_VECTOR_MASK_DATA[j] & PM_PATTERN_IGNORE)&&
     743            (isfinite(A->data.F64[y][x]))&&(isfinite(B->data.F64[y+1][x]))&&
     744            (fabs(A->data.F64[y][x] - B->data.F64[y+1][x]) < critical_value)
     745            ) {
     746          solution->data.F64[i] += A->data.F64[y][x] - B->data.F64[y+1][x];
     747          XX->data.F64[i][i] += 1;
     748          XX->data.F64[i][j] += -1;
     749        }
     750      }
     751      if (y - 1 > -1) {
     752        j = 8 * x +  (y - 1);
     753        psTrace("psModules.detrend.cont",5,"BmA %d %d %d %d %g %g",
     754                i,x,y,j,
     755                B->data.F64[y][x],
     756                A->data.F64[y-1][x]
     757                );
     758        if (fabs(A->data.F64[y-1][x]) > fabs(B->data.F64[y][x])) {
     759          critical_value = 2.0 * fabs(B->data.F64[y][x]);
     760        }
     761        else {
     762          critical_value = 2.0 * fabs(A->data.F64[y-1][x]);
     763        }
     764        if (critical_value < 25) { critical_value = 25; }
     765        if (!(meanMask->data.PS_TYPE_VECTOR_MASK_DATA[j] & PM_PATTERN_IGNORE)&&
     766            (isfinite(B->data.F64[y][x]))&&(isfinite(A->data.F64[y-1][x]))&&
     767            (fabs(B->data.F64[y][x] - A->data.F64[y-1][x]) < critical_value)
     768            ) {
     769          solution->data.F64[i] += B->data.F64[y][x] - A->data.F64[y-1][x];
     770          XX->data.F64[i][i] += 1;
     771          XX->data.F64[i][j] += -1;
     772        }
     773      }
     774    }
     775    double max_XX = 0;
     776    double solution_V = 0;
     777    int i_peak = -1;
     778    for (int i = 0; i < numCells; i++) { // If any cells have no value of themself, set the matrix to 1.0.
     779      if (XX->data.F64[i][i] == 0.0) {
     780        XX->data.F64[i][i] = 1.0;
     781      }
     782      if (XX->data.F64[i][i] > max_XX) {
     783        max_XX = XX->data.F64[i][i];
     784        solution_V = solution->data.F64[i];
     785        i_peak = i;
     786      }
     787    }
     788    psTrace("psModules.detrend.cont",5,"fixed point: %d %g\n",
     789            i_peak,solution_V);
     790
     791    for (int i = 0; i < numCells; i++) {
     792/*        if (!((XX->data.F64[i][i] == 1.0)&& */
     793/*          (solution->data.F64[i] == 0.0))) { */
     794        solution->data.F64[i] -= solution_V;
     795        if (i != i_peak) {
     796          for (int j = 0; j < numCells; j++) {
     797            XX->data.F64[i][j] -= XX->data.F64[i_peak][j];
     798          }
     799        }
     800/*        } */
     801    }
     802    for (int i = 0; i < numCells; i++) {
     803      XX->data.F64[i_peak][i] = 0.0;
     804    }
     805    XX->data.F64[i_peak][i_peak] = 1.0;
     806   
     807   
     808#if (1)
     809    for (int i = 0; i < numCells; i++) { // print matrix A
     810      psTrace("psModules.detrend.cont",5,"A: %3d % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f % 2.0f",
     811              i,
     812              XX->data.F64[i][0],             XX->data.F64[i][1],             XX->data.F64[i][2],             XX->data.F64[i][3],
     813              XX->data.F64[i][4],             XX->data.F64[i][5],             XX->data.F64[i][6],             XX->data.F64[i][7],
     814              XX->data.F64[i][8],             XX->data.F64[i][9],             XX->data.F64[i][10],            XX->data.F64[i][11],
     815              XX->data.F64[i][12],            XX->data.F64[i][13],            XX->data.F64[i][14],            XX->data.F64[i][15],
     816              XX->data.F64[i][16],            XX->data.F64[i][17],            XX->data.F64[i][18],            XX->data.F64[i][19],
     817              XX->data.F64[i][20],            XX->data.F64[i][21],            XX->data.F64[i][22],            XX->data.F64[i][23],
     818              XX->data.F64[i][24],            XX->data.F64[i][25],            XX->data.F64[i][26],            XX->data.F64[i][27],
     819              XX->data.F64[i][28],            XX->data.F64[i][29],            XX->data.F64[i][30],            XX->data.F64[i][31],
     820              XX->data.F64[i][32],            XX->data.F64[i][33],            XX->data.F64[i][34],            XX->data.F64[i][35],
     821              XX->data.F64[i][36],            XX->data.F64[i][37],            XX->data.F64[i][38],            XX->data.F64[i][39],
     822              XX->data.F64[i][40],            XX->data.F64[i][41],            XX->data.F64[i][42],            XX->data.F64[i][43],
     823              XX->data.F64[i][44],            XX->data.F64[i][45],            XX->data.F64[i][46],            XX->data.F64[i][47],
     824              XX->data.F64[i][48],            XX->data.F64[i][49],            XX->data.F64[i][50],            XX->data.F64[i][51],
     825              XX->data.F64[i][52],            XX->data.F64[i][53],            XX->data.F64[i][54],            XX->data.F64[i][55],
     826              XX->data.F64[i][56],            XX->data.F64[i][57],            XX->data.F64[i][58],            XX->data.F64[i][59],
     827              XX->data.F64[i][60],            XX->data.F64[i][61],            XX->data.F64[i][62],            XX->data.F64[i][63]
     828              );
     829    }
     830
     831    for (int i = 0; i < numCells; i++) { // print vector b
     832      psTrace("psModules.detrend.cont",5,"b: %d %f",
     833              i,
     834              solution->data.F64[i]
     835              );
     836    }
     837#endif   
     838   
     839    // Solve the Ax=b equation
     840    //    psMatrixLUSolve(XX,solution);
     841    psMatrixGJSolve(XX,solution);
     842#if (1)
     843    for (int i = 0; i < numCells; i++) { // print vector b
     844      psTrace("psModules.detrend.cont",5,"x: %d %f",
     845              i,
     846              solution->data.F64[i]
     847              );
     848    }
     849#endif
     850   
     851    /* old code to remove the minimum solution value from the set, to give a "minimal set of offsets." Mathematically unnecessary. */
     852/*     double min = 99e99; */
     853/*     for (int i = 0; i < numCells; i++) { */
     854/*       if (solution->data.F64[i] < min) { */
     855/*      min = solution->data.F64[i]; */
     856/*       } */
     857/*       psTrace("psModules.detrend.cont",5,"x: %d %f %f ", */
     858/*            i, */
     859/*            solution->data.F64[i],min */
     860/*            ); */
     861/*     } */
     862/*     for (int i = 0; i < numCells; i++) { */
     863/*      if (solution->data.F64[i] != 0.0) { */
     864/*        solution->data.F64[i] -= min; */
     865/*      } */
     866/*     } */
     867
     868    // Cleanup
     869    psFree(XX);
     870    psFree(A);
     871    psFree(B);
     872    psFree(C);
     873    psFree(D);
     874
     875    // Correct cells based on the offsets calculated, and store the result in the analysis metadata.
     876    for (int i = 0; i < numCells; i++) {
     877        if (meanMask->data.PS_TYPE_VECTOR_MASK_DATA[i] & PM_PATTERN_IGNORE) {
     878            continue;
     879        }
     880        if (!(meanMask->data.PS_TYPE_VECTOR_MASK_DATA[i] & PM_PATTERN_TWEAK)) {
     881            continue;
     882        }
     883        pmCell *cell = chip->cells->data[i]; // Cell of interest
     884        pmReadout *ro = cell->readouts->data[0]; // Readout of interest
     885
     886        float correction = solution->data.F64[i];
     887        const char *cellName = psMetadataLookupStr(NULL, cell->concepts, "CELL.NAME"); // Name of cell
     888        psLogMsg("psModules.detrend", PS_LOG_DETAIL, "Correcting background of cell %s by %f",
     889                 cellName, correction);
     890        psBinaryOp(ro->image, ro->image, "-", psScalarAlloc(correction, PS_TYPE_F32));
     891        psMetadataAddF32(ro->analysis, PS_LIST_TAIL, PM_PATTERN_CELL_CORRECTION, PS_META_REPLACE,
     892                         "Pattern cell correction solution", correction);
     893    }
     894
     895    psFree(solution);
     896    psFree(meanMask);
     897
     898    return true;
     899}
     900
     901bool pmPatternContinuityApply(pmReadout *ro, psImageMaskType maskBad)
     902{
     903    PM_ASSERT_READOUT_NON_NULL(ro, false);
     904    PM_ASSERT_READOUT_IMAGE(ro, false);
     905
     906    bool mdok;                          // Status of MD lookup
     907    float corr = psMetadataLookupF32(&mdok, ro->analysis, PM_PATTERN_CELL_CORRECTION); // Correction to apply
     908    if (!mdok) {
     909        // No correction to apply
     910        return true;
     911    }
     912
     913    psImage *image = ro->image, *mask = ro->mask; // Image and mask of interest
     914    int numCols = image->numCols, numRows = image->numRows; // Size of image
     915
     916    if (!isfinite(corr)) {
     917        for (int y = 0; y < numRows; y++) {
     918            for (int x = 0; x < numCols; x++) {
     919                image->data.F32[y][x] = NAN;
     920            }
     921        }
     922        if (mask) {
     923            for (int y = 0; y < numRows; y++) {
     924                for (int x = 0; x < numCols; x++) {
     925                    mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] |= maskBad;
     926                }
     927            }
     928        }
     929    } else {
     930        for (int y = 0; y < numRows; y++) {
     931            for (int x = 0; x < numCols; x++) {
     932                image->data.F32[y][x] += corr;
     933            }
     934        }
     935    }
     936
     937    return true;
     938}
     939
     940
  • branches/meh_branches/ppstack_test/psModules/src/detrend/pmPattern.h

    r26893 r33415  
    5454                        );
    5555
     56/// Fix the background on cells known to be troublesome
     57bool pmPatternContinuity(
     58    pmChip *chip,                       ///< Chip to correct
     59    const psVector *tweak,              ///< U8 vector indicating whether to tweak the corresponding cell
     60    psStatsOptions bgStat,              ///< Statistic to use for background measurement
     61    psStatsOptions cellStat,            ///< Statistic to use for combination of cell background measurements
     62    psImageMaskType maskVal,            ///< Mask value to use
     63    psImageMaskType maskBad,            ///< Mask value to give bad pixels
     64    int edgeWidth                       ///< Size of box to use
     65    );
     66
     67/// Apply previously measured cell pattern correction
     68bool pmPatternContinuityApply(pmReadout *ro,          ///< Readout to correct
     69                        psImageMaskType maskBad ///< Mask value to give bad pixels
     70                        );
     71
     72
    5673
    5774/// @}
  • branches/meh_branches/ppstack_test/psModules/src/detrend/pmShutterCorrection.c

    r29004 r33415  
    805805        if (threaded) {
    806806            // wait here for the threaded jobs to finish
    807             if (!psThreadPoolWait(true)) {
     807            if (!psThreadPoolWait(true, true)) {
    808808                psError(PS_ERR_UNKNOWN, false, "Unable to apply shutter correction.");
    809809                psFree(shutterImage);
  • branches/meh_branches/ppstack_test/psModules/src/imcombine/pmPSFEnvelope.c

    r31451 r33415  
    3636
    3737
    38 //#define TESTING                         // Enable test output
     38#define TESTING                         // Enable test output
    3939// #define PEAK_NORM                       // Normalise peaks?
    4040#define PEAK_FLUX 1.0e4                 // Peak flux for each source
     
    380380
    381381        // measure the source moments: tophat windowing, no pixel S/N cutoff
    382         if (!pmSourceMoments(source, maxRadius, 0.0, 0.0, 0.0, maskVal)) {
     382        if (!pmSourceMoments(source, maxRadius, 0.25*maxRadius, 0.0, 0.0, maskVal)) {
    383383            // Can't do anything about it; limp along as best we can
    384384            psErrorClear();
  • branches/meh_branches/ppstack_test/psModules/src/imcombine/pmStackReject.c

    r31435 r33415  
    313313    }
    314314
    315     if (!psThreadPoolWait(false)) {
     315    if (!psThreadPoolWait(false, true)) {
    316316        psError(psErrorCodeLast(), false, "Unable to grow bad pixels.");
    317317        psFree(source);
  • branches/meh_branches/ppstack_test/psModules/src/imcombine/pmSubtraction.c

    r30738 r33415  
    905905        }
    906906    }
    907     if (!psThreadPoolWait(true)) {
     907    if (!psThreadPoolWait(true, true)) {
    908908        psError(psErrorCodeLast(), false, "Error waiting for threads.");
    909909        return false;
     
    10191019                }
    10201020            }
    1021             pmSubtractionStampPrint(ds9, stamp->x, stamp->y, stamps->footprint, "red");
     1021
     1022            psString ds9text = NULL;
     1023
     1024            psStringAppend(&ds9text, "flux: %.0f ", match->fluxes->data.F32[i]);
     1025            psStringAppend(&ds9text, "chi2: %.0f ", match->chisq->data.F32[i]);
     1026
     1027            pmSubtractionStampPrint(ds9, stamp->x, stamp->y, stamps->footprint, "red", ds9text);
     1028
     1029            psFree(ds9text);       
    10221030
    10231031            // Set stamp for replacement
     
    10411049        } else {
    10421050            numGood++;
    1043             pmSubtractionStampPrint(ds9, stamp->x, stamp->y, stamps->footprint, "green");
     1051
     1052            //MEH bad way to do this - should also add to rej/red one as well
     1053            // -- is match from subQuality what want?
     1054            psString ds9text = NULL;
     1055
     1056            psStringAppend(&ds9text, "flux: %.0f ", match->fluxes->data.F32[i]);
     1057            psStringAppend(&ds9text, "chi2: %.0f ", match->chisq->data.F32[i]);
     1058
     1059            pmSubtractionStampPrint(ds9, stamp->x, stamp->y, stamps->footprint, "green", ds9text);
     1060
     1061            psFree(ds9text);       
    10441062        }
    10451063    }
     
    14271445    }
    14281446
    1429     if (!psThreadPoolWait(false)) {
     1447    if (!psThreadPoolWait(false, true)) {
    14301448        psError(psErrorCodeLast(), false, "Error waiting for threads.");
    14311449        return false;
     
    14871505            }
    14881506        }
     1507        psFree(out1->covariance);
    14891508        out1->covariance = psImageCovarianceAverage(covars);
    14901509        psFree(covars);
     
    15271546            }
    15281547        }
     1548        psFree(out2->covariance);
    15291549        out2->covariance = psImageCovarianceAverage(covars);
    15301550        psFree(covars);
  • branches/meh_branches/ppstack_test/psModules/src/imcombine/pmSubtractionEquation.c

    r30622 r33415  
    796796    stamp->normSquare1 = normSquare1;
    797797    stamp->normSquare2 = normSquare2;
    798 
    799     // psLogMsg ("psModules.imcombine", PS_LOG_DETAIL, "normValue: %f %f %f  (%f %f)\n", normI1, normI2, stamp->norm, normSquare1, normSquare2);
     798   
     799    //psLogMsg ("psModules.imcombine", PS_LOG_DETAIL, "normValue: %f %f %f  (%f %f)\n", normI1, normI2, stamp->norm, normSquare1, normSquare2);
    800800
    801801    return true;
     
    958958    }
    959959
    960     if (!psThreadPoolWait(true)) {
     960    if (!psThreadPoolWait(true, true)) {
    961961        psError(psErrorCodeLast(), false, "Error waiting for threads.");
    962962        return false;
     
    10371037                (void)psBinaryOp(sumVector, sumVector, "+", stamp->vector);
    10381038
    1039                 pmSubtractionStampPrint(ds9, stamp->x, stamp->y, stamps->footprint, "green");
     1039                pmSubtractionStampPrint(ds9, stamp->x, stamp->y, stamps->footprint, "green", "");
    10401040                numStamps++;
    10411041            } else if (stamp->status == PM_SUBTRACTION_STAMP_REJECTED) {
    1042                 pmSubtractionStampPrint(ds9, stamp->x, stamp->y, stamps->footprint, "red");
     1042                pmSubtractionStampPrint(ds9, stamp->x, stamp->y, stamps->footprint, "red", "");
    10431043            }
    10441044        }
     
    11391139                normSquare2 += stamp->normSquare2;
    11401140
    1141                 pmSubtractionStampPrint(ds9, stamp->x, stamp->y, stamps->footprint, "green");
     1141                pmSubtractionStampPrint(ds9, stamp->x, stamp->y, stamps->footprint, "green", "");
    11421142                numStamps++;
    11431143            } else if (stamp->status == PM_SUBTRACTION_STAMP_REJECTED) {
    1144                 pmSubtractionStampPrint(ds9, stamp->x, stamp->y, stamps->footprint, "red");
     1144                pmSubtractionStampPrint(ds9, stamp->x, stamp->y, stamps->footprint, "red", "");
    11451145            }
    11461146        }
     
    13821382        float Myy = fluxY2 / fluxC1;
    13831383
     1384        //MEH uncomment and update
    13841385        // fprintf (stderr, "conv1, flux2: %f, Mx: %f, My: %f, Mxx: %f, Myy: %f, chisq: %f, npix: %d\n", flux2, Mx, My, Mxx, Myy, chisq, npix);
     1386        //fprintf (stderr, "conv1, flux2: %f, fluxC1: %f, Mxx: %f, Myy: %f, chisqR: %f, npix: %d\n", flux2, fluxC1, Mxx, Myy, chisqR, npix);
     1387
    13851388        moment += Mxx + Myy;
    13861389    }
     
    15541557                    residual->kernel[y][x] = difference->kernel[y][x] - convolved1->kernel[y][x];
    15551558                    convolved1->kernel[y][x] += source->kernel[y][x] * norm;
     1559                    //MEH
     1560                    //psLogMsg("psModules.imcombine", PS_LOG_INFO, "xy: %d %d, norm: %6.3f, bg: %6.3f, difference: %6.3f, target: %6.3f, source: %6.3f, residual: %6.3f, convolved1: %6.3f \n",x,y,norm,background,difference->kernel[y][x],target->kernel[y][x],source->kernel[y][x],residual->kernel[y][x],convolved1->kernel[y][x]);
     1561
    15561562                }
    15571563            }
     
    16521658    } else {
    16531659        sumKernel2 = 1.0;
    1654     }
     1660        //MEH
     1661        sumKernel2 = 0.001;
     1662    }
     1663    //MEH if sumKernel2 not use essentially, then not need to be 2.0*? but level of orderFactor may need to be adjusted then
    16551664
    16561665    // if we modify the chisq value by the (sumKernel1 + sumKernel2), we account for the
     
    16581667    // penalized by increasing the score somewhat.  the 0.01 value is not well-chosen.
    16591668    float orderFactor = 0.01 * kernels->spatialOrder;
    1660     float score = 2.0 * chisqRValue / (sumKernel1 + sumKernel2) + orderFactor;
    1661     psLogMsg("psModules.imcombine", PS_LOG_INFO, "chisq: %6.3f, chisqD: %6.3f, moment: %6.3f, sumKernel_1: %6.3f, sumKernel_2, score: %6.3f: %6.3f\n", chisqRValue, chisqDValue, momentValue, sumKernel1, sumKernel2, score);
     1669    //MEH
     1670    //float score = 2.0 * chisqRValue / (sumKernel1 + sumKernel2) + orderFactor;
     1671    float score = 2.0 * chisqRValue / (sqrt(sumKernel1) + sqrt(sumKernel2)) + orderFactor;
     1672    psLogMsg("psModules.imcombine", PS_LOG_INFO, "chisq: %6.3f, chisqD: %6.3f, moment: %6.3f, sumKernel_1: %6.3f, sumKernel_2: %6.3f, score: %6.3f\n", chisqRValue, chisqDValue, momentValue, sumKernel1, sumKernel2, score);
    16621673
    16631674    // save this result if it is the first or the best (skip if bestMatch is NULL)
  • branches/meh_branches/ppstack_test/psModules/src/imcombine/pmSubtractionEquation.v0.c

    r30622 r33415  
    882882    }
    883883
    884     if (!psThreadPoolWait(true)) {
     884    if (!psThreadPoolWait(true, true)) {
    885885        psError(psErrorCodeLast(), false, "Error waiting for threads.");
    886886        return false;
  • branches/meh_branches/ppstack_test/psModules/src/imcombine/pmSubtractionMatch.c

    r31671 r33415  
    2929static bool useFFT = true;              // Do convolutions using FFT
    3030
    31 //#define TESTING
    32 //#define TESTING_MEMORY
     31#define TESTING
     32#define TESTING_MEMORY
    3333
    3434// Output memory usage information
     
    538538    // Where does our variance map come from?
    539539    // Getting the variance exactly right is not necessary --- it's just used for weighting.
     540    // MEH - helpful to have one used output to log -- at some level want log output for most every step
     541
    540542    psImage *variance = NULL;             // Variance image to use
    541543    if (ro1->variance && ro2->variance) {
    542544        variance = (psImage*)psBinaryOp(NULL, ro1->variance, "+", ro2->variance);
     545        psLogMsg("psModules.imcombine", PS_LOG_DETAIL, "TESTING:SubMatch variance avail: var1+var2");
    543546    } else if (ro1->variance) {
    544547        variance = psMemIncrRefCounter(ro1->variance);
     548        psLogMsg("psModules.imcombine", PS_LOG_DETAIL, "TESTING:SubMatch variance avail: var1");
    545549    } else if (ro2->variance) {
    546550        variance = psMemIncrRefCounter(ro2->variance);
     551        psLogMsg("psModules.imcombine", PS_LOG_DETAIL, "TESTING:SubMatch variance avail: var2");
    547552    } else {
    548553        variance = (psImage*)psBinaryOp(NULL, ro1->image, "+", ro2->image);
    549     }
     554        psLogMsg("psModules.imcombine", PS_LOG_DETAIL, "TESTING:SubMatch variance avail: none ro1+ro2");
     555    }
     556
    550557
    551558    // Putting important variable declarations here, since they are freed after a "goto" if there is an error.
     
    726733                float radMoment1 = stamps->normWindow1 / 2.75;
    727734                float radMoment2 = stamps->normWindow2 / 2.75;
     735                //MEH - FWHM vs radialMoment need *2? may mess up other parts
     736                //float radMoment1 = stamps->normWindow1 / 2.75*2;
     737                //float radMoment2 = stamps->normWindow2 / 2.75*2;
    728738                pmSubtractionParamsScale(NULL, NULL, isisWidths, radMoment1, radMoment2);
    729739
     
    810820                    }
    811821                }
    812 
     822                //MEH probably should comment out but should be ok?
    813823                // step 0 : calculate the normalizations, pass along to the next steps via stamps->normValue
    814824                psTrace("psModules.imcombine", 3, "Calculating normalization...\n");
     
    825835                for (int order = 0; order <= N_TEST_ORDER; order++) {
    826836                    for (int j = 0; j < N_TEST_MODES; j++) {
     837                        //MEH: thinking pmSubtractionCalculateNormalization needs to be called here for conv source
     838                        // per mode
     839                        //psTrace("psModules.imcombine", 3, "Calculating normalization...order: %d  mode: %d\n",order,j);
     840                        //                        if (!pmSubtractionCalculateNormalization(stamps, TestModes[j])) {
     841                        //    psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation.");
     842                        //    goto MATCH_ERROR;
     843                        //}
     844                        //
    827845                        if (!pmSubtractionMatchAttempt(&bestMatch, kernels, stamps, TestModes[j], order, false)) {
    828846                            goto MATCH_ERROR;
     
    843861            // apply the best fit so we are ready to roll
    844862            psLogMsg("psModules.imcombine", PS_LOG_INFO, "applying order: %d, mode: %d\n", bestMatch->spatialOrder, bestMatch->mode);
     863            //MEH need to call normalization one more time for final/best run -
     864            // but what if dual - already checked for in pmSubtractionCalculateNormalization
     865            //if (!pmSubtractionCalculateNormalization(stamps, bestMatch->mode)) {
     866            //    psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation.");
     867            //    goto MATCH_ERROR;
     868            //}
     869            //
    845870            if (!pmSubtractionMatchAttempt(NULL, kernels, stamps, bestMatch->mode, bestMatch->spatialOrder, true)) {
    846871                goto MATCH_ERROR;
     
    10911116    }
    10921117
    1093     if (!psThreadPoolWait(true)) {
     1118    if (!psThreadPoolWait(true, true)) {
    10941119        psError(psErrorCodeLast(), false, "Error waiting for threads.");
    10951120        psFree(models);
     
    13311356        *stampSize = *stampSize * scale + 0.5;
    13321357    }
    1333 
     1358    //MEH
     1359    psLogMsg("psModules.imcombine", PS_LOG_INFO, "TESTING Scaling kernel parameters fwhm1,2,refscale/min/max: %f %f %f %f %f", fwhm1,fwhm2,scaleRefOption,scaleMinOption,scaleMaxOption);
    13341360    psLogMsg("psModules.imcombine", PS_LOG_INFO, "Scaling kernel parameters by %f", scale);
    13351361    if (kernelSize) psLogMsg("psModules.imcombine", PS_LOG_INFO, " modified kernel size %d", *kernelSize);
  • branches/meh_branches/ppstack_test/psModules/src/imcombine/pmSubtractionStamps.c

    r31543 r33415  
    127127                continue;
    128128            }
     129            //MEH hack to limit bright end test
     130//            if ((image1 && image1->data.F32[y][x] > 2000) ||
     131//                (image2 && image2->data.F32[y][x] > 2000 )) {
     132//              fprintf (stderr, "%f,%f : thresh\n",image1->data.F32[y][x],image2->data.F32[y][x]);
     133//                continue;
     134//            }
    129135
    130136            if (subMask && subMask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] &
     
    188194}
    189195
    190 void pmSubtractionStampPrint(FILE *ds9, float x, float y, float size, const char *color)
     196// MEH adding text to ds9
     197void pmSubtractionStampPrint(FILE *ds9, float x, float y, float size, const char *color, const char *ds9text)
    191198{
    192199    if (!ds9regions || !ds9) {
     
    196203    if (color && strlen(color) > 0) {
    197204        fprintf(ds9, " # color=%s", color);
     205    }
     206    if (ds9text && strlen(ds9text) > 0) {
     207        fprintf(ds9, " text={%s}", ds9text);
    198208    }
    199209    fprintf(ds9, "\n");
     
    486496                                             normFrac, sysErr, skyErr);
    487497    }
    488 
     498    //MEH - stamps.dat will repeatedly be overwritten - out to trace may be btter -- see end for summary
    489499    // XXX TEST : dump all stars in the stamps here
    490     if (0) {
     500    if (1) {
    491501        FILE *f = fopen ("stamp.dat", "w");
    492502        for (int i = 0; i < stamps->num; i++) {
     
    589599                stamp->status = PM_SUBTRACTION_STAMP_FOUND;
    590600                numFound++;
    591                 psTrace("psModules.imcombine", 5, "Found stamp in subregion %d: %d,%d\n",
    592                         i, (int)stamp->x, (int)stamp->y);
     601//                psTrace("psModules.imcombine", 5, "Found stamp in subregion %d: %d,%d\n",
     602//                        i, (int)stamp->x, (int)stamp->y);
     603                //MEH adding int flux to say something about the source
     604                psTrace("psModules.imcombine", 5, "Found stamp in subregion %d: %d,%d  Flux: %d\n",
     605                        i, (int)stamp->x, (int)stamp->y, (int)stamp->flux);
    593606            } else {
    594607                stamp->status = PM_SUBTRACTION_STAMP_NONE;
     
    666679            psTrace("psModules.imcombine", 9, "Rejecting input stamp (%d,%d) because outside region",
    667680                    xPix, yPix);
    668             pmSubtractionStampPrint(ds9, xPix, yPix, footprint, "red");
     681            pmSubtractionStampPrint(ds9, xPix, yPix, footprint, "red", "");
    669682            continue;
    670683        }
    671 
     684        //MEH - are all using -0.5? seen some seem shifted
    672685        // fprintf (stderr, "stamp: %5.1f %5.1f == %d %d\n", xStamp, yStamp, xPix, yPix);
    673686
     
    692705                psTrace("psModules.imcombine", 9, "Putting input stamp (%d,%d) into subregion %d",
    693706                        xPix, yPix, j);
    694                 pmSubtractionStampPrint(ds9, xPix, yPix, footprint, "green");
     707                pmSubtractionStampPrint(ds9, xPix, yPix, footprint, "green", "");
    695708            }
    696709        }
     
    699712            psTrace("psModules.imcombine", 9, "Unable to find subregion for stamp (%d,%d)",
    700713                    xPix, yPix);
    701             pmSubtractionStampPrint(ds9, xPix, yPix, footprint, "yellow");
     714            pmSubtractionStampPrint(ds9, xPix, yPix, footprint, "yellow", "");
    702715        }
    703716    }
     
    865878        }
    866879    }
    867 
    868 #if 0
     880//MEH
     881#if 1
    869882    {
    870883        psFits *fits = NULL;
     
    11561169                float sysErr = 0.25 * PS_SQR(stamps->sysErr); // Systematic error
    11571170                float skyErr = stamps->skyErr;
     1171                //MEH - image2 not used if not adding to additional.. also these are never freed here, but upstream/downstream?
    11581172                psKernel *image1 = stamp->image1, *image2 = stamp->image2; // Input images
     1173                //psKernel *image2 = stamp->image2; // Input images
    11591174                for (int y = -size; y <= size; y++) {
    11601175                    for (int x = -size; x <= size; x++) {
     1176                        //MEH -- if conv to model then what does sys and weight mean for both?
     1177                        // w1+w2 vs 1/var1+1/var2.. depends on what the weight is for?
     1178                        // why additional ^2?
    11611179                        float additional = image1->kernel[y][x] + image2->kernel[y][x];
    1162                         weight->kernel[y][x] = 1.0 / (skyErr + var->kernel[y][x] + sysErr * PS_SQR(additional));
     1180                        //float additional = image2->kernel[y][x];
     1181//                        weight->kernel[y][x] = 1.0 / (skyErr + var->kernel[y][x] + sysErr * PS_SQR(additional));
     1182                        weight->kernel[y][x] = 1.0 / (skyErr + 1000.0*var->kernel[y][x] + sysErr * PS_SQR(additional));
    11631183                    }
    11641184                }
     1185                psLogMsg("psModules.imcombine", PS_LOG_DETAIL, "TESTING:: Stamp %d (%.1f,%.1f) weight: %f var: %.1f sysErr: %.2f im1: %.0f im2: %.0f \n",
     1186                         i, stamp->x, stamp->y, weight->kernel[0][0],var->kernel[0][0],sysErr,image2->kernel[0][0],image1->kernel[0][0]);
     1187
    11651188            } else {
    11661189                for (int y = -size; y <= size; y++) {
    11671190                    for (int x = -size; x <= size; x++) {
    1168                         weight->kernel[y][x] = 1.0 / var->kernel[y][x];
     1191//                        weight->kernel[y][x] = 1.0 / var->kernel[y][x];
     1192                        weight->kernel[y][x] = 1.0 / (1000.0*var->kernel[y][x]);
    11691193                    }
    11701194                }
  • branches/meh_branches/ppstack_test/psModules/src/imcombine/pmSubtractionStamps.h

    r30622 r33415  
    163163                             float x, float y, ///< Position of stamp
    164164                             float size,///< Size of circle
    165                              const char *color ///< Colour
     165                             const char *color, ///< Colour
     166                             const char *ds9text ///< info text
    166167    );
    167 
     168// MEH added text to ds9 file
    168169
    169170bool pmSubtractionStampsResetStatus (pmSubtractionStampList *stamps);
  • branches/meh_branches/ppstack_test/psModules/src/objects

    • Property svn:ignore
      •  

        old new  
        55*.la
        66*.lo
         7pmSourceIO_CMF_PS1_V1.c
         8pmSourceIO_CMF_PS1_V2.c
         9pmSourceIO_CMF_PS1_V3.c
         10pmSourceIO_CMF_PS1_V4.c
         11pmSourceIO_CMF_PS1_V3.v1.c
         12pmSourceIO_CMF_PS1_V1.v1.c
         13pmSourceIO_CMF_PS1_V2.v1.c
         14
  • branches/meh_branches/ppstack_test/psModules/src/objects/Makefile.am

    r31670 r33415  
    4545        pmSourceIO_CMF_PS1_V2.c \
    4646        pmSourceIO_CMF_PS1_V3.c \
     47        pmSourceIO_CMF_PS1_V4.c \
    4748        pmSourceIO_CMF_PS1_SV1.c \
    4849        pmSourceIO_CMF_PS1_DV1.c \
     
    130131
    131132# pmSourceID_CMF_* functions use a common framework
    132 BUILT_SOURCES = pmSourceIO_CMF_PS1_V1.v1.c pmSourceIO_CMF_PS1_V2.v1.c pmSourceIO_CMF_PS1_V3.v1.c
     133BUILT_SOURCES = pmSourceIO_CMF_PS1_V1.c pmSourceIO_CMF_PS1_V2.c pmSourceIO_CMF_PS1_V3.c pmSourceIO_CMF_PS1_V4.c
    133134
    134 pmSourceIO_CMF_PS1_V1.v1.c : pmSourceIO_CMF.c.in mksource.pl
    135         mksource.pl pmSourceIO_CMF.c.in PS1_V1 pmSourceIO_CMF_PS1_V1.v1.c
     135pmSourceIO_CMF_PS1_V1.c : pmSourceIO_CMF.c.in mksource.pl
     136        mksource.pl pmSourceIO_CMF.c.in PS1_V1 pmSourceIO_CMF_PS1_V1.c
    136137
    137 pmSourceIO_CMF_PS1_V2.v1.c : pmSourceIO_CMF.c.in mksource.pl
    138         mksource.pl pmSourceIO_CMF.c.in PS1_V2 pmSourceIO_CMF_PS1_V2.v1.c
     138pmSourceIO_CMF_PS1_V2.c : pmSourceIO_CMF.c.in mksource.pl
     139        mksource.pl pmSourceIO_CMF.c.in PS1_V2 pmSourceIO_CMF_PS1_V2.c
    139140
    140 pmSourceIO_CMF_PS1_V3.v1.c : pmSourceIO_CMF.c.in mksource.pl
    141         mksource.pl pmSourceIO_CMF.c.in PS1_V2 pmSourceIO_CMF_PS1_V3.v1.c
     141pmSourceIO_CMF_PS1_V3.c : pmSourceIO_CMF.c.in mksource.pl
     142        mksource.pl pmSourceIO_CMF.c.in PS1_V3 pmSourceIO_CMF_PS1_V3.c
     143
     144pmSourceIO_CMF_PS1_V4.c : pmSourceIO_CMF.c.in mksource.pl
     145        mksource.pl pmSourceIO_CMF.c.in PS1_V4 pmSourceIO_CMF_PS1_V4.c
    142146
    143147# EXTRA_DIST = pmErrorCodes.h.in pmErrorCodes.dat pmErrorCodes.c.in
  • branches/meh_branches/ppstack_test/psModules/src/objects/mksource.pl

    r31670 r33415  
    1414
    1515# see if we can add in PS1_DV* and PS1_SV* as well...
    16 @cmfmodes = ("PS1_V1", 1,
     16%cmfmodes = ("PS1_V1", 1,
    1717             "PS1_V2", 2,
    18              "PS1_V3", 3);
     18             "PS1_V3", 3,
     19             "PS1_V4", 4);
     20
     21print "1: $cmfmodes{1}\n";
     22print "PS1_V1: $cmfmodes{'PS1_V1'}\n";
    1923
    2024open (FILE, "$template") || die "failed to open template $template\n";
     
    5054
    5155    if ($gtMode) {
     56        # print "gtMode : $line\n";
    5257        $thisLevel = $cmfmodes{$gtMode};
    5358        $myLevel = $cmfmodes{$cmfmode};
    54         if ($thisLevel <= $myLevel) { next; }
    55         $line =~ s|\@<\S*\@\s*||;
     59        print "gtMode : $gtMode vs $cmfmode, $thisLevel, $myLevel\n";
     60        if ($myLevel <= $thisLevel) { next; }
     61        $line =~ s|\@>\S*\@\s*||;
    5662    }
    5763
    5864    if ($ltMode) {
     65        # print "ltMode : $line\n";
    5966        $thisLevel = $cmfmodes{$ltMode};
    6067        $myLevel = $cmfmodes{$cmfmode};
    61         if ($thisLevel >= $myLevel) { next; }
    62         $line =~ s|\@>\S*\@\s*||;
     68        print "ltMode : $ltMode vs $cmfmode, $thisLevel, $myLevel\n";
     69        if ($myLevel >= $thisLevel) { next; }
     70        $line =~ s|\@<\S*\@\s*||;
    6371    }
    6472
  • branches/meh_branches/ppstack_test/psModules/src/objects/models/pmModel_DEV.c

    r31451 r33415  
    8989static bool limitsApply = true;         // Apply limits?
    9090
     91# include "pmModel_SERSIC.CP.h"
     92
    9193psF32 PM_MODEL_FUNC (psVector *deriv,
    9294                     const psVector *params,
     
    9496{
    9597    psF32 *PAR = params->data.F32;
    96 
    97     float index = 0.5 / ALPHA;
    98     float bn = 1.9992*index - 0.3271;
    99     float Io = exp(bn);
    10098
    10199    psF32 X  = pixcoord->data.F32[0] - PAR[PM_PAR_XPOS];
     
    105103    psF32 z  = (PS_SQR(px) + PS_SQR(py) + PAR[PM_PAR_SXY]*X*Y);
    106104
    107     assert (z >= 0);
     105    // If the elliptical contour is defined in a valid way, we should never trigger this
     106    // assert.  Other models (like PGAUSS) don't use fractional powers, and thus do not have
     107    // NaN values for negative values of z
     108    psAssert (z >= 0, "do not allow negative z values in model");
     109
     110    float index = 0.5 / ALPHA;
     111    float par7 = ALPHA;
     112    float bn = 1.9992*index - 0.3271;
     113    float Io = exp(bn);
    108114
    109115    psF32 f2 = bn*pow(z,ALPHA);
    110116    psF32 f1 = Io*exp(-f2);
     117
     118    psF32 radius = hypot(X, Y);
     119    if (radius < 1.0) {
     120
     121        // ** use bilinear interpolation to the given location from the 4 surrounding pixels centered on the object center
     122
     123        // first, use Rmajor and index to find the central pixel flux (fraction of total flux)
     124        psEllipseShape shape;
     125
     126        shape.sx  = PAR[PM_PAR_SXX];
     127        shape.sy  = PAR[PM_PAR_SYY];
     128        shape.sxy = PAR[PM_PAR_SXY];
     129
     130        // for a non-circular Sersic, the flux of the Rmajor equivalent is scaled by the AspectRatio
     131        psEllipseAxes axes = psEllipseShapeToAxes (shape, 20.0);
     132
     133        // get the central pixel flux from the lookup table
     134        float xPix = (axes.major - centralPixelXo) / centralPixeldX;
     135        xPix = PS_MIN (PS_MAX(xPix, 0), centralPixelNX - 1);
     136        float yPix = (index - centralPixelYo) / centralPixeldY;
     137        yPix = PS_MIN (PS_MAX(yPix, 0), centralPixelNY - 1);
     138
     139        // the integral of a Sersic has an analytical form as follows:
     140        float logGamma = lgamma(2.0*index);
     141        float bnFactor = pow(bn, 2.0*index);
     142        float norm = 2.0 * M_PI * PS_SQR(axes.major) * index * exp(bn) * exp(logGamma) / bnFactor;
     143
     144        // XXX interpolate to get the value
     145        // XXX for the moment, just integerize
     146        // XXX I need to multiply by the integrated flux to get the flux in the central pixel
     147        float Vcenter = centralPixel[(int)yPix][(int)xPix] * norm;
     148       
     149        float px1 = 1.0 / PAR[PM_PAR_SXX];
     150        float py1 = 1.0 / PAR[PM_PAR_SYY];
     151        float z10 = PS_SQR(px1);
     152        float z01 = PS_SQR(py1);
     153
     154        // which pixels do we need for this interpolation?
     155        // (I do not keep state information, so I don't know anything about other evaluations of nearby pixels...)
     156        if ((X >= 0) && (Y >= 0)) {
     157            float z11 = z10 + z01 + PAR[PM_PAR_SXY]; // X * Y positive
     158            float V00 = Vcenter;
     159            float V10 = Io*exp(-bn*pow(z10,par7));
     160            float V01 = Io*exp(-bn*pow(z01,par7));
     161            float V11 = Io*exp(-bn*pow(z11,par7));
     162            f1 = interpolatePixels(V00, V10, V01, V11, X, Y);
     163        }
     164        if ((X < 0) && (Y >= 0)) {
     165            float z11 = z10 + z01 - PAR[PM_PAR_SXY]; // X * Y negative
     166            float V00 = Io*exp(-bn*pow(z10,par7));
     167            float V10 = Vcenter;
     168            float V01 = Io*exp(-bn*pow(z11,par7));
     169            float V11 = Io*exp(-bn*pow(z01,par7));
     170            f1 = interpolatePixels(V00, V10, V01, V11, (1.0 + X), Y);
     171        }
     172        if ((X >= 0) && (Y < 0)) {
     173            float z11 = z10 + z01 - PAR[PM_PAR_SXY]; // X * Y negative
     174            float V00 = Io*exp(-bn*pow(z01,par7));
     175            float V10 = Io*exp(-bn*pow(z11,par7));
     176            float V01 = Vcenter;
     177            float V11 = Io*exp(-bn*pow(z10,par7));
     178            f1 = interpolatePixels(V00, V10, V01, V11, X, (1.0 + Y));
     179        }
     180        if ((X < 0) && (Y < 0)) {
     181            float z11 = z10 + z01 + PAR[PM_PAR_SXY]; // X * Y positive
     182            float V00 = Io*exp(-bn*pow(z11,par7));
     183            float V10 = Io*exp(-bn*pow(z10,par7));
     184            float V01 = Io*exp(-bn*pow(z01,par7));
     185            float V11 = Vcenter;
     186            f1 = interpolatePixels(V00, V10, V01, V11, (1.0 + X), (1.0 + Y));
     187        }
     188    }   
     189
    111190    psF32 z0 = PAR[PM_PAR_I0]*f1;
    112191    psF32 f0 = PAR[PM_PAR_SKY] + z0;
     
    120199        psF32 *dPAR = deriv->data.F32;
    121200
     201        dPAR[PM_PAR_SKY]  = +1.0;
     202        dPAR[PM_PAR_I0]   = +2.0*f1; // XXX extra damping..
     203
    122204        // gradient is infinite for z = 0; saturate at z = 0.01
    123205        psF32 z1 = (z < 0.01) ? z0*bn*ALPHA*pow(0.01,ALPHA - 1.0) : z0*bn*ALPHA*pow(z,ALPHA - 1.0);
    124 
    125         dPAR[PM_PAR_SKY]  = +1.0;
    126         dPAR[PM_PAR_I0]   = +2.0*f1;
    127206
    128207        assert (isfinite(z1));
     
    223302
    224303    // set the shape parameters
     304    // XXX adjust this?
    225305    if (!pmModelSetShape(&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], source->moments)) {
    226306      return false;
     
    246326}
    247327
     328// A DeVaucouleur model is equivalent to a Sersic with index = 4.0
    248329psF64 PM_MODEL_FLUX (const psVector *params)
    249330{
    250     float z, norm;
    251331    psEllipseShape shape;
    252332
    253333    psF32 *PAR = params->data.F32;
    254334
    255     shape.sx  = PAR[PM_PAR_SXX] / M_SQRT2;
    256     shape.sy  = PAR[PM_PAR_SYY] / M_SQRT2;
     335    shape.sx  = PAR[PM_PAR_SXX];
     336    shape.sy  = PAR[PM_PAR_SYY];
    257337    shape.sxy = PAR[PM_PAR_SXY];
    258338
    259     // Area is equivalent to 2 pi sigma^2
     339    // for a non-circular DeVaucouleur, the flux of the Rmajor equivalent is scaled by the AspectRatio
    260340    psEllipseAxes axes = psEllipseShapeToAxes (shape, 20.0);
    261     psF64 Area = 2.0 * M_PI * axes.major * axes.minor;
    262 
    263     // the area needs to be multiplied by the integral of f(z)
    264     norm = 0.0;
    265 
    266     # define DZ 0.25
    267 
    268     float f0 = 1.0;
    269     float f1, f2;
    270     for (z = DZ; z < 150; z += DZ) {
    271         f1 = exp(-pow(z,ALPHA));
    272         z += DZ;
    273         f2 = exp(-pow(z,ALPHA));
    274         norm += f0 + 4*f1 + f2;
    275         f0 = f2;
    276     }
    277     norm *= DZ / 3.0;
    278 
    279     psF64 Flux = PAR[PM_PAR_I0] * Area * norm;
     341    float AspectRatio = axes.minor / axes.major;
     342
     343    float index = 4.0;
     344    float bn = 1.9992*index - 0.3271;
     345
     346    // the integral of a Sersic has an analytical form as follows:
     347    float logGamma = lgamma(2.0*index);
     348    float bnFactor = pow(bn, 2.0*index);
     349    float norm = 2.0 * M_PI * PS_SQR(axes.major) * index * exp(bn) * exp(logGamma) / bnFactor;
     350   
     351    psF64 Flux = PAR[PM_PAR_I0] * norm * AspectRatio;
    280352
    281353    return(Flux);
     
    297369        return (1.0);
    298370
    299     shape.sx  = PAR[PM_PAR_SXX] / M_SQRT2;
    300     shape.sy  = PAR[PM_PAR_SYY] / M_SQRT2;
     371    shape.sx  = PAR[PM_PAR_SXX];
     372    shape.sy  = PAR[PM_PAR_SYY];
    301373    shape.sxy = PAR[PM_PAR_SXY];
    302374
  • branches/meh_branches/ppstack_test/psModules/src/objects/models/pmModel_EXP.c

    r31451 r33415  
    8181static bool limitsApply = true;         // Apply limits?
    8282
     83# include "pmModel_SERSIC.CP.h"
     84
    8385psF32 PM_MODEL_FUNC (psVector *deriv,
    8486                     const psVector *params,
     
    9395    psF32 z  = PS_SQR(px) + PS_SQR(py) + PAR[PM_PAR_SXY]*X*Y;
    9496
    95     // XXX if the elliptical contour is defined in valid way, this step should not be required.
    96     // other models (like PGAUSS) don't use fractional powers, and thus do not have NaN values
    97     // for negative values of z
    98     // XXX use an assert here to force the elliptical parameters to be correctly determined
    99     // if (z < 0) z = 0;
    100     assert (z >= 0);
    101 
    102     psF32 f2 = sqrt(z);
    103     psF32 f1 = exp(-f2);
     97    // If the elliptical contour is defined in a valid way, we should never trigger this
     98    // assert.  Other models (like PGAUSS) don't use fractional powers, and thus do not have
     99    // NaN values for negative values of z
     100    psAssert (z >= 0, "do not allow negative z values in model");
     101
     102    float index = 1.0;
     103    float par7 = 0.5;
     104    float bn = 1.9992*index - 0.3271;
     105    float Io = exp(bn);
     106
     107    psF32 f2 = bn*sqrt(z);
     108    psF32 f1 = Io*exp(-f2);
     109
     110    psF32 radius = hypot(X, Y);
     111    if (radius < 1.0) {
     112
     113        // ** use bilinear interpolation to the given location from the 4 surrounding pixels centered on the object center
     114
     115        // first, use Rmajor and index to find the central pixel flux (fraction of total flux)
     116        psEllipseShape shape;
     117
     118        shape.sx  = PAR[PM_PAR_SXX];
     119        shape.sy  = PAR[PM_PAR_SYY];
     120        shape.sxy = PAR[PM_PAR_SXY];
     121
     122        // for a non-circular Sersic, the flux of the Rmajor equivalent is scaled by the AspectRatio
     123        psEllipseAxes axes = psEllipseShapeToAxes (shape, 20.0);
     124
     125        // get the central pixel flux from the lookup table
     126        float xPix = (axes.major - centralPixelXo) / centralPixeldX;
     127        xPix = PS_MIN (PS_MAX(xPix, 0), centralPixelNX - 1);
     128        float yPix = (index - centralPixelYo) / centralPixeldY;
     129        yPix = PS_MIN (PS_MAX(yPix, 0), centralPixelNY - 1);
     130
     131        // the integral of a Sersic has an analytical form as follows:
     132        float logGamma = lgamma(2.0*index);
     133        float bnFactor = pow(bn, 2.0*index);
     134        float norm = 2.0 * M_PI * PS_SQR(axes.major) * index * exp(bn) * exp(logGamma) / bnFactor;
     135
     136        // XXX interpolate to get the value
     137        // XXX for the moment, just integerize
     138        // XXX I need to multiply by the integrated flux to get the flux in the central pixel
     139        float Vcenter = centralPixel[(int)yPix][(int)xPix] * norm;
     140       
     141        float px1 = 1.0 / PAR[PM_PAR_SXX];
     142        float py1 = 1.0 / PAR[PM_PAR_SYY];
     143        float z10 = PS_SQR(px1);
     144        float z01 = PS_SQR(py1);
     145
     146        // which pixels do we need for this interpolation?
     147        // (I do not keep state information, so I don't know anything about other evaluations of nearby pixels...)
     148        if ((X >= 0) && (Y >= 0)) {
     149            float z11 = z10 + z01 + PAR[PM_PAR_SXY]; // X * Y positive
     150            float V00 = Vcenter;
     151            float V10 = Io*exp(-bn*pow(z10,par7));
     152            float V01 = Io*exp(-bn*pow(z01,par7));
     153            float V11 = Io*exp(-bn*pow(z11,par7));
     154            f1 = interpolatePixels(V00, V10, V01, V11, X, Y);
     155        }
     156        if ((X < 0) && (Y >= 0)) {
     157            float z11 = z10 + z01 - PAR[PM_PAR_SXY]; // X * Y negative
     158            float V00 = Io*exp(-bn*pow(z10,par7));
     159            float V10 = Vcenter;
     160            float V01 = Io*exp(-bn*pow(z11,par7));
     161            float V11 = Io*exp(-bn*pow(z01,par7));
     162            f1 = interpolatePixels(V00, V10, V01, V11, (1.0 + X), Y);
     163        }
     164        if ((X >= 0) && (Y < 0)) {
     165            float z11 = z10 + z01 - PAR[PM_PAR_SXY]; // X * Y negative
     166            float V00 = Io*exp(-bn*pow(z01,par7));
     167            float V10 = Io*exp(-bn*pow(z11,par7));
     168            float V01 = Vcenter;
     169            float V11 = Io*exp(-bn*pow(z10,par7));
     170            f1 = interpolatePixels(V00, V10, V01, V11, X, (1.0 + Y));
     171        }
     172        if ((X < 0) && (Y < 0)) {
     173            float z11 = z10 + z01 + PAR[PM_PAR_SXY]; // X * Y positive
     174            float V00 = Io*exp(-bn*pow(z11,par7));
     175            float V10 = Io*exp(-bn*pow(z10,par7));
     176            float V01 = Io*exp(-bn*pow(z01,par7));
     177            float V11 = Vcenter;
     178            f1 = interpolatePixels(V00, V10, V01, V11, (1.0 + X), (1.0 + Y));
     179        }
     180    }   
     181
    104182    psF32 z0 = PAR[PM_PAR_I0]*f1;
    105183    psF32 f0 = PAR[PM_PAR_SKY] + z0;
     
    118196        // gradient is infinite for z = 0; saturate at z = 0.01
    119197        // z1 is -df/dz (the negative sign is canceled by most of dz/dPAR[i]
    120         psF32 z1 = (z < 0.01) ? 0.5*z0/sqrt(0.01) : 0.5*z0/sqrt(z);
     198        psF32 z1 = (z < 0.01) ? 0.5*bn*z0/sqrt(0.01) : 0.5*bn*z0/sqrt(z);
    121199
    122200        // XXX dampen SXX and SYY as in GAUSS?
     
    216294
    217295    // set the shape parameters
     296    // XXX adjust this?
    218297    if (!pmModelSetShape(&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], source->moments)) {
    219298      return false;
     
    233312}
    234313
     314// An exponential model is equivalent to a Sersic with index = 1.0
    235315psF64 PM_MODEL_FLUX (const psVector *params)
    236316{
    237     float z, norm;
    238317    psEllipseShape shape;
    239318
    240319    psF32 *PAR = params->data.F32;
    241320
    242     shape.sx  = PAR[PM_PAR_SXX] / M_SQRT2;
    243     shape.sy  = PAR[PM_PAR_SYY] / M_SQRT2;
     321    shape.sx  = PAR[PM_PAR_SXX];
     322    shape.sy  = PAR[PM_PAR_SYY];
    244323    shape.sxy = PAR[PM_PAR_SXY];
    245324
    246     // Area is equivalent to 2 pi sigma^2
     325    // for a non-circular Exponential, the flux of the Rmajor equivalent is scaled by the AspectRatio
    247326    psEllipseAxes axes = psEllipseShapeToAxes (shape, 20.0);
    248     psF64 Area = 2.0 * M_PI * axes.major * axes.minor;
    249 
    250     // the area needs to be multiplied by the integral of f(z) = exp(-sqrt(z)) [0 to infinity]
    251     norm = 0.0;
    252 
    253     # define DZ 0.25
    254 
    255     float f0 = 1.0;
    256     float f1, f2;
    257     for (z = DZ; z < 150; z += DZ) {
    258         f1 = exp(-sqrt(z));
    259         z += DZ;
    260         f2 = exp(-sqrt(z));
    261         norm += f0 + 4*f1 + f2;
    262         f0 = f2;
    263     }
    264     norm *= DZ / 3.0;
    265 
    266     psF64 Flux = PAR[PM_PAR_I0] * Area * norm;
     327    float AspectRatio = axes.minor / axes.major;
     328
     329    float index = 1.0;
     330    float bn = 1.9992*index - 0.3271;
     331
     332    // the integral of a Sersic has an analytical form as follows:
     333    float logGamma = lgamma(2.0*index);
     334    float bnFactor = pow(bn, 2.0*index);
     335    float norm = 2.0 * M_PI * PS_SQR(axes.major) * index * exp(bn) * exp(logGamma) / bnFactor;
     336   
     337    psF64 Flux = PAR[PM_PAR_I0] * norm * AspectRatio;
    267338
    268339    return(Flux);
     
    284355        return (1.0);
    285356
    286     shape.sx  = PAR[PM_PAR_SXX] / M_SQRT2;
    287     shape.sy  = PAR[PM_PAR_SYY] / M_SQRT2;
     357    shape.sx  = PAR[PM_PAR_SXX];
     358    shape.sy  = PAR[PM_PAR_SYY];
    288359    shape.sxy = PAR[PM_PAR_SXY];
    289360
  • branches/meh_branches/ppstack_test/psModules/src/objects/models/pmModel_PGAUSS.c

    r31451 r33415  
    217217}
    218218
    219 psF64 PM_MODEL_FLUX(const psVector *params)
    220 {
    221     float norm, z;
     219// integrate the model to get the full flux
     220psF64 PM_MODEL_FLUX (const psVector *params)
     221{
     222    float z, norm;
    222223    psEllipseShape shape;
    223224
     
    228229    shape.sxy = PAR[PM_PAR_SXY];
    229230
    230     // Area is equivalent to 2 pi sigma^2
    231231    psEllipseAxes axes = psEllipseShapeToAxes (shape, 20.0);
    232     psF64 Area = 2.0 * M_PI * axes.major * axes.minor;
    233 
    234     // the area needs to be multiplied by the integral of f(z)
     232    float AspectRatio = axes.minor / axes.major;
     233
     234    // flux = 2 \pi \int f(r) r dr
    235235    norm = 0.0;
    236236
    237     # define DZ 0.25
    238 
    239     float f0 = 1.0;
     237    # define DR 0.25
     238
     239    // f = f(r) * r
     240    float f0 = 0.0;
    240241    float f1, f2;
    241     for (z = DZ; z < 150; z += DZ) {
    242         f1 = 1.0 / (1 + z + z*z/2.0 + z*z*z/6.0);
    243         z += DZ;
    244         f2 = 1.0 / (1 + z + z*z/2.0 + z*z*z/6.0);
     242    for (float r = DR; r < 150; r += DR) {
     243        z = 0.5 * PS_SQR(r / axes.major);
     244        f1 = r / (1 + z + z*z/2.0 + z*z*z/6.0);
     245        r += DR;
     246        z = 0.5 * PS_SQR(r / axes.major);
     247        f2 = r / (1 + z + z*z/2.0 + z*z*z/6.0);
    245248        norm += f0 + 4*f1 + f2;
    246249        f0 = f2;
    247250    }
    248     norm *= DZ / 3.0;
    249 
    250     psF64 Flux = PAR[PM_PAR_I0] * Area * norm;
     251    norm *= DR / 3.0;
     252
     253    psF64 Flux = PAR[PM_PAR_I0] * norm * 2.0 * M_PI * AspectRatio;
    251254
    252255    return(Flux);
  • branches/meh_branches/ppstack_test/psModules/src/objects/models/pmModel_PS1_V1.c

    r31670 r33415  
    1414   * PM_PAR_XPOS 2  - X center of object
    1515   * PM_PAR_YPOS 3  - Y center of object
    16    * PM_PAR_SXX 4   - X^2 term of elliptical contour (sqrt(2) / SigmaX)
    17    * PM_PAR_SYY 5   - Y^2 term of elliptical contour (sqrt(2) / SigmaY)
     16   * PM_PAR_SXX 4   - X^2 term of elliptical contour (SigmaX / sqrt(2))
     17   * PM_PAR_SYY 5   - Y^2 term of elliptical contour (SigmaY / sqrt(2))
    1818   * PM_PAR_SXY 6   - X*Y term of elliptical contour
    1919   * PM_PAR_7   7   - amplitude of the linear component (k)
     
    239239}
    240240
     241// integrate the model to get the full flux
    241242psF64 PM_MODEL_FLUX (const psVector *params)
    242243{
     
    250251    shape.sxy = PAR[PM_PAR_SXY];
    251252
    252     // Area is equivalent to 2 pi sigma^2
    253253    psEllipseAxes axes = psEllipseShapeToAxes (shape, 20.0);
    254     psF64 Area = 2.0 * M_PI * axes.major * axes.minor;
    255 
    256     // the area needs to be multiplied by the integral of f(z)
     254    float AspectRatio = axes.minor / axes.major;
     255
     256    // flux = 2 \pi \int f(r) r dr
    257257    norm = 0.0;
    258258
    259     # define DZ 0.25
    260 
    261     float f0 = 1.0;
     259    # define DR 0.25
     260
     261    // f = f(r) * r
     262    float f0 = 0.0;
    262263    float f1, f2;
    263     for (z = DZ; z < 150; z += DZ) {
    264         f1 = 1.0 / (1 + PAR[PM_PAR_7]*z + pow(z, ALPHA));
    265         z += DZ;
    266         f2 = 1.0 / (1 + PAR[PM_PAR_7]*z + pow(z, ALPHA));
     264    for (float r = DR; r < 150; r += DR) {
     265        z = 0.5 * PS_SQR(r / axes.major);
     266        f1 = r / (1 + PAR[PM_PAR_7]*z + pow(z, ALPHA));
     267        r += DR;
     268        z = 0.5 * PS_SQR(r / axes.major);
     269        f2 = r / (1 + PAR[PM_PAR_7]*z + pow(z, ALPHA));
    267270        norm += f0 + 4*f1 + f2;
    268271        f0 = f2;
    269272    }
    270     norm *= DZ / 3.0;
    271 
    272     psF64 Flux = PAR[PM_PAR_I0] * Area * norm;
     273    norm *= DR / 3.0;
     274
     275    psF64 Flux = PAR[PM_PAR_I0] * norm * 2.0 * M_PI * AspectRatio;
    273276
    274277    return(Flux);
  • branches/meh_branches/ppstack_test/psModules/src/objects/models/pmModel_QGAUSS.c

    r31670 r33415  
    240240}
    241241
     242// integrate the model to get the full flux
    242243psF64 PM_MODEL_FLUX (const psVector *params)
    243244{
     
    251252    shape.sxy = PAR[PM_PAR_SXY];
    252253
    253     // Area is equivalent to 2 pi sigma^2
    254254    psEllipseAxes axes = psEllipseShapeToAxes (shape, 20.0);
    255     psF64 Area = 2.0 * M_PI * axes.major * axes.minor;
    256 
    257     // the area needs to be multiplied by the integral of f(z)
     255    float AspectRatio = axes.minor / axes.major;
     256
     257    // flux = 2 \pi \int f(r) r dr
    258258    norm = 0.0;
    259259
    260     # define DZ 0.25
    261 
    262     float f0 = 1.0;
     260    # define DR 0.25
     261
     262    // f = f(r) * r
     263    float f0 = 0.0;
    263264    float f1, f2;
    264     for (z = DZ; z < 150; z += DZ) {
    265         f1 = 1.0 / (1 + PAR[PM_PAR_7]*z + pow(z, ALPHA));
    266         z += DZ;
    267         f2 = 1.0 / (1 + PAR[PM_PAR_7]*z + pow(z, ALPHA));
     265    for (float r = DR; r < 150; r += DR) {
     266        z = 0.5 * PS_SQR(r / axes.major);
     267        f1 = r / (1 + PAR[PM_PAR_7]*z + pow(z, ALPHA));
     268        r += DR;
     269        z = 0.5 * PS_SQR(r / axes.major);
     270        f2 = r / (1 + PAR[PM_PAR_7]*z + pow(z, ALPHA));
    268271        norm += f0 + 4*f1 + f2;
    269272        f0 = f2;
    270273    }
    271     norm *= DZ / 3.0;
    272 
    273     psF64 Flux = PAR[PM_PAR_I0] * Area * norm;
     274    norm *= DR / 3.0;
     275
     276    psF64 Flux = PAR[PM_PAR_I0] * norm * 2.0 * M_PI * AspectRatio;
    274277
    275278    return(Flux);
  • branches/meh_branches/ppstack_test/psModules/src/objects/models/pmModel_RGAUSS.c

    r31451 r33415  
    229229}
    230230
     231// integrate the model to get the full flux
    231232psF64 PM_MODEL_FLUX (const psVector *params)
    232233{
    233     float norm, z;
     234    float z, norm;
    234235    psEllipseShape shape;
    235236
     
    240241    shape.sxy = PAR[PM_PAR_SXY];
    241242
    242     // Area is equivalent to 2 pi sigma^2
    243243    psEllipseAxes axes = psEllipseShapeToAxes (shape, 20.0);
    244     psF64 Area = 2.0 * M_PI * axes.major * axes.minor;
    245 
    246     // the area needs to be multiplied by the integral of f(z)
     244    float AspectRatio = axes.minor / axes.major;
     245
     246    // flux = 2 \pi \int f(r) r dr
    247247    norm = 0.0;
    248248
    249     # define DZ 0.25
    250 
    251     float f0 = 1.0;
     249    # define DR 0.25
     250
     251    // f = f(r) * r
     252    float f0 = 0.0;
    252253    float f1, f2;
    253     for (z = DZ; z < 150; z += DZ) {
    254         f1 = 1.0 / (1 + z + pow(z, PAR[PM_PAR_7]));
    255         z += DZ;
    256         f2 = 1.0 / (1 + z + pow(z, PAR[PM_PAR_7]));
     254    for (float r = DR; r < 150; r += DR) {
     255        z = 0.5 * PS_SQR(r / axes.major);
     256        f1 = r / (1 + z + pow(z, PAR[PM_PAR_7]));
     257        r += DR;
     258        z = 0.5 * PS_SQR(r / axes.major);
     259        f2 = r / (1 + z + pow(z, PAR[PM_PAR_7]));
    257260        norm += f0 + 4*f1 + f2;
    258261        f0 = f2;
    259262    }
    260     norm *= DZ / 3.0;
    261 
    262     psF64 Flux = PAR[PM_PAR_I0] * Area * norm;
     263    norm *= DR / 3.0;
     264
     265    psF64 Flux = PAR[PM_PAR_I0] * norm * 2.0 * M_PI * AspectRatio;
    263266
    264267    return(Flux);
  • branches/meh_branches/ppstack_test/psModules/src/objects/models/pmModel_SERSIC.c

    r31451 r33415  
    1313   * PM_PAR_XPOS 2  - X center of object
    1414   * PM_PAR_YPOS 3  - Y center of object
    15    * PM_PAR_SXX 4   - X^2 term of elliptical contour (sqrt(2) / SigmaX)
    16    * PM_PAR_SYY 5   - Y^2 term of elliptical contour (sqrt(2) / SigmaY)
     15   * PM_PAR_SXX 4   - X^2 term of elliptical contour (SigmaX / sqrt(2))
     16   * PM_PAR_SYY 5   - Y^2 term of elliptical contour (SigmaY / sqrt(2))
    1717   * PM_PAR_SXY 6   - X*Y term of elliptical contour
    1818   * PM_PAR_7   7   - normalized sersic parameter
     19
     20   * note that a Sersic model is usually defined in terms of R_e, the half-light radius.  This
     21     construction does not include a factor of 2 in the X^2 term, etc, like for a Gaussian.
     22     Conversion from SXX, SYY, SXY to R_major, R_minor, theta can be done by using setting:
     23     shape.sx = SXX / sqrt(2), shape.sy = SYY / sqrt(2), shape.sxy = SXY, then calling
     24     psEllipseShapeToAxes, and multiplying the values of axes.major, axes.minor by sqrt(2)
    1925
    2026   note that a standard sersic model uses exp(-K*(z^(1/2n) - 1).  the additional elements (K,
     
    8591static bool limitsApply = true;         // Apply limits?
    8692
     93# include "pmModel_SERSIC.CP.h"
     94
    8795psF32 PM_MODEL_FUNC (psVector *deriv,
    8896                     const psVector *params,
     
    97105    psF32 z  = PS_SQR(px) + PS_SQR(py) + PAR[PM_PAR_SXY]*X*Y;
    98106
    99     // XXX if the elliptical contour is defined in valid way, this step should not be required.
    100     // other models (like PGAUSS) don't use fractional powers, and thus do not have NaN values
    101     // for negative values of z
    102     // XXX use an assert here to force the elliptical parameters to be correctly determined
    103     // if (z < 0) z = 0;
    104     assert (z >= 0);
     107    // If the elliptical contour is defined in a valid way, we should never trigger this
     108    // assert.  Other models (like PGAUSS) don't use fractional powers, and thus do not have
     109    // NaN values for negative values of z
     110    psAssert (z >= 0, "do not allow negative z values in model");
    105111
    106112    float index = 0.5 / PAR[PM_PAR_7];
     113    float par7 = PAR[PM_PAR_7];
    107114    float bn = 1.9992*index - 0.3271;
    108115    float Io = exp(bn);
    109116
    110     psF32 f2 = bn*pow(z,PAR[PM_PAR_7]);
     117    psF32 f2 = bn*pow(z,par7);
    111118    psF32 f1 = Io*exp(-f2);
     119
     120    psF32 radius = hypot(X, Y);
     121    if (radius < 1.0) {
     122
     123        // ** use bilinear interpolation to the given location from the 4 surrounding pixels centered on the object center
     124
     125        // first, use Rmajor and index to find the central pixel flux (fraction of total flux)
     126        psEllipseShape shape;
     127
     128        shape.sx  = PAR[PM_PAR_SXX];
     129        shape.sy  = PAR[PM_PAR_SYY];
     130        shape.sxy = PAR[PM_PAR_SXY];
     131
     132        // for a non-circular Sersic, the flux of the Rmajor equivalent is scaled by the AspectRatio
     133        psEllipseAxes axes = psEllipseShapeToAxes (shape, 20.0);
     134
     135        // get the central pixel flux from the lookup table
     136        float xPix = (axes.major - centralPixelXo) / centralPixeldX;
     137        xPix = PS_MIN (PS_MAX(xPix, 0), centralPixelNX - 1);
     138        float yPix = (index - centralPixelYo) / centralPixeldY;
     139        yPix = PS_MIN (PS_MAX(yPix, 0), centralPixelNY - 1);
     140
     141        // the integral of a Sersic has an analytical form as follows:
     142        float logGamma = lgamma(2.0*index);
     143        float bnFactor = pow(bn, 2.0*index);
     144        float norm = 2.0 * M_PI * PS_SQR(axes.major) * index * exp(bn) * exp(logGamma) / bnFactor;
     145
     146        // XXX interpolate to get the value
     147        // XXX for the moment, just integerize
     148        // XXX I need to multiply by the integrated flux to get the flux in the central pixel
     149        float Vcenter = centralPixel[(int)yPix][(int)xPix] * norm;
     150       
     151        float px1 = 1.0 / PAR[PM_PAR_SXX];
     152        float py1 = 1.0 / PAR[PM_PAR_SYY];
     153        float z10 = PS_SQR(px1);
     154        float z01 = PS_SQR(py1);
     155
     156        // which pixels do we need for this interpolation?
     157        // (I do not keep state information, so I don't know anything about other evaluations of nearby pixels...)
     158        if ((X >= 0) && (Y >= 0)) {
     159            float z11 = z10 + z01 + PAR[PM_PAR_SXY]; // X * Y positive
     160            float V00 = Vcenter;
     161            float V10 = Io*exp(-bn*pow(z10,par7));
     162            float V01 = Io*exp(-bn*pow(z01,par7));
     163            float V11 = Io*exp(-bn*pow(z11,par7));
     164            f1 = interpolatePixels(V00, V10, V01, V11, X, Y);
     165        }
     166        if ((X < 0) && (Y >= 0)) {
     167            float z11 = z10 + z01 - PAR[PM_PAR_SXY]; // X * Y negative
     168            float V00 = Io*exp(-bn*pow(z10,par7));
     169            float V10 = Vcenter;
     170            float V01 = Io*exp(-bn*pow(z11,par7));
     171            float V11 = Io*exp(-bn*pow(z01,par7));
     172            f1 = interpolatePixels(V00, V10, V01, V11, (1.0 + X), Y);
     173        }
     174        if ((X >= 0) && (Y < 0)) {
     175            float z11 = z10 + z01 - PAR[PM_PAR_SXY]; // X * Y negative
     176            float V00 = Io*exp(-bn*pow(z01,par7));
     177            float V10 = Io*exp(-bn*pow(z11,par7));
     178            float V01 = Vcenter;
     179            float V11 = Io*exp(-bn*pow(z10,par7));
     180            f1 = interpolatePixels(V00, V10, V01, V11, X, (1.0 + Y));
     181        }
     182        if ((X < 0) && (Y < 0)) {
     183            float z11 = z10 + z01 + PAR[PM_PAR_SXY]; // X * Y positive
     184            float V00 = Io*exp(-bn*pow(z11,par7));
     185            float V10 = Io*exp(-bn*pow(z10,par7));
     186            float V01 = Io*exp(-bn*pow(z01,par7));
     187            float V11 = Vcenter;
     188            f1 = interpolatePixels(V00, V10, V01, V11, (1.0 + X), (1.0 + Y));
     189        }
     190    }   
     191
    112192    psF32 z0 = PAR[PM_PAR_I0]*f1;
    113193    psF32 f0 = PAR[PM_PAR_SKY] + z0;
     
    121201        psF32 *dPAR = deriv->data.F32;
    122202
    123         // gradient is infinite for z = 0; saturate at z = 0.01
    124         psF32 z1 = (z < 0.01) ? z0*bn*PAR[PM_PAR_7]*pow(0.01,PAR[PM_PAR_7] - 1.0) : z0*bn*PAR[PM_PAR_7]*pow(z,PAR[PM_PAR_7] - 1.0);
    125 
    126203        dPAR[PM_PAR_SKY]  = +1.0;
    127204        dPAR[PM_PAR_I0]   = +f1;
    128         dPAR[PM_PAR_7]    = (z < 0.01) ? -z0*pow(0.01,PAR[PM_PAR_7])*log(0.01) : -z0*f2*log(z);
     205
     206        // gradient is infinite for z = 0; saturate at z = 0.01
     207        psF32 z1 = (z < 0.01) ? z0*bn*par7*pow(0.01,par7 - 1.0) : z0*bn*par7*pow(z,par7 - 1.0);
     208
     209        dPAR[PM_PAR_7]    = (z < 0.01) ? -z0*pow(0.01,par7)*log(0.01) : -z0*f2*log(z);
    129210        dPAR[PM_PAR_7]   *= 3.0;
    130211
     
    269350    float Io = exp(0.5*bn);
    270351
    271     // XXX do we need this factor of sqrt(2)?
    272     // float Sxx = PS_MAX(0.5, M_SQRT2*shape.sx);
    273     // float Syy = PS_MAX(0.5, M_SQRT2*shape.sy);
    274 
    275352    float Sxx = PS_MAX(0.5, shape.sx);
    276353    float Syy = PS_MAX(0.5, shape.sy);
     
    294371}
    295372
     373// A sersic model has an integral flux which can be analytically represented
    296374psF64 PM_MODEL_FLUX (const psVector *params)
    297375{
    298     float z, norm;
    299376    psEllipseShape shape;
    300377
    301378    psF32 *PAR = params->data.F32;
    302379
    303     shape.sx  = PAR[PM_PAR_SXX] / M_SQRT2;
    304     shape.sy  = PAR[PM_PAR_SYY] / M_SQRT2;
     380    shape.sx  = PAR[PM_PAR_SXX];
     381    shape.sy  = PAR[PM_PAR_SYY];
    305382    shape.sxy = PAR[PM_PAR_SXY];
    306383
    307     // Area is equivalent to 2 pi sigma^2
     384    // for a non-circular Sersic, the flux of the Rmajor equivalent is scaled by the AspectRatio
    308385    psEllipseAxes axes = psEllipseShapeToAxes (shape, 20.0);
    309     psF64 Area = 2.0 * M_PI * axes.major * axes.minor;
    310 
    311     // the area needs to be multiplied by the integral of f(z)
    312     norm = 0.0;
    313 
    314     # define DZ 0.25
    315 
    316     float f0 = 1.0;
    317     float f1, f2;
    318     for (z = DZ; z < 150; z += DZ) {
    319         // f1 = 1.0 / (1 + PAR[PM_PAR_7]*z + pow(z, 2.25));
    320         f1 = exp(-pow(z,PAR[PM_PAR_7]));
    321         z += DZ;
    322         f2 = exp(-pow(z,PAR[PM_PAR_7]));
    323         norm += f0 + 4*f1 + f2;
    324         f0 = f2;
    325     }
    326     norm *= DZ / 3.0;
    327 
    328     psF64 Flux = PAR[PM_PAR_I0] * Area * norm;
     386    float AspectRatio = axes.minor / axes.major;
     387
     388    float index = 0.5 / PAR[PM_PAR_7];
     389    float bn = 1.9992*index - 0.3271;
     390
     391    // the integral of a Sersic has an analytical form as follows:
     392    float logGamma = lgamma(2.0*index);
     393    float bnFactor = pow(bn, 2.0*index);
     394    float norm = 2.0 * M_PI * PS_SQR(axes.major) * index * exp(bn) * exp(logGamma) / bnFactor;
     395   
     396    psF64 Flux = PAR[PM_PAR_I0] * norm * AspectRatio;
    329397
    330398    return(Flux);
     
    346414        return (1.0);
    347415
    348     shape.sx  = PAR[PM_PAR_SXX] / M_SQRT2;
    349     shape.sy  = PAR[PM_PAR_SYY] / M_SQRT2;
     416    shape.sx  = PAR[PM_PAR_SXX];
     417    shape.sy  = PAR[PM_PAR_SYY];
    350418    shape.sxy = PAR[PM_PAR_SXY];
    351419
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmFootprintCullPeaks.c

    r31263 r33415  
    118118            threshbounds->data.F32[i] = 0.25*beta2*PS_SQR(i) + min_threshold;       
    119119        }
    120         psAssert(threshbounds->data.F32[threshbounds->n-1] > maxFlux, "upper limit does not include max flux");
    121 
     120        if (threshbounds->data.F32[threshbounds->n-1] > maxFlux) {
     121            psWarning ("upper limit: %f does not include max flux: %f",
     122                    threshbounds->data.F32[threshbounds->n-1], maxFlux);
     123        }
    122124        psHistogram *threshist = psHistogramAllocGeneric(threshbounds);
    123125
     
    181183            if (!myFP->n) {
    182184                psWarning ("empty footprint?");
     185                psFree (myFP);
    183186                continue;
    184187            }
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmModelUtils.c

    r31153 r33415  
    122122    if (!isfinite(axes.theta)) return false;
    123123
     124    // Mxx, Mxy, Myy define the elliptical shape, but Mrf defines the width
     125    float scale = (isfinite(moments->Mrf) && (moments->Mrf > 0.0)) ? moments->Mrf / axes.major : 1.0;
     126    axes.major *= scale;
     127    axes.minor *= scale;
     128
    124129    psEllipseShape shape = psEllipseAxesToShape (axes);
    125130
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmMoments.c

    r29004 r33415  
    3232    tmp->Mrf = 0.0;
    3333    tmp->Mrh = 0.0;
     34
     35    tmp->KronCore = 0.0;
     36    tmp->KronCoreErr = 0.0;
     37
    3438    tmp->KronFlux = 0.0;
    3539    tmp->KronFluxErr = 0.0;
     
    3741    tmp->KronFinner = 0.0;
    3842    tmp->KronFouter = 0.0;
     43
     44    tmp->KronFluxPSF = 0.0;
     45    tmp->KronFluxPSFErr = 0.0;
     46    tmp->KronRadiusPSF = 0.0;
    3947
    4048    tmp->Mx = 0.0;
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmMoments.h

    r31153 r33415  
    5151    int nPixels;  ///< Number of pixels used.
    5252
     53    float KronFluxPSF; ///< Kron Flux using PSF-optimized window
     54    float KronFluxPSFErr; ///< Kron Flux Error using PSF-optimized window
     55    float KronRadiusPSF; ///< Kron Radius using PSF-optimized window (Flux in 2.5 Radius)
     56
    5357    float KronCore;    ///< flux in r < 1.0*Mrf
    5458    float KronCoreErr;    ///< error on flux in r < 1.0*Mrf
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmPCM_MinimizeChisq.c

    r29012 r33415  
    4545# define USE_FFT 1
    4646# define PRE_CONVOLVE 1
     47# define TESTCOPY 0
    4748
    4849bool pmPCM_MinimizeChisq (
     
    9394        psFree (pcm->psfFFT);
    9495    }
    95     pcm->psfFFT = psImageConvolveKernelInit(pcm->modelFlux, pcm->psf);
     96# if (!TESTCOPY)
     97    if (!pcm->use1Dgauss) {
     98        pcm->psfFFT = psImageConvolveKernelInit(pcm->modelFlux, pcm->psf);
     99    }
     100# endif
    96101# endif   
    97102
     
    285290
    286291            // Convert i/j to image space:
    287             coord->data.F32[0] = (psF32) (j + source->pixels->col0);
    288             coord->data.F32[1] = (psF32) (i + source->pixels->row0);
     292            coord->data.F32[0] = (psF32) (j + 0.5 + source->pixels->col0);
     293            coord->data.F32[1] = (psF32) (i + 0.5 + source->pixels->row0);
    289294
    290295            pcm->modelFlux->data.F32[i][j] = pcm->modelConv->modelFunc (deriv, params, coord);
     
    309314# if (PRE_CONVOLVE)
    310315    // convolve model image and derivative images with pre-convolved kernel
    311     psImageConvolveKernel (pcm->modelConvFlux, pcm->modelFlux, NULL, 0, pcm->psfFFT);
     316
     317// XXX for a test, just copy, rather than convolve
     318# if (TESTCOPY)
     319    psImageCopy (pcm->modelConvFlux, pcm->modelFlux, pcm->modelFlux->type.type);
     320# else
     321    if (pcm->use1Dgauss) {
     322        // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread):
     323        // * the model flux is not masked
     324        // * threading takes place above this level
     325        pcm->modelConvFlux = psImageCopy (pcm->modelConvFlux, pcm->modelFlux, pcm->modelFlux->type.type);
     326        psImageSmooth_PreAlloc_F32 (pcm->modelConvFlux, pcm->smdata);
     327        // psImageSmooth (pcm->modelConvFlux, pcm->sigma, pcm->nsigma);
     328    } else {
     329        psImageConvolveKernel (pcm->modelConvFlux, pcm->modelFlux, NULL, 0, pcm->psfFFT);
     330    }
     331# endif
     332
    312333    for (int n = 0; n < pcm->dmodelsFlux->n; n++) {
    313334        if (pcm->dmodelsFlux->data[n] == NULL) continue;
     
    315336        psImage *dmodel = pcm->dmodelsFlux->data[n];
    316337        psImage *dmodelConv = pcm->dmodelsConvFlux->data[n];
    317         psImageConvolveKernel (dmodelConv, dmodel, NULL, 0, pcm->psfFFT);
     338# if (TESTCOPY)
     339        psImageCopy (dmodelConv, dmodel, dmodel->type.type);
     340# else
     341        if (pcm->use1Dgauss) {
     342            // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread):
     343            // * the model flux is not masked
     344            // * threading takes place above this level
     345            dmodelConv = psImageCopy (dmodelConv, dmodel, dmodel->type.type);
     346            psImageSmooth_PreAlloc_F32 (dmodelConv, pcm->smdata);
     347            // psImageSmooth (dmodelConv, pcm->sigma, pcm->nsigma);
     348        } else {
     349            psImageConvolveKernel (dmodelConv, dmodel, NULL, 0, pcm->psfFFT);
     350        }
     351# endif
    318352    }
    319353# else
     
    325359        psImage *dmodel = pcm->dmodelsFlux->data[n];
    326360        psImage *dmodelConv = pcm->dmodelsConvFlux->data[n];
    327         psImageConvolveFFT (dmodelConv, dmodel, NULL, 0, pcm->psf);
     361
     362        if (pcm->use1Dgauss) {
     363            // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread):
     364            // * the model flux is not masked
     365            // * threading takes place above this level
     366            dmodelConv = psImageCopy (dmodelConv, dmodel, dmodel->type.type);
     367            psImageSmooth_PreAlloc_F32 (dmodelConv, pcm->smdata);
     368            // psImageSmooth (dmodelConv, pcm->sigma, pcm->nsigma);
     369        } else {
     370            psImageConvolveFFT (dmodelConv, dmodel, NULL, 0, pcm->psf);
     371        }
    328372    }
    329373# endif // PRE-CONVOLVE
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmPCMdata.c

    r31451 r33415  
    4141#include "pmPCMdata.h"
    4242
     43# define USE_DELTA_PSF 0
     44# define USE_1D_GAUSS 1
     45
    4346static void pmPCMdataFree (pmPCMdata *pcm) {
    4447
     
    5457    psFree (pcm->psfFFT);
    5558    psFree (pcm->constraint);
     59    psFree (pcm->smdata); // pre-allocated data for psImageSmooth_PreAlloc
    5660    return;
    5761}
     
    8892    pcm->constraint = NULL;
    8993    pcm->nDOF = 0;
     94
     95    // full convolution with the PSF is expensive.  if we have to save time, we can do a 1D
     96    // convolution with a Gaussian approximation to the kernel
     97    pcm->use1Dgauss = false;
     98    pcm->nsigma = 3.0;
     99    pcm->sigma = 1.0; // this should be set to something sensible when the psf is known
    90100
    91101    return pcm;
     
    257267    pcm->nDOF = nPix - nParams;
    258268
     269# if (USE_1D_GAUSS)
     270    pmModel *modelPSF = source->modelPSF;
     271    psAssert (modelPSF, "psf model must be defined");
     272   
     273    psEllipseShape shape;
     274    psEllipseAxes axes;
     275
     276    shape.sx  = modelPSF->params->data.F32[PM_PAR_SXX];
     277    shape.sy  = modelPSF->params->data.F32[PM_PAR_SYY];
     278    shape.sxy = modelPSF->params->data.F32[PM_PAR_SXY];
     279    axes = psEllipseShapeToAxes (shape, 20.0);
     280   
     281    float FWHM_MAJOR = 2*modelPSF->modelRadius (modelPSF->params, 0.5*modelPSF->params->data.F32[PM_PAR_I0]);
     282    float FWHM_MINOR = FWHM_MAJOR * (axes.minor / axes.major);
     283
     284    pcm->use1Dgauss = true;
     285    pcm->sigma = 0.5 * (FWHM_MAJOR + FWHM_MINOR) / 2.35;
     286    pcm->nsigma = 2.0;
     287
     288    pcm->smdata = psImageSmooth_PreAlloc_DataAlloc (source->pixels, pcm->sigma, pcm->nsigma);
     289# else
     290    pcm->smdata = NULL;
     291# endif
     292
    259293    return pcm;
    260294}
     
    364398            pcm->dmodelsConvFlux->data[n] = psImageCopy (pcm->dmodelsConvFlux->data[n], source->pixels, PS_TYPE_F32);
    365399        }
     400        psFree(pcm->smdata);
     401        pcm->smdata = psImageSmooth_PreAlloc_DataAlloc (source->pixels, pcm->sigma, pcm->nsigma);
    366402    }
    367403
    368404    return true;
    369405}
     406
     407// construct a realization of the source model
     408bool pmPCMCacheModel (pmSource *source, psImageMaskType maskVal, int psfSize) {
     409
     410    PS_ASSERT_PTR_NON_NULL(source, false);
     411
     412    // select appropriate model
     413    pmModel *model = pmSourceGetModel (NULL, source);
     414    if (model == NULL) return false;  // model must be defined
     415
     416    // if we already have a cached image, re-use that memory
     417    source->modelFlux = psImageCopy (source->modelFlux, source->pixels, PS_TYPE_F32);
     418    psImageInit (source->modelFlux, 0.0);
     419
     420    // modelFlux always has unity normalization (I0 = 1.0)
     421    pmModelAdd (source->modelFlux, source->maskObj, model, PM_MODEL_OP_FULL | PM_MODEL_OP_NORM, maskVal);
     422
     423    // convolve the model image with the PSF
     424    if (USE_1D_GAUSS) {
     425        // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread):
     426        // * the model flux is not masked
     427        // * threading takes place above this level
     428       
     429        // define the Gauss parameters from the psf
     430        pmModel *modelPSF = source->modelPSF;
     431        psAssert (modelPSF, "psf model must be defined");
     432   
     433        psEllipseShape shape;
     434        psEllipseAxes axes;
     435
     436        shape.sx  = modelPSF->params->data.F32[PM_PAR_SXX];
     437        shape.sy  = modelPSF->params->data.F32[PM_PAR_SYY];
     438        shape.sxy = modelPSF->params->data.F32[PM_PAR_SXY];
     439        axes = psEllipseShapeToAxes (shape, 20.0);
     440   
     441        float FWHM_MAJOR = 2*modelPSF->modelRadius (modelPSF->params, 0.5*modelPSF->params->data.F32[PM_PAR_I0]);
     442        float FWHM_MINOR = FWHM_MAJOR * (axes.minor / axes.major);
     443
     444        float sigma = 0.5 * (FWHM_MAJOR + FWHM_MINOR) / 2.35;
     445        float nsigma = 2.0;
     446
     447        psImageSmooth (source->modelFlux, sigma, nsigma);
     448    } else {
     449        // make sure we save a cached copy of the psf flux
     450        pmSourceCachePSF (source, maskVal);
     451
     452        // convert the cached cached psf model for this source to a psKernel
     453        psKernel *psf = pmPCMkernelFromPSF (source, psfSize);
     454        if (!psf) {
     455            // NOTE: this only happens if the source is too close to an edge
     456            model->flags |= PM_MODEL_STATUS_BADARGS;
     457            return NULL;
     458        }
     459
     460        // XXX not sure if I can place the output on top of the input
     461        psImageConvolveFFT (source->modelFlux, source->modelFlux, NULL, 0, psf);
     462    }
     463    return true;
     464}
     465
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmPCMdata.h

    r31153 r33415  
    3535    int nPar;
    3636    int nDOF;
     37
     38    bool use1Dgauss;
     39    float sigma;
     40    float nsigma;
     41
     42    psImageSmooth_PreAlloc_Data *smdata;
    3743} pmPCMdata;
    3844
     
    9096bool pmSourceFitPCM (pmPCMdata *pcm, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize);
    9197
     98bool pmPCMCacheModel (pmSource *source, psImageMaskType maskVal, int psfSize);
    9299
    93100/// @}
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmPSF.c

    r31451 r33415  
    281281// convert the parameters used in the fitted source model
    282282// to the parameters used in the 2D PSF model
     283// XXX this function may be invalid for SERSIC, DEV, EXP models (SQRT2 not used?)
    283284bool pmPSF_FitToModel (psF32 *fittedPar, float minMinorAxis)
    284285{
     
    307308// convert the PSF parameters used in the 2D PSF model fit into the
    308309// parameters used in the source model
     310// XXX this function may be invalid for SERSIC, DEV, EXP models (SQRT2 not used?)
    309311psEllipsePol pmPSF_ModelToFit (psF32 *modelPar)
    310312{
     
    329331// convert the parameters used in the fitted source model to the psEllipseAxes representation
    330332// (major,minor,theta)
    331 psEllipseAxes pmPSF_ModelToAxes (psF32 *modelPar, double maxAR)
     333psEllipseAxes pmPSF_ModelToAxes (psF32 *modelPar, double maxAR, pmModelType type)
    332334{
    333335    psEllipseShape shape;
     
    336338    axes.minor = NAN;
    337339    axes.theta = NAN;
    338 //   XXX: must assert non-NULL input parameter
     340    //   XXX: must assert non-NULL input parameter
    339341    PS_ASSERT_PTR_NON_NULL(modelPar, axes);
    340342
    341     shape.sx  = modelPar[PM_PAR_SXX] / M_SQRT2;
    342     shape.sy  = modelPar[PM_PAR_SYY] / M_SQRT2;
    343     shape.sxy = modelPar[PM_PAR_SXY];
     343    bool useReff = true;
     344    useReff |= (type == pmModelClassGetType ("PS_MODEL_SERSIC"));
     345    useReff |= (type == pmModelClassGetType ("PS_MODEL_DEV"));
     346    useReff |= (type == pmModelClassGetType ("PS_MODEL_EXP"));
     347
     348    if (useReff) {
     349        shape.sx  = modelPar[PM_PAR_SXX];
     350        shape.sy  = modelPar[PM_PAR_SYY];
     351        shape.sxy = modelPar[PM_PAR_SXY];
     352    } else {
     353        shape.sx  = modelPar[PM_PAR_SXX] / M_SQRT2;
     354        shape.sy  = modelPar[PM_PAR_SYY] / M_SQRT2;
     355        shape.sxy = modelPar[PM_PAR_SXY];
     356    }
    344357
    345358    if ((shape.sx == 0) || (shape.sy == 0)) {
     
    357370// convert the psEllipseAxes representation (major,minor,theta) to the parameters used in the
    358371// fitted source model
    359 bool pmPSF_AxesToModel (psF32 *modelPar, psEllipseAxes axes)
     372bool pmPSF_AxesToModel (psF32 *modelPar, psEllipseAxes axes, pmModelType type)
    360373{
    361374    PS_ASSERT_PTR_NON_NULL(modelPar, false);
     
    370383    psEllipseShape shape = psEllipseAxesToShape (axes);
    371384
    372     modelPar[PM_PAR_SXX] = shape.sx * M_SQRT2;
    373     modelPar[PM_PAR_SYY] = shape.sy * M_SQRT2;
    374     modelPar[PM_PAR_SXY] = shape.sxy;
    375 
     385    bool useReff = true;
     386    useReff |= pmModelClassGetType ("PS_MODEL_SERSIC");
     387    useReff |= pmModelClassGetType ("PS_MODEL_DEV");
     388    useReff |= pmModelClassGetType ("PS_MODEL_EXP");
     389
     390    if (useReff) {
     391        modelPar[PM_PAR_SXX] = shape.sx;
     392        modelPar[PM_PAR_SYY] = shape.sy;
     393        modelPar[PM_PAR_SXY] = shape.sxy;
     394    } else {
     395        modelPar[PM_PAR_SXX] = shape.sx * M_SQRT2;
     396        modelPar[PM_PAR_SYY] = shape.sy * M_SQRT2;
     397        modelPar[PM_PAR_SXY] = shape.sxy;
     398    }
    376399    return true;
    377400}
     
    438461# if (0)
    439462    psF32 *params = model->params->data.F32; // Model parameters
    440     psEllipseAxes axes = pmPSF_ModelToAxes(params, MAX_AXIS_RATIO); // Ellipse axes
     463    psEllipseAxes axes = pmPSF_ModelToAxes(params, MAX_AXIS_RATIO, model->type); // Ellipse axes
    441464
    442465    // Curiously, the minor axis can be larger than the major axis, so need to check.
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmPSF.h

    r31451 r33415  
    106106pmPSF *pmPSFBuildSimple (char *typeName, float sxx, float syy, float sxy, ...);
    107107
    108 bool pmPSF_AxesToModel (psF32 *modelPar, psEllipseAxes axes);
     108bool pmPSF_AxesToModel (psF32 *modelPar, psEllipseAxes axes, pmModelType type);
    109109bool pmPSF_FitToModel (psF32 *fittedPar, float minMinorAxis);
    110110
    111111psEllipsePol pmPSF_ModelToFit (psF32 *modelPar);
    112 psEllipseAxes pmPSF_ModelToAxes (psF32 *modelPar, double maxAR);
     112psEllipseAxes pmPSF_ModelToAxes (psF32 *modelPar, double maxAR, pmModelType type);
    113113
    114114/// Calculate FWHM value from a PSF
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmPeaks.c

    r31451 r33415  
    137137*****************************************************************************/
    138138static void peakFree(pmPeak *tmp)
    139 {} //
     139{
     140    if (!tmp) return;
     141    psFree (tmp->saddlePoints);
     142    return;
     143}
    140144
    141145pmPeak *pmPeakAlloc(psS32 x,
     
    162166    tmp->type = type;
    163167    tmp->footprint = NULL;
     168    tmp->saddlePoints = NULL;
    164169
    165170    psMemSetDeallocator(tmp, (psFreeFunc) peakFree);
     
    185190    out->assigned        = in->assigned;
    186191    out->type            = in->type;
     192    out->footprint       = in->footprint;
    187193
    188194    return true;
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmPeaks.h

    r31451 r33415  
    7171    bool assigned;                      ///< is peak assigned to a source?
    7272    pmPeakType type;                    ///< Description of peak.
    73     pmFootprint *footprint;             ///< reference to containing footprint
     73    pmFootprint *footprint;             ///< reference to containing footprint (just a view, not a memcopy)
     74    psArray *saddlePoints;              ///< set of saddle points between this peak and near neighbors
    7475}
    7576pmPeak;
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmSource.c

    r31670 r33415  
    5858    psFree(tmp->modelEXT);
    5959    psFree(tmp->modelFits);
     60    psFree(tmp->extFitPars);
    6061    psFree(tmp->extpars);
    6162    psFree(tmp->moments);
     
    119120    source->modelEXT = NULL;
    120121    source->modelFits = NULL;
     122    source->extFitPars = NULL;
     123
    121124    source->type = PM_SOURCE_TYPE_UNKNOWN;
    122125    source->mode = PM_SOURCE_MODE_DEFAULT;
     
    136139    source->apFluxErr        = NAN;
    137140
     141    source->windowRadius     = NAN;
     142    source->skyRadius        = NAN;
     143    source->skyFlux          = NAN;
     144    source->skySlope         = NAN;
     145
    138146    source->pixWeightNotBad  = NAN;
    139147    source->pixWeightNotPoor = NAN;
     
    196204    // NOTE : because of the const id element, we cannot just assign *source = *in
    197205
     206    source->imageID          = in->imageID;
     207
    198208    source->type             = in->type;
    199209    source->mode             = in->mode;
    200210    source->mode2            = in->mode2;
    201211    source->tmpFlags         = in->tmpFlags;
     212
    202213    source->psfMag           = in->psfMag;
    203214    source->psfMagErr        = in->psfMagErr;
     
    210221    source->apFlux           = in->apFlux;
    211222    source->apFluxErr        = in->apFluxErr;
     223
     224    source->windowRadius     = in->windowRadius;
     225    source->skyRadius        = in->skyRadius;   
     226    source->skyFlux          = in->skyFlux;     
     227    source->skySlope         = in->skySlope;   
     228
    212229    source->pixWeightNotBad  = in->pixWeightNotBad;
    213230    source->pixWeightNotPoor = in->pixWeightNotPoor;
     231
    214232    source->psfChisq         = in->psfChisq;
    215233    source->crNsigma         = in->crNsigma;
     
    252270    }
    253271    mySource->region   = srcRegion;
     272    mySource->windowRadius = Radius;
    254273
    255274    return true;
     
    321340        mySource->psfImage = NULL;
    322341    }
     342    mySource->windowRadius = Radius;
    323343    return extend;
    324344}
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmSource.h

    r31670 r33415  
    3636    PM_SOURCE_TMPF_MOMENTS_MEASURED  = 0x0010,
    3737    PM_SOURCE_TMPF_CANDIDATE_PSFSTAR = 0x0020,
     38    PM_SOURCE_TMPF_RADIAL_KEEP       = 0x0040,
     39    PM_SOURCE_TMPF_RADIAL_SKIP       = 0x0080,
     40    PM_SOURCE_TMPF_PETRO_KEEP        = 0x0100,
     41    PM_SOURCE_TMPF_PETRO_SKIP        = 0x0200,
    3842} pmSourceTmpF;
    3943
     
    7680    pmModel *modelEXT;                  ///< EXT Model fit used for subtraction (parameters and type)
    7781    psArray *modelFits;                 ///< collection of extended source models (best == modelEXT)
     82    psArray *extFitPars;                ///< extra extended fit parameters
    7883    pmSourceType type;                  ///< Best identification of object.
    7984    pmSourceMode mode;                  ///< analysis flags set for object.
     
    9196    float apFlux;                       ///< apFlux corresponding to psfMag or extMag (depending on type)
    9297    float apFluxErr;                    ///< apFluxErr corresponding to psfMag or extMag (depending on type)
     98
     99    float windowRadius;                 ///< size of box used for full analysis
     100    float skyRadius;                    ///< radius at which profile hits local sky (or goes flat)
     101    float skyFlux;                      ///< mean flux per pixel in aperture at which profile hits local sky (or goes flat)
     102    float skySlope;                     ///< mean flux slope at which profile hits local sky (or goes flat)
    93103
    94104    float pixWeightNotBad;              ///< PSF-weighted coverage of unmasked (not BAD) pixels
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmSourceExtendedPars.c

    r31153 r33415  
    258258    return ( psMemGetDeallocator(ptr) == (psFreeFunc) pmSourceExtendedFluxFree);
    259259}
     260
     261// *** pmSourceExtFitPars describes extra metadata related to an extended fit
     262static void pmSourceExtFitParsFree (pmSourceExtFitPars *pars) {
     263    return;
     264}
     265
     266pmSourceExtFitPars *pmSourceExtFitParsAlloc (void) {
     267
     268    pmSourceExtFitPars *pars = (pmSourceExtFitPars *) psAlloc(sizeof(pmSourceExtFitPars));
     269    psMemSetDeallocator(pars, (psFreeFunc) pmSourceExtFitParsFree);
     270
     271    pars->Mxx = NAN;
     272    pars->Mxy = NAN;
     273    pars->Myy = NAN;
     274
     275    pars->Mrf    = NAN;
     276    pars->Mrh    = NAN;
     277
     278    pars->apMag  = NAN;
     279    pars->krMag  = NAN;
     280    pars->psfMag = NAN;
     281    pars->peakMag = NAN;
     282
     283    return pars;
     284}
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmSourceExtendedPars.h

    r31153 r33415  
    6767} pmSourceExtendedPars;
    6868
     69// additional measurements related to the model fits
     70typedef struct {
     71    float Mxx;
     72    float Mxy;
     73    float Myy;
     74   
     75    float Mrf;
     76    float Mrh;
     77
     78    float apMag;
     79    float krMag;
     80    float psfMag;
     81    float peakMag;
     82} pmSourceExtFitPars;
     83
    6984pmSourceRadialFlux *pmSourceRadialFluxAlloc();
    7085bool psMemCheckSourceRadialFlux(psPtr ptr);
     
    92107bool pmSourceRadialProfileSortPair(psVector *index, psVector *extra);
    93108
    94 
     109pmSourceExtFitPars *pmSourceExtFitParsAlloc (void);
    95110
    96111/// @}
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmSourceFitModel.c

    r31153 r33415  
    176176        break;
    177177      case PM_SOURCE_FIT_EXT:
    178         // EXT model fits all params (except sky)
    179         nParams = params->n - 1;
     178        // EXT model fits all shape params and Io (not Xo, Yo, sky)
     179        nParams = params->n - 3;
    180180        psVectorInit (constraint->paramMask, 0);
     181        constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_XPOS] = 1;
     182        constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_YPOS] = 1;
    181183        constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_SKY] = 1;
    182184        break;
     
    193195        break;
    194196      case PM_SOURCE_FIT_NO_INDEX:
    195         // PSF model only fits Io, index (PAR7) -- only Io for models with < 8 params
     197        // PSF model only fits Io, Sxx, Sxy, Syy
    196198        psVectorInit (constraint->paramMask, 0);
     199        constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_XPOS] = 1;
     200        constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_YPOS] = 1;
    197201        constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_SKY] = 1;
    198202        if (params->n == 7) {
    199             nParams = params->n - 1;
     203            nParams = params->n - 3;
    200204        } else {
    201             nParams = params->n - 2;
     205            nParams = params->n - 4;
    202206            constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_7] = 1;
    203207        }
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmSourceFitPCM.c

    r31153 r33415  
    4848// convolved model image.
    4949
     50# define TIMING 0
     51
    5052bool pmSourceFitPCM (pmPCMdata *pcm, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) {
    5153   
     54    if (TIMING) { psTimerStart ("pmSourceFitPCM"); }
     55
    5256    psVector *params  = pcm->modelConv->params;
    5357    psVector *dparams  = pcm->modelConv->dparams;
     
    6367
    6468    psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F32);
     69    // NOTE : 4 allocs to here
    6570
     71    float t1, t2, t3, t4, t5;
     72    if (TIMING) { t1 = psTimerMark ("pmSourceFitPCM"); }
     73
     74    // NOTE : 996 allocs in here
    6675    bool fitStatus = pmPCM_MinimizeChisq (myMin, covar, params, source, pcm);
     76    if (TIMING) { t2 = psTimerMark ("pmSourceFitPCM"); }
     77
    6778    for (int i = 0; i < dparams->n; i++) {
    6879        if ((pcm->constraint->paramMask != NULL) && pcm->constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[i])
     
    7687    }
    7788    psTrace ("psphot", 4, "niter: %d, chisq: %f", myMin->iter, myMin->value);
     89    if (TIMING) { t3 = psTimerMark ("pmSourceFitPCM"); }
    7890
    7991    // renormalize output model image (generated by fitting process)
     
    97109        pmSourceChisqUnsubtracted (source, pcm->modelConv, maskVal);
    98110    }
     111    if (TIMING) { t4 = psTimerMark ("pmSourceFitPCM"); }
    99112
    100113    // set the model success or failure status
     
    114127
    115128    source->mode |= PM_SOURCE_MODE_FITTED; // XXX is this needed?
     129    if (TIMING) { t5 = psTimerMark ("pmSourceFitPCM"); }
     130
     131     if (TIMING) {
     132        fprintf (stderr, "nIter: %2d, npix: %5d, t1: %6.4f, t2: %6.4f, t3: %6.4f, t4: %6.4f, t5: %6.4f\n", myMin->iter, pcm->nPix, t1, t2, t3, t4, t5);
     133     }
    116134
    117135    psFree(myMin);
     
    121139}
    122140
     141// XXX deprecate this function or merge with the empirical model
    123142bool pmSourceModelGuessPCM (pmPCMdata *pcm, pmSource *source, psImageMaskType maskVal, psImageMaskType markVal) {
    124143
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmSourceIO.c

    r31670 r33415  
    5757#define BLANK_HEADERS "BLANK.HEADERS"   // Name of metadata in camera configuration containing header names
    5858                                        // for putting values into a blank PHU
     59static bool pmReadoutReadXSRC(pmFPAfile *file, char * exttype, psMetadata *hduHeader, psString xsrcname, psArray *sources, long *sourceIndex);
     60static bool pmReadoutReadXFIT(pmFPAfile *file, char * exttype, psMetadata *hduHeader, psString xfitname, psArray *sources, long *sourceIndex);
     61static bool pmReadoutReadXRAD(pmFPAfile *file, pmReadout *readout, char * exttype, psMetadata *hduHeader, psString xfitname, psArray *sources, long *sourceIndex);
    5962
    6063// lookup the EXTNAME values used for table data and image header segments
     
    569572            PM_SOURCES_WRITE("PS1_V2",    CMF_PS1_V2);
    570573            PM_SOURCES_WRITE("PS1_V3",    CMF_PS1_V3);
     574            PM_SOURCES_WRITE("PS1_V4",    CMF_PS1_V4);
    571575            PM_SOURCES_WRITE("PS1_SV1",   CMF_PS1_SV1);
    572576            PM_SOURCES_WRITE("PS1_DV1",   CMF_PS1_DV1);
     
    960964        psString dataname = NULL;
    961965        psString deteffname = NULL;
    962         if (!pmSourceIOextnames(&headname, &dataname, &deteffname, NULL, NULL, NULL, file, view)) {
     966        psString xsrcname = NULL;
     967        psString xfitname = NULL;
     968        psString xradname = NULL;
     969
     970        // determine the output table format. Assume if we need to output extendend source
     971        // parameters that they may exist in the input.
     972        // XXX: Perhaps we should use different recipe values.
     973        // I.E. EXTENDED_SOURCE_ANALYSIS_READ or something like that
     974        psMetadata *recipe = psMetadataLookupMetadata(&status, config->recipes, "PSPHOT");
     975        if (!status) {
     976            psError(PS_ERR_UNKNOWN, true, "missing recipe PSPHOT in config data");
     977            return false;
     978        }
     979        // if this is not TRUE, the output files only contain the psf measurements.
     980        bool XSRC_OUTPUT = psMetadataLookupBool(&status, recipe, "EXTENDED_SOURCE_ANALYSIS");
     981        bool XFIT_OUTPUT = psMetadataLookupBool(&status, recipe, "EXTENDED_SOURCE_FITS");
     982        bool XRAD_OUTPUT = psMetadataLookupBool(&status, recipe, "RADIAL_APERTURES");
     983
     984        if (!pmSourceIOextnames(&headname, &dataname, &deteffname,
     985                XSRC_OUTPUT ? &xsrcname : NULL,
     986                XFIT_OUTPUT ? &xfitname : NULL,
     987                XRAD_OUTPUT ? &xradname : NULL,
     988                file, view)) {
    963989            return false;
    964990        }
     
    10251051                sources = pmSourcesRead_CMF_PS1_V3 (file->fits, hdu->header);
    10261052            }
     1053            if (!strcmp (exttype, "PS1_V4")) {
     1054                sources = pmSourcesRead_CMF_PS1_V4 (file->fits, hdu->header);
     1055            }
    10271056            if (!strcmp (exttype, "PS1_SV1")) {
    10281057                sources = pmSourcesRead_CMF_PS1_SV1 (file->fits, hdu->header);
     
    10341063                sources = pmSourcesRead_CMF_PS1_DV2 (file->fits, hdu->header);
    10351064            }
     1065
     1066            long *sourceIndex = NULL;
     1067            if (XSRC_OUTPUT || XFIT_OUTPUT || XRAD_OUTPUT) {
     1068                long seq_max = -1;
     1069                for (long i = sources->n -1; i >= 0; i--) {
     1070                    pmSource *source = sources->data[i];
     1071                    if (source->seq > seq_max) {
     1072                        seq_max = source->seq;
     1073                    }
     1074                }
     1075                sourceIndex = psAlloc((seq_max + 1) * sizeof(long));
     1076                for (long i = 0; i < seq_max; i++) {
     1077                    sourceIndex[i] = -1;
     1078                }
     1079                for (long i = 0; i < sources->n; i++) {
     1080                    pmSource *source = sources->data[i];
     1081                    sourceIndex[source->seq] = i;
     1082                }
     1083            }
     1084            if (XSRC_OUTPUT && xsrcname) {
     1085                if (!pmReadoutReadXSRC(file, exttype, hdu->header, xsrcname, sources, sourceIndex)) {
     1086                    // XXX: is this an error?
     1087                    psErrorClear();
     1088                }
     1089                psFree(xsrcname);
     1090            }
     1091            if (XFIT_OUTPUT && xfitname) {
     1092                if (!pmReadoutReadXFIT(file, exttype, hdu->header, xfitname, sources, sourceIndex)) {
     1093                    // XXX: is this an error?
     1094                    psErrorClear();
     1095                }
     1096                psFree(xfitname);
     1097            }
     1098            if (XRAD_OUTPUT && xradname) {
     1099                if (!pmReadoutReadXRAD(file, readout, exttype, hdu->header, xradname, sources, sourceIndex)) {
     1100                    // XXX: is this an error?
     1101                    psErrorClear();
     1102                }
     1103                psFree(xradname);
     1104            }
     1105            psFree(sourceIndex);
    10361106
    10371107            if (!pmReadoutReadDetEff(file->fits, readout, deteffname)) {
     
    11611231}
    11621232
    1163 
     1233// XXX: We might be able to macroize this and reuse for the other types
     1234
     1235static bool pmReadoutReadXSRC(pmFPAfile *file, char *exttype, psMetadata *hduHeader, psString xsrcname, psArray *sources, long *sourceIndex)
     1236{
     1237    if (!psFitsMoveExtName (file->fits, xsrcname)) {
     1238        psError(PS_ERR_UNKNOWN, false, "cannot find xsrc extension %s in %s", xsrcname, file->filename);
     1239        return false;
     1240    }
     1241
     1242    psMetadata *tableHeader = psFitsReadHeader(NULL, file->fits); // The FITS header
     1243    if (!tableHeader) psAbort("cannot read table header");
     1244
     1245    char *xtension = psMetadataLookupStr (NULL, tableHeader, "XTENSION");
     1246    if (!xtension) psAbort("cannot read table type");
     1247    if (strcmp (xtension, "BINTABLE")) {
     1248        psWarning ("no binary table in extension %s, skipping\n", xsrcname);
     1249        return false;
     1250    }
     1251
     1252    // XXX these are case-sensitive since the EXTYPE is case-sensitive
     1253    bool status = false;
     1254    if (file->type == PM_FPA_FILE_CMF) {
     1255        if (!strcmp (exttype, "PS1_SV1")) {
     1256            status  = pmSourcesRead_CMF_PS1_SV1_XSRC (file->fits, hduHeader, sources, sourceIndex);
     1257        }
     1258    }
     1259    psFree(tableHeader);
     1260    return status;
     1261}
     1262
     1263static bool pmReadoutReadXFIT(pmFPAfile *file, char *exttype, psMetadata *hduHeader, psString extname, psArray *sources, long *sourceIndex)
     1264{
     1265    if (!psFitsMoveExtName (file->fits, extname)) {
     1266        psError(PS_ERR_UNKNOWN, false, "cannot find extension %s in %s", extname, file->filename);
     1267        return false;
     1268    }
     1269
     1270    psMetadata *tableHeader = psFitsReadHeader(NULL, file->fits); // The FITS header
     1271    if (!tableHeader) psAbort("cannot read table header");
     1272
     1273    char *xtension = psMetadataLookupStr (NULL, tableHeader, "XTENSION");
     1274    if (!xtension) psAbort("cannot read table type");
     1275    if (strcmp (xtension, "BINTABLE")) {
     1276        psWarning ("no binary table in extension %s, skipping\n", extname);
     1277        return false;
     1278    }
     1279
     1280    // XXX these are case-sensitive since the EXTYPE is case-sensitive
     1281    bool status = false;
     1282    if (file->type == PM_FPA_FILE_CMF) {
     1283        if (!strcmp (exttype, "PS1_SV1")) {
     1284            status  = pmSourcesRead_CMF_PS1_SV1_XFIT (file->fits, hduHeader, sources, sourceIndex);
     1285        }
     1286    }
     1287    psFree(tableHeader);
     1288    return status;
     1289}
     1290static bool pmReadoutReadXRAD(pmFPAfile *file, pmReadout *readout, char *exttype, psMetadata *hduHeader, psString extname, psArray *sources, long *sourceIndex)
     1291{
     1292    if (!psFitsMoveExtName (file->fits, extname)) {
     1293        psError(PS_ERR_UNKNOWN, false, "cannot find extension %s in %s", extname, file->filename);
     1294        return false;
     1295    }
     1296
     1297    psMetadata *tableHeader = psFitsReadHeader(NULL, file->fits); // The FITS header
     1298    if (!tableHeader) psAbort("cannot read table header");
     1299
     1300    char *xtension = psMetadataLookupStr (NULL, tableHeader, "XTENSION");
     1301    if (!xtension) psAbort("cannot read table type");
     1302    if (strcmp (xtension, "BINTABLE")) {
     1303        psWarning ("no binary table in extension %s, skipping\n", extname);
     1304        return false;
     1305    }
     1306
     1307    // XXX these are case-sensitive since the EXTYPE is case-sensitive
     1308    bool status = false;
     1309    if (file->type == PM_FPA_FILE_CMF) {
     1310        if (!strcmp (exttype, "PS1_SV1")) {
     1311            status  = pmSourcesRead_CMF_PS1_SV1_XRAD (file->fits, readout, hduHeader, sources, sourceIndex);
     1312        }
     1313    }
     1314    psFree(tableHeader);
     1315    return status;
     1316}
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmSourceIO.h

    r30621 r33415  
    6262bool pmSourcesWrite_CMF_PS1_V3_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe);
    6363
     64bool pmSourcesWrite_CMF_PS1_V4(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe);
     65bool pmSourcesWrite_CMF_PS1_V4_XSRC(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe);
     66bool pmSourcesWrite_CMF_PS1_V4_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname);
     67bool pmSourcesWrite_CMF_PS1_V4_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe);
     68
    6469bool pmSourcesWrite_CMF_PS1_SV1(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe);
    6570bool pmSourcesWrite_CMF_PS1_SV1_XSRC(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe);
     
    8691psArray *pmSourcesRead_CMF_PS1_V2 (psFits *fits, psMetadata *header);
    8792psArray *pmSourcesRead_CMF_PS1_V3 (psFits *fits, psMetadata *header);
     93psArray *pmSourcesRead_CMF_PS1_V4 (psFits *fits, psMetadata *header);
    8894psArray *pmSourcesRead_CMF_PS1_SV1 (psFits *fits, psMetadata *header);
     95bool pmSourcesRead_CMF_PS1_SV1_XSRC (psFits *fits, psMetadata *header, psArray *sources, long *);
     96bool pmSourcesRead_CMF_PS1_SV1_XFIT (psFits *fits, psMetadata *header, psArray *sources, long *);
     97bool pmSourcesRead_CMF_PS1_SV1_XRAD (psFits *fits, pmReadout *readout, psMetadata *header, psArray *sources, long *);
    8998psArray *pmSourcesRead_CMF_PS1_DV1 (psFits *fits, psMetadata *header);
    9099psArray *pmSourcesRead_CMF_PS1_DV2 (psFits *fits, psMetadata *header);
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmSourceIO_CMF.c.in

    r31670 r33415  
    5555// followed by a zero-size matrix, followed by the table data
    5656
    57 // # define MODE @CMFMODE@
    5857bool pmSourcesWrite_CMF_@CMFMODE@ (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe)
    5958{
     
    128127
    129128        @ALL@     psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG",           PS_DATA_F32, "magnitude in standard aperture",             source->apMag);
    130         @=PS1_V3@ psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG_RAW",       PS_DATA_F32, "magnitude in reported aperture",             source->apMagRaw);
     129        @>PS1_V2@ psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG_RAW",       PS_DATA_F32, "magnitude in reported aperture",             source->apMagRaw);
    131130        @ALL@     psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG_RADIUS",    PS_DATA_F32, "radius used for aperture mags",              outputs.apRadius);
    132131        @<PS1_V3@ psMetadataAdd (row, PS_LIST_TAIL, "PEAK_FLUX_AS_MAG", PS_DATA_F32, "Peak flux expressed as magnitude",           outputs.peakMag);
     
    139138        @>PS1_V1@ psMetadataAdd (row, PS_LIST_TAIL, "DEC_PSF",          PS_DATA_F64, "PSF DEC coordinate (degrees)",               outputs.dec);
    140139
    141         @=PS1_V3@ psMetadataAdd (row, PS_LIST_TAIL, "PEAK_FLUX_AS_MAG", PS_DATA_F32, "Peak flux expressed as magnitude",           outputs.peakMag);
     140        @>PS1_V2@ psMetadataAdd (row, PS_LIST_TAIL, "PEAK_FLUX_AS_MAG", PS_DATA_F32, "Peak flux expressed as magnitude",           outputs.peakMag);
    142141        @ALL@     psMetadataAdd (row, PS_LIST_TAIL, "SKY",              PS_DATA_F32, "Sky level",                                  source->sky);
    143142        @ALL@     psMetadataAdd (row, PS_LIST_TAIL, "SKY_SIGMA",        PS_DATA_F32, "Sigma of sky level",                         source->skyErr);
     
    151150        @ALL@     psMetadataAdd (row, PS_LIST_TAIL, "PSF_THETA",        PS_DATA_F32, "PSF orientation angle",                      outputs.psfTheta);
    152151        @ALL@     psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF",           PS_DATA_F32, "PSF coverage/quality factor (bad)",          source->pixWeightNotBad);
    153         @=PS1_V3@ psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF_PERFECT",   PS_DATA_F32, "PSF coverage/quality factor (poor)",         source->pixWeightNotPoor);
     152        @>PS1_V2@ psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF_PERFECT",   PS_DATA_F32, "PSF coverage/quality factor (poor)",         source->pixWeightNotPoor);
    154153        @ALL@     psMetadataAdd (row, PS_LIST_TAIL, "PSF_NDOF",         PS_DATA_S32, "degrees of freedom",                         outputs.nDOF);
    155154        @ALL@     psMetadataAdd (row, PS_LIST_TAIL, "PSF_NPIX",         PS_DATA_S32, "number of pixels in fit",                    outputs.nPix);
     
    159158        @ALL@     psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_YY",       PS_DATA_F32, "second moments (Y*Y)",                       moments.Myy);
    160159
    161         @=PS1_V3@ psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M3C",      PS_DATA_F32, "third momemt cos theta",                     moments.M_c3);
    162         @=PS1_V3@ psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M3S",      PS_DATA_F32, "third momemt sin theta",                     moments.M_s3);
    163         @=PS1_V3@ psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M4C",      PS_DATA_F32, "fourth momemt cos theta",                    moments.M_c4);
    164         @=PS1_V3@ psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M4S",      PS_DATA_F32, "fourth momemt sin theta",                    moments.M_s4);
    165 
    166         @=PS1_V3@ psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_R1",       PS_DATA_F32, "first radial moment",                        moments.Mrf);
    167         @=PS1_V3@ psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_RH",       PS_DATA_F32, "half radial moment",                         moments.Mrh);
    168         @=PS1_V3@ psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX",        PS_DATA_F32, "Kron Flux (in 2.5 R1)",                      moments.Krf);
    169         @=PS1_V3@ psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_ERR",    PS_DATA_F32, "Kron Flux Error",                            moments.dKrf);
    170         @=PS1_V3@ psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_INNER",  PS_DATA_F32, "Kron Flux (in 2.5 R1)",                      moments.Kinner);
    171         @=PS1_V3@ psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_OUTER",  PS_DATA_F32, "Kron Flux (in 2.5 R1)",                      moments.Kouter);
    172 
    173         // Do NOT write these : not consistent with the definition of PS1_V3 in Ohana/src/libautocode/dev/cmf-ps1-v3.d
    174         // psMetadataAdd (row, PS_LIST_TAIL, "KRON_CORE_FLUX",   PS_DATA_F32, "Kron Flux (in 1.0 R1)",                      moments.KronCore);
    175         // psMetadataAdd (row, PS_LIST_TAIL, "KRON_CORE_ERROR",  PS_DATA_F32, "Kron Error (in 1.0 R1)",                     moments.KronCoreErr);
     160        @>PS1_V2@ psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M3C",      PS_DATA_F32, "third momemt cos theta",                     moments.M_c3);
     161        @>PS1_V2@ psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M3S",      PS_DATA_F32, "third momemt sin theta",                     moments.M_s3);
     162        @>PS1_V2@ psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M4C",      PS_DATA_F32, "fourth momemt cos theta",                    moments.M_c4);
     163        @>PS1_V2@ psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M4S",      PS_DATA_F32, "fourth momemt sin theta",                    moments.M_s4);
     164
     165        @>PS1_V2@ psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_R1",       PS_DATA_F32, "first radial moment",                        moments.Mrf);
     166        @>PS1_V2@ psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_RH",       PS_DATA_F32, "half radial moment",                         moments.Mrh);
     167        @>PS1_V2@ psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX",        PS_DATA_F32, "Kron Flux (in 2.5 R1)",                      moments.Krf);
     168        @>PS1_V2@ psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_ERR",    PS_DATA_F32, "Kron Flux Error",                            moments.dKrf);
     169        @>PS1_V2@ psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_INNER",  PS_DATA_F32, "Kron Flux (in 2.5 R1)",                      moments.Kinner);
     170        @>PS1_V2@ psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_OUTER",  PS_DATA_F32, "Kron Flux (in 2.5 R1)",                      moments.Kouter);
     171
     172        @>PS1_V3@ psMetadataAdd (row, PS_LIST_TAIL, "SKY_LIMIT_RAD",    PS_DATA_F32, "Radius where object hits sky",               source->skyRadius);
     173        @>PS1_V3@ psMetadataAdd (row, PS_LIST_TAIL, "SKY_LIMIT_FLUX",   PS_DATA_F32, "Flux / pix where object hits sky",           source->skyFlux);
     174        @>PS1_V3@ psMetadataAdd (row, PS_LIST_TAIL, "SKY_LIMIT_SLOPE",  PS_DATA_F32, "d(Flux/pix)/dRadius where object hits sky",  source->skySlope);
     175
    176176        @ALL@     psMetadataAdd (row, PS_LIST_TAIL, "FLAGS",            PS_DATA_U32, "psphot analysis flags",                      source->mode);
    177         @=PS1_V3@ psMetadataAdd (row, PS_LIST_TAIL, "FLAGS2",           PS_DATA_U32, "psphot analysis flags",                      source->mode2);
    178         @=PS1_V3@ psMetadataAdd (row, PS_LIST_TAIL, "PADDING2",         PS_DATA_S32, "more padding", 0);
     177        @>PS1_V2@ psMetadataAdd (row, PS_LIST_TAIL, "FLAGS2",           PS_DATA_U32, "psphot analysis flags",                      source->mode2);
     178        @>PS1_V2@ psMetadataAdd (row, PS_LIST_TAIL, "PADDING2",         PS_DATA_S32, "more padding", 0);
    179179
    180180        // XXX not sure how to get this : need to load Nimages with weight?
     
    222222
    223223// read in a readout from the fits file
    224 psArray *pmSourcesRead_CMF_PS1_V3 (psFits *fits, psMetadata *header)
     224psArray *pmSourcesRead_CMF_@CMFMODE@ (psFits *fits, psMetadata *header)
    225225{
    226226    PS_ASSERT_PTR_NON_NULL(fits, false);
     
    281281        // XXX use these to determine PAR[PM_PAR_I0]?
    282282        @ALL@     source->psfMag    = psMetadataLookupF32 (&status, row, "PSF_INST_MAG");
    283         @ALL@     source->psfMagErr    = psMetadataLookupF32 (&status, row, "PSF_INST_MAG_SIG");
     283        @ALL@     source->psfMagErr = psMetadataLookupF32 (&status, row, "PSF_INST_MAG_SIG");
    284284        @ALL@     source->apMag     = psMetadataLookupF32 (&status, row, "AP_MAG");
     285        @>PS1_V2@ source->apMagRaw  = psMetadataLookupF32 (&status, row, "AP_MAG_RAW");
     286
     287        // XXX use these to determine PAR[PM_PAR_I0] if they exist?
     288        @>PS1_V2@ source->psfFlux   = psMetadataLookupF32 (&status, row, "PSF_INST_FLUX");
     289        @>PS1_V2@ source->psfFluxErr= psMetadataLookupF32 (&status, row, "PSF_INST_FLUX_SIG");
    285290
    286291        // XXX this scaling is incorrect: does not include the 2 \pi AREA factor
     
    288293        @ALL@     dPAR[PM_PAR_I0]   = (isfinite(source->psfMag)) ? PAR[PM_PAR_I0] * source->psfMagErr : NAN;
    289294
    290         pmPSF_AxesToModel (PAR, axes);
     295        pmPSF_AxesToModel (PAR, axes, modelType);
    291296
    292297        @ALL@     float peakMag     = psMetadataLookupF32 (&status, row, "PEAK_FLUX_AS_MAG");
     
    303308
    304309        @ALL@     source->pixWeightNotBad = psMetadataLookupF32 (&status, row, "PSF_QF");
    305         @=PS1_V3@ source->pixWeightNotPoor = psMetadataLookupF32 (&status, row, "PSF_QF_PERFECT");
     310        @>PS1_V2@ source->pixWeightNotPoor = psMetadataLookupF32 (&status, row, "PSF_QF_PERFECT");
    306311        @ALL@     source->crNsigma  = psMetadataLookupF32 (&status, row, "CR_NSIGMA");
    307312        @ALL@     source->extNsigma = psMetadataLookupF32 (&status, row, "EXT_NSIGMA");
     
    321326        @ALL@     source->moments->Myy = psMetadataLookupF32 (&status, row, "MOMENTS_YY");
    322327
    323         @=PS1_V3@ source->moments->Mrf         = psMetadataLookupF32 (&status, row, "MOMENTS_R1");
    324         @=PS1_V3@ source->moments->Mrh         = psMetadataLookupF32 (&status, row, "MOMENTS_RH");
    325         @=PS1_V3@ source->moments->KronFlux    = psMetadataLookupF32 (&status, row, "KRON_FLUX");
    326         @=PS1_V3@ source->moments->KronFluxErr = psMetadataLookupF32 (&status, row, "KRON_FLUX_ERR");
    327 
    328         @=PS1_V3@ source->moments->KronFinner  = psMetadataLookupF32 (&status, row, "KRON_FLUX_INNER");
    329         @=PS1_V3@ source->moments->KronFouter  = psMetadataLookupF32 (&status, row, "KRON_FLUX_OUTER");
     328        @>PS1_V2@ source->moments->Mrf         = psMetadataLookupF32 (&status, row, "MOMENTS_R1");
     329        @>PS1_V2@ source->moments->Mrh         = psMetadataLookupF32 (&status, row, "MOMENTS_RH");
     330        @>PS1_V2@ source->moments->KronFlux    = psMetadataLookupF32 (&status, row, "KRON_FLUX");
     331        @>PS1_V2@ source->moments->KronFluxErr = psMetadataLookupF32 (&status, row, "KRON_FLUX_ERR");
     332
     333        @>PS1_V2@ source->moments->KronFinner  = psMetadataLookupF32 (&status, row, "KRON_FLUX_INNER");
     334        @>PS1_V2@ source->moments->KronFouter  = psMetadataLookupF32 (&status, row, "KRON_FLUX_OUTER");
     335
     336        @>PS1_V3@ source->skyRadius            = psMetadataLookupF32 (&status, row, "SKY_LIMIT_RAD");
     337        @>PS1_V3@ source->skyFlux              = psMetadataLookupF32 (&status, row, "SKY_LIMIT_FLUX");
     338        @>PS1_V3@ source->skySlope             = psMetadataLookupF32 (&status, row, "SKY_LIMIT_SLOPE");
    330339
    331340        // XXX we do not save all of the 3rd and 4th moment parameters. when we load in data,
    332341        // we are storing enough information so the output will be consistent with the input
    333         @=PS1_V3@ source->moments->Mxxx = +1.0 * psMetadataLookupF32 (&status, row, "MOMENTS_M3C");
    334         @=PS1_V3@ source->moments->Mxxy = 0.0;
    335         @=PS1_V3@ source->moments->Mxyy = 0.0;
    336         @=PS1_V3@ source->moments->Myyy = -1.0 * psMetadataLookupF32 (&status, row, "MOMENTS_M3S");
    337 
    338         @=PS1_V3@ source->moments->Mxxxx = +1.00 * psMetadataLookupF32 (&status, row, "MOMENTS_M4C");
    339         @=PS1_V3@ source->moments->Mxxxy = 0.0;
    340         @=PS1_V3@ source->moments->Mxxyy = 0.0;
    341         @=PS1_V3@ source->moments->Mxyyy = -0.25 * psMetadataLookupF32 (&status, row, "MOMENTS_M4S");
    342         @=PS1_V3@ source->moments->Myyyy = 0.0;
     342        @>PS1_V2@ source->moments->Mxxx = +1.0 * psMetadataLookupF32 (&status, row, "MOMENTS_M3C");
     343        @>PS1_V2@ source->moments->Mxxy = 0.0;
     344        @>PS1_V2@ source->moments->Mxyy = 0.0;
     345        @>PS1_V2@ source->moments->Myyy = -1.0 * psMetadataLookupF32 (&status, row, "MOMENTS_M3S");
     346
     347        @>PS1_V2@ source->moments->Mxxxx = +1.00 * psMetadataLookupF32 (&status, row, "MOMENTS_M4C");
     348        @>PS1_V2@ source->moments->Mxxxy = 0.0;
     349        @>PS1_V2@ source->moments->Mxxyy = 0.0;
     350        @>PS1_V2@ source->moments->Mxyyy = -0.25 * psMetadataLookupF32 (&status, row, "MOMENTS_M4S");
     351        @>PS1_V2@ source->moments->Myyyy = 0.0;
    343352
    344353        @ALL@     source->mode = psMetadataLookupU32 (&status, row, "FLAGS");
    345         @=PS1_V3@ source->mode2 = psMetadataLookupU32 (&status, row, "FLAGS2");
     354        @>PS1_V2@ source->mode2 = psMetadataLookupU32 (&status, row, "FLAGS2");
    346355        assert (status);
    347356
     
    353362}
    354363
    355 bool pmSourcesWrite_CMF_PS1_V3_XSRC (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe)
     364bool pmSourcesWrite_CMF_@CMFMODE@_XSRC (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe)
    356365{
    357366    bool status;
     
    541550
    542551// XXX this layout is still the same as PS1_DEV_1
    543 bool pmSourcesWrite_CMF_PS1_V3_XFIT (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname)
     552bool pmSourcesWrite_CMF_@CMFMODE@_XFIT (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname)
    544553{
    545554
     
    590599            assert (model);
    591600
     601            // pmSourceExtFitPars *extPars = source->extFitPars->data[j];
     602            // assert (extPars);
     603
    592604            // skip models which were not actually fitted
    593605            if (model->flags & PM_MODEL_STATUS_BADARGS) continue;
     
    600612            yErr = dPAR[PM_PAR_YPOS];
    601613
    602             axes = pmPSF_ModelToAxes (PAR, 20.0);
     614            axes = pmPSF_ModelToAxes (PAR, 20.0, model->type);
     615
     616            float kronFlux = source->moments ? source->moments->KronFlux : NAN;
     617            float kronMag = isfinite(kronFlux) ? -2.5*log10(kronFlux) : NAN;
    603618
    604619            row = psMetadataAlloc ();
     
    612627            psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_INST_MAG",     0, "EXT fit instrumental magnitude",             model->mag);
    613628            psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_INST_MAG_SIG", 0, "Sigma of PSF instrumental magnitude",        model->magErr);
     629
     630            // psMetadataAddF32 (row, PS_LIST_TAIL, "MOMENTS_XX",       0, "second moment in x",                      extPars->Mxx);
     631            // psMetadataAddF32 (row, PS_LIST_TAIL, "MOMENTS_XY",       0, "second moment in x,y",                    extPars->Mxy);
     632            // psMetadataAddF32 (row, PS_LIST_TAIL, "MOMENTS_YY",       0, "second moment in y",                      extPars->Myy);
     633            // psMetadataAddF32 (row, PS_LIST_TAIL, "MOMENTS_R1",       0, "first radial moment",                     extPars->Mrf);
     634            // psMetadataAddF32 (row, PS_LIST_TAIL, "MOMENTS_RH",       0, "half radial moment",                      extPars->Mrh);
     635
     636            psMetadataAddF32 (row, PS_LIST_TAIL, "PSF_INST_MAG",     0, "PSF fit instrumental magnitude",             source->psfMag);
     637            psMetadataAddF32 (row, PS_LIST_TAIL, "AP_MAG",           0, "PSF-sized aperture magnitude",               source->apMag);
     638            psMetadataAddF32 (row, PS_LIST_TAIL, "KRON_MAG",         0, "Kron Mag",                                   kronMag);
    614639
    615640            psMetadataAddF32 (row, PS_LIST_TAIL, "NPARAMS",          0, "number of model parameters",                 model->params->n);
     
    673698}
    674699
    675 bool pmSourcesWrite_CMF_PS1_V3_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe)
     700bool pmSourcesWrite_CMF_@CMFMODE@_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe)
    676701{
    677702    return true;
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmSourceIO_CMF_PS1_DV1.c

    r31451 r33415  
    263263        dPAR[PM_PAR_I0]   = (isfinite(source->psfMag)) ? PAR[PM_PAR_I0] * source->psfMagErr : NAN;
    264264
    265         pmPSF_AxesToModel (PAR, axes);
     265        pmPSF_AxesToModel (PAR, axes, modelType);
    266266
    267267        float peakMag     = psMetadataLookupF32 (&status, row, "PEAK_FLUX_AS_MAG");
     
    547547            yErr = dPAR[PM_PAR_YPOS];
    548548
    549             axes = pmPSF_ModelToAxes (PAR, 20.0);
     549            axes = pmPSF_ModelToAxes (PAR, 20.0, model->type);
    550550
    551551            row = psMetadataAlloc ();
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmSourceIO_CMF_PS1_DV2.c

    r31451 r33415  
    281281        dPAR[PM_PAR_I0]   = (isfinite(source->psfMag)) ? PAR[PM_PAR_I0] * source->psfMagErr : NAN;
    282282
    283         pmPSF_AxesToModel (PAR, axes);
     283        pmPSF_AxesToModel (PAR, axes, modelType);
    284284
    285285        float peakMag     = psMetadataLookupF32 (&status, row, "PEAK_FLUX_AS_MAG");
     
    572572            yErr = dPAR[PM_PAR_YPOS];
    573573
    574             axes = pmPSF_ModelToAxes (PAR, 20.0);
     574            axes = pmPSF_ModelToAxes (PAR, 20.0, model->type);
    575575
    576576            row = psMetadataAlloc ();
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmSourceIO_CMF_PS1_SV1.c

    r31451 r33415  
    280280        dPAR[PM_PAR_I0]   = (isfinite(source->psfMag)) ? PAR[PM_PAR_I0] * source->psfMagErr : NAN;
    281281
    282         pmPSF_AxesToModel (PAR, axes);
     282        pmPSF_AxesToModel (PAR, axes, modelType);
    283283
    284284        float peakMag     = psMetadataLookupF32 (&status, row, "PEAK_FLUX_AS_MAG");
     
    539539}
    540540
     541bool pmSourcesRead_CMF_PS1_SV1_XSRC(psFits *fits, psMetadata *hduHeader, psArray *sources, long *sourceIndex)
     542{
     543    PS_ASSERT_PTR_NON_NULL(fits, false);
     544    PS_ASSERT_PTR_NON_NULL(sources, false);
     545
     546    bool status;
     547    long numSources = psFitsTableSize(fits); // Number of sources in table
     548    if (numSources == 0) {
     549        psError(psErrorCodeLast(), false, "XSRC Table contains no entries\n");
     550        return false;
     551    }
     552
     553    // petrosian mags are not saved, we need to calculate fluxes. For this we need exptime and zero point
     554    float zeropt = psMetadataLookupF32(&status, hduHeader, "FPA.ZP");
     555    float exptime = psMetadataLookupF32(&status, hduHeader, "EXPTIME");
     556    float magOffset = zeropt + 2.5*log10(exptime);
     557
     558    for (long i = 0; i < numSources; i++) {
     559        psMetadata *row = psFitsReadTableRow(fits, i); // Table row
     560        if (!row) {
     561            psError(psErrorCodeLast(), false, "Unable to read row %ld of sources", i);
     562            psFree(row);
     563            return false;
     564        }
     565        // Find the source with this sequence number.
     566        // XXX: I am assuming that sources is sorted in order of seq
     567        long seq = psMetadataLookupU32 (&status, row, "IPP_IDET");
     568        pmSource *source = NULL;
     569#ifndef ASSUME_SORTED
     570        long j = seq < sources->n ? seq : sources->n - 1;
     571        for (; j >= 0; j--) {
     572            source = sources->data[j];
     573            if (source->seq == seq) {
     574                break;
     575            }
     576        }
     577#else
     578        long j = sourceIndex[seq];
     579        psAssert(j >= 0 && j < sources->n, "invalid sourceIndex");
     580        source = sources->data[j];
     581#endif
     582        if (!source) {
     583            psError(PS_ERR_UNKNOWN, false, "Failed to find source for row %ld sequence number %ld\n", i, seq);
     584            psFree(row);
     585            return false;
     586        }
     587
     588        if (!source->extpars) {
     589            source->extpars = pmSourceExtendedParsAlloc ();
     590        }
     591        pmSourceExtendedPars *extpars = source->extpars;
     592
     593        // Assume that X_EXT Y_EXT and sigmas match the psf src so skip
     594
     595        // We don't have enough information to calculate the major and minor axis. Set major to 1. Should we scale this by
     596        // psf size or something?
     597        extpars->axes.major = 1.0;
     598        extpars->axes.minor = extpars->axes.major * psMetadataLookupF32(&status, row, "F25_ARATIO");
     599        extpars->axes.theta = psMetadataLookupF32(&status, row, "F25_THETA");
     600
     601        float mag = psMetadataLookupF32(&status, row, "PETRO_MAG");
     602        float magErr = psMetadataLookupF32(&status, row, "PETRO_MAG_ERR");
     603        if (isfinite(mag)) {
     604            extpars->petrosianFlux    = pow(10., (magOffset - mag) / 2.5);
     605            if (isfinite(magErr)) {
     606                extpars->petrosianFluxErr = extpars->petrosianFlux / magErr;
     607            }
     608        }
     609
     610        extpars->petrosianRadius   = psMetadataLookupF32(&status, row, "PETRO_RADIUS");
     611        extpars->petrosianRadiusErr= psMetadataLookupF32(&status, row, "PETRO_RADIUS_ERR");
     612        extpars->petrosianR50      = psMetadataLookupF32(&status, row, "PETRO_RADIUS_50");
     613        extpars->petrosianR50Err   = psMetadataLookupF32(&status, row, "PETRO_RADIUS_50_ERR");
     614        extpars->petrosianR90      = psMetadataLookupF32(&status, row, "PETRO_RADIUS_90");
     615        extpars->petrosianR90Err   = psMetadataLookupF32(&status, row, "PETRO_RADIUS_90_ERR");
     616        extpars->petrosianFill     = psMetadataLookupF32(&status, row, "PETRO_FILL");
     617
     618        psVector *radSB   = psMetadataLookupVector(&status, row, "PROF_SB");
     619        psVector *radFlux = psMetadataLookupVector(&status, row, "PROF_FLUX");
     620        psVector *radFill = psMetadataLookupVector(&status, row, "PROF_FILL");
     621
     622        if (radSB && radSB->n > 0) {
     623            extpars->radProfile = pmSourceRadialProfileAlloc();
     624            extpars->radProfile->binSB   = psMemIncrRefCounter(radSB);
     625            extpars->radProfile->binSum   = psMemIncrRefCounter(radFlux);
     626            extpars->radProfile->binFill = psMemIncrRefCounter(radFill);
     627        }
     628
     629        psFree(row);
     630    }
     631
     632    return true;
     633}
     634
    541635// XXX this layout is still the same as PS1_DEV_1
    542636bool pmSourcesWrite_CMF_PS1_SV1_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname)
     
    607701            yErr = dPAR[PM_PAR_YPOS];
    608702
    609             axes = pmPSF_ModelToAxes (PAR, 20.0);
     703            axes = pmPSF_ModelToAxes (PAR, 20.0, model->type);
    610704
    611705            row = psMetadataAlloc ();
     
    684778    psFree (outhead);
    685779    psFree (table);
     780    return true;
     781}
     782
     783bool pmSourcesRead_CMF_PS1_SV1_XFIT(psFits *fits, psMetadata *hduHeader, psArray *sources, long *sourceIndex)
     784{
     785    PS_ASSERT_PTR_NON_NULL(fits, false);
     786    PS_ASSERT_PTR_NON_NULL(sources, false);
     787
     788    bool status;
     789    long numSources = psFitsTableSize(fits); // Number of sources in table
     790    if (numSources == 0) {
     791        psError(psErrorCodeLast(), false, "XFIT Table contains no entries\n");
     792        return false;
     793    }
     794
     795    for (long i = 0; i < numSources; i++) {
     796        psMetadata *row = psFitsReadTableRow(fits, i); // Table row
     797        if (!row) {
     798            psError(psErrorCodeLast(), false, "Unable to read row %ld of sources", i);
     799            psFree(row);
     800            return false;
     801        }
     802        // Find the source with this sequence number.
     803        // XXX: I am assuming that sources is sorted in order of seq.
     804        long seq = psMetadataLookupU32 (&status, row, "IPP_IDET");
     805        long j = seq < sources->n ? seq : sources->n - 1;
     806        pmSource *source = NULL;
     807        for (; j >= 0; j--) {
     808            source = sources->data[j];
     809            if (source->seq == seq) {
     810                break;
     811            }
     812        }
     813        if (!source) {
     814            psError(PS_ERR_UNKNOWN, false, "Failed to find source for row %ld sequence number %ld\n", i, seq);
     815            psFree(row);
     816            return false;
     817        }
     818        if (!source->modelFits) {
     819            // XXX: where to find the number of models to expect?
     820            source->modelFits = psArrayAllocEmpty(5);
     821        }
     822        psString modelName = psMetadataLookupStr(&status, row, "MODEL_TYPE");
     823        if (!modelName) {
     824            psError(PS_ERR_UNKNOWN, true, "Failed to find model name for row %ld\n", i);
     825            psFree(row);
     826            return false;
     827        }
     828        pmModelType modelType = pmModelClassGetType(modelName);
     829        if (modelType < 0) {
     830            psError(PS_ERR_UNKNOWN, true, "Failed to find model type for %s\n", modelName);
     831            psFree(row);
     832            return false;
     833        }
     834        pmModel *model = pmModelAlloc(modelType);
     835
     836        psF32 *PAR = model->params->data.F32;
     837        psF32 *dPAR = model->dparams->data.F32;
     838
     839        PAR[PM_PAR_XPOS] = psMetadataLookupF32(&status, row, "X_EXT");
     840        PAR[PM_PAR_YPOS] = psMetadataLookupF32(&status, row, "Y_EXT");
     841        dPAR[PM_PAR_XPOS] = psMetadataLookupF32(&status, row, "X_EXT_SIG");
     842        dPAR[PM_PAR_YPOS] = psMetadataLookupF32(&status, row, "Y_EXT_SIG");
     843
     844        model->mag = psMetadataLookupF32(&status, row, "EXT_INST_MAG");
     845        model->magErr = psMetadataLookupF32(&status, row, "EXT_INST_MAG_SIG");
     846
     847        psEllipseAxes axes;
     848        axes.major = psMetadataLookupF32(&status, row, "EXT_WIDTH_MAJ");
     849        axes.minor = psMetadataLookupF32(&status, row, "EXT_WIDTH_MIN");
     850        axes.theta = psMetadataLookupF32(&status, row, "EXT_THETA");
     851        if (!pmPSF_AxesToModel(PAR, axes, modelType)) {
     852            // Do we need to fail here or can this happen?
     853            psError(PS_ERR_UNKNOWN, false, "Failed to convert psf axes to model");
     854            psFree(model);
     855            psFree(row);
     856            return false;
     857        }
     858        // XXX: clean this up
     859        if (model->params->n > 7) {
     860            PAR[7] = psMetadataLookupF32(&status, row, "EXT_PAR_07");
     861        }
     862        // read the covariance matrix
     863        int nparams = model->params->n;
     864        psImage *covar = psImageAlloc(nparams, nparams, PS_TYPE_F32);
     865        for (int y = 0; y < nparams; y++) {
     866            for (int x = 0; x < nparams; x++) {
     867                char name[64];
     868                snprintf(name, 64, "EXT_COVAR_%02d_%02d", y, x);
     869                covar->data.F32[y][x] = psMetadataLookupF32(&status, row, name);
     870            }
     871        }
     872        model->covar = covar;
     873
     874        psArrayAdd(source->modelFits, 1, model);
     875        psFree(model);
     876
     877        psFree(row);
     878    }
     879
    686880    return true;
    687881}
     
    8311025    return true;
    8321026}
     1027
     1028bool pmSourcesRead_CMF_PS1_SV1_XRAD(psFits *fits, pmReadout *readout, psMetadata *hduHeader, psArray *sources, long *sourceIndex)
     1029{
     1030    PS_ASSERT_PTR_NON_NULL(fits, false);
     1031    PS_ASSERT_PTR_NON_NULL(sources, false);
     1032
     1033    bool status;
     1034    long numSources = psFitsTableSize(fits); // Number of sources in table
     1035    if (numSources == 0) {
     1036        psError(psErrorCodeLast(), false, "XRAD Table contains no entries\n");
     1037        return false;
     1038    }
     1039
     1040    long       seq_first = -1;
     1041    long       seq_last = -1;
     1042    psVector   *fwhmValues = psVectorAllocEmpty(10, PS_TYPE_F32);
     1043    long       max_entries = -1;
     1044    long       num_entries = -1;
     1045
     1046    for (long i = 0; i < numSources; i++) {
     1047        psMetadata *row = psFitsReadTableRow(fits, i); // Table row
     1048        if (!row) {
     1049            psError(psErrorCodeLast(), false, "Unable to read row %ld of sources", i);
     1050            psFree(row);
     1051            return false;
     1052        }
     1053        // Find the source with this sequence number.
     1054        // XXX: I am assuming that sources is sorted in order of seq.
     1055        long seq = psMetadataLookupU32 (&status, row, "IPP_IDET");
     1056        long j = seq < sources->n ? seq : sources->n - 1;
     1057        pmSource *source = NULL;
     1058        for (; j >= 0; j--) {
     1059            source = sources->data[j];
     1060            if (source->seq == seq) {
     1061                break;
     1062            }
     1063        }
     1064        if (!source) {
     1065            psError(PS_ERR_UNKNOWN, false, "Failed to find source for row %ld sequence number %ld\n", i, seq);
     1066            psFree(row);
     1067            return false;
     1068        }
     1069        if (seq_first == -1) {
     1070            seq_first = seq;
     1071        }
     1072        if (seq == seq_first) {
     1073            psF32 value = psMetadataLookupF32(&status, row, "PSF_FWHM");
     1074            psVectorAppend(fwhmValues, value);
     1075        }
     1076        if (seq == seq_last) {
     1077            num_entries++;
     1078        } else {
     1079            num_entries = 1;
     1080            seq_last = seq;
     1081        }
     1082        if (num_entries > max_entries) {
     1083            max_entries = num_entries;
     1084        }
     1085
     1086        if (!source->radialAper) {
     1087            // XXX: where to find the number of models to expect?
     1088            source->radialAper = psArrayAllocEmpty(5);
     1089        }
     1090        pmSourceRadialApertures *radialAper = pmSourceRadialAperturesAlloc();
     1091
     1092        radialAper->flux = psMemIncrRefCounter(psMetadataLookupVector(&status, row, "APER_FLUX"));
     1093        radialAper->fluxStdev = psMemIncrRefCounter(psMetadataLookupVector(&status, row, "APER_FLUX_STDEV"));
     1094        radialAper->fluxErr = psMemIncrRefCounter(psMetadataLookupVector(&status, row, "APER_FLUX_ERR"));
     1095        radialAper->fill = psMemIncrRefCounter(psMetadataLookupVector(&status, row, "APER_FILL"));
     1096
     1097        psArrayAdd(source->radialAper, 1, radialAper);
     1098
     1099        psFree(radialAper);
     1100        psFree(row);
     1101    }
     1102
     1103    // check for consistency between the length of fwhmValues and the maximum number of entries for each row
     1104    if (fwhmValues->n != max_entries) {
     1105        psError(PS_ERR_PROGRAMMING, true, "number of PSF_FWHM values found %ld does not match expected number: %ld\n",
     1106            fwhmValues->n, max_entries);
     1107        psAssert(0, "fixme");
     1108    }
     1109
     1110    if (!readout->analysis) {
     1111        readout->analysis = psMetadataAlloc();
     1112    }
     1113
     1114    psMetadataAddVector(readout->analysis, PS_LIST_TAIL, "STACK.PSF.FWHM.VALUES", PS_META_REPLACE, "PSF sizes", fwhmValues);
     1115    psFree(fwhmValues);
     1116
     1117    return true;
     1118}
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmSourceIO_CMP.c

    r31451 r33415  
    135135        lsky = (source->sky < 1.0) ? 0.0 : log10(source->sky);
    136136
    137         axes = pmPSF_ModelToAxes (PAR, 20.0);
     137        axes = pmPSF_ModelToAxes (PAR, 20.0, model->type);
    138138
    139139        float psfMagErr = isfinite(source->psfMagErr) ? source->psfMagErr : 999;
     
    293293                goto skip_source;
    294294
    295             pmPSF_AxesToModel (PAR, axes);
     295            pmPSF_AxesToModel (PAR, axes, modelType);
    296296
    297297            psArrayAdd (sources, 100, source);
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmSourceIO_OBJ.c

    r29004 r33415  
    9191        }
    9292
    93         axes = pmPSF_ModelToAxes (PAR, 20.0);
     93        axes = pmPSF_ModelToAxes (PAR, 20.0, model->type);
    9494
    9595        psLineInit (line);
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmSourceIO_PS1_CAL_0.c

    r31451 r33415  
    113113            yErr = dPAR[PM_PAR_YPOS];
    114114            if (isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX])) {
    115                 axes = pmPSF_ModelToAxes (PAR, 20.0);
     115                axes = pmPSF_ModelToAxes (PAR, 20.0, model->type);
    116116            } else {
    117117                axes.major = NAN;
     
    288288        dPAR[PM_PAR_I0]   = (isfinite(source->psfMag)) ? PAR[PM_PAR_I0] * source->psfMagErr : NAN;
    289289
    290         pmPSF_AxesToModel (PAR, axes);
     290        pmPSF_AxesToModel (PAR, axes, modelType);
    291291
    292292        float peakMag     = psMetadataLookupF32 (&status, row, "PEAK_FLUX_AS_MAG");
     
    618618            yErr = dPAR[PM_PAR_YPOS];
    619619
    620             axes = pmPSF_ModelToAxes (PAR, 20.0);
     620            axes = pmPSF_ModelToAxes (PAR, 20.0, model->type);
    621621
    622622            // generate RA,DEC
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmSourceIO_PS1_DEV_0.c

    r31451 r33415  
    8989            yErr = dPAR[PM_PAR_YPOS];
    9090
    91             axes = pmPSF_ModelToAxes (PAR, 20.0);
     91            axes = pmPSF_ModelToAxes (PAR, 20.0, model->type);
    9292        } else {
    9393            // XXX: This code seg faults if source->peak is NULL.
     
    214214        source->psfMagErr    = psMetadataLookupF32 (&status, row, "PSF_INST_MAG_SIG");
    215215
    216         pmPSF_AxesToModel (PAR, axes);
     216        pmPSF_AxesToModel (PAR, axes, modelType);
    217217
    218218        float peakMag = psMetadataLookupF32 (&status, row, "PEAK_FLUX_AS_MAG");
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmSourceIO_PS1_DEV_1.c

    r31451 r33415  
    9595            yErr = dPAR[PM_PAR_YPOS];
    9696            if (isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX])) {
    97                 axes = pmPSF_ModelToAxes (PAR, 20.0);
     97                axes = pmPSF_ModelToAxes (PAR, 20.0, model->type);
    9898            } else {
    9999                axes.major = NAN;
     
    257257        dPAR[PM_PAR_I0]   = (isfinite(source->psfMag)) ? PAR[PM_PAR_I0] * source->psfMagErr : NAN;
    258258
    259         pmPSF_AxesToModel (PAR, axes);
     259        pmPSF_AxesToModel (PAR, axes, modelType);
    260260
    261261        float peakMag     = psMetadataLookupF32 (&status, row, "PEAK_FLUX_AS_MAG");
     
    522522            yErr = dPAR[PM_PAR_YPOS];
    523523
    524             axes = pmPSF_ModelToAxes (PAR, 20.0);
     524            axes = pmPSF_ModelToAxes (PAR, 20.0, model->type);
    525525
    526526            row = psMetadataAlloc ();
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmSourceIO_SMPDATA.c

    r31451 r33415  
    9292            lsky = (source->sky < 1.0) ? 0.0 : log10(source->sky);
    9393
    94             axes = pmPSF_ModelToAxes (PAR, 20.0);
     94            axes = pmPSF_ModelToAxes (PAR, 20.0, model->type);
    9595
    9696        } else {
     
    190190        axes.theta       = psMetadataLookupF32 (&status, row, "THETA");
    191191
    192         pmPSF_AxesToModel (PAR, axes);
     192        pmPSF_AxesToModel (PAR, axes, modelType);
    193193
    194194        source->psfMag = psMetadataLookupF32 (&status, row, "MAG_RAW") - ZERO_POINT;
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmSourceIO_SX.c

    r31451 r33415  
    8181        // pmSourceSextractType (source, &type, &flags);
    8282
    83         axes = pmPSF_ModelToAxes (PAR, 20.0);
     83        axes = pmPSF_ModelToAxes (PAR, 20.0, model->type);
    8484
    8585        psLineInit (line);
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmSourceMasks.h

    r31670 r33415  
    4646    PM_SOURCE_MODE2_DIFF_WITH_DOUBLE = 0x00000002, ///< diff source matched to positive detections in both images
    4747    PM_SOURCE_MODE2_MATCHED          = 0x00000004, ///< diff source matched to positive detections in both images
     48    PM_SOURCE_MODE2_DIFF_SELF_MATCH  = 0x00000800, ///< positive detection match is probably this source
    4849
    4950    PM_SOURCE_MODE2_ON_SPIKE         = 0x00000008, ///< > 25% of (PSF-weighted) pixels land on diffraction spike
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmSourceMoments.c

    r31670 r33415  
    9696    // (int) so they can be used in the image index below.
    9797
    98     // do 2 passes : the first pass should use a somewhat smaller radius and no sigma window to
    99     // get an unbiased (but probably noisy) centroid
    100     if (!pmSourceMomentsGetCentroid (source, 0.75*radius, 0.0, minSN, maskVal, source->peak->xf, source->peak->yf)) {
    101         return false;
    102     }
    103     // second pass applies the Gaussian window and uses the centroid from the first pass
    104     if (!pmSourceMomentsGetCentroid (source, radius, sigma, minSN, maskVal, source->moments->Mx, source->moments->My)) {
     98    // XXX // do 2 passes : the first pass should use a somewhat smaller radius and no sigma window to
     99    // XXX // get an unbiased (but probably noisy) centroid
     100    // XXX if (!pmSourceMomentsGetCentroid (source, 0.75*radius, 0.0, minSN, maskVal, source->peak->xf, source->peak->yf)) {
     101    // XXX      return false;
     102    // XXX }
     103    // XXX // second pass applies the Gaussian window and uses the centroid from the first pass
     104    // XXX if (!pmSourceMomentsGetCentroid (source, radius, sigma, minSN, maskVal, source->moments->Mx, source->moments->My)) {
     105    // XXX      return false;
     106    // XXX }
     107
     108    // If we use a large radius for the centroid, it will be biased by any neighbors.  The flux
     109    // of any object drops pretty quickly outside 1-2 sigmas.  (The exception is bright
     110    // saturated stars, for which we need to use a very large radius here)
     111    if (!pmSourceMomentsGetCentroid (source, 1.5*sigma, 0.0, minSN, maskVal, source->peak->xf, source->peak->yf)) {
    105112        return false;
    106113    }
     
    108115    // Now calculate higher-order moments, using the above-calculated first moments to adjust coordinates
    109116    // Xn  = SUM (x - xc)^n * (z - sky)
    110 
    111     float RFW = 0.0;
    112     float RHW = 0.0;
    113 
    114     float RF = 0.0;
    115     float RH = 0.0;
    116     float RS = 0.0;
    117117    float XX = 0.0;
    118118    float XY = 0.0;
     
    143143    float yCM = Yo - 0.5 - source->pixels->row0; // coord of peak in subimage
    144144
     145    // calculate the higher-order moments using Xo,Yo
    145146    for (psS32 row = 0; row < source->pixels->numRows ; row++) {
    146147
     
    194195            Sum += pDiff;
    195196
    196             // Kron Flux uses the 1st radial moment (NOT Gaussian windowed?)
    197197            float r = sqrt(r2);
    198             float rf = r * fDiff;
    199             float rh = sqrt(r) * fDiff;
    200             float rs = fDiff;
    201 
    202             float rfw = r * pDiff;
    203             float rhw = sqrt(r) * pDiff;
    204198
    205199            float x = xDiff * pDiff;
     
    221215            float yyyy = yDiff * yyy / r2;
    222216
    223             RF  += rf;
    224             RH  += rh;
    225             RS  += rs;
    226 
    227             RFW  += rfw;
    228             RHW  += rhw;
    229 
    230217            XX  += xx;
    231218            XY  += xy;
     
    242229            XYYY  += xyyy;
    243230            YYYY  += yyyy;
     231
     232            // Kron Flux uses the 1st radial moment (NOT Gaussian windowed?)
     233            // XXX float r = sqrt(r2);
     234            // XXX float rf = r * fDiff;
     235            // XXX float rh = sqrt(r) * fDiff;
     236            // XXX float rs = fDiff;
     237            // XXX
     238            // XXX float rfw = r * pDiff;
     239            // XXX float rhw = sqrt(r) * pDiff;
     240            // XXX
     241            // XXX RF  += rf;
     242            // XXX RH  += rh;
     243            // XXX RS  += rs;
     244            // XXX
     245            // XXX RFW  += rfw;
     246            // XXX RHW  += rhw;
    244247        }
    245248    }
    246 
    247     source->moments->Mrf = RF/RS;
    248     source->moments->Mrh = RH/RS;
    249 
    250249    source->moments->Mxx = XX/Sum;
    251250    source->moments->Mxy = XY/Sum;
     
    262261    source->moments->Mxyyy = XYYY/Sum;
    263262    source->moments->Myyyy = YYYY/Sum;
     263
     264    // *** now calculate the 1st radial moment (for kron flux) -- symmetrical averaging
     265
     266    float **vPix = source->pixels->data.F32;
     267    float **vWgt = source->variance->data.F32;
     268    psImageMaskType  **vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA;
     269
     270    float RF = 0.0;
     271    float RH = 0.0;
     272    float RS = 0.0;
     273
     274    for (psS32 row = 0; row < source->pixels->numRows ; row++) {
     275
     276        float yDiff = row - yCM;
     277        if (fabs(yDiff) > radius) continue;
     278
     279        // coordinate of mirror pixel
     280        int yFlip = yCM - yDiff;
     281        if (yFlip < 0) continue;
     282        if (yFlip >= source->pixels->numRows) continue;
     283
     284        for (psS32 col = 0; col < source->pixels->numCols ; col++) {
     285            // check mask and value for this pixel
     286            if (vMsk && (vMsk[row][col] & maskVal)) continue;
     287            if (isnan(vPix[row][col])) continue;
     288
     289            float xDiff = col - xCM;
     290            if (fabs(xDiff) > radius) continue;
     291
     292            // coordinate of mirror pixel
     293            int xFlip = xCM - xDiff;
     294            if (xFlip < 0) continue;
     295            if (xFlip >= source->pixels->numCols) continue;
     296
     297            // check mask and value for mirror pixel
     298            if (vMsk && (vMsk[yFlip][xFlip] & maskVal)) continue;
     299            if (isnan(vPix[yFlip][xFlip])) continue;
     300
     301            // radius is just a function of (xDiff, yDiff)
     302            float r2  = PS_SQR(xDiff) + PS_SQR(yDiff);
     303            if (r2 > R2) continue;
     304
     305            float fDiff1 = vPix[row][col] - sky;
     306            float fDiff2 = vPix[yFlip][xFlip] - sky;
     307            float pDiff = (fDiff1 > 0.0) ? sqrt(fabs(fDiff1*fDiff2)) : -sqrt(fabs(fDiff1*fDiff2));
     308
     309            // Kron Flux uses the 1st radial moment (NOT Gaussian windowed?)
     310            float r = sqrt(r2);
     311            float rf = r * pDiff;
     312            float rh = sqrt(r) * pDiff;
     313            float rs = 0.5 * (fDiff1 + fDiff2);
     314
     315            RF  += rf;
     316            RH  += rh;
     317            RS  += rs;
     318        }
     319    }
     320
     321    source->moments->Mrf = RF/RS;
     322    source->moments->Mrh = RH/RS;
    264323
    265324    // if Mrf (first radial moment) is very small, we are getting into low-significance
     
    270329        kronRefRadius = MIN(radius, kronRefRadius);
    271330    }
     331
     332    // *** now calculate the kron flux values using the 1st radial moment
    272333
    273334    float radKinner = 1.0*kronRefRadius;
     
    283344    float SumOuter = 0.0;
    284345
     346    // calculate the Kron flux, and related fluxes (NO symmetrical averaging)
    285347    for (psS32 row = 0; row < source->pixels->numRows ; row++) {
    286 
     348       
    287349        float yDiff = row - yCM;
    288350        if (fabs(yDiff) > radKouter) continue;
     351       
     352        for (psS32 col = 0; col < source->pixels->numCols ; col++) {
     353            // check mask and value for this pixel
     354            if (vMsk && (vMsk[row][col] & maskVal)) continue;
     355            if (isnan(vPix[row][col])) continue;
     356           
     357            float xDiff = col - xCM;
     358            if (fabs(xDiff) > radKouter) continue;
     359           
     360            // radKron is just a function of (xDiff, yDiff)
     361            float r2  = PS_SQR(xDiff) + PS_SQR(yDiff);
     362
     363            float fDiff1 = vPix[row][col] - sky;
     364            float pDiff = fDiff1;
     365            float wDiff = vWgt[row][col];
     366                                   
     367            // skip pixels below specified significance level.  this is allowed, but should be
     368            // avoided -- the over-weights the wings of bright stars compared to those of faint
     369            // stars.
     370            if (PS_SQR(pDiff) < minSN2*wDiff) continue;
     371           
     372            float r  = sqrt(r2);
     373            if (r < radKron) {
     374                Sum += pDiff;
     375                Var += wDiff;
     376                nKronPix ++;
     377                // if (beVerbose) fprintf (stderr, "mome: %d %d  %f  %f  %f\n", col, row, sky, *vPix, Sum);
     378            }
     379
     380            // use sigma (fixed by psf) not a radKron based value
     381            if (r < sigma) {
     382                SumCore += pDiff;
     383                VarCore += wDiff;
     384                nCorePix ++;
     385            }
     386
     387            if ((r > radKinner) && (r < radKron)) {
     388                SumInner += pDiff;
     389                nInner ++;
     390            }
     391            if ((r > radKron)  && (r < radKouter)) {
     392                SumOuter += pDiff;
     393                nOuter ++;
     394            }
     395        }
     396    }
     397    // *** should I rescale these fluxes by pi R^2 / nNpix?
     398    // XXX source->moments->KronCore    = SumCore       * M_PI * PS_SQR(sigma) / nCorePix;
     399    // XXX source->moments->KronCoreErr = sqrt(VarCore) * M_PI * PS_SQR(sigma) / nCorePix;
     400    // XXX source->moments->KronFlux    = Sum       * M_PI * PS_SQR(radKron) / nKronPix;
     401    // XXX source->moments->KronFluxErr = sqrt(Var) * M_PI * PS_SQR(radKron) / nKronPix;
     402    // XXX source->moments->KronFinner = SumInner * M_PI * (PS_SQR(radKron)   - PS_SQR(radKinner)) / nInner;
     403    // XXX source->moments->KronFouter = SumOuter * M_PI * (PS_SQR(radKouter) -   PS_SQR(radKron)) / nOuter;
     404
     405    source->moments->KronCore    = SumCore;
     406    source->moments->KronCoreErr = sqrt(VarCore);
     407    source->moments->KronFlux    = Sum;
     408    source->moments->KronFluxErr = sqrt(Var);
     409    source->moments->KronFinner = SumInner;
     410    source->moments->KronFouter = SumOuter;
     411
     412    // XXX not sure I should save this here...
     413    source->moments->KronFluxPSF    = source->moments->KronFlux;
     414    source->moments->KronFluxPSFErr = source->moments->KronFluxErr;
     415    source->moments->KronRadiusPSF  = source->moments->Mrf;
     416
     417    psTrace ("psModules.objects", 4, "Mrf: %f  KronFlux: %f  Mxx: %f  Mxy: %f  Myy: %f  Mxxx: %f  Mxxy: %f  Mxyy: %f  Myyy: %f  Mxxxx: %f  Mxxxy: %f  Mxxyy: %f  Mxyyy: %f  Mxyyy: %f\n",
     418             source->moments->Mrf,   source->moments->KronFlux,
     419             source->moments->Mxx,   source->moments->Mxy,   source->moments->Myy,
     420             source->moments->Mxxx,  source->moments->Mxxy,  source->moments->Mxyy,  source->moments->Myyy,
     421             source->moments->Mxxxx, source->moments->Mxxxy, source->moments->Mxxyy, source->moments->Mxyyy, source->moments->Myyyy);
     422
     423    psTrace ("psModules.objects", 3, "peak %f %f (%f = %f) Mx: %f  My: %f  Sum: %f  Mxx: %f  Mxy: %f  Myy: %f  sky: %f  Npix: %d\n",
     424             source->peak->xf, source->peak->yf, source->peak->rawFlux, sqrt(source->peak->detValue), source->moments->Mx,   source->moments->My, Sum, source->moments->Mxx,   source->moments->Mxy,   source->moments->Myy, sky, source->moments->nPixels);
     425
     426    return(true);
     427}
     428
     429bool pmSourceMomentsGetCentroid(pmSource *source, float radius, float sigma, float minSN, psImageMaskType maskVal, float xGuess, float yGuess) {
     430
     431    // First Pass: calculate the first moments (these are subtracted from the coordinates below)
     432    // Sum = SUM (z - sky)
     433    // X1  = SUM (x - xc)*(z - sky)
     434    // .. etc
     435
     436    float sky = 0.0;
     437
     438    float peakPixel = -PS_MAX_F32;
     439    psS32 numPixels = 0;
     440    float Sum = 0.0;
     441    float Var = 0.0;
     442    float X1 = 0.0;
     443    float Y1 = 0.0;
     444    float R2 = PS_SQR(radius);
     445    float minSN2 = PS_SQR(minSN);
     446    float rsigma2 = 0.5 / PS_SQR(sigma);
     447
     448    float xPeak = xGuess - source->pixels->col0; // coord of peak in subimage
     449    float yPeak = yGuess - source->pixels->row0; // coord of peak in subimage
     450
     451    // we are guaranteed to have a valid pixel and variance at this location (right? right?)
     452    // float weightNorm = source->pixels->data.F32[yPeak][xPeak] / sqrt (source->variance->data.F32[yPeak][xPeak]);
     453    // psAssert (isfinite(source->pixels->data.F32[yPeak][xPeak]), "peak must be on valid pixel");
     454    // psAssert (isfinite(source->variance->data.F32[yPeak][xPeak]), "peak must be on valid pixel");
     455    // psAssert (source->variance->data.F32[yPeak][xPeak] > 0, "peak must be on valid pixel");
     456
     457    // the moments [Sum(x*f) / Sum(f)] are calculated in pixel index values, and should
     458    // not depend on the fractional pixel location of the source.  However, the aperture
     459    // (radius) and the Gaussian window (sigma) depend subtly on the fractional pixel
     460    // position of the expected centroid
     461
     462    for (psS32 row = 0; row < source->pixels->numRows ; row++) {
     463
     464        float yDiff = row + 0.5 - yPeak;
     465        if (fabs(yDiff) > radius) continue;
    289466
    290467        float *vPix = source->pixels->data.F32[row];
    291468        float *vWgt = source->variance->data.F32[row];
    292469
    293         psImageMaskType  *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[row];
    294         // psImageMaskType  *vMsk = (source->maskView == NULL) ? NULL : source->maskView->data.PS_TYPE_IMAGE_MASK_DATA[row];
     470        psImageMaskType *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[row];
     471        // psImageMaskType *vMsk = (source->maskView == NULL) ? NULL : source->maskView->data.PS_TYPE_IMAGE_MASK_DATA[row];
    295472
    296473        for (psS32 col = 0; col < source->pixels->numCols ; col++, vPix++, vWgt++) {
     
    304481            if (isnan(*vPix)) continue;
    305482
    306             float xDiff = col - xCM;
    307             if (fabs(xDiff) > radKouter) continue;
    308 
    309             // radKron is just a function of (xDiff, yDiff)
    310             float r2  = PS_SQR(xDiff) + PS_SQR(yDiff);
    311 
    312             float pDiff = *vPix - sky;
    313             float wDiff = *vWgt;
    314 
    315             // skip pixels below specified significance level.  this is allowed, but should be
    316             // avoided -- the over-weights the wings of bright stars compared to those of faint
    317             // stars.
    318             if (PS_SQR(pDiff) < minSN2*wDiff) continue;
    319 
    320             float r  = sqrt(r2);
    321             if (r < radKron) {
    322                 Sum += pDiff;
    323                 Var += wDiff;
    324                 nKronPix ++;
    325                 // if (beVerbose) fprintf (stderr, "mome: %d %d  %f  %f  %f\n", col, row, sky, *vPix, Sum);
    326             }
    327 
    328             // use sigma (fixed by psf) not a radKron based value
    329             if (r < sigma) {
    330                 SumCore += pDiff;
    331                 VarCore += wDiff;
    332                 nCorePix ++;
    333             }
    334 
    335             if ((r > radKinner) && (r < radKron)) {
    336                 SumInner += pDiff;
    337                 nInner ++;
    338             }
    339             if ((r > radKron)  && (r < radKouter)) {
    340                 SumOuter += pDiff;
    341                 nOuter ++;
    342             }
    343         }
    344     }
    345     // *** should I rescale these fluxes by pi R^2 / nNpix?
    346     source->moments->KronCore    = SumCore       * M_PI * PS_SQR(sigma) / nCorePix;
    347     source->moments->KronCoreErr = sqrt(VarCore) * M_PI * PS_SQR(sigma) / nCorePix;
    348     source->moments->KronFlux    = Sum       * M_PI * PS_SQR(radKron) / nKronPix;
    349     source->moments->KronFluxErr = sqrt(Var) * M_PI * PS_SQR(radKron) / nKronPix;
    350     source->moments->KronFinner = SumInner * M_PI * (PS_SQR(radKron)   - PS_SQR(radKinner)) / nInner;
    351     source->moments->KronFouter = SumOuter * M_PI * (PS_SQR(radKouter) -   PS_SQR(radKron)) / nOuter;
    352 
    353     psTrace ("psModules.objects", 4, "Mrf: %f  KronFlux: %f  Mxx: %f  Mxy: %f  Myy: %f  Mxxx: %f  Mxxy: %f  Mxyy: %f  Myyy: %f  Mxxxx: %f  Mxxxy: %f  Mxxyy: %f  Mxyyy: %f  Mxyyy: %f\n",
    354              source->moments->Mrf,   source->moments->KronFlux,
    355              source->moments->Mxx,   source->moments->Mxy,   source->moments->Myy,
    356              source->moments->Mxxx,  source->moments->Mxxy,  source->moments->Mxyy,  source->moments->Myyy,
    357              source->moments->Mxxxx, source->moments->Mxxxy, source->moments->Mxxyy, source->moments->Mxyyy, source->moments->Myyyy);
    358 
    359     psTrace ("psModules.objects", 3, "peak %f %f (%f = %f) Mx: %f  My: %f  Sum: %f  Mxx: %f  Mxy: %f  Myy: %f  sky: %f  Npix: %d\n",
    360              source->peak->xf, source->peak->yf, source->peak->rawFlux, sqrt(source->peak->detValue), source->moments->Mx,   source->moments->My, Sum, source->moments->Mxx,   source->moments->Mxy,   source->moments->Myy, sky, source->moments->nPixels);
    361 
    362     return(true);
    363 }
    364 
    365 bool pmSourceMomentsGetCentroid(pmSource *source, float radius, float sigma, float minSN, psImageMaskType maskVal, float xGuess, float yGuess) {
    366 
    367     // First Pass: calculate the first moments (these are subtracted from the coordinates below)
    368     // Sum = SUM (z - sky)
    369     // X1  = SUM (x - xc)*(z - sky)
    370     // .. etc
    371 
    372     float sky = 0.0;
    373 
    374     float peakPixel = -PS_MAX_F32;
    375     psS32 numPixels = 0;
    376     float Sum = 0.0;
    377     float Var = 0.0;
    378     float X1 = 0.0;
    379     float Y1 = 0.0;
    380     float R2 = PS_SQR(radius);
    381     float minSN2 = PS_SQR(minSN);
    382     float rsigma2 = 0.5 / PS_SQR(sigma);
    383 
    384     float xPeak = xGuess - source->pixels->col0; // coord of peak in subimage
    385     float yPeak = yGuess - source->pixels->row0; // coord of peak in subimage
    386 
    387     // we are guaranteed to have a valid pixel and variance at this location (right? right?)
    388     // float weightNorm = source->pixels->data.F32[yPeak][xPeak] / sqrt (source->variance->data.F32[yPeak][xPeak]);
    389     // psAssert (isfinite(source->pixels->data.F32[yPeak][xPeak]), "peak must be on valid pixel");
    390     // psAssert (isfinite(source->variance->data.F32[yPeak][xPeak]), "peak must be on valid pixel");
    391     // psAssert (source->variance->data.F32[yPeak][xPeak] > 0, "peak must be on valid pixel");
    392 
    393     // the moments [Sum(x*f) / Sum(f)] are calculated in pixel index values, and should
    394     // not depend on the fractional pixel location of the source.  However, the aperture
    395     // (radius) and the Gaussian window (sigma) depend subtly on the fractional pixel
    396     // position of the expected centroid
    397 
    398     for (psS32 row = 0; row < source->pixels->numRows ; row++) {
    399 
    400         float yDiff = row + 0.5 - yPeak;
    401         if (fabs(yDiff) > radius) continue;
    402 
    403         float *vPix = source->pixels->data.F32[row];
    404         float *vWgt = source->variance->data.F32[row];
    405 
    406         psImageMaskType *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[row];
    407         // psImageMaskType *vMsk = (source->maskView == NULL) ? NULL : source->maskView->data.PS_TYPE_IMAGE_MASK_DATA[row];
    408 
    409         for (psS32 col = 0; col < source->pixels->numCols ; col++, vPix++, vWgt++) {
    410             if (vMsk) {
    411                 if (*vMsk & maskVal) {
    412                     vMsk++;
    413                     continue;
    414                 }
    415                 vMsk++;
    416             }
    417             if (isnan(*vPix)) continue;
    418 
    419483            float xDiff = col + 0.5 - xPeak;
    420484            if (fabs(xDiff) > radius) continue;
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmSourceOutputs.c

    r31451 r33415  
    107107        }
    108108        if (isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXY]) && isfinite(PAR[PM_PAR_SYY])) {
    109             axes = pmPSF_ModelToAxes (PAR, 20.0);
     109            axes = pmPSF_ModelToAxes (PAR, 20.0, model->type);
    110110            outputs->psfMajor = axes.major;
    111111            outputs->psfMinor = axes.minor;
     
    178178    moments->KronCore    = source->moments ? source->moments->KronCore : NAN;
    179179    moments->KronCoreErr = source->moments ? source->moments->KronCoreErr : NAN;
    180 
    181     return true;
    182 }
     180    moments->KronPSF    = source->moments ? source->moments->KronFluxPSF : NAN;
     181    moments->KronPSFErr = source->moments ? source->moments->KronFluxPSFErr : NAN;
     182
     183    return true;
     184}
     185
     186bool pmSourceLocalAstrometry (psSphere *ptSky, float *posAngle, float *pltScale, pmChip *chip, float xPos, float yPos) {
     187
     188    pmFPA *fpa = chip->parent;
     189
     190    if (!chip->toFPA) goto escape;
     191    if (!fpa->toTPA) goto escape;
     192    if (!fpa->toSky) goto escape;
     193
     194    // generate RA,DEC
     195    psPlane ptCH, ptFP, ptTP_o, ptTP_x, ptTP_y;
     196
     197    // calculate the astrometry for the coordinate of interest
     198    ptCH.x = xPos;
     199    ptCH.y = yPos;
     200    psPlaneTransformApply (&ptFP, chip->toFPA, &ptCH);
     201    psPlaneTransformApply (&ptTP_o, fpa->toTPA, &ptFP);
     202    psDeproject (ptSky, &ptTP_o, fpa->toSky);
     203
     204    // calculate the astrometry for the coordinate + 1pix in X
     205    ptCH.x = xPos + 1.0;
     206    ptCH.y = yPos;
     207    psPlaneTransformApply (&ptFP, chip->toFPA, &ptCH);
     208    psPlaneTransformApply (&ptTP_x, fpa->toTPA, &ptFP);
     209
     210    // calculate the astrometry for the coordinate + 1pix in Y
     211    ptCH.x = xPos;
     212    ptCH.y = yPos + 1.0;
     213    psPlaneTransformApply (&ptFP, chip->toFPA, &ptCH);
     214    psPlaneTransformApply (&ptTP_y, fpa->toTPA, &ptFP);
     215
     216    // the resulting Tangent Plane coordinates are in TP pixels; convert to local Tangent Plane
     217    // degrees
     218
     219    float dTPx_dCHx = fpa->toSky->Xs * (ptTP_x.x - ptTP_o.x);
     220    float dTPy_dCHx = fpa->toSky->Ys * (ptTP_x.y - ptTP_o.y);
     221
     222    float dTPx_dCHy = fpa->toSky->Xs * (ptTP_y.x - ptTP_o.x);
     223    float dTPy_dCHy = fpa->toSky->Ys * (ptTP_y.y - ptTP_o.y);
     224
     225    float pltScale_x = hypot(dTPx_dCHx, dTPy_dCHx);
     226    float pltScale_y = hypot(dTPx_dCHy, dTPy_dCHy);
     227    *pltScale = 0.5*(pltScale_x + pltScale_y);
     228
     229    float posAngle_x = atan2 (+dTPy_dCHx, +dTPx_dCHx);
     230    float posAngle_y = atan2 (-dTPy_dCHy, +dTPx_dCHy);
     231    *posAngle = 0.5*(posAngle_x + posAngle_y);
     232
     233    return true;
     234
     235escape:
     236    // no astrometry calibration, give up
     237    ptSky->r = NAN;
     238    ptSky->d = NAN;
     239    *posAngle = NAN;
     240    *pltScale = NAN;
     241
     242    return false;
     243}
     244
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmSourceOutputs.h

    r31153 r33415  
    5252    float KronCore;
    5353    float KronCoreErr;
     54    float KronPSF;
     55    float KronPSFErr;
    5456} pmSourceOutputsMoments;
    5557
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmSourcePhotometry.c

    r31670 r33415  
    5656static psImageMaskType maskBurntool = 0;
    5757static psImageMaskType maskConvPoor = 0;
     58static psImageMaskType maskGhost    = 0;
     59static psImageMaskType maskGlint    = 0;
    5860
    5961bool pmSourceMagnitudesInit (pmConfig *config, psMetadata *recipe)
     
    6870        maskBurntool = pmConfigMaskGet("BURNTOOL", config);
    6971        maskConvPoor = pmConfigMaskGet("CONV.POOR", config);
     72        maskGhost    = pmConfigMaskGet("GHOST", config);
     73        maskGlint    = pmConfigMaskGet("GHOST", config);
    7074        maskSuspect  = maskSpike | maskStarCore | maskBurntool | maskConvPoor;
    7175    }
     
    9498{
    9599    PS_ASSERT_PTR_NON_NULL(source, false);
    96     PS_ASSERT_PTR_NON_NULL(psf, false);
     100    // PS_ASSERT_PTR_NON_NULL(psf, false);
    97101
    98102    int status = false;
     
    533537    }
    534538
     539    // Check that if the peak is on/off a ghost, glint, or diffraction spike.  In regular IPP
     540    // processing, these values are only set in the image mask after the 'camera' stage
     541
     542    int xChip = source->peak->x;
     543    int yChip = source->peak->y;
     544
     545    // need to access the parent if we are looking at a subimage (likely)
     546    psImage *chipImage = (source->pixels == NULL) ? source->pixels : (psImage *) source->pixels->parent;
     547
     548    bool onChip = true;
     549    onChip &= (xChip >= 0);
     550    onChip &= (xChip < chipImage->numCols);
     551    onChip &= (yChip >= 0);
     552    onChip &= (yChip < chipImage->numRows);
     553    if (!onChip) {
     554        // if the source is off the edge of the chip, raise a different bit?
     555        source->mode |= PM_SOURCE_MODE_OFF_CHIP;
     556    } else {
     557        int xMask = xChip - mask->col0;
     558        int yMask = yChip - mask->row0;
     559        psImageMaskType maskValue = mask->data.PS_TYPE_IMAGE_MASK_DATA[yMask][xMask];
     560        if (maskValue & maskGhost) {
     561            source->mode |= PM_SOURCE_MODE_ON_GHOST;
     562        }
     563        pmSourceMode PM_SOURCE_MODE_ON_GLINT = PM_SOURCE_MODE_ON_GHOST;
     564        if (maskValue & maskGlint) {
     565            source->mode |= PM_SOURCE_MODE_ON_GLINT;
     566        }
     567        if (maskValue & maskSpike) {
     568            source->mode |= PM_SOURCE_MODE_ON_SPIKE;
     569        }
     570    }
    535571    return (true);
    536572}
  • branches/meh_branches/ppstack_test/psModules/src/objects/pmSourcePlotPSFModel.c

    r29004 r33415  
    145145        // force the axis ratio to be < 20.0
    146146        psEllipseAxes axes_mnt = psEllipseMomentsToAxes (moments, 20.0);
    147         psEllipseAxes axes_psf = pmPSF_ModelToAxes (PAR, 20.0);
     147        psEllipseAxes axes_psf = pmPSF_ModelToAxes (PAR, 20.0, model->type);
    148148
    149149        // moments major axis
Note: See TracChangeset for help on using the changeset viewer.