Skip to content
Snippets Groups Projects
ParallelEventLoader.cpp 2.97 KiB
Newer Older
#include "MantidDataHandling/ParallelEventLoader.h"
#include "MantidDataObjects/EventWorkspace.h"
#include "MantidGeometry/Instrument.h"
#include "MantidGeometry/Instrument/ComponentInfo.h"
#include "MantidGeometry/Instrument/DetectorInfo.h"
#include "MantidParallel/IO/EventLoader.h"
#include "MantidTypes/Event/TofEvent.h"

namespace Mantid {
namespace DataHandling {

std::vector<int32_t> bankOffsets(const API::ExperimentInfo &ws,
                                 const std::vector<std::string> &bankNames) {
  const auto instrument = ws.getInstrument();
  const auto &compInfo = ws.componentInfo();
  const auto &detInfo = ws.detectorInfo();
  const auto &detIDs = detInfo.detectorIDs();

  // Monitors are not loaded by LoadEventNexus, so we have to exclude them when
  // computing an offset based on detector IDs. Currently this is computed in a
  // naive way and works only if all monitors have IDs smaller than any
  // detector.
  const auto monitors = instrument->getMonitors();
  int32_t monitorOffset = static_cast<int32_t>(monitors.size());
  for (size_t i = 0; i < monitors.size(); ++i)
    if (monitors[i] != detIDs[i])
      throw std::runtime_error(
          "Monitors are not corresponding to the first detector IDs in the "
          "instrument. This is currently not supported by ParallelEventLoader");

  std::vector<int32_t> bankOffsets;
  for (const auto &bankName : bankNames) {
    // Removing "_events" from bankName
    auto bank =
        instrument->getComponentByName(bankName.substr(0, bankName.size() - 7));
    if (bank) {
      const auto &detectors =
          compInfo.detectorsInSubtree(compInfo.indexOf(bank->getComponentID()));
      const size_t detIndex = detectors.front();
      bankOffsets.push_back(detIDs[detIndex] - static_cast<int32_t>(detIndex) +
                            monitorOffset);
      if ((detIDs[detectors.back()] - detIDs[detectors.front()]) !=
          static_cast<int32_t>(detectors.size()) - 1)
        throw std::runtime_error("Detector ID range in bank is not contiguous. "
                                 "Cannot use ParallelEventLoader.");
    } else {
      throw std::runtime_error(
          "ParallelEventLoader: Bank " + bankName +
          " not found. Cannot determine detector ID offset.");
    }
  }
  return bankOffsets;
}

void ParallelEventLoader::load(DataObjects::EventWorkspace &ws,
                               const std::string &filename,
                               const std::string &groupName,
                               const std::vector<std::string> &bankNames) {
  const size_t size = ws.getNumberHistograms();
  std::vector<std::vector<Types::Event::TofEvent> *> eventLists(size, nullptr);
  for (size_t i = 0; i < size; ++i)
    DataObjects::getEventsFrom(ws.getSpectrum(i), eventLists[i]);

  Parallel::IO::EventLoader::load(filename, groupName, bankNames,
                                  bankOffsets(ws, bankNames),
                                  std::move(eventLists));
}

} // namespace DataHandling
} // namespace Mantid