//# tProfileFit1D.cc: test the ProfileFit1D class //# Copyright (C) 1995,1996,1998,1999,2000,2001,2002,2004 //# Associated Universities, Inc. Washington DC, USA. //# //# This program is free software; you can redistribute it and/or modify it //# under the terms of the GNU General Public License as published by the Free //# Software Foundation; either version 2 of the License, or (at your option) //# any later version. //# //# This program is distributed in the hope that it will be useful, but WITHOUT //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for //# more details. //# //# You should have received a copy of the GNU General Public License along //# with this program; if not, write to the Free Software Foundation, Inc., //# 675 Massachusetts Ave, Cambridge, MA 02139, USA. //# //# Correspondence concerning AIPS++ should be addressed as follows: //# Internet email: aips2-request@nrao.edu. //# Postal address: AIPS++ Project Office //# National Radio Astronomy Observatory //# 520 Edgemont Road //# Charlottesville, VA 22903-2475 USA //# //# $Id: tProfileFit1D.cc 21451 2014-06-10 07:48:08Z gervandiepen $ #include #include #include #include #include #include #include #include #include #include #include void makeData (Vector& x, Vector& y, Vector& m, Double& amp, Double& cen, Double& sigma, Double& p0, Double& p1); void check (Double amp, Double cen, Double sigma, Double p0, Double p1, const SpectralList& l); void checkMasks (uInt n, const ProfileFit1D& fitter, Int start, Int end); GaussianMultipletSpectralElement makeMultiplet ( Vector& x, Vector& y, const Vector& amp, const Vector& cen, const Vector& sigma ); vector makeLorentzians ( Vector& x, Vector& y, const Vector& amp, const Vector& cen, const Vector& fwhm ); PowerLogPolynomialSpectralElement makePowerLogPoly( Vector&x, Vector& y, const Vector& coeffs ); PolynomialSpectralElement makePoly( Vector&x, Vector& y, const Vector& coeffs ); int main() { try { { // Data Vector x,y; Vector m; Double amp, cen, sig, p0, p1; makeData(x, y, m, amp, cen, sig, p0, p1); const uInt n = x.nelements(); // Make fitter, set data and fit ProfileFit1D fitter; fitter.setData (x,y,m); fitter.setGaussianElements (1); const SpectralElement *firstEl = fitter.getList(False)[0]; AlwaysAssert( firstEl->getType() == SpectralElement::GAUSSIAN, AipsError ); PolynomialSpectralElement p(1); fitter.addElement(p); AlwaysAssert(fitter.fit(), AipsError); // Check ok AlwaysAssert(fitter.getDataMask().nelements()==n, AipsError); AlwaysAssert(allEQ(fitter.getDataMask(), True), AipsError); AlwaysAssert(fitter.getRangeMask().nelements()==0, AipsError); AlwaysAssert(fitter.getTotalMask().nelements()==n, AipsError); AlwaysAssert(allEQ(fitter.getTotalMask(), True), AipsError); { const SpectralList& fitList = fitter.getList(True); check (amp, cen, sig, p0, p1, fitList); } { ProfileFit1D fitter2(fitter); const SpectralList& fitList = fitter2.getList(True); check (amp, cen, sig, p0, p1, fitList); } { ProfileFit1D fitter2; fitter2 = fitter; const SpectralList& fitList = fitter2.getList(True); check (amp, cen, sig, p0, p1, fitList); } // Set a range mask via indices { Vector start(1), end(1); start(0) = n/2; end(0) = start(0) + n/10; fitter.setRangeMask (start, end, True); // Check masks checkMasks (n, fitter, start(0), end(0)); // Now set range mask via abcissa values Vector startF(1), endF(1); startF(0) = x(start(0)); endF(0) = x(end(0)); fitter.setRangeMask (startF, endF, True); // Check masks checkMasks (n, fitter, start(0), end(0)); } } { Vector x, y, amp(2), cen(2), sigma(2); amp[0] = 1; amp[1] = 1; cen[0] = 10; cen[1] = 60; sigma[0] = 6; sigma[1] = 6; GaussianMultipletSpectralElement gm0 = makeMultiplet (x, y, amp, cen, sigma); ProfileFit1D fitter; Vector m (x.size(), True); fitter.setData (x,y,m); fitter.addElement(gm0); AlwaysAssert( fitter.getList(False).nelements() == 1, AipsError ); const SpectralElement *firstEl = fitter.getList(False)[0]; AlwaysAssert( firstEl->getType() == SpectralElement::GMULTIPLET, AipsError ); AlwaysAssert(fitter.fit(), AipsError); // Check ok AlwaysAssert(fitter.getDataMask().nelements() == x.size(), AipsError); AlwaysAssert(allEQ(fitter.getDataMask(), True), AipsError); AlwaysAssert(fitter.getRangeMask().nelements() == 0, AipsError); AlwaysAssert(fitter.getTotalMask().nelements() == x.size(), AipsError); AlwaysAssert(allEQ(fitter.getTotalMask(), True), AipsError); AlwaysAssert( *dynamic_cast( fitter.getList(True)[0] ) == *dynamic_cast( fitter.getList(False)[0] ), AipsError ); Matrix r(1, 3); GaussianMultipletSpectralElement gm = gm0; cout << "amplitude ratio constrained" << endl; fitter = ProfileFit1D(); fitter.setData (x,y,m); r = 0; r(0, 0) = 0.9; gm = GaussianMultipletSpectralElement(gm0.getGaussians(), r); fitter.addElement(gm); AlwaysAssert(fitter.fit(), AipsError); cout << *dynamic_cast( fitter.getList(True)[0] ) << endl; cout << "niter " << fitter.getNumberIterations() << endl; cout << endl; cout << "amplitude ratio constrained, sigma of reference fixed" << endl; fitter = ProfileFit1D(); fitter.setData (x,y,m); r = 0; r(0, 0) = 0.9; gm = GaussianMultipletSpectralElement(gm0.getGaussians(), r); Vector fixed(5, False); fixed[2] = True; gm.fix(fixed); fitter.addElement(gm); AlwaysAssert(fitter.fit(), AipsError); cout << *dynamic_cast( fitter.getList(True)[0] ) << endl; cout << "niter " << fitter.getNumberIterations() << endl; cout << endl; cout << "center offset constrained" << endl; fitter = ProfileFit1D(); fitter.setData (x,y,m); r = 0; r(0, 1) = 48.5; gm = GaussianMultipletSpectralElement(gm0.getGaussians(), r); fitter.addElement(gm); AlwaysAssert(fitter.fit(), AipsError); cout << *dynamic_cast( fitter.getList(True)[0] ) << endl; cout << "niter " << fitter.getNumberIterations() << endl; cout << endl; cout << "sigma ratio constrained" << endl; fitter = ProfileFit1D(); fitter.setData (x,y,m); r = 0; r(0, 2) = 0.9; gm = GaussianMultipletSpectralElement(gm0.getGaussians(), r); fitter.addElement(gm); AlwaysAssert(fitter.fit(), AipsError); cout << *dynamic_cast( fitter.getList(True)[0] ) << endl; cout << "niter " << fitter.getNumberIterations() << endl; cout << endl; } { Vector x, y, amp(2), cen(2), fwhm(2); amp[0] = 1.5; amp[1] = 4; cen[0] = 10; cen[1] = 60; fwhm[0] = 6; fwhm[1] = 6.5; vector lse = makeLorentzians (x, y, amp, cen, fwhm); ProfileFit1D fitter; Vector m (x.size(), True); fitter.setData (x,y,m); for (uInt i=0; igetType() == SpectralElement::LORENTZIAN, AipsError ); AlwaysAssert(fitter.fit(), AipsError); // Check ok AlwaysAssert(fitter.getDataMask().nelements() == x.size(), AipsError); AlwaysAssert(allEQ(fitter.getDataMask(), True), AipsError); AlwaysAssert(fitter.getRangeMask().nelements() == 0, AipsError); AlwaysAssert(fitter.getTotalMask().nelements() == x.size(), AipsError); AlwaysAssert(allEQ(fitter.getTotalMask(), True), AipsError); for (uInt i=0; i( fitter.getList(True)[i] ); LorentzianSpectralElement exp = lse[i]; AlwaysAssert(nearAbs(*got, exp, 1e-15), AipsError); } cout << "niter " << fitter.getNumberIterations() << endl; cout << endl; } cout << "*** Fit a power log polynomial" << endl; { ProfileFit1D fitter; Vector x, y; Vector estimates(2); estimates[0] = 0.5; estimates[1] = 2; makePowerLogPoly(x, y, estimates); Vector mask(x.size(), True); fitter.setData(x, y, mask); SpectralList list; estimates[1] = 1; estimates[0] = 1; list.add(PowerLogPolynomialSpectralElement(estimates)); fitter.setElements(list); AlwaysAssert(fitter.fit(), AipsError); Vector parms = fitter.getList(True)[0]->get(); cout << "parms " << parms << endl; AlwaysAssert(near(parms[0], 0.5) && near(parms[1], 2.0), AipsError); } { ProfileFit1D fitter; Vector x, y; Vector estimates(3); estimates[0] = 0.5; estimates[1] = 2; estimates[2] = 0; makePowerLogPoly(x, y, estimates); Vector mask(x.size(), True); fitter.setData(x, y, mask); SpectralList list; estimates[0] = 0.55; estimates[1] = 1.93; estimates[2] = 0.4; list.add(PowerLogPolynomialSpectralElement(estimates)); fitter.setElements(list); AlwaysAssert(fitter.fit(), AipsError); Vector parms = fitter.getList(True)[0]->get(); cout << "parms " << parms << endl; AlwaysAssert(near(parms[0], 0.5) && near(parms[1], 2.0), AipsError); } { ProfileFit1D fitter; Vector x, y; Vector mask(x.size(), True); Vector estimates(3); estimates[0] = 0.5; estimates[1] = 2; estimates[2] = 1; makePowerLogPoly(x, y, estimates); fitter.setData(x, y, mask); estimates[1] = 1.99; estimates[2] = 0.999; SpectralList list; list.add(PowerLogPolynomialSpectralElement(estimates)); fitter.setElements(list); AlwaysAssert(fitter.fit(), AipsError); Vector parms = fitter.getList()[0]->get(); cout << "parms " << parms << endl; AlwaysAssert( near(parms[0], 0.5, 1e-4) && near(parms[1], 2.0, 1e-4) && nearAbs(parms[2], 1.0, 1e-4), AipsError ); } { cout << "*** Fit a polynomial" << endl; ProfileFit1D fitter; Vector x, y; Vector mask(x.size(), True); Vector estimates(3); estimates[0] = 0.5; estimates[1] = 2; estimates[2] = 1; makePoly(x, y, estimates); fitter.setData(x, y, mask); SpectralList list; list.add(PolynomialSpectralElement(estimates)); fitter.setElements(list); AlwaysAssert(fitter.fit(), AipsError); Vector parms = fitter.getList()[0]->get(); cout << "parms " << parms << endl; cout << "niter " << fitter.getNumberIterations() << endl; AlwaysAssert(allNear(parms, estimates, 1e-5), AipsError); Vector bad(3); bad[0] = 2; bad[1] = 5; bad[2] = 3; list.clear(); list.add(PolynomialSpectralElement(bad)); fitter.clearList(); fitter.setElements(list); AlwaysAssert(fitter.fit(), AipsError); parms = fitter.getList()[0]->get(); cout << "niter " << fitter.getNumberIterations() << endl; cout << "parms " << parms << endl; AlwaysAssert(allNear(parms, estimates, 1e-5), AipsError); } cout << "OK" << endl; return 0; } catch (const AipsError& err) { cerr << err.getMesg() << endl; } return 1; } void makeData (Vector& x, Vector& y, Vector& m, Double& amp, Double& cen, Double& sigma, Double& p0, Double& p1) { Int n = 256; x.resize(n); y.resize(n); m.resize(n); indgen(x); x *= (2.3); x += (1.0); m = True; // amp = 10.0; cen = x(n/2); sigma = (x[n-1] - x[0]) / 50.0; p0 = 0.15; p1 = 1.2; GaussianSpectralElement g(amp, cen, sigma); cerr << "Gaussian: " << amp << ", " << cen << ", " << sigma << endl; cerr << "Polynomial: " << p0 << ", " << p1 << endl; // Vector pars(2); pars(0) = p0; pars(1) = p1; PolynomialSpectralElement p(pars); for (uInt i=0; i p; const SpectralElement *elG = list[0]; const SpectralElement *elP = list[1]; elG->get(p); cout << "p " << p << " amp " << amp << " tol " << tol << endl; AlwaysAssert(near(amp, p[0], tol), AipsError); AlwaysAssert(near(cen, p[1], tol), AipsError); AlwaysAssert(near(sig, p[2], tol), AipsError); p.resize(0); elP->get(p); AlwaysAssert(near(p0, p[0], tol), AipsError); AlwaysAssert(near(p1, p[1], tol), AipsError); } void checkMasks (uInt n, const ProfileFit1D& fitter, Int start, Int end) { Vector rangeMask = fitter.getRangeMask(); Vector totalMask = fitter.getTotalMask(); // AlwaysAssert(rangeMask.nelements()==n, AipsError); AlwaysAssert(totalMask.nelements()==n, AipsError); AlwaysAssert(allEQ(rangeMask, totalMask), AipsError); // IPosition iStart(1), iEnd(1); { iStart(0) = 0; iEnd(0) = start-1; Vector tmp = rangeMask(iStart, iEnd); AlwaysAssert(allEQ(tmp, False), AipsError); } { iStart(0) = start; iEnd(0) = end; Vector tmp = rangeMask(iStart, iEnd); AlwaysAssert(allEQ(tmp, True), AipsError); } { iStart(0) = end+1; iEnd(0) = n-1; Vector tmp = rangeMask(iStart, iEnd); AlwaysAssert(allEQ(tmp, False), AipsError); } } GaussianMultipletSpectralElement makeMultiplet ( Vector& x, Vector& y, const Vector& amp, const Vector& cen, const Vector& sigma ) { Double minx = cen[0] - 5*sigma[0]; Double maxx = cen[0] + 5*sigma[0]; for (uInt i=1; i g(amp.size()); Matrix r(g.size() - 1, 3, 0); for (uInt i=0; i 0) { r(i-1, 0) = amp[i]/amp[0]; } } GaussianMultipletSpectralElement gm(g, r); for (uInt i=0; i makeLorentzians ( Vector& x, Vector& y, const Vector& amp, const Vector& cen, const Vector& fwhm ) { Double minx = cen[0] - 5*fwhm[0]; Double maxx = cen[0] + 5*fwhm[0]; for (uInt i=1; i lse; for (uInt i=0; i&x, Vector& y, const Vector& coeffs ) { x.resize(10); x[0] = 1; x[1] = 3; x[2] = 5; x[3] = 6; x[4] = 8; x[5] = 10; x[6] = 12; x[7] = 15; x[8] = 20; x[9] = 25; y.resize(x.size()); PowerLogPolynomialSpectralElement plp(coeffs); for (uInt i=0; i&x, Vector& y, const Vector& coeffs ) { x.resize(10); x[0] = 1; x[1] = 3; x[2] = 5; x[3] = 6; x[4] = 8; x[5] = 10; x[6] = 12; x[7] = 15; x[8] = 20; x[9] = 25; y.resize(x.size()); PolynomialSpectralElement poly(coeffs); for (uInt i=0; i