diff --git a/Framework/Muon/CMakeLists.txt b/Framework/Muon/CMakeLists.txt
index 7d495a27ea01718a488e5f5a80c767afe4c3ce5e..676a0670d395d59b5c1a59e01a1ecf7b4f54a373 100644
--- a/Framework/Muon/CMakeLists.txt
+++ b/Framework/Muon/CMakeLists.txt
@@ -1,66 +1,69 @@
 set ( SRC_FILES
- 	src/AlphaCalc.cpp
-	src/ApplyDeadTimeCorr.cpp
+        src/AlphaCalc.cpp
+        src/ApplyDeadTimeCorr.cpp
         src/ApplyMuonDetectorGrouping.cpp
         src/ApplyMuonDetectorGroupPairing.cpp
-	src/AsymmetryCalc.cpp
-	src/CalculateMuonAsymmetry.cpp
-	src/CalMuonDeadTime.cpp
-	src/CalMuonDetectorPhases.cpp
+        src/AsymmetryCalc.cpp
+        src/CalculateMuonAsymmetry.cpp
+        src/CalMuonDeadTime.cpp
+        src/CalMuonDetectorPhases.cpp
         src/ConvertFitFunctionForMuonTFAsymmetry.cpp
         src/LoadAndApplyMuonDetectorGrouping.cpp
-	src/EstimateMuonAsymmetryFromCounts.cpp
+        src/EstimateMuonAsymmetryFromCounts.cpp
         src/MuonAlgorithmHelper.cpp
-	src/MuonAsymmetryHelper.cpp
-	src/MuonGroupDetectors.cpp
-	src/MuonPreProcess.cpp
-	src/PhaseQuadMuon.cpp
-	src/PlotAsymmetryByLogValue.cpp
-	src/RemoveExpDecay.cpp
-	src/RRFMuon.cpp
+        src/MuonAsymmetryHelper.cpp
+        src/MuonGroupDetectors.cpp
+        src/MuonGroupingCounts.cpp
+        src/MuonPreProcess.cpp
+        src/PhaseQuadMuon.cpp
+        src/PlotAsymmetryByLogValue.cpp
+        src/RemoveExpDecay.cpp
+        src/RRFMuon.cpp
 )
 
 set ( INC_FILES
-	inc/MantidMuon/AlphaCalc.h
-	inc/MantidMuon/ApplyDeadTimeCorr.h
+        inc/MantidMuon/AlphaCalc.h
+        inc/MantidMuon/ApplyDeadTimeCorr.h
         inc/MantidMuon/ApplyMuonDetectorGrouping.h
         inc/MantidMuon/ApplyMuonDetectorGroupPairing.h
-	inc/MantidMuon/AsymmetryCalc.h
-	inc/MantidMuon/CalculateMuonAsymmetry.h
-	inc/MantidMuon/CalMuonDeadTime.h
-	inc/MantidMuon/CalMuonDetectorPhases.h
+        inc/MantidMuon/AsymmetryCalc.h
+        inc/MantidMuon/CalculateMuonAsymmetry.h
+        inc/MantidMuon/CalMuonDeadTime.h
+        inc/MantidMuon/CalMuonDetectorPhases.h
         inc/MantidMuon/ConvertFitFunctionForMuonTFAsymmetry.h
         inc/MantidMuon/LoadAndApplyMuonDetectorGrouping.h
-	inc/MantidMuon/EstimateMuonAsymmetryFromCounts.h
+        inc/MantidMuon/EstimateMuonAsymmetryFromCounts.h
         inc/MantidMuon/MuonAlgorithmHelper.h
-	inc/MantidMuon/MuonAsymmetryHelper.h
-	inc/MantidMuon/MuonGroupDetectors.h
-	inc/MantidMuon/MuonPreProcess.h
-	inc/MantidMuon/PhaseQuadMuon.h
-	inc/MantidMuon/PlotAsymmetryByLogValue.h
-	inc/MantidMuon/RemoveExpDecay.h
-	inc/MantidMuon/RRFMuon.h
+        inc/MantidMuon/MuonAsymmetryHelper.h
+        inc/MantidMuon/MuonGroupDetectors.h
+        inc/MantidMuon/MuonGroupingCounts.h
+        inc/MantidMuon/MuonPreProcess.h
+        inc/MantidMuon/PhaseQuadMuon.h
+        inc/MantidMuon/PlotAsymmetryByLogValue.h
+        inc/MantidMuon/RemoveExpDecay.h
+        inc/MantidMuon/RRFMuon.h
 )
 
 set ( TEST_FILES
-	AlphaCalcTest.h
-	ApplyDeadTimeCorrTest.h
+        AlphaCalcTest.h
+        ApplyDeadTimeCorrTest.h
         ApplyMuonDetectorGroupingTest.h
         ApplyMuonDetectorGroupPairingTest.h
-	AsymmetryCalcTest.h
-	CalculateMuonAsymmetryTest.h
-	CalMuonDeadTimeTest.h
-	CalMuonDetectorPhasesTest.h
+        AsymmetryCalcTest.h
+        CalculateMuonAsymmetryTest.h
+        CalMuonDeadTimeTest.h
+        CalMuonDetectorPhasesTest.h
         ConvertFitFunctionForMuonTFAsymmetryTest.h
         LoadAndApplyMuonDetectorGroupingTest.h
         MuonAlgorithmHelperTest.h
-	EstimateMuonAsymmetryFromCountsTest.h
-	MuonGroupDetectorsTest.h
-	MuonPreProcessTest.h
-	PhaseQuadMuonTest.h
-	PlotAsymmetryByLogValueTest.h
-	RemoveExpDecayTest.h
-	RRFMuonTest.h
+        EstimateMuonAsymmetryFromCountsTest.h
+        MuonGroupDetectorsTest.h
+        MuonGroupingCountsTest.h
+        MuonPreProcessTest.h
+        PhaseQuadMuonTest.h
+        PlotAsymmetryByLogValueTest.h
+        RemoveExpDecayTest.h
+        RRFMuonTest.h
 )
 
 if (COVERALLS)
