source: trunk/src/STIdxIter.cpp@ 2914

Last change on this file since 2914 was 2914, checked in by Takeshi Nakazato, 10 years ago

New Development: No

JIRA Issue: No

Ready for Test: Yes

Interface Changes: Yes/No

What Interface Changed: Please list interface changes

Test Programs: List test programs

Put in Release Notes: Yes/No

Module(s): Module Names change impacts.

Description: Describe your changes here...

Bug fix on assertion check.


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