From 124e3302028f0b0f6cbfd56a011d92c67d04564d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Offringa?= <offringa@astron.nl>
Date: Wed, 14 Mar 2012 10:41:00 +0000
Subject: [PATCH] Task #1892: Added a rudimentary zenith imager (not working
 yet)

---
 .gitattributes                                |   3 +
 .../include/AOFlagger/imaging/zenithimager.h  |  56 ++++++
 .../include/AOFlagger/msio/antennainfo.h      |  19 +-
 .../include/AOFlagger/msio/measurementset.h   |   3 +-
 CEP/DP3/AOFlagger/src/CMakeLists.txt          |   1 +
 .../AOFlagger/src/imaging/zenithimager.cpp    | 120 ++++++++++++
 CEP/DP3/AOFlagger/src/imgzenith.cpp           | 173 ++++++++++++++++++
 CEP/DP3/AOFlagger/src/msinfo.cpp              |   2 +-
 CEP/DP3/AOFlagger/src/msio/measurementset.cpp |   4 +-
 9 files changed, 375 insertions(+), 6 deletions(-)
 create mode 100644 CEP/DP3/AOFlagger/include/AOFlagger/imaging/zenithimager.h
 create mode 100644 CEP/DP3/AOFlagger/src/imaging/zenithimager.cpp
 create mode 100644 CEP/DP3/AOFlagger/src/imgzenith.cpp

diff --git a/.gitattributes b/.gitattributes
index 73df04b9d8b..ca09c7cf98c 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -317,6 +317,7 @@ CEP/DP3/AOFlagger/include/AOFlagger/imaging/fourproductcorrelatortester.h -text
 CEP/DP3/AOFlagger/include/AOFlagger/imaging/model.h -text
 CEP/DP3/AOFlagger/include/AOFlagger/imaging/observatorium.h -text
 CEP/DP3/AOFlagger/include/AOFlagger/imaging/uvimager.h -text
+CEP/DP3/AOFlagger/include/AOFlagger/imaging/zenithimager.h -text
 CEP/DP3/AOFlagger/include/AOFlagger/msio/antennainfo.h -text
 CEP/DP3/AOFlagger/include/AOFlagger/msio/arraycolumniterator.h -text
 CEP/DP3/AOFlagger/include/AOFlagger/msio/baselinematrixloader.h -text
@@ -592,6 +593,8 @@ CEP/DP3/AOFlagger/src/gui/tfstatoptionwindow.cpp -text
 CEP/DP3/AOFlagger/src/imaging/fourproductcorrelatortester.cpp -text
 CEP/DP3/AOFlagger/src/imaging/model.cpp -text
 CEP/DP3/AOFlagger/src/imaging/uvimager.cpp -text
+CEP/DP3/AOFlagger/src/imaging/zenithimager.cpp -text
+CEP/DP3/AOFlagger/src/imgzenith.cpp -text
 CEP/DP3/AOFlagger/src/ms2uv.cpp -text
 CEP/DP3/AOFlagger/src/msinfo.cpp -text
 CEP/DP3/AOFlagger/src/msio/baselinematrixloader.cpp -text
