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

Generated by: LCOV version 1.16