From a1e89605d6e9ab03505a4d92e4a91c753d2c5899 Mon Sep 17 00:00:00 2001
From: Marcel Loose <loose@astron.nl>
Date: Fri, 21 Jul 2006 09:57:13 +0000
Subject: [PATCH] BugID: 753

* Updated the BBSStep family and BBSStrategy classes to reflect the latest
  proposed changes to the parset file. Most notably, a BBSStep now "inherits"
  initial values for its data member from its parent.

* Several nested structs were pulled out of the encapsulating class and put in
  a separate file, because it resulted in too much code duplication.
---
 .../include/BBSControl/BBSMultiStep.h         |  14 +-
 .../include/BBSControl/BBSSingleStep.h        |  36 +++-
 .../include/BBSControl/BBSSolveStep.h         |  80 +++++++++
 .../BBSControl/include/BBSControl/BBSStep.h   |  88 +++++++---
 .../include/BBSControl/BBSStrategy.h          |  68 ++------
 .../include/BBSControl/BBSStructs.h           | 119 +++++++++++++
 .../BBSControl/include/BBSControl/Makefile.am |   3 +
 .../include/BBSControl/StreamFormatting.h     |  87 ++++++++++
 CEP/BB/BBSControl/src/BBS.cc                  |  16 +-
 CEP/BB/BBSControl/src/BBSMultiStep.cc         |  13 +-
 CEP/BB/BBSControl/src/BBSSingleStep.cc        |  22 ++-
 CEP/BB/BBSControl/src/BBSSolveStep.cc         | 102 ++++++++++++
 CEP/BB/BBSControl/src/BBSStep.cc              | 156 +++++++++++++-----
 CEP/BB/BBSControl/src/BBSStrategy.cc          |  88 ++++------
 CEP/BB/BBSControl/src/BBSStructs.cc           | 105 ++++++++++++
 CEP/BB/BBSControl/src/Makefile.am             |   3 +
 CEP/BB/BBSControl/src/StreamFormatting.cc     |  38 +++++
 CEP/BB/BBSControl/test/tBBSControl.parset     |  39 +----
 CEP/BB/BBSControl/test/tBBSStrategy.parset    |  39 +----
 19 files changed, 850 insertions(+), 266 deletions(-)
 create mode 100644 CEP/BB/BBSControl/include/BBSControl/BBSSolveStep.h
 create mode 100644 CEP/BB/BBSControl/include/BBSControl/BBSStructs.h
 create mode 100644 CEP/BB/BBSControl/include/BBSControl/StreamFormatting.h
 create mode 100644 CEP/BB/BBSControl/src/BBSSolveStep.cc
 create mode 100644 CEP/BB/BBSControl/src/BBSStructs.cc
 create mode 100644 CEP/BB/BBSControl/src/StreamFormatting.cc

diff --git a/CEP/BB/BBSControl/include/BBSControl/BBSMultiStep.h b/CEP/BB/BBSControl/include/BBSControl/BBSMultiStep.h
index da274e68fb6..0b268d15bb8 100644
--- a/CEP/BB/BBSControl/include/BBSControl/BBSMultiStep.h
+++ b/CEP/BB/BBSControl/include/BBSControl/BBSMultiStep.h
@@ -1,4 +1,4 @@
-//# BBSMultiStep.h: A sequence of BBSSteps.
+//# BBSMultiStep.h: Derived composite class of the BBSStep composite pattern.
 //#
 //# Copyright (C) 2006
 //# ASTRON (Netherlands Foundation for Research in Astronomy)
@@ -24,7 +24,7 @@
 #define LOFAR_BBSCONTROL_BBSMULTISTEP_H
 
 // \file
-// The properties for solvable parameters
+// Derived composite class of the BBSStep composite pattern.
 
 //# Includes
 #include <BBSControl/BBSStep.h>
@@ -37,20 +37,20 @@ namespace LOFAR
     // \addtogroup BBS
     // @{
 
+    // This is the so-called \e composite class in the composite pattern (see
+    // Gamma, 1995). The composite class contains pointers to zero or more
+    // BBSStep (component) objects.
     class BBSMultiStep : public BBSStep
     {
     public:
       BBSMultiStep(const string& name,
-		   const ACC::APS::ParameterSet& parset);
+		   const ACC::APS::ParameterSet& parset,
+		   const BBSStep* parent);
 
       virtual ~BBSMultiStep();
 
       virtual void print(ostream& os) const;
 
-//       virtual BBSMultiStep* getMultiStep() { return this; }
-
-//       virtual void addStep(const BBSStep*& aStep);
-
     private:
       // Vector holding a sequence of BBSSteps.
       vector<const BBSStep*> itsSteps;
diff --git a/CEP/BB/BBSControl/include/BBSControl/BBSSingleStep.h b/CEP/BB/BBSControl/include/BBSControl/BBSSingleStep.h
index 8d5cda9867e..cb62848bb5b 100644
--- a/CEP/BB/BBSControl/include/BBSControl/BBSSingleStep.h
+++ b/CEP/BB/BBSControl/include/BBSControl/BBSSingleStep.h
@@ -1,4 +1,4 @@
-//# BBSSingleStep.h: The properties for solvable parameters
+//# BBSSingleStep.h: Derived leaf class of the BBSStep composite pattern.
 //#
 //# Copyright (C) 2006
 //# ASTRON (Netherlands Foundation for Research in Astronomy)
@@ -24,7 +24,7 @@
 #define LOFAR_BBSCONTROL_BBSSINGLESTEP_H
 
 // \file
-// The properties for solvable parameters
+// Derived leaf class of the BBSStep composite pattern.
 
 //# Includes
 #include <BBSControl/BBSStep.h>
@@ -33,29 +33,47 @@ namespace LOFAR
 {
   namespace BBS
   {
-    //# Forward Declarations.
-    class DataSelection;
-    class SourceGroup;
-
     // \addtogroup BBS
     // @{
 
+    // This is a so-called \e leaf class in the BBSStep composite pattern (see
+    // Gamma, 1995).
+    // \note %BBSSingleStep not implemented as a leaf class; it contains a
+    // number of data members that are common to "real" BBSStep leaf classes,
+    // like BBSSolveStep.
     class BBSSingleStep : public BBSStep
     {
     public:
+      // Construct a BBSSingleStep having the name \a name. Configuration
+      // information for this step can be retrieved from the parameter set \a
+      // parset, by searching for keys <tt>Step.\a name</tt>. \a parent
+      // is a pointer to the BBSStep object that is the parent of \c *this.
       BBSSingleStep(const string& name,
-		    const ACC::APS::ParameterSet& parset);
+		    const ACC::APS::ParameterSet& parset,
+		    const BBSStep* parent);
 
       virtual ~BBSSingleStep();
 
+      // Print the contents of \c *this in human readable form.
       virtual void print(ostream& os) const;
 
     private:
+      // Name of the data column to write data to
+      string          itsOutputData;
 
-//       DataSelection       itsDataSelection;
-//       vector<SourceGroup> itsSourceGroups;
     };
 
+    // For the time being we'll define the following steps as typedefs. If,
+    // and when, they need to be "upgraded" to a real class, we can do so,
+    // without affecting code referring to these types.
+    // @{
+    typedef BBSSingleStep BBSSubtractStep;
+    typedef BBSSingleStep BBSCorrectStep;
+    typedef BBSSingleStep BBSPredictStep;
+    typedef BBSSingleStep BBSShiftStep;
+    typedef BBSSingleStep BBSRefitStep;
+    // @}
+
     // @}
     
   } // namespace BBS
