diff --git a/Code/Mantid/Framework/Algorithms/src/AsymmetryCalc.cpp b/Code/Mantid/Framework/Algorithms/src/AsymmetryCalc.cpp
index 5d4e392d793cd19fb0e2ca8f6a6ddb6dcd90ca43..dccdb036bc8811ded03c46e84d79dcc13949fabd 100644
--- a/Code/Mantid/Framework/Algorithms/src/AsymmetryCalc.cpp
+++ b/Code/Mantid/Framework/Algorithms/src/AsymmetryCalc.cpp
@@ -110,6 +110,11 @@ void AsymmetryCalc::exec()
     specIDs[1] = backward;
     std::vector<size_t> indices;
     tmpWS->getIndicesFromSpectra( specIDs, indices );
+
+    // If some spectra were not found, can't continue
+    if(specIDs.size() != indices.size())
+      throw std::invalid_argument("Some of the spectra specified do not exist in a workspace");
+
     forward = static_cast<int>( indices[0] );
     backward = static_cast<int>( indices[1] );
   }
diff --git a/Code/Mantid/MantidQt/CustomInterfaces/CMakeLists.txt b/Code/Mantid/MantidQt/CustomInterfaces/CMakeLists.txt
index 8d92af6411327588e3d126aa8199ad13e9fc9a39..cbc2272ecfd278f05e05456c477c96391a2e53e9 100644
--- a/Code/Mantid/MantidQt/CustomInterfaces/CMakeLists.txt
+++ b/Code/Mantid/MantidQt/CustomInterfaces/CMakeLists.txt
@@ -148,6 +148,7 @@ set( TEST_FILES CreateMDWorkspaceAlgDialogTest.h
                 WorkspaceMementoTest.h
                 WorkspaceInADSTest.h
                 RawFileMementoTest.h
+                IO_MuonGroupingTest.h
 )
 
 include_directories ( inc )
diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IO_MuonGrouping.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IO_MuonGrouping.h
index c4310b465560c39d8901359e768e37d3d5211824..2ab1b8280fbec7f801efe436bc570e4d865522ea 100644
--- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IO_MuonGrouping.h
+++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IO_MuonGrouping.h
@@ -5,8 +5,9 @@
 // Includes
 //----------------------
 #include "ui_MuonAnalysis.h"
-#include "MantidQtCustomInterfaces/MuonAnalysis.h"
 #include "MantidQtAPI/UserSubWindow.h"
+#include "MantidQtCustomInterfaces/MuonAnalysis.h"
+#include "MantidQtCustomInterfaces/DllConfig.h"
 
 #include "MantidQtMantidWidgets/pythonCalc.h"
 #include "MantidQtMantidWidgets/MWRunFiles.h"
@@ -51,20 +52,53 @@ File change history is stored at: <https://github.com/mantidproject/mantid>
 Code Documentation is available at: <http://doxygen.mantidproject.org>    
 */
 
-/// save XML grouping file
-void saveGroupingTabletoXML(Ui::MuonAnalysis& m_uiForm, const std::string& filename);
+using namespace Mantid;
+using namespace Mantid::API;
+
+/// Structure to represent grouping information for Muon Analysis
+typedef struct {
+  std::vector<std::string> groupNames;
+  std::vector<std::string> groups; // Range strings, e.g. "1-32"
+
+  std::vector<std::string> pairNames;
+  std::vector<std::pair<size_t, size_t> > pairs; // Pairs of group ids
+  std::vector<double> pairAlphas;
+
+  std::string description;
+  std::string defaultName; // Not storing id because can be either group or pair
+} Grouping;
+
+/// Saves grouping to the XML file specified
+void MANTIDQT_CUSTOMINTERFACES_DLL saveGroupingToXML(const Grouping& grouping, 
+  const std::string& filename);
+
+/// Loads grouping from the XML file specified
+void MANTIDQT_CUSTOMINTERFACES_DLL loadGroupingFromXML(const std::string& filename, 
+  Grouping& grouping);
+
+/// Parses information from the grouping table and saves to Grouping struct
+void MANTIDQT_CUSTOMINTERFACES_DLL parseGroupingTable(const Ui::MuonAnalysis& form, 
+  Grouping& grouping);
+
+/// Fills in the grouping table using information from provided Grouping struct
+void MANTIDQT_CUSTOMINTERFACES_DLL fillGroupingTable(const Grouping& grouping, 
+  Ui::MuonAnalysis& form);
 
-/// load XML grouping file
-void loadGroupingXMLtoTable(Ui::MuonAnalysis& m_uiForm, const std::string& filename);
+/// Groups the workspace according to grouping provided
+MatrixWorkspace_sptr MANTIDQT_CUSTOMINTERFACES_DLL groupWorkspace(MatrixWorkspace_const_sptr ws, 
+  const Grouping& g);
 
 /// create 'map' relating group number to row number in group table
-void whichGroupToWhichRow(Ui::MuonAnalysis& m_uiForm, std::vector<int>& groupToRow);
+void MANTIDQT_CUSTOMINTERFACES_DLL whichGroupToWhichRow(const Ui::MuonAnalysis& m_uiForm, 
+  std::vector<int>& groupToRow);
 
 /// create 'map' relating pair number to row number in pair table
-void whichPairToWhichRow(Ui::MuonAnalysis& m_uiForm, std::vector<int>& pairToRow);
+void MANTIDQT_CUSTOMINTERFACES_DLL whichPairToWhichRow(const Ui::MuonAnalysis& m_uiForm, 
+  std::vector<int>& pairToRow);
 
 /// Set Group / Group Pair name
-void setGroupGroupPair(Ui::MuonAnalysis& m_uiForm, const std::string& name);
+void MANTIDQT_CUSTOMINTERFACES_DLL setGroupGroupPair(Ui::MuonAnalysis& m_uiForm, 
+  const std::string& name);
 
 }
 }
diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h
index 667e9d376b5deddebe612a7f1bbca61ef3cb2e4a..44c70a4c0e52e4739dc677a4bcefefb206195576 100644
--- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h
+++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MuonAnalysis.h
@@ -228,10 +228,6 @@ private:
   /// is grouping set
   bool isGroupingSet();
 
