source: trunk/src/STIdxIter.cpp@ 2912

Last change on this file since 2912 was 2912, 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: List test programs

Put in Release Notes: Yes/No

Module(s): Module Names change impacts.

Description: Describe your changes here...

Minor improvement on STIdxIter2.


File size: 16.4 KB
Line 
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>
7#include <casa/Utilities/DataType.h>
8#include <tables/Tables/ScalarColumn.h>
9#include <tables/Tables/TableRow.h>
10#include <tables/Tables/TableRecord.h>
11#include "STIdxIter.h"
12
13namespace asap {
14
15IndexIterator::IndexIterator( IPosition &shape )
16 : niter_m( 0 )
17{
18 nfield_m = shape.nelements() ;
19 prod_m.resize( nfield_m ) ;
20 idx_m.resize( nfield_m ) ;
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] ;
25 idx_m[i] = 0 ;
26 }
27 maxiter_m = prod_m[0] * shape[0] ;
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 ;
40 for ( Int i = 0 ; i < nfield_m ; i++ ) {
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 )
50 : arr_m( arr ),
51 pos_m( 1 )
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 }
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 }
70// cout << "shape=" << shape << endl ;
71 iter_m = new IndexIterator( shape ) ;
72 current_m.resize( ncol_m ) ;
73}
74
75ArrayIndexIterator::~ArrayIndexIterator()
76{
77 delete iter_m ;
78}
79
80Vector<uInt> ArrayIndexIterator::current()
81{
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 ;
86}
87
88Bool ArrayIndexIterator::pastEnd()
89{
90 return iter_m->pastEnd() ;
91}
92
93ArrayIndexIteratorNormal::ArrayIndexIteratorNormal( Matrix<uInt> &arr,
94 vector< vector<uInt> > idlist )
95 : ArrayIndexIterator( arr, idlist )
96{
97 storage_m.resize( nrow_m ) ;
98}
99
100void ArrayIndexIteratorNormal::next()
101{
102 iter_m->next() ;
103}
104
105Vector<uInt> ArrayIndexIteratorNormal::getRows( StorageInitPolicy policy )
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() ;
119 return Vector<uInt>( pos_m, p, policy ) ;
120}
121
122ArrayIndexIteratorAcc::ArrayIndexIteratorAcc( Matrix<uInt> &arr,
123 vector< vector<uInt> > idlist )
124 : ArrayIndexIterator( arr, idlist )
125{
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 // ...
132 storage_m.resize( arr_m.nelements()+nrow_m ) ;
133 // initialize constant temporary storage
134 uInt *p = storage_m.storage() ;
135 for ( uInt i = 0 ; i < nrow_m ; i++ ) {
136 *p = i ;
137 p++ ;
138 }
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 // ...
144 len_m.resize( ncol_m+1 ) ;
145 p = len_m.storage() ;
146 for ( uInt i = 0 ; i < ncol_m+1 ; i++ ) {
147 *p = nrow_m ;
148 p++ ;
149// cout << "len[" << i << "]=" << len_m[i] << endl ;
150 }
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 }
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 ;
167}
168
169void ArrayIndexIteratorAcc::next()
170{
171 prev_m = iter_m->current() ;
172 iter_m->next() ;
173}
174
175Vector<uInt> ArrayIndexIteratorAcc::getRows( StorageInitPolicy policy )
176{
177 Block<uInt> v = iter_m->current() ;
178 Int c = isChanged( v ) ;
179// cout << "v=" << Vector<uInt>(IPosition(1,v.nelements()),v.storage(),SHARE) << endl ;
180// cout << "c=" << c << endl ;
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++ ;
187// cout << "offset=" << offset << endl ;
188 return Vector<uInt>( pos_m, storage_m.storage()+offset*nrow_m, policy ) ;
189 }
190 Int offset = c - 1 ;
191 while( offset >= 0 && skip_m[offset] )
192 offset-- ;
193 offset++ ;
194// cout << "offset = " << offset << endl ;
195 uInt *base = storage_m.storage() + offset * nrow_m ;
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 ;
198 for ( Int i = c ; i < ncol_m ; i++ ) {
199 base = updateStorage( i, base, idxlist_m[i][v[i]] ) ;
200// cout << "len_m[" << i << "]=" << len_m[i] << endl ;
201// cout << "base=" << Vector<uInt>(IPosition(1,len_m[i]),base,SHARE) << endl ;
202 }
203 pos_m[0] = len_m[ncol_m] ;
204// cout << "pos_m=" << pos_m << endl ;
205// cout << "ret=" << Vector<uInt>( pos_m, base, policy ) << endl ;
206 return Vector<uInt>( pos_m, base, policy ) ;
207}
208
209Int ArrayIndexIteratorAcc::isChanged( Block<uInt> &idx )
210{
211 Int i = 0 ;
212 while( i < ncol_m && idx[i] == prev_m[i] )
213 i++ ;
214 return i ;
215}
216
217uInt *ArrayIndexIteratorAcc::updateStorage( Int &icol,
218 uInt *base,
219 uInt &v )
220{
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
225 uInt *p ;
226 if ( skip_m[icol] ) {
227 // skip update, just update len_m[icol] and pass appropriate pointer
228// cout << "skip " << icol << endl ;
229 p = base ;
230 len_m[icol+1] = len_m[icol] ;
231 }
232 else {
233// cout << "update " << icol << endl ;
234 uInt len = 0 ;
235 p = storage_m.storage() + (icol+1) * nrow_m ;
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
241 const uInt *warr_p = arr_p + icol * nrow_m ;
242 for ( uInt i = 0 ; i < len_m[icol] ; i++ ) {
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++ ;
257 }
258 arr_m.freeStorage( arr_p, b ) ;
259 len_m[icol+1] = len ;
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
292Vector<uInt> STIdxIter::getRows( StorageInitPolicy policy )
293{
294 return iter_m->getRows( policy ) ;
295}
296
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 ;
328 Vector<uInt> v ;
329 for ( uInt i = 0 ; i < ncol ; i++ ) {
330 col.attach( t, cols[i] ) ;
331 v.reference( arr.column( i ) ) ;
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() ;
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]
372 Matrix<uInt> arr( nrow, ncol ) ;
373 Vector<uInt> v ;
374 ROScalarColumn<uInt> col ;
375 for ( uInt i = 0 ; i < ncol ; i++ ) {
376 col.attach( t, cols[i] ) ;
377 v.reference( arr.column( i ) ) ;
378 col.getColumn( v ) ;
379 }
380 iter_m = new ArrayIndexIteratorAcc( arr ) ;
381}
382
383STIdxIterExAcc::STIdxIterExAcc()
384 : STIdxIter(),
385 srctypeid_m( -1 ),
386 srcnameid_m( -1 )
387{
388}
389
390STIdxIterExAcc::STIdxIterExAcc( const string &name,
391 const vector<string> &cols )
392 : STIdxIter( name, cols ),
393 srctypeid_m( -1 ),
394 srcnameid_m( -1 )
395{
396 Table t( name, Table::Old ) ;
397 init( t, cols ) ;
398}
399
400STIdxIterExAcc::STIdxIterExAcc( const CountedPtr<Scantable> &s,
401 const vector<string> &cols )
402 : STIdxIter( s, cols ),
403 srctypeid_m( -1 ),
404 srcnameid_m( -1 )
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{
455 convertArray( out, in ) ;
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 }
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 ;
478 }
479 }
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 }
489}
490
491Int STIdxIterExAcc::getSrcType()
492{
493 if ( srctypeid_m >= 0 )
494 return (Int)(iter_m->current()[srctypeid_m]) ;
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
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 num_row_ = table_.nrow();
610 for (uInt i = 0; i < cols_.size(); ++i) {
611 addSortKey(cols_[i]);
612 }
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 void *raw_storage = malloc(sizeof(T) * num_row_);
656 T *storage = reinterpret_cast<T*>(raw_storage);
657 Vector<T> array(IPosition(1, num_row_), storage, SHARE);
658 ROScalarColumn<T> col(table_, name);
659 col.getColumn(array);
660 sorter_.sortKey(storage, U, 0, Sort::Ascending);
661 pointer_.push_back(raw_storage);
662}
663} // namespace
664
Note: See TracBrowser for help on using the repository browser.