diff --git a/CEP/BB/BBSControl/include/BBSControl/BBSSolveStep.h b/CEP/BB/BBSControl/include/BBSControl/BBSSolveStep.h
new file mode 100644
index 00000000000..de7eee6d386
--- /dev/null
+++ b/CEP/BB/BBSControl/include/BBSControl/BBSSolveStep.h
@@ -0,0 +1,80 @@
+//# BBSSolveStep.h: The properties for solvable parameters
+//#
+//# Copyright (C) 2006
+//# ASTRON (Netherlands Foundation for Research in Astronomy)
+//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.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
+//#
+//# $Id$
+
+#ifndef LOFAR_BBSCONTROL_BBSSOLVESTEP_H
+#define LOFAR_BBSCONTROL_BBSSOLVESTEP_H
+
+// \file
+// The properties for solvable parameters
+
+//# Includes
+#include <BBSControl/BBSSingleStep.h>
+#include <Common/LofarTypes.h>
+#include <Common/lofar_vector.h>
+#include <Common/lofar_string.h>
+
+namespace LOFAR
+{
+  namespace BBS
+  {
+    // \addtogroup BBS
+    // @{
+
+    class BBSSolveStep : public BBSSingleStep
+    {
+    public:
+      BBSSolveStep(const string& name,
+		   const ACC::APS::ParameterSet& parset,
+		   const BBSStep* parent);
+
+      virtual ~BBSSolveStep();
+
+      virtual void print(ostream& os) const;
+
+    private:
+      // Solve domain size.
+      struct DomainSize
+      {
+	double bandWidth;           ///< Bandwidth in Hz.
+	double timeInterval;        ///< Time interval in seconds.
+      };
+      uint32 itsMaxIter;            ///< Maximum number of iterations
+      double itsEpsilon;            ///< Convergence threshold
+      double itsMinConverged;       ///< Fraction that must have converged
+      vector<string> itsParms;      ///< Names of the solvable parameters
+      vector<string> itsExclParms;  ///< Parameters to be excluded from solve
+      DomainSize itsDomainSize;     ///< Solve domain size.
+
+      // Write the contents of a BBSSolveStep to an output stream.
+      friend ostream& operator<<(ostream&, const BBSSolveStep&);
+      friend ostream& operator<<(ostream&, const BBSSolveStep::DomainSize&);
+
+    };
+
+    // @}
+    
+  } // namespace BBS
+
+} // namespace LOFAR
+
+#endif
+
diff --git a/CEP/BB/BBSControl/include/BBSControl/BBSStep.h b/CEP/BB/BBSControl/include/BBSControl/BBSStep.h
index 9081f7d0cd0..62cf62e3c3a 100644
--- a/CEP/BB/BBSControl/include/BBSControl/BBSStep.h
+++ b/CEP/BB/BBSControl/include/BBSControl/BBSStep.h
@@ -1,4 +1,4 @@
-//# BBSStep.h: The properties for solvable parameters
+//# BBSStep.h: Base component class of the BBSStep composite pattern.
 //#
 //# Copyright (C) 2006
 //# ASTRON (Netherlands Foundation for Research in Astronomy)
@@ -24,9 +24,10 @@
 #define LOFAR_BBSCONTROL_BBSSTEP_H
 
 // \file
-// The properties for solvable parameters
+// Base component class of the BBSStep composite pattern.
 
 //# Includes
+#include <BBSControl/BBSStructs.h>
 #include <Common/lofar_string.h>
 #include <Common/lofar_vector.h>
 #include <Common/lofar_iosfwd.h>
@@ -45,62 +46,95 @@ namespace LOFAR
     // \addtogroup BBS
     // @{
 
+    // This is the so-called \e component class in the BBSStep composite
+    // pattern (see Gamma, 1995). It is the base class for all BBSStep
+    // classes, both composite and leaf classes. It has data members that are
+    // common to all BBSStep classes.
     class BBSStep
     {
     public:
 
+      // Destructor.
       virtual ~BBSStep();
 
-      // Return the name of \c this.
-      const string& name() const { return itsName; }
+      // Initialize the data members of the current BBSStep by looking up
+      // their key/value pairs in the given ParameterSet. If a key/value pair
+      // is not present, then the value will be that of the parent BBSStep
+      // object.
 
-      // Print the contents of \c this into the output stream \a os.
+      // Print the contents of \c *this in human readable form into the output
+      // stream \a os.
       virtual void print(ostream& os) const;
 
-//       // Return a pointer to the current BBSMultiStep. Since the base class is
-//       // not a BBSMultiStep, it will return a null pointer.
-//       virtual BBSMultiStep* getMultiStep() { return 0; }
+      // Return the name of this step.
+      const string& name() const { return itsName; }
 
-//       // Add a BBSStep to the current BBSStep.
-//       // \note You can \e only add a BBSStep to a BBSMultiStep. 
-//       // \throw AssertError if \c this is not an instance of BBSMultiStep.
-//       virtual void addStep(const BBSStep*& aStep);
+      // Return the full name of this step. The full name consists of the name
+      // of this step, preceeded by that of its parent, etc., separated by
+      // dots.
+      string fullName() const;
 
       // Create a new step object. The new step can either be a BBSSingleStep
       // or a BBSMultiStep object. This is determined by examining the
       // parameter set \a parSet. If this set contains a key
       // <tt>Step.<em>name</em>.Steps</tt>, then \a aName is a BBSMultiStep,
-      // otherwise it is a SingleStep.
+      // otherwise it is a SingleStep. The third, optional, argument is used
+      // to pass a backreference to the parent BBSStep object.
       static BBSStep* create(const string& name,
-			     const ACC::APS::ParameterSet& parSet);
+			     const ACC::APS::ParameterSet& parSet,
+			     const BBSStep* parent = 0);
 
     protected:
+      // Construct a BBSStep. \a name identifies the step name in the
+      // parameter set file. It does \e not uniquely identify the step \e
+      // object being created. The third argument is used to pass a
+      // backreference to the parent BBSStep object.
       BBSStep(const string& name, 
-	      const ACC::APS::ParameterSet& parSet);
+	      const ACC::APS::ParameterSet& parSet,
+	      const BBSStep* parent);
 
     private:
-      // This struct contains two vectors of stations ID's, which, when paired
-      // element-wise, define the baselines to be used in the current step.
-      struct Selection
-      {
-	vector<uint32> station1;
-	vector<uint32> station2;
-      };
+      // Override the default values, "inherited" from the parent step object,
+      // for those members that are specified in \a parSet.
+      void setParms(const ACC::APS::ParameterSet& parSet);
 
       // Name of this step.
       string                 itsName;
 
+      // Pointer to the parent of \c *this. All BBSStep objects have a parent,
+      // except the top-level BBSStep object. The parent reference is used,
+      // among other things, to initialize the data members of the child
+      // object with those of its parent.
+      const BBSStep*         itsParent;
+
       // Selection of baselines for this step.
-      Selection              itsSelection;
+      Baselines              itsBaselines;
+
+      // Parameters describing which correlation products for which
+      // polarizations should be used for this step.
+      Correlation            itsCorrelation;
 
-      // The sources in the source model.
+      // Parameters describing the amount of integration that must be applied
+      // to the data. Integration can be useful to decrease the amount of
+      // data.
+      Integration            itsIntegration;
+
+      // The sources in the source model for the current patch.
       vector<string>         itsSources;
 
-      // Write the contents of a BBSStep to an output stream.
-      friend ostream& operator<<(ostream&, const BBSStep&);
-      friend ostream& operator<<(ostream&, const BBSStep::Selection&); 
+      // Extra sources outside the current patch that may contribute to the
+      // current patch. They should be taken into account in order to improve
+      // the predictions of source parameters for the current patch.
+      vector<string>         itsExtraSources;
+
+      // A list of instrument models to be used for this step.
+      vector<string>         itsInstrumentModels;
+
     };
 
+    // Write the contents of a BBSStep to an output stream.
+    ostream& operator<<(ostream&, const BBSStep&);
+
     // @}
     
   } // namespace BBS
diff --git a/CEP/BB/BBSControl/include/BBSControl/BBSStrategy.h b/CEP/BB/BBSControl/include/BBSControl/BBSStrategy.h
index fd2df1ffaaa..b32fd9ce376 100644
--- a/CEP/BB/BBSControl/include/BBSControl/BBSStrategy.h
+++ b/CEP/BB/BBSControl/include/BBSControl/BBSStrategy.h
@@ -27,6 +27,7 @@
 // The properties for solvable parameters
 
 //# Includes
+#include <BBSControl/BBSStructs.h>
 #include <APS/ParameterSet.h>
 #include <Common/lofar_iosfwd.h>
 #include <Common/lofar_string.h>
@@ -60,69 +61,30 @@ namespace LOFAR
 
     private:
 
