LVector LTransform::operator*(const LVector rhs) const { if (_orderIn != rhs.getOrder()) FormatAndThrow<>() << "Order mismatch between LTransform [" << _orderIn << "] and LVector [" << rhs.getOrder() << "]"; boost::shared_ptr<tmv::Vector<double> > out(new tmv::Vector<double>(sizeOut())); *out = (*_m) * rhs.rVector(); return LVector(_orderOut, out); }
void ShapeletFitImage(double sigma, LVector& bvec, const BaseImage<T>& image, double image_scale, const Position<double>& center) { // TODO: It would be nice to be able to fit this with an arbitrary WCS to fit in // sky coordinates. For now, just use the image_scale. dbg<<"Start ShapeletFitImage:\n"; xdbg<<"sigma = "<<sigma<<std::endl; xdbg<<"bvec = "<<bvec<<std::endl; xdbg<<"center = "<<center<<std::endl; double scale = image_scale / sigma; xdbg<<"scale = "<<scale<<std::endl; const int nx = image.getXMax() - image.getXMin() + 1; const int ny = image.getYMax() - image.getYMin() + 1; xdbg<<"nx,ny = "<<nx<<','<<ny<<std::endl; const int npts = nx * ny; xdbg<<"npts = "<<npts<<std::endl; tmv::Vector<double> x(npts); tmv::Vector<double> y(npts); tmv::Vector<double> I(npts); int i=0; for (int ix = image.getXMin(); ix <= image.getXMax(); ++ix) { for (int iy = image.getYMin(); iy <= image.getYMax(); ++iy,++i) { x[i] = (ix - center.x) * scale; y[i] = (iy - center.y) * scale; I[i] = image(ix,iy); } } xxdbg<<"x = "<<x<<std::endl; xxdbg<<"y = "<<y<<std::endl; xxdbg<<"I = "<<I<<std::endl; tmv::Matrix<double> psi(npts,bvec.size()); LVector::basis(x.view(),y.view(),psi.view(),bvec.getOrder(),sigma); // I = psi * b // TMV solves this by writing b = I/psi. // We use QRP in case the psi matrix is close to singular (although it shouldn't be). psi.divideUsing(tmv::QRP); bvec.rVector() = I/psi; xdbg<<"Done FitImage: bvec = "<<bvec<<std::endl; }
int main(int argc, char *argv[]) { // Parameters to set: // columns for necessary input: int idCol; int segIdCol; int raCol; int decCol; int magCol; int bgCol; int rCol; // half-light radius (pix) int aCol, bCol, paCol; // WC observed ellipse int g1Col; int g2Col; int fwdColStart; int fwdColEnd; // The fit: int order; double maskSigma; // Input files string fitsName; string catName; string psfName; int psfOrder; string weightName; string wcsName; string segmentationName; int segmentationPadding; string weightScaleKey; string fluxScaleKey; // Data properties double sky; //double rn; //double gain; int stampSize; // GL interpolation of missing values double maxBadPixels; int interpolationOrder; double maxBadFlux; Pset parameters; { const int def=PsetMember::hasDefault; const int low=PsetMember::hasLowerBound; const int up=PsetMember::hasUpperBound; const int lowopen = low | PsetMember::openLowerBound; const int upopen = up | PsetMember::openUpperBound; parameters.addMemberNoValue("FILES:",0, "Input data"); parameters.addMember("fitsName", &fitsName, def, "Image FITS file", "set0001.fit"); parameters.addMember("catName", &catName, def, "Input SExtractor catalog", "set0001.scat"); parameters.addMember("psfName", &psfName, def, "Input PSFEx file", "model.txt"); parameters.addMember("psfOrder", &psfOrder, def | low, (std::string("Maximum order of polynomial psf variation used; ")+ std::string("-1 for order of PSFEx model")).c_str(), -1, -1); parameters.addMember("weightName", &weightName, def, "Input weight map proportional to inverse variance", "weight.fit"); parameters.addMember("wcsName", &wcsName, def, "World coordinate header file", "wcs.txt"); parameters.addMember("weightScaleKey", &weightScaleKey, def, "Scaling factor for weight map (e.g. from Swarp) keyword in WCS header", "WTSCALE"); // This is the scale that transforms weight proportional to 1/sig^2 to weights EQUAL to // 1/sig^2 of the respective single frame. // Note that single frame rescaling is happening on top of this on both the science and // weight frames parameters.addMember("fluxScaleKey", &fluxScaleKey, def, "Scaling factor for flux (e.g. from WCS header) keyword in WCS header", "FLXSCALE"); parameters.addMember("segmentationName", &segmentationName, def, "segmentation map", "segment.fits"); parameters.addMember("segmentationPadding", &segmentationPadding, def | low, "padding around segmentation maps [pix]", 0, 0); parameters.addMember("stampSize", &stampSize, def | low, "Pixel size of img postage stamps", 64, 3); parameters.addMemberNoValue("DATA PROPERTIES:",0, "Input data"); parameters.addMember("sky", &sky, def, "sky level", 0.); //parameters.addMember("rn", &rn, def | low, // "Read noise, i.e. RMS at 0 ADU", 1000., 0.); //parameters.addMember("gain", &gain, def | low, // "Gain, e/ADU for Poissson, 0 for no Poisson", 1., 0.); parameters.addMemberNoValue("FDNT:",0, "Fitting parameters:"); parameters.addMember("order", &order, def, "FDNT GL-fit order (0 for FFT)", 0); parameters.addMember("maskSigma", &maskSigma, def, "GL and FDNT mask sigma (-1 auto)", -1. /*4.*/); // changed 21.11.12 parameters.addMemberNoValue("CATALOG TRANSLATION:",0, "Columns holding input data"); parameters.addMember("idCol", &idCol, def | low, "Object ID", 1, 1); parameters.addMember("segIdCol", &segIdCol, def | low, "Object ID in segmentation map; determined automatically if 0", 1, 0); parameters.addMember("raCol", &raCol, def | low, "RA centroid", 2, 1); parameters.addMember("decCol", &decCol, def | low, "DEC centroid", 3, 1); parameters.addMember("magCol", &magCol, def | low, "Magnitude", 4, 1); parameters.addMember("bgCol", &bgCol, def | low, "photometric background flux (zero if bgCol==0)", 5, 0); parameters.addMember("rCol", &rCol, def | low, "Half-light radius (in pixels)", 6, 1); parameters.addMember("g1Col", &g1Col, def | low, "g1 shape estimate (use native shape if 0)", 7, 0); parameters.addMember("g2Col", &g2Col, def | low, "g2 shape estimate (use native shape if 0)", 8, 0); parameters.addMember("aCol", &aCol, def | low, "Major axis (in WC)", 7, 1); parameters.addMember("bCol", &bCol, def | low, "Minor axis (in WC)", 8, 1); parameters.addMember("paCol", &paCol, def | low, "Position angle (in WC)", 9, 1); parameters.addMember("fwdColStart", &fwdColStart, def | low, "first forwarded column from input catalog", 0, 1); parameters.addMember("fwdColEnd", &fwdColEnd, def | low, "last forwarded column from input catalog", 0, 1); parameters.addMember("maxBadPixels", &maxBadPixels, def, "Maximum fraction of bad pixels in postage stamp", 0.1); parameters.addMember("maxBadFlux", &maxBadFlux, def, "Maximum fraction of model flux in bad pixels", 0.05); parameters.addMember("interpolationOrder", &interpolationOrder, def, "GL order for bad pixel interpolation", 4); } parameters.setDefault(); try { for (int i=1; i<argc; i++) { // Open & read all specified input files ifstream ifs(argv[i]); if (!ifs) { cerr << "Can't open file " << argv[i] << endl; exit(1); } try { parameters.setStream(ifs); } catch (std::runtime_error &m) { cerr << "In file " << argv[i] << ":" << endl; quit(m,1); } } // ... and from stdin try { parameters.setStream(cin); } catch (std::runtime_error &m) { cerr << "In stdin:" << endl; quit(m,1); } cerr << "# " << stringstuff::taggedCommandLine(argc, argv) << endl; parameters.dump(cerr); // (1) Read the PSF PSFExModel *model; try { model = new PSFExModel(psfName.c_str()); } catch (PSFExError &e) { cerr << "Error reading PSFEx model: " << e.what() << "; exiting." << endl; exit(1); } catch (...) { cerr << "Error reading PSFEx model; exiting." << endl; exit(1); } if (!model->selfTest(1, 3, psfOrder)) { // this is a very lenient self-test cerr << "PSFEx model did not pass self test; exiting." << endl; exit(1); } cerr << "reading image " << flush; // (2) Open image Image<> sci; FITSImage<> fits(fitsName); sci = fits.extract(); cerr << ", header " << flush; // (3) Read astrometry img::ImageHeader h; ifstream mapfs(wcsName.c_str()); if (!mapfs) { cerr << "Could not open astrometry file " << wcsName << "; trying FITS header in science frame" << endl; h = *(sci.header()); } else { h = img::HeaderFromStream(mapfs); } SCAMPMap *fullmap = new SCAMPMap(h,0); double xw, yw; fullmap->toWorld(0,0,xw,yw); #ifdef DEBUGFDNTPSFEX cerr << "# WCS " << xw << " " << yw << " is the (0,0) pixel WC w.r.t. the TP" << endl; #endif cerr << ", weight " << flush; // (4) Open weight image and read weight scale Image<> wt; FITSImage<> wtfits(weightName); wt = wtfits.extract(); cerr << "read, " << flush; HdrRecordBase* weightScaleRecord = h.find(weightScaleKey); double weightScale = 1.0; if (weightScaleRecord) weightScale = atof(weightScaleRecord->getValueString().c_str()); else cerr << "WARNING: weight scale key not found in header; assuming weight scale is 1.0\n"; cerr << "SCAMP weight scale: " << weightScale << endl; HdrRecordBase* fluxScaleRecord = h.find(fluxScaleKey); double fluxScale = 1.0; if (fluxScaleRecord) fluxScale = atof(fluxScaleRecord->getValueString().c_str()); else cerr << "WARNING: flux scale key not found in header; assuming flux scale is 1.0\n"; cerr << "SCAMP flux scale: " << fluxScale << endl; cerr << "reading segmentation map" << endl; Image<> seg; FITSImage<> fitsseg(segmentationName.c_str()); seg = fitsseg.extract(); // (5) rescale weight map Bounds<int> chip_bounds = sci.getBounds(); Bounds<int> safe_chip_bounds = chip_bounds; safe_chip_bounds.addBorder(-2); // the inverse variance scales with flux in the following way: weightScale = weightScale / (fluxScale*fluxScale); for (int iy=chip_bounds.getYMin(); iy<=chip_bounds.getYMax(); iy++) for (int ix=chip_bounds.getXMin(); ix<=chip_bounds.getXMax(); ix++) { // weight map just rescaled sky inverse-variance: wt(ix,iy) = wt(ix,iy) * weightScale; sci(ix,iy) = sci(ix,iy) * fluxScale; } // initialize sums UnweightedShearEstimator se; int ngood=0; int nfail=0; int nfail_post=0; int nfail_postmeas=0; int nfail_badpix=0; int nfail_bpgl=0; int nfail_bpff=0; int nfail_fdnt=0; int nfail_seg=0; // (6) Loop through objects int nread=MAX(idCol, raCol); nread = MAX(nread, decCol); nread = MAX(nread, segIdCol); nread = MAX(nread, rCol); nread = MAX(nread, aCol); nread = MAX(nread, bCol); nread = MAX(nread, paCol); nread = MAX(nread, bgCol); nread = MAX(nread, g1Col); nread = MAX(nread, g2Col); nread = MAX(nread, fwdColEnd); vector<string> readvals(nread); ifstream ccat(catName.c_str()); if (!ccat) { cerr << "Error opening catalog file " << catName << endl; exit(1); } string buffer; tmv::SymMatrix<double> covE(2); cout << "# id x_pix y_pix eta1 eta2 sig1 sig2 cov12 mu egFix fdFlags " << "considered_success forwarded_column" << endl; while (stringstuff::getlineNoComment(ccat, buffer)) { // all objects /* cerr << "######################################################" << endl << "// (a) Acquire info of object " << flush; */ istringstream iss(buffer); for (int i=0; i<nread; i++) iss >> readvals[i]; if (!iss) { cerr << "Bad catalog input line: " << buffer; exit(1); } string id = readvals[idCol-1]; //cerr << id << endl; double ra0 = atof(readvals[raCol-1].c_str()); double dec0 = atof(readvals[decCol-1].c_str()); double a_wc = atof(readvals[aCol-1].c_str()); double b_wc = atof(readvals[bCol-1].c_str()); double pa_wc = atof(readvals[paCol-1].c_str()); double r_pix = atof(readvals[rCol-1].c_str()); // FLUX_RADIUS in pixels, not wcs double bg = 0.; if (bgCol > 0) bg = atof(readvals[bgCol-1].c_str()); string fwd = ""; if (fwdColStart <= fwdColEnd && fwdColEnd > 0) { for (int i=max(1,fwdColStart); i<=fwdColEnd; i++) { fwd += readvals[i-1]; fwd += " "; } } double x_wc, y_wc; // tangent plane coordinates double x_pix, y_pix; fullmap->toWorld(x_pix, y_pix, x_wc, y_wc); #ifdef DEBUGFDNTPSFEX cerr << "(a) processing object at (RA,dec)=(" << ra0 << "," << dec0 << ")=(" << x_wc << "," << y_wc << ") " << "(x,y)=(" << x_pix << "," << y_pix << ")" << endl; #endif // deproject spherical coordinates to xi (x_wc) and eta (y_wc) SphericalICRS point(ra0*DEGREE, dec0*DEGREE); TangentPlane tp(point, fullmap->projection()); tp.getLonLat(x_wc, y_wc); x_wc /= DEGREE; y_wc /= DEGREE; try { //cerr << "# object at WCS " << x_wc << " " << y_wc << endl; // DEBUG fullmap->toPix(x_wc, y_wc, x_pix, y_pix); } catch (AstrometryError& e) { cerr << e.what() << endl; cerr << "(b) processing object at (RA,dec)=(" << ra0 << "," << dec0 << ")" << endl; cerr << "toPix failure" << endl; exit(0); } if (!safe_chip_bounds.includes(int(x_pix), int(y_pix))) continue; cerr << "######################################################" << endl << "// (a) Acquire info of object " << id << endl << "# object at WCS " << x_wc << " " << y_wc << endl; // DEBUG #ifdef DEBUGFDNTPSFEX cerr << "processing object at (RA,dec)=(" << ra0 << "," << dec0 << ")=(" << x_wc << "," << y_wc << ") " << "(x,y)=(" << x_pix << "," << y_pix << ")" << endl; #endif #ifdef DEBUGFDNTPSFEX cerr << "// (b) get the Jacobian of coordinate transformation at that position" << endl; #endif Matrix22 J = fullmap->dWorlddPix(x_pix,y_pix); double rescale = sqrt(fabs(J(0,0)*J(1,1)-J(0,1)*J(1,0))); // distorted approximate pixel scale: how much the scales are enlarged by WC transform #ifdef DEBUGFDNTPSFEX cerr << "rescaling by " << rescale << endl; cerr << "// (c) get PSF model at the position" << endl; #endif // generate model PSF at this location model->fieldPosition(x_pix, y_pix); // model now holds the psf model at this position cerr << "flux before normalization: " << model->sb()->getFlux() << endl; model->setFlux(1.0); // FWHM is twice the half-light radius for Gaussian psf, scaled to world coords double ee50psf = model->getFWHM()/2.*rescale; Ellipse psfBasis(0., 0., log(ee50psf/1.17)); // generate PSF image in WC SBDistort psfWCS(*(model->sb()),J(0,0),J(0,1),J(1,0),J(1,1)); cerr << "dWorld/dPix " << J; // J comes with its own endl cerr << ee50psf << endl; // sets flux of basis correctly to have flux normalization after distortion psfWCS.setFlux(1.); double dx = ee50psf / 2.35; // magic 4.7 factor from PSFEx cerr << "drawing psf postage stamp with dx=" << dx << endl; Image<> ipsf = psfWCS.draw(dx); // Measure PSF GL size & significance Image<> psfwt(ipsf.getBounds()); psfwt = pow(1e-5/dx, -2.); psfBasis.setMu( psfBasis.getMu() - log(dx)); GLSimple<> gl(ipsf, psfwt, psfBasis, 4); if (!gl.solve()) { cerr << "# Failed measuring psf, flags " << gl.getFlags() << "; ignoring object" << endl; continue; } psfBasis = gl.getBasis(); psfBasis.setMu( psfBasis.getMu() + log(dx)); #ifdef DEBUGFDNTPSFEX cerr << "# PSF e and GL sigma: " << psfBasis.getS() << " " << exp(psfBasis.getMu()) << endl; #endif PSFInformation psfinfo(psfWCS, psfBasis); #ifdef DEBUGFDNTPSFEX cerr << "// (d) Starting ellipse of galaxy" << endl; #endif double e1start = (a_wc*a_wc-b_wc*b_wc)/(a_wc*a_wc+b_wc*b_wc); double e2start = e1start * sin(2*pa_wc*PI/180.); e1start *= cos(2*pa_wc*PI/180.); cerr << "SExtractor ellipse r = " << r_pix*rescale << ", e = " << e1start << "," << e2start << endl; // all in wcs pixel coordinates Ellipse sexE(e1start, e2start, log(r_pix*rescale), x_wc, y_wc); Shear initShear; Ellipse initE; double g1_wc; double g2_wc; if (g1Col > 0 && g2Col > 0) { // read in g1, g2 (if available) g1_wc = atof(readvals[g1Col-1].c_str()); g2_wc = atof(readvals[g2Col-1].c_str()); double gabs = sqrt(g1_wc*g1_wc+g2_wc*g2_wc); if (gabs > 0.95) { // sanitize shear g1_wc=g1_wc*0.95/gabs; g2_wc=g2_wc*0.95/gabs; } initShear.setG1G2(g1_wc, g2_wc); initShear.getE1E2(e1start, e2start); initE = Ellipse(e1start, e2start, log(r_pix*rescale), x_wc, y_wc); // all in wcs } else if (g1Col <= 0 && g2Col <= 0) { // approximate g1, g2 with native shape (if g1, g2 not available) initE = sexE; } else { cerr << "g1Col / g2Col specification inconsistent, exiting" << endl; exit(2); } /* cerr << "starting ellipse r = " << r_pix*rescale << ", e = " << e1start << ", " << e2start << endl; */ #ifdef DEBUGFDNTPSFEX cerr << "// (e) building FitExposure" << endl; #endif FitExposure<>* fep; #ifdef DEBUGFDNTPSFEX cerr << "// get the postage stamp" << endl; #endif int xi0 = x_pix-stampSize/2; if (xi0 < chip_bounds.getXMin()) xi0 = chip_bounds.getXMin(); if ((xi0 + stampSize+1) > chip_bounds.getXMax()) xi0 = chip_bounds.getXMax() - stampSize - 1; int yi0 = y_pix-stampSize / 2; if (yi0 < chip_bounds.getYMin()) yi0 = chip_bounds.getYMin(); if ((yi0 + stampSize+1) > chip_bounds.getYMax()) yi0 = chip_bounds.getYMax() - stampSize - 1; #ifdef DEBUGFDNTPSFEX cerr << "// " << xi0 << " " << xi0+stampSize-1 << " " << yi0 << " " << yi0+stampSize-1 << endl; cerr << "// hopefully inside x=" << chip_bounds.getXMin() << ".." << chip_bounds.getXMax() << ", y=" << chip_bounds.getYMin() << ".." << chip_bounds.getYMax() << endl; #endif Bounds<int> stamp(xi0,xi0+stampSize-1, yi0, yi0+stampSize-1); cerr << "set bounds" << endl; Image<float> scistamp = sci.subimage(stamp).duplicate(); cerr << "sci bounds" << endl; Image<float> wtstamp = wt.subimage(stamp).duplicate(); cerr << "wt bounds" << endl; Image<float> segstamp = seg.subimage(stamp).duplicate(); cerr << "seg bounds" << endl; Image<double> xwstamp(stamp); Image<double> ywstamp(stamp); int segId = 0; if (segIdCol > 0) segId = atoi(readvals[segIdCol-1].c_str()); else { bool badSegID=false; // check a small square region for (int dx=0; dx<=1; dx++) { for (int dy=0; dy<=1; dy++) { //cerr << int(x_pix) + dx << " " << int(y_pix) + dy << endl; int dsegId = seg(int(x_pix)+dx, int(y_pix)+dy); if (!segId && dsegId) { segId = dsegId; } else if (dsegId && segId!=dsegId) { badSegID = true; } } } if (badSegID) { cerr << "# fail: could not get segmentation id for " << id << endl; #ifdef CHECKPLOTS ipsf.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_psf_badseg.fits",ipsf); wtstamp.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_wt_badseg.fits",wtstamp); scistamp.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_sci_badseg.fits",scistamp); segstamp.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_seg_badseg.fits",segstamp); #endif nfail++; nfail_seg++; continue; } } cerr << "got segid" << endl; try { for (int iy=stamp.getYMin(); iy<=stamp.getYMax(); iy++) { for (int ix=stamp.getXMin(); ix<=stamp.getXMax(); ix++) { double dxw,dyw; fullmap->toWorld(ix,iy,dxw,dyw); xwstamp(ix,iy) = dxw; ywstamp(ix,iy) = dyw; if (segstamp(ix,iy) && segstamp(ix,iy)!=segId) { //it's another object! for (int iiy=max(stamp.getYMin(),iy-segmentationPadding); iiy<=min(stamp.getYMax(),iy+segmentationPadding); iiy++) for (int iix=max(stamp.getXMin(),ix-segmentationPadding); iix<=min(stamp.getXMax(),ix+segmentationPadding); iix++) wtstamp(iix,iiy)=0.; } } } fep = new FitExposure<>(scistamp, wtstamp, xwstamp, ywstamp, 0, sky+bg); // stack background with sky-subtracted single frames == // photometric local background in stack flux scale } catch (...) { cerr << "# fail: could not get postage stamp for " << id << endl; nfail++; nfail_post++; delete fep; continue; } #ifdef DEBUGFDNTPSFEX cerr << "// (f) checking bad pixels" << endl; #endif double meanweight=0.; vector< Position<int> > bp = fep->badPixels(meanweight); cerr << "mean weight: " << meanweight << endl; if (bp.size()>maxBadPixels*stampSize*stampSize) { cerr << "# fail: " << id << " has too many bad pixels" << endl; #ifdef CHECKPLOTS ipsf.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_psf_badpix.fits",ipsf); wtstamp.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_wt_badpix.fits",wtstamp); scistamp.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_sci_badpix.fits",scistamp); segstamp.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_seg_badpix.fits",segstamp); #endif nfail++; nfail_badpix++; delete fep; continue; } #ifdef DEBUGFDNTPSFEX // residual image (science image with the GL model subtracted) Image<float> glstamp = sci.subimage(stamp).duplicate(); #endif // has bad pixels, but not too many to begin with: do GL interpolation if (bp.size() > 0) { #ifdef DEBUGFDNTPSFEX cerr << "# trying to interpolate " << bp.size() << " bad pixels" << endl; cerr << sexE << " " << interpolationOrder << endl; #endif GLSimple<> gal(*fep, sexE, interpolationOrder); if (!gal.solve()) { cerr << "# fail: GL fit failed for " << id << endl; #ifdef CHECKPLOTS ipsf.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_psf_bpgl.fits",ipsf); wtstamp.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_wt_bpgl.fits",wtstamp); scistamp.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_sci_bpgl.fits",scistamp); segstamp.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_seg_bpgl.fits",segstamp); #endif nfail++; nfail_bpgl++; delete fep; continue; } LVector bvec = gal.getB(); double fluxModel = bvec.flux(); Ellipse basis = gal.getBasis(); double missingFlux=0.; double scaleFactor = exp(basis.getMu()); for (vector< Position<int> >::iterator it=bp.begin(); it<bp.end(); it++) { LVector psi(bvec.getOrder()); Position<double> xunit = basis.inv(Position<double>(xwstamp((*it).x,(*it).y), ywstamp((*it).x,(*it).y))); psi.fillBasis(xunit.x, xunit.y, scaleFactor); scistamp((*it).x,(*it).y)=bvec.dot(psi); wtstamp((*it).x,(*it).y)=meanweight; // The interpolated pixel is assumed to have the mean weight of the good pixels; // this makes sense because in the Fourier code homogeneous uncertainties are // assumed missingFlux += scistamp((*it).x,(*it).y); scistamp((*it).x,(*it).y)+=sky+bg; } missingFlux *= rescale*rescale; // scale flux with coordinate system #ifdef DEBUGFDNTPSFEX for (int iy=stamp.getYMin(); iy<=stamp.getYMax(); iy++) { for (int ix=stamp.getXMin(); ix<=stamp.getXMax(); ix++) { LVector psi(bvec.getOrder()); Position<double> xunit = basis.inv(Position<double>(xwstamp(ix,iy), ywstamp(ix,iy))); psi.fillBasis(xunit.x, xunit.y, scaleFactor); glstamp(ix,iy) -= bvec.dot(psi); } } cerr << "# fluxModel = " << fluxModel << endl; cerr << "# scaleFactor = " << scaleFactor << endl; cerr << "# missingFlux = " << missingFlux << endl; #endif if (missingFlux/fluxModel > maxBadFlux) { cerr << "# fail: bad pixels in " << id << " have too high flux fraction" << endl; #ifdef CHECKPLOTS ipsf.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_psf_bpff.fits",ipsf); wtstamp.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_wt_bpff.fits",wtstamp); scistamp.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_sci_bpff.fits",scistamp); segstamp.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_seg_bpff.fits",segstamp); glstamp.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_glr_bpff.fits",glstamp); #endif nfail++; nfail_bpff++; delete fep; continue; } } #ifdef DEBUGFDNTPSFEX cerr << "// (g) running FDNT..." << flush; #endif FDNT<> fd(*fep, psfinfo, initE, order); fd.setMaskSigma(maskSigma); fd.GLAll(); bool success = fd.prepare(); if (success) cerr << " success!" << endl; else cerr << " failed." << endl; #ifdef DEBUGFDNTPSFEX cerr << "// (h) evaluating FDNT" << endl; #endif Shear targetS = fd.getBasis().getS(); cerr << targetS << endl; double prob; tmv::SymMatrix<double> covE(2,2); if (success) { cerr << "making the actual measurement" << endl; try { targetS = fd.shape2(prob, covE); // THIS IS THE ACTUAL MEASUREMENT!! } catch (...) { cerr << "an error occurred" << endl; } cerr << "made the actual measurement" << endl; // ??? Make flag mask an input parameter ??? success = !(fd.getFlags() & (DidNotConverge + Singularity + OutOfBounds + TooLarge + UnderSampled + TooElliptical + GLFailure)); } double eta1, eta2; targetS.getEta1Eta2(eta1, eta2); double egFix = 0.; double sig1 = 0., sig2 = 0.; double cov12 = 0.; if (success) { try { egFix = fd.shrinkResponse(targetS); cerr << "got shrink response" << endl; sig1 = sqrt(covE(0,0)); sig2 = sqrt(covE(1,1)); cov12 = covE(0,1); se.add(targetS, egFix, sig1, sig2); cerr << "good " << targetS << " " << egFix << " " << sig1 << " " << sig2 << endl; ngood++; } catch (...) { cerr << "an error occured on previously successful measurement" << endl; nfail++; nfail_postmeas++; success=false; } #ifdef CHECKPLOTS ipsf.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_psf_good.fits",ipsf); wtstamp.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_wt_good.fits",wtstamp); scistamp.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_sci_good.fits",scistamp); segstamp.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_seg_good.fits",segstamp); Image<> filter1 = fd.drawFilter1(targetS,initE); Image<> filter2 = fd.drawFilter2(targetS,initE); filter1.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_f1_good.fits",filter1); filter2.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_f2_good.fits",filter2); if (bp.size()>0) { glstamp.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_glr_good.fits",glstamp); } #endif } else { cerr << "# fail: some obscure thing in FDNT::prepare() happens for " << id << ", flags " << fd.getFlags() << endl; stringstream flags; flags << fd.getFlags(); #ifdef CHECKPLOTS ipsf.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_psf_fdnt_"+flags.str()+".fits",ipsf); wtstamp.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_wt_fdnt_"+flags.str()+".fits",wtstamp); scistamp.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_sci_fdnt_"+flags.str()+".fits",scistamp); segstamp.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_seg_fdnt_"+flags.str()+".fits",segstamp); if (bp.size()>0) { glstamp.shift(1,1); FITSImage<>::writeToFITS("check_"+id+"_glr_fdnt_"+flags.str()+".fits",glstamp); } #endif nfail++; nfail_fdnt++; } double mu = fd.getBasis().getMu(); cout << id << " " << ra0 << " " << dec0 << " " << x_pix << " " << y_pix //<< " " << mag << " " << eta1 << " " << eta2 << " " << sig1 << " " << sig2 << " " << cov12 << " " << mu << " " << egFix << " " << fd.getFlags() << " " << success << " " << fwd << endl; delete fep; } delete model; delete fullmap; // Print out mean shear estimate Shear S(se); double g1, g2, sig1, sig2; S.getG1G2(g1,g2); se.sigmaE(sig1,sig2, false); cout << fixed << setprecision(6); // Approximate the reduced-shear error as 1/2 of the distortion error cout << "# Means: " << g1 << " +- " << sig1/2 << " " << g2 << " +- " << sig2/2 << endl; cout << "# Failed / good " << nfail << " / " << ngood << endl; cout << "# Reasons for failure:\n# " << nfail_post << "\t couldn't get postage stamp\n# " << nfail_badpix << "\t had too many bad pixels\n# " << nfail_bpgl << "\t couldn't GL-interpolate bad pixels\n# " << nfail_bpff << "\t had too much flux in bad pixels\n# " << nfail_postmeas << "\t failed after measurement\n# " << nfail_fdnt << "\t had some error in FDNT\n# " << nfail_seg << "\t had ambiguous segmentation information\n"<< endl; } catch (std::runtime_error &m) { cerr << m.what() << endl; quit(m,1); } }