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 7367 : ComponentList::ComponentList()
112 7367 : :itsList(),
113 7367 : itsNelements(0),
114 7367 : itsTable(),
115 7367 : itsROFlag(false),
116 7367 : itsSelectedFlags(),
117 7367 : itsOrder(),
118 7367 : itsAddOptCol(false),
119 7367 : itsRewriteTable(True)
120 : {
121 7367 : AlwaysAssert(ok(), AipsError);
122 7367 : }
123 :
124 3 : ComponentList::ComponentList(const Path& fileName, Bool readOnly, Bool rewriteTable)
125 3 : :itsList(),
126 3 : itsNelements(0),
127 3 : itsTable(),
128 3 : itsROFlag(false),
129 3 : itsSelectedFlags(),
130 3 : itsOrder(),
131 3 : itsAddOptCol(false),
132 3 : itsRewriteTable(rewriteTable)
133 : {
134 3 : readTable(fileName, readOnly);
135 3 : AlwaysAssert(ok(), AipsError);
136 3 : }
137 :
138 1 : ComponentList::ComponentList(const ComponentList& other)
139 1 : :itsList(other.itsList),
140 1 : itsNelements(other.itsNelements),
141 1 : itsTable(other.itsTable),
142 1 : itsROFlag(other.itsROFlag),
143 1 : itsSelectedFlags(other.itsSelectedFlags),
144 1 : itsOrder(other.itsOrder),
145 1 : itsAddOptCol(other.itsAddOptCol),
146 1 : itsRewriteTable(other.itsRewriteTable)
147 : {
148 1 : }
149 :
150 7370 : ComponentList::~ComponentList() {
151 7370 : if (! itsROFlag && ! itsTable.isNull() && itsRewriteTable) {
152 10 : writeTable();
153 : }
154 : // AlwaysAssert(ok(), AipsError);
155 7370 : }
156 :
157 325 : ComponentList& ComponentList::operator=(const ComponentList& other){
158 325 : if (this != &other) {
159 325 : if (! itsROFlag && ! itsTable.isNull() && itsRewriteTable) {
160 0 : writeTable();
161 : }
162 325 : itsList = other.itsList;
163 325 : itsNelements = other.itsNelements;
164 325 : itsTable = other.itsTable;
165 325 : itsROFlag = other.itsROFlag;
166 325 : itsSelectedFlags = other.itsSelectedFlags;
167 325 : itsOrder = other.itsOrder;
168 325 : itsAddOptCol = other.itsAddOptCol;
169 325 : itsRewriteTable = other.itsRewriteTable;
170 : }
171 325 : 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 0 : 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 0 : samples = 0.0;
211 0 : for (uInt i = 0; i < nelements(); i++) {
212 0 : component(i).sample(samples, reqUnit, directions, dirRef,
213 : pixelLatSize, pixelLongSize, frequencies, freqRef);
214 : }
215 0 : }
216 :
217 6737 : void ComponentList::add(SkyComponent component) {
218 : // AlwaysAssert(itsROFlag == false, AipsError);
219 6737 : uInt blockSize = itsList.nelements();
220 6737 : if (itsNelements == blockSize) {
221 6737 : const uInt newSize
222 6737 : = (blockSize < 50) ? 2 * blockSize + 1 : blockSize + 100;
223 6737 : itsList.resize(newSize);
224 6737 : itsSelectedFlags.resize(newSize);
225 6737 : itsOrder.resize(newSize);
226 : }
227 : // for limb-darkened disk shape, add an optional col
228 6737 : if (component.shape().type()==ComponentType::LDISK) {
229 0 : itsAddOptCol=true;
230 : }
231 6737 : itsList[itsNelements] = component;
232 6737 : itsSelectedFlags[itsNelements] = false;
233 6737 : itsOrder[itsNelements] = itsNelements;
234 6737 : itsNelements++;
235 6737 : }
236 :
237 130 : void ComponentList::addList(const ComponentList& list) {
238 260 : for (uInt i=0; i<list.nelements(); i++) {
239 130 : add(list.component(i));
240 : }
241 130 : }
242 :
243 :
244 0 : void ComponentList::remove(const uInt& index) {
245 : // AlwaysAssert(itsROFlag == false, AipsError);
246 0 : AlwaysAssert(index < nelements(), AipsError);
247 0 : uInt realIndex = itsOrder[index];
248 0 : itsSelectedFlags.remove(realIndex, false);
249 0 : itsList.remove(realIndex, false);
250 0 : itsOrder.remove(index, false);
251 0 : itsNelements--;
252 0 : for (uInt i = 0; i < nelements(); i++) {
253 0 : if (itsOrder[i] > realIndex) {
254 0 : itsOrder[i]--;
255 : }
256 : }
257 0 : }
258 :
259 0 : void ComponentList::remove(const Vector<Int>& indices) {
260 0 : Vector<Int> zeroCheck(indices);
261 0 : AlwaysAssert(allGE(zeroCheck, 0), AipsError);
262 0 : uInt c = indices.nelements();
263 0 : Vector<uInt> uIndices(c);
264 0 : convertArray(uIndices, indices);
265 0 : GenSort<uInt>::sort(uIndices);
266 0 : while (c != 0) {
267 0 : c--;
268 0 : remove(uIndices(c));
269 : }
270 0 : }
271 :
272 15993 : uInt ComponentList::nelements() const {
273 15993 : return itsNelements;
274 : }
275 :
276 2 : uInt ComponentList::size() const {
277 2 : 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 2 : void ComponentList::setLabel(const Vector<Int>& which,
315 : const String& newLabel) {
316 : uInt c;
317 4 : for (uInt i = 0; i < which.nelements(); i++) {
318 2 : AlwaysAssert(which(i) >= 0, AipsError);
319 2 : c = which(i);
320 2 : component(c).label() = newLabel;
321 : }
322 2 : }
323 :
324 65 : void ComponentList::getFlux(Vector<casacore::Quantity>& fluxQuant, int which) const {
325 65 : 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 65 : Vector<Complex> flux(comp.flux().value().nelements());
330 65 : convertArray(flux,comp.flux().value());
331 65 : Unit unit = comp.flux().unit();
332 65 : fluxQuant.resize(flux.nelements());
333 325 : for (uInt i=0; i<flux.nelements(); ++i) {
334 260 : fluxQuant[i] = casacore::Quantity(real(flux[i]), unit);
335 : }
336 65 : }
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 2 : void ComponentList::setFlux(const Vector<Int>& which,
352 : const Flux<Double>& newFlux) {
353 : uInt c;
354 4 : for (uInt i = 0; i < which.nelements(); i++) {
355 2 : AlwaysAssert(which(i) >= 0, AipsError);
356 2 : c = which(i);
357 2 : component(c).flux() = newFlux;
358 : }
359 2 : }
360 :
361 130 : Vector<String> ComponentList::getStokes(const Int& which) const {
362 130 : SkyComponent comp = component(which);
363 130 : ComponentType::Polarisation stokesType = comp.flux().pol();
364 130 : Vector<String> polarization(4);
365 : // the polarization determination logic needs to be refactored into
366 : // a method in a more appropriate class
367 130 : if (stokesType == ComponentType::STOKES) {
368 130 : polarization[0] = "I";
369 130 : polarization[1] = "Q";
370 130 : polarization[2] = "U";
371 130 : 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 260 : return polarization;
389 130 : }
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 2 : void ComponentList::setRefDirection(const Vector<Int>& which,
412 : const MVDirection& newDir) {
413 : uInt c;
414 2 : MDirection curDir;
415 4 : for (uInt i = 0; i < which.nelements(); i++) {
416 2 : AlwaysAssert(which(i) >= 0, AipsError);
417 2 : c = which(i);
418 2 : ComponentShape& curShape = component(c).shape();
419 2 : curDir = curShape.refDirection();
420 2 : curDir.set(newDir);
421 2 : curShape.setRefDirection(curDir);
422 : }
423 2 : }
424 :
425 2 : void ComponentList::setRefDirectionFrame(const Vector<Int>& which,
426 : MDirection::Types newFrame) {
427 : uInt c;
428 2 : MDirection curDir;
429 2 : const MDirection::Ref newRef(newFrame);
430 4 : for (uInt i = 0; i < which.nelements(); i++) {
431 2 : AlwaysAssert(which(i) >= 0, AipsError);
432 2 : c = which(i);
433 2 : ComponentShape& curShape = component(c).shape();
434 2 : curDir = curShape.refDirection();
435 2 : curDir.set(newRef);
436 2 : curShape.setRefDirection(curDir);
437 : }
438 2 : }
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 0 : MDirection ComponentList::getRefDirection(Int which) const {
456 0 : const ComponentShape& compShape = component(which).shape();
457 0 : MDirection refDir = compShape.refDirection();
458 0 : return refDir;
459 : }
460 :
461 130 : void ComponentList::setShape(const Vector<Int>& which,
462 : const ComponentShape& newShape) {
463 : uInt c;
464 260 : for (uInt i = 0; i < which.nelements(); i++) {
465 130 : AlwaysAssert(which(i) >= 0, AipsError);
466 130 : c = which(i);
467 130 : component(c).setShape(newShape);
468 : //for limb-darkened disk shape
469 130 : if (newShape.type()==ComponentType::LDISK) {
470 0 : itsAddOptCol=true;
471 : }
472 : }
473 130 : }
474 :
475 388 : const ComponentShape* ComponentList::getShape(Int which) const {
476 388 : return component(which).shape().getPtr();
477 : }
478 :
479 :
480 2 : void ComponentList::setShapeParms(const Vector<Int>& which,
481 : const ComponentShape& newShape) {
482 : uInt c;
483 2 : MDirection oldDir;
484 4 : for (uInt i = 0; i < which.nelements(); i++) {
485 2 : AlwaysAssert(which(i) >= 0, AipsError);
486 2 : c = which(i);
487 2 : SkyComponent& comp = component(c);
488 2 : oldDir = comp.shape().refDirection();
489 2 : component(c).setShape(newShape);
490 2 : comp.shape().setRefDirection(oldDir);
491 : }
492 2 : }
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 3 : void ComponentList::setSpectrumParms(const Vector<Int>& which,
523 : const SpectralModel& newSpectrum) {
524 : uInt c;
525 3 : MFrequency oldFreq;
526 6 : for (uInt i = 0; i < which.nelements(); i++) {
527 3 : AlwaysAssert(which(i) >= 0, AipsError);
528 3 : c = which(i);
529 3 : SkyComponent& comp = component(c);
530 3 : oldFreq = comp.spectrum().refFrequency();
531 3 : component(c).setSpectrum(newSpectrum);
532 3 : comp.spectrum().setRefFrequency(oldFreq);
533 : }
534 3 : }
535 :
536 8 : void ComponentList::setRefFrequency(const Vector<Int>& which,
537 : const MVFrequency& newFreq) {
538 : uInt c;
539 8 : MFrequency curFreq;
540 16 : for (uInt i = 0; i < which.nelements(); i++) {
541 8 : AlwaysAssert(which(i) >= 0, AipsError);
542 8 : c = which(i);
543 8 : SpectralModel& curSpectrum = component(c).spectrum();
544 8 : curFreq = curSpectrum.refFrequency();
545 8 : curFreq.set(newFreq);
546 8 : curSpectrum.setRefFrequency(curFreq);
547 : }
548 8 : }
549 :
550 2 : void ComponentList::setRefFrequencyFrame(const Vector<Int>& which,
551 : MFrequency::Types newFrame) {
552 : uInt c;
553 2 : MFrequency curFreq;
554 2 : const MFrequency::Ref newRef(newFrame);
555 4 : for (uInt i = 0; i < which.nelements(); i++) {
556 2 : AlwaysAssert(which(i) >= 0, AipsError);
557 2 : c = which(i);
558 2 : SpectralModel& curSpectrum = component(c).spectrum();
559 2 : curFreq = curSpectrum.refFrequency();
560 2 : curFreq.set(newRef);
561 2 : curSpectrum.setRefFrequency(curFreq);
562 : }
563 2 : }
564 :
565 :
566 2 : void ComponentList::setRefFrequencyUnit(const Vector<Int>& which,
567 : const Unit& unit) {
568 : uInt c;
569 4 : for (uInt i = 0; i < which.nelements(); i++) {
570 2 : AlwaysAssert(which(i) >= 0, AipsError);
571 2 : c = which(i);
572 2 : component(c).spectrum().convertFrequencyUnit(unit);
573 : }
574 2 : }
575 :
576 594 : SkyComponent& ComponentList::component(const uInt& index) {
577 : // AlwaysAssert(itsROFlag == false, AipsError);
578 594 : AlwaysAssert(index < nelements(), AipsError);
579 594 : return itsList[itsOrder[index]];
580 : }
581 :
582 7774 : const SkyComponent& ComponentList::component(const uInt& index) const {
583 7774 : AlwaysAssert(index < nelements(), AipsError);
584 7774 : return itsList[itsOrder[index]];
585 : }
586 :
587 8 : void ComponentList::rename(const Path& fileName,
588 : const Table::TableOption option) {
589 8 : AlwaysAssert(option != Table::Old, AipsError);
590 8 : AlwaysAssert(itsROFlag == false, AipsError);
591 8 : if (fileName.length() != 0) {
592 : // See if this list is associated with a Table.
593 8 : if (itsTable.isNull()) {
594 : //createTable(fileName, option, addOptCol_p);
595 8 : 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 8 : itsTable.flush();
604 : } else {
605 0 : if (!itsTable.isNull()) {
606 0 : itsTable.markForDelete();
607 0 : itsTable = Table();
608 0 : itsROFlag = false;
609 : }
610 : }
611 8 : }
612 :
613 0 : ComponentList ComponentList::copy() const {
614 0 : ComponentList copiedList;
615 0 : SkyComponent currentComp;
616 0 : for (uInt c = 0; c < nelements(); c++) {
617 0 : currentComp = component(c).copy();
618 0 : copiedList.add(currentComp);
619 : }
620 0 : return copiedList;
621 0 : }
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 7370 : 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 7370 : 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 7370 : 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 7370 : if (! itsTable.isNull()) {
715 3 : String tablename = itsTable.tableName();
716 3 : 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 3 : 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 3 : }
731 7373 : for (uInt i = 0; i < itsNelements; i++) {
732 3 : 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 7370 : return true;
741 : }
742 :
743 8 : 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 16 : TableDesc td("ComponentListDescription", "4", TableDesc::Scratch);
749 8 : td.comment() = "A description of a component list";
750 : {
751 : {
752 : const ArrayColumnDesc<DComplex>
753 16 : fluxValCol(fluxName, "Flux values", IPosition(1,4),ColumnDesc::Direct);
754 8 : td.addColumn(fluxValCol);
755 : const ScalarColumnDesc<String>
756 8 : fluxUnitCol(fluxUnitName, "Flux units", ColumnDesc::Direct);
757 8 : td.addColumn(fluxUnitCol);
758 : const ScalarColumnDesc<String>
759 : fluxPolCol(fluxPolName, "Flux polarisation representation",
760 8 : ColumnDesc::Direct);
761 8 : td.addColumn(fluxPolCol);
762 : const ArrayColumnDesc<DComplex>
763 8 : fluxErrCol(fluxErrName, "Flux errors", IPosition(1,4),
764 16 : ColumnDesc::Direct);
765 8 : td.addColumn(fluxErrCol);
766 8 : }
767 : {
768 : const ScalarColumnDesc<String>
769 8 : shapeCol(shapeName, "Shape of the Component", ColumnDesc::Direct);
770 8 : td.addColumn(shapeCol);
771 8 : const String dirValColName = refDirName;
772 : const ArrayColumnDesc<Double>
773 : dirValCol(dirValColName, "Reference direction values",
774 16 : IPosition(1,2), ColumnDesc::Direct);
775 8 : td.addColumn(dirValCol);
776 8 : const String dirRefColName = "Direction_Frame";
777 : const ScalarColumnDesc<String>
778 : dirRefCol(dirRefColName, "The reference direction frame",
779 8 : ColumnDesc::Direct);
780 8 : td.addColumn(dirRefCol);
781 : {
782 8 : const TableMeasRefDesc dirRefTMCol(td, dirRefColName);
783 8 : const TableMeasValueDesc dirValTMCol(td, dirValColName);
784 8 : TableMeasDesc<MDirection> dirTMCol(dirValTMCol, dirRefTMCol);
785 8 : dirTMCol.write(td);
786 8 : }
787 : const ArrayColumnDesc<Double>
788 : dirErrCol(dirErrName, "Error in the reference direction values",
789 16 : IPosition(1,2), ColumnDesc::Direct);
790 8 : td.addColumn(dirErrCol);
791 : const ArrayColumnDesc<String>
792 : dirErrUnitCol(dirErrUnitName, "Units of the direction error",
793 16 : IPosition(1,2), ColumnDesc::Direct);
794 8 : td.addColumn(dirErrUnitCol);
795 : {
796 8 : TableQuantumDesc dirErrTMCol(td, dirErrName, dirErrUnitName);
797 8 : dirErrTMCol.write(td);
798 8 : }
799 :
800 : const ArrayColumnDesc<Double>
801 : shapeParmCol(shapeParName,
802 8 : "Parameters specific to the component shape", 1);
803 8 : td.addColumn(shapeParmCol);
804 : const ArrayColumnDesc<Double>
805 : shapeErrCol(shapeErrName,
806 8 : "Error in the shape parameters", 1);
807 8 : td.addColumn(shapeErrCol);
808 8 : }
809 : {
810 : const ScalarColumnDesc<String>
811 : freqShapeCol(spectrumName, "Shape of the spectrum",
812 8 : ColumnDesc::Direct);
813 8 : td.addColumn (freqShapeCol);
814 8 : const String freqValColName = refFreqName;
815 : const ScalarColumnDesc<Double>
816 : freqValCol(freqValColName, "The reference frequency values",
817 8 : ColumnDesc::Direct);
818 8 : td.addColumn(freqValCol);
819 8 : const String freqRefColName = "Frequency_Frame";
820 : const ScalarColumnDesc<String>
821 : freqRefCol(freqRefColName, "The reference frequency frame",
822 8 : ColumnDesc::Direct);
823 8 : td.addColumn(freqRefCol);
824 : {
825 8 : const TableMeasRefDesc freqRefTMCol(td, freqRefColName);
826 8 : const TableMeasValueDesc freqValTMCol(td, freqValColName);
827 8 : TableMeasDesc<MFrequency> freqTMCol(freqValTMCol, freqRefTMCol);
828 8 : freqTMCol.write(td);
829 8 : }
830 : const ScalarColumnDesc<Double>
831 : freqErrCol(freqErrName, "Error in the reference frequency",
832 8 : ColumnDesc::Direct);
833 8 : td.addColumn(freqErrCol);
834 : const ScalarColumnDesc<String>
835 : freqErrUnitCol(freqErrUnitName, "Units of the frequency error",
836 8 : ColumnDesc::Direct);
837 8 : td.addColumn(freqErrUnitCol);
838 : {
839 8 : TableQuantumDesc freqErrTMCol(td, freqErrName, freqErrUnitName);
840 8 : freqErrTMCol.write(td);
841 8 : }
842 : const ArrayColumnDesc<Double>
843 : specParmCol(spectParName,
844 8 : "Parameters specific to the components spectrum", 1);
845 8 : td.addColumn(specParmCol);
846 : const ArrayColumnDesc<Double>
847 : specErrCol(spectErrName,
848 8 : "Errors in the spectral parameters", 1);
849 8 : td.addColumn(specErrCol);
850 8 : }
851 : {
852 : const ScalarColumnDesc<String>
853 : labelCol(labelName, "An arbitrary label for the user",
854 8 : ColumnDesc::Direct);
855 8 : td.addColumn (labelCol);
856 8 : }
857 : }
858 8 : 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 8 : SetupNewTable newTable(fileName.absoluteName(), td, option);
865 :
866 8 : if (itsAddOptCol) {
867 0 : TiledCellStMan optcolsm("TiledOptParms",IPosition(1,1));
868 0 : newTable.bindColumn(optParColName,optcolsm);
869 0 : }
870 8 : itsTable = Table(newTable, TableLock::AutoLocking, nelements(), false);
871 : {
872 8 : TableInfo& info(itsTable.tableInfo());
873 8 : info.setType(TableInfo::type(TableInfo::COMPONENTLIST));
874 8 : info.readmeAddLine(String(
875 : "This is a ComponentList Table containing parameterised representations"));
876 8 : info.readmeAddLine(String("of the sky brightness."));
877 : }
878 8 : }
879 :
880 10 : void ComponentList::writeTable() {
881 10 : if (itsTable.isWritable() == false) {
882 0 : itsTable.reopenRW();
883 : }
884 : {
885 10 : const casacore::rownr_t nRows = itsTable.nrow();
886 10 : const casacore::rownr_t nelem = nelements();
887 10 : if (nRows < nelem) {
888 0 : itsTable.addRow(nelem - nRows);
889 10 : } 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 10 : ArrayColumn<DComplex> fluxValCol(itsTable, fluxName);
896 10 : ScalarColumn<String> fluxUnitCol(itsTable, fluxUnitName);
897 10 : ScalarColumn<String> fluxPolCol(itsTable, fluxPolName);
898 10 : ScalarColumn<String> shapeCol(itsTable, shapeName);
899 10 : MDirection::ScalarColumn dirCol(itsTable, refDirName);
900 10 : ArrayColumn<Double> shapeParmCol(itsTable, shapeParName);
901 10 : ScalarColumn<String> specShapeCol(itsTable, spectrumName);
902 10 : MFrequency::ScalarColumn freqCol(itsTable, refFreqName);
903 10 : ArrayColumn<Double> specShapeParmCol(itsTable, spectParName);
904 10 : ScalarColumn<String> labelCol(itsTable, labelName);
905 10 : ArrayColumn<DComplex> fluxErrCol;
906 10 : ArrayQuantColumn<Double> dirErrCol;
907 10 : ArrayColumn<Double> shapeErrCol;
908 10 : ScalarQuantColumn<Double> freqErrCol;
909 10 : ArrayColumn<Double> spectErrCol;
910 10 : ScalarColumn<TableRecord> specRecord;
911 10 : ArrayColumn<Double> optParCol;
912 : {
913 10 : const ColumnDescSet& cds=itsTable.tableDesc().columnDescSet();
914 10 : if (!cds.isDefined(spectralRecordName)) {
915 8 : itsTable.addColumn(ScalarRecordColumnDesc(spectralRecordName));
916 : }
917 10 : specRecord.attach(itsTable, spectralRecordName);
918 10 : if (!cds.isDefined(fluxErrName)) {
919 : itsTable.addColumn
920 0 : (ArrayColumnDesc<DComplex>(fluxErrName, "Flux errors", IPosition(1,4),
921 : ColumnDesc::Direct));
922 : }
923 :
924 10 : fluxErrCol.attach(itsTable, fluxErrName);
925 10 : 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 10 : dirErrCol.attach(itsTable, dirErrName);
939 10 : if (!cds.isDefined(shapeErrName)) {
940 : itsTable.addColumn
941 0 : (ArrayColumnDesc<Double>(shapeErrName,
942 : "Error in the shape parameters", 1));
943 : }
944 10 : shapeErrCol.attach(itsTable, shapeErrName);
945 :
946 10 : 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 10 : freqErrCol.attach(itsTable, freqErrName);
960 10 : if (!cds.isDefined(spectErrName)) {
961 : itsTable.addColumn
962 0 : (ArrayColumnDesc<Double>(spectErrName,
963 : "Error in the spectral parameters", 1));
964 : }
965 10 : spectErrCol.attach(itsTable, spectErrName);
966 :
967 10 : 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 10 : Vector<Quantum<Double> > dirErr(2);
979 20 : for (uInt i = 0; i < nelements(); i++) {
980 : {
981 10 : const Flux<Double>& flux = component(i).flux();
982 10 : fluxValCol.put(i, flux.value());
983 10 : fluxUnitCol.put(i, flux.unit().getName());
984 10 : fluxPolCol.put(i, ComponentType::name(flux.pol()));
985 10 : fluxErrCol.put(i, flux.errors());
986 : }
987 : {
988 10 : const ComponentShape& compShape = component(i).shape();
989 10 : shapeCol.put(i, compShape.ident());
990 10 : dirCol.put(i, compShape.refDirection());
991 10 : if (!dirErrCol.isNull()) {
992 10 : dirErr(0) = compShape.refDirectionErrorLat();
993 10 : dirErr(1) = compShape.refDirectionErrorLong();
994 10 : dirErrCol.put(i, dirErr);
995 : }
996 10 : shapeParmCol.put(i, compShape.parameters());
997 10 : shapeErrCol.put(i, compShape.errors());
998 : }
999 : {
1000 10 : const SpectralModel& compSpectrum = component(i).spectrum();
1001 10 : specShapeCol.put(i, compSpectrum.ident());
1002 10 : TableRecord rec;
1003 10 : String err;
1004 10 : if(compSpectrum.toRecord(err, rec))
1005 10 : specRecord.put(i,rec);
1006 10 : freqCol.put(i, compSpectrum.refFrequency());
1007 10 : if (!freqErrCol.isNull()) {
1008 10 : freqErrCol.put(i, compSpectrum.refFrequencyError());
1009 : }
1010 10 : specShapeParmCol.put(i, compSpectrum.parameters());
1011 10 : spectErrCol.put(i, compSpectrum.errors());
1012 10 : }
1013 : {
1014 10 : labelCol.put(i, component(i).label());
1015 : }
1016 10 : 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 10 : }
1025 :
1026 3 : void ComponentList::readTable(const Path& fileName, const Bool readOnly) {
1027 : {
1028 3 : const String& fullName = fileName.absoluteName();
1029 3 : if (readOnly) {
1030 1 : AlwaysAssert(Table::isReadable(fullName), AipsError);
1031 1 : itsTable = Table(fullName, Table::Old);
1032 : }
1033 : else {
1034 2 : AlwaysAssert(Table::isWritable(fullName), AipsError);
1035 4 : itsTable = Table(fullName, TableLock(TableLock::AutoLocking),
1036 2 : Table::Update);
1037 : }
1038 : }
1039 3 : const ArrayColumn<DComplex> fluxValCol(itsTable, fluxName);
1040 3 : const ScalarColumn<String> fluxUnitCol(itsTable, fluxUnitName);
1041 3 : const ScalarColumn<String> fluxPolCol(itsTable, fluxPolName);
1042 3 : const ScalarColumn<String> shapeCol(itsTable, shapeName);
1043 3 : const MDirection::ScalarColumn dirCol(itsTable, refDirName);
1044 3 : const ArrayColumn<Double> shapeParmCol(itsTable, shapeParName);
1045 3 : const ScalarColumn<String> specShapeCol(itsTable, spectrumName);
1046 3 : const MFrequency::ScalarColumn freqCol(itsTable, refFreqName);
1047 3 : const ArrayColumn<Double> spectralParmCol(itsTable,spectParName);
1048 3 : const ScalarColumn<String> labelCol(itsTable, labelName);
1049 :
1050 3 : ArrayColumn<DComplex> fluxErrCol;
1051 3 : ROArrayQuantColumn<Double> dirErrCol;
1052 3 : ArrayColumn<Double> shapeErrCol;
1053 3 : ROScalarQuantColumn<Double> freqErrCol;
1054 3 : ArrayColumn<Double> spectralErrCol;
1055 3 : ScalarColumn<TableRecord> specRecord;
1056 3 : ArrayColumn<Double> optParmCol;
1057 : {// Old componentlist tables may not have the error columns
1058 3 : const ColumnDescSet& cds=itsTable.tableDesc().columnDescSet();
1059 3 : if (cds.isDefined(fluxErrName)) {
1060 3 : fluxErrCol.attach(itsTable, fluxErrName);
1061 : }
1062 3 : if (cds.isDefined(dirErrName)) {
1063 3 : dirErrCol.attach(itsTable, dirErrName);
1064 : }
1065 3 : if (cds.isDefined(shapeErrName)) {
1066 3 : shapeErrCol.attach(itsTable, shapeErrName);
1067 : }
1068 3 : if (cds.isDefined(freqErrName)) {
1069 3 : freqErrCol.attach(itsTable, freqErrName);
1070 : }
1071 3 : if (cds.isDefined(spectErrName)) {
1072 3 : spectralErrCol.attach(itsTable, spectErrName);
1073 : }
1074 3 : if (cds.isDefined(spectralRecordName)) {
1075 3 : specRecord.attach(itsTable, spectralRecordName);
1076 : }
1077 : // new optional parameter column
1078 3 : if (cds.isDefined(optParColName)) {
1079 0 : optParmCol.attach(itsTable,optParColName);
1080 : }
1081 : }
1082 :
1083 3 : SkyComponent currentComp;
1084 3 : const uInt nComp = fluxValCol.nrow();
1085 3 : Vector<DComplex> compFluxValue(4);
1086 3 : Vector<Double> shapeParms, spectralParms, optParms;
1087 3 : String compName, compLabel, compFluxPol, compFluxUnit, compSpectrum;
1088 3 : MDirection compDir;
1089 3 : MFrequency compFreq;
1090 3 : Vector<Quantum<Double> > newDirErr(2);
1091 3 : Quantum<Double> newFreqErr;
1092 6 : for (uInt i = 0; i < nComp; i++) {
1093 3 : shapeCol.get(i, compName);
1094 3 : specShapeCol.get(i, compSpectrum);
1095 : //cout << "CompSpec " << compSpectrum << " shape " <<ComponentType::spectralShape(compSpectrum) << endl;
1096 6 : currentComp = SkyComponent(ComponentType::shape(compName),
1097 6 : ComponentType::spectralShape(compSpectrum));
1098 : {
1099 3 : Flux<Double>& compFlux = currentComp.flux();
1100 3 : fluxValCol.get(i, compFluxValue);
1101 3 : compFlux.setValue(compFluxValue);
1102 3 : fluxUnitCol.get(i, compFluxUnit);
1103 3 : compFlux.setUnit(compFluxUnit);
1104 3 : fluxPolCol.get(i, compFluxPol);
1105 3 : compFlux.setPol(ComponentType::polarisation(compFluxPol));
1106 3 : if (!fluxErrCol.isNull()) {
1107 3 : fluxErrCol.get(i, compFluxValue);
1108 3 : compFlux.setErrors(compFluxValue(0), compFluxValue(1),
1109 3 : compFluxValue(2), compFluxValue(3));
1110 : }
1111 : }
1112 : {
1113 3 : ComponentShape& compShape = currentComp.shape();
1114 3 : dirCol.get(i, compDir);
1115 3 : compShape.setRefDirection(compDir);
1116 3 : if (!dirErrCol.isNull()) {
1117 3 : dirErrCol.get(i, newDirErr);
1118 3 : compShape.setRefDirectionError(newDirErr(0), newDirErr(1));
1119 : }
1120 3 : shapeParmCol.get(i, shapeParms, true);
1121 3 : compShape.setParameters(shapeParms);
1122 3 : if (!shapeErrCol.isNull()) {
1123 3 : shapeErrCol.get(i, shapeParms);
1124 3 : compShape.setErrors(shapeParms);
1125 : }
1126 : }
1127 : {
1128 3 : freqCol.get(i, compFreq);
1129 3 : SpectralModel& compSpectrum = currentComp.spectrum();
1130 :
1131 3 : if (!specRecord.isNull()) {
1132 3 : if(specRecord.isDefined(i)){
1133 3 : TableRecord rec;
1134 3 : specRecord.get(i, rec);
1135 3 : String err;
1136 3 : compSpectrum.fromRecord(err, rec);
1137 3 : }
1138 : }
1139 3 : compSpectrum.setRefFrequency(compFreq);
1140 3 : if (!freqErrCol.isNull()) {
1141 3 : freqErrCol.get(i, newFreqErr);
1142 3 : compSpectrum.setRefFrequencyError(newFreqErr);
1143 : }
1144 3 : spectralParmCol.get(i, spectralParms, true);
1145 3 : compSpectrum.setParameters(spectralParms);
1146 3 : if (!spectralErrCol.isNull()) {
1147 3 : spectralErrCol.get(i, spectralParms);
1148 3 : compSpectrum.setErrors(spectralParms);
1149 : }
1150 : }
1151 : {
1152 3 : labelCol.get(i, currentComp.label());
1153 : }
1154 : {
1155 3 : 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 3 : add(currentComp);
1166 : }
1167 3 : itsROFlag = readOnly;
1168 3 : }
1169 :
1170 396 : Bool ComponentList::toRecord(String& error, RecordInterface& outRec) const {
1171 :
1172 396 : Bool retval=true;
1173 :
1174 396 : outRec.define("nelements", itsNelements);
1175 792 : for (uInt k=0; k < itsNelements; ++k){
1176 396 : Record componentContainer;
1177 396 : retval= (retval && component(k).toRecord(error, componentContainer));
1178 792 : String componentId=String("component")+String::toString(k);
1179 396 : outRec.defineRecord(componentId, componentContainer);
1180 :
1181 396 : }
1182 396 : return retval;
1183 :
1184 : }
1185 :
1186 6465 : Bool ComponentList::fromRecord(String& error, const RecordInterface& inRec){
1187 :
1188 6465 : Bool retval= true;
1189 6465 : 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 6465 : uInt nelements=0;
1199 6465 : if (inRec.isDefined("nelements")) {
1200 6465 : inRec.get("nelements", nelements);
1201 6465 : if(nelements >0){
1202 12930 : for(uInt k=0; k < nelements; ++k){
1203 12930 : String componentId=String("component")+String::toString(k);
1204 6465 : Record componentRecord=inRec.asRecord(componentId);
1205 6465 : SkyComponent tempComponent;
1206 6465 : retval=(retval && tempComponent.fromRecord(error, componentRecord));
1207 6465 : if(retval){
1208 6465 : add(tempComponent);
1209 : }
1210 : else{
1211 0 : return retval;
1212 : }
1213 6465 : }
1214 : }
1215 : }
1216 6465 : 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 0 : Table& ComponentList::_getTable() {
1225 0 : return itsTable;
1226 : }
1227 :
1228 0 : const Table& ComponentList::getTable() const {
1229 0 : 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 :
|