diff --git a/.gitattributes b/.gitattributes index 81463bd741d889806c6a3819feabbd8261153372..e4c88e8c515f4275fb67980fe4d6d003fcaaf071 100644 --- a/.gitattributes +++ b/.gitattributes @@ -36,10 +36,11 @@ CEP/Calibration/BBSKernel/include/BBSKernel/Apply.h -text CEP/Calibration/BBSKernel/include/BBSKernel/BaselineMask.h -text CEP/Calibration/BBSKernel/include/BBSKernel/Correlation.h -text CEP/Calibration/BBSKernel/include/BBSKernel/CorrelationMask.h -text -CEP/Calibration/BBSKernel/include/BBSKernel/ElementBeamExpr.h -text CEP/Calibration/BBSKernel/include/BBSKernel/Estimate.h -text CEP/Calibration/BBSKernel/include/BBSKernel/EstimateUtil.h -text -CEP/Calibration/BBSKernel/include/BBSKernel/Expr/AntennaFieldAzEl.h -text +CEP/Calibration/BBSKernel/include/BBSKernel/Expr/AntennaElementHBA.h -text +CEP/Calibration/BBSKernel/include/BBSKernel/Expr/AntennaElementLBA.h -text +CEP/Calibration/BBSKernel/include/BBSKernel/Expr/AntennaFieldThetaPhi.h -text CEP/Calibration/BBSKernel/include/BBSKernel/Expr/CachePolicy.h -text CEP/Calibration/BBSKernel/include/BBSKernel/Expr/Delay.h -text CEP/Calibration/BBSKernel/include/BBSKernel/Expr/ElevationCut.h -text @@ -48,6 +49,7 @@ CEP/Calibration/BBSKernel/include/BBSKernel/Expr/FaradayRotation.h -text CEP/Calibration/BBSKernel/include/BBSKernel/Expr/ITRFDirection.h -text CEP/Calibration/BBSKernel/include/BBSKernel/Expr/IonPhaseShift.h -text CEP/Calibration/BBSKernel/include/BBSKernel/Expr/LinearToCircularRL.h -text +CEP/Calibration/BBSKernel/include/BBSKernel/Expr/ParallacticRotation.h -text CEP/Calibration/BBSKernel/include/BBSKernel/Expr/Scope.h -text CEP/Calibration/BBSKernel/include/BBSKernel/Expr/ShapeletCoherence.h -text CEP/Calibration/BBSKernel/include/BBSKernel/Expr/ShapeletSource.h -text @@ -75,10 +77,11 @@ CEP/Calibration/BBSKernel/src/Contrib/SBY_DipoleBeam/hba_beam_phi.c -text CEP/Calibration/BBSKernel/src/Contrib/SBY_DipoleBeam/hba_beam_theta.c -text CEP/Calibration/BBSKernel/src/Correlation.cc -text CEP/Calibration/BBSKernel/src/CorrelationMask.cc -text -CEP/Calibration/BBSKernel/src/ElementBeamExpr.cc -text CEP/Calibration/BBSKernel/src/Estimate.cc -text CEP/Calibration/BBSKernel/src/EstimateUtil.cc -text -CEP/Calibration/BBSKernel/src/Expr/AntennaFieldAzEl.cc -text +CEP/Calibration/BBSKernel/src/Expr/AntennaElementHBA.cc -text +CEP/Calibration/BBSKernel/src/Expr/AntennaElementLBA.cc -text +CEP/Calibration/BBSKernel/src/Expr/AntennaFieldThetaPhi.cc -text CEP/Calibration/BBSKernel/src/Expr/CachePolicy.cc -text CEP/Calibration/BBSKernel/src/Expr/Delay.cc -text CEP/Calibration/BBSKernel/src/Expr/ElevationCut.cc -text @@ -87,6 +90,7 @@ CEP/Calibration/BBSKernel/src/Expr/FaradayRotation.cc -text CEP/Calibration/BBSKernel/src/Expr/ITRFDirection.cc -text CEP/Calibration/BBSKernel/src/Expr/IonPhaseShift.cc -text CEP/Calibration/BBSKernel/src/Expr/LinearToCircularRL.cc -text +CEP/Calibration/BBSKernel/src/Expr/ParallacticRotation.cc -text CEP/Calibration/BBSKernel/src/Expr/Scope.cc -text CEP/Calibration/BBSKernel/src/Expr/ShapeletCoherence.cc -text CEP/Calibration/BBSKernel/src/Expr/ShapeletSource.cc -text diff --git a/CEP/Calibration/BBSControl/src/Step.cc b/CEP/Calibration/BBSControl/src/Step.cc index 61e40ce06e204894f0000ff1a700afa72c47664a..fa07affa90e7d3e9d1367b5a6da85b5130b11de8 100644 --- a/CEP/Calibration/BBSControl/src/Step.cc +++ b/CEP/Calibration/BBSControl/src/Step.cc @@ -157,8 +157,6 @@ namespace LOFAR ps.add(prefix + "Model.Beam.Mode", BeamConfig::asString(config.mode())); ps.add(prefix + "Model.Beam.ConjugateAF", toString(config.conjugateAF())); - ps.add(prefix + "Model.Beam.Element.Path", - config.getElementPath().originalName()); } ps.add(prefix + "Model.DirectionalTEC.Enable", @@ -243,18 +241,7 @@ namespace LOFAR bool conjugateAF = ps.getBool("Model.Beam.ConjugateAF", parentConfig.conjugateAF()); - string defaultPath; - if(itsModelConfig.useBeam()) { - defaultPath = parentConfig.getElementPath().originalName(); - } else { - defaultPath = "$LOFARROOT/share"; - } - - string elementPath = ps.getString("Model.Beam.Element.Path", - defaultPath); - - itsModelConfig.setBeamConfig(BeamConfig(mode, conjugateAF, - casa::Path(elementPath))); + itsModelConfig.setBeamConfig(BeamConfig(mode, conjugateAF)); } else { itsModelConfig.clearBeamConfig(); } diff --git a/CEP/Calibration/BBSKernel/CMakeLists.txt b/CEP/Calibration/BBSKernel/CMakeLists.txt index 2cc46bb4c2fb0307248344b4f5d4c5145c5f9ef8..7abae3e6495d9754c3e35032827e9aa93bc60376 100644 --- a/CEP/Calibration/BBSKernel/CMakeLists.txt +++ b/CEP/Calibration/BBSKernel/CMakeLists.txt @@ -1,6 +1,6 @@ # $Id$ -lofar_package(BBSKernel 1.0 DEPENDS Blob Common ParmDB) +lofar_package(BBSKernel 1.0 DEPENDS Blob Common ParmDB ElementResponse) include(LofarFindPackage) lofar_find_package(Boost REQUIRED) diff --git a/CEP/Calibration/BBSKernel/include/BBSKernel/CMakeLists.txt b/CEP/Calibration/BBSKernel/include/BBSKernel/CMakeLists.txt index 9a181070de34869725e4a02b500db569ff635e24..45cc134da39cc2e1e8584425e8b3a1a4d6585b00 100644 --- a/CEP/Calibration/BBSKernel/include/BBSKernel/CMakeLists.txt +++ b/CEP/Calibration/BBSKernel/include/BBSKernel/CMakeLists.txt @@ -39,7 +39,9 @@ install(FILES VisSelection.h DESTINATION include/${PACKAGE_NAME}) install(FILES - Expr/AntennaFieldAzEl.h + Expr/AntennaElementLBA.h + Expr/AntennaElementHBA.h + Expr/AntennaFieldThetaPhi.h Expr/AzEl.h Expr/BasicExpr.h Expr/Cache.h @@ -63,7 +65,6 @@ install(FILES Expr/FlagIf.h Expr/GaussianCoherence.h Expr/GaussianSource.h - Expr/HamakerDipole.h Expr/IonPhaseShift.h Expr/ITRFDirection.h Expr/LinearToCircularRL.h @@ -81,6 +82,7 @@ install(FILES Expr/MatrixSum.h Expr/MatrixTmp.h Expr/MergeFlags.h + Expr/ParallacticRotation.h Expr/PhaseShift.h Expr/PiercePoint.h Expr/PointCoherence.h diff --git a/CEP/Calibration/BBSKernel/include/BBSKernel/ElementBeamExpr.h b/CEP/Calibration/BBSKernel/include/BBSKernel/ElementBeamExpr.h deleted file mode 100644 index a25f2cc9e2cef8eca1af84fc473814d1f35dd6dd..0000000000000000000000000000000000000000 --- a/CEP/Calibration/BBSKernel/include/BBSKernel/ElementBeamExpr.h +++ /dev/null @@ -1,103 +0,0 @@ -//# ElementBeamExpr.h: Wrapper class that constructs the correct beam expr based -//# on the BeamConfig instance provided in the constructor. It also caches any -//# shared auxilliary data. -//# -//# Copyright (C) 2009 -//# ASTRON (Netherlands Institute for Radio Astronomy) -//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands -//# -//# This file is part of the LOFAR software suite. -//# The LOFAR software suite is free software: you can redistribute it and/or -//# modify it under the terms of the GNU General Public License as published -//# by the Free Software Foundation, either version 3 of the License, or -//# (at your option) any later version. -//# -//# The LOFAR software suite 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 General Public License for more details. -//# -//# You should have received a copy of the GNU General Public License along -//# with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>. -//# -//# $Id$ - -#ifndef LOFAR_BBSKERNEL_ELEMENTBEAMEXPR_H -#define LOFAR_BBSKERNEL_ELEMENTBEAMEXPR_H - -// \file -// Wrapper class that constructs the correct beam expr based on the BeamConfig -// instance provided in the constructor. It also caches any shared auxilliary -// data. - -#include <BBSKernel/Expr/Expr.h> -#include <BBSKernel/Expr/HamakerDipole.h> - -#include <Common/lofar_smartptr.h> - -#include <casa/OS/Path.h> - -namespace LOFAR -{ -namespace BBS -{ - -class BeamConfig; -class Scope; - -// \addtogroup BBSKernel -// @{ - -class ElementBeamExpr -{ -public: - typedef shared_ptr<ElementBeamExpr> Ptr; - typedef shared_ptr<const ElementBeamExpr> ConstPtr; - - static ElementBeamExpr::Ptr create(const BeamConfig &config, Scope &scope); - - virtual ~ElementBeamExpr(); - - virtual Expr<JonesMatrix>::Ptr - construct(const Expr<Vector<2> >::ConstPtr &direction, - const Expr<Scalar>::ConstPtr &orientation) const = 0; -}; - -class HamakerBeamExpr: public ElementBeamExpr -{ -public: - typedef shared_ptr<HamakerBeamExpr> Ptr; - typedef shared_ptr<const HamakerBeamExpr> ConstPtr; - - HamakerBeamExpr(const BeamConfig &config, Scope &scope); - - virtual Expr<JonesMatrix>::Ptr - construct(const Expr<Vector<2> >::ConstPtr &direction, - const Expr<Scalar>::ConstPtr &orientation) const; - -private: - HamakerBeamCoeff itsCoeff; -}; - -class YatawattaBeamExpr: public ElementBeamExpr -{ -public: - typedef shared_ptr<YatawattaBeamExpr> Ptr; - typedef shared_ptr<const YatawattaBeamExpr> ConstPtr; - - YatawattaBeamExpr(const BeamConfig &config, Scope &scope); - - virtual Expr<JonesMatrix>::Ptr - construct(const Expr<Vector<2> >::ConstPtr &direction, - const Expr<Scalar>::ConstPtr &orientation) const; - -private: - casa::Path itsModulePath[2]; -}; - -// @} - -} //# namespace BBS -} //# namespace LOFAR - -#endif diff --git a/CEP/Calibration/BBSKernel/include/BBSKernel/Expr/YatawattaDipole.h b/CEP/Calibration/BBSKernel/include/BBSKernel/Expr/AntennaElementHBA.h similarity index 62% rename from CEP/Calibration/BBSKernel/include/BBSKernel/Expr/YatawattaDipole.h rename to CEP/Calibration/BBSKernel/include/BBSKernel/Expr/AntennaElementHBA.h index 404baf3ce39ebb552463e49ce4c88d4982b0356a..4e46bae67ae78e0a273b407ebe00d5cb557775f7 100644 --- a/CEP/Calibration/BBSKernel/include/BBSKernel/Expr/YatawattaDipole.h +++ b/CEP/Calibration/BBSKernel/include/BBSKernel/Expr/AntennaElementHBA.h @@ -1,7 +1,7 @@ -//# YatawattaDipole.h: Dipole voltage beam using Sarod Yatawatta's analytical -//# model. +//# AntennaElementHBA.h: Model of an idealized LOFAR HBA dual dipole antenna +//# element. //# -//# Copyright (C) 2008 +//# Copyright (C) 2011 //# ASTRON (Netherlands Institute for Radio Astronomy) //# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands //# @@ -21,16 +21,13 @@ //# //# $Id$ -#ifndef LOFAR_BBSKERNEL_EXPR_YATAWATTADIPOLE_H -#define LOFAR_BBSKERNEL_EXPR_YATAWATTADIPOLE_H +#ifndef LOFAR_BBSKERNEL_EXPR_ANTENNAELEMENTHBA_H +#define LOFAR_BBSKERNEL_EXPR_ANTENNAELEMENTHBA_H -#include <BBSKernel/Expr/BasicExpr.h> -#include <BBSKernel/Expr/ExternalFunction.h> +// \file +// Model of an idealized LOFAR HBA dual dipole antenna element. -namespace casa -{ - class Path; -} +#include <BBSKernel/Expr/BasicExpr.h> namespace LOFAR { @@ -40,19 +37,17 @@ namespace BBS // \addtogroup Expr // @{ -class YatawattaDipole: public BasicBinaryExpr<Vector<2>, Scalar, JonesMatrix> +class AntennaElementHBA: public BasicUnaryExpr<Vector<2>, JonesMatrix> { public: - YatawattaDipole(const casa::Path &moduleTheta, const casa::Path &modulePhi, - const Expr<Vector<2> >::ConstPtr &azel, - const Expr<Scalar>::ConstPtr &orientation); + typedef shared_ptr<AntennaElementHBA> Ptr; + typedef shared_ptr<const AntennaElementHBA> ConstPtr; + + AntennaElementHBA(const Expr<Vector<2> >::ConstPtr &target); protected: virtual const JonesMatrix::View evaluateImpl(const Grid &grid, - const Vector<2>::View &azel, const Scalar::View &orientation) const; - -private: - ExternalFunction itsThetaFunction, itsPhiFunction; + const Vector<2>::View &target) const; }; // @} diff --git a/CEP/Calibration/BBSKernel/include/BBSKernel/Expr/AntennaElementLBA.h b/CEP/Calibration/BBSKernel/include/BBSKernel/Expr/AntennaElementLBA.h new file mode 100644 index 0000000000000000000000000000000000000000..ce9fbefda8a97870dcc72739210e5b0f5a6d7696 --- /dev/null +++ b/CEP/Calibration/BBSKernel/include/BBSKernel/Expr/AntennaElementLBA.h @@ -0,0 +1,58 @@ +//# AntennaElementLBA.h: Model of an idealized LOFAR LBA dual dipole antenna +//# element. +//# +//# Copyright (C) 2011 +//# ASTRON (Netherlands Institute for Radio Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +//# +//# This file is part of the LOFAR software suite. +//# The LOFAR software suite is free software: you can redistribute it and/or +//# modify it under the terms of the GNU General Public License as published +//# by the Free Software Foundation, either version 3 of the License, or +//# (at your option) any later version. +//# +//# The LOFAR software suite 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License along +//# with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>. +//# +//# $Id$ + +#ifndef LOFAR_BBSKERNEL_EXPR_ANTENNAELEMENTLBA_H +#define LOFAR_BBSKERNEL_EXPR_ANTENNAELEMENTLBA_H + +// \file +// Model of an idealized LOFAR LBA dual dipole antenna element. + +#include <BBSKernel/Expr/BasicExpr.h> + +namespace LOFAR +{ +namespace BBS +{ + +// \addtogroup Expr +// @{ + +class AntennaElementLBA: public BasicUnaryExpr<Vector<2>, JonesMatrix> +{ +public: + typedef shared_ptr<AntennaElementLBA> Ptr; + typedef shared_ptr<const AntennaElementLBA> ConstPtr; + + AntennaElementLBA(const Expr<Vector<2> >::ConstPtr &target); + +protected: + virtual const JonesMatrix::View evaluateImpl(const Grid &grid, + const Vector<2>::View &target) const; +}; + +// @} + +} //# namespace BBS +} //# namespace LOFAR + +#endif diff --git a/CEP/Calibration/BBSKernel/include/BBSKernel/Expr/AntennaFieldAzEl.h b/CEP/Calibration/BBSKernel/include/BBSKernel/Expr/AntennaFieldAzEl.h deleted file mode 100644 index 7c00e7ad35c3293f23e6a06e02110c946f62e4bd..0000000000000000000000000000000000000000 --- a/CEP/Calibration/BBSKernel/include/BBSKernel/Expr/AntennaFieldAzEl.h +++ /dev/null @@ -1,72 +0,0 @@ -//# AntennaFieldAzEl.h: Compute azimuth and elevation in radians relevative to -//# the antenna field coordinate system (P, Q, R). The input direction as well -//# as the positive coordinate axes are assumed to be unit vectors expressed in -//# ITRF. Zero azimuth corresponds to the positive Q axis and positive azimuth -//# runs from the positive Q axis to the positive P axis. Elevation is the angle -//# the direction makes with the (P, Q) plane. -//# -//# Copyright (C) 2011 -//# ASTRON (Netherlands Institute for Radio Astronomy) -//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands -//# -//# This file is part of the LOFAR software suite. -//# The LOFAR software suite is free software: you can redistribute it and/or -//# modify it under the terms of the GNU General Public License as published -//# by the Free Software Foundation, either version 3 of the License, or -//# (at your option) any later version. -//# -//# The LOFAR software suite 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 General Public License for more details. -//# -//# You should have received a copy of the GNU General Public License along -//# with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>. -//# -//# $Id$ - -#ifndef LOFAR_BBSKERNEL_EXPR_ANTENNAFIELDAZEL_H -#define LOFAR_BBSKERNEL_EXPR_ANTENNAFIELDAZEL_H - -// \file -// Compute azimuth and elevation in radians relevative to the antenna field -// coordinate system (P, Q, R). The input direction as well as the positive -// coordinate axes are assumed to be unit vectors expressed in ITRF. Zero -// azimuth corresponds to the positive Q axis and positive azimuth runs from the -// positive Q axis to the positive P axis. Elevation is the angle the direction -// makes with the (P, Q) plane. - -#include <BBSKernel/Expr/BasicExpr.h> -#include <BBSKernel/Instrument.h> - -namespace LOFAR -{ -namespace BBS -{ - -// \addtogroup Expr -// @{ - -class AntennaFieldAzEl: public BasicUnaryExpr<Vector<3>, Vector<2> > -{ -public: - typedef shared_ptr<AntennaFieldAzEl> Ptr; - typedef shared_ptr<const AntennaFieldAzEl> ConstPtr; - - AntennaFieldAzEl(const Expr<Vector<3> >::ConstPtr &direction, - const AntennaField::ConstPtr &field); - -protected: - virtual const Vector<2>::View evaluateImpl(const Grid &grid, - const Vector<3>::View &direction) const; - -private: - AntennaField::ConstPtr itsField; -}; - -// @} - -} //# namespace BBS -} //# namespace LOFAR - -#endif diff --git a/CEP/Calibration/BBSKernel/include/BBSKernel/Expr/AntennaFieldThetaPhi.h b/CEP/Calibration/BBSKernel/include/BBSKernel/Expr/AntennaFieldThetaPhi.h new file mode 100644 index 0000000000000000000000000000000000000000..bee80c9b4eda48993df0afb1962e033c409a6a40 --- /dev/null +++ b/CEP/Calibration/BBSKernel/include/BBSKernel/Expr/AntennaFieldThetaPhi.h @@ -0,0 +1,76 @@ +//# AntennaFieldThetaPhi.h: Compute topocentric (local) theta and phi spherical +//# coordinates (in radians) relative to the Cartesian antenna field coordinate +//# system (PQR), for a given target direction. The target direction is assumed +//# to be an ITRF unit vector in the direction of arrival. The positive +//# coordinate axes are assumed to be ITRF unit vectors. Zero phi corresponds to +//# the positive P axis, and positive phi runs from the positive P axis towards +//# the positive Q axis (roughly East over North). Theta or zenith angle is the +//# angle the target direction makes with the positive R axis. +//# +//# Copyright (C) 2011 +//# ASTRON (Netherlands Institute for Radio Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +//# +//# This file is part of the LOFAR software suite. +//# The LOFAR software suite is free software: you can redistribute it and/or +//# modify it under the terms of the GNU General Public License as published +//# by the Free Software Foundation, either version 3 of the License, or +//# (at your option) any later version. +//# +//# The LOFAR software suite 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License along +//# with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>. +//# +//# $Id$ + +#ifndef LOFAR_BBSKERNEL_EXPR_ANTENNAFIELDTHETAPHI_H +#define LOFAR_BBSKERNEL_EXPR_ANTENNAFIELDTHETAPHI_H + +// \file +// Compute topocentric (local) theta and phi spherical coordinates (in radians) +// relative to the Cartesian antenna field coordinate system (PQR), for a given +// target direction. The target direction is assumed to be an ITRF unit vector +// in the direction of arrival. The positive coordinate axes are assumed to be +// ITRF unit vectors. Zero phi corresponds to the positive P axis, and positive +// phi runs from the positive P axis towards the positive Q axis (roughly East +// over North). Theta or zenith angle is the angle the target direction makes +// with the positive R axis. + +#include <BBSKernel/Expr/BasicExpr.h> +#include <BBSKernel/Instrument.h> + +namespace LOFAR +{ +namespace BBS +{ + +// \addtogroup Expr +// @{ + +class AntennaFieldThetaPhi: public BasicUnaryExpr<Vector<3>, Vector<2> > +{ +public: + typedef shared_ptr<AntennaFieldThetaPhi> Ptr; + typedef shared_ptr<const AntennaFieldThetaPhi> ConstPtr; + + AntennaFieldThetaPhi(const Expr<Vector<3> >::ConstPtr &direction, + const AntennaField::ConstPtr &field); + +protected: + virtual const Vector<2>::View evaluateImpl(const Grid &grid, + const Vector<3>::View &direction) const; + +private: + AntennaField::ConstPtr itsField; +}; + +// @} + +} //# namespace BBS +} //# namespace LOFAR + +#endif diff --git a/CEP/Calibration/BBSKernel/include/BBSKernel/Expr/HamakerDipole.h b/CEP/Calibration/BBSKernel/include/BBSKernel/Expr/HamakerDipole.h deleted file mode 100644 index 1471e126210786004cd157d60eed4571c47aa8c7..0000000000000000000000000000000000000000 --- a/CEP/Calibration/BBSKernel/include/BBSKernel/Expr/HamakerDipole.h +++ /dev/null @@ -1,122 +0,0 @@ -//# HamakerDipole.h: Implementation of J.P. Hamaker's memo -//# "Mathematical-physical analysis of the generic dual-dipole antenna". -//# -//# Copyright (C) 2008 -//# ASTRON (Netherlands Institute for Radio Astronomy) -//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands -//# -//# This file is part of the LOFAR software suite. -//# The LOFAR software suite is free software: you can redistribute it and/or -//# modify it under the terms of the GNU General Public License as published -//# by the Free Software Foundation, either version 3 of the License, or -//# (at your option) any later version. -//# -//# The LOFAR software suite 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 General Public License for more details. -//# -//# You should have received a copy of the GNU General Public License along -//# with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>. -//# -//# $Id$ - -#ifndef LOFAR_BBSKERNEL_EXPR_HAMAKERDIPOLE_H -#define LOFAR_BBSKERNEL_EXPR_HAMAKERDIPOLE_H - -// \file -// Implementation of J.P. Hamaker's memo "Mathematical-physical analysis of the -// generic dual-dipole antenna". - -#include <BBSKernel/Expr/BasicExpr.h> -#include <Common/lofar_complex.h> - -#include <casa/Arrays.h> - -namespace casa -{ - class Path; -} - -namespace LOFAR -{ -namespace BBS -{ - -// \addtogroup Expr -// @{ - -class HamakerBeamCoeff -{ -public: - HamakerBeamCoeff(); - - void init(const casa::Path &coeffFile); - - // Center frequency used to scale frequency to range [-1.0, 1.0]. - double center() const; - // Width used to scale frequency to range [-1.0, 1.0]. - double width() const; - - unsigned int shape(unsigned int i) const; - - dcomplex operator()(unsigned int element, unsigned int harmonic, - unsigned int powTheta, unsigned int powFreq) const; - -private: - double itsCenter, itsWidth; - casa::Array<dcomplex> itsCoeff; -}; - -class HamakerDipole: public BasicBinaryExpr<Vector<2>, Scalar, JonesMatrix> -{ -public: - typedef shared_ptr<HamakerDipole> Ptr; - typedef shared_ptr<const HamakerDipole> ConstPtr; - - HamakerDipole(const HamakerBeamCoeff &coeff, - const Expr<Vector<2> >::ConstPtr &azel, - const Expr<Scalar>::ConstPtr &orientation); - -protected: - virtual const JonesMatrix::View evaluateImpl(const Grid &grid, - const Vector<2>::View &azel, const Scalar::View &orientation) const; - -private: - HamakerBeamCoeff itsCoeff; -}; - -// @} - -// -------------------------------------------------------------------------- // -// - Implementation: HamakerBeamCoeff - // -// -------------------------------------------------------------------------- // - -inline double HamakerBeamCoeff::center() const -{ - return itsCenter; -} - -inline double HamakerBeamCoeff::width() const -{ - return itsWidth; -} - -inline unsigned int HamakerBeamCoeff::shape(unsigned int i) const -{ - // Reverse axes because casa::Array<> uses fortran order. - DBGASSERT(i < 4); - return itsCoeff.shape()(3 - i); -} - -inline dcomplex HamakerBeamCoeff::operator()(unsigned int element, - unsigned int harmonic, unsigned int powTheta, unsigned int powFreq) const -{ - // Reverse axes because casa::Array<> uses fortran order. - return itsCoeff(casa::IPosition(4, powFreq, powTheta, harmonic, element)); -} - -} //# namespace BBS -} //# namespace LOFAR - -#endif diff --git a/CEP/Calibration/BBSKernel/include/BBSKernel/Expr/ParallacticRotation.h b/CEP/Calibration/BBSKernel/include/BBSKernel/Expr/ParallacticRotation.h new file mode 100644 index 0000000000000000000000000000000000000000..32642f5ddab4f468991ce9ea585142e17c5e7399 --- /dev/null +++ b/CEP/Calibration/BBSKernel/include/BBSKernel/Expr/ParallacticRotation.h @@ -0,0 +1,71 @@ +//# ParallacticRotation.h: Jones matrix that relates the (X,Y)-frame used to +//# express polarization on the sky (according to the IAU definition) to the +//# topocentric (theta,phi)-frame. Both are Cartesian frames defined on the +//# tangent plane, with +X towards the North, +Y towards the East, +theta away +//# from the (pseudo) zenith, and +phi East over North around the (pseudo) +//# zenith. +//# +//# Copyright (C) 2011 +//# ASTRON (Netherlands Institute for Radio Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +//# +//# This file is part of the LOFAR software suite. +//# The LOFAR software suite is free software: you can redistribute it and/or +//# modify it under the terms of the GNU General Public License as published +//# by the Free Software Foundation, either version 3 of the License, or +//# (at your option) any later version. +//# +//# The LOFAR software suite 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License along +//# with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>. +//# +//# $Id$ + +#ifndef LOFAR_BBSKERNEL_EXPR_PARALLACTICROTATION_H +#define LOFAR_BBSKERNEL_EXPR_PARALLACTICROTATION_H + +// \file +// Jones matrix that relates the (X,Y)-frame used to express polarization on the +// sky (according to the IAU definition) to the topocentric (theta,phi)-frame. +// Both are Cartesian frames defined on the tangent plane, with +X towards the +// North, +Y towards the East, +theta away from the (pseudo) zenith, and +phi +// East over North around the (pseudo) zenith. + +#include <BBSKernel/Expr/BasicExpr.h> +#include <BBSKernel/Instrument.h> + +namespace LOFAR +{ +namespace BBS +{ + +// \addtogroup Expr +// @{ + +class ParallacticRotation: public BasicUnaryExpr<Vector<3>, JonesMatrix> +{ +public: + typedef shared_ptr<ParallacticRotation> Ptr; + typedef shared_ptr<const ParallacticRotation> ConstPtr; + + ParallacticRotation(const Expr<Vector<3> >::ConstPtr &target, + const AntennaField::ConstPtr &field); + +protected: + virtual const JonesMatrix::View evaluateImpl(const Grid &grid, + const Vector<3>::View &target) const; + +private: + AntennaField::ConstPtr itsField; +}; + +// @} + +} //# namespace BBS +} //# namespace LOFAR + +#endif diff --git a/CEP/Calibration/BBSKernel/include/BBSKernel/Instrument.h b/CEP/Calibration/BBSKernel/include/BBSKernel/Instrument.h index a90cf6839318c6259dea27d0f0ba2b1022b8a5ee..d442b93df93be7034b58cd7b39b817b0d4eb3389 100644 --- a/CEP/Calibration/BBSKernel/include/BBSKernel/Instrument.h +++ b/CEP/Calibration/BBSKernel/include/BBSKernel/Instrument.h @@ -50,8 +50,8 @@ namespace BBS class AntennaField { public: - typedef shared_ptr<AntennaField> Ptr; - typedef shared_ptr<AntennaField> ConstPtr; + typedef shared_ptr<AntennaField> Ptr; + typedef shared_ptr<const AntennaField> ConstPtr; enum Axis { @@ -72,7 +72,7 @@ public: const string &name() const; const Vector3 &position() const; - const Vector3 &axis(Axis axis); + const Vector3 &axis(Axis axis) const; bool isHBA() const; @@ -82,11 +82,13 @@ public: void appendElement(const Element &element); inline size_t nElement() const; + inline size_t nActiveElement() const; inline const Element &element(size_t i) const; private: string itsName; Vector3 itsPosition; + size_t itsActiveElementCount; Vector3 itsAxes[N_Axis]; vector<Vector3> itsTileElements; vector<Element> itsElements; @@ -95,8 +97,8 @@ private: class Station { public: - typedef shared_ptr<Station> Ptr; - typedef shared_ptr<Station> ConstPtr; + typedef shared_ptr<Station> Ptr; + typedef shared_ptr<const Station> ConstPtr; Station(const string &name, const casa::MPosition &position); Station(const string &name, const casa::MPosition &position, @@ -109,6 +111,9 @@ public: bool isPhasedArray() const; unsigned int nField() const; + size_t nElement() const; + size_t nActiveElement() const; + AntennaField::ConstPtr field(unsigned int i) const; private: @@ -120,8 +125,8 @@ private: class Instrument { public: - typedef shared_ptr<Instrument> Ptr; - typedef shared_ptr<Instrument> ConstPtr; + typedef shared_ptr<Instrument> Ptr; + typedef shared_ptr<const Instrument> ConstPtr; Instrument(const string &name, const casa::MPosition &position); @@ -166,6 +171,11 @@ inline size_t AntennaField::nElement() const return itsElements.size(); } +inline size_t AntennaField::nActiveElement() const +{ + return itsActiveElementCount; +} + inline const AntennaField::Element &AntennaField::element(size_t i) const { return itsElements[i]; diff --git a/CEP/Calibration/BBSKernel/include/BBSKernel/MeasurementAIPS.h b/CEP/Calibration/BBSKernel/include/BBSKernel/MeasurementAIPS.h index ad8d4809256d34fd9825216a8b0fd9bfdeb1be15..bdba8e923cbde5f2491d4a10de06f9ed85f2a90a 100644 --- a/CEP/Calibration/BBSKernel/include/BBSKernel/MeasurementAIPS.h +++ b/CEP/Calibration/BBSKernel/include/BBSKernel/MeasurementAIPS.h @@ -72,24 +72,15 @@ public: virtual void writeHistory(const ParameterSet &parset) const; virtual BaselineMask asMask(const string &filter) const; - // @} private: - void initInstrument(); - Station::Ptr initStation(unsigned int id, const string &name, - const casa::MPosition &position) const; void initReferenceDirections(); void initDimensions(); - bool hasColumn(const string &column) const; - bool hasColumn(const casa::Table &table, const string &column) const; void createVisibilityColumn(const string &name); void createCovarianceColumn(const string &name); - bool hasSubTable(const string &table) const; - casa::Table getSubTable(const string &table) const; - casa::MDirection getColumnPhaseReference(const string &column) const; casa::Table getVisSelection(casa::Table table, @@ -126,6 +117,16 @@ private: unsigned int itsIdDataDescription; }; +Instrument::Ptr readInstrument(const casa::MeasurementSet &ms, + unsigned int idObservation = 0); +casa::MDirection readPhaseReference(const casa::MeasurementSet &ms, + unsigned int idField = 0); +casa::MDirection readDelayReference(const casa::MeasurementSet &ms, + unsigned int idField = 0); +casa::MDirection readTileReference(const casa::MeasurementSet &ms, + unsigned int idField = 0); +double readFreqReference(const casa::MeasurementSet &ms, + unsigned int idDataDescription = 0); // @} } //# namespace BBS diff --git a/CEP/Calibration/BBSKernel/include/BBSKernel/MeasurementExprLOFAR.h b/CEP/Calibration/BBSKernel/include/BBSKernel/MeasurementExprLOFAR.h index d9e4ad4d7ef0561424c9286c45e4f6dc742ec5fc..e6f0a273780563468ea7035ea105a27c1fb8cf2b 100644 --- a/CEP/Calibration/BBSKernel/include/BBSKernel/MeasurementExprLOFAR.h +++ b/CEP/Calibration/BBSKernel/include/BBSKernel/MeasurementExprLOFAR.h @@ -38,7 +38,6 @@ #include <BBSKernel/VisBuffer.h> #include <BBSKernel/Expr/CachePolicy.h> #include <BBSKernel/Expr/Expr.h> -#include <BBSKernel/Expr/HamakerDipole.h> #include <BBSKernel/Expr/Scope.h> #include <BBSKernel/Expr/Source.h> #include <ParmDB/ParmDB.h> @@ -64,7 +63,7 @@ public: MeasurementExprLOFAR(SourceDB &sourceDB, const BufferMap &buffers, const ModelConfig &config, - const Instrument::Ptr &instrument, + const Instrument::ConstPtr &instrument, const BaselineSeq &baselines, double refFreq, const casa::MDirection &refPhase, @@ -105,7 +104,7 @@ private: void makeForwardExpr(SourceDB &sourceDB, const BufferMap &buffers, const ModelConfig &config, - const Instrument::Ptr &instrument, + const Instrument::ConstPtr &instrument, double refFreq, const casa::MDirection &refPhase, const casa::MDirection &refDelay, diff --git a/CEP/Calibration/BBSKernel/include/BBSKernel/MeasurementExprLOFARUtil.h b/CEP/Calibration/BBSKernel/include/BBSKernel/MeasurementExprLOFARUtil.h index f7bcc096fcf0e4572879518e00839961693014c0..a95ed4e5afb3bd8f3aec9e462b39a5ba62da0637 100644 --- a/CEP/Calibration/BBSKernel/include/BBSKernel/MeasurementExprLOFARUtil.h +++ b/CEP/Calibration/BBSKernel/include/BBSKernel/MeasurementExprLOFARUtil.h @@ -43,8 +43,6 @@ namespace LOFAR { namespace BBS { -class HamakerBeamCoeff; - // \addtogroup BBSKernel // @{ @@ -108,9 +106,7 @@ makeBeamExpr(Scope &scope, const Expr<Vector<3> >::Ptr &exprITRF, const Expr<Vector<3> >::Ptr &exprRefDelayITRF, const Expr<Vector<3> >::Ptr &exprRefTileITRF, - const BeamConfig &config, - const HamakerBeamCoeff &coeffLBA, - const HamakerBeamCoeff &coeffHBA); + const BeamConfig &config); Expr<JonesMatrix>::Ptr makeDirectionalTECExpr(Scope &scope, diff --git a/CEP/Calibration/BBSKernel/include/BBSKernel/ModelConfig.h b/CEP/Calibration/BBSKernel/include/BBSKernel/ModelConfig.h index 82d922dc16f86f936dcc7df4e0e422075bca6ec0..ef63b0b05bdaa84ddcde72a416d16a9537562959 100644 --- a/CEP/Calibration/BBSKernel/include/BBSKernel/ModelConfig.h +++ b/CEP/Calibration/BBSKernel/include/BBSKernel/ModelConfig.h @@ -31,8 +31,6 @@ #include <Common/lofar_vector.h> #include <Common/lofar_iosfwd.h> -#include <casa/OS/Path.h> - namespace LOFAR { namespace BBS @@ -54,11 +52,10 @@ public: }; BeamConfig(); - BeamConfig(Mode mode, bool conjugateAF, const casa::Path &elementPath); + BeamConfig(Mode mode, bool conjugateAF); Mode mode() const; bool conjugateAF() const; - const casa::Path &getElementPath() const; static bool isDefined(Mode in); static Mode asMode(const string &in); @@ -67,7 +64,6 @@ public: private: Mode itsMode; bool itsConjugateAF; - casa::Path itsElementPath; }; // Configuration options specific to the ionospheric model. diff --git a/CEP/Calibration/BBSKernel/include/BBSKernel/StationExprLOFAR.h b/CEP/Calibration/BBSKernel/include/BBSKernel/StationExprLOFAR.h index e62521134e70881651f4fb69d4eee2ccc8bef5c9..ab8556c6b3056db594b3825efc3cfd8e9fa9c94d 100644 --- a/CEP/Calibration/BBSKernel/include/BBSKernel/StationExprLOFAR.h +++ b/CEP/Calibration/BBSKernel/include/BBSKernel/StationExprLOFAR.h @@ -36,7 +36,6 @@ #include <BBSKernel/Expr/CachePolicy.h> #include <BBSKernel/Expr/Expr.h> #include <BBSKernel/Expr/ExprValue.h> -#include <BBSKernel/Expr/HamakerDipole.h> #include <BBSKernel/Expr/Scope.h> #include <ParmDB/SourceDB.h> #include <measures/Measures/MDirection.h> @@ -87,7 +86,7 @@ private: void initialize(SourceDB &sourceDB, const BufferMap &buffers, const ModelConfig &config, - const Instrument::Ptr &instrument, + const Instrument::ConstPtr &instrument, double refFreq, const casa::MDirection &refPhase, const casa::MDirection &refDelay, diff --git a/CEP/Calibration/BBSKernel/include/BBSKernel/StationResponse.h b/CEP/Calibration/BBSKernel/include/BBSKernel/StationResponse.h index 38336154120064855b4ff0813b997c99d5b7472c..5541def25a4d392c1cfa8d80ec2d3dae266f0a18 100644 --- a/CEP/Calibration/BBSKernel/include/BBSKernel/StationResponse.h +++ b/CEP/Calibration/BBSKernel/include/BBSKernel/StationResponse.h @@ -38,7 +38,6 @@ #include <ms/MeasurementSets/MeasurementSet.h> #include <measures/Measures/MDirection.h> -#include <BBSKernel/Expr/HamakerDipole.h> namespace LOFAR { @@ -108,9 +107,6 @@ public: // Set the tile delay reference direction (used by the tile beamformer). void setRefTile(const casa::MDirection &reference); - // Set the reference orientation of the +X dipole. - void setRefOrientation(double orientation); - // Set the direction of interest. void setDirection(const casa::MDirection &direction); @@ -125,11 +121,6 @@ public: const JonesMatrix::View evaluate(unsigned int i); private: - Instrument::Ptr initInstrument(const casa::MeasurementSet &ms) const; - Station::Ptr initStation(const casa::MeasurementSet &ms, unsigned int id, - const string &name, const casa::MPosition &position) const; - double getReferenceFreq(const casa::MeasurementSet &ms) const; - // Right multiply \p lhs by \p rhs. Return \p rhs if \p lhs is // uninitialized. Expr<JonesMatrix>::Ptr compose(const Expr<JonesMatrix>::Ptr &lhs, @@ -137,7 +128,6 @@ private: Dummy<Vector<2> >::Ptr itsRefDelay; Dummy<Vector<2> >::Ptr itsRefTile; - Dummy<Scalar>::Ptr itsRefOrientation; Dummy<Vector<2> >::Ptr itsDirection; vector<Expr<JonesMatrix>::Ptr> itsExpr; Request itsRequest; diff --git a/CEP/Calibration/BBSKernel/src/CMakeLists.txt b/CEP/Calibration/BBSKernel/src/CMakeLists.txt index 7608e00f472ce181e3d709defe7680c2cfbe7fe8..153c6abe659478855401920d2d520bcfdc01ad0a 100644 --- a/CEP/Calibration/BBSKernel/src/CMakeLists.txt +++ b/CEP/Calibration/BBSKernel/src/CMakeLists.txt @@ -2,7 +2,7 @@ include(LofarPackageVersion) -add_subdirectory(Contrib) +#add_subdirectory(Contrib) lofar_add_library(bbskernel Package__Version.cc @@ -31,7 +31,9 @@ lofar_add_library(bbskernel VisDimensions.cc VisEquator.cc VisSelection.cc - Expr/AntennaFieldAzEl.cc + Expr/AntennaElementLBA.cc + Expr/AntennaElementHBA.cc + Expr/AntennaFieldThetaPhi.cc Expr/AzEl.cc Expr/CachePolicy.cc Expr/Cache.cc @@ -52,7 +54,6 @@ lofar_add_library(bbskernel Expr/FlagArray.cc Expr/GaussianCoherence.cc Expr/GaussianSource.cc - Expr/HamakerDipole.cc Expr/IonPhaseShift.cc Expr/ITRFDirection.cc Expr/LinearToCircularRL.cc @@ -69,6 +70,7 @@ lofar_add_library(bbskernel Expr/MatrixRep.cc Expr/MatrixSum.cc Expr/MatrixTmp.cc + Expr/ParallacticRotation.cc Expr/PhaseShift.cc Expr/PiercePoint.cc Expr/PointCoherence.cc @@ -91,4 +93,4 @@ lofar_add_library(bbskernel Expr/Timer.cc) # Because we're using dlopen() -target_link_libraries(bbskernel ${CMAKE_DL_LIBS}) +#target_link_libraries(bbskernel ${CMAKE_DL_LIBS}) diff --git a/CEP/Calibration/BBSKernel/src/Contrib/CMakeLists.txt b/CEP/Calibration/BBSKernel/src/Contrib/CMakeLists.txt index 36a016d81e5ef8c4e341085fe9573e0a9142ce62..c633d91530b9ee6bb67194c89698cc894929d421 100644 --- a/CEP/Calibration/BBSKernel/src/Contrib/CMakeLists.txt +++ b/CEP/Calibration/BBSKernel/src/Contrib/CMakeLists.txt @@ -1,4 +1,4 @@ # $Id$ -#add_subdirectory(SBY_DipoleBeam) +add_subdirectory(SBY_DipoleBeam) add_subdirectory(JPH_DipoleBeam) diff --git a/CEP/Calibration/BBSKernel/src/ElementBeamExpr.cc b/CEP/Calibration/BBSKernel/src/ElementBeamExpr.cc deleted file mode 100644 index d286b894bef634ef875345fb048caafe650cef53..0000000000000000000000000000000000000000 --- a/CEP/Calibration/BBSKernel/src/ElementBeamExpr.cc +++ /dev/null @@ -1,115 +0,0 @@ -//# ElementBeamExpr.cc: Wrapper class that constructs the correct beam expr based on the BeamConfig instance provided in the constructor. It also caches any shared auxilliary data. -//# -//# Copyright (C) 2009 -//# ASTRON (Netherlands Institute for Radio Astronomy) -//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands -//# -//# This file is part of the LOFAR software suite. -//# The LOFAR software suite is free software: you can redistribute it and/or -//# modify it under the terms of the GNU General Public License as published -//# by the Free Software Foundation, either version 3 of the License, or -//# (at your option) any later version. -//# -//# The LOFAR software suite 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 General Public License for more details. -//# -//# You should have received a copy of the GNU General Public License along -//# with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>. -//# -//# $Id$ - -#include <lofar_config.h> -#include <BBSKernel/ElementBeamExpr.h> -#include <BBSKernel/Exceptions.h> -#include <BBSKernel/ModelConfig.h> -#include <BBSKernel/Expr/YatawattaDipole.h> - -namespace LOFAR -{ -namespace BBS -{ - -ElementBeamExpr::~ElementBeamExpr() -{ -} - -ElementBeamExpr::Ptr ElementBeamExpr::create(const BeamConfig &config, - Scope &scope) -{ - LOG_INFO_STR("Using element beam type: " - << BeamConfig::asString(config.getElementType())); - ASSERT(BeamConfig::isDefined(config.getElementType())); - - switch(config.getElementType()) - { - case BeamConfig::HAMAKER_LBA: - case BeamConfig::HAMAKER_HBA: - { - return ElementBeamExpr::Ptr(new HamakerBeamExpr(config, scope)); - } - - case BeamConfig::YATAWATTA_LBA: - case BeamConfig::YATAWATTA_HBA: - { - return ElementBeamExpr::Ptr(new YatawattaBeamExpr(config, scope)); - } - - default: - THROW(BBSKernelException, "Unsupported element type encountered."); - } -} - -HamakerBeamExpr::HamakerBeamExpr(const BeamConfig &config, Scope&) -{ - ASSERT(config.getElementType() == BeamConfig::HAMAKER_LBA - || config.getElementType() == BeamConfig::HAMAKER_HBA); - - casa::Path path = config.getElementPath(); - path.append("element_beam_" + BeamConfig::asString(config.getElementType()) - + ".coeff"); - LOG_INFO_STR("Element beam config file: " << path.expandedName()); - - // Read beam coefficients from file. - itsCoeff.init(path); -} - -Expr<JonesMatrix>::Ptr -HamakerBeamExpr::construct(const Expr<Vector<2> >::ConstPtr &direction, - const Expr<Scalar>::ConstPtr &orientation) const -{ - return Expr<JonesMatrix>::Ptr(new HamakerDipole(itsCoeff, direction, - orientation)); -} - -YatawattaBeamExpr::YatawattaBeamExpr(const BeamConfig &config, Scope&) -{ - ASSERT(config.getElementType() == BeamConfig::YATAWATTA_LBA - || config.getElementType() == BeamConfig::YATAWATTA_HBA); - - // TODO: Transparantly handle platforms that use a different extension for - // loadable modules. - itsModulePath[0] = config.getElementPath(); - itsModulePath[0].append("element_beam_" - + BeamConfig::asString(config.getElementType()) + "_theta.so"); - - itsModulePath[1] = config.getElementPath(); - itsModulePath[1].append("element_beam_" - + BeamConfig::asString(config.getElementType()) + "_phi.so"); - - LOG_INFO_STR("Element beam loadable modules: [" - << itsModulePath[0].expandedName() << "," - << itsModulePath[1].expandedName() << "]"); -} - -Expr<JonesMatrix>::Ptr -YatawattaBeamExpr::construct(const Expr<Vector<2> >::ConstPtr &direction, - const Expr<Scalar>::ConstPtr &orientation) const -{ - return Expr<JonesMatrix>::Ptr(new YatawattaDipole(itsModulePath[0], - itsModulePath[1], direction, orientation)); -} - -} //# namespace BBS -} //# namespace LOFAR diff --git a/CEP/Calibration/BBSKernel/src/Expr/AntennaElementHBA.cc b/CEP/Calibration/BBSKernel/src/Expr/AntennaElementHBA.cc new file mode 100644 index 0000000000000000000000000000000000000000..90ec9c88fa4fb7635167a4835ebc12707ad2d8a8 --- /dev/null +++ b/CEP/Calibration/BBSKernel/src/Expr/AntennaElementHBA.cc @@ -0,0 +1,100 @@ +//# AntennaElementHBA.cc: Model of an idealized LOFAR HBA dual dipole antenna +//# element. +//# +//# Copyright (C) 2011 +//# ASTRON (Netherlands Institute for Radio Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +//# +//# This file is part of the LOFAR software suite. +//# The LOFAR software suite is free software: you can redistribute it and/or +//# modify it under the terms of the GNU General Public License as published +//# by the Free Software Foundation, either version 3 of the License, or +//# (at your option) any later version. +//# +//# The LOFAR software suite 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License along +//# with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>. +//# +//# $Id$ + +#include <lofar_config.h> +#include <BBSKernel/Expr/AntennaElementHBA.h> +#include <ElementResponse/ElementResponse.h> +#include <casa/BasicSL/Constants.h> + +namespace LOFAR +{ +namespace BBS +{ + +AntennaElementHBA::AntennaElementHBA(const Expr<Vector<2> >::ConstPtr &target) + : BasicUnaryExpr<Vector<2>, JonesMatrix>(target) +{ +} + +const JonesMatrix::View AntennaElementHBA::evaluateImpl(const Grid &grid, + const Vector<2>::View &target) const +{ + const size_t nFreq = grid[FREQ]->size(); + const size_t nTime = grid[TIME]->size(); + + // Check preconditions. + ASSERT(!target(0).isComplex() && target(0).nx() == 1 + && static_cast<size_t>(target(0).ny()) == nTime); + ASSERT(!target(1).isComplex() && target(1).nx() == 1 + && static_cast<size_t>(target(1).ny()) == nTime); + + // Get pointers to input and output data. + const double *theta = target(0).doubleStorage(); + const double *phi = target(1).doubleStorage(); + + Matrix E00, E01, E10, E11; + double *E00_re, *E00_im; + E00.setDCMat(nFreq, nTime); + E00.dcomplexStorage(E00_re, E00_im); + + double *E01_re, *E01_im; + E01.setDCMat(nFreq, nTime); + E01.dcomplexStorage(E01_re, E01_im); + + double *E10_re, *E10_im; + E10.setDCMat(nFreq, nTime); + E10.dcomplexStorage(E10_re, E10_im); + + double *E11_re, *E11_im; + E11.setDCMat(nFreq, nTime); + E11.dcomplexStorage(E11_re, E11_im); + + // Evaluate antenna model. + dcomplex J[2][2]; + for(size_t i = 0; i < nTime; ++i) + { + for(size_t j = 0; j < nFreq; ++j) + { + // The positive X dipole direction is SW of the reference + // orientation, which translates to a phi coordinate of 5/4*pi in + // the topocentric spherical coordinate system. The phi coordinate + // is corrected for this offset before evaluating the antenna model. + element_response_hba(grid[FREQ]->center(j), theta[i], + phi[i] - 5.0 * casa::C::pi_4, J); + + *E00_re++ = real(J[0][0]); + *E00_im++ = imag(J[0][0]); + *E01_re++ = real(J[0][1]); + *E01_im++ = imag(J[0][1]); + *E10_re++ = real(J[1][0]); + *E10_im++ = imag(J[1][0]); + *E11_re++ = real(J[1][1]); + *E11_im++ = imag(J[1][1]); + } + } + + return JonesMatrix::View(E00, E01, E10, E11); +} + +} //# namespace BBS +} //# namespace LOFAR diff --git a/CEP/Calibration/BBSKernel/src/Expr/AntennaElementLBA.cc b/CEP/Calibration/BBSKernel/src/Expr/AntennaElementLBA.cc new file mode 100644 index 0000000000000000000000000000000000000000..d8446801832a4b44ae00f32dd0446a6b0be3c0b3 --- /dev/null +++ b/CEP/Calibration/BBSKernel/src/Expr/AntennaElementLBA.cc @@ -0,0 +1,100 @@ +//# AntennaElementLBA.cc: Model of an idealized LOFAR LBA dual dipole antenna +//# element. +//# +//# Copyright (C) 2011 +//# ASTRON (Netherlands Institute for Radio Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +//# +//# This file is part of the LOFAR software suite. +//# The LOFAR software suite is free software: you can redistribute it and/or +//# modify it under the terms of the GNU General Public License as published +//# by the Free Software Foundation, either version 3 of the License, or +//# (at your option) any later version. +//# +//# The LOFAR software suite 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License along +//# with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>. +//# +//# $Id$ + +#include <lofar_config.h> +#include <BBSKernel/Expr/AntennaElementLBA.h> +#include <ElementResponse/ElementResponse.h> +#include <casa/BasicSL/Constants.h> + +namespace LOFAR +{ +namespace BBS +{ + +AntennaElementLBA::AntennaElementLBA(const Expr<Vector<2> >::ConstPtr &target) + : BasicUnaryExpr<Vector<2>, JonesMatrix>(target) +{ +} + +const JonesMatrix::View AntennaElementLBA::evaluateImpl(const Grid &grid, + const Vector<2>::View &target) const +{ + const size_t nFreq = grid[FREQ]->size(); + const size_t nTime = grid[TIME]->size(); + + // Check preconditions. + ASSERT(!target(0).isComplex() && target(0).nx() == 1 + && static_cast<size_t>(target(0).ny()) == nTime); + ASSERT(!target(1).isComplex() && target(1).nx() == 1 + && static_cast<size_t>(target(1).ny()) == nTime); + + // Get pointers to input and output data. + const double *theta = target(0).doubleStorage(); + const double *phi = target(1).doubleStorage(); + + Matrix E00, E01, E10, E11; + double *E00_re, *E00_im; + E00.setDCMat(nFreq, nTime); + E00.dcomplexStorage(E00_re, E00_im); + + double *E01_re, *E01_im; + E01.setDCMat(nFreq, nTime); + E01.dcomplexStorage(E01_re, E01_im); + + double *E10_re, *E10_im; + E10.setDCMat(nFreq, nTime); + E10.dcomplexStorage(E10_re, E10_im); + + double *E11_re, *E11_im; + E11.setDCMat(nFreq, nTime); + E11.dcomplexStorage(E11_re, E11_im); + + // Evaluate antenna model. + dcomplex J[2][2]; + for(size_t i = 0; i < nTime; ++i) + { + for(size_t j = 0; j < nFreq; ++j) + { + // The positive X dipole direction is SW of the reference + // orientation, which translates to a phi coordinate of 5/4*pi in + // the topocentric spherical coordinate system. The phi coordinate + // is corrected for this offset before evaluating the antenna model. + element_response_lba(grid[FREQ]->center(j), theta[i], + phi[i] - 5.0 * casa::C::pi_4, J); + + *E00_re++ = real(J[0][0]); + *E00_im++ = imag(J[0][0]); + *E01_re++ = real(J[0][1]); + *E01_im++ = imag(J[0][1]); + *E10_re++ = real(J[1][0]); + *E10_im++ = imag(J[1][0]); + *E11_re++ = real(J[1][1]); + *E11_im++ = imag(J[1][1]); + } + } + + return JonesMatrix::View(E00, E01, E10, E11); +} + +} //# namespace BBS +} //# namespace LOFAR diff --git a/CEP/Calibration/BBSKernel/src/Expr/AntennaFieldAzEl.cc b/CEP/Calibration/BBSKernel/src/Expr/AntennaFieldThetaPhi.cc similarity index 53% rename from CEP/Calibration/BBSKernel/src/Expr/AntennaFieldAzEl.cc rename to CEP/Calibration/BBSKernel/src/Expr/AntennaFieldThetaPhi.cc index 567ac7932f0a61491e2f9a876359c5c3d2eef116..3455e296c705d1429c8aa6c1dd691e1fff55986a 100644 --- a/CEP/Calibration/BBSKernel/src/Expr/AntennaFieldAzEl.cc +++ b/CEP/Calibration/BBSKernel/src/Expr/AntennaFieldThetaPhi.cc @@ -1,9 +1,11 @@ -//# AntennaFieldAzEl.cc: Compute azimuth and elevation in radians relevative to -//# the antenna field coordinate system (P, Q, R). The input direction as well -//# as the positive coordinate axes are assumed to be unit vectors expressed in -//# ITRF. Zero azimuth corresponds to the positive Q axis and positive azimuth -//# runs from the positive Q axis to the positive P axis. Elevation is the angle -//# the direction makes with the (P, Q) plane. +//# AntennaFieldThetaPhi.cc: Compute topocentric (local) theta and phi spherical +//# coordinates (in radians) relative to the Cartesian antenna field coordinate +//# system (PQR), for a given target direction. The target direction is assumed +//# to be an ITRF unit vector in the direction of arrival. The positive +//# coordinate axes are assumed to be ITRF unit vectors. Zero phi corresponds to +//# the positive P axis, and positive phi runs from the positive P axis towards +//# the positive Q axis (roughly East over North). Theta or zenith angle is the +//# angle the target direction makes with the positive R axis. //# //# Copyright (C) 2011 //# ASTRON (Netherlands Institute for Radio Astronomy) @@ -26,7 +28,7 @@ //# $Id$ #include <lofar_config.h> -#include <BBSKernel/Expr/AntennaFieldAzEl.h> +#include <BBSKernel/Expr/AntennaFieldThetaPhi.h> #include <casa/BasicSL/Constants.h> namespace LOFAR @@ -34,14 +36,14 @@ namespace LOFAR namespace BBS { -AntennaFieldAzEl::AntennaFieldAzEl(const Expr<Vector<3> >::ConstPtr &direction, +AntennaFieldThetaPhi::AntennaFieldThetaPhi(const Expr<Vector<3> >::ConstPtr &direction, const AntennaField::ConstPtr &field) : BasicUnaryExpr<Vector<3>, Vector<2> >(direction), itsField(field) { } -const Vector<2>::View AntennaFieldAzEl::evaluateImpl(const Grid&, +const Vector<2>::View AntennaFieldThetaPhi::evaluateImpl(const Grid&, const Vector<3>::View &direction) const { // Check preconditions. @@ -61,19 +63,27 @@ const Vector<2>::View AntennaFieldAzEl::evaluateImpl(const Grid&, + direction(2) * q[2]; // Compute the inner product between the antenna field normal (R) and the - // direction vector to get the sine of the elevation (cosine of the zenith - // angle). - Matrix sinEl = direction(0) * r[0] + direction(1) * r[1] + // direction vector to get the cosine of the zenith angle (sine of the + // elevation). + Matrix projectionR = direction(0) * r[0] + direction(1) * r[1] + direction(2) * r[2]; - // Compute azimuth and elevation. Zero azimuth corresponds to the positive Q - // axis and positive azimuth runs from the positive Q axis to the positive P - // axis. Elevation is computed by taking the arcsine of the angle computed - // earlier. - Vector<2>::View azel; - azel.assign(0, atan2(projectionP, projectionQ)); - azel.assign(1, asin(sinEl)); - return azel; + // Compute theta and phi. Zero phi corresponds to the positive P axis and + // positive phi runs from the positive P axis to the positive Q axis. + Vector<2>::View result; + result.assign(0, acos(projectionR)); + result.assign(1, atan2(projectionQ, projectionP)); + +// LOG_DEBUG_STR("EP: [" << p[0] << ", " << p[1] << ", " << p[2] << "]"); +// LOG_DEBUG_STR("EQ: [" << q[0] << ", " << q[1] << ", " << q[2] << "]"); +// LOG_DEBUG_STR("ER: [" << r[0] << ", " << r[1] << ", " << r[2] << "]"); +// LOG_DEBUG_STR("X: " << direction(0)); +// LOG_DEBUG_STR("Y: " << direction(1)); +// LOG_DEBUG_STR("Z: " << direction(2)); +// LOG_DEBUG_STR("THETA: " << result(0)); +// LOG_DEBUG_STR("PHI: " << result(1)); + + return result; } } //# namespace BBS diff --git a/CEP/Calibration/BBSKernel/src/Expr/HamakerDipole.cc b/CEP/Calibration/BBSKernel/src/Expr/HamakerDipole.cc deleted file mode 100644 index c157c52a1981601cf80c8161d4e7f82968f41f7e..0000000000000000000000000000000000000000 --- a/CEP/Calibration/BBSKernel/src/Expr/HamakerDipole.cc +++ /dev/null @@ -1,261 +0,0 @@ -//# HamakerDipole.cc: Implementation of J.P. Hamaker's memo -//# "Mathematical-physical analysis of the generic dual-dipole antenna". -//# -//# Copyright (C) 2008 -//# ASTRON (Netherlands Institute for Radio Astronomy) -//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands -//# -//# This file is part of the LOFAR software suite. -//# The LOFAR software suite is free software: you can redistribute it and/or -//# modify it under the terms of the GNU General Public License as published -//# by the Free Software Foundation, either version 3 of the License, or -//# (at your option) any later version. -//# -//# The LOFAR software suite 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 General Public License for more details. -//# -//# You should have received a copy of the GNU General Public License along -//# with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>. -//# -//# $Id$ - -#include <lofar_config.h> - -#include <BBSKernel/Expr/HamakerDipole.h> -#include <BBSKernel/Exceptions.h> - -#include <casa/BasicSL/Constants.h> -#include <casa/OS/Path.h> - -namespace LOFAR -{ -namespace BBS -{ - -HamakerBeamCoeff::HamakerBeamCoeff() - : itsCenter(0.0), - itsWidth(1.0) -{ -} - -void HamakerBeamCoeff::init(const casa::Path &coeffFile) -{ - // Open file. - casa::String path = coeffFile.expandedName(); - ifstream in(path.c_str()); - if(!in) - { - THROW(BBSKernelException, "" << path << ": unable to open file"); - } - - // Read file header. - string header, token0, token1, token2, token3, token4, token5; - getline(in, header); - - size_t nElements, nHarmonics, nPowerTime, nPowerFreq; - double freqAvg, freqRange; - - istringstream iss(header); - iss >> token0 >> nElements >> token1 >> nHarmonics >> token2 >> nPowerTime - >> token3 >> nPowerFreq >> token4 >> freqAvg >> token5 >> freqRange; - - if(!in || !iss || token0 != "d" || token1 != "k" || token2 != "pwrT" - || token3 != "pwrF" || token4 != "freqAvg" || token5 != "freqRange") - { - THROW(BBSKernelException, "" << path << ": unable to parse header"); - } - - if(nElements * nHarmonics * nPowerTime * nPowerFreq == 0) - { - THROW(BBSKernelException, "" << path << ": the number of coefficients" - " should be larger than zero."); - } - - LOG_DEBUG_STR("" << path << ": nElements: " << nElements << " nHarmonics: " - << nHarmonics << " nPowerTime: " << nPowerTime << " nPowerFreq: " - << nPowerFreq); - - // Allocate coefficient matrix. - itsCenter = freqAvg; - itsWidth = freqRange; - itsCoeff = casa::Array<dcomplex>(casa::IPosition(4, nPowerFreq, nPowerTime, - nHarmonics, nElements)); - - size_t nCoeff = 0; - while(in.good()) - { - // Read line from file. - string line; - getline(in, line); - - // Skip lines that contain only whitespace. - if(line.find_last_not_of(" ") == string::npos) - { - continue; - } - - // Parse line. - size_t element, harmonic, powerTime, powerFreq; - double re, im; - - iss.clear(); - iss.str(line); - iss >> element >> harmonic >> powerTime >> powerFreq >> re >> im; - - if(!iss || element >= nElements || harmonic >= nHarmonics - || powerTime >= nPowerTime || powerFreq >= nPowerFreq) - { - THROW(BBSKernelException, "" << path << ": errror reading file."); - } - - // Store coefficient. - itsCoeff(casa::IPosition(4, powerFreq, powerTime, harmonic, element)) = - makedcomplex(re, im); - - // Update coefficient counter. - ++nCoeff; - } - - if(!in.eof()) - { - THROW(BBSKernelException, "" << path << ": error reading file."); - } - - if(nCoeff != nElements * nHarmonics * nPowerTime * nPowerFreq) - { - THROW(BBSKernelException, "" << path << ": the number of coefficients" - " specified in the header does not match the number of coefficients" - " in the file."); - } -} - -HamakerDipole::HamakerDipole(const HamakerBeamCoeff &coeff, - const Expr<Vector<2> >::ConstPtr &azel, - const Expr<Scalar>::ConstPtr &orientation) - : BasicBinaryExpr<Vector<2>, Scalar, JonesMatrix>(azel, orientation), - itsCoeff(coeff) -{ -} - -const JonesMatrix::View HamakerDipole::evaluateImpl(const Grid &grid, - const Vector<2>::View &azel, const Scalar::View &orientation) const -{ - const size_t nFreq = grid[FREQ]->size(); - const size_t nTime = grid[TIME]->size(); - - // Check preconditions. - ASSERT(static_cast<size_t>(azel(0).nelements()) == nTime); - ASSERT(static_cast<size_t>(azel(1).nelements()) == nTime); - ASSERT(static_cast<size_t>(orientation().nelements()) == 1); - - // Get pointers to input and output data. - const double *az = azel(0).doubleStorage(); - const double *el = azel(1).doubleStorage(); - const double angle = orientation().getDouble(0, 0); - - Matrix E00, E01, E10, E11; - double *E00_re, *E00_im; - E00.setDCMat(nFreq, nTime); - E00.dcomplexStorage(E00_re, E00_im); - - double *E01_re, *E01_im; - E01.setDCMat(nFreq, nTime); - E01.dcomplexStorage(E01_re, E01_im); - - double *E10_re, *E10_im; - E10.setDCMat(nFreq, nTime); - E10.dcomplexStorage(E10_re, E10_im); - - double *E11_re, *E11_im; - E11.setDCMat(nFreq, nTime); - E11.dcomplexStorage(E11_re, E11_im); - - // Evaluate beam. - const unsigned int nHarmonics = itsCoeff.shape(1); - const unsigned int nPowTheta = itsCoeff.shape(2); - const unsigned int nPowFreq = itsCoeff.shape(3); - - for(size_t t = 0; t < nTime; ++t) - { - // Correct azimuth for dipole orientation. - const double phi = az[t] - angle; - - // NB: The model is parameterized in terms of zenith angle. The - // appropriate conversion is taken care of below. - const double theta = casa::C::pi_2 - el[t]; - - for(size_t f = 0; f < nFreq; ++f) - { - // J-jones matrix (2x2 complex matrix) - dcomplex J[2][2] = {{0.0, 0.0}, {0.0, 0.0}}; - - // Only compute the beam response for directions above the horizon. - if(theta < casa::C::pi_2) - { - // NB: The model is parameterized in terms of a normalized - // frequency in the range [-1, 1]. The appropriate conversion is - // taken care of below. - const double normFreq = (grid[FREQ]->center(f) - - itsCoeff.center()) / itsCoeff.width(); - - for(size_t k = 0; k < nHarmonics; ++k) - { - // Compute diagonal projection matrix P for the current - // harmonic. - dcomplex P[2] = {0.0, 0.0}; - - dcomplex inner[2]; - for(long i = nPowTheta - 1; i >= 0; --i) - { - inner[0] = itsCoeff(0, k, i, nPowFreq - 1); - inner[1] = itsCoeff(1, k, i, nPowFreq - 1); - - for(long j = nPowFreq - 2; j >= 0; --j) - { - inner[0] = - inner[0] * normFreq + itsCoeff(0, k, i, j); - inner[1] = - inner[1] * normFreq + itsCoeff(1, k, i, j); - } - P[0] = P[0] * theta + inner[0]; - P[1] = P[1] * theta + inner[1]; - } - - // Compute Jones matrix for this harmonic by rotating P over - // kappa * phi and add it to the result. - const double kappa = - ((k & 1) == 0 ? 1.0 : -1.0) * (2.0 * k + 1.0); - const double cphi = std::cos(kappa * phi); - const double sphi = std::sin(kappa * phi); - - J[0][0] += cphi * P[0]; - J[0][1] += -sphi * P[1]; - J[1][0] += sphi * P[0]; - J[1][1] += cphi * P[1]; - } - } - - *E00_re++ = real(J[0][0]); - *E00_im++ = imag(J[0][0]); - *E01_re++ = real(J[0][1]); - *E01_im++ = imag(J[0][1]); - *E10_re++ = real(J[1][0]); - *E10_im++ = imag(J[1][0]); - *E11_re++ = real(J[1][1]); - *E11_im++ = imag(J[1][1]); - } - } - - JonesMatrix::View result; - result.assign(0, 0, E00); - result.assign(0, 1, E01); - result.assign(1, 0, E10); - result.assign(1, 1, E11); - - return result; -} - -} //# namespace BBS -} //# namespace LOFAR diff --git a/CEP/Calibration/BBSKernel/src/Expr/ParallacticRotation.cc b/CEP/Calibration/BBSKernel/src/Expr/ParallacticRotation.cc new file mode 100644 index 0000000000000000000000000000000000000000..50fe91836a62c5c9164e02766d424a72125fa86f --- /dev/null +++ b/CEP/Calibration/BBSKernel/src/Expr/ParallacticRotation.cc @@ -0,0 +1,166 @@ +//# ParallacticRotation.cc: Jones matrix that relates the (X,Y)-frame used to +//# express polarization on the sky (according to the IAU definition) to the +//# topocentric (theta,phi)-frame. Both are Cartesian frames defined on the +//# tangent plane, with +X towards the North, +Y towards the East, +theta away +//# from the (pseudo) zenith, and +phi East over North around the (pseudo) +//# zenith. +//# +//# Copyright (C) 2011 +//# ASTRON (Netherlands Institute for Radio Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +//# +//# This file is part of the LOFAR software suite. +//# The LOFAR software suite is free software: you can redistribute it and/or +//# modify it under the terms of the GNU General Public License as published +//# by the Free Software Foundation, either version 3 of the License, or +//# (at your option) any later version. +//# +//# The LOFAR software suite 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License along +//# with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>. +//# +//# $Id$ + +#include <lofar_config.h> +#include <BBSKernel/Expr/ParallacticRotation.h> +#include <Common/LofarLogger.h> + +namespace LOFAR +{ +namespace BBS +{ + +ParallacticRotation::ParallacticRotation( + const Expr<Vector<3> >::ConstPtr &target, + const AntennaField::ConstPtr &field) + : BasicUnaryExpr<Vector<3>, JonesMatrix>(target), + itsField(field) +{ +} + +const JonesMatrix::View ParallacticRotation::evaluateImpl(const Grid &grid, + const Vector<3>::View &target) const +{ + const size_t nFreq = grid[FREQ]->size(); + const size_t nTime = grid[TIME]->size(); + + // Check preconditions. + ASSERT(!target(0).isComplex() && target(0).nx() == 1 + && static_cast<size_t>(target(0).ny()) == nTime); + ASSERT(!target(1).isComplex() && target(1).nx() == 1 + && static_cast<size_t>(target(1).ny()) == nTime); + ASSERT(!target(2).isComplex() && target(2).nx() == 1 + && static_cast<size_t>(target(2).ny()) == nTime); + + // Compute the cross product of the NCP and the target direction. This + // yields a vector tangent to the celestial sphere at the target direction, + // pointing towards the East (the direction of +Y in the IAU definition, + // or positive right ascension). + Matrix v1x = -target(1); + Matrix v1y = target(0); + Matrix v1z = Matrix(0.0); + + Matrix v1norm = sqrt(sqr(v1x) + sqr(v1y) + sqr(v1z)); + v1x = v1x / v1norm; + v1y = v1y / v1norm; + v1z = v1z / v1norm; + + // Compute the cross product of the antenna field normal (R) and the target + // direction. This yields a vector tangent to the topocentric spherical + // coordinate system at the target direction, pointing towards the direction + // of positive phi (which runs East over North around the pseudo zenith). + const Vector3 &r = itsField->axis(AntennaField::R); + Matrix v2x = target(2) * r[1] - target(1) * r[2]; + Matrix v2y = target(0) * r[2] - target(2) * r[0]; + Matrix v2z = target(1) * r[0] - target(0) * r[1]; + + Matrix v2norm = sqrt(sqr(v2x) + sqr(v2y) + sqr(v2z)); + v2x = v2x / v2norm; + v2y = v2y / v2norm; + v2z = v2z / v2norm; + + // Compute the cosine and sine of the parallactic angle, i.e. the angle + // between v1 and v2, both tangent to a latitude circle of their respective + // spherical coordinate systems. + Matrix coschi = v1x * v2x + v1y * v2y + v1z * v2z; + Matrix sinchi = (v1y * v2z - v1z * v2y) * target(0) + + (v1z * v2x - v1x * v2z) * target(1) + + (v1x * v2y - v1y * v2x) * target(2); + + // The input coordinate system is a right handed system with its third axis + // along the direction of propagation (IAU +Z). The output coordinate system + // is right handed as well, but its third axis points in the direction of + // arrival (i.e. exactly opposite). + // + // Because the electromagnetic field is always perpendicular to the + // direction of propagation, we only need to relate the (X, Y) axes of the + // input system to the corresponding (theta, phi) axes of the output system. + // + // To this end, we first rotate the input system around its third axis to + // align the Y axis with the phi axis. The X and theta axis are parallel + // after this rotation, but point in opposite directions. To align the X + // axis with the theta axis, we flip it. + // + // The Jones matrix to align the Y axis with the phi axis when these are + // separated by an angle phi (measured counter-clockwise around the + // direction of propagation, looking towards the origin), is given by: + // + // [ cos(phi) sin(phi)] + // [-sin(phi) cos(phi)] + // + // Here, cos(phi) and sin(phi) can be computed directly, without having to + // compute phi first (see the computation of coschi and sinchi above). + // + // Now, sinchi as computed above is opposite to sin(phi), because the + // direction used in the computation is the direction of arrival instead + // of the direction of propagation. Therefore, the sign of sinchi needs to + // be reversed. Furthermore, as explained above, the X axis has to be + // flipped to align with the theta axis. The Jones matrix returned from this + // function is therefore given by: + // + // [-coschi sinchi] + // [ sinchi coschi] + // + // This is an improper rotation, or rotoreflection. + +// LOG_DEBUG_STR("COS: " << coschi); +// LOG_DEBUG_STR("SIN: " << sinchi); + + ASSERT(!coschi.isComplex() && coschi.nx() == 1 + && static_cast<size_t>(coschi.ny()) == nTime); + ASSERT(!sinchi.isComplex() && sinchi.nx() == 1 + && static_cast<size_t>(sinchi.ny()) == nTime); + + if(nFreq == 1) + { + return JonesMatrix::View(-coschi, sinchi, sinchi, coschi); + } + + // Create 2D arrays because MeqMatrix does not support 1D. + const double *p_coschi = coschi.doubleStorage(); + const double *p_sinchi = sinchi.doubleStorage(); + + Matrix coschi2, sinchi2; + double *p_coschi2 = coschi2.setDoubleFormat(nFreq, nTime); + double *p_sinchi2 = sinchi2.setDoubleFormat(nFreq, nTime); + + for(unsigned int t = 0; t < nTime; ++t) + { + for(unsigned int f = 0; f < nFreq; ++f) + { + *p_coschi2++ = *p_coschi; + *p_sinchi2++ = *p_sinchi; + } + ++p_coschi; + ++p_sinchi; + } + + return JonesMatrix::View(-coschi2, sinchi2, sinchi2, coschi2); +} + +} //# namespace BBS +} //# namespace LOFAR diff --git a/CEP/Calibration/BBSKernel/src/Expr/StationBeamFormer.cc b/CEP/Calibration/BBSKernel/src/Expr/StationBeamFormer.cc index fde5e02b52349a81390c0158651b3c0d2360dfe4..15dd68fa90e03318d4196f01b3182e52658a562f 100644 --- a/CEP/Calibration/BBSKernel/src/Expr/StationBeamFormer.cc +++ b/CEP/Calibration/BBSKernel/src/Expr/StationBeamFormer.cc @@ -221,7 +221,6 @@ const JonesMatrix::View StationBeamFormer::evaluateImpl(const Grid &grid, Matrix E[2][2]; Matrix AF(makedcomplex(0.0, 0.0), nFreq, nTime); - size_t countX = 0, countY = 0; for(size_t i = 0; i < itsStation->nField(); ++i) { AntennaField::ConstPtr field = itsStation->field(i); @@ -285,13 +284,11 @@ const JonesMatrix::View StationBeamFormer::evaluateImpl(const Grid &grid, if(!element.flag[0]) { AFX += AF; - ++countX; } if(!element.flag[1]) { AFY += AF; - ++countY; } } @@ -319,16 +316,13 @@ const JonesMatrix::View StationBeamFormer::evaluateImpl(const Grid &grid, } // Normalize. - if(countX > 0) + const size_t nActiveElement = itsStation->nActiveElement(); + if(nActiveElement > 0) { - E[0][0] /= countX; - E[0][1] /= countX; - } - - if(countY > 0) - { - E[1][0] /= countY; - E[1][1] /= countY; + E[0][0] /= nActiveElement; + E[0][1] /= nActiveElement; + E[1][0] /= nActiveElement; + E[1][1] /= nActiveElement; } return JonesMatrix::View(E[0][0], E[0][1], E[1][0], E[1][1]); diff --git a/CEP/Calibration/BBSKernel/src/Expr/YatawattaDipole.cc b/CEP/Calibration/BBSKernel/src/Expr/YatawattaDipole.cc deleted file mode 100644 index 6e53ed87da5de1f8c85aa0ea38c16747c069cc37..0000000000000000000000000000000000000000 --- a/CEP/Calibration/BBSKernel/src/Expr/YatawattaDipole.cc +++ /dev/null @@ -1,150 +0,0 @@ -//# YatawattaDipole.cc: Dipole voltage beam based on external functions. -//# -//# Copyright (C) 2008 -//# ASTRON (Netherlands Institute for Radio Astronomy) -//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands -//# -//# This file is part of the LOFAR software suite. -//# The LOFAR software suite is free software: you can redistribute it and/or -//# modify it under the terms of the GNU General Public License as published -//# by the Free Software Foundation, either version 3 of the License, or -//# (at your option) any later version. -//# -//# The LOFAR software suite 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 General Public License for more details. -//# -//# You should have received a copy of the GNU General Public License along -//# with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>. -//# -//# $Id$ - -#include <lofar_config.h> - -#include <BBSKernel/Expr/YatawattaDipole.h> - -#include <Common/lofar_complex.h> -#include <casa/BasicSL/Constants.h> - -namespace LOFAR -{ -namespace BBS -{ - -YatawattaDipole::YatawattaDipole(const casa::Path &moduleTheta, - const casa::Path &modulePhi, const Expr<Vector<2> >::ConstPtr &azel, - const Expr<Scalar>::ConstPtr &orientation) - : BasicBinaryExpr<Vector<2>, Scalar, JonesMatrix>(azel, orientation), - itsThetaFunction(moduleTheta, "test"), - itsPhiFunction(modulePhi, "test") -{ - ASSERT(itsThetaFunction.nArguments() == 5); - ASSERT(itsPhiFunction.nArguments() == 5); -} - -const JonesMatrix::View YatawattaDipole::evaluateImpl(const Grid &grid, - const Vector<2>::View &azel, const Scalar::View &orientation) const -{ - const size_t nFreq = grid[FREQ]->size(); - const size_t nTime = grid[TIME]->size(); - - // Check preconditions. - ASSERT(static_cast<size_t>(azel(0).nelements()) == nTime); - ASSERT(static_cast<size_t>(azel(1).nelements()) == nTime); - ASSERT(static_cast<size_t>(orientation().nelements()) == 1); - - // Get pointers to input and output data. - const double *az = azel(0).doubleStorage(); - const double *el = azel(1).doubleStorage(); - const double angle = orientation().getDouble(0, 0); - - Matrix E00, E01, E10, E11; - double *E00_re, *E00_im; - E00.setDCMat(nFreq, nTime); - E00.dcomplexStorage(E00_re, E00_im); - - double *E01_re, *E01_im; - E01.setDCMat(nFreq, nTime); - E01.dcomplexStorage(E01_re, E01_im); - - double *E10_re, *E10_im; - E10.setDCMat(nFreq, nTime); - E10.dcomplexStorage(E10_re, E10_im); - - double *E11_re, *E11_im; - E11.setDCMat(nFreq, nTime); - E11.dcomplexStorage(E11_re, E11_im); - - // Parameters for external functions: - // 0: time - // (NOTE: ignored) - // 1: frequency - // 2: az - // 3: el - // (NOTE: incorrectly labelled zenith angle in implementation!) - // 4: orientation (phi0) - - // Create argument vectors for the X and Y dipole (used for calling - // external functions). - vector<dcomplex> xArgs(5, makedcomplex(0.0, 0.0)); - vector<dcomplex> yArgs(5, makedcomplex(0.0, 0.0)); - - // TODO: Inside external function, these parameters are added to the - // azimuth. The resulting azimuth is therefore: - // - // az = az + orientation (- pi / 2.0) - // - // Whereas it seems to me that the orientation should be subtracted - // instead of added. It probably does not matter much, because the - // beam pattern is symmetric with respect to azimuth. - xArgs[4] = makedcomplex(angle, 0.0); - yArgs[4] = makedcomplex(angle - casa::C::pi_2, 0.0); - - // Evaluate beam. - for(size_t t = 0; t < nTime; ++t) - { - // TODO: Where does the -pi/4 term in azimuth come from (see - // global_model.py in EJones_HBA)? Is this just the default dipole - // orientation? If so, the term should be removed in favor of setting - // a correct dipole orientation in the parameter database (such that - // the orientation in the parameter database corresponds 1:1 with the - // real orientation). -// xArgs[2] = yArgs[2] = makedcomplex(az[t] - casa::C::pi_4, 0.0); - xArgs[2] = yArgs[2] = makedcomplex(az[t], 0.0); - xArgs[3] = yArgs[3] = makedcomplex(el[t], 0.0); - - for(size_t f = 0; f < nFreq; ++f) - { - // Update frequency. - xArgs[1] = yArgs[1] = makedcomplex(grid[FREQ]->center(f), 0.0); - - // Compute dipole beam value. - const dcomplex xTheta = itsThetaFunction(xArgs); - const dcomplex xPhi = itsPhiFunction(xArgs); - *E00_re++ = real(xTheta); - *E00_im++ = imag(xTheta); - *E01_re++ = real(xPhi); - *E01_im++ = imag(xPhi); - - const dcomplex yTheta = itsThetaFunction(yArgs); - const dcomplex yPhi = itsPhiFunction(yArgs); - *E10_re++ = real(yTheta); - *E10_im++ = imag(yTheta); - *E11_re++ = real(yPhi); - *E11_im++ = imag(yPhi); - } - } - - JonesMatrix::View result; - result.assign(0, 0, E00); - result.assign(0, 1, E01); - result.assign(1, 0, E10); - result.assign(1, 1, E11); - - return result; -} - - -} //# namespace BBS -} //# namespace LOFAR diff --git a/CEP/Calibration/BBSKernel/src/Instrument.cc b/CEP/Calibration/BBSKernel/src/Instrument.cc index f151d2acee3e455d00c332ff75e092b60ea9c916..f3031d5dda5d56b5929d7de0614c35225d841601 100644 --- a/CEP/Calibration/BBSKernel/src/Instrument.cc +++ b/CEP/Calibration/BBSKernel/src/Instrument.cc @@ -37,7 +37,8 @@ namespace BBS AntennaField::AntennaField(const string &name, const Vector3 &position, const Vector3 &p, const Vector3 &q, const Vector3 &r) : itsName(name), - itsPosition(position) + itsPosition(position), + itsActiveElementCount(0) { itsAxes[P] = p; itsAxes[Q] = q; @@ -54,7 +55,7 @@ const Vector3 &AntennaField::position() const return itsPosition; } -const Vector3 &AntennaField::axis(Axis axis) +const Vector3 &AntennaField::axis(Axis axis) const { return itsAxes[axis]; } @@ -72,6 +73,11 @@ void AntennaField::appendTileElement(const Vector3 &offset) void AntennaField::appendElement(const Element &element) { itsElements.push_back(element); + + if(!element.flag[0] || !element.flag[1]) + { + ++itsActiveElementCount; + } } Station::Station(const string &name, const casa::MPosition &position) @@ -117,6 +123,26 @@ unsigned int Station::nField() const return itsFields.size(); } +size_t Station::nElement() const +{ + size_t count = 0; + for(unsigned int i = 0; i < nField(); ++i) + { + count += field(i)->nElement(); + } + return count; +} + +size_t Station::nActiveElement() const +{ + size_t count = 0; + for(unsigned int i = 0; i < nField(); ++i) + { + count += field(i)->nActiveElement(); + } + return count; +} + AntennaField::ConstPtr Station::field(unsigned int i) const { return itsFields[i]; diff --git a/CEP/Calibration/BBSKernel/src/MeasurementAIPS.cc b/CEP/Calibration/BBSKernel/src/MeasurementAIPS.cc index 886b61e50dc30a94daa36e878b969dd998a2b945..ace130b686bac7654750f999b1d68799ba47d784 100644 --- a/CEP/Calibration/BBSKernel/src/MeasurementAIPS.cc +++ b/CEP/Calibration/BBSKernel/src/MeasurementAIPS.cc @@ -25,7 +25,7 @@ #include <BBSKernel/MeasurementAIPS.h> #include <BBSKernel/Exceptions.h> -#include <cstring> +//#include <cstring> #include <Common/Timer.h> #include <Common/lofar_algorithm.h> #include <Common/LofarLogger.h> @@ -79,6 +79,16 @@ namespace LOFAR namespace BBS { +namespace +{ + bool hasColumn(const Table &table, const string &column); + bool hasSubTable(const Table &table, const string &name); + Table getSubTable(const Table &table, const string &name); + + Station::Ptr readStation(const Table &table, unsigned int id, + const string &name, const MPosition &position); +} + MeasurementAIPS::MeasurementAIPS(const string &filename, unsigned int idObservation, unsigned int idField, unsigned int idDataDescription) @@ -89,7 +99,7 @@ MeasurementAIPS::MeasurementAIPS(const string &filename, itsIdDataDescription(idDataDescription) { // Get information about the telescope (instrument). - initInstrument(); + itsInstrument = readInstrument(itsMS, itsIdObservation); // Get the reference directions for the selected field (i.e. phase center, // delay center, tile delay center). @@ -127,7 +137,7 @@ VisBuffer::Ptr MeasurementAIPS::read(const VisSelection &selection, // Find the column with covariance information associated with the specified // column. string columnCov = getLinkedCovarianceColumn(column, - hasColumn("WEIGHT_SPECTRUM") ? "WEIGHT_SPECTRUM" : "WEIGHT"); + hasColumn(itsMS, "WEIGHT_SPECTRUM") ? "WEIGHT_SPECTRUM" : "WEIGHT"); // Create cell slicers for array columns. Slicer slicer = getCellSlicer(selection); @@ -309,7 +319,7 @@ void MeasurementAIPS::write(VisBuffer::Ptr buffer, ASSERT(itsMS.isWritable()); // Add visbility column if it does not exist. - if(!hasColumn(column)) + if(!hasColumn(itsMS, column)) { LOG_INFO_STR("Creating visibility column: " << column); createVisibilityColumn(column); @@ -327,7 +337,7 @@ void MeasurementAIPS::write(VisBuffer::Ptr buffer, setLinkedCovarianceColumn(column, columnCov); // Add covariance column if it does not exist. - if(!hasColumn(columnCov)) + if(!hasColumn(itsMS, columnCov)) { LOG_INFO_STR("Creating covariance column: " << columnCov); createCovarianceColumn(columnCov); @@ -510,7 +520,7 @@ void MeasurementAIPS::write(VisBuffer::Ptr buffer, void MeasurementAIPS::writeHistory(const ParameterSet &parset) const { - Table tab_history = getSubTable("HISTORY"); + Table tab_history = getSubTable(itsMS, "HISTORY"); tab_history.reopenRW(); ScalarColumn<double> c_time(tab_history, "TIME"); @@ -592,182 +602,14 @@ BaselineMask MeasurementAIPS::asMask(const string &filter) const return mask; } -void MeasurementAIPS::initInstrument() -{ - // Get station names and positions in ITRF coordinates. - ROMSAntennaColumns antenna(itsMS.antenna()); - ROMSObservationColumns observation(itsMS.observation()); - - ASSERT(observation.nrow() > itsIdObservation); - ASSERT(!observation.flagRow()(itsIdObservation)); - - // Get instrument name. - string name(observation.telescopeName()(itsIdObservation)); - - // Get station positions. - MVPosition centroid; - vector<Station::Ptr> stations(antenna.nrow()); - for(unsigned int i = 0; i < stations.size(); ++i) - { - // Get station name and ITRF position. - MPosition position = MPosition::Convert(antenna.positionMeas()(i), - MPosition::ITRF)(); - - // Store station information. - stations[i] = initStation(i, antenna.name()(i), position); - - // Update ITRF centroid. - centroid += position.getValue(); - } - - // Get the instrument position in ITRF coordinates, or use the centroid - // of the station positions if the instrument position is unknown. - MPosition position; - if(MeasTable::Observatory(position, name)) - { - position = MPosition::Convert(position, MPosition::ITRF)(); - } - else - { - LOG_WARN("Instrument position unknown; will use centroid of stations."); - ASSERT(antenna.nrow() != 0); - centroid *= 1.0 / static_cast<double>(antenna.nrow()); - position = MPosition(centroid, MPosition::ITRF); - } - - itsInstrument = Instrument::Ptr(new Instrument(name, position, - stations.begin(), stations.end())); -} - -Station::Ptr MeasurementAIPS::initStation(unsigned int id, const string &name, - const MPosition &position) const -{ - if(!hasSubTable("LOFAR_ANTENNA_FIELD")) - { - return Station::Ptr(new Station(name, position)); - } - - Table tab_field = getSubTable("LOFAR_ANTENNA_FIELD"); - tab_field = tab_field(tab_field.col("ANTENNA_ID") == static_cast<Int>(id)); - - const size_t nFields = tab_field.nrow(); - if(nFields < 1 || nFields > 2) - { - LOG_WARN_STR("Antenna " << name << " consists of an incompatible number" - " of antenna fields. Beam model simulation will not work for this" - " antenna."); - return Station::Ptr(new Station(name, position)); - } - - ROScalarColumn<String> c_name(tab_field, "NAME"); - ROArrayQuantColumn<Double> c_position(tab_field, "POSITION", "m"); - ROArrayQuantColumn<Double> c_axes(tab_field, "COORDINATE_AXES", "m"); - ROArrayQuantColumn<Double> c_tile_offset(tab_field, "TILE_ELEMENT_OFFSET", - "m"); - ROArrayQuantColumn<Double> c_offset(tab_field, "ELEMENT_OFFSET", "m"); - ROArrayColumn<Bool> c_flag(tab_field, "ELEMENT_FLAG"); - - AntennaField::Ptr field[2]; - for(size_t i = 0; i < nFields; ++i) - { - // Read antenna field center (ITRF). - Vector<Quantum<Double> > aips_position = c_position(i); - ASSERT(aips_position.size() == 3); - - Vector3 position = {{aips_position(0).getValue(), - aips_position(1).getValue(), aips_position(2).getValue()}}; - - // Read antenna field coordinate axes (ITRF). - Matrix<Quantum<Double> > aips_axes = c_axes(i); - ASSERT(aips_axes.shape().isEqual(IPosition(2, 3, 3))); - - Vector3 P = {{aips_axes(0, 0).getValue(), aips_axes(1, 0).getValue(), - aips_axes(2, 0).getValue()}}; - Vector3 Q = {{aips_axes(0, 1).getValue(), aips_axes(1, 1).getValue(), - aips_axes(2, 1).getValue()}}; - Vector3 R = {{aips_axes(0, 2).getValue(), aips_axes(1, 2).getValue(), - aips_axes(2, 2).getValue()}}; - - // Store information as AntennaField. - field[i] = AntennaField::Ptr(new AntennaField(c_name(i), position, P, - Q, R)); - - // Read offsets (ITRF) of the dipoles within a tile for HBA antenna - // fields. - if(c_name(i) != "LBA") - { - // Read tile configuration for HBA antenna fields. - Matrix<Quantum<Double> > aips_offset = c_tile_offset(i); - ASSERT(aips_offset.nrow() == 3); - - const size_t nElement = aips_offset.ncolumn(); - for(size_t j = 0; j < nElement; ++j) - { - Vector3 offset = {{aips_offset(0, j).getValue(), - aips_offset(1, j).getValue(), - aips_offset(2, j).getValue()}}; - - field[i]->appendTileElement(offset); - } - } - - // Read element offsets and flags. - Matrix<Quantum<Double> > aips_offset = c_offset(i); - Matrix<Bool> aips_flag = c_flag(i); - - const size_t nElement = aips_offset.ncolumn(); - ASSERT(aips_offset.shape().isEqual(IPosition(2, 3, nElement))); - ASSERT(aips_flag.shape().isEqual(IPosition(2, 2, nElement))); - - for(size_t j = 0; j < nElement; ++j) - { - AntennaField::Element element; - element.offset[0] = aips_offset(0, j).getValue(); - element.offset[1] = aips_offset(1, j).getValue(); - element.offset[2] = aips_offset(2, j).getValue(); - element.flag[0] = aips_flag(0, j); - element.flag[1] = aips_flag(1, j); - - field[i]->appendElement(element); - } - } - - return (nFields == 1 ? Station::Ptr(new Station(name, position, field[0])) - : Station::Ptr(new Station(name, position, field[0], field[1]))); -} - void MeasurementAIPS::initReferenceDirections() { - // Get phase center as RA and DEC (J2000). - ROMSFieldColumns field(itsMS.field()); - ASSERT(field.nrow() > itsIdField); - ASSERT(!field.flagRow()(itsIdField)); - - itsPhaseReference = MDirection::Convert(field.phaseDirMeas(itsIdField), - MDirection::J2000)(); - itsDelayReference = MDirection::Convert(field.delayDirMeas(itsIdField), - MDirection::J2000)(); - - // By default, the tile beam reference direction is assumed to be equal - // to the station beam reference direction (for backward compatibility, - // and for non-HBA measurements). - itsTileReference = itsDelayReference; - - // The MeasurementSet class does not support LOFAR specific columns, so we - // use ROArrayMeasColumn to read the tile beam reference direction. - Table tab_field = getSubTable("FIELD"); - - static const String columnName = "LOFAR_TILE_BEAM_DIR"; - if(hasColumn(tab_field, columnName)) - { - ROArrayMeasColumn<MDirection> c_direction(tab_field, columnName); - if(c_direction.isDefined(itsIdField)) - { - itsTileReference = - MDirection::Convert(c_direction(itsIdField)(IPosition(1, 0)), - MDirection::J2000)(); - } - } + itsPhaseReference = MDirection::Convert(readPhaseReference(itsMS, + itsIdField), MDirection::J2000)(); + itsDelayReference = MDirection::Convert(readDelayReference(itsMS, + itsIdField), MDirection::J2000)(); + itsTileReference = MDirection::Convert(readTileReference(itsMS, + itsIdField), MDirection::J2000)(); } void MeasurementAIPS::initDimensions() @@ -886,16 +728,6 @@ void MeasurementAIPS::initDimensions() itsDims.setCorrelations(correlations); } -bool MeasurementAIPS::hasColumn(const string &column) const -{ - return hasColumn(itsMS, column); -} - -bool MeasurementAIPS::hasColumn(const Table &table, const string &column) const -{ - return table.tableDesc().isColumn(column); -} - void MeasurementAIPS::createVisibilityColumn(const string &name) { // Added column should get the same shape as the other data columns in @@ -948,7 +780,7 @@ void MeasurementAIPS::createCovarianceColumn(const string &name) itsMS.addColumn(columnDescriptor, storageManager); // Figure out which column to use as input. - bool hasSpectrum = hasColumn("WEIGHT_SPECTRUM"); + bool hasSpectrum = hasColumn(itsMS, "WEIGHT_SPECTRUM"); string weightColumn = hasSpectrum ? "WEIGHT_SPECTRUM" : "WEIGHT"; // Initialize the covariance column using the weight (assumed to equal one @@ -1052,16 +884,6 @@ void MeasurementAIPS::createCovarianceColumn(const string &name) == static_cast<Int>(itsIdDataDescription)); } -bool MeasurementAIPS::hasSubTable(const string &table) const -{ - return itsMS.keywordSet().isDefined(table); -} - -Table MeasurementAIPS::getSubTable(const string &table) const -{ - return itsMS.keywordSet().asTable(table); -} - MDirection MeasurementAIPS::getColumnPhaseReference(const string &column) const { static const String keyword = "LOFAR_DIRECTION"; @@ -1166,7 +988,7 @@ BaselineMask MeasurementAIPS::getBaselineMask(const VisSelection &selection) return asMask("*&&"); } -// NOTE: OPTIMIZATION OPPORTUNITY: when reading all channels, do not use a +// NOTE: OPTIMIZATION OPPORTUNITY: When reading all channels, do not use a // slicer at all. Interval<size_t> MeasurementAIPS::getChannelRange(const VisSelection &selection) const @@ -1462,5 +1284,228 @@ VisDimensions MeasurementAIPS::getDimensionsImpl(const Table &tab_selection, return dims; } +Instrument::Ptr readInstrument(const MeasurementSet &ms, + unsigned int idObservation) +{ + ROMSObservationColumns observation(ms.observation()); + ASSERT(observation.nrow() > idObservation); + ASSERT(!observation.flagRow()(idObservation)); + + // Get station names and positions in ITRF coordinates. + ROMSAntennaColumns antenna(ms.antenna()); + + // Get station positions. + MVPosition centroid; + vector<Station::Ptr> stations(antenna.nrow()); + for(unsigned int i = 0; i < stations.size(); ++i) + { + // Get station name and ITRF position. + MPosition position = MPosition::Convert(antenna.positionMeas()(i), + MPosition::ITRF)(); + + // Store station information. + stations[i] = readStation(ms, i, antenna.name()(i), position); + + // Update ITRF centroid. + centroid += position.getValue(); + } + + // Get the instrument position in ITRF coordinates, or use the centroid + // of the station positions if the instrument position is unknown. + MPosition position; + + // Read observatory name and try to look-up its position. + const string observatory = observation.telescopeName()(idObservation); + if(MeasTable::Observatory(position, observatory)) + { + position = MPosition::Convert(position, MPosition::ITRF)(); + } + else + { + LOG_WARN("Instrument position unknown; will use centroid of stations."); + ASSERT(antenna.nrow() != 0); + centroid *= 1.0 / static_cast<double>(antenna.nrow()); + position = MPosition(centroid, MPosition::ITRF); + } + + return Instrument::Ptr(new Instrument(observatory, position, + stations.begin(), stations.end())); +} + +MDirection readPhaseReference(const MeasurementSet &ms, unsigned int idField) +{ + ROMSFieldColumns field(ms.field()); + ASSERT(field.nrow() > idField); + ASSERT(!field.flagRow()(idField)); + + return field.phaseDirMeas(idField); +} + +MDirection readDelayReference(const MeasurementSet &ms, unsigned int idField) +{ + ROMSFieldColumns field(ms.field()); + ASSERT(field.nrow() > idField); + ASSERT(!field.flagRow()(idField)); + + return field.delayDirMeas(idField); +} + +MDirection readTileReference(const MeasurementSet &ms, unsigned int idField) +{ + // The MeasurementSet class does not support LOFAR specific columns, so we + // use ROArrayMeasColumn to read the tile beam reference direction. + Table tab_field = getSubTable(ms, "FIELD"); + + static const String columnName = "LOFAR_TILE_BEAM_DIR"; + if(hasColumn(tab_field, columnName)) + { + ROArrayMeasColumn<MDirection> c_direction(tab_field, columnName); + if(c_direction.isDefined(idField)) + { + return c_direction(idField)(IPosition(1, 0)); + } + } + + // By default, the tile beam reference direction is assumed to be equal + // to the station beam reference direction (for backward compatibility, + // and for non-HBA measurements). + return readDelayReference(ms, idField); +} + +double readFreqReference(const MeasurementSet &ms, + unsigned int idDataDescription) +{ + // Read spectral window id. + ROMSDataDescColumns desc(ms.dataDescription()); + ASSERT(desc.nrow() > idDataDescription); + ASSERT(!desc.flagRow()(idDataDescription)); + + const unsigned int idWindow = desc.spectralWindowId()(idDataDescription); + + // Read reference frequency. + ROMSSpWindowColumns window(ms.spectralWindow()); + ASSERT(window.nrow() > idWindow); + ASSERT(!window.flagRow()(idWindow)); + + return window.refFrequency()(idWindow); +} + +namespace +{ + +bool hasColumn(const Table &table, const string &column) +{ + return table.tableDesc().isColumn(column); +} + +bool hasSubTable(const Table &table, const string &name) +{ + return table.keywordSet().isDefined(name); +} + +Table getSubTable(const Table &table, const string &name) +{ + return table.keywordSet().asTable(name); +} + +Station::Ptr readStation(const Table &table, unsigned int id, + const string &name, const MPosition &position) +{ + if(!hasSubTable(table, "LOFAR_ANTENNA_FIELD")) + { + return Station::Ptr(new Station(name, position)); + } + + Table tab_field = getSubTable(table, "LOFAR_ANTENNA_FIELD"); + tab_field = tab_field(tab_field.col("ANTENNA_ID") == static_cast<Int>(id)); + + const size_t nFields = tab_field.nrow(); + if(nFields < 1 || nFields > 2) + { + LOG_WARN_STR("Antenna " << name << " consists of an incompatible number" + " of antenna fields. Beam model simulation will not work for this" + " antenna."); + return Station::Ptr(new Station(name, position)); + } + + ROScalarColumn<String> c_name(tab_field, "NAME"); + ROArrayQuantColumn<Double> c_position(tab_field, "POSITION", "m"); + ROArrayQuantColumn<Double> c_axes(tab_field, "COORDINATE_AXES", "m"); + ROArrayQuantColumn<Double> c_tile_offset(tab_field, "TILE_ELEMENT_OFFSET", + "m"); + ROArrayQuantColumn<Double> c_offset(tab_field, "ELEMENT_OFFSET", "m"); + ROArrayColumn<Bool> c_flag(tab_field, "ELEMENT_FLAG"); + + AntennaField::Ptr field[2]; + for(size_t i = 0; i < nFields; ++i) + { + // Read antenna field center (ITRF). + Vector<Quantum<Double> > aips_position = c_position(i); + ASSERT(aips_position.size() == 3); + + Vector3 position = {{aips_position(0).getValue(), + aips_position(1).getValue(), aips_position(2).getValue()}}; + + // Read antenna field coordinate axes (ITRF). + Matrix<Quantum<Double> > aips_axes = c_axes(i); + ASSERT(aips_axes.shape().isEqual(IPosition(2, 3, 3))); + + Vector3 P = {{aips_axes(0, 0).getValue(), aips_axes(1, 0).getValue(), + aips_axes(2, 0).getValue()}}; + Vector3 Q = {{aips_axes(0, 1).getValue(), aips_axes(1, 1).getValue(), + aips_axes(2, 1).getValue()}}; + Vector3 R = {{aips_axes(0, 2).getValue(), aips_axes(1, 2).getValue(), + aips_axes(2, 2).getValue()}}; + + // Store information as AntennaField. + field[i] = AntennaField::Ptr(new AntennaField(c_name(i), position, P, + Q, R)); + + // Read offsets (ITRF) of the dipoles within a tile for HBA antenna + // fields. + if(c_name(i) != "LBA") + { + // Read tile configuration for HBA antenna fields. + Matrix<Quantum<Double> > aips_offset = c_tile_offset(i); + ASSERT(aips_offset.nrow() == 3); + + const size_t nElement = aips_offset.ncolumn(); + for(size_t j = 0; j < nElement; ++j) + { + Vector3 offset = {{aips_offset(0, j).getValue(), + aips_offset(1, j).getValue(), + aips_offset(2, j).getValue()}}; + + field[i]->appendTileElement(offset); + } + } + + // Read element offsets and flags. + Matrix<Quantum<Double> > aips_offset = c_offset(i); + Matrix<Bool> aips_flag = c_flag(i); + + const size_t nElement = aips_offset.ncolumn(); + ASSERT(aips_offset.shape().isEqual(IPosition(2, 3, nElement))); + ASSERT(aips_flag.shape().isEqual(IPosition(2, 2, nElement))); + + for(size_t j = 0; j < nElement; ++j) + { + AntennaField::Element element; + element.offset[0] = aips_offset(0, j).getValue(); + element.offset[1] = aips_offset(1, j).getValue(); + element.offset[2] = aips_offset(2, j).getValue(); + element.flag[0] = aips_flag(0, j); + element.flag[1] = aips_flag(1, j); + + field[i]->appendElement(element); + } + } + + return (nFields == 1 ? Station::Ptr(new Station(name, position, field[0])) + : Station::Ptr(new Station(name, position, field[0], field[1]))); +} + +} //# namespace unnamed + } //# namespace BBS } //# namespace LOFAR diff --git a/CEP/Calibration/BBSKernel/src/MeasurementExprLOFAR.cc b/CEP/Calibration/BBSKernel/src/MeasurementExprLOFAR.cc index 84e52fb12c1754f35062746660e383ec34f40673..3ebca01db48b09dc20e506d08b97e13566c9e907 100644 --- a/CEP/Calibration/BBSKernel/src/MeasurementExprLOFAR.cc +++ b/CEP/Calibration/BBSKernel/src/MeasurementExprLOFAR.cc @@ -60,7 +60,7 @@ namespace BBS MeasurementExprLOFAR::MeasurementExprLOFAR(SourceDB &sourceDB, const BufferMap &buffers, const ModelConfig &config, - const Instrument::Ptr &instrument, const BaselineSeq &baselines, + const Instrument::ConstPtr &instrument, const BaselineSeq &baselines, double refFreq, const casa::MDirection &refPhase, const casa::MDirection &refDelay, const casa::MDirection &refTile, bool circular) @@ -104,7 +104,7 @@ void MeasurementExprLOFAR::solvablesChanged() void MeasurementExprLOFAR::makeForwardExpr(SourceDB &sourceDB, const BufferMap &buffers, const ModelConfig &config, - const Instrument::Ptr &instrument, double refFreq, + const Instrument::ConstPtr &instrument, double refFreq, const casa::MDirection &refPhase, const casa::MDirection &refDelay, const casa::MDirection &refTile, bool circular) { @@ -149,21 +149,6 @@ void MeasurementExprLOFAR::makeForwardExpr(SourceDB &sourceDB, instrument->station(i)->position(), refPhase); } - HamakerBeamCoeff coeffLBA, coeffHBA; - if(config.useBeam()) - { - // Read LBA beam model coefficients. - casa::Path path; - path = config.getBeamConfig().getElementPath(); - path.append("element_beam_HAMAKER_LBA.coeff"); - coeffLBA.init(path); - - // Read HBA beam model coefficients. - path = config.getBeamConfig().getElementPath(); - path.append("element_beam_HAMAKER_HBA.coeff"); - coeffHBA.init(path); - } - IonosphereExpr::Ptr exprIonosphere; if(config.useIonosphere()) { @@ -215,7 +200,7 @@ void MeasurementExprLOFAR::makeForwardExpr(SourceDB &sourceDB, exprDDE[j] = compose(exprDDE[j], makeBeamExpr(itsScope, instrument->station(j), refFreq, exprPatchPositionITRF, exprRefDelayITRF, exprRefTileITRF, - config.getBeamConfig(), coeffLBA, coeffHBA)); + config.getBeamConfig())); } // Directional TEC. @@ -343,7 +328,7 @@ void MeasurementExprLOFAR::makeInverseExpr(SourceDB &sourceDB, LOG_DEBUG_STR("Building expression tree..."); - Instrument::Ptr instrument = buffer->instrument(); + Instrument::ConstPtr instrument = buffer->instrument(); // Allocate space for the station response expressions. vector<Expr<JonesMatrix>::Ptr> stationExpr(instrument->nStations()); @@ -411,21 +396,6 @@ void MeasurementExprLOFAR::makeInverseExpr(SourceDB &sourceDB, Expr<Vector<3> >::Ptr exprRefTileITRF = makeITRFExpr(instrument->position(), exprRefTile); - HamakerBeamCoeff coeffLBA, coeffHBA; - if(config.useBeam()) - { - // Read LBA beam model coefficients. - casa::Path path; - path = config.getBeamConfig().getElementPath(); - path.append("element_beam_HAMAKER_LBA.coeff"); - coeffLBA.init(path); - - // Read HBA beam model coefficients. - path = config.getBeamConfig().getElementPath(); - path.append("element_beam_HAMAKER_HBA.coeff"); - coeffHBA.init(path); - } - // Functor for the creation of the ionosphere sub-expression. IonosphereExpr::Ptr exprIonosphere; if(config.useIonosphere()) @@ -462,7 +432,7 @@ void MeasurementExprLOFAR::makeInverseExpr(SourceDB &sourceDB, makeBeamExpr(itsScope, instrument->station(i), buffer->getReferenceFreq(), exprRefPhaseITRF, exprRefDelayITRF, exprRefTileITRF, - config.getBeamConfig(), coeffLBA, coeffHBA)); + config.getBeamConfig())); } // Ionosphere. @@ -510,7 +480,7 @@ void MeasurementExprLOFAR::makeInverseExpr(SourceDB &sourceDB, makeBeamExpr(itsScope, instrument->station(i), buffer->getReferenceFreq(), exprPatchPositionITRF, exprRefDelayITRF, exprRefTileITRF, - config.getBeamConfig(), coeffLBA, coeffHBA)); + config.getBeamConfig())); } // Directional TEC. diff --git a/CEP/Calibration/BBSKernel/src/MeasurementExprLOFARUtil.cc b/CEP/Calibration/BBSKernel/src/MeasurementExprLOFARUtil.cc index 29c844690463962c398790fcb07355908b2aef5d..b99dbc038acec7f37e2cc4d7ec7b246bb93f0cee 100644 --- a/CEP/Calibration/BBSKernel/src/MeasurementExprLOFARUtil.cc +++ b/CEP/Calibration/BBSKernel/src/MeasurementExprLOFARUtil.cc @@ -24,20 +24,22 @@ #include <lofar_config.h> #include <BBSKernel/MeasurementExprLOFARUtil.h> #include <BBSKernel/Exceptions.h> -#include <BBSKernel/Expr/AntennaFieldAzEl.h> +#include <BBSKernel/Expr/AntennaElementLBA.h> +#include <BBSKernel/Expr/AntennaElementHBA.h> +#include <BBSKernel/Expr/AntennaFieldThetaPhi.h> #include <BBSKernel/Expr/AzEl.h> #include <BBSKernel/Expr/Delay.h> #include <BBSKernel/Expr/ElevationCut.h> #include <BBSKernel/Expr/EquatorialCentroid.h> #include <BBSKernel/Expr/ExprAdaptors.h> #include <BBSKernel/Expr/FaradayRotation.h> -#include <BBSKernel/Expr/HamakerDipole.h> #include <BBSKernel/Expr/ITRFDirection.h> #include <BBSKernel/Expr/Literal.h> #include <BBSKernel/Expr/LMN.h> #include <BBSKernel/Expr/MatrixMul2.h> #include <BBSKernel/Expr/MatrixMul3.h> #include <BBSKernel/Expr/MatrixSum.h> +#include <BBSKernel/Expr/ParallacticRotation.h> #include <BBSKernel/Expr/PhaseShift.h> #include <BBSKernel/Expr/ScalarMatrixMul.h> #include <BBSKernel/Expr/StationBeamFormer.h> @@ -240,9 +242,7 @@ makeBeamExpr(Scope&, const Expr<Vector<3> >::Ptr &exprITRF, const Expr<Vector<3> >::Ptr &exprRefDelayITRF, const Expr<Vector<3> >::Ptr &exprRefTileITRF, - const BeamConfig &config, - const HamakerBeamCoeff &coeffLBA, - const HamakerBeamCoeff &coeffHBA) + const BeamConfig &config) { // Check if the beam model can be computed for this station. if(!station->isPhasedArray()) @@ -252,10 +252,6 @@ makeBeamExpr(Scope&, " station beam is missing."); } - // The positive X dipole direction is SE of the reference orientation, which - // translates to an azimuth of 3/4*pi. - Expr<Scalar>::Ptr exprOrientation(new Literal(3.0 * casa::C::pi_4)); - // Build expressions for the dual-dipole or tile beam of each antenna field. Expr<JonesMatrix>::Ptr exprElementBeam[2]; for(size_t i = 0; i < station->nField(); ++i) @@ -265,21 +261,28 @@ makeBeamExpr(Scope&, // Element (dual-dipole) beam expression. if(config.mode() != BeamConfig::ARRAY_FACTOR) { - Expr<Vector<2> >::Ptr exprAzEl(new AntennaFieldAzEl(exprITRF, + Expr<Vector<2> >::Ptr exprThetaPhi = + Expr<Vector<2> >::Ptr(new AntennaFieldThetaPhi(exprITRF, field)); if(field->isHBA()) { exprElementBeam[i] = - Expr<JonesMatrix>::Ptr(new HamakerDipole(coeffHBA, exprAzEl, - exprOrientation)); + Expr<JonesMatrix>::Ptr(new AntennaElementHBA(exprThetaPhi)); } else { exprElementBeam[i] = - Expr<JonesMatrix>::Ptr(new HamakerDipole(coeffLBA, exprAzEl, - exprOrientation)); + Expr<JonesMatrix>::Ptr(new AntennaElementLBA(exprThetaPhi)); } + + Expr<JonesMatrix>::Ptr exprRotation = + Expr<JonesMatrix>::Ptr(new ParallacticRotation(exprITRF, + field)); + + exprElementBeam[i] = + Expr<JonesMatrix>::Ptr(new MatrixMul2(exprElementBeam[i], + exprRotation)); } else { diff --git a/CEP/Calibration/BBSKernel/src/ModelConfig.cc b/CEP/Calibration/BBSKernel/src/ModelConfig.cc index 486399574e450bf21c893ce82b356ff8d0377878..33db77ca8e20f752020767be4c4930c15f7abf28 100644 --- a/CEP/Calibration/BBSKernel/src/ModelConfig.cc +++ b/CEP/Calibration/BBSKernel/src/ModelConfig.cc @@ -96,11 +96,9 @@ BeamConfig::BeamConfig() { } -BeamConfig::BeamConfig(Mode mode, bool conjugateAF, - const casa::Path &elementPath) +BeamConfig::BeamConfig(Mode mode, bool conjugateAF) : itsMode(mode), - itsConjugateAF(conjugateAF), - itsElementPath(elementPath) + itsConjugateAF(conjugateAF) { } @@ -114,11 +112,6 @@ bool BeamConfig::conjugateAF() const return itsConjugateAF; } -const casa::Path &BeamConfig::getElementPath() const -{ - return itsElementPath; -} - // -------------------------------------------------------------------------- // // - IonosphereConfig implementation - // // -------------------------------------------------------------------------- // @@ -421,9 +414,7 @@ ostream &operator<<(ostream &out, const BeamConfig &obj) { out << indent << "Mode: " << BeamConfig::asString(obj.mode()) << endl << indent << "Conjugate array factor: " << boolalpha - << obj.conjugateAF() << noboolalpha - << endl << indent << "Element model path: " - << obj.getElementPath().originalName(); + << obj.conjugateAF() << noboolalpha; return out; } diff --git a/CEP/Calibration/BBSKernel/src/StationExprLOFAR.cc b/CEP/Calibration/BBSKernel/src/StationExprLOFAR.cc index e0d660437c6e75c861ab10eb607db5a386e6be2f..99f882f24ee64ba45be4cfb03be738fa113ba0da 100644 --- a/CEP/Calibration/BBSKernel/src/StationExprLOFAR.cc +++ b/CEP/Calibration/BBSKernel/src/StationExprLOFAR.cc @@ -25,7 +25,6 @@ #include <BBSKernel/StationExprLOFAR.h> #include <BBSKernel/Exceptions.h> #include <BBSKernel/MeasurementExprLOFARUtil.h> -#include <BBSKernel/Expr/AntennaFieldAzEl.h> #include <BBSKernel/Expr/AzEl.h> #include <BBSKernel/Expr/CachePolicy.h> #include <BBSKernel/Expr/Delay.h> @@ -64,7 +63,7 @@ StationExprLOFAR::StationExprLOFAR(SourceDB &sourceDB, const BufferMap &buffers, } void StationExprLOFAR::initialize(SourceDB &sourceDB, const BufferMap &buffers, - const ModelConfig &config, const Instrument::Ptr &instrument, + const ModelConfig &config, const Instrument::ConstPtr &instrument, double refFreq, const casa::MDirection &refPhase, const casa::MDirection &refDelay, const casa::MDirection &refTile, bool inverse) @@ -128,21 +127,6 @@ void StationExprLOFAR::initialize(SourceDB &sourceDB, const BufferMap &buffers, Expr<Vector<3> >::Ptr exprRefTileITRF = makeITRFExpr(instrument->position(), exprRefTile); - HamakerBeamCoeff coeffLBA, coeffHBA; - if(config.useBeam()) - { - // Read LBA beam model coefficients. - casa::Path path; - path = config.getBeamConfig().getElementPath(); - path.append("element_beam_HAMAKER_LBA.coeff"); - coeffLBA.init(path); - - // Read HBA beam model coefficients. - path = config.getBeamConfig().getElementPath(); - path.append("element_beam_HAMAKER_HBA.coeff"); - coeffHBA.init(path); - } - // Functor for the creation of the ionosphere sub-expression. IonosphereExpr::Ptr exprIonosphere; if(config.useIonosphere()) @@ -177,8 +161,7 @@ void StationExprLOFAR::initialize(SourceDB &sourceDB, const BufferMap &buffers, itsExpr[i] = compose(itsExpr[i], makeBeamExpr(itsScope, instrument->station(i), refFreq, exprRefPhaseITRF, exprRefDelayITRF, - exprRefTileITRF, config.getBeamConfig(), coeffLBA, - coeffHBA)); + exprRefTileITRF, config.getBeamConfig())); } // Ionosphere. @@ -225,8 +208,7 @@ void StationExprLOFAR::initialize(SourceDB &sourceDB, const BufferMap &buffers, itsExpr[i] = compose(itsExpr[i], makeBeamExpr(itsScope, instrument->station(i), refFreq, exprPatchPositionITRF, exprRefDelayITRF, - exprRefTileITRF, config.getBeamConfig(), coeffLBA, - coeffHBA)); + exprRefTileITRF, config.getBeamConfig())); } // Directional TEC. diff --git a/CEP/Calibration/BBSKernel/src/StationResponse.cc b/CEP/Calibration/BBSKernel/src/StationResponse.cc index 04c95f73b3f1c23ad3bffd874ed7f093cbde4dda..00924ed38d03c6d8b206c30ae57287167c51b96c 100644 --- a/CEP/Calibration/BBSKernel/src/StationResponse.cc +++ b/CEP/Calibration/BBSKernel/src/StationResponse.cc @@ -24,36 +24,23 @@ #include <lofar_config.h> #include <BBSKernel/StationResponse.h> #include <BBSKernel/Exceptions.h> +#include <BBSKernel/MeasurementAIPS.h> +#include <BBSKernel/Expr/AntennaElementLBA.h> +#include <BBSKernel/Expr/AntennaElementHBA.h> +#include <BBSKernel/Expr/AntennaFieldThetaPhi.h> #include <BBSKernel/Expr/CachePolicy.h> -#include <BBSKernel/Expr/HamakerDipole.h> +#include <BBSKernel/Expr/ExprAdaptors.h> +#include <BBSKernel/Expr/ITRFDirection.h> #include <BBSKernel/Expr/Literal.h> #include <BBSKernel/Expr/MatrixInverse.h> #include <BBSKernel/Expr/MatrixMul2.h> -#include <BBSKernel/Expr/ExprAdaptors.h> -#include <BBSKernel/Expr/AntennaFieldAzEl.h> -#include <BBSKernel/Expr/ITRFDirection.h> +#include <BBSKernel/Expr/ParallacticRotation.h> #include <BBSKernel/Expr/ScalarMatrixMul.h> #include <BBSKernel/Expr/StationBeamFormer.h> #include <BBSKernel/Expr/TileArrayFactor.h> #include <Common/LofarLogger.h> #include <measures/Measures/MeasConvert.h> #include <measures/Measures/MCDirection.h> -#include <measures/Measures/MCPosition.h> -#include <ms/MeasurementSets/MSAntenna.h> -#include <ms/MeasurementSets/MSAntennaParse.h> -#include <ms/MeasurementSets/MSAntennaColumns.h> -#include <ms/MeasurementSets/MSDataDescription.h> -#include <ms/MeasurementSets/MSDataDescColumns.h> -#include <ms/MeasurementSets/MSField.h> -#include <ms/MeasurementSets/MSFieldColumns.h> -#include <ms/MeasurementSets/MSObservation.h> -#include <ms/MeasurementSets/MSObsColumns.h> -#include <ms/MeasurementSets/MSPolarization.h> -#include <ms/MeasurementSets/MSPolColumns.h> -#include <ms/MeasurementSets/MSSpectralWindow.h> -#include <ms/MeasurementSets/MSSpWindowColumns.h> -#include <ms/MeasurementSets/MSSelection.h> -#include <measures/Measures/MeasTable.h> namespace LOFAR { @@ -64,7 +51,6 @@ StationResponse::StationResponse(const casa::MeasurementSet &ms, bool inverse, bool useElementBeam, bool useArrayFactor, bool conjugateAF) : itsRefDelay(new Dummy<Vector<2> >()), itsRefTile(new Dummy<Vector<2> >()), - itsRefOrientation(new Dummy<Scalar>()), itsDirection(new Dummy<Vector<2> >()) { // Set pointing and beamformer reference directions towards NCP by default. @@ -72,13 +58,9 @@ StationResponse::StationResponse(const casa::MeasurementSet &ms, setRefTile(casa::MDirection()); setDirection(casa::MDirection()); - // The positive X dipole direction is SE of the reference orientation, which - // translates to an azimuth of 3/4*pi. - setRefOrientation(3.0 * casa::C::pi_4); - // Load observation details. - Instrument::Ptr instrument = initInstrument(ms); - double refFreq = getReferenceFreq(ms); + Instrument::Ptr instrument = readInstrument(ms); + double refFreq = readFreqReference(ms); // The ITRF direction vectors for the direction of interest and the // reference direction are computed w.r.t. the center of the station @@ -92,13 +74,6 @@ StationResponse::StationResponse(const casa::MeasurementSet &ms, Expr<Vector<3> >::Ptr(new ITRFDirection(instrument->position(), itsRefTile)); - // Load beam model coefficients. - HamakerBeamCoeff coeffLBA, coeffHBA; - coeffLBA.init(casa::Path("$LOFARROOT/share/element_beam_HAMAKER_LBA" - ".coeff")); - coeffHBA.init(casa::Path("$LOFARROOT/share/element_beam_HAMAKER_HBA" - ".coeff")); - itsExpr.reserve(instrument->nStations()); for(size_t i = 0; i < instrument->nStations(); ++i) { @@ -129,21 +104,28 @@ StationResponse::StationResponse(const casa::MeasurementSet &ms, // Element (dual-dipole) beam expression. if(useElementBeam) { - Expr<Vector<2> >::Ptr exprAzEl(new AntennaFieldAzEl(exprDirITRF, + Expr<Vector<2> >::Ptr exprThetaPhi = + Expr<Vector<2> >::Ptr(new AntennaFieldThetaPhi(exprDirITRF, field)); if(field->isHBA()) { exprElementBeam[j] = - Expr<JonesMatrix>::Ptr(new HamakerDipole(coeffHBA, - exprAzEl, itsRefOrientation)); + Expr<JonesMatrix>::Ptr(new AntennaElementHBA(exprThetaPhi)); } else { exprElementBeam[j] = - Expr<JonesMatrix>::Ptr(new HamakerDipole(coeffLBA, - exprAzEl, itsRefOrientation)); + Expr<JonesMatrix>::Ptr(new AntennaElementLBA(exprThetaPhi)); } + + Expr<JonesMatrix>::Ptr exprRotation = + Expr<JonesMatrix>::Ptr(new ParallacticRotation(exprDirITRF, + field)); + + exprElementBeam[j] = + Expr<JonesMatrix>::Ptr(new MatrixMul2(exprElementBeam[j], + exprRotation)); } else { @@ -243,16 +225,6 @@ void StationResponse::setRefTile(const casa::MDirection &reference) itsCache.clearStats(); } -void StationResponse::setRefOrientation(double orientation) -{ - // Update dipole reference orientation. - itsRefOrientation->setValue(Scalar(Matrix(orientation))); - - // Clear cache. - itsCache.clear(); - itsCache.clearStats(); -} - void StationResponse::setDirection(const casa::MDirection &direction) { // Convert to ensure the direction is specified with respect to the correct @@ -306,171 +278,5 @@ StationResponse::compose(const Expr<JonesMatrix>::Ptr &lhs, return rhs; } -Instrument::Ptr StationResponse::initInstrument(const casa::MeasurementSet &ms) - const -{ - // Get station names and positions in ITRF coordinates. - casa::ROMSAntennaColumns antenna(ms.antenna()); - casa::ROMSObservationColumns observation(ms.observation()); - ASSERT(observation.nrow() > 0); - ASSERT(!observation.flagRow()(0)); - - // Get instrument name. - string name = observation.telescopeName()(0); - - // Get station positions. - casa::MVPosition centroid; - vector<Station::Ptr> stations(antenna.nrow()); - for(unsigned int i = 0; i < stations.size(); ++i) - { - // Get station name and ITRF position. - casa::MPosition position = - casa::MPosition::Convert(antenna.positionMeas()(i), - casa::MPosition::ITRF)(); - - // Store station information. - stations[i] = initStation(ms, i, antenna.name()(i), position); - - // Update ITRF centroid. - centroid += position.getValue(); - } - - // Get the instrument position in ITRF coordinates, or use the centroid - // of the station positions if the instrument position is unknown. - casa::MPosition position; - if(casa::MeasTable::Observatory(position, name)) - { - position = casa::MPosition::Convert(position, casa::MPosition::ITRF)(); - } - else - { - LOG_WARN("Instrument position unknown; will use centroid of stations."); - ASSERT(antenna.nrow() != 0); - centroid *= 1.0 / static_cast<double>(antenna.nrow()); - position = casa::MPosition(centroid, casa::MPosition::ITRF); - } - - return Instrument::Ptr(new Instrument(name, position, stations.begin(), - stations.end())); -} - -Station::Ptr StationResponse::initStation(const casa::MeasurementSet &ms, - unsigned int id, const string &name, const casa::MPosition &position) const -{ - if(!ms.keywordSet().isDefined("LOFAR_ANTENNA_FIELD")) - { - return Station::Ptr(new Station(name, position)); - } - - casa::Table tab_field(ms.keywordSet().asTable("LOFAR_ANTENNA_FIELD")); - tab_field = tab_field(tab_field.col("ANTENNA_ID") - == static_cast<casa::Int>(id)); - - const size_t nFields = tab_field.nrow(); - if(nFields < 1 || nFields > 2) - { - LOG_WARN_STR("Antenna " << name << " consists of an incompatible number" - " of antenna fields. Beam model simulation will not work for this" - " antenna."); - return Station::Ptr(new Station(name, position)); - } - - casa::ROScalarColumn<casa::String> c_name(tab_field, "NAME"); - casa::ROArrayQuantColumn<casa::Double> c_position(tab_field, "POSITION", - "m"); - casa::ROArrayQuantColumn<casa::Double> c_axes(tab_field, "COORDINATE_AXES", - "m"); - casa::ROArrayQuantColumn<casa::Double> c_tile_offset(tab_field, - "TILE_ELEMENT_OFFSET", "m"); - casa::ROArrayQuantColumn<casa::Double> c_offset(tab_field, "ELEMENT_OFFSET", - "m"); - casa::ROArrayColumn<casa::Bool> c_flag(tab_field, "ELEMENT_FLAG"); - - AntennaField::Ptr field[2]; - for(size_t i = 0; i < nFields; ++i) - { - // Read antenna field center. - casa::Vector<casa::Quantum<casa::Double> > aips_position = - c_position(i); - ASSERT(aips_position.size() == 3); - - Vector3 position = {{aips_position(0).getValue(), - aips_position(1).getValue(), aips_position(2).getValue()}}; - - // Read antenna field coordinate axes. - casa::Matrix<casa::Quantum<casa::Double> > aips_axes = c_axes(i); - ASSERT(aips_axes.shape().isEqual(casa::IPosition(2, 3, 3))); - - Vector3 P = {{aips_axes(0, 0).getValue(), aips_axes(1, 0).getValue(), - aips_axes(2, 0).getValue()}}; - Vector3 Q = {{aips_axes(0, 1).getValue(), aips_axes(1, 1).getValue(), - aips_axes(2, 1).getValue()}}; - Vector3 R = {{aips_axes(0, 2).getValue(), aips_axes(1, 2).getValue(), - aips_axes(2, 2).getValue()}}; - - // Store information as AntennaField. - field[i] = AntennaField::Ptr(new AntennaField(c_name(i), position, P, - Q, R)); - - if(c_name(i) != "LBA") - { - // Read tile configuration for HBA antenna fields. - casa::Matrix<casa::Quantum<casa::Double> > aips_offset = - c_tile_offset(i); - ASSERT(aips_offset.nrow() == 3); - - const size_t nElement = aips_offset.ncolumn(); - for(size_t j = 0; j < nElement; ++j) - { - Vector3 offset = {{aips_offset(0, j).getValue(), - aips_offset(1, j).getValue(), - aips_offset(2, j).getValue()}}; - - field[i]->appendTileElement(offset); - } - } - - // Read element position offsets and flags. - casa::Matrix<casa::Quantum<casa::Double> > aips_offset = c_offset(i); - casa::Matrix<casa::Bool> aips_flag = c_flag(i); - - const size_t nElement = aips_offset.ncolumn(); - ASSERT(aips_offset.shape().isEqual(casa::IPosition(2, 3, nElement))); - ASSERT(aips_flag.shape().isEqual(casa::IPosition(2, 2, nElement))); - - for(size_t j = 0; j < nElement; ++j) - { - AntennaField::Element element; - element.offset[0] = aips_offset(0, j).getValue(); - element.offset[1] = aips_offset(1, j).getValue(); - element.offset[2] = aips_offset(2, j).getValue(); - element.flag[0] = aips_flag(0, j); - element.flag[1] = aips_flag(1, j); - - field[i]->appendElement(element); - } - } - - return (nFields == 1 ? Station::Ptr(new Station(name, position, field[0])) - : Station::Ptr(new Station(name, position, field[0], field[1]))); -} - -double StationResponse::getReferenceFreq(const casa::MeasurementSet &ms) const -{ - // Read polarization id and spectral window id. - casa::ROMSDataDescColumns desc(ms.dataDescription()); - ASSERT(desc.nrow() > 0); - ASSERT(!desc.flagRow()(0)); - - const unsigned int idWindow = desc.spectralWindowId()(0); - - // Get spectral information. - casa::ROMSSpWindowColumns window(ms.spectralWindow()); - ASSERT(window.nrow() > idWindow); - ASSERT(!window.flagRow()(idWindow)); - - return window.refFrequency()(idWindow); -} - } //# namespace BBS } //# namespace LOFAR diff --git a/CEP/Calibration/ElementResponse/include/ElementResponse/ElementResponse.h b/CEP/Calibration/ElementResponse/include/ElementResponse/ElementResponse.h index c1cf9fb93533fee4461c3e52be877a24eb8e9509..f95ba672544e94f30f6046d752f3cf73ffa1c853 100644 --- a/CEP/Calibration/ElementResponse/include/ElementResponse/ElementResponse.h +++ b/CEP/Calibration/ElementResponse/include/ElementResponse/ElementResponse.h @@ -37,61 +37,59 @@ namespace LOFAR // @{ // Compute the response of an idealized LOFAR LBA dual dipole antenna to -// radiation at frequency freq (Hz) arriving from the direction given by -// az, el (rad). The +X dipole is at azimuth 0.0, the +Y dipole is at azimuth -// pi / 2.0. +// radiation at frequency freq (Hz) arriving from the direction given by theta, +// phi (rad). The antenna model is described in a spherical coordinate system +// with coordinates theta (zenith angle) and phi (azimith). The +X dipole is at +// azimuth zero, the +Y dipole is at azimuth PI / 2.0. // // Preconditions: // -------------- // freq: Frequency in Hz in the range [10 MHz, 100 MHz]. -// az: Azimuth in rad in the range [0.0, 2.0 * pi]. -// el: Elevation in rad in the range [0.0, pi / 2.0]. +// theta: Zenith angle in rad in the range [0.0, PI / 2.0]. +// phi: Azimuth in rad in the range [0.0, 2.0 * PI]. // -// NB: Clipping directions below the horizon (el < 0.0) is the responsibility of -// the caller. -void element_response_lba(double freq, double az, double el, +void element_response_lba(double freq, double theta, double phi, std::complex<double> (&response)[2][2]); // Compute the response of an idealized LOFAR HBA dual dipole antenna to -// radiation at frequency freq (Hz) arriving from the direction given by -// az, el (rad). The +X dipole is at azimuth 0.0, the +Y dipole is at azimuth -// pi / 2.0. +// radiation at frequency freq (Hz) arriving from the direction given by theta, +// phi (rad). The antenna model is described in a spherical coordinate system +// with coordinates theta (zenith angle) and phi (azimith). The +X dipole is at +// azimuth zero, the +Y dipole is at azimuth PI / 2.0. // // Preconditions: // -------------- // freq: Frequency in Hz in the range [120 MHz, 240 MHz]. -// az: Azimuth in rad in the range [0.0, 2.0 * pi]. -// el: Elevation in rad in the range [0.0, pi / 2.0]. +// theta: Zenith angle in rad in the range [0.0, PI / 2.0]. +// phi: Azimuth in rad in the range [0.0, 2.0 * PI]. // -// NB: Clipping directions below the horizon (el < 0.0) is the responsibility of -// the caller. -void element_response_hba(double freq, double az, double el, +void element_response_hba(double freq, double theta, double phi, std::complex<double> (&response)[2][2]); // Compute the response of an idealized LOFAR dual dipole antenna to radiation -// at frequency freq (Hz) arriving from the direction given by az, el (rad). -// The +X dipole is at azimuth 0.0, the +Y dipole is at azimuth pi / 2.0. +// at frequency freq (Hz) arriving from the direction given by theta, phi (rad). +// The antenna model is described in a spherical coordinate system with +// coordinates theta (zenith angle) and phi (azimith). The +X dipole is at +// azimuth zero, the +Y dipole is at azimuth PI / 2.0. // // This function uses a set of user defined coefficients to evaluate the beam // model. The coeff_shape parameter defines the shape of the coefficient array // as no. of harmonics x degree in theta x degree in frequency x 2. The last // dimension is implicit and always equal to 2. The coeff parameter points to an -// array of coefficients of the proper size, stored in row-major order (or "C"- -// order). The freq_center and freq_range parameters define the frequency range -// covered by the model described by the set of coefficients. +// array of coefficients of the proper size, stored in row-major order +// ("C"-order). The freq_center and freq_range parameters define the frequency +// range covered by the model described by the set of coefficients. // // Preconditions: // -------------- // freq: Frequency in Hz in the range [freq_center - freq_range, // freq_center + freq_range]. -// az: Azimuth in rad in the range [0.0, 2.0 * pi]. -// el: Elevation in rad in the range [0.0, pi / 2.0]. +// theta: Zenith angle in rad in the range [0.0, PI / 2.0]. +// phi: Azimuth in rad in the range [0.0, 2.0 * PI]. // freq_range, freq_center: Frequency center and range in Hz, should be > 0. // coeff_shape: Shape of the coefficient array, all dimensions should be > 0. // -// NB: Clipping directions below the horizon (el < 0.0) is the responsibility of -// the caller. -void element_response(double freq, double az, double el, +void element_response(double freq, double theta, double phi, std::complex<double> (&response)[2][2], double freq_center, double freq_range, const unsigned int (&coeff_shape)[3], const std::complex<double> coeff[]); diff --git a/CEP/Calibration/ElementResponse/src/CMakeLists.txt b/CEP/Calibration/ElementResponse/src/CMakeLists.txt index ad09788de60c25444395006ef59585770ba3064a..fbbf6cf0cc590054491f91aa4ef16c2b2732ccf5 100644 --- a/CEP/Calibration/ElementResponse/src/CMakeLists.txt +++ b/CEP/Calibration/ElementResponse/src/CMakeLists.txt @@ -1,7 +1,7 @@ # $Id: CMakeLists.txt 18775 2011-09-06 13:36:45Z zwieten $ -#include(LofarPackageVersion) +include(LofarPackageVersion) lofar_add_library(elementresponse -# Package__Version.cc + Package__Version.cc ElementResponse.cc) diff --git a/CEP/Calibration/ElementResponse/src/ElementResponse.cc b/CEP/Calibration/ElementResponse/src/ElementResponse.cc index 6008a52ca164ba8357f9f1b0afd2803217cab639..1324bfd4be5479bbadbd685bad2362e4d4c260fc 100644 --- a/CEP/Calibration/ElementResponse/src/ElementResponse.cc +++ b/CEP/Calibration/ElementResponse/src/ElementResponse.cc @@ -39,43 +39,45 @@ const double pi_2 = 1.570796326794896619231322; namespace LOFAR { -void element_response_lba(double freq, double az, double el, +void element_response_lba(double freq, double theta, double phi, std::complex<double> (&response)[2][2]) { - element_response(freq, az, el, response, default_lba_freq_center, + element_response(freq, theta, phi, response, default_lba_freq_center, default_lba_freq_range, default_lba_coeff_shape, default_lba_coeff); } -void element_response_hba(double freq, double az, double el, +void element_response_hba(double freq, double theta, double phi, std::complex<double> (&response)[2][2]) { - element_response(freq, az, el, response, default_hba_freq_center, + element_response(freq, theta, phi, response, default_hba_freq_center, default_hba_freq_range, default_hba_coeff_shape, default_hba_coeff); } -void element_response(double freq, double az, double el, +void element_response(double freq, double theta, double phi, std::complex<double> (&response)[2][2], double freq_center, double freq_range, const unsigned int (&coeff_shape)[3], const std::complex<double> coeff[]) { + // Initialize the response to zero. + response[0][0] = 0.0; + response[0][1] = 0.0; + response[1][0] = 0.0; + response[1][1] = 0.0; + + // Clip directions below the horizon. + if(theta >= pi_2) + { + return; + } + const unsigned int nHarmonics = coeff_shape[0]; const unsigned int nPowerTheta = coeff_shape[1]; const unsigned int nPowerFreq = coeff_shape[2]; - // The model is parameterized in terms of zenith angle. The appropriate - // conversion is taken care of below. - const double theta = pi_2 - el; - // The model is parameterized in terms of a normalized frequency in the // range [-1, 1]. The appropriate conversion is taken care of below. freq = (freq - freq_center) / freq_range; - // Initialize the response to zero. - response[0][0] = 0.0; - response[0][1] = 0.0; - response[1][0] = 0.0; - response[1][1] = 0.0; - // The variables sign and kappa are used to compute the value of kappa // mentioned in the description of the beam model [kappa = (-1)^k * (2 * k //+ 1)] incrementally. @@ -137,7 +139,7 @@ void element_response(double freq, double az, double el, // Compute the Jones matrix for the current harmonic, by rotating P over // kappa * az, and add it to the result. - const double angle = sign * kappa * az; + const double angle = sign * kappa * phi; const double caz = std::cos(angle); const double saz = std::sin(angle); diff --git a/CEP/Calibration/pystationresponse/src/__init__.py b/CEP/Calibration/pystationresponse/src/__init__.py index c04a4105506eb1ae02bd6473346a5d367592817c..d5bb434c54b1b60677064cf7701d6d41d2319a63 100755 --- a/CEP/Calibration/pystationresponse/src/__init__.py +++ b/CEP/Calibration/pystationresponse/src/__init__.py @@ -91,20 +91,6 @@ class stationresponse(StationResponse): """ self._setRefTile(ra, dec) - def setRefOrientation (self, orientation): - """Set the orientation of the +X dipole (azimuth in the antenna field - coordinate system). Antenna field azimuth is defined with respect to the - positive Q axis, and positive azimuth runs from the positive Q axis to - the positive P axis (roughly North over East, depending on the field). - The orientation of the +Y dipole is assumed to be +90 degrees away from - orientation of the +X dipole. - - `orientation` - Orientation of the +X dipole as azimuth North over East, in radians. - Defaults to SW, or an azimuth of 3/4*pi. - """ - self._setRefOrientation(orientation) - def setDirection (self, ra, dec): """Set the direction of interest (can be and often will be different from the pointing). By default, PHASE_DIR of field 0 is used. diff --git a/CEP/Calibration/pystationresponse/src/pystationresponse.cc b/CEP/Calibration/pystationresponse/src/pystationresponse.cc index fe58492ecc01a7bad4bf179b667b8b49949a149b..d57fa9a4a9539248b31df3fd5227a872cc5fe3e2 100755 --- a/CEP/Calibration/pystationresponse/src/pystationresponse.cc +++ b/CEP/Calibration/pystationresponse/src/pystationresponse.cc @@ -66,14 +66,6 @@ namespace LOFAR { namespace BBS { // relevant only for HBA observations. void setRefTile(double ra, double dec); - // Set the orientation of the +X dipole (azimuth in the antenna field - // coordinate system). Antenna field azimuth is defined with respect to the - // positive Q axis, and positive azimuth runs from the positive Q axis to - // the positive P axis (roughly North over East, depending on the field). - // The orientation of the +Y dipole is assumed to be +90 degrees away from - // orientation of the +X dipole. - void setRefOrientation(double orientation); - // Set the direction of interest in radians, J2000. Can and often will be // different than the delay and/or tile reference direction. void setDirection(double ra, double dec); @@ -134,11 +126,6 @@ namespace LOFAR { namespace BBS { itsResponse->setRefTile(MDirection(radec, MDirection::J2000)); } - void PyStationResponse::setRefOrientation(double orientation) - { - itsResponse->setRefOrientation(orientation); - } - void PyStationResponse::setDirection(double ra, double dec) { MVDirection radec(Quantity(ra,"rad"), Quantity(dec,"rad")); @@ -277,8 +264,6 @@ namespace LOFAR { namespace BBS { (boost::python::arg("ra"), boost::python::arg("dec"))) .def ("_setRefTile", &PyStationResponse::setRefTile, (boost::python::arg("ra"), boost::python::arg("dec"))) - .def ("_setRefOrientation", &PyStationResponse::setRefOrientation, - (boost::python::arg("orientation"))) .def ("_setDirection", &PyStationResponse::setDirection, (boost::python::arg("ra"), boost::python::arg("dec"))) .def ("_evaluate0", &PyStationResponse::evaluate0, diff --git a/CEP/DP3/AOFlagger/include/AOFlagger/gui/quality/histogrampage.h b/CEP/DP3/AOFlagger/include/AOFlagger/gui/quality/histogrampage.h index fa67fe6a6f7df3c30da296d18144995d47e82fd5..54f053b6612a64b85e7ce9bc86cd5037afa231e4 100644 --- a/CEP/DP3/AOFlagger/include/AOFlagger/gui/quality/histogrampage.h +++ b/CEP/DP3/AOFlagger/include/AOFlagger/gui/quality/histogrampage.h @@ -32,6 +32,7 @@ #include <AOFlagger/gui/plot/plot2d.h> #include <AOFlagger/gui/plot/plotwidget.h> +#include <gtkmm/textview.h> /** @author A.R. Offringa <offringa@astro.rug.nl> @@ -63,9 +64,11 @@ class HistogramPage : public Gtk::HBox { void updatePlot(); void plotPolarization(class HistogramCollection &histograms, unsigned p); void plotFit(class LogHistogram &histogram, const std::string &title); + void plotSlope(class LogHistogram &histogram, const std::string &title); void onPlotPropertiesClicked(); void onDataExportClicked(); void readFromFile(); + void updateSlopeFrame(); void updateDataWindow(); void onAutoRangeClicked() @@ -98,6 +101,11 @@ class HistogramPage : public Gtk::HBox { Gtk::Button _plotPropertiesButton, _dataExportButton; + Gtk::Frame _slopeFrame; + Gtk::VBox _slopeBox; + Gtk::TextView _slopeTextView; + Gtk::CheckButton _drawSlope; + std::string _statFilename; Plot2D _plot; PlotWidget _plotWidget; diff --git a/CEP/DP3/AOFlagger/include/AOFlagger/quality/histogramcollection.h b/CEP/DP3/AOFlagger/include/AOFlagger/quality/histogramcollection.h index f3a81a4152c1534cef1e140f36b4457928aa3434..40dfe35b33d589779affc6f46f5663f460920e40 100644 --- a/CEP/DP3/AOFlagger/include/AOFlagger/quality/histogramcollection.h +++ b/CEP/DP3/AOFlagger/include/AOFlagger/quality/histogramcollection.h @@ -34,6 +34,10 @@ class HistogramCollection public: typedef std::pair<unsigned, unsigned> AntennaPair; + HistogramCollection() : _polarizationCount(0) + { + } + HistogramCollection(unsigned polarizationCount) : _polarizationCount(polarizationCount) { init(); @@ -54,6 +58,13 @@ class HistogramCollection destruct(); } + void SetPolarizationCount(unsigned polarizationCount) + { + destruct(); + _polarizationCount = polarizationCount; + init(); + } + void Add(const unsigned antenna1, const unsigned antenna2, const unsigned polarization, const std::complex<float> *values, const bool *isRFI, size_t sampleCount) { LogHistogram &totalHistogram = GetTotalHistogram(antenna1, antenna2, polarization); @@ -120,25 +131,34 @@ class HistogramCollection void init() { - _totalHistograms = new std::map<AntennaPair, LogHistogram*>[_polarizationCount]; - _rfiHistograms = new std::map<AntennaPair, LogHistogram*>[_polarizationCount]; + if(_polarizationCount != 0) + { + _totalHistograms = new std::map<AntennaPair, LogHistogram*>[_polarizationCount]; + _rfiHistograms = new std::map<AntennaPair, LogHistogram*>[_polarizationCount]; + } else { + _totalHistograms = 0; + _rfiHistograms = 0; + } } void destruct() { - for(unsigned p=0;p<_polarizationCount;++p) + if(_polarizationCount != 0) { - for(std::map<AntennaPair, LogHistogram*>::iterator i=_totalHistograms[p].begin(); i!=_totalHistograms[p].end(); ++i) - { - delete i->second; - } - for(std::map<AntennaPair, LogHistogram*>::iterator i=_rfiHistograms[p].begin(); i!=_rfiHistograms[p].end(); ++i) + for(unsigned p=0;p<_polarizationCount;++p) { - delete i->second; + for(std::map<AntennaPair, LogHistogram*>::iterator i=_totalHistograms[p].begin(); i!=_totalHistograms[p].end(); ++i) + { + delete i->second; + } + for(std::map<AntennaPair, LogHistogram*>::iterator i=_rfiHistograms[p].begin(); i!=_rfiHistograms[p].end(); ++i) + { + delete i->second; + } } + delete[] _totalHistograms; + delete[] _rfiHistograms; } - delete[] _totalHistograms; - delete[] _rfiHistograms; } void copy(std::map<AntennaPair, LogHistogram*> &destination, const std::map<AntennaPair, LogHistogram*> &source) diff --git a/CEP/DP3/AOFlagger/include/AOFlagger/quality/loghistogram.h b/CEP/DP3/AOFlagger/include/AOFlagger/quality/loghistogram.h index 8577bc29d6c1435e0e3d79216e790b7a0486edaf..0d5da46cdebb15757f4b34626d9ab2199fcca2e8 100644 --- a/CEP/DP3/AOFlagger/include/AOFlagger/quality/loghistogram.h +++ b/CEP/DP3/AOFlagger/include/AOFlagger/quality/loghistogram.h @@ -194,13 +194,12 @@ class LogHistogram { unsigned long n = 0; long double sumX = 0.0, sumXY = 0.0, sumY = 0.0, sumXSquare = 0.0; - for(std::map<double, class AmplitudeBin>::const_iterator i=_amplitudes.begin();i!=_amplitudes.end();++i) + for(const_iterator i=begin();i!=end();++i) { - if(i->first >= startAmplitude && i->first < endAmplitude) + if(i.value() >= startAmplitude && i.value() < endAmplitude) { - long unsigned count = i->second.GetCount(); - double x = log10(i->first); - double y = log10((double) count / i->first); + double x = log10(i.value()); + double y = log10(i.normalizedCount()); ++n; sumX += x; sumXSquare += x * x; @@ -211,12 +210,38 @@ class LogHistogram return (sumXY - sumX*sumY/n)/(sumXSquare - (sumX*sumX/n)); } - double NormalizedSlopeInRFIRegion() const + double NormalizedSlopeOffset(double startAmplitude, double endAmplitude, double slope) const + { + unsigned long n = 0; + long double sumOffset = 0.0; + for(const_iterator i=begin();i!=end();++i) + { + if(i.value() >= startAmplitude && i.value() < endAmplitude) + { + double y = log10(i.normalizedCount()); + double x = log10(i.value()); + double ySlope = x*slope; + ++n; + sumOffset += (y - ySlope); + } + } + return (double) (sumOffset/(long double) n); + } + + void GetRFIRegion(double &start, double &end) const { double sigmaEstimate = AmplitudeWithMaxNormalizedCount(); double maxAmplitude = MaxAmplitude(); double halfWay = exp((log(sigmaEstimate) + log(maxAmplitude)) * 0.5); - return NormalizedSlope(sigmaEstimate * 20.0, halfWay); + start = sigmaEstimate * 20.0; + end = halfWay; + } + + double NormalizedSlopeInRFIRegion() const + { + double start, end; + GetRFIRegion(start ,end); + return NormalizedSlope(start, end); } void SetData(std::vector<HistogramTablesFormatter::HistogramItem> &histogramData) diff --git a/CEP/DP3/AOFlagger/src/aoquality.cpp b/CEP/DP3/AOFlagger/src/aoquality.cpp index 80819992f7258348d84c0f1be4f7b54f5b3c27d2..7394773555892bdd70ae5c08bef39930a945054b 100644 --- a/CEP/DP3/AOFlagger/src/aoquality.cpp +++ b/CEP/DP3/AOFlagger/src/aoquality.cpp @@ -60,7 +60,7 @@ enum CollectingMode CollectHistograms }; -void actionCollect(const std::string &filename, enum CollectingMode mode) +void actionCollect(const std::string &filename, enum CollectingMode mode, StatisticsCollection &statisticsCollection, HistogramCollection &histogramCollection) { MeasurementSet *ms = new MeasurementSet(filename); const unsigned polarizationCount = ms->GetPolarizationCount(); @@ -93,19 +93,19 @@ void actionCollect(const std::string &filename, enum CollectingMode mode) std::cout << "Channel zero will be included in the statistics, as it seems that channel 0 is okay.\n"; // Initialize statisticscollection - StatisticsCollection collection(polarizationCount); + statisticsCollection.SetPolarizationCount(polarizationCount); if(mode == CollectDefault) { for(unsigned b=0;b<bandCount;++b) { if(ignoreChannelZero) - collection.InitializeBand(b, (frequencies[b]+1), bands[b].channelCount-1); + statisticsCollection.InitializeBand(b, (frequencies[b]+1), bands[b].channelCount-1); else - collection.InitializeBand(b, frequencies[b], bands[b].channelCount); + statisticsCollection.InitializeBand(b, frequencies[b], bands[b].channelCount); } } // Initialize Histograms collection - HistogramCollection histogramCollection(polarizationCount); + histogramCollection.SetPolarizationCount(polarizationCount); // get columns casa::Table table(filename, casa::Table::Update); @@ -170,7 +170,7 @@ void actionCollect(const std::string &filename, enum CollectingMode mode) case CollectDefault: { const bool origFlags = false; - collection.Add(antenna1Index, antenna2Index, time, bandIndex, p, &samples[p]->real(), &samples[p]->imag(), isRFI[p], &origFlags, band.channelCount - startChannel, 2, 1, 0); + statisticsCollection.Add(antenna1Index, antenna2Index, time, bandIndex, p, &samples[p]->real(), &samples[p]->imag(), isRFI[p], &origFlags, band.channelCount - startChannel, 2, 1, 0); } break; case CollectHistograms: @@ -193,6 +193,14 @@ void actionCollect(const std::string &filename, enum CollectingMode mode) delete[] frequencies; delete[] bands; std::cout << "100\n"; +} + +void actionCollect(const std::string &filename, enum CollectingMode mode) +{ + StatisticsCollection statisticsCollection; + HistogramCollection histogramCollection; + + actionCollect(filename, mode, statisticsCollection, histogramCollection); switch(mode) { @@ -201,7 +209,7 @@ void actionCollect(const std::string &filename, enum CollectingMode mode) std::cout << "Writing quality tables..." << std::endl; QualityTablesFormatter qualityData(filename); - collection.Save(qualityData); + statisticsCollection.Save(qualityData); } break; case CollectHistograms: @@ -212,76 +220,17 @@ void actionCollect(const std::string &filename, enum CollectingMode mode) histogramCollection.Save(histograms); } break; - - /*const std::map<HistogramCollection::AntennaPair, LogHistogram*> &map = histogramCollection.GetHistograms(0); - Plot plotSlopes("histogram-slopes.pdf"); - plotSlopes.SetYRange(-10.0, 10.0); - Plot plotHistograms("histograms.pdf"); - for(std::map<HistogramCollection::AntennaPair, LogHistogram*>::const_iterator i = map.begin(); i != map.end(); ++i) - { - if(i->first.first != i->first.second) - { - const LogHistogram *histogram = i->second; - double rangeCentre = histogram->MinPositiveAmplitude(); - rangeCentre = exp2(floor(log2(rangeCentre))); - const double maxAmplitude = histogram->MaxAmplitude(); - std::cout << "Antennae " << i->first.first << " x " << i->first.second << "\n"; - std::stringstream s; - s << i->first.first << " x " << i->first.second; - //plotSlopes.StartLine(s.str()); - //plotHistograms.StartLine(s.str()); - plotSlopes.StartLine(); - plotSlopes.SetLogScale(true, false); - plotHistograms.StartLine(); - plotHistograms.SetLogScale(true, true); - while(rangeCentre < maxAmplitude && rangeCentre > 0.0) - { - const double rangeStart = rangeCentre * 0.75; - const double rangeEnd = rangeCentre * 1.5; - const double slope = histogram->NormalizedSlope(rangeStart, rangeEnd, LogHistogram::TotalAmplitudeHistogram); - std::cout << rangeStart << "-" << rangeEnd << ": " << slope << "\n"; - rangeCentre *= 2.0; - plotSlopes.PushDataPoint(rangeCentre, slope); - const double count = histogram->NormalizedCount(rangeStart, rangeEnd, LogHistogram::TotalAmplitudeHistogram); - if(count > 0 && std::isfinite(count)) - plotHistograms.PushDataPoint(rangeCentre, count); - } - } - } - Plot plotFine("histogram-fine.pdf"); - Plot plotGlobalSlopes("histogram-gslopes.pdf"); - plotFine.SetLogScale(true, true); - plotGlobalSlopes.SetLogScale(true, false); - plotGlobalSlopes.SetYRange(-5.0, 5.0); - LogHistogram intHistogram; - histogramCollection.GetHistogramForCrossCorrelations(0, intHistogram); - - plotFine.StartLine("Total"); - plotGlobalSlopes.StartLine("Total"); - for(LogHistogram::iterator i=intHistogram.begin(); i!=intHistogram.end(); ++i) - { - plotFine.PushDataPoint(i.value(), i.normalizedCount(LogHistogram::TotalAmplitudeHistogram)); - plotGlobalSlopes.PushDataPoint(i.value(), intHistogram.NormalizedSlope(i.value()*0.5, i.value()*2.0, LogHistogram::TotalAmplitudeHistogram)); - } - plotFine.StartLine("RFI"); - plotGlobalSlopes.StartLine("RFI"); - for(LogHistogram::iterator i=intHistogram.begin(); i!=intHistogram.end(); ++i) - { - plotFine.PushDataPoint(i.value(), i.normalizedCount(LogHistogram::RFIAmplitudeHistogram)); - plotGlobalSlopes.PushDataPoint(i.value(), intHistogram.NormalizedSlope(i.value()*0.5, i.value()*2.0, LogHistogram::RFIAmplitudeHistogram)); - } - plotFine.StartLine("Data"); - plotGlobalSlopes.StartLine("Data"); - for(LogHistogram::iterator i=intHistogram.begin(); i!=intHistogram.end(); ++i) - { - plotFine.PushDataPoint(i.value(), i.normalizedCount(LogHistogram::DataAmplitudeHistogram)); - plotGlobalSlopes.PushDataPoint(i.value(), intHistogram.NormalizedSlope(i.value()*0.5, i.value()*2.0, LogHistogram::DataAmplitudeHistogram)); - }*/ } std::cout << "Done.\n"; } +void actionCollectHistogram(const std::string &filename, HistogramCollection &histogramCollection) +{ + StatisticsCollection tempCollection; + actionCollect(filename, CollectHistograms, tempCollection, histogramCollection); +} + void printStatistics(std::complex<long double> *complexStat, unsigned count) { if(count != 1) @@ -481,10 +430,10 @@ void actionHistogram(const std::string &filename, const std::string &query) { HistogramTablesFormatter histogramFormatter(filename); const unsigned polarizationCount = MeasurementSet::GetPolarizationCount(filename); - HistogramCollection collection(polarizationCount); - collection.Load(histogramFormatter); if(query == "rfislope") { + HistogramCollection collection(polarizationCount); + collection.Load(histogramFormatter); MeasurementSet set(filename); std::cout << set.GetBandInfo(0).CenterFrequencyHz(); for(unsigned p=0;p<polarizationCount;++p) @@ -494,6 +443,29 @@ void actionHistogram(const std::string &filename, const std::string &query) std::cout << '\t' << histogram.NormalizedSlopeInRFIRegion(); } std::cout << '\n'; + } else if(query == "rfislope-per-baseline") + { + HistogramCollection collection; + actionCollectHistogram(filename, collection); + MeasurementSet set(filename); + size_t antennaCount = set.AntennaCount(); + AntennaInfo antennae[antennaCount]; + for(size_t a=0;a<antennaCount;++a) + antennae[a] = set.GetAntennaInfo(a); + + for(unsigned p=0;p<polarizationCount;++p) + { + const std::map<HistogramCollection::AntennaPair, LogHistogram*> &histogramMap = collection.GetRFIHistogram(p); + for(std::map<HistogramCollection::AntennaPair, LogHistogram*>::const_iterator i=histogramMap.begin(); i!=histogramMap.end();++i) + { + const unsigned a1 = i->first.first, a2 = i->first.second; + Baseline baseline(antennae[a1], antennae[a2]); + double length = baseline.Distance(); + const LogHistogram &histogram = *i->second; + double slope = histogram.NormalizedSlopeInRFIRegion(); + std::cout << p << '\t' << a1 << '\t' << a2 << '\t' << length << '\t' << slope << '\n'; + } + } } } diff --git a/CEP/DP3/AOFlagger/src/gui/plot/plot2d.cpp b/CEP/DP3/AOFlagger/src/gui/plot/plot2d.cpp index 2919ee7e5c463bea7afd8520287016a438d7468a..a3e567ba9dbf0886a1af210b78c5d82dafe8359a 100644 --- a/CEP/DP3/AOFlagger/src/gui/plot/plot2d.cpp +++ b/CEP/DP3/AOFlagger/src/gui/plot/plot2d.cpp @@ -238,7 +238,7 @@ void Plot2D::render(Cairo::RefPtr<Cairo::Context> cr, Plot2DPointSet &pointSet) y2Val = (log10(pointSet.GetY(i+1)) - minYLog10) / (maxYLog10 - minYLog10); } else { y1Val = (pointSet.GetY(i) - yMin) / (yMax - yMin); - y2Val = (pointSet.GetY(i) - yMin) / (yMax - yMin); + y2Val = (pointSet.GetY(i+1) - yMin) / (yMax - yMin); } if(y1Val < 0.0) y1Val = 0.0; if(y1Val > 1.0) y1Val = 1.0; diff --git a/CEP/DP3/AOFlagger/src/gui/quality/histogrampage.cpp b/CEP/DP3/AOFlagger/src/gui/quality/histogrampage.cpp index 1652e7921b92919c0d786dad1a1fa520c72e8ac9..147d70504b178e83e0ebe010a200ddec85975a1d 100644 --- a/CEP/DP3/AOFlagger/src/gui/quality/histogrampage.cpp +++ b/CEP/DP3/AOFlagger/src/gui/quality/histogrampage.cpp @@ -49,6 +49,8 @@ HistogramPage::HistogramPage() : _dndsButton("dN(S)/dS"), _plotPropertiesButton("Properties"), _dataExportButton("Data"), + _slopeFrame("Slope"), + _drawSlope("Draw"), _plotPropertiesWindow(0), _histograms(0) { @@ -120,6 +122,13 @@ HistogramPage::HistogramPage() : _dataExportButton.signal_clicked().connect(sigc::mem_fun(*this, &HistogramPage::onDataExportClicked)); _sideBox.pack_start(_dataExportButton, Gtk::PACK_SHRINK); + _slopeBox.pack_start(_slopeTextView, Gtk::PACK_SHRINK); + _drawSlope.signal_clicked().connect(sigc::mem_fun(*this, &HistogramPage::updatePlot)); + _slopeBox.pack_start(_drawSlope, Gtk::PACK_SHRINK); + + _slopeFrame.add(_slopeBox); + _sideBox.pack_start(_slopeFrame, Gtk::PACK_SHRINK); + pack_start(_sideBox, Gtk::PACK_SHRINK); _plotWidget.SetPlot(_plot); @@ -178,6 +187,7 @@ void HistogramPage::updatePlot() plotPolarization(*_histograms, 3); _plotWidget.Update(); + updateSlopeFrame(); updateDataWindow(); } } @@ -208,6 +218,10 @@ void HistogramPage::plotPolarization(class HistogramCollection &histograms, unsi { plotFit(rfiHistogram, "Fit to RFI"); } + if(_drawSlope.get_active()) + { + plotSlope(rfiHistogram, "Fitted slope"); + } } if(_notRFIHistogramButton.get_active()) @@ -323,6 +337,21 @@ void HistogramPage::addRayleighDifferenceToPlot(LogHistogram &histogram, double } } +void HistogramPage::plotSlope(class LogHistogram &histogram, const std::string &title) +{ + double start, end; + histogram.GetRFIRegion(start, end); + double slope = histogram.NormalizedSlope(start, end); + double offset = histogram.NormalizedSlopeOffset(start, end, slope); + _plot.StartLine(title, "Amplitude in arbitrary units (log)", "Frequency (log)"); + double xStart = log10(start / 10.0); + double xEnd = log10(histogram.MaxAmplitude()); + double yStart = xStart*slope + offset; + double yEnd = xEnd*slope + offset; + _plot.PushDataPoint(xStart, yStart); + _plot.PushDataPoint(xEnd, yEnd); +} + void HistogramPage::onPlotPropertiesClicked() { if(_plotPropertiesWindow == 0) @@ -342,6 +371,20 @@ void HistogramPage::onDataExportClicked() updateDataWindow(); } +void HistogramPage::updateSlopeFrame() +{ + std::stringstream str; + str << "Slopes:"; + for(size_t p=0;p<_histograms->PolarizationCount();++p) + { + LogHistogram histogram; + _histograms->GetRFIHistogramForCrossCorrelations(p, histogram); + double slope = histogram.NormalizedSlopeInRFIRegion(); + str << '\n' << slope; + } + _slopeTextView.get_buffer()->set_text(str.str()); +} + void HistogramPage::updateDataWindow() { if(_dataWindow->is_visible()) diff --git a/CEP/DP3/DPPP/src/Demixer.cc b/CEP/DP3/DPPP/src/Demixer.cc index 7978b8e9385b34b9bcd089246d41c50efd81238c..c7141e75fb151e936d0a691012622c9c75f44093 100644 --- a/CEP/DP3/DPPP/src/Demixer.cc +++ b/CEP/DP3/DPPP/src/Demixer.cc @@ -176,7 +176,7 @@ namespace LOFAR { // stations.begin(), stations.end())); MeasurementAIPS ___bla(input->msName()); - Instrument::Ptr instrument = ___bla.instrument(); + Instrument::ConstPtr instrument = ___bla.instrument(); // Get directions and make sure they are in J2000. @@ -223,8 +223,7 @@ namespace LOFAR { ModelConfig config; // config.setDirectionalGain(); config.setGain(); - BeamConfig beamConfig(BeamConfig::DEFAULT, false, - casa::Path("$LOFARROOT/share")); + BeamConfig beamConfig(BeamConfig::DEFAULT, false); config.setBeamConfig(beamConfig); config.setCache(); diff --git a/CEP/Imager/LofarFT/CMakeLists.txt b/CEP/Imager/LofarFT/CMakeLists.txt index 8b2233b9b20b1668232d425e53bf5c920edf7aaa..16bb5a78907e2cf608ab787ab1b486d47e424f47 100644 --- a/CEP/Imager/LofarFT/CMakeLists.txt +++ b/CEP/Imager/LofarFT/CMakeLists.txt @@ -1,11 +1,11 @@ # $Id$ -lofar_package(LofarFT 0.1 DEPENDS BBSKernel Common ParmDB) +lofar_package(LofarFT 0.1 DEPENDS BBSKernel Common ParmDB ElementResponse) lofar_find_package(Casarest REQUIRED COMPONENTS synthesis) lofar_find_package(Casacore REQUIRED COMPONENTS images msfits) lofar_find_package(Boost REQUIRED COMPONENTS thread) -lofar_find_package (FFTW3 REQUIRED COMPONENTS single double) +lofar_find_package(FFTW3 REQUIRED COMPONENTS single double) # Needed for casarest add_definitions(-DCASA_STANDALONE) diff --git a/CEP/Imager/LofarFT/include/LofarFT/LofarATerm.h b/CEP/Imager/LofarFT/include/LofarFT/LofarATerm.h index 87624dfdd5b815fabda1ce0b21f44c16136cee54..0eb48cf502d745831a0bf23629e80803da55dff0 100644 --- a/CEP/Imager/LofarFT/include/LofarFT/LofarATerm.h +++ b/CEP/Imager/LofarFT/include/LofarFT/LofarATerm.h @@ -24,271 +24,114 @@ #define LOFAR_LOFARFT_LOFARATERM_H #include <Common/LofarTypes.h> -#include <Common/lofar_map.h> #include <Common/lofar_vector.h> +#include <BBSKernel/Instrument.h> +#include <ParmDB/ParmFacade.h> #include <casa/Arrays/Array.h> -#include <casa/BasicSL/String.h> -#include <measures/Measures/MPosition.h> +#include <casa/Containers/Record.h> #include <measures/Measures/MDirection.h> +#include <measures/Measures/MEpoch.h> namespace casa { class DirectionCoordinate; - class MEpoch; class MeasurementSet; - class Path; } namespace LOFAR { - struct Vector3 - { - const double &operator[](uint i) const - { return __data[i]; } - - double &operator[](uint i) - { return __data[i]; } - - double __data[3]; - }; - - class AntennaField + class LofarATerm { public: - enum Axis - { - P, - Q, - R, - N_Axis - }; + LofarATerm(const casa::MeasurementSet &ms, const casa::Record& parameters); - struct Element + struct ITRFDirectionMap { - Vector3 offset; - bool flag[2]; + casa::MEpoch epoch; + BBS::Vector3 refDelay; + BBS::Vector3 refTile; + casa::Cube<casa::Double> directions; }; - - AntennaField() - { - } - - AntennaField(const casa::String &name, const Vector3 &position, - const Vector3 &p, - const Vector3 &q, const Vector3 &r); - - const casa::String &name() const; - const Vector3 &position() const; - const Vector3 &axis(Axis axis) const; - - bool isHBA() const; - - void appendTileElement(const Vector3 &offset); - inline uint nTileElement() const; - inline const Vector3 &tileElement(uint i) const; - - void appendElement(const Element &element); - inline uint nElement() const; - inline const Element &element(uint i) const; - - private: - casa::String m_name; - Vector3 m_position; - Vector3 m_axes[N_Axis]; - vector<Vector3> m_tileElements; - vector<Element> m_elements; - }; - - class Station - { - public: - Station() - { - } - - Station(const casa::String &name, const casa::MPosition &position); - Station(const casa::String &name, const casa::MPosition &position, - const AntennaField &field0); - Station(const casa::String &name, const casa::MPosition &position, - const AntennaField &field0, const AntennaField &field1); - - const casa::String &name() const; - const casa::MPosition &position() const; - - bool isPhasedArray() const; - uint nField() const; - const AntennaField &field(uint i) const; - - private: - casa::String m_name; - casa::MPosition m_position; - vector<AntennaField> m_fields; - }; - - class Instrument - { - public: - Instrument() - { - } - - Instrument(const casa::String &name, const casa::MPosition &position); - - template <typename T> - Instrument(const casa::String &name, const casa::MPosition &position, - T first, T last); - - const casa::String &name() const; - const casa::MPosition &position() const; - - uint nStations() const; - const Station &station(uint i) const; - const Station &station(const casa::String &name) const; - - void append(const Station &station); - - private: - casa::String m_name; - casa::MPosition m_position; - map<casa::String, uint> m_index; - vector<Station> m_stations; - }; - - inline uint AntennaField::nTileElement() const - { - return m_tileElements.size(); - } - - const Vector3 &AntennaField::tileElement(uint i) const - { - return m_tileElements[i]; - } - - inline uint AntennaField::nElement() const - { - return m_elements.size(); - } - - inline const AntennaField::Element &AntennaField::element(uint i) const - { - return m_elements[i]; - } - - template <typename T> - Instrument::Instrument(const casa::String &name, - const casa::MPosition &position, - T first, T last) - : m_name(name), - m_position(position), - m_stations(first, last) - { - } - - class BeamCoeff - { - public: - BeamCoeff(); - - void load(const casa::Path &path); - - // Center frequency used to scale frequency to range [-1.0, 1.0]. - double center() const - { - return m_center; - } - - // Width used to scale frequency to range [-1.0, 1.0]. - double width() const - { - return m_width; - } - - uint nElements() const - { - return m_coeff.shape()(0); - } - - uint nPowerFreq() const - { - return m_coeff.shape()(1); - } - - uint nPowerTheta() const - { - return m_coeff.shape()(2); - } - - uint nHarmonics() const - { - return m_coeff.shape()(3); - } - - casa::DComplex operator()(uint i, uint freq, uint theta, uint harmonic) const - { - return m_coeff(casa::IPosition(4, i, freq, theta, harmonic)); - } - - private: - double m_center, m_width; - casa::Array<casa::DComplex> m_coeff; - }; - - class LofarATerm - { - public: - LofarATerm(const casa::MeasurementSet &ms, - const casa::String &beamElementPath); - - vector<casa::Cube<casa::Complex> > evaluate(const casa::IPosition &shape, - const casa::DirectionCoordinate &coordinates, + + void setDirection(const casa::DirectionCoordinate &coordinates, const casa::IPosition &shape); + + void setEpoch(const casa::MEpoch &epoch); + + // Compute an ITRF direction vector for each pixel at the given epoch. This + // map can then be used to call any of the evaluate* functions. + ITRFDirectionMap + makeDirectionMap(const casa::DirectionCoordinate &coordinates, + const casa::IPosition &shape, + const casa::MEpoch &epoch) const; + + // Compute the LOFAR station response for the given station. This includes + // the effects of paralactic rotation, the dual dipole LOFAR antenna, the + // tile beam former (HBA only), and the station beam former. + // + // The freq argument is a list of frequencies at which the response will be + // evaluated. The reference argument is a list of station beam former + // reference frequencies. The normalize argument, when set to true, causes + // the response to be multiplied by the inverse of the response at the + // central pixel. + vector<casa::Cube<casa::Complex> > evaluate(uint idStation, + const casa::Vector<casa::Double> &freq, + const casa::Vector<casa::Double> &reference, bool normalize = false) + const; + + // Compute the array factor for the given station and polarization (0 = X, + // 1 = Y). + // + // The freq argument is a list of frequencies at which the array factor will + // be evaluated. The reference argument is a list of station beam former + // reference frequencies. The normalize argument, when set to true, causes + // the response to be multiplied by the inverse of the array factor at the + // central pixel. + vector<casa::Matrix<casa::Complex> > evaluateArrayFactor(uint idStation, + uint idPolarization, + const casa::Vector<casa::Double> &freq, + const casa::Vector<casa::Double> &reference, bool normalize = false) + const; + + // Compute the LOFAR element response for the given station and antenna + // field. This includes the effects of paralactic rotation and the dual + // dipole LOFAR antenna. + // + // The freq argument is a list of frequencies at which the response will be + // evaluated. The normalize argument, when set to true, causes the response + // to be multiplied by the inverse of the response at the central pixel. + vector<casa::Cube<casa::Complex> > evaluateElementResponse(uint idStation, + uint idField, + const casa::Vector<casa::Double> &freq, bool normalize = false) const; + + vector<casa::Cube<casa::Complex> > evaluateIonosphere( uint station, - const casa::MEpoch &epoch, const casa::Vector<casa::Double> &freq, - bool normalize = false) const; + bool normalize); private: - casa::Array<casa::DComplex> - normalize(const casa::Array<casa::DComplex> &response) const; - - casa::Cube<casa::Double> - computeITRFMap(const casa::DirectionCoordinate &coordinates, - const casa::IPosition &shape, - casa::MDirection::Convert convertor) const; - - casa::Array<casa::DComplex> evaluateStationBeam(const Station &station, - const Vector3 &refDelay, - const Vector3 &refTile, - const casa::Cube<casa::Double> &map, - const casa::Vector<casa::Double> &freq) const; - - casa::Cube<casa::DComplex> evaluateTileArrayFactor(const AntennaField &field, - const Vector3 &reference, - const casa::Cube<casa::Double> &map, - const casa::Vector<casa::Double> &freq) const; - - casa::Array<casa::DComplex> evaluateElementBeam(const BeamCoeff &coeff, - const AntennaField &field, - const casa::Cube<casa::Double> &map, - const casa::Vector<casa::Double> &freq) const; - - void initInstrument(const casa::MeasurementSet &ms); - - Station initStation(const casa::MeasurementSet &ms, - uint id, - const casa::String &name, - const casa::MPosition &position) const; - - void initReferenceDirections(const casa::MeasurementSet &ms, uint idField); - - void initReferenceFreq(const casa::MeasurementSet &ms, - uint idDataDescription); - - BeamCoeff m_coeffLBA, m_coeffHBA; - casa::MDirection m_refDelay, m_refTile; - double m_refFreq; - Instrument m_instrument; + + void initParmDB(const casa::String &parmdbname); + double get_parmvalue( std::string parmname ); + + casa::Record itsParameters; + + BBS::Instrument::Ptr itsInstrument; + const casa::DirectionCoordinate *itsDirectionCoordinates; + const casa::IPosition *itsShape; + casa::MDirection itsRefDelay, itsRefTile; + ITRFDirectionMap itsITRFDirectionMap; + + // state variables for ionosphere + casa::Bool itsapplyIonosphere; + LOFAR::BBS::ParmFacade* pdb; + double time, r0, beta, height; + casa::Vector<casa::String> cal_pp_names; + casa::Matrix<casa::Double> cal_pp; + casa::Vector<casa::Double> tec_white; + }; + } // namespace LOFAR #endif diff --git a/CEP/Imager/LofarFT/include/LofarFT/LofarATermOld.h b/CEP/Imager/LofarFT/include/LofarFT/LofarATermOld.h new file mode 100644 index 0000000000000000000000000000000000000000..02d88016369279431e17636f7717d19e89fd15bc --- /dev/null +++ b/CEP/Imager/LofarFT/include/LofarFT/LofarATermOld.h @@ -0,0 +1,294 @@ +//# LofarATermOld.h: Compute the LOFAR beam response on the sky. +//# +//# Copyright (C) 2011 +//# ASTRON (Netherlands Institute for Radio Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +//# +//# This file is part of the LOFAR software suite. +//# The LOFAR software suite is free software: you can redistribute it and/or +//# modify it under the terms of the GNU General Public License as published +//# by the Free Software Foundation, either version 3 of the License, or +//# (at your option) any later version. +//# +//# The LOFAR software suite 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License along +//# with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>. +//# +//# $Id$ + +#ifndef LOFAR_LOFARFT_LOFARATERMOLD_H +#define LOFAR_LOFARFT_LOFARATERMOLD_H + +#include <Common/LofarTypes.h> +#include <Common/lofar_map.h> +#include <Common/lofar_vector.h> + +#include <casa/Arrays/Array.h> +#include <casa/BasicSL/String.h> +#include <measures/Measures/MPosition.h> +#include <measures/Measures/MDirection.h> + +namespace casa +{ + class DirectionCoordinate; + class MEpoch; + class MeasurementSet; + class Path; +} + +namespace LOFAR +{ + struct Vector3 + { + const double &operator[](uint i) const + { return __data[i]; } + + double &operator[](uint i) + { return __data[i]; } + + double __data[3]; + }; + + class AntennaField + { + public: + enum Axis + { + P, + Q, + R, + N_Axis + }; + + struct Element + { + Vector3 offset; + bool flag[2]; + }; + + AntennaField() + { + } + + AntennaField(const casa::String &name, const Vector3 &position, + const Vector3 &p, + const Vector3 &q, const Vector3 &r); + + const casa::String &name() const; + const Vector3 &position() const; + const Vector3 &axis(Axis axis) const; + + bool isHBA() const; + + void appendTileElement(const Vector3 &offset); + inline uint nTileElement() const; + inline const Vector3 &tileElement(uint i) const; + + void appendElement(const Element &element); + inline uint nElement() const; + inline const Element &element(uint i) const; + + private: + casa::String m_name; + Vector3 m_position; + Vector3 m_axes[N_Axis]; + vector<Vector3> m_tileElements; + vector<Element> m_elements; + }; + + class Station + { + public: + Station() + { + } + + Station(const casa::String &name, const casa::MPosition &position); + Station(const casa::String &name, const casa::MPosition &position, + const AntennaField &field0); + Station(const casa::String &name, const casa::MPosition &position, + const AntennaField &field0, const AntennaField &field1); + + const casa::String &name() const; + const casa::MPosition &position() const; + + bool isPhasedArray() const; + uint nField() const; + const AntennaField &field(uint i) const; + + private: + casa::String m_name; + casa::MPosition m_position; + vector<AntennaField> m_fields; + }; + + class Instrument + { + public: + Instrument() + { + } + + Instrument(const casa::String &name, const casa::MPosition &position); + + template <typename T> + Instrument(const casa::String &name, const casa::MPosition &position, + T first, T last); + + const casa::String &name() const; + const casa::MPosition &position() const; + + uint nStations() const; + const Station &station(uint i) const; + const Station &station(const casa::String &name) const; + + void append(const Station &station); + + private: + casa::String m_name; + casa::MPosition m_position; + map<casa::String, uint> m_index; + vector<Station> m_stations; + }; + + inline uint AntennaField::nTileElement() const + { + return m_tileElements.size(); + } + + const Vector3 &AntennaField::tileElement(uint i) const + { + return m_tileElements[i]; + } + + inline uint AntennaField::nElement() const + { + return m_elements.size(); + } + + inline const AntennaField::Element &AntennaField::element(uint i) const + { + return m_elements[i]; + } + + template <typename T> + Instrument::Instrument(const casa::String &name, + const casa::MPosition &position, + T first, T last) + : m_name(name), + m_position(position), + m_stations(first, last) + { + } + + class BeamCoeff + { + public: + BeamCoeff(); + + void load(const casa::Path &path); + + // Center frequency used to scale frequency to range [-1.0, 1.0]. + double center() const + { + return m_center; + } + + // Width used to scale frequency to range [-1.0, 1.0]. + double width() const + { + return m_width; + } + + uint nElements() const + { + return m_coeff.shape()(0); + } + + uint nPowerFreq() const + { + return m_coeff.shape()(1); + } + + uint nPowerTheta() const + { + return m_coeff.shape()(2); + } + + uint nHarmonics() const + { + return m_coeff.shape()(3); + } + + casa::DComplex operator()(uint i, uint freq, uint theta, uint harmonic) const + { + return m_coeff(casa::IPosition(4, i, freq, theta, harmonic)); + } + + private: + double m_center, m_width; + casa::Array<casa::DComplex> m_coeff; + }; + + class LofarATermOld + { + public: + LofarATermOld(const casa::MeasurementSet &ms, + const casa::String &beamElementPath); + + vector<casa::Cube<casa::Complex> > evaluate(const casa::IPosition &shape, + const casa::DirectionCoordinate &coordinates, + uint station, + const casa::MEpoch &epoch, + const casa::Vector<casa::Double> &freq, + bool normalize = false) const; + + private: + casa::Array<casa::DComplex> + normalize(const casa::Array<casa::DComplex> &response) const; + + casa::Cube<casa::Double> + computeITRFMap(const casa::DirectionCoordinate &coordinates, + const casa::IPosition &shape, + casa::MDirection::Convert convertor) const; + + casa::Array<casa::DComplex> evaluateStationBeam(const Station &station, + const Vector3 &refDelay, + const Vector3 &refTile, + const casa::Cube<casa::Double> &map, + const casa::Vector<casa::Double> &freq) const; + + casa::Cube<casa::DComplex> evaluateTileArrayFactor(const AntennaField &field, + const Vector3 &reference, + const casa::Cube<casa::Double> &map, + const casa::Vector<casa::Double> &freq) const; + + casa::Array<casa::DComplex> evaluateElementBeam(const BeamCoeff &coeff, + const AntennaField &field, + const casa::Cube<casa::Double> &map, + const casa::Vector<casa::Double> &freq) const; + + void initInstrument(const casa::MeasurementSet &ms); + + Station initStation(const casa::MeasurementSet &ms, + uint id, + const casa::String &name, + const casa::MPosition &position) const; + + void initReferenceDirections(const casa::MeasurementSet &ms, uint idField); + + void initReferenceFreq(const casa::MeasurementSet &ms, + uint idDataDescription); + + BeamCoeff m_coeffLBA, m_coeffHBA; + casa::MDirection m_refDelay, m_refTile; + double m_refFreq; + Instrument m_instrument; + }; +} // namespace LOFAR + +#endif diff --git a/CEP/Imager/LofarFT/include/LofarFT/LofarConvolutionFunction.h b/CEP/Imager/LofarFT/include/LofarFT/LofarConvolutionFunction.h index 4bf2c5640ffcf674b4865a73fe015b9d38e0fdf9..5058100c751815273f41c1122ef798dea5552022 100644 --- a/CEP/Imager/LofarFT/include/LofarFT/LofarConvolutionFunction.h +++ b/CEP/Imager/LofarFT/include/LofarFT/LofarConvolutionFunction.h @@ -44,6 +44,11 @@ #include <coordinates/Coordinates/DirectionCoordinate.h> #include <casa/OS/PrecTimer.h> +#include <lattices/Lattices/ArrayLattice.h> +#include <lattices/Lattices/LatticeFFT.h> + + + using namespace casa; @@ -73,10 +78,16 @@ namespace LOFAR const MeasurementSet& ms, uInt nW, double Wmax, uInt oversample, - const String& beamElementPath, - Int verbose, - Int maxsupport, - const String& imgName); + Int verbose, + Int maxsupport, + const String& imgName, + Bool Use_EJones, + Bool Apply_Element, + const casa::Record& parameters + ); + //, + // Int TaylorTerm, + // Double RefFreq); // ~LofarConvolutionFunction () // { @@ -118,8 +129,12 @@ namespace LOFAR bool degridding_step, double Append_average_PB_CF, Matrix<Complex>& Stack_PB_CF, - double& sum_weight_square); + double& sum_weight_square, + uInt spw, Int TaylorTerm, double RefFreq); + Array<Complex> ApplyElementBeam(Array<Complex> input_grid, Double time, uInt spw, const Matrix<bool>& Mask_Mueller_in, bool degridding_step); + Array<Complex> ApplyElementBeam2(Array<Complex>& input_grid, Double time, uInt spw, const Matrix<bool>& Mask_Mueller_in, bool degridding_step, Int UsedMask=-1); + // Returns the average Primary Beam from the disk Matrix<float> Give_avg_pb(); @@ -133,20 +148,90 @@ namespace LOFAR // Zero padding of a Matrix Matrix<Complex> zero_padding(const Matrix<Complex>& Image, int Npixel_Out); + // Get the W scale. const WScale& wScale() const { return m_wScale; } + vector< Matrix< Bool > > itsVectorMasksDegridElement; + void MakeMaskDegrid( const Array<Complex>& gridin, Int NumMask) + { + + String MaskName("JAWS_masks_degrid/Mask"+String::toString(NumMask)+".boolim"); + File MaskFile(MaskName); + if(!MaskFile.exists()){ + //cout<<"... Making Masks ..."<<endl; + Matrix<Bool> Mask(IPosition(2,gridin.shape()[0],gridin.shape()[0]),false); + Matrix<Int> IntMask(IPosition(2,gridin.shape()[0],gridin.shape()[0]),false); + int GridSize(gridin.shape()[0]); + const Complex* inPtr = gridin.data(); + Bool* outPtr = Mask.data(); + for (uInt i=0; i<GridSize; ++i) { + for (uInt j=0; j<GridSize; ++j) { + if (inPtr->real() != 0 || inPtr->imag() != 0) { + (*(outPtr)) = true; + } + inPtr++; + outPtr++; + } + } + //itsVectorMasksDegridElement.push_back(Mask); + + store(Mask,MaskName); + //cout<<"... Done Making Masks ..."<<endl; + } + } + + Bool itsFilledVectorMasks; + //vector< Matrix< Bool > > itsVectorMasksDegridElement; + void ReadMaskDegrid() + { + Int NumMask(0); + while(true){ + String MaskName("JAWS_masks_degrid/Mask"+String::toString(NumMask)+".boolim"); + File MaskFile(MaskName); + if(MaskFile.exists()) + { + //cout<<"Reading:"<<MaskName<<endl; + PagedImage<Bool> pim(MaskName); + Array<Bool> arr = pim.get(); + Matrix<Bool> Mask; + Mask.reference (arr.nonDegenerate(2)); + itsVectorMasksDegridElement.push_back(Mask); + NumMask+=1; + } + else + { + break; + } + } + itsFilledVectorMasks=true; + + } + + Bool VectorMaskIsFilled(){return itsFilledVectorMasks;} + private: void normalized_fft (Matrix<Complex>&, bool toFreq=true); void normalized_fft (PrecTimer& timer, Matrix<Complex>&, bool toFreq=true); + Matrix<Complex> give_normalized_fft_lapack(const Matrix<Complex> &im, bool toFreq=true) + { + Matrix<Complex> result(im.copy()); + ArrayLattice<Complex> lattice(result); + LatticeFFT::cfft2d(lattice, toFreq); + if(toFreq){ + result/=static_cast<Float>(result.shape()(0)*result.shape()(1)); + } + else{ + result*=static_cast<Float>(result.shape()(0)*result.shape()(1)); + }; + return result; + } + MEpoch observationStartTime (const MeasurementSet &ms, uInt idObservation) const; - Double observationReferenceFreq (const MeasurementSet &ms, - uInt idDataDescription); - // Estime spheroidal convolution function from the support of the fft // of the spheroidal in the image plane Double makeSpheroidCut(); @@ -158,11 +243,12 @@ namespace LOFAR Double pixelSize, Double w) const; + // Return the angular resolution required for making the image of the // angular size determined by coordinates and shape. // The resolution is assumed to be the same on both direction axes. Double estimateAResolution(const IPosition &shape, - const DirectionCoordinate &coordinates) const; + const DirectionCoordinate &coordinates, double station_diam = 70.) const; // Apply a spheroidal taper to the input function. template <typename T> @@ -181,7 +267,216 @@ namespace LOFAR } } } + + + // Linear interpolation + template <typename T> + Matrix< T > LinearInterpol(Matrix<T> ImageIn, Int NpixOut) + { + Matrix<T> ImageOut(IPosition(2,NpixOut,NpixOut),0.); + float d0(1./(NpixOut-1.)); + float d1(1./(ImageIn.shape()[0]-1.)); + float dd(d0/d1); + float dx,dy,dxd,dyd,xin,yin; + float onef(1.); + uInt NpixOutm(NpixOut-1); + for(uInt i=0;i<(NpixOut);++i){ + dxd=i*dd; + xin=floor(dxd); + dx=dxd-xin; + for(uInt j=0;j<(NpixOut);++j){ + dyd=j*dd; + yin=floor(dyd); + dy=dyd-yin; + ImageOut(i,j)=(onef-dx)*(onef-dy)*ImageIn(xin,yin) + (onef-dx)*(dy)*ImageIn(xin,yin+1) + (dx)*(onef-dy)*ImageIn(xin+1,yin) + (dx)*(dy)*ImageIn(xin+1,yin+1); + } + } + return ImageOut; + } + + void Convolve(Matrix<Complex> gridin, Matrix<Complex> gridout, Matrix<Complex> ConvFunc){ + Int Support(ConvFunc.shape()[0]); + Int GridSize(gridin.shape()[0]); + Int off(Support/2); + for(uInt i=Support/2;i<GridSize-Support/2;++i){ + for(uInt j=Support/2;j<GridSize-Support/2;++j){ + if((gridin(i,j))!=Complex(0.,0.)){ + Complex val(gridin(i,j)); + for(uInt ii=0;ii<Support;++ii){ + for(uInt jj=0;jj<Support;++jj){ + gridout(i-off+ii,j-off+jj)+=ConvFunc(ii,jj)*val; + } + } + } + } + } + } + + void ConvolveOpt(Matrix<Complex> gridin, Matrix<Complex> gridout, Matrix<Complex> ConvFunc){ + Int Support(ConvFunc.shape()[0]); + Int GridSize(gridin.shape()[0]); + Int off(Support/2); + + Complex* __restrict__ gridInPtr = gridin.data(); + Complex* __restrict__ gridOutPtr = gridout.data(); + Complex* __restrict__ ConvFuncPtr = ConvFunc.data(); + + for(uInt i=Support/2;i<GridSize-Support/2;++i){ + for(uInt j=Support/2;j<GridSize-Support/2;++j){ + gridInPtr=gridin.data()+GridSize*i+j; + if (gridInPtr->real() != 0 || gridInPtr->imag() != 0) {//if((*gridInPtr)!=Complex(0.,0.)){ + ConvFuncPtr = ConvFunc.data(); + for(uInt jj=0;jj<Support;++jj){ + for(uInt ii=0;ii<Support;++ii){ + gridOutPtr = gridout.data()+(j-off+jj)*GridSize+i-off+ii; + (*gridOutPtr) += (*ConvFuncPtr)*(*gridInPtr); + ConvFuncPtr++;//=ConvFunc.data()+Support*ii+jj; + } + } + } + //gridInPtr++; + } + } + + } + + void ConvolveGer( const Matrix<Complex>& gridin, Matrix<Complex>& gridout, + const Matrix<Complex>& ConvFunc) + { + int Support(ConvFunc.shape()[0]); + int GridSize(gridin.shape()[0]); + int off(Support/2); + const Complex* inPtr = gridin.data() + off*GridSize + off; + for (uInt i=0; i<GridSize-Support; ++i) { + for (uInt j=0; j<GridSize-Support; ++j) { + if (inPtr->real() != 0 || inPtr->imag() != 0) { + const Complex* cfPtr = ConvFunc.data(); + for (uInt ii=0; ii<Support; ++ii) { + Complex* outPtr = gridout.data() + (i+ii)*GridSize + j; + for (uInt jj=0; jj<Support; ++jj) { + outPtr[jj] += *cfPtr++ * *inPtr; + } + } + } + inPtr++; + } + inPtr += Support; + } + } + + void ConvolveGerArray( const Array<Complex>& gridin, Int ConvPol, Matrix<Complex>& gridout, + const Matrix<Complex>& ConvFunc) + { + int Support(ConvFunc.shape()[0]); + int GridSize(gridin.shape()[0]); + int off(Support/2); + + const Complex* inPtr = gridin.data() + ConvPol*GridSize*GridSize + off*GridSize + off; + for (uInt i=0; i<GridSize-Support; ++i) { + for (uInt j=0; j<GridSize-Support; ++j) { + if (inPtr->real() != 0 || inPtr->imag() != 0) { + const Complex* cfPtr = ConvFunc.data(); + for (uInt ii=0; ii<Support; ++ii) { + Complex* outPtr = gridout.data() + (i+ii)*GridSize + j; + for (uInt jj=0; jj<Support; ++jj) { + outPtr[jj] += *cfPtr++ * *inPtr; + } + } + } + inPtr++; + } + inPtr += Support; + } + } + + + void ConvolveGerArrayMask( const Array<Complex>& gridin, Int ConvPol, Matrix<Complex>& gridout, + const Matrix<Complex>& ConvFunc, Int UsedMask) + { + int Support(ConvFunc.shape()[0]); + int GridSize(gridin.shape()[0]); + int off(Support/2); + + const Complex* inPtr = gridin.data() + ConvPol*GridSize*GridSize + off*GridSize + off; + const Bool* MaskPtr = itsVectorMasksDegridElement[UsedMask].data() + off*GridSize + off; + for (uInt i=0; i<GridSize-Support; ++i) { + for (uInt j=0; j<GridSize-Support; ++j) { + if ((*MaskPtr)==true) { + const Complex* cfPtr = ConvFunc.data(); + for (uInt ii=0; ii<Support; ++ii) { + Complex* outPtr = gridout.data() + (i+ii)*GridSize + j; + for (uInt jj=0; jj<Support; ++jj) { + outPtr[jj] += *cfPtr++ * *inPtr; + } + } + } + MaskPtr++; + inPtr++; + } + inPtr += Support; + MaskPtr += Support; + } + } + + + + // Linear interpolation + template <typename T> + Matrix< T > LinearInterpol2(Matrix<T> ImageIn, Int NpixOut) + { + Matrix<T> ImageOut(IPosition(2,NpixOut,NpixOut),1e-7); + int nd(ImageIn.shape()[0]); + int ni(NpixOut); + float off(-.5);//-(((1.+1./(nd-1.))-1.)/2.)*(nd-1)); + float a(nd/(ni-1.));//((1.+1./(nd-1.))/(ni-1.))*(nd-1)); + float dx,dy,dxd,dyd,xin,yin; + float onef(1.); + uInt NpixOutm(NpixOut-1); + for(uInt i=0;i<(NpixOut);++i){ + dxd=i*a+off; + xin=floor(dxd); + dx=dxd-xin; + for(uInt j=0;j<(NpixOut);++j){ + dyd=j*a+off; + yin=floor(dyd); + dy=dyd-yin; + if((dxd<0)||((xin+1)>ImageIn.shape()[0]-1.)){continue;} + if((dyd<0)||((yin+1)>ImageIn.shape()[0]-1.)){continue;} + ImageOut(i,j)=(onef-dx)*(onef-dy)*ImageIn(xin,yin) + (onef-dx)*(dy)*ImageIn(xin,yin+1) + (dx)*(onef-dy)*ImageIn(xin+1,yin) + (dx)*(dy)*ImageIn(xin+1,yin+1); + } + } + /* store(ImageIn,"ImageIn.img"); */ + /* store(ImageOut,"ImageOut.img"); */ + /* assert(false); */ + return ImageOut; + } + + void EstimateCoordShape(IPosition shape, DirectionCoordinate coordinate, double station_diameter=70.){ + coordinate = m_coordinates; + Double aPixelAngSize = min(m_pixelSizeSpheroidal, + estimateAResolution(m_shape, m_coordinates, station_diameter)); + + Double pixelSize = abs(m_coordinates.increment()[0]); + Double imageDiameter = pixelSize * m_shape(0); + Int nPixelsConv = imageDiameter / aPixelAngSize; + if (nPixelsConv > itsMaxSupport) { + nPixelsConv = itsMaxSupport; + } + // Make odd and optimal. + nPixelsConv = FFTCMatrix::optimalOddFFTSize (nPixelsConv); + aPixelAngSize = imageDiameter / nPixelsConv; + + shape=IPosition(2, nPixelsConv, nPixelsConv); + Vector<Double> increment_old(coordinate.increment()); + Vector<Double> increment(2); + increment[0] = aPixelAngSize*sign(increment_old[0]); + increment[1] = aPixelAngSize*sign(increment_old[1]); + coordinate.setIncrement(increment); + Vector<Double> refpix(2, 0.5*(nPixelsConv-1)); + coordinate.setReferencePixel(refpix); + } + Double spheroidal(Double nu) const; template <typename T> @@ -200,6 +495,7 @@ namespace LOFAR //# Data members. + casa::Record itsParameters; IPosition m_shape; DirectionCoordinate m_coordinates; WScale m_wScale; @@ -217,15 +513,20 @@ namespace LOFAR Matrix<Complex> Spheroid_cut; //# Stack of the convolution functions for the average PB calculation Matrix<Float> Spheroid_cut_im; + Matrix<Float> Spheroid_cut_im_element; //# List of the ferquencies the CF have to be caluclated for Vector< Double > list_freq; vector< Matrix<Complex> > m_WplanesStore; //# Aterm_store[double time][antenna][channel]=Cube[Npix,Npix,4] map<Double, vector< vector< Cube<Complex> > > > m_AtermStore; + map<Double, vector< vector< Cube<Complex> > > > m_AtermStore_element; + map<Double, vector< vector< Cube<Complex> > > > m_AtermStore_station; //# Average primary beam Matrix<Float> Im_Stack_PB_CF0; Int itsVerbose; Int itsMaxSupport; + // Int itsTaylorTerm; + //Double itsRefFreq; String itsImgName; vector<FFTCMatrix> itsFFTMachines; Double itsTimeW; @@ -240,6 +541,17 @@ namespace LOFAR Double itsTimeCFpar; Double itsTimeCFfft; unsigned long long itsTimeCFcnt; + Bool its_Use_EJones; + Bool its_Apply_Element; + uInt its_MaxWSupport; + uInt its_count_time; + mutable LogIO m_logIO; + Matrix<Complex> spheroid_cut_element_fft; + vector< vector< Matrix< Complex > > > GridsMueller; + LogIO &logIO() const + { + return m_logIO; + } }; @@ -264,7 +576,7 @@ namespace LOFAR void store (const DirectionCoordinate &dir, const Matrix<T> &data, const string &name) { - cout<<"Saving... "<<name<<endl; + //cout<<"Saving... "<<name<<endl; Vector<Int> stokes(1); stokes(0) = Stokes::I; CoordinateSystem csys; @@ -295,7 +607,7 @@ namespace LOFAR const string &name) { AlwaysAssert(data.shape()(2) == 4, SynthesisError); - cout<<"Saving... "<<name<<endl; + //cout<<"Saving... "<<name<<endl; Vector<Int> stokes(4); stokes(0) = Stokes::XX; stokes(1) = Stokes::XY; diff --git a/CEP/Imager/LofarFT/include/LofarFT/LofarConvolutionFunctionOld.h b/CEP/Imager/LofarFT/include/LofarFT/LofarConvolutionFunctionOld.h new file mode 100644 index 0000000000000000000000000000000000000000..f6d4a0e6499b5387651df5668a8c2a6ad24582c7 --- /dev/null +++ b/CEP/Imager/LofarFT/include/LofarFT/LofarConvolutionFunctionOld.h @@ -0,0 +1,234 @@ +//# LofarConvolutionFunctionOld.h: Compute LOFAR convolution functions on demand. +//# +//# Copyright (C) 2011 +//# ASTRON (Netherlands Institute for Radio Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +//# +//# This file is part of the LOFAR software suite. +//# The LOFAR software suite is free software: you can redistribute it and/or +//# modify it under the terms of the GNU General Public License as published +//# by the Free Software Foundation, either version 3 of the License, or +//# (at your option) any later version. +//# +//# The LOFAR software suite 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License along +//# with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>. +//# +//# $Id$ + +#ifndef LOFARFT_LOFARCONVOLUTIONFUNCTIONOLD_H +#define LOFARFT_LOFARCONVOLUTIONFUNCTIONOLD_H + +#include <LofarFT/LofarATermOld.h> +#include <LofarFT/LofarWTerm.h> +#include <LofarFT/LofarCFStore.h> +#include <LofarFT/FFTCMatrix.h> +#include <Common/Timer.h> + +#include <casa/Arrays/Cube.h> +#include <casa/Arrays/Matrix.h> +#include <casa/Arrays/MatrixMath.h> +#include <casa/Arrays/ArrayIter.h> +#include <casa/Arrays/ArrayMath.h> +#include <images/Images/PagedImage.h> +#include <casa/Utilities/Assert.h> +#include <ms/MeasurementSets/MeasurementSet.h> +#include <measures/Measures/MDirection.h> +#include <coordinates/Coordinates/CoordinateSystem.h> +#include <coordinates/Coordinates/SpectralCoordinate.h> +#include <coordinates/Coordinates/StokesCoordinate.h> +#include <coordinates/Coordinates/DirectionCoordinate.h> +#include <casa/OS/PrecTimer.h> + + +using namespace casa; + +namespace LOFAR +{ + + class LofarConvolutionFunctionOld + { + + public: + LofarConvolutionFunctionOld(const IPosition& shape, + const DirectionCoordinate& coordinates, + const MeasurementSet& ms, + uInt nW, double Wmax, + uInt oversample, + const String& beamElementPath, + Int verbose, + Int maxsupport, + const String& imgName); + +// ~LofarConvolutionFunctionOld () +// { +// } + + // Show the relative timings of the various steps. + void showTimings (std::ostream&, double duration, double timeCF) const; + + // Show percentage of value in total with 1 decimal. + static void showPerc1 (std::ostream& os, double value, double total); + + // Compute and store W-terms and A-terms in the fourier domain + void store_all_W_images(); + + // Get the spheroidal cut. + const Matrix<Float>& getSpheroidCut(); + + // Get the spheroidal cut from the file. + static Matrix<Float> getSpheroidCut (const String& imgName); + + // Get the average PB from the file. + static Matrix<Float> getAveragePB (const String& imgName); + + + // Compute the fft of the beam at the minimal resolution for all antennas, + // and append it to a map object with a (double time) key. + void computeAterm(Double time); + + // Compute the convolution function for all channel, for the polarisations + // specified in the Mueller_mask matrix + // Also specify weither to compute the Mueller matrix for the forward or + // the backward step. A dirty way to calculate the average beam has been + // implemented, by specifying the beam correcting to the given baseline + // and timeslot. + // RETURNS in a LofarCFStore: result[channel][Mueller row][Mueller column] + LofarCFStore makeConvolutionFunction(uInt stationA, uInt stationB, + Double time, Double w, + const Matrix<bool>& Mask_Mueller, + bool degridding_step, + double Append_average_PB_CF, + Matrix<Complex>& Stack_PB_CF, + double& sum_weight_square); + + // Returns the average Primary Beam from the disk + Matrix<float> Give_avg_pb(); + + // Compute the average Primary Beam from the Stack of convolution functions + Matrix<Float> Compute_avg_pb(Matrix<Complex> &Sum_Stack_PB_CF, + double sum_weight_square); + + // Zero padding of a Cube + Cube<Complex> zero_padding(const Cube<Complex>& Image, int Npixel_Out); + + // Zero padding of a Matrix + Matrix<Complex> zero_padding(const Matrix<Complex>& Image, int Npixel_Out); + + // Get the W scale. + const WScale& wScale() const + { return m_wScale; } + + private: + void normalized_fft (Matrix<Complex>&, bool toFreq=true); + void normalized_fft (PrecTimer& timer, Matrix<Complex>&, bool toFreq=true); + + MEpoch observationStartTime (const MeasurementSet &ms, + uInt idObservation) const; + + Double observationReferenceFreq (const MeasurementSet &ms, + uInt idDataDescription); + + // Estime spheroidal convolution function from the support of the fft + // of the spheroidal in the image plane + Double makeSpheroidCut(); + + // Return the angular resolution required for making the image of the + // angular size determined by coordinates and shape. + // The resolution is assumed to be the same on both direction axes. + Double estimateWResolution(const IPosition &shape, + Double pixelSize, + Double w) const; + + // Return the angular resolution required for making the image of the + // angular size determined by coordinates and shape. + // The resolution is assumed to be the same on both direction axes. + Double estimateAResolution(const IPosition &shape, + const DirectionCoordinate &coordinates) const; + + // Apply a spheroidal taper to the input function. + template <typename T> + void taper (Matrix<T> &function) const + { + AlwaysAssert(function.shape()[0] == function.shape()[1], SynthesisError); + uInt size = function.shape()[0]; + Double halfSize = (size-1) / 2.0; + Vector<Double> x(size); + for (uInt i=0; i<size; ++i) { + x[i] = spheroidal(abs(i - halfSize) / halfSize); + } + for (uInt i=0; i<size; ++i) { + for (uInt j=0; j<size; ++j) { + function(j, i) *= x[i] * x[j]; + } + } + } + + Double spheroidal(Double nu) const; + + template <typename T> + uInt findSupport(Matrix<T> &function, Double threshold) const + { + /// Double peak = abs(max(abs(function))); + Double peak = max(amplitude(function)); + threshold *= peak; + uInt halfSize = function.shape()[0] / 2; + uInt x = 0; + while (x < halfSize && abs(function(x, halfSize)) < threshold) { + ++x; + } + return 2 * (halfSize - x); + } + + + //# Data members. + IPosition m_shape; + DirectionCoordinate m_coordinates; + WScale m_wScale; + LofarWTerm m_wTerm; + LofarATermOld m_aTerm; + Double m_maxW; + Double m_pixelSizeSpheroidal; + uInt m_nWPlanes; + uInt m_nStations; + uInt m_oversampling; + uInt m_nChannel; + Double m_refFrequency; + uInt m_maxCFSupport; + //# Stack of the convolution functions for the average PB calculation + Matrix<Complex> Spheroid_cut; + //# Stack of the convolution functions for the average PB calculation + Matrix<Float> Spheroid_cut_im; + //# List of the ferquencies the CF have to be caluclated for + Vector< Double > list_freq; + vector< Matrix<Complex> > m_WplanesStore; + //# Aterm_store[double time][antenna][channel]=Cube[Npix,Npix,4] + map<Double, vector< vector< Cube<Complex> > > > m_AtermStore; + //# Average primary beam + Matrix<Float> Im_Stack_PB_CF0; + Int itsVerbose; + Int itsMaxSupport; + String itsImgName; + vector<FFTCMatrix> itsFFTMachines; + Double itsTimeW; + Double itsTimeWpar; + Double itsTimeWfft; + unsigned long long itsTimeWcnt; + Double itsTimeA; + Double itsTimeApar; + Double itsTimeAfft; + unsigned long long itsTimeAcnt; + Double itsTimeCF; + Double itsTimeCFpar; + Double itsTimeCFfft; + unsigned long long itsTimeCFcnt; + }; + + +} //# end namespace casa + +#endif diff --git a/CEP/Imager/LofarFT/include/LofarFT/LofarCubeSkyEquation.h b/CEP/Imager/LofarFT/include/LofarFT/LofarCubeSkyEquation.h index 1a409d92a34089ff8382ca3cd6b9fba73ad6149d..9d82a5163d03cfabdb0f3fce07ef5c5b30d7e4cc 100644 --- a/CEP/Imager/LofarFT/include/LofarFT/LofarCubeSkyEquation.h +++ b/CEP/Imager/LofarFT/include/LofarFT/LofarCubeSkyEquation.h @@ -46,36 +46,52 @@ class LofarCubeSkyEquation : public SkyEquation { public: LofarCubeSkyEquation(SkyModel& sm, VisSet& vs, FTMachine& ft, ComponentFTMachine& cft, Bool noModelCol=False); - + //Read only iterator...hence no scratch col LofarCubeSkyEquation(SkyModel& sm, ROVisibilityIterator& vi, FTMachine& ft, ComponentFTMachine& cft, Bool noModelCol=False); virtual ~LofarCubeSkyEquation(); virtual void predict(Bool incremental=False, MS::PredefinedColumns Type=MS::MODEL_DATA); virtual void gradientsChiSquared(Bool incremental, Bool commitModel=False); - + +// virtual Matrix<Float> GiveAvgPB (Int taylor_order) +// { +// Matrix< Float > a((ftm_p[taylor_order]->getAveragePB()).copy()); +// return a; +// }; + + /* virtual const Matrix<Float>& GiveAvgPB(Int taylor_order) { */ + /* Matrix< Float> a(IPosition(2,2,2),0.); */ + /* return a; */ + /* }; */ + virtual void initializePutSlice(const VisBuffer& vb, Int cubeSlice=0, Int nCubeSlice=1); - virtual void putSlice(VisBuffer& vb, Bool dopsf, - FTMachine::Type col,Int cubeSlice=0, + virtual void putSlice(VisBuffer& vb, Bool dopsf, + FTMachine::Type col,Int cubeSlice=0, Int nCubeSlice=1); - virtual void finalizePutSlice(const VisBuffer& vb, + virtual void finalizePutSlice(const VisBuffer& vb, Int cubeSlice=0, Int nCubeSlice=1); void initializeGetSlice(const VisBuffer& vb, Int row, - Bool incremental, Int cubeSlice=0, - Int nCubeSlice=1); - virtual VisBuffer& getSlice(VisBuffer& vb, + Bool incremental, Int cubeSlice=0, + Int nCubeSlice=1); + virtual VisBuffer& getSlice(VisBuffer& vb, Bool incremental, Int cubeSlice=0, - Int nCubeSlice=1); + Int nCubeSlice=1); void finalizeGetSlice(); void isLargeCube(ImageInterface<Complex>& theIm, Int& nCubeSlice); //void makeApproxPSF(Int model, ImageInterface<Float>& psf); - //virtual void makeApproxPSF(Int model, ImageInterface<Float>& psf); + //virtual void makeApproxPSF(Int model, ImageInterface<Float>& psf); void makeApproxPSF(PtrBlock<TempImage<Float> * >& psfs); //Get the flux scale that the ftmachines have if they have virtual void getCoverageImage(Int model, ImageInterface<Float>& im); + + + protected: + + //Different versions of psf making void makeSimplePSF(PtrBlock<TempImage<Float> * >& psfs); void makeMosaicPSF(PtrBlock<TempImage<Float> * >& psfs); @@ -85,15 +101,16 @@ class LofarCubeSkyEquation : public SkyEquation { Block<Matrix<Float> >weightSlice_p; Slicer sl_p; Int nchanPerSlice_p; - // Type of copy + // Type of copy // 0 => a independent image just with coordinates gotten from cImage // 1 => a subImage referencing cImage ...no image copy - void sliceCube(CountedPtr<ImageInterface<Complex> >& slice,Int model, Int cubeSlice, Int nCubeSlice, Int typeOfCopy=0); + void sliceCube(CountedPtr<ImageInterface<Complex> >& slice,Int model, Int cubeSlice, Int nCubeSlice, Int typeOfCopy=0); void sliceCube(SubImage<Float>*& slice,ImageInterface<Float>& image, Int cubeSlice, Int nCubeSlice); //frequency range from image Bool getFreqRange(ROVisibilityIterator& vi, const CoordinateSystem& coords, Int slice, Int nslice); + private: // if skyjones changed in get or put we need to tell put or get respectively // about it @@ -101,6 +118,7 @@ class LofarCubeSkyEquation : public SkyEquation { Bool destroyVisibilityIterator_p; + Bool internalChangesPut_p; Bool internalChangesGet_p; Bool firstOneChangesPut_p; diff --git a/CEP/Imager/LofarFT/include/LofarFT/LofarFTMachine.h b/CEP/Imager/LofarFT/include/LofarFT/LofarFTMachine.h index eac1048497a8e110de7e35af3c38f3eea650c697..ad54ac195d515c23a1b4004c81c5fe5e73b54fc5 100644 --- a/CEP/Imager/LofarFT/include/LofarFT/LofarFTMachine.h +++ b/CEP/Imager/LofarFT/include/LofarFT/LofarFTMachine.h @@ -48,6 +48,7 @@ #include <lattices/Lattices/LatticeCache.h> #include <lattices/Lattices/ArrayLattice.h> +#include <Common/OpenMP.h> using namespace casa; @@ -144,13 +145,25 @@ public: LofarFTMachine(Long cachesize, Int tilesize, CountedPtr<VisibilityResamplerBase>& visResampler, String convType, const MeasurementSet& ms, Int nwPlanes, MPosition mLocation, Float padding, Bool usezero, - Bool useDoublePrec, double wmax, const String& beamPath, + Bool useDoublePrec, double wmax, Int verbose, - Int maxsupport, + Int maxsupport, Int oversample, const String& imageName, const Matrix<Bool>& gridMuellerMask, - const Matrix<Bool>& degridMuellerMask); + const Matrix<Bool>& degridMuellerMask, + Double RefFreq, + Bool Use_Linear_Interp_Gridder, + Bool Use_EJones, + int StepApplyElement, + Double PBCut, + Bool PredictFT, + String PsfOnDisk, + Bool UseMasksDegrid, + Bool ReallyDoPSF, + const casa::Record& parameters + );//, + //Double FillFactor); // LofarFTMachine(Long cachesize, Int tilesize, CountedPtr<VisibilityResamplerBase>& visResampler,String convType, // MDirection mTangent, Float padding=1.0, Bool usezero=True, // Bool useDoublePrec=False); @@ -205,6 +218,8 @@ public: void put(const VisBuffer& vb, Int row=-1, Bool dopsf=False, FTMachine::Type type=FTMachine::OBSERVED); + mutable Matrix<Float> itsAvgPB; + Bool its_Use_Linear_Interp_Gridder; // Make the entire image void makeImage(FTMachine::Type type, @@ -217,7 +232,7 @@ public: ImageInterface<Complex>& getImage(Matrix<Float>&, Bool normalize=True); // Get the average primary beam. - const Matrix<Float>& getAveragePB() const; + virtual const Matrix<Float>& getAveragePB() const; // Get the spheroidal cut. const Matrix<Float>& getSpheroidCut() const @@ -242,7 +257,7 @@ public: // size is not done. If sumWt is not provided, normalization by // the sum of weights is also not done. // - + virtual void makeSensitivityImage(Lattice<Complex>&, @@ -289,18 +304,33 @@ public: virtual void setNoPadding(Bool nopad){noPadding_p=nopad;}; virtual String name(); - virtual void setMiscInfo(const Int qualifier){(void)qualifier;}; + //virtual void setMiscInfo(const Int qualifier){(void)qualifier;}; + + //Cyr: The FTMachine has got to know the order of the Taylor term + virtual void setMiscInfo(const Int qualifier){thisterm_p=qualifier;}; virtual void ComputeResiduals(VisBuffer&vb, Bool useCorrected); - void makeConjPolMap(const VisBuffer& vb, const Vector<Int> cfPolMap, Vector<Int>& conjPolMap); - // Vector<Int> makeConjPolMap(const VisBuffer& vb); - void makeCFPolMap(const VisBuffer& vb, const Vector<Int>& cfstokes, Vector<Int>& polM); + void makeConjPolMap(const VisBuffer& vb, const Vector<Int> cfPolMap, Vector<Int>& conjPolMap); + // Vector<Int> makeConjPolMap(const VisBuffer& vb); + void makeCFPolMap(const VisBuffer& vb, const Vector<Int>& cfstokes, Vector<Int>& polM); + + String itsNamePsfOnDisk; + void setPsfOnDisk(String NamePsf){itsNamePsfOnDisk=NamePsf;} + virtual String GiveNamePsfOnDisk(){return itsNamePsfOnDisk;} + protected: // Padding in FFT Float padding_p; - + Int thisterm_p; + Double itsRefFreq; + Bool itsPredictFT; + Int itsTotalStepsGrid; + Int itsTotalStepsDeGrid; + Bool itsMasksAllDone; + Bool its_UseMasksDegrid; + //Float its_FillFactor; // Get the appropriate data pointer Array<Complex>* getDataPointer(const IPosition&, Bool); @@ -322,6 +352,65 @@ protected: // Gridder ConvolveGridder<Double, Complex>* gridder; + //Sum Grids + void SumGridsOMP(Array<Complex>& grid, const Array<Complex>& GridToAdd){ + int y,ch,pol,dChan,dPol,dx; + int GridSize(grid.shape()[0]); + int NPol(grid.shape()[2]); + int NChan(grid.shape()[3]); + Complex* gridPtr; + const Complex* GridToAddPtr; + +#pragma omp parallel for private(y,ch,pol,gridPtr,GridToAddPtr) + for(int x=0 ; x<grid.shape()[0] ; ++x){ + for(ch=0 ; ch<NChan ; ++ch){ + for(pol=0 ; pol<NPol ; ++pol){ + gridPtr = grid.data() + ch*NPol*GridSize*GridSize + pol*GridSize*GridSize+x*GridSize; + GridToAddPtr = GridToAdd.data() + ch*NPol*GridSize*GridSize + pol*GridSize*GridSize+x*GridSize; + for(y=0 ; y<grid.shape()[1] ; ++y){ + (*gridPtr++) += *GridToAddPtr++; + //gridPtr++; + //GridToAddPtr++; + } + } + } + } + + } + + void SumGridsOMP(Array<Complex>& grid, const vector< Array<Complex> >& GridToAdd0 ){ + + for(uInt vv=0; vv<GridToAdd0.size();vv++){ + Array<Complex> GridToAdd(GridToAdd0[vv]); + int y,ch,pol,dChan,dPol,dx; + int GridSize(grid.shape()[0]); + int NPol(grid.shape()[2]); + int NChan(grid.shape()[3]); + Complex* gridPtr; + const Complex* GridToAddPtr; + +#pragma omp parallel for private(y,ch,pol,gridPtr,GridToAddPtr) + for(int x=0 ; x<grid.shape()[0] ; ++x){ + for(ch=0 ; ch<NChan ; ++ch){ + for(pol=0 ; pol<NPol ; ++pol){ + gridPtr = grid.data() + ch*NPol*GridSize*GridSize + pol*GridSize*GridSize+x*GridSize; + GridToAddPtr = GridToAdd.data() + ch*NPol*GridSize*GridSize + pol*GridSize*GridSize+x*GridSize; + for(y=0 ; y<grid.shape()[1] ; ++y){ + (*gridPtr++) += *GridToAddPtr++; + //gridPtr++; + //GridToAddPtr++; + } + } + } + } + } + + } + + + + + // Is this tiled? Bool isTiled; @@ -344,15 +433,18 @@ protected: // Arrays for non-tiled gridding (one per thread). vector< Array<Complex> > itsGriddedData; + Array<Complex> its_stacked_GriddedData; + vector< Array<DComplex> > itsGriddedData2; vector< Matrix<Complex> > itsSumPB; vector< Matrix<Double> > itsSumWeight; vector< double > itsSumCFWeight; + + ///Array<Complex> griddedData; ///Array<DComplex> griddedData2; ///Matrix<Complex> itsSumPB; ///double itsSumWeight; - mutable Matrix<Float> itsAvgPB; Int priorCacheSize; @@ -385,17 +477,22 @@ protected: LofarVisResampler visResamplers_p; + casa::Record itsParameters; casa::MeasurementSet itsMS; Int itsNWPlanes; double itsWMax; + Double its_PBCut; int itsNThread; - + Bool its_Use_EJones; + Bool its_Apply_Element; + Bool its_Already_Initialized; + Bool its_reallyDoPSF; CountedPtr<LofarConvolutionFunction> itsConvFunc; Vector<Int> ConjCFMap_p, CFMap_p; - String itsBeamPath; int itsVerbose; int itsMaxSupport; Int itsOversample; + Vector< Double > itsListFreq; String itsImgName; Matrix<Bool> itsGridMuellerMask; Matrix<Bool> itsDegridMuellerMask; @@ -403,12 +500,22 @@ protected: double itsDegriddingTime; double itsCFTime; PrecTimer itsTotalTimer; + PrecTimer itsCyrilTimer; + + double itsNextApplyTime; + int itsCounterTimes; + int itsStepApplyElement; + double itsTStartObs; + double itsDeltaTime; + Array<Complex> itsTmpStackedGriddedData; + Array<Complex> itsGridToDegrid; + template <class T> void store(const Cube<T> &data, const string &name) { - + CoordinateSystem csys; Matrix<Double> xform(2, 2); xform = 0.0; @@ -427,7 +534,7 @@ protected: stokes(3) = Stokes::YY; csys.addCoordinate(StokesCoordinate(stokes)); csys.addCoordinate(SpectralCoordinate(casa::MFrequency::TOPO, 60e6, 0.0, 0.0, 60e6)); - + PagedImage<T> im(TiledShape(IPosition(4, data.shape()(0), data.shape()(1), 4, 1)), csys, name); im.putSlice(data, IPosition(4, 0, 0, 0, 0)); } diff --git a/CEP/Imager/LofarFT/include/LofarFT/LofarFTMachineOld.h b/CEP/Imager/LofarFT/include/LofarFT/LofarFTMachineOld.h new file mode 100644 index 0000000000000000000000000000000000000000..61ad036b49a5efeae5bb7d7a46c68e4bc9e07bfc --- /dev/null +++ b/CEP/Imager/LofarFT/include/LofarFT/LofarFTMachineOld.h @@ -0,0 +1,440 @@ +//# LofarFTMachineOld.h: Definition for LofarFTMachineOld +//# Copyright (C) 1996,1997,1998,1999,2000,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$ + +#ifndef LOFARFT_LOFARFTMACHINEOLD_H +#define LOFARFT_LOFARFTMACHINEOLD_H + +#include <synthesis/MeasurementComponents/FTMachine.h> +#include <casa/OS/File.h> +#include <casa/OS/PrecTimer.h> +#include <LofarFT/LofarVisResamplerOld.h> +#include <LofarFT/LofarConvolutionFunctionOld.h> +#include <LofarFT/LofarCFStore.h> +#include <casa/Arrays/Matrix.h> +#include <scimath/Mathematics/FFTServer.h> +#include <msvis/MSVis/VisBuffer.h> +#include <images/Images/ImageInterface.h> +#include <images/Images/ImageInterface.h> +#include <casa/Containers/Block.h> +#include <casa/Arrays/Array.h> +#include <casa/Arrays/Vector.h> +#include <casa/Arrays/Matrix.h> +#include <scimath/Mathematics/ConvolveGridder.h> +#include <lattices/Lattices/LatticeCache.h> +#include <lattices/Lattices/ArrayLattice.h> + + +using namespace casa; + +namespace LOFAR { + +class casa::UVWMachine; +// <summary> An FTMachine for Gridded Fourier transforms </summary> + +// <use visibility=export> + +// <reviewed reviewer="" date="" tests="" demos=""> + +// <prerequisite> +// <li> <linkto class=FTMachine>FTMachine</linkto> module +// <li> <linkto class=SkyEquation>SkyEquation</linkto> module +// <li> <linkto class=VisBuffer>VisBuffer</linkto> module +// </prerequisite> +// +// <etymology> +// FTMachine is a Machine for Fourier Transforms. LofarFTMachine does +// Grid-based Fourier transforms. +// </etymology> +// +// <synopsis> +// The <linkto class=SkyEquation>SkyEquation</linkto> needs to be able +// to perform Fourier transforms on visibility data. LofarFTMachine +// allows efficient Fourier Transform processing using a +// <linkto class=VisBuffer>VisBuffer</linkto> which encapsulates +// a chunk of visibility (typically all baselines for one time) +// together with all the information needed for processing +// (e.g. UVW coordinates). +// +// Gridding and degridding in LofarFTMachine are performed using a +// novel sort-less algorithm. In this approach, the gridded plane is +// divided into small patches, a cache of which is maintained in memory +// using a general-purpose <linkto class=LatticeCache>LatticeCache</linkto> class. As the (time-sorted) +// visibility data move around slowly in the Fourier plane, patches are +// swapped in and out as necessary. Thus, optimally, one would keep at +// least one patch per baseline. +// +// A grid cache is defined on construction. If the gridded uv plane is smaller +// than this, it is kept entirely in memory and all gridding and +// degridding is done entirely in memory. Otherwise a cache of tiles is +// kept an paged in and out as necessary. Optimally the cache should be +// big enough to hold all polarizations and frequencies for all +// baselines. The paging rate will then be small. As the cache size is +// reduced below this critical value, paging increases. The algorithm will +// work for only one patch but it will be very slow! +// +// This scheme works well for arrays having a moderate number of +// antennas since the saving in space goes as the ratio of +// baselines to image size. For the ATCA, VLBA and WSRT, this ratio is +// quite favorable. For the VLA, one requires images of greater than +// about 200 pixels on a side to make it worthwhile. +// +// The FFT step is done plane by plane for images having less than +// 1024 * 1024 pixels on each plane, and line by line otherwise. +// +// The gridding and degridding steps are implemented in Fortran +// for speed. In gridding, the visibilities are added onto the +// grid points in the neighborhood using a weighting function. +// In degridding, the value is derived by a weight summ of the +// same points, using the same weighting function. +// </synopsis> +// +// <example> +// See the example for <linkto class=SkyModel>SkyModel</linkto>. +// </example> +// +// <motivation> +// Define an interface to allow efficient processing of chunks of +// visibility data +// </motivation> +// +// <todo asof="97/10/01"> +// <ul> Deal with large VLA spectral line case +// </todo> + +class LofarFTMachineOld : public casa::FTMachine { +public: + + // Constructor: cachesize is the size of the cache in words + // (e.g. a few million is a good number), tilesize is the + // size of the tile used in gridding (cannot be less than + // 12, 16 works in most cases), and convType is the type of + // gridding used (SF is prolate spheriodal wavefunction, + // and BOX is plain box-car summation). mLocation is + // the position to be used in some phase rotations. If + // mTangent is specified then the uvw rotation is done for + // that location iso the image center. + // <group> +// LofarFTMachineOld(Long cachesize, Int tilesize, CountedPtr<VisibilityResamplerBase>& visResampler, +// String convType="SF", Float padding=1.0, Bool usezero=True, Bool useDoublePrec=False); + LofarFTMachineOld(Long cachesize, Int tilesize, CountedPtr<VisibilityResamplerBase>& visResampler, String convType, const MeasurementSet& ms, + Int nwPlanes, + MPosition mLocation, Float padding, Bool usezero, + Bool useDoublePrec, double wmax, const String& beamPath, + Int verbose, + Int maxsupport, + Int oversample, + const String& imageName, + const Matrix<Bool>& gridMuellerMask, + const Matrix<Bool>& degridMuellerMask); +// LofarFTMachineOld(Long cachesize, Int tilesize, CountedPtr<VisibilityResamplerBase>& visResampler,String convType, +// MDirection mTangent, Float padding=1.0, Bool usezero=True, +// Bool useDoublePrec=False); +// LofarFTMachineOld(Long cachesize, Int tilesize, CountedPtr<VisibilityResamplerBase>& visResampler,String convType, +// MPosition mLocation, MDirection mTangent, Float passing=1.0, +// Bool usezero=True, Bool useDoublePrec=False); + // </group> + + // Construct from a Record containing the LofarFTMachineOld state +// LofarFTMachineOld(const RecordInterface& stateRec); + + // Copy constructor + LofarFTMachineOld(const LofarFTMachineOld &other); + + // Assignment operator + LofarFTMachineOld &operator=(const LofarFTMachineOld &other); + + // Clone + LofarFTMachineOld* clone() const; + + + ~LofarFTMachineOld(); + + // Show the relative timings of the various steps. + void showTimings (std::ostream&, double duration) const; + + // Initialize transform to Visibility plane using the image + // as a template. The image is loaded and Fourier transformed. + void initializeToVis(ImageInterface<Complex>& image, + const VisBuffer& vb); + + // Finalize transform to Visibility plane: flushes the image + // cache and shows statistics if it is being used. + void finalizeToVis(); + + // Initialize transform to Sky plane: initializes the image + void initializeToSky(ImageInterface<Complex>& image, Matrix<Float>& weight, + const VisBuffer& vb); + + + // Finalize transform to Sky plane: flushes the image + // cache and shows statistics if it is being used. DOES NOT + // DO THE FINAL TRANSFORM! + void finalizeToSky(); + + + // Get actual coherence from grid by degridding + void get(VisBuffer& vb, Int row=-1); + + + // Put coherence to grid by gridding. + void put(const VisBuffer& vb, Int row=-1, Bool dopsf=False, + FTMachine::Type type=FTMachine::OBSERVED); + + + // Make the entire image + void makeImage(FTMachine::Type type, + VisSet& vs, + ImageInterface<Complex>& image, + Matrix<Float>& weight); + + // Get the final image: do the Fourier transform and + // grid-correct, then optionally normalize by the summed weights + ImageInterface<Complex>& getImage(Matrix<Float>&, Bool normalize=True); + + // Get the average primary beam. + const Matrix<Float>& getAveragePB() const; + + // Get the spheroidal cut. + const Matrix<Float>& getSpheroidCut() const + { return itsConvFunc->getSpheroidCut(); } + + + /// virtual void normalizeImage(Lattice<Complex>& skyImage, + /// const Matrix<Double>& sumOfWts, + /// Lattice<Float>& sensitivityImage, + /// Bool fftNorm) + /// {throw(AipsError("LofarFTMachineOld::normalizeImage() called"));} + + void normalizeAvgPB(); + void normalizeAvgPB(ImageInterface<Complex>& inImage, + ImageInterface<Float>& outImage); + // + // Make a sensitivity image (sensitivityImage), given the gridded + // weights (wtImage). These are related to each other by a + // Fourier transform and normalization by the sum-of-weights + // (sumWt) and normalization by the product of the 2D FFT size + // along each axis. If doFFTNorm=False, normalization by the FFT + // size is not done. If sumWt is not provided, normalization by + // the sum of weights is also not done. + // + + + + virtual void makeSensitivityImage(Lattice<Complex>&, + ImageInterface<Float>&, + const Matrix<Float>& =Matrix<Float>(), + const Bool& =True) {} + virtual void makeSensitivityImage(const VisBuffer& vb, const ImageInterface<Complex>& imageTemplate, + ImageInterface<Float>& sensitivityImage); + + inline virtual Float pbFunc(const Float& a, const Float& limit) + {if (abs(a) >= limit) return (a);else return 1.0;}; + inline virtual Complex pbFunc(const Complex& a, const Float& limit) + {if (abs(a)>=limit) return (a); else return Complex(1.0,0.0);}; + // + // Given the sky image (Fourier transform of the visibilities), + // sum of weights and the sensitivity image, this method replaces + // the skyImage with the normalized image of the sky. + // + virtual void normalizeImage(Lattice<Complex>& skyImage, + const Matrix<Double>& sumOfWts, + Lattice<Float>& sensitivityImage, + Bool fftNorm=True); + virtual void normalizeImage(Lattice<Complex>& skyImage, + const Matrix<Double>& sumOfWts, + Lattice<Float>& sensitivityImage, + Lattice<Complex>& sensitivitySqImage, + Bool fftNorm=True); + + virtual ImageInterface<Float>& getSensitivityImage() {return *avgPB_p;} + virtual Matrix<Double>& getSumOfWeights() {return sumWeight;}; + virtual Matrix<Double>& getSumOfCFWeights() {return sumCFWeight;}; + + // Get the final weights image + void getWeightImage(ImageInterface<Float>&, Matrix<Float>&); + + // Save and restore the LofarFTMachineOld to and from a record + virtual Bool toRecord(String& error, RecordInterface& outRec, + Bool withImage=False); + virtual Bool fromRecord(String& error, const RecordInterface& inRec); + + // Can this FTMachine be represented by Fourier convolutions? + virtual Bool isFourier() {return True;} + + virtual void setNoPadding(Bool nopad){noPadding_p=nopad;}; + + virtual String name(); + virtual void setMiscInfo(const Int qualifier){(void)qualifier;}; + virtual void ComputeResiduals(VisBuffer&vb, Bool useCorrected); + + void makeConjPolMap(const VisBuffer& vb, const Vector<Int> cfPolMap, Vector<Int>& conjPolMap); + // Vector<Int> makeConjPolMap(const VisBuffer& vb); + void makeCFPolMap(const VisBuffer& vb, const Vector<Int>& cfstokes, Vector<Int>& polM); + + +protected: + // Padding in FFT + Float padding_p; + + // Get the appropriate data pointer + Array<Complex>* getDataPointer(const IPosition&, Bool); + + void ok(); + + void init(); + + // Is this record on Grid? check both ends. This assumes that the + // ends bracket the middle + Bool recordOnGrid(const VisBuffer& vb, Int rownr) const; + + // Image cache + LatticeCache<Complex> * imageCache; + + // Sizes + Long cachesize; + Int tilesize; + + // Gridder + ConvolveGridder<Double, Complex>* gridder; + + // Is this tiled? + Bool isTiled; + + // Array lattice + CountedPtr<Lattice<Complex> > arrayLattice; + + // Lattice. For non-tiled gridding, this will point to arrayLattice, + // whereas for tiled gridding, this points to the image + CountedPtr<Lattice<Complex> > lattice; + + String convType; + + Float maxAbsData; + + // Useful IPositions + IPosition centerLoc, offsetLoc; + + // Image Scaling and offset + Vector<Double> uvScale, uvOffset; + + // Arrays for non-tiled gridding (one per thread). + vector< Array<Complex> > itsGriddedData; + vector< Array<DComplex> > itsGriddedData2; + vector< Matrix<Complex> > itsSumPB; + vector< Matrix<Double> > itsSumWeight; + vector< double > itsSumCFWeight; + ///Array<Complex> griddedData; + ///Array<DComplex> griddedData2; + ///Matrix<Complex> itsSumPB; + ///double itsSumWeight; + mutable Matrix<Float> itsAvgPB; + + Int priorCacheSize; + + // Grid/degrid zero spacing points? + + Bool usezero_p; + + //force no padding + Bool noPadding_p; + + //Check if using put that avoids non-necessary reads + Bool usePut2_p; + + //machine name + String machineName_p; + + // Shape of the padded image + IPosition padded_shape; + + Int convSampling; + Float pbLimit_p; + Int sensitivityPatternQualifier_p; + String sensitivityPatternQualifierStr_p; + Vector<Float> pbPeaks; + Bool pbNormalized_p; + // The average PB for sky image normalization + // + CountedPtr<ImageInterface<Float> > avgPB_p; + CountedPtr<ImageInterface<Complex> > avgPBSq_p; + + LofarVisResamplerOld visResamplers_p; + + casa::MeasurementSet itsMS; + Int itsNWPlanes; + double itsWMax; + int itsNThread; + + CountedPtr<LofarConvolutionFunctionOld> itsConvFunc; + Vector<Int> ConjCFMap_p, CFMap_p; + String itsBeamPath; + int itsVerbose; + int itsMaxSupport; + Int itsOversample; + String itsImgName; + Matrix<Bool> itsGridMuellerMask; + Matrix<Bool> itsDegridMuellerMask; + double itsGriddingTime; + double itsDegriddingTime; + double itsCFTime; + PrecTimer itsTotalTimer; + + + template <class T> + void store(const Cube<T> &data, const string &name) + { + + CoordinateSystem csys; + Matrix<Double> xform(2, 2); + xform = 0.0; + xform.diagonal() = 1.0; + Quantum<Double> incLon((8.0 / data.shape()(0)) * C::pi / 180.0, "rad"); + Quantum<Double> incLat((8.0 / data.shape()(1)) * C::pi / 180.0, "rad"); + Quantum<Double> refLatLon(45.0 * C::pi / 180.0, "rad"); + csys.addCoordinate(DirectionCoordinate(MDirection::J2000, Projection(Projection::SIN), + refLatLon, refLatLon, incLon, incLat, + xform, data.shape()(0) / 2, data.shape()(1) / 2)); + + Vector<Int> stokes(4); + stokes(0) = Stokes::XX; + stokes(1) = Stokes::XY; + stokes(2) = Stokes::YX; + stokes(3) = Stokes::YY; + csys.addCoordinate(StokesCoordinate(stokes)); + csys.addCoordinate(SpectralCoordinate(casa::MFrequency::TOPO, 60e6, 0.0, 0.0, 60e6)); + + PagedImage<T> im(TiledShape(IPosition(4, data.shape()(0), data.shape()(1), 4, 1)), csys, name); + im.putSlice(data, IPosition(4, 0, 0, 0, 0)); + } + + +}; + +} //# end namespace + +#endif diff --git a/CEP/Imager/LofarFT/include/LofarFT/LofarImager.h b/CEP/Imager/LofarFT/include/LofarFT/LofarImager.h index 51a9da81974d9448918d112a1c9673dc537661c0..bb47a0ec822e151206aeeb962d524465af6af340 100644 --- a/CEP/Imager/LofarFT/include/LofarFT/LofarImager.h +++ b/CEP/Imager/LofarFT/include/LofarFT/LofarImager.h @@ -26,6 +26,7 @@ #define LOFAR_LOFARFT_LOFARIMAGER_H #include <LofarFT/LofarFTMachine.h> +#include <LofarFT/LofarFTMachineOld.h> #include <synthesis/MeasurementEquations/Imager.h> #include <casa/Containers/Record.h> @@ -50,19 +51,20 @@ namespace LOFAR // Get the average primary beam. const Matrix<Float>& getAveragePB() const - { return itsMachine->getAveragePB(); } + { return itsMachine ? itsMachine->getAveragePB() : itsMachineOld->getAveragePB(); } // Get the spheroidal cut. const Matrix<Float>& getSpheroidCut() const - { return itsMachine->getSpheroidCut(); } + { return itsMachine ? itsMachine->getSpheroidCut() : itsMachineOld->getSpheroidCut(); } // Show the relative timings of the various steps. void showTimings (std::ostream&, double duration) const; private: //# Data members. - casa::Record itsParameters; - LofarFTMachine* itsMachine; + casa::Record itsParameters; + LofarFTMachine* itsMachine; + LofarFTMachineOld* itsMachineOld; }; } //# end namespace diff --git a/CEP/Imager/LofarFT/include/LofarFT/LofarVisResampler.h b/CEP/Imager/LofarFT/include/LofarFT/LofarVisResampler.h index 49c7f0bbad33f6cf9ce0d436fe12c21e9d56ff18..9abc2078ec8ec8d4711045027691444385b52dca 100644 --- a/CEP/Imager/LofarFT/include/LofarFT/LofarVisResampler.h +++ b/CEP/Imager/LofarFT/include/LofarFT/LofarVisResampler.h @@ -110,6 +110,20 @@ namespace LOFAR { //# NAMESPACE CASA - BEGIN const Bool& dopsf, LofarCFStore& cfs) {DataToGridImpl_p(griddedData, vbs, rows, rbeg, rend, sumwt,dopsf,cfs);} + void lofarDataToGrid_linear (Array<Complex>& griddedData, LofarVBStore& vbs, + const Vector<uInt>& rows, + Int rbeg, Int rend, + Matrix<Double>& sumwt, + const Bool& dopsf, LofarCFStore& cfs) + {DataToGridImpl_linear_p(griddedData, vbs, rows, rbeg, rend, sumwt,dopsf,cfs);} + void lofarDataToGrid_linear (Array<DComplex>& griddedData, LofarVBStore& vbs, + const Vector<uInt>& rows, + Int rbeg, Int rend, + Matrix<Double>& sumwt, + const Bool& dopsf, LofarCFStore& cfs) + {DataToGridImpl_linear_p(griddedData, vbs, rows, rbeg, rend, sumwt,dopsf,cfs);} + + void lofarGridToData(LofarVBStore& vbs, const Array<Complex>& grid, const Vector<uInt>& rows, @@ -166,6 +180,13 @@ namespace LOFAR { //# NAMESPACE CASA - BEGIN Matrix<Double>& sumwt,const Bool& dopsf, LofarCFStore& cfs); + template <class T> + void DataToGridImpl_linear_p(Array<T>& griddedData, LofarVBStore& vb, + const Vector<uInt>& rows, + Int rbeg, Int rend, + Matrix<Double>& sumwt,const Bool& dopsf, + LofarCFStore& cfs); + Vector<Int> cfMap_p, conjCFMap_p; }; diff --git a/CEP/Imager/LofarFT/include/LofarFT/LofarVisResamplerOld.h b/CEP/Imager/LofarFT/include/LofarFT/LofarVisResamplerOld.h new file mode 100644 index 0000000000000000000000000000000000000000..4e59cf224803c0d665e21205492aca646666b677 --- /dev/null +++ b/CEP/Imager/LofarFT/include/LofarFT/LofarVisResamplerOld.h @@ -0,0 +1,173 @@ +//# LofarVisResamplerOld.h: Convolutional AW resampler for LOFAR data +//# Copyright (C) 2011 +//# 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$ + +#ifndef LOFARFT_LOFARVISRESAMPLEROLD_H +#define LOFARFT_LOFARVISRESAMPLEROLD_H + +#include <synthesis/MeasurementComponents/AWVisResampler.h> +#include <LofarFT/LofarCFStore.h> +#include <LofarFT/LofarVBStore.h> +//added +#include <LofarFT/LofarCFStore.h> + +#include <casa/Logging/LogIO.h> +#include <casa/Logging/LogOrigin.h> +#include <casa/Arrays/Cube.h> +#include <casa/Arrays/Matrix.h> +#include <casa/Arrays/ArrayIter.h> +#include <casa/Arrays/ArrayMath.h> +#include <images/Images/PagedImage.h> +#include <casa/Utilities/Assert.h> + +#include <coordinates/Coordinates/CoordinateSystem.h> +#include <coordinates/Coordinates/SpectralCoordinate.h> +#include <coordinates/Coordinates/StokesCoordinate.h> + +#include <ms/MeasurementSets/MeasurementSet.h> +#include <measures/Measures/MDirection.h> +#include <measures/Measures/MeasConvert.h> +#include <measures/Measures/MCDirection.h> +#include <measures/Measures/MCPosition.h> +#include <ms/MeasurementSets/MSAntenna.h> +#include <ms/MeasurementSets/MSAntennaParse.h> +#include <ms/MeasurementSets/MSAntennaColumns.h> +#include <ms/MeasurementSets/MSDataDescription.h> +#include <ms/MeasurementSets/MSDataDescColumns.h> +#include <ms/MeasurementSets/MSField.h> +#include <ms/MeasurementSets/MSFieldColumns.h> +#include <ms/MeasurementSets/MSObservation.h> +#include <ms/MeasurementSets/MSObsColumns.h> +#include <ms/MeasurementSets/MSPolarization.h> +#include <ms/MeasurementSets/MSPolColumns.h> +#include <ms/MeasurementSets/MSSpectralWindow.h> +#include <ms/MeasurementSets/MSSpWindowColumns.h> +#include <ms/MeasurementSets/MSSelection.h> +#include <measures/Measures/MeasTable.h> + +#include <lattices/Lattices/ArrayLattice.h> +#include <lattices/Lattices/LatticeFFT.h> +#include <stdio.h> +#include <stdlib.h> +#include <casa/vector.h> +#include <casa/OS/Directory.h> + +//========= + +using namespace casa; + +namespace LOFAR { //# NAMESPACE CASA - BEGIN + + class LofarVisResamplerOld: public AWVisResampler + { + public: + LofarVisResamplerOld(): AWVisResampler() {} + LofarVisResamplerOld(const CFStore& cfs): AWVisResampler(cfs) {} + virtual ~LofarVisResamplerOld() {} + + virtual VisibilityResamplerBase* clone() + {return new LofarVisResamplerOld(*this);} + + void copy(const LofarVisResamplerOld& other) + {AWVisResampler::copy(other); } + + // Re-sample the griddedData on the VisBuffer (a.k.a gridding). + void lofarDataToGrid (Array<Complex>& griddedData, LofarVBStore& vbs, + const Vector<uInt>& rows, + Int rbeg, Int rend, + Matrix<Double>& sumwt, + const Bool& dopsf, LofarCFStore& cfs) + {DataToGridImpl_p(griddedData, vbs, rows, rbeg, rend, sumwt,dopsf,cfs);} + void lofarDataToGrid (Array<DComplex>& griddedData, LofarVBStore& vbs, + const Vector<uInt>& rows, + Int rbeg, Int rend, + Matrix<Double>& sumwt, + const Bool& dopsf, LofarCFStore& cfs) + {DataToGridImpl_p(griddedData, vbs, rows, rbeg, rend, sumwt,dopsf,cfs);} + + void lofarGridToData(LofarVBStore& vbs, + const Array<Complex>& grid, + const Vector<uInt>& rows, + Int rbeg, Int rend, + LofarCFStore& cfs); + + + virtual void setCFMaps(const Vector<Int>& cfMap, const Vector<Int>& conjCFMap) + {cfMap_p.assign(cfMap); conjCFMap_p.assign(conjCFMap);} + + void lofarComputeResiduals(LofarVBStore& vbs); + + void sgrid(Vector<Double>& pos, Vector<Int>& loc, + Vector<Int>& off, Complex& phasor, + const Int& irow, const Matrix<Double>& uvw, + const Double& dphase, const Double& freq, + const Vector<Double>& scale, + const Vector<Double>& offset, + const Vector<Float>& sampling); + + /* + template <class T> + void store2(const Matrix<T> &data, const string &name) + { + CoordinateSystem csys; + + Matrix<Double> xform(2, 2); + xform = 0.0; + xform.diagonal() = 1.0; + Quantum<Double> incLon((8.0 / data.shape()(0)) * C::pi / 180.0, "rad"); + Quantum<Double> incLat((8.0 / data.shape()(1)) * C::pi / 180.0, "rad"); + Quantum<Double> refLatLon(45.0 * C::pi / 180.0, "rad"); + csys.addCoordinate(DirectionCoordinate(MDirection::J2000, Projection(Projection::SIN), + refLatLon, refLatLon, incLon, incLat, + xform, data.shape()(0) / 2, data.shape()(1) / 2)); + + Vector<Int> stokes(1); + stokes(0) = Stokes::I; + csys.addCoordinate(StokesCoordinate(stokes)); + csys.addCoordinate(SpectralCoordinate(casa::MFrequency::TOPO, 60e6, 0.0, 0.0, 60e6)); + + PagedImage<T> im(TiledShape(IPosition(4, data.shape()(0), data.shape()(1), 1, 1)), csys, name); + im.putSlice(data, IPosition(4, 0, 0, 0, 0)); + }; + */ + + private: + // Re-sample the griddedData on the VisBuffer (a.k.a de-gridding). + // + template <class T> + void DataToGridImpl_p(Array<T>& griddedData, LofarVBStore& vb, + const Vector<uInt>& rows, + Int rbeg, Int rend, + Matrix<Double>& sumwt,const Bool& dopsf, + LofarCFStore& cfs); + + + Vector<Int> cfMap_p, conjCFMap_p; + }; + +} //# NAMESPACE CASA - END + +#endif // diff --git a/CEP/Imager/LofarFT/include/LofarFT/LofarWTerm.h b/CEP/Imager/LofarFT/include/LofarFT/LofarWTerm.h index d31aa137b983246566c7f04b893a1ed4964b6b8a..7253064ca58311360971494c0ec96f0eef5cdb0e 100644 --- a/CEP/Imager/LofarFT/include/LofarFT/LofarWTerm.h +++ b/CEP/Imager/LofarFT/include/LofarFT/LofarWTerm.h @@ -71,12 +71,12 @@ namespace LOFAR { if (m_scale == 0.0) { return 0; } - w = abs(w); uint estimate = floor(sqrt(w / m_scale)); return w > upper(estimate) ? estimate + 1 : estimate; } + private: //# Data members. double m_scale; diff --git a/CEP/Imager/LofarFT/src/CMakeLists.txt b/CEP/Imager/LofarFT/src/CMakeLists.txt index cf3040123333305a73bb45640e135ecfc11d8c80..462d30cd5ddd87c01184e203637d5486abc24c00 100644 --- a/CEP/Imager/LofarFT/src/CMakeLists.txt +++ b/CEP/Imager/LofarFT/src/CMakeLists.txt @@ -6,13 +6,17 @@ lofar_add_library(lofarft Package__Version.cc FFTCMatrix.cc LofarATerm.cc + LofarATermOld.cc LofarConvolutionFunction.cc + LofarConvolutionFunctionOld.cc LofarImager.cc LofarCFStore.cc LofarFTMachine.cc + LofarFTMachineOld.cc LofarWTerm.cc # LofarVisibilityResamplerBase.cc LofarVisResampler.cc + LofarVisResamplerOld.cc LofarCubeSkyEquation.cc ) diff --git a/CEP/Imager/LofarFT/src/LofarATerm.cc b/CEP/Imager/LofarFT/src/LofarATerm.cc index 3c5ec0147eec390e60bfd129cae21f8981ae2d37..f6c27f4d17202527c13bf847962b06a752d1db09 100644 --- a/CEP/Imager/LofarFT/src/LofarATerm.cc +++ b/CEP/Imager/LofarFT/src/LofarATerm.cc @@ -22,1017 +22,855 @@ #include <lofar_config.h> #include <LofarFT/LofarATerm.h> + #include <Common/LofarLogger.h> #include <Common/Exception.h> +#include <BBSKernel/MeasurementAIPS.h> +#include <ElementResponse/ElementResponse.h> -#include <casa/OS/Path.h> #include <casa/Arrays/ArrayIter.h> #include <casa/Arrays/Cube.h> #include <coordinates/Coordinates/DirectionCoordinate.h> -#include <measures/Measures/MeasTable.h> #include <measures/Measures/MeasConvert.h> #include <measures/Measures/MCDirection.h> #include <measures/Measures/MCPosition.h> -#include <ms/MeasurementSets/MeasurementSet.h> -#include <ms/MeasurementSets/MSAntenna.h> -#include <ms/MeasurementSets/MSAntennaParse.h> -#include <ms/MeasurementSets/MSAntennaColumns.h> -#include <ms/MeasurementSets/MSDataDescription.h> -#include <ms/MeasurementSets/MSDataDescColumns.h> -#include <ms/MeasurementSets/MSField.h> -#include <ms/MeasurementSets/MSFieldColumns.h> -#include <ms/MeasurementSets/MSObservation.h> -#include <ms/MeasurementSets/MSObsColumns.h> -#include <ms/MeasurementSets/MSPolarization.h> -#include <ms/MeasurementSets/MSPolColumns.h> -#include <ms/MeasurementSets/MSSpectralWindow.h> -#include <ms/MeasurementSets/MSSpWindowColumns.h> -#include <ms/MeasurementSets/MSSelection.h> #include <synthesis/MeasurementComponents/SynthesisError.h> -// DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG -#include <iomanip> -// DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG - using namespace casa; namespace LOFAR { - LofarATerm::LofarATerm(const MeasurementSet& ms, - const String& beamElementPath) - { - if (beamElementPath.empty()) { - m_coeffLBA.load(Path("element_beam_HAMAKER_LBA.coeff")); - m_coeffHBA.load(Path("element_beam_HAMAKER_HBA.coeff")); - } else { - m_coeffLBA.load(Path(beamElementPath + "/element_beam_HAMAKER_LBA.coeff")); - m_coeffHBA.load(Path(beamElementPath + "/element_beam_HAMAKER_HBA.coeff")); - } - // m_coeffLBA.load(Path("element_beam_LBA.coeff")); - // m_coeffHBA.load(Path("element_beam_HBA.coeff")); - - initInstrument(ms); - initReferenceFreq(ms, 0); - initReferenceDirections(ms, 0); - } - - vector<Cube<Complex> > LofarATerm::evaluate(const IPosition &shape, - const DirectionCoordinate &coordinates, - uint station, - const MEpoch &epoch, - const Vector<Double> &freq, - bool normalize) const - { - AlwaysAssert(station < m_instrument.nStations(), SynthesisError); - AlwaysAssert(shape[0] > 0 && shape[1] > 0, SynthesisError); - AlwaysAssert(freq.size() > 0, SynthesisError); - - // Create conversion engine (from J2000 -> ITRF). - MDirection::Convert convertor = MDirection::Convert(MDirection::J2000, - MDirection::Ref(MDirection::ITRF, - MeasFrame(epoch, m_instrument.position()))); - - MVDirection mvRefDelay = convertor(m_refDelay).getValue(); - Vector3 refDelay = {{mvRefDelay(0), mvRefDelay(1), mvRefDelay(2)}}; - - MVDirection mvRefTile = convertor(m_refTile).getValue(); - Vector3 refTile = {{mvRefTile(0), mvRefTile(1), mvRefTile(2)}}; - - // Compute ITRF map. - LOG_INFO("LofarATerm::evaluate(): Computing ITRF map..."); - Cube<double> mapITRF = computeITRFMap(coordinates, shape, convertor); - LOG_INFO("LofarATerm::evaluate(): Computing ITRF map... done."); - // Compute element beam response. - LOG_INFO("LofarATerm::evaluate(): Computing station response..."); - Array<DComplex> response = - evaluateStationBeam(m_instrument.station(station), refDelay, refTile, - mapITRF, freq); - - // DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG -// MDirection world; -// Vector<double> refPixel = coordinates.referencePixel(); - -// cout << "shape: " << shape << " ref. pixel: " << refPixel << endl; -// coordinates.toWorld(world, refPixel); - -// casa::Quantum<casa::Vector<casa::Double> > refAngles = world.getAngle(); -// double ra = refAngles.getBaseValue()(0); -// double dec = refAngles.getBaseValue()(1); -// cout << "ref. world: " << std::setprecision(17) << ra << " " << dec << endl; - -// cout << "station: " << station << endl; -// cout << "freq: " << std::setprecision(17) << freq << endl; -// cout << "time: " << std::setprecision(17) << epoch.getValue().getTime("s") << endl; -// IPosition st(4, refPixel(0), refPixel(1), 0, 0); -// IPosition en(4, refPixel(0), refPixel(1), 3, freq.size() - 1); -// Array<DComplex> tmpResponse = response(st, en).nonDegenerate(); -// cout << "response shape: " << tmpResponse.shape() << endl; -// cout << "response: " << endl << tmpResponse << endl; +namespace +{ + Array<DComplex> computeFieldArrayFactor(const BBS::Station::ConstPtr &station, + uint idField, const LofarATerm::ITRFDirectionMap &map, + const Vector<Double> &freq, const Vector<Double> &reference); -// refPixel = 0.0; -// coordinates.toWorld(world, refPixel); -// refAngles = world.getAngle(); -// ra = refAngles.getBaseValue()(0); -// dec = refAngles.getBaseValue()(1); -// cout << "0 world: " << std::setprecision(17) << ra << " " << dec << endl; + Cube<DComplex> + computeTileArrayFactor(const BBS::AntennaField::ConstPtr &field, + const LofarATerm::ITRFDirectionMap &map, const Vector<Double> &freq); -// st = IPosition(4, 0, 0, 0, 0); -// en = IPosition(4, 0, 0, 3, freq.size() - 1); -// Array<DComplex> tmpResponse2 = response(st, en).nonDegenerate(); -// cout << "response shape: " << tmpResponse2.shape() << endl; -// cout << "response: " << endl << tmpResponse2 << endl; + struct ElementLBA; + struct ElementHBA; -// AlwaysAssert(false, SynthesisError); - // DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG + template <typename T_ELEMENT> + Array<DComplex> + computeElementResponse(const BBS::AntennaField::ConstPtr &field, + const LofarATerm::ITRFDirectionMap &map, const Vector<Double> &freq); + void rescale(Array<DComplex> &response); + void rescale(Cube<DComplex> &response); + vector<Cube<Complex> > asVector(Array<DComplex> &response); + vector<Matrix<Complex> > asVector(Cube<DComplex> &response); +} - //Cyril - if(normalize) + LofarATerm::LofarATerm(const MeasurementSet& ms, const casa::Record& parameters) + { + itsInstrument = BBS::readInstrument(ms); + itsRefDelay = MDirection::Convert(BBS::readDelayReference(ms), + MDirection::J2000)(); + itsRefTile = MDirection::Convert(BBS::readTileReference(ms), + MDirection::J2000)(); + itsDirectionCoordinates = 0; + itsParameters = parameters; + itsapplyIonosphere = False; + if (itsParameters.fieldNumber("applyIonosphere") > -1) itsapplyIonosphere = itsParameters.asBool("applyIonosphere"); + cout << "Apply Ionosphere:" << itsapplyIonosphere << endl; + if (itsapplyIonosphere) { - response = this->normalize(response); + String parmdbname = ms.tableName() + "/instrument"; + cout << parmdbname << endl; + initParmDB(parmdbname); + cout << cal_pp_names << endl; } - LOG_INFO("LofarATerm::evaluate(): Computing station response... done."); + } - // Convert an Array<DComplex> to a vector<Cube<Complex> >. - vector<Cube<Complex> > tmp; - tmp.reserve(freq.size()); - for (ArrayIterator<DComplex> iter(response, 3); - !iter.pastEnd(); iter.next()) + void LofarATerm::initParmDB(const casa::String &parmdbname) + { + this->pdb = new LOFAR::BBS::ParmFacade (parmdbname); + std::string prefix = "Piercepoint:X:"; + std::vector<std::string> v = this->pdb->getNames(prefix + "*"); + this->cal_pp_names = Vector<String>(v.size()); + this->cal_pp = Matrix<Double>(3,v.size()); + this->tec_white = Vector<Double>(v.size()); + + //strip cal_pp_names from prefix + for (uint i=0; i<v.size(); i++) { - Cube<Complex> planef(iter.array().shape()); - convertArray (planef, iter.array()); - tmp.push_back(planef); + this->cal_pp_names[i] = v[i].substr(prefix.length()); } - - // if(normalize) - // MDirection::Convert convertor = MDirection::Convert(MDirection::J2000, MDirection::Ref(MDirection::ITRF, MeasFrame(epoch, m_instrument.position()))); - // mapITRF = computeITRFMap(coordinates, shape, convertor); - // Cube<double> mapITRF_center; - // DirectionCoordinate coordinates_center(coordinates); - // Vector<Double> Refpix(2,0.); - // coordinates_center.setReferencePixel(Refpix); - // mapITRF_center = computeITRFMap(coordinates_center, IPosition(2,1,1), convertor); - // for(uInt i = 0; i < freq.size(); ++i){ - // { - // evaluateStationBeam(m_instrument.station(station), refDelay, refTile, - // mapITRF, freq); - // Cube<Complex> gain(evaluateStationBeam(mapITRF_center, convertor(m_phaseReference), m_instrument.station(station), freq[i])); - // Matrix<Complex> central_gain(gain.xzPlane(0)); - // // central_gain.resize(2,2,true); //resize does not work: - // // Central gain Axis Lengths: [1, 4] (NB: Matrix in Row/Column order) - // // [(-0.0235668,-0.000796029), (-0.0345345,-0.000373378), (0.030112,0.000938836), (-0.0268743,-0.000258621)] - // // Central gain Axis Lengths: [2, 2] (NB: Matrix in Row/Column order) - // // [(-0.0235668,-0.000796029), (-0.0345345,-0.000373378) - // // (0,0), (0,0)] - // Matrix<Complex> central_gain_reform(central_gain.reform(IPosition(2,2,2))); - // Matrix<Complex> central_gain_invert(invert(central_gain_reform)); - - // //Cube<Complex> IM=beams[i]; - // for(uInt ii=0;ii<shape[0];++ii) - // { - // for(uInt jj=0;jj<shape[1];++jj) - // { - // Cube<Complex> pixel(tmp[i](IPosition(3,ii,jj,0),IPosition(3,ii,jj,3)).copy()); - // // cout<<"================="<<pixel<<endl; - // // cout<<"pixel"<<pixel<<endl; - // Matrix<Complex> pixel_reform(pixel.reform(IPosition(2,2,2))); - // // cout<<"pixel_reform"<<pixel_reform<<endl; - // Matrix<Complex> pixel_product=product(central_gain_invert,pixel_reform); - // // cout<<"pixel_product"<<pixel_product<<endl; - // Matrix<Complex> pixel_product_reform(pixel_product.reform(IPosition(2,1,4))); - // // cout<<"pixel_product_reform"<<pixel_product_reform<<endl; - - // for(uInt ind=0;ind<4;++ind){tmp[i](ii,jj,ind)=pixel_product_reform(0,ind);}; - // //beams[i](IPosition(3,ii,jj,0),IPosition(3,ii,jj,3))=pixel_product; - // //IM(ii,jj)=pixel_product; - // } - // } - // }; - - return tmp; + } - - Array<DComplex> LofarATerm::normalize(const Array<DComplex> &response) - const - { - const uint nX = response.shape()[0]; - const uint nY = response.shape()[1]; - const uint nFreq = response.shape()[3]; - AlwaysAssert(response.shape()[2] == 4, SynthesisError); - AlwaysAssert(nX > 0 && nY > 0 && nFreq > 0, SynthesisError); - - // Cast away const, to be able to use Array<T>::operator(IPosition, - // IPosition) to extract a slice (for reading). - Array<DComplex> &__response = const_cast<Array<DComplex>&>(response); - - // Extract beam response for the central pixel at the central frequency. - IPosition start(4, floor(nX / 2.), floor(nY / 2.), 0, floor(nFreq / 2.)); - IPosition end(4, floor(nX / 2.), floor(nY / 2.), 3, floor(nFreq / 2.)); - - // Use assignment operator to force a copy. - Vector<DComplex> factor; - factor = __response(start, end).nonDegenerate(); - - // Compute the inverse of the reponse. - Vector<DComplex> inverse(4); - DComplex determinant = factor(0) * factor(3) - factor(1) * factor(2); - inverse(0) = factor(3) / determinant; - inverse(1) = -factor(1) / determinant; - inverse(2) = -factor(2) / determinant; - inverse(3) = factor(0) / determinant; - - // Multiply the beam response for all pixels, at all frequencies, by the - // computed inverse. - Array<DComplex> XX = __response(IPosition(4, 0, 0, 0, 0), - IPosition(4, nX - 1, nY - 1, 0, nFreq - 1)); - Array<DComplex> XY = __response(IPosition(4, 0, 0, 1, 0), - IPosition(4, nX - 1, nY - 1, 1, nFreq - 1)); - Array<DComplex> YX = __response(IPosition(4, 0, 0, 2, 0), - IPosition(4, nX - 1, nY - 1, 2, nFreq - 1)); - Array<DComplex> YY = __response(IPosition(4, 0, 0, 3, 0), - IPosition(4, nX - 1, nY - 1, 3, nFreq - 1)); - - Array<DComplex> normal(response.shape()); - Array<DComplex> nXX = normal(IPosition(4, 0, 0, 0, 0), - IPosition(4, nX - 1, nY - 1, 0, nFreq - 1)); - Array<DComplex> nXY = normal(IPosition(4, 0, 0, 1, 0), - IPosition(4, nX - 1, nY - 1, 1, nFreq - 1)); - Array<DComplex> nYX = normal(IPosition(4, 0, 0, 2, 0), - IPosition(4, nX - 1, nY - 1, 2, nFreq - 1)); - Array<DComplex> nYY = normal(IPosition(4, 0, 0, 3, 0), - IPosition(4, nX - 1, nY - 1, 3, nFreq - 1)); - - nXX = inverse(0) * XX + inverse(1) * YX; - nXY = inverse(0) * XY + inverse(1) * YY; - nYX = inverse(2) * XX + inverse(3) * YX; - nYY = inverse(2) * XY + inverse(3) * YY; - - return normal; + + void LofarATerm::setDirection(const casa::DirectionCoordinate &coordinates, const IPosition &shape) { + itsDirectionCoordinates = &coordinates; + itsShape = &shape; } - - Array<DComplex> LofarATerm::evaluateElementBeam(const BeamCoeff &coeff, - const AntennaField &field, - const Cube<double> &map, - const Vector<double> &freq) const + + + void LofarATerm::setEpoch( const MEpoch &epoch ) { - const Vector3 &p = field.axis(AntennaField::P); - const Vector3 &q = field.axis(AntennaField::Q); - const Vector3 &r = field.axis(AntennaField::R); - - const uint nX = map.shape()[1]; - const uint nY = map.shape()[2]; - const uint nFreq = freq.shape()[0]; - - Array<DComplex> beam(IPosition(4, nX, nY, 4, nFreq), DComplex(0.0, 0.0)); - for(uint j = 0; j < nY; ++j) + if (this->itsDirectionCoordinates) itsITRFDirectionMap = makeDirectionMap(*itsDirectionCoordinates, *itsShape, epoch); + if (this->itsapplyIonosphere) { - for(uint i = 0; i < nX; ++i) - { - if(map(0, i, j) == 0.0 && map(1, i, j) == 0.0 && map(2, i, j) == 0.0) - { - // Non-physical pixel. - continue; - } + this->time = epoch.get(casa::Unit("s")).getValue(); + this->r0 = get_parmvalue("r_0"); + this->beta = get_parmvalue("beta"); + this->height = get_parmvalue("height"); + for(uint i = 0; i < this->cal_pp_names.size(); ++i) { + this->cal_pp(0, i) = get_parmvalue("Piercepoint:X:" + this->cal_pp_names(i)); + this->cal_pp(1, i) = get_parmvalue("Piercepoint:Y:" + this->cal_pp_names(i)); + this->cal_pp(2, i) = get_parmvalue("Piercepoint:Z:" + this->cal_pp_names(i)); + this->tec_white(i) = get_parmvalue("TECfit_white:0:" + this->cal_pp_names(i)); + } + } + } + + double LofarATerm::get_parmvalue( std::string parmname ) + { + double freq = 50e6; // the ionospheric parameters are not frequency dependent, so just pick an arbitrary frequency + // this frequency should be within the range specified in the parmdbname + // this range is again quite arbitrary + casa::Record result = this->pdb->getValues (parmname, freq, freq+0.5, 1.0, this->time, this->time + 0.5, 1.0 ); + casa::Array<double> parmvalues; + result.subRecord(parmname).get("values", parmvalues); + return parmvalues(IPosition(2,0,0)); + } + + + LofarATerm::ITRFDirectionMap + LofarATerm::makeDirectionMap(const DirectionCoordinate &coordinates, + const IPosition &shape, const MEpoch &epoch) const + { + AlwaysAssert(shape[0] > 0 && shape[1] > 0, SynthesisError); - // Compute the P and Q coordinate of the direction vector by projecting - // onto the positive P and Q axis. - double projectionP = map(0, i, j) * p[0] + map(1, i, j) * p[1] + map(2, i, j) * p[2]; - double projectionQ = map(0, i, j) * q[0] + map(1, i, j) * q[1] + map(2, i, j) * q[2]; + ITRFDirectionMap map; + map.epoch = epoch; - // Compute the inner product between the antenna field normal - // (R) and the direction vector to get the sine of the elevation - // (cosine of the zenith angle). - double sinEl = map(0, i, j) * r[0] + map(1, i, j) * r[1] + map(2, i, j) * r[2]; + // Create conversion engine J2000 -> ITRF at epoch. + MDirection::Convert convertor = MDirection::Convert(MDirection::J2000, + MDirection::Ref(MDirection::ITRF, + MeasFrame(epoch, itsInstrument->position()))); - double az = atan2(projectionP, projectionQ); - double el = asin(sinEl); + MVDirection mvRefDelay = convertor(itsRefDelay).getValue(); + map.refDelay[0] = mvRefDelay(0); + map.refDelay[1] = mvRefDelay(1); + map.refDelay[2] = mvRefDelay(2); - // Evaluate beam. - // Correct azimuth for dipole orientation. - const double phi = az - 3.0 * C::pi_4; + MVDirection mvRefTile = convertor(itsRefTile).getValue(); + map.refTile[0] = mvRefTile(0); + map.refTile[1] = mvRefTile(1); + map.refTile[2] = mvRefTile(2); - // NB: The model is parameterized in terms of zenith angle. The - // appropriate conversion is taken care of below. - const double theta = C::pi_2 - el; + MDirection world; + casa::Vector<Double> pixel = coordinates.referencePixel(); - // Only compute the beam response for directions above the horizon. - if(theta < C::pi_2) + Cube<Double> mapITRF(3, shape[0], shape[1], 0.0); + for(pixel[1] = 0.0; pixel(1) < shape[1]; ++pixel[1]) + { + for(pixel[0] = 0.0; pixel[0] < shape[0]; ++pixel[0]) + { + // CoodinateSystem::toWorld() + // DEC range [-pi/2,pi/2] + // RA range [-pi,pi] + if(coordinates.toWorld(world, pixel)) { - for(uint k = 0; k < nFreq; ++k) - { - // J-jones matrix (2x2 complex matrix) - DComplex J[2][2] = {{0.0, 0.0}, {0.0, 0.0}}; - - // NB: The model is parameterized in terms of a normalized - // frequency in the range [-1, 1]. The appropriate conversion is - // taken care of below. - const double normFreq = (freq[k] - coeff.center()) / coeff.width(); - - for(uint l = 0; l < coeff.nHarmonics(); ++l) - { - // Compute diagonal projection matrix P for the current - // harmonic. - DComplex P[2] = {0.0, 0.0}; - - DComplex inner[2]; - for(int m = coeff.nPowerTheta() - 1; m >= 0; --m) - { - inner[0] = coeff(0, coeff.nPowerFreq() - 1, m, l); - inner[1] = coeff(1, coeff.nPowerFreq() - 1, m, l); - - for(int n = coeff.nPowerFreq() - 2; n >= 0; --n) - { - inner[0] = inner[0] * normFreq + coeff(0, n, m, l); - inner[1] = inner[1] * normFreq + coeff(1, n, m, l); - } - - P[0] = P[0] * theta + inner[0]; - P[1] = P[1] * theta + inner[1]; - } - - // Compute Jones matrix for this harmonic by rotating P over - // kappa * phi and add it to the result. - const double kappa = ((l & 1) == 0 ? 1.0 : -1.0) * (2.0 * l + 1.0); - const double cphi = cos(kappa * phi); - const double sphi = sin(kappa * phi); - - J[0][0] += cphi * P[0]; - J[0][1] += -sphi * P[1]; - J[1][0] += sphi * P[0]; - J[1][1] += cphi * P[1]; - } - - beam(IPosition(4, i, j, 0, k)) = J[0][0]; - beam(IPosition(4, i, j, 1, k)) = J[0][1]; - beam(IPosition(4, i, j, 2, k)) = J[1][0]; - beam(IPosition(4, i, j, 3, k)) = J[1][1]; - } + MVDirection mvITRF = convertor(world).getValue(); + mapITRF(0, pixel[0], pixel[1]) = mvITRF(0); + mapITRF(1, pixel[0], pixel[1]) = mvITRF(1); + mapITRF(2, pixel[0], pixel[1]) = mvITRF(2); } } } - return beam; + map.directions.reference(mapITRF); + return map; } - Array<DComplex> LofarATerm::evaluateStationBeam(const Station &station, - const Vector3 &refDelay, - const Vector3 &refTile, - const Cube<Double> &map, - const Vector<Double> &freq) const + vector<Cube<Complex> > LofarATerm::evaluate(uint idStation, + const Vector<Double> &freq, + const Vector<Double> &reference, bool normalize) const { - const uint nX = map.shape()[1]; - const uint nY = map.shape()[2]; - const uint nFreq = freq.shape()[0]; + const ITRFDirectionMap &map = itsITRFDirectionMap; + AlwaysAssert(idStation < itsInstrument->nStations(), SynthesisError); + BBS::Station::ConstPtr station = itsInstrument->station(idStation); + + const uint nX = map.directions.shape()[1]; + const uint nY = map.directions.shape()[2]; + const uint nFreq = freq.size(); - uint countX = 0, countY = 0; Array<DComplex> E(IPosition(4, nX, nY, 4, nFreq), DComplex(0.0, 0.0)); - for(uint i = 0; i < station.nField(); ++i) + for(uint i = 0; i < station->nField(); ++i) { - const AntennaField &field = station.field(i); + BBS::AntennaField::ConstPtr field = station->field(i); // Compute element beam. - LOG_INFO("LofarATerm::computeStationBeam: Computing element beam..."); - Array<DComplex> beam; - if(field.isHBA()) + Array<DComplex> element; + if(field->isHBA()) { - beam = evaluateElementBeam(m_coeffHBA, field, map, freq); + element.reference(computeElementResponse<ElementHBA>(field, map, freq)); } else { - beam = evaluateElementBeam(m_coeffLBA, field, map, freq); + element.reference(computeElementResponse<ElementLBA>(field, map, freq)); } - LOG_INFO("LofarATerm::computeStationBeam: Computing element beam... done."); - if(field.isHBA()) + // Compute antenna field array factor. + Array<DComplex> fieldAF = computeFieldArrayFactor(station, i, map, freq, + reference); + + // Multiply the element or tile response by the antenna field array + // factor. + for(uint j = 0; j < 2; ++j) { - // Compute tile array factor. - LOG_INFO("LofarATerm::computeStationBeam: Computing tile array factor..."); - Cube<DComplex> tileAF = evaluateTileArrayFactor(field, refTile, map, - freq); - LOG_INFO("LofarATerm::computeStationBeam: Computing tile array factor... done."); + IPosition start(4, 0, 0, j, 0); + IPosition end(4, nX - 1, nY - 1, j, nFreq - 1); + Array<DComplex> slice = E(start, end); - Array<DComplex> tileAF4 = tileAF.reform(IPosition(4, nX, nY, 1, nFreq)); + IPosition startAF(4, 0, 0, 0, 0); + IPosition endAF(4, nX - 1, nY - 1, 0, nFreq - 1); + slice += fieldAF(startAF, endAF) * element(start, end); + } - // Multiply the element beam by the tile array factor. - for(uint j = 0; j < 4; ++j) - { - IPosition start(4, 0, 0, j, 0); - IPosition end(4, nX - 1, nY - 1, j, nFreq - 1); + for(uint j = 2; j < 4; ++j) + { + IPosition startAF(4, 0, 0, 1, 0); + IPosition endAF(4, nX - 1, nY - 1, 1, nFreq - 1); - Array<DComplex> plane = beam(start, end); - plane *= tileAF4; - } + IPosition start(4, 0, 0, j, 0); + IPosition end(4, nX - 1, nY - 1, j, nFreq - 1); + Array<DComplex> slice = E(start, end); + slice += fieldAF(startAF, endAF) * element(start, end); } + } - LOG_INFO("LofarATerm::computeStationBeam: Computing station array factor..."); + if(normalize) + { + rescale(E); + } - // Account for the case where the delay reference position is not equal to - // the field center (only applies to core HBA fields). - const Vector3 &fieldCenter = field.position(); - MVPosition delayCenter = station.position().getValue(); - Vector3 offsetShift = {{fieldCenter[0] - delayCenter(0), - fieldCenter[1] - delayCenter(1), - fieldCenter[2] - delayCenter(2)}}; + return asVector(E); + } - // Compute field array factors. - Cube<DComplex> fieldAFX(nX, nY, nFreq, DComplex(0.0, 0.0)); - Cube<DComplex> fieldAFY(nX, nY, nFreq, DComplex(0.0, 0.0)); - Cube<DComplex> phase(nX, nY, nFreq, DComplex(0.0, 0.0)); + vector<Matrix<Complex> > LofarATerm::evaluateArrayFactor(uint idStation, + uint idPolarization, + const Vector<Double> &freq, const Vector<Double> &reference, bool normalize) + const + { + AlwaysAssert(idStation < itsInstrument->nStations(), SynthesisError); + AlwaysAssert(idPolarization < 2, SynthesisError); - for(uint j = 0; j < field.nElement(); ++j) - { - const AntennaField::Element &element = field.element(j); - if(element.flag[0] && element.flag[1]) - { - continue; - } + const ITRFDirectionMap &map = itsITRFDirectionMap; + BBS::Station::ConstPtr station = itsInstrument->station(idStation); + Array<DComplex> AF = computeFieldArrayFactor(station, 0, map, freq, + reference); - // Compute the offset relative to the delay center. - Vector3 offset = {{element.offset[0] + offsetShift[0], - element.offset[1] + offsetShift[1], - element.offset[2] + offsetShift[2]}}; + if(station->nField() > 1) + { + AF += computeFieldArrayFactor(station, 1, map, freq, reference); + } - // Compute the delay for a plane wave approaching from the delay - // reference direction with respect to the element position. - double delay0 = (refDelay[0] * offset[0] + refDelay[1] * offset[1] - + refDelay[2] * offset[2]) / casa::C::c; - double shift0 = C::_2pi * m_refFreq * delay0; + const uint nX = AF.shape()[0]; + const uint nY = AF.shape()[1]; + const uint nFreq = AF.shape()[3]; - for(uint y = 0; y < nY; ++y) - { - for(uint x = 0; x < nX; ++x) - { - // Compute the delay for a plane wave approaching from the direction - // of interest with respect to the element position. - double delay = (map(0, x, y) * offset[0] - + map(1, x, y) * offset[1] - + map(2, x, y) * offset[2]) / casa::C::c; - - for(uint k = 0; k < nFreq; ++k) - { - double shift = C::_2pi * freq[k] * delay - shift0; - phase(x, y, k) = DComplex(cos(shift), sin(shift)); - } - } - } + IPosition start(4, 0, 0, idPolarization, 0); + IPosition end(4, nX - 1, nY - 1, idPolarization, nFreq - 1); + Cube<DComplex> slice = AF(start, end).reform(IPosition(3, nX, nY, nFreq)); - if(!element.flag[0]) - { - fieldAFX += phase; - ++countX; - } + if(normalize) + { + rescale(slice); + } - if(!element.flag[1]) - { - fieldAFY += phase; - ++countY; - } - } + return asVector(slice); + } - LOG_INFO("LofarATerm::computeStationBeam: Computing station array factor... done."); - Array<DComplex> fieldAFX4 = fieldAFX.reform(IPosition(4, nX, nY, 1, nFreq)); - for(uint k = 0; k < 2; ++k) - { - IPosition start(4, 0, 0, k, 0); - IPosition end(4, nX - 1, nY - 1, k, nFreq - 1); - Array<DComplex> plane = E(start, end); - plane += fieldAFX4 * beam(start, end); - } + vector<Cube<Complex> > LofarATerm::evaluateElementResponse(uint idStation, + uint idField, const Vector<Double> &freq, + bool normalize) const + { + AlwaysAssert(idStation < itsInstrument->nStations(), SynthesisError); - Array<DComplex> fieldAFY4 = fieldAFY.reform(IPosition(4, nX, nY, 1, nFreq)); - for(uint k = 2; k < 4; ++k) - { - IPosition start(4, 0, 0, k, 0); - IPosition end(4, nX - 1, nY - 1, k, nFreq - 1); - Array<DComplex> plane = E(start, end); - plane += fieldAFY4 * beam(start, end); - } - } // fields + const ITRFDirectionMap &map = itsITRFDirectionMap; + BBS::AntennaField::ConstPtr field = + itsInstrument->station(idStation)->field(idField); - // Normalize. - if(countX > 0) + Array<DComplex> response; + if(field->isHBA()) { - IPosition start(4, 0, 0, 0, 0); - IPosition end(4, nX - 1, nY - 1, 1, nFreq - 1); - Array<DComplex> plane = E(start, end); - plane /= static_cast<Double>(countX); + response.reference(computeElementResponse<ElementHBA>(field, map, freq)); + } + else + { + response.reference(computeElementResponse<ElementLBA>(field, map, freq)); } - if(countY > 0) + if(normalize) { - IPosition start(4, 0, 0, 2, 0); - IPosition end(4, nX - 1, nY - 1, 3, nFreq - 1); - Array<DComplex> plane = E(start, end); - plane /= static_cast<Double>(countY); + rescale(response); } - return E; + return asVector(response); } - Cube<DComplex> LofarATerm::evaluateTileArrayFactor(const AntennaField &field, - const Vector3 &reference, - const Cube<Double> &map, - const Vector<Double> &freq) const + vector<Cube<Complex> > LofarATerm::evaluateIonosphere( + uint station, + const Vector<Double> &freq, + bool normalize) { - const uint nX = map.shape()[1]; - const uint nY = map.shape()[2]; - const uint nFreq = freq.shape()[0]; + const ITRFDirectionMap &map = itsITRFDirectionMap; + +// AlwaysAssert(station < this->instrument.nStations(), SynthesisError); +// AlwaysAssert(shape[0] > 0 && shape[1] > 0, SynthesisError); +// AlwaysAssert(freq.size() > 0, SynthesisError); + + // Create conversion engine (from J2000 -> ITRF). - Cube<DComplex> factor(nX, nY, nFreq, DComplex(0.0, 0.0)); - for(uint y = 0; y < nY; ++y) + const uint nX = map.directions.shape()[1]; + const uint nY = map.directions.shape()[2]; + + const uint nFreq = freq.size(); + + const casa::MVPosition p = this->itsInstrument->station(station)->position().getValue(); + + const double earth_ellipsoid_a = 6378137.0; + const double earth_ellipsoid_a2 = earth_ellipsoid_a*earth_ellipsoid_a; + const double earth_ellipsoid_b = 6356752.3142; + const double earth_ellipsoid_b2 = earth_ellipsoid_b*earth_ellipsoid_b; + const double earth_ellipsoid_e2 = (earth_ellipsoid_a2 - earth_ellipsoid_b2) / earth_ellipsoid_a2; + + const double ion_ellipsoid_a = earth_ellipsoid_a + height; + const double ion_ellipsoid_a2_inv = 1.0 / (ion_ellipsoid_a * ion_ellipsoid_a); + const double ion_ellipsoid_b = earth_ellipsoid_b + height; + const double ion_ellipsoid_b2_inv = 1.0 / (ion_ellipsoid_b * ion_ellipsoid_b); + + + double x = p(0)/ion_ellipsoid_a; + double y = p(1)/ion_ellipsoid_a; + double z = p(2)/ion_ellipsoid_b; + double c = x*x + y*y + z*z - 1.0; + + casa::Cube<double> piercepoints(4, nX, nY, 0.0); + + #pragma omp parallel { - for(uint x = 0; x < nX; ++x) + #pragma omp for + for(uint i = 0 ; i < nX; ++i) + { + for(uint j = 0 ; j < nY; ++j) { - // Instead of computing a phase shift for the pointing direction and a - // phase shift for the direction of interest and then computing the - // difference, compute the resultant phase shift in one go. Here we make - // use of the relation a . b + a . c = a . (b + c). The sign of k is - // related to the sign of the phase shift. - double k[3]; - k[0] = map(0, x, y) - reference[0]; - k[1] = map(1, x, y) - reference[1]; - k[2] = map(2, x, y) - reference[2]; + double dx = map.directions(0,i,j) / ion_ellipsoid_a; + double dy = map.directions(1,i,j) / ion_ellipsoid_a; + double dz = map.directions(2,i,j) / ion_ellipsoid_b; + double a = dx*dx + dy*dy + dz*dz; + double b = x*dx + y*dy + z*dz; + double alpha = (-b + std::sqrt(b*b - a*c))/a; + piercepoints(0, i, j) = p(0) + alpha*map.directions(0,i,j); + piercepoints(1, i, j) = p(1) + alpha*map.directions(1,i,j); + piercepoints(2, i, j) = p(2) + alpha*map.directions(2,i,j); + double normal_x = piercepoints(0, i, j) * ion_ellipsoid_a2_inv; + double normal_y = piercepoints(1, i, j) * ion_ellipsoid_a2_inv; + double normal_z = piercepoints(2, i, j) * ion_ellipsoid_b2_inv; + double norm_normal2 = normal_x*normal_x + normal_y*normal_y + normal_z*normal_z; + double norm_normal = std::sqrt(norm_normal2); + double sin_lat2 = normal_z*normal_z / norm_normal2; +// double cos_za = (mapITRF(0,i,j)*normal_x + mapITRF(1,i,j)*normal_y + mapITRF(2,i,j)*normal_z) / norm_normal; +// piercepoints(3, i, j) = cos_za; + +// casa::MPosition p1(casa::MVPosition(piercepoints(0, i, j), piercepoints(1, i, j), piercepoints(2, i, j)),casa::MPosition::ITRF); +// positionWGS84 = casa::MPosition::Convert(p1, casa::MPosition::WGS84)(); +// piercepoints(2, i, j) = positionWGS84.getValue().getLength().getValue()-height; + + double g = 1.0 - earth_ellipsoid_e2*sin_lat2; + double sqrt_g = std::sqrt(g); + + double M = earth_ellipsoid_b2 / ( earth_ellipsoid_a * g * sqrt_g ); + double N = earth_ellipsoid_a / sqrt_g; + + double local_ion_ellipsoid_e2 = (M-N) / ((M+height)*sin_lat2 - N - height); + double local_ion_ellipsoid_a = (N+height) * std::sqrt(1.0 - local_ion_ellipsoid_e2*sin_lat2); + double local_ion_ellipsoid_b = local_ion_ellipsoid_a*std::sqrt(1.0 - local_ion_ellipsoid_e2); + + double z_offset = ((1.0-earth_ellipsoid_e2)*N + height - (1.0-local_ion_ellipsoid_e2)*(N+height)) * std::sqrt(sin_lat2); + + double x1 = p(0)/local_ion_ellipsoid_a; + double y1 = p(1)/local_ion_ellipsoid_a; + double z1 = (p(2)-z_offset)/local_ion_ellipsoid_b; + double c1 = x1*x1 + y1*y1 + z1*z1 - 1.0; + + dx = map.directions(0,i,j) / local_ion_ellipsoid_a; + dy = map.directions(1,i,j) / local_ion_ellipsoid_a; + dz = map.directions(2,i,j) / local_ion_ellipsoid_b; + a = dx*dx + dy*dy + dz*dz; + b = x1*dx + y1*dy + z1*dz; + alpha = (-b + std::sqrt(b*b - a*c1))/a; + + piercepoints(0, i, j) = p(0) + alpha*map.directions(0,i,j); + piercepoints(1, i, j) = p(1) + alpha*map.directions(1,i,j); + piercepoints(2, i, j) = p(2) + alpha*map.directions(2,i,j); + normal_x = piercepoints(0, i, j) / (local_ion_ellipsoid_a * local_ion_ellipsoid_a); + normal_y = piercepoints(1, i, j) / (local_ion_ellipsoid_a * local_ion_ellipsoid_a); + normal_z = (piercepoints(2, i, j)-z_offset) / (local_ion_ellipsoid_b * local_ion_ellipsoid_b); + norm_normal2 = normal_x*normal_x + normal_y*normal_y + normal_z*normal_z; + norm_normal = std::sqrt(norm_normal2); + double cos_za_rec = norm_normal / (map.directions(0,i,j)*normal_x + map.directions(1,i,j)*normal_y + map.directions(2,i,j)*normal_z); + piercepoints(3, i, j) = cos_za_rec; + +// p1 = casa::MPosition(casa::MVPosition(piercepoints(0, i, j), piercepoints(1, i, j), piercepoints(2, i, j)),casa::MPosition::ITRF); +// positionWGS84 = casa::MPosition::Convert(p1, casa::MPosition::WGS84)(); +// piercepoints(0, i, j) = positionWGS84.getValue().getLength().getValue()-height; +// cout << positionWGS84.getValue().getLength().getValue()-height << endl; - for(uint j = 0; j < field.nTileElement(); ++j) + } + } + } + Matrix<Double> tec(nX, nY, 0.0); + + Double r0sqr = r0 * r0; + Double beta_2 = 0.5 * beta; + #pragma omp parallel + { + #pragma omp for + for(uint i = 0 ; i < nX; ++i) + { + for(uint j = 0 ; j < nY; ++j) + { + for(uint k = 0 ; k < cal_pp_names.size(); ++k) { - // Compute the effective delay for a plane wave approaching from the - // direction of interest with respect to the position of element i - // when beam forming in the reference direction using time delays. - const Vector3 &offset = field.tileElement(j); - double delay = (k[0] * offset[0] + k[1] * offset[1] + k[2] * offset[2]) - / C::c; - - // Turn the delay into a phase shift. - for(uint k = 0; k < nFreq; ++k) - { - double shift = C::_2pi * freq[k] * delay; - factor(x, y, k) += DComplex(cos(shift), sin(shift)); - } + Double dx = cal_pp(0, k) - piercepoints(0,i,j); + Double dy = cal_pp(1, k) - piercepoints(1,i,j); + Double dz = cal_pp(2, k) - piercepoints(2,i,j); + Double weight = pow((dx * dx + dy * dy + dz * dz) / r0sqr, beta_2); + tec(i,j) += weight * tec_white(k); } + tec(i,j) *= (-0.5 * piercepoints(3,i,j)); } } - - // Normalize. - if(field.nTileElement() > 0) - { - factor /= static_cast<Double>(field.nTileElement()); } - return factor; - } - - Cube<double> LofarATerm::computeITRFMap(const DirectionCoordinate &coordinates, - const IPosition &shape, - MDirection::Convert convertor) const - { - MDirection world; - Vector<double> pixel = coordinates.referencePixel(); + // Convert an Array<DComplex> to a vector<Cube<Complex> >. - Cube<double> map(3, shape[0], shape[1], 0.0); - for(pixel[1] = 0.0; pixel(1) < shape[1]; ++pixel[1]) + vector<Cube<Complex> > tmp; +// cout << "freq: " << freq[0] << endl; + tmp.reserve(nFreq); + for (uint i = 0; i < freq.size(); ++i) + { + Double a = (8.44797245e9 / freq[i]); + Cube<Complex> planef(IPosition(3, nX, nY, 4), Complex(0.0, 0.0)); + for(uint j = 0 ; j < nX; ++j) { - for(pixel[0] = 0.0; pixel[0] < shape[0]; ++pixel[0]) - { - // CoodinateSystem::toWorld() - // DEC range [-pi/2,pi/2] - // RA range [-pi,pi] - if(coordinates.toWorld(world, pixel)) - { - MVDirection mvITRF(convertor(world).getValue()); - map(0, pixel[0], pixel[1]) = mvITRF(0); - map(1, pixel[0], pixel[1]) = mvITRF(1); - map(2, pixel[0], pixel[1]) = mvITRF(2); - } - } + for(uint k = 0 ; k < nY; ++k) + { + Double phase = -tec(j,k) * a; + Complex phasor(cos(phase), sin(phase)); + planef(j,k, 0) = phasor; + planef(j,k, 3) = phasor; + } } - - return map; +// cout << planef << endl; + tmp.push_back(planef); + } + return tmp; } - - void LofarATerm::initInstrument(const MeasurementSet &ms) + + +namespace +{ + vector<Cube<Complex> > asVector(Array<DComplex> &response) { - // Get station names and positions in ITRF coordinates. - ROMSAntennaColumns antenna(ms.antenna()); - ROMSObservationColumns observation(ms.observation()); - ASSERT(observation.nrow() > 0); - ASSERT(!observation.flagRow()(0)); - - // Get instrument name. - String name = observation.telescopeName()(0); - - // Get station positions. - MVPosition centroid; - vector<Station> stations(antenna.nrow()); - for(uint i = 0; i < stations.size(); ++i) - { - // Get station name and ITRF position. - MPosition position = - MPosition::Convert(antenna.positionMeas()(i), - MPosition::ITRF)(); - - // Store station information. - stations[i] = initStation(ms, i, antenna.name()(i), position); - - ASSERT(stations[i].nField() > 0); - - // Update ITRF centroid. - centroid += position.getValue(); - } - - // Get the instrument position in ITRF coordinates, or use the centroid - // of the station positions if the instrument position is unknown. - MPosition position; - if(MeasTable::Observatory(position, name)) - { - position = MPosition::Convert(position, MPosition::ITRF)(); - } - else - { - LOG_INFO("LofarATerm initInstrument " - "Instrument position unknown; will use centroid of stations."); - ASSERT(antenna.nrow() != 0); - centroid *= 1.0 / static_cast<double>(antenna.nrow()); - position = MPosition(centroid, MPosition::ITRF); - } + vector<Cube<Complex> > result; + for(ArrayIterator<DComplex> it(response, 3); !it.pastEnd(); it.next()) + { + Cube<Complex> slice(it.array().shape()); + convertArray(slice, it.array()); + result.push_back(slice); + } - m_instrument = Instrument(name, position, stations.begin(), stations.end()); + return result; } - Station LofarATerm::initStation(const MeasurementSet &ms, - uint id, - const String &name, - const MPosition &position) const + vector<Matrix<Complex> > asVector(Cube<DComplex> &response) { - AlwaysAssert(ms.keywordSet().isDefined("LOFAR_ANTENNA_FIELD"), SynthesisError); - - Table tab_field(ms.keywordSet().asTable("LOFAR_ANTENNA_FIELD")); - tab_field = tab_field(tab_field.col("ANTENNA_ID") == static_cast<Int>(id)); - - const uLong nFields = tab_field.nrow(); - AlwaysAssert(nFields == 1 || nFields == 2, SynthesisError); - - ROScalarColumn<String> c_name(tab_field, "NAME"); - ROArrayQuantColumn<double> c_position(tab_field, "POSITION", - "m"); - ROArrayQuantColumn<double> c_axes(tab_field, "COORDINATE_AXES", - "m"); - ROArrayQuantColumn<double> c_tile_offset(tab_field, - "TILE_ELEMENT_OFFSET", "m"); - ROArrayQuantColumn<double> c_offset(tab_field, "ELEMENT_OFFSET", - "m"); - ROArrayColumn<Bool> c_flag(tab_field, "ELEMENT_FLAG"); - - AntennaField field[2]; - for(uLong i = 0; i < nFields; ++i) - { - // Read antenna field center. - Vector<Quantum<double> > aips_position = - c_position(i); - ASSERT(aips_position.size() == 3); - - Vector3 position = {{aips_position[0].getValue(), - aips_position[1].getValue(), - aips_position[2].getValue()}}; - - // Read antenna field coordinate axes. - Matrix<Quantum<double> > aips_axes = c_axes(i); - ASSERT(aips_axes.shape().isEqual(IPosition(2, 3, 3))); - - Vector3 P = {{aips_axes(0, 0).getValue(), aips_axes(1, 0).getValue(), - aips_axes(2, 0).getValue()}}; - Vector3 Q = {{aips_axes(0, 1).getValue(), aips_axes(1, 1).getValue(), - aips_axes(2, 1).getValue()}}; - Vector3 R = {{aips_axes(0, 2).getValue(), aips_axes(1, 2).getValue(), - aips_axes(2, 2).getValue()}}; - - // Store information as AntennaField. - field[i] = AntennaField(c_name(i), position, P, Q, R); - - if(c_name(i) != "LBA") - { - // Read tile configuration for HBA antenna fields. - Matrix<Quantum<double> > aips_offset = - c_tile_offset(i); - ASSERT(aips_offset.nrow() == 3); - - const uLong nElement = aips_offset.ncolumn(); - for(uLong j = 0; j < nElement; ++j) - { - Vector3 offset = {{aips_offset(0, j).getValue(), - aips_offset(1, j).getValue(), - aips_offset(2, j).getValue()}}; - - field[i].appendTileElement(offset); - } - } - - // Read element position offsets and flags. - Matrix<Quantum<double> > aips_offset = c_offset(i); - Matrix<Bool> aips_flag = c_flag(i); - - const uLong nElement = aips_offset.ncolumn(); - ASSERT(aips_offset.shape().isEqual(IPosition(2, 3, nElement))); - ASSERT(aips_flag.shape().isEqual(IPosition(2, 2, nElement))); - - for(uLong j = 0; j < nElement; ++j) - { - AntennaField::Element element; - element.offset[0] = aips_offset(0, j).getValue(); - element.offset[1] = aips_offset(1, j).getValue(); - element.offset[2] = aips_offset(2, j).getValue(); - element.flag[0] = aips_flag(0, j); - element.flag[1] = aips_flag(1, j); - - field[i].appendElement(element); - } - } + vector<Matrix<Complex> > result; + for(ArrayIterator<DComplex> it(response, 2); !it.pastEnd(); it.next()) + { + Matrix<Complex> slice(it.array().shape()); + convertArray(slice, it.array()); + result.push_back(slice); + } - return (nFields == 1 ? Station(name, position, field[0]) - : Station(name, position, field[0], field[1])); + return result; } - void LofarATerm::initReferenceDirections(const MeasurementSet &ms, - uint idField) + void rescale(Array<DComplex> &response) { - // Get phase center as RA and DEC (J2000). - ROMSFieldColumns field(ms.field()); - ASSERT(field.nrow() > idField); - ASSERT(!field.flagRow()(idField)); - - m_refDelay = MDirection::Convert(field.delayDirMeas(idField), - MDirection::J2000)(); + AlwaysAssert(response.ndim() == 4, SynthesisError); + AlwaysAssert(response.shape()[2] == 4, SynthesisError); - // By default, the tile beam reference direction is assumed to be equal - // to the station beam reference direction (for backward compatibility, - // and for non-HBA measurements). - m_refTile = m_refDelay; + const uint nX = response.shape()[0]; + const uint nY = response.shape()[1]; + const uint centerX = nX / 2; + const uint centerY = nY / 2; - // The MeasurementSet class does not support LOFAR specific columns, so we - // use ROArrayMeasColumn to read the tile beam reference direction. - Table tab_field(ms.keywordSet().asTable("FIELD")); - static const String columnName = "LOFAR_TILE_BEAM_DIR"; - if(tab_field.tableDesc().isColumn(columnName)) + DComplex invXX, invXY, invYX, invYY; + for(ArrayIterator<DComplex> it(response, 3); !it.pastEnd(); it.next()) { - ROArrayMeasColumn<MDirection> c_direction(tab_field, columnName); - if(c_direction.isDefined(idField)) + Cube<DComplex> slice(it.array()); + + // Compute the inverse of the Jones matrix at the central pixel. + DComplex det = slice(centerX, centerY, 0) * slice(centerX, centerY, 3) + - slice(centerX, centerY, 1) * slice(centerX, centerY, 2); + invXX = slice(centerX, centerY, 3) / det; + invXY = -slice(centerX, centerY, 1) / det; + invYX = -slice(centerX, centerY, 2) / det; + invYY = slice(centerX, centerY, 0) / det; + + // Apply the inverse of the Jones matrix at the central pixel to all Jones + // matrices. + Matrix<DComplex> XX = slice(IPosition(3, 0, 0, 0), + IPosition(3, nX - 1, nY - 1, 0)).nonDegenerate(); + Matrix<DComplex> XY = slice(IPosition(3, 0, 0, 1), + IPosition(3, nX - 1, nY - 1, 1)).nonDegenerate(); + Matrix<DComplex> YX = slice(IPosition(3, 0, 0, 2), + IPosition(3, nX - 1, nY - 1, 2)).nonDegenerate(); + Matrix<DComplex> YY = slice(IPosition(3, 0, 0, 3), + IPosition(3, nX - 1, nY - 1, 3)).nonDegenerate(); + + DComplex normXX, normXY, normYX, normYY; + for(uint j = 0; j < nY; ++j) { - m_refTile = MDirection::Convert(c_direction(idField)(IPosition(1, 0)), - MDirection::J2000)(); + for(uint i = 0; i < nX; ++i) + { + normXX = invXX * XX(i, j) + invXY * YX(i, j); + normXY = invXX * XY(i, j) + invXY * YY(i, j); + normYX = invYX * XX(i, j) + invYY * YX(i, j); + normYY = invYX * XY(i, j) + invYY * YY(i, j); + + XX(i, j) = normXX; + XY(i, j) = normXY; + YX(i, j) = normYX; + YY(i, j) = normYY; + } } } } - void LofarATerm::initReferenceFreq(const MeasurementSet &ms, - uint idDataDescription) + void rescale(Cube<DComplex> &response) { - // Read polarization id and spectral window id. - ROMSDataDescColumns desc(ms.dataDescription()); - ASSERT(desc.nrow() > idDataDescription); - ASSERT(!desc.flagRow()(idDataDescription)); - - const uint idWindow = desc.spectralWindowId()(idDataDescription); - - // Get spectral information. - ROMSSpWindowColumns window(ms.spectralWindow()); - ASSERT(window.nrow() > idWindow); - ASSERT(!window.flagRow()(idWindow)); - - m_refFreq = window.refFrequency()(idWindow); + const uint centerX = response.shape()[0] / 2; + const uint centerY = response.shape()[1] / 2; + for(ArrayIterator<DComplex> it(response, 2); !it.pastEnd(); it.next()) + { + Matrix<DComplex> slice(it.array()); + slice /= slice(centerX, centerY); + } } - BeamCoeff::BeamCoeff() - : m_center(0.0), - m_width(1.0) + Array<DComplex> computeFieldArrayFactor(const BBS::Station::ConstPtr &station, + uint idField, const LofarATerm::ITRFDirectionMap &map, + const Vector<Double> &freq, const Vector<Double> &reference) { - } + const uint nX = map.directions.shape()[1]; + const uint nY = map.directions.shape()[2]; + const uint nFreq = freq.size(); - void BeamCoeff::load(const Path &path) - { - // Open file. - String expandedPath = path.expandedName(); - ifstream in(expandedPath.c_str()); - cout<<"Reading "<<expandedPath<<endl; - if(!in) - { - THROW (Exception, "Unable to open beam coefficient file."); - } + // Account for the case where the delay reference position is not equal to + // the field center (only applies to core HBA fields). + BBS::AntennaField::ConstPtr field = station->field(idField); + const BBS::Vector3 &fieldCenter = field->position(); - // Read file header. - String header, token0, token1, token2, token3, token4, token5; - getline(in, header); + MVPosition delayCenter = station->position().getValue(); + BBS::Vector3 offsetShift = {{fieldCenter[0] - delayCenter(0), + fieldCenter[1] - delayCenter(1), + fieldCenter[2] - delayCenter(2)}}; - uLong nElements, nHarmonics, nPowerTheta, nPowerFreq; - double freqAvg, freqRange; + // Compute field array factors. + Array<DComplex> AF(IPosition(4, nX, nY, 2, nFreq), DComplex(0.0, 0.0)); + Cube<DComplex> weight(nX, nY, nFreq); - istringstream iss(header); - iss >> token0 >> nElements >> token1 >> nHarmonics >> token2 >> nPowerTheta - >> token3 >> nPowerFreq >> token4 >> freqAvg >> token5 >> freqRange; - - if(!in || !iss || token0 != "d" || token1 != "k" || token2 != "pwrT" - || token3 != "pwrF" || token4 != "freqAvg" || token5 != "freqRange") - { - THROW (Exception, "Unable to parse header"); - } - - if(nElements * nHarmonics * nPowerTheta * nPowerFreq == 0) + for(uint i = 0; i < field->nElement(); ++i) + { + const BBS::AntennaField::Element &element = field->element(i); + if(element.flag[0] && element.flag[1]) { - THROW (Exception, "The number of coefficients should be" - " larger than zero."); + continue; } - ASSERT(nElements == 2); - ASSERT(in.good()); + // Compute the offset relative to the delay center. + BBS::Vector3 offset = {{element.offset[0] + offsetShift[0], + element.offset[1] + offsetShift[1], + element.offset[2] + offsetShift[2]}}; - // Allocate coefficient matrix. - m_center = freqAvg; - m_width = freqRange; - m_coeff = Array<DComplex>(IPosition(4, 2, nPowerFreq, nPowerTheta, nHarmonics)); + // Compute the delay for a plane wave approaching from the delay + // reference direction with respect to the element position. + double delay0 = (map.refDelay[0] * offset[0] + + map.refDelay[1] * offset[1] + + map.refDelay[2] * offset[2]) / C::c; - uLong nCoeff = 0; - while(in.good()) + for(uint k = 0; k < nY; ++k) { - // Read line from file. - String line; - getline(in, line); - - // Skip lines that contain only whitespace. - if(line.find_last_not_of(" ", String::npos) == String::npos) - { - continue; - } - - // Parse line. - uLong element, harmonic, powerTheta, powerFreq; - double re, im; - - iss.clear(); - iss.str(line); - iss >> element >> harmonic >> powerTheta >> powerFreq >> re >> im; + for(uint j = 0; j < nX; ++j) + { + // Compute the delay for a plane wave approaching from the direction + // of interest with respect to the element position. + double delay = (map.directions(0, j, k) * offset[0] + + map.directions(1, j, k) * offset[1] + + map.directions(2, j, k) * offset[2]) / C::c; - if(!iss || element >= nElements || harmonic >= nHarmonics - || powerTheta >= nPowerTheta || powerFreq >= nPowerFreq) + for(uint l = 0; l < nFreq; ++l) { - THROW (Exception, "Error reading beam coefficient file."); + double shift = C::_2pi * (freq[l] * delay - reference[l] * delay0); + weight(j, k, l) = DComplex(cos(shift), sin(shift)); } - - // Store coefficient. - m_coeff(IPosition(4, element, powerFreq, powerTheta, harmonic)) = DComplex(re, im); - - // Update coefficient counter. - ++nCoeff; + } } - if(!in.eof()) + if(!element.flag[0]) { - THROW (Exception, "Error reading beam coefficient" - " file."); + IPosition start(4, 0, 0, 0, 0); + IPosition end(4, nX - 1, nY - 1, 0, nFreq - 1); + Array<DComplex> slice = AF(start, end).reform(weight.shape()); + slice += weight; } - if(nCoeff != nElements * nHarmonics * nPowerTheta * nPowerFreq) + if(!element.flag[1]) { - THROW (Exception, "The number of coefficients" - " specified in the header does not match the number of coefficients" - " in the file."); + IPosition start(4, 0, 0, 1, 0); + IPosition end(4, nX - 1, nY - 1, 1, nFreq - 1); + Array<DComplex> slice = AF(start, end).reform(weight.shape()); + slice += weight; } - } - - AntennaField::AntennaField(const String &name, - const Vector3 &position, - const Vector3 &p, - const Vector3 &q, - const Vector3 &r) - : m_name(name), - m_position(position) - { - m_axes[P] = p; - m_axes[Q] = q; - m_axes[R] = r; - } - - const String &AntennaField::name() const - { - return m_name; - } + } - const Vector3 &AntennaField::position() const - { - return m_position; - } + // Normalize. + if(station->nActiveElement() > 0) + { + AF /= static_cast<Double>(station->nActiveElement()); + } - const Vector3 &AntennaField::axis(Axis axis) const - { - return m_axes[axis]; - } + if(field->isHBA()) + { + // Compute tile array factor. + Cube<DComplex> tileAF = computeTileArrayFactor(field, map, freq); - Bool AntennaField::isHBA() const - { - return m_name != "LBA"; - } + // Multiply the station array factor by the tile array factor. + for(uint i = 0; i < 2; ++i) + { + IPosition start(4, 0, 0, i, 0); + IPosition end(4, nX - 1, nY - 1, i, nFreq - 1); + Array<DComplex> slice = AF(start, end).reform(tileAF.shape()); + slice *= tileAF; + } + } - void AntennaField::appendTileElement(const Vector3 &offset) - { - m_tileElements.push_back(offset); + return AF; } - void AntennaField::appendElement(const Element &element) + Cube<DComplex> + computeTileArrayFactor(const BBS::AntennaField::ConstPtr &field, + const LofarATerm::ITRFDirectionMap &map, const Vector<Double> &freq) { - m_elements.push_back(element); - } + const uint nX = map.directions.shape()[1]; + const uint nY = map.directions.shape()[2]; + const uint nFreq = freq.size(); - Station::Station(const String &name, - const MPosition &position) - : m_name(name), - m_position(position) - { - } + Cube<DComplex> AF(nX, nY, nFreq, DComplex(0.0, 0.0)); + for(uint j = 0; j < nY; ++j) + { + for(uint i = 0; i < nX; ++i) + { + // Instead of computing a phase shift for the pointing direction and a + // phase shift for the direction of interest and then computing the + // difference, compute the resultant phase shift in one go. Here we make + // use of the relation a . b + a . c = a . (b + c). The sign of k is + // related to the sign of the phase shift. + double k[3]; + k[0] = map.directions(0, i, j) - map.refTile[0]; + k[1] = map.directions(1, i, j) - map.refTile[1]; + k[2] = map.directions(2, i, j) - map.refTile[2]; - Station::Station(const String &name, - const MPosition &position, - const AntennaField &field0) - : m_name(name), - m_position(position) - { - m_fields.push_back(field0); - } + for(uint l = 0; l < field->nTileElement(); ++l) + { + // Compute the effective delay for a plane wave approaching from the + // direction of interest with respect to the position of element i + // when beam forming in the reference direction using time delays. + const BBS::Vector3 &offset = field->tileElement(l); + double delay = (k[0] * offset[0] + k[1] * offset[1] + k[2] + * offset[2]) / C::c; - Station::Station(const String &name, - const MPosition &position, - const AntennaField &field0, - const AntennaField &field1) - : m_name(name), - m_position(position) - { - m_fields.push_back(field0); - m_fields.push_back(field1); - } + // Turn the delay into a phase shift. + for(uint m = 0; m < nFreq; ++m) + { + double shift = C::_2pi * freq[m] * delay; + AF(i, j, m) += DComplex(cos(shift), sin(shift)); + } + } + } + } - const String &Station::name() const - { - return m_name; - } + // Normalize. + if(field->nTileElement() > 0) + { + AF /= static_cast<Double>(field->nTileElement()); + } - const MPosition &Station::position() const - { - return m_position; + return AF; } - bool Station::isPhasedArray() const + struct ElementLBA { - return !m_fields.empty(); - } + static void response(double freq, double theta, double phi, + DComplex (&response)[2][2]) + { + element_response_lba(freq, theta, phi, response); + } + }; - uint Station::nField() const + struct ElementHBA { - return m_fields.size(); - } + static void response(double freq, double theta, double phi, + DComplex (&response)[2][2]) + { + element_response_hba(freq, theta, phi, response); + } + }; - const AntennaField &Station::field(uint i) const + template <typename T_ELEMENT> + Array<DComplex> + computeElementResponse(const BBS::AntennaField::ConstPtr &field, + const LofarATerm::ITRFDirectionMap &map, const Vector<Double> &freq) { - return m_fields[i]; - } + const BBS::Vector3 &p = field->axis(BBS::AntennaField::P); + const BBS::Vector3 &q = field->axis(BBS::AntennaField::Q); + const BBS::Vector3 &r = field->axis(BBS::AntennaField::R); - Instrument::Instrument(const String &name, - const MPosition &position) - : m_name(name), - m_position(position) - { - } + const uint nX = map.directions.shape()[1]; + const uint nY = map.directions.shape()[2]; + const uint nFreq = freq.size(); - const String &Instrument::name() const - { - return m_name; - } + DComplex J[2][2]; + Array<DComplex> E(IPosition(4, nX, nY, 4, nFreq), DComplex(0.0, 0.0)); + for(uint j = 0; j < nY; ++j) + { + for(uint i = 0; i < nX; ++i) + { + BBS::Vector3 target = {{map.directions(0, i, j), + map.directions(1, i, j), map.directions(2, i, j)}}; - const MPosition &Instrument::position() const - { - return m_position; - } + // Check for non-physical directions (the image is square while the + // projected sky is circular, therefore some image pixels may map to + // invalid directions. + if(target[0] == 0.0 && target[1] == 0.0 && target[2] == 0.0) + { + continue; + } - uint Instrument::nStations() const - { - return m_stations.size(); - } + // Compute the cross product of the NCP and the target direction. This + // yields a vector tangent to the celestial sphere at the target + // direction, pointing towards the East (the direction of +Y in the IAU + // definition, or positive right ascension). + BBS::Vector3 v1 = {{-target[1], target[0], 0.0}}; + double normv1 = sqrt(v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2]); + v1[0] /= normv1; + v1[1] /= normv1; + v1[2] /= normv1; + + // Compute the cross product of the antenna field normal (R) and the + // target direction. This yields a vector tangent to the topocentric + // spherical coordinate system at the target direction, pointing towards + // the direction of positive phi (which runs East over North around the + // pseudo zenith). + BBS::Vector3 v2 = {{r[1] * target[2] - r[2] * target[1], + r[2] * target[0] - r[0] * target[2], + r[0] * target[1] - r[1] * target[0]}}; + double normv2 = sqrt(v2[0] * v2[0] + v2[1] * v2[1] + v2[2] * v2[2]); + v2[0] /= normv2; + v2[1] /= normv2; + v2[2] /= normv2; + + // Compute the cosine and sine of the parallactic angle, i.e. the angle + // between v1 and v2, both tangent to a latitude circle of their + // respective spherical coordinate systems. + double coschi = v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]; + double sinchi = (v1[1] * v2[2] - v1[2] * v2[1]) * target[0] + + (v1[2] * v2[0] - v1[0] * v2[2]) * target[1] + + (v1[0] * v2[1] - v1[1] * v2[0]) * target[2]; + + // The input coordinate system is a right handed system with its third + // axis along the direction of propagation (IAU +Z). The output + // coordinate system is right handed as well, but its third axis points + // in the direction of arrival (i.e. exactly opposite). + // + // Because the electromagnetic field is always perpendicular to the + // direction of propagation, we only need to relate the (X, Y) axes of + // the input system to the corresponding (theta, phi) axes of the output + // system. + // + // To this end, we first rotate the input system around its third axis + // to align the Y axis with the phi axis. The X and theta axis are + // parallel after this rotation, but point in opposite directions. To + // align the X axis with the theta axis, we flip it. + // + // The Jones matrix to align the Y axis with the phi axis when these are + // separated by an angle phi (measured counter-clockwise around the + // direction of propagation, looking towards the origin), is given by: + // + // [ cos(phi) sin(phi)] + // [-sin(phi) cos(phi)] + // + // Here, cos(phi) and sin(phi) can be computed directly, without having + // to compute phi first (see the computation of coschi and sinchi + // above). + // + // Now, sinchi as computed above is opposite to sin(phi), because the + // direction used in the computation is the direction of arrival instead + // of the direction of propagation. Therefore, the sign of sinchi needs + // to be reversed. Furthermore, as explained above, the X axis has to be + // flipped to align with the theta axis. The Jones matrix returned from + // this function is therefore given by: + // + // [-coschi sinchi] + // [ sinchi coschi] - const Station &Instrument::station(uint i) const - { - return m_stations[i]; - } + // Compute the P and Q coordinate of the direction vector by projecting + // onto the positive P and Q axis. + double projectionP = target[0] * p[0] + target[1] * p[1] + target[2] + * p[2]; + double projectionQ = target[0] * q[0] + target[1] * q[1] + target[2] + * q[2]; + + // Compute the inner product between the antenna field normal (R) and + // the direction vector to get the cosine of the zenith angle. + double projectionR = target[0] * r[0] + target[1] * r[1] + target[2] + * r[2]; + + double theta = acos(projectionR); + double phi = atan2(projectionQ, projectionP); + + // The positive X dipole direction is SW of the reference orientation, + // which translates to a phi coordinate of 5/4*pi in the topocentric + // spherical coordinate system. The phi coordinate is corrected for this + // offset before evaluating the antenna model. + phi -= 5.0 * C::pi_4; + + for(uint k = 0; k < nFreq; ++k) + { + T_ELEMENT::response(freq[k], theta, phi, J); - const Station &Instrument::station(const String &name) const - { - map<String, uint>::const_iterator it = m_index.find(name); - if(it == m_index.end()) - { - THROW (Exception, "Unknown station: " + name); + E(IPosition(4, i, j, 0, k)) = J[0][0] * -coschi + J[0][1] * sinchi; + E(IPosition(4, i, j, 1, k)) = J[0][0] * sinchi + J[0][1] * coschi; + E(IPosition(4, i, j, 2, k)) = J[1][0] * -coschi + J[1][1] * sinchi; + E(IPosition(4, i, j, 3, k)) = J[1][0] * sinchi + J[1][1] * coschi; + } } + } - return m_stations[it->second]; + return E; } + +} // unnamed namespace - void Instrument::append(const Station &station) - { - m_stations.push_back(station); - } } // namespace LOFAR diff --git a/CEP/Imager/LofarFT/src/LofarATermOld.cc b/CEP/Imager/LofarFT/src/LofarATermOld.cc new file mode 100644 index 0000000000000000000000000000000000000000..c2704db3f398a24b29578769cdff1773f3268791 --- /dev/null +++ b/CEP/Imager/LofarFT/src/LofarATermOld.cc @@ -0,0 +1,1038 @@ +//# LofarATermOld.cc: Compute the LOFAR beam response on the sky. +//# +//# Copyright (C) 2011 +//# ASTRON (Netherlands Institute for Radio Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +//# +//# This file is part of the LOFAR software suite. +//# The LOFAR software suite is free software: you can redistribute it and/or +//# modify it under the terms of the GNU General Public License as published +//# by the Free Software Foundation, either version 3 of the License, or +//# (at your option) any later version. +//# +//# The LOFAR software suite 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License along +//# with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>. +//# +//# $Id$ + +#include <lofar_config.h> +#include <LofarFT/LofarATermOld.h> +#include <Common/LofarLogger.h> +#include <Common/Exception.h> + +#include <casa/OS/Path.h> +#include <casa/Arrays/ArrayIter.h> +#include <casa/Arrays/Cube.h> +#include <coordinates/Coordinates/DirectionCoordinate.h> +#include <measures/Measures/MeasTable.h> +#include <measures/Measures/MeasConvert.h> +#include <measures/Measures/MCDirection.h> +#include <measures/Measures/MCPosition.h> +#include <ms/MeasurementSets/MeasurementSet.h> +#include <ms/MeasurementSets/MSAntenna.h> +#include <ms/MeasurementSets/MSAntennaParse.h> +#include <ms/MeasurementSets/MSAntennaColumns.h> +#include <ms/MeasurementSets/MSDataDescription.h> +#include <ms/MeasurementSets/MSDataDescColumns.h> +#include <ms/MeasurementSets/MSField.h> +#include <ms/MeasurementSets/MSFieldColumns.h> +#include <ms/MeasurementSets/MSObservation.h> +#include <ms/MeasurementSets/MSObsColumns.h> +#include <ms/MeasurementSets/MSPolarization.h> +#include <ms/MeasurementSets/MSPolColumns.h> +#include <ms/MeasurementSets/MSSpectralWindow.h> +#include <ms/MeasurementSets/MSSpWindowColumns.h> +#include <ms/MeasurementSets/MSSelection.h> +#include <synthesis/MeasurementComponents/SynthesisError.h> + +// DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG +#include <iomanip> +// DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG + +using namespace casa; + +namespace LOFAR +{ + LofarATermOld::LofarATermOld(const MeasurementSet& ms, + const String& beamElementPath) + { + if (beamElementPath.empty()) { + m_coeffLBA.load(Path("element_beam_HAMAKER_LBA.coeff")); + m_coeffHBA.load(Path("element_beam_HAMAKER_HBA.coeff")); + } else { + m_coeffLBA.load(Path(beamElementPath + "/element_beam_HAMAKER_LBA.coeff")); + m_coeffHBA.load(Path(beamElementPath + "/element_beam_HAMAKER_HBA.coeff")); + } + // m_coeffLBA.load(Path("element_beam_LBA.coeff")); + // m_coeffHBA.load(Path("element_beam_HBA.coeff")); + + initInstrument(ms); + initReferenceFreq(ms, 0); + initReferenceDirections(ms, 0); + } + + vector<Cube<Complex> > LofarATermOld::evaluate(const IPosition &shape, + const DirectionCoordinate &coordinates, + uint station, + const MEpoch &epoch, + const Vector<Double> &freq, + bool normalize) const + { + AlwaysAssert(station < m_instrument.nStations(), SynthesisError); + AlwaysAssert(shape[0] > 0 && shape[1] > 0, SynthesisError); + AlwaysAssert(freq.size() > 0, SynthesisError); + + // Create conversion engine (from J2000 -> ITRF). + MDirection::Convert convertor = MDirection::Convert(MDirection::J2000, + MDirection::Ref(MDirection::ITRF, + MeasFrame(epoch, m_instrument.position()))); + + MVDirection mvRefDelay = convertor(m_refDelay).getValue(); + Vector3 refDelay = {{mvRefDelay(0), mvRefDelay(1), mvRefDelay(2)}}; + + MVDirection mvRefTile = convertor(m_refTile).getValue(); + Vector3 refTile = {{mvRefTile(0), mvRefTile(1), mvRefTile(2)}}; + + // Compute ITRF map. + LOG_INFO("LofarATermOld::evaluate(): Computing ITRF map..."); + Cube<double> mapITRF = computeITRFMap(coordinates, shape, convertor); + LOG_INFO("LofarATermOld::evaluate(): Computing ITRF map... done."); + + // Compute element beam response. + LOG_INFO("LofarATermOld::evaluate(): Computing station response..."); + Array<DComplex> response = + evaluateStationBeam(m_instrument.station(station), refDelay, refTile, + mapITRF, freq); + + // DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG +// MDirection world; +// Vector<double> refPixel = coordinates.referencePixel(); + +// cout << "shape: " << shape << " ref. pixel: " << refPixel << endl; +// coordinates.toWorld(world, refPixel); + +// casa::Quantum<casa::Vector<casa::Double> > refAngles = world.getAngle(); +// double ra = refAngles.getBaseValue()(0); +// double dec = refAngles.getBaseValue()(1); +// cout << "ref. world: " << std::setprecision(17) << ra << " " << dec << endl; + +// cout << "station: " << station << endl; +// cout << "freq: " << std::setprecision(17) << freq << endl; +// cout << "time: " << std::setprecision(17) << epoch.getValue().getTime("s") << endl; +// IPosition st(4, refPixel(0), refPixel(1), 0, 0); +// IPosition en(4, refPixel(0), refPixel(1), 3, freq.size() - 1); +// Array<DComplex> tmpResponse = response(st, en).nonDegenerate(); +// cout << "response shape: " << tmpResponse.shape() << endl; +// cout << "response: " << endl << tmpResponse << endl; + +// refPixel = 0.0; +// coordinates.toWorld(world, refPixel); +// refAngles = world.getAngle(); +// ra = refAngles.getBaseValue()(0); +// dec = refAngles.getBaseValue()(1); +// cout << "0 world: " << std::setprecision(17) << ra << " " << dec << endl; + +// st = IPosition(4, 0, 0, 0, 0); +// en = IPosition(4, 0, 0, 3, freq.size() - 1); +// Array<DComplex> tmpResponse2 = response(st, en).nonDegenerate(); +// cout << "response shape: " << tmpResponse2.shape() << endl; +// cout << "response: " << endl << tmpResponse2 << endl; + +// AlwaysAssert(false, SynthesisError); + // DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG + + + + //Cyril + if(normalize) + { + response = this->normalize(response); + } + LOG_INFO("LofarATermOld::evaluate(): Computing station response... done."); + + // Convert an Array<DComplex> to a vector<Cube<Complex> >. + vector<Cube<Complex> > tmp; + tmp.reserve(freq.size()); + for (ArrayIterator<DComplex> iter(response, 3); + !iter.pastEnd(); iter.next()) + { + Cube<Complex> planef(iter.array().shape()); + convertArray (planef, iter.array()); + tmp.push_back(planef); + } + + // if(normalize) + // MDirection::Convert convertor = MDirection::Convert(MDirection::J2000, MDirection::Ref(MDirection::ITRF, MeasFrame(epoch, m_instrument.position()))); + // mapITRF = computeITRFMap(coordinates, shape, convertor); + // Cube<double> mapITRF_center; + // DirectionCoordinate coordinates_center(coordinates); + // Vector<Double> Refpix(2,0.); + // coordinates_center.setReferencePixel(Refpix); + // mapITRF_center = computeITRFMap(coordinates_center, IPosition(2,1,1), convertor); + // for(uInt i = 0; i < freq.size(); ++i){ + // { + // evaluateStationBeam(m_instrument.station(station), refDelay, refTile, + // mapITRF, freq); + // Cube<Complex> gain(evaluateStationBeam(mapITRF_center, convertor(m_phaseReference), m_instrument.station(station), freq[i])); + // Matrix<Complex> central_gain(gain.xzPlane(0)); + // // central_gain.resize(2,2,true); //resize does not work: + // // Central gain Axis Lengths: [1, 4] (NB: Matrix in Row/Column order) + // // [(-0.0235668,-0.000796029), (-0.0345345,-0.000373378), (0.030112,0.000938836), (-0.0268743,-0.000258621)] + // // Central gain Axis Lengths: [2, 2] (NB: Matrix in Row/Column order) + // // [(-0.0235668,-0.000796029), (-0.0345345,-0.000373378) + // // (0,0), (0,0)] + // Matrix<Complex> central_gain_reform(central_gain.reform(IPosition(2,2,2))); + // Matrix<Complex> central_gain_invert(invert(central_gain_reform)); + + // //Cube<Complex> IM=beams[i]; + // for(uInt ii=0;ii<shape[0];++ii) + // { + // for(uInt jj=0;jj<shape[1];++jj) + // { + // Cube<Complex> pixel(tmp[i](IPosition(3,ii,jj,0),IPosition(3,ii,jj,3)).copy()); + // // cout<<"================="<<pixel<<endl; + // // cout<<"pixel"<<pixel<<endl; + // Matrix<Complex> pixel_reform(pixel.reform(IPosition(2,2,2))); + // // cout<<"pixel_reform"<<pixel_reform<<endl; + // Matrix<Complex> pixel_product=product(central_gain_invert,pixel_reform); + // // cout<<"pixel_product"<<pixel_product<<endl; + // Matrix<Complex> pixel_product_reform(pixel_product.reform(IPosition(2,1,4))); + // // cout<<"pixel_product_reform"<<pixel_product_reform<<endl; + + // for(uInt ind=0;ind<4;++ind){tmp[i](ii,jj,ind)=pixel_product_reform(0,ind);}; + // //beams[i](IPosition(3,ii,jj,0),IPosition(3,ii,jj,3))=pixel_product; + // //IM(ii,jj)=pixel_product; + // } + // } + // }; + + return tmp; + } + + Array<DComplex> LofarATermOld::normalize(const Array<DComplex> &response) + const + { + const uint nX = response.shape()[0]; + const uint nY = response.shape()[1]; + const uint nFreq = response.shape()[3]; + AlwaysAssert(response.shape()[2] == 4, SynthesisError); + AlwaysAssert(nX > 0 && nY > 0 && nFreq > 0, SynthesisError); + + // Cast away const, to be able to use Array<T>::operator(IPosition, + // IPosition) to extract a slice (for reading). + Array<DComplex> &__response = const_cast<Array<DComplex>&>(response); + + // Extract beam response for the central pixel at the central frequency. + IPosition start(4, floor(nX / 2.), floor(nY / 2.), 0, floor(nFreq / 2.)); + IPosition end(4, floor(nX / 2.), floor(nY / 2.), 3, floor(nFreq / 2.)); + + // Use assignment operator to force a copy. + Vector<DComplex> factor; + factor = __response(start, end).nonDegenerate(); + + // Compute the inverse of the reponse. + Vector<DComplex> inverse(4); + DComplex determinant = factor(0) * factor(3) - factor(1) * factor(2); + inverse(0) = factor(3) / determinant; + inverse(1) = -factor(1) / determinant; + inverse(2) = -factor(2) / determinant; + inverse(3) = factor(0) / determinant; + + // Multiply the beam response for all pixels, at all frequencies, by the + // computed inverse. + Array<DComplex> XX = __response(IPosition(4, 0, 0, 0, 0), + IPosition(4, nX - 1, nY - 1, 0, nFreq - 1)); + Array<DComplex> XY = __response(IPosition(4, 0, 0, 1, 0), + IPosition(4, nX - 1, nY - 1, 1, nFreq - 1)); + Array<DComplex> YX = __response(IPosition(4, 0, 0, 2, 0), + IPosition(4, nX - 1, nY - 1, 2, nFreq - 1)); + Array<DComplex> YY = __response(IPosition(4, 0, 0, 3, 0), + IPosition(4, nX - 1, nY - 1, 3, nFreq - 1)); + + Array<DComplex> normal(response.shape()); + Array<DComplex> nXX = normal(IPosition(4, 0, 0, 0, 0), + IPosition(4, nX - 1, nY - 1, 0, nFreq - 1)); + Array<DComplex> nXY = normal(IPosition(4, 0, 0, 1, 0), + IPosition(4, nX - 1, nY - 1, 1, nFreq - 1)); + Array<DComplex> nYX = normal(IPosition(4, 0, 0, 2, 0), + IPosition(4, nX - 1, nY - 1, 2, nFreq - 1)); + Array<DComplex> nYY = normal(IPosition(4, 0, 0, 3, 0), + IPosition(4, nX - 1, nY - 1, 3, nFreq - 1)); + + nXX = inverse(0) * XX + inverse(1) * YX; + nXY = inverse(0) * XY + inverse(1) * YY; + nYX = inverse(2) * XX + inverse(3) * YX; + nYY = inverse(2) * XY + inverse(3) * YY; + + return normal; + } + + Array<DComplex> LofarATermOld::evaluateElementBeam(const BeamCoeff &coeff, + const AntennaField &field, + const Cube<double> &map, + const Vector<double> &freq) const + { + const Vector3 &p = field.axis(AntennaField::P); + const Vector3 &q = field.axis(AntennaField::Q); + const Vector3 &r = field.axis(AntennaField::R); + + const uint nX = map.shape()[1]; + const uint nY = map.shape()[2]; + const uint nFreq = freq.shape()[0]; + + Array<DComplex> beam(IPosition(4, nX, nY, 4, nFreq), DComplex(0.0, 0.0)); + for(uint j = 0; j < nY; ++j) + { + for(uint i = 0; i < nX; ++i) + { + if(map(0, i, j) == 0.0 && map(1, i, j) == 0.0 && map(2, i, j) == 0.0) + { + // Non-physical pixel. + continue; + } + + // Compute the P and Q coordinate of the direction vector by projecting + // onto the positive P and Q axis. + double projectionP = map(0, i, j) * p[0] + map(1, i, j) * p[1] + map(2, i, j) * p[2]; + double projectionQ = map(0, i, j) * q[0] + map(1, i, j) * q[1] + map(2, i, j) * q[2]; + + // Compute the inner product between the antenna field normal + // (R) and the direction vector to get the sine of the elevation + // (cosine of the zenith angle). + double sinEl = map(0, i, j) * r[0] + map(1, i, j) * r[1] + map(2, i, j) * r[2]; + + double az = atan2(projectionP, projectionQ); + double el = asin(sinEl); + + // Evaluate beam. + // Correct azimuth for dipole orientation. + const double phi = az - 3.0 * C::pi_4; + + // NB: The model is parameterized in terms of zenith angle. The + // appropriate conversion is taken care of below. + const double theta = C::pi_2 - el; + + // Only compute the beam response for directions above the horizon. + if(theta < C::pi_2) + { + for(uint k = 0; k < nFreq; ++k) + { + // J-jones matrix (2x2 complex matrix) + DComplex J[2][2] = {{0.0, 0.0}, {0.0, 0.0}}; + + // NB: The model is parameterized in terms of a normalized + // frequency in the range [-1, 1]. The appropriate conversion is + // taken care of below. + const double normFreq = (freq[k] - coeff.center()) / coeff.width(); + + for(uint l = 0; l < coeff.nHarmonics(); ++l) + { + // Compute diagonal projection matrix P for the current + // harmonic. + DComplex P[2] = {0.0, 0.0}; + + DComplex inner[2]; + for(int m = coeff.nPowerTheta() - 1; m >= 0; --m) + { + inner[0] = coeff(0, coeff.nPowerFreq() - 1, m, l); + inner[1] = coeff(1, coeff.nPowerFreq() - 1, m, l); + + for(int n = coeff.nPowerFreq() - 2; n >= 0; --n) + { + inner[0] = inner[0] * normFreq + coeff(0, n, m, l); + inner[1] = inner[1] * normFreq + coeff(1, n, m, l); + } + + P[0] = P[0] * theta + inner[0]; + P[1] = P[1] * theta + inner[1]; + } + + // Compute Jones matrix for this harmonic by rotating P over + // kappa * phi and add it to the result. + const double kappa = ((l & 1) == 0 ? 1.0 : -1.0) * (2.0 * l + 1.0); + const double cphi = cos(kappa * phi); + const double sphi = sin(kappa * phi); + + J[0][0] += cphi * P[0]; + J[0][1] += -sphi * P[1]; + J[1][0] += sphi * P[0]; + J[1][1] += cphi * P[1]; + } + + beam(IPosition(4, i, j, 0, k)) = J[0][0]; + beam(IPosition(4, i, j, 1, k)) = J[0][1]; + beam(IPosition(4, i, j, 2, k)) = J[1][0]; + beam(IPosition(4, i, j, 3, k)) = J[1][1]; + } + } + } + } + + return beam; + } + + Array<DComplex> LofarATermOld::evaluateStationBeam(const Station &station, + const Vector3 &refDelay, + const Vector3 &refTile, + const Cube<Double> &map, + const Vector<Double> &freq) const + { + const uint nX = map.shape()[1]; + const uint nY = map.shape()[2]; + const uint nFreq = freq.shape()[0]; + + uint countX = 0, countY = 0; + Array<DComplex> E(IPosition(4, nX, nY, 4, nFreq), DComplex(0.0, 0.0)); + for(uint i = 0; i < station.nField(); ++i) + { + const AntennaField &field = station.field(i); + + // Compute element beam. + LOG_INFO("LofarATermOld::computeStationBeam: Computing element beam..."); + Array<DComplex> beam; + if(field.isHBA()) + { + beam = evaluateElementBeam(m_coeffHBA, field, map, freq); + } + else + { + beam = evaluateElementBeam(m_coeffLBA, field, map, freq); + } + LOG_INFO("LofarATermOld::computeStationBeam: Computing element beam... done."); + + if(field.isHBA()) + { + // Compute tile array factor. + LOG_INFO("LofarATermOld::computeStationBeam: Computing tile array factor..."); + Cube<DComplex> tileAF = evaluateTileArrayFactor(field, refTile, map, + freq); + LOG_INFO("LofarATermOld::computeStationBeam: Computing tile array factor... done."); + + Array<DComplex> tileAF4 = tileAF.reform(IPosition(4, nX, nY, 1, nFreq)); + + // Multiply the element beam by the tile array factor. + for(uint j = 0; j < 4; ++j) + { + IPosition start(4, 0, 0, j, 0); + IPosition end(4, nX - 1, nY - 1, j, nFreq - 1); + + Array<DComplex> plane = beam(start, end); + plane *= tileAF4; + } + } + + LOG_INFO("LofarATermOld::computeStationBeam: Computing station array factor..."); + + // Account for the case where the delay reference position is not equal to + // the field center (only applies to core HBA fields). + const Vector3 &fieldCenter = field.position(); + MVPosition delayCenter = station.position().getValue(); + Vector3 offsetShift = {{fieldCenter[0] - delayCenter(0), + fieldCenter[1] - delayCenter(1), + fieldCenter[2] - delayCenter(2)}}; + + // Compute field array factors. + Cube<DComplex> fieldAFX(nX, nY, nFreq, DComplex(0.0, 0.0)); + Cube<DComplex> fieldAFY(nX, nY, nFreq, DComplex(0.0, 0.0)); + Cube<DComplex> phase(nX, nY, nFreq, DComplex(0.0, 0.0)); + + for(uint j = 0; j < field.nElement(); ++j) + { + const AntennaField::Element &element = field.element(j); + if(element.flag[0] && element.flag[1]) + { + continue; + } + + // Compute the offset relative to the delay center. + Vector3 offset = {{element.offset[0] + offsetShift[0], + element.offset[1] + offsetShift[1], + element.offset[2] + offsetShift[2]}}; + + // Compute the delay for a plane wave approaching from the delay + // reference direction with respect to the element position. + double delay0 = (refDelay[0] * offset[0] + refDelay[1] * offset[1] + + refDelay[2] * offset[2]) / casa::C::c; + double shift0 = C::_2pi * m_refFreq * delay0; + + for(uint y = 0; y < nY; ++y) + { + for(uint x = 0; x < nX; ++x) + { + // Compute the delay for a plane wave approaching from the direction + // of interest with respect to the element position. + double delay = (map(0, x, y) * offset[0] + + map(1, x, y) * offset[1] + + map(2, x, y) * offset[2]) / casa::C::c; + + for(uint k = 0; k < nFreq; ++k) + { + double shift = C::_2pi * freq[k] * delay - shift0; + phase(x, y, k) = DComplex(cos(shift), sin(shift)); + } + } + } + + if(!element.flag[0]) + { + fieldAFX += phase; + ++countX; + } + + if(!element.flag[1]) + { + fieldAFY += phase; + ++countY; + } + } + + LOG_INFO("LofarATermOld::computeStationBeam: Computing station array factor... done."); + Array<DComplex> fieldAFX4 = fieldAFX.reform(IPosition(4, nX, nY, 1, nFreq)); + for(uint k = 0; k < 2; ++k) + { + IPosition start(4, 0, 0, k, 0); + IPosition end(4, nX - 1, nY - 1, k, nFreq - 1); + Array<DComplex> plane = E(start, end); + plane += fieldAFX4 * beam(start, end); + } + + Array<DComplex> fieldAFY4 = fieldAFY.reform(IPosition(4, nX, nY, 1, nFreq)); + for(uint k = 2; k < 4; ++k) + { + IPosition start(4, 0, 0, k, 0); + IPosition end(4, nX - 1, nY - 1, k, nFreq - 1); + Array<DComplex> plane = E(start, end); + plane += fieldAFY4 * beam(start, end); + } + } // fields + + // Normalize. + if(countX > 0) + { + IPosition start(4, 0, 0, 0, 0); + IPosition end(4, nX - 1, nY - 1, 1, nFreq - 1); + Array<DComplex> plane = E(start, end); + plane /= static_cast<Double>(countX); + } + + if(countY > 0) + { + IPosition start(4, 0, 0, 2, 0); + IPosition end(4, nX - 1, nY - 1, 3, nFreq - 1); + Array<DComplex> plane = E(start, end); + plane /= static_cast<Double>(countY); + } + + return E; + } + + Cube<DComplex> LofarATermOld::evaluateTileArrayFactor(const AntennaField &field, + const Vector3 &reference, + const Cube<Double> &map, + const Vector<Double> &freq) const + { + const uint nX = map.shape()[1]; + const uint nY = map.shape()[2]; + const uint nFreq = freq.shape()[0]; + + Cube<DComplex> factor(nX, nY, nFreq, DComplex(0.0, 0.0)); + for(uint y = 0; y < nY; ++y) + { + for(uint x = 0; x < nX; ++x) + { + // Instead of computing a phase shift for the pointing direction and a + // phase shift for the direction of interest and then computing the + // difference, compute the resultant phase shift in one go. Here we make + // use of the relation a . b + a . c = a . (b + c). The sign of k is + // related to the sign of the phase shift. + double k[3]; + k[0] = map(0, x, y) - reference[0]; + k[1] = map(1, x, y) - reference[1]; + k[2] = map(2, x, y) - reference[2]; + + for(uint j = 0; j < field.nTileElement(); ++j) + { + // Compute the effective delay for a plane wave approaching from the + // direction of interest with respect to the position of element i + // when beam forming in the reference direction using time delays. + const Vector3 &offset = field.tileElement(j); + double delay = (k[0] * offset[0] + k[1] * offset[1] + k[2] * offset[2]) + / C::c; + + // Turn the delay into a phase shift. + for(uint k = 0; k < nFreq; ++k) + { + double shift = C::_2pi * freq[k] * delay; + factor(x, y, k) += DComplex(cos(shift), sin(shift)); + } + } + } + } + + // Normalize. + if(field.nTileElement() > 0) + { + factor /= static_cast<Double>(field.nTileElement()); + } + + return factor; + } + + Cube<double> LofarATermOld::computeITRFMap(const DirectionCoordinate &coordinates, + const IPosition &shape, + MDirection::Convert convertor) const + { + MDirection world; + Vector<double> pixel = coordinates.referencePixel(); + + Cube<double> map(3, shape[0], shape[1], 0.0); + for(pixel[1] = 0.0; pixel(1) < shape[1]; ++pixel[1]) + { + for(pixel[0] = 0.0; pixel[0] < shape[0]; ++pixel[0]) + { + // CoodinateSystem::toWorld() + // DEC range [-pi/2,pi/2] + // RA range [-pi,pi] + if(coordinates.toWorld(world, pixel)) + { + MVDirection mvITRF(convertor(world).getValue()); + map(0, pixel[0], pixel[1]) = mvITRF(0); + map(1, pixel[0], pixel[1]) = mvITRF(1); + map(2, pixel[0], pixel[1]) = mvITRF(2); + } + } + } + + return map; + } + + void LofarATermOld::initInstrument(const MeasurementSet &ms) + { + // Get station names and positions in ITRF coordinates. + ROMSAntennaColumns antenna(ms.antenna()); + ROMSObservationColumns observation(ms.observation()); + ASSERT(observation.nrow() > 0); + ASSERT(!observation.flagRow()(0)); + + // Get instrument name. + String name = observation.telescopeName()(0); + + // Get station positions. + MVPosition centroid; + vector<Station> stations(antenna.nrow()); + for(uint i = 0; i < stations.size(); ++i) + { + // Get station name and ITRF position. + MPosition position = + MPosition::Convert(antenna.positionMeas()(i), + MPosition::ITRF)(); + + // Store station information. + stations[i] = initStation(ms, i, antenna.name()(i), position); + + ASSERT(stations[i].nField() > 0); + + // Update ITRF centroid. + centroid += position.getValue(); + } + + // Get the instrument position in ITRF coordinates, or use the centroid + // of the station positions if the instrument position is unknown. + MPosition position; + if(MeasTable::Observatory(position, name)) + { + position = MPosition::Convert(position, MPosition::ITRF)(); + } + else + { + LOG_INFO("LofarATermOld initInstrument " + "Instrument position unknown; will use centroid of stations."); + ASSERT(antenna.nrow() != 0); + centroid *= 1.0 / static_cast<double>(antenna.nrow()); + position = MPosition(centroid, MPosition::ITRF); + } + + m_instrument = Instrument(name, position, stations.begin(), stations.end()); + } + + Station LofarATermOld::initStation(const MeasurementSet &ms, + uint id, + const String &name, + const MPosition &position) const + { + AlwaysAssert(ms.keywordSet().isDefined("LOFAR_ANTENNA_FIELD"), SynthesisError); + + Table tab_field(ms.keywordSet().asTable("LOFAR_ANTENNA_FIELD")); + tab_field = tab_field(tab_field.col("ANTENNA_ID") == static_cast<Int>(id)); + + const uLong nFields = tab_field.nrow(); + AlwaysAssert(nFields == 1 || nFields == 2, SynthesisError); + + ROScalarColumn<String> c_name(tab_field, "NAME"); + ROArrayQuantColumn<double> c_position(tab_field, "POSITION", + "m"); + ROArrayQuantColumn<double> c_axes(tab_field, "COORDINATE_AXES", + "m"); + ROArrayQuantColumn<double> c_tile_offset(tab_field, + "TILE_ELEMENT_OFFSET", "m"); + ROArrayQuantColumn<double> c_offset(tab_field, "ELEMENT_OFFSET", + "m"); + ROArrayColumn<Bool> c_flag(tab_field, "ELEMENT_FLAG"); + + AntennaField field[2]; + for(uLong i = 0; i < nFields; ++i) + { + // Read antenna field center. + Vector<Quantum<double> > aips_position = + c_position(i); + ASSERT(aips_position.size() == 3); + + Vector3 position = {{aips_position[0].getValue(), + aips_position[1].getValue(), + aips_position[2].getValue()}}; + + // Read antenna field coordinate axes. + Matrix<Quantum<double> > aips_axes = c_axes(i); + ASSERT(aips_axes.shape().isEqual(IPosition(2, 3, 3))); + + Vector3 P = {{aips_axes(0, 0).getValue(), aips_axes(1, 0).getValue(), + aips_axes(2, 0).getValue()}}; + Vector3 Q = {{aips_axes(0, 1).getValue(), aips_axes(1, 1).getValue(), + aips_axes(2, 1).getValue()}}; + Vector3 R = {{aips_axes(0, 2).getValue(), aips_axes(1, 2).getValue(), + aips_axes(2, 2).getValue()}}; + + // Store information as AntennaField. + field[i] = AntennaField(c_name(i), position, P, Q, R); + + if(c_name(i) != "LBA") + { + // Read tile configuration for HBA antenna fields. + Matrix<Quantum<double> > aips_offset = + c_tile_offset(i); + ASSERT(aips_offset.nrow() == 3); + + const uLong nElement = aips_offset.ncolumn(); + for(uLong j = 0; j < nElement; ++j) + { + Vector3 offset = {{aips_offset(0, j).getValue(), + aips_offset(1, j).getValue(), + aips_offset(2, j).getValue()}}; + + field[i].appendTileElement(offset); + } + } + + // Read element position offsets and flags. + Matrix<Quantum<double> > aips_offset = c_offset(i); + Matrix<Bool> aips_flag = c_flag(i); + + const uLong nElement = aips_offset.ncolumn(); + ASSERT(aips_offset.shape().isEqual(IPosition(2, 3, nElement))); + ASSERT(aips_flag.shape().isEqual(IPosition(2, 2, nElement))); + + for(uLong j = 0; j < nElement; ++j) + { + AntennaField::Element element; + element.offset[0] = aips_offset(0, j).getValue(); + element.offset[1] = aips_offset(1, j).getValue(); + element.offset[2] = aips_offset(2, j).getValue(); + element.flag[0] = aips_flag(0, j); + element.flag[1] = aips_flag(1, j); + + field[i].appendElement(element); + } + } + + return (nFields == 1 ? Station(name, position, field[0]) + : Station(name, position, field[0], field[1])); + } + + void LofarATermOld::initReferenceDirections(const MeasurementSet &ms, + uint idField) + { + // Get phase center as RA and DEC (J2000). + ROMSFieldColumns field(ms.field()); + ASSERT(field.nrow() > idField); + ASSERT(!field.flagRow()(idField)); + + m_refDelay = MDirection::Convert(field.delayDirMeas(idField), + MDirection::J2000)(); + + // By default, the tile beam reference direction is assumed to be equal + // to the station beam reference direction (for backward compatibility, + // and for non-HBA measurements). + m_refTile = m_refDelay; + + // The MeasurementSet class does not support LOFAR specific columns, so we + // use ROArrayMeasColumn to read the tile beam reference direction. + Table tab_field(ms.keywordSet().asTable("FIELD")); + static const String columnName = "LOFAR_TILE_BEAM_DIR"; + if(tab_field.tableDesc().isColumn(columnName)) + { + ROArrayMeasColumn<MDirection> c_direction(tab_field, columnName); + if(c_direction.isDefined(idField)) + { + m_refTile = MDirection::Convert(c_direction(idField)(IPosition(1, 0)), + MDirection::J2000)(); + } + } + } + + void LofarATermOld::initReferenceFreq(const MeasurementSet &ms, + uint idDataDescription) + { + // Read polarization id and spectral window id. + ROMSDataDescColumns desc(ms.dataDescription()); + ASSERT(desc.nrow() > idDataDescription); + ASSERT(!desc.flagRow()(idDataDescription)); + + const uint idWindow = desc.spectralWindowId()(idDataDescription); + + // Get spectral information. + ROMSSpWindowColumns window(ms.spectralWindow()); + ASSERT(window.nrow() > idWindow); + ASSERT(!window.flagRow()(idWindow)); + + m_refFreq = window.refFrequency()(idWindow); + } + + BeamCoeff::BeamCoeff() + : m_center(0.0), + m_width(1.0) + { + } + + void BeamCoeff::load(const Path &path) + { + // Open file. + String expandedPath = path.expandedName(); + ifstream in(expandedPath.c_str()); + cout<<"Reading "<<expandedPath<<endl; + if(!in) + { + THROW (Exception, "Unable to open beam coefficient file."); + } + + // Read file header. + String header, token0, token1, token2, token3, token4, token5; + getline(in, header); + + uLong nElements, nHarmonics, nPowerTheta, nPowerFreq; + double freqAvg, freqRange; + + istringstream iss(header); + iss >> token0 >> nElements >> token1 >> nHarmonics >> token2 >> nPowerTheta + >> token3 >> nPowerFreq >> token4 >> freqAvg >> token5 >> freqRange; + + if(!in || !iss || token0 != "d" || token1 != "k" || token2 != "pwrT" + || token3 != "pwrF" || token4 != "freqAvg" || token5 != "freqRange") + { + THROW (Exception, "Unable to parse header"); + } + + if(nElements * nHarmonics * nPowerTheta * nPowerFreq == 0) + { + THROW (Exception, "The number of coefficients should be" + " larger than zero."); + } + + ASSERT(nElements == 2); + ASSERT(in.good()); + + // Allocate coefficient matrix. + m_center = freqAvg; + m_width = freqRange; + m_coeff = Array<DComplex>(IPosition(4, 2, nPowerFreq, nPowerTheta, nHarmonics)); + + uLong nCoeff = 0; + while(in.good()) + { + // Read line from file. + String line; + getline(in, line); + + // Skip lines that contain only whitespace. + if(line.find_last_not_of(" ", String::npos) == String::npos) + { + continue; + } + + // Parse line. + uLong element, harmonic, powerTheta, powerFreq; + double re, im; + + iss.clear(); + iss.str(line); + iss >> element >> harmonic >> powerTheta >> powerFreq >> re >> im; + + if(!iss || element >= nElements || harmonic >= nHarmonics + || powerTheta >= nPowerTheta || powerFreq >= nPowerFreq) + { + THROW (Exception, "Error reading beam coefficient file."); + } + + // Store coefficient. + m_coeff(IPosition(4, element, powerFreq, powerTheta, harmonic)) = DComplex(re, im); + + // Update coefficient counter. + ++nCoeff; + } + + if(!in.eof()) + { + THROW (Exception, "Error reading beam coefficient" + " file."); + } + + if(nCoeff != nElements * nHarmonics * nPowerTheta * nPowerFreq) + { + THROW (Exception, "The number of coefficients" + " specified in the header does not match the number of coefficients" + " in the file."); + } + } + + AntennaField::AntennaField(const String &name, + const Vector3 &position, + const Vector3 &p, + const Vector3 &q, + const Vector3 &r) + : m_name(name), + m_position(position) + { + m_axes[P] = p; + m_axes[Q] = q; + m_axes[R] = r; + } + + const String &AntennaField::name() const + { + return m_name; + } + + const Vector3 &AntennaField::position() const + { + return m_position; + } + + const Vector3 &AntennaField::axis(Axis axis) const + { + return m_axes[axis]; + } + + Bool AntennaField::isHBA() const + { + return m_name != "LBA"; + } + + void AntennaField::appendTileElement(const Vector3 &offset) + { + m_tileElements.push_back(offset); + } + + void AntennaField::appendElement(const Element &element) + { + m_elements.push_back(element); + } + + Station::Station(const String &name, + const MPosition &position) + : m_name(name), + m_position(position) + { + } + + Station::Station(const String &name, + const MPosition &position, + const AntennaField &field0) + : m_name(name), + m_position(position) + { + m_fields.push_back(field0); + } + + Station::Station(const String &name, + const MPosition &position, + const AntennaField &field0, + const AntennaField &field1) + : m_name(name), + m_position(position) + { + m_fields.push_back(field0); + m_fields.push_back(field1); + } + + const String &Station::name() const + { + return m_name; + } + + const MPosition &Station::position() const + { + return m_position; + } + + bool Station::isPhasedArray() const + { + return !m_fields.empty(); + } + + uint Station::nField() const + { + return m_fields.size(); + } + + const AntennaField &Station::field(uint i) const + { + return m_fields[i]; + } + + Instrument::Instrument(const String &name, + const MPosition &position) + : m_name(name), + m_position(position) + { + } + + const String &Instrument::name() const + { + return m_name; + } + + const MPosition &Instrument::position() const + { + return m_position; + } + + uint Instrument::nStations() const + { + return m_stations.size(); + } + + const Station &Instrument::station(uint i) const + { + return m_stations[i]; + } + + const Station &Instrument::station(const String &name) const + { + map<String, uint>::const_iterator it = m_index.find(name); + if(it == m_index.end()) + { + THROW (Exception, "Unknown station: " + name); + } + + return m_stations[it->second]; + } + + void Instrument::append(const Station &station) + { + m_stations.push_back(station); + } +} // namespace LOFAR diff --git a/CEP/Imager/LofarFT/src/LofarConvolutionFunction.cc b/CEP/Imager/LofarFT/src/LofarConvolutionFunction.cc index 226fda025dea172629ae5f81ec81636f5b1a5259..087b1451e59d4bd15bd78f917ea1b47dc56ce9c0 100644 --- a/CEP/Imager/LofarFT/src/LofarConvolutionFunction.cc +++ b/CEP/Imager/LofarFT/src/LofarConvolutionFunction.cc @@ -25,12 +25,16 @@ #include <Common/LofarLogger.h> #include <Common/OpenMP.h> +#include <BBSKernel/MeasurementAIPS.h> + #include <casa/Logging/LogIO.h> #include <casa/Logging/LogOrigin.h> #include <casa/Arrays/Cube.h> #include <casa/Arrays/Matrix.h> #include <casa/Arrays/MatrixMath.h> #include <casa/Arrays/ArrayMath.h> +#include <casa/Arrays/ArrayUtil.h> +#include <casa/Arrays/ArrayIter.h> #include <ms/MeasurementSets/MeasurementSet.h> #include <measures/Measures/MDirection.h> @@ -59,6 +63,9 @@ #include <casa/sstream.h> #include <iomanip> +#include <lattices/Lattices/ArrayLattice.h> +#include <lattices/Lattices/LatticeFFT.h> + namespace LOFAR { @@ -68,13 +75,20 @@ namespace LOFAR const MeasurementSet& ms, uInt nW, double Wmax, uInt oversample, - const String& beamElementPath, Int verbose, Int maxsupport, - const String& imgName) + const String& imgName, + Bool Use_EJones, + Bool Apply_Element, + const casa::Record& parameters + ) + // , + //Int TaylorTerm, + //Double RefFreq : m_shape(shape), m_coordinates(coordinates), - m_aTerm(ms, beamElementPath), + itsParameters(parameters), + m_aTerm(ms, parameters), m_maxW(Wmax), //maximum W set by ft machine to flag the w>wmax m_nWPlanes(nW), m_oversampling(oversample), @@ -92,7 +106,6 @@ namespace LOFAR itsTimeCFpar(0), itsTimeCFfft(0), itsTimeCFcnt(0) - //Not sure how useful that is { if (itsVerbose > 0) { cout<<"LofarConvolutionFunction:shape "<<shape<<endl; @@ -101,17 +114,29 @@ namespace LOFAR // m_maxCFSupport=0; //need this parameter to stack all the CF for average PB estimate - m_wScale = WScale(m_maxW, m_nWPlanes); + //itsTaylorTerm=TaylorTerm; + //itsRefFreq=RefFreq; + //cout<<"itsTaylorTerm itsRefFreq "<<itsTaylorTerm<<" "<<itsRefFreq<<endl; + m_wScale = WScale(m_maxW, m_nWPlanes); MEpoch start = observationStartTime(ms, 0); - m_refFrequency = observationReferenceFreq(ms, 0); - + m_refFrequency = BBS::readFreqReference(ms, 0); + its_Use_EJones=Use_EJones; + its_Apply_Element=Apply_Element; + its_count_time=0; + //if(!its_Use_EJones){cout<<"Not using the beam in the calculation of the CFs...."<<endl;} if (m_oversampling%2 == 0) { // Make OverSampling an odd number m_oversampling++; } - list_freq = Vector<Double>(1, m_refFrequency); + //list_freq = Vector<Double>(1, m_refFrequency); + ROMSSpWindowColumns window(ms.spectralWindow()); + list_freq.resize(window.nrow()); + for(uInt i=0; i<window.nrow();++i){ + list_freq[i]=window.refFrequency()(i); + }; + m_nChannel = list_freq.size(); ROMSAntennaColumns antenna(ms.antenna()); m_nStations = antenna.nrow(); @@ -131,6 +156,35 @@ namespace LOFAR // Precalculate the Wtwerm fft for all w-planes. store_all_W_images(); + itsFilledVectorMasks=false; + + // Build the cutted spheroidal for the element beam image + Double pixelSize = abs(m_coordinates.increment()[0]); + Double imageDiameter = pixelSize * m_shape(0); + DirectionCoordinate coordinate = m_coordinates; + Double aPixelAngSize = min(m_pixelSizeSpheroidal, + estimateAResolution(m_shape, m_coordinates)); + //Double aPixelAngSize = estimateAResolution(m_shape, m_coordinates, 30); + Int nPixelsConv = imageDiameter / aPixelAngSize; + Matrix<Complex> spheroid_cut_element(IPosition(2,nPixelsConv,nPixelsConv),1.); + taper(spheroid_cut_element); + //Matrix<Complex> spheroid_cut_element_fft=give_normalized_fft_lapack(spheroid_cut_element, true); + normalized_fft(spheroid_cut_element, true); + spheroid_cut_element_fft=spheroid_cut_element; + Matrix<Complex> spheroid_cut_element_padfft(zero_padding(spheroid_cut_element_fft, m_shape(0))); + //Matrix<Complex> spheroid_cut_element_padfft_fft=give_normalized_fft_lapack (spheroid_cut_element_padfft, false); + normalized_fft (spheroid_cut_element_padfft, false); + Matrix<Complex> spheroid_cut_element_padfft_fft(spheroid_cut_element_padfft); + float threshold = 1.e-6; + for (Int jj=0; jj<m_shape[1]; ++jj) { + for (Int ii=0; ii<m_shape[0]; ++ii) { + Float absVal = abs(spheroid_cut_element_padfft_fft(ii,jj)); + spheroid_cut_element_padfft_fft(ii,jj) = std::max (absVal, threshold); + } + } + Spheroid_cut_im_element.reference (real(spheroid_cut_element_padfft_fft)); + store(m_coordinates,Spheroid_cut_im_element,"Spheroid_cut_im_element.img"); + } // ~LofarConvolutionFunction () @@ -140,6 +194,7 @@ namespace LOFAR // Precalculate all W-terms in the fourier domain void LofarConvolutionFunction::store_all_W_images() { + logIO()<<"LofarConvolutionFunction::store_all_W_images() "<<"Computing the Wterms..."<< LogIO::POST;//<<endl; PrecTimer wTimer; wTimer.start(); Double pixelSize = abs(m_coordinates.increment()[0]); @@ -166,7 +221,7 @@ namespace LOFAR if (itsVerbose > 0) { cout<<"Number of pixel in the "<<i<<"-wplane: "<<nPixelsConv <<" (w="<<w<<")"<<endl; - } + } if (nPixelsConv > itsMaxSupport) { nPixelsConv = itsMaxSupport; } @@ -194,8 +249,17 @@ namespace LOFAR #pragma omp atomic itsTimeWpar += ptime; } // end omp parallel + + its_MaxWSupport=0; + for (uInt i=0; i<m_nWPlanes; ++i) { + if(m_WplanesStore[i].shape()[0]>its_MaxWSupport){its_MaxWSupport=m_WplanesStore[i].shape()[0];}; + } + + + wTimer.stop(); itsTimeW = wTimer.getReal(); + logIO()<<"LofarConvolutionFunction::store_all_W_images() "<<"... Done!"<< LogIO::POST;//<<endl; } @@ -204,6 +268,9 @@ namespace LOFAR // Put it in a map object with a (double time) key. void LofarConvolutionFunction::computeAterm (Double time) { + //logIO()<<"LofarConvolutionFunction::computeAterm "<<"Computing the Aterms for t="<<time<<", and maximum Wupport="<<its_MaxWSupport<< LogIO::POST;//<<endl; + PrecTimer timerCyril; + timerCyril.start(); if (m_AtermStore.find(time) != m_AtermStore.end()) { // Already done. return; @@ -215,73 +282,173 @@ namespace LOFAR // Try to avoid making copies when inserting elements in vector or map. // Therefore first create the elements and resize them. m_AtermStore[time] = vector< vector< Cube<Complex> > >(); + m_AtermStore_element[time] = vector< vector< Cube<Complex> > >(); + m_AtermStore_station[time] = vector< vector< Cube<Complex> > >(); vector< vector< Cube<Complex> > >& aTermList = m_AtermStore[time]; + vector< vector< Cube<Complex> > >& aTermList_element = m_AtermStore_element[time]; + vector< vector< Cube<Complex> > >& aTermList_station = m_AtermStore_station[time]; // Calculate the A-term and fill the vector for all stations. aTermList.resize (m_nStations); + aTermList_element.resize (m_nStations); + aTermList_station.resize (m_nStations); ///#pragma omp parallel { // Thread private variables. PrecTimer timerFFT; PrecTimer timerPar; + ///#pragma omp for + DirectionCoordinate coordinate = m_coordinates; + Double aPixelAngSize = min(m_pixelSizeSpheroidal, estimateAResolution(m_shape, m_coordinates)); + Int nPixelsConv = imageDiameter / aPixelAngSize; + if (nPixelsConv > itsMaxSupport) { + nPixelsConv = itsMaxSupport; + } + // Make odd and optimal. + nPixelsConv = FFTCMatrix::optimalOddFFTSize (nPixelsConv); + aPixelAngSize = imageDiameter / nPixelsConv; + IPosition shape(2, nPixelsConv, nPixelsConv); + Vector<Double> increment_old(coordinate.increment()); + Vector<Double> increment(2); + increment[0] = aPixelAngSize*sign(increment_old[0]); + increment[1] = aPixelAngSize*sign(increment_old[1]); + coordinate.setIncrement(increment); + Vector<Double> refpix(2, 0.5*(nPixelsConv-1)); + coordinate.setReferencePixel(refpix); + + DirectionCoordinate coordinate_element = m_coordinates; + //Double aPixelAngSize_element = estimateAResolution(m_shape, m_coordinates, 30.); + Double aPixelAngSize_element = min(m_pixelSizeSpheroidal, estimateAResolution(m_shape, m_coordinates)); + Int nPixelsConv_element = imageDiameter / aPixelAngSize_element; + //cout<<"Element_beam size:"<<"1 "<<nPixelsConv_element<<", 2 "<<aPixelAngSize_element<<endl; + nPixelsConv_element = FFTCMatrix::optimalOddFFTSize (nPixelsConv_element); + aPixelAngSize_element = imageDiameter / nPixelsConv_element; + //cout<<"Element_beam size:"<<"1 "<<nPixelsConv_element<<", 2 "<<aPixelAngSize_element<<endl; + IPosition shape_element(2, nPixelsConv_element, nPixelsConv_element); + Vector<Double> increment_element(2); + increment_element[0] = aPixelAngSize_element*sign(increment_old[0]); + increment_element[1] = aPixelAngSize_element*sign(increment_old[1]); + coordinate_element.setIncrement(increment_element); + Vector<Double> refpix_element(2, 0.5*(nPixelsConv_element-1)); + coordinate_element.setReferencePixel(refpix_element); + + //hier is het + + m_aTerm.setDirection(coordinate, shape); + + MEpoch binEpoch; + binEpoch.set(Quantity(time, "s")); + + m_aTerm.setEpoch(binEpoch); +// LofarATerm::ITRFDirectionMap dirMap = m_aTerm.makeDirectionMap(coordinate, shape, binEpoch); + for (uInt i=0; i<m_nStations; ++i) { timerPar.start(); - DirectionCoordinate coordinate = m_coordinates; - Double aPixelAngSize = min(m_pixelSizeSpheroidal, - estimateAResolution(m_shape, m_coordinates)); - Int nPixelsConv = imageDiameter / aPixelAngSize; - if (nPixelsConv > itsMaxSupport) { - nPixelsConv = itsMaxSupport; - } - // Make odd and optimal. - nPixelsConv = FFTCMatrix::optimalOddFFTSize (nPixelsConv); - aPixelAngSize = imageDiameter / nPixelsConv; - if (itsVerbose > 0) { - cout.precision(20); - cout<<"Number of pixel in the Aplane of "<<i<<": "<<nPixelsConv - <<", time="<<fixed<<time<<endl; - } - IPosition shape(2, nPixelsConv, nPixelsConv); - Vector<Double> increment_old(coordinate.increment()); - Vector<Double> increment(2); - increment[0] = aPixelAngSize*sign(increment_old[0]); - increment[1] = aPixelAngSize*sign(increment_old[1]); - coordinate.setIncrement(increment); - Vector<Double> refpix(2, 0.5*(nPixelsConv-1)); - coordinate.setReferencePixel(refpix); //====================================== - // Disable the beam + // Separated element and station //====================================== - //Cube<Complex> aterm_cube(IPosition(3,nPixels_Conv,nPixels_Conv,4),1.); - //for (uInt iiii=0;iiii<nPixels_Conv;++iiii) { - // for (uInt iiiii=0;iiiii<nPixels_Conv;++iiiii) { - // aterm_cube(iiii,iiiii,1)=0.; - // aterm_cube(iiii,iiiii,2)=0.; - // } - //} - //vector< Cube<Complex> > aTermA; - //aTermA.push_back(aterm_cube); + vector< Cube<Complex> > aTermA_element; + vector< Cube<Complex> > aTermA_array; + + vector< Matrix<Complex> > aTermA_array_plane(m_aTerm.evaluateArrayFactor(i, 0, list_freq , list_freq , true)); + aTermA_array.resize(m_nChannel); + for (uInt ch=0; ch<m_nChannel; ++ch) { + aTermA_array[ch].resize(IPosition(3,shape[0],shape[0],4)); + aTermA_array[ch]=0.; + } + for (uInt ch=0; ch<m_nChannel; ++ch) { + Matrix<Complex> plane(aTermA_array[ch].xyPlane(0)); + plane=aTermA_array_plane[ch].copy(); + Matrix<Complex> plane2(aTermA_array[ch].xyPlane(3)); + plane2=aTermA_array_plane[ch].copy(); + } + + aTermA_element=m_aTerm.evaluateElementResponse(i, 0, list_freq, true); + + //store(coordinate,aTermA_element[0],"aTermA_element."+String::toString(i)+".img"); + //store(coordinate,aTermA_array[0],"aTermA_array."+String::toString(i)+".img"); + + //vector< Cube<Complex> > aTermA = m_aTerm.evaluate(i, dirMap, list_freq, list_freq, false); + //store(coordinate,aTermA[0],"aTermA."+String::toString(i)+".orig.img"); + +// aTermAtmp = m_aTerm.evaluateSeparated(shape_element, +// coordinate_element, +// i, binEpoch, +// list_freq, true); +// aTermA_element=aTermAtmp[0]; +// aTermAtmp2 = m_aTerm.evaluateSeparated(shape, +// coordinate, +// i, binEpoch, +// list_freq, true); +// aTermA_station=aTermAtmp2[1]; + //store(aTermA_element[0],"aTermA_element.img"); + //store(aTermA_station[0],"aTermA_station.img"); + + //vector< Cube<Complex> > aTermA; + // if(!its_Use_EJones){ + + // for (uInt ch=0; ch<m_nChannel; ++ch) { + // Matrix<Complex> slice0=aTermA_element[ch].xyPlane(0); + // slice0=1.; + // Matrix<Complex> slice1=aTermA_element[ch].xyPlane(1); + // slice1=0.; + // Matrix<Complex> slice2=aTermA_element[ch].xyPlane(2); + // slice2=0.; + // Matrix<Complex> slice3=aTermA_element[ch].xyPlane(3); + // slice3=1.; + // } + // for (uInt ch=0; ch<m_nChannel; ++ch) { + // Matrix<Complex> slice0=aTermA_array[ch].xyPlane(0); + // slice0=1.; + // Matrix<Complex> slice1=aTermA_array[ch].xyPlane(1); + // slice1=0.; + // Matrix<Complex> slice2=aTermA_array[ch].xyPlane(2); + // slice2=0.; + // Matrix<Complex> slice3=aTermA_array[ch].xyPlane(3); + // slice3=1.; + // } + + // } + // else{ //====================================== // Enable the beam //====================================== - MEpoch binEpoch; - binEpoch.set(Quantity(time, "s")); - vector< Cube<Complex> > aTermA = m_aTerm.evaluate(shape, - coordinate, - i, binEpoch, - list_freq, true); +// aTermA = m_aTerm.evaluate(shape, +// coordinate, +// i, binEpoch, +// list_freq, true); + // } + + +// // JVZ: Direction map should be computed only once for all stations. +// // However, this requires the DirectionCoordinate instance and shape to +// // be exactly equal for all stations. + +// vector< Cube<Complex> > aTermA = m_aTerm.evaluate(i, dirMap, list_freq, +// list_freq, true); + // Compute the fft on the beam + vector< Cube<Complex> > aTermAs; + aTermAs.resize(m_nChannel); + aTermAs[0].resize(IPosition(3,its_MaxWSupport,its_MaxWSupport,4)); for (uInt ch=0; ch<m_nChannel; ++ch) { for (uInt pol=0; pol<4; ++pol) { - Matrix<Complex> plane (aTermA[ch].xyPlane(pol)); - AlwaysAssert (plane.contiguousStorage(), AipsError); - normalized_fft (timerFFT, plane); + + Matrix<Complex> plane1 (aTermA_array[ch].xyPlane(pol)); + //Matrix< Complex > plane0int = LinearInterpol2(plane1,200.); + normalized_fft (timerFFT, plane1); + + } } + // store(coordinate,aTermA_array[0],"aTermA_array.fft."+String::toString(i)+".img"); + // Note that push_back uses the copy constructor, so for the Cubes // in the vector the copy constructor is called too (which is cheap). - aTermList[i] = aTermA; + //aTermList[i] = aTermA; + aTermList_element[i] = aTermA_element; + aTermList_station[i] = aTermA_array; timerPar.stop(); } // end omp for // Update the timing info. @@ -297,8 +464,424 @@ namespace LOFAR } // end omp parallel aTimer.stop(); itsTimeA = aTimer.getReal(); + //logIO()<<"LofarConvolutionFunction::computeAterm "<<"...Done!"<< LogIO::POST;//<<endl; + timerCyril.stop(); + //cout.precision(20); + //cout<<"For time: "<<time<<endl; + //assert(false); + //timerCyril.show(cout,"LofarConvolutionFunction::computeAterm"); } + + Array<Complex> LofarConvolutionFunction::ApplyElementBeam(Array<Complex> input_grid, Double time, uInt spw, const Matrix<bool>& Mask_Mueller_in, bool degridding_step) + { + + map<Double, vector< vector< Cube<Complex> > > >::const_iterator aiter_element = m_AtermStore_element.find(time); + AlwaysAssert (aiter_element!=m_AtermStore_element.end(), AipsError); + const vector< vector< Cube<Complex> > >& aterm_element = aiter_element->second; + + + + vector< vector< IPosition > > Mueller_Coordinates; + Mueller_Coordinates.resize(4); + for(uInt i=0;i<4;++i){ + Mueller_Coordinates[i].resize(4); + IPosition pos(2,2,1); + for(uInt j=0;j<4;++j){ + Mueller_Coordinates[i][j]=pos; + } + } + + + uInt ind0; + uInt ind1; + uInt ii = 0; + IPosition cfShape; + Bool allElem = True; + for (uInt row0=0; row0<=1; ++row0) { + for (uInt col0=0; col0<=1; ++col0) { + vector < Matrix<Complex> > Row(4); + vector < Matrix<Complex> > Row_non_padded(4); + uInt jj = 0; + for (uInt row1=0; row1<=1; ++row1) { + for (uInt col1=0; col1<=1; ++col1) { + // This Mueller ordering is for polarisation given as XX,XY,YX YY + ind0 = row0 + 2*row1; + ind1 = col0 + 2*col1; + IPosition pos(2,2,1); + pos[0]=ind0; + pos[1]=ind1; + Mueller_Coordinates[ii][jj]=pos; + ++jj; + } + } + ++ii; + } + } + + + + vector< vector< Matrix<Complex> > > vec_element_product; + vec_element_product.resize(4); + vector< vector< Matrix<Complex> > > vec_plane_product; + vec_plane_product.resize(4); + if (!degridding_step) { + for (uInt i=0; i<4; ++i) { + for (uInt j=i; j<4; ++j) { + IPosition pos_tmp(Mueller_Coordinates[i][j]); + Mueller_Coordinates[i][j]=Mueller_Coordinates[j][i]; + Mueller_Coordinates[j][i]=pos_tmp; + } + } + } + + Int nx(input_grid.shape()[0]); + Int ny(input_grid.shape()[1]); + Int npol(input_grid.shape()[2]); + + Cube<Complex> aTermA(aterm_element[0][spw].copy()); + Array<Complex> grid_out(input_grid.shape(),0.); + + + if(!degridding_step){ + + logIO() <<"LofarConvolutionFunction::ApplyElementBeam "<<"FFT of the gridded data for this timeslot" << LogIO::POST;//<<endl; + + for(uInt channel=0;channel< input_grid.shape()[3];++channel){ + { +#pragma omp parallel for + for(uInt jj=0;jj<npol;++jj){ + //cout<<"jj="<<jj<<endl; + Matrix<Complex> plane_array_in = input_grid(Slicer(IPosition(4, 0, 0, jj, 0), + IPosition(4, nx, nx, 1, 1))).nonDegenerate(); + //store(plane_array_in,"plane_array_in"+String::toString(jj)+".img"); + normalized_fft (plane_array_in, false); + //store(plane_array_in,"plane_array_in"+String::toString(jj)+".img"); + } + } + } + } + + + + //cout<<"LofarConvolutionFunction::ApplyElementBeam "<<"Calculate element beams"<<endl; + logIO()<<"LofarConvolutionFunction::ApplyElementBeam "<<"Calculate element beams"<< LogIO::POST;//<<endl; + for(uInt ii=0;ii<4;++ii){ + vec_element_product[ii].resize(4); + vec_plane_product[ii].resize(4); + for(uInt jj=0;jj<4;++jj){ + if(Mask_Mueller_in(ii,jj)==true){ + vec_element_product[ii][jj].resize(IPosition(2, nx, nx)); + vec_plane_product[ii][jj].resize(aTermA.xyPlane(0).shape()); + vec_plane_product[ii][jj]=aTermA.xyPlane((Mueller_Coordinates[ii][jj])[0]) * aTermA.xyPlane((Mueller_Coordinates[ii][jj])[1]); + taper(vec_plane_product[ii][jj]); + if(!degridding_step){vec_plane_product[ii][jj]=conj(vec_plane_product[ii][jj]);}; + } + //store(vec_plane_product[ii][jj],"vec_plane_product"+String::toString(ii)+String::toString(jj)+".img"); + } + } + + + logIO()<<"LofarConvolutionFunction::ApplyElementBeam "<<"FFT - Zero Pad - IFFT"<< LogIO::POST;//<<endl; + //#pragma omp parallel + { + Int ii; + Int jj; +#pragma omp parallel for private(ii,jj) + for(uInt iii=0;iii<16;++iii){ + jj=floor(float(iii)/4.); + ii=floor((float(iii)/4.-jj)*4.); + //cout<<"iii"<<iii<<" "<<ii<<" "<<jj<<endl; + if(Mask_Mueller_in(ii,jj)==true){ + normalized_fft (vec_plane_product[ii][jj], true); + vec_element_product[ii][jj]=zero_padding(vec_plane_product[ii][jj], nx); + normalized_fft (vec_element_product[ii][jj], false); + //store(vec_element_product[ii][jj],"vec_element_product"+String::toString(ii)+String::toString(jj)+".img"); + } + + } + } + + // assert(false); + + + //#pragma omp parallel + if(npol==4) + { + logIO()<<"LofarConvolutionFunction::ApplyElementBeam "<<"Multiply element and data in the image plane"<< LogIO::POST;//<<endl; + int y=0; + uInt ii=0; + uInt jj=0; +#pragma omp parallel for private(y,ii,jj) + for(int x=0 ; x<nx ; ++x){ + //cout<<"x="<<x<<endl; + for(y=0 ; y<nx ; ++y){ + + for(ii=0;ii<4;++ii){ + for(jj=0;jj<4;++jj){ + if(Mask_Mueller_in(ii,jj)==true){ + grid_out(IPosition(4,x,y,jj,0)) += vec_element_product[ii][jj](x,y) * input_grid(IPosition(4,x,y,ii,0))/Spheroid_cut_im_element(x,y); + + } + } + } + } + } + } + + if(npol==1) + { + logIO()<<"LofarConvolutionFunction::ApplyElementBeam "<<"Multiply element and data in the image plane"<< LogIO::POST;//<<endl; + int y=0; + uInt ii=0; + uInt jj=0; +#pragma omp parallel for private(y,ii,jj) + for(int x=0 ; x<nx ; ++x){ + //cout<<"x="<<x<<endl; + for(y=0 ; y<nx ; ++y){ + + for(ii=0;ii<4;++ii){ + for(jj=0;jj<4;++jj){ + if(Mask_Mueller_in(ii,jj)==true){ + grid_out(IPosition(4,x,y,0,0)) += vec_element_product[ii][jj](x,y) * input_grid(IPosition(4,x,y,0,0))/(2.*Spheroid_cut_im_element(x,y)); + } + } + } + } + } + + } + + logIO()<<"LofarConvolutionFunction::ApplyElementBeam "<<"Shapes InputGrid:"<<input_grid.shape()<<", Shapes OutputGrid:"<< LogIO::POST;//<<grid_out.shape()<<endl; + + + return grid_out; + + } + + //================================================================== + //================================================================== + Array<Complex> LofarConvolutionFunction::ApplyElementBeam2(Array<Complex>& input_grid, Double time, uInt spw, const Matrix<bool>& Mask_Mueller_in2, bool degridding_step, Int UsedMask) + { + + Matrix<bool> Mask_Mueller_in(Mask_Mueller_in2.copy()); + for(uInt i=0;i<4;++i){ + for(uInt j=0;j<4;++j){ + Mask_Mueller_in(i,j)=true; + } + } + map<Double, vector< vector< Cube<Complex> > > >::const_iterator aiter_element = m_AtermStore_element.find(time); + AlwaysAssert (aiter_element!=m_AtermStore_element.end(), AipsError); + const vector< vector< Cube<Complex> > >& aterm_element = aiter_element->second; + + + + vector< vector< IPosition > > Mueller_Coordinates; + Mueller_Coordinates.resize(4); + for(uInt i=0;i<4;++i){ + Mueller_Coordinates[i].resize(4); + IPosition pos(2,2,1); + for(uInt j=0;j<4;++j){ + Mueller_Coordinates[i][j]=pos; + } + } + + { + uInt ind0; + uInt ind1; + uInt ii = 0; + IPosition cfShape; + Bool allElem = True; + for (uInt row0=0; row0<=1; ++row0) { + for (uInt col0=0; col0<=1; ++col0) { + vector < Matrix<Complex> > Row(4); + vector < Matrix<Complex> > Row_non_padded(4); + uInt jj = 0; + for (uInt row1=0; row1<=1; ++row1) { + for (uInt col1=0; col1<=1; ++col1) { + // This Mueller ordering is for polarisation given as XX,XY,YX YY + ind0 = row0 + 2*row1; + ind1 = col0 + 2*col1; + //ind0 = 2.*row0 + row1; + //ind1 = 2.*col0 + col1; + IPosition pos(2,2,1); + pos[0]=ind0; + pos[1]=ind1; + Mueller_Coordinates[ii][jj]=pos; + ++jj; + } + } + ++ii; + } + } + } + + if (!degridding_step) { + for (uInt i=0; i<4; ++i) { + for (uInt j=i; j<4; ++j) { + IPosition pos_tmp(Mueller_Coordinates[i][j]); + Mueller_Coordinates[i][j]=Mueller_Coordinates[j][i]; + Mueller_Coordinates[j][i]=pos_tmp; + Bool bool_tmp(Mask_Mueller_in(i,j)); + Mask_Mueller_in(i,j)=Mask_Mueller_in(j,i); + Mask_Mueller_in(i,j)=bool_tmp; + } + } + } + + Cube<Complex> aTermA(aterm_element[0][spw].copy()); + Array<Complex> grid_out(input_grid.shape(),0.); + Int nx(input_grid.shape()[0]); + Int ny(input_grid.shape()[1]); + Int npol(input_grid.shape()[2]); + + vector< vector< Matrix<Complex> > > vec_plane_product; + vec_plane_product.resize(4); + + + //logIO()<<"LofarConvolutionFunction::ApplyElementBeam "<<"Calculate element beams"<< LogIO::POST;//<<endl; + for(uInt ii=0;ii<4;++ii){ + vec_plane_product[ii].resize(4); + for(uInt jj=0;jj<4;++jj){ + if(Mask_Mueller_in(ii,jj)==true){ + vec_plane_product[ii][jj].resize(aTermA.xyPlane(0).shape()); + vec_plane_product[ii][jj]=aTermA.xyPlane((Mueller_Coordinates[ii][jj])[0]) * conj(aTermA.xyPlane((Mueller_Coordinates[ii][jj])[1])); + taper(vec_plane_product[ii][jj]); + if(!degridding_step){vec_plane_product[ii][jj]=conj(vec_plane_product[ii][jj]);}; + //store(vec_plane_product[ii][jj],"vec_plane_product."+String::toString(ii)+"."+String::toString(jj)+".img"); + normalized_fft(vec_plane_product[ii][jj],true); + } + } + } + + //assert(false); + //#pragma omp parallel + if(GridsMueller.size()==0){ + //logIO()<<"LofarConvolutionFunction::ApplyElementBeam "<<"...Declare GridsMueller Matrix"<< LogIO::POST;//<<endl; + GridsMueller.resize(4); + for(uInt ii=0;ii<4;++ii){ + GridsMueller[ii].resize(4); + for(uInt jj=0;jj<4;++jj){ + if(Mask_Mueller_in(ii,jj)==true){ + GridsMueller[ii][jj].resize(IPosition(2,nx,nx)); + GridsMueller[ii][jj]=Complex(); + } + } + } + } else { + for(uInt ii=0;ii<4;++ii){ + for(uInt jj=0;jj<4;++jj){ + if(Mask_Mueller_in(ii,jj)==true){ + GridsMueller[ii][jj]=Complex(); + } + } + } + } + + //logIO()<<"LofarConvolutionFunction::ApplyElementBeam "<<"Convolve..."<< LogIO::POST;//<<endl; + { + Int ii; + Int jj; +#pragma omp parallel for private(ii,jj) + for(uInt iii=0;iii<16;++iii){ + ii=floor(float(iii)/4.); + jj=floor((float(iii)/4.-ii)*4.); + //cout<<"iii"<<iii<<" "<<ii<<" "<<jj<<" M="<<Mask_Mueller_in(jj,ii)<<endl; + if(Mask_Mueller_in(ii,jj)==true){ + Matrix<Complex> ConvFunc(vec_plane_product[ii][jj]); + + //ConvolveGerArray(input_grid, ii, GridsMueller[ii][jj], ConvFunc); + + if(npol==1){ + if(!(UsedMask>-1)){ + ConvolveGerArray(input_grid, 0, GridsMueller[ii][jj], ConvFunc); + } else { + ConvolveGerArrayMask(input_grid, 0, GridsMueller[ii][jj], ConvFunc, UsedMask); + } + } + if(npol==4){ + if(!(UsedMask>-1)){ + ConvolveGerArray(input_grid, ii, GridsMueller[ii][jj], ConvFunc); + } else { + ConvolveGerArrayMask(input_grid, ii, GridsMueller[ii][jj], ConvFunc, UsedMask); + } + } + + + } + + } + } + + //logIO()<<"LofarConvolutionFunction::ApplyElementBeam "<<"Convolve ... Done!"<< LogIO::POST;//<<endl; + // Int ii; + // Int jj; + // for(uInt iii=0;iii<16;++iii){ + // jj=floor(float(iii)/4.); + // ii=floor((float(iii)/4.-jj)*4.); + // //cout<<"iii"<<iii<<" "<<ii<<" "<<jj<<endl; + // if(Mask_Mueller_in(ii,jj)==true){ + // store(GridsMueller[ii][jj],"grid_out"+String::toString(ii)+String::toString(jj)+".img"); + // } + // } + + + + + + // #pragma omp parallel + if(npol==4) + { + int y=0; + uInt ii=0; + uInt jj=0; + #pragma omp parallel for private(y,ii,jj) + for(int x=0 ; x<nx ; ++x){ + //cout<<"x="<<x<<endl; + for(y=0 ; y<nx ; ++y){ + + for(ii=0;ii<4;++ii){ + for(jj=0;jj<4;++jj){ + //if(Mask_Mueller_in(ii,jj)==true){ + grid_out(IPosition(4,x,y,jj,0)) += GridsMueller[ii][jj](x,y) ;///Spheroid_cut_im_element(x,y); + + //} + } + } + } + } + } + + + if(npol==1) + { + int y=0; + uInt ii=0; + #pragma omp parallel for private(y,ii) + for(int x=0 ; x<nx ; ++x){ + for(y=0 ; y<nx ; ++y){ + for(ii=0;ii<4;++ii){ + grid_out(IPosition(4,x,y,0,0)) += 0.5*(GridsMueller[0][ii](x,y) + GridsMueller[3][ii](x,y));///Spheroid_cut_im_element(x,y); + + } + } + } + } + + + + //logIO()<<"LofarConvolutionFunction::ApplyElementBeam "<<"Shapes InputGrid:"<<input_grid.shape()<<", Shapes OutputGrid:"<< LogIO::POST;//<<grid_out.shape()<<endl; + + + return grid_out; + + } + + //================================================================== + //================================================================== + + + //================================================ // Compute the convolution function for all channel, for the polarisations specified in the Mueller_mask matrix // Also specify weither to compute the Mueller matrix for the forward or the backward step. A dirty way to calculate @@ -307,34 +890,52 @@ namespace LOFAR LofarCFStore LofarConvolutionFunction::makeConvolutionFunction (uInt stationA, uInt stationB, Double time, Double w, - const Matrix<bool>& Mask_Mueller, bool degridding_step, + const Matrix<bool>& Mask_Mueller_in, bool degridding_step, double Append_average_PB_CF, Matrix<Complex>& Stack_PB_CF, - double& sum_weight_square) + double& sum_weight_square, uInt spw, Int TaylorTerm, double RefFreq) { // Initialize timers. PrecTimer timerFFT; PrecTimer timerPar; + PrecTimer timerCyril; timerPar.start(); + Matrix<bool> Mask_Mueller(IPosition(2,4,4),false); + Mask_Mueller(0,0)=true; + // Stack_PB_CF should be called Sum_PB_CF (it is a sum, no stack). CountedPtr<CFTypeVec> res (new vector< vector< vector < Matrix<Complex> > > >()); CFTypeVec& result = *res; vector< vector< vector < Matrix<Complex> > > > result_non_padded; + // Stack the convolution function if averagepb.img don't exist - Matrix<Complex> Stack_PB_CF_fft(IPosition(2,m_shape(0),m_shape(0)),0.); + //Matrix<Complex> Stack_PB_CF_fft(IPosition(2,m_shape(0),m_shape(0)),0.); Bool Stack = (Append_average_PB_CF != 0.); + + // If the beam is not in memory, compute it - - map<Double, vector< vector< Cube<Complex> > > >::const_iterator aiter = - m_AtermStore.find(time); - AlwaysAssert (aiter!=m_AtermStore.end(), AipsError); - const vector< vector< Cube<Complex> > >& aterm = aiter->second; + + // map<Double, vector< vector< Cube<Complex> > > >::const_iterator aiter = + // m_AtermStore.find(time); + // AlwaysAssert (aiter!=m_AtermStore.end(), AipsError); + // const vector< vector< Cube<Complex> > >& aterm = aiter->second; + + + map<Double, vector< vector< Cube<Complex> > > >::const_iterator aiter_station = + m_AtermStore_station.find(time); + AlwaysAssert (aiter_station!=m_AtermStore_station.end(), AipsError); + const vector< vector< Cube<Complex> > >& aterm_station = aiter_station->second; + + + + /// if(m_AtermStore.find(time)==m_AtermStore.end()){computeAterm(time);} // Load the Wterm - uInt w_index = m_wScale.plane(w); + double ratio_freqs=list_freq[0]/list_freq[spw]; + uInt w_index = m_wScale.plane(w*ratio_freqs); Matrix<Complex> wTerm; wTerm = m_WplanesStore[w_index]; Int Npix_out = 0; @@ -353,17 +954,36 @@ namespace LOFAR wTerm.reference (conj(wTerm)); } - for (uInt ch=0; ch<m_nChannel; ++ch) { + uInt ch(spw); + //for (uInt ch=0; ch<m_nChannel; ++ch) { // Load the Aterm - const Cube<Complex>& aTermA(aterm[stationA][ch]); - const Cube<Complex>& aTermB(aterm[stationB][ch]); + //const Cube<Complex> aTermA(aterm_station[stationA][ch].copy()); + Cube<Complex> aTermA(aterm_station[stationA][ch].copy()); + + + //const Cube<Complex>& aTermB(aterm_station[stationB][ch]); + Cube<Complex> aTermB(aterm_station[stationB][ch].copy()); + //============================== + //============================== + // Cyr: MFS + //============================== + //============================== + // if( TaylorTerm > 0 ) + // { + // Float freq=0.0,mulfactor=1.0; + // freq = list_freq[ch]; + // mulfactor = ((freq-RefFreq)/RefFreq); + // //cout<<"mulfactor "<<mulfactor<<endl; + // Cube<Complex> slice(aTermA); + // slice *= pow(mulfactor,TaylorTerm);//mulfactor; + // } + //============================== + //============================== // Determine maximum support of A, W, and Spheroidal function for zero padding Npix_out = std::max(std::max(aTermA.shape()[0], aTermB.shape()[0]), std::max(wTerm.shape()[0], Spheroid_cut.shape()[0])); - if (itsVerbose > 0) { - cout<<"Number of pixel in the final conv function for baseline ["<< stationA<<", "<<stationB<<"] = "<<Npix_out - <<" "<<aTermA.shape()[0]<<" "<<aTermB.shape()[0]<<" "<<wTerm.shape()[0]<<endl; - } + + //cout << "CF Shapes, Wterm:" << wTerm.shape()[0] << ", Beam " << aTermA.shape()[0] << ", Spheroid: " << Spheroid_cut.shape()[0] << endl; // Zero pad to make the image planes of the A1, A2, and W term have the same resolution in the image plane Matrix<Complex> Spheroid_cut_paddedf(zero_padding(Spheroid_cut,Npix_out)); @@ -378,10 +998,9 @@ namespace LOFAR cout << "fft shapes " << wTerm_paddedf.shape() << ' ' << Spheroid_cut_paddedf.shape() << ' ' << aTermA_padded.shape() << ' ' << aTermB_padded.shape() << endl; } + + for (uInt i=0; i<4; ++i) { - //Matrix<Complex> planeAf(aTermA_padded.xyPlane(i)); - //Matrix<Complex> planeBf(aTermB_padded.xyPlane(i)); - // AlwaysAssert(planeAf.contiguousStorage(), AipsError); // Make a matrix referencing the data in the cube's plane. Matrix<Complex> planeAf(aTermA_padded.xyPlane(i)); Matrix<Complex> planeBf(aTermB_padded.xyPlane(i)); @@ -390,30 +1009,62 @@ namespace LOFAR normalized_fft (timerFFT, planeBf, false); } + //if (itsVerbose > 0) { + // if((stationA==3)&( stationB==0)){ + // cout<<"Number of pixel in the final conv function for baseline ["<< stationA<<", "<<stationB<<"] = "<<Npix_out + // <<" "<<aTermA.shape()[0]<<" "<<aTermB.shape()[0]<<" "<<wTerm.shape()[0]<<endl; + // store(aTermA,"aTermAfft."+String::toString(its_count_time)+".img"); + // store(aTermB,"aTermBfft."+String::toString(its_count_time)+".img"); + // store(aTermA_padded,"aTermAfft."+String::toString(its_count_time)+".fft.img"); + // store(aTermB_padded,"aTermBfft."+String::toString(its_count_time)+".fft.img"); + // its_count_time+=1; + // //assert(false); + // } // Create the vectors of Matrices giving the convolution functions // for each Mueller element. vector< vector < Matrix<Complex> > > Kron_Product; Kron_Product.reserve(4); - // Something I still don't completely understand: for the average PB calculation. + // timerCyril.reset(); + // timerCyril.start(); + // //TEST!!!! + // Matrix<Complex> Spheroid_cut_paddedf(LinearInterpol(Spheroid_cut,Npix_out)); + // Matrix<Complex> wTerm_paddedf(LinearInterpol(wTerm, Npix_out)); + // Cube<Complex> aTermA_padded(IPosition(3,Npix_out,Npix_out,4),0.); + // Cube<Complex> aTermB_padded(IPosition(3,Npix_out,Npix_out,4),0.); + // for (uInt i=0; i<4; ++i) { + // Matrix<Complex> planeAf=aTermA_padded.xyPlane(i); + // Matrix<Complex> planeAf=aTermA_padded.xyPlane(i); + // planeAf=LinearInterpol(aTermA.xyPlane(i), Npix_out); + // planeBf=LinearInterpol(aTermA.xyPlane(i), Npix_out); + // } + // timerCyril.stop(); + // timerCyril.show(cout,"linear"); + + + + // Something I still don't completely understand: for the average PB calculation. // The convolution functions padded with a higher value than the minimum one give a // better result in the end. If you try Npix_out2=Npix_out, then the average PB shows // structure like aliasing, producing high values in the devided disrty map... This // is likely to be due to the way fft works?... - // FIX: I now do the average of the PB by stacking the CF, FFT the result and square - // it in the end. This is not the way to do in principle but the result is almost the + // FIX: I now do the average of the PB by stacking the CF, FFT the result and square + // it in the end. This is not the way to do in principle but the result is almost the // same. It should pose no problem I think. Matrix<Complex> Spheroid_cut_padded2f; + Matrix<Complex> spheroid_cut_element_fft2; Cube<Complex> aTermA_padded2; Cube<Complex> aTermB_padded2; // Keep the non-padded convolution functions for average PB calculation. vector< vector < Matrix<Complex> > > Kron_Product_non_padded; Kron_Product_non_padded.reserve(4); - + if (Stack) { Npix_out2 = Npix_out; Spheroid_cut_padded2f = zero_padding(Spheroid_cut, Npix_out2); + spheroid_cut_element_fft2 = zero_padding(spheroid_cut_element_fft, Npix_out2); + normalized_fft (timerFFT, spheroid_cut_element_fft2, false); aTermA_padded2 = zero_padding(aTermA, Npix_out2); aTermB_padded2 = zero_padding(aTermB, Npix_out2); normalized_fft (timerFFT, Spheroid_cut_padded2f, false); @@ -448,6 +1099,7 @@ namespace LOFAR aTermA_padded.xyPlane(ind1)); plane_product *= wTerm_paddedf; plane_product *= Spheroid_cut_paddedf; + Matrix<Complex> plane_product_paddedf (zero_padding(plane_product, plane_product.shape()[0] * m_oversampling)); @@ -471,6 +1123,7 @@ namespace LOFAR Matrix<Complex> plane_productf(aTermB_padded2.xyPlane(ind0)* aTermA_padded2.xyPlane(ind1)); plane_productf *= Spheroid_cut_padded2f; + if(its_Apply_Element){plane_productf *= spheroid_cut_element_fft2;} normalized_fft (timerFFT, plane_productf); Row_non_padded[jj].reference (plane_productf); } @@ -493,7 +1146,12 @@ namespace LOFAR if (degridding_step) { for (uInt i=0; i<4; ++i) { for (uInt j=i; j<4; ++j) { - AlwaysAssert (Mask_Mueller(i,j) == Mask_Mueller(j,i), AipsError); + //AlwaysAssert (Mask_Mueller(i,j) == Mask_Mueller(j,i), AipsError); + if ((Mask_Mueller(i,j)==false)&&(Mask_Mueller(j,i)==true)){ + Matrix<Complex> a(Kron_Product[i][j].copy()); + a=0.; + Kron_Product[i][j]=a.copy(); + }; if (Mask_Mueller(i,j)) { if (i!=j) { Matrix<Complex> conj_product(conj(Kron_Product[i][j])); @@ -523,8 +1181,8 @@ namespace LOFAR if (Stack) { result_non_padded.push_back(Kron_Product_non_padded); } - } - + //} + // Stacks the weighted quadratic sum of the convolution function of // average PB estimate (!!!!! done for channel 0 only!!!) if (Stack) { @@ -552,7 +1210,7 @@ namespace LOFAR } } } - + // Put the resulting vec(vec(vec))) in a LofarCFStore object CoordinateSystem csys; Vector<Float> samp(2, m_oversampling); @@ -575,12 +1233,14 @@ namespace LOFAR #pragma omp atomic itsTimeCFpar += ptime; + return LofarCFStore (res, csys, samp, xsup, ysup, maxXSup, maxYSup, PA, mosPointing, Mask_Mueller); } + //================================================ - + // Returns the average Primary Beam from the disk Matrix<Float> LofarConvolutionFunction::Give_avg_pb() { @@ -615,21 +1275,34 @@ namespace LOFAR cout<<"..... Compute average PB"<<endl; } Sum_Stack_PB_CF /= float(sum_weight_square); - //store(Stack_PB_CF,"Stack_PB_CF.img"); + //store(Sum_Stack_PB_CF,"Stack_PB_CF.img"); normalized_fft(Sum_Stack_PB_CF, false); - //store(Im_Stack_PB_CF00,"Im_Stack_PB_CF00.img"); + //store(Sum_Stack_PB_CF,"Im_Stack_PB_CF00.img"); + //store(Sum_Stack_PB_CF, itsImgName + ".before"); Im_Stack_PB_CF0.resize (IPosition(2, m_shape[0], m_shape[1])); - - float threshold = 1.e-6; + + float maxPB(0.); + float maxPB_noabs(0.); + for(uInt i=0;i<m_shape[1];++i){ + for(uInt j=0;j<m_shape[1];++j){ + Complex pixel(Sum_Stack_PB_CF(i,j)); + if(abs(pixel)>maxPB){ + maxPB=abs(pixel); + //maxPB_noabs=pixel; + }; + } + } + float threshold = 1.e-8; for (Int jj=0; jj<m_shape[1]; ++jj) { for (Int ii=0; ii<m_shape[0]; ++ii) { Float absVal = abs(Sum_Stack_PB_CF(ii,jj)); - Im_Stack_PB_CF0(ii,jj) = std::max (absVal*absVal, threshold); + Im_Stack_PB_CF0(ii,jj) = std::max (absVal*absVal, threshold*maxPB); + //Im_Stack_PB_CF0(ii,jj) = sqrt(Im_Stack_PB_CF0(ii,jj))*sign(maxPB_noabs); } } // Make it persistent. - store(Im_Stack_PB_CF0, itsImgName + ".avgpb"); + store(m_coordinates,Im_Stack_PB_CF0, itsImgName + ".avgpb"); } return Im_Stack_PB_CF0; } @@ -642,15 +1315,17 @@ namespace LOFAR if (Image.shape()[0] == Npixel_Out) { return Image.copy(); } - if ((Npixel_Out%2) != 1) { - Npixel_Out++; - } + + // if ((Npixel_Out%2) != 1) { + // Npixel_Out++; + // } + Cube<Complex> Image_Enlarged(Npixel_Out,Npixel_Out,Image.shape()[2]); uInt Dii = Image.shape()(0)/2; uInt Start_image_enlarged=Npixel_Out/2-Dii; //Is an even number, Assume square image - if ((Start_image_enlarged-floor(Start_image_enlarged))!=0.) { - Start_image_enlarged += 0.5; //If number of pixel odd then 0th order at the center, shifted by one otherwise - } + // if ((Start_image_enlarged-floor(Start_image_enlarged))!=0.) { + // Start_image_enlarged += 0.5; //If number of pixel odd then 0th order at the center, shifted by one otherwise + // } /* cout<<Start_image_enlarged<<" "<<floor(Start_image_enlarged)<<endl; */ /* if((Start_image_enlarged-floor(Start_image_enlarged))!=0.){ */ /* cout<<"Not even!!!"<<endl; */ @@ -681,9 +1356,6 @@ namespace LOFAR if (Image.shape()[0] == Npixel_Out) { return Image.copy(); } - if (Npixel_Out%2 != 1) { - Npixel_Out++; - } IPosition shape_im_out(2, Npixel_Out, Npixel_Out); Matrix<Complex> Image_Enlarged(shape_im_out, 0.); @@ -695,9 +1367,9 @@ namespace LOFAR uInt Start_image_enlarged = shape_im_out[0]/2-Dii; //Is an even number, Assume square image //If number of pixel odd then 0th order at the center, shifted by one otherwise - if ((Start_image_enlarged-floor(Start_image_enlarged))!=0.) { - Start_image_enlarged += 0.5; - } + // if ((Start_image_enlarged-floor(Start_image_enlarged))!=0.) { + // Start_image_enlarged += 0.5; + // } /* cout<<Start_image_enlarged<<" "<<floor(Start_image_enlarged)<<endl; */ /* if((Start_image_enlarged-floor(Start_image_enlarged))!=0.){ */ @@ -705,7 +1377,7 @@ namespace LOFAR /* Start_image_enlarged+=0.5;} */ for (Int jj=0; jj<Image.shape()[1]; ++jj) { for (Int ii=0; ii<Image.shape()[0]; ++ii) { - Image_Enlarged(Start_image_enlarged+ii,Start_image_enlarged+jj) = + Image_Enlarged(Start_image_enlarged+ii,Start_image_enlarged+jj) = ratio*Image(ii,jj); } } @@ -716,6 +1388,7 @@ namespace LOFAR void LofarConvolutionFunction::normalized_fft (Matrix<Complex> &im, bool toFreq) { + //cout<<" "<<im.ncolumn()<<" "<<im.nrow()<<" "<<im.size()<<" "<<im.contiguousStorage()<<endl; AlwaysAssert (im.ncolumn() == im.nrow() && im.size() > 0 && im.contiguousStorage(), AipsError); int tnr = OpenMP::threadNum(); @@ -746,28 +1419,6 @@ namespace LOFAR return observation.timeRangeMeas()(0)(IPosition(1, 0)); } - //================================================= - Double LofarConvolutionFunction::observationReferenceFreq - (const MeasurementSet &ms, uInt idDataDescription) - { - // Read polarization id and spectral window id. - ROMSDataDescColumns desc(ms.dataDescription()); - AlwaysAssert(desc.nrow() > idDataDescription, SynthesisError); - AlwaysAssert(!desc.flagRow()(idDataDescription), SynthesisError); - - const uInt idWindow = desc.spectralWindowId()(idDataDescription); - - /* logIO() << LogOrigin("LofarATerm", "initReferenceFreq") << LogIO::NORMAL - << "spectral window: " << desc.spectralWindowId()(idDataDescription) << LogIO::POST;*/ - // << "spectral window: " << desc.spectralWindowId() << LogIO::POST; - // Get spectral information. - ROMSSpWindowColumns window(ms.spectralWindow()); - AlwaysAssert(window.nrow() > idWindow, SynthesisError); - AlwaysAssert(!window.flagRow()(idWindow), SynthesisError); - - return window.refFrequency()(idWindow); - } - //================================================= // Estime spheroidal convolution function from the support of the fft of the spheroidal in the image plane @@ -816,7 +1467,7 @@ namespace LOFAR store(Spheroid_cut_im, itsImgName + ".spheroid_cut_im"); if (itsVerbose > 0) { store(Spheroid_cut, itsImgName + ".spheroid_cut"); - } + } return Pixel_Size_Spheroidal; } @@ -869,12 +1520,12 @@ namespace LOFAR // Return the angular resolution required for making the image of the angular size determined by // coordinates and shape. The resolution is assumed to be the same on both direction axes. Double LofarConvolutionFunction::estimateAResolution - (const IPosition &shape, const DirectionCoordinate &coordinates) const + (const IPosition &shape, const DirectionCoordinate &coordinates, double station_diam) const { Double res_ini=abs(coordinates.increment()(0)); // pixel size in image in radian Double diam_image=res_ini*shape(0); // image diameter in radian - Double station_diam = 70.; // station diameter in meters: To be adapted to the individual station size. - Double Res_beam_image= ((C::c/m_refFrequency)/station_diam)/2.; // pixel size in A-term image in radian + //Double station_diam = 70.; // station diameter in meters: To be adapted to the individual station size. + Double Res_beam_image= 0.5*((C::c/m_refFrequency)/station_diam)/2.; // pixel size in A-term image in radian uInt Npix=floor(diam_image/Res_beam_image); // Number of pixel size in A-term image Res_beam_image=diam_image/Npix; if (Npix%2 != 1) { @@ -920,7 +1571,7 @@ namespace LOFAR bot += Q[part][k] * delnusqPow; delnusqPow *= delnusq; } - + double result = (bot == 0 ? 0 : (1.0 - nusq) * (top / bot)); //if(result<1.e-3){result=1.e-3;} return result; diff --git a/CEP/Imager/LofarFT/src/LofarConvolutionFunctionOld.cc b/CEP/Imager/LofarFT/src/LofarConvolutionFunctionOld.cc new file mode 100644 index 0000000000000000000000000000000000000000..de9946a8da70cd2c4ff4853c8d6773be83944b9f --- /dev/null +++ b/CEP/Imager/LofarFT/src/LofarConvolutionFunctionOld.cc @@ -0,0 +1,965 @@ +//# LofarConvolutionFunctionOld.cc: Compute the LOFAR convolution function +//# +//# Copyright (C) 2011 +//# ASTRON (Netherlands Institute for Radio Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +//# +//# This file is part of the LOFAR software suite. +//# The LOFAR software suite is free software: you can redistribute it and/or +//# modify it under the terms of the GNU General Public License as published +//# by the Free Software Foundation, either version 3 of the License, or +//# (at your option) any later version. +//# +//# The LOFAR software suite 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License along +//# with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>. +//# +//# $Id$ + +#include <lofar_config.h> +#include <LofarFT/LofarConvolutionFunctionOld.h> +#include <LofarFT/LofarConvolutionFunction.h> // needed for store function +#include <Common/LofarLogger.h> +#include <Common/OpenMP.h> + +#include <casa/Logging/LogIO.h> +#include <casa/Logging/LogOrigin.h> +#include <casa/Arrays/Cube.h> +#include <casa/Arrays/Matrix.h> +#include <casa/Arrays/MatrixMath.h> +#include <casa/Arrays/ArrayMath.h> + +#include <ms/MeasurementSets/MeasurementSet.h> +#include <measures/Measures/MDirection.h> +#include <measures/Measures/MeasConvert.h> +#include <measures/Measures/MCDirection.h> +#include <measures/Measures/MCPosition.h> +#include <ms/MeasurementSets/MSAntenna.h> +#include <ms/MeasurementSets/MSAntennaParse.h> +#include <ms/MeasurementSets/MSAntennaColumns.h> +#include <ms/MeasurementSets/MSDataDescription.h> +#include <ms/MeasurementSets/MSDataDescColumns.h> +#include <ms/MeasurementSets/MSField.h> +#include <ms/MeasurementSets/MSFieldColumns.h> +#include <ms/MeasurementSets/MSObservation.h> +#include <ms/MeasurementSets/MSObsColumns.h> +#include <ms/MeasurementSets/MSPolarization.h> +#include <ms/MeasurementSets/MSPolColumns.h> +#include <ms/MeasurementSets/MSSpectralWindow.h> +#include <ms/MeasurementSets/MSSpWindowColumns.h> +#include <ms/MeasurementSets/MSSelection.h> +#include <measures/Measures/MeasTable.h> +#include <coordinates/Coordinates/CoordinateSystem.h> +#include <coordinates/Coordinates/SpectralCoordinate.h> +#include <coordinates/Coordinates/StokesCoordinate.h> +#include <casa/OS/PrecTimer.h> +#include <casa/sstream.h> +#include <iomanip> + +namespace LOFAR +{ + + LofarConvolutionFunctionOld::LofarConvolutionFunctionOld + (const IPosition& shape, + const DirectionCoordinate& coordinates, + const MeasurementSet& ms, + uInt nW, double Wmax, + uInt oversample, + const String& beamElementPath, + Int verbose, + Int maxsupport, + const String& imgName) + : m_shape(shape), + m_coordinates(coordinates), + m_aTerm(ms, beamElementPath), + m_maxW(Wmax), //maximum W set by ft machine to flag the w>wmax + m_nWPlanes(nW), + m_oversampling(oversample), + itsVerbose (verbose), + itsMaxSupport(maxsupport), + itsImgName(imgName), + itsTimeW (0), + itsTimeWpar (0), + itsTimeWfft (0), + itsTimeWcnt (0), + itsTimeA (0), + itsTimeApar (0), + itsTimeAfft (0), + itsTimeAcnt (0), + itsTimeCFpar(0), + itsTimeCFfft(0), + itsTimeCFcnt(0) + //Not sure how useful that is + { + if (itsVerbose > 0) { + cout<<"LofarConvolutionFunctionOld:shape "<<shape<<endl; + } + itsFFTMachines.resize (OpenMP::maxThreads()); + + // m_maxCFSupport=0; //need this parameter to stack all the CF for average PB estimate + + m_wScale = WScale(m_maxW, m_nWPlanes); + MEpoch start = observationStartTime(ms, 0); + + m_refFrequency = observationReferenceFreq(ms, 0); + + if (m_oversampling%2 == 0) { + // Make OverSampling an odd number + m_oversampling++; + } + + list_freq = Vector<Double>(1, m_refFrequency); + m_nChannel = list_freq.size(); + ROMSAntennaColumns antenna(ms.antenna()); + m_nStations = antenna.nrow(); + + m_pixelSizeSpheroidal = makeSpheroidCut(); + //Double PixelSize=abs(m_coordinates.increment()(0)); + //Double ImageDiameter=PixelSize * m_shape(0); + //Double W_Pixel_Ang_Size=min(Pixel_Size_Spheroidal,estimateWResolution(m_shape, m_coordinates, m_maxW)); + //m_maxCFSupport= ImageDiameter / W_Pixel_Ang_Size; + //Matrix<Complex> Stack_pb_cf0(IPosition(2,m_maxCFSupport,m_maxCFSupport),0.); + Matrix<Complex> Stack_pb_cf0(IPosition(2,m_shape(0),m_shape(0)),0.); + Matrix<float> Stack_pb_cf1(IPosition(2,m_shape(0),m_shape(0)),0.); + + //Stack_pb_cf0(256,300)=1.; + //Matrix<Complex> Avg_PB_padded00(give_normalized_fft(Stack_pb_cf0,false)); + //store(Avg_PB_padded00,"Avg_PB_padded00.img"); + + // Precalculate the Wtwerm fft for all w-planes. + store_all_W_images(); + } + + // ~LofarConvolutionFunctionOld () + // { + // } + + // Precalculate all W-terms in the fourier domain + void LofarConvolutionFunctionOld::store_all_W_images() + { + PrecTimer wTimer; + wTimer.start(); + Double pixelSize = abs(m_coordinates.increment()[0]); + Double imageDiameter = pixelSize * m_shape(0); + // Size the vector, but give each element its own default matrix, + // so the vector can be safely filled in parallel. + m_WplanesStore.reserve (m_nWPlanes); + for (uInt i=0; i<m_nWPlanes; ++i) { + m_WplanesStore.push_back (Matrix<Complex>()); + } +#pragma omp parallel + { + // Thread private variables. + PrecTimer timerFFT; + PrecTimer timerPar; +#pragma omp for schedule(dynamic) + for (uInt i=0; i<m_nWPlanes; ++i) { + timerPar.start(); + Double w = m_wScale.center(i); + Double wPixelAngSize = min(m_pixelSizeSpheroidal, + estimateWResolution(m_shape, + pixelSize, w)); + Int nPixelsConv = imageDiameter / wPixelAngSize; + if (itsVerbose > 0) { + cout<<"Number of pixel in the "<<i<<"-wplane: "<<nPixelsConv + <<" (w="<<w<<")"<<endl; + } + if (nPixelsConv > itsMaxSupport) { + nPixelsConv = itsMaxSupport; + } + // Make odd and optimal. + nPixelsConv = FFTCMatrix::optimalOddFFTSize (nPixelsConv); + wPixelAngSize = imageDiameter / nPixelsConv; + IPosition shape(2, nPixelsConv, nPixelsConv); + //Careful with the sign of increment!!!! To check!!!!!!! + Vector<Double> increment(2, wPixelAngSize); + double wavelength(C::c / list_freq[0]); + Matrix<Complex> wTerm = m_wTerm.evaluate(shape, increment, + w/wavelength); + normalized_fft(timerFFT, wTerm); + m_WplanesStore[i].reference (wTerm); + timerPar.stop(); + } + // Update the timing info. + double ftime = timerFFT.getReal(); +#pragma omp atomic + itsTimeWfft += ftime; + unsigned long long cnt = timerFFT.getCount(); +#pragma omp atomic + itsTimeWcnt += cnt; + double ptime = timerPar.getReal(); +#pragma omp atomic + itsTimeWpar += ptime; + } // end omp parallel + wTimer.stop(); + itsTimeW = wTimer.getReal(); + } + + + // Compute the fft of the beam at the minimal resolution for all antennas + // if not done yet. + // Put it in a map object with a (double time) key. + void LofarConvolutionFunctionOld::computeAterm (Double time) + { + if (m_AtermStore.find(time) != m_AtermStore.end()) { + // Already done. + return; + } + PrecTimer aTimer; + aTimer.start(); + Double pixelSize = abs(m_coordinates.increment()[0]); + Double imageDiameter = pixelSize * m_shape(0); + // Try to avoid making copies when inserting elements in vector or map. + // Therefore first create the elements and resize them. + m_AtermStore[time] = vector< vector< Cube<Complex> > >(); + vector< vector< Cube<Complex> > >& aTermList = m_AtermStore[time]; + // Calculate the A-term and fill the vector for all stations. + aTermList.resize (m_nStations); + ///#pragma omp parallel + { + // Thread private variables. + PrecTimer timerFFT; + PrecTimer timerPar; + ///#pragma omp for + for (uInt i=0; i<m_nStations; ++i) { + timerPar.start(); + DirectionCoordinate coordinate = m_coordinates; + Double aPixelAngSize = min(m_pixelSizeSpheroidal, + estimateAResolution(m_shape, m_coordinates)); + Int nPixelsConv = imageDiameter / aPixelAngSize; + if (nPixelsConv > itsMaxSupport) { + nPixelsConv = itsMaxSupport; + } + // Make odd and optimal. + nPixelsConv = FFTCMatrix::optimalOddFFTSize (nPixelsConv); + aPixelAngSize = imageDiameter / nPixelsConv; + if (itsVerbose > 0) { + cout.precision(20); + cout<<"Number of pixel in the Aplane of "<<i<<": "<<nPixelsConv + <<", time="<<fixed<<time<<endl; + } + IPosition shape(2, nPixelsConv, nPixelsConv); + Vector<Double> increment_old(coordinate.increment()); + Vector<Double> increment(2); + increment[0] = aPixelAngSize*sign(increment_old[0]); + increment[1] = aPixelAngSize*sign(increment_old[1]); + coordinate.setIncrement(increment); + Vector<Double> refpix(2, 0.5*(nPixelsConv-1)); + coordinate.setReferencePixel(refpix); + + //====================================== + // Disable the beam + //====================================== + //Cube<Complex> aterm_cube(IPosition(3,nPixels_Conv,nPixels_Conv,4),1.); + //for (uInt iiii=0;iiii<nPixels_Conv;++iiii) { + // for (uInt iiiii=0;iiiii<nPixels_Conv;++iiiii) { + // aterm_cube(iiii,iiiii,1)=0.; + // aterm_cube(iiii,iiiii,2)=0.; + // } + //} + //vector< Cube<Complex> > aTermA; + //aTermA.push_back(aterm_cube); + //====================================== + // Enable the beam + //====================================== + MEpoch binEpoch; + binEpoch.set(Quantity(time, "s")); + vector< Cube<Complex> > aTermA = m_aTerm.evaluate(shape, + coordinate, + i, binEpoch, + list_freq, true); + // Compute the fft on the beam + for (uInt ch=0; ch<m_nChannel; ++ch) { + for (uInt pol=0; pol<4; ++pol) { + Matrix<Complex> plane (aTermA[ch].xyPlane(pol)); + AlwaysAssert (plane.contiguousStorage(), AipsError); + normalized_fft (timerFFT, plane); + } + } + // Note that push_back uses the copy constructor, so for the Cubes + // in the vector the copy constructor is called too (which is cheap). + aTermList[i] = aTermA; + timerPar.stop(); + } // end omp for + // Update the timing info. + double ftime = timerFFT.getReal(); + ///#pragma omp atomic + itsTimeAfft += ftime; + unsigned long long cnt = timerFFT.getCount(); + ///#pragma omp atomic + itsTimeAcnt += cnt; + double ptime = timerPar.getReal(); + ///#pragma omp atomic + itsTimeApar += ptime; + } // end omp parallel + aTimer.stop(); + itsTimeA = aTimer.getReal(); + } + + //================================================ + // Compute the convolution function for all channel, for the polarisations specified in the Mueller_mask matrix + // Also specify weither to compute the Mueller matrix for the forward or the backward step. A dirty way to calculate + // the average beam has been implemented, by specifying the beam correcping to the given baseline and timeslot. + // RETURNS in a LofarCFStore: result[channel][Mueller row][Mueller column] + + LofarCFStore LofarConvolutionFunctionOld::makeConvolutionFunction + (uInt stationA, uInt stationB, Double time, Double w, + const Matrix<bool>& Mask_Mueller, bool degridding_step, + double Append_average_PB_CF, Matrix<Complex>& Stack_PB_CF, + double& sum_weight_square) + { + // Initialize timers. + PrecTimer timerFFT; + PrecTimer timerPar; + timerPar.start(); + + // Stack_PB_CF should be called Sum_PB_CF (it is a sum, no stack). + CountedPtr<CFTypeVec> res (new vector< vector< vector < Matrix<Complex> > > >()); + CFTypeVec& result = *res; + vector< vector< vector < Matrix<Complex> > > > result_non_padded; + + // Stack the convolution function if averagepb.img don't exist + Matrix<Complex> Stack_PB_CF_fft(IPosition(2,m_shape(0),m_shape(0)),0.); + Bool Stack = (Append_average_PB_CF != 0.); + + // If the beam is not in memory, compute it + + map<Double, vector< vector< Cube<Complex> > > >::const_iterator aiter = + m_AtermStore.find(time); + AlwaysAssert (aiter!=m_AtermStore.end(), AipsError); + const vector< vector< Cube<Complex> > >& aterm = aiter->second; + /// if(m_AtermStore.find(time)==m_AtermStore.end()){computeAterm(time);} + + // Load the Wterm + uInt w_index = m_wScale.plane(w); + Matrix<Complex> wTerm; + wTerm = m_WplanesStore[w_index]; + Int Npix_out = 0; + Int Npix_out2 = 0; + + // Matrix<Complex> Term_test(IPosition(2,101,101),1.); + // normalized_fft(Term_test); + // store (Term_test,"Term_test.img"); + // normalized_fft(Term_test,false); + // store (Term_test,"Term_test_0.img"); + // normalized_fft(Term_test); + // store (Term_test,"Term_test_1.img"); + // assert(false); + + if (w > 0.) { + wTerm.reference (conj(wTerm)); + } + + for (uInt ch=0; ch<m_nChannel; ++ch) { + // Load the Aterm + const Cube<Complex>& aTermA(aterm[stationA][ch]); + const Cube<Complex>& aTermB(aterm[stationB][ch]); + // Determine maximum support of A, W, and Spheroidal function for zero padding + Npix_out = std::max(std::max(aTermA.shape()[0], aTermB.shape()[0]), + std::max(wTerm.shape()[0], Spheroid_cut.shape()[0])); + if (itsVerbose > 0) { + cout<<"Number of pixel in the final conv function for baseline ["<< stationA<<", "<<stationB<<"] = "<<Npix_out + <<" "<<aTermA.shape()[0]<<" "<<aTermB.shape()[0]<<" "<<wTerm.shape()[0]<<endl; + } + + // Zero pad to make the image planes of the A1, A2, and W term have the same resolution in the image plane + Matrix<Complex> Spheroid_cut_paddedf(zero_padding(Spheroid_cut,Npix_out)); + Matrix<Complex> wTerm_paddedf(zero_padding(wTerm, Npix_out)); + Cube<Complex> aTermA_padded(zero_padding(aTermA, Npix_out)); + Cube<Complex> aTermB_padded(zero_padding(aTermB, Npix_out)); + + // FFT (backward) the A and W terms + normalized_fft (timerFFT, wTerm_paddedf, false); + normalized_fft (timerFFT, Spheroid_cut_paddedf, false); + if (itsVerbose > 0) { + cout << "fft shapes " << wTerm_paddedf.shape() << ' ' << Spheroid_cut_paddedf.shape() + << ' ' << aTermA_padded.shape() << ' ' << aTermB_padded.shape() << endl; + } + for (uInt i=0; i<4; ++i) { + //Matrix<Complex> planeAf(aTermA_padded.xyPlane(i)); + //Matrix<Complex> planeBf(aTermB_padded.xyPlane(i)); + // AlwaysAssert(planeAf.contiguousStorage(), AipsError); + // Make a matrix referencing the data in the cube's plane. + Matrix<Complex> planeAf(aTermA_padded.xyPlane(i)); + Matrix<Complex> planeBf(aTermB_padded.xyPlane(i)); + AlwaysAssert(planeAf.contiguousStorage(), AipsError); + normalized_fft (timerFFT, planeAf, false); + normalized_fft (timerFFT, planeBf, false); + } + + // Create the vectors of Matrices giving the convolution functions + // for each Mueller element. + vector< vector < Matrix<Complex> > > Kron_Product; + Kron_Product.reserve(4); + + // Something I still don't completely understand: for the average PB calculation. + // The convolution functions padded with a higher value than the minimum one give a + // better result in the end. If you try Npix_out2=Npix_out, then the average PB shows + // structure like aliasing, producing high values in the devided disrty map... This + // is likely to be due to the way fft works?... + // FIX: I now do the average of the PB by stacking the CF, FFT the result and square + // it in the end. This is not the way to do in principle but the result is almost the + // same. It should pose no problem I think. + Matrix<Complex> Spheroid_cut_padded2f; + Cube<Complex> aTermA_padded2; + Cube<Complex> aTermB_padded2; + + // Keep the non-padded convolution functions for average PB calculation. + vector< vector < Matrix<Complex> > > Kron_Product_non_padded; + Kron_Product_non_padded.reserve(4); + + if (Stack) { + Npix_out2 = Npix_out; + Spheroid_cut_padded2f = zero_padding(Spheroid_cut, Npix_out2); + aTermA_padded2 = zero_padding(aTermA, Npix_out2); + aTermB_padded2 = zero_padding(aTermB, Npix_out2); + normalized_fft (timerFFT, Spheroid_cut_padded2f, false); + for (uInt i=0; i<4; ++i) { + Matrix<Complex> planeA2f(aTermA_padded2.xyPlane(i)); + Matrix<Complex> planeB2f(aTermB_padded2.xyPlane(i)); + normalized_fft (timerFFT, planeA2f, false); + normalized_fft (timerFFT, planeB2f, false); + } + } + + // Compute the Mueller matrix considering the Mueller Mask + uInt ind0; + uInt ind1; + uInt ii = 0; + IPosition cfShape; + Bool allElem = True; + for (uInt row0=0; row0<=1; ++row0) { + for (uInt col0=0; col0<=1; ++col0) { + vector < Matrix<Complex> > Row(4); + vector < Matrix<Complex> > Row_non_padded(4); + uInt jj = 0; + for (uInt row1=0; row1<=1; ++row1) { + for (uInt col1=0; col1<=1; ++col1) { + // This Mueller ordering is for polarisation given as XX,XY,YX YY + ind0 = row0 + 2*row1; + ind1 = col0 + 2*col1; + // Compute the convolution function for the given Mueller element + if (Mask_Mueller(ii,jj)) { + // Padded version for oversampling the convolution function + Matrix<Complex> plane_product (aTermB_padded.xyPlane(ind0) * + aTermA_padded.xyPlane(ind1)); + plane_product *= wTerm_paddedf; + plane_product *= Spheroid_cut_paddedf; + Matrix<Complex> plane_product_paddedf + (zero_padding(plane_product, + plane_product.shape()[0] * m_oversampling)); + normalized_fft (timerFFT, plane_product_paddedf); + + plane_product_paddedf *= static_cast<Float>(m_oversampling * + m_oversampling); + if (itsVerbose>3 && row0==0 && col0==0 && row1==0 && col1==0) { + store (plane_product_paddedf, "awfft"+String::toString(stationA)+'-'+String::toString(stationB)); + } + + // Maybe to do: + // Find circle (from outside to inside) until value > peak*1e-3. + // Cut out that box to use as the convolution function. + // See nPBWProjectFT.cc (findSupport). + + Row[jj].reference (plane_product_paddedf); + cfShape = plane_product_paddedf.shape(); + // Non padded version for PB calculation (no W-term) + if (Stack) { + Matrix<Complex> plane_productf(aTermB_padded2.xyPlane(ind0)* + aTermA_padded2.xyPlane(ind1)); + plane_productf *= Spheroid_cut_padded2f; + normalized_fft (timerFFT, plane_productf); + Row_non_padded[jj].reference (plane_productf); + } + } else { + allElem = False; + } + ++jj; + } + } + ++ii; + Kron_Product.push_back(Row); + if (Stack) { + // Keep non-padded for primary beam calculation. + Kron_Product_non_padded.push_back(Row_non_padded); + } + } + } + + // When degridding, transpose and use conjugate. + if (degridding_step) { + for (uInt i=0; i<4; ++i) { + for (uInt j=i; j<4; ++j) { + AlwaysAssert (Mask_Mueller(i,j) == Mask_Mueller(j,i), AipsError); + if (Mask_Mueller(i,j)) { + if (i!=j) { + Matrix<Complex> conj_product(conj(Kron_Product[i][j])); + Kron_Product[i][j].reference (conj(Kron_Product[j][i])); + Kron_Product[j][i].reference (conj_product); + } else { + Kron_Product[i][j].reference (conj(Kron_Product[i][j])); + } + } + } + } + } + + // Put similarly shaped matrix with zeroes for missing Mueller elements. + if (!allElem) { + Matrix<Complex> zeroCF(cfShape); + for (uInt i=0; i<4; ++i) { + for (uInt j=0; j<4; ++j) { + if (! Mask_Mueller(i,j)) { + Kron_Product[i][j].reference (zeroCF); + } + } + } + } + // Add the conv.func. for this channel to the result. + result.push_back(Kron_Product); + if (Stack) { + result_non_padded.push_back(Kron_Product_non_padded); + } + } + + // Stacks the weighted quadratic sum of the convolution function of + // average PB estimate (!!!!! done for channel 0 only!!!) + if (Stack) { + // cout<<"...Stack CF for PB estimate"<<endl; + double weight_square = 4. * Append_average_PB_CF * Append_average_PB_CF; + double weight_sqsq = weight_square * weight_square; + for (uInt i=0; i<4; ++i) { + //if((i==2)||(i==1)) break; + for (uInt j=0; j<4; ++j) { + // Only use diagonal terms for average primary beam. + if (i==j && Mask_Mueller(i,j)) { + //Stack_PB_CF=0.; + double istart = 0.5 * (m_shape[0] - Npix_out2); + if (istart-floor(istart) != 0.) { + istart += 0.5; //If number of pixel odd then 0th order at the center, shifted by one otherwise + } + for (Int jj=0; jj<Npix_out2; ++jj) { + for (Int ii=0; ii<Npix_out2; ++ii) { + Complex gain = result_non_padded[0][i][j](ii,jj); + Stack_PB_CF(istart+ii,istart+jj) += gain*weight_sqsq; + } + } + sum_weight_square += weight_sqsq; + } + } + } + } + + // Put the resulting vec(vec(vec))) in a LofarCFStore object + CoordinateSystem csys; + Vector<Float> samp(2, m_oversampling); + Vector<Int> xsup(1, Npix_out/2); + Vector<Int> ysup(1, Npix_out/2); + Int maxXSup(Npix_out);///2); + Int maxYSup(Npix_out);///2); + Quantity PA(0., "deg"); + Int mosPointing(0); + + // Update the timing info. + timerPar.stop(); + double ftime = timerFFT.getReal(); +#pragma omp atomic + itsTimeCFfft += ftime; + unsigned long long cnt = timerFFT.getCount(); +#pragma omp atomic + itsTimeCFcnt += cnt; + double ptime = timerPar.getReal(); +#pragma omp atomic + itsTimeCFpar += ptime; + + return LofarCFStore (res, csys, samp, xsup, ysup, maxXSup, maxYSup, + PA, mosPointing, Mask_Mueller); + } + + //================================================ + + // Returns the average Primary Beam from the disk + Matrix<Float> LofarConvolutionFunctionOld::Give_avg_pb() + { + // Only read if not available. + if (Im_Stack_PB_CF0.empty()) { + if (itsVerbose > 0) { + cout<<"==============Give_avg_pb()"<<endl; + } + String PBFile_name(itsImgName + ".avgpb"); + File PBFile(PBFile_name); + if (! PBFile.exists()) { + throw SynthesisError (PBFile_name + " not found"); + } + if (itsVerbose > 0) { + cout<<"..... loading Primary Beam image from disk ....."<<endl; + } + PagedImage<Float> tmp(PBFile_name); + IPosition shape(tmp.shape()); + AlwaysAssert (shape[0]==m_shape[0] && shape[1]==m_shape[1], AipsError); + tmp.get (Im_Stack_PB_CF0, True); // remove degenerate axes. + } + return Im_Stack_PB_CF0; + } + + // Compute the average Primary Beam from the Stack of convolution functions + Matrix<Float> LofarConvolutionFunctionOld::Compute_avg_pb + (Matrix<Complex>& Sum_Stack_PB_CF, double sum_weight_square) + { + // Only calculate if not done yet. + if (Im_Stack_PB_CF0.empty()) { + if (itsVerbose > 0) { + cout<<"..... Compute average PB"<<endl; + } + Sum_Stack_PB_CF /= float(sum_weight_square); + //store(Stack_PB_CF,"Stack_PB_CF.img"); + + normalized_fft(Sum_Stack_PB_CF, false); + //store(Im_Stack_PB_CF00,"Im_Stack_PB_CF00.img"); + Im_Stack_PB_CF0.resize (IPosition(2, m_shape[0], m_shape[1])); + + float threshold = 1.e-6; + for (Int jj=0; jj<m_shape[1]; ++jj) { + for (Int ii=0; ii<m_shape[0]; ++ii) { + Float absVal = abs(Sum_Stack_PB_CF(ii,jj)); + Im_Stack_PB_CF0(ii,jj) = std::max (absVal*absVal, threshold); + } + } + // Make it persistent. + store(Im_Stack_PB_CF0, itsImgName + ".avgpb"); + } + return Im_Stack_PB_CF0; + } + + //================================================ + // Does Zeros padding of a Cube + Cube<Complex> LofarConvolutionFunctionOld::zero_padding + (const Cube<Complex>& Image, int Npixel_Out) + { + if (Image.shape()[0] == Npixel_Out) { + return Image.copy(); + } + if ((Npixel_Out%2) != 1) { + Npixel_Out++; + } + Cube<Complex> Image_Enlarged(Npixel_Out,Npixel_Out,Image.shape()[2]); + uInt Dii = Image.shape()(0)/2; + uInt Start_image_enlarged=Npixel_Out/2-Dii; //Is an even number, Assume square image + if ((Start_image_enlarged-floor(Start_image_enlarged))!=0.) { + Start_image_enlarged += 0.5; //If number of pixel odd then 0th order at the center, shifted by one otherwise + } + /* cout<<Start_image_enlarged<<" "<<floor(Start_image_enlarged)<<endl; */ + /* if((Start_image_enlarged-floor(Start_image_enlarged))!=0.){ */ + /* cout<<"Not even!!!"<<endl; */ + /* Start_image_enlarged+=0.5;} */ + + //double ratio(double(Npixel_Out)*double(Npixel_Out)/(Image.shape()(0)*Image.shape()(0))); + //if(!toFrequency){ratio=1./ratio;} + double ratio=1.; + + for (Int pol=0; pol<Image.shape()[2]; ++pol) { + //cout<<"pol: "<<pol<<endl; + for (Int jj=0; jj<Image.shape()[1]; ++jj) { + for (Int ii=0; ii<Image.shape()[0]; ++ii) { + Image_Enlarged(Start_image_enlarged+ii, + Start_image_enlarged+jj,pol) = ratio*Image(ii,jj,pol); + } + } + } + return Image_Enlarged; + } + + //================================================ + // Zeros padding of a Matrix + + Matrix<Complex> LofarConvolutionFunctionOld::zero_padding + (const Matrix<Complex>& Image, int Npixel_Out) + { + if (Image.shape()[0] == Npixel_Out) { + return Image.copy(); + } + if (Npixel_Out%2 != 1) { + Npixel_Out++; + } + IPosition shape_im_out(2, Npixel_Out, Npixel_Out); + Matrix<Complex> Image_Enlarged(shape_im_out, 0.); + + double ratio=1.; + + //if(!toFrequency){ratio=double(Npixel_Out)*double(Npixel_Out)/(Image.shape()(0)*Image.shape()(0));} + + uInt Dii = Image.shape()[0]/2; + uInt Start_image_enlarged = shape_im_out[0]/2-Dii; + //Is an even number, Assume square image + //If number of pixel odd then 0th order at the center, shifted by one otherwise + if ((Start_image_enlarged-floor(Start_image_enlarged))!=0.) { + Start_image_enlarged += 0.5; + } + + /* cout<<Start_image_enlarged<<" "<<floor(Start_image_enlarged)<<endl; */ + /* if((Start_image_enlarged-floor(Start_image_enlarged))!=0.){ */ + /* cout<<"Not even!!!"<<endl; */ + /* Start_image_enlarged+=0.5;} */ + for (Int jj=0; jj<Image.shape()[1]; ++jj) { + for (Int ii=0; ii<Image.shape()[0]; ++ii) { + Image_Enlarged(Start_image_enlarged+ii,Start_image_enlarged+jj) = + ratio*Image(ii,jj); + } + } + return Image_Enlarged; + } + + //================================================ + void LofarConvolutionFunctionOld::normalized_fft + (Matrix<Complex> &im, bool toFreq) + { + AlwaysAssert (im.ncolumn() == im.nrow() && im.size() > 0 && + im.contiguousStorage(), AipsError); + int tnr = OpenMP::threadNum(); + if (toFreq) { + itsFFTMachines[tnr].normalized_forward (im.nrow(), im.data()); + } else { + itsFFTMachines[tnr].normalized_backward (im.nrow(), im.data()); + } + } + + void LofarConvolutionFunctionOld::normalized_fft + (PrecTimer& timer, Matrix<Complex> &im, bool toFreq) + { + timer.start(); + normalized_fft (im, toFreq); + timer.stop(); + } + + //================================================= + MEpoch LofarConvolutionFunctionOld::observationStartTime + (const MeasurementSet &ms, uInt idObservation) const + { + // Get phase center as RA and DEC (J2000). + ROMSObservationColumns observation(ms.observation()); + AlwaysAssert(observation.nrow() > idObservation, SynthesisError); + AlwaysAssert(!observation.flagRow()(idObservation), SynthesisError); + + return observation.timeRangeMeas()(0)(IPosition(1, 0)); + } + + //================================================= + Double LofarConvolutionFunctionOld::observationReferenceFreq + (const MeasurementSet &ms, uInt idDataDescription) + { + // Read polarization id and spectral window id. + ROMSDataDescColumns desc(ms.dataDescription()); + AlwaysAssert(desc.nrow() > idDataDescription, SynthesisError); + AlwaysAssert(!desc.flagRow()(idDataDescription), SynthesisError); + + const uInt idWindow = desc.spectralWindowId()(idDataDescription); + + /* logIO() << LogOrigin("LofarATerm", "initReferenceFreq") << LogIO::NORMAL + << "spectral window: " << desc.spectralWindowId()(idDataDescription) << LogIO::POST;*/ + // << "spectral window: " << desc.spectralWindowId() << LogIO::POST; + // Get spectral information. + ROMSSpWindowColumns window(ms.spectralWindow()); + AlwaysAssert(window.nrow() > idWindow, SynthesisError); + AlwaysAssert(!window.flagRow()(idWindow), SynthesisError); + + return window.refFrequency()(idWindow); + } + + //================================================= + // Estime spheroidal convolution function from the support of the fft of the spheroidal in the image plane + + Double LofarConvolutionFunctionOld::makeSpheroidCut() + { + // Only calculate if not done yet. + if (! Spheroid_cut_im.empty()) { + return m_pixelSizeSpheroidal; + } + Matrix<Complex> spheroidal(m_shape[0], m_shape[1], 1.); + taper(spheroidal); + if (itsVerbose > 0) { + store(spheroidal, itsImgName + ".spheroidal"); + } + normalized_fft(spheroidal); + Double Support_Speroidal = findSupport(spheroidal, 0.0001); + if (itsVerbose > 0) { + store(spheroidal, itsImgName + ".spheroidal_fft"); + } + + Double res_ini = abs(m_coordinates.increment()(0)); + Double diam_image = res_ini*m_shape[0]; + Double Pixel_Size_Spheroidal = diam_image/Support_Speroidal; + uInt Npix = floor(diam_image/Pixel_Size_Spheroidal); + if (Npix%2 != 1) { + // Make the resulting image have an even number of pixel (to make the zeros padding step easier) + ++Npix; + Pixel_Size_Spheroidal = diam_image/Npix; + } + Matrix<Complex> Spheroid_cut0(IPosition(2,Npix,Npix),0.); + Spheroid_cut=Spheroid_cut0; + double istart(m_shape[0]/2.-Npix/2.); + if ((istart-floor(istart))!=0.) { + //If number of pixel odd then 0th order at the center, shifted by one otherwise + istart += 0.5; + } + for (uInt j=0; j<Npix; ++j) { + for (uInt i=0; i<Npix; ++i) { + Spheroid_cut(i,j) = spheroidal(istart+i,istart+j); + } + } + Matrix<Complex> Spheroid_cut_paddedf=zero_padding(Spheroid_cut,m_shape[0]); + normalized_fft(Spheroid_cut_paddedf, false); + Spheroid_cut_im.reference (real(Spheroid_cut_paddedf)); + // Only this one is really needed. + store(Spheroid_cut_im, itsImgName + ".spheroid_cut_im"); + if (itsVerbose > 0) { + store(Spheroid_cut, itsImgName + ".spheroid_cut"); + } + return Pixel_Size_Spheroidal; + } + + const Matrix<Float>& LofarConvolutionFunctionOld::getSpheroidCut() + { + if (Spheroid_cut_im.empty()) { + makeSpheroidCut(); + } + return Spheroid_cut_im; + } + + Matrix<Float> LofarConvolutionFunctionOld::getSpheroidCut (const String& imgName) + { + PagedImage<Float> im(imgName+".spheroid_cut_im"); + return im.get (True); + } + + Matrix<Float> LofarConvolutionFunctionOld::getAveragePB (const String& imgName) + { + PagedImage<Float> im(imgName+".avgpb"); + return im.get (True); + } + + //================================================= + // Return the angular resolution required for making the image of the angular size determined by + // coordinates and shape. The resolution is assumed to be the same on both direction axes. + Double LofarConvolutionFunctionOld::estimateWResolution + (const IPosition &shape, Double pixelSize, + Double w) const + { + Double diam_image = pixelSize*shape[0]; // image diameter in radian + if (w == 0.) { + return diam_image; + } + // Get pixel size in W-term image in radian + Double Res_w_image = 0.5/(sqrt(2.)*w*(shape[0]/2.)*pixelSize); + // Get number of pixel size in W-term image + uInt Npix=floor(diam_image/Res_w_image); + Res_w_image = diam_image/Npix; + if (Npix%2 != 1) { + // Make the resulting image have an even number of pixel + // (to make the zeros padding step easier) + ++Npix; + Res_w_image = diam_image/Npix; + } + return Res_w_image; + } + + //================================================= + // Return the angular resolution required for making the image of the angular size determined by + // coordinates and shape. The resolution is assumed to be the same on both direction axes. + Double LofarConvolutionFunctionOld::estimateAResolution + (const IPosition &shape, const DirectionCoordinate &coordinates) const + { + Double res_ini=abs(coordinates.increment()(0)); // pixel size in image in radian + Double diam_image=res_ini*shape(0); // image diameter in radian + Double station_diam = 70.; // station diameter in meters: To be adapted to the individual station size. + Double Res_beam_image= ((C::c/m_refFrequency)/station_diam)/2.; // pixel size in A-term image in radian + uInt Npix=floor(diam_image/Res_beam_image); // Number of pixel size in A-term image + Res_beam_image=diam_image/Npix; + if (Npix%2 != 1) { + // Make the resulting image have an even number of pixel (to make the zeros padding step easier) + ++Npix; + Res_beam_image = diam_image/Npix; + } + return Res_beam_image; + } + + //================================================= + Double LofarConvolutionFunctionOld::spheroidal(Double nu) const + { + static Double P[2][5] = {{ 8.203343e-2, -3.644705e-1, 6.278660e-1, + -5.335581e-1, 2.312756e-1}, + { 4.028559e-3, -3.697768e-2, 1.021332e-1, + -1.201436e-1, 6.412774e-2}}; + static Double Q[2][3] = {{1.0000000e0, 8.212018e-1, 2.078043e-1}, + {1.0000000e0, 9.599102e-1, 2.918724e-1}}; + uInt part = 0; + Double end = 0.0; + if (nu >= 0.0 && nu < 0.75) { + part = 0; + end = 0.75; + } else if (nu >= 0.75 && nu <= 1.00) { + part = 1; + end = 1.00; + } else { + return 0.0; + } + Double nusq = nu * nu; + Double delnusq = nusq - end * end; + Double delnusqPow = delnusq; + Double top = P[part][0]; + for (uInt k=1; k<5; ++k) { + top += P[part][k] * delnusqPow; + delnusqPow *= delnusq; + } + + Double bot = Q[part][0]; + delnusqPow = delnusq; + for (uInt k=1; k<3; ++k) { + bot += Q[part][k] * delnusqPow; + delnusqPow *= delnusq; + } + + double result = (bot == 0 ? 0 : (1.0 - nusq) * (top / bot)); + //if(result<1.e-3){result=1.e-3;} + return result; + } + + void LofarConvolutionFunctionOld::showTimings (ostream& os, + double duration, + double timeCF) const + { + os << " Wterm calculation "; + showPerc1 (os, itsTimeW, duration); + os << " fft-part "; + showPerc1 (os, itsTimeWfft, itsTimeW); + os << " ("; + showPerc1 (os, itsTimeWfft, duration); + os << " of total; #ffts=" << itsTimeWcnt << ')' << endl; + os << " Aterm calculation "; + showPerc1 (os, itsTimeA, duration); + os << " fft-part "; + showPerc1 (os, itsTimeAfft, itsTimeA); + os << " ("; + showPerc1 (os, itsTimeAfft, duration); + os << " of total; #ffts=" << itsTimeAcnt << ')' << endl; + os << " CFunc calculation "; + showPerc1 (os, timeCF, duration); + os << " fft-part "; + showPerc1 (os, itsTimeCFfft, timeCF); + os << " ("; + showPerc1 (os, itsTimeCFfft, duration); + os << " of total; #ffts=" << itsTimeCFcnt << ')' << endl; + } + + void LofarConvolutionFunctionOld::showPerc1 (ostream& os, + double value, double total) + { + int perc = (total==0 ? 0 : int(1000. * value / total + 0.5)); + os << std::setw(3) << perc/10 << '.' << perc%10 << '%'; + } + + +} //# end namespace casa diff --git a/CEP/Imager/LofarFT/src/LofarCubeSkyEquation.cc b/CEP/Imager/LofarFT/src/LofarCubeSkyEquation.cc index de087459d25efce5f28cbf85cbbe14fd71607a43..64450723415e81e25056d257e816fedfb88ded81 100644 --- a/CEP/Imager/LofarFT/src/LofarCubeSkyEquation.cc +++ b/CEP/Imager/LofarFT/src/LofarCubeSkyEquation.cc @@ -25,6 +25,7 @@ //# //# $Id$ +#include <lofar_config.h> #include <casa/iostream.h> #include <casa/Exceptions/Error.h> #include <casa/Utilities/Assert.h> @@ -35,6 +36,7 @@ #include <casa/OS/HostInfo.h> #include <casa/System/ProgressMeter.h> #include <casa/Utilities/CountedPtr.h> +#include <lattices/Lattices/ArrayLattice.h> #include <coordinates/Coordinates/CoordinateSystem.h> #include <coordinates/Coordinates/DirectionCoordinate.h> @@ -74,6 +76,8 @@ #include <msvis/MSVis/VisBufferAsync.h> //#include <synthesis/Utilities/ThreadTimers.h> +#include <casa/OS/PrecTimer.h> + namespace casa { //# NAMESPACE CASA - BEGIN LofarCubeSkyEquation::LofarCubeSkyEquation(SkyModel& sm, VisSet& vs, FTMachine& ft, @@ -85,7 +89,6 @@ LofarCubeSkyEquation::LofarCubeSkyEquation(SkyModel& sm, VisSet& vs, FTMachine& firstOneChangesPut_p(False), firstOneChangesGet_p(False) { - init(ft); } @@ -107,19 +110,19 @@ void LofarCubeSkyEquation::init(FTMachine& ft){ doflat_p=False; nchanPerSlice_p = 1; - - if(sm_->numberOfTaylorTerms()>1) + + if(sm_->numberOfTaylorTerms()>1) { nmod = (sm_->numberOfModels()/sm_->numberOfTaylorTerms()) * (2 * sm_->numberOfTaylorTerms() - 1); } - + //case of component ft only if(nmod==0) nmod=1; - + ftm_p.resize(nmod, True); iftm_p.resize(nmod, True); - + //make a distinct ift_ as gridding and degridding can occur simultaneously if(ft.name() == "MosaicFT"){ ft_=new MosaicFT(static_cast<MosaicFT &>(ft)); @@ -127,9 +130,9 @@ void LofarCubeSkyEquation::init(FTMachine& ft){ ftm_p[0]=ft_; iftm_p[0]=ift_; //For mosaic ...outlier fields get normal GridFT's - + MPosition loc=ift_->getLocation(); - for (Int k=1; k < (nmod); ++k){ + for (Int k=1; k < (nmod); ++k){ ftm_p[k]=new GridFT(1000000, 16, "SF", loc, 1.0, False); iftm_p[k]=new GridFT(1000000, 16, "SF", loc, 1.0, False); } @@ -144,9 +147,9 @@ void LofarCubeSkyEquation::init(FTMachine& ft){ static_cast<WProjectFT &>(*ftm_p[0]).setConvFunc(sharedconvFunc); static_cast<WProjectFT &>(*iftm_p[0]).setConvFunc(sharedconvFunc); // For now have all the fields have WProjectFt machines.... - //but should be seperated between GridFT's for the outliers and + //but should be seperated between GridFT's for the outliers and //WProject for the facets. - for (Int k=1; k < (nmod); ++k){ + for (Int k=1; k < (nmod); ++k){ ftm_p[k]=new WProjectFT(static_cast<WProjectFT &>(*ft_)); iftm_p[k]=new WProjectFT(static_cast<WProjectFT &>(*ift_)); // Give each pair of FTMachine a convolution function set to share @@ -171,7 +174,7 @@ void LofarCubeSkyEquation::init(FTMachine& ft){ iftm_p[0]=ift_; if(nmod != (2 * sm_->numberOfTaylorTerms() - 1)) /* MFS */ throw(AipsError("No multifield with pb-projection allowed")); - for (Int k=1; k < (nmod); ++k){ + for (Int k=1; k < (nmod); ++k){ ftm_p[k]=new nPBWProjectFT(static_cast<nPBWProjectFT &>(*ft_)); iftm_p[k]=new nPBWProjectFT(static_cast<nPBWProjectFT &>(*ift_)); } @@ -184,7 +187,7 @@ void LofarCubeSkyEquation::init(FTMachine& ft){ iftm_p[0]=ift_; if(nmod != (2 * sm_->numberOfTaylorTerms() - 1)) /* MFS */ throw(AipsError("No multifield with a-projection allowed")); - for (Int k=1; k < (nmod); ++k){ + for (Int k=1; k < (nmod); ++k){ ftm_p[k]=new AWProjectFT(static_cast<AWProjectFT &>(*ft_)); iftm_p[k]=new AWProjectFT(static_cast<AWProjectFT &>(*ift_)); // iftm_p[k]=ftm_p[k]; @@ -198,10 +201,10 @@ void LofarCubeSkyEquation::init(FTMachine& ft){ iftm_p[0]=ift_; // if(nmod != (2 * sm_->numberOfTaylorTerms() - 1)) /* MFS */ // throw(AipsError("No multifield with a-projection allowed")); - for (Int k=1; k < (nmod); ++k){ + for (Int k=1; k < (nmod); ++k){ ftm_p[k]=new AWProjectWBFT(static_cast<AWProjectWBFT &>(*ft_)); iftm_p[k]=new AWProjectWBFT(static_cast<AWProjectWBFT &>(*ift_)); - if(sm_->numberOfTaylorTerms()>1) + if(sm_->numberOfTaylorTerms()>1) { for (Int model=0; model < (sm_->numberOfModels()) ; ++model) { @@ -221,7 +224,7 @@ void LofarCubeSkyEquation::init(FTMachine& ft){ iftm_p[0]=ift_; if(nmod != (2 * sm_->numberOfTaylorTerms() - 1)) /* MFS */ throw(AipsError("No multifield with pb-mosaic allowed")); - for (Int k=1; k < (nmod); ++k){ + for (Int k=1; k < (nmod); ++k){ ftm_p[k]=new PBMosaicFT(static_cast<PBMosaicFT &>(*ft_)); iftm_p[k]=new PBMosaicFT(static_cast<PBMosaicFT &>(*ift_)); } @@ -232,7 +235,7 @@ void LofarCubeSkyEquation::init(FTMachine& ft){ // ftm_p[0]=CountedPtr<FTMachine>(ft_, False); ftm_p[0]=ft_; iftm_p[0]=ift_; - for (Int k=1; k < (nmod); ++k){ + for (Int k=1; k < (nmod); ++k){ ftm_p[k]=new rGridFT(static_cast<rGridFT &>(*ft_)); iftm_p[k]=new rGridFT(static_cast<rGridFT &>(*ift_)); } @@ -242,11 +245,11 @@ void LofarCubeSkyEquation::init(FTMachine& ft){ ift_=new MultiTermFT(static_cast<MultiTermFT &>(ft)); ftm_p[0]=ft_; iftm_p[0]=ift_; - for (Int k=1; k < (nmod); ++k){ + for (Int k=1; k < (nmod); ++k){ ftm_p[k]=new MultiTermFT(static_cast<MultiTermFT &>(*ft_)); iftm_p[k]=new MultiTermFT(static_cast<MultiTermFT &>(*ift_)); } - for (Int k=0; k < (nmod); ++k){ + for (Int k=0; k < (nmod); ++k){ ftm_p[k]->setMiscInfo(sm_->getTaylorIndex(k)); iftm_p[k]->setMiscInfo(sm_->getTaylorIndex(k)); } @@ -257,13 +260,30 @@ void LofarCubeSkyEquation::init(FTMachine& ft){ // ift_=ft_; ftm_p[0]=ft_; iftm_p[0]=ift_; - if(nmod != (2 * sm_->numberOfTaylorTerms() - 1)) /* MFS */ - throw(AipsError("No multifield with a-projection allowed")); - for (Int k=1; k < (nmod); ++k){ + ftm_p[0]->setMiscInfo(0); + iftm_p[0]->setMiscInfo(0); + cout<<"nmod="<<nmod<<endl; + //if(nmod != (2 * sm_->numberOfTaylorTerms() - 1)) /* MFS */ + // throw(AipsError("No multifield with a-projection allowed")); + for (Int k=1; k < (nmod); ++k){ ftm_p[k]=new LOFAR::LofarFTMachine(static_cast<LOFAR::LofarFTMachine &>(*ft_)); iftm_p[k]=new LOFAR::LofarFTMachine(static_cast<LOFAR::LofarFTMachine &>(*ift_)); + // test MSMFT for LOFAR + ftm_p[k]->setMiscInfo(0);//sm_->getTaylorIndex(k)); + iftm_p[k]->setMiscInfo(0);//sm_->getTaylorIndex(k)); + + } + // if(sm_->numberOfTaylorTerms()>1) + // { + // for (Int model=0; model < (sm_->numberOfModels()) ; ++model) + // { + // ftm_p[model]->setMiscInfo(sm_->getTaylorIndex(model)); + // iftm_p[model]->setMiscInfo(sm_->getTaylorIndex(model)); + + // } + // } // iftm_p[k]=ftm_p[k]; - } + //} } else { ft_=new GridFT(static_cast<GridFT &>(ft)); @@ -271,7 +291,7 @@ void LofarCubeSkyEquation::init(FTMachine& ft){ // ftm_p[0]=CountedPtr<FTMachine>(ft_, False); ftm_p[0]=ft_; iftm_p[0]=ift_; - for (Int k=1; k < (nmod); ++k){ + for (Int k=1; k < (nmod); ++k){ ftm_p[k]=new GridFT(static_cast<GridFT &>(*ft_)); iftm_p[k]=new GridFT(static_cast<GridFT &>(*ift_)); } @@ -284,7 +304,7 @@ void LofarCubeSkyEquation::init(FTMachine& ft){ } LofarCubeSkyEquation::~LofarCubeSkyEquation(){ - //As we make an explicit ift_ in the constructor we need + //As we make an explicit ift_ in the constructor we need //to take care of it here... //if(ift_ && (ift_ != ft_)) // delete ift_; @@ -300,7 +320,7 @@ void LofarCubeSkyEquation::predict(Bool incremental, MS::PredefinedColumns col) VisibilityIterator::DataColumn visCol=VisibilityIterator::Model; if(col==MS::DATA){ visCol=VisibilityIterator::Observed; - } + } if(col==MS::CORRECTED_DATA){ visCol=VisibilityIterator::Corrected; } @@ -310,7 +330,7 @@ void LofarCubeSkyEquation::predict(Bool incremental, MS::PredefinedColumns col) if(sm_->numberOfModels()!= 0) AlwaysAssert(ok(),AipsError); if(noModelCol_p) throw(AipsError("Cannot predict visibilities without using scratch columns yet")); - // Initialize + // Initialize VisIter& vi=*wvi_p; //Lets get the channel selection for later use vi.getChannelSelection(blockNumChanGroup_p, blockChanStart_p, @@ -323,16 +343,16 @@ void LofarCubeSkyEquation::predict(Bool incremental, MS::PredefinedColumns col) Bool initialized=False; predictComponents(incremental, initialized); //set to zero then loop over model...check for size...subimage then loop over subimages - - + + Bool isEmpty=True; for (Int model=0; model < (sm_->numberOfModels());++model){ - isEmpty=isEmpty && (sm_->isEmpty(model)); - + isEmpty=isEmpty && (sm_->isEmpty(model)); + } - - - if( (sm_->numberOfModels() >0) && isEmpty && !initialized && !incremental){ + + + if( (sm_->numberOfModels() >0) && isEmpty && !initialized && !incremental){ // We are at the begining with an empty model as starting point for (vi.originChunks();vi.moreChunks();vi.nextChunk()) { for (vi.origin(); vi.more(); vi++) { @@ -341,15 +361,15 @@ void LofarCubeSkyEquation::predict(Bool incremental, MS::PredefinedColumns col) } } } - + //If all model is zero...no need to continue - if(isEmpty) + if(isEmpty) return; - - - + + + // Now do the images - for (Int model=0; model < (sm_->numberOfModels());++model){ + for (Int model=0; model < (sm_->numberOfModels());++model){ // Change the model polarization frame if(vb->polFrame()==MSIter::Linear) { StokesImageUtil::changeCStokesRep(sm_->cImage(model), @@ -389,22 +409,22 @@ void LofarCubeSkyEquation::predict(Bool incremental, MS::PredefinedColumns col) finalizeGetSlice(); if(!incremental&&!initialized) initialized=True; } - + for(Int model=0; model < sm_->numberOfModels(); ++model){ //For now unscale test on name of ft_ ft_=&(*ftm_p[model]); unScaleImage(model, incremental); } ft_=&(*ftm_p[0]); - + //lets return original selection back to iterator if(changedVI) - vi.selectChannel(blockNumChanGroup_p, blockChanStart_p, - blockChanWidth_p, blockChanInc_p, blockSpw_p); - + vi.selectChannel(blockNumChanGroup_p, blockChanStart_p, + blockChanWidth_p, blockChanInc_p, blockSpw_p); + } -void LofarCubeSkyEquation::makeApproxPSF(PtrBlock<TempImage<Float> * >& psfs) +void LofarCubeSkyEquation::makeApproxPSF(PtrBlock<TempImage<Float> * >& psfs) { if(iftm_p[0]->name()=="MosaicFT") @@ -451,7 +471,7 @@ void LofarCubeSkyEquation::makeMosaicPSF(PtrBlock<TempImage<Float> * >& psfs){ planeMax = LEN.getFloat(); if( (planeMax >0.0) && (planeMax < 0.8 *peak)){ psfSub.put(goodplane); - + } } } @@ -480,6 +500,17 @@ void LofarCubeSkyEquation::makeMosaicPSF(PtrBlock<TempImage<Float> * >& psfs){ void LofarCubeSkyEquation::makeSimplePSF(PtrBlock<TempImage<Float> * >& psfs) { + // PrecTimer TimerCyril; + // TimerCyril.start(); + +// cout<<"psfs[0].name() "<<psfs[0]->name()<<endl; +//File myFile("Cube_dirty.img"+String::toString(count_cycle)); +// if(!myFile.exists()){ +// } + + + + Int nmodels=psfs.nelements(); LogIO os(LogOrigin("LofarCubeSkyEquation", "makeSimplePSF")); ft_->setNoPadding(noModelCol_p); @@ -499,6 +530,11 @@ void LofarCubeSkyEquation::makeSimplePSF(PtrBlock<TempImage<Float> * >& psfs) { VisBufferAutoPtr vb (vi); vi.originChunks(); vi.origin(); + // TimerCyril.stop(); + // TimerCyril.show(cout,"1"); + // TimerCyril.reset(); + // TimerCyril.start(); + // Change the model polarization frame for (Int model=0; model < nmodels; ++model){ if(vb->polFrame()==MSIter::Linear) { @@ -514,6 +550,10 @@ void LofarCubeSkyEquation::makeSimplePSF(PtrBlock<TempImage<Float> * >& psfs) { Int nCubeSlice=1; isLargeCube(sm_->cImage(0), nCubeSlice); + // TimerCyril.stop(); + // TimerCyril.show(cout,"2"); + // TimerCyril.reset(); + // TimerCyril.start(); for (Int cubeSlice=0; cubeSlice< nCubeSlice; ++cubeSlice){ changedVI= getFreqRange(vi, sm_->cImage(0).coordinates(), cubeSlice, nCubeSlice) || changedVI; @@ -527,8 +567,16 @@ void LofarCubeSkyEquation::makeSimplePSF(PtrBlock<TempImage<Float> * >& psfs) { initializePutSlice(* vb, cubeSlice, nCubeSlice); + // TimerCyril.stop(); + // TimerCyril.show(cout,"3"); + // TimerCyril.reset(); + // TimerCyril.start(); for (vi.originChunks();vi.moreChunks();vi.nextChunk()) { for (vi.origin(); vi.more(); vi++) { + // TimerCyril.stop(); + // TimerCyril.show(cout,"4a"); + // TimerCyril.reset(); + // TimerCyril.start(); if(noModelCol_p) { //This here forces the modelVisCube shape and prevents reading model column vb->setModelVisCube(Complex(0.0,0.0)); @@ -537,12 +585,16 @@ void LofarCubeSkyEquation::makeSimplePSF(PtrBlock<TempImage<Float> * >& psfs) { cohDone+=vb->nRow(); pm.update(Double(cohDone)); + // TimerCyril.stop(); + // TimerCyril.show(cout,"4b"); + // TimerCyril.reset(); + // TimerCyril.start(); } } finalizePutSlice(* vb, cubeSlice, nCubeSlice); } - //lets return original selection back to iterator + //lets return original selection back to iterator if(changedVI) @@ -552,6 +604,10 @@ void LofarCubeSkyEquation::makeSimplePSF(PtrBlock<TempImage<Float> * >& psfs) { fixImageScale(); for(Int model=0; model < nmodels; ++model){ { + // TimerCyril.stop(); + // TimerCyril.show(cout,"5a"); + // TimerCyril.reset(); + // TimerCyril.start(); //Normalize the gS image Int nXX=sm_->ggS(model).shape()(0); Int nYY=sm_->ggS(model).shape()(1); @@ -561,6 +617,10 @@ void LofarCubeSkyEquation::makeSimplePSF(PtrBlock<TempImage<Float> * >& psfs) { IPosition trc(4, nXX, nYY, npola, nchana); blc(0)=0; blc(1)=0; trc(0)=nXX-1; trc(1)=nYY-1; //max weights per plane + // TimerCyril.stop(); + // TimerCyril.show(cout,"5b"); + // TimerCyril.reset(); + // TimerCyril.start(); for (Int j=0; j < npola; ++j){ for (Int k=0; k < nchana ; ++k){ @@ -583,40 +643,119 @@ void LofarCubeSkyEquation::makeSimplePSF(PtrBlock<TempImage<Float> * >& psfs) { } } } + // TimerCyril.stop(); + // TimerCyril.show(cout,"6"); + // TimerCyril.reset(); + // TimerCyril.start(); // } + //PtrBlock<TempImage<Float> * >& psfs + + + // Cyril: Gets the PSF from disk + // String nameii("PSF.keep"); + // ostringstream nameiii(nameii); + // PagedImage<Float> tmpi(nameiii.str().c_str()); + // Slicer slicei(IPosition(4,0,0,0,0), tmpi.shape(), IPosition(4,1,1,1,1)); + // Array<Float> PSF_Disk; + // tmpi.doGetSlice(PSF_Disk, slicei); + // CountedPtr<Lattice<Float> > PSF_Lattice; + // PSF_Lattice = new ArrayLattice<Float>(PSF_Disk); + // SubImage<Float> psfSub(*(psfs[0]), slicei, True); + // psfSub.copyData(*PSF_Lattice); + /* if(0){ PagedImage<Float> thisScreen(psfs[model]->shape(), psfs[model]->coordinates(), String("ELPSF).psf")); LatticeExpr<Float> le(*psfs[model]); thisScreen.copyData(le); - } + } */ - LatticeExprNode maxPSF=max(*psfs[model]); - Float maxpsf=maxPSF.getFloat(); - if(abs(maxpsf-1.0) > 1e-3) { - os << "Maximum of approximate PSF for field " << model << " = " - << maxpsf << " : renormalizing to unity" << LogIO::POST; - } - if(maxpsf > 0.0 ){ - LatticeExpr<Float> len((*psfs[model])/maxpsf); - psfs[model]->copyData(len); - } - else{ - if(sm_->numberOfTaylorTerms()>1) { /* MFS */ - os << "PSF calculation resulted in a PSF with its peak being 0 or less. This is ok for MS-MFS." << LogIO::POST; - } - else{ - throw(PSFZero("SkyEquation:: PSF calculation resulted in a PSF with its peak being 0 or less!")); - } - } + + //=============================================== + //Cyril: For MF cleaning, Itry take this of + //=============================================== + // LatticeExprNode maxPSF=max(*psfs[model]); + // Float maxpsf=maxPSF.getFloat(); + // if(abs(maxpsf-1.0) > 1e-3) { + // os << "Maximum of approximate PSF for field " << model << " = " + // << maxpsf << " : renormalizing to unity" << LogIO::POST; + // } + // if(maxpsf > 0.0 ){ + // LatticeExpr<Float> len((*psfs[model])/maxpsf); + // psfs[model]->copyData(len); + // } + // else{ + // if(sm_->numberOfTaylorTerms()>1) { /* MFS */ + // os << "PSF calculation resulted in a PSF with its peak being 0 or less. This is ok for MS-MFS." << LogIO::POST; + // } + // else{ + // throw(PSFZero("SkyEquation:: PSF calculation resulted in a PSF with its peak being 0 or less!")); + // } + // } + //=============================================== + + + } isPSFWork_p=False; // resetting this flag so that subsequent calculation uses // the right SkyJones correction; } + + + +// //============================ ADDED by Cyril + +// void LofarCubeSkyEquation::setExistingPSF(PtrBlock<TempImage<Float> * >& psfs) { + +// Int nmodels=psfs.nelements(); +// String FileName("test.img.psf"); +// PagedImage<Float> myimage (FileName); +// for(Int model=0; model < nmodels; ++model){ +// { +// Int nXX=sm_->ggS(model).shape()(0); +// Int nYY=sm_->ggS(model).shape()(1); +// Int npola= sm_->ggS(model).shape()(2); +// Int nchana= sm_->ggS(model).shape()(3); +// IPosition blc(4,nXX, nYY, npola, nchana); +// IPosition trc(4, nXX, nYY, npola, nchana); +// blc(0)=0; blc(1)=0; trc(0)=nXX-1; trc(1)=nYY-1; +// for (Int j=0; j < npola; ++j){ +// for (Int k=0; k < nchana ; ++k){ + +// blc(2)=j; trc(2)=j; +// blc(3)=k; trc(3)=k; +// Slicer sl(blc, trc, Slicer::endIsLast); +// SubImage<Float> gSSub(sm_->gS(model), sl, False); +// SubImage<Float> ggSSub(sm_->ggS(model), sl, False); +// SubImage<Float> psfSub(*(psfs[model]), sl, True); +// Float planeMax; +// LatticeExprNode LEN = max( ggSSub ); +// planeMax = LEN.getFloat(); +// if(planeMax !=0){ +// psfSub.copyData( (LatticeExpr<Float>) +// (iif(ggSSub > (0.0), +// (gSSub/planeMax),0.0))); +// } +// else{ +// psfSub.set(0.0); +// } +// } +// } + +// } + +// isPSFWork_p=False; +// } + +// // ======================== END added by Cyril + + + + void LofarCubeSkyEquation::gradientsChiSquared(Bool /*incr*/, Bool commitModel){ @@ -687,9 +826,9 @@ void LofarCubeSkyEquation::gradientsChiSquared(Bool /*incr*/, Bool commitModel){ checkVisIterNumRows(*rvi_p); VisBufferAutoPtr vb (rvi_p); // Timers tVisAutoPtr=Timers::getTime(); - + /**** Do we need to do this - if( (sm_->isEmpty(0)) && !initialized && !incremental){ + if( (sm_->isEmpty(0)) && !initialized && !incremental){ // We are at the begining with an empty model as starting point for (vi.originChunks();vi.moreChunks();vi.nextChunk()) { for (vi.origin(); vi.more(); vi++) { @@ -777,11 +916,12 @@ void LofarCubeSkyEquation::gradientsChiSquared(Bool /*incr*/, Bool commitModel){ for (rvi_p->origin(); rvi_p->more(); (*rvi_p)++) { // Timers tInitModel=Timers::getTime(); + if(!incremental && !predictedComp) { //This here forces the modelVisCube shape and prevents reading model column vb->setModelVisCube(Complex(0.0,0.0)); } - // get the model visibility and write it to the model MS + // get the model visibility and write it to the model MS // Timers tGetSlice=Timers::getTime(); // Timers tgetSlice=Timers::getTime(); if(!isEmpty) @@ -794,7 +934,7 @@ void LofarCubeSkyEquation::gradientsChiSquared(Bool /*incr*/, Bool commitModel){ // Now lets grid the -ve of residual // use visCube if there is no correctedData // Timers tGetRes=Timers::getTime(); - + if(!iftm_p[0]->canComputeResiduals()){ cout<<"CANNOT!!!!"<<endl; if(!useCorrected) vb->modelVisCube()-=vb->visCube(); @@ -805,10 +945,11 @@ void LofarCubeSkyEquation::gradientsChiSquared(Bool /*incr*/, Bool commitModel){ // Timers tPutSlice = Timers::getTime(); //putSlice(* vb, False, FTMachine::MODEL, cubeSlice, nCubeSlice); - putSlice(* vb, False, FTMachine::MODEL, cubeSlice, nCubeSlice); + putSlice(* vb, False, FTMachine::MODEL, cubeSlice, nCubeSlice); cohDone+=vb->nRow(); pm.update(Double(cohDone)); + // Timers tDoneGridding=Timers::getTime(); // aInitModel += tgetSlice - tInitModel; // aGetSlice += tsetModel - tgetSlice; @@ -825,7 +966,7 @@ void LofarCubeSkyEquation::gradientsChiSquared(Bool /*incr*/, Bool commitModel){ // Timers tFinalizePutSlice=Timers::getTime(); finalizePutSlice(* vb, cubeSlice, nCubeSlice); // Timers tDoneFinalizePutSlice=Timers::getTime(); - + // aFinalizeGetSlice += tFinalizePutSlice - tFinalizeGetSlice; // aFinalizePutSlice += tDoneFinalizePutSlice - tFinalizePutSlice; } @@ -853,31 +994,31 @@ void LofarCubeSkyEquation::gradientsChiSquared(Bool /*incr*/, Bool commitModel){ rvi_p = oldRvi; // make the old vi the current vi } // cerr << "gradChiSq: " - // << "InitGrad = " << aInitGrad.formatAverage().c_str() << " " - // << "GetChanSel = " << aGetChanSel.formatAverage().c_str() << " " - // << "ChangeStokes = " << aChangeStokes.formatAverage().c_str() << " " - // << "CheckVisRows = " << aCheckVisRows.formatAverage().c_str() << " " - // << "GetFreq = " << aGetFreq.formatAverage().c_str() << " " - // << "OrigChunks = " << aOrigChunks.formatAverage().c_str() << " " - // << "VBInValid = " << aVBInValid.formatAverage().c_str() << " " - // << "InitGetSlice = " << aInitGetSlice.formatAverage().c_str() << " " - // << "InitPutSlice = " << aInitPutSlice.formatAverage().c_str() << " " - // << "PutSlice = " << aPutSlice.formatAverage().c_str() << " " - // << "FinalGetSlice = " << aFinalizeGetSlice.formatAverage().c_str() << " " - // << "FinalPutSlice = " << aFinalizePutSlice.formatAverage().c_str() << " " + // << "InitGrad = " << aInitGrad.formatAverage().c_str() << " " + // << "GetChanSel = " << aGetChanSel.formatAverage().c_str() << " " + // << "ChangeStokes = " << aChangeStokes.formatAverage().c_str() << " " + // << "CheckVisRows = " << aCheckVisRows.formatAverage().c_str() << " " + // << "GetFreq = " << aGetFreq.formatAverage().c_str() << " " + // << "OrigChunks = " << aOrigChunks.formatAverage().c_str() << " " + // << "VBInValid = " << aVBInValid.formatAverage().c_str() << " " + // << "InitGetSlice = " << aInitGetSlice.formatAverage().c_str() << " " + // << "InitPutSlice = " << aInitPutSlice.formatAverage().c_str() << " " + // << "PutSlice = " << aPutSlice.formatAverage().c_str() << " " + // << "FinalGetSlice = " << aFinalizeGetSlice.formatAverage().c_str() << " " + // << "FinalPutSlice = " << aFinalizePutSlice.formatAverage().c_str() << " " // << endl; - - // cerr << "VB loop: " - // << "InitModel = " << aInitModel.formatAverage().c_str() << " " - // << "GetSlice = " << aGetSlice.formatAverage().c_str() << " " - // << "SetModel = " << aSetModel.formatAverage().c_str() << " " - // << "GetRes = " << aGetRes.formatAverage().c_str() << " " - // << "PutSlice = " << aPutSlice.formatAverage().c_str() << " " - // << "Extra = " << aExtra.formatAverage().c_str() << " " + + // cerr << "VB loop: " + // << "InitModel = " << aInitModel.formatAverage().c_str() << " " + // << "GetSlice = " << aGetSlice.formatAverage().c_str() << " " + // << "SetModel = " << aSetModel.formatAverage().c_str() << " " + // << "GetRes = " << aGetRes.formatAverage().c_str() << " " + // << "PutSlice = " << aPutSlice.formatAverage().c_str() << " " + // << "Extra = " << aExtra.formatAverage().c_str() << " " // << endl; } -void LofarCubeSkyEquation::isLargeCube(ImageInterface<Complex>& theIm, +void LofarCubeSkyEquation::isLargeCube(ImageInterface<Complex>& theIm, Int& nslice) { //non-cube @@ -896,7 +1037,7 @@ void LofarCubeSkyEquation::isLargeCube(ImageInterface<Complex>& theIm, if(memtot < 512000){ ostringstream oss; oss << "The amount of memory reported " << memtot << " kB is too small to work with" << endl; - throw(AipsError(String(oss))); + throw(AipsError(String(oss))); } Long pixInMem=(memtot/8)*1024; @@ -923,9 +1064,10 @@ void LofarCubeSkyEquation::isLargeCube(ImageInterface<Complex>& theIm, } } -void LofarCubeSkyEquation::initializePutSlice(const VisBuffer& vb, +void LofarCubeSkyEquation::initializePutSlice(const VisBuffer& vb, Int cubeSlice, Int nCubeSlice) { + AlwaysAssert(ok(),AipsError); Bool dirDep= (ej_ != NULL); for(Int model=0; model < (sm_->numberOfModels()) ; ++model){ @@ -960,7 +1102,7 @@ LofarCubeSkyEquation::putSlice(VisBuffer & vb, Bool dopsf, FTMachine::Type col, firstOneChangesPut_p=False; // Has this VB changed from the previous one? if((ftm_p[0]->name() != "MosaicFT") && (ftm_p[0]->name() != "PBWProjectFT") && (ftm_p[0]->name() != "AWProjectFT") && (ftm_p[0]->name() != "AWProjectWBFT") && - (ftm_p[0]->name() != "LofarFTMachine") ) + (ftm_p[0]->name() != "LofarFTMachine") ) { changedSkyJonesLogic(vb, firstOneChangesPut_p, internalChangesPut_p); } @@ -988,6 +1130,7 @@ LofarCubeSkyEquation::putSlice(VisBuffer & vb, Bool dopsf, FTMachine::Type col, } for (Int model=0; model<sm_->numberOfModels(); ++model){ + // cout<<"model = "<<model<<endl; iftm_p[model]->put(vb, row, dopsf, col); } } @@ -1003,11 +1146,13 @@ LofarCubeSkyEquation::putSlice(VisBuffer & vb, Bool dopsf, FTMachine::Type col, initializePutSlice(vb, cubeSlice, nCubeSlice); isBeginingOfSkyJonesCache_p=False; for (Int model=0; model<sm_->numberOfModels(); ++model){ + //cout<<"modelb = "<<model<<endl; iftm_p[model]->put(vb, -1, dopsf, col); } } else { for (Int model=0; model<sm_->numberOfModels(); ++model){ + // cout<<"modelc = "<<model<<endl; iftm_p[model]->put(vb, -1, dopsf, col); } } @@ -1016,7 +1161,7 @@ LofarCubeSkyEquation::putSlice(VisBuffer & vb, Bool dopsf, FTMachine::Type col, } -void LofarCubeSkyEquation::finalizePutSlice(const VisBuffer& vb, +void LofarCubeSkyEquation::finalizePutSlice(const VisBuffer& vb, Int cubeSlice, Int nCubeSlice) { for (Int model=0; model < sm_->numberOfModels(); ++model){ //the different apply...jones use ft_ and ift_ @@ -1024,11 +1169,11 @@ void LofarCubeSkyEquation::finalizePutSlice(const VisBuffer& vb, ift_=&(*iftm_p[model]); // Actually do the transform. Update weights as we do so. iftm_p[model]->finalizeToSky(); - // 1. Now get the (unnormalized) image and add the + // 1. Now get the (unnormalized) image and add the // weight to the summed weight Matrix<Float> delta; imPutSlice_p[model]->copyData(iftm_p[model]->getImage(delta, False)); - + @@ -1052,11 +1197,11 @@ void LofarCubeSkyEquation::finalizePutSlice(const VisBuffer& vb, *gSSlice); SubImage<Float> *ggSSlice; sliceCube(ggSSlice, sm_->ggS(model), cubeSlice, nCubeSlice); - + // 3. Apply the square of the SkyJones and add this to gradgrad chisquared applySkyJonesSquare(vb, -1, weightSlice_p[model], *workSlice, *ggSSlice); - + delete workSlice; delete gSSlice; @@ -1068,9 +1213,9 @@ void LofarCubeSkyEquation::finalizePutSlice(const VisBuffer& vb, sm_->addStatistics(sumwt, chisq); } -void LofarCubeSkyEquation::initializeGetSlice(const VisBuffer& vb, - Int row, - Bool incremental, Int cubeSlice, +void LofarCubeSkyEquation::initializeGetSlice(const VisBuffer& vb, + Int row, + Bool incremental, Int cubeSlice, Int nCubeSlice){ imGetSlice_p.resize(sm_->numberOfModels(), True, False); for(Int model=0; model < sm_->numberOfModels(); ++model){ @@ -1090,11 +1235,11 @@ void LofarCubeSkyEquation::initializeGetSlice(const VisBuffer& vb, } ft_=&(*ftm_p[0]); ift_=&(*iftm_p[0]); - + } -void LofarCubeSkyEquation::sliceCube(CountedPtr<ImageInterface<Complex> >& slice,Int model, Int cubeSlice, +void LofarCubeSkyEquation::sliceCube(CountedPtr<ImageInterface<Complex> >& slice,Int model, Int cubeSlice, Int nCubeSlice, Int typeOfSlice){ IPosition blc(4,0,0,0,0); @@ -1110,8 +1255,8 @@ void LofarCubeSkyEquation::sliceCube(CountedPtr<ImageInterface<Complex> >& slice sl_p=Slicer (blc, trc, Slicer::endIsLast); SubImage<Complex>* sliceIm= new SubImage<Complex>(sm_->cImage(model), sl_p, False); // cerr << "SliceCube: " << beginChannel << " " << endChannel << endl; - if(typeOfSlice==0){ - + if(typeOfSlice==0){ + Double memoryMB=HostInfo::memoryTotal(true)/1024.0/(8.0*(sm_->numberOfModels())); slice=new TempImage<Complex> (sliceIm->shape(), sliceIm->coordinates(), memoryMB); //slice.copyData(sliceIm); @@ -1126,7 +1271,7 @@ void LofarCubeSkyEquation::sliceCube(CountedPtr<ImageInterface<Complex> >& slice } void LofarCubeSkyEquation::sliceCube(SubImage<Float>*& slice, - ImageInterface<Float>& image, Int cubeSlice, + ImageInterface<Float>& image, Int cubeSlice, Int nCubeSlice){ IPosition blc(4,0,0,0,0); IPosition trc(4,image.shape()(0)-1, @@ -1143,7 +1288,7 @@ void LofarCubeSkyEquation::sliceCube(SubImage<Float>*& slice, slice= new SubImage<Float> (image, sl_p, True); } -VisBuffer& LofarCubeSkyEquation::getSlice(VisBuffer& result, +VisBuffer& LofarCubeSkyEquation::getSlice(VisBuffer& result, Bool incremental, Int cubeSlice, Int nCubeSlice) { @@ -1175,7 +1320,7 @@ VisBuffer& LofarCubeSkyEquation::getSlice(VisBuffer& result, Matrix<Complex> refvb; for (Int row=0; row<nRow; row++) { finalizeGetSlice(); - initializeGetSlice(result, row, False, cubeSlice, + initializeGetSlice(result, row, False, cubeSlice, nCubeSlice); if(incremental || (nmodels > 1)){ for (Int model=0; model < nmodels; ++model){ @@ -1228,6 +1373,7 @@ LofarCubeSkyEquation::finalizeGetSlice(){ // ftm_p[model]->finalizeToVis(); } + Bool LofarCubeSkyEquation::getFreqRange(ROVisibilityIterator& vi, const CoordinateSystem& coords, @@ -1259,7 +1405,7 @@ LofarCubeSkyEquation::getFreqRange(ROVisibilityIterator& vi, if(nslice==1) return False; - Double start=0.0; + Double start=0.0; Double end=0.0; Double chanwidth=1.0; Int specIndex=coords.findCoordinate(Coordinate::SPECTRAL); @@ -1286,8 +1432,8 @@ LofarCubeSkyEquation::getFreqRange(ROVisibilityIterator& vi, if(spwb.nelements()==0) return False; - //vi.selectChannel(1, startb[0][0], nchanb[0][0], 1, spwb[0][0]); - vi.selectChannel(blockNumChanGroup_p, startb, nchanb, incrb, spwb); + //vi.selectChannel(1, startb[0][0], nchanb[0][0], 1, spwb[0][0]); + vi.selectChannel(blockNumChanGroup_p, startb, nchanb, incrb, spwb); return True; @@ -1298,27 +1444,27 @@ void LofarCubeSkyEquation::fixImageScale() LogIO os(LogOrigin("LofarCubeSkyEquation", "fixImageScale")); // make a minimum value to ggS - // This has the same effect as Sault Weighting, but + // This has the same effect as Sault Weighting, but // is implemented somewhat differently. // We also keep the fluxScale(mod) images around to // undo the weighting. Float ggSMax=0.0; for (Int model=0;model<sm_->numberOfModels();model++) { - + LatticeExprNode LEN = max( sm_->ggS(model) ); ggSMax = max(ggSMax,LEN.getFloat()); } ggSMax_p=ggSMax; Float ggSMin1; Float ggSMin2; - + ggSMin1 = ggSMax * constPB_p * constPB_p; ggSMin2 = ggSMax * minPB_p * minPB_p; - + for (Int model=0;model<sm_->numberOfModels();model++) { if(ej_ || (ftm_p[model]->name() == "MosaicFT") ) { - - + + /*Don't print this for now if (scaleType_p == "SAULT") { @@ -1331,7 +1477,7 @@ void LofarCubeSkyEquation::fixImageScale() sm_->fluxScale(model).removeRegion ("mask0", RegionHandler::Any, False); if ((ftm_p[model]->name()!="MosaicFT")) { if(scaleType_p=="SAULT"){ - + // Adjust flux scale to account for ggS being truncated at ggSMin1 // Below ggSMin2, set flux scale to 0.0 // FluxScale * image => true brightness distribution, but @@ -1339,47 +1485,47 @@ void LofarCubeSkyEquation::fixImageScale() // if ggS < ggSMin2, set to Zero; // if ggS > ggSMin2 && < ggSMin1, set to ggSMin1/ggS // if ggS > ggSMin1, set to 1.0 - - sm_->fluxScale(model).copyData( (LatticeExpr<Float>) + + sm_->fluxScale(model).copyData( (LatticeExpr<Float>) (iif(sm_->ggS(model) < (ggSMin2), 0.0, sqrt((sm_->ggS(model))/ggSMin1) )) ); - sm_->fluxScale(model).copyData( (LatticeExpr<Float>) + sm_->fluxScale(model).copyData( (LatticeExpr<Float>) (iif(sm_->ggS(model) > (ggSMin1), 1.0, (sm_->fluxScale(model)) )) ); // truncate ggS at ggSMin1 - sm_->ggS(model).copyData( (LatticeExpr<Float>) - (iif(sm_->ggS(model) < (ggSMin1), ggSMin1*(sm_->fluxScale(model)), + sm_->ggS(model).copyData( (LatticeExpr<Float>) + (iif(sm_->ggS(model) < (ggSMin1), ggSMin1*(sm_->fluxScale(model)), sm_->ggS(model)) ) ); - + } else{ - sm_->fluxScale(model).copyData( (LatticeExpr<Float>) + sm_->fluxScale(model).copyData( (LatticeExpr<Float>) (iif(sm_->ggS(model) < (ggSMin2), 0.0, sqrt((sm_->ggS(model))/ggSMax) )) ); - sm_->ggS(model).copyData( (LatticeExpr<Float>) + sm_->ggS(model).copyData( (LatticeExpr<Float>) (iif(sm_->ggS(model) < (ggSMin2), 0.0, sqrt((sm_->ggS(model))*ggSMax) )) ); } } else { - + Int nXX=sm_->ggS(model).shape()(0); Int nYY=sm_->ggS(model).shape()(1); Int npola= sm_->ggS(model).shape()(2); Int nchana= sm_->ggS(model).shape()(3); IPosition blc(4,nXX, nYY, npola, nchana); IPosition trc(4, nXX, nYY, npola, nchana); - blc(0)=0; blc(1)=0; trc(0)=nXX-1; trc(1)=nYY-1; + blc(0)=0; blc(1)=0; trc(0)=nXX-1; trc(1)=nYY-1; - //Those damn weights per plane can be wildly different so + //Those damn weights per plane can be wildly different so //deal with it properly here for (Int j=0; j < npola; ++j){ for (Int k=0; k < nchana ; ++k){ - + blc(2)=j; trc(2)=j; blc(3)=k; trc(3)=k; Slicer sl(blc, trc, Slicer::endIsLast); @@ -1399,49 +1545,49 @@ void LofarCubeSkyEquation::fixImageScale() ///lets be conservative and go to 1% of ggsMin2 if(planeMax !=0){ if(doflat_p){ - fscalesub.copyData( (LatticeExpr<Float>) - (iif(ggSSub < (ggSMin2/100.0), + fscalesub.copyData( (LatticeExpr<Float>) + (iif(ggSSub < (ggSMin2/100.0), 0.0, sqrt(ggSSub/planeMax)))); - ggSSub.copyData( (LatticeExpr<Float>) - (iif(ggSSub < (ggSMin2/100.0), 0.0, + ggSSub.copyData( (LatticeExpr<Float>) + (iif(ggSSub < (ggSMin2/100.0), 0.0, sqrt(planeMax*ggSSub)))); } else{ - fscalesub.copyData( (LatticeExpr<Float>) - (iif(ggSSub < (ggSMin2/100.0), + fscalesub.copyData( (LatticeExpr<Float>) + (iif(ggSSub < (ggSMin2/100.0), 0.0, (ggSSub/planeMax)))); - ggSSub.copyData( (LatticeExpr<Float>) - (iif(ggSSub < (ggSMin2/100.0), 0.0, + ggSSub.copyData( (LatticeExpr<Float>) + (iif(ggSSub < (ggSMin2/100.0), 0.0, (planeMax)))); } - //ggSSub.copyData( (LatticeExpr<Float>) - // (iif(ggSSub < (ggSMin2/100.0), 0.0, + //ggSSub.copyData( (LatticeExpr<Float>) + // (iif(ggSSub < (ggSMin2/100.0), 0.0, // planeMax))); - + } } } /* - + ftm_p[model]->getFluxImage(sm_->fluxScale(model)); - - sm_->fluxScale(model).copyData( (LatticeExpr<Float>) + + sm_->fluxScale(model).copyData( (LatticeExpr<Float>) (iif(sm_->ggS(model) < (ggSMin2), 0.0, (sm_->ggS(model)/ggSMax) )) ); */ - //} + //} } - + //because for usual ft machines a applySJoneInv is done on the gS //in the finalizeput stage...need to understand if its necessary /*need to understand that square business if( (ft_->name() != "MosaicFT") && (!isPSFWork_p)){ - sm_->gS(model).copyData( (LatticeExpr<Float>) - (iif(sm_->fluxScale(model) > 0.0, + sm_->gS(model).copyData( (LatticeExpr<Float>) + (iif(sm_->fluxScale(model) > 0.0, ((sm_->gS(model))/(sm_->fluxScale(model))), 0.0 )) ); } diff --git a/CEP/Imager/LofarFT/src/LofarFTMachine.cc b/CEP/Imager/LofarFT/src/LofarFTMachine.cc index cc1bc5188a31ed334fffc71793aae94aa70a2bb0..5985558dad5aa892d354de316472b041d6b3311f 100644 --- a/CEP/Imager/LofarFT/src/LofarFTMachine.cc +++ b/CEP/Imager/LofarFT/src/LofarFTMachine.cc @@ -21,9 +21,9 @@ //# $Id$ #include <lofar_config.h> -// #include <Common/LofarLogger.h> -// #include <Common/Exception.h> -#include <Common/OpenMP.h> +// #include <Common/OpenMP.h> +// #include <omp.h> + #include <msvis/MSVis/VisibilityIterator.h> #include <casa/Quanta/UnitMap.h> #include <casa/Quanta/UnitVal.h> @@ -76,6 +76,8 @@ #include <casa/Utilities/CompositeNumber.h> #include <casa/OS/PrecTimer.h> #include <casa/sstream.h> +#include <casa/OS/HostInfo.h> +#include <casa/BasicMath/Random.h> #define DORES True @@ -107,23 +109,39 @@ LofarFTMachine::LofarFTMachine(Long icachesize, Int itilesize, const MeasurementSet& ms, Int nwPlanes, MPosition mLocation, Float padding, Bool usezero, Bool useDoublePrec, double wmax, - const String& beamPath, Int verbose, + Int verbose, Int maxsupport, Int oversample, const String& imgName, const Matrix<bool>& gridMuellerMask, - const Matrix<bool>& degridMuellerMask) + const Matrix<bool>& degridMuellerMask, + Double RefFreq, + Bool Use_Linear_Interp_Gridder, + Bool Use_EJones, + int StepApplyElement, + Double PBCut, + Bool PredictFT, + String PsfOnDisk, + Bool UseMasksDegrid, + Bool reallyDoPSF, + const Record& parameters + )//, + //Double FillFactor) : FTMachine(), padding_p(padding), imageCache(0), cachesize(icachesize), tilesize(itilesize), gridder(0), isTiled(False), convType(iconvType), maxAbsData(0.0), centerLoc(IPosition(4,0)), offsetLoc(IPosition(4,0)), usezero_p(usezero), noPadding_p(False), usePut2_p(False), machineName_p("LofarFTMachine"), itsMS(ms), - itsNWPlanes(nwPlanes), itsWMax(wmax), itsConvFunc(0), itsBeamPath(beamPath), + itsNWPlanes(nwPlanes), itsWMax(wmax), itsConvFunc(0), itsVerbose(verbose), itsMaxSupport(maxsupport), itsOversample(oversample), itsImgName(imgName), itsGridMuellerMask(gridMuellerMask), itsDegridMuellerMask(degridMuellerMask), - itsGriddingTime(0), itsDegriddingTime(0), itsCFTime(0) + itsGriddingTime(0), itsDegriddingTime(0), itsCFTime(0), itsParameters(parameters) { + cout << "=======LofarFTMachine====================================" << endl; + cout << itsParameters << endl; + cout << "=========================================================" << endl; + logIO() << LogOrigin("LofarFTMachine", "LofarFTMachine") << LogIO::NORMAL; logIO() << "You are using a non-standard FTMachine" << LogIO::WARN << LogIO::POST; mLocation_p=mLocation; @@ -137,6 +155,32 @@ LofarFTMachine::LofarFTMachine(Long icachesize, Int itilesize, itsSumPB.resize (itsNThread); itsSumCFWeight.resize (itsNThread); itsSumWeight.resize (itsNThread); + itsRefFreq=RefFreq; + itsNamePsfOnDisk=PsfOnDisk; + its_Use_Linear_Interp_Gridder=Use_Linear_Interp_Gridder; + its_Use_EJones=Use_EJones; + its_UseMasksDegrid=UseMasksDegrid; + its_PBCut=PBCut; + its_reallyDoPSF=reallyDoPSF; + //its_FillFactor=FillFactor; + itsStepApplyElement=StepApplyElement; + its_Apply_Element=false; + itsPredictFT=PredictFT; + if(itsStepApplyElement>0){its_Apply_Element=true;} + + if(its_Use_Linear_Interp_Gridder){ + cout<<"Gridding using oversampling of 1 only"<<endl; + itsOversample=1; + }; + //cout<<"FTMahin: itsRefFreq "<<itsRefFreq<<endl; + + ROMSSpWindowColumns window(ms.spectralWindow()); + itsListFreq.resize(window.nrow()); + for(uInt i=0; i<window.nrow();++i){ + itsListFreq[i]=window.refFrequency()(i); + cout<<"SPW"<<i<<", freq="<<itsListFreq[i]<<endl; + }; + its_Already_Initialized=false; } //LofarFTMachine::LofarFTMachine(Long icachesize, Int itilesize, @@ -224,6 +268,20 @@ LofarFTMachine& LofarFTMachine::operator=(const LofarFTMachine& other) itsNWPlanes = other.itsNWPlanes; itsWMax = other.itsWMax; itsConvFunc = other.itsConvFunc; + //cyrr: mfs + itsRefFreq=other.itsRefFreq; + thisterm_p=other.thisterm_p; + its_Use_Linear_Interp_Gridder= other.its_Use_Linear_Interp_Gridder; + its_Use_EJones= other.its_Use_EJones; + its_UseMasksDegrid=other.its_UseMasksDegrid; + its_Apply_Element= other.its_Apply_Element; + itsStepApplyElement=other.itsStepApplyElement; + its_Already_Initialized= other.its_Already_Initialized; + its_reallyDoPSF = other.its_reallyDoPSF; + its_PBCut= other.its_PBCut; + //its_FillFactor=other.its_FillFactor; + //cyrr: mfs + ConjCFMap_p = other.ConjCFMap_p; CFMap_p = other.CFMap_p; itsNThread = other.itsNThread; @@ -232,16 +290,17 @@ LofarFTMachine& LofarFTMachine::operator=(const LofarFTMachine& other) itsSumPB.resize (itsNThread); itsSumCFWeight.resize (itsNThread); itsSumWeight.resize (itsNThread); - itsBeamPath = other.itsBeamPath; itsVerbose = other.itsVerbose; itsMaxSupport = other.itsMaxSupport; itsOversample = other.itsOversample; + itsPredictFT = other.itsPredictFT; itsImgName = other.itsImgName; itsGridMuellerMask = other.itsGridMuellerMask; itsDegridMuellerMask = other.itsDegridMuellerMask; itsGriddingTime = other.itsGriddingTime; itsDegriddingTime = other.itsDegriddingTime; itsCFTime = other.itsCFTime; + itsParameters = other.itsParameters; } return *this; } @@ -267,6 +326,7 @@ void LofarFTMachine::init() { logIO() << LogOrigin("LofarFTMachine", "init") << LogIO::NORMAL; canComputeResiduals_p = DORES; ok(); + // cout<<"LofarFTMachine::init()" <<endl; /* hardwiring isTiled is False // Padding is possible only for non-tiled processing @@ -280,6 +340,9 @@ void LofarFTMachine::init() { else { */ // We are padding. + + //cout<<"padding_p!!!!! "<<padding_p<<endl; + isTiled=False; if(!noPadding_p){ CompositeNumber cn(uInt(image->shape()(0)*2)); @@ -334,14 +397,19 @@ void LofarFTMachine::init() { itsConvFunc = new LofarConvolutionFunction(padded_shape, image->coordinates().directionCoordinate (image->coordinates().findCoordinate(Coordinate::DIRECTION)), itsMS, itsNWPlanes, itsWMax, - itsOversample, itsBeamPath, - itsVerbose, itsMaxSupport, - itsImgName); + itsOversample, + itsVerbose, itsMaxSupport, + itsImgName+String::toString(thisterm_p), + its_Use_EJones, + its_Apply_Element, + itsParameters); // Set up image cache needed for gridding. For BOX-car convolution // we can use non-overlapped tiles. Otherwise we need to use // overlapped tiles and additive gridding so that only increments // to a tile are written. + its_Already_Initialized=true; + if(imageCache) delete imageCache; imageCache=0; if(isTiled) { @@ -364,6 +432,12 @@ void LofarFTMachine::init() { (tileOverlap>0.0)); } + itsCyrilTimer.start(); + itsTStartObs=1.e30; + itsDeltaTime=0.; + itsNextApplyTime=0.;; + itsCounterTimes=0; + } // This is nasty, we should use CountedPointers here. @@ -377,9 +451,11 @@ LofarFTMachine::~LofarFTMachine() const Matrix<Float>& LofarFTMachine::getAveragePB() const { + //cout<<"return beam"<<endl; // Read average beam from disk if not present. if (itsAvgPB.empty()) { - PagedImage<Float> pim(itsImgName + ".avgpb"); + //cout<<"...read beam "<<itsImgName+String::toString(thisterm_p) + ".avgpb"<<endl; + PagedImage<Float> pim(itsImgName+String::toString(thisterm_p) + ".avgpb"); Array<Float> arr = pim.get(); itsAvgPB.reference (arr.nonDegenerate(2)); } @@ -391,13 +467,10 @@ const Matrix<Float>& LofarFTMachine::getAveragePB() const void LofarFTMachine::initializeToVis(ImageInterface<Complex>& iimage, const VisBuffer& vb) { - if (itsVerbose > 0) { - cout<<"---------------------------> initializeToVis"<<endl; - } image=&iimage; ok(); - init(); + if(!its_Already_Initialized){init();};//init(); // Initialize the maps for polarization and channel. These maps // translate visibility indices into image indices @@ -425,6 +498,8 @@ void LofarFTMachine::initializeToVis(ImageInterface<Complex>& iimage, // Note the other itsGriddedData buffers are assigned later. itsGriddedData[0].resize (gridShape); itsGriddedData[0] = Complex(); + its_stacked_GriddedData.resize (gridShape); + its_stacked_GriddedData = Complex(); for (int i=0; i<itsNThread; ++i) { itsSumPB[i].resize (padded_shape[0], padded_shape[1]); itsSumPB[i] = Complex(); @@ -432,6 +507,11 @@ void LofarFTMachine::initializeToVis(ImageInterface<Complex>& iimage, itsSumWeight[i].resize(npol, nchan); itsSumWeight[i] = 0.; } + itsCounterTimes=0; + itsTStartObs=1.e30; + itsDeltaTime=0.; + itsTotalStepsGrid=0; + itsTotalStepsDeGrid=0; //griddedData can be a reference of image data...if not using model col //hence using an undocumented feature of resize that if @@ -446,10 +526,10 @@ void LofarFTMachine::initializeToVis(ImageInterface<Complex>& iimage, <<blc<<" "<<trc<<" "<<nx<<" "<<ny<<" "<<image->shape()<<endl; } IPosition start(4, 0); - itsGriddedData[0](blc, trc) = image->getSlice(start, image->shape()); + its_stacked_GriddedData(blc, trc) = image->getSlice(start, image->shape()); //if(arrayLattice) delete arrayLattice; arrayLattice=0; //======================CHANGED - arrayLattice = new ArrayLattice<Complex>(itsGriddedData[0]); + arrayLattice = new ArrayLattice<Complex>(its_stacked_GriddedData); // Array<Complex> result(IPosition(4, nx, ny, npol, nchan),0.); // griddedData=result; // arrayLattice = new ArrayLattice<Complex>(griddedData); @@ -480,10 +560,9 @@ void LofarFTMachine::initializeToVis(ImageInterface<Complex>& iimage, // } //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - // Normalising clean components by the beam - - // const Matrix<Float>& datai = getSpheroidCut(); + // Normalising clean components by the beam + // const Matrix<Float>& datai = getSpheroidCut(); const Matrix<Float>& data = getAveragePB(); // cout<<"tmp.shape() "<<data.shape()<<" "<<lattice->shape()<<endl; IPosition pos(4,lattice->shape()[0],lattice->shape()[1],1,1); @@ -493,17 +572,43 @@ void LofarFTMachine::initializeToVis(ImageInterface<Complex>& iimage, pos2[2]=0.; pos2[3]=0.; Int offset_pad(floor(data.shape()[0]-lattice->shape()[0])/2.); - + // cout<<"LofarFTMachine::initializeToVis lattice->shape() == "<<lattice->shape()<<endl; + String nameii(itsImgName+String::toString(thisterm_p) + ".spheroid_cut_im"); + ostringstream nameiii(nameii); + PagedImage<Float> tmpi(nameiii.str().c_str()); + Slicer slicei(IPosition(4,0,0,0,0), tmpi.shape(), IPosition(4,1,1,1,1)); + Array<Float> datai; + tmpi.doGetSlice(datai, slicei); + + String nameii_element("Spheroid_cut_im_element.img"); + ostringstream nameiii_element(nameii_element); + PagedImage<Float> tmpi_element(nameiii_element.str().c_str()); + Slicer slicei_element(IPosition(4,0,0,0,0), tmpi_element.shape(), IPosition(4,1,1,1,1)); + Array<Float> spheroidCutElement; + tmpi_element.doGetSlice(spheroidCutElement, slicei_element); Complex ff; double I=100.; - double Q=40.; - double U=20.; - double V=10.; + double Q=0.; + double U=0.; + double V=0.; + + double maxPB(0.); + double minPB(1e10); + for(uInt i=0;i<lattice->shape()[0];++i){ + for(uInt j=0;j<lattice->shape()[0];++j){ + double pixel(data(i+offset_pad,j+offset_pad)); + if(abs(pixel)>maxPB){maxPB=abs(pixel);}; + if(abs(pixel)<minPB){minPB=abs(pixel);}; + } + } + for(Int k=0;k<lattice->shape()[2];++k){ ff=0.; + //cout<<"k="<<k<<endl; if(k==0){ff=I+Q;} + // if(k==1){ff=I-Q;} if(k==1){ff=Complex(U,0.)+Complex(0.,V);} if(k==2){ff=Complex(U,0.)-Complex(0.,V);} if(k==3){ff=I-Q;} @@ -518,27 +623,38 @@ void LofarFTMachine::initializeToVis(ImageInterface<Complex>& iimage, double fact(1.); // pixel=0.; - // if((pos[0]==351.)&&(pos[1]==319.)){//319 + // if((pos[0]==372.)&&(pos[1]==370.)){//319 // pixel=ff;//*139./143;//-100.; - // if(datai(pos2)>1e-6){fact/=datai(pos2);};//*datai(pos2);}; + // //if(datai(pos2)>1e-6){fact/=datai(pos2)*datai(pos2);};//*datai(pos2);}; + // //if(datai(pos2)>1e-6){fact*=sqrt(maxPB)/sqrt(data(pos2));}; + // fact*=sqrt(maxPB)/sqrt(data(pos2)); // //if(data(pos2)>1e-6){fact/=sqrt(data(pos2));};//*datai(pos2);}; // pixel*=Complex(fact); // } - - fact/=sqrt(data(pos2)); + + if(!itsPredictFT){ + fact*=sqrt(maxPB)/sqrt(data(pos2)); + } else { + fact/=datai(pos2);//*datai(pos2); + if(its_Apply_Element){fact/=spheroidCutElement(pos2);} + } pixel*=Complex(fact); - - lattice->putAt(pixel,pos); + + if((data(pos2)>(minPB))&&(abs(pixel)>0.)){ + lattice->putAt(pixel,pos); + }; } } } - //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // Now do the FFT2D in place LatticeFFT::cfft2d(*lattice); + if((!(itsConvFunc->itsFilledVectorMasks))&&(its_Apply_Element)){itsConvFunc->ReadMaskDegrid();} + //if((!(itsConvFunc->VectorMaskIsFilled()))&&(its_Apply_Element)){itsConvFunc->ReadMaskDegrid();} + logIO() << LogIO::DEBUGGING << "Finished grid correction and FFT of image" << LogIO::POST; @@ -550,7 +666,7 @@ void LofarFTMachine::initializeToVis(ImageInterface<Complex>& iimage, // pos[2]=k; // Complex pixel(lattice->getAt(pos)); // //cout<<"i,j,pixel value: "<<i<<" "<<j<<" "<<pixel<<endl; - + // }; // }; // }; @@ -574,10 +690,10 @@ void LofarFTMachine::initializeToSky(ImageInterface<Complex>& iimage, { // image always points to the image image=&iimage; - if (itsVerbose > 0) { - cout<<"---------------------------> initializeToSky"<<endl; - } - init(); + //if (itsVerbose > 0) { + //cout<<"---------------------------> initializeToSky"<<" its_Already_Initialized : "<<its_Already_Initialized<<endl; + //} + if(!its_Already_Initialized){init();}; // Initialize the maps for polarization and channel. These maps // translate visibility indices into image indices @@ -593,6 +709,8 @@ void LofarFTMachine::initializeToSky(ImageInterface<Complex>& iimage, AlwaysAssert (!isTiled, AipsError); IPosition gridShape(4, nx, ny, npol, nchan); // Size and initialize the grid buffer per thread. + its_stacked_GriddedData.resize (gridShape); + its_stacked_GriddedData = Complex(); for (int i=0; i<itsNThread; ++i) { itsGriddedData[i].resize (gridShape); itsGriddedData[i] = Complex(); @@ -604,10 +722,15 @@ void LofarFTMachine::initializeToSky(ImageInterface<Complex>& iimage, } weight.resize(itsSumWeight[0].shape()); weight=0.0; + itsCounterTimes=0; + itsTStartObs=1.e30; + itsDeltaTime=0.; + itsTotalStepsGrid=0; + itsTotalStepsDeGrid=0; //iimage.get(griddedData, False); //if(arrayLattice) delete arrayLattice; arrayLattice=0; - arrayLattice = new ArrayLattice<Complex>(itsGriddedData[0]); + arrayLattice = new ArrayLattice<Complex>(its_stacked_GriddedData); lattice=arrayLattice; // if(useDoubleGrid_p) visResampler_p->initializePutBuffers(griddedData2, sumWeight); // else visResampler_p->initializePutBuffers(griddedData, sumWeight); @@ -628,41 +751,61 @@ void LofarFTMachine::finalizeToSky() cout<<"---------------------------> finalizeToSky"<<endl; } // DEBUG: Store the grid per thread - uInt nx(itsGriddedData[0].shape()[0]); - IPosition shapecube(3,nx,nx,4); - for (int ii=0; ii<itsNThread; ++ii) { - Cube<Complex> tempimage(shapecube,0.); - for(Int k=0;k<4;++k){ - for(uInt i=0;i<nx;++i){ - for(uInt j=0;j<nx;++j){ - IPosition pos(4,i,j,k,0); - Complex pixel(itsGriddedData[ii](pos)); - tempimage(i,j,k)=pixel; - } - } + // uInt nx(itsGriddedData[0].shape()[0]); + // IPosition shapecube(3,nx,nx,4); + // for (int ii=0; ii<itsNThread; ++ii) { + // Cube<Complex> tempimage(shapecube,0.); + // for(Int k=0;k<itsGriddedData[0].shape()[2];++k){ + // for(uInt i=0;i<nx;++i){ + // for(uInt j=0;j<nx;++j){ + // IPosition pos(4,i,j,k,0); + // Complex pixel(itsGriddedData[ii](pos)); + // tempimage(i,j,k)=pixel; + // } + // } + // } + // store(tempimage,"Grid"+String::toString(ii)+".img"); + // } + + // Add all buffers into the first one. + + // for(uInt channel=0;channel< its_stacked_GriddedData.shape()[3];++channel){ + // for(uInt jj=0;jj<its_stacked_GriddedData.shape()[2];++jj){ + // cout<<"Add all buffers into the first one. jj="<<jj<<endl; + // Matrix<Complex> plane_array_out = its_stacked_GriddedData(Slicer(IPosition(4, 0, 0, jj, 0), + // IPosition(4, nx, nx, 1, 1))).nonDegenerate(); + // ArrayLattice<Complex> lattice(plane_array_out); + // LatticeFFT::cfft2d(lattice, true); + // plane_array_out/=static_cast<Float>(plane_array_out.shape()(0)*plane_array_out.shape()(1)); + // } + // } + + if(!its_Apply_Element){ + SumGridsOMP(its_stacked_GriddedData, itsGriddedData); + for (int i=0; i<itsNThread; ++i) { + itsGriddedData[i]=Complex(); } - store(tempimage,"Grid"+String::toString(ii)+".img"); } - // Add all buffers into the first one. + for (int i=1; i<itsNThread; ++i) { - itsGriddedData[0] += itsGriddedData[i]; + //itsGriddedData[0] += itsGriddedData[i]; itsSumWeight[0] += itsSumWeight[i]; itsSumCFWeight[0] += itsSumCFWeight[i]; itsSumPB[0] += itsSumPB[i]; } - Cube<Complex> tempimage(shapecube,0.); - for(Int k=0;k<4;++k){ - for(uInt i=0;i<nx;++i){ - for(uInt j=0;j<nx;++j){ - IPosition pos(4,i,j,k,0); - Complex pixel(itsGriddedData[0](pos)); - tempimage(i,j,k)=pixel; - } - } - } - store(tempimage,"Grid00.img"); + // Cube<Complex> tempimage(IPosition(3,nx,nx,4),0.); + // for(Int k=0;k<4;++k){ + // for(uInt i=0;i<nx;++i){ + // for(uInt j=0;j<nx;++j){ + // IPosition pos(4,i,j,k,0); + // Complex pixel(its_stacked_GriddedData(pos)); + // tempimage(i,j,k)=pixel; + // } + // } + // } + // store(tempimage,"Grid00.img"); // if(useDoubleGrid_p) visResamplers_p[0].GatherGrids(griddedData2, sumWeight); // else visResamplers_p[0].GatherGrids(griddedData, sumWeight); @@ -687,11 +830,16 @@ Array<Complex>* LofarFTMachine::getDataPointer(const IPosition& centerLoc2D, void LofarFTMachine::put(const VisBuffer& vb, Int row, Bool dopsf, FTMachine::Type type) { - if (itsVerbose > 0) { + + itsCyrilTimer.stop(); + //PrecTimer TimerCyril; + //TimerCyril.start(); + + if (itsVerbose > 0) { logIO() << LogOrigin("LofarFTMachine", "put") << LogIO::NORMAL << "I am gridding " << vb.nRow() << " row(s)." << LogIO::POST; logIO() << LogIO::NORMAL << "Padding is " << padding_p << LogIO::POST; - } + } gridOk(gridder->cSupport()(0)); @@ -709,16 +857,21 @@ void LofarFTMachine::put(const VisBuffer& vb, Int row, Bool dopsf, chanMap=multiChanMap_p[vb.spectralWindow()]; } + + + + //cout<<"... Gridding Spectral Window: "<<vb.spectralWindow()<<", with Taylor Term: "<< thisterm_p<<endl; + + uInt spw(vb.spectralWindow()); + //No point in reading data if it's not matching in frequency if(max(chanMap)==-1) return; const Matrix<Float> *imagingweight; imagingweight=&(vb.imagingWeight()); - // dopsf=true; - + if(its_reallyDoPSF) {dopsf=true;} if(dopsf) {type=FTMachine::PSF;} - Cube<Complex> data; //Fortran gridder need the flag as ints Cube<Int> flags; @@ -737,10 +890,27 @@ void LofarFTMachine::put(const VisBuffer& vb, Int row, Bool dopsf, // irrelevant for other cases. Matrix<Double> uvw(3, vb.uvw().nelements()); uvw=0.0; Vector<Double> dphase(vb.uvw().nelements()); dphase=0.0; + + + // // const Vector<Double>& times = vb.timeCentroid(); + // // double time = 0.5 * (times[times.size()-1] + times[0]); + // const Vector<Double>& freq = vb.lsrFrequency(); + // const Vector<Int>& obs = vb.observationId(); + // Vector<Double> lsrFreq(0); + // Bool condoo=False; + // vb.lsrFrequency(0, lsrFreq, condoo); + // cout<<"mmm " <<lsrFreq<<" "<<condoo<<endl; + // vb.lsrFrequency(1, lsrFreq, condoo); + // cout<<"mmmmm " <<lsrFreq<<" "<<condoo<<endl; + //const Vector<Double>& timess = vb.timeCentroid(); + //NEGATING to correct for an image inversion problem for (Int i=startRow;i<=endRow;i++) { for (Int idim=0;idim<2;idim++) uvw(idim,i)=-vb.uvw()(i)(idim); uvw(2,i)=vb.uvw()(i)(2); + // cout << "freq "<< freq[i] << endl; + // cout << "obsid "<< obs[i] << vb.dataDescriptionId() <<endl; + // cout << "times "<< timess[i] << endl; } rotateUVW(uvw, dphase, vb); @@ -784,6 +954,7 @@ void LofarFTMachine::put(const VisBuffer& vb, Int row, Bool dopsf, blEnd.push_back (i-1); } } + // Skip auto-correlations and high W-values. // All w values are close, so if first w is too high, skip baseline. usebl = false; @@ -826,6 +997,8 @@ void LofarFTMachine::put(const VisBuffer& vb, Int row, Bool dopsf, // However the VBS objects should ultimately be references // directly to bool cubes. //************** + + vbs.flagCube_p.resize(flags.shape()); vbs.flagCube_p = False; vbs.flagCube_p(flags!=0) = True; // vbs.flagCube_p.reference(vb.flagCube()); //************** @@ -835,36 +1008,73 @@ void LofarFTMachine::put(const VisBuffer& vb, Int row, Bool dopsf, visResamplers_p.setMaps(chanMap, polMap); // First compute the A-terms for all stations (if needed). + PrecTimer CyrilTimer2Aterm; + CyrilTimer2Aterm.start(); itsConvFunc->computeAterm (time); + CyrilTimer2Aterm.stop(); + double Taterm=CyrilTimer2Aterm.getReal(); uInt Nchannels = vb.nChannel(); itsTotalTimer.start(); -#pragma omp parallel + + vector< Bool> done; + done.resize(int(blStart.size())); + for(int i=0; i<int(blStart.size()); ++i) {done[i]=false;}; + + Bool all_done(false); + Int doagain(0); + + /// Int Max_Num_Threads(itsNThread); + /// omp_set_num_threads(Max_Num_Threads); + + + //logIO() <<"============================== Gridding data " << LogIO::POST; + //cout<<"... gridding with t= "<<time<<endl; + PrecTimer CyrilTimer2grid; + PrecTimer CyrilTimer2conv; + PrecTimer CyrilTimer2gridconv; + CyrilTimer2gridconv.start(); + // CyrilTimer2conv.reset(); + + while(!all_done){ + +#pragma omp parallel { // Thread-private variables. PrecTimer gridTimer; PrecTimer cfTimer; + PrecTimer CyrilTimer; // The for loop can be parallellized. This must be done dynamically, // because the execution times of iterations can vary greatly. + + #pragma omp for schedule(dynamic) for (int i=0; i<int(blStart.size()); ++i) { Int ist = blIndex[blStart[i]]; Int iend = blIndex[blEnd[i]]; + if(done[i]==true){continue;}; + //if(doagain>0){ + //cout<<"Doing again (doagain) baseline: A1="<<ant1[ist]<<", A2="<<ant2[ist]<<endl; + //} + + try{ // compute average weight for baseline for CF averaging - double average_weight(0.); - uInt Nvis(0); + double average_weight=0.; + uInt Nvis=0; for(Int j=ist; j<iend; ++j){ uInt row=blIndex[j]; if(!vbs.rowFlag()[row]){ Nvis+=1; - for(uint k=0; k<Nchannels; ++k) { + for(uInt k=0; k<Nchannels; ++k) { average_weight=average_weight+vbs.imagingWeight()(k,row); } } } - average_weight=average_weight/Nvis; + if(Nvis>0){ + average_weight=average_weight/Nvis; + } else {average_weight=0.;} /// itsSumWeight += average_weight * average_weight; if (itsVerbose > 1) { cout<<"average weights= "<<average_weight<<", Nvis="<<Nvis<<endl; @@ -877,27 +1087,31 @@ void LofarFTMachine::put(const VisBuffer& vb, Int row, Bool dopsf, cout.precision(20); cout<<"A1="<<ant1[ist]<<", A2="<<ant2[ist]<<", time="<<fixed<<time<<endl; } - LofarCFStore cfStore; //#pragma omp critical(LofarFTMachine_makeConvolutionFunction) //{ + CyrilTimer2conv.start(); cfTimer.start(); - cfStore = + Double Wmean=0.5*(vbs.uvw()(2,ist) + vbs.uvw()(2,iend)); + //cout<< Wmean<<endl; + LofarCFStore cfStore = itsConvFunc->makeConvolutionFunction (ant1[ist], ant2[ist], time, - 0.5*(vbs.uvw()(2,ist) + vbs.uvw()(2,iend)), + Wmean, itsGridMuellerMask, false, average_weight, itsSumPB[threadNum], - itsSumCFWeight[threadNum]); - cfTimer.stop(); - //}; + itsSumCFWeight[threadNum], + spw,thisterm_p,itsRefFreq + ); + - //cout<<"DONE LOADING CF..."<<endl; - //Double or single precision gridding. - // cout<<"============================================"<<endl; - // cout<<"Antenna "<<ant1[ist]<<" and "<<ant2[ist]<<endl; - //#pragma omp critical(LofarFTMachine_makeConvolutionFunction) - //{ + //cfTimer.stop(); + CyrilTimer2conv.stop(); + + Int nConvX = (*(cfStore.vdata))[0][0][0].shape()[0]; + //cout<<ant1[ist]<<" "<<ant2[ist]<<" " <<nConvX/5<<endl; + //double cfstep=CyrilTimer2conv.getReal(); + CyrilTimer2grid.start(); if (useDoubleGrid_p) { visResamplers_p.lofarDataToGrid(itsGriddedData2[threadNum], vbs, blIndex, blStart[i], blEnd[i], @@ -907,13 +1121,35 @@ void LofarFTMachine::put(const VisBuffer& vb, Int row, Bool dopsf, cout<<" gridding"<<" thread="<<threadNum<<'('<<itsNThread<<"), A1="<<ant1[ist]<<", A2="<<ant2[ist]<<", time=" <<time<<endl; } gridTimer.start(); - visResamplers_p.lofarDataToGrid - (itsGriddedData[threadNum], vbs, blIndex, blStart[i], - blEnd[i], itsSumWeight[threadNum], dopsf, cfStore); - gridTimer.stop(); + if(!its_Use_Linear_Interp_Gridder){ + //cout<<"itsGriddedData[threadNum] "<<itsGriddedData[threadNum].shape()<<endl; + visResamplers_p.lofarDataToGrid + (itsGriddedData[threadNum], vbs, blIndex, blStart[i], + blEnd[i], itsSumWeight[threadNum], dopsf, cfStore); + } else{ + visResamplers_p.lofarDataToGrid_linear + (itsGriddedData[threadNum], vbs, blIndex, blStart[i], + blEnd[i], itsSumWeight[threadNum], dopsf, cfStore); + + }; + gridTimer.stop(); } + CyrilTimer2grid.stop(); + //cout<<"Gridding calculation: "<<nConvX<<" "<<cfstep<<" "<<CyrilTimer2grid.getReal()<<endl; + //CyrilTimer2grid.reset(); + //CyrilTimer2conv.reset(); + //CyrilTimer.reset(); + done[i]=true; + } catch (std::bad_alloc &) + { + cout<<"-----------------------------------------"<<endl; + cout<<"!!!!!!! GRIDDING: Skipping baseline: "<<ant1[ist]<<" | "<<ant2[ist]<<endl; + cout<<"memoryUsed() "<< HostInfo::memoryUsed()<< ", Free: "<<HostInfo::memoryFree()<<endl; + cout<<"-----------------------------------------"<<endl; + }; // } // end omp critical } // end omp for + double cftime = cfTimer.getReal(); #pragma omp atomic itsCFTime += cftime; @@ -921,16 +1157,73 @@ void LofarFTMachine::put(const VisBuffer& vb, Int row, Bool dopsf, #pragma omp atomic itsGriddingTime += gtime; } // end omp parallel + + all_done=true; + int number_missed(0); + for (int i=0; i<int(blStart.size()); ++i) { + if(done[i]==false){all_done=false;number_missed+=1;}; + }; + if(all_done==false){ + //cout<<"================================"<<endl; + //cout<<"Memory exception returned by "<<number_missed<<" threads"<<endl; + //cout<<"Reducing number of threads to: "<<int(omp_get_num_threads()/2.)<<endl; + //cout<<"================================"<<endl; + doagain+=1; + //omp_set_num_threads(int(omp_get_num_threads()/2.)); + }; + + }//end While loop + + CyrilTimer2gridconv.stop(); + double Tgridconv=CyrilTimer2gridconv.getReal(); + + PrecTimer CyrilTimer2elem; + if(itsDeltaTime<(times[times.size()-1] - times[0])){itsDeltaTime=(times[times.size()-1] - times[0]);}; + Bool lastchunk(false); + if((times[times.size()-1] - times[0])<0.95*itsDeltaTime){ + lastchunk=true; + itsDeltaTime=0.; + } + + //cout<<"time: "<<time<<" "<<itsStepApplyElement<<" "<<its_Apply_Element<<endl; + CyrilTimer2elem.start(); + + if(itsCounterTimes==(itsStepApplyElement-1)/2){itsNextApplyTime=time;} + if(its_Apply_Element){ + if((itsCounterTimes==itsStepApplyElement-1)||(lastchunk)){ + Array<Complex> tmp_stacked_GriddedData; + tmp_stacked_GriddedData.resize (itsGriddedData[0].shape()); + tmp_stacked_GriddedData = Complex(); + SumGridsOMP(tmp_stacked_GriddedData, itsGriddedData); + //itsConvFunc->MakeMaskDegrid(tmp_stacked_GriddedData, itsTotalStepsGrid); + Array<Complex> tmp_stacked_GriddedData_appliedelement=itsConvFunc->ApplyElementBeam2 (tmp_stacked_GriddedData, itsNextApplyTime, spw, itsGridMuellerMask, false); + if(its_UseMasksDegrid){ + itsConvFunc->MakeMaskDegrid(tmp_stacked_GriddedData_appliedelement, itsTotalStepsGrid); + } + SumGridsOMP(its_stacked_GriddedData, tmp_stacked_GriddedData_appliedelement); + CyrilTimer2elem.stop(); + itsCounterTimes=0; + for (int i=0; i<itsNThread; ++i) { + itsGriddedData[i]=Complex(); + } + itsTotalStepsGrid+=1; + } else { + itsCounterTimes+=1; + } + } + + CyrilTimer2elem.stop(); + //cout<<"times: aterm:"<<Taterm<<", conv: "<<CyrilTimer2conv.getReal()<<", grid: "<<CyrilTimer2grid.getReal()<<", gridconv: "<<Tgridconv<<", sum: "<<CyrilTimer2elem.getReal()<<", other: "<<itsCyrilTimer.getReal()<<endl; + //cout<<"times: conv:"<<CyrilTimer2conv.getReal()<<", grid:"<<CyrilTimer2grid.getReal()<<", element:"<<CyrilTimer2elem.getReal()<<endl; itsTotalTimer.stop(); + itsCyrilTimer.reset(); + itsCyrilTimer.start(); } // Degrid void LofarFTMachine::get(VisBuffer& vb, Int row) { - if (itsVerbose > 0) { - cout<<"///////////////////// GET!!!!!!!!!!!!!!!!!!"<<endl; - } gridOk(gridder->cSupport()(0)); // If row is -1 then we pass through all rows Int startRow, endRow, nRow; @@ -950,6 +1243,8 @@ void LofarFTMachine::get(VisBuffer& vb, Int row) //Check if ms has changed then cache new spw and chan selection if(vb.newMS()) matchAllSpwChans(vb); + uInt spw(vb.spectralWindow()); + //cout<<"... De-Gridding Spectral Window: "<<vb.spectralWindow()<<", with Taylor Term: "<< thisterm_p<<endl; //Channel matching for the actual spectral window of buffer @@ -980,7 +1275,7 @@ void LofarFTMachine::get(VisBuffer& vb, Int row) vbs.uvw_p.reference(uvw); // vbs.imagingWeight.reference(elWeight); vbs.visCube_p.reference(data); - + vbs.freq_p.reference(interpVisFreq_p); vbs.rowFlag_p.resize(0); vbs.rowFlag_p = vb.flagRow(); if(!usezero_p) @@ -1066,7 +1361,71 @@ void LofarFTMachine::get(VisBuffer& vb, Int row) // First compute the A-terms for all stations (if needed). itsConvFunc->computeAterm (time); + if(times[0]<itsTStartObs){itsTStartObs=times[0];} + if(itsDeltaTime<(times[times.size()-1] - times[0])){itsDeltaTime=(times[times.size()-1] - times[0]);}; + if(itsDeltaTime<(times[times.size()-1] - times[0])){itsDeltaTime=(times[times.size()-1] - times[0]);}; + itsTotalTimer.start(); + + vector< Bool> done; + done.resize(int(blStart.size())); + for(int i=0; i<int(blStart.size()); ++i) {done[i]=false;}; + + Bool all_done(false); + /// Int Max_Num_Threads(itsNThread); + /// omp_set_num_threads(Max_Num_Threads); + + PrecTimer CyrilElement; + CyrilElement.start(); + cout.precision(20); + //cout<<" ======================= De-Grid ... time="<<time<<", at "<<itsCounterTimes<<endl; + if(its_Apply_Element){ + //cout<<"itsCounterTimes= "<<itsCounterTimes<<endl; + if(itsCounterTimes==0){ + double TimeElement(itsTStartObs+itsDeltaTime*itsStepApplyElement/2.); + //cout<<"... Appying element with t="<<TimeElement<<", itsTStartObs="<<itsTStartObs<<", itsDeltaTime="<<itsDeltaTime<<endl; + itsConvFunc->computeAterm(TimeElement); + if(its_UseMasksDegrid){ + itsGridToDegrid.reference(itsConvFunc->ApplyElementBeam2(its_stacked_GriddedData, TimeElement, spw, itsGridMuellerMask, true, itsTotalStepsDeGrid)); + }else{ + itsGridToDegrid.reference(itsConvFunc->ApplyElementBeam2(its_stacked_GriddedData, TimeElement, spw, itsGridMuellerMask, true)); + } + itsTotalStepsDeGrid+=1; + } + itsCounterTimes+=1; + if(itsCounterTimes==itsStepApplyElement){ + itsTStartObs=1.e30; + itsCounterTimes=0; + } + Bool lastchunk(false); + if((times[times.size()-1] - times[0])<0.95*itsDeltaTime){ + //cout<<"Last Chunk Degrid!!!"<<endl; + lastchunk=true; + itsDeltaTime=0.; + itsTStartObs=1e12; + } + + + } else{ + itsGridToDegrid.reference(its_stacked_GriddedData); + } + CyrilElement.stop(); + + // arrayLattice = new ArrayLattice<Complex>(tmp_stacked_GriddedData2); + // cout<<"LofarConvolutionFunction::ApplyElementBeam "<<"FFT the element corrected model image"<<endl; + // lattice=arrayLattice; + // LatticeFFT::cfft2d(*lattice); + + //logIO() <<"============================== De-Gridding data " << LogIO::POST; + PrecTimer CyrilConv; + PrecTimer CyrilGrid; + + + while(!all_done){ + + + + #pragma omp parallel { // Thread-private variables. @@ -1080,12 +1439,16 @@ void LofarFTMachine::get(VisBuffer& vb, Int row) // { Int ist = blIndex[blStart[i]]; Int iend = blIndex[blEnd[i]]; + if(done[i]==true){continue;}; + try { int threadNum = OpenMP::threadNum(); // Get the convolution function for degridding. if (itsVerbose > 1) { cout<<"ANTENNA "<<ant1[ist]<<" "<<ant2[ist]<<endl; } cfTimer.start(); + CyrilConv.start(); + LofarCFStore cfStore = itsConvFunc->makeConvolutionFunction (ant1[ist], ant2[ist], time, 0.5*(vbs.uvw()(2,ist) + vbs.uvw()(2,iend)), @@ -1093,15 +1456,29 @@ void LofarFTMachine::get(VisBuffer& vb, Int row) true, 0.0, itsSumPB[threadNum], - itsSumCFWeight[threadNum]); + itsSumCFWeight[threadNum] + ,spw,thisterm_p,itsRefFreq); cfTimer.stop(); - //Double or single precision gridding. - // cout<<"GRID "<<ant1[ist]<<" "<<ant2[ist]<<endl; + CyrilConv.stop(); + CyrilGrid.start(); + degridTimer.start(); - visResamplers_p.lofarGridToData(vbs, itsGriddedData[0], + visResamplers_p.lofarGridToData(vbs, itsGridToDegrid,//its_stacked_GriddedData,//itsGriddedData[0], blIndex, blStart[i], blEnd[i], cfStore); + CyrilGrid.stop(); + degridTimer.stop(); + done[i]=true; + + } catch (std::bad_alloc &) + { + cout<<"-----------------------------------------"<<endl; + cout<<"!!!!!!! DE-GRIDDING: Skipping baseline: "<<ant1[ist]<<" | "<<ant2[ist]<<endl; + cout<<"memoryUsed() "<< HostInfo::memoryUsed()<< ", Free: "<<HostInfo::memoryFree()<<endl; + cout<<"-----------------------------------------"<<endl; + } + } // end omp for double cftime = cfTimer.getReal(); #pragma omp atomic @@ -1110,6 +1487,27 @@ void LofarFTMachine::get(VisBuffer& vb, Int row) #pragma omp atomic itsGriddingTime += gtime; } // end omp parallel + + all_done=true; + int number_missed(0); + for (int i=0; i<int(blStart.size()); ++i) { + //cout<<"done: "<<i<<" "<<done[i]<<endl; + if(done[i]==false){all_done=false;number_missed+=1;}; + }; + if(all_done==false){ + //cout<<"================================"<<endl; + //cout<<"Memory exception returned by "<<number_missed<<" threads"<<endl; + //cout<<"Reducing number of threads to: "<<int(omp_get_num_threads()/2.)<<endl; + //cout<<"================================"<<endl; + //omp_set_num_threads(int(omp_get_num_threads()/2.)); + }; + + }//end While loop + + //cout<<"Element: "<<CyrilElement.getReal()<<", Conv: "<<CyrilConv.getReal()<<", Grid: "<<CyrilGrid.getReal()<<endl;; + + + itsTotalTimer.stop(); interpolateFrequencyFromgrid(vb, data, FTMachine::MODEL); } @@ -1125,9 +1523,6 @@ ImageInterface<Complex>& LofarFTMachine::getImage(Matrix<Float>& weights, Bool n AlwaysAssert(image, AipsError); logIO() << LogOrigin("LofarFTMachine", "getImage") << LogIO::NORMAL; - if (itsVerbose > 0) { - cout<<"GETIMAGE"<<endl; - } itsAvgPB.reference (itsConvFunc->Compute_avg_pb(itsSumPB[0], itsSumCFWeight[0])); //cout<<"weights.shape() "<<weights.shape()<<" "<<sumWeight<<endl; @@ -1236,10 +1631,10 @@ ImageInterface<Complex>& LofarFTMachine::getImage(Matrix<Float>& weights, Bool n // posi[2]=0.; // posi[3]=0.; // posi2[2]=0.; - // posi2[3]=0.; + // posi2[3]=0.; // Int offset_pad(floor(data.shape()[0]-lattice->shape()[0])/2.); - + // for(uInt k=0;k<lattice->shape()[2];++k){ @@ -1267,6 +1662,19 @@ ImageInterface<Complex>& LofarFTMachine::getImage(Matrix<Float>& weights, Bool n Cube<Complex> tempimage(IPosition(3,shapeout,shapeout,lattice->shape()[2])); pos[3]=0.; + double minPB(1e10); + double maxPB(0.); + for(uInt i=0;i<shapeout;++i){ + for(uInt j=0;j<shapeout;++j){ + double pixel(itsAvgPB(i+istart,j+istart)); + if(abs(pixel)>maxPB){maxPB=abs(pixel);}; + if(abs(pixel)<minPB){minPB=abs(pixel);}; + } + } + + const Matrix<Float>& sphe = getSpheroidCut(); + + //maxPB=1.; for(Int k=0;k<lattice->shape()[2];++k){ for(uInt i=0;i<shapeout;++i){ for(uInt j=0;j<shapeout;++j){ @@ -1274,26 +1682,40 @@ ImageInterface<Complex>& LofarFTMachine::getImage(Matrix<Float>& weights, Bool n pos[1]=j+istart; pos[2]=k; Complex pixel(lattice->getAt(pos)); - //cout<<"pixel value: "<<pixel<<", Primary beam: "<<avg_PB(i,j)<<endl; - pixel/=sqrt(itsAvgPB(i+istart,j+istart));//*sqrt(avg_PB(i+istart,j+istart)); - //pixel*=(lattice->shape()[0]*lattice->shape()[0]); + + pixel*=sqrt(maxPB)/sqrt(itsAvgPB(i+istart,j+istart)); + + + //if(itsAvgPB(pos)<1e-6*maxPB){pixel=0.;} + if((sqrt(itsAvgPB(pos))/sphe(pos)<its_PBCut)||(itsAvgPB(pos)<2.*minPB)){pixel=0.;} lattice->putAt(pixel,pos); - //tempimage(i,j,k)=pixel/weights(0,0); + tempimage(i,j,k)=pixel;///weights(0,0); } } } + // uInt count_cycle(0); // Bool written(false); // while(!written){ + // Cube<Complex> tempimagePB(IPosition(3,shapeout,shapeout,lattice->shape()[2])); + // for(Int k=0;k<lattice->shape()[2];++k){ + // for(uInt i=0;i<shapeout;++i){ + // for(uInt j=0;j<shapeout;++j){ + // tempimagePB(i,j,k)=itsAvgPB(i,j); + // }; + // }; + // }; // cout<<"count_cycle ======================= "<<count_cycle<<" "<<normalize<<endl; // File myFile("Cube_dirty.img"+String::toString(count_cycle)); // if(!myFile.exists()){ - // written=true; - // store(tempimage,"Cube_dirty.img"+String::toString(count_cycle)); + // written=true; + // store(tempimage,"Cube_dirty.img"+String::toString(count_cycle)); + // store(tempimagePB,"Cube_dirty.img"+String::toString(count_cycle)+".pb"); + // } // else{ - // count_cycle++; + // count_cycle++; // }; // }; @@ -1310,7 +1732,7 @@ ImageInterface<Complex>& LofarFTMachine::getImage(Matrix<Float>& weights, Bool n IPosition trc(blc+image->shape()-stride); // Do the copy IPosition start(4, 0); - image->put(itsGriddedData[0](blc, trc)); + image->put(its_stacked_GriddedData(blc, trc)); } } @@ -1448,16 +1870,16 @@ Bool LofarFTMachine::fromRecord(String& error, const RecordInterface& inRec) // Make the grid the correct shape and turn it into an array lattice // Check the section from the image BEFORE converting to a lattice IPosition gridShape(4, nx, ny, npol, nchan); - itsGriddedData[0].resize(gridShape); - itsGriddedData[0]=Complex(0.0); + its_stacked_GriddedData.resize(gridShape); + its_stacked_GriddedData=Complex(0.0); IPosition blc(4, (nx-image->shape()(0)+(nx%2==0))/2, (ny-image->shape()(1)+(ny%2==0))/2, 0, 0); IPosition start(4, 0); IPosition stride(4, 1); IPosition trc(blc+image->shape()-stride); - itsGriddedData[0](blc, trc)=image->getSlice(start, image->shape()); + its_stacked_GriddedData(blc, trc)=image->getSlice(start, image->shape()); //if(arrayLattice) delete arrayLattice; arrayLattice=0; - arrayLattice = new ArrayLattice<Complex>(itsGriddedData[0]); + arrayLattice = new ArrayLattice<Complex>(its_stacked_GriddedData); lattice=arrayLattice; } @@ -1555,7 +1977,11 @@ String LofarFTMachine::name(){ void LofarFTMachine::ComputeResiduals(VisBuffer&vb, Bool useCorrected) { + + //cout<<"LofarFTMachine::ComputeResiduals "<<vb.corrType()<<endl; LofarVBStore vbs; + PrecTimer TimerResid; + TimerResid.start(); vbs.nRow_p = vb.nRow(); vbs.beginRow_p = 0; vbs.endRow_p = vbs.nRow_p; @@ -1563,12 +1989,15 @@ void LofarFTMachine::ComputeResiduals(VisBuffer&vb, Bool useCorrected) if (useCorrected) vbs.correctedCube_p.reference(vb.correctedVisCube()); else vbs.visCube_p.reference(vb.visCube()); // cout<<"BLA===="<<vb.visCube()<<" "<<useCorrected<<endl; - + //for(uInt i=0;i<vbs.nRow_p;++i){cout<<"ROW "<<i<<" "<<vb.antenna1()(i)<<" "<<vb.antenna2()(i)<<endl;}; vbs.useCorrected_p = useCorrected; visResamplers_p.lofarComputeResiduals(vbs); + TimerResid.stop(); + //cout<<"Residuals: "<<TimerResid.getReal()<<endl; + // vb.correctedVisCube()=0.;//vb.modelVisCube(); } @@ -1576,6 +2005,7 @@ void LofarFTMachine::ComputeResiduals(VisBuffer&vb, Bool useCorrected) const ImageInterface<Complex>& imageTemplate, ImageInterface<Float>& sensitivityImage) { + cout<<"============================== makeSensitivityImage"<<endl; if (convFuncCtor_p->makeAverageResponse(vb, imageTemplate, sensitivityImage)) cfCache_p->flush(sensitivityImage,sensitivityPatternQualifierStr_p); } @@ -1928,6 +2358,7 @@ void LofarFTMachine::ComputeResiduals(VisBuffer&vb, Bool useCorrected) { LogIO log_l(LogOrigin("LofarFTMachine", "findPointingOffsets")); Vector<Int> msStokes = vb.corrType(); + //cout<<"LofarFTMachine findPointingOffsets "<< msStokes << " "<<locCfStokes<<endl; Int nPol = msStokes.nelements(); polM.resize(polMap.shape()); polM = -1; @@ -1978,7 +2409,7 @@ void LofarFTMachine::ComputeResiduals(VisBuffer&vb, Bool useCorrected) conjPolMap = cfPolMap; Int i,j,N = cfPolMap.nelements(); - + for(i=0;i<N;i++) if (cfPolMap[i] > -1) { diff --git a/CEP/Imager/LofarFT/src/LofarFTMachineOld.cc b/CEP/Imager/LofarFT/src/LofarFTMachineOld.cc new file mode 100644 index 0000000000000000000000000000000000000000..63de319cb5653155980cdc93d330b6db028bb0bf --- /dev/null +++ b/CEP/Imager/LofarFT/src/LofarFTMachineOld.cc @@ -0,0 +1,2037 @@ +//# LofarFTMachineOld.cc: Gridder for LOFAR data correcting for DD effects +//# +//# Copyright (C) 2011 +//# ASTRON (Netherlands Institute for Radio Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +//# +//# This file is part of the LOFAR software suite. +//# The LOFAR software suite is free software: you can redistribute it and/or +//# modify it under the terms of the GNU General Public License as published +//# by the Free Software Foundation, either version 3 of the License, or +//# (at your option) any later version. +//# +//# The LOFAR software suite 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License along +//# with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>. +//# +//# $Id$ + +#include <lofar_config.h> +// #include <Common/LofarLogger.h> +// #include <Common/Exception.h> +#include <Common/OpenMP.h> +#include <msvis/MSVis/VisibilityIterator.h> +#include <casa/Quanta/UnitMap.h> +#include <casa/Quanta/UnitVal.h> +#include <measures/Measures/Stokes.h> +#include <coordinates/Coordinates/CoordinateSystem.h> +#include <coordinates/Coordinates/DirectionCoordinate.h> +#include <coordinates/Coordinates/SpectralCoordinate.h> +#include <coordinates/Coordinates/StokesCoordinate.h> +#include <coordinates/Coordinates/Projection.h> +#include <ms/MeasurementSets/MSColumns.h> +#include <casa/BasicSL/Constants.h> +#include <scimath/Mathematics/FFTServer.h> +#include <LofarFT/LofarFTMachineOld.h> +#include <LofarFT/LofarCFStore.h> +#include <LofarFT/LofarConvolutionFunctionOld.h> +#include <synthesis/MeasurementComponents/Utils.h> +#include <LofarFT/LofarVisResamplerOld.h> +#include <synthesis/MeasurementComponents/CFStore.h> +#include <LofarFT/LofarVBStore.h> +#include <scimath/Mathematics/RigidVector.h> +#include <msvis/MSVis/StokesVector.h> +#include <synthesis/MeasurementEquations/StokesImageUtil.h> +#include <msvis/MSVis/VisBuffer.h> +#include <msvis/MSVis/VisSet.h> +#include <images/Images/ImageInterface.h> +#include <images/Images/PagedImage.h> +#include <casa/Containers/Block.h> +#include <casa/Containers/Record.h> +#include <casa/Arrays/ArrayLogical.h> +#include <casa/Arrays/ArrayMath.h> +#include <casa/Arrays/Array.h> +#include <casa/Arrays/MaskedArray.h> +#include <casa/Arrays/Vector.h> +#include <casa/Arrays/Slicer.h> +#include <casa/Arrays/Matrix.h> +#include <casa/Arrays/Cube.h> +#include <casa/Arrays/MatrixIter.h> +#include <casa/BasicSL/String.h> +#include <casa/Utilities/Assert.h> +#include <casa/Exceptions/Error.h> +#include <lattices/Lattices/ArrayLattice.h> +#include <measures/Measures/UVWMachine.h> +#include <lattices/Lattices/SubLattice.h> +#include <lattices/Lattices/LCBox.h> +#include <lattices/Lattices/LatticeCache.h> +#include <lattices/Lattices/LatticeFFT.h> +#include <lattices/Lattices/LatticeIterator.h> +#include <lattices/Lattices/LatticeStepper.h> +#include <scimath/Mathematics/ConvolveGridder.h> +#include <casa/Utilities/CompositeNumber.h> +#include <casa/OS/PrecTimer.h> +#include <casa/sstream.h> +#define DORES True + + +using namespace casa; + +namespace LOFAR { //# NAMESPACE CASA - BEGIN + +// LofarFTMachineOld::LofarFTMachineOld(Long icachesize, Int itilesize, +// CountedPtr<VisibilityResamplerBase>&, +// String iconvType, Float padding, +// Bool usezero, Bool useDoublePrec) +//: FTMachine(), padding_p(padding), imageCache(0), cachesize(icachesize), tilesize(itilesize), +// gridder(0), isTiled(False), convType(iconvType), +// maxAbsData(0.0), centerLoc(IPosition(4,0)), offsetLoc(IPosition(4,0)), +// usezero_p(usezero), noPadding_p(False), usePut2_p(False), +// machineName_p("LofarFTMachineOld") + +//{ +//// LOG_INFO ("LofarFTMachineOld::LofarFTMachineOld" << 1.0); +//// logIO() << LogOrigin("LofarFTMachineOld", "LofarFTMachineOld") << LogIO::NORMAL; +// logIO() << "You are using a non-standard FTMachine" << LogIO::WARN << LogIO::POST; +// useDoubleGrid_p=useDoublePrec; +// canComputeResiduals_p=DORES; +//} + +LofarFTMachineOld::LofarFTMachineOld(Long icachesize, Int itilesize, + CountedPtr<VisibilityResamplerBase>&, + String iconvType, + const MeasurementSet& ms, Int nwPlanes, + MPosition mLocation, Float padding, Bool usezero, + Bool useDoublePrec, double wmax, + const String& beamPath, Int verbose, + Int maxsupport, Int oversample, + const String& imgName, + const Matrix<bool>& gridMuellerMask, + const Matrix<bool>& degridMuellerMask) + : FTMachine(), padding_p(padding), imageCache(0), cachesize(icachesize), + tilesize(itilesize), gridder(0), isTiled(False), convType(iconvType), + maxAbsData(0.0), centerLoc(IPosition(4,0)), + offsetLoc(IPosition(4,0)), usezero_p(usezero), noPadding_p(False), + usePut2_p(False), machineName_p("LofarFTMachineOld"), itsMS(ms), + itsNWPlanes(nwPlanes), itsWMax(wmax), itsConvFunc(0), itsBeamPath(beamPath), + itsVerbose(verbose), + itsMaxSupport(maxsupport), itsOversample(oversample), itsImgName(imgName), + itsGridMuellerMask(gridMuellerMask), + itsDegridMuellerMask(degridMuellerMask), + itsGriddingTime(0), itsDegriddingTime(0), itsCFTime(0) +{ + logIO() << LogOrigin("LofarFTMachineOld", "LofarFTMachineOld") << LogIO::NORMAL; + logIO() << "You are using a non-standard FTMachine" << LogIO::WARN << LogIO::POST; + mLocation_p=mLocation; + tangentSpecified_p=False; + useDoubleGrid_p=useDoublePrec; + canComputeResiduals_p=DORES; + itsNThread = OpenMP::maxThreads(); + AlwaysAssert (itsNThread>0, AipsError); + itsGriddedData.resize (itsNThread); + itsGriddedData2.resize (itsNThread); + itsSumPB.resize (itsNThread); + itsSumCFWeight.resize (itsNThread); + itsSumWeight.resize (itsNThread); +} + +//LofarFTMachineOld::LofarFTMachineOld(Long icachesize, Int itilesize, +// CountedPtr<VisibilityResamplerBase>&, +// String iconvType, +// MDirection mTangent, Float padding, Bool usezero, Bool useDoublePrec) +//: FTMachine(), padding_p(padding), imageCache(0), cachesize(icachesize), +// tilesize(itilesize), gridder(0), isTiled(False), convType(iconvType), maxAbsData(0.0), centerLoc(IPosition(4,0)), +// offsetLoc(IPosition(4,0)), usezero_p(usezero), noPadding_p(False), +// usePut2_p(False), machineName_p("LofarFTMachineOld") +//{ +// logIO() << LogOrigin("LofarFTMachineOld", "LofarFTMachineOld") << LogIO::NORMAL; +// logIO() << "You are using a non-standard FTMachine" << LogIO::WARN << LogIO::POST; +// mTangent_p=mTangent; +// tangentSpecified_p=True; +// useDoubleGrid_p=useDoublePrec; +// canComputeResiduals_p=DORES; +//} + +//LofarFTMachineOld::LofarFTMachineOld(Long icachesize, Int itilesize, +// CountedPtr<VisibilityResamplerBase>&, +// String iconvType, MPosition mLocation, MDirection mTangent, Float padding, +// Bool usezero, Bool useDoublePrec) +//: FTMachine(), padding_p(padding), imageCache(0), cachesize(icachesize), +// tilesize(itilesize), gridder(0), isTiled(False), convType(iconvType), maxAbsData(0.0), centerLoc(IPosition(4,0)), +// offsetLoc(IPosition(4,0)), usezero_p(usezero), noPadding_p(False), +// usePut2_p(False),machineName_p("LofarFTMachineOld") +//{ +// logIO() << LogOrigin("LofarFTMachineOld", "LofarFTMachineOld") << LogIO::NORMAL; +// logIO() << "You are using a non-standard FTMachine" << LogIO::WARN << LogIO::POST; +// mLocation_p=mLocation; +// mTangent_p=mTangent; +// tangentSpecified_p=True; +// useDoubleGrid_p=useDoublePrec; +// canComputeResiduals_p=DORES; +//} + +//LofarFTMachineOld::LofarFTMachineOld(const RecordInterface& stateRec) +// : FTMachine() +//{ +// // Construct from the input state record +// logIO() << LogOrigin("LofarFTMachineOld", "LofarFTMachineOld(RecordInterface)") << LogIO::NORMAL; +// logIO() << "You are using a non-standard FTMachine" << LogIO::WARN << LogIO::POST; +// String error; +// if (!fromRecord(error, stateRec)) +// throw (AipsError("Failed to create gridder: " + error)); +// canComputeResiduals_p=DORES; +//} + +//---------------------------------------------------------------------- +LofarFTMachineOld& LofarFTMachineOld::operator=(const LofarFTMachineOld& other) +{ + if(this!=&other) { + //Do the base parameters + FTMachine::operator=(other); + + //private params + imageCache=other.imageCache; + cachesize=other.cachesize; + tilesize=other.tilesize; + convType=other.convType; + uvScale.resize(); + uvOffset.resize(); + uvScale=other.uvScale; + uvOffset=other.uvOffset; + if(other.gridder==0) + gridder=0; + else{ + gridder = new ConvolveGridder<Double, Complex>(IPosition(2, nx, ny), + uvScale, uvOffset, + convType); + } + isTiled=other.isTiled; + //lattice=other.lattice; + lattice=0; + tilesize=other.tilesize; + arrayLattice=0; + maxAbsData=other.maxAbsData; + centerLoc=other.centerLoc; + offsetLoc=other.offsetLoc; + padding_p=other.padding_p; + usezero_p=other.usezero_p; + noPadding_p=other.noPadding_p; + itsMS = other.itsMS; + itsNWPlanes = other.itsNWPlanes; + itsWMax = other.itsWMax; + itsConvFunc = other.itsConvFunc; + ConjCFMap_p = other.ConjCFMap_p; + CFMap_p = other.CFMap_p; + itsNThread = other.itsNThread; + itsGriddedData.resize (itsNThread); + itsGriddedData2.resize (itsNThread); + itsSumPB.resize (itsNThread); + itsSumCFWeight.resize (itsNThread); + itsSumWeight.resize (itsNThread); + itsBeamPath = other.itsBeamPath; + itsVerbose = other.itsVerbose; + itsMaxSupport = other.itsMaxSupport; + itsOversample = other.itsOversample; + itsImgName = other.itsImgName; + itsGridMuellerMask = other.itsGridMuellerMask; + itsDegridMuellerMask = other.itsDegridMuellerMask; + itsGriddingTime = other.itsGriddingTime; + itsDegriddingTime = other.itsDegriddingTime; + itsCFTime = other.itsCFTime; + } + return *this; +} + +//---------------------------------------------------------------------- + LofarFTMachineOld::LofarFTMachineOld(const LofarFTMachineOld& other) : FTMachine(), machineName_p("LofarFTMachineOld") + { + // visResampler_p.init(useDoubleGrid_p); + operator=(other); + } + +//---------------------------------------------------------------------- +// CountedPtr<LofarFTMachineOld> LofarFTMachineOld::clone() const + LofarFTMachineOld* LofarFTMachineOld::clone() const + { + LofarFTMachineOld* newftm = new LofarFTMachineOld(*this); + return newftm; + } + +//---------------------------------------------------------------------- +void LofarFTMachineOld::init() { + + logIO() << LogOrigin("LofarFTMachineOld", "init") << LogIO::NORMAL; + canComputeResiduals_p = DORES; + ok(); + + /* hardwiring isTiled is False + // Padding is possible only for non-tiled processing + if((padding_p*padding_p*image->shape().product())>cachesize) { + isTiled=True; + nx = image->shape()(0); + ny = image->shape()(1); + npol = image->shape()(2); + nchan = image->shape()(3); + } + else { + */ + // We are padding. + isTiled=False; + if(!noPadding_p){ + CompositeNumber cn(uInt(image->shape()(0)*2)); + nx = cn.nextLargerEven(Int(padding_p*Float(image->shape()(0))-0.5)); + ny = cn.nextLargerEven(Int(padding_p*Float(image->shape()(1))-0.5)); + } + else{ + nx = image->shape()(0); + ny = image->shape()(1); + } + npol = image->shape()(2); + nchan = image->shape()(3); + // } + + uvScale.resize(3); + uvScale=0.0; + uvScale(0)=Float(nx)*image->coordinates().increment()(0); + uvScale(1)=Float(ny)*image->coordinates().increment()(1); + uvScale(2)=Float(1)*abs(image->coordinates().increment()(0)); + + uvOffset.resize(3); + uvOffset(0)=nx/2; + uvOffset(1)=ny/2; + uvOffset(2)=0; + + // Now set up the gridder. The possibilities are BOX and SF + if(gridder) delete gridder; gridder=0; + gridder = new ConvolveGridder<Double, Complex>(IPosition(2, nx, ny), + uvScale, uvOffset, + convType); + + // Setup the CFStore object to carry relavent info. of the Conv. Func. + cfs_p.xSupport = gridder->cSupport(); + cfs_p.ySupport = gridder->cSupport(); + cfs_p.sampling.resize(2); + cfs_p.sampling = gridder->cSampling(); + if (cfs_p.rdata.null()) + cfs_p.rdata = new Array<Double>(gridder->cFunction()); + // else + // (*cfs_p.rdata) = gridder->cFunction(); + + padded_shape = image->shape(); + padded_shape(0) = nx; + padded_shape(1) = ny; + if (itsVerbose > 0) { + cout << "Original shape " << image->shape()(0) << "," + << image->shape()(1) << endl; + cout << "Padded shape " << padded_shape(0) << "," + << padded_shape(1) << endl; + } + //assert(padded_shape(0)!=image->shape()(0)); + itsConvFunc = new LofarConvolutionFunctionOld(padded_shape, + image->coordinates().directionCoordinate (image->coordinates().findCoordinate(Coordinate::DIRECTION)), + itsMS, itsNWPlanes, itsWMax, + itsOversample, itsBeamPath, + itsVerbose, itsMaxSupport, + itsImgName); + + // Set up image cache needed for gridding. For BOX-car convolution + // we can use non-overlapped tiles. Otherwise we need to use + // overlapped tiles and additive gridding so that only increments + // to a tile are written. + if(imageCache) delete imageCache; imageCache=0; + + if(isTiled) { + Float tileOverlap=0.5; + if(convType=="box") { + tileOverlap=0.0; + } + else { + tileOverlap=0.5; + tilesize=max(12,tilesize); + } + IPosition tileShape=IPosition(4,tilesize,tilesize,npol,nchan); + Vector<Float> tileOverlapVec(4); + tileOverlapVec=0.0; + tileOverlapVec(0)=tileOverlap; + tileOverlapVec(1)=tileOverlap; + Int tmpCacheVal=static_cast<Int>(cachesize); + imageCache=new LatticeCache <Complex> (*image, tmpCacheVal, tileShape, + tileOverlapVec, + (tileOverlap>0.0)); + + } +} + +// This is nasty, we should use CountedPointers here. +LofarFTMachineOld::~LofarFTMachineOld() +{ + if(imageCache) delete imageCache; imageCache=0; + //if(arrayLattice) delete arrayLattice; arrayLattice=0; + if(gridder) delete gridder; gridder=0; +// delete itsConvFunc; +} + +const Matrix<Float>& LofarFTMachineOld::getAveragePB() const +{ + // Read average beam from disk if not present. + if (itsAvgPB.empty()) { + PagedImage<Float> pim(itsImgName + ".avgpb"); + Array<Float> arr = pim.get(); + itsAvgPB.reference (arr.nonDegenerate(2)); + } + return itsAvgPB; +} + +// Initialize for a transform from the Sky domain. This means that +// we grid-correct, and FFT the image +void LofarFTMachineOld::initializeToVis(ImageInterface<Complex>& iimage, + const VisBuffer& vb) +{ + if (itsVerbose > 0) { + cout<<"---------------------------> initializeToVis"<<endl; + } + image=&iimage; + + ok(); + init(); + + // Initialize the maps for polarization and channel. These maps + // translate visibility indices into image indices + initMaps(vb); + + visResamplers_p.init(useDoubleGrid_p); + visResamplers_p.setMaps(chanMap, polMap); + visResamplers_p.setCFMaps(CFMap_p, ConjCFMap_p); + + // Need to reset nx, ny for padding + // Padding is possible only for non-tiled processing + + // If we are memory-based then read the image in and create an + // ArrayLattice otherwise just use the PagedImage + AlwaysAssert (!isTiled, AipsError); + + // cout<<"LofarFTMachineOld::initializeToVis === is_NOT_Tiled!"<<endl; + //======================CHANGED + //nx=640; + //ny=640; + //======================END CHANGED + //cout << "npol="<<npol<<endl; + IPosition gridShape(4, nx, ny, npol, nchan); + // Size and initialize the grid buffer per thread. + // Note the other itsGriddedData buffers are assigned later. + itsGriddedData[0].resize (gridShape); + itsGriddedData[0] = Complex(); + for (int i=0; i<itsNThread; ++i) { + itsSumPB[i].resize (padded_shape[0], padded_shape[1]); + itsSumPB[i] = Complex(); + itsSumCFWeight[i] = 0.; + itsSumWeight[i].resize(npol, nchan); + itsSumWeight[i] = 0.; + } + + //griddedData can be a reference of image data...if not using model col + //hence using an undocumented feature of resize that if + //the size is the same as old data it is not changed. + //if(!usePut2_p) griddedData.set(0); + + IPosition stride(4, 1); + IPosition blc(4, (nx-image->shape()(0)+(nx%2==0))/2, (ny-image->shape()(1)+(ny%2==0))/2, 0, 0); + IPosition trc(blc+image->shape()-stride); + if (itsVerbose > 0) { + cout<<"LofarFTMachineOld::initializeToVis === blc,trc,nx,ny,image->shape()" + <<blc<<" "<<trc<<" "<<nx<<" "<<ny<<" "<<image->shape()<<endl; + } + IPosition start(4, 0); + itsGriddedData[0](blc, trc) = image->getSlice(start, image->shape()); + //if(arrayLattice) delete arrayLattice; arrayLattice=0; + //======================CHANGED + arrayLattice = new ArrayLattice<Complex>(itsGriddedData[0]); + // Array<Complex> result(IPosition(4, nx, ny, npol, nchan),0.); + // griddedData=result; + // arrayLattice = new ArrayLattice<Complex>(griddedData); + //======================END CHANGED + lattice=arrayLattice; + + //AlwaysAssert(lattice, AipsError); + + logIO() << LogIO::DEBUGGING + << "Starting grid correction and FFT of image" << LogIO::POST; + + //========================== + // Cyr: I have commeneted that part which does the spheroidal correction of the clean components in the image plane. + // We do this based on our estimate of the spheroidal function, stored in an image + // Do the Grid-correction. + // { + // Vector<Complex> correction(nx); + // correction=Complex(1.0, 0.0); + // // Do the Grid-correction + // IPosition cursorShape(4, nx, 1, 1, 1); + // IPosition axisPath(4, 0, 1, 2, 3); + // LatticeStepper lsx(lattice->shape(), cursorShape, axisPath); + // LatticeIterator<Complex> lix(*lattice, lsx); + // for(lix.reset();!lix.atEnd();lix++) { + // gridder->correctX1D(correction, lix.position()(1)); + // lix.rwVectorCursor()/=correction; + // } + // } + + //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // Normalising clean components by the beam + + // const Matrix<Float>& datai = getSpheroidCut(); + + const Matrix<Float>& data = getAveragePB(); + // cout<<"tmp.shape() "<<data.shape()<<" "<<lattice->shape()<<endl; + IPosition pos(4,lattice->shape()[0],lattice->shape()[1],1,1); + IPosition pos2(2,lattice->shape()[0],lattice->shape()[1]); + pos[2]=0.; + pos[3]=0.; + pos2[2]=0.; + pos2[3]=0.; + Int offset_pad(floor(data.shape()[0]-lattice->shape()[0])/2.); + + // cout<<"LofarFTMachineOld::initializeToVis lattice->shape() == "<<lattice->shape()<<endl; + + Complex ff; + double I=100.; + double Q=40.; + double U=20.; + double V=10.; + for(Int k=0;k<lattice->shape()[2];++k){ + ff=0.; + if(k==0){ff=I+Q;} + if(k==1){ff=Complex(U,0.)+Complex(0.,V);} + if(k==2){ff=Complex(U,0.)-Complex(0.,V);} + if(k==3){ff=I-Q;} + for(Int i=0;i<lattice->shape()[0];++i){ + for(Int j=0;j<lattice->shape()[0];++j){ + pos[0]=i; + pos[1]=j; + pos[2]=k; + pos2[0]=i+offset_pad; + pos2[1]=j+offset_pad; + Complex pixel(lattice->getAt(pos)); + double fact(1.); + + // pixel=0.; + // if((pos[0]==351.)&&(pos[1]==319.)){//319 + // pixel=ff;//*139./143;//-100.; + // if(datai(pos2)>1e-6){fact/=datai(pos2);};//*datai(pos2);}; + // //if(data(pos2)>1e-6){fact/=sqrt(data(pos2));};//*datai(pos2);}; + // pixel*=Complex(fact); + // } + + fact/=sqrt(data(pos2)); + pixel*=Complex(fact); + + lattice->putAt(pixel,pos); + } + } + } + + + //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + // Now do the FFT2D in place + LatticeFFT::cfft2d(*lattice); + + logIO() << LogIO::DEBUGGING + << "Finished grid correction and FFT of image" << LogIO::POST; + + // for(uInt k=0;k<lattice->shape()[2];++k){ + // for(uInt i=0;i<lattice->shape()[0];++i){ + // for(uInt j=0;j<lattice->shape()[0];++j){ + // pos[0]=i; + // pos[1]=j; + // pos[2]=k; + // Complex pixel(lattice->getAt(pos)); + // //cout<<"i,j,pixel value: "<<i<<" "<<j<<" "<<pixel<<endl; + + // }; + // }; + // }; +} + + + + +void LofarFTMachineOld::finalizeToVis() +{ + if (itsVerbose > 0) { + cout<<"---------------------------> finalizeToVis"<<endl; + } +} + + +// Initialize the FFT to the Sky. Here we have to setup and initialize the +// grid. +void LofarFTMachineOld::initializeToSky(ImageInterface<Complex>& iimage, + Matrix<Float>& weight, const VisBuffer& vb) +{ + // image always points to the image + image=&iimage; + if (itsVerbose > 0) { + cout<<"---------------------------> initializeToSky"<<endl; + } + init(); + + // Initialize the maps for polarization and channel. These maps + // translate visibility indices into image indices + initMaps(vb); + + visResamplers_p.init(useDoubleGrid_p); + visResamplers_p.setMaps(chanMap, polMap); + visResamplers_p.setCFMaps(CFMap_p, ConjCFMap_p); + + // Initialize for in memory or to disk gridding. lattice will + // point to the appropriate Lattice, either the ArrayLattice for + // in memory gridding or to the image for to disk gridding. + AlwaysAssert (!isTiled, AipsError); + IPosition gridShape(4, nx, ny, npol, nchan); + // Size and initialize the grid buffer per thread. + for (int i=0; i<itsNThread; ++i) { + itsGriddedData[i].resize (gridShape); + itsGriddedData[i] = Complex(); + itsSumPB[i].resize (padded_shape[0], padded_shape[1]); + itsSumPB[i] = Complex(); + itsSumCFWeight[i] = 0.; + itsSumWeight[i].resize (npol, nchan); + itsSumWeight[i] = 0.; + } + weight.resize(itsSumWeight[0].shape()); + weight=0.0; + + //iimage.get(griddedData, False); + //if(arrayLattice) delete arrayLattice; arrayLattice=0; + arrayLattice = new ArrayLattice<Complex>(itsGriddedData[0]); + lattice=arrayLattice; + // if(useDoubleGrid_p) visResampler_p->initializePutBuffers(griddedData2, sumWeight); + // else visResampler_p->initializePutBuffers(griddedData, sumWeight); +//// Are the following calls needed for LOFAR? +/// if(useDoubleGrid_p) visResamplers_p.initializeToSky(griddedData2, sumWeight); +/// else visResamplers_p.initializeToSky(griddedData, sumWeight); + //AlwaysAssert(lattice, AipsError); +} + + + +void LofarFTMachineOld::finalizeToSky() +{ + //AlwaysAssert(lattice, AipsError); + // Now we flush the cache and report statistics + // For memory based, we don't write anything out yet. + if (itsVerbose > 0) { + cout<<"---------------------------> finalizeToSky"<<endl; + } + // DEBUG: Store the grid per thread + uInt nx(itsGriddedData[0].shape()[0]); + IPosition shapecube(3,nx,nx,4); + for (int ii=0; ii<itsNThread; ++ii) { + Cube<Complex> tempimage(shapecube,0.); + for(Int k=0;k<4;++k){ + for(uInt i=0;i<nx;++i){ + for(uInt j=0;j<nx;++j){ + IPosition pos(4,i,j,k,0); + Complex pixel(itsGriddedData[ii](pos)); + tempimage(i,j,k)=pixel; + } + } + } + store(tempimage,"Grid"+String::toString(ii)+".img"); + } + + // Add all buffers into the first one. + for (int i=1; i<itsNThread; ++i) { + itsGriddedData[0] += itsGriddedData[i]; + itsSumWeight[0] += itsSumWeight[i]; + itsSumCFWeight[0] += itsSumCFWeight[i]; + itsSumPB[0] += itsSumPB[i]; + } + + Cube<Complex> tempimage(shapecube,0.); + for(Int k=0;k<4;++k){ + for(uInt i=0;i<nx;++i){ + for(uInt j=0;j<nx;++j){ + IPosition pos(4,i,j,k,0); + Complex pixel(itsGriddedData[0](pos)); + tempimage(i,j,k)=pixel; + } + } + } + store(tempimage,"Grid00.img"); + + // if(useDoubleGrid_p) visResamplers_p[0].GatherGrids(griddedData2, sumWeight); + // else visResamplers_p[0].GatherGrids(griddedData, sumWeight); +//// Are the following calls needed for LOFAR? +/// if(useDoubleGrid_p) visResamplers_p.finalizeToSky(griddedData2, sumWeight); +/// else visResamplers_p.finalizeToSky(griddedData, sumWeight); +} + + + +Array<Complex>* LofarFTMachineOld::getDataPointer(const IPosition& centerLoc2D, + Bool readonly) { + Array<Complex>* result; + // Is tiled: get tiles and set up offsets + centerLoc(0)=centerLoc2D(0); + centerLoc(1)=centerLoc2D(1); + result=&imageCache->tile(offsetLoc,centerLoc, readonly); + gridder->setOffset(IPosition(2, offsetLoc(0), offsetLoc(1))); + return result; +} + +void LofarFTMachineOld::put(const VisBuffer& vb, Int row, Bool dopsf, + FTMachine::Type type) +{ + if (itsVerbose > 0) { + logIO() << LogOrigin("LofarFTMachineOld", "put") << LogIO::NORMAL + << "I am gridding " << vb.nRow() << " row(s)." << LogIO::POST; + logIO() << LogIO::NORMAL << "Padding is " << padding_p << LogIO::POST; + } + + + gridOk(gridder->cSupport()(0)); + + //Check if ms has changed then cache new spw and chan selection + if(vb.newMS()) matchAllSpwChans(vb); + + //Here we redo the match or use previous match + + //Channel matching for the actual spectral window of buffer + if (doConversion_p[vb.spectralWindow()]) { + matchChannel(vb.spectralWindow(), vb); + } else { + chanMap.resize(); + chanMap=multiChanMap_p[vb.spectralWindow()]; + } + + //No point in reading data if it's not matching in frequency + if(max(chanMap)==-1) return; + + const Matrix<Float> *imagingweight; + imagingweight=&(vb.imagingWeight()); + + // dopsf=true; + + if(dopsf) {type=FTMachine::PSF;} + + Cube<Complex> data; + //Fortran gridder need the flag as ints + Cube<Int> flags; + Matrix<Float> elWeight; + interpolateFrequencyTogrid(vb, *imagingweight,data, flags, elWeight, type); + + + Int startRow, endRow, nRow; + if (row==-1) { nRow=vb.nRow(); startRow=0; endRow=nRow-1; } + else { nRow=1; startRow=row; endRow=row; } + + // Get the uvws in a form that Fortran can use and do that + // necessary phase rotation. On a Pentium Pro 200 MHz + // when null, this step takes about 50us per uvw point. This + // is just barely noticeable for Stokes I continuum and + // irrelevant for other cases. + Matrix<Double> uvw(3, vb.uvw().nelements()); uvw=0.0; + Vector<Double> dphase(vb.uvw().nelements()); dphase=0.0; + //NEGATING to correct for an image inversion problem + for (Int i=startRow;i<=endRow;i++) { + for (Int idim=0;idim<2;idim++) uvw(idim,i)=-vb.uvw()(i)(idim); + uvw(2,i)=vb.uvw()(i)(2); + } + + rotateUVW(uvw, dphase, vb); + refocus(uvw, vb.antenna1(), vb.antenna2(), dphase, vb); + + // Set up VBStore object to point to the relevant info of the VB. + LofarVBStore vbs; + makeCFPolMap(vb,cfStokes_p,CFMap_p); + makeConjPolMap(vb,CFMap_p,ConjCFMap_p); + + // Determine the baselines in the VisBuffer. + const Vector<Int>& ant1 = vb.antenna1(); + const Vector<Int>& ant2 = vb.antenna2(); + int nrant = 1 + max(max(ant1), max(ant2)); + // Sort on baseline (use a baseline nr which is faster to sort). + Vector<Int> blnr(nrant*ant1); + blnr += ant2; // This is faster than nrant*ant1+ant2 in a single line + Vector<uInt> blIndex; + GenSortIndirect<Int>::sort (blIndex, blnr); + // Now determine nr of unique baselines and their start index. + vector<int> blStart, blEnd; + blStart.reserve (nrant*(nrant+1)/2); + blEnd.reserve (nrant*(nrant+1)/2); + Int lastbl = -1; + Int lastIndex = 0; + bool usebl = false; + bool allFlagged = true; + const Vector<Bool>& flagRow = vb.flagRow(); + for (uint i=0; i<blnr.size(); ++i) { + Int inx = blIndex[i]; + Int bl = blnr[inx]; + if (bl != lastbl) { + // New baseline. Write the previous end index if applicable. + if (usebl && !allFlagged) { + double Wmean(0.5*(vb.uvw()[blIndex[lastIndex]](2) + vb.uvw()[blIndex[i-1]](2))); + if (abs(Wmean) <= itsWMax) { + if (itsVerbose > 1) { + cout<<"using w="<<Wmean<<endl; + } + blStart.push_back (lastIndex); + blEnd.push_back (i-1); + } + } + // Skip auto-correlations and high W-values. + // All w values are close, so if first w is too high, skip baseline. + usebl = false; + + if (ant1[inx] != ant2[inx]) { + usebl = true; + } + lastbl=bl; + lastIndex=i; + } + // Test if the row is flagged. + if (! flagRow[inx]) { + allFlagged = false; + } + } + // Write the last end index if applicable. + if (usebl && !allFlagged) { + double Wmean(0.5*(vb.uvw()[blIndex[lastIndex]](2) + vb.uvw()[blIndex[blnr.size()-1]](2))); + if (abs(Wmean) <= itsWMax) { + if (itsVerbose > 1) { + cout<<"...using w="<<Wmean<<endl; + } + blStart.push_back (lastIndex); + blEnd.push_back (blnr.size()-1); + } + } + // Determine the time center of this data chunk. + const Vector<Double>& times = vb.timeCentroid(); + double time = 0.5 * (times[times.size()-1] + times[0]); + + vbs.nRow_p = vb.nRow(); + vbs.uvw_p.reference(uvw); + vbs.imagingWeight_p.reference(elWeight); + vbs.visCube_p.reference(data); + // vbs.visCube_p.reference(vb.modelVisCube()); + vbs.freq_p.reference(interpVisFreq_p); + vbs.rowFlag_p.reference(vb.flagRow()); + + // Really nice way of converting a Cube<Int> to Cube<Bool>. + // However the VBS objects should ultimately be references + // directly to bool cubes. + //************** + vbs.flagCube_p.resize(flags.shape()); vbs.flagCube_p = False; vbs.flagCube_p(flags!=0) = True; + // vbs.flagCube_p.reference(vb.flagCube()); + //************** + + // Determine the terms of the Mueller matrix that should be calculated + visResamplers_p.setParams(uvScale,uvOffset,dphase); + visResamplers_p.setMaps(chanMap, polMap); + + // First compute the A-terms for all stations (if needed). + itsConvFunc->computeAterm (time); + + uInt Nchannels = vb.nChannel(); + + itsTotalTimer.start(); +#pragma omp parallel + { + // Thread-private variables. + PrecTimer gridTimer; + PrecTimer cfTimer; + // The for loop can be parallellized. This must be done dynamically, + // because the execution times of iterations can vary greatly. +#pragma omp for schedule(dynamic) + for (int i=0; i<int(blStart.size()); ++i) { + Int ist = blIndex[blStart[i]]; + Int iend = blIndex[blEnd[i]]; + + // compute average weight for baseline for CF averaging + double average_weight(0.); + uInt Nvis(0); + for(Int j=ist; j<iend; ++j){ + uInt row=blIndex[j]; + if(!vbs.rowFlag()[row]){ + Nvis+=1; + for(uint k=0; k<Nchannels; ++k) { + average_weight=average_weight+vbs.imagingWeight()(k,row); + } + } + } + average_weight=average_weight/Nvis; + /// itsSumWeight += average_weight * average_weight; + if (itsVerbose > 1) { + cout<<"average weights= "<<average_weight<<", Nvis="<<Nvis<<endl; + } + + int threadNum = OpenMP::threadNum(); + + // Get the convolution function. + if (itsVerbose > 1) { + cout.precision(20); + cout<<"A1="<<ant1[ist]<<", A2="<<ant2[ist]<<", time="<<fixed<<time<<endl; + } + LofarCFStore cfStore; + //#pragma omp critical(LofarFTMachineOld_makeConvolutionFunction) + //{ + cfTimer.start(); + cfStore = + itsConvFunc->makeConvolutionFunction (ant1[ist], ant2[ist], time, + 0.5*(vbs.uvw()(2,ist) + vbs.uvw()(2,iend)), + itsGridMuellerMask, false, + average_weight, + itsSumPB[threadNum], + itsSumCFWeight[threadNum]); + cfTimer.stop(); + //}; + + + //cout<<"DONE LOADING CF..."<<endl; + //Double or single precision gridding. + // cout<<"============================================"<<endl; + // cout<<"Antenna "<<ant1[ist]<<" and "<<ant2[ist]<<endl; + //#pragma omp critical(LofarFTMachineOld_makeConvolutionFunction) + //{ + if (useDoubleGrid_p) { + visResamplers_p.lofarDataToGrid(itsGriddedData2[threadNum], vbs, blIndex, + blStart[i], blEnd[i], + itsSumWeight[threadNum], dopsf, cfStore); + } else { + if (itsVerbose > 1) { + cout<<" gridding"<<" thread="<<threadNum<<'('<<itsNThread<<"), A1="<<ant1[ist]<<", A2="<<ant2[ist]<<", time=" <<time<<endl; + } + gridTimer.start(); + visResamplers_p.lofarDataToGrid + (itsGriddedData[threadNum], vbs, blIndex, blStart[i], + blEnd[i], itsSumWeight[threadNum], dopsf, cfStore); + gridTimer.stop(); + } + // } // end omp critical + } // end omp for + double cftime = cfTimer.getReal(); +#pragma omp atomic + itsCFTime += cftime; + double gtime = gridTimer.getReal(); +#pragma omp atomic + itsGriddingTime += gtime; + } // end omp parallel + itsTotalTimer.stop(); +} + + +// Degrid +void LofarFTMachineOld::get(VisBuffer& vb, Int row) +{ + if (itsVerbose > 0) { + cout<<"///////////////////// GET!!!!!!!!!!!!!!!!!!"<<endl; + } + gridOk(gridder->cSupport()(0)); + // If row is -1 then we pass through all rows + Int startRow, endRow, nRow; + if (row < 0) { nRow=vb.nRow(); startRow=0; endRow=nRow-1;} + else { nRow=1; startRow=row; endRow=row; } + + // Get the uvws in a form that Fortran can use + Matrix<Double> uvw(3, vb.uvw().nelements()); uvw=0.0; + Vector<Double> dphase(vb.uvw().nelements()); dphase=0.0; + //NEGATING to correct for an image inversion problem + for (Int i=startRow;i<=endRow;i++) { + for (Int idim=0;idim<2;idim++) uvw(idim,i)=-vb.uvw()(i)(idim); + uvw(2,i)=vb.uvw()(i)(2); + } + rotateUVW(uvw, dphase, vb); + refocus(uvw, vb.antenna1(), vb.antenna2(), dphase, vb); + + //Check if ms has changed then cache new spw and chan selection + if(vb.newMS()) matchAllSpwChans(vb); + + + //Channel matching for the actual spectral window of buffer + if(doConversion_p[vb.spectralWindow()]) + matchChannel(vb.spectralWindow(), vb); + else + { + chanMap.resize(); + chanMap=multiChanMap_p[vb.spectralWindow()]; + } + + //No point in reading data if its not matching in frequency + if(max(chanMap)==-1) return; + + Cube<Complex> data; + Cube<Int> flags; + getInterpolateArrays(vb, data, flags); + + // Apparently we don't support "tiled gridding" any more (good! :)). + if(isTiled) + throw(SynthesisFTMachineError("LofarFTMachineOld::get(): Internal error. isTiled is True. ")); + + LofarVBStore vbs; + vbs.nRow_p = vb.nRow(); + vbs.beginRow_p = 0; + vbs.endRow_p = vbs.nRow_p; + + vbs.uvw_p.reference(uvw); + // vbs.imagingWeight.reference(elWeight); + vbs.visCube_p.reference(data); + + vbs.freq_p.reference(interpVisFreq_p); + vbs.rowFlag_p.resize(0); vbs.rowFlag_p = vb.flagRow(); + if(!usezero_p) + for (Int rownr=startRow; rownr<=endRow; rownr++) + if(vb.antenna1()(rownr)==vb.antenna2()(rownr)) vbs.rowFlag_p(rownr)=True; + + // Really nice way of converting a Cube<Int> to Cube<Bool>. + // However these should ultimately be references directly to bool + // cubes. + vbs.flagCube_p.resize(flags.shape()); vbs.flagCube_p = False; vbs.flagCube_p(flags!=0) = True; + // vbs.rowFlag.resize(rowFlags.shape()); vbs.rowFlag = False; vbs.rowFlag(rowFlags) = True; + + // Determine the terms of the Mueller matrix that should be calculated + visResamplers_p.setParams(uvScale,uvOffset,dphase); + visResamplers_p.setMaps(chanMap, polMap); + + + // Determine the baselines in the VisBuffer. + const Vector<Int>& ant1 = vb.antenna1(); + const Vector<Int>& ant2 = vb.antenna2(); + int nrant = 1 + max(max(ant1), max(ant2)); + // Sort on baseline (use a baseline nr which is faster to sort). + Vector<Int> blnr(nrant*ant1); + blnr += ant2; // This is faster than nrant*ant1+ant2 in a single line + Vector<uInt> blIndex; + GenSortIndirect<Int>::sort (blIndex, blnr); + // Now determine nr of unique baselines and their start index. + vector<int> blStart, blEnd; + blStart.reserve (nrant*(nrant+1)/2); + blEnd.reserve (nrant*(nrant+1)/2); + Int lastbl = -1; + Int lastIndex = 0; + bool usebl = false; + bool allFlagged = true; + const Vector<Bool>& flagRow = vb.flagRow(); + for (uint i=0; i<blnr.size(); ++i) { + Int inx = blIndex[i]; + Int bl = blnr[inx]; + if (bl != lastbl) { + // New baseline. Write the previous end index if applicable. + if (usebl && !allFlagged) { + double Wmean(0.5*(vb.uvw()[blIndex[lastIndex]](2) + vb.uvw()[blIndex[i-1]](2))); + if (abs(Wmean) <= itsWMax) { + if (itsVerbose > 1) { + cout<<"using w="<<Wmean<<endl; + } + blStart.push_back (lastIndex); + blEnd.push_back (i-1); + } + } + // Skip auto-correlations and high W-values. + // All w values are close, so if first w is too high, skip baseline. + usebl = false; + + if (ant1[inx] != ant2[inx]) { + usebl = true; + } + lastbl=bl; + lastIndex=i; + } + // Test if the row is flagged. + if (! flagRow[inx]) { + allFlagged = false; + } + } + // Write the last end index if applicable. + if (usebl && !allFlagged) { + double Wmean(0.5*(vb.uvw()[blIndex[lastIndex]](2) + vb.uvw()[blIndex[blnr.size()-1]](2))); + if (abs(Wmean) <= itsWMax) { + if (itsVerbose > 1) { + cout<<"...using w="<<Wmean<<endl; + } + blStart.push_back (lastIndex); + blEnd.push_back (blnr.size()-1); + } + } + + // Determine the time center of this data chunk. + const Vector<Double>& times = vb.timeCentroid(); + double time = 0.5 * (times[times.size()-1] + times[0]); + //ROVisIter& via(vb.iter()); + + // First compute the A-terms for all stations (if needed). + itsConvFunc->computeAterm (time); + + itsTotalTimer.start(); +#pragma omp parallel + { + // Thread-private variables. + PrecTimer degridTimer; + PrecTimer cfTimer; + // The for loop can be parallellized. This must be done dynamically, + // because the execution times of iterations can vary greatly. + #pragma omp for schedule(dynamic) + for (int i=0; i<int(blStart.size()); ++i) { + // #pragma omp critical(LofarFTMachineOld_lofarGridToData) + // { + Int ist = blIndex[blStart[i]]; + Int iend = blIndex[blEnd[i]]; + int threadNum = OpenMP::threadNum(); + // Get the convolution function for degridding. + if (itsVerbose > 1) { + cout<<"ANTENNA "<<ant1[ist]<<" "<<ant2[ist]<<endl; + } + cfTimer.start(); + LofarCFStore cfStore = + itsConvFunc->makeConvolutionFunction (ant1[ist], ant2[ist], time, + 0.5*(vbs.uvw()(2,ist) + vbs.uvw()(2,iend)), + itsDegridMuellerMask, + true, + 0.0, + itsSumPB[threadNum], + itsSumCFWeight[threadNum]); + cfTimer.stop(); + + //Double or single precision gridding. + // cout<<"GRID "<<ant1[ist]<<" "<<ant2[ist]<<endl; + degridTimer.start(); + visResamplers_p.lofarGridToData(vbs, itsGriddedData[0], + blIndex, blStart[i], blEnd[i], cfStore); + degridTimer.stop(); + } // end omp for + double cftime = cfTimer.getReal(); +#pragma omp atomic + itsCFTime += cftime; + double gtime = degridTimer.getReal(); +#pragma omp atomic + itsGriddingTime += gtime; + } // end omp parallel + itsTotalTimer.stop(); + interpolateFrequencyFromgrid(vb, data, FTMachine::MODEL); +} + + + +// Finalize the FFT to the Sky. Here we actually do the FFT and +// return the resulting image +ImageInterface<Complex>& LofarFTMachineOld::getImage(Matrix<Float>& weights, Bool normalize) +{ + //AlwaysAssert(lattice, AipsError); + AlwaysAssert(gridder, AipsError); + AlwaysAssert(image, AipsError); + logIO() << LogOrigin("LofarFTMachineOld", "getImage") << LogIO::NORMAL; + + if (itsVerbose > 0) { + cout<<"GETIMAGE"<<endl; + } + itsAvgPB.reference (itsConvFunc->Compute_avg_pb(itsSumPB[0], itsSumCFWeight[0])); + + //cout<<"weights.shape() "<<weights.shape()<<" "<<sumWeight<<endl; + + weights.resize(itsSumWeight[0].shape()); + + convertArray(weights, itsSumWeight[0]); + // If the weights are all zero then we cannot normalize + // otherwise we don't care. + if(normalize&&max(weights)==0.0) { + logIO() << LogIO::SEVERE << "No useful data in LofarFTMachineOld: weights all zero" + << LogIO::POST; + } + else { + + const IPosition latticeShape = lattice->shape(); + + logIO() << LogIO::DEBUGGING + << "Starting FFT and scaling of image" << LogIO::POST; + + + + // if(useDoubleGrid_p){ + // convertArray(griddedData, griddedData2); + // //Don't need the double-prec grid anymore... + // griddedData2.resize(); + // } + + // x and y transforms + // LatticeFFT::cfft2d(*lattice,False); + // + // Retain the double precision grid for FFT as well. Convert it + // to single precision just after (since images are still single + // precision). + // + if(useDoubleGrid_p) { + ArrayLattice<DComplex> darrayLattice(itsGriddedData2[0]); + LatticeFFT::cfft2d(darrayLattice,False); + convertArray(itsGriddedData[0], itsGriddedData2[0]); + //Don't need the double-prec grid anymore... + ///griddedData2.resize(); + } else { + LatticeFFT::cfft2d(*lattice, False); + } + + if (itsVerbose > 0) { + cout<<"POLMAP::::::: "<<polMap<<endl; + cout<<"POLMAP::::::: "<<CFMap_p<<endl; + } + //cout<<"CFPOLMAP::::::: "<<cfPolMap<<endl; + //Int i,j,N = cfPolMap.nelements(); + //for(i=0;i<N;i++){ + // if (cfPolMap[i] > -1){cout<<"cfPolMap[i]<<visStokes[i]"<<cfPolMap[i]<<" "<<visStokes[i]<<endl;}; + //}; + + + // Cyr: This does a normalisation by the number of pixel and spheroidal + // function in the dirty image. + // I have commented out the spheroidal normalisation (correctX1D part) + { + Int inx = lattice->shape()(0); + Int iny = lattice->shape()(1); + Vector<Complex> correction(inx); + correction=Complex(1.0, 0.0); + // Do the Grid-correction + IPosition cursorShape(4, inx, 1, 1, 1); + IPosition axisPath(4, 0, 1, 2, 3); + LatticeStepper lsx(lattice->shape(), cursorShape, axisPath); + LatticeIterator<Complex> lix(*lattice, lsx); + for(lix.reset();!lix.atEnd();lix++) { + Int pol=lix.position()(2); + //cout<<"pol "<<pol<<endl; + Int chan=lix.position()(3); + if(weights(pol, chan)!=0.0) { + //gridder->correctX1D(correction, lix.position()(1)); + //cout<<"correction "<<correction<<endl; + //lix.rwVectorCursor()/=correction; + if(normalize) { + Complex rnorm(Float(inx)*Float(iny)/weights(pol,chan)); + lix.rwCursor()*=rnorm; + //cout<<"rnorm "<<rnorm<<endl; + } + else { + Complex rnorm(Float(inx)*Float(iny)); + lix.rwCursor()*=rnorm; + //cout<<"rnorm "<<rnorm<<endl; + } + } + else { + lix.woCursor()=0.0; + } + } + } + + //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // Normalising dirty image by the spheroidal function + + // String namei("sphe.img"); + // ostringstream name(namei); + // PagedImage<Float> tmp(name.str().c_str()); + // Slicer slice(IPosition(4,0,0,0,0), tmp.shape(), IPosition(4,1,1,1,1)); + // Array<Float> data; + // tmp.doGetSlice(data, slice); + // IPosition posi(4,lattice->shape()[0],lattice->shape()[1],1,1); + // IPosition posi2(4,lattice->shape()[0],lattice->shape()[1],1,1); + // posi[2]=0.; + // posi[3]=0.; + // posi2[2]=0.; + // posi2[3]=0.; + // Int offset_pad(floor(data.shape()[0]-lattice->shape()[0])/2.); + + + + + // for(uInt k=0;k<lattice->shape()[2];++k){ + // for(uInt i=0;i<lattice->shape()[0];++i){ + // for(uInt j=0;j<lattice->shape()[0];++j){ + // posi[0]=i; + // posi[1]=j; + // posi[2]=k; + // posi2[0]=i+offset_pad; + // posi2[1]=j+offset_pad; + // Complex pixel(lattice->getAt(posi)); + // //pixel/=data(posi2);//*data(posi2); + // lattice->putAt(pixel,posi); + // }; + // }; + // }; + //==================================================================================================================== + //==================================================================================================================== + //==================================================================================================================== + // Cyr: Normalisation by the beam!!!!! + //cout<<"lattice shape: "<<lattice->shape()<<endl; + IPosition pos(4,lattice->shape()[0],lattice->shape()[1],1,1); + uInt shapeout(floor(lattice->shape()[0]/padding_p)); + uInt istart(floor((lattice->shape()[0]-shapeout)/2.)); + Cube<Complex> tempimage(IPosition(3,shapeout,shapeout,lattice->shape()[2])); + + pos[3]=0.; + for(Int k=0;k<lattice->shape()[2];++k){ + for(uInt i=0;i<shapeout;++i){ + for(uInt j=0;j<shapeout;++j){ + pos[0]=i+istart; + pos[1]=j+istart; + pos[2]=k; + Complex pixel(lattice->getAt(pos)); + //cout<<"pixel value: "<<pixel<<", Primary beam: "<<avg_PB(i,j)<<endl; + pixel/=sqrt(itsAvgPB(i+istart,j+istart));//*sqrt(avg_PB(i+istart,j+istart)); + //pixel*=(lattice->shape()[0]*lattice->shape()[0]); + lattice->putAt(pixel,pos); + //tempimage(i,j,k)=pixel/weights(0,0); + } + } + } + // uInt count_cycle(0); + // Bool written(false); + + // while(!written){ + // cout<<"count_cycle ======================= "<<count_cycle<<" "<<normalize<<endl; + // File myFile("Cube_dirty.img"+String::toString(count_cycle)); + // if(!myFile.exists()){ + // written=true; + // store(tempimage,"Cube_dirty.img"+String::toString(count_cycle)); + // } + // else{ + // count_cycle++; + // }; + // }; + + //==================================================================================================================== + //==================================================================================================================== + //==================================================================================================================== + + + + if(!isTiled) { + // Check the section from the image BEFORE converting to a lattice + IPosition blc(4, (nx-image->shape()(0)+(nx%2==0))/2, (ny-image->shape()(1)+(ny%2==0))/2, 0, 0); + IPosition stride(4, 1); + IPosition trc(blc+image->shape()-stride); + // Do the copy + IPosition start(4, 0); + image->put(itsGriddedData[0](blc, trc)); + } + } + + //store(*image,"last.img"); + return *image; +} + +// Get weight image +void LofarFTMachineOld::getWeightImage(ImageInterface<Float>& weightImage, Matrix<Float>& weights) +{ + + logIO() << LogOrigin("LofarFTMachineOld", "getWeightImage") << LogIO::NORMAL; + + weights.resize(itsSumWeight[0].shape()); + convertArray(weights,itsSumWeight[0]); + + const IPosition latticeShape = weightImage.shape(); + + Int nx=latticeShape(0); + Int ny=latticeShape(1); + + IPosition loc(2, 0); + IPosition cursorShape(4, nx, ny, 1, 1); + IPosition axisPath(4, 0, 1, 2, 3); + LatticeStepper lsx(latticeShape, cursorShape, axisPath); + LatticeIterator<Float> lix(weightImage, lsx); + for(lix.reset();!lix.atEnd();lix++) { + Int pol=lix.position()(2); + Int chan=lix.position()(3); + lix.rwCursor()=weights(pol,chan); + } +} + +Bool LofarFTMachineOld::toRecord(String& error, RecordInterface& outRec, + Bool withImage) { + + // Save the current LofarFTMachineOld object to an output state record + Bool retval = True; + + Double cacheVal=(Double)cachesize; + outRec.define("cache", cacheVal); + outRec.define("tile", tilesize); + outRec.define("gridfunction", convType); + + Vector<Double> phaseValue(2); + String phaseUnit; + phaseValue=mTangent_p.getAngle().getValue(); + phaseUnit= mTangent_p.getAngle().getUnit(); + outRec.define("phasevalue", phaseValue); + outRec.define("phaseunit", phaseUnit); + + Vector<Double> dirValue(3); + String dirUnit; + dirValue=mLocation_p.get("m").getValue(); + dirUnit=mLocation_p.get("m").getUnit(); + outRec.define("dirvalue", dirValue); + outRec.define("dirunit", dirUnit); + + outRec.define("padding", padding_p); + outRec.define("maxdataval", maxAbsData); + + Vector<Int> center_loc(4), offset_loc(4); + for (Int k=0; k<4 ; k++){ + center_loc(k)=centerLoc(k); + offset_loc(k)=offsetLoc(k); + } + outRec.define("centerloc", center_loc); + outRec.define("offsetloc", offset_loc); + outRec.define("sumofweights", itsSumWeight[0]); + if(withImage && image){ + ImageInterface<Complex>& tempimage(*image); + Record imageContainer; + retval = (retval || tempimage.toRecord(error, imageContainer)); + outRec.defineRecord("image", imageContainer); + } + return retval; +} + +Bool LofarFTMachineOld::fromRecord(String& error, const RecordInterface& inRec) +{ + Bool retval = True; + gridder=0; imageCache=0; lattice=0; arrayLattice=0; + Double cacheVal; + inRec.get("cache", cacheVal); + cachesize=(Long)cacheVal; + inRec.get("tile", tilesize); + inRec.get("gridfunction", convType); + + Vector<Double> phaseValue(2); + inRec.get("phasevalue",phaseValue); + String phaseUnit; + inRec.get("phaseunit",phaseUnit); + Quantity val1(phaseValue(0), phaseUnit); + Quantity val2(phaseValue(1), phaseUnit); + MDirection phasecenter(val1, val2); + + mTangent_p=phasecenter; + // This should be passed down too but the tangent plane is + // expected to be specified in all meaningful cases. + tangentSpecified_p=True; + Vector<Double> dirValue(3); + String dirUnit; + inRec.get("dirvalue", dirValue); + inRec.get("dirunit", dirUnit); + MVPosition dummyMVPos(dirValue(0), dirValue(1), dirValue(2)); + MPosition mLocation(dummyMVPos, MPosition::ITRF); + mLocation_p=mLocation; + + inRec.get("padding", padding_p); + inRec.get("maxdataval", maxAbsData); + + Vector<Int> center_loc(4), offset_loc(4); + inRec.get("centerloc", center_loc); + inRec.get("offsetloc", offset_loc); + uInt ndim4 = 4; + centerLoc=IPosition(ndim4, center_loc(0), center_loc(1), center_loc(2), + center_loc(3)); + offsetLoc=IPosition(ndim4, offset_loc(0), offset_loc(1), offset_loc(2), + offset_loc(3)); + inRec.get("sumofweights", itsSumWeight[0]); + if(inRec.nfields() > 12 ){ + Record imageAsRec=inRec.asRecord("image"); + if(!image) { + image= new TempImage<Complex>(); + } + retval = (retval || image->fromRecord(error, imageAsRec)); + + // Might be changing the shape of sumWeight + init(); + + if(isTiled) { + lattice=CountedPtr<Lattice<Complex> >(image, False); + } + else { + // Make the grid the correct shape and turn it into an array lattice + // Check the section from the image BEFORE converting to a lattice + IPosition gridShape(4, nx, ny, npol, nchan); + itsGriddedData[0].resize(gridShape); + itsGriddedData[0]=Complex(0.0); + IPosition blc(4, (nx-image->shape()(0)+(nx%2==0))/2, (ny-image->shape()(1)+(ny%2==0))/2, 0, 0); + IPosition start(4, 0); + IPosition stride(4, 1); + IPosition trc(blc+image->shape()-stride); + itsGriddedData[0](blc, trc)=image->getSlice(start, image->shape()); + + //if(arrayLattice) delete arrayLattice; arrayLattice=0; + arrayLattice = new ArrayLattice<Complex>(itsGriddedData[0]); + lattice=arrayLattice; + } + + //AlwaysAssert(lattice, AipsError); + AlwaysAssert(gridder, AipsError); + AlwaysAssert(image, AipsError); + } + return retval; +} + +void LofarFTMachineOld::ok() { + AlwaysAssert(image, AipsError); +} + +// Make a plain straightforward honest-to-God image. This returns +// a complex image, without conversion to Stokes. The representation +// is that required for the visibilities. +//---------------------------------------------------------------------- +void LofarFTMachineOld::makeImage(FTMachine::Type type, + VisSet& vs, + ImageInterface<Complex>& theImage, + Matrix<Float>& weight) { + + + logIO() << LogOrigin("LofarFTMachineOld", "makeImage") << LogIO::NORMAL; + + if(type==FTMachine::COVERAGE) { + logIO() << "Type COVERAGE not defined for Fourier transforms" << LogIO::EXCEPTION; + } + + + // Initialize the gradients + ROVisIter& vi(vs.iter()); + + // Loop over all visibilities and pixels + VisBuffer vb(vi); + + // Initialize put (i.e. transform to Sky) for this model + vi.origin(); + + if(vb.polFrame()==MSIter::Linear) { + StokesImageUtil::changeCStokesRep(theImage, SkyModel::LINEAR); + } + else { + StokesImageUtil::changeCStokesRep(theImage, SkyModel::CIRCULAR); + } + + initializeToSky(theImage,weight,vb); + + // Loop over the visibilities, putting VisBuffers + for (vi.originChunks();vi.moreChunks();vi.nextChunk()) { + for (vi.origin(); vi.more(); vi++) { + + switch(type) { + case FTMachine::RESIDUAL: + if (itsVerbose > 0) cout<<"FTMachine::RESIDUAL"<<endl; + vb.visCube()=vb.correctedVisCube(); + vb.visCube()-=vb.modelVisCube(); + put(vb, -1, False); + break; + case FTMachine::MODEL: + if (itsVerbose > 0) cout<<"FTMachine::MODEL"<<endl; + vb.visCube()=vb.modelVisCube(); + put(vb, -1, False); + break; + case FTMachine::CORRECTED: + if (itsVerbose > 0) cout<<"FTMachine::CORRECTED"<<endl; + vb.visCube()=vb.correctedVisCube(); + put(vb, -1, False); + break; + case FTMachine::PSF: + if (itsVerbose > 0) cout<<"FTMachine::PSF"<<endl; + vb.visCube()=Complex(1.0,0.0); + put(vb, -1, True); + break; + case FTMachine::OBSERVED: + default: + if (itsVerbose > 0) cout<<"FTMachine::OBSERVED"<<endl; + put(vb, -1, False); + break; + } + } + } + finalizeToSky(); + // Normalize by dividing out weights, etc. + getImage(weight, True); +} + +String LofarFTMachineOld::name(){ + + return machineName_p; + + +} + +void LofarFTMachineOld::ComputeResiduals(VisBuffer&vb, Bool useCorrected) +{ + LofarVBStore vbs; + vbs.nRow_p = vb.nRow(); + vbs.beginRow_p = 0; + vbs.endRow_p = vbs.nRow_p; + vbs.modelCube_p.reference(vb.modelVisCube()); + if (useCorrected) vbs.correctedCube_p.reference(vb.correctedVisCube()); + else vbs.visCube_p.reference(vb.visCube()); + // cout<<"BLA===="<<vb.visCube()<<" "<<useCorrected<<endl; + + //for(uInt i=0;i<vbs.nRow_p;++i){cout<<"ROW "<<i<<" "<<vb.antenna1()(i)<<" "<<vb.antenna2()(i)<<endl;}; + + vbs.useCorrected_p = useCorrected; + visResamplers_p.lofarComputeResiduals(vbs); + + // vb.correctedVisCube()=0.;//vb.modelVisCube(); +} + + void LofarFTMachineOld::makeSensitivityImage(const VisBuffer& vb, + const ImageInterface<Complex>& imageTemplate, + ImageInterface<Float>& sensitivityImage) + { + if (convFuncCtor_p->makeAverageResponse(vb, imageTemplate, sensitivityImage)) + cfCache_p->flush(sensitivityImage,sensitivityPatternQualifierStr_p); + } + // + //--------------------------------------------------------------- + // + void LofarFTMachineOld::normalizeAvgPB(ImageInterface<Complex>& inImage, + ImageInterface<Float>& outImage) + { + LogIO log_l(LogOrigin("LofarFTMachineOld", "normalizeAvgPB")); + if (pbNormalized_p) return; + IPosition inShape(inImage.shape()),ndx(4,0,0,0,0); + Vector<Complex> peak(inShape(2)); + + outImage.resize(inShape); + outImage.setCoordinateInfo(inImage.coordinates()); + + Bool isRefIn, isRefOut; + Array<Complex> inBuf; + Array<Float> outBuf; + + isRefIn = inImage.get(inBuf); + isRefOut = outImage.get(outBuf); + log_l << "Normalizing the average PBs to unity" + << LogIO::NORMAL << LogIO::POST; + // + // Normalize each plane of the inImage separately to unity. + // + Complex inMax = max(inBuf); + if (abs(inMax)-1.0 > 1E-3) + { + for(ndx(3)=0;ndx(3)<inShape(3);ndx(3)++) + for(ndx(2)=0;ndx(2)<inShape(2);ndx(2)++) + { + peak(ndx(2)) = 0; + for(ndx(1)=0;ndx(1)<inShape(1);ndx(1)++) + for(ndx(0)=0;ndx(0)<inShape(0);ndx(0)++) + if (abs(inBuf(ndx)) > peak(ndx(2))) + peak(ndx(2)) = inBuf(ndx); + + for(ndx(1)=0;ndx(1)<inShape(1);ndx(1)++) + for(ndx(0)=0;ndx(0)<inShape(0);ndx(0)++) + // avgPBBuf(ndx) *= (pbPeaks(ndx(2))/peak(ndx(2))); + inBuf(ndx) /= peak(ndx(2)); + } + if (isRefIn) inImage.put(inBuf); + } + + ndx=0; + for(ndx(1)=0;ndx(1)<inShape(1);ndx(1)++) + for(ndx(0)=0;ndx(0)<inShape(0);ndx(0)++) + { + IPosition plane1(ndx); + plane1=ndx; + plane1(2)=1; // The other poln. plane + // avgPBBuf(ndx) = (avgPBBuf(ndx) + avgPBBuf(plane1))/2.0; + outBuf(ndx) = sqrt(real(inBuf(ndx) * inBuf(plane1))); + } + // + // Rather convoluted way of copying Pol. plane-0 to Pol. plane-1!!! + // + for(ndx(1)=0;ndx(1)<inShape(1);ndx(1)++) + for(ndx(0)=0;ndx(0)<inShape(0);ndx(0)++) + { + IPosition plane1(ndx); + plane1=ndx; + plane1(2)=1; // The other poln. plane + outBuf(plane1) = outBuf(ndx); + } + + pbNormalized_p = True; + } + // + //--------------------------------------------------------------- + // + void LofarFTMachineOld::normalizeAvgPB() + { + LogIO log_l(LogOrigin("LofarFTMachineOld", "normalizeAvgPB")); + if (pbNormalized_p) return; + Bool isRefF; + Array<Float> avgPBBuf; + isRefF=avgPB_p->get(avgPBBuf); + // Float pbMax = max(avgPBBuf); + { + pbPeaks.resize(avgPB_p->shape()(2),True); + // if (makingPSF) pbPeaks = 1.0; + // else pbPeaks /= (Float)noOfPASteps; + pbPeaks = 1.0; + log_l << "Normalizing the average PBs to " << 1.0 + << LogIO::NORMAL << LogIO::POST; + + IPosition avgPBShape(avgPB_p->shape()),ndx(4,0,0,0,0); + Vector<Float> peak(avgPBShape(2)); + + + Float pbMax = max(avgPBBuf); + if (fabs(pbMax-1.0) > 1E-3) + { + // avgPBBuf = avgPBBuf/noOfPASteps; + for(ndx(3)=0;ndx(3)<avgPBShape(3);ndx(3)++) + for(ndx(2)=0;ndx(2)<avgPBShape(2);ndx(2)++) + { + peak(ndx(2)) = 0; + for(ndx(1)=0;ndx(1)<avgPBShape(1);ndx(1)++) + for(ndx(0)=0;ndx(0)<avgPBShape(0);ndx(0)++) + if (abs(avgPBBuf(ndx)) > peak(ndx(2))) + peak(ndx(2)) = avgPBBuf(ndx); + + for(ndx(1)=0;ndx(1)<avgPBShape(1);ndx(1)++) + for(ndx(0)=0;ndx(0)<avgPBShape(0);ndx(0)++) + // avgPBBuf(ndx) *= (pbPeaks(ndx(2))/peak(ndx(2))); + avgPBBuf(ndx) /= peak(ndx(2)); + } + if (isRefF) avgPB_p->put(avgPBBuf); + } + + ndx=0; + for(ndx(1)=0;ndx(1)<avgPBShape(1);ndx(1)++) + for(ndx(0)=0;ndx(0)<avgPBShape(0);ndx(0)++) + { + IPosition plane1(ndx); + plane1=ndx; + plane1(2)=1; // The other poln. plane + avgPBBuf(ndx) = (avgPBBuf(ndx) + avgPBBuf(plane1))/2.0; + // avgPBBuf(ndx) = (avgPBBuf(ndx) * avgPBBuf(plane1)); + } + for(ndx(1)=0;ndx(1)<avgPBShape(1);ndx(1)++) + for(ndx(0)=0;ndx(0)<avgPBShape(0);ndx(0)++) + { + IPosition plane1(ndx); + plane1=ndx; + plane1(2)=1; // The other poln. plane + avgPBBuf(plane1) = avgPBBuf(ndx); + } + } + pbNormalized_p = True; + } + + void LofarFTMachineOld::normalizeImage(Lattice<Complex>& skyImage, + const Matrix<Double>& sumOfWts, + Lattice<Float>& sensitivityImage, + Lattice<Complex>& sensitivitySqImage, + Bool fftNorm) + { + // + // Apply the gridding correction + // + if (itsVerbose > 0) { + cout<<"LofarFTMachineOld::normalizeImage"<<endl; + } + Int inx = skyImage.shape()(0); + Int iny = skyImage.shape()(1); + Vector<Complex> correction(inx); + + Vector<Float> sincConv(nx); + Float centerX=nx/2; + for (Int ix=0;ix<nx;ix++) + { + Float x=C::pi*Float(ix-centerX)/(Float(nx)*Float(convSampling)); + if(ix==centerX) sincConv(ix)=1.0; + else sincConv(ix)=sin(x)/x; + } + + IPosition cursorShape(4, inx, 1, 1, 1); + IPosition axisPath(4, 0, 1, 2, 3); + LatticeStepper lsx(skyImage.shape(), cursorShape, axisPath); + LatticeIterator<Complex> lix(skyImage, lsx); + + LatticeStepper lavgpb(sensitivityImage.shape(),cursorShape,axisPath); + LatticeIterator<Float> liavgpb(sensitivityImage, lavgpb); + LatticeStepper lavgpbSq(sensitivitySqImage.shape(),cursorShape,axisPath); + LatticeIterator<Complex> liavgpbSq(sensitivitySqImage, lavgpbSq); + + for(lix.reset(),liavgpb.reset(),liavgpbSq.reset(); + !lix.atEnd(); + lix++,liavgpb++,liavgpbSq++) + { + Int pol=lix.position()(2); + Int chan=lix.position()(3); + + if(sumOfWts(pol, chan)>0.0) + { + Int iy=lix.position()(1); + gridder->correctX1D(correction,iy); + + Vector<Complex> PBCorrection(liavgpb.rwVectorCursor().shape()); + Vector<Float> avgPBVec(liavgpb.rwVectorCursor().shape()); + Vector<Complex> avgPBSqVec(liavgpbSq.rwVectorCursor().shape()); + + avgPBSqVec= liavgpbSq.rwVectorCursor(); + avgPBVec = liavgpb.rwVectorCursor(); + + for(int i=0;i<PBCorrection.shape();i++) + { + // + // This with the PS functions + // + // PBCorrection(i)=FUNC(avgPBVec(i))*sincConv(i)*sincConv(iy); + // if ((abs(PBCorrection(i)*correction(i))) >= pbLimit_p) + // lix.rwVectorCursor()(i) /= PBCorrection(i)*correction(i); + // else if (!makingPSF) + // lix.rwVectorCursor()(i) /= correction(i)*sincConv(i)*sincConv(iy); + // + // This without the PS functions + // + + + + // if (makingPSF) + PBCorrection(i)=(avgPBSqVec(i)/avgPBVec(i));///(sincConv(i)*sincConv(iy)); + // PBCorrection(i)=(avgPBSqVec(i));///(sincConv(i)*sincConv(iy)); + // PBCorrection(i)=avgPBVec(i);///(sincConv(i)*sincConv(iy)); + + // else + // PBCorrection(i)=(avgPBVec(i));//*sincConv(i)*sincConv(iy); + // if ((abs(avgPBSqVec(i))) >= pbLimit_p) + if ((abs(avgPBVec(i))) >= pbLimit_p) + lix.rwVectorCursor()(i) /= PBCorrection(i); + + // if ((abs(PBCorrection(i))) >= pbLimit_p) + // lix.rwVectorCursor()(i) /= PBCorrection(i); + // else if (!makingPSF) + // lix.rwVectorCursor()(i) /= sincConv(i)*sincConv(iy); + + + // PBCorrection(i)=FUNC(avgPBVec(i)/avgPBSqVec(i))/(sincConv(i)*sincConv(iy)); + // lix.rwVectorCursor()(i) *= PBCorrection(i); + + // if ((abs(avgPBSqVec(i))) >= pbLimit_p) + // lix.rwVectorCursor()(i) *= PBCorrection(i); + // else if (!makingPSF) + // lix.rwVectorCursor()(i) /= sincConv(i)*sincConv(iy); + } + + if(fftNorm) + { + Complex rnorm(Float(inx)*Float(iny)/sumOfWts(pol,chan)); + lix.rwCursor()*=rnorm; + } + else + { + Complex rnorm(Float(inx)*Float(iny)); + lix.rwCursor()*=rnorm; + } + } + else + lix.woCursor()=0.0; + } + } + // + //--------------------------------------------------------------- + // + void LofarFTMachineOld::normalizeImage(Lattice<Complex>& skyImage, + const Matrix<Double>& sumOfWts, + Lattice<Float>& sensitivityImage, + Bool fftNorm) + { + // + // Apply the gridding correction + // + if (itsVerbose > 0) { + cout<<"LofarFTMachineOld::normalizeImage<"<<endl; + } + Int inx = skyImage.shape()(0); + Int iny = skyImage.shape()(1); + Vector<Complex> correction(inx); + + Vector<Float> sincConv(nx); + Float centerX=nx/2; + for (Int ix=0;ix<nx;ix++) + { + Float x=C::pi*Float(ix-centerX)/(Float(nx)*Float(convSampling)); + if(ix==centerX) sincConv(ix)=1.0; + else sincConv(ix)=sin(x)/x; + } + + IPosition cursorShape(4, inx, 1, 1, 1); + IPosition axisPath(4, 0, 1, 2, 3); + LatticeStepper lsx(skyImage.shape(), cursorShape, axisPath); + // LatticeIterator<Complex> lix(skyImage, lsx); + LatticeIterator<Complex> lix(skyImage, lsx); + + LatticeStepper lavgpb(sensitivityImage.shape(),cursorShape,axisPath); + // Array<Float> senArray;sensitivityImage.get(senArray,True); + // ArrayLattice<Float> senLat(senArray,True); + // LatticeIterator<Float> liavgpb(senLat, lavgpb); + LatticeIterator<Float> liavgpb(sensitivityImage, lavgpb); + + for(lix.reset(),liavgpb.reset(); + !lix.atEnd(); + lix++,liavgpb++) + { + Int pol=lix.position()(2); + Int chan=lix.position()(3); + + if(sumOfWts(pol, chan)>0.0) + { + Int iy=lix.position()(1); + gridder->correctX1D(correction,iy); + + Vector<Float> avgPBVec(liavgpb.rwVectorCursor().shape()); + + avgPBVec = liavgpb.rwVectorCursor(); + + for(int i=0;i<avgPBVec.shape();i++) + { + // + // This with the PS functions + // + // PBCorrection(i)=FUNC(avgPBVec(i))*sincConv(i)*sincConv(iy); + // if ((abs(PBCorrection(i)*correction(i))) >= pbLimit_p) + // lix.rwVectorCursor()(i) /= PBCorrection(i)*correction(i); + // else if (!makingPSF) + // lix.rwVectorCursor()(i) /= correction(i)*sincConv(i)*sincConv(iy); + // + // This without the PS functions + // + // Float tt=sqrt(avgPBVec(i))/avgPBVec(i); + Float tt = pbFunc(avgPBVec(i),pbLimit_p); + // PBCorrection(i)=pbFunc(avgPBVec(i),pbLimit_p)*sincConv(i)*sincConv(iy); + // lix.rwVectorCursor()(i) /= PBCorrection(i); + // lix.rwVectorCursor()(i) *= tt; + + lix.rwVectorCursor()(i) /= tt; + // if ((abs(tt) >= pbLimit_p)) + // lix.rwVectorCursor()(i) /= tt; + // else if (!makingPSF) + // lix.rwVectorCursor()(i) /= sincConv(i)*sincConv(iy); + } + + if(fftNorm) + { + Complex rnorm(Float(inx)*Float(iny)/sumOfWts(pol,chan)); + lix.rwCursor()*=rnorm; + } + else + { + Complex rnorm(Float(inx)*Float(iny)); + lix.rwCursor()*=rnorm; + } + } + else + lix.woCursor()=0.0; + } + } + + + void LofarFTMachineOld::makeCFPolMap(const VisBuffer& vb, const Vector<Int>& locCfStokes, + Vector<Int>& polM) + { + LogIO log_l(LogOrigin("LofarFTMachineOld", "findPointingOffsets")); + Vector<Int> msStokes = vb.corrType(); + Int nPol = msStokes.nelements(); + polM.resize(polMap.shape()); + polM = -1; + + for(Int i=0;i<nPol;i++) + for(uInt j=0;j<locCfStokes.nelements();j++) + if (locCfStokes(j) == msStokes(i)) + {polM(i) = j;break;} + } + // + //--------------------------------------------------------------- + // + // Given a polMap (mapping of which Visibility polarization is + // gridded onto which grid plane), make a map of the conjugate + // planes of the grid E.g, for Stokes-I and -V imaging, the two + // planes of the uv-grid are [LL,RR]. For input VisBuffer + // visibilites in order [RR,RL,LR,LL], polMap = [1,-1,-1,0]. The + // conjugate map will be [0,-1,-1,1]. + // + void LofarFTMachineOld::makeConjPolMap(const VisBuffer& vb, + const Vector<Int> cfPolMap, + Vector<Int>& conjPolMap) + { + LogIO log_l(LogOrigin("LofarFTMachineOld", "makConjPolMap")); + // + // All the Natak (Drama) below with slicers etc. is to extract the + // Poln. info. for the first IF only (not much "information + // hiding" for the code to slice arrays in a general fashion). + // + // Extract the shape of the array to be sliced. + // + Array<Int> stokesForAllIFs = vb.msColumns().polarization().corrType().getColumn(); + IPosition stokesShape(stokesForAllIFs.shape()); + IPosition firstIFStart(stokesShape),firstIFLength(stokesShape); + // + // Set up the start and length IPositions to extract only the + // first column of the array. The following is required since the + // array could have only one column as well. + // + firstIFStart(0)=0;firstIFLength(0)=stokesShape(0); + for(uInt i=1;i<stokesShape.nelements();i++) {firstIFStart(i)=0;firstIFLength(i)=1;} + // + // Construct the slicer and produce the slice. .nonDegenerate + // required to ensure the result of slice is a pure vector. + // + Vector<Int> visStokes = stokesForAllIFs(Slicer(firstIFStart,firstIFLength)).nonDegenerate(); + + conjPolMap = cfPolMap; + + Int i,j,N = cfPolMap.nelements(); + + for(i=0;i<N;i++) + if (cfPolMap[i] > -1) + { + if (visStokes[i] == Stokes::XX) + { + conjPolMap[i]=-1; + for(j=0;j<N;j++) if (visStokes[j] == Stokes::YY) break; + conjPolMap[i]=cfPolMap[j]; + } + else if (visStokes[i] == Stokes::YY) + { + conjPolMap[i]=-1; + for(j=0;j<N;j++) if (visStokes[j] == Stokes::XX) break; + conjPolMap[i]=cfPolMap[j]; + } + else if (visStokes[i] == Stokes::YX) + { + conjPolMap[i]=-1; + for(j=0;j<N;j++) if (visStokes[j] == Stokes::XY) break; + conjPolMap[i]=cfPolMap[j]; + } + else if (visStokes[i] == Stokes::XY) + { + conjPolMap[i]=-1; + for(j=0;j<N;j++) if (visStokes[j] == Stokes::YX) break; + conjPolMap[i]=cfPolMap[j]; + } + } + } + + void LofarFTMachineOld::showTimings (ostream& os, double duration) const + { + // The total time is the real elapsed time. + // The cf and (de)gridding time is the sum of all threads, so scale + // them back to real time. + double total = itsCFTime + itsGriddingTime + itsDegriddingTime; + double scale = 1; + if (total > 0) { + scale = itsTotalTimer.getReal() / total; + } + itsConvFunc->showTimings (os, duration, itsCFTime*scale); + if (itsGriddingTime > 0) { + os << " gridding "; + LofarConvolutionFunctionOld::showPerc1 (os, itsGriddingTime*scale, + duration); + os << endl; + } + if (itsDegriddingTime > 0) { + os << " degridding "; + LofarConvolutionFunctionOld::showPerc1 (os, itsDegriddingTime*scale, + duration); + os << endl; + } + } + +} //# end namespace diff --git a/CEP/Imager/LofarFT/src/LofarImager.cc b/CEP/Imager/LofarFT/src/LofarImager.cc index 08068444b85b24d8fe605f6394c7a7ab61b38146..34fa5eb10411462a0e0c5f728a840f1d1f341624 100644 --- a/CEP/Imager/LofarFT/src/LofarImager.cc +++ b/CEP/Imager/LofarFT/src/LofarImager.cc @@ -40,10 +40,11 @@ namespace LOFAR // @brief Imager for LOFAR data correcting for DD effects LofarImager::LofarImager (MeasurementSet& ms, const Record& parameters) - : Imager(ms), - itsParameters (parameters) + : Imager(ms,false, true), + itsParameters (parameters), + itsMachine (0), + itsMachineOld (0) { - cout << itsParameters<<endl; } LofarImager::~LofarImager() @@ -53,7 +54,36 @@ namespace LOFAR { CountedPtr<VisibilityResamplerBase> visResampler; Bool useDoublePrecGrid = False; - itsMachine = new LofarFTMachine(cache_p/2, tile_p, + Double RefFreq((*sm_p).getReferenceFrequency()); + + if (itsParameters.asBool("splitbeam")) { + cout << itsParameters<<endl; + itsMachine = new LofarFTMachine(cache_p/2, tile_p, + visResampler, gridfunction_p, + *ms_p, wprojPlanes_p, mLocation_p, + padding_p, false, useDoublePrecGrid, + itsParameters.asDouble("wmax"), + itsParameters.asInt("verbose"), + itsParameters.asInt("maxsupport"), + itsParameters.asInt("oversample"), + itsParameters.asString("imagename"), + itsParameters.asArrayBool("mueller.grid"), + itsParameters.asArrayBool("mueller.degrid"), + RefFreq, + itsParameters.asBool("UseLIG"), + itsParameters.asBool("UseEJones"), + itsParameters.asInt("StepApplyElement"), + itsParameters.asDouble("PBCut"), + itsParameters.asBool("PredictFT"), + itsParameters.asString("PsfImage"), + itsParameters.asBool("UseMasksDegrid"), + itsParameters.asBool("doPSF"), + itsParameters);//, + //itsParameters.asDouble("FillFactor")); + + ft_p = itsMachine; + } else { + itsMachineOld = new LofarFTMachineOld(cache_p/2, tile_p, visResampler, gridfunction_p, *ms_p, wprojPlanes_p, mLocation_p, padding_p, false, useDoublePrecGrid, @@ -65,7 +95,9 @@ namespace LOFAR itsParameters.asString("imagename"), itsParameters.asArrayBool("mueller.grid"), itsParameters.asArrayBool("mueller.degrid")); - ft_p = itsMachine; + ft_p = itsMachineOld; + } + cft_p = new SimpleComponentFTMachine(); //setClarkCleanImageSkyModel(); @@ -79,9 +111,13 @@ namespace LOFAR Int nrowBlock = nrowPerTime * max(1,ntime); // Set row blocking in VisIter. rvi_p->setRowBlocking (nrowBlock); + if(itsParameters.asInt("RowBlock")>0){ + rvi_p->setRowBlocking (itsParameters.asInt("RowBlock")); + }; /* os << LogIO::NORMAL << "vi.setRowBlocking(" << nrowBlock << ")" << LogIO::POST;*/ + return True; } @@ -89,6 +125,7 @@ namespace LOFAR { se_p = new LofarCubeSkyEquation(*sm_p, *rvi_p, *ft_p, *cft_p, !useModelCol_p); + return; } @@ -102,9 +139,12 @@ namespace LOFAR // Show the relative timings of the various steps. void LofarImager::showTimings (std::ostream&, double duration) const { - itsMachine->showTimings (cout, duration); + if (itsMachine) { + itsMachine->showTimings (cout, duration); + } else if (itsMachineOld) { + itsMachineOld->showTimings (cout, duration); + } } } //# end namespace - diff --git a/CEP/Imager/LofarFT/src/LofarVisResampler.cc b/CEP/Imager/LofarFT/src/LofarVisResampler.cc index 5533e971bd620abf3fcca4e9e7e88ea5ffff31c7..a9249dd8ab1bbd2e7054eb2b1bd83b948bef0c41 100644 --- a/CEP/Imager/LofarFT/src/LofarVisResampler.cc +++ b/CEP/Imager/LofarFT/src/LofarVisResampler.cc @@ -20,15 +20,224 @@ //# //# $Id$ +#include <lofar_config.h> #include <LofarFT/LofarVisResampler.h> #include <synthesis/MeasurementComponents/Utils.h> #include <coordinates/Coordinates/SpectralCoordinate.h> #include <coordinates/Coordinates/CoordinateSystem.h> -#include<cassert> +#include <cassert> +#include <Common/OpenMP.h> namespace LOFAR { // Instantiate both templates. + + + template + void LofarVisResampler::DataToGridImpl_linear_p(Array<DComplex>& grid, LofarVBStore& vbs, + const Vector<uInt>& rows, + Int rbeg, Int rend, + Matrix<Double>& sumwt,const Bool& dopsf, + LofarCFStore& cfs) __restrict__; + template + void LofarVisResampler::DataToGridImpl_linear_p(Array<Complex>& grid, LofarVBStore& vbs, + const Vector<uInt>& rows, + Int rbeg, Int rend, + Matrix<Double>& sumwt,const Bool& dopsf, + LofarCFStore& cfs) __restrict__; + + + template <class T> + void LofarVisResampler::DataToGridImpl_linear_p(Array<T>& grid, LofarVBStore& vbs, + const Vector<uInt>& rows, + Int rbeg, Int rend, + Matrix<Double>& sumwt, + const Bool& dopsf, + LofarCFStore& cfs) __restrict__ + { + // grid[nx,ny,np,nf] + // vbs.data[np,nf,nrow] + // cfs[nmx,nmy,nf,ncx,ncy] (mueller,freq,convsize) + + // Get size of convolution functions. + Int nConvX = (*(cfs.vdata))[0][0][0].shape()[0]; + Int nConvY = (*(cfs.vdata))[0][0][0].shape()[1]; + // Get size of grid. + Int nGridX = grid.shape()[0]; + Int nGridY = grid.shape()[1]; + Int nGridPol = grid.shape()[2]; + Int nGridChan = grid.shape()[3]; + //cout<<"nGridPol<<nGridChan "<<nGridPol<<" "<<nGridChan<<endl; + + // Get visibility data size. + Int nVisPol = vbs.flagCube_p.shape()[0]; + Int nVisChan = vbs.flagCube_p.shape()[1]; + //cout<<"nVisPol<<nVisChan "<<nVisPol<<" "<<nVisChan<<endl; + // Get oversampling and support size. + Int sampx = SynthesisUtils::nint (cfs.sampling[0]); + Int sampy = SynthesisUtils::nint (cfs.sampling[1]); + Int supx = cfs.xSupport[0]; + Int supy = cfs.ySupport[0]; + ///AlwaysAssert ((2*supx+1)*sampx == nConvX, AipsError); + ///AlwaysAssert ((2*supy+1)*sampy == nConvY, AipsError); + + Double* __restrict__ sumWtPtr = sumwt.data(); + Complex psfValues[4]; + psfValues[0] = psfValues[1] = psfValues[2] = psfValues[3] = Complex(1,0); + + vector< Float > Weights_Lin_Interp; + Weights_Lin_Interp.resize(4); + vector< Int > deltax_pix_interp; + deltax_pix_interp.resize(4); + vector< Int > deltay_pix_interp; + deltay_pix_interp.resize(4); + for(uInt i=0;i<4;i++){ + deltax_pix_interp[i]=0; + deltay_pix_interp[i]=0; + } + + // Loop over all visibility rows to process. + for (Int inx=rbeg; inx<=rend; ++inx) { + Int irow = rows[inx]; + const Double* __restrict__ uvwPtr = vbs.uvw_p.data() + irow*3; + const Float* __restrict__ imgWtPtr = vbs.imagingWeight_p.data() + + irow * nVisChan; + // Loop over all channels in the visibility data. + // Map the visibility channel to the grid channel. + // Skip channel if data are not needed. + for (Int visChan=0; visChan<nVisChan; ++visChan) { + Int gridChan = chanMap_p[visChan]; + + //cout<<"visChan "<<visChan<<endl; + if (gridChan >= 0 && gridChan < nGridChan) { + // Determine the grid position from the UV coordinates in wavelengths. + Double recipWvl = vbs.freq_p[visChan] / C::c; + Double posx = uvwScale_p[0] * uvwPtr[0] * recipWvl + offset_p[0]; + Double posy = uvwScale_p[1] * uvwPtr[1] * recipWvl + offset_p[1]; + Int locx = floor(posx);//SynthesisUtils::nint (posx); // location in grid + Int locy = floor(posy);//SynthesisUtils::nint (posy); + Double diffx = locx - posx; + //if (diffx < 0) diffx += 1; + Double diffy = locy - posy; + + if(diffx>0){ + deltax_pix_interp[0]=-1; + deltax_pix_interp[1]=0; + deltax_pix_interp[2]=-1; + deltax_pix_interp[3]=0; + } else { + deltax_pix_interp[0]=0; + deltax_pix_interp[1]=1; + deltax_pix_interp[2]=0; + deltax_pix_interp[3]=1; + } + if(diffy>0){ + deltay_pix_interp[0]=-1; + deltay_pix_interp[1]=-1; + deltay_pix_interp[2]=0; + deltay_pix_interp[3]=0; + } else { + deltay_pix_interp[0]=0; + deltay_pix_interp[1]=0; + deltay_pix_interp[2]=1; + deltay_pix_interp[3]=1; + } + + Double diff_floor_x(abs(posx-floor(posx))); + Double diff_floor_y(abs(posy-floor(posy))); + + + Weights_Lin_Interp[0]=(1.-diff_floor_x)*(1.-diff_floor_y); + Weights_Lin_Interp[1]= diff_floor_x *(1.-diff_floor_y); + Weights_Lin_Interp[2]=(1.-diff_floor_x)* diff_floor_y ; + Weights_Lin_Interp[3]= diff_floor_x * diff_floor_y ; + + //cout<<"diff_floor_x<<diff_floor_y "<<diff_floor_x<<" "<<diff_floor_y<<" "<<Weights_Lin_Interp[0]<<" "<<Weights_Lin_Interp[1]<<" "<<Weights_Lin_Interp[2]<<" "<<Weights_Lin_Interp[3]<<" "<<endl; + + ///if (diffy < 0) diffy += 1; + Int offx = 0;//SynthesisUtils::nint (diffx * sampx); // location in + Int offy = 0;//SynthesisUtils::nint (diffy * sampy); // oversampling + /// cout<<" pos= ["<<posx<<", "<<posy<<"]" + /// <<", loc= ["<<locx<<", "<<locy<<"]" + /// <<", off= ["<<offx<<", "<<offy<<"]" << endl; + offx += (nConvX-1)/2; + offy += (nConvY-1)/2; + + // Scaling with frequency is not necessary (according to Cyril). + Double freqFact = 1; // = cfFreq / vbs.freq_p[visChan]; + Int fsampx = SynthesisUtils::nint (sampx * freqFact); + Int fsampy = SynthesisUtils::nint (sampy * freqFact); + Int fsupx = SynthesisUtils::nint (supx / freqFact); + Int fsupy = SynthesisUtils::nint (supy / freqFact); + + // Only use visibility point if the full support is within grid. + if (locx-supx >= 0 && locx+supx < nGridX && + locy-supy >= 0 && locy+supy < nGridY) { + /// cout << "in grid"<<endl; + // Get pointer to data and flags for this channel. + Int doff = (irow * nVisChan + visChan) * nVisPol; + const Complex* __restrict__ visPtr = vbs.visCube_p.data() + doff; + const Bool* __restrict__ flagPtr = vbs.flagCube_p.data() + doff; + if (dopsf) { + visPtr = psfValues; + } + + // Handle a visibility if not flagged. + for (Int w=0; w<4; w++) { + Double weight_interp(Weights_Lin_Interp[w]); + for (Int ipol=0; ipol<nVisPol; ++ipol) { + if (! flagPtr[ipol]) { + // Map to grid polarization. Only use pol if needed. + Int gridPol = polMap_p(ipol); + if (gridPol >= 0 && gridPol < nGridPol) { + //cout<<"ipol: "<<ipol<<endl; + // Get the offset in the grid data array. + Int goff = (gridChan*nGridPol + gridPol) * nGridX * nGridY; + // Loop over the scaled support. + for (Int sy=-fsupy; sy<=fsupy; ++sy) { + // Get the pointer in the grid for the first x in this y. + T* __restrict__ gridPtr = grid.data() + goff + + (locy+sy+deltay_pix_interp[w])*nGridX + locx-supx+deltax_pix_interp[w]; + //cout<<"goff<<locy<<sy<<nGridX<<locx<<supx "<<goff<<" "<<locy<<" "<<sy<<" "<<nGridX<<" "<<locx<<" "<<supx<<endl; + // Get pointers to the first element to use in the 4 + // convolution functions for this channel,pol. + const Complex* __restrict__ cf[4]; + + Int cfoff = (offy + sy*fsampy)*nConvX + offx - fsupx*fsampx; + //cout<<"cfoff<<offy<<fsampy<<nConvX<<offx<<fsupx<<fsampx "<<cfoff<<" "<<offy<<" "<<fsampy<<" "<<nConvX<<" "<<offx<<" "<<fsupx<<" "<<fsampx<<endl; + for (int i=0; i<4; ++i) { + cf[i] = (*cfs.vdata)[gridChan][i][ipol].data() + cfoff; + } + for (Int sx=-fsupx; sx<=fsupx; ++sx) { + // Loop over polarizations to correct for leakage. + Complex polSum(0,0); + for (Int i=0; i<4; ++i) { + /// cout<<"cf="<< cf[i]-(*cfs.vdata)[gridChan][ipol][i].data()<<','; + //cout<<"visPtr[i] <<" "<< *cf[i] == "<<visPtr[i] <<" "<< *cf[i]<<endl; + polSum += (visPtr[i] * *cf[i])* weight_interp ; + cf[i] += fsampx; + } + /// cout<<" g="<<gridPtr-grid.data()<<' '<<visPtr[i]<<endl; + polSum *= (*imgWtPtr); + *gridPtr++ += polSum ; + } + } + sumWtPtr[gridPol+gridChan*nGridPol] += (*imgWtPtr) * weight_interp; + } // end if gridPol + } // end if !flagPtr + } // end for ipol + } + } // end if ongrid + } // end if gridChan + imgWtPtr++; + } // end for visChan + } // end for inx + } + + + // ================================ + // "Traditional" gridder + template void LofarVisResampler::DataToGridImpl_p(Array<DComplex>& grid, LofarVBStore& vbs, const Vector<uInt>& rows, @@ -42,7 +251,6 @@ namespace LOFAR { Matrix<Double>& sumwt,const Bool& dopsf, LofarCFStore& cfs) __restrict__; - template <class T> void LofarVisResampler::DataToGridImpl_p(Array<T>& grid, LofarVBStore& vbs, const Vector<uInt>& rows, @@ -63,20 +271,29 @@ namespace LOFAR { Int nGridY = grid.shape()[1]; Int nGridPol = grid.shape()[2]; Int nGridChan = grid.shape()[3]; + //cout<<"nGridPol<<nGridChan "<<nGridPol<<" "<<nGridChan<<endl; + // Get visibility data size. Int nVisPol = vbs.flagCube_p.shape()[0]; Int nVisChan = vbs.flagCube_p.shape()[1]; + //cout<<"nVisPol<<nVisChan "<<nVisPol<<" "<<nVisChan<<endl; // Get oversampling and support size. Int sampx = SynthesisUtils::nint (cfs.sampling[0]); Int sampy = SynthesisUtils::nint (cfs.sampling[1]); Int supx = cfs.xSupport[0]; Int supy = cfs.ySupport[0]; + ///AlwaysAssert ((2*supx+1)*sampx == nConvX, AipsError); ///AlwaysAssert ((2*supy+1)*sampy == nConvY, AipsError); Double* __restrict__ sumWtPtr = sumwt.data(); Complex psfValues[4]; psfValues[0] = psfValues[1] = psfValues[2] = psfValues[3] = Complex(1,0); + // psfValues[0] = -Complex(2,0); + // psfValues[1] = -Complex(1,1); + // psfValues[2] = -Complex(1,-1); + // psfValues[3] = -Complex(0,0); + // Loop over all visibility rows to process. for (Int inx=rbeg; inx<=rend; ++inx) { @@ -89,7 +306,14 @@ namespace LOFAR { // Skip channel if data are not needed. for (Int visChan=0; visChan<nVisChan; ++visChan) { Int gridChan = chanMap_p[visChan]; + + + // !! dirty trick to select all channels + chanMap_p[visChan]=0; + + if (gridChan >= 0 && gridChan < nGridChan) { + // Determine the grid position from the UV coordinates in wavelengths. Double recipWvl = vbs.freq_p[visChan] / C::c; Double posx = uvwScale_p[0] * uvwPtr[0] * recipWvl + offset_p[0]; @@ -115,8 +339,11 @@ namespace LOFAR { Int fsupy = SynthesisUtils::nint (supy / freqFact); // Only use visibility point if the full support is within grid. + if (locx-supx >= 0 && locx+supx < nGridX && locy-supy >= 0 && locy+supy < nGridY) { + + /// cout << "in grid"<<endl; // Get pointer to data and flags for this channel. Int doff = (irow * nVisChan + visChan) * nVisPol; @@ -128,9 +355,12 @@ namespace LOFAR { // Handle a visibility if not flagged. for (Int ipol=0; ipol<nVisPol; ++ipol) { if (! flagPtr[ipol]) { + // Map to grid polarization. Only use pol if needed. Int gridPol = polMap_p(ipol); if (gridPol >= 0 && gridPol < nGridPol) { + + //cout<<"ipol: "<<ipol<<endl; // Get the offset in the grid data array. Int goff = (gridChan*nGridPol + gridPol) * nGridX * nGridY; // Loop over the scaled support. @@ -138,25 +368,41 @@ namespace LOFAR { // Get the pointer in the grid for the first x in this y. T* __restrict__ gridPtr = grid.data() + goff + (locy+sy)*nGridX + locx-supx; + //cout<<"goff<<locy<<sy<<nGridX<<locx<<supx "<<goff<<" "<<locy<<" "<<sy<<" "<<nGridX<<" "<<locx<<" "<<supx<<endl; // Get pointers to the first element to use in the 4 // convolution functions for this channel,pol. - const Complex* __restrict__ cf[4]; + + // Fast version + + const Complex* __restrict__ cf[1]; Int cfoff = (offy + sy*fsampy)*nConvX + offx - fsupx*fsampx; - for (int i=0; i<4; ++i) { - cf[i] = (*cfs.vdata)[gridChan][ipol][i].data() + cfoff; - } + cf[0] = (*cfs.vdata)[gridChan][0][0].data() + cfoff; for (Int sx=-fsupx; sx<=fsupx; ++sx) { // Loop over polarizations to correct for leakage. Complex polSum(0,0); - for (Int i=0; i<nVisPol; ++i) { - /// cout<<"cf="<< cf[i]-(*cfs.vdata)[gridChan][ipol][i].data()<<','; - polSum += visPtr[i] * *cf[i]; - cf[i] += fsampx; - } - /// cout<<" g="<<gridPtr-grid.data()<<' '<<visPtr[i]<<endl; - polSum *= *imgWtPtr; + polSum += visPtr[ipol] * *cf[0]; + cf[0] += fsampx; + polSum *= *imgWtPtr; *gridPtr++ += polSum; } + + // // Full version + // const Complex* __restrict__ cf[4]; + // Int cfoff = (offy + sy*fsampy)*nConvX + offx - fsupx*fsampx; + // for (int i=0; i<4; ++i) { + // cf[i] = (*cfs.vdata)[gridChan][i][ipol].data() + cfoff; + // } + // for (Int sx=-fsupx; sx<=fsupx; ++sx) { + // // Loop over polarizations to correct for leakage. + // Complex polSum(0,0); + // for (Int i=0; i<4; ++i) { + // polSum += visPtr[i] * *cf[i]; + // cf[i] += fsampx; + // } + // polSum *= *imgWtPtr; + // *gridPtr++ += polSum; + // } + } sumWtPtr[gridPol+gridChan*nGridPol] += *imgWtPtr; } // end if gridPol @@ -169,6 +415,9 @@ namespace LOFAR { } // end for inx } + + + /* template <class T> void LofarVisResampler::DataToGridImpl_p(Array<T>& grid, LofarVBStore& vbs, @@ -232,7 +481,7 @@ namespace LOFAR { } } //cout<<"cfs.vdata= "<<&cfs<<endl; - + const Double *freq = vbs.freq_p.data(); // Cache increment values for adding to grid in gridInc. This is @@ -256,7 +505,7 @@ namespace LOFAR { // grid(tt)*=1.0; // } - for(Int inx=rbeg; inx< rend; inx++){ + for(Int inx=rbeg; inx<=rend; inx++){ Int irow = rows[inx]; for(Int ichan=0; ichan< nDataChan; ichan++){ Int achan=chanMap_p[ichan]; @@ -357,6 +606,17 @@ namespace LOFAR { */ + //===================================================================================================================================== + //===================================================================================================================================== + //===================================================================================================================================== + //===================================================================================================================================== + //===================================================================================================================================== + //===================================================================================================================================== + //===================================================================================================================================== + + + + // //----------------------------------------------------------------------------------- // Re-sample VisBuffer from a regular grid (griddedData) (a.k.a. de-gridding) @@ -390,6 +650,13 @@ namespace LOFAR { ///AlwaysAssert ((2*supx+1)*sampx == nConvX, AipsError); ///AlwaysAssert ((2*supy+1)*sampy == nConvY, AipsError); + vector< Float > Weights_Lin_Interp; + Weights_Lin_Interp.resize(4); + vector< Int > deltax_pix_interp; + deltax_pix_interp.resize(4); + vector< Int > deltay_pix_interp; + deltay_pix_interp.resize(4); + // Loop over all visibility rows to process. for (Int inx=rbeg; inx<=rend; ++inx) { Int irow = rows[inx]; @@ -399,6 +666,11 @@ namespace LOFAR { // Skip channel if data are not needed. for (Int visChan=0; visChan<nVisChan; ++visChan) { Int gridChan = chanMap_p[visChan]; + + + // !! dirty trick to select all channels + chanMap_p[visChan]=0; + if (gridChan >= 0 && gridChan < nGridChan) { // Determine the grid position from the UV coordinates in wavelengths. Double recipWvl = vbs.freq_p[visChan] / C::c; @@ -410,6 +682,12 @@ namespace LOFAR { ///if (diffx < 0) diffx += 1; Double diffy = locy - posy; ///if (diffy < 0) diffy += 1; + + Weights_Lin_Interp[0]=(1.-diffx)*(1.-diffy); + Weights_Lin_Interp[1]=(1.-diffx)*diffy; + Weights_Lin_Interp[2]=diffx*(1.-diffy); + Weights_Lin_Interp[3]=diffx*diffy; + Int offx = SynthesisUtils::nint (diffx * sampx); // location in Int offy = SynthesisUtils::nint (diffy * sampy); // oversampling /// cout<<" pos= ["<<posx<<", "<<posy<<"]" @@ -435,9 +713,11 @@ namespace LOFAR { // Handle a visibility if not flagged. for (Int ipol=0; ipol<nVisPol; ++ipol) { if (! flagPtr[ipol]) { - visPtr[ipol] = Complex(0,0); + visPtr[ipol] = Complex(0,0); } } + //for (Int w=0; w<4; ++w) { + // Double weight_interp(Weights_Lin_Interp[w]); for (Int ipol=0; ipol<nVisPol; ++ipol) { if (! flagPtr[ipol]) { // Map to grid polarization. Only use pol if needed. @@ -453,31 +733,160 @@ namespace LOFAR { (locy+sy)*nGridX + locx-supx; // Get pointers to the first element to use in the 4 // convolution functions for this channel,pol. - const Complex* __restrict__ cf[4]; + + // fast version + const Complex* __restrict__ cf[1]; Int cfoff = (offy + sy*fsampy)*nConvX + offx - fsupx*fsampx; - for (int i=0; i<4; ++i) { - cf[i] = (*cfs.vdata)[gridChan][i][ipol].data() + cfoff; - } + cf[0] = (*cfs.vdata)[gridChan][0][0].data() + cfoff; for (Int sx=-fsupx; sx<=fsupx; ++sx) { - // Loop over polarizations to correct for leakage. - for (Int i=0; i<nGridPol; ++i) { - /// cout<<"cf="<< cf[i]-(*cfs.vdata)[gridChan][ipol][i].data()<<','; - visPtr[i] += *gridPtr * *cf[i]; - cf[i] += fsampx; - } - /// cout<<" g="<<gridPtr-grid.data()<<' '<<nvalue<<endl; + visPtr[ipol] += *gridPtr * *cf[0]; + cf[0] += fsampx; gridPtr++; } + + // // Full version + // const Complex* __restrict__ cf[4]; + // Int cfoff = (offy + sy*fsampy)*nConvX + offx - fsupx*fsampx; + // for (int i=0; i<4; ++i) { + // cf[i] = (*cfs.vdata)[gridChan][i][ipol].data() + cfoff; + // } + // for (Int sx=-fsupx; sx<=fsupx; ++sx) { + // for (Int i=0; i<nVisPol; ++i) { + // visPtr[i] += *gridPtr * *cf[i]; + // cf[i] += fsampx; + // } + // gridPtr++; + // } + } } // end if gridPol } // end if !flagPtr } // end for ipol } // end if ongrid } // end if gridChan + //} } // end for visChan } // end for inx } + // void LofarVisResampler::lofarGridToData(LofarVBStore& vbs, + // const Array<Complex>& grid, + // const Vector<uInt>& rows, + // Int rbeg, Int rend, + // LofarCFStore& cfs) + // { + // // grid[nx,ny,np,nf] + // // vbs.data[np,nf,nrow] + // // cfs[nmx,nmy,nf,ncx,ncy] (mueller,freq,convsize) + + // // Get size of convolution functions. + // Int nConvX = (*(cfs.vdata))[0][0][0].shape()[0]; + // Int nConvY = (*(cfs.vdata))[0][0][0].shape()[1]; + // // Get size of grid. + // Int nGridX = grid.shape()[0]; + // Int nGridY = grid.shape()[1]; + // Int nGridPol = grid.shape()[2]; + // Int nGridChan = grid.shape()[3]; + // // Get visibility data size. + // Int nVisPol = vbs.flagCube_p.shape()[0]; + // Int nVisChan = vbs.flagCube_p.shape()[1]; + // // Get oversampling and support size. + // Int sampx = SynthesisUtils::nint (cfs.sampling[0]); + // Int sampy = SynthesisUtils::nint (cfs.sampling[1]); + // Int supx = cfs.xSupport[0]; + // Int supy = cfs.ySupport[0]; + // ///AlwaysAssert ((2*supx+1)*sampx == nConvX, AipsError); + // ///AlwaysAssert ((2*supy+1)*sampy == nConvY, AipsError); + + // // Loop over all visibility rows to process. + // for (Int inx=rbeg; inx<=rend; ++inx) { + // Int irow = rows[inx]; + // const Double* __restrict__ uvwPtr = vbs.uvw_p.data() + irow*3; + // // Loop over all channels in the visibility data. + // // Map the visibility channel to the grid channel. + // // Skip channel if data are not needed. + // for (Int visChan=0; visChan<nVisChan; ++visChan) { + // Int gridChan = chanMap_p[visChan]; + // if (gridChan >= 0 && gridChan < nGridChan) { + // // Determine the grid position from the UV coordinates in wavelengths. + // Double recipWvl = vbs.freq_p[visChan] / C::c; + // Double posx = uvwScale_p[0] * uvwPtr[0] * recipWvl + offset_p[0]; + // Double posy = uvwScale_p[1] * uvwPtr[1] * recipWvl + offset_p[1]; + // Int locx = SynthesisUtils::nint (posx); // location in grid + // Int locy = SynthesisUtils::nint (posy); + // Double diffx = locx - posx; + // ///if (diffx < 0) diffx += 1; + // Double diffy = locy - posy; + // ///if (diffy < 0) diffy += 1; + // Int offx = SynthesisUtils::nint (diffx * sampx); // location in + // Int offy = SynthesisUtils::nint (diffy * sampy); // oversampling + // /// cout<<" pos= ["<<posx<<", "<<posy<<"]" + // /// <<", loc= ["<<locx<<", "<<locy<<"]" + // /// <<", off= ["<<offx<<", "<<offy<<"]" << endl; + // offx += (nConvX-1)/2; + // offy += (nConvY-1)/2; + // // Scaling with frequency is not necessary (according to Cyril). + // Double freqFact = 1; // = cfFreq / vbs.freq_p[visChan]; + // Int fsampx = SynthesisUtils::nint (sampx * freqFact); + // Int fsampy = SynthesisUtils::nint (sampy * freqFact); + // Int fsupx = SynthesisUtils::nint (supx / freqFact); + // Int fsupy = SynthesisUtils::nint (supy / freqFact); + + // // Only use visibility point if the full support is within grid. + // if (locx-supx >= 0 && locx+supx < nGridX && + // locy-supy >= 0 && locy+supy < nGridY) { + // /// cout << "in grid"<<endl; + // // Get pointer to data and flags for this channel. + // Int doff = (irow * nVisChan + visChan) * nVisPol; + // Complex* __restrict__ visPtr = vbs.visCube_p.data() + doff; + // const Bool* __restrict__ flagPtr = vbs.flagCube_p.data() + doff; + // // Handle a visibility if not flagged. + // for (Int ipol=0; ipol<nVisPol; ++ipol) { + // if (! flagPtr[ipol]) { + // visPtr[ipol] = Complex(0,0); + // } + // } + // for (Int ipol=0; ipol<nVisPol; ++ipol) { + // if (! flagPtr[ipol]) { + // // Map to grid polarization. Only use pol if needed. + // Int gridPol = polMap_p(ipol); + // if (gridPol >= 0 && gridPol < nGridPol) { + // /// Complex norm(0,0); + // // Get the offset in the grid data array. + // Int goff = (gridChan*nGridPol + gridPol) * nGridX * nGridY; + // // Loop over the scaled support. + // for (Int sy=-fsupy; sy<=fsupy; ++sy) { + // // Get the pointer in the grid for the first x in this y. + // const Complex* __restrict__ gridPtr = grid.data() + goff + + // (locy+sy)*nGridX + locx-supx; + // // Get pointers to the first element to use in the 4 + // // convolution functions for this channel,pol. + // const Complex* __restrict__ cf[4]; + // Int cfoff = (offy + sy*fsampy)*nConvX + offx - fsupx*fsampx; + // for (int i=0; i<4; ++i) { + // cf[i] = (*cfs.vdata)[gridChan][i][ipol].data() + cfoff; + // } + // for (Int sx=-fsupx; sx<=fsupx; ++sx) { + // // Loop over polarizations to correct for leakage. + // for (Int i=0; i<nVisPol; ++i) { + // /// cout<<"cf="<< cf[i]-(*cfs.vdata)[gridChan][ipol][i].data()<<','; + // visPtr[i] += *gridPtr * *cf[i]; + // cf[i] += fsampx; + // } + // /// cout<<" g="<<gridPtr-grid.data()<<' '<<nvalue<<endl; + // gridPtr++; + // } + // } + // } // end if gridPol + // } // end if !flagPtr + // } // end for ipol + // } // end if ongrid + // } // end if gridChan + // } // end for visChan + // } // end for inx + // } + + /* void LofarVisResampler::lofarGridToData(LofarVBStore& vbs, const Array<Complex>& grid, @@ -536,14 +945,14 @@ namespace LOFAR { //store2(im,"Aterm-ch"+String::toString(i)+".img"); } } - - + + // Vector<Double> UVWSCALE_MOI(uvwScale_p*1.4); // Vector<Double> UVWOFF_MOI(offset_p); // UVWOFF_MOI(0)=320; // UVWOFF_MOI(1)=320; // UVWOFF_MOI(2)=0; - + Double *freq=vbs.freq_p.getStorage(Dummy); Matrix<Float>& imagingWeight=vbs.imagingWeight_p; @@ -557,7 +966,7 @@ namespace LOFAR { cacheAxisIncrements(grid.shape().asVector(), gridInc_p); cacheAxisIncrements(cfShape, cfInc_p); - for(Int inx=rbeg; inx<rend; inx++) { + for(Int inx=rbeg; inx<=rend; inx++) { Int irow = rows[inx]; for (Int ichan=0; ichan < nDataChan; ichan++) { @@ -574,7 +983,7 @@ namespace LOFAR { uvwScale_p,offset_p,sampling); //sgrid(pos,loc,off,phasor,irow,uvw,dphase_p[irow],freq[ichan], // UVWSCALE_MOI,UVWOFF_MOI,sampling); - + iloc[2]=max(0, min(nw-1, loc[2])); @@ -651,31 +1060,36 @@ namespace LOFAR { IPosition start(vbDataShape), last(vbDataShape); start=0; start(2)=rbeg; last(2)=rend; //last=last-1; + //cout<<"vbDataShape "<<vbDataShape<<" ,last "<<" ,start "<<start<<" ,vbs.modelCube_p "<< (vbs.modelCube_p).shape() << endl; //cout<<"//////////////////// Compuute residual!!!!!!"<<"vbs.useCorrected_p"<<vbs.useCorrected_p<<endl; + + if (!vbs.useCorrected_p) { for(uInt ichan = start(0); ichan < last(0); ichan++) for(uInt ipol = start(1); ipol < last(1); ipol++) for(uInt irow = start(2); irow < last(2); irow++) vbs.modelCube_p(ichan,ipol,irow) = vbs.modelCube_p(ichan,ipol,irow) - vbs.visCube_p(ichan,ipol,irow); - + } else { - for(uInt ichan = start(0); ichan < last(0); ichan++) - for(uInt ipol = start(1); ipol < last(1); ipol++) - for(uInt irow = start(2); irow < last(2); irow++){ + for(uInt ichan = start(0); ichan < last(0); ichan++){ + //cout<< ichan << vbs.modelCube_p(ichan,0,347) <<vbs.correctedCube_p(ichan,0,347)<< endl; + for(uInt ipol = start(1); ipol < last(1); ipol++){ + for(uInt irow = start(2); irow < last(2); irow++){ //cout<<"===="<<endl; //if(!(abs(vbs.modelCube_p(ichan,ipol,irow))==0.)){cout<<ipol<<" "<<ichan<<" "<<irow<<" "<<vbs.modelCube_p(ichan,ipol,irow)<<" "<<vbs.correctedCube_p(ichan,ipol,irow)<<endl;}; - + //if(!(abs(vbs.modelCube_p(ichan,ipol,irow))==0.)){cout<<"data "<<ipol<<" "<<ichan<<" "<<irow<<" "<<vbs.modelCube_p(ichan,ipol,irow)<<" "<<vbs.correctedCube_p(ichan,ipol,irow)<<endl;}; - + vbs.modelCube_p(ichan,ipol,irow) = vbs.modelCube_p(ichan,ipol,irow) - vbs.correctedCube_p(ichan,ipol,irow); //cout<<vbs.modelCube_p(ichan,ipol,irow)<<" "<<vbs.modelCube_p(ichan,ipol,irow)<<" "<<vbs.correctedCube_p(ichan,ipol,irow)<<endl; - }; - + } + } + } } // if (!vbs.useCorrected_p) @@ -684,7 +1098,7 @@ namespace LOFAR { // for(uInt ipol = start(1); ipol < last(1); ipol++) // for(uInt irow = start(2); irow < last(2); irow++) // vbs.modelCube_p(ichan,ipol,irow) = vbs.modelCube_p(ichan,ipol,irow) - vbs.visCube_p(ichan,ipol,irow); - + // } // else // { @@ -696,7 +1110,7 @@ namespace LOFAR { // vbs.correctedCube_p(ichan,ipol,irow) = vbs.correctedCube_p(ichan,ipol,irow) - vbs.modelCube_p(ichan,ipol,irow); // //cout<<vbs.correctedCube_p(ichan,ipol,irow)<<" "<< vbs.correctedCube_p(ichan,ipol,irow)<<" "<< vbs.modelCube_p(ichan,ipol,irow)<<endl; // }; - + // } diff --git a/CEP/Imager/LofarFT/src/LofarVisResamplerOld.cc b/CEP/Imager/LofarFT/src/LofarVisResamplerOld.cc new file mode 100644 index 0000000000000000000000000000000000000000..15808792852dcfdc173ed1373d15ced6aa5ead86 --- /dev/null +++ b/CEP/Imager/LofarFT/src/LofarVisResamplerOld.cc @@ -0,0 +1,741 @@ +//# LofarVisResamplerOld.cc: Implementation of the LofarVisResamplerOld class +//# +//# Copyright (C) 2011 +//# ASTRON (Netherlands Institute for Radio Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +//# +//# This file is part of the LOFAR software suite. +//# The LOFAR software suite is free software: you can redistribute it and/or +//# modify it under the terms of the GNU General Public License as published +//# by the Free Software Foundation, either version 3 of the License, or +//# (at your option) any later version. +//# +//# The LOFAR software suite 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 General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License along +//# with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>. +//# +//# $Id$ + +#include <LofarFT/LofarVisResamplerOld.h> +#include <synthesis/MeasurementComponents/Utils.h> +#include <coordinates/Coordinates/SpectralCoordinate.h> +#include <coordinates/Coordinates/CoordinateSystem.h> +#include<cassert> + +namespace LOFAR { + + // Instantiate both templates. + template + void LofarVisResamplerOld::DataToGridImpl_p(Array<DComplex>& grid, LofarVBStore& vbs, + const Vector<uInt>& rows, + Int rbeg, Int rend, + Matrix<Double>& sumwt,const Bool& dopsf, + LofarCFStore& cfs) __restrict__; + template + void LofarVisResamplerOld::DataToGridImpl_p(Array<Complex>& grid, LofarVBStore& vbs, + const Vector<uInt>& rows, + Int rbeg, Int rend, + Matrix<Double>& sumwt,const Bool& dopsf, + LofarCFStore& cfs) __restrict__; + + + template <class T> + void LofarVisResamplerOld::DataToGridImpl_p(Array<T>& grid, LofarVBStore& vbs, + const Vector<uInt>& rows, + Int rbeg, Int rend, + Matrix<Double>& sumwt, + const Bool& dopsf, + LofarCFStore& cfs) __restrict__ + { + // grid[nx,ny,np,nf] + // vbs.data[np,nf,nrow] + // cfs[nmx,nmy,nf,ncx,ncy] (mueller,freq,convsize) + + // Get size of convolution functions. + Int nConvX = (*(cfs.vdata))[0][0][0].shape()[0]; + Int nConvY = (*(cfs.vdata))[0][0][0].shape()[1]; + // Get size of grid. + Int nGridX = grid.shape()[0]; + Int nGridY = grid.shape()[1]; + Int nGridPol = grid.shape()[2]; + Int nGridChan = grid.shape()[3]; + // Get visibility data size. + Int nVisPol = vbs.flagCube_p.shape()[0]; + Int nVisChan = vbs.flagCube_p.shape()[1]; + // Get oversampling and support size. + Int sampx = SynthesisUtils::nint (cfs.sampling[0]); + Int sampy = SynthesisUtils::nint (cfs.sampling[1]); + Int supx = cfs.xSupport[0]; + Int supy = cfs.ySupport[0]; + ///AlwaysAssert ((2*supx+1)*sampx == nConvX, AipsError); + ///AlwaysAssert ((2*supy+1)*sampy == nConvY, AipsError); + + Double* __restrict__ sumWtPtr = sumwt.data(); + Complex psfValues[4]; + psfValues[0] = psfValues[1] = psfValues[2] = psfValues[3] = Complex(1,0); + + // Loop over all visibility rows to process. + for (Int inx=rbeg; inx<=rend; ++inx) { + Int irow = rows[inx]; + const Double* __restrict__ uvwPtr = vbs.uvw_p.data() + irow*3; + const Float* __restrict__ imgWtPtr = vbs.imagingWeight_p.data() + + irow * nVisChan; + // Loop over all channels in the visibility data. + // Map the visibility channel to the grid channel. + // Skip channel if data are not needed. + for (Int visChan=0; visChan<nVisChan; ++visChan) { + Int gridChan = chanMap_p[visChan]; + if (gridChan >= 0 && gridChan < nGridChan) { + // Determine the grid position from the UV coordinates in wavelengths. + Double recipWvl = vbs.freq_p[visChan] / C::c; + Double posx = uvwScale_p[0] * uvwPtr[0] * recipWvl + offset_p[0]; + Double posy = uvwScale_p[1] * uvwPtr[1] * recipWvl + offset_p[1]; + Int locx = SynthesisUtils::nint (posx); // location in grid + Int locy = SynthesisUtils::nint (posy); + Double diffx = locx - posx; + ///if (diffx < 0) diffx += 1; + Double diffy = locy - posy; + ///if (diffy < 0) diffy += 1; + Int offx = SynthesisUtils::nint (diffx * sampx); // location in + Int offy = SynthesisUtils::nint (diffy * sampy); // oversampling + /// cout<<" pos= ["<<posx<<", "<<posy<<"]" + /// <<", loc= ["<<locx<<", "<<locy<<"]" + /// <<", off= ["<<offx<<", "<<offy<<"]" << endl; + offx += (nConvX-1)/2; + offy += (nConvY-1)/2; + // Scaling with frequency is not necessary (according to Cyril). + Double freqFact = 1; // = cfFreq / vbs.freq_p[visChan]; + Int fsampx = SynthesisUtils::nint (sampx * freqFact); + Int fsampy = SynthesisUtils::nint (sampy * freqFact); + Int fsupx = SynthesisUtils::nint (supx / freqFact); + Int fsupy = SynthesisUtils::nint (supy / freqFact); + + // Only use visibility point if the full support is within grid. + if (locx-supx >= 0 && locx+supx < nGridX && + locy-supy >= 0 && locy+supy < nGridY) { + /// cout << "in grid"<<endl; + // Get pointer to data and flags for this channel. + Int doff = (irow * nVisChan + visChan) * nVisPol; + const Complex* __restrict__ visPtr = vbs.visCube_p.data() + doff; + const Bool* __restrict__ flagPtr = vbs.flagCube_p.data() + doff; + if (dopsf) { + visPtr = psfValues; + } + // Handle a visibility if not flagged. + for (Int ipol=0; ipol<nVisPol; ++ipol) { + if (! flagPtr[ipol]) { + // Map to grid polarization. Only use pol if needed. + Int gridPol = polMap_p(ipol); + if (gridPol >= 0 && gridPol < nGridPol) { + // Get the offset in the grid data array. + Int goff = (gridChan*nGridPol + gridPol) * nGridX * nGridY; + // Loop over the scaled support. + for (Int sy=-fsupy; sy<=fsupy; ++sy) { + // Get the pointer in the grid for the first x in this y. + T* __restrict__ gridPtr = grid.data() + goff + + (locy+sy)*nGridX + locx-supx; + // Get pointers to the first element to use in the 4 + // convolution functions for this channel,pol. + const Complex* __restrict__ cf[4]; + Int cfoff = (offy + sy*fsampy)*nConvX + offx - fsupx*fsampx; + for (int i=0; i<4; ++i) { + cf[i] = (*cfs.vdata)[gridChan][ipol][i].data() + cfoff; + } + for (Int sx=-fsupx; sx<=fsupx; ++sx) { + // Loop over polarizations to correct for leakage. + Complex polSum(0,0); + for (Int i=0; i<nVisPol; ++i) { + /// cout<<"cf="<< cf[i]-(*cfs.vdata)[gridChan][ipol][i].data()<<','; + polSum += visPtr[i] * *cf[i]; + cf[i] += fsampx; + } + /// cout<<" g="<<gridPtr-grid.data()<<' '<<visPtr[i]<<endl; + polSum *= *imgWtPtr; + *gridPtr++ += polSum; + } + } + sumWtPtr[gridPol+gridChan*nGridPol] += *imgWtPtr; + } // end if gridPol + } // end if !flagPtr + } // end for ipol + } // end if ongrid + } // end if gridChan + imgWtPtr++; + } // end for visChan + } // end for inx + } + + /* + template <class T> + void LofarVisResamplerOld::DataToGridImpl_p(Array<T>& grid, LofarVBStore& vbs, + const Vector<uInt>& rows, + Int rbeg, Int rend, + Matrix<Double>& sumwt, + const Bool& dopsf, + LofarCFStore& cfs) + { + Vector<Float> sampling(2); + Vector<Double> pos(3); + Vector<Int> support(2),loc(3), off(3), iloc(4),tiloc(4); + Vector<Int> scaledSampling(2), scaledSupport(2); + Vector<Int> igrdpos(4); + //Float sampling[2]; + //Double pos[3] + // Int support[2], loc[3], off[3], iloc[4], tiloc[4]; + //Int scaledSampling[2], scledSupport[2]; + //Int igrdpos[4]; + + Double norm=0.0; + Complex phasor, nvalue, wt; + // A conv. fucntion per pol. + // For time being only one channel. + Vector<Int> cfShape(4,1); + cfShape[0] = (*(cfs.vdata))[0][0][0].shape()[0]; + cfShape[1] = (*(cfs.vdata))[0][0][0].shape()[1]; + Vector<Int> convOrigin = (cfShape-1)/2; + + Int nx = grid.shape()[0]; + Int ny = grid.shape()[1]; + Int nw = 1; + Int nGridPol = grid.shape()[2]; + Int nGridChan = grid.shape()[3]; + + Int nDataPol = vbs.flagCube_p.shape()[0]; + Int nDataChan = vbs.flagCube_p.shape()[1]; + + sampling[0] = sampling[1] = cfs.sampling[0]; + support[0] = cfs.xSupport[0]; + support[1] = cfs.ySupport[0]; + + T* __restrict__ gridStore = grid.data(); + const Int * __restrict__ iPosPtr = igrdpos.data(); + // const Complex* __restrict__ convFuncV[4]; + // for (int i=0; i<4; ++i) { + // convFuncV[i] = (*(cfs.vdata))[0][i][i].data(); + // } + + const Complex* __restrict__ convFuncV[4][4]; + for (int i=0; i<4; ++i) { + for (int j=0; j<4; ++j) { + const Array<Complex>& conv = (*(cfs.vdata))[0][j][i]; + if (conv.empty()) { + convFuncV[j][i] = 0; + } else { + convFuncV[j][i] = conv.data(); + } + //Matrix<Complex> im((*(cfs.vdata))[0][i][i]); + //store2(im,"Aterm-ch"+String::toString(i)+".img"); + } + } + //cout<<"cfs.vdata= "<<&cfs<<endl; + + const Double *freq = vbs.freq_p.data(); + + // Cache increment values for adding to grid in gridInc. This is + // supplied to addTo4DArray later. + cacheAxisIncrements(grid.shape().asVector(), gridInc_p); + // Cache the CF related increments internally in + // VisibilityResamplerBase for use in getFrom4DArray later. + cacheAxisIncrements(cfShape, cfInc_p); + + const Bool * __restrict__ flagCube_ptr=vbs.flagCube_p.data(); + const Float * __restrict__ imgWts_ptr = vbs.imagingWeight_p.data(); + const Complex * __restrict__ visCube_ptr = vbs.visCube_p.data(); + Double * __restrict__ sumWt_ptr = sumwt.data(); + + // { + // IPosition tt(4); + // for(tt(0)=0;tt(0)<grid.shape()(0);tt(0)++) + // for(tt(1)=0;tt(1)<grid.shape()(1);tt(1)++) + // for(tt(2)=0;tt(2)<grid.shape()(2);tt(2)++) + // for(tt(3)=0;tt(3)<grid.shape()(3);tt(3)++) + // grid(tt)*=1.0; + // } + + for(Int inx=rbeg; inx< rend; inx++){ + Int irow = rows[inx]; + for(Int ichan=0; ichan< nDataChan; ichan++){ + Int achan=chanMap_p[ichan]; + + if((achan>=0) && (achan<nGridChan)) { + + scaledSampling[0] = SynthesisUtils::nint(sampling[0]); + scaledSampling[1] = SynthesisUtils::nint(sampling[1]); + scaledSupport[0] = support[0]; + scaledSupport[1] = support[1]; + + sgrid(pos,loc,off, phasor, irow, + vbs.uvw_p, dphase_p[irow], freq[ichan], + uvwScale_p, offset_p, sampling); + +/// cout<<" pos= ["<<pos[0]<<", "<<pos[1]<<"]" +/// <<", loc= ["<<loc[0]<<", "<<loc[1]<<", "<<loc[2]<<"]" +/// <<", off= ["<<off[0]<<", "<<off[1]<<", "<<off[2]<<"] " +/// << nx << ' '<<ny<<' '<<support[0]<<' '<<support[1] +/// <<endl; + + iloc[2]=max(0, min(nw-1, loc[2])); + + //cout<< nx <<" "<<ny<<" "<<nw<<" "<<loc<<" "<< support<<" "<<onGrid(nx, ny, nw, loc, support)<<endl; + //assert(false); + if (onGrid(nx, ny, nw, loc, support)) { +/// cout << "on grid"<<endl; + + for(Int ipol=0; ipol< nDataPol; ipol++) { + // if((!flagCube(ipol,ichan,irow))){ + if((!(*(flagCube_ptr + ipol + ichan*nDataPol + irow*nDataPol*nDataChan)))){ + Int apol=polMap_p(ipol); + if ((apol>=0) && (apol<nGridPol)) { + igrdpos[2]=apol; igrdpos[3]=achan; + + norm=0.0; + //int ConjPlane = cfMap_p[ipol]; + //int PolnPlane = conjCFMap_p[ipol]; + + iloc[3]=ipol; //PolnPlane; + + //cout<<"Weight= "<<Complex(*(imgWts_ptr + ichan + irow*nDataChan))<<", Vis= "<<(*(visCube_ptr+ipol+ichan*nDataPol+irow*nDataChan*nDataPol)*phasor)<<endl; + + + if(dopsf) nvalue=Complex(*(imgWts_ptr + ichan + irow*nDataChan)); + else nvalue= *(imgWts_ptr+ichan+irow*nDataChan)* + (*(visCube_ptr+ipol+ichan*nDataPol+irow*nDataChan*nDataPol)*phasor); + + + //cout<<"nvalue: "<<nvalue<<endl; + + for(Int iy=-scaledSupport[1]; iy <= scaledSupport[1]; iy++) + { + iloc[1]=(Int)(scaledSampling[1]*iy+off[1]); + igrdpos[1]=loc[1]+iy; + for(Int ix=-scaledSupport[0]; ix <= scaledSupport[0]; ix++) + { + iloc[0]=(Int)(scaledSampling[0]*ix+off[0]); + tiloc=iloc; + if (reindex(iloc,tiloc, 0, 1, + convOrigin, cfShape)) { + //cout << "reindexed"<<iloc<<tiloc<<cfShape<<endl; + + for (int ic=0; ic<4; ++ic) { + if (convFuncV[iloc[3]][ic]) { + //cout<<ic<<" "<<iloc[3]<<" "<<tiloc[0]<<endl; + wt = convFuncV[iloc[3]][ic][tiloc[1]*cfInc_p[1]+tiloc[0]]; +/// cout<<"cf="<<iloc[3]<<' '<<tiloc[1]*cfInc_p[1]+tiloc[0]<<','; + //cout<<wt<<endl; + //wt=convFuncV[iloc[3]][tiloc[1]*cfInc_p[1]+tiloc[0]]; + //wt = (*(cfs.vdata))[0][iloc[3]][iloc[3]](tiloc[0],tiloc[1]); + /// wt = getFrom4DArray(convFuncV, tiloc,cfInc_p); + igrdpos[0]=loc[0]+ix; + // grid(igrdpos) += nvalue*wt; + //cout<<igrdpos[0]<<endl; + //cout<<"ipol="<<ipol<<", iloc[1]="<<iloc[1]<<", cfInc_p[1]="<<cfInc_p[1]<<", iloc[0]="<<iloc[0]<<", wt="<<wt<<", vis="<<nvalue<<endl; + //assert (wt > 1e-10 && wt < 1); + // The following uses raw index on the 4D grid +/// cout << "add " << igrdpos<< gridInc_p +/// << igrdpos[0] + igrdpos[1]*gridInc_p[1] + igrdpos[2]*gridInc_p[2] +igrdpos[3]*gridInc_p[3]<<endl; + addTo4DArray(gridStore,iPosPtr,gridInc_p, nvalue,wt); + // norm+=real(wt); + } + } + } + } + } + // sumwt(apol,achan)+=imagingWeight(ichan,irow);// *norm; + *(sumWt_ptr+apol+achan*nGridChan)+= *(imgWts_ptr+ichan+irow*nDataChan); + } + } + } + } + } + } + } + } + */ + + + // + //----------------------------------------------------------------------------------- + // Re-sample VisBuffer from a regular grid (griddedData) (a.k.a. de-gridding) + // + void LofarVisResamplerOld::lofarGridToData(LofarVBStore& vbs, + const Array<Complex>& grid, + const Vector<uInt>& rows, + Int rbeg, Int rend, + LofarCFStore& cfs) + { + // grid[nx,ny,np,nf] + // vbs.data[np,nf,nrow] + // cfs[nmx,nmy,nf,ncx,ncy] (mueller,freq,convsize) + + // Get size of convolution functions. + Int nConvX = (*(cfs.vdata))[0][0][0].shape()[0]; + Int nConvY = (*(cfs.vdata))[0][0][0].shape()[1]; + // Get size of grid. + Int nGridX = grid.shape()[0]; + Int nGridY = grid.shape()[1]; + Int nGridPol = grid.shape()[2]; + Int nGridChan = grid.shape()[3]; + // Get visibility data size. + Int nVisPol = vbs.flagCube_p.shape()[0]; + Int nVisChan = vbs.flagCube_p.shape()[1]; + // Get oversampling and support size. + Int sampx = SynthesisUtils::nint (cfs.sampling[0]); + Int sampy = SynthesisUtils::nint (cfs.sampling[1]); + Int supx = cfs.xSupport[0]; + Int supy = cfs.ySupport[0]; + ///AlwaysAssert ((2*supx+1)*sampx == nConvX, AipsError); + ///AlwaysAssert ((2*supy+1)*sampy == nConvY, AipsError); + + // Loop over all visibility rows to process. + for (Int inx=rbeg; inx<=rend; ++inx) { + Int irow = rows[inx]; + const Double* __restrict__ uvwPtr = vbs.uvw_p.data() + irow*3; + // Loop over all channels in the visibility data. + // Map the visibility channel to the grid channel. + // Skip channel if data are not needed. + for (Int visChan=0; visChan<nVisChan; ++visChan) { + Int gridChan = chanMap_p[visChan]; + if (gridChan >= 0 && gridChan < nGridChan) { + // Determine the grid position from the UV coordinates in wavelengths. + Double recipWvl = vbs.freq_p[visChan] / C::c; + Double posx = uvwScale_p[0] * uvwPtr[0] * recipWvl + offset_p[0]; + Double posy = uvwScale_p[1] * uvwPtr[1] * recipWvl + offset_p[1]; + Int locx = SynthesisUtils::nint (posx); // location in grid + Int locy = SynthesisUtils::nint (posy); + Double diffx = locx - posx; + ///if (diffx < 0) diffx += 1; + Double diffy = locy - posy; + ///if (diffy < 0) diffy += 1; + Int offx = SynthesisUtils::nint (diffx * sampx); // location in + Int offy = SynthesisUtils::nint (diffy * sampy); // oversampling + /// cout<<" pos= ["<<posx<<", "<<posy<<"]" + /// <<", loc= ["<<locx<<", "<<locy<<"]" + /// <<", off= ["<<offx<<", "<<offy<<"]" << endl; + offx += (nConvX-1)/2; + offy += (nConvY-1)/2; + // Scaling with frequency is not necessary (according to Cyril). + Double freqFact = 1; // = cfFreq / vbs.freq_p[visChan]; + Int fsampx = SynthesisUtils::nint (sampx * freqFact); + Int fsampy = SynthesisUtils::nint (sampy * freqFact); + Int fsupx = SynthesisUtils::nint (supx / freqFact); + Int fsupy = SynthesisUtils::nint (supy / freqFact); + + // Only use visibility point if the full support is within grid. + if (locx-supx >= 0 && locx+supx < nGridX && + locy-supy >= 0 && locy+supy < nGridY) { + /// cout << "in grid"<<endl; + // Get pointer to data and flags for this channel. + Int doff = (irow * nVisChan + visChan) * nVisPol; + Complex* __restrict__ visPtr = vbs.visCube_p.data() + doff; + const Bool* __restrict__ flagPtr = vbs.flagCube_p.data() + doff; + // Handle a visibility if not flagged. + for (Int ipol=0; ipol<nVisPol; ++ipol) { + if (! flagPtr[ipol]) { + visPtr[ipol] = Complex(0,0); + } + } + for (Int ipol=0; ipol<nVisPol; ++ipol) { + if (! flagPtr[ipol]) { + // Map to grid polarization. Only use pol if needed. + Int gridPol = polMap_p(ipol); + if (gridPol >= 0 && gridPol < nGridPol) { + /// Complex norm(0,0); + // Get the offset in the grid data array. + Int goff = (gridChan*nGridPol + gridPol) * nGridX * nGridY; + // Loop over the scaled support. + for (Int sy=-fsupy; sy<=fsupy; ++sy) { + // Get the pointer in the grid for the first x in this y. + const Complex* __restrict__ gridPtr = grid.data() + goff + + (locy+sy)*nGridX + locx-supx; + // Get pointers to the first element to use in the 4 + // convolution functions for this channel,pol. + const Complex* __restrict__ cf[4]; + Int cfoff = (offy + sy*fsampy)*nConvX + offx - fsupx*fsampx; + for (int i=0; i<4; ++i) { + cf[i] = (*cfs.vdata)[gridChan][i][ipol].data() + cfoff; + } + for (Int sx=-fsupx; sx<=fsupx; ++sx) { + // Loop over polarizations to correct for leakage. + for (Int i=0; i<nGridPol; ++i) { + /// cout<<"cf="<< cf[i]-(*cfs.vdata)[gridChan][ipol][i].data()<<','; + visPtr[i] += *gridPtr * *cf[i]; + cf[i] += fsampx; + } + /// cout<<" g="<<gridPtr-grid.data()<<' '<<nvalue<<endl; + gridPtr++; + } + } + } // end if gridPol + } // end if !flagPtr + } // end for ipol + } // end if ongrid + } // end if gridChan + } // end for visChan + } // end for inx + } + + /* + void LofarVisResamplerOld::lofarGridToData(LofarVBStore& vbs, + const Array<Complex>& grid, + const Vector<uInt>& rows, + Int rbeg, Int rend, + LofarCFStore& cfs) + { + Int nDataChan, nDataPol, nGridPol, nGridChan, nx, ny,nw; + Int achan, apol, PolnPlane, ConjPlane; + Vector<Float> sampling(2); + Vector<Int> support(2),loc(3), off(3), iloc(4),tiloc(4), scaledSampling(2), scaledSupport(2); + Vector<Double> pos(3); + + IPosition grdpos(4); + + Complex phasor, nvalue, norm, wt; + Vector<Int> cfShape(4,1); + cfShape[0] = (*(cfs.vdata))[0][0][0].shape()[0]; + cfShape[1] = (*(cfs.vdata))[0][0][0].shape()[1]; + // Vector<Int> convOrigin = (cfShape-1)/2; + Vector<Int> convOrigin = (cfShape-1)/2; + Double sinDPA=0.0, cosDPA=1.0; + + nx = grid.shape()[0]; ny = grid.shape()[1]; + nw = cfShape[2]; + nGridPol = grid.shape()[2]; nGridChan = grid.shape()[3]; + + nDataPol = vbs.flagCube_p.shape()[0]; + nDataChan = vbs.flagCube_p.shape()[1]; + + sampling[0] = sampling[1] = cfs.sampling[0]; + support(0) = cfs.xSupport[0]; + support(1) = cfs.ySupport[0]; + // + // The following code reduces most array accesses to the simplest + // possible to improve performance. However this made no + // difference in the run-time performance compared to Vector, + // Matrix and Cube indexing. + // + Bool Dummy; + const Complex *gridStore = grid.getStorage(Dummy); + Vector<Int> igrdpos(4); + const Int *iPosPtr = igrdpos.getStorage(Dummy); + + // Take all Mueller elements into account. + const Complex* __restrict__ convFuncV[4][4]; + for (int i=0; i<4; ++i) { + for (int j=0; j<4; ++j) { + const Array<Complex>& conv = (*(cfs.vdata))[0][j][i]; + if (conv.empty()) { + convFuncV[j][i] = 0; + } else { + convFuncV[j][i] = conv.data(); + } + //Matrix<Complex> im((*(cfs.vdata))[0][i][i]); + //store2(im,"Aterm-ch"+String::toString(i)+".img"); + } + } + + + // Vector<Double> UVWSCALE_MOI(uvwScale_p*1.4); + // Vector<Double> UVWOFF_MOI(offset_p); + // UVWOFF_MOI(0)=320; + // UVWOFF_MOI(1)=320; + // UVWOFF_MOI(2)=0; + + Double *freq=vbs.freq_p.getStorage(Dummy); + + Matrix<Float>& imagingWeight=vbs.imagingWeight_p; + Matrix<Double>& uvw=vbs.uvw_p; + Cube<Complex>& visCube=vbs.visCube_p; + Cube<Bool>& flagCube=vbs.flagCube_p; + + Vector<Int> gridInc, cfInc; + + // cacheAxisIncrements(nx,ny,nGridPol, nGridChan); + cacheAxisIncrements(grid.shape().asVector(), gridInc_p); + cacheAxisIncrements(cfShape, cfInc_p); + + for(Int inx=rbeg; inx<rend; inx++) { + Int irow = rows[inx]; + + for (Int ichan=0; ichan < nDataChan; ichan++) { + achan=chanMap_p[ichan]; + + if((achan>=0) && (achan<nGridChan)) { + + scaledSampling[0] = SynthesisUtils::nint(sampling[0]); + scaledSampling[1] = SynthesisUtils::nint(sampling[1]); + scaledSupport[0] = support[0]; + scaledSupport[1] = support[1]; + + sgrid(pos,loc,off,phasor,irow,uvw,dphase_p[irow],freq[ichan], + uvwScale_p,offset_p,sampling); + //sgrid(pos,loc,off,phasor,irow,uvw,dphase_p[irow],freq[ichan], + // UVWSCALE_MOI,UVWOFF_MOI,sampling); + + + + iloc[2]=max(0, min(nw-1, loc[2])); + //cout<<"-----------------------"<<endl; + if (onGrid(nx, ny, nw, loc, support)) { + for(Int ipol=0; ipol < nDataPol; ipol++) { + //cout<<"ipol "<<ipol<<endl; + if(!flagCube(ipol,ichan,irow)) { + apol=polMap_p[ipol]; + + if((apol>=0) && (apol<nGridPol)) { + igrdpos[2]=apol; igrdpos[3]=achan; + nvalue=0.0; + norm =0.0; + + //ConjPlane = cfMap_p(ipol); + //PolnPlane = conjCFMap_p(ipol); + + iloc[3]=ipol; + + for(Int iy=-scaledSupport[1]; iy <= scaledSupport[1]; iy++) + { + iloc(1)=(Int)(scaledSampling[1]*iy+off[1]); + igrdpos[1]=loc[1]+iy; + + for(Int ix=-scaledSupport[0]; ix <= scaledSupport[0]; ix++) + { + iloc(0)=(Int)(scaledSampling[0]*ix+off[0]); + igrdpos[0]=loc[0]+ix; + tiloc=iloc; + if (reindex(iloc,tiloc,sinDPA, cosDPA, + convOrigin, cfShape)) + { + // Use polarization leakage terms if defined. + for (int ic=0; ic<4; ++ic) { + if (convFuncV[ic][iloc[3]]) { + //cout<<"iloc[3]<<ic "<<iloc[3]<<" "<<ic<<endl; + wt = convFuncV[iloc[3]][ic][tiloc[1]*cfInc_p[1]+tiloc[0]]; + //wt = conj(convFuncV[ic][iloc[3]][tiloc[1]*cfInc_p[1]+tiloc[0]]); + norm+=(wt); + // nvalue+=wt*grid(grdpos); + // The following uses raw index on the 4D grid + // nvalue+=wt*getFrom4DArray(gridStore,iPosPtr,gridInc); + igrdpos[2] = ic; + //igrdpos[2] = iloc[3];//ic; + Complex wt2=getFrom4DArray(gridStore,igrdpos,gridInc_p); + //cout<<"Resampler : ic iloc cf sumcf vis: "<<ic<<" "<<iloc[3]<<" "<<wt<<" "<<nvalue<<" "<<wt2<<endl; + nvalue+=wt*wt2; + //cout<<"wt wt2 wt*wt2 = "<<wt<<" "<<wt2<<" "<<wt*wt2<<endl; + } + } + } + } + } + //cout<<"nvalue<<" "<<conj(phasor)<<" "<<norm= "<<nvalue<<" "<<conj(phasor)<<" "<<norm<<endl; + visCube(ipol,ichan,irow)=nvalue;//(nvalue*conj(phasor))/norm; + //cout<<"Vis "<<visCube(ipol,ichan,irow)<<" "<<ipol<<" "<<ichan<<" "<<irow<<endl; + //modelCube(ipol,ichan,irow)=(nvalue*conj(phasor))/norm; + //cout<<"modelCube = "<<modelCube(ipol,ichan,irow)<<endl; + } + } + } + } + } + } + } + } + */ + + void LofarVisResamplerOld::lofarComputeResiduals(LofarVBStore& vbs) + { + Int rbeg = vbs.beginRow_p, rend = vbs.endRow_p; + IPosition vbDataShape=vbs.modelCube_p.shape(); + IPosition start(vbDataShape), last(vbDataShape); + start=0; start(2)=rbeg; + last(2)=rend; //last=last-1; + + //cout<<"//////////////////// Compuute residual!!!!!!"<<"vbs.useCorrected_p"<<vbs.useCorrected_p<<endl; + + if (!vbs.useCorrected_p) + { + for(uInt ichan = start(0); ichan < last(0); ichan++) + for(uInt ipol = start(1); ipol < last(1); ipol++) + for(uInt irow = start(2); irow < last(2); irow++) + vbs.modelCube_p(ichan,ipol,irow) = vbs.modelCube_p(ichan,ipol,irow) - vbs.visCube_p(ichan,ipol,irow); + + } + else + { + for(uInt ichan = start(0); ichan < last(0); ichan++) + for(uInt ipol = start(1); ipol < last(1); ipol++) + for(uInt irow = start(2); irow < last(2); irow++){ + //cout<<"===="<<endl; + //if(!(abs(vbs.modelCube_p(ichan,ipol,irow))==0.)){cout<<ipol<<" "<<ichan<<" "<<irow<<" "<<vbs.modelCube_p(ichan,ipol,irow)<<" "<<vbs.correctedCube_p(ichan,ipol,irow)<<endl;}; + + //if(!(abs(vbs.modelCube_p(ichan,ipol,irow))==0.)){cout<<"data "<<ipol<<" "<<ichan<<" "<<irow<<" "<<vbs.modelCube_p(ichan,ipol,irow)<<" "<<vbs.correctedCube_p(ichan,ipol,irow)<<endl;}; + + vbs.modelCube_p(ichan,ipol,irow) = vbs.modelCube_p(ichan,ipol,irow) - vbs.correctedCube_p(ichan,ipol,irow); + //cout<<vbs.modelCube_p(ichan,ipol,irow)<<" "<<vbs.modelCube_p(ichan,ipol,irow)<<" "<<vbs.correctedCube_p(ichan,ipol,irow)<<endl; + }; + + } + + // if (!vbs.useCorrected_p) + // { + // for(uInt ichan = start(0); ichan < last(0); ichan++) + // for(uInt ipol = start(1); ipol < last(1); ipol++) + // for(uInt irow = start(2); irow < last(2); irow++) + // vbs.modelCube_p(ichan,ipol,irow) = vbs.modelCube_p(ichan,ipol,irow) - vbs.visCube_p(ichan,ipol,irow); + + // } + // else + // { + // for(uInt ichan = start(0); ichan < last(0); ichan++) + // for(uInt ipol = start(1); ipol < last(1); ipol++) + // for(uInt irow = start(2); irow < last(2); irow++){ + // //cout<<"===="<<endl; + // //cout<<vbs.correctedCube_p(ichan,ipol,irow)<<" "<< vbs.correctedCube_p(ichan,ipol,irow)<<" "<< vbs.modelCube_p(ichan,ipol,irow)<<endl; + // vbs.correctedCube_p(ichan,ipol,irow) = vbs.correctedCube_p(ichan,ipol,irow) - vbs.modelCube_p(ichan,ipol,irow); + // //cout<<vbs.correctedCube_p(ichan,ipol,irow)<<" "<< vbs.correctedCube_p(ichan,ipol,irow)<<" "<< vbs.modelCube_p(ichan,ipol,irow)<<endl; + // }; + + // } + + + } + + void LofarVisResamplerOld::sgrid(Vector<Double>& pos, Vector<Int>& loc, + Vector<Int>& off, Complex& phasor, + const Int& irow, const Matrix<Double>& uvw, + const Double& dphase, const Double& freq, + const Vector<Double>& scale, + const Vector<Double>& offset, + const Vector<Float>& sampling) + { + Double phase; + Vector<Double> uvw_l(3,0); // This allows gridding of weights + // centered on the uv-origin + if (uvw.nelements() > 0) for(Int i=0;i<3;i++) uvw_l[i]=uvw(i,irow); + + pos(2)=0;//sqrt(abs(scale[2]*uvw_l(2)*freq/C::c))+offset[2]; + loc(2)=0;//SynthesisUtils::nint(pos[2]); + off(2)=0; + + for(Int idim=0;idim<2;idim++) + { + pos[idim]=scale[idim]*uvw_l(idim)*freq/C::c+offset[idim]; + /// cout<<scale[idim]<<' '<<uvw_l[idim]<<' '<<offset[idim]<<' '<<pos[idim]<<endl; + loc[idim]=SynthesisUtils::nint(pos[idim]); + //off[idim]=SynthesisUtils::nint((loc[idim]-pos[idim])*sampling[idim]); // Cyr: I've added "+1" next line, and it solves a difficult problem, i don't know why + ////off[idim]=SynthesisUtils::nint((loc[idim]-pos[idim])*sampling[idim]+1); + off[idim]=SynthesisUtils::nint((loc[idim]-pos[idim])*sampling[idim]); + } + + //if (dphase != 0.0) + // { +// phase=-2.0*C::pi*dphase*freq/C::c; +// phasor=Complex(cos(phase), sin(phase)); + // } + //else + phasor=Complex(1.0); + } + +} // end namespace diff --git a/CEP/Imager/LofarFT/src/awimager.cc b/CEP/Imager/LofarFT/src/awimager.cc index 18f38d6d6f876086e3abf1d8bed5790362cfba4e..f782f4e58e14461766257328ef3af859504db643 100644 --- a/CEP/Imager/LofarFT/src/awimager.cc +++ b/CEP/Imager/LofarFT/src/awimager.cc @@ -1,4 +1,4 @@ -//# awzim.cc: Program to create and/or clean a LOFAR image +//# awimager.cc: Program to create and/or clean a LOFAR image //# Copyright (C) 2011 //# Associated Universities, Inc. Washington DC, USA. //# @@ -39,6 +39,7 @@ #include <casa/Utilities/Regex.h> #include <casa/Utilities/Assert.h> #include <casa/OS/Directory.h> +#include <casa/OS/File.h> #include <casa/Exceptions/Error.h> #include <casa/OS/Timer.h> #include <casa/OS/PrecTimer.h> @@ -128,7 +129,7 @@ void readFilter (const String& filter, } } -Matrix<Bool> readMueller (const String& str) +Matrix<Bool> readMueller (const String& str, String stokes, Bool grid) { Matrix<Bool> mat(4,4, True); String s(str); @@ -147,6 +148,20 @@ Matrix<Bool> readMueller (const String& str) throw AipsError (str + " is an invalid Mueller specification"); } } + if((stokes=="I")&&(grid)){ + for(uInt i=0;i<4;++i){ + mat(1,i)=0; + mat(2,i)=0; + }; + } + if((stokes=="I")&&(!grid)){ + for(uInt i=0;i<4;++i){ + mat(1,i)=0; + mat(2,i)=0; + // mat(i,1)=0; + // mat(i,2)=0; + }; + }; return mat; } @@ -163,6 +178,7 @@ void applyFactors (PagedImage<Float>& image, const Array<Float>& factors) { Array<Float> data; image.get (data); + /// cout << "apply factor to " << data.data()[0] << ' ' << factors.data()[0]<<endl; // Loop over channels for (ArrayIterator<Float> iter1(data, 3); !iter1.pastEnd(); iter1.next()) { // Loop over Stokes. @@ -173,10 +189,12 @@ void applyFactors (PagedImage<Float>& image, const Array<Float>& factors) } } image.put (data); + /// cout << "applied factor to " << data.data()[0] << ' ' << factors.data()[0]<<endl; } void correctImages (const String& restoName, const String& modelName, - const String& residName, const String& imgName) + const String& residName, const String& imgName, + LOFAR::LofarImager& imager, Bool CorrectElement) { // Copy the images to .corr ones. { @@ -195,15 +213,14 @@ void correctImages (const String& restoName, const String& modelName, restoredImage.shape() == modelImage.shape(), SynthesisError); // Get average primary beam and spheroidal. - Matrix<Float> avgPB = LOFAR::LofarConvolutionFunction::getAveragePB(imgName); - Matrix<Float> spheroidCut = LOFAR::LofarConvolutionFunction::getSpheroidCut(imgName); - // String nameii(imgName + ".spheroid_cut_im"); - //ostringstream nameiii(nameii); - //PagedImage<Float> restoredImageiii(nameiii.str().c_str()); - //Slicer sliceiiii(IPosition(4,0,0,0,0), restoredImageiii.shape(), IPosition(4,1,1,1,1)); - //Array<Float> spheroidCut; - //restoredImageiii.doGetSlice(spheroidCut , sliceiiii); - + Matrix<Float> avgPB = LOFAR::LofarConvolutionFunction::getAveragePB(imgName+"0"); + Matrix<Float> spheroidCut = LOFAR::LofarConvolutionFunction::getSpheroidCut(imgName+"0"); + String nameii("Spheroid_cut_im_element.img"); + ostringstream nameiii(nameii); + PagedImage<Float> tmpi(nameiii.str().c_str()); + Slicer slicei(IPosition(4,0,0,0,0), tmpi.shape(), IPosition(4,1,1,1,1)); + Array<Float> spheroidCutElement; + tmpi.doGetSlice(spheroidCutElement, slicei); // Use the inner part of the beam and spheroidal. Int nximg = restoredImage.shape()[0]; Int nxpb = avgPB.shape()[0]; @@ -219,7 +236,15 @@ void correctImages (const String& restoName, const String& modelName, IPosition(2, nximg, nximg))); Array<Float> sphinner = spheroidCut(Slicer(IPosition(2, offsph, offsph), IPosition(2, nximg, nximg))); - Array<Float> factors = sphinner / sqrt(pbinner); + Array<Float> factors; + if(CorrectElement){ + Array<Float> sphinner_el = (spheroidCutElement(Slicer(IPosition(4, offsph, offsph,0,0), + IPosition(4, nximg, nximg,1,1)))).nonDegenerate(); + factors = sphinner_el *sphinner / sqrt(pbinner);//sphinner_el * sphinner / sqrt(pbinner); + } else{ + + factors = sphinner / sqrt(pbinner);//sphinner_el * sphinner / sqrt(pbinner); + } applyFactors (restoredImage, factors); applyFactors (modelImage, factors); applyFactors (residualImage, factors); @@ -292,14 +317,11 @@ int main (Int argc, char** argv) inputs.create ("wmax", "500.0", "omit data with w-term > wmax (in meters)", "float"); - inputs.create ("beamelementpath", "$LOFARROOT/share", - "directory where the Hamaker beam element files reside", - "string"); inputs.create ("muellergrid", "all", - "Nueller elements to use when gridding (all,diagonal,band1,band2)", + "Mueller elements to use when gridding (all,diagonal,band1,band2)", "string"); inputs.create ("muellerdegrid", "all", - "Nueller elements to use when degridding (all,diagonal,band1,band2)", + "Mueller elements to use when degridding (all,diagonal,band1,band2)", "string"); inputs.create ("cachesize", "512", "maximum size of gridding cache (in MBytes)", @@ -354,7 +376,7 @@ int main (Int argc, char** argv) "string"); inputs.create ("operation", "image", /// "Operation (empty,image,clark,hogbom,csclean,multiscale,entropy)", - "Operation (empty,image,csclean)", + "Operation (empty,image,csclean,predict,psf)", "string"); inputs.create ("niter", "1000", "Number of clean iterations", @@ -404,12 +426,68 @@ int main (Int argc, char** argv) inputs.create ("oversample", "8", "oversampling for convolution functions", "int"); - + inputs.create ("uvdist", "", + "UV Range", + "string"); + inputs.create ("RefFreq", "", + "Reference Frequency (Hz)", + "Double"); + inputs.create ("nterms", "1", + "Number of Taylor terms", + "int"); + inputs.create ("UseLIG", "false", + "Use gridder using linear interpolation (not working yet, never to be)", + "bool"); + inputs.create ("UseEJones", "true", + "Use the beam for the calculation of the convolution function (not working yet)", + "bool"); + inputs.create ("applyIonosphere", "false", + "apply ionospheric correction", + "bool"); + inputs.create ("splitbeam", "true", + "Evaluate station beam and element beam separately (splitbeam = true is faster)", + "bool"); + // inputs.create ("ApplyElement", "false", + // "Apply the element beam", + // "bool"); + inputs.create ("PBCut", "1e-2", + "Level below which the dirty images will be set to zero. Expressed in units of peak primary beam.", + "Double"); + inputs.create ("cyclefactor", "1.5", + "Cycle Factor. See Casa definition.", + "Double"); + inputs.create ("cyclespeedup", "-1", + "Cycle Factor. See Casa definition.", + "Double"); + inputs.create ("ModelImPredict", "", + "Input Model image for the predict", + "string"); + inputs.create ("PsfImage", "", + "Input PSF image for the cleaning", + "string"); + inputs.create ("StepApplyElement", "0", + "If turned to >0, apply the element beam every N number of timewindows.", + "int"); + inputs.create ("UseMasks", "true", + "When the element beam is applied (StepApplyElement), the addictional step of convolving the grid can be made more efficient by computing masks. If true, it will create a directory in which it stores the masks.", + "bool"); + inputs.create ("RowBlock", "0", + "In certain obscure circounstances (taql, selection using uvdist), the RowBlocking used by the imager calculated from the timewindow value is not correct. This parameter can be used to specify the RowBlocking.", + "int"); + // inputs.create ("FillFactor", "1", + // "Fraction of the data that will be selected from the selected MS. (don't use it yet)", + // "Double"); + // Fill the input structure from the command line. inputs.readArguments (argc, argv); // Get the input specification. Bool fixed = inputs.getBool("fixed"); + Bool UseLIG = inputs.getBool("UseLIG"); + Bool UseEJones = inputs.getBool("UseEJones"); + Bool applyIonosphere = inputs.getBool("applyIonosphere"); + Bool splitbeam = inputs.getBool("splitbeam"); + Bool ApplyElement ;//= inputs.getBool("ApplyElement"); Bool constrainFlux = inputs.getBool("constrainflux"); Bool preferVelocity = inputs.getBool("prefervelocity"); Bool displayProgress= inputs.getBool("displayprogress"); @@ -430,11 +508,15 @@ int main (Int argc, char** argv) Int verbose = inputs.getInt("verbose"); Int maxsupport = inputs.getInt("maxsupport"); Int oversample = inputs.getInt("oversample"); + Int StepApplyElement = inputs.getInt("StepApplyElement"); + if ((StepApplyElement%2 == 0)&&((StepApplyElement%2 != 0))) { + StepApplyElement++; + } + Int nterms = inputs.getInt("nterms"); Vector<Double> userScaleSizes(inputs.getDoubleVector("uservector")); Double padding = inputs.getDouble("padding"); Double gain = inputs.getDouble("gain"); Double maskValue = inputs.getDouble("maskvalue"); - String beamDir = inputs.getString("beamelementpath"); String mode = inputs.getString("mode"); String operation = inputs.getString("operation"); String weight = inputs.getString("weight"); @@ -461,11 +543,21 @@ int main (Int argc, char** argv) String psfName = inputs.getString("psf"); String imageType = inputs.getString("data"); String select = inputs.getString("select"); + String uvdist = inputs.getString("uvdist"); String maskName = inputs.getString("mask"); String mstrBlc = inputs.getString("maskblc"); String mstrTrc = inputs.getString("masktrc"); - Matrix<Bool> muelgrid = readMueller (inputs.getString("muellergrid")); - Matrix<Bool> mueldegrid = readMueller (inputs.getString("muellerdegrid")); + Double RefFreq = inputs.getDouble("RefFreq"); + Double PBCut = inputs.getDouble("PBCut"); + Double cyclefactor = inputs.getDouble("cyclefactor"); + Double cyclespeedup = inputs.getDouble("cyclespeedup"); + Matrix<Bool> muelgrid = readMueller (inputs.getString("muellergrid"), stokes, true); + Matrix<Bool> mueldegrid = readMueller (inputs.getString("muellerdegrid"), stokes, false); + String ModelImPredict = inputs.getString("ModelImPredict"); + String PsfImage = inputs.getString("PsfImage"); + Bool Use_masks = inputs.getBool("UseMasks"); + Int RowBlock = inputs.getInt("RowBlock"); + //Double FillFactor= 1.;//inputs.getDouble("FillFactor"); // Check and interpret input values. Quantity qcellsize = readQuantity (cellsize); @@ -534,13 +626,13 @@ int main (Int argc, char** argv) phaseCenter = readDirection (phasectr); } operation.downcase(); - AlwaysAssertExit (operation=="empty" || operation=="image" || operation=="csclean"); + AlwaysAssertExit (operation=="empty" || operation=="image" || operation=="csclean"|| operation=="msmfs"||operation=="predict"||operation=="psf"); ///AlwaysAssertExit (operation=="empty" || operation=="image" || operation=="hogbom" || operation=="clark" || operation=="csclean" || operation=="multiscale" || operation =="entropy"); IPosition maskBlc, maskTrc; Quantity threshold; Quantity sigma; Quantity targetFlux; - Bool doClean = (operation != "empty" && operation != "image"); + Bool doClean = (operation != "empty" && operation != "image"&& operation != "psf"); if (doClean) { maskBlc = readIPosition (mstrBlc); maskTrc = readIPosition (mstrTrc); @@ -548,6 +640,11 @@ int main (Int argc, char** argv) sigma = readQuantity (sigmaStr); targetFlux = readQuantity (targetStr); } + Bool doPSF =(operation=="psf"); + if(doPSF==true){ + operation="csclean"; + niter=0; + } // Get axis specification from filter. Quantity bmajor, bminor, bpa; readFilter (filter, bmajor, bminor, bpa); @@ -558,21 +655,54 @@ int main (Int argc, char** argv) Record params; params.define ("timewindow", timewindow); params.define ("wmax", wmax); - params.define ("beam.element.path", beamDir); params.define ("mueller.grid", muelgrid); params.define ("mueller.degrid", mueldegrid); params.define ("verbose", verbose); params.define ("maxsupport", maxsupport); params.define ("oversample", oversample); params.define ("imagename", imgName); + params.define ("UseLIG", UseLIG); + params.define ("UseEJones", UseEJones); + //params.define ("ApplyElement", ApplyElement); + params.define ("PBCut", PBCut); + params.define ("StepApplyElement", StepApplyElement); + Bool PredictFT(false); + if(operation=="predict"){PredictFT=true;} + params.define ("PredictFT", PredictFT); + params.define ("PsfImage", PsfImage); + params.define ("UseMasksDegrid", Use_masks); + params.define ("RowBlock", RowBlock); + params.define ("doPSF", doPSF); + params.define ("applyIonosphere", applyIonosphere); + params.define ("splitbeam", splitbeam); + //params.define ("FillFactor", FillFactor); + LOFAR::LofarImager imager(ms, params); + + MSSpWindowColumns window(ms.spectralWindow()); + // ROMSObservationColumns timerange(ms.observation()); + // cout<<"timerange"<<timerange.timerange()<<endl; + Vector<Int> wind(window.nrow()); + for(uInt iii=0;iii<window.nrow();++iii){wind(iii)=iii;}; + cout<<"... Windows is shit"<<endl; + + ROArrayColumn<Double> chfreq(window.chanFreq()); + + cout<<"Number of channels: "<<chfreq(0).shape()[0]<<endl; + + Vector<Int> chansel(1); + chansel(0)=chfreq(0).shape()[0]; + //chansel(1)=1; + //chansel(2)=2; + //chansel(3)=3; + imager.setdata (chanmode, // mode - nchan, + chansel,//nchan, chanstart, chanstep, MRadialVelocity(), // mStart MRadialVelocity(), // mStep - spwid, + wind,//spwid, Vector<Int>(1,fieldid), select, // msSelect String(), // timerng @@ -580,10 +710,22 @@ int main (Int argc, char** argv) Vector<Int>(), // antIndex String(), // antnames String(), // spwstring - String(), // uvdist + uvdist, // uvdist String(), // scan True); // useModelCol + + imager.setmfcontrol(cyclefactor, //Float cyclefactor, + cyclespeedup, //Float cyclespeedup, + 0.8, //Float cyclemaxpsffraction, + 2, //Int stoplargenegatives, + -1, //Int stoppointmode, + "", //String& scaleType, + 0.1, //Float minPB, + 0.4, //loat constPB, + Vector<String>(1, ""), //Vector<String>& fluxscale, + true); //Bool flatnoise); + imager.defineImage (npix, // nx npix, // ny qcellsize, // cellx @@ -598,9 +740,25 @@ int main (Int argc, char** argv) MFrequency(), // mFreqstart MRadialVelocity(), // mStart Quantity(1,"km/s"), // qstep, Def=1 km/s - spwid, // spectralwindowids + wind,//spwid, // spectralwindowids nfacet); // facets + if (operation=="predict"){ + String ftmachine("ft"); + if (wplanes > 0) { + ftmachine = "wproject"; + } + imager.setoptions(ftmachine, // ftmachine + cachesize*1024*(1024/8), // cache + 16, // tile + "SF", // gridfunction + MPosition(), // mLocation + padding, // padding + wplanes); // wprojplanes + imager.ft(Vector<String>(1, ModelImPredict), "", + False); + } else{ + // Create empty image? if (operation == "empty" ) { makeEmpty (imager, imgName, fieldid); @@ -707,25 +865,109 @@ int main (Int argc, char** argv) Vector<String>(1, maskName), // mask Vector<String>(1, restoName), // restored Vector<String>(1, residName)); // residual - } else { + } + if (operation == "msmfs") { + //uInt nterms(2); + + //imager.settaylorterms(nterms,5.95e+07); + imager.settaylorterms(nterms,RefFreq); + String scaleMethod; + Vector<Float> userVector(1); userVector(0)=0; + convertArray (userVector, userScaleSizes); + if (userScaleSizes.size() > 1) { + scaleMethod = "uservector"; + } else { + scaleMethod = "nscales"; + } + imager.setscales(scaleMethod, 1, userVector); + cout<<imgName<<endl; + makeEmpty (imager, imgName, 0); + Directory filee(imgName); + + + Vector<String> modelNames(nterms); + for(uInt i=0;i<nterms;++i){ + modelNames(i)="test.img.model.tt"+String::toString(i); + + Directory filee0(modelNames(i)); + File file_model0(modelNames(i)); + if(file_model0.exists()){filee0.removeRecursive();}; + Path model0(modelNames(i)); + filee.copy(model0); + }; + + // assert(false); + + imager.clean("msmfs", // algorithm, + niter, // niter + gain, // gain + threshold, // threshold + displayProgress, // displayProgress + //Vector<String>(1, modelName), // model + modelNames, + Vector<Bool>(1, fixed), // fixed + "", // complist + Vector<String>(1, maskName), // mask + Vector<String>(1, restoName), // restored + Vector<String>(1, residName), // residual + Vector<String>(1, psfName)); // psf + + } + else { + Vector<String> modelNames(2); + modelNames[0]="model.main"; + modelNames[1]="model.outlier"; + File Dir_masks_file("JAWS_masks_degrid"); + Directory Dir_masks("JAWS_masks_degrid"); + if(Dir_masks_file.exists()){ + Dir_masks.removeRecursive(); + } + if(Use_masks){ + Dir_masks.create(); + } + // Vector<String> Namelist(5); + // Namelist[0]=".spheroid_cut_im"; + // Namelist[1]=".residual"; + // Namelist[2]=".residual.corr"; + // Namelist[3]=".restored"; + // Namelist[4]=".restored.corr"; + // //Namelist[5]="0.avgpb"; + // for(uInt i=0; i<Namelist.size(); ++i){ + // String avgpb_name(imgName + Namelist[i]); + // File avgpb_name_file(avgpb_name); + // Directory avgpb_name_dir(avgpb_name); + // cout<<avgpb_name<<endl; + // if(avgpb_name_file.exists()){ + // cout<<"... remove"<<endl; + // avgpb_name_dir.removeRecursive(); + // } + // } + // Regex rx1 (Regex::fromPattern ("*.avgpb")); + // Vector<String> avgpbfiles; + // avgpbfiles=Directory::find(rx1); + imager.clean(operation, // algorithm, niter, // niter gain, // gain threshold, // threshold displayProgress, // displayProgress Vector<String>(1, modelName), // model + // modelNames, Vector<Bool>(1, fixed), // fixed "", // complist Vector<String>(1, maskName), // mask Vector<String>(1, restoName), // restored Vector<String>(1, residName), // residual Vector<String>(1, psfName)); // psf + } // Do the final correction for primary beam and spheroidal. - correctImages (restoName, modelName, residName, imgName); + ApplyElement=false; + if(StepApplyElement>0){ApplyElement=true;} + correctImages (restoName, modelName, residName, imgName, imager, ApplyElement); precTimer.stop(); timer.show ("clean"); - ///imager.showTimings (cout, precTimer.getReal()); + /// imager.showTimings (cout, precTimer.getReal()); // Convert result to fits if needed. if (! fitsName.empty()) { String error; @@ -740,10 +982,10 @@ int main (Int argc, char** argv) } } } - } catch (AipsError& x) { + } }catch (AipsError& x) { cout << x.getMesg() << endl; return 1; - } - cout << "awzim normally ended" << endl; + } + cout << "awimager normally ended" << endl; return 0; } diff --git a/CEP/Imager/LofarFT/src/makefftwisdom2d.cc b/CEP/Imager/LofarFT/src/makefftwisdom2d.cc index c86442986dabd3617b9c9c6899396aa79d8605a1..9259136d5bec368bcd3a3122b08743c6ef858d6a 100644 --- a/CEP/Imager/LofarFT/src/makefftwisdom2d.cc +++ b/CEP/Imager/LofarFT/src/makefftwisdom2d.cc @@ -92,7 +92,7 @@ int main (int argc, char* argv[]) cerr << endl; cout << "Creating 2D FFTW wisdom for some multiples of 1024 (till 16384) ..." << endl; - int otherSizes[] = {512, 1024, 2048, 4096, 6144, 8192, 10240, 12288, 16384}; + int otherSizes[] = {512, 1024};//, 2048, 4096, 6144, 8192, 10240, 12288, 16384}; nsizes = sizeof(otherSizes) / sizeof(int); for (int i=0; i<2; ++i) { cerr << ' ' << otherSizes[i]; diff --git a/CEP/ParmDB/src/makesourcedb.cc b/CEP/ParmDB/src/makesourcedb.cc index 11b227910083ffb6fc67a9e3fc5b2579dbad053b..8aaebb4b6bf56ad4e0b2f3ac995ff0303ecebe35 100644 --- a/CEP/ParmDB/src/makesourcedb.cc +++ b/CEP/ParmDB/src/makesourcedb.cc @@ -973,10 +973,7 @@ void make (const string& in, const string& out, int nrsource = 0; int nrpatchfnd = 0; int nrsourcefnd = 0; - if (in.empty()) { - process (string(), pdb, sdbf, check, nrpatch, nrsource, - nrpatchfnd, nrsourcefnd, searchInfo); - } else { + if (! in.empty()) { ifstream infile(in.c_str()); ASSERTSTR (infile, "File " << in << " could not be opened"); casa::Regex regexf("^[ \t]*[fF][oO][rR][mM][aA][tT][ \t]*=.*"); @@ -1015,11 +1012,11 @@ void make (const string& in, const string& out, << pdb.getParmDBMeta().getTableName() << endl; vector<string> dp(pdb.findDuplicatePatches()); if (dp.size() > 0) { - cout << "Duplicate patches: " << dp << endl; + cerr << "Duplicate patches: " << dp << endl; } vector<string> ds(pdb.findDuplicateSources()); if (ds.size() > 0) { - cout << "Duplicate sources: " << ds << endl; + cerr << "Duplicate sources: " << ds << endl; } } @@ -1031,6 +1028,9 @@ string readFormat (string file, const string& catFile) if (file.empty()) { file = catFile; } + if (file.empty()) { + return string(); + } // Read file until format line is found or until non-comment is found. ifstream infile(file.c_str()); ASSERTSTR (infile, "File " << file @@ -1075,13 +1075,12 @@ int main (int argc, char* argv[]) try { // Get the inputs. Input inputs(1); - inputs.version ("GvD 2011-Sep-01"); + inputs.version ("GvD 2011-Feb-17"); inputs.create("in", "", "Input file name", "string"); inputs.create("out", "", "Output sourcedb name", "string"); - inputs.create("format", "Name,Type,Ra,Dec,I,Q,U,V,MajorAxis," - "MinorAxis,Orientation", + inputs.create("format", "", "Format of the input lines or name of file containing format", "string"); inputs.create("append", "true", @@ -1125,10 +1124,15 @@ int main (int argc, char* argv[]) // Read format from file. format = readFormat (format.substr(st), in); } + // Use default if empty format. + if (format.empty()) { + cerr << "No format string found; using default format" << endl; + format = "Name,Type,Ra,Dec,I,Q,U,V,MajorAxis,MinorAxis,Orientation"; + } make (in, out, format, append, check, getSearchInfo (center, radius, width)); } catch (Exception& x) { - std::cerr << "Caught LOFAR exception: " << x << std::endl; + cerr << "Caught LOFAR exception: " << x << endl; return 1; } diff --git a/LCS/ApplCommon/include/ApplCommon/Observation.h b/LCS/ApplCommon/include/ApplCommon/Observation.h index 59aed628f08f85771e8c7888dfc393e7aaeca72d..aa3161f8195d892b2d32af646680557a2a4f4554 100644 --- a/LCS/ApplCommon/include/ApplCommon/Observation.h +++ b/LCS/ApplCommon/include/ApplCommon/Observation.h @@ -66,8 +66,6 @@ public: // Returns a bitset containing the RCU's requested by the observation. bitset<MAX_RCUS> getRCUbitset(int nrLBAs, int nrHBAs, const string& anAntennaSet); - // TEMP HACK - string getAntennaArrayName(bool hasSplitters) const; // Support for dynamic dataslot allocation vector<int> getBeamAllocation(const string& stationName = "") const; @@ -76,6 +74,9 @@ public: // for operator << ostream& print (ostream& os) const; + // TEMP HACK + string getAntennaFieldName(bool hasSplitters, uint32 beamIdx = 0) const; + // data types typedef bitset<MAX_RCUS> RCUset_t; diff --git a/LCS/ApplCommon/src/Observation.cc b/LCS/ApplCommon/src/Observation.cc index 482c576d283fea238a75a6b4e853c43cb07d02ff..527ca5649449fce84b721d765e41d083e0552ba8 100644 --- a/LCS/ApplCommon/src/Observation.cc +++ b/LCS/ApplCommon/src/Observation.cc @@ -144,7 +144,8 @@ Observation::Observation(const ParameterSet* aParSet, } // determine if DataslotLists are available in this parset - itsHasDataslots = aParSet->isDefined(prefix+str(format("Dataslots.%s%s.DataslotList") % stations[0] % antennaArray)); + LOG_DEBUG_STR(str(format("Dataslots.%s%s.DataslotList") % stations[0] % getAntennaFieldName(itsStnHasDualHBA))); + itsHasDataslots = aParSet->isDefined(prefix+str(format("Dataslots.%s%s.DataslotList") % stations[0] % getAntennaFieldName(itsStnHasDualHBA))); if (itsHasDataslots) { itsDataslotParset = aParSet->makeSubset(prefix+"Dataslots."); // save subset for later } @@ -232,9 +233,11 @@ Observation::Observation(const ParameterSet* aParSet, } // finally update vector with beamnumbers - int nrBeamlets = newBeam.subbands.size(); + int nrSubbands = newBeam.subbands.size(); if (!itsHasDataslots) { // old situation BeamBeamlets = aParSet->getInt32Vector(beamPrefix+"beamletList", vector<int32>(), true); // true:expandable + int nrBeamlets = BeamBeamlets.size(); + ASSERTSTR(nrBeamlets == nrSubbands, "Number of beamlets(" << nrBeamlets << ") != nr of subbands(" << nrSubbands << ") for Beam " << beamIdx); for (int i = 0; i < nrBeamlets; ++i) { if (beamlet2beams[BeamBeamlets[i]] != -1) { stringstream os; @@ -246,7 +249,7 @@ Observation::Observation(const ParameterSet* aParSet, } // for all beamlets } else { // new situation - for (int i = 0; i < nrBeamlets; ++i) { + for (int i = 0; i < nrSubbands; ++i) { // Note nrBeamlets=nrSubbands itsBeamSlotList.push_back(beamIdx); } } // itsHasDataslots @@ -500,13 +503,15 @@ vector<int> Observation::getBeamAllocation(const string& stationName) const } } // is DSL for this station available? - if (!itsDataslotParset.isDefined(str(format("%s%s.DataslotList") % station % antennaArray)) || - !itsDataslotParset.isDefined(str(format("%s%s.RSPBoardList") % station % antennaArray))) { + string fieldName = getAntennaFieldName(itsStnHasDualHBA); + string dsl(str(format("%s%s.DataslotList") % station % fieldName)); + string rbl(str(format("%s%s.RSPBoardList") % station % fieldName)); + if (!itsDataslotParset.isDefined(dsl) || !itsDataslotParset.isDefined(rbl)) { LOG_ERROR_STR("No dataslots defined for " << station << antennaArray); return (b2b); } - vector<int> RSPboardList = itsDataslotParset.getIntVector(str(format("%s%s.RSPBoardList") % station % antennaArray),true); - vector<int> DataslotList = itsDataslotParset.getIntVector(str(format("%s%s.DataslotList") % station % antennaArray),true); + vector<int> RSPboardList = itsDataslotParset.getIntVector(rbl,true); + vector<int> DataslotList = itsDataslotParset.getIntVector(dsl,true); ASSERTSTR (RSPboardList.size() == DataslotList.size(), "RSPBoardlist (" << RSPboardList << ") differs size of DataslotList(" << DataslotList << ") for station " << station); @@ -536,8 +541,10 @@ vector<int> Observation::getBeamAllocation(const string& stationName) const vector<int> Observation::getBeamlets (uint beamIdx, const string& stationName) const { uint parsetIdx = (dualMode && itsStnHasDualHBA) ? beamIdx/2 : beamIdx; + string fieldName = getAntennaFieldName(itsStnHasDualHBA, beamIdx); if (!itsHasDataslots) { + // both fields use the same beamlet mapping return (itsDataslotParset.getInt32Vector(str(format("Beam[%d].beamletList") % parsetIdx), vector<int32>(), true)); // true:expandable } @@ -552,14 +559,15 @@ vector<int> Observation::getBeamlets (uint beamIdx, const string& stationName) c } // is DSL for this station available? + // both fields have their own beamlet mapping + string dsl(str(format("%s%s.DataslotList") % station % fieldName)); + string rbl(str(format("%s%s.RSPBoardList") % station % fieldName)); vector<int> result; - if (!itsDataslotParset.isDefined(str(format("%s%s.DataslotList") % station % antennaArray)) || - !itsDataslotParset.isDefined(str(format("%s%s.RSPBoardList") % station % antennaArray))) { + if (!itsDataslotParset.isDefined(dsl) || !itsDataslotParset.isDefined(rbl)) { return (result); } - vector<int> RSPboardList = itsDataslotParset.getIntVector(str(format("%s%s.RSPBoardList") % station % antennaArray),true); - vector<int> DataslotList = itsDataslotParset.getIntVector(str(format("%s%s.DataslotList") % station % antennaArray),true); - + vector<int> RSPboardList = itsDataslotParset.getIntVector(rbl,true); + vector<int> DataslotList = itsDataslotParset.getIntVector(dsl,true); uint nrEntries = itsBeamSlotList.size(); for (uint i = 0; i < nrEntries; ++i) { if (itsBeamSlotList[i] == parsetIdx) { @@ -571,9 +579,11 @@ vector<int> Observation::getBeamlets (uint beamIdx, const string& stationName) c // -// TEMP HACK TO GET THE ANTENNAARRAYNAME +// TEMP HACK TO GET THE ANTENNAFIELDNAME +// +// Except for the beamIdx dependancy we should look in the antennaSet file. // -string Observation::getAntennaArrayName(bool hasSplitters) const +string Observation::getAntennaFieldName(bool hasSplitters, uint32 beamIdx) const { string result; if (antennaSet.empty()) { @@ -595,6 +605,7 @@ string Observation::getAntennaArrayName(bool hasSplitters) const if (result == "HBA_ZERO") return ("HBA0"); if (result == "HBA_ONE") return ("HBA1"); if (result == "HBA_JOINED") return ("HBA"); + if (result == "HBA_DUAL") return (beamIdx % 2 == 0 ? "HBA0" : "HBA1"); return ("HBA"); } diff --git a/LCS/ApplCommon/test/tObservation.cc b/LCS/ApplCommon/test/tObservation.cc index 3a6bea348e6a6ed3ae8e9b0322d8e75188216716..17c3a22ab7ded5c125d4846a6c1c01507f06829d 100644 --- a/LCS/ApplCommon/test/tObservation.cc +++ b/LCS/ApplCommon/test/tObservation.cc @@ -45,8 +45,8 @@ int main (int argc, char* argv[]) cout << "getRCUbitset(96,96,LBA_XXX) = " << someObs.getRCUbitset(96,96,"LBA_XXX") << endl; // Core cout << "getRCUbitset(96,48,HBA_XXX) = " << someObs.getRCUbitset(96,48,"HBA_XXX") << endl; // Core cout << "getRCUbitset(96,96,HBA_XXX) = " << someObs.getRCUbitset(96,96,"HBA_XXX") << endl; // Core - vector<int> b2b = someObs.getBeamAllocation("RS005"); - cout << "BeamAlloc for RS005 : " << b2b << endl; + vector<int> b2b = someObs.getBeamAllocation("CS002"); + cout << "BeamAlloc for CS002 : " << b2b << endl; return (0); } @@ -119,27 +119,27 @@ int main (int argc, char* argv[]) // test translation of antennaSetname obs3.antennaSet = "HBA_ZERO"; - cout << "HBA_ZERO(false) = " << obs3.getAntennaArrayName(false) << endl; - cout << "HBA_ZERO(true) = " << obs3.getAntennaArrayName(true) << endl; + cout << "HBA_ZERO(false) = " << obs3.getAntennaFieldName(false) << endl; + cout << "HBA_ZERO(true) = " << obs3.getAntennaFieldName(true) << endl; obs3.antennaSet = "HBA_ONE"; - cout << "HBA_ONE(false) = " << obs3.getAntennaArrayName(false) << endl; - cout << "HBA_ONE(true) = " << obs3.getAntennaArrayName(true) << endl; + cout << "HBA_ONE(false) = " << obs3.getAntennaFieldName(false) << endl; + cout << "HBA_ONE(true) = " << obs3.getAntennaFieldName(true) << endl; obs3.antennaSet = "HBA_DUAL"; - cout << "HBA_DUAL(false) = " << obs3.getAntennaArrayName(false) << endl; - cout << "HBA_DUAL(true) = " << obs3.getAntennaArrayName(true) << endl; + cout << "HBA_DUAL(false) = " << obs3.getAntennaFieldName(false) << endl; + cout << "HBA_DUAL(true) = " << obs3.getAntennaFieldName(true) << endl; obs3.antennaSet = "HBA_JOINED"; - cout << "HBA_JOINED(false) = " << obs3.getAntennaArrayName(false) << endl; - cout << "HBA_JOINED(true) = " << obs3.getAntennaArrayName(true) << endl; + cout << "HBA_JOINED(false) = " << obs3.getAntennaFieldName(false) << endl; + cout << "HBA_JOINED(true) = " << obs3.getAntennaFieldName(true) << endl; obs3.antennaSet = "LBA_INNER"; - cout << "LBA_INNER(false) = " << obs3.getAntennaArrayName(false) << endl; - cout << "LBA_INNER(true) = " << obs3.getAntennaArrayName(true) << endl; + cout << "LBA_INNER(false) = " << obs3.getAntennaFieldName(false) << endl; + cout << "LBA_INNER(true) = " << obs3.getAntennaFieldName(true) << endl; obs3.antennaSet = "LBA_OUTER"; - cout << "LBA_OUTER(false) = " << obs3.getAntennaArrayName(false) << endl; - cout << "LBA_OUTER(true) = " << obs3.getAntennaArrayName(true) << endl; + cout << "LBA_OUTER(false) = " << obs3.getAntennaFieldName(false) << endl; + cout << "LBA_OUTER(true) = " << obs3.getAntennaFieldName(true) << endl; obs3.antennaSet = "LBA_X"; - cout << "LBA_X(false) = " << obs3.getAntennaArrayName(false) << endl; - cout << "LBA_X(true) = " << obs3.getAntennaArrayName(true) << endl; + cout << "LBA_X(false) = " << obs3.getAntennaFieldName(false) << endl; + cout << "LBA_X(true) = " << obs3.getAntennaFieldName(true) << endl; // test old syntax agains new syntax cout << ">>>" << endl; diff --git a/LCS/ApplCommon/test/tObservation.in_newParset b/LCS/ApplCommon/test/tObservation.in_newParset index 3da73e1b91c1688becdae98a717cf37f1f80f154..6965201eb8a21111f20d0e47516387276c58c303 100644 --- a/LCS/ApplCommon/test/tObservation.in_newParset +++ b/LCS/ApplCommon/test/tObservation.in_newParset @@ -30,12 +30,18 @@ ObsSW.Observation.VirtualInstrument.partitionList=[R001_128_0,R001_128_1,R001_12 ObsSW.Observation.VirtualInstrument.stationList=[CS001,RS005,CS004] ObsSW.Observation.VirtualInstrument.storageCapacity=760 ObsSW.Observation.VirtualInstrument.storageNodeList=[list001,list002] -ObsSW.Observation.Dataslots.CS001HBA.DataslotList=[45..47,0..11] -ObsSW.Observation.Dataslots.CS001HBA.RSPBoardList=[3*0,12*1] -ObsSW.Observation.Dataslots.RS005HBA.DataslotList=[0..3,45..47,0..7] -ObsSW.Observation.Dataslots.RS005HBA.RSPBoardList=[7*0,8*1] -ObsSW.Observation.Dataslots.CS004HBA.DataslotList=[0..14] -ObsSW.Observation.Dataslots.CS004HBA.RSPBoardList=[15*0] +ObsSW.Observation.Dataslots.CS001HBA0.DataslotList=[45..47,0..11] +ObsSW.Observation.Dataslots.CS001HBA0.RSPBoardList=[3*0,12*1] +ObsSW.Observation.Dataslots.CS001HBA1.DataslotList=[45..47,0..11] +ObsSW.Observation.Dataslots.CS001HBA1.RSPBoardList=[3*0,12*1] +ObsSW.Observation.Dataslots.RS005HBA0.DataslotList=[0..3,45..47,0..7] +ObsSW.Observation.Dataslots.RS005HBA0.RSPBoardList=[7*0,8*1] +ObsSW.Observation.Dataslots.RS005HBA1.DataslotList=[0..3,45..47,0..7] +ObsSW.Observation.Dataslots.RS005HBA1.RSPBoardList=[7*0,8*1] +ObsSW.Observation.Dataslots.CS004HBA0.DataslotList=[0..14] +ObsSW.Observation.Dataslots.CS004HBA0.RSPBoardList=[15*0] +ObsSW.Observation.Dataslots.CS004HBA1.DataslotList=[0..14] +ObsSW.Observation.Dataslots.CS004HBA1.RSPBoardList=[15*0] ObsSW.Observation.antennaArray=HBA ObsSW.Observation.antennaSet=HBA_DUAL ObsSW.Observation.bandFilter=HBA_210_250 diff --git a/LCS/ApplCommon/test/tObservation.stdout b/LCS/ApplCommon/test/tObservation.stdout index 7985247fbd4e1772c92e55e202d2ee72ffcae24c..dfd78a1103e353cc59f960eeb7cb71cf1f62d782 100644 --- a/LCS/ApplCommon/test/tObservation.stdout +++ b/LCS/ApplCommon/test/tObservation.stdout @@ -1,4 +1,5 @@ >>> +DEBUG LCS.ApplCommon - Dataslots.CS016HBA.DataslotList Observation : ObsID : 5025 @@ -35,6 +36,7 @@ Beam[0].TAB[1]: 5.990000, 0.490000, J2000, 20.000000, incoherent beamlet2beams : [0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,999,999,999,999,999,999,999,999,999,999,999,999,999,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,999,999,999,999,999,999,999,999,999,999,999,999,999,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,999,999,999,999,999,999,999,999,999,999,999,999,999,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,999,999,999,999,999,999,999,999,999,999,999,999,999] nrAnaBeams : 0 +DEBUG LCS.ApplCommon - Dataslots.CS016HBA.DataslotList Observation : ObsID : 5025 @@ -72,6 +74,7 @@ beamlet2beams : [0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 nrAnaBeams : 0 <<< +DEBUG LCS.ApplCommon - Dataslots.CS016HBA.DataslotList Observation : ObsID : 5025 @@ -119,15 +122,22 @@ TABringsize : 0 beamlet2beams : [0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,-1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,999,999,999,999,999,999,999,999,999,999,999,999,999,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,999,999,999,999,999,999,999,999,999,999,999,999,999,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,999,999,999,999,999,999,999,999,999,999,999,999,999,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,999,999,999,999,999,999,999,999,999,999,999,999,999] nrAnaBeams : 0 +DEBUG LCS.ApplCommon - Dataslots.CS016HBA.DataslotList >>> +DEBUG LCS.ApplCommon - Dataslots.CS016HBA.DataslotList INFO LCS.ApplCommon - Clock of observation 5025 and 5026 conflict +DEBUG LCS.ApplCommon - Dataslots.CS016HBA.DataslotList INFO LCS.ApplCommon - Conflicting use of receivers between observation 5025 and 5027 DEBUG LCS.ApplCommon - receiverConflict: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111100000000 +DEBUG LCS.ApplCommon - Dataslots.CS016HBA.DataslotList INFO LCS.ApplCommon - Conflict in beamlets between observation 5025 and 5028 DEBUG LCS.ApplCommon - First conflicting beamlet: 2 +DEBUG LCS.ApplCommon - Dataslots.CS016HBA.DataslotList INFO LCS.ApplCommon - Conflict in nrSlotsInFrame: 48<->54 for resp. observation 5025 and 5029 +DEBUG LCS.ApplCommon - Dataslots.CS016HBA.DataslotList <<< No conflict found in file 5 which is oke. +DEBUG LCS.ApplCommon - Dataslots.CS016HBA.DataslotList getRCUbitset(96,48,'') = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111 getRCUbitset(96,96,'') = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111 getRCUbitset(96,48,LBA_XXX) = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111 @@ -139,7 +149,7 @@ HBA_ZERO(true) = HBA0 HBA_ONE(false) = HBA HBA_ONE(true) = HBA1 HBA_DUAL(false) = HBA -HBA_DUAL(true) = HBA +HBA_DUAL(true) = HBA0 HBA_JOINED(false) = HBA HBA_JOINED(true) = HBA LBA_INNER(false) = LBA @@ -149,6 +159,7 @@ LBA_OUTER(true) = LBA LBA_X(false) = LBA LBA_X(true) = LBA >>> +DEBUG LCS.ApplCommon - Dataslots.CS001HBA0.DataslotList OLD SYNTAX Observation : @@ -164,8 +175,6 @@ filter : HBA_210_250 splitter : ON nyquistZone : 3 -Meas.set : - (Receivers) : [0..11] Stations : [CS001,RS005,CS004] BLG nodes : [bgl001..bgl003] @@ -173,36 +182,53 @@ Storage nodes: [list001,list002] nrBeams : 4 Beam[0].name : observation[5025]beam[0]_0 +Beam[0].target : Beam[0].antennaSet : HBA_ZERO Beam[0].momID : 0 Beam[0].subbandList: [2,3,4,5] Beam[0].beamletList: [0,1,2,3] nrPointings : 1 Beam[0].pointing[0]: 6.000000, 0.500000, J2000, 2008-Dec-16 15:30:00 +nrTABs : 0 +nrTABrings : 0 +TABringsize : 0 Beam[1].name : observation[5025]beam[0]_1 +Beam[1].target : Beam[1].antennaSet : HBA_ONE Beam[1].momID : 0 Beam[1].subbandList: [2,3,4,5] Beam[1].beamletList: [0,1,2,3] nrPointings : 1 Beam[1].pointing[0]: 6.000000, 0.500000, J2000, 2008-Dec-16 15:30:00 +nrTABs : 0 +nrTABrings : 0 +TABringsize : 0 Beam[2].name : observation[5025]beam[1]_0 +Beam[2].target : Beam[2].antennaSet : HBA_ZERO Beam[2].momID : 0 Beam[2].subbandList: [20,21,22,23,24,25,40,41,42,43,44] Beam[2].beamletList: [45,46,47,61,62,63,64,65,66,67,68] nrPointings : 1 Beam[2].pointing[0]: 1.000000, 1.500000, J2000, 2008-Dec-16 15:30:00 +nrTABs : 0 +nrTABrings : 0 +TABringsize : 0 Beam[3].name : observation[5025]beam[1]_1 +Beam[3].target : Beam[3].antennaSet : HBA_ONE Beam[3].momID : 0 Beam[3].subbandList: [20,21,22,23,24,25,40,41,42,43,44] Beam[3].beamletList: [45,46,47,61,62,63,64,65,66,67,68] nrPointings : 1 Beam[3].pointing[0]: 1.000000, 1.500000, J2000, 2008-Dec-16 15:30:00 +nrTABs : 0 +nrTABrings : 0 +TABringsize : 0 beamlet2beams : [0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,1,999,999,999,999,999,999,999,999,999,999,999,999,999,1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,999,999,999,999,999,999,999,999,999,999,999,999,999,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,999,999,999,999,999,999,999,999,999,999,999,999,999,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,999,999,999,999,999,999,999,999,999,999,999,999,999] nrAnaBeams : 0 +DEBUG LCS.ApplCommon - Dataslots.CS001HBA0.DataslotList NEW SYNTAX Observation : @@ -218,8 +244,6 @@ filter : HBA_210_250 splitter : ON nyquistZone : 3 -Meas.set : - (Receivers) : [0..11] Stations : [CS001,RS005,CS004] BLG nodes : [bgl001..bgl003] @@ -227,33 +251,49 @@ Storage nodes: [list001,list002] nrBeams : 4 Beam[0].name : observation[5025]beam[0]_0 +Beam[0].target : Beam[0].antennaSet : HBA_ZERO Beam[0].momID : 0 Beam[0].subbandList: [2,3,4,5] Beam[0].beamletList: [0,1,2,3] nrPointings : 1 Beam[0].pointing[0]: 6.000000, 0.500000, J2000, 2008-Dec-16 15:30:00 +nrTABs : 0 +nrTABrings : 0 +TABringsize : 0 Beam[1].name : observation[5025]beam[0]_1 +Beam[1].target : Beam[1].antennaSet : HBA_ONE Beam[1].momID : 0 Beam[1].subbandList: [2,3,4,5] Beam[1].beamletList: [0,1,2,3] nrPointings : 1 Beam[1].pointing[0]: 6.000000, 0.500000, J2000, 2008-Dec-16 15:30:00 +nrTABs : 0 +nrTABrings : 0 +TABringsize : 0 Beam[2].name : observation[5025]beam[1]_0 +Beam[2].target : Beam[2].antennaSet : HBA_ZERO Beam[2].momID : 0 Beam[2].subbandList: [20,21,22,23,24,25,40,41,42,43,44] Beam[2].beamletList: [45,46,47,61,62,63,64,65,66,67,68] nrPointings : 1 Beam[2].pointing[0]: 1.000000, 1.500000, J2000, 2008-Dec-16 15:30:00 +nrTABs : 0 +nrTABrings : 0 +TABringsize : 0 Beam[3].name : observation[5025]beam[1]_1 +Beam[3].target : Beam[3].antennaSet : HBA_ONE Beam[3].momID : 0 Beam[3].subbandList: [20,21,22,23,24,25,40,41,42,43,44] Beam[3].beamletList: [45,46,47,61,62,63,64,65,66,67,68] nrPointings : 1 Beam[3].pointing[0]: 1.000000, 1.500000, J2000, 2008-Dec-16 15:30:00 +nrTABs : 0 +nrTABrings : 0 +TABringsize : 0 beamlet2beams : [0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,1,999,999,999,999,999,999,999,999,999,999,999,999,999,1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,999,999,999,999,999,999,999,999,999,999,999,999,999,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,999,999,999,999,999,999,999,999,999,999,999,999,999,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,999,999,999,999,999,999,999,999,999,999,999,999,999] nrAnaBeams : 0 diff --git a/MAC/Deployment/data/OTDB/OLAP.comp b/MAC/Deployment/data/OTDB/OLAP.comp index 0579289d0ee73cfaf329df5a84c6b52103612c0b..0098827a6e8b8fe12f6efef99a8a6e81e8c8a08b 100644 --- a/MAC/Deployment/data/OTDB/OLAP.comp +++ b/MAC/Deployment/data/OTDB/OLAP.comp @@ -30,7 +30,7 @@ node CNProc_CoherentStokes 4.0.0 development 'node constraint' "Coherent par which I ptext - 10 0 "I|IQUV|XXYY;I" - "Which Stokes values to compute" par channelsPerSubband I int - 10 0 ">>Observation.channelsPerSubband" - "Number of channels for Stokes data" par timeIntegrationFactor I int - 10 0 1 - "Time-wise integration of Stokes data (in samples)" -par subbandsPerFile I int - 10 0 1 - "the number of subbands each Stokes file will hold" +par subbandsPerFile I int - 10 0 512 - "the number of subbands each Stokes file will hold" # -- CNProc_IncoherentStokes -- # @@ -43,7 +43,7 @@ node CNProc_IncoherentStokes 4.0.0 development 'node constraint' "Incohere par which I ptext - 10 0 "I|IQUV;I" - "Which Stokes values to compute" par channelsPerSubband I int - 10 0 ">>Observation.channelsPerSubband" - "Number of channels for Stokes data" par timeIntegrationFactor I int - 10 0 1 - "Time-wise integration of Stokes data (in samples)" -par subbandsPerFile I int - 10 0 1 - "the number of subbands each Stokes file will hold" +par subbandsPerFile I int - 10 0 512 - "the number of subbands each Stokes file will hold" # -- OLAP_Conni --