source: trunk/src/STIdxIter.cpp@ 2911

Last change on this file since 2911 was 2911, checked in by Takeshi Nakazato, 11 years ago

New Development: No

JIRA Issue: No

Ready for Test: Yes

Interface Changes: No

What Interface Changed: Please list interface changes

Test Programs: test_sdcal

Put in Release Notes: Yes/No

Module(s): Module Names change impacts.

Description: Describe your changes here...

Defined new index iterator class, STIdxIter2.
STIdxIter2 has almost same functionality as STIdxIter and support
various kind of data.


File size: 16.4 KB
RevLine 
[2519]1#include <iostream>
2#include <casa/Utilities/GenSort.h>
3#include <casa/Arrays/Vector.h>
4#include <casa/Arrays/Matrix.h>
5#include <casa/Arrays/ArrayMath.h>
6#include <casa/Arrays/ArrayIO.h>
[2911]7#include <casa/Utilities/DataType.h>
[2519]8#include <tables/Tables/ScalarColumn.h>
[2911]9#include <tables/Tables/TableRow.h>
10#include <tables/Tables/TableRecord.h>
[2519]11#include "STIdxIter.h"
12
13namespace asap {
14
[2533]15IndexIterator::IndexIterator( IPosition &shape )
16 : niter_m( 0 )
[2519]17{
[2533]18 nfield_m = shape.nelements() ;
[2536]19 prod_m.resize( nfield_m ) ;
20 idx_m.resize( nfield_m ) ;
[2547]21 prod_m[nfield_m-1] = 1 ;
22 idx_m[nfield_m-1] = 0 ;
23 for ( Int i = nfield_m-2 ; i >= 0 ; i-- ) {
24 prod_m[i] = shape[i+1] * prod_m[i+1] ;
[2536]25 idx_m[i] = 0 ;
[2519]26 }
[2547]27 maxiter_m = prod_m[0] * shape[0] ;
[2519]28// cout << "maxiter_m=" << maxiter_m << endl ;
29}
30
31Bool IndexIterator::pastEnd()
32{
33 return niter_m >= maxiter_m ;
34}
35
36void IndexIterator::next()
37{
38 niter_m++ ;
39 uInt x = niter_m ;
[2547]40 for ( Int i = 0 ; i < nfield_m ; i++ ) {
[2519]41 idx_m[i] = x / prod_m[i] ;
42 //cout << "i=" << i << ": prod=" << prod_m[i]
43 // << ", idx=" << idx_m[i] << endl ;
44 x %= prod_m[i] ;
45 }
46}
47
48ArrayIndexIterator::ArrayIndexIterator( Matrix<uInt> &arr,
49 vector< vector<uInt> > idlist )
[2533]50 : arr_m( arr ),
[2536]51 pos_m( 1 )
[2519]52{
53 ncol_m = arr_m.ncolumn() ;
54 nrow_m = arr_m.nrow() ;
55 vector< vector<uInt> > l = idlist ;
56 if ( l.size() != ncol_m ) {
57 l.resize( ncol_m ) ;
58 for ( uInt i = 0 ; i < ncol_m ; i++ ) {
59 Vector<uInt> a( arr_m.column( i ).copy() ) ;
60 uInt n = genSort( a, Sort::Ascending, Sort::QuickSort|Sort::NoDuplicates ) ;
61 a.resize(n,True) ;
62 a.tovector( l[i] ) ;
63 }
64 }
[2533]65 idxlist_m = l ;
66 IPosition shape( ncol_m ) ;
67 for ( uInt i = 0 ; i < ncol_m ; i++ ) {
68 shape[i] = idxlist_m[i].size() ;
69 }
[2536]70// cout << "shape=" << shape << endl ;
[2533]71 iter_m = new IndexIterator( shape ) ;
72 current_m.resize( ncol_m ) ;
[2519]73}
74
75ArrayIndexIterator::~ArrayIndexIterator()
76{
77 delete iter_m ;
78}
79
80Vector<uInt> ArrayIndexIterator::current()
81{
[2533]82 Block<uInt> idx = iter_m->current() ;
83 for ( uInt i = 0 ; i < ncol_m ; i++ )
84 current_m[i] = idxlist_m[i][idx[i]] ;
85 return current_m ;
[2519]86}
87
88Bool ArrayIndexIterator::pastEnd()
89{
90 return iter_m->pastEnd() ;
91}
92
93ArrayIndexIteratorNormal::ArrayIndexIteratorNormal( Matrix<uInt> &arr,
94 vector< vector<uInt> > idlist )
[2533]95 : ArrayIndexIterator( arr, idlist )
[2519]96{
97 storage_m.resize( nrow_m ) ;
98}
99
100void ArrayIndexIteratorNormal::next()
101{
102 iter_m->next() ;
103}
104
[2524]105Vector<uInt> ArrayIndexIteratorNormal::getRows( StorageInitPolicy policy )
[2519]106{
107 Vector<uInt> v = current() ;
108 uInt len = 0 ;
109 uInt *p = storage_m.storage() ;
110 for ( uInt i = 0 ; i < nrow_m ; i++ ) {
111 if ( allEQ( v, arr_m.row( i ) ) ) {
112 *p = i ;
113 len++ ;
114 p++ ;
115 }
116 }
117 pos_m[0] = len ;
118 p = storage_m.storage() ;
[2524]119 return Vector<uInt>( pos_m, p, policy ) ;
[2519]120}
121
122ArrayIndexIteratorAcc::ArrayIndexIteratorAcc( Matrix<uInt> &arr,
123 vector< vector<uInt> > idlist )
[2533]124 : ArrayIndexIterator( arr, idlist )
[2519]125{
[2547]126 // storage_m layout
127 // length: ncol_m * (nrow_m + 1)
128 // 0~nrow_m-1: constant temporary storage that indicates whole rows
129 // nrow_m~2*nrow_m-1: temporary storage for column 0
130 // 2*nrow_m~3*nrow_m-1: temporary storage for column 1
131 // ...
[2519]132 storage_m.resize( arr_m.nelements()+nrow_m ) ;
[2550]133 // initialize constant temporary storage
[2547]134 uInt *p = storage_m.storage() ;
[2519]135 for ( uInt i = 0 ; i < nrow_m ; i++ ) {
[2536]136 *p = i ;
137 p++ ;
[2519]138 }
[2550]139 // len_m layout
140 // len[0]: length of temporary storage that incidates whole rows (constant)
141 // len[1]: number of matched row for column 0 selection
142 // len[2]: number of matched row for column 1 selection
143 // ...
[2519]144 len_m.resize( ncol_m+1 ) ;
[2536]145 p = len_m.storage() ;
[2519]146 for ( uInt i = 0 ; i < ncol_m+1 ; i++ ) {
[2536]147 *p = nrow_m ;
148 p++ ;
[2519]149// cout << "len[" << i << "]=" << len_m[i] << endl ;
150 }
[2550]151 // skip_m layout
152 // skip_m[0]: True if column 0 is filled by unique value
153 // skip_m[1]: True if column 1 is filled by unique value
154 // ...
155 skip_m.resize( ncol_m ) ;
156 for ( uInt i = 0 ; i < ncol_m ; i++ ) {
157 skip_m[i] = (Bool)(idxlist_m[i].size()==1) ;
158// cout << "skip_m[" << i << "]=" << skip_m[i] << endl ;
159 }
[2536]160 prev_m = iter_m->current() ;
161 p = prev_m.storage() ;
162 for ( uInt i = 0 ; i < ncol_m ; i++ ) {
163 *p = *p - 1 ;
164 p++ ;
165 }
166// cout << "prev_m=" << Vector<uInt>(IPosition(1,ncol_m),prev_m.storage()) << endl ;
[2519]167}
168
169void ArrayIndexIteratorAcc::next()
170{
[2536]171 prev_m = iter_m->current() ;
[2519]172 iter_m->next() ;
173}
174
[2524]175Vector<uInt> ArrayIndexIteratorAcc::getRows( StorageInitPolicy policy )
[2519]176{
[2536]177 Block<uInt> v = iter_m->current() ;
[2519]178 Int c = isChanged( v ) ;
[2548]179// cout << "v=" << Vector<uInt>(IPosition(1,v.nelements()),v.storage(),SHARE) << endl ;
180// cout << "c=" << c << endl ;
[2547]181 if ( c > ncol_m-1 ) {
182 pos_m[0] = len_m[ncol_m] ;
183 Int offset = ncol_m - 1 ;
184 while( offset >= 0 && skip_m[offset] )
185 offset-- ;
186 offset++ ;
[2536]187// cout << "offset=" << offset << endl ;
188 return Vector<uInt>( pos_m, storage_m.storage()+offset*nrow_m, policy ) ;
[2519]189 }
[2547]190 Int offset = c - 1 ;
191 while( offset >= 0 && skip_m[offset] )
192 offset-- ;
193 offset++ ;
[2548]194// cout << "offset = " << offset << endl ;
[2537]195 uInt *base = storage_m.storage() + offset * nrow_m ;
[2519]196// cout << "len_m[c+1]=" << len_m[c+1] << endl ;
197// cout << "base=" << Vector<uInt>(IPosition(1,len_m[c+1]),base,SHARE) << endl ;
[2550]198 for ( Int i = c ; i < ncol_m ; i++ ) {
199 base = updateStorage( i, base, idxlist_m[i][v[i]] ) ;
[2548]200// cout << "len_m[" << i << "]=" << len_m[i] << endl ;
[2519]201// cout << "base=" << Vector<uInt>(IPosition(1,len_m[i]),base,SHARE) << endl ;
202 }
[2547]203 pos_m[0] = len_m[ncol_m] ;
[2537]204// cout << "pos_m=" << pos_m << endl ;
[2548]205// cout << "ret=" << Vector<uInt>( pos_m, base, policy ) << endl ;
[2536]206 return Vector<uInt>( pos_m, base, policy ) ;
[2519]207}
208
[2536]209Int ArrayIndexIteratorAcc::isChanged( Block<uInt> &idx )
[2519]210{
[2547]211 Int i = 0 ;
212 while( i < ncol_m && idx[i] == prev_m[i] )
213 i++ ;
[2519]214 return i ;
215}
216
217uInt *ArrayIndexIteratorAcc::updateStorage( Int &icol,
218 uInt *base,
219 uInt &v )
220{
[2550]221 // CAUTION:
222 // indexes for storage_m and len_m differ from index for skip_m by 1
223 // (skip_m[0] corresponds to storage_m[1] and len_m[1]) since there
224 // is additional temporary storage at first segment in storage_m
[2536]225 uInt *p ;
[2550]226 if ( skip_m[icol] ) {
[2536]227 // skip update, just update len_m[icol] and pass appropriate pointer
228// cout << "skip " << icol << endl ;
229 p = base ;
[2550]230 len_m[icol+1] = len_m[icol] ;
[2536]231 }
232 else {
[2537]233// cout << "update " << icol << endl ;
[2536]234 uInt len = 0 ;
[2550]235 p = storage_m.storage() + (icol+1) * nrow_m ;
[2536]236 uInt *work = p ;
237 Bool b ;
238 const uInt *arr_p = arr_m.getStorage( b ) ;
239 long offset = 0 ;
240 // warr_p points a first element of (icol)-th column
[2550]241 const uInt *warr_p = arr_p + icol * nrow_m ;
242 for ( uInt i = 0 ; i < len_m[icol] ; i++ ) {
[2536]243 // increment warr_p by (*(base)-*(base-1))
244 warr_p += *base - offset ;
245 // check if target element is equal to value specified
246 if ( *warr_p == v ) {
247 // then, add current index to storage_m
248 // cout << "add " << *base << endl ;
249 *work = *base ;
250 len++ ;
251 work++ ;
252 }
253 // update offset
254 offset = *base ;
255 // next index
256 base++ ;
[2519]257 }
[2536]258 arr_m.freeStorage( arr_p, b ) ;
[2550]259 len_m[icol+1] = len ;
[2519]260 }
261 return p ;
262}
263
264STIdxIter::STIdxIter()
265{
266 iter_m = 0 ;
267}
268
269STIdxIter::STIdxIter( const string &name,
270 const vector<string> &cols )
271{
272}
273
274STIdxIter::STIdxIter( const CountedPtr<Scantable> &s,
275 const vector<string> &cols )
276{
277}
278
279STIdxIter::~STIdxIter()
280{
281 if ( iter_m != 0 )
282 delete iter_m ;
283}
284
285vector<uInt> STIdxIter::tovector( Vector<uInt> v )
286{
287 vector<uInt> ret ;
288 v.tovector( ret ) ;
289 return ret ;
290}
291
[2533]292Vector<uInt> STIdxIter::getRows( StorageInitPolicy policy )
293{
294 return iter_m->getRows( policy ) ;
295}
296
[2519]297STIdxIterNormal::STIdxIterNormal()
298 : STIdxIter()
299{
300}
301
302STIdxIterNormal::STIdxIterNormal( const string &name,
303 const vector<string> &cols )
304 : STIdxIter( name, cols )
305{
306 Table t( name, Table::Old ) ;
307 init( t, cols ) ;
308}
309
310STIdxIterNormal::STIdxIterNormal( const CountedPtr<Scantable> &s,
311 const vector<string> &cols )
312 : STIdxIter( s, cols )
313{
314 init( s->table(), cols ) ;
315}
316
317STIdxIterNormal::~STIdxIterNormal()
318{
319}
320
321void STIdxIterNormal::init( Table &t,
322 const vector<string> &cols )
323{
324 uInt ncol = cols.size() ;
325 uInt nrow = t.nrow() ;
326 Matrix<uInt> arr( nrow, ncol ) ;
327 ROScalarColumn<uInt> col ;
[2536]328 Vector<uInt> v ;
[2519]329 for ( uInt i = 0 ; i < ncol ; i++ ) {
330 col.attach( t, cols[i] ) ;
[2536]331 v.reference( arr.column( i ) ) ;
[2519]332 col.getColumn( v ) ;
333 }
334 iter_m = new ArrayIndexIteratorNormal( arr ) ;
335}
336
337STIdxIterAcc::STIdxIterAcc()
338 : STIdxIter()
339{
340}
341
342STIdxIterAcc::STIdxIterAcc( const string &name,
343 const vector<string> &cols )
344 : STIdxIter( name, cols )
345{
346 Table t( name, Table::Old ) ;
347 init( t, cols ) ;
348}
349
350STIdxIterAcc::STIdxIterAcc( const CountedPtr<Scantable> &s,
351 const vector<string> &cols )
352 : STIdxIter( s, cols )
353{
354 init( s->table(), cols ) ;
355}
356
357STIdxIterAcc::~STIdxIterAcc()
358{
359}
360
361void STIdxIterAcc::init( Table &t,
362 const vector<string> &cols )
363{
364 uInt ncol = cols.size() ;
365 uInt nrow = t.nrow() ;
[2536]366 // array shape here is as follows if cols=["BEAMNO","POLNO","IFNO"]:
367 // [[B0,B1,B2,...,BN],
368 // [P0,P1,P2,...,PN],
369 // [I0,I1,I2,...,IN]]
370 // order of internal storage is
371 // [B0,B1,B2,..,BN,P0,P1,P2,...,PN,I0,I1,I2,...,IN]
[2519]372 Matrix<uInt> arr( nrow, ncol ) ;
[2536]373 Vector<uInt> v ;
[2519]374 ROScalarColumn<uInt> col ;
375 for ( uInt i = 0 ; i < ncol ; i++ ) {
376 col.attach( t, cols[i] ) ;
[2536]377 v.reference( arr.column( i ) ) ;
[2519]378 col.getColumn( v ) ;
379 }
380 iter_m = new ArrayIndexIteratorAcc( arr ) ;
381}
382
[2537]383STIdxIterExAcc::STIdxIterExAcc()
[2547]384 : STIdxIter(),
385 srctypeid_m( -1 ),
386 srcnameid_m( -1 )
[2537]387{
388}
389
390STIdxIterExAcc::STIdxIterExAcc( const string &name,
391 const vector<string> &cols )
[2547]392 : STIdxIter( name, cols ),
393 srctypeid_m( -1 ),
394 srcnameid_m( -1 )
[2537]395{
396 Table t( name, Table::Old ) ;
397 init( t, cols ) ;
398}
399
400STIdxIterExAcc::STIdxIterExAcc( const CountedPtr<Scantable> &s,
401 const vector<string> &cols )
[2547]402 : STIdxIter( s, cols ),
403 srctypeid_m( -1 ),
404 srcnameid_m( -1 )
[2537]405{
406 init( s->table(), cols ) ;
407}
408
409STIdxIterExAcc::~STIdxIterExAcc()
410{
411}
412
413void STIdxIterExAcc::init( Table &t,
414 const vector<string> &cols )
415{
416 uInt ncol = cols.size() ;
417 uInt nrow = t.nrow() ;
418 // array shape here is as follows if cols=["BEAMNO","POLNO","IFNO"]:
419 // [[B0,B1,B2,...,BN],
420 // [P0,P1,P2,...,PN],
421 // [I0,I1,I2,...,IN]]
422 // order of internal storage is
423 // [B0,B1,B2,..,BN,P0,P1,P2,...,PN,I0,I1,I2,...,IN]
424 Matrix<uInt> arr( nrow, ncol ) ;
425 Vector<uInt> v ;
426 ROScalarColumn<uInt> col ;
427 ROScalarColumn<String> strCol ;
428 ROScalarColumn<Int> intCol ;
429 for ( uInt i = 0 ; i < ncol ; i++ ) {
430 v.reference( arr.column( i ) ) ;
431 if ( cols[i] == "SRCTYPE" ) {
432 intCol.attach( t, cols[i] ) ;
433 Vector<Int> srctype = intCol.getColumn() ;
434 processIntCol( srctype, v, srctype_m ) ;
435 srctypeid_m = i ;
436 }
437 else if ( cols[i] == "SRCNAME" ) {
438 strCol.attach( t, cols[i] ) ;
439 Vector<String> srcname = strCol.getColumn() ;
440 processStrCol( srcname, v, srcname_m ) ;
441 srcnameid_m = i ;
442 }
443 else {
444 col.attach( t, cols[i] ) ;
445 col.getColumn( v ) ;
446 }
447 }
448 iter_m = new ArrayIndexIteratorAcc( arr ) ;
449}
450
451void STIdxIterExAcc::processIntCol( Vector<Int> &in,
452 Vector<uInt> &out,
453 Block<Int> &val )
454{
[2547]455 convertArray( out, in ) ;
[2537]456}
457
458void STIdxIterExAcc::processStrCol( Vector<String> &in,
459 Vector<uInt> &out,
460 Block<String> &val )
461{
462 uInt len = in.nelements() ;
463 Vector<String> tmp = in.copy() ;
464 uInt n = genSort( tmp, Sort::Ascending, Sort::QuickSort|Sort::NoDuplicates ) ;
465 val.resize( n ) ;
466 for ( uInt i = 0 ; i < n ; i++ ) {
467 val[i] = tmp[i] ;
468// cout << "val[" << i << "]=" << val[i] << endl ;
469 }
[2547]470 if ( n == 1 ) {
471 //cout << "n=1" << endl ;
472 out = 0 ;
473 }
474 else if ( n == 2 ) {
475 //cout << "n=2" << endl ;
476 for ( uInt i = 0 ; i < len ; i++ ) {
477 out[i] = (in[i] == val[0]) ? 0 : 1 ;
[2537]478 }
479 }
[2547]480 else {
481 //cout << "n=" << n << endl ;
482 map<String,uInt> m ;
483 for ( uInt i = 0 ; i < n ; i++ )
484 m[val[i]] = i ;
485 for ( uInt i = 0 ; i < len ; i++ ) {
486 out[i] = m[in[i]] ;
487 }
488 }
[2537]489}
490
491Int STIdxIterExAcc::getSrcType()
492{
[2547]493 if ( srctypeid_m >= 0 )
494 return (Int)(iter_m->current()[srctypeid_m]) ;
[2537]495 else
496 return -999 ;
497}
498
499String STIdxIterExAcc::getSrcName()
500{
501 if ( srcname_m.nelements() > 0 )
502 return srcname_m[iter_m->current()[srcnameid_m]] ;
503 else
504 return "" ;
505}
506
[2911]507STIdxIter2::STIdxIter2()
508 : cols_(),
509 table_(),
510 counter_(0),
511 num_iter_(0),
512 num_row_(0),
513 sorter_(),
514 index_(),
515 unique_(),
516 pointer_()
517{
518}
519
520STIdxIter2::STIdxIter2( const string &name,
521 const vector<string> &cols )
522 : cols_(cols),
523 table_(name, Table::Old),
524 counter_(0),
525 num_iter_(0),
526 num_row_(0),
527 sorter_(),
528 index_(),
529 unique_(),
530 pointer_()
531{
532 init();
533}
534
535STIdxIter2::STIdxIter2( const CountedPtr<Scantable> &s,
536 const vector<string> &cols )
537 : cols_(cols),
538 table_(s->table()),
539 counter_(0),
540 num_iter_(0),
541 num_row_(0),
542 sorter_(),
543 index_(),
544 unique_(),
545 pointer_()
546{
547 init();
548}
549
550STIdxIter2::~STIdxIter2()
551{
552 deallocate();
553}
554
555void STIdxIter2::deallocate()
556{
557 for (vector<void*>::iterator i = pointer_.begin(); i != pointer_.end(); ++i) {
558 free(*i);
559 }
560}
561
562Record STIdxIter2::currentValue() {
563 assert(counter_ < num_iter_);
564 Vector<String> cols(cols_.size());
565 for (uInt i = 0; i < cols.nelements(); ++i) {
566 cols[i] = cols_[i];
567 }
568 const ROTableRow row(table_, cols);
569 const TableRecord rec = row.get(index_[unique_[counter_]]);
570 return Record(rec);
571}
572
573Bool STIdxIter2::pastEnd() {
574 return counter_ >= num_iter_;
575}
576
577void STIdxIter2::next() {
578 counter_++;
579}
580
581vector<uInt> STIdxIter2::tovector( Vector<uInt> v )
582{
583 vector<uInt> ret ;
584 v.tovector( ret ) ;
585 return ret ;
586}
587
588Vector<uInt> STIdxIter2::getRows( StorageInitPolicy policy )
589{
590 assert(num_iter_ > 1);
591 assert(counter_ < num_iter_);
592 if (counter_ == num_iter_ - 1) {
593 uInt start = unique_[counter_];
594 uInt num_row = num_row_ - start;
595 Vector<uInt> rows(IPosition(1, num_row), &(index_.data()[start]), policy);
596 return rows;
597 }
598 else {
599 uInt start = unique_[counter_];
600 uInt end = unique_[counter_ + 1];
601 uInt num_row = end - start;
602 Vector<uInt> rows(IPosition(1, num_row), &(index_.data()[start]), policy);
603 return rows;
604 }
605}
606
607void STIdxIter2::init()
608{
609 for (uInt i = 0; i < cols_.size(); ++i) {
610 addSortKey(cols_[i]);
611 }
612 num_row_ = table_.nrow();
613 sorter_.sort(index_, num_row_);
614 num_iter_ = sorter_.unique(unique_, index_);
615 // cout << "num_row_ = " << num_row_ << endl
616 // << "num_iter_ = " << num_iter_ << endl;
617 // cout << "unique_ = " << unique_ << endl;
618 // cout << "index_ = " << index_ << endl;
619}
620
621void STIdxIter2::addSortKey(const string &name)
622{
623 const ColumnDesc &desc = table_.tableDesc().columnDesc(name);
624 const DataType dtype = desc.trueDataType();
625 switch (dtype) {
626 case TpUInt:
627 addColumnToKey<uInt, TpUInt>(name);
628 break;
629 case TpInt:
630 addColumnToKey<Int, TpInt>(name);
631 break;
632 case TpFloat:
633 addColumnToKey<Float, TpFloat>(name);
634 break;
635 case TpDouble:
636 addColumnToKey<Double, TpDouble>(name);
637 break;
638 case TpComplex:
639 addColumnToKey<Complex, TpComplex>(name);
640 break;
641 // case TpString:
642 // addColumnToKey<String, TpString>(name);
643 // break;
644 default:
645 deallocate();
646 stringstream oss;
647 oss << name << ": data type is not supported" << endl;
648 throw(AipsError(oss.str()));
649 }
650}
651
652template<class T, DataType U>
653void STIdxIter2::addColumnToKey(const string &name)
654{
655 uInt nrow = table_.nrow();
656 void *raw_storage = malloc(sizeof(T) * nrow);
657 T *storage = reinterpret_cast<T*>(raw_storage);
658 Vector<T> array(IPosition(1, nrow), storage, SHARE);
659 ROScalarColumn<T> col(table_, name);
660 col.getColumn(array);
661 sorter_.sortKey(storage, U, 0, Sort::Ascending);
662 pointer_.push_back(raw_storage);
663}
[2519]664} // namespace
[2911]665
Note: See TracBrowser for help on using the repository browser.