Line data Source code
1 : /* 2 : * NROReader.h 3 : * 4 : * Created on: May 9, 2016 5 : * Author: wataru kawasaki 6 : */ 7 : 8 : #ifndef SINGLEDISH_FILLER_NRO2MSREADER_H_ 9 : #define SINGLEDISH_FILLER_NRO2MSREADER_H_ 10 : 11 : #define STRING2CHAR(s) const_cast<char *>((s).c_str()) 12 : 13 : #include <casacore/measures/Measures/Stokes.h> 14 : #include <casacore/tables/Tables/Table.h> 15 : #include <casacore/tables/Tables/ScaColDesc.h> 16 : #include <casacore/tables/Tables/SetupNewTab.h> 17 : 18 : #include <singledishfiller/Filler/ReaderInterface.h> 19 : #include <singledishfiller/Filler/NROData.h> 20 : #include <string> 21 : #include <memory> 22 : #include <functional> 23 : 24 : using namespace std; 25 : 26 : namespace casa { //# NAMESPACE CASA - BEGIN 27 : 28 : // forward declaration 29 : class NROOptionalTables; 30 : 31 : class NRO2MSReader final : public ReaderInterface { 32 : public: 33 : // NROOptionalTables generates optional tables 34 : // required for NRO data 35 : using OptionalTables = NROOptionalTables; 36 : 37 : NRO2MSReader(std::string const &scantable_name); 38 : virtual ~NRO2MSReader(); 39 : 40 : // get number of rows 41 : size_t getNumberOfRows() const override; 42 : 43 : casacore::MDirection::Types getDirectionFrame() const override; 44 : 45 0 : casacore::Bool isFloatData() const override { 46 0 : return true; 47 : } 48 : 49 0 : casacore::String getDataUnit() const override { 50 0 : return "K"; 51 : } 52 : 53 : // to get OBSERVATION table 54 0 : casacore::Bool getObservationRow(sdfiller::ObservationRecord &record) override { 55 : POST_START; 56 0 : casacore::Bool return_value = get_observation_row_(record); 57 : POST_END; 58 0 : return return_value; 59 : } 60 : 61 : // to get ANTENNA table 62 0 : casacore::Bool getAntennaRow(sdfiller::AntennaRecord &record) override { 63 : POST_START; 64 0 : casacore::Bool return_value = get_antenna_row_(record); 65 : POST_END; 66 0 : return return_value; 67 : } 68 : 69 : // to get PROCESSOR table 70 0 : casacore::Bool getProcessorRow(sdfiller::ProcessorRecord &record) override { 71 : POST_START; 72 0 : casacore::Bool return_value = get_processor_row_(record); 73 : POST_END; 74 0 : return return_value; 75 : } 76 : 77 : // to get SOURCE table 78 0 : casacore::Bool getSourceRow(sdfiller::SourceRecord &record) override { 79 : POST_START; 80 0 : casacore::Bool return_value = get_source_row_(record); 81 : POST_END; 82 0 : return return_value; 83 : } 84 : 85 : // to get FIELD table 86 0 : casacore::Bool getFieldRow(sdfiller::FieldRecord &record) override { 87 : POST_START; 88 0 : casacore::Bool return_value = get_field_row_(record); 89 : POST_END; 90 0 : return return_value; 91 : } 92 : 93 : // to get SOURCE table 94 0 : casacore::Bool getSpectralWindowRow(sdfiller::SpectralWindowRecord &record) override { 95 : POST_START; 96 0 : casacore::Bool return_value = get_spw_row_(record); 97 : POST_END; 98 0 : return return_value; 99 : } 100 : 101 : // for DataAccumulator 102 : casacore::Bool getData(size_t irow, sdfiller::DataRecord &record) override; 103 : 104 : protected: 105 : void initializeSpecific() override; 106 : void finalizeSpecific() override; 107 : 108 : private: 109 : FILE *fp_; 110 : sdfiller::NRODataObsHeader obs_header_; 111 : void readObsHeader(); 112 : void readScanData(int const irow, sdfiller::NRODataScanData &data); 113 : void checkEndian(); 114 : template<typename T> 115 0 : void convertEndian(T &value) { 116 0 : char volatile *first = reinterpret_cast<char volatile *>(&value) ; 117 0 : char volatile *last = first + sizeof(T) ; 118 0 : std::reverse(first, last) ; 119 0 : } 120 : 121 : bool same_endian_; 122 : 123 : template<typename T> 124 0 : void readHeader(T &v) { 125 0 : if ((int)fread(&v, 1, sizeof(T), fp_) != sizeof(T)) { 126 0 : cout << "read failed." << endl; 127 : } 128 0 : if (!same_endian_) { 129 0 : convertEndian(v); 130 : } 131 0 : } 132 : 133 : template<typename T> 134 0 : void readHeader(T *v, size_t numArray) { 135 0 : for (size_t i = 0; i < numArray; ++i) { 136 0 : readHeader<T>(v[i]); 137 : } 138 0 : } 139 : 140 0 : void readHeader(string &v, size_t strLength) { 141 0 : v.resize(strLength); 142 0 : if (fread(STRING2CHAR(v), 1, strLength, fp_) != strLength) { 143 0 : cout << "read failed." << endl; 144 : } 145 0 : v.resize(strlen(v.c_str())); // remove trailing null characters 146 0 : } 147 : 148 0 : void readHeader(string *v, size_t strLength, size_t numArray) { 149 0 : for (size_t i = 0; i < numArray; ++i) { 150 0 : readHeader(v[i], strLength); 151 : } 152 0 : } 153 : 154 : struct NROArrayData { 155 : int beam_id=-1; 156 : casacore::Stokes::StokesTypes stokes_type = casacore::Stokes::Undefined; 157 : string pol_name=""; 158 : int spw_id=-1; 159 : bool is_used=false; 160 0 : void set(int16_t const arr_data, string const *pol_data) { 161 : // indices in NOSTAR data are 1-base 162 0 : if (arr_data < 1101) { 163 0 : is_used = false; 164 0 : beam_id = -1; 165 0 : spw_id = -1; 166 0 : pol_name = ""; 167 0 : stokes_type = casacore::Stokes::Undefined; 168 0 : return; 169 : } 170 0 : is_used = true; 171 0 : beam_id = static_cast<int>(arr_data/1000) - 1; 172 0 : int pol_id = static_cast<int>((arr_data % 1000)/100) - 1; 173 0 : spw_id = static_cast<int>(arr_data % 100) -1; 174 0 : pol_name = pol_data[pol_id]; 175 0 : stokes_type = casacore::Stokes::type(pol_name); 176 0 : if (stokes_type == casacore::Stokes::Undefined) { 177 0 : throw casacore::AipsError("Got unsupported polarization type\n"); 178 : } 179 : } 180 0 : int getBeamId() const { 181 0 : if (beam_id < 0) 182 0 : throw casacore::AipsError("Array data is not set yet\n"); 183 0 : return beam_id;} 184 0 : casacore::Stokes::StokesTypes getPol() const { 185 0 : if (stokes_type == casacore::Stokes::Undefined) 186 0 : throw casacore::AipsError("Array data is not set yet\n"); 187 0 : return stokes_type;} 188 0 : int getSpwId() const { 189 0 : if (spw_id < 0) 190 0 : throw casacore::AipsError("Array data is not set yet\n"); 191 0 : return spw_id;} 192 0 : string getPolName() const { 193 0 : if (pol_name.size() == 0) 194 0 : throw casacore::AipsError("Array data is not set yet\n"); 195 0 : return pol_name;} 196 0 : bool isUsed() const { 197 0 : return is_used; 198 : } 199 : }; 200 : 201 : std::vector<NROArrayData> array_mapper_; 202 : 203 : void constructArrayTable(); 204 : bool checkScanArray(string const scan_array, NROArrayData const *header_array); 205 : // Returns the first array ID whose SPW ID is spwid. 206 0 : int getFirstArrayIdWithSpwID(int spwid) { 207 0 : for (int iarr = 0; iarr < obs_header_.ARYNM0 ; ++iarr) { 208 0 : if (spwid == array_mapper_[iarr].spw_id) { 209 0 : return iarr; 210 : } 211 : } 212 : // no array with spwid found 213 0 : throw casacore::AipsError("Internal ERROR: Could not find array ID corresponds to an SPW ID\n"); 214 : } 215 : 216 : int beam_id_counter_; 217 : int source_spw_id_counter_; 218 : int spw_id_counter_; 219 : casacore::Vector<casacore::Double> time_range_sec_; 220 : int const len_obs_header_ = 15136; 221 : double getMJD(string const &time); 222 : double getIntMiddleTimeSec(sdfiller::NRODataScanData const &data); 223 : double getIntStartTimeSec(int const scanno); 224 : double getIntEndTimeSec(int const scanno); 225 : void getFullTimeRange(); 226 : double getMiddleOfTimeRangeSec(); 227 : 228 : casacore::Double const posx_ = -3.8710235e6; 229 : casacore::Double const posy_ = 3.4281068e6; 230 : casacore::Double const posz_ = 3.7240395e6; 231 : 232 : double getRestFrequency(int const spwno); 233 : string convertVRefName(string const &vref0); 234 : void shiftFrequency(string const &vdef, 235 : double const v, 236 : std::vector<double> &freqs); 237 : 238 : std::vector<double> getSpectrum(int const irow, sdfiller::NRODataScanData const &data); 239 : // casacore::Int getPolNo(string const &rx); 240 : 241 : std::function<casacore::Bool(sdfiller::AntennaRecord &)> get_antenna_row_; 242 : std::function<casacore::Bool(sdfiller::FieldRecord &)> get_field_row_; 243 : std::function<casacore::Bool(sdfiller::ObservationRecord &)> get_observation_row_; 244 : std::function<casacore::Bool(sdfiller::ProcessorRecord &)> get_processor_row_; 245 : std::function<casacore::Bool(sdfiller::SourceRecord &)> get_source_row_; 246 : std::function<casacore::Bool(sdfiller::SpectralWindowRecord &)> get_spw_row_; 247 : 248 : casacore::Bool getAntennaRowImpl(sdfiller::AntennaRecord &record); 249 : casacore::Bool getFieldRowImpl(sdfiller::FieldRecord &record); 250 : casacore::Bool getObservationRowImpl(sdfiller::ObservationRecord &record); 251 : casacore::Bool getProcessorRowImpl(sdfiller::ProcessorRecord &record); 252 : casacore::Bool getSourceRowImpl(sdfiller::SourceRecord &record); 253 : casacore::Bool getSpectralWindowRowImpl(sdfiller::SpectralWindowRecord &record); 254 : 255 : template<class _Record> 256 0 : casacore::Bool noMoreRowImpl(_Record &) { 257 : POST_START;POST_END; 258 0 : return false; 259 : } 260 : 261 : // methods that are only accessible from NROOptionalTables 262 0 : int getNROArraySize() const { 263 : // return obs_header_.ARYNM0; //obs_header_.NBEAM * obs_header_.NPOL * obs_header_.NSPWIN; 264 0 : return NRO_ARYMAX; 265 : } 266 : int getNRONumBeam() const { 267 : return obs_header_.NBEAM; 268 : } 269 : int getNRONumPol() const { 270 : return obs_header_.NPOL; 271 : } 272 : int getNRONumSpw() const { 273 : return obs_header_.NSPWIN; 274 : } 275 : 276 0 : bool isNROArrayUsed(int array_id) const { 277 0 : return array_mapper_[array_id].isUsed(); 278 : } 279 0 : int getNROArrayBeamId(int array_id) const { 280 : // assert(array_id >= 0 && array_id < getNROArraySize()); 281 0 : return array_mapper_[array_id].getBeamId(); 282 : } 283 0 : casacore::Stokes::StokesTypes getNROArrayPol(int array_id) const { 284 : // assert(array_id >= 0 && array_id < getNROArraySize()); 285 0 : return array_mapper_[array_id].getPol(); 286 : } 287 0 : int getNROArraySpwId(int array_id) const { 288 : // assert(array_id >= 0 && array_id < getNROArraySize()); 289 0 : return array_mapper_[array_id].getSpwId(); 290 : } 291 : 292 : // friend: NROOptionalTables 293 : friend NROOptionalTables; 294 : }; 295 : 296 : // OptionalTables class for NRO data 297 : class NROOptionalTables { 298 : public: 299 0 : static void Generate(casacore::Table &table, NRO2MSReader const &reader) { 300 : // generate NRO_ARRAY table 301 0 : Generate_NRO_ARRAY(table, reader); 302 0 : } 303 : 304 : private: 305 0 : static void Generate_NRO_ARRAY(casacore::Table &table, NRO2MSReader const &reader) { 306 0 : casacore::String const nro_tablename = "NRO_ARRAY"; 307 : 308 0 : casacore::TableDesc td(nro_tablename, casacore::TableDesc::Scratch); 309 0 : td.addColumn(casacore::ScalarColumnDesc<casacore::Int>("ARRAY")); 310 0 : td.addColumn(casacore::ScalarColumnDesc<casacore::Int>("BEAM")); 311 0 : td.addColumn(casacore::ScalarColumnDesc<casacore::Int>("POLARIZATION")); 312 0 : td.addColumn(casacore::ScalarColumnDesc<casacore::Int>("SPECTRAL_WINDOW")); 313 0 : casacore::String tabname = table.tableName() + "/" + nro_tablename; 314 0 : casacore::SetupNewTable newtab(tabname, td, casacore::Table::Scratch); 315 0 : table.rwKeywordSet().defineTable(nro_tablename, 316 0 : casacore::Table(newtab, reader.getNROArraySize())); 317 : 318 0 : casacore::Table nro_table = table.rwKeywordSet().asTable(nro_tablename); 319 0 : casacore::ScalarColumn<int> arr(nro_table, "ARRAY"); 320 0 : casacore::ScalarColumn<int> bea(nro_table, "BEAM"); 321 0 : casacore::ScalarColumn<int> pol(nro_table, "POLARIZATION"); 322 0 : casacore::ScalarColumn<int> spw(nro_table, "SPECTRAL_WINDOW"); 323 0 : for (int iarr = 0; iarr < reader.getNROArraySize(); ++iarr) { 324 0 : arr.put(iarr, iarr); 325 0 : if (reader.isNROArrayUsed(iarr)) { 326 0 : bea.put(iarr, reader.getNROArrayBeamId(iarr)); 327 0 : pol.put(iarr, reader.getNROArrayPol(iarr)); 328 0 : spw.put(iarr, reader.getNROArraySpwId(iarr)); 329 : } else { 330 : // array is not used, fill with -1 331 0 : bea.put(iarr, -1); 332 0 : pol.put(iarr, -1); 333 0 : spw.put(iarr, -1); 334 : } 335 : } 336 0 : } 337 : }; 338 : 339 : } //# NAMESPACE CASA - END 340 : 341 : #endif /* SINGLEDISH_FILLER_NRO2MSREADER_H_ */