-  /// Apply grouping specified in xml file to workspace
-  bool applyGroupingToWS( const std::string& inputWS,  const std::string& outputWS, 
-    const std::string& filename);
-
   /// create WS contained the data for a plot
   void createPlotWS(const std::string& groupName, 
                     const std::string& inputWS, const std::string& outWS);
@@ -344,9 +340,6 @@ private:
   /// List of current group names 
   std::vector<std::string> m_groupNames;
 
-  /// name for file to temperary store grouping
-  std::string m_groupingTempFilename;
-
   /// Deal with input file changes.
   void handleInputFileChanges();
 
@@ -412,6 +405,9 @@ private:
   /// Boolean to show whether the gui is being updated
   bool m_updating;
 
+  /// Flag to indicate that grouping table is being updated
+  bool m_updatingGrouping;
+
   /// Boolean to show when data has been loaded. (Can't auto-update data that hasn't been loaded)
   bool m_loaded;
 
diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IO_MuonGrouping.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IO_MuonGrouping.cpp
index 27ba9bc214b8d15bb7cf4e20a5c7cbe4817266d8..a0114e100984530ef36e1cc6e5be957378ede140 100644
--- a/Code/Mantid/MantidQt/CustomInterfaces/src/IO_MuonGrouping.cpp
+++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IO_MuonGrouping.cpp
@@ -28,6 +28,7 @@
 #include <Poco/Path.h>
 
 #include <boost/shared_ptr.hpp>
+#include <boost/bind.hpp>
 #include <fstream>  
 //-----------------------------------------------------------------------------
 using namespace Poco::XML;
