Line data Source code
1 : /*
2 : * ScantableIterator.h
3 : *
4 : * Created on: Jan 28, 2016
5 : * Author: nakazato
6 : */
7 :
8 : #ifndef SINGLEDISH_FILLER_SCANTABLEITERATOR_H_
9 : #define SINGLEDISH_FILLER_SCANTABLEITERATOR_H_
10 :
11 : #include <casacore/casa/Arrays/Vector.h>
12 : #include <casacore/casa/Utilities/Compare.h>
13 : #include <casacore/casa/Utilities/Sort.h>
14 :
15 : #include <casacore/measures/Measures/MFrequency.h>
16 :
17 : #include <casacore/tables/Tables/Table.h>
18 : #include <casacore/tables/Tables/ScalarColumn.h>
19 : #include <casacore/tables/Tables/ArrayColumn.h>
20 : #include <casacore/tables/TaQL/ExprNode.h>
21 : #include <singledishfiller/Filler/FieldRecord.h>
22 : #include <singledishfiller/Filler/FillerUtil.h>
23 : #include <singledishfiller/Filler/SourceRecord.h>
24 : #include <singledishfiller/Filler/SpectralWindowRecord.h>
25 : #include <singledishfiller/Filler/SysCalRecord.h>
26 :
27 : using namespace casacore;
28 :
29 : namespace {
30 : template<class T>
31 5 : inline void getDataRangePerId(casacore::Vector<casacore::uInt> const &index_list,
32 : casacore::Vector<T> const &id_list, size_t start,
33 : size_t end, std::map<T, casacore::Block<casacore::uInt> > &range_index) {
34 5 : casacore::uInt id_prev = id_list[index_list[start]];
35 5 : casacore::uInt id_min = index_list[start];
36 5 : casacore::uInt id_max = 0;
37 5 : casacore::Block < casacore::uInt > current_index(2);
38 990 : for (casacore::uInt i = start + 1; i < end; ++i) {
39 985 : casacore::uInt j = index_list[i];
40 985 : casacore::uInt current_id = id_list[j];
41 : // std::cout << "weather_id = " << weather_id << " id_prev = " << id_prev
42 : // << " time range (" << time_min << "," << time_max << ")" << std::endl;
43 985 : if (current_id != id_prev) {
44 20 : id_max = index_list[i - 1];
45 20 : current_index[0] = id_min;
46 20 : current_index[1] = id_max;
47 20 : range_index[id_prev] = current_index;
48 :
49 20 : id_prev = current_id;
50 20 : id_min = j;
51 : }
52 : }
53 5 : casacore::uInt last_id = id_list[index_list[end - 1]];
54 5 : if (range_index.find(last_id) == range_index.end()) {
55 5 : id_max = index_list[end - 1];
56 5 : current_index[0] = id_min;
57 5 : current_index[1] = id_max;
58 5 : range_index[last_id] = current_index;
59 : }
60 5 : }
61 :
62 : }
63 :
64 : namespace casa { //# NAMESPACE CASA - BEGIN
65 :
66 : class ScantableIteratorBase {
67 : public:
68 15 : ScantableIteratorBase() :
69 15 : current_iter_(0), num_iter_(0) {
70 15 : }
71 15 : virtual ~ScantableIteratorBase() {
72 15 : }
73 15 : void initialize(size_t num_iter) {
74 15 : num_iter_ = num_iter;
75 15 : current_iter_ = 0;
76 15 : }
77 70 : bool moreData() const {
78 70 : return current_iter_ < num_iter_;
79 : }
80 55 : void next() {
81 55 : ++current_iter_;
82 55 : }
83 :
84 : protected:
85 : size_t current_iter_;
86 :
87 : private:
88 : size_t num_iter_;
89 : };
90 :
91 : template<class _Product, class _Record>
92 : class ScantableIteratorInterface: public ScantableIteratorBase {
93 : public:
94 : using Product = _Product;
95 : using Record = _Record;
96 15 : ScantableIteratorInterface(casacore::Table const &table) :
97 15 : ScantableIteratorBase(), main_table_(table) {
98 15 : }
99 15 : virtual ~ScantableIteratorInterface() {}
100 : virtual void getEntry(Record &record) = 0;
101 : virtual void getProduct(Product *p) = 0;
102 : protected:
103 : casacore::Table const main_table_;
104 : };
105 :
106 : class ScantableFrequenciesIterator final :
107 : public ScantableIteratorInterface<std::map<casacore::Int, casacore::Int>, sdfiller::SpectralWindowRecord> {
108 : public:
109 5 : ScantableFrequenciesIterator(casacore::Table const &table) :
110 5 : ScantableIteratorInterface(table) {
111 5 : casacore::TableRecord const &header = main_table_.keywordSet();
112 5 : sub_table_ = header.asTable("FREQUENCIES");
113 : //size_t nrow = sub_table_.nrow();
114 5 : casacore::ScalarColumn < casacore::uInt > ifno_column(main_table_, "IFNO");
115 5 : casacore::Vector < casacore::uInt > ifno_list = ifno_column.getColumn();
116 5 : casacore::Sort sorter;
117 5 : sorter.sortKey(ifno_list.data(), TpUInt);
118 5 : casacore::Vector < casacore::uInt > index_vector;
119 5 : casacore::uInt n = sorter.sort(index_vector, ifno_list.nelements(),
120 : casacore::Sort::HeapSort | casacore::Sort::NoDuplicates);
121 :
122 5 : initialize(n);
123 5 : ifno_list_.resize(n);
124 30 : for (casacore::uInt i = 0; i < n; ++i) {
125 25 : ifno_list_[i] = ifno_list[index_vector[i]];
126 : }
127 :
128 5 : casacore::ScalarColumn < casacore::uInt > freq_id_column(main_table_, "FREQ_ID");
129 :
130 : // attach columns
131 5 : id_column_.attach(sub_table_, "ID");
132 5 : refpix_column_.attach(sub_table_, "REFPIX");
133 5 : refval_column_.attach(sub_table_, "REFVAL");
134 5 : increment_column_.attach(sub_table_, "INCREMENT");
135 5 : id_list_ = id_column_.getColumn();
136 5 : }
137 10 : virtual ~ScantableFrequenciesIterator() {
138 10 : }
139 :
140 25 : void getEntry(Record &record) override {
141 25 : size_t const irow = current_iter_;
142 : // std::cout << "getEntry for row " << irow << std::endl;
143 25 : casacore::Int spw_id = ifno_list_[irow];
144 50 : casacore::Table subtable = main_table_(main_table_.col("IFNO") == (casacore::uInt) spw_id, 1);
145 25 : casacore::ScalarColumn < casacore::uInt > freq_id_column(subtable, "FREQ_ID");
146 25 : casacore::uInt freq_id = freq_id_column(0);
147 25 : casacore::Int jrow = -1;
148 295 : for (casacore::uInt i = 0; i < id_list_.size(); ++i) {
149 295 : if (id_list_[i] == freq_id) {
150 25 : jrow = (casacore::Int) i;
151 25 : break;
152 : }
153 : }
154 25 : casacore::ArrayColumn<casacore::uChar> flag_column(subtable, "FLAGTRA");
155 25 : casacore::Int num_chan = flag_column.shape(0)[0];
156 25 : casacore::String freq_frame = sub_table_.keywordSet().asString("BASEFRAME");
157 : casacore::MFrequency::Types frame_type;
158 25 : casacore::Bool status = casacore::MFrequency::getType(frame_type, freq_frame);
159 25 : if (!status) {
160 0 : frame_type = casacore::MFrequency::N_Types;
161 : }
162 25 : casacore::Double refpix = refpix_column_(jrow);
163 25 : casacore::Double refval = refval_column_(jrow);
164 25 : casacore::Double increment = increment_column_(jrow);
165 : // std::cout << "spw " << spw_id << " nchan " << num_chan << " mfr "
166 : // << (casacore::Int) frame_type << " (" << freq_frame << ") ref " << refpix << ", "
167 : // << refval << ", " << increment << std::endl;
168 25 : record.spw_id = spw_id;
169 25 : record.num_chan = num_chan;
170 25 : record.meas_freq_ref = frame_type;
171 25 : record.refpix = refpix;
172 25 : record.refval = refval;
173 25 : record.increment = increment;
174 :
175 : // update product
176 25 : product_[spw_id] = num_chan;
177 25 : }
178 5 : void getProduct(Product *p) override {
179 5 : if (p) {
180 30 : for (auto iter = product_.begin(); iter != product_.end(); ++iter) {
181 25 : (*p)[iter->first] = iter->second;
182 : }
183 : }
184 5 : }
185 :
186 : private:
187 : casacore::Table sub_table_;
188 : casacore::ScalarColumn<casacore::uInt> id_column_;
189 : casacore::ScalarColumn<casacore::Double> refpix_column_;
190 : casacore::ScalarColumn<casacore::Double> refval_column_;
191 : casacore::ScalarColumn<casacore::Double> increment_column_;
192 : casacore::Vector<casacore::uInt> ifno_list_;
193 : casacore::Vector<casacore::uInt> id_list_;
194 : Product product_;
195 : };
196 :
197 : class ScantableFieldIterator final :
198 : public ScantableIteratorInterface<std::map<casacore::String, casacore::Int>, sdfiller::FieldRecord> {
199 : public:
200 5 : ScantableFieldIterator(casacore::Table const &table) :
201 10 : ScantableIteratorInterface(table), row_list_(), is_reserved_(), field_column_(
202 15 : main_table_, "FIELDNAME"), source_column_(main_table_, "SRCNAME"), time_column_(
203 15 : main_table_, "TIME"), direction_column_(main_table_, "SRCDIRECTION"), scanrate_column_(
204 15 : main_table_, "SCANRATE"), direction_storage_(2, 2, 0.0) {
205 5 : casacore::Vector < casacore::String > field_name_list = field_column_.getColumn();
206 5 : casacore::Sort sorter;
207 5 : sorter.sortKey(field_name_list.data(), TpString);
208 5 : casacore::uInt n = sorter.sort(row_list_, field_name_list.size(),
209 : casacore::Sort::QuickSort | casacore::Sort::NoDuplicates);
210 5 : is_reserved_.resize(n);
211 5 : is_reserved_ = false;
212 5 : initialize(n);
213 5 : }
214 :
215 10 : virtual ~ScantableFieldIterator() {
216 10 : }
217 :
218 5 : void getEntry(Record &record) override {
219 5 : casacore::uInt const irow = row_list_[current_iter_];
220 5 : casacore::String field_name_with_id = field_column_(irow);
221 5 : auto pos = field_name_with_id.find("__");
222 : auto defaultFieldId =
223 5 : [&]() {
224 5 : casacore::Int my_field_id = 0;
225 5 : while (is_reserved_[my_field_id] && (casacore::uInt)my_field_id < is_reserved_.size()) {
226 0 : my_field_id++;
227 : }
228 5 : if ((casacore::uInt)my_field_id >= is_reserved_.size()) {
229 0 : throw casacore::AipsError("Internal inconsistency in FIELD_ID numbering");
230 : }
231 5 : is_reserved_[my_field_id] = true;
232 5 : return my_field_id;
233 5 : };
234 5 : if (pos != casacore::String::npos) {
235 5 : record.name = field_name_with_id.substr(0, pos);
236 5 : casacore::Int field_id = casacore::String::toInt(field_name_with_id.substr(pos + 2));
237 5 : if (field_id < 0 || (casacore::uInt) field_id >= is_reserved_.size()) {
238 5 : record.field_id = defaultFieldId();
239 0 : } else if (!is_reserved_[field_id]) {
240 0 : record.field_id = field_id;
241 0 : is_reserved_[field_id] = true;
242 : } else {
243 0 : record.field_id = defaultFieldId();
244 : }
245 : } else {
246 0 : record.name = field_name_with_id;
247 0 : record.field_id = defaultFieldId();
248 : }
249 5 : record.time = time_column_(irow) * 86400.0;
250 5 : record.source_name = source_column_(irow);
251 5 : record.frame = casacore::MDirection::J2000;
252 : casacore::Matrix < Double
253 10 : > direction(direction_storage_(casacore::IPosition(2, 0, 0), casacore::IPosition(2, 1, 0)));
254 : // std::cout << "direction = " << direction << " (shape " << direction.shape()
255 : // << ")" << std::endl;
256 5 : direction_storage_.column(0) = direction_column_(irow);
257 5 : if (scanrate_column_.isDefined(irow)) {
258 5 : casacore::Vector < casacore::Double > scan_rate = scanrate_column_(irow);
259 5 : if (anyNE(scan_rate, 0.0)) {
260 0 : direction_storage_.column(1) = scan_rate;
261 0 : direction.reference(direction_storage_);
262 : }
263 5 : }
264 : // std::cout << "direction = " << direction << " (shape " << direction.shape()
265 : // << ")" << std::endl;
266 5 : record.direction = direction;
267 :
268 : // update product
269 5 : product_[field_name_with_id] = record.field_id;
270 5 : }
271 5 : void getProduct(Product *p) override {
272 5 : if (p) {
273 10 : for (auto iter = product_.begin(); iter != product_.end(); ++iter) {
274 5 : (*p)[iter->first] = iter->second;
275 : }
276 : }
277 5 : }
278 :
279 : private:
280 : casacore::Vector<casacore::uInt> row_list_;
281 : casacore::Vector<casacore::Bool> is_reserved_;
282 : casacore::ScalarColumn<casacore::String> field_column_;
283 : casacore::ScalarColumn<casacore::String> source_column_;
284 : casacore::ScalarColumn<casacore::Double> time_column_;
285 : casacore::ArrayColumn<casacore::Double> direction_column_;
286 : casacore::ArrayColumn<casacore::Double> scanrate_column_;
287 : casacore::Matrix<casacore::Double> direction_storage_;
288 : Product product_;
289 : };
290 :
291 : class ScantableSourceIterator final :
292 : public ScantableIteratorInterface<void *, sdfiller::SourceRecord> {
293 : public:
294 5 : ScantableSourceIterator(casacore::Table const &table) :
295 10 : ScantableIteratorInterface(table), name_column_(main_table_, "SRCNAME"), direction_column_(
296 10 : main_table_, "SRCDIRECTION"), proper_motion_column_(main_table_,
297 10 : "SRCPROPERMOTION"), sysvel_column_(main_table_, "SRCVELOCITY"), molecule_id_column_(
298 15 : main_table_, "MOLECULE_ID"), ifno_column_(main_table_, "IFNO"), molecules_table_(), row_list_(), source_id_map_() {
299 5 : casacore::TableRecord const &header = main_table_.keywordSet();
300 5 : molecules_table_ = header.asTable("MOLECULES");
301 5 : restfrequency_column_.attach(molecules_table_, "RESTFREQUENCY");
302 5 : molecule_name_column_.attach(molecules_table_, "NAME");
303 5 : casacore::Vector < casacore::String > source_name_list = name_column_.getColumn();
304 5 : casacore::Vector < casacore::uInt > ifno_list = ifno_column_.getColumn();
305 5 : casacore::Sort sorter;
306 5 : sorter.sortKey(source_name_list.data(), TpString);
307 5 : casacore::Vector < casacore::uInt > unique_vector;
308 5 : casacore::uInt num_unique = sorter.sort(unique_vector, source_name_list.size(),
309 : casacore::Sort::QuickSort | casacore::Sort::NoDuplicates);
310 10 : for (casacore::uInt i = 0; i < num_unique; ++i) {
311 5 : source_id_map_[name_column_(unique_vector[i])] = (casacore::Int) i;
312 : }
313 5 : casacore::Sort sorter2;
314 5 : sorter2.sortKey(source_name_list.data(), TpString);
315 5 : sorter2.sortKey(ifno_list.data(), TpUInt);
316 5 : unique_vector.resize();
317 5 : num_unique = sorter2.sort(row_list_, source_name_list.size(),
318 : casacore::Sort::QuickSort | casacore::Sort::NoDuplicates);
319 : // for (casacore::uInt i = 0; i < num_unique; ++i) {
320 : // std::cout << i << ": SRCNAME \"" << name_column_(row_list_[i])
321 : // << "\" IFNO " << ifno_column_(row_list_[i]) << std::endl;
322 : // }
323 5 : initialize(num_unique);
324 :
325 : // generate molecule_id_map_
326 5 : casacore::ScalarColumn < casacore::uInt > id_column(molecules_table_, "ID");
327 5 : casacore::Vector < casacore::uInt > molecule_id_list = id_column.getColumn();
328 30 : for (casacore::uInt i = 0; i < id_column.nrow(); ++i) {
329 25 : molecule_id_map_[molecule_id_list[i]] = i;
330 : }
331 :
332 : // generate sorted_index_
333 5 : casacore::uInt nrow_main = main_table_.nrow();
334 5 : casacore::ScalarColumn < casacore::String > srcname_column(main_table_, "SRCNAME");
335 5 : casacore::ScalarColumn < casacore::uInt > ifno_column(main_table_, "IFNO");
336 5 : casacore::ScalarColumn < casacore::Double > time_column(main_table_, "TIME");
337 5 : casacore::ScalarColumn < casacore::Double > &interval_column = time_column;
338 5 : casacore::Sort sorter3;
339 5 : casacore::Vector < casacore::String > srcname_list = srcname_column.getColumn();
340 5 : casacore::Vector < casacore::Double > time_list = time_column.getColumn();
341 5 : sorter3.sortKey(srcname_list.data(), TpString, 0, casacore::Sort::Ascending);
342 5 : sorter3.sortKey(ifno_list.data(), TpUInt, 0, casacore::Sort::Ascending);
343 5 : sorter3.sortKey(time_list.data(), TpDouble, 0, casacore::Sort::Ascending);
344 5 : casacore::Vector < casacore::uInt > index_list;
345 5 : sorter3.sort(index_list, nrow_main, casacore::Sort::QuickSort);
346 :
347 5 : std::vector<size_t> srcname_boundary;
348 5 : srcname_boundary.push_back(0u);
349 5 : casacore::String current = srcname_list[index_list[0]];
350 990 : for (casacore::uInt i = 1; i < nrow_main; ++i) {
351 985 : casacore::String name = srcname_list[index_list[i]];
352 985 : if (current != name) {
353 0 : srcname_boundary.push_back(i);
354 0 : current = name;
355 : }
356 985 : }
357 5 : srcname_boundary.push_back(nrow_main);
358 :
359 5 : constexpr double kDay2Sec = 86400.0;
360 5 : interval_column.attach(main_table_, "INTERVAL");
361 5 : time_range_.clear();
362 10 : for (size_t i = 0; i < srcname_boundary.size() - 1; ++i) {
363 5 : casacore::String name = srcname_list[index_list[srcname_boundary[i]]];
364 5 : size_t start = srcname_boundary[i];
365 5 : size_t end = srcname_boundary[i + 1];
366 5 : std::map<casacore::uInt, casacore::Block<casacore::Double> > range;
367 5 : std::map<casacore::uInt, casacore::Block<casacore::uInt> > range_index;
368 5 : getDataRangePerId(index_list, ifno_list, start, end,
369 : range_index);
370 30 : for (auto iter = range_index.begin(); iter != range_index.end(); ++iter) {
371 25 : casacore::Block<casacore::uInt> idx = iter->second;
372 25 : casacore::Block<casacore::Double> time_range(2);
373 25 : time_range[0] = time_list[idx[0]] * kDay2Sec
374 25 : - 0.5 * interval_column(idx[0]);
375 25 : time_range[1] = time_list[idx[1]] * kDay2Sec
376 25 : + 0.5 * interval_column(idx[1]);
377 25 : range[iter->first] = time_range;
378 25 : }
379 5 : time_range_[name] = range;
380 5 : }
381 :
382 : // for (auto i = time_range_.begin(); i != time_range_.end(); ++i) {
383 : // std::cout << "SRCNAME \"" << i->first << "\": " << std::endl;
384 : // for (auto j = i->second.begin(); j != i->second.end(); ++j) {
385 : // std::cout << " " << j->first << ": " << j->second[0] << " "
386 : // << j->second[1] << std::endl;
387 : // }
388 : // }
389 5 : }
390 :
391 10 : virtual ~ScantableSourceIterator() {
392 10 : }
393 :
394 25 : void getEntry(sdfiller::SourceRecord &record) override {
395 25 : casacore::uInt const irow = row_list_[current_iter_];
396 25 : casacore::uInt const ifno = ifno_column_(irow);
397 25 : record.name = name_column_(irow);
398 25 : record.source_id = source_id_map_[record.name];
399 25 : record.spw_id = ifno; //ifno_column_(irow);
400 50 : record.direction = casacore::MDirection(
401 50 : casacore::Quantum<casacore::Vector<casacore::Double> >(direction_column_(irow), "rad"),
402 25 : casacore::MDirection::J2000);
403 25 : record.proper_motion = proper_motion_column_(irow);
404 25 : casacore::uInt molecule_id = molecule_id_column_(irow);
405 25 : auto iter = molecule_id_map_.find(molecule_id);
406 25 : if (iter != molecule_id_map_.end()) {
407 25 : casacore::uInt jrow = iter->second;
408 25 : if (restfrequency_column_.isDefined(jrow)) {
409 25 : record.rest_frequency = restfrequency_column_(jrow);
410 : }
411 25 : if (molecule_name_column_.isDefined(jrow)) {
412 25 : record.transition = molecule_name_column_(jrow);
413 : }
414 : }
415 : // 2016/02/04 TN
416 : // comment out the following else block since if no ID is found in
417 : // molecule_id_map_ it indicates that there is no corresponding
418 : // entry in MOLECULES table for given MOLECULE_ID. Serch result is
419 : // always empty table.
420 : // else {
421 : // casacore::Table t = molecules_table_(molecules_table_.col("ID") == molecule_id, 1);
422 : // if (t.nrow() == 1) {
423 : // casacore::ArrayColumn<casacore::Double> rest_freq_column(t, "RESTFREQUENCY");
424 : // casacore::ArrayColumn<casacore::String> molecule_name_column(t, "NAME");
425 : // if (rest_freq_column.isDefined(0)) {
426 : // record.rest_frequency = rest_freq_column(0);
427 : // }
428 : // if (molecule_name_column.isDefined(0)) {
429 : // record.transition = molecule_name_column(0);
430 : // }
431 : // }
432 : // }
433 25 : casacore::Double sysvel = sysvel_column_(irow);
434 25 : record.num_lines = record.rest_frequency.size();
435 25 : record.sysvel = casacore::Vector < casacore::Double > (record.num_lines, sysvel);
436 :
437 : // casacore::Table t = main_table_(
438 : // main_table_.col("SRCNAME") == record.name
439 : // && main_table_.col("IFNO") == record.spw_id);
440 : // time_column_.attach(t, "TIME");
441 : // casacore::Vector < casacore::Double > time_list = time_column_.getColumn();
442 : // casacore::Sort sorter;
443 : // sorter.sortKey(time_list.data(), TpDouble);
444 : // casacore::Vector < casacore::uInt > index_vector;
445 : // casacore::uInt n = sorter.sort(index_vector, time_list.size());
446 : // interval_column_.attach(t, "INTERVAL");
447 : // constexpr double kDay2Sec = 86400.0;
448 : // casacore::Double time_min = time_list[index_vector[0]] * kDay2Sec
449 : // - 0.5 * interval_column_(index_vector[0]);
450 : // casacore::Double time_max = time_list[index_vector[n - 1]] * kDay2Sec
451 : // + 0.5 * interval_column_(index_vector[n - 1]);
452 25 : casacore::Block<casacore::Double> const &time_range = time_range_[record.name][ifno];
453 25 : casacore::Double time_min = time_range[0];
454 25 : casacore::Double time_max = time_range[1];
455 25 : record.time = 0.5 * (time_min + time_max);
456 25 : record.interval = (time_max - time_min);
457 25 : }
458 5 : void getProduct(Product */*p*/) override {
459 :
460 5 : }
461 :
462 : private:
463 : casacore::ScalarColumn<casacore::String> name_column_;
464 : casacore::ArrayColumn<casacore::Double> direction_column_;
465 : casacore::ArrayColumn<casacore::Double> proper_motion_column_;
466 : casacore::ScalarColumn<casacore::Double> sysvel_column_;
467 : casacore::ScalarColumn<casacore::uInt> molecule_id_column_;
468 : casacore::ScalarColumn<casacore::uInt> ifno_column_;
469 : casacore::ScalarColumn<casacore::Double> time_column_;
470 : casacore::ScalarColumn<casacore::Double> interval_column_;
471 : casacore::ArrayColumn<casacore::Double> restfrequency_column_;
472 : casacore::ArrayColumn<casacore::String> molecule_name_column_;
473 : casacore::Table molecules_table_;
474 : casacore::Vector<casacore::uInt> row_list_;
475 : std::map<casacore::String, casacore::Int> source_id_map_;
476 : std::map<casacore::uInt, casacore::uInt> molecule_id_map_;
477 : std::map<casacore::String, std::map<casacore::uInt, casacore::Block<casacore::Double> > > time_range_;
478 : };
479 :
480 : } //# NAMESPACE CASA - END
481 :
482 : #endif /* SINGLEDISH_FILLER_SCANTABLEITERATOR_H_ */
|