Changeset 2794 for trunk/src


Ignore:
Timestamp:
03/15/13 18:23:04 (11 years ago)
Author:
Kana Sugimoto
Message:

New Development: Yes

JIRA Issue: Yes (CAS-4141/TRAC-290)

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs:

Put in Release Notes: No

Module(s): sbseparator module

Description: Pushed python codes down to cpp.


Location:
trunk/src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/STSideBandSep.cpp

    r2726 r2794  
    2626
    2727// asap
     28#include "STGrid.h"
     29#include "STMath.h"
     30#include "MathUtils.h"
    2831#include "STSideBandSep.h"
    2932
     
    3235using namespace asap ;
    3336
    34 #ifndef KS_DEBUG
    35 #define KS_DEBUG
    36 #endif
     37// #ifndef KS_DEBUG
     38// #define KS_DEBUG
     39// #endif
    3740
    3841namespace asap {
     
    7881
    7982  init();
     83  tp_ = intabList_[0]->table().tableType();
    8084
    8185  os << ntable_ << " tables are set." << LogIO::POST;
     
    9296{
    9397  // frequency setup
    94   sigIfno_= 0;
     98  sigIfno_= -1;
    9599  ftol_ = -1;
    96100  solFrame_ = MFrequency::N_Types;
     
    109113  // Default LO frame is TOPO
    110114  loFrame_ = MFrequency::TOPO;
     115  // scantable storage
     116  tp_ = Table::Memory;
    111117};
    112118
     
    130136
    131137  // IFNO
    132   sigIfno_ = ifno;
     138  sigIfno_ = (int) ifno;
    133139
    134140  // Frequency tolerance
     
    219225      if (i != imgShift_.size()-1) os << " , ";
    220226    }
    221     os << " ) [channel]" << LogIO::POST;
     227    os << " ) [channels]" << LogIO::POST;
    222228  }
    223229};
     
    227233  LogIO os(LogOrigin("STSideBandSep","setThreshold()", WHERE));
    228234  if (limit < 0)
    229     throw( AipsError("Rejection limit should be positive number.") );
     235    throw( AipsError("Rejection limit should be a positive number.") );
    230236
    231237  rejlimit_ = limit;
    232   os << "Rejection limit is set to " << rejlimit_;
    233 };
    234 
    235 // Temporal function to set scantable of image sideband
    236 void STSideBandSep::setImageTable(const ScantableWrapper &s)
    237 {
    238 #ifdef KS_DEBUG
    239   cout << "STSideBandSep::setImageTable" << endl;
    240   cout << "got image table nrow = " << s.nrow() << endl;
    241 #endif
    242   imgTab_p = s.getCP();
    243   AlwaysAssert(!imgTab_p.null(),AipsError);
    244 
    245 };
    246 
    247 //
    248 void STSideBandSep::setLO1(const double lo1, const string frame,
     238  os << "Rejection limit is set to " << rejlimit_ << LogIO::POST;
     239};
     240
     241void STSideBandSep::separate(string outname)
     242{
     243#ifdef KS_DEBUG
     244  cout << "STSideBandSep::separate" << endl;
     245#endif
     246  LogIO os(LogOrigin("STSideBandSep","separate()", WHERE));
     247  if (outname.empty())
     248    outname = "sbseparated.asap";
     249
     250  // Set up a goup of IFNOs in the list of scantables within
     251  // the frequency tolerance and make them a list.
     252  nshift_ = setupShift();
     253  if (nshift_ < 2)
     254    throw( AipsError("At least 2 IFs are necessary for convolution.") );
     255  // Grid scantable and generate output tables
     256  ScantableWrapper gridst = gridTable();
     257  sigTab_p = gridst.getCP();
     258  if (doboth_)
     259    imgTab_p = gridst.copy().getCP();
     260  vector<unsigned int> remRowIds;
     261  remRowIds.resize(0);
     262  Matrix<float> specMat(nchan_, nshift_);
     263  vector<float> sigSpec(nchan_), imgSpec(nchan_);
     264  vector<uInt> tabIdvec;
     265
     266  //Generate FFTServer
     267  fftsf.resize(IPosition(1, nchan_), FFTEnums::REALTOCOMPLEX);
     268  fftsi.resize(IPosition(1, nchan_), FFTEnums::COMPLEXTOREAL);
     269
     270  /// Loop over sigTab_p and separate sideband
     271  for (int irow = 0; irow < sigTab_p->nrow(); irow++){
     272    tabIdvec.resize(0);
     273    const int polId = sigTab_p->getPol(irow);
     274    const int beamId = sigTab_p->getBeam(irow);
     275    const vector<double> dir = sigTab_p->getDirectionVector(irow);
     276    // Get a set of spectra to solve
     277    if (!getSpectraToSolve(polId, beamId, dir[0], dir[1],
     278                           specMat, tabIdvec)){
     279      remRowIds.push_back(irow);
     280#ifdef KS_DEBUG
     281      cout << "no matching row found. skipping row = " << irow << endl;
     282#endif
     283      continue;
     284    }
     285    // Solve signal sideband
     286    sigSpec = solve(specMat, tabIdvec, true);
     287    sigTab_p->setSpectrum(sigSpec, irow);
     288
     289    // Solve image sideband
     290    if (doboth_) {
     291      imgSpec = solve(specMat, tabIdvec, false);
     292      imgTab_p->setSpectrum(imgSpec, irow);
     293    }
     294  } // end of row loop
     295
     296  // Remove or flag rows without relevant data from gridded tables
     297  if (remRowIds.size() > 0) {
     298    const size_t nrem = remRowIds.size();
     299    if ( sigTab_p->table().canRemoveRow() ) {
     300      sigTab_p->table().removeRow(remRowIds);
     301      os << "Removing " << nrem << " rows from the signal band table"
     302         << LogIO::POST;
     303    } else {
     304      sigTab_p->flagRow(remRowIds, false);
     305      os << "Cannot remove rows from the signal band table. Flagging "
     306         << nrem << " rows" << LogIO::POST;
     307    }
     308
     309    if (doboth_) {
     310      if ( imgTab_p->table().canRemoveRow() ) {
     311        imgTab_p->table().removeRow(remRowIds);
     312        os << "Removing " << nrem << " rows from the image band table"
     313           << LogIO::POST;
     314      } else {
     315        imgTab_p->flagRow(remRowIds, false);
     316        os << "Cannot remove rows from the image band table. Flagging "
     317           << nrem << " rows" << LogIO::POST;
     318      }
     319    }
     320  }
     321
     322  // Finally, save tables on disk
     323  if (outname.size() ==0)
     324    outname = "sbseparated.asap";
     325  const string sigName = outname + ".signalband";
     326  os << "Saving SIGNAL sideband table: " << sigName << LogIO::POST;
     327  sigTab_p->makePersistent(sigName);
     328  if (doboth_) {
     329    solveImageFrequency();
     330    const string imgName = outname + ".imageband";
     331    os << "Saving IMAGE sideband table: " << sigName << LogIO::POST;
     332    imgTab_p->makePersistent(imgName);
     333  }
     334
     335};
     336
     337unsigned int STSideBandSep::setupShift()
     338{
     339  LogIO os(LogOrigin("STSideBandSep","setupShift()", WHERE));
     340  if (infileList_.size() == 0 && intabList_.size() == 0)
     341    throw( AipsError("No scantable has been set. Set a list of scantables first.") );
     342
     343  const bool byname = (intabList_.size() == 0);
     344  // Make sure sigIfno_ exists in the first table.
     345  CountedPtr<Scantable> stab;
     346  vector<string> coordsav;
     347  vector<string> coordtmp(3);
     348  os << "Checking IFNO in the first table." << LogIO::POST;
     349  if (byname) {
     350    if (!checkFile(infileList_[0], "d"))
     351      os << LogIO::SEVERE << "Could not find scantable '" << infileList_[0]
     352         << "'" << LogIO::EXCEPTION;
     353    stab = CountedPtr<Scantable>(new Scantable(infileList_[0]));
     354  } else {
     355    stab = intabList_[0];
     356  }
     357  if (sigIfno_ < 0) {
     358    sigIfno_ = (int) stab->getIF(0);
     359    os << "IFNO to process has not been set. Using the first IF = "
     360       << sigIfno_ << LogIO::POST;
     361  }
     362
     363  unsigned int basench;
     364  double basech0, baseinc, ftolval, inctolval;
     365  coordsav = stab->getCoordInfo();
     366  const string stfframe = coordsav[1];
     367  coordtmp[0] = "Hz";
     368  coordtmp[1] = ( (solFrame_ == MFrequency::N_Types) ?
     369                  stfframe :
     370                  MFrequency::showType(solFrame_) );
     371  coordtmp[2] = coordsav[2];
     372  stab->setCoordInfo(coordtmp);
     373  if (!getFreqInfo(stab, (unsigned int) sigIfno_, basech0, baseinc, basench)) {
     374    os << LogIO::SEVERE << "No data with IFNO=" << sigIfno_
     375       << " found in the first table." << LogIO::EXCEPTION;
     376  }
     377  else {
     378    os << "Found IFNO = " << sigIfno_
     379       << " in the first table." << LogIO::POST;
     380  }
     381  if (ftol_.getUnit().empty()) {
     382    // tolerance in unit of channels
     383    ftolval = ftol_.getValue() * baseinc;
     384  }
     385  else {
     386    ftolval = ftol_.getValue("Hz");
     387  }
     388  inctolval = abs(baseinc/(double) basench);
     389  const string poltype0 = stab->getPolType();
     390
     391  // Initialize shift values
     392  initshift();
     393
     394  const bool setImg = ( doboth_ && (imgShift_.size() == 0) );
     395  // Select IFs
     396  for (unsigned int itab = 0; itab < ntable_; itab++ ){
     397    os << "Table " << itab << LogIO::POST;
     398    if (itab > 0) {
     399      if (byname) {
     400        if (!checkFile(infileList_[itab], "d"))
     401          os << LogIO::SEVERE << "Could not find scantable '"
     402             << infileList_[itab] << "'" << LogIO::EXCEPTION;
     403        stab = CountedPtr<Scantable>(new Scantable(infileList_[itab]));
     404      } else {
     405        stab = intabList_[itab];
     406      }
     407      //POLTYPE should be the same.
     408      if (stab->getPolType() != poltype0 ) {
     409        os << LogIO::WARN << "POLTYPE differs from the first table."
     410           << " Skipping the table" << LogIO::POST;
     411        continue;
     412      }
     413      // Multi beam data may not handled properly
     414      if (stab->nbeam() > 1)
     415        os <<  LogIO::WARN << "Table contains multiple beams. "
     416           << "It may not be handled properly."  << LogIO::POST;
     417
     418      coordsav = stab->getCoordInfo();
     419      coordtmp[2] = coordsav[2];
     420      stab->setCoordInfo(coordtmp);
     421    }
     422    bool selected = false;
     423    vector<uint> ifnos = stab->getIFNos();
     424    vector<uint>::iterator iter;
     425    const STSelector& basesel = stab->getSelection();
     426    for (iter = ifnos.begin(); iter != ifnos.end(); iter++){
     427      unsigned int nch;
     428      double freq0, incr;
     429      if ( getFreqInfo(stab, *iter, freq0, incr, nch) ){
     430        if ( (nch == basench) && (abs(freq0-basech0) < ftolval)
     431             && (abs(incr-baseinc) < inctolval) ){
     432          //Found
     433          STSelector sel(basesel);
     434          sel.setIFs(vector<int>(1,(int) *iter));
     435          stab->setSelection(sel);
     436          CountedPtr<Scantable> seltab = ( new Scantable(*stab, false) );
     437          stab->setSelection(basesel);
     438          seltab->setCoordInfo(coordsav);
     439          const double chShift = (freq0 - basech0) / baseinc;
     440          tableList_.push_back(seltab);
     441          sigShift_.push_back(chShift);
     442          if (setImg)
     443            imgShift_.push_back(-chShift);
     444
     445          selected = true;
     446          os << "- IF" << *iter << " selected: sideband shift = "
     447             << chShift << " channels" << LogIO::POST;
     448        }
     449      }
     450    } // ifno loop
     451    stab->setCoordInfo(coordsav);
     452    if (!selected)
     453      os << LogIO::WARN << "No data selected in Table "
     454         << itab << LogIO::POST;
     455  } // table loop
     456  nchan_ = basench;
     457
     458  os << "Total number of IFs selected = " << tableList_.size()
     459     << LogIO::POST;
     460  if ( setImg && (sigShift_.size() != imgShift_.size()) ){
     461      os << LogIO::SEVERE
     462         << "User defined channel shift of image sideband has "
     463         << imgShift_.size()
     464         << " elements, while selected IFNOs are " << sigShift_.size()
     465         << "\nThe frequency tolerance (freqtol) may be too small."
     466         << LogIO::EXCEPTION;
     467  }
     468
     469  return tableList_.size();
     470};
     471
     472bool STSideBandSep::getFreqInfo(const CountedPtr<Scantable> &stab,
     473                                const unsigned int &ifno,
     474                                double &freq0, double &incr,
     475                                unsigned int &nchan)
     476{
     477    vector<uint> ifnos = stab->getIFNos();
     478    bool found = false;
     479    vector<uint>::iterator iter;
     480    for (iter = ifnos.begin(); iter != ifnos.end(); iter++){
     481      if (*iter == ifno) {
     482        found = true;
     483        break;
     484      }
     485    }
     486    if (!found)
     487      return false;
     488
     489    const STSelector& basesel = stab->getSelection();
     490    STSelector sel(basesel);
     491    sel.setIFs(vector<int>(1,(int) ifno));
     492    stab->setSelection(sel);
     493    vector<double> freqs;
     494    freqs = stab->getAbcissa(0);
     495    freq0 = freqs[0];
     496    incr = freqs[1] - freqs[0];
     497    nchan = freqs.size();
     498    stab->setSelection(basesel);
     499    return true;
     500};
     501
     502ScantableWrapper STSideBandSep::gridTable()
     503{
     504  LogIO os(LogOrigin("STSideBandSep","gridTable()", WHERE));
     505  if (tableList_.size() == 0)
     506    throw( AipsError("Internal error. No scantable has been set to grid.") );
     507  Double xmin, xmax, ymin, ymax;
     508  mapExtent(tableList_, xmin, xmax, ymin, ymax);
     509  const Double centx = 0.5 * (xmin + xmax);
     510  const Double centy = 0.5 * (ymin + ymax);
     511  const int nx = max(1, (int) ceil( (xmax - xmin) * cos(centy) /xtol_ ) );
     512  const int ny = max(1, (int) ceil( (ymax - ymin) / ytol_ ) );
     513
     514  string scellx, scelly;
     515  {
     516    ostringstream oss;
     517    oss << xtol_ << "rad" ;
     518    scellx = oss.str();
     519  }
     520  {
     521    ostringstream oss;
     522    oss << ytol_ << "rad" ;
     523    scelly = oss.str();
     524  }
     525
     526  ScantableWrapper stab0;
     527  if (intabList_.size() > 0)
     528    stab0 = ScantableWrapper(intabList_[0]);
     529  else
     530    stab0 = ScantableWrapper(infileList_[0]);
     531
     532  string scenter;
     533  {
     534    ostringstream oss;
     535    oss << stab0.getCP()->getDirectionRefString() << " "
     536        << centx << "rad" << " " << centy << "rad";
     537    scenter = oss.str();
     538  }
     539 
     540  STGrid2 gridder = STGrid2(stab0);
     541  gridder.setIF(sigIfno_);
     542  gridder.defineImage(nx, ny, scellx, scelly, scenter);
     543  gridder.setFunc("box", 1);
     544  gridder.setWeight("uniform");
     545#ifdef KS_DEBUG
     546  cout << "Grid parameter summary: " << endl;
     547  cout << "- IF = " << sigIfno_ << endl;
     548  cout << "- center = " << scenter << ")\n"
     549       << "- npix = (" << nx << ", " << ny << ")\n"
     550       << "- cell = (" << scellx << ", " << scelly << endl;
     551#endif
     552  gridder.grid();
     553  const int itp = (tp_ == Table::Memory ? 0 : 1);
     554  ScantableWrapper gtab = gridder.getResultAsScantable(itp);
     555  return gtab;
     556};
     557
     558void STSideBandSep::mapExtent(vector< CountedPtr<Scantable> > &tablist,
     559                              Double &xmin, Double &xmax,
     560                              Double &ymin, Double &ymax)
     561{
     562  ROArrayColumn<Double> dirCol_;
     563  dirCol_.attach( tablist[0]->table(), "DIRECTION" );
     564  Matrix<Double> direction = dirCol_.getColumn();
     565  Vector<Double> ra( direction.row(0) );
     566  mathutil::rotateRA(ra);
     567  minMax( xmin, xmax, ra );
     568  minMax( ymin, ymax, direction.row(1) );
     569  Double amin, amax, bmin, bmax;
     570  const uInt ntab = tablist.size();
     571  for ( uInt i = 1 ; i < ntab ; i++ ) {
     572    dirCol_.attach( tablist[i]->table(), "DIRECTION" );
     573    direction.assign( dirCol_.getColumn() );
     574    ra.assign( direction.row(0) );
     575    mathutil::rotateRA(ra);
     576    minMax( amin, amax, ra );
     577    minMax( bmin, bmax, direction.row(1) );
     578    xmin = min(xmin, amin);
     579    xmax = max(xmax, amax);
     580    ymin = min(ymin, bmin);
     581    ymax = max(ymax, bmax);
     582  }
     583};
     584
     585bool STSideBandSep::getSpectraToSolve(const int polId, const int beamId,
     586                                      const double dirX, const double dirY,
     587                                      Matrix<float> &specMat, vector<uInt> &tabIdvec)
     588{
     589  LogIO os(LogOrigin("STSideBandSep","getSpectraToSolve()", WHERE));
     590
     591  tabIdvec.resize(0);
     592  specMat.resize(nchan_, nshift_);
     593  Vector<float> spec;
     594  uInt nspec = 0;
     595  STMath stm(false); // insitu has no effect for average.
     596  for (uInt itab = 0 ; itab < nshift_ ; itab++) {
     597    CountedPtr<Scantable> currtab_p = tableList_[itab];
     598    // Selection by POLNO and BEAMNO
     599    const STSelector& basesel = currtab_p->getSelection();
     600    STSelector sel(basesel);
     601    sel.setPolarizations(vector<int>(1, polId));
     602    sel.setBeams(vector<int>(1, beamId));
     603    try {
     604      currtab_p->setSelection(sel);
     605    } catch (...) {
     606#ifdef KS_DEBUG
     607      cout << "Table " << itab << " - No spectrum found. skipping the table."
     608           << endl;
     609#endif
     610      continue;
     611    }
     612    // Selection by direction;
     613    vector<int> selrow(0);
     614    vector<double> currDir(2, 0.);
     615    const int nselrow = currtab_p->nrow();
     616    for (int irow = 0 ; irow < nselrow ; irow++) {
     617      currDir = currtab_p->getDirectionVector(irow);
     618      if ( (abs(currDir[0]-dirX) > xtol_) ||
     619           (abs(currDir[1]-dirY) > ytol_) )
     620        continue;
     621      // within direction tolerance
     622      selrow.push_back(irow);
     623    } // end of row loop
     624
     625    if (selrow.size() < 1) {
     626      currtab_p->setSelection(basesel);
     627
     628#ifdef KS_DEBUG
     629      cout << "Table " << itab << " - No spectrum found. skipping the table."
     630           << endl;
     631#endif
     632
     633      continue;
     634    }
     635
     636    // At least a spectrum is selected in this table
     637    CountedPtr<Scantable> seltab_p = ( new Scantable(*currtab_p, false) );
     638    currtab_p->setSelection(basesel);
     639    STSelector sel2(seltab_p->getSelection());
     640    sel2.setRows(selrow);
     641    seltab_p->setSelection(sel2);
     642    CountedPtr<Scantable> avetab_p;
     643    vector<bool> mask;
     644    if (seltab_p->nrow() > 1) {
     645      avetab_p = stm.average(vector< CountedPtr<Scantable> >(1, seltab_p),
     646                             vector<bool>(), "TINTSYS", "NONE");
     647#ifdef KS_DEBUG
     648      cout << "Table " << itab << " - more than a spectrum is selected. averaging rows..."
     649           << endl;
     650#endif
     651      if (avetab_p->nrow() > 1)
     652        throw( AipsError("Averaged table has more than a row. Somethigs went wrong.") );
     653    } else {
     654      avetab_p = seltab_p;
     655    }
     656    spec.reference(specMat.column(nspec));
     657    spec = avetab_p->getSpectrum(0);
     658    tabIdvec.push_back((uInt) itab);
     659    nspec++;
     660  } // end of table loop
     661  if (nspec != nshift_){
     662    //shiftSpecmat.resize(nchan_, nspec, true);
     663#ifdef KS_DEBUG
     664      cout << "Could not find corresponding rows in some tables."
     665           << endl;
     666      cout << "Number of spectra selected = " << nspec << endl;
     667#endif
     668  }
     669  if (nspec < 2) {
     670#ifdef KS_DEBUG
     671      cout << "At least 2 spectra are necessary for convolution"
     672           << endl;
     673#endif
     674      return false;
     675  }
     676  return true;
     677};
     678
     679vector<float> STSideBandSep::solve(const Matrix<float> &specmat,
     680                                   const vector<uInt> &tabIdvec,
     681                                   const bool signal)
     682{
     683  LogIO os(LogOrigin("STSideBandSep","solve()", WHERE));
     684  if (tabIdvec.size() == 0)
     685    throw(AipsError("Internal error. Table index is not defined."));
     686  if (specmat.ncolumn() != tabIdvec.size())
     687    throw(AipsError("Internal error. The row number of input matrix is not conformant."));
     688  if (specmat.nrow() != nchan_)
     689    throw(AipsError("Internal error. The channel size of input matrix is not conformant."));
     690 
     691
     692#ifdef KS_DEBUG
     693  cout << "Solving " << (signal ? "SIGNAL" : "IMAGE") << " sideband."
     694     << endl;
     695#endif
     696
     697  const size_t nspec = tabIdvec.size();
     698  vector<double> *thisShift, *otherShift;
     699  if (signal == otherside_) {
     700    // (solve signal && solveother = T) OR (solve image && solveother = F)
     701    thisShift = &imgShift_;
     702    otherShift = &sigShift_;
     703#ifdef KS_DEBUG
     704    cout << "Image sideband will be deconvolved." << endl;
     705#endif
     706  } else {
     707    // (solve signal && solveother = F) OR (solve image && solveother = T)
     708    thisShift =  &sigShift_;
     709    otherShift = &imgShift_;
     710#ifdef KS_DEBUG
     711    cout << "Signal sideband will be deconvolved." << endl;
     712#endif
     713 }
     714
     715  vector<double> spshift(nspec);
     716  Matrix<float> shiftSpecmat(nchan_, nspec, 0.);
     717  double tempshift;
     718  Vector<float> shiftspvec;
     719  for (uInt i = 0 ; i < nspec; i++) {
     720    spshift[i] = otherShift->at(i) - thisShift->at(i);
     721    tempshift = - thisShift->at(i);
     722    shiftspvec.reference(shiftSpecmat.column(i));
     723    shiftSpectrum(specmat.column(i), tempshift, shiftspvec);
     724  }
     725
     726  Matrix<float> convmat(nchan_, nspec*(nspec-1)/2, 0.);
     727  vector<float> thisvec(nchan_, 0.);
     728
     729  float minval, maxval;
     730  minMax(minval, maxval, shiftSpecmat);
     731#ifdef KS_DEBUG
     732  cout << "Max/Min of input Matrix = (max: " << maxval << ", min: " << minval << ")" << endl;
     733#endif
     734
     735#ifdef KS_DEBUG
     736  cout << "starting deconvolution" << endl;
     737#endif
     738  deconvolve(shiftSpecmat, spshift, rejlimit_, convmat);
     739#ifdef KS_DEBUG
     740  cout << "finished deconvolution" << endl;
     741#endif
     742
     743  minMax(minval, maxval, convmat);
     744#ifdef KS_DEBUG
     745  cout << "Max/Min of output Matrix = (max: " << maxval << ", min: " << minval << ")" << endl;
     746#endif
     747
     748  aggregateMat(convmat, thisvec);
     749
     750  if (!otherside_) return thisvec;
     751
     752  // subtract from the other side band.
     753  vector<float> othervec(nchan_, 0.);
     754  subtractFromOther(shiftSpecmat, thisvec, spshift, othervec);
     755  return othervec;
     756};
     757
     758
     759void STSideBandSep::shiftSpectrum(const Vector<float> &invec,
     760                                  double shift,
     761                                  Vector<float> &outvec)
     762{
     763  LogIO os(LogOrigin("STSideBandSep","shiftSpectrum()", WHERE));
     764  if (invec.size() != nchan_)
     765    throw(AipsError("Internal error. The length of input vector differs from nchan_"));
     766  if (outvec.size() != nchan_)
     767    throw(AipsError("Internal error. The length of output vector differs from nchan_"));
     768
     769#ifdef KS_DEBUG
     770  cout << "Start shifting spectrum for " << shift << "channels" << endl;
     771#endif
     772
     773  // tweak shift to be in 0 ~ nchan_-1
     774  if ( fabs(shift) > nchan_ ) shift = fmod(shift, nchan_);
     775  if (shift < 0.) shift += nchan_;
     776  double rweight = fmod(shift, 1.);
     777  if (rweight < 0.) rweight += 1.;
     778  double lweight = 1. - rweight;
     779  uInt lchan, rchan;
     780
     781  outvec = 0;
     782  for (uInt i = 0 ; i < nchan_ ; i++) {
     783    lchan = uInt( floor( fmod( (i + shift), nchan_ ) ) );
     784    if (lchan < 0.) lchan += nchan_;
     785    rchan = ( (lchan + 1) % nchan_ );
     786    outvec(lchan) += invec(i) * lweight;
     787    outvec(rchan) += invec(i) * rweight;
     788  }
     789};
     790
     791void STSideBandSep::deconvolve(Matrix<float> &specmat,
     792                               const vector<double> shiftvec,
     793                               const double threshold,
     794                               Matrix<float> &outmat)
     795{
     796  LogIO os(LogOrigin("STSideBandSep","deconvolve()", WHERE));
     797  if (specmat.nrow() != nchan_)
     798    throw(AipsError("Internal error. The length of input matrix differs from nchan_"));
     799  if (specmat.ncolumn() != shiftvec.size())
     800    throw(AipsError("Internal error. The number of input shifts and spectrum  differs."));
     801
     802  float minval, maxval;
     803#ifdef KS_DEBUG
     804  minMax(minval, maxval, specmat);
     805  cout << "Max/Min of input Matrix = (max: " << maxval << ", min: " << minval << ")" << endl;
     806#endif
     807
     808  uInt ninsp = shiftvec.size();
     809  outmat.resize(nchan_, ninsp*(ninsp-1)/2, 0.);
     810  Matrix<Complex> fftspmat(nchan_/2+1, ninsp, 0.);
     811  Vector<float> rvecref(nchan_, 0.);
     812  Vector<Complex> cvecref(nchan_/2+1, 0.);
     813  uInt icol = 0;
     814  unsigned int nreject = 0;
     815
     816#ifdef KS_DEBUG
     817  cout << "Starting initial FFT. The number of input spectra = " << ninsp << endl;
     818  cout << "out matrix has ncolumn = " << outmat.ncolumn() << endl;
     819#endif
     820
     821  for (uInt isp = 0 ; isp < ninsp ; isp++) {
     822    rvecref.reference( specmat.column(isp) );
     823    cvecref.reference( fftspmat.column(isp) );
     824
     825#ifdef KS_DEBUG
     826    minMax(minval, maxval, rvecref);
     827    cout << "Max/Min of inv FFTed Matrix = (max: " << maxval << ", min: " << minval << ")" << endl;
     828#endif
     829
     830    fftsf.fft0(cvecref, rvecref, true);
     831
     832#ifdef KS_DEBUG
     833    double maxr=cvecref[0].real(), minr=cvecref[0].real(),
     834      maxi=cvecref[0].imag(), mini=cvecref[0].imag();
     835    for (uInt i = 1; i<cvecref.size();i++){
     836      maxr = max(maxr, cvecref[i].real());
     837      maxi = max(maxi, cvecref[i].imag());
     838      minr = min(minr, cvecref[i].real());
     839      mini = min(mini, cvecref[i].imag());
     840    }
     841    cout << "Max/Min of inv FFTed Matrix (size=" << cvecref.size() << ") = (max: " << maxr << " + " << maxi << "j , min: " << minr << " + " << mini << "j)" << endl;
     842#endif
     843  }
     844
     845  //Liberate from reference
     846  rvecref.unique();
     847
     848  Vector<Complex> cspec(nchan_/2+1, 0.);
     849  const double PI = 6.0 * asin(0.5);
     850  const double nchani = 1. / (float) nchan_;
     851  const Complex trans(0., 1.);
     852#ifdef KS_DEBUG
     853  cout << "starting actual deconvolution" << endl;
     854#endif
     855  for (uInt j = 0 ; j < ninsp ; j++) {
     856    for (uInt k = j+1 ; k < ninsp ; k++) {
     857      const double dx = (shiftvec[k] - shiftvec[j]) * 2. * PI * nchani;
     858
     859#ifdef KS_DEBUG
     860      cout << "icol = " << icol << endl;
     861#endif
     862
     863      for (uInt ichan = 0 ; ichan < cspec.size() ; ichan++){
     864        cspec[ichan] = ( fftspmat(ichan, j) + fftspmat(ichan, k) )*0.5;
     865        double phase = dx*ichan;
     866        if ( fabs( sin(phase) ) > threshold){
     867          cspec[ichan] += ( fftspmat(ichan, j) - fftspmat(ichan, k) ) * 0.5
     868            * trans * sin(phase) / ( 1. - cos(phase) );
     869        } else {
     870          nreject++;
     871        }
     872      } // end of channel loop
     873
     874#ifdef KS_DEBUG
     875      cout << "done calculation of cspec" << endl;
     876#endif
     877
     878      Vector<Float> rspec;
     879      rspec.reference( outmat.column(icol) );
     880
     881#ifdef KS_DEBUG
     882      cout << "Starting inverse FFT. icol = " << icol << endl;
     883      //cout << "- size of complex vector = " << cspec.size() << endl;
     884      double maxr=cspec[0].real(), minr=cspec[0].real(),
     885        maxi=cspec[0].imag(), mini=cspec[0].imag();
     886      for (uInt i = 1; i<cspec.size();i++){
     887        maxr = max(maxr, cspec[i].real());
     888        maxi = max(maxi, cspec[i].imag());
     889        minr = min(minr, cspec[i].real());
     890        mini = min(mini, cspec[i].imag());
     891      }
     892      cout << "Max/Min of conv vector (size=" << cspec.size() << ") = (max: " << maxr << " + " << maxi << "j , min: " << minr << " + " << mini << "j)" << endl;
     893#endif
     894
     895      fftsi.fft0(rspec, cspec, false);
     896
     897#ifdef KS_DEBUG
     898      //cout << "- size of inversed real vector = " << rspec.size() << endl;
     899      minMax(minval, maxval, rspec);
     900      cout << "Max/Min of inv FFTed Vector (size=" << rspec.size() << ") = (max: " << maxval << ", min: " << minval << ")" << endl;
     901      //cout << "Done inverse FFT. icol = " << icol << endl;
     902#endif
     903
     904      icol++;
     905    }
     906  }
     907
     908#ifdef KS_DEBUG
     909  minMax(minval, maxval, outmat);
     910  cout << "Max/Min of inv FFTed Matrix = (max: " << maxval << ", min: " << minval << ")" << endl;
     911#endif
     912
     913  os << "Threshold = " << threshold << ", Rejected channels = " << nreject << endl;
     914};
     915
     916////////////////////////////////////////////////////////////////////
     917// void STSideBandSep::cpprfft(std::vector<float> invec)
     918// {
     919//   cout << "c++ method cpprfft" << endl;
     920//   const unsigned int len = invec.size();
     921//   Vector<Complex> carr(len/2+1, 0.);
     922//   Vector<float> inarr = Vector<float>(invec);
     923//   Vector <float> outarr(len, 0.);
     924//   FFTServer<Float, Complex> fftsf, fftsi;
     925//   fftsf.resize(IPosition(1, len), FFTEnums::REALTOCOMPLEX);
     926//   fftsi.resize(IPosition(1, invec.size()), FFTEnums::COMPLEXTOREAL);
     927//   cout << "Input float array (length = " << len << "):" << endl;
     928//   for (uInt i = 0 ; i < len ; i++){
     929//     cout << (i == 0 ? "( " : " ") << inarr[i] << (i == len-1 ? ")" : ",");
     930//   }
     931//   cout << endl;
     932//   cout << "R->C transform" << endl;
     933//   fftsf.fft0(carr, inarr, true);
     934//   cout << "FFTed complex array (length = " << carr.size() << "):" << endl;
     935//   for (uInt i = 0 ; i < carr.size() ; i++){
     936//     cout << (i == 0 ? "( " : " ") << carr[i] << ( (i == carr.size()-1) ? ")" : "," );
     937//   }
     938//   cout << endl;
     939//   cout << "C->R transform" << endl;
     940//   fftsi.fft0(outarr, carr, false);
     941//   cout << "invFFTed float array (length = " << outarr.size() << "):" << endl;
     942//   for (uInt i = 0 ; i < outarr.size() ; i++){
     943//     cout << (i == 0 ? "( " : " ") << outarr[i] << ( (i == outarr.size()-1) ? ")" : "," );
     944//   }
     945//   cout << endl;
     946// };
     947////////////////////////////////////////////////////////////////////
     948
     949
     950void STSideBandSep::aggregateMat(Matrix<float> &inmat,
     951                                 vector<float> &outvec)
     952{
     953  LogIO os(LogOrigin("STSideBandSep","aggregateMat()", WHERE));
     954  if (inmat.nrow() != nchan_)
     955    throw(AipsError("Internal error. The row numbers of input matrix differs from nchan_"));
     956//   if (outvec.size() != nchan_)
     957//     throw(AipsError("Internal error. The size of output vector should be equal to nchan_"));
     958
     959  os << "Averaging " << inmat.ncolumn() << " spectra in the input matrix."
     960     << LogIO::POST;
     961
     962  const uInt nspec = inmat.ncolumn();
     963  const double scale = 1./( (double) nspec );
     964  // initialize values with 0
     965  outvec.assign(nchan_, 0);
     966  for (uInt isp = 0 ; isp < nspec ; isp++) {
     967    for (uInt ich = 0 ; ich < nchan_ ; ich++) {
     968      outvec[ich] += inmat(ich, isp);
     969    }
     970  }
     971
     972  vector<float>::iterator iter;
     973  for (iter = outvec.begin(); iter != outvec.end(); iter++){
     974    *iter *= scale;
     975  }
     976};
     977
     978void STSideBandSep::subtractFromOther(const Matrix<float> &shiftmat,
     979                                      const vector<float> &invec,
     980                                      const vector<double> &shift,
     981                                      vector<float> &outvec)
     982{
     983  LogIO os(LogOrigin("STSideBandSep","subtractFromOther()", WHERE));
     984  if (shiftmat.nrow() != nchan_)
     985    throw(AipsError("Internal error. The row numbers of input matrix differs from nchan_"));
     986  if (invec.size() != nchan_)
     987    throw(AipsError("Internal error. The length of input vector should be nchan_"));
     988  if (shift.size() != shiftmat.ncolumn())
     989    throw(AipsError("Internal error. The column numbers of input matrix != the number of elements in shift"));
     990
     991  const uInt nspec = shiftmat.ncolumn();
     992  Vector<float> subsp(nchan_, 0.), shiftsub;
     993  Matrix<float> submat(nchan_, nspec, 0.);
     994  vector<float>::iterator iter;
     995  for (uInt isp = 0 ; isp < nspec ; isp++) {
     996    for (uInt ich = 0; ich < nchan_ ; ich++) {
     997      subsp(ich) = shiftmat(ich, isp) - invec[ich];
     998    }
     999    shiftsub.reference(submat.column(isp));
     1000    shiftSpectrum(subsp, shift[isp], shiftsub);
     1001  }
     1002
     1003  aggregateMat(submat, outvec);
     1004};
     1005
     1006
     1007void STSideBandSep::setLO1(const string lo1, const string frame,
    2491008                           const double reftime, const string refdir)
    2501009{
    251   lo1Freq_ = lo1;
     1010  Quantum<Double> qfreq;
     1011  readQuantity(qfreq, String(lo1));
     1012  lo1Freq_ = qfreq.getValue("Hz");
    2521013  MFrequency::getType(loFrame_, frame);
    2531014  loTime_ = reftime;
     
    2971058};
    2981059
    299 ///// TEMPORAL FUNCTION!!! /////
    300 void STSideBandSep::setScanTb0(const ScantableWrapper &s){
    301   st0_ = s.getCP();
    302 };
    303 ////////////////////////////////
    304 
    305 void STSideBandSep::solveImageFreqency()
    306 {
    307 #ifdef KS_DEBUG
    308   cout << "STSideBandSep::solveImageFrequency" << endl;
    309 #endif
     1060
     1061void STSideBandSep::solveImageFrequency()
     1062{
    3101063  LogIO os(LogOrigin("STSideBandSep","solveImageFreqency()", WHERE));
    3111064  os << "Start calculating frequencies of image side band" << LogIO::POST;
     
    3831136    sigrefval = toloframe(Quantum<Double>(refval, "Hz")).get("Hz").getValue();
    3841137
    385 
    3861138  // Check for the availability of LO1
    3871139  if (lo1Freq_ > 0.) {
     
    4021154    // Try getting ASDM name from scantable header
    4031155    os << "Try getting information from scantable header" << LogIO::POST;
    404     if (!getLo1FromScanTab(st0_, sigrefval, refpix, increment, nChan)) {
     1156    if (!getLo1FromScanTab(tableList_[0], sigrefval, refpix, increment, nChan)) {
    4051157      //throw AipsError("Failed to get LO1 frequency from asis table");
    4061158      os << LogIO::WARN << "Failed to get LO1 frequency using information in scantable." << LogIO::POST;
     
    4101162    }
    4111163  }
     1164
    4121165  // LO1 should now be ready.
    4131166  if (lo1Freq_ < 0.)
    4141167    throw(AipsError("Got negative LO1 Frequency"));
    4151168
    416   // Print summary (LO1)
    417   Vector<Double> dirvec = md.getAngle(Unit(String("rad"))).getValue();
    418   os << "[LO1 settings]" << LogIO::POST;
    419   os << "- Frequency: " << lo1Freq_ << " [Hz] ("
    420      << MFrequency::showType(loFrame_) << ")" << LogIO::POST;
    421   os << "- Reference time: " << me.get(Unit(String("d"))).getValue()
    422      << " [day]" << LogIO::POST;
    423   os << "- Reference direction: [" << dirvec[0] << ", " << dirvec[1]
    424      << "] (" << md.getRefString() << ") " << LogIO::POST;
    425 
    426   //Print summary (signal)
    427   os << "[Signal side band]" << LogIO::POST;
    428   os << "- IFNO: " << imgTab_p->getIF(0) << " (FREQ_ID = " << freqid << ")"
    429      << LogIO::POST;
    430   os << "- Reference value: " << refval << " [Hz] ("
    431      << MFrequency::showType(tabframe) << ") = "
    432      << sigrefval << " [Hz] (" <<  MFrequency::showType(loFrame_)
    433      << ")" << LogIO::POST;
    434   os << "- Reference pixel: " << refpix  << LogIO::POST;
    435   os << "- Increment: " << increment << " [Hz]" << LogIO::POST;
     1169  // Print summary
     1170  {
     1171    // LO1
     1172    Vector<Double> dirvec = md.getAngle(Unit(String("rad"))).getValue();
     1173    os << "[LO1 settings]" << LogIO::POST;
     1174    os << "- Frequency: " << lo1Freq_ << " [Hz] ("
     1175       << MFrequency::showType(loFrame_) << ")" << LogIO::POST;
     1176    os << "- Reference time: " << me.get(Unit(String("d"))).getValue()
     1177       << " [day]" << LogIO::POST;
     1178    os << "- Reference direction: [" << dirvec[0] << ", " << dirvec[1]
     1179       << "] (" << md.getRefString() << ") " << LogIO::POST;
     1180
     1181    // signal sideband
     1182    os << "[Signal side band]" << LogIO::POST;
     1183    os << "- IFNO: " << imgTab_p->getIF(0) << " (FREQ_ID = " << freqid << ")"
     1184       << LogIO::POST;
     1185    os << "- Reference value: " << refval << " [Hz] ("
     1186       << MFrequency::showType(tabframe) << ") = "
     1187       << sigrefval << " [Hz] (" <<  MFrequency::showType(loFrame_)
     1188       << ")" << LogIO::POST;
     1189    os << "- Reference pixel: " << refpix  << LogIO::POST;
     1190    os << "- Increment: " << increment << " [Hz]" << LogIO::POST;
     1191  }
    4361192
    4371193  // Calculate image band incr and refval in loFrame_
     
    4471203  freqIdVec = fIDnew;
    4481204
    449   // Print summary (Image side band)
    450   os << "[Image side band]" << LogIO::POST;
    451   os << "- IFNO: " << imgTab_p->getIF(0) << " (FREQ_ID = " << freqIdVec(0)
    452      << ")" << LogIO::POST;
    453   os << "- Reference value: " << imgrefval << " [Hz] ("
    454      << MFrequency::showType(tabframe) << ") = "
    455      << imgrefval_tab << " [Hz] (" <<  MFrequency::showType(loFrame_)
    456      << ")" << LogIO::POST;
    457   os << "- Reference pixel: " << refpix  << LogIO::POST;
    458   os << "- Increment: " << imgincr << " [Hz]" << LogIO::POST;
     1205  // Print summary (Image sideband)
     1206  {
     1207    os << "[Image side band]" << LogIO::POST;
     1208    os << "- IFNO: " << imgTab_p->getIF(0) << " (FREQ_ID = " << freqIdVec(0)
     1209       << ")" << LogIO::POST;
     1210    os << "- Reference value: " << imgrefval << " [Hz] ("
     1211       << MFrequency::showType(tabframe) << ") = "
     1212       << imgrefval_tab << " [Hz] (" <<  MFrequency::showType(loFrame_)
     1213       << ")" << LogIO::POST;
     1214    os << "- Reference pixel: " << refpix  << LogIO::POST;
     1215    os << "- Increment: " << imgincr << " [Hz]" << LogIO::POST;
     1216  }
    4591217};
    4601218
     
    6191377};
    6201378
    621 // String STSideBandSep::()
    622 // {
    623 
    624 // };
    625 
    6261379} //namespace asap
  • trunk/src/STSideBandSep.h

    r2726 r2794  
    2222#include <coordinates/Coordinates/DirectionCoordinate.h>
    2323#include <coordinates/Coordinates/SpectralCoordinate.h>
     24#include <scimath/Mathematics/FFTServer.h>
    2425// asap
    2526#include "ScantableWrapper.h"
     
    4041  explicit STSideBandSep(const vector<ScantableWrapper> &tables);
    4142  virtual ~STSideBandSep();
     43
     44  ///////////// temp functions //////////////////////
     45  //void cpprfft(std::vector<float> invec);
     46  //////////////////////////////////////////////////
     47
     48  /**
     49   * Separate side bands
     50   **/
     51  void separate(string outname);
    4252
    4353  /**
     
    8393   * Set additional information to fill frequencies of image sideband
    8494   **/
    85   void setLO1(const double lo1, const string frame="TOPO",
     95  void setLO1(const string lo1, const string frame="TOPO",
    8696              const double reftime=-1, string refdir="");
    8797  void setLO1Root(const string name);
    88 
    89   /**
    90    * Actual calculation of frequencies of image sideband
    91    **/
    92   void solveImageFreqency();
    9398
    9499private:
     
    99104  /** Return if the path exists (optionally, check file type) **/
    100105  Bool checkFile(const string name, string type="");
     106
     107  /** **/
     108  unsigned int setupShift();
     109  bool getFreqInfo(const CountedPtr<Scantable> &stab, const unsigned int &ifno,
     110                   double &freq0, double &incr, unsigned int &nchan);
     111
     112  /** Grid scantable **/
     113  ScantableWrapper gridTable();
     114  void mapExtent(vector< CountedPtr<Scantable> > &tablist,
     115                 Double &xmin, Double &xmax,
     116                 Double &ymin, Double &ymax);
     117
     118  /**
     119   * Actual calculation of frequencies of image sideband
     120   **/
     121  void solveImageFrequency();
    101122
    102123  /**
     
    112133                         const double refval, const double refpix,
    113134                         const double increment, const int nChan);
     135  bool getSpectraToSolve(const int polId, const int beamId,
     136                         const double dirX, const double dirY,
     137                         Matrix<float> &specmat, vector<uInt> &tabIdvec);
     138
     139  vector<float> solve(const Matrix<float> &specmat,
     140                      const vector<uInt> &tabIdvec,
     141                      const bool signal = true);
     142
     143  void shiftSpectrum(const Vector<float> &invec, double shift,
     144                     Vector<float> &outvec);
     145
     146  void deconvolve(Matrix<float> &specmat, const vector<double> shiftvec,
     147                  const double threshold, Matrix<float> &outmat);
     148
     149  void aggregateMat(Matrix<float> &inmat, vector<float> &outvec);
     150
     151  void subtractFromOther(const Matrix<float> &shiftmat,
     152                         const vector<float> &invec,
     153                         const vector<double> &shift,
     154                         vector<float> &outvec);
     155
     156
    114157
    115158  /** Member variables **/
     
    119162  unsigned int ntable_;
    120163  // frequency and direction setup to select data.
    121   unsigned int sigIfno_;
     164  int sigIfno_;
    122165  Quantum<Double> ftol_;
    123166  MFrequency::Types solFrame_;
     
    130173  double rejlimit_;
    131174  // LO1
    132   double lo1Freq_;
     175  double lo1Freq_; // in Hz
    133176  MFrequency::Types loFrame_;
    134177  double loTime_;
     
    136179  string asdmName_, asisName_;
    137180
     181  //CountedPtr<Scantable> imgTab_p, sigTab_p;
    138182  CountedPtr<Scantable> imgTab_p, sigTab_p;
     183  Table::TableType tp_;
     184  FFTServer<Float, Complex> fftsf, fftsi;
    139185  // TEMPORAL member
    140186  CountedPtr<Scantable> st0_;
  • trunk/src/python_STSideBandSep.cpp

    r2726 r2794  
    3434           boost::python::arg("refdir")="") )
    3535    .def( "set_lo1root", &STSideBandSep::setLO1Root )
    36     // temporal methods
    37     .def( "set_imgtable", &STSideBandSep::setImageTable )
    38     .def( "solve_imgfreq", &STSideBandSep::solveImageFreqency )
    39     .def( "_get_asistb_from_scantb", &STSideBandSep::setScanTb0 )
     36    .def( "separate", &STSideBandSep::separate )
     37    //// temporal methods
     38    //.def( "_cpprfft", &STSideBandSep::cpprfft )
     39    //.def( "solve_imgfreq", &STSideBandSep::solveImageFreqency )
     40    //.def( "_get_asistb_from_scantb", &STSideBandSep::setScanTb0 )
    4041  ;
    4142};
Note: See TracChangeset for help on using the changeset viewer.