diff --git a/Framework/Muon/inc/MantidMuon/MuonAlgorithmHelper.h b/Framework/Muon/inc/MantidMuon/MuonAlgorithmHelper.h
index f076ee23cd75da124d4c8c91fb821ed256744b33..eafd889e648203f4f57b1bc3034e6e814ebac68b 100644
--- a/Framework/Muon/inc/MantidMuon/MuonAlgorithmHelper.h
+++ b/Framework/Muon/inc/MantidMuon/MuonAlgorithmHelper.h
@@ -139,6 +139,8 @@ DLLExport void addSampleLog(Mantid::API::MatrixWorkspace_sptr workspace,
                             const std::string &logName,
                             const std::string &logValue);
 
+DLLExport bool isAlphanumericOrUnderscore(char character);
+
 //
 ///// Saves grouping to the XML file specified
 // DLLExport std::string groupingToXML(const Mantid::API::Grouping &grouping);
diff --git a/Framework/Muon/inc/MantidMuon/MuonGroupingCounts.h b/Framework/Muon/inc/MantidMuon/MuonGroupingCounts.h
new file mode 100644
index 0000000000000000000000000000000000000000..6ddcb46094c8489dd0ab5c64fa59308659f9c5ea
--- /dev/null
+++ b/Framework/Muon/inc/MantidMuon/MuonGroupingCounts.h
@@ -0,0 +1,46 @@
+// Mantid Repository : https://github.com/mantidproject/mantid
+//
+// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
+//     NScD Oak Ridge National Laboratory, European Spallation Source
+//     & Institut Laue - Langevin
+// SPDX - License - Identifier: GPL - 3.0 +
+#ifndef MANTID_MUON_MUONGROUPINGCOUNTS_H_
+#define MANTID_MUON_MUONGROUPINGCOUNTS_H_
+
+#include "MantidAPI/Algorithm.h"
+
+using namespace Mantid::API;
+
+namespace Mantid {
+namespace Muon {
+
+class DLLExport MuonGroupingCounts : public API::Algorithm {
+public:
+  MuonGroupingCounts() : API::Algorithm() {}
+  ~MuonGroupingCounts() {}
+
+  const std::string name() const override { return "MuonGroupingCounts"; }
+  int version() const override { return (1); }
+  const std::string category() const override { return "Muon\\DataHandling"; }
+  const std::string summary() const override {
+    return "Apply a grouping (summation of counts) across a set of detectors "
+           "in Muon data.";
+  }
+  const std::vector<std::string> seeAlso() const override {
+    return {"MuonProcess", "Minus", "Plus"};
+  }
+
+  /// Perform validation of inputs to the algorithm
+  std::map<std::string, std::string> validateInputs() override;
+
+private:
+  void init() override;
+  void exec() override;
+
+  void setGroupingSampleLogs(MatrixWorkspace_sptr workspace);
+};
+
+} // namespace Muon
+} // namespace Mantid
+
+#endif /* MANTID_MUON_MUONGROUPINGCOUNTS_H_ */
diff --git a/Framework/Muon/src/MuonAlgorithmHelper.cpp b/Framework/Muon/src/MuonAlgorithmHelper.cpp
index 498a1e5fb1db175f0614e04a18ce6432da17f6ba..f6599d66788fae017c380482237417ea0915a9b3 100644
--- a/Framework/Muon/src/MuonAlgorithmHelper.cpp
+++ b/Framework/Muon/src/MuonAlgorithmHelper.cpp
@@ -607,5 +607,9 @@ void addSampleLog(MatrixWorkspace_sptr workspace, const std::string &logName,
   alg->execute();
 }
 
+bool isAlphanumericOrUnderscore(char character) {
+  return (isalpha(character) || isdigit(character) || (character == '_'));
+}
+
 } // namespace MuonAlgorithmHelper
 } // namespace Mantid
