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 = $?