-      // The relevant strategy parameters.
-      struct Parameters
-      {
-	string dataBase;	///< name of the parameter database 
-	string instrument;	///< Instrument parameters (MS table)
-	string localSky;	///< Local sky parameters (MS table)
-	string inData;		///< MS column containing the input data
-      };
-
-      // The work domain size is defined by two parameters: bandwidth f(Hz),
-      // and time interval t(s).
-      struct WorkDomainSize
-      {
-	WorkDomainSize() : bandWidth(0), timeInterval(0) {}
-	void print(ostream& os) const;
-	double bandWidth;	///< Bandwidth in Hz.
-	double timeInterval;	///< Time interval is seconds.
-      };
-
-      // Selection type of the correlation products.
-      struct Selection
-      {
-	enum Corr{
-	  ALL,                  ///< Both auto- and cross correlation
-	  CROSS,                ///< Cross correlation only.
-	  AUTO                  ///< Auto correlation only.
-	} corr;
-	Selection(Corr c = ALL) : corr(c) {}
-      };
-
-
-      // Information about the Blackboard database.
-      struct BBDB
-      {
-	BBDB() : port(0) {}
-	string host;          ///< Host name or IP address
-	uint16 port;          ///< Port number
-      };
+      // Name of the Measurement Set
+      string                 itsDataSet;
 
-      // Sequence of steps that comprise this solve strategy.
-      vector<const BBSStep*> itsSteps;
+      // Information about the blackboard database.
+      BBDB                   itsBBDB;
 
-      // ID's of the stations to use
-      vector<uint32>         itsStations;
+      // Information about the parameter database.
+      ParmDB                 itsParmDB;
 
       // The work domain size
-      WorkDomainSize         itsDomainSize;
+      DomainSize             itsDomainSize;
       
-      // Name of the Measurement Set
-      string                 itsDataSet;
-
       // Selection type of the correlation products.
-      Selection              itsSelection;
+      Correlation            itsCorrelation;
 
-      // Host name of the BlackBoard DataBase.
-      BBDB                   itsBBDB;
+      // ID's of the stations to use
+      vector<uint32>         itsStations;
+
+      // Sequence of steps that comprise this solve strategy.
+      vector<const BBSStep*> itsSteps;
 
       // Write the contents of a BBSStrategy to an output stream.
       friend ostream& operator<<(ostream&, const BBSStrategy&);
-      friend ostream& operator<<(ostream&, const BBSStrategy::WorkDomainSize&);
-      friend ostream& operator<<(ostream&, const BBSStrategy::Selection&);
-      friend ostream& operator<<(ostream&, const BBSStrategy::BBDB&);
-      
+
     };
 
     // @}
diff --git a/CEP/BB/BBSControl/include/BBSControl/BBSStructs.h b/CEP/BB/BBSControl/include/BBSControl/BBSStructs.h
new file mode 100644
index 00000000000..bf7c08dcc0c
--- /dev/null
+++ b/CEP/BB/BBSControl/include/BBSControl/BBSStructs.h
@@ -0,0 +1,119 @@
+//# BBSStructs.h: Some global structs.
+//#
+//# Copyright (C) 2006
+//# ASTRON (Netherlands Foundation for Research in Astronomy)
+//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.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
+//#
+//# $Id$
+
+#ifndef LOFAR_BBSCONTROL_BBSSTRUCTS_H
+#define LOFAR_BBSCONTROL_BBSSTRUCTS_H
+
+// \file
+// Some global structs. The main purpose of these structs is to bundle data
+// that are logically related. Most of these structs are used in more than one
+// class, which justifies them being defined here, outside these classes.
+
+//# Includes
+#include <Common/LofarTypes.h>
+#include <Common/lofar_string.h>
+#include <Common/lofar_vector.h>
+
+namespace LOFAR
+{
+  namespace BBS
+  {
+    // \addtogroup BBS
+    // @{
+
+    // Information about the Blackboard database.
+    struct BBDB
+    {
+      BBDB() : port(0) {}
+      string host;          ///< Host name or IP address of the BB DBMS
+      uint16 port;          ///< Port used by BB DBMS
+      string dbName;        ///< Name of the BB database
+      string username;      ///< Username for accessing the DBMS
+      string password;      ///< Password for accessing the DBMS
+    };
+
+    // Information about the parameter database.
+    // \note These are currently AIPS++ MS tables.
+    struct ParmDB
+    {
+      string instrument;    ///< Instrument parameters (MS table)
+      string localSky;	    ///< Local sky parameters (MS table)
+    };
+
+    // Domain size is defined by two parameters: bandwidth f(Hz), and time
+    // interval t(s).
+    struct DomainSize
+    {
+      DomainSize() : bandWidth(0), timeInterval(0) {}
+      double bandWidth;	    ///< Bandwidth in Hz.
+      double timeInterval;  ///< Time interval is seconds.
+    };
+
+    // Information about which correlation products (auto, cross, or both),
+    // and which polarizations should be used.
+    struct Correlation
+    {
+      Correlation() : selection(NONE) {}
+      enum Selection {
+	NONE,               ///< No correlations
+	AUTO,               ///< Auto correlation only.
+	CROSS,              ///< Cross correlation only.
+	ALL                 ///< Both auto- and cross correlation
+      } selection;
+      vector<string> type;  ///< E.g., ["XX", "XY", "YX", "YY"]
+    };
+
+    // Sizes of the integration intervals, when applied. Integration can be
+    // performed along the frequency axis and the time axis.q
+    struct Integration
+    {
+      Integration() : deltaFreq(0), deltaTime(0) {}
+      double deltaFreq;     ///< frequency integration interval: f(Hz)
+      double deltaTime;     ///< time integration interval: t(s)
+    };
+
+    // Two vectors of stations ID's, which, when paired element-wise, define
+    // the baselines to be used in the current step.
+    struct Baselines
+    {
+      vector<uint32> station1;
+      vector<uint32> station2;
+    };
+
+
+    // Write the contents of these structs in human readable form.
+    // @{
+    ostream& operator<<(ostream&, const BBDB&);
+    ostream& operator<<(ostream&, const ParmDB&);
+    ostream& operator<<(ostream&, const DomainSize&);
+    ostream& operator<<(ostream&, const Correlation&);
+    ostream& operator<<(ostream&, const Integration&);
+    ostream& operator<<(ostream&, const Baselines&);
+    // @}
+
+    // @}
+    
+  } // namespace BBS
+
+} // namespace LOFAR
+
+#endif
diff --git a/CEP/BB/BBSControl/include/BBSControl/Makefile.am b/CEP/BB/BBSControl/include/BBSControl/Makefile.am
index 7f592b2cede..df7da27623a 100644
--- a/CEP/BB/BBSControl/include/BBSControl/Makefile.am
+++ b/CEP/BB/BBSControl/include/BBSControl/Makefile.am
@@ -1,8 +1,10 @@
 pkginclude_HEADERS = \
 	BBSStep.h \
 	BBSSingleStep.h \
+	BBSSolveStep.h \
 	BBSMultiStep.h \
 	BBSStrategy.h \
+	BBSStructs.h \
 	BlackBoardDemo.h \
 	BlobAipsIO.h \
 	DH_Prediff.h \
@@ -14,6 +16,7 @@ pkginclude_HEADERS = \
 	SC_Simple.h \
 	SC_WritePredData.h \
 	StrategyController.h \
+	StreamFormatting.h \
 	WH_Control.h \
 	WH_Prediff.h \
 	WH_Solve.h
