Skip to content
Snippets Groups Projects
GetAllEi.cpp 47.3 KiB
Newer Older
  *
  * @param t_beg -- initial time for current time interval
  * @param t_end -- final time for current time interval
  * @param inSelection -- the boolean indicating if previous interval
  *                       was selected on input and current selected on 
  *                       output
  * @param startTime -- total selection time start moment
  * @param endTime   -- total selection time final moments
  *
  *@return true if selection interval is completed 
  *        (current interval is not selected) and false otherwise
  */
  bool SelectInterval(const Kernel::DateAndTime &t_beg, 
    const Kernel::DateAndTime &t_end,
    double value, bool &inSelection,
    Kernel::DateAndTime &startTime,  Kernel::DateAndTime &endTime){

      if (value > 0) {
        if (!inSelection) {
          startTime = t_beg;
        }
        inSelection = true;
      } else {
        if (inSelection) {
          inSelection = false;
          if (endTime > startTime)
            return true;
        }
      }
      endTime = t_end;
      return false;
  };
}
/**Analyze chopper logs and identify chopper speed and delay
@param  inputWS    -- sp to workspace with attached logs.
@param chop_speed -- output value for chopper speed in uSec
@param chop_delay -- output value for chopper delay in uSec
*/
void GetAllEi::findChopSpeedAndDelay(const API::MatrixWorkspace_sptr &inputWS,
                                     double &chop_speed, double &chop_delay) {

  // TODO: Make it dependent on inputWS time range

  std::vector<Kernel::SplittingInterval> splitter;
  if (m_pFilterLog) {
    std::unique_ptr<Kernel::TimeSeriesProperty<double>> pDerivative;

    // Define selecting function
    bool inSelection(false);
    // time interval to select (start-end)
    Kernel::DateAndTime startTime, endTime;
    //
    // Analyze filtering log
    auto dateAndTimes = m_pFilterLog->valueAsCorrectMap();
    auto it = dateAndTimes.begin();
    auto next = it;
    next++;
    std::map<Kernel::DateAndTime, double> derivMap;
    auto itder = it;
    if (m_FilterWithDerivative) {
      pDerivative = m_pFilterLog->getDerivative();
      derivMap = pDerivative->valueAsCorrectMap();
      itder = derivMap.begin();
    }

    // initialize selection log
    if (dateAndTimes.size() <= 1) {
      SelectInterval(it->first, it->first, itder->second,
                     inSelection,startTime,endTime);
      if (inSelection) {
        startTime = inputWS->run().startTime();
        endTime = inputWS->run().endTime();
        Kernel::SplittingInterval interval(startTime, endTime, 0);
        splitter.push_back(interval);
      } else {
        throw std::runtime_error("filtered all data points. Nothing to do");
      SelectInterval(it->first, next->first, itder->second,
                     inSelection,startTime,endTime);
    }

    // if its filtered using log, both iterator walk through the same values
    // if use derivative, derivative's values are used for filtering
    // and derivative assumed in a center of an interval
    for (; next != dateAndTimes.end(); ++next, ++itder) {
      if (SelectInterval(it->first, next->first, itder->second,
                         inSelection,startTime,endTime)) {
        Kernel::SplittingInterval interval(startTime, endTime, 0);
        splitter.push_back(interval);
      }
      it = next;
    }
    // final interval
    if (inSelection && (endTime > startTime)) {
      Kernel::SplittingInterval interval(startTime, endTime, 0);
      splitter.push_back(interval);
    }
  } // End of USE filter log.

  chop_speed = this->getAvrgLogValue(inputWS, "ChopperSpeedLog", splitter);
  chop_speed = std::fabs(chop_speed);
  if (chop_speed < 1.e-7) {
    throw std::runtime_error("Chopper speed can not be zero ");
  }
  chop_delay =
      std::fabs(this->getAvrgLogValue(inputWS, "ChopperDelayLog", splitter));

  // process chopper delay in the units of degree (phase)
  auto pProperty = getPLogForProperty(inputWS, "ChopperDelayLog");
  if (!pProperty)
    throw std::runtime_error("ChopperDelayLog has been removed from workspace "
                             "during the algorithm execution");
  std::string units = pProperty->units();
  // its chopper phase provided
  if (units == "deg" || units.c_str()[0] == -80) { //<- userd in ISIS ASCII representation of o(deg)
    chop_delay *= 1.e+6 / (360. * chop_speed); // convert in uSec
  }
  chop_delay += m_phase / chop_speed;
}

namespace { // namespace for lambda functions, used in validators
/* former Lambda to validate if appropriate log is present in workspace
and if it's present, it is a time-series property
* @param prop_name    -- the name of the log to check
* @param err_presence -- core error message to return if no log found
* @param err_type     -- core error message to return if
*                        log is of incorrect type
* @param fail         -- fail or warn if appropriate log is not available.
*
* @param result       -- map to add the result of check for errors
*                       if no error found the map is not modified and remains
*                       empty.
* @return             -- false if all checks are fine, or true if check is
*                        failed
*/
bool check_time_series_property(
    const GetAllEi *algo, const API::MatrixWorkspace_sptr &inputWS,
    const boost::shared_ptr<const Geometry::IComponent> &chopper,
    const std::string &prop_name, const std::string &err_presence,
    const std::string &err_type, bool fail,
    std::map<std::string, std::string> &result) {

  std::string LogName = algo->getProperty(prop_name);
  if (boost::iequals(LogName, "Defined in IDF")) {
    try {
      auto theLogs = chopper->getStringParameter(prop_name);
      if (theLogs.size() == 0) {
        if (fail)
          result[prop_name] = "Can not retrieve parameter " + prop_name +
                              " from the instrument definition file.";
        return true;
      }
      LogName = theLogs[0];
    } catch (...) {
      result[prop_name] = "Can not retrieve parameter " + prop_name +
                          " from the instrument definition file.";
      return true;
    }
  }
  try {
    Kernel::Property *pProp = inputWS->run().getProperty(LogName);
    auto pTSProp = dynamic_cast<Kernel::TimeSeriesProperty<double> *>(pProp);
    if (!pTSProp) {
      if (fail)
        result[prop_name] = "Workspace contains " + err_type + LogName +
                            " But its type is not a timeSeries property";
      return true;
    }
  } catch (std::runtime_error &) {
    if (fail)
      result[prop_name] = "Workspace has to contain " + err_presence + LogName;
    return true;
  }
  return false;
};
/**Validates if input workspace contains all necessary logs and if all
*  these logs are the logs of appropriate type
@return list of invalid logs or empty list if no errors is found.
*/
std::map<std::string, std::string> GetAllEi::validateInputs() {

  // Do Validation
  std::map<std::string, std::string> result;

  API::MatrixWorkspace_sptr inputWS = getProperty("Workspace");
  if (!inputWS) {
    result["Workspace"] = "Input workspace can not be identified";
    return result;
  }
  if (!inputWS->isHistogramData()) {
    result["Workspace"] = "Only histogram workspaces are currently supported. "
                          "Rebin input workspace first.";
  }

  specid_t specNum1 = getProperty("Monitor1SpecID");
  try {
    inputWS->getIndexFromSpectrumNumber(specNum1);
  } catch (std::runtime_error &) {
    result["Monitor1SpecID"] =
        "Input workspace does not contain spectra with ID: " +
        boost::lexical_cast<std::string>(specNum1);
  }
  specid_t specNum2 = getProperty("Monitor2SpecID");
  try {
    inputWS->getIndexFromSpectrumNumber(specNum2);
  } catch (std::runtime_error &) {
    result["Monitor2SpecID"] =
        "Input workspace does not contain spectra with ID: " +
        boost::lexical_cast<std::string>(specNum2);
  }
  // check chopper and initiate it if present (for debugging)
Alex Buts's avatar
Alex Buts committed
  m_chopper = inputWS->getInstrument()->getComponentByName("chopper-position");
    result["Workspace_chopper"] =
        " For this algorithm to work workspace has"
        " to contain well defined 'chopper-position' component";
    return result;
  }

  check_time_series_property(this, inputWS, m_chopper, "ChopperSpeedLog",
                             "chopper speed log with name: ",
                             "chopper speed log ", true, result);
  check_time_series_property(
      this, inputWS, m_chopper, "ChopperDelayLog",
      "property related to chopper delay log with name: ", "chopper delay log ",
      true, result);
  bool failed = check_time_series_property(
      this, inputWS, m_chopper, "FilterBaseLog", "filter base log named: ",
      "filter base log: ", false, result);
  if (failed) {
    g_log.warning()
        << " Can not find a log to identify good DAE operations.\n"
           " Assuming that good operations start from experiment time=0";
  } else {
    this->setFilterLog(inputWS);
  }
  return result;
}

} // namespace Algorithms
} // namespace Mantid