Mantid
Loading...
Searching...
No Matches
LoadHKL.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 +
9#include "MantidAPI/Run.h"
10#include "MantidAPI/Sample.h"
14#include "MantidKernel/Utils.h"
15#include <fstream>
16
17using namespace Mantid::Geometry;
18using namespace Mantid::DataObjects;
19using namespace Mantid::Kernel;
20using namespace Mantid::API;
21using namespace Mantid::PhysicalConstants;
22
23namespace Mantid::Crystal {
24
25// Register the algorithm into the AlgorithmFactory
26DECLARE_ALGORITHM(LoadHKL)
27
28
30void LoadHKL::init() {
31 declareProperty(std::make_unique<FileProperty>("Filename", "", FileProperty::Load, ".hkl"),
32 "Path to an hkl file to save.");
33
34 declareProperty(std::make_unique<WorkspaceProperty<PeaksWorkspace>>("OutputWorkspace", "", Direction::Output),
35 "Name of the output workspace.");
36}
37
41
42 std::string filename = getPropertyValue("Filename");
44 bool cosines = false;
45
46 std::fstream in;
47 in.open(filename.c_str(), std::ios::in);
48
49 // Anvred write from Art Schultz
50 // hklFile.write('%4d%4d%4d%8.2f%8.2f%4d%8.4f%7.4f%7d%7d%7.4f%4d%9.5f%9.4f\n'
51 // % (H, K, L, FSQ, SIGFSQ, hstnum, WL, TBAR, CURHST, SEQNUM, TRANSMISSION,
52 // DN, TWOTH, DSP))
53 // HKL is flipped by -1 due to different q convention in ISAW vs mantid.
54 // Default for kf-ki has -q
55 double qSign = -1.0;
56 std::string convention = ConfigService::Instance().getString("Q.convention");
57 if (convention == "Crystallography")
58 qSign = 1.0;
60 Detector *detector = new Detector("det1", -1, nullptr);
61 detector->setPos(0.0, 0.0, 0.0);
62 inst->add(detector); // This takes care of deletion
63 inst->markAsDetector(detector);
65 inst->add(sample); // This takes care of deletion
66 inst->markAsSamplePos(sample);
68 source->setPos(0.0, 0.0, -1.0);
69 inst->add(source); // This takes care of deletion
70 inst->markAsSource(source);
71
72 std::string line;
73 bool first = true;
74 double mu1 = 0.0, mu2 = 0.0, wl1 = 0.0, wl2 = 0.0, sc1 = 0.0, astar1 = 0.0;
75 do {
76 getline(in, line);
77 if (line.length() > 125)
78 cosines = true;
79 double h = std::stod(line.substr(0, 4));
80 double k = std::stod(line.substr(4, 4));
81 double l = std::stod(line.substr(8, 4));
82 if (h == 0.0 && k == 0 && l == 0)
83 break;
84 double Inti = std::stod(line.substr(12, 8));
85 double SigI = std::stod(line.substr(20, 8));
86 double wl = std::stod(line.substr(32, 8));
87 double tbar, trans, scattering;
88 int run, bank;
89 int seqNum;
90 if (cosines) {
91 tbar = std::stod(line.substr(40, 8)); // tbar
92 run = std::stoi(line.substr(102, 6));
93 trans = std::stod(line.substr(114, 7)); // transmission
94 seqNum = std::stoi(line.substr(109, 7));
95 bank = std::stoi(line.substr(121, 4));
96 scattering = std::stod(line.substr(125, 9));
97 } else {
98 tbar = std::stod(line.substr(40, 7)); // tbar
99 run = std::stoi(line.substr(47, 7));
100 trans = std::stod(line.substr(61, 7)); // transmission
101 seqNum = std::stoi(line.substr(54, 7));
102 bank = std::stoi(line.substr(68, 4));
103 scattering = std::stod(line.substr(72, 9));
104 }
105
106 if (first) {
107 mu1 = -std::log(trans) / tbar;
108 wl1 = wl / 1.8;
109 sc1 = scattering;
110 astar1 = 1.0 / trans;
111 first = false;
112 } else {
113 mu2 = -std::log(trans) / tbar;
114 wl2 = wl / 1.8;
115 }
116
117 Peak peak(inst, scattering, wl);
118 peak.setHKL(qSign * h, qSign * k, qSign * l);
119 peak.setIntensity(Inti);
120 peak.setSigmaIntensity(SigI);
121 peak.setRunNumber(run);
122 peak.setPeakNumber(seqNum);
123 std::ostringstream oss;
124 oss << "bank" << bank;
125 std::string bankName = oss.str();
126
127 peak.setBankName(bankName);
128 if (cosines) {
129 int col = std::stoi(line.substr(142, 7));
130 int row = std::stoi(line.substr(149, 7));
131 peak.setCol(col);
132 peak.setRow(row);
133 }
134 ws->addPeak(peak);
135
136 } while (!in.eof());
137
138 in.close();
139 // solve 2 linear equations to find amu and smu
140 double amu = (mu2 - 1.0 * mu1) / (-1.0 * wl1 + wl2);
141 double smu = mu1 - wl1 * amu;
142 double theta = sc1 * radtodeg * 0.5;
143
144 // find roots of polynomial that describes
145 double radius = 0.0;
146 if (std::isfinite(astar1) && astar1 >= 1) {
147 const size_t ndeg = sizeof pc / sizeof pc[0]; // order of poly
148 double coefs[ndeg];
149 std::vector<double> murs;
150 murs.reserve(2);
151 auto ith_lo = static_cast<size_t>(theta / 5.);
152 for (size_t ith = ith_lo; ith < ith_lo + 2; ith++) {
153 for (size_t ideg = 0; ideg < ndeg; ideg++) {
154 coefs[ideg] = pc[ndeg - 1 - ideg][ith];
155 }
156 coefs[0] = coefs[0] - std::log(1.0 / astar1);
157 double roots[2 * (ndeg - 1)];
158 gsl_poly_complex_workspace *w = gsl_poly_complex_workspace_alloc(ndeg);
159 gsl_poly_complex_solve(coefs, ndeg, w, roots);
160 gsl_poly_complex_workspace_free(w);
161
162 for (size_t irt = 0; irt < ndeg - 1; irt++) {
163 if (roots[2 * irt] > 0 && roots[2 * irt] < 9 && std::abs(roots[2 * irt + 1]) < 1e-15) {
164 murs.emplace_back(roots[2 * irt]); // real root in range 0 < muR < 9 cm^-1 (fitted in AnvredCorrection)
165 }
166 }
167 }
168 if (murs.size() == 2) {
169 double frac = (theta - static_cast<double>(ith_lo) * 5.0) / 5.0;
170 radius = (murs[0] * (1 - frac) + murs[1] * frac) / mu1;
171 g_log.notice() << "LinearScatteringCoef = " << smu << " LinearAbsorptionCoef = " << amu << " Radius = " << radius
172 << " calculated from tbar and transmission of 2 peaks\n";
173 } else {
174 g_log.warning() << "Radius set to 0.0 cm - failed to find physical root to polynomial in AnvredCorrections\n";
175 }
176 } else {
177 g_log.warning() << "Radius set to 0.0 cm - non-physical transmission supplied.\n";
178 }
179
180 API::Run &mrun = ws->mutableRun();
181 mrun.addProperty<double>("Radius", radius, true);
182 NeutronAtom neutron(0, 0, 0.0, 0.0, smu, 0.0, smu, amu);
183 auto shape =
184 std::shared_ptr<IObject>(ws->sample().getShape().cloneWithMaterial(Material("SetInLoadHKL", neutron, 1.0)));
185 ws->mutableSample().setShape(shape);
186
187 setProperty("OutputWorkspace", std::dynamic_pointer_cast<PeaksWorkspace>(ws));
188}
189
190} // namespace Mantid::Crystal
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
double radius
Definition: Rasterize.cpp:31
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
Definition: Algorithm.cpp:2026
Kernel::Logger & g_log
Definition: Algorithm.h:451
@ Load
allowed here which will be passed to the algorithm
Definition: FileProperty.h:52
void addProperty(Kernel::Property *prop, bool overwrite=false)
Add data to the object in the form of a property.
Definition: LogManager.h:79
This class stores information regarding an experimental run as a series of log entries.
Definition: Run.h:38
A property class for workspaces.
LoadHKL : Load an ISAW-style .hkl file into a PeaksWorkspace.
Definition: LoadHKL.h:24
void exec() override
Run the algorithm.
Definition: LoadHKL.cpp:40
void setSigmaIntensity(double m_sigmaIntensity) override
Set the error on the integrated peak intensity.
Definition: BasePeak.cpp:206
void setRunNumber(int m_runNumber) override
Set the run number that measured this peak.
Definition: BasePeak.cpp:82
void setPeakNumber(int m_peakNumber) override
Sets the unique peak number.
Definition: BasePeak.cpp:239
void setIntensity(double m_intensity) override
Set the integrated peak intensity.
Definition: BasePeak.cpp:198
void setHKL(double H, double K, double L) override
Set all three H,K,L indices of the peak.
Definition: BasePeak.cpp:132
Structure describing a single-crystal peak.
Definition: Peak.h:34
void setRow(int row)
For RectangularDetectors only, sets the row (y) of the pixel of the detector.
Definition: Peak.cpp:338
void setBankName(std::string bankName)
Set the BankName of this peak.
Definition: Peak.cpp:358
void setCol(int col)
For RectangularDetectors only, sets the column (x) of the pixel of the detector.
Definition: Peak.cpp:347
The class PeaksWorkspace stores information about a set of SCD peaks.
Component is a wrapper for a Component which can modify some of its parameters, e....
Definition: Component.h:41
void setPos(double, double, double) override
Set the IComponent position, x, y, z respective to parent (if present)
Definition: Component.cpp:204
This class represents a detector - i.e.
Definition: Detector.h:30
Base Instrument Class.
Definition: Instrument.h:47
Object Component class, this class brings together the physical attributes of the component to the po...
Definition: ObjComponent.h:33
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void notice(const std::string &msg)
Logs at notice level.
Definition: Logger.cpp:95
void warning(const std::string &msg)
Logs at warning level.
Definition: Logger.cpp:86
A material is defined as being composed of a given element, defined as a PhysicalConstants::NeutronAt...
Definition: Material.h:50
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
const double radtodeg
const double pc[8][19]
std::shared_ptr< PeaksWorkspace > PeaksWorkspace_sptr
Typedef for a shared pointer to a peaks workspace.
std::shared_ptr< Instrument > Instrument_sptr
Shared pointer to an instrument object.
A namespace containing physical constants that are required by algorithms and unit routines.
Definition: Atom.h:14
static constexpr double h
Planck constant in J*s.
@ Output
An output workspace.
Definition: Property.h:54
Structure to store neutronic scattering information for the various elements.
Definition: NeutronAtom.h:22