//# VisBuffGroupAcc.cc: Implementation of VisBuffGroupAcc.h //# Copyright (C) 2008 //# Associated Universities, Inc. Washington DC, USA. //# //# This library is free software; you can redistribute it and/or modify it //# under the terms of the GNU Library General Public License as published by //# the Free Software Foundation; either version 2 of the License, or (at your //# option) any later version. //# //# This library is distributed in the hope that it will be useful, but WITHOUT //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public //# License for more details. //# //# You should have received a copy of the GNU Library General Public License //# along with this library; if not, write to the Free Software Foundation, //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. //# //# Correspondence concerning AIPS++ should be addressed as follows: //# Internet email: aips2-request@nrao.edu. //# Postal address: AIPS++ Project Office //# National Radio Astronomy Observatory //# 520 Edgemont Road //# Charlottesville, VA 22903-2475 USA //# //# $Id: VisBuffAccumulator.cc,v 19.7 2006/01/17 08:22:27 gvandiep Exp $ //---------------------------------------------------------------------------- #include <msvis/MSVis/VisBuffGroupAcc.h> #include <casacore/ms/MeasurementSets/MSColumns.h> #include <casacore/ms/MSSel/MSSelection.h> #include <casacore/casa/Exceptions/Error.h> using namespace casacore; namespace casa { //# NAMESPACE CASA - BEGIN //---------------------------------------------------------------------------- VisBuffGroupAcc::VisBuffGroupAcc(const Int& nAnt, const Int& nSpw, const Int& nFld, const Double& subinterval, const Bool fillModel) : nAnt_p(nAnt), nSpw_p(nSpw), nFld_p(nFld), nBuf_p(0), subinterval_p(subinterval), fillModel_p(fillModel), prenorm_p(false), globalTimeStamp_p(0.0), VBA_p(), spwfldids_p(nSpw,nFld,-1), tvi_debug(False) { // Interval MUST be strictly greater than zero if (subinterval_p < DBL_EPSILON) subinterval_p=0.1; // TBD: is this reasonable? // NB: Enforcing no prenormalization here, for now } //---------------------------------------------------------------------------- VisBuffGroupAcc::~VisBuffGroupAcc() { // Null default destructor // // Delete all VBAs. // TBD: encapsulate this for more general use? for (Int i=0;i<nBuf_p;++i) if (VBA_p[i]) delete VBA_p[i]; VBA_p.resize(0); } void VisBuffGroupAcc::clearChanMask(std::map<Int, Vector<Bool>*>& chanmask) { for(std::map<Int, Vector<Bool>*>::iterator it = chanmask.begin(); it != chanmask.end(); ++it) if(it->second) delete it->second; chanmask.clear(); } Bool VisBuffGroupAcc::fillChanMask(std::map<Int, Vector<Bool>*>& chanmask, const String& spwstr, const MeasurementSet& ms) { clearChanMask(chanmask); MSSelection mssel; mssel.setSpwExpr(spwstr != "" ? spwstr : "*"); Matrix<Int> chansel = mssel.getChanList(&ms, 1); uInt nranges = chansel.nrow(); Bool didSel = nranges > 0; if(didSel){ MSSpWindowColumns spwCols(ms.spectralWindow()); Vector<Int> nChan0 = spwCols.numChan().getColumn(); Vector<Int> uspw(chansel.column(0)); Vector<Int> ustart(chansel.column(1)); Vector<Int> uend(chansel.column(2)); Vector<Int> ustep(chansel.column(3)); for(uInt rangenum = 0; rangenum < nranges; ++rangenum){ Int spw = uspw[rangenum]; // Initialize this spw mask, if necessary (def = masked) if(chanmask.count(spw) < 1) chanmask[spw] = new Vector<Bool>(nChan0[spw], true); Int unchan = uend[rangenum] - ustart[rangenum] + 1; // Update the mask (false = selected) (*chanmask[spw])(Slice(ustart[rangenum], unchan, ustep[rangenum])) = false; } // rangenum } // non-triv spw selection return didSel; } uInt VisBuffGroupAcc::applyChanMask(std::map<Int, Vector<Bool>*>& chanmask) { uInt naffected = 0; for(Int i = 0; i < nBuf_p; ++i){ Int spw = VBA_p[i]->aveCalVisBuff().spectralWindow(); if(chanmask.count(spw) > 0){ Int chan0 = VBA_p[i]->aveCalVisBuff().channel()(0); Int nchan = VBA_p[i]->aveCalVisBuff().nChannel(); if(sum((*(chanmask[spw]))(Slice(chan0, nchan))) > 0){ // There are some channels to mask... Vector<Bool> fr(VBA_p[i]->aveCalVisBuff().flagRow()); Matrix<Bool> f(VBA_p[i]->aveCalVisBuff().flag()); Vector<Bool> fc; Vector<Bool> chm((*(chanmask[spw]))(Slice(chan0, nchan))); uInt nr = VBA_p[i]->aveCalVisBuff().nRow(); for(uInt irow = 0; irow < nr; ++irow){ if(!fr(irow)){ fc.reference(f.column(irow)); fc = fc || chm; } } ++naffected; } } } return naffected; } //---------------------------------------------------------------------------- void VisBuffGroupAcc::accumulate (const VisBuffer& vb) { Int spw = vb.spectralWindow(); Int fld = vb.fieldId(); Int ibuf = spwfldids_p(spw, fld); // Create the new VisBuffAccumulator, if needed if (ibuf<0) { ibuf=nBuf_p; ++nBuf_p; VBA_p.resize(nBuf_p, false, true); spwfldids_p(spw, fld) = ibuf; VBA_p[ibuf] = new VisBuffAccumulator(nAnt_p, subinterval_p, prenorm_p, fillModel_p); VBA_p[ibuf]->setTVIDebug(tvi_debug); } // ibuf should be non-negative now if(ibuf < 0) throw(AipsError("VisBuffGroupAcc: VisBuffAccumulator index failure.")); // Accumulate the vb into the correct accumulator VBA_p[ibuf]->accumulate(vb); } //---------------------------------------------------------------------------- void VisBuffGroupAcc::finalizeAverage() { globalTimeStamp_p=0.0; Double globalTimeStampWt(0.0); Double t0(-1.0); // avoid round-off problems in time average for (Int ibuf=0;ibuf<nBuf_p;++ibuf) { // tell a VBA to finalize itself VBA_p[ibuf]->finalizeAverage(); // Accumulate weighted timestamps Double& thistimewt(VBA_p[ibuf]->timeStampWt()); if (thistimewt>0.0) { globalTimeStampWt+=(thistimewt); Double& thistime(VBA_p[ibuf]->timeStamp()); if (t0<0.0) t0=thistime; else globalTimeStamp_p+=(thistimewt*(thistime-t0)); } } // Form global timestamp if (globalTimeStampWt>0.0) globalTimeStamp_p/=globalTimeStampWt; // Add offset back in! globalTimeStamp_p+=t0; // NB: the per-VBA timestamp weights are approximately (exactly?) // the relative weights of the _data_ going into the solution. // This could be a useful log message?.... }; void VisBuffGroupAcc::enforceAPonData(const String& apmode) { // Delegate to each CalVisBuffer in turn for (Int ibuf=0;ibuf<nBuf_p;++ibuf) if (VBA_p[ibuf]) this->operator()(ibuf).enforceAPonData(apmode); } void VisBuffGroupAcc::enforceSolveCorrWeights(const Bool phandonly) { // If requested set cross-hand weights to zero (if they exist): if(phandonly) for(Int ibuf = 0; ibuf < nBuf_p; ++ibuf) if (VBA_p[ibuf]) { CalVisBuffer& cvb(this->operator()(ibuf)); if (cvb.nCorr() > 2) cvb.weightMat()(Slice(1, 2, 1), Slice()).set(0.0); } } CalVisBuffer& VisBuffGroupAcc::operator()(const Int& buf) { if (buf > -1 && buf < nBuf_p) return VBA_p[buf]->aveCalVisBuff(); else throw(AipsError("VisBuffGroupAcc: operator(buf) index out-of-range.")); } CalVisBuffer& VisBuffGroupAcc::operator()(const Int& spw,const Int& fld) { if (spw>-1 && fld > -1 && spwfldids_p(spw,fld) > 0) return this->operator()(spwfldids_p(spw,fld)); else throw(AipsError("VisBuffGroupAcc: operator(spw,fld) index out-of-range.")); } const Vector<Int>& VisBuffGroupAcc::outToInRow(const Int buf, const Bool hurl) const { if(buf > -1 && buf < nBuf_p) return VBA_p[buf]->outToInRow(hurl); else throw(AipsError("VisBuffGroupAcc outToInRow: buf index out of range.")); } const Vector<Int>& VisBuffGroupAcc::outToInRow(const Int spw, const Int fld, const Bool hurl) const { if(spw > -1 && fld > -1 && spwfldids_p(spw, fld) > 0) return outToInRow(spwfldids_p(spw, fld), hurl); else throw(AipsError( "VisBuffGroupAcc outToInRow: (spw, fld) index out of range.")); } void VisBuffGroupAcc::reportData() { cout << "nBuf=" << nBuf_p << endl; for(Int ibuf = 0; ibuf < nBuf_p; ++ibuf) { cout << "iBuf=" << ibuf << endl; if (VBA_p[ibuf]) VBA_p[ibuf]->reportData(); } } } //# NAMESPACE CASA - END