diff --git a/.gitattributes b/.gitattributes
index b23b7e4e58a711f48671ad67651ec82328542f61..49f9db19d3ad072b698f95715ebf367f614e4ee6 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1994,8 +1994,14 @@ RTCP/CNProc/src/FIR_OriginalCepPPFWeights.h -text
 RTCP/CNProc/src/FIR_OriginalStationPPFWeights.h -text
 RTCP/CNProc/src/FilterBank.cc -text
 RTCP/CNProc/src/FilterBank.h -text
+RTCP/CNProc/src/Flagger.cc -text
+RTCP/CNProc/src/Flagger.h -text
 RTCP/CNProc/src/InversePPF.cc -text
 RTCP/CNProc/src/InversePPF.h -text
+RTCP/CNProc/src/PostCorrelationFlagger.cc -text
+RTCP/CNProc/src/PostCorrelationFlagger.h -text
+RTCP/CNProc/src/PreCorrelationFlagger.cc -text
+RTCP/CNProc/src/PreCorrelationFlagger.h -text
 RTCP/CNProc/src/Ring.h -text
 RTCP/CNProc/src/Stokes.cc -text
 RTCP/CNProc/src/Stokes.h -text
diff --git a/RTCP/CNProc/src/CMakeLists.txt b/RTCP/CNProc/src/CMakeLists.txt
index e455faabc6d9a1241d3edaa72d7824896257eaa6..2e08f8ee239dd98651580aead118d7db040ece30 100644
--- a/RTCP/CNProc/src/CMakeLists.txt
+++ b/RTCP/CNProc/src/CMakeLists.txt
@@ -26,6 +26,9 @@ set(cnproc_LIB_SRCS
   FilterBank.cc
   LocationInfo.cc
   PPF.cc
+  Flagger.cc
+  PreCorrelationFlagger.cc
+  PostCorrelationFlagger.cc
   Stokes.cc)
 
 # Maybe we shoud use LOFAR_COMPILER_SUITE, because ASM-BGP_COMPILER_WORKS