diff --git a/CEP/BB/BBSControl/include/BBSControl/StreamFormatting.h b/CEP/BB/BBSControl/include/BBSControl/StreamFormatting.h
new file mode 100644
index 00000000000..3a3d0bfe99e
--- /dev/null
+++ b/CEP/BB/BBSControl/include/BBSControl/StreamFormatting.h
@@ -0,0 +1,87 @@
+//#  StreamFormatting.h: useful stream formatting methods.
+//#
+//#  Copyright (C) 2002-2003
+//#  ASTRON (Netherlands Foundation for Research in Astronomy)
+//#  P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.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
+//#
+//#  $Id$
+
+#ifndef LOFAR_BBSCONTROL_STREAMFORMATTING_H
+#define LOFAR_BBSCONTROL_STREAMFORMATTING_H
+
+// \file
+// Useful stream formatting methods.
+
+//# Includes
+#include <Common/LofarTypes.h>
+#include <Common/lofar_string.h>
+#include <Common/lofar_vector.h>
+#include <Common/lofar_iosfwd.h>
+
+namespace LOFAR
+{
+  namespace BBS
+  {
+    // Handles indentation of text lines. Every time an Indent object is
+    // constructed, the static member \c level is incremented by one, and
+    // every time an Indent object is destructed \c level is decremented by
+    // one. To increment the amount of indentation you simply create an Indent
+    // object. When this object goes out of scope, the amount of indentation
+    // is automagically decremented.
+    class Indent {
+    public:
+      // Constructor. Increments indentation level.
+      Indent() { lvl++; }
+      // Destructor. Decrements indentation level.
+      ~Indent() { lvl--; }
+      // Return the amount of indentation.
+      static uint level() { return lvl; }
+      // Return the token to be printed per indentation level
+      static const string& token() { return tok; }
+    private:
+      // Indentation level.
+      static uint lvl;
+      // Token to be printed per indentation level.
+      static const string tok;
+    };
+
+
+    // Print an indentation that depends on the number of Indent objects
+    // currently in existence.
+    inline ostream& indent(ostream& os) 
+    {
+      for (uint i = 0; i < Indent::level(); ++i) os << Indent::token();
+      return os;
+    }
+
+
+    // Print the contents of a vector of \c T. 
+    // \note operator<<() must be defined for type \c T.
+    template<typename T>
+    inline ostream& operator<<(ostream& os, const vector<T>& v)
+    {
+      os << "[";
+      for (uint i = 0; i < v.size(); ++i) os << " " << v[i];
+      os << " ]";
+      return os;
+    }
+
+  } // namespace BBS
+
+} // namespace LOFAR
+
+#endif
diff --git a/CEP/BB/BBSControl/src/BBS.cc b/CEP/BB/BBSControl/src/BBS.cc
index b50f0a7e7cb..55f3bd2375c 100644
--- a/CEP/BB/BBSControl/src/BBS.cc
+++ b/CEP/BB/BBSControl/src/BBS.cc
@@ -23,15 +23,14 @@
 #include <lofar_config.h>
 
 #include <BBSControl/BlackBoardDemo.h>
+#include <BBS/BBSTestLogger.h>
 #include <MS/MSDesc.h>
+
 #ifdef HAVE_MPI
-#include <Transport/TH_MPI.h>
+# include <Transport/TH_MPI.h>
 #endif
-#include <Blob/KeyParser.h>
-#include <string>
-#include <iostream>
-#include <fstream>
 
+#include <Blob/KeyParser.h>
 #include <Blob/BlobOBufChar.h>
 #include <Blob/BlobIBufChar.h>
 #include <Blob/BlobOStream.h>
@@ -39,13 +38,14 @@
 #include <Blob/BlobIBufStream.h>
 #include <Blob/BlobArray.h>
 
+#include <Common/lofar_string.h>
+#include <Common/lofar_iostream.h>
+#include <Common/lofar_fstream.h>
+
 #include <casa/Arrays/Matrix.h>
 #include <casa/Quanta/MVTime.h>
 
-#include <BBS/BBSTestLogger.h>
-
 using namespace LOFAR;
-using namespace std;
 using namespace casa;
 
 // This program should be called with input file name(1) and user name(2) as
diff --git a/CEP/BB/BBSControl/src/BBSMultiStep.cc b/CEP/BB/BBSControl/src/BBSMultiStep.cc
index 93de7ab0922..db448e75315 100644
--- a/CEP/BB/BBSControl/src/BBSMultiStep.cc
+++ b/CEP/BB/BBSControl/src/BBSMultiStep.cc
@@ -25,7 +25,7 @@
 #include <BBSControl/BBSMultiStep.h>
 #include <APS/ParameterSet.h>
 #include <Common/LofarLogger.h>
-#include <Common/StreamUtil.h>
+#include <BBSControl/StreamFormatting.h>
 
 namespace LOFAR
 {
@@ -35,8 +35,9 @@ namespace LOFAR
   {
     
     BBSMultiStep::BBSMultiStep(const string& name,
-			       const ParameterSet& parset) :
-      BBSStep(name, parset)
+			       const ParameterSet& parset,
+			       const BBSStep* parent) :
+      BBSStep(name, parset, parent)
     {
       LOG_TRACE_FLOW(AUTO_FUNCTION_NAME);
 
@@ -45,7 +46,7 @@ namespace LOFAR
 
       // Create a new step for each name in \a steps.
       for (uint i = 0; i < steps.size(); ++i) {
-	itsSteps.push_back(BBSStep::create(steps[i], parset));
+	itsSteps.push_back(BBSStep::create(steps[i], parset, this));
       }
     }
 
@@ -65,9 +66,9 @@ namespace LOFAR
     void BBSMultiStep::print(ostream& os) const
     {
       BBSStep::print(os);
-      Indent id;  // Add one indentation level
+      Indent id;
       for (uint i = 0; i < itsSteps.size(); ++i) {
-	itsSteps[i]->print(os);
+	os << endl << indent << *itsSteps[i];
       }
     }
 
diff --git a/CEP/BB/BBSControl/src/BBSSingleStep.cc b/CEP/BB/BBSControl/src/BBSSingleStep.cc
index 8c163ad3008..d411671b854 100644
--- a/CEP/BB/BBSControl/src/BBSSingleStep.cc
+++ b/CEP/BB/BBSControl/src/BBSSingleStep.cc
@@ -23,19 +23,31 @@
 #include <lofar_config.h>
 
 #include <BBSControl/BBSSingleStep.h>
+#include <BBSControl/Exceptions.h>
+#include <APS/ParameterSet.h>
 #include <Common/LofarLogger.h>
-#include <Common/StreamUtil.h>
+#include <BBSControl/StreamFormatting.h>
 
 namespace LOFAR
 {
   namespace BBS
   {
+    using ACC::APS::ParameterSet;
+    using LOFAR::operator<<;
 
     BBSSingleStep::BBSSingleStep(const string& name, 
-				 const ACC::APS::ParameterSet& parset) :
-      BBSStep(name, parset)
+				 const ParameterSet& parset,
+				 const BBSStep* parent) :
+      BBSStep(name, parset, parent)
     {
       LOG_TRACE_FLOW(AUTO_FUNCTION_NAME);
+
+      // Create a subset of \a parset, containing only the relevant keys for
+      // the current BBSSingleStep.
+      ParameterSet ps(parset.makeSubset("Step." + name + "."));
+
+      // Get the name of the data column to write to
+      itsOutputData = ps.getString("OutputData");
     }
 
     BBSSingleStep::~BBSSingleStep()
@@ -46,10 +58,10 @@ namespace LOFAR
     void BBSSingleStep::print(ostream& os) const
     {
       BBSStep::print(os);
-      Indent id;  // Add one indentation level
+      Indent id;
+      os << endl << indent << "Output data: " << itsOutputData;
     }
 
-
   } // namespace BBS
 
 } // namespace LOFAR
