diff --git a/Framework/Algorithms/src/CorrectKiKf.cpp b/Framework/Algorithms/src/CorrectKiKf.cpp
index e4eeb280e902cd704b760b930ffb9ccb9ab0a944..9cc3b2dc48b7a40598a1162f38dda94193f1a6c8 100644
--- a/Framework/Algorithms/src/CorrectKiKf.cpp
+++ b/Framework/Algorithms/src/CorrectKiKf.cpp
@@ -67,9 +67,9 @@ void CorrectKiKf::exec() {
   }
 
   // If input and output workspaces are not the same, create a new workspace for
-  // the output
+  // the output using the clone method to account for different workspace types
   if (outputWS != inputWS) {
-    outputWS = create<MatrixWorkspace>(*inputWS);
+    outputWS = inputWS->clone();
   }
 
   const size_t size = inputWS->blocksize();
diff --git a/Framework/Algorithms/src/Rebin2D.cpp b/Framework/Algorithms/src/Rebin2D.cpp
index 1d0d922a26f74d18dd454224a7d9f0f5a4404ac5..8301c3292612451ade37a55d912988c65bc9c984 100644
--- a/Framework/Algorithms/src/Rebin2D.cpp
+++ b/Framework/Algorithms/src/Rebin2D.cpp
@@ -155,7 +155,8 @@ void Rebin2D::exec() {
   }
   PARALLEL_CHECK_INTERUPT_REGION
   if (useFractionalArea) {
-    outputRB->finalize(true, true);
+    FractionalRebinning::finalizeFractionalRebin(*outputRB);
+    outputRB->finalize(true);
   }
 
   FractionalRebinning::normaliseOutput(outputWS, inputWS, m_progress.get());
diff --git a/Framework/Algorithms/src/SofQWNormalisedPolygon.cpp b/Framework/Algorithms/src/SofQWNormalisedPolygon.cpp
index 56e9482ab0b39815ce80aedac63badc5d77aea32..e18a314c97e1b38a95457d50097c9c14cff13dde 100644
--- a/Framework/Algorithms/src/SofQWNormalisedPolygon.cpp
+++ b/Framework/Algorithms/src/SofQWNormalisedPolygon.cpp
@@ -461,6 +461,7 @@ void SofQWNormalisedPolygon::exec() {
   }
   PARALLEL_CHECK_INTERUPT_REGION
 
+  FractionalRebinning::finalizeFractionalRebin(*outputWS);
   outputWS->finalize();
   FractionalRebinning::normaliseOutput(outputWS, inputWS, m_progress.get());
 
