Esempio n. 1
0
/// Get the source slit size from the slit information of the run properties
void EQSANSLoad::getSourceSlitSize()
{
  if (!dataWS->run().hasProperty("vBeamSlit"))
  {
    m_output_message += "   Could not determine source aperture diameter: ";
    m_output_message += "slit parameters were not found in the run log\n";
    return;
  }

  Mantid::Kernel::Property* prop = dataWS->run().getProperty("vBeamSlit");
  Mantid::Kernel::TimeSeriesProperty<double>* dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop);
  int slit1 = (int)dp->getStatistics().mean;

  prop = dataWS->run().getProperty("vBeamSlit2");
  dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop);
  int slit2 = (int)dp->getStatistics().mean;

  prop = dataWS->run().getProperty("vBeamSlit3");
  dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop);
  int slit3 = (int)dp->getStatistics().mean;

  if (slit1<0 && slit2<0 && slit3<0)
  {
    m_output_message += "   Could not determine source aperture diameter\n";
    return;
  }

  // Default slit size
  double S1 = 20.0;
  double L1 = -1.0;
  const double ssd = fabs(dataWS->getInstrument()->getSource()->getPos().Z())*1000.0;
  int slits[3] = {slit1, slit2, slit3};
  for (int i=0; i<3; i++)
  {
    int m = slits[i]-1;
    if (m>=0 && m<6)
    {
      double x = m_slit_positions[i][m];
      double y = ssd - m_slit_to_source[i];
      if (L1<0 || x/y<S1/L1)
      {
        L1 = y;
        S1 = x;
      }
    }
  }
  dataWS->mutableRun().addProperty("source-aperture-diameter", S1, "mm", true);
  m_output_message += "   Source aperture diameter: ";
  Poco::NumberFormatter::append(m_output_message, S1, 1);
  m_output_message += " mm\n";
}
Esempio n. 2
0
double RefReduction::calculateAngleREFL(MatrixWorkspace_sptr workspace)
{
  Mantid::Kernel::Property* prop = workspace->run().getProperty("ths");
  Mantid::Kernel::TimeSeriesProperty<double>* dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop);
  const double ths = dp->getStatistics().mean;

  prop = workspace->run().getProperty("tthd");
  dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop);
  const double tthd = dp->getStatistics().mean;

  double offset = getProperty("AngleOffset");
  if (isEmpty(offset)) offset = 0.0;
  return tthd - ths + offset;
}
Esempio n. 3
0
/**
 * Extract the first good frame of a workspace
 * @param ws :: a workspace
 * @returns the date and time of the first good frame
 */
