ScantableIterator.h

Go to the documentation of this file.
00001 /*
00002  * ScantableIterator.h
00003  *
00004  *  Created on: Jan 28, 2016
00005  *      Author: nakazato
00006  */
00007 
00008 #ifndef SINGLEDISH_FILLER_SCANTABLEITERATOR_H_
00009 #define SINGLEDISH_FILLER_SCANTABLEITERATOR_H_
00010 
00011 #include <singledish/Filler/FillerUtil.h>
00012 #include <singledish/Filler/FieldRecord.h>
00013 #include <singledish/Filler/SourceRecord.h>
00014 #include <singledish/Filler/SpectralWindowRecord.h>
00015 #include <singledish/Filler/SysCalRecord.h>
00016 
00017 #include <casacore/casa/Arrays/Vector.h>
00018 #include <casacore/casa/Utilities/Compare.h>
00019 #include <casacore/casa/Utilities/Sort.h>
00020 
00021 #include <casacore/measures/Measures/MFrequency.h>
00022 
00023 #include <casacore/tables/Tables/Table.h>
00024 #include <casacore/tables/Tables/ScalarColumn.h>
00025 #include <casacore/tables/Tables/ArrayColumn.h>
00026 #include <casacore/tables/TaQL/ExprNode.h>
00027 
00028 using namespace casacore;
00029 
00030 namespace {
00031 template<class T>
00032 inline void getDataRangePerId(Vector<uInt> const &index_list,
00033     Vector<T> const &id_list, size_t start,
00034     size_t end, std::map<T, Block<uInt> > &range_index) {
00035   uInt id_prev = id_list[index_list[start]];
00036   uInt id_min = index_list[start];
00037   uInt id_max = 0;
00038   Block < uInt > current_index(2);
00039   for (uInt i = start + 1; i < end; ++i) {
00040     uInt j = index_list[i];
00041     uInt current_id = id_list[j];
00042 //      std::cout << "weather_id = " << weather_id << " id_prev = " << id_prev
00043 //          << " time range (" << time_min << "," << time_max << ")" << std::endl;
00044     if (current_id != id_prev) {
00045       id_max = index_list[i - 1];
00046       current_index[0] = id_min;
00047       current_index[1] = id_max;
00048       range_index[id_prev] = current_index;
00049 
00050       id_prev = current_id;
00051       id_min = j;
00052     }
00053   }
00054   uInt last_id = id_list[index_list[end - 1]];
00055   if (range_index.find(last_id) == range_index.end()) {
00056     id_max = index_list[end - 1];
00057     current_index[0] = id_min;
00058     current_index[1] = id_max;
00059     range_index[last_id] = current_index;
00060   }
00061 }
00062 
00063 }
00064 
00065 namespace casa { //# NAMESPACE CASA - BEGIN
00066 
00067 class ScantableIteratorInterface {
00068 public:
00069   ScantableIteratorInterface(Table const &table) :
00070       current_iter_(0), main_table_(table), num_iter_(0) {
00071   }
00072   virtual ~ScantableIteratorInterface() {
00073   }
00074   void initialize(size_t num_iter) {
00075     num_iter_ = num_iter;
00076     current_iter_ = 0;
00077   }
00078   bool moreData() const {
00079     return current_iter_ < num_iter_;
00080   }
00081   void next() {
00082     ++current_iter_;
00083   }
00084 
00085 protected:
00086   size_t current_iter_;
00087   Table const main_table_;
00088 
00089 private:
00090   size_t num_iter_;
00091 };
00092 
00093 class ScantableFrequenciesIterator: public ScantableIteratorInterface {
00094 public:
00095   typedef std::map<Int, Int> Product;
00096   ScantableFrequenciesIterator(Table const &table) :
00097       ScantableIteratorInterface(table) {
00098     TableRecord const &header = main_table_.keywordSet();
00099     sub_table_ = header.asTable("FREQUENCIES");
00100     //size_t nrow = sub_table_.nrow();
00101     ROScalarColumn < uInt > ifno_column(main_table_, "IFNO");
00102     Vector < uInt > ifno_list = ifno_column.getColumn();
00103     Sort sorter;
00104     sorter.sortKey(ifno_list.data(), TpUInt);
00105     Vector < uInt > index_vector;
00106     uInt n = sorter.sort(index_vector, ifno_list.nelements(),
00107         Sort::HeapSort | Sort::NoDuplicates);
00108 
00109     initialize(n);
00110     ifno_list_.resize(n);
00111     for (uInt i = 0; i < n; ++i) {
00112       ifno_list_[i] = ifno_list[index_vector[i]];
00113     }
00114 
00115     ROScalarColumn < uInt > freq_id_column(main_table_, "FREQ_ID");
00116 
00117     // attach columns
00118     id_column_.attach(sub_table_, "ID");
00119     refpix_column_.attach(sub_table_, "REFPIX");
00120     refval_column_.attach(sub_table_, "REFVAL");
00121     increment_column_.attach(sub_table_, "INCREMENT");
00122     id_list_ = id_column_.getColumn();
00123   }
00124   virtual ~ScantableFrequenciesIterator() {
00125   }
00126 
00127   void getEntry(sdfiller::SpectralWindowRecord &record) {
00128     size_t const irow = current_iter_;
00129 //    std::cout << "getEntry for row " << irow << std::endl;
00130     Int spw_id = ifno_list_[irow];
00131     Table subtable = main_table_(main_table_.col("IFNO") == (uInt) spw_id, 1);
00132     ROScalarColumn < uInt > freq_id_column(subtable, "FREQ_ID");
00133     uInt freq_id = freq_id_column(0);
00134     Int jrow = -1;
00135     for (uInt i = 0; i < id_list_.size(); ++i) {
00136       if (id_list_[i] == freq_id) {
00137         jrow = (Int) i;
00138         break;
00139       }
00140     }
00141     ROArrayColumn<uChar> flag_column(subtable, "FLAGTRA");
00142     Int num_chan = flag_column.shape(0)[0];
00143     String freq_frame = sub_table_.keywordSet().asString("BASEFRAME");
00144     MFrequency::Types frame_type;
00145     Bool status = MFrequency::getType(frame_type, freq_frame);
00146     if (!status) {
00147       frame_type = MFrequency::N_Types;
00148     }
00149     Double refpix = refpix_column_(jrow);
00150     Double refval = refval_column_(jrow);
00151     Double increment = increment_column_(jrow);
00152 //    std::cout << "spw " << spw_id << " nchan " << num_chan << " mfr "
00153 //        << (Int) frame_type << " (" << freq_frame << ") ref " << refpix << ", "
00154 //        << refval << ", " << increment << std::endl;
00155     record.spw_id = spw_id;
00156     record.num_chan = num_chan;
00157     record.meas_freq_ref = frame_type;
00158     record.refpix = refpix;
00159     record.refval = refval;
00160     record.increment = increment;
00161 
00162     // update product
00163     product_[spw_id] = num_chan;
00164   }
00165   virtual void getProduct(Product *p) {
00166     if (p) {
00167       for (auto iter = product_.begin(); iter != product_.end(); ++iter) {
00168         (*p)[iter->first] = iter->second;
00169       }
00170     }
00171   }
00172 
00173 private:
00174   Table sub_table_;
00175   ScalarColumn<uInt> id_column_;
00176   ScalarColumn<Double> refpix_column_;
00177   ScalarColumn<Double> refval_column_;
00178   ScalarColumn<Double> increment_column_;
00179   Vector<uInt> ifno_list_;
00180   Vector<uInt> id_list_;
00181   Product product_;
00182 };
00183 
00184 class ScantableFieldIterator: public ScantableIteratorInterface {
00185 public:
00186   typedef std::map<String, Int> Product;
00187   ScantableFieldIterator(Table const &table) :
00188       ScantableIteratorInterface(table), row_list_(), is_reserved_(), field_column_(
00189           main_table_, "FIELDNAME"), source_column_(main_table_, "SRCNAME"), time_column_(
00190           main_table_, "TIME"), direction_column_(main_table_, "SRCDIRECTION"), scanrate_column_(
00191           main_table_, "SCANRATE"), direction_storage_(2, 2, 0.0) {
00192     Vector < String > field_name_list = field_column_.getColumn();
00193     Sort sorter;
00194     sorter.sortKey(field_name_list.data(), TpString);
00195     uInt n = sorter.sort(row_list_, field_name_list.size(),
00196         Sort::QuickSort | Sort::NoDuplicates);
00197     is_reserved_.resize(n);
00198     is_reserved_ = False;
00199     initialize(n);
00200   }
00201 
00202   virtual ~ScantableFieldIterator() {
00203   }
00204 
00205   void getEntry(sdfiller::FieldRecord &record) {
00206     uInt const irow = row_list_[current_iter_];
00207     String field_name_with_id = field_column_(irow);
00208     auto pos = field_name_with_id.find("__");
00209     auto defaultFieldId =
00210         [&]() {
00211           Int my_field_id = 0;
00212           while (is_reserved_[my_field_id] && (uInt)my_field_id < is_reserved_.size()) {
00213             my_field_id++;
00214           }
00215           if ((uInt)my_field_id >= is_reserved_.size()) {
00216             throw AipsError("Internal inconsistency in FIELD_ID numbering");
00217           }
00218           is_reserved_[my_field_id] = True;
00219           return my_field_id;
00220         };
00221     if (pos != String::npos) {
00222       record.name = field_name_with_id.substr(0, pos);
00223       Int field_id = String::toInt(field_name_with_id.substr(pos + 2));
00224       if (field_id < 0) {
00225         record.field_id = defaultFieldId();
00226       } else if ((uInt) field_id >= is_reserved_.size()
00227           || !is_reserved_[field_id]) {
00228         record.field_id = field_id;
00229         is_reserved_[field_id] = True;
00230       } else {
00231         record.field_id = defaultFieldId();
00232       }
00233     } else {
00234       record.name = field_name_with_id;
00235       record.field_id = defaultFieldId();
00236     }
00237     record.time = time_column_(irow) * 86400.0;
00238     record.source_name = source_column_(irow);
00239     record.frame = MDirection::J2000;
00240     Matrix < Double
00241         > direction(direction_storage_(IPosition(2, 0, 0), IPosition(2, 1, 0)));
00242 //    std::cout << "direction = " << direction << " (shape " << direction.shape()
00243 //        << ")" << std::endl;
00244     direction_storage_.column(0) = direction_column_(irow);
00245     if (scanrate_column_.isDefined(irow)) {
00246       Vector < Double > scan_rate = scanrate_column_(irow);
00247       if (anyNE(scan_rate, 0.0)) {
00248         direction_storage_.column(1) = scan_rate;
00249         direction.reference(direction_storage_);
00250       }
00251     }
00252 //    std::cout << "direction = " << direction << " (shape " << direction.shape()
00253 //        << ")" << std::endl;
00254     record.direction = direction;
00255 
00256     // update product
00257     product_[field_name_with_id] = record.field_id;
00258   }
00259   virtual void getProduct(Product *p) {
00260     if (p) {
00261       for (auto iter = product_.begin(); iter != product_.end(); ++iter) {
00262         (*p)[iter->first] = iter->second;
00263       }
00264     }
00265   }
00266 
00267 private:
00268   Vector<uInt> row_list_;
00269   Vector<Bool> is_reserved_;
00270   ROScalarColumn<String> field_column_;
00271   ROScalarColumn<String> source_column_;
00272   ROScalarColumn<Double> time_column_;
00273   ArrayColumn<Double> direction_column_;
00274   ArrayColumn<Double> scanrate_column_;
00275   Matrix<Double> direction_storage_;
00276   Product product_;
00277 };
00278 
00279 class ScantableSourceIterator: public ScantableIteratorInterface {
00280 public:
00281   typedef void * Product;
00282   ScantableSourceIterator(Table const &table) :
00283       ScantableIteratorInterface(table), name_column_(main_table_, "SRCNAME"), direction_column_(
00284           main_table_, "SRCDIRECTION"), proper_motion_column_(main_table_,
00285           "SRCPROPERMOTION"), sysvel_column_(main_table_, "SRCVELOCITY"), molecule_id_column_(
00286           main_table_, "MOLECULE_ID"), ifno_column_(main_table_, "IFNO"), molecules_table_(), row_list_(), source_id_map_() {
00287     TableRecord const &header = main_table_.keywordSet();
00288     molecules_table_ = header.asTable("MOLECULES");
00289     restfrequency_column_.attach(molecules_table_, "RESTFREQUENCY");
00290     molecule_name_column_.attach(molecules_table_, "NAME");
00291     Vector < String > source_name_list = name_column_.getColumn();
00292     Vector < uInt > ifno_list = ifno_column_.getColumn();
00293     Sort sorter;
00294     sorter.sortKey(source_name_list.data(), TpString);
00295     Vector < uInt > unique_vector;
00296     uInt num_unique = sorter.sort(unique_vector, source_name_list.size(),
00297         Sort::QuickSort | Sort::NoDuplicates);
00298     for (uInt i = 0; i < num_unique; ++i) {
00299       source_id_map_[name_column_(unique_vector[i])] = (Int) i;
00300     }
00301     Sort sorter2;
00302     sorter2.sortKey(source_name_list.data(), TpString);
00303     sorter2.sortKey(ifno_list.data(), TpUInt);
00304     unique_vector.resize();
00305     num_unique = sorter2.sort(row_list_, source_name_list.size(),
00306         Sort::QuickSort | Sort::NoDuplicates);
00307 //    for (uInt i = 0; i < num_unique; ++i) {
00308 //      std::cout << i << ": SRCNAME \"" << name_column_(row_list_[i])
00309 //          << "\" IFNO " << ifno_column_(row_list_[i]) << std::endl;
00310 //    }
00311     initialize(num_unique);
00312 
00313     // generate molecule_id_map_
00314     ROScalarColumn < uInt > id_column(molecules_table_, "ID");
00315     Vector < uInt > molecule_id_list = id_column.getColumn();
00316     for (uInt i = 0; i < id_column.nrow(); ++i) {
00317       molecule_id_map_[molecule_id_list[i]] = i;
00318     }
00319 
00320     // generate sorted_index_
00321     uInt nrow_main = main_table_.nrow();
00322     ROScalarColumn < String > srcname_column(main_table_, "SRCNAME");
00323     ROScalarColumn < uInt > ifno_column(main_table_, "IFNO");
00324     ROScalarColumn < Double > time_column(main_table_, "TIME");
00325     ROScalarColumn < Double > &interval_column = time_column;
00326     Sort sorter3;
00327     Vector < String > srcname_list = srcname_column.getColumn();
00328     Vector < Double > time_list = time_column.getColumn();
00329     sorter3.sortKey(srcname_list.data(), TpString, 0, Sort::Ascending);
00330     sorter3.sortKey(ifno_list.data(), TpUInt, 0, Sort::Ascending);
00331     sorter3.sortKey(time_list.data(), TpDouble, 0, Sort::Ascending);
00332     Vector < uInt > index_list;
00333     sorter3.sort(index_list, nrow_main, Sort::QuickSort);
00334 
00335     std::vector<size_t> srcname_boundary;
00336     srcname_boundary.push_back(0u);
00337     String current = srcname_list[index_list[0]];
00338     for (uInt i = 1; i < nrow_main; ++i) {
00339       String name = srcname_list[index_list[i]];
00340       if (current != name) {
00341         srcname_boundary.push_back(i);
00342         current = name;
00343       }
00344     }
00345     srcname_boundary.push_back(nrow_main);
00346 
00347     constexpr double kDay2Sec = 86400.0;
00348     interval_column.attach(main_table_, "INTERVAL");
00349     time_range_.clear();
00350     for (size_t i = 0; i < srcname_boundary.size() - 1; ++i) {
00351       String name = srcname_list[srcname_boundary[i]];
00352       size_t start = srcname_boundary[i];
00353       size_t end = srcname_boundary[i + 1];
00354       std::map<uInt, Block<Double> > range;
00355       std::map<uInt, Block<uInt> > range_index;
00356       getDataRangePerId(index_list, ifno_list, start, end,
00357           range_index);
00358       for (auto iter = range_index.begin(); iter != range_index.end(); ++iter) {
00359         Block<uInt> idx = iter->second;
00360         Block<Double> time_range(2);
00361         time_range[0] = time_list[idx[0]] * kDay2Sec
00362             - 0.5 * interval_column(idx[0]);
00363         time_range[1] = time_list[idx[1]] * kDay2Sec
00364             + 0.5 * interval_column(idx[1]);
00365         range[iter->first] = time_range;
00366       }
00367       time_range_[name] = range;
00368     }
00369 
00370 //    for (auto i = time_range_.begin(); i != time_range_.end(); ++i) {
00371 //      std::cout << "SRCNAME \"" << i->first << "\": " << std::endl;
00372 //      for (auto j = i->second.begin(); j != i->second.end(); ++j) {
00373 //        std::cout << "    " << j->first << ": " << j->second[0] << " "
00374 //            << j->second[1] << std::endl;
00375 //      }
00376 //    }
00377   }
00378 
00379   virtual ~ScantableSourceIterator() {
00380   }
00381 
00382   void getEntry(sdfiller::SourceRecord &record) {
00383     uInt const irow = row_list_[current_iter_];
00384     uInt const ifno = ifno_column_(irow);
00385     record.name = name_column_(irow);
00386     record.source_id = source_id_map_[record.name];
00387     record.spw_id = ifno;    //ifno_column_(irow);
00388     record.direction = MDirection(
00389         Quantum<Vector<Double> >(direction_column_(irow), "rad"),
00390         MDirection::J2000);
00391     record.proper_motion = proper_motion_column_(irow);
00392     uInt molecule_id = molecule_id_column_(irow);
00393     auto iter = molecule_id_map_.find(molecule_id);
00394     if (iter != molecule_id_map_.end()) {
00395       uInt jrow = iter->second;
00396       if (restfrequency_column_.isDefined(jrow)) {
00397         record.rest_frequency = restfrequency_column_(jrow);
00398       }
00399       if (molecule_name_column_.isDefined(jrow)) {
00400         record.transition = molecule_name_column_(jrow);
00401       }
00402     }
00403     // 2016/02/04 TN
00404     // comment out the following else block since if no ID is found in
00405     // molecule_id_map_ it indicates that there is no corresponding
00406     // entry in MOLECULES table for given MOLECULE_ID. Serch result is
00407     // always empty table.
00408 //    else {
00409 //      Table t = molecules_table_(molecules_table_.col("ID") == molecule_id, 1);
00410 //      if (t.nrow() == 1) {
00411 //        ArrayColumn<Double> rest_freq_column(t, "RESTFREQUENCY");
00412 //        ArrayColumn<String> molecule_name_column(t, "NAME");
00413 //        if (rest_freq_column.isDefined(0)) {
00414 //          record.rest_frequency = rest_freq_column(0);
00415 //        }
00416 //        if (molecule_name_column.isDefined(0)) {
00417 //          record.transition = molecule_name_column(0);
00418 //        }
00419 //      }
00420 //    }
00421     Double sysvel = sysvel_column_(irow);
00422     record.num_lines = record.rest_frequency.size();
00423     record.sysvel = Vector < Double > (record.num_lines, sysvel);
00424 
00425 //    Table t = main_table_(
00426 //        main_table_.col("SRCNAME") == record.name
00427 //            && main_table_.col("IFNO") == record.spw_id);
00428 //    time_column_.attach(t, "TIME");
00429 //    Vector < Double > time_list = time_column_.getColumn();
00430 //    Sort sorter;
00431 //    sorter.sortKey(time_list.data(), TpDouble);
00432 //    Vector < uInt > index_vector;
00433 //    uInt n = sorter.sort(index_vector, time_list.size());
00434 //    interval_column_.attach(t, "INTERVAL");
00435 //    constexpr double kDay2Sec = 86400.0;
00436 //    Double time_min = time_list[index_vector[0]] * kDay2Sec
00437 //        - 0.5 * interval_column_(index_vector[0]);
00438 //    Double time_max = time_list[index_vector[n - 1]] * kDay2Sec
00439 //        + 0.5 * interval_column_(index_vector[n - 1]);
00440     Block<Double> const &time_range = time_range_[record.name][ifno];
00441     Double time_min = time_range[0];
00442     Double time_max = time_range[1];
00443     record.time = 0.5 * (time_min + time_max);
00444     record.interval = (time_max - time_min);
00445   }
00446   virtual void getProduct(Product */*p*/) {
00447 
00448   }
00449 
00450 private:
00451   ROScalarColumn<String> name_column_;
00452   ArrayColumn<Double> direction_column_;
00453   ArrayColumn<Double> proper_motion_column_;
00454   ROScalarColumn<Double> sysvel_column_;
00455   ROScalarColumn<uInt> molecule_id_column_;
00456   ROScalarColumn<uInt> ifno_column_;
00457   ROScalarColumn<Double> time_column_;
00458   ROScalarColumn<Double> interval_column_;
00459   ArrayColumn<Double> restfrequency_column_;
00460   ArrayColumn<String> molecule_name_column_;
00461   Table molecules_table_;
00462   Vector<uInt> row_list_;
00463   std::map<String, Int> source_id_map_;
00464   std::map<uInt, uInt> molecule_id_map_;
00465   std::map<String, std::map<uInt, Block<Double> > > time_range_;
00466 };
00467 
00468 } //# NAMESPACE CASA - END
00469 
00470 #endif /* SINGLEDISH_FILLER_SCANTABLEITERATOR_H_ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 31 Aug 2016 for casa by  doxygen 1.6.1