diff --git a/CEP/Calibration/BBSControl/include/BBSControl/KernelProcessControl.h b/CEP/Calibration/BBSControl/include/BBSControl/KernelProcessControl.h index 684ce55b9983e45f4de3e71d2048edec271e6f6e..49e2a4d0e719a2cad6436cbbc5d7d06a3f0f20be 100644 --- a/CEP/Calibration/BBSControl/include/BBSControl/KernelProcessControl.h +++ b/CEP/Calibration/BBSControl/include/BBSControl/KernelProcessControl.h @@ -32,17 +32,11 @@ #include <BBSControl/CommandVisitor.h> #include <BBSControl/SolveStep.h> #include <BBSControl/Types.h> - #include <BBSKernel/Measurement.h> #include <BBSKernel/VisSelection.h> #include <BBSKernel/VisBuffer.h> - -#include <PLC/ProcessControl.h> - #include <ParmDB/SourceDB.h> - -//#include <ParmDB/ParmDBLog.h> // logging of solver parameters in ParmDB - +#include <PLC/ProcessControl.h> #include <Common/lofar_smartptr.h> #include <Common/lofar_string.h> #include <Common/lofar_vector.h> @@ -137,6 +131,7 @@ private: KernelIndex itsKernelIndex; // Measurement. + string itsPath; Measurement::Ptr itsMeasurement; string itsInputColumn; @@ -150,8 +145,6 @@ private: // Connection to the global solver. shared_ptr<BlobStreamableConnection> itsSolver; - -// scoped_ptr<ParmDBLog> itsParmLogger; }; //@} diff --git a/CEP/Calibration/BBSControl/include/BBSControl/SolveStep.h b/CEP/Calibration/BBSControl/include/BBSControl/SolveStep.h index b21dbcede5f8b3377163fd06b0ce919a388f47b8..11c5c006be8e8553721244a503dc938b8249c2b5 100644 --- a/CEP/Calibration/BBSControl/include/BBSControl/SolveStep.h +++ b/CEP/Calibration/BBSControl/include/BBSControl/SolveStep.h @@ -92,6 +92,11 @@ namespace LOFAR { return itsCellChunkSize; } bool propagate() const { return itsPropagateFlag; } + string logName() const + { return itsLogName; } + string logLevel() const + { return itsLogLevel; } + bool uvFlag() const { return itsUVFlag; } pair<double, double> uvRange() const @@ -128,9 +133,6 @@ namespace LOFAR { return itsBalancedEq; } bool useSVD() const { return itsUseSVD; } - - string parmLogLevel() const - { return itsParmLogLevel; } // @} // Return the command type of \c *this as a string. @@ -165,6 +167,11 @@ namespace LOFAR uint32 itsCellChunkSize; // Propagate solutions? bool itsPropagateFlag; + // Solver statistics log. + string itsLogName; + // Solver statistics log level. + string itsLogLevel; + // Should visbilities be flagged temporarily based on UV distance? bool itsUVFlag; // Interval of baseline (UV) length in wavelengths used to select samples @@ -206,9 +213,6 @@ namespace LOFAR bool itsBalancedEq; // Use singular value decomposition. bool itsUseSVD; - - // Solver ParmDB logging level - string itsParmLogLevel; }; // @} diff --git a/CEP/Calibration/BBSControl/src/KernelProcessControl.cc b/CEP/Calibration/BBSControl/src/KernelProcessControl.cc index 6aa9ec10e051031ac44da38ad928f5e15453eefe..51609455e1ec720ef0d8376d8ee56d3e1ebb8ebf 100644 --- a/CEP/Calibration/BBSControl/src/KernelProcessControl.cc +++ b/CEP/Calibration/BBSControl/src/KernelProcessControl.cc @@ -134,12 +134,11 @@ namespace LOFAR string path = ps->getString("ObservationPart.Path"); string skyDb = ps->getString("ParmDB.Sky"); string instrumentDb = ps->getString("ParmDB.Instrument"); - string solverDb=ps->getString("ParmLog", "solver"); - string loggingLevel=ps->getString("ParmLoglevel", "NONE"); try { // Open observation part. LOG_INFO_STR("Observation part: " << filesys << " : " << path); + itsPath = path; itsMeasurement.reset(new MeasurementAIPS(path)); } catch(Exception &e) { @@ -171,32 +170,6 @@ namespace LOFAR return false; } -// if(loggingLevel!="NONE") // If no parmDBLogging is set, skip the initialization -// { -// try { -// // Open ParmDBLog ParmDB for solver logging -// LOG_INFO_STR("Solver log table: " << solverDb); -// LOG_INFO_STR("Solver logging level: " << loggingLevel); -// -// // Depending on value read from parset file for logging level call constructor -// // with the corresponding enum value -// // -// if(loggingLevel=="PERSOLUTION") -// itsParmLogger.reset(new ParmDBLog(solverDb, ParmDBLog::PERSOLUTION)); -// if(loggingLevel=="PERSOLUTION_CORRMATRIX") -// itsParmLogger.reset(new ParmDBLog(solverDb, ParmDBLog::PERSOLUTION_CORRMATRIX)); -// if(loggingLevel=="PERITERATION") -// itsParmLogger.reset(new ParmDBLog(solverDb, ParmDBLog::PERITERATION)); -// if(loggingLevel=="PERITERATION_CORRMATRIX") -// itsParmLogger.reset(new ParmDBLog(solverDb, ParmDBLog::PERITERATION_CORRMATRIX)); -// } -// catch(Exception &e) { -// LOG_ERROR_STR("Failed to open instrument model parameter database: " -// << instrumentDb); -// return false; -// } -// } - string key = ps->getString("BBDB.Key", "default"); itsCalSession.reset(new CalSession(key, ps->getString("BBDB.Name"), @@ -205,12 +178,6 @@ namespace LOFAR ps->getString("BBDB.Host", "localhost"), ps->getString("BBDB.Port", ""))); - - // Get the GlobalParameterSet and write it into the MS/History table - ParameterSet parset = itsCalSession->getParset(); - //LOG_DEBUG_STR("KernelProcessControl::init() Parset = " << parset); - itsMeasurement->writeHistory(parset); - // Poll until Control is ready to accept workers. while(itsCalSession->getState() == CalSession::WAITING_FOR_CONTROL) { sleep(3); @@ -219,20 +186,22 @@ namespace LOFAR // Try to register as kernel. if(!itsCalSession->registerAsKernel(filesys, path, itsMeasurement->grid())) { - LOG_ERROR_STR("Could not register as kernel. There may be stale" - " state in the database for key: " << key); - //LOG_ERROR("Registration denied."); + LOG_ERROR_STR("Could not register as kernel. There may be stale state" + " in the database for key: " << key); return false; } - LOG_INFO_STR("Registration OK."); + + // Get the global ParameterSet and write it into the HISTORY table. + itsMeasurement->writeHistory(itsCalSession->getParset()); + setState(RUN); } catch(Exception& e) { LOG_ERROR_STR(e); return false; } - + return true; } @@ -911,7 +880,13 @@ namespace LOFAR command.rmsThreshold().end()); options.setEpsilon(command.epsilon().begin(), command.epsilon().end()); - estimate(itsChunk, blMask, crMask, model, solGrid, + // Open solution log. + casa::Path path(itsPath); + path.append(command.logName()); + ParmDBLog log(path.absoluteName(), + ParmDBLoglevel(command.logLevel()).get(), itsChunkCount != 0); + + estimate(log, itsChunk, blMask, crMask, model, solGrid, ParmManager::instance().makeSubset(command.parms(), command.exclParms(), model->parms()), options); } diff --git a/CEP/Calibration/BBSControl/src/SolveStep.cc b/CEP/Calibration/BBSControl/src/SolveStep.cc index b5585dab1f8f69617f17317c585ee944ac42c648..2af235b8ce768ce5775ea2f49b6c35be53e55828 100644 --- a/CEP/Calibration/BBSControl/src/SolveStep.cc +++ b/CEP/Calibration/BBSControl/src/SolveStep.cc @@ -91,11 +91,18 @@ namespace LOFAR << endl << indent << itsCellSize << endl << indent << "Cell chunk size: " << itsCellChunkSize << endl << indent << "Propagate solutions: " << boolalpha - << itsPropagateFlag << noboolalpha - << endl << indent << "Flag on UV interval: " << boolalpha << itsUVFlag - << noboolalpha; - if(itsUVFlag) + << itsPropagateFlag << noboolalpha; + + os << endl << indent << "Log:"; { + Indent id; + os << endl << indent << "Name: " << itsLogName + << endl << indent << "Level: " << itsLogLevel; + } + + os << endl << indent << "Flag on UV interval: " << boolalpha + << itsUVFlag << noboolalpha; + if(itsUVFlag) { Indent id; os << endl << indent << "UV interval: [" << itsUVRange.first << "," << itsUVRange.second << "] (wavelenghts)"; @@ -103,8 +110,7 @@ namespace LOFAR os << endl << indent << "Outlier rejection: " << boolalpha << itsRejectFlag << noboolalpha; - if(itsRejectFlag) - { + if(itsRejectFlag) { Indent id; os << endl << indent << "RMS threshold: " << itsRMSThreshold; @@ -112,8 +118,7 @@ namespace LOFAR os << endl << indent << "Resample observed data: " << boolalpha << itsResampleFlag << noboolalpha; - if(itsResampleFlag) - { + if(itsResampleFlag) { Indent id; os << endl << indent << "Resample cell size: "; { @@ -127,8 +132,7 @@ namespace LOFAR os << endl << indent << "Phase shift observed data: " << boolalpha << itsShiftFlag << noboolalpha; - if(itsShiftFlag) - { + if(itsShiftFlag) { Indent id; os << endl << indent << "Direction: " << itsDirectionASCII; } @@ -180,6 +184,9 @@ namespace LOFAR ps.replace(prefix + "CellSize.Time", toString(itsCellSize.time)); ps.replace(prefix + "CellChunkSize", toString(itsCellChunkSize)); ps.replace(prefix + "PropagateSolutions", toString(itsPropagateFlag)); + ps.replace(prefix + "Log.Name", itsLogName); + ps.replace(prefix + "Log.Level", itsLogLevel); + if(itsUVFlag) { ps.replace(prefix + "UVRange", "[" + toString(itsUVRange.first) @@ -240,6 +247,9 @@ namespace LOFAR itsCellSize.time = pss.getUint32("CellSize.Time"); itsCellChunkSize = pss.getUint32("CellChunkSize"); itsPropagateFlag = pss.getBool("PropagateSolutions", false); + itsLogName = pss.getString("Log.Name", "solver_log"); + itsLogLevel = pss.getString("Log.Level", "NONE"); + setUVRange(pss); itsRejectFlag = pss.getBool("OutlierRejection.Enable", false); diff --git a/CEP/Calibration/BBSKernel/include/BBSKernel/Estimate.h b/CEP/Calibration/BBSKernel/include/BBSKernel/Estimate.h index 8e45203dbef138a2b83c57ee9aaaf6433562c99f..13945da725a277e15d21a7219c2bf2faec95aa6e 100644 --- a/CEP/Calibration/BBSKernel/include/BBSKernel/Estimate.h +++ b/CEP/Calibration/BBSKernel/include/BBSKernel/Estimate.h @@ -35,6 +35,8 @@ //# For the definition of SolverOptions... #include <BBSKernel/Solver.h> +#include <ParmDB/ParmDBLog.h> + namespace LOFAR { namespace BBS @@ -134,7 +136,8 @@ private: // the visibilities simulated using \p model. An independent solution is // computed for each cell in \p grid. Only those baselines and correlations // selected in \p baselines and \p correlations will be used. -void estimate(const VisBuffer::Ptr &buffer, +void estimate(ParmDBLog &log, + const VisBuffer::Ptr &buffer, const BaselineMask &baselines, const CorrelationMask &correlations, const MeasurementExpr::Ptr &model, diff --git a/CEP/Calibration/BBSKernel/include/BBSKernel/Measurement.h b/CEP/Calibration/BBSKernel/include/BBSKernel/Measurement.h index 1d9e28ca7e4faf2bdaafe5a9e6a3184ca2ce9ac1..54a29395acd539f49d8bbb3a45610dcb7d57e180 100644 --- a/CEP/Calibration/BBSKernel/include/BBSKernel/Measurement.h +++ b/CEP/Calibration/BBSKernel/include/BBSKernel/Measurement.h @@ -60,6 +60,8 @@ public: bool writeCovariance = false, bool writeFlags = true, flag_t flagMask = ~flag_t(0)) = 0; + virtual void writeHistory(const ParameterSet &parset) const = 0; + // Apply the given filter to the baselines contained in the Measurement and // return the result as a (boolean) baseline mask. virtual BaselineMask asMask(const string &filter) const = 0; @@ -70,8 +72,6 @@ public: Instrument::ConstPtr instrument() const; const VisDimensions &dimensions() const; - virtual void writeHistory(ParameterSet &parset) const = 0; - // Convenience functions that delegate to VisDimensions (refer to the // documentation of VisDimensions for their documentation). // @{ diff --git a/CEP/Calibration/BBSKernel/include/BBSKernel/MeasurementAIPS.h b/CEP/Calibration/BBSKernel/include/BBSKernel/MeasurementAIPS.h index a90ee8135df15a7164e98fcbab921f40664e4a32..e8278ac7d9c9e69be0aa666acd169304ff23c0e8 100644 --- a/CEP/Calibration/BBSKernel/include/BBSKernel/MeasurementAIPS.h +++ b/CEP/Calibration/BBSKernel/include/BBSKernel/MeasurementAIPS.h @@ -65,10 +65,10 @@ public: const string &column = "CORRECTED_DATA", bool writeCovariance = false, bool writeFlags = true, flag_t flagMask = ~flag_t(0)); + virtual void writeHistory(const ParameterSet &parset) const; + virtual BaselineMask asMask(const string &filter) const; - - //void writeHistory(ParameterSet &parset) const; - + // @} private: @@ -109,8 +109,6 @@ private: VisDimensions getDimensionsImpl(const casa::Table &tab_selection, const casa::Slicer &slicer) const; - void writeHistory(ParameterSet &parset) const; - casa::MeasurementSet itsMS; casa::Table itsMainTableView; diff --git a/CEP/Calibration/BBSKernel/src/Estimate.cc b/CEP/Calibration/BBSKernel/src/Estimate.cc index 168f4b2ed82781597a83ec42d46843bfd6e4ed0a..7ccccc6b83e8bc3946283d5e4bdc840c86e9deec 100644 --- a/CEP/Calibration/BBSKernel/src/Estimate.cc +++ b/CEP/Calibration/BBSKernel/src/Estimate.cc @@ -90,6 +90,9 @@ namespace // State kept for a single cell in the solution grid. struct Cell { + // Flag that indicates if processing has completed. + bool done; + // LSQ solver and current estimates for the coefficients. casa::LSQFit solver; vector<double> coeff; @@ -200,13 +203,29 @@ namespace // \pre The range starting at \p cell should contain exactly one Cell // instance for each cell in the range [\p start, \p end]. template <typename T> - IterationStatus iterate(const Location &start, const Location &end, - const ParmGroup &solvables, const EstimateOptions &options, T cell); + IterationStatus iterate(ParmDBLog &log, const Grid &grid, + const Location &start, const Location &end, const ParmGroup &solvables, + const EstimateOptions &options, T cell); + + // Decode casa::LSQFit ready codes and update the status counts. + void updateIterationStatus(const Cell &cell, IterationStatus &status); + + // Write a map that maps parameter names to positions in the solution vector + // to the solver log. This is necessary to be able to correctly interpret + // the solution vectors in the log afterwards. + void logCoefficientIndex(ParmDBLog &log, const ParmGroup &solvables); + + // Write the configuration of the least squares solver to the solver log. + void logLSQOptions(ParmDBLog &log, const EstimateOptions &options); + + // Log solver statistics for the given cell. + void logCellStats(ParmDBLog &log, const Box &box, Cell &cell); // Function that does the actual iteration over chunk of cells and can be // specialised using \p T_CELL_PROCESSOR. template <typename T_CELL_PROCESSOR> - void estimateImpl(const VisBuffer::Ptr &buffer, + void estimateImpl(ParmDBLog &log, + const VisBuffer::Ptr &buffer, const BaselineMask &baselines, const CorrelationMask &correlations, const MeasurementExpr::Ptr &model, @@ -215,7 +234,8 @@ namespace const EstimateOptions &options); } //# anonymous namespace -void estimate(const VisBuffer::Ptr &buffer, +void estimate(ParmDBLog &log, + const VisBuffer::Ptr &buffer, const BaselineMask &baselines, const CorrelationMask &correlations, const MeasurementExpr::Ptr &model, @@ -230,18 +250,18 @@ void estimate(const VisBuffer::Ptr &buffer, { case EstimateOptions::AMPLITUDE: estimateImpl<CellProcessorReal<SampleModifierAmplitude, - WeightModifierL1> >(buffer, baselines, correlations, - model, grid, solvables, options); + WeightModifierL1> >(log, buffer, baselines, + correlations, model, grid, solvables, options); break; case EstimateOptions::PHASE: estimateImpl<CellProcessorComplex<SampleModifierPhase, - WeightModifierL1> >(buffer, baselines, correlations, - model, grid, solvables, options); + WeightModifierL1> >(log, buffer, baselines, + correlations, model, grid, solvables, options); break; case EstimateOptions::COMPLEX: estimateImpl<CellProcessorComplex<SampleModifierComplex, - WeightModifierL1> >(buffer, baselines, correlations, - model, grid, solvables, options); + WeightModifierL1> >(log, buffer, baselines, + correlations, model, grid, solvables, options); break; default: THROW(BBSKernelException, "Invalid mode selected."); @@ -253,18 +273,18 @@ void estimate(const VisBuffer::Ptr &buffer, { case EstimateOptions::AMPLITUDE: estimateImpl<CellProcessorReal<SampleModifierAmplitude, - WeightModifierL2> >(buffer, baselines, correlations, - model, grid, solvables, options); + WeightModifierL2> >(log, buffer, baselines, + correlations, model, grid, solvables, options); break; case EstimateOptions::PHASE: estimateImpl<CellProcessorComplex<SampleModifierPhase, - WeightModifierL2> >(buffer, baselines, correlations, - model, grid, solvables, options); + WeightModifierL2> >(log, buffer, baselines, + correlations, model, grid, solvables, options); break; case EstimateOptions::COMPLEX: estimateImpl<CellProcessorComplex<SampleModifierComplex, - WeightModifierL2> >(buffer, baselines, correlations, - model, grid, solvables, options); + WeightModifierL2> >(log, buffer, baselines, + correlations, model, grid, solvables, options); break; default: THROW(BBSKernelException, "Invalid mode selected."); @@ -438,7 +458,8 @@ const string &EstimateOptions::asString(Algorithm in) namespace { template <typename T_CELL_PROCESSOR> - void estimateImpl(const VisBuffer::Ptr &buffer, + void estimateImpl(ParmDBLog &log, + const VisBuffer::Ptr &buffer, const BaselineMask &baselines, const CorrelationMask &correlations, const MeasurementExpr::Ptr &model, @@ -489,6 +510,10 @@ namespace // Assign solution grid to solvables. ParmManager::instance().setGrid(grid, solvables); + // Log information that holds for all chunks. + logCoefficientIndex(log, solvables); + logLSQOptions(log, options); + // --------------------------------------------------------------------- // Process each chunk of cells in a loop. // --------------------------------------------------------------------- @@ -578,8 +603,8 @@ namespace // Perform a single iteration. timerIterate.start(); - status = iterate(chunkStart, chunkEnd, solvables, options, - cells.begin()); + status = iterate(log, grid, chunkStart, chunkEnd, solvables, + options, cells.begin()); timerIterate.stop(); // Notify model that solvables have changed. @@ -658,31 +683,28 @@ namespace } template <typename T> - IterationStatus iterate(const Location &start, const Location &end, - const ParmGroup &solvables, const EstimateOptions &options, T cell) + IterationStatus iterate(ParmDBLog &log, const Grid &grid, + const Location &start, const Location &end, const ParmGroup &solvables, + const EstimateOptions &options, T cell) { -// LOG_DEBUG_STR("================================================================================" << endl); - IterationStatus status = {0, 0, 0, 0, 0}; for(CellIterator it(start, end); !it.atEnd(); ++it, ++cell) { + // If processing on the cell is already done, only update the status + // counts and continue to the next cell. + if(cell->done) + { + updateIterationStatus(*cell, status); + continue; + } + // Compute RMS. if(cell->count > 0) { cell->rms = sqrt(cell->rms / cell->count); } -// if(!cell->done) -// { -// LOG_DEBUG_STR("cell: (" << it->first << "," << it->second -// << ") rms: " << cell->rms << " count: " << cell->count -// << " flag: " << cell->flag << " outliers: " << cell->outliers -// << " threshold: " << cell->threshold << " (" -// << cell->thresholdIdx << ") epsilon: " << cell->epsilon << " (" -// << cell->epsilonIdx << ")"); -// } - - // Turn outlier detection of by default. May be enabled later on. + // Turn outlier detection off by default. May be enabled later on. cell->flag = false; // Perform a single iteration if the cell has not yet converged or @@ -747,54 +769,137 @@ namespace ++cell->thresholdIdx; } - // Decode and record the solver status. - switch(cell->solver.isReady()) + // Log solution statistics. + if(!options.robust() + && (options.algorithm() == EstimateOptions::L2)) { - case casa::LSQFit::NONREADY: - ++status.nActive; - break; - - case casa::LSQFit::SOLINCREMENT: - case casa::LSQFit::DERIVLEVEL: - ++status.nConverged; - break; - - case casa::LSQFit::MAXITER: - ++status.nStopped; - break; - - case casa::LSQFit::NOREDUCTION: - ++status.nNoReduction; - break; - - case casa::LSQFit::SINGULAR: - ++status.nSingular; - break; - - default: - // This assert triggers if an casa::LSQFit ready - // code is encountered that is not covered above. - // The most likely cause is that the - // casa::LSQFit::ReadyCode enumeration has changes - // in which case the code above needs to be changed - // accordingly. - ASSERT(false); - break; + logCellStats(log, grid.getCell(*it), *cell); } - // If not yet converged or failed, reset state for the next - // iteration. - if(!cell->solver.isReady()) + if(cell->solver.isReady()) { + cell->done = true; + } + else + { + // If not yet converged or failed, reset state for the next + // iteration. cell->rms = 0.0; cell->count = 0; cell->outliers = 0; } + + updateIterationStatus(*cell, status); } return status; } + void updateIterationStatus(const Cell &cell, IterationStatus &status) + { + // casa::LSQFit::isReady() is incorrectly labelled non-const. + casa::LSQFit &solver = const_cast<casa::LSQFit&>(cell.solver); + + // Decode and record the solver status. + switch(solver.isReady()) + { + case casa::LSQFit::NONREADY: + ++status.nActive; + break; + + case casa::LSQFit::SOLINCREMENT: + case casa::LSQFit::DERIVLEVEL: + ++status.nConverged; + break; + + case casa::LSQFit::MAXITER: + ++status.nStopped; + break; + + case casa::LSQFit::NOREDUCTION: + ++status.nNoReduction; + break; + + case casa::LSQFit::SINGULAR: + ++status.nSingular; + break; + + default: + // This assert triggers if an casa::LSQFit ready + // code is encountered that is not covered above. + // The most likely cause is that the + // casa::LSQFit::ReadyCode enumeration has changes + // in which case the code above needs to be changed + // accordingly. + ASSERT(false); + break; + } + } + + void logCoefficientIndex(ParmDBLog &log, const ParmGroup &solvables) + { + CoeffIndex index; + for(ParmGroup::const_iterator it = solvables.begin(), + end = solvables.end(); it != end; ++it) + { + ParmProxy::Ptr parm = ParmManager::instance().get(*it); + index.insert(parm->getName(), parm->getCoeffCount()); + } + + log.addParmKeywords(index); + } + + void logLSQOptions(ParmDBLog &log, const EstimateOptions &options) + { + log.addSolverKeywords(options.lsqOptions()); + } + + void logCellStats(ParmDBLog &log, const Box &box, Cell &cell) + { + const ParmDBLoglevel level = log.getLoggingLevel(); + if(level.is(ParmDBLoglevel::NONE)) + { + return; + } + + // Get some statistics from the solver. Note that the chi squared is + // valid for the _previous_ iteration. The solver cannot compute the chi + // squared directly after an iteration, because it needs the new + // condition equations for that and these are computed by the kernel. + casa::uInt rank, nun, np, ncon, ner, *piv; + casa::Double *nEq, *known, *constr, *er, *sEq, *sol, prec, nonlin; + cell.solver.debugIt(nun, np, ncon, ner, rank, nEq, known, constr, er, + piv, sEq, sol, prec, nonlin); + + if(level.is(ParmDBLoglevel::PERITERATION) + || (!cell.solver.isReady() + && level.is(ParmDBLoglevel::PERITERATION_CORRMATRIX)) + || (cell.solver.isReady() && level.is(ParmDBLoglevel::PERSOLUTION))) + { + log.add(box.lower().first, box.upper().first, box.lower().second, + box.upper().second, cell.solver.nIterations(), 0, + cell.solver.isReady(), rank, cell.solver.getDeficiency(), + cell.solver.getChi(), nonlin, cell.coeff, + cell.solver.readyText()); + } + else if(cell.solver.isReady() + && (level.is(ParmDBLoglevel::PERSOLUTION_CORRMATRIX) + || level.is(ParmDBLoglevel::PERITERATION_CORRMATRIX))) + { + casa::Array<double> corrMatrix(casa::IPosition(1, + cell.solver.nUnknowns() * cell.solver.nUnknowns())); + + bool status = cell.solver.getCovariance(corrMatrix.data()); + ASSERT(status); + + log.add(box.lower().first, box.upper().first, box.lower().second, + box.upper().second, cell.solver.nIterations(), 0, + cell.solver.isReady(), rank, cell.solver.getDeficiency(), + cell.solver.getChi(), nonlin, cell.coeff, + cell.solver.readyText(), corrMatrix); + } + } + template <typename T> void initCells(const Location &start, const Location &end, const ParmGroup &solvables, size_t nCoeff, @@ -802,6 +907,9 @@ namespace { for(CellIterator it(start, end); !it.atEnd(); ++it, ++cell) { + // Processing has not completed yet. + cell->done = false; + // Initalize LSQ solver. cell->solver = casa::LSQFit(static_cast<casa::uInt>(nCoeff)); configLSQSolver(cell->solver, options.lsqOptions()); diff --git a/CEP/Calibration/BBSKernel/src/MeasurementAIPS.cc b/CEP/Calibration/BBSKernel/src/MeasurementAIPS.cc index 11d0a79ecf9db58ae4cdc1e030d18c741006a98c..f7a13365b56c60ba0ada36adb7ed8a3e0eef1eaf 100644 --- a/CEP/Calibration/BBSKernel/src/MeasurementAIPS.cc +++ b/CEP/Calibration/BBSKernel/src/MeasurementAIPS.cc @@ -120,54 +120,6 @@ VisDimensions MeasurementAIPS::dimensions(const VisSelection &selection) getCellSlicer(selection)); } - -void MeasurementAIPS::writeHistory(ParameterSet &parset) const -{ - Table histtab(itsMS.keywordSet().asTable("HISTORY")); - histtab.reopenRW(); - ScalarColumn<double> time (histtab, "TIME"); - ScalarColumn<int> obsId (histtab, "OBSERVATION_ID"); - ScalarColumn<String> message (histtab, "MESSAGE"); - ScalarColumn<String> application (histtab, "APPLICATION"); - ScalarColumn<String> priority (histtab, "PRIORITY"); - ScalarColumn<String> origin (histtab, "ORIGIN"); - ArrayColumn<String> parms (histtab, "APP_PARAMS"); - ArrayColumn<String> cli (histtab, "CLI_COMMAND"); - // Put all parset entries in a Vector<String>. - // Some WSRT MSs have a FixedShape APP_PARAMS and CLI_COMMAND column. - // For them, put all params in a single vector element (with newlines). - bool fixedShaped = - (parms.columnDesc().options() & ColumnDesc::FixedShape) != 0; - Vector<String> appvec; - Vector<String> clivec; - if (fixedShaped) { - appvec.resize(1); - clivec.resize(1); - ostringstream ostr; - parset.writeStream (ostr); - appvec[0] = ostr.str(); - } else { - appvec.resize (parset.size()); - Array<String>::contiter viter = appvec.cbegin(); - for (ParameterSet::const_iterator iter = parset.begin(); - iter != parset.end(); ++iter, ++viter) { - *viter = iter->first + '=' + iter->second.get(); - } - } - - uint rownr = histtab.nrow(); - histtab.addRow(); - time.put (rownr, Time().modifiedJulianDay()*24.*3600.); - obsId.put (rownr, 0); - message.put (rownr, "parameters"); - application.put (rownr, "BBS"); - priority.put (rownr, "NORMAL"); - origin.put (rownr, Version::getInfo<BBSKernelVersion>("BBS", "other")); - parms.put (rownr, appvec); - cli.put (rownr, clivec); -} - - VisBuffer::Ptr MeasurementAIPS::read(const VisSelection &selection, const string &column) const { @@ -507,7 +459,6 @@ void MeasurementAIPS::write(VisBuffer::Ptr buffer, c_covariance.putSlice(i, slicerCov, covariance); } - } writeTimer.stop(); @@ -529,6 +480,57 @@ void MeasurementAIPS::write(VisBuffer::Ptr buffer, LOG_DEBUG_STR("Write time: " << writeTimer); } +void MeasurementAIPS::writeHistory(const ParameterSet &parset) const +{ + Table histtab = getSubTable("HISTORY"); + histtab.reopenRW(); + + ScalarColumn<double> time (histtab, "TIME"); + ScalarColumn<int> obsId (histtab, "OBSERVATION_ID"); + ScalarColumn<String> message (histtab, "MESSAGE"); + ScalarColumn<String> application(histtab, "APPLICATION"); + ScalarColumn<String> priority (histtab, "PRIORITY"); + ScalarColumn<String> origin (histtab, "ORIGIN"); + ArrayColumn<String> parms (histtab, "APP_PARAMS"); + ArrayColumn<String> cli (histtab, "CLI_COMMAND"); + + // Put all parset entries in a Vector<String>. + Vector<String> appvec; + Vector<String> clivec; + if(parms.columnDesc().isFixedShape()) + { + // Some WSRT MSs have a FixedShape APP_PARAMS and CLI_COMMAND column. + // For them, put all params in a single vector element (with newlines). + appvec.resize(1); + clivec.resize(1); + + ostringstream ostr; + parset.writeStream(ostr); + appvec[0] = ostr.str(); + } + else + { + appvec.resize (parset.size()); + Array<String>::contiter viter = appvec.cbegin(); + for(ParameterSet::const_iterator iter = parset.begin(); + iter != parset.end(); ++iter, ++viter) + { + *viter = iter->first + '=' + iter->second.get(); + } + } + + uint rownr = histtab.nrow(); + histtab.addRow(); + time.put (rownr, Time().modifiedJulianDay() * 24.0 * 3600.0); + obsId.put (rownr, itsIdObservation); + message.put (rownr, "parameters"); + application.put(rownr, "BBS"); + priority.put (rownr, "NORMAL"); + origin.put (rownr, Version::getInfo<BBSKernelVersion>("BBS", "other")); + parms.put (rownr, appvec); + cli.put (rownr, clivec); +} + BaselineMask MeasurementAIPS::asMask(const string &filter) const { // Find all unique baselines.