diff --git a/RTCP/CNProc/src/Flagger.cc b/RTCP/CNProc/src/Flagger.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c12c78211a48d2b0cbf246973fb511786d5b560d
--- /dev/null
+++ b/RTCP/CNProc/src/Flagger.cc
@@ -0,0 +1,45 @@
+//# Always #include <lofar_config.h> first!
+#include <lofar_config.h>
+
+#include <Flagger.h>
+#include <math.h>
+#include <algorithm>
+
+namespace LOFAR {
+namespace RTCP {
+
+Flagger::  Flagger(const unsigned nrStations, const unsigned nrChannels, const unsigned totalNrSamples, const float cutoffThreshold) :
+  itsNrStations(nrStations),
+  itsNrChannels(nrChannels),
+  itsTotalNrSamples(totalNrSamples),
+  itsCutoffThreshold(cutoffThreshold)
+{
+}
+
+
+float Flagger::calculateStdDev(const std::vector<float>& data, const float mean) {
+  float stdDev = 0.0f;
+
+  for(unsigned i = 0; i<data.size(); i++) {
+    float diff = data[i] - mean;
+    stdDev += diff * diff;
+  }
+  stdDev /= data.size();
+  stdDev = sqrt(stdDev);
+
+  return stdDev;
+}
+
+
+float Flagger::calculateMedian(const std::vector<float>& origData) {
+  // we have to copy the vector, nth_element changes the ordering.
+  std::vector<float> data = origData;
+
+  // calculate median, expensive, but nth_element is guaranteed to be O(n)
+  std::vector<float>::iterator it = data.begin() + (data.size() / 2);
+  std::nth_element(data.begin(), it, data.end());
+  return *it;
+}
+
+} // namespace RTCP
+} // namespace LOFAR
diff --git a/RTCP/CNProc/src/Flagger.h b/RTCP/CNProc/src/Flagger.h
new file mode 100644
index 0000000000000000000000000000000000000000..70695c59a094996d599af4b4f6da7f8657c8bbb4
--- /dev/null
+++ b/RTCP/CNProc/src/Flagger.h
@@ -0,0 +1,32 @@
+#ifndef LOFAR_CNPROC_FLAGGER_H
+#define LOFAR_CNPROC_FLAGGER_H
+
+#include <vector>
+
+namespace LOFAR {
+namespace RTCP {
+
+class Flagger
+{
+  public:
+
+  Flagger(const unsigned nrStations, const unsigned nrChannels, const unsigned itsTotalNrSamples, const float cutoffThreshold);
+
+  static float calculateStdDev(const std::vector<float>& data, const float mean);
+  static float calculateMedian(const std::vector<float>& origData);
+
+
+  const unsigned itsNrStations, itsNrChannels;
+  const unsigned itsTotalNrSamples;
+  const float itsCutoffThreshold;
+
+  std::vector<float> itsPowers;
+  float itsPowerMean;
+  float itsPowerStdDev;
+  float itsPowerMedian;
+};
+
+} // namespace RTCP
+} // namespace LOFAR
+
+#endif // LOFAR_CNPROC_FLAGGER_H
diff --git a/RTCP/CNProc/src/PostCorrelationFlagger.cc b/RTCP/CNProc/src/PostCorrelationFlagger.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f567a4e119217f2855c1ad403b3b5fc619811f1c
--- /dev/null
+++ b/RTCP/CNProc/src/PostCorrelationFlagger.cc
@@ -0,0 +1,148 @@
+//# Always #include <lofar_config.h> first!
+#include <lofar_config.h>
+
+#include <Common/Timer.h>
+
+#include <PostCorrelationFlagger.h>
+#include <Correlator.h>
+
+namespace LOFAR {
+namespace RTCP {
+
+static NSTimer RFIStatsTimer("RFI statistics calculations (post correlation)", true, true);
+static NSTimer thresholdingFlaggerTimer("Thresholding flagger (post correlation)", true, true);
+static NSTimer detectBrokenStationsTimer("DetectBrokenStations (post correlation)", true, true);
+
+  // CorrelatedData samples: [nrBaselines][nrChannels][NR_POLARIZATIONS][NR_POLARIZATIONS]
+
+  PostCorrelationFlagger::PostCorrelationFlagger(const unsigned nrStations, unsigned nrBaselines, const unsigned nrChannels, float cutoffThreshold)
+:
+  Flagger(nrStations, nrChannels, nrBaselines * nrChannels * NR_POLARIZATIONS * NR_POLARIZATIONS, cutoffThreshold),
+  itsNrBaselines(nrBaselines)
+{
+  itsPowers.resize(itsTotalNrSamples);
+  itsSummedBaselinePowers.resize(itsNrBaselines);
+  itsSummedStationPowers.resize(itsNrStations);
+}
+
+
+void PostCorrelationFlagger::flag(CorrelatedData* correlatedData)
+{
+  calculateGlobalStatistics(correlatedData);
+  thresholdingFlagger(correlatedData);
+}
+
+
+void PostCorrelationFlagger::thresholdingFlagger(CorrelatedData* correlatedData)
+{
+  thresholdingFlaggerTimer.start();
+  
+  float threshold = itsPowerMean + itsCutoffThreshold * itsPowerStdDev;
+
+  unsigned index = 0;
+  unsigned totalSamplesFlagged = 0;
+
+  for(unsigned baseline = 0; baseline < itsNrBaselines; baseline++) {
+    for(unsigned channel = 0; channel < itsNrChannels; channel++) {
+      for(unsigned pol1 = 0; pol1< NR_POLARIZATIONS; pol1++) {
+	for(unsigned pol2 = 0; pol2< NR_POLARIZATIONS; pol2++) {
+	  const float power = itsPowers[index++];
+
+	  if(power > threshold) {
+	    // flag this sample, both polarizations.
+	    // TODO: currently, we can only flag all channels at once! This is a limitation in CorrelatedData.
+	    //	    correlatedData->flags[station].include(time, time);
+
+#ifdef LOFAR_STMAN_V2      
+	    correlatedData->nrValidSamplesV2[baseline] = 0;
+#else
+	    correlatedData->nrValidSamples[baseline][channel] = 0;
+#endif
+
+	    totalSamplesFlagged++;
+	  }
+	}
+      }
+    }
+  }
+
+  thresholdingFlaggerTimer.stop();
+
+  float percentageFlagged = totalSamplesFlagged * 100.0f / itsPowers.size();
+
+  std::cerr << "thresholdingFlagger: flagged " << totalSamplesFlagged << " samples, " << percentageFlagged << " %" << std::endl;
+}
+
+
+void PostCorrelationFlagger::detectBrokenStations()
+{
+  detectBrokenStationsTimer.start();
+
+  // Sum all baselines that involve a station (both horizontally and vertically).
+  float total = 0.0f;
+
+  for(unsigned station=0; station < itsNrStations; station++) {
+    float sum = 0.0f;
+    for(unsigned stationH=station; stationH < itsNrStations; stationH++) {
+      for(unsigned stationV=0; stationV < station; stationV++) {
+	unsigned baseline = Correlator::baseline(stationH, stationV);
+	sum += itsSummedBaselinePowers[baseline];
+      }
+    } 
+    itsSummedStationPowers[station] = sum;
+    total += sum;
+  }
+
+  float mean = total / itsNrStations;
+  float stdDev = calculateStdDev(itsSummedStationPowers, mean);
+  float median = calculateMedian(itsSummedStationPowers);
+  float threshold = mean + itsCutoffThreshold * stdDev;
+
+  std::cout << "detectBrokenStations: mean = " << mean << ", median = " << median << " stdDev = " << stdDev << ", threshold = " << threshold << std::endl;
+
+  for(unsigned station=0; station < itsNrStations; station++) {
+    if(itsSummedStationPowers[station] > threshold) {
+      std::cerr << "WARNING, station " << station << " seems to be corrupted, total summed power = " << itsSummedStationPowers[station] << std::endl;
+    }
+  }
+
+  detectBrokenStationsTimer.stop();
+}
+
+
+void PostCorrelationFlagger::calculateGlobalStatistics(CorrelatedData* correlatedData)
+{
+  RFIStatsTimer.start();
+
+  float sum = 0.0f;
+  unsigned index = 0;
+
+  for(unsigned baseline = 0; baseline < itsNrBaselines; baseline++) {
+    float baselineSum = 0.0f;
+    for(unsigned channel = 0; channel < itsNrChannels; channel++) {
+      for(unsigned pol1 = 0; pol1< NR_POLARIZATIONS; pol1++) {
+	for(unsigned pol2 = 0; pol2< NR_POLARIZATIONS; pol2++) {
+	  fcomplex sample = correlatedData->visibilities[baseline][channel][pol1][pol2];
+	  float power = real(sample) * real(sample) + imag(sample) * imag(sample);
+	  itsPowers[index++] = power;
+	  baselineSum += power;
+	}
+      }
+    }
+    itsSummedBaselinePowers[baseline] = baselineSum;
+    sum += baselineSum;
+  }
+ 
+  itsPowerMean = sum / itsTotalNrSamples;
+
+  itsPowerStdDev = calculateStdDev(itsPowers, itsPowerMean);
+  itsPowerMedian = calculateMedian(itsPowers);
+
+  RFIStatsTimer.stop();
+
+  std::cerr << "global RFI stats: mean = " << itsPowerMean << ", median = " << itsPowerMedian << ", stddev = " << itsPowerStdDev << std::endl;
+}
+
+
+} // namespace RTCP
+} // namespace LOFAR
diff --git a/RTCP/CNProc/src/PostCorrelationFlagger.h b/RTCP/CNProc/src/PostCorrelationFlagger.h
new file mode 100644
index 0000000000000000000000000000000000000000..3954a29ba1a66668d7d49c8a1916f684c8005c9f
--- /dev/null
+++ b/RTCP/CNProc/src/PostCorrelationFlagger.h
@@ -0,0 +1,39 @@
+#ifndef LOFAR_CNPROC_POST_CORRELATION_FLAGGER_H
+#define LOFAR_CNPROC_POST_CORRELATION_FLAGGER_H
+
+#include <Flagger.h>
+#include <Interface/CorrelatedData.h>
+
+namespace LOFAR {
+namespace RTCP {
+
+  class PostCorrelationFlagger : public Flagger
+{
+  public:
+  PostCorrelationFlagger(const unsigned nrStations, unsigned nrBaselines, const unsigned nrChannels, float cutoffThreshold = 7.0f);
+
+  void flag(CorrelatedData* correlatedData);
+
+  // Does simple thresholding
+  void thresholdingFlagger(CorrelatedData* correlatedData);
+
+  // Tries to detect broken stations
+  void detectBrokenStations();
+
+  // calculates mean, stddev, and median.
+  void calculateGlobalStatistics(CorrelatedData* correlatedData);
+
+  private:
+  const unsigned itsNrBaselines;
+  
+  std::vector<float> itsSummedBaselinePowers; // [nrBaselines]
+
+  std::vector<float> itsSummedStationPowers; // [nrStations]
+
+};
+
+
+} // namespace RTCP
+} // namespace LOFAR
+
+#endif // LOFAR_CNPROC_POST_CORRELATION_FLAGGER_H
diff --git a/RTCP/CNProc/src/PreCorrelationFlagger.cc b/RTCP/CNProc/src/PreCorrelationFlagger.cc
new file mode 100644
index 0000000000000000000000000000000000000000..dc068cea321415a62c66ffeffc743259d9264b8d
--- /dev/null
+++ b/RTCP/CNProc/src/PreCorrelationFlagger.cc
@@ -0,0 +1,100 @@
+//# Always #include <lofar_config.h> first!
+#include <lofar_config.h>
+
+#include <Common/Timer.h>
+
+#include <PreCorrelationFlagger.h>
+
+
+namespace LOFAR {
+namespace RTCP {
+
+static NSTimer RFIStatsTimer("RFI statistics calculations (pre correlation)", true, true);
+static NSTimer thresholdingFlaggerTimer("Thresholding flagger (pre correlation)", true, true);
+
+  // FilteredData samples: [nrChannels][nrStations][nrSamplesPerIntegration][NR_POLARIZATIONS]
+  // FilteredData flags:   std::vector<SparseSet<unsigned> >  flags;
+
+  PreCorrelationFlagger::PreCorrelationFlagger(const unsigned nrStations, const unsigned nrChannels, const unsigned nrSamplesPerIntegration, const float cutoffThreshold)
+:
+  Flagger(nrStations, nrChannels, nrStations * nrChannels * nrSamplesPerIntegration * NR_POLARIZATIONS, cutoffThreshold),
+  itsNrSamplesPerIntegration(nrSamplesPerIntegration)
+{
+  itsPowers.resize(itsTotalNrSamples);
+}
+
+
+void PreCorrelationFlagger::flag(FilteredData* filteredData)
+{
+  calculateGlobalStatistics(filteredData);
+  thresholdingFlagger(filteredData);
+}
+
+
+void PreCorrelationFlagger::thresholdingFlagger(FilteredData* filteredData)
+{
+  thresholdingFlaggerTimer.start();
+  
+  float threshold = itsPowerMean + itsCutoffThreshold * itsPowerStdDev;
+
+  unsigned index = 0;
+  unsigned totalSamplesFlagged = 0;
+
+  for(unsigned channel = 0; channel < itsNrChannels; channel++) {
+    for(unsigned station = 0; station < itsNrStations; station++) {
+      for(unsigned time = 0; time < itsNrSamplesPerIntegration; time++) {
+	for(unsigned pol = 0; pol< NR_POLARIZATIONS; pol++) {
+	  const float power = itsPowers[index++];
+
+	  if(power > threshold) {
+	    // flag this sample, both polarizations.
+	    // TODO: currently, we can only flag all channels at once! This is a limitation in FilteredData.
+	    filteredData->flags[station].include(time, time);
+	    totalSamplesFlagged++;
+	  }
+	}
+      }
+    }
+  }
+
+  thresholdingFlaggerTimer.stop();
+
+  float percentageFlagged = totalSamplesFlagged * 100.0f / itsPowers.size();
+
+  std::cerr << "thresholdingFlagger: flagged " << totalSamplesFlagged << " samples, " << percentageFlagged << " %" << std::endl;
+}
+
+
+void PreCorrelationFlagger::calculateGlobalStatistics(FilteredData* filteredData)
+{
+  RFIStatsTimer.start();
+
+  float sum = 0.0f;
+  unsigned index = 0;
+
+  for(unsigned channel = 0; channel < itsNrChannels; channel++) {
+    for(unsigned station = 0; station < itsNrStations; station++) {
+      for(unsigned time = 0; time < itsNrSamplesPerIntegration; time++) {
+	for(unsigned pol = 0; pol< NR_POLARIZATIONS; pol++) {
+	  fcomplex sample = filteredData->samples[channel][station][time][pol];
+	  float power = real(sample) * real(sample) + imag(sample) * imag(sample);
+	  sum += power;
+	  itsPowers[index++] = power;
+	}
+      }
+    }
+  }
+
+  itsPowerMean = sum / itsTotalNrSamples;
+
+  itsPowerStdDev = calculateStdDev(itsPowers, itsPowerMean);
+  itsPowerMedian = calculateMedian(itsPowers);
+
+  RFIStatsTimer.stop();
+
+  std::cerr << "global RFI stats: mean = " << itsPowerMean << ", median = " << itsPowerMedian << ", stddev = " << itsPowerStdDev << std::endl;
+}
+
+
+} // namespace RTCP
+} // namespace LOFAR
diff --git a/RTCP/CNProc/src/PreCorrelationFlagger.h b/RTCP/CNProc/src/PreCorrelationFlagger.h
new file mode 100644
index 0000000000000000000000000000000000000000..e065fdb8c8ec05e2a4d21a73650114ede98063d3
--- /dev/null
+++ b/RTCP/CNProc/src/PreCorrelationFlagger.h
@@ -0,0 +1,33 @@
+#ifndef LOFAR_CNPROC_PRE_CORRELATION_FLAGGER_H
+#define LOFAR_CNPROC_PRE_CORRELATION_FLAGGER_H
+
+#include <Flagger.h>
+#include <Interface/FilteredData.h>
+
+namespace LOFAR {
+namespace RTCP {
+
+  class PreCorrelationFlagger : public Flagger
+{
+  public:
+  PreCorrelationFlagger(const unsigned nrStations, const unsigned nrChannels, const unsigned nrSamplesPerIntegration, float cutoffThreshold = 7.0f);
+
+  void flag(FilteredData* filteredData);
+
+  private:
+
+  // Does simple thresholding
+  void thresholdingFlagger(FilteredData* filteredData);
+
+  // calculates mean, stddev, and median.
+  void calculateGlobalStatistics(FilteredData* filteredData);
+
+
+  const unsigned itsNrSamplesPerIntegration;
+};
+
+
+} // namespace RTCP
+} // namespace LOFAR
+
+#endif // LOFAR_CNPROC_PRE_CORRELATION_FLAGGER_H