diff --git a/.gitattributes b/.gitattributes
index e8b5088e4f62ca4352a5709010a4e8a89972ab33..0b507270f45586099d1fdcdcb2eb8bc6d7f739ac 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -3936,8 +3936,9 @@ RTCP/Storage/test/tMeasurementSetFormat.parset-j2000 -text
 RTCP/Storage/test/tMeasurementSetFormat.parset-sun -text
 RTCP/Storage/test/tTBB_StaticMapping.cc -text
 RTCP/Storage/test/tTBB_StaticMapping.sh -text
+RTCP/Storage/test/tTBB_Writer-spectral.parset -text
+RTCP/Storage/test/tTBB_Writer-transient.parset -text
 RTCP/Storage/test/tTBB_Writer-verify.py -text
-RTCP/Storage/test/tTBB_Writer.parset -text
 RTCP/Storage/test/tTBB_Writer.sh -text
 SAS/OTB/OTB-distribution/assembly.xml -text
 SAS/OTB/OTB-distribution/pom.xml -text
diff --git a/RTCP/Storage/include/Storage/TBB_Writer.h b/RTCP/Storage/include/Storage/TBB_Writer.h
index 0a9c95ce037c8e08f98e8f3d994083616b435899..0b29e0854530d16d3ba02bea1128773f9c211f7e 100644
--- a/RTCP/Storage/include/Storage/TBB_Writer.h
+++ b/RTCP/Storage/include/Storage/TBB_Writer.h
@@ -18,7 +18,7 @@
  * You should have received a copy of the GNU General Public License along
  * with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>.
  *
- * $Id: TBB_Writer.h 13275 2012-09-07 15:41:22Z amesfoort $
+ * $Id: TBB_Writer.h 14188 2012-09-07 15:41:22Z amesfoort $
  */
 
 #ifndef LOFAR_STORAGE_TBB_WRITER_H
@@ -29,7 +29,6 @@
 #include <string>
 #include <vector>
 #include <map>
-#include <fstream>
 
 #include <boost/crc.hpp>
 
@@ -39,6 +38,7 @@
 #endif
 #include <Common/Thread/Thread.h>
 #include <Common/Thread/Queue.h>
+#include <Stream/FileStream.h>
 #include <Interface/Parset.h>
 
 /*
@@ -49,7 +49,7 @@
 #ifndef TBB_WRITER_VERSION
 #include <Storage/Package__Version.h>
 #else
-#warning TBB_Writer version not derived from cmake build system, but hard coded using TBB_WRITER_VERSION define.
+#warning TBB_Writer version not derived from the cmake build system, but hard-coded using the TBB_WRITER_VERSION symbol.
 #endif
 
 #include <dal/lofar/TBB_File.h>
@@ -83,9 +83,9 @@ struct TBB_Header {
 		uint32_t sampleNr;
 
 		// In spectral mode indicates frequency band and slice (transform block of 1024 samples) of first payload sample.
-		uint32_t bandsliceNr; // bandNr[9:0] and sliceNr[31:10].
-		// Avoid bit fields, (portable) compilation support is messy. Instead use mask and shift to decode.
-#define TBB_BAND_NR_MASK	((1 << 11) - 1) 
+		uint32_t bandSliceNr; // bandNr[9:0] and sliceNr[31:10].
+		// Avoid bit fields, (portable) compilation support is messy. Instead use mask and shift to extract.
+#define TBB_BAND_NR_MASK	((1 << 10) - 1) 
 #define TBB_SLICE_NR_SHIFT	10
 	};
 
@@ -103,7 +103,7 @@ struct TBB_Header {
 
 struct TBB_Payload {
 	/*
-	 * In transient mode, a sample is 12 bit. In spectral, 2*16 bit (real, imag).
+	 * In transient mode, a sample is a signed 12 bit integer. In spectral mode, it is a complex int16_t.
 	 * In the TBBs, transient samples are packed (2 samples per 3 bytes) with the checksum all the way at the end. This changes on transfer.
 	 *
 	 * TBB stores a frame in 2040 bytes (actually, 2048 with preamble and gaps). It sends a frame at a time, so derive our max from it.
@@ -115,11 +115,20 @@ struct TBB_Payload {
 
 	// Unpacked, sign-extended (for transient) samples without padding, i.e. as received.
 	// Frames might not be full; the crc32 is always sent right after (no padding unlike as stored by TBB),
-	// so we include it in 'data', but note that the crc32 is a little endian uint32_t, hence + 2. The crc32 is computed for transient data only.
-	int16_t data[MAX_TBB_TRANSIENT_NSAMPLES + 2];				// 1300*2 bytes; Because only transient data is unpacked, use its max.
+	// so we include it in 'data', but note that the crc32 is a little endian uint32_t, hence ' + 2'.
+#ifndef MAX
+#define MAX(a, b)	((a) > (b) ? (a) : (b))
+#endif
+	int16_t data[MAX(MAX_TBB_TRANSIENT_NSAMPLES, 2 * MAX_TBB_SPECTRAL_NSAMPLES) + 2];				
+
+	// For transient, TBB always sends sends 1024 samples per frame (from the spec and from the data).
+	// For spectral, it depends on the nr of subbands (max is equal to MAX_TBB_SPECTRAL_NSAMPLES).
+	// TBB sends as many samples for all subbands as it can fit; e.g. with 5 subbands, each frame has 485 samples. TODO: correct?
 
-#define DEFAULT_TRANSIENT_NSAMPLES	1024						// From the spec and from real data.
-#define DEFAULT_SPECTRAL_NSAMPLES	MAX_TBB_SPECTRAL_NSAMPLES	// The spec only states a max, so guess. Spectral mode has never been used or tested.
+#define SPECTRAL_TRANSFORM_SIZE		1024						// RSP FFT block size
+
+#define DEFAULT_TBB_TRANSIENT_NSAMPLES	1024
+#define DEFAULT_TBB_SPECTRAL_NSAMPLES	487
 };
 
 struct TBB_Frame {
@@ -127,7 +136,6 @@ struct TBB_Frame {
 	TBB_Payload payload;
 };
 
-
 // Station meta data from other sources than the parset.
 struct StationMetaData {
 	// If we receive data from a station not in the obs, we won't have all the meta data.
@@ -136,7 +144,7 @@ struct StationMetaData {
 	// from the antenna field files
 	std::vector<double> antPositions;
 	std::vector<double> normalVector;   // [3]
-	std::vector<double> rotationMatrix; // [3, 3] row-minor order
+	std::vector<double> rotationMatrix; // [3, 3] row-major order
 
 	// from the station calibration table files
 	//...
@@ -145,21 +153,29 @@ struct StationMetaData {
 // From station ID to a vector of antenna position coordinate components.
 typedef std::map<unsigned, StationMetaData> StationMetaDataMap;
 
+struct SubbandInfo {
+	std::vector<double>   centralFreqs;   // empty in transient mode
+	std::vector<unsigned> storageIndices; // idem
+};
+
 
 class TBB_Dipole {
 	dal::TBB_DipoleDataset* itsDataset;
-	std::ofstream itsRawOut; // if raw out requested
-
+	LOFAR::FileStream*	itsRawOut;
 	std::vector<dal::Range> itsFlagOffsets;
 
-	ssize_t itsDatasetLen;
-
 	uint32_t itsSampleFreq; // Hz
-	uint32_t itsTime0; // seconds
-	uint32_t itsSampleNr0; // for transient data only
+	unsigned itsNrSubbands; // spectral mode only, 0 in transient mode
+
+	uint32_t itsTime; // seconds
+	union {
+		uint32_t itsExpSampleNr; // transient mode
+		uint32_t itsExpSliceNr;  // spectral mode
+	};
+	ssize_t itsDatasetLen;
 
 	// Same truncated polynomial as standard crc32, but with initial_remainder=0, final_xor_value=0, reflected_input=false, reflected_remainder_output=false.
-	// The boost::crc_optimal<> declarations precompute lookup tables, so do not declare inside the checking routine.
+	// The boost::crc_optimal<> declarations precompute lookup tables, so do not declare inside the checking routine. (Still, for every TBB_Dipole...)
 	boost::crc_optimal<32, 0x04C11DB7/*, 0, 0, false, false*/> itsCrc32gen; // instead of boost::crc_32_type
 
 	// do not use
@@ -172,22 +188,23 @@ public:
 
 	// Output threads
 	bool isInitialized() const;
-	bool usesExternalDataFile() const;
 
 	// All TBB_Dipole objects are default constructed in a vector, so provide an init procedure.
-	void initDipole(const TBB_Header& header, const Parset& parset, const StationMetaData& stationMetaData,
-                    const std::string& rawFilename, dal::TBB_Station& station, Mutex& h5Mutex);
+	void init(const TBB_Header& header, const Parset& parset, const StationMetaData& stationMetaData,
+              const SubbandInfo& subbandInfo, const std::string& rawFilename, dal::TBB_Station& station,
+              Mutex& h5Mutex);
 
-	void processFrameData(const TBB_Frame& frame, Mutex& h5Mutex);
+	void processTransientFrameData(const TBB_Frame& frame);
+	void processSpectralFrameData(const TBB_Frame& frame, const SubbandInfo& subbandInfo);
 
 private:
 	void addFlags(size_t offset, size_t len);
 	// initTBB_DipoleDataset() must be called with the global h5Mutex held.
 	void initTBB_DipoleDataset(const TBB_Header& header, const Parset& parset,
-                               const StationMetaData& stationMetaData, const std::string& rawFilename,
-                               dal::TBB_Station& station);
-	bool hasAllZeroDataSamples(const TBB_Frame& frame) const;
-	bool crc32tbb(const TBB_Payload* payload, size_t nsamples);
+                               const StationMetaData& stationMetaData, const SubbandInfo& subbandInfo,
+                               const std::string& rawFilename, dal::TBB_Station& station);
+	bool hasAllZeroDataSamples(const TBB_Payload& payload, size_t nTrSamples) const;
+	bool crc32tbb(const TBB_Payload* payload, size_t nTrSamples);
 };
 
 class TBB_Station {
@@ -197,10 +214,12 @@ class TBB_Station {
 	std::vector<TBB_Dipole> itsDipoles;
 	const Parset& itsParset;
 	const StationMetaData& itsStationMetaData;
+	const SubbandInfo itsSubbandInfo; // relevant for spectral mode
 	const std::string itsH5Filename;
-	const bool itsDumpRaw;
 
-	std::string getRawFilename(unsigned rspID, unsigned rcuID);
+	double getSubbandCentralFreq(unsigned subbandNr, unsigned nyquistZone, double sampleFreq) const;
+	SubbandInfo getSubbandInfo(const Parset& parset) const;
+	std::string getRawFilename(unsigned rspID, unsigned rcuID) const;
 
 	// do not use
 	TBB_Station();
@@ -209,10 +228,9 @@ class TBB_Station {
 
 public:
 	// This constructor must be called with the h5Mutex already held.
-	// The caller must still unlock, even though a ref to the same mutex is passed.
+	// The caller must still unlock after the return, the constructor does not use the passed ref to unlock.
 	TBB_Station(const string& stationName, Mutex& h5Mutex, const Parset& parset,
-                const StationMetaData& stationMetaData, const std::string& h5Filename,
-                bool dumpRaw);
+                const StationMetaData& stationMetaData, const std::string& h5Filename);
 	~TBB_Station();
 
 	// Output threads
@@ -225,7 +243,7 @@ private:
 	void initCommonLofarAttributes();
 	void initTBB_RootAttributesAndGroups(const std::string& stName);
 	void initStationGroup(dal::TBB_Station& st, const std::string& stName,
-                              const std::vector<double>& stPosition);
+                          const std::string& stFullName, const std::vector<double>& stPosition);
 	void initTriggerGroup(dal::TBB_Trigger& tg);
 };
 
