diff --git a/Framework/API/src/ExperimentInfo.cpp b/Framework/API/src/ExperimentInfo.cpp
index 3eb512910b36fe4eb1418b035d51e54ae03edf13..9b399d15c5c728aed7301d1e03cd590fa2e52d33 100644
--- a/Framework/API/src/ExperimentInfo.cpp
+++ b/Framework/API/src/ExperimentInfo.cpp
@@ -1458,7 +1458,7 @@ void ExperimentInfo::readParameterMap(const std::string &parameterStr) {
     std::string paramValue = tokens[3];
     int size = static_cast<int>(tokens.count());
     for (int i = 4; i < size; i++)
-      paramValue += ";" + tokens[4];
+      paramValue += ";" + tokens[i];
 
     const auto &paramType = tokens[1];
     const auto &paramName = tokens[2];
diff --git a/Framework/API/test/ExperimentInfoTest.h b/Framework/API/test/ExperimentInfoTest.h
index 2f2b3e7f1852ad85037484386b62514b31f69f46..16101dc1c8727bebbcfed18ca2b47627b8f7dfa6 100644
--- a/Framework/API/test/ExperimentInfoTest.h
+++ b/Framework/API/test/ExperimentInfoTest.h
@@ -941,6 +941,19 @@ public:
                      compInfo.parent(compInfo.indexOf(bankId)));
   }
 
+  void test_readParameterMap_semicolons_in_value() {
+    auto inst = ComponentCreationHelper::createMinimalInstrument(
+        V3D{-2, 0, 0} /*source*/, V3D{10, 0, 0} /*sample*/,
+        V3D{12, 0, 0} /*detector*/);
+    ExperimentInfo expInfo;
+    expInfo.setInstrument(inst);
+    expInfo.readParameterMap("detID:1;string;par;11;22;33;44");
+    auto &pmap = expInfo.instrumentParameters();
+    auto det = expInfo.getInstrument()->getDetector(1);
+    auto value = pmap.getString(det.get(), "par");
+    TS_ASSERT_EQUALS(value, "11;22;33;44");
+  }
+
 private:
   void addInstrumentWithParameter(ExperimentInfo &expt, const std::string &name,
                                   const std::string &value) {
diff --git a/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOneAuto2.h b/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOneAuto2.h
index 6cca5e217006f13101bf89d05de85ca7ad2cf764..f35a79b529eb8e8004805227ed7aedfc60f831fb 100644
--- a/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOneAuto2.h
+++ b/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOneAuto2.h
@@ -76,6 +76,10 @@ private:
   void populateAlgorithmicCorrectionProperties(
       Mantid::API::IAlgorithm_sptr alg,
       Mantid::Geometry::Instrument_const_sptr instrument);
+  /// Get a polarization efficiencies workspace.
+  std::tuple<API::MatrixWorkspace_sptr, std::string, std::string>
+  getPolarizationEfficiencies();
+  void applyPolarizationCorrection(std::string const &outputIvsLam);
 };
 
 } // namespace Algorithms
