00001
00002
00003
00004
00005
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
00043
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 {
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
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
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
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
00153
00154
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
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
00243
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
00253
00254 record.direction = direction;
00255
00256
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
00308
00309
00310
00311 initialize(num_unique);
00312
00313
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
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
00371
00372
00373
00374
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;
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
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
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
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
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 *) {
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 }
00469
00470 #endif