@@ -255,14 +273,21 @@ class TBB_StreamWriter {
 
 	TBB_Writer& itsWriter;
 	const std::string& itsInputStreamName;
+	const size_t itsExpFrameSize;
 	const std::string& itsLogPrefix;
+	int& itsInExitStatus;
+	int& itsOutExitStatus;
 
-	// See TBB_Writer_main.cc::doTBB_Run() why this is used racily and thus tmp.
+	// See TBB_Writer_main.cc::doTBB_Run() why this is used racily for now.
 	// Inflate struct timeval to 64 bytes (typical LEVEL1_DCACHE_LINESIZE).
 	struct timeval itsTimeoutStamp __attribute__((aligned(64)));
 
 	boost::crc_optimal<16, 0x8005/*, 0, 0, false, false*/> itsCrc16gen; // instead of boost::crc_16_type
 
+#ifdef DUMP_RAW_STATION_DATA
+	LOFAR::FileStream* itsRawStationData;
+#endif
+
 	// Thread objects must be last in TBB_StreamWriter for safe destruction.
 	Thread* itsOutputThread;
 	Thread* itsInputThread;
@@ -274,7 +299,8 @@ class TBB_StreamWriter {
 
 public:
 	TBB_StreamWriter(TBB_Writer& writer, const std::string& inputStreamName,
-                     const std::string& logPrefix);
+                     size_t expNTrSamples, const std::string& logPrefix,
+                     int& inExitStatus, int& outExitStatus);
 	~TBB_StreamWriter();
 
 	// Main thread
@@ -283,7 +309,7 @@ public:
 private:
 	// Input threads
 	void frameHeaderLittleToHost(TBB_Header& fh) const;
-	void correctTransientSampleNr(TBB_Header& header) const;
+	void correctSampleNr(TBB_Header& header) const;
 	bool crc16tbb(const TBB_Header* header);
 	void processHeader(TBB_Header& header, size_t recvPayloadSize);
 	void mainInputLoop();
@@ -295,7 +321,7 @@ private:
 class TBB_Writer {
 	// Usually, we handle only 1 station, but we can handle multiple at a time.
 	// map from stationID to a TBB_Station*
-	std::map<unsigned, TBB_Station* > itsStations;
+	std::map<unsigned, TBB_Station*> itsStations;
 	Mutex itsStationsMutex;
 
 	// Global H5 mutex. All HDF5 operations go under a single mutex, incl file creation:
@@ -306,12 +332,11 @@ class TBB_Writer {
 	const StationMetaDataMap& itsStationMetaDataMap;
 	StationMetaData itsUnknownStationMetaData; // referred to for data from unknown stations
 	const std::string& itsOutDir;
-	const bool itsDumpRaw;
 
 	unsigned itsRunNr;
 
-	// Stream writers (threads) must be last in TBB_Writer for safe destruction.
-	std::vector<TBB_StreamWriter* > itsStreamWriters;
+	std::vector<TBB_StreamWriter*> itsStreamWriters;
+	// NOTE: do not add vars here; leave itsStreamWriters last for safe thread destruction!
 
 	// do not use
 	TBB_Writer();
@@ -320,12 +345,13 @@ class TBB_Writer {
 
 public:
 	TBB_Writer(const std::vector<std::string>& inputStreamNames, const Parset& parset,
-                   const StationMetaDataMap& stationMetaDataMap, const std::string& outDir,
-                   bool dumpRaw, const std::string& logPrefix);
+               const StationMetaDataMap& stationMetaDataMap, const std::string& outDir,
+               const std::string& logPrefix, vector<int>& thrExitStatus);
 	~TBB_Writer();
 
 	// Output threads
 	TBB_Station* getStation(const TBB_Header& header);
+	// Must be called holding itsStationsMutex.
 	std::string createNewTBB_H5Filename(const TBB_Header& header, const std::string& stationName);
 
 	// Main thread
diff --git a/RTCP/Storage/src/TBB_Writer.cc b/RTCP/Storage/src/TBB_Writer.cc
index 6b619781a1ca91859c581deeff0c68c80f629d57..1c3af79eb332dd61b460c78a8bc262748e4cb8be 100644
--- a/RTCP/Storage/src/TBB_Writer.cc
+++ b/RTCP/Storage/src/TBB_Writer.cc
@@ -18,11 +18,12 @@
  * You should have received a copy of the GNU General Public License along
  * with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>.
  *
- * $Id: TBB_Writer.cc 38741 2012-09-07 11:54:53Z amesfoort $
+ * $Id: TBB_Writer.cc 47912 2012-09-07 11:54:53Z amesfoort $
  */
 
 #include <lofar_config.h>
 
+#define _FILE_OFFSET_BITS 64
 #include <cstddef>
 #include <csignal>
 #include <ctime>
@@ -38,6 +39,7 @@
 
 #include <iostream>
 #include <sstream>
+#include <algorithm>
 
 #include <Storage/TBB_Writer.h>
 #include <Common/LofarConstants.h>
@@ -56,6 +58,11 @@
 
 #include <dal/lofar/StationNames.h>
 
+#define TBB_TRANSIENT_MODE			1
+#define TBB_SPECTRAL_MODE			2
+
+#define RSP_NR_SUBBANDS				512		// nr of subbands produced by the RSP polyphase filter
+
 namespace LOFAR {
 namespace RTCP {
 
@@ -70,25 +77,42 @@ EXCEPTION_CLASS(TBB_MalformedFrameException, StorageException);
 static string formatFilenameTimestamp(const struct timeval& tv, const char* output_format,
                                       const char* output_format_secs, size_t output_size) {
 	struct tm tm;
-	gmtime_r(&tv.tv_sec, &tm);
+	::gmtime_r(&tv.tv_sec, &tm);
 	double secs = tm.tm_sec + tv.tv_usec / 1000000.0;
 
 	vector<char> date(output_size);
 
-	size_t nwritten = strftime(&date[0], output_size, output_format, &tm);
+	size_t nwritten = ::strftime(&date[0], output_size, output_format, &tm);
 	if (nwritten == 0) {
 		date[0] = '\0';
 	}
-	(void)snprintf(&date[0] + nwritten, output_size - nwritten, output_format_secs, secs);
+	(void)::snprintf(&date[0] + nwritten, output_size - nwritten, output_format_secs, secs);
 
 	return string(&date[0]);
 }
 
+// FileStream doesn't do pwrite(2). Roll our own as nobody else needs it, but in the FileStream way, just in case.
+static size_t tryPWrite(int fd, const void *ptr, size_t size, off_t offset) {
+	ssize_t bytes = ::pwrite(fd, ptr, size, offset);
+	if (bytes < 0)
+		throw SystemCallException("pwrite", errno, THROW_ARGS);
+	return bytes;
+}
+
+static void pwrite(int fd, const void *ptr, size_t size, off_t offset) {
+	while (size > 0) {
+		size_t bytes = tryPWrite(fd, ptr, size, offset);
+		size   -= bytes;
+		offset += bytes;
+		ptr     = static_cast<const char *>(ptr) + bytes;
+	}
+}
+
 string TBB_Header::toString() const {
-	std::ostringstream oss;
-	oss << (uint32_t)stationID << " " << (uint32_t)rspID << " " << (uint32_t)rcuID << " " << (uint32_t)sampleFreq <<
-			" " << seqNr << " " << time << " " << sampleNr << " " << nOfSamplesPerFrame << " " << nOfFreqBands <<
-			" " /*<< bandSel << " "*/ << spare << " " << crc16;
+	ostringstream oss;
+	oss << (unsigned)stationID << " " << (unsigned)rspID << " " << (unsigned)rcuID << " " << (unsigned)sampleFreq <<
+           " " << seqNr << " " << time << " " << (nOfFreqBands == 0 ? sampleNr : bandSliceNr) << " " << nOfSamplesPerFrame <<
+           " " << nOfFreqBands << " " << spare << " " << crc16; // casts uin8_t to unsigned to avoid printing as char
 	return oss.str();
 }
 
@@ -96,39 +120,49 @@ string TBB_Header::toString() const {
 
 TBB_Dipole::TBB_Dipole()
 : itsDataset(NULL) // needed, setting the others is superfluous
-, itsDatasetLen(0)
+, itsRawOut(NULL)
+, itsFlagOffsets()
 , itsSampleFreq(0)
-, itsTime0(0)
-, itsSampleNr0(0)
+, itsNrSubbands(0)
+, itsTime(0)
+, itsExpSampleNr(0) // also inits itsExpSliceNr
+, itsDatasetLen(0)
 {
 }
 
 // Do not use. Only needed for vector<TBB_Dipole>(N).
 TBB_Dipole::TBB_Dipole(const TBB_Dipole& rhs)
 : itsDataset(rhs.itsDataset) // needed, setting the others is superfluous
-//, itsRawOut(rhs.itsRawOut) // ofstream has no copy constr and is unnecessary (this whole func is), so disabled
+, itsRawOut(NULL) // Safe destr. FileStream has no copy constr, so disabled; also see comments in init()
 , itsFlagOffsets(rhs.itsFlagOffsets)
-, itsDatasetLen(rhs.itsDatasetLen)
 , itsSampleFreq(rhs.itsSampleFreq)
-, itsTime0(rhs.itsTime0)
-, itsSampleNr0(rhs.itsSampleNr0)
+, itsNrSubbands(rhs.itsNrSubbands)
+, itsTime(rhs.itsTime)
+, itsExpSampleNr(rhs.itsExpSampleNr) // also inits itsExpSliceNr
+, itsDatasetLen(rhs.itsDatasetLen)
 {
 }
 
 TBB_Dipole::~TBB_Dipole() {
 	/*
-	 * Set dataset len (if ext raw) and DATA_LENGTH and FLAG_OFFSETS attributes at the end.
+	 * Set dataset len (if ext raw) and SPECTRAL_*, DATA_LENGTH and FLAG_OFFSETS attributes at the end.
 	 * Executed by the main thread after joined with all workers, so no need to lock or delay cancellation.
 	 * Skip on uninitialized (default constructed) objects.
 	 */
 	if (itsDataset != NULL) {
-		if (usesExternalDataFile()) {
-			try {
+		try {
+			if (itsNrSubbands == 0) { // transient mode
 				itsDataset->resize1D(itsDatasetLen);
-			} catch (dal::DALException& exc) {
-				LOG_WARN_STR("TBB: failed to resize HDF5 dipole dataset to external data size: " << exc.what());
+			} else { // spectral mode
+				vector<ssize_t> newDims(2);
+				newDims[0] = itsDatasetLen;
+				newDims[1] = itsNrSubbands; // only the 1st dim can be extended
+				itsDataset->resize(newDims);
 			}
+		} catch (exception& exc) { // dal::DALException, or std::bad_alloc from vector constr
+			LOG_WARN_STR("TBB: failed to resize HDF5 dipole dataset to external data size: " << exc.what());
 		}
+
 		try {
 			itsDataset->dataLength().value = static_cast<unsigned long long>(itsDatasetLen);
 		} catch (dal::DALException& exc) {
@@ -142,43 +176,50 @@ TBB_Dipole::~TBB_Dipole() {
 
 		delete itsDataset;
 	}
+
+	delete itsRawOut;
 }
 
-void TBB_Dipole::initDipole(const TBB_Header& header, const Parset& parset, const StationMetaData& stationMetaData,
-		const string& rawFilename, dal::TBB_Station& station, Mutex& h5Mutex) {
-	if (header.sampleFreq == 200 || header.sampleFreq == 160) {
-		itsSampleFreq = static_cast<uint32_t>(header.sampleFreq) * 1000000;
-	} else { // might happen if header of first frame is corrupt (doesn't mean we (can) deal with that on any corruption)
-		itsSampleFreq = parset.clockSpeed(); // Hz
-		LOG_WARN("TBB: Unknown sample rate in TBB frame header; using sample rate from the parset");
-	}
+void TBB_Dipole::init(const TBB_Header& header, const Parset& parset,
+                            const StationMetaData& stationMetaData,
+                            const SubbandInfo& subbandInfo, const string& rawFilename,
+                            dal::TBB_Station& station, Mutex& h5Mutex) {
+	itsSampleFreq = static_cast<uint32_t>(header.sampleFreq) * 1000000;
+	itsNrSubbands = subbandInfo.centralFreqs.size();
+
+	itsRawOut = new FileStream(rawFilename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
 
 	{
 		ScopedLock h5OutLock(h5Mutex);
-		initTBB_DipoleDataset(header, parset, stationMetaData, rawFilename, station);
-	}
-
-	if (!rawFilename.empty()) {
-		itsRawOut.open(rawFilename.c_str(), ios_base::out | ios_base::binary | ios_base::trunc);
-		if (!itsRawOut.good()) {
-			throw SystemCallException("Failed to open external raw file, dropping frame");
+		try {
+			initTBB_DipoleDataset(header, parset, stationMetaData, subbandInfo, rawFilename, station);
+		} catch (exception& ) {
+			/*
+			 * This nonsense is needed, because FileStream has no FileStream() and open() (and swap()),
+			 * and since we know the filename only at runtime (timestamp), we need itsRawOut to be a raw ptr.
+			 * We already have a raw ptr for itsDataset and >1 raw ptr in 1 C++ class becomes buggy or messy.
+			 */
+			delete itsRawOut;
+			itsRawOut = NULL;
+			throw;
 		}
 	}
 
-	itsTime0 = header.time;
-	itsSampleNr0 = header.sampleNr;
+	itsTime = header.time;
+	if (itsNrSubbands == 0) { // transient mode
+		itsExpSampleNr = header.sampleNr;
+	} else { // spectral mode
+		itsExpSliceNr  = header.bandSliceNr >> TBB_SLICE_NR_SHIFT;
+	}
+	itsDatasetLen = 0; // already 0, so just for completeness
 }
 
 bool TBB_Dipole::isInitialized() const {
-	return itsDataset != NULL;
-}
-
-bool TBB_Dipole::usesExternalDataFile() const {
-	return itsRawOut.is_open();
+	return itsDataset != NULL; // constructed after itsRawOut so test itsDataset
 }
 
+// Add a new flag range or extend the last stored flag range. 'len' may not be 0.
 void TBB_Dipole::addFlags(size_t offset, size_t len) {
-	// Add a new flag range or extend the last stored flag range. 'len' cannot be 0.
 	if (itsFlagOffsets.empty() || offset > itsFlagOffsets.back().end) {
 		itsFlagOffsets.push_back(dal::Range(offset, offset + len));
 	} else { // extend flag range
@@ -186,96 +227,173 @@ void TBB_Dipole::addFlags(size_t offset, size_t len) {
 	}
 }
 
-void TBB_Dipole::processFrameData(const TBB_Frame& frame, Mutex& h5Mutex) {
-	off_t offset = (frame.header.time - itsTime0) * itsSampleFreq + frame.header.sampleNr - itsSampleNr0;
+void TBB_Dipole::processTransientFrameData(const TBB_Frame& frame) {
+	/*
+	 * Out-of-order or duplicate frames are very unlikely in the LOFAR TBB setup,
+	 * but let us know if it ever happens, then we will adapt this code and addFlags().
+	 */
+	if (frame.header.time < itsTime || (frame.header.time == itsTime && frame.header.sampleNr < itsExpSampleNr)) {
+		LOG_WARN_STR("TBB: Please notify developer: unhandled out-of-order or duplicate TBB frame: " <<
+                     (unsigned)frame.header.stationID << " " << (unsigned)frame.header.rspID << " " << (unsigned)frame.header.rcuID <<
+                     " " << frame.header.time << " " << itsTime << " " << frame.header.sampleNr << " " << itsExpSampleNr);
+		return;
+	}
 
-	if (frame.header.nOfFreqBands == 0) { // transient mode
+	off_t offset = 0;
+	if (frame.header.time == itsTime) {
+		offset = itsDatasetLen + frame.header.sampleNr - itsExpSampleNr;
+	} else { // crossed a seconds boundary, potentially more than once on excessive frame loss
+		// A dump does not have to start at a sec bound, so up till the first bound, we may have had fewer than itsSampleFreq samples.
+		if (itsDatasetLen < (int32_t)itsSampleFreq) {
+			offset = itsDatasetLen;
+			itsTime++;
+		}
+		offset += (off_t)(frame.header.time - itsTime) * itsSampleFreq;
 
-#ifndef DISABLE_CRCS
-		// Verify data checksum.
-		if (!crc32tbb(&frame.payload, frame.header.nOfSamplesPerFrame)) {
-			/*
-			 * On a data checksum error 'flag' this offset, but still store the data.
-			 * Lost frame vs crc error can be seen from the data: a block of zeros indicates lost.
-			 */
-			addFlags(offset, frame.header.nOfSamplesPerFrame);
+		uint32_t newSecSampleNr0 = frame.header.sampleNr & (frame.header.nOfSamplesPerFrame - 1); // 0, or 512 by correctSampleNr()
+		offset += frame.header.sampleNr - newSecSampleNr0;
+	}
 
-			const uint32_t* crc32 = reinterpret_cast<const uint32_t*>(&frame.payload.data[frame.header.nOfSamplesPerFrame]);
-			LOG_INFO_STR("TBB: crc32: " << frame.header.toString() << " " << *crc32);
-		}
-		else
-#endif
-		if (hasAllZeroDataSamples(frame)) {
-			/* Because of the crc32tbb variant, payloads with only zeros validate as correct.
-			 * Given the used frame size (1024 samples for transient), this is extremenly unlikely
-			 * to be real data. Rather, such zero blocks are from RCUs that are disabled or broken.
-			 * Flag it, but still store the zeros to be able to distinguish from lost frames.
-			 */
-			addFlags(offset, frame.header.nOfSamplesPerFrame);
-		}
+	/*
+	 * Flag lost frame(s) (assume no out-of-order, see below). Assumes all frames have the same nr of samples.
+	 * Note: this cannot detect lost frames at the end of a dataset.
+	 */
+	size_t nskipped = offset - itsDatasetLen;
+	if (nskipped > 0) {
+		addFlags(itsDatasetLen, nskipped);
+		itsRawOut->skip(nskipped * sizeof(frame.payload.data[0])); // skip space of lost frame(s)
+	}
 
-	} else { // spectral mode
-		//uint32_t bandNr  = frame.header.bandsliceNr & TBB_BAND_NR_MASK;
-		//uint32_t sliceNr = frame.header.bandsliceNr >> TBB_SLICE_NR_SHIFT;
+	/*
+	 * On a data checksum error, flag these samples.
+	 * Flag zeroed payloads too, as incredibly unlikely to be correct, but not rejected by crc32tbb.
+	 */
+	if (!crc32tbb(&frame.payload, frame.header.nOfSamplesPerFrame)) {
+		addFlags(offset, frame.header.nOfSamplesPerFrame);
+		const uint32_t* crc32 = reinterpret_cast<const uint32_t*>(&frame.payload.data[frame.header.nOfSamplesPerFrame]);
+		LOG_INFO_STR("TBB: crc32: " << frame.header.toString() << " " << *crc32);
+	} else if (hasAllZeroDataSamples(frame.payload, frame.header.nOfSamplesPerFrame)) {
+		addFlags(offset, frame.header.nOfSamplesPerFrame);
 	}
 
-	if (offset >= itsDatasetLen) {
-		/*
-		 * If writing around HDF5, there is no need to lock. Set the HDF5 dataset size at the end (destr).
-		 * If writing through HDF5, we have to lock and the HDF5 dataset size is updated by HDF5.
-		 */
-		if (usesExternalDataFile()) {
-			if (offset > itsDatasetLen) {
-				itsRawOut.seekp(offset * sizeof(frame.payload.data[0])); // skip space of lost frame(s)
-			}
-			itsRawOut.write(reinterpret_cast<const char*>(frame.payload.data), static_cast<size_t>(frame.header.nOfSamplesPerFrame) * sizeof(frame.payload.data[0]));
-		} else {
-			ScopedLock h5Lock(h5Mutex);
-			itsDataset->resize1D(offset + frame.header.nOfSamplesPerFrame);
-			itsDataset->set1D(offset, frame.payload.data, frame.header.nOfSamplesPerFrame);
-		}
+	// Since we are writing around HDF5, there is no need to lock. Resize the HDF5 dataset at the end (destr).
+	itsRawOut->write(frame.payload.data, static_cast<size_t>(frame.header.nOfSamplesPerFrame) * sizeof(frame.payload.data[0]));
 
-		/*
-		 * Flag lost frame(s) (assume no out-of-order, see below). Assumes all frames have the same nr of samples.
-		 * Note: this cannot detect lost frames at the end of a dataset.
-		 */
-		size_t nflags = offset - itsDatasetLen;
-		if (nflags > 0) {
-			addFlags(itsDatasetLen, nflags);
+	itsTime        = frame.header.time;
+	itsExpSampleNr = frame.header.sampleNr + frame.header.nOfSamplesPerFrame;
+	itsDatasetLen  = offset + frame.header.nOfSamplesPerFrame;
+}
+
+void TBB_Dipole::processSpectralFrameData(const TBB_Frame& frame, const SubbandInfo& subbandInfo) {
+	/*
+	 * Out-of-order or duplicate frames are very unlikely in the LOFAR TBB setup,
+	 * but let us know if it ever happens, then we will adapt this code and addFlags().
+	 */
+	uint32_t sliceNr = frame.header.bandSliceNr >> TBB_SLICE_NR_SHIFT; // cannot sanitize fully: too large values indicate lost data: flag
+	if (frame.header.time < itsTime || (frame.header.time == itsTime && sliceNr < itsExpSliceNr)) {
+		LOG_WARN_STR("TBB: Please notify developer: unhandled out-of-order or duplicate TBB frame: " <<
+                     (unsigned)frame.header.stationID << " " << (unsigned)frame.header.rspID << " " << (unsigned)frame.header.rcuID <<
+                     " " << frame.header.time << " " << itsTime << " " << frame.header.bandSliceNr << " " << itsExpSliceNr);
+		return;
+	}
+
+	off_t offset = 0;
+	if (frame.header.time == itsTime) {
+		offset = itsDatasetLen + sliceNr - itsExpSliceNr;
+	} else { // crossed a seconds boundary, potentially more than once on excessive frame loss
+		// A dump does not have to start at a sec bound, so up till the first bound, we may have had fewer than itsSampleFreq samples.
+		if (itsDatasetLen < (int32_t)itsSampleFreq) {
+			offset = itsDatasetLen;
+			itsTime++;
 		}
+		offset += (off_t)(frame.header.time - itsTime) * itsSampleFreq + sliceNr;
+	}
 
-		itsDatasetLen = offset + frame.header.nOfSamplesPerFrame;
-	} else { // Out-of-order or duplicate frames are very unlikely in the LOFAR TBB setup.
-		// Let us know if it ever happens, then we will do something. (here and in addFlags())
-		LOG_WARN_STR("TBB: Dropped out-of-order or duplicate TBB frame at " << frame.header.stationID <<
-				" " << frame.header.rspID << " " << frame.header.rcuID << " " << offset);
+	/*
+	 * Flag lost frame(s) (assume no out-of-order, see below). Assumes all frames have the same nr of samples.
+	 * Note: this cannot detect lost frames at the end of a dataset.
+	 */
+	unsigned nSamplesPerSubband = frame.header.nOfSamplesPerFrame / itsNrSubbands; // TODO: remainder is zeroed??? chksum pos???
+	size_t nskipped = offset - itsDatasetLen;
+	if (nskipped > 0) {
+////		addFlags(itsDatasetLen, nskipped); // no need to skip/lseek; we use pwrite() below
+	}
+
+	/*
+	 * On a data checksum error, flag these samples.
+	 * Flag zeroed payloads too, as incredibly unlikely to be correct, but not rejected by crc32tbb.
+	 *
+	 * The spec says the crc32 is computed for transient data only, but it is also present and valid for spectral data.
+	 */
+	if (!crc32tbb(&frame.payload, 2 * frame.header.nOfSamplesPerFrame)) {
+////		addFlags(offset, frame.header.nOfSamplesPerFrame);
+		const uint32_t* crc32 = reinterpret_cast<const uint32_t*>(&frame.payload.data[2 * frame.header.nOfSamplesPerFrame]);
+		LOG_INFO_STR("TBB: crc32: " << frame.header.toString() << " " << *crc32);
+	} else if (hasAllZeroDataSamples(frame.payload, 2 * frame.header.nOfSamplesPerFrame)) {
+////		addFlags(offset, frame.header.nOfSamplesPerFrame);
 	}
+
+	unsigned bandNr = frame.header.bandSliceNr & TBB_BAND_NR_MASK;
+	if (bandNr + itsNrSubbands >= RSP_NR_SUBBANDS) {
+		LOG_WARN("TBB: Incorrect band number has been corrected to 0");
+		bandNr = 0; // may also be wrong, but at least mem safe
+	}
+	// Data arrives interleaved, so reorder, one sample at a time. Esp. inefficient if only 1 subband, but fast enough.
+	for (unsigned i = 0; i < nSamplesPerSubband; ++i) {
+		for (unsigned j = 0; j < itsNrSubbands; ++j) {
+			off_t sampleOffset = (offset + subbandInfo.storageIndices[bandNr + j] * SPECTRAL_TRANSFORM_SIZE) * 2 * sizeof(frame.payload.data[0]);
+			pwrite(itsRawOut->fd, &frame.payload.data[2 * (i * itsNrSubbands + j)], 2 * sizeof(frame.payload.data[0]), sampleOffset);
+		}
+		offset += 1;
+	}
+
+	itsTime       = frame.header.time;
+	itsExpSliceNr = sliceNr + frame.header.nOfSamplesPerFrame;
+	itsDatasetLen = offset;
 }
 
-void TBB_Dipole::initTBB_DipoleDataset(const TBB_Header& header, const Parset& parset, const StationMetaData& stationMetaData,
+void TBB_Dipole::initTBB_DipoleDataset(const TBB_Header& header, const Parset& parset,
+                                       const StationMetaData& stationMetaData,
+                                       const SubbandInfo& subbandInfo,
                                        const string& rawFilename, dal::TBB_Station& station) {
-	itsDataset = new dal::TBB_DipoleDataset(station.dipole(header.stationID, header.rspID, header.rcuID));
+	itsDataset = new dal::TBB_DipoleDataset(station.dipole(header.stationID, header.rspID, header.rcuID)); // deleted in destr
 
-	// Create 1-dim, unbounded (-1) dataset. 
+	// Create 1- or 2-dim, unbounded (-1) dataset. 
 	// Override endianess. TBB data is always stored little endian and also received as such, so written as-is on any platform.
-	itsDataset->create1D(0, -1, LOFAR::basename(rawFilename), itsDataset->LITTLE);
+	if (subbandInfo.centralFreqs.empty()) { // transient mode
+		itsDataset->create1D(0, -1, LOFAR::basename(rawFilename), itsDataset->LITTLE);
+
+		itsDataset->sampleNumber().value = header.sampleNr;
+	} else { // spectral mode
+		vector<ssize_t> dims(2), maxdims(2);
+		dims[0]    = 0;
+		dims[1]    = subbandInfo.centralFreqs.size();
+		maxdims[0] = -1; // only the 1st dim can be extendible
+		maxdims[1] = subbandInfo.centralFreqs.size();
+		itsDataset->create(dims, maxdims, LOFAR::basename(rawFilename), itsDataset->LITTLE);
+
+// TODO: enable and add to DAL
+//		itsDataset->sliceNumber().value       = header.bandSliceNr >> TBB_SLICE_NR_SHIFT; // TODO: needed?
+
+//		itsDataset->spectralNofBands().value  = subbandInfo.centralFreqs.size();
+//		itsDataset->spectralBands().value     = subbandInfo.centralFreqs;
+//		itsDataset->spectralBandsUnit().value = "MHz";
+	}
 
 	itsDataset->groupType().value = "DipoleDataset";
 	itsDataset->stationID().value = header.stationID;
 	itsDataset->rspID()    .value = header.rspID;
 	itsDataset->rcuID()    .value = header.rcuID;
 
-	itsDataset->sampleFrequency()    .value = itsSampleFreq / 1000000;
+	itsDataset->sampleFrequency()    .value = header.sampleFreq;
 	itsDataset->sampleFrequencyUnit().value = "MHz";
 
-	itsDataset->time().value = header.time; // in seconds. Note: may have been corrected in correctTransientSampleNr()
-	if (header.nOfFreqBands == 0) { // transient mode
-		itsDataset->sampleNumber().value = header.sampleNr;
-	}
-	itsDataset->samplesPerFrame().value = header.nOfSamplesPerFrame;
+	itsDataset->time().value                = header.time; // in seconds
+
+	itsDataset->samplesPerFrame().value     = header.nOfSamplesPerFrame; // possibly sanitized
 	//itsDataset->dataLength().value is set at the end (destr)
-	//itsDataset->flagOffsets().value is set at the end (destr)
-	itsDataset->nyquistZone().value = parset.nyquistZone();
+	//itsDataset->flagOffsets().value is set at the end (destr) // TODO: remove
+	itsDataset->nyquistZone().value         = parset.nyquistZone();
 
 //#include "MAC/APL/PIC/RSP_Driver/src/CableSettings.h" or "RCUCables.h"
 	// Cable delays (optional) from static meta data.
@@ -328,7 +446,7 @@ maar nu vraag ik me wel weer af of de frequenties of de rcus eerst komen
 		 * decided to store them per antenna.
 		 */
 		itsDataset->antennaNormalVector()  .value = stationMetaData.normalVector;   // 3 doubles
-		itsDataset->antennaRotationMatrix().value = stationMetaData.rotationMatrix; // 9 doubles, 3x3, row-minor
+		itsDataset->antennaRotationMatrix().value = stationMetaData.rotationMatrix; // 9 doubles, 3x3, row-major
 	}
 
 	// Tile beam is the analog beam. Only HBA can have one analog beam; optional.
@@ -352,13 +470,13 @@ maar nu vraag ik me wel weer af of de frequenties of de rcus eerst komen
 	itsDataset->dispersionMeasureUnit().value = "pc/cm^3";
 }
 
-bool TBB_Dipole::hasAllZeroDataSamples(const TBB_Frame& frame) const {
+bool TBB_Dipole::hasAllZeroDataSamples(const TBB_Payload& payload, size_t nTrSamples) const {
 	/*
-	 * Real data only has a few consecutive zero values, so this loop terminates
+	 * Good data only has a few consecutive zero values, so this loop terminates
 	 * quickly, unless the antenna is broken or disabled, which happens sometimes.
 	 */
-	for (size_t i = 0; i < frame.header.nOfSamplesPerFrame; i++) {
-		if (frame.payload.data[i] != 0) {
+	for (size_t i = 0; i < nTrSamples; i++) {
+		if (payload.data[i] != 0) {
 			return false;
 		}
 	}
@@ -369,16 +487,15 @@ bool TBB_Dipole::hasAllZeroDataSamples(const TBB_Frame& frame) const {
 //////////////////////////////////////////////////////////////////////////////
 
 TBB_Station::TBB_Station(const string& stationName, Mutex& h5Mutex, const Parset& parset,
-                         const StationMetaData& stationMetaData, const string& h5Filename,
-                         bool dumpRaw)
+                         const StationMetaData& stationMetaData, const string& h5Filename)
 : itsH5File(dal::TBB_File(h5Filename, dal::TBB_File::CREATE))
 , itsH5Mutex(h5Mutex)
 , itsStation(itsH5File.station(stationName))
 , itsDipoles(MAX_RSPBOARDS/* = per station*/ * NR_RCUS_PER_RSPBOARD) // = 192 for int'l stations
 , itsParset(parset)
 , itsStationMetaData(stationMetaData)
+, itsSubbandInfo(getSubbandInfo(parset))
 , itsH5Filename(h5Filename)
-, itsDumpRaw(dumpRaw)
 {
 	initCommonLofarAttributes();
 	initTBB_RootAttributesAndGroups(stationName);
@@ -393,8 +510,44 @@ TBB_Station::~TBB_Station() {
 	}
 }
 
-string TBB_Station::getRawFilename(unsigned rspID, unsigned rcuID) {
-	string rawFilename = itsH5Filename;
+double TBB_Station::getSubbandCentralFreq(unsigned subbandNr, unsigned nyquistZone, double sampleFreq) const {
+	return (nyquistZone - 1 + (double)subbandNr / RSP_NR_SUBBANDS) * sampleFreq / 2.0;
+}
+
+SubbandInfo TBB_Station::getSubbandInfo(const Parset& parset) const {
+	SubbandInfo info;
+
+	int operatingMode = itsParset.getInt("Observation.TBB.TBBsetting.operatingMode", 0);
+	if (operatingMode == TBB_SPECTRAL_MODE) {
+		vector<unsigned> tbbSubbandList(parset.getUint32Vector("Observation.TBB.TBBsetting.subbandList", true)); // TODO: what happens if key does not exists? exc? also test empty parset
+		if (tbbSubbandList.empty() || tbbSubbandList.size() > MAX_TBB_SPECTRAL_NSAMPLES) {
+			throw InterfaceException("TBB: in spectral mode, the TBB subband list must be non-empty and not too long");
+		}
+		sort(tbbSubbandList.begin(), tbbSubbandList.end());
+
+		unsigned nyquistZone = parset.nyquistZone();
+		unsigned sampleFreq  = parset.clockSpeed() / 1000000;
+		info.centralFreqs.reserve(tbbSubbandList.size());
+		for (size_t i = 0; i < tbbSubbandList.size(); ++i) {
+			info.centralFreqs.push_back(getSubbandCentralFreq(tbbSubbandList[i], nyquistZone, sampleFreq));
+		}
+
+		// "Invert" tbbSubbandList, such that we can later simply lookup where to store a subband.
+		info.storageIndices.resize(RSP_NR_SUBBANDS, (unsigned)-1);
+		for (unsigned i = 0; i < tbbSubbandList.size(); ++i) {
+			unsigned sbNr = tbbSubbandList[i];
+			if (sbNr >= RSP_NR_SUBBANDS) {
+				throw InterfaceException("TBB: all indicated subband numbers must be < 512");
+			}
+			info.storageIndices[sbNr] = i;
+		}
+	}
+
+	return info;
+}
+
+string TBB_Station::getRawFilename(unsigned rspID, unsigned rcuID) const {
+	string rawFilename(itsH5Filename);
 	string rsprcuStr(formatString("_%03u%03u", rspID, rcuID));
 	size_t pos = rawFilename.find('_', rawFilename.find('_') + 1);
 	rawFilename.insert(pos, rsprcuStr); // insert _rsp/rcu IDs after station name (2nd '_')
@@ -408,16 +561,18 @@ void TBB_Station::processPayload(const TBB_Frame& frame) {
 	TBB_Dipole& dipole(itsDipoles.at(frame.header.rspID * NR_RCUS_PER_RSPBOARD + frame.header.rcuID));
 
 	// Each dipole stream is sent to a single port (thread), so no need to grab a mutex here to avoid double init.
-	// Do pass a ref to the h5 mutex for when writing into the HDF5 file.
 	if (!dipole.isInitialized()) {
-		string rawFilename("");
-		if (itsDumpRaw) {
-			rawFilename = getRawFilename(frame.header.rspID, frame.header.rcuID);
-		}
-		dipole.initDipole(frame.header, itsParset, itsStationMetaData, rawFilename, itsStation, itsH5Mutex);
+		string rawFilename(getRawFilename(frame.header.rspID, frame.header.rcuID));
+		// Do pass a ref to the h5 mutex for when writing into the HDF5 file.
+		dipole.init(frame.header, itsParset, itsStationMetaData, itsSubbandInfo,
+                            rawFilename, itsStation, itsH5Mutex);
 	}
 
-	dipole.processFrameData(frame, itsH5Mutex);
+	if (itsSubbandInfo.centralFreqs.empty()) { // transient mode
+		dipole.processTransientFrameData(frame);
+	} else { // spectral mode
+		dipole.processSpectralFrameData(frame, itsSubbandInfo);
+	}
 }
 
 // For timestamp attributes in UTC.
@@ -463,7 +618,7 @@ void TBB_Station::initCommonLofarAttributes() {
 	itsH5File.observationStartMJD().value = toMJD(itsParset.startTime());
 
 	// The stop time can be a bit further than the one actually specified, because we process in blocks.
-	unsigned nrBlocks = floor((itsParset.stopTime() - itsParset.startTime()) / itsParset.CNintegrationTime());
+	unsigned nrBlocks = floor((itsParset.stopTime() - itsParset.startTime()) / itsParset.CNintegrationTime()); // TODO: check vs bf: unsigned nrBlocks = parset.nrBeamFormedBlocks();
 	double stopTime = itsParset.startTime() + nrBlocks * itsParset.CNintegrationTime();
 
 	itsH5File.observationEndUTC().value = utcTimeStr(stopTime);
@@ -474,16 +629,23 @@ void TBB_Station::initCommonLofarAttributes() {
 	// This may not correspond to which station HDF5 groups will be written for TBB, but that is true anyway, regardless of any merging.
 	itsH5File.observationStationsList().value = itsParset.allStationNames(); // TODO: SS beamformer?
 
+	double subbandBandwidth = itsParset.subbandBandwidth();
+	double channelBandwidth = itsParset.channelWidth();
+
+	// if PPF is used, the frequencies are shifted down by half a channel
+	// We'll annotate channel 0 to be below channel 1, but in reality it will
+	// contain frequencies from both the top and the bottom half-channel.
+	double frequencyOffsetPPF = itsParset.nrChannelsPerSubband() > 1 ? 0.5 * channelBandwidth : 0.0;
+
 	const vector<double> subbandCenterFrequencies(itsParset.subbandToFrequencyMapping());
+
 	double min_centerfrequency = *min_element( subbandCenterFrequencies.begin(), subbandCenterFrequencies.end() );
 	double max_centerfrequency = *max_element( subbandCenterFrequencies.begin(), subbandCenterFrequencies.end() );
 	double sum_centerfrequencies = accumulate( subbandCenterFrequencies.begin(), subbandCenterFrequencies.end(), 0.0 );
 
-	double subbandBandwidth = itsParset.subbandBandwidth();
-
-	itsH5File.observationFrequencyMax()   .value = (max_centerfrequency + subbandBandwidth / 2) / 1e6;
-	itsH5File.observationFrequencyMin()   .value = (min_centerfrequency - subbandBandwidth / 2) / 1e6;
-	itsH5File.observationFrequencyCenter().value = sum_centerfrequencies / subbandCenterFrequencies.size();
+	itsH5File.observationFrequencyMax()   .value = (max_centerfrequency + subbandBandwidth / 2 - frequencyOffsetPPF) / 1e6;
+	itsH5File.observationFrequencyMin()   .value = (min_centerfrequency - subbandBandwidth / 2 - frequencyOffsetPPF) / 1e6;
+	itsH5File.observationFrequencyCenter().value = (sum_centerfrequencies / subbandCenterFrequencies.size() - frequencyOffsetPPF) / 1e6;
 	itsH5File.observationFrequencyUnit()  .value = "MHz";
 
 	itsH5File.observationNofBitsPerSample().value = itsParset.nrBitsPerSample();
@@ -517,12 +679,11 @@ void TBB_Station::initCommonLofarAttributes() {
 // The writer creates one HDF5 file per station, so create only one Station Group here.
 void TBB_Station::initTBB_RootAttributesAndGroups(const string& stName) {
 	int operatingMode = itsParset.getInt("Observation.TBB.TBBsetting.operatingMode", 0);
-	if (operatingMode == 1) {
-		itsH5File.operatingMode().value = "transient";
-	} else if (operatingMode == 2) {
+	if (operatingMode == TBB_SPECTRAL_MODE) {
 		itsH5File.operatingMode().value = "spectral";
-	} else { // should not happen, parset assumed to be ok
-		LOG_WARN("TBB: Failed to get operating mode from parset");
+//		itsH5File.spectralTransformSize().value = SPECTRAL_TRANSFORM_SIZE; // TODO: enable and add to DAL
+	} else {
+		itsH5File.operatingMode().value = "transient";
 	}
 
 	itsH5File.nofStations().value = 1u;
@@ -535,17 +696,20 @@ void TBB_Station::initTBB_RootAttributesAndGroups(const string& stName) {
 
 	vector<double> stationPositions(itsParset.positions()); // len must be (is generated as) 3x #stations
 	vector<double>::const_iterator posIt(stationPositions.begin());
-
+	string stFullName;
 	for ( ; nameIt != obsStationNames.end(); ++nameIt, posIt += 3) {
-		if (*nameIt == stName) { // both include "HBA0" or similar suffix
+		stFullName = *nameIt;
+		if (stName == stFullName.substr(0, stName.size())) { // for TBB, consider "CS001" == "CS001HBA0" etc
 			break;
 		}
 	}
 	if (nameIt != obsStationNames.end() && posIt < stationPositions.end()) { // found?
 		stPos.assign(posIt, posIt + 3);
+	} else { // N/A, but create the group anyway to be able to store incoming data.
+		stFullName.clear();
 	}
 	itsStation.create();
-	initStationGroup(itsStation, stName, stPos);
+	initStationGroup(itsStation, stName, stFullName, stPos);
 
 	// Trigger Group
 	dal::TBB_Trigger tg(itsH5File.trigger());
@@ -553,26 +717,32 @@ void TBB_Station::initTBB_RootAttributesAndGroups(const string& stName) {
 	initTriggerGroup(tg);
 }
 
-void TBB_Station::initStationGroup(dal::TBB_Station& st, const string& stName, const vector<double>& stPosition) {
+void TBB_Station::initStationGroup(dal::TBB_Station& st, const string& stName,
+                                   const string& stFullName, const vector<double>& stPosition) {
 	st.groupType()  .value = "StationGroup";
 	st.stationName().value = stName;
 
 	if (!stPosition.empty()) {
 		st.stationPosition()     .value = stPosition;
 		st.stationPositionUnit() .value = "m";
-		st.stationPositionFrame().value = itsParset.positionType(); // "ITRF"
+		st.stationPositionFrame().value = itsParset.positionType();
 	}
 
 	// digital beam(s)
-	if (itsParset.nrBeams() > 0) { // TODO: What if >1 station beams? For now, only write beam 0.
+	if (itsParset.nrBeams() > 0) { // TODO: adapt DAL, so we can write all digital beams, analog too if tiles (HBA)
 		st.beamDirection()     .value = itsParset.getBeamDirection(0);
-		st.beamDirectionFrame().value = itsParset.getBeamDirectionType(0);
 		st.beamDirectionUnit() .value = "m";
+		st.beamDirectionFrame().value = itsParset.getBeamDirectionType(0);
 	}
 
-	// clockCorrectionTime() returns 0.0 if stName is unknown, while 0.0 is valid for some stations... TODO: call underlying function
-	st.clockOffset()    .value = itsParset.clockCorrectionTime(stName);
-	st.clockOffsetUnit().value = "s";
+	// Parset clockCorrectionTime() also returns 0.0 if stFullName is unknown. Avoid this ambiguity.
+	try {
+		double clockCorr = itsParset.getDouble(string("PIC.Core.") + stFullName + ".clockCorrectionTime");
+		st.clockOffset()    .value = clockCorr;
+		st.clockOffsetUnit().value = "s";
+	} catch (APSException& exc) {
+		LOG_WARN_STR("TBB: failed to write clock correction and offset attributes: " << exc);
+	}
 
 	//st.nofDipoles.value is set at the end (destr)
 }
@@ -590,7 +760,7 @@ void TBB_Station::initTriggerGroup(dal::TBB_Trigger& tg) {
 		tg.paramElevationMin()       .value = itsParset.getDouble("Observation.ObservationControl.StationControl.TBBControl.MinElevation");
 		tg.paramFitVarianceMax()     .value = itsParset.getDouble("Observation.ObservationControl.StationControl.TBBControl.MaxFitVariance");
 	} catch (APSException& exc) {
-		LOG_WARN("TBB: Failed to write all trigger parameters: missing from parset");
+		LOG_WARN_STR("TBB: Failed to write trigger parameters: " << exc);
 	}
 
 	// Trigger data (per trigger)
@@ -605,19 +775,30 @@ void TBB_Station::initTriggerGroup(dal::TBB_Trigger& tg) {
 	 *
 	 * If you add fields using parset getTYPE(), catch the possible APSException as above.
 	 */
+
 }
 
 //////////////////////////////////////////////////////////////////////////////
 
-TBB_StreamWriter::TBB_StreamWriter(TBB_Writer& writer, const string& inputStreamName, const string& logPrefix)
+TBB_StreamWriter::TBB_StreamWriter(TBB_Writer& writer, const string& inputStreamName,
+                                   size_t expNTrSamples, const string& logPrefix,
+                                   int& inExitStatus, int& outExitStatus)
 : itsWriter(writer)
 , itsInputStreamName(inputStreamName)
+, itsExpFrameSize(sizeof(TBB_Header) + expNTrSamples * sizeof(int16_t) + sizeof(uint32_t))
 , itsLogPrefix(logPrefix)
+, itsInExitStatus(inExitStatus)
+, itsOutExitStatus(outExitStatus)
 {
 	itsFrameBuffers = new TBB_Frame[nrFrameBuffers];
 	//itsReceiveQueue.reserve(nrFrameBuffers); // Queue does not support this...
-	for (unsigned i = nrFrameBuffers; i > 0; ) {
-		itsFreeQueue.append(&itsFrameBuffers[--i]);
+	try {
+		for (unsigned i = nrFrameBuffers; i > 0; ) {
+			itsFreeQueue.append(&itsFrameBuffers[--i]);
+		}
+	} catch (exception& exc) {
+		delete[] itsFrameBuffers;
+		throw;
 	}
 
 	itsTimeoutStamp.tv_sec = 0;
@@ -639,12 +820,24 @@ TBB_StreamWriter::TBB_StreamWriter(TBB_Writer& writer, const string& inputStream
 		delete[] itsFrameBuffers;
 		throw;
 	}
+
+#ifdef DUMP_RAW_STATION_DATA
+	string rawStDataFilename("station_data_" + formatString("%zu", itsFrameBuffers) + ".raw");
+	try {
+		itsRawStationData = new FileStream(rawStDataFilename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
+	} catch (exception& exc) {
+		LOG_WARN_STR("Failed to open raw station data file: " << exc.what());
+	}
+#endif
 }
 
 TBB_StreamWriter::~TBB_StreamWriter() {
-	// Only cancel input thread. It will notify the output thread.
+	// Only cancel the input thread, which will notify the output thread.
 	itsInputThread->cancel();
 
+#ifdef DUMP_RAW_STATION_DATA
+	delete itsRawStationData;
+#endif
 	delete itsInputThread;
 	delete itsOutputThread;
 	delete[] itsFrameBuffers;
@@ -655,28 +848,25 @@ time_t TBB_StreamWriter::getTimeoutStampSec() const {
 }
 
 void TBB_StreamWriter::frameHeaderLittleToHost(TBB_Header& header) const {
-	//header.seqNr              = le32toh(header.seqNr); // (must be) zeroed, but otherwise not useful for us
+	header.seqNr              = le32toh(header.seqNr); // to be zeroed to check header crc; otherwise not so useful
 	header.time               = le32toh(header.time);
-	header.sampleNr           = le32toh(header.sampleNr); // also swaps header.bandsliceNr
+	header.sampleNr           = le32toh(header.sampleNr); // also swaps header.bandSliceNr
 	header.nOfSamplesPerFrame = le16toh(header.nOfSamplesPerFrame);
 	header.nOfFreqBands       = le16toh(header.nOfFreqBands);
-	//header.spare              = le16toh(header.spare); // unused
+	header.spare              = le16toh(header.spare); // unused
 	header.crc16              = le16toh(header.crc16);
 }
 
-void TBB_StreamWriter::correctTransientSampleNr(TBB_Header& header) const {
+void TBB_StreamWriter::correctSampleNr(TBB_Header& header) const {
 	/*
-	 * LOFAR antennas have a header.sampleFreq of either 200 or 160 MHz (another multiple of #samples per frame is also fine).
-	 * 
-	 * At 200 MHz sample rate with 1024 samples per frame, we have 195213.5 frames per second.
-	 * This means that every 2 seconds, a frame overlaps a seconds boundary; every odd frame needs its sampleNr corrected.
+	 * LOFAR uses a sample rate of either 200 or 160 MHz.
+	 * In transient mode, at 200 MHz we get 1024 samples per frame, and thus 195213.5 frames per second.
+	 * This means that every 2 seconds, a frame overlaps a seconds boundary. But the sample values generated
+	 * by the RSPs start at zero for each second, even if it should start at 512 for odd timestamps at 200 MHz.
 	 * At 160 MHz sample rate, an integer number of frames fits in a second (156250), so no correction is needed.
-	 *
-	 * This fixup assumes no other sample freq than 200 MHz that needs a correction is used (checked in initDipole()),
-	 * and that the hw time nr starts even (cannot be checked, because dumps can start at any frame, but it is 0, thus fine).
 	 */
 	if (header.sampleFreq == 200 && header.time & 1) {
-		header.sampleNr += DEFAULT_TRANSIENT_NSAMPLES / 2;
+		header.sampleNr += header.nOfSamplesPerFrame / 2;
 	}
 }
 
@@ -689,16 +879,14 @@ bool TBB_StreamWriter::crc16tbb(const TBB_Header* header) {
 
 	/*
 	 * The header checksum is done like the data, i.e. on 16 bit little endian blocks at a time.
-	 * As with the data, both big and little endian CPUs need to byte swap.
+	 * As with the data crc, both big and little endian CPUs need to byte swap.
 	 */
-	const int16_t* ptr = reinterpret_cast<const int16_t*>(header);
-	size_t i;
-	for (i = 0; i < (sizeof(*header) - sizeof(header->crc16)) / sizeof(int16_t); i++) {
+	const int16_t* ptr = reinterpret_cast<const int16_t*>(header); // TODO: access cross-type through char or uchar ptrs (or memcpy), in all reint_cast cases in the code: unsigned char *ptr = (unsigned char*)&floatVar; // and then accessing ptr[0] to ptr[sizeof(floatVar)-1] is legal.
+	for (size_t i = 0; i < (sizeof(*header) - sizeof(header->crc16)) / sizeof(int16_t); i++) {
 		int16_t val = __bswap_16(ptr[i]);
 		itsCrc16gen.process_bytes(&val, sizeof(int16_t));
 	}
 
-	// Byte swap the little endian checksum on big endian only.
 	// It is also possible to process header->crc16 and see if checksum() equals 0.
 	uint16_t crc16val = header->crc16;
 #if __BYTE_ORDER == __BIG_ENDIAN
@@ -708,9 +896,10 @@ bool TBB_StreamWriter::crc16tbb(const TBB_Header* header) {
 }
 
 /*
- * Note: The nsamples arg is without the space taken by the crc32 in payload. (Drop too small frames earlier.)
+ * Note: The nTrSamples arg is without the space taken by the crc32 in payload (drop too small frames earlier)
+ * and in terms of the transient sample size, i.e. sizeof(int16_t).
  */
-bool TBB_Dipole::crc32tbb(const TBB_Payload* payload, size_t nsamples) {
+bool TBB_Dipole::crc32tbb(const TBB_Payload* payload, size_t nTrSamples) {
 	itsCrc32gen.reset();
 
 	/*
@@ -718,15 +907,13 @@ bool TBB_Dipole::crc32tbb(const TBB_Payload* payload, size_t nsamples) {
 	 * in little and the boost routines treat it as uint8_t[] (big).
 	 */
 	const int16_t* ptr = reinterpret_cast<const int16_t*>(payload->data);
-	size_t i;
-	for (i = 0; i < nsamples; i++) {
+	for (size_t i = 0; i < nTrSamples; i++) {
 		int16_t val = __bswap_16(ptr[i]);
 		itsCrc32gen.process_bytes(&val, sizeof(int16_t));
 	}
 
-	// Byte swap the little endian checksum on big endian only.
 	// It is also possible to process crc32val and see if checksum() equals 0.
-	uint32_t crc32val = *reinterpret_cast<const uint32_t*>(&ptr[nsamples]);
+	uint32_t crc32val = *reinterpret_cast<const uint32_t*>(&ptr[nTrSamples]);
 #if __BYTE_ORDER == __BIG_ENDIAN
 	crc32val = __bswap_32(crc32val);
 #endif
@@ -738,91 +925,113 @@ bool TBB_Dipole::crc32tbb(const TBB_Payload* payload, size_t nsamples) {
  * Note that this function may update the header, but not its crc, so you cannot re-verify it.
  */
 void TBB_StreamWriter::processHeader(TBB_Header& header, size_t recvPayloadSize) {
-#ifndef DISABLE_CRCS
 	header.seqNr = 0; // For the header crc. Don't save/restore it as we don't need this field.
 	if (!crc16tbb(&header)) {
 		/*
-		 * Spec says each frame has the same fixed length, so the previous values are a good base guess if the header crc fails.
-		 * But it is not clear if it is worth the effort. For now, drop the frame.
+		 * The TBB spec states that each frame has the same fixed length, so the previous values are a good base guess if the header crc fails.
+		 * But it is not clear if it is worth the effort to try to guess to fix something up. More likely there is a bug, so for now, drop the frame.
 		 */
-		throw TBB_MalformedFrameException("crc16: " + header.toString());
+		throw TBB_MalformedFrameException("crc16: " + header.toString()); // printed header not bswapped on big endian
 	}
-#endif
-
-	frameHeaderLittleToHost(header); // no-op on little endian
 
-	if (header.nOfFreqBands == 0) { // transient mode
-		// Use received size instead of received nOfSamplesPerFrame header field to access data.
-		if (recvPayloadSize < 2 * sizeof(int16_t) + sizeof(uint32_t)) {
-			// Drop it. The data crc routine only works for at least 2 data elements + a crc32.
-			throw TBB_MalformedFrameException("dropping too small TBB transient frame");
-		}
-		uint16_t recvSamples = (recvPayloadSize - sizeof(uint32_t)) / sizeof(int16_t);
-		header.nOfSamplesPerFrame = recvSamples; // most likely already DEFAULT_TRANSIENT_NSAMPLES
+	/*
+	 * Use received size instead of received nOfSamplesPerFrame header field to access data, to be safe.
+	 * Just write it into the header; it's most likely already there.
+	 */
+	if (recvPayloadSize < 2 * sizeof(int16_t) + sizeof(uint32_t)) {
+		// Drop it. The data crc routine only works for at least 2 transient or 1 spectral sample(s) + a crc32.
+		throw TBB_MalformedFrameException("dropping too small frame: " + recvPayloadSize);
+	}
+	frameHeaderLittleToHost(header);
+	// Verify indicated sample freq, also to reject zeroed headers, which the crc16tbb does not reject.
+	if (header.sampleFreq != 200 && header.sampleFreq != 160) {
+		throw TBB_MalformedFrameException("invalid sample frequency in frame header: " + header.sampleFreq);
+	}
 
-		correctTransientSampleNr(header);
+	size_t sampleSize;
+	if (header.nOfFreqBands == 0) { // transient mode TODO: do not rely on data to check data size!
+		correctSampleNr(header);
+		sampleSize = sizeof(int16_t);
 	} else { // spectral mode
-		if (recvPayloadSize < sizeof(int16_t)) {
-			throw TBB_MalformedFrameException("dropping too small TBB spectral frame");
-		}
-		uint16_t recvSamples = recvPayloadSize / (2 * sizeof(int16_t));
-		header.nOfSamplesPerFrame = recvSamples;
+		sampleSize = 2 * sizeof(int16_t);
 	}
+	// Div with a bad recvPayloadSize could round. Causes crc32 error at worst, but avoids wrong or misaligned memory access.
+	header.nOfSamplesPerFrame = (recvPayloadSize - sizeof(uint32_t)) / sampleSize;
 }
 
 void TBB_StreamWriter::mainInputLoop() {
-	LOG_INFO_STR(itsLogPrefix << "Waiting for incoming data at " << itsInputStreamName);
-	Stream* stream = createStream(itsInputStreamName, true); // allocates, but wrapped in an obj proved a hassle
+	// Always (try to) notify output thread to stop at the end.
+	class NotifyOutputThread {
+		Queue<TBB_Frame*>& queue;
+	public:
+		NotifyOutputThread(Queue<TBB_Frame*>& queue) : queue(queue) { }
+		~NotifyOutputThread() {
+			try {
+				queue.append(NULL);
+			} catch (exception& exc) {
+				LOG_WARN_STR("TBB: may have failed to notify output thread to terminate: " << exc.what());
+			}
+		}
+	} notifyOutThr(itsReceiveQueue);
+
+	Stream* stream;
+	try {
+		stream = createStream(itsInputStreamName, true);
+	} catch (Exception& exc) { // SystemCallException or InterfaceException (or TimeOutException)
+		LOG_WARN_STR(itsLogPrefix << exc);
+		return; // do not set itsInExitStatus to 1: if not all files with "$" replaced exist, that's fine
+	}
+	LOG_INFO_STR(itsLogPrefix << "reading incoming data from " << itsInputStreamName);
 
 	while (1) {
 		TBB_Frame* frame;
 
 		try {
-			frame = NULL;
-			frame = itsFreeQueue.remove();
+			frame = itsFreeQueue.remove(); // may only throw SystemCallException
+
+			size_t nread = stream->tryRead(frame, itsExpFrameSize); // cannot simply retry until expected size: UDP used unless local test
 
-			size_t datagramSize = stream->tryRead(frame, sizeof(*frame));
+			// Notify master that we are still busy. (Racy, but ok, see the timeoutstamp decl.)
+			::gettimeofday(&itsTimeoutStamp, NULL);
 
-			// Notify master that we are still busy. (Racy, see TS decl)
-			gettimeofday(&itsTimeoutStamp, NULL);
+#ifdef DUMP_RAW_STATION_DATA
+			try {
+				itsRawStationData->write(frame, nread);
+			} catch (exception& exc) { /* open() probably failed, don't spam */ }
+#endif
 
-			if (datagramSize < sizeof(TBB_Header)) {
+			if (nread < sizeof(TBB_Header)) {
 				throw TBB_MalformedFrameException("dropping too small TBB frame");
 			}
-			processHeader(frame->header, datagramSize - sizeof(TBB_Header));
+			processHeader(frame->header, nread - sizeof(TBB_Header));
 
 			itsReceiveQueue.append(frame);
+
 		} catch (TBB_MalformedFrameException& mffExc) {
-			LOG_WARN_STR(itsLogPrefix << mffExc.what());
-			if (frame != NULL) {
+			LOG_WARN_STR(itsLogPrefix << mffExc);
+			try {
 				itsFreeQueue.append(frame);
+			} catch (exception& exc) {
+				LOG_WARN_STR(itsLogPrefix << "may have lost a frame buffer (1): " << exc.what());
 			}
-		} catch (Stream::EndOfStreamException& ) { // we use thread cancellation, but just in case
-			LOG_INFO_STR(itsLogPrefix << "EndOfStreamException");
+		} catch (Stream::EndOfStreamException& ) { // after end of stream, for input from file or pipe
 			break;
 		} catch (exception& exc) {
 			LOG_FATAL_STR(itsLogPrefix << exc.what());
+			itsInExitStatus = 1;
 			break;
-		} catch (...) { // Cancellation exc happens at exit. Nothing to do, so disabled. Otherwise, must rethrow.
+		} catch (...) { // thread cancellation exc induced after timeout, for input from udp
 			delete stream;
-			try {
-				itsReceiveQueue.append(NULL); // always notify output thread at exit of no more data
-			} catch (exception& exc) {
-				LOG_WARN_STR(itsLogPrefix << "may have failed to notify output thread to terminate: " << exc.what());
-			}
-			throw;
+			throw; // mandatory
 		}
 	}
 
 	delete stream;
-	itsReceiveQueue.append(NULL);
 }
 
 void TBB_StreamWriter::mainOutputLoop() {
-	const unsigned maxErrors = 16;
-	unsigned nrErrors = 0; // i.e. per output thread per dump
-
-	while (1) {
+	bool running = true;
+	while (running) {
 		TBB_Frame* frame;
 		try {
 			frame = NULL;
@@ -837,20 +1046,30 @@ void TBB_StreamWriter::mainOutputLoop() {
 
 			TBB_Station* station = itsWriter.getStation(frame->header);
 			station->processPayload(*frame);
+
+		// Tolerate the following exceptions. Maybe next rsp/rcu is ok; probably fatal too...
+		} catch (SystemCallException& exc) {
+			LOG_WARN_STR(itsLogPrefix << exc);
+		} catch (StorageException& exc) {
+			LOG_WARN_STR(itsLogPrefix << exc);
+		} catch (dal::DALException& exc) {
+			LOG_WARN_STR(itsLogPrefix << exc.what());
+		} catch (out_of_range& exc) {
+			LOG_WARN_STR(itsLogPrefix << exc.what());
+
+		// Config/parset and other errors are fatal.
 		} catch (exception& exc) {
-			// e.g. std::out_of_range for at() on bad rsp/rcu ID,
-			// DALException, or StorageException/SystemCallException on failed to create file.
-			nrErrors += 1;
-			if (nrErrors < maxErrors) {
-				LOG_WARN_STR(itsLogPrefix << exc.what());
-			} else {
-				LOG_FATAL_STR(itsLogPrefix << exc.what());
-				break;
-			}
+			LOG_FATAL_STR(itsLogPrefix << exc.what());
+			itsOutExitStatus = 1;
+			running = false;
 		}
 
 		if (frame != NULL) {
-			itsFreeQueue.append(frame);
+			try {
+				itsFreeQueue.append(frame);
+			} catch (exception& exc) {
+				LOG_WARN_STR(itsLogPrefix << "may have lost a frame buffer (2): " << exc.what());
+			}
 		}
 	}
 }
@@ -858,12 +1077,12 @@ void TBB_StreamWriter::mainOutputLoop() {
 //////////////////////////////////////////////////////////////////////////////
 
 TBB_Writer::TBB_Writer(const vector<string>& inputStreamNames, const Parset& parset,
-                       const StationMetaDataMap& stationMetaDataMap, const string& outDir, bool dumpRaw,
-                       const string& logPrefix)
+                       const StationMetaDataMap& stationMetaDataMap,
+                       const string& outDir, const string& logPrefix,
+                       vector<int>& thrExitStatus)
 : itsParset(parset)
 , itsStationMetaDataMap(stationMetaDataMap)
 , itsOutDir(outDir)
-, itsDumpRaw(dumpRaw)
 , itsRunNr(0)
 {
 	// Mask all signals to inherit for workers. This forces signals to be delivered to the main thread.
@@ -873,16 +1092,16 @@ TBB_Writer::TBB_Writer(const vector<string>& inputStreamNames, const Parset& par
 
 		SigMask() {
 			sigset_t sigset_all_masked;
-			sigfillset(&sigset_all_masked);
-			if (pthread_sigmask(SIG_SETMASK, &sigset_all_masked, &sigset_old) != 0) {
+			::sigfillset(&sigset_all_masked);
+			if (::pthread_sigmask(SIG_SETMASK, &sigset_all_masked, &sigset_old) != 0) {
 				// The LOFAR sys uses another way to control us, so do not make this fatal.
 				LOG_WARN_STR("TBB: pthread_sigmask() failed to mask signals to inherit for worker threads.");
 			}
 		}
 
 		~SigMask() {
-			if (pthread_sigmask(SIG_SETMASK, &sigset_old, NULL) != 0) {
-				// No exc in destr. If restoring fails and --keeprunning, we remain deaf.
+			if (::pthread_sigmask(SIG_SETMASK, &sigset_old, NULL) != 0) {
+				// No exc in destr. If restoring fails and keepRunning = true, we remain deaf.
 				LOG_WARN_STR("TBB: pthread_sigmask() failed to restore signals. We may be deaf to signals.");
 			}
 		}
@@ -890,20 +1109,32 @@ TBB_Writer::TBB_Writer(const vector<string>& inputStreamNames, const Parset& par
 
 	itsUnknownStationMetaData.available = false;
 
+	size_t expNTrSamples; // in terms of the transient sample size
+	int operatingMode = itsParset.getInt("Observation.TBB.TBBsetting.operatingMode", 0);
+	if (operatingMode == TBB_TRANSIENT_MODE) {
+		expNTrSamples = DEFAULT_TBB_TRANSIENT_NSAMPLES;
+	} else if (operatingMode == TBB_SPECTRAL_MODE) {
+		expNTrSamples = 2 * DEFAULT_TBB_SPECTRAL_NSAMPLES;
+	} else {
+		LOG_WARN("TBB: Failed to get operating mode from parset, assuming transient");
+	}
+
+	itsStreamWriters.reserve(inputStreamNames.size());
 	for (unsigned i = 0; i < inputStreamNames.size(); i++) {
-		itsStreamWriters.push_back(new TBB_StreamWriter(*this, inputStreamNames[i], logPrefix)); // TODO: leaks just created obj if push_back() fails
+		itsStreamWriters.push_back(new TBB_StreamWriter(*this, inputStreamNames[i], expNTrSamples,
+                                   logPrefix, thrExitStatus[2*i], thrExitStatus[2*i+1]));
 	}
 }
 
 TBB_Writer::~TBB_Writer() {
+	for (unsigned i = itsStreamWriters.size(); i > 0; ) {
+		delete itsStreamWriters[--i];
+	}
+
 	map<unsigned, TBB_Station* >::iterator it(itsStations.begin());
 	for ( ; it != itsStations.end(); ++it) {
 		delete it->second;
 	}
-
-	for (unsigned i = itsStreamWriters.size(); i > 0; ) {
-		delete itsStreamWriters[--i];
-	}
 }
 
 TBB_Station* TBB_Writer::getStation(const TBB_Header& header) {
@@ -923,13 +1154,12 @@ TBB_Station* TBB_Writer::getStation(const TBB_Header& header) {
 	TBB_Station* station;
 	{
 		ScopedLock slH5(itsH5Mutex);
-		station = new TBB_Station(stationName, itsH5Mutex, itsParset, stMetaData, h5Filename, itsDumpRaw); // TODO: mem leak if insert() fails. (But if destr here, destructor is not thread-safe.)
+		station = new TBB_Station(stationName, itsH5Mutex, itsParset, stMetaData, h5Filename); // TODO: must guarantee insert() cannot fail, else leaks; destr here is unsafe
 	}
 
 	return itsStations.insert(make_pair(header.stationID, station)).first->second;
 }
 
-// Must be called holding itsStationsMutex.
 string TBB_Writer::createNewTBB_H5Filename(const TBB_Header& header, const string& stationName) {
 	const string typeExt("tbb.h5");
 	string obsIDStr(formatString("%u", itsParset.observationID()));
@@ -937,11 +1167,13 @@ string TBB_Writer::createNewTBB_H5Filename(const TBB_Header& header, const strin
 	// Use the recording time of the first (received) frame as timestamp.
 	struct timeval tv;
 	tv.tv_sec = header.time;
+	unsigned long usecNr;
 	if (header.nOfFreqBands == 0) { // transient mode
-		tv.tv_usec = static_cast<unsigned long>(round( static_cast<double>(header.sampleNr) / header.sampleFreq ));
+		usecNr = header.sampleNr;
 	} else { // spectral mode
-		tv.tv_usec = 0;
+		usecNr = header.bandSliceNr >> TBB_SLICE_NR_SHIFT;
 	}
+	tv.tv_usec = static_cast<unsigned long>(round( static_cast<double>(usecNr) / header.sampleFreq ));
 
 	// Generate the output filename, because for TBB it is not in the parset.
 	// From LOFAR-USG-ICD005 spec named "LOFAR Data Format ICD File Naming Conventions", by A. Alexov et al.
@@ -954,10 +1186,10 @@ string TBB_Writer::createNewTBB_H5Filename(const TBB_Header& header, const strin
 	// If the file already exists, add a run nr and retry. (seq race with DAL's open and doesn't check .raw, but good enough)
 	// If >1 stations per node, start at the prev run nr if any (hence itsRunNr).
 	if (itsRunNr == 0) {
-		if (access(h5Filename.c_str(), F_OK) != 0 && errno == ENOENT) {
+		if (::access(h5Filename.c_str(), F_OK) != 0 && errno == ENOENT) {
 			// Does not exist (or broken dir after all, or dangling sym link...). Try this one.
 			return h5Filename;
-		} else { // Exists, inc run number. 
+		} else { // exists, inc run number
 			itsRunNr = 1;
 		}
 	}
@@ -965,7 +1197,7 @@ string TBB_Writer::createNewTBB_H5Filename(const TBB_Header& header, const strin
 	size_t pos = h5Filename.size() - typeExt.size();
 	string runNrStr(formatString("R%03u_", itsRunNr));
 	h5Filename.insert(pos, runNrStr);
-	while (itsRunNr < 1000 && ( access(h5Filename.c_str(), F_OK) == 0 || errno != ENOENT )) {
+	while (itsRunNr < 1000 && ( ::access(h5Filename.c_str(), F_OK) == 0 || errno != ENOENT )) {
 		itsRunNr += 1;
 		runNrStr = formatString("R%03u_", itsRunNr);
 		h5Filename.replace(pos, runNrStr.size(), runNrStr);
diff --git a/RTCP/Storage/src/TBB_Writer_main.cc b/RTCP/Storage/src/TBB_Writer_main.cc
index a7dc45e498c504885623da5d32623d3ce2b5ff41..22ad98aedac9be82acd0a422a0abb1b7400d195c 100644
--- a/RTCP/Storage/src/TBB_Writer_main.cc
+++ b/RTCP/Storage/src/TBB_Writer_main.cc
@@ -17,23 +17,17 @@
  * You should have received a copy of the GNU General Public License along
  * with the LOFAR software suite.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * $Id: TBB_Writer_main.cc 17682 2012-09-07 18:58:53Z amesfoort $
- *
- * @author Alexander S. van Amesfoort
- * Parts derived from the BF writer written by Jan David Mol, and from
- * TBB writers written by Lars Baehren, Andreas Horneffer, and Joseph Masters.
+ * $Id: TBB_Writer_main.cc 17261 2012-09-07 18:58:53Z amesfoort $
  */
 
-/*
- * NOTE: Only transient data mode has been implemented and tested.
- * TODO: Some code for spectral mode is implemented, but it could never be tested and the TBB HDF5 format considers transient data only.
+/* @author Alexander S. van Amesfoort
+ * Parts derived from the BF writer written by Jan David Mol, and from
+ * TBB writers written by Lars Baehren, Andreas Horneffer, and Joseph Masters.
  */
 
-#define _POSIX_C_SOURCE			1	// sigaction(2)
-#define _GNU_SOURCE			1	// getopt_long(3)
-
 #include <lofar_config.h>			// before any other include
 
+#define _FILE_OFFSET_BITS 64
 #include <cstddef>
 #include <cstdlib>
 #include <csignal>
@@ -54,6 +48,7 @@
 #include <Common/LofarLogger.h>
 #include <Common/StringUtil.h>
 #include <Common/NewHandler.h>
+#include <ApplCommon/StationConfig.h>
 #include <ApplCommon/AntField.h>
 #include <Interface/Exceptions.h>
 #include <Storage/IOPriority.h>
@@ -63,19 +58,23 @@
 #define TBB_DEFAULT_BASE_PORT		0x7bb0	// i.e. tbb0
 #define TBB_DEFAULT_LAST_PORT		0x7bbb	// 0x7bbf for NL, 0x7bbb for int'l stations
 
+#define STDLOG_BUFFER_SIZE			1024
+
 using namespace std;
 
 struct progArgs {
 	string parsetFilename;
 	string antFieldDir;
 	string outputDir;
-	string proto;
+	string input;
 	uint16_t port;
 	struct timeval timeoutVal;
 	bool keepRunning;
-	bool rawDataFiles;
 };
 
+static char stdoutbuf[STDLOG_BUFFER_SIZE];
+static char stderrbuf[STDLOG_BUFFER_SIZE];
+
 // Install a new handler to produce backtraces for std::bad_alloc.
 LOFAR::NewHandler badAllocExcHandler(LOFAR::BadAllocException::newHandler);
 
@@ -110,25 +109,34 @@ static void setTermSigsHandler() {
 	}
 }
 
-static vector<string> getTBB_InputStreamNames(const string& proto, uint16_t portsBase) {
-	/*
-	 * Proto: TBB always arrives over UDP (but command-line override).
-	 * 
-	 * Ports: Each board sends data to port TBB_DEFAULT_BASE_PORT + itsBoardNr, so that's where put a r/w thread pair each to listen.
-	 * The number of TBB boards can be retrieved using LCS/ApplCommon/src/StationConfig.cc: nrTBBs = StationInfo.getInt("RS.N_TBBOARDS");
-	 * but we know that stations have 6 (NL stations) or 12 (EU stations) TBB boards, so simply use defines.
-	 */
-	vector<string> allInputStreamNames;
+static vector<string> getTBB_InputStreamNames(const string& input, uint16_t portsBase) {
+	int nTbbBoards;
+	try {
+		LOFAR::StationConfig stConf;
+		nTbbBoards = stConf.nrTBBs;
+	} catch (LOFAR::AssertError& ) { // config file not found
+		LOG_DEBUG_STR("Falling back to up to " << TBB_DEFAULT_LAST_PORT - TBB_DEFAULT_BASE_PORT + 1 << " streams (1 per board)");
+		nTbbBoards = TBB_DEFAULT_LAST_PORT - TBB_DEFAULT_BASE_PORT + 1; // fallback
+	}
 
-	if (proto == "udp" || proto == "tcp") {
-		uint16_t portsEnd = portsBase + TBB_DEFAULT_LAST_PORT - TBB_DEFAULT_BASE_PORT;
-		for (uint16_t port = portsBase; port <= portsEnd; port++) {
-			// 0.0.0.0: It would be better to restrict to station IPs/network, but need netmask lookup and need to allow localhost.
-			string streamName(proto + ":0.0.0.0:" + LOFAR::formatString("%hu", port));
+	vector<string> allInputStreamNames;
+	if (input == "udp" || input == "tcp") {
+		for (uint16_t port = portsBase; port <= portsBase + nTbbBoards; ++port) {
+			// 0.0.0.0: could restrict to station IPs/network, but need netmask lookup and allow localhost. Not critical: we are on a separate VLAN.
+			string streamName(input + ":0.0.0.0:" + LOFAR::formatString("%hu", port));
 			allInputStreamNames.push_back(streamName);
 		}
-	} else { // e.g. "file:data/rw_20110719_110541_1110.dat" or "pipe:data/rw_20110719_110541_1110.pipe"
-		allInputStreamNames.push_back(proto);
+	} else { // file or named pipe input
+		size_t placeholderPos = input.find_last_of('%');
+		if (placeholderPos == string::npos) { // single input, no expansion needed
+			allInputStreamNames.push_back(input);
+		} else { // expand: replace e.g. file:x%y-%.raw by file:x%y-0.raw, file:x%y-1.raw, ..., file:x%y-11.raw
+			for (int i = 0; i < nTbbBoards; ++i) {
+				string streamName(input);
+				streamName.replace(placeholderPos, 1, LOFAR::formatString("%u", i));
+				allInputStreamNames.push_back(streamName);
+			}
+		}
 	}
 
 	return allInputStreamNames;
@@ -200,8 +208,9 @@ static LOFAR::RTCP::StationMetaDataMap getExternalStationMetaData(const LOFAR::R
 
 			stMdMap.insert(make_pair(dal::stationNameToID(stName), stMetaData));
 		}
-	} catch (exception& exc) { // LOFAR::AssertError or dal::DALValueError (rare)
-		// AssertError already sends a message to the logger.
+	} catch (LOFAR::AssertError& exc) {
+		// Throwing AssertError already sends a message to the logger.
+	} catch (dal::DALValueError& exc) {
 		throw LOFAR::RTCP::StorageException(exc.what());
 	}
 
@@ -212,11 +221,11 @@ static int doTBB_Run(const vector<string>& inputStreamNames, const LOFAR::RTCP::
                      const LOFAR::RTCP::StationMetaDataMap& stMdMap, struct progArgs& args) {
 	string logPrefix("TBB obs " + LOFAR::formatString("%u", parset.observationID()) + ": ");
 
+	vector<int> thrExitStatus(2 * inputStreamNames.size(), 0);
 	int err = 1;
 	try {
 		// When this obj goes out of scope, worker threads are cancelled and joined with.
-		LOFAR::RTCP::TBB_Writer writer(inputStreamNames, parset, stMdMap,
-                                       args.outputDir, args.rawDataFiles, logPrefix);
+		LOFAR::RTCP::TBB_Writer writer(inputStreamNames, parset, stMdMap, args.outputDir, logPrefix, thrExitStatus);
 
 		/*
 		 * We don't know how much data comes in, so cancel workers when all are idle for a while (timeoutVal).
@@ -234,7 +243,7 @@ static int doTBB_Run(const vector<string>& inputStreamNames, const LOFAR::RTCP::
 		do {
 			pause();
 			if (sigint_seen) { // typically Ctrl-C
-				args.keepRunning = false;
+				args.keepRunning = false; // for main(), not for worker threads
 				break;
 			}
 
@@ -251,15 +260,21 @@ static int doTBB_Run(const vector<string>& inputStreamNames, const LOFAR::RTCP::
 				}
 			}
 		} while (nrWorkersDone < inputStreamNames.size());
-
 		err = 0;
-
 	} catch (LOFAR::Exception& exc) {
-		LOG_FATAL_STR(logPrefix << "LOFAR::Exception: " << exc.text());
+		LOG_FATAL_STR(logPrefix << "LOFAR::Exception: " << exc);
 	} catch (exception& exc) {
 		LOG_FATAL_STR(logPrefix << "std::exception: " << exc.what());
 	}
 
+	// Propagate exit status != 0 from any input or output worker thread.
+	for (unsigned i = 0; i < thrExitStatus.size(); ++i) {
+		if (thrExitStatus[i] != 0) {
+			err = 1;
+			break;
+		}
+	}
+
 	return err;
 }
 
@@ -298,14 +313,12 @@ static void printUsage(const char* progname) {
 	cout << endl;
 	cout << "  -a, --antfielddir=/d/AntennaFields  override $LOFARROOT and parset path for antenna field files (like CS001-AntennaField.conf)" << endl;
 	cout << "  -o, --outputdir=tbbout              output directory" << endl;
-	cout << "  -p, --proto=tcp|udp                 input stream type (default: udp)" << endl;
-	cout << "              file:raw.dat" << endl;
-	cout << "              pipe:named.pipe" << endl;
+	cout << "  -i, --input=tcp|udp                 input stream(s) or type (default: udp)" << endl;
+	cout << "              file:raw.dat                if file or pipe name has a '%'," << endl;
+	cout << "              pipe:named-%.pipe           then the last '%' is replaced by 0, 1, ..., 11" << endl;
 	cout << "  -b, --portbase=31665                start of range of 12 consecutive udp/tcp ports to receive from" << endl;
 	cout << "  -t, --timeout=10                    seconds of input inactivity until dump is considered completed" << endl;
 	cout << endl;
-	cout << "  -r, --rawdatafiles[=true|false]     output separate .raw data files (default: true; do not set to false atm);" << endl;
-	cout << "                                      .raw files is strongly recommended, esp. when receiving from multiple stations" << endl;
 	cout << "  -k, --keeprunning[=true|false]      accept new input after a dump completed (default: true)" << endl;
 	cout << endl;
 	cout << "  -h, --help                          print program name, version number and this info, then exit" << endl;
@@ -320,11 +333,10 @@ static int parseArgs(int argc, char *argv[], struct progArgs* args) {
 	args->antFieldDir = "";		// idem
 
 	args->outputDir = "";
-	args->proto = "udp";
+	args->input = "udp";
 	args->port = TBB_DEFAULT_BASE_PORT;
 	args->timeoutVal.tv_sec = 10; // after this default of inactivity cancel all input threads and close output files
 	args->timeoutVal.tv_usec = 0;
-	args->rawDataFiles = true;
 	args->keepRunning = true;
 
 	static const struct option long_opts[] = {
@@ -332,11 +344,10 @@ static int parseArgs(int argc, char *argv[], struct progArgs* args) {
 		{"parsetfile",   required_argument, NULL, 's'}, // observation (s)ettings
 		{"antfielddir",  required_argument, NULL, 'a'},
 		{"outputdir",    required_argument, NULL, 'o'},
-		{"proto",        required_argument, NULL, 'p'},
+		{"input",        required_argument, NULL, 'i'},
 		{"portbase",     required_argument, NULL, 'b'}, // port (b)ase
 		{"timeout",      required_argument, NULL, 't'},
 
-		{"rawdatafiles", optional_argument, NULL, 'r'},
 		{"keeprunning",  optional_argument, NULL, 'k'},
 
 		{"help",         no_argument,       NULL, 'h'},
@@ -347,7 +358,7 @@ static int parseArgs(int argc, char *argv[], struct progArgs* args) {
 
 	opterr = 0; // prevent error printing to stderr by getopt_long()
 	int opt;
-	while ((opt = getopt_long(argc, argv, "hvs:a:o:p:b:t:r::k::", long_opts, NULL)) != -1) {
+	while ((opt = getopt_long(argc, argv, "hvs:a:o:p:b:t:k::", long_opts, NULL)) != -1) {
 		switch (opt) {
 		case 's':
 			args->parsetFilename = optarg;
@@ -364,12 +375,12 @@ static int parseArgs(int argc, char *argv[], struct progArgs* args) {
 				args->outputDir.push_back('/');
 			}
 			break;
-		case 'p':
+		case 'i':
 			if (strcmp(optarg, "tcp") == 0 || strcmp(optarg, "udp") == 0 ||
-				strncmp(optarg, "file", sizeof("file")-1) == 0 || strncmp(optarg, "pipe", sizeof("pipe")-1) == 0) {
-				args->proto = optarg;
+				strncmp(optarg, "file:", sizeof("file:")-1) == 0 || strncmp(optarg, "pipe:", sizeof("pipe:")-1) == 0) {
+				args->input = optarg;
 			} else {
-				cerr << "Invalid protocol option: " << optarg << endl;
+				LOG_FATAL_STR("TBB: Invalid input option: " << optarg);
 				rv = 1;
 			}
 			break;
@@ -380,7 +391,7 @@ static int parseArgs(int argc, char *argv[], struct progArgs* args) {
 					throw boost::bad_lexical_cast(); // abuse exc type to have single catch
 				}
 			} catch (boost::bad_lexical_cast& /*exc*/) {
-				cerr << "Invalid port option: " << optarg << endl;
+				LOG_FATAL_STR("TBB: Invalid port option: " << optarg);
 				rv = 1;
 			}
 			break;
@@ -388,19 +399,7 @@ static int parseArgs(int argc, char *argv[], struct progArgs* args) {
 			try {
 				args->timeoutVal.tv_sec = boost::lexical_cast<unsigned long>(optarg);
 			} catch (boost::bad_lexical_cast& /*exc*/) {
-				cerr << "Invalid timeout option: " << optarg << endl;
-				rv = 1;
-			}
-			break;
-		case 'r':
-			if (optarg == NULL || optarg[0] == '\0') {
-				args->rawDataFiles = true;
-				break;
-			}
-			try {
-				args->rawDataFiles = boost::lexical_cast<bool>(optarg);
-			} catch (boost::bad_lexical_cast& /*exc*/) {
-				cerr << "Invalid rawdata option: " << optarg << endl;
+				LOG_FATAL_STR("TBB: Invalid timeout option: " << optarg);
 				rv = 1;
 			}
 			break;
@@ -412,7 +411,7 @@ static int parseArgs(int argc, char *argv[], struct progArgs* args) {
 			try {
 				args->keepRunning = boost::lexical_cast<bool>(optarg);
 			} catch (boost::bad_lexical_cast& /*exc*/) {
-				cerr << "Invalid keeprunning option: " << optarg << endl;
+				LOG_FATAL_STR("TBB: Invalid keeprunning option: " << optarg);
 				rv = 1;
 			}
 			break;
@@ -423,46 +422,51 @@ static int parseArgs(int argc, char *argv[], struct progArgs* args) {
 			}
 			break;
 		default: // '?'
-			cerr << "Invalid program argument: " << argv[optind-1] << endl;
+			LOG_FATAL_STR("TBB: Invalid program argument: " << argv[optind-1]);
 			rv = 1;
 		}
 	}
 
 	if (optind < argc) {
-		cerr << "Failed to recognize options:";
+		LOG_FATAL("TBB: Failed to recognize options:");
 		while (optind < argc) {
-			cerr << " " << argv[optind++];
+			LOG_FATAL_STR(" " << argv[optind++]);
 		}
-		cerr << endl;
 		rv = 1;
 	}
 
 	return rv;
 }
 
-static char stdoutbuf[1024], stderrbuf[1024];
-
 int main(int argc, char* argv[]) {
 	struct progArgs args;
 	int err;
 
-	setvbuf(stdout, stdoutbuf, _IOLBF, sizeof stdoutbuf);
-	setvbuf(stderr, stderrbuf, _IOLBF, sizeof stderrbuf);
-
-#if defined HAVE_LOG4CPLUS
-	char *dirc = strdup(argv[0]);
-
-	INIT_LOGGER(string(getenv("LOFARROOT") ? : dirname(dirc)) + "/../etc/TBB_Writer_main.log_prop");
+#if defined HAVE_LOG4CPLUS || defined HAVE_LOG4CXX
+	struct Log {
+		Log(const char* argv0) {
+			char *dirc = strdup(argv0); // dirname() may clobber its arg
+			if (dirc != NULL) {
+				INIT_LOGGER(string(getenv("LOFARROOT") ? : dirname(dirc)) + "/../etc/Storage_main.log_prop");
+				free(dirc);
+			}
+		}
 
-	free(dirc);
+		~Log() {
+			LOGGER_EXIT_THREAD(); // destroys NDC created by INIT_LOGGER()
+		}
+	} logger(argv[0]);
 #endif
 
+	err  = setvbuf(stdout, stdoutbuf, _IOLBF, sizeof stdoutbuf);
+	err |= setvbuf(stderr, stderrbuf, _IOLBF, sizeof stderrbuf);
+	if (err != 0) {
+		LOG_WARN("TBB: failed to change stdout and/or stderr output buffers");
+	}
+
 	if ((err = parseArgs(argc, argv, &args)) != 0) {
 		if (err == 2) err = 0;
 		printUsage(argv[0]);
-#if defined HAVE_LOG4CPLUS
-		LOGGER_EXIT_THREAD();
-#endif
 		return err;
 	}
 
@@ -470,13 +474,10 @@ int main(int argc, char* argv[]) {
 
 	if ((err = ensureOutputDirExists(args.outputDir)) != 0) {
 		LOG_FATAL_STR("TBB: output directory: " << strerror(err));
-#if defined HAVE_LOG4CPLUS
-		LOGGER_EXIT_THREAD();
-#endif
 		return 1;
 	}
 
-	const vector<string> inputStreamNames(getTBB_InputStreamNames(args.proto, args.port));
+	const vector<string> inputStreamNames(getTBB_InputStreamNames(args.input, args.port));
 
 	// We don't run alone, so try to increase the QoS we get from the OS to decrease the chance of data loss.
 	setIOpriority(); // reqs CAP_SYS_NICE or CAP_SYS_ADMIN
@@ -498,17 +499,13 @@ int main(int argc, char* argv[]) {
 
 	// Config exceptions (opening or parsing) are fatal. Too bad we cannot have it in one type.
 	} catch (LOFAR::RTCP::InterfaceException& exc) {
-		LOG_FATAL_STR("TBB: LOFAR::InterfaceException: parset: " << exc.text());
+		LOG_FATAL_STR("TBB: LOFAR::InterfaceException: parset: " << exc);
 	} catch (LOFAR::APSException& exc) {
-		LOG_FATAL_STR("TBB: LOFAR::APSException: parameterset: " << exc.text());
+		LOG_FATAL_STR("TBB: LOFAR::APSException: parameterset: " << exc);
 	} catch (LOFAR::RTCP::StorageException& exc) {
-		LOG_FATAL_STR("TBB: LOFAR::StorageException: antenna field files: " << exc.text());
+		LOG_FATAL_STR("TBB: LOFAR::StorageException: antenna field files: " << exc);
 	}
 
-#if defined HAVE_LOG4CPLUS
-	LOGGER_EXIT_THREAD();
-#endif
-
 	return err == 0 ? 0 : 1;
 }
 
diff --git a/RTCP/Storage/src/TBB_Writer_main.log_prop b/RTCP/Storage/src/TBB_Writer_main.log_prop
deleted file mode 100644
index 3d46179d269ba4b755029cce75af58c2e416468f..0000000000000000000000000000000000000000
--- a/RTCP/Storage/src/TBB_Writer_main.log_prop
+++ /dev/null
@@ -1,29 +0,0 @@
-
-# Configure the loggers
-log4cplus.rootLogger=INFO, STDOUT
-log4cplus.logger.TRC=INFO
-
-# prevent debug messages: accept >=WARN only, and don't forward messages to the rootLogger
-log4cplus.logger.LCS.ApplCommon=WARN, STDOUT
-log4cplus.additivity.LCS.ApplCommon=false
-log4cplus.logger.LCS.MSLofar=WARN, STDOUT
-log4cplus.additivity.LCS.MSLofar=false
-
-# Define the appenders
-log4cplus.appender.STDOUT=log4cplus::ConsoleAppender
-log4cplus.appender.STDOUT.layout=log4cplus::PatternLayout
-log4cplus.appender.STDOUT.layout.ConversionPattern=%x %D{%d-%m-%y %H:%M:%S.%q} %-5p %m%n
-
-#log4cplus.appender.STDERR=log4cplus::ConsoleAppender
-#log4cplus.appender.STDERR.layout=log4cplus::PatternLayout
-#log4cplus.appender.STDERR.layout.ConversionPattern=%x %D{%d-%m-%y %H:%M:%S.%q} %-5p %c{3} - %m [%.25l]%n
-#log4cplus.appender.STDERR.logToStdErr=true
-
-#log4cplus.appender.FILE=log4cplus::RollingFileAppender
-#log4cplus.appender.FILE.File=${LOG4CPLUS_LOGFILENAME}.log
-#log4cplus.appender.FILE.MaxFileSize=10MB
-#log4cplus.appender.FILE.MaxBackupIndex=2
-#log4cplus.appender.FILE.layout=log4cplus::PatternLayout
-#log4cplus.appender.FILE.layout.ConversionPattern=%x %D{%d-%m-%y %H:%M:%S.%q} %-5p %c{3} - %m [%.25l]%n
-
-log4cplus.appender.DUMP=log4cplus::NullAppender
diff --git a/RTCP/Storage/test/tTBB_Writer-spectral.parset b/RTCP/Storage/test/tTBB_Writer-spectral.parset
new file mode 100644
index 0000000000000000000000000000000000000000..16af39ad435f56656a00b8e670407a4ce02b029f
--- /dev/null
+++ b/RTCP/Storage/test/tTBB_Writer-spectral.parset
@@ -0,0 +1,994 @@
+ApplCtrl.application = CorrAppl
+ApplCtrl.procesOrder = []
+ApplCtrl.processes = [CorrProc]
+ApplCtrl.resultfile = '/opt/lofar/share/ACC_CCU001:OnlineControl[0]{59640}_CorrAppl_result.param'
+ApplCtrl.timeout_createsubsets = 30s
+ApplCtrl.timeout_define = 30s
+ApplCtrl.timeout_info = 30s
+ApplCtrl.timeout_init = 30s
+ApplCtrl.timeout_kill = 30s
+ApplCtrl.timeout_pause = 90s
+ApplCtrl.timeout_quit = 10s
+ApplCtrl.timeout_recover = 30s
+ApplCtrl.timeout_reinit = 30s
+ApplCtrl.timeout_release = 30s
+ApplCtrl.timeout_run = 90s
+ApplCtrl.timeout_snapshot = 30s
+ApplCtrl.timeout_startup = 30s
+CorrAppl.CorrProc._ACnode = bgfen0
+CorrAppl.CorrProc._ACport = 3922
+CorrAppl.CorrProc._executable = CN_Processing
+CorrAppl.CorrProc._hostname = bgstfen
+CorrAppl.CorrProc._nodes = []
+CorrAppl.CorrProc._startstopType = bgl
+CorrAppl.CorrProc.workingdir = /opt/lofar/bin/
+CorrAppl._hostname = bgstfen
+CorrAppl.extraInfo = [OLAP,PIC]
+CorrAppl.procesOrder = []
+CorrAppl.processes = [CorrProc]
+OLAP.BeamsAreTransposed = True
+OLAP.CNProc.coresPerPset = 64
+OLAP.CNProc.integrationSteps = 3072
+OLAP.CNProc.nrPPFTaps = 16
+OLAP.CNProc.partition = R00
+OLAP.CNProc.phaseOnePsets = [46,34,36,38,33,35,37,50,48,32,39,42,51,44,58,41,40,54,43,45,26,47,52,55,23,49,60,62,30,53,63,31]
+OLAP.CNProc.phaseOneTwoCores = [0..63]
+OLAP.CNProc.phaseThreeCores = [0..63]
+OLAP.CNProc.phaseThreePsets = [0..63]
+OLAP.CNProc.phaseTwoPsets = [0..63]
+OLAP.CNProc.tabList = []
+OLAP.CNProc.usedCores = [0..63]
+OLAP.CNProc_CoherentStokes.channelsPerSubband = 16
+OLAP.CNProc_CoherentStokes.subbandsPerFile = 244
+OLAP.CNProc_CoherentStokes.timeIntegrationFactor = 64
+OLAP.CNProc_CoherentStokes.which = I
+OLAP.CNProc_IncoherentStokes.channelsPerSubband = 16
+OLAP.CNProc_IncoherentStokes.subbandsPerFile = 244
+OLAP.CNProc_IncoherentStokes.timeIntegrationFactor = 64
+OLAP.CNProc_IncoherentStokes.which = I
+OLAP.Correlator.integrationTime = 1
+OLAP.DelayComp.nrCalcDelays = 16
+OLAP.DelayComp.positionType = ITRF
+OLAP.IONProc.PLC_controlled = T
+OLAP.IONProc.integrationSteps = 4
+OLAP.IONProc.psetList = [10.170.0.1,10.170.0.2,10.170.0.5,10.170.0.6,10.170.0.9,10.170.0.10,10.170.0.13,10.170.0.14,10.170.0.17,10.170.0.18,10.170.0.21,10.170.0.22,10.170.0.25,10.170.0.26,10.170.0.29,10.170.0.30,10.170.0.33,10.170.0.34,10.170.0.37,10.170.0.38,10.170.0.41,10.170.0.42,10.170.0.45,10.170.0.46,10.170.0.49,10.170.0.50,10.170.0.53,10.170.0.54,10.170.0.57,10.170.0.58,10.170.0.61,10.170.0.62,10.170.0.129,10.170.0.130,10.170.0.133,10.170.0.134,10.170.0.137,10.170.0.138,10.170.0.141,10.170.0.142,10.170.0.145,10.170.0.146,10.170.0.149,10.170.0.150,10.170.0.153,10.170.0.154,10.170.0.157,10.170.0.158,10.170.0.161,10.170.0.162,10.170.0.165,10.170.0.166,10.170.0.169,10.170.0.170,10.170.0.173,10.170.0.174,10.170.0.177,10.170.0.178,10.170.0.181,10.170.0.182,10.170.0.185,10.170.0.186,10.170.0.189,10.170.0.190]
+OLAP.IncoherentStokesAreTransposed = True
+OLAP.OLAP_Conn.IONProc_CNProc_Transport = FCNP
+OLAP.OLAP_Conn.IONProc_Storage_Transport = TCP
+OLAP.PPF = True
+OLAP.PencilInfo.flysEye = false
+OLAP.PencilInfo.storageNodeList = [0,1]
+OLAP.Storage.AntennaFieldsDir = /data/home/lofarsys/production/lofar/etc/StaticMetaData
+OLAP.Storage.AntennaSetsConf = /data/home/lofarsys/production/lofar/etc/AntennaSets.conf
+OLAP.Storage.HBADeltasDir = /data/home/lofarsys/production/lofar/etc/StaticMetaData
+OLAP.Storage.hosts = [locus072,locus088]
+OLAP.Storage.msWriter = /data/home/lofarsys/production/lofar/bin/Storage_main
+OLAP.Storage.sshIdentityFile = /globalhome/lofarsystem/.ssh/id_rsa
+OLAP.Storage.targetDirectory = /data
+OLAP.Storage.userName = lofarsys
+OLAP.StorageProc.subbandsPerMS = 1
+OLAP.coherentDedisperseChannels = false
+OLAP.correctBandPass = true
+OLAP.correctClocks = T
+OLAP.delayCompensation = true
+OLAP.dispersionMeasure = 0
+OLAP.maxNetworkDelay = 0.25
+Observation.nrBitsPerSample = 16
+OLAP.nrPsets = 64
+OLAP.nrSecondsOfBuffer = 2.5
+OLAP.nrSubbandsPerFrame = 61
+OLAP.nrTimesInFrame = 16
+OLAP.realTime = true
+OLAP.storageNodeList = [122*0,122*1]
+OLAP.storageStationNames = [CS001LBA,CS002LBA,CS003LBA,CS004LBA,CS005LBA,CS006LBA,CS007LBA,CS011LBA,CS017LBA,CS021LBA,CS024LBA,CS026LBA,CS028LBA,CS030LBA,CS031LBA,CS032LBA,CS101LBA,CS103LBA,CS201LBA,CS301LBA,CS302LBA,CS401LBA,CS501LBA,RS106LBA,RS205LBA,RS208LBA,RS306LBA,RS307LBA,RS406LBA,RS503LBA,RS508LBA,RS509LBA]
+OLAP.tiedArrayStationNames = []
+Observation.AnaBeam.angle1 = 0
+Observation.AnaBeam.angle2 = 0
+Observation.AnaBeam.directionType = J2000
+Observation.AnaBeam.duration = 0
+Observation.AnaBeam.maximizeDuration = false
+Observation.AnaBeam.rank = 1
+Observation.AnaBeam.startTime = 
+Observation.AnaBeam.target = 
+Observation.Beam[0].TiedArrayBeam[0].angle1 = 0.0
+Observation.Beam[0].TiedArrayBeam[0].angle2 = 0.0
+Observation.Beam[0].TiedArrayBeam[0].coherent = true
+Observation.Beam[0].TiedArrayBeam[0].directionType = J2000
+Observation.Beam[0].TiedArrayBeam[0].dispersionMeasure = 0
+Observation.Beam[0].TiedArrayBeam[0].specificationType = manual
+Observation.Beam[0].TiedArrayBeam[0].stationList = []
+Observation.Beam[0].TiedArrayBeam[1].angle1 = 0
+Observation.Beam[0].TiedArrayBeam[1].angle2 = 0
+Observation.Beam[0].TiedArrayBeam[1].coherent = false
+Observation.Beam[0].TiedArrayBeam[1].directionType = J2000
+Observation.Beam[0].TiedArrayBeam[1].dispersionMeasure = 0
+Observation.Beam[0].TiedArrayBeam[1].specificationType = manual
+Observation.Beam[0].TiedArrayBeam[1].stationList = []
+Observation.Beam[0].angle1 = 0.9293449206762021
+Observation.Beam[0].angle2 = 0.9525764650544495
+Observation.Beam[0].beamletList = []
+Observation.Beam[0].directionType = J2000
+Observation.Beam[0].duration = 900
+Observation.Beam[0].maximizeDuration = false
+Observation.Beam[0].momID = 119965
+Observation.Beam[0].nrTabRings = 0
+Observation.Beam[0].nrTiedArrayBeams = 2
+Observation.Beam[0].startTime = 
+Observation.Beam[0].subbandList = [175..418]
+Observation.Beam[0].tabRingSize = 0.0
+Observation.Beam[0].target = B0329+54
+Observation.Beamformer.stationList = []
+Observation.Campaign.CO_I = 'Pizzo, Dr. Roberto Francesco'
+Observation.Campaign.PI = 'Polatidis, Dr Antonios'
+Observation.Campaign.contact = 'Polatidis, Dr Antonios'
+Observation.Campaign.name = 2012LOFAROBS
+Observation.Campaign.title = 2012LOFAROBS
+Observation.DataProducts.Input_Beamformed.dirmask = 
+Observation.DataProducts.Input_Beamformed.enabled = false
+Observation.DataProducts.Input_Beamformed.filenames = []
+Observation.DataProducts.Input_Beamformed.identifications = []
+Observation.DataProducts.Input_Beamformed.locations = []
+Observation.DataProducts.Input_Beamformed.mountpoints = []
+Observation.DataProducts.Input_Beamformed.namemask = 
+Observation.DataProducts.Input_Beamformed.skip = []
+Observation.DataProducts.Input_CoherentStokes.dirmask = 
+Observation.DataProducts.Input_CoherentStokes.enabled = false
+Observation.DataProducts.Input_CoherentStokes.filenames = []
+Observation.DataProducts.Input_CoherentStokes.identifications = []
+Observation.DataProducts.Input_CoherentStokes.locations = []
+Observation.DataProducts.Input_CoherentStokes.mountpoints = []
+Observation.DataProducts.Input_CoherentStokes.namemask = 
+Observation.DataProducts.Input_CoherentStokes.skip = []
+Observation.DataProducts.Input_Correlated.dirmask = 
+Observation.DataProducts.Input_Correlated.enabled = false
+Observation.DataProducts.Input_Correlated.filenames = []
+Observation.DataProducts.Input_Correlated.identifications = []
+Observation.DataProducts.Input_Correlated.locations = []
+Observation.DataProducts.Input_Correlated.mountpoints = []
+Observation.DataProducts.Input_Correlated.namemask = 
+Observation.DataProducts.Input_Correlated.skip = []
+Observation.DataProducts.Input_IncoherentStokes.dirmask = 
+Observation.DataProducts.Input_IncoherentStokes.enabled = false
+Observation.DataProducts.Input_IncoherentStokes.filenames = []
+Observation.DataProducts.Input_IncoherentStokes.identifications = []
+Observation.DataProducts.Input_IncoherentStokes.locations = []
+Observation.DataProducts.Input_IncoherentStokes.mountpoints = []
+Observation.DataProducts.Input_IncoherentStokes.namemask = 
+Observation.DataProducts.Input_IncoherentStokes.skip = []
+Observation.DataProducts.Input_InstrumentModel.dirmask = 
+Observation.DataProducts.Input_InstrumentModel.enabled = false
+Observation.DataProducts.Input_InstrumentModel.filenames = []
+Observation.DataProducts.Input_InstrumentModel.identifications = []
+Observation.DataProducts.Input_InstrumentModel.locations = []
+Observation.DataProducts.Input_InstrumentModel.mountpoints = []
+Observation.DataProducts.Input_InstrumentModel.namemask = 
+Observation.DataProducts.Input_InstrumentModel.skip = []
+Observation.DataProducts.Input_SkyImage.dirmask = 
+Observation.DataProducts.Input_SkyImage.enabled = false
+Observation.DataProducts.Input_SkyImage.filenames = []
+Observation.DataProducts.Input_SkyImage.identifications = []
+Observation.DataProducts.Input_SkyImage.locations = []
+Observation.DataProducts.Input_SkyImage.mountpoints = []
+Observation.DataProducts.Input_SkyImage.namemask = 
+Observation.DataProducts.Input_SkyImage.skip = []
+Observation.DataProducts.Output_Beamformed.archived = false
+Observation.DataProducts.Output_Beamformed.deleted = false
+Observation.DataProducts.Output_Beamformed.dirmask = 
+Observation.DataProducts.Output_Beamformed.enabled = True
+Observation.DataProducts.Output_Beamformed.filenames = [L59640_SAP000_B000_S0_P000_bf.raw,L59640_SAP000_B001_S0_P000_bf.raw]
+Observation.DataProducts.Output_Beamformed.identifications = []
+Observation.DataProducts.Output_Beamformed.locations = [locus072:/data/L59640/,locus088:/data/L59640/]
+Observation.DataProducts.Output_Beamformed.mountpoints = []
+Observation.DataProducts.Output_Beamformed.namemask = 
+Observation.DataProducts.Output_Beamformed.percentageWritten = []
+Observation.DataProducts.Output_Beamformed.retentiontime = 14
+Observation.DataProducts.Output_Beamformed.skip = []
+Observation.DataProducts.Output_CoherentStokes.archived = false
+Observation.DataProducts.Output_CoherentStokes.deleted = false
+Observation.DataProducts.Output_CoherentStokes.dirmask = L${OBSID}
+Observation.DataProducts.Output_CoherentStokes.enabled = true
+Observation.DataProducts.Output_CoherentStokes.filenames = []
+Observation.DataProducts.Output_CoherentStokes.identifications = []
+Observation.DataProducts.Output_CoherentStokes.locations = []
+Observation.DataProducts.Output_CoherentStokes.mountpoints = [locus072:/data]
+Observation.DataProducts.Output_CoherentStokes.namemask = L${OBSID}_SAP${SAP}_B${BEAM}_S${STOKES}_P${PART}_bf.raw
+Observation.DataProducts.Output_CoherentStokes.percentageWritten = []
+Observation.DataProducts.Output_CoherentStokes.retentiontime = 14
+Observation.DataProducts.Output_CoherentStokes.skip = []
+Observation.DataProducts.Output_Correlated.archived = false
+Observation.DataProducts.Output_Correlated.deleted = false
+Observation.DataProducts.Output_Correlated.dirmask = 
+Observation.DataProducts.Output_Correlated.enabled = false
+Observation.DataProducts.Output_Correlated.filenames = []
+Observation.DataProducts.Output_Correlated.identifications = []
+Observation.DataProducts.Output_Correlated.locations = []
+Observation.DataProducts.Output_Correlated.mountpoints = []
+Observation.DataProducts.Output_Correlated.namemask = 
+Observation.DataProducts.Output_Correlated.percentageWritten = []
+Observation.DataProducts.Output_Correlated.retentiontime = 14
+Observation.DataProducts.Output_Correlated.skip = []
+Observation.DataProducts.Output_IncoherentStokes.archived = false
+Observation.DataProducts.Output_IncoherentStokes.deleted = false
+Observation.DataProducts.Output_IncoherentStokes.dirmask = L${OBSID}
+Observation.DataProducts.Output_IncoherentStokes.enabled = true
+Observation.DataProducts.Output_IncoherentStokes.filenames = []
+Observation.DataProducts.Output_IncoherentStokes.identifications = []
+Observation.DataProducts.Output_IncoherentStokes.locations = []
+Observation.DataProducts.Output_IncoherentStokes.mountpoints = [locus088:/data]
+Observation.DataProducts.Output_IncoherentStokes.namemask = L${OBSID}_SAP${SAP}_B${BEAM}_S${STOKES}_P${PART}_bf.raw
+Observation.DataProducts.Output_IncoherentStokes.percentageWritten = []
+Observation.DataProducts.Output_IncoherentStokes.retentiontime = 14
+Observation.DataProducts.Output_IncoherentStokes.skip = []
+Observation.DataProducts.Output_InstrumentModel.archived = false
+Observation.DataProducts.Output_InstrumentModel.deleted = false
+Observation.DataProducts.Output_InstrumentModel.dirmask = 
+Observation.DataProducts.Output_InstrumentModel.enabled = false
+Observation.DataProducts.Output_InstrumentModel.filenames = []
+Observation.DataProducts.Output_InstrumentModel.identifications = []
+Observation.DataProducts.Output_InstrumentModel.locations = []
+Observation.DataProducts.Output_InstrumentModel.mountpoints = []
+Observation.DataProducts.Output_InstrumentModel.namemask = 
+Observation.DataProducts.Output_InstrumentModel.percentageWritten = []
+Observation.DataProducts.Output_InstrumentModel.retentiontime = 14
+Observation.DataProducts.Output_InstrumentModel.skip = []
+Observation.DataProducts.Output_SkyImage.archived = false
+Observation.DataProducts.Output_SkyImage.deleted = false
+Observation.DataProducts.Output_SkyImage.dirmask = 
+Observation.DataProducts.Output_SkyImage.enabled = false
+Observation.DataProducts.Output_SkyImage.filenames = []
+Observation.DataProducts.Output_SkyImage.identifications = []
+Observation.DataProducts.Output_SkyImage.locations = []
+Observation.DataProducts.Output_SkyImage.mountpoints = []
+Observation.DataProducts.Output_SkyImage.namemask = 
+Observation.DataProducts.Output_SkyImage.percentageWritten = []
+Observation.DataProducts.Output_SkyImage.retentiontime = 14
+Observation.DataProducts.Output_SkyImage.skip = []
+Observation.DataProducts.Output_Trigger.dirmask = L${YEAR}_${OBSID}
+Observation.DataProducts.Output_Trigger.enabled = False
+Observation.DataProducts.Output_Trigger.namemask = L${OBSID}_SAP${SAP}_B${BEAM}_S${STOKES}_P${PART}_bf.trigger
+Observation.DataProducts.nrOfOutput_BeamFormed_ = 0
+Observation.DataProducts.nrOfOutput_Correlated_ = 0
+Observation.DataProducts.nrOfOutput_InstrumentModels_ = 0
+Observation.DataProducts.nrOfOutput_SkyImages_ = 0
+Observation.Dataslots.CS001LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.CS001LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.CS002LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.CS002LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.CS003LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.CS003LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.CS004LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.CS004LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.CS005LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.CS005LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.CS006LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.CS006LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.CS007LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.CS007LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.CS011LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.CS011LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.CS017LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.CS017LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.CS021LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.CS021LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.CS024LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.CS024LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.CS026LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.CS026LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.CS028LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.CS028LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.CS030LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.CS030LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.CS031LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.CS031LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.CS032LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.CS032LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.CS101LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.CS101LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.CS103LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.CS103LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.CS201LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.CS201LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.CS301LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.CS301LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.CS302LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.CS302LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.CS401LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.CS401LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.CS501LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.CS501LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.DataslotInfo.DataslotList = []
+Observation.Dataslots.DataslotInfo.RSPBoardList = []
+Observation.Dataslots.RS106LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.RS106LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.RS205LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.RS205LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.RS208LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.RS208LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.RS306LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.RS306LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.RS307LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.RS307LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.RS406LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.RS406LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.RS503LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.RS503LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.RS508LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.RS508LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.Dataslots.RS509LBA.DataslotList = [0..60,0..60,0..60,0..60]
+Observation.Dataslots.RS509LBA.RSPBoardList = [61*0,61*1,61*2,61*3]
+Observation.KSPType = surveys
+Observation.ObsID = 59640
+Observation.ObservationControl.OnlineControl.ApplCtrl.application = []
+Observation.ObservationControl.OnlineControl.ApplCtrl.procesOrder = []
+Observation.ObservationControl.OnlineControl.ApplCtrl.processes = []
+Observation.ObservationControl.OnlineControl.ApplCtrl.resultfile = ../log/ACC.result
+Observation.ObservationControl.OnlineControl.ApplCtrl.timeout_createsubsets = 30s
+Observation.ObservationControl.OnlineControl.ApplCtrl.timeout_define = 30s
+Observation.ObservationControl.OnlineControl.ApplCtrl.timeout_info = 30s
+Observation.ObservationControl.OnlineControl.ApplCtrl.timeout_init = 30s
+Observation.ObservationControl.OnlineControl.ApplCtrl.timeout_kill = 30s
+Observation.ObservationControl.OnlineControl.ApplCtrl.timeout_pause = 90s
+Observation.ObservationControl.OnlineControl.ApplCtrl.timeout_quit = 10s
+Observation.ObservationControl.OnlineControl.ApplCtrl.timeout_recover = 30s
+Observation.ObservationControl.OnlineControl.ApplCtrl.timeout_reinit = 30s
+Observation.ObservationControl.OnlineControl.ApplCtrl.timeout_release = 30s
+Observation.ObservationControl.OnlineControl.ApplCtrl.timeout_run = 90s
+Observation.ObservationControl.OnlineControl.ApplCtrl.timeout_snapshot = 30s
+Observation.ObservationControl.OnlineControl.ApplCtrl.timeout_startup = 30s
+Observation.ObservationControl.OnlineControl.CorrAppl.CorrProc._executable = CN_Processing
+Observation.ObservationControl.OnlineControl.CorrAppl.CorrProc._hostname = bgstfen
+Observation.ObservationControl.OnlineControl.CorrAppl.CorrProc._nodes = []
+Observation.ObservationControl.OnlineControl.CorrAppl.CorrProc._startstopType = bgl
+Observation.ObservationControl.OnlineControl.CorrAppl.CorrProc.workingdir = /opt/lofar/bin/
+Observation.ObservationControl.OnlineControl.CorrAppl._hostname = bgstfen
+Observation.ObservationControl.OnlineControl.CorrAppl.extraInfo = [OLAP,PIC]
+Observation.ObservationControl.OnlineControl.CorrAppl.procesOrder = []
+Observation.ObservationControl.OnlineControl.CorrAppl.processes = [CorrProc]
+Observation.ObservationControl.OnlineControl.OLAP.CNProc.coresPerPset = 64
+Observation.ObservationControl.OnlineControl.OLAP.CNProc.integrationSteps = 768
+Observation.ObservationControl.OnlineControl.OLAP.CNProc.nrPPFTaps = 16
+Observation.ObservationControl.OnlineControl.OLAP.CNProc.phaseOnePsets = []
+Observation.ObservationControl.OnlineControl.OLAP.CNProc.phaseThreePsets = []
+Observation.ObservationControl.OnlineControl.OLAP.CNProc.phaseTwoPsets = []
+Observation.ObservationControl.OnlineControl.OLAP.CNProc.usedCores = [0..63]
+Observation.ObservationControl.OnlineControl.OLAP.CNProc_CoherentStokes.channelsPerSubband = 0
+Observation.ObservationControl.OnlineControl.OLAP.CNProc_CoherentStokes.subbandsPerFile = 244
+Observation.ObservationControl.OnlineControl.OLAP.CNProc_CoherentStokes.timeIntegrationFactor = 64
+Observation.ObservationControl.OnlineControl.OLAP.CNProc_CoherentStokes.which = I
+Observation.ObservationControl.OnlineControl.OLAP.CNProc_IncoherentStokes.channelsPerSubband = 0
+Observation.ObservationControl.OnlineControl.OLAP.CNProc_IncoherentStokes.subbandsPerFile = 244
+Observation.ObservationControl.OnlineControl.OLAP.CNProc_IncoherentStokes.timeIntegrationFactor = 64
+Observation.ObservationControl.OnlineControl.OLAP.CNProc_IncoherentStokes.which = I
+Observation.ObservationControl.OnlineControl.OLAP.Correlator.integrationTime = 1
+Observation.ObservationControl.OnlineControl.OLAP.DelayComp.nrCalcDelays = 16
+Observation.ObservationControl.OnlineControl.OLAP.DelayComp.positionType = ITRF
+Observation.ObservationControl.OnlineControl.OLAP.IONProc.integrationSteps = 30
+Observation.ObservationControl.OnlineControl.OLAP.OLAP_Conn.IONProc_CNProc_Transport = FCNP
+Observation.ObservationControl.OnlineControl.OLAP.PencilInfo.flysEye = false
+Observation.ObservationControl.OnlineControl.OLAP.StorageProc.subbandsPerMS = 1
+Observation.ObservationControl.OnlineControl.OLAP.coherentDedisperseChannels = false
+Observation.ObservationControl.OnlineControl.OLAP.correctBandPass = true
+Observation.ObservationControl.OnlineControl.OLAP.delayCompensation = true
+Observation.ObservationControl.OnlineControl.OLAP.maxNetworkDelay = 0.25
+Observation.ObservationControl.OnlineControl.Observation.nrBitsPerSample = 16
+Observation.ObservationControl.OnlineControl.OLAP.nrSecondsOfBuffer = 2.5
+Observation.ObservationControl.OnlineControl.OLAP.nrSubbandsPerFrame = 61
+Observation.ObservationControl.OnlineControl.OLAP.nrTimesInFrame = 16
+Observation.ObservationControl.OnlineControl.OLAP.realTime = true
+Observation.ObservationControl.OnlineControl.OLAP.storageStationNames = AllStations
+Observation.ObservationControl.OnlineControl._hostname = CCU001
+Observation.ObservationControl.OnlineControl.applOrder = [CorrAppl]
+Observation.ObservationControl.OnlineControl.applications = [CorrAppl]
+Observation.ObservationControl.OnlineControl.inspectionHost = 
+Observation.ObservationControl.OnlineControl.inspectionProgram = 
+Observation.ObservationControl.StationControl.TBBControl.CoincidenceTime = 0
+Observation.ObservationControl.StationControl.TBBControl.DoDirectionFit = none
+Observation.ObservationControl.StationControl.TBBControl.MaxFitVariance = 0
+Observation.ObservationControl.StationControl.TBBControl.MinElevation = 0
+Observation.ObservationControl.StationControl.TBBControl.NoCoincChann = 0
+Observation.ObservationControl.StationControl.TBBControl.ParamExtension = 
+Observation.ObservationControl.StationControl._hostname = [CS001,CS002,CS003,CS004,CS005,CS006,CS007,CS011,CS017,CS021,CS024,CS026,CS028,CS030,CS031,CS032,CS101,CS103,CS201,CS301,CS302,CS401,CS501,RS106,RS205,RS208,RS306,RS307,RS406,RS503,RS508,RS509]
+Observation.ObservationControl.StationControl.tbbPiggybackAllowed = false
+Observation.ObservationControl._hostname = MCU001
+Observation.ObservationControl.heartbeatInterval = 10
+Observation.ObserverName = unknown
+Observation.ProjectName = unknown
+Observation.Scheduler.contactEmail = 
+Observation.Scheduler.contactName = 
+Observation.Scheduler.contactPhone = 
+Observation.Scheduler.firstPossibleDay = 0
+Observation.Scheduler.fixedDay = false
+Observation.Scheduler.fixedTime = false
+Observation.Scheduler.lastPossibleDay = 0
+Observation.Scheduler.late = false
+Observation.Scheduler.nightTimeWeightFactor = 0
+Observation.Scheduler.predMaxTimeDif = 
+Observation.Scheduler.predMinTimeDif = 
+Observation.Scheduler.predecessors = []
+Observation.Scheduler.priority = 0.0
+Observation.Scheduler.reason = 
+Observation.Scheduler.referenceFrame = 0
+Observation.Scheduler.reservation = 0
+Observation.Scheduler.storageSelectionMode = 1
+Observation.Scheduler.taskDuration = 900
+Observation.Scheduler.taskID = 63
+Observation.Scheduler.taskName = 'LBAm1 18-06-2012'
+Observation.Scheduler.taskType = 0
+Observation.Scheduler.windowMaximumTime = 
+Observation.Scheduler.windowMinimumTime = 
+Observation.TBB.TBBsetting.RCUs = []
+Observation.TBB.TBBsetting.baselevel = 127
+Observation.TBB.TBBsetting.filter = 0
+Observation.TBB.TBBsetting.filter0_coeff0 = 0
+Observation.TBB.TBBsetting.filter0_coeff1 = 0
+Observation.TBB.TBBsetting.filter0_coeff2 = 0
+Observation.TBB.TBBsetting.filter0_coeff3 = 0
+Observation.TBB.TBBsetting.filter1_coeff0 = 0
+Observation.TBB.TBBsetting.filter1_coeff1 = 0
+Observation.TBB.TBBsetting.filter1_coeff2 = 0
+Observation.TBB.TBBsetting.filter1_coeff3 = 0
+Observation.TBB.TBBsetting.operatingMode = 2
+Observation.TBB.TBBsetting.startlevel = 7
+Observation.TBB.TBBsetting.stoplevel = 7
+Observation.TBB.TBBsetting.subbandList = [0]
+Observation.TBB.TBBsetting.subbandList2 = [175..418]
+Observation.TBB.TBBsetting.triggerMode = 1
+Observation.TBB.TBBsetting.window = 1M
+Observation.VirtualInstrument.imageNodeList = []
+Observation.VirtualInstrument.minimalNrStations = 1
+Observation.VirtualInstrument.partitionList = [R00]
+Observation.VirtualInstrument.stationList = [CS001,CS002,CS003,CS004,CS005,CS006,CS007,CS011,CS017,CS021,CS024,CS026,CS028,CS030,CS031,CS032,CS101,CS103,CS201,CS301,CS302,CS401,CS501,RS106,RS205,RS208,RS306,RS307,RS406,RS503,RS508,RS509]
+Observation.VirtualInstrument.stationSet = Custom
+Observation.VirtualInstrument.storageCapacity = 760
+Observation.VirtualInstrument.storageNodeList = []
+Observation.antennaArray = LBA
+Observation.antennaSet = LBA_INNER
+Observation.bandFilter = LBA_10_90
+Observation.beamList = [244*0]
+Observation.channelWidth = 762.939453125
+Observation.channelsPerSubband = 16
+Observation.claimPeriod = 50
+Observation.clockMode = <<Clock200
+Observation.existingAntennaFields = [LBA,HBA,HBA0,HBA1]
+Observation.existingStations = [CS001,CS002,CS003,CS004,CS005,CS006,CS007,CS011,CS013,CS017,CS021,CS024,CS026,CS028,CS030,CS031,CS101,CS103,CS201,CS301,CS302,CS401,CS501,RS106,RS205,RS208,RS306,RS307,RS406,RS503,DE601,DE602,DE603,DE604,DE605,FR606,UK608]
+Observation.longBaselines = false
+Observation.nrAnaBeams = 0
+Observation.nrBeamformers = 0
+Observation.nrBeams = 1
+Observation.nrPolarisations = 2
+Observation.nrSlotsInFrame = 61
+Observation.nrTBBSettings = 0
+Observation.preparePeriod = 30
+Observation.processSubtype = 'Beam Observation'
+Observation.processType = Observation
+Observation.receiverList = []
+Observation.referencePhaseCenter = [3826577.066,461022.948,5064892.786]
+Observation.rspBoardList = [244*0]
+Observation.rspSlotList = [244*0]
+Observation.sampleClock = 200
+Observation.samplesPerSecond = 196608
+Observation.startTime = '2012-06-19 08:00:00'
+Observation.stopTime = '2012-06-19 16:15:00'
+Observation.strategy = default
+Observation.subbandList = [175..418]
+Observation.subbandWidth = 195.3125
+Observation.topologyID = 
+PIC.Core.CS001HBA.clockCorrectionTime = 0
+PIC.Core.CS001HBA.phaseCenter = [3826937.810,460938.526,5064630.696]
+PIC.Core.CS001HBA0.clockCorrectionTime = 0
+PIC.Core.CS001HBA0.phaseCenter = [3826896.235,460979.455,5064658.203]
+PIC.Core.CS001HBA1.clockCorrectionTime = 0
+PIC.Core.CS001HBA1.phaseCenter = [3826979.384,460897.597,5064603.189]
+PIC.Core.CS001LBA.clockCorrectionTime = 0
+PIC.Core.CS001LBA.phaseCenter = [3826923.546,460915.441,5064643.489]
+PIC.Core.CS001LBA.position = [3826923.546,460915.441,5064643.489]
+PIC.Core.CS002HBA.clockCorrectionTime = 8.318569e-06
+PIC.Core.CS002HBA.phaseCenter = [3826583.278,460955.756,5064894.197]
+PIC.Core.CS002HBA0.clockCorrectionTime = 8.318834e-06
+PIC.Core.CS002HBA0.phaseCenter = [3826600.961,460953.402,5064881.136]
+PIC.Core.CS002HBA1.clockCorrectionTime = 8.318304e-06
+PIC.Core.CS002HBA1.phaseCenter = [3826565.594,460958.110,5064907.258]
+PIC.Core.CS002LBA.clockCorrectionTime = 8.339918e-06
+PIC.Core.CS002LBA.phaseCenter = [3826577.066,461022.948,5064892.786]
+PIC.Core.CS002LBA.position = [3826577.066,461022.948,5064892.786]
+PIC.Core.CS003HBA.clockCorrectionTime = 6.917899e-06
+PIC.Core.CS003HBA.phaseCenter = [3826494.580,461017.698,5064955.176]
+PIC.Core.CS003HBA0.clockCorrectionTime = 6.917926e-06
+PIC.Core.CS003HBA0.phaseCenter = [3826471.348,461000.138,5064974.201]
+PIC.Core.CS003HBA1.clockCorrectionTime = 6.917872e-06
+PIC.Core.CS003HBA1.phaseCenter = [3826517.812,461035.258,5064936.150]
+PIC.Core.CS003LBA.clockCorrectionTime = 6.936566e-06
+PIC.Core.CS003LBA.phaseCenter = [3826516.748,460930.066,5064946.457]
+PIC.Core.CS003LBA.position = [3826516.748,460930.066,5064946.457]
+PIC.Core.CS004HBA.clockCorrectionTime = 7.889733e-06
+PIC.Core.CS004HBA.phaseCenter = [3826582.556,460891.662,5064900.532]
+PIC.Core.CS004HBA0.clockCorrectionTime = 7.889961e-06
+PIC.Core.CS004HBA0.phaseCenter = [3826585.626,460865.844,5064900.561]
+PIC.Core.CS004HBA1.clockCorrectionTime = 7.889505e-06
+PIC.Core.CS004HBA1.phaseCenter = [3826579.486,460917.480,5064900.502]
+PIC.Core.CS004LBA.clockCorrectionTime = 7.905512e-06
+PIC.Core.CS004LBA.phaseCenter = [3826654.197,460939.576,5064842.426]
+PIC.Core.CS004LBA.position = [3826654.197,460939.576,5064842.426]
+PIC.Core.CS005HBA.clockCorrectionTime = 8.541942e-06
+PIC.Core.CS005HBA.phaseCenter = [3826666.177,461005.533,5064827.472]
+PIC.Core.CS005HBA0.clockCorrectionTime = 8.542093e-06
+PIC.Core.CS005HBA0.phaseCenter = [3826701.160,460989.250,5064802.685]
+PIC.Core.CS005HBA1.clockCorrectionTime = 8.541791e-06
+PIC.Core.CS005HBA1.phaseCenter = [3826631.194,461021.815,5064852.259]
+PIC.Core.CS005LBA.clockCorrectionTime = 8.556805e-06
+PIC.Core.CS005LBA.phaseCenter = [3826668.750,461069.550,5064819.754]
+PIC.Core.CS005LBA.position = [3826668.750,461069.550,5064819.754]
+PIC.Core.CS006HBA.clockCorrectionTime = 7.882660e-06
+PIC.Core.CS006HBA.phaseCenter = [3826633.141,461108.369,5064842.975]
+PIC.Core.CS006HBA0.clockCorrectionTime = 7.882360e-06
+PIC.Core.CS006HBA0.phaseCenter = [3826653.783,461136.440,5064824.943]
+PIC.Core.CS006HBA1.clockCorrectionTime = 7.882960e-06
+PIC.Core.CS006HBA1.phaseCenter = [3826612.499,461080.298,5064861.006]
+PIC.Core.CS006LBA.clockCorrectionTime = 7.905282e-06
+PIC.Core.CS006LBA.phaseCenter = [3826596.730,461145.178,5064866.978]
+PIC.Core.CS006LBA.position = [3826596.730,461145.178,5064866.978]
+PIC.Core.CS007HBA.clockCorrectionTime = 7.913140e-06
+PIC.Core.CS007HBA.phaseCenter = [3826508.368,461126.726,5064934.972]
+PIC.Core.CS007HBA0.clockCorrectionTime = 7.913020e-06
+PIC.Core.CS007HBA0.phaseCenter = [3826478.715,461083.720,5064961.117]
+PIC.Core.CS007HBA1.clockCorrectionTime = 7.913260e-06
+PIC.Core.CS007HBA1.phaseCenter = [3826538.021,461169.731,5064908.827]
+PIC.Core.CS007LBA.clockCorrectionTime = 7.928823e-06
+PIC.Core.CS007LBA.phaseCenter = [3826533.361,461098.966,5064918.721]
+PIC.Core.CS007LBA.position = [3826533.361,461098.966,5064918.721]
+PIC.Core.CS011HBA.clockCorrectionTime = 0
+PIC.Core.CS011HBA.phaseCenter = [3826643.191,461290.793,5064819.069]
+PIC.Core.CS011HBA0.clockCorrectionTime = 0
+PIC.Core.CS011HBA0.phaseCenter = [3826637.421,461227.345,5064829.134]
+PIC.Core.CS011HBA1.clockCorrectionTime = 0
+PIC.Core.CS011HBA1.phaseCenter = [3826648.961,461354.241,5064809.003]
+PIC.Core.CS011LBA.clockCorrectionTime = 0
+PIC.Core.CS011LBA.phaseCenter = [3826667.069,461285.849,5064801.592]
+PIC.Core.CS011LBA.position = [3826667.069,461285.849,5064801.592]
+PIC.Core.CS013HBA.clockCorrectionTime = 0
+PIC.Core.CS013HBA.phaseCenter = [3826360.529,460815.196,5065074.343]
+PIC.Core.CS013HBA0.clockCorrectionTime = 0
+PIC.Core.CS013HBA0.phaseCenter = [3826318.954,460856.125,5065101.850]
+PIC.Core.CS013HBA1.clockCorrectionTime = 0
+PIC.Core.CS013HBA1.phaseCenter = [3826402.103,460774.267,5065046.836]
+PIC.Core.CS013LBA.clockCorrectionTime = 0
+PIC.Core.CS013LBA.phaseCenter = [3826346.265,460792.111,5065087.136]
+PIC.Core.CS017HBA.clockCorrectionTime = 0
+PIC.Core.CS017HBA.phaseCenter = [3826452.439,461529.979,5064940.511]
+PIC.Core.CS017HBA0.clockCorrectionTime = 0
+PIC.Core.CS017HBA0.phaseCenter = [3826405.095,461507.460,5064978.083]
+PIC.Core.CS017HBA1.clockCorrectionTime = 0
+PIC.Core.CS017HBA1.phaseCenter = [3826499.783,461552.498,5064902.938]
+PIC.Core.CS017LBA.clockCorrectionTime = 0
+PIC.Core.CS017LBA.phaseCenter = [3826462.054,461501.950,5064935.827]
+PIC.Core.CS017LBA.position = [3826462.054,461501.950,5064935.827]
+PIC.Core.CS021HBA.clockCorrectionTime = 0
+PIC.Core.CS021HBA.phaseCenter = [3826416.158,460510.576,5065060.187]
+PIC.Core.CS021HBA0.clockCorrectionTime = 0
+PIC.Core.CS021HBA0.phaseCenter = [3826463.502,460533.094,5065022.614]
+PIC.Core.CS021HBA1.clockCorrectionTime = 0
+PIC.Core.CS021HBA1.phaseCenter = [3826368.813,460488.057,5065097.759]
+PIC.Core.CS021LBA.clockCorrectionTime = 0
+PIC.Core.CS021LBA.phaseCenter = [3826406.543,460538.604,5065064.870]
+PIC.Core.CS021LBA.position = [3826406.543,460538.604,5065064.870]
+PIC.Core.CS024HBA.clockCorrectionTime = 0
+PIC.Core.CS024HBA.phaseCenter = [3827170.849,461381.379,5064416.362]
+PIC.Core.CS024HBA0.clockCorrectionTime = 0
+PIC.Core.CS024HBA0.phaseCenter = [3827218.193,461403.898,5064378.790]
+PIC.Core.CS024HBA1.clockCorrectionTime = 0
+PIC.Core.CS024HBA1.phaseCenter = [3827123.504,461358.861,5064453.935]
+PIC.Core.CS024LBA.clockCorrectionTime = 0
+PIC.Core.CS024LBA.phaseCenter = [3827161.234,461409.408,5064421.046]
+PIC.Core.CS024LBA.position = [3827161.234,461409.408,5064421.046]
+PIC.Core.CS026HBA.clockCorrectionTime = 0
+PIC.Core.CS026HBA.phaseCenter = [3826376.653,461846.767,5064968.706]
+PIC.Core.CS026HBA0.clockCorrectionTime = 0
+PIC.Core.CS026HBA0.phaseCenter = [3826418.227,461805.837,5064941.199]
+PIC.Core.CS026HBA1.clockCorrectionTime = 0
+PIC.Core.CS026HBA1.phaseCenter = [3826335.078,461887.696,5064996.213]
+PIC.Core.CS026LBA.clockCorrectionTime = 0
+PIC.Core.CS026LBA.phaseCenter = [3826390.916,461869.852,5064955.913]
+PIC.Core.CS026LBA.position = [3826390.916,461869.852,5064955.913]
+PIC.Core.CS028HBA.clockCorrectionTime = 0
+PIC.Core.CS028HBA.phaseCenter = [3825614.709,461283.678,5065591.532]
+PIC.Core.CS028HBA0.clockCorrectionTime = 0
+PIC.Core.CS028HBA0.phaseCenter = [3825573.134,461324.607,5065619.039]
+PIC.Core.CS028HBA1.clockCorrectionTime = 0
+PIC.Core.CS028HBA1.phaseCenter = [3825656.283,461242.749,5065564.025]
+PIC.Core.CS028LBA.clockCorrectionTime = 0
+PIC.Core.CS028LBA.phaseCenter = [3825600.445,461260.593,5065604.325]
+PIC.Core.CS028LBA.position = [3825600.445,461260.593,5065604.325]
+PIC.Core.CS030HBA.clockCorrectionTime = 0
+PIC.Core.CS030HBA.phaseCenter = [3826000.003,460364.303,5065385.121]
+PIC.Core.CS030HBA0.clockCorrectionTime = 0
+PIC.Core.CS030HBA0.phaseCenter = [3826041.577,460323.374,5065357.614]
+PIC.Core.CS030HBA1.clockCorrectionTime = 0
+PIC.Core.CS030HBA1.phaseCenter = [3825958.428,460405.233,5065412.628]
+PIC.Core.CS030LBA.clockCorrectionTime = 0
+PIC.Core.CS030LBA.phaseCenter = [3826014.266,460387.389,5065372.328]
+PIC.Core.CS030LBA.position = [3826014.266,460387.389,5065372.328]
+PIC.Core.CS031HBA.clockCorrectionTime = 0
+PIC.Core.CS031HBA.phaseCenter = [3826430.381,460301.862,5065068.278]
+PIC.Core.CS031HBA0.clockCorrectionTime = 0
+PIC.Core.CS031HBA0.phaseCenter = [3826383.037,460279.343,5065105.850]
+PIC.Core.CS031HBA1.clockCorrectionTime = 0
+PIC.Core.CS031HBA1.phaseCenter = [3826477.725,460324.381,5065030.705]
+PIC.Core.CS031LBA.clockCorrectionTime = 0
+PIC.Core.CS031LBA.phaseCenter = [3826439.996,460273.833,5065063.594]
+PIC.Core.CS031LBA.position = [3826439.996,460273.833,5065063.594]
+PIC.Core.CS032HBA.clockCorrectionTime = 0
+PIC.Core.CS032HBA.phaseCenter = [3826905.837,460410.995,5064702.499]
+PIC.Core.CS032HBA0.clockCorrectionTime = 0
+PIC.Core.CS032HBA0.phaseCenter = [3826864.262,460451.924,5064730.006]
+PIC.Core.CS032HBA1.clockCorrectionTime = 0
+PIC.Core.CS032HBA1.phaseCenter = [3826947.411,460370.066,5064674.992]
+PIC.Core.CS032LBA.clockCorrectionTime = 0
+PIC.Core.CS032LBA.phaseCenter = [3826891.573,460387.910,5064715.292]
+PIC.Core.CS032LBA.position = [3826891.573,460387.910,5064715.292]
+PIC.Core.CS101HBA.clockCorrectionTime = 0
+PIC.Core.CS101HBA.phaseCenter = [3825857.958,461661.510,5065374.102]
+PIC.Core.CS101HBA0.clockCorrectionTime = 0
+PIC.Core.CS101HBA0.phaseCenter = [3825905.302,461684.028,5065336.529]
+PIC.Core.CS101HBA1.clockCorrectionTime = 0
+PIC.Core.CS101HBA1.phaseCenter = [3825810.613,461638.991,5065411.674]
+PIC.Core.CS101LBA.clockCorrectionTime = 0
+PIC.Core.CS101LBA.phaseCenter = [3825848.343,461689.538,5065378.785]
+PIC.Core.CS101LBA.position = [3825848.343,461689.538,5065378.785]
+PIC.Core.CS103HBA.clockCorrectionTime = 0
+PIC.Core.CS103HBA.phaseCenter = [3826290.016,462800.003,5064947.127]
+PIC.Core.CS103HBA0.clockCorrectionTime = 0
+PIC.Core.CS103HBA0.phaseCenter = [3826331.590,462759.074,5064919.620]
+PIC.Core.CS103HBA1.clockCorrectionTime = 0
+PIC.Core.CS103HBA1.phaseCenter = [3826248.441,462840.933,5064974.634]
+PIC.Core.CS103LBA.clockCorrectionTime = 0
+PIC.Core.CS103LBA.phaseCenter = [3826304.279,462823.089,5064934.334]
+PIC.Core.CS103LBA.position = [3826304.279,462823.089,5064934.334]
+PIC.Core.CS201HBA.clockCorrectionTime = 0
+PIC.Core.CS201HBA.phaseCenter = [3826685.051,461918.691,5064731.315]
+PIC.Core.CS201HBA0.clockCorrectionTime = 0
+PIC.Core.CS201HBA0.phaseCenter = [3826679.281,461855.243,5064741.380]
+PIC.Core.CS201HBA1.clockCorrectionTime = 0
+PIC.Core.CS201HBA1.phaseCenter = [3826690.821,461982.139,5064721.249]
+PIC.Core.CS201LBA.clockCorrectionTime = 0
+PIC.Core.CS201LBA.phaseCenter = [3826708.929,461913.747,5064713.838]
+PIC.Core.CS201LBA.position = [3826708.929,461913.747,5064713.838]
+PIC.Core.CS301HBA.clockCorrectionTime = 0
+PIC.Core.CS301HBA.phaseCenter = [3827453.340,460985.281,5064240.201]
+PIC.Core.CS301HBA0.clockCorrectionTime = 0
+PIC.Core.CS301HBA0.phaseCenter = [3827459.109,461048.728,5064230.136]
+PIC.Core.CS301HBA1.clockCorrectionTime = 0
+PIC.Core.CS301HBA1.phaseCenter = [3827447.570,460921.833,5064250.266]
+PIC.Core.CS301LBA.clockCorrectionTime = 0
+PIC.Core.CS301LBA.phaseCenter = [3827429.462,460990.224,5064257.677]
+PIC.Core.CS301LBA.position = [3827429.462,460990.224,5064257.677]
+PIC.Core.CS302HBA.clockCorrectionTime = 0
+PIC.Core.CS302HBA.phaseCenter = [3827931.652,459769.554,5064002.807]
+PIC.Core.CS302HBA0.clockCorrectionTime = 0
+PIC.Core.CS302HBA0.phaseCenter = [3827973.226,459728.624,5063975.300]
+PIC.Core.CS302HBA1.clockCorrectionTime = 0
+PIC.Core.CS302HBA1.phaseCenter = [3827890.077,459810.483,5064030.313]
+PIC.Core.CS302LBA.clockCorrectionTime = 0
+PIC.Core.CS302LBA.phaseCenter = [3827945.916,459792.639,5063990.016]
+PIC.Core.CS302LBA.position = [3827945.916,459792.639,5063990.016]
+PIC.Core.CS401HBA.clockCorrectionTime = 8.069737e-06
+PIC.Core.CS401HBA.phaseCenter = [3826789.982,460095.444,5064818.996]
+PIC.Core.CS401HBA0.clockCorrectionTime = 8.069604e-06
+PIC.Core.CS401HBA0.phaseCenter = [3826795.752,460158.894,5064808.929]
+PIC.Core.CS401HBA1.clockCorrectionTime = 8.069870e-06
+PIC.Core.CS401HBA1.phaseCenter = [3826784.211,460031.993,5064829.062]
+PIC.Core.CS401LBA.clockCorrectionTime = 8.06397e-06
+PIC.Core.CS401LBA.phaseCenter = [3826766.106,460100.388,5064836.470]
+PIC.Core.CS401LBA.position = [3826766.106,460100.388,5064836.470]
+PIC.Core.CS501HBA.clockCorrectionTime = 0
+PIC.Core.CS501HBA.phaseCenter = [3825616.164,460670.139,5065645.456]
+PIC.Core.CS501HBA0.clockCorrectionTime = 0
+PIC.Core.CS501HBA0.phaseCenter = [3825568.820,460647.620,5065683.028]
+PIC.Core.CS501HBA1.clockCorrectionTime = 0
+PIC.Core.CS501HBA1.phaseCenter = [3825663.508,460692.658,5065607.883]
+PIC.Core.CS501LBA.clockCorrectionTime = 0
+PIC.Core.CS501LBA.phaseCenter = [3825625.779,460642.110,5065640.772]
+PIC.Core.CS501LBA.position = [3825625.779,460642.110,5065640.772]
+PIC.Core.DE601HBA.clockCorrectionTime = 1.1e-6
+PIC.Core.DE601HBA.phaseCenter = [4034099.840,487013.425,4900229.635]
+PIC.Core.DE601LBA.clockCorrectionTime = 1.1e-6
+PIC.Core.DE601LBA.phaseCenter = [4034036.396,487026.791,4900279.047]
+PIC.Core.DE602HBA.clockCorrectionTime = 0
+PIC.Core.DE602HBA.phaseCenter = [4152568.006,828789.153,4754362.203]
+PIC.Core.DE602LBA.clockCorrectionTime = 0
+PIC.Core.DE602LBA.phaseCenter = [4152560.658,828869.076,4754357.155]
+PIC.Core.DE603HBA.clockCorrectionTime = 0
+PIC.Core.DE603HBA.phaseCenter = [3940295.706,816722.865,4932394.416]
+PIC.Core.DE603LBA.clockCorrectionTime = 0
+PIC.Core.DE603LBA.phaseCenter = [3940284.908,816802.334,4932393.021]
+PIC.Core.DE604HBA.clockCorrectionTime = 0
+PIC.Core.DE604HBA.phaseCenter = [3796379.823,877614.130,5032712.528]
+PIC.Core.DE604LBA.clockCorrectionTime = 0
+PIC.Core.DE604LBA.phaseCenter = [3796327.178,877591.636,5032757.508]
+PIC.Core.DE605HBA.clockCorrectionTime = 0
+PIC.Core.DE605HBA.phaseCenter = [4005681.020,450968.643,4926458.211]
+PIC.Core.DE605LBA.clockCorrectionTime = 0
+PIC.Core.DE605LBA.phaseCenter = [4005681.355,450968.621,4926457.941]
+PIC.Core.FR606HBA.clockCorrectionTime = 0
+PIC.Core.FR606HBA.phaseCenter = [4324016.708,165545.525,4670271.363]
+PIC.Core.FR606LBA.clockCorrectionTime = 0
+PIC.Core.FR606LBA.phaseCenter = [4323979.809,165608.773,4670303.094]
+PIC.Core.IONProc.R00[0].inputs = []
+PIC.Core.IONProc.R00[10].inputs = []
+PIC.Core.IONProc.R00[11].inputs = []
+PIC.Core.IONProc.R00[12].inputs = []
+PIC.Core.IONProc.R00[13].inputs = []
+PIC.Core.IONProc.R00[14].inputs = []
+PIC.Core.IONProc.R00[15].inputs = []
+PIC.Core.IONProc.R00[16].inputs = []
+PIC.Core.IONProc.R00[17].inputs = []
+PIC.Core.IONProc.R00[18].inputs = []
+PIC.Core.IONProc.R00[19].inputs = []
+PIC.Core.IONProc.R00[1].inputs = []
+PIC.Core.IONProc.R00[20].inputs = []
+PIC.Core.IONProc.R00[21].inputs = []
+PIC.Core.IONProc.R00[22].inputs = []
+PIC.Core.IONProc.R00[23].inputs = [RS205LBA/RSP0,RS205LBA/RSP1,RS205LBA/RSP2,RS205LBA/RSP3]
+PIC.Core.IONProc.R00[24].inputs = []
+PIC.Core.IONProc.R00[25].inputs = []
+PIC.Core.IONProc.R00[26].inputs = [CS302LBA/RSP0,CS302LBA/RSP1,CS302LBA/RSP2,CS302LBA/RSP3]
+PIC.Core.IONProc.R00[27].inputs = []
+PIC.Core.IONProc.R00[28].inputs = []
+PIC.Core.IONProc.R00[29].inputs = []
+PIC.Core.IONProc.R00[2].inputs = []
+PIC.Core.IONProc.R00[30].inputs = [RS406LBA/RSP0,RS406LBA/RSP1,RS406LBA/RSP2,RS406LBA/RSP3]
+PIC.Core.IONProc.R00[31].inputs = [RS509LBA/RSP0,RS509LBA/RSP1,RS509LBA/RSP2,RS509LBA/RSP3]
+PIC.Core.IONProc.R00[32].inputs = [CS021LBA/RSP0,CS021LBA/RSP1,CS021LBA/RSP2,CS021LBA/RSP3]
+PIC.Core.IONProc.R00[33].inputs = [CS005LBA/RSP0,CS005LBA/RSP1,CS005LBA/RSP2,CS005LBA/RSP3]
+PIC.Core.IONProc.R00[34].inputs = [CS002LBA/RSP0,CS002LBA/RSP1,CS002LBA/RSP2,CS002LBA/RSP3]
+PIC.Core.IONProc.R00[35].inputs = [CS006LBA/RSP0,CS006LBA/RSP1,CS006LBA/RSP2,CS006LBA/RSP3]
+PIC.Core.IONProc.R00[36].inputs = [CS003LBA/RSP0,CS003LBA/RSP1,CS003LBA/RSP2,CS003LBA/RSP3]
+PIC.Core.IONProc.R00[37].inputs = [CS007LBA/RSP0,CS007LBA/RSP1,CS007LBA/RSP2,CS007LBA/RSP3]
+PIC.Core.IONProc.R00[38].inputs = [CS004LBA/RSP0,CS004LBA/RSP1,CS004LBA/RSP2,CS004LBA/RSP3]
+PIC.Core.IONProc.R00[39].inputs = [CS024LBA/RSP0,CS024LBA/RSP1,CS024LBA/RSP2,CS024LBA/RSP3]
+PIC.Core.IONProc.R00[3].inputs = []
+PIC.Core.IONProc.R00[40].inputs = [CS101LBA/RSP0,CS101LBA/RSP1,CS101LBA/RSP2,CS101LBA/RSP3]
+PIC.Core.IONProc.R00[41].inputs = [CS032LBA/RSP0,CS032LBA/RSP1,CS032LBA/RSP2,CS032LBA/RSP3]
+PIC.Core.IONProc.R00[42].inputs = [CS026LBA/RSP0,CS026LBA/RSP1,CS026LBA/RSP2,CS026LBA/RSP3]
+PIC.Core.IONProc.R00[43].inputs = [CS201LBA/RSP0,CS201LBA/RSP1,CS201LBA/RSP2,CS201LBA/RSP3]
+PIC.Core.IONProc.R00[44].inputs = [CS030LBA/RSP0,CS030LBA/RSP1,CS030LBA/RSP2,CS030LBA/RSP3]
+PIC.Core.IONProc.R00[45].inputs = [CS301LBA/RSP0,CS301LBA/RSP1,CS301LBA/RSP2,CS301LBA/RSP3]
+PIC.Core.IONProc.R00[46].inputs = [CS001LBA/RSP0,CS001LBA/RSP1,CS001LBA/RSP2,CS001LBA/RSP3]
+PIC.Core.IONProc.R00[47].inputs = [CS401LBA/RSP0,CS401LBA/RSP1,CS401LBA/RSP2,CS401LBA/RSP3]
+PIC.Core.IONProc.R00[48].inputs = [CS017LBA/RSP0,CS017LBA/RSP1,CS017LBA/RSP2,CS017LBA/RSP3]
+PIC.Core.IONProc.R00[49].inputs = [RS208LBA/RSP0,RS208LBA/RSP1,RS208LBA/RSP2,RS208LBA/RSP3]
+PIC.Core.IONProc.R00[4].inputs = []
+PIC.Core.IONProc.R00[50].inputs = [CS011LBA/RSP0,CS011LBA/RSP1,CS011LBA/RSP2,CS011LBA/RSP3]
+PIC.Core.IONProc.R00[51].inputs = [CS028LBA/RSP0,CS028LBA/RSP1,CS028LBA/RSP2,CS028LBA/RSP3]
+PIC.Core.IONProc.R00[52].inputs = [CS501LBA/RSP0,CS501LBA/RSP1,CS501LBA/RSP2,CS501LBA/RSP3]
+PIC.Core.IONProc.R00[53].inputs = [RS503LBA/RSP0,RS503LBA/RSP1,RS503LBA/RSP2,RS503LBA/RSP3]
+PIC.Core.IONProc.R00[54].inputs = [CS103LBA/RSP0,CS103LBA/RSP1,CS103LBA/RSP2,CS103LBA/RSP3]
+PIC.Core.IONProc.R00[55].inputs = [RS106LBA/RSP0,RS106LBA/RSP1,RS106LBA/RSP2,RS106LBA/RSP3]
+PIC.Core.IONProc.R00[56].inputs = []
+PIC.Core.IONProc.R00[57].inputs = []
+PIC.Core.IONProc.R00[58].inputs = [CS031LBA/RSP0,CS031LBA/RSP1,CS031LBA/RSP2,CS031LBA/RSP3]
+PIC.Core.IONProc.R00[59].inputs = []
+PIC.Core.IONProc.R00[5].inputs = []
+PIC.Core.IONProc.R00[60].inputs = [RS306LBA/RSP0,RS306LBA/RSP1,RS306LBA/RSP2,RS306LBA/RSP3]
+PIC.Core.IONProc.R00[61].inputs = []
+PIC.Core.IONProc.R00[62].inputs = [RS307LBA/RSP0,RS307LBA/RSP1,RS307LBA/RSP2,RS307LBA/RSP3]
+PIC.Core.IONProc.R00[63].inputs = [RS508LBA/RSP0,RS508LBA/RSP1,RS508LBA/RSP2,RS508LBA/RSP3]
+PIC.Core.IONProc.R00[6].inputs = []
+PIC.Core.IONProc.R00[7].inputs = []
+PIC.Core.IONProc.R00[8].inputs = []
+PIC.Core.IONProc.R00[9].inputs = []
+PIC.Core.RS106HBA.clockCorrectionTime = 0
+PIC.Core.RS106HBA.phaseCenter = [3829205.598,469142.533,5062181.002]
+PIC.Core.RS106LBA.clockCorrectionTime = 0
+PIC.Core.RS106LBA.phaseCenter = [3829261.425,469162.285,5062137.310]
+PIC.Core.RS106LBA.position = [3829261.425,469162.285,5062137.310]
+PIC.Core.RS205HBA.clockCorrectionTime = 0
+PIC.Core.RS205HBA.phaseCenter = [3831479.670,463487.529,5060989.903]
+PIC.Core.RS205LBA.clockCorrectionTime = 0
+PIC.Core.RS205LBA.phaseCenter = [3831438.563,463435.440,5061025.466]
+PIC.Core.RS205LBA.position = [3831438.563,463435.440,5061025.466]
+PIC.Core.RS208HBA.clockCorrectionTime = 0
+PIC.Core.RS208HBA.phaseCenter = [3847753.310,466962.809,5048397.244]
+PIC.Core.RS208LBA.clockCorrectionTime = 0
+PIC.Core.RS208LBA.phaseCenter = [3847810.051,466929.706,5048357.222]
+PIC.Core.RS208LBA.position = [3847810.051,466929.706,5048357.222]
+PIC.Core.RS306HBA.clockCorrectionTime = 0
+PIC.Core.RS306HBA.phaseCenter = [3829771.249,452761.702,5063243.181]
+PIC.Core.RS306LBA.clockCorrectionTime = 0
+PIC.Core.RS306LBA.phaseCenter = [3829791.808,452829.848,5063221.590]
+PIC.Core.RS306LBA.position = [3829791.808,452829.848,5063221.590]
+PIC.Core.RS307HBA.clockCorrectionTime = 0
+PIC.Core.RS307HBA.phaseCenter = [3837964.520,449627.261,5057357.585]
+PIC.Core.RS307LBA.clockCorrectionTime = 0
+PIC.Core.RS307LBA.phaseCenter = [3837940.949,449560.756,5057381.288]
+PIC.Core.RS307LBA.position = [3837940.949,449560.756,5057381.288]
+PIC.Core.RS406HBA.clockCorrectionTime = 0
+PIC.Core.RS406HBA.phaseCenter = [3818424.939,452020.269,5071817.644]
+PIC.Core.RS406LBA.clockCorrectionTime = 0
+PIC.Core.RS406LBA.phaseCenter = [3818467.634,451974.601,5071790.597]
+PIC.Core.RS406LBA.position = [3818467.634,451974.601,5071790.597]
+PIC.Core.RS503HBA.clockCorrectionTime = 0
+PIC.Core.RS503HBA.phaseCenter = [3824138.566,459476.972,5066858.578]
+PIC.Core.RS503LBA.clockCorrectionTime = 0
+PIC.Core.RS503LBA.phaseCenter = [3824090.452,459438.282,5066898.190]
+PIC.Core.RS503LBA.position = [3824090.452,459438.282,5066898.190]
+PIC.Core.RS508HBA.clockCorrectionTime = 0
+PIC.Core.RS508HBA.phaseCenter = [3797136.484,463114.447,5086651.286]
+PIC.Core.RS508LBA.clockCorrectionTime = 0
+PIC.Core.RS508LBA.phaseCenter = [3797202.116,463087.509,5086605.037]
+PIC.Core.RS508LBA.position = [3797202.116,463087.509,5086605.037]
+PIC.Core.RS509HBA.clockCorrectionTime = 0
+PIC.Core.RS509HBA.phaseCenter = [3783537.525,450130.064,5097866.146]
+PIC.Core.RS509LBA.clockCorrectionTime = 0
+PIC.Core.RS509LBA.phaseCenter = [3783579.131,450178.882,5097830.835]
+PIC.Core.RS509LBA.position = [3783579.131,450178.882,5097830.835]
+PIC.Core.S1.phaseCenter = [3826615.56096,460986.585898,5064718.84237]
+PIC.Core.S10.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S129.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S13.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S130.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S133.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S134.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S137.phaseCenter = [3826967.64713,460904.072585,5064612.8258]
+PIC.Core.S138.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S14.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S141.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S142.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S145.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S146.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S149.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S150.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S153.phaseCenter = [3826967.64713,460904.072585,5064612.8258]
+PIC.Core.S154.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S157.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S158.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S161.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S162.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S165.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S166.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S169.phaseCenter = [3826967.64713,460904.072585,5064612.8258]
+PIC.Core.S17.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S170.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S173.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S174.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S177.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S178.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S18.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S181.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S182.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S185.phaseCenter = [3826967.64713,460904.072585,5064612.8258]
+PIC.Core.S186.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S189.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S190.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S2.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S21.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S22.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S25.phaseCenter = [3826967.64713,460904.072585,5064612.8258]
+PIC.Core.S26.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S29.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S30.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S33.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S34.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S37.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S38.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S41.phaseCenter = [3826967.64713,460904.072585,5064612.8258]
+PIC.Core.S42.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S45.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S46.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S49.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S5.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S50.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S53.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S54.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S57.phaseCenter = [3826967.64713,460904.072585,5064612.8258]
+PIC.Core.S58.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S6.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S61.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S62.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.S9.phaseCenter = [3826967.64713,460904.072585,5064612.8258]
+PIC.Core.SE607HBA.clockCorrectionTime = 0
+PIC.Core.SE607HBA.phaseCenter = [3370271.657,712125.881,5349991.165]
+PIC.Core.SE607LBA.clockCorrectionTime = 0
+PIC.Core.SE607LBA.phaseCenter = [3370286.931,712053.871,5349991.459]
+PIC.Core.Station.CS001LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.CS002LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.CS003LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.CS004LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.CS005LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.CS006LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.CS007LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.CS011LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.CS017LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.CS021LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.CS024LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.CS026LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.CS028LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.CS030LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.CS031LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.CS032LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.CS101LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.CS103LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.CS201LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.CS301LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.CS302LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.CS401LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.CS501LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.RS106LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.RS205LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.RS208LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.RS306LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.RS307LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.RS406LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.RS503LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.RS508LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.Station.RS509LBA.RSP.ports = [0.0.0.0:4346,0.0.0.0:4347,0.0.0.0:4348,0.0.0.0:4349]
+PIC.Core.T1.phaseCenter = [3826615.56096,460986.585898,5064718.84237]
+PIC.Core.T10.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T129.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T13.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T130.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T133.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T134.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T137.phaseCenter = [3826967.64713,460904.072585,5064612.8258]
+PIC.Core.T138.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T14.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T141.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T142.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T145.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T146.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T149.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T150.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T153.phaseCenter = [3826967.64713,460904.072585,5064612.8258]
+PIC.Core.T154.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T157.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T158.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T161.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T162.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T165.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T166.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T169.phaseCenter = [3826967.64713,460904.072585,5064612.8258]
+PIC.Core.T17.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T170.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T173.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T174.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T177.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T178.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T18.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T181.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T182.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T185.phaseCenter = [3826967.64713,460904.072585,5064612.8258]
+PIC.Core.T186.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T189.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T190.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T2.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T21.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T22.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T25.phaseCenter = [3826967.64713,460904.072585,5064612.8258]
+PIC.Core.T26.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T29.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T30.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T33.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T34.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T37.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T38.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T41.phaseCenter = [3826967.64713,460904.072585,5064612.8258]
+PIC.Core.T42.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T45.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T46.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T49.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T5.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T50.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T53.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T54.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T57.phaseCenter = [3826967.64713,460904.072585,5064612.8258]
+PIC.Core.T58.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T6.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T61.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T62.phaseCenter = [3826815.56096,460986.585898,5064718.84237]
+PIC.Core.T9.phaseCenter = [3826967.64713,460904.072585,5064612.8258]
+PIC.Core.UK608HBA.clockCorrectionTime = 0
+PIC.Core.UK608HBA.phaseCenter = [4008461.941,-100376.609,4943716.874]
+PIC.Core.UK608LBA.clockCorrectionTime = 0
+PIC.Core.UK608LBA.phaseCenter = [4008438.457,-100309.725,4943735.828]
+_DPname = LOFAR_ObsSW_TempObs0054
+_parsetPrefix = CorrAppl.CorrProc.
+_processName = CorrProc
diff --git a/RTCP/Storage/test/tTBB_Writer.parset b/RTCP/Storage/test/tTBB_Writer-transient.parset
similarity index 100%
rename from RTCP/Storage/test/tTBB_Writer.parset
rename to RTCP/Storage/test/tTBB_Writer-transient.parset
diff --git a/RTCP/Storage/test/tTBB_Writer.sh b/RTCP/Storage/test/tTBB_Writer.sh
index f586d3a6a3a735f94242b8c445dc22e5fb509b77..dc7868f11e457bbf93a2a476442aa26dc1cc0fc3 100755
--- a/RTCP/Storage/test/tTBB_Writer.sh
+++ b/RTCP/Storage/test/tTBB_Writer.sh
@@ -11,7 +11,7 @@ touch tTBB_Writer.log
 
 nstreams = 6    # the nr of RSPs in NL stations
 
-parsetfilename = "tTBB_Writer.parset"
+parsetfilename = "tTBB_Writer-transient.parset" # does not belong to the test data, but good enough to test
 declare -a rawinfilenames
 outfilename = "unk.h5"
 declare -a rawoutfilenames
@@ -25,6 +25,10 @@ done
 
 ./runctest.sh TBB_Writer --parsetfile=$parsetfilename --timeout=1 --keeprunning=0 2>&1 >> tTBB_Writer.log
 
+# Ideally, we use h5check first to verify that the file is a proper hdf5 file,
+# but h5check is a separate util and usually not installed, so check content straight away.
+
+#can use lofar_tbb_headerinfo.py for a first guess/test
 ./tTBB_Writer-verify.py $outfilename 2>&1 >> tTBB_Writer.log
 STATUS = $?