diff --git a/Framework/Muon/src/MuonGroupingCounts.cpp b/Framework/Muon/src/MuonGroupingCounts.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..103e0234b434eb8e49a210a8e1d82ab4658f0278
--- /dev/null
+++ b/Framework/Muon/src/MuonGroupingCounts.cpp
@@ -0,0 +1,215 @@
+// Mantid Repository : https://github.com/mantidproject/mantid
+//
+// Copyright &copy; 2018 ISIS Rutherford Appleton Laboratory UKRI,
+//     NScD Oak Ridge National Laboratory, European Spallation Source
+//     & Institut Laue - Langevin
+// SPDX - License - Identifier: GPL - 3.0 +
+#include "MantidMuon/MuonGroupingCounts.h"
+#include "MantidAPI/Algorithm.h"
+#include "MantidAPI/AlgorithmManager.h"
+#include "MantidAPI/MatrixWorkspace.h"
+#include "MantidAPI/WorkspaceFactory.h"
+#include "MantidAPI/WorkspaceGroup.h"
+#include "MantidDataObjects/TableWorkspace.h"
+#include "MantidHistogramData/HistogramMath.h"
+#include "MantidKernel/ArrayProperty.h"
+#include "MantidKernel/System.h"
+#include "MantidMuon/MuonAlgorithmHelper.h"
+#include <boost/format.hpp>
+
+using namespace Mantid::API;
+using namespace Mantid::DataObjects;
+using namespace Mantid::Kernel;
+using namespace Mantid::HistogramData;
+
+namespace {
+
+bool checkPeriodInWorkspaceGroup(const int &period,
+                                 WorkspaceGroup_sptr workspace) {
+  return period <= workspace->getNumberOfEntries();
+}
+
+MatrixWorkspace_sptr groupDetectors(MatrixWorkspace_sptr workspace,
+                                    const std::vector<int> &detectorIDs) {
+
+  auto outputWS = WorkspaceFactory::Instance().create(workspace, 1);
+
+  std::vector<size_t> wsIndices =
+      workspace->getIndicesFromDetectorIDs(detectorIDs);
+
+  if (wsIndices.size() != detectorIDs.size()) {
+    std::string errorMsg =
+        str(boost::format("The number of detectors"
+                          "requested does not equalthe number of detectors "
+                          "provided %1% != %2% ") %
+            wsIndices.size() % detectorIDs.size());
+    throw std::invalid_argument(errorMsg);
+  }
+
+  outputWS->getSpectrum(0).clearDetectorIDs();
+  outputWS->setSharedX(0, workspace->sharedX(wsIndices.front()));
+
+  auto hist = outputWS->histogram(0);
+  for (auto &wsIndex : wsIndices) {
+    hist += workspace->histogram(wsIndex);
+    outputWS->getSpectrum(0).addDetectorIDs(
+        workspace->getSpectrum(wsIndex).getDetectorIDs());
+  }
+  outputWS->setHistogram(0, hist);
+  outputWS->getSpectrum(0).setSpectrumNo(static_cast<int32_t>(1));
+  return outputWS;
+}
+
+} // namespace
+
+namespace Mantid {
+namespace Muon {
+
+// Register the algorithm into the AlgorithmFactory
+DECLARE_ALGORITHM(MuonGroupingCounts)
+
+void MuonGroupingCounts::init() {
+  std::string emptyString("");
+  std::vector<int> defaultGrouping = {1};
+
+  declareProperty(
+      Mantid::Kernel::make_unique<WorkspaceProperty<WorkspaceGroup>>(
+          "InputWorkspace", emptyString, Direction::Input,
+          PropertyMode::Mandatory),
+      "Input workspace containing data from detectors which are to "
+      "be grouped.");
+
+  declareProperty(Mantid::Kernel::make_unique<WorkspaceProperty<Workspace>>(
+                      "OutputWorkspace", emptyString, Direction::Output),
+                  "Output workspace which will hold the grouped data.");
+
+  declareProperty("GroupName", emptyString,
+                  "The name of the group. Must contain at least one "
+                  "alphanumeric character.",
+                  Direction::Input);
+  declareProperty(make_unique<ArrayProperty<int>>(
+                      "Grouping", defaultGrouping,
+                      IValidator_sptr(new NullValidator), Direction::Input),
+                  "The grouping of detectors, comma separated list of detector "
+                  "IDs or hyphenated ranges of IDs.");
+
+  declareProperty(make_unique<ArrayProperty<int>>(
+                      "SummedPeriods", defaultGrouping,
+                      IValidator_sptr(new NullValidator), Direction::Input),
+                  "A list of periods to sum in multiperiod data.");
+  declareProperty(
+      make_unique<ArrayProperty<int>>("SubtractedPeriods", Direction::Input),
+      "A list of periods to subtract in multiperiod data.");
+
+  // Perform Group Associations.
+
+  std::string groupingGrp("Grouping Information");
+  setPropertyGroup("GroupName", groupingGrp);
+  setPropertyGroup("Grouping", groupingGrp);
+
+  std::string periodGrp("Multi-period Data");
+  setPropertyGroup("SummedPeriods", periodGrp);
+  setPropertyGroup("SubtractedPeriods", periodGrp);
+}
+
+std::map<std::string, std::string> MuonGroupingCounts::validateInputs() {
+  std::map<std::string, std::string> errors;
+
+  std::string groupName = this->getProperty("GroupName");
+  if (groupName.empty()) {
+    errors["GroupName"] = "Group name must be specified.";
+  }
+
+  if (!std::all_of(std::begin(groupName), std::end(groupName),
+                   Mantid::MuonAlgorithmHelper::isAlphanumericOrUnderscore)) {
+    errors["GroupName"] =
+        "The group name must contain alphnumeric characters and _ only.";
+  }
+
+  WorkspaceGroup_sptr inputWS = getProperty("InputWorkspace");
+  std::vector<int> summedPeriods = getProperty("SummedPeriods");
+  std::vector<int> subtractedPeriods = getProperty("SubtractedPeriods");
+
+  if (summedPeriods.empty() && subtractedPeriods.empty()) {
+    errors["SummedPeriods"] = "At least one period must be specified";
+  }
+
+  if (!summedPeriods.empty()) {
+    const int highestSummedPeriod =
+        *std::max_element(summedPeriods.begin(), summedPeriods.end());
+    if (!checkPeriodInWorkspaceGroup(highestSummedPeriod, inputWS)) {
+      errors["SummedPeriods"] = "Requested period (" +
+                                std::to_string(highestSummedPeriod) +
+                                ") exceeds periods in data";
+    }
+    if (std::any_of(summedPeriods.begin(), summedPeriods.end(),
+                    [](const int &i) { return i < 0; })) {
+      errors["SummedPeriods"] = "Requested periods must be greater that 0.";
+    }
+  }
+
+  if (!subtractedPeriods.empty()) {
+    const int highestSubtractedPeriod =
+        *std::max_element(subtractedPeriods.begin(), subtractedPeriods.end());
+    if (!checkPeriodInWorkspaceGroup(highestSubtractedPeriod, inputWS)) {
+      errors["SubtractedPeriods"] = "Requested period (" +
+                                    std::to_string(highestSubtractedPeriod) +
+                                    ") exceeds periods in data";
+    }
+    if (std::any_of(subtractedPeriods.begin(), subtractedPeriods.end(),
+                    [](const int &i) { return i < 0; })) {
+      errors["SubtractedPeriods"] = "Requested periods must be greater that 0.";
+    }
+  }
+
+  if (inputWS->getNumberOfEntries() < 1) {
+    errors["InputWorkspace"] = "WorkspaceGroup contains no periods.";
+  }
+
+  return errors;
+}
+
+void MuonGroupingCounts::exec() {
+
+  WorkspaceGroup_sptr inputWS = getProperty("InputWorkspace");
+  MatrixWorkspace_sptr outputWS;
+
+  // Group detectors in each period
+  std::vector<int> group = getProperty("Grouping");
+  auto groupedPeriods = boost::make_shared<WorkspaceGroup>();
+  for (auto &&workspace : *inputWS) {
+    groupedPeriods->addWorkspace(groupDetectors(
+        boost::dynamic_pointer_cast<MatrixWorkspace>(workspace), group));
+  }
+
+  std::vector<int> summedPeriods = getProperty("SummedPeriods");
+  std::vector<int> subtractedPeriods = getProperty("SubtractedPeriods");
+  MatrixWorkspace_sptr addedPeriodsWS =
+      Mantid::MuonAlgorithmHelper::sumPeriods(groupedPeriods, summedPeriods);
+  if (!subtractedPeriods.empty()) {
+    MatrixWorkspace_sptr subtractedPeriodsWS =
+        Mantid::MuonAlgorithmHelper::sumPeriods(groupedPeriods,
+                                                subtractedPeriods);
+    outputWS = Mantid::MuonAlgorithmHelper::subtractWorkspaces(
+        addedPeriodsWS, subtractedPeriodsWS);
+  } else {
+    outputWS = addedPeriodsWS;
+  }
+
+  setGroupingSampleLogs(outputWS);
+  setProperty("OutputWorkspace", outputWS);
+}
+
+void MuonGroupingCounts::setGroupingSampleLogs(MatrixWorkspace_sptr workspace) {
+  MuonAlgorithmHelper::addSampleLog(workspace, "analysis_group_name",
+                                    getPropertyValue("GroupName"));
+  MuonAlgorithmHelper::addSampleLog(workspace, "analysis_group",
+                                    getPropertyValue("Grouping"));
+  MuonAlgorithmHelper::addSampleLog(workspace, "analysis_periods_summed",
+                                    getPropertyValue("SummedPeriods"));
+  MuonAlgorithmHelper::addSampleLog(workspace, "analysis_periods_subtracted",
+                                    getPropertyValue("SubtractedPeriods"));
+}
+
+} // namespace Muon
+} // namespace Mantid
diff --git a/Framework/Muon/test/MuonGroupingCountsTest.h b/Framework/Muon/test/MuonGroupingCountsTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..2d3b2fc1d1308fdd52e9fb5b642f670d8ab94001
--- /dev/null
+++ b/Framework/Muon/test/MuonGroupingCountsTest.h
@@ -0,0 +1,322 @@
+// Mantid Repository : https://github.com/mantidproject/mantid
+//
+// Copyright &copy; 2018 ISIS Rutherford Appleton Laboratory UKRI,
+//     NScD Oak Ridge National Laboratory, European Spallation Source
+//     & Institut Laue - Langevin
+// SPDX - License - Identifier: GPL - 3.0 +
+#ifndef MANTID_MUON_MUONGROUPINGCOUNTSTEST_H_
+#define MANTID_MUON_MUONGROUPINGCOUNTSTEST_H_
+
+#include "MantidAPI/AlgorithmManager.h"
+#include "MantidAPI/FrameworkManager.h"
+#include "MantidMuon/MuonGroupingCounts.h"
+#include "MantidTestHelpers/MuonWorkspaceCreationHelper.h"
+
+#include <cxxtest/TestSuite.h>
+
+using namespace Mantid;
+using namespace Mantid::Kernel;
+using namespace Mantid::API;
+using namespace Mantid::DataObjects;
+using namespace Mantid::Muon;
+using namespace MuonWorkspaceCreationHelper;
+
+namespace {
+
+// Simple class to set up the ADS with the configuration required by the
+// algorithm (a MatrixWorkspace).
+class setUpADSWithWorkspace {
+public:
+  setUpADSWithWorkspace(Workspace_sptr ws) {
+    AnalysisDataService::Instance().addOrReplace(inputWSName, ws);
+  };
+  ~setUpADSWithWorkspace() { AnalysisDataService::Instance().clear(); };
+
+  std::string const inputWSName = "inputData";
+};
+
+// Set only mandatory fields; input and output workspace
+IAlgorithm_sptr
+algorithmWithoutOptionalPropertiesSet(const std::string &inputWSName) {
+
+  auto alg = boost::make_shared<MuonGroupingCounts>();
+  alg->initialize();
+  alg->setProperty("InputWorkspace", inputWSName);
+  alg->setProperty("OutputWorkspace", "__notUsed");
+  alg->setAlwaysStoreInADS(false);
+  alg->setLogging(false);
+  return alg;
+}
+
+// Set up algorithm without any optional properties
+// i.e. just the input workspace and group name.
+IAlgorithm_sptr
+setUpAlgorithmWithoutOptionalProperties(WorkspaceGroup_sptr ws,
+                                        const std::string &name) {
+  setUpADSWithWorkspace setup(ws);
+  IAlgorithm_sptr alg =
+      algorithmWithoutOptionalPropertiesSet(setup.inputWSName);
+  alg->setProperty("GroupName", name);
+  return alg;
+}
+
+// Set up algorithm with GroupName applied
+IAlgorithm_sptr setUpAlgorithmWithGroupName(WorkspaceGroup_sptr ws,
+                                            const std::string &name) {
+  setUpADSWithWorkspace setup(ws);
+  IAlgorithm_sptr alg =
+      algorithmWithoutOptionalPropertiesSet(setup.inputWSName);
+  alg->setProperty("GroupName", name);
+  return alg;
+}
+
+// Set up algorithm with TimeOffset applied
+IAlgorithm_sptr
+setUpAlgorithmWithGroupNameAndDetectors(WorkspaceGroup_sptr ws,
+                                        const std::string &name,
+                                        const std::vector<int> &detectors) {
+  setUpADSWithWorkspace setup(ws);
+  IAlgorithm_sptr alg =
+      algorithmWithoutOptionalPropertiesSet(setup.inputWSName);
+  alg->setProperty("GroupName", name);
+  alg->setProperty("Grouping", detectors);
+  return alg;
+}
+
+// Retrieve the output workspace from an executed algorithm
+MatrixWorkspace_sptr getOutputWorkspace(IAlgorithm_sptr alg) {
+  Workspace_sptr outputWS = alg->getProperty("OutputWorkspace");
+  auto wsOut = boost::dynamic_pointer_cast<MatrixWorkspace>(outputWS);
+  return wsOut;
+}
+
+} // namespace
+
+class MuonGroupingCountsTest : public CxxTest::TestSuite {
+public:
+  static MuonGroupingCountsTest *createSuite() {
+    return new MuonGroupingCountsTest();
+  }
+  static void destroySuite(MuonGroupingCountsTest *suite) { delete suite; }
+
+  // --------------------------------------------------------------------------
+  // Initialization / Execution
+  // --------------------------------------------------------------------------
+
+  void test_that_algorithm_initializes() {
+    MuonGroupingCounts alg;
+
+    TS_ASSERT_THROWS_NOTHING(alg.initialize());
+    TS_ASSERT(alg.isInitialized());
+  }
+
+  void test_that_algorithm_executes_with_no_optional_properties_set() {
+
+    auto ws = createMultiPeriodWorkspaceGroup(2, 1, 10, "group1");
+    auto alg = setUpAlgorithmWithoutOptionalProperties(ws, "group1");
+
+    TS_ASSERT_THROWS_NOTHING(alg->execute());
+    TS_ASSERT(alg->isExecuted())
+  }
+
+  // --------------------------------------------------------------------------
+  // Validation : Group Names and Detector Grouping
+  // --------------------------------------------------------------------------
+
+  void test_that_input_workspace_cannot_be_a_Workspace2D() {
+
+    auto ws = createCountsWorkspace(5, 10, 0.0);
+    setUpADSWithWorkspace setup(ws);
+    auto alg = boost::make_shared<MuonGroupingCounts>();
+    alg->initialize();
+
+    TS_ASSERT_THROWS_ANYTHING(
+        alg->setProperty("InputWorkspace", setup.inputWSName));
+  }
+
+  void test_that_input_workspace_can_be_a_WorkspaceGroup() {
+
+    auto ws = createMultiPeriodWorkspaceGroup(2, 1, 10, "group1");
+    setUpADSWithWorkspace setup(ws);
+    auto alg = boost::make_shared<MuonGroupingCounts>();
+    alg->initialize();
+
+    TSM_ASSERT_THROWS_NOTHING(
+        "", alg->setProperty("InputWorkspace", setup.inputWSName))
+  }
+
+  void test_that_group_name_must_be_supplied() {
+
+    auto ws = createMultiPeriodWorkspaceGroup(2, 1, 10, "group1");
+    setUpADSWithWorkspace setup(ws);
+    IAlgorithm_sptr alg =
+        algorithmWithoutOptionalPropertiesSet(setup.inputWSName);
+
+    TS_ASSERT_THROWS(alg->execute(), std::runtime_error);
+  }
+
+  void
+  test_that_group_names_with_alphanumeric_characters_or_underscores_are_allowed() {
+    auto ws = createMultiPeriodWorkspaceGroup(2, 1, 10, "group1");
+
+    std::vector<std::string> validNames = {"fwd", "fwd2", "bwd_2"};
+    for (auto &&validName : validNames) {
+      auto alg = setUpAlgorithmWithGroupName(ws, validName);
+      TSM_ASSERT_THROWS_NOTHING("", alg->execute());
+    }
+  }
+
+  void
+  test_that_exec_throws_if_group_name_is_not_alphanumeric_or_underscored() {
+    auto ws = createMultiPeriodWorkspaceGroup(2, 1, 10, "group1");
+
+    std::vector<std::string> invalidNames = {"@", "fwd!", "#1", "fwd @", "   "};
+    for (auto &&invalidName : invalidNames) {
+      auto alg = setUpAlgorithmWithGroupName(ws, invalidName);
+      TS_ASSERT_THROWS_ANYTHING(alg->execute());
+    }
+  }
+
+  void
+  test_that_cannot_add_spectra_to_group_which_exceed_those_in_the_workspace() {
+    auto ws = createMultiPeriodWorkspaceGroup(1, 5, 10, "group1");
+
+    std::vector<int> detectors = {6, 7, 8, 9, 10};
+    auto alg = setUpAlgorithmWithGroupNameAndDetectors(ws, "group1", detectors);
+    alg->setRethrows(true);
+
+    TS_ASSERT_THROWS_ANYTHING(alg->execute());
+    TS_ASSERT(!alg->isExecuted());
+  }
+
+  // --------------------------------------------------------------------------
+  // Validation : multi period data
+  // --------------------------------------------------------------------------
+
+  void test_that_at_least_one_period_must_be_specified() {
+    auto ws = createMultiPeriodWorkspaceGroup(2, 3, 10, "group");
+    std::vector<int> detectors = {1, 2};
+    auto alg = setUpAlgorithmWithGroupNameAndDetectors(ws, "group", detectors);
+
+    std::vector<int> summedPeriods = {};
+    std::vector<int> subtractedPeriods = {};
+    alg->setProperty("SummedPeriods", summedPeriods);
+    alg->setProperty("SubtractedPeriods", subtractedPeriods);
+
+    TS_ASSERT_THROWS(alg->execute(), std::runtime_error);
+  }
+
+  void
+  test_that_supplying_too_many_periods_to_SummedPeriods_throws_on_execute() {
+    auto ws = createMultiPeriodWorkspaceGroup(2, 3, 10, "group");
+    std::vector<int> detectors = {1, 2, 3};
+    auto alg = setUpAlgorithmWithGroupNameAndDetectors(ws, "group", detectors);
+
+    std::vector<int> summedPeriods = {3};
+    alg->setProperty("SummedPeriods", summedPeriods);
+
+    TS_ASSERT_THROWS(alg->execute(), std::runtime_error);
+  }
+
+  void
+  test_that_supplying_too_many_periods_to_SubtractedPeriods_throws_on_execute() {
+    auto ws = createMultiPeriodWorkspaceGroup(2, 3, 10, "group");
+    std::vector<int> detectors = {1, 2, 3};
+    auto alg = setUpAlgorithmWithGroupNameAndDetectors(ws, "group", detectors);
+
+    std::vector<int> subtractedPeriods = {3};
+    alg->setProperty("SubtractedPeriods", subtractedPeriods);
+
+    TS_ASSERT_THROWS(alg->execute(), std::runtime_error);
+  }
+
+  // --------------------------------------------------------------------------
+  // Correct Output
+  // --------------------------------------------------------------------------
+
+  void test_that_single_period_data_combines_detectors_correctly() {
+    // Spec 1 y-vals : 1,  2,  3,  4,  5,  6,  7,  8,  9,  10
+    // Spec 2 y-vals : 11, 12, 13, 14, 15, 16 ,17, 18, 19, 20
+    // Spec 3 y-vals : 21, 22, 23, 24, 25, 26, 27, 28, 29, 30
+    auto ws = createMultiPeriodWorkspaceGroup(1, 3, 10, "group");
+    std::vector<int> detectors = {1, 2, 3};
+    auto alg = setUpAlgorithmWithGroupNameAndDetectors(ws, "group", detectors);
+    alg->execute();
+
+    auto wsOut = getOutputWorkspace(alg);
+
+    TS_ASSERT_DELTA(wsOut->readX(0)[0], 0.000, 0.001);
+    TS_ASSERT_DELTA(wsOut->readX(0)[4], 0.400, 0.001);
+    TS_ASSERT_DELTA(wsOut->readX(0)[9], 0.900, 0.001);
+
+    TS_ASSERT_DELTA(wsOut->readY(0)[0], 33.000, 0.001);
+    TS_ASSERT_DELTA(wsOut->readY(0)[4], 45.000, 0.001);
+    TS_ASSERT_DELTA(wsOut->readY(0)[9], 60.000, 0.001);
+    // Quadrature errors : Sqrt(3 * 0.005^2 )
+    TS_ASSERT_DELTA(wsOut->readE(0)[0], 0.00866, 0.0001);
+    TS_ASSERT_DELTA(wsOut->readE(0)[4], 0.00866, 0.0001);
+    TS_ASSERT_DELTA(wsOut->readE(0)[9], 0.00866, 0.0001);
+  }
+
+  void test_that_summing_periods_combines_detectors_correctly() {
+    // Period 1 :
+    // Spec 1 y-vals : 1,  2,  3,  4,  5,  6,  7,  8,  9,  10
+    // Spec 2 y-vals : 11, 12, 13, 14, 15, 16 ,17, 18, 19, 20
+    // Period 2 :
+    // Spec 1 y-vals : 2,  3,  4,  5,  6,  7,  8,  9,  10, 11
+    // Spec 2 y-vals : 12, 13, 14, 15, 16, 17 ,18, 19, 20, 21
+    auto ws = createMultiPeriodWorkspaceGroup(2, 2, 10, "group");
+    std::vector<int> detectors = {1, 2};
+    std::vector<int> summedPeriods = {1, 2};
+    auto alg = setUpAlgorithmWithGroupNameAndDetectors(ws, "group", detectors);
+    alg->setProperty("SummedPeriods", summedPeriods);
+    alg->execute();
+
+    auto wsOut = getOutputWorkspace(alg);
+
+    TS_ASSERT_DELTA(wsOut->readX(0)[0], 0.000, 0.001);
+    TS_ASSERT_DELTA(wsOut->readX(0)[4], 0.400, 0.001);
+    TS_ASSERT_DELTA(wsOut->readX(0)[9], 0.900, 0.001);
+
+    TS_ASSERT_DELTA(wsOut->readY(0)[0], 26.000, 0.001);
+    TS_ASSERT_DELTA(wsOut->readY(0)[4], 42.000, 0.001);
+    TS_ASSERT_DELTA(wsOut->readY(0)[9], 62.000, 0.001);
+    // Quadrature errors : Sqrt(4 * 0.005^2 )
+    TS_ASSERT_DELTA(wsOut->readE(0)[0], 0.0100, 0.0001);
+    TS_ASSERT_DELTA(wsOut->readE(0)[4], 0.0100, 0.0001);
+    TS_ASSERT_DELTA(wsOut->readE(0)[9], 0.0100, 0.0001);
+  }
+
+  void test_that_subtracting_periods_combines_detectors_correctly() {
+    // Period 1 :
+    // Spec 1 y-vals : 1,  2,  3,  4,  5,  6,  7,  8,  9,  10
+    // Spec 2 y-vals : 11, 12, 13, 14, 15, 16 ,17, 18, 19, 20
+    // Period 2 :
+    // Spec 1 y-vals : 2,  3,  4,  5,  6,  7,  8,  9,  10, 11
+    // Spec 2 y-vals : 12, 13, 14, 15, 16, 17 ,18, 19, 20, 21
+    auto ws = createMultiPeriodWorkspaceGroup(2, 2, 10, "group");
+    std::vector<int> detectors = {1, 2};
+    std::vector<int> summedPeriods = {2};
+    std::vector<int> subtractedPeriods = {1};
+    auto alg = setUpAlgorithmWithGroupNameAndDetectors(ws, "group", detectors);
+    alg->setProperty("SummedPeriods", summedPeriods);
+    alg->setProperty("SubtractedPeriods", subtractedPeriods);
+    alg->execute();
+
+    auto wsOut = getOutputWorkspace(alg);
+
+    TS_ASSERT_DELTA(wsOut->readX(0)[0], 0.000, 0.001);
+    TS_ASSERT_DELTA(wsOut->readX(0)[4], 0.400, 0.001);
+    TS_ASSERT_DELTA(wsOut->readX(0)[9], 0.900, 0.001);
+
+    TS_ASSERT_DELTA(wsOut->readY(0)[0], 2.000, 0.001);
+    TS_ASSERT_DELTA(wsOut->readY(0)[4], 2.000, 0.001);
+    TS_ASSERT_DELTA(wsOut->readY(0)[9], 2.000, 0.001);
+    // Quadrature errors : Sqrt(4 * 0.005^2 )
+    TS_ASSERT_DELTA(wsOut->readE(0)[0], 0.0100, 0.0001);
+    TS_ASSERT_DELTA(wsOut->readE(0)[4], 0.0100, 0.0001);
+    TS_ASSERT_DELTA(wsOut->readE(0)[9], 0.0100, 0.0001);
+  }
+};
+
+#endif /* MANTID_MUON_MUONGROUPINGCOUNTSTEST_H_ */
diff --git a/docs/source/algorithms/MuonGroupingCounts-v1.rst b/docs/source/algorithms/MuonGroupingCounts-v1.rst
new file mode 100644
index 0000000000000000000000000000000000000000..7e1f8eaffecd5d861b34f8fa1f59c480944be85f
--- /dev/null
+++ b/docs/source/algorithms/MuonGroupingCounts-v1.rst
@@ -0,0 +1,153 @@
+.. algorithm::
+
+.. summary::
+
+.. relatedalgorithms::
+
+.. properties::
+
+Description
+-----------
+
+When interacting with the :ref:`Muon_Analysis-ref` interface, operations such as detector grouping, group asymmetry and pair asymmetry are performed on data. This algorithm performs a "grouping counts" operation, in other words it sums the counts associated to a given sequence of detector IDs.
+
+This algorithm is part of a set of four; with :ref:`algm-MuonPreProcess` being run first; and the output being fed into this one. This allows the replication of the workflow used by the muon analysis interface to produce group data. 
+
+Analysis
+########
+
+A workspace has one or more *spectra* contained within it; for muon data each spectra has a unique detector ID. Assuming the y-values represent counts; a *detector grouping* operation causes the counts to be summed across the given set of detector IDs which are supplied to the **Grouping** argument (for example `1,2,3,4,5` and `1-5`).
+
+The **InputWorkspace** must be a *WorkspaceGroup*, where each workspace within the workspace-group represents a single period. Thus, single period data is just a *workspaceGroup* with a single workspace within it.
+
+The detector-group must be given a name via **GroupName** which can consist of letters, numbers and underscores. 
+
+#. Valid names : "fwd", "fwd2", "fwd_2", "1234"
+#. Invalid names : "", "fwd!", "fwd "
+
+The detector-group name does not affect the data; however the name is used in the muon interface when automatically generating workspace names from detector-group data.
+
+Multi period data 
+#################
+
+Both single and multi period data are supported by the algorithm.
+
+The **SummedPeriods** and **SubtractedPeriods** inputs are used to control the way that periods are combined. so for example;
+
+#. SummedPeriods = 1,2
+#. SubtractedPeriods = 3,4 
+
+would combine periods in the combination $(1+2)-(3+4)$.
+
+Usage
+-----
+
+**Example - Using MuonPreProcess followed by MuonGroupingCounts on Single Period Data**
+
+.. testcode:: ConvertToGroup
+
+    # Single period data with four spectra
+    dataX = [0, 1, 2, 3, 4, 5] * 4
+    dataY = [10, 20, 30, 20, 10] * 4
+    input_workspace = CreateWorkspace(dataX, dataY, NSpec=4)
+    for i in range(4):
+        # set detector IDs to be 1,2,3,4
+        # these do not have to be the same as the spectrum numbers
+        # (the spectrum number are 0,1,2,3 in this case)
+        input_workspace.getSpectrum(i).setDetectorID(i + 1)
+
+    # We are not actually applying any processing to the data
+    # but the algorithm will convert our single period data into
+    # the required form (a WorkspaceGroup)
+    pre_processed_workspace = MuonPreProcess(InputWorkspace=input_workspace)
+
+    output_workspace = MuonGroupingCounts(InputWorkspace=pre_processed_workspace,
+                                                    GroupName="fwd",
+                                                    Grouping=[1, 2, 3, 4])
+
+    print("X values are : {}".format(output_workspace.readX(0)))
+    print("Y values are : {}".format(output_workspace.readY(0)))
+
+
+Output:
+
+.. testoutput:: ConvertToGroup
+
+    X values are : [ 0.  1.  2.  3.  4.  5.]
+    Y values are : [  40.   80.  120.   80.   40.]
+
+**Example - Using Only MuonGroupingCounts on Single Period Data**
+
+.. testcode:: ConvertToGroup
+
+    # Create a workspaces with four spectra
+    dataX = [0, 1, 2, 3, 4, 5] * 4
+    dataY = [10, 20, 30, 20, 10] * 4
+    ws = CreateWorkspace(dataX, dataY, NSpec=4)
+    for i in range(4):
+        # set detector IDs to be 1,2,3,4
+        # these do not have to be the same as the spectrum numbers
+        # (the spectrum number are 0,1,2,3 in this case)
+        ws.getSpectrum(i).setDetectorID(i + 1)
+
+    # Put the workspace inside a WorkspaceGroup
+    input_workspace = GroupWorkspaces(ws)
+
+    output_workspace = MuonGroupingCounts(InputWorkspace=input_workspace,
+                                                    GroupName="fwd",
+                                                    Grouping=[1, 2, 3, 4])
+
+    print("X values are : {}".format(output_workspace.readX(0)))
+    print("Y values are : {}".format(output_workspace.readY(0)))
+
+
+Output:
+
+.. testoutput:: ConvertToGroup
+
+    X values are : [ 0.  1.  2.  3.  4.  5.]
+    Y values are : [  40.   80.  120.   80.   40.]
+
+**Example - Multi Period Data**
+
+.. testcode:: ExampleTimeOffset
+
+    # Create two workspaces with four spectra
+    dataX = [0, 1, 2, 3, 4, 5] * 4
+    dataY = [10, 20, 30, 20, 10] * 4
+    ws1 = CreateWorkspace(dataX, dataY, NSpec=4)
+    ws2 = CreateWorkspace(dataX, dataY, NSpec=4)
+    for i in range(4):
+        # set detector IDs to be 1,2,3,4
+        # these do not have to be the same as the spectrum numbers
+        # (the spectrum number are 0,1,2,3 in this case)
+        ws1.getSpectrum(i).setDetectorID(i + 1)
+        ws2.getSpectrum(i).setDetectorID(i + 1)
+
+    # Create multi period data
+    multi_period_data = GroupWorkspaces(ws1)
+    multi_period_data.addWorkspace(ws2)
+
+    # This time we won't run MuonPreProcess, as we don't want to apply any pre-processing
+    # and we already have a WorkspaceGroup
+
+    output_workspace = MuonGroupingCounts(InputWorkspace=multi_period_data,
+                                                    GroupName="fwd",
+                                                    Grouping=[1, 2, 3, 4],
+                                                    SummedPeriods=[1, 2])
+
+    # We have asked for periods 1+2, with each period summing detectors 1,2,3,4
+    print("X values are : {}".format(output_workspace.readX(0)))
+    print("Y values are : {}".format(output_workspace.readY(0)))
+
+
+Output:
+
+.. testoutput:: ExampleTimeOffset
+
+    X values are : [ 0.  1.  2.  3.  4.  5.]
+    Y values are : [  80.  160.  240.  160.   80.]
+
+.. categories::
+
+.. sourcelink::
\ No newline at end of file