14#include "MantidNexus/NexusFile.h"
16#include <boost/algorithm/string/compare.hpp>
17#include <boost/algorithm/string/predicate.hpp>
23using namespace Kernel;
25using namespace Geometry;
29const char *DELAY_PARAM =
"DelayTime";
31const char *PRESSURE_PARAM =
"TubePressure";
33const char *THICKNESS_PARAM =
"TubeThickness";
41 :
Algorithm(), m_samplePos(), m_moveDets(false), m_workspace(), m_instDelta(-1.0), m_instPressure(-1.0),
42 m_instThickness(-1.0) {}
47 "The name of the workspace to that the detector information "
48 "will be loaded into.");
50 const std::vector<std::string> exts{
".dat",
".raw",
".sca",
".nxs"};
52 "A **raw, dat, nxs** or **sca** file that contains information about the "
54 "workspace. The description of **dat** and **nxs** file format is "
58 "If true, the detectors are moved to "
59 "the positions specified in the file "
60 "defined by the field above.",
67 std::string ext = std::filesystem::path(filename).extension().string().substr(1);
68 if (boost::iequals(ext,
"dat") || boost::iequals(ext,
"sca")) {
70 }
else if (boost::iequals(ext,
"raw")) {
72 }
else if (boost::iequals(ext,
"nxs")) {
75 throw std::invalid_argument(
"Unknown file type with extension=." + ext);
86 const auto &componentInfo =
m_workspace->componentInfo();
87 if (componentInfo.hasSample())
92 const size_t root = componentInfo.root();
94 auto values = componentInfo.getNumberParameter(root, DELAY_PARAM,
false);
98 values = componentInfo.getNumberParameter(root, PRESSURE_PARAM,
false);
102 values = componentInfo.getNumberParameter(root, THICKNESS_PARAM,
false);
112 std::ifstream datFile(filename.c_str());
119 for (
int i = 0; i < 3; ++i)
120 getline(datFile, line);
123 auto &componentInfo =
m_workspace->mutableComponentInfo();
124 auto &wsDetInfo =
m_workspace->mutableDetectorInfo();
125 while (getline(datFile, line)) {
126 if (line.empty() || line[0] ==
'#')
129 std::istringstream is(line);
132 float delta(0.0f),
l2(0.0f), theta(0.0f), phi(0.0f);
133 is >> detID >>
delta >>
l2 >> code >> theta >> phi;
138 size_t index = wsDetInfo.indexOf(detID);
139 if (wsDetInfo.isMonitor(
index) || code == 1)
143 for (
int i = 0; i < 10; ++i) {
144 float droppedFloat(0.0f);
149 float pressure(0.0), thickness(0.0);
150 is >> pressure >> thickness;
153 }
catch (std::out_of_range &) {
168 const int numDets = iraw.
i_det;
169 const int numUserTables = iraw.
i_use;
170 int pressureTabNum(0), thicknessTabNum(0);
171 if (numUserTables == 10) {
174 }
else if (numUserTables == 14) {
176 thicknessTabNum = 12;
178 throw std::invalid_argument(
"RAW file contains unexpected number of user tables=" +
std::to_string(numUserTables) +
179 ". Expected 10 or 14.");
184 bool phiPresent = (iraw.
ut[0] != 1.0 && iraw.
ut[0] != 2.0);
187 auto &componentInfo =
m_workspace->mutableComponentInfo();
188 auto &wsDetInfo =
m_workspace->mutableDetectorInfo();
189 for (
int i = 0; i < numDets; ++i) {
191 int code = iraw.
code[i];
193 size_t index = wsDetInfo.indexOf(detID);
194 if (wsDetInfo.isMonitor(
index) || code == 1)
199 float theta = iraw.
tthe[i];
200 float phi = (phiPresent ? iraw.
ut[i] : 0.0f);
207 float pressure = iraw.
ut[i + pressureTabNum * numDets];
208 float thickness = iraw.
ut[i + thicknessTabNum * numDets];
211 }
catch (std::out_of_range &) {
222 Nexus::File nxsFile(filename,
232 std::map<std::string, std::string> entries;
233 nxsFile.getEntries(entries);
234 if (entries.find(
"full_reference_detector") != entries.end()) {
235 nxsFile.openGroup(
"full_reference_detector",
"NXIXTdetector");
237 nxsFile.closeGroup();
238 }
else if (entries.find(
"detectors.dat") != entries.end()) {
239 nxsFile.openGroup(
"detectors.dat",
"NXEntry");
241 nxsFile.closeGroup();
243 throw std::invalid_argument(
"Unknown NeXus file type");
248 auto &componentInfo =
m_workspace->mutableComponentInfo();
249 auto &wsDetInfo =
m_workspace->mutableDetectorInfo();
250 auto numDets =
static_cast<int>(detInfo.
ids.size());
251 for (
int i = 0; i < numDets; ++i) {
253 int code = detInfo.
codes[i];
255 size_t index = wsDetInfo.indexOf(detID);
256 if (wsDetInfo.isMonitor(
index) || code == 1)
260 double l2 = detInfo.
l2[i];
261 double theta = detInfo.
theta[i];
262 double phi = detInfo.
phi[i];
273 }
catch (std::out_of_range &) {
287 nxsFile.readData<int32_t>(
"det_no", detInfo.
ids);
288 nxsFile.readData<int32_t>(
"det_type", detInfo.
codes);
289 nxsFile.readData<
double>(
"delay_time", detInfo.
delays);
290 const size_t numDets = detInfo.
ids.size();
293 nxsFile.readData<
double>(
"L2", detInfo.
l2);
294 nxsFile.readData<
double>(
"theta", detInfo.
theta);
295 nxsFile.readData<
double>(
"phi", detInfo.
phi);
298 detInfo.
l2.resize(numDets, -1.0);
299 detInfo.
theta.resize(numDets, -1.0);
300 detInfo.
phi.resize(numDets, -1.0);
304 double pressure = -1.0;
305 double thickness = -1.0;
306 nxsFile.openGroup(
"det_he3",
"NXIXTdet_he3");
307 nxsFile.readData<
double>(
"gas_pressure", pressure);
308 nxsFile.readData<
double>(
"wall_thickness", thickness);
309 nxsFile.closeGroup();
310 if (pressure <= 0.0) {
311 g_log.
warning(
"The data file does not contain correct He3 pressure, "
312 "default value of 10 bar is used instead");
315 if (thickness <= 0.0) {
316 g_log.
warning(
"The data file does not contain correct detector's wall "
317 "thickness, default value of 0.8mm is used instead");
320 detInfo.
pressures.resize(numDets, pressure);
332 std::vector<int32_t> fileIDs;
333 nxsFile.readData<int32_t>(
"detID", fileIDs);
334 std::vector<float> fileOffsets;
335 nxsFile.readData<
float>(
"timeOffsets", fileOffsets);
336 const size_t numDets = fileOffsets.size() / 2;
338 std::vector<float> detCoords;
340 nxsFile.readData<
float>(
"detSphericalCoord", detCoords);
342 detCoords.resize(3 * numDets, -1.0f);
346 std::vector<float> pressureAndWall;
347 nxsFile.readData<
float>(
"detPressureAndWall", pressureAndWall);
349 if (numDets != fileIDs.size() / 2 || numDets != detCoords.size() / 3 || numDets != pressureAndWall.size() / 2) {
350 std::ostringstream os;
351 os <<
"The sizes of NeXus data columns are inconsistent in detectors.dat.\n"
352 <<
"detIDs=" << fileIDs.size() <<
", offsets=" << fileOffsets.size()
353 <<
", pressure & thickness=" << pressureAndWall.size() <<
"\n";
354 throw std::runtime_error(os.str());
357 detInfo.
ids.resize(numDets);
358 detInfo.
codes.resize(numDets);
359 detInfo.
delays.resize(numDets);
360 detInfo.
l2.resize(numDets);
361 detInfo.
theta.resize(numDets);
362 detInfo.
phi.resize(numDets);
367 for (
int i = 0; i < static_cast<int>(numDets); i++) {
368 detInfo.
ids[i] = fileIDs[2 * i];
369 detInfo.
codes[i] = fileIDs[2 * i + 1];
370 detInfo.
delays[i] = fileOffsets[2 * i];
372 detInfo.
l2[i] = detCoords[3 * i + 0];
373 detInfo.
theta[i] = detCoords[3 * i + 1];
374 detInfo.
phi[i] = detCoords[3 * i + 2];
376 detInfo.
pressures[i] = pressureAndWall[2 * i];
377 detInfo.
thicknesses[i] = pressureAndWall[2 * i + 1];
395 const double phi,
const double delay,
const double pressure,
396 const double thickness)
const {
400 componentInfo.
addDouble(detIndex, DELAY_PARAM, delay);
402 componentInfo.
addDouble(detIndex, PRESSURE_PARAM, pressure);
404 componentInfo.
addDouble(detIndex, THICKNESS_PARAM, thickness);
#define DECLARE_ALGORITHM(classname)
std::map< DeltaEMode::Type, std::string > index
#define PARALLEL_FOR_NO_WSP_CHECK()
float * ut
nuse UT* user tables (total size NUSE*NDET) ut01=phi
int i_use
number of user defined UTn tables NUSE
float * delt
hold off table (size NDET)
int i_det
number of detectors NDET
int * code
code for UTn tables (size NDET)
int readFromFile(const char *filename, bool read_data=true)
stuff
int * udet
user detector number for each detector (size NDET)
float * tthe
2theta scattering angle (size NDET)
float * len2
L2 table (size NDET)
Base class from which all concrete algorithm classes should be derived.
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.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
@ Load
allowed here which will be passed to the algorithm
A property class for workspaces.
void readLibisisNxs(Nexus::File &nxsFile, DetectorInfo &detInfo) const
Read data from old-style libisis NeXus file.
double m_instThickness
Wall thickness value set on the instrument level.
double m_instDelta
Delta value that has been set on the instrument.
void loadFromRAW(const std::string &filename)
Use a .raw file as input.
void cacheInputs()
Cache the user input that will be frequently accessed.
bool m_moveDets
If set to true then update the detector positions base on the information in the given file.
void readNXSDotDat(Nexus::File &nxsFile, DetectorInfo &detInfo) const
Read data from old-style libisis NeXus file.
void exec() override
Virtual method - must be overridden by concrete algorithm.
Kernel::V3D m_samplePos
Cached sample position for this workspace.
API::MatrixWorkspace_sptr m_workspace
store a pointer to the user selected workspace
void loadFromIsisNXS(const std::string &filename)
Use a isis raw nexus or event file as input.
void init() override
Virtual method - must be overridden by concrete algorithm.
double m_instPressure
Pressure value set on the instrument level.
void updateParameterMap(Geometry::DetectorInfo &detectorInfo, const size_t detIndex, Geometry::ComponentInfo &componentInfo, const double l2, const double theta, const double phi, const double delay, const double pressure, const double thickness) const
Update the parameter map with the new values for the given detector.
void loadFromDAT(const std::string &filename)
Use a .dat or .sca file as input.
ComponentInfo : Provides a component centric view on to the instrument.
void addDouble(const size_t componentIndex, const std::string &name, double value, const std::string *const pDescription=nullptr, const std::string &pVisible="true")
Add or replace a named double parameter at a specific component index.
Geometry::DetectorInfo is an intermediate step towards a DetectorInfo that is part of Instrument-2....
void setPosition(const size_t index, const Kernel::V3D &position)
Set the absolute position of the detector with given index. Not thread safe.
Records the filename and the description of failure.
void warning(const std::string &msg)
Logs at warning level.
void spherical(const double R, const double theta, const double phi) noexcept
Sets the vector position based on spherical coordinates.
int32_t detid_t
Typedef for a detector ID.
std::string to_string(const wide_integer< Bits, Signed > &n)
Simple data holder for passing the detector info around when dealing with the NeXus data.
std::vector< double > pressures
std::vector< detid_t > ids
std::vector< double > thicknesses
std::vector< double > delays
std::vector< double > phi
std::vector< double > theta
std::vector< int32_t > codes
@ InOut
Both an input & output workspace.
@ Input
An input workspace.