From 2c54a54135f0fe0141d62cbd79d0b0fecc584629 Mon Sep 17 00:00:00 2001
From: Maik Nijhuis <maik.nijhuis@triopsys.nl>
Date: Wed, 2 Nov 2022 12:46:01 +0000
Subject: [PATCH] AST-1086 Pass spectral window via DPInfo

---
 base/DPInfo.cc                                | 31 +++++++------
 base/test/unit/tDPInfo.cc                     | 28 ++++++------
 include/dp3/base/DPInfo.h                     | 28 ++++++------
 steps/BDAAverager.cc                          |  2 +-
 steps/BDAExpander.cc                          |  2 +-
 steps/BdaGroupPredict.cc                      |  4 +-
 steps/InputStep.cc                            |  4 --
 steps/InputStep.h                             |  3 --
 steps/MSBDAReader.cc                          | 12 +++---
 steps/MSBDAReader.h                           |  4 --
 steps/MSBDAWriter.cc                          |  5 +--
 steps/MSReader.cc                             | 43 ++++++++++---------
 steps/MSReader.h                              |  6 +--
 steps/MSWriter.cc                             | 40 ++++++++---------
 steps/MSWriter.h                              |  8 ++--
 steps/MultiMSReader.cc                        | 23 ++++------
 steps/MultiMSReader.h                         |  1 -
 .../test/tDynamicTestStep.cc                  |  4 +-
 steps/test/unit/tAOFlaggerStep.cc             |  2 +-
 steps/test/unit/tApplyCal.cc                  |  2 +-
 steps/test/unit/tApplyCalH5.cc                |  2 +-
 steps/test/unit/tAverager.cc                  |  4 +-
 steps/test/unit/tBDAAverager.cc               |  2 +-
 steps/test/unit/tBDAExpander.cc               |  4 +-
 steps/test/unit/tBdaGroupPredict.cc           |  2 +-
 steps/test/unit/tFilter.cc                    |  4 +-
 steps/test/unit/tIDGPredict.cc                |  2 +-
 steps/test/unit/tInterpolate.cc               |  2 +-
 steps/test/unit/tMSBDAReader.cc               |  2 +-
 steps/test/unit/tMSBDAWriter.cc               | 15 ++++---
 steps/test/unit/tMedFlagger.cc                |  2 +-
 steps/test/unit/tOnePredict.cc                |  2 +-
 steps/test/unit/tPSet.cc                      |  2 +-
 steps/test/unit/tPhaseShift.cc                |  2 +-
 steps/test/unit/tPreFlagger.cc                |  2 +-
 steps/test/unit/tPyStep.cc                    |  2 +-
 steps/test/unit/tScaleData.cc                 |  2 +-
 steps/test/unit/tScaleDataBDA.cc              |  2 +-
 steps/test/unit/tStationAdder.cc              |  2 +-
 steps/test/unit/tUVWFlagger.cc                |  4 +-
 steps/test/unit/tUpsample.cc                  |  2 +-
 41 files changed, 148 insertions(+), 167 deletions(-)

diff --git a/base/DPInfo.cc b/base/DPInfo.cc
index dae285d44..43cb9ba3e 100644
--- a/base/DPInfo.cc
+++ b/base/DPInfo.cc
@@ -42,6 +42,7 @@ DPInfo::DPInfo()
       start_time_(0),
       time_interval_(0),
       beam_correction_mode_(static_cast<int>(everybeam::CorrectionMode::kNone)),
