diff --git a/Framework/DataHandling/inc/MantidDataHandling/LoadANSTOHelper.h b/Framework/DataHandling/inc/MantidDataHandling/LoadANSTOHelper.h
index 7776187428c496f80e7c7011322cb10a5be3ddfa..134809d2757324a1e06eb5ab96e667ced139839e 100644
--- a/Framework/DataHandling/inc/MantidDataHandling/LoadANSTOHelper.h
+++ b/Framework/DataHandling/inc/MantidDataHandling/LoadANSTOHelper.h
@@ -22,6 +22,7 @@
 namespace Mantid {
 namespace DataHandling {
 namespace ANSTO {
+
 /// pointer to the vector of events
 typedef std::vector<DataObjects::TofEvent> *EventVector_pt;
 
@@ -47,61 +48,75 @@ public:
   void complete();
 };
 
-class EventCounter {
-private:
+class EventProcessor {
+protected:
   // fields
-  std::vector<size_t> &m_eventCounts;
-  const std::vector<bool> &m_mask;
-  const std::vector<int> &m_offsets;
+  const std::vector<bool> &m_roi;
   const size_t m_stride;
-  const size_t m_pixelsCutOffL;
-  const size_t m_tubeBinning;
-  const size_t m_finalBinsY;
-  // tof boundaries
-  double m_tofMin;
-  double m_tofMax;
-  // correction
+  // tof correction
   const double m_period;
   const double m_phase;
+  // boundaries
+  const double m_tofMinBoundary;
+  const double m_tofMaxBoundary;
+
+  // methods
+  virtual void endOfFrameImpl() = 0;
+  virtual void addEventImpl(size_t id, double tof) = 0;
 
 public:
   // construction
-  EventCounter(std::vector<size_t> &eventCounts, const std::vector<bool> &mask,
-               const std::vector<int> &offsets, size_t stride,
-               size_t pixelsCutOffL, size_t tubeBinning, size_t finalBinsY,
-               double periode, double phase);
-
-  // properties
-  double tofMin() const;
-  double tofMax() const;
+  EventProcessor(const std::vector<bool> &roi, const size_t stride,
+                 const double period, const double phase,
+                 const double tofMinBoundary, const double tofMaxBoundary);
 
   // methods
+  void endOfFrame();
   void addEvent(size_t x, size_t y, double tof);
 };
 
-class EventAssigner {
-private:
+class EventCounter : public EventProcessor {
+protected:
   // fields
-  std::vector<EventVector_pt> &m_eventVectors;
-  const std::vector<bool> &m_mask;
-  const std::vector<int> &m_offsets;
-  const size_t m_stride;
-  const size_t m_pixelsCutOffL;
-  const size_t m_tubeBinning;
-  const size_t m_finalBinsY;
-  // correction
-  const double m_period;
-  const double m_phase;
+  std::vector<size_t> &m_eventCounts;
+  // number of frames
+  size_t m_numFrames;
+  // tof
+  double m_tofMin;
+  double m_tofMax;
+
+  // methods
+  virtual void endOfFrameImpl();
+  virtual void addEventImpl(size_t id, double tof);
 
 public:
   // construction
-  EventAssigner(std::vector<EventVector_pt> &eventVectors,
-                const std::vector<bool> &mask, const std::vector<int> &offsets,
-                size_t stride, size_t pixelsCutOffL, size_t tubeBinning,
-                size_t finalBinsY, double periode, double phase);
+  EventCounter(const std::vector<bool> &roi, const size_t stride,
+               const double period, const double phase,
+               const double tofMinBoundary, const double tofMaxBoundary,
+               std::vector<size_t> &eventCounts);
+
+  // properties
+  size_t numFrames() const;
+  double tofMin() const;
+  double tofMax() const;
+};
+
+class EventAssigner : public EventProcessor {
+protected:
+  // fields
+  std::vector<EventVector_pt> &m_eventVectors;
 
   // methods
-  void addEvent(size_t x, size_t y, double tof);
+  virtual void endOfFrameImpl();
+  virtual void addEventImpl(size_t id, double tof);
+
+public:
+  // construction
+  EventAssigner(const std::vector<bool> &roi, const size_t stride,
+                const double period, const double phase,
+                const double tofMinBoundary, const double tofMaxBoundary,
+                std::vector<EventVector_pt> &eventVectors);
 };
 
 class FastReadOnlyFile {
@@ -125,6 +140,7 @@ public:
 };
 
 namespace Tar {
+
 struct EntryHeader {
   // cppcheck-suppress unusedStructMember
   char FileName[100];
@@ -158,8 +174,6 @@ struct EntryHeader {
   char FilenamePrefix[155];
 };
 
-template <size_t N> int64_t octalToInt(char(&str)[N]);
-
 class File {
 
   static const auto BUFFER_SIZE = 4096;
@@ -206,8 +220,10 @@ public:
   size_t read(void *dst, size_t size);
   int read_byte();
 };
-}
-}
-}
-}
+
+} // Tar
+} // ANSTO
+} // DataHandling
+} // Mantid
+
 #endif // DATAHANDING_ANSTO_H_
\ No newline at end of file
diff --git a/Framework/DataHandling/inc/MantidDataHandling/LoadBBY.h b/Framework/DataHandling/inc/MantidDataHandling/LoadBBY.h
index 75c9c4f54e4a70d0c700cc4efd5ec45e89962667..37cfc22c64995142aff1445f08cc7d68b660b4fd 100644
--- a/Framework/DataHandling/inc/MantidDataHandling/LoadBBY.h
+++ b/Framework/DataHandling/inc/MantidDataHandling/LoadBBY.h
@@ -15,8 +15,7 @@ namespace Mantid {
 namespace DataHandling {
 /**
 Loads a Bilby data file. Implements API::IFileLoader and its file check methods
-to
-recognise a file as the one containing Bilby data.
+to recognise a file as the one containing Bilby data.
 
 @author David Mannicke (ANSTO), Anders Markvardsen (ISIS), Roman Tolchenov
 (Tessella plc)
@@ -34,7 +33,7 @@ the Free Software Foundation; either version 3 of the License, or
 
 Mantid is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
@@ -45,6 +44,32 @@ Code Documentation is available at: <http://doxygen.mantidproject.org>
 */
 
 class DLLExport LoadBBY : public API::IFileLoader<Kernel::FileDescriptor> {
+
+  struct InstrumentInfo {
+    //
+    int32_t bm_counts;
+    int32_t att_pos;
+    //
+    double period_master;
+    double period_slave;
+    double phase_slave;
+    //
+    double L1_chopper_value;
+    double L2_det_value;
+    //
+    double L2_curtainl_value;
+    double L2_curtainr_value;
+    double L2_curtainu_value;
+    double L2_curtaind_value;
+    //
+    double D_det_value;
+    //
+    double D_curtainl_value;
+    double D_curtainr_value;
+    double D_curtainu_value;
+    double D_curtaind_value;
+  };
+
 public:
   // construction
   LoadBBY() {}
@@ -68,26 +93,26 @@ protected:
   virtual void exec();
 
 private:
+  // region of intreset
+  static std::vector<bool> createRoiVector(const std::string &maskfile);
+
   // instrument creation
-  Geometry::Instrument_sptr
-  createInstrument(ANSTO::Tar::File &tarFile, size_t pixelsCutOffL,
-                   size_t pixelsCutOffH, size_t tubeBinning, size_t finalBinsY);
+  Geometry::Instrument_sptr createInstrument(ANSTO::Tar::File &tarFile,
+                                             InstrumentInfo &instrumentInfo);
 
   // load nx dataset
   template <class T>
-  static bool loadNXDataSet(T &value, NeXus::NXEntry &entry,
-                            const std::string &path);
+  static bool loadNXDataSet(NeXus::NXEntry &entry, const std::string &path,
+                            T &value);
 
   // binary file access
-  template <class Counter>
+  template <class EventProcessor>
   static void loadEvents(API::Progress &prog, const char *progMsg,
-                         ANSTO::Tar::File &file, const double tofMinBoundary,
-                         const double tofMaxBoundary, Counter &counter);
-  static std::vector<bool> createMaskVector(const std::string &filename,
-                                            bool &fileLoaded);
-  static std::vector<int> createOffsetVector(const std::string &filename,
-                                             bool &fileLoaded);
+                         ANSTO::Tar::File &tarFile,
+                         EventProcessor &eventProcessor);
 };
-}
-}
+
+} // DataHandling
+} // Mantid
+
 #endif // DATAHANDING_LOADBBY_H_
\ No newline at end of file
diff --git a/Framework/DataHandling/src/LoadANSTOHelper.cpp b/Framework/DataHandling/src/LoadANSTOHelper.cpp
index 55394d84ab274c7aac5c9d744bd0d1a87e73d274..2e539fb756adc0e48415746d9fcd9bbb5229d2e1 100644
--- a/Framework/DataHandling/src/LoadANSTOHelper.cpp
+++ b/Framework/DataHandling/src/LoadANSTOHelper.cpp
@@ -9,11 +9,10 @@
 #include "MantidGeometry/Objects/ShapeFactory.h"
 #include "MantidNexus/NexusClasses.h"
 
