Line data Source code
1 : //# VLAADA.cc:
2 : //# Copyright (C) 1999,2000,2001
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$
27 :
28 : #include <iomanip>
29 : #include <nrao/VLA/VLAADA.h>
30 : #include <casacore/casa/Utilities/Assert.h>
31 : #include <casacore/casa/Exceptions/Error.h>
32 : #include <casacore/casa/BasicSL/String.h>
33 : #include <casacore/casa/Quanta/QC.h>
34 : #include <casacore/casa/Quanta/Unit.h>
35 : #include <casacore/casa/Arrays/Vector.h>
36 : #include <casacore/casa/Arrays/ArrayLogical.h>
37 : #include <casacore/casa/Logging/LogIO.h>
38 : #include <casacore/casa/Logging/LogOrigin.h>
39 : #include <casacore/casa/BasicMath/Math.h>
40 :
41 : Double ns2m;
42 :
43 0 : VLAADA::VLAADA()
44 0 : :itsRecord(),
45 0 : itsOffset(0)
46 : {
47 0 : ns2m = QC::c( ).getValue("m/ns");
48 : // cerr << QC::c( ) << endl;
49 : // cerr << C::c << endl;
50 0 : DebugAssert(ok(), AipsError);
51 0 : }
52 :
53 0 : VLAADA::VLAADA(ByteSource& record, uInt offset)
54 0 : :itsRecord(record),
55 0 : itsOffset(offset)
56 : {
57 0 : DebugAssert(ok(), AipsError);
58 0 : }
59 :
60 0 : VLAADA::VLAADA(const VLAADA& other)
61 0 : :itsRecord(other.itsRecord),
62 0 : itsOffset(other.itsOffset)
63 : {
64 0 : DebugAssert(ok(), AipsError);
65 0 : }
66 :
67 0 : VLAADA::~VLAADA()
68 : {
69 0 : DebugAssert(ok(), AipsError);
70 0 : }
71 :
72 0 : VLAADA& VLAADA::operator=(const VLAADA& other) {
73 0 : if (this != &other) {
74 0 : itsRecord = other.itsRecord;
75 0 : itsOffset = other.itsOffset;
76 : }
77 0 : DebugAssert(ok(), AipsError);
78 0 : return *this;
79 : }
80 :
81 0 : void VLAADA::attach(ByteSource& record, uInt offset) {
82 0 : itsRecord = record;
83 0 : itsOffset = offset;
84 0 : DebugAssert(ok(), AipsError);
85 0 : }
86 :
87 0 : uInt VLAADA::antId() const {
88 0 : DebugAssert(ok(), AipsError);
89 0 : const Int64 where = itsOffset + 2*(0);
90 0 : itsRecord.seek(where);
91 : uChar id;
92 0 : itsRecord >> id;
93 0 : return id;
94 : }
95 :
96 0 : String VLAADA::antName(Bool newStyle) const {
97 0 : DebugAssert(ok(), AipsError);
98 0 : String antid=String::toString(antId());
99 0 : if(antId() < 10)
100 0 : antid=String("0")+antid;
101 0 : if(newStyle){
102 0 : Int64 where = itsOffset + 2*(1);
103 0 : itsRecord.seek(where);
104 :
105 : Short bits;
106 0 : itsRecord >> bits;
107 : // Bit 9 == fiber == evla or pie town (0x0040 = 0000.0000.0100.0000)
108 0 : Bool fiber = (bits & 0x0040);
109 :
110 0 : if (fiber)
111 0 : if (antId()==29)
112 : // pie town is just an old VLA antenna in this context
113 0 : antid=String("VA")+antid;
114 : else
115 : // evla
116 0 : antid=String("EA")+antid;
117 :
118 : else
119 0 : antid=String("VA")+antid;
120 :
121 : }
122 0 : return antid;
123 0 : }
124 :
125 0 : Float VLAADA::frontEndTemp(VLAEnum::IF which) const {
126 0 : DebugAssert(ok(), AipsError);
127 0 : Int64 where = itsOffset+2*(48);
128 0 : switch (which) {
129 0 : case VLAEnum::IFA:
130 0 : break;
131 0 : case VLAEnum::IFB:
132 0 : where += 4;
133 0 : break;
134 0 : case VLAEnum::IFC:
135 0 : where += 8;
136 0 : break;
137 0 : case VLAEnum::IFD:
138 0 : where += 12;
139 0 : break;
140 0 : default:
141 0 : throw(AipsError("VLAADA::Unknown IF"));
142 : }
143 0 : itsRecord.seek(where);
144 : Float temp;
145 0 : itsRecord >> temp;
146 0 : return temp;
147 : }
148 :
149 0 : Double VLAADA::u() const {
150 0 : DebugAssert(ok(), AipsError);
151 0 : const Int64 where = itsOffset+2*(28);
152 0 : itsRecord.seek(where);
153 : Double u;
154 0 : itsRecord >> u;
155 : // cerr << u << " " << ns2m << " ";
156 0 : return u*ns2m;
157 : }
158 :
159 0 : Double VLAADA::v() const {
160 0 : DebugAssert(ok(), AipsError);
161 0 : const Int64 where = itsOffset+2*(30);
162 0 : itsRecord.seek(where);
163 : Double v;
164 0 : itsRecord >> v;
165 0 : return v*ns2m;
166 : }
167 0 : Double VLAADA::w() const {
168 0 : DebugAssert(ok(), AipsError);
169 0 : const Int64 where = itsOffset+2*(32);
170 0 : itsRecord.seek(where);
171 : Double w;
172 0 : itsRecord >> w;
173 0 : return w*ns2m;
174 : }
175 :
176 0 : Double VLAADA::bx() const {
177 0 : DebugAssert(ok(), AipsError);
178 0 : const Int64 where = itsOffset+2*(34);
179 0 : itsRecord.seek(where);
180 : Double bx;
181 0 : itsRecord >> bx;
182 0 : return bx*ns2m;
183 : }
184 :
185 0 : Double VLAADA::by() const {
186 0 : DebugAssert(ok(), AipsError);
187 0 : const Int64 where = itsOffset+2*(38);
188 0 : itsRecord.seek(where);
189 : Double by;
190 0 : itsRecord >> by;
191 0 : return by*ns2m;
192 : }
193 :
194 0 : Double VLAADA::bz() const {
195 0 : DebugAssert(ok(), AipsError);
196 0 : const Int64 where = itsOffset+2*(42);
197 0 : itsRecord.seek(where);
198 : Double bz;
199 0 : itsRecord >> bz;
200 0 : return bz*ns2m;
201 : }
202 :
203 0 : Vector<Double> VLAADA::pos() const {
204 0 : DebugAssert(ok(), AipsError);
205 0 : Vector<Double> pos(3);
206 0 : pos(0) = bx();
207 0 : pos(1) = by();
208 0 : pos(2) = bz();
209 0 : return pos;
210 0 : }
211 :
212 0 : String VLAADA::padName() const {
213 0 : DebugAssert(ok(), AipsError);
214 0 : const Double x = bx();
215 0 : const uInt nPad = 74;
216 0 : static Block<Double> padX(nPad);
217 0 : static Block<String> padName(nPad);
218 : static Bool init = false;
219 0 : if (!init) { // These are the nominal bx positions of the pads. This table
220 : // was extracted from the AIPS task FILLM
221 0 : padName[0] = "W1"; padX[0] = 77. ;
222 0 : padName[1] = "W2"; padX[1] = 49. ;
223 0 : padName[2] = "W3"; padX[2] = 96. ;
224 0 : padName[3] = "W4"; padX[3] = 156. ;
225 0 : padName[4] = "W5"; padX[4] = 229. ;
226 0 : padName[5] = "W6"; padX[5] = 312. ;
227 0 : padName[6] = "W7"; padX[6] = 406. ;
228 0 : padName[7] = "W8"; padX[7] = 510. ;
229 0 : padName[8] = "W9"; padX[8] = 623. ;
230 0 : padName[9] = "W10"; padX[9] = 747. ;
231 0 : padName[10] = "W12"; padX[10] = 1021. ;
232 0 : padName[11] = "W14"; padX[11] = 1328. ;
233 0 : padName[12] = "W16"; padX[12] = 1667. ;
234 0 : padName[13] = "W18"; padX[13] = 2041. ;
235 0 : padName[14] = "W20"; padX[14] = 2446. ;
236 0 : padName[15] = "W24"; padX[15] = 3354. ;
237 0 : padName[16] = "W28"; padX[16] = 4391. ;
238 0 : padName[17] = "W32"; padX[17] = 5470. ;
239 0 : padName[18] = "W36"; padX[18] = 6671. ;
240 0 : padName[19] = "W40"; padX[19] = 7988. ;
241 0 : padName[20] = "W48"; padX[20] = 10926.;
242 0 : padName[21] = "W56"; padX[21] = 14206.;
243 0 : padName[22] = "W64"; padX[22] = 17843.;
244 0 : padName[23] = "W72"; padX[23] = 21803.;
245 0 : padName[24] = "E1"; padX[24] = 151. ;
246 0 : padName[25] = "E2"; padX[25] = 38. ;
247 0 : padName[26] = "E3"; padX[26] = 73. ;
248 0 : padName[27] = "E4"; padX[27] = 119. ;
249 0 : padName[28] = "E5"; padX[28] = 173. ;
250 0 : padName[29] = "E6"; padX[29] = 236. ;
251 0 : padName[30] = "E7"; padX[30] = 305. ;
252 0 : padName[31] = "E8"; padX[31] = 382. ;
253 0 : padName[32] = "E9"; padX[32] = 466. ;
254 0 : padName[33] = "E10"; padX[33] = 558. ;
255 0 : padName[34] = "E12"; padX[34] = 765. ;
256 0 : padName[35] = "E14"; padX[35] = 1000. ;
257 0 : padName[36] = "E16"; padX[36] = 1257. ;
258 0 : padName[37] = "E18"; padX[37] = 1548. ;
259 0 : padName[38] = "E20"; padX[38] = 1868. ;
260 0 : padName[39] = "E24"; padX[39] = 2552. ;
261 0 : padName[40] = "E28"; padX[40] = 3331. ;
262 0 : padName[41] = "E32"; padX[41] = 4180. ;
263 0 : padName[42] = "E36"; padX[42] = 5119. ;
264 0 : padName[43] = "E40"; padX[43] = 6127. ;
265 0 : padName[44] = "E48"; padX[44] = 8325. ;
266 0 : padName[45] = "E56"; padX[45] = 10814.;
267 0 : padName[46] = "E64"; padX[46] = 13620.;
268 0 : padName[47] = "E72"; padX[47] = 16204.;
269 0 : padName[48] = "N1"; padX[48] = 2.5 ;
270 0 : padName[49] = "N2"; padX[49] = -100. ;
271 0 : padName[50] = "N3"; padX[50] = -175. ;
272 0 : padName[51] = "N4"; padX[51] = -250. ;
273 0 : padName[52] = "N5"; padX[52] = -362. ;
274 0 : padName[53] = "N6"; padX[53] = -495. ;
275 0 : padName[54] = "N7"; padX[54] = -646. ;
276 0 : padName[55] = "N8"; padX[55] = -813. ;
277 0 : padName[56] = "N9"; padX[56] = -995. ;
278 0 : padName[57] = "N10"; padX[57] = -1193. ;
279 0 : padName[58] = "N12"; padX[58] = -1632. ;
280 0 : padName[59] = "N14"; padX[59] = -2126. ;
281 0 : padName[60] = "N16"; padX[60] = -2673. ;
282 0 : padName[61] = "N18"; padX[61] = -3271. ;
283 0 : padName[62] = "N20"; padX[62] = -3917. ;
284 0 : padName[63] = "N24"; padX[63] = -5539. ;
285 0 : padName[64] = "N28"; padX[64] = -6976. ;
286 0 : padName[65] = "N32"; padX[65] = -8770. ;
287 0 : padName[66] = "N36"; padX[66] = -10733.;
288 0 : padName[67] = "N40"; padX[67] = -12858.;
289 0 : padName[68] = "N48"; padX[68] = -17583.;
290 0 : padName[69] = "N56"; padX[69] = -22919.;
291 0 : padName[70] = "N64"; padX[70] = -28827.;
292 0 : padName[71] = "N72"; padX[71] = -35283.;
293 0 : padName[72] = "MPD"; padX[72] = 1148.;
294 0 : padName[73] = "VPT"; padX[73] = -46201.; // Pie Town
295 0 : for (uInt i = 0; i < nPad; i++) {
296 0 : padX[i] *= ns2m;
297 : }
298 0 : init = true;
299 : }
300 0 : String name;
301 0 : uInt i = 0;
302 0 : String arrname=arrayName();
303 0 : while (name.length() == 0 && i < nPad) {
304 0 : if (nearAbs(x, padX[i], 0.5)) { // This is nearly the largest slop
305 : // allowable as W1 is at 77*(0.3m/ns) and E3 is at 73.*(0.3m/ns)
306 :
307 0 : name = arrayName();
308 0 : name += padName[i];
309 : }
310 0 : i++;
311 : }
312 0 : if (name.length() == 0) {
313 0 : name = "UNKNOWN";
314 : }
315 0 : return name;
316 0 : }
317 :
318 0 : uInt VLAADA::ifStatus(VLAEnum::IF which) const {
319 0 : DebugAssert(ok(), AipsError);
320 0 : Int64 where = itsOffset+2*(3);
321 0 : if (which == VLAEnum::IFC || which == VLAEnum::IFD) {
322 0 : where++;
323 : }
324 0 : itsRecord.seek(where);
325 : uChar status;
326 0 : itsRecord >> status;
327 0 : if (which == VLAEnum::IFA || which == VLAEnum::IFC) {
328 0 : status >>= 4;
329 : }
330 0 : status &= 0x0f;
331 0 : return status;
332 : }
333 :
334 0 : Float VLAADA::nominalSensitivity(VLAEnum::IF which) const {
335 0 : DebugAssert(ok(), AipsError);
336 0 : Int64 where = itsOffset+2*(4);
337 0 : switch (which) {
338 0 : case VLAEnum::IFA:
339 0 : break;
340 0 : case VLAEnum::IFB:
341 0 : where += 4;
342 0 : break;
343 0 : case VLAEnum::IFC:
344 0 : where += 8;
345 0 : break;
346 0 : case VLAEnum::IFD:
347 0 : where += 12;
348 0 : break;
349 0 : default:
350 0 : throw(AipsError("VLAADA::Unknown IF"));
351 : }
352 0 : itsRecord.seek(where);
353 : Float sensitivity;
354 0 : itsRecord >> sensitivity;
355 0 : return sensitivity;
356 : }
357 :
358 0 : Stokes::StokesTypes VLAADA::ifPol(VLAEnum::IF which) const {
359 0 : DebugAssert(ok(), AipsError);
360 0 : Int64 where = itsOffset+2*(1);
361 0 : itsRecord.seek(where);
362 : uChar bits;
363 0 : itsRecord >> bits;
364 0 : Bool swap = bits & 0x80;
365 0 : if (which == VLAEnum::IFA || which == VLAEnum::IFB) {
366 0 : if (swap) {
367 0 : return Stokes::LCircular;
368 : } else {
369 0 : return Stokes::RCircular;
370 : }
371 : } else {
372 0 : if (swap) {
373 0 : return Stokes::RCircular;
374 : } else {
375 0 : return Stokes::LCircular;
376 : }
377 : }
378 : }
379 :
380 : // Has nominal sensitivity been applied to amplitudes?
381 0 : Bool VLAADA::nomSensApplied(VLAEnum::IF which,const uInt rev) const {
382 0 : DebugAssert(ok(), AipsError);
383 :
384 : // Prior (exclusive) to rev 25, nominal sensitivity ALWAYS applied
385 0 : if (rev < 25) return true;
386 :
387 : // Note that VLA Archive Data Format (May 1, 1996) doc has typo
388 : // in section 2.3. The ADA's IF control bits are in words 64-67
389 : // (not 65-68).
390 :
391 0 : Int64 where = itsOffset + 2*(64+which);
392 0 : itsRecord.seek(where);
393 :
394 : Short bits;
395 0 : itsRecord >> bits;
396 : // Bit 2 == Tsys Corr On (0x2000 = 0010.0000.0000.0000)
397 0 : return (bits & 0x2000);
398 :
399 : }
400 :
401 0 : String VLAADA::arrayName() const {
402 :
403 : // For prepending to padName
404 :
405 0 : Int64 where = itsOffset + 2*(1);
406 0 : itsRecord.seek(where);
407 :
408 : Short bits;
409 0 : itsRecord >> bits;
410 : // Bit 9 == fiber (0x0040 = 0100.0000.0100.0000)
411 0 : Bool fiber = (bits & 0x0040);
412 :
413 : // VLBA and EVLA are connected by fiber
414 0 : if (fiber) {
415 : // It is a VLBA antenna (e.g. PT)
416 0 : if (antId()>28)
417 : // return String("VLBA:");
418 0 : return String("VLA:_");
419 : else
420 : // evla
421 0 : return String("EVLA:");
422 : }
423 : // Otherwise this is just the old VLA
424 : // (the underscore is so string length same as above, for AIPS)
425 0 : return String("VLA:_");
426 :
427 : }
428 :
429 :
430 0 : Bool VLAADA::ok() const {
431 : // The LogIO class is only constructed if an Error is detected for
432 : // performance reasons. Both function static and file static variables
433 : // where considered and rejected for this purpose.
434 :
435 : // This function fails (dumps core) if the itsRecord data member was
436 : // constructed using the default constructor. I need to add a isNull
437 : // function to the BaseSinkSource class to overcome this
438 0 : if (!itsRecord.isNull()) {
439 0 : if (!itsRecord.isReadable()) {
440 0 : LogIO logErr(LogOrigin("VLAADA", "ok()"));
441 : logErr << LogIO::SEVERE
442 : << "The VLA logical record is not readable"
443 0 : << LogIO::POST;
444 0 : return false;
445 0 : }
446 0 : if (!itsRecord.isSeekable()) {
447 0 : LogIO logErr(LogOrigin("VLAADA", "ok()"));
448 : logErr << LogIO::SEVERE
449 : << "The VLA logical record is not seekable"
450 0 : << LogIO::POST;
451 0 : return false;
452 0 : }
453 0 : if (itsOffset == 0) {
454 0 : LogIO logErr(LogOrigin("VLAADA", "ok()"));
455 : logErr << LogIO::SEVERE
456 : << "The antenna data area cannot have a zero offset"
457 0 : << LogIO::POST;
458 0 : return false;
459 0 : }
460 : }
461 0 : return true;
462 : }
463 :
464 : // Local Variables:
465 : // compile-command: "gmake VLAADA"
466 : // End:
|