//# VisSetUtil.cc: VisSet Utilities //# Copyright (C) 1996,1997,1998,1999,2001,2002 //# 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 adressed 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$ #include <casacore/casa/aips.h> #include <casacore/casa/Arrays/Matrix.h> #include <casacore/casa/Arrays/MatrixMath.h> #include <casacore/casa/Arrays/ArrayMath.h> #include <casacore/casa/Arrays/Cube.h> #include <casacore/casa/BasicMath/Math.h> #include <casacore/casa/BasicSL/Complex.h> #include <casacore/casa/BasicSL/Constants.h> #include <casacore/casa/Utilities/Assert.h> #include <casacore/tables/Tables/ArrColDesc.h> #include <casacore/tables/Tables/ScaColDesc.h> #include <casacore/tables/Tables/TableCopy.h> #include <casacore/tables/DataMan/TiledDataStMan.h> #include <casacore/tables/DataMan/TiledShapeStMan.h> #include <casacore/tables/DataMan/StandardStMan.h> #include <casacore/tables/DataMan/TiledDataStManAccessor.h> #include <casacore/tables/DataMan/CompressComplex.h> #include <casacore/tables/DataMan/CompressFloat.h> #include <casacore/ms/MeasurementSets/MSColumns.h> #include <msvis/MSVis/VisModelDataI.h> #include <msvis/MSVis/VisSet.h> #include <msvis/MSVis/VisBuffer.h> #include <msvis/MSVis/VisSetUtil.h> #include <casacore/casa/Quanta/UnitMap.h> #include <casacore/casa/Quanta/UnitVal.h> #include <casacore/measures/Measures/Stokes.h> #include <casacore/casa/Quanta/MVAngle.h> #include <casacore/casa/Logging/LogIO.h> #include <iostream> using std::vector; using std::pair; using namespace casacore; namespace casa { //# NAMESPACE CASA - BEGIN // <summary> // </summary> // <reviewed reviewer="" date="" tests="tMEGI" demos=""> // <prerequisite> // </prerequisite> // // <etymology> // </etymology> // // <synopsis> // </synopsis> // // <example> // <srcblock> // </srcblock> // </example> // // <motivation> // </motivation> // // <todo asof=""> // </todo> // Calculate sensitivity void VisSetUtil::Sensitivity(VisSet &vs, Matrix<Double>& mssFreqSel, Matrix<Int>& mssChanSel, Quantity& pointsourcesens, Double& relativesens, Double& sumwt, Double& effectiveBandwidth, Double& effectiveIntegration, Int& nBaselines, Vector<Vector<Int> >& nData, Vector<Vector<Double> >& sumwtChan, Vector<Vector<Double> >& sumwtsqChan, Vector<Vector<Double> >& sumInverseVarianceChan) { ROVisIter& vi(vs.iter()); VisSetUtil::Sensitivity(vi, mssFreqSel, mssChanSel, pointsourcesens, relativesens, sumwt, effectiveBandwidth, effectiveIntegration, nBaselines, nData, sumwtChan, sumwtsqChan, sumInverseVarianceChan); } void VisSetUtil::Sensitivity(ROVisIter &vi, Matrix<Double>& /*mssFreqSel*/, Matrix<Int>& mssChanSel, Quantity& pointsourcesens, Double& relativesens, Double& sumwt, Double& effectiveBandwidth, Double& effectiveIntegration, Int& nBaselines, Vector<Vector<Int> >& nData, Vector<Vector<Double> >& sumwtChan, Vector<Vector<Double> >& sumwtsqChan, Vector<Vector<Double> >& sumInverseVarianceChan) { LogIO os(LogOrigin("VisSetUtil", "Sensitivity()", WHERE)); sumwt=0.0; Vector<Double> timeInterval, chanWidth; Double sumwtsq=0.0; Double sumInverseVariance=0.0; // Vector<Vector<Double> > sumwtChan, sumwtsqChan, sumInverseVarianceChan; VisBuffer vb(vi); Int nd=0,totalRows=0,spw=0; nBaselines=0; effectiveBandwidth=effectiveIntegration=0.0; Vector<Double> bwList; bwList.resize(mssChanSel.shape()(0)); bwList=0.0; sumwtChan.resize(mssChanSel.shape()(0)); sumwtsqChan.resize(mssChanSel.shape()(0)); sumInverseVarianceChan.resize(mssChanSel.shape()(0)); nData.resize(mssChanSel.shape()(0)); for (spw=0; spw<mssChanSel.shape()(0); spw++) { Int nc=mssChanSel(spw,2)-mssChanSel(spw,1)+1; for (int c=0; c<nc; c++) { sumwtChan(spw).resize(nc); sumwtChan(spw)=0.0; sumwtsqChan(spw).resize(nc); sumwtsqChan(spw) = 0.0; sumInverseVarianceChan(spw).resize(nc); sumInverseVarianceChan(spw)=0.0; nData(spw).resize(nc); nData(spw)=0; } } // sumwtChan=0.0; // sumwtsqChan=0.0; // sumInverseVarianceChan=0.0; // Now iterate through the data Int nant=vi.msColumns().antenna().nrow(); Matrix<Int> baselines(nant,nant); baselines=0; Vector<Int> a1,a2; Vector<Double> t0, spwIntegTime; t0.resize(mssChanSel.shape()(0)); spwIntegTime.resize(mssChanSel.shape()(0)); t0 = spwIntegTime = 0.0; for (vi.originChunks();vi.moreChunks();vi.nextChunk()) { for (vi.origin();vi.more();vi++) { Int nRow=vb.nRow(); vb.nChannel(); Int spwIndex; spw=vb.spectralWindow(); spwIndex=-1; for (Int i=0;i<mssChanSel.shape()(0); i++) if (mssChanSel(i,0) == spw) {spwIndex=i; break;} if (spwIndex == -1) os << "Internal error: Could not locate the SPW index in the list of selected SPWs." << LogIO::EXCEPTION; timeInterval.assign(vb.timeInterval()); Vector<Bool> rowFlags=vb.flagRow(); Matrix<Bool> flag = vb.flag(); // cerr << "SPW shape = " << vb.msColumns().spectralWindow().chanWidth().shape(spw) << " "; chanWidth.assign(vb.msColumns().spectralWindow().chanWidth().get(spw)); a1.assign(vb.antenna1()); a2.assign(vb.antenna2()); for (Int row=0; row<nRow; row++) { // TBD: Should probably use weight() here, which updates with calibration if (!rowFlags(row)) { // Double variance=square(vb.sigma()(row)); Double variance=1.0/(vb.weight()(row)); if (abs(vb.time()(row) - t0(spwIndex)) > timeInterval(row)) { t0(spwIndex)=vb.time()(row); spwIntegTime(spwIndex) += timeInterval(row); } totalRows++; baselines(a1(row), a2(row))++; for (Int chn=mssChanSel(spwIndex,1); chn<mssChanSel(spwIndex,2); chn+=mssChanSel(spwIndex,3)) { if(!flag(chn,row)&&(variance>0.0)) { sumwt+=vb.imagingWeight()(chn,row)*variance; sumwtsq+=square(vb.imagingWeight()(chn,row)*variance); // sumwtsq+=square(vb.imagingWeight()(chn,row)); sumInverseVariance+=1.0/variance; sumwtChan(spwIndex)(chn) += vb.imagingWeight()(chn,row); //sumwtsqChan(spwIndex)(chn)+=square(vb.imagingWeight()(chn,row))*variance; sumwtsqChan(spwIndex)(chn)+=square(vb.imagingWeight()(chn,row)); bwList(spwIndex) += abs(chanWidth(chn)); (nData(spwIndex)(chn))++; nd++; } } } } } } if (totalRows == 0) os << "Cannot calculate sensitivty: No unflagged rows found" << LogIO::EXCEPTION; for (uInt spwndx=0; spwndx<bwList.nelements(); spwndx++) { // cerr << spwndx << " " << bwList(spwndx) << " " << nData(spwndx) << endl; // cerr << spwndx << " " << spwIntegTime(spwndx) << " " << endl; spw=mssChanSel(spwndx,0); // Get the SPW ID; chanWidth.assign(vi.msColumns().spectralWindow().chanWidth().get(spw)); // Extract the list of chan widths Int nchan=nData(spwndx).nelements(); // If a channel from the current SPW was used, uses its width // for effective bandwidth calculation. for (Int j=0; j<nchan; j++) if (nData(spwndx)(j) > 0) effectiveBandwidth += abs(chanWidth(j)); effectiveIntegration += spwIntegTime(spwndx)/bwList.nelements(); } for (Int i=0; i<nant; i++) for (Int j=0; j<nant; j++) if (baselines(i,j) > 0) nBaselines++; if(sumwt==0.0) { os << "Cannot calculate sensitivity: sum of weights is zero" << endl << "Perhaps you need to weight the data" << LogIO::EXCEPTION; } if(sumInverseVariance==0.0) { os << "Cannot calculate sensitivity: sum of inverse variances is zero" << endl << "Perhaps you need to weight the data" << LogIO::EXCEPTION; } // Double naturalsens=1.0/sqrt(sumInverseVariance); // pointsourcesens=Quantity(sqrt(sumwtsq)/sumwt, "Jy"); // relativesens=sqrt(sumwtsq)/sumwt/naturalsens; // cerr << "sumwt, sumwtsq, nd: " << sumwt << " " << sumwtsq << " " << nd << endl; relativesens=sqrt(nd*sumwtsq)/sumwt; //Double naturalsens=1.0/sqrt(sumInverseVariance); Double KB=1.3806488e-23; pointsourcesens=Quantity((10e26*2*KB*relativesens/sqrt(nBaselines*effectiveIntegration*effectiveBandwidth)), "Jy m^2/K"); // cerr << "Pt src. = " << pointsourcesens << " " << integTime << " " << bandWidth/totalRows << endl; // cerr << baselines << endl; } void VisSetUtil::HanningSmooth(VisSet &vs, const String& dataCol, const Bool& doFlagAndWeight) { VisIter& vi(vs.iter()); VisSetUtil::HanningSmooth(vi, dataCol, doFlagAndWeight); } void VisSetUtil::HanningSmooth(VisIter &vi, const String& dataCol, const Bool& doFlagAndWeight) { using casacore::operator*; LogIO os(LogOrigin("VisSetUtil", "HanningSmooth()")); VisBuffer vb(vi); Int row, chn, pol; for (vi.originChunks();vi.moreChunks();vi.nextChunk()) { if (vi.existsWeightSpectrum()) { for (vi.origin();vi.more();vi++) { Cube<Complex>& vc = ( dataCol=="data" ? vb.visCube() : vb.correctedVisCube()); Cube<Bool>& fc= vb.flagCube(); Cube<Float>& wc= vb.weightSpectrum(); Int nRow=vb.nRow(); Int nChan=vb.nChannel(); if (nChan < 3) break; Int nPol=vi.visibilityShape()(0); Cube<Complex> smoothedData(nPol,nChan,nRow); Cube<Bool> newFlag(nPol,nChan,nRow); Cube<Float> newWeight(nPol,nChan,nRow); for (row=0; row<nRow; row++) { for (pol=0; pol<nPol; pol++) { ///Handle first channel and flag it smoothedData(pol,0,row) = vc(pol,0,row)*0.5 + vc(pol,1,row)*0.5; newWeight(pol,0,row) = 0.0; newFlag(pol,0,row) = true; for (chn=1; chn<nChan-1; chn++) { smoothedData(pol,chn,row) = vc(pol,chn-1,row)*0.25 + vc(pol,chn,row)*0.50 + vc(pol,chn+1,row)*0.25; if (wc(pol,chn-1,row) != 0 && wc(pol,chn,row) != 0 && wc(pol,chn+1,row) != 0) { newWeight(pol,chn,row) = 1.0 / (1.0/(wc(pol,chn-1,row)*16.0) + 1.0/(wc(pol,chn,row)*4.0) + 1.0/(wc(pol,chn+1,row)*16.0)); } else { newWeight(pol,chn,row) = 0.0; } newFlag(pol,chn,row) = fc(pol,chn-1,row)||fc(pol,chn,row)||fc(pol,chn+1,row); } //Handle last channel and flag it smoothedData(pol,nChan-1,row) = vc(pol,nChan-2,row)*0.5+vc(pol,nChan-1,row)*0.5; newWeight(pol,nChan-1,row) = 0.0; newFlag(pol,nChan-1,row) = true; // flag last channel } } if(dataCol=="data"){ if(doFlagAndWeight){ vi.setVisAndFlag(smoothedData,newFlag,VisibilityIterator::Observed); vi.setWeightSpectrum(newWeight); } else{ vi.setVis(smoothedData,VisibilityIterator::Observed); } } else{ if(doFlagAndWeight){ vi.setVisAndFlag(smoothedData,newFlag,VisibilityIterator::Corrected); vi.setWeightSpectrum(newWeight); } else{ vi.setVis(smoothedData,VisibilityIterator::Corrected); } } } } else { for (vi.origin();vi.more();vi++) { Cube<Complex>& vc = (dataCol=="data" ? vb.visCube() : vb.correctedVisCube()); Cube<Bool>& fc= vb.flagCube(); Matrix<Float>& wm = vb.weightMat(); Int nRow=vb.nRow(); Int nChan=vb.nChannel(); if (nChan < 3) break; Int nPol=vi.visibilityShape()(0); Cube<Complex> smoothedData(nPol,nChan,nRow); Cube<Bool> newFlag(nPol,nChan,nRow); Matrix<Float> newWeight(nPol, nRow); for (row=0; row<nRow; row++) { for (pol=0; pol<nPol; pol++) { ///Handle first channel and flag it smoothedData(pol,0,row) = vc(pol,0,row)*0.5 + vc(pol,1,row)*0.5; newFlag(pol,0,row) = true; ///Handle chan-independent weights newWeight(pol, row) = 8.0*wm(pol, row)/3.0; for (chn=1; chn<nChan-1; chn++) { smoothedData(pol,chn,row) = vc(pol,chn-1,row)*0.25 + vc(pol,chn,row)*0.50 + vc(pol,chn+1,row)*0.25; newFlag(pol,chn,row) = fc(pol,chn-1,row)||fc(pol,chn,row)||fc(pol,chn+1,row); } //Handle last channel and flag it smoothedData(pol,nChan-1,row) = vc(pol,nChan-2,row)*0.5+vc(pol,nChan-1,row)*0.5; newFlag(pol,nChan-1,row) = true; // flag last channel } } if(dataCol=="data"){ if(doFlagAndWeight){ vi.setVisAndFlag(smoothedData,newFlag,VisibilityIterator::Observed); vi.setWeightMat(newWeight); } else{ vi.setVis(smoothedData,VisibilityIterator::Observed); } } else{ if(doFlagAndWeight){ vi.setVisAndFlag(smoothedData,newFlag,VisibilityIterator::Corrected); vi.setWeightMat(newWeight); } else{ vi.setVis(smoothedData,VisibilityIterator::Corrected); } } } } } } void VisSetUtil::addScrCols(MeasurementSet& ms, Bool addModel, Bool addCorr, Bool alsoinit, Bool compress) { // Add but DO NOT INITIALIZE calibration set (comprising a set of CORRECTED_DATA // and MODEL_DATA columns) to the MeasurementSet. // Sense if anything is to be done addModel=addModel && !(ms.tableDesc().isColumn("MODEL_DATA")); addCorr=addCorr && !(ms.tableDesc().isColumn("CORRECTED_DATA")); // Escape (silently) without doing anything if nothing // to be done if (!addModel && !addCorr) return; else { // Remove SORTED_TABLE and continue // This is needed because old SORTED_TABLE won't see // the added column(s) if (ms.keywordSet().isDefined("SORT_COLUMNS")) ms.rwKeywordSet().removeField("SORT_COLUMNS"); if (ms.keywordSet().isDefined("SORTED_TABLE")) ms.rwKeywordSet().removeField("SORTED_TABLE"); } // If we are adding the MODEL_DATA column, make it // the exclusive origin for model visibilities by // deleting any OTF model keywords if (addModel) VisSetUtil::remOTFModel(ms); // Form log message String addMessage("Adding "); if (addModel) { addMessage+="MODEL_DATA "; if (addCorr) addMessage+="and "; } if (addCorr) addMessage+="CORRECTED_DATA "; addMessage+="column(s)."; LogSink logSink; LogMessage message(addMessage,LogOrigin("VisSetUtil","addScrCols")); logSink.post(message); { // Define a column accessor to the observed data TableColumn* data; const bool data_is_float = ms.tableDesc().isColumn(MS::columnName(MS::FLOAT_DATA)); if (data_is_float) { data = new ArrayColumn<Float> (ms, MS::columnName(MS::FLOAT_DATA)); } else { data = new ArrayColumn<Complex> (ms, MS::columnName(MS::DATA)); }; // Check if the data column is tiled and, if so, the // smallest tile shape used. TableDesc td = ms.actualTableDesc(); const ColumnDesc& cdesc = td[data->columnDesc().name()]; String dataManType = cdesc.dataManagerType(); String dataManGroup = cdesc.dataManagerGroup(); IPosition dataTileShape; Bool tiled = (dataManType.contains("Tiled")); Bool simpleTiling = false; if (!tiled || !simpleTiling) { // Untiled, or tiled at a higher than expected dimensionality // Use a canonical tile shape of 1 MB size MSSpWindowColumns msspwcol(ms.spectralWindow()); Int maxNchan = max (msspwcol.numChan().getColumn()); Int tileSize = maxNchan/10 + 1; Int nCorr = data->shape(0)(0); dataTileShape = IPosition(3, nCorr, tileSize, 131072/nCorr/tileSize + 1); }; delete data; if(addModel){ // Add the MODEL_DATA column TableDesc tdModel, tdModelComp, tdModelScale; CompressComplex* ccModel=NULL; String colModel=MS::columnName(MS::MODEL_DATA); tdModel.addColumn(ArrayColumnDesc<Complex>(colModel,"model data", 2)); td.addColumn(ArrayColumnDesc<Complex>(colModel,"model data", 2)); IPosition modelTileShape = dataTileShape; if (compress) { tdModelComp.addColumn(ArrayColumnDesc<Int>(colModel+"_COMPRESSED", "model data compressed",2)); tdModelScale.addColumn(ScalarColumnDesc<Float>(colModel+"_SCALE")); tdModelScale.addColumn(ScalarColumnDesc<Float>(colModel+"_OFFSET")); ccModel = new CompressComplex(colModel, colModel+"_COMPRESSED", colModel+"_SCALE", colModel+"_OFFSET", true); StandardStMan modelScaleStMan("ModelScaleOffset"); ms.addColumn(tdModelScale, modelScaleStMan); TiledShapeStMan modelCompStMan("ModelCompTiled", modelTileShape); ms.addColumn(tdModelComp, modelCompStMan); ms.addColumn(tdModel, *ccModel); } else { // Make a clone of the appropriate data column. The clone can differ by // by having a different element datatype. try { String dataColumnName = data_is_float ? MS::columnName (MS::FLOAT_DATA) : MS::columnName (MS::DATA); TableCopy::cloneColumnTyped<Complex> (ms, dataColumnName, ms, MS::columnName(MS::MODEL_DATA), "TiledModel"); // Now fill the model column with complex zeroes. Using the function below // to do the filling preserves the tiling of the hypercubes making up // the column. The later call to initScrCols will set these appropriately // since depending on the way the correlations are represented, only one // of the correlations will be set to one. Unfortunately, this results in // two writes of the scratch column where one would do. TableCopy::fillColumnData (ms, MS::columnName (MS::MODEL_DATA), Complex (0.0, 0.0), ms, dataColumnName, true); // last arg preserves tile shape } catch (AipsError & e){ // Column cloning failed (presumably). Try it the old way. MeasurementSet::addColumnToDesc(tdModel, MeasurementSet::MODEL_DATA, 2); TiledShapeStMan modelStMan("ModelTiled", modelTileShape); ms.addColumn(tdModel, modelStMan); } } if (ccModel) delete ccModel; } if (addCorr) { // Add the CORRECTED_DATA column TableDesc tdCorr, tdCorrComp, tdCorrScale; CompressComplex* ccCorr=NULL; String colCorr=MS::columnName(MS::CORRECTED_DATA); tdCorr.addColumn(ArrayColumnDesc<Complex>(colCorr,"corrected data", 2)); IPosition corrTileShape = dataTileShape; if (compress) { tdCorrComp.addColumn(ArrayColumnDesc<Int>(colCorr+"_COMPRESSED", "corrected data compressed",2)); tdCorrScale.addColumn(ScalarColumnDesc<Float>(colCorr+"_SCALE")); tdCorrScale.addColumn(ScalarColumnDesc<Float>(colCorr+"_OFFSET")); ccCorr = new CompressComplex(colCorr, colCorr+"_COMPRESSED", colCorr+"_SCALE", colCorr+"_OFFSET", true); StandardStMan corrScaleStMan("CorrScaleOffset"); ms.addColumn(tdCorrScale, corrScaleStMan); TiledShapeStMan corrCompStMan("CorrectedCompTiled", corrTileShape); ms.addColumn(tdCorrComp, corrCompStMan); ms.addColumn(tdCorr, *ccCorr); } else { try { // Make a clone of the appropriate data column, except the new column // will have datatype complex. String dataColumnName = data_is_float ? MS::columnName (MS::FLOAT_DATA) : MS::columnName (MS::DATA); TableCopy::cloneColumnTyped<Complex> (ms, dataColumnName, ms, colCorr, "TiledCorrected"); // Copy the appropriate data column into the new one, preserving the tiling // of the column's hypercubes. TableCopy::copyColumnData (ms, dataColumnName, ms, colCorr, true); // last arg preserves tile shape addCorr = false; // We've already done the copying } catch (AipsError & e){ // Table clone failed (presumably): try it the old way TiledShapeStMan corrStMan("CorrectedTiled", corrTileShape); ms.addColumn(tdCorr, corrStMan); } // Copy the column keywords String dataColumnName = data_is_float ? MS::columnName (MS::FLOAT_DATA) : MS::columnName (MS::DATA); const TableRecord& dataColKeyWord = ms.tableDesc().columnDesc(dataColumnName).keywordSet(); if (dataColKeyWord.nfields() > 0) { LogMessage message("Start copying column keyword(s) of "+colCorr+" from "+dataColumnName,LogOrigin("VisSetUtil","addScrCols")); logSink.post(message); ArrayColumn<Complex> corrCol(ms, colCorr); TableRecord &corrColKeyWord = corrCol.rwKeywordSet(); if (corrColKeyWord.nfields()==0) { corrColKeyWord.assign(dataColKeyWord); } else { corrColKeyWord.merge(dataColKeyWord, RecordInterface::OverwriteDuplicates); } } } if (ccCorr) delete ccCorr; } ms.flush(); } if (alsoinit) // Initialize only what we added VisSetUtil::initScrCols(ms,addModel,addCorr); return; } void VisSetUtil::remScrCols(MeasurementSet& ms, Bool remModel, Bool remCorr) { Vector<String> colNames(2); colNames(0)=MS::columnName(MS::MODEL_DATA); colNames(1)=MS::columnName(MS::CORRECTED_DATA); Vector<Bool> doCol(2); doCol(0)=remModel; doCol(1)=remCorr; for (uInt j=0; j<colNames.nelements(); j++) { if (doCol(j)) { if (ms.tableDesc().isColumn(colNames(j))) { ms.removeColumn(colNames(j)); }; if (ms.tableDesc().isColumn(colNames(j)+"_COMPRESSED")) { ms.removeColumn(colNames(j)+"_COMPRESSED"); }; if (ms.tableDesc().isColumn(colNames(j)+"_SCALE")) { ms.removeColumn(colNames(j)+"_SCALE"); }; if (ms.tableDesc().isColumn(colNames(j)+"_OFFSET")) { ms.removeColumn(colNames(j)+"_OFFSET"); }; }; }; } void VisSetUtil::remOTFModel(MeasurementSet& ms) { CountedPtr<VisModelDataI> visModelData = VisModelDataI::create(); visModelData->clearModelI(ms); } void VisSetUtil::initScrCols(MeasurementSet& ms, Bool initModel, Bool initCorr) { // Sense if anything is to be done (relevant scr cols must be present) initModel=initModel && ms.tableDesc().isColumn("MODEL_DATA"); initCorr=initCorr && ms.tableDesc().isColumn("CORRECTED_DATA"); // Do nothing? if (!initModel && !initCorr) return; /* Reconsider this trap? // Trap missing columns: if (initModel && !ms.tableDesc().isColumn("MODEL_DATA")) throw(AipsError("Cannot initialize MODEL_DATA if column is absent.")); if (initCorr && !ms.tableDesc().isColumn("CORRECTED_DATA")) throw(AipsError("Cannot initialize CORRECTED_DATA if column is absent.")); */ // Create ordinary (un-row-selected) VisibilityIterator from the MS VisibilityIterator vi(ms,Block<Int>(),0.0); // Pass to VisibilityIterator-oriented method VisSetUtil::initScrCols(vi,initModel,initCorr); } void VisSetUtil::initScrCols(VisibilityIterator& vi, Bool initModel, Bool initCorr) { // Sense if anything is to be done (relevant scr cols must be present) initModel=initModel && vi.ms().tableDesc().isColumn("MODEL_DATA"); initCorr=initCorr && vi.ms().tableDesc().isColumn("CORRECTED_DATA"); // Do nothing? if (!initModel && !initCorr) return; /* Reconsider this trap? // Trap missing columns: if (initModel && !vi.ms().tableDesc().isColumn("MODEL_DATA")) throw(AipsError("Cannot initialize MODEL_DATA if column is absent.")); if (initCorr && !vi.ms().tableDesc().isColumn("CORRECTED_DATA")) throw(AipsError("Cannot initialize CORRECTED_DATA if column is absent.")); */ // Form log message String initMessage("Initializing "); if (initModel) { initMessage+="MODEL_DATA to (unity)"; if (initCorr) initMessage+=" and "; } if (initCorr) initMessage+="CORRECTED_DATA (to DATA)"; initMessage+="."; LogSink logSink; LogMessage message(initMessage,LogOrigin("VisSetUtil","initScrCols")); logSink.post(message); Vector<Int> lastCorrType; Vector<Bool> zero; Int nRows(0); vi.setRowBlocking(10000); for (vi.originChunks(); vi.moreChunks(); vi.nextChunk()) { Vector<Int> corrType; vi.corrType(corrType); uInt nCorr = corrType.nelements(); if (initModel) { // figure out which correlations to set to 1. and 0. for the model. if (nCorr != lastCorrType.nelements() || !allEQ(corrType, lastCorrType)) { lastCorrType.resize(nCorr); lastCorrType=corrType; zero.resize(nCorr); for (uInt i=0; i<nCorr; i++) { zero[i]=(corrType[i]==Stokes::RL || corrType[i]==Stokes::LR || corrType[i]==Stokes::XY || corrType[i]==Stokes::YX); } } } for (vi.origin(); vi.more(); vi++) { nRows+=vi.nRow(); Cube<Complex> data; vi.visibility(data, VisibilityIterator::Observed); if (initCorr) { // Read DATA and set CORRECTED_DATA vi.setVis(data,VisibilityIterator::Corrected); } if (initModel) { // Set MODEL_DATA data.set(1.0); if (ntrue(zero)>0) { for (uInt i=0; i < nCorr; i++) { if (zero[i]) data(Slice(i), Slice(), Slice()) = Complex(0.0,0.0); } } vi.setVis(data,VisibilityIterator::Model); } } } vi.ms().relinquishAutoLocks(); vi.originChunks(); vi.setRowBlocking(0); ostringstream os; os << "Initialized " << nRows << " rows."; message.message(os.str()); logSink.post(message); } void VisSetUtil::removeCalSet(MeasurementSet& ms, Bool removeModel) { // Remove an existing calibration set (comprising a set of CORRECTED_DATA // and MODEL_DATA columns) from the MeasurementSet. //Remove model in header if(removeModel) VisSetUtil::remOTFModel(ms); VisSetUtil::remScrCols(ms,true,true); } void VisSetUtil::UVSub(VisSet &vs, Bool reverse) { VisIter& vi(vs.iter()); VisSetUtil::UVSub(vi, reverse); } void VisSetUtil::UVSub(VisIter &vi, Bool reverse) { LogIO os(LogOrigin("VisSetUtil", "UVSub()")); VisBuffer vb(vi); Int row, chn, pol; for (vi.originChunks();vi.moreChunks();vi.nextChunk()) { for (vi.origin();vi.more();vi++) { Cube<Complex>& vc= vb.correctedVisCube(); Cube<Complex>& mc= vb.modelVisCube(); Int nRow=vb.nRow(); Int nChan=vb.nChannel(); Int nPol=vi.visibilityShape()(0); Cube<Complex> residualData(nPol,nChan,nRow); if (reverse) { for (row=0; row<nRow; row++) { for (pol=0; pol<nPol; pol++) { for (chn=0; chn<nChan; chn++) { residualData(pol,chn,row) = vc(pol,chn,row)+mc(pol,chn ,row); } } } } else { for (row=0; row<nRow; row++) { for (pol=0; pol<nPol; pol++) { for (chn=0; chn<nChan; chn++) { residualData(pol,chn,row) = vc(pol,chn,row)-mc(pol,chn ,row); } } } } vi.setVis(residualData,VisibilityIterator::Corrected); } } } } //# NAMESPACE CASA - END