//# Spectral2Element.cc: Record conversion for SpectralElement //# Copyright (C) 2001,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: Spectral2Element.cc 20652 2009-07-06 05:04:32Z Malte.Marquarding $ //# Includes #include <casacore/casa/Containers/Record.h> #include <memory> #include <components/SpectralComponents/CompiledSpectralElement.h> #include <components/SpectralComponents/GaussianSpectralElement.h> #include <components/SpectralComponents/GaussianMultipletSpectralElement.h> #include <components/SpectralComponents/LogTransformedPolynomialSpectralElement.h> #include <components/SpectralComponents/LorentzianSpectralElement.h> #include <components/SpectralComponents/PolynomialSpectralElement.h> #include <components/SpectralComponents/PowerLogPolynomialSpectralElement.h> #include <components/SpectralComponents/SpectralElementFactory.h> using namespace casacore; namespace casa { //# NAMESPACE CASA - BEGIN SpectralElement* SpectralElementFactory::fromRecord( const RecordInterface &in ) { std::unique_ptr<SpectralElement> specEl; String origin = "SpectralElementFactory::fromRecord: "; if ( ! in.isDefined("type") || in.type(in.idToNumber(RecordFieldId("type"))) != TpString ) { throw AipsError("Record does not represent a SpectralElement"); } String stp; SpectralElement::Types tp; in.get(RecordFieldId("type"), stp); if (!SpectralElement::toType(tp, stp)) { throw AipsError("Unknown spectral type in SpectralElement::fromRecord\n"); } Vector<Double> errs; // Get the errors if defined in record if (in.isDefined("errors")) { DataType dataType = in.dataType("errors"); if (dataType == TpArrayDouble) { in.get("errors", errs); } else if (dataType == TpArrayFloat) { Vector<Float> v; in.get("errors", v); errs.resize(v.nelements()); convertArray(errs, v); } else if (dataType == TpArrayInt) { Vector<Int> v; in.get("errors", v); errs.resize(v.nelements()); convertArray(errs, v); } else { throw AipsError( "SpectralElement::fromRecord: errors field " "must be double, float or int\n" ); } } Vector<Double> param; if (in.isDefined(("parameters"))) { DataType dataType = in.dataType("parameters"); if (dataType == TpArrayDouble) { in.get("parameters", param); } else if (dataType == TpArrayFloat) { Vector<Float> v; in.get("parameters", v); param.resize(v.nelements()); convertArray(param, v); } else if (dataType == TpArrayInt) { Vector<Int> v; in.get("parameters", v); param.resize(v.nelements()); convertArray(param, v); } else { throw AipsError( origin + "SpectralElement::fromRecord: parameters field " "must be double, float or int\n" ); } } // Make sizes of errors and params equal if (errs.nelements() == 0) { errs.resize(param.nelements()); errs = 0.0; } if (errs.nelements() != param.nelements()) { throw AipsError( origin + "SpectralElement::fromRecord must have equal lengths " "for parameters and errors fields" ); } switch (tp) { case SpectralElement::GAUSSIAN: if (param.nelements() != 3) { throw AipsError( origin + "Illegal number of parameters for Gaussian element" ); } if (param(2) <= 0.0) { throw AipsError( origin + "The width of a Gaussian element must be positive" ); } param(2) = GaussianSpectralElement::sigmaFromFWHM (param(2)); errs(2) = GaussianSpectralElement::sigmaFromFWHM (errs(2)); specEl = std::unique_ptr<SpectralElement>(new GaussianSpectralElement(param(0), param(1), param(2))); specEl->setError(errs); break; case SpectralElement::LORENTZIAN: if (param.nelements() != 3) { throw AipsError( "Illegal number of parameters for Lorentzian element" ); } if (param(2) <= 0.0) { throw AipsError( "The width of a Lorentzian element must be positive" ); } specEl = std::unique_ptr<SpectralElement>(new LorentzianSpectralElement(param(0), param(1), param(2))); specEl->setError(errs); break; case SpectralElement::POLYNOMIAL: if (param.nelements() == 0) { throw AipsError( "Polynomial spectral element must have order " "of at least zero" ); } specEl = std::unique_ptr<SpectralElement>(new PolynomialSpectralElement(param.nelements() - 1)); specEl->set(param); specEl->setError(errs); break; case SpectralElement::COMPILED: if ( in.isDefined("compiled") && in.type(in.idToNumber(RecordFieldId("compiled"))) == TpString ) { String function; in.get(RecordFieldId("compiled"), function); specEl = std::unique_ptr<SpectralElement>(new CompiledSpectralElement(function, param)); specEl->setError(errs); } else { throw AipsError( "No compiled string in SpectralElement::fromRecord\n" ); } break; case SpectralElement::GMULTIPLET: { if (! in.isDefined("gaussians")) { throw AipsError("gaussians not defined in record"); } if (! in.isDefined("fixedMatrix")) { throw AipsError("fixed matrix not defined in record"); } Record gaussians = in.asRecord("gaussians"); uInt i = 0; std::vector<GaussianSpectralElement> comps(0); while(true) { String id = "*" + String::toString(i); if (gaussians.isDefined(id)) { std::unique_ptr<SpectralElement> gauss(fromRecord(gaussians.asRecord(id))); comps.push_back( *dynamic_cast<GaussianSpectralElement*>( gauss.get() ) ); i++; } else { break; } } Matrix<Double> fixedMatrix = in.asArrayDouble("fixedMatrix"); fixedMatrix.reform(IPosition(2, comps.size()-1, 3)); specEl = std::unique_ptr<SpectralElement>(new GaussianMultipletSpectralElement(comps, fixedMatrix)); } break; case SpectralElement::POWERLOGPOLY: { specEl = std::unique_ptr<SpectralElement>(new PowerLogPolynomialSpectralElement(param)); specEl->set(param); specEl->setError(errs); } break; case SpectralElement::LOGTRANSPOLY: { specEl = std::unique_ptr<SpectralElement>(new LogTransformedPolynomialSpectralElement(param)); specEl->setError(errs); } break; default: throw AipsError( "Unhandled or illegal spectral element record in " "SpectralElementFactory::fromRecord\n" ); } if (in.isDefined("fixed")) { specEl->fix(in.asArrayBool("fixed")); } // ready to return, fish out the pointer and return it without deleting it SpectralElement *sp = specEl.get(); specEl.release( ); return sp; } } //# NAMESPACE CASA - END