Mantid
Loading...
Searching...
No Matches
SaveDiffCal.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 +
13
14#include <H5Cpp.h>
15#include <Poco/File.h>
16#include <Poco/Path.h>
17
18namespace Mantid::DataHandling {
19
30
31using namespace H5;
32
33// Register the algorithm into the AlgorithmFactory
34DECLARE_ALGORITHM(SaveDiffCal)
35
36//----------------------------------------------------------------------------------------------
37
38
39const std::string SaveDiffCal::name() const { return "SaveDiffCal"; }
40
42int SaveDiffCal::version() const { return 1; }
43
45const std::string SaveDiffCal::category() const { return "DataHandling\\Instrument;Diffraction\\DataHandling"; }
46
48const std::string SaveDiffCal::summary() const { return "Saves a calibration file for powder diffraction"; }
49
50//----------------------------------------------------------------------------------------------
54 declareProperty(std::make_unique<WorkspaceProperty<ITableWorkspace>>("CalibrationWorkspace", "", Direction::Input),
55 "An output workspace.");
56
57 declareProperty(std::make_unique<WorkspaceProperty<GroupingWorkspace>>("GroupingWorkspace", "", Direction::Input,
59 "Optional: A GroupingWorkspace giving the grouping info.");
60
62 std::make_unique<WorkspaceProperty<MaskWorkspace>>("MaskWorkspace", "", Direction::Input, PropertyMode::Optional),
63 "Optional: A MaskWorkspace giving which detectors are masked.");
64
65 declareProperty(std::make_unique<FileProperty>("Filename", "", FileProperty::Save, ".h5"),
66 "Path to the .h5 file that will be created.");
67}
68
69std::map<std::string, std::string> SaveDiffCal::validateInputs() {
70 std::map<std::string, std::string> result;
71
72 ITableWorkspace_const_sptr calibrationWS = getProperty("CalibrationWorkspace");
73 if (!bool(calibrationWS)) {
74 result["CalibrationWorkspace"] = "Cannot save empty table";
75 } else {
76 size_t numRows = calibrationWS->rowCount();
77 if (numRows == 0) {
78 result["CalibrationWorkspace"] = "Cannot save empty table";
79 } else {
80 GroupingWorkspace_const_sptr groupingWS = getProperty("GroupingWorkspace");
81 if (bool(groupingWS) && numRows < groupingWS->getNumberHistograms()) {
82 result["GroupingWorkspace"] = "Must have equal or less number of spectra as the table has rows";
83 }
84 MaskWorkspace_const_sptr maskWS = getProperty("MaskWorkspace");
85 if (bool(maskWS) && numRows < maskWS->getNumberHistograms()) {
86 result["MaskWorkspace"] = "Must have equal or less number of spectra as the table has rows";
87 }
88 }
89 }
90
91 return result;
92}
93
101void SaveDiffCal::writeDoubleFieldFromTable(H5::Group &group, const std::string &name) {
102 auto column = m_calibrationWS->getColumn(name);
103 // Retrieve only the first m_numValues, not necessarily the whole column
104 auto data = column->numeric_fill<>(m_numValues);
105 H5Util::writeArray1D(group, name, data);
106}
107
115void SaveDiffCal::writeIntFieldFromTable(H5::Group &group, const std::string &name) {
116 auto column = m_calibrationWS->getColumn(name);
117 // Retrieve only the first m_numValues, not necessarily the whole column
118 auto data = column->numeric_fill<int32_t>(m_numValues);
119 H5Util::writeArray1D(group, name, data);
120}
121
130void SaveDiffCal::writeIntFieldFromSVWS(H5::Group &group, const std::string &name,
132 const bool isMask = (name == "use");
133
134 // output array defaults to all one (one group, use the pixel)
135 std::vector<int32_t> values(m_numValues, 1);
136
137 if (bool(ws)) {
138 for (size_t i = 0; i < m_numValues; ++i) {
139 auto &ids = ws->getSpectrum(i).getDetectorIDs(); // set of detector ID's
140 // check if the first detector ID in the set is in the calibration table
141 auto found = m_detidToIndex.find(*(ids.begin())); // (detID, row_index)
142 if (found != m_detidToIndex.end()) {
143 auto value = static_cast<int32_t>(ws->getValue(found->first));
144 // in maskworkspace 0=use, 1=dontuse - backwards from the file
145 if (isMask) {
146 if (value == 0)
147 value = 1; // thus "use" means a calibrated detector, good for use
148 else
149 value = 0;
150 }
151 values[found->second] = value;
152 }
153 }
154 }
155
156 H5Util::writeArray1D(group, name, values);
157}
158
160 m_detidToIndex.clear();
161
162 auto detidCol = m_calibrationWS->getColumn("detid");
163 auto detids = detidCol->numeric_fill<detid_t>();
164
165 const size_t numDets = detids.size();
166 for (size_t i = 0; i < numDets; ++i) {
167 m_detidToIndex[static_cast<detid_t>(detids[i])] = i;
168 }
169}
170
171bool SaveDiffCal::tableHasColumn(const std::string &ColumnName) const {
172 const std::vector<std::string> names = m_calibrationWS->getColumnNames();
173 return std::any_of(names.cbegin(), names.cend(), [&ColumnName](const auto &name) { return name == ColumnName; });
174}
175
176//----------------------------------------------------------------------------------------------
180 m_calibrationWS = getProperty("CalibrationWorkspace");
181 this->generateDetidToIndex();
182 GroupingWorkspace_const_sptr groupingWS = getProperty("GroupingWorkspace");
183 MaskWorkspace_const_sptr maskWS = getProperty("MaskWorkspace");
184 std::string filename = getProperty("Filename");
185
186 // initialize `m_numValues` as the minimum of (CalibrationWorkspace_row_count,
187 // GroupingWorkspace_histogram_count, MaskWorkspace_histogram_count)
188 m_numValues = m_calibrationWS->rowCount();
189 if (bool(groupingWS) && groupingWS->getNumberHistograms() < m_numValues) {
190 m_numValues = groupingWS->getNumberHistograms();
191 }
192 if (bool(maskWS) && maskWS->getNumberHistograms() < m_numValues) {
193 m_numValues = maskWS->getNumberHistograms();
194 }
195
196 // delete the file if it already exists
197 if (Poco::File(filename).exists()) {
198 Poco::File(filename).remove();
199 }
200
201 H5File file(filename, H5F_ACC_EXCL);
202
203 auto calibrationGroup = H5Util::createGroupNXS(file, "calibration", "NXentry");
204
205 // write the d-spacing to TOF conversion parameters for the selected pixels
206 // as datasets under the NXentry group
207 this->writeDoubleFieldFromTable(calibrationGroup, "difc");
208 this->writeDoubleFieldFromTable(calibrationGroup, "difa");
209 this->writeDoubleFieldFromTable(calibrationGroup, "tzero");
210
211 this->writeIntFieldFromTable(calibrationGroup, "detid");
212 if (this->tableHasColumn("dasid")) // optional field
213 this->writeIntFieldFromTable(calibrationGroup, "dasid");
214 else
215 g_log.information("Not writing out values for \"dasid\"");
216
217 this->writeIntFieldFromSVWS(calibrationGroup, "group", groupingWS);
218 this->writeIntFieldFromSVWS(calibrationGroup, "use", maskWS);
219
220 // check if the input calibration table has an "offset" field
221 if (this->tableHasColumn("offset")) // optional field
222 this->writeDoubleFieldFromTable(calibrationGroup, "offset");
223 else
224 g_log.information("Not writing out values for \"offset\"");
225
226 // get the instrument information only if a GroupingWorkspace or
227 // MaskWorkspace is supplied by the user
228 std::string instrumentName;
229 std::string instrumentSource;
230 if (bool(groupingWS)) {
231 instrumentName = groupingWS->getInstrument()->getName();
232 instrumentSource = groupingWS->getInstrument()->getFilename();
233 }
234 if (bool(maskWS)) {
235 if (instrumentName.empty()) {
236 instrumentName = maskWS->getInstrument()->getName();
237 }
238 if (instrumentSource.empty()) {
239 instrumentSource = maskWS->getInstrument()->getFilename();
240 }
241 }
242 if (!instrumentSource.empty()) {
243 instrumentSource = Poco::Path(instrumentSource).getFileName();
244 }
245
246 // add the instrument information
247 auto instrumentGroup = calibrationGroup.createGroup("instrument");
248 H5Util::writeStrAttribute(instrumentGroup, "NX_class", "NXinstrument");
249 if (!instrumentName.empty()) {
250 H5Util::write(instrumentGroup, "name", instrumentName);
251 }
252 if (!instrumentSource.empty()) {
253 H5Util::write(instrumentGroup, "instrument_source", instrumentSource);
254 }
255
256 file.close();
257}
258
259} // namespace Mantid::DataHandling
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
double value
The value of the point.
Definition: FitMW.cpp:51
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
Kernel::Logger & g_log
Definition: Algorithm.h:451
A specialized class for dealing with file properties.
Definition: FileProperty.h:42
@ Save
to specify a file to write to, the file may or may not exist
Definition: FileProperty.h:49
ITableWorkspace is an implementation of Workspace in which the data are organised in columns of same ...
A property class for workspaces.
SaveDiffCal : TODO: DESCRIPTION.
Definition: SaveDiffCal.h:23
const std::string summary() const override
Algorithm's summary for use in the GUI and help.
Definition: SaveDiffCal.cpp:48
void writeIntFieldFromTable(H5::Group &group, const std::string &name)
Create a dataset under a given group with a given name Use CalibrationWorkspace to retrieve the data.
API::ITableWorkspace_sptr m_calibrationWS
Definition: SaveDiffCal.h:46
const std::string category() const override
Algorithm's category for identification.
Definition: SaveDiffCal.cpp:45
void writeDoubleFieldFromTable(H5::Group &group, const std::string &name)
Create a dataset under a given group with a given name Use CalibrationWorkspace to retrieve the data.
int version() const override
Algorithm's version for identification.
Definition: SaveDiffCal.cpp:42
void init() override
Initialize the algorithm's properties.
Definition: SaveDiffCal.cpp:53
std::map< detid_t, size_t > m_detidToIndex
Definition: SaveDiffCal.h:47
const std::string name() const override
Algorithms name for identification.
Definition: SaveDiffCal.cpp:39
bool tableHasColumn(const std::string &ColumnName) const
std::map< std::string, std::string > validateInputs() override
Perform validation of ALL the input properties of the algorithm.
Definition: SaveDiffCal.cpp:69
void exec() override
Execute the algorithm.
void writeIntFieldFromSVWS(H5::Group &group, const std::string &name, const DataObjects::SpecialWorkspace2D_const_sptr &ws)
Create a dataset under a given group with a given name Use GroupingWorkspace or MaskWorkspace to retr...
A GroupingWorkspace is a subclass of Workspace2D where each spectrum has a single number entry,...
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
Definition: H5Util.h:16
std::shared_ptr< const ITableWorkspace > ITableWorkspace_const_sptr
shared pointer to Mantid::API::ITableWorkspace (const version)
void writeArray1D(H5::Group &group, const std::string &name, const std::vector< NumT > &values)
MANTID_DATAHANDLING_DLL H5::Group createGroupNXS(H5::H5File &file, const std::string &name, const std::string &nxtype)
MANTID_DATAHANDLING_DLL void write(H5::Group &group, const std::string &name, const std::string &value)
void writeStrAttribute(LocationType &location, const std::string &name, const std::string &value)
Definition: H5Util.cpp:116
bool exists(::NeXus::File &file, const std::string &name)
Based on the current group in the file, does the named sub-entry exist?
std::shared_ptr< const GroupingWorkspace > GroupingWorkspace_const_sptr
shared pointer to a const GroupingWorkspace
std::shared_ptr< const SpecialWorkspace2D > SpecialWorkspace2D_const_sptr
shared pointer to a const SpecialWorkspace2D
std::shared_ptr< const MaskWorkspace > MaskWorkspace_const_sptr
shared pointer to a const MaskWorkspace
Definition: MaskWorkspace.h:67
int32_t detid_t
Typedef for a detector ID.
Definition: SpectrumInfo.h:21
STL namespace.
Enumeration for a mandatory/optional property.
Describes the direction (within an algorithm) of a Property.
Definition: Property.h:50
@ Input
An input workspace.
Definition: Property.h:53