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">