@@ -39,91 +40,79 @@ namespace CustomInterfaces
 namespace Muon
 {
 
-  using namespace Poco::XML;
-  using namespace MantidQt::API;
+using namespace Poco::XML;
+using namespace MantidQt::API;
 
 /**
- * save XML grouping file
+ * Save grouping to the XML file specified.
+ *
+ * @param        g :: Struct with grouping information
+ * @param filename :: XML filename where information will be saved
  */
-void saveGroupingTabletoXML(Ui::MuonAnalysis& m_uiForm, const std::string& filename)
+void saveGroupingToXML(const Grouping& g, const std::string& filename)
 {
   std::ofstream outFile(filename.c_str());
   if (!outFile)
-  {
-    throw Mantid::Kernel::Exception::FileError("Unable to open file:", filename);
-  }
+    throw Mantid::Kernel::Exception::FileError("Unable to open output file", filename);
 
   DOMWriter writer;
   writer.setNewLine("\n");
   writer.setOptions(XMLWriter::PRETTY_PRINT);
 
   Poco::XML::Document* mDoc = new Document();
+
+  // Create root element with a description
   Element* rootElem = mDoc->createElement("detector-grouping");
-  rootElem->setAttribute("description", m_uiForm.groupDescription->text().toStdString());
+  rootElem->setAttribute("description", g.description);
   mDoc->appendChild(rootElem);
 
-  // loop over groups in table
-
-  std::vector<int> groupToRow;
-  whichGroupToWhichRow(m_uiForm, groupToRow);
-
-  int num = static_cast<int>(groupToRow.size());
-  for (int i = 0; i < num; i++)
+  // Create group elements
+  for (size_t gi = 0; gi < g.groups.size(); gi++)
   {
     Element* gElem = mDoc->createElement("group");
-    gElem->setAttribute("name", m_uiForm.groupTable->item(groupToRow[i],0)->text().toStdString());
+    gElem->setAttribute("name", g.groupNames[gi]);
     rootElem->appendChild(gElem);
+
     Element* idsElem = mDoc->createElement("ids");
-    idsElem->setAttribute("val", m_uiForm.groupTable->item(groupToRow[i],1)->text().toStdString());
+    idsElem->setAttribute("val", g.groups[gi]);
     gElem->appendChild(idsElem);
   }
 
-  // loop over pairs in pair table
-
-  num = m_uiForm.pairTable->rowCount();
-  for (int i = 0; i < num; i++)
+  // Create pair elements
+  for (size_t pi = 0; pi < g.pairs.size(); pi++)
   {
-    QTableWidgetItem *itemName = m_uiForm.pairTable->item(i,0);
-    if (!itemName)
-      break;
-    if ( itemName->text().isEmpty() )
-      break;
-    QTableWidgetItem *itemAlpha = m_uiForm.pairTable->item(i,3);
-    if (!itemAlpha)
-      break;
-    if ( itemAlpha->text().isEmpty() )
-      break;
-
-    QComboBox* qw1 = static_cast<QComboBox*>(m_uiForm.pairTable->cellWidget(i,1));
-    QComboBox* qw2 = static_cast<QComboBox*>(m_uiForm.pairTable->cellWidget(i,2));
-
     Element* gElem = mDoc->createElement("pair");
-    gElem->setAttribute("name", itemName->text().toStdString());
+    gElem->setAttribute("name", g.pairNames[pi]);
     rootElem->appendChild(gElem);
+
     Element* fwElem = mDoc->createElement("forward-group");
-    fwElem->setAttribute("val", qw1->currentText().toStdString());
+    fwElem->setAttribute("val", g.groupNames[g.pairs[pi].first]);
     gElem->appendChild(fwElem);
+
     Element* bwElem = mDoc->createElement("backward-group");
-    bwElem->setAttribute("val", qw2->currentText().toStdString());
+    bwElem->setAttribute("val", g.groupNames[g.pairs[pi].second]);
     gElem->appendChild(bwElem);
+
     Element* alphaElem = mDoc->createElement("alpha");
-    alphaElem->setAttribute("val", itemAlpha->text().toStdString());
+    alphaElem->setAttribute("val", boost::lexical_cast<std::string>(g.pairAlphas[pi]));
     gElem->appendChild(alphaElem);
   } 
 
-  // save default
-
+  // Create default group/pair name element
   Element* gElem = mDoc->createElement("default");
-  gElem->setAttribute("name", m_uiForm.frontGroupGroupPairComboBox->currentText().toStdString());
+  gElem->setAttribute("name", g.defaultName);
   rootElem->appendChild(gElem);
 
   writer.writeNode(outFile, mDoc);
 }
 
 /**
- * load XML grouping file. It is assumed that tables and combo box cleared before this method is called
+ * Loads grouping from the XML file specified.
+ *
+ * @param filename :: XML filename to load grouping information from
+ * @param        g :: Struct to store grouping information to
  */
-void loadGroupingXMLtoTable(Ui::MuonAnalysis& m_uiForm, const std::string& filename)
+void loadGroupingFromXML(const std::string& filename, Grouping& g)
 {
   // Set up the DOM parser and parse xml file
   DOMParser pParser;
@@ -134,174 +123,237 @@ void loadGroupingXMLtoTable(Ui::MuonAnalysis& m_uiForm, const std::string& filen
   }
   catch(...)
   {
-    throw Mantid::Kernel::Exception::FileError("Unable to parse File:" , filename);
+    throw Mantid::Kernel::Exception::FileError("Unable to parse File" , filename);
   }
+
   // Get pointer to root element
   Element* pRootElem = pDoc->documentElement();
-  if ( !pRootElem->hasChildNodes() )
-  {
-    throw Mantid::Kernel::Exception::FileError("No root element in XML grouping file:" , filename);
-  }  
-
-  NodeList* pNL_group = pRootElem->getElementsByTagName("group");
-  if ( pNL_group->length() == 0 )
-  {
-    throw Mantid::Kernel::Exception::FileError("XML group file contains no group elements:" , filename);
-  }
+  if (!pRootElem->hasChildNodes())
+    throw Mantid::Kernel::Exception::FileError("No root element in XML grouping file" , filename);
 
+  // Parse information for groups
+  NodeList* groups = pRootElem->getElementsByTagName("group");
+  if (groups->length() == 0)
+    throw Mantid::Kernel::Exception::FileError("No groups specified in XML grouping file" , filename);
 
-  // add content to group table
+  // Resize vectors
+  g.groupNames.resize(groups->length());
+  g.groups.resize(groups->length());
 
-  QStringList allGroupNames;  // used to populate combo boxes 
-  int numberGroups = static_cast<int>(pNL_group->length());
-  for (int iGroup = 0; iGroup < numberGroups; iGroup++)
+  for (size_t ig = 0; ig < groups->length(); ig++)
   {
-    Element* pGroupElem = static_cast<Element*>(pNL_group->item(iGroup));
+    Element* pGroupElem = static_cast<Element*>(groups->item(ig));
 
-    if ( !pGroupElem->hasAttribute("name") )
+    if (!pGroupElem->hasAttribute("name"))
       throw Mantid::Kernel::Exception::FileError("Group element without name" , filename);
-    std::string gName = pGroupElem->getAttribute("name");
 
+    g.groupNames[ig] = pGroupElem->getAttribute("name");
 
     Element* idlistElement = pGroupElem->getChildElement("ids");
-    if (idlistElement)
-    {
-      std::string ids = idlistElement->getAttribute("val");
+    if (!idlistElement)
+      throw Mantid::Kernel::Exception::FileError("Group element without <ids>" , filename);
 
-      // add info to table
-      m_uiForm.groupTable->setItem(iGroup, 0, new QTableWidgetItem(gName.c_str()) );
-      m_uiForm.groupTable->setItem(iGroup,1, new QTableWidgetItem(ids.c_str()) );
-      allGroupNames.push_back( m_uiForm.groupTable->item(static_cast<int>(iGroup),0)->text() );
-    }
-    else
-    {
-      throw Mantid::Kernel::Exception::FileError("XML group file contains no <ids> elements:" , filename);
-    }   
+    g.groups[ig] = idlistElement->getAttribute("val");
   }
-  pNL_group->release();
+
+  groups->release();
   
 
-  // populate pair table combo boxes
+  // Parse information for pairs
+  NodeList* pairs = pRootElem->getElementsByTagName("pair");
+
+  // Resize vectors
+  g.pairNames.resize(pairs->length());
+  g.pairs.resize(pairs->length());
+  g.pairAlphas.resize(pairs->length());
 
-  int rowNum = m_uiForm.pairTable->rowCount();
-  for (int i = 0; i < rowNum; i++)
+  for (size_t ip = 0; ip < pairs->length(); ip++)
   {
-    QComboBox* qw1 = static_cast<QComboBox*>(m_uiForm.pairTable->cellWidget(i,1));
-    QComboBox* qw2 = static_cast<QComboBox*>(m_uiForm.pairTable->cellWidget(i,2));
+    Element* pPairElem = static_cast<Element*>(pairs->item(ip));
+
+    if ( !pPairElem->hasAttribute("name") )
+      throw Mantid::Kernel::Exception::FileError("Pair element without name" , filename);
 
-    for (int ii = 0; ii < allGroupNames.size(); ii++)
+    g.pairNames[ip] = pPairElem->getAttribute("name");
+
+    size_t fwdGroupId, bwdGroupId; // Ids of forward/backward groups
+
+    // Try to get id of the first group
+    if (Element* fwdElement = pPairElem->getChildElement("forward-group"))
     {
+      if(!fwdElement->hasAttribute("val"))
+        throw Mantid::Kernel::Exception::FileError("Pair forward-group without <val>" , filename);
+      
+      // Find the group with the given name
+      auto it = std::find(g.groupNames.begin(), g.groupNames.end(), fwdElement->getAttribute("val"));
 
-      qw1->addItem( allGroupNames[ii] );
-      qw2->addItem( allGroupNames[ii] );
-    }
-    
-    if ( qw2->count() > 1 )
-      qw2->setCurrentIndex(1);
-  }
+      if(it == g.groupNames.end())
+        throw Mantid::Kernel::Exception::FileError("Pair forward-group name not recognized" , filename);
 
+      // Get index of the iterator
+      fwdGroupId = it - g.groupNames.begin();
+    }
+    else
+    {
+      throw Mantid::Kernel::Exception::FileError("Pair element without <forward-group>" , filename);
+    }
 
+    // Try to get id of the second group
+    if(Element* bwdElement = pPairElem->getChildElement("backward-group"))
+    {
+      if(!bwdElement->hasAttribute("val"))
+        throw Mantid::Kernel::Exception::FileError("Pair backward-group without <val>" , filename);
 
+      // Find the group with the given name
+      auto it = std::find(g.groupNames.begin(), g.groupNames.end(), bwdElement->getAttribute("val"));
 
-  // add content to pair table
+      if(it == g.groupNames.end())
+        throw Mantid::Kernel::Exception::FileError("Pair backward-group name not recognized" , filename);
 
-  QStringList allPairNames;  
-  NodeList* pNL_pair = pRootElem->getElementsByTagName("pair");
-  int nPairs = static_cast<int>(pNL_pair->length());
-  if ( pNL_pair->length() > 0 )
-  {
-    for (int iPair = 0; iPair < nPairs; iPair++)
+      // Get index of the iterator
+      bwdGroupId = it - g.groupNames.begin();
+    }
+    else
     {
-      Element* pGroupElem = static_cast<Element*>(pNL_pair->item(iPair));
+      throw Mantid::Kernel::Exception::FileError("Pair element without <backward-group>" , filename);
+    }
 
-      if ( !pGroupElem->hasAttribute("name") )
-        throw Mantid::Kernel::Exception::FileError("pair element without name" , filename);
-      std::string gName = pGroupElem->getAttribute("name");
-      m_uiForm.pairTable->setItem(iPair,0, new QTableWidgetItem(gName.c_str()) );
-      allPairNames.push_back(gName.c_str());
+    g.pairs[ip] = std::make_pair(fwdGroupId, bwdGroupId);
 
-      Element* fwElement = pGroupElem->getChildElement("forward-group");
-      if (fwElement)
+    // Try to get alpha element
+    if (Element* aElement = pPairElem->getChildElement("alpha"))
+    {
+      if (!aElement->hasAttribute("val") )
+        throw Mantid::Kernel::Exception::FileError("Pair alpha element with no <val>" , filename);
+     
+      try // ... to convert value to double
       {
-        std::string ids = fwElement->getAttribute("val");
-        QComboBox* qw1 = static_cast<QComboBox*>(m_uiForm.pairTable->cellWidget(iPair,1));
-        int comboIndex = qw1->findText(ids.c_str());
-        if ( comboIndex < 0 )
-          throw Mantid::Kernel::Exception::FileError("XML pair group contains forward-group with unrecognised group name" , filename);
-        qw1->setCurrentIndex(comboIndex);
+        g.pairAlphas[ip] = boost::lexical_cast<double>(aElement->getAttribute("val"));
       }
-      else
+      catch(boost::bad_lexical_cast&)
       {
-        throw Mantid::Kernel::Exception::FileError("XML pair group contains no <forward-group> elements:" , filename);
+        throw Mantid::Kernel::Exception::FileError("Pair alpha value is not a number" , filename);
       }   
+    }
+    // If alpha element not there, default it to 1.0
+    else 
+    {
+      g.pairAlphas[ip] = 1.0;
+    }
 
-      Element* bwElement = pGroupElem->getChildElement("backward-group");
-      if (bwElement)
-      {
-        std::string ids = bwElement->getAttribute("val");
-        QComboBox* qw2 = static_cast<QComboBox*>(m_uiForm.pairTable->cellWidget(iPair,2));
-        int comboIndex = qw2->findText(ids.c_str());
-        if ( comboIndex < 0 )
-          throw Mantid::Kernel::Exception::FileError("XML pair group contains backward-group with unrecognised group name" , filename);
-        qw2->setCurrentIndex(comboIndex);
-      }
-      else
-      {
-        throw Mantid::Kernel::Exception::FileError("XML pair group contains no <backward-group> elements:" , filename);
-      }
+  }
+  
+  pairs->release(); 
 
-      Element* element = pGroupElem->getChildElement("alpha");
-      if (element)
-      {
-        if ( element->hasAttribute("val") )
-        {
-          m_uiForm.pairTable->setItem(iPair,3, new QTableWidgetItem(element->getAttribute("val").c_str()));
-        }
-        else
-          throw Mantid::Kernel::Exception::FileError("XML pair group contains an <alpha> element with no 'val' attribute:" , filename);
-      }
-      // if alpha element not there for now just default it to 1.0
-      else 
-      {
-        m_uiForm.pairTable->setItem(iPair,3, new QTableWidgetItem(1.0));
-      }
+  // Try to get description
+  if (pRootElem->hasAttribute("description"))
+  {
+    g.description = pRootElem->getAttribute("description");
+  }
 
-    }
+  // Try to get default group/pair name
+  if(Element* defaultElement = pRootElem->getChildElement("default"))
+  {
+    if(!defaultElement->hasAttribute("name"))
+      throw Mantid::Kernel::Exception::FileError("Default element with no <name>" , filename);
+    
+    g.defaultName = defaultElement->getAttribute("name");
   }
