From 34bffa936b2d84d50ec80b8d3fbb5c38fcde5ac0 Mon Sep 17 00:00:00 2001
From: Roman Tolchenov <roman.tolchenov@stfc.ac.uk>
Date: Thu, 20 Sep 2012 10:58:21 +0100
Subject: [PATCH] Re #5838. Saving the changes to a branch

---
 Code/Mantid/Framework/API/CMakeLists.txt      |   2 +-
 Code/Mantid/Framework/API/src/FileFinder.cpp  |   3 +-
 .../Framework/API/test/ExperimentInfoTest.h   |   5 +
 .../Framework/API/test/FileFinderTest.h       |  15 ++-
 .../src/GetTimeSeriesLogInformation.cpp       |   2 +-
 .../Framework/DataObjects/src/Workspace2D.cpp |   2 +-
 .../Kernel/inc/MantidKernel/InstrumentInfo.h  |  18 ++-
 .../inc/MantidKernel/MultiFileNameParser.h    |   8 +-
 .../Framework/Kernel/src/InstrumentInfo.cpp   | 119 ++++++++++++++++--
 .../Kernel/src/MultiFileNameParser.cpp        |  39 +++---
 .../Framework/Kernel/test/FacilitiesTest.h    |   9 +-
 .../Kernel/test/InstrumentInfoTest.h          |  99 ++++++++++++++-
 .../Kernel/test/MultiFileNameParserTest.h     |  13 ++
 Code/Mantid/instrument/Facilities.xml         |  36 ++++--
 14 files changed, 311 insertions(+), 59 deletions(-)

diff --git a/Code/Mantid/Framework/API/CMakeLists.txt b/Code/Mantid/Framework/API/CMakeLists.txt
index 901593b63ec..5cab1ee7c95 100644
--- a/Code/Mantid/Framework/API/CMakeLists.txt
+++ b/Code/Mantid/Framework/API/CMakeLists.txt
@@ -288,7 +288,7 @@ set ( TEST_FILES
 	ILiveListenerTest.h
 	IMDWorkspaceTest.h
 	ISpectrumTest.h
-	IkedaCarpenterModeratorTest.h
+#	IkedaCarpenterModeratorTest.h
 	ImmutableCompositeFunctionTest.h
 	ImplicitFunctionParserFactoryTest.h
 	InstrumentDataServiceTest.h
diff --git a/Code/Mantid/Framework/API/src/FileFinder.cpp b/Code/Mantid/Framework/API/src/FileFinder.cpp
index f562388138d..a62bd195cf0 100644
--- a/Code/Mantid/Framework/API/src/FileFinder.cpp
+++ b/Code/Mantid/Framework/API/src/FileFinder.cpp
@@ -265,8 +265,9 @@ namespace Mantid
         runPart = hint.substr(nChars);
       }
 
+      unsigned int irunPart = boost::lexical_cast<unsigned int>( runPart );
       Kernel::InstrumentInfo instr = Kernel::ConfigService::Instance().getInstrument(instrPart);
-      size_t nZero = instr.zeroPadding();
+      size_t nZero = instr.zeroPadding(irunPart);
       // remove any leading zeros in case there are too many of them
       std::string::size_type i = runPart.find_first_not_of('0');
       runPart.erase(0, i);
