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