diff --git a/Framework/Algorithms/src/SumSpectra.cpp b/Framework/Algorithms/src/SumSpectra.cpp
index 856e4d87864b6ce0e21a826cae29642cf03dfd28..709247612b0812a9834b8ba8a3ef1cc755b808dc 100644
--- a/Framework/Algorithms/src/SumSpectra.cpp
+++ b/Framework/Algorithms/src/SumSpectra.cpp
@@ -165,6 +165,10 @@ void SumSpectra::init() {
   setPropertySettings(
       "MultiplyBySpectra",
       std::make_unique<EnabledWhenProperty>("WeightedSum", IS_EQUAL_TO, "1"));
+
+  declareProperty("UseFractionalArea", true,
+                  "Normalize the output workspace to the fractional area for "
+                  "RebinnedOutput workspaces.");
 }
 
 /*
@@ -520,6 +524,10 @@ void SumSpectra::doFractionalSum(MatrixWorkspace_sptr outputWorkspace,
   RebinnedOutput_sptr outWS =
       boost::dynamic_pointer_cast<RebinnedOutput>(outputWorkspace);
 
+  // Check finalize state prior to the sum process, at the completion
+  // the output is unfinalized
+  auto isFinalized = inWS->isFinalized();
+
   // Get references to the output workspaces's data vectors
   auto &outSpec = outputWorkspace->getSpectrum(0);
   auto &YSum = outSpec.mutableY();
@@ -548,21 +556,22 @@ void SumSpectra::doFractionalSum(MatrixWorkspace_sptr outputWorkspace,
     if (m_calculateWeightedSum) {
       for (size_t yIndex = 0; yIndex < m_yLength; ++yIndex) {
         const double yErrorsVal = YErrors[yIndex];
+        const double fracVal = (isFinalized ? FracArea[yIndex] : 1.0);
         if (std::isnormal(yErrorsVal)) { // is non-zero, nan, or infinity
-          const double errsq =
-              yErrorsVal * yErrorsVal * FracArea[yIndex] * FracArea[yIndex];
+          const double errsq = yErrorsVal * yErrorsVal * fracVal * fracVal;
           YErrorSum[yIndex] += errsq;
           Weight[yIndex] += 1. / errsq;
-          YSum[yIndex] += YValues[yIndex] * FracArea[yIndex] / errsq;
+          YSum[yIndex] += YValues[yIndex] * fracVal / errsq;
         } else {
           nZeros[yIndex]++;
         }
       }
     } else {
       for (size_t yIndex = 0; yIndex < m_yLength; ++yIndex) {
-        YSum[yIndex] += YValues[yIndex] * FracArea[yIndex];
-        YErrorSum[yIndex] += YErrors[yIndex] * YErrors[yIndex] *
-                             FracArea[yIndex] * FracArea[yIndex];
+        const double fracVal = (isFinalized ? FracArea[yIndex] : 1.0);
+        YSum[yIndex] += YValues[yIndex] * fracVal;
+        YErrorSum[yIndex] +=
+            YErrors[yIndex] * YErrors[yIndex] * fracVal * fracVal;
       }
     }
     // accumulation of fractional weight is the same
@@ -583,8 +592,11 @@ void SumSpectra::doFractionalSum(MatrixWorkspace_sptr outputWorkspace,
     numZeros = 0;
   }
 
-  // Create the correct representation
-  outWS->finalize();
+  // Create the correct representation if using fractional area
+  auto useFractionalArea = getProperty("UseFractionalArea");
+  if (useFractionalArea) {
+    outWS->finalize();
+  }
 }
 
 /** Executes the algorithm
diff --git a/Framework/Algorithms/test/SumSpectraTest.h b/Framework/Algorithms/test/SumSpectraTest.h
index 9b788614fb39d0b4a404da52ca29c360f67f5308..4f6b59606eb21cdea1cc6e2410d79552b32f68fa 100644
--- a/Framework/Algorithms/test/SumSpectraTest.h
+++ b/Framework/Algorithms/test/SumSpectraTest.h
@@ -342,28 +342,52 @@ public:
     RebinnedOutput_sptr output;
     output =
         AnalysisDataService::Instance().retrieveWS<RebinnedOutput>(outName);
-    TS_ASSERT(output);
-    TS_ASSERT_EQUALS(output->getNumberHistograms(), 1);
-    TS_ASSERT_EQUALS(output->blocksize(), 6);
-    // Row with full acceptance
-    TS_ASSERT_EQUALS(output->y(0)[1], 1.);
-    TS_ASSERT_DELTA(output->e(0)[1], 0.40824829046386296, 1.e-5);
-    TS_ASSERT_EQUALS(output->dataF(0)[1], 6.);
-    // Row with limited, but non-zero acceptance, shouldn't have nans!
-    TS_ASSERT_DELTA(output->y(0)[5], 0.66666, 1.e-5);
-    TS_ASSERT_DELTA(output->e(0)[5], 0.47140452079103173, 1.e-5);
-    TS_ASSERT_EQUALS(output->dataF(0)[5], 3.);
 
-    TS_ASSERT(output->run().hasProperty("NumAllSpectra"))
-    TS_ASSERT(output->run().hasProperty("NumMaskSpectra"))
-    TS_ASSERT(output->run().hasProperty("NumZeroSpectra"))
-
-    TS_ASSERT_EQUALS(boost::lexical_cast<std::string>(nHist),
-                     output->run().getLogData("NumAllSpectra")->value())
-    TS_ASSERT_EQUALS(boost::lexical_cast<std::string>(0),
-                     output->run().getLogData("NumMaskSpectra")->value())
-    TS_ASSERT_EQUALS(boost::lexical_cast<std::string>(0),
-                     output->run().getLogData("NumZeroSpectra")->value())
+    auto evaluate = [&, nHist](RebinnedOutput_sptr &output) {
+      TS_ASSERT(output);
+      TS_ASSERT_EQUALS(output->getNumberHistograms(), 1);
+      TS_ASSERT_EQUALS(output->blocksize(), 6);
+      // Row with full acceptance
+      TS_ASSERT_EQUALS(output->y(0)[1], 1.);
+      TS_ASSERT_DELTA(output->e(0)[1], 0.40824829046386296, 1.e-5);
+      TS_ASSERT_EQUALS(output->dataF(0)[1], 6.);
+      // Row with limited, but non-zero acceptance, shouldn't have nans!
+      TS_ASSERT_DELTA(output->y(0)[5], 0.66666, 1.e-5);
+      TS_ASSERT_DELTA(output->e(0)[5], 0.47140452079103173, 1.e-5);
+      TS_ASSERT_EQUALS(output->dataF(0)[5], 3.);
+
+      TS_ASSERT(output->run().hasProperty("NumAllSpectra"))
+      TS_ASSERT(output->run().hasProperty("NumMaskSpectra"))
+      TS_ASSERT(output->run().hasProperty("NumZeroSpectra"))
+
+      TS_ASSERT_EQUALS(boost::lexical_cast<std::string>(nHist),
+                       output->run().getLogData("NumAllSpectra")->value())
+      TS_ASSERT_EQUALS(boost::lexical_cast<std::string>(0),
+                       output->run().getLogData("NumMaskSpectra")->value())
+      TS_ASSERT_EQUALS(boost::lexical_cast<std::string>(0),
+                       output->run().getLogData("NumZeroSpectra")->value())
+    };
+
+    evaluate(output);
+
+    // unfinalize the workspace and confirm it gives the same results
+    // using a clean algorithm
+    ws->unfinalize();
+    AnalysisDataService::Instance().addOrReplace(inName, ws);
+    Mantid::Algorithms::SumSpectra alg3a;
+    if (!alg3a.isInitialized()) {
+      alg3a.initialize();
+    }
+    // Set the properties
+    alg3a.setPropertyValue("InputWorkspace", inName);
+    alg3a.setPropertyValue("OutputWorkspace", outName);
+    alg3a.setProperty("IncludeMonitors", false);
+    alg3a.setProperty("RemoveSpecialValues", true);
+    alg3a.execute();
+    TS_ASSERT(alg3a.isExecuted());
+    output =
+        AnalysisDataService::Instance().retrieveWS<RebinnedOutput>(outName);
+    evaluate(output);
   }
   void testExecNoLimitsWeighted() {
     Mantid::Algorithms::SumSpectra alg2;
diff --git a/Framework/DataHandling/src/LoadNexusProcessed.cpp b/Framework/DataHandling/src/LoadNexusProcessed.cpp
index e251aea1bb830fc4d0c679526c2393eebaff14be..f22a90ae90b0b7ea5ded8acc6a8a874032817d2e 100644
--- a/Framework/DataHandling/src/LoadNexusProcessed.cpp
+++ b/Framework/DataHandling/src/LoadNexusProcessed.cpp
@@ -1302,6 +1302,16 @@ API::MatrixWorkspace_sptr LoadNexusProcessed::loadNonEventEntry(
   NXDataSetTyped<double> fracarea = errors;
   if (hasFracArea) {
     fracarea = wksp_cls.openNXDouble("frac_area");
+
+    // Set the fractional area attributes, default values consistent with
+    // previous assumptions: finalized = true, sqrdErrs = false
+    auto rbWS = boost::dynamic_pointer_cast<RebinnedOutput>(local_workspace);
+    auto finalizedValue = fracarea.attributes("finalized");
+    auto finalized = (finalizedValue.empty() ? true : finalizedValue == "1");
+    rbWS->setFinalized(finalized);
+    auto sqrdErrsValue = fracarea.attributes("sqrd_errors");
+    auto sqrdErrs = (sqrdErrsValue.empty() ? false : sqrdErrsValue == "1");
+    rbWS->setSqrdErrors(sqrdErrs);
   }
 
   // Check for x errors; as with fracArea we set it to xbins
diff --git a/Framework/DataObjects/inc/MantidDataObjects/FractionalRebinning.h b/Framework/DataObjects/inc/MantidDataObjects/FractionalRebinning.h
index eaa08f04d077365c80a85291dce65708ec6c755f..6bf685879efb01964daafd16d8628848d658894f 100644
--- a/Framework/DataObjects/inc/MantidDataObjects/FractionalRebinning.h
+++ b/Framework/DataObjects/inc/MantidDataObjects/FractionalRebinning.h
@@ -62,6 +62,10 @@ MANTID_DATAOBJECTS_DLL void rebinToFractionalOutput(
     const std::vector<double> &verticalAxis,
     const DataObjects::RebinnedOutput_const_sptr &inputRB = nullptr);
 
+/// Set finalize flag after fractional rebinning loop
+MANTID_DATAOBJECTS_DLL void
+finalizeFractionalRebin(DataObjects::RebinnedOutput &outputWS);
+
 } // namespace FractionalRebinning
 
 } // namespace DataObjects
diff --git a/Framework/DataObjects/inc/MantidDataObjects/RebinnedOutput.h b/Framework/DataObjects/inc/MantidDataObjects/RebinnedOutput.h
index 28ba488a3b6aa53a96265beda56ede5a61d307c6..4335a7c7d0fb4a6d9133415e45220b9cf625508e 100644
--- a/Framework/DataObjects/inc/MantidDataObjects/RebinnedOutput.h
+++ b/Framework/DataObjects/inc/MantidDataObjects/RebinnedOutput.h
@@ -25,8 +25,9 @@ namespace DataObjects {
 */
 class DLLExport RebinnedOutput : public Workspace2D {
 public:
-  RebinnedOutput() : m_finalized(false) {}
-  RebinnedOutput(bool finalized) : m_finalized(finalized) {}
+  RebinnedOutput() : m_finalized(false), m_hasSqrdErrs(true) {}
+  RebinnedOutput(bool finalized, bool hasSqrdErrs)
+      : m_finalized(finalized), m_hasSqrdErrs(hasSqrdErrs) {}
   /// Returns a clone of the workspace
   std::unique_ptr<RebinnedOutput> clone() const {
     return std::unique_ptr<RebinnedOutput>(doClone());
@@ -46,18 +47,30 @@ public:
   /// Returns the fractional area
   virtual const MantidVec &dataF(const std::size_t index) const;
 
-  /// Create final representation
-  void finalize(bool hasSqrdErrs = true, bool force = false);
-  void unfinalize(bool hasSqrdErrs = false, bool force = false);
+  /// Finalize to fractional area representation
+  void finalize(bool hasSqrdErrs = true);
+  /// Undo fractional area representation
+  void unfinalize();
 
   /// Returns if finalize has been called
   bool isFinalized() const { return m_finalized; }
+  /// Override the finalized flag
+  void setFinalized(bool value) { m_finalized = value; }
+
+  /// Returns if using squared errors
+  bool hasSqrdErrors() const { return m_hasSqrdErrs; }
+  /// Override the squared errors flag
+  void setSqrdErrors(bool value) { m_hasSqrdErrs = value; }
 
   /// Returns a read-only (i.e. const) reference to the specified F array
   const MantidVec &readF(std::size_t const index) const;
 
   /// Set the fractional area array for a given index.
   void setF(const std::size_t index, const MantidVecPtr &F);
+  /// Multiply the fractional area arrays by a scale factor
+  void scaleF(const double scale);
+  /// Returns if the fractional area is non zero
+  bool nonZeroF() const;
 
 protected:
   /// Protected copy constructor. May be used by childs for cloning.
@@ -74,10 +87,13 @@ protected:
   /// Flag to indicate if finalize has been called, and if errors/variance used
   bool m_finalized;
 
+  /// Flag to indiciate if the finalized data used squared errors
+  bool m_hasSqrdErrs;
+
 private:
   RebinnedOutput *doClone() const override { return new RebinnedOutput(*this); }
   RebinnedOutput *doCloneEmpty() const override {
-    return new RebinnedOutput(m_finalized);
+    return new RebinnedOutput(m_finalized, m_hasSqrdErrs);
   }
 };
 
diff --git a/Framework/DataObjects/src/FractionalRebinning.cpp b/Framework/DataObjects/src/FractionalRebinning.cpp
index a645ace793659e49f68682240bb89a8dbe6b083c..3064644bf89025447f3f597f81f79af207f2ed01 100644
--- a/Framework/DataObjects/src/FractionalRebinning.cpp
+++ b/Framework/DataObjects/src/FractionalRebinning.cpp
@@ -663,6 +663,8 @@ void rebinToFractionalOutput(const Quadrilateral &inputQ,
     if (inputRB->isFinalized()) {
       signal *= inF[j];
       error *= inF[j];
+      if (inputRB->hasSqrdErrors())
+        error *= inF[j];
     }
   }
 
@@ -683,6 +685,16 @@ void rebinToFractionalOutput(const Quadrilateral &inputQ,
   }
 }
 