diff --git a/CEP/DP3/AOFlagger/include/AOFlagger/imaging/zenithimager.h b/CEP/DP3/AOFlagger/include/AOFlagger/imaging/zenithimager.h
new file mode 100644
index 00000000000..d42e59bfa02
--- /dev/null
+++ b/CEP/DP3/AOFlagger/include/AOFlagger/imaging/zenithimager.h
@@ -0,0 +1,56 @@
+/***************************************************************************
+ *   Copyright (C) 2012 by A.R. Offringa                                   *
+ *   offringa@astro.rug.nl                                                 *
+ *                                                                         *
+ *   This program 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 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program 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 this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef ZENITH_IMAGER_H
+#define ZENITH_IMAGER_H
+
+#include <complex>
+
+#include <AOFlagger/msio/image2d.h>
+
+class ZenithImager
+{
+	public:
+		ZenithImager();
+		
+		void Initialize(size_t resolution);
+		
+		void Clear();
+		
+		void Add(const class BandInfo &band, const std::complex<float> *samples, const bool *isRFI, double u, double v, double w, double phaseRotation);
+		
+		void FourierTransform(Image2DPtr &real, Image2DPtr &imaginary);
+		
+		Image2DCPtr UVReal() const { return _real; }
+		Image2DCPtr UVImaginary() const { return _imaginary; }
+	private:
+		void add(const class BandInfo &band, double r, double i, double u, double v, double w, double phaseRotation, double wavelength);
+		
+		static long double Wavelength(long double frequency)
+		{
+			return 299792458.0L / frequency;
+		}
+		
+		size_t _resolution, _totalCount, _outsideCount;
+		
+		Image2DPtr _real, _imaginary, _weights;
+};
+
+#endif
diff --git a/CEP/DP3/AOFlagger/include/AOFlagger/msio/antennainfo.h b/CEP/DP3/AOFlagger/include/AOFlagger/msio/antennainfo.h
index 9baf25ee4c2..c021bc987d9 100644
--- a/CEP/DP3/AOFlagger/include/AOFlagger/msio/antennainfo.h
+++ b/CEP/DP3/AOFlagger/include/AOFlagger/msio/antennainfo.h
@@ -41,7 +41,7 @@ struct EarthPosition : public Serializable {
 		s.width(16);
 		s.precision(16);
 		s << x << "," << y << "," << z << " (alt " << sqrtl(x*x+y*y+z*z) << "), or "
-		<< "N" << Lattitude()*180/M_PI << " E" << Longitude()*180/M_PI;
+		<< "N" << Latitude()*180/M_PI << " E" << Longitude()*180/M_PI;
 		return s.str();
 	}
 	EarthPosition FromITRS(long double x, long double y, long double z);
@@ -50,8 +50,18 @@ struct EarthPosition : public Serializable {
 	{
 		return atan2l(y, x);
 	}
+	
+	long double LongitudeL() const
+	{
+		return atan2l(y, x);
+	}
 
-	double Lattitude() const
+	double Latitude() const
+	{
+		return atan2l(z, sqrtl((long double) x*x + y*y));
+	}
+	
+	long double LatitudeL() const
 	{
 		return atan2l(z, sqrtl((long double) x*x + y*y));
 	}
@@ -60,6 +70,11 @@ struct EarthPosition : public Serializable {
 	{
 		return sqrtl((long double) x*x+y*y+z*z);
 	}
+	
+	double AltitudeL() const
+	{
+		return sqrtl((long double) x*x+y*y+z*z);
+	}
 
 	virtual void Serialize(std::ostream &stream) const
 	{
diff --git a/CEP/DP3/AOFlagger/include/AOFlagger/msio/measurementset.h b/CEP/DP3/AOFlagger/include/AOFlagger/msio/measurementset.h
index 11d4c3a9881..9921e349e86 100644
--- a/CEP/DP3/AOFlagger/include/AOFlagger/msio/measurementset.h
+++ b/CEP/DP3/AOFlagger/include/AOFlagger/msio/measurementset.h
@@ -126,11 +126,12 @@ class MeasurementSet {
 		}
 		size_t GetPolarizationCount();
 		static size_t GetPolarizationCount(const std::string &filename);
+		static struct BandInfo GetBandInfo(const std::string &filename, unsigned bandIndex);
 		size_t AntennaCount();
 		size_t FieldCount();
 		size_t BandCount();
 		struct AntennaInfo GetAntennaInfo(unsigned antennaId);
-		struct BandInfo GetBandInfo(unsigned bandIndex);
+		struct BandInfo GetBandInfo(unsigned bandIndex) {return GetBandInfo(_location, bandIndex);}
 		struct FieldInfo GetFieldInfo(unsigned fieldIndex);
 		void DataMerge(const MeasurementSet &source);
 		std::string Location() const throw() { return _location; }
diff --git a/CEP/DP3/AOFlagger/src/CMakeLists.txt b/CEP/DP3/AOFlagger/src/CMakeLists.txt
index 74c6960061c..c85b2fd76b1 100644
--- a/CEP/DP3/AOFlagger/src/CMakeLists.txt
+++ b/CEP/DP3/AOFlagger/src/CMakeLists.txt
@@ -248,6 +248,7 @@ lofar_add_bin_program(msinfo msinfo.cpp)
 lofar_add_bin_program(ns2bbs ns2bbs.cpp)
 lofar_add_bin_program(colormapper colormapper.cpp)
 lofar_add_bin_program(versionaoflagger versionaoflagger.cc Package__Version.cc)
+lofar_add_bin_program(imgzenith imgzenith.cpp imaging/zenithimager.cpp)
 
 if(BOOST_ASIO_H_FOUND AND SIGCXX_FOUND)
   lofar_add_bin_program(aoquality aoquality.cpp ${REMOTE_FILES})
diff --git a/CEP/DP3/AOFlagger/src/imaging/zenithimager.cpp b/CEP/DP3/AOFlagger/src/imaging/zenithimager.cpp
new file mode 100644
index 00000000000..7ca135d2530
--- /dev/null
+++ b/CEP/DP3/AOFlagger/src/imaging/zenithimager.cpp
@@ -0,0 +1,120 @@
+/***************************************************************************
+ *   Copyright (C) 2012 by A.R. Offringa                                   *
+ *   offringa@astro.rug.nl                                                 *
+ *                                                                         *
+ *   This program 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 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program 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 this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#include <AOFlagger/imaging/zenithimager.h>
+
+#include <AOFlagger/msio/antennainfo.h>
+
+#include <AOFlagger/util/ffttools.h>
+
+ZenithImager::ZenithImager() : _resolution(0), _totalCount(0), _outsideCount(0)
+{
+}
+
+void ZenithImager::Initialize(size_t resolution)
+{
+	_resolution = resolution;
+	_real = Image2D::CreateZeroImagePtr(resolution, resolution);
+	_imaginary = Image2D::CreateZeroImagePtr(resolution, resolution);
+	_weights = Image2D::CreateZeroImagePtr(resolution, resolution);
+}
+
+void ZenithImager::Clear()
+{
+	_real->SetAll(0.0);
+	_imaginary->SetAll(0.0);
+	_weights->SetAll(0.0);
+	_totalCount = 0;
+	_outsideCount = 0;
+}
+
+void ZenithImager::Add(const BandInfo &band, const std::complex<float> *samples, const bool *isRFI, double u, double v, double w, double phaseRotation)
+{
+	size_t n = band.channelCount;
+	for(size_t f=0;f<n;++f)
+	{
+		if(!isRFI[f])
+		{
+			const double wavelength = Wavelength(band.channels[f].frequencyHz);
+			const double r = samples[f].real(), i = samples[f].imag();
+			add(band, r, i, u, v, w, phaseRotation, wavelength);
+		}
+	}
+}
+
+void ZenithImager::add(const BandInfo &band, double r, double i, double u, double v, double w, double phaseRotation, double wavelength)
+{
+	const double factor = 1.0 / wavelength;
+	u *= factor;
+	v *= factor;
+	//w *= factor;
+	phaseRotation *= factor * 2 * M_PI;
+	
+	const double centre = (double) (_resolution + 1.0) * 0.5;
+	
+	int uPos = (int) round(u + centre);
+	int vPos = (int) round(v + centre);
+	
+	if(uPos >= 0 && vPos >= 0 && uPos < (int) _resolution && vPos < (int) _resolution)
+	{
+		const double sinR = sin(phaseRotation), cosR = cos(phaseRotation);
+		const double rotatedR = r * cosR - i * sinR;
+		const double rotatedI = r * sinR + i * cosR;
+		
+		_real->AddValue(uPos, vPos, rotatedR);
+		_imaginary->AddValue(uPos, vPos, rotatedI);
+		_weights->AddValue(uPos, vPos, 1.0);
+		
+		int uPos2 = (int) round(centre - u);
+		int vPos2 = (int) round(centre - v);
+		if(uPos2 >= 0 && vPos2 >= 0 && uPos2 < (int) _resolution && vPos2 < (int) _resolution)
+		{
+			_real->AddValue(uPos2, vPos2, rotatedR);
+			_imaginary->AddValue(uPos2, vPos2, -rotatedI);
+			_weights->AddValue(uPos2, vPos2, 1.0);
+		}
+	} else {
+		_outsideCount++;
+	}
+	
+	++_totalCount;
+}
+
+void ZenithImager::FourierTransform(Image2DPtr &real, Image2DPtr &imaginary)
+{
+	std::cout << "Performing FT of " << _totalCount << " samples, " << _outsideCount << " fell outside uv area... " << std::flush;
+	
+	double normFactor = _weights->Sum() / ((num_t) _real->Height() * _real->Width());
+	for(size_t y=0;y<_real->Height();++y) {
+		for(size_t x=0;x<_real->Width();++x) {
+			num_t weight = _weights->Value(x, y);
+			if(weight != 0.0)
+			{
+				_real->SetValue(x, y, _real->Value(x, y) * normFactor / weight);
+				_imaginary->SetValue(x, y, _imaginary->Value(x, y) * normFactor / weight);
+				_weights->SetValue(x, y, 1.0);
+			} 
+		}
+	}
+	
+	real = Image2D::CreateUnsetImagePtr(_resolution, _resolution);
+	imaginary = Image2D::CreateUnsetImagePtr(_resolution, _resolution);
+	FFTTools::CreateFFTImage(*_real, *_imaginary, *real, *imaginary);
+}
diff --git a/CEP/DP3/AOFlagger/src/imgzenith.cpp b/CEP/DP3/AOFlagger/src/imgzenith.cpp
new file mode 100644
index 00000000000..328018d4ca8
--- /dev/null
+++ b/CEP/DP3/AOFlagger/src/imgzenith.cpp
@@ -0,0 +1,173 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by A.R. Offringa                                   *
+ *   offringa@astro.rug.nl                                                 *
+ *                                                                         *
+ *   This program 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 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program 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 this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#include <tables/Tables/Table.h>
+
+#include <measures/Measures/UVWMachine.h>
+#include <measures/Measures/MEpoch.h>
+
+#include <ms/MeasurementSets/MeasurementSet.h>
+
+#include <AOFlagger/msio/antennainfo.h>
+#include <AOFlagger/msio/measurementset.h>
+
+#include <AOFlagger/imaging/zenithimager.h>
+#include <AOFlagger/msio/pngfile.h>
+
+const casa::Unit radUnit("rad");
+const casa::Unit dayUnit("d");
+
+void repoint(casa::MDirection &phaseDirection, casa::MPosition &position, const casa::MEpoch &obstime, double &u, double &v, double &w, double &phaseRotation)
+{
+	//MPosition location(MVPosition(Quantity(1, "km"), Quantity(150, "deg"), Quantity(20, "deg")), MPosition::WGS84);
+	
+	//casa::MEpoch obstime(casa::Quantity(t, dayUnit), casa::MEpoch::UTC);
+	//std::cout << "Time=" << obstime.getValue() << '\n';
+	
+	casa::MeasFrame timeAndLocation(obstime, position);
+	
+	casa::MDirection::Ref refApparent(casa::MDirection::APP, timeAndLocation);
+	
+	// Calculate zenith
+	casa::MDirection outDirection(casa::Quantity(M_PI, radUnit), casa::Quantity(0.0, radUnit), refApparent);
+	//std::cout << "Out=" << outDirection.getValue() << '\n';
+	
+	// Construct a CASA UVW converter
+	casa::UVWMachine uvwConverter(outDirection, phaseDirection);
+	casa::Vector<double> uvwVector(3);
+	uvwVector[0] = u;
+	uvwVector[1] = v;
+	uvwVector[2] = w;
+	//std::cout << "In: " << u << ',' << v << ',' << w << '\n';
+	//std::cout << "Phase shift: " << uvwConverter.getPhase(uvwVector) << '\n';
+	//uvwConverter.convertUVW(uvwVector); // getPhase already does that!
+	u = uvwVector[0];
+	v = uvwVector[1];
+	w = uvwVector[2];
+	//std::cout << "Out: " << u << ',' << v << ',' << w << '\n';
+	//std::cout << "Phase centre: " << uvwConverter.phaseCenter().getValue() << '\n';
+}
+
+int main(int argc, char *argv[])
+{
+	std::string filename(argv[1]);
+	size_t integrationSteps;
+	if(argc >= 3)
+		integrationSteps = atoi(argv[2]);
+	else
+		integrationSteps = 60;
+	
+	std::cout << "Opening " << filename << "...\n";
+	
+	const unsigned polarizationCount = MeasurementSet::GetPolarizationCount(filename);
+	const BandInfo band = MeasurementSet::GetBandInfo(filename, 0);
+	
+	const unsigned antennaIndex = 0;
+	
+	casa::MeasurementSet table(argv[1]);
+	casa::MEpoch::ROScalarColumn timeColumn(table, "TIME");
+	casa::ROArrayColumn<double> uvwColumn(table, "UVW");
+	casa::ROScalarColumn<int> ant1Column(table, "ANTENNA1");
+	casa::ROScalarColumn<int> ant2Column(table, "ANTENNA2");
+	casa::ROArrayColumn<casa::Complex> dataColumn(table, "DATA");
+	casa::ROArrayColumn<bool> flagColumn(table, "FLAG");
+	
+	casa::Table antennaTable(table.antenna());
+	casa::MPosition::ROScalarColumn antPositionColumn(antennaTable, "POSITION");
+	casa::ROScalarColumn<casa::String> antNameColumn(antennaTable, "NAME");
+	casa::MPosition position  = antPositionColumn(antennaIndex);
+	std::cout << "Imaging zenith of antenna " << antNameColumn(antennaIndex)
+		<< ", pos=" << position.getValue() << '\n';
+		
+	casa::Table fieldTable(table.field());
+	casa::MDirection::ROArrayColumn phaseDirColumn(fieldTable, "PHASE_DIR");
+	casa::MDirection phaseDirection = *phaseDirColumn(0).begin();
+	std::cout << "Phase direction: " << phaseDirection.getValue() << '\n';
+
+	std::complex<float> *samples[polarizationCount];
+	bool *isRFI[polarizationCount];
+	for(unsigned p = 0; p < polarizationCount; ++p)
+	{
+		isRFI[p] = new bool[band.channelCount];
+		samples[p] = new std::complex<float>[band.channelCount];
+	}
+
+	unsigned row = 0;
+	ZenithImager imager;
+	imager.Initialize(2048);
+	size_t timeStep = 0;
+	while(row<table.nrow())
+	{
+		const casa::MEpoch t = timeColumn(row);
+		do
+		{
+			if(ant1Column(row) != ant2Column(row))
+			{
+				casa::Array<double> uvw = uvwColumn(row);
+				casa::Array<double>::const_iterator uvw_i = uvw.begin();
+				double u = *uvw_i; ++uvw_i;
+				double v = *uvw_i; ++uvw_i;
+				double w = *uvw_i;
+				double phaseRotation;
+				repoint(phaseDirection, position, t, u, v, w, phaseRotation);
+				
+				const casa::Array<casa::Complex> dataArray = dataColumn(row);
+				const casa::Array<bool> flagArray = flagColumn(row);
+				
+				casa::Array<casa::Complex>::const_iterator dataIter = dataArray.begin();
+				casa::Array<bool>::const_iterator flagIter = flagArray.begin();
+				
+				for(unsigned channel = 0; channel<band.channelCount; ++channel)
+				{
+					for(unsigned p = 0; p < polarizationCount; ++p)
+					{
+						samples[p][channel] = *dataIter;
+						isRFI[p][channel] = *flagIter;
+						
+						++dataIter;
+						++flagIter;
+					}
+				}
+				
+				imager.Add(band, samples[0], isRFI[0], u, v, w, phaseRotation);
+			}
+			++row;
+		} while(row<table.nrow() && timeColumn(row).getValue() == t.getValue());
+		
+		timeStep++;
+		if(timeStep % integrationSteps == 0)
+		{
+			Image2DPtr real, imaginary;
+			imager.FourierTransform(real, imaginary);
+			
+			std::stringstream s;
+			if(timeStep < 10000) s << '0';
+			if(timeStep < 1000) s << '0';
+			if(timeStep < 100) s << '0';
+			if(timeStep < 10) s << '0';
+			s << timeStep << ".png";
+			std::cout << "Saving " << s.str() << "... " << std::flush;
+			PngFile::Save(*real, std::string("zen/") + s.str());
+			PngFile::Save(*imager.UVReal(), std::string("zen-uv/") + s.str());
+			imager.Clear();
+			std::cout << "Done.\n";
+		}
+	}
+}
diff --git a/CEP/DP3/AOFlagger/src/msinfo.cpp b/CEP/DP3/AOFlagger/src/msinfo.cpp
index b3160e59599..48f146d74d3 100644
--- a/CEP/DP3/AOFlagger/src/msinfo.cpp
+++ b/CEP/DP3/AOFlagger/src/msinfo.cpp
@@ -90,7 +90,7 @@ int main(int argc, char *argv[])
 			cout.width(16);
 			cout.precision(16);
 			const AntennaInfo antenna = set.GetAntennaInfo(i);
-			cout << antenna.id << '\t' << antenna.position.Lattitude()*180.0/M_PI << '\t' << antenna.position.Longitude()*180.0/M_PI << '\t' << antenna.position.Altitude() << '\n';
+			cout << antenna.id << '\t' << antenna.position.Latitude()*180.0/M_PI << '\t' << antenna.position.Longitude()*180.0/M_PI << '\t' << antenna.position.Altitude() << '\n';
 		}
 	}
 	else {
diff --git a/CEP/DP3/AOFlagger/src/msio/measurementset.cpp b/CEP/DP3/AOFlagger/src/msio/measurementset.cpp
index 747867dbeb1..88ccfaf3f80 100644
--- a/CEP/DP3/AOFlagger/src/msio/measurementset.cpp
+++ b/CEP/DP3/AOFlagger/src/msio/measurementset.cpp
@@ -198,10 +198,10 @@ struct AntennaInfo MeasurementSet::GetAntennaInfo(unsigned antennaId)
 	return info;
 }
 
-struct BandInfo MeasurementSet::GetBandInfo(unsigned bandIndex)
+BandInfo MeasurementSet::GetBandInfo(const std::string &filename, unsigned bandIndex)
 {
 	BandInfo band;
-	casa::MeasurementSet ms(_location);
+	casa::MeasurementSet ms(filename);
 	casa::Table spectralWindowTable = ms.spectralWindow();
 	casa::ROScalarColumn<int> numChanCol(spectralWindowTable, "NUM_CHAN");
 	casa::ROArrayColumn<double> frequencyCol(spectralWindowTable, "CHAN_FREQ");
-- 
GitLab