source: trunk/src/STGrid.cpp @ 3106

Last change on this file since 3106 was 3106, checked in by Takeshi Nakazato, 8 years ago

New Development: No

JIRA Issue: No

Ready for Test: Yes/No?

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...


Check-in asap modifications from Jim regarding casacore namespace conversion.

File size: 63.6 KB
Line 
1//
2// C++ Implementation: STGrid
3//
4// Description:
5//
6//
7// Author: Takeshi Nakazato <takeshi.nakazato@nao.ac.jp>, (C) 2011
8//
9// Copyright: See COPYING file that comes with this distribution
10//
11//
12
13// ASAP
14// STGrid must be included first to avoid compiler warning related
15// with _XOPEN_SOURCE
16#include "STGrid.h"
17#include "MathUtils.h"
18#include <atnf/PKSIO/SrcType.h>
19
20#include <casa/BasicSL/String.h>
21#include <casa/Arrays/Vector.h>
22#include <casa/Arrays/ArrayMath.h>
23#include <casa/Quanta/Quantum.h>
24#include <casa/Quanta/QuantumHolder.h>
25#include <casa/Utilities/CountedPtr.h>
26#include <casa/Logging/LogIO.h>
27
28#include <coordinates/Coordinates/DirectionCoordinate.h>
29
30#include <tables/Tables/Table.h>
31#include <tables/Tables/TableRecord.h>
32#include <tables/Tables/TableRow.h>
33#include <tables/TaQL/ExprNode.h>
34#include <tables/Tables/ScalarColumn.h>
35#include <tables/Tables/ArrayColumn.h>
36#include <tables/Tables/TableCopy.h>
37
38#include <measures/Measures/MDirection.h>
39
40using namespace std ;
41using namespace concurrent ;
42using namespace casacore;
43using namespace asap ;
44
45namespace asap {
46
47// for performance check
48double eToInt = 0.0 ;
49double eGetWeight = 0.0 ;
50
51// constructor
52STGrid::STGrid()
53  : vshape_( 1 ), wshape_( 2 ), dshape_( 2 )
54{
55  init() ;
56}
57
58STGrid::STGrid( const string infile )
59  : vshape_( 1 ), wshape_( 2 ), dshape_( 2 )
60{
61  init() ;
62
63  setFileIn( infile ) ;
64}
65
66STGrid::STGrid( const vector<string> infile )
67{
68  init() ;
69
70  setFileList( infile ) ;
71}
72
73void  STGrid::init()
74{
75  ifno_ = -1 ;
76  nx_ = -1 ;
77  ny_ = -1 ;
78  npol_ = 0 ;
79  nchan_ = 0 ;
80  nrow_ = 0 ;
81  cellx_ = 0.0 ;
82  celly_ = 0.0 ;
83  center_ = Vector<Double> ( 2, 0.0 ) ;
84  convType_ = "BOX" ;
85  wtype_ = "UNIFORM" ;
86  convSupport_ = -1 ;
87  userSupport_ = -1 ;
88  truncate_ = "";
89  gwidth_ = "";
90  jwidth_ = "";
91  convSampling_ = 100 ;
92  nprocessed_ = 0 ;
93  nchunk_ = 0 ;
94
95  // initialize user input
96  nxUI_ = -1 ;
97  nyUI_ = -1 ;
98  cellxUI_ = "" ;
99  cellyUI_ = "" ;
100  centerUI_ = "" ;
101  doclip_ = False ;
102}
103
104void STGrid::setFileIn( const string infile )
105{
106  nfile_ = 1 ;
107  String name( infile ) ;
108  infileList_.resize( nfile_ ) ;
109  infileList_[0] = String(infile) ;
110}
111
112void STGrid::setFileList( const vector<string> infile )
113{
114  nfile_ = infile.size() ;
115  infileList_.resize( nfile_ ) ;
116  for ( uInt i = 0 ; i < nfile_ ; i++ ) {
117    infileList_[i] = infile[i] ;
118  }
119}
120
121void STGrid::setPolList( vector<unsigned int> pols )
122{
123  pollist_.assign( Vector<uInt>( pols ) ) ;
124}
125
126void STGrid::setScanList( vector<unsigned int> scans )
127{
128  scanlist_.assign( Vector<uInt>( scans ) ) ;
129}
130
131void STGrid::setWeight( const string wType )
132{
133  wtype_ = String( wType ) ;
134  wtype_.upcase() ;
135}
136
137void STGrid::defineImage( int nx,
138                          int ny,
139                          string scellx,
140                          string scelly,
141                          string scenter )
142{
143  nxUI_ = (Int)nx ;
144  nyUI_ = (Int)ny ;
145  cellxUI_ = String( scellx ) ;
146  cellyUI_ = String( scelly ) ;
147  centerUI_ = String( scenter ) ;
148}
149 
150void STGrid::setFunc( string convType,
151                      int convSupport,
152                      string truncate,
153                      string gwidth,
154                      string jwidth )
155{
156  convType_ = String( convType ) ;
157  convType_.upcase() ;
158  userSupport_ = (Int)convSupport ;
159  truncate_ = String( truncate );
160  gwidth_ = String( gwidth );
161  jwidth_ = String( jwidth );
162}
163
164#define NEED_UNDERSCORES
165#if defined(NEED_UNDERSCORES)
166#define ggridsd ggridsd_
167#endif
168extern "C" {
169   void ggridsd(Double*,
170                const Complex*,
171                Int*,
172                Int*,
173                Int*,
174                const Int*,
175                const Int*,
176                const Float*,
177                Int*,
178                Int*,
179                Complex*,
180                Float*,
181                Int*,
182                Int*,
183                Int *,
184                Int *,
185                Int*,
186                Int*,
187                Float*,
188                Int*,
189                Int*,
190                Double*);
191}
192void STGrid::call_ggridsd( Array<Double> &xypos,
193                           Array<Complex> &spectra,
194                           Int &nvispol,
195                           Int &nvischan,
196                           Array<Int> &flagtra,
197                           Array<Int> &flagrow,
198                           Array<Float> &weight,
199                           Int &nrow,
200                           Int &irow,
201                           Array<Complex> &gdata,
202                           Array<Float> &gwgt,
203                           Int &nx,
204                           Int &ny,
205                           Int &npol,
206                           Int &nchan,
207                           Int &support,
208                           Int &sampling,
209                           Vector<Float> &convFunc,
210                           Int *chanMap,
211                           Int *polMap )
212{
213  // parameters for gridding
214  Int idopsf = 0 ;
215  Int len = npol*nchan ;
216  Double *sumw_p = new Double[len] ;
217  {
218    Double *work_p = sumw_p ;
219    for ( Int i = 0 ; i < len ; i++ ) {
220      *work_p = 0.0 ;
221      work_p++ ;
222    }
223  }
224
225  // prepare pointer
226  Bool deletePos, deleteData, deleteWgt, deleteFlag, deleteFlagR, deleteConv, deleteDataG, deleteWgtG ;
227  Double *xy_p = xypos.getStorage( deletePos ) ;
228  const Complex *values_p = spectra.getStorage( deleteData ) ;
229  const Int *flag_p = flagtra.getStorage( deleteFlag ) ;
230  const Int *rflag_p = flagrow.getStorage( deleteFlagR ) ;
231  const Float *wgt_p = weight.getStorage( deleteWgt ) ;
232  Complex *grid_p = gdata.getStorage( deleteDataG ) ;
233  Float *wgrid_p = gwgt.getStorage( deleteWgtG ) ;
234  Float *conv_p = convFunc.getStorage( deleteConv ) ;
235
236  // pass copy of irow to ggridsd since it will be modified in theroutine
237  Int irowCopy = irow ;
238     
239  // call ggridsd
240  ggridsd( xy_p,
241           values_p,
242           &nvispol,
243           &nvischan,
244           &idopsf,
245           flag_p,
246           rflag_p,
247           wgt_p,
248           &nrow,
249           &irowCopy,
250           grid_p,
251           wgrid_p,
252           &nx,
253           &ny,
254           &npol,
255           &nchan,
256           &support,
257           &sampling,
258           conv_p,
259           chanMap,
260           polMap,
261           sumw_p ) ;
262
263  // finalization
264  xypos.putStorage( xy_p, deletePos ) ;
265  spectra.freeStorage( values_p, deleteData ) ;
266  flagtra.freeStorage( flag_p, deleteFlag ) ;
267  flagrow.freeStorage( rflag_p, deleteFlagR ) ;
268  weight.freeStorage( wgt_p, deleteWgt ) ;
269  gdata.putStorage( grid_p, deleteDataG ) ;
270  gwgt.putStorage( wgrid_p, deleteWgtG ) ;
271  convFunc.putStorage( conv_p, deleteConv ) ;
272  delete sumw_p ;
273}
274
275#define NEED_UNDERSCORES
276#if defined(NEED_UNDERSCORES)
277#define ggridsd2 ggridsd2_
278#endif
279extern "C" {
280   void ggridsd2(Double*,
281                 const Complex*,
282                 Int*,
283                 Int*,
284                 Int*,
285                 const Int*,
286                 const Int*,
287                 const Float*,
288                 Int*,
289                 Int*,
290                 Complex*,
291                 Float*,
292                 Int*,
293                 Complex*,
294                 Float*,
295                 Float*,
296                 Complex*,
297                 Float*,
298                 Float*,
299                 Int*,
300                 Int*,
301                 Int *,
302                 Int *,
303                 Int*,
304                 Int*,
305                 Float*,
306                 Int*,
307                 Int*,
308                 Double*);
309}
310void STGrid::call_ggridsd2( Array<Double> &xypos,
311                            Array<Complex> &spectra,
312                            Int &nvispol,
313                            Int &nvischan,
314                            Array<Int> &flagtra,
315                            Array<Int> &flagrow,
316                            Array<Float> &weight,
317                            Int &nrow,
318                            Int &irow,
319                            Array<Complex> &gdata,
320                            Array<Float> &gwgt,
321                            Array<Int> &npoints,
322                            Array<Complex> &clipmin,
323                            Array<Float> &clipwmin,
324                            Array<Float> &clipcmin,
325                            Array<Complex> &clipmax,
326                            Array<Float> &clipwmax,
327                            Array<Float> &clipcmax,
328                            Int &nx,
329                            Int &ny,
330                            Int &npol,
331                            Int &nchan,
332                            Int &support,
333                            Int &sampling,
334                            Vector<Float> &convFunc,
335                            Int *chanMap,
336                            Int *polMap )
337{
338  // parameters for gridding
339  Int idopsf = 0 ;
340  Int len = npol*nchan ;
341  Double *sumw_p = new Double[len] ;
342  {
343    Double *work_p = sumw_p ;
344    for ( Int i = 0 ; i < len ; i++ ) {
345      *work_p = 0.0 ;
346      work_p++ ;
347    }
348  }
349
350  // prepare pointer
351  Bool deletePos, deleteData, deleteWgt, deleteFlag, deleteFlagR, deleteConv, deleteDataG, deleteWgtG, deleteNpts, deleteCMin, deleteCWMin, deleteCCMin, deleteCMax, deleteCWMax, deleteCCMax ;
352  Double *xy_p = xypos.getStorage( deletePos ) ;
353  const Complex *values_p = spectra.getStorage( deleteData ) ;
354  const Int *flag_p = flagtra.getStorage( deleteFlag ) ;
355  const Int *rflag_p = flagrow.getStorage( deleteFlagR ) ;
356  const Float *wgt_p = weight.getStorage( deleteWgt ) ;
357  Complex *grid_p = gdata.getStorage( deleteDataG ) ;
358  Float *wgrid_p = gwgt.getStorage( deleteWgtG ) ;
359  Float *conv_p = convFunc.getStorage( deleteConv ) ;
360  Int *npts_p = npoints.getStorage( deleteNpts ) ;
361  Complex *cmin_p = clipmin.getStorage( deleteCMin ) ;
362  Float *cwmin_p = clipwmin.getStorage( deleteCWMin ) ;
363  Float *ccmin_p = clipcmin.getStorage( deleteCCMin ) ;
364  Complex *cmax_p = clipmax.getStorage( deleteCMax ) ;
365  Float *cwmax_p = clipwmax.getStorage( deleteCWMax ) ;
366  Float *ccmax_p = clipcmax.getStorage( deleteCCMax ) ;
367
368  // pass copy of irow to ggridsd since it will be modified in theroutine
369  Int irowCopy = irow ;
370     
371  // call ggridsd
372  ggridsd2( xy_p,
373            values_p,
374            &nvispol,
375            &nvischan,
376            &idopsf,
377            flag_p,
378            rflag_p,
379            wgt_p,
380            &nrow,
381            &irowCopy,
382            grid_p,
383            wgrid_p,
384            npts_p,
385            cmin_p,
386            cwmin_p,
387            ccmin_p,
388            cmax_p,
389            cwmax_p,
390            ccmax_p,
391            &nx,
392            &ny,
393            &npol,
394            &nchan,
395            &support,
396            &sampling,
397            conv_p,
398            chanMap,
399            polMap,
400            sumw_p ) ;
401
402  // finalization
403  xypos.putStorage( xy_p, deletePos ) ;
404  spectra.freeStorage( values_p, deleteData ) ;
405  flagtra.freeStorage( flag_p, deleteFlag ) ;
406  flagrow.freeStorage( rflag_p, deleteFlagR ) ;
407  weight.freeStorage( wgt_p, deleteWgt ) ;
408  gdata.putStorage( grid_p, deleteDataG ) ;
409  gwgt.putStorage( wgrid_p, deleteWgtG ) ;
410  convFunc.putStorage( conv_p, deleteConv ) ;
411  clipmin.putStorage( cmin_p, deleteCMin ) ;
412  clipwmin.putStorage( cwmin_p, deleteCWMin ) ;
413  clipcmin.putStorage( ccmin_p, deleteCCMin ) ;
414  clipmax.putStorage( cmax_p, deleteCMax ) ;
415  clipwmax.putStorage( cwmax_p, deleteCWMax ) ;
416  clipcmax.putStorage( ccmax_p, deleteCCMax ) ;
417  delete sumw_p ;
418}
419
420void STGrid::grid()
421{
422  LogIO os( LogOrigin("STGrid", "grid", WHERE) ) ;
423  double t0,t1 ;
424
425  // data selection
426  t0 = mathutil::gettimeofday_sec() ;
427  selectData() ;
428  t1 = mathutil::gettimeofday_sec() ;
429  os << LogIO::DEBUGGING << "selectData: elapsed time is " << t1-t0 << " sec." << LogIO::POST ;
430
431  setupGrid() ;
432  setupArray() ;
433
434  if ( wtype_.compare("UNIFORM") != 0 &&
435       wtype_.compare("TINT") != 0 &&
436       wtype_.compare("TSYS") != 0 &&
437       wtype_.compare("TINTSYS") != 0 ) {
438    LogIO os( LogOrigin("STGrid", "grid", WHERE) ) ;
439    os << LogIO::WARN << "Unsupported weight type '" << wtype_ << "', apply UNIFORM weight" << LogIO::POST ;
440    wtype_ = "UNIFORM" ;
441  }
442
443  // Warn if gauss or gjinc gridding with non-square cells
444  if ((cellx_ != celly_) && (convType_=="GAUSS"||convType_=="GJINC")) {
445    os << LogIO::WARN
446       << "The " << convType_ << " gridding doesn't support non-square grid." << endl
447       << "Result may be wrong." << LogIO::POST;
448  }
449
450  // grid parameter
451  os << LogIO::DEBUGGING ;
452  os << "----------" << endl ;
453  os << "Data selection summary" << endl ;
454  os << "   ifno = " << ifno_ << endl ;
455  os << "   pollist = " << pollist_ << endl ;
456  os << "   scanlist = " << scanlist_ << endl ;
457  os << "----------" << endl ;
458  os << "Grid parameter summary" << endl ;
459  os << "   (nx,ny) = (" << nx_ << "," << ny_ << ")" << endl ;
460  os << "   (cellx,celly) = (" << cellx_ << "," << celly_ << ")" << endl ;
461  os << "   center = " << center_ << endl ;
462  os << "   weighting = " << wtype_ << endl ;
463  os << "   convfunc = " << convType_ << endl;
464  if (convType_ == "GAUSS") {
465    os << "      gwidth = " << gwidth_ << endl;
466    os << "      truncate = " << truncate_ << endl;
467  }
468  else if (convType_ == "GJINC") {
469    os << "      gwidth = " << gwidth_ << endl;
470    os << "      jwidth = " << jwidth_ << endl;
471    os << "      truncate = " << truncate_ << endl;
472  }
473  else {
474    os << "      support = " << userSupport_ << endl;
475  }
476  os << "   doclip = " << (doclip_?"True":"False") << endl ;
477  os << "----------" << LogIO::POST ;
478  os << LogIO::NORMAL ;
479
480  if ( doclip_ )
481    gridPerRowWithClipping() ;
482  else
483    gridPerRow() ;
484}
485
486void STGrid::updateChunkShape()
487{
488  // TODO: nchunk_ must be determined from nchan_, npol_, and (nx_,ny_)
489  //       by considering data size to be allocated for ggridsd input/output
490  nchunk_ = 400 ;
491  nchunk_ = min( nchunk_, nrow_ ) ;
492  vshape_ = IPosition( 1, nchunk_ ) ;
493  wshape_ = IPosition( 2, nchan_, nchunk_ ) ;
494  dshape_ = IPosition( 2, 2, nchunk_ ) ;
495}
496
497struct STGChunk {
498  Int nrow ;
499  Array<Complex> spectra;
500  Array<Int> flagtra;
501  Array<Int> rflag;
502  Array<Float> weight;
503  Array<Double> direction;
504  STGChunk(IPosition const &wshape, IPosition const &vshape,
505           IPosition const &dshape)
506    : spectra(wshape), flagtra(wshape), rflag(vshape), weight(wshape),
507      direction(dshape)
508  { }
509};
510
511struct STCommonData {
512  Int gnx;
513  Int gny;
514  Int *chanMap;
515  Vector<Float> convFunc ;
516  Array<Complex> gdataArrC;
517  Array<Float> gwgtArr;
518  STCommonData(IPosition const &gshape, Array<Float> const &data)
519    : gdataArrC(gshape, 0.0), gwgtArr(data) {}
520};
521
522struct STCommonDataWithClipping {
523  Int gnx;
524  Int gny;
525  Int *chanMap;
526  Vector<Float> convFunc ;
527  Array<Complex> gdataArrC;
528  Array<Float> gwgtArr;
529  Array<Int> npoints ;
530  Array<Complex> clipMin ;
531  Array<Float> clipWMin ;
532  Array<Float> clipCMin ;
533  Array<Complex> clipMax ;
534  Array<Float> clipWMax ;
535  Array<Float> clipCMax ; 
536  STCommonDataWithClipping(IPosition const &gshape,
537                           IPosition const &pshape,
538                           Array<Float> const &data)
539    : gdataArrC(gshape, 0.0),
540      gwgtArr(data),
541      npoints(pshape, 0),
542      clipMin(gshape, Complex(FLT_MAX,0.0)),
543      clipWMin(gshape, 0.0),
544      clipCMin(gshape, 0.0),
545      clipMax(gshape, Complex(-FLT_MAX,0.0)),
546      clipWMax(gshape, 0.0),
547      clipCMax(gshape, 0.0)
548  {}
549};
550
551#define DO_AHEAD 3
552
553struct STContext {
554  STCommonData &common;
555  FIFO<STGChunk *, DO_AHEAD> queue;
556  STGrid *const self;
557  const Int pol;
558  STContext(STGrid *obj, STCommonData &common, Int pol)
559    : common(common), self(obj), pol(pol) {}
560};
561
562struct STContextWithClipping {
563  STCommonDataWithClipping &common;
564  FIFO<STGChunk *, DO_AHEAD> queue;
565  STGrid *const self;
566  const Int pol;
567  STContextWithClipping(STGrid *obj, STCommonDataWithClipping &common, Int pol)
568    : common(common), self(obj), pol(pol) {}
569};
570
571
572bool STGrid::produceChunk(void *ctx) throw(PCException)
573{
574  STContext &context = *(STContext *)ctx;
575  if ( context.self->nprocessed_ >= context.self->nrow_ ) {
576    return false;
577  }
578  STGChunk *chunk = new STGChunk(context.self->wshape_,
579                                 context.self->vshape_,
580                                 context.self->dshape_);
581
582  double t0 = mathutil::gettimeofday_sec() ;
583  chunk->nrow = context.self->getDataChunk(
584        context.self->wshape_, context.self->vshape_, context.self->dshape_,
585        chunk->spectra, chunk->direction,
586        chunk->flagtra, chunk->rflag, chunk->weight);
587  double t1 = mathutil::gettimeofday_sec() ;
588  context.self->eGetData_ += t1-t0 ;
589
590  context.queue.lock();
591  context.queue.put(chunk);
592  context.queue.unlock();
593  return true;
594}
595
596void STGrid::consumeChunk(void *ctx) throw(PCException)
597{
598  STContext &context = *(STContext *)ctx;
599  STGChunk *chunk = NULL;
600  try {
601    context.queue.lock();
602    chunk = context.queue.get();
603    context.queue.unlock();
604  } catch (FullException &e) {
605    context.queue.unlock();
606    // TODO: log error
607    throw PCException();
608  }
609
610  double t0, t1 ;
611  // world -> pixel
612  Array<Double> xypos( context.self->dshape_ ) ;
613  t0 = mathutil::gettimeofday_sec() ;
614  context.self->toPixel( chunk->direction, xypos ) ;
615  t1 = mathutil::gettimeofday_sec() ;
616  context.self->eToPixel_ += t1-t0 ;
617   
618  // call ggridsd
619  Int nvispol = 1 ;
620  Int irow = -1 ;
621  t0 = mathutil::gettimeofday_sec() ;
622  context.self->call_ggridsd( xypos,
623                chunk->spectra,
624                nvispol,
625                context.self->nchan_,
626                chunk->flagtra,
627                chunk->rflag,
628                chunk->weight,
629                chunk->nrow,
630                irow,
631                context.common.gdataArrC,
632                context.common.gwgtArr,
633                context.common.gnx,
634                context.common.gny,
635                context.self->npol_,
636                context.self->nchan_,
637                context.self->convSupport_,
638                context.self->convSampling_,
639                context.common.convFunc,
640                context.common.chanMap,
641                (Int*)&context.pol ) ;
642  t1 = mathutil::gettimeofday_sec() ;
643  context.self->eGGridSD_ += t1-t0 ;
644 
645  delete chunk;
646}
647
648void STGrid::gridPerRow()
649{
650  LogIO os( LogOrigin("STGrid", "gridPerRow", WHERE) ) ;
651  double t0, t1 ;
652
653
654  // grid data
655  // Extend grid plane with convSupport_
656  //   Int gnx = nx_+convSupport_*2 ;
657  //   Int gny = ny_+convSupport_*2 ;
658  Int gnx = nx_;
659  Int gny = ny_;
660
661  IPosition gshape( 4, gnx, gny, npol_, nchan_ ) ;
662  // 2011/12/20 TN
663  // data_ and gwgtArr share storage
664  data_.resize( gshape ) ;
665  data_ = 0.0 ;
666  flag_.resize( gshape ) ;
667  flag_ = (uChar)0;
668  STCommonData common = STCommonData(gshape, data_);
669  common.gnx = gnx ;
670  common.gny = gny ;
671
672  // parameters for gridding
673  Int *chanMap = new Int[nchan_] ;
674  for ( Int i = 0 ; i < nchan_ ; i++ ) {
675    chanMap[i] = i ;
676  }
677  common.chanMap = chanMap;
678
679  // convolution kernel
680  t0 = mathutil::gettimeofday_sec() ;
681  setConvFunc( common.convFunc ) ;
682  t1 = mathutil::gettimeofday_sec() ;
683  os << LogIO::DEBUGGING << "setConvFunc: elapsed time is " << t1-t0 << " sec." << LogIO::POST ;
684
685  // for performance check
686  eGetData_ = 0.0 ;
687  eToPixel_ = 0.0 ;
688  eGGridSD_ = 0.0 ;
689  double eInitPol = 0.0 ;
690
691  for ( uInt ifile = 0 ; ifile < nfile_ ; ifile++ ) {
692    initTable( ifile ) ;
693
694    os << "start table " << ifile << ": " << infileList_[ifile] << LogIO::POST ;   
695    Broker broker = Broker(produceChunk, consumeChunk);
696    for ( Int ipol = 0 ; ipol < npol_ ; ipol++ ) {
697      t0 = mathutil::gettimeofday_sec() ;
698      initPol( ipol ) ; // set ptab_ and attach()
699      t1 = mathutil::gettimeofday_sec() ;
700      eInitPol += t1-t0 ;
701     
702      STContext context(this, common, ipol);
703     
704      os << "start pol " << ipol << LogIO::POST ;
705     
706      nprocessed_ = 0 ;
707#if 1
708      broker.runProducerAsMasterThread(&context, DO_AHEAD);
709#else
710      for (;;) {
711        bool produced = produceChunk(&context);
712        if (! produced) {
713          break;
714        }
715        consumeChunk(&context);
716      }
717#endif
718
719      os << "end pol " << ipol << LogIO::POST ;
720
721    }
722    os << "end table " << ifile << LogIO::POST ;   
723  }
724  os << LogIO::DEBUGGING << "initPol: elapsed time is " << eInitPol << " sec." << LogIO::POST ;
725  os << LogIO::DEBUGGING << "getData: elapsed time is " << eGetData_-eToInt-eGetWeight << " sec." << LogIO::POST ;
726  os << LogIO::DEBUGGING << "toPixel: elapsed time is " << eToPixel_ << " sec." << LogIO::POST ;
727  os << LogIO::DEBUGGING << "ggridsd: elapsed time is " << eGGridSD_ << " sec." << LogIO::POST ;
728  os << LogIO::DEBUGGING << "toInt: elapsed time is " << eToInt << " sec." << LogIO::POST ;
729  os << LogIO::DEBUGGING << "getWeight: elapsed time is " << eGetWeight << " sec." << LogIO::POST ;
730 
731  delete chanMap ;
732
733  // set data
734  setData( common.gdataArrC, common.gwgtArr ) ;
735
736}
737
738void STGrid::consumeChunkWithClipping(void *ctx) throw(PCException)
739{
740  STContextWithClipping &context = *(STContextWithClipping *)ctx;
741  STGChunk *chunk = NULL;
742  try {
743    context.queue.lock();
744    chunk = context.queue.get();
745    context.queue.unlock();
746  } catch (FullException &e) {
747    context.queue.unlock();
748    // TODO: log error
749    throw PCException();
750  }
751
752  double t0, t1 ;
753  // world -> pixel
754  Array<Double> xypos( context.self->dshape_ ) ;
755  t0 = mathutil::gettimeofday_sec() ;
756  context.self->toPixel( chunk->direction, xypos ) ;
757  t1 = mathutil::gettimeofday_sec() ;
758  context.self->eToPixel_ += t1-t0 ;
759   
760  // call ggridsd
761  Int nvispol = 1 ;
762  Int irow = -1 ;
763  t0 = mathutil::gettimeofday_sec() ;
764  context.self->call_ggridsd2( xypos,
765                chunk->spectra,
766                nvispol,
767                context.self->nchan_,
768                chunk->flagtra,
769                chunk->rflag,
770                chunk->weight,
771                chunk->nrow,
772                irow,
773                context.common.gdataArrC,
774                context.common.gwgtArr,
775                context.common.npoints,
776                context.common.clipMin,
777                context.common.clipWMin,
778                context.common.clipCMin,
779                context.common.clipMax,
780                context.common.clipWMax,
781                context.common.clipCMax,
782                context.common.gnx,
783                context.common.gny,
784                context.self->npol_,
785                context.self->nchan_,
786                context.self->convSupport_,
787                context.self->convSampling_,
788                context.common.convFunc,
789                context.common.chanMap,
790                (Int*)&context.pol ) ;
791  t1 = mathutil::gettimeofday_sec() ;
792  context.self->eGGridSD_ += t1-t0 ;
793 
794  delete chunk;
795}
796
797void STGrid::gridPerRowWithClipping()
798{
799  LogIO os( LogOrigin("STGrid", "gridPerRowWithClipping", WHERE) ) ;
800  double t0, t1 ;
801
802
803  // grid data
804  // Extend grid plane with convSupport_
805  //   Int gnx = nx_+convSupport_*2 ;
806  //   Int gny = ny_+convSupport_*2 ;
807  Int gnx = nx_;
808  Int gny = ny_;
809
810  IPosition gshape( 4, gnx, gny, npol_, nchan_ ) ;
811  IPosition pshape( 3, gnx, gny, npol_ ) ;
812  // 2011/12/20 TN
813  // data_ and gwgtArr share storage
814  data_.resize( gshape ) ;
815  data_ = 0.0 ;
816  flag_.resize( gshape ) ;
817  flag_ = (uChar)0;
818  STCommonDataWithClipping common = STCommonDataWithClipping( gshape,
819                                                              pshape,
820                                                              data_ ) ;
821  common.gnx = gnx ;
822  common.gny = gny ;
823
824  // parameters for gridding
825  Int *chanMap = new Int[nchan_] ;
826  for ( Int i = 0 ; i < nchan_ ; i++ ) {
827    chanMap[i] = i ;
828  }
829  common.chanMap = chanMap;
830
831  // convolution kernel
832  t0 = mathutil::gettimeofday_sec() ;
833  setConvFunc( common.convFunc ) ;
834  t1 = mathutil::gettimeofday_sec() ;
835  os << LogIO::DEBUGGING << "setConvFunc: elapsed time is " << t1-t0 << " sec." << LogIO::POST ;
836
837  // for performance check
838  eGetData_ = 0.0 ;
839  eToPixel_ = 0.0 ;
840  eGGridSD_ = 0.0 ;
841  double eInitPol = 0.0 ;
842
843  for ( uInt ifile = 0 ; ifile < nfile_ ; ifile++ ) {
844    initTable( ifile ) ;
845
846    os << "start table " << ifile << ": " << infileList_[ifile] << LogIO::POST ;   
847    Broker broker = Broker(produceChunk, consumeChunkWithClipping);
848    for ( Int ipol = 0 ; ipol < npol_ ; ipol++ ) {
849      t0 = mathutil::gettimeofday_sec() ;
850      initPol( ipol ) ; // set ptab_ and attach()
851      t1 = mathutil::gettimeofday_sec() ;
852      eInitPol += t1-t0 ;
853     
854      STContextWithClipping context(this, common, ipol);
855     
856      os << "start pol " << ipol << LogIO::POST ;
857     
858      nprocessed_ = 0 ;
859#if 1
860      broker.runProducerAsMasterThread(&context, DO_AHEAD);
861#else
862      for (;;) {
863        bool produced = produceChunk(&context);
864        if (! produced) {
865          break;
866        }
867        consumeChunkWithClipping(&context);
868      }
869#endif
870
871      os << "end pol " << ipol << LogIO::POST ;
872
873    }
874    os << "end table " << ifile << LogIO::POST ;   
875  }
876  os << LogIO::DEBUGGING << "initPol: elapsed time is " << eInitPol << " sec." << LogIO::POST ;
877  os << LogIO::DEBUGGING << "getData: elapsed time is " << eGetData_-eToInt-eGetWeight << " sec." << LogIO::POST ;
878  os << LogIO::DEBUGGING << "toPixel: elapsed time is " << eToPixel_ << " sec." << LogIO::POST ;
879  os << LogIO::DEBUGGING << "ggridsd2: elapsed time is " << eGGridSD_ << " sec." << LogIO::POST ;
880  os << LogIO::DEBUGGING << "toInt: elapsed time is " << eToInt << " sec." << LogIO::POST ;
881  os << LogIO::DEBUGGING << "getWeight: elapsed time is " << eGetWeight << " sec." << LogIO::POST ;
882 
883  delete chanMap ;
884
885  // clip min and max in each grid
886//   os << "BEFORE CLIPPING" << LogIO::POST ;
887//   os << "gdataArrC=" << common.gdataArrC << LogIO::POST ;
888//   os << "gwgtArr=" << common.gwgtArr << LogIO::POST ;
889  t0 = mathutil::gettimeofday_sec() ;
890  clipMinMax( common.gdataArrC,
891              common.gwgtArr,
892              common.npoints,
893              common.clipMin,
894              common.clipWMin,
895              common.clipCMin,
896              common.clipMax,
897              common.clipWMax,
898              common.clipCMax ) ;
899  t1 = mathutil::gettimeofday_sec() ;
900  os << LogIO::DEBUGGING << "clipMinMax: elapsed time is " << t1-t0 << " sec." << LogIO::POST ;
901//   os << "AFTER CLIPPING" << LogIO::POST ;
902//   os << "gdataArrC=" << common.gdataArrC << LogIO::POST ;
903//   os << "gwgtArr=" << common.gwgtArr << LogIO::POST ;
904
905  // set data
906  setData( common.gdataArrC, common.gwgtArr ) ;
907
908}
909
910void STGrid::clipMinMax( Array<Complex> &grid,
911                         Array<Float> &weight,
912                         Array<Int> &npoints,
913                         Array<Complex> &clipmin,
914                         Array<Float> &clipwmin,
915                         Array<Float> &clipcmin,
916                         Array<Complex> &clipmax,
917                         Array<Float> &clipwmax,
918                         Array<Float> &clipcmax )
919{
920  //LogIO os( LogOrigin("STGrid","clipMinMax",WHERE) ) ;
921
922  // prepare pointers
923  Bool delG, delW, delNP, delCMin, delCWMin, delCCMin, delCMax, delCWMax, delCCMax ;
924  Complex *grid_p = grid.getStorage( delG ) ;
925  Float *wgt_p = weight.getStorage( delW ) ;
926  const Int *npts_p = npoints.getStorage( delNP ) ;
927  const Complex *cmin_p = clipmin.getStorage( delCMin ) ;
928  const Float *cwmin_p = clipwmin.getStorage( delCWMin ) ;
929  const Float *ccmin_p = clipcmin.getStorage( delCCMin ) ;
930  const Complex *cmax_p = clipmax.getStorage( delCMax ) ;
931  const Float *cwmax_p = clipwmax.getStorage( delCWMax ) ;
932  const Float *ccmax_p = clipcmax.getStorage( delCCMax ) ;
933
934  const IPosition &gshape = grid.shape() ;
935  long offset = gshape[0] * gshape[1] * gshape[2] ; // nx * ny * npol
936  Int nchan = gshape[3] ;
937  long origin = nchan * offset ;
938  for ( long i = 0 ; i < offset ; i++ ) {
939    if ( *npts_p > 2 ) {
940      for ( Int ichan = 0 ; ichan < nchan ; ichan++ ) {
941        // clip minimum and maximum
942        *grid_p -= (*cmin_p)*(*cwmin_p)*(*ccmin_p)
943          + (*cmax_p)*(*cwmax_p)*(*ccmax_p) ;
944        *wgt_p -= (*cwmin_p)*(*ccmin_p)
945          + (*cwmax_p)*(*ccmax_p) ;
946       
947        grid_p += offset ;
948        wgt_p += offset ;
949        cmin_p += offset ;
950        cwmin_p += offset ;
951        ccmin_p += offset ;
952        cmax_p += offset ;
953        cwmax_p += offset ;
954        ccmax_p += offset ;
955      }
956      grid_p -= origin ;
957      wgt_p -= origin ;
958      cmin_p -= origin ;
959      cwmin_p -= origin ;
960      ccmin_p -= origin ;
961      cmax_p -= origin ;
962      cwmax_p -= origin ;
963      ccmax_p -= origin ;
964    }
965    grid_p++ ;
966    wgt_p++ ;
967    npts_p++ ;
968    cmin_p++ ;
969    cwmin_p++ ;
970    ccmin_p++ ;
971    cmax_p++ ;
972    cwmax_p++ ;
973    ccmax_p++ ;
974  }
975  grid_p -= offset ;
976  wgt_p -= offset ;
977  npts_p -= offset ;
978  cmin_p -= offset ;
979  cwmin_p -= offset ;
980  ccmin_p -= offset ;
981  cmax_p -= offset ;
982  cwmax_p -= offset ;
983  ccmax_p -= offset ; 
984
985  // finalization
986  grid.putStorage( grid_p, delG ) ;
987  weight.putStorage( wgt_p, delW ) ;
988  npoints.freeStorage( npts_p, delNP ) ;
989  clipmin.freeStorage( cmin_p, delCMin ) ;
990  clipwmin.freeStorage( cwmin_p, delCWMin ) ;
991  clipcmin.freeStorage( ccmin_p, delCCMin ) ;
992  clipmax.freeStorage( cmax_p, delCMax ) ;
993  clipwmax.freeStorage( cwmax_p, delCWMax ) ;
994  clipcmax.freeStorage( ccmax_p, delCCMax ) ;
995}
996
997void STGrid::initPol( Int ipol )
998{
999  LogIO os( LogOrigin("STGrid","initPol",WHERE) ) ;
1000  if ( npolOrg_ == 1 ) {
1001    os << "single polarization data." << LogIO::POST ;
1002    ptab_ = tab_ ;
1003  }
1004  else
1005    ptab_ = tab_( tab_.col("POLNO") == pollist_[ipol] ) ;
1006
1007  attach( ptab_ ) ;
1008}
1009
1010void STGrid::initTable( uInt idx )
1011{
1012  tab_ = tableList_[idx] ;
1013  nrow_ = rows_[idx] ;
1014  updateChunkShape() ;
1015}
1016
1017void STGrid::setData( Array<Complex> &gdata,
1018                      Array<Float> &gwgt )
1019{
1020  // 2011/12/20 TN
1021  // gwgt and data_ share storage
1022  LogIO os( LogOrigin("STGrid","setData",WHERE) ) ;
1023  double t0, t1 ;
1024  t0 = mathutil::gettimeofday_sec() ;
1025  uInt len = data_.nelements() ;
1026  Bool b1, b2, b3 ;
1027  const Complex *gdata_p = gdata.getStorage( b1 ) ;
1028  Float *gwgt_p = gwgt.getStorage( b2 ) ; // storage shared with data_
1029  uChar *gflg_p = flag_.getStorage( b3 ) ;
1030  for ( uInt i = 0 ; i < len ; i++ ) {
1031    if (gwgt_p[i] > 0.0) {
1032      gwgt_p[i] = (gdata_p[i]).real() / gwgt_p[i];
1033      gflg_p[i] = (uChar)0;
1034    }
1035    else {
1036      gflg_p[i] = (uChar)1;
1037    }
1038  }
1039  gdata.freeStorage( gdata_p, b1 ) ;
1040  data_.putStorage( gwgt_p, b2 ) ;
1041  flag_.putStorage( gflg_p, b3 ) ;
1042  t1 = mathutil::gettimeofday_sec() ;
1043  os << LogIO::DEBUGGING << "setData: elapsed time is " << t1-t0 << " sec." << LogIO::POST ;
1044}
1045
1046void STGrid::setupGrid()
1047{
1048  Double xmin,xmax,ymin,ymax ;
1049  mapExtent( xmin, xmax, ymin, ymax ) ;
1050 
1051  setupGrid( nxUI_, nyUI_, cellxUI_, cellyUI_,
1052             xmin, xmax, ymin, ymax, centerUI_ ) ;
1053}
1054
1055void STGrid::setupGrid( Int &nx,
1056                        Int &ny,
1057                        String &cellx,
1058                        String &celly,
1059                        Double &xmin,
1060                        Double &xmax,
1061                        Double &ymin,
1062                        Double &ymax,
1063                        String &center )
1064{
1065  LogIO os( LogOrigin("STGrid","setupGrid",WHERE) ) ;
1066  //cout << "nx=" << nx << ", ny=" << ny << endl ;
1067
1068  // center position
1069  if ( center.size() == 0 ) {
1070    center_(0) = 0.5 * ( xmin + xmax ) ;
1071    center_(1) = 0.5 * ( ymin + ymax ) ;
1072  }
1073  else {
1074    String::size_type pos0 = center.find( " " ) ;
1075    if ( pos0 == String::npos ) {
1076      throw AipsError( "bad string format in parameter center" ) ;
1077    }
1078    String::size_type pos1 = center.find( " ", pos0+1 ) ;
1079    String typestr, xstr, ystr ;
1080    if ( pos1 != String::npos ) {
1081      typestr = center.substr( 0, pos0 ) ;
1082      xstr = center.substr( pos0+1, pos1-pos0 ) ;
1083      ystr = center.substr( pos1+1 ) ;
1084      // todo: convert to J2000 (or direction ref for DIRECTION column)
1085    }
1086    else {
1087      typestr = "J2000" ;
1088      xstr = center.substr( 0, pos0 ) ;
1089      ystr = center.substr( pos0+1 ) ;
1090    }
1091    QuantumHolder qh ;
1092    String err ;
1093    qh.fromString( err, xstr ) ;
1094    Quantum<Double> xcen = qh.asQuantumDouble() ;
1095    qh.fromString( err, ystr ) ;
1096    Quantum<Double> ycen = qh.asQuantumDouble() ;
1097    center_(0) = xcen.getValue( "rad" ) ;
1098    center_(1) = ycen.getValue( "rad" ) ;
1099    double base = 0.5 * (xmin + xmax) ;
1100    int maxrotate = 1 ;
1101    int nelem = 2 * maxrotate + 1 ;
1102    double *sep = new double[nelem] ;
1103    for ( int i = 0 ; i < nelem ; i++ )
1104      sep[i] = abs(base - center_[0] - (i-maxrotate) * C::_2pi) ;
1105//     os << "sep[0]=" << sep[0] << endl 
1106//        << "sep[1]=" << sep[1] << endl
1107//        << "sep[2]=" << sep[2] << LogIO::POST ;
1108    int idx = 0 ;
1109    base = sep[0] ;
1110    int nrotate = 0 ;
1111    while ( idx < nelem ) {
1112      if ( base > sep[idx] ) {
1113        base = sep[idx] ;
1114        nrotate = idx ;
1115      }
1116      idx++ ;
1117    }
1118    delete sep ;
1119    nrotate -= maxrotate ;
1120//     os << "nrotate = " << nrotate << LogIO::POST ;
1121    center_[0] += nrotate * C::_2pi ;
1122  }
1123//   os << "xmin=" << xmin << LogIO::POST ;
1124//   os << "center_=" << center_ << LogIO::POST ;
1125
1126  nx_ = nx ;
1127  ny_ = ny ;
1128  if ( nx < 0 && ny > 0 ) {
1129    nx_ = ny ;
1130    ny_ = ny ;
1131  }
1132  if ( ny < 0 && nx > 0 ) {
1133    nx_ = nx ;
1134    ny_ = nx ;
1135  }
1136
1137  //Double wx = xmax - xmin ;
1138  //Double wy = ymax - ymin ;
1139  Double wx = max( abs(xmax-center_(0)), abs(xmin-center_(0)) ) * 2 ;
1140  Double wy = max( abs(ymax-center_(1)), abs(ymin-center_(1)) ) * 2 ;
1141
1142  Quantum<Double> qcellx ;
1143  Quantum<Double> qcelly ;
1144  //cout << "nx_ = " << nx_ << ",  ny_ = " << ny_ << endl ;
1145  if ( cellx.size() != 0 && celly.size() != 0 ) {
1146    readQuantity( qcellx, cellx ) ;
1147    readQuantity( qcelly, celly ) ;
1148  }
1149  else if ( celly.size() != 0 ) {
1150    os << "Using celly to x-axis..." << LogIO::POST ;
1151    readQuantity( qcelly, celly ) ;
1152    qcellx = qcelly ;
1153  }
1154  else if ( cellx.size() != 0 ) {
1155    os << "Using cellx to y-axis..." << LogIO::POST ;
1156    readQuantity( qcellx, cellx ) ;
1157    qcelly = qcellx ;
1158  }
1159  else {
1160    if ( nx_ < 0 ) {
1161      os << "No user preference in grid setting. Using default..." << LogIO::POST ;
1162      readQuantity( qcellx, "1.0arcmin" ) ;
1163      qcelly = qcellx ;
1164    }
1165    else {
1166      if ( wx == 0.0 ) {
1167        os << "Using default spatial extent (10arcmin) in x" << LogIO::POST ;
1168        wx = 0.00290888 ;
1169      }
1170      if ( wy == 0.0 ) {
1171        os << "Using default spatial extent (10arcmin) in y" << LogIO::POST ;
1172        wy = 0.00290888 ;
1173      }
1174      if (nx_ > 1) {
1175        qcellx = Quantum<Double>(wx / (nx_ - 1) * cos(center_[1]), "rad");
1176      }
1177      else {
1178        qcellx = Quantum<Double>( 1.1f * wx / nx_ * cos(center_[1]), "rad" );
1179      }
1180      if (ny_ > 1) {
1181        qcelly = Quantum<Double>(wy / (ny_ - 1), "rad");
1182      }
1183      else {
1184        qcelly = Quantum<Double>( 1.1f * wy / ny_, "rad" );
1185      }
1186    }
1187  }
1188  cellx_ = qcellx.getValue( "rad" ) ;
1189  celly_ = qcelly.getValue( "rad" ) ;
1190  //os << "cellx_=" << cellx_ << ", celly_=" << celly_ << ", cos("<<center_(1)<<")=" << cos(center_(1)) << LogIO::POST ;
1191  if ( nx_ < 0 ) {
1192    if ( wx == 0.0 ) {
1193      os << "Using default spatial extent (10arcmin) in x" << LogIO::POST ;
1194      wx = 0.00290888 ;
1195    }
1196    if ( wy == 0.0 ) {
1197      os << "Using default spatial extent (10arcmin) in y" << LogIO::POST ;
1198      wy = 0.00290888 ;
1199    }
1200    nx_ = Int( ceil( wx/(cellx_/cos(center_[1])) ) ) ;
1201    ny_ = Int( ceil( wy/celly_ ) ) ;
1202  }
1203
1204  // create DirectionCoordinate
1205  Matrix<Double> xform(2,2) ;
1206  xform = 0.0 ;
1207  xform.diagonal() = 1.0 ;
1208  dircoord_ = new DirectionCoordinate(MDirection::J2000,
1209                                      Projection( Projection::SIN ),
1210                                      center_[0], center_[1],
1211                                      -cellx_, celly_,
1212                                      xform,
1213                                      0.5*Double(nx_-1),
1214                                      0.5*Double(ny_-1)) ;
1215}
1216
1217void STGrid::mapExtent( Double &xmin, Double &xmax,
1218                        Double &ymin, Double &ymax )
1219{
1220  //LogIO os( LogOrigin("STGrid","mapExtent",WHERE) ) ;
1221  directionCol_.attach( tableList_[0], "DIRECTION" ) ;
1222  Matrix<Double> direction = directionCol_.getColumn() ;
1223  //os << "dirCol.nrow() = " << dirCol.nrow() << LogIO::POST ;
1224  Vector<Double> ra( direction.row(0) ) ;
1225  mathutil::rotateRA( ra ) ;
1226  minMax( xmin, xmax, direction.row( 0 ) ) ;
1227  minMax( ymin, ymax, direction.row( 1 ) ) ;
1228  Double amin, amax, bmin, bmax ;
1229  for ( uInt i = 1 ; i < nfile_ ; i++ ) {
1230    directionCol_.attach( tableList_[i], "DIRECTION" ) ;
1231    direction.assign( directionCol_.getColumn() ) ;
1232    //os << "dirCol.nrow() = " << dirCol.nrow() << LogIO::POST ;
1233    // to make contiguous RA distribution (no 2pi jump)
1234    Vector<Double> ra( direction.row(0) ) ;
1235    mathutil::rotateRA( ra ) ;
1236    minMax( amin, amax, direction.row( 0 ) ) ;
1237    minMax( bmin, bmax, direction.row( 1 ) ) ;
1238    xmin = min( xmin, amin ) ;
1239    xmax = max( xmax, amax ) ;
1240    ymin = min( ymin, bmin ) ;
1241    ymax = max( ymax, bmax ) ;
1242  }
1243  //os << "(xmin,xmax)=(" << xmin << "," << xmax << ")" << LogIO::POST ;
1244  //os << "(ymin,ymax)=(" << ymin << "," << ymax << ")" << LogIO::POST ;
1245}
1246
1247void STGrid::table( Table &tab, uInt i )
1248{
1249  if ( i < nfile_ )
1250    tab = Table( infileList_[i] ) ;
1251}
1252
1253void STGrid::selectData()
1254{
1255  LogIO os( LogOrigin("STGrid","selectData",WHERE) ) ;   
1256  Int ifno = ifno_ ;
1257  tableList_.resize( nfile_ ) ;
1258  if ( ifno_ == -1 ) {
1259    //Table taborg( infileList_[0] ) ;
1260    Table taborg ;
1261    table( taborg, 0 ) ;
1262    ROScalarColumn<uInt> ifnoCol( taborg, "IFNO" ) ;
1263    ifno_ = ifnoCol( 0 ) ;
1264    os << LogIO::WARN
1265       << "IFNO is not given. Using default IFNO: " << ifno_ << LogIO::POST ;
1266  }
1267  for ( uInt i = 0 ; i < nfile_ ; i++ ) {
1268    //Table taborg( infileList_[i] ) ;
1269    Table taborg ;
1270    table( taborg, i ) ;
1271    TableExprNode node ;
1272    if ( ifno != -1 || isMultiIF( taborg ) ) {
1273      os << "apply selection on IFNO" << LogIO::POST ;
1274      node = taborg.col("IFNO") == ifno_ ;
1275    }
1276    if ( scanlist_.size() > 0 ) {
1277      os << "apply selection on SCANNO" << LogIO::POST ;
1278      node = node && taborg.col("SCANNO").in( scanlist_ ) ;
1279    }
1280    if ( node.isNull() ) {
1281      tableList_[i] = taborg ;
1282    }
1283    else {
1284      tableList_[i] = taborg( node ) ;
1285    }
1286    os << LogIO::DEBUGGING << "tableList_[" << i << "].nrow()=" << tableList_[i].nrow() << LogIO::POST ;
1287    if ( tableList_[i].nrow() == 0 ) {
1288      os << LogIO::SEVERE
1289         << "No corresponding rows for given selection: IFNO " << ifno_ ;
1290      if ( scanlist_.size() > 0 )
1291        os << " SCANNO " << scanlist_ ;
1292      os << LogIO::EXCEPTION ;
1293    }
1294  }
1295}
1296
1297Bool STGrid::isMultiIF( Table &tab )
1298{
1299  ROScalarColumn<uInt> ifnoCol( tab, "IFNO" ) ;
1300  Vector<uInt> ifnos = ifnoCol.getColumn() ;
1301  return anyNE( ifnos, ifnos[0] ) ;
1302}
1303
1304void STGrid::attach( Table &tab )
1305{
1306  // attach to table
1307  spectraCol_.attach( tab, "SPECTRA" ) ;
1308  flagtraCol_.attach( tab, "FLAGTRA" ) ;
1309  directionCol_.attach( tab, "DIRECTION" ) ;
1310  flagRowCol_.attach( tab, "FLAGROW" ) ;
1311  tsysCol_.attach( tab, "TSYS" ) ;
1312  intervalCol_.attach( tab, "INTERVAL" ) ;
1313}
1314
1315Int STGrid::getDataChunk(
1316                         IPosition const &wshape,
1317                         IPosition const &vshape,
1318                         IPosition const &/* dshape */,
1319                         Array<Complex> &spectra,
1320                         Array<Double> &direction,
1321                         Array<Int> &flagtra,
1322                         Array<Int> &rflag,
1323                         Array<Float> &weight )
1324{
1325  LogIO os( LogOrigin("STGrid","getDataChunk",WHERE) ) ;
1326
1327  Array<Float> spectraF_(wshape);
1328  Array<uChar> flagtraUC_(wshape);
1329  Array<uInt> rflagUI_(vshape);
1330  Int nrow = getDataChunk( spectraF_, direction, flagtraUC_, rflagUI_, weight ) ;
1331  if ( nrow < nchunk_ ) {
1332    spectra.resize( spectraF_.shape() ) ;
1333    flagtra.resize( flagtraUC_.shape() ) ;
1334    rflag.resize( rflagUI_.shape() ) ;
1335  }
1336  double t0, t1 ;
1337  t0 = mathutil::gettimeofday_sec() ;
1338  convertArray( spectra, spectraF_ ) ;
1339  toInt( flagtraUC_, flagtra ) ;
1340  toInt( rflagUI_, rflag ) ;
1341  t1 = mathutil::gettimeofday_sec() ;
1342  eToInt = t1 - t0 ;
1343 
1344  return nrow ;
1345}
1346
1347#if 0
1348Int STGrid::getDataChunk( Array<Complex> &spectra,
1349                          Array<Double> &direction,
1350                          Array<Int> &flagtra,
1351                          Array<Int> &rflag,
1352                          Array<Float> &weight )
1353{
1354  LogIO os( LogOrigin("STGrid","getDataChunk",WHERE) ) ;
1355  Int nrow = getDataChunk( spectraF_, direction, flagtraUC_, rflagUI_, weight ) ;
1356  if ( nrow < nchunk_ ) {
1357    spectra.resize( spectraF_.shape() ) ;
1358    flagtra.resize( flagtraUC_.shape() ) ;
1359    rflag.resize( rflagUI_.shape() ) ;
1360  }
1361  double t0, t1 ;
1362  t0 = mathutil::gettimeofday_sec() ;
1363  convertArray( spectra, spectraF_ ) ;
1364  toInt( flagtraUC_, flagtra ) ;
1365  toInt( rflagUI_, rflag ) ;
1366  t1 = mathutil::gettimeofday_sec() ;
1367  eToInt = t1 - t0 ;
1368 
1369  return nrow ;
1370}
1371#endif
1372
1373Int STGrid::getDataChunk( Array<Float> &spectra,
1374                          Array<Double> &direction,
1375                          Array<uChar> &flagtra,
1376                          Array<uInt> &rflag,
1377                          Array<Float> &weight )
1378{
1379  LogIO os( LogOrigin("STGrid","getDataChunk",WHERE) ) ;
1380  Int nrow = spectra.shape()[1] ;
1381  Int remainingRow = nrow_ - nprocessed_ ;
1382  if ( remainingRow < nrow ) {
1383    nrow = remainingRow ;
1384    IPosition mshape( 2, nchan_, nrow ) ;
1385    IPosition vshape( 1, nrow ) ;
1386    spectra.resize( mshape ) ;
1387    flagtra.resize( mshape ) ;
1388    direction.resize( IPosition(2,2,nrow) ) ;
1389    rflag.resize( vshape ) ;
1390    weight.resize( mshape ) ;
1391  }
1392  // 2011/12/22 TN
1393  // tsys shares its storage with weight
1394  Array<Float> tsys( weight ) ;
1395  Array<Double> tint( rflag.shape() ) ;
1396
1397  Vector<uInt> rflagVec( rflag ) ;
1398  Vector<Double> tintVec( tint ) ;
1399
1400  RefRows rows( nprocessed_, nprocessed_+nrow-1, 1 ) ;
1401  //os<<LogIO::DEBUGGING<<"nprocessed_="<<nprocessed_<<": rows.nrows()="<<rows.nrows()<<LogIO::POST ;
1402  spectraCol_.getColumnCells( rows, spectra ) ;
1403  flagtraCol_.getColumnCells( rows, flagtra ) ;
1404  directionCol_.getColumnCells( rows, direction ) ;
1405  // to make contiguous RA distribution (no 2pi jump)
1406  Vector<Double> v( Matrix<Double>(direction).row(0) ) ;
1407  mathutil::rotateRA( v ) ;
1408  flagRowCol_.getColumnCells( rows, rflagVec ) ;
1409  intervalCol_.getColumnCells( rows, tintVec ) ;
1410  Vector<Float> tsysTemp = tsysCol_( nprocessed_ ) ;
1411  if ( tsysTemp.nelements() == (uInt)nchan_ )
1412    tsysCol_.getColumnCells( rows, tsys ) ;
1413  else
1414    tsys = tsysTemp[0] ;
1415
1416  double t0,t1 ;
1417  t0 = mathutil::gettimeofday_sec() ;
1418  getWeight( weight, tsys, tint ) ;
1419  t1 = mathutil::gettimeofday_sec() ;
1420  eGetWeight += t1-t0 ;
1421
1422  nprocessed_ += nrow ;
1423 
1424  return nrow ;
1425}
1426
1427void STGrid::setupArray()
1428{
1429  LogIO os( LogOrigin("STGrid","setupArray",WHERE) ) ;
1430  ROScalarColumn<uInt> polnoCol( tableList_[0], "POLNO" ) ;
1431  Vector<uInt> pols = polnoCol.getColumn() ;
1432  //os << pols << LogIO::POST ;
1433  Vector<uInt> pollistOrg ;
1434  npolOrg_ = 0 ;
1435  uInt polno ;
1436  for ( uInt i = 0 ; i < polnoCol.nrow() ; i++ ) {
1437    //polno = polnoCol( i ) ;
1438    polno = pols( i ) ;
1439    if ( allNE( pollistOrg, polno ) ) {
1440      pollistOrg.resize( npolOrg_+1, True ) ;
1441      pollistOrg[npolOrg_] = polno ;
1442      npolOrg_++ ;
1443    }
1444  }
1445  if ( pollist_.size() == 0 )
1446    pollist_ = pollistOrg ;
1447  else {
1448    Vector<uInt> newlist ;
1449    uInt newsize = 0 ;
1450    for ( uInt i = 0 ; i < pollist_.size() ; i++ ) {
1451      if ( anyEQ( pollistOrg, pollist_[i] ) ) {
1452        newlist.resize( newsize+1, True ) ;
1453        newlist[newsize] = pollist_[i] ;
1454        newsize++ ;
1455      }
1456    }
1457    pollist_.assign( newlist ) ;
1458  }
1459  npol_ = pollist_.size() ;
1460  if ( npol_ == 0 ) {
1461    os << LogIO::SEVERE << "Empty pollist" << LogIO::EXCEPTION ;
1462  }
1463  rows_.resize( nfile_ ) ;
1464  for ( uInt i = 0 ; i < nfile_ ; i++ ) {
1465    rows_[i] = tableList_[i].nrow() / npolOrg_ ;
1466    //if ( nrow_ < rows_[i] )
1467    //  nrow_ = rows_[i] ;
1468  }
1469  flagtraCol_.attach( tableList_[0], "FLAGTRA" ) ;
1470  nchan_ = flagtraCol_( 0 ).nelements() ;
1471//   os << "npol_ = " << npol_ << "(" << pollist_ << ")" << endl
1472//      << "nchan_ = " << nchan_ << endl
1473//      << "nrow_ = " << nrow_ << LogIO::POST ;
1474}
1475
1476void STGrid::getWeight( Array<Float> &w,
1477                              Array<Float> &tsys,
1478                              Array<Double> &tint )
1479{
1480  LogIO os( LogOrigin("STGrid","getWeight",WHERE) ) ;
1481
1482  // 2011/12/22 TN
1483  // w (weight) and tsys share storage
1484  IPosition refShape = tsys.shape() ;
1485  Int nchan = refShape[0] ;
1486  Int nrow = refShape[1] ;
1487//   os << "nchan=" << nchan << ", nrow=" << nrow << LogIO::POST ;
1488//   os << "w.shape()=" << w.shape() << endl
1489//      << "tsys.shape()=" << tsys.shape() << endl
1490//      << "tint.shape()=" << tint.shape() << LogIO::POST ;
1491
1492  // set weight
1493  if ( wtype_.compare( "UNIFORM" ) == 0 ) {
1494    w = 1.0 ;
1495  }
1496  else if ( wtype_.compare( "TINT" ) == 0 ) {
1497    Bool b0, b1 ;
1498    Float *w_p = w.getStorage( b0 ) ;
1499    Float *w0_p = w_p ;
1500    const Double *ti_p = tint.getStorage( b1 ) ;
1501    const Double *w1_p = ti_p ;
1502    for ( Int irow = 0 ; irow < nrow ; irow++ ) {
1503      for ( Int ichan = 0 ; ichan < nchan ; ichan++ ) {
1504        *w0_p = *w1_p ;
1505        w0_p++ ;
1506      }
1507      w1_p++ ;
1508    }
1509    w.putStorage( w_p, b0 ) ;
1510    tint.freeStorage( ti_p, b1 ) ;
1511  }
1512  else if ( wtype_.compare( "TSYS" ) == 0 ) {
1513    Bool b0 ;
1514    Float *w_p = w.getStorage( b0 ) ;
1515    Float *w0_p = w_p ;
1516    for ( Int irow = 0 ; irow < nrow ; irow++ ) {
1517      for ( Int ichan = 0 ; ichan < nchan ; ichan++ ) {
1518        Float temp = *w0_p ;
1519        *w0_p = 1.0 / ( temp * temp ) ;
1520        w0_p++ ;
1521      }
1522    }
1523    w.putStorage( w_p, b0 ) ;
1524  }
1525  else if ( wtype_.compare( "TINTSYS" ) == 0 ) {
1526    Bool b0, b1 ;
1527    Float *w_p = w.getStorage( b0 ) ;
1528    Float *w0_p = w_p ;
1529    const Double *ti_p = tint.getStorage( b1 ) ;
1530    const Double *w1_p = ti_p ;
1531    for ( Int irow = 0 ; irow < nrow ; irow++ ) {
1532      Float interval = *w1_p ;
1533      for ( Int ichan = 0 ; ichan < nchan ; ichan++ ) {
1534        Float temp = *w0_p ;
1535        *w0_p = interval / ( temp * temp ) ;
1536        w0_p++ ;
1537      }
1538      w1_p++ ;
1539    }
1540    w.putStorage( w_p, b0 ) ;
1541    tint.freeStorage( ti_p, b1 ) ;
1542  }
1543  else {
1544    //LogIO os( LogOrigin("STGrid", "getWeight", WHERE) ) ;
1545    //os << LogIO::WARN << "Unsupported weight type '" << wtype_ << "', apply UNIFORM weight" << LogIO::POST ;
1546    w = 1.0 ;
1547  }
1548}
1549
1550void STGrid::toInt( Array<uChar> &u, Array<Int> &v )
1551{
1552  uInt len = u.nelements() ;
1553  Int *int_p = new Int[len] ;
1554  Bool deleteIt ;
1555  const uChar *data_p = u.getStorage( deleteIt ) ;
1556  Int *i_p = int_p ;
1557  const uChar *u_p = data_p ;
1558  for ( uInt i = 0 ; i < len ; i++ ) {
1559    *i_p = ( *u_p == 0 ) ? 0 : 1 ;
1560    i_p++ ;
1561    u_p++ ;
1562  }
1563  u.freeStorage( data_p, deleteIt ) ;
1564  v.takeStorage( u.shape(), int_p, TAKE_OVER ) ;
1565}
1566
1567void STGrid::toInt( Array<uInt> &u, Array<Int> &v )
1568{
1569  uInt len = u.nelements() ;
1570  Int *int_p = new Int[len] ;
1571  Bool deleteIt ;
1572  const uInt *data_p = u.getStorage( deleteIt ) ;
1573  Int *i_p = int_p ;
1574  const uInt *u_p = data_p ;
1575  for ( uInt i = 0 ; i < len ; i++ ) {
1576    *i_p = ( *u_p == 0 ) ? 0 : 1 ;
1577    i_p++ ;
1578    u_p++ ;
1579  }
1580  u.freeStorage( data_p, deleteIt ) ;
1581  v.takeStorage( u.shape(), int_p, TAKE_OVER ) ;
1582}
1583
1584void STGrid::toPixel( Array<Double> &world, Array<Double> &pixel )
1585{
1586  uInt nrow = world.shape()[1] ;
1587  Bool bw, bp ;
1588  Double *w_p = world.getStorage( bw ) ;
1589  Double *p_p = pixel.getStorage( bp ) ;
1590  Double *ww_p = w_p ;
1591  Double *wp_p = p_p ;
1592  IPosition vshape( 1, 2 ) ;
1593  Vector<Double> _world, _pixel ;
1594  for ( uInt i = 0 ; i < nrow ; i++ ) {
1595    _world.takeStorage( vshape, ww_p, SHARE ) ;
1596    _pixel.takeStorage( vshape, wp_p, SHARE ) ;
1597    dircoord_->toPixel( _pixel, _world ) ;
1598    ww_p += 2 ;
1599    wp_p += 2 ;
1600  }
1601  world.putStorage( w_p, bw ) ;
1602  pixel.putStorage( p_p, bp ) ;
1603}
1604
1605void STGrid::boxFunc( Vector<Float> &convFunc, Int &convSize )
1606{
1607  convFunc = 0.0 ;
1608  for ( Int i = 0 ; i < convSize/2 ; i++ )
1609    convFunc(i) = 1.0 ;
1610}
1611
1612#define NEED_UNDERSCORES
1613#if defined(NEED_UNDERSCORES)
1614#define grdsf grdsf_
1615#define grdgauss grdgauss_
1616#define grdjinc1 grdjinc1_
1617#endif
1618#if defined(USE_CASAPY)
1619extern "C" {
1620  void grdsf(Double*, Double*);
1621  void grdgauss(Double*, Double*, Double*);
1622  void grdjinc1(Double*, Double*, Int*, Double*);
1623}
1624#else
1625extern "C" {
1626  void grdsf(Double*, Double*);
1627}
1628void grdgauss(Double *hwhm, Double *val, Double *out)
1629{
1630  *out = exp(-log(2.0) * (*val / *hwhm) * (*val / *hwhm));
1631}
1632void grdjinc1(Double *c, Double *val, Int *normalize, Double *out)
1633{
1634  // Calculate J_1(x) using approximate formula
1635  Double x = C::pi * *val / *c;
1636  Double ax = fabs(x);
1637  Double ans;
1638  if ( ax < 8.0 ) {
1639    Double y = x * x;
1640    Double ans1 = x * (72362614232.0 + y * (-7895059235.0
1641                       + y * (242396853.1 + y * (-2972611.439
1642                       + y * (15704.48260 + y * (-30.16036606))))));
1643    Double ans2 = 144725228442.0 + y * (2300535178.0
1644                       + y * (18583304.74 + y * (99447.43394
1645                       + y * (376.9991397 + y * 1.0))));
1646    ans = ans1 / ans2;
1647  }
1648  else {
1649    Double z = 8.0 / ax;
1650    Double y = z * z;
1651    Double xx = ax - 2.356194491;
1652    Double ans1 = 1.0 + y * (0.183105e-2 + y * (-0.3516396496e-4
1653                      + y * (0.2457520174e-5 + y * (-0.240337019e-6))));
1654    Double ans2 = 0.04687499995 + y * (-0.2002690873e-3
1655                      + y * (0.8449199096e-5 + y * (-0.88228987e-6
1656                      + y * (0.105787412e-6))));
1657    ans = sqrt(0.636619772 / ax) * (cos(xx) * ans1
1658                                    - z * sin(xx) * ans2);
1659    if (x < 0.0)
1660      ans = -ans;
1661  }
1662 
1663  // Then, calculate Jinc
1664  if (x == 0.0) {
1665    *out = 0.5;
1666  }
1667  else {
1668    *out = ans / x;
1669  }
1670
1671  if (*normalize == 1)
1672    *out = *out / 0.5; 
1673}
1674#endif
1675void STGrid::spheroidalFunc( Vector<Float> &convFunc )
1676{
1677  convFunc = 0.0 ;
1678  for ( Int i = 0 ; i < convSampling_*convSupport_ ; i++ ) {
1679    Double nu = Double(i) / Double(convSupport_*convSampling_) ;
1680    Double val ;
1681    grdsf( &nu, &val ) ;
1682    convFunc(i) = ( 1.0 - nu * nu ) * val ;
1683  }
1684}
1685
1686void STGrid::gaussFunc( Vector<Float> &convFunc, Double hwhm, Double truncate )
1687{
1688  convFunc = 0.0 ;
1689  Int len = (Int)(truncate*Double(convSampling_)+0.5);
1690  Double out, val;
1691  for ( Int i = 0 ; i < len ; i++ ) {
1692    val = Double(i) / Double(convSampling_) ;
1693    grdgauss(&hwhm, &val, &out);
1694    convFunc(i) = out;
1695  }
1696}
1697
1698void STGrid::gjincFunc( Vector<Float> &convFunc, Double hwhm, Double c, Double truncate )
1699{
1700  convFunc = 0.0;
1701  Double out1, out2, val;
1702  Int normalize = 1;
1703  if  (truncate >= 0.0) {
1704    Int len = (Int)(truncate*Double(convSampling_)+0.5);
1705    for (Int i = 0 ; i < len ; i++) {
1706      val = Double(i) / Double(convSampling_);
1707      grdgauss(&hwhm, &val, &out1);
1708      grdjinc1(&c, &val, &normalize, &out2);
1709      convFunc(i) = out1 * out2;
1710    }
1711  }
1712  else {
1713    Int len = convFunc.nelements();
1714    for (Int i = 0 ; i < len ; i++) {
1715      val = Double(i) / Double(convSampling_);
1716      grdjinc1(&c, &val, &normalize, &out2);
1717      if (out2 <= 0.0) {
1718        LogIO os(LogOrigin("STGrid","gjincFunc",WHERE));
1719        os << LogIO::DEBUG1 << "convFunc is automatically truncated at radius " << val << LogIO::POST;
1720        break;
1721      }
1722      grdgauss(&hwhm, &val, &out1);
1723      convFunc(i) = out1 * out2;
1724    }
1725  }
1726}
1727
1728void STGrid::pbFunc( Vector<Float> &convFunc )
1729{
1730  convFunc = 0.0 ;
1731}
1732
1733vector<float> STGrid::getConvFunc()
1734{
1735  LogIO os(LogOrigin("STGrid","getConvFunc",WHERE));
1736  Vector<Float> convFunc;
1737  vector<float> out;
1738
1739  if (cellx_ <= 0.0 || celly_ <= 0.0) {
1740    selectData();
1741    setupGrid();
1742  }
1743
1744  if (convType_ == "BOX" || convType_ == "SF") {
1745    setConvFunc(convFunc);
1746  }
1747  else if (convType_ == "GAUSS") {
1748    Quantum<Double> q1,q2;
1749    readQuantity(q1,gwidth_);
1750    readQuantity(q2,truncate_);
1751//     if (celly_ <= 0.0
1752//         && ((!q1.getUnit().empty()&&q1.getUnit()!="pixel") ||
1753//             (!q2.getUnit().empty()&&q2.getUnit()!="pixel"))) {
1754//       throw AipsError("You have to call defineImage to get correct convFunc");
1755//     }
1756    setConvFunc(convFunc);
1757  }
1758  else if (convType_ == "GJINC") {
1759    Quantum<Double> q1,q2,q3;
1760    readQuantity(q1,gwidth_);
1761    readQuantity(q2,truncate_);
1762    readQuantity(q3,jwidth_);
1763//     if (celly_ <= 0.0
1764//         && ((!q1.getUnit().empty()&&q1.getUnit()!="pixel") ||
1765//             (!q2.getUnit().empty()&&q2.getUnit()!="pixel") ||
1766//             (!q3.getUnit().empty()&&q3.getUnit()!="pixel"))) {
1767//       throw AipsError("You have to call defineImage to get correct convFunc");
1768//     }
1769    setConvFunc(convFunc);
1770  }
1771  else if (convType_ == "PB") {
1772    throw AipsError("Grid function PB is not available");
1773  }
1774  else {
1775    throw AipsError("Unknown grid function: "+convType_);
1776  }
1777
1778  convFunc.tovector(out);
1779  return out;
1780}
1781
1782void STGrid::setConvFunc( Vector<Float> &convFunc )
1783{
1784  LogIO os(LogOrigin("STGrid","setConvFunc",WHERE));
1785  convSupport_ = userSupport_ ;
1786  if ( convType_ == "BOX" ) {
1787    if ( convSupport_ < 0 )
1788      convSupport_ = 0 ;
1789    Int convSize = convSampling_ * ( 2 * convSupport_ + 2 )  ;
1790    convFunc.resize( convSize ) ;
1791    boxFunc( convFunc, convSize ) ;
1792    os << LogIO::DEBUGGING
1793       << "convType_ = " << convType_ << endl
1794       << "convSupport_ = " << convSupport_ << LogIO::POST;
1795  }
1796  else if ( convType_ == "SF" ) {
1797    if ( convSupport_ < 0 )
1798      convSupport_ = 3 ;
1799    Int convSize = convSampling_ * ( 2 * convSupport_ + 2 )  ;
1800    convFunc.resize( convSize ) ;
1801    spheroidalFunc( convFunc ) ;
1802    os << LogIO::DEBUGGING
1803       << "convType_ = " << convType_ << endl
1804       << "convSupport_ = " << convSupport_ << LogIO::POST;
1805  }
1806  else if ( convType_ == "GAUSS" ) {
1807    // determine pixel gwidth
1808    // default is HWHM corresponding to b = 1.0 (Mangum et al. 2007)
1809    Double pixelGW = -1.0;
1810    Quantum<Double> q ;
1811    if (!gwidth_.empty()) {
1812      readQuantity( q, gwidth_ );
1813      if ( q.getUnit().empty() || q.getUnit()=="pixel" ) {
1814        pixelGW = q.getValue();
1815      }
1816      else {
1817        pixelGW = q.getValue("rad")/celly_;
1818      }
1819    }
1820    pixelGW = (pixelGW >= 0.0) ? pixelGW : sqrt(log(2.0));
1821    if (pixelGW < 0.0) {
1822      os << LogIO::SEVERE
1823         << "Negative width is specified for gaussian" << LogIO::EXCEPTION;
1824    }
1825    // determine truncation radius
1826    // default is 3 * HWHM
1827    Double truncate = -1.0;
1828    if (!truncate_.empty()) {
1829      readQuantity( q, truncate_ );
1830      if ( q.getUnit().empty() || q.getUnit()=="pixel" ) {
1831        truncate = q.getValue();
1832      }
1833      else {
1834        truncate = q.getValue("rad")/celly_;
1835      }
1836    }     
1837    //convSupport_ = (Int)(truncate+0.5);
1838    truncate = (truncate >= 0.0) ? truncate : 3.0 * pixelGW;
1839    convSupport_ = Int(truncate);
1840    convSupport_ += (((truncate-(Double)convSupport_) > 0.0) ? 1 : 0);
1841    Int convSize = convSampling_ * ( 2*convSupport_ + 2 ) ;
1842    convFunc.resize( convSize ) ;
1843    gaussFunc( convFunc, pixelGW, truncate ) ;
1844    os << LogIO::DEBUGGING
1845       << "convType_ = " << convType_ << endl
1846       << "convSupport_ = " << convSupport_ << endl
1847       << "truncate_ = " << truncate << "pixel" << endl
1848       << "gwidth_ = " << pixelGW << "pixel" << LogIO::POST;
1849  }
1850  else if ( convType_ == "GJINC" ) {
1851    // determine pixel gwidth
1852    // default is HWHM corresponding to b = 2.52 (Mangum et al. 2007)
1853    Double pixelGW = -1.0;
1854    Quantum<Double> q ;
1855    if (!gwidth_.empty()) {
1856      readQuantity( q, gwidth_ );
1857      if ( q.getUnit().empty() || q.getUnit()=="pixel" ) {
1858        pixelGW = q.getValue();
1859      }
1860      else {
1861        pixelGW = q.getValue("rad")/celly_;
1862      }
1863    }
1864    pixelGW = (pixelGW >= 0.0) ? pixelGW : sqrt(log(2.0)) * 2.52;
1865    if (pixelGW < 0.0) {
1866      os << LogIO::SEVERE
1867         << "Negative width is specified for gaussian" << LogIO::EXCEPTION;
1868    }
1869    // determine pixel c
1870    // default is c = 1.55 (Mangum et al. 2007)
1871    Double pixelJW = -1.0;
1872    if (!jwidth_.empty()) {
1873      readQuantity( q, jwidth_ );
1874      if ( q.getUnit().empty() || q.getUnit()=="pixel" ) {
1875        pixelJW = q.getValue();
1876      }
1877      else {
1878        pixelJW = q.getValue("rad")/celly_;
1879      }
1880    }
1881    pixelJW = (pixelJW >= 0.0) ? pixelJW : 1.55;
1882    if (pixelJW < 0.0) {
1883      os << LogIO::SEVERE
1884         << "Negative width is specified for jinc" << LogIO::EXCEPTION;
1885    }
1886    // determine truncation radius
1887    // default is -1.0 (truncate at first null)
1888    Double truncate = -1.0;
1889    if (!truncate_.empty()) {
1890      readQuantity( q, truncate_ );
1891      if ( q.getUnit().empty() || q.getUnit()=="pixel" ) {
1892        truncate = q.getValue();
1893      }
1894      else {
1895        truncate = q.getValue("rad")/celly_;
1896      }
1897    }     
1898    //convSupport_ = (truncate >= 0.0) ? (Int)(truncate+0.5) : (Int)(2*pixelJW+0.5);
1899    Double convSupportF = (truncate >= 0.0) ? truncate : (2*pixelJW);
1900    convSupport_ = (Int)convSupportF;
1901    convSupport_ += (((convSupportF-(Double)convSupport_) > 0.0) ? 1 : 0);
1902    Int convSize = convSampling_ * ( 2*convSupport_ + 2 ) ;
1903    convFunc.resize( convSize ) ;
1904    gjincFunc( convFunc, pixelGW, pixelJW, truncate ) ;
1905    os << LogIO::DEBUGGING
1906       << "convType_ = " << convType_ << endl
1907       << "convSupport_ = " << convSupport_ << endl
1908       << "truncate_ = " << truncate << "pixel" << endl
1909       << "gwidth_ = " << pixelGW << "pixel" << endl
1910       << "jwidth_ = " << pixelJW << "pixel" << LogIO::POST;
1911  }
1912  else if ( convType_ == "PB" ) {
1913    if ( convSupport_ < 0 )
1914      convSupport_ = 0 ;
1915    pbFunc( convFunc ) ;
1916  }
1917  else {
1918    throw AipsError( "Unsupported convolution function" ) ;
1919  }
1920}
1921
1922string STGrid::saveData( string outfile )
1923{
1924  LogIO os( LogOrigin("STGrid", "saveData", WHERE) ) ;
1925  double t0, t1 ;
1926  t0 = mathutil::gettimeofday_sec() ;
1927
1928  //Int polno = 0 ;
1929  String outfile_ ;
1930  if ( outfile.size() == 0 ) {
1931    if ( infileList_[0].lastchar() == '/' ) {
1932      outfile_ = infileList_[0].substr( 0, infileList_[0].size()-1 ) ;
1933    }
1934    else {
1935      outfile_ = infileList_[0] ;
1936    }
1937    outfile_ += ".grid" ;
1938  }
1939  else {
1940    outfile_ = outfile ;
1941  }
1942  Table tab ;
1943  prepareTable( tab, outfile_ ) ;
1944  fillTable( tab ) ;
1945
1946  t1 = mathutil::gettimeofday_sec() ;
1947  os << LogIO::DEBUGGING << "saveData: elapsed time is " << t1-t0 << " sec." << LogIO::POST ;
1948
1949  return outfile_ ;
1950}
1951
1952void STGrid::prepareTable( Table &tab, String &name )
1953{
1954  Table t( infileList_[0], Table::Old ) ;
1955  t.deepCopy( name, Table::New, False, t.endianFormat(), True ) ;
1956  tab = Table( name, Table::Update ) ;
1957  // 2012/02/13 TN
1958  // explicitly copy subtables since no rows including subtables are
1959  // copied by Table::deepCopy with noRows=True
1960  //TableCopy::copySubTables( tab, t ) ;
1961  const TableRecord &inrec = t.keywordSet();
1962  TableRecord &outrec = tab.rwKeywordSet();
1963  for (uInt i = 0 ; i < inrec.nfields() ; i++) {
1964    if (inrec.type(i) == TpTable) {
1965      String name = inrec.name(i);
1966      Table intable = inrec.asTable(name);
1967      Table outtable = outrec.asTable(name);
1968      TableCopy::copyRows(outtable, intable);
1969    }
1970  }
1971}
1972
1973void STGrid::fillTable( Table &tab )
1974{
1975  //IPosition dshape = data_.shape() ;
1976  Int nrow = nx_ * ny_ * npol_ ;
1977  tab.rwKeywordSet().define( "nPol", npol_ ) ;
1978  tab.addRow( nrow ) ;
1979  Vector<Double> cpix( 2 ) ;
1980  cpix(0) = Double( nx_ - 1 ) * 0.5 ;
1981  cpix(1) = Double( ny_ - 1 ) * 0.5 ;
1982  Vector<Double> dir( 2 ) ;
1983  Vector<Double> pix( 2 );
1984  ArrayColumn<Double> directionCol( tab, "DIRECTION" ) ;
1985  ArrayColumn<Float> spectraCol( tab, "SPECTRA" ) ;
1986  ArrayColumn<uChar> flagtraCol( tab, "FLAGTRA" ) ;
1987  ScalarColumn<uInt> flagRowCol( tab, "FLAGROW" );
1988  ScalarColumn<uInt> polnoCol( tab, "POLNO" ) ;
1989  ScalarColumn<uInt> scannoCol( tab, "SCANNO" ) ;
1990  Int irow = 0 ;
1991  Vector<Float> sp( nchan_ ) ;
1992  Vector<uChar> flag( nchan_ ) ;
1993  Bool bsp, bdata, bflag ;
1994  const Float *data_p = data_.getStorage( bdata ) ;
1995  const uChar *flag_p = flag_.getStorage( bflag ) ;
1996  Float *wsp_p, *sp_p ;
1997  const Float *wdata_p = data_p ;
1998  const uChar *wflag_p = flag_p ;
1999  long step = nx_ * ny_ * npol_ ;
2000  long offset ;
2001  uInt scanno = 0 ;
2002  uChar rflag;
2003  for ( Int iy = 0 ; iy < ny_ ; iy++ ) {
2004    pix(1) = (Double)(iy);
2005    for ( Int ix = 0 ; ix < nx_ ; ix++ ) {
2006      pix(0) = (Double)(ix);
2007      dircoord_->toWorld(dir,pix);
2008      //os << "dir[" << ix << "," << iy << "]=" << dir << LogIO::POST;
2009      for ( Int ipol = 0 ; ipol < npol_ ; ipol++ ) {
2010        offset = ix + nx_ * (iy + ipol * ny_) ;
2011        //os << "offset = " << offset << LogIO::POST ;
2012        sp_p = sp.getStorage( bsp ) ;
2013        wsp_p = sp_p ;
2014        wdata_p = data_p + offset ;
2015        wflag_p = flag_p + offset ;
2016        rflag = ~0 ; //11111111
2017        for ( Int ichan = 0 ; ichan < nchan_ ; ichan++ ) {
2018          *wsp_p = *wdata_p ;
2019          wsp_p++ ;
2020          wdata_p += step ;
2021          flag[ichan] = *wflag_p ;
2022          rflag &= flag[ichan] ;
2023          wflag_p += step ;
2024        }
2025        sp.putStorage( sp_p, bsp ) ;
2026        spectraCol.put( irow, sp ) ;
2027        flagtraCol.put( irow, flag ) ;
2028        flagRowCol.put( irow, ((rflag>0) ? 1 : 0) ) ;
2029        directionCol.put( irow, dir ) ;
2030        polnoCol.put( irow, pollist_[ipol] ) ;
2031        scannoCol.put( irow, scanno ) ;
2032        irow++ ;
2033      }
2034      scanno++ ;
2035    }
2036  }
2037  data_.freeStorage( data_p, bdata ) ;
2038  flag_.freeStorage( flag_p, bflag ) ;
2039
2040  fillMainColumns( tab ) ;
2041}
2042
2043void STGrid::fillMainColumns( Table &tab )
2044{
2045  // values for fill
2046  //Table t( infileList_[0], Table::Old ) ;
2047  Table t ;
2048  table( t, 0 ) ;
2049  Table tsel = t( t.col( "IFNO" ) == (uInt)ifno_, 1 ) ;
2050  ROTableRow row( tsel ) ;
2051  row.get( 0 ) ;
2052  const TableRecord &rec = row.record() ;
2053  uInt freqId = rec.asuInt( "FREQ_ID" ) ;
2054  uInt molId = rec.asuInt( "MOLECULE_ID" ) ;
2055  uInt tcalId = rec.asuInt( "TCAL_ID" ) ;
2056  uInt focusId = rec.asuInt( "FOCUS_ID" ) ;
2057  uInt weatherId = rec.asuInt( "WEATHER_ID" ) ;
2058  String srcname = rec.asString( "SRCNAME" ) ;
2059  String fieldname = rec.asString( "FIELDNAME" ) ;
2060  Vector<Float> defaultTsys( 1, 1.0 ) ;
2061  // @todo how to set flagtra for gridded spectra?
2062  Vector<uChar> flagtra = rec.asArrayuChar( "FLAGTRA" ) ;
2063  flagtra = (uChar)0 ;
2064  Float opacity = rec.asFloat( "OPACITY" ) ;
2065  Double srcvel = rec.asDouble( "SRCVELOCITY" ) ;
2066  Vector<Double> srcpm = rec.asArrayDouble( "SRCPROPERMOTION" ) ;
2067  Vector<Double> srcdir = rec.asArrayDouble( "SRCDIRECTION" ) ;
2068  Vector<Double> scanrate = rec.asArrayDouble( "SCANRATE" ) ;
2069  Double time = rec.asDouble( "TIME" ) ;
2070  Double interval = rec.asDouble( "INTERVAL" ) ;
2071
2072  // fill columns
2073  Int nrow = tab.nrow() ;
2074  ScalarColumn<uInt> ifnoCol( tab, "IFNO" ) ;
2075  ScalarColumn<uInt> beamnoCol(tab, "BEAMNO");
2076  ScalarColumn<uInt> freqIdCol( tab, "FREQ_ID" ) ;
2077  ScalarColumn<uInt> molIdCol( tab, "MOLECULE_ID" ) ;
2078  ScalarColumn<uInt> tcalidCol( tab, "TCAL_ID" ) ;
2079  ScalarColumn<Int> fitidCol( tab, "FIT_ID" ) ;
2080  ScalarColumn<uInt> focusidCol( tab, "FOCUS_ID" ) ;
2081  ScalarColumn<uInt> weatheridCol( tab, "WEATHER_ID" ) ;
2082  ArrayColumn<uChar> flagtraCol( tab, "FLAGTRA" ) ;
2083  ScalarColumn<uInt> rflagCol( tab, "FLAGROW" ) ;
2084  ArrayColumn<Float> tsysCol( tab, "TSYS" ) ;
2085  ScalarColumn<String> srcnameCol( tab, "SRCNAME" ) ;
2086  ScalarColumn<String> fieldnameCol( tab, "FIELDNAME" ) ;
2087  ScalarColumn<Int> srctypeCol( tab, "SRCTYPE" ) ;
2088  ScalarColumn<Float> opacityCol( tab, "OPACITY" ) ;
2089  ScalarColumn<Double> srcvelCol( tab, "SRCVELOCITY" ) ;
2090  ArrayColumn<Double> srcpmCol( tab, "SRCPROPERMOTION" ) ;
2091  ArrayColumn<Double> srcdirCol( tab, "SRCDIRECTION" ) ;
2092  ArrayColumn<Double> scanrateCol( tab, "SCANRATE" ) ;
2093  ScalarColumn<Double> timeCol( tab, "TIME" ) ;
2094  ScalarColumn<Double> intervalCol( tab, "INTERVAL" ) ;
2095  for ( Int i = 0 ; i < nrow ; i++ ) {
2096    ifnoCol.put( i, (uInt)ifno_ ) ;
2097    beamnoCol.put(i, 0);
2098    freqIdCol.put( i, freqId ) ;
2099    molIdCol.put( i, molId ) ;
2100    tcalidCol.put( i, tcalId ) ;
2101    fitidCol.put( i, -1 ) ;
2102    focusidCol.put( i, focusId ) ;
2103    weatheridCol.put( i, weatherId ) ;
2104    //flagtraCol.put( i, flagtra ) ;
2105    //rflagCol.put( i, 0 ) ;
2106    tsysCol.put( i, defaultTsys ) ;
2107    srcnameCol.put( i, srcname ) ;
2108    fieldnameCol.put( i, fieldname ) ;
2109    srctypeCol.put( i, (Int)SrcType::PSON ) ;
2110    opacityCol.put( i, opacity ) ;
2111    srcvelCol.put( i, srcvel ) ;
2112    srcpmCol.put( i, srcpm ) ;
2113    srcdirCol.put( i, srcdir ) ;
2114    scanrateCol.put( i, scanrate ) ;
2115    timeCol.put( i, time ) ;
2116    intervalCol.put( i, interval ) ;
2117    if ( (i + 1) % npol_ == 0 ) {
2118      time += interval / 86400.0;
2119    }
2120  }
2121}
2122
2123vector<int> STGrid::getResultantMapSize()
2124{
2125  vector<int> r(2);
2126  r[0] = nx_;
2127  r[1] = ny_;
2128  return r;
2129}
2130
2131vector<double> STGrid::getResultantCellSize()
2132{
2133  vector<double> r(2);
2134  r[0] = cellx_;
2135  r[1] = celly_;
2136  return r;
2137}
2138
2139// STGrid2
2140STGrid2::STGrid2()
2141  : STGrid()
2142{
2143}
2144
2145STGrid2::STGrid2( const ScantableWrapper &s )
2146  : STGrid()
2147{
2148  setScantable( s ) ;
2149}
2150
2151STGrid2::STGrid2( const vector<ScantableWrapper> &v )
2152  : STGrid()
2153{
2154  setScantableList( v ) ;
2155}
2156
2157void STGrid2::setScantable( const ScantableWrapper &s )
2158{
2159  nfile_ = 1 ;
2160  dataList_.resize( nfile_ ) ;
2161  dataList_[0] = s ;
2162  infileList_.resize( nfile_ ) ;
2163  infileList_[0] = s.getCP()->table().tableName() ;
2164}
2165
2166void STGrid2::setScantableList( const vector<ScantableWrapper> &v )
2167{
2168  nfile_ = v.size() ;
2169  dataList_.resize( nfile_ ) ;
2170  infileList_.resize( nfile_ ) ;
2171  for ( uInt i = 0 ; i < nfile_ ; i++ ) {
2172    dataList_[i] = v[i] ;
2173    infileList_[i] = v[i].getCP()->table().tableName() ;
2174  }
2175}
2176
2177ScantableWrapper STGrid2::getResultAsScantable( int tp )
2178{
2179  ScantableWrapper sw( tp ) ;
2180  CountedPtr<Scantable> s = sw.getCP() ;
2181  s->setHeader( dataList_[0].getCP()->getHeader() ) ;
2182  Table tout, tin ;
2183  String subt[] = { "FREQUENCIES", "FOCUS", "WEATHER",
2184                    "TCAL", "MOLECULES", "HISTORY", "FIT" } ;
2185  for ( uInt i = 0 ; i < 7 ; i++ ) {
2186    tout = s->table().rwKeywordSet().asTable(subt[i]) ;
2187    tin = dataList_[0].getCP()->table().rwKeywordSet().asTable(subt[i]) ;
2188    TableCopy::copyRows( tout, tin ) ;
2189    tout.rwKeywordSet() = tin.rwKeywordSet();
2190  }
2191  fillTable( s->table() ) ;
2192  return sw ;
2193}
2194
2195void STGrid2::table( Table &tab, uInt i )
2196{
2197  if ( i < nfile_ )
2198    tab = dataList_[i].getCP()->table() ;
2199}
2200
2201}
Note: See TracBrowser for help on using the repository browser.