Line data Source code
1 : //# AsdmStMan.cc: Storage Manager for the main table of a raw ASDM MS
2 : //# Copyright (C) 2012
3 : //# Associated Universities, Inc. Washington DC, USA.
4 : //# (c) European Southern Observatory, 2012
5 : //# Copyright by ESO (in the framework of the ALMA collaboration)
6 : //#
7 : //# This library is free software; you can redistribute it and/or modify it
8 : //# under the terms of the GNU Library General Public License as published by
9 : //# the Free Software Foundation; either version 2 of the License, or (at your
10 : //# option) any later version.
11 : //#
12 : //# This library is distributed in the hope that it will be useful, but WITHOUT
13 : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 : //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
15 : //# License for more details.
16 : //#
17 : //# You should have receied a copy of the GNU Library General Public License
18 : //# along with this library; if not, write to the Free Software Foundation,
19 : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
20 : //#
21 : //# Correspondence concerning AIPS++ should be addressed as follows:
22 : //# Internet email: aips2-request@nrao.edu.
23 : //# Postal address: AIPS++ Project Office
24 : //# National Radio Astronomy Observatory
25 : //# 520 Edgemont Road
26 : //# Charlottesville, VA 22903-2475 USA
27 : //#
28 : //# $Id: AsdmStMan.cc 21600 2012-07-16 09:59:20Z diepen $
29 :
30 : #include <asdmstman/AsdmStMan.h>
31 : #include <asdmstman/AsdmColumn.h>
32 : #include <casacore/tables/Tables/Table.h>
33 : #include <casacore/tables/DataMan/DataManError.h>
34 : #include <casacore/casa/Containers/Record.h>
35 : #include <casacore/casa/Containers/BlockIO.h>
36 : #include <casacore/casa/IO/AipsIO.h>
37 : #include <casacore/casa/OS/CanonicalConversion.h>
38 : #include <casacore/casa/OS/HostInfo.h>
39 : #include <casacore/casa/OS/DOos.h>
40 : #include <casacore/casa/Utilities/BinarySearch.h>
41 : #include <casacore/casa/Utilities/Assert.h>
42 : #include <casacore/casa/Logging/LogIO.h>
43 :
44 : #include <map>
45 :
46 : #if !defined(__clang__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
47 : #define CASA_ATTR_VECTORIZE __attribute__((optimize("tree-vectorize")))
48 : #else
49 : #define CASA_ATTR_VECTORIZE
50 : #endif
51 :
52 : using namespace std;
53 :
54 : using namespace casacore;
55 : namespace casa {
56 :
57 0 : AsdmStMan::AsdmStMan (const String& dataManName)
58 : : DataManager (),
59 : itsDataManName (dataManName),
60 : itsBDF (0),
61 : itsOpenBDF (-1),
62 0 : itsNBl(0)
63 0 : {}
64 :
65 0 : AsdmStMan::AsdmStMan (const String& dataManName,
66 0 : const Record&)
67 : : DataManager (),
68 : itsDataManName (dataManName),
69 : itsBDF (0),
70 : itsOpenBDF (-1),
71 0 : itsNBl(0)
72 0 : {}
73 :
74 0 : AsdmStMan::AsdmStMan (const AsdmStMan& that)
75 : : DataManager (),
76 0 : itsDataManName (that.itsDataManName),
77 : itsBDF (0),
78 : itsOpenBDF (-1),
79 0 : itsNBl(0)
80 0 : {}
81 :
82 0 : AsdmStMan::~AsdmStMan()
83 : {
84 0 : for (uInt i=0; i<ncolumn(); i++) {
85 0 : delete itsColumns[i];
86 : }
87 0 : closeBDF();
88 0 : }
89 :
90 0 : DataManager* AsdmStMan::clone() const
91 : {
92 0 : return new AsdmStMan (*this);
93 : }
94 :
95 0 : String AsdmStMan::dataManagerType() const
96 : {
97 0 : return "AsdmStMan";
98 : }
99 :
100 0 : String AsdmStMan::dataManagerName() const
101 : {
102 0 : return itsDataManName;
103 : }
104 :
105 0 : Record AsdmStMan::dataManagerSpec() const
106 : {
107 0 : return itsSpec;
108 : }
109 :
110 :
111 0 : DataManagerColumn* AsdmStMan::makeScalarColumn (const String& name,
112 : int,
113 : const String&)
114 : {
115 0 : throw DataManError(name + " is unknown scalar column for AsdmStMan");
116 : }
117 :
118 0 : DataManagerColumn* AsdmStMan::makeDirArrColumn (const String& name,
119 : int dataType,
120 : const String& dataTypeId)
121 : {
122 0 : return makeIndArrColumn (name, dataType, dataTypeId);
123 : }
124 :
125 0 : DataManagerColumn* AsdmStMan::makeIndArrColumn (const String& name,
126 : int dtype,
127 : const String&)
128 : {
129 : AsdmColumn* col;
130 0 : if (name == "DATA") {
131 0 : col = new AsdmDataColumn(this, dtype);
132 0 : } else if (name == "FLOAT_DATA") {
133 0 : col = new AsdmFloatDataColumn(this, dtype);
134 0 : } else if (name == "FLAG") {
135 0 : col = new AsdmFlagColumn(this, dtype);
136 0 : } else if (name == "WEIGHT") {
137 0 : col = new AsdmWeightColumn(this, dtype);
138 0 : } else if (name == "SIGMA") {
139 0 : col = new AsdmSigmaColumn(this, dtype);
140 : } else {
141 0 : throw DataManError (name + " is unknown array column for AsdmStMan");
142 : }
143 0 : itsColumns.push_back (col);
144 0 : return col;
145 : }
146 :
147 0 : DataManager* AsdmStMan::makeObject (const String& group, const Record& spec)
148 : {
149 : // This function is called when reading a table back.
150 0 : return new AsdmStMan (group, spec);
151 : }
152 :
153 0 : void AsdmStMan::registerClass()
154 : {
155 0 : DataManager::registerCtor ("AsdmStMan", makeObject);
156 0 : }
157 :
158 0 : Bool AsdmStMan::isRegular() const
159 : {
160 0 : return false;
161 : }
162 0 : Bool AsdmStMan::canAddRow() const
163 : {
164 0 : return true;
165 : }
166 0 : Bool AsdmStMan::canRemoveRow() const
167 : {
168 0 : return false;
169 : }
170 0 : Bool AsdmStMan::canAddColumn() const
171 : {
172 0 : return true;
173 : }
174 0 : Bool AsdmStMan::canRemoveColumn() const
175 : {
176 0 : return true;
177 : }
178 :
179 0 : void AsdmStMan::addRow (uInt)
180 0 : {}
181 0 : void AsdmStMan::removeRow (uInt)
182 : {
183 0 : throw DataManError ("AsdmStMan cannot remove rows");
184 : }
185 0 : void AsdmStMan::addColumn (DataManagerColumn*)
186 0 : {}
187 0 : void AsdmStMan::removeColumn (DataManagerColumn*)
188 0 : {}
189 :
190 0 : Bool AsdmStMan::flush (AipsIO&, Bool)
191 : {
192 0 : return false;
193 : }
194 :
195 0 : void AsdmStMan::create (uInt)
196 0 : {}
197 :
198 0 : void AsdmStMan::open (uInt, AipsIO&)
199 : {
200 : // Read the index file.
201 0 : init();
202 0 : }
203 :
204 0 : void AsdmStMan::prepare()
205 : {
206 0 : for (uInt i=0; i<ncolumn(); i++) {
207 0 : itsColumns[i]->prepareCol();
208 : }
209 0 : }
210 :
211 0 : void AsdmStMan::resync (uInt)
212 0 : {}
213 :
214 0 : void AsdmStMan::reopenRW()
215 0 : {}
216 :
217 0 : void AsdmStMan::deleteManager()
218 : {
219 0 : closeBDF();
220 : // Remove index file.
221 0 : DOos::remove (fileName()+"asdmindex", false, false);
222 0 : }
223 :
224 0 : void AsdmStMan::closeBDF()
225 : {
226 0 : if (itsOpenBDF >= 0) {
227 0 : delete itsBDF;
228 0 : itsBDF = 0;
229 0 : FiledesIO::close (itsFD);
230 0 : itsOpenBDF = -1;
231 : }
232 0 : }
233 :
234 0 : void AsdmStMan::init()
235 : {
236 : // Open index file and check version.
237 0 : AipsIO aio(fileName() + "asdmindex");
238 0 : itsVersion = aio.getstart ("AsdmStMan");
239 0 : if (itsVersion > 1) {
240 0 : throw DataManError ("AsdmStMan can only handle up to version 1");
241 : }
242 : // Read the index info.
243 : Bool asBigEndian;
244 0 : aio >> asBigEndian >> itsBDFNames;
245 0 : aio.get (itsIndex);
246 0 : aio.getend();
247 0 : itsDoSwap = (asBigEndian != HostInfo::bigEndian());
248 : // Fill the vector with rows from the index.
249 0 : itsIndexRows.resize (itsIndex.size());
250 0 : for (uInt i=0; i<itsIndex.size(); ++i) {
251 0 : itsIndexRows[i] = itsIndex[i].row;
252 : }
253 : // Fill the specification record (only used for reporting purposes).
254 0 : itsSpec.define ("version", itsVersion);
255 0 : itsSpec.define ("bigEndian", asBigEndian);
256 0 : itsSpec.define ("BDFs", Vector<String>(itsBDFNames.begin(),itsBDFNames.end()));
257 : // Set to nothing read yet.
258 0 : itsStartRow = -1;
259 0 : itsEndRow = -1;
260 0 : itsIndexEntry = 0;
261 :
262 0 : if(itsIndex.size()>0){
263 : // test if the referenced ASDM seems to be present
264 : try{
265 0 : itsFD = FiledesIO::open (itsBDFNames[0].c_str(), false);
266 0 : itsBDF = new FiledesIO (itsFD, itsBDFNames[0]);
267 0 : itsOpenBDF = 0;
268 0 : closeBDF();
269 : }
270 0 : catch (AipsError x){
271 0 : LogIO os(LogOrigin("AsdmStMan", "init()"));
272 : os << LogIO::WARN
273 : << "An error occured when accessing the ASDM referenced by this table:" << endl
274 : << x.what() << endl
275 0 : << "This means you will not be able to access the columns" << endl;
276 0 : for(uInt i=0; i<itsColumns.size(); i++){
277 0 : os << itsColumns[i]->columnName() << endl;
278 : }
279 : os << "You may have (re)moved the ASDM from its import location." << endl
280 : << "If you want to access the above columns, please restore the ASDM\nor correct the reference to it."
281 0 : << LogIO::POST;
282 : }
283 : }
284 :
285 0 : }
286 :
287 0 : uInt AsdmStMan::searchIndex (Int64 rownr)
288 : {
289 : // Search index entry matching this rownr.
290 : // If not exactly found, it is previous one.
291 : /// vector<uInt>::const_iterator low = std::lower_bound (itsIndexRows.begin(),
292 : /// itsIndexRows.end(),
293 : /// rownr);
294 : ///return low - itsIndexRows.begin();
295 : Bool found;
296 0 : uInt v = binarySearchBrackets (found, itsIndexRows, rownr,
297 0 : itsIndexRows.size());
298 0 : if (!found){
299 0 : if(v>0){
300 0 : v--;
301 : }
302 : else{
303 0 : throw DataManError ("AsdmStMan: index empty.");
304 : }
305 : }
306 :
307 0 : return v;
308 : }
309 :
310 0 : const AsdmIndex& AsdmStMan::findIndex (Int64 rownr)
311 : {
312 : // Only get if not current.
313 0 : if (rownr < itsStartRow || rownr >= itsEndRow) {
314 0 : itsIndexEntry = searchIndex (rownr);
315 0 : const AsdmIndex& ix = itsIndex[itsIndexEntry];
316 : // Resize to indicate not read yet.
317 : // Note that reserved size stays the same, so no extra mallocs needed.
318 : // itsData.resize (0); commented out by Michel Caillat 03 Dec 2012
319 0 : itsStartRow = ix.row;
320 0 : itsEndRow = ix.row + ix.nrow();
321 : }
322 0 : return itsIndex[itsIndexEntry];
323 : }
324 :
325 0 : void CASA_ATTR_VECTORIZE AsdmStMan::getShort (const AsdmIndex& ix, Complex* buf, uInt bl, uInt spw)
326 : {
327 : // Get pointer to the data in the block.
328 0 : Short* data = (reinterpret_cast<Short*>(&itsData[0]));
329 0 : data = data + 2 * ix.blockOffset + 2 * bl * ix.stepBl ; // Michel Caillat - 21 Nov 2012
330 :
331 : //cout << "getShort works at this adress : " << (unsigned long long int) data << endl;
332 :
333 0 : if (itsDoSwap) {
334 : Short real,imag;
335 0 : for (uInt j=0; j<ix.nChan; ++j) {
336 0 : for (uInt i=0; i<ix.nPol; ++i) {
337 0 : CanonicalConversion::reverse2 (&real, data);
338 0 : CanonicalConversion::reverse2 (&imag, data+1);
339 0 : *buf++ = Complex(real/ix.scaleFactors[spw],
340 0 : imag/ix.scaleFactors[spw]);
341 0 : data += 2;
342 : }
343 : }
344 : } else {
345 : // GCC < 5 fails vectorizing Complex so use floats (same layout c++11 26.4)
346 0 : Float * fbuf = reinterpret_cast<Float*>(buf);
347 0 : for (uInt j=0; j<ix.nChan * ix.nPol; ++j) {
348 0 : *fbuf++ = data[0]/ix.scaleFactors[spw];
349 0 : *fbuf++ = data[1]/ix.scaleFactors[spw];
350 0 : data += 2;
351 : }
352 : }
353 0 : }
354 :
355 0 : void AsdmStMan::getInt (const AsdmIndex& ix, Complex* buf, uInt bl, uInt spw)
356 : {
357 : // Get pointer to the data in the block.
358 0 : Int* data = (reinterpret_cast<Int*>(&(itsData[0])));
359 0 : data = data + 2 * ix.blockOffset + 2 * bl * ix.stepBl; // 21 Nov 2012 - Michel Caillat
360 0 : if (itsDoSwap) {
361 : Int real,imag;
362 0 : for (uInt j=0; j<ix.nChan; ++j) {
363 0 : for (uInt i=0; i<ix.nPol; ++i) {
364 0 : CanonicalConversion::reverse4 (&real, data);
365 0 : CanonicalConversion::reverse4 (&imag, data+1);
366 0 : *buf++ = Complex(real/ix.scaleFactors[spw],
367 0 : imag/ix.scaleFactors[spw]);
368 0 : data += 2;
369 : }
370 : }
371 : } else {
372 0 : for (uInt j=0; j<ix.nChan; ++j) {
373 0 : for (uInt i=0; i<ix.nPol; ++i) {
374 0 : *buf++ = Complex(data[0]/ix.scaleFactors[spw],
375 0 : data[1]/ix.scaleFactors[spw]);
376 0 : data += 2;
377 : }
378 : }
379 : }
380 0 : }
381 :
382 0 : void AsdmStMan::getFloat (const AsdmIndex& ix, Complex* buf, uInt bl, uInt spw)
383 : {
384 : // Get pointer to the data in the block.
385 0 : Float* data = (reinterpret_cast<Float*>(&(itsData[0])));
386 0 : data = data + 2 * ix.blockOffset + 2 * bl * ix.stepBl; // 21 Nov 2012 Michel Caillat
387 0 : if (itsDoSwap) {
388 : Float real,imag;
389 0 : for (uInt j=0; j<ix.nChan; ++j) {
390 0 : for (uInt i=0; i<ix.nPol; ++i) {
391 0 : CanonicalConversion::reverse4 (&real, data);
392 0 : CanonicalConversion::reverse4 (&imag, data+1);
393 0 : *buf++ = Complex(real/ix.scaleFactors[spw],
394 0 : imag/ix.scaleFactors[spw]);
395 0 : data += 2;
396 : }
397 : }
398 : } else {
399 0 : for (uInt j=0; j<ix.nChan; ++j) {
400 0 : for (uInt i=0; i<ix.nPol; ++i) {
401 0 : *buf++ = Complex(data[0]/ix.scaleFactors[spw],
402 0 : data[1]/ix.scaleFactors[spw]);
403 0 : data += 2;
404 : }
405 : }
406 : }
407 0 : }
408 :
409 0 : void AsdmStMan::getAuto (const AsdmIndex& ix, Complex* buf, uInt bl)
410 : {
411 : // Get pointer to the data in the block.
412 0 : Float* data = (reinterpret_cast<Float*>(&(itsData[0])));
413 0 : data = data + ix.blockOffset + bl * ix.stepBl; // 21 Nov 2012 . Michel Caillat
414 :
415 : // The autocorr can have 1, 2, 3 or 4 npol.
416 : // 1 and 2 are XX and/or YY which are real numbers.
417 : // 3 are all 4 pols with XY a complex number and YX=conj(XY).
418 : // 4 are all 4 pols with XX,YY real and XY,YX complex.
419 0 : if (itsDoSwap) {
420 : Float valr, vali;
421 0 : if (ix.nPol == 3) {
422 0 : for (uInt i=0; i<ix.nChan; ++i) {
423 0 : CanonicalConversion::reverse4 (&valr, data++);
424 0 : *buf++ = Complex(valr); // XX
425 0 : CanonicalConversion::reverse4 (&valr, data++);
426 0 : CanonicalConversion::reverse4 (&vali, data++);
427 0 : *buf++ = Complex(valr, vali); // XY
428 0 : *buf++ = Complex(valr, -vali); // YX
429 0 : CanonicalConversion::reverse4 (&valr, data++);
430 0 : *buf++ = Complex(valr); // YY
431 : }
432 0 : } else if (ix.nPol == 4) {
433 0 : for (uInt i=0; i<ix.nChan; ++i) {
434 0 : CanonicalConversion::reverse4 (&valr, data++);
435 0 : *buf++ = Complex(valr); // XX
436 0 : CanonicalConversion::reverse4 (&valr, data++);
437 0 : CanonicalConversion::reverse4 (&vali, data++);
438 0 : *buf++ = Complex(valr, vali); // XY
439 0 : CanonicalConversion::reverse4 (&valr, data++);
440 0 : CanonicalConversion::reverse4 (&vali, data++);
441 0 : *buf++ = Complex(valr, vali); // YX
442 0 : CanonicalConversion::reverse4 (&valr, data++);
443 0 : *buf++ = Complex(valr); // YY
444 : }
445 : } else {
446 0 : for (uInt i=0; i<ix.nChan * ix.nPol; ++i) {
447 0 : CanonicalConversion::reverse4 (&valr, data++);
448 0 : *buf++ = Complex(valr);
449 : }
450 : }
451 : } else {
452 : // No byte swap needed.
453 0 : if (ix.nPol == 3) {
454 0 : for (uInt i=0; i<ix.nChan; ++i) {
455 0 : *buf++ = Complex(data[0]);
456 0 : *buf++ = Complex(data[1], data[2]);
457 0 : *buf++ = Complex(data[1], -data[2]);
458 0 : *buf++ = Complex(data[3]);
459 0 : data += 4;
460 : }
461 0 : } else if (ix.nPol == 4) {
462 0 : for (uInt i=0; i<ix.nChan; ++i) {
463 0 : *buf++ = Complex(data[0]);
464 0 : *buf++ = Complex(data[1], data[2]);
465 0 : *buf++ = Complex(data[3], data[4]);
466 0 : *buf++ = Complex(data[5]);
467 0 : data += 6;
468 : }
469 : } else {
470 0 : for (uInt i=0; i<ix.nChan * ix.nPol; ++i) {
471 0 : *buf++ = Complex(data[i]);
472 : }
473 : }
474 : }
475 0 : }
476 :
477 0 : void AsdmStMan::getAuto (const AsdmIndex& ix, Float* buf, uInt bl)
478 : {
479 : // Get pointer to the data in the block.
480 0 : Float* data = (reinterpret_cast<Float*>(&(itsData[0])));
481 0 : data = data + ix.blockOffset + bl * ix.stepBl;
482 :
483 : // This can only apply to the FLOAT_DATA column, and in that
484 : // case nPol can only be 1 or 2, anything else is an error.
485 : // No complex values should be possible here.
486 :
487 0 : if (ix.nPol > 2) {
488 0 : throw DataManError ("AsdmStMan: more than 2 polarizations found for FLOAT_DATA, can not accomodate.");
489 : }
490 :
491 0 : if (itsDoSwap) {
492 : Float valr;
493 0 : for (uInt i=0; i<ix.nChan * ix.nPol; ++i) {
494 0 : CanonicalConversion::reverse4 (&valr, data++);
495 0 : *buf++ = valr;
496 : }
497 : } else {
498 : // No byte swap needed.
499 0 : for (uInt i=0; i<ix.nChan * ix.nPol; ++i) {
500 0 : *buf++ = data[i];
501 : }
502 : }
503 0 : }
504 :
505 0 : IPosition AsdmStMan::getShape (uInt rownr)
506 : {
507 : // Here determine the shape from the rownr.
508 : /// For now fill in some shape.
509 0 : uInt inx = searchIndex (rownr);
510 0 : const AsdmIndex& ix = itsIndex[inx];
511 0 : if (ix.dataType == 10 && ix.nPol == 3) {
512 : // 3 autocorrs means 4 (YX = conj(XY));
513 0 : return IPosition(2, 4, ix.nChan);
514 : }
515 0 : return IPosition(2, ix.nPol, ix.nChan);
516 : }
517 :
518 0 : void AsdmStMan::getData (uInt rownr, Complex* buf)
519 : {
520 0 : const AsdmIndex& ix = findIndex (rownr);
521 :
522 : // If we are in front of Correlator data, do we have to update the baseline numbers tranposition ?
523 0 : if (ix.dataType != 10)
524 0 : if (ix.nBl != itsNBl)
525 0 : setTransposeBLNum(ix.nBl);
526 :
527 : // Open the BDF if needed.
528 0 : if (Int(ix.fileNr) != itsOpenBDF) {
529 0 : closeBDF();
530 0 : itsFD = FiledesIO::open (itsBDFNames[ix.fileNr].c_str(), false);
531 0 : itsBDF = new FiledesIO (itsFD, itsBDFNames[ix.fileNr]);
532 0 : itsOpenBDF = ix.fileNr;
533 0 : itsFileOffset = ix.fileOffset;
534 0 : itsData.resize(0);
535 : }
536 :
537 : // Or we did not have open a new BDF but are aiming at a new position in the same BDF
538 0 : else if ( itsFileOffset != ix.fileOffset ) {
539 0 : itsFileOffset = ix.fileOffset;
540 0 : itsData.resize(0);
541 : }
542 :
543 : // Read data block if not done yet, i.e. if and only if we are in a new BDF or in the same
544 : // one but at a new position (fileOffset).
545 : //
546 0 : if (itsData.empty()) {
547 0 : itsData.resize (ix.dataSize());
548 0 : itsBDF->seek (ix.fileOffset);
549 0 : itsBDF->read (itsData.size(), &(itsData[0]));
550 : }
551 : // Determine the spw and baseline from the row.
552 : // The rows are stored in order of spw,baseline.
553 0 : uInt spw = ix.iSpw ; // 19 Feb 2014 : Michel Caillat changed this assignement;
554 :
555 : //
556 : // Attention !!! If we are in front of Correlator data we must apply the transposition function
557 : uInt bl;
558 : //cerr << "shape0 "<< itsTransposeBLNum_v.size() << endl;
559 0 : if (ix.dataType != 10 )
560 0 : bl = itsTransposeBLNum_v[rownr - ix.row];
561 : else
562 0 : bl = (rownr - ix.row);
563 :
564 0 : switch (ix.dataType) {
565 0 : case 0:
566 0 : getShort (ix, buf, bl, spw);
567 0 : break;
568 0 : case 1:
569 0 : getInt (ix, buf, bl, spw);
570 0 : break;
571 0 : case 3:
572 0 : getFloat (ix, buf, bl, spw);
573 0 : break;
574 0 : case 10:
575 0 : getAuto (ix, buf, bl);
576 0 : break;
577 0 : default:
578 0 : throw DataManError ("AsdmStMan: Unknown data type");
579 : }
580 0 : }
581 :
582 0 : void AsdmStMan::getData (uInt rownr, Float* buf)
583 : {
584 0 : const AsdmIndex& ix = findIndex (rownr);
585 :
586 : // float data can only be fetched for type 10
587 0 : if (ix.dataType != 10) {
588 0 : throw DataManError ("AsdmStMan: illegal data type for FLOAT_DATA column");
589 : }
590 :
591 : // Open the BDF if needed.
592 0 : if (Int(ix.fileNr) != itsOpenBDF) {
593 0 : closeBDF();
594 0 : itsFD = FiledesIO::open (itsBDFNames[ix.fileNr].c_str(), false);
595 0 : itsBDF = new FiledesIO (itsFD, itsBDFNames[ix.fileNr]);
596 0 : itsOpenBDF = ix.fileNr;
597 0 : itsFileOffset = ix.fileOffset;
598 0 : itsData.resize(0);
599 : }
600 :
601 : // Or we did not have open a new BDF but are aiming at a new position in the same BDF
602 0 : else if ( itsFileOffset != ix.fileOffset ) {
603 0 : itsFileOffset = ix.fileOffset;
604 0 : itsData.resize(0);
605 : }
606 :
607 : // Read data block if not done yet, i.e. if and only if we are in a new BDF or in the same
608 : // one but at a new position (fileOffset).
609 : //
610 0 : if (itsData.empty()) {
611 0 : itsData.resize (ix.dataSize());
612 0 : itsBDF->seek (ix.fileOffset);
613 0 : itsBDF->read (itsData.size(), &(itsData[0]));
614 : }
615 : // Determine the spw and baseline from the row.
616 : // The rows are stored in order of spw,baseline.
617 : // getAuto appears to not depend on spw. R.Garwood.
618 :
619 0 : uInt bl = (rownr - ix.row);
620 0 : getAuto (ix, buf, bl);
621 0 : }
622 :
623 0 : void AsdmStMan::getBDFNames(Block<String>& bDFNames)
624 : {
625 0 : bDFNames = itsBDFNames;
626 0 : return;
627 : }
628 :
629 0 : Bool AsdmStMan::setBDFNames(Block<String>& bDFNames)
630 : {
631 0 : if(bDFNames.size() == itsBDFNames.size()){
632 0 : itsBDFNames = bDFNames;
633 0 : return true;
634 : }
635 : else{
636 0 : return false;
637 : }
638 : }
639 :
640 0 : void AsdmStMan::writeIndex(){
641 :
642 0 : AipsIO aio(fileName() + "asdmindex", ByteIO::New);
643 0 : aio.putstart("AsdmStMan", itsVersion);
644 0 : aio << HostInfo::bigEndian() << itsBDFNames;
645 0 : aio.put(itsIndex);
646 0 : aio.putend();
647 :
648 0 : }
649 :
650 0 : void AsdmStMan::setTransposeBLNum(uInt nBl) {
651 :
652 0 : itsTransposeBLNum_v.clear();
653 :
654 : // Deduce the number of antennas from the number of baselines
655 0 : uInt numAnt = (uInt) (floor((1 + sqrt(1 + 8*nBl)) / 2 + 0.5));
656 :
657 : //cerr << "AsdmStMan::setTransposeBLNum, numAnt=" << numAnt << endl;
658 :
659 0 : uInt blNum = 0;
660 0 : map<uInt, map<uInt, uInt> > _mm;
661 0 : for (uInt i2 = 1; i2 < numAnt; i2++) {
662 0 : map<uInt, uInt> _m;
663 0 : for (uInt i1 = 0; i1 < i2; i1++) {
664 0 : _m[i1] = blNum;
665 0 : blNum++;
666 : }
667 0 : _mm[i2] = _m;
668 : }
669 :
670 0 : for (uInt i1 = 0; i1 < numAnt; i1++)
671 0 : for (uInt i2 = i1+1; i2 < numAnt; i2++)
672 0 : itsTransposeBLNum_v.push_back(_mm[i2][i1]);
673 :
674 0 : itsNBl = nBl;
675 0 : }
676 :
677 : } //# end namespace
|