+/**
+ * Called at the completion of the fractional rebinning loop
+ * to the set the finalize flag in the output workspace.
+ * @param outputWS Reference to the rebinned output workspace
+ */
+void finalizeFractionalRebin(RebinnedOutput &outputWS) {
+  // rebinToFractionalOutput() leaves the data in an unfinalized state
+  outputWS.setFinalized(false);
+}
+
 } // namespace FractionalRebinning
 
 } // namespace DataObjects
diff --git a/Framework/DataObjects/src/RebinnedOutput.cpp b/Framework/DataObjects/src/RebinnedOutput.cpp
index 4c88fd691a336a38acd95ccf677e973a9f715fb3..04570f44d9d606767c997e116cc8c408b5ff73aa 100644
--- a/Framework/DataObjects/src/RebinnedOutput.cpp
+++ b/Framework/DataObjects/src/RebinnedOutput.cpp
@@ -82,7 +82,7 @@ const MantidVec &RebinnedOutput::readF(const std::size_t index) const {
 }
 
 /**
- * Function that sets the fractional area arrat for a given index.
+ * Function that sets the fractional area array for a given index.
  * @param index :: the particular array to set
  * @param F :: the array contained the information
  */
@@ -91,28 +91,73 @@ void RebinnedOutput::setF(const std::size_t index, const MantidVecPtr &F) {
 }
 
 /**
- * This function takes the data/error arrays and divides them by the
- * corresponding fractional area array. This creates a representation that
- * is easily visualized. The Rebin and Integration algorithms will have to
- * undo this in order to properly treat the data.
- * @param hasSqrdErrs :: does the workspace have squared errors?
- * @param force :: ignore finalize flag or not?
+ * Function that scales the fractional area arrays.
+ * @param scale :: the scale factor
  */