diff --git a/CEP/BB/BBSControl/src/BBSSolveStep.cc b/CEP/BB/BBSControl/src/BBSSolveStep.cc
new file mode 100644
index 00000000000..8bd795323dd
--- /dev/null
+++ b/CEP/BB/BBSControl/src/BBSSolveStep.cc
@@ -0,0 +1,102 @@
+//#  BBSSolveStep.cc: 
+//#
+//#  Copyright (C) 2002-2004
+//#  ASTRON (Netherlands Foundation for Research in Astronomy)
+//#  P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.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
+//#
+//#  $Id$
+
+#include <lofar_config.h>
+
+#include <BBSControl/BBSSolveStep.h>
+#include <BBSControl/Exceptions.h>
+#include <APS/ParameterSet.h>
+#include <Common/LofarLogger.h>
+#include <BBSControl/StreamFormatting.h>
+
+namespace LOFAR
+{
+  namespace BBS
+  {
+    using ACC::APS::ParameterSet;
+    using LOFAR::operator<<;
+
+    BBSSolveStep::BBSSolveStep(const string& name, 
+			       const ParameterSet& parset,
+			       const BBSStep* parent) :
+      BBSSingleStep(name, parset, parent)
+    {
+      LOG_TRACE_FLOW(AUTO_FUNCTION_NAME);
+
+      // Create a subset of \a parset, containing only the relevant keys for
+      // the current BBSSingleStep.
+      ParameterSet ps(parset.makeSubset("Step." + name + ".Solve."));
+
+      // Get the relevant parameters from the Parameter Set \a parset. 
+      // \note A missing key is considered an error.
+      itsMaxIter                 = ps.getUint32("MaxIter");
+      itsEpsilon                 = ps.getDouble("Epsilon");
+      itsMinConverged            = ps.getDouble("MinConverged");
+      itsParms                   = ps.getStringVector("Parms");
+      itsExclParms               = ps.getStringVector("ExclParms");
+      itsDomainSize.bandWidth    = ps.getDouble("DomainSize.Freq");
+      itsDomainSize.timeInterval = ps.getDouble("DomainSize.Time");
+    }
+
+
+    BBSSolveStep::~BBSSolveStep()
+    {
+      LOG_TRACE_FLOW(AUTO_FUNCTION_NAME);
+    }
+
+
+    void BBSSolveStep::print(ostream& os) const
+    {
+      BBSSingleStep::print(os);
+      Indent id;
+      os << endl << indent << "Solve: ";
+      {
+	Indent id;
+	os << endl << indent << "Max nr. of iterations: "  << itsMaxIter
+	   << endl << indent << "Convergence threshold: "  << itsEpsilon
+	   << endl << indent << "Min fraction converged: " << itsMinConverged
+	   << endl << indent << "Solvable parameters: "    << itsParms
+	   << endl << indent << "Excluded parameters: "    << itsExclParms
+	   << endl << indent << itsDomainSize;
+      }
+    }
+
+
+    ostream& operator<<(ostream& os, const BBSSolveStep& bs)
+    {
+      bs.print(os);
+      return os;
+    }
+
+    ostream& operator<<(ostream& os, const BBSSolveStep::DomainSize& ds)
+    {
+      os << "Domain size: ";
+      Indent id;  // Add one indentation level
+      os << endl << indent << "Bandwidth: " << ds.bandWidth << " (Hz)"
+	 << endl << indent << "Time interval: " << ds.timeInterval << " (s)";
+      return os;
+    }
+
+
+  } // namespace BBS
+
+} // namespace LOFAR
diff --git a/CEP/BB/BBSControl/src/BBSStep.cc b/CEP/BB/BBSControl/src/BBSStep.cc
index 553de0822d1..997e5f94afb 100644
--- a/CEP/BB/BBSControl/src/BBSStep.cc
+++ b/CEP/BB/BBSControl/src/BBSStep.cc
@@ -25,85 +25,165 @@
 #include <BBSControl/BBSStep.h>
 #include <BBSControl/BBSSingleStep.h>
 #include <BBSControl/BBSMultiStep.h>
+#include <BBSControl/BBSSolveStep.h>
+#include <BBSControl/Exceptions.h>
 #include <APS/ParameterSet.h>
+#include <APS/Exceptions.h>
 #include <Common/LofarLogger.h>