-//#include <Poco/File.h>
-
 namespace Mantid {
 namespace DataHandling {
 namespace ANSTO {
+
 // ProgressTracker
 ProgressTracker::ProgressTracker(API::Progress &progBar, const char *msg,
                                  int64_t target, size_t count)
@@ -49,26 +48,16 @@ void ProgressTracker::complete() {
   }
 }
 
-// EventCounter
-EventCounter::EventCounter(std::vector<size_t> &eventCounts,
-                           const std::vector<bool> &mask,
-                           const std::vector<int> &offsets, size_t stride,
-                           size_t pixelsCutOffL, size_t tubeBinning,
-                           size_t finalBinsY, double periode, double phase)
-    : m_eventCounts(eventCounts), m_mask(mask), m_offsets(offsets),
-      m_stride(stride), m_pixelsCutOffL(pixelsCutOffL),
-      m_tubeBinning(tubeBinning), m_finalBinsY(finalBinsY),
-      m_tofMin(std::numeric_limits<double>::max()),
-      m_tofMax(std::numeric_limits<double>::min()), m_period(periode),
-      m_phase(phase) {}
-double EventCounter::tofMin() const {
-  return m_tofMin <= m_tofMax ? m_tofMin : 0.0;
-}
-double EventCounter::tofMax() const {
-  return m_tofMin <= m_tofMax ? m_tofMax : 0.0;
-}
-void EventCounter::addEvent(size_t x, size_t y, double tof) {
-  // correction
+// EventProcessor
+EventProcessor::EventProcessor(const std::vector<bool> &roi,
+                               const size_t stride, const double period,
+                               const double phase, const double tofMinBoundary,
+                               const double tofMaxBoundary)
+    : m_roi(roi), m_stride(stride), m_period(period), m_phase(phase),
+      m_tofMinBoundary(tofMinBoundary), m_tofMaxBoundary(tofMaxBoundary) {}
+void EventProcessor::endOfFrame() { endOfFrameImpl(); }
+void EventProcessor::addEvent(size_t x, size_t y, double tof) {
+  // tof correction
   if (m_period > 0.0) {
     tof += m_phase;
     while (tof > m_period)
@@ -77,51 +66,61 @@ void EventCounter::addEvent(size_t x, size_t y, double tof) {
       tof += m_period;
   }
 
-  y = y + (size_t)m_offsets[x];
-  if (y < m_stride) { // sufficient because yNew is size_t
-    if (m_mask[m_stride * x + y]) {
-      if (m_tofMin > tof)
-        m_tofMin = tof;
-      if (m_tofMax < tof)
-        m_tofMax = tof;
+  // check if event is in valid range
+  if ((y < m_stride) && (m_tofMinBoundary <= tof) &&
+      (tof <= m_tofMaxBoundary)) {
 
-      // transformation to bin index
-      size_t j = (y - m_pixelsCutOffL) / m_tubeBinning;
+    // detector id
+    size_t id = m_stride * x + y;
 
-      m_eventCounts[m_finalBinsY * x + j]++;
-    }
+    // check if neutron is in region of intreset
+    if (m_roi[id])
+      addEventImpl(id, tof);
   }
 }
 
-// EventAssigner
-EventAssigner::EventAssigner(std::vector<EventVector_pt> &eventVectors,
-                             const std::vector<bool> &mask,
-                             const std::vector<int> &offsets, size_t stride,
-                             size_t pixelsCutOffL, size_t tubeBinning,
-                             size_t finalBinsY, double periode, double phase)
-    : m_eventVectors(eventVectors), m_mask(mask), m_offsets(offsets),
-      m_stride(stride), m_pixelsCutOffL(pixelsCutOffL),
-      m_tubeBinning(tubeBinning), m_finalBinsY(finalBinsY), m_period(periode),
-      m_phase(phase) {}
-void EventAssigner::addEvent(size_t x, size_t y, double tof) {
-  // correction
-  if (m_period > 0.0) {
-    tof += m_phase;
-    while (tof > m_period)
-      tof -= m_period;
-    while (tof < 0)
-      tof += m_period;
-  }
-
-  y = y + (size_t)m_offsets[x];
-  if (y < m_stride) { // sufficient because yNew is size_t
-    if (m_mask[m_stride * x + y]) {
-      // transformation to bin index
-      size_t j = (y - m_pixelsCutOffL) / m_tubeBinning;
+// EventCounter
+EventCounter::EventCounter(const std::vector<bool> &roi, const size_t stride,
+                           const double period, const double phase,
+                           const double tofMinBoundary,
+                           const double tofMaxBoundary,
+                           std::vector<size_t> &eventCounts)
+    : EventProcessor(roi, stride, period, phase, tofMinBoundary,
+                     tofMaxBoundary),
+      m_eventCounts(eventCounts), m_numFrames(0),
+      m_tofMin(std::numeric_limits<double>::max()),
+      m_tofMax(std::numeric_limits<double>::min()) {}
+size_t EventCounter::numFrames() const { return m_numFrames; }
+double EventCounter::tofMin() const {
+  return m_tofMin <= m_tofMax ? m_tofMin : 0.0;
+}
+double EventCounter::tofMax() const {
+  return m_tofMin <= m_tofMax ? m_tofMax : 0.0;
+}
+void EventCounter::endOfFrameImpl() { m_numFrames++; }
+void EventCounter::addEventImpl(size_t id, double tof) {
+  if (m_tofMin > tof)
+    m_tofMin = tof;
+  if (m_tofMax < tof)
+    m_tofMax = tof;
+
+  m_eventCounts[id]++;
+}
 
-      m_eventVectors[m_finalBinsY * x + j]->push_back(tof);
-    }
-  }
+// EventAssigner
+EventAssigner::EventAssigner(const std::vector<bool> &roi, const size_t stride,
+                             const double period, const double phase,
+                             const double tofMinBoundary,
+                             const double tofMaxBoundary,
+                             std::vector<EventVector_pt> &eventVectors)
+    : EventProcessor(roi, stride, period, phase, tofMinBoundary,
+                     tofMaxBoundary),
+      m_eventVectors(eventVectors) {}
+void EventAssigner::endOfFrameImpl() {
+  // ignore
+}
+void EventAssigner::addEventImpl(size_t id, double tof) {
+  m_eventVectors[id]->push_back(tof);
 }
 
 // FastReadOnlyFile
@@ -332,7 +331,8 @@ int File::read_byte() {
   m_position++;
   return m_buffer[m_bufferPosition++];
 }
-}
-}
-} // namespace
-} // namespace
\ No newline at end of file
+
+} // Tar
+} // ANSTO
+} // DataHandling
+} // Mantid
\ No newline at end of file
diff --git a/Framework/DataHandling/src/LoadBBY.cpp b/Framework/DataHandling/src/LoadBBY.cpp
index 8697cb516daf673774849deae53ec9430ff138a2..5c670badbacd110171d22b117186b3d4f9f54c32 100644
--- a/Framework/DataHandling/src/LoadBBY.cpp
+++ b/Framework/DataHandling/src/LoadBBY.cpp
@@ -1,5 +1,6 @@
 #include "MantidDataHandling/LoadBBY.h"
 #include "MantidDataObjects/EventWorkspace.h"
+#include "MantidKernel/PropertyWithValue.h"
 #include "MantidAPI/FileProperty.h"
 #include "MantidAPI/RegisterFileLoader.h"
 #include "MantidAPI/WorkspaceValidators.h"
@@ -10,9 +11,12 @@
 #include "MantidNexus/NexusClasses.h"
 
 #include <Poco/TemporaryFile.h>
+#include <math.h>
+#include <stdio.h>
 
 namespace Mantid {
 namespace DataHandling {
+
 // register the algorithm into the AlgorithmFactory
 DECLARE_FILELOADER_ALGORITHM(LoadBBY)
 
@@ -20,11 +24,37 @@ DECLARE_FILELOADER_ALGORITHM(LoadBBY)
 static const size_t HISTO_BINS_X = 240;
 static const size_t HISTO_BINS_Y = 256;
 // 100 = 40 + 20 + 40
-static const size_t Progress_LoadBinFile = 40;
-static const size_t Progress_ReserveMemory = 20;
+static const size_t Progress_LoadBinFile = 48;
+static const size_t Progress_ReserveMemory = 4;
+static const size_t Progress_Total =
+    2 * Progress_LoadBinFile + Progress_ReserveMemory;
+
+static char const *const FilenameStr = "Filename";
+static char const *const MaskStr = "Mask";
+
+static char const *const PeriodMasterStr = "PeriodMaster";
+static char const *const PeriodSlaveStr = "PeriodSlave";
+static char const *const PhaseSlaveStr = "PhaseSlave";
+
+static char const *const FilterByTofMinStr = "FilterByTofMin";
+static char const *const FilterByTofMaxStr = "FilterByTofMax";
 
 using ANSTO::EventVector_pt;
 
+template <typename TYPE>
+void AddSinglePointTimeSeriesProperty(API::LogManager &logManager,
+                                      const std::string &time,
+                                      const std::string &name,
+                                      const TYPE value) {
+  // create time series property and add single value
+  Kernel::TimeSeriesProperty<TYPE> *p =
+      new Kernel::TimeSeriesProperty<TYPE>(name);
+  p->addValue(time, value);
+
+  // add to log manager
+  logManager.addProperty(p);
+}
+
 class BbyDetectorBankFactory {
 private:
   // fields
@@ -83,7 +113,7 @@ int LoadBBY::confidence(Kernel::FileDescriptor &descriptor) const {
  * read from after the execution (output).
  */
 void LoadBBY::init() {
-  // Specify file extensions which can be associated with a BBY file.
+  // Specify file extensions which can be associated with a specific file.
   std::vector<std::string> exts;
 
   // Declare the Filename algorithm property. Mandatory. Sets the path to the
@@ -91,181 +121,110 @@ void LoadBBY::init() {
   exts.clear();
   exts.push_back(".tar");
   declareProperty(
-      new API::FileProperty("Filename", "", API::FileProperty::Load, exts),
+      new API::FileProperty(FilenameStr, "", API::FileProperty::Load, exts),
       "The input filename of the stored data");
 
   // mask
   exts.clear();
   exts.push_back(".xml");
   declareProperty(
-      new API::FileProperty("Mask", "", API::FileProperty::OptionalLoad, exts),
+      new API::FileProperty(MaskStr, "", API::FileProperty::OptionalLoad, exts),
       "The input filename of the mask data");
 
-  // offsets
-  exts.clear();
-  exts.push_back(".csv");
-  declareProperty(new API::FileProperty("TubeOffsets", "",
-                                        API::FileProperty::OptionalLoad, exts),
-                  "The input filename of the tube offset data");
-
+  // OutputWorkspace
   declareProperty(new API::WorkspaceProperty<API::IEventWorkspace>(
       "OutputWorkspace", "", Kernel::Direction::Output));
 
-  declareProperty(new Kernel::PropertyWithValue<size_t>(
-                      "TubeBinning", 1, Kernel::Direction::Input),
-                  "Default: 1");
-
+  // FilterByTofMin
   declareProperty(new Kernel::PropertyWithValue<double>(
-                      "FilterByTofMin", 0, Kernel::Direction::Input),
+                      FilterByTofMinStr, 0, Kernel::Direction::Input),
                   "Optional: To exclude events that do not fall within a range "
                   "of times-of-flight. "
                   "This is the minimum accepted value in microseconds. Keep "
                   "blank to load all events.");
+
+  // FilterByTofMax
   declareProperty(new Kernel::PropertyWithValue<double>(
-                      "FilterByTofMax", 50000000, Kernel::Direction::Input),
+                      FilterByTofMaxStr, EMPTY_DBL(), Kernel::Direction::Input),
                   "Optional: To exclude events that do not fall within a range "
                   "of times-of-flight. "
                   "This is the maximum accepted value in microseconds. Keep "
                   "blank to load all events.");
+
+  // FilterByTimeStart
   declareProperty(
       new Kernel::PropertyWithValue<double>("FilterByTimeStart", EMPTY_DBL(),
                                             Kernel::Direction::Input),
       "Optional: To only include events after the provided start time, in "
       "seconds (relative to the start of the run).");
+
+  // FilterByTimeStop
   declareProperty(
       new Kernel::PropertyWithValue<double>("FilterByTimeStop", EMPTY_DBL(),
                                             Kernel::Direction::Input),
       "Optional: To only include events before the provided stop time, in "
       "seconds (relative to the start of the run).");
 
+  // period and phase
   declareProperty(new Kernel::PropertyWithValue<double>(
-                      "PeriodMaster", 0.0, Kernel::Direction::Input),
-                  "Optional:");
+                      PeriodMasterStr, EMPTY_DBL(), Kernel::Direction::Input),
+                  "Optional");
   declareProperty(new Kernel::PropertyWithValue<double>(
-                      "PeriodSlave", 0.0, Kernel::Direction::Input),
-                  "Optional:");
+                      PeriodSlaveStr, EMPTY_DBL(), Kernel::Direction::Input),
+                  "Optional");
   declareProperty(new Kernel::PropertyWithValue<double>(
-                      "PhaseSlave", 0.0, Kernel::Direction::Input),
-                  "Optional:");
+                      PhaseSlaveStr, EMPTY_DBL(), Kernel::Direction::Input),
+                  "Optional");
 
-  std::string grpOptional = "Optional";
-  setPropertyGroup("TubeBinning", grpOptional);
-  setPropertyGroup("FilterByTofMin", grpOptional);
-  setPropertyGroup("FilterByTofMax", grpOptional);
+  std::string grpOptional = "Filters";
+  setPropertyGroup(FilterByTofMinStr, grpOptional);
+  setPropertyGroup(FilterByTofMaxStr, grpOptional);
   setPropertyGroup("FilterByTimeStart", grpOptional);
   setPropertyGroup("FilterByTimeStop", grpOptional);
 
   std::string grpPhaseCorrection = "Phase Correction";
