104 Nexus::File file(filename);
105 std::string mainEntry = (*(file.getEntries().begin())).first;
106 file.openGroup(mainEntry,
"NXentry");
107 file.openData(
"definition");
109 throw std::invalid_argument(
"Not NXSPE");
113 throw std::invalid_argument(
"Not NeXus or not NXSPE");
117 Nexus::File file(filename);
119 std::string mainEntry = (*(file.getEntries().begin())).first;
120 file.openGroup(mainEntry,
"NXentry");
122 file.openGroup(
"NXSPE_info",
"NXcollection");
123 std::map<std::string, std::string> entries = file.getEntries();
124 std::vector<double> temporary;
125 double fixed_energy, psi = 0.;
127 if (!entries.count(
"fixed_energy")) {
128 throw std::invalid_argument(
"fixed_energy field was not found");
130 file.openData(
"fixed_energy");
131 file.getData(temporary);
132 fixed_energy = temporary.at(0);
135 if (entries.count(
"psi")) {
136 file.openData(
"psi");
137 file.getData(temporary);
138 psi = temporary.at(0);
139 if (std::isnan(psi)) {
141 g_log.
warning(
"Entry for PSI is empty, will use default of 0.0 instead.");
147 if (entries.count(
"ki_over_kf_scaling")) {
148 file.openData(
"ki_over_kf_scaling");
149 std::vector<int> temporaryint;
150 file.getData(temporaryint);
151 kikfscaling = temporaryint.at(0);
157 file.openGroup(
"data",
"NXdata");
158 entries = file.getEntries();
160 if (!entries.count(
"data")) {
161 throw std::invalid_argument(
"data field was not found");
163 file.openData(
"data");
165 auto numSpectra =
static_cast<std::size_t
>(info.
dims.at(0));
166 auto numBins =
static_cast<std::size_t
>(info.
dims.at(1));
167 std::vector<double> data;
171 if (!entries.count(
"error")) {
172 throw std::invalid_argument(
"error field was not found");
174 file.openData(
"error");
175 std::vector<double>
error;
179 if (!entries.count(
"energy")) {
180 throw std::invalid_argument(
"energy field was not found");
182 file.openData(
"energy");
183 std::vector<double> energies;
184 file.getData(energies);
187 if (!entries.count(
"azimuthal")) {
188 throw std::invalid_argument(
"azimuthal field was not found");
190 file.openData(
"azimuthal");
191 std::vector<double> azimuthal;
192 file.getData(azimuthal);
195 if (!entries.count(
"azimuthal_width")) {
196 throw std::invalid_argument(
"azimuthal_width field was not found");
198 file.openData(
"azimuthal_width");
199 std::vector<double> azimuthal_width;
200 file.getData(azimuthal_width);
203 if (!entries.count(
"polar")) {
204 throw std::invalid_argument(
"polar field was not found");
206 file.openData(
"polar");
207 std::vector<double> polar;
211 if (!entries.count(
"polar_width")) {
212 throw std::invalid_argument(
"polar_width field was not found");
214 file.openData(
"polar_width");
215 std::vector<double> polar_width;
216 file.getData(polar_width);
220 std::vector<double> distance;
221 if (entries.count(
"distance")) {
222 file.openData(
"distance");
223 file.getData(distance);
229 file.openGroup(
"instrument",
"NXinstrument");
230 entries = file.getEntries();
231 std::string instrument_name;
232 if (entries.count(
"name")) {
233 file.openData(
"name");
234 instrument_name = file.getStrData();
243 if ((
error.size() != data.size()) || (azimuthal.size() != numSpectra) || (azimuthal_width.size() != numSpectra) ||
244 (polar.size() != numSpectra) || (polar_width.size() != numSpectra) ||
245 ((energies.size() != numBins) && (energies.size() != numBins + 1))) {
246 throw std::invalid_argument(
"incompatible sizes of fields in the NXSPE file");
252 outputWS->getAxis(0)->unit() = UnitFactory::Instance().create(
"DeltaE");
253 outputWS->setYUnit(
"SpectraNumber");
258 outputWS->mutableRun().addLogData(
264 outputWS->mutableRun().setGoniometer(gm,
true);
270 source->
setPos(0.0, 0.0, -10.);
271 instrument->add(source);
272 instrument->markAsSource(source);
274 instrument->add(sample);
275 instrument->markAsSamplePos(sample);
277 constexpr double deg2rad = M_PI / 180.0;
279 for (std::size_t i = 0; i < numSpectra; ++i) {
281 if (!distance.empty()) {
286 pos.
spherical(r, polar.at(i), azimuthal.at(i));
289 r * sin(std::min(std::min(std::abs(polar_width.at(i)), std::abs(azimuthal_width.at(i))), 2.0) *
deg2rad / 2);
296 instrument->add(det);
297 instrument->markAsDetector(det);
299 outputWS->setInstrument(instrument);
301 std::vector<double>::iterator itdata = data.begin(), iterror =
error.begin(), itdataend, iterrorend;
302 auto &spectrumInfo = outputWS->mutableSpectrumInfo();
304 BinEdges edges(std::move(energies));
305 for (std::size_t i = 0; i < numSpectra; ++i) {
306 itdataend = itdata + numBins;
307 iterrorend = iterror + numBins;
308 outputWS->getSpectrum(i).setDetectorID(
static_cast<detid_t>(i + 1));
309 outputWS->setBinEdges(i, edges);
310 if ((!std::isfinite(*itdata)) || (*itdata <= -1e10))
312 spectrumInfo.setMasked(i,
true);
314 outputWS->mutableY(i).assign(itdata, itdataend);
315 outputWS->mutableE(i).assign(iterror, iterrorend);
317 itdata = (itdataend);
318 iterror = (iterrorend);
324 if (!instrument_name.empty() && instrument_name !=
"NXSPE") {
326 std::string instrument_parfile = IDF_filename.substr(0, IDF_filename.find(
"_Definition")) +
"_Parameters.xml";
327 if (std::filesystem::exists(instrument_parfile)) {
330 loadParamAlg->setProperty(
"Filename", instrument_parfile);
331 loadParamAlg->setProperty(
"Workspace", outputWS);
332 loadParamAlg->execute();
339 outputWS->setDistribution(
true);