-void RebinnedOutput::finalize(bool hasSqrdErrs, bool force) {
-  if (m_finalized && !force)
-    return;
-  auto nHist = static_cast<int>(this->getNumberHistograms());
+void RebinnedOutput::scaleF(const double scale) {
+  std::size_t nHist = this->getNumberHistograms();
+  for (std::size_t i = 0; i < nHist; ++i) {
+    MantidVec &frac = this->dataF(i);
+    std::transform(frac.begin(), frac.end(), frac.begin(),
+                   [scale](double x) { return scale * x; });
+  }
+}
+
+/**
+ * The functions checks if the fractional area data is non zero.
+ */
+bool RebinnedOutput::nonZeroF() const {
+
   // Checks that the fractions are not all zeros.
+  auto nHist = static_cast<int>(this->getNumberHistograms());
   bool frac_all_zeros = true;
   for (int i = 0; i < nHist; ++i) {
-    MantidVec &frac = this->dataF(i);
+    const MantidVec &frac = this->readF(i);
     if (std::accumulate(frac.begin(), frac.end(), 0.) != 0) {
       frac_all_zeros = false;
       break;
     }
   }
-  if (frac_all_zeros)
+  return !frac_all_zeros;
+}
+
+/**
+ * This function takes the data/error arrays and divides them by the
+ * corresponding fractional area array. This creates a representation that
+ * is easily visualized. The Rebin and Integration algorithms will have to
+ * undo this in order to properly treat the data. If the fractional area
+ * is all zero skip the operation as there will be no meaningful data.
+ * @param hasSqrdErrs :: does the workspace have squared errors?
+ */
+void RebinnedOutput::finalize(bool hasSqrdErrs) {
+  if (m_finalized && hasSqrdErrs == m_hasSqrdErrs)
     return;
+
+  // Checks that the fractions are not all zeros.
+  if (!this->nonZeroF())
+    return;
+
+  // Fix the squared error representation before returning
+  auto nHist = static_cast<int>(this->getNumberHistograms());
+  if (m_finalized) {
+    PARALLEL_FOR_IF(Kernel::threadSafe(*this))
+    for (int i = 0; i < nHist; ++i) {
+      MantidVec &err = this->dataE(i);
+      MantidVec &frac = this->dataF(i);
+      if (hasSqrdErrs) {
+        std::transform(err.begin(), err.end(), frac.begin(), err.begin(),
+                       std::divides<double>());
+      } else {
+        std::transform(err.begin(), err.end(), frac.begin(), err.begin(),
+                       std::multiplies<double>());
+      }
+    }
+
+    // Sets flag so subsequent algorithms know to correctly treat data
+    m_hasSqrdErrs = hasSqrdErrs;
+    return;
+  }
+
   PARALLEL_FOR_IF(Kernel::threadSafe(*this))
   for (int i = 0; i < nHist; ++i) {
     MantidVec &data = this->dataY(i);
@@ -127,19 +172,21 @@ void RebinnedOutput::finalize(bool hasSqrdErrs, bool force) {
                      std::divides<double>());
     }
   }
-  // Sets flag so subsequent algorithms know to correctly treat data
+  // Sets flags so subsequent algorithms know to correctly treat data
   m_finalized = true;
+  m_hasSqrdErrs = hasSqrdErrs;
 }
 
 /**
  * This function "unfinalizes" the workspace by taking the data/error arrays
- * and multiplying them by the corresponding fractional area array.
- * @param hasSqrdErrs :: does the workspace have squared errors?
- * @param force :: ignore finalize flag or not?
+ * and multiplying them by the corresponding fractional area array if the array
+ * is non zero. If all the values are zero skip the process as all data will
+ * will be lost.
  */