diff --git a/Framework/Algorithms/src/PolarizationCorrectionFredrikze.cpp b/Framework/Algorithms/src/PolarizationCorrectionFredrikze.cpp
index ccc49951484ab2c478347ec7601c21c1f3ca7b4f..f62a0e248a5d07bebf5976341f88dbcce764e191 100644
--- a/Framework/Algorithms/src/PolarizationCorrectionFredrikze.cpp
+++ b/Framework/Algorithms/src/PolarizationCorrectionFredrikze.cpp
@@ -239,9 +239,9 @@ PolarizationCorrectionFredrikze::execPA(WorkspaceGroup_sptr inWS) {
       (A0 - A1 + A2 - A3 + A4 + A5 - A6 + A7 - A8 + Ipp + Iaa - Ipa - Iap) / D;
   const auto nIaa =
       (A0 + A1 - A2 + A3 - A4 - A5 + A6 - A7 + A8 + Ipp + Iaa - Ipa - Iap) / D;
-  const auto nIpa =
-      (A0 - A1 + A2 + A3 - A4 - A5 + A6 + A7 - A8 - Ipp - Iaa + Ipa + Iap) / D;
   const auto nIap =
+      (A0 - A1 + A2 + A3 - A4 - A5 + A6 + A7 - A8 - Ipp - Iaa + Ipa + Iap) / D;
+  const auto nIpa =
       (A0 + A1 - A2 - A3 + A4 + A5 - A6 - A7 + A8 - Ipp - Iaa + Ipa + Iap) / D;
 
   WorkspaceGroup_sptr dataOut = boost::make_shared<WorkspaceGroup>();
diff --git a/Framework/Algorithms/src/ReflectometryReductionOne2.cpp b/Framework/Algorithms/src/ReflectometryReductionOne2.cpp
index f180dd3e7b53fc46e898aa0abd14d19707b3e496..7c2e8b0663065a013a8b9422f3735e09c910ba12 100644
--- a/Framework/Algorithms/src/ReflectometryReductionOne2.cpp
+++ b/Framework/Algorithms/src/ReflectometryReductionOne2.cpp
@@ -532,11 +532,16 @@ ReflectometryReductionOne2::monitorCorrection(MatrixWorkspace_sptr detectorWS) {
   Property *backgroundMinProperty =
       getProperty("MonitorBackgroundWavelengthMin");
   Property *backgroundMaxProperty =
-      getProperty("MonitorBackgroundWavelengthMin");
+      getProperty("MonitorBackgroundWavelengthMax");
   if (!monProperty->isDefault() && !backgroundMinProperty->isDefault() &&
       !backgroundMaxProperty->isDefault()) {
     const bool integratedMonitors =
         getProperty("NormalizeByIntegratedMonitors");
+    int index = getProperty("I0MonitorIndex");
+    if (!m_spectrumInfo->isMonitor(index)) {
+      throw std::invalid_argument("A monitor is expected at spectrum index " +
+                                  std::to_string(index));
+    }
     const auto monitorWS = makeMonitorWS(m_runWS, integratedMonitors);
     if (!integratedMonitors)
       detectorWS = rebinDetectorsToMonitors(detectorWS, monitorWS);
@@ -760,6 +765,11 @@ void ReflectometryReductionOne2::findDetectorGroups() {
 
   for (const auto &group : m_detectorGroups) {
     for (const auto &spIdx : group) {
+      if (m_spectrumInfo->isMonitor(spIdx)) {
+        throw std::invalid_argument("A detector is expected at spectrum " +
+                                    std::to_string(spIdx) +
+                                    ", found a monitor");
+      }
       if (spIdx > m_spectrumInfo->size() - 1) {
         throw std::runtime_error(
             "ProcessingInstructions contains an out-of-range index: " +
diff --git a/Framework/Algorithms/src/ReflectometryReductionOneAuto2.cpp b/Framework/Algorithms/src/ReflectometryReductionOneAuto2.cpp
index f53abe892ef620c80d7498cc290c6a1af0ad534a..bd30f72c8078ab292c3b286b773fa6d38f4a71c3 100644
--- a/Framework/Algorithms/src/ReflectometryReductionOneAuto2.cpp
+++ b/Framework/Algorithms/src/ReflectometryReductionOneAuto2.cpp
@@ -185,7 +185,7 @@ void ReflectometryReductionOneAuto2::init() {
   initMomentumTransferProperties();
 
   // Polarization correction
-  std::vector<std::string> propOptions = {"None", "PA", "PNR"};
+  std::vector<std::string> propOptions = {"None", "PA", "PNR", "ParameterFile"};
   declareProperty("PolarizationAnalysis", "None",
                   boost::make_shared<StringListValidator>(propOptions),
                   "Polarization analysis mode.");
@@ -243,7 +243,6 @@ void ReflectometryReductionOneAuto2::exec() {
 
   IAlgorithm_sptr alg = createChildAlgorithm("ReflectometryReductionOne");
   alg->initialize();
-
   // Mandatory properties
   alg->setProperty("SummationType", getPropertyValue("SummationType"));
   alg->setProperty("ReductionType", getPropertyValue("ReductionType"));
@@ -746,35 +745,7 @@ bool ReflectometryReductionOneAuto2::processGroups() {
     return true;
   }
 
-  auto groupIvsLam =
-      AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>(outputIvsLam);
-  auto effAlg = createChildAlgorithm("CreatePolarizationEfficiencies");
-  effAlg->setProperty("InputWorkspace", groupIvsLam->getItem(0));
-  if (!isDefault("Pp")) {
-    effAlg->setProperty("Pp", getPropertyValue("Pp"));
-  }
-  if (!isDefault("Rho")) {
-    effAlg->setProperty("Rho", getPropertyValue("Rho"));
-  }
-  if (!isDefault("Ap")) {
-    effAlg->setProperty("Ap", getPropertyValue("Ap"));
-  }
-  if (!isDefault("Alpha")) {
-    effAlg->setProperty("Alpha", getPropertyValue("Alpha"));
-  }
-  effAlg->execute();
-  MatrixWorkspace_sptr efficiencies = effAlg->getProperty("OutputWorkspace");
-
-  Algorithm_sptr polAlg =
-      createChildAlgorithm("PolarizationCorrectionFredrikze");
-  polAlg->setChild(false);
-  polAlg->setRethrows(true);
-  polAlg->setProperty("InputWorkspace", outputIvsLam);
-  polAlg->setProperty("OutputWorkspace", outputIvsLam);
-  polAlg->setProperty("PolarizationAnalysis",
-                      getPropertyValue("PolarizationAnalysis"));
-  polAlg->setProperty("Efficiencies", efficiencies);
-  polAlg->execute();
+  applyPolarizationCorrection(outputIvsLam);
 
   // Now we've overwritten the IvsLam workspaces, we'll need to recalculate
   // the IvsQ ones
@@ -802,6 +773,79 @@ bool ReflectometryReductionOneAuto2::processGroups() {
   return true;
 }
 
+/** Construct a polarization efficiencies workspace based on values of input
+ * properties.
+ */
+std::tuple<API::MatrixWorkspace_sptr, std::string, std::string>
+ReflectometryReductionOneAuto2::getPolarizationEfficiencies() {
+  auto groupIvsLam = AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>(
+      getPropertyValue("OutputWorkspaceWavelength"));
+
+  std::string const paMethod = getPropertyValue("PolarizationAnalysis");
+  Workspace_sptr workspace = groupIvsLam->getItem(0);
+  MatrixWorkspace_sptr efficiencies;
+  std::string correctionMethod;
+  std::string correctionOption;
+
+  if (paMethod == "ParameterFile") {
+    auto effAlg = createChildAlgorithm("ExtractPolarizationEfficiencies");
+    effAlg->setProperty("InputWorkspace", workspace);
+    effAlg->execute();
+    efficiencies = effAlg->getProperty("OutputWorkspace");
+    correctionMethod = effAlg->getPropertyValue("CorrectionMethod");
+    correctionOption = effAlg->getPropertyValue("CorrectionOption");
+  } else {
+    auto effAlg = createChildAlgorithm("CreatePolarizationEfficiencies");
+    effAlg->setProperty("InputWorkspace", workspace);
+    if (!isDefault("Pp")) {
+      effAlg->setProperty("Pp", getPropertyValue("Pp"));
+    }
+    if (!isDefault("Rho")) {
+      effAlg->setProperty("Rho", getPropertyValue("Rho"));
+    }
+    if (!isDefault("Ap")) {
+      effAlg->setProperty("Ap", getPropertyValue("Ap"));
+    }
+    if (!isDefault("Alpha")) {
+      effAlg->setProperty("Alpha", getPropertyValue("Alpha"));
+    }
+    effAlg->execute();
+    efficiencies = effAlg->getProperty("OutputWorkspace");
+    correctionMethod = "Fredrikze";
+    correctionOption = paMethod;
+  }
+  return std::make_tuple(efficiencies, correctionMethod, correctionOption);
+}
+
+/**
+ * Apply a polarization correction to workspaces in lambda.
+ * @param outputIvsLam :: Name of a workspace group to apply the correction to.
+ */
+void ReflectometryReductionOneAuto2::applyPolarizationCorrection(
+    std::string const &outputIvsLam) {
+  MatrixWorkspace_sptr efficiencies;
+  std::string correctionMethod;
+  std::string correctionOption;
+  std::tie(efficiencies, correctionMethod, correctionOption) =
+      getPolarizationEfficiencies();
+
+  Algorithm_sptr polAlg = createChildAlgorithm("PolarizationEfficiencyCor");
+  polAlg->setChild(false);
+  polAlg->setRethrows(true);
+  polAlg->setProperty("OutputWorkspace", outputIvsLam);
+  polAlg->setProperty("Efficiencies", efficiencies);
+  polAlg->setProperty("CorrectionMethod", correctionMethod);
+
+  if (correctionMethod == "Fredrikze") {
+    polAlg->setProperty("InputWorkspaceGroup", outputIvsLam);
+    polAlg->setProperty("PolarizationAnalysis", correctionOption);
+  } else {
+    throw std::invalid_argument("Unsupported polarization correction method: " +
+                                correctionMethod);
+  }
+  polAlg->execute();
+}
+
 /**
  * Sum transmission workspaces that belong to a workspace group
  * @param transGroup : The transmission group containing the transmission runs
diff --git a/Framework/Algorithms/test/CMakeLists.txt b/Framework/Algorithms/test/CMakeLists.txt
index 27bd0b3ee0c07a71479dcc1f9d621d156c4d13a7..0396d63368d60fbcd1c72305a89b777480d07c2c 100644
--- a/Framework/Algorithms/test/CMakeLists.txt
+++ b/Framework/Algorithms/test/CMakeLists.txt
@@ -39,6 +39,7 @@ if ( CXXTEST_FOUND )
                         ../../TestHelpers/src/TearDownWorld.cpp
                         ../../TestHelpers/src/WorkspaceCreationHelper.cpp
                         ../../TestHelpers/src/ParallelRunner.cpp
+                        ../../TestHelpers/src/ReflectometryHelper.cpp
                         )
   cxxtest_add_test ( AlgorithmsTest ${TEST_FILES} )
   target_link_libraries ( AlgorithmsTest LINK_PRIVATE ${TCMALLOC_LIBRARIES_LINKTIME} ${MANTIDLIBS}
diff --git a/Framework/Algorithms/test/PolarizationCorrectionFredrikzeTest.h b/Framework/Algorithms/test/PolarizationCorrectionFredrikzeTest.h
index 0e3d0d69fe3e1dee18d09aa3cb963289b6dc11f6..e40856319f20164d75355e0e51b86768f6cb598f 100644
--- a/Framework/Algorithms/test/PolarizationCorrectionFredrikzeTest.h
+++ b/Framework/Algorithms/test/PolarizationCorrectionFredrikzeTest.h
@@ -9,10 +9,10 @@
 #include "MantidAPI/WorkspaceGroup.h"
 #include "MantidAlgorithms/PolarizationCorrectionFredrikze.h"
 #include "MantidDataHandling/CreatePolarizationEfficiencies.h"
+#include "MantidDataHandling/JoinISISPolarizationEfficiencies.h"
 #include "MantidDataObjects/TableWorkspace.h"
 #include "MantidDataObjects/Workspace2D.h"
 #include "MantidKernel/OptionalBool.h"
-
 #include "MantidTestHelpers/WorkspaceCreationHelper.h"
 
 #include <boost/make_shared.hpp>
@@ -312,6 +312,86 @@ public:
       TS_ASSERT(checkAlg->getProperty("Result"));
     }
   }
+
+  void test_run_PA_non_unity() {
+    auto Rpp = create1DWorkspace(4, 0.9, 1);
+    auto Rpa = create1DWorkspace(4, 0.8, 1);
+    auto Rap = create1DWorkspace(4, 0.7, 1);
+    auto Raa = create1DWorkspace(4, 0.6, 1);
+
+    auto Pp = create1DWorkspace(4, 0.99, 1);
+    auto Ap = create1DWorkspace(4, 0.98, 1);
+    auto Pa = create1DWorkspace(4, 0.97, 1);
+    auto Aa = create1DWorkspace(4, 0.96, 1);
+
+    auto Rho = Pa / Pp;
+    auto Alpha = Aa / Ap;
+
+    Mantid::DataHandling::JoinISISPolarizationEfficiencies join_eff;
+    join_eff.initialize();
+    join_eff.setChild(true);
+    join_eff.setRethrows(true);
+    join_eff.setProperty("Pp", Pp);
+    join_eff.setProperty("Ap", Ap);
+    join_eff.setProperty("Rho", Rho);
+    join_eff.setProperty("Alpha", Alpha);
+    join_eff.setPropertyValue("OutputWorkspace", "dummy");
+    join_eff.execute();
+    MatrixWorkspace_sptr efficiencies = join_eff.getProperty("OutputWorkspace");
+    TS_ASSERT(efficiencies);
+
+    auto groupWS = boost::make_shared<WorkspaceGroup>(); // Empty group ws.
+
+    auto Ipp = (Rpp * (Pp + 1.0) * (Ap + 1.0) +
+                Raa * (Pp * (-1.0) + 1.0) * (Ap * (-1.0) + 1.0) +
+                Rpa * (Pp + 1.0) * (Ap * (-1.0) + 1.0) +
+                Rap * (Pp * (-1.0) + 1.0) * (Ap + 1.0)) /
+               4.;
+    auto Iaa = (Raa * (Pa + 1.0) * (Aa + 1.0) +
+                Rpp * (Pa * (-1.0) + 1.0) * (Aa * (-1.0) + 1.0) +
+                Rap * (Pa + 1.0) * (Aa * (-1.0) + 1.0) +
+                Rpa * (Pa * (-1.0) + 1.0) * (Aa + 1.0)) /
+               4.;
+    auto Ipa = (Rpa * (Pp + 1.0) * (Aa + 1.0) +
+                Rap * (Pp * (-1.0) + 1.0) * (Aa * (-1.0) + 1.0) +
+                Rpp * (Pp + 1.0) * (Aa * (-1.0) + 1.0) +
+                Raa * (Pp * (-1.0) + 1.0) * (Aa + 1.0)) /
+               4.;
+    auto Iap = (Rap * (Pa + 1.0) * (Ap + 1.0) +
+                Rpa * (Pa * (-1.0) + 1.0) * (Ap * (-1.0) + 1.0) +
+                Raa * (Pa + 1.0) * (Ap * (-1.0) + 1.0) +
+                Rpp * (Pa * (-1.0) + 1.0) * (Ap + 1.0)) /
+               4.;
+
+    groupWS->addWorkspace(Ipp);
+    groupWS->addWorkspace(Ipa);
+    groupWS->addWorkspace(Iap);
+    groupWS->addWorkspace(Iaa);
+
+    PolarizationCorrectionFredrikze alg;
+    alg.setChild(true);
+    alg.setRethrows(true);
+    alg.initialize();
+    alg.setProperty("InputWorkspace", groupWS);
+    alg.setPropertyValue("OutputWorkspace", "dummy");
+    alg.setProperty("PolarizationAnalysis", "PA");
+    alg.setProperty("Efficiencies", efficiencies);
+    alg.execute();
+    WorkspaceGroup_sptr outWS = alg.getProperty("OutputWorkspace");
+
+    TSM_ASSERT_EQUALS("Wrong number of output workspaces", outWS->size(),
+                      groupWS->size());
+
+    auto out1 = boost::dynamic_pointer_cast<MatrixWorkspace>(outWS->getItem(0));
+    auto out2 = boost::dynamic_pointer_cast<MatrixWorkspace>(outWS->getItem(1));
+    auto out3 = boost::dynamic_pointer_cast<MatrixWorkspace>(outWS->getItem(2));
+    auto out4 = boost::dynamic_pointer_cast<MatrixWorkspace>(outWS->getItem(3));
+
+    TS_ASSERT_DELTA(out1->y(0)[0], 0.9, 1e-14);
+    TS_ASSERT_DELTA(out2->y(0)[0], 0.8, 1e-14);
+    TS_ASSERT_DELTA(out3->y(0)[0], 0.7, 1e-14);
+    TS_ASSERT_DELTA(out4->y(0)[0], 0.6, 1e-14);
+  }
 };
 
 #endif /* MANTID_ALGORITHMS_POLARIZATIONCORRECTIONFREDRIKZE_TEST_H_ */
diff --git a/Framework/Algorithms/test/ReflectometryReductionOneAuto2Test.h b/Framework/Algorithms/test/ReflectometryReductionOneAuto2Test.h
index 8179b8eac358dc690d3d564f5817b339555586a3..1d3fcb8673507394cc14d4c16ac7c88d11ccecc3 100644
--- a/Framework/Algorithms/test/ReflectometryReductionOneAuto2Test.h
+++ b/Framework/Algorithms/test/ReflectometryReductionOneAuto2Test.h
@@ -3,21 +3,29 @@
 
 #include <cxxtest/TestSuite.h>
 
-#include "MantidAPI/AlgorithmManager.h"
+#include "MantidAlgorithms/ReflectometryReductionOneAuto2.h"
+
+#include "MantidAPI/AnalysisDataService.h"
 #include "MantidAPI/FrameworkManager.h"
 #include "MantidAPI/MatrixWorkspace.h"
 #include "MantidAPI/WorkspaceGroup.h"
-#include "MantidAlgorithms/ReflectometryReductionOneAuto2.h"
 #include "MantidGeometry/Instrument.h"
+#include "MantidTestHelpers/ReflectometryHelper.h"
 #include "MantidTestHelpers/WorkspaceCreationHelper.h"
 
-using Mantid::Algorithms::ReflectometryReductionOneAuto2;
+using namespace Mantid::Algorithms;
 using namespace Mantid::API;
+using namespace Mantid::DataHandling;
+using namespace Mantid::DataObjects;
+using namespace Mantid::HistogramData;
+using namespace Mantid::Kernel;
+using namespace Mantid::TestHelpers;
 
 class ReflectometryReductionOneAuto2Test : public CxxTest::TestSuite {
 private:
   MatrixWorkspace_sptr m_notTOF;
   MatrixWorkspace_sptr m_TOF;
+  AnalysisDataServiceImpl &ADS = AnalysisDataService::Instance();
 
   MatrixWorkspace_sptr loadRun(const std::string &run) {
 
@@ -565,35 +573,68 @@ public:
     TS_ASSERT_DELTA(outQ->x(0)[7], 0.5962, 0.0001);
   }
 
-  void test_polarization_correction() {
+  void test_polarization_correction_PA() {
+    std::string const name = "input";
+    prepareInputGroup(name);
+    applyPolarizationEfficiencies(name);
 
-    MatrixWorkspace_sptr first = m_TOF->clone();
-    MatrixWorkspace_sptr second = m_TOF->clone();
-    MatrixWorkspace_sptr third = m_TOF->clone();
-    MatrixWorkspace_sptr fourth = m_TOF->clone();
+    ReflectometryReductionOneAuto2 alg;
+    alg.initialize();
+    alg.setPropertyValue("InputWorkspace", name);
+    alg.setProperty("WavelengthMin", 1.0);
+    alg.setProperty("WavelengthMax", 15.0);
+    alg.setProperty("ThetaIn", 10.0);
+    alg.setProperty("ProcessingInstructions", "1");
+    alg.setProperty("MomentumTransferStep", 0.04);
+    alg.setProperty("PolarizationAnalysis", "PA");
+    alg.setProperty("Pp", "0.9,0,0");
+    alg.setProperty("Ap", "0.8,0,0");
+    alg.setProperty("Rho", "0.7778,0,0");
+    alg.setProperty("Alpha", "0.75,0");
+    alg.setPropertyValue("OutputWorkspace", "IvsQ");
+    alg.setPropertyValue("OutputWorkspaceBinned", "IvsQ_binned");
+    alg.setPropertyValue("OutputWorkspaceWavelength", "IvsLam");
+    alg.execute();
 
-    WorkspaceGroup_sptr inputWSGroup = boost::make_shared<WorkspaceGroup>();
-    inputWSGroup->addWorkspace(first);
-    inputWSGroup->addWorkspace(second);
-    inputWSGroup->addWorkspace(third);
-    inputWSGroup->addWorkspace(fourth);
-    WorkspaceGroup_sptr transWSGroup = boost::make_shared<WorkspaceGroup>();
-    transWSGroup->addWorkspace(first);
-    transWSGroup->addWorkspace(second);
-    transWSGroup->addWorkspace(third);
-    transWSGroup->addWorkspace(fourth);
-    AnalysisDataService::Instance().addOrReplace("input", inputWSGroup);
-    AnalysisDataService::Instance().addOrReplace("trans", transWSGroup);
+    auto outQGroup = retrieveOutWS("IvsQ");
+    auto outLamGroup = retrieveOutWS("IvsLam");
+
+    TS_ASSERT_EQUALS(outQGroup.size(), 4);
+    TS_ASSERT_EQUALS(outLamGroup.size(), 4);
+
+    TS_ASSERT_EQUALS(outLamGroup[0]->blocksize(), 9);
+    // X range in outLam
+    TS_ASSERT_DELTA(outLamGroup[0]->x(0).front(), 2.0729661466, 0.0001);
+    TS_ASSERT_DELTA(outLamGroup[0]->x(0).back(), 14.2963182408, 0.0001);
+
+    TS_ASSERT_DELTA(outLamGroup[0]->y(0)[0], 0.9, 0.0001);
+    TS_ASSERT_DELTA(outLamGroup[1]->y(0)[0], 0.8, 0.0001);
+    TS_ASSERT_DELTA(outLamGroup[2]->y(0)[0], 0.7, 0.0001);
+    TS_ASSERT_DELTA(outLamGroup[3]->y(0)[0], 0.6, 0.0001);
+
+    TS_ASSERT_EQUALS(outQGroup[0]->blocksize(), 9);
+
+    TS_ASSERT_DELTA(outQGroup[0]->y(0)[0], 0.9, 0.0001);
+    TS_ASSERT_DELTA(outQGroup[1]->y(0)[0], 0.8, 0.0001);
+    TS_ASSERT_DELTA(outQGroup[2]->y(0)[0], 0.7, 0.0001);
+    TS_ASSERT_DELTA(outQGroup[3]->y(0)[0], 0.6, 0.0001);
+
+    ADS.clear();
+  }
+
+  void test_polarization_correction_PNR_wrong_input() {
+    std::string const name = "input";
+    prepareInputGroup(name);
 
     ReflectometryReductionOneAuto2 alg;
     alg.initialize();
-    alg.setPropertyValue("InputWorkspace", "input");
-    alg.setPropertyValue("FirstTransmissionRun", "trans");
-    alg.setProperty("WavelengthMin", 1.5);
+    alg.setPropertyValue("InputWorkspace", name);
+    alg.setProperty("WavelengthMin", 1.0);
     alg.setProperty("WavelengthMax", 15.0);
-    alg.setProperty("ProcessingInstructions", "2");
+    alg.setProperty("ThetaIn", 10.0);
+    alg.setProperty("ProcessingInstructions", "1");
     alg.setProperty("MomentumTransferStep", 0.04);
-    alg.setProperty("PolarizationAnalysis", "PA");
+    alg.setProperty("PolarizationAnalysis", "PNR");
     alg.setProperty("Pp", "1,1,2");
     alg.setProperty("Ap", "1,1,2");
     alg.setProperty("Rho", "1,1");
@@ -601,50 +642,140 @@ public:
     alg.setPropertyValue("OutputWorkspace", "IvsQ");
     alg.setPropertyValue("OutputWorkspaceBinned", "IvsQ_binned");
     alg.setPropertyValue("OutputWorkspaceWavelength", "IvsLam");
+    TS_ASSERT_THROWS_EQUALS(
+        alg.execute(), std::invalid_argument & e, std::string(e.what()),
+        "For PNR analysis, input group must have 2 periods.");
+  }
+
+  void test_polarization_correction_PNR() {
+    std::string const name = "input";
+    prepareInputGroup(name, "", 2);
+
+    ReflectometryReductionOneAuto2 alg;
+    alg.initialize();
+    alg.setPropertyValue("InputWorkspace", name);
+    alg.setProperty("WavelengthMin", 1.0);
+    alg.setProperty("WavelengthMax", 15.0);
+    alg.setProperty("ThetaIn", 10.0);
+    alg.setProperty("ProcessingInstructions", "1");
+    alg.setProperty("MomentumTransferStep", 0.04);
+    alg.setProperty("PolarizationAnalysis", "PNR");
+    alg.setProperty("Pp", "1,1,2");
+    alg.setProperty("Rho", "1,1");
+    alg.setPropertyValue("OutputWorkspace", "IvsQ");
+    alg.setPropertyValue("OutputWorkspaceBinned", "IvsQ_binned");
+    alg.setPropertyValue("OutputWorkspaceWavelength", "IvsLam");
     alg.execute();
-    auto outQGroup =
-        AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>("IvsQ");
-    auto outLamGroup =
-        AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>("IvsLam");
-
-    TS_ASSERT(outQGroup);
-    TS_ASSERT(outLamGroup);
-
-    if (!outQGroup || !outLamGroup)
-      return;
-
-    TS_ASSERT_EQUALS(outQGroup->size(), 4);
-    TS_ASSERT_EQUALS(outLamGroup->size(), 4);
-
-    {
-      auto outQ =
-          boost::dynamic_pointer_cast<MatrixWorkspace>(outQGroup->getItem(0));
-      TS_ASSERT_EQUALS(outQ->getNumberHistograms(), 1);
-      TS_ASSERT_EQUALS(outQ->blocksize(), 14);
-      // X range in outQ
-      TS_ASSERT_DELTA(outQ->x(0)[0], 0.3353, 0.0001);
-      TS_ASSERT_DELTA(outQ->x(0)[7], 0.5962, 0.0001);
-      auto outLam =
-          boost::dynamic_pointer_cast<MatrixWorkspace>(outLamGroup->getItem(0));
-      // X range in outLam
-      TS_ASSERT_DELTA(outLam->x(0)[0], 1.7924, 0.0001);
-      TS_ASSERT_DELTA(outLam->x(0)[7], 8.0658, 0.0001);
-    }
 
-    {
-      auto outQ =
-          boost::dynamic_pointer_cast<MatrixWorkspace>(outQGroup->getItem(1));
-      TS_ASSERT_EQUALS(outQ->getNumberHistograms(), 1);
-      TS_ASSERT_EQUALS(outQ->blocksize(), 14);
-      // X range in outQ
-      TS_ASSERT_DELTA(outQ->x(0)[0], 0.3353, 0.0001);
-      TS_ASSERT_DELTA(outQ->x(0)[7], 0.5962, 0.0001);
-      auto outLam =
-          boost::dynamic_pointer_cast<MatrixWorkspace>(outLamGroup->getItem(1));
-      // X range in outLam
-      TS_ASSERT_DELTA(outLam->x(0)[0], 1.7924, 0.0001);
-      TS_ASSERT_DELTA(outLam->x(0)[7], 8.0658, 0.0001);
-    }
+    auto outQGroup = retrieveOutWS("IvsQ");
+    auto outLamGroup = retrieveOutWS("IvsLam");
+
+    TS_ASSERT_EQUALS(outQGroup.size(), 2);
+    TS_ASSERT_EQUALS(outLamGroup.size(), 2);
+
+    TS_ASSERT_EQUALS(outLamGroup[0]->blocksize(), 9);
+    // X range in outLam
+    TS_ASSERT_DELTA(outLamGroup[0]->x(0).front(), 2.0729661466, 0.0001);
+    TS_ASSERT_DELTA(outLamGroup[0]->x(0).back(), 14.2963182408, 0.0001);
+
+    TS_ASSERT_DELTA(outLamGroup[0]->y(0)[0], 0.8800698581, 0.0001);
+    TS_ASSERT_DELTA(outLamGroup[1]->y(0)[0], 0.8778429658, 0.0001);
+
+    TS_ASSERT_EQUALS(outQGroup[0]->blocksize(), 9);
+    TS_ASSERT_DELTA(outQGroup[0]->y(0)[0], 0.8936134321, 0.0001);
+    TS_ASSERT_DELTA(outQGroup[1]->y(0)[0], 0.8935802109, 0.0001);
+
+    ADS.clear();
+  }
+
+  void test_polarization_correction_default() {
+
+    std::string const name = "input";
+    prepareInputGroup(name, "Fredrikze");
+    applyPolarizationEfficiencies(name);
+
+    ReflectometryReductionOneAuto2 alg;
+    alg.initialize();
+    alg.setPropertyValue("InputWorkspace", name);
+    alg.setProperty("ThetaIn", 10.0);
+    alg.setProperty("WavelengthMin", 1.0);
+    alg.setProperty("WavelengthMax", 15.0);
+    alg.setProperty("ProcessingInstructions", "1");
+    alg.setProperty("MomentumTransferStep", 0.04);
+    alg.setProperty("PolarizationAnalysis", "ParameterFile");
+    alg.setPropertyValue("OutputWorkspace", "IvsQ");
+    alg.setPropertyValue("OutputWorkspaceBinned", "IvsQ_binned");
+    alg.setPropertyValue("OutputWorkspaceWavelength", "IvsLam");
+    alg.execute();
+
+    auto outQGroup = retrieveOutWS("IvsQ");
+    auto outLamGroup = retrieveOutWS("IvsLam");
+
+    TS_ASSERT_EQUALS(outQGroup.size(), 4);
+    TS_ASSERT_EQUALS(outLamGroup.size(), 4);
+
+    TS_ASSERT_EQUALS(outLamGroup[0]->blocksize(), 9);
+    // X range in outLam
+    TS_ASSERT_DELTA(outLamGroup[0]->x(0).front(), 2.0729661466, 0.0001);
+    TS_ASSERT_DELTA(outLamGroup[0]->x(0).back(), 14.2963182408, 0.0001);
+
+    TS_ASSERT_DELTA(outLamGroup[0]->y(0)[0], 0.9, 0.0001);
+    TS_ASSERT_DELTA(outLamGroup[1]->y(0)[0], 0.8, 0.0001);
+    TS_ASSERT_DELTA(outLamGroup[2]->y(0)[0], 0.7, 0.0001);
+    TS_ASSERT_DELTA(outLamGroup[3]->y(0)[0], 0.6, 0.0001);
+
+    TS_ASSERT_EQUALS(outQGroup[0]->blocksize(), 9);
+
+    TS_ASSERT_DELTA(outQGroup[0]->y(0)[0], 0.9, 0.0001);
+    TS_ASSERT_DELTA(outQGroup[1]->y(0)[0], 0.8, 0.0001);
+    TS_ASSERT_DELTA(outQGroup[2]->y(0)[0], 0.7, 0.0001);
+    TS_ASSERT_DELTA(outQGroup[3]->y(0)[0], 0.6, 0.0001);
+
+    ADS.clear();
+  }
+
+  void test_monitor_index_in_group() {
+    std::string const name = "input";
+    prepareInputGroup(name);
+
+    ReflectometryReductionOneAuto2 alg;
+    alg.setRethrows(true);
+    alg.initialize();
+    alg.setPropertyValue("InputWorkspace", name);
+    alg.setProperty("WavelengthMin", 1.0);
+    alg.setProperty("WavelengthMax", 5.0);
+    alg.setProperty("ProcessingInstructions", "0");
+    alg.setProperty("MomentumTransferStep", 0.04);
+    alg.setProperty("PolarizationAnalysis", "ParameterFile");
+    alg.setPropertyValue("OutputWorkspace", "IvsQ");
+    alg.setPropertyValue("OutputWorkspaceBinned", "IvsQ_binned");
+    alg.setPropertyValue("OutputWorkspaceWavelength", "IvsLam");
+    TS_ASSERT_THROWS_EQUALS(
+        alg.execute(), std::invalid_argument & e, std::string(e.what()),
+        "A detector is expected at spectrum 0, found a monitor");
+  }
+
+  void test_I0MonitorIndex_is_detector() {
+    std::string const name = "input";
+    prepareInputGroup(name);
+
+    ReflectometryReductionOneAuto2 alg;
+    alg.setRethrows(true);
+    alg.initialize();
+    alg.setPropertyValue("InputWorkspace", name);
+    alg.setProperty("WavelengthMin", 1.0);
+    alg.setProperty("WavelengthMax", 5.0);
+    alg.setProperty("MonitorBackgroundWavelengthMin", 1.0);
+    alg.setProperty("MonitorBackgroundWavelengthMax", 5.0);
+    alg.setPropertyValue("I0MonitorIndex", "1");
+    alg.setProperty("ProcessingInstructions", "1");
+    alg.setProperty("MomentumTransferStep", 0.04);
+    alg.setPropertyValue("OutputWorkspace", "IvsQ");
+    alg.setPropertyValue("OutputWorkspaceBinned", "IvsQ_binned");
+    alg.setPropertyValue("OutputWorkspaceWavelength", "IvsLam");
+    TS_ASSERT_THROWS_EQUALS(alg.execute(), std::invalid_argument & e,
+                            std::string(e.what()),
+                            "A monitor is expected at spectrum index 1");
   }
 };
 
diff --git a/Framework/DataHandling/CMakeLists.txt b/Framework/DataHandling/CMakeLists.txt
index 220c1e62f1facd25ab13c450db3d99f91e1a1663..e30f516e5cb8afd614bcc0103ad352257c90c9fb 100644
--- a/Framework/DataHandling/CMakeLists.txt
+++ b/Framework/DataHandling/CMakeLists.txt
@@ -22,6 +22,7 @@ set ( SRC_FILES
 	src/DownloadInstrument.cpp
 	src/EventWorkspaceCollection.cpp
 	src/ExtractMonitorWorkspace.cpp
+	src/ExtractPolarizationEfficiencies.cpp
 	src/FilterEventsByLogValuePreNexus.cpp
 	src/FindDetectorsInShape.cpp
 	src/FindDetectorsPar.cpp
@@ -209,6 +210,7 @@ set ( INC_FILES
 	inc/MantidDataHandling/DownloadInstrument.h
 	inc/MantidDataHandling/EventWorkspaceCollection.h
 	inc/MantidDataHandling/ExtractMonitorWorkspace.h
+	inc/MantidDataHandling/ExtractPolarizationEfficiencies.h
 	inc/MantidDataHandling/FilterEventsByLogValuePreNexus.h
 	inc/MantidDataHandling/FindDetectorsInShape.h
 	inc/MantidDataHandling/FindDetectorsPar.h
@@ -393,6 +395,7 @@ set ( TEST_FILES
 	DownloadInstrumentTest.h
 	EventWorkspaceCollectionTest.h
 	ExtractMonitorWorkspaceTest.h
+	ExtractPolarizationEfficienciesTest.h
 	FilterEventsByLogValuePreNexusTest.h
 	FindDetectorsInShapeTest.h
 	FindDetectorsParTest.h
diff --git a/Framework/DataHandling/inc/MantidDataHandling/ExtractPolarizationEfficiencies.h b/Framework/DataHandling/inc/MantidDataHandling/ExtractPolarizationEfficiencies.h
new file mode 100644
index 0000000000000000000000000000000000000000..3401bfbe384b12c41de2fdabeb1dab2d6bba7ee6
--- /dev/null
+++ b/Framework/DataHandling/inc/MantidDataHandling/ExtractPolarizationEfficiencies.h
@@ -0,0 +1,52 @@
+#ifndef MANTID_DATAHANDLING_EXTRACTPOLARIZATIONEFFICIENCIES_H_
+#define MANTID_DATAHANDLING_EXTRACTPOLARIZATIONEFFICIENCIES_H_
+
+#include "MantidAPI/Algorithm.h"
+#include "MantidKernel/System.h"
+
+namespace Mantid {
+namespace DataHandling {
+/** Looks for a parameter in the parameter file that stores polarization
+   efficiencies to be used with the polarization correction algorithm
+   (PolarizationEfficienciesCor).
+
+    Copyright &copy; 2014 ISIS Rutherford Appleton Laboratory, NScD Oak Ridge
+   National Laboratory & European Spallation Source
+
+    This file is part of Mantid.
+
+    Mantid is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    Mantid is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+    File change history is stored at: <https://github.com/mantidproject/mantid>
+    Code Documentation is available at: <http://doxygen.mantidproject.org>
+*/
+class DLLExport ExtractPolarizationEfficiencies : public API::Algorithm {
+public:
+  const std::string name() const override;
+  int version() const override;
+  const std::vector<std::string> seeAlso() const override {
+    return {"PolarizationEfficiencyCor"};
+  }
+  const std::string category() const override;
+  const std::string summary() const override;
+
+private:
+  void init() override;
+  void exec() override;
+};
+
+} // namespace DataHandling
+} // namespace Mantid
+
+#endif /* MANTID_DATAHANDLING_EXTRACTPOLARIZATIONEFFICIENCIES_H_ */
diff --git a/Framework/DataHandling/src/ExtractPolarizationEfficiencies.cpp b/Framework/DataHandling/src/ExtractPolarizationEfficiencies.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b7badbe04f345a63e63e49021053742fd14a9fcd
--- /dev/null
+++ b/Framework/DataHandling/src/ExtractPolarizationEfficiencies.cpp
@@ -0,0 +1,156 @@
+#include "MantidDataHandling/ExtractPolarizationEfficiencies.h"
+#include "MantidAPI/MatrixWorkspace.h"
+#include "MantidDataObjects/Workspace2D.h"
+#include "MantidGeometry/Instrument.h"
+#include "MantidHistogramData/Counts.h"
+#include "MantidHistogramData/LinearGenerator.h"
+#include "MantidHistogramData/Points.h"
+#include "MantidKernel/Unit.h"
+
+#include <sstream>
+
+namespace Mantid {
+namespace DataHandling {
+// Register the algorithm into the AlgorithmFactory
+DECLARE_ALGORITHM(ExtractPolarizationEfficiencies)
+
+using namespace Mantid::API;
+using namespace Mantid::DataObjects;
+using namespace Mantid::HistogramData;
+using namespace Mantid::Kernel;
+
+namespace {
+
+std::string const METHOD_FREDRIKZE("Fredrikze");
+std::string const METHOD_WILDES("Wildes");
+std::string const METHOD_PARAMETER("polarization_correction_method");
+std::string const OPTION_PARAMETER("polarization_correction_option");
+std::string const LAMBDA_PARAMETER("efficiency_lambda");
+
+std::map<std::string, std::vector<std::string>> const EFFICIENCIES{
+    {METHOD_FREDRIKZE, {"Pp", "Ap", "Rho", "Alpha"}},
+    {METHOD_WILDES, {"P1", "P2", "F1", "F2"}}};
+
+std::vector<double> parseVector(std::string const &name,
+                                std::string const &value) {
+  std::istringstream istr(value);
+  std::vector<double> result;
+  double number;
+  while (istr >> number) {
+    result.push_back(number);
+  }
+
+  if (!istr.eof()) {
+    throw std::invalid_argument(
+        "Error while parsing instrument vector parameter " + name);
+  }
+
+  return result;
+}
+
+MatrixWorkspace_sptr createWorkspace(std::vector<double> const &x,
+                                     std::vector<double> const &y) {
+  Points xVals(x);
+  Counts yVals(y);
+  auto retVal = boost::make_shared<Workspace2D>();
+  retVal->initialize(1, Histogram(xVals, yVals));
+  return retVal;
+}
+
+} // namespace
+
+/// Algorithm's name for identification. @see Algorithm::name
+const std::string ExtractPolarizationEfficiencies::name() const {
+  return "ExtractPolarizationEfficiencies";
+}
+
+/// Algorithm's version for identification. @see Algorithm::version
+int ExtractPolarizationEfficiencies::version() const { return 1; }
+
+/// Algorithm's category for identification. @see Algorithm::category
+const std::string ExtractPolarizationEfficiencies::category() const {
+  return "DataHandling;ISIS\\Reflectometry";
+}
+
+/// Algorithm's summary for use in the GUI and help. @see Algorithm::summary
+const std::string ExtractPolarizationEfficiencies::summary() const {
+  return "Extracts polarization efficiencies from instrument's parameter file.";
+}
+
+/** Initialize the algorithm's properties.
+ */
+void ExtractPolarizationEfficiencies::init() {
+  declareProperty(
+      make_unique<WorkspaceProperty<>>("InputWorkspace", "", Direction::Input),
+      "A workspace with attached instrument whose parameters contain "
+      "polarization efficiencies.");
+  declareProperty(make_unique<WorkspaceProperty<>>("OutputWorkspace", "",
+                                                   Direction::Output),
+                  "The workspace with extracted efficiencies.");
+  declareProperty<std::string>("CorrectionMethod", "",
+                               "Correction method: Fredrikze or Wildes.",
+                               Kernel::Direction::Output);
+  declareProperty<std::string>(
+      "CorrectionOption", "",
+      "Correction option, eg \"PA\" or \"PNR\" for Fredrikze method.",
+      Kernel::Direction::Output);
+}
+
+/** Execute the algorithm.
+ */
+void ExtractPolarizationEfficiencies::exec() {
+  MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace");
+
+  auto instrument = inputWS->getInstrument();
+  auto const method = instrument->getParameterAsString(METHOD_PARAMETER);
+  if (method.empty()) {
+    throw std::invalid_argument("Correction method is undefined");
+  }
+  if (method != METHOD_FREDRIKZE && method != METHOD_WILDES) {
+    throw std::invalid_argument("Unknown correction method: " + method);
+  }
+  setProperty("CorrectionMethod", method);
+  auto const lambdaValue = instrument->getParameterAsString(LAMBDA_PARAMETER);
+  if (lambdaValue.empty()) {
+    throw std::invalid_argument(
+        "Wavelengths are missing from the correction parameters");
+  }
+  auto const lambda = parseVector(LAMBDA_PARAMETER, lambdaValue);
+  if (lambda.size() < 2) {
+    throw std::runtime_error("Instrument vector parameter \"" +
+                             LAMBDA_PARAMETER +
+                             "\" must have at least 2 elements but it has " +
+                             std::to_string(lambda.size()));
+  }
+
+  auto alg = createChildAlgorithm("JoinISISPolarizationEfficiencies");
+  auto const &efficiencies = EFFICIENCIES.at(method);
+  for (auto const &name : efficiencies) {
+    auto const propValue = instrument->getParameterAsString(name);
+    if (propValue.empty()) {
+      throw std::invalid_argument("Parameter " + name +
+                                  " is missing from the correction parameters");
+    }
+    auto const prop = parseVector(name, propValue);
+    if (lambda.size() != prop.size()) {
+      throw std::runtime_error("Instrument vector parameter \"" + name +
+                               "\" is expeced to be the same size as \"" +
+                               LAMBDA_PARAMETER + "\" but " +
+                               std::to_string(prop.size()) + " != " +
+                               std::to_string(lambda.size()));
+    }
+    auto ws = createWorkspace(lambda, prop);
+    alg->setProperty(name, ws);
+  }
+  alg->execute();
+  MatrixWorkspace_sptr result = alg->getProperty("OutputWorkspace");
+  setProperty("OutputWorkspace", result);
+  auto const option = instrument->getParameterAsString(OPTION_PARAMETER);
+  if (option.empty()) {
+    throw std::invalid_argument("Correction option is undefined");
+  }
+  setProperty("CorrectionOption", option);
+}
+
+} // namespace DataHandling
+} // namespace Mantid
diff --git a/Framework/DataHandling/test/ExtractPolarizationEfficienciesTest.h b/Framework/DataHandling/test/ExtractPolarizationEfficienciesTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..b2666930a36c5725ec08ebd50c35bd98a92a2ac1
--- /dev/null
+++ b/Framework/DataHandling/test/ExtractPolarizationEfficienciesTest.h
@@ -0,0 +1,446 @@
+#ifndef MANTID_DATAHANDLING_EXTRACTPOLARIZATIONEFFICIENCIESTEST_H_
+#define MANTID_DATAHANDLING_EXTRACTPOLARIZATIONEFFICIENCIESTEST_H_
+
+#include <cxxtest/TestSuite.h>
+
+#include "MantidAPI/Axis.h"
+#include "MantidDataHandling/ExtractPolarizationEfficiencies.h"
+#include "MantidDataHandling/LoadInstrument.h"
+#include "MantidDataHandling/LoadParameterFile.h"
+#include "MantidDataObjects/Workspace2D.h"
+#include "MantidGeometry/Instrument.h"
+#include "MantidGeometry/Instrument/ParameterMap.h"
+#include "MantidHistogramData/Counts.h"
+#include "MantidHistogramData/LinearGenerator.h"
+#include "MantidHistogramData/Points.h"
+#include "MantidKernel/OptionalBool.h"
+#include "MantidKernel/Unit.h"
+#include "MantidTestHelpers/WorkspaceCreationHelper.h"
+
+using namespace Mantid::API;
+using namespace Mantid::DataHandling;
+using namespace Mantid::DataObjects;
+using namespace Mantid::Geometry;
+using namespace Mantid::HistogramData;
+using namespace Mantid::Kernel;
+
+class ExtractPolarizationEfficienciesTest : public CxxTest::TestSuite {
+public:
+  // This pair of boilerplate methods prevent the suite being created statically
+  // This means the constructor isn't called when running other tests
+  static ExtractPolarizationEfficienciesTest *createSuite() {
+    return new ExtractPolarizationEfficienciesTest();
+  }
+  static void destroySuite(ExtractPolarizationEfficienciesTest *suite) {
+    delete suite;
+  }
+
+  void test_init() {
+    ExtractPolarizationEfficiencies alg;
+    TS_ASSERT_THROWS_NOTHING(alg.initialize());
+    TS_ASSERT(alg.isInitialized());
+  }
+
+  void test_no_instrument() {
+    auto workspace = createPointWS(1, 0, 10);
+    ExtractPolarizationEfficiencies alg;
+    alg.initialize();
+    alg.setChild(true);
+    alg.setRethrows(true);
+    alg.setProperty("InputWorkspace", workspace);
+    alg.setProperty("OutputWorkspace", "dummy");
+    TS_ASSERT_THROWS(alg.execute(), std::invalid_argument);
+  }
+
+  void test_wrong_method() {
+    auto workspace = createInputWorkspace("Einstein");
+    ExtractPolarizationEfficiencies alg;
+    alg.initialize();
+    alg.setChild(true);
+    alg.setRethrows(true);
+    alg.setProperty("InputWorkspace", workspace);
+    alg.setProperty("OutputWorkspace", "dummy");
+    TS_ASSERT_THROWS(alg.execute(), std::invalid_argument);
+  }
+
+  void test_no_lambda() {
+    auto lambda = "";
+    auto workspace = createInputWorkspace("Wildes", lambda);
+    ExtractPolarizationEfficiencies alg;
+    alg.initialize();
+    alg.setChild(true);
+    alg.setRethrows(true);
+    alg.setProperty("InputWorkspace", workspace);
+    alg.setProperty("OutputWorkspace", "dummy");
+    TS_ASSERT_THROWS(alg.execute(), std::invalid_argument);
+  }
+
+  void test_space_sep() {
+    auto lambda = "1 2 3 4";
+    auto workspace = createInputWorkspace("Wildes", lambda);
+    ExtractPolarizationEfficiencies alg;
+    alg.initialize();
+    alg.setChild(true);
+    alg.setRethrows(true);
+    alg.setProperty("InputWorkspace", workspace);
+    alg.setProperty("OutputWorkspace", "dummy");
+    alg.execute();
+    MatrixWorkspace_sptr outWS = alg.getProperty("OutputWorkspace");
+
+    TS_ASSERT(outWS);
+    TS_ASSERT_EQUALS(outWS->getNumberHistograms(), 4);
+    TS_ASSERT_EQUALS(outWS->blocksize(), 4);
+    TS_ASSERT_DELTA(outWS->x(0)[0], 1.0, 1e-14);
+    TS_ASSERT_DELTA(outWS->x(0)[1], 2.0, 1e-14);
+    TS_ASSERT_DELTA(outWS->x(0)[2], 3.0, 1e-14);
+    TS_ASSERT_DELTA(outWS->x(0)[3], 4.0, 1e-14);
+  }
+
+  void test_double_space_sep() {
+    auto lambda = " 1  2  3  4 ";
+    auto workspace = createInputWorkspace("Wildes", lambda);
+    ExtractPolarizationEfficiencies alg;
+    alg.initialize();
+    alg.setChild(true);
+    alg.setRethrows(true);
+    alg.setProperty("InputWorkspace", workspace);
+    alg.setProperty("OutputWorkspace", "dummy");
+    alg.execute();
+    MatrixWorkspace_sptr outWS = alg.getProperty("OutputWorkspace");
+
+    TS_ASSERT(outWS);
+    TS_ASSERT_EQUALS(outWS->getNumberHistograms(), 4);
+    TS_ASSERT_EQUALS(outWS->blocksize(), 4);
+    TS_ASSERT_DELTA(outWS->x(0)[0], 1.0, 1e-14);
+    TS_ASSERT_DELTA(outWS->x(0)[1], 2.0, 1e-14);
+    TS_ASSERT_DELTA(outWS->x(0)[2], 3.0, 1e-14);
+    TS_ASSERT_DELTA(outWS->x(0)[3], 4.0, 1e-14);
+  }
+
+  void test_comma_space_sep() {
+    auto lambda = "1, 2, 3, 4";
+    auto workspace = createInputWorkspace("Wildes", lambda);
+    ExtractPolarizationEfficiencies alg;
+    alg.initialize();
+    alg.setChild(true);
+    alg.setRethrows(true);
+    alg.setProperty("InputWorkspace", workspace);
+    alg.setProperty("OutputWorkspace", "dummy");
+    TS_ASSERT_THROWS(alg.execute(), std::invalid_argument);
+  }
+
+  void test_non_number() {
+    auto lambda = "one two three four";
+    auto workspace = createInputWorkspace("Wildes", lambda);
+    ExtractPolarizationEfficiencies alg;
+    alg.initialize();
+    alg.setChild(true);
+    alg.setRethrows(true);
+    alg.setProperty("InputWorkspace", workspace);
+    alg.setProperty("OutputWorkspace", "dummy");
+    TS_ASSERT_THROWS(alg.execute(), std::invalid_argument);
+  }
+
+  void test_new_line_sep() {
+    auto lambda = "1\n 2\n 3\n 4";
+    auto workspace = createInputWorkspace("Wildes", lambda);
+    ExtractPolarizationEfficiencies alg;
+    alg.initialize();
+    alg.setChild(true);
+    alg.setRethrows(true);
+    alg.setProperty("InputWorkspace", workspace);
+    alg.setProperty("OutputWorkspace", "dummy");
+    alg.execute();
+    MatrixWorkspace_sptr outWS = alg.getProperty("OutputWorkspace");
+
+    TS_ASSERT(outWS);
+    TS_ASSERT_EQUALS(outWS->getNumberHistograms(), 4);
+    TS_ASSERT_EQUALS(outWS->blocksize(), 4);
+    TS_ASSERT_DELTA(outWS->x(0)[0], 1.0, 1e-14);
+    TS_ASSERT_DELTA(outWS->x(0)[1], 2.0, 1e-14);
+    TS_ASSERT_DELTA(outWS->x(0)[2], 3.0, 1e-14);
+    TS_ASSERT_DELTA(outWS->x(0)[3], 4.0, 1e-14);
+  }
+
+  void test_missing_P1() {
+    auto lambda = "1 2 3 4";
+    bool skipP1 = true;
+    auto workspace = createInputWorkspace("Wildes", lambda, skipP1);
+    ExtractPolarizationEfficiencies alg;
+    alg.initialize();
+    alg.setChild(true);
+    alg.setRethrows(true);
+    alg.setProperty("InputWorkspace", workspace);
+    alg.setProperty("OutputWorkspace", "dummy");
+    TS_ASSERT_THROWS(alg.execute(), std::invalid_argument);
+  }
+
+  void test_Fredrikze() {
+    auto workspace = createInputWorkspace("Fredrikze");
+
+    ExtractPolarizationEfficiencies alg;
+    alg.initialize();
+    alg.setChild(true);
+    alg.setRethrows(true);
+    alg.setProperty("InputWorkspace", workspace);
+    alg.setProperty("OutputWorkspace", "dummy");
+    alg.execute();
+    MatrixWorkspace_sptr outWS = alg.getProperty("OutputWorkspace");
+
+    TS_ASSERT(outWS);
+    TS_ASSERT_EQUALS(outWS->getNumberHistograms(), 4);
+    TS_ASSERT_EQUALS(outWS->blocksize(), 4);
+    TS_ASSERT_EQUALS(outWS->getAxis(0)->unit()->caption(), "Wavelength");
+
+    auto axis1 = outWS->getAxis(1);
+    TS_ASSERT_EQUALS(axis1->label(0), "Pp");
+    TS_ASSERT_EQUALS(axis1->label(1), "Ap");
+    TS_ASSERT_EQUALS(axis1->label(2), "Rho");
+    TS_ASSERT_EQUALS(axis1->label(3), "Alpha");
+
+    TS_ASSERT(!outWS->isHistogramData());
+
+    TS_ASSERT_DELTA(outWS->x(0)[0], 1.0, 1e-14);
+    TS_ASSERT_DELTA(outWS->x(0)[1], 2.0, 1e-14);
+    TS_ASSERT_DELTA(outWS->x(0)[2], 3.0, 1e-14);
+    TS_ASSERT_DELTA(outWS->x(0)[3], 4.0, 1e-14);
+
+    TS_ASSERT_DELTA(outWS->y(0)[0], 0.991, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(0)[1], 0.992, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(0)[2], 0.993, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(0)[3], 0.994, 1e-14);
+
+    TS_ASSERT_DELTA(outWS->y(1)[0], 0.981, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(1)[1], 0.982, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(1)[2], 0.983, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(1)[3], 0.984, 1e-14);
+
+    TS_ASSERT_DELTA(outWS->y(2)[0], 0.971, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(2)[1], 0.972, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(2)[2], 0.973, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(2)[3], 0.974, 1e-14);
+
+    TS_ASSERT_DELTA(outWS->y(3)[0], 0.961, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(3)[1], 0.962, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(3)[2], 0.963, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(3)[3], 0.964, 1e-14);
+  }
+
+  void test_Wildes() {
+    auto workspace = createInputWorkspace("Wildes");
+
+    ExtractPolarizationEfficiencies alg;
+    alg.initialize();
+    alg.setChild(true);
+    alg.setRethrows(true);
+    alg.setProperty("InputWorkspace", workspace);
+    alg.setProperty("OutputWorkspace", "dummy");
+    alg.execute();
+    MatrixWorkspace_sptr outWS = alg.getProperty("OutputWorkspace");
+
+    TS_ASSERT(outWS);
+    TS_ASSERT_EQUALS(outWS->getNumberHistograms(), 4);
+    TS_ASSERT_EQUALS(outWS->blocksize(), 4);
+    TS_ASSERT_EQUALS(outWS->getAxis(0)->unit()->caption(), "Wavelength");
+
+    auto axis1 = outWS->getAxis(1);
+    TS_ASSERT_EQUALS(axis1->label(0), "P1");
+    TS_ASSERT_EQUALS(axis1->label(1), "P2");
+    TS_ASSERT_EQUALS(axis1->label(2), "F1");
+    TS_ASSERT_EQUALS(axis1->label(3), "F2");
+
+    TS_ASSERT(!outWS->isHistogramData());
+
+    TS_ASSERT_DELTA(outWS->x(0)[0], 1.0, 1e-14);
+    TS_ASSERT_DELTA(outWS->x(0)[1], 2.0, 1e-14);
+    TS_ASSERT_DELTA(outWS->x(0)[2], 3.0, 1e-14);
+    TS_ASSERT_DELTA(outWS->x(0)[3], 4.0, 1e-14);
+
+    TS_ASSERT_DELTA(outWS->y(0)[0], 0.991, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(0)[1], 0.992, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(0)[2], 0.993, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(0)[3], 0.994, 1e-14);
+
+    TS_ASSERT_DELTA(outWS->y(1)[0], 0.981, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(1)[1], 0.982, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(1)[2], 0.983, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(1)[3], 0.984, 1e-14);
+
+    TS_ASSERT_DELTA(outWS->y(2)[0], 0.971, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(2)[1], 0.972, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(2)[2], 0.973, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(2)[3], 0.974, 1e-14);
+
+    TS_ASSERT_DELTA(outWS->y(3)[0], 0.961, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(3)[1], 0.962, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(3)[2], 0.963, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(3)[3], 0.964, 1e-14);
+  }
+
+  void test_loading_from_file() {
+    auto workspace = createPointWS(1, 0, 10);
+    LoadInstrument loader;
+    loader.initialize();
+    loader.setPropertyValue("Filename",
+                            "IDFs_for_UNIT_TESTING/REFL_Definition.xml");
+    loader.setProperty("Workspace", workspace);
+    loader.setProperty("RewriteSpectraMap", OptionalBool(true));
+    loader.execute();
+    LoadParameterFile paramLoader;
+    paramLoader.initialize();
+    paramLoader.setPropertyValue(
+        "Filename", "IDFs_for_UNIT_TESTING/REFL_Parameters_Fredrikze.xml");
+    paramLoader.setProperty("Workspace", workspace);
+    paramLoader.execute();
+
+    ExtractPolarizationEfficiencies alg;
+    alg.initialize();
+    alg.setChild(true);
+    alg.setRethrows(true);
+    alg.setProperty("InputWorkspace", workspace);
+    alg.setProperty("OutputWorkspace", "dummy");
+    alg.execute();
+    MatrixWorkspace_sptr outWS = alg.getProperty("OutputWorkspace");
+
+    TS_ASSERT(outWS);
+    TS_ASSERT_EQUALS(outWS->getNumberHistograms(), 4);
+    TS_ASSERT_EQUALS(outWS->blocksize(), 6);
+    TS_ASSERT_EQUALS(outWS->getAxis(0)->unit()->caption(), "Wavelength");
+
+    auto axis1 = outWS->getAxis(1);
+    TS_ASSERT_EQUALS(axis1->label(0), "Pp");
+    TS_ASSERT_EQUALS(axis1->label(1), "Ap");
+    TS_ASSERT_EQUALS(axis1->label(2), "Rho");
+    TS_ASSERT_EQUALS(axis1->label(3), "Alpha");
+
+    TS_ASSERT(!outWS->isHistogramData());
+
+    TS_ASSERT_DELTA(outWS->x(0)[0], 0.0, 1e-14);
+    TS_ASSERT_DELTA(outWS->x(0)[1], 3.0, 1e-14);
+    TS_ASSERT_DELTA(outWS->x(0)[2], 6.0, 1e-14);
+    TS_ASSERT_DELTA(outWS->x(0)[3], 10.0, 1e-14);
+    TS_ASSERT_DELTA(outWS->x(0)[4], 15.0, 1e-14);
+    TS_ASSERT_DELTA(outWS->x(0)[5], 20.0, 1e-14);
+
+    TS_ASSERT_DELTA(outWS->y(0)[0], 0.9, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(0)[1], 0.9, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(0)[2], 0.9, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(0)[3], 0.9, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(0)[4], 0.9, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(0)[5], 0.9, 1e-14);
+
+    TS_ASSERT_DELTA(outWS->y(1)[0], 0.8, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(1)[1], 0.8, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(1)[2], 0.8, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(1)[3], 0.8, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(1)[4], 0.8, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(1)[5], 0.8, 1e-14);
+
+    TS_ASSERT_DELTA(outWS->y(2)[0], 0.778, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(2)[1], 0.778, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(2)[2], 0.778, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(2)[3], 0.778, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(2)[4], 0.778, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(2)[5], 0.778, 1e-14);
+
+    TS_ASSERT_DELTA(outWS->y(3)[0], 0.75, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(3)[1], 0.75, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(3)[2], 0.75, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(3)[3], 0.75, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(3)[4], 0.75, 1e-14);
+    TS_ASSERT_DELTA(outWS->y(3)[5], 0.75, 1e-14);
+  }
+
+  void test_short_lambda() {
+    auto workspace = createInputWorkspace("Wildes", "0");
+
+    ExtractPolarizationEfficiencies alg;
+    alg.initialize();
+    alg.setChild(true);
+    alg.setRethrows(true);
+    alg.setProperty("InputWorkspace", workspace);
+    alg.setProperty("OutputWorkspace", "dummy");
+    TS_ASSERT_THROWS_EQUALS(alg.execute(), std::runtime_error & e,
+                            std::string(e.what()),
+                            "Instrument vector parameter \"efficiency_lambda\" "
+                            "must have at least 2 elements but it has 1");
+  }
+
+  void test_empty_lambda() {
+    auto workspace = createInputWorkspace("Wildes", " ");
+
+    ExtractPolarizationEfficiencies alg;
+    alg.initialize();
+    alg.setChild(true);
+    alg.setRethrows(true);
+    alg.setProperty("InputWorkspace", workspace);
+    alg.setProperty("OutputWorkspace", "dummy");
+    TS_ASSERT_THROWS_EQUALS(alg.execute(), std::runtime_error & e,
+                            std::string(e.what()),
+                            "Instrument vector parameter \"efficiency_lambda\" "
+                            "must have at least 2 elements but it has 0");
+  }
+
+  void test_wrong_vector_size() {
+    auto workspace = createInputWorkspace("Wildes", "1 2 3");
+
+    ExtractPolarizationEfficiencies alg;
+    alg.initialize();
+    alg.setChild(true);
+    alg.setRethrows(true);
+    alg.setProperty("InputWorkspace", workspace);
+    alg.setProperty("OutputWorkspace", "dummy");
+    TS_ASSERT_THROWS_EQUALS(
+        alg.execute(), std::runtime_error & e, std::string(e.what()),
+        "Instrument vector parameter \"P1\" is expeced to be the same size as "
+        "\"efficiency_lambda\" but 4 != 3");
+  }
+
+private:
+  MatrixWorkspace_sptr createPointWS(size_t size, double startX,
+                                     double endX) const {
+    double const dX = (endX - startX) / double(size - 1);
+    Points xVals(size, LinearGenerator(startX, dX));
+    Counts yVals(size, 1.0);
+    auto retVal = boost::make_shared<Workspace2D>();
+    retVal->initialize(1, Histogram(xVals, yVals));
+    return retVal;
+  }
+
+  MatrixWorkspace_sptr
+  createInputWorkspace(std::string const &method,
+                       std::string const &lambda = "1 2 3 4",
+                       bool skipP1 = false) {
+    auto workspace = createPointWS(1, 0, 10);
+    auto pmap = boost::make_shared<ParameterMap>();
+    auto instrument = boost::make_shared<Instrument>();
+
+    pmap->addString(instrument.get(), "polarization_correction_method", method);
+    if (!lambda.empty()) {
+      pmap->addString(instrument.get(), "efficiency_lambda", lambda);
+    }
+    if (method == "Fredrikze") {
+      pmap->addString(instrument.get(), "polarization_correction_option", "PA");
+      pmap->addString(instrument.get(), "Pp", "0.991 0.992 0.993 0.994");
+      pmap->addString(instrument.get(), "Ap", "0.981 0.982 0.983 0.984");
+      pmap->addString(instrument.get(), "Rho", "0.971 0.972 0.973 0.974");
+      pmap->addString(instrument.get(), "Alpha", "0.961 0.962 0.963 0.964");
+    } else {
+      pmap->addString(instrument.get(), "polarization_correction_option",
+                      "00,01,10,11");
+      if (!skipP1) {
+        pmap->addString(instrument.get(), "P1", "0.991 0.992 0.993 0.994");
+      }
+      pmap->addString(instrument.get(), "P2", "0.981 0.982 0.983 0.984");
+      pmap->addString(instrument.get(), "F1", "0.971 0.972 0.973 0.974");
+      pmap->addString(instrument.get(), "F2", "0.961 0.962 0.963 0.964");
+    }
+
+    instrument = boost::make_shared<Instrument>(instrument, pmap);
+    workspace->setInstrument(instrument);
+
+    return workspace;
+  }
+};
+
+#endif /* MANTID_DATAHANDLING_EXTRACTPOLARIZATIONEFFICIENCIESTEST_H_ */
diff --git a/Framework/Geometry/inc/MantidGeometry/Instrument/Parameter.h b/Framework/Geometry/inc/MantidGeometry/Instrument/Parameter.h
index b7ca9aa319a86884c204822538027ef49b477844..728285c908c6e8c113785a8feefd320fd463b972 100644
--- a/Framework/Geometry/inc/MantidGeometry/Instrument/Parameter.h
+++ b/Framework/Geometry/inc/MantidGeometry/Instrument/Parameter.h
@@ -191,6 +191,14 @@ void ParameterType<Type>::fromString(const std::string &value) {
   istr >> m_value;
 }
 
+/**
+ * Specialization for a string.
+ */
+template <>
+inline void ParameterType<std::string>::fromString(const std::string &value) {
+  m_value = value;
+}
+
 /** Set the value of the parameter via the assignment operator
  * @tparam The parameter type
  * @param value :: The vlue of the parameter
diff --git a/Framework/Geometry/test/ParameterMapTest.h b/Framework/Geometry/test/ParameterMapTest.h
index ccb8378474c268b5a4045103fdb9967b8b0d7067..718b816a17fc4995dc6ad7d02e88718f0c4e6813 100644
--- a/Framework/Geometry/test/ParameterMapTest.h
+++ b/Framework/Geometry/test/ParameterMapTest.h
@@ -192,6 +192,14 @@ public:
     TS_ASSERT_EQUALS(descr, "Short description.");
   }
 
+  void test_add_string_with_spaces() {
+    ParameterMap pmap;
+    auto const comp = m_testInstrument.get();
+    pmap.add("string", comp, "name", std::string("A B C"));
+    auto value = pmap.get(comp, "name");
+    TS_ASSERT_EQUALS(value->value<std::string>(), "A B C");
+  }
+
   void testAdding_A_Parameter_That_Is_Not_Present_Puts_The_Parameter_In() {
     // Add a parameter for the first component of the instrument
     IComponent_sptr comp = m_testInstrument->getChild(0);
diff --git a/Framework/TestHelpers/inc/MantidTestHelpers/ReflectometryHelper.h b/Framework/TestHelpers/inc/MantidTestHelpers/ReflectometryHelper.h
new file mode 100644
index 0000000000000000000000000000000000000000..3411489d03932878f952f8dbcb650bc7663a7b7c
--- /dev/null
+++ b/Framework/TestHelpers/inc/MantidTestHelpers/ReflectometryHelper.h
@@ -0,0 +1,53 @@
+#ifndef MANTID_TESTHELPERS_REFLECTOMETRYHELPER_H_
+#define MANTID_TESTHELPERS_REFLECTOMETRYHELPER_H_
+
+#include "MantidAPI/MatrixWorkspace_fwd.h"
+#include "MantidAPI/WorkspaceGroup_fwd.h"
+
+#include <vector>
+
+namespace Mantid {
+
+using namespace API;
+
+namespace TestHelpers {
+
+// Create a workspace equipped with fake instrument from
+// IDFs_for_UNIT_TESTING/REFL_Definition.xml IDF.
+// @param nBins :: Number of bins in each spectrum.
+// @param startX :: Start value of the x-axis in TOF
+// @param endX :: End value of the x-axis in TOF
+// @param values :: Y-values. The created workspace will have as many spectra as
+// there are values -
+//     one value per spectrum.
+// @param paramsType :: Defines which instrument parameters file to load.
+// paramsType is appended to
+//     "REFL_Parameters_" to form the name for the file to load.
+MatrixWorkspace_sptr createREFL_WS(size_t nBins, double startX, double endX,
+                                   std::vector<double> const &values,
+                                   std::string const &paramsType = "");
+
+// Create a group of workspaces created with createREFL_WS(...) function and
+// store it in the ADS.
+// Ys get some hard-coded values.
+// @param name :: Group's name in the ADS.
+// @param size :: Size of the group.
+void prepareInputGroup(std::string const &name,
+                       std::string const &paramsType = "", size_t size = 4,
+                       double const startX = 5000.0,
+                       double const endX = 100000.0);
+
+// Retrieve wprkspace group with name name, cast its items to MatrixWorkspace
+// and return a vector of those.
+std::vector<MatrixWorkspace_sptr> retrieveOutWS(std::string const &name);
+
+// Apply some polarization efficiencies (Fredrikze) to a workspace such that
+// when it's run
+// through the polarization correction algorithm it gets restored to the
+// original.
+void applyPolarizationEfficiencies(std::string const &name);
+
+} // namespace TestHelpers
+} // namespace Mantid
+
+#endif // MANTID_TESTHELPERS_REFLECTOMETRYHELPER_H_
diff --git a/Framework/TestHelpers/src/ReflectometryHelper.cpp b/Framework/TestHelpers/src/ReflectometryHelper.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4dc37a027a56186d8398a8e61373549679bb0110
--- /dev/null
+++ b/Framework/TestHelpers/src/ReflectometryHelper.cpp
@@ -0,0 +1,179 @@
+#include "MantidTestHelpers/ReflectometryHelper.h"
+
+#include "MantidAPI/AnalysisDataService.h"
+#include "MantidAPI/MatrixWorkspace.h"
+#include "MantidAPI/WorkspaceGroup.h"
+#include "MantidAlgorithms/CreateWorkspace.h"
+#include "MantidAlgorithms/GroupWorkspaces.h"
+#include "MantidDataHandling/LoadInstrument.h"
+#include "MantidDataHandling/LoadParameterFile.h"
+#include "MantidHistogramData/BinEdges.h"
+#include "MantidHistogramData/LinearGenerator.h"
+#include "MantidKernel/OptionalBool.h"
+
+namespace Mantid {
+
+using namespace Algorithms;
+using namespace API;
+using namespace DataHandling;
+using namespace DataObjects;
+using namespace HistogramData;
+using namespace Kernel;
+
+namespace TestHelpers {
+
+MatrixWorkspace_sptr createHistoWS(size_t nBins, double startX, double endX,
+                                   std::vector<double> const &values,
+                                   std::string const &unitX = "TOF") {
+  double const dX = (endX - startX) / double(nBins);
+  BinEdges xVals(nBins + 1, LinearGenerator(startX, dX));
+  size_t nSpec = values.size();
+  std::vector<double> yVals(nSpec * nBins);
+  for (size_t i = 0; i < nSpec; ++i) {
+    std::fill(yVals.begin() + i * nBins, yVals.begin() + (i + 1) * nBins,
+              values[i]);
+  }
+
+  CreateWorkspace creator;
+  creator.setChild(true);
+  creator.initialize();
+  creator.setProperty("DataX", xVals.rawData());
+  creator.setProperty("DataY", yVals);
+  creator.setProperty("NSpec", int(nSpec));
+  creator.setProperty("UnitX", unitX);
+  creator.setPropertyValue("OutputWorkspace", "dummy");
+  creator.execute();
+  MatrixWorkspace_sptr workspace = creator.getProperty("OutputWorkspace");
+  return workspace;
+}
+
+MatrixWorkspace_sptr createREFL_WS(size_t nBins, double startX, double endX,
+                                   std::vector<double> const &values,
+                                   std::string const &paramsType) {
+  MatrixWorkspace_sptr workspace = createHistoWS(nBins, startX, endX, values);
+
+  LoadInstrument instrumentLoader;
+  instrumentLoader.initialize();
+  instrumentLoader.setPropertyValue(
+      "Filename", "IDFs_for_UNIT_TESTING/REFL_Definition.xml");
+  instrumentLoader.setProperty("Workspace", workspace);
+  instrumentLoader.setProperty("RewriteSpectraMap", OptionalBool(true));
+  instrumentLoader.execute();
+
+  if (!paramsType.empty()) {
+    LoadParameterFile paramLoader;
+    paramLoader.initialize();
+    paramLoader.setPropertyValue("Filename",
+                                 "IDFs_for_UNIT_TESTING/REFL_Parameters_" +
+                                     paramsType + ".xml");
+    paramLoader.setProperty("Workspace", workspace);
+    paramLoader.execute();
+  }
+
+  return workspace;
+}
+
+void prepareInputGroup(std::string const &name, std::string const &paramsType,
+                       size_t size, double const startX, double const endX) {
+  double monitorValue = 99.0;
+  double detectorValue = 0.9;
+  std::string names;
+
+  auto &ADS = AnalysisDataService::Instance();
+
+  for (size_t i = 0; i < size; ++i) {
+    std::vector<double> values(257, detectorValue);
+    values[0] = monitorValue;
+    MatrixWorkspace_sptr ws =
+        createREFL_WS(10, startX, endX, values, paramsType);
+    std::string const name1 = name + "_" + std::to_string(i + 1);
+    ADS.addOrReplace(name1, ws);
+    monitorValue -= 1.0;
+    detectorValue -= 0.1;
+    if (i > 0)
+      names.append(",");
+    names.append(name1);
+  }
+
+  GroupWorkspaces mkGroup;
+  mkGroup.initialize();
+  mkGroup.setProperty("InputWorkspaces", names);
+  mkGroup.setProperty("OutputWorkspace", name);
+  mkGroup.execute();
+}
+
+std::vector<MatrixWorkspace_sptr> groupToVector(WorkspaceGroup_sptr group) {
+  std::vector<MatrixWorkspace_sptr> out;
+  for (size_t i = 0; i < group->size(); ++i) {
+    out.emplace_back(
+        boost::dynamic_pointer_cast<MatrixWorkspace>(group->getItem(i)));
+  }
+  return out;
+}
+
+std::vector<MatrixWorkspace_sptr> retrieveOutWS(std::string const &name) {
+  auto group = AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>(name);
+  return groupToVector(group);
+}
+
+void applyPolarizationEfficiencies(WorkspaceGroup_sptr ws) {
+
+  auto wss = groupToVector(ws);
+  auto Rpp = wss[0];
+  auto Rpa = wss[1];
+  auto Rap = wss[2];
+  auto Raa = wss[3];
+
+  auto nBins = Rpp->blocksize();
+  auto startX = Rpp->x(0).front();
+  auto endX = Rpp->x(0).back();
+
+  auto Pp = createHistoWS(nBins, startX, endX, {0.9});
+  auto Ap = createHistoWS(nBins, startX, endX, {0.8});
+  auto Pa = createHistoWS(nBins, startX, endX, {0.7});
+  auto Aa = createHistoWS(nBins, startX, endX, {0.6});
+
+  auto Rho = Pa / Pp;
+  auto Alpha = Aa / Ap;
+
+  auto Ipp = (Rpp * (Pp + 1.0) * (Ap + 1.0) +
+              Raa * (Pp * (-1.0) + 1.0) * (Ap * (-1.0) + 1.0) +
+              Rpa * (Pp + 1.0) * (Ap * (-1.0) + 1.0) +
+              Rap * (Pp * (-1.0) + 1.0) * (Ap + 1.0)) /
+             4.;
+  auto Iaa = (Raa * (Pa + 1.0) * (Aa + 1.0) +
+              Rpp * (Pa * (-1.0) + 1.0) * (Aa * (-1.0) + 1.0) +
+              Rap * (Pa + 1.0) * (Aa * (-1.0) + 1.0) +
+              Rpa * (Pa * (-1.0) + 1.0) * (Aa + 1.0)) /
+             4.;
+  auto Ipa = (Rpa * (Pp + 1.0) * (Aa + 1.0) +
+              Rap * (Pp * (-1.0) + 1.0) * (Aa * (-1.0) + 1.0) +
+              Rpp * (Pp + 1.0) * (Aa * (-1.0) + 1.0) +
+              Raa * (Pp * (-1.0) + 1.0) * (Aa + 1.0)) /
+             4.;
+  auto Iap = (Rap * (Pa + 1.0) * (Ap + 1.0) +
+              Rpa * (Pa * (-1.0) + 1.0) * (Ap * (-1.0) + 1.0) +
+              Raa * (Pa + 1.0) * (Ap * (-1.0) + 1.0) +
+              Rpp * (Pa * (-1.0) + 1.0) * (Ap + 1.0)) /
+             4.;
+
+  auto &ADS = AnalysisDataService::Instance();
+  ADS.addOrReplace(Rpp->getName(), Ipp);
+  ADS.addOrReplace(Rpa->getName(), Ipa);
+  ADS.addOrReplace(Rap->getName(), Iap);
+  ADS.addOrReplace(Raa->getName(), Iaa);
+
+  auto instrument = Rpp->getInstrument();
+  Ipp->setInstrument(instrument);
+  Ipa->setInstrument(instrument);
+  Iap->setInstrument(instrument);
+  Iaa->setInstrument(instrument);
+}
+
+void applyPolarizationEfficiencies(std::string const &name) {
+  auto group = AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>(name);
+  applyPolarizationEfficiencies(group);
+}
+
+} // namespace TestHelpers
+} // namespace Mantid
diff --git a/MantidPlot/src/Graph.cpp b/MantidPlot/src/Graph.cpp
index a19870e6eeb2f32cc1610ea8dedbb5271761e2ef..87d333cb4b7330b5765be8584cbe071953e5bc13 100644
--- a/MantidPlot/src/Graph.cpp
+++ b/MantidPlot/src/Graph.cpp
@@ -5622,8 +5622,12 @@ void Graph::updateDataCurves() {
 void Graph::checkValuesInAxisRange(MantidMatrixCurve *mc) {
   auto *data = mc->mantidData();
   double xMin(data->x(0)); // Needs to be min of current graph (x-axis)
+  auto const dataSize = data->size();
+  if (dataSize == 0) {
+    throw std::runtime_error("Cannot draw the curve: no plottable values.");
+  }
   double xMax(
-      data->x(data->size() - 1)); // Needs to be max of current graph (x-axis)
+      data->x(dataSize - 1)); // Needs to be max of current graph (x-axis)
   if (xMin > xMax) {
     std::swap(xMin, xMax);
   }
diff --git a/Testing/SystemTests/tests/analysis/FlatPlatePaalmanPingsCorrectionTest.py b/Testing/SystemTests/tests/analysis/FlatPlatePaalmanPingsCorrectionTest.py
index 692afbe7e03bb02827bf23c47946ab43c4249b7c..c13843fe5a0bd9214a74ea12b85175e490b472b6 100644
--- a/Testing/SystemTests/tests/analysis/FlatPlatePaalmanPingsCorrectionTest.py
+++ b/Testing/SystemTests/tests/analysis/FlatPlatePaalmanPingsCorrectionTest.py
@@ -38,7 +38,7 @@ class FlatPlatePaalmanPingsCorrectionTest(stresstesting.MantidStressTest):
                                                       CanFrontThickness=can_front_thickness, CanBackThickness=can_back_thickness)
 
         LoadNexusProcessed(Filename="FlatPlatePaalmanPings_" + name + ".nxs", OutputWorkspace='ref')
-        result = CompareWorkspaces(Workspace1=FPPP_Result, Workspace2='ref', Tolerance=1e-6)
+        result = CompareWorkspaces(Workspace1=FPPP_Result, Workspace2='ref', Tolerance=1e-6, CheckInstrument=False)
         if not result[0]:
             self.assertTrue(result[0], "Mismatch in " + name + ": " + result[1].row(0)['Message'])
 
diff --git a/docs/source/algorithms/ExtractPolarizationEfficiencies-v1.rst b/docs/source/algorithms/ExtractPolarizationEfficiencies-v1.rst
new file mode 100644
index 0000000000000000000000000000000000000000..09dc9922f3d5492dc184dda2b86f9f383d92575e
--- /dev/null
+++ b/docs/source/algorithms/ExtractPolarizationEfficiencies-v1.rst
@@ -0,0 +1,36 @@
+.. algorithm::
+
+.. summary::
+
+.. relatedalgorithms::
+
+.. properties::
+
+Description
+-----------
+
+This algorithm reads polarization correction parameters from the instruments parameters file and creates an efficiency workspace ready to be used with :ref:`algm-PolarizationEfficiencyCor`. It is intended to be used as a child algorithm by the reflectometry
+reduction algorithms and not to be used directly.
+
+To work with this algorithm the parameters file must contain the following parameters (all of type `string` and in the scope of the instrument):
+
+1. `polarization_correction_method` to specify the method of correction. Possible values are `Fredrikze` and `Wildes`.
+2. `polarization_correction_option` to specify the additional property of the correction algorithm. For `Fredrikze` the possible values are those of the `PolarizationAnalysis` property. For `Wildes` they are the values of the `Flippers` property.
+3. `efficiency_lambda` is a vector of wavelengths at which the efficiencies are sampled.
+4. A set of four parameters for each of the four efficiencies stored as vectors of values at the wavelengths in `efficiency_lambda`. The names of the parameters are different for the two methods of correction: `Pp`, `Ap`, `Rho` and `Alpha` for `Fredrikze` and `P1`, `P2`, `F1` and `F2` for `Wildes`.
+
+The values in the vector parameters must be separated by spaces, for example:
+
+.. code-block:: xml
+
+  <parameter name="efficiency_lambda" type="string">
+    <value val="0 1 2 3 4 5" />
+  </parameter>
+
+.. categories::
+
+.. sourcelink::
+
+
+
+
diff --git a/docs/source/algorithms/ReflectometryReductionOne-v2.rst b/docs/source/algorithms/ReflectometryReductionOne-v2.rst
index 53545e0fb478776293b54638ca1a10899b18bf5a..0116f7f71ff330415cd5673c97a6fbdc3155f7bf 100644
--- a/docs/source/algorithms/ReflectometryReductionOne-v2.rst
+++ b/docs/source/algorithms/ReflectometryReductionOne-v2.rst
@@ -224,7 +224,7 @@ Usage
    IvsQ, IvsLam = ReflectometryReductionOne(InputWorkspace=run,
                                             WavelengthMin=1.0,
                                             WavelengthMax=17.0,
-                                            ProcessingInstructions='3:4',
+                                            ProcessingInstructions='3',
                                             I0MonitorIndex=2,
                                             MonitorBackgroundWavelengthMin=15.0,
                                             MonitorBackgroundWavelengthMax=17.0,
@@ -258,7 +258,7 @@ Output:
    IvsQ, IvsLam = ReflectometryReductionOne(InputWorkspace=run,
                                             WavelengthMin=1.0,
                                             WavelengthMax=17.0,
-                                            ProcessingInstructions='3-4',
+                                            ProcessingInstructions='3',
                                             I0MonitorIndex=2,
                                             MonitorBackgroundWavelengthMin=15.0,
                                             MonitorBackgroundWavelengthMax=17.0,
diff --git a/docs/source/release/v3.13.0/reflectometry.rst b/docs/source/release/v3.13.0/reflectometry.rst
index fd0736526830dff1a8a3a20d24826850eba1fd90..2a8b10d5b61252d87ac05fa2f35f38a897bbdc93 100644
--- a/docs/source/release/v3.13.0/reflectometry.rst
+++ b/docs/source/release/v3.13.0/reflectometry.rst
@@ -17,6 +17,7 @@ New
 
 - Fully-automatic processing has been added to the interface. Click ``Autoprocess`` to process all of the runs for an investigation and to start polling for new runs. Whenever new runs are found, they will automatically be added to the table and processed.
 - A new option has been added to the Settings tab to control whether partial bins should be included when summing in Q.
+- ``ReflectometryReductionOneAuto`` takes the polarization correction properties from the instrument parameter file when ``PolarizationAnalysis`` is set to ``ParameterFile``. The instrument parameter file can store the efficiencies as vectors of doubles.
 
 Improvements
 ############
diff --git a/instrument/IDFs_for_UNIT_TESTING/REFL_Definition.xml b/instrument/IDFs_for_UNIT_TESTING/REFL_Definition.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2a921ba53bf8c7130fa680b2af9f0c7d0e467e4a
--- /dev/null
+++ b/instrument/IDFs_for_UNIT_TESTING/REFL_Definition.xml
@@ -0,0 +1,96 @@
+<?xml version='1.0' encoding='ASCII'?>
+<instrument name="REFL" valid-from   ="1900-01-31 23:59:59"
+                        valid-to     ="2100-01-31 23:59:59"
+        last-modified="2010-10-01 09:56:20.177358">
+
+  <defaults>
+    <length unit="meter" />
+    <angle unit="degree" />
+    <reference-frame>
+      <along-beam axis="z" />
+      <pointing-up axis="y" />
+      <handedness val="right" />
+    </reference-frame>
+    <components-are-facing x="0.0" y="0.0" z="0.0" />
+  </defaults>
+ 
+  <!-- source and sample-position components -->
+
+  <component type="source">
+    <location z="-23.83" />
+  </component>
+  <type name="source" is="Source"/>
+   
+  <component type="some-surface-holder">
+    <location x="0.0" y="0.0" z="0.0" />
+  </component>
+  <type name="some-surface-holder" is="SamplePos"/>
+  
+  <!-- LIST OF PHYSICAL COMPONENTS (which the instrument consists of) -->
+
+  <!-- detector components (including monitors) -->
+
+  <component type="monitor1" idlist="monitor1">
+    <location r="11.38" t="180.0" />
+  </component>
+
+  <type name="monitor1" is="monitor">
+    <percent-transparency val="95" />
+    <cylinder id="shape">
+      <centre-of-bottom-base x="0.0" y="-0.02" z="0.0" />
+      <axis x="0.0" y="1.0" z="0.0" /> 
+      <radius val="0.015" />
+      <height val="0.04" />
+    </cylinder> 
+    <algebra val="shape" />
+  </type>  
+
+   <component type="LinearDetector" idlist="LinearDetector">
+     <location z="3.65" /> 
+   </component>
+
+  <type name="LinearDetector">
+  <component type="pixel">
+    <locations y="-0.1301" y-end="0.1771" n-elements="256" />
+  </component>
+  </type>
+
+  <type name="pixel" is="detector">
+    <cuboid id="shape">
+      <left-front-bottom-point x="-0.025" y="-0.0006" z="0.0"  />
+      <left-front-top-point  x="-0.025" y="0.0006" z="0.0"  />
+      <left-back-bottom-point  x="-0.025" y="-0.0006" z="0.05"  />
+      <right-front-bottom-point  x="0.025" y="-0.0006" z="0.0"  />
+    </cuboid>
+    <algebra val="shape" />
+  </type>
+
+  <component type="point-detector" idlist="point-detector">
+     <location z="3.19" /> 
+  </component>   
+
+  <type name="point-detector" is="detector">
+    <cylinder id="shape">
+      <centre-of-bottom-base x="-0.05" y="0.0" z="0.0" />
+      <axis x="1.0" y="0.0" z="0.0" /> 
+      <radius val="0.005" />
+      <height val="0.1" />
+    </cylinder> 
+    <algebra val="shape" />
+  </type>    
+
+  <!-- DETECTOR and MONITOR ID LISTS -->
+
+  <idlist idname="monitor1">
+    <id val="1" />  
+  </idlist>
+
+  <idlist idname="LinearDetector">
+    <id start="1001" end="1256" />
+  </idlist>
+
+  <idlist idname="point-detector">
+    <id val="2000" />
+  </idlist>
+
+</instrument>
diff --git a/instrument/IDFs_for_UNIT_TESTING/REFL_Parameters.xml b/instrument/IDFs_for_UNIT_TESTING/REFL_Parameters.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a49b96715afcb96fd9d764ea170e89e520360f5c
--- /dev/null
+++ b/instrument/IDFs_for_UNIT_TESTING/REFL_Parameters.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<parameter-file instrument="REFL" valid-from="forever">
+
+<component-link name="REFL" >
+
+  <parameter name="dummy" type="string">
+    <value val="No parameters here" />
+  </parameter>
+
+</component-link>
+
+</parameter-file>
diff --git a/instrument/IDFs_for_UNIT_TESTING/REFL_Parameters_Fredrikze.xml b/instrument/IDFs_for_UNIT_TESTING/REFL_Parameters_Fredrikze.xml
new file mode 100644
index 0000000000000000000000000000000000000000..05744ae854290f426daec4323d5da735219f3f8e
--- /dev/null
+++ b/instrument/IDFs_for_UNIT_TESTING/REFL_Parameters_Fredrikze.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<parameter-file instrument="REFL" valid-from="forever">
+
+<component-link name="REFL" >
+
+  <parameter name="polarization_correction_method" type="string">
+    <value val="Fredrikze" />
+  </parameter>
+
+  <parameter name="polarization_correction_option" type="string">
+    <value val="PA" />
+  </parameter>
+
+  <parameter name="efficiency_lambda" type="string">
+    <value val="0 3 6 10 15 20" />
+    <description is="The wavelengths at which the efficiencies are sampled."/>
+  </parameter>
+
+  <parameter name="Pp" type="string">
+    <value val="0.9 0.9 0.9 0.9 0.9 0.9" />
+    <description is="The values of the Pp efficiency."/>
+  </parameter>
+
+  <parameter name="Ap" type="string">
+    <value val="0.8 0.8 0.8 0.8 0.8 0.8" />
+    <description is="The values of the Ap efficiency."/>
+  </parameter>
+
+  <parameter name="Rho" type="string">
+    <value val="0.778 0.778 0.778 0.778 0.778 0.778" />
+    <description is="The values of the Rho efficiency."/>
+  </parameter>
+
+  <parameter name="Alpha" type="string">
+    <value val="0.75 0.75 0.75 0.75 0.75 0.75" />
+    <description is="The values of the Alpha efficiency."/>
+  </parameter>
+
+</component-link>
+
+</parameter-file>
diff --git a/qt/scientific_interfaces/ISISReflectometry/QtReflSettingsView.cpp b/qt/scientific_interfaces/ISISReflectometry/QtReflSettingsView.cpp
index 8e9786a59b3b95eb602f0274d635a54d6e734d24..7de74eb2ba9eac031ee02f746a9e7ed2cb401ae5 100644
--- a/qt/scientific_interfaces/ISISReflectometry/QtReflSettingsView.cpp
+++ b/qt/scientific_interfaces/ISISReflectometry/QtReflSettingsView.cpp
@@ -52,6 +52,8 @@ void QtReflSettingsView::initLayout() {
           SLOT(addPerAngleOptionsTableRow()));
   connect(m_ui.correctDetectorsCheckBox, SIGNAL(clicked(bool)), this,
           SLOT(setDetectorCorrectionEnabled(bool)));
+  connect(m_ui.polCorrComboBox, SIGNAL(currentIndexChanged(int)), this,
+          SLOT(setPolCorPageForIndex(int)));
 }
 
 void QtReflSettingsView::initOptionsTable() {
@@ -692,5 +694,18 @@ bool QtReflSettingsView::instrumentSettingsEnabled() const {
   return m_ui.instSettingsGroup->isChecked();
 }
 
+/**
+  Set the current page index of m_ui.polCorStackedWidget depending on the index
+  of m_ui.polCorrComboBox. They don't match 1-to-1 because PA and PNR options
+  share a page.
+  @param index :: New current index of m_ui.polCorrComboBox.
+ */
+void QtReflSettingsView::setPolCorPageForIndex(int index) {
+  assert(m_ui.polCorrComboBox->count() == 4);
+  assert(m_ui.polCorStackedWidget->count() == 3);
+  static std::array<int, 4> const indexMap = {{0, 1, 1, 2}};
+  m_ui.polCorStackedWidget->setCurrentIndex(indexMap[index]);
+}
+
 } // namespace CustomInterfaces
 } // namespace Mantid
diff --git a/qt/scientific_interfaces/ISISReflectometry/QtReflSettingsView.h b/qt/scientific_interfaces/ISISReflectometry/QtReflSettingsView.h
index 3a7b7fc326aa0b30e6dc17c39688f08a71a4c621..cdc8023347f0de6243a8f065a849179132c0c34f 100644
--- a/qt/scientific_interfaces/ISISReflectometry/QtReflSettingsView.h
+++ b/qt/scientific_interfaces/ISISReflectometry/QtReflSettingsView.h
@@ -136,6 +136,9 @@ public slots:
   /// Adds another row to the per-angle options table
   void addPerAngleOptionsTableRow();
 
+private slots:
+  void setPolCorPageForIndex(int index);
+
 private:
   /// Initialise the interface
   void initLayout();
diff --git a/qt/scientific_interfaces/ISISReflectometry/ReflGenericDataProcessorPresenterFactory.cpp b/qt/scientific_interfaces/ISISReflectometry/ReflGenericDataProcessorPresenterFactory.cpp
index 7f59700922f411d4c158ef1d848822d31233e334..148699c2b7fe61421fc832470dea93095c22bb5e 100644
--- a/qt/scientific_interfaces/ISISReflectometry/ReflGenericDataProcessorPresenterFactory.cpp
+++ b/qt/scientific_interfaces/ISISReflectometry/ReflGenericDataProcessorPresenterFactory.cpp
@@ -113,7 +113,7 @@ ReflGenericDataProcessorPresenterFactory::create(int group) {
 
   return Mantid::Kernel::make_unique<ReflDataProcessorPresenter>(
       whitelist, preprocessMap, processor, postprocessor, group, postprocessMap,
-      "LoadISISNexus");
+      "LoadNexus");
 }
 }
 }
diff --git a/qt/scientific_interfaces/ISISReflectometry/ReflSettingsPresenter.cpp b/qt/scientific_interfaces/ISISReflectometry/ReflSettingsPresenter.cpp
index c82d0fc04985850bfd2408f81544e4de52f40fb3..4478d6e5d4bc9100a45f8d305ef1304b935f2461 100644
--- a/qt/scientific_interfaces/ISISReflectometry/ReflSettingsPresenter.cpp
+++ b/qt/scientific_interfaces/ISISReflectometry/ReflSettingsPresenter.cpp
@@ -220,12 +220,17 @@ OptionsQMap ReflSettingsPresenter::getReductionOptions() const {
 
   if (m_view->experimentSettingsEnabled()) {
     addIfNotEmpty(options, "AnalysisMode", m_view->getAnalysisMode());
-    addIfNotEmpty(options, "Rho", m_view->getCRho());
-    addIfNotEmpty(options, "Alpha", m_view->getCAlpha());
-    addIfNotEmpty(options, "Ap", m_view->getCAp());
-    addIfNotEmpty(options, "Pp", m_view->getCPp());
-    addIfNotEmpty(options, "PolarizationAnalysis",
-                  m_view->getPolarisationCorrections());
+    auto const pa = m_view->getPolarisationCorrections();
+    addIfNotEmpty(options, "PolarizationAnalysis", pa);
+    if (pa == "PA") {
+      addIfNotEmpty(options, "Rho", m_view->getCRho());
+      addIfNotEmpty(options, "Alpha", m_view->getCAlpha());
+      addIfNotEmpty(options, "Ap", m_view->getCAp());
+      addIfNotEmpty(options, "Pp", m_view->getCPp());
+    } else if (pa == "PNR") {
+      addIfNotEmpty(options, "Ap", m_view->getCAp());
+      addIfNotEmpty(options, "Pp", m_view->getCPp());
+    }
     addIfNotEmpty(options, "StartOverlap", m_view->getStartOverlap());
     addIfNotEmpty(options, "EndOverlap", m_view->getEndOverlap());
 
diff --git a/qt/scientific_interfaces/ISISReflectometry/ReflSettingsWidget.ui b/qt/scientific_interfaces/ISISReflectometry/ReflSettingsWidget.ui
index bce5c37873d7e74d47dd89a0ea49b75c91ad6d34..32146ba02ce413f9881836f5218a6532f3d1c651 100644
--- a/qt/scientific_interfaces/ISISReflectometry/ReflSettingsWidget.ui
+++ b/qt/scientific_interfaces/ISISReflectometry/ReflSettingsWidget.ui
@@ -27,16 +27,7 @@
    <string>Settings Tab</string>
   </property>
   <layout class="QVBoxLayout" name="settingsMainLayout" stretch="1,1">
-   <property name="leftMargin">
-    <number>5</number>
-   </property>
-   <property name="topMargin">
-    <number>5</number>
-   </property>
-   <property name="rightMargin">
-    <number>5</number>
-   </property>
-   <property name="bottomMargin">
+   <property name="margin">
     <number>5</number>
    </property>
    <item>
@@ -49,219 +40,11 @@
      </property>
      <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="10,2">
       <item>
-       <layout class="QGridLayout" name="expSettingsLayout0" rowstretch="1,1,1,1,1,1,1,1,0,0,0,0" columnstretch="1,1,1,1">
-        <property name="leftMargin">
-         <number>10</number>
-        </property>
-        <property name="topMargin">
-         <number>10</number>
-        </property>
-        <property name="rightMargin">
-         <number>10</number>
-        </property>
-        <property name="bottomMargin">
+       <layout class="QGridLayout" name="expSettingsLayout0" rowstretch="1,0,0,0,0,0,0,0,0,0" columnstretch="0,0,0,0">
+        <property name="margin">
          <number>10</number>
         </property>
-        <item row="10" column="1">
-         <widget class="QLineEdit" name="CApEdit"/>
-        </item>
-        <item row="1" column="0">
-         <widget class="QLabel" name="summationTypeLabel">
-          <property name="minimumSize">
-           <size>
-            <width>117</width>
-            <height>0</height>
-           </size>
-          </property>
-          <property name="text">
-           <string>SummationType</string>
-          </property>
-         </widget>
-        </item>
-        <item row="10" column="0">
-         <widget class="QLabel" name="CApLabel">
-          <property name="text">
-           <string>CAp</string>
-          </property>
-         </widget>
-        </item>
-        <item row="8" column="0">
-         <widget class="QLabel" name="polCorrLabel">
-          <property name="minimumSize">
-           <size>
-            <width>117</width>
-            <height>0</height>
-           </size>
-          </property>
-          <property name="text">
-           <string>PolarisationCorrections</string>
-          </property>
-         </widget>
-        </item>
-        <item row="0" column="0">
-         <widget class="QLabel" name="analysisModeLabel">
-          <property name="text">
-           <string>AnalysisMode</string>
-          </property>
-         </widget>
-        </item>
-        <item row="3" column="0">
-         <widget class="QLabel" name="perAngleTableLabel">
-          <property name="text">
-           <string>Per-angle defaults</string>
-          </property>
-          <property name="alignment">
-           <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
-          </property>
-         </widget>
-        </item>
-        <item row="1" column="1">
-         <widget class="QComboBox" name="summationTypeComboBox">
-          <property name="sizePolicy">
-           <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
-            <horstretch>0</horstretch>
-            <verstretch>0</verstretch>
-           </sizepolicy>
-          </property>
-          <item>
-           <property name="text">
-            <string>SumInLambda</string>
-           </property>
-          </item>
-          <item>
-           <property name="text">
-            <string>SumInQ</string>
-           </property>
-          </item>
-         </widget>
-        </item>
-        <item row="9" column="0">
-         <widget class="QLabel" name="CRhoLabel">
-          <property name="text">
-           <string>CRho</string>
-          </property>
-         </widget>
-        </item>
-        <item row="0" column="1">
-         <widget class="QComboBox" name="analysisModeComboBox">
-          <property name="sizePolicy">
-           <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
-            <horstretch>0</horstretch>
-            <verstretch>0</verstretch>
-           </sizepolicy>
-          </property>
-          <item>
-           <property name="text">
-            <string>PointDetectorAnalysis</string>
-           </property>
-          </item>
-          <item>
-           <property name="text">
-            <string>MultiDetectorAnalysis</string>
-           </property>
-          </item>
-         </widget>
-        </item>
-        <item row="8" column="1">
-         <widget class="QComboBox" name="polCorrComboBox">
-          <property name="sizePolicy">
-           <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
-            <horstretch>0</horstretch>
-            <verstretch>0</verstretch>
-           </sizepolicy>
-          </property>
-          <item>
-           <property name="text">
-            <string>None</string>
-           </property>
-          </item>
-          <item>
-           <property name="text">
-            <string>PA</string>
-           </property>
-          </item>
-          <item>
-           <property name="text">
-            <string>PNR</string>
-           </property>
-          </item>
-         </widget>
-        </item>
-        <item row="9" column="3">
-         <widget class="QLineEdit" name="CAlphaEdit"/>
-        </item>
-        <item row="10" column="2">
-         <widget class="QLabel" name="CPpLabel">
-          <property name="minimumSize">
-           <size>
-            <width>117</width>
-            <height>0</height>
-           </size>
-          </property>
-          <property name="text">
-           <string>CPp</string>
-          </property>
-         </widget>
-        </item>
-        <item row="9" column="1">
-         <widget class="QLineEdit" name="CRhoEdit"/>
-        </item>
-        <item row="10" column="3">
-         <widget class="QLineEdit" name="CPpEdit"/>
-        </item>
-        <item row="9" column="2">
-         <widget class="QLabel" name="CAlphaLabel">
-          <property name="minimumSize">
-           <size>
-            <width>117</width>
-            <height>0</height>
-           </size>
-          </property>
-          <property name="text">
-           <string>CAlpha</string>
-          </property>
-         </widget>
-        </item>
-        <item row="6" column="1">
-         <widget class="QPushButton" name="addPerAngleOptionsButton">
-          <property name="toolTip">
-           <string>Add another row to the per-angle options table</string>
-          </property>
-          <property name="whatsThis">
-           <string>Adds another row to the per-angle options table so that additional angles can be added</string>
-          </property>
-          <property name="text">
-           <string>Add row</string>
-          </property>
-         </widget>
-        </item>
-        <item row="7" column="0">
-         <widget class="QLabel" name="startOverlapLabel">
-          <property name="text">
-           <string>TransRunStartOverlap</string>
-          </property>
-         </widget>
-        </item>
-        <item row="7" column="1">
-         <widget class="QLineEdit" name="startOverlapEdit"/>
-        </item>
-        <item row="7" column="2">
-         <widget class="QLabel" name="endOverlapLabel">
-          <property name="minimumSize">
-           <size>
-            <width>117</width>
-            <height>0</height>
-           </size>
-          </property>
-          <property name="text">
-           <string>TransRunEndOverlap</string>
-          </property>
-         </widget>
-        </item>
-        <item row="7" column="3">
-         <widget class="QLineEdit" name="endOverlapEdit"/>
-        </item>
-        <item row="3" column="1" rowspan="3" colspan="3">
+        <item row="3" column="1" rowspan="2" colspan="3">
          <widget class="QTableWidget" name="optionsTable">
           <property name="sizePolicy">
            <sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
@@ -360,15 +143,41 @@
           </column>
          </widget>
         </item>
-        <item row="11" column="0">
-         <widget class="QLabel" name="stitchLabel">
+        <item row="6" column="2">
+         <widget class="QLabel" name="endOverlapLabel">
+          <property name="minimumSize">
+           <size>
+            <width>117</width>
+            <height>0</height>
+           </size>
+          </property>
           <property name="text">
-           <string>Stitch1DMany</string>
+           <string>TransRunEndOverlap</string>
           </property>
          </widget>
         </item>
-        <item row="2" column="0">
-         <widget class="QLabel" name="reductionTypeLabel">
+        <item row="0" column="1">
+         <widget class="QComboBox" name="analysisModeComboBox">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <item>
+           <property name="text">
+            <string>PointDetectorAnalysis</string>
+           </property>
+          </item>
+          <item>
+           <property name="text">
+            <string>MultiDetectorAnalysis</string>
+           </property>
+          </item>
+         </widget>
+        </item>
+        <item row="1" column="0">
+         <widget class="QLabel" name="summationTypeLabel">
           <property name="minimumSize">
            <size>
             <width>117</width>
@@ -376,10 +185,195 @@
            </size>
           </property>
           <property name="text">
-           <string>ReductionType</string>
+           <string>SummationType</string>
+          </property>
+         </widget>
+        </item>
+        <item row="8" column="1">
+         <widget class="QComboBox" name="polCorrComboBox">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <item>
+           <property name="text">
+            <string>None</string>
+           </property>
+          </item>
+          <item>
+           <property name="text">
+            <string>PA</string>
+           </property>
+          </item>
+          <item>
+           <property name="text">
+            <string>PNR</string>
+           </property>
+          </item>
+          <item>
+           <property name="text">
+            <string>ParameterFile</string>
+           </property>
+          </item>
+         </widget>
+        </item>
+        <item row="0" column="0">
+         <widget class="QLabel" name="analysisModeLabel">
+          <property name="text">
+           <string>AnalysisMode</string>
+          </property>
+         </widget>
+        </item>
+        <item row="5" column="1">
+         <widget class="QPushButton" name="addPerAngleOptionsButton">
+          <property name="toolTip">
+           <string>Add another row to the per-angle options table</string>
+          </property>
+          <property name="whatsThis">
+           <string>Adds another row to the per-angle options table so that additional angles can be added</string>
+          </property>
+          <property name="text">
+           <string>Add row</string>
+          </property>
+         </widget>
+        </item>
+        <item row="6" column="1">
+         <widget class="QLineEdit" name="startOverlapEdit"/>
+        </item>
+        <item row="6" column="3">
+         <widget class="QLineEdit" name="endOverlapEdit"/>
+        </item>
+        <item row="3" column="0">
+         <widget class="QLabel" name="perAngleTableLabel">
+          <property name="text">
+           <string>Per-angle defaults</string>
+          </property>
+          <property name="alignment">
+           <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="1">
+         <widget class="QComboBox" name="summationTypeComboBox">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <item>
+           <property name="text">
+            <string>SumInLambda</string>
+           </property>
+          </item>
+          <item>
+           <property name="text">
+            <string>SumInQ</string>
+           </property>
+          </item>
+         </widget>
+        </item>
+        <item row="8" column="0">
+         <widget class="QLabel" name="polCorrLabel">
+          <property name="minimumSize">
+           <size>
+            <width>117</width>
+            <height>0</height>
+           </size>
+          </property>
+          <property name="text">
+           <string>PolarisationCorrections</string>
+          </property>
+         </widget>
+        </item>
+        <item row="6" column="0">
+         <widget class="QLabel" name="startOverlapLabel">
+          <property name="text">
+           <string>TransRunStartOverlap</string>
           </property>
          </widget>
         </item>
+        <item row="9" column="0" colspan="4">
+         <widget class="QStackedWidget" name="polCorStackedWidget">
+          <property name="currentIndex">
+           <number>0</number>
+          </property>
+          <widget class="QWidget" name="pageNone"/>
+          <widget class="QWidget" name="pagePA_PNR">
+           <layout class="QVBoxLayout" name="verticalLayout">
+            <item>
+             <layout class="QGridLayout" name="gridLayout">
+              <item row="0" column="2">
+               <widget class="QLabel" name="CPpLabel">
+                <property name="minimumSize">
+                 <size>
+                  <width>117</width>
+                  <height>0</height>
+                 </size>
+                </property>
+                <property name="text">
+                 <string>CPp</string>
+                </property>
+               </widget>
+              </item>
+              <item row="0" column="0">
+               <widget class="QLabel" name="CApLabel">
+                <property name="text">
+                 <string>CAp</string>
+                </property>
+               </widget>
+              </item>
+              <item row="0" column="3">
+               <widget class="QLineEdit" name="CPpEdit"/>
+              </item>
+              <item row="0" column="1">
+               <widget class="QLineEdit" name="CApEdit"/>
+              </item>
+              <item row="1" column="0">
+               <widget class="QLabel" name="CAlphaLabel">
+                <property name="minimumSize">
+                 <size>
+                  <width>117</width>
+                  <height>0</height>
+                 </size>
+                </property>
+                <property name="text">
+                 <string>CAlpha</string>
+                </property>
+               </widget>
+              </item>
+              <item row="1" column="1">
+               <widget class="QLineEdit" name="CRhoEdit"/>
+              </item>
+              <item row="1" column="2">
+               <widget class="QLabel" name="CRhoLabel">
+                <property name="text">
+                 <string>CRho</string>
+                </property>
+               </widget>
+              </item>
+              <item row="1" column="3">
+               <widget class="QLineEdit" name="CAlphaEdit"/>
+              </item>
+             </layout>
+            </item>
+           </layout>
+          </widget>
+          <widget class="QWidget" name="pageParamFile">
+           <layout class="QHBoxLayout" name="horizontalLayout_3">
+            <item>
+             <widget class="QLabel" name="label">
+              <property name="text">
+               <string>Use parameters from the instrument parameter file</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </widget>
+        </item>
         <item row="2" column="1">
          <widget class="QComboBox" name="reductionTypeComboBox">
           <property name="enabled">
@@ -408,26 +402,40 @@
           </item>
          </widget>
         </item>
+        <item row="2" column="2">
+         <widget class="QLabel" name="stitchLabel">
+          <property name="text">
+           <string>IncludePartialBins</string>
+          </property>
+         </widget>
+        </item>
         <item row="2" column="3">
          <widget class="QCheckBox" name="includePartialBinsCheckBox">
           <property name="enabled">
            <bool>false</bool>
           </property>
-          <property name="toolTip">
-           <string>If true then partial bins from the beginning and end of the output range are included</string>
+          <property name="text">
+           <string/>
           </property>
-          <property name="whatsThis">
-           <string>When summing in Q, this option controls whether counts from the input range should be included in the output if they would result in partially filled bins, that is, where the intensity in the output bin is not the true intensity because not all of the input for that line of constant Q was available in the input range. By default, this option is off, and any partial bins are excluded.</string>
+         </widget>
+        </item>
+        <item row="2" column="0">
+         <widget class="QLabel" name="reductionTypeLabel">
+          <property name="minimumSize">
+           <size>
+            <width>117</width>
+            <height>0</height>
+           </size>
           </property>
           <property name="text">
-           <string/>
+           <string>ReductionType</string>
           </property>
          </widget>
         </item>
-        <item row="2" column="2">
-         <widget class="QLabel" name="includePartialBinsLabel">
+        <item row="7" column="0">
+         <widget class="QLabel" name="stitchLabel_2">
           <property name="text">
-           <string>IncludePartialBins</string>
+           <string>Stitch1DMany</string>
           </property>
          </widget>
         </item>
@@ -472,17 +480,8 @@
      </property>
      <layout class="QHBoxLayout" name="horizontalLayout" stretch="10,2">
       <item>
-       <layout class="QGridLayout" name="instSettingsLayout0" rowstretch="1,1,1,1,1,1" columnstretch="1,1,1,1">
-        <property name="leftMargin">
-         <number>10</number>
-        </property>
-        <property name="topMargin">
-         <number>10</number>
-        </property>
-        <property name="rightMargin">
-         <number>10</number>
-        </property>
-        <property name="bottomMargin">
+       <layout class="QGridLayout" name="instSettingsLayout0" rowstretch="1,1,1,1,1,1" columnstretch="0,1,0,1">
+        <property name="margin">
          <number>10</number>
         </property>
         <item row="5" column="0">
diff --git a/qt/scientific_interfaces/test/ReflSettingsPresenterTest.h b/qt/scientific_interfaces/test/ReflSettingsPresenterTest.h
index 2a62575dc4370038139fb528a895526dca021a90..c57e5c4439b06a95d74aa85713ddd9c287e479c2 100644
--- a/qt/scientific_interfaces/test/ReflSettingsPresenterTest.h
+++ b/qt/scientific_interfaces/test/ReflSettingsPresenterTest.h
@@ -189,12 +189,6 @@ public:
     EXPECT_CALL(mockView, getPolarisationCorrections())
         .Times(AtLeast(1))
         .WillOnce(Return("PNR"));
-    EXPECT_CALL(mockView, getCRho())
-        .Times(AtLeast(1))
-        .WillOnce(Return("2.5,0.4,1.1"));
-    EXPECT_CALL(mockView, getCAlpha())
-        .Times(AtLeast(1))
-        .WillOnce(Return("0.6,0.9,1.2"));
     EXPECT_CALL(mockView, getCAp())
         .Times(AtLeast(1))
         .WillOnce(Return("100.0,17.0,44.0"));
@@ -204,8 +198,8 @@ public:
 
     auto options = presenter.getReductionOptions();
     TS_ASSERT_EQUALS(variantToString(options["PolarizationAnalysis"]), "PNR");
-    TS_ASSERT_EQUALS(variantToString(options["Rho"]), "2.5,0.4,1.1");
-    TS_ASSERT_EQUALS(variantToString(options["Alpha"]), "0.6,0.9,1.2");
+    TS_ASSERT_EQUALS(variantToString(options["Rho"]), "");
+    TS_ASSERT_EQUALS(variantToString(options["Alpha"]), "");
     TS_ASSERT_EQUALS(variantToString(options["Ap"]), "100.0,17.0,44.0");
     TS_ASSERT_EQUALS(variantToString(options["Pp"]), "0.54,0.33,1.81");
 
@@ -542,10 +536,10 @@ public:
 
     // Experiment settings should be called
     EXPECT_CALL(mockView, getAnalysisMode()).Times(Exactly(2));
-    EXPECT_CALL(mockView, getCRho()).Times(Exactly(1));
-    EXPECT_CALL(mockView, getCAlpha()).Times(Exactly(1));
-    EXPECT_CALL(mockView, getCAp()).Times(Exactly(1));
-    EXPECT_CALL(mockView, getCPp()).Times(Exactly(1));
+    EXPECT_CALL(mockView, getCRho()).Times(Exactly(0));
+    EXPECT_CALL(mockView, getCAlpha()).Times(Exactly(0));
+    EXPECT_CALL(mockView, getCAp()).Times(Exactly(0));
+    EXPECT_CALL(mockView, getCPp()).Times(Exactly(0));
     EXPECT_CALL(mockView, getPolarisationCorrections()).Times(Exactly(1));
     EXPECT_CALL(mockView, getStartOverlap()).Times(Exactly(2));
     EXPECT_CALL(mockView, getEndOverlap()).Times(Exactly(2));