IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Sep 13, 2005, 3:35:20 PM (21 years ago)
Author:
eugene
Message:

substantial work to match with psLib v.7

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psphot/src/pmObjects_EAM.c

    r4977 r5048  
    66 *  @author EAM, IfA: significant modifications.
    77 *
    8  *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
    9  *  @date $Date: 2005-09-08 04:32:40 $
     8 *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
     9 *  @date $Date: 2005-09-14 01:35:20 $
    1010 *
    1111 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    603603     members.
    604604*****************************************************************************/
    605 pmSource *pmSourceLocalSky(const psImage *image,
    606                            const pmPeak *peak,
    607                            psStatsOptions statsOptions,
    608                            psF32 innerRadius,
    609                            psF32 outerRadius)
    610 {
    611     PS_ASSERT_IMAGE_NON_NULL(image, NULL);
    612     PS_ASSERT_IMAGE_TYPE(image, PS_TYPE_F32, NULL);
    613     PS_ASSERT_PTR_NON_NULL(peak, NULL);
    614     PS_FLOAT_COMPARE(0.0, innerRadius, NULL);
    615     PS_FLOAT_COMPARE(innerRadius, outerRadius, NULL);
    616     psS32 innerRadiusS32 = (psS32) innerRadius;
    617     psS32 outerRadiusS32 = (psS32) outerRadius;
    618 
    619     //
    620     // We define variables for code readability.
    621     //
    622     // XXX: Since the peak->xy coords are in image, not subImage coords,
    623     // these variables should be renamed for clarity (imageCenterRow, etc).
    624     //
    625     // peak->x,y is guaranteed to be on image
    626     psS32 SubImageCenterRow = peak->y;
    627     psS32 SubImageCenterCol = peak->x;
    628 
    629     // XXX EAM : I added this code to stay on the image. So did George
    630     // XXX EAM : EndRow is *exclusive* of pixel region (ie, last pixel + 1)
    631     // XXX EAM : dropped the Annulus width (not needed)
    632     // XXX EAM : dropped off-boundary tests (not needed)
    633     psS32 SubImageStartRow  = PS_MAX (0, SubImageCenterRow - outerRadiusS32);
    634     psS32 SubImageEndRow    = PS_MIN (image->numRows, SubImageCenterRow + outerRadiusS32 + 1);
    635     psS32 SubImageStartCol  = PS_MAX (0, SubImageCenterCol - outerRadiusS32);
    636     psS32 SubImageEndCol    = PS_MIN (image->numCols, SubImageCenterCol + outerRadiusS32 + 1);
    637     //
    638     // Grab a subimage of the original image of size (2 * outerRadius).
    639     //
    640     // XXX EAM : merged psImageSubset & psRegionSet
    641     // XXX EAM : cast for image is needed because of const (above)
    642     psImage *subImage = psImageSubset((psImage *) image, psRegionSet(SubImageStartCol,
    643                                                          SubImageEndCol,
    644                                                          SubImageStartRow,
    645                                                          SubImageEndRow));
    646 
    647     psImage *subImageMask = psImageAlloc(subImage->numCols,
    648                                          subImage->numRows,
    649                                          PS_TYPE_U8);
    650     // XXX EAM : for consistency, mask needs col0,row0 set to match image
    651     // XXX EAM : CONFLICT between psLib and code requirement. FIX PSLIB!!!
    652     // subImageMask->col0 = subImage->col0;
    653     // subImageMask->row0 = subImage->row0;
    654     psAbort ("pmObjects", "must fix this error before psphot will work!!!\n");
    655 
    656     //
    657     // Loop through the subimage mask & initialize PSPHOT_MASK_INVALID
    658     //
    659     for (psS32 row = 0 ; row < subImageMask->numRows; row++) {
    660         for (psS32 col = 0 ; col < subImageMask->numCols; col++) {
    661             subImageMask->data.U8[row][col] = PSPHOT_MASK_INVALID;
    662         }
    663     }
    664 
    665     //
    666     // Loop through the subimage, mask off pixels in the inner square.
    667     // XXX this uses a static mask value of 0
    668     // XXX EAM : this was wrong: it masked the wrong pixels at the edge of the image
    669     // XXX EAM : this masks the pixels in the center region
    670     // XXX EAM : should we be using psImageMaskRegion ???
    671     psS32 StartRow  = PS_MAX (0, SubImageCenterRow - subImageMask->row0 - innerRadiusS32);
    672     psS32 EndRow    = PS_MIN (subImageMask->numRows, SubImageCenterRow - subImageMask->row0 + innerRadiusS32 + 1);
    673     psS32 StartCol  = PS_MAX (0, SubImageCenterCol - subImageMask->col0 - innerRadiusS32);
    674     psS32 EndCol    = PS_MIN (subImageMask->numCols, SubImageCenterCol - subImageMask->col0 + innerRadiusS32 + 1);
    675     for (psS32 row = StartRow; row < EndRow; row++) {
    676         for (psS32 col = StartCol; col < EndCol; col++) {
    677             subImageMask->data.U8[row][col] = PSPHOT_MASK_CLEAR;
    678         }
    679     }
    680 
    681     // XXX EAM : make this trace information??
    682     //    for (psS32 row = 0 ; row < subImage->numRows; row++) {
    683     //        for (psS32 col = 0 ; col < subImage->numCols; col++) {
    684     //            printf("(%d) ", subImageMask->data.U8[row][col]);
    685     //        }
    686     //        printf("\n");
    687     //    }
    688 
    689     //
    690     // Allocate the myStats structure, then call psImageStats(), which will
    691     // calculate the specified statistic.
    692     //
     605bool pmSourceLocalSky (pmSource *source,
     606                           psStatsOptions statsOptions,
     607                           psF32 Radius)
     608{
     609
     610    psImage *image = source->pixels;
     611    psImage *mask  = source->mask;
     612    pmPeak *peak  = source->peak;
     613    psRegion srcRegion;
     614
     615    // XXX EAM : psRegionXXX funcs should take value not ptr
     616    srcRegion = psRegionForSquare (peak->x, peak->y, Radius);
     617    srcRegion = psRegionForImage (mask, &srcRegion);
     618
     619    psImageMaskRegion (mask, &srcRegion, "OR", PSPHOT_MASK_MARKED);
    693620    psStats *myStats = psStatsAlloc(statsOptions);
    694     myStats = psImageStats(myStats, subImage, subImageMask, 1);
    695 
    696     //
    697     // Create the output mySource, and set appropriate members.
    698     //
    699     pmSource *mySource = pmSourceAlloc();
    700     mySource->peak = (pmPeak *) peak;
    701     mySource->moments = pmMomentsAlloc();
     621    myStats = psImageStats(myStats, image, mask, 0xff);
     622    psImageMaskRegion (mask, &srcRegion, "AND", ~PSPHOT_MASK_MARKED);
     623
    702624    psF64 tmpF64;
    703625    p_psGetStatValue(myStats, &tmpF64);
    704     mySource->moments->Sky = (psF32) tmpF64;
    705     mySource->pixels = subImage;
    706     mySource->mask = subImageMask;
    707 
    708     //
    709     // Free things.  XXX: This should be static memory.
    710     //
    711     psFree(myStats);
    712 
    713     return(mySource);
    714 }
    715 
    716 /******************************************************************************
    717 bool checkRadius(*peak, radius, x, y): private function which simply
    718 determines if the (x, y) point is within the radius of the specified peak.
    719  
    720 XXX: macro this for performance.
    721 *****************************************************************************/
    722 static bool checkRadius(pmPeak *peak,
    723                         psF32 radius,
    724                         psS32 x,
    725                         psS32 y)
    726 {
    727     if (PS_SQR(radius) >= (psF32) (PS_SQR(x - peak->x) + PS_SQR(y - peak->y))) {
    728         return(true);
    729     }
    730 
    731     return(false);
     626    psFree (myStats);
     627
     628    if (isnan(tmpF64)) return (false);
     629    source->moments = pmMomentsAlloc();
     630    source->moments->Sky = (psF32) tmpF64;
     631    return (true);
    732632}
    733633
     
    762662    pmSource->peak
    763663    pmSource->pixels
     664    pmSource->noise
     665    pmSource->mask
    764666 
    765667XXX: The peak calculations are done in image coords, not subImage coords.
    766668 
    767 XXX: mask values?
    768 *****************************************************************************/
     669XXX EAM : this version clips input pixels on S/N
     670XXX EAM : this version returns false for several reasons
     671*****************************************************************************/
     672# define VALID_RADIUS(X,Y,RAD2) (((RAD2) >= (PS_SQR(X) + PS_SQR(Y))) ? 1 : 0)
     673
    769674bool pmSourceMoments(pmSource *source,
    770675                     psF32 radius)
    771676{
    772     PS_ASSERT_PTR_NON_NULL(source, NULL);
    773     PS_ASSERT_PTR_NON_NULL(source->peak, NULL);
    774     PS_ASSERT_PTR_NON_NULL(source->pixels, NULL);
     677    // PS_PTR_CHECK_NULL(source, NULL);
     678    // PS_PTR_CHECK_NULL(source->peak, NULL);
     679    // PS_PTR_CHECK_NULL(source->pixels, NULL);
     680    // PS_PTR_CHECK_NULL(source->noise, NULL);
    775681    PS_FLOAT_COMPARE(0.0, radius, NULL);
    776682
     
    791697    // XY  = SUM (x - xc)*(y - yc)*(z - sky)
    792698    //
    793     psF32 Sum = 0.0;
    794699    psF32 peakPixel = -PS_MAX_F32;
    795700    psS32 numPixels = 0;
     701    psF32 Sum = 0.0;
    796702    psF32 X1 = 0.0;
    797703    psF32 Y1 = 0.0;
     
    799705    psF32 Y2 = 0.0;
    800706    psF32 XY = 0.0;
    801     psF32 x = 0;
    802     psF32 y = 0;
    803     //
     707    psF32 x  = 0;
     708    psF32 y  = 0;
     709    psF32 R2 = PS_SQR(radius);
     710
     711    psF32 xPeak = source->peak->x;
     712    psF32 yPeak = source->peak->y;
     713
    804714    // XXX why do I get different results for these two methods of finding Sx?
    805715    // XXX Sx, Sy would be better measured if we clip pixels close to sky
     
    809719    // proceed with the moments calculation.  need to do two loops for a
    810720    // numerically stable result.  first loop: get the sums.
    811     //
     721    // XXX EAM : mask == 0 is valid
     722
    812723    for (psS32 row = 0; row < source->pixels->numRows ; row++) {
    813724        for (psS32 col = 0; col < source->pixels->numCols ; col++) {
    814             // XXX EAM : mask == 0 is valid
    815725            if ((source->mask != NULL) && (source->mask->data.U8[row][col])) continue;
    816             psS32 imgColCoord = col + source->pixels->col0;
    817             psS32 imgRowCoord = row + source->pixels->row0;
    818             if (checkRadius(source->peak,
    819                             radius,
    820                             imgColCoord,
    821                             imgRowCoord)) {
    822                 psF32 xDiff = (psF32) (imgColCoord - source->peak->x);
    823                 psF32 yDiff = (psF32) (imgRowCoord - source->peak->y);
    824                 psF32 pDiff = source->pixels->data.F32[row][col] - sky;
    825 
    826                 Sum+= pDiff;
    827                 X1+= xDiff * pDiff;
    828                 Y1+= yDiff * pDiff;
    829                 XY+= xDiff * yDiff * pDiff;
    830 
    831                 X2+= PS_SQR(xDiff) * pDiff;
    832                 Y2+= PS_SQR(yDiff) * pDiff;
    833 
    834                 if (source->pixels->data.F32[row][col] > peakPixel) {
    835                     peakPixel = source->pixels->data.F32[row][col];
    836                 }
    837                 numPixels++;
    838             }
     726
     727            psF32 xDiff = col + source->pixels->col0 - xPeak;
     728            psF32 yDiff = row + source->pixels->row0 - yPeak;
     729
     730            // XXX EAM : calculate xDiff, yDiff up front;
     731            //           radius is just a function of (xDiff, yDiff)
     732            if (!VALID_RADIUS(xDiff, yDiff, R2)) continue;
     733
     734            psF32 pDiff = source->pixels->data.F32[row][col] - sky;
     735
     736            // XXX EAM : check for valid S/N in pixel
     737            // XXX EAM : should this limit be user-defined?
     738            if (pDiff / sqrt(source->noise->data.F32[row][col]) < 1) continue;
     739           
     740            Sum += pDiff;
     741            X1  += xDiff * pDiff;
     742            Y1  += yDiff * pDiff;
     743            XY  += xDiff * yDiff * pDiff;
     744           
     745            X2  += PS_SQR(xDiff) * pDiff;
     746            Y2  += PS_SQR(yDiff) * pDiff;
     747           
     748            peakPixel = PS_MAX (source->pixels->data.F32[row][col], peakPixel);
     749            numPixels++;
    839750        }
    840751    }
    841752    // XXX EAM - the limit is a bit arbitrary.  make it user defined?
    842753    if ((numPixels < 3) || (Sum <= 0)) {
    843         psTrace (".psModules.pmSourceMoments", 5, "no valid pixels for source\n");
    844         return (false);
     754      psTrace (".psModules.pmSourceMoments", 5, "no valid pixels for source\n");
     755      return (false);
    845756    }
    846757
     
    857768    y = Y1/Sum;
    858769    if ((fabs(x) > radius) || (fabs(y) > radius)) {
    859         psTrace (".psModules.pmSourceMoments", 5,
    860                  "large centroid swing; invalid peak %d, %d\n",
    861                  source->peak->x, source->peak->y);
    862         return (false);
    863     }
    864 
    865     source->moments->x = x + ((psF32) source->peak->x);
    866     source->moments->y = y + ((psF32) source->peak->y);
    867 
     770      psTrace (".psModules.pmSourceMoments", 5,
     771               "large centroid swing; invalid peak %d, %d\n",
     772               source->peak->x, source->peak->y);
     773      return (false);
     774    }
     775
     776    source->moments->x = x + xPeak;
     777    source->moments->y = y + yPeak;
     778
     779    // XXX EAM : Sxy needs to have x*y subtracted
    868780    source->moments->Sxy = XY/Sum - x*y;
    869781    source->moments->Sum = Sum;
     
    919831*****************************************************************************/
    920832
     833// XXX EAM include a S/N cutoff in selecting the sources?
    921834pmPSFClump pmSourcePSFClump(psArray *sources, psMetadata *metadata)
    922835{
     
    11231036        bool big = (sigX > (clump.X - clump.dX)) && (sigY > (clump.Y - clump.dY));
    11241037        if ((Nsatpix > 1) && big) {
    1125             tmpSrc->type |= PS_SOURCE_SATSTAR;
     1038            tmpSrc->type |= PM_SOURCE_SATSTAR;
    11261039            Nsatstar ++;
    11271040            continue;
     
    11301043        // saturated object (not a star, eg bleed trails, hot pixels)
    11311044        if (Nsatpix > 1) {
    1132             tmpSrc->type |= PS_SOURCE_SATURATED;
     1045            tmpSrc->type |= PM_SOURCE_SATURATED;
    11331046            Nsat ++;
    11341047            continue;
     
    11391052        // only set candidate defects if
    11401053        if ((sigX < 0.05) || (sigY < 0.05)) {
    1141             tmpSrc->type |= PS_SOURCE_DEFECT;
     1054            tmpSrc->type |= PM_SOURCE_DEFECT;
    11421055            Ncr ++;
    11431056            continue;
     
    11461059        // likely unsaturated galaxy (too large to be stellar)
    11471060        if ((sigX > (clump.X + 3*clump.dX)) || (sigY > (clump.Y + 3*clump.dY))) {
    1148             tmpSrc->type |= PS_SOURCE_GALAXY;
     1061            tmpSrc->type |= PM_SOURCE_GALAXY;
    11491062            Ngal ++;
    11501063            continue;
     
    11591072        psF32 radius = hypot ((sigX-clump.X)/clump.dX, (sigY-clump.Y)/clump.dY);
    11601073        if ((SN > PSF_SN_LIM) && (radius < 1.5)) {
    1161             tmpSrc->type |= PS_SOURCE_PSFSTAR;
     1074            tmpSrc->type |= PM_SOURCE_PSFSTAR;
    11621075            Npsf ++;
    11631076            continue;
     
    11651078
    11661079        // random type of star
    1167         tmpSrc->type |= PS_SOURCE_OTHER;
     1080        tmpSrc->type |= PM_SOURCE_OTHER;
    11681081    }
    11691082
     
    11971110XXX: The circle will have a diameter of (1+radius).  This is different from
    11981111     the pmSourceSetLocal() function.
     1112
     1113XXX: this should probably use the psImageMaskCircle Function for consistency
    11991114*****************************************************************************/
    12001115bool pmSourceSetPixelsCircle(pmSource *source,
     
    15371452XXX EAM : fit the specified model (not necessarily the one in source)
    15381453*****************************************************************************/
    1539 bool pmSourceFitModel(pmSource *source,
    1540                       pmModel *model,
    1541                       const bool PSF)
     1454bool pmSourceFitModel_v5(pmSource *source,
     1455                        pmModel *model,
     1456                        const bool PSF)
    15421457{
    15431458    PS_ASSERT_PTR_NON_NULL(source, false);
     
    15541469    //           tests below could be conditions (!NULL)
    15551470
    1556     pmModelFunc modelFunc = pmModelFunc_GetFunction (model->type);
    1557 
    15581471    psVector *params = model->params;
    15591472    psVector *dparams = model->dparams;
    15601473    psVector *paramMask = NULL;
     1474
     1475    pmModelFunc modelFunc = pmModelFunc_GetFunction (model->type);
    15611476
    15621477    int nParams = PSF ? params->n - 4 : params->n;
     
    16151530    }       
    16161531
    1617     psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F32);
     1532    // XXX EAM : covar must be F64?
     1533    psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F64);
    16181534
    16191535    psTrace (".pmObjects.pmSourceFitModel", 5, "fitting function\n");
     
    16211537    for (int i = 0; i < dparams->n; i++) {
    16221538        if ((paramMask != NULL) && paramMask->data.U8[i]) continue;
    1623         dparams->data.F32[i] = sqrt(covar->data.F32[i][i]);
     1539        dparams->data.F32[i] = sqrt(covar->data.F64[i][i]);
    16241540    }
    16251541 
     
    16401556    // XXX EAM get the Gauss-Newton distance for fixed model parameters
    16411557    if (paramMask != NULL) {
    1642         psVector *delta = psVectorAlloc (params->n, PS_TYPE_F32);
     1558        psVector *delta = psVectorAlloc (params->n, PS_TYPE_F64);
    16431559        psMinimizeGaussNewtonDelta (delta, params, NULL, x, y, yErr, modelFunc);
    16441560        for (int i = 0; i < dparams->n; i++) {
    16451561            if (!paramMask->data.U8[i]) continue;
    1646             dparams->data.F32[i] = delta->data.F32[i];
     1562            dparams->data.F32[i] = delta->data.F64[i];
    16471563        }
    16481564        psFree (delta);
     
    16551571    psFree(covar);
    16561572    psFree(paramMask);
     1573
     1574    rc = (onPic && fitStatus);
     1575    return(rc);
     1576}
     1577
     1578// XXX EAM : new version with parameter range limits and noise enhancement
     1579bool pmSourceFitModel (pmSource *source,
     1580                       pmModel *model,
     1581                       const bool PSF)
     1582{
     1583    PS_ASSERT_PTR_NON_NULL(source, false);
     1584    PS_ASSERT_PTR_NON_NULL(source->moments, false);
     1585    PS_ASSERT_PTR_NON_NULL(source->peak, false);
     1586    PS_ASSERT_PTR_NON_NULL(source->pixels, false);
     1587    PS_ASSERT_PTR_NON_NULL(source->mask, false);
     1588    PS_ASSERT_PTR_NON_NULL(source->noise, false);
     1589
     1590    // XXX EAM : is it necessary for the mask & noise to exist?  the
     1591    //           tests below could be conditions (!NULL)
     1592
     1593    psBool fitStatus = true;
     1594    psBool onPic     = true;
     1595    psBool rc        = true;
     1596    psF32  Ro, ymodel;
     1597
     1598    psVector *params = model->params;
     1599    psVector *dparams = model->dparams;
     1600    psVector *paramMask = NULL;
     1601
     1602    pmModelFunc modelFunc = pmModelFunc_GetFunction (model->type);
     1603
     1604    // XXX EAM : I need to use the sky value to constrain the noise model
     1605    int nParams = PSF ? params->n - 4 : params->n;
     1606    psF32 So = params->data.F32[0];
     1607
     1608    // find the number of valid pixels
     1609    // XXX EAM : this loop and the loop below could just be one pass
     1610    //           using the psArrayAdd and psVectorExtend functions
     1611    psS32 count = 0;
     1612    for (psS32 i = 0; i < source->pixels->numRows; i++) {
     1613        for (psS32 j = 0; j < source->pixels->numCols; j++) {
     1614            if (source->mask->data.U8[i][j] == 0) {
     1615                count++;
     1616            }
     1617        }
     1618    }
     1619    if (count <  nParams + 1) {
     1620        psTrace (".pmObjects.pmSourceFitModel", 4, "insufficient valid pixels\n");
     1621        return(false);
     1622    }
     1623
     1624    // construct the coordinate and value entries
     1625    psArray *x = psArrayAlloc(count);
     1626    psVector *y = psVectorAlloc(count, PS_TYPE_F32);
     1627    psVector *yErr = psVectorAlloc(count, PS_TYPE_F32);
     1628    psS32 tmpCnt = 0;
     1629    for (psS32 i = 0; i < source->pixels->numRows; i++) {
     1630        for (psS32 j = 0; j < source->pixels->numCols; j++) {
     1631            if (source->mask->data.U8[i][j] == 0) {
     1632                psVector *coord = psVectorAlloc(2, PS_TYPE_F32);
     1633                // XXX: Convert i/j to image space:
     1634                // XXX EAM: coord order is (x,y) == (col,row)
     1635                coord->data.F32[0] = (psF32) (j + source->pixels->col0);
     1636                coord->data.F32[1] = (psF32) (i + source->pixels->row0);
     1637                x->data[tmpCnt] = (psPtr *) coord;
     1638                y->data.F32[tmpCnt] = source->pixels->data.F32[i][j];
     1639
     1640                // compare observed flux to model flux to adjust weight
     1641                ymodel = modelFunc (NULL, model->params, coord);
     1642               
     1643                // this test enhances the noise based on deviation from the model flux
     1644                Ro = 1.0 + fabs (y->data.F32[tmpCnt] - ymodel) / sqrt(PS_SQR(ymodel - So) + PS_SQR(So));
     1645
     1646                // XXX EAM : note the wasted effort: we carry dY^2, take sqrt(), then
     1647                //           the minimization function calculates sq().
     1648                //           should psMinimizeLMChi2 take dY^2?
     1649                yErr->data.F32[tmpCnt] = sqrt (source->noise->data.F32[i][j] * Ro);
     1650                tmpCnt++;
     1651            }
     1652        }
     1653    }
     1654
     1655    psMinimization *myMin = psMinimizationAlloc(PM_SOURCE_FIT_MODEL_NUM_ITERATIONS,
     1656                                                PM_SOURCE_FIT_MODEL_TOLERANCE);
     1657
     1658    // PSF model only fits first 4 parameters, FLT model fits all
     1659    if (PSF) {
     1660        paramMask = psVectorAlloc (params->n, PS_TYPE_U8);
     1661        for (int i = 0; i < 4; i++) {
     1662            paramMask->data.U8[i] = 0;
     1663        }
     1664        for (int i = 4; i < paramMask->n; i++) {
     1665            paramMask->data.U8[i] = 1;
     1666        }
     1667    } 
     1668
     1669    // XXX EAM : I've added three types of parameter range checks
     1670    // XXX EAM : this requires my new psMinimization functions
     1671    pmModelLimits modelLimits = pmModelLimits_GetFunction (model->type);
     1672    psVector *beta_lim = NULL;
     1673    psVector *params_min = NULL;
     1674    psVector *params_max = NULL;
     1675
     1676    // XXX EAM : in this implementation, I pass in the limits with the covar matrix.
     1677    //           in the SDRS, I define a new psMinimization which will take these in
     1678    psImage *covar = psImageAlloc (params->n, 3, PS_TYPE_F64);
     1679    modelLimits (&beta_lim, &params_min, &params_max);
     1680    for (int i = 0; i < params->n; i++) {
     1681        covar->data.F64[0][i] = beta_lim->data.F32[i];
     1682        covar->data.F64[1][i] = params_min->data.F32[i];
     1683        covar->data.F64[2][i] = params_max->data.F32[i];
     1684    }
     1685
     1686    psTrace (".pmObjects.pmSourceFitModel", 5, "fitting function\n");
     1687    fitStatus = psMinimizeLMChi2_EAM(myMin, covar, params, paramMask, x, y, yErr, modelFunc);
     1688    for (int i = 0; i < dparams->n; i++) {
     1689        if ((paramMask != NULL) && paramMask->data.U8[i]) continue;
     1690        dparams->data.F32[i] = sqrt(covar->data.F64[i][i]);
     1691    }
     1692 
     1693    // XXX EAM: we need to do something (give an error?) if rc is false
     1694    // XXX EAM: psMinimizeLMChi2 does not check convergence
     1695
     1696    // XXX models can go insane: reject these
     1697    onPic &= (params->data.F32[2] >= source->pixels->col0);
     1698    onPic &= (params->data.F32[2] <  source->pixels->col0 + source->pixels->numCols);
     1699    onPic &= (params->data.F32[3] >= source->pixels->row0);
     1700    onPic &= (params->data.F32[3] <  source->pixels->row0 + source->pixels->numRows);
     1701
     1702    // XXX EAM: save the resulting chisq, nDOF, nIter
     1703    model->chisq = myMin->value;
     1704    model->nIter = myMin->iter;
     1705    model->nDOF  = y->n - nParams;
     1706
     1707    // XXX EAM get the Gauss-Newton distance for fixed model parameters
     1708    if (paramMask != NULL) {
     1709        psVector *delta = psVectorAlloc (params->n, PS_TYPE_F64);
     1710        psMinimizeGaussNewtonDelta (delta, params, NULL, x, y, yErr, modelFunc);
     1711        for (int i = 0; i < dparams->n; i++) {
     1712            if (!paramMask->data.U8[i]) continue;
     1713            dparams->data.F32[i] = delta->data.F64[i];
     1714        }
     1715    }
     1716
     1717    psFree(paramMask);
     1718    psFree(x);
     1719    psFree(y);
     1720    psFree(myMin);
    16571721
    16581722    rc = (onPic && fitStatus);
Note: See TracChangeset for help on using the changeset viewer.