diff --git a/.gitattributes b/.gitattributes index 4a0935e794db3bdea28e382a1784cbf91466b8ea..025ea37510b4e5035910341e53e6e67593ff5567 100644 --- a/.gitattributes +++ b/.gitattributes @@ -895,6 +895,8 @@ CEP/DP3/DPPP/test/tApplyCal.cc -text CEP/DP3/DPPP/test/tApplyCal.in_parmdb.tgz -text svneol=unset#application/x-gzip CEP/DP3/DPPP/test/tApplyCal.run -text CEP/DP3/DPPP/test/tApplyCal.sh -text +CEP/DP3/DPPP/test/tApplyCal2.run -text +CEP/DP3/DPPP/test/tApplyCal2.sh -text CEP/DP3/DPPP/test/tApplyCal_parmdbscript -text CEP/DP3/DPPP/test/tDemix.in_MS.tgz -text CEP/DP3/DPPP/test/tDemix.run -text diff --git a/CEP/DP3/DPPP/include/DPPP/ApplyBeam.h b/CEP/DP3/DPPP/include/DPPP/ApplyBeam.h index 2f80b2f860f61a03d215ebea29a2d19b3bf09cfa..c27c34e2af0ae3470e266a780f048e77184a4070 100644 --- a/CEP/DP3/DPPP/include/DPPP/ApplyBeam.h +++ b/CEP/DP3/DPPP/include/DPPP/ApplyBeam.h @@ -82,13 +82,14 @@ namespace LOFAR { template<typename T> static void applyBeam( - const DPInfo& info, double time, T* data0, + const DPInfo& info, double time, T* data0, float* weight0, const StationResponse::vector3r_t& srcdir, const StationResponse::vector3r_t& refdir, const StationResponse::vector3r_t& tiledir, const vector<StationResponse::Station::Ptr>& antBeamInfo, vector<StationResponse::matrix22c_t>& beamValues, - bool useChannelFreq, bool invert, int mode=DEFAULT); + bool useChannelFreq, bool invert, int mode, + bool doUpdateWeights=false); private: StationResponse::vector3r_t dir2Itrf( @@ -100,6 +101,7 @@ namespace LOFAR { string itsName; DPBuffer itsBuffer; bool itsInvert; + bool itsUpdateWeights; bool itsUseChannelFreq; Position itsPhaseRef; BeamMode itsMode; diff --git a/CEP/DP3/DPPP/include/DPPP/ApplyBeam.tcc b/CEP/DP3/DPPP/include/DPPP/ApplyBeam.tcc index ecaeef750c8211871841e1b32623b02c309818bf..d241f43c03c2d61c49d5f79469693901cdb86d5e 100644 --- a/CEP/DP3/DPPP/include/DPPP/ApplyBeam.tcc +++ b/CEP/DP3/DPPP/include/DPPP/ApplyBeam.tcc @@ -66,13 +66,13 @@ namespace LOFAR { // applyBeam is templated on the type of the data, could be double or float template<typename T> void ApplyBeam::applyBeam( - const DPInfo& info, double time, T* data0, + const DPInfo& info, double time, T* data0, float* weight0, const StationResponse::vector3r_t& srcdir, const StationResponse::vector3r_t& refdir, const StationResponse::vector3r_t& tiledir, const vector<StationResponse::Station::Ptr>& antBeamInfo, vector<StationResponse::matrix22c_t>& beamValues, bool useChannelFreq, - bool invert, int mode) + bool invert, int mode, bool doUpdateWeights) { // Get the beam values for each station. uint nCh = info.chanFreqs().size(); @@ -162,6 +162,10 @@ void ApplyBeam::applyBeam( data[1] = tmp[0] * r[1] + tmp[1] * r[3]; data[2] = tmp[2] * r[0] + tmp[3] * r[2]; data[3] = tmp[2] * r[1] + tmp[3] * r[3]; + + if (doUpdateWeights) { + ApplyCal::applyWeights(l, r, weight0 + bl * 4 * nCh + ch * 4); + } } } } diff --git a/CEP/DP3/DPPP/include/DPPP/ApplyCal.h b/CEP/DP3/DPPP/include/DPPP/ApplyCal.h index 113b39c2a5e6be7ea6b4ced7f320da9b8c8c5fc0..b827eaa81d45d260d05328791932e9485fd2cc1a 100644 --- a/CEP/DP3/DPPP/include/DPPP/ApplyCal.h +++ b/CEP/DP3/DPPP/include/DPPP/ApplyCal.h @@ -92,6 +92,18 @@ namespace LOFAR { uint bl, uint chan, bool updateWeights, FlagCounter& flagCounter); + // Do the same as the combination of BBS + python script + // covariance2weight.py (cookbook), except it stores weights per freq. + // The diagonal of covariance matrix is transferred to the weights. + // Note that the real covariance (mixing of noise terms after which they + // are not independent anymore) is not stored. + // The input covariance matrix C is assumed to be diagonal with elements + // w_i (the weights), the result the diagonal of + // (gainA kronecker gainB^H).C.(gainA kronecker gainB^H)^H + static void applyWeights (const casa::DComplex* gainA, + const casa::DComplex* gainB, + float* weight); + private: // Read parameters from the associated parmdb and store them in itsParms void updateParms (const double bufStartTime); diff --git a/CEP/DP3/DPPP/src/ApplyBeam.cc b/CEP/DP3/DPPP/src/ApplyBeam.cc index 7f9b139c69c384462c538383d009984652af69ea..8d1484bb1a096196e55fb6fccbe87ae0828ea1d2 100644 --- a/CEP/DP3/DPPP/src/ApplyBeam.cc +++ b/CEP/DP3/DPPP/src/ApplyBeam.cc @@ -54,10 +54,11 @@ namespace LOFAR { namespace DPPP { ApplyBeam::ApplyBeam(DPInput* input, const ParameterSet& parset, - const string& prefix, bool substep) + const string& prefix, bool substep) : itsInput(input), itsName(prefix), + itsUpdateWeights(parset.getBool(prefix + "updateweights", false)), itsUseChannelFreq(parset.getBool(prefix + "usechannelfreq", true)), itsDebugLevel(parset.getInt(prefix + "debuglevel", 0)) { @@ -94,6 +95,9 @@ namespace LOFAR { info() = infoIn; info().setNeedVisData(); info().setWriteData(); + if (itsUpdateWeights) { + info().setWriteWeights(); + } MDirection dirJ2000( MDirection::Convert(infoIn.phaseCenter(), MDirection::J2000)()); @@ -136,6 +140,7 @@ namespace LOFAR { os << endl; os << " use channelfreq: " << boolalpha << itsUseChannelFreq << endl; os << " invert: " << boolalpha << itsInvert << endl; + os << " update weights: " << boolalpha << itsUpdateWeights << endl; } void ApplyBeam::showTimings(std::ostream& os, double duration) const @@ -151,6 +156,11 @@ namespace LOFAR { itsBuffer.copy (bufin); Complex* data=itsBuffer.getData().data(); + if (itsUpdateWeights) { + itsInput->fetchWeights (bufin, itsBuffer, itsTimer); + } + float* weight = itsBuffer.getWeights().data(); + double time = itsBuffer.getTime(); //Set up directions for beam evaluation @@ -168,9 +178,9 @@ namespace LOFAR { uint thread = OpenMP::threadNum(); StationResponse::vector3r_t srcdir = refdir; - applyBeam(info(), time, data, srcdir, refdir, tiledir, + applyBeam(info(), time, data, weight, srcdir, refdir, tiledir, itsAntBeamInfo[thread], itsBeamValues[thread], - itsUseChannelFreq, itsInvert, itsMode); + itsUseChannelFreq, itsInvert, itsMode, itsUpdateWeights); itsTimer.stop(); getNextStep()->process(itsBuffer); diff --git a/CEP/DP3/DPPP/src/ApplyCal.cc b/CEP/DP3/DPPP/src/ApplyCal.cc index 0e4f28cdca3e250deaadff749a61d886d1dc6aac..08f0dc16ea97438a84bcb684718b742262db6a5d 100644 --- a/CEP/DP3/DPPP/src/ApplyCal.cc +++ b/CEP/DP3/DPPP/src/ApplyCal.cc @@ -554,7 +554,7 @@ namespace LOFAR { void ApplyCal::applyFull (const DComplex* gainA, const DComplex* gainB, Complex* vis, float* weight, bool* flag, - uint bl, uint chan, bool updateWeights, + uint bl, uint chan, bool doUpdateWeights, FlagCounter& flagCounter) { DComplex gainAxvis[4]; @@ -595,46 +595,44 @@ namespace LOFAR { } } - // The code below does the same as the combination of BBS + python script - // covariance2weight.py (cookbook), except it stores weights per freq. - // The diagonal of covariance matrix is transferred to the weights. - // Note that the real covariance (mixing of noise terms after which they - // are not independent anymore) is not stored. - // The input covariance matrix C is assumed to be diagonal with elements - // w_i (the weights), the result the diagonal of - // (gainA kronecker gainB^H).C.(gainA kronecker gainB^H)^H - if (updateWeights) { - float cov[4], normGainA[4], normGainB[4]; - for (uint i=0;i<4;++i) { - cov[i]=1./weight[i]; - normGainA[i]=norm(gainA[i]); - normGainB[i]=norm(gainB[i]); - } + if (doUpdateWeights) { + applyWeights(gainA, gainB, weight); + } + } - weight[0]=cov[0]*(normGainA[0]*normGainB[0]) - +cov[1]*(normGainA[0]*normGainB[1]) - +cov[2]*(normGainA[1]*normGainB[0]) - +cov[3]*(normGainA[1]*normGainB[1]); - weight[0]=1./weight[0]; - - weight[1]=cov[0]*(normGainA[0]*normGainB[2]) - +cov[1]*(normGainA[0]*normGainB[3]) - +cov[2]*(normGainA[1]*normGainB[2]) - +cov[3]*(normGainA[1]*normGainB[3]); - weight[1]=1./weight[1]; - - weight[2]=cov[0]*(normGainA[2]*normGainB[0]) - +cov[1]*(normGainA[2]*normGainB[1]) - +cov[2]*(normGainA[3]*normGainB[0]) - +cov[3]*(normGainA[3]*normGainB[1]); - weight[2]=1./weight[2]; - - weight[3]=cov[0]*(normGainA[2]*normGainB[2]) - +cov[1]*(normGainA[2]*normGainB[3]) - +cov[2]*(normGainA[3]*normGainB[2]) - +cov[3]*(normGainA[3]*normGainB[3]); - weight[3]=1./weight[3]; + void ApplyCal::applyWeights(const DComplex* gainA, + const DComplex* gainB, + float* weight) { + float cov[4], normGainA[4], normGainB[4]; + for (uint i=0;i<4;++i) { + cov[i]=1./weight[i]; + normGainA[i]=norm(gainA[i]); + normGainB[i]=norm(gainB[i]); } + + weight[0]=cov[0]*(normGainA[0]*normGainB[0]) + +cov[1]*(normGainA[0]*normGainB[1]) + +cov[2]*(normGainA[1]*normGainB[0]) + +cov[3]*(normGainA[1]*normGainB[1]); + weight[0]=1./weight[0]; + + weight[1]=cov[0]*(normGainA[0]*normGainB[2]) + +cov[1]*(normGainA[0]*normGainB[3]) + +cov[2]*(normGainA[1]*normGainB[2]) + +cov[3]*(normGainA[1]*normGainB[3]); + weight[1]=1./weight[1]; + + weight[2]=cov[0]*(normGainA[2]*normGainB[0]) + +cov[1]*(normGainA[2]*normGainB[1]) + +cov[2]*(normGainA[3]*normGainB[0]) + +cov[3]*(normGainA[3]*normGainB[1]); + weight[2]=1./weight[2]; + + weight[3]=cov[0]*(normGainA[2]*normGainB[2]) + +cov[1]*(normGainA[2]*normGainB[3]) + +cov[2]*(normGainA[3]*normGainB[2]) + +cov[3]*(normGainA[3]*normGainB[3]); + weight[3]=1./weight[3]; } void ApplyCal::showCounts (std::ostream& os) const diff --git a/CEP/DP3/DPPP/src/Predict.cc b/CEP/DP3/DPPP/src/Predict.cc index 64db694225cb1c64de98ff83ee4ae1bf083777fd..e8b318a82fcb41b337322ef9db88ad4bb3c3caa3 100644 --- a/CEP/DP3/DPPP/src/Predict.cc +++ b/CEP/DP3/DPPP/src/Predict.cc @@ -337,9 +337,12 @@ namespace LOFAR { MDirection::J2000); StationResponse::vector3r_t srcdir = dir2Itrf(dir,itsMeasConverters[thread]); - ApplyBeam::applyBeam(info(), time, data0, srcdir, refdir, + float* dummyweight = 0; + + ApplyBeam::applyBeam(info(), time, data0, dummyweight, srcdir, refdir, tiledir, itsAntBeamInfo[thread], - itsBeamValues[thread], itsUseChannelFreq, false, itsBeamMode); + itsBeamValues[thread], itsUseChannelFreq, false, + itsBeamMode, false); //Add temporary buffer to itsModelVis std::transform(itsModelVis[thread].data(), diff --git a/CEP/DP3/DPPP/test/CMakeLists.txt b/CEP/DP3/DPPP/test/CMakeLists.txt index cbe865863114480aee462f556f65e35f893ab1b0..f5e4caa66ae1360515f5433759d5c13d8e31e830 100644 --- a/CEP/DP3/DPPP/test/CMakeLists.txt +++ b/CEP/DP3/DPPP/test/CMakeLists.txt @@ -17,6 +17,7 @@ lofar_add_test(tPhaseShift tPhaseShift.cc) lofar_add_test(tStationAdder tStationAdder.cc) lofar_add_test(tScaleData tScaleData.cc) lofar_add_test(tApplyCal tApplyCal.cc) +lofar_add_test(tApplyCal2) lofar_add_test(tFilter tFilter.cc) #lofar_add_test(tDemixer tDemixer.cc) lofar_add_test(tNDPPP tNDPPP.cc) diff --git a/CEP/DP3/DPPP/test/tApplyBeam.run b/CEP/DP3/DPPP/test/tApplyBeam.run index 8878b0ad9ecf1ceadeba6111c041649ff1f5756e..19daa40a2d1c7d8f867db1d1b3b2147645bc14dc 100755 --- a/CEP/DP3/DPPP/test/tApplyBeam.run +++ b/CEP/DP3/DPPP/test/tApplyBeam.run @@ -58,3 +58,9 @@ echo; echo "Test with beammode=ELEMENT"; echo # Compare the DATA column of the output MS with the BBS reference output. $taqlexe 'select from outinv.ms t1, tApplyBeam.tab t2 where not all(near(t1.DATA,t2.DATA_ELEMENT,1e-5) || (isnan(t1.DATA) && isnan(t2.DATA_ELEMENT)))' > taql.out diff taql.out taql.ref || exit 1 + +echo; echo "Test with updateweights=true"; echo +../../src/NDPPP msin=tNDPPP-generic.MS msout=. steps=[applybeam] applybeam.updateweights=truue msout.weightcolumn=NEW_WEIGHT_SPECTRUM +# Check that the weights have changed +$taqlexe 'select from tNDPPP-generic.MS where all(near(WEIGHT_SPECTRUM, NEW_WEIGHT_SPECTRUM))' > taql.out +diff taql.out taql.ref || exit 1 diff --git a/CEP/DP3/DPPP/test/tApplyCal2.run b/CEP/DP3/DPPP/test/tApplyCal2.run new file mode 100755 index 0000000000000000000000000000000000000000..3e460f1ffa58d39f196c7c3aabff9962068265ca --- /dev/null +++ b/CEP/DP3/DPPP/test/tApplyCal2.run @@ -0,0 +1,43 @@ +#!/bin/bash + +# Get the taql executable and srcdir (script created by cmake's CONFIGURE_FILE). +source findenv.run_script +echo "srcdirx=$rt_srcdir" + +# Set srcdir if not defined (in case run by hand). +if test "$srcdir" = ""; then + srcdir="$rt_srcdir" +fi + +if test ! -f ${srcdir}/tNDPPP-generic.in_MS.tgz; then + exit 3 # untested +fi + +rm -rf tApplyCal2_tmp +mkdir -p tApplyCal2_tmp +# Unpack the MS and other files and do the DPPP run. +cd tApplyCal2_tmp +tar zxf ${srcdir}/tNDPPP-generic.in_MS.tgz + +# Create expected taql output. +echo " select result of 0 rows" > taql.ref + +echo; echo "Creating parmdb with defvalues 3" +../../../../ParmDB/src/parmdbm <<EOL +open table="tApplyCal.parmdb" +adddef Gain:0:0:Real values=3. +adddef Gain:1:1:Real values=3. +EOL + +echo; echo "Testing without updateweights" +../../src/NDPPP msin=tNDPPP-generic.MS msout=. msout.datacolumn=DATA3 msout.weightcolumn=WEIGHTS_NEW steps=[applycal] applycal.parmdb=tApplyCal.parmdb showcounts=false +$taqlexe 'select from tNDPPP-generic.MS where not(all(DATA~=9*DATA3))' > taql.out +diff taql.out taql.ref || exit 1 +$taqlexe 'select from tNDPPP-generic.MS where not(all(WEIGHTS_NEW~=WEIGHT_SPECTRUM))' > taql.out +diff taql.out taql.ref || exit 1 + +echo; echo "Testing with updateweights" +../../src/NDPPP msin=tNDPPP-generic.MS msout=. msout.datacolumn=DATA3 msout.weightcolumn=WEIGHTS_NEW steps=[applycal] applycal.parmdb=tApplyCal.parmdb showcounts=false applycal.updateweights=true +$taqlexe 'select from tNDPPP-generic.MS where not(all(WEIGHTS_NEW~=81*WEIGHT_SPECTRUM))' > taql.out +diff taql.out taql.ref || exit 1 + diff --git a/CEP/DP3/DPPP/test/tApplyCal2.sh b/CEP/DP3/DPPP/test/tApplyCal2.sh new file mode 100755 index 0000000000000000000000000000000000000000..2c166e188f8c8671ea007c9e084af4ce70fde811 --- /dev/null +++ b/CEP/DP3/DPPP/test/tApplyCal2.sh @@ -0,0 +1,2 @@ +#!/bin/sh +./runctest.sh tApplyCal2