From 206a9fc110835c1ce11af29d164926df86522188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Offringa?= <offringa@astron.nl> Date: Sat, 17 Mar 2012 22:40:20 +0000 Subject: [PATCH] Task #1892: added variance normalization to strategy files, made the action thread safe --- .../actions/normalizevarianceaction.h | 23 ++++- .../strategy/control/strategyreader.h | 1 + .../strategy/control/strategywriter.h | 1 + .../AOFlagger/strategy/control/types.h | 3 +- .../actions/normalizevarianceaction.cpp | 83 ++++++++++++------- .../src/strategy/control/strategyreader.cpp | 20 +++-- .../src/strategy/control/strategywriter.cpp | 12 ++- 7 files changed, 103 insertions(+), 40 deletions(-) diff --git a/CEP/DP3/AOFlagger/include/AOFlagger/strategy/actions/normalizevarianceaction.h b/CEP/DP3/AOFlagger/include/AOFlagger/strategy/actions/normalizevarianceaction.h index 25c8f1bed93..63976ae26a6 100644 --- a/CEP/DP3/AOFlagger/include/AOFlagger/strategy/actions/normalizevarianceaction.h +++ b/CEP/DP3/AOFlagger/include/AOFlagger/strategy/actions/normalizevarianceaction.h @@ -22,6 +22,8 @@ #include <map> +#include <boost/thread/mutex.hpp> + #include <AOFlagger/strategy/actions/action.h> #include <AOFlagger/strategy/control/artifactset.h> @@ -34,23 +36,36 @@ namespace rfiStrategy { class NormalizeVarianceAction : public Action { public: NormalizeVarianceAction() : - _medianFilterSizeInS(60.0*15.0) - { - } - virtual ~NormalizeVarianceAction() + _medianFilterSizeInS(60.0*15.0), _isInitialized(false) { } + virtual ~NormalizeVarianceAction(); virtual std::string Description() { return "Normalize variance over time"; } virtual void Perform(ArtifactSet &artifacts, ProgressListener &progress); + virtual void Initialize() + { + clean(); + } + virtual void Finish() + { + clean(); + } virtual ActionType Type() const { return NormalizeVarianceActionType; } + double MedianFilterSizeInS() const { return _medianFilterSizeInS; } + void SetMedianFilterSizeInS(double filterSize) { _medianFilterSizeInS = filterSize; } private: double _medianFilterSizeInS; + boost::mutex _mutex; + bool _isInitialized; + std::map<double, double> _stddevs; + void initializeStdDevs(ArtifactSet &artifacts); + void clean(); void correctData(std::vector<Image2DPtr> &data, size_t timeStep, double stddev); void correctDataUpTo(std::vector<Image2DPtr> &data, size_t &dataTimeIndex, double time, const std::vector<double> &observationTimes, double stddev); }; diff --git a/CEP/DP3/AOFlagger/include/AOFlagger/strategy/control/strategyreader.h b/CEP/DP3/AOFlagger/include/AOFlagger/strategy/control/strategyreader.h index 57165808e52..f40fcdb72ed 100644 --- a/CEP/DP3/AOFlagger/include/AOFlagger/strategy/control/strategyreader.h +++ b/CEP/DP3/AOFlagger/include/AOFlagger/strategy/control/strategyreader.h @@ -77,6 +77,7 @@ class StrategyReader { class Action *parseFringeStopAction(xmlNode *node); class Action *parseImagerAction(xmlNode *node); class Action *parseIterationBlock(xmlNode *node); + class Action *parseNormalizeVarianceAction(xmlNode *node); class Action *parsePlotAction(xmlNode *node); class Action *parseQuickCalibrateAction(xmlNode *node); class Action *parseRawAppenderAction(xmlNode *node); diff --git a/CEP/DP3/AOFlagger/include/AOFlagger/strategy/control/strategywriter.h b/CEP/DP3/AOFlagger/include/AOFlagger/strategy/control/strategywriter.h index 2c09c84dbf8..7586f279643 100644 --- a/CEP/DP3/AOFlagger/include/AOFlagger/strategy/control/strategywriter.h +++ b/CEP/DP3/AOFlagger/include/AOFlagger/strategy/control/strategywriter.h @@ -92,6 +92,7 @@ namespace rfiStrategy { void writeFringeStopAction(const class FringeStopAction &action); void writeImagerAction(const class ImagerAction &action); void writeIterationBlock(const class IterationBlock &action); + void writeNormalizeVarianceAction(const class NormalizeVarianceAction &action); void writePlotAction(const class PlotAction &action); void writeQuickCalibrateAction(const class QuickCalibrateAction &action); void writeRawAppenderAction(const class RawAppenderAction &action); diff --git a/CEP/DP3/AOFlagger/include/AOFlagger/strategy/control/types.h b/CEP/DP3/AOFlagger/include/AOFlagger/strategy/control/types.h index 7e3747c54ab..3ed997f4807 100644 --- a/CEP/DP3/AOFlagger/include/AOFlagger/strategy/control/types.h +++ b/CEP/DP3/AOFlagger/include/AOFlagger/strategy/control/types.h @@ -83,7 +83,8 @@ class Observatorium; // 3.4 : Renamed ThresholdAction to SumThresholdAction // 3.5 : Added the AbsThresholdAction // 3.6 : Added the DirectionProfileAction and the EigenValueVerticalAction. -#define STRATEGY_FILE_FORMAT_VERSION 3.6 +// 3.7 : Added the NormalizeVarianceAction +#define STRATEGY_FILE_FORMAT_VERSION 3.7 // The earliest format version which can be read by this version of the software #define STRATEGY_FILE_FORMAT_VERSION_REQUIRED 3.4 diff --git a/CEP/DP3/AOFlagger/src/strategy/actions/normalizevarianceaction.cpp b/CEP/DP3/AOFlagger/src/strategy/actions/normalizevarianceaction.cpp index 06d4b38c8b3..022346b4e6e 100644 --- a/CEP/DP3/AOFlagger/src/strategy/actions/normalizevarianceaction.cpp +++ b/CEP/DP3/AOFlagger/src/strategy/actions/normalizevarianceaction.cpp @@ -33,20 +33,58 @@ #include <AOFlagger/quality/statisticsderivator.h> namespace rfiStrategy { + +NormalizeVarianceAction::~NormalizeVarianceAction() +{ +} + +void NormalizeVarianceAction::initializeStdDevs(ArtifactSet &artifacts) +{ + // The thread that calls this function first will initialize the + // std dev. When a new measurement set is read, Initialize or Finalize + // will be called, causing a clean(). + boost::mutex::scoped_lock lock(_mutex); + if(!_isInitialized) + { + if(!artifacts.HasImageSet()) + throw std::runtime_error("Normalize variance called without image set"); + ImageSet *imageSet = artifacts.ImageSet(); + MSImageSet *msImageSet = dynamic_cast<MSImageSet*>(imageSet); + if(msImageSet == 0) + throw std::runtime_error("Normalize variance actions needs measurement set"); + std::string filename = msImageSet->Reader()->Set().Location(); + QualityTablesFormatter qtables(filename); + StatisticsCollection statCollection(msImageSet->Reader()->Set().GetPolarizationCount()); + statCollection.LoadTimeStatisticsOnly(qtables); + statCollection.IntegrateTimeToOneChannel(); + _isInitialized = true; + + // Calculate all stddevs + const std::map<double, DefaultStatistics> &statMap = statCollection.TimeStatistics(); + _stddevs.clear(); + std::map<double, double>::iterator pos = _stddevs.begin(); + for(std::map<double, DefaultStatistics>::const_iterator i = statMap.begin(); + i != statMap.end(); ++i) + { + double stddev = StatisticsDerivator::GetStatisticAmplitude( + QualityTablesFormatter::DStandardDeviationStatistic, + i->second.ToSinglePolarization(), 0); + pos = _stddevs.insert(pos, std::pair<double, double>(i->first, stddev)); + } + } +} + +void NormalizeVarianceAction::clean() +{ + boost::mutex::scoped_lock lock(_mutex); + _isInitialized = false; + _stddevs.clear(); // frees a bit of memory. +} + void NormalizeVarianceAction::Perform(ArtifactSet &artifacts, ProgressListener &progress) { - if(!artifacts.HasImageSet()) - throw std::runtime_error("Normalize variance called without image set"); - ImageSet *imageSet = artifacts.ImageSet(); - MSImageSet *msImageSet = dynamic_cast<MSImageSet*>(imageSet); - if(msImageSet == 0) - throw std::runtime_error("Normalize variance actions needs measurement set"); - std::string filename = msImageSet->Reader()->Set().Location(); - QualityTablesFormatter qtables(filename); - StatisticsCollection statCollection(msImageSet->Reader()->Set().GetPolarizationCount()); - statCollection.LoadTimeStatisticsOnly(qtables); - statCollection.IntegrateTimeToOneChannel(); + initializeStdDevs(artifacts); TimeFrequencyData &original = artifacts.OriginalData(); const std::vector<double> &observationTimes = artifacts.MetaData()->ObservationTimes(); @@ -57,22 +95,10 @@ void NormalizeVarianceAction::Perform(ArtifactSet &artifacts, ProgressListener & for(unsigned img=0;img<original.ImageCount();++img) data.push_back(Image2D::CreateCopy(original.GetImage(img))); - // Calculate all stddevs - const std::map<double, DefaultStatistics> &statMap = statCollection.TimeStatistics(); - std::map<double, double> stddevs; - for(std::map<double, DefaultStatistics>::const_iterator i = statMap.begin(); - i != statMap.end(); ++i) - { - double stddev = StatisticsDerivator::GetStatisticAmplitude( - QualityTablesFormatter::DStandardDeviationStatistic, - i->second.ToSinglePolarization(), 0); - stddevs.insert(std::pair<double, double>(i->first, stddev)); - } - // Add the first half of the window const double halfWindowTime = _medianFilterSizeInS * 0.5; MedianWindow<double> window; - std::map<double, double>::const_iterator windowRightSideIterator = stddevs.begin(); + std::map<double, double>::const_iterator windowRightSideIterator = _stddevs.begin(); const double startTime = windowRightSideIterator->first; do { window.Add(windowRightSideIterator->second); @@ -81,7 +107,7 @@ void NormalizeVarianceAction::Perform(ArtifactSet &artifacts, ProgressListener & // Add the second half, and start correcting the data size_t dataTimeIndex = 0; - while(windowRightSideIterator != stddevs.end() && + while(windowRightSideIterator != _stddevs.end() && windowRightSideIterator->first - startTime < _medianFilterSizeInS) { correctDataUpTo(data, dataTimeIndex, windowRightSideIterator->first, observationTimes, window.Median()); @@ -90,9 +116,9 @@ void NormalizeVarianceAction::Perform(ArtifactSet &artifacts, ProgressListener & } // Slide window until right side hits end - std::map<double, double>::const_iterator windowLeftSideIterator = stddevs.begin(); - const double endTime = stddevs.rbegin()->first; - while(windowRightSideIterator != stddevs.end() && windowRightSideIterator->first < endTime) + std::map<double, double>::const_iterator windowLeftSideIterator = _stddevs.begin(); + const double endTime = _stddevs.rbegin()->first; + while(windowRightSideIterator != _stddevs.end() && windowRightSideIterator->first < endTime) { correctDataUpTo(data, dataTimeIndex, windowRightSideIterator->first, observationTimes, window.Median()); @@ -136,7 +162,6 @@ void NormalizeVarianceAction::correctDataUpTo(std::vector<Image2DPtr> &data, siz void NormalizeVarianceAction::correctData(std::vector<Image2DPtr> &data, size_t timeStep, double stddev) { - AOLogger::Debug << "Scaling timestep " << timeStep << " with " << stddev << '\n'; num_t oneOverStddev = 1.0 / stddev; for(std::vector<Image2DPtr>::iterator i=data.begin();i!=data.end();++i) diff --git a/CEP/DP3/AOFlagger/src/strategy/control/strategyreader.cpp b/CEP/DP3/AOFlagger/src/strategy/control/strategyreader.cpp index ca82c6f80f4..cf4441cf48f 100644 --- a/CEP/DP3/AOFlagger/src/strategy/control/strategyreader.cpp +++ b/CEP/DP3/AOFlagger/src/strategy/control/strategyreader.cpp @@ -43,6 +43,7 @@ #include <AOFlagger/strategy/actions/fringestopaction.h> #include <AOFlagger/strategy/actions/imageraction.h> #include <AOFlagger/strategy/actions/iterationaction.h> +#include <AOFlagger/strategy/actions/normalizevarianceaction.h> #include <AOFlagger/strategy/actions/plotaction.h> #include <AOFlagger/strategy/actions/quickcalibrateaction.h> #include <AOFlagger/strategy/actions/rawappenderaction.h> @@ -280,6 +281,8 @@ Action *StrategyReader::parseAction(xmlNode *node) newAction = parseImagerAction(node); else if(typeStr == "IterationBlock") newAction = parseIterationBlock(node); + else if(typeStr == "NormalizeVarianceAction") + newAction = parseNormalizeVarianceAction(node); else if(typeStr == "PlotAction") newAction = parsePlotAction(node); else if(typeStr == "QuickCalibrateAction") @@ -533,7 +536,7 @@ Action *StrategyReader::parseFourierTransformAction(xmlNode *) return newAction; } -class Action *StrategyReader::parseFrequencyConvolutionAction(xmlNode *node) +Action *StrategyReader::parseFrequencyConvolutionAction(xmlNode *node) { FrequencyConvolutionAction *newAction = new FrequencyConvolutionAction(); newAction->SetConvolutionSize(getInt(node, "convolution-size")); @@ -541,14 +544,14 @@ class Action *StrategyReader::parseFrequencyConvolutionAction(xmlNode *node) return newAction; } -class Action *StrategyReader::parseFrequencySelectionAction(xmlNode *node) +Action *StrategyReader::parseFrequencySelectionAction(xmlNode *node) { FrequencySelectionAction *newAction = new FrequencySelectionAction(); newAction->SetThreshold(getDouble(node, "threshold")); return newAction; } -class Action *StrategyReader::parseFringeStopAction(xmlNode *node) +Action *StrategyReader::parseFringeStopAction(xmlNode *node) { FringeStopAction *newAction = new FringeStopAction(); newAction->SetFitChannelsIndividually(getBool(node, "fit-channels-individually")); @@ -559,13 +562,13 @@ class Action *StrategyReader::parseFringeStopAction(xmlNode *node) return newAction; } -class Action *StrategyReader::parseImagerAction(xmlNode *) +Action *StrategyReader::parseImagerAction(xmlNode *) { ImagerAction *newAction = new ImagerAction(); return newAction; } -class Action *StrategyReader::parseIterationBlock(xmlNode *node) +Action *StrategyReader::parseIterationBlock(xmlNode *node) { IterationBlock *newAction = new IterationBlock(); newAction->SetIterationCount(getInt(node, "iteration-count")); @@ -574,6 +577,13 @@ class Action *StrategyReader::parseIterationBlock(xmlNode *node) return newAction; } +Action *StrategyReader::parseNormalizeVarianceAction(xmlNode *node) +{ + NormalizeVarianceAction *newAction = new NormalizeVarianceAction(); + newAction->SetMedianFilterSizeInS(getDouble(node, "median-filter-size-in-s")); + return newAction; +} + Action *StrategyReader::parseSetFlaggingAction(xmlNode *node) { SetFlaggingAction *newAction = new SetFlaggingAction(); diff --git a/CEP/DP3/AOFlagger/src/strategy/control/strategywriter.cpp b/CEP/DP3/AOFlagger/src/strategy/control/strategywriter.cpp index 91db62daf33..3405d3cc65d 100644 --- a/CEP/DP3/AOFlagger/src/strategy/control/strategywriter.cpp +++ b/CEP/DP3/AOFlagger/src/strategy/control/strategywriter.cpp @@ -40,6 +40,7 @@ #include <AOFlagger/strategy/actions/fringestopaction.h> #include <AOFlagger/strategy/actions/imageraction.h> #include <AOFlagger/strategy/actions/iterationaction.h> +#include <AOFlagger/strategy/actions/normalizevarianceaction.h> #include <AOFlagger/strategy/actions/plotaction.h> #include <AOFlagger/strategy/actions/quickcalibrateaction.h> #include <AOFlagger/strategy/actions/rawappenderaction.h> @@ -161,6 +162,9 @@ namespace rfiStrategy { case IterationBlockType: writeIterationBlock(static_cast<const IterationBlock&>(action)); break; + case NormalizeVarianceActionType: + writeNormalizeVarianceAction(static_cast<const NormalizeVarianceAction&>(action)); + break; case PlotActionType: writePlotAction(static_cast<const PlotAction&>(action)); break; @@ -399,7 +403,13 @@ namespace rfiStrategy { writeContainerItems(action); } - void StrategyWriter::writePlotAction(const class PlotAction &action) + void StrategyWriter::writeNormalizeVarianceAction(const NormalizeVarianceAction &action) + { + Attribute("type", "NormalizeVarianceAction"); + Write<double>("median-filter-size-in-s", action.MedianFilterSizeInS()); + } + + void StrategyWriter::writePlotAction(const PlotAction &action) { Attribute("type", "PlotAction"); Write<int>("plot-kind", action.PlotKind()); -- GitLab