-void RebinnedOutput::unfinalize(bool hasSqrdErrs, bool force) {
-  if (!m_finalized && !force)
+void RebinnedOutput::unfinalize() {
+  if (!m_finalized || !this->nonZeroF())
     return;
+
   auto nHist = static_cast<int>(this->getNumberHistograms());
   PARALLEL_FOR_IF(Kernel::threadSafe(*this))
   for (int i = 0; i < nHist; ++i) {
@@ -150,7 +197,7 @@ void RebinnedOutput::unfinalize(bool hasSqrdErrs, bool force) {
                    std::multiplies<double>());
     std::transform(err.begin(), err.end(), frac.begin(), err.begin(),
                    std::multiplies<double>());
-    if (hasSqrdErrs) {
+    if (this->m_hasSqrdErrs) {
       std::transform(err.begin(), err.end(), frac.begin(), err.begin(),
                      std::multiplies<double>());
     }
diff --git a/Framework/DataObjects/src/ReflectometryTransform.cpp b/Framework/DataObjects/src/ReflectometryTransform.cpp
index a3231deedb7a1e9f798e555afd6e4eed80886e51..b0a1dd48628308d68db34cff3a4baa6784e52825 100644
--- a/Framework/DataObjects/src/ReflectometryTransform.cpp
+++ b/Framework/DataObjects/src/ReflectometryTransform.cpp
@@ -513,6 +513,7 @@ MatrixWorkspace_sptr ReflectometryTransform::executeNormPoly(
       }
     }
   }
+  FractionalRebinning::finalizeFractionalRebin(*outWS);
   outWS->finalize();
   FractionalRebinning::normaliseOutput(outWS, inputWS);
   // Set the output spectrum-detector mapping
diff --git a/Framework/Nexus/src/NexusFileIO.cpp b/Framework/Nexus/src/NexusFileIO.cpp
index 33c950ebee21fafba10cf687b1a7e41f2e13e3f1..acad6618507121d287b9ac711c689d78e8e1677e 100644
--- a/Framework/Nexus/src/NexusFileIO.cpp
+++ b/Framework/Nexus/src/NexusFileIO.cpp
@@ -404,6 +404,12 @@ int NexusFileIO::writeNexusProcessedData2D(
         NXputslab(fileID, rebin_workspace->readF(s).data(), start, asize);
         start[0]++;
       }
+
+      std::string finalized = (rebin_workspace->isFinalized()) ? "1" : "0";
+      NXputattr(fileID, "finalized", finalized.c_str(), 2, NX_CHAR);
+      std::string sqrdErrs = (rebin_workspace->hasSqrdErrors()) ? "1" : "0";
+      NXputattr(fileID, "sqrd_errors", sqrdErrs.c_str(), 2, NX_CHAR);
+
       if (m_progress != nullptr)
         m_progress->reportIncrement(1, "Writing data");
     }
diff --git a/Framework/PythonInterface/mantid/dataobjects/src/Exports/RebinnedOutput.cpp b/Framework/PythonInterface/mantid/dataobjects/src/Exports/RebinnedOutput.cpp
index 422c9239cccf0572896e998ddf1fc5a034866ac1..c241b305e68462d8e917d079fd32eee78b3d86d6 100644
--- a/Framework/PythonInterface/mantid/dataobjects/src/Exports/RebinnedOutput.cpp
+++ b/Framework/PythonInterface/mantid/dataobjects/src/Exports/RebinnedOutput.cpp
@@ -5,22 +5,92 @@
 //     & Institut Laue - Langevin
 // SPDX - License - Identifier: GPL - 3.0 +
 #include "MantidDataObjects/RebinnedOutput.h"
+#include "MantidPythonInterface/core/Converters/NDArrayToVector.h"
+#include "MantidPythonInterface/core/Converters/PySequenceToVector.h"
+#include "MantidPythonInterface/core/Converters/WrapWithNDArray.h"
 #include "MantidPythonInterface/core/GetPointer.h"
+#include "MantidPythonInterface/core/Policies/VectorToNumpy.h"
 #include "MantidPythonInterface/kernel/Registry/RegisterWorkspacePtrToPython.h"
 
 #include <boost/python/class.hpp>
 
 using Mantid::DataObjects::RebinnedOutput;
 using Mantid::DataObjects::Workspace2D;
+using namespace Mantid::PythonInterface;
+using namespace Mantid::PythonInterface::Converters;
+using namespace Mantid::PythonInterface::Policies;
 using namespace Mantid::PythonInterface::Registry;
 using namespace boost::python;
 
 GET_POINTER_SPECIALIZATION(RebinnedOutput)
 
+namespace {
+/// Typedef for data access, i.e. dataX,Y,E members
+using data_modifier = Mantid::MantidVec &(RebinnedOutput::*)(const std::size_t);
+
+/// return_value_policy for read-only numpy array
+using return_readonly_numpy =
+    return_value_policy<VectorRefToNumpy<WrapReadOnly>>;
+/// return_value_policy for read-write numpy array
+using return_readwrite_numpy =
+    return_value_policy<VectorRefToNumpy<WrapReadWrite>>;
+
+/**
+ * Set the F values from an python array-style object
+ * @param self :: A reference to the calling object
+ * @param wsIndex :: The workspace index for the spectrum to set
+ * @param values :: A numpy array, length must match F array length
+ */
+void setFFromPyObject(RebinnedOutput &self, const size_t wsIndex,
+                      const boost::python::object &values) {
+
+  if (NDArray::check(values)) {
+    NDArrayToVector<double> converter(values);
+    converter.copyTo(self.dataF(wsIndex));
+  } else {
+    PySequenceToVector<double> converter(values);
+    converter.copyTo(self.dataF(wsIndex));
+  }
+}
+} // namespace
+
 void export_RebinnedOutput() {
   class_<RebinnedOutput, bases<Workspace2D>, boost::noncopyable>(
-      "RebinnedOutput", no_init);
-
+      "RebinnedOutput", no_init)
+      .def("readF", &RebinnedOutput::readF,
+           (arg("self"), arg("workspaceIndex")), return_readonly_numpy(),
+           "Creates a read-only numpy wrapper "
+           "around the original F data at the "
+           "given index")
+      .def("dataF", (data_modifier)&RebinnedOutput::dataF,
+           return_readwrite_numpy(), args("self", "workspaceIndex"),
+           "Creates a writable numpy wrapper around the original F data at the "
+           "given index")
+      .def("setF", &setFFromPyObject, args("self", "workspaceIndex", "x"),
+           "Set F values from a python list or numpy array. It performs a "
+           "simple copy into the array")
+      .def("scaleF", &RebinnedOutput::scaleF, (arg("self"), arg("scale")),
+           "Scales the fractional area arrays")
+      .def("nonZeroF", &RebinnedOutput::nonZeroF, (arg("self")),
+           "Returns if the fractional area is non zero")
+      .def("finalize", &RebinnedOutput::finalize,
+           (arg("self"), arg("hasSqrdErrs")),
+           "Divides the data/error arrays by the corresponding fractional area "
+           "array")
+      .def("unfinalize", &RebinnedOutput::unfinalize, (arg("self")),
+           "Multiplies the data/error arrays by the corresponding fractional "
+           "area array")
+      .def("isFinalized", &RebinnedOutput::isFinalized, (arg("self")),
+           "Returns if values are normalized to the fractional area array")
+      .def("hasSqrdErrors", &RebinnedOutput::hasSqrdErrors, (arg("self")),
+           "Returns if squared errors are used with fractional area "
+           "normalization")
+      .def("setFinalized", &RebinnedOutput::setFinalized,
+           (arg("self"), arg("value")),
+           "Sets the value of the is finalized flag")
+      .def("setSqrdErrors", &RebinnedOutput::setSqrdErrors,
+           (arg("self"), arg("value")),
+           "Sets the value of the squared errors flag");
   // register pointers
   RegisterWorkspacePtrToPython<RebinnedOutput>();
 }
