Mantid
Loading...
Searching...
No Matches
ORNLDataArchive.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 +
7//----------------------------------------------------------------------
8// Includes
9//----------------------------------------------------------------------
10#include <sstream>
11
18#include "MantidKernel/Logger.h"
19
20#include <boost/regex.hpp>
21
22using Mantid::Catalog::Exception::CatalogError;
23using Mantid::Catalog::ONCat::ONCat;
24using Mantid::Catalog::ONCat::ONCat_uptr;
25using Mantid::Catalog::ONCat::ONCatEntity;
26using Mantid::Catalog::ONCat::QueryParameter;
27using Mantid::Catalog::ONCat::QueryParameters;
28
29namespace {
30
31std::string toUpperCase(const std::string &s) {
32 std::string result(s);
33 std::transform(s.begin(), s.end(), result.begin(), toupper);
34 return result;
35}
36
37const static boost::regex FILE_REGEX("^(.*?)_(\\d+).*$");
38const static std::string NOT_FOUND("");
39
40Mantid::Kernel::Logger g_log("ORNLDataArchive");
41} // namespace
42
43namespace Mantid::DataHandling {
44
45DECLARE_ARCHIVESEARCH(ORNLDataArchive, ORNLDataSearch)
46DECLARE_ARCHIVESEARCH(ORNLDataArchive, SNSDataSearch)
47
48
95const API::Result<std::filesystem::path>
96ORNLDataArchive::getArchivePath(const std::set<std::string> &basenames,
97 const std::vector<std::string> &suffixes) const {
98 if (basenames.size() == 0) {
99 return API::Result<std::filesystem::path>(NOT_FOUND, "Not found.");
100 }
101
102 // Mimic previous functionality by only using the first basename.
103 const auto basename = *basenames.cbegin();
104
105 // Validate and parse the basename.
106 boost::smatch result;
107 if (!boost::regex_match(basename, result, FILE_REGEX)) {
108 g_log.debug() << "Unexpected input passed to getArchivePath():" << std::endl << basename << std::endl;
109 return API::Result<std::filesystem::path>(NOT_FOUND, "Not found.");
110 ;
111 }
112
113 assert(result.size() == 3);
114 const std::string instrument = toUpperCase(result[1]);
115 const std::string run = result[2];
116
117 const auto &config = Mantid::Kernel::ConfigService::Instance();
118 std::string facility;
119 try {
120 facility = config.getInstrument(instrument).facility().name();
121
122 if (facility != "HFIR" && facility != "SNS") {
123 return API::Result<std::filesystem::path>(NOT_FOUND, "Not found.");
124 }
126 g_log.debug() << "\"" << instrument << "\" is not an instrument known to Mantid." << std::endl;
127 return API::Result<std::filesystem::path>(NOT_FOUND, "Not found.");
128 }
129
130 // Note that we will only be asking for raw files with the given instrument
131 // and run number, and *not* filtering by suffix at this point. (ONCat has
132 // a strict definition of what a file "extension" is, and has no way of
133 // filtering by, for example, "_event.nxs".)
134 const QueryParameters params{{"facility", facility},
135 {"instrument", instrument},
136 {"projection", "location"},
137 {"tags", "type/raw"},
138 {"sort_by", "ingested"},
139 {"sort_direction", "DESCENDING"},
140 {"ranges_q", "indexed.run_number:" + run}};
141
142 // If we've not manually set up an ONCat instance (presumably for testing
143 // purposes) then we must instead create one using the settings in the
144 // currently-running instance of Mantid, making sure to run it in an
145 // "unauthenticated" mode. If we were to authenticate we'd be able to see
146 // more information, but that would require users logging in and publically
147 // available information is more than enough for our purposes here, anyway.
148 auto defaultOncat = ONCat::fromMantidSettings();
149 auto *oncat = m_oncat ? m_oncat.get() : defaultOncat.get();
150
151 const auto datafiles = [&]() {
152 try {
153 return oncat->list("api", "datafiles", params);
154 } catch (CatalogError &ce) {
155 g_log.debug() << "Error while calling ONCat:" << std::endl << ce.what() << std::endl;
156 return std::vector<ONCatEntity>();
157 }
158 }();
159
160 if (datafiles.size() == 0) {
161 g_log.debug() << "ONCat does not know the location of run \"" << run << "\" for \"" << instrument << "\"."
162 << std::endl;
163 return API::Result<std::filesystem::path>(NOT_FOUND, "Not found.");
164 }
165
166 g_log.debug() << "All datafiles returned from ONCat:" << std::endl;
167 for (const auto &datafile : datafiles) {
168 g_log.debug() << datafile.toString() << std::endl;
169 }
170
171 // It's technically possible to have been given multiple locations for a
172 // single run, since runs are occasionally written out to the wrong IPTS and
173 // therefore need to be "re-translated", leaving us with duplicates in the
174 // catalog. Duplicates require manual intervention to be removed, and so in
175 // the meantime, since we have asked for locations to be returned to us in
176 // descending order of the time at which they were ingested, we can take the
177 // first one and be (quite) sure we end up with the correct run location.
178 const auto location = *datafiles.cbegin()->get<std::string>("location");
179
180 // Mimic the previous ICAT-calling functionality by taking "full"
181 // suffixes into account.
182 for (const auto &suffix : suffixes) {
183 const std::string fullSuffix = basename + suffix;
184 if (toUpperCase(location).ends_with(toUpperCase(fullSuffix))) {
185 return API::Result<std::filesystem::path>(location);
186 }
187 }
188
189 if (toUpperCase(location).ends_with(toUpperCase(basename))) {
190 return API::Result<std::filesystem::path>(location);
191 }
192
193 return API::Result<std::filesystem::path>(NOT_FOUND, "Not found.");
194}
195
196void ORNLDataArchive::setONCat(ONCat_uptr oncat) { m_oncat = std::move(oncat); }
197
198} // namespace Mantid::DataHandling
#define DECLARE_ARCHIVESEARCH(classname, facility)
const API::Result< std::filesystem::path > getArchivePath(const std::set< std::string > &hintstrs, const std::vector< std::string > &suffixes) const override
Exception for when an item is not found in a collection.
Definition Exception.h:145
The Logger class is in charge of the publishing messages from the framework through various channels.
Definition Logger.h:51
void debug(const std::string &msg)
Logs at debug level.
Definition Logger.cpp:145
Kernel::Logger g_log("ExperimentInfo")
static logger object
Kernel::Logger g_log("DetermineSpinStateOrder")