Line data Source code
1 : //# Copyright (C) 1993,1994,1995,1996,1999,2001
2 : //# Associated Universities, Inc. Washington DC, USA.
3 : //#
4 : //# This library is free software; you can redistribute it and/or modify it
5 : //# under the terms of the GNU Library General Public License as published by
6 : //# the Free Software Foundation; either version 2 of the License, or (at your
7 : //# option) any later version.
8 : //#
9 : //# This library is distributed in the hope that it will be useful, but WITHOUT
10 : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 : //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 : //# License for more details.
13 : //#
14 : //# You should have received a copy of the GNU Library General Public License
15 : //# along with this library; if not, write to the Free Software Foundation,
16 : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
17 : //#
18 : //# Correspondence concerning AIPS++ should be addressed as follows:
19 : //# Internet email: casa-feedback@nrao.edu.
20 : //# Postal address: AIPS++ Project Office
21 : //# National Radio Astronomy Observatory
22 : //# 520 Edgemont Road
23 : //# Charlottesville, VA 22903-2475 USA
24 : //#
25 :
26 : #include <components/SpectralComponents/SpectralListFactory.h>
27 :
28 : #include <components/SpectralComponents/GaussianSpectralElement.h>
29 : #include <components/SpectralComponents/GaussianMultipletSpectralElement.h>
30 : #include <components/SpectralComponents/LorentzianSpectralElement.h>
31 : #include <components/SpectralComponents/PowerLogPolynomialSpectralElement.h>
32 : #include <components/SpectralComponents/LogTransformedPolynomialSpectralElement.h>
33 :
34 : #include <stdcasa/StdCasa/CasacSupport.h>
35 :
36 : using namespace casacore;
37 : using namespace casac;
38 :
39 : using namespace casacore;
40 : namespace casa {
41 :
42 93 : SpectralList SpectralListFactory::create(
43 : LogIO& log, const variant& pampest,
44 : const variant& pcenterest, const variant& pfwhmest,
45 : const variant& pfix, const variant& gmncomps,
46 : const variant& gmampcon, const variant& gmcentercon,
47 : const variant& gmfwhmcon, const vector<double>& gmampest,
48 : const vector<double>& gmcenterest, const vector<double>& gmfwhmest,
49 : const variant& gmfix, const variant& pfunc,
50 : const variant& plpest, const variant& plpfix,
51 : const variant& ltpest, const variant& ltpfix
52 : ) {
53 93 : vector<double> myampest = toVectorDouble(pampest, "pampest");
54 93 : vector<double> mycenterest = toVectorDouble(pcenterest, "pcenterest");
55 93 : vector<double> myfwhmest = toVectorDouble(pfwhmest, "pfwhmest");
56 93 : vector<string> myfix = toVectorString(pfix, "pfix");
57 93 : vector<string> myfunc = toVectorString(pfunc, "pfunc");
58 93 : vector<double> myplpest = toVectorDouble(plpest, "plpest");
59 93 : vector<bool> myplpfix = toVectorBool(plpfix, "plpfix");
60 93 : vector<double> myltpest = toVectorDouble(ltpest, "ltpest");
61 93 : vector<bool> myltpfix = toVectorBool(ltpfix, "ltpfix");
62 :
63 93 : vector<int> mygmncomps = gmncomps.type() == variant::INT
64 93 : && gmncomps.toInt() == 0
65 93 : ? vector<int>(0)
66 279 : : toVectorInt(gmncomps, "gmncomps");
67 93 : vector<double> mygmampcon = toVectorDouble(gmampcon, "gmampcon");
68 93 : vector<double> mygmcentercon = toVectorDouble(gmcentercon, "gmcentercon");
69 93 : vector<double> mygmfwhmcon = toVectorDouble(gmfwhmcon, "gmfwhmcon");
70 93 : vector<string> mygmfix = toVectorString(gmfix, "gmfix");
71 : Bool makeSpectralList = (
72 93 : mygmncomps.size() + myplpest.size() + myltpest.size() > 0
73 240 : || ! (
74 75 : myampest.size() == 0
75 72 : && mycenterest.size() == 0
76 72 : && myfwhmest.size() == 0
77 : )
78 93 : );
79 93 : SpectralList spectralList;
80 93 : Bool gfixSpecified = (myfix.size() > 0);
81 93 : if (! makeSpectralList) {
82 72 : if (gfixSpecified) {
83 : log << "The fix array is specified but no corresponding estimates are "
84 : << "set via ampest, centerest, and fwhmest. The fix array will be ignored."
85 0 : << LogIO::WARN;
86 : }
87 72 : return spectralList;
88 : }
89 21 : uInt mynpcf = myampest.size();
90 21 : if (myfunc.size() == 0) {
91 20 : myfunc.resize(myampest.size(), "G");
92 : }
93 21 : ThrowIf(
94 : mycenterest.size() != mynpcf
95 : || myfwhmest.size() != mynpcf
96 : || myfunc.size() != mynpcf,
97 : "pampest, pcenterest, pfwhmest, and pfunc arrays "
98 : "must all be the same length"
99 : );
100 21 : ThrowIf(
101 : gfixSpecified && myfix.size() != mynpcf,
102 : "If the gfix array is specified the number of "
103 : "elements it has must be the same as the number of elements "
104 : "in the ampest array even if some elements are empty strings"
105 : );
106 21 : if (mygmncomps.size() > 0) {
107 2 : _addGaussianMultiplets(
108 : spectralList, log, mygmncomps, mygmampcon,
109 : mygmcentercon, mygmfwhmcon,
110 : gmampest, gmcenterest, gmfwhmest,
111 : mygmfix
112 : );
113 : }
114 27 : for (uInt i=0; i<mynpcf; i++) {
115 6 : String func(myfunc[i]);
116 6 : func.upcase();
117 6 : Bool doGauss = func.startsWith("G");
118 6 : Bool doLorentz = func.startsWith("L");
119 6 : if (! doGauss && ! doLorentz) {
120 0 : log << myfunc[i] << " does not minimally match 'gaussian' or 'lorentzian'"
121 0 : << LogIO::EXCEPTION;
122 : }
123 : std::unique_ptr<PCFSpectralElement> pcf(
124 : doGauss
125 : ? dynamic_cast<PCFSpectralElement*>(
126 : new GaussianSpectralElement(
127 4 : myampest[i], mycenterest[i],
128 4 : GaussianSpectralElement::sigmaFromFWHM(myfwhmest[i])
129 4 : )
130 : )
131 : : doLorentz
132 4 : ? dynamic_cast<PCFSpectralElement*>(
133 : new LorentzianSpectralElement(
134 2 : myampest[i], mycenterest[i], myfwhmest[i]
135 2 : )
136 : )
137 : : 0
138 16 : );
139 6 : if (gfixSpecified) {
140 0 : pcf->fixByString(myfix[i]);
141 : }
142 6 : if (! spectralList.add(*pcf)) {
143 : log << "Unable to add element to spectral list"
144 0 : << LogIO::EXCEPTION;
145 : }
146 6 : }
147 21 : if (myplpest.size() > 0) {
148 11 : _addPowerLogPolynomial(
149 : spectralList, log, myplpest, myplpfix
150 : );
151 : }
152 21 : if (myltpest.size() > 0) {
153 5 : _addLogTransformedPolynomial(
154 : spectralList, myltpest, myltpfix
155 : );
156 : }
157 21 : return spectralList;
158 93 : }
159 :
160 2 : void SpectralListFactory::_addGaussianMultiplets(
161 : SpectralList& spectralList,
162 : LogIO& log,
163 : const vector<int>& mygmncomps,
164 : vector<double>& mygmampcon,
165 : vector<double>& mygmcentercon,
166 : vector<double>& mygmfwhmcon,
167 : const vector<double>& gmampest,
168 : const vector<double>& gmcenterest, const vector<double>& gmfwhmest,
169 : const vector<string>& mygmfix
170 : ) {
171 2 : uInt sum = 0;
172 4 : for (uInt i=0; i<mygmncomps.size(); i++) {
173 2 : if (mygmncomps[i] <= 0) {
174 0 : log << "All elements of gmncomps must be greater than 0" << LogIO::EXCEPTION;
175 : }
176 2 : sum += mygmncomps[i];
177 : }
178 2 : if (gmampest.size() != sum) {
179 : log << "gmampest must have exactly "
180 0 : << sum << " elements" << LogIO::EXCEPTION;
181 : }
182 2 : if (gmcenterest.size() != sum) {
183 : log << "gmcenterest must have exactly "
184 0 : << sum << " elements" << LogIO::EXCEPTION;
185 : }
186 2 : if (gmfwhmest.size() != sum) {
187 : log << "gmfwhmest must have exactly "
188 0 : << sum << " elements" << LogIO::EXCEPTION;
189 : }
190 2 : if (mygmfix.size() > 0 && mygmfix.size() != sum) {
191 : log << "gmfwhmest must have either zero or " << sum
192 : << " elements, even if some are empty strings."
193 0 : << LogIO::EXCEPTION;
194 : }
195 2 : uInt nConstraints = sum - mygmncomps.size();
196 2 : if (mygmampcon.size() == 0) {
197 0 : mygmampcon = vector<double>(nConstraints, 0);
198 : }
199 2 : else if (
200 2 : mygmampcon.size() > 0
201 2 : && mygmampcon.size() != nConstraints
202 : ) {
203 : log << "If specified, gmampcon must have exactly "
204 : << nConstraints << " elements, even if some are zero"
205 0 : << LogIO::EXCEPTION;
206 : }
207 2 : if (mygmcentercon.size() == 0) {
208 0 : mygmcentercon = vector<double>(nConstraints, 0);
209 : }
210 2 : else if (
211 2 : mygmcentercon.size() > 0
212 2 : && mygmcentercon.size() != nConstraints
213 : ) {
214 : log << "If specified, gmcentercon must have exactly "
215 : << nConstraints << " elements, even if some are zero"
216 0 : << LogIO::EXCEPTION;
217 : }
218 2 : if (mygmfwhmcon.size() == 0) {
219 2 : mygmfwhmcon = vector<double>(nConstraints, 0);
220 : }
221 0 : else if (
222 0 : mygmfwhmcon.size() > 0
223 0 : && mygmfwhmcon.size() != nConstraints
224 : ) {
225 : log << "If specified, gmfwhmcon must have exactly "
226 : << nConstraints << " elements, even if some are zero"
227 0 : << LogIO::EXCEPTION;
228 : }
229 2 : uInt compNumber = 0;
230 4 : for (uInt i=0; i<mygmncomps.size(); i++) {
231 2 : if (mygmncomps[i] < 0) {
232 : log << "All elements of gmncomps must be positive"
233 0 : << LogIO::EXCEPTION;
234 : }
235 2 : vector<GaussianSpectralElement> g(mygmncomps[i]);
236 2 : Matrix<Double> constraints(mygmncomps[i] - 1, 3);
237 8 : for (uInt j=0; j<(uInt)mygmncomps[i]; j++) {
238 18 : g[j] = GaussianSpectralElement(
239 6 : gmampest[compNumber], gmcenterest[compNumber],
240 6 : GaussianSpectralElement::sigmaFromFWHM(gmfwhmest[compNumber])
241 6 : );
242 6 : if (mygmfix.size() > 0) {
243 0 : g[j].fixByString(mygmfix[compNumber]);
244 : }
245 6 : if (j > 0) {
246 4 : constraints(j-1, 0) = mygmampcon[compNumber - (i+1)];
247 4 : constraints(j-1, 1) = mygmcentercon[compNumber - (i+1)];
248 4 : constraints(j-1, 2) = mygmfwhmcon[compNumber - (i+1)];
249 : }
250 6 : compNumber++;
251 : }
252 2 : if (
253 2 : ! spectralList.add(
254 4 : GaussianMultipletSpectralElement(g, constraints)
255 : )
256 : ) {
257 : log << "Unable to add gaussian multiplet to spectral list"
258 0 : << LogIO::EXCEPTION;
259 : }
260 2 : }
261 2 : }
262 :
263 11 : void SpectralListFactory::_addPowerLogPolynomial(
264 : SpectralList& spectralList,
265 : LogIO& log, vector<double>& myplpest,
266 : vector<bool>& myplpfix
267 : ) {
268 11 : uInt nest = myplpest.size();
269 11 : if (nest < 2) {
270 : log << "Number of elements in the power log polynomial estimates list must be at least 2"
271 0 : << LogIO::EXCEPTION;
272 : }
273 11 : uInt nfix = myplpfix.size();
274 11 : if (nfix == 0) {
275 9 : myplpfix = vector<bool>(nest, false);
276 : }
277 2 : else if (nfix != myplpest.size()) {
278 : log << "Number of elements in the power logarithmic polynomial fixed parameter list must "
279 : << "either be 0 or equal to the number of elements in the estimates list"
280 0 : << LogIO::EXCEPTION;
281 : }
282 11 : Vector<double> const myplpestV(myplpest);
283 11 : Vector<bool> const myplpfixV(myplpfix);
284 11 : PowerLogPolynomialSpectralElement plp(myplpestV);
285 11 : plp.fix(myplpfixV);
286 11 : spectralList.add(plp);
287 11 : }
288 :
289 5 : void SpectralListFactory::_addLogTransformedPolynomial(
290 : SpectralList& spectralList,
291 : vector<double>& myltpest,
292 : vector<bool>& myltpfix
293 : ) {
294 5 : uInt nest = myltpest.size();
295 5 : ThrowIf(
296 : nest < 2,
297 : "Number of elements in the log transformed polynomial "
298 : "estimates list must be at least 2"
299 : );
300 5 : uInt nfix = myltpfix.size();
301 5 : if (nfix == 0) {
302 4 : myltpfix = vector<bool>(nest, false);
303 : }
304 : else {
305 1 : ThrowIf(
306 : nfix != myltpest.size(),
307 : "Number of elements in the logarithmic transformed polynomial "
308 : "fixed parameter list must either be 0 or equal to the number "
309 : "of elements in the estimates list"
310 : );
311 : }
312 5 : Vector<double> const myltpestV(myltpest);
313 5 : Vector<bool> const myltpfixV(myltpfix);
314 5 : LogTransformedPolynomialSpectralElement ltp(myltpestV);
315 5 : ltp.fix(myltpfixV);
316 5 : spectralList.add(ltp);
317 5 : }
318 :
319 : using namespace casacore;
320 : } // end namespace casa
|