-  pNL_pair->release(); 
 
+  pDoc->release();
+}
 
-  // populate front combobox
+/**
+ * Parses information from the grouping table and saves to Grouping struct.
+ *
+ * @param form :: Muon Analysis UI containing table widgets
+ * @param    g :: Grouping struct to store parsed info to
+ */
+void parseGroupingTable(const Ui::MuonAnalysis& form, Grouping& g)
+{
+  // Parse description
+  g.description = form.groupDescription->text().toStdString();
 
-  //m_uiForm.frontGroupGroupPairComboBox->addItems(allGroupNames);
-  //m_uiForm.frontGroupGroupPairComboBox->addItems(allPairNames);
+  // Parse grouping info
+  std::vector<int> groupToRow;
+  whichGroupToWhichRow(form, groupToRow);
 
+  // Resize group arrays
+  g.groupNames.resize(groupToRow.size());
+  g.groups.resize(groupToRow.size());
 
-  if ( pRootElem->hasAttribute("description") )
+  // Fill group arrays
+  for (size_t gi = 0; gi < groupToRow.size(); gi++)
   {
-    m_uiForm.groupDescription->setText(pRootElem->getAttribute("description").c_str());
+    g.groupNames[gi] = form.groupTable->item(groupToRow[gi],0)->text().toStdString();
+    g.groups[gi] = form.groupTable->item(groupToRow[gi],1)->text().toStdString();
   }
-  else
+
+  // Parse pair info
+  std::vector<int> pairToRow;
+  whichPairToWhichRow(form, pairToRow);
+
+  // Resize pair arrays
+  g.pairNames.resize(pairToRow.size());
+  g.pairs.resize(pairToRow.size());
+  g.pairAlphas.resize(pairToRow.size());
+
+  // Fill pair arrays
+  for (size_t pi = 0; pi < pairToRow.size(); pi++)
   {
-    m_uiForm.groupDescription->setText("");
-  }
+    g.pairNames[pi] = form.pairTable->item(pairToRow[pi],0)->text().toStdString();
+
+    QComboBox* fwd = static_cast<QComboBox*>(form.pairTable->cellWidget(pairToRow[pi],1));
+    QComboBox* bwd = static_cast<QComboBox*>(form.pairTable->cellWidget(pairToRow[pi],2));
 
-  // reads default choice 
+    g.pairs[pi] = std::make_pair(fwd->currentIndex(), bwd->currentIndex());
 
-  Element* element = pRootElem->getChildElement("default");
-  if (element)
+    g.pairAlphas[pi] = form.pairTable->item(pairToRow[pi],3)->text().toDouble();
+  } 
+
+  // Use currently selected group/pair as default value
+  g.defaultName = form.frontGroupGroupPairComboBox->currentText().toStdString();
+}
+
+/**
+ * Fills in the grouping table using information from provided Grouping struct.
+ *
+ * @param    g :: Grouping struct to use for filling the table
+ * @param form :: Muon Analysis UI containing table widgets
+ */
+void fillGroupingTable(const Grouping& g, Ui::MuonAnalysis& form)
+{
+  // Add groups to a table
+  for(int gi = 0; gi < static_cast<int>(g.groups.size()); gi++)
   {
-    if ( element->hasAttribute("name") )
-    {
-      setGroupGroupPair(m_uiForm, element->getAttribute("name"));
-    }
+    form.groupTable->setItem(gi, 0, new QTableWidgetItem(g.groupNames[gi].c_str()));
+    form.groupTable->setItem(gi, 1, new QTableWidgetItem(g.groups[gi].c_str()));
+  }
+
+  // Add pairs to the table
+  for(int pi = 0; pi < static_cast<int>(g.pairs.size()); pi++)
+  {
+    // Set the name
+    form.pairTable->setItem(pi, 0, new QTableWidgetItem(g.pairNames[pi].c_str()));
+
+    // Set selected forward/backward groups
+    QComboBox* fwd = static_cast<QComboBox*>(form.pairTable->cellWidget(pi,1));
+    fwd->setCurrentIndex(static_cast<int>(g.pairs[pi].first));
+    QComboBox* bwd = static_cast<QComboBox*>(form.pairTable->cellWidget(pi,2));
+    bwd->setCurrentIndex(static_cast<int>(g.pairs[pi].second));
+
+    // Set alpha
+    form.pairTable->setItem(pi, 3, 
+      new QTableWidgetItem(boost::lexical_cast<std::string>(g.pairAlphas[pi]).c_str()));
   }
 
+  // Set description
+  form.groupDescription->setText(g.description.c_str());
 
-  pDoc->release();
+  // Select default element
+  setGroupGroupPair(form, g.defaultName);
 }
 
