Line data Source code
1 : //# ComponentList.cc: this defines the ComponentList implementation
2 : //# Copyright (C) 1996,1997,1998,1999,2000,2001,2002
3 : //# Associated Universities, Inc. Washington DC, USA.
4 : //#
5 : //# This library is free software; you can redistribute it and/or modify it
6 : //# under the terms of the GNU Library General Public License as published by
7 : //# the Free Software Foundation; either version 2 of the License, or (at your
8 : //# option) any later version.
9 : //#
10 : //# This library is distributed in the hope that it will be useful, but WITHOUT
11 : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 : //# License for more details.
14 : //#
15 : //# You should have received a copy of the GNU Library General Public License
16 : //# along with this library; if not, write to the Free Software Foundation,
17 : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
18 : //#
19 : //# Correspondence concerning AIPS++ should be addressed as follows:
20 : //# Internet email: casa-feedback@nrao.edu.
21 : //# Postal address: AIPS++ Project Office
22 : //# National Radio Astronomy Observatory
23 : //# 520 Edgemont Road
24 : //# Charlottesville, VA 22903-2475 USA
25 : //#
26 : //# $Id: ComponentList.cc 21229 2012-04-02 12:00:20Z gervandiepen $
27 :
28 : #include <components/ComponentModels/ComponentList.h>
29 : #include <components/ComponentModels/ComponentType.h>
30 : #include <components/ComponentModels/Flux.h>
31 : #include <casacore/tables/Tables/ScalarColumn.h>
32 : #include <casacore/tables/Tables/ScaColDesc.h>
33 : #include <casacore/tables/Tables/ScaRecordColDesc.h>
34 : #include <components/ComponentModels/ComponentShape.h>
35 : #include <components/ComponentModels/SpectralModel.h>
36 : #include <casacore/measures/TableMeasures/ScalarMeasColumn.h>
37 : #include <casacore/measures/TableMeasures/ArrayQuantColumn.h>
38 : #include <casacore/measures/TableMeasures/ScalarQuantColumn.h>
39 : #include <casacore/measures/TableMeasures/TableMeasDesc.h>
40 : #include <casacore/measures/TableMeasures/TableMeasRefDesc.h>
41 : #include <casacore/measures/TableMeasures/TableMeasValueDesc.h>
42 : #include <casacore/measures/TableMeasures/TableQuantumDesc.h>
43 : #include <casacore/casa/Arrays/Array.h>
44 : #include <casacore/casa/Arrays/ArrayMath.h>
45 : #include <casacore/casa/Arrays/ArrayLogical.h>
46 : #include <casacore/casa/Arrays/Vector.h>
47 : #include <casacore/casa/Arrays/Cube.h>
48 : #include <casacore/casa/Exceptions/Error.h>
49 : #include <casacore/casa/Logging/LogIO.h>
50 : #include <casacore/casa/BasicSL/Constants.h>
51 : #include <casacore/casa/BasicSL/Complex.h>
52 : #include <casacore/casa/BasicMath/Math.h>
53 : #include <casacore/measures/Measures/MDirection.h>
54 : #include <casacore/measures/Measures/MFrequency.h>
55 : #include <casacore/measures/Measures/MCDirection.h>
56 : #include <casacore/measures/Measures/MCFrequency.h>
57 : #include <casacore/casa/Quanta/MVFrequency.h>
58 : #include <casacore/casa/Quanta/MVAngle.h>
59 : #include <casacore/casa/Quanta/MVDirection.h>
60 : #include <casacore/measures/Measures/MeasConvert.h>
61 : #include <casacore/casa/Containers/ValueHolder.h>
62 : #include <casacore/casa/Quanta/Quantum.h>
63 : #include <casacore/casa/Quanta/Unit.h>
64 : #include <casacore/casa/OS/Path.h>
65 : #include <casacore/tables/Tables/ArrColDesc.h>
66 : #include <casacore/tables/Tables/ArrayColumn.h>
67 : #include <casacore/tables/Tables/ColumnDesc.h>
68 : #include <casacore/tables/Tables/ScaColDesc.h>
69 : #include <casacore/tables/Tables/ScalarColumn.h>
70 : #include <casacore/tables/Tables/SetupNewTab.h>
71 : #include <casacore/tables/Tables/TableDesc.h>
72 : #include <casacore/tables/Tables/ColDescSet.h>
73 : #include <casacore/tables/Tables/TableLock.h>
74 : #include <casacore/tables/Tables/TableProxy.h>
75 : #include <casacore/tables/Tables/TableRecord.h>
76 : #include <casacore/tables/DataMan/TiledCellStMan.h>
77 : #include <casacore/casa/Utilities/Assert.h>
78 : #include <casacore/casa/Utilities/GenSort.h>
79 : #include <casacore/casa/Utilities/Sort.h>
80 : #include <casacore/casa/BasicSL/String.h>
81 : #include <casacore/casa/Containers/Record.h>
82 : #include <stdcasa/StdCasa/CasacSupport.h>
83 : #include <stdcasa/variant.h>
84 : #include <memory>
85 :
86 : using namespace casacore;
87 : using namespace casac;
88 : namespace casa { //# NAMESPACE CASA - BEGIN
89 :
90 : const String fluxName = "Flux";
91 : const String fluxUnitName = "Flux_Unit";
92 : const String fluxPolName = "Flux_Polarisation";
93 : const String fluxErrName = "Flux_Error";
94 : const String shapeName = "Shape";
95 : const String refDirName = "Reference_Direction";
96 : const String dirErrName = "Direction_Error";
97 : const String dirErrUnitName = "Direction_Error_Units";
98 : const String shapeParName = "Shape_Parameters";
99 : const String shapeErrName = "Shape_Error";
100 : const String spectrumName = "Spectrum_Shape";
101 : const String refFreqName = "Reference_Frequency";
102 : const String freqErrName = "Frequency_Error";
103 : const String spectralRecordName = "Spectral_Record";
104 : const String freqErrUnitName = "Frequency_Error_Units";
105 : const String spectParName = "Spectral_Parameters";
106 : const String spectErrName = "Spectral_Error";
107 : const String labelName = "Label";
108 : const String optParColName = "Optional_Parameters";
109 :
110 :
111 25759 : ComponentList::ComponentList()
112 25759 : :itsList(),
113 25759 : itsNelements(0),
114 25759 : itsTable(),
115 25759 : itsROFlag(false),
116 25759 : itsSelectedFlags(),
117 25759 : itsOrder(),
118 25759 : itsAddOptCol(false),
119 25759 : itsRewriteTable(True)
120 : {
121 25759 : AlwaysAssert(ok(), AipsError);
122 25759 : }
123 :
124 31 : ComponentList::ComponentList(const Path& fileName, Bool readOnly, Bool rewriteTable)
125 31 : :itsList(),
126 31 : itsNelements(0),
127 31 : itsTable(),
128 31 : itsROFlag(false),
129 31 : itsSelectedFlags(),
130 31 : itsOrder(),
131 31 : itsAddOptCol(false),
132 31 : itsRewriteTable(rewriteTable)
133 : {
134 31 : readTable(fileName, readOnly);
135 31 : AlwaysAssert(ok(), AipsError);
136 31 : }
137 :
138 37 : ComponentList::ComponentList(const ComponentList& other)
139 37 : :itsList(other.itsList),
140 37 : itsNelements(other.itsNelements),
141 37 : itsTable(other.itsTable),
142 37 : itsROFlag(other.itsROFlag),
143 37 : itsSelectedFlags(other.itsSelectedFlags),
144 37 : itsOrder(other.itsOrder),
145 37 : itsAddOptCol(other.itsAddOptCol),
146 37 : itsRewriteTable(other.itsRewriteTable)
147 : {
148 37 : }
149 :
150 25826 : ComponentList::~ComponentList() {
151 25826 : if (! itsROFlag && ! itsTable.isNull() && itsRewriteTable) {
152 25 : writeTable();
153 : }
154 : // AlwaysAssert(ok(), AipsError);
155 25826 : }
156 :
157 15 : ComponentList& ComponentList::operator=(const ComponentList& other){
158 15 : if (this != &other) {
159 15 : if (! itsROFlag && ! itsTable.isNull() && itsRewriteTable) {
160 0 : writeTable();
161 : }
162 15 : itsList = other.itsList;
163 15 : itsNelements = other.itsNelements;
164 15 : itsTable = other.itsTable;
165 15 : itsROFlag = other.itsROFlag;
166 15 : itsSelectedFlags = other.itsSelectedFlags;
167 15 : itsOrder = other.itsOrder;
168 15 : itsAddOptCol = other.itsAddOptCol;
169 15 : itsRewriteTable = other.itsRewriteTable;
170 : }
171 15 : return *this;
172 : }
173 :
174 0 : Bool ComponentList::isPhysical(const Vector<Int>& indices) const {
175 0 : Bool retVal = true;
176 0 : uInt c = indices.nelements();
177 0 : while (retVal && c > 0) {
178 0 : c--;
179 0 : retVal = itsList[indices(c)].isPhysical();
180 : }
181 0 : return retVal;
182 : }
183 :
184 0 : Flux<Double> ComponentList::sample(const MDirection& sampleDir,
185 : const MVAngle& pixelLatSize,
186 : const MVAngle& pixelLongSize,
187 : const MFrequency& centerFreq) const {
188 0 : const Unit retUnit("Jy");
189 0 : const ComponentType::Polarisation retPol(ComponentType::STOKES);
190 0 : Vector<DComplex> result(4, DComplex(0,0));
191 0 : Flux<Double> compFlux;
192 0 : for (uInt i = 0; i < nelements(); i++) {
193 0 : compFlux = component(i).sample(sampleDir, pixelLatSize, pixelLongSize,
194 0 : centerFreq);
195 0 : compFlux.convertUnit(retUnit);
196 0 : compFlux.convertPol(retPol);
197 0 : result += compFlux.value();
198 : }
199 0 : return Flux<Double>(result, retPol);
200 0 : }
201 :
202 823 : void ComponentList::sample(Cube<Double>& samples,
203 : const Unit& reqUnit,
204 : const Vector<MVDirection>& directions,
205 : const MeasRef<MDirection>& dirRef,
206 : const MVAngle& pixelLatSize,
207 : const MVAngle& pixelLongSize,
208 : const Vector<MVFrequency>& frequencies,
209 : const MeasRef<MFrequency>& freqRef) const {
210 823 : samples = 0.0;
211 5101 : for (uInt i = 0; i < nelements(); i++) {
212 4278 : component(i).sample(samples, reqUnit, directions, dirRef,
213 : pixelLatSize, pixelLongSize, frequencies, freqRef);
214 : }
215 823 : }
216 :
217 26077 : void ComponentList::add(SkyComponent component) {
218 : // AlwaysAssert(itsROFlag == false, AipsError);
219 26077 : uInt blockSize = itsList.nelements();
220 26077 : if (itsNelements == blockSize) {
221 25860 : const uInt newSize
222 25860 : = (blockSize < 50) ? 2 * blockSize + 1 : blockSize + 100;
223 25860 : itsList.resize(newSize);
224 25860 : itsSelectedFlags.resize(newSize);
225 25860 : itsOrder.resize(newSize);
226 : }
227 : // for limb-darkened disk shape, add an optional col
228 26077 : if (component.shape().type()==ComponentType::LDISK) {
229 0 : itsAddOptCol=true;
230 : }
231 26077 : itsList[itsNelements] = component;
232 26077 : itsSelectedFlags[itsNelements] = false;
233 26077 : itsOrder[itsNelements] = itsNelements;
234 26077 : itsNelements++;
235 26077 : }
236 :
237 0 : void ComponentList::addList(const ComponentList& list) {
238 0 : for (uInt i=0; i<list.nelements(); i++) {
239 0 : add(list.component(i));
240 : }
241 0 : }
242 :
243 :
244 1 : void ComponentList::remove(const uInt& index) {
245 : // AlwaysAssert(itsROFlag == false, AipsError);
246 1 : AlwaysAssert(index < nelements(), AipsError);
247 1 : uInt realIndex = itsOrder[index];
248 1 : itsSelectedFlags.remove(realIndex, false);
249 1 : itsList.remove(realIndex, false);
250 1 : itsOrder.remove(index, false);
251 1 : itsNelements--;
252 1 : for (uInt i = 0; i < nelements(); i++) {
253 0 : if (itsOrder[i] > realIndex) {
254 0 : itsOrder[i]--;
255 : }
256 : }
257 1 : }
258 :
259 1 : void ComponentList::remove(const Vector<Int>& indices) {
260 1 : Vector<Int> zeroCheck(indices);
261 1 : AlwaysAssert(allGE(zeroCheck, 0), AipsError);
262 1 : uInt c = indices.nelements();
263 1 : Vector<uInt> uIndices(c);
264 1 : convertArray(uIndices, indices);
265 1 : GenSort<uInt>::sort(uIndices);
266 2 : while (c != 0) {
267 1 : c--;
268 1 : remove(uIndices(c));
269 : }
270 1 : }
271 :
272 65900 : uInt ComponentList::nelements() const {
273 65900 : return itsNelements;
274 : }
275 :
276 1 : uInt ComponentList::size() const {
277 1 : return itsNelements;
278 : }
279 :
280 0 : void ComponentList::deselect(const Vector<Int>& indexes) {
281 0 : for (uInt i = 0; i < indexes.nelements(); i++) {
282 0 : AlwaysAssert(indexes(i) < Int(nelements()), AipsError);
283 0 : AlwaysAssert(indexes(i) >= 0, AipsError);
284 0 : itsSelectedFlags[itsOrder[indexes(i)]] = false;
285 : }
286 0 : }
287 :
288 0 : void ComponentList::select(const Vector<Int>& indexes) {
289 0 : for (uInt i = 0; i < indexes.nelements(); i++) {
290 0 : AlwaysAssert(indexes(i) < Int(nelements()), AipsError);
291 0 : AlwaysAssert(indexes(i) >= 0, AipsError);
292 0 : itsSelectedFlags[itsOrder[indexes(i)]] = true;
293 : }
294 0 : }
295 :
296 0 : Vector<Int> ComponentList::selected() const {
297 0 : uInt nSelected = 0;
298 0 : for (uInt i = 0; i < nelements(); i++) {
299 0 : if (itsSelectedFlags[i] == true) {
300 0 : nSelected++;
301 : }
302 : }
303 0 : Vector<Int> retVal(nSelected);
304 0 : uInt s = 0;
305 0 : for (uInt j = 0; j < nelements(); j++) {
306 0 : if (itsSelectedFlags[j] == true) {
307 0 : retVal(s) = j;
308 0 : s++;
309 : }
310 : }
311 0 : return retVal;
312 0 : }
313 :
314 1 : void ComponentList::setLabel(const Vector<Int>& which,
315 : const String& newLabel) {
316 : uInt c;
317 2 : for (uInt i = 0; i < which.nelements(); i++) {
318 1 : AlwaysAssert(which(i) >= 0, AipsError);
319 1 : c = which(i);
320 1 : component(c).label() = newLabel;
321 : }
322 1 : }
323 :
324 0 : void ComponentList::getFlux(Vector<casacore::Quantity>& fluxQuant, int which) const {
325 0 : SkyComponent comp = component(which);
326 : // each element in the returned vector represents a different polarization.
327 : // NumericTraits::Conjugate is just a confusing way of saying Complex if you
328 : // look at how comp.flux().value() is implemented.
329 0 : Vector<Complex> flux(comp.flux().value().nelements());
330 0 : convertArray(flux,comp.flux().value());
331 0 : Unit unit = comp.flux().unit();
332 0 : fluxQuant.resize(flux.nelements());
333 0 : for (uInt i=0; i<flux.nelements(); ++i) {
334 0 : fluxQuant[i] = casacore::Quantity(real(flux[i]), unit);
335 : }
336 0 : }
337 :
338 0 : void ComponentList::getFlux(Vector<Quantum<Complex> >& fluxQuant, const Int& which) {
339 0 : SkyComponent comp = component(which);
340 0 : Vector<Complex> flux(comp.flux().value().nelements());
341 0 : convertArray(flux,comp.flux().value());
342 0 : Unit unit = comp.flux().unit();
343 0 : fluxQuant.resize(flux.nelements());
344 0 : for (uInt i=0; i<flux.nelements(); ++i) {
345 0 : fluxQuant[i] = Quantum<Complex>(flux[i], unit);
346 : }
347 0 : }
348 :
349 :
350 :
351 1 : void ComponentList::setFlux(const Vector<Int>& which,
352 : const Flux<Double>& newFlux) {
353 : uInt c;
354 2 : for (uInt i = 0; i < which.nelements(); i++) {
355 1 : AlwaysAssert(which(i) >= 0, AipsError);
356 1 : c = which(i);
357 1 : component(c).flux() = newFlux;
358 : }
359 1 : }
360 :
361 0 : Vector<String> ComponentList::getStokes(const Int& which) const {
362 0 : SkyComponent comp = component(which);
363 0 : ComponentType::Polarisation stokesType = comp.flux().pol();
364 0 : Vector<String> polarization(4);
365 : // the polarization determination logic needs to be refactored into
366 : // a method in a more appropriate class
367 0 : if (stokesType == ComponentType::STOKES) {
368 0 : polarization[0] = "I";
369 0 : polarization[1] = "Q";
370 0 : polarization[2] = "U";
371 0 : polarization[3] = "V";
372 : }
373 0 : else if (stokesType == ComponentType::LINEAR) {
374 0 : polarization[0] = "XX";
375 0 : polarization[1] = "XY";
376 0 : polarization[2] = "YX";
377 0 : polarization[3] = "YY";
378 : }
379 0 : else if (stokesType == ComponentType::CIRCULAR) {
380 0 : polarization[0] = "RR";
381 0 : polarization[1] = "RL";
382 0 : polarization[2] = "LR";
383 0 : polarization[3] = "LL";
384 : }
385 : else {
386 0 : polarization.set("UNKNOWN");
387 : }
388 0 : return polarization;
389 0 : }
390 :
391 0 : void ComponentList::convertFluxUnit(const Vector<Int>& which,
392 : const Unit& unit) {
393 : uInt c;
394 0 : for (uInt i = 0; i < which.nelements(); i++) {
395 0 : AlwaysAssert(which(i) >= 0, AipsError);
396 0 : c = which(i);
397 0 : component(c).flux().convertUnit(unit);
398 : }
399 0 : }
400 :
401 0 : void ComponentList::convertFluxPol(const Vector<Int>& which,
402 : ComponentType::Polarisation pol) {
403 : uInt c;
404 0 : for (uInt i = 0; i < which.nelements(); i++) {
405 0 : AlwaysAssert(which(i) >= 0, AipsError);
406 0 : c = which(i);
407 0 : component(c).flux().convertPol(pol);
408 : }
409 0 : }
410 :
411 1 : void ComponentList::setRefDirection(const Vector<Int>& which,
412 : const MVDirection& newDir) {
413 : uInt c;
414 1 : MDirection curDir;
415 2 : for (uInt i = 0; i < which.nelements(); i++) {
416 1 : AlwaysAssert(which(i) >= 0, AipsError);
417 1 : c = which(i);
418 1 : ComponentShape& curShape = component(c).shape();
419 1 : curDir = curShape.refDirection();
420 1 : curDir.set(newDir);
421 1 : curShape.setRefDirection(curDir);
422 : }
423 1 : }
424 :
425 1 : void ComponentList::setRefDirectionFrame(const Vector<Int>& which,
426 : MDirection::Types newFrame) {
427 : uInt c;
428 1 : MDirection curDir;
429 1 : const MDirection::Ref newRef(newFrame);
430 2 : for (uInt i = 0; i < which.nelements(); i++) {
431 1 : AlwaysAssert(which(i) >= 0, AipsError);
432 1 : c = which(i);
433 1 : ComponentShape& curShape = component(c).shape();
434 1 : curDir = curShape.refDirection();
435 1 : curDir.set(newRef);
436 1 : curShape.setRefDirection(curDir);
437 : }
438 1 : }
439 :
440 0 : void ComponentList::convertRefDirection(const Vector<Int>& which,
441 : MDirection::Types newFrame) {
442 : uInt c;
443 0 : MDirection::Convert converter;
444 0 : converter.setOut(newFrame);
445 0 : MDirection curDir;
446 0 : for (uInt i = 0; i < which.nelements(); i++) {
447 0 : AlwaysAssert(which(i) >= 0, AipsError);
448 0 : c = which(i);
449 0 : ComponentShape& curShape = component(c).shape();
450 0 : curDir = curShape.refDirection();
451 0 : curShape.setRefDirection(converter(curDir));
452 : }
453 0 : }
454 :
455 1 : MDirection ComponentList::getRefDirection(Int which) const {
456 1 : const ComponentShape& compShape = component(which).shape();
457 1 : MDirection refDir = compShape.refDirection();
458 1 : return refDir;
459 : }
460 :
461 0 : void ComponentList::setShape(const Vector<Int>& which,
462 : const ComponentShape& newShape) {
463 : uInt c;
464 0 : for (uInt i = 0; i < which.nelements(); i++) {
465 0 : AlwaysAssert(which(i) >= 0, AipsError);
466 0 : c = which(i);
467 0 : component(c).setShape(newShape);
468 : //for limb-darkened disk shape
469 0 : if (newShape.type()==ComponentType::LDISK) {
470 0 : itsAddOptCol=true;
471 : }
472 : }
473 0 : }
474 :
475 79 : const ComponentShape* ComponentList::getShape(Int which) const {
476 79 : return component(which).shape().getPtr();
477 : }
478 :
479 :
480 1 : void ComponentList::setShapeParms(const Vector<Int>& which,
481 : const ComponentShape& newShape) {
482 : uInt c;
483 1 : MDirection oldDir;
484 2 : for (uInt i = 0; i < which.nelements(); i++) {
485 1 : AlwaysAssert(which(i) >= 0, AipsError);
486 1 : c = which(i);
487 1 : SkyComponent& comp = component(c);
488 1 : oldDir = comp.shape().refDirection();
489 1 : component(c).setShape(newShape);
490 1 : comp.shape().setRefDirection(oldDir);
491 : }
492 1 : }
493 :
494 0 : void ComponentList::setOptParms(const Vector<Int>& which,
495 : const ComponentShape& newShape) {
496 : uInt c;
497 0 : Vector<Double> optparms;
498 0 : for (uInt i = 0; i < which.nelements(); i++) {
499 0 : AlwaysAssert(which(i) >= 0, AipsError);
500 0 : c = which(i);
501 0 : SkyComponent& comp = component(c);
502 0 : component(c).setShape(newShape);
503 0 : if (comp.shape().type()==ComponentType::LDISK) {
504 0 : optparms = comp.shape().optParameters();
505 : //comp.shape().setOptParameters(optparms);
506 0 : component(c).optionalParameters()=optparms;
507 0 : itsAddOptCol=true;
508 : }
509 : }
510 0 : }
511 :
512 0 : void ComponentList::setSpectrum(const Vector<Int>& which,
513 : const SpectralModel& newSpectrum) {
514 : uInt c;
515 0 : for (uInt i = 0; i < which.nelements(); i++) {
516 0 : AlwaysAssert(which(i) >= 0, AipsError);
517 0 : c = which(i);
518 0 : component(c).setSpectrum(newSpectrum);
519 : }
520 0 : }
521 :
522 1 : void ComponentList::setSpectrumParms(const Vector<Int>& which,
523 : const SpectralModel& newSpectrum) {
524 : uInt c;
525 1 : MFrequency oldFreq;
526 2 : for (uInt i = 0; i < which.nelements(); i++) {
527 1 : AlwaysAssert(which(i) >= 0, AipsError);
528 1 : c = which(i);
529 1 : SkyComponent& comp = component(c);
530 1 : oldFreq = comp.spectrum().refFrequency();
531 1 : component(c).setSpectrum(newSpectrum);
532 1 : comp.spectrum().setRefFrequency(oldFreq);
533 : }
534 1 : }
535 :
536 1 : void ComponentList::setRefFrequency(const Vector<Int>& which,
537 : const MVFrequency& newFreq) {
538 : uInt c;
539 1 : MFrequency curFreq;
540 2 : for (uInt i = 0; i < which.nelements(); i++) {
541 1 : AlwaysAssert(which(i) >= 0, AipsError);
542 1 : c = which(i);
543 1 : SpectralModel& curSpectrum = component(c).spectrum();
544 1 : curFreq = curSpectrum.refFrequency();
545 1 : curFreq.set(newFreq);
546 1 : curSpectrum.setRefFrequency(curFreq);
547 : }
548 1 : }
549 :
550 1 : void ComponentList::setRefFrequencyFrame(const Vector<Int>& which,
551 : MFrequency::Types newFrame) {
552 : uInt c;
553 1 : MFrequency curFreq;
554 1 : const MFrequency::Ref newRef(newFrame);
555 2 : for (uInt i = 0; i < which.nelements(); i++) {
556 1 : AlwaysAssert(which(i) >= 0, AipsError);
557 1 : c = which(i);
558 1 : SpectralModel& curSpectrum = component(c).spectrum();
559 1 : curFreq = curSpectrum.refFrequency();
560 1 : curFreq.set(newRef);
561 1 : curSpectrum.setRefFrequency(curFreq);
562 : }
563 1 : }
564 :
565 :
566 1 : void ComponentList::setRefFrequencyUnit(const Vector<Int>& which,
567 : const Unit& unit) {
568 : uInt c;
569 2 : for (uInt i = 0; i < which.nelements(); i++) {
570 1 : AlwaysAssert(which(i) >= 0, AipsError);
571 1 : c = which(i);
572 1 : component(c).spectrum().convertFrequencyUnit(unit);
573 : }
574 1 : }
575 :
576 672 : SkyComponent& ComponentList::component(const uInt& index) {
577 : // AlwaysAssert(itsROFlag == false, AipsError);
578 672 : AlwaysAssert(index < nelements(), AipsError);
579 672 : return itsList[itsOrder[index]];
580 : }
581 :
582 32192 : const SkyComponent& ComponentList::component(const uInt& index) const {
583 32192 : AlwaysAssert(index < nelements(), AipsError);
584 32192 : return itsList[itsOrder[index]];
585 : }
586 :
587 1 : void ComponentList::rename(const Path& fileName,
588 : const Table::TableOption option) {
589 1 : AlwaysAssert(option != Table::Old, AipsError);
590 1 : AlwaysAssert(itsROFlag == false, AipsError);
591 1 : if (fileName.length() != 0) {
592 : // See if this list is associated with a Table.
593 1 : if (itsTable.isNull()) {
594 : //createTable(fileName, option, addOptCol_p);
595 1 : createTable(fileName, option);
596 : } else {
597 0 : if (!itsTable.isWritable()) itsTable.reopenRW();
598 0 : itsTable.rename(fileName.absoluteName(), option);
599 : }
600 :
601 : // Ensure that the Table::isReadable(fileName) returns true, otherwise the
602 : // ok() function will fail.
603 1 : itsTable.flush();
604 : } else {
605 0 : if (!itsTable.isNull()) {
606 0 : itsTable.markForDelete();
607 0 : itsTable = Table();
608 0 : itsROFlag = false;
609 : }
610 : }
611 1 : }
612 :
613 30 : ComponentList ComponentList::copy() const {
614 30 : ComponentList copiedList;
615 30 : SkyComponent currentComp;
616 188 : for (uInt c = 0; c < nelements(); c++) {
617 158 : currentComp = component(c).copy();
618 158 : copiedList.add(currentComp);
619 : }
620 60 : return copiedList;
621 30 : }
622 :
623 0 : void ComponentList::sort(ComponentList::SortCriteria criteria) {
624 0 : Block<Double> val(nelements());
625 0 : Sort::Order order = Sort::Ascending;
626 0 : Bool doSort = true;
627 0 : switch (criteria) {
628 0 : case ComponentList::FLUX: {
629 0 : for (uInt i = 0; i < nelements(); i++) {
630 0 : itsList[i].flux().convertPol(ComponentType::STOKES);
631 0 : val[i] = abs(itsList[i].flux().value(0u).real());
632 : }
633 0 : order = Sort::Descending;
634 0 : break;
635 : }
636 0 : case ComponentList::POSITION: {
637 0 : MDirection compDir;
638 0 : MVDirection refDir(0.0, 0.0);
639 0 : Vector<Double> position(2);
640 0 : for (uInt i = 0; i < nelements(); i++) {
641 0 : val[i] = refDir.separation(itsList[i].shape().refDirection().getValue());
642 : }
643 0 : order = Sort::Ascending;
644 0 : break;
645 0 : }
646 0 : case ComponentList::POLARISATION: {
647 0 : Vector<Double> f(4);
648 0 : for (uInt i = 0; i < nelements(); i++) {
649 0 : itsList[i].flux().value(f);
650 0 : if (!nearAbs(f(0), 0.0, DBL_MIN)) {
651 0 : val[i] = sqrt(f(1)*f(1)+f(2)*f(2)+f(3)*f(3))/f(0);
652 : }
653 : else {
654 0 : val[i] = 0.0;
655 : }
656 : }
657 0 : order = Sort::Descending;
658 0 : break;
659 0 : }
660 0 : case ComponentList::UNSORTED:
661 : case ComponentList::NUMBER_CRITERIA:
662 0 : doSort = false;
663 0 : break;
664 : };
665 : // The genSort function requires a Vector<uInt> and not a Block<uInt> so
666 : // I'll create a temporary Vector here which references the data in the
667 : // 'itsOrder' Block.
668 0 : if (doSort) {
669 0 : Vector<uInt> vecOrder(IPosition(1,nelements()), itsOrder.storage(), SHARE);
670 0 : AlwaysAssert(genSort(vecOrder, val, order) == nelements(),
671 : AipsError);
672 0 : }
673 0 : }
674 :
675 0 : String ComponentList::name(ComponentList::SortCriteria enumerator) {
676 0 : switch (enumerator) {
677 0 : case ComponentList::FLUX: return "Flux";
678 0 : case ComponentList::POSITION: return "Position";
679 0 : case ComponentList::POLARISATION: return "Polarization";
680 0 : default: return "unknown";
681 : };
682 : }
683 :
684 0 : ComponentList::SortCriteria ComponentList::type(const String& criteria) {
685 0 : String canonicalCase(criteria);
686 0 : canonicalCase.capitalize();
687 0 : for (uInt i = 0; i < ComponentList::NUMBER_CRITERIA; i++) {
688 0 : if (canonicalCase.
689 0 : matches(ComponentList::name((ComponentList::SortCriteria) i))) {
690 0 : return (ComponentList::SortCriteria) i;
691 : }
692 : }
693 0 : return ComponentList::UNSORTED;
694 0 : }
695 :
696 25790 : Bool ComponentList::ok() const {
697 : // The LogIO class is only constructed if an Error is detected for
698 : // performance reasons. Both function static and file static variables
699 : // where considered and rejected for this purpose.
700 25790 : if (itsList.nelements() < itsNelements) {
701 0 : LogIO logErr(LogOrigin("ComponentList", "ok()"));
702 : logErr << LogIO::SEVERE
703 : << "The list size is inconsistant with its cached size"
704 0 : << LogIO::POST;
705 0 : return false;
706 0 : }
707 25790 : if (itsROFlag == true && itsTable.isNull() == true) {
708 0 : LogIO logErr(LogOrigin("ComponentList", "ok()"));
709 : logErr << LogIO::SEVERE
710 : << "Only ComponentList's associated with a Table can be readonly"
711 0 : << LogIO::POST;
712 0 : return false;
713 0 : }
714 25790 : if (! itsTable.isNull()) {
715 31 : String tablename = itsTable.tableName();
716 31 : if (! Table::isReadable(tablename)) {
717 0 : LogIO logErr(LogOrigin("ComponentList", "ok()"));
718 : logErr << LogIO::SEVERE
719 : << "Table associated with ComponentList is not readable"
720 0 : << LogIO::POST;
721 0 : return false;
722 0 : }
723 31 : if (itsROFlag == false && Table::isWritable(tablename) == false) {
724 0 : LogIO logErr(LogOrigin("ComponentList", "ok()"));
725 : logErr << LogIO::SEVERE
726 : << "Table associated with ComponentList is not writeable"
727 0 : << LogIO::POST;
728 0 : return false;
729 0 : }
730 31 : }
731 25948 : for (uInt i = 0; i < itsNelements; i++) {
732 158 : if (itsOrder[i] >= itsNelements) {
733 0 : LogIO logErr(LogOrigin("ComponentList", "ok()"));
734 : logErr << LogIO::SEVERE
735 : << "Cannot index to an element that is outside the list!"
736 0 : << LogIO::POST;
737 0 : return false;
738 0 : }
739 : }
740 25790 : return true;
741 : }
742 :
743 1 : void ComponentList::createTable(const Path& fileName,
744 : const Table::TableOption option) {
745 : // const Table::TableOption option,
746 : // const Bool addOptCol) {
747 : // Build a default table description
748 2 : TableDesc td("ComponentListDescription", "4", TableDesc::Scratch);
749 1 : td.comment() = "A description of a component list";
750 : {
751 : {
752 : const ArrayColumnDesc<DComplex>
753 2 : fluxValCol(fluxName, "Flux values", IPosition(1,4),ColumnDesc::Direct);
754 1 : td.addColumn(fluxValCol);
755 : const ScalarColumnDesc<String>
756 1 : fluxUnitCol(fluxUnitName, "Flux units", ColumnDesc::Direct);
757 1 : td.addColumn(fluxUnitCol);
758 : const ScalarColumnDesc<String>
759 : fluxPolCol(fluxPolName, "Flux polarisation representation",
760 1 : ColumnDesc::Direct);
761 1 : td.addColumn(fluxPolCol);
762 : const ArrayColumnDesc<DComplex>
763 1 : fluxErrCol(fluxErrName, "Flux errors", IPosition(1,4),
764 2 : ColumnDesc::Direct);
765 1 : td.addColumn(fluxErrCol);
766 1 : }
767 : {
768 : const ScalarColumnDesc<String>
769 1 : shapeCol(shapeName, "Shape of the Component", ColumnDesc::Direct);
770 1 : td.addColumn(shapeCol);
771 1 : const String dirValColName = refDirName;
772 : const ArrayColumnDesc<Double>
773 : dirValCol(dirValColName, "Reference direction values",
774 2 : IPosition(1,2), ColumnDesc::Direct);
775 1 : td.addColumn(dirValCol);
776 1 : const String dirRefColName = "Direction_Frame";
777 : const ScalarColumnDesc<String>
778 : dirRefCol(dirRefColName, "The reference direction frame",
779 1 : ColumnDesc::Direct);
780 1 : td.addColumn(dirRefCol);
781 : {
782 1 : const TableMeasRefDesc dirRefTMCol(td, dirRefColName);
783 1 : const TableMeasValueDesc dirValTMCol(td, dirValColName);
784 1 : TableMeasDesc<MDirection> dirTMCol(dirValTMCol, dirRefTMCol);
785 1 : dirTMCol.write(td);
786 1 : }
787 : const ArrayColumnDesc<Double>
788 : dirErrCol(dirErrName, "Error in the reference direction values",
789 2 : IPosition(1,2), ColumnDesc::Direct);
790 1 : td.addColumn(dirErrCol);
791 : const ArrayColumnDesc<String>
792 : dirErrUnitCol(dirErrUnitName, "Units of the direction error",
793 2 : IPosition(1,2), ColumnDesc::Direct);
794 1 : td.addColumn(dirErrUnitCol);
795 : {
796 1 : TableQuantumDesc dirErrTMCol(td, dirErrName, dirErrUnitName);
797 1 : dirErrTMCol.write(td);
798 1 : }
799 :
800 : const ArrayColumnDesc<Double>
801 : shapeParmCol(shapeParName,
802 1 : "Parameters specific to the component shape", 1);
803 1 : td.addColumn(shapeParmCol);
804 : const ArrayColumnDesc<Double>
805 : shapeErrCol(shapeErrName,
806 1 : "Error in the shape parameters", 1);
807 1 : td.addColumn(shapeErrCol);
808 1 : }
809 : {
810 : const ScalarColumnDesc<String>
811 : freqShapeCol(spectrumName, "Shape of the spectrum",
812 1 : ColumnDesc::Direct);
813 1 : td.addColumn (freqShapeCol);
814 1 : const String freqValColName = refFreqName;
815 : const ScalarColumnDesc<Double>
816 : freqValCol(freqValColName, "The reference frequency values",
817 1 : ColumnDesc::Direct);
818 1 : td.addColumn(freqValCol);
819 1 : const String freqRefColName = "Frequency_Frame";
820 : const ScalarColumnDesc<String>
821 : freqRefCol(freqRefColName, "The reference frequency frame",
822 1 : ColumnDesc::Direct);
823 1 : td.addColumn(freqRefCol);
824 : {
825 1 : const TableMeasRefDesc freqRefTMCol(td, freqRefColName);
826 1 : const TableMeasValueDesc freqValTMCol(td, freqValColName);
827 1 : TableMeasDesc<MFrequency> freqTMCol(freqValTMCol, freqRefTMCol);
828 1 : freqTMCol.write(td);
829 1 : }
830 : const ScalarColumnDesc<Double>
831 : freqErrCol(freqErrName, "Error in the reference frequency",
832 1 : ColumnDesc::Direct);
833 1 : td.addColumn(freqErrCol);
834 : const ScalarColumnDesc<String>
835 : freqErrUnitCol(freqErrUnitName, "Units of the frequency error",
836 1 : ColumnDesc::Direct);
837 1 : td.addColumn(freqErrUnitCol);
838 : {
839 1 : TableQuantumDesc freqErrTMCol(td, freqErrName, freqErrUnitName);
840 1 : freqErrTMCol.write(td);
841 1 : }
842 : const ArrayColumnDesc<Double>
843 : specParmCol(spectParName,
844 1 : "Parameters specific to the components spectrum", 1);
845 1 : td.addColumn(specParmCol);
846 : const ArrayColumnDesc<Double>
847 : specErrCol(spectErrName,
848 1 : "Errors in the spectral parameters", 1);
849 1 : td.addColumn(specErrCol);
850 1 : }
851 : {
852 : const ScalarColumnDesc<String>
853 : labelCol(labelName, "An arbitrary label for the user",
854 1 : ColumnDesc::Direct);
855 1 : td.addColumn (labelCol);
856 1 : }
857 : }
858 1 : if (itsAddOptCol) {
859 : const ArrayColumnDesc<Double>
860 0 : optParCol(optParColName,"optional parameter column",1,ColumnDesc::Undefined);
861 0 : td.addColumn (optParCol);
862 0 : td.defineHypercolumn("TiledOptParms",1,stringToVector(optParColName));
863 0 : }
864 1 : SetupNewTable newTable(fileName.absoluteName(), td, option);
865 :
866 1 : if (itsAddOptCol) {
867 0 : TiledCellStMan optcolsm("TiledOptParms",IPosition(1,1));
868 0 : newTable.bindColumn(optParColName,optcolsm);
869 0 : }
870 1 : itsTable = Table(newTable, TableLock::AutoLocking, nelements(), false);
871 : {
872 1 : TableInfo& info(itsTable.tableInfo());
873 1 : info.setType(TableInfo::type(TableInfo::COMPONENTLIST));
874 1 : info.readmeAddLine(String(
875 : "This is a ComponentList Table containing parameterised representations"));
876 1 : info.readmeAddLine(String("of the sky brightness."));
877 : }
878 1 : }
879 :
880 25 : void ComponentList::writeTable() {
881 25 : if (itsTable.isWritable() == false) {
882 0 : itsTable.reopenRW();
883 : }
884 : {
885 25 : const casacore::rownr_t nRows = itsTable.nrow();
886 25 : const casacore::rownr_t nelem = nelements();
887 25 : if (nRows < nelem) {
888 0 : itsTable.addRow(nelem - nRows);
889 25 : } else if (nRows > nelem) {
890 0 : Vector<casacore::rownr_t> rows(nRows - nelem);
891 0 : indgen(rows, nelem);
892 0 : itsTable.removeRow(RowNumbers(rows));
893 0 : }
894 : }
895 25 : ArrayColumn<DComplex> fluxValCol(itsTable, fluxName);
896 25 : ScalarColumn<String> fluxUnitCol(itsTable, fluxUnitName);
897 25 : ScalarColumn<String> fluxPolCol(itsTable, fluxPolName);
898 25 : ScalarColumn<String> shapeCol(itsTable, shapeName);
899 25 : MDirection::ScalarColumn dirCol(itsTable, refDirName);
900 25 : ArrayColumn<Double> shapeParmCol(itsTable, shapeParName);
901 25 : ScalarColumn<String> specShapeCol(itsTable, spectrumName);
902 25 : MFrequency::ScalarColumn freqCol(itsTable, refFreqName);
903 25 : ArrayColumn<Double> specShapeParmCol(itsTable, spectParName);
904 25 : ScalarColumn<String> labelCol(itsTable, labelName);
905 25 : ArrayColumn<DComplex> fluxErrCol;
906 25 : ArrayQuantColumn<Double> dirErrCol;
907 25 : ArrayColumn<Double> shapeErrCol;
908 25 : ScalarQuantColumn<Double> freqErrCol;
909 25 : ArrayColumn<Double> spectErrCol;
910 25 : ScalarColumn<TableRecord> specRecord;
911 25 : ArrayColumn<Double> optParCol;
912 : {
913 25 : const ColumnDescSet& cds=itsTable.tableDesc().columnDescSet();
914 25 : if (!cds.isDefined(spectralRecordName)) {
915 1 : itsTable.addColumn(ScalarRecordColumnDesc(spectralRecordName));
916 : }
917 25 : specRecord.attach(itsTable, spectralRecordName);
918 25 : if (!cds.isDefined(fluxErrName)) {
919 : itsTable.addColumn
920 0 : (ArrayColumnDesc<DComplex>(fluxErrName, "Flux errors", IPosition(1,4),
921 : ColumnDesc::Direct));
922 : }
923 :
924 25 : fluxErrCol.attach(itsTable, fluxErrName);
925 25 : if (!cds.isDefined(dirErrName)) {
926 : itsTable.addColumn
927 0 : (ArrayColumnDesc<Double>(dirErrName,
928 : "Error in the reference direction values",
929 0 : IPosition(1,2), ColumnDesc::Direct));
930 : itsTable.addColumn
931 0 : (ArrayColumnDesc<String>(dirErrUnitName,
932 : "Units of the direction error",
933 0 : IPosition(1,2), ColumnDesc::Direct));
934 : TableQuantumDesc dirErrTMCol(itsTable.tableDesc(), dirErrName,
935 0 : dirErrUnitName);
936 0 : dirErrTMCol.write(itsTable);
937 0 : }
938 25 : dirErrCol.attach(itsTable, dirErrName);
939 25 : if (!cds.isDefined(shapeErrName)) {
940 : itsTable.addColumn
941 0 : (ArrayColumnDesc<Double>(shapeErrName,
942 : "Error in the shape parameters", 1));
943 : }
944 25 : shapeErrCol.attach(itsTable, shapeErrName);
945 :
946 25 : if (!cds.isDefined(freqErrName)) {
947 : itsTable.addColumn
948 0 : (ScalarColumnDesc<Double>(freqErrName,
949 : "Error in the reference frequency",
950 : ColumnDesc::Direct));
951 : itsTable.addColumn
952 0 : (ScalarColumnDesc<String>(freqErrUnitName,
953 : "Units of the frequency error",
954 : ColumnDesc::Direct));
955 : TableQuantumDesc freqErrTMCol(itsTable.tableDesc(), freqErrName,
956 0 : freqErrUnitName);
957 0 : freqErrTMCol.write(itsTable);
958 0 : }
959 25 : freqErrCol.attach(itsTable, freqErrName);
960 25 : if (!cds.isDefined(spectErrName)) {
961 : itsTable.addColumn
962 0 : (ArrayColumnDesc<Double>(spectErrName,
963 : "Error in the spectral parameters", 1));
964 : }
965 25 : spectErrCol.attach(itsTable, spectErrName);
966 :
967 25 : if (itsAddOptCol) {
968 0 : if (!cds.isDefined(optParColName)) {
969 : itsTable.addColumn
970 0 : (ArrayColumnDesc<Double>(optParColName,
971 : "Optional parameters", 1));
972 : //cerr<<"added optional parameter col"<<endl;
973 : }
974 0 : optParCol.attach(itsTable, optParColName);
975 : }
976 : }
977 :
978 25 : Vector<Quantum<Double> > dirErr(2);
979 154 : for (uInt i = 0; i < nelements(); i++) {
980 : {
981 129 : const Flux<Double>& flux = component(i).flux();
982 129 : fluxValCol.put(i, flux.value());
983 129 : fluxUnitCol.put(i, flux.unit().getName());
984 129 : fluxPolCol.put(i, ComponentType::name(flux.pol()));
985 129 : fluxErrCol.put(i, flux.errors());
986 : }
987 : {
988 129 : const ComponentShape& compShape = component(i).shape();
989 129 : shapeCol.put(i, compShape.ident());
990 129 : dirCol.put(i, compShape.refDirection());
991 129 : if (!dirErrCol.isNull()) {
992 129 : dirErr(0) = compShape.refDirectionErrorLat();
993 129 : dirErr(1) = compShape.refDirectionErrorLong();
994 129 : dirErrCol.put(i, dirErr);
995 : }
996 129 : shapeParmCol.put(i, compShape.parameters());
997 129 : shapeErrCol.put(i, compShape.errors());
998 : }
999 : {
1000 129 : const SpectralModel& compSpectrum = component(i).spectrum();
1001 129 : specShapeCol.put(i, compSpectrum.ident());
1002 129 : TableRecord rec;
1003 129 : String err;
1004 129 : if(compSpectrum.toRecord(err, rec))
1005 129 : specRecord.put(i,rec);
1006 129 : freqCol.put(i, compSpectrum.refFrequency());
1007 129 : if (!freqErrCol.isNull()) {
1008 129 : freqErrCol.put(i, compSpectrum.refFrequencyError());
1009 : }
1010 129 : specShapeParmCol.put(i, compSpectrum.parameters());
1011 129 : spectErrCol.put(i, compSpectrum.errors());
1012 129 : }
1013 : {
1014 129 : labelCol.put(i, component(i).label());
1015 : }
1016 129 : if (itsAddOptCol) {
1017 0 : const ComponentShape& compShape2 = component(i).shape();
1018 0 : if (compShape2.type()==ComponentType::LDISK) {
1019 : //optParCol.put(i,compShape2.optParameters());
1020 0 : optParCol.put(i,component(i).optionalParameters());
1021 : }
1022 : }
1023 : }
1024 25 : }
1025 :
1026 31 : void ComponentList::readTable(const Path& fileName, const Bool readOnly) {
1027 : {
1028 31 : const String& fullName = fileName.absoluteName();
1029 31 : if (readOnly) {
1030 7 : AlwaysAssert(Table::isReadable(fullName), AipsError);
1031 7 : itsTable = Table(fullName, Table::Old);
1032 : }
1033 : else {
1034 24 : AlwaysAssert(Table::isWritable(fullName), AipsError);
1035 48 : itsTable = Table(fullName, TableLock(TableLock::AutoLocking),
1036 24 : Table::Update);
1037 : }
1038 : }
1039 31 : const ArrayColumn<DComplex> fluxValCol(itsTable, fluxName);
1040 31 : const ScalarColumn<String> fluxUnitCol(itsTable, fluxUnitName);
1041 31 : const ScalarColumn<String> fluxPolCol(itsTable, fluxPolName);
1042 31 : const ScalarColumn<String> shapeCol(itsTable, shapeName);
1043 31 : const MDirection::ScalarColumn dirCol(itsTable, refDirName);
1044 31 : const ArrayColumn<Double> shapeParmCol(itsTable, shapeParName);
1045 31 : const ScalarColumn<String> specShapeCol(itsTable, spectrumName);
1046 31 : const MFrequency::ScalarColumn freqCol(itsTable, refFreqName);
1047 31 : const ArrayColumn<Double> spectralParmCol(itsTable,spectParName);
1048 31 : const ScalarColumn<String> labelCol(itsTable, labelName);
1049 :
1050 31 : ArrayColumn<DComplex> fluxErrCol;
1051 31 : ROArrayQuantColumn<Double> dirErrCol;
1052 31 : ArrayColumn<Double> shapeErrCol;
1053 31 : ROScalarQuantColumn<Double> freqErrCol;
1054 31 : ArrayColumn<Double> spectralErrCol;
1055 31 : ScalarColumn<TableRecord> specRecord;
1056 31 : ArrayColumn<Double> optParmCol;
1057 : {// Old componentlist tables may not have the error columns
1058 31 : const ColumnDescSet& cds=itsTable.tableDesc().columnDescSet();
1059 31 : if (cds.isDefined(fluxErrName)) {
1060 31 : fluxErrCol.attach(itsTable, fluxErrName);
1061 : }
1062 31 : if (cds.isDefined(dirErrName)) {
1063 31 : dirErrCol.attach(itsTable, dirErrName);
1064 : }
1065 31 : if (cds.isDefined(shapeErrName)) {
1066 31 : shapeErrCol.attach(itsTable, shapeErrName);
1067 : }
1068 31 : if (cds.isDefined(freqErrName)) {
1069 31 : freqErrCol.attach(itsTable, freqErrName);
1070 : }
1071 31 : if (cds.isDefined(spectErrName)) {
1072 31 : spectralErrCol.attach(itsTable, spectErrName);
1073 : }
1074 31 : if (cds.isDefined(spectralRecordName)) {
1075 31 : specRecord.attach(itsTable, spectralRecordName);
1076 : }
1077 : // new optional parameter column
1078 31 : if (cds.isDefined(optParColName)) {
1079 0 : optParmCol.attach(itsTable,optParColName);
1080 : }
1081 : }
1082 :
1083 31 : SkyComponent currentComp;
1084 31 : const uInt nComp = fluxValCol.nrow();
1085 31 : Vector<DComplex> compFluxValue(4);
1086 31 : Vector<Double> shapeParms, spectralParms, optParms;
1087 31 : String compName, compLabel, compFluxPol, compFluxUnit, compSpectrum;
1088 31 : MDirection compDir;
1089 31 : MFrequency compFreq;
1090 31 : Vector<Quantum<Double> > newDirErr(2);
1091 31 : Quantum<Double> newFreqErr;
1092 189 : for (uInt i = 0; i < nComp; i++) {
1093 158 : shapeCol.get(i, compName);
1094 158 : specShapeCol.get(i, compSpectrum);
1095 : //cout << "CompSpec " << compSpectrum << " shape " <<ComponentType::spectralShape(compSpectrum) << endl;
1096 316 : currentComp = SkyComponent(ComponentType::shape(compName),
1097 316 : ComponentType::spectralShape(compSpectrum));
1098 : {
1099 158 : Flux<Double>& compFlux = currentComp.flux();
1100 158 : fluxValCol.get(i, compFluxValue);
1101 158 : compFlux.setValue(compFluxValue);
1102 158 : fluxUnitCol.get(i, compFluxUnit);
1103 158 : compFlux.setUnit(compFluxUnit);
1104 158 : fluxPolCol.get(i, compFluxPol);
1105 158 : compFlux.setPol(ComponentType::polarisation(compFluxPol));
1106 158 : if (!fluxErrCol.isNull()) {
1107 158 : fluxErrCol.get(i, compFluxValue);
1108 158 : compFlux.setErrors(compFluxValue(0), compFluxValue(1),
1109 158 : compFluxValue(2), compFluxValue(3));
1110 : }
1111 : }
1112 : {
1113 158 : ComponentShape& compShape = currentComp.shape();
1114 158 : dirCol.get(i, compDir);
1115 158 : compShape.setRefDirection(compDir);
1116 158 : if (!dirErrCol.isNull()) {
1117 158 : dirErrCol.get(i, newDirErr);
1118 158 : compShape.setRefDirectionError(newDirErr(0), newDirErr(1));
1119 : }
1120 158 : shapeParmCol.get(i, shapeParms, true);
1121 158 : compShape.setParameters(shapeParms);
1122 158 : if (!shapeErrCol.isNull()) {
1123 158 : shapeErrCol.get(i, shapeParms);
1124 158 : compShape.setErrors(shapeParms);
1125 : }
1126 : }
1127 : {
1128 158 : freqCol.get(i, compFreq);
1129 158 : SpectralModel& compSpectrum = currentComp.spectrum();
1130 :
1131 158 : if (!specRecord.isNull()) {
1132 158 : if(specRecord.isDefined(i)){
1133 158 : TableRecord rec;
1134 158 : specRecord.get(i, rec);
1135 158 : String err;
1136 158 : compSpectrum.fromRecord(err, rec);
1137 158 : }
1138 : }
1139 158 : compSpectrum.setRefFrequency(compFreq);
1140 158 : if (!freqErrCol.isNull()) {
1141 158 : freqErrCol.get(i, newFreqErr);
1142 158 : compSpectrum.setRefFrequencyError(newFreqErr);
1143 : }
1144 158 : spectralParmCol.get(i, spectralParms, true);
1145 158 : compSpectrum.setParameters(spectralParms);
1146 158 : if (!spectralErrCol.isNull()) {
1147 158 : spectralErrCol.get(i, spectralParms);
1148 158 : compSpectrum.setErrors(spectralParms);
1149 : }
1150 : }
1151 : {
1152 158 : labelCol.get(i, currentComp.label());
1153 : }
1154 : {
1155 158 : if (!optParmCol.isNull()) {
1156 0 : if (optParmCol.isDefined(i)) {
1157 0 : ComponentShape& compShape2 = currentComp.shape();
1158 0 : optParmCol.get(i,optParms,true);
1159 0 : compShape2.setOptParameters(optParms);
1160 0 : currentComp.optionalParameters()=optParms;
1161 : }
1162 : }
1163 : }
1164 :
1165 158 : add(currentComp);
1166 : }
1167 31 : itsROFlag = readOnly;
1168 31 : }
1169 :
1170 815 : Bool ComponentList::toRecord(String& error, RecordInterface& outRec) const {
1171 :
1172 815 : Bool retval=true;
1173 :
1174 815 : outRec.define("nelements", itsNelements);
1175 1694 : for (uInt k=0; k < itsNelements; ++k){
1176 879 : Record componentContainer;
1177 879 : retval= (retval && component(k).toRecord(error, componentContainer));
1178 1758 : String componentId=String("component")+String::toString(k);
1179 879 : outRec.defineRecord(componentId, componentContainer);
1180 :
1181 879 : }
1182 815 : return retval;
1183 :
1184 : }
1185 :
1186 25615 : Bool ComponentList::fromRecord(String& error, const RecordInterface& inRec){
1187 :
1188 25615 : Bool retval= true;
1189 25615 : if(itsNelements > 0){
1190 0 : LogIO logErr(LogOrigin("ComponentList", "fromRecord()"));
1191 : logErr << LogIO::SEVERE
1192 : << "Trying to overwrite a non-empty componentList from Record"
1193 0 : << LogIO::POST;
1194 0 : return false;
1195 :
1196 0 : }
1197 :
1198 25615 : uInt nelements=0;
1199 25615 : if (inRec.isDefined("nelements")) {
1200 25615 : inRec.get("nelements", nelements);
1201 25615 : if(nelements >0){
1202 51294 : for(uInt k=0; k < nelements; ++k){
1203 51358 : String componentId=String("component")+String::toString(k);
1204 25679 : Record componentRecord=inRec.asRecord(componentId);
1205 25679 : SkyComponent tempComponent;
1206 25679 : retval=(retval && tempComponent.fromRecord(error, componentRecord));
1207 25679 : if(retval){
1208 25679 : add(tempComponent);
1209 : }
1210 : else{
1211 0 : return retval;
1212 : }
1213 25679 : }
1214 : }
1215 : }
1216 25615 : return retval;
1217 : }
1218 :
1219 0 : String ComponentList::summarize(uInt index) const {
1220 0 : AlwaysAssert(index < nelements(), AipsError);
1221 0 : return component(index).summarize();
1222 : }
1223 :
1224 30 : Table& ComponentList::_getTable() {
1225 30 : return itsTable;
1226 : }
1227 :
1228 15 : const Table& ComponentList::getTable() const {
1229 15 : return itsTable;
1230 : }
1231 :
1232 0 : bool ComponentList::hasKeyword(const String& keyword) const {
1233 0 : ThrowIf(itsTable.isNull(), "A table is not attached to this ComponentList");
1234 0 : return itsTable.keywordSet().fieldNumber(keyword) >= 0;
1235 : }
1236 :
1237 0 : void ComponentList::putKeyword(const String& keyword, const variant& value) {
1238 0 : ThrowIf(itsTable.isNull(), "A table is not attached to this ComponentList");
1239 0 : if (! itsTable.isWritable()) {
1240 0 : itsTable.reopenRW();
1241 : }
1242 0 : std::unique_ptr<ValueHolder> aval(toValueHolder(value));
1243 0 : TableProxy tp(itsTable);
1244 0 : tp.putKeyword(String(), keyword, -1, false, *aval);
1245 0 : }
1246 :
1247 0 : variant* ComponentList::getKeyword(const String& keyword) const {
1248 0 : ThrowIf(itsTable.isNull(), "A table is not attached to this ComponentList");
1249 0 : TableProxy tp(itsTable);
1250 0 : auto value = tp.getKeyword(String(), keyword, -1);
1251 0 : return fromValueHolder(value);
1252 0 : }
1253 :
1254 : } //# NAMESPACE CASA - END
1255 :
|