Mantid
Loading...
Searching...
No Matches
DiffractionFocussing.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#include "MantidAPI/Axis.h"
12#include "MantidHistogramData/Histogram.h"
13#include "MantidIndexing/IndexInfo.h"
14#include "MantidKernel/Unit.h"
15
16#include <algorithm>
17#include <fstream>
18#include <iterator>
19#include <limits>
20#include <map>
21
22namespace Mantid::Algorithms {
23
24// Register the class into the algorithm factory
25DECLARE_ALGORITHM(DiffractionFocussing)
26
27
29 this->useAlgorithm("DiffractionFocussing", 2);
30}
31
32using namespace Kernel;
33using namespace HistogramData;
34
39
44 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>("InputWorkspace", "", Direction::Input),
45 "The input workspace");
46 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>("OutputWorkspace", "", Direction::Output),
47 "The result of diffraction focussing of InputWorkspace");
48 declareProperty(std::make_unique<FileProperty>("GroupingFileName", "", FileProperty::Load, ".cal"),
49 "The name of the CalFile with grouping data");
50}
51
60 // retrieve the properties
61 std::string groupingFileName = getProperty("GroupingFileName");
62
63 // Get the input workspace
64 MatrixWorkspace_sptr inputW = getProperty("InputWorkspace");
65
66 bool dist = inputW->isDistribution();
67
68 // do this first to check that a valid file is available before doing any work
69 auto detectorGroups = readGroupingFile(groupingFileName); // <group, UDET>
70
71 // Convert to d-spacing units
73
74 // Rebin to a common set of bins
75 RebinWorkspace(tmpW);
76
77 std::set<int64_t> groupNumbers;
78 std::transform(detectorGroups.cbegin(), detectorGroups.cend(), std::inserter(groupNumbers, groupNumbers.begin()),
79 [](const auto &e) { return e.first; });
80
81 int iprogress = 0;
82 auto iprogress_count = static_cast<int>(groupNumbers.size());
83 int iprogress_step = iprogress_count / 100;
84 if (iprogress_step == 0)
85 iprogress_step = 1;
86 std::vector<int64_t> resultIndeces;
87 for (auto groupNumber : groupNumbers) {
88 if (iprogress++ % iprogress_step == 0) {
89 progress(0.68 + double(iprogress) / iprogress_count / 3);
90 }
91 auto from = detectorGroups.lower_bound(groupNumber);
92 auto to = detectorGroups.upper_bound(groupNumber);
93 std::vector<detid_t> detectorList;
94 for (auto d = from; d != to; ++d)
95 detectorList.emplace_back(static_cast<detid_t>(d->second));
96 // Want version 1 of GroupDetectors here
97 auto childAlg = createChildAlgorithm("GroupDetectors", -1.0, -1.0, true, 1);
98 childAlg->setProperty("Workspace", tmpW);
99 childAlg->setProperty<std::vector<detid_t>>("DetectorList", detectorList);
100 childAlg->executeAsChildAlg();
101 try {
102 // get the index of the combined spectrum
103 int ri = childAlg->getProperty("ResultIndex");
104 if (ri >= 0) {
105 resultIndeces.emplace_back(ri);
106 }
107 } catch (...) {
108 throw std::runtime_error("Unable to get Properties from GroupDetectors Child Algorithm");
109 }
110 }
111
112 // Discard left-over spectra, but print warning message giving number
113 // discarded
114 int discarded = 0;
115 const int64_t oldHistNumber = tmpW->getNumberHistograms();
116 API::Axis *spectraAxis = tmpW->getAxis(1);
117 for (int64_t i = 0; i < oldHistNumber; i++)
118 if (spectraAxis->spectraNo(i) >= 0 && find(resultIndeces.begin(), resultIndeces.end(), i) == resultIndeces.end()) {
119 ++discarded;
120 }
121 g_log.warning() << "Discarded " << discarded << " spectra that were not assigned to any group\n";
122
123 // Running GroupDetectors leads to a load of redundant spectra
124 // Create a new workspace that's the right size for the meaningful spectra and
125 // copy them in
126 int64_t newSize = tmpW->blocksize();
128 DataObjects::create<API::MatrixWorkspace>(*tmpW, resultIndeces.size(), BinEdges(newSize + 1));
129
130 std::vector<Indexing::SpectrumNumber> specNums;
131 const auto &tmpIndices = tmpW->indexInfo();
132 for (int64_t hist = 0; hist < static_cast<int64_t>(resultIndeces.size()); hist++) {
133 int64_t i = resultIndeces[hist];
134 outputW->setHistogram(hist, tmpW->histogram(i));
135 specNums.emplace_back(tmpIndices.spectrumNumber(i));
136 }
137 auto outputIndices = outputW->indexInfo();
138 outputIndices.setSpectrumNumbers(std::move(specNums));
139 outputW->setIndexInfo(outputIndices);
140
141 progress(1.);
142
143 outputW->setDistribution(dist);
144
145 // Assign it to the output workspace property
146 setProperty("OutputWorkspace", outputW);
147}
148
151 const std::string CONVERSION_UNIT = "dSpacing";
152
153 Unit_const_sptr xUnit = workspace->getAxis(0)->unit();
154
155 g_log.information() << "Converting units from " << xUnit->label().ascii() << " to " << CONVERSION_UNIT << ".\n";
156
157 auto childAlg = createChildAlgorithm("ConvertUnits", 0.34, 0.66);
158 childAlg->setProperty("InputWorkspace", workspace);
159 childAlg->setPropertyValue("Target", CONVERSION_UNIT);
160 childAlg->executeAsChildAlg();
161
162 return childAlg->getProperty("OutputWorkspace");
163}
164
167
168 double min = 0;
169 double max = 0;
170 double step = 0;
171
172 calculateRebinParams(workspace, min, max, step);
173 std::vector<double> paramArray{min, -step, max};
174
175 g_log.information() << "Rebinning from " << min << " to " << max << " in " << step << " logaritmic steps.\n";
176
177 auto childAlg = createChildAlgorithm("Rebin");
178 childAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", workspace);
179 childAlg->setProperty<std::vector<double>>("Params", paramArray);
180 childAlg->executeAsChildAlg();
181 workspace = childAlg->getProperty("OutputWorkspace");
182}
183
193 double &max, double &step) {
194
195 min = std::numeric_limits<double>::max();
196 // for min and max we need to iterate over the data block and investigate each
197 // one
198 int64_t length = workspace->getNumberHistograms();
199 for (int64_t i = 0; i < length; i++) {
200 auto &xVec = workspace->x(i);
201 const double &localMin = xVec.front();
202 const double &localMax = xVec.back();
203 if (std::isfinite(localMin) && std::isfinite(localMax)) {
204 min = std::min(min, localMin);
205 max = std::max(max, localMax);
206 }
207 }
208
209 if (min <= 0.)
210 min = 1e-6;
211
212 // step is easy
213 auto n = static_cast<double>(workspace->blocksize());
214 step = (log(max) - log(min)) / n;
215}
216
223std::multimap<int64_t, int64_t> DiffractionFocussing::readGroupingFile(const std::string &groupingFileName) {
224 std::ifstream grFile(groupingFileName.c_str());
225 if (!grFile) {
226 g_log.error() << "Unable to open grouping file " << groupingFileName << '\n';
227 throw Exception::FileError("Error reading .cal file", groupingFileName);
228 }
229
230 std::multimap<int64_t, int64_t> detectorGroups;
231 std::string str;
232 while (getline(grFile, str)) {
233 if (str.empty() || str[0] == '#')
234 continue;
235 std::istringstream istr(str);
236 int n, udet, sel, group;
237 double offset;
238 istr >> n >> udet >> offset >> sel >> group;
239 // Check the line wasn't badly formatted - return a failure if it is
240 // if ( ! istr.good() ) return false;
241 // only allow groups with +ve ids
242 if ((sel) && (group > 0)) {
243 detectorGroups.emplace(group, udet);
244 }
245 }
246 return detectorGroups;
247}
248
249} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
IPeaksWorkspace_sptr workspace
Definition: IndexPeaks.cpp:114
IntArray detectorList
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:85
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
virtual std::shared_ptr< Algorithm > createChildAlgorithm(const std::string &name, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true, const int &version=-1)
Create a Child Algorithm.
Definition: Algorithm.cpp:842
Kernel::Logger & g_log
Definition: Algorithm.h:451
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
Definition: Algorithm.cpp:231
Class to represent the axis of a workspace.
Definition: Axis.h:30
virtual specnum_t spectraNo(const std::size_t &index) const
Get the spectrum number.
Definition: Axis.cpp:60
Class for marking algorithms as deprecated.
A specialized class for dealing with file properties.
Definition: FileProperty.h:42
@ Load
allowed here which will be passed to the algorithm
Definition: FileProperty.h:52
Base MatrixWorkspace Abstract Class.
A property class for workspaces.
This is a parent algorithm that uses several different child algorithms to perform it's task.
void init() override
Initialisation method.
void RebinWorkspace(API::MatrixWorkspace_sptr &workspace)
Run Rebin as a Child Algorithm to harmonise the bin boundaries.
void exec() override
Executes the algorithm.
void calculateRebinParams(const API::MatrixWorkspace_const_sptr &workspace, double &min, double &max, double &step)
Calculates rebin parameters: the min and max bin boundaries and the logarithmic step.
std::multimap< int64_t, int64_t > readGroupingFile(const std::string &groupingFileName)
Reads in the file with the grouping information.
API::MatrixWorkspace_sptr convertUnitsToDSpacing(const API::MatrixWorkspace_sptr &workspace)
Run ConvertUnits as a Child Algorithm to convert to dSpacing.
Records the filename and the description of failure.
Definition: Exception.h:98
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
void warning(const std::string &msg)
Logs at warning level.
Definition: Logger.cpp:86
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< const Unit > Unit_const_sptr
Shared pointer to the Unit base class (const version)
Definition: Unit.h:231
int32_t detid_t
Typedef for a detector ID.
Definition: SpectrumInfo.h:21
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54