Skip to content
Snippets Groups Projects
LoadRawHelper.cpp 52.1 KiB
Newer Older
    specnum_t &monitorwsSpecs) {
  if (!m_interval && !m_bmspeclist) {
    monitorwsSpecs = static_cast<specnum_t>(monitorSpecList.size());
    normalwsSpecs = m_total_specs - monitorwsSpecs;
    g_log.debug()
        << "normalwsSpecs   when m_interval  & m_bmspeclist are  false is  "
        << normalwsSpecs << "  monitorwsSpecs is " << monitorwsSpecs << '\n';
  } else if (m_interval || m_bmspeclist) {
    if (m_interval) {
      int msize = 0;
      std::vector<specnum_t>::const_iterator itr1;
      for (itr1 = monitorSpecList.begin(); itr1 != monitorSpecList.end();
           ++itr1) {
        if (*itr1 >= m_spec_min && *itr1 < m_spec_max)
          ++msize;
      monitorwsSpecs = msize;
      normalwsSpecs = m_total_specs - monitorwsSpecs;
      g_log.debug() << "normalwsSpecs when  m_interval true is  "
                    << normalwsSpecs << "  monitorwsSpecs is " << monitorwsSpecs
    if (m_bmspeclist) {
      if (m_interval) {
        std::vector<specnum_t>::iterator itr;
        for (itr = m_spec_list.begin();
             itr != m_spec_list.end();) { // if  the m_spec_list elements are in
                                          // the range between m_spec_min &
                                          // m_spec_max
          if (*itr >= m_spec_min && *itr < m_spec_max)
            itr = m_spec_list.erase(itr);
          else
            ++itr;
          g_log.debug() << "normalwsSpecs is " << normalwsSpecs
                        << "  monitorwsSpecs is " << monitorwsSpecs << '\n';
        } else { // at this point there are monitors in the list which are not
                 // in the min& max range
          // so find those  monitors  count and calculate the workspace specs
          std::vector<specnum_t>::const_iterator itr;
          std::vector<specnum_t>::const_iterator monitr;
          specnum_t monCounter = 0;
          for (itr = m_spec_list.begin(); itr != m_spec_list.end(); ++itr) {
            monitr = find(monitorSpecList.begin(), monitorSpecList.end(), *itr);
            if (monitr != monitorSpecList.end())
              ++monCounter;
          monitorwsSpecs += monCounter;
          normalwsSpecs = m_total_specs - monitorwsSpecs;
          g_log.debug() << "normalwsSpecs is  " << normalwsSpecs
                        << "  monitorwsSpecs is " << monitorwsSpecs << '\n';
      }      // end if loop for m_interval
      else { // if only List true
        specnum_t mSize = 0;
        std::vector<specnum_t>::const_iterator itr;
        std::vector<specnum_t>::const_iterator monitr;
        for (itr = m_spec_list.begin(); itr != m_spec_list.end(); ++itr) {
          monitr = find(monitorSpecList.begin(), monitorSpecList.end(), *itr);
          if (monitr != monitorSpecList.end()) {
            ++mSize;
        monitorwsSpecs = mSize;
        normalwsSpecs = m_total_specs - monitorwsSpecs;
    } // end of if loop for m_bmspeclist
  }
}

void LoadRawHelper::loadSpectra(
    FILE *file, const int &period, const int &total_specs,
    DataObjects::Workspace2D_sptr ws_sptr,
    std::vector<boost::shared_ptr<MantidVec>> timeChannelsVec) {
  double progStart = m_prog;
  double progEnd = 1.0; // Assume this function is called last

  int64_t histCurrent = -1;
  int64_t wsIndex = 0;
  int64_t numberOfPeriods = static_cast<int64_t>(isisRaw->t_nper);
  double histTotal = static_cast<double>(total_specs * numberOfPeriods);
  int64_t noTimeRegimes = getNumberofTimeRegimes();
  int64_t lengthIn = static_cast<int64_t>(isisRaw->t_ntc1 + 1);

  const int64_t periodTimesNSpectraP1 =
      period * (static_cast<int64_t>(m_numberOfSpectra) + 1);
  // loop through spectra
  for (specnum_t i = 1; i <= m_numberOfSpectra; ++i) {
    int64_t histToRead = i + periodTimesNSpectraP1;
    if ((i >= m_spec_min && i < m_spec_max) ||
        (m_list &&
         find(m_spec_list.begin(), m_spec_list.end(), i) !=
             m_spec_list.end())) {
      progress(m_prog, "Reading raw file data...");

      // read spectrum from raw file
      if (!readData(file, histToRead))
        throw std::runtime_error("Error reading raw file, in "
                                 "LoadRawHelper::loadSpectra, readData failed");
      // set workspace data
      setWorkspaceData(ws_sptr, timeChannelsVec, wsIndex, i, noTimeRegimes,
                       lengthIn, 1);
      ++wsIndex;

      if (numberOfPeriods == 1) {
        if (++histCurrent % 100 == 0) {
          m_prog = progStart +
                   (progEnd - progStart) *
                       (static_cast<double>(histCurrent) / histTotal);
        interruption_point();
    } else {
      skipData(file, histToRead);
  }
}

/**
 * Return the confidence with with this algorithm can load the file
 * @param descriptor A descriptor for the file
 * @returns An integer specifying the confidence level. 0 indicates it will not
 * be used
 */
int LoadRawHelper::confidence(Kernel::FileDescriptor &descriptor) const {
  auto &stream = descriptor.data();
  // 85th character is a space & 89th character is a ~
  stream.seekg(84, std::ios::beg);
  int c = stream.get();
  int confidence(0);
  if (c == 32) {
    stream.seekg(3, std::ios::cur);
    int c = stream.get();
    if (c == 126)
      confidence = 80;
  }
  return confidence;
}

/**
 * Searches for log files related to RAW file loaded using LoadLog algorithm.
 * @param pathToRawFile The path and name of the raw file.
 * @returns A set containing paths to log files related to RAW file used.
 */
std::list<std::string>
LoadRawHelper::searchForLogFiles(const std::string &pathToRawFile) {
  // If pathToRawFile is the filename of a raw datafile then search for
  // potential log files
  // in the directory of this raw datafile. Otherwise check if it is a potential
  // log file. Add the filename of these potential log files to:
  // potentialLogFiles.
  std::set<std::string> potentialLogFiles;
  // Using a list instead of a set to preserve order. The three column names
  // will
  // be added to the end of the list. This means if a column exists in the two
  // and three column file then it will be overridden correctly.
  std::list<std::string> potentialLogFilesList;

  // File property checks whether the given path exists, just check that is
  // actually a file
  Poco::File l_path(pathToRawFile);
  if (l_path.isDirectory()) {
    g_log.error("In LoadLog: " + pathToRawFile +
                " must be a filename not a directory.");
    throw Exception::FileError("Filename is a directory:", pathToRawFile);
  }

  // start the process or populating potential log files into the container:
  // potentialLogFiles
  std::string l_filenamePart =
      Poco::Path(l_path.path()).getFileName(); // get filename part only
  if (isAscii(pathToRawFile) &&
      l_filenamePart.rfind('_') != std::string::npos) {
    // then we will assume that the file is an ISIS log file
    potentialLogFiles.insert(pathToRawFile);
  } else {
    // then we will assume that the file is an ISIS raw file. The file validator
    // will have warned the user if the extension is not one of the suggested
    // ones.

    // strip out the raw data file identifier
    std::string l_rawID("");
    size_t idx = l_filenamePart.rfind('.');

    if (idx != std::string::npos) {
      l_rawID = l_filenamePart.substr(0, l_filenamePart.rfind('.'));
    } else {
      l_rawID = l_filenamePart;
    /// check for alternate data stream exists for raw file
    /// if exists open the stream and read  log files name  from ADS
    if (adsExists(pathToRawFile)) {
      potentialLogFiles = getLogFilenamesfromADS(pathToRawFile);
    } else {
      // look for log files in the directory of the raw datafile
      std::string pattern(l_rawID + "_*.txt");
      Poco::Path dir(pathToRawFile);
      dir.makeParent();

      try {
        Kernel::Glob::glob(Poco::Path(dir).resolve(pattern), potentialLogFiles);
      } catch (std::exception &) {

    // push potential log files from set to list.
    potentialLogFilesList.insert(potentialLogFilesList.begin(),
                                 potentialLogFiles.begin(),
                                 potentialLogFiles.end());
    // Remove extension from path, and append .log to path.
    std::string logName =
        pathToRawFile.substr(0, pathToRawFile.rfind('.')) + ".log";
    // Check if log file exists in current directory.
    std::ifstream fileExists(logName.c_str());
    if (fileExists) {
      // Push three column filename to end of list.
      potentialLogFilesList.insert(potentialLogFilesList.end(), logName);
  }
  return (potentialLogFilesList);
}

/**
 * This method looks for ADS with name checksum exists
 * @param pathToFile The path and name of the file.
 * @return True if ADS stream checksum exists
 */
bool LoadRawHelper::adsExists(const std::string &pathToFile) {
#ifdef _WIN32
  std::string adsname(pathToFile + ":checksum");
  std::ifstream adstream(adsname.c_str());
  if (!adstream) {
    return false;
  }
  adstream.close();
  return true;
#else
  UNUSED_ARG(pathToFile);
  return (false);
#endif
}

/**
 * This method reads the checksum ADS associated with the raw file and returns
 * the filenames of the log files
 * @param pathToRawFile The path and name of the raw file.
 * @return list of logfile names.
 */
std::set<std::string>
LoadRawHelper::getLogFilenamesfromADS(const std::string &pathToRawFile) {
  std::string adsname(pathToRawFile + ":checksum");
  std::ifstream adstream(adsname.c_str());
  if (!adstream) {
    return (std::set<std::string>());
  }

  std::string str;
  std::string path;
  std::string logFile;
  std::set<std::string> logfilesList;
  Poco::Path logpath(pathToRawFile);
  size_t pos = pathToRawFile.find_last_of('/');
  if (pos == std::string::npos) {
    pos = pathToRawFile.find_last_of('\\');
  }
  if (pos != std::string::npos) {
    path = pathToRawFile.substr(0, pos);
  }
  while (Mantid::Kernel::Strings::extractToEOL(adstream, str)) {
    std::string fileName;
    if (pos == std::string::npos)
      continue;
    fileName = str.substr(pos + 1, str.length() - pos);
    pos = fileName.find("txt");
    if (pos == std::string::npos)
      continue;
    logFile = path + "/" + fileName;
    if (logFile.empty())
      continue;
    logfilesList.insert(logFile);
  }
  return (logfilesList);
}

/**
 * Checks whether filename is a simple text file
 * @param filename :: The filename to inspect
 * @returns true if the filename has the .txt extension
 */
bool LoadRawHelper::isAscii(const std::string &filename) {
  FILE *file = fopen(filename.c_str(), "rb");
  char data[256];
  size_t n = fread(data, 1, sizeof(data), file);
  fclose(file);
  char *pend = &data[n];
  // Call it a binary file if we find a non-ascii character in the first 256
  // bytes of the file.
  for (char *p = data; p < pend; ++p) {
    unsigned long ch = static_cast<unsigned long>(*p);
    if (!(ch <= 0x7F)) {
      return false;
  }
  return true;
}

/** This method checks the value of LoadMonitors property and returns true or
 * false
 *  @return true if Exclude Monitors option is selected,otherwise false
 */
bool LoadRawHelper::isExcludeMonitors(const std::string &monitorOption) {
  bool bExclude;
  monitorOption.compare("Exclude") ? (bExclude = false) : (bExclude = true);
  return bExclude;
}

/**This method checks the value of LoadMonitors property and returns true or
 * false
 * @return true if Include Monitors option is selected,otherwise false
 */
bool LoadRawHelper::isIncludeMonitors(const std::string &monitorOption) {
  bool bExclude;
  monitorOption.compare("Include") ? (bExclude = false) : (bExclude = true);

  return bExclude;
}

/** This method checks the value of LoadMonitors property and returns true or
 * false
 *  @return true if Separate Monitors option is selected,otherwise false
 */
bool LoadRawHelper::isSeparateMonitors(const std::string &monitorOption) {
  bool bSeparate;
  monitorOption.compare("Separate") ? (bSeparate = false) : (bSeparate = true);
  return bSeparate;
}
/**The method to interpret LoadMonitors property options and convert then into
 * boolean values
 * @param bincludeMonitors  :: if monitors requested to be included with
 * workspace
 * @param bseparateMonitors :: if monitors requested to be loaded separately
 * from the workspace
 * @param bexcludeMonitors  :: if monitors should not be loaded at all.
 * @param pAlgo             :: pointer to the algorithm, which has LoadMonitors
 * property.
 */
void LoadRawHelper::ProcessLoadMonitorOptions(bool &bincludeMonitors,
                                              bool &bseparateMonitors,
                                              bool &bexcludeMonitors,
                                              API::Algorithm *pAlgo) {
  // process monitor option
  std::string monitorOption = pAlgo->getProperty("LoadMonitors");
  if (monitorOption == "1")
    monitorOption = "Separate";
  if (monitorOption == "0")
    monitorOption = "Exclude";

  bincludeMonitors = LoadRawHelper::isIncludeMonitors(monitorOption);
  bseparateMonitors = false;
  bexcludeMonitors = false;
  if (!bincludeMonitors) {
    bseparateMonitors = LoadRawHelper::isSeparateMonitors(monitorOption);
    bexcludeMonitors = LoadRawHelper::isExcludeMonitors(monitorOption);
  }
  //
}

} // namespace DataHandling