-#include <Common/StreamUtil.h>
+#include <BBSControl/StreamFormatting.h>
 
 namespace LOFAR
 {
   using ACC::APS::ParameterSet;
+  using ACC::APS::APSException;
 
   namespace BBS
   {
-    using LOFAR::operator<<;
 
-    BBSStep::BBSStep(const string& name, const ParameterSet& parSet) :
-      itsName(name)
+    //##--------   P u b l i c   m e t h o d s   --------##//
+
+    BBSStep::~BBSStep()
     {
       LOG_TRACE_FLOW(AUTO_FUNCTION_NAME);
+    }
 
-      // Create a subset of \a aParSet, containing only the relevant keys for
-      // the current BBSStep.
-      ParameterSet ps(parSet.makeSubset("Step." + name + "."));
-
-      // Get the baseline selection for this step.
-      itsSelection.station1 = ps.getUint32Vector("Selection.Station1");
-      itsSelection.station2 = ps.getUint32Vector("Selection.Station2");
 
-      // Get the sources for the current source model.
-      itsSources = ps.getStringVector("Sources");
+    void BBSStep::print(ostream& os) const
+    {
+      os << "Step: " << itsName;
+      Indent id;  // add an extra indentation level
+      os << endl << indent << "Full name: " << fullName()
+	 << endl << indent << itsBaselines
+	 << endl << indent << itsCorrelation
+	 << endl << indent << itsIntegration
+	 << endl << indent << "Sources: " << itsSources
+	 << endl << indent << "Extra sources: " << itsExtraSources
+	 << endl << indent << "Instrument models: " << itsInstrumentModels;
     }
 
 
-    BBSStep::~BBSStep()
+    string BBSStep::fullName() const
     {
-      LOG_TRACE_FLOW(AUTO_FUNCTION_NAME);
+      string name;
+      if (itsParent) name = itsParent->fullName() + ".";
+      name += itsName;
+      return name;
     }
 
-//     void BBSStep::addStep(const BBSStep*&)
-//     {
-//       ASSERTSTR(false, "A BBSStep can only be added to a BBSMultiStep");
-//     }
-
 
     BBSStep* BBSStep::create(const string& name,
-			     const ParameterSet& parSet)
+			     const ParameterSet& parset,
+			     const BBSStep* parent)
     {
       LOG_TRACE_FLOW(AUTO_FUNCTION_NAME);
 
-      // If \a parSet contains a key <tt>Step.<em>name</em>.Steps</tt>, then
+      // If \a parset contains a key <tt>Step.<em>name</em>.Steps</tt>, then
       // \a name is a BBSMultiStep, otherwise it is a SingleStep.
-      if (parSet.isDefined("Step." + name + ".Steps")) {
+      if (parset.isDefined("Step." + name + ".Steps")) {
 	LOG_TRACE_COND_STR(name << " is a MultiStep");
-	return new BBSMultiStep(name, parSet);
+	return new BBSMultiStep(name, parset, parent);
       } else {
 	LOG_TRACE_COND_STR(name << " is a SingleStep");
-	return new BBSSingleStep(name, parSet);
+	// We'll have to figure out what kind of SingleStep we must
+	// create. The key "Operation" contains this information.
+	string oper = toUpper(parset.getString("Step." + name + ".Operation"));
+	LOG_TRACE_COND_STR("Creating a " << oper << " step ...");
+	if      (oper == "SOLVE")
+	  return new BBSSolveStep(name, parset, parent);
+	else if (oper == "SUBTRACT")
+	  return new BBSSubtractStep(name, parset, parent);
+	else if (oper == "CORRECT")
+	  return new BBSCorrectStep(name, parset, parent);
+	else if (oper == "PREDICT")
+	  return new BBSPredictStep(name, parset, parent);
+	else if (oper == "SHIFT")
+	  return new BBSShiftStep(name, parset, parent);
+	else if (oper == "REFIT")
+	  return new BBSRefitStep(name, parset, parent);
+	else THROW (BBSControlException, "Operation \"" << oper << 
+		    "\" is not a valid Step operation");
       }
     }
 
 
-    void BBSStep::print(ostream& os) const
+    //##--------   P r o t e c t e d   m e t h o d s   --------##//
+
+    BBSStep::BBSStep(const string& name, 
+		     const ParameterSet& parset,
+		     const BBSStep* parent)
     {
-      os << indent << "Step: " << itsName << endl;
-      Indent id;  // add an extra indentation level
-      os << itsSelection << endl
-	 << indent << "Sources: " << itsSources << endl;
+      LOG_TRACE_FLOW(AUTO_FUNCTION_NAME);
+
+      // Copy the data members from the parent, if present, so that they have
+      // sensible default values.
+      if (parent) *this = *parent;
+
+      // We must reset these values, because they were overwritten by the
+      // previous data copy.
+      itsName = name;
+      itsParent = parent;
+
+      // Overrride default values for data members of the current BBSStep, if
+      // they're specified in \a parset.
+      setParms(parset.makeSubset("Step." + name + "."));
+
     }
 
 
-    ostream& operator<<(ostream& os, const BBSStep& bs)
+    //##--------   P r i v a t e   m e t h o d s   --------##//
+
+    void BBSStep::setParms(const ParameterSet& ps)
     {
-      bs.print(os);
-      return os;
+      LOG_TRACE_FLOW(AUTO_FUNCTION_NAME);
+
+      // If defined, get the baseline selection for this step.
+      try {
+	itsBaselines.station1 = ps.getUint32Vector("Baselines.Station1");
+	itsBaselines.station2 = ps.getUint32Vector("Baselines.Station2");
+      } catch (APSException&) {}
+
+      // If defined, get the correlation selection (ALL, AUTO, or CROSS), and
+      // type (e.g., ["XX", "XY", "YX", "YY"]
+      try {
+	string sel = ps.getString("Correlation.Selection");
+	if      (sel == "ALL")   itsCorrelation.selection = Correlation::ALL;
+	else if (sel == "AUTO")  itsCorrelation.selection = Correlation::AUTO;
+	else if (sel == "CROSS") itsCorrelation.selection = Correlation::CROSS;
+	else THROW(BBSControlException, 
+		   "Invalid correlation selection " << sel);
+	itsCorrelation.type = ps.getStringVector("Correlation.Type");
+      } catch (APSException&) {}
+
+      // If defined, get the integration intervals in frequency (Hz) and
+      // time (s).
+      try {
+	itsIntegration.deltaFreq = ps.getDouble("Integration.Freq");
+	itsIntegration.deltaTime = ps.getDouble("Integration.Time");
+      } catch (APSException&) {}
+
+      // If defined, get the sources for the current patch.
+      try {
+	itsSources = ps.getStringVector("Sources");
+      } catch (APSException&) {}
+
+      // If defined, get the extra source, outside the current patch.
+      try {
+	itsExtraSources = ps.getStringVector("ExtraSources");
+      } catch (APSException&) {}
+
+      // If defined, get the instrument model(s) used.
+      try {
+	itsInstrumentModels = ps.getStringVector("InstrumentModel");
+      } catch (APSException&) {}
+
     }
 
-    ostream& operator<<(ostream& os, const BBSStep::Selection& sel)
+
+    //##--------   G l o b a l   m e t h o d s   --------##//
+
+    ostream& operator<<(ostream& os, const BBSStep& bs)
     {
-      os << indent << "Selection:" << endl;
-      Indent id;  // add an extra indentation level
-      os << indent << "Station1: " << sel.station1 << endl
-	 << indent << "Station2: " << sel.station2;
+      bs.print(os);
       return os;
     }
 
diff --git a/CEP/BB/BBSControl/src/BBSStrategy.cc b/CEP/BB/BBSControl/src/BBSStrategy.cc
index e11c4d8e57e..a0d7a4e810f 100644
--- a/CEP/BB/BBSControl/src/BBSStrategy.cc
+++ b/CEP/BB/BBSControl/src/BBSStrategy.cc
@@ -26,7 +26,7 @@
 #include <BBSControl/BBSStep.h>
 #include <BBSControl/Exceptions.h>
 #include <Common/LofarLogger.h>
-#include <Common/StreamUtil.h>
+#include <BBSControl/StreamFormatting.h>
 
 namespace LOFAR
 {
@@ -35,42 +35,25 @@ namespace LOFAR
   namespace BBS
   {
 
-    using LOFAR::operator<<;
+    //##--------   P u b l i c   m e t h o d s   --------##//
 
-    ostream& operator<<(ostream& os, const BBSStrategy::WorkDomainSize& wds)
-    {
-      os << indent << "Workdomain size:" << endl;
-      Indent id;  // add an indentation level
-      os << indent << "Bandwidth: " << wds.bandWidth << " (Hz)" << endl
-	 << indent << "Time interval: " << wds.timeInterval << " (s)";
-      return os;
-    }
-
-    ostream& operator<<(ostream& os, const BBSStrategy::Selection& sel)
+    BBSStrategy::BBSStrategy(const ParameterSet& aParSet)
     {
-      os << indent << "Selection: ";
-      switch(sel.corr) {
-      case BBSStrategy::Selection::ALL:     os << "ALL";   break;
-      case BBSStrategy::Selection::CROSS:   os << "CROSS"; break;
-      case BBSStrategy::Selection::AUTO:    os << "AUTO";  break;
-      default: os << "*****"; break;
-      }
-      return os;
-    }
+      LOG_TRACE_FLOW(AUTO_FUNCTION_NAME);
 
-    ostream& operator<<(ostream& os, const BBSStrategy::BBDB& bbdb)
-    {
-      os << indent << "Blackboard database:" << endl;
-      Indent id; // add an indentation level
-      os << indent << "Host: " << bbdb.host << endl
-	 << indent << "Port: " << bbdb.port;
-      return os;
-    }
+      // Get the name of the Measurement Set.
+      itsDataSet = aParSet.getString("DataSet");
 
+      // Retrieve the blackboard related key/value pairs.
+      itsBBDB.host = aParSet.getString("BBDB.Host");
+      itsBBDB.port = aParSet.getUint16("BBDB.Port");
+      itsBBDB.dbName = aParSet.getString("BBDB.DBName");
+      itsBBDB.username = aParSet.getString("BBDB.UserName");
+      itsBBDB.password = aParSet.getString("BBDB.PassWord");
 
-    BBSStrategy::BBSStrategy(const ParameterSet& aParSet)
-    {
-      LOG_TRACE_FLOW(AUTO_FUNCTION_NAME);
+      // Retrieve the parameter database related key/value pairs.
+      itsParmDB.instrument = aParSet.getString("ParmDB.Instrument");
+      itsParmDB.localSky = aParSet.getString("ParmDB.LocalSky");
 
       // Create a subset of \a aParSet, containing only the relevant keys for
       // a Strategy.
@@ -81,30 +64,25 @@ namespace LOFAR
 
       // Create a new step for each name in \a steps.
       for (uint i = 0; i < steps.size(); ++i) {
-	itsSteps.push_back(BBSStep::create(steps[i], aParSet));
+	itsSteps.push_back(BBSStep::create(steps[i], aParSet, 0));
       }
 
       // ID's of the stations to be used by this strategy.
       itsStations = ps.getUint32Vector("Stations");
 
-      // Get the work domain size for this strategy
-      itsDomainSize.bandWidth = ps.getDouble("DomainSize.Freq");
-      itsDomainSize.timeInterval = ps.getDouble("DomainSize.Time");
 
-      // Get the names of the Measurement Sets
-      itsDataSet = ps.getString("DataSet");
+      // Get the work domain size for this strategy
+      itsDomainSize.bandWidth = ps.getDouble("WorkDomainSize.Freq");
+      itsDomainSize.timeInterval = ps.getDouble("WorkDomainSize.Time");
 
       // Get the correlation product selection (ALL, AUTO, or CROSS)
-      string sel = ps.getString("Selection");
-      if (sel == "ALL") itsSelection = Selection::ALL;
-      else if (sel == "AUTO") itsSelection = Selection::AUTO;
-      else if (sel == "CROSS") itsSelection = Selection::CROSS;
+      string sel = ps.getString("Correlation.Selection");
+      if      (sel == "ALL")   itsCorrelation.selection = Correlation::ALL;
+      else if (sel == "AUTO")  itsCorrelation.selection = Correlation::AUTO;
+      else if (sel == "CROSS") itsCorrelation.selection = Correlation::CROSS;
       else THROW(BBSControlException, 
 		 "Invalid correlation selection " << sel);
-
-      // Get the hostname/ipaddr and portnr of the Blackboard database
-      itsBBDB.host = ps.getString("BBDB.Host");
-      itsBBDB.port = ps.getUint16("BBDB.Port");
+      itsCorrelation.type = ps.getStringVector("Correlation.Type");
 
     }
 
@@ -123,16 +101,17 @@ namespace LOFAR
 
     void BBSStrategy::print(ostream& os) const
     {
-      os << indent << "Strategy:" << endl;
+      os << endl << indent << "Measurement Set: " << itsDataSet
+	 << endl << indent << itsBBDB
+	 << endl << indent << itsParmDB
+	 << endl << indent << "Strategy:";
       Indent id;
+      os << endl << indent << itsDomainSize
+	 << endl << indent << itsCorrelation
+	 << endl << indent << "Stations: " << itsStations;
       for (uint i = 0; i < itsSteps.size(); ++i) {
-	itsSteps[i]->print(os);
+	os << endl << indent << *itsSteps[i];
       }
-      os << indent << "Stations: " << itsStations << endl
-	 << itsDomainSize << endl
-	 << indent << "Data set: " << itsDataSet << endl
-	 << itsSelection << endl
-	 << itsBBDB << endl;
     }
 
 
@@ -141,6 +120,9 @@ namespace LOFAR
 //       itsSteps.push_back(aStep);
 //     }
 
+
+    //##--------   G l o b a l   m e t h o d s   --------##//
+
     ostream& operator<<(ostream& os, const BBSStrategy& bs)
     {
       bs.print(os); 
diff --git a/CEP/BB/BBSControl/src/BBSStructs.cc b/CEP/BB/BBSControl/src/BBSStructs.cc
new file mode 100644
index 00000000000..dc660a3e239
--- /dev/null
+++ b/CEP/BB/BBSControl/src/BBSStructs.cc
@@ -0,0 +1,105 @@
+//#  BBSStructs.cc: 
+//#
+//#  Copyright (C) 2002-2004
+//#  ASTRON (Netherlands Foundation for Research in Astronomy)
+//#  P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.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
+//#
+//#  $Id$
+
+#include <lofar_config.h>
+
+#include <BBSControl/BBSStructs.h>
+#include <BBSControl/StreamFormatting.h>
+
+namespace LOFAR
+{
+  namespace BBS
+  {
+
+    ostream& operator<<(ostream& os, const BBDB& obj)
+    {
+      os << "Blackboard database:";
+      Indent id;
+      os << endl << indent << "Host: " << obj.host
+	 << endl << indent << "Port: " << obj.port
+	 << endl << indent << "DBName: " << obj.dbName
+	 << endl << indent << "Username: " << obj.username
+	 << endl << indent << "Password: " << obj.password;
+      return os;
+    }
+
+
+    ostream& operator<<(ostream& os, const ParmDB& obj)
+    {
+      os << "Parameter database:";
+      Indent id;
+      os << endl << indent << "Instrument table: " << obj.instrument
+	 << endl << indent << "Local sky table: " << obj.localSky;
+      return os;
+    }
+
+
+    ostream& operator<<(ostream& os, const DomainSize& obj)
+    {
+      os << "Domain size:";
+      Indent id;
+      os << endl << indent << "Bandwidth: " << obj.bandWidth << " (Hz)"
+	 << endl << indent << "Time interval: " << obj.timeInterval << " (s)";
+      return os;
+    }
+
+
+    ostream& operator<<(ostream& os, const Correlation& obj)
+    {
+      os << "Correlation:";
+      Indent id;
+      os << endl << indent << "Selection: ";
+      switch(obj.selection) {
+      case Correlation::NONE:  os << "NONE";  break;
+      case Correlation::AUTO:  os << "AUTO";  break;
+      case Correlation::CROSS: os << "CROSS"; break;
+      case Correlation::ALL:   os << "ALL";   break;
+      default: os << "*****"; break;
+      }
+      os << endl << indent << "Type:" << obj.type;
+      return os;
+    }
+
+
+    ostream& operator<<(ostream& os, const Integration& obj)
+    {
+      os << "Integration:";
+      Indent id;
+      os << endl << indent << "Delta frequency: " << obj.deltaFreq << " (Hz)"
+	 << endl << indent << "Delta time: " << obj.deltaTime << " (s)";
+      return os;
+    }
+
+
+    ostream& operator<<(ostream& os, const Baselines& obj)
+    {
+      os << "Baselines:";
+      Indent id;
+      os << endl << indent << "Station1: " << obj.station1
+	 << endl << indent << "Station2: " << obj.station2;
+      return os;
+    }
+
+
+  } // namespace BBS
+
+} // namespace LOFAR
diff --git a/CEP/BB/BBSControl/src/Makefile.am b/CEP/BB/BBSControl/src/Makefile.am
index 803be52b9ae..ac3e12ebc8d 100644
--- a/CEP/BB/BBSControl/src/Makefile.am
+++ b/CEP/BB/BBSControl/src/Makefile.am
@@ -4,8 +4,10 @@ libbbscontrol_la_SOURCES= \
 	BBS.cc \
 	BBSStep.cc \
 	BBSSingleStep.cc \
+	BBSSolveStep.cc \
 	BBSMultiStep.cc \
 	BBSStrategy.cc \
+	BBSStructs.cc \
 	BlackBoardDemo.cc \
 	BlobAipsIO.cc \
 	DH_Prediff.cc \
@@ -18,6 +20,7 @@ libbbscontrol_la_SOURCES= \
 	SC_Simple.cc \
 	SC_WritePredData.cc \
 	StrategyController.cc \
+	StreamFormatting.cc \
 	WH_Control.cc \
 	WH_Prediff.cc \
 	WH_Solve.cc
diff --git a/CEP/BB/BBSControl/src/StreamFormatting.cc b/CEP/BB/BBSControl/src/StreamFormatting.cc
new file mode 100644
index 00000000000..e2207205867
--- /dev/null
+++ b/CEP/BB/BBSControl/src/StreamFormatting.cc
@@ -0,0 +1,38 @@
+//#  StreamUtil.cc: implementation of the stream utilities.
+//#
+//#  Copyright (C) 2002-2005
+//#  ASTRON (Netherlands Foundation for Research in Astronomy)
+//#  P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.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
+//#
+//#  $Id$
+
+//# Always #include <lofar_config.h> first!
+#include <lofar_config.h>
+
+#include <BBSControl/StreamFormatting.h>
+
+namespace LOFAR
+{
+  namespace BBS
+  {
+    // Initialize static variables.
+    uint Indent::lvl = 0;
+    const string Indent::tok = ". ";
+
+  } // namespace BBS
+
+} // namespace LOFAR
diff --git a/CEP/BB/BBSControl/test/tBBSControl.parset b/CEP/BB/BBSControl/test/tBBSControl.parset
index b166b026503..d52ff3752b8 100644
--- a/CEP/BB/BBSControl/test/tBBSControl.parset
+++ b/CEP/BB/BBSControl/test/tBBSControl.parset
@@ -20,8 +20,8 @@ ParmDB.Instrument        = "test.mep"       # instrument parameters (MS table)
 ParmDB.LocalSky          = "test.gsm"       # local sky parameters (MS table)
 
 Step.xyz1.Steps          = ["sl1", "sl2"]
-Step.xyz1.Selection.Station1 = [0, 0, 0, 1, 1, 2] # baselines to use 
-Step.xyz1.Selection.Station2 = [0, 1, 2, 1, 2, 2] # (all if empty)
+Step.xyz1.Baselines.Station1 = [0, 0, 0, 1, 1, 2] # baselines to use 
+Step.xyz1.Baselines.Station2 = [0, 1, 2, 1, 2, 2] # (all if empty)
 Step.xyz1.Sources        = ["3C343"]        # list of sources
 Step.xyz1.ExtraSources   = ["M81"]          # list of sources outside patch
 Step.xyz1.InstrumentModel = ["Bandpass",  \ # Instrument model
@@ -33,17 +33,16 @@ Step.xyz1.Correlation.Type = ["XX", "XY", \ # which (cross) correlations to use
                               "YX", "YY"]
 
 Step.xyz2.Steps          = ["sl1", "sl3"]
-Step.xyz2.Selection.Station1 = [0, 0, 1]    # baselines to use
-Step.xyz2.Selection.Station2 = [0, 1, 1]    # (all if empty)
+Step.xyz2.Baselines.Station1 = [0, 0, 1]    # baselines to use
+Step.xyz2.Baselines.Station2 = [0, 1, 1]    # (all if empty)
 Step.xyz2.Sources        = ["3C343"]        # sources in the source model
 Step.xyz2.InstrumentModel = ["Bandpass"]    # Instrument model
 
-Step.sl1.Selection.Station1 = [0, 1]        # baselines to use
-Step.sl1.Selection.Station2 = [1, 2]        # (all if empty)
-Step.sl1.Sources         = []               # list of sources
+Step.sl1.Baselines.Station1 = [0, 1]        # baselines to use
+Step.sl1.Baselines.Station2 = [1, 2]        # (all if empty)
 Step.sl1.Operation       = SOLVE          \ # one of SOLVE, SUBTRACT, CORRECT,
                                             # PREDICT, SHIFT, REFIT
-Step.sl1.OutData         = "OUTDATA1"       # MS output data column
+Step.sl1.OutputData      = "OUTDATA1"       # MS output data column
 Step.sl1.Solve.MaxIter   = 10               # maximum number of iterations
 Step.sl1.Solve.Epsilon   = 1e-7             # convergence threshold
 Step.sl1.Solve.MinConverged = 0.95          # fraction that must have converged
@@ -53,32 +52,12 @@ Step.sl1.Solve.DomainSize.Freq = 1000       # f(Hz)
 Step.sl1.Solve.DomainSize.Time = 1          # t(s)
 Step.sl1.InstrumentModel = ["Bandpass", "Phase"]
 
-Step.sl2.Selection.Station1 = []            # baselines to use
-Step.sl2.Selection.Station2 = []            # (all if empty)
-Step.sl2.Sources         = []               # list of sources
 Step.sl2.Operation       = CORRECT        \ # one of SOLVE, SUBTRACT, CORRECT,
                                             # PREDICT, SHIFT, REFIT
-Step.sl2.OutData         = "OUTDATA2"       # MS output data column
-Step.sl2.Solve.MaxIter   = 10               # maximum number of iterations
-Step.sl2.Solve.Epsilon   = 1e-6             # convergence threshold
-Step.sl2.Solve.MinConverged = 0.85          # fraction that must have converged
-Step.sl2.Solve.Parms     = ["GAIN:*"]       # names of solvable parameters
-Step.sl2.Solve.ExclParms = ["PHASE:*"]      # parameters excluded from solve
-Step.sl2.Solve.DomainSize.Freq = 500        # f(Hz)
-Step.sl2.Solve.DomainSize.Time = 2          # t(s)
+Step.sl2.OutputData      = "OUTDATA2"       # MS output data column
 Step.sl2.InstrumentModel = ["DirGain", "Phase"]
 
-Step.sl3.Selection.Station1 = []            # baselines to use
-Step.sl3.Selection.Station2 = []            # (all if empty)
-Step.sl3.Sources         = []               # list of sources
 Step.sl3.Operation       = PREDICT        \ # one of SOLVE, SUBTRACT, CORRECT,
                                             # PREDICT, SHIFT, REFIT
-Step.sl3.OutData         = "OUTDATA3"       # MS output data column
-Step.sl3.Solve.MaxIter   = 10               # maximum number of iterations
-Step.sl3.Solve.Epsilon   = 1e-5             # convergence threshold
-Step.sl3.Solve.MinConverged = 0.98          # fraction that must have converged
-Step.sl3.Solve.Parms     = ["GAIN:*", "PHASE:*"] # names of solvable parameters
-Step.sl3.Solve.ExclParms = [""]             # parameters excluded from solve
-Step.sl3.Solve.DomainSize.Freq = 250        # f(Hz)
-Step.sl3.Solve.DomainSize.Time = 4          # t(s)
+Step.sl3.OutputData      = "OUTDATA3"       # MS output data column
 Step.sl3.InstrumentModel = ["Phase"]
diff --git a/CEP/BB/BBSControl/test/tBBSStrategy.parset b/CEP/BB/BBSControl/test/tBBSStrategy.parset
index b166b026503..d52ff3752b8 100644
--- a/CEP/BB/BBSControl/test/tBBSStrategy.parset
+++ b/CEP/BB/BBSControl/test/tBBSStrategy.parset
@@ -20,8 +20,8 @@ ParmDB.Instrument        = "test.mep"       # instrument parameters (MS table)
 ParmDB.LocalSky          = "test.gsm"       # local sky parameters (MS table)
 
 Step.xyz1.Steps          = ["sl1", "sl2"]
-Step.xyz1.Selection.Station1 = [0, 0, 0, 1, 1, 2] # baselines to use 
-Step.xyz1.Selection.Station2 = [0, 1, 2, 1, 2, 2] # (all if empty)
+Step.xyz1.Baselines.Station1 = [0, 0, 0, 1, 1, 2] # baselines to use 
+Step.xyz1.Baselines.Station2 = [0, 1, 2, 1, 2, 2] # (all if empty)
 Step.xyz1.Sources        = ["3C343"]        # list of sources
 Step.xyz1.ExtraSources   = ["M81"]          # list of sources outside patch
 Step.xyz1.InstrumentModel = ["Bandpass",  \ # Instrument model
@@ -33,17 +33,16 @@ Step.xyz1.Correlation.Type = ["XX", "XY", \ # which (cross) correlations to use
                               "YX", "YY"]
 
 Step.xyz2.Steps          = ["sl1", "sl3"]
-Step.xyz2.Selection.Station1 = [0, 0, 1]    # baselines to use
-Step.xyz2.Selection.Station2 = [0, 1, 1]    # (all if empty)
+Step.xyz2.Baselines.Station1 = [0, 0, 1]    # baselines to use
+Step.xyz2.Baselines.Station2 = [0, 1, 1]    # (all if empty)
 Step.xyz2.Sources        = ["3C343"]        # sources in the source model
 Step.xyz2.InstrumentModel = ["Bandpass"]    # Instrument model
 
-Step.sl1.Selection.Station1 = [0, 1]        # baselines to use
-Step.sl1.Selection.Station2 = [1, 2]        # (all if empty)
-Step.sl1.Sources         = []               # list of sources
+Step.sl1.Baselines.Station1 = [0, 1]        # baselines to use
+Step.sl1.Baselines.Station2 = [1, 2]        # (all if empty)
 Step.sl1.Operation       = SOLVE          \ # one of SOLVE, SUBTRACT, CORRECT,
                                             # PREDICT, SHIFT, REFIT
-Step.sl1.OutData         = "OUTDATA1"       # MS output data column
+Step.sl1.OutputData      = "OUTDATA1"       # MS output data column
 Step.sl1.Solve.MaxIter   = 10               # maximum number of iterations
 Step.sl1.Solve.Epsilon   = 1e-7             # convergence threshold
 Step.sl1.Solve.MinConverged = 0.95          # fraction that must have converged
@@ -53,32 +52,12 @@ Step.sl1.Solve.DomainSize.Freq = 1000       # f(Hz)
 Step.sl1.Solve.DomainSize.Time = 1          # t(s)
 Step.sl1.InstrumentModel = ["Bandpass", "Phase"]
 
-Step.sl2.Selection.Station1 = []            # baselines to use
-Step.sl2.Selection.Station2 = []            # (all if empty)
-Step.sl2.Sources         = []               # list of sources
 Step.sl2.Operation       = CORRECT        \ # one of SOLVE, SUBTRACT, CORRECT,
                                             # PREDICT, SHIFT, REFIT
-Step.sl2.OutData         = "OUTDATA2"       # MS output data column
-Step.sl2.Solve.MaxIter   = 10               # maximum number of iterations
-Step.sl2.Solve.Epsilon   = 1e-6             # convergence threshold
-Step.sl2.Solve.MinConverged = 0.85          # fraction that must have converged
-Step.sl2.Solve.Parms     = ["GAIN:*"]       # names of solvable parameters
-Step.sl2.Solve.ExclParms = ["PHASE:*"]      # parameters excluded from solve
-Step.sl2.Solve.DomainSize.Freq = 500        # f(Hz)
-Step.sl2.Solve.DomainSize.Time = 2          # t(s)
+Step.sl2.OutputData      = "OUTDATA2"       # MS output data column
 Step.sl2.InstrumentModel = ["DirGain", "Phase"]
 
-Step.sl3.Selection.Station1 = []            # baselines to use
-Step.sl3.Selection.Station2 = []            # (all if empty)
-Step.sl3.Sources         = []               # list of sources
 Step.sl3.Operation       = PREDICT        \ # one of SOLVE, SUBTRACT, CORRECT,
                                             # PREDICT, SHIFT, REFIT
-Step.sl3.OutData         = "OUTDATA3"       # MS output data column
-Step.sl3.Solve.MaxIter   = 10               # maximum number of iterations
-Step.sl3.Solve.Epsilon   = 1e-5             # convergence threshold
-Step.sl3.Solve.MinConverged = 0.98          # fraction that must have converged
-Step.sl3.Solve.Parms     = ["GAIN:*", "PHASE:*"] # names of solvable parameters
-Step.sl3.Solve.ExclParms = [""]             # parameters excluded from solve
-Step.sl3.Solve.DomainSize.Freq = 250        # f(Hz)
-Step.sl3.Solve.DomainSize.Time = 4          # t(s)
+Step.sl3.OutputData      = "OUTDATA3"       # MS output data column
 Step.sl3.InstrumentModel = ["Phase"]
-- 
GitLab