+      spectral_window_(0),
       n_threads_(aocommon::system::ProcessorCount()) {}
 
 void DPInfo::init(unsigned int ncorr, unsigned int startChan,
@@ -67,10 +68,11 @@ void DPInfo::setMsNames(const std::string& ms_name,
   weight_column_name_ = weight_column_name;
 }
 
-void DPInfo::set(std::vector<double>&& chan_freqs,
-                 std::vector<double>&& chan_widths,
-                 std::vector<double>&& resolutions,
-                 std::vector<double>&& effective_bw, double ref_freq) {
+void DPInfo::setChannels(std::vector<double>&& chan_freqs,
+                         std::vector<double>&& chan_widths,
+                         std::vector<double>&& resolutions,
+                         std::vector<double>&& effective_bw, double ref_freq,
+                         int spectral_window) {
   if (resolutions.empty()) {
     resolutions = chan_widths;
   }
@@ -78,11 +80,13 @@ void DPInfo::set(std::vector<double>&& chan_freqs,
     effective_bw = chan_widths;
   }
 
+  n_channels_ = chan_freqs.size();
   if (ref_freq == 0) {
-    int n = chan_freqs.size();
     // Takes mean of middle elements if n is even; takes middle if odd.
-    ref_freq = 0.5 * (chan_freqs[(n - 1) / 2] + chan_freqs[n / 2]);
+    ref_freq =
+        0.5 * (chan_freqs[(n_channels_ - 1) / 2] + chan_freqs[n_channels_ / 2]);
   }
+  reference_frequency_ = ref_freq;
 
   channel_frequencies_.clear();
   channel_widths_.clear();
@@ -96,14 +100,14 @@ void DPInfo::set(std::vector<double>&& chan_freqs,
 
   total_bandwidth_ = std::accumulate(effective_bandwidth_.front().begin(),
                                      effective_bandwidth_.front().end(), 0.0);
-  reference_frequency_ = ref_freq;
+  spectral_window_ = spectral_window;
 }
 
-void DPInfo::set(std::vector<std::vector<double>>&& chan_freqs,
-                 std::vector<std::vector<double>>&& chan_widths,
-                 std::vector<std::vector<double>>&& resolutions,
-                 std::vector<std::vector<double>>&& effective_bw,
-                 double ref_freq) {
+void DPInfo::setChannels(std::vector<std::vector<double>>&& chan_freqs,
+                         std::vector<std::vector<double>>&& chan_widths,
+                         std::vector<std::vector<double>>&& resolutions,
+                         std::vector<std::vector<double>>&& effective_bw,
+                         double ref_freq, int spectral_window) {
   if (resolutions.empty()) {
     resolutions = chan_widths;
   }
@@ -137,13 +141,14 @@ void DPInfo::set(std::vector<std::vector<double>>&& chan_freqs,
     // Takes mean of middle elements if n is even; takes middle if odd.
     ref_freq = 0.5 * ((*it)[(n_channels_ - 1) / 2] + (*it)[n_channels_ / 2]);
   }
+  reference_frequency_ = ref_freq;
 
   channel_frequencies_ = std::move(chan_freqs);
   channel_widths_ = std::move(chan_widths);
   resolutions_ = std::move(resolutions);
   effective_bandwidth_ = std::move(effective_bw);
   total_bandwidth_ = total_bw;
-  reference_frequency_ = ref_freq;
+  spectral_window_ = spectral_window;
 }
 
 bool DPInfo::channelsAreRegular() const {
diff --git a/base/test/unit/tDPInfo.cc b/base/test/unit/tDPInfo.cc
index 9c3ef1bf2..692404dff 100644
--- a/base/test/unit/tDPInfo.cc
+++ b/base/test/unit/tDPInfo.cc
@@ -54,7 +54,8 @@ BOOST_AUTO_TEST_CASE(set_frequency_info) {
   const double kTotalWidth = 11.0;
 
   dp3::base::DPInfo info;
-  info.set(std::vector<double>(kFreqs), std::vector<double>(kWidths));
+  info.setChannels(std::vector<double>(kFreqs), std::vector<double>(kWidths));
+  BOOST_TEST(kFreqs.size() == info.nchan());
   BOOST_TEST(kFreqs == info.chanFreqs());
   BOOST_TEST(kWidths == info.chanWidths());
   BOOST_TEST(kWidths == info.resolutions());
@@ -74,14 +75,15 @@ BOOST_AUTO_TEST_CASE(set_bda_frequency_info) {
 
   dp3::base::DPInfo info;
   info.set(kAntNames, kAntDiam, kAntPos, kAnt, kAnt);  // Set baseline count.
-  info.set(std::vector<std::vector<double>>(kFreqs),
-           std::vector<std::vector<double>>(kWidths));
+  info.setChannels(std::vector<std::vector<double>>(kFreqs),
+                   std::vector<std::vector<double>>(kWidths));
   for (std::size_t i = 0; i < kFreqs.size(); i++) {
     BOOST_TEST(kFreqs[i] == info.chanFreqs(i));
     BOOST_TEST(kWidths[i] == info.chanWidths(i));
     BOOST_TEST(kWidths[i] == info.resolutions(i));
     BOOST_TEST(kWidths[i] == info.effectiveBW(i));
   }
+  BOOST_TEST(5 == info.nchan());  // Maximum number of channels.
   BOOST_TEST(kRefFreq == info.refFreq());
   BOOST_TEST(kTotalWidth == info.totalBW());
 }
@@ -108,20 +110,20 @@ BOOST_AUTO_TEST_CASE(channels_are_regular) {
   // Test using a single baseline.
   {
     dp3::base::DPInfo info;
-    info.set(std::vector<double>(kRegularFreqs.front()),
-             std::vector<double>(kRegularWidths.front()));
+    info.setChannels(std::vector<double>(kRegularFreqs.front()),
+                     std::vector<double>(kRegularWidths.front()));
     BOOST_TEST(info.channelsAreRegular());
   }
   {
     dp3::base::DPInfo info;
-    info.set(std::vector<double>(kRegularFreqs.front()),
-             std::vector<double>(kIrregularWidths));
+    info.setChannels(std::vector<double>(kRegularFreqs.front()),
+                     std::vector<double>(kIrregularWidths));
     BOOST_TEST(!info.channelsAreRegular());
   }
   {
     dp3::base::DPInfo info;
-    info.set(std::vector<double>(kIrregularFreqs),
-             std::vector<double>(kRegularWidths.front()));
+    info.setChannels(std::vector<double>(kIrregularFreqs),
+                     std::vector<double>(kRegularWidths.front()));
     BOOST_TEST(!info.channelsAreRegular());
   }
 
@@ -129,15 +131,15 @@ BOOST_AUTO_TEST_CASE(channels_are_regular) {
   {
     dp3::base::DPInfo info;
     info.set(kAntNames, kAntDiam, kAntPos, kAnt, kAnt);  // Set baseline count.
-    info.set(std::vector<std::vector<double>>(kRegularFreqs),
-             std::vector<std::vector<double>>(kRegularWidths));
+    info.setChannels(std::vector<std::vector<double>>(kRegularFreqs),
+                     std::vector<std::vector<double>>(kRegularWidths));
     BOOST_TEST(info.channelsAreRegular());
   }
   {
     dp3::base::DPInfo info;
     info.set(kAntNames, kAntDiam, kAntPos, kAnt, kAnt);  // Set baseline count.
-    info.set(std::vector<std::vector<double>>(kIrregularFreqsBDA),
-             std::vector<std::vector<double>>(kIrregularWidthsBDA));
+    info.setChannels(std::vector<std::vector<double>>(kIrregularFreqsBDA),
+                     std::vector<std::vector<double>>(kIrregularWidthsBDA));
     BOOST_TEST(!info.channelsAreRegular());
   }
 }
diff --git a/include/dp3/base/DPInfo.h b/include/dp3/base/DPInfo.h
index 2984a285c..2c89abecf 100644
--- a/include/dp3/base/DPInfo.h
+++ b/include/dp3/base/DPInfo.h
@@ -45,9 +45,6 @@ class DPInfo {
     bda_interval_factor_is_integer_ = isIntervalInteger;
   }
 
-  /// Set nr of channels.
-  void setNChan(unsigned int nchan) { n_channels_ = nchan; }
-
   /// Set the time interval and the number of time steps.
   void setTimeIntervalAndSteps(double timeInterval, unsigned int ntime) {
     time_interval_ = timeInterval;
@@ -58,23 +55,24 @@ class DPInfo {
   /// An empty resolutions or effectiveBW is default to chanWidths.
   /// total_bandwidth_ is set to the sum of effectiveBW.
   /// If refFreq is 0, it is set to the middle of chanFreqs (mean if even).
-  void set(std::vector<double>&& chanFreqs, std::vector<double>&& chanWidths,
-           std::vector<double>&& resolutions = std::vector<double>(),
-           std::vector<double>&& effectiveBW = std::vector<double>(),
-           double refFreq = 0);
+  void setChannels(std::vector<double>&& chanFreqs,
+                   std::vector<double>&& chanWidths,
+                   std::vector<double>&& resolutions = std::vector<double>(),
+                   std::vector<double>&& effectiveBW = std::vector<double>(),
+                   double refFreq = 0, int spectralWindow = 0);
 
   /// Set the frequency info, using different info per baseline.
   /// An empty resolutions or effectiveBW is default to chanWidths.
   /// total_bandwidth_ is set to the sum of effectiveBW, which should be equal
   /// for all baselines. If refFreq is 0, it is set to the middle of chanFreqs
   /// (mean if even). of the baseline with the most channels.
-  void set(std::vector<std::vector<double>>&& chanFreqs,
-           std::vector<std::vector<double>>&& chanWidths,
-           std::vector<std::vector<double>>&& resolutions =
-               std::vector<std::vector<double>>(),
-           std::vector<std::vector<double>>&& effectiveBW =
-               std::vector<std::vector<double>>(),
-           double refFreq = 0);
+  void setChannels(std::vector<std::vector<double>>&& chanFreqs,
+                   std::vector<std::vector<double>>&& chanWidths,
+                   std::vector<std::vector<double>>&& resolutions =
+                       std::vector<std::vector<double>>(),
+                   std::vector<std::vector<double>>&& effectiveBW =
+                       std::vector<std::vector<double>>(),
+                   double refFreq = 0, int spectralWindow = 0);
 
   void setArrayInformation(const casacore::MPosition& arrayPos,
                            const casacore::MDirection& phaseCenter,
@@ -188,6 +186,7 @@ class DPInfo {
   }
   double totalBW() const { return total_bandwidth_; }
   double refFreq() const { return reference_frequency_; }
+  int spectralWindow() const { return spectral_window_; }
   ///@}
 
   /// Get the antenna numbers actually used in the (selected) baselines.
@@ -296,6 +295,7 @@ class DPInfo {
   std::vector<std::vector<double>> effective_bandwidth_;
   double total_bandwidth_;
   double reference_frequency_;
+  int spectral_window_;
   std::vector<std::string> antenna_names_;
   std::vector<double> antenna_diameters_;
   std::vector<casacore::MPosition> antenna_positions_;
diff --git a/steps/BDAAverager.cc b/steps/BDAAverager.cc
index 2cb31f4a5..eeddd9734 100644
--- a/steps/BDAAverager.cc
+++ b/steps/BDAAverager.cc
@@ -200,7 +200,7 @@ void BDAAverager::updateInfo(const DPInfo& _info) {
   bda_pool_size_ = _info.ncorr() * bda_channels;
 
   info().update(std::move(baseline_factors));
-  info().set(std::move(freqs), std::move(widths));
+  info().setChannels(std::move(freqs), std::move(widths));
 }
 
 bool BDAAverager::process(const DPBuffer& buffer) {
diff --git a/steps/BDAExpander.cc b/steps/BDAExpander.cc
index 03b5a5973..8165a1ac1 100644
--- a/steps/BDAExpander.cc
+++ b/steps/BDAExpander.cc
@@ -91,7 +91,7 @@ void BDAExpander::updateInfo(const DPInfo &_info) {
     }
   }
 
-  info().set(std::move(freqs), std::move(widths));
+  info().setChannels(std::move(freqs), std::move(widths));
 }
 
 void BDAExpander::show(std::ostream &os) const {
diff --git a/steps/BdaGroupPredict.cc b/steps/BdaGroupPredict.cc
index b683ad1f1..a14d281a7 100644
--- a/steps/BdaGroupPredict.cc
+++ b/steps/BdaGroupPredict.cc
@@ -69,9 +69,7 @@ class BdaGroupPredict::BaselineGroup {
     std::vector<double> chanFreqs(info_in.chanFreqs(baselines_[0]));
     std::vector<double> chanWidths(info_in.chanWidths(baselines_[0]));
     std::size_t nr_chan = chanFreqs.size();
-    info.set(std::move(chanFreqs),
-             std::move(chanWidths));  // This does not update info.nchan() !!
-    info.setNChan(nr_chan);           // So we need to set it
+    info.setChannels(std::move(chanFreqs), std::move(chanWidths));
     predict_step_->setInfo(info);
     dpbuffer_.getData().resize(info_in.ncorr(), nr_chan, nr_baselines);
     dpbuffer_.getWeights().resize(info_in.ncorr(), nr_chan, nr_baselines);
diff --git a/steps/InputStep.cc b/steps/InputStep.cc
index 3e9a947df..51fceffeb 100644
--- a/steps/InputStep.cc
+++ b/steps/InputStep.cc
@@ -120,10 +120,6 @@ double InputStep::lastTime() const {
   throw std::runtime_error("InputStep::lastTime not implemented");
 }
 
-unsigned int InputStep::spectralWindow() const {
-  throw std::runtime_error("InputStep::spectralWindow not implemented");
-}
-
 unsigned int InputStep::nchanAvgFullRes() const {
   throw std::runtime_error("InputStep::nchanAvgFullRes not implemented");
 }
diff --git a/steps/InputStep.h b/steps/InputStep.h
index f748ecd5b..c6067664b 100644
--- a/steps/InputStep.h
+++ b/steps/InputStep.h
@@ -87,9 +87,6 @@ class InputStep : public Step {
   virtual double firstTime() const;
   virtual double lastTime() const;
 
-  /// Get the selected spectral window.
-  virtual unsigned int spectralWindow() const;
-
   /// Get the nr of averaged full resolution channels.
   virtual unsigned int nchanAvgFullRes() const;
   /// Get the nr of averaged full resolution time slots.
diff --git a/steps/MSBDAReader.cc b/steps/MSBDAReader.cc
index 70150dff7..6461081ec 100644
--- a/steps/MSBDAReader.cc
+++ b/steps/MSBDAReader.cc
@@ -91,12 +91,10 @@ MSBDAReader::MSBDAReader(const casacore::MeasurementSet& ms,
   // a programming error, and not a user error, if the MS doesn't have BDA data.
   assert(HasBda(ms));
 
-  int spwInt = parset.getInt(prefix + "band", -1);
-  if (spwInt > 0) {
+  const int spectral_window = parset.getInt(prefix + "band", -1);
+  if (spectral_window > 0) {
     throw std::invalid_argument(
         "BDA in combination with multiple spectral windows is not implemented");
-  } else {
-    spw_ = 0;
   }
 
   const unsigned int nchan = parset.getInt(prefix + "nchan", 0);
@@ -344,7 +342,7 @@ void MSBDAReader::FillInfoMetaData() {
                              tile_beam_dir);
 
   info().update(std::move(baseline_factors));
-  info().set(std::move(freqs), std::move(widths));
+  info().setChannels(std::move(freqs), std::move(widths));
 }
 
 void MSBDAReader::show(std::ostream& os) const {
@@ -353,8 +351,8 @@ void MSBDAReader::show(std::ostream& os) const {
   if (ms_.isNull()) {
     os << "    *** MS does not exist ***\n";
   } else {
-    os << "  band            " << spw_ << '\n';
-    os << "  start_chan:      " << 0 << '\n';
+    os << "  band            " << getInfo().spectralWindow() << '\n';
+    os << "  start_chan:     " << 0 << '\n';
     os << "  nchan:          " << getInfo().nchan() << '\n';
     os << "  ncorrelations:  " << getInfo().ncorr() << '\n';
     os << "  nbaselines:     " << getInfo().nbaselines() << '\n';
diff --git a/steps/MSBDAReader.h b/steps/MSBDAReader.h
index 69c087388..eb9cb292a 100644
--- a/steps/MSBDAReader.h
+++ b/steps/MSBDAReader.h
@@ -141,9 +141,6 @@ class MSBDAReader : public InputStep {
   /// Get the main MS table.
   const casacore::Table& table() const override { return ms_; }
 
-  /// Get the selected spectral window.
-  unsigned int spectralWindow() const override { return spw_; }
-
   /// Get the nr of averaged full resolution channels.
   unsigned int nchanAvgFullRes() const override { return 1; }
 
@@ -166,7 +163,6 @@ class MSBDAReader : public InputStep {
   double last_ms_interval_;
   double interval_;  ///< original interval of the MS
   bool is_interval_integer_;
-  unsigned int spw_;    ///< spw (band) to use (<0 no select)
   unsigned int nread_;  ///< nr of time slots read from MS
   common::NSTimer timer_;
   std::size_t pool_size_;  ///< Pool size that will be used for the BDA buffers
diff --git a/steps/MSBDAWriter.cc b/steps/MSBDAWriter.cc
index 187748663..b5a5feb1a 100644
--- a/steps/MSBDAWriter.cc
+++ b/steps/MSBDAWriter.cc
@@ -376,9 +376,8 @@ void MSBDAWriter::OverwriteSubTables(const Int bda_set_id) {
 
   // Remove all rows before and after the selected band.
   // Do it from the end, otherwise row numbers change.
-  for (unsigned int i = outSPW.nrow(); i > 0;) {
-    --i;
-    if (i == reader_->spectralWindow()) {
+  for (int i = int(outSPW.nrow()) - 1; i >= 0; --i) {
+    if (i == info().spectralWindow()) {
       measFreqRef =
           outSPW.col(MS_SPW::columnName(MS_SPW::MEAS_FREQ_REF)).getInt(i);
       name = outSPW.col(MS_SPW::columnName(MS_SPW::NAME)).getString(i);
diff --git a/steps/MSReader.cc b/steps/MSReader.cc
index b0f8def69..5bdbe2e16 100644
--- a/steps/MSReader.cc
+++ b/steps/MSReader.cc
@@ -93,7 +93,6 @@ MSReader::MSReader(const casacore::MeasurementSet& ms,
       itsAutoWeightForce(parset.getBool(prefix + "forceautoweight", false)),
       itsUseFlags(parset.getBool(prefix + "useflag", true)),
       itsMissingData(missingData),
-      itsSpw(parset.getInt(prefix + "band", -1)),
       itsTimeTolerance(parset.getDouble(prefix + "timetolerance", 1e-2)) {
   common::NSTimer::StartStop sstime(itsTimer);
   // Get info from parset.
@@ -109,19 +108,20 @@ MSReader::MSReader(const casacore::MeasurementSet& ms,
   assert(!HasBda(ms));
   // See if a selection on band needs to be done.
   // We assume that DATA_DESC_ID and SPW_ID map 1-1.
-  if (itsSpw >= 0) {
+  int spectralWindow = parset.getInt(prefix + "band", -1);
+  if (spectralWindow >= 0) {
     DPLOG_INFO_STR(" MSReader selecting spectral window " +
-                   std::to_string(itsSpw) + " ...");
-    Table subset = itsSelMS(itsSelMS.col("DATA_DESC_ID") == itsSpw);
+                   std::to_string(spectralWindow) + " ...");
+    Table subset = itsSelMS(itsSelMS.col("DATA_DESC_ID") == spectralWindow);
     // If not all is selected, use the selection.
     if (subset.nrow() < itsSelMS.nrow()) {
       if (subset.nrow() <= 0)
-        throw std::runtime_error("Band " + std::to_string(itsSpw) +
+        throw std::runtime_error("Band " + std::to_string(spectralWindow) +
                                  " not found in " + msName());
       itsSelMS = subset;
     }
   } else {
-    itsSpw = 0;
+    spectralWindow = 0;
   }
   // See if a selection on baseline needs to be done.
   if (!itsSelBL.empty()) {
@@ -258,7 +258,7 @@ MSReader::MSReader(const casacore::MeasurementSet& ms,
   // Are all channels used?
   itsUseAllChan = itsStartChan == 0 && itsNrChan == nAllChan;
   // Do the rest of the preparation.
-  prepare2();
+  prepare2(spectralWindow);
   // Take subset of channel frequencies if needed.
   // Make sure to copy the subset to get a proper Vector.
   // Form the slicer to get channels and correlations from column.
@@ -453,7 +453,7 @@ void MSReader::show(std::ostream& os) const {
     if (!itsSelBL.empty()) {
       os << "  baseline:       " << itsSelBL << '\n';
     }
-    os << "  band            " << itsSpw << '\n';
+    os << "  band            " << getInfo().spectralWindow() << '\n';
     os << "  startchan:      " << itsStartChan << "  (" << itsStartChanStr
        << ")\n";
     os << "  nchan:          " << getInfo().nchan() << "  (" << itsNrChanStr
@@ -669,7 +669,7 @@ void MSReader::prepare(double& firstTime, double& lastTime, double& interval) {
       std::make_unique<base::UVWCalculator>(phaseCenter, arrayPos, antPos);
 }
 
-void MSReader::prepare2() {
+void MSReader::prepare2(int spectralWindow) {
   // Set the info.
   // The 1.5 comes from a) rounding (0.5) + b) the paaltjesprobleem.
   unsigned int ntime =
@@ -690,24 +690,25 @@ void MSReader::prepare2() {
   ArrayColumn<double> resolCol(spwtab, "RESOLUTION");
   ArrayColumn<double> effBWCol(spwtab, "EFFECTIVE_BW");
   ScalarColumn<double> refCol(spwtab, "REF_FREQUENCY");
-  std::vector<double> chanFreqs = freqCol(itsSpw).tovector();
-  std::vector<double> chanWidths = widthCol(itsSpw).tovector();
-  std::vector<double> resolutions = resolCol(itsSpw).tovector();
-  std::vector<double> effectiveBW = effBWCol(itsSpw).tovector();
-  const double refFreq = refCol(itsSpw);
+  std::vector<double> chanFreqs = freqCol(spectralWindow).tovector();
+  std::vector<double> chanWidths = widthCol(spectralWindow).tovector();
+  std::vector<double> resolutions = resolCol(spectralWindow).tovector();
+  std::vector<double> effectiveBW = effBWCol(spectralWindow).tovector();
+  const double refFreq = refCol(spectralWindow);
   if (itsUseAllChan) {
-    info().set(std::move(chanFreqs), std::move(chanWidths),
-               std::move(resolutions), std::move(effectiveBW), refFreq);
+    info().setChannels(std::move(chanFreqs), std::move(chanWidths),
+                       std::move(resolutions), std::move(effectiveBW), refFreq,
+                       spectralWindow);
   } else {
     auto freqBegin = chanFreqs.begin() + itsStartChan;
     auto widthBegin = chanWidths.begin() + itsStartChan;
     auto resolBegin = resolutions.begin() + itsStartChan;
     auto effbwBegin = effectiveBW.begin() + itsStartChan;
-    info().set(std::vector<double>(freqBegin, freqBegin + itsNrChan),
-               std::vector<double>(widthBegin, widthBegin + itsNrChan),
-               std::vector<double>(resolBegin, resolBegin + itsNrChan),
-               std::vector<double>(effbwBegin, effbwBegin + itsNrChan),
-               refFreq);
+    info().setChannels(std::vector<double>(freqBegin, freqBegin + itsNrChan),
+                       std::vector<double>(widthBegin, widthBegin + itsNrChan),
+                       std::vector<double>(resolBegin, resolBegin + itsNrChan),
+                       std::vector<double>(effbwBegin, effbwBegin + itsNrChan),
+                       refFreq, spectralWindow);
   }
 }
 
diff --git a/steps/MSReader.h b/steps/MSReader.h
index c743abada..439002a47 100644
--- a/steps/MSReader.h
+++ b/steps/MSReader.h
@@ -184,9 +184,6 @@ class MSReader : public InputStep {
   double firstTime() const override { return itsFirstTime; }
   double lastTime() const override { return itsLastTime; }
 
-  /// Get the selected spectral window.
-  unsigned int spectralWindow() const override { return itsSpw; }
-
   /// Get the baseline selection.
   const string& baselineSelection() const { return itsSelBL; }
 
@@ -222,7 +219,7 @@ class MSReader : public InputStep {
   void prepare(double& firstTime, double& lastTime, double& interval);
 
   /// Do the rest of the preparation.
-  void prepare2();
+  void prepare2(int spectralWindow);
 
   /// Skip the first times in the MS in case a start time was given.
   /// If needed, it sets itsFirstTime properly.
@@ -252,7 +249,6 @@ class MSReader : public InputStep {
   bool itsUseFlags{true};
   bool itsUseAllChan{false};   ///< all channels (i.e. no slicer)?
   bool itsMissingData{false};  ///< allow missing data column?
-  int itsSpw{-1};              ///< spw (band) to use (<0 no select)
   unsigned int itsNrBl{0};
   unsigned int itsNrCorr{0};
   unsigned int itsNrChan{0};
diff --git a/steps/MSWriter.cc b/steps/MSWriter.cc
index 4dbac455e..282c7dd0b 100644
--- a/steps/MSWriter.cc
+++ b/steps/MSWriter.cc
@@ -187,7 +187,7 @@ void MSWriter::StartNewMs() {
       chunk_duration_ == 0.0
           ? out_name_
           : InsertNumberInFilename(out_name_, current_chunk_index_);
-  CreateMs(chunk_name, info(), tile_size_, tile_n_chan_);
+  CreateMs(chunk_name, tile_size_, tile_n_chan_);
   // Write the parset info into the history.
   WriteHistory(ms_, parset_);
   ms_.flush(true, true);
@@ -302,8 +302,8 @@ void MSWriter::MakeArrayColumn(ColumnDesc desc, const IPosition& ipos,
   }
 }
 
-void MSWriter::CreateMs(const string& out_name, const DPInfo& info,
-                        unsigned int tile_size, unsigned int tile_n_chan) {
+void MSWriter::CreateMs(const std::string& out_name, unsigned int tile_size,
+                        unsigned int tile_n_chan) {
   // Determine the data shape.
   IPosition data_shape(2, nr_corr_, nr_chan_);
   // Obtain the MS description.
@@ -514,17 +514,18 @@ void MSWriter::CreateMs(const string& out_name, const DPInfo& info,
   omitted_subtables[1] = base::DP3MS::kBDAFactorsTable;
   TableCopy::copySubTables(ms_, temptable, false, omitted_subtables);
   // Adjust the SPECTRAL_WINDOW and DATA_DESCRIPTION table as needed.
-  UpdateSpw(out_name, info);
+  UpdateSpw(out_name);
   // Adjust the OBSERVATION table as needed.
   UpdateObs(out_name);
   // Adjust the FIELD table as needed.
-  if (info.originalPhaseCenter().getValue() != info.phaseCenter().getValue()) {
-    UpdatePhaseCentre(out_name, info);
+  if (info().originalPhaseCenter().getValue() !=
+      info().phaseCenter().getValue()) {
+    UpdatePhaseCentre(out_name);
   }
-  UpdateBeam(ms_, "DATA", info);
+  UpdateBeam(ms_, "DATA", info());
 }
 
-void MSWriter::UpdateSpw(const string& out_name, const DPInfo& info) {
+void MSWriter::UpdateSpw(const std::string& out_name) {
   // Fix the SPECTRAL_WINDOW values by updating the values in the subtable.
   IPosition shape(1, nr_chan_);
   Table in_spw = reader_.table().keywordSet().asTable("SPECTRAL_WINDOW");
@@ -534,11 +535,10 @@ void MSWriter::UpdateSpw(const string& out_name, const DPInfo& info) {
     throw std::runtime_error(
         "nrow in SPECTRAL_WINDOW table is not the same as nrow in "
         "DATA_DESCRIPTION table");
-  unsigned int spw = reader_.spectralWindow();
   // Remove all rows before and after the selected band.
   // Do it from the end, otherwise row numbers change.
-  for (unsigned int i = out_spw.nrow(); i > 0;) {
-    if (--i != spw) {
+  for (int i = int(out_spw.nrow()) - 1; i >= 0; --i) {
+    if (i != info().spectralWindow()) {
       out_spw.removeRow(i);
       out_dd.removeRow(i);
     }
@@ -559,12 +559,12 @@ void MSWriter::UpdateSpw(const string& out_name, const DPInfo& info) {
   ArrayColumn<double> out_resolution(out_spw, "RESOLUTION");
   ScalarColumn<double> out_totalbw(out_spw, "TOTAL_BANDWIDTH");
   ScalarColumn<double> out_reffreq(out_spw, "REF_FREQUENCY");
-  out_freq.put(0, casacore::Vector<double>(info.chanFreqs()));
-  out_width.put(0, casacore::Vector<double>(info.chanWidths()));
-  out_bw.put(0, casacore::Vector<double>(info.effectiveBW()));
-  out_resolution.put(0, casacore::Vector<double>(info.resolutions()));
-  out_totalbw.put(0, info.totalBW());
-  out_reffreq.put(0, info.refFreq());
+  out_freq.put(0, casacore::Vector<double>(info().chanFreqs()));
+  out_width.put(0, casacore::Vector<double>(info().chanWidths()));
+  out_bw.put(0, casacore::Vector<double>(info().effectiveBW()));
+  out_resolution.put(0, casacore::Vector<double>(info().resolutions()));
+  out_totalbw.put(0, info().totalBW());
+  out_reffreq.put(0, info().refFreq());
   // Adjust the spwid in the DATA_DESCRIPTION.
   ScalarColumn<int> spw_col(out_dd, "SPECTRAL_WINDOW_ID");
   spw_col.put(0, 0);
@@ -583,15 +583,15 @@ void MSWriter::UpdateObs(const string& out_name) {
   }
 }
 
-void MSWriter::UpdatePhaseCentre(const string& out_name, const DPInfo& info) {
+void MSWriter::UpdatePhaseCentre(const string& out_name) {
   Table out_field = Table(out_name + "/FIELD", Table::Update);
   // Write new phase center.
   ArrayMeasColumn<MDirection> phase_col(out_field, "PHASE_DIR");
   // If a moving reference type like AZELGEO was used in the original MS, and
   // the phase centre is changed (with a phaseshift), the ref frame of the
   // column must be reset:
-  phase_col.setDescRefCode(info.phaseCenter().getRefPtr()->getType(), false);
-  casacore::Vector<MDirection> dir(1, info.phaseCenter());
+  phase_col.setDescRefCode(info().phaseCenter().getRefPtr()->getType(), false);
+  casacore::Vector<MDirection> dir(1, info().phaseCenter());
   phase_col.put(0, dir);
 }
 
diff --git a/steps/MSWriter.h b/steps/MSWriter.h
index bee527ca6..f1a44d5a4 100644
--- a/steps/MSWriter.h
+++ b/steps/MSWriter.h
@@ -107,17 +107,17 @@ class MSWriter : public OutputStep {
   /// Create the MS by cloning all subtables from the input MS.
   /// All output columns in the main table are using normal storage managers.
   /// The SPECTRAL_WINDOW table is adapted as needed.
-  void CreateMs(const std::string& out_name, const base::DPInfo& info,
-                unsigned int tile_size, unsigned int tile_n_chan);
+  void CreateMs(const std::string& out_name, unsigned int tile_size,
+                unsigned int tile_n_chan);
 
   /// Update the SPECTRAL_WINDOW table for averaged channels.
-  void UpdateSpw(const string& out_name, const base::DPInfo& info);
+  void UpdateSpw(const string& out_name);
 
   /// Update the OBSERVATION table with the correct start and end time.
   void UpdateObs(const string& out_name);
 
   /// Update the FIELD table with the new phase center.
-  void UpdatePhaseCentre(const string& out_name, const base::DPInfo& info);
+  void UpdatePhaseCentre(const string& out_name);
 
   /// Update @ref internal_buffer_ with the provided @a buffer.
   void UpdateInternalBuffer(const base::DPBuffer& buffer);
diff --git a/steps/MultiMSReader.cc b/steps/MultiMSReader.cc
index 2466ae4bb..07637a1b9 100644
--- a/steps/MultiMSReader.cc
+++ b/steps/MultiMSReader.cc
@@ -44,10 +44,7 @@ namespace steps {
 MultiMSReader::MultiMSReader(const std::vector<std::string>& msNames,
                              const common::ParameterSet& parset,
                              const string& prefix)
-    : itsFirst(-1),
-      itsNMissing(0),
-      itsMSNames(msNames),
-      itsRegularChannels(true) {
+    : itsFirst(-1), itsNMissing(0), itsMSNames(msNames) {
   if (msNames.empty())
     throw std::runtime_error("No names of MeasurementSets given");
   itsStartChanStr = parset.getString(prefix + "startchan", "0");
@@ -141,8 +138,10 @@ void MultiMSReader::handleBands() {
                       itsReaders[i]->getInfo().effectiveBW().data(), nchan);
     inx += nchan;
   }
-  info().set(std::move(chanFreqs), std::move(chanWidths),
-             std::move(resolutions), std::move(effectiveBW));
+  info().setChannels(std::move(chanFreqs), std::move(chanWidths),
+                     std::move(resolutions), std::move(effectiveBW),
+                     itsReaders[itsFirst]->getInfo().refFreq(),
+                     itsReaders[itsFirst]->getInfo().spectralWindow());
 }
 
 void MultiMSReader::sortBands() {
@@ -210,7 +209,7 @@ void MultiMSReader::fillBands() {
     }
   }
 
-  info().set(std::move(chanFreqs), std::move(chanWidths));
+  info().setChannels(std::move(chanFreqs), std::move(chanWidths));
 }
 
 bool MultiMSReader::process(const DPBuffer& buf) {
@@ -298,7 +297,6 @@ void MultiMSReader::updateInfo(const DPInfo& infoIn) {
   itsLastTime = itsReaders[itsFirst]->lastTime();
   itsTimeInterval = getInfo().timeInterval();
   itsSelBL = itsReaders[itsFirst]->baselineSelection();
-  itsSpw = itsReaders[itsFirst]->spectralWindow();
   itsNrCorr = getInfo().ncorr();
   itsNrBl = getInfo().nbaselines();
   itsNrChan = 0;
@@ -353,11 +351,6 @@ void MultiMSReader::updateInfo(const DPInfo& infoIn) {
   // Sort them if needed.
   handleBands();
 
-  // check that channels are regularly spaced, give warning otherwise
-  itsRegularChannels = info().channelsAreRegular();
-
-  // Set correct nr of channels.
-  info().setNChan(itsNrChan);
   // Initialize the flag counters.
   itsFlagCounter.init(getInfo());
 }
@@ -371,11 +364,11 @@ void MultiMSReader::show(std::ostream& os) const {
   if (!itsSelBL.empty()) {
     os << "  baseline:       " << itsSelBL << '\n';
   }
-  os << "  band            " << itsSpw << '\n';
+  os << "  band            " << getInfo().spectralWindow() << '\n';
   os << "  startchan:      " << itsStartChan << "  (" << itsStartChanStr << ')'
      << '\n';
   os << "  nchan:          " << itsNrChan << "  (" << itsNrChanStr << ')';
-  if (itsRegularChannels) {
+  if (getInfo().channelsAreRegular()) {
     os << " (regularly spaced)" << '\n';
   } else {
     os << " (NOT regularly spaced)" << '\n';
diff --git a/steps/MultiMSReader.h b/steps/MultiMSReader.h
index 9ba4cad67..9ee8044f1 100644
--- a/steps/MultiMSReader.h
+++ b/steps/MultiMSReader.h
@@ -175,7 +175,6 @@ class MultiMSReader final : public MSReader {
   std::vector<base::DPBuffer> itsBuffers;
   unsigned int itsFillNChan;  ///< nr of chans for missing MSs
   base::FlagCounter itsFlagCounter;
-  bool itsRegularChannels;  /// Are resulting channels regularly spaced
 };
 
 }  // namespace steps
diff --git a/steps/dynamic_test_step/test/tDynamicTestStep.cc b/steps/dynamic_test_step/test/tDynamicTestStep.cc
index 94a494772..0561b8f55 100644
--- a/steps/dynamic_test_step/test/tDynamicTestStep.cc
+++ b/steps/dynamic_test_step/test/tDynamicTestStep.cc
@@ -85,7 +85,7 @@ class TestInput : public dp3::steps::MockInput {
     for (int i = 0; i < itsNChan; i++) {
       chanFreqs.push_back(1050000. + i * 100000.);
     }
-    info().set(std::move(chanFreqs), std::move(chanWidth));
+    info().setChannels(std::move(chanFreqs), std::move(chanWidth));
   }
   int itsCount, itsNTime, itsNBl, itsNChan, itsNCorr;
   bool itsFlag;
@@ -239,7 +239,7 @@ class TestInput3 : public dp3::steps::MockInput {
     for (int i = 0; i < itsNrChan; i++) {
       chanFreqs.push_back(1050000. + i * 100000.);
     }
-    info().set(std::move(chanFreqs), std::move(chanWidth));
+    info().setChannels(std::move(chanFreqs), std::move(chanWidth));
   }
   int itsCount, itsNrTime, itsNrBl, itsNrChan, itsNrCorr;
   Cube<bool> itsFullResFlags;
diff --git a/steps/test/unit/tAOFlaggerStep.cc b/steps/test/unit/tAOFlaggerStep.cc
index 59836c45b..e022e7eff 100644
--- a/steps/test/unit/tAOFlaggerStep.cc
+++ b/steps/test/unit/tAOFlaggerStep.cc
@@ -98,7 +98,7 @@ class TestInput : public dp3::steps::MockInput {
     std::vector<double> chanFreqs(nchan);
     std::vector<double> chanWidth(nchan, 100000.);
     std::iota(chanFreqs.begin(), chanFreqs.end(), 1050000);
-    info().set(std::move(chanFreqs), std::move(chanWidth));
+    info().setChannels(std::move(chanFreqs), std::move(chanWidth));
   }
 
  private:
diff --git a/steps/test/unit/tApplyCal.cc b/steps/test/unit/tApplyCal.cc
index dd083130f..27964c4ff 100644
--- a/steps/test/unit/tApplyCal.cc
+++ b/steps/test/unit/tApplyCal.cc
@@ -92,7 +92,7 @@ class TestInput : public dp3::steps::MockInput {
     for (int i = 0; i < nchan; ++i) {
       chanFreqs.push_back(10500000. + i * 1000000.);
     }
-    info().set(std::move(chanFreqs), std::move(chanWidth));
+    info().setChannels(std::move(chanFreqs), std::move(chanWidth));
   }
 
  private:
diff --git a/steps/test/unit/tApplyCalH5.cc b/steps/test/unit/tApplyCalH5.cc
index 2f96acba1..c5e2f95ab 100644
--- a/steps/test/unit/tApplyCalH5.cc
+++ b/steps/test/unit/tApplyCalH5.cc
@@ -110,7 +110,7 @@ class TestInput : public dp3::steps::MockInput {
       chanFreqs[0] = 100.e6;
       chanFreqs[1] = 101.e6;
     }
-    info().set(std::move(chanFreqs), std::move(chanWidth));
+    info().setChannels(std::move(chanFreqs), std::move(chanWidth));
   }
 
  private:
diff --git a/steps/test/unit/tAverager.cc b/steps/test/unit/tAverager.cc
index 68386d02a..377d1a0df 100644
--- a/steps/test/unit/tAverager.cc
+++ b/steps/test/unit/tAverager.cc
@@ -85,7 +85,7 @@ class TestInput : public dp3::steps::MockInput {
     for (int i = 0; i < itsNChan; i++) {
       chanFreqs.push_back(1050000. + i * 100000.);
     }
-    info().set(std::move(chanFreqs), std::move(chanWidth));
+    info().setChannels(std::move(chanFreqs), std::move(chanWidth));
   }
   int itsCount, itsNTime, itsNBl, itsNChan, itsNCorr;
   bool itsFlag;
@@ -244,7 +244,7 @@ class TestInput3 : public dp3::steps::MockInput {
     for (int i = 0; i < itsNrChan; i++) {
       chanFreqs.push_back(1050000. + i * 100000.);
     }
-    info().set(std::move(chanFreqs), std::move(chanWidth));
+    info().setChannels(std::move(chanFreqs), std::move(chanWidth));
   }
   int itsCount, itsNrTime, itsNrBl, itsNrChan, itsNrCorr;
   casacore::Cube<bool> itsFullResFlags;
diff --git a/steps/test/unit/tBDAAverager.cc b/steps/test/unit/tBDAAverager.cc
index 6f38a66ff..d95786e35 100644
--- a/steps/test/unit/tBDAAverager.cc
+++ b/steps/test/unit/tBDAAverager.cc
@@ -67,7 +67,7 @@ void InitInfo(DPInfo& info, const std::vector<int>& ant1,
   info.init(kNCorr, kStartChan, n_chan, kNTime, kStartTime, kInterval,
             kAntennaSet);
   info.set(kAntNames, kAntDiam, kAntPos, ant1, ant2);
-  info.set(std::move(chan_freqs), std::move(chan_widths));
+  info.setChannels(std::move(chan_freqs), std::move(chan_widths));
 }
 
 void CheckInfo(
diff --git a/steps/test/unit/tBDAExpander.cc b/steps/test/unit/tBDAExpander.cc
index daaea1c8e..0182400d8 100644
--- a/steps/test/unit/tBDAExpander.cc
+++ b/steps/test/unit/tBDAExpander.cc
@@ -136,7 +136,7 @@ BOOST_AUTO_TEST_CASE(time_expansion) {
             kInterval, kAntennaSet);
   info.set(kAntNames, kAntDiam, kAntPos, kAnt1_2Bl, kAnt2_2Bl);
   info.setIsBDAIntervalFactorInteger(true);
-  info.set(std::move(chan_freqs), std::move(chan_widths));
+  info.setChannels(std::move(chan_freqs), std::move(chan_widths));
 
   dp3::common::ParameterSet parset;
   dp3::steps::MockInput mock_input;
@@ -249,7 +249,7 @@ BOOST_AUTO_TEST_CASE(frequency_expansion) {
 
   info.set(kAntNames, kAntDiam, kAntPos, kAnt1_2Bl, kAnt2_2Bl);
   info.setIsBDAIntervalFactorInteger(true);
-  info.set(std::move(chan_freqs), std::move(chan_widths));
+  info.setChannels(std::move(chan_freqs), std::move(chan_widths));
 
   dp3::common::ParameterSet parset;
   dp3::steps::MockInput mock_input;
diff --git a/steps/test/unit/tBdaGroupPredict.cc b/steps/test/unit/tBdaGroupPredict.cc
index 813304833..2e83379d5 100644
--- a/steps/test/unit/tBdaGroupPredict.cc
+++ b/steps/test/unit/tBdaGroupPredict.cc
@@ -37,7 +37,7 @@ class BdaPredictFixture {
 
     // Use unusal values since to make clear the value is not used.
     info.update(std::vector<unsigned>{-1u, -1u, -1u});
-    info.set(std::move(chan_freqs), std::move(chan_widths));
+    info.setChannels(std::move(chan_freqs), std::move(chan_widths));
     predict_->setInfo(info);
   }
 
diff --git a/steps/test/unit/tFilter.cc b/steps/test/unit/tFilter.cc
index 0fec71193..96d3b84d0 100644
--- a/steps/test/unit/tFilter.cc
+++ b/steps/test/unit/tFilter.cc
@@ -143,7 +143,7 @@ class TestInput : public dp3::steps::MockInput {
     for (int i = 0; i < nchan; i++) {
       chanFreqs.push_back(1050000. + i * 100000.);
     }
-    info().set(std::move(chanFreqs), std::move(chanWidth));
+    info().setChannels(std::move(chanFreqs), std::move(chanWidth));
   }
 
  private:
@@ -199,7 +199,7 @@ class TestInput : public dp3::steps::MockInput {
     for (int i = 0; i < itsNChan; i++) {
       chanFreqs.push_back(1050000. + i * 100000.);
     }
-    info().set(std::move(chanFreqs), std::move(chanWidth));
+    info().setChannels(std::move(chanFreqs), std::move(chanWidth));
   }
   int itsCount, itsNTime, itsNBl, itsNChan, itsNCorr;
   bool itsFlag;
diff --git a/steps/test/unit/tIDGPredict.cc b/steps/test/unit/tIDGPredict.cc
index 110df7cf7..74d544736 100644
--- a/steps/test/unit/tIDGPredict.cc
+++ b/steps/test/unit/tIDGPredict.cc
@@ -50,7 +50,7 @@ void InitInfo(dp3::base::DPInfo& info, const std::vector<int>& ant1,
   info.init(kNCorr, kStartChan, n_chan, kNTime, kStartTime, kInterval,
             kAntennaSet);
   info.set(kAntNames, kAntDiam, kAntPos, ant1, ant2);
-  info.set(std::move(chan_freqs), std::move(chan_widths));
+  info.setChannels(std::move(chan_freqs), std::move(chan_widths));
 }
 
 /**
diff --git a/steps/test/unit/tInterpolate.cc b/steps/test/unit/tInterpolate.cc
index a8a412405..892ba1029 100644
--- a/steps/test/unit/tInterpolate.cc
+++ b/steps/test/unit/tInterpolate.cc
@@ -87,7 +87,7 @@ class TestInput : public dp3::steps::MockInput {
     for (int i = 0; i < nchan; i++) {
       chanFreqs.push_back(1050000. + i * 100000.);
     }
-    info().set(std::move(chanFreqs), std::move(chanWidth));
+    info().setChannels(std::move(chanFreqs), std::move(chanWidth));
   }
 
  private:
diff --git a/steps/test/unit/tMSBDAReader.cc b/steps/test/unit/tMSBDAReader.cc
index a96e1a5c3..e94158178 100644
--- a/steps/test/unit/tMSBDAReader.cc
+++ b/steps/test/unit/tMSBDAReader.cc
@@ -38,7 +38,7 @@ BOOST_AUTO_TEST_CASE(set_info) {
                    // (2000/08/03 13h22m05.000) into seconds
 
   const DPInfo& info = reader.getInfo();
-  BOOST_TEST(reader.spectralWindow() == 0U);
+  BOOST_TEST(info.spectralWindow() == 0U);
   BOOST_TEST(info.nchan() == 16U);
   BOOST_TEST(info.ncorr() == 4U);
   // With BDA we approximate this amount of buffers to be streamed.
diff --git a/steps/test/unit/tMSBDAWriter.cc b/steps/test/unit/tMSBDAWriter.cc
index 4777fc2de..f642adb14 100644
--- a/steps/test/unit/tMSBDAWriter.cc
+++ b/steps/test/unit/tMSBDAWriter.cc
@@ -55,9 +55,10 @@ BOOST_FIXTURE_TEST_CASE(process_simple, FixtureDirectory,
   info.set(std::vector<std::string>{"ant"}, std::vector<double>{1.0},
            {casacore::MVPosition{0, 0, 0}}, std::vector<int>{0},
            std::vector<int>{0});
-  info.set(std::vector<std::vector<double>>{{1.}},
-           std::vector<std::vector<double>>{{10.}});
-  info.set(std::vector<double>(nchan, 1.), std::vector<double>(nchan, 5000.));
+  info.setChannels(std::vector<std::vector<double>>{{1.}},
+                   std::vector<std::vector<double>>{{10.}});
+  info.setChannels(std::vector<double>(nchan, 1.),
+                   std::vector<double>(nchan, 5000.));
   writer.updateInfo(info);
 
   auto buffer = std::make_unique<BDABuffer>(1);
@@ -159,7 +160,7 @@ BOOST_FIXTURE_TEST_CASE(exception_when_mismatch, FixtureDirectory) {
            std::vector<double>{1.0, 2.0},
            {casacore::MVPosition{0, 0, 0}, casacore::MVPosition{0, 0, 0}},
            std::vector<int>{0, 1}, std::vector<int>{0, 1});
-  info.set(std::vector<double>(1, 1.), std::vector<double>(1, 5000.));
+  info.setChannels(std::vector<double>(1, 1.), std::vector<double>(1, 5000.));
 
   // ntimeAvgs is 1, nbaselines 2 so we expect an exception
   BOOST_TEST(info.ntimeAvgs().size() == size_t(1));
@@ -176,7 +177,7 @@ BOOST_FIXTURE_TEST_CASE(create_default_subtables, FixtureDirectory,
   info.set(std::vector<std::string>{"ant"}, std::vector<double>{1.0},
            {casacore::MVPosition{0, 0, 0}}, std::vector<int>{0},
            std::vector<int>{0});
-  info.set(std::vector<double>(1, 1.), std::vector<double>(1, 5000.));
+  info.setChannels(std::vector<double>(1, 1.), std::vector<double>(1, 5000.));
   const std::string kMsName = "default_tables.MS";
 
   MSBDAWriter writer(nullptr, kMsName, ParameterSet(), "");
@@ -210,8 +211,8 @@ BOOST_FIXTURE_TEST_CASE(different_bda_intervals, FixtureDirectory,
            std::vector<double>{1.0, 1.0},
            {casacore::MVPosition{0, 0, 0}, casacore::MVPosition{10, 10, 0}},
            std::vector<int>{0, 1}, std::vector<int>{0, 1});
-  info.set(std::vector<std::vector<double>>{{1.}, {1.}},
-           std::vector<std::vector<double>>{{5000.}, {5000.}});
+  info.setChannels(std::vector<std::vector<double>>{{1.}, {1.}},
+                   std::vector<std::vector<double>>{{5000.}, {5000.}});
   info.update(std::vector<unsigned int>{kMinTimeInterval, kMaxTimeInterval});
   casacore::MeasurementSet ms_in("../tNDPPP_tmp.MS");
   MSReader reader(ms_in, parset, prefix);
diff --git a/steps/test/unit/tMedFlagger.cc b/steps/test/unit/tMedFlagger.cc
index 14ce7e268..2941ce5ab 100644
--- a/steps/test/unit/tMedFlagger.cc
+++ b/steps/test/unit/tMedFlagger.cc
@@ -130,7 +130,7 @@ class TestInput : public dp3::steps::MockInput {
     for (int i = 0; i < itsNChan; i++) {
       chanFreqs.push_back(1050000. + i * 100000.);
     }
-    info().set(std::move(chanFreqs), std::move(chanWidth));
+    info().setChannels(std::move(chanFreqs), std::move(chanWidth));
   }
 
   int itsCount, itsNTime, itsNBl, itsNChan, itsNCorr;
diff --git a/steps/test/unit/tOnePredict.cc b/steps/test/unit/tOnePredict.cc
index 90b75c0e2..a5f340e8a 100644
--- a/steps/test/unit/tOnePredict.cc
+++ b/steps/test/unit/tOnePredict.cc
@@ -56,7 +56,7 @@ class OnePredictFixture {
     std::vector<double> chan_freqs(1, 10.0e6);
     std::vector<double> chan_widths(1, 3.0e6);
 
-    info.set(std::move(chan_freqs), std::move(chan_widths));
+    info.setChannels(std::move(chan_freqs), std::move(chan_widths));
     predict_->setInfo(info);
   }
 
diff --git a/steps/test/unit/tPSet.cc b/steps/test/unit/tPSet.cc
index 3569247af..9603cd17e 100644
--- a/steps/test/unit/tPSet.cc
+++ b/steps/test/unit/tPSet.cc
@@ -51,7 +51,7 @@ class TestInput : public dp3::steps::MockInput {
     for (int i = 0; i < nchan; i++) {
       chanFreqs.push_back(1050000. + i * 100000.);
     }
-    info().set(std::move(chanFreqs), std::move(chanWidth));
+    info().setChannels(std::move(chanFreqs), std::move(chanWidth));
   }
 
  private:
diff --git a/steps/test/unit/tPhaseShift.cc b/steps/test/unit/tPhaseShift.cc
index 8160815b9..1630c2791 100644
--- a/steps/test/unit/tPhaseShift.cc
+++ b/steps/test/unit/tPhaseShift.cc
@@ -52,7 +52,7 @@ class TestInput : public dp3::steps::MockInput {
     for (int i = 0; i < nchan; i++) {
       chanFreqs.push_back(1050000. + i * 100000.);
     }
-    info().set(std::move(chanFreqs), std::move(chanWidth));
+    info().setChannels(std::move(chanFreqs), std::move(chanWidth));
     // Fill the baseline stations.
     // Determine nr of stations using:  na*(na+1)/2 = nbl
     // If many baselines, divide into groups of 6 to test if
diff --git a/steps/test/unit/tPreFlagger.cc b/steps/test/unit/tPreFlagger.cc
index dbd17b556..923bb59ed 100644
--- a/steps/test/unit/tPreFlagger.cc
+++ b/steps/test/unit/tPreFlagger.cc
@@ -97,7 +97,7 @@ class TestInput : public dp3::steps::MockInput {
     for (int i = 0; i < nchan; i++) {
       chanFreqs.push_back(1050000. + i * 100000.);
     }
-    info().set(std::move(chanFreqs), std::move(chanWidth));
+    info().setChannels(std::move(chanFreqs), std::move(chanWidth));
   }
 
  private:
diff --git a/steps/test/unit/tPyStep.cc b/steps/test/unit/tPyStep.cc
index 952192ed7..3d393e8cd 100644
--- a/steps/test/unit/tPyStep.cc
+++ b/steps/test/unit/tPyStep.cc
@@ -75,7 +75,7 @@ class TestInput final : public steps::MockInput {
     for (int i = 0; i < kNChannels; i++) {
       chan_freqs.push_back(1050000. + i * 100000.);
     }
-    info().set(std::move(chan_freqs), std::move(chan_width));
+    info().setChannels(std::move(chan_freqs), std::move(chan_width));
   }
   int count_;
 };
diff --git a/steps/test/unit/tScaleData.cc b/steps/test/unit/tScaleData.cc
index e882b1615..6315d8932 100644
--- a/steps/test/unit/tScaleData.cc
+++ b/steps/test/unit/tScaleData.cc
@@ -86,7 +86,7 @@ class TestInput : public dp3::steps::MockInput {
     for (int i = 0; i < nchan; i++) {
       chanFreqs.push_back((kBaseFreq + i) * 1e6);
     }
-    info().set(std::move(chanFreqs), std::move(chanWidth));
+    info().setChannels(std::move(chanFreqs), std::move(chanWidth));
   }
 
  private:
diff --git a/steps/test/unit/tScaleDataBDA.cc b/steps/test/unit/tScaleDataBDA.cc
index b911afe11..87fb5f431 100644
--- a/steps/test/unit/tScaleDataBDA.cc
+++ b/steps/test/unit/tScaleDataBDA.cc
@@ -85,7 +85,7 @@ DPInfo GenerateDPInfo(int ntime, int nbl, int nchan, int ncorr) {
   // Define the frequencies.
   std::vector<double> chan_width(nchan, 1e6);
   std::vector<double> chan_freqs(nchan, kFreq * 1e6);
-  info.set(std::move(chan_freqs), std::move(chan_width));
+  info.setChannels(std::move(chan_freqs), std::move(chan_width));
 
   return info;
 }
diff --git a/steps/test/unit/tStationAdder.cc b/steps/test/unit/tStationAdder.cc
index b47d9e771..82cc3fb8c 100644
--- a/steps/test/unit/tStationAdder.cc
+++ b/steps/test/unit/tStationAdder.cc
@@ -92,7 +92,7 @@ class TestInput : public dp3::steps::MockInput {
     for (int i = 0; i < nchan; i++) {
       chanFreqs.push_back(10500000. + i * 1000000.);
     }
-    info().set(std::move(chanFreqs), std::move(chanWidth));
+    info().setChannels(std::move(chanFreqs), std::move(chanWidth));
   }
 
  private:
diff --git a/steps/test/unit/tUVWFlagger.cc b/steps/test/unit/tUVWFlagger.cc
index 29cb00bee..17e66ba7b 100644
--- a/steps/test/unit/tUVWFlagger.cc
+++ b/steps/test/unit/tUVWFlagger.cc
@@ -181,7 +181,7 @@ void TestInput<DPBuffer>::updateInfo(const DPInfo&) {
     channel_frequencies.push_back(start_frequency_ +
                                   (i + 0.5) * min_channel_width_);
   }
-  info().set(std::move(channel_frequencies), std::move(channel_widths));
+  info().setChannels(std::move(channel_frequencies), std::move(channel_widths));
 }
 
 template <>
@@ -208,7 +208,7 @@ void TestInput<std::unique_ptr<BDABuffer>>::updateInfo(const DPInfo&) {
     }
   }
 
-  info().set(std::move(channel_frequencies), std::move(channel_widths));
+  info().setChannels(std::move(channel_frequencies), std::move(channel_widths));
 }
 
 // Class to check result of flagged, unaveraged TestInput run by test1.
diff --git a/steps/test/unit/tUpsample.cc b/steps/test/unit/tUpsample.cc
index 81cf3eede..6715fe950 100644
--- a/steps/test/unit/tUpsample.cc
+++ b/steps/test/unit/tUpsample.cc
@@ -90,7 +90,7 @@ class TestInput : public dp3::steps::MockInput {
     for (unsigned int i = 0; i < kNChannels; i++) {
       chan_freqs.push_back(1050000. + i * 100000.);
     }
-    info().set(std::move(chan_freqs), std::move(chan_width));
+    info().setChannels(std::move(chan_freqs), std::move(chan_width));
 
     // Define antennas and baselines.
     const std::vector<std::string> kAntNames{"ant0", "ant1", "ant2"};
-- 
GitLab