-  setPropertyGroup("PeriodMaster", grpPhaseCorrection);
-  setPropertyGroup("PeriodSlave", grpPhaseCorrection);
-  setPropertyGroup("PhaseSlave", grpPhaseCorrection);
+  setPropertyGroup(PeriodMasterStr, grpPhaseCorrection);
+  setPropertyGroup(PeriodSlaveStr, grpPhaseCorrection);
+  setPropertyGroup(PhaseSlaveStr, grpPhaseCorrection);
 }
 /**
  * Execute the algorithm.
  */
 void LoadBBY::exec() {
-
   // Delete the output workspace name if it existed
   std::string outName = getPropertyValue("OutputWorkspace");
   if (API::AnalysisDataService::Instance().doesExist(outName))
     API::AnalysisDataService::Instance().remove(outName);
 
   // Get the name of the data file.
-  std::string filename = getPropertyValue("Filename");
-  ANSTO::Tar::File file(filename);
-  if (!file.good())
-    return;
+  std::string filename = getPropertyValue(FilenameStr);
+  ANSTO::Tar::File tarFile(filename);
+  if (!tarFile.good())
+    throw std::invalid_argument("invalid BBY file");
 
-  // load mask file
-  bool maskFileLoaded = false;
-  std::vector<bool> mask =
-      createMaskVector(getPropertyValue("Mask"), maskFileLoaded);
-
-  // load tube offsets
-  bool offsetFileLoaded = false;
-  std::vector<int> offsets =
-      createOffsetVector(getPropertyValue("TubeOffsets"), offsetFileLoaded);
-  for (size_t x = 0; x != HISTO_BINS_X; x++) {
-    int offset = offsets[x];
-    if (offset != 0) {
-      maskFileLoaded = true;
-
-      size_t s0 = HISTO_BINS_Y * x;
-      if (offset > 0) {
-        for (int y = 0; y != offset; y++)
-          mask[s0 + (size_t)y] = false;
-      } else { // if (offset < 0)
-        for (size_t y = HISTO_BINS_Y + static_cast<size_t>(offset);
-             y != HISTO_BINS_Y; y++)
-          mask[s0 + y] = false;
-      }
-    }
-  }
+  // region of intreset
+  std::vector<bool> roi = createRoiVector(getPropertyValue(MaskStr));
 
-  size_t nBins = 1;
-
-  size_t tubeBinning = getProperty("TubeBinning");
-  if (tubeBinning < 1)
-    tubeBinning = 1;
-  else if (tubeBinning > HISTO_BINS_Y)
-    tubeBinning = HISTO_BINS_Y;
-
-  size_t finalBinsY = HISTO_BINS_Y / tubeBinning;
-  size_t pixelsCutOff = HISTO_BINS_Y % tubeBinning;
-  size_t pixelsCutOffH = pixelsCutOff / 2;
-  size_t pixelsCutOffL = pixelsCutOff - pixelsCutOffH;
-
-  // update masking
-  if (tubeBinning > 1)
-    for (size_t x = 0; x != HISTO_BINS_X; x++) {
-      size_t s0 = HISTO_BINS_Y * x;
-
-      // mask out cut off pixels (low)
-      for (size_t y = 0; y < pixelsCutOffL; y++)
-        mask[s0 + y] = false;
-
-      // mask out cut off pixels (high)
-      for (size_t y = HISTO_BINS_Y - pixelsCutOffH; y < HISTO_BINS_Y; y++)
-        mask[s0 + y] = false;
-
-      // if one pixel is masked then all pixels in that binning group have to be
-      // masked
-      for (size_t j = 0; j < finalBinsY; j++) {
-        size_t y0 = j * tubeBinning + pixelsCutOffL;
-        for (size_t dy = 0; dy < tubeBinning; dy++)
-          // if one pixel is masked ...
-          if (!mask[s0 + y0 + dy]) {
-            for (dy = 0; dy < tubeBinning; dy++)
-              mask[s0 + y0 + dy] = false; // ... mask all pixels
-            break;
-          }
-      }
-    }
+  double tofMinBoundary = getProperty(FilterByTofMinStr);
+  double tofMaxBoundary = getProperty(FilterByTofMaxStr);
 
-  double tofMinBoundary = getProperty("FilterByTofMin");
-  double tofMaxBoundary = getProperty("FilterByTofMax");
-
-  // "loading neutron counts", "creating neutron event lists" and "loading
-  // neutron events"
-  API::Progress prog(this, 0.0, 1.0, Progress_LoadBinFile +
-                                         Progress_ReserveMemory +
-                                         Progress_LoadBinFile);
+  API::Progress prog(this, 0.0, 1.0, Progress_Total);
   prog.doReport("creating instrument");
 
   // create workspace
   DataObjects::EventWorkspace_sptr eventWS =
       boost::make_shared<DataObjects::EventWorkspace>();
 
-  eventWS->initialize(finalBinsY * HISTO_BINS_X,
-                      nBins + 1, // number of TOF bin boundaries
-                      nBins);
+  eventWS->initialize(HISTO_BINS_Y * HISTO_BINS_X,
+                      2, // number of TOF bin boundaries
+                      1);
 
   // set the units
   eventWS->getAxis(0)->unit() = Kernel::UnitFactory::Instance().create("TOF");
   eventWS->setYUnit("Counts");
 
   // set title
-  const std::vector<std::string> &subFiles = file.files();
+  const std::vector<std::string> &subFiles = tarFile.files();
   for (auto itr = subFiles.begin(); itr != subFiles.end(); ++itr)
     if (itr->compare(0, 3, "BBY") == 0) {
       std::string title = *itr;
@@ -280,66 +239,73 @@ void LoadBBY::exec() {
       break;
     }
 
-  // set auxiliaries
-  eventWS->mutableRun().addProperty("Filename", filename);
-  // eventWS->mutableRun().addProperty("run_number", 1);
-  // eventWS->mutableRun().addProperty("run_start", "1991-01-01T00:00:00", true
-  // );
-  // eventWS->mutableRun().addProperty("duration", duration[0], units);
-
   // create instrument
-  Geometry::Instrument_sptr instrument = createInstrument(
-      file, pixelsCutOffL, pixelsCutOffH, tubeBinning, finalBinsY);
-  eventWS->setInstrument(instrument);
+  InstrumentInfo instrumentInfo;
 
-  // load events
+  // Geometry::Instrument_sptr instrument =
+  createInstrument(tarFile, /* ref */ instrumentInfo);
+  // eventWS->setInstrument(instrument);
 
+  // load events
   size_t numberHistograms = eventWS->getNumberHistograms();
 
   std::vector<EventVector_pt> eventVectors(numberHistograms, NULL);
   std::vector<size_t> eventCounts(numberHistograms, 0);
-  std::vector<detid_t> detIDs = instrument->getDetectorIDs();
 
   // phase correction
-  double periodMaster = getProperty("PeriodMaster");
-  double periodSlave = getProperty("PeriodSlave");
-  double phaseSlave = getProperty("PhaseSlave");
-
-  if ((periodMaster < 0.0) || (periodSlave < 0.0))
-    throw std::runtime_error(
-        "Please specify a positive value for PeriodMaster and PeriodSlave.");
+  Kernel::Property *periodMasterProperty =
+      getPointerToProperty(PeriodMasterStr);
+  Kernel::Property *periodSlaveProperty = getPointerToProperty(PeriodSlaveStr);
+  Kernel::Property *phaseSlaveProperty = getPointerToProperty(PhaseSlaveStr);
+
+  double periodMaster;
+  double periodSlave;
+  double phaseSlave;
+
+  if (periodMasterProperty->isDefault() || periodSlaveProperty->isDefault() ||
+      phaseSlaveProperty->isDefault()) {
+
+    if (!periodMasterProperty->isDefault() ||
+        !periodSlaveProperty->isDefault() || !phaseSlaveProperty->isDefault()) {
+      throw std::invalid_argument("Please specify PeriodMaster, PeriodSlave "
+                                  "and PhaseSlave or none of them.");
+    }
 
-  bool setPeriodMaster = periodMaster > 0.0;
-  bool setPeriodSlave = periodSlave > 0.0;
-  bool setPhaseSlave = phaseSlave != 0.0;
+    // if values have not been specified in loader then use values from hdf file
+    periodMaster = instrumentInfo.period_master;
+    periodSlave = instrumentInfo.period_slave;
+    phaseSlave = instrumentInfo.phase_slave;
+  } else {
+    periodMaster = getProperty(PeriodMasterStr);
+    periodSlave = getProperty(PeriodSlaveStr);
+    phaseSlave = getProperty(PhaseSlaveStr);
 
-  if ((setPeriodMaster != setPeriodSlave) || setPhaseSlave)
-    throw std::runtime_error("Please specify PeriodMaster, PeriodSlave and "
-                             "PhaseSlave or none of them.");
+    if ((periodMaster < 0.0) || (periodSlave < 0.0))
+      throw std::invalid_argument(
+          "Please specify a positive value for PeriodMaster and PeriodSlave.");
+  }
 
-  double periode = periodSlave > 0.0 ? periodSlave : periodMaster;
+  double period = periodSlave;
   double shift = -1.0 / 6.0 * periodMaster - periodSlave * phaseSlave / 360.0;
 
   // count total events per pixel to reserve necessary memory
-  ANSTO::EventCounter eventCounter(eventCounts, mask, offsets, HISTO_BINS_Y,
-                                   pixelsCutOffL, tubeBinning, finalBinsY,
-                                   periode, shift);
-  loadEvents(prog, "loading neutron counts", file, tofMinBoundary,
-             tofMaxBoundary, eventCounter);
+  ANSTO::EventCounter eventCounter(roi, HISTO_BINS_Y, period, shift,
+                                   tofMinBoundary, tofMaxBoundary, eventCounts);
+
+  loadEvents(prog, "loading neutron counts", tarFile, eventCounter);
 
   // prepare event storage
   ANSTO::ProgressTracker progTracker(prog, "creating neutron event lists",
                                      numberHistograms, Progress_ReserveMemory);
+
   for (size_t i = 0; i != numberHistograms; ++i) {
     DataObjects::EventList &eventList = eventWS->getEventList(i);
 
-    eventList.setSortOrder(
-        DataObjects::PULSETIME_SORT); // why not PULSETIME[TOF]_SORT ?
+    eventList.setSortOrder(DataObjects::PULSETIME_SORT);
     eventList.reserve(eventCounts[i]);
 
-    detid_t id = detIDs[i];
-    eventList.setDetectorID(id);
-    eventList.setSpectrumNo(id);
+    eventList.setDetectorID(Mantid::detid_t(i));
+    eventList.setSpectrumNo(Mantid::detid_t(i));
 
     DataObjects::getEventsFrom(eventList, eventVectors[i]);
 
@@ -347,52 +313,35 @@ void LoadBBY::exec() {
   }
   progTracker.complete();
 
-  ANSTO::EventAssigner eventAssigner(eventVectors, mask, offsets, HISTO_BINS_Y,
-                                     pixelsCutOffL, tubeBinning, finalBinsY,
-                                     periode, shift);
-  loadEvents(prog, "loading neutron events", file, tofMinBoundary,
-             tofMaxBoundary, eventAssigner);
+  ANSTO::EventAssigner eventAssigner(roi, HISTO_BINS_Y, period, shift,
+                                     tofMinBoundary, tofMaxBoundary,
+                                     eventVectors);
+
+  loadEvents(prog, "loading neutron events", tarFile, eventAssigner);
 
   Kernel::cow_ptr<MantidVec> axis;
   MantidVec &xRef = axis.access();
   xRef.resize(2, 0.0);
-  xRef[0] = std::max(0.0, eventCounter.tofMin() -
-                              1); // just to make sure the bins hold it all
+  xRef[0] = std::max(
+      0.0,
+      floor(eventCounter.tofMin())); // just to make sure the bins hold it all
   xRef[1] = eventCounter.tofMax() + 1;
   eventWS->setAllX(axis);
 
-  if (maskFileLoaded) {
-    // count total number of masked bins
-    size_t maskedBins = 0;
-
-    for (size_t x = 0; x != HISTO_BINS_X; x++) {
-      size_t s0 = HISTO_BINS_Y * x;
-      for (size_t j = 0; j < finalBinsY; j++) {
-        size_t y0 = j * tubeBinning + pixelsCutOffL;
-        for (size_t dy = 0; dy < tubeBinning; dy++)
-          if (!mask[s0 + y0 + dy]) {
-            maskedBins++;
-            break;
-          }
-      }
-    }
+  // count total number of masked bins
+  size_t maskedBins = 0;
+  for (size_t i = 0; i != roi.size(); i++)
+    if (!roi[i])
+      maskedBins++;
 
+  if (maskedBins > 0) {
     // create list of masked bins
     std::vector<size_t> maskIndexList(maskedBins);
-    size_t binIndex = 0;
     size_t maskIndex = 0;
 
-    for (size_t x = 0; x != HISTO_BINS_X; x++) {
-      size_t s0 = HISTO_BINS_Y * x;
-      for (size_t j = 0; j < finalBinsY; j++, binIndex++) {
-        size_t y0 = j * tubeBinning + pixelsCutOffL;
-        for (size_t dy = 0; dy < tubeBinning; dy++)
-          if (!mask[s0 + y0 + dy]) {
-            maskIndexList[maskIndex++] = binIndex;
-            break;
-          }
-      }
-    }
+    for (size_t i = 0; i != roi.size(); i++)
+      if (!roi[i])
+        maskIndexList[maskIndex++] = i;
 
     API::IAlgorithm_sptr maskingAlg = createChildAlgorithm("MaskDetectors");
     maskingAlg->setProperty("Workspace", eventWS);
@@ -400,53 +349,143 @@ void LoadBBY::exec() {
     maskingAlg->executeAsChildAlg();
   }
 
+  // set log values
+  API::LogManager &logManager = eventWS->mutableRun();
+
+  logManager.addProperty("filename", filename);
+  logManager.addProperty("att_pos", static_cast<int>(instrumentInfo.att_pos));
+  logManager.addProperty("frame_count",
+                         static_cast<int>(eventCounter.numFrames()));
+  logManager.addProperty("period", period);
+
+  // currently beam monitor counts are not available, instead number of frames
+  // times period is used
+  logManager.addProperty(
+      "bm_counts", static_cast<double>(eventCounter.numFrames()) * period /
+                       1.0e6); // static_cast<double>(instrumentInfo.bm_counts)
+
+  // currently
+  Kernel::time_duration duration =
+      boost::posix_time::microseconds(static_cast<boost::int64_t>(
+          static_cast<double>(eventCounter.numFrames()) * period));
+
+  Kernel::DateAndTime start_time("2000-01-01T00:00:00");
+  Kernel::DateAndTime end_time(start_time + duration);
+
+  logManager.addProperty("start_time", start_time.toISO8601String());
+  logManager.addProperty("end_time", end_time.toISO8601String());
+
+  std::string time_str = start_time.toISO8601String();
+  AddSinglePointTimeSeriesProperty(logManager, time_str, "L1_chopper_value",
+                                   instrumentInfo.L1_chopper_value);
+  AddSinglePointTimeSeriesProperty(logManager, time_str, "L2_det_value",
+                                   instrumentInfo.L2_det_value);
+  AddSinglePointTimeSeriesProperty(logManager, time_str, "L2_curtainl_value",
+                                   instrumentInfo.L2_curtainl_value);
+  AddSinglePointTimeSeriesProperty(logManager, time_str, "L2_curtainr_value",
+                                   instrumentInfo.L2_curtainr_value);
+  AddSinglePointTimeSeriesProperty(logManager, time_str, "L2_curtainu_value",
+                                   instrumentInfo.L2_curtainu_value);
+  AddSinglePointTimeSeriesProperty(logManager, time_str, "L2_curtaind_value",
+                                   instrumentInfo.L2_curtaind_value);
+  AddSinglePointTimeSeriesProperty(logManager, time_str, "D_det_value",
+                                   instrumentInfo.D_det_value);
+  AddSinglePointTimeSeriesProperty(logManager, time_str, "D_curtainl_value",
+                                   instrumentInfo.D_curtainl_value);
+  AddSinglePointTimeSeriesProperty(logManager, time_str, "D_curtainr_value",
+                                   instrumentInfo.D_curtainr_value);
+  AddSinglePointTimeSeriesProperty(logManager, time_str, "D_curtainu_value",
+                                   instrumentInfo.D_curtainu_value);
+  AddSinglePointTimeSeriesProperty(logManager, time_str, "D_curtaind_value",
+                                   instrumentInfo.D_curtaind_value);
+  AddSinglePointTimeSeriesProperty(logManager, time_str, "curtain_rotation",
+                                   10.0);
+
+  API::IAlgorithm_sptr loadInstrumentAlg =
+      createChildAlgorithm("LoadInstrument");
+  loadInstrumentAlg->setProperty("Workspace", eventWS);
+  loadInstrumentAlg->setPropertyValue("InstrumentName", "BILBY");
+  loadInstrumentAlg->executeAsChildAlg();
+
   setProperty("OutputWorkspace", eventWS);
 }
 
-// instrument creation
-Geometry::Instrument_sptr LoadBBY::createInstrument(ANSTO::Tar::File &tarFile,
-                                                    size_t pixelsCutOffL,
-                                                    size_t pixelsCutOffH,
-                                                    size_t tubeBinning,
-                                                    size_t finalBinsY) {
-  // instrument
-  Geometry::Instrument_sptr instrument =
-      boost::make_shared<Geometry::Instrument>("BILBY");
-  instrument->setDefaultViewAxis("Z-");
+// region of intreset
+std::vector<bool> LoadBBY::createRoiVector(const std::string &maskfile) {
+  std::vector<bool> result(HISTO_BINS_Y * HISTO_BINS_X, true);
+
+  if (maskfile.length() == 0)
+    return result;
+
+  std::ifstream input(maskfile.c_str());
+  if (!input.good())
+    throw std::invalid_argument("invalid mask file");
+
+  std::string line;
+  while (std::getline(input, line)) {
+    auto i0 = line.find("<detids>");
+    auto iN = line.find("</detids>");
+
+    if ((i0 != std::string::npos) && (iN != std::string::npos) && (i0 < iN)) {
+      line = line.substr(i0 + 8, iN - i0 - 8); // 8 = len("<detids>")
+      std::stringstream ss(line);
+
+      std::string item;
+      while (std::getline(ss, item, ',')) {
+        auto k = item.find('-');
+
+        size_t p0, p1;
+        if (k != std::string::npos) {
+          p0 = boost::lexical_cast<size_t>(item.substr(0, k));
+          p1 = boost::lexical_cast<size_t>(
+              item.substr(k + 1, item.size() - k - 1));
+
+          if (p0 > p1)
+            std::swap(p0, p1);
+        } else {
+          p0 = boost::lexical_cast<size_t>(item);
+          p1 = p0;
+        }
 
-  // source
-  Geometry::ObjComponent *source =
-      new Geometry::ObjComponent("Source", instrument.get());
-  instrument->add(source);
-  instrument->markAsSource(source);
+        if (p0 < result.size()) {
+          if (p1 >= result.size())
+            p1 = result.size() - 1;
 
-  //// chopper
-  // Geometry::ObjComponent *chopperPoint = new
-  // Geometry::ObjComponent("Chopper", instrument.get());
-  // instrument->add(chopper);
-  // instrument->markAsChopperPoint(chopper);
+          while (p0 <= p1)
+            result[p0++] = false;
+        }
+      }
+    }
+  }
 
-  // sample
-  Geometry::ObjComponent *samplePos =
-      new Geometry::ObjComponent("Sample", instrument.get());
-  instrument->add(samplePos);
-  instrument->markAsSamplePos(samplePos);
+  return result;
+}
+
+// instrument creation
+Geometry::Instrument_sptr
+LoadBBY::createInstrument(ANSTO::Tar::File &tarFile,
+                          InstrumentInfo &instrumentInfo) {
+  instrumentInfo.bm_counts = 0;
+  instrumentInfo.att_pos = 0;
 
-  double L2_det_value = 33.15616015625;
-  double L1_chopper_value = 18.47258984375;
-  // double L1_source_value    =  9.35958984375;
+  instrumentInfo.period_master = 0.0;
+  instrumentInfo.period_slave = 0.0;
+  instrumentInfo.phase_slave = 0.0;
 
-  double L2_curtainl_value = 23.28446093750;
-  double L2_curtainr_value = 23.28201953125;
-  double L2_curtainu_value = 24.28616015625;
-  double L2_curtaind_value = 24.28235937500;
+  instrumentInfo.L1_chopper_value = 18.47258984375;
+  instrumentInfo.L2_det_value = 33.15616015625;
 
-  double D_det_value = (8.4 + 2.0) / (2 * 1000);
+  instrumentInfo.L2_curtainl_value = 23.28446093750;
+  instrumentInfo.L2_curtainr_value = 23.28201953125;
+  instrumentInfo.L2_curtainu_value = 24.28616015625;
+  instrumentInfo.L2_curtaind_value = 24.28235937500;
 
-  double D_curtainl_value = 0.3816;
-  double D_curtainr_value = 0.4024;
-  double D_curtainu_value = 0.3947;
-  double D_curtaind_value = 0.3978;
+  instrumentInfo.D_det_value = (8.4 + 2.0) / (2 * 1000);
+
+  instrumentInfo.D_curtainl_value = 0.3816;
+  instrumentInfo.D_curtainr_value = 0.4024;
+  instrumentInfo.D_curtainu_value = 0.3947;
+  instrumentInfo.D_curtaind_value = 0.3978;
 
   // extract hdf file
   int64_t fileSize = 0;
@@ -459,7 +498,7 @@ Geometry::Instrument_sptr LoadBBY::createInstrument(ANSTO::Tar::File &tarFile,
     }
 
   if (fileSize != 0) {
-    // create tmp file
+    // extract hdf file into tmp file
     Poco::TemporaryFile hdfFile;
     boost::shared_ptr<FILE> handle(fopen(hdfFile.path().c_str(), "wb"), fclose);
     if (handle) {
@@ -473,37 +512,72 @@ Geometry::Instrument_sptr LoadBBY::createInstrument(ANSTO::Tar::File &tarFile,
       NeXus::NXRoot root(hdfFile.path());
       NeXus::NXEntry entry = root.openFirstEntry();
 
-      float tmp;
+      float tmp_float;
+      int32_t tmp_int32 = 0;
       const double toMeters = 1.0 / 1000;
 
-      if (loadNXDataSet(tmp, entry, "instrument/L2_det"))
-        L2_det_value = tmp * toMeters;
-      if (loadNXDataSet(tmp, entry, "instrument/Ltof_det"))
-        L1_chopper_value = tmp * toMeters - L2_det_value;
-      // if (loadNXDataSet(tmp, entry, "instrument/L1"))
-      //  L1_source_value = tmp * toMeters;
-
-      if (loadNXDataSet(tmp, entry, "instrument/L2_curtainl"))
-        L2_curtainl_value = tmp * toMeters;
-      if (loadNXDataSet(tmp, entry, "instrument/L2_curtainr"))
-        L2_curtainr_value = tmp * toMeters;
-      if (loadNXDataSet(tmp, entry, "instrument/L2_curtainu"))
-        L2_curtainu_value = tmp * toMeters;
-      if (loadNXDataSet(tmp, entry, "instrument/L2_curtaind"))
-        L2_curtaind_value = tmp * toMeters;
-
-      if (loadNXDataSet(tmp, entry, "instrument/detector/curtainl"))
-        D_curtainl_value = tmp * toMeters;
-      if (loadNXDataSet(tmp, entry, "instrument/detector/curtainr"))
-        D_curtainr_value = tmp * toMeters;
-      if (loadNXDataSet(tmp, entry, "instrument/detector/curtainu"))
-        D_curtainu_value = tmp * toMeters;
-      if (loadNXDataSet(tmp, entry, "instrument/detector/curtaind"))
-        D_curtaind_value = tmp * toMeters;
+      if (loadNXDataSet(entry, "monitor/bm1_counts", tmp_int32))
+        instrumentInfo.bm_counts = tmp_int32;
+      if (loadNXDataSet(entry, "instrument/att_pos", tmp_float))
+        instrumentInfo.att_pos =
+            static_cast<int32_t>(tmp_float + 0.5f); // [1.0, 2.0, ..., 5.0]
+
+      if (loadNXDataSet(entry, "instrument/master_chopper_freq", tmp_float))
+        instrumentInfo.period_master = 1.0 / tmp_float * 1.0e6;
+      if (loadNXDataSet(entry, "instrument/t0_chopper_freq", tmp_float))
+        instrumentInfo.period_slave = 1.0 / tmp_float * 1.0e6;
+      if (loadNXDataSet(entry, "instrument/t0_chopper_phase", tmp_float))
+        instrumentInfo.phase_slave = tmp_float < 999.0 ? tmp_float : 0.0;
+
+      if (loadNXDataSet(entry, "instrument/L2_det", tmp_float))
+        instrumentInfo.L2_det_value = tmp_float * toMeters;
+      if (loadNXDataSet(entry, "instrument/Ltof_det", tmp_float))
+        instrumentInfo.L1_chopper_value =
+            tmp_float * toMeters - instrumentInfo.L2_det_value;
+      // if (loadNXDataSet(entry, "instrument/L1", tmp_float))
+      //  instrumentInfo.L1_source_value = tmp_float * toMeters;
+
+      if (loadNXDataSet(entry, "instrument/L2_curtainl", tmp_float))
+        instrumentInfo.L2_curtainl_value = tmp_float * toMeters;
+      if (loadNXDataSet(entry, "instrument/L2_curtainr", tmp_float))
+        instrumentInfo.L2_curtainr_value = tmp_float * toMeters;
+      if (loadNXDataSet(entry, "instrument/L2_curtainu", tmp_float))
+        instrumentInfo.L2_curtainu_value = tmp_float * toMeters;
+      if (loadNXDataSet(entry, "instrument/L2_curtaind", tmp_float))
+        instrumentInfo.L2_curtaind_value = tmp_float * toMeters;
+
+      if (loadNXDataSet(entry, "instrument/detector/curtainl", tmp_float))
+        instrumentInfo.D_curtainl_value = tmp_float * toMeters;
+      if (loadNXDataSet(entry, "instrument/detector/curtainr", tmp_float))
+        instrumentInfo.D_curtainr_value = tmp_float * toMeters;
+      if (loadNXDataSet(entry, "instrument/detector/curtainu", tmp_float))
+        instrumentInfo.D_curtainu_value = tmp_float * toMeters;
+      if (loadNXDataSet(entry, "instrument/detector/curtaind", tmp_float))
+        instrumentInfo.D_curtaind_value = tmp_float * toMeters;
     }
   }
 
-  source->setPos(0.0, 0.0, -L1_chopper_value);
+  return Geometry::Instrument_sptr();
+
+  /*
+  // instrument
+  Geometry::Instrument_sptr instrument =
+  boost::make_shared<Geometry::Instrument>("BILBY");
+  instrument->setDefaultViewAxis("Z-");
+
+  // source
+  Geometry::ObjComponent *source = new Geometry::ObjComponent("Source",
+  instrument.get());
+  instrument->add(source);
+  instrument->markAsSource(source);
+
+  // sample
+  Geometry::ObjComponent *samplePos = new Geometry::ObjComponent("Sample",
+  instrument.get());
+  instrument->add(samplePos);
+  instrument->markAsSamplePos(samplePos);
+
+  source->setPos(0.0, 0.0, -instrumentInfo.L1_chopper_value);
   samplePos->setPos(0.0, 0.0, 0.0);
 
   // dimensions of the detector (height is in y direction, width is in x
@@ -520,14 +594,6 @@ Geometry::Instrument_sptr LoadBBY::createInstrument(ANSTO::Tar::File &tarFile,
   double pixel_width = width / static_cast<double>(xPixelCount);
   double pixel_height = height / static_cast<double>(yPixelCount);
 
-  // adjusting for binning
-  auto diffPixelsCutOff = (pixelsCutOffL - pixelsCutOffH);
-  double detectorYOffset = static_cast<double>(diffPixelsCutOff) * pixel_height;
-
-  yPixelCount = finalBinsY;
-  pixel_height *= static_cast<double>(tubeBinning);
-  height = pixel_height * static_cast<double>(finalBinsY);
-
   // final number of pixels
   size_t pixelCount = xPixelCount * yPixelCount;
 
@@ -543,19 +609,16 @@ Geometry::Instrument_sptr LoadBBY::createInstrument(ANSTO::Tar::File &tarFile,
   // http://www.mantidproject.org/HowToDefineGeometricShape for details on
   // shapes in Mantid.
   std::string detXML =
-      "<cuboid id=\"pixel\">"
-      "<left-front-bottom-point   x=\"+" +
-      pixel_width_str + "\" y=\"-" + pixel_height_str +
-      "\" z=\"0\"  />"
-      "<left-front-top-point      x=\"+" +
-      pixel_width_str + "\" y=\"-" + pixel_height_str + "\" z=\"" +
-      pixel_depth_str + "\"  />"
-                        "<left-back-bottom-point    x=\"-" +
-      pixel_width_str + "\" y=\"-" + pixel_height_str +
-      "\" z=\"0\"  />"
-      "<right-front-bottom-point  x=\"+" +
-      pixel_width_str + "\" y=\"+" + pixel_height_str + "\" z=\"0\"  />"
-                                                        "</cuboid>";
+    "<cuboid id=\"pixel\">"
+      "<left-front-bottom-point   x=\"+"+pixel_width_str+"\"
+  y=\"-"+pixel_height_str+"\" z=\"0\"  />"
+      "<left-front-top-point      x=\"+"+pixel_width_str+"\"
+  y=\"-"+pixel_height_str+"\" z=\""+pixel_depth_str+"\"  />"
+      "<left-back-bottom-point    x=\"-"+pixel_width_str+"\"
+  y=\"-"+pixel_height_str+"\" z=\"0\"  />"
+      "<right-front-bottom-point  x=\"+"+pixel_width_str+"\"
+  y=\"+"+pixel_height_str+"\" z=\"0\"  />"
+    "</cuboid>";
 
   // Create a shape object which will be shared by all pixels.
   Geometry::Object_sptr pixelShape =
@@ -564,77 +627,83 @@ Geometry::Instrument_sptr LoadBBY::createInstrument(ANSTO::Tar::File &tarFile,
   // create detector banks
   BbyDetectorBankFactory factory(
       instrument, pixelShape, xPixelCount, yPixelCount, pixel_width,
-      pixel_height,
-      Kernel::V3D(0, (height - pixel_height) / 2 - detectorYOffset, 0));
+      pixel_height, Kernel::V3D(0, (height - pixel_height) / 2, 0));
 
   // curtain l
   factory.createAndAssign(0 * pixelCount,
-                          Kernel::V3D(+D_curtainl_value, 0, L2_curtainl_value),
+                          Kernel::V3D(+instrumentInfo.D_curtainl_value, 0,
+  instrumentInfo.L2_curtainl_value),
                           Kernel::Quat(0, Kernel::V3D(0, 0, 1)) *
                               Kernel::Quat(angle, Kernel::V3D(0, 1, 0)));
 
   // curtain r
   factory.createAndAssign(1 * pixelCount,
-                          Kernel::V3D(-D_curtainr_value, 0, L2_curtainr_value),
+                          Kernel::V3D(-instrumentInfo.D_curtainr_value, 0,
+  instrumentInfo.L2_curtainr_value),
                           Kernel::Quat(180, Kernel::V3D(0, 0, 1)) *
                               Kernel::Quat(angle, Kernel::V3D(0, 1, 0)));
 
   // curtain u
   factory.createAndAssign(2 * pixelCount,
-                          Kernel::V3D(0, +D_curtainu_value, L2_curtainu_value),
+                          Kernel::V3D(0, +instrumentInfo.D_curtainu_value,
+  instrumentInfo.L2_curtainu_value),
                           Kernel::Quat(90, Kernel::V3D(0, 0, 1)) *
                               Kernel::Quat(angle, Kernel::V3D(0, 1, 0)));
 
   // curtain d
   factory.createAndAssign(3 * pixelCount,
-                          Kernel::V3D(0, -D_curtaind_value, L2_curtaind_value),
+                          Kernel::V3D(0, -instrumentInfo.D_curtaind_value,
+  instrumentInfo.L2_curtaind_value),
                           Kernel::Quat(-90, Kernel::V3D(0, 0, 1)) *
                               Kernel::Quat(angle, Kernel::V3D(0, 1, 0)));
 
   // back 1 (left)
   factory.createAndAssign(4 * pixelCount,
-                          Kernel::V3D(+D_det_value, 0, L2_det_value),
+                          Kernel::V3D(+instrumentInfo.D_det_value, 0,
+  instrumentInfo.L2_det_value),
                           Kernel::Quat(0, Kernel::V3D(0, 0, 1)));
 
   // back 2 (right)
   factory.createAndAssign(5 * pixelCount,
-                          Kernel::V3D(-D_det_value, 0, L2_det_value),
+                          Kernel::V3D(-instrumentInfo.D_det_value, 0,
+  instrumentInfo.L2_det_value),
                           Kernel::Quat(180, Kernel::V3D(0, 0, 1)));
 
   return instrument;
+  */
 }
 
 // load nx dataset
 template <class T>
-bool LoadBBY::loadNXDataSet(T &value, NeXus::NXEntry &entry,
-                            const std::string &path) {
+bool LoadBBY::loadNXDataSet(NeXus::NXEntry &entry, const std::string &path,
+                            T &value) {
   try {
-    // if (entry.isValid(path)) {
-    NeXus::NXDataSetTyped<T> dataSet = entry.openNXDataSet<float>(path);
+    NeXus::NXDataSetTyped<T> dataSet = entry.openNXDataSet<T>(path);
     dataSet.load();
 
     value = *dataSet();
     return true;
-    //}
   } catch (std::runtime_error &) {
+    return false;
   }
-  return false;
 }
 
 // read counts/events from binary file
-template <class Counter>
+template <class EventProcessor>
 void LoadBBY::loadEvents(API::Progress &prog, const char *progMsg,
-                         ANSTO::Tar::File &file, const double tofMinBoundary,
-                         const double tofMaxBoundary, Counter &counter) {
+                         ANSTO::Tar::File &tarFile,
+                         EventProcessor &eventProcessor) {
   prog.doReport(progMsg);
 
+  bool countsInFrame = false;
+
   // select bin file
   int64_t fileSize = 0;
-  const std::vector<std::string> &files = file.files();
+  const std::vector<std::string> &files = tarFile.files();
   for (auto itr = files.begin(); itr != files.end(); ++itr)
     if (itr->rfind(".bin") == itr->length() - 4) {
-      file.select(itr->c_str());
-      fileSize = file.selected_size();
+      tarFile.select(itr->c_str());
+      fileSize = tarFile.selected_size();
       break;
     }
 
@@ -650,12 +719,12 @@ void LoadBBY::loadEvents(API::Progress &prog, const char *progMsg,
   unsigned int dt = 0;
   double tof = 0.0;
 
-  if ((fileSize == 0) || !file.skip(128))
+  if ((fileSize == 0) || !tarFile.skip(128))
     return;
 
   int state = 0;
   unsigned int c;
-  while ((c = (unsigned int)file.read_byte()) != (unsigned int)-1) {
+  while ((c = (unsigned int)tarFile.read_byte()) != (unsigned int)-1) {
 
     bool event_ended = false;
     switch (state) {
@@ -697,104 +766,27 @@ void LoadBBY::loadEvents(API::Progress &prog, const char *progMsg,
 
       if ((x == 0) && (y == 0) && (dt == 0xFFFFFFFF)) {
         tof = 0.0;
+
+        // only count frames that contain neutrons
+        if (countsInFrame) {
+          eventProcessor.endOfFrame();
+          countsInFrame = false;
+        }
       } else if ((x >= HISTO_BINS_X) || (y >= HISTO_BINS_Y)) {
       } else {
         // conversion from 100 nanoseconds to 1 microsecond
         tof += ((int)dt) * 0.1;
 
-        if ((tofMinBoundary <= tof) && (tof <= tofMaxBoundary))
-          counter.addEvent(x, y, tof);
+        eventProcessor.addEvent(x, y, tof);
+        countsInFrame = true;
       }
 
-      progTracker.update(file.selected_position());
+      progTracker.update(tarFile.selected_position());
     }
   }
-}
-
-// load mask file
-std::vector<bool> LoadBBY::createMaskVector(const std::string &filename,
-                                            bool &fileLoaded) {
-  std::vector<bool> result(HISTO_BINS_X * HISTO_BINS_Y, true);
-
-  std::ifstream input(filename.c_str());
-  if (input.good()) {
-    std::string line;
-    while (std::getline(input, line)) {
-
-      auto i0 = line.find("<detids>");
-      auto iN = line.find("</detids>");
-
-      if ((i0 != std::string::npos) && (iN != std::string::npos) && (i0 < iN)) {
-
-        line = line.substr(i0 + 8, iN - i0 - 8);
-        std::stringstream ss(line);
-
-        std::string item;
-        while (std::getline(ss, item, ',')) {
-          auto k = item.find('-');
-
-          size_t p0, p1;
-          if (k != std::string::npos) {
-            p0 = boost::lexical_cast<size_t>(item.substr(0, k));
-            p1 = boost::lexical_cast<size_t>(
-                item.substr(k + 1, item.size() - k - 1));
-
-            if (p0 > p1)
-              std::swap(p0, p1);
-          } else {
-            p0 = boost::lexical_cast<size_t>(item);
-            p1 = p0;
-          }
-
-          if (p0 < result.size()) {
-
-            if (p1 >= result.size())
-              p1 = result.size() - 1;
-
-            while (p0 <= p1)
-              result[p0++] = false;
-          }
-        }
-      }
-    }
-    fileLoaded = true;
-  } else {
-    fileLoaded = false;
-  }
 
-  return result;
-}
-
-// load tube offset file
-std::vector<int> LoadBBY::createOffsetVector(const std::string &filename,
-                                             bool &fileLoaded) {
-  std::vector<int> result(HISTO_BINS_X, 0);
-
-  std::ifstream input(filename.c_str());
-  if (input.good()) {
-    std::string line;
-    while (std::getline(input, line)) {
-      auto i1 = line.find_first_of(",;");
-      if (i1 == std::string::npos)
-        continue;
-
-      auto i2 = line.find_first_of(",;", i1 + 1);
-      if (i2 == std::string::npos)
-        i2 = line.size();
-
-      size_t index = boost::lexical_cast<size_t>(line.substr(0, i1));
-      int offset =
-          boost::lexical_cast<int>(line.substr(i1 + 1, line.size() - i1 - 1));
-
-      if (index < HISTO_BINS_X)
-        result[index] = offset;
-    }
-    fileLoaded = true;
-  } else {
-    fileLoaded = false;
-  }
-
-  return result;
+  if (countsInFrame)
+    eventProcessor.endOfFrame();
 }
 
 // DetectorBankFactory
@@ -811,7 +803,8 @@ void BbyDetectorBankFactory::createAndAssign(size_t startIndex,
   // create a RectangularDetector which represents a rectangular array of pixels
   Geometry::RectangularDetector *bank = new Geometry::RectangularDetector(
       "bank",
-      m_instrument.get()); // ??? possible memory leak!? "new" without "delete"
+      m_instrument.get()); // Bank gets registered with instrument component.
+                           // instrument acts as sink and manages lifetime.
 
   bank->initialize(m_pixelShape,
                    // x
@@ -831,5 +824,6 @@ void BbyDetectorBankFactory::createAndAssign(size_t startIndex,
   bank->rotate(rot);
   bank->translate(pos - center);
 }
-} // namespace
-} // namespace
\ No newline at end of file
+
+} // DataHandling
+} // Mantid
\ No newline at end of file
diff --git a/Framework/DataHandling/src/LoadGSS.cpp b/Framework/DataHandling/src/LoadGSS.cpp
index 9ddea8c26c208e5ff974ed8f0dda42b49d17186a..6f27008e5c7716c5d20e0c65e42499d6eb9cb516 100644
--- a/Framework/DataHandling/src/LoadGSS.cpp
+++ b/Framework/DataHandling/src/LoadGSS.cpp
@@ -35,7 +35,8 @@ DECLARE_FILELOADER_ALGORITHM(LoadGSS)
  * be used
   */
 int LoadGSS::confidence(Kernel::FileDescriptor &descriptor) const {
-  if (!descriptor.isAscii())
+
+  if (!descriptor.isAscii() || descriptor.extension() == ".tar")
     return 0;
 
   std::string str;
diff --git a/Framework/DataHandling/test/LoadBBYTest.h b/Framework/DataHandling/test/LoadBBYTest.h
index 6973745e264c5711c144529a3972117a43986d5e..106c4df0a8472782e522fa28e359e0054f29e988 100644
--- a/Framework/DataHandling/test/LoadBBYTest.h
+++ b/Framework/DataHandling/test/LoadBBYTest.h
@@ -21,45 +21,101 @@ using namespace Mantid::DataObjects;
 
 class LoadBBYTest : public CxxTest::TestSuite {
 public:
-  void testInit() {
+  void test_load_bby_algorithm_init() {
+    LoadBBY algToBeTested;
+
     TS_ASSERT_THROWS_NOTHING(algToBeTested.initialize());
     TS_ASSERT(algToBeTested.isInitialized());
   }
 
-  // test loading of bilby dataset
-  void testExec() {
+  void test_load_bby_algorithm() {
+    LoadBBY algToBeTested;
+
     if (!algToBeTested.isInitialized())
       algToBeTested.initialize();
 
-    outputSpace = "LoadBBYTest";
+    std::string outputSpace = "LoadBBYTest";
     algToBeTested.setPropertyValue("OutputWorkspace", outputSpace);
 
-    // Should fail because mandatory parameter has not been set
+    // should fail because mandatory parameter has not been set
     TS_ASSERT_THROWS(algToBeTested.execute(), std::runtime_error);
 
-    inputFile = "BBY0000014.tar";
+    // should succeed now
+    std::string inputFile = "BBY0000014.tar";
     algToBeTested.setPropertyValue("Filename", inputFile);
     TS_ASSERT_THROWS_NOTHING(algToBeTested.execute());
     TS_ASSERT(algToBeTested.isExecuted());
 
-    //  get workspace generated
+    // get workspace generated
     MatrixWorkspace_sptr output =
         AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(
             outputSpace);
 
-    // test it is as expected
+    // check number of histograms
     TS_ASSERT_EQUALS(output->getNumberHistograms(), 61440);
     double sum = 0.0;
     for (size_t i = 0; i < output->getNumberHistograms(); i++)
       sum += output->readY(i)[0];
     sum *= 1.0e22;
     TS_ASSERT_DELTA(sum / 1.0E27, 2.0, 0.0001);
-  }
 
-private:
-  LoadBBY algToBeTested;
-  std::string inputFile;
-  std::string outputSpace;
+    // check that all required log values are there
+    auto run = output->run();
+
+    // test start and end time
+    TS_ASSERT(
+        run.getProperty("start_time")->value().compare("2000-01-01T00:00:00") ==
+        0)
+    TS_ASSERT(
+        run.getProperty("end_time")->value().compare("2000-01-01T00:00:00") ==
+        0)
+
+    // test data properties
+    TS_ASSERT_EQUALS(run.getPropertyValueAsType<int>("att_pos"), 1);
+    TS_ASSERT_EQUALS(run.getPropertyValueAsType<int>("frame_count"), 4);
+    TS_ASSERT_DELTA(run.getPropertyValueAsType<double>("period"), 0, 1.0e-5);
+    TS_ASSERT_DELTA(run.getPropertyValueAsType<double>("bm_counts"), 0, 1.0e-5);
+
+    // test instrument setup
+    TS_ASSERT_DELTA(dynamic_cast<TimeSeriesProperty<double> *>(
+                        run.getProperty("L1_chopper_value"))->firstValue(),
+                    18.4726, 1.0e-3);
+
+    TS_ASSERT_DELTA(dynamic_cast<TimeSeriesProperty<double> *>(
+                        run.getProperty("L2_det_value"))->firstValue(),
+                    33.1562, 1.0e-3);
+    TS_ASSERT_DELTA(dynamic_cast<TimeSeriesProperty<double> *>(
+                        run.getProperty("L2_curtainl_value"))->firstValue(),
+                    23.2845, 1.0e-3);
+    TS_ASSERT_DELTA(dynamic_cast<TimeSeriesProperty<double> *>(
+                        run.getProperty("L2_curtainr_value"))->firstValue(),
+                    23.2820, 1.0e-3);
+    TS_ASSERT_DELTA(dynamic_cast<TimeSeriesProperty<double> *>(
+                        run.getProperty("L2_curtainu_value"))->firstValue(),
+                    24.2862, 1.0e-3);
+    TS_ASSERT_DELTA(dynamic_cast<TimeSeriesProperty<double> *>(
+                        run.getProperty("L2_curtaind_value"))->firstValue(),
+                    24.2824, 1.0e-3);
+
+    TS_ASSERT_DELTA(dynamic_cast<TimeSeriesProperty<double> *>(
+                        run.getProperty("D_det_value"))->firstValue(),
+                    0.0052, 1.0e-4);
+    TS_ASSERT_DELTA(dynamic_cast<TimeSeriesProperty<double> *>(
+                        run.getProperty("D_curtainl_value"))->firstValue(),
+                    0.3816, 1.0e-4);
+    TS_ASSERT_DELTA(dynamic_cast<TimeSeriesProperty<double> *>(
+                        run.getProperty("D_curtainr_value"))->firstValue(),
+                    0.4024, 1.0e-4);
+    TS_ASSERT_DELTA(dynamic_cast<TimeSeriesProperty<double> *>(
+                        run.getProperty("D_curtainu_value"))->firstValue(),
+                    0.3947, 1.0e-4);
+    TS_ASSERT_DELTA(dynamic_cast<TimeSeriesProperty<double> *>(
+                        run.getProperty("D_curtaind_value"))->firstValue(),
+                    0.3978, 1.0e-4);
+    TS_ASSERT_DELTA(dynamic_cast<TimeSeriesProperty<double> *>(
+                        run.getProperty("curtain_rotation"))->firstValue(),
+                    10, 1.0e-7);
+  }
 };
 
 #endif /*LoadBBYTEST_H_*/
diff --git a/instrument/Bilby_Definition.xml b/instrument/Bilby_Definition.xml
new file mode 100644
index 0000000000000000000000000000000000000000..81029ac258ae427777382b1c5f79f82a6478b94b
--- /dev/null
+++ b/instrument/Bilby_Definition.xml
@@ -0,0 +1,506 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- For help on the notation used to specify an Instrument Definition File 
+     see http://www.mantidproject.org/IDF -->
+<instrument xmlns="http://www.mantidproject.org/IDF/1.0" 
+            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+            xsi:schemaLocation="http://www.mantidproject.org/IDF/1.0 http://schema.mantidproject.org/IDF/1.0/IDFSchema.xsd"
+ name="Bilby" valid-from   ="1901-01-01 00:00:00"
+                       valid-to     ="2100-01-01 00:00:00"
+		       last-modified="2100-01-01 00:00:00">
+
+  <defaults>
+    <length unit="meter"/>
+    <angle unit="degree"/>
+    <reference-frame>
+      <!-- The z-axis is set parallel to and in the direction of the beam. the 
+           y-axis points up and the coordinate system is right handed. -->
+      <along-beam axis="z"/>
+      <pointing-up axis="y"/>
+      <handedness val="right"/>
+    </reference-frame>
+    <default-view axis-view="z-"/>
+  </defaults>
+
+  
+  <!-- source and sample-position components -->
+  <component name="Source" type="source">
+    <location x="0.0" y="0.0" />
+    <parameter name="z"> 
+      <logfile id="L1_chopper_value" eq="1*value"/>
+    </parameter>
+  </component>
+  <type name="source" is="Source" />
+  
+  <component name="Sample-Holder" type="some-sample-holder">
+    <location z="0.0" x="0.0" y="0.0"/>
+  </component>
+  <type name="some-sample-holder" is="SamplePos" />
+  
+  <type name="pixel" is="detector">
+    <cylinder id="cyl-approx">
+      <centre-of-bottom-base r="0.0" t="0.0" p="0.0" />
+      <axis x="0.0" y="1.0" z="0.0" />
+      <radius val="0.004" />
+      <height val="0.0025" /> <!-- height 0.64m/256 -->
+    </cylinder>
+    <algebra val="cyl-approx" />
+  </type>
+  
+    <component name="CurtainLeft" type="bank01" idlist="bank01">
+  <location/>
+ </component>
+  <type name="bank01">
+ <component type="IdealBilbyPanel">
+    <location y="0.0">
+      <!-- Rotate the panel 10 degrees -->
+      <rot val="10" axis-x="0" axis-y="1" axis-z="0">
+      </rot>
+    </location>
+    <parameter name="z">
+      <logfile id="L2_curtainl_value" eq="1*value - ( sin(10 * _pi / 180.0) * 0.0084 * 40 / 2 )"/> <!-- front l panel position -->
+    </parameter>
+    <parameter name="x">
+	  <!-- from beam center 0.1678 = ( (0.008*40) + (0.0004 * 39) ) / 2 -->
+      <logfile id="D_curtainl_value" eq="0.1678 + value"/> <!-- from beam center -->
+    </parameter>
+ </component>
+ </type>
+ 
+<component name="CurtainTop" type="bank03" idlist="bank03">
+  <location/>
+</component>
+<type name="bank03">
+ <component type="IdealBilbyPanel">
+    <location x="0.0"> 
+    <rot val="90" axis-x="0" axis-y="0" axis-z="1">
+    <!-- Rotate the panel 10 degrees -->
+    <rot val="10" axis-x="0" axis-y="1" axis-z="0" />
+    </rot>
+    </location>
+    <parameter name="z">
+      <logfile id="L2_curtainu_value" eq="1*value - ( sin(10 * _pi / 180.0) * 0.0084 * 40 / 2 )"/> <!-- front t panel z position -->
+    </parameter>
+    <parameter name="y">
+	 <!-- from beam center 0.1678 = ( (0.008*40) + (0.0004 * 39) ) / 2 -->
+      <logfile id="D_curtainu_value" eq="0.1678 + value"/> <!-- from beam center -->
+    </parameter>
+ </component>
+</type>
+
+    <component name="CurtainRight" type="bank02" idlist="bank02">
+  <location/>
+ </component>
+  <type name="bank02">
+ <component type="IdealBilbyPanel">
+    <location y="0.0" > 
+    <rot val="180" axis-x="0" axis-y="0" axis-z="1">
+    <!-- Rotate the panel 10 degrees -->
+    <rot val="10" axis-x="0" axis-y="1" axis-z="0" />
+    </rot>
+    </location>
+    <parameter name="z">
+      <logfile id="L2_curtainr_value" eq="1*value - ( sin(10 * _pi / 180.0) * 0.0084 * 40 / 2 )"/> <!-- front r panel z position -->
+    </parameter>
+    <parameter name="x">
+	  <!-- from beam center 0.1678 = ( (0.008*40) + (0.0004 * 39) ) / 2 -->
+      <logfile id="D_curtainr_value" eq="-0.1678 - value"/> <!-- from beam center --> 
+    </parameter>
+ </component>
+ </type>
+ 
+     <component name="CurtainBottom" type="bank04" idlist="bank04">
+  <location/>
+ </component>
+  <type name="bank04">
+ <component type="IdealBilbyPanel">
+    <location x="0.0" > 
+    <rot val="270" axis-x="0" axis-y="0" axis-z="1">
+    <!-- Rotate the panel 10 degrees -->
+    <rot val="10" axis-x="0" axis-y="1" axis-z="0" />
+    </rot>
+    </location>
+    <parameter name="z">
+      <logfile id="L2_curtaind_value" eq="1*value - ( sin(10 * _pi / 180.0) * 0.0084 * 40 / 2 )"/> <!-- front b panel z position -->
+    </parameter>
+    <parameter name="y">
+	 <!-- from beam center 0.1678 = ( (0.008*40) + (0.0004 * 39) ) / 2 -->
+      <logfile id="D_curtaind_value" eq="-0.1678 - value"/> <!-- from beam center -->
+    </parameter>
+ </component>
+ </type>
+ 
+ <component name="BackDetectorLeft" type="bank05" idlist="bank05">
+  <location/>
+ </component>
+  <type name="bank05">
+ <component type="EastBilbyPanel">
+    <location  y="0.0" > 
+    </location>
+    <parameter name="z"> 
+      <logfile id="L2_det_value"/> <!-- back panel z position -->
+    </parameter>
+    <parameter name="x">
+	  <!-- from beam center 0.1678 = ( (0.008*40) + (0.0004 * 39) ) / 2 -->
+      <logfile id="D_det_value" eq="0.1678 + value"/> <!-- x pos -->
+    </parameter>
+ </component>
+ </type>
+ 
+  <component name="BackDetectorRight" type="bank06" idlist="bank06">
+  <location/>
+ </component>
+  <type name="bank06">
+ <component type="WestBilbyPanel">
+    <location x="-0.168" y="0.0" > 
+     <rot val="180" axis-x="0" axis-y="0" axis-z="1" />
+    </location>
+    <parameter name="z"> 
+      <logfile id="L2_det_value"/> <!-- back panel z position -->
+    </parameter>
+    <parameter name="x">
+	  <!-- from beam center 0.1678 = ( (0.008*40) + (0.0004 * 39) ) / 2 -->
+      <logfile id="D_det_value" eq="-0.1678 - value"/>  <!-- x pos -->
+    </parameter>
+ </component>
+ </type>
+ 
+ <!--- Bilby's 6 panels are 0.64m high, and 0.336m wide. Each panel has 40 tubes each made from 256 pixels. --> 
+ 
+  <!-- Grouping by eight-packs would really be unnecessary. All tubes equally spaced. -->
+ <type name="IdealBilbyPanel"> 
+ <component type="eight_pack">
+<location  x="-0.168000" name="eight_pack1" />
+<location  x="-0.100800" name="eight_pack2" />
+<location  x="-0.033600" name="eight_pack3" />
+<location  x="0.033600" name="eight_pack4" />
+<location  x="0.100800" name="eight_pack5" />
+ </component>
+ </type> 
+ 
+ <!-- eight-packs not equally separated. -->
+ <type name="EastBilbyPanel"> 
+ <!-- Grouping by eight-packs would really be unnecessary. All tubes equally spaced. -->
+ <component type="eight_pack">
+<location  x="-0.167000" name="eight_pack1" />
+<location  x="-0.099200" name="eight_pack2" />
+<location  x="-0.031600" name="eight_pack3" />
+<location  x="0.036200" name="eight_pack4" />
+<location  x="0.104000" name="eight_pack5" />
+ </component>
+ </type> 
+ 
+  <!-- eight-packs not equally separated. -->
+  <type name="WestBilbyPanel"> 
+ <!-- Grouping by eight-packs would really be unnecessary. All tubes equally spaced. -->
+ <component type="eight_pack">
+<location  x="-0.167000" name="eight_pack1" />
+<location  x="-0.099200" name="eight_pack2" />
+<location  x="-0.031600" name="eight_pack3" />
+<location  x="0.035700" name="eight_pack4" />
+<location  x="0.103900" name="eight_pack5" />
+ </component>
+ </type> 
+ 
+<type name="eight_pack">
+<component type="tube">
+<!-- tubes in each eight_pack are 0.0004 m separated -->
+<location  x="0.000000" name="tube1" />
+<location  x="0.008400" name="tube2" />
+<location  x="0.016800" name="tube3" />
+<location  x="0.025200" name="tube4" />
+<location  x="0.033600" name="tube5" />
+<location  x="0.042000" name="tube6" />
+<location  x="0.050400" name="tube7" />
+<location  x="0.058800" name="tube8" />
+</component>
+</type>
+
+ 
+ <type name="tube" outline="yes">
+ <component type="pixel">
+<location y="-0.320000" name="pixel1"/>
+<location y="-0.317500" name="pixel2"/>
+<location y="-0.315000" name="pixel3"/>
+<location y="-0.312500" name="pixel4"/>
+<location y="-0.310000" name="pixel5"/>
+<location y="-0.307500" name="pixel6"/>
+<location y="-0.305000" name="pixel7"/>
+<location y="-0.302500" name="pixel8"/>
+<location y="-0.300000" name="pixel9"/>
+<location y="-0.297500" name="pixel10"/>
+<location y="-0.295000" name="pixel11"/>
+<location y="-0.292500" name="pixel12"/>
+<location y="-0.290000" name="pixel13"/>
+<location y="-0.287500" name="pixel14"/>
+<location y="-0.285000" name="pixel15"/>
+<location y="-0.282500" name="pixel16"/>
+<location y="-0.280000" name="pixel17"/>
+<location y="-0.277500" name="pixel18"/>
+<location y="-0.275000" name="pixel19"/>
+<location y="-0.272500" name="pixel20"/>
+<location y="-0.270000" name="pixel21"/>
+<location y="-0.267500" name="pixel22"/>
+<location y="-0.265000" name="pixel23"/>
+<location y="-0.262500" name="pixel24"/>
+<location y="-0.260000" name="pixel25"/>
+<location y="-0.257500" name="pixel26"/>
+<location y="-0.255000" name="pixel27"/>
+<location y="-0.252500" name="pixel28"/>
+<location y="-0.250000" name="pixel29"/>
+<location y="-0.247500" name="pixel30"/>
+<location y="-0.245000" name="pixel31"/>
+<location y="-0.242500" name="pixel32"/>
+<location y="-0.240000" name="pixel33"/>
+<location y="-0.237500" name="pixel34"/>
+<location y="-0.235000" name="pixel35"/>
+<location y="-0.232500" name="pixel36"/>
+<location y="-0.230000" name="pixel37"/>
+<location y="-0.227500" name="pixel38"/>
+<location y="-0.225000" name="pixel39"/>
+<location y="-0.222500" name="pixel40"/>
+<location y="-0.220000" name="pixel41"/>
+<location y="-0.217500" name="pixel42"/>
+<location y="-0.215000" name="pixel43"/>
+<location y="-0.212500" name="pixel44"/>
+<location y="-0.210000" name="pixel45"/>
+<location y="-0.207500" name="pixel46"/>
+<location y="-0.205000" name="pixel47"/>
+<location y="-0.202500" name="pixel48"/>
+<location y="-0.200000" name="pixel49"/>
+<location y="-0.197500" name="pixel50"/>
+<location y="-0.195000" name="pixel51"/>
+<location y="-0.192500" name="pixel52"/>
+<location y="-0.190000" name="pixel53"/>
+<location y="-0.187500" name="pixel54"/>
+<location y="-0.185000" name="pixel55"/>
+<location y="-0.182500" name="pixel56"/>
+<location y="-0.180000" name="pixel57"/>
+<location y="-0.177500" name="pixel58"/>
+<location y="-0.175000" name="pixel59"/>
+<location y="-0.172500" name="pixel60"/>
+<location y="-0.170000" name="pixel61"/>
+<location y="-0.167500" name="pixel62"/>
+<location y="-0.165000" name="pixel63"/>
+<location y="-0.162500" name="pixel64"/>
+<location y="-0.160000" name="pixel65"/>
+<location y="-0.157500" name="pixel66"/>
+<location y="-0.155000" name="pixel67"/>
+<location y="-0.152500" name="pixel68"/>
+<location y="-0.150000" name="pixel69"/>
+<location y="-0.147500" name="pixel70"/>
+<location y="-0.145000" name="pixel71"/>
+<location y="-0.142500" name="pixel72"/>
+<location y="-0.140000" name="pixel73"/>
+<location y="-0.137500" name="pixel74"/>
+<location y="-0.135000" name="pixel75"/>
+<location y="-0.132500" name="pixel76"/>
+<location y="-0.130000" name="pixel77"/>
+<location y="-0.127500" name="pixel78"/>
+<location y="-0.125000" name="pixel79"/>
+<location y="-0.122500" name="pixel80"/>
+<location y="-0.120000" name="pixel81"/>
+<location y="-0.117500" name="pixel82"/>
+<location y="-0.115000" name="pixel83"/>
+<location y="-0.112500" name="pixel84"/>
+<location y="-0.110000" name="pixel85"/>
+<location y="-0.107500" name="pixel86"/>
+<location y="-0.105000" name="pixel87"/>
+<location y="-0.102500" name="pixel88"/>
+<location y="-0.100000" name="pixel89"/>
+<location y="-0.097500" name="pixel90"/>
+<location y="-0.095000" name="pixel91"/>
+<location y="-0.092500" name="pixel92"/>
+<location y="-0.090000" name="pixel93"/>
+<location y="-0.087500" name="pixel94"/>
+<location y="-0.085000" name="pixel95"/>
+<location y="-0.082500" name="pixel96"/>
+<location y="-0.080000" name="pixel97"/>
+<location y="-0.077500" name="pixel98"/>
+<location y="-0.075000" name="pixel99"/>
+<location y="-0.072500" name="pixel100"/>
+<location y="-0.070000" name="pixel101"/>
+<location y="-0.067500" name="pixel102"/>
+<location y="-0.065000" name="pixel103"/>
+<location y="-0.062500" name="pixel104"/>
+<location y="-0.060000" name="pixel105"/>
+<location y="-0.057500" name="pixel106"/>
+<location y="-0.055000" name="pixel107"/>
+<location y="-0.052500" name="pixel108"/>
+<location y="-0.050000" name="pixel109"/>
+<location y="-0.047500" name="pixel110"/>
+<location y="-0.045000" name="pixel111"/>
+<location y="-0.042500" name="pixel112"/>
+<location y="-0.040000" name="pixel113"/>
+<location y="-0.037500" name="pixel114"/>
+<location y="-0.035000" name="pixel115"/>
+<location y="-0.032500" name="pixel116"/>
+<location y="-0.030000" name="pixel117"/>
+<location y="-0.027500" name="pixel118"/>
+<location y="-0.025000" name="pixel119"/>
+<location y="-0.022500" name="pixel120"/>
+<location y="-0.020000" name="pixel121"/>
+<location y="-0.017500" name="pixel122"/>
+<location y="-0.015000" name="pixel123"/>
+<location y="-0.012500" name="pixel124"/>
+<location y="-0.010000" name="pixel125"/>
+<location y="-0.007500" name="pixel126"/>
+<location y="-0.005000" name="pixel127"/>
+<location y="-0.002500" name="pixel128"/>
+<location y="0.000000" name="pixel129"/>
+<location y="0.002500" name="pixel130"/>
+<location y="0.005000" name="pixel131"/>
+<location y="0.007500" name="pixel132"/>
+<location y="0.010000" name="pixel133"/>
+<location y="0.012500" name="pixel134"/>
+<location y="0.015000" name="pixel135"/>
+<location y="0.017500" name="pixel136"/>
+<location y="0.020000" name="pixel137"/>
+<location y="0.022500" name="pixel138"/>
+<location y="0.025000" name="pixel139"/>
+<location y="0.027500" name="pixel140"/>
+<location y="0.030000" name="pixel141"/>
+<location y="0.032500" name="pixel142"/>
+<location y="0.035000" name="pixel143"/>
+<location y="0.037500" name="pixel144"/>
+<location y="0.040000" name="pixel145"/>
+<location y="0.042500" name="pixel146"/>
+<location y="0.045000" name="pixel147"/>
+<location y="0.047500" name="pixel148"/>
+<location y="0.050000" name="pixel149"/>
+<location y="0.052500" name="pixel150"/>
+<location y="0.055000" name="pixel151"/>
+<location y="0.057500" name="pixel152"/>
+<location y="0.060000" name="pixel153"/>
+<location y="0.062500" name="pixel154"/>
+<location y="0.065000" name="pixel155"/>
+<location y="0.067500" name="pixel156"/>
+<location y="0.070000" name="pixel157"/>
+<location y="0.072500" name="pixel158"/>
+<location y="0.075000" name="pixel159"/>
+<location y="0.077500" name="pixel160"/>
+<location y="0.080000" name="pixel161"/>
+<location y="0.082500" name="pixel162"/>
+<location y="0.085000" name="pixel163"/>
+<location y="0.087500" name="pixel164"/>
+<location y="0.090000" name="pixel165"/>
+<location y="0.092500" name="pixel166"/>
+<location y="0.095000" name="pixel167"/>
+<location y="0.097500" name="pixel168"/>
+<location y="0.100000" name="pixel169"/>
+<location y="0.102500" name="pixel170"/>
+<location y="0.105000" name="pixel171"/>
+<location y="0.107500" name="pixel172"/>
+<location y="0.110000" name="pixel173"/>
+<location y="0.112500" name="pixel174"/>
+<location y="0.115000" name="pixel175"/>
+<location y="0.117500" name="pixel176"/>
+<location y="0.120000" name="pixel177"/>
+<location y="0.122500" name="pixel178"/>
+<location y="0.125000" name="pixel179"/>
+<location y="0.127500" name="pixel180"/>
+<location y="0.130000" name="pixel181"/>
+<location y="0.132500" name="pixel182"/>
+<location y="0.135000" name="pixel183"/>
+<location y="0.137500" name="pixel184"/>
+<location y="0.140000" name="pixel185"/>
+<location y="0.142500" name="pixel186"/>
+<location y="0.145000" name="pixel187"/>
+<location y="0.147500" name="pixel188"/>
+<location y="0.150000" name="pixel189"/>
+<location y="0.152500" name="pixel190"/>
+<location y="0.155000" name="pixel191"/>
+<location y="0.157500" name="pixel192"/>
+<location y="0.160000" name="pixel193"/>
+<location y="0.162500" name="pixel194"/>
+<location y="0.165000" name="pixel195"/>
+<location y="0.167500" name="pixel196"/>
+<location y="0.170000" name="pixel197"/>
+<location y="0.172500" name="pixel198"/>
+<location y="0.175000" name="pixel199"/>
+<location y="0.177500" name="pixel200"/>
+<location y="0.180000" name="pixel201"/>
+<location y="0.182500" name="pixel202"/>
+<location y="0.185000" name="pixel203"/>
+<location y="0.187500" name="pixel204"/>
+<location y="0.190000" name="pixel205"/>
+<location y="0.192500" name="pixel206"/>
+<location y="0.195000" name="pixel207"/>
+<location y="0.197500" name="pixel208"/>
+<location y="0.200000" name="pixel209"/>
+<location y="0.202500" name="pixel210"/>
+<location y="0.205000" name="pixel211"/>
+<location y="0.207500" name="pixel212"/>
+<location y="0.210000" name="pixel213"/>
+<location y="0.212500" name="pixel214"/>
+<location y="0.215000" name="pixel215"/>
+<location y="0.217500" name="pixel216"/>
+<location y="0.220000" name="pixel217"/>
+<location y="0.222500" name="pixel218"/>
+<location y="0.225000" name="pixel219"/>
+<location y="0.227500" name="pixel220"/>
+<location y="0.230000" name="pixel221"/>
+<location y="0.232500" name="pixel222"/>
+<location y="0.235000" name="pixel223"/>
+<location y="0.237500" name="pixel224"/>
+<location y="0.240000" name="pixel225"/>
+<location y="0.242500" name="pixel226"/>
+<location y="0.245000" name="pixel227"/>
+<location y="0.247500" name="pixel228"/>
+<location y="0.250000" name="pixel229"/>
+<location y="0.252500" name="pixel230"/>
+<location y="0.255000" name="pixel231"/>
+<location y="0.257500" name="pixel232"/>
+<location y="0.260000" name="pixel233"/>
+<location y="0.262500" name="pixel234"/>
+<location y="0.265000" name="pixel235"/>
+<location y="0.267500" name="pixel236"/>
+<location y="0.270000" name="pixel237"/>
+<location y="0.272500" name="pixel238"/>
+<location y="0.275000" name="pixel239"/>
+<location y="0.277500" name="pixel240"/>
+<location y="0.280000" name="pixel241"/>
+<location y="0.282500" name="pixel242"/>
+<location y="0.285000" name="pixel243"/>
+<location y="0.287500" name="pixel244"/>
+<location y="0.290000" name="pixel245"/>
+<location y="0.292500" name="pixel246"/>
+<location y="0.295000" name="pixel247"/>
+<location y="0.297500" name="pixel248"/>
+<location y="0.300000" name="pixel249"/>
+<location y="0.302500" name="pixel250"/>
+<location y="0.305000" name="pixel251"/>
+<location y="0.307500" name="pixel252"/>
+<location y="0.310000" name="pixel253"/>
+<location y="0.312500" name="pixel254"/>
+<location y="0.315000" name="pixel255"/>
+<location y="0.317500" name="pixel256"/>
+ </component>
+ </type>
+ 
+   <idlist idname="bank01">
+     <id start="0" end="10239" />
+   </idlist>
+   
+   <idlist idname="bank02">
+     <id start="10240" end="20479" />
+   </idlist>
+   
+   <idlist idname="bank03">
+     <id start="20480" end="30719" />
+   </idlist>
+   
+   <idlist idname="bank04">
+     <id start="30720" end="40959" />
+   </idlist>
+   
+   <idlist idname="bank05">
+     <id start="40960" end="51199" />
+   </idlist>
+   
+   <idlist idname="bank06">
+     <id start="51200" end="61439" />
+   </idlist>
+   
+  
+</instrument>
+  
\ No newline at end of file
diff --git a/instrument/Facilities.xml b/instrument/Facilities.xml
index 320fe4089c44e25783ca9b5cb6ece153a632f096..e83d54feffb20fac7ab30c92b6d0ade40679e106 100644
--- a/instrument/Facilities.xml
+++ b/instrument/Facilities.xml
@@ -640,6 +640,13 @@
   </instrument>
 </facility>
 
+<!-- ANSTO -->
+<facility name="ANSTO" FileExtensions=".nxs,.tar">
+  <instrument name="Bilby">
+    <technique>Small Angle Scattering</technique>
+  </instrument>
+</facility>
+
 <!--  Test Facility to allow example usage of Live listeners against "Fake" instrument sources -->
 <facility name="TEST_LIVE" FileExtensions=".nxs,.raw">
   <instrument name="ISIS_Histogram">