diff --git a/Code/Mantid/Framework/DataHandling/CMakeLists.txt b/Code/Mantid/Framework/DataHandling/CMakeLists.txt index 88bfc8d118be8be54cbfdd8084c941073a0ea4ba..012b4a90a4a91dc3924e5bd55402e33b9fb78c11 100644 --- a/Code/Mantid/Framework/DataHandling/CMakeLists.txt +++ b/Code/Mantid/Framework/DataHandling/CMakeLists.txt @@ -50,6 +50,7 @@ set ( SRC_FILES src/LoadInstrumentFromNexus.cpp src/LoadInstrumentFromRaw.cpp src/LoadIsawDetCal.cpp + src/LoadLLB.cpp src/LoadLOQDistancesFromRaw.cpp src/LoadLiveData.cpp src/LoadLog.cpp @@ -194,6 +195,7 @@ set ( INC_FILES inc/MantidDataHandling/LoadInstrumentFromNexus.h inc/MantidDataHandling/LoadInstrumentFromRaw.h inc/MantidDataHandling/LoadIsawDetCal.h + inc/MantidDataHandling/LoadLLB.h inc/MantidDataHandling/LoadLOQDistancesFromRaw.h inc/MantidDataHandling/LoadLiveData.h inc/MantidDataHandling/LoadLog.h @@ -287,7 +289,6 @@ set ( INC_FILES ) set ( TEST_FILES - LoadDAETest.h #LoadSNSNexusTest.h # TODO has no active tests in it #Needs fixing to not rely on network. SNSLiveEventDataListenerTest.h ADARAPacketTest.h @@ -315,6 +316,7 @@ set ( TEST_FILES LoadAsciiTest.h LoadCalFileTest.h LoadCanSAS1dTest.h + LoadDAETest.h LoadDaveGrpTest.h LoadDetectorInfoTest.h LoadDetectorsGroupingFileTest.h @@ -330,12 +332,13 @@ set ( TEST_FILES LoadInstrumentFromRawTest.h LoadInstrumentTest.h LoadIsawDetCalTest.h + LoadLLBTest.h LoadLiveDataTest.h LoadLogTest.h LoadLogsFromSNSNexusTest.h LoadMappingTableTest.h LoadMaskTest.h - LoadMcStasNexusTest.h + LoadMcStasNexusTest.h LoadMuonLogTest.h LoadMuonNexus1Test.h LoadMuonNexus2Test.h @@ -343,7 +346,7 @@ set ( TEST_FILES LoadNexusLogsTest.h LoadNexusMonitorsTest.h LoadNexusProcessedTest.h - LoadNexusTest.h + LoadNexusTest.h LoadPDFgetNFileTest.h LoadParameterFileTest.h LoadPreNexusMonitorsTest.h @@ -400,7 +403,7 @@ set ( TEST_FILES SaveRKHTest.h SaveSPETest.h SaveToSNSHistogramNexusTest.h - SetSampleMaterialTest.h + SetSampleMaterialTest.h SetScalingPSDTest.h StartLiveDataTest.h UpdateInstrumentFromFileTest.h diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadLLB.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadLLB.h new file mode 100644 index 0000000000000000000000000000000000000000..55bcce21d54c95072b6d1ba5d8f3faccb63e2dd1 --- /dev/null +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadLLB.h @@ -0,0 +1,82 @@ +#ifndef MANTID_DATAHANDLING_LOADLLB_H_ +#define MANTID_DATAHANDLING_LOADLLB_H_ + +#include "MantidKernel/System.h" +#include "MantidAPI/Algorithm.h" +#include "MantidAPI/IDataFileChecker.h" +#include "MantidNexus/NexusClasses.h" + +namespace Mantid +{ +namespace DataHandling +{ + + /** LoadLLB : TODO: DESCRIPTION + + Copyright © 2013 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 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 + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + File change history is stored at: <https://github.com/mantidproject/mantid> + Code Documentation is available at: <http://doxygen.mantidproject.org> + */ +class DLLExport LoadLLB: public API::IDataFileChecker { +public: + LoadLLB(); + virtual ~LoadLLB(); + + virtual const std::string name() const; + virtual int version() const; + virtual const std::string category() const; + ///checks the file can be loaded by reading 1st 100 bytes and looking at the file extension. + bool quickFileCheck(const std::string& filePath, size_t nread, + const file_header& header); + /// check the structure of the file and if this file can be loaded return a value between 1 and 100 + int fileCheck(const std::string& filePath); + +private: + virtual void initDocs(); + void init(); + void exec(); + void setInstrumentName(NeXus::NXEntry& entry); + std::string getInstrumentName(NeXus::NXEntry& entry); + void initWorkSpace(NeXus::NXEntry&); + void loadDataIntoTheWorkSpace(NeXus::NXEntry&); + /// Calculate error for y + static double calculateError(double in) { + return sqrt(in); + } + void loadExperimentDetails(NeXus::NXEntry&); + void loadRunDetails(NeXus::NXEntry &); + double calculateEnergy(double); + void runLoadInstrument(); + + std::vector<std::string> supportedInstruments; + std::string m_nexusInstrumentEntryName; + std::string m_instrumentName; + API::MatrixWorkspace_sptr m_localWorkspace; + size_t m_numberOfTubes; // number of tubes - X + size_t m_numberOfPixelsPerTube; //number of pixels per tube - Y + size_t m_numberOfChannels; // time channels - Z + size_t m_numberOfHistograms; + +}; + + +} // namespace DataHandling +} // namespace Mantid + +#endif /* MANTID_DATAHANDLING_LOADLLB_H_ */ diff --git a/Code/Mantid/Framework/DataHandling/src/LoadLLB.cpp b/Code/Mantid/Framework/DataHandling/src/LoadLLB.cpp new file mode 100644 index 0000000000000000000000000000000000000000..05452e517cc64bd3e68b7caf1491df743221f4f0 --- /dev/null +++ b/Code/Mantid/Framework/DataHandling/src/LoadLLB.cpp @@ -0,0 +1,350 @@ +/*WIKI* + TODO: Enter a full wiki-markup description of your algorithm here. You can then use the Build/wiki_maker.py script to generate your full wiki page. + *WIKI*/ + +#include "MantidDataHandling/LoadLLB.h" +#include "MantidAPI/FileProperty.h" +#include "MantidKernel/UnitFactory.h" +#include "MantidAPI/LoadAlgorithmFactory.h" +#include "MantidAPI/Progress.h" +#include "MantidGeometry/Instrument.h" + +#include <limits> +#include <algorithm> +#include <iostream> +#include <vector> +#include <cmath> + +namespace Mantid { +namespace DataHandling { + +using namespace Kernel; +using namespace API; +using namespace NeXus; + +// Register the algorithm into the AlgorithmFactory +DECLARE_ALGORITHM(LoadLLB) +//register the algorithm into loadalgorithm factory +DECLARE_LOADALGORITHM(LoadLLB) + +//---------------------------------------------------------------------------------------------- +/** Constructor + */ +LoadLLB::LoadLLB() { + m_instrumentName = ""; + supportedInstruments.push_back("MIBEMOL"); +} + +//---------------------------------------------------------------------------------------------- +/** Destructor + */ +LoadLLB::~LoadLLB() { +} + +//---------------------------------------------------------------------------------------------- +/// Algorithm's name for identification. @see Algorithm::name +const std::string LoadLLB::name() const { + return "LoadLLB"; +} +; + +/// Algorithm's version for identification. @see Algorithm::version +int LoadLLB::version() const { + return 1; +} +; + +/// Algorithm's category for identification. @see Algorithm::category +const std::string LoadLLB::category() const { + return "DataHandling"; +} + +//---------------------------------------------------------------------------------------------- +/// Sets documentation strings for this algorithm +void LoadLLB::initDocs() { + this->setWikiSummary("Loads LLB nexus file."); + this->setOptionalMessage("Loads LLB nexus file."); +} + + +bool LoadLLB::quickFileCheck(const std::string& filePath, size_t nread, + const file_header& header) { + std::string extn = extension(filePath); + bool bnexs(false); + (!extn.compare("nxs") || !extn.compare("nx5")) ? bnexs = true : bnexs = + false; + /* + * HDF files have magic cookie in the first 4 bytes + */ + if (((nread >= sizeof(unsigned)) + && (ntohl(header.four_bytes) == g_hdf_cookie)) || bnexs) { + //hdf + return true; + } else if ((nread >= sizeof(g_hdf5_signature)) + && (!memcmp(header.full_hdr, g_hdf5_signature, + sizeof(g_hdf5_signature)))) { + //hdf5 + return true; + } + return false; +} + +/** + * Checks the file by opening it and reading few lines + * @param filePath :: name of the file inluding its path + * @return an integer value how much this algorithm can load the file + */ +int LoadLLB::fileCheck(const std::string& filePath) { + // Create the root Nexus class + NXRoot root(filePath); + NXEntry entry = root.openFirstEntry(); + std::string instrumentName = getInstrumentName(entry); + if (std::find(supportedInstruments.begin(), supportedInstruments.end(), + instrumentName) != supportedInstruments.end()) { + // FOUND + return 80; + } + return 0; +} + +//---------------------------------------------------------------------------------------------- +/** Initialize the algorithm's properties. + */ +void LoadLLB::init() { + std::vector<std::string> exts; + exts.push_back(".nxs"); + exts.push_back(".hdf"); + declareProperty(new FileProperty("Filename", "", FileProperty::Load, exts), + "The name of the Nexus file to load"); + declareProperty( + new WorkspaceProperty<>("OutputWorkspace", "", Direction::Output), + "The name to use for the output workspace"); +} + +//---------------------------------------------------------------------------------------------- +/** Execute the algorithm. + */ +void LoadLLB::exec() { + + std::string filename = getPropertyValue("Filename"); + NXRoot root(filename); + NXEntry entry = root.openFirstEntry(); + setInstrumentName(entry); + + initWorkSpace(entry); + + loadDataIntoTheWorkSpace(entry); + + loadRunDetails(entry); + loadExperimentDetails(entry); + + runLoadInstrument(); + + setProperty("OutputWorkspace", m_localWorkspace); +} + +void LoadLLB::setInstrumentName(NeXus::NXEntry& entry) { + + m_instrumentName = getInstrumentName(entry); + if (m_instrumentName == "") { + std::string message( + "Cannot read the instrument name from the Nexus file!"); + g_log.error(message); + throw std::runtime_error(message); + } + +} + +std::string LoadLLB::getInstrumentName(NeXus::NXEntry& entry) { + + // format: /entry0/?????/name + + std::string instrumentName = ""; + + std::vector<NXClassInfo> v = entry.groups(); + for (auto it = v.begin(); it < v.end(); it++) { + if (it->nxclass == "NXinstrument" || it->nxname == "nxinstrument") { + m_nexusInstrumentEntryName = it->nxname; + std::string insNamePath = m_nexusInstrumentEntryName + "/name"; + instrumentName = entry.getString(insNamePath); + g_log.debug() << "Instrument Name: " << instrumentName + << " in NxPath: " << insNamePath << std::endl; + break; + } + } + //std::replace( instrumentName.begin(), instrumentName.end(), ' ', '_'); // replace all ' ' to '_' + long unsigned int pos = instrumentName.find(" "); + instrumentName = instrumentName.substr (0,pos); + return instrumentName; + +} + +void LoadLLB::initWorkSpace(NeXus::NXEntry& entry) { + + // read in the data + NXData dataGroup = entry.openNXData("nxdata"); + NXInt data = dataGroup.openIntData(); + + m_numberOfTubes = static_cast<size_t>(data.dim0()); + m_numberOfPixelsPerTube = 1; + m_numberOfChannels = static_cast<size_t>(data.dim1()); + + // dim0 * m_numberOfPixelsPerTube is the total number of detectors + m_numberOfHistograms = m_numberOfTubes * m_numberOfPixelsPerTube; + + g_log.debug() << "NumberOfTubes: " << m_numberOfTubes << std::endl; + g_log.debug() << "NumberOfPixelsPerTube: " << m_numberOfPixelsPerTube + << std::endl; + g_log.debug() << "NumberOfChannels: " << m_numberOfChannels << std::endl; + + // Now create the output workspace + // Might need to get this value from the number of monitors in the Nexus file + // params: + // workspace type, + // total number of spectra + (number of monitors = 0), + // bin boundaries = m_numberOfChannels + 1 + // Z/time dimension + m_localWorkspace = WorkspaceFactory::Instance().create("Workspace2D", + m_numberOfHistograms, m_numberOfChannels + 1, m_numberOfChannels); + m_localWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create( + "TOF"); + m_localWorkspace->setYUnitLabel("Counts"); + +} + +void LoadLLB::loadDataIntoTheWorkSpace(NeXus::NXEntry& entry) { + + // read in the data + NXData dataGroup = entry.openNXData("nxdata"); + NXInt data = dataGroup.openIntData(); + data.load(); + + NXFloat timeBinning = entry.openNXFloat("nxdata/x_axis"); + timeBinning.load(); + + + size_t numberOfBins = static_cast<size_t>(timeBinning.dim1()) + 1; // boundaries + g_log.debug() << "Number of bins: " << numberOfBins << std::endl; + + // Assign time bin to first X entry + float* timeBinning_p = &timeBinning[0]; + std::vector<double> timeBinningTmp(numberOfBins); + timeBinningTmp.assign(timeBinning_p,timeBinning_p + numberOfBins); + timeBinningTmp[numberOfBins-1] = timeBinningTmp[numberOfBins-2]+timeBinningTmp[1]-timeBinningTmp[0]; + m_localWorkspace->dataX(0).assign(timeBinningTmp.begin(),timeBinningTmp.end()); + + Progress progress(this, 0, 1, m_numberOfTubes * m_numberOfPixelsPerTube); + size_t spec = 0; + for (size_t i = 0; i < m_numberOfTubes; ++i) { + for (size_t j = 0; j < m_numberOfPixelsPerTube; ++j) { + if (spec > 0) { + // just copy the time binning axis to every spectra + m_localWorkspace->dataX(spec) = m_localWorkspace->readX(0); + } + // Assign Y + int* data_p = &data(static_cast<int>(i), static_cast<int>(j)); + m_localWorkspace->dataY(spec).assign(data_p, + data_p + m_numberOfChannels); + + // Assign Error + MantidVec& E = m_localWorkspace->dataE(spec); + std::transform(data_p, data_p + m_numberOfChannels, E.begin(), + LoadLLB::calculateError); + + ++spec; + progress.report(); + } + } + + g_log.debug() << "Data loading inti WS done...." << std::endl; +} + +void LoadLLB::loadRunDetails(NXEntry & entry) { + + API::Run & runDetails = m_localWorkspace->mutableRun(); + +// int runNum = entry.getInt("run_number"); +// std::string run_num = boost::lexical_cast<std::string>(runNum); +// runDetails.addProperty("run_number", run_num); + + std::string start_time = entry.getString("start_time"); + //start_time = getDateTimeInIsoFormat(start_time); + runDetails.addProperty("run_start", start_time); + + std::string end_time = entry.getString("end_time"); + //end_time = getDateTimeInIsoFormat(end_time); + runDetails.addProperty("run_end", end_time); + + double wavelength = entry.getFloat("nxbeam/incident_wavelength"); + runDetails.addProperty<double>("wavelength", wavelength); + + double energy = calculateEnergy(wavelength); + runDetails.addProperty<double>("Ei", energy,true); //overwrite + + std::string title = entry.getString("title"); + runDetails.addProperty("title", title); + m_localWorkspace->setTitle(title); + +} + +/** + * Calculate Neutron Energy from wavelength: \f$ E = h^2 / 2m\lambda ^2 \f$ + * @param wavelength :: wavelength in \f$ \AA \f$ + * @return tof in seconds + */ +double LoadLLB::calculateEnergy(double wavelength) { + double e = (PhysicalConstants::h * PhysicalConstants::h) / + (2 * PhysicalConstants::NeutronMass * wavelength*wavelength * 1e-20)/ + PhysicalConstants::meV; + return e; +} + +/* + * Load data about the Experiment. + * + * TODO: This is very incomplete. In ISIS they much more info in the nexus file than ILL. + * + * @param entry :: The Nexus entry + */ +void LoadLLB::loadExperimentDetails(NXEntry & entry) { + + // TODO: Do the rest + // Pick out the geometry information + + (void)entry; + +// std::string description = boost::lexical_cast<std::string>( +// entry.getFloat("sample/description")); +// +// m_localWorkspace->mutableSample().setName(description); + +// m_localWorkspace->mutableSample().setThickness(static_cast<double> (isis_raw->spb.e_thick)); +// m_localWorkspace->mutableSample().setHeight(static_cast<double> (isis_raw->spb.e_height)); +// m_localWorkspace->mutableSample().setWidth(static_cast<double> (isis_raw->spb.e_width)); + +} + + +/** + * Run the Child Algorithm LoadInstrument. + */ +void LoadLLB::runLoadInstrument() { + + IAlgorithm_sptr loadInst = createChildAlgorithm("LoadInstrument"); + + // Now execute the Child Algorithm. Catch and log any error, but don't stop. + try { + + // TODO: depending on the m_numberOfPixelsPerTube we might need to load a different IDF + + loadInst->setPropertyValue("InstrumentName", m_instrumentName); + loadInst->setProperty<MatrixWorkspace_sptr>("Workspace", + m_localWorkspace); + loadInst->execute(); + } catch (...) { + g_log.information("Cannot load the instrument definition."); + } +} + +} // namespace DataHandling +} // namespace Mantid diff --git a/Code/Mantid/Framework/DataHandling/test/LoadLLBTest.h b/Code/Mantid/Framework/DataHandling/test/LoadLLBTest.h new file mode 100644 index 0000000000000000000000000000000000000000..3877c72bcc4c20dc2856004ad4df1cc9628e4e4f --- /dev/null +++ b/Code/Mantid/Framework/DataHandling/test/LoadLLBTest.h @@ -0,0 +1,69 @@ +#ifndef MANTID_DATAHANDLING_LOADLLBTEST_H_ +#define MANTID_DATAHANDLING_LOADLLBTEST_H_ + +#include <cxxtest/TestSuite.h> + +#include "MantidDataHandling/LoadLLB.h" + +using namespace Mantid::API; +using Mantid::DataHandling::LoadLLB; + +class LoadLLBTest: public CxxTest::TestSuite { +public: + // This pair of boilerplate methods prevent the suite being created statically + // This means the constructor isn't called when running other tests + static LoadLLBTest *createSuite() { + return new LoadLLBTest(); + } + static void destroySuite(LoadLLBTest *suite) { + delete suite; + } + + LoadLLBTest() : + m_testFile("LLB_d22418.nxs") { + } + void testName() { + LoadLLB alg; + TS_ASSERT_EQUALS(alg.name(), "LoadLLB"); + } + + void testVersion() { + LoadLLB alg; + TS_ASSERT_EQUALS(alg.version(), 1); + } + + void test_Init() { + LoadLLB alg; + TS_ASSERT_THROWS_NOTHING(alg.initialize()) + TS_ASSERT(alg.isInitialized()) + } + + void test_exec() { + LoadLLB loader; + loader.initialize(); + loader.setPropertyValue("Filename", m_testFile); + + std::string outputSpace = "LoadLLBTest_out"; + loader.setPropertyValue("OutputWorkspace", outputSpace); + TS_ASSERT_THROWS_NOTHING(loader.execute()); + + // test workspace, copied from LoadMuonNexusTest.h + MatrixWorkspace_sptr output; + + (output = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>( + outputSpace)); + MatrixWorkspace_sptr output2D = boost::dynamic_pointer_cast< + MatrixWorkspace>(output); + + TS_ASSERT_EQUALS(output2D->getNumberHistograms(), 84); + + AnalysisDataService::Instance().clear(); + } + + +private: + std::string m_testFile; + +}; + +#endif /* MANTID_DATAHANDLING_LOADLLBTEST_H_ */ diff --git a/Code/Mantid/instrument/Facilities.xml b/Code/Mantid/instrument/Facilities.xml index 2b8dd916f59a23a852b3cac51f20a5db4bbff5ba..97ba6100e2ddfcfb6301cda7edd69d835357eb9a 100644 --- a/Code/Mantid/instrument/Facilities.xml +++ b/Code/Mantid/instrument/Facilities.xml @@ -474,6 +474,15 @@ </facility> +<!-- Reactor Orphee (France) --> +<facility name="LLB" FileExtensions=".nxs,.hdf"> + <instrument name="MIBEMOL"> + <technique>Neutron Spectroscopy</technique> + <technique>Reactor Direct Geometry Spectroscopy</technique> + </instrument> +</facility> + + <facility name="TEST" FileExtensions=".nxs,.dat,.xml"> <livedata listener="MockILiveListener"/> diff --git a/Code/Mantid/instrument/MIBEMOL_Definition.xml b/Code/Mantid/instrument/MIBEMOL_Definition.xml new file mode 100644 index 0000000000000000000000000000000000000000..e559b5a88bfc57e0a9a20ad3c730a30abc76439e --- /dev/null +++ b/Code/Mantid/instrument/MIBEMOL_Definition.xml @@ -0,0 +1,136 @@ +<?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 name="MIBEMOL" valid-from="1900-01-31 23:59:59" valid-to="2100-01-31 23:59:59" last-modified="2013-05-27 12:29:36"> + <!-- Author: ricardo.leal@ill.fr --> + <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> + </defaults> + <component type="moderator"> + <location z="-0.490000" /> + </component> + <type name="moderator" is="Source"></type> + <!-- Sample position --> + <component type="sample-position"> + <location y="0.0" x="0.0" z="0.0" /> + </component> + <type name="sample-position" is="SamplePos" /> + <idlist idname="detectors"> + <id start="1" end="84" /> + </idlist> + <!-- Detector list def --> + <component type="detectors" idlist="detectors"> + <location /> + </component> + <!-- Detector Banks --> + <type name="detectors"> + <component type="bank"> + <location /> + </component> + </type> + <!-- Definition of every bank --> + <type name="bank"> + <component type="pack"> + <location r="3.580000" t="147.157000" p="0.000000" name="det1"></location> + <location r="3.580000" t="143.666000" p="0.000000" name="det2"></location> + <location r="3.580000" t="141.509000" p="0.000000" name="det3"></location> + <location r="3.580000" t="141.484000" p="0.000000" name="det4"></location> + <location r="3.580000" t="139.462000" p="0.000000" name="det5"></location> + <location r="3.580000" t="138.475000" p="0.000000" name="det6"></location> + <location r="3.580000" t="136.565000" p="0.000000" name="det7"></location> + <location r="3.580000" t="135.639000" p="0.000000" name="det8"></location> + <location r="3.580000" t="134.732000" p="0.000000" name="det9"></location> + <location r="3.580000" t="132.967000" p="0.000000" name="det10"></location> + <location r="3.580000" t="132.107000" p="0.000000" name="det11"></location> + <location r="3.580000" t="131.262000" p="0.000000" name="det12"></location> + <location r="3.580000" t="128.009000" p="0.000000" name="det13"></location> + <location r="3.580000" t="126.453000" p="0.000000" name="det14"></location> + <location r="3.580000" t="125.690000" p="0.000000" name="det15"></location> + <location r="3.580000" t="124.193000" p="0.000000" name="det16"></location> + <location r="3.580000" t="122.732000" p="0.000000" name="det17"></location> + <location r="3.580000" t="121.304000" p="0.000000" name="det18"></location> + <location r="3.580000" t="120.602000" p="0.000000" name="det19"></location> + <location r="3.580000" t="119.220000" p="0.000000" name="det20"></location> + <location r="3.580000" t="117.866000" p="0.000000" name="det21"></location> + <location r="3.580000" t="116.538000" p="0.000000" name="det22"></location> + <location r="3.580000" t="115.235000" p="0.000000" name="det23"></location> + <location r="3.580000" t="112.695000" p="0.000000" name="det24"></location> + <location r="3.580000" t="110.845000" p="0.000000" name="det25"></location> + <location r="3.580000" t="110.237000" p="0.000000" name="det26"></location> + <location r="3.580000" t="108.443000" p="0.000000" name="det27"></location> + <location r="3.580000" t="107.853000" p="0.000000" name="det28"></location> + <location r="3.580000" t="106.109000" p="0.000000" name="det29"></location> + <location r="3.580000" t="104.965000" p="0.000000" name="det30"></location> + <location r="3.580000" t="103.836000" p="0.000000" name="det31"></location> + <location r="3.580000" t="102.721000" p="0.000000" name="det32"></location> + <location r="3.580000" t="101.620000" p="0.000000" name="det33"></location> + <location r="3.580000" t="99.991000" p="0.000000" name="det34"></location> + <location r="3.580000" t="98.921000" p="0.000000" name="det35"></location> + <location r="3.580000" t="96.814000" p="0.000000" name="det36"></location> + <location r="3.580000" t="95.263000" p="0.000000" name="det37"></location> + <location r="3.580000" t="94.241000" p="0.000000" name="det38"></location> + <location r="3.580000" t="92.727000" p="0.000000" name="det39"></location> + <location r="3.580000" t="91.729000" p="0.000000" name="det40"></location> + <location r="3.580000" t="90.248000" p="0.000000" name="det41"></location> + <location r="3.580000" t="89.272000" p="0.000000" name="det42"></location> + <location r="3.580000" t="87.822000" p="0.000000" name="det43"></location> + <location r="3.580000" t="86.390000" p="0.000000" name="det44"></location> + <location r="3.580000" t="85.445000" p="0.000000" name="det45"></location> + <location r="3.580000" t="84.040000" p="0.000000" name="det46"></location> + <location r="3.580000" t="79.915000" p="0.000000" name="det47"></location> + <location r="3.580000" t="79.015000" p="0.000000" name="det48"></location> + <location r="3.580000" t="77.677000" p="0.000000" name="det49"></location> + <location r="3.580000" t="76.350000" p="0.000000" name="det50"></location> + <location r="3.580000" t="75.473000" p="0.000000" name="det51"></location> + <location r="3.580000" t="73.884000" p="0.000000" name="det52"></location> + <location r="3.580000" t="72.442000" p="0.000000" name="det53"></location> + <location r="3.580000" t="71.586000" p="0.000000" name="det54"></location> + <location r="3.580000" t="69.889000" p="0.000000" name="det55"></location> + <location r="3.580000" t="69.047000" p="0.000000" name="det56"></location> + <location r="3.580000" t="67.792000" p="0.000000" name="det57"></location> + <location r="3.580000" t="64.899000" p="0.000000" name="det58"></location> + <location r="3.580000" t="63.674000" p="0.000000" name="det59"></location> + <location r="3.580000" t="62.456000" p="0.000000" name="det60"></location> + <location r="3.580000" t="61.246000" p="0.000000" name="det61"></location> + <location r="3.580000" t="60.044000" p="0.000000" name="det62"></location> + <location r="3.580000" t="58.452000" p="0.000000" name="det63"></location> + <location r="3.580000" t="57.266000" p="0.000000" name="det64"></location> + <location r="3.580000" t="56.087000" p="0.000000" name="det65"></location> + <location r="3.580000" t="54.525000" p="0.000000" name="det66"></location> + <location r="3.580000" t="53.360000" p="0.000000" name="det67"></location> + <location r="3.580000" t="52.202000" p="0.000000" name="det68"></location> + <location r="3.580000" t="48.759000" p="0.000000" name="det69"></location> + <location r="3.580000" t="47.623000" p="0.000000" name="det70"></location> + <location r="3.580000" t="46.114000" p="0.000000" name="det71"></location> + <location r="3.580000" t="44.989000" p="0.000000" name="det72"></location> + <location r="3.580000" t="43.868000" p="0.000000" name="det73"></location> + <location r="3.580000" t="42.380000" p="0.000000" name="det74"></location> + <location r="3.580000" t="41.269000" p="0.000000" name="det75"></location> + <location r="3.580000" t="40.162000" p="0.000000" name="det76"></location> + <location r="3.580000" t="38.692000" p="0.000000" name="det77"></location> + <location r="3.580000" t="37.594000" p="0.000000" name="det78"></location> + <location r="3.580000" t="36.499000" p="0.000000" name="det79"></location> + <location r="3.580000" t="27.500000" p="0.000000" name="det80"></location> + <location r="3.580000" t="26.100000" p="0.000000" name="det81"></location> + <location r="3.580000" t="24.800000" p="0.000000" name="det82"></location> + <location r="3.580000" t="23.500000" p="0.000000" name="det83"></location> + <location r="3.580000" t="0.000000" p="0.000000" name="det84"></location> + </component> + </type> + <type name="pack" is="detector"> + <cuboid id="pack-pixel-shape"> + <left-front-bottom-point z="-0.005" y="-0.2" x="-0.01" /> + <left-front-top-point z="-0.005" y="0.2" x="-0.01" /> + <left-back-bottom-point z="-0.005" y="-0.2" x="0.01" /> + <right-front-bottom-point z="0.005" y="-0.2" x="-0.01" /> + </cuboid> + <algebra val="pack-pixel-shape" /> + </type> +</instrument> diff --git a/Test/AutoTestData/LLB_d22418.nxs b/Test/AutoTestData/LLB_d22418.nxs new file mode 100644 index 0000000000000000000000000000000000000000..b1567003f57a2012aacd60956c98b30c9e4c6a78 Binary files /dev/null and b/Test/AutoTestData/LLB_d22418.nxs differ