//# SpectralFit2.cc: Least Squares fitting of spectral elements: templated part //# Copyright (C) 2001,2002,2004 //# Associated Universities, Inc. Washington DC, USA. //# //# This library is free software; you can redistribute it and/or modify it //# under the terms of the GNU Library General Public License as published by //# the Free Software Foundation; either version 2 of the License, or (at your //# option) any later version. //# //# This library 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 Library General Public //# License for more details. //# //# You should have received a copy of the GNU Library General Public License //# along with this library; 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: SpectralFit2.tcc 21465 2014-06-19 05:56:56Z gervandiepen $ //# Includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace casa { //# NAMESPACE CASA - BEGIN //# Templated member functions template Bool SpectralFit::fit(const Vector &y, const Vector &x, const Vector *mask) { Vector sigma(x.nelements()); sigma = 1.0; return fit(sigma, y, x, mask); } template Bool SpectralFit::fit( const Vector &sigma, const Vector &y, const Vector &x, const Vector *mask ) { NonLinearFitLM fitter; iter_p = 0; // The functions to fit CompoundFunction > func; uInt ncomps = slist_p.nelements(); PtrHolder > > autodiff; for (uInt i=0; igetOrder(); SpectralElement::Types type = slist_p[i]->getType(); switch(type) { case SpectralElement::GAUSSIAN: { autodiff.set(new Gaussian1D >()); } break; case SpectralElement::POLYNOMIAL: { PolynomialSpectralElement *x = dynamic_cast(elem); autodiff.set(new Polynomial >(x->getDegree())); } break; case SpectralElement::COMPILED: // Allow fall through; these use the same code case SpectralElement::GMULTIPLET: { CompiledSpectralElement *x = dynamic_cast(elem); autodiff.set(new CompiledFunction >()); dynamic_cast > *>( autodiff.ptr() )->setFunction(x->getFunction()); } break; case SpectralElement::LORENTZIAN: { autodiff.set(new Lorentzian1D >()); } break; case SpectralElement::POWERLOGPOLY: { Vector parms = elem->get(); autodiff.set(new PowerLogarithmicPolynomial > (nparms)); } break; case SpectralElement::LOGTRANSPOLY: { LogTransformedPolynomialSpectralElement *x = dynamic_cast< LogTransformedPolynomialSpectralElement* >(elem); // treated as a polynomial for fitting purposes. The caller is responsible for passing the ln's of // the ordinate and obscissa values to the fitter. autodiff.set(new Polynomial > (x->getDegree())); } break; default: throw AipsError("SpectralFit::fit(): Logic Error: Unhandled SpectralElement type"); } Vector parms = elem->get(); Vector fixed = elem->fixed(); for (uInt j=0; j(parms[j], nparms, j); if (j == PCFSpectralElement::WIDTH && type == SpectralElement::GAUSSIAN) { (*autodiff)[j] *= GaussianSpectralElement::SigmaToFWHM; } autodiff->mask(j) = ! fixed[j]; } func.addFunction(*autodiff); } fitter.setFunction(func); // Max. number of iterations fitter.setMaxIter(50+ ncomps*10); // Convergence criterium fitter.setCriteria(0.001); // Fit Vector sol; Vector err; sol = fitter.fit(x, y, sigma, mask); err = fitter.errors(); // Number of iterations iter_p = fitter.currentIteration(); chiSq_p = fitter.getChi2(); uInt j = 0; Vector tmp, terr; for (uInt i=0; igetOrder(); tmp.resize(nparms); terr.resize(nparms); SpectralElement::Types type = element->getType(); for (uInt k=0; kset(tmp); element->setError(terr); } return fitter.converged(); } } //# NAMESPACE CASA - END