LCOV - code coverage report
Current view: top level - singledishfiller/Filler - NRO2MSReader.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 545 598 91.1 %
Date: 2024-12-11 20:54:31 Functions: 47 47 100.0 %

          Line data    Source code
       1             : /*
       2             :  * NRO2MSReader.cc
       3             :  *
       4             :  *  Created on: May 9, 2016
       5             :  *      Author: wataru kawasaki
       6             :  */
       7             : 
       8             : #include <singledishfiller/Filler/NRO2MSReader.h>
       9             : 
      10             : #include <iostream>
      11             : #include <string>
      12             : #include <map>
      13             : 
      14             : #include <casacore/casa/OS/File.h>
      15             : #include <casacore/casa/Containers/Record.h>
      16             : #include <casacore/casa/Utilities/Regex.h>
      17             : #include <casacore/tables/Tables/TableRecord.h>
      18             : #include <casacore/casa/Arrays/Vector.h>
      19             : #include <casacore/casa/Arrays/ArrayMath.h>
      20             : #include <casacore/casa/IO/ArrayIO.h>
      21             : #include <casacore/tables/Tables/Table.h>
      22             : 
      23             : using namespace casacore;
      24             : 
      25             : namespace {
      26           8 : Double queryAntennaDiameter(String const &name) {
      27           8 :   String capitalized = name;
      28           8 :   capitalized.upcase();
      29           8 :   Double diameter = 0.0;
      30           8 :   if (capitalized.matches(Regex(".*(DV|DA|PM)[0-9]+$"))) {
      31           0 :     diameter = 12.0;
      32           8 :   } else if (capitalized.matches(Regex(".*CM[0-9]+$"))) {
      33           0 :     diameter = 7.0;
      34           8 :   } else if (capitalized.contains("GBT")) {
      35           0 :     diameter = 104.9;
      36           8 :   } else if (capitalized.contains("MOPRA")) {
      37           0 :     diameter = 22.0;
      38           8 :   } else if (capitalized.contains("PKS") || capitalized.contains("PARKS")) {
      39           0 :     diameter = 64.0;
      40           8 :   } else if (capitalized.contains("TIDBINBILLA")) {
      41           0 :     diameter = 70.0;
      42           8 :   } else if (capitalized.contains("CEDUNA")) {
      43           0 :     diameter = 30.0;
      44           8 :   } else if (capitalized.contains("HOBART")) {
      45           0 :     diameter = 26.0;
      46           8 :   } else if (capitalized.contains("APEX")) {
      47           0 :     diameter = 12.0;
      48           8 :   } else if (capitalized.contains("ASTE")) {
      49           0 :     diameter = 10.0;
      50           8 :   } else if (capitalized.contains("NRO")) {
      51           8 :     diameter = 45.0;
      52             :   }
      53             : 
      54           8 :   return diameter;
      55           8 : }
      56             : 
      57             : template<class T, class U>
      58       54336 : U getMapValue(std::map<T, U> const mymap, T const key, U const default_value) {
      59       54336 :   auto iter = mymap.find(key);
      60       54336 :   if (iter != mymap.end()) {
      61       54336 :     return iter->second;
      62             :   } else {
      63           0 :     return default_value;
      64             :   }
      65             : }
      66             : 
      67       27168 : String getIntent(Int srctype) {
      68       27168 :   static std::map<Int, String> intent_map;
      69       27168 :   if (intent_map.size() == 0) {
      70           1 :     String sep1 = "#";
      71           1 :     String sep2 = ",";
      72           1 :     String target = "OBSERVE_TARGET";
      73           1 :     String atmcal = "CALIBRATE_ATMOSPHERE";
      74           1 :     String anycal = "CALIBRATE_SOMETHING";
      75           1 :     String onstr = "ON_SOURCE";
      76           1 :     String offstr = "OFF_SOURCE";
      77           1 :     String pswitch = "POSITION_SWITCH";
      78           1 :     String nod = "NOD";
      79           1 :     String fswitch = "FREQUENCY_SWITCH";
      80           1 :     String sigstr = "SIG";
      81           1 :     String refstr = "REF";
      82           1 :     String hot = "HOT";
      83           1 :     String warm = "WARM";
      84           1 :     String cold = "COLD";
      85           1 :     String unspecified = "UNSPECIFIED";
      86           1 :     String ftlow = "LOWER";
      87           1 :     String fthigh = "HIGHER";
      88           1 :     intent_map[0] = target + sep1 + onstr + sep2 + pswitch;
      89           1 :     intent_map[1] = target + sep1 + offstr + sep2 + pswitch;
      90           1 :     intent_map[2] = target + sep1 + onstr + sep2 + nod;
      91           1 :     intent_map[3] = target + sep1 + onstr + sep2 + fswitch + sep1 + sigstr;
      92           1 :     intent_map[4] = target + sep1 + onstr + sep2 + fswitch + sep1 + refstr;
      93           1 :     intent_map[6] = atmcal + sep1 + offstr + sep2 + unspecified;
      94           1 :     intent_map[7] = atmcal + sep1 + hot + sep2 + unspecified;
      95           1 :     intent_map[8] = atmcal + sep1 + warm + sep2 + unspecified;
      96           1 :     intent_map[9] = atmcal + sep1 + cold + sep2 + unspecified;
      97           1 :     intent_map[10] = atmcal + sep1 + onstr + sep2 + pswitch;
      98           1 :     intent_map[11] = atmcal + sep1 + offstr + sep2 + pswitch;
      99           1 :     intent_map[12] = atmcal + sep1 + onstr + sep2 + nod;
     100           1 :     intent_map[13] = atmcal + sep1 + onstr + sep2 + fswitch + sep1 + sigstr;
     101           1 :     intent_map[14] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + refstr;
     102           1 :     intent_map[20] = target + sep1 + onstr + sep2 + fswitch + sep1 + ftlow;
     103           1 :     intent_map[21] = target + sep1 + offstr + sep2 + fswitch + sep1 + ftlow;
     104           1 :     intent_map[26] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + ftlow;
     105           1 :     intent_map[27] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + ftlow;
     106           1 :     intent_map[28] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + ftlow;
     107           1 :     intent_map[29] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + ftlow;
     108           1 :     intent_map[30] = target + sep1 + onstr + sep2 + fswitch + sep1 + fthigh;
     109           1 :     intent_map[31] = target + sep1 + offstr + sep2 + fswitch + sep1 + fthigh;
     110           1 :     intent_map[36] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + fthigh;
     111           1 :     intent_map[37] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + fthigh;
     112           1 :     intent_map[38] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + fthigh;
     113           1 :     intent_map[39] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + fthigh;
     114           1 :     intent_map[90] = target + sep1 + onstr + sep2 + unspecified;
     115           1 :     intent_map[91] = target + sep1 + offstr + sep2 + unspecified;
     116           1 :     intent_map[92] = anycal + sep1 + offstr + sep2 + unspecified;
     117           1 :   }
     118       27168 :   String default_type = "UNKNOWN_INTENT";
     119       54336 :   return getMapValue(intent_map, srctype, default_type);
     120       27168 : }
     121             : 
     122       27168 : Int getSubscan(Int srctype) {
     123       27168 :   static std::map<Int, Int> subscan_map;
     124       27168 :   if (subscan_map.size() == 0) {
     125           1 :     subscan_map[0] = 1;
     126           1 :     subscan_map[1] = 2;
     127           1 :     subscan_map[2] = 1;
     128           1 :     subscan_map[3] = 1;
     129           1 :     subscan_map[4] = 2;
     130           1 :     subscan_map[6] = 1;
     131           1 :     subscan_map[7] = 2;
     132           1 :     subscan_map[8] = 3;
     133           1 :     subscan_map[9] = 4;
     134           1 :     subscan_map[10] = 5;
     135           1 :     subscan_map[11] = 6;
     136           1 :     subscan_map[12] = 7;
     137           1 :     subscan_map[13] = 8;
     138           1 :     subscan_map[14] = 9;
     139           1 :     subscan_map[20] = 1;
     140           1 :     subscan_map[21] = 2;
     141           1 :     subscan_map[26] = 1;
     142           1 :     subscan_map[27] = 2;
     143           1 :     subscan_map[28] = 3;
     144           1 :     subscan_map[29] = 4;
     145           1 :     subscan_map[30] = 3;
     146           1 :     subscan_map[31] = 4;
     147           1 :     subscan_map[36] = 5;
     148           1 :     subscan_map[37] = 6;
     149           1 :     subscan_map[38] = 7;
     150           1 :     subscan_map[39] = 8;
     151           1 :     subscan_map[90] = 1;
     152           1 :     subscan_map[91] = 2;
     153           1 :     subscan_map[92] = 1;
     154             :   }
     155       27168 :   Int default_subscan = 1;
     156       27168 :   return getMapValue(subscan_map, srctype, default_subscan);
     157             : }
     158             : 
     159             : constexpr double kDay2Sec = 86400.0;
     160             : // constexpr double kSec2Day = 1.0 / kDay2Sec;
     161             : 
     162             : // CAS-11223
     163             : // Time difference between JST and UTC is 9 hours
     164             : constexpr double kJSTOffsetHour = 9.0;
     165             : constexpr double kJSTOffsetMin = kJSTOffsetHour * 60.0;
     166             : constexpr double kJSTOffsetSec = kJSTOffsetMin * 60.0;
     167             : //inline double jst2utcHour(double jst_time) {
     168             : //  return jst_time - kJSTOffsetHour;
     169             : //}
     170       27178 : inline double jst2utcSec(double jst_time) {
     171       27178 :   return jst_time - kJSTOffsetSec;
     172             : }
     173             : }
     174             : 
     175             : using namespace casacore;
     176             : namespace casa { //# NAMESPACE CASA - BEGIN
     177             : 
     178             : using namespace sdfiller;
     179             : 
     180           2 : NRO2MSReader::NRO2MSReader(std::string const &scantable_name) :
     181           2 :   ReaderInterface(scantable_name), fp_(NULL), obs_header_(),
     182           2 :   beam_id_counter_(0), source_spw_id_counter_(0), spw_id_counter_(0),
     183           2 :   time_range_sec_(),
     184           8 :   get_antenna_row_([&](sdfiller::AntennaRecord &r) {return NRO2MSReader::getAntennaRowImpl(r);}),
     185           4 :   get_field_row_([&](sdfiller::FieldRecord &r) {return NRO2MSReader::getFieldRowImpl(r);}),
     186           4 :   get_observation_row_([&](sdfiller::ObservationRecord &r) {return NRO2MSReader::getObservationRowImpl(r);}),
     187           4 :   get_processor_row_([&](sdfiller::ProcessorRecord &r) {return NRO2MSReader::getProcessorRowImpl(r);}),
     188           6 :   get_source_row_([&](sdfiller::SourceRecord &r) {return NRO2MSReader::getSourceRowImpl(r);}),
     189          10 :   get_spw_row_([&](sdfiller::SpectralWindowRecord &r) {return NRO2MSReader::getSpectralWindowRowImpl(r);})
     190             :   {
     191             : //  std::cout << "NRO2MSReader::NRO2MSReader" << std::endl;
     192           2 : }
     193             : 
     194           4 : NRO2MSReader::~NRO2MSReader() {
     195             : //  std::cout << "NRO2MSReader::~NRO2MSReader" << std::endl;
     196             :   // to ensure file pointer is closed
     197           2 :   finalizeSpecific();
     198           4 : }
     199             : 
     200           2 : void NRO2MSReader::checkEndian() {
     201           2 :   fseek(fp_, 144, SEEK_SET) ;
     202             :   int tmp ;
     203           2 :   if (fread(&tmp, 1, sizeof(int), fp_) != sizeof(int)) {
     204           0 :     return ;
     205             :   }
     206           2 :   if ((0 < tmp)&&(tmp <= NRO_ARYMAX)) {
     207           0 :     same_endian_ = true;
     208             :   } else {
     209           2 :     same_endian_ = false;
     210             :   }
     211             : }
     212             : 
     213           2 : void NRO2MSReader::readObsHeader() {
     214           2 :   fseek(fp_, 0, SEEK_SET);
     215             : 
     216           2 :   readHeader(obs_header_.LOFIL0, 8);
     217           2 :   readHeader(obs_header_.VER0,   8);
     218           2 :   readHeader(obs_header_.GROUP0, 16);
     219           2 :   readHeader(obs_header_.PROJ0,  16);
     220           2 :   readHeader(obs_header_.SCHED0, 24);
     221           2 :   readHeader(obs_header_.OBSVR0, 40);
     222           2 :   readHeader(obs_header_.LOSTM0, 16);
     223           2 :   readHeader(obs_header_.LOETM0, 16);
     224           2 :   readHeader(obs_header_.ARYNM0);
     225           2 :   readHeader(obs_header_.NSCAN0);
     226           2 :   readHeader(obs_header_.TITLE0, 120);
     227           2 :   readHeader(obs_header_.OBJ0, 16);
     228           2 :   readHeader(obs_header_.EPOCH0, 8);
     229           2 :   readHeader(obs_header_.RA00);
     230           2 :   readHeader(obs_header_.DEC00);
     231           2 :   readHeader(obs_header_.GL00);
     232           2 :   readHeader(obs_header_.GB00);
     233           2 :   readHeader(obs_header_.NCALB0);
     234           2 :   readHeader(obs_header_.SCNCD0);
     235           2 :   readHeader(obs_header_.SCMOD0, 120);
     236           2 :   readHeader<double>(obs_header_.VEL0);
     237           2 :   readHeader(obs_header_.VREF0,  4);
     238           2 :   readHeader(obs_header_.VDEF0,  4);
     239           2 :   readHeader(obs_header_.SWMOD0, 8);
     240           2 :   readHeader<double>(obs_header_.FRQSW0);
     241           2 :   readHeader<double>(obs_header_.DBEAM0);
     242           2 :   readHeader<double>(obs_header_.MLTOF0);
     243           2 :   readHeader<double>(obs_header_.CMTQ0);
     244           2 :   readHeader<double>(obs_header_.CMTE0);
     245           2 :   readHeader<double>(obs_header_.CMTSOM0);
     246           2 :   readHeader<double>(obs_header_.CMTNODE0);
     247           2 :   readHeader<double>(obs_header_.CMTI0);
     248           2 :   readHeader(obs_header_.CMTTMO0, 24);
     249           2 :   readHeader<double>(obs_header_.SBDX0);
     250           2 :   readHeader<double>(obs_header_.SBDY0);
     251           2 :   readHeader<double>(obs_header_.SBDZ10);
     252           2 :   readHeader<double>(obs_header_.SBDZ20);
     253           2 :   readHeader<double>(obs_header_.DAZP0);
     254           2 :   readHeader<double>(obs_header_.DELP0);
     255           2 :   readHeader<int>(obs_header_.CBIND0);
     256           2 :   readHeader<int>(obs_header_.NCH0);
     257           2 :   readHeader<int>(obs_header_.CHRANGE0, 2);
     258           2 :   readHeader<double>(obs_header_.ALCTM0);
     259           2 :   readHeader<double>(obs_header_.IPTIM0);
     260           2 :   readHeader<double>(obs_header_.PA0);
     261           2 :   readHeader(obs_header_.RX0, 16, NRO_ARYMAX);
     262           2 :   readHeader<double>(obs_header_.HPBW0, NRO_ARYMAX);
     263           2 :   readHeader<double>(obs_header_.EFFA0, NRO_ARYMAX);
     264           2 :   readHeader<double>(obs_header_.EFFB0, NRO_ARYMAX);
     265           2 :   readHeader<double>(obs_header_.EFFL0, NRO_ARYMAX);
     266           2 :   readHeader<double>(obs_header_.EFSS0, NRO_ARYMAX);
     267           2 :   readHeader<double>(obs_header_.GAIN0, NRO_ARYMAX);
     268           2 :   readHeader(obs_header_.HORN0, 4, NRO_ARYMAX);
     269           2 :   readHeader(obs_header_.POLTP0, 4, NRO_ARYMAX);
     270           2 :   readHeader<double>(obs_header_.POLDR0, NRO_ARYMAX);
     271           2 :   readHeader<double>(obs_header_.POLAN0, NRO_ARYMAX);
     272           2 :   readHeader<double>(obs_header_.DFRQ0, NRO_ARYMAX);
     273           2 :   readHeader(obs_header_.SIDBD0, 4, NRO_ARYMAX);
     274           2 :   readHeader<int>(obs_header_.REFN0, NRO_ARYMAX);
     275           2 :   readHeader<int>(obs_header_.IPINT0, NRO_ARYMAX);
     276           2 :   readHeader<int>(obs_header_.MULTN0, NRO_ARYMAX);
     277           2 :   readHeader<double>(obs_header_.MLTSCF0, NRO_ARYMAX);
     278           2 :   readHeader(obs_header_.LAGWIN0, 8, NRO_ARYMAX);
     279           2 :   readHeader<double>(obs_header_.BEBW0, NRO_ARYMAX);
     280           2 :   readHeader<double>(obs_header_.BERES0, NRO_ARYMAX);
     281           2 :   readHeader<double>(obs_header_.CHWID0, NRO_ARYMAX);
     282           2 :   readHeader<int>(obs_header_.ARRY0, NRO_ARYMAX);
     283           2 :   readHeader<int>(obs_header_.NFCAL0, NRO_ARYMAX);
     284           2 :   readHeader<double>(obs_header_.F0CAL0, NRO_ARYMAX);
     285          72 :   for (size_t i = 0; i < NRO_ARYMAX; ++i) {
     286          70 :     readHeader<double>(obs_header_.FQCAL0[i], 10);
     287             :   }
     288          72 :   for (size_t i = 0; i < NRO_ARYMAX; ++i) {
     289          70 :     readHeader<double>(obs_header_.CHCAL0[i], 10);
     290             :   }
     291          72 :   for (size_t i = 0; i < NRO_ARYMAX; ++i) {
     292          70 :     readHeader<double>(obs_header_.CWCAL0[i], 10);
     293             :   }
     294           2 :   readHeader<int>(obs_header_.SCNLEN0);
     295           2 :   readHeader<int>(obs_header_.SBIND0);
     296           2 :   readHeader<int>(obs_header_.IBIT0);
     297           2 :   readHeader(obs_header_.SITE0, 8);
     298           2 :   readHeader(obs_header_.TRK_TYPE, 8);
     299           2 :   readHeader(obs_header_.SCAN_COORD, 8);
     300           2 :   readHeader<int>(obs_header_.NBEAM);
     301           2 :   readHeader<int>(obs_header_.NPOL);
     302           2 :   readHeader<int>(obs_header_.NSPWIN);
     303           2 :   readHeader<int>(obs_header_.CHMAX);
     304           2 :   readHeader(obs_header_.VERSION, 40);
     305           2 :   readHeader<int16_t>(obs_header_.ARRYTB, 36);
     306           2 :   readHeader(obs_header_.POLNAME, 3, 12);
     307             : //  readHeader(obs_header_.CDMY1, 108);
     308             :         { // Debug output
     309           4 :                 LogIO os(LogOrigin("NRODataset", "readObsHeader", WHERE) );
     310           2 :                 os << LogIO::DEBUGGING << "NRO ARRAY TABLE from NOSTAR header:" << LogIO::POST;
     311          72 :                 for (int i = 0; i < NRO_ARYMAX; ++i) {
     312          70 :                         os << LogIO::DEBUGGING << "- Array" << i << " : " << obs_header_.ARRYTB[i] << LogIO::POST;
     313             :                 }
     314           2 :                 os << LogIO::DEBUGGING << "POL NAMES:" << LogIO::POST;
     315          26 :                 for (size_t i = 0; i < 12; ++i) {
     316          24 :                         if (obs_header_.POLNAME[i][0] == '\0') continue;
     317           4 :                         os << LogIO::DEBUGGING << i << " : " << obs_header_.POLNAME[i] << LogIO::POST;
     318             :                 }
     319           2 :         }
     320           2 : }
     321             : 
     322       27172 : void NRO2MSReader::readScanData(int const irow, sdfiller::NRODataScanData &data) {
     323       27172 :   if (irow < 0) throw AipsError("Negative row number");
     324       27172 :   size_t offset = len_obs_header_ + static_cast<size_t>(irow) * obs_header_.SCNLEN0;
     325       27172 :   fseek(fp_, offset, SEEK_SET);
     326             : 
     327       27172 :   readHeader(data.LSFIL0, 4);
     328       27172 :   readHeader(data.ISCN0);
     329       27172 :   readHeader(data.LAVST0, 24);
     330       27172 :   readHeader(data.SCNTP0, 8);
     331       27172 :   readHeader(data.DSCX0);
     332       27172 :   readHeader(data.DSCY0);
     333       27172 :   readHeader(data.SCX0);
     334       27172 :   readHeader(data.SCY0);
     335       27172 :   readHeader(data.PAZ0);
     336       27172 :   readHeader(data.PEL0);
     337       27172 :   readHeader(data.RAZ0);
     338       27172 :   readHeader(data.REL0);
     339       27172 :   readHeader(data.XX0);
     340       27172 :   readHeader(data.YY0);
     341       27172 :   readHeader(data.ARRYT0, 4);
     342       27172 :   readHeader(data.TEMP0);
     343       27172 :   readHeader(data.PATM0);
     344       27172 :   readHeader(data.PH200);
     345       27172 :   readHeader(data.VWIND0);
     346       27172 :   readHeader(data.DWIND0);
     347       27172 :   readHeader(data.TAU0);
     348       27172 :   readHeader(data.TSYS0);
     349       27172 :   readHeader(data.BATM0);
     350       27172 :   readHeader(data.LINE0);
     351       27172 :   readHeader(data.IDMY1, 4);
     352       27172 :   readHeader(data.VRAD0);
     353       27172 :   readHeader(data.FRQ00);
     354       27172 :   readHeader(data.FQTRK0);
     355       27172 :   readHeader(data.FQIF10);
     356       27172 :   readHeader(data.ALCV0);
     357       81516 :   for (size_t i = 0; i < 2; ++i) {
     358       54344 :     readHeader(data.OFFCD0[i], 2);
     359             :   }
     360       27172 :   readHeader(data.IDMY0);
     361       27172 :   readHeader(data.IDMY2);
     362       27172 :   readHeader(data.DPFRQ0);
     363       27172 :   readHeader(data.ARRYSCN, 8);
     364       27172 :   readHeader(data.CDMY1, 136);
     365       27172 :   readHeader(data.SFCTR0);
     366       27172 :   readHeader(data.ADOFF0);
     367             :   // KS: use of NCH0 instead of CHMAX (2017/01/25)
     368       27172 :   readHeader(data.LDATA, obs_header_.NCH0 * obs_header_.IBIT0 / 8);
     369       27172 : }
     370             : 
     371       27168 : bool NRO2MSReader::checkScanArray(string const scan_array,
     372             :                 NROArrayData const *header_array) {
     373             :         // ARRYSCN is a string in the form, ##SS## (beam id in 2 digits, pol name, and spw id in 2 digits)
     374       27168 :         if (scan_array.size() < 6) {
     375           0 :                 throw AipsError(
     376           0 :                                 "Internal Data ERROR: insufficient length of ARRAY information from scan header");
     377             :         }
     378             :         // indices in NOSTAR data are 1-base
     379       27168 :         int const sbeam = atoi(scan_array.substr(0, 2).c_str()) -1;
     380       27168 :         string const spol = scan_array.substr(2, 2);
     381       27168 :         int const sspw = atoi(scan_array.substr(4, 2).c_str()) -1;
     382       54336 :         return (sbeam == header_array->getBeamId()
     383       54336 :                         && spol == header_array->getPolName()
     384       81504 :                         && sspw == header_array->getSpwId());
     385       27168 : }
     386             : 
     387             : 
     388       27172 : double NRO2MSReader::getMJD(string const &strtime) {
     389             :   // TODO: should be checked which time zone the time depends on
     390             :   // 2008/11/14 Takeshi Nakazato
     391       27172 :   string strYear = strtime.substr(0, 4);
     392       27172 :   string strMonth = strtime.substr(4, 2);
     393       27172 :   string strDay = strtime.substr(6, 2);
     394       27172 :   string strHour = strtime.substr(8, 2);
     395       27172 :   string strMinute = strtime.substr(10, 2);
     396       27172 :   string strSecond = strtime.substr(12, strtime.size() - 12);
     397       27172 :   unsigned int year = atoi(strYear.c_str());
     398       27172 :   unsigned int month = atoi(strMonth.c_str());
     399       27172 :   unsigned int day = atoi(strDay.c_str());
     400       27172 :   unsigned int hour = atoi(strHour.c_str());
     401       27172 :   unsigned int minute = atoi(strMinute.c_str());
     402       27172 :   double second = atof(strSecond.c_str());
     403       27172 :   Time t(year, month, day, hour, minute, second);
     404             : 
     405       54344 :   return t.modifiedJulianDay() ;
     406       27172 : }
     407             : 
     408       27168 : double NRO2MSReader::getIntMiddleTimeSec(sdfiller::NRODataScanData const &data) {
     409       27168 :   return getMJD(data.LAVST0) * kDay2Sec + 0.5 * obs_header_.IPTIM0;
     410             : }
     411             : 
     412           4 : double NRO2MSReader::getIntStartTimeSec(int const scanno) {
     413           4 :   if (scanno < 0) throw AipsError("Negative scan number");
     414           4 :   size_t offset = len_obs_header_ + static_cast<size_t>(scanno) * obs_header_.ARYNM0 * obs_header_.SCNLEN0 + 8;
     415           4 :   fseek(fp_, offset, SEEK_SET);
     416           4 :   string time_header;
     417           4 :   readHeader(time_header, 24);
     418           8 :   return getMJD(time_header) * kDay2Sec;
     419           4 : }
     420             : 
     421           2 : double NRO2MSReader::getIntEndTimeSec(int const scanno) {
     422           2 :   double interval = obs_header_.IPTIM0;
     423           2 :   return getIntStartTimeSec(scanno) + interval;
     424             : }
     425             : 
     426           2 : void NRO2MSReader::getFullTimeRange() {
     427           2 :   if (time_range_sec_.size() != 2) {
     428           2 :     time_range_sec_.resize(2);
     429             :   }
     430           2 :   time_range_sec_[0] = getIntStartTimeSec(0);
     431           2 :   time_range_sec_[1] = getIntEndTimeSec(obs_header_.NSCAN0 - 1);
     432           2 : }
     433             : 
     434           6 : double NRO2MSReader::getMiddleOfTimeRangeSec() {
     435           6 :   return 0.5 * (time_range_sec_[0] + time_range_sec_[1]);
     436             : }
     437             : 
     438           4 : double NRO2MSReader::getRestFrequency(int const spwno) {
     439           4 :   size_t offset = len_obs_header_ + static_cast<size_t>(getFirstArrayIdWithSpwID(spwno)) * obs_header_.SCNLEN0 + 184;
     440           4 :   fseek(fp_, offset, SEEK_SET);
     441             :   double restfreq_header;
     442           4 :   readHeader(restfreq_header);
     443           4 :   return restfreq_header;
     444             : }
     445             : 
     446           2 : void NRO2MSReader::constructArrayTable() {
     447           2 :   size_t array_max = NRO_ARYMAX;
     448           2 :   array_mapper_.resize(array_max);
     449           4 :         LogIO os(LogOrigin("NRODataset", "constructArrayTable", WHERE) );
     450           2 :         os << LogIO::DEBUG1 << "NRO ARRAY TABLE:" << LogIO::POST;
     451             : 
     452          72 :         for (size_t i = 0; i < array_mapper_.size(); ++i) {
     453          70 :                 array_mapper_[i].set(obs_header_.ARRYTB[i], obs_header_.POLNAME);
     454          70 :                 int beam_id = array_mapper_[i].beam_id;
     455          70 :                 int spw_id = array_mapper_[i].spw_id;
     456          70 :                 int stokes = array_mapper_[i].stokes_type;
     457          70 :                 if (array_mapper_[i].isUsed()) {
     458          32 :       if (beam_id < 0 || beam_id >= obs_header_.NBEAM
     459          32 :           || stokes == Stokes::Undefined || spw_id < 0
     460          32 :           || spw_id >= obs_header_.NSPWIN) {
     461           0 :         throw AipsError("Internal Data ERROR: inconsistent ARRAY table");
     462             :       }
     463             :       os << LogIO::DEBUG1 << "- Array " << i << " : (beam, pol, spw) = ("
     464          64 :           << beam_id << ", " << array_mapper_[i].pol_name
     465          32 :           << ", "       << spw_id << ")" << LogIO::POST;
     466             :                 }
     467             :                 else {
     468          38 :       os << LogIO::DEBUG1 << "- Array " << i << " : Unused" << LogIO::POST;
     469             :                 }
     470             :         }
     471           2 : }
     472             : 
     473           4 : string NRO2MSReader::convertVRefName(string const &vref0) {
     474           4 :   string res;
     475           4 :   if (vref0 == "LSR") {
     476           4 :     res = "LSRK";
     477           0 :   } else if (vref0 == "HEL") {
     478           0 :     res = "BARY";
     479           0 :   } else if (vref0 == "GAL") {
     480           0 :     res = "GALACTO";
     481             :   } else {
     482           0 :     res = "Undefined";
     483             :   }
     484           4 :   return res;
     485           0 : }
     486             : 
     487           4 : void NRO2MSReader::shiftFrequency(string const &vdef,
     488             :                                   double const v,
     489             :                                   std::vector<double> &freqs) {
     490           4 :   double factor = v/2.99792458e8;
     491           4 :   if (vdef == "RAD") {
     492             :     //factor = 1.0 / (1.0 + factor);
     493           4 :     factor = 1.0 - factor;
     494           0 :   } else if (vdef == "OPT") {
     495             :     //factor += 1.0;
     496           0 :     factor = 1.0 / (1.0 + factor);
     497             :   } else {
     498           0 :     cout << "vdef=" << vdef << " is not supported." << endl;
     499           0 :     factor = 1.0;
     500             :   }
     501          12 :   for (size_t i = 0; i < 2; ++i) {
     502           8 :     freqs[i] *= factor;
     503             :   }
     504           4 : }
     505             : 
     506       27168 : std::vector<double> NRO2MSReader::getSpectrum(int const irow, sdfiller::NRODataScanData const &data) {
     507             :   // size of spectrum is not (SCNLEN-HEADER_SIZE)*8/IBIT0
     508             :   // but obs_header_.NCH0 after binding
     509       27168 :   int const nchan = obs_header_.NCH0;
     510       27168 :   int const chmax_ = (obs_header_.SCNLEN0 - SCNLEN_HEADER_SIZE) * 8 / obs_header_.IBIT0;
     511       27168 :   vector<double> spec( chmax_ ) ;  // spectrum "after" binding
     512             :   // DEBUG
     513             :   //cout << "NRODataset::getSpectrum()  nchan = " << nchan << " chmax_ = " << chmax_ << endl ;
     514             : 
     515       27168 :   const int bit = obs_header_.IBIT0;   // fixed to 12 bit
     516       27168 :   double scale = data.SFCTR0;
     517             :   // DEBUG
     518             :   //cout << "NRODataset::getSpectrum()  scale = " << scale << endl ;
     519       27168 :   double offset = data.ADOFF0;
     520             :   // DEBUG
     521             :   //cout << "NRODataset::getSpectrum()  offset = " << offset << endl ;
     522             : 
     523       27168 :   if ((scale == 0.0) && (offset == 0.0)) {
     524           0 :     LogIO os( LogOrigin("NRODataset","getSpectrum",WHERE) );
     525           0 :     os << LogIO::WARN << "zero spectrum for row " << irow << LogIO::POST;
     526           0 :     if (spec.size() != (unsigned int)nchan) {
     527           0 :       spec.resize(nchan);
     528             :     }
     529           0 :     for (vector<double>::iterator i = spec.begin(); i != spec.end(); ++i) {
     530           0 :       *i = 0.0;
     531             :     }
     532           0 :     return spec;
     533           0 :   }
     534             : 
     535       27168 :   unsigned char *cdata = reinterpret_cast<unsigned char *>(const_cast<char *>(data.LDATA.c_str()));
     536       27168 :   vector<double> mscale;
     537       27168 :   mscale.resize(NRO_ARYMAX);
     538      978048 :   for (size_t i = 0; i < NRO_ARYMAX; ++i) {
     539      950880 :     mscale[i] = obs_header_.MLTSCF0[i];
     540             :   }
     541       27168 :   string sbeamno = data.ARRYT0.substr(1, data.ARRYT0.size() - 1);
     542       27168 :   int index = atoi(sbeamno.c_str()) - 1;
     543       27168 :   double dscale = mscale[index];
     544             : 
     545             :   // char -> int -> double
     546       27168 :   vector<double>::iterator iter = spec.begin();
     547             : 
     548             :   static const int shift_right[] = { 4, 0 };
     549             :   static const int start_pos[]   = { 0, 1 };
     550             :   static const int incr[]        = { 0, 3 };
     551       27168 :   int j = 0;
     552   111307296 :   for (int i = 0; i < chmax_; ++i) {
     553             :     // char -> int
     554   111280128 :     int ivalue = 0;
     555   111280128 :     if (bit == 12) {  // 12 bit qunatization
     556   111280128 :       const int ialt = i & 1;
     557   111280128 :       const int idx = j + start_pos[ialt];
     558   111280128 :       const unsigned tmp = unsigned(cdata[idx]) << 8 | cdata[idx + 1];
     559   111280128 :       ivalue = int((tmp >> shift_right[ialt]) & 0xFFF);
     560   111280128 :       j += incr[ialt];
     561             :     }
     562             : 
     563   111280128 :     if ((ivalue < 0) || (ivalue > 4096)) {
     564             :       //cerr << "NRODataset::getSpectrum()  ispec[" << i << "] is out of range" << endl ;
     565           0 :       LogIO os( LogOrigin( "NRODataset", "getSpectrum", WHERE));
     566           0 :       os << LogIO::SEVERE << "ivalue for row " << i << " is out of range" << LogIO::EXCEPTION;
     567           0 :       if (spec.size() != (unsigned int)nchan) {
     568           0 :         spec.resize(nchan);
     569             :       }
     570           0 :       for (vector<double>::iterator i = spec.begin(); i != spec.end(); ++i) {
     571           0 :         *i = 0.0;
     572             :       }
     573           0 :       return spec;
     574           0 :     }
     575             : 
     576             :     // int -> double
     577   111280128 :     *iter = (double)(ivalue * scale + offset) * dscale;
     578             :     // DEBUG
     579             :     //cout << "NRODataset::getSpectrum()  spec[" << i << "] = " << *iter << endl ;
     580   111280128 :     iter++;
     581             :   }
     582             : 
     583             :   // DEBUG
     584             :   //cout << "NRODataset::getSpectrum() end process" << endl ;
     585       27168 :   return spec;
     586       27168 : }
     587             : 
     588             : //Int NRO2MSReader::getPolNo(string const &rx) {
     589             : //  Int polno = 0;
     590             : //  // 2013/01/23 TN
     591             : //  // In NRO 45m telescope, naming convension for dual-polarization
     592             : //  // receiver is as follows:
     593             : //  //
     594             : //  //    xxxH for horizontal component,
     595             : //  //    xxxV for vertical component.
     596             : //  //
     597             : //  // Exception is H20ch1/ch2.
     598             : //  // Here, POLNO is assigned as follows:
     599             : //  //
     600             : //  //    POLNO=0: xxxH or H20ch1
     601             : //  //          1: xxxV or H20ch2
     602             : //  //
     603             : //  // For others, POLNO is always 0.
     604             : //  string last_letter = rx.substr(rx.size()-1, 1);
     605             : //  if ((last_letter == "V") || (rx == "H20ch2")) {
     606             : //    polno = 1;
     607             : //  }
     608             : //
     609             : //  return polno;
     610             : //}
     611             : 
     612           2 : void NRO2MSReader::initializeSpecific() {
     613             : //  std::cout << "NRO2MSReader::initialize" << std::endl;
     614           2 :   fp_ = fopen(STRING2CHAR(name_), "rb");
     615           2 :   if (fp_ == NULL) {
     616           0 :     throw AipsError("Input data doesn't exist or is invalid");
     617             :   }
     618           2 :   checkEndian();
     619             : 
     620           2 :   readObsHeader();
     621           2 :   getFullTimeRange();
     622           2 :   constructArrayTable();
     623           2 : }
     624             : 
     625           4 : void NRO2MSReader::finalizeSpecific() {
     626             : //  std::cout << "NRO2MSReader::finalize" << std::endl;
     627           4 :   if (fp_ != NULL) {
     628           2 :     fclose(fp_);
     629             :   }
     630           4 :   fp_ = NULL;
     631           4 : }
     632             : 
     633       27170 : size_t NRO2MSReader::getNumberOfRows() const {
     634       27170 :   int nrows = obs_header_.ARYNM0 * obs_header_.NSCAN0;
     635       27170 :   return (nrows >= 0) ? nrows : 0;
     636             : }
     637             : 
     638           8 : MDirection::Types NRO2MSReader::getDirectionFrame() const {
     639             :   MDirection::Types res;
     640           8 :   int scan_coord = obs_header_.SCNCD0;
     641             :   //std::cout << "********** SCNCD0 = " << scan_coord << std::endl;
     642           8 :   if (scan_coord == 0) { // RADEC
     643           8 :     string epoch = obs_header_.EPOCH0;
     644           8 :     if (epoch == "J2000") {
     645           8 :       res = MDirection::J2000;
     646           0 :     } else if (epoch == "B1950") {
     647           0 :       res = MDirection::B1950;
     648             :     } else {
     649           0 :       throw AipsError("Unsupported epoch.");
     650             :     }
     651           8 :   } else if (scan_coord == 1) { // LB
     652           0 :     res = MDirection::GALACTIC;
     653           0 :   } else if (scan_coord == 2) { // AZEL
     654           0 :     res = MDirection::AZEL;
     655             :   } else {
     656           0 :     throw AipsError("Unsupported epoch.");
     657             :   }
     658           8 :   return res;
     659             : }
     660             : 
     661           8 : Bool NRO2MSReader::getAntennaRowImpl(AntennaRecord &record) {
     662             : //  std::cout << "NRO2MSReader::getAntennaRowImpl" << std::endl;
     663             : 
     664           8 :   record.station = "";
     665           8 :   String header_antenna_name = obs_header_.SITE0;
     666           8 :   ostringstream oss;
     667           8 :   oss << header_antenna_name << "-BEAM" << beam_id_counter_;
     668           8 :   record.name = String(oss);
     669           8 :   record.mount = "ALT-AZ";
     670           8 :   record.dish_diameter = queryAntennaDiameter(header_antenna_name);
     671           8 :   record.type = "GROUND-BASED";
     672           8 :   record.position = MPosition(MVPosition(posx_, posy_, posz_), MPosition::ITRF);
     673             : 
     674           8 :   beam_id_counter_++;
     675           8 :   if (obs_header_.NBEAM <= beam_id_counter_) {
     676           4 :     get_antenna_row_ = [&](sdfiller::AntennaRecord &r) {return NRO2MSReader::noMoreRowImpl<AntennaRecord>(r);};
     677             :   }
     678             : 
     679           8 :   return true;
     680           8 : }
     681             : 
     682           2 : Bool NRO2MSReader::getObservationRowImpl(ObservationRecord &record) {
     683             : //  std::cout << "NRO2MSReader::getObservationRowImpl" << std::endl;
     684             : 
     685           2 :   if (record.time_range.size() != 2) {
     686           2 :     record.time_range.resize(2);
     687             :   }
     688           6 :   for (int i = 0; i < 2; ++i) {
     689             :     // 2018/05/30 TN
     690             :     // time_range should be in sec
     691             :     // CAS-11223 NRO timestamp is in JST so it should be converted to UTC
     692           4 :     record.time_range[i] = jst2utcSec(time_range_sec_[i]);
     693             :   }
     694             : 
     695           2 :   record.observer = obs_header_.OBSVR0;
     696           2 :   record.project = obs_header_.PROJ0;
     697           2 :   record.telescope_name = obs_header_.SITE0;
     698             : 
     699             :   // only one entry so redirect function pointer to noMoreRowImpl
     700           4 :   get_observation_row_ = [&](sdfiller::ObservationRecord &r) {return NRO2MSReader::noMoreRowImpl<ObservationRecord>(r);};
     701             : 
     702           2 :   return true;
     703             : }
     704             : 
     705             : 
     706           2 : Bool NRO2MSReader::getProcessorRowImpl(ProcessorRecord &/*record*/) {
     707             : //  std::cout << "NRO2MSReader::getProcessorRowImpl" << std::endl;
     708             : 
     709             :   // just add empty row once
     710             : 
     711             :   // only one entry so redirect function pointer to noMoreRowImpl
     712           4 :   get_processor_row_ = [&](sdfiller::ProcessorRecord &r) {return NRO2MSReader::noMoreRowImpl<ProcessorRecord>(r);};
     713             : 
     714           2 :   return true;
     715             : }
     716             : 
     717           4 : Bool NRO2MSReader::getSourceRowImpl(SourceRecord &record) {
     718           4 :   record.name = obs_header_.OBJ0;
     719           4 :   record.source_id = 0;
     720           4 :   record.spw_id = source_spw_id_counter_;
     721          12 :   record.direction = MDirection(
     722           8 :       Quantity(obs_header_.RA00, "rad"),
     723           8 :       Quantity(obs_header_.DEC00, "rad"),
     724           4 :       getDirectionFrame());
     725           4 :   record.proper_motion = Vector<Double>(0, 0.0);
     726           4 :   record.rest_frequency.resize(1);
     727           4 :   record.rest_frequency[0] = getRestFrequency(source_spw_id_counter_);
     728             :   //record.transition
     729           4 :   record.num_lines = 1;
     730           4 :   record.sysvel.resize(1);
     731           4 :   record.sysvel[0] = obs_header_.VEL0;
     732           4 :   double time_sec = getMiddleOfTimeRangeSec();
     733             :   // 2018/05/30 TN
     734             :   // CAS-11223
     735           4 :   record.time = jst2utcSec(time_sec);
     736             :   // 2018/05/30 TN
     737             :   // CAS-11442
     738           4 :   record.interval = time_range_sec_[1] - time_range_sec_[0];
     739             : 
     740           4 :   source_spw_id_counter_++;
     741           4 :   if (obs_header_.NSPWIN <= source_spw_id_counter_) {
     742           4 :     get_source_row_ = [&](sdfiller::SourceRecord &r) {return NRO2MSReader::noMoreRowImpl<SourceRecord>(r);};
     743             :   }
     744             : 
     745           4 :   return true;
     746             : }
     747             : 
     748           2 : Bool NRO2MSReader::getFieldRowImpl(FieldRecord &record) {
     749           2 :   record.name = obs_header_.OBJ0;
     750           2 :   record.field_id = 0;
     751             :   // 2018/05/30 TN
     752             :   // CAS-11223
     753           2 :   record.time = jst2utcSec(getMiddleOfTimeRangeSec());
     754           2 :   record.source_name = obs_header_.OBJ0;
     755           2 :   record.frame = getDirectionFrame();
     756           2 :   Matrix<Double> direction0(2, 2, 0.0);
     757           4 :   Matrix<Double> direction(direction0(IPosition(2, 0, 0), IPosition(2, 1, 0)));
     758           2 :   direction(0, 0) = obs_header_.RA00;
     759           2 :   direction(1, 0) = obs_header_.DEC00;
     760           2 :   record.direction = direction;
     761             : 
     762             :   // only one entry so redirect function pointer to noMoreRowImpl
     763           4 :   get_field_row_ = [&](sdfiller::FieldRecord &r) {return NRO2MSReader::noMoreRowImpl<FieldRecord>(r);};
     764             : 
     765           2 :   return true;
     766           2 : }
     767             : 
     768           4 : Bool NRO2MSReader::getSpectralWindowRowImpl(
     769             :     SpectralWindowRecord &record) {
     770           4 :   record.spw_id = spw_id_counter_;
     771           4 :   record.num_chan = obs_header_.NCH0;
     772             :   MFrequency::Types frame_type;
     773           4 :   Bool status = MFrequency::getType(frame_type, convertVRefName(obs_header_.VREF0));
     774           4 :   if (!status) {
     775           0 :     frame_type = MFrequency::N_Types;
     776             :   }
     777           4 :   record.meas_freq_ref = frame_type;
     778             : 
     779           4 :   NRODataScanData scan_data;
     780           4 :   int spw_id_array = getFirstArrayIdWithSpwID(spw_id_counter_);
     781           4 :   readScanData(spw_id_array, scan_data);
     782           4 :   double freq_offset = scan_data.FRQ00 - obs_header_.F0CAL0[spw_id_array];
     783           4 :   std::vector<double> freqs(2, freq_offset);
     784           4 :   std::vector<double> chcal(2);
     785          12 :   for (size_t i = 0; i < 2; ++i) {
     786           8 :     freqs[i] += obs_header_.FQCAL0[spw_id_array][i];
     787           8 :     chcal[i]  = obs_header_.CHCAL0[spw_id_array][i];
     788             :   }
     789             :   //-------------(change 2016/9/23)---------
     790           4 :   shiftFrequency(obs_header_.VDEF0, obs_header_.VEL0, freqs);
     791             :   //-------------(end change 2016/9/23)-----
     792           4 :   double band_width = freqs[1] - freqs[0];
     793           4 :   double chan_width = band_width / (chcal[1] - chcal[0]);
     794           4 :   if (scan_data.FQIF10 > 0.0) { // USB
     795           4 :     double tmp = freqs[1];
     796           4 :     freqs[1] = freqs[0];
     797           4 :     freqs[0] = tmp;
     798           4 :     chan_width *= -1.0;
     799             :   }
     800           4 :   record.refpix = chcal[0] - 1; // 0-based
     801           4 :   record.refval = freqs[0];
     802           4 :   record.increment = chan_width;
     803             : 
     804           4 :   spw_id_counter_++;
     805           4 :   if (obs_header_.NSPWIN <= spw_id_counter_) {
     806           4 :     get_spw_row_ = [&](sdfiller::SpectralWindowRecord &r) {return NRO2MSReader::noMoreRowImpl<SpectralWindowRecord>(r);};
     807             :   }
     808             : 
     809           4 :   return true;
     810           4 : }
     811             : 
     812       27168 : Bool NRO2MSReader::getData(size_t irow, DataRecord &record) {
     813             : //  std::cout << "NRO2MSReader::getData(irow=" << irow << ")" << std::endl;
     814             : 
     815       27168 :   if (irow >= getNumberOfRows()) {
     816           0 :     return false;
     817             :   }
     818             : 
     819             : //  std::cout << "Accessing row " << irow << std::endl;
     820       27168 :   NRODataScanData scan_data;
     821       27168 :   readScanData(irow, scan_data);
     822             : 
     823             :   // Verify Array INFO in scan header
     824       27168 :   string array_number = scan_data.ARRYT0.substr(1, scan_data.ARRYT0.size() - 1);
     825       27168 :   size_t const array_id = atoi(array_number.c_str()) - 1; // 1-base -> 0-base
     826       27168 :   if (!checkScanArray(scan_data.ARRYSCN, &array_mapper_[array_id])) {
     827           0 :           throw AipsError("Internal Data ERROR: inconsistent ARRAY information in scan header");
     828             :   }
     829             : 
     830             :   // 2018/05/30 TN
     831             :   // CAS-11223
     832       27168 :   record.time = jst2utcSec(getIntMiddleTimeSec(scan_data));
     833       27168 :   record.interval = obs_header_.IPTIM0;
     834             : //  std::cout << "TIME=" << record.time << " INTERVAL=" << record.interval
     835             : //      << std::endl;
     836             : 
     837       27168 :   Int srctype = (scan_data.SCNTP0 == "ON") ? 0 : 1;
     838       27168 :   record.intent = getIntent(srctype);
     839       27168 :   record.scan = (Int)scan_data.ISCN0;
     840       27168 :   record.subscan = getSubscan(srctype);
     841       27168 :   record.field_id = 0;
     842             : //  Int ndata_per_ant = obs_header_.NPOL * obs_header_.NSPWIN;
     843       27168 :   record.antenna_id = (Int) getNROArrayBeamId(array_id); //(irow / ndata_per_ant % obs_header_.NBEAM);
     844       27168 :   record.direction_vector(0) = scan_data.SCX0;
     845       27168 :   record.direction_vector(1) = scan_data.SCY0;
     846       27168 :   record.scan_rate = 0.0;
     847       27168 :   record.feed_id = (Int)0;
     848       27168 :   record.spw_id = (Int) getNROArraySpwId(array_id);//(irow % obs_header_.NSPWIN);
     849             : //  Int ndata_per_scan = obs_header_.NBEAM * obs_header_.NPOL * obs_header_.NSPWIN;
     850       27168 :   record.pol = getNROArrayPol(array_id); //getPolNo(obs_header_.RX0[irow % ndata_per_scan]);
     851       27168 :   record.pol_type = "linear";
     852             : 
     853             : //  std::cout << "set data size to " << num_chan_map_[record.spw_id] << " shape "
     854             : //      << record.data.shape() << std::endl;
     855       27168 :   record.setDataSize(obs_header_.NCH0);
     856       27168 :   auto const spectrum = getSpectrum(irow, scan_data);
     857       27168 :   record.data.resize(spectrum.size());
     858       27168 :   std::copy(spectrum.cbegin(), spectrum.cend(), record.data.begin());
     859       27168 :   size_t flag_len = obs_header_.NCH0;
     860   111307296 :   for (size_t i = 0; i < flag_len; ++i) {
     861   111280128 :     record.flag(i) = false;
     862             :   }
     863       27168 :   record.flag_row = false;
     864             : 
     865             : //    std::cout << "set tsys size to " << tsys_column_.shape(index)[0]
     866             : //        << " shape " << record.tsys.shape() << std::endl;
     867       27168 :   record.setTsysSize(1);
     868       27168 :   record.tsys(0) = scan_data.TSYS0;
     869             : 
     870       27168 :   record.temperature = scan_data.TEMP0 + 273.15; // Celsius to Kelvin
     871       27168 :   record.pressure = scan_data.PATM0;
     872       27168 :   record.rel_humidity = scan_data.PH200;
     873       27168 :   record.wind_speed = scan_data.VWIND0;
     874       27168 :   record.wind_direction = scan_data.DWIND0;
     875             : 
     876       27168 :   return true;
     877       27168 : }
     878             : 
     879             : } //# NAMESPACE CASA - END

Generated by: LCOV version 1.16