diff --git a/CEP/DP3/DPPP/include/DPPP/DPBuffer.h b/CEP/DP3/DPPP/include/DPPP/DPBuffer.h index df9d330b52f11f6fa16ecc201d9b9a71f7ccb25f..d8c3a1cd870388ed5b0ba4c7cfa010bb3b357c0d 100644 --- a/CEP/DP3/DPPP/include/DPPP/DPBuffer.h +++ b/CEP/DP3/DPPP/include/DPPP/DPBuffer.h @@ -165,7 +165,7 @@ namespace LOFAR { { return itsTime; } // Get or set the row numbers used by the DPInput class. - // It can be empty (e.g. when MSReader inserted an dummy time slot). + // It can be empty (e.g. when MSReader inserted a dummy time slot). void setRowNrs (const casa::Vector<uint>& rownrs) { itsRowNrs.reference (rownrs); } const casa::Vector<uint>& getRowNrs() const diff --git a/CEP/DP3/DPPP/include/DPPP/DPInput.h b/CEP/DP3/DPPP/include/DPPP/DPInput.h index c40f49b148c52e9f599590c9098b94c3108fc05c..58e4f816b28e269593d820cf95e585b3c8007604 100644 --- a/CEP/DP3/DPPP/include/DPPP/DPInput.h +++ b/CEP/DP3/DPPP/include/DPPP/DPInput.h @@ -98,6 +98,10 @@ namespace LOFAR { const casa::Vector<int>& getAnt2() const { return itsAnt2; } + // Get the baseline table index of the autocorrelations. + // A negative value means there are no autocorrelations for that antenna. + const vector<int>& getAutoCorrIndex() const; + // Get the lengths of the baselines (in meters). const vector<double>& getBaselineLengths() const; @@ -153,14 +157,16 @@ namespace LOFAR { uint itsNrChan; uint itsNrCorr; uint itsNrBl; - casa::Vector<int> itsAnt1; //# ant1 of all baselines - casa::Vector<int> itsAnt2; //# ant2 of all baselines - mutable vector<double> itsBLength; //# baseline lengths + casa::Vector<casa::Int> itsAnt1; //# ant1 of all baselines + casa::Vector<casa::Int> itsAnt2; //# ant2 of all baselines + mutable vector<double> itsBLength; //# baseline lengths + mutable vector<int> itsAutoCorrIndex; //# autocorr index per ant casa::Vector<casa::String> itsAntNames; vector<casa::MPosition> itsAntPos; casa::MPosition itsArrayPos; casa::MDirection itsPhaseCenter; casa::Vector<double> itsChanFreqs; + casa::Vector<double> itsChanWidths; }; } //# end namespace diff --git a/CEP/DP3/DPPP/include/DPPP/MSReader.h b/CEP/DP3/DPPP/include/DPPP/MSReader.h index ad1bf4c58ed9c0dc54da77fa7b62d0bbf099b9a3..513f5a0c91b463a8c0b4afcb55209d47fb5dd488 100644 --- a/CEP/DP3/DPPP/include/DPPP/MSReader.h +++ b/CEP/DP3/DPPP/include/DPPP/MSReader.h @@ -52,6 +52,7 @@ namespace LOFAR { // Currently the following can be given: // <ul> // <li> msin: name of the MS + // <li> msin.autoweight: calculate weights from autocorrelations? [no] // <li> msin.startchan: first channel to use [0] // <li> msin.nchan: number of channels to use [all] // <li> msin.useflag: use the existing flags? [yes] @@ -101,6 +102,8 @@ namespace LOFAR { // WEIGHT_SPECTRUM is used if present and containing valid data, // otherwise column WEIGHT is used. The weights of an inserted // time slot are set to 0. + // If autoweight is on, the autocorrelations are used to + // calculate proper weights. // </td> // </tr> // <tr> @@ -211,10 +214,14 @@ namespace LOFAR { // Calculate the UVWs for a missing time slot. void calcUVW(); + // Calculate the weights from the autocorrelations. + void autoWeight (casa::Cube<float>& weights); + //# Data members. casa::Table itsMS; casa::TableIterator itsIter; casa::String itsDataColName; + bool itsAutoWeight; //# calculate weights from autocorr? bool itsHasWeightSpectrum; bool itsUseFlags; bool itsUseAllChan; //# all channels (i.e. no slicer)? diff --git a/CEP/DP3/DPPP/src/Averager.cc b/CEP/DP3/DPPP/src/Averager.cc index d639fd8f7cdd0df68a36e688e238cc3f1b7962c0..1dba3f824238fff0c6288876c7b7426f1e3fc006 100644 --- a/CEP/DP3/DPPP/src/Averager.cc +++ b/CEP/DP3/DPPP/src/Averager.cc @@ -213,7 +213,7 @@ namespace LOFAR { float sumw=0; uint np = 0; for (uint j=0; j<nch; ++j) { - sumd += indata[inxi]; + sumd += indata[inxi]; // Note: weight is accounted for in process sumw += inwght[inxi]; np += innp[inxi]; inxi += ncorr; diff --git a/CEP/DP3/DPPP/src/DPInput.cc b/CEP/DP3/DPPP/src/DPInput.cc index a3e673f721e89bd83c9750151f1ccbcd71a08564..d01bb472847dd14d59e22521f60b377601879eb4 100644 --- a/CEP/DP3/DPPP/src/DPInput.cc +++ b/CEP/DP3/DPPP/src/DPInput.cc @@ -78,6 +78,22 @@ namespace LOFAR { return itsBLength; } + const vector<int>& DPInput::getAutoCorrIndex() const + { + if (itsAutoCorrIndex.empty()) { + int nant = 1 + std::max(max(itsAnt1), max(itsAnt2)); + itsAutoCorrIndex.resize (nant); + std::fill (itsAutoCorrIndex.begin(), itsAutoCorrIndex.end(), -1); + // Keep the baseline table index for the autocorrelations. + for (uint i=0; i<itsAnt1.size(); ++i) { + if (itsAnt1[i] == itsAnt2[i]) { + itsAutoCorrIndex[itsAnt1[i]] = i; + } + } + } + return itsAutoCorrIndex; + } + Cube<bool> DPInput::fetchFullResFlags (const DPBuffer& buf, const RefRows& rowNrs, bool merge) diff --git a/CEP/DP3/DPPP/src/MSReader.cc b/CEP/DP3/DPPP/src/MSReader.cc index a319dd17596af11da5d1eddf12bd0d8d2c83c963..d7e3235f581a75a4d58c40e9e37b867a16a9b3bc 100644 --- a/CEP/DP3/DPPP/src/MSReader.cc +++ b/CEP/DP3/DPPP/src/MSReader.cc @@ -58,6 +58,7 @@ namespace LOFAR { string endTimeStr = parset.getString (prefix+"endtime", ""); itsUseFlags = parset.getBool (prefix+"useflag", true); itsDataColName = parset.getString (prefix+"datacolumn", "DATA"); + itsAutoWeight = parset.getBool (prefix+"autoweight", False); // Prepare the MS access and get time info. double startTime, endTime; prepare (startTime, endTime, itsInterval); @@ -262,6 +263,7 @@ namespace LOFAR { os << " ntimes: " << itsMS.nrow() / itsNrBl << std::endl; os << " time interval: " << itsInterval << std::endl; os << " DATA column: " << itsDataColName << std::endl; + os << " autoweight: " << itsAutoWeight << std::endl; } void MSReader::showCounts (std::ostream& os) const @@ -342,8 +344,8 @@ namespace LOFAR { ASSERTSTR (sortab.nrow() == itsNrBl, "The MS appears to have multiple subbands"); // Get the baselines. - ROScalarColumn<int>(itsIter.table(), "ANTENNA1").getColumn (itsAnt1); - ROScalarColumn<int>(itsIter.table(), "ANTENNA2").getColumn (itsAnt2); + ROScalarColumn<Int>(itsIter.table(), "ANTENNA1").getColumn (itsAnt1); + ROScalarColumn<Int>(itsIter.table(), "ANTENNA2").getColumn (itsAnt2); // Keep the row numbers of the first part to be used for the meta info // of possibly missing time slots. itsBaseRowNrs = itsIter.table().rowNumbers(itsMS); @@ -367,8 +369,10 @@ namespace LOFAR { // Read the center frequencies of all channels. Table spwtab(itsMS.keywordSet().asTable("SPECTRAL_WINDOW")); ROArrayColumn<double> freqCol (spwtab, "CHAN_FREQ"); + ROArrayColumn<double> widthCol (spwtab, "CHAN_WIDTH"); // Take only the channels used in the input. - itsChanFreqs = freqCol(0); + itsChanFreqs = freqCol(0); + itsChanWidths = widthCol(0); // Get the array position using the telescope name from the OBSERVATION // subtable. Table obstab (itsMS.keywordSet().asTable ("OBSERVATION")); @@ -446,35 +450,79 @@ namespace LOFAR { weights = 0; return weights; } - // Get weights for entire spectrum if pesent. + Cube<float> weights; + // Get weights for entire spectrum if present. if (itsHasWeightSpectrum) { ROArrayColumn<float> wsCol(itsMS, "WEIGHT_SPECTRUM"); // Using getColumnCells(rowNrs,itsColSlicer) fails for LofarStMan. // Hence work around it. - Cube<float> weights = wsCol.getColumnCells (rowNrs); - return (itsUseAllChan ? weights : weights(itsArrSlicer)); - } - // No spectrum present, so get global weights and assign to each channel. - ROArrayColumn<float> wCol(itsMS, "WEIGHT"); - Matrix<float> inArr = wCol.getColumnCells (rowNrs); - Cube<float> outArr(itsNrCorr, itsNrChan, itsNrBl); - float* inPtr = inArr.data(); - float* outPtr = outArr.data(); - for (uint i=0; i<itsNrBl; ++i) { - // If global weights are zero, set them to 1. Some old MSs need that. - for (uint k=0; k<itsNrCorr; ++k) { - if (inPtr[k] == 0.) { - inPtr[k] = 1.; - } + weights.reference (wsCol.getColumnCells (rowNrs)); + if (!itsUseAllChan) { + weights.reference (weights(itsArrSlicer)); } - for (uint j=0; j<itsNrChan; ++j) { + } else { + // No spectrum present; get global weights and assign to each channel. + ROArrayColumn<float> wCol(itsMS, "WEIGHT"); + Matrix<float> inArr = wCol.getColumnCells (rowNrs); + Cube<float> outArr(itsNrCorr, itsNrChan, itsNrBl); + float* inPtr = inArr.data(); + float* outPtr = outArr.data(); + for (uint i=0; i<itsNrBl; ++i) { + // If global weights are zero, set them to 1. Some old MSs need that. for (uint k=0; k<itsNrCorr; ++k) { - *outPtr++ = inPtr[k]; + if (inPtr[k] == 0.) { + inPtr[k] = 1.; + } + } + for (uint j=0; j<itsNrChan; ++j) { + for (uint k=0; k<itsNrCorr; ++k) { + *outPtr++ = inPtr[k]; + } + } + inPtr += itsNrCorr; + } + weights.reference (outArr); + } + if (itsAutoWeight) { + // Adapt weights using autocorrelations. + autoWeight (weights); + } + return weights; + } + + void MSReader::autoWeight (Cube<float>& weights) + { + const double* chanWidths = itsChanWidths.data(); + uint npol = weights.shape()[0]; + uint nchan = weights.shape()[1]; + uint nbl = weights.shape()[2]; + // Get the autocorrelations indices. + const vector<int>& autoInx = getAutoCorrIndex(); + // Calculate the weight for each cross-correlation data point. + const Complex* data = itsBuffer.getData().data(); + float* weight = weights.data(); + for (uint i=0; i<nbl; ++i) { + // Can only be done if both autocorrelations are present. + if (itsAnt1[i] != itsAnt2[i] && + autoInx[itsAnt1[i]] >= 0 && autoInx[itsAnt2[i]] >= 0) { + // Get offset of both autocorr in data array. + const Complex* auto1 = data + autoInx[itsAnt1[i]]*nchan*npol; + const Complex* auto2 = data + autoInx[itsAnt2[i]]*nchan*npol; + for (uint j=0; j<nchan; ++j) { + double w = chanWidths[j] * itsInterval; + *weight++ *= w / (auto1[0].real() * auto2[0].real()); // XX + if (npol == 4) { + *weight++ *= w / (auto1[0].real() * auto2[1].real()); // XY + *weight++ *= w / (auto1[1].real() * auto2[0].real()); // YX + *weight++ *= w / (auto1[1].real() * auto2[1].real()); // YY + } else if (npol == 2) { + *weight++ *= w / (auto1[1].real() * auto2[1].real()); // YY + } } + } else { + weight += nchan*npol; } - inPtr += itsNrCorr; } - return outArr; } Cube<bool> MSReader::getFullResFlags (const RefRows& rowNrs) diff --git a/CEP/DP3/DPPP/test/tAverager.cc b/CEP/DP3/DPPP/test/tAverager.cc index 3329568362eab81fab1ab5a8add862b35a4697e1..9edf29153d1543926fb8bc5224d04ffedcafced0 100644 --- a/CEP/DP3/DPPP/test/tAverager.cc +++ b/CEP/DP3/DPPP/test/tAverager.cc @@ -117,9 +117,7 @@ private: for (int j=itsCount*itsNAvgTime; j<itsCount*itsNAvgTime+navgtime; ++j) { for (int i=0; i<int(data.size()); ++i) { data.data()[i] += Complex(i+j*10,i-1000+j*6); - if (!itsFlag) { - weights.data()[i] += float(1); - } + weights.data()[i] += float(1); } } fullResFlags(Slicer(IPosition(3,0,0,0),