DateAndTime
ChangeTimeZero::getStartTimeFromWorkspace(API::MatrixWorkspace_sptr ws) const {
  auto run = ws->run();
  // Check for the first good frame in the log
  Mantid::Kernel::TimeSeriesProperty<double> *goodFrame = NULL;
  try {
    goodFrame = run.getTimeSeriesProperty<double>("proton_charge");
  } catch (std::invalid_argument) {
    throw std::invalid_argument("ChangeTimeZero: The log needs a proton_charge "
                                "time series to determine the zero time.");
  }

  DateAndTime startTime;
  if (goodFrame->size() > 0) {
    startTime = goodFrame->firstTime();
  }

  return startTime;
}
Esempio n. 4
0
double RefReduction::calculateAngleREFM(MatrixWorkspace_sptr workspace)
{
  double dangle = getProperty("DetectorAngle");
  if (isEmpty(dangle))
  {
    Mantid::Kernel::Property* prop = workspace->run().getProperty("DANGLE");
    Mantid::Kernel::TimeSeriesProperty<double>* dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop);
    dangle = dp->getStatistics().mean;
  }

  double dangle0 = getProperty("DetectorAngle0");
  if (isEmpty(dangle0))
  {
    Mantid::Kernel::Property* prop = workspace->run().getProperty("DANGLE0");
    Mantid::Kernel::TimeSeriesProperty<double>* dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop);
    dangle0 = dp->getStatistics().mean;
  }

  Mantid::Kernel::Property* prop = workspace->run().getProperty("SampleDetDis");
  Mantid::Kernel::TimeSeriesProperty<double>* dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop);
  const double det_distance = dp->getStatistics().mean/1000.0;

  double direct_beam_pix = getProperty("DirectPixel");
  if (isEmpty(direct_beam_pix))
  {
    Mantid::Kernel::Property* prop = workspace->run().getProperty("DIRPIX");
    Mantid::Kernel::TimeSeriesProperty<double>* dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop);
    direct_beam_pix = dp->getStatistics().mean;
  }

  double ref_pix = getProperty("ReflectivityPixel");
  if (ref_pix==0 || isEmpty(ref_pix))
  {
    const std::vector<int> peakRange = getProperty("SignalPeakPixelRange");
    if (peakRange.size()<2) {
      g_log.error() << "SignalPeakPixelRange parameter should be a vector of two values" << std::endl;
      throw std::invalid_argument("SignalPeakPixelRange parameter should be a vector of two values");
    }
    ref_pix = (peakRange[0] + peakRange[1])/2.0;
  }

  double theta = (dangle-dangle0)*M_PI/180.0/2.0
      + ((direct_beam_pix-ref_pix)*PIXEL_SIZE)/ (2.0*det_distance);

  return theta*180.0/M_PI;
}
Esempio n. 5
0
    /**
     * reads the .log stream and creates timeseries property and sets that to the run object
     * @param logFileStream :: The stream of the log file (data).
     * @param logFileName :: The name of the log file to load.
     * @param run :: The run information object
     */
    void LoadLog::loadThreeColumnLogFile(std::ifstream& logFileStream, std::string logFileName, API::Run& run)
    {
      std::string str;
      std::string propname;
      Mantid::Kernel::TimeSeriesProperty<double>* logd = 0;
      Mantid::Kernel::TimeSeriesProperty<std::string>* logs = 0;
      std::map<std::string,Kernel::TimeSeriesProperty<double>*> dMap;
      std::map<std::string,Kernel::TimeSeriesProperty<std::string>*> sMap;
      typedef std::pair<std::string,Kernel::TimeSeriesProperty<double>* > dpair;
      typedef std::pair<std::string,Kernel::TimeSeriesProperty<std::string>* > spair;
      kind l_kind(LoadLog::empty);
      bool isNumeric(false);

      if (!logFileStream)
      {
        throw std::invalid_argument("Unable to open file " + m_filename);
      }

      while(Mantid::Kernel::Strings::extractToEOL(logFileStream,str))
      {
        if ( !isDateTimeString(str) )
        {
          throw std::invalid_argument("File" + logFileName + " is not a standard ISIS log file. Expected to be a file starting with DateTime String format.");
        }

        if (!Kernel::TimeSeriesProperty<double>::isTimeString(str) || (str[0]=='#'))
        {    //if the line doesn't start with a time read the next line
          continue;
        }

        std::stringstream line(str);
        std::string timecolumn;
        line >> timecolumn;

        std::string blockcolumn;
        line >> blockcolumn;
        l_kind = classify(blockcolumn);

        if ( LoadLog::string != l_kind )
        {
          throw std::invalid_argument("ISIS log file contains unrecognised second column entries:" + logFileName);
        }

        std::string valuecolumn;
        line >> valuecolumn;
        l_kind = classify(valuecolumn);

        if ( LoadLog::string != l_kind && LoadLog::number != l_kind)
        {
          continue; //no value defined, just skip this entry
        }

        // column two in .log file is called block column
        propname = stringToLower(blockcolumn);
        //check if the data is numeric
        std::istringstream istr(valuecolumn);
        double dvalue;
        istr >> dvalue;
        isNumeric = !istr.fail();

        if (isNumeric)
        {
          std::map<std::string,Kernel::TimeSeriesProperty<double>*>::iterator ditr = dMap.find(propname);
          if(ditr != dMap.end())
          {
            Kernel::TimeSeriesProperty<double>* prop = ditr->second;
            if (prop) prop->addValue(timecolumn,dvalue);
          }
          else
          {
            logd = new Kernel::TimeSeriesProperty<double>(propname);
            logd->addValue(timecolumn,dvalue);
            dMap.insert(dpair(propname,logd));
          }
        }
        else
        {
          std::map<std::string,Kernel::TimeSeriesProperty<std::string>*>::iterator sitr = sMap.find(propname);
          if(sitr != sMap.end())
          {
            Kernel::TimeSeriesProperty<std::string>* prop = sitr->second;
            if (prop) prop->addValue(timecolumn,valuecolumn);
          }
          else
          {
            logs = new Kernel::TimeSeriesProperty<std::string>(propname);
            logs->addValue(timecolumn,valuecolumn);
            sMap.insert(spair(propname,logs));
          }
        }
      }
      try
      {
        std::map<std::string,Kernel::TimeSeriesProperty<double>*>::const_iterator itr = dMap.begin();
        for(;itr != dMap.end(); ++itr)
        {
          run.addLogData(itr->second);
        }
        std::map<std::string,Kernel::TimeSeriesProperty<std::string>*>::const_iterator sitr = sMap.begin();
        for(;sitr!=sMap.end();++sitr)
        {
          run.addLogData(sitr->second);
        }
      }
      catch(std::invalid_argument &e)
      {
        g_log.warning() << e.what();
      }
      catch(Exception::ExistsError&e)
      {
        g_log.warning() << e.what();
      }
    }
