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