diff --git a/Code/Mantid/Framework/API/test/ExperimentInfoTest.h b/Code/Mantid/Framework/API/test/ExperimentInfoTest.h
index 45443886e2f..f58e0198fad 100644
--- a/Code/Mantid/Framework/API/test/ExperimentInfoTest.h
+++ b/Code/Mantid/Framework/API/test/ExperimentInfoTest.h
@@ -64,6 +64,10 @@ class ExperimentInfoTest : public CxxTest::TestSuite
 {
 public:
 
+  ExperimentInfoTest()
+  {
+    ConfigService::Instance().updateFacilities();
+  }
 
   void test_GetInstrument_default()
   {
@@ -546,6 +550,7 @@ public:
   //
   void testHelperFunctions()
   {
+    ConfigService::Instance().updateFacilities();
     ExperimentInfo helper;
     std::string boevs = helper.getInstrumentFilename("BIOSANS", "2100-01-31 22:59:59");
     TS_ASSERT(!boevs.empty());
diff --git a/Code/Mantid/Framework/API/test/FileFinderTest.h b/Code/Mantid/Framework/API/test/FileFinderTest.h
index d4d2d11a8c7..be4d38f7b31 100644
--- a/Code/Mantid/Framework/API/test/FileFinderTest.h
+++ b/Code/Mantid/Framework/API/test/FileFinderTest.h
@@ -39,22 +39,27 @@ public:
       "    <instrument name=\"HRPD\" shortname=\"HRP\">"
       "      <technique>Powder Diffraction</technique>"
       "    </instrument>"
-      "    <instrument name=\"ABCD\" shortname=\"ABC\" zeropadding=\"8\">"
+      "    <instrument name=\"ABCD\" shortname=\"ABC\" >"
+      "      <zeropadding size=\"8\"/>"
       "      <technique>Powder Diffraction</technique>"
       "    </instrument>"
-      "    <instrument name=\"EFG2H\" shortname=\"EFG2H\" zeropadding=\"8\">"
+      "    <instrument name=\"EFG2H\" shortname=\"EFG2H\">"
+      "      <zeropadding size=\"8\"/>"
       "      <technique>Powder Diffraction</technique>"
       "    </instrument>"
       "    <instrument name=\"CRISP\" shortname=\"CSP\">"
       "      <technique>Technique</technique>"
       "    </instrument>"
-      "    <instrument name=\"MUSR\" zeropadding=\"8\">"
+      "    <instrument name=\"MUSR\">"
+      "      <zeropadding size=\"8\"/>"
       "      <technique>Powder Diffraction</technique>"
       "    </instrument>"
-      "    <instrument name=\"LOQ\" zeropadding=\"5\">"
+      "    <instrument name=\"LOQ\">"
+      "     <zeropadding size=\"5\"/>"
       "     <technique>Small Angle Scattering</technique>"
       "    </instrument>"
-      "    <instrument name=\"OFFSPEC\"  zeropadding=\"8\">"
+      "    <instrument name=\"OFFSPEC\">"
+      "      <zeropadding size=\"8\"/>"
       "      <technique>Reflectometer</technique>"
       "    </instrument>"
       "  </facility>"
diff --git a/Code/Mantid/Framework/Algorithms/src/GetTimeSeriesLogInformation.cpp b/Code/Mantid/Framework/Algorithms/src/GetTimeSeriesLogInformation.cpp
index 0a5608e870e..ac5f38f88c2 100644
--- a/Code/Mantid/Framework/Algorithms/src/GetTimeSeriesLogInformation.cpp
+++ b/Code/Mantid/Framework/Algorithms/src/GetTimeSeriesLogInformation.cpp
@@ -800,7 +800,7 @@ namespace Algorithms
   void GetTimeSeriesLogInformation::exportErrorLog(API::MatrixWorkspace_sptr ws, std::vector<Kernel::DateAndTime> abstimevec, double dts)
   {
     std::string outputdir = getProperty("OutputDirectory");
-    if (outputdir[outputdir.size()-1] != '/')
+    if (!outputdir.empty() && outputdir[outputdir.size()-1] != '/')
       outputdir += "/";
 
     std::string ofilename = outputdir + "errordeltatime.txt";
diff --git a/Code/Mantid/Framework/DataObjects/src/Workspace2D.cpp b/Code/Mantid/Framework/DataObjects/src/Workspace2D.cpp
index 9a0afe8fb37..64ebbb45531 100644
--- a/Code/Mantid/Framework/DataObjects/src/Workspace2D.cpp
+++ b/Code/Mantid/Framework/DataObjects/src/Workspace2D.cpp
@@ -30,7 +30,7 @@ namespace Mantid
     ///Destructor
     Workspace2D::~Workspace2D()
     {
-      // Clear out the memory.
+      // Clear out the memory
       for (size_t i=0; i<data.size(); i++)
       {
         delete data[i];
diff --git a/Code/Mantid/Framework/Kernel/inc/MantidKernel/InstrumentInfo.h b/Code/Mantid/Framework/Kernel/inc/MantidKernel/InstrumentInfo.h
index 09fec6467b5..5a4fd228036 100644
--- a/Code/Mantid/Framework/Kernel/inc/MantidKernel/InstrumentInfo.h
+++ b/Code/Mantid/Framework/Kernel/inc/MantidKernel/InstrumentInfo.h
@@ -8,6 +8,7 @@
 #include "MantidKernel/Logger.h"
 #include <set>
 #include <string>
+#include <map>
 
 //----------------------------------------------------------------------
 // Forward declarations
@@ -63,8 +64,10 @@ public:
   const std::string name() const;
   /// Return the short name of the instrument
   const std::string shortName() const ;
-  /// Returns zero padding for this instrument
-  int zeroPadding() const;
+  /// Returns zero padding for this instrument and a run number
+  int zeroPadding(unsigned int runNumber) const;
+  /// Returns file prefix for this instrument and a run number
+  std::string filePrefix(unsigned int runNumber) const;
   /// Returns the default delimiter between instrument name and run number
   std::string delimiter() const;
   /// Returns the name of the live listener
@@ -79,11 +82,20 @@ public:
 private:
   void fillTechniques(const Poco::XML::Element* elem);
   void fillLiveData(const Poco::XML::Element* elem);
+  void fillZeroPadding(const Poco::XML::Element* elem);
+
+  /// Typedef for the zeropadding holder, first is starting run-number, 
+  /// second is file prefix - zero padding pair
+  typedef std::map<unsigned int, std::pair<std::string,int> > ZeroPaddingMap;
+  /// get the zeropadding part
+  int getZeroPadding(ZeroPaddingMap::const_iterator it) const {return it->second.second;}
+  /// get the prefix part
+  const std::string& getPrefix(ZeroPaddingMap::const_iterator it) const {return it->second.first;}
 
   const FacilityInfo* m_facility;          ///< Facility
   std::string m_name;                      ///< Instrument name
   std::string m_shortName;                 ///< Instrument short name
-  int m_zeroPadding;                       ///< Zero padding
+  ZeroPaddingMap m_zeroPadding;            ///< Run number-dependent zero padding
   std::string m_delimiter;                 ///< Delimiter between instrument name and run number
   std::string m_liveListener;              ///< Name of the live listener class
   std::string m_liveDataAddress;           ///< Host & port for live data connection
diff --git a/Code/Mantid/Framework/Kernel/inc/MantidKernel/MultiFileNameParser.h b/Code/Mantid/Framework/Kernel/inc/MantidKernel/MultiFileNameParser.h
index f289b1b8b34..e0d734d16a0 100644
--- a/Code/Mantid/Framework/Kernel/inc/MantidKernel/MultiFileNameParser.h
+++ b/Code/Mantid/Framework/Kernel/inc/MantidKernel/MultiFileNameParser.h
@@ -121,7 +121,7 @@ namespace Kernel
       /// The various sections of the given string to parse.
       std::string m_dirString, m_instString, m_underscoreString, m_runString, m_extString;
       /// The instrument-specific run zero padding value.
-      int m_zeroPadding;
+      //int m_zeroPadding;
       /// All the valid instrument names.
       std::set<std::string, ReverseCaselessCompare> m_validInstNames;
     };
@@ -134,7 +134,7 @@ namespace Kernel
     {
     public:
       /// Constructor.
-      GenerateFileName(const std::string & prefix, const std::string & suffix, int zeroPadding);
+      GenerateFileName(const std::string & prefix, const std::string & suffix, const std::string & instString);
 
       /// Overloaded function operator that generates a vector of file names from a vector of runs.
       std::vector<std::string> operator()(const std::vector<unsigned int> & runs);
@@ -146,8 +146,8 @@ namespace Kernel
       std::string m_prefix;
       /// String that suffixes any generated file names.
       std::string m_suffix;
-      /// The length of zero padding needed.
-      int m_zeroPadding;
+      /// String that identifies the instrument
+      std::string m_instString;
     };
 
     /**
diff --git a/Code/Mantid/Framework/Kernel/src/InstrumentInfo.cpp b/Code/Mantid/Framework/Kernel/src/InstrumentInfo.cpp
index 6f533277d07..cf72e569c46 100644
--- a/Code/Mantid/Framework/Kernel/src/InstrumentInfo.cpp
+++ b/Code/Mantid/Framework/Kernel/src/InstrumentInfo.cpp
@@ -10,6 +10,8 @@
 #include <Poco/DOM/NodeList.h>
 #include <Poco/DOM/Text.h>
 
+#include <boost/lexical_cast.hpp>
+
 #include <algorithm>
 
 namespace Mantid
@@ -27,11 +29,6 @@ namespace Mantid
     InstrumentInfo::InstrumentInfo(const FacilityInfo* f,const Poco::XML::Element* elem)
       : m_facility(f), m_liveListener(), m_liveDataAddress()
     {
-      std::string paddingStr = elem->getAttribute("zeropadding");
-      if ( paddingStr.empty() || !Mantid::Kernel::Strings::convert(paddingStr,m_zeroPadding) )
-      {
-        m_zeroPadding = f->zeroPadding();
-      }
 
       m_name = elem->getAttribute("name");
       if (m_name.empty())
@@ -55,6 +52,7 @@ namespace Mantid
 
       fillTechniques(elem);
       fillLiveData(elem);
+      fillZeroPadding(elem);
     }
 
     /**
@@ -86,9 +84,54 @@ namespace Mantid
     }
 
     /// Returns zero padding for this instrument
-    int InstrumentInfo::zeroPadding() const
+    int InstrumentInfo::zeroPadding(unsigned int runNumber) const
     {
-      return m_zeroPadding;
+      if ( m_zeroPadding.empty() ) return m_facility->zeroPadding();
+      if ( m_zeroPadding.size() == 1 )
+      {
+        auto padding = m_zeroPadding.begin();
+        if ( runNumber >= padding->first )
+          return getZeroPadding(padding);
+        else
+          return m_facility->zeroPadding();
+      }
+      auto last = m_zeroPadding.end(); --last;
+      for(auto it = m_zeroPadding.begin(); it != last; ++it)
+      {
+        auto next = it; ++next;
+        if ( runNumber >= it->first && runNumber < next->first )
+        {
+          return getZeroPadding(it);
+        }
+      }
+      return getZeroPadding(last);
+    }
+
+    /**
+     * Returns file prefix for this instrument and a run number.
+     * @param runNumber :: A run number.
+     */
+    std::string InstrumentInfo::filePrefix(unsigned int runNumber) const
+    {
+      if ( m_zeroPadding.empty() ) return m_shortName;
+      if ( m_zeroPadding.size() == 1 )
+      {
+        auto padding = m_zeroPadding.begin();
+        if ( runNumber >= padding->first )
+          return getPrefix(padding);
+        else
+          return m_shortName;
+      }
+      auto last = m_zeroPadding.end(); --last;
+      for(auto it = m_zeroPadding.begin(); it != last; ++it)
+      {
+        auto next = it; ++next;
+        if ( runNumber >= it->first && runNumber < next->first )
+        {
+          return getPrefix(it);
+        }
+      }
+      return getPrefix(last);
     }
 
     /// Returns the name of the live listener
@@ -118,6 +161,68 @@ namespace Mantid
       return *m_facility;
     }
 
+    /// Called from constructor to fill zero padding
+    void InstrumentInfo::fillZeroPadding(const Poco::XML::Element* elem)
+    {
+      Poco::XML::NodeList* pNL_zeropadding = elem->getElementsByTagName("zeropadding");
+      unsigned long n = pNL_zeropadding->length();
+
+      for (unsigned long i = 0; i < n; ++i)
+      {
+        auto elem = dynamic_cast<Poco::XML::Element*>( pNL_zeropadding->item(i) );
+        if ( !elem ) continue;
+        // read the zero padding size
+        if ( !elem->hasAttribute("size") )
+        {
+          g_log.error("Zeropadding size is missing for instrument "+m_name);
+          throw std::runtime_error("Zeropadding size is missing for instrument "+m_name);
+        }
+        auto& sizeStr = elem->getAttribute("size");
+        int size = 0;
+        if ( !Mantid::Kernel::Strings::convert(sizeStr,size) )
+        {
+          g_log.error("Zeropadding size must be an integer value (instrument "+m_name+")");
+          throw std::runtime_error("Zeropadding size must be an integer value (instrument "+m_name+")");
+        }
+        // read the start run number
+        unsigned int startRunNumber = 0;
+        if ( !elem->hasAttribute("startRunNumber") )
+        {
+          if ( !m_zeroPadding.empty() )
+          {
+            g_log.error("Zeropadding size is missing for instrument "+m_name);
+            throw std::runtime_error("Zeropadding size is missing for instrument "+m_name);
+          }
+        }
+        else
+        {
+          auto& startRunNumberStr = elem->getAttribute("startRunNumber");
+          try
+          {
+            startRunNumber = boost::lexical_cast<unsigned int>( startRunNumberStr );
+          }
+          catch(...)
+          {
+            g_log.error("Zeropadding start run number must be an integer value (instrument "+m_name+")");
+            throw std::runtime_error("Zeropadding start run number must be an integer value (instrument "+m_name+")");
+          }
+        }
+        // read the file prefix
+        std::string prefix = m_shortName;
+        if ( elem->hasAttribute("prefix") )
+        {
+          prefix = elem->getAttribute("prefix");
+        }
+        m_zeroPadding[startRunNumber] = std::make_pair(prefix,size);
+      }
+      pNL_zeropadding->release();
+
+      if (m_zeroPadding.empty())
+      {
+        m_zeroPadding[0] = std::make_pair(m_shortName,m_facility->zeroPadding());
+      }
+    }
+
     /// Called from constructor to fill live listener name
     void InstrumentInfo::fillTechniques(const Poco::XML::Element* elem)
     {
diff --git a/Code/Mantid/Framework/Kernel/src/MultiFileNameParser.cpp b/Code/Mantid/Framework/Kernel/src/MultiFileNameParser.cpp
index 124f6668afa..385f05a0f25 100644
--- a/Code/Mantid/Framework/Kernel/src/MultiFileNameParser.cpp
+++ b/Code/Mantid/Framework/Kernel/src/MultiFileNameParser.cpp
@@ -70,7 +70,7 @@ namespace Kernel
       void validateToken(const std::string & token);
       bool matchesFully(const std::string & stringToMatch, const std::string & regexString, bool caseless = false);
       std::string getMatchingString(const std::string & regexString, const std::string & toParse, bool caseless = false);
-      std::string pad(std::string run, unsigned int padLength);
+      std::string pad(unsigned int run, const std::string& instString);
 
       std::set< std::pair<unsigned int, unsigned int> > & mergeAdjacentRanges(
         std::set< std::pair<unsigned int, unsigned int> > & ranges, 
@@ -190,7 +190,9 @@ namespace Kernel
     /// Constructor.
     Parser::Parser() :
       m_runs(), m_fileNames(), m_multiFileName(), m_dirString(), m_instString(), 
-      m_underscoreString(), m_runString(), m_extString(), m_zeroPadding(), m_validInstNames()
+      m_underscoreString(), m_runString(), m_extString(), 
+      //m_zeroPadding(),
+      m_validInstNames()
     {
       ConfigServiceImpl & config = ConfigService::Instance();
 
@@ -238,9 +240,9 @@ namespace Kernel
 
       // Set up helper functor.
       GenerateFileName generateFileName(
-        m_dirString + m_instString + m_underscoreString,
+        m_dirString,
         m_extString,
-        m_zeroPadding);
+        m_instString);
 
       // Generate complete file names for each run using helper functor.
       std::transform(
@@ -338,7 +340,7 @@ namespace Kernel
       
       InstrumentInfo instInfo = ConfigService::Instance().getInstrument(m_instString);
       m_instString = instInfo.shortName(); // Make sure we're using the shortened form of the isntrument name.
-      m_zeroPadding = instInfo.zeroPadding();
+      //m_zeroPadding = instInfo.zeroPadding(0);
 
       if(boost::starts_with(base, instInfo.delimiter()))
       {
@@ -366,8 +368,8 @@ namespace Kernel
      * @param suffix      :: a string that suffixes the generated file names.
      * @param zeroPadding :: the number of zeros with which to pad the run number of genrerated file names.
      */
-    GenerateFileName::GenerateFileName(const std::string & prefix, const std::string & suffix, int zeroPadding) :
-        m_prefix(prefix), m_suffix(suffix), m_zeroPadding(zeroPadding)
+    GenerateFileName::GenerateFileName(const std::string & prefix, const std::string & suffix, const std::string & instString) :
+        m_prefix(prefix), m_suffix(suffix), m_instString(instString)
       {}
 
     /**
@@ -402,7 +404,7 @@ namespace Kernel
       std::stringstream fileName;
 
       fileName << m_prefix
-               << pad(boost::lexical_cast<std::string>(run), m_zeroPadding)
+               << pad(run, m_instString)
                << m_suffix;
 
       return fileName.str();
@@ -728,20 +730,25 @@ namespace Kernel
       /**
        * Zero pads the run number used in a file name to required length.
        *
-       * @param run - the run number of the file.  May as well pass by value here.
-       * @param count - the required length of the string.
+       * @param run - the run number of the file.
+       * @param instString - the name of the instrument
        *
        * @returns the string, padded to the required length.
        * @throws std::runtime_error if run is longer than size of count.
        */
-      std::string pad(std::string run, unsigned int padLength)
+      std::string pad(unsigned int run, const std::string& instString)
       {
-        if(run.size() < padLength)
-          return run.insert(0, padLength - run.size(), '0');
-        else if(run.size() > padLength)
-          throw std::runtime_error("Could not parse run number \"" + run + 
+        InstrumentInfo instInfo = ConfigService::Instance().getInstrument(instString);
+        std::string prefix = instInfo.filePrefix( run ) + instInfo.delimiter();
+        unsigned int padLength = instInfo.zeroPadding( run );
+        std::string runStr = boost::lexical_cast<std::string>( run );
+        if(runStr.size() < padLength)
+          runStr.insert(0, padLength - runStr.size(), '0');
+        else if(runStr.size() > padLength)
+          throw std::runtime_error("Could not parse run number \"" + runStr + 
             "\" since the instrument run number length required is " + boost::lexical_cast<std::string>(padLength));
-        return run;
+        runStr.insert(0, prefix);
+        return runStr;
       }
 
       /**
diff --git a/Code/Mantid/Framework/Kernel/test/FacilitiesTest.h b/Code/Mantid/Framework/Kernel/test/FacilitiesTest.h
index 7475e6ae58f..cb0e31db76f 100644
--- a/Code/Mantid/Framework/Kernel/test/FacilitiesTest.h
+++ b/Code/Mantid/Framework/Kernel/test/FacilitiesTest.h
@@ -102,7 +102,9 @@ public:
       "    <instrument name=\"HRPD\" shortname=\"HRP\">"
       "      <technique>Powder Diffraction</technique>"
       "    </instrument>"
-      "    <instrument name=\"WISH\" zeropadding=\"8\">"
+      "    <instrument name=\"WISH\" >"
+      "      <zeropadding size=\"8\"/>"
+      "      <zeropadding size=\"15\" startRunNumber=\"300\"/>"
       "      <technique>Powder Diffraction</technique>"
       "      <technique>Single Crystal Diffraction</technique>"
       "    </instrument>"
@@ -137,13 +139,14 @@ public:
     InstrumentInfo instr = fac->instrument("HRP"); // Tests getting by short name
     TS_ASSERT_EQUALS(instr.name(),"HRPD");
     TS_ASSERT_EQUALS(instr.shortName(),"HRP");
-    TS_ASSERT_EQUALS(instr.zeroPadding(),5);
+    TS_ASSERT_EQUALS(instr.zeroPadding(123),5);
 
     TS_ASSERT_THROWS_NOTHING(fac->instrument("WISH"));
     instr = fac->instrument("WISH");
     TS_ASSERT_EQUALS(instr.name(),"WISH");
     TS_ASSERT_EQUALS(instr.shortName(),"WISH");
-    TS_ASSERT_EQUALS(instr.zeroPadding(),8);
+    TS_ASSERT_EQUALS(instr.zeroPadding(123),8);
+    TS_ASSERT_EQUALS(instr.zeroPadding(301),15);
 
     const std::vector<InstrumentInfo> pwdInstr = fac->instruments("Powder Diffraction");
     TS_ASSERT_EQUALS(pwdInstr.size(),2);
diff --git a/Code/Mantid/Framework/Kernel/test/InstrumentInfoTest.h b/Code/Mantid/Framework/Kernel/test/InstrumentInfoTest.h
index 0772e9e877e..70d5068bed1 100644
--- a/Code/Mantid/Framework/Kernel/test/InstrumentInfoTest.h
+++ b/Code/Mantid/Framework/Kernel/test/InstrumentInfoTest.h
@@ -37,7 +37,7 @@ public:
 
     TS_ASSERT_EQUALS( inst.name(), "AnInst" );
     TS_ASSERT_EQUALS( inst.shortName(), "AnInst" );
-    TS_ASSERT_EQUALS( inst.zeroPadding(), 0 );
+    TS_ASSERT_EQUALS( inst.zeroPadding(123), fac->zeroPadding() );
     TS_ASSERT( inst.delimiter().empty() );
     TS_ASSERT( inst.liveListener().empty() );
     TS_ASSERT( inst.liveDataAddress().empty() );
@@ -66,7 +66,7 @@ public:
 
     InstrumentInfo inst = fac->instruments().front();
 
-    TS_ASSERT_EQUALS( inst.zeroPadding(), 99 );
+    TS_ASSERT_EQUALS( inst.zeroPadding(123), 99 );
     TS_ASSERT_EQUALS( inst.delimiter(), "!" );
     TS_ASSERT_EQUALS( inst.liveListener(), "I'm listening" );
 
@@ -79,7 +79,8 @@ public:
       "<facilities>"
       "  <facility name=\"MyFacility\" zeropadding=\"99\" delimiter=\"!\" FileExtensions=\".xyz\">"
       "    <livedata listener=\"I'm listening\" />"
-      "    <instrument name=\"AnInst\" zeropadding=\"66\" delimiter=\"?\" >"
+      "    <instrument name=\"AnInst\" delimiter=\"?\" >"
+      "      <zeropadding size=\"66\"/>"
       "      <livedata listener=\"pardon\" />"
       "      <technique>Measuring Stuff</technique>"
       "    </instrument>"
@@ -91,7 +92,7 @@ public:
 
     InstrumentInfo inst = fac->instruments().front();
 
-    TS_ASSERT_EQUALS( inst.zeroPadding(), 66 );
+    TS_ASSERT_EQUALS( inst.zeroPadding(123), 66 );
     TS_ASSERT_EQUALS( inst.delimiter(), "?" );
     TS_ASSERT_EQUALS( inst.liveListener(), "pardon" );
 
@@ -101,7 +102,8 @@ public:
   void test_setting_all_aspects_of_instrument()
   {
     const std::string instStr =
-      "<instrument name=\"MyInst\" shortname=\"mine\" zeropadding=\"8\" delimiter=\":\" >"
+      "<instrument name=\"MyInst\" shortname=\"mine\" delimiter=\":\" >"
+      "  <zeropadding size=\"8\"/>"
       "  <livedata listener=\"AListener\" address=\"myinst.facility.gov:99\" />"
       "  <technique>Measuring Stuff</technique>"
       "  <technique>Doing Stuff</technique>"
@@ -114,7 +116,7 @@ public:
 
     TS_ASSERT_EQUALS( inst.name(), "MyInst" );
     TS_ASSERT_EQUALS( inst.shortName(), "mine" );
-    TS_ASSERT_EQUALS( inst.zeroPadding(), 8 );
+    TS_ASSERT_EQUALS( inst.zeroPadding(123), 8 );
     TS_ASSERT_EQUALS( inst.delimiter(), ":" );
     TS_ASSERT_EQUALS( inst.liveListener(), "AListener" );
     TS_ASSERT_EQUALS( inst.liveDataAddress(), "myinst.facility.gov:99" );
@@ -132,6 +134,91 @@ public:
     delete fac;
   }
   
+  void test_multiple_zeropadding()
+  {
+    const std::string instStr =
+      "<instrument name=\"MyInst\" shortname=\"mine\" delimiter=\":\" >"
+      "  <technique>Measuring Stuff</technique>"
+      "  <zeropadding size=\"8\"/>"
+      "  <zeropadding size=\"15\" startRunNumber=\"123\" prefix=\"MyNewInstrument\"/>"
+      "  <zeropadding size=\"20\" startRunNumber=\"321\"/>"
+      "</instrument>";
+
+    FacilityInfo * fac = NULL;
+    TS_ASSERT_THROWS_NOTHING( fac = createInstInfoInMinimalFacility(instStr) );
+    
+    InstrumentInfo inst = fac->instruments().front();
+
+    TS_ASSERT_EQUALS( inst.zeroPadding(0), 8 );
+    TS_ASSERT_EQUALS( inst.zeroPadding(12), 8 );
+    TS_ASSERT_EQUALS( inst.zeroPadding(122), 8 );
+    TS_ASSERT_EQUALS( inst.zeroPadding(123), 15 );
+    TS_ASSERT_EQUALS( inst.zeroPadding(130), 15 );
+    TS_ASSERT_EQUALS( inst.zeroPadding(320), 15 );
+    TS_ASSERT_EQUALS( inst.zeroPadding(321), 20 );
+    TS_ASSERT_EQUALS( inst.zeroPadding(32100), 20 );
+
+    TS_ASSERT_EQUALS( inst.filePrefix(0), "mine" );
+    TS_ASSERT_EQUALS( inst.filePrefix(12), "mine" );
+    TS_ASSERT_EQUALS( inst.filePrefix(122), "mine" );
+    TS_ASSERT_EQUALS( inst.filePrefix(123), "MyNewInstrument" );
+    TS_ASSERT_EQUALS( inst.filePrefix(130), "MyNewInstrument" );
+    TS_ASSERT_EQUALS( inst.filePrefix(320), "MyNewInstrument" );
+    TS_ASSERT_EQUALS( inst.filePrefix(321), "mine" );
+    TS_ASSERT_EQUALS( inst.filePrefix(32100), "mine" );
+
+    delete fac;
+  }
+  
+  void test_error_in_multiple_zeropadding()
+  {
+    const std::string instStr =
+      "<instrument name=\"MyInst\" shortname=\"mine\" delimiter=\":\" >"
+      "  <technique>Measuring Stuff</technique>"
+      "  <zeropadding size=\"8\"/>"
+      "  <zeropadding size=\"15\"/>"
+      "</instrument>";
+
+    FacilityInfo * fac = NULL;
+    TS_ASSERT_THROWS( fac = createInstInfoInMinimalFacility(instStr), std::runtime_error );
+  }
+  
+  void test_error_1_in_multiple_zeropadding()
+  {
+    const std::string instStr =
+      "<instrument name=\"MyInst\" shortname=\"mine\" delimiter=\":\" >"
+      "  <technique>Measuring Stuff</technique>"
+      "  <zeropadding size=\"nan\"/>"
+      "</instrument>";
+
+    FacilityInfo * fac = NULL;
+    TS_ASSERT_THROWS( fac = createInstInfoInMinimalFacility(instStr), std::runtime_error );
+  }
+  
+  void test_error_2_in_multiple_zeropadding()
+  {
+    const std::string instStr =
+      "<instrument name=\"MyInst\" shortname=\"mine\" delimiter=\":\" >"
+      "  <technique>Measuring Stuff</technique>"
+      "  <zeropadding size=\"8\" startRunNumber=\"nan\"/>"
+      "</instrument>";
+
+    FacilityInfo * fac = NULL;
+    TS_ASSERT_THROWS( fac = createInstInfoInMinimalFacility(instStr), std::runtime_error );
+  }
+  
+  void test_error_3_in_multiple_zeropadding()
+  {
+    const std::string instStr =
+      "<instrument name=\"MyInst\" shortname=\"mine\" delimiter=\":\" >"
+      "  <technique>Measuring Stuff</technique>"
+      "  <zeropadding startRunNumber=\"333\"/>"
+      "</instrument>";
+
+    FacilityInfo * fac = NULL;
+    TS_ASSERT_THROWS( fac = createInstInfoInMinimalFacility(instStr), std::runtime_error );
+  }
+  
   void test_equality_operator()
   {
     const std::string instStr = "<instrument name=\"AnInst\">"
diff --git a/Code/Mantid/Framework/Kernel/test/MultiFileNameParserTest.h b/Code/Mantid/Framework/Kernel/test/MultiFileNameParserTest.h
index 273d72f6fcc..88b7ed873b3 100644
--- a/Code/Mantid/Framework/Kernel/test/MultiFileNameParserTest.h
+++ b/Code/Mantid/Framework/Kernel/test/MultiFileNameParserTest.h
@@ -324,6 +324,19 @@ public:
     TS_ASSERT_EQUALS(filenames[1][0], "c:/TSC00003.raw");
     TS_ASSERT_EQUALS(filenames[2][0], "c:/TSC00004.raw");
   }
+
+  void test_instrument_with_multiple_padding()
+  {
+    Parser parser;
+    parser.parse("TESTHISTOLISTENER123,299-301");
+
+    std::vector<std::vector<std::string> > filenames = parser.fileNames();
+
+    TS_ASSERT_EQUALS(filenames[0][0], "TESTHISTOLISTENER00000123" );
+    TS_ASSERT_EQUALS(filenames[1][0], "TESTHISTOLISTENER00000299" );
+    TS_ASSERT_EQUALS(filenames[1][1], "TST00000000300" );
+    TS_ASSERT_EQUALS(filenames[1][2], "TST00000000301" );
+  }
 };
 
 #endif /* MANTID_KERNEL_MULTIFILENAMEPARSERTEST_H_ */
\ No newline at end of file
diff --git a/Code/Mantid/instrument/Facilities.xml b/Code/Mantid/instrument/Facilities.xml
index e6c61d2c4f9..fd01bffc545 100644
--- a/Code/Mantid/instrument/Facilities.xml
+++ b/Code/Mantid/instrument/Facilities.xml
@@ -22,7 +22,8 @@
     <livedata address="NDXCRISP:6789" />
   </instrument>
 
-  <instrument name="ENGIN-X" shortname="ENGINX" zeropadding="8">
+  <instrument name="ENGIN-X" shortname="ENGINX" >
+    <zeropadding size="8"/>
     <technique>Neutron Diffraction</technique>
     <livedata address="NDXENGINX:6789" />
   </instrument>
@@ -79,6 +80,7 @@
   </instrument>
 
   <instrument name="OSIRIS" shortname="OSI" beamline="N6">
+    <zeropadding size="8" startRunNumber="99780" prefix="OSIRIS"/>
     <technique>Neutron Diffraction</technique>
     <technique>Neutron Spectroscopy</technique>
     <technique>TOF Indirect Geometry Spectroscopy</technique>
@@ -124,60 +126,70 @@
     <livedata address="NDXVESUVIO:6789" />
   </instrument>
   
-  <instrument name="LET" zeropadding="8">
+  <instrument name="LET">
+    <zeropadding size="8"/>
     <technique>Neutron Spectroscopy</technique>
     <technique>TOF Direct Geometry Spectroscopy</technique>
     <livedata address="NDXLET:6789" />
   </instrument>
 
-  <instrument name="NIMROD" zeropadding="8">
+  <instrument name="NIMROD">
+    <zeropadding size="8"/>
     <technique>Neutron Diffraction</technique>
     <technique>Neutron Diffraction with isotopic substitution</technique>
     <livedata address="NDXNIMROD:6789" />
   </instrument>
 
-  <instrument name="OFFSPEC" zeropadding="8">
+  <instrument name="OFFSPEC">
+    <zeropadding size="8"/>
     <technique>Reflectometry</technique>
     <livedata address="NDXOFFSPEC:6789" />
   </instrument>
 
-  <instrument name="POLREF" zeropadding="8">
+  <instrument name="POLREF">
+    <zeropadding size="8"/>
     <technique>Reflectometry</technique>
     <livedata address="NDXPOLREF:6789" />
   </instrument>
 
-  <instrument name="SANS2D" zeropadding="8">
+  <instrument name="SANS2D">
+    <zeropadding size="8"/>
     <technique>Small Angle Scattering</technique>
     <livedata address="NDXSANS2D:6789" />
   </instrument>
   
-  <instrument name="WISH" zeropadding="8">
+  <instrument name="WISH">
+    <zeropadding size="8"/>
     <technique>Neutron Diffraction</technique>
     <technique>Powder Diffraction</technique>
     <technique>Single Crystal Diffraction</technique>
     <livedata address="NDXWISH:6789" />
   </instrument>
   
-  <instrument name="HIFI" zeropadding="8">
+  <instrument name="HIFI">
+    <zeropadding size="8"/>
     <technique>Muon level crossing resonance</technique>
     <technique>Muon spectroscopy</technique>
     <technique>Radio frequency muSR</technique>
     <livedata address="NDXHIFI:6789" />
   </instrument>
   
-  <instrument name="MUSR" zeropadding="8">
+  <instrument name="MUSR">
+    <zeropadding size="8"/>
     <technique>Muon spectroscopy</technique>
     <technique>Radio frequency muSR</technique>
     <livedata address="NDXMUSR:6789" />
   </instrument>
   
-  <instrument name="EMU" zeropadding="8">
+  <instrument name="EMU">
+    <zeropadding size="8"/>
     <technique>Muon spectroscopy</technique>
     <technique>Radio frequency muSR</technique>
     <livedata address="NDXEMU:6789" />
   </instrument>  
  
-  <instrument name="ARGUS" zeropadding="7">
+  <instrument name="ARGUS">
+    <zeropadding size="7"/>
     <technique>Muon spectroscopy</technique>
     <technique>Radio frequency muSR</technique>
     <livedata address="NDXARGUS:6789" />
@@ -186,6 +198,8 @@
   <livedata listener="ISISHistoDataListener"/>
 
   <instrument name="TESTHISTOLISTENER"> 
+    <zeropadding size="8"/>
+    <zeropadding size="11" startRunNumber="300" prefix="TST"/>
     <technique>Test ISISHistoDataListener</technique>
     <livedata address="127.0.0.1:6789" />
   </instrument>
-- 
GitLab