diff --git a/Framework/PythonInterface/test/python/mantid/api/MatrixWorkspaceTest.py b/Framework/PythonInterface/test/python/mantid/api/MatrixWorkspaceTest.py
index 5bed2dd3f6475cb1bc735b5915c70af91c728edc..d334cdb21a2dc9d9ea8223a9914fd84ede773205 100644
--- a/Framework/PythonInterface/test/python/mantid/api/MatrixWorkspaceTest.py
+++ b/Framework/PythonInterface/test/python/mantid/api/MatrixWorkspaceTest.py
@@ -458,6 +458,53 @@ class MatrixWorkspaceTest(unittest.TestCase):
         for index in maskedBinsIndices:
             self.assertEqual(1, index)
 
+    def test_rebinnedOutput(self):
+        rebin = WorkspaceFactory.create("RebinnedOutput", 2, 3, 2)
+        self.assertFalse(rebin.nonZeroF())
+        fv = rebin.readF(1)
+        rebin.dataY(1)[:] = 10.0
+        rebin.dataE(1)[:] = 1.0
+        twos = np.ones(len(fv)) * 2.0
+        rebin.setF(1, twos)
+        self.assertTrue(rebin.nonZeroF())
+        rebin.setFinalized(False)
+        rebin.setSqrdErrors(False)
+        rebin.unfinalize()
+        self.assertFalse(rebin.isFinalized())
+        yv = rebin.readY(1)
+        ev = rebin.readE(1)
+        self.assertAlmostEqual(yv[0], 10.0)
+        self.assertAlmostEqual(ev[0], 1.0)
+
+        rebin.finalize(True)
+        self.assertTrue(rebin.isFinalized())
+        self.assertTrue(rebin.hasSqrdErrors())
+        yv = rebin.readY(1)
+        ev = rebin.readE(1)
+        self.assertAlmostEqual(yv[0], 5.0)
+        self.assertAlmostEqual(ev[0], 0.25)
+
+        rebin.finalize(False)
+        self.assertTrue(rebin.isFinalized())
+        self.assertFalse(rebin.hasSqrdErrors())
+        yv = rebin.readY(1)
+        ev = rebin.readE(1)
+        self.assertAlmostEqual(yv[0], 5.0)
+        self.assertAlmostEqual(ev[0], 0.5)
+
+        rebin.unfinalize()
+        self.assertFalse(rebin.isFinalized())
+        yv = rebin.readY(1)
+        ev = rebin.readE(1)
+        self.assertAlmostEqual(yv[0], 10.0)
+        self.assertAlmostEqual(ev[0], 1.0)
+
+        rebin.scaleF(2.0)
+        fv = rebin.readF(1)
+        self.assertAlmostEqual(fv[0], 4.0)
+
+
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/Framework/PythonInterface/test/python/mantid/api/WorkspaceFactoryTest.py b/Framework/PythonInterface/test/python/mantid/api/WorkspaceFactoryTest.py
index 1a8c96c7f2c2a8006f55b59ef75cea703e098e51..9aae031906ca55eab92f740ad840508a7f8b1883 100644
--- a/Framework/PythonInterface/test/python/mantid/api/WorkspaceFactoryTest.py
+++ b/Framework/PythonInterface/test/python/mantid/api/WorkspaceFactoryTest.py
@@ -20,9 +20,9 @@ class WorkspaceFactoryTest(unittest.TestCase):
         return WorkspaceFactory.create("Workspace2D", NVectors=nhist,
                                        XLength=xlength, YLength=ylength)
 
