102 Nexus::File file(filename);
103 std::string mainEntry = (*(file.getEntries().begin())).first;
104 file.openGroup(mainEntry,
"NXentry");
105 file.openData(
"definition");
107 throw std::invalid_argument(
"Not NXSPE");
111 throw std::invalid_argument(
"Not NeXus or not NXSPE");
115 Nexus::File file(filename);
117 std::string mainEntry = (*(file.getEntries().begin())).first;
118 file.openGroup(mainEntry,
"NXentry");
120 file.openGroup(
"NXSPE_info",
"NXcollection");
121 std::map<std::string, std::string> entries = file.getEntries();
122 std::vector<double> temporary;
123 double fixed_energy, psi = 0.;
125 if (!entries.count(
"fixed_energy")) {
126 throw std::invalid_argument(
"fixed_energy field was not found");
128 file.openData(
"fixed_energy");
129 file.getData(temporary);
130 fixed_energy = temporary.at(0);
133 if (entries.count(
"psi")) {
134 file.openData(
"psi");
135 file.getData(temporary);
136 psi = temporary.at(0);
137 if (std::isnan(psi)) {
139 g_log.
warning(
"Entry for PSI is empty, will use default of 0.0 instead.");
145 if (entries.count(
"ki_over_kf_scaling")) {
146 file.openData(
"ki_over_kf_scaling");
147 std::vector<int> temporaryint;
148 file.getData(temporaryint);
149 kikfscaling = temporaryint.at(0);
155 file.openGroup(
"data",
"NXdata");
156 entries = file.getEntries();
158 if (!entries.count(
"data")) {
159 throw std::invalid_argument(
"data field was not found");
161 file.openData(
"data");
163 auto numSpectra =
static_cast<std::size_t
>(info.
dims.at(0));
164 auto numBins =
static_cast<std::size_t
>(info.
dims.at(1));
165 std::vector<double> data;
169 if (!entries.count(
"error")) {
170 throw std::invalid_argument(
"error field was not found");
172 file.openData(
"error");
173 std::vector<double>
error;
177 if (!entries.count(
"energy")) {
178 throw std::invalid_argument(
"energy field was not found");
180 file.openData(
"energy");
181 std::vector<double> energies;
182 file.getData(energies);
185 if (!entries.count(
"azimuthal")) {
186 throw std::invalid_argument(
"azimuthal field was not found");
188 file.openData(
"azimuthal");
189 std::vector<double> azimuthal;
190 file.getData(azimuthal);
193 if (!entries.count(
"azimuthal_width")) {
194 throw std::invalid_argument(
"azimuthal_width field was not found");
196 file.openData(
"azimuthal_width");
197 std::vector<double> azimuthal_width;
198 file.getData(azimuthal_width);
201 if (!entries.count(
"polar")) {
202 throw std::invalid_argument(
"polar field was not found");
204 file.openData(
"polar");
205 std::vector<double> polar;
209 if (!entries.count(
"polar_width")) {
210 throw std::invalid_argument(
"polar_width field was not found");
212 file.openData(
"polar_width");
213 std::vector<double> polar_width;
214 file.getData(polar_width);
218 std::vector<double> distance;
219 if (entries.count(
"distance")) {
220 file.openData(
"distance");
221 file.getData(distance);
227 file.openGroup(
"instrument",
"NXinstrument");
228 entries = file.getEntries();
229 std::string instrument_name;
230 if (entries.count(
"name")) {
231 file.openData(
"name");
232 instrument_name = file.getStrData();
241 if ((
error.size() != data.size()) || (azimuthal.size() != numSpectra) || (azimuthal_width.size() != numSpectra) ||
242 (polar.size() != numSpectra) || (polar_width.size() != numSpectra) ||
243 ((energies.size() != numBins) && (energies.size() != numBins + 1))) {
244 throw std::invalid_argument(
"incompatible sizes of fields in the NXSPE file");
250 outputWS->getAxis(0)->unit() = UnitFactory::Instance().create(
"DeltaE");
251 outputWS->setYUnit(
"SpectraNumber");
256 outputWS->mutableRun().addLogData(
262 outputWS->mutableRun().setGoniometer(gm,
true);
268 source->
setPos(0.0, 0.0, -10.);
269 instrument->add(source);
270 instrument->markAsSource(source);
272 instrument->add(sample);
273 instrument->markAsSamplePos(sample);
275 constexpr double deg2rad = M_PI / 180.0;
277 for (std::size_t i = 0; i < numSpectra; ++i) {
279 if (!distance.empty()) {
284 pos.
spherical(r, polar.at(i), azimuthal.at(i));
287 r * sin(std::min(std::min(std::abs(polar_width.at(i)), std::abs(azimuthal_width.at(i))), 2.0) *
deg2rad / 2);
294 instrument->add(det);
295 instrument->markAsDetector(det);
297 outputWS->setInstrument(instrument);
299 std::vector<double>::iterator itdata = data.begin(), iterror =
error.begin(), itdataend, iterrorend;
300 auto &spectrumInfo = outputWS->mutableSpectrumInfo();
302 BinEdges edges(std::move(energies));
303 for (std::size_t i = 0; i < numSpectra; ++i) {
304 itdataend = itdata + numBins;
305 iterrorend = iterror + numBins;
306 outputWS->getSpectrum(i).setDetectorID(
static_cast<detid_t>(i + 1));
307 outputWS->setBinEdges(i, edges);
308 if ((!std::isfinite(*itdata)) || (*itdata <= -1e10))
310 spectrumInfo.setMasked(i,
true);
312 outputWS->mutableY(i).assign(itdata, itdataend);
313 outputWS->mutableE(i).assign(iterror, iterrorend);
315 itdata = (itdataend);
316 iterror = (iterrorend);
322 if (!instrument_name.empty() && instrument_name !=
"NXSPE") {
324 std::string instrument_parfile = IDF_filename.substr(0, IDF_filename.find(
"_Definition")) +
"_Parameters.xml";
325 if (std::filesystem::exists(instrument_parfile)) {
328 loadParamAlg->setProperty(
"Filename", instrument_parfile);
329 loadParamAlg->setProperty(
"Workspace", outputWS);
330 loadParamAlg->execute();
337 outputWS->setDistribution(
true);