-
 /**
  * Set Group / Group Pair name
  *
@@ -321,7 +373,49 @@ void setGroupGroupPair(Ui::MuonAnalysis& m_uiForm, const std::string& name)
   }
 }
 
+/**
+ * Groups the workspace according to grouping provided.
+ *
+ * @param ws :: Workspace to group
+ * @param  g :: The grouping information
+ * @return Sptr to created grouped workspace
+ */
+MatrixWorkspace_sptr groupWorkspace(MatrixWorkspace_const_sptr ws, const Grouping& g)
+{
+  // As I couldn't specify multiple groups for GroupDetectors, I am going down quite a complicated
+  // route - for every group distinct grouped workspace is created using GroupDetectors. These
+  // workspaces are then merged into the output workspace.
+
+  // Create output workspace
+  MatrixWorkspace_sptr outWs =
+    WorkspaceFactory::Instance().create(ws, g.groups.size(), ws->readX(0).size(), ws->blocksize());
+
+  for(size_t gi = 0; gi < g.groups.size(); gi++)
+  {
+    Mantid::API::IAlgorithm_sptr alg = AlgorithmManager::Instance().create("GroupDetectors");
+    alg->setChild(true); // So Output workspace is not added to the ADS
+    alg->initialize();
+    alg->setProperty("InputWorkspace", boost::const_pointer_cast<MatrixWorkspace>(ws));
+    alg->setPropertyValue("SpectraList", g.groups[gi]);
+    alg->setPropertyValue("OutputWorkspace", "grouped"); // Is not actually used, just to make validators happy
+    alg->execute();
+
+    MatrixWorkspace_sptr grouped = alg->getProperty("OutputWorkspace");
+
+    // Copy the spectrum
+    *(outWs->getSpectrum(gi)) = *(grouped->getSpectrum(0));
+
+    // Update spectrum number
+    outWs->getSpectrum(gi)->setSpectrumNo(static_cast<specid_t>(gi));
+
+    // Copy to the output workspace
+    outWs->dataY(gi) = grouped->readY(0);
+    outWs->dataX(gi) = grouped->readX(0);
+    outWs->dataE(gi) = grouped->readE(0);
+  }
 
+  return outWs;
+}
 
 /**
  * create 'map' relating group number to row number in group table
@@ -329,7 +423,7 @@ void setGroupGroupPair(Ui::MuonAnalysis& m_uiForm, const std::string& name)
  * @param m_uiForm :: The UI form
  * @param groupToRow :: The 'map' returned
  */