-    def _verify(self, wksp, nhist, xlength, ylength):
+    def _verify(self, wksp, nhist, xlength, ylength, wsId="Workspace2D"):
         self.assertTrue(isinstance(wksp, MatrixWorkspace))
-        self.assertEqual(wksp.id(), "Workspace2D")
+        self.assertEqual(wksp.id(), wsId)
         self.assertEqual(wksp.getNumberHistograms(), nhist)
         self.assertEqual(len(wksp.readX(0)), xlength)
         self.assertEqual(wksp.blocksize(), ylength)
@@ -58,5 +58,12 @@ class WorkspaceFactoryTest(unittest.TestCase):
         peaks = WorkspaceFactory.createPeaks()
         self.assertTrue(isinstance(peaks, IPeaksWorkspace))
 
+    def test_creating_rebinnedoutput(self):
+        rebin = WorkspaceFactory.create("RebinnedOutput", 2, 6, 5)
+        self._verify(rebin, 2, 6, 5, wsId="RebinnedOutput")
+        fv = rebin.readF(1)
+        self.assertEqual(len(fv), 5)
+
+
 if __name__ == '__main__':
     unittest.main()
diff --git a/Framework/TestHelpers/src/WorkspaceCreationHelper.cpp b/Framework/TestHelpers/src/WorkspaceCreationHelper.cpp
index 1214b02df26391c7df8834cafd7a71a82819df1c..04a8c90d5ff1b095d7e438e43efa579cff40b4e5 100644
--- a/Framework/TestHelpers/src/WorkspaceCreationHelper.cpp
+++ b/Framework/TestHelpers/src/WorkspaceCreationHelper.cpp
@@ -1278,13 +1278,14 @@ RebinnedOutput_sptr createRebinnedOutputWorkspace() {
   // Set representation
   outputWS->finalize();
 
-  // Make errors squared rooted
+  // Make errors squared rooted and set sqrd err flag
   for (int i = 0; i < numHist; ++i) {
     auto &mutableE = outputWS->mutableE(i);
     for (int j = 0; j < numX - 1; ++j) {
       mutableE[j] = std::sqrt(mutableE[j]);
     }
   }
+  outputWS->setSqrdErrors(false);
 
   return outputWS;
 }