15#include <boost/algorithm/string/compare.hpp>
16#include <boost/algorithm/string/predicate.hpp>
17#include <nexus/NeXusFile.hpp>
22using namespace Kernel;
24using namespace Geometry;
28const char *DELAY_PARAM =
"DelayTime";
30const char *PRESSURE_PARAM =
"TubePressure";
32const char *THICKNESS_PARAM =
"TubeThickness";
40 :
Algorithm(), m_baseInstrument(), m_samplePos(), m_moveDets(false), m_workspace(), m_instDelta(-1.0),
41 m_instPressure(-1.0), m_instThickness(-1.0) {}
46 "The name of the workspace to that the detector information "
47 "will be loaded into.");
49 const std::vector<std::string> exts{
".dat",
".raw",
".sca",
".nxs"};
51 "A **raw, dat, nxs** or **sca** file that contains information about the "
53 "workspace. The description of **dat** and **nxs** file format is "
57 "If true, the detectors are moved to "
58 "the positions specified in the file "
59 "defined by the field above.",
66 std::string ext = Poco::Path(filename).getExtension();
67 if (boost::iequals(ext,
"dat") || boost::iequals(ext,
"sca")) {
69 }
else if (boost::iequals(ext,
"raw")) {
71 }
else if (boost::iequals(ext,
"nxs")) {
74 throw std::invalid_argument(
"Unknown file type with extension=." + ext);
113 std::ifstream datFile(filename.c_str());
120 for (
int i = 0; i < 3; ++i)
121 getline(datFile, line);
125 auto &wsDetInfo =
m_workspace->mutableDetectorInfo();
126 while (getline(datFile, line)) {
127 if (line.empty() || line[0] ==
'#')
130 std::istringstream is(line);
133 float delta(0.0f),
l2(0.0f), theta(0.0f), phi(0.0f);
134 is >> detID >>
delta >>
l2 >> code >> theta >> phi;
139 size_t index = wsDetInfo.indexOf(detID);
140 if (wsDetInfo.isMonitor(
index) || code == 1)
144 for (
int i = 0; i < 10; ++i) {
145 float droppedFloat(0.0f);
150 float pressure(0.0), thickness(0.0);
151 is >> pressure >> thickness;
154 }
catch (std::out_of_range &) {
169 const int numDets = iraw.
i_det;
170 const int numUserTables = iraw.
i_use;
171 int pressureTabNum(0), thicknessTabNum(0);
172 if (numUserTables == 10) {
175 }
else if (numUserTables == 14) {
177 thicknessTabNum = 12;
179 throw std::invalid_argument(
"RAW file contains unexpected number of user tables=" +
std::to_string(numUserTables) +
180 ". Expected 10 or 14.");
185 bool phiPresent = (iraw.
ut[0] != 1.0 && iraw.
ut[0] != 2.0);
189 auto &wsDetInfo =
m_workspace->mutableDetectorInfo();
190 for (
int i = 0; i < numDets; ++i) {
192 int code = iraw.
code[i];
194 size_t index = wsDetInfo.indexOf(detID);
195 if (wsDetInfo.isMonitor(
index) || code == 1)
200 float theta = iraw.
tthe[i];
201 float phi = (phiPresent ? iraw.
ut[i] : 0.0f);
208 float pressure = iraw.
ut[i + pressureTabNum * numDets];
209 float thickness = iraw.
ut[i + thicknessTabNum * numDets];
212 }
catch (std::out_of_range &) {
223 ::NeXus::File nxsFile(filename,
233 std::map<std::string, std::string> entries;
234 nxsFile.getEntries(entries);
235 if (entries.find(
"full_reference_detector") != entries.end()) {
236 nxsFile.openGroup(
"full_reference_detector",
"NXIXTdetector");
238 nxsFile.closeGroup();
239 }
else if (entries.find(
"detectors.dat") != entries.end()) {
240 nxsFile.openGroup(
"detectors.dat",
"NXEntry");
242 nxsFile.closeGroup();
244 throw std::invalid_argument(
"Unknown NeXus file type");
250 auto &wsDetInfo =
m_workspace->mutableDetectorInfo();
251 auto numDets =
static_cast<int>(detInfo.
ids.size());
252 for (
int i = 0; i < numDets; ++i) {
254 int code = detInfo.
codes[i];
256 size_t index = wsDetInfo.indexOf(detID);
257 if (wsDetInfo.isMonitor(
index) || code == 1)
261 double l2 = detInfo.
l2[i];
262 double theta = detInfo.
theta[i];
263 double phi = detInfo.
phi[i];
274 }
catch (std::out_of_range &) {
288 nxsFile.readData<int32_t>(
"det_no", detInfo.
ids);
289 nxsFile.readData<int32_t>(
"det_type", detInfo.
codes);
290 nxsFile.readData<
double>(
"delay_time", detInfo.
delays);
291 const size_t numDets = detInfo.
ids.size();
294 nxsFile.readData<
double>(
"L2", detInfo.
l2);
295 nxsFile.readData<
double>(
"theta", detInfo.
theta);
296 nxsFile.readData<
double>(
"phi", detInfo.
phi);
299 detInfo.
l2.resize(numDets, -1.0);
300 detInfo.
theta.resize(numDets, -1.0);
301 detInfo.
phi.resize(numDets, -1.0);
305 double pressure = -1.0;
306 double thickness = -1.0;
307 nxsFile.openGroup(
"det_he3",
"NXIXTdet_he3");
308 nxsFile.readData<
double>(
"gas_pressure", pressure);
309 nxsFile.readData<
double>(
"wall_thickness", thickness);
310 nxsFile.closeGroup();
311 if (pressure <= 0.0) {
312 g_log.
warning(
"The data file does not contain correct He3 pressure, "
313 "default value of 10 bar is used instead");
316 if (thickness <= 0.0) {
317 g_log.
warning(
"The data file does not contain correct detector's wall "
318 "thickness, default value of 0.8mm is used instead");
321 detInfo.
pressures.resize(numDets, pressure);
333 std::vector<int32_t> fileIDs;
334 nxsFile.readData<int32_t>(
"detID", fileIDs);
335 std::vector<float> fileOffsets;
336 nxsFile.readData<
float>(
"timeOffsets", fileOffsets);
337 const size_t numDets = fileOffsets.size() / 2;
339 std::vector<float> detCoords;
341 nxsFile.readData<
float>(
"detSphericalCoord", detCoords);
343 detCoords.resize(3 * numDets, -1.0f);
347 std::vector<float> pressureAndWall;
348 nxsFile.readData<
float>(
"detPressureAndWall", pressureAndWall);
350 if (numDets != fileIDs.size() / 2 || numDets != detCoords.size() / 3 || numDets != pressureAndWall.size() / 2) {
351 std::ostringstream os;
352 os <<
"The sizes of NeXus data columns are inconsistent in detectors.dat.\n"
353 <<
"detIDs=" << fileIDs.size() <<
", offsets=" << fileOffsets.size()
354 <<
", pressure & thickness=" << pressureAndWall.size() <<
"\n";
355 throw std::runtime_error(os.str());
358 detInfo.
ids.resize(numDets);
359 detInfo.
codes.resize(numDets);
360 detInfo.
delays.resize(numDets);
361 detInfo.
l2.resize(numDets);
362 detInfo.
theta.resize(numDets);
363 detInfo.
phi.resize(numDets);
368 for (
int i = 0; i < static_cast<int>(numDets); i++) {
369 detInfo.
ids[i] = fileIDs[2 * i];
370 detInfo.
codes[i] = fileIDs[2 * i + 1];
371 detInfo.
delays[i] = fileOffsets[2 * i];
373 detInfo.
l2[i] = detCoords[3 * i + 0];
374 detInfo.
theta[i] = detCoords[3 * i + 1];
375 detInfo.
phi[i] = detCoords[3 * i + 2];
377 detInfo.
pressures[i] = pressureAndWall[2 * i];
378 detInfo.
thicknesses[i] = pressureAndWall[2 * i + 1];
396 const double phi,
const double delay,
const double pressure,
397 const double thickness)
const {
403 pmap.addDouble(detCompID, DELAY_PARAM, delay);
405 pmap.addDouble(detCompID, PRESSURE_PARAM, pressure);
407 pmap.addDouble(detCompID, 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.
double m_instThickness
Wall thickness value set on the instrument level.
void readNXSDotDat(::NeXus::File &nxsFile, DetectorInfo &detInfo) const
Read data from old-style libisis NeXus file.
double m_instDelta
Delta value that has been set on the instrument.
Geometry::Instrument_const_sptr m_baseInstrument
Cached instrument for this workspace.
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 updateParameterMap(Geometry::DetectorInfo &detectorInfo, const size_t detIndex, Geometry::ParameterMap &pmap, 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 readLibisisNxs(::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 loadFromDAT(const std::string &filename)
Use a .dat or .sca file as input.
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.
const Geometry::IDetector & detector(const size_t index) const
Return a const reference to the detector with given index.
virtual ComponentID getComponentID() const =0
Returns the ComponentID - a unique identifier of the component.
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.
std::shared_ptr< const IComponent > IComponent_const_sptr
Typdef of a shared pointer to a const IComponent.
int32_t detid_t
Typedef for a detector ID.
Generate a tableworkspace to store the calibration results.
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.