-void whichGroupToWhichRow(Ui::MuonAnalysis& m_uiForm, std::vector<int>& groupToRow)
+void whichGroupToWhichRow(const Ui::MuonAnalysis& m_uiForm, std::vector<int>& groupToRow)
 {
   groupToRow.clear();
 
@@ -369,7 +463,7 @@ void whichGroupToWhichRow(Ui::MuonAnalysis& m_uiForm, std::vector<int>& groupToR
  * @param m_uiForm :: The UI form
  * @param pairToRow :: The 'map' returned
  */
-void whichPairToWhichRow(Ui::MuonAnalysis& m_uiForm, std::vector<int>& pairToRow)
+void whichPairToWhichRow(const Ui::MuonAnalysis& m_uiForm, std::vector<int>& pairToRow)
 {
   pairToRow.clear();
 
diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp
index bed038f634e70f29e8c75be0595528e1ff27a145..106ceb3c37c4551f3d145f1c452406fbedad3003 100644
--- a/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp
+++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MuonAnalysis.cpp
@@ -85,27 +85,7 @@ MuonAnalysis::MuonAnalysis(QWidget *parent) :
   m_groupTableRowInFocus(0), m_pairTableRowInFocus(0),m_tabNumber(0), m_groupNames(), 
   m_settingsGroup("CustomInterfaces/MuonAnalysis/"),  m_updating(false), m_loaded(false), 
   m_deadTimesChanged(false), m_textToDisplay(""), m_nexusTimeZero(0.0)
-{
-  try
-  {
-    Poco::File tempFile(ConfigService::Instance().getInstrumentDirectory());
-
-    // If the instrument directory can't be written to... (linux problem)
-    if (tempFile.exists() && !tempFile.canWrite() ) 
-    {
-      g_log.information() << "Instrument directory is read only, writing temp grouping to system temp.\n";
-      m_groupingTempFilename = ConfigService::Instance().getTempDir()+"tempMuonAnalysisGrouping.xml";
-    }
-    else
-    {
-      m_groupingTempFilename = ConfigService::Instance().getInstrumentDirectory()+"Grouping/tempMuonAnalysisGrouping.xml";
-    }
-  }
-  catch(...)
-  {
-    g_log.debug() << "Problem writing temp grouping file";
-  }
-}
+{}
 
 /**
  * Initialize local Python environmnet. 
@@ -405,7 +385,9 @@ void MuonAnalysis::runSaveGroupButton()
 
   if( ! groupingFile.isEmpty() )
   {
-    saveGroupingTabletoXML(m_uiForm, groupingFile.toStdString());
+    Grouping groupingToSave;
+    parseGroupingTable(m_uiForm, groupingToSave);
+    saveGroupingToXML(groupingToSave, groupingFile.toStdString());
     
     QString directory = QFileInfo(groupingFile).path();
     prevValues.setValue("dir", directory);
@@ -438,20 +420,23 @@ void MuonAnalysis::runLoadGroupButton()
   QString directory = QFileInfo(groupingFile).path();
   prevValues.setValue("dir", directory);
 
-  saveGroupingTabletoXML(m_uiForm, m_groupingTempFilename);
-  clearTablesAndCombo();
+  Grouping loadedGrouping;
 
   try
   {
-    loadGroupingXMLtoTable(m_uiForm, groupingFile.toStdString());
+    loadGroupingFromXML(groupingFile.toStdString(), loadedGrouping);
   }
   catch (Exception::FileError& e)
   {
+    g_log.error("Unable to load grouping. Data left unchanged");
     g_log.error(e.what());
-    g_log.error("Revert to previous grouping");
-    loadGroupingXMLtoTable(m_uiForm, m_groupingTempFilename);
+    m_updating = false;
+    return;
   }
 
+  clearTablesAndCombo();
+  fillGroupingTable(loadedGrouping, m_uiForm);
+
   // add number of detectors column to group table
   int numRows = m_uiForm.groupTable->rowCount();
   for (int i = 0; i < numRows; i++)
@@ -1201,8 +1186,6 @@ void MuonAnalysis::inputFileChanged(const QStringList& files)
       setDummyGrouping(static_cast<int>(matrix_workspace->getInstrument()->getDetectorIDs().size()));
 
     if ( !applyGroupingToWS(m_workspace_name, m_workspace_name+"Grouped") )
-      // TODO: applyGroupingToWS shows it's own messages as well. Should make it throw exceptions 
-      //       instead.
       throw std::runtime_error("Couldn't apply grouping");
 
     // Populate instrument fields
@@ -2612,63 +2595,86 @@ bool MuonAnalysis::isGroupingSet()
 }
 
 /**
- * Apply grouping specified in xml file to workspace
- *
- * @param inputWS :: The input workspace to apply grouping
- * @param outputWS :: The resulting workspace
- * @param filename :: Name of grouping file
+ * Apply whatever grouping is specified in GUI tables to workspace.
  */
-bool MuonAnalysis::applyGroupingToWS( const std::string& inputWS,  const std::string& outputWS,
-   const std::string& filename)
+bool MuonAnalysis::applyGroupingToWS( const std::string& inputWsName,  const std::string& outputWsName)
 {
-  if ( AnalysisDataService::Instance().doesExist(inputWS) )
-  {
-    AnalysisDataService::Instance().remove(outputWS);
+  if (!isGroupingSet() || !AnalysisDataService::Instance().doesExist(inputWsName))
+    return false;
 
-    Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("GroupDetectors");
-    alg->setPropertyValue("InputWorkspace", inputWS);
-    alg->setPropertyValue("OutputWorkspace", outputWS);
-    alg->setPropertyValue("MapFile", filename);
-    try
-    {
-      alg->execute();
-      return true;
-    }
-    catch(...)
-    {
-      m_optionTab->noDataAvailable();
-      QMessageBox::warning(this, "MantidPlot - MuonAnalysis", "Can't group data file according to group-table. Plotting disabled.");
-      return false;
-    }
+  std::string complaint = isGroupingAndDataConsistent();
+  if (!( complaint.empty() ) )
+  {
+    if (m_uiForm.frontPlotButton->isEnabled() )
+      QMessageBox::warning(this, "MantidPlot - MuonAnalysis", complaint.c_str());
+    m_optionTab->noDataAvailable();
+    return false;
+  }
+  else
+  {
+    if (!m_uiForm.frontPlotButton->isEnabled() )
+      m_optionTab->nowDataAvailable();
   }
-  return false;
-}
 
-/**
- * Apply whatever grouping is specified in GUI tables to workspace.
- */
-bool MuonAnalysis::applyGroupingToWS( const std::string& inputWS,  const std::string& outputWS)
-{
-  if ( isGroupingSet() && AnalysisDataService::Instance().doesExist(inputWS) )
+  // If output workspace exists, remove explicitly, so even if something goes wrong - old data 
+  // is not used
+  if(AnalysisDataService::Instance().doesExist(outputWsName))
   {
+    // Using DeleteWorkspace algorithm so if outputWs is a group - it is fully removed
+    Mantid::API::IAlgorithm_sptr rmWs = AlgorithmManager::Instance().create("DeleteWorkspace");
+    rmWs->initialize();
+    rmWs->setPropertyValue("Workspace", outputWsName);
+    rmWs->execute();
+  }
 
-    std::string complaint = isGroupingAndDataConsistent();
-    if (!( complaint.empty() ) )
-    {
-      if (m_uiForm.frontPlotButton->isEnabled() )
-        QMessageBox::warning(this, "MantidPlot - MuonAnalysis", complaint.c_str());
-      m_optionTab->noDataAvailable();
-      return false;
-    }
+  Grouping tableGrouping;
+  parseGroupingTable(m_uiForm, tableGrouping);
+
+  // Retrieve input workspace
+  Workspace_sptr inputWs = AnalysisDataService::Instance().retrieve(inputWsName);
+
+  Workspace_sptr outputWs;
+
+  try // ... to group
+  {
+    // Single workspace
+    if(MatrixWorkspace_sptr ws = boost::dynamic_pointer_cast<MatrixWorkspace>(inputWs))
     {
-      if (!m_uiForm.frontPlotButton->isEnabled() )
-        m_optionTab->nowDataAvailable();
+      outputWs = groupWorkspace(ws, tableGrouping);
     }
+    // Workspace group
+    else if(WorkspaceGroup_sptr group = boost::dynamic_pointer_cast<WorkspaceGroup>(inputWs))
+    { 
+      // Create output group
+      WorkspaceGroup_sptr outputGroup = boost::make_shared<WorkspaceGroup>();
+  
+      for(size_t i = 0; i < group->size(); i++)
+      {
+        if(MatrixWorkspace_sptr member = boost::dynamic_pointer_cast<MatrixWorkspace>(group->getItem(i)))
+        {
+          MatrixWorkspace_sptr groupedMember = groupWorkspace(member, tableGrouping);
+
+          outputGroup->addWorkspace(groupedMember);
+        }
+        else
+          throw std::invalid_argument("Group contains unsupported workspace type");
+      }
 
-    saveGroupingTabletoXML(m_uiForm, m_groupingTempFilename);
-    return applyGroupingToWS(inputWS, outputWS, m_groupingTempFilename);
+      outputWs = outputGroup;
+    }
+    else
+      throw std::invalid_argument("Unsupported workspace type");
   }
-  return false;
+  catch(std::exception& e)
+  {
+    m_optionTab->noDataAvailable();
+    g_log.error(e.what());
+    return false;
+  }
+
+  AnalysisDataService::Instance().add(outputWsName, outputWs);
+
+  return true;
 }
 
 /**
@@ -2885,7 +2891,6 @@ void MuonAnalysis::startUpLook()
 */
 void MuonAnalysis::setGroupingFromNexus(const QString& nexusFile)
 {
-  // for now do try to set grouping from nexus file if it is already set
   if ( isGroupingSet() )
     return;
 
@@ -3087,15 +3092,20 @@ void MuonAnalysis::setGroupingFromIDF(const std::string& mainFieldDirection, Mat
 
   if ( groupFile.size() == 1 )
   {
+    Grouping loadedGrouping;
+
     try
     {
-      loadGroupingXMLtoTable(m_uiForm, directoryName+groupFile[0]);
+      loadGroupingFromXML(directoryName+groupFile[0], loadedGrouping);
     }
     catch (...)
     {
-      QMessageBox::warning(this, "MantidPlot - MuonAnalysis", QString("Can't load default grouping file in IDF.\n")
-        + "with name: " + groupFile[0].c_str());
+      QMessageBox::warning(this, "MantidPlot - MuonAnalysis", 
+        QString("Can't load default grouping file in IDF. \n With name: ") + groupFile[0].c_str());
+      return;
     }
+
+    fillGroupingTable(loadedGrouping, m_uiForm);
   }
 }
 
diff --git a/Code/Mantid/MantidQt/CustomInterfaces/test/IO_MuonGroupingTest.h b/Code/Mantid/MantidQt/CustomInterfaces/test/IO_MuonGroupingTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..9ad7e7f22b46d0db6601b5971fddb1183ddb79d9
--- /dev/null
+++ b/Code/Mantid/MantidQt/CustomInterfaces/test/IO_MuonGroupingTest.h
@@ -0,0 +1,179 @@
+#ifndef MANTID_CUSTOMINTERFACES_IO_MUONGROUPINGTEST_H_
+#define MANTID_CUSTOMINTERFACES_IO_MUONGROUPINGTEST_H_
+
+#include <numeric>
+
+#include <cxxtest/TestSuite.h>
+#include <Poco/Path.h>
+#include <Poco/File.h>
+
+#include "MantidAPI/AlgorithmManager.h"
+#include "MantidAPI/FrameworkManager.h"
+#include "MantidQtCustomInterfaces/IO_MuonGrouping.h"
+
+using namespace Mantid::API;
+using namespace MantidQt::CustomInterfaces::Muon;
+
+class IO_MuonGroupingTest : 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 IO_MuonGroupingTest *createSuite() { return new IO_MuonGroupingTest(); }
+  static void destroySuite( IO_MuonGroupingTest *suite ) { delete suite; }
+
+  /// Constructor
+  IO_MuonGroupingTest()
+  {
+    using Mantid::Kernel::ConfigService;
+
+    auto dataPaths = ConfigService::Instance().getDataSearchDirs();
+
+    // Find the path of AutoTestData
+    for(auto it = dataPaths.begin(); it != dataPaths.end(); ++it)
+    {
+      Poco::Path path(*it);
+
+      if(path.directory(path.depth() - 1) == "AutoTestData")
+      {
+        m_testDataDir = *it;
+        break;
+      }
+    }
+
+    TSM_ASSERT("Unable to find AutoTestData directory", !m_testDataDir.empty());
+
+    m_tmpDir = ConfigService::Instance().getTempDir();
+
+    // To make sure API is initialized properly
+    FrameworkManager::Instance();
+  }
+
+  void test_loadGroupingFromXML()
+  {
+    Grouping g;
+
+    TS_ASSERT_THROWS_NOTHING(loadGroupingFromXML(m_testDataDir + "MUSRGrouping.xml", g));
+
+    TS_ASSERT_EQUALS(g.groupNames.size(), 2);
+    TS_ASSERT_EQUALS(g.groupNames[0], "fwd");
+    TS_ASSERT_EQUALS(g.groupNames[1], "bwd");
+
+    TS_ASSERT_EQUALS(g.groups.size(), 2);
+    TS_ASSERT_EQUALS(g.groups[0], "33-64");
+    TS_ASSERT_EQUALS(g.groups[1], "1-32");
+
+    TS_ASSERT_EQUALS(g.pairNames.size(), 1);
+    TS_ASSERT_EQUALS(g.pairNames[0], "long");
+
+    TS_ASSERT_EQUALS(g.pairs.size(), 1);
+    TS_ASSERT_EQUALS(g.pairs[0].first, 0);
+    TS_ASSERT_EQUALS(g.pairs[0].second, 1);
+
+    TS_ASSERT_EQUALS(g.pairAlphas.size(), 1);
+    TS_ASSERT_EQUALS(g.pairAlphas[0], 1);
+
+    TS_ASSERT_EQUALS(g.description, "musr longitudinal (64 detectors)");
+    TS_ASSERT_EQUALS(g.defaultName, "long");
+  }
+
+  void test_saveGroupingToXML()
+  {
+    Grouping g, lg;
+
+    std::string tmpFile = m_tmpDir + "tmp_MUSRGrouping.xml";
+
+    // Load grouping first
+    TS_ASSERT_THROWS_NOTHING(loadGroupingFromXML(m_testDataDir + "MUSRGrouping.xml", g));
+
+    // Then save it
+    TS_ASSERT_THROWS_NOTHING(saveGroupingToXML(g, tmpFile));
+
+    // And load it again
+    TS_ASSERT_THROWS_NOTHING(loadGroupingFromXML(tmpFile, lg));
+
+    // Check that all the information was saved
+    TS_ASSERT_EQUALS(lg.groupNames.size(), 2);
+    TS_ASSERT_EQUALS(lg.groupNames[0], "fwd");
+    TS_ASSERT_EQUALS(lg.groupNames[1], "bwd");
+
+    TS_ASSERT_EQUALS(lg.groups.size(), 2);
+    TS_ASSERT_EQUALS(lg.groups[0], "33-64");
+    TS_ASSERT_EQUALS(lg.groups[1], "1-32");
+
+    TS_ASSERT_EQUALS(lg.pairNames.size(), 1);
+    TS_ASSERT_EQUALS(lg.pairNames[0], "long");
+
+    TS_ASSERT_EQUALS(lg.pairs.size(), 1);
+    TS_ASSERT_EQUALS(lg.pairs[0].first, 0);
+    TS_ASSERT_EQUALS(lg.pairs[0].second, 1);
+
+    TS_ASSERT_EQUALS(lg.pairAlphas.size(), 1);
+    TS_ASSERT_EQUALS(lg.pairAlphas[0], 1);
+
+    TS_ASSERT_EQUALS(lg.description, "musr longitudinal (64 detectors)");
+    TS_ASSERT_EQUALS(lg.defaultName, "long");
+
+    // Remove temporary file
+    Poco::File(tmpFile).remove();
+  }
+
+  void test_groupWorkspace()
+  {
+    // Load grouping for MUSR
+    Grouping g;
+    TS_ASSERT_THROWS_NOTHING(loadGroupingFromXML(m_testDataDir + "MUSRGrouping.xml", g));
+
+    // Load MUSR data file
+    IAlgorithm_sptr loadAlg = AlgorithmManager::Instance().create("LoadMuonNexus");
+    loadAlg->setChild(true); // So outptu ws don't end up in the ADS
+    loadAlg->initialize();
+    loadAlg->setPropertyValue("Filename", m_testDataDir + "MUSR00015189.nxs");
+    loadAlg->setPropertyValue("OutputWorkspace", "data"); // Is not used, just for validator
+    loadAlg->execute();
+
+    Workspace_sptr loadedWs = loadAlg->getProperty("OutputWorkspace");
+    WorkspaceGroup_sptr loadedGroup = boost::dynamic_pointer_cast<WorkspaceGroup>(loadedWs);
+    MatrixWorkspace_sptr ws = boost::dynamic_pointer_cast<MatrixWorkspace>(loadedGroup->getItem(0));
+
+    // Group the loaded workspace using loaded grouping
+    MatrixWorkspace_sptr gWs; // Grouped workspace
+    TS_ASSERT_THROWS_NOTHING(gWs = groupWorkspace(ws, g));
+    TS_ASSERT(gWs);
+
+    if(!gWs) 
+      return;
+
+    // Check that was grouped properly
+    TS_ASSERT_EQUALS(gWs->getNumberHistograms(), 2);
+
+    TS_ASSERT_EQUALS(gWs->getSpectrum(0)->getDetectorIDs(), setFromRange(33, 64));
+    TS_ASSERT_EQUALS(gWs->getSpectrum(1)->getDetectorIDs(), setFromRange(1, 32));
+
+    TS_ASSERT_EQUALS(std::accumulate(gWs->readY(0).begin(), gWs->readY(0).end(), 0.0), 355655);
+    TS_ASSERT_DELTA(std::accumulate(gWs->readX(0).begin(), gWs->readX(0).end(), 0.0), 30915.5, 0.1);
+    TS_ASSERT_DELTA(std::accumulate(gWs->readE(0).begin(), gWs->readE(0).end(), 0.0), 14046.9, 0.1);
+
+    TS_ASSERT_EQUALS(std::accumulate(gWs->readY(1).begin(), gWs->readY(1).end(), 0.0), 262852);
+    TS_ASSERT_EQUALS(gWs->readX(1), gWs->readX(0));
+    TS_ASSERT_DELTA(std::accumulate(gWs->readE(1).begin(), gWs->readE(1).end(), 0.0), 12079.8, 0.1);
+  }
+
+private:
+  std::string m_testDataDir;
+  std::string m_tmpDir;
+
+  std::set<int> setFromRange(int from, int to)
+  {
+    std::set<int> result;
+
+    for(int i = from; i <= to; i++)
+      result.insert(i);
+    
+    return result;
+  }
+
+};
+
+
+#endif /* MANTID_CUSTOMINTERFACES_IO_MUONGROUPINGTEST_H_ */
\ No newline at end of file