source: tags/asap2.3.0/src/STFiller.cpp@ 1997

Last change on this file since 1997 was 1504, checked in by Malte Marquarding, 16 years ago

Fix for ticket #151: added facilities to help with on/off scan identification/setting

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.9 KB
Line 
1//
2// C++ Implementation: STFiller
3//
4// Description:
5//
6//
7// Author: Malte Marquarding <asap@atnf.csiro.au>, (C) 2006-2007
8//
9// Copyright: See COPYING file that comes with this distribution
10//
11//
12#include <casa/iostream.h>
13#include <casa/iomanip.h>
14
15#include <casa/Exceptions.h>
16#include <casa/OS/Path.h>
17#include <casa/OS/File.h>
18#include <casa/Quanta/Unit.h>
19#include <casa/Arrays/ArrayMath.h>
20#include <casa/Arrays/ArrayLogical.h>
21#include <casa/Utilities/Regex.h>
22
23#include <casa/Containers/RecordField.h>
24
25#include <tables/Tables/TableRow.h>
26
27#include <atnf/PKSIO/PKSrecord.h>
28#include <atnf/PKSIO/PKSreader.h>
29#ifdef HAS_ALMA
30 #include <casa/System/ProgressMeter.h>
31#endif
32
33#include "STDefs.h"
34#include "STAttr.h"
35
36#include "STFiller.h"
37#include "STHeader.h"
38
39using namespace casa;
40
41namespace asap {
42
43STFiller::STFiller() :
44 reader_(0),
45 header_(0),
46 table_(0),
47 refRx_(".*(e|w|_R)$")
48{
49}
50
51STFiller::STFiller( CountedPtr< Scantable > stbl ) :
52 reader_(0),
53 header_(0),
54 table_(stbl),
55 refRx_(".*(e|w|_R)$")
56{
57}
58
59STFiller::STFiller(const std::string& filename, int whichIF, int whichBeam ) :
60 reader_(0),
61 header_(0),
62 table_(0),
63 refRx_(".*(e|w|_R)$")
64{
65 open(filename, whichIF, whichBeam);
66}
67
68STFiller::~STFiller()
69{
70 close();
71}
72
73void STFiller::open( const std::string& filename, int whichIF, int whichBeam )
74{
75 if (table_.null()) {
76 table_ = new Scantable();
77 }
78 if (reader_) { delete reader_; reader_ = 0; }
79 Bool haveBase, haveSpectra;
80
81 String inName(filename);
82 Path path(inName);
83 inName = path.expandedName();
84
85 File file(inName);
86 if ( !file.exists() ) {
87 throw(AipsError("File does not exist"));
88 }
89 filename_ = inName;
90
91 // Create reader and fill in values for arguments
92 String format;
93 Vector<Bool> beams, ifs;
94 Vector<uInt> nchans,npols;
95 if ( (reader_ = getPKSreader(inName, 0, 0, format, beams, ifs,
96 nchans, npols, haveXPol_,haveBase, haveSpectra
97 )) == 0 ) {
98 throw(AipsError("Creation of PKSreader failed"));
99 }
100 if (!haveSpectra) {
101 delete reader_;
102 reader_ = 0;
103 throw(AipsError("No spectral data in file."));
104 return;
105 }
106 nBeam_ = beams.nelements();
107 nIF_ = ifs.nelements();
108 // Get basic parameters.
109 if ( anyEQ(haveXPol_, True) ) {
110 pushLog("Cross polarization present");
111 for (uInt i=0; i< npols.nelements();++i) {
112 if (npols[i] < 3) npols[i] += 2;// Convert Complex -> 2 Floats
113 }
114 }
115 if (header_) delete header_;
116 header_ = new STHeader();
117 header_->nchan = max(nchans);
118 header_->npol = max(npols);
119 header_->nbeam = nBeam_;
120
121 Int status = reader_->getHeader(header_->observer, header_->project,
122 header_->antennaname, header_->antennaposition,
123 header_->obstype,
124 header_->fluxunit,
125 header_->equinox,
126 header_->freqref,
127 header_->utc, header_->reffreq,
128 header_->bandwidth);
129
130 if (status) {
131 delete reader_;
132 reader_ = 0;
133 delete header_;
134 header_ = 0;
135 throw(AipsError("Failed to get header."));
136 }
137 if ((header_->obstype).matches("*SW*")) {
138 // need robust way here - probably read ahead of next timestamp
139 pushLog("Header indicates frequency switched observation.\n"
140 "setting # of IFs = 1 ");
141 nIF_ = 1;
142 header_->obstype = String("fswitch");
143 }
144 // Determine Telescope and set brightness unit
145
146
147 Bool throwIt = False;
148 Instrument inst = STAttr::convertInstrument(header_->antennaname, throwIt);
149
150 if (inst==ATMOPRA || inst==TIDBINBILLA) {
151 header_->fluxunit = "K";
152 } else {
153 // downcase for use with Quanta
154 if (header_->fluxunit == "JY") {
155 header_->fluxunit = "Jy";
156 }
157 }
158 STAttr stattr;
159 header_->poltype = stattr.feedPolType(inst);
160 header_->nif = nIF_;
161 header_->epoch = "UTC";
162 // *** header_->frequnit = "Hz"
163 // Apply selection criteria.
164 Vector<Int> ref;
165 ifOffset_ = 0;
166 if (whichIF>=0) {
167 if (whichIF>=0 && whichIF<nIF_) {
168 ifs = False;
169 ifs(whichIF) = True;
170 header_->nif = 1;
171 nIF_ = 1;
172 ifOffset_ = whichIF;
173 } else {
174 delete reader_;
175 reader_ = 0;
176 delete header_;
177 header_ = 0;
178 throw(AipsError("Illegal IF selection"));
179 }
180 }
181 beamOffset_ = 0;
182 if (whichBeam>=0) {
183 if (whichBeam>=0 && whichBeam<nBeam_) {
184 beams = False;
185 beams(whichBeam) = True;
186 header_->nbeam = 1;
187 nBeam_ = 1;
188 beamOffset_ = whichBeam;
189 } else {
190 delete reader_;
191 reader_ = 0;
192 delete header_;
193 header_ = 0;
194 throw(AipsError("Illegal Beam selection"));
195 }
196 }
197 Vector<Int> start(nIF_, 1);
198 Vector<Int> end(nIF_, 0);
199 reader_->select(beams, ifs, start, end, ref, True, haveXPol_[0]);
200 table_->setHeader(*header_);
201 //For MS, add the location of POINTING of the input MS so one get
202 //pointing data from there, if necessary.
203 //Also find nrow in MS
204 nInDataRow = 0;
205 if (format == "MS2") {
206 Path datapath(inName);
207 String ptTabPath = datapath.absoluteName();
208 Table inMS(ptTabPath);
209 nInDataRow = inMS.nrow();
210 ptTabPath.append("/POINTING");
211 table_->table().rwKeywordSet().define("POINTING", ptTabPath);
212 if ((header_->antennaname).matches("GBT")) {
213 String GOTabPath = datapath.absoluteName();
214 GOTabPath.append("/GBT_GO");
215 table_->table().rwKeywordSet().define("GBT_GO", GOTabPath);
216 }
217 }
218
219}
220
221void STFiller::close( )
222{
223 delete reader_;reader_=0;
224 delete header_;header_=0;
225 table_ = 0;
226}
227
228int asap::STFiller::read( )
229{
230 int status = 0;
231
232 Double min = 0.0;
233 Double max = nInDataRow;
234#ifdef HAS_ALMA
235 ProgressMeter fillpm(min, max, "Data importing progress");
236#endif
237 PKSrecord pksrec;
238 int n = 0;
239 while ( status == 0 ) {
240 status = reader_->read(pksrec);
241 if ( status != 0 ) break;
242 n += 1;
243
244 Regex filterrx(".*[SL|PA]$");
245 Regex obsrx("^AT.+");
246 if ( header_->antennaname.matches(obsrx) &&
247 pksrec.obsType.matches(filterrx)) {
248 //cerr << "ignoring paddle scan" << endl;
249 continue;
250 }
251 TableRow row(table_->table());
252 TableRecord& rec = row.record();
253 // fields that don't get used and are just passed through asap
254 RecordFieldPtr<Array<Double> > srateCol(rec, "SCANRATE");
255 // MRC changed type from double to float
256 Vector<Double> sratedbl(pksrec.scanRate.nelements());
257 convertArray(sratedbl, pksrec.scanRate);
258 *srateCol = sratedbl;
259 RecordFieldPtr<Array<Double> > spmCol(rec, "SRCPROPERMOTION");
260 *spmCol = pksrec.srcPM;
261 RecordFieldPtr<Array<Double> > sdirCol(rec, "SRCDIRECTION");
262 *sdirCol = pksrec.srcDir;
263 RecordFieldPtr<Double> svelCol(rec, "SRCVELOCITY");
264 *svelCol = pksrec.srcVel;
265 // the real stuff
266 RecordFieldPtr<Int> fitCol(rec, "FIT_ID");
267 *fitCol = -1;
268 RecordFieldPtr<uInt> scanoCol(rec, "SCANNO");
269 *scanoCol = pksrec.scanNo-1;
270 RecordFieldPtr<uInt> cyclenoCol(rec, "CYCLENO");
271 *cyclenoCol = pksrec.cycleNo-1;
272 RecordFieldPtr<Double> mjdCol(rec, "TIME");
273 *mjdCol = pksrec.mjd;
274 RecordFieldPtr<Double> intCol(rec, "INTERVAL");
275 *intCol = pksrec.interval;
276 RecordFieldPtr<String> srcnCol(rec, "SRCNAME");
277 RecordFieldPtr<Int> srctCol(rec, "SRCTYPE");
278 RecordFieldPtr<String> fieldnCol(rec, "FIELDNAME");
279 *fieldnCol = pksrec.fieldName;
280 // try to auto-identify if it is on or off.
281 Regex rx(refRx_);
282 Regex rx2("_S$");
283 Int match = pksrec.srcName.matches(rx);
284 if (match) {
285 *srcnCol = pksrec.srcName;
286 } else {
287 *srcnCol = pksrec.srcName.before(rx2);
288 }
289 //*srcnCol = pksrec.srcName;//.before(rx2);
290 *srctCol = match;
291 RecordFieldPtr<uInt> beamCol(rec, "BEAMNO");
292 *beamCol = pksrec.beamNo-beamOffset_-1;
293 RecordFieldPtr<Int> rbCol(rec, "REFBEAMNO");
294 Int rb = -1;
295 if (nBeam_ > 1 ) rb = pksrec.refBeam-1;
296 *rbCol = rb;
297 RecordFieldPtr<uInt> ifCol(rec, "IFNO");
298 *ifCol = pksrec.IFno-ifOffset_- 1;
299 uInt id;
300 /// @todo this has to change when nchan isn't global anymore
301 id = table_->frequencies().addEntry(Double(header_->nchan/2),
302 pksrec.refFreq, pksrec.freqInc);
303 RecordFieldPtr<uInt> mfreqidCol(rec, "FREQ_ID");
304 *mfreqidCol = id;
305
306 id = table_->molecules().addEntry(pksrec.restFreq);
307 RecordFieldPtr<uInt> molidCol(rec, "MOLECULE_ID");
308 *molidCol = id;
309
310 id = table_->tcal().addEntry(pksrec.tcalTime, pksrec.tcal);
311 RecordFieldPtr<uInt> mcalidCol(rec, "TCAL_ID");
312 *mcalidCol = id;
313 id = table_->weather().addEntry(pksrec.temperature, pksrec.pressure,
314 pksrec.humidity, pksrec.windSpeed,
315 pksrec.windAz);
316 RecordFieldPtr<uInt> mweatheridCol(rec, "WEATHER_ID");
317 *mweatheridCol = id;
318 RecordFieldPtr<uInt> mfocusidCol(rec, "FOCUS_ID");
319 id = table_->focus().addEntry(pksrec.focusAxi, pksrec.focusTan,
320 pksrec.focusRot);
321 *mfocusidCol = id;
322 RecordFieldPtr<Array<Double> > dirCol(rec, "DIRECTION");
323 *dirCol = pksrec.direction;
324 RecordFieldPtr<Float> azCol(rec, "AZIMUTH");
325 *azCol = pksrec.azimuth;
326 RecordFieldPtr<Float> elCol(rec, "ELEVATION");
327 *elCol = pksrec.elevation;
328
329 RecordFieldPtr<Float> parCol(rec, "PARANGLE");
330 *parCol = pksrec.parAngle;
331
332 RecordFieldPtr< Array<Float> > specCol(rec, "SPECTRA");
333 RecordFieldPtr< Array<uChar> > flagCol(rec, "FLAGTRA");
334 RecordFieldPtr< uInt > polnoCol(rec, "POLNO");
335
336 RecordFieldPtr< Array<Float> > tsysCol(rec, "TSYS");
337 // Turn the (nchan,npol) matrix and possible complex xPol vector
338 // into 2-4 rows in the scantable
339 Vector<Float> tsysvec(1);
340 // Why is pksrec.spectra.ncolumn() == 3 for haveXPol_ == True
341 uInt npol = (pksrec.spectra.ncolumn()==1 ? 1: 2);
342 for ( uInt i=0; i< npol; ++i ) {
343 tsysvec = pksrec.tsys(i);
344 *tsysCol = tsysvec;
345 *polnoCol = i;
346
347 *specCol = pksrec.spectra.column(i);
348 *flagCol = pksrec.flagged.column(i);
349 table_->table().addRow();
350 row.put(table_->table().nrow()-1, rec);
351 }
352 if ( haveXPol_[0] ) {
353 // no tsys given for xpol, so emulate it
354 tsysvec = sqrt(pksrec.tsys[0]*pksrec.tsys[1]);
355 *tsysCol = tsysvec;
356 // add real part of cross pol
357 *polnoCol = 2;
358 Vector<Float> r(real(pksrec.xPol));
359 *specCol = r;
360 // make up flags from linears
361 /// @fixme this has to be a bitwise or of both pols
362 *flagCol = pksrec.flagged.column(0);// | pksrec.flagged.column(1);
363 table_->table().addRow();
364 row.put(table_->table().nrow()-1, rec);
365 // ad imaginary part of cross pol
366 *polnoCol = 3;
367 Vector<Float> im(imag(pksrec.xPol));
368 *specCol = im;
369 table_->table().addRow();
370 row.put(table_->table().nrow()-1, rec);
371 }
372#ifdef HAS_ALMA
373 fillpm._update(n);
374#endif
375 }
376 if (status > 0) {
377 close();
378 throw(AipsError("Reading error occured, data possibly corrupted."));
379 }
380#ifdef HAS_ALMA
381 fillpm.done();
382#endif
383 return status;
384}
385
386}//namespace asap
Note: See TracBrowser for help on using the repository browser.