source: trunk/external-alma/atnf/PKSIO/NRODataset.cc @ 2782

Last change on this file since 2782 was 2782, checked in by Takeshi Nakazato, 11 years ago

New Development: No

JIRA Issue: No

Ready for Test: Yes

Interface Changes: No

What Interface Changed: Please list interface changes

Test Programs: List test programs

Put in Release Notes: Yes/No?

Module(s): Module Names change impacts.

Description: Describe your changes here...

Refactoring NRO filler.


File size: 26.4 KB
Line 
1//#---------------------------------------------------------------------------
2//# NRODataset.cc: Base class for NRO dataset.
3//#---------------------------------------------------------------------------
4//# Copyright (C) 2000-2006
5//# Associated Universities, Inc. Washington DC, USA.
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 received 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$
29//#---------------------------------------------------------------------------
30//# Original: 2009/02/27, Takeshi Nakazato, NAOJ
31//#---------------------------------------------------------------------------
32
33#include <atnf/PKSIO/NRODataset.h>
34#include <casa/OS/Time.h>
35#include <casa/Utilities/Regex.h>
36#include <scimath/Mathematics/InterpolateArray1D.h>
37
38#include <measures/Measures/MeasConvert.h>
39#include <measures/Measures/MCFrequency.h>
40#include <measures/Measures/MFrequency.h>
41#include <measures/Measures/MPosition.h>
42#include <measures/Measures/MEpoch.h>
43#include <measures/Measures/MDirection.h>
44
45#include <math.h>
46#include <fstream>
47
48//#include <casa/namespace.h>
49
50using namespace std ;
51
52//
53// NRODataset
54//
55// Base class for NRO dataset.
56//
57
58// constructor
59NRODataset::NRODataset( string name )
60  : scanNum_(0),
61    rowNum_(0),
62    scanLen_(0),
63    dataLen_(0),
64    dataid_(-1),
65    filename_(name),
66    fp_(NULL),
67    same_(-1),
68    frec_()
69{}
70
71// destructor
72NRODataset::~NRODataset()
73{
74  // release memory
75  releaseRecord() ;
76
77  // close file
78  close() ;
79}
80
81// data initialization
82void NRODataset::initialize()
83{
84  LogIO os( LogOrigin( "NRODataset", "initialize()", WHERE ) ) ;
85
86  int arymax = arrayMax() ;
87
88  // check endian
89  open() ;
90  fseek( fp_, 144, SEEK_SET ) ;
91  int tmp ;
92  if( fread( &tmp, 1, sizeof(int), fp_ ) != sizeof(int) ) {
93    os << LogIO::SEVERE << "Error while checking endian of the file. " << LogIO::EXCEPTION ;
94    return ;
95  }
96  if ( ( 0 < tmp ) && ( tmp <= arymax ) ) {
97    same_ = 1 ;
98    os << LogIO::NORMAL << "same endian " << LogIO::POST ;
99  }
100  else {
101    same_ = 0 ;
102    os << LogIO::NORMAL << "different endian " << LogIO::POST ;
103  }
104  fseek( fp_, 0, SEEK_SET ) ;
105
106  // common part of calculation of data size and memory allocation
107  RX.resize( arymax ) ;
108  HPBW.resize( arymax ) ;
109  EFFA.resize( arymax ) ;
110  EFFB.resize( arymax ) ;
111  EFFL.resize( arymax ) ;
112  EFSS.resize( arymax ) ;
113  GAIN.resize( arymax ) ;
114  HORN.resize( arymax ) ;
115  POLTP.resize( arymax ) ;
116  POLDR.resize( arymax ) ;
117  POLAN.resize( arymax ) ;
118  DFRQ.resize( arymax ) ;
119  SIDBD.resize( arymax ) ;
120  REFN.resize( arymax ) ;
121  IPINT.resize( arymax ) ;
122  MULTN.resize( arymax ) ;
123  MLTSCF.resize( arymax ) ;
124  LAGWIND.resize( arymax ) ;
125  BEBW.resize( arymax ) ;
126  BERES.resize( arymax ) ;
127  CHWID.resize( arymax ) ;
128  ARRY.resize( arymax ) ;
129  NFCAL.resize( arymax ) ;
130  F0CAL.resize( arymax ) ;
131  FQCAL.resize( arymax ) ;
132  CHCAL.resize( arymax ) ;
133  CWCAL.resize( arymax ) ;
134  DSBFC.resize( arymax ) ;
135
136  for ( int i = 0 ; i < arymax ; i++ ) {
137    FQCAL[i].resize( 10 ) ;
138    CHCAL[i].resize( 10 ) ;
139    CWCAL[i].resize( 10 ) ;
140  }
141
142  datasize_ = sizeof( char ) * 8   // LOFIL
143    + sizeof( char ) * 8           // VER
144    + sizeof( char ) * 16          // GROUP
145    + sizeof( char ) * 16          // PROJ
146    + sizeof( char ) * 24          // SCHED
147    + sizeof( char ) * 40          // OBSVR
148    + sizeof( char ) * 16          // LOSTM
149    + sizeof( char ) * 16          // LOETM
150    + sizeof( int ) * 2            // ARYNM, NSCAN
151    + sizeof( char ) * 120         // TITLE
152    + sizeof( char ) * 16          // OBJ
153    + sizeof( char ) * 8           // EPOCH
154    + sizeof( double ) * 4         // RA0, DEC0, GLNG0, GLAT0
155    + sizeof( int ) * 2            // NCALB, SCNCD
156    + sizeof( char ) * 120         // SCMOD
157    + sizeof( double )             // URVEL
158    + sizeof( char ) * 4           // VREF
159    + sizeof( char ) * 4           // VDEF
160    + sizeof( char ) * 8           // SWMOD
161    + sizeof( double ) * 8         // FRQSW, DBEAM, MLTOF, CMTQ, CMTE, CMTSOM, CMTNODE, CMTI
162    + sizeof( char ) * 24          // CMTTM
163    + sizeof( double ) * 6         // SBDX, SBDY, SBDZ1, SBDZ2, DAZP, DELP
164    + sizeof( int ) * 4            // CHBIND, NUMCH, CHMIN, CHMAX
165    + sizeof( double ) * 3         // ALCTM, IPTIM, PA
166    + sizeof( int ) * 3            // SCNLEN, SBIND, IBIT
167    + sizeof( char ) * 8 ;         // SITE
168
169  // NRODataRecord
170  record_ = new NRODataRecord() ;
171  record_->LDATA = NULL ;
172
173  // reference frequency
174  refFreq_.resize( arymax, 0.0 ) ;
175}
176
177// fill data header
178int NRODataset::fillHeader()
179{
180  LogIO os( LogOrigin( "NRODataset", "fillHeader()", WHERE ) ) ;
181
182  // open file
183  if ( open() ) {
184    os << LogIO::SEVERE << "Error opening file " << filename_ << "." << LogIO::EXCEPTION ;
185    return -1 ;
186  }
187
188  // fill
189  int status = fillHeader( same_ ) ;
190
191  if ( status != 0 ) {
192    os << LogIO::SEVERE << "Error while reading header " << filename_ << "." << LogIO::EXCEPTION ;
193    return status ;
194  }
195
196  //scanNum_ = NSCAN + 1 ; // includes ZERO scan
197  scanLen_ = SCNLEN ;
198  dataLen_ = scanLen_ - SCAN_HEADER_SIZE ;
199  scanNum_ = getScanNum();
200  rowNum_ = scanNum_ * ARYNM ;
201  chmax_ = (int) ( dataLen_ * 8 / IBIT ) ;
202  record_->LDATA = new char[dataLen_] ;
203
204  initArray();
205
206  show() ;
207
208  return status ;
209}
210
211void NRODataset::convertEndian( int &value )
212{
213  char volatile *first = reinterpret_cast<char volatile *>( &value ) ;
214  char volatile *last = first + sizeof( int ) ;
215  std::reverse( first, last ) ;
216}
217
218void NRODataset::convertEndian( float &value )
219{
220  char volatile *first = reinterpret_cast<char volatile *>( &value ) ;
221  char volatile *last = first + sizeof( float ) ;
222  std::reverse( first, last ) ;
223}
224
225void NRODataset::convertEndian( double &value )
226{
227  char volatile *first = reinterpret_cast<char volatile *>( &value ) ;
228  char volatile *last = first + sizeof( double ) ;
229  std::reverse( first, last ) ;
230}
231
232int NRODataset::readHeader( char *v, int size )
233{
234  if ( (int)( fread( v, 1, size, fp_ ) ) != size ) {
235    return -1 ;
236  }
237  return 0 ;
238}
239
240int NRODataset::readHeader( int &v, int b )
241{
242  if ( fread( &v, 1, sizeof(int), fp_ ) != sizeof(int) ) {
243    return -1 ;
244  }
245
246  if ( b == 0 )
247    convertEndian( v ) ;
248
249  return 0 ;
250}
251
252int NRODataset::readHeader( float &v, int b )
253{
254  if ( fread( &v, 1, sizeof(float), fp_ ) != sizeof(float) ) {
255    return -1 ;
256  }
257
258  if ( b == 0 )
259    convertEndian( v ) ;
260
261  return 0 ;
262}
263
264int NRODataset::readHeader( double &v, int b )
265{
266  if ( fread( &v, 1, sizeof(double), fp_ ) != sizeof(double) ) {
267    return -1 ;
268  }
269
270  if ( b == 0 )
271    convertEndian( v ) ;
272
273  return 0 ;
274}
275
276void NRODataset::convertEndian( NRODataRecord &r )
277{
278  convertEndian( r.ISCAN ) ;
279  convertEndian( r.DSCX ) ;
280  convertEndian( r.DSCY ) ;
281  convertEndian( r.SCX ) ;
282  convertEndian( r.SCY ) ;
283  convertEndian( r.PAZ ) ;
284  convertEndian( r.PEL ) ;
285  convertEndian( r.RAZ ) ;
286  convertEndian( r.REL ) ;
287  convertEndian( r.XX ) ;
288  convertEndian( r.YY ) ;
289  convertEndian( r.TEMP ) ;
290  convertEndian( r.PATM ) ;
291  convertEndian( r.PH2O ) ;
292  convertEndian( r.VWIND ) ;
293  convertEndian( r.DWIND ) ;
294  convertEndian( r.TAU ) ; 
295  convertEndian( r.TSYS ) ;
296  convertEndian( r.BATM ) ;
297  convertEndian( r.LINE ) ;
298  for ( int i = 0 ; i < 4 ; i++ )
299    convertEndian( r.IDMY1[i] ) ;
300  convertEndian( r.VRAD ) ;
301  convertEndian( r.FREQ0 ) ;
302  convertEndian( r.FQTRK ) ;
303  convertEndian( r.FQIF1 ) ;
304  convertEndian( r.ALCV ) ;
305  for ( int i = 0 ; i < 2 ; i++ )
306    for ( int j = 0 ; j < 2 ; j++ )
307      convertEndian( r.OFFCD[i][j] ) ;
308  convertEndian( r.IDMY0 ) ;
309  convertEndian( r.IDMY2 ) ;
310  convertEndian( r.DPFRQ ) ;
311  convertEndian( r.SFCTR ) ;
312  convertEndian( r.ADOFF ) ;
313}
314
315void NRODataset::releaseRecord()
316{
317  if ( !record_.null() ) {
318    record_ = NULL ;
319  }
320  dataid_ = -1 ;
321}
322
323// Get specified scan
324NRODataRecord *NRODataset::getRecord( int i )
325{
326  // DEBUG
327  //cout << "NRODataset::getRecord()  Start " << i << endl ;
328  //
329  if ( i < 0 || i >= rowNum_ ) {
330    LogIO os( LogOrigin( "NRODataset", "getRecord()", WHERE ) ) ;
331    //cerr << "NRODataset::getRecord()  data index out of range." << endl ;
332    os << LogIO::SEVERE << "data index " << i << " out of range. return NULL." << LogIO::POST ;
333    return NULL ;
334  }
335
336  if ( i == dataid_ ) {
337    return &(*record_) ;
338  }
339
340  // DEBUG
341  //cout << "NRODataset::getData()  Get new dataset" << endl ;
342  //
343  // read data
344  int status = fillRecord( i ) ;
345  if ( status == 0 ) {
346    dataid_ = i ;
347  }
348  else {
349    LogIO os( LogOrigin( "NRODataset", "getRecord()", WHERE ) ) ;
350    //cerr << "NRODataset::getRecord()  error while reading data " << i << endl ;
351    os << LogIO::SEVERE << "error while reading data " << i << ". return NULL." << LogIO::EXCEPTION ;
352    dataid_ = -1 ;
353    return NULL ;
354  }
355
356  return &(*record_) ;
357}
358
359int NRODataset::fillRecord( int i )
360{
361  int status = 0 ;
362
363  status = open() ;
364  if ( status != 0 )
365    return status ;
366   
367
368  // fill NRODataset
369  long offset = getDataSize() + scanLen_ * i ;
370  // DEBUG
371  //cout << "NRODataset::fillRecord()  offset (header) = " << offset << endl ;
372  //cout << "NRODataset::fillRecord()  sizeof(NRODataRecord) = " << sizeof( NRODataRecord ) << " byte" << endl ;
373  fseek( fp_, offset, SEEK_SET ) ;
374  if ( (int)fread( &(*record_), 1, SCAN_HEADER_SIZE, fp_ ) != SCAN_HEADER_SIZE ) {
375    //cerr << "Failed to read scan header: " << i << endl ;
376    LogIO os( LogOrigin( "NRODataset", "fillRecord()", WHERE ) ) ;
377    os << LogIO::SEVERE << "Failed to read scan header for " << i << "th row." << LogIO::POST ;
378    return -1 ;
379  }
380  if ( (int)fread( &(*record_->LDATA), 1, dataLen_, fp_ ) != dataLen_ ) {
381    //cerr << "Failed to read spectral data: " << i << endl ;
382    LogIO os( LogOrigin( "NRODataset", "fillRecord()", WHERE ) ) ;
383    os << LogIO::SEVERE << "Failed to read spectral data for " << i << "th row." << LogIO::POST ;
384    return -1 ;
385  }
386
387  if ( same_ == 0 ) {
388    convertEndian( *record_ ) ;
389  }
390
391  // DWIND unit conversion (deg -> rad)
392  record_->DWIND = record_->DWIND * M_PI / 180.0 ;
393
394  return status ;
395}
396
397// open
398int NRODataset::open()
399{
400  int status = 0 ;
401
402  if ( fp_ == NULL ) {
403    if ( (fp_ = fopen( filename_.c_str(), "rb" )) == NULL )
404      status = -1 ;
405    else
406      status = 0 ;
407  }
408
409  return status ;
410}
411
412// close
413void NRODataset::close()
414{
415  // DEBUG
416  //cout << "NRODataset::close()  close file" << endl ;
417  //
418  if ( fp_ != NULL )
419    fclose( fp_ ) ;
420  fp_ = NULL ;
421}
422
423// get spectrum
424vector< vector<double> > NRODataset::getSpectrum()
425{
426  vector< vector<double> > spec(rowNum_);
427
428  for ( int i = 0 ; i < rowNum_ ; i++ ) {
429    spec[i] = getSpectrum( i ) ;
430  }
431
432  return spec ;
433}
434
435vector<double> NRODataset::getSpectrum( int i )
436{
437  // DEBUG
438  //cout << "NRODataset::getSpectrum() start process (" << i << ")" << endl ;
439  //
440  // size of spectrum is not chmax_ but dataset_->getNCH() after binding
441  const int nchan = NUMCH ;
442  vector<double> spec( chmax_ ) ;  // spectrum "before" binding
443  // DEBUG
444  //cout << "NRODataset::getSpectrum()  nchan = " << nchan << " chmax_ = " << chmax_ << endl ;
445  //
446
447  const NRODataRecord *record = getRecord( i ) ;
448
449  const int bit = IBIT ;   // fixed to 12 bit
450  double scale = record->SFCTR ;
451  // DEBUG
452  //cout << "NRODataset::getSpectrum()  scale = " << scale << endl ;
453  //
454  double offset = record->ADOFF ;
455  // DEBUG
456  //cout << "NRODataset::getSpectrum()  offset = " << offset << endl ;
457  //
458  if ( ( scale == 0.0 ) && ( offset == 0.0 ) ) {
459    //cerr << "NRODataset::getSpectrum()  zero spectrum (" << i << ")" << endl ;
460    LogIO os( LogOrigin("NRODataset","getSpectrum",WHERE) ) ;
461    os << LogIO::WARN << "zero spectrum for row " << i << LogIO::POST ;
462    if ( spec.size() != (unsigned int)nchan )
463      spec.resize( nchan ) ;
464    for ( vector<double>::iterator i = spec.begin() ;
465          i != spec.end() ; i++ )
466      *i = 0.0 ;
467    return spec ;
468  }
469  unsigned char *cdata = (unsigned char *)&(*record->LDATA) ;
470  vector<double> mscale = MLTSCF ;
471  double dscale = mscale[getIndex( i )] ;
472  int cbind = CHBIND ;
473  int chmin = CHMIN ;
474
475  // char -> int -> double
476  vector<double>::iterator iter = spec.begin() ;
477
478  static const int shift_right[] = {
479    4, 0
480  };
481  static const int start_pos[] = {
482    0, 1
483  };
484  static const int incr[] = {
485    0, 3
486  };
487  int j = 0 ;
488  for ( int i = 0 ; i < chmax_ ; i++ ) {
489    // char -> int
490    int ivalue = 0 ;
491    if ( bit == 12 ) {  // 12 bit qunatization
492      const int ialt = i & 1 ;
493      const int idx = j + start_pos[ialt];
494      const unsigned tmp = unsigned(cdata[idx]) << 8 | cdata[idx + 1];
495      ivalue = int((tmp >> shift_right[ialt]) & 0xFFF);
496      j += incr[ialt];
497    }
498
499    if ( ( ivalue < 0 ) || ( ivalue > 4096 ) ) {
500      //cerr << "NRODataset::getSpectrum()  ispec[" << i << "] is out of range" << endl ;
501      LogIO os( LogOrigin( "NRODataset", "getSpectrum", WHERE ) ) ;
502      os << LogIO::SEVERE << "ivalue for row " << i << " is out of range" << LogIO::EXCEPTION ;
503      if ( spec.size() != (unsigned int)nchan )
504        spec.resize( nchan ) ;
505      for ( vector<double>::iterator i = spec.begin() ;
506            i != spec.end() ; i++ )
507        *i = 0.0 ;
508      return spec ;
509    }
510    // DEBUG
511    //cout << "NRODataset::getSpectrum()  ispec[" << i << "] = " << ispec[i] << endl ;
512    //
513
514    // int -> double
515    *iter = (double)( ivalue * scale + offset ) * dscale ;
516    // DEBUG
517    //cout << "NRODataset::getSpectrum()  spec[" << i << "] = " << *iter << endl ;
518    //
519    iter++ ;
520  }
521
522  // channel binding if necessary
523  if ( cbind != 1 ) {
524    iter = spec.begin() ;
525    advance( iter, chmin ) ;
526    vector<double>::iterator iter2 = spec.begin() ;
527    for ( int i = 0 ; i < nchan ; i++ ) {
528      double sum0 = 0 ;
529      double sum1 = 0 ;
530      for ( int j = 0 ; j < cbind ; j++ ) {
531        sum0 += *iter ;
532        sum1 += 1.0 ;
533        iter++ ;
534      }
535      *iter2 = sum0 / sum1 ;
536      iter2++ ;
537      // DEBUG
538      //cout << "NRODataset::getSpectrum()  bspec[" << i << "] = " << bspec[i] << endl ;
539      //
540    }
541    spec.resize( nchan ) ;
542  }
543
544  // DEBUG
545  //cout << "NRODataset::getSpectrum() end process" << endl ;
546  //
547
548  return spec ;
549}
550
551int NRODataset::getIndex( int irow )
552{
553  // DEBUG
554  //cout << "NRODataset::getIndex()  start" << endl ;
555  //
556  const NRODataRecord *record = getRecord( irow ) ;
557
558  const string str = record->ARRYT ;
559  // DEBUG
560  //cout << "NRODataset::getIndex()  str = " << str << endl ;
561  //
562  int index = (int)getArrayId(str);
563  // DEBUG
564  //cout << "NRODataset::getIndex()  irow = " << irow << "str = " << str << " index = " << index << endl ;
565  //
566
567  // DEBUG
568  //cout << "NRODataset::getIndex()  end" << endl ;
569  //
570  return index ;
571}
572
573int NRODataset::getPolarizationNum()
574{
575  // DEBUG
576  //cout << "NRODataset::getPolarizationNum()  start process" << endl ;
577  //
578  int npol = 1;
579  Regex reRx2("(.*V|H20ch2)$");
580  Regex reRx1("(.*H|H20ch1)$");
581  Bool match1 = false;
582  Bool match2 = false;
583  for (int i = 0; i < arrayMax(); i++) {
584    //cout << "RX[" << i << "]=" << RX[i] << endl;
585    if (!match1) {
586      match1 = (reRx1.match(RX[i].c_str(), RX[i].size()) != String::npos);
587    }
588    if (!match2) {
589      match2 = (reRx2.match(RX[i].c_str(), RX[i].size()) != String::npos);
590    }
591  }
592
593  if (match1 && match2)
594    npol = 2; 
595
596  //cout << "npol = " << npol << endl;
597
598  // DEBUG
599  //cout << "NRODataset::getPolarizationNum()  end process" << endl ;
600  //
601
602  return npol ;
603}
604
605vector<double> NRODataset::getStartIntTime()
606{
607  vector<double> times ;
608  for ( int i = 0 ; i < rowNum_ ; i++ ) {
609    times.push_back( getStartIntTime( i ) ) ;
610  }
611  return times ;
612}
613
614double NRODataset::getStartIntTime( int i )
615{
616  const NRODataRecord *record = getRecord( i ) ;
617
618  const char *t = record->LAVST ;
619  return getMJD( t ) ;
620}
621
622double NRODataset::getMJD( const char *time )
623{
624  // TODO: should be checked which time zone the time depends on
625  // 2008/11/14 Takeshi Nakazato
626  string strStartTime( time ) ;
627  string strYear = strStartTime.substr( 0, 4 ) ;
628  string strMonth = strStartTime.substr( 4, 2 ) ;
629  string strDay = strStartTime.substr( 6, 2 ) ;
630  string strHour = strStartTime.substr( 8, 2 ) ;
631  string strMinute = strStartTime.substr( 10, 2 ) ;
632  string strSecond = strStartTime.substr( 12, strStartTime.size() - 12 ) ;
633  unsigned int year = atoi( strYear.c_str() ) ;
634  unsigned int month = atoi( strMonth.c_str() ) ;
635  unsigned int day = atoi( strDay.c_str() ) ;
636  unsigned int hour = atoi( strHour.c_str() ) ;
637  unsigned int minute = atoi( strMinute.c_str() ) ;
638  double second = atof( strSecond.c_str() ) ;
639  Time t( year, month, day, hour, minute, second ) ;
640
641  return t.modifiedJulianDay() ;
642}
643
644double NRODataset::getScanTime( int i )
645{
646  double startTime = getStartIntTime( i ) ;
647  double interval = getIPTIM() / 86400.0 ; // [sec]->[day]
648  return startTime+0.5*interval ;
649}
650
651vector<bool> NRODataset::getIFs()
652{
653  vector<bool> v ;
654  vector< vector<double> > fref ;
655  vector< vector<double> > chcal = CHCAL ;
656  vector<double> f0cal = F0CAL ;
657  vector<double> beres = BERES ;
658  for ( int i = 0 ; i < rowNum_ ; i++ ) {
659    vector<double> f( 4, 0 ) ;
660    uInt index = getIndex( i ) ;
661    f[0] = chcal[index][0] ;
662    f[1] = f0cal[index] ;
663    f[2] = beres[index] ;
664    if ( f[0] != 0. ) {
665      f[1] = f[1] - f[0] * f[2] ;
666    }
667    const NRODataRecord *record = getRecord( i ) ;
668    f[3] = record->FREQ0 ;
669    if ( v.size() == 0 ) {
670      v.push_back( True ) ;
671      fref.push_back( f ) ;
672    }
673    else {
674      bool b = true ;
675      int fsize = fref.size() ;
676      for ( int j = 0 ; j < fsize ; j++ ) {
677        if ( fref[j][1] == f[1] && fref[j][2] == f[2] && fref[j][3] == f[3] ) {
678          b = false ;
679        }
680      }
681      if ( b ) {
682        v.push_back( True ) ;
683        fref.push_back( f ) ;
684      }
685    }
686  }
687
688
689  // DEBUG
690  //cout << "NRODataset::getIFs()   number of IF is " << v.size() << endl ;
691  //
692
693  return v ;
694}
695
696vector<double> NRODataset::getFrequencies( int i )
697{
698  // return value
699  // v[0]  reference channel
700  // v[1]  reference frequency
701  // v[2]  frequency increment
702  vector<double> v( 3, 0.0 ) ;
703
704  const NRODataRecord *record = getRecord( i ) ;
705  string arryt = string( record->ARRYT ) ;
706  uInt ib = getArrayId( arryt ) ;
707  string rxname = getRX()[0] ;
708  string key = arryt ;
709  if ( rxname.find("MULT2") != string::npos )
710    key = "BEARS" ;
711
712  if ( frec_.isDefined( key ) ) {
713    // frequency for the array is already calculated
714    Vector<Double> f =  frec_.asArrayDouble( key ) ;
715    Double *f_p = f.data() ;
716    for ( int i = 0 ; i < 3 ; i++ )
717      v[i] = (double)(f_p[i]) ;
718    return v ;
719  }
720
721  //int ia = -1 ;
722  bool isAOS = false ;
723  //cout << "NRODataset::getFrequencies()  record->ARRYT=" << record->ARRYT << endl ;
724  //cout << "NRODataset::getFrequencies()  ib = " << ib << endl ;
725
726  if ( arryt[0] == 'W' || arryt[0] == 'U' || arryt[0] == 'H' )
727    isAOS = true ;
728
729  Bool isUSB ;
730  if ( record->FQIF1 > 0 )
731    isUSB = True ;  // USB
732  else
733    isUSB = False ;  // LSB
734
735  int ivdef = -1 ;
736  if ( (getVDEF()).compare( 0, 3, "RAD" ) == 0 )
737    ivdef = 0 ;
738  else if ( (getVDEF()).compare( 0, 3, "OPT" ) == 0 )
739    ivdef = 1 ;
740  // DEBUG
741  //cout << "NRODataset::getFrequencies() ivdef = " << ivdef << endl ;
742  //
743  double vel = getURVEL() + record->VRAD ;
744  double cvel = 2.99792458e8 ; // speed of light [m/s]
745  double fq0 = record->FREQ0 ;
746  //double fq0 = record->FQTRK ;
747
748  int ncal = getNFCAL()[ib] ;
749  double cw = 0.0 ;
750  vector<double> fqcal = getFQCAL()[ib] ;
751  vector<double> chcal = getCHCAL()[ib] ;
752  double f0cal = getF0CAL()[ib] ;
753  Vector<Double> freqs( ncal, fq0-f0cal ) ;
754
755  double factor = vel / cvel ;
756  if ( ivdef == 0 )
757    factor = 1.0 / ( 1.0 - factor ) ;
758  for ( int ii = 0 ; ii < ncal ; ii++ ) {
759    freqs[ii] += fqcal[ii] ;
760    if ( ivdef == 0 ) {
761      freqs[ii] = freqs[ii] * factor + record->FQTRK * ( 1.0 - factor ) ;
762    }
763    else if ( ivdef == 1 ) {
764      freqs[ii] = freqs[ii] * ( 1.0 + factor ) - record->FQTRK * factor ;
765    }
766
767    //ofstream ofs("freqs.txt",ios::out|ios::app) ;
768    //ofs << setprecision(16) ;
769    //ofs << i << " " << record->ARRYT << " " << chcal[ii] << " " << freqs[ii] << " " << record->ISCAN << " " << fqcal[ii] << " " << f0cal << " " << record->FQTRK << " " << vel << endl ;
770    //ofs.close() ;
771
772  }
773
774  if ( isAOS ) {
775    // regridding
776    while ( ncal < (int)chcal.size() ) {
777      chcal.pop_back() ;
778    }
779    Vector<Double> xin( chcal ) ;
780    Vector<Double> yin( freqs ) ;
781    int nchan = getNUMCH() ;
782    Vector<Double> xout( nchan ) ;
783    indgen( xout ) ;
784    Vector<Double> yout ;
785    InterpolateArray1D<Double, Double>::interpolate( yout, xout, xin, yin, InterpolateArray1D<Double,Double>::cubic ) ;
786    Double bw = abs( yout[nchan-1] - yout[0] ) ;
787    bw += 0.5 * abs( yout[nchan-1] - yout[nchan-2] + yout[1] - yout[0] ) ;
788    Double dz = bw / (Double) nchan ;
789    if ( yout[0] > yout[1] )
790      dz = - dz ;
791    v[0] = 0 ;
792    v[1] = yout[0] ;
793    v[2] = dz ;
794  }
795  else {
796
797    cw = ( freqs[1] - freqs[0] )
798      / ( chcal[1] - chcal[0] ) ;   
799
800    if ( isUSB ) {
801      // channel frequency inversion
802      cw *= -1.0 ;
803      Double tmp = freqs[1] ;
804      freqs[1] = freqs[0] ;
805      freqs[0] = tmp ;
806    }
807   
808    v[0] = chcal[0] - 1 ; // 0-base
809    v[1] = freqs[0] ;
810    v[2] = cw ;
811  }
812
813  if ( refFreq_[ib] == 0.0 )
814    refFreq_[ib] = v[1] ;
815
816  // register frequency setting to Record
817  Vector<Double> f( v ) ;
818  frec_.define( key, f ) ;
819
820  return v ;
821}
822
823uInt NRODataset::getArrayId( string type )
824{
825  string sbeamno = type.substr( 1, type.size()-1 ) ;
826  uInt ib = atoi( sbeamno.c_str() ) - 1 ;
827  return ib ;
828}
829
830uInt NRODataset::getSortedArrayId( string type )
831{
832  uInt index = 0;
833  while (arrayNames_[index] != type && index < (uInt)ARYNM)
834    ++index;
835  return index;
836}
837
838void NRODataset::show()
839{
840  LogIO os( LogOrigin( "NRODataset", "show()", WHERE ) ) ;
841
842  os << LogIO::NORMAL << "------------------------------------------------------------" << endl ;
843  os << LogIO::NORMAL << "Number of scan = " << scanNum_ << endl ;
844  os << LogIO::NORMAL << "Number of data record = " << rowNum_ << endl ;
845  os << LogIO::NORMAL << "Length of data record = " << scanLen_ << " bytes" << endl ;
846  os << LogIO::NORMAL << "Allocated memory for spectral data = " << dataLen_ << " bytes" << endl ;
847  os << LogIO::NORMAL << "Max number of channel = " << chmax_ << endl ;
848  os << LogIO::NORMAL << "------------------------------------------------------------" << endl ;
849  os.post() ;
850
851}
852
853double NRODataset::toLSR( double v, double t, double x, double y )
854{
855  double vlsr ;
856
857  // get epoch
858  double tcent = t + 0.5*getIPTIM()/86400.0 ;
859  MEpoch me( Quantity( tcent, "d" ), MEpoch::UTC ) ;
860
861  // get antenna position
862  MPosition mp ;
863  if ( SITE.find( "45" ) != string::npos ) {
864    // 45m telescope
865    Double posx = -3.8710235e6 ;
866    Double posy = 3.4281068e6 ;
867    Double posz = 3.7240395e6 ;
868    mp = MPosition( MVPosition( posx, posy, posz ),
869                    MPosition::ITRF ) ;
870  }
871  else {
872    // ASTE
873    Vector<Double> pos( 2 ) ;
874    pos[0] = -67.7031 ;
875    pos[1] = -22.9717 ;
876    Double sitealt = 4800.0 ;
877    mp = MPosition( MVPosition( Quantity( sitealt, "m" ),
878                                Quantum< Vector<Double> >( pos, "deg" ) ),
879                    MPosition::WGS84 ) ;
880  }
881
882  // get direction
883  MDirection md ;
884  if ( SCNCD == 0 ) {
885    // RADEC
886    if ( EPOCH == "B1950" ) {
887      md = MDirection( Quantity( Double(x), "rad" ), Quantity( Double(y), "rad" ),
888                       MDirection::B1950 ) ;
889    }
890    else {
891      md = MDirection( Quantity( Double(x), "rad" ), Quantity( Double(y), "rad" ),
892                       MDirection::J2000 ) ;
893    }
894  }
895  else if ( SCNCD == 1 ) {
896    // LB
897    md = MDirection( Quantity( Double(x), "rad" ), Quantity( Double(y), "rad" ),
898                     MDirection::GALACTIC ) ;
899  }
900  else {
901    // AZEL
902    md = MDirection( Quantity( Double(x), "rad" ), Quantity( Double(y), "rad" ),
903                     MDirection::AZEL ) ;
904  }
905   
906  // to LSR
907  MeasFrame mf( me, mp, md ) ;
908  MFrequency::Convert tolsr( MFrequency::TOPO, MFrequency::Ref( MFrequency::LSRK, mf ) ) ;
909  vlsr = (double)(tolsr( Double(v) ).get( "Hz" ).getValue()) ;
910
911  return vlsr ;
912}
913
914uInt NRODataset::getPolNo( int i )
915{
916  int idx = getIndex( i ) ;
917//   cout << "HORN[" << idx << "]=" << HORN[idx]
918//        << ", RX[" << idx << "]=" << RX[idx] << endl ;
919  return polNoFromRX( RX[idx] ) ;
920}
921
922uInt NRODataset::polNoFromRX( const string &rx )
923{
924  uInt polno = 0 ;
925  // 2013/01/23 TN
926  // In NRO 45m telescope, naming convension for dual-polarization
927  // receiver is as follows:
928  //
929  //    xxxH for horizontal component,
930  //    xxxV for vertical component.
931  //
932  // Exception is H20ch1/ch2.
933  // Here, POLNO is assigned as follows:
934  //
935  //    POLNO=0: xxxH or H20ch1
936  //          1: xxxV or H20ch2
937  //
938  // For others, POLNO is always 0.
939  String rxString(rx);
940  rxString.trim();
941  //cout << "rx='" << rxString << "' (size " << rxString.size() << ")" << endl;
942  Regex reRx("(.*V|H20ch2)$");
943  if (reRx.match(rxString.c_str(), rxString.size()) != String::npos) {
944    //cout << "match!" << endl;
945    polno = 1;
946  }
947  return polno ;
948}
949
950void NRODataset::initArray()
951{
952  if (ARYNM <= 0)
953    throw AipsError("ARYNM must be greater than zero.");
954
955  int numArray = 0;
956  arrayNames_.resize(ARYNM);
957  for (int irow = 0; numArray < ARYNM && irow < rowNum_; irow++) {
958    //cout << "irow " << irow << endl;
959    const NRODataRecord *record = getRecord( irow ) ;
960    const string str = record->ARRYT ;
961    if (find(arrayNames_.begin(), arrayNames_.end(), str) == arrayNames_.end()) {
962      arrayNames_[numArray] = str;
963      //cout << "arrayNames_[" << numArray << "]=" << str << endl;
964      ++numArray;
965    }
966  }
967  //cout << "numArray=" << numArray << endl;
968}
969
970int NRODataset::getScanNum()
971{
972  long offset = getDataSize() + scanLen_ * NSCAN * ARYNM ;
973  fseek( fp_, offset, SEEK_SET ) ;
974  // try to read data
975  fgetc( fp_ ) ;
976  int eof = feof( fp_ ) ;
977  //cout << "eof=" << eof << endl;
978  // reset file pointer
979  fseek( fp_, 0, SEEK_SET ) ;
980  return NSCAN + (eof > 0 ? 0 : 1) ;
981}
Note: See TracBrowser for help on using the repository browser.