Mantid
Loading...
Searching...
No Matches
LoadQKK.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
8
9#include "MantidAPI/Axis.h"
18#include "MantidIndexing/IndexInfo.h"
21
22#include <fstream>
23
24using namespace Mantid::DataHandling;
25using namespace Mantid::API;
26using namespace Mantid::Kernel;
27
28namespace Mantid::DataHandling {
29
30// Register the algorithm into the AlgorithmFactory
32
33
39int LoadQKK::confidence(Nexus::NexusDescriptor &descriptor) const {
40 const auto &firstEntryName = descriptor.firstEntryNameType().first;
41 if (descriptor.isEntry("/" + firstEntryName + "/data/hmm_xy"))
42 return 80;
43 else
44 return 0;
45}
46
53 // Declare the Filename algorithm property. Mandatory. Sets the path to the
54 // file to load.
55 declareProperty(std::make_unique<API::FileProperty>("Filename", "", API::FileProperty::Load, ".nx.hdf"),
56 "The input filename of the stored data");
57 // Declare the OutputWorkspace property. This sets the name of the workspace
58 // to be filled with the data
59 // from the file.
60 declareProperty(std::make_unique<API::WorkspaceProperty<>>("OutputWorkspace", "", Kernel::Direction::Output));
61}
62
67 using namespace Mantid::API;
68 // Get the name of the file.
69 std::string filename = getPropertyValue("Filename");
70
71 // Open the root.
72 Nexus::NXRoot root(filename);
73 // Open the first NXentry found in the file.
74 Nexus::NXEntry entry = root.openFirstEntry();
75 // Open NXdata group with name "data"
76 Nexus::NXData data = entry.openNXData("data");
77 // Read in wavelength value
78 double wavelength = static_cast<double>(data.getFloat("wavelength"));
79 // open the data set with the counts. It is identified by the signal=1
80 // attribute
81 Nexus::NXInt hmm = data.openIntData();
82 // Read the data into memory
83 hmm.load();
84
85 // Get the wavelength spread
86 double wavelength_spread = static_cast<double>(entry.getFloat("instrument/velocity_selector/wavelength_spread"));
87 double wavelength0 = wavelength - wavelength_spread / 2;
88 double wavelength1 = wavelength + wavelength_spread / 2;
89
90 // hmm is a 3d array with axes: sample_x, y_pixel_offset, x_pixel_offset
91 size_t ny = hmm.dim1(); // second dimension
92 size_t nx = hmm.dim2(); // third dimension
93 size_t nHist = ny * nx; // number of spectra in the dataset
94 if (nHist == 0) {
95 throw std::runtime_error("Error in data dimensions: " + std::to_string(ny) + " X " + std::to_string(nx));
96 }
97
98 // Build instrument geometry
99
100 // Create a new instrument and set its name
101 std::string instrumentname = "QUOKKA";
102 Geometry::Instrument_sptr instrument(new Geometry::Instrument(instrumentname));
103
104 // Add dummy source and samplepos to instrument
105
106 // Create an instrument component wich will represent the sample position.
107 Geometry::Component *samplepos = new Geometry::Component("Sample", instrument.get());
108 instrument->add(samplepos);
109 instrument->markAsSamplePos(samplepos);
110 // Put the sample in the centre of the coordinate system
111 samplepos->setPos(0.0, 0.0, 0.0);
112
113 // Create a component to represent the source
114 Geometry::ObjComponent *source = new Geometry::ObjComponent("Source", instrument.get());
115 instrument->add(source);
116 instrument->markAsSource(source);
117
118 // Read in the L1 value and place the source at (0,0,-L1)
119 double l1 = static_cast<double>(entry.getFloat("instrument/parameters/L1"));
120 source->setPos(0.0, 0.0, -1.0 * l1);
121
122 // Create a component for the detector.
123
124 // We assumed that these are the dimensions of the detector, and height is in
125 // y direction and width is in x direction
126 double height = static_cast<double>(entry.getFloat("instrument/detector/active_height"));
127 double width = static_cast<double>(entry.getFloat("instrument/detector/active_width"));
128 // Convert them to metres
129 height /= 1000;
130 width /= 1000;
131
132 // We assumed that individual pixels have the same size and shape of a cuboid
133 // with dimensions:
134 double pixel_height = height / static_cast<double>(ny);
135 double pixel_width = width / static_cast<double>(nx);
136 // Create size strings for shape creation
137 std::string pixel_height_str = boost::lexical_cast<std::string>(pixel_height / 2);
138 std::string pixel_width_str = boost::lexical_cast<std::string>(pixel_width / 2);
139 // Set the depth of a pixel to a very small number
140 std::string pixel_depth_str = "0.00001";
141
142 // Create a RectangularDetector which represents a rectangular array of pixels
143 Geometry::RectangularDetector *bank = new Geometry::RectangularDetector("bank", instrument.get());
144 // Define shape of a pixel as an XML string. See
145 // docs/source/concepts/HowToDefineGeometricShape.rst for details
146 std::string detXML = "<cuboid id=\"pixel\">"
147 "<left-front-bottom-point x= \"" +
148 pixel_width_str + "\" y=\"-" + pixel_height_str +
149 "\" z=\"0\" />"
150 "<left-front-top-point x= \"" +
151 pixel_width_str + "\" y=\"-" + pixel_height_str + "\" z=\"" + pixel_depth_str +
152 "\" />"
153 "<left-back-bottom-point x=\"-" +
154 pixel_width_str + "\" y=\"-" + pixel_height_str +
155 "\" z=\"0\" />"
156 "<right-front-bottom-point x= \"" +
157 pixel_width_str + "\" y= \"" + pixel_height_str +
158 "\" z=\"0\" />"
159 "</cuboid>";
160 // Create a shape object which will be shared by all pixels.
161 auto shape = Geometry::ShapeFactory().createShape(detXML);
162 // Initialise the detector specifying the sizes.
163 bank->initialize(shape, int(nx), 0, pixel_width, int(ny), 0, pixel_height, 1, true, int(nx));
164 for (int i = 0; i < static_cast<int>(ny); ++i)
165 for (int j = 0; j < static_cast<int>(nx); ++j) {
166 instrument->markAsDetector(bank->getAtXY(j, i).get());
167 }
168 // Position the detector so the z axis goes through its centre
169 bank->setPos(-width / 2, -height / 2, 0);
170
171 // Create a workspace with nHist spectra and a single y bin.
172 auto outputWorkspace =
173 DataObjects::create<DataObjects::Workspace2D>(instrument, Indexing::IndexInfo(nHist), HistogramData::BinEdges(2));
174 // Set the units of the x axis as Wavelength
175 outputWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create("Wavelength");
176 // Set the units of the data as Counts
177 outputWorkspace->setYUnitLabel("Counts");
178
179 using namespace HistogramData;
180 const BinEdges binEdges = {wavelength0, wavelength1};
181 for (size_t index = 0; index < nHist; ++index) {
182 auto x = static_cast<int>(index % nx);
183 auto y = static_cast<int>(index / nx);
184 auto c = hmm(0, x, y);
185
186 Counts yValue = {static_cast<double>(c)};
187 outputWorkspace->setHistogram(index, binEdges, yValue);
188 }
189
190 outputWorkspace->setTitle(entry.getString("experiment/title"));
191 setProperty("OutputWorkspace", std::move(outputWorkspace));
192}
193
194} // namespace Mantid::DataHandling
double height
Definition GetAllEi.cpp:155
std::map< DeltaEMode::Type, std::string > index
#define DECLARE_NEXUS_FILELOADER_ALGORITHM(classname)
DECLARE_NEXUS_FILELOADER_ALGORITHM should be used in place of the standard DECLARE_ALGORITHM macro wh...
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
@ Load
allowed here which will be passed to the algorithm
A property class for workspaces.
Loads a Quokka data file.
Definition LoadQKK.h:26
void exec() override
Execution code.
Definition LoadQKK.cpp:66
void init() override
Initialisation code.
Definition LoadQKK.cpp:52
Component is a wrapper for a Component which can modify some of its parameters, e....
Definition Component.h:42
void setPos(double, double, double) override
Set the IComponent position, x, y, z respective to parent (if present)
virtual void setPos(double, double, double)=0
Set the IComponent position, x, y, z respective to parent (if present)
Base Instrument Class.
Definition Instrument.h:47
Object Component class, this class brings together the physical attributes of the component to the po...
RectangularDetector is a type of CompAssembly, an assembly of components.
std::shared_ptr< Detector > getAtXY(const int X, const int Y) const
Return a pointer to the component in the assembly at the (X,Y) pixel position.
void initialize(std::shared_ptr< IObject > shape, int xpixels, double xstart, double xstep, int ypixels, double ystart, double ystep, int idstart, bool idfillbyfirst_y, int idstepbyrow, int idstep=1)
Create all the detector pixels of this rectangular detector.
Class originally intended to be used with the DataHandling 'LoadInstrument' algorithm.
std::shared_ptr< CSGObject > createShape(Poco::XML::Element *pElem)
Creates a geometric object from a DOM-element-node pointing to an element whose child nodes contain t...
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
float getFloat(const std::string &name) const
Returns a float.
std::string getString(const std::string &name) const
Returns a string.
Templated class implementation of NXDataSet.
void load()
Read all of the datablock in.
dimsize_t dim2() const
Returns the number of elements along the third dimension.
dimsize_t dim1() const
Returns the number of elements along the second dimension.
Implements NXdata Nexus class.
NXInt openIntData()
Opens data of int type.
Implements NXentry Nexus class.
NXData openNXData(const std::string &name) const
Opens a NXData.
Implements NXroot Nexus class.
NXEntry openFirstEntry()
Open the first NXentry in the file.
std::shared_ptr< Instrument > Instrument_sptr
Shared pointer to an instrument object.
std::string to_string(const wide_integer< Bits, Signed > &n)
@ Output
An output workspace.
Definition Property.h:54