Esempio n. 6
0
IEventWorkspace_sptr RefReduction::loadData(const std::string dataRun,
    const std::string polarization)
{
  const std::string instrument = getProperty("Instrument");

  // Check whether dataRun refers to an existing workspace
  // Create a good name for the raw workspace
  std::string ws_name = "__ref_"+dataRun+"-"+polarization+"_raw";
  IEventWorkspace_sptr rawWS;
  if (AnalysisDataService::Instance().doesExist(dataRun))
  {
    rawWS = AnalysisDataService::Instance().retrieveWS<EventWorkspace>(dataRun);
    g_log.notice() << "Found workspace: " << dataRun << std::endl;
    m_output_message += "    |Input data run is a workspace: " + dataRun + "\n";
  }
  else if (AnalysisDataService::Instance().doesExist(ws_name))
  {
    rawWS = AnalysisDataService::Instance().retrieveWS<EventWorkspace>(ws_name);
    g_log.notice() << "Using existing workspace: " << ws_name << std::endl;
    m_output_message += "    |Found workspace from previous reduction: " + ws_name + "\n";
  }
  else
  {
    // If we can't find a workspace, find a file to load
    std::string path = FileFinder::Instance().getFullPath(dataRun);

    if (path.size()==0 || !Poco::File(path).exists())
    {
      try
      {
        std::vector<std::string> paths = FileFinder::Instance().findRuns(instrument+dataRun);
        path = paths[0];
      }
      catch(Exception::NotFoundError&) { /* Pass. We report the missing file later. */ }
    }

    if (path.size()==0 || !Poco::File(path).exists())
    {
      try
      {
        std::vector<std::string> paths = FileFinder::Instance().findRuns(dataRun);
        path = paths[0];
      }
      catch(Exception::NotFoundError&) { /* Pass. We report the missing file later. */ }
    }

    if (Poco::File(path).exists()) {
      g_log.notice() << "Found: " << path << std::endl;
      m_output_message += "    |Loading from " + path + "\n";
      IAlgorithm_sptr loadAlg = createChildAlgorithm("LoadEventNexus", 0, 0.2);
      loadAlg->setProperty("Filename", path);
      if (polarization.compare(PolStateNone)!=0)
        loadAlg->setProperty("NXentryName", polarization);
      loadAlg->executeAsChildAlg();
      rawWS = loadAlg->getProperty("OutputWorkspace");
      if (rawWS->getNumberEvents()==0)
      {
        g_log.notice() << "No data in " << polarization << std::endl;
        m_output_message += "    |No data for " + polarization + "\n";
        return rawWS;
      }

      // Move the detector to the right position
      if (instrument.compare("REF_M")==0)
      {
          double det_distance = rawWS->getInstrument()->getDetector(0)->getPos().Z();
          Mantid::Kernel::Property* prop = rawWS->run().getProperty("SampleDetDis");
          Mantid::Kernel::TimeSeriesProperty<double>* dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop);
          double sdd = dp->getStatistics().mean/1000.0;
          IAlgorithm_sptr mvAlg = createChildAlgorithm("MoveInstrumentComponent", 0.2, 0.25);
          mvAlg->setProperty<MatrixWorkspace_sptr>("Workspace", rawWS);
          mvAlg->setProperty("ComponentName", "detector1");
          mvAlg->setProperty("Z", sdd-det_distance);
          mvAlg->setProperty("RelativePosition", true);
          mvAlg->executeAsChildAlg();
          g_log.notice() << "Ensuring correct Z position: Correction = "
              << Poco::NumberFormatter::format(sdd-det_distance)
              << " m" << std::endl;
      }
      AnalysisDataService::Instance().addOrReplace(ws_name, rawWS);
    } else {
        g_log.error() << "Could not find a data file for " << dataRun << std::endl;
        throw std::invalid_argument("Could not find a data file for the given input");
    }
  }

  // Crop TOF as needed and set binning
  double tofMin = getProperty("TOFMin");
  double tofMax = getProperty("TOFMax");
  if (isEmpty(tofMin) || isEmpty(tofMax))
  {
    const MantidVec& x = rawWS->readX(0);
    if (isEmpty(tofMin)) tofMin = *std::min_element(x.begin(), x.end());
    if (isEmpty(tofMax)) tofMax = *std::max_element(x.begin(), x.end());
  }

  int nBins = getProperty("NBins");
  double tofStep = getProperty("TOFStep");
  if (!isEmpty(nBins))
    tofStep = (tofMax-tofMin)/nBins;
  else
    nBins = (int)floor( (tofMax-tofMin)/tofStep );

  std::vector<double> params;
  params.push_back(tofMin);
  params.push_back(tofStep);
  params.push_back(tofMax);

  IAlgorithm_sptr rebinAlg = createChildAlgorithm("Rebin", 0.25, 0.3);
  rebinAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", rawWS);
  rebinAlg->setProperty("Params", params);
  rebinAlg->setProperty("PreserveEvents", true);
  rebinAlg->executeAsChildAlg();
  MatrixWorkspace_sptr outputWS = rebinAlg->getProperty("OutputWorkspace");
  m_output_message += "    |TOF binning: "
      +  Poco::NumberFormatter::format(tofMin) + " to "
      +  Poco::NumberFormatter::format(tofMax) + " in steps of "
      +  Poco::NumberFormatter::format(tofStep) + " microsecs\n";

  // Normalise by current
  IAlgorithm_sptr normAlg = createChildAlgorithm("NormaliseByCurrent", 0.3, 0.35);
  normAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", outputWS);
  //normAlg->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", outputWS);
  normAlg->executeAsChildAlg();
  outputWS = normAlg->getProperty("OutputWorkspace");

  // Convert to wavelength
  IAlgorithm_sptr convAlg = createChildAlgorithm("ConvertUnits", 0.35, 0.4);
  convAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", outputWS);
  convAlg->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", outputWS);
  convAlg->setProperty("Target", "Wavelength");
  convAlg->executeAsChildAlg();

  // Rebin in wavelength
  const MantidVec& x = outputWS->readX(0);
  double wlMin = *std::min_element(x.begin(), x.end());
  double wlMax = *std::max_element(x.begin(), x.end());

  std::vector<double> wl_params;
  wl_params.push_back(wlMin);
  wl_params.push_back((wlMax-wlMin)/nBins);
  wl_params.push_back(wlMax);

  IAlgorithm_sptr rebinAlg2 = createChildAlgorithm("Rebin", 0.25, 0.3);
  rebinAlg2->setProperty<MatrixWorkspace_sptr>("InputWorkspace", outputWS);
  rebinAlg2->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", outputWS);
  rebinAlg2->setProperty("Params", wl_params);
  rebinAlg2->setProperty("PreserveEvents", true);
  rebinAlg2->executeAsChildAlg();

  IEventWorkspace_sptr outputEvtWS = boost::dynamic_pointer_cast<IEventWorkspace>(outputWS);
  return outputEvtWS;
}
Esempio n. 7
0
void EQSANSLoad::exec() {
  // Verify the validity of the inputs
  // TODO: this should be done by the new data management algorithm used for
  // live data reduction (when it's implemented...)
  const std::string fileName = getPropertyValue("Filename");
  EventWorkspace_sptr inputEventWS = getProperty("InputWorkspace");
  if (fileName.size() == 0 && !inputEventWS) {
    g_log.error() << "EQSANSLoad input error: Either a valid file path or an "
                     "input workspace must be provided\n";
    throw std::runtime_error("EQSANSLoad input error: Either a valid file path "
                             "or an input workspace must be provided");
  } else if (fileName.size() > 0 && inputEventWS) {
    g_log.error() << "EQSANSLoad input error: Either a valid file path or an "
                     "input workspace must be provided, but not both\n";
    throw std::runtime_error("EQSANSLoad input error: Either a valid file path "
                             "or an input workspace must be provided, but not "
                             "both");
  }

  // Read in default TOF cuts
  const bool skipTOFCorrection = getProperty("SkipTOFCorrection");
  m_low_TOF_cut = getProperty("LowTOFCut");
  m_high_TOF_cut = getProperty("HighTOFCut");

  // Read in default beam center
  m_center_x = getProperty("BeamCenterX");
  m_center_y = getProperty("BeamCenterY");
  const bool noBeamCenter = getProperty("NoBeamCenter");

  // Reduction property manager
  const std::string reductionManagerName = getProperty("ReductionProperties");
  boost::shared_ptr<PropertyManager> reductionManager;
  if (PropertyManagerDataService::Instance().doesExist(reductionManagerName)) {
    reductionManager =
        PropertyManagerDataService::Instance().retrieve(reductionManagerName);
  } else {
    reductionManager = boost::make_shared<PropertyManager>();
    PropertyManagerDataService::Instance().addOrReplace(reductionManagerName,
                                                        reductionManager);
  }

  if (!reductionManager->existsProperty("LoadAlgorithm")) {
    auto loadProp = make_unique<AlgorithmProperty>("LoadAlgorithm");
    setPropertyValue("InputWorkspace", "");
    setProperty("NoBeamCenter", false);
    loadProp->setValue(toString());
    reductionManager->declareProperty(std::move(loadProp));
  }

  if (!reductionManager->existsProperty("InstrumentName")) {
    reductionManager->declareProperty(
        make_unique<PropertyWithValue<std::string>>("InstrumentName",
                                                    "EQSANS"));
  }

  // Output log
  m_output_message = "";

  // Check whether we need to load the data
  if (!inputEventWS) {
    const bool loadMonitors = getProperty("LoadMonitors");
    IAlgorithm_sptr loadAlg = createChildAlgorithm("LoadEventNexus", 0, 0.2);
    loadAlg->setProperty("LoadMonitors", loadMonitors);
    loadAlg->setProperty("MonitorsAsEvents", false);
    loadAlg->setProperty("Filename", fileName);
    if (skipTOFCorrection) {
      if (m_low_TOF_cut > 0.0)
        loadAlg->setProperty("FilterByTofMin", m_low_TOF_cut);
      if (m_high_TOF_cut > 0.0)
        loadAlg->setProperty("FilterByTofMax", m_high_TOF_cut);
    }
    loadAlg->execute();
    Workspace_sptr dataWS_asWks = loadAlg->getProperty("OutputWorkspace");
    dataWS = boost::dynamic_pointer_cast<MatrixWorkspace>(dataWS_asWks);

    // Get monitor workspace as necessary
    std::string mon_wsname = getPropertyValue("OutputWorkspace") + "_monitors";
    if (loadMonitors && loadAlg->existsProperty("MonitorWorkspace")) {
      Workspace_sptr monWSOutput = loadAlg->getProperty("MonitorWorkspace");
      MatrixWorkspace_sptr monWS =
          boost::dynamic_pointer_cast<MatrixWorkspace>(monWSOutput);
      if ((monWSOutput) && (!monWS)) {
        // this was a group workspace - EQSansLoad does not support multi period
        // data yet
        throw Exception::NotImplementedError("The file contains multi period "
                                             "data, support for this is not "
                                             "implemented in EQSANSLoad yet");
      }
      declareProperty(Kernel::make_unique<WorkspaceProperty<>>(
                          "MonitorWorkspace", mon_wsname, Direction::Output),
                      "Monitors from the Event NeXus file");
      setProperty("MonitorWorkspace", monWS);
    }
  } else {
    MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace");
    EventWorkspace_sptr outputEventWS =
        boost::dynamic_pointer_cast<EventWorkspace>(outputWS);
    if (inputEventWS != outputEventWS) {
      IAlgorithm_sptr copyAlg = createChildAlgorithm("CloneWorkspace", 0, 0.2);
      copyAlg->setProperty("InputWorkspace", inputEventWS);
      copyAlg->executeAsChildAlg();
      Workspace_sptr dataWS_asWks = copyAlg->getProperty("OutputWorkspace");
      dataWS = boost::dynamic_pointer_cast<MatrixWorkspace>(dataWS_asWks);
    } else {
      dataWS = boost::dynamic_pointer_cast<MatrixWorkspace>(inputEventWS);
    }
  }

  // Get the sample-detector distance
  double sdd = 0.0;
  const double sample_det_dist = getProperty("SampleDetectorDistance");
  if (!isEmpty(sample_det_dist)) {
    sdd = sample_det_dist;
  } else {
    if (!dataWS->run().hasProperty("detectorZ")) {
      g_log.error()
          << "Could not determine Z position: the "
             "SampleDetectorDistance property was not set "
             "and the run logs do not contain the detectorZ property\n";
      throw std::invalid_argument(
          "Could not determine Z position: stopping execution");
    }

    const std::string dzName = "detectorZ";
    Mantid::Kernel::Property *prop = dataWS->run().getProperty(dzName);
    Mantid::Kernel::TimeSeriesProperty<double> *dp =
        dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double> *>(prop);
    if (!dp) {
      throw std::runtime_error("Could not cast (interpret) the property " +
                               dzName + " as a time series property value.");
    }
    sdd = dp->getStatistics().mean;

    // Modify SDD according to offset if given
    const double sample_det_offset =
        getProperty("SampleDetectorDistanceOffset");
    if (!isEmpty(sample_det_offset)) {
      sdd += sample_det_offset;
    }
  }
  dataWS->mutableRun().addProperty("sample_detector_distance", sdd, "mm", true);

  // Move the detector to its correct position
  IAlgorithm_sptr mvAlg =
      createChildAlgorithm("MoveInstrumentComponent", 0.2, 0.4);
  mvAlg->setProperty<MatrixWorkspace_sptr>("Workspace", dataWS);
  mvAlg->setProperty("ComponentName", "detector1");
  mvAlg->setProperty("Z", sdd / 1000.0);
  mvAlg->setProperty("RelativePosition", false);
  mvAlg->executeAsChildAlg();
  g_log.information() << "Moving detector to " << sdd / 1000.0 << " meters\n";
  m_output_message += "   Detector position: " +
                      Poco::NumberFormatter::format(sdd / 1000.0, 3) + " m\n";

  // Get the run number so we can find the proper config file
  int run_number = 0;
  std::string config_file = "";
  if (dataWS->run().hasProperty("run_number")) {
    const std::string run_str =
        dataWS->run().getPropertyValueAsType<std::string>("run_number");
    Poco::NumberParser::tryParse(run_str, run_number);
    // Find a proper config file
    config_file = findConfigFile(run_number);
  } else {
    g_log.error() << "Could not find run number for workspace "
                  << getPropertyValue("OutputWorkspace") << '\n';
    m_output_message += "   Could not find run number for data file\n";
  }

  // Process the config file
  bool use_config = getProperty("UseConfig");
  if (use_config && config_file.size() > 0) {
    // Special case to force reading the beam center from the config file
    // We're adding this to be compatible with the original EQSANS load
    // written in python
    if (m_center_x == 0.0 && m_center_y == 0.0) {
      setProperty("UseConfigBeam", true);
    }

    readConfigFile(config_file);
  } else if (use_config) {
    use_config = false;
    g_log.error() << "Cound not find config file for workspace "
                  << getPropertyValue("OutputWorkspace") << '\n';
    m_output_message += "   Could not find configuration file for run " +
                        Poco::NumberFormatter::format(run_number) + "\n";
  }

  // If we use the config file, move the moderator position
  if (use_config) {
    if (m_moderator_position > -13.0)
      g_log.error()
          << "Moderator position seems close to the sample, please check\n";
    g_log.information() << "Moving moderator to " << m_moderator_position
                        << '\n';
    m_output_message += "   Moderator position: " +
                        Poco::NumberFormatter::format(m_moderator_position) +
                        " m\n";
    mvAlg = createChildAlgorithm("MoveInstrumentComponent", 0.4, 0.45);
    mvAlg->setProperty<MatrixWorkspace_sptr>("Workspace", dataWS);
    mvAlg->setProperty("ComponentName", "moderator");
    mvAlg->setProperty("Z", m_moderator_position);
    mvAlg->setProperty("RelativePosition", false);
    mvAlg->executeAsChildAlg();
  }

  // Get source aperture radius
  getSourceSlitSize();

  // Move the beam center to its proper position
  if (!noBeamCenter) {
    if (isEmpty(m_center_x) || isEmpty(m_center_y)) {
      if (reductionManager->existsProperty("LatestBeamCenterX") &&
          reductionManager->existsProperty("LatestBeamCenterY")) {
        m_center_x = reductionManager->getProperty("LatestBeamCenterX");
        m_center_y = reductionManager->getProperty("LatestBeamCenterY");
      }
    }
    moveToBeamCenter();

    // Add beam center to reduction properties, as the last beam center position
    // that was used.
    // This will give us our default position next time.
    if (!reductionManager->existsProperty("LatestBeamCenterX"))
      reductionManager->declareProperty(make_unique<PropertyWithValue<double>>(
          "LatestBeamCenterX", m_center_x));
    else
      reductionManager->setProperty("LatestBeamCenterX", m_center_x);
    if (!reductionManager->existsProperty("LatestBeamCenterY"))
      reductionManager->declareProperty(make_unique<PropertyWithValue<double>>(
          "LatestBeamCenterY", m_center_y));
    else
      reductionManager->setProperty("LatestBeamCenterY", m_center_y);
  }

  // Modify TOF
  const bool correct_for_flight_path = getProperty("CorrectForFlightPath");
  double wl_min = 0.0;
  double wl_max = 0.0;
  double wl_combined_max = 0.0;
  if (skipTOFCorrection) {
    m_output_message +=
        "    Skipping EQSANS TOF correction: assuming a single frame\n";
    dataWS->mutableRun().addProperty("is_frame_skipping", 0, true);
    if (correct_for_flight_path) {
      g_log.error() << "CorrectForFlightPath and SkipTOFCorrection can't be "
                       "set to true at the same time\n";
      m_output_message += "    Skipped flight path correction: see error log\n";
    }
  } else {
    m_output_message += "   Flight path correction ";
    if (!correct_for_flight_path)
      m_output_message += "NOT ";
    m_output_message += "applied\n";
    DataObjects::EventWorkspace_sptr dataWS_evt =
        boost::dynamic_pointer_cast<EventWorkspace>(dataWS);
    IAlgorithm_sptr tofAlg =
        createChildAlgorithm("EQSANSTofStructure", 0.5, 0.7);
    tofAlg->setProperty<EventWorkspace_sptr>("InputWorkspace", dataWS_evt);
    tofAlg->setProperty("LowTOFCut", m_low_TOF_cut);
    tofAlg->setProperty("HighTOFCut", m_high_TOF_cut);
    tofAlg->setProperty("FlightPathCorrection", correct_for_flight_path);
    tofAlg->executeAsChildAlg();
    wl_min = tofAlg->getProperty("WavelengthMin");
    wl_max = tofAlg->getProperty("WavelengthMax");
    if (wl_min != wl_min || wl_max != wl_max) {
      g_log.error() << "Bad wavelength range\n";
      g_log.error() << m_output_message << '\n';
    }

    const bool frame_skipping = tofAlg->getProperty("FrameSkipping");
    dataWS->mutableRun().addProperty("wavelength_min", wl_min, "Angstrom",
                                     true);
    dataWS->mutableRun().addProperty("wavelength_max", wl_max, "Angstrom",
                                     true);
    dataWS->mutableRun().addProperty("is_frame_skipping", int(frame_skipping),
                                     true);
    wl_combined_max = wl_max;
    m_output_message += "   Wavelength range: " +
                        Poco::NumberFormatter::format(wl_min) + " - " +
                        Poco::NumberFormatter::format(wl_max);
    if (frame_skipping) {
      const double wl_min2 = tofAlg->getProperty("WavelengthMinFrame2");
      const double wl_max2 = tofAlg->getProperty("WavelengthMaxFrame2");
      wl_combined_max = wl_max2;
      dataWS->mutableRun().addProperty("wavelength_min_frame2", wl_min2,
                                       "Angstrom", true);
      dataWS->mutableRun().addProperty("wavelength_max_frame2", wl_max2,
                                       "Angstrom", true);
      m_output_message += " and " + Poco::NumberFormatter::format(wl_min2) +
                          " - " + Poco::NumberFormatter::format(wl_max2) +
                          " Angstrom\n";
    } else
      m_output_message += " Angstrom\n";
  }

  // Convert to wavelength
  const double ssd =
      fabs(dataWS->getInstrument()->getSource()->getPos().Z()) * 1000.0;
  const double conversion_factor = 3.9560346 / (sdd + ssd);
  m_output_message += "   TOF to wavelength conversion factor: " +
                      Poco::NumberFormatter::format(conversion_factor) + "\n";

  if (skipTOFCorrection) {
    DataObjects::EventWorkspace_sptr dataWS_evt =
        boost::dynamic_pointer_cast<EventWorkspace>(dataWS);
    if (dataWS_evt->getNumberEvents() == 0)
      throw std::invalid_argument("No event to process: check your TOF cuts");
    wl_min = dataWS_evt->getTofMin() * conversion_factor;
    wl_max = dataWS_evt->getTofMax() * conversion_factor;
    wl_combined_max = wl_max;
    g_log.information() << "Wavelength range: " << wl_min << " to " << wl_max
                        << '\n';
    dataWS->mutableRun().addProperty("wavelength_min", wl_min, "Angstrom",
                                     true);
    dataWS->mutableRun().addProperty("wavelength_max", wl_max, "Angstrom",
                                     true);
  }

  IAlgorithm_sptr scAlg = createChildAlgorithm("ScaleX", 0.7, 0.71);
  scAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", dataWS);
  scAlg->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", dataWS);
  scAlg->setProperty("Factor", conversion_factor);
  scAlg->executeAsChildAlg();
  dataWS->getAxis(0)->setUnit("Wavelength");

  // Rebin so all the wavelength bins are aligned
  const bool preserveEvents = getProperty("PreserveEvents");
  const double wl_step = getProperty("WavelengthStep");

  const double wl_min_rounded = round(wl_min * 100.0) / 100.0;
  const double wl_max_rounded = round(wl_combined_max * 100.0) / 100.0;
  std::string params = Poco::NumberFormatter::format(wl_min_rounded, 2) + "," +
                       Poco::NumberFormatter::format(wl_step) + "," +
                       Poco::NumberFormatter::format(wl_max_rounded, 2);
  g_log.information() << "Rebin parameters: " << params << '\n';
  IAlgorithm_sptr rebinAlg = createChildAlgorithm("Rebin", 0.71, 0.72);
  rebinAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", dataWS);
  if (preserveEvents)
    rebinAlg->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", dataWS);
  rebinAlg->setPropertyValue("Params", params);
  rebinAlg->setProperty("PreserveEvents", preserveEvents);
  rebinAlg->executeAsChildAlg();

  if (!preserveEvents)
    dataWS = rebinAlg->getProperty("OutputWorkspace");

  dataWS->mutableRun().addProperty("event_ws",
                                   getPropertyValue("OutputWorkspace"), true);
  setProperty<MatrixWorkspace_sptr>(
      "OutputWorkspace", boost::dynamic_pointer_cast<MatrixWorkspace>(dataWS));
  // m_output_message = "Loaded " + fileName + '\n' + m_output_message;
  setPropertyValue("OutputMessage", m_output_message);
}
Esempio n. 8
0
void EQSANSLoad::exec()
{
  // Read in default TOF cuts
  m_low_TOF_cut = getProperty("LowTOFCut");
  m_high_TOF_cut = getProperty("HighTOFCut");

  // Read in default beam center
  m_center_x = getProperty("BeamCenterX");
  m_center_y = getProperty("BeamCenterY");

  TableWorkspace_sptr reductionTable = getProperty("ReductionTableWorkspace");
  ReductionTableHandler reductionHandler(reductionTable);
  if (!reductionTable)
  {
    const std::string reductionTableName = getPropertyValue("ReductionTableWorkspace");
    if (reductionTableName.size()>0) setProperty("ReductionTableWorkspace", reductionHandler.getTable());
  }
  if (reductionHandler.findStringEntry("LoadAlgorithm").size()==0)
    reductionHandler.addEntry("LoadAlgorithm", toString());

  const std::string fileName = getPropertyValue("Filename");

  // Output log
  m_output_message = "";

  IAlgorithm_sptr loadAlg = createSubAlgorithm("LoadEventNexus", 0, 0.2);
  loadAlg->setProperty("Filename", fileName);
  loadAlg->executeAsSubAlg();
  IEventWorkspace_sptr dataWS_tmp = loadAlg->getProperty("OutputWorkspace");
  dataWS = boost::dynamic_pointer_cast<MatrixWorkspace>(dataWS_tmp);

  // Get the sample-detector distance
  double sdd = 0.0;
  const double sample_det_dist = getProperty("SampleDetectorDistance");
  if (!isEmpty(sample_det_dist))
  {
    sdd = sample_det_dist;
  } else {
    Mantid::Kernel::Property* prop = dataWS->run().getProperty("detectorZ");
    Mantid::Kernel::TimeSeriesProperty<double>* dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop);
    sdd = dp->getStatistics().mean;

    // Modify SDD according to offset if given
    const double sample_det_offset = getProperty("SampleDetectorDistanceOffset");
    if (!isEmpty(sample_det_offset))
    {
      sdd += sample_det_offset;
    }
  }
  dataWS->mutableRun().addProperty("sample_detector_distance", sdd, "mm", true);

  // Move the detector to its correct position
  IAlgorithm_sptr mvAlg = createSubAlgorithm("MoveInstrumentComponent", 0.2, 0.4);
  mvAlg->setProperty<MatrixWorkspace_sptr>("Workspace", dataWS);
  mvAlg->setProperty("ComponentName", "detector1");
  mvAlg->setProperty("Z", sdd/1000.0);
  mvAlg->setProperty("RelativePosition", false);
  mvAlg->executeAsSubAlg();
  g_log.information() << "Moving detector to " << sdd/1000.0 << std::endl;
  m_output_message += "   Detector position: " + Poco::NumberFormatter::format(sdd/1000.0, 3) + " m\n";

  // Get the run number so we can find the proper config file
  int run_number = 0;
  std::string config_file = "";
  if (dataWS->run().hasProperty("run_number"))
  {
    Mantid::Kernel::Property* prop = dataWS->run().getProperty("run_number");
    Mantid::Kernel::PropertyWithValue<std::string>* dp = dynamic_cast<Mantid::Kernel::PropertyWithValue<std::string>* >(prop);
    const std::string run_str = *dp;
    Poco::NumberParser::tryParse(run_str, run_number);
    // Find a proper config file
    config_file = findConfigFile(run_number);
  } else {
    g_log.error() << "Could not find run number for workspace " << getPropertyValue("OutputWorkspace") << std::endl;
    m_output_message += "   Could not find run number for data file\n";
  }

  // Process the config file
  bool use_config = getProperty("UseConfig");
  if (use_config && config_file.size()>0)
  {
    readConfigFile(config_file);
  } else if (use_config) {
    use_config = false;
    g_log.error() << "Cound not find config file for workspace " << getPropertyValue("OutputWorkspace") << std::endl;
    m_output_message += "   Could not find configuration file for run " + Poco::NumberFormatter::format(run_number) + "\n";
  }

  // If we use the config file, move the moderator position
  if (use_config)
  {
      if (m_moderator_position > -13.0)
        g_log.error() << "Moderator position seems close to the sample, please check" << std::endl;
      g_log.information() << "Moving moderator to " << m_moderator_position << std::endl;
      m_output_message += "   Moderator position: " + Poco::NumberFormatter::format(m_moderator_position, 3) + " m\n";
      mvAlg = createSubAlgorithm("MoveInstrumentComponent", 0.4, 0.45);
      mvAlg->setProperty<MatrixWorkspace_sptr>("Workspace", dataWS);
      mvAlg->setProperty("ComponentName", "moderator");
      mvAlg->setProperty("Z", m_moderator_position);
      mvAlg->setProperty("RelativePosition", false);
      mvAlg->executeAsSubAlg();
  }

  // Get source aperture radius
  getSourceSlitSize();

  // Move the beam center to its proper position
  moveToBeamCenter();

  // Modify TOF
  bool correct_for_flight_path = getProperty("CorrectForFlightPath");
  m_output_message += "   Flight path correction ";
  if (!correct_for_flight_path) m_output_message += "NOT ";
  m_output_message += "applied\n";
  DataObjects::EventWorkspace_sptr dataWS_evt = boost::dynamic_pointer_cast<EventWorkspace>(dataWS_tmp);
  IAlgorithm_sptr tofAlg = createSubAlgorithm("EQSANSTofStructure", 0.5, 0.7);
  tofAlg->setProperty<EventWorkspace_sptr>("InputWorkspace", dataWS_evt);
  tofAlg->setProperty("LowTOFCut", m_low_TOF_cut);
  tofAlg->setProperty("HighTOFCut", m_high_TOF_cut);
  tofAlg->setProperty("FlightPathCorrection", correct_for_flight_path);
  tofAlg->executeAsSubAlg();
  const double wl_min = tofAlg->getProperty("WavelengthMin");
  const double wl_max = tofAlg->getProperty("WavelengthMax");
  const bool frame_skipping = tofAlg->getProperty("FrameSkipping");
  dataWS->mutableRun().addProperty("wavelength_min", wl_min, "Angstrom", true);
  dataWS->mutableRun().addProperty("wavelength_max", wl_max, "Angstrom", true);
  dataWS->mutableRun().addProperty("is_frame_skipping", int(frame_skipping), true);
  double wl_combined_max = wl_max;
  m_output_message += "   Wavelength range: " + Poco::NumberFormatter::format(wl_min, 1)
      + " - " + Poco::NumberFormatter::format(wl_max, 1);
  if (frame_skipping)
  {
    const double wl_min2 = tofAlg->getProperty("WavelengthMinFrame2");
    const double wl_max2 = tofAlg->getProperty("WavelengthMaxFrame2");
    wl_combined_max = wl_max2;
    dataWS->mutableRun().addProperty("wavelength_min_frame2", wl_min2, "Angstrom", true);
    dataWS->mutableRun().addProperty("wavelength_max_frame2", wl_max2, "Angstrom", true);
    m_output_message += " and " + Poco::NumberFormatter::format(wl_min2, 1)
        + " - " + Poco::NumberFormatter::format(wl_max2, 1) + " Angstrom\n";
  } else
    m_output_message += " Angstrom\n";

  // Convert to wavelength
  const double ssd = fabs(dataWS->getInstrument()->getSource()->getPos().Z())*1000.0;
  const double conversion_factor = 3.9560346 / (sdd+ssd);
  m_output_message += "   TOF to wavelength conversion factor: " + Poco::NumberFormatter::format(conversion_factor) + "\n";
  IAlgorithm_sptr scAlg = createSubAlgorithm("ScaleX", 0.7, 0.71);
  scAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", dataWS);
  scAlg->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", dataWS);
  scAlg->setProperty("Factor", conversion_factor);
  scAlg->executeAsSubAlg();
  dataWS->getAxis(0)->setUnit("Wavelength");

  // Rebin so all the wavelength bins are aligned
  const bool preserveEvents = getProperty("PreserveEvents");
  std::string params = Poco::NumberFormatter::format(wl_min, 2)
      + ",0.1," + Poco::NumberFormatter::format(wl_combined_max, 2);
  IAlgorithm_sptr rebinAlg = createSubAlgorithm("Rebin", 0.71, 0.72);
  rebinAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", dataWS);
  if (preserveEvents) rebinAlg->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", dataWS);
  rebinAlg->setPropertyValue("Params", params);
  rebinAlg->setProperty("PreserveEvents", preserveEvents);
  rebinAlg->executeAsSubAlg();

  if (!preserveEvents) dataWS = rebinAlg->getProperty("OutputWorkspace");

  dataWS->mutableRun().addProperty("event_ws", getPropertyValue("OutputWorkspace"), true);
  setProperty<MatrixWorkspace_sptr>("OutputWorkspace", boost::dynamic_pointer_cast<MatrixWorkspace>(dataWS));
  setPropertyValue("OutputMessage", m_output_message);
}