Beispiel #1
0
/** Makes sure that the input properties are set correctly
 *  @param inputWorkspace The input workspace
 */
void NormaliseToMonitor::checkProperties(
    const MatrixWorkspace_sptr &inputWorkspace) {

  // Check where the monitor spectrum should come from
  Property *monSpec = getProperty("MonitorSpectrum");
  MatrixWorkspace_sptr monWS = getProperty("MonitorWorkspace");
  Property *monID = getProperty("MonitorID");
  // Is the monitor spectrum within the main input workspace
  const bool inWS = !monSpec->isDefault();
  m_scanInput = inputWorkspace->detectorInfo().isScanning();
  // Or is it in a separate workspace
  bool sepWS{monWS};
  if (m_scanInput && sepWS)
    throw std::runtime_error("Can not currently use a separate monitor "
                             "workspace with a detector scan input workspace.");
  // or monitor ID
  bool monIDs = !monID->isDefault();
  // something has to be set
  // One and only one of these properties should have been set
  // input from separate workspace is overwritten by monitor spectrum
  if (inWS && sepWS) {
    g_log.information("Both input workspace MonitorSpectrum number and monitor "
                      "workspace are specified. Ignoring Monitor Workspace");
    sepWS = false;
  }
  // input from detector ID is rejected in favor of monitor sp
  if (inWS && monIDs) {
    g_log.information("Both input workspace MonitorSpectrum number and "
                      "detector ID are specified. Ignoring Detector ID");
    monIDs = false;
  }
  // separate ws takes over detectorID (this logic is duplicated within
  // getInWSMonitorSpectrum)
  if (sepWS && monIDs) {
    g_log.information("Both input MonitorWorkspace and detector ID are "
                      "specified. Ignoring Detector ID");
  }

  // Do a check for common binning and store
  m_commonBins = inputWorkspace->isCommonBins();

  // Check the monitor spectrum or workspace and extract into new workspace
  m_monitor = sepWS ? getMonitorWorkspace(inputWorkspace)
                    : getInWSMonitorSpectrum(inputWorkspace);

  // Check that the 'monitor' spectrum actually relates to a monitor - warn if
  // not
  try {
    const auto &monitorSpecInfo = m_monitor->spectrumInfo();
    for (const auto workspaceIndex : m_workspaceIndexes)
      if (!monitorSpecInfo.isMonitor(workspaceIndex))
        g_log.warning() << "The spectrum N: " << workspaceIndex
                        << " in MonitorWorkspace does not refer to a monitor.\n"
                        << "Continuing with normalization regardless.";
  } catch (Kernel::Exception::NotFoundError &e) {
    g_log.warning("Unable to check if the spectrum provided relates to a "
                  "monitor - the instrument is not fully specified.\n "
                  "Continuing with normalization regardless.");
    g_log.warning() << "Error was: " << e.what() << "\n";
    if (m_scanInput)
      throw std::runtime_error("Can not continue, spectrum can not be obtained "
                               "for monitor workspace, but the input workspace "
                               "has a detector scan.");
  }
}
void TOFSANSResolutionByPixel::exec()
{
  MatrixWorkspace_sptr inOutWS = getProperty("InputWorkspace");
  double deltaR = getProperty("DeltaR");
  double R1 = getProperty("SourceApertureRadius");
  double R2 = getProperty("SampleApertureRadius");
  // Convert to meters
  deltaR /= 1000.0;
  R1 /= 1000.0;
  R2 /= 1000.0;
  const double sigmaModeratorMicroSec = getProperty("SigmaModerator");

  const V3D samplePos = inOutWS->getInstrument()->getSample()->getPos();
  const V3D sourcePos = inOutWS->getInstrument()->getSource()->getPos();
  const V3D SSD = samplePos - sourcePos;
  const double L1 = SSD.norm();

  const int numberOfSpectra = static_cast<int>(inOutWS->getNumberHistograms());
  Progress progress(this,0.0,1.0,numberOfSpectra);

  //PARALLEL_FOR1(inOutWS)
  for (int i = 0; i < numberOfSpectra; i++)
  {
    //PARALLEL_START_INTERUPT_REGION
    IDetector_const_sptr det;
    try {
      det = inOutWS->getDetector(i);
    } catch (Exception::NotFoundError&) {
      g_log.information() << "Spectrum index " << i << " has no detector assigned to it - discarding" << std::endl;
      // Catch if no detector. Next line tests whether this happened - test placed
      // outside here because Mac Intel compiler doesn't like 'continue' in a catch
      // in an openmp block.
    }
    // If no detector found or if it's masked or a monitor, skip onto the next spectrum
    if ( !det || det->isMonitor() || det->isMasked() ) continue;

    // Get the flight path from the sample to the detector pixel
    const V3D scatteredFlightPathV3D = det->getPos() - samplePos; 

    const double L2 = scatteredFlightPathV3D.norm();
    const double Lsum = L1+L2;

    // calculate part that is wavelenght independent
    const double dTheta2 = (4.0 * M_PI * M_PI / 12.0) * 
      ( 3.0*R1*R1/(L1*L1) + 3.0*R2*R2*Lsum*Lsum/(L1*L1*L2*L2) + (deltaR*deltaR)/(L2*L2) );

    // Multiplicative factor to go from lambda to Q
    // Don't get fooled by the function name...
    const double theta = inOutWS->detectorTwoTheta(det);
    const double factor = 4.0 * M_PI * sin( theta/2.0 );

    const MantidVec& xIn = inOutWS->readX(i);
    MantidVec& yIn = inOutWS->dataY(i);
    const size_t xLength = xIn.size();

    for ( size_t j = 0; j < xLength-1; j++)
    {
      // Calculate q. Alternatively q could be calculated using ConvertUnit
      const double wl = (xIn[j+1]+xIn[j])/2.0;
      const double q = factor/wl;

      // calculate wavelenght resolution from moderator and histogram time bin width and
      // convert to from unit of micro-seconds to Aangstrom
      const double sigmaLambda = sigmaModeratorMicroSec*3.9560/(1000.0*Lsum);

      // calculate sigmaQ for a given lambda and pixel
      const double sigmaOverLambdaTimesQ = q*sigmaLambda/wl;
      const double sigmaQ = std::sqrt(dTheta2/(wl*wl)+sigmaOverLambdaTimesQ*sigmaOverLambdaTimesQ);

      // update inout workspace with this sigmaQ
      yIn[j] = sigmaQ;
    }

    progress.report("Computing Q resolution");
    //PARALLEL_END_INTERUPT_REGION
  }

}
Beispiel #3
0
/// Execute the algorithm in case of a histogrammed data.
void ExtractSpectra::execHistogram() {
  // Retrieve and validate the input properties
  this->checkProperties();

  // Create the output workspace
  MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create(
      m_inputWorkspace, m_workspaceIndexList.size(), m_maxX - m_minX,
      m_maxX - m_minX - m_histogram);
  outputWorkspace->setIndexInfo(
      Indexing::extract(m_inputWorkspace->indexInfo(), m_workspaceIndexList));

  // If this is a Workspace2D, get the spectra axes for copying in the spectraNo
  // later
  Axis *inAxis1(nullptr);
  TextAxis *outTxtAxis(nullptr);
  NumericAxis *outNumAxis(nullptr);
  if (m_inputWorkspace->axes() > 1) {
    inAxis1 = m_inputWorkspace->getAxis(1);
    auto outAxis1 = outputWorkspace->getAxis(1);
    outTxtAxis = dynamic_cast<TextAxis *>(outAxis1);
    if (!outTxtAxis)
      outNumAxis = dynamic_cast<NumericAxis *>(outAxis1);
  }

  cow_ptr<HistogramData::HistogramX> newX(nullptr);
  if (m_commonBoundaries) {
    auto &oldX = m_inputWorkspace->x(m_workspaceIndexList.front());
    newX = make_cow<HistogramData::HistogramX>(oldX.begin() + m_minX,
                                               oldX.begin() + m_maxX);
  }

  bool doCrop = ((m_minX != 0) || (m_maxX != m_inputWorkspace->x(0).size()));

  Progress prog(this, 0.0, 1.0, (m_workspaceIndexList.size()));
  // Loop over the required workspace indices, copying in the desired bins
  for (int j = 0; j < static_cast<int>(m_workspaceIndexList.size()); ++j) {
    auto i = m_workspaceIndexList[j];

    bool hasDx = m_inputWorkspace->hasDx(i);

    // Preserve/restore sharing if X vectors are the same
    if (m_commonBoundaries) {
      outputWorkspace->setSharedX(j, newX);
      if (hasDx) {
        auto &oldDx = m_inputWorkspace->dx(i);
        outputWorkspace->setSharedDx(
            j,
            make_cow<HistogramData::HistogramDx>(
                oldDx.begin() + m_minX, oldDx.begin() + m_maxX - m_histogram));
      }
    } else {
      // Safe to just copy whole vector 'cos can't be cropping in X if not
      // common
      outputWorkspace->setSharedX(j, m_inputWorkspace->sharedX(i));
      outputWorkspace->setSharedDx(j, m_inputWorkspace->sharedDx(i));
    }

    if (doCrop) {
      auto &oldY = m_inputWorkspace->y(i);
      outputWorkspace->mutableY(j)
          .assign(oldY.begin() + m_minX, oldY.begin() + (m_maxX - m_histogram));
      auto &oldE = m_inputWorkspace->e(i);
      outputWorkspace->mutableE(j)
          .assign(oldE.begin() + m_minX, oldE.begin() + (m_maxX - m_histogram));
    } else {
      outputWorkspace->setSharedY(j, m_inputWorkspace->sharedY(i));
      outputWorkspace->setSharedE(j, m_inputWorkspace->sharedE(i));
    }

    // copy over the axis entry for each spectrum, regardless of the type of
    // axes present
    if (inAxis1) {
      if (outTxtAxis) {
        outTxtAxis->setLabel(j, inAxis1->label(i));
      } else if (outNumAxis) {
        outNumAxis->setValue(j, inAxis1->operator()(i));
      }
      // spectra axis is implicit in workspace creation
    }

    if (!m_commonBoundaries)
      this->cropRagged(outputWorkspace, static_cast<int>(i), j);

    // Propagate bin masking if there is any
    if (m_inputWorkspace->hasMaskedBins(i)) {
      const MatrixWorkspace::MaskList &inputMasks =
          m_inputWorkspace->maskedBins(i);
      MatrixWorkspace::MaskList::const_iterator it;
      for (it = inputMasks.begin(); it != inputMasks.end(); ++it) {
        const size_t maskIndex = (*it).first;
        if (maskIndex >= m_minX && maskIndex < m_maxX - m_histogram)
          outputWorkspace->flagMasked(j, maskIndex - m_minX, (*it).second);
      }
    }
    prog.report();
  }

  setProperty("OutputWorkspace", outputWorkspace);
}
/**  Calculate the integral asymmetry for a workspace (red & green).
*   The calculation is done by MuonAsymmetryCalc and SimpleIntegration algorithms.
*   @param ws_red :: The red workspace
*   @param ws_green :: The green workspace
*   @param Y :: Reference to a variable receiving the value of asymmetry
*   @param E :: Reference to a variable receiving the value of the error
*/
void PlotAsymmetryByLogValue::calcIntAsymmetry(API::MatrixWorkspace_sptr ws_red,
        API::MatrixWorkspace_sptr ws_green,double& Y, double& E)
{
    if ( !m_autogroup )
    {
        groupDetectors(ws_red,m_backward_list);
        groupDetectors(ws_red,m_forward_list);
        groupDetectors(ws_green,m_backward_list);
        groupDetectors(ws_green,m_forward_list);
    }

    Property* startXprop = getProperty("TimeMin");
    Property* endXprop = getProperty("TimeMax");
    bool setX = !startXprop->isDefault() && !endXprop->isDefault();
    double startX(0.0),endX(0.0);
    if (setX)
    {
        startX = getProperty("TimeMin");
        endX = getProperty("TimeMax");
    }
    if (!m_int)
    {   //  "Differential asymmetry"

        API::MatrixWorkspace_sptr tmpWS = API::WorkspaceFactory::Instance().create(
                                              ws_red,1,ws_red->readX(0).size(),ws_red->readY(0).size());

        for(size_t i=0; i<tmpWS->dataY(0).size(); i++)
        {
            double FNORM = ws_green->readY(0)[i] + ws_red->readY(0)[i];
            FNORM = FNORM != 0.0 ? 1.0 / FNORM : 1.0;
            double BNORM = ws_green->readY(1)[i] + ws_red->readY(1)[i];
            BNORM = BNORM != 0.0 ? 1.0 / BNORM : 1.0;
            double ZF = ( ws_green->readY(0)[i] - ws_red->readY(0)[i] ) * FNORM;
            double ZB = ( ws_green->readY(1)[i] - ws_red->readY(1)[i] ) * BNORM;
            tmpWS->dataY(0)[i] = ZB - ZF;
            tmpWS->dataE(0)[i] = (1.0+ZF*ZF)*FNORM+(1.0+ZB*ZB)*BNORM;
        }

        IAlgorithm_sptr integr = createChildAlgorithm("Integration");
        integr->setProperty("InputWorkspace",tmpWS);
        integr->setPropertyValue("OutputWorkspace","tmp");
        if (setX)
        {
            integr->setProperty("RangeLower",startX);
            integr->setProperty("RangeUpper",endX);
        }
        integr->execute();
        MatrixWorkspace_sptr out = integr->getProperty("OutputWorkspace");

        Y = out->readY(0)[0] / static_cast<double>(tmpWS->dataY(0).size());
        E = out->readE(0)[0] / static_cast<double>(tmpWS->dataY(0).size());
    }
    else
    {
        //  "Integral asymmetry"
        IAlgorithm_sptr integr = createChildAlgorithm("Integration");
        integr->setProperty("InputWorkspace", ws_red);
        integr->setPropertyValue("OutputWorkspace","tmp");
        if (setX)
        {
            integr->setProperty("RangeLower",startX);
            integr->setProperty("RangeUpper",endX);
        }
        integr->execute();
        API::MatrixWorkspace_sptr intWS_red = integr->getProperty("OutputWorkspace");

        integr = createChildAlgorithm("Integration");
        integr->setProperty("InputWorkspace", ws_green);
        integr->setPropertyValue("OutputWorkspace","tmp");
        if (setX)
        {
            integr->setProperty("RangeLower",startX);
            integr->setProperty("RangeUpper",endX);
        }
        integr->execute();
        API::MatrixWorkspace_sptr intWS_green = integr->getProperty("OutputWorkspace");

        double YIF = ( intWS_green->readY(0)[0] - intWS_red->readY(0)[0] ) / ( intWS_green->readY(0)[0] + intWS_red->readY(0)[0] );
        double YIB = ( intWS_green->readY(1)[0] - intWS_red->readY(1)[0] ) / ( intWS_green->readY(1)[0] + intWS_red->readY(1)[0] );

        Y = YIB - YIF;

        double VARIF = (1.0 + YIF*YIF) / ( intWS_green->readY(0)[0] + intWS_red->readY(0)[0] );
        double VARIB = (1.0 + YIB*YIB) / ( intWS_green->readY(1)[0] + intWS_red->readY(1)[0] );

        E = sqrt( VARIF + VARIB );
    }

}
MatrixWorkspace_sptr
CreateFloodWorkspace::scaleToCentralPixel(MatrixWorkspace_sptr ws) {
  int const centralSpectrum = getProperty(Prop::CENTRAL_PIXEL);
  auto const nHisto = static_cast<int>(ws->getNumberHistograms());
  if (centralSpectrum >= nHisto) {
    throw std::invalid_argument(
        "Spectrum index " + std::to_string(centralSpectrum) +
        " passed to property " + Prop::CENTRAL_PIXEL +
        " is outside the range 0-" + std::to_string(nHisto - 1));
  }
  auto const spectraMap = ws->getSpectrumToWorkspaceIndexMap();
  auto const centralIndex = spectraMap.at(centralSpectrum);
  auto const scaleFactor = ws->y(centralIndex).front();
  g_log.information() << "Scale to central pixel, factor = " << scaleFactor
                      << '\n';
  if (scaleFactor <= 0.0) {
    throw std::runtime_error("Scale factor muhst be > 0, found " +
                             std::to_string(scaleFactor));
  }
  auto const axis = ws->getAxis(1);
  auto const sa = dynamic_cast<const SpectraAxis *>(axis);
  double const startX =
      isDefault(Prop::START_X) ? sa->getMin() : getProperty(Prop::START_X);
  double const endX =
      isDefault(Prop::END_X) ? sa->getMax() : getProperty(Prop::END_X);
  PARALLEL_FOR_IF(Kernel::threadSafe(*ws))
  for (int i = 0; i < nHisto; ++i) {
    PARALLEL_START_INTERUPT_REGION
    auto const spec = ws->getSpectrum(i).getSpectrumNo();
    if (isExcludedSpectrum(spec)) {
      ws->mutableY(i)[0] = VERY_BIG_VALUE;
      ws->mutableE(i)[0] = 0.0;
    } else if (spec >= startX && spec <= endX) {
      ws->mutableY(i)[0] /= scaleFactor;
      ws->mutableE(i)[0] /= scaleFactor;
    } else {
      ws->mutableY(i)[0] = 1.0;
      ws->mutableE(i)[0] = 0.0;
    }
    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION
  return ws;
}
WorkspaceGroup_sptr PolarizationCorrection::execPA(WorkspaceGroup_sptr inWS) {

  if (isPropertyDefault(cAlphaLabel())) {
    throw std::invalid_argument("Must provide as input for PA: " +
                                cAlphaLabel());
  }
  if (isPropertyDefault(cApLabel())) {
    throw std::invalid_argument("Must provide as input for PA: " + cApLabel());
  }

  size_t itemIndex = 0;
  MatrixWorkspace_sptr Ipp =
      boost::dynamic_pointer_cast<MatrixWorkspace>(inWS->getItem(itemIndex++));
  MatrixWorkspace_sptr Ipa =
      boost::dynamic_pointer_cast<MatrixWorkspace>(inWS->getItem(itemIndex++));
  MatrixWorkspace_sptr Iap =
      boost::dynamic_pointer_cast<MatrixWorkspace>(inWS->getItem(itemIndex++));
  MatrixWorkspace_sptr Iaa =
      boost::dynamic_pointer_cast<MatrixWorkspace>(inWS->getItem(itemIndex++));

  Ipp->setTitle("Ipp");
  Iaa->setTitle("Iaa");
  Ipa->setTitle("Ipa");
  Iap->setTitle("Iap");

  auto cropAlg = this->createChildAlgorithm("CropWorkspace");
  cropAlg->initialize();
  cropAlg->setProperty("InputWorkspace", Ipp);
  cropAlg->setProperty("EndWorkspaceIndex", 0);
  cropAlg->execute();
  MatrixWorkspace_sptr croppedIpp = cropAlg->getProperty("OutputWorkspace");

  MatrixWorkspace_sptr ones = copyShapeAndFill(croppedIpp, 1.0);
  // The ones workspace is now identical to the input workspaces in x, but has 1
  // as y values. It can therefore be used to build real polynomial functions.

  const VecDouble c_rho = getProperty(crhoLabel());
  const VecDouble c_alpha = getProperty(cAlphaLabel());
  const VecDouble c_pp = getProperty(cppLabel());
  const VecDouble c_ap = getProperty(cApLabel());

  const auto rho = this->execPolynomialCorrection(
      ones, c_rho); // Execute polynomial expression
  const auto pp = this->execPolynomialCorrection(
      ones, c_pp); // Execute polynomial expression
  const auto alpha = this->execPolynomialCorrection(
      ones, c_alpha); // Execute polynomial expression
  const auto ap = this->execPolynomialCorrection(
      ones, c_ap); // Execute polynomial expression

  const auto A0 = (Iaa * pp * ap) + (ap * Ipa * rho * pp) +
                  (ap * Iap * alpha * pp) + (Ipp * ap * alpha * rho * pp);
  const auto A1 = pp * Iaa;
  const auto A2 = pp * Iap;
  const auto A3 = ap * Iaa;
  const auto A4 = ap * Ipa;
  const auto A5 = ap * alpha * Ipp;
  const auto A6 = ap * alpha * Iap;
  const auto A7 = pp * rho * Ipp;
  const auto A8 = pp * rho * Ipa;

  const auto D = pp * ap * (rho + alpha + 1.0 + (rho * alpha));

  const auto nIpp =
      (A0 - A1 + A2 - A3 + A4 + A5 - A6 + A7 - A8 + Ipp + Iaa - Ipa - Iap) / D;
  const auto nIaa =
      (A0 + A1 - A2 + A3 - A4 - A5 + A6 - A7 + A8 + Ipp + Iaa - Ipa - Iap) / D;
  const auto nIpa =
      (A0 - A1 + A2 + A3 - A4 - A5 + A6 + A7 - A8 - Ipp - Iaa + Ipa + Iap) / D;
  const auto nIap =
      (A0 + A1 - A2 - A3 + A4 + A5 - A6 - A7 + A8 - Ipp - Iaa + Ipa + Iap) / D;

  WorkspaceGroup_sptr dataOut = boost::make_shared<WorkspaceGroup>();
  dataOut->addWorkspace(nIpp);
  dataOut->addWorkspace(nIpa);
  dataOut->addWorkspace(nIap);
  dataOut->addWorkspace(nIaa);
  size_t totalGroupEntries(dataOut->getNumberOfEntries());
  for (size_t i = 1; i < totalGroupEntries; i++) {
    auto alg = this->createChildAlgorithm("ReplaceSpecialValues");
    alg->setProperty("InputWorkspace", dataOut->getItem(i));
    alg->setProperty("OutputWorkspace", "dataOut_" + std::to_string(i));
    alg->setProperty("NaNValue", 0.0);
    alg->setProperty("NaNError", 0.0);
    alg->setProperty("InfinityValue", 0.0);
    alg->setProperty("InfinityError", 0.0);
    alg->execute();
  }
  // Preserve the history of the inside workspaces
  nIpp->history().addHistory(Ipp->getHistory());
  nIaa->history().addHistory(Iaa->getHistory());
  nIpa->history().addHistory(Ipa->getHistory());
  nIap->history().addHistory(Iap->getHistory());

  return dataOut;
}
/**
*   Executes the algorithm
*/
void PlotAsymmetryByLogValue::exec()
{
    m_forward_list = getProperty("ForwardSpectra");
    m_backward_list = getProperty("BackwardSpectra");
    m_autogroup = ( m_forward_list.size() == 0 && m_backward_list.size() == 0);

    //double alpha = getProperty("Alpha");

    std::string logName = getProperty("LogValue");

    int red = getProperty("Red");
    int green = getProperty("Green");

    std::string stype = getProperty("Type");
    m_int = stype == "Integral";

    std::string firstFN = getProperty("FirstRun");
    std::string lastFN = getProperty("LastRun");

    std::string ext = firstFN.substr(firstFN.find_last_of("."));

    firstFN.erase(firstFN.size()-4);
    lastFN.erase(lastFN.size()-4);

    std::string fnBase = firstFN;
    size_t i = fnBase.size()-1;
    while(isdigit(fnBase[i]))  i--;
    if (i == fnBase.size()-1)
    {
        g_log.error("File name must end with a number.");
        throw Exception::FileError("File name must end with a number.",firstFN);
    }
    fnBase.erase(i+1);

    firstFN.erase(0,fnBase.size());
    lastFN.erase(0,fnBase.size());

    size_t is = atoi(firstFN.c_str());  // starting run number
    size_t ie = atoi(lastFN.c_str());   // last run number
    int w  = static_cast<int>(firstFN.size());

    // The number of runs
    size_t npoints = ie - is + 1;

    // Create the 2D workspace for the output
    int nplots = green != EMPTY_INT() ? 4 : 1;
    MatrixWorkspace_sptr outWS = WorkspaceFactory::Instance().create("Workspace2D",
                                 nplots,          //  the number of plots
                                 npoints,    //  the number of data points on a plot
                                 npoints     //  it's not a histogram
                                                                    );
    TextAxis* tAxis = new TextAxis(nplots);
    if (nplots == 1)
    {
        tAxis->setLabel(0,"Asymmetry");
    }
    else
    {
        tAxis->setLabel(0,"Red-Green");
        tAxis->setLabel(1,"Red");
        tAxis->setLabel(2,"Green");
        tAxis->setLabel(3,"Red+Green");
    }
    outWS->replaceAxis(1,tAxis);

    Progress progress(this,0,1,ie-is+2);
    for(size_t i=is; i<=ie; i++)
    {
        std::ostringstream fn,fnn;
        fnn << std::setw(w) << std::setfill('0') << i ;
        fn << fnBase << fnn.str() << ext;

        // Load a muon nexus file with auto_group set to true
        IAlgorithm_sptr loadNexus = createChildAlgorithm("LoadMuonNexus");
        loadNexus->setPropertyValue("Filename", fn.str());
        loadNexus->setPropertyValue("OutputWorkspace","tmp"+fnn.str());
        if (m_autogroup)
            loadNexus->setPropertyValue("AutoGroup","1");
        loadNexus->execute();

        std::string wsProp = "OutputWorkspace";

        DataObjects::Workspace2D_sptr ws_red;
        DataObjects::Workspace2D_sptr ws_green;

        // Run through the periods of the loaded file and do calculations on the selected ones
        Workspace_sptr tmp = loadNexus->getProperty(wsProp);
        WorkspaceGroup_sptr wsGroup = boost::dynamic_pointer_cast<WorkspaceGroup>(tmp);
        if (!wsGroup)
        {
            ws_red = boost::dynamic_pointer_cast<DataObjects::Workspace2D>(tmp);
            TimeSeriesProperty<double>* logp =
                dynamic_cast<TimeSeriesProperty<double>*>(ws_red->run().getLogData(logName));
            if (!logp)
            {
                throw std::invalid_argument("Log "+logName+" does not exist or not a double type");
            }
            double Y,E;
            calcIntAsymmetry(ws_red,Y,E);
            outWS->dataY(0)[i-is] = Y;
            outWS->dataX(0)[i-is] = logp->lastValue();
            outWS->dataE(0)[i-is] = E;
        }
        else
        {

            for( int period = 1; period <= wsGroup->getNumberOfEntries(); ++period )
            {
                std::stringstream suffix;
                suffix << period;
                wsProp = "OutputWorkspace_" + suffix.str();// form the property name for higher periods
                // Do only one period
                if (green == EMPTY_INT() && period == red)
                {
                    Workspace_sptr tmpff = loadNexus->getProperty(wsProp);
                    ws_red = boost::dynamic_pointer_cast<DataObjects::Workspace2D>(tmpff);
                    TimeSeriesProperty<double>* logp =
                        dynamic_cast<TimeSeriesProperty<double>*>(ws_red->run().getLogData(logName));
                    if (!logp)
                    {
                        throw std::invalid_argument("Log "+logName+" does not exist or not a double type");
                    }
                    double Y,E;
                    calcIntAsymmetry(ws_red,Y,E);
                    outWS->dataY(0)[i-is] = Y;
                    outWS->dataX(0)[i-is] = logp->lastValue();
                    outWS->dataE(0)[i-is] = E;
                }
                else // red & green
                {
                    if (period == red)
                    {
                        Workspace_sptr temp = loadNexus->getProperty(wsProp);
                        ws_red = boost::dynamic_pointer_cast<Workspace2D>(temp);
                    }
                    if (period == green)
                    {
                        Workspace_sptr temp = loadNexus->getProperty(wsProp);
                        ws_green = boost::dynamic_pointer_cast<Workspace2D>(temp);
                    }
                }

            }
            // red & green claculation
            if (green != EMPTY_INT())
            {
                if (!ws_red || !ws_green)
                    throw std::invalid_argument("Red or green period is out of range");
                TimeSeriesProperty<double>* logp =
                    dynamic_cast<TimeSeriesProperty<double>*>(ws_red->run().getLogData(logName));
                if (!logp)
                {
                    throw std::invalid_argument("Log "+logName+" does not exist or not a double type");
                }
                double Y,E;
                double Y1,E1;
                calcIntAsymmetry(ws_red,Y,E);
                calcIntAsymmetry(ws_green,Y1,E1);
                outWS->dataY(1)[i-is] = Y;
                outWS->dataX(1)[i-is] = logp->lastValue();
                outWS->dataE(1)[i-is] = E;

                outWS->dataY(2)[i-is] = Y1;
                outWS->dataX(2)[i-is] = logp->lastValue();
                outWS->dataE(2)[i-is] = E1;

                outWS->dataY(3)[i-is] = Y + Y1;
                outWS->dataX(3)[i-is] = logp->lastValue();
                outWS->dataE(3)[i-is] = sqrt(E*E+E1*E1);

                // move to last for safety since some grouping takes place in the
                // calcIntAsymmetry call below
                calcIntAsymmetry(ws_red,ws_green,Y,E);
                outWS->dataY(0)[i-is] = Y;
                outWS->dataX(0)[i-is] = logp->lastValue();
                outWS->dataE(0)[i-is] = E;
            }
            else if (!ws_red)
                throw std::invalid_argument("Red period is out of range");

        }
        progress.report();
    }

    outWS->getAxis(0)->title() = logName;
    outWS->setYUnitLabel("Asymmetry");

    // Assign the result to the output workspace property
    setProperty("OutputWorkspace", outWS);

}
Beispiel #8
0
  /**
   * Execute the algorithm.
   */
  void SofQW3::exec()
  {
    MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace");
    // Do the full check for common binning
    if( !WorkspaceHelpers::commonBoundaries(inputWS) )
    {
      throw std::invalid_argument("The input workspace must have common binning across all spectra");
    }

    RebinnedOutput_sptr outputWS = this->setUpOutputWorkspace(inputWS,
                                                 getProperty("QAxisBinning"),
                                                              m_Qout);
    g_log.debug() << "Workspace type: " << outputWS->id() << std::endl;
    setProperty("OutputWorkspace", outputWS);
    const size_t nEnergyBins = inputWS->blocksize();
    const size_t nHistos = inputWS->getNumberHistograms();

    // Progress reports & cancellation
    const size_t nreports(nHistos * nEnergyBins);
    m_progress = boost::shared_ptr<API::Progress>(new API::Progress(this, 0.0,
                                                                    1.0,
                                                                    nreports));

    // Compute input caches
    this->initCachedValues(inputWS);

    std::vector<double> par = inputWS->getInstrument()->getNumberParameter("detector-neighbour-offset");
    if (par.empty())
    {
      // Index theta cache
      this->initThetaCache(inputWS);
    }
    else
    {
      g_log.debug() << "Offset: " << par[0] << std::endl;
      this->m_detNeighbourOffset = static_cast<int>(par[0]);
      this->getValuesAndWidths(inputWS);
    }

    const MantidVec & X = inputWS->readX(0);

    PARALLEL_FOR2(inputWS, outputWS)
    for (int64_t i = 0; i < static_cast<int64_t>(nHistos); ++i) // signed for openmp
    {
      PARALLEL_START_INTERUPT_REGION

      DetConstPtr detector = inputWS->getDetector(i);
      if (detector->isMasked() || detector->isMonitor())
      {
        continue;
      }

      double theta = this->m_theta[i];
      double phi = 0.0;
      double thetaWidth = 0.0;
      double phiWidth = 0.0;
      // Non-PSD mode
      if (par.empty())
      {
        thetaWidth = this->m_thetaWidth;
      }
      // PSD mode
      else
      {
        phi = this->m_phi[i];
        thetaWidth = this->m_thetaWidths[i];
        phiWidth = this->m_phiWidths[i];
      }

      double thetaHalfWidth = 0.5 * thetaWidth;
      double phiHalfWidth = 0.5 * phiWidth;

      const double thetaLower = theta - thetaHalfWidth;
      const double thetaUpper = theta + thetaHalfWidth;

      const double phiLower = phi - phiHalfWidth;
      const double phiUpper = phi + phiHalfWidth;

      const double efixed = this->getEFixed(detector);

      for(size_t j = 0; j < nEnergyBins; ++j)
      {
        m_progress->report("Computing polygon intersections");
        // For each input polygon test where it intersects with
        // the output grid and assign the appropriate weights of Y/E
        const double dE_j = X[j];
        const double dE_jp1 = X[j+1];

        const V2D ll(dE_j, this->calculateQ(efixed, dE_j, thetaLower, phiLower));
        const V2D lr(dE_jp1, this->calculateQ(efixed, dE_jp1, thetaLower, phiLower));
        const V2D ur(dE_jp1, this->calculateQ(efixed, dE_jp1, thetaUpper, phiUpper));
        const V2D ul(dE_j, this->calculateQ(efixed, dE_j, thetaUpper, phiUpper));
        Quadrilateral inputQ = Quadrilateral(ll, lr, ur, ul);

        this->rebinToFractionalOutput(inputQ, inputWS, i, j, outputWS, m_Qout);
      }

      PARALLEL_END_INTERUPT_REGION
    }
    PARALLEL_CHECK_INTERUPT_REGION

    outputWS->finalize();
    this->normaliseOutput(outputWS, inputWS);
  }
Beispiel #9
0
    /**
    * Reads the data from the file. It is assumed that the provided file stream has its position
    * set such that the first call to getline will be give the first line of data
    * @param file :: A reference to a file stream
    * @returns A pointer to a new workspace
    */
    API::Workspace_sptr LoadAscii::readData(std::ifstream & file) const
    {
      // Get the first line and find the number of spectra from the number of columns
      std::string line;
      getline(file,line);
      boost::trim(line);

      std::list<std::string> columns;
      const int numCols = splitIntoColumns(columns, line);
      if( numCols < 2 ) 
      {
        g_log.error() << "Invalid data format found in file \"" << getPropertyValue("Filename") << "\"\n";
        throw std::runtime_error("Invalid data format. Fewer than 2 columns found.");
      }
      size_t numSpectra(0);
      bool haveErrors(false);
      bool haveXErrors(false);
      // Assume single data set with no errors
      if( numCols == 2 )
      {
        numSpectra = numCols/2;
      }
      // Data with errors
      else if( (numCols-1) % 2 == 0 )
      {
        numSpectra = (numCols - 1)/2;
        haveErrors = true;
      }
      // Data with errors on both X and Y (4-column file)
      else if( numCols == 4 )
      {
        numSpectra = 1;
        haveErrors = true;
        haveXErrors = true;
      }
      else
      {
        g_log.error() << "Invalid data format found in file \"" << getPropertyValue("Filename") << "\"\n";
        g_log.error() << "LoadAscii requires the number of columns to be an even multiple of either 2 or 3.";
        throw std::runtime_error("Invalid data format.");
      }

      // A quick check at the number of lines won't be accurate enough as potentially there
      // could be blank lines and comment lines
      int numBins(0), lineNo(0);
      std::vector<DataObjects::Histogram1D> spectra(numSpectra);
      std::vector<double> values(numCols, 0.);
      do
      {
        ++lineNo;
        boost::trim(line);
        if( this->skipLine(line) ) continue;
        columns.clear();
        int lineCols = this->splitIntoColumns(columns, line); 
        if( lineCols != numCols )
        {
          std::ostringstream ostr;
          ostr << "Number of columns changed at line " << lineNo;
          throw std::runtime_error(ostr.str());
        }

        try
        {
          fillInputValues(values, columns); //ignores nans and replaces them with 0
        }
        catch(boost::bad_lexical_cast&)
        {
          g_log.error() << "Invalid value on line " << lineNo << " of \""
            << getPropertyValue("Filename") << "\"\n";
          throw std::runtime_error("Invalid value encountered.");
        }

        for (size_t i = 0; i < numSpectra; ++i)
        {
          spectra[i].dataX().push_back(values[0]);
          spectra[i].dataY().push_back(values[i*2+1]);
          if( haveErrors )
          {
            spectra[i].dataE().push_back(values[i*2+2]);
          }
          if( haveXErrors )
          {
            // Note: we only have X errors with 4-column files.
            // We are only here when i=0.
            spectra[i].dataDx().push_back(values[3]);
          }
        }
        ++numBins;
      }
      while(getline(file,line));

      MatrixWorkspace_sptr localWorkspace = boost::dynamic_pointer_cast<MatrixWorkspace>
        (WorkspaceFactory::Instance().create("Workspace2D",numSpectra,numBins,numBins));
      try 
      {
        localWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create(getProperty("Unit"));
      } 
      catch (Exception::NotFoundError&) 
      {
        // Asked for dimensionless workspace (obviously not in unit factory)
      }

      for (size_t i = 0; i < numSpectra; ++i)
      {
        localWorkspace->dataX(i) = spectra[i].dataX();
        localWorkspace->dataY(i) = spectra[i].dataY();
        /* If Y or E errors are not there, DON'T copy across as the 'spectra' vectors
           have not been filled above. The workspace will by default have vectors of
           the right length filled with zeroes. */
        if ( haveErrors ) localWorkspace->dataE(i) = spectra[i].dataE();
        if ( haveXErrors ) localWorkspace->dataDx(i) = spectra[i].dataDx();
        // Just have spectrum number start at 1 and count up
        localWorkspace->getSpectrum(i)->setSpectrumNo(static_cast<specid_t>(i)+1);
      }
      return localWorkspace;
    }
Beispiel #10
0
/** Executes the rebin algorithm
*
*  @throw runtime_error Thrown if the bin range does not intersect the range of the input workspace
*/
void Rebin::exec()
{
    // Get the input workspace
    MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace");
    MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace");

    // Are we preserving event workspace-iness?
    bool PreserveEvents = getProperty("PreserveEvents");

    // Rebinning in-place
    bool inPlace = (inputWS == outputWS);

    std::vector<double> rbParams = rebinParamsFromInput(getProperty("Params"), *inputWS, g_log);

    const bool dist = inputWS->isDistribution();
    const bool isHist = inputWS->isHistogramData();

    // workspace independent determination of length
    const int histnumber = static_cast<int>(inputWS->getNumberHistograms());

    bool fullBinsOnly = getProperty("FullBinsOnly");

    MantidVecPtr XValues_new;
    // create new output X axis
    const int ntcnew = VectorHelper::createAxisFromRebinParams(rbParams, XValues_new.access(),
                       true, fullBinsOnly);

    //---------------------------------------------------------------------------------
    //Now, determine if the input workspace is actually an EventWorkspace
    EventWorkspace_const_sptr eventInputWS = boost::dynamic_pointer_cast<const EventWorkspace>(inputWS);

    if (eventInputWS != NULL)
    {
        //------- EventWorkspace as input -------------------------------------
        EventWorkspace_sptr eventOutputWS = boost::dynamic_pointer_cast<EventWorkspace>(outputWS);

        if (inPlace && PreserveEvents)
        {
            // -------------Rebin in-place, preserving events ----------------------------------------------
            // This only sets the X axis. Actual rebinning will be done upon data access.
            eventOutputWS->setAllX(XValues_new);
            this->setProperty("OutputWorkspace", boost::dynamic_pointer_cast<MatrixWorkspace>(eventOutputWS));
        }
        else if (!inPlace && PreserveEvents)
        {
            // -------- NOT in-place, but you want to keep events for some reason. ----------------------
            // Must copy the event workspace to a new EventWorkspace (and bin that).

            //Make a brand new EventWorkspace
            eventOutputWS = boost::dynamic_pointer_cast<EventWorkspace>(
                                API::WorkspaceFactory::Instance().create("EventWorkspace", inputWS->getNumberHistograms(), 2, 1));
            //Copy geometry over.
            API::WorkspaceFactory::Instance().initializeFromParent(inputWS, eventOutputWS, false);
            //You need to copy over the data as well.
            eventOutputWS->copyDataFrom( (*eventInputWS) );

            // This only sets the X axis. Actual rebinning will be done upon data access.
            eventOutputWS->setAllX(XValues_new);

            //Cast to the matrixOutputWS and save it
            this->setProperty("OutputWorkspace", boost::dynamic_pointer_cast<MatrixWorkspace>(eventOutputWS));
        }
        else
        {
            //--------- Different output, OR you're inplace but not preserving Events --- create a Workspace2D -------
            g_log.information() << "Creating a Workspace2D from the EventWorkspace " << eventInputWS->getName() << ".\n";

            //Create a Workspace2D
            // This creates a new Workspace2D through a torturous route using the WorkspaceFactory.
            // The Workspace2D is created with an EMPTY CONSTRUCTOR
            outputWS = WorkspaceFactory::Instance().create("Workspace2D",histnumber,ntcnew,ntcnew-1);
            WorkspaceFactory::Instance().initializeFromParent(inputWS, outputWS, true);

            //Initialize progress reporting.
            Progress prog(this,0.0,1.0, histnumber);

            //Go through all the histograms and set the data
            PARALLEL_FOR3(inputWS, eventInputWS, outputWS)
            for (int i=0; i < histnumber; ++i)
            {
                PARALLEL_START_INTERUPT_REGION

                //Set the X axis for each output histogram
                outputWS->setX(i, XValues_new);

                //Get a const event list reference. eventInputWS->dataY() doesn't work.
                const EventList& el = eventInputWS->getEventList(i);
                MantidVec y_data, e_data;
                // The EventList takes care of histogramming.
                el.generateHistogram(*XValues_new, y_data, e_data);

                //Copy the data over.
                outputWS->dataY(i).assign(y_data.begin(), y_data.end());
                outputWS->dataE(i).assign(e_data.begin(), e_data.end());

                //Report progress
                prog.report(name());
                PARALLEL_END_INTERUPT_REGION
            }
            PARALLEL_CHECK_INTERUPT_REGION

            //Copy all the axes
            for (int i=1; i<inputWS->axes(); i++)
            {
                outputWS->replaceAxis( i, inputWS->getAxis(i)->clone(outputWS.get()) );
                outputWS->getAxis(i)->unit() = inputWS->getAxis(i)->unit();
            }

            //Copy the units over too.
            for (int i=0; i < outputWS->axes(); ++i)
                outputWS->getAxis(i)->unit() = inputWS->getAxis(i)->unit();
            outputWS->setYUnit(eventInputWS->YUnit());
            outputWS->setYUnitLabel(eventInputWS->YUnitLabel());

            // Assign it to the output workspace property
            setProperty("OutputWorkspace", outputWS);
        }

    } // END ---- EventWorkspace
Beispiel #11
0
/**Executes the main part of the algorithm that handles the conversion of the
* units
* @param inputWS :: the input workspace that will be converted
* @throw std::runtime_error :: If the workspace has invalid X axis binning
* @return A pointer to a MatrixWorkspace_sptr that contains the converted units
*/
MatrixWorkspace_sptr
ConvertUnits::executeUnitConversion(const API::MatrixWorkspace_sptr inputWS) {

  // A WS holding BinEdges cannot have less than 2 values, as a bin has
  // 2 edges, having less than 2 values would mean that the WS contains Points
  if (inputWS->x(0).size() < 2) {
    std::stringstream msg;
    msg << "Input workspace has invalid X axis binning parameters. Should "
           "have "
           "at least 2 values. Found " << inputWS->x(0).size() << ".";
    throw std::runtime_error(msg.str());
  }
  if (inputWS->x(0).front() > inputWS->x(0).back() ||
      inputWS->x(m_numberOfSpectra / 2).front() >
          inputWS->x(m_numberOfSpectra / 2).back())
    throw std::runtime_error("Input workspace has invalid X axis binning "
                             "parameters. X values should be increasing.");

  MatrixWorkspace_sptr outputWS;
  // Check whether there is a quick conversion available
  double factor, power;
  if (m_inputUnit->quickConversion(*m_outputUnit, factor, power))
  // If test fails, could also check whether a quick conversion in the
  // opposite
  // direction has been entered
  {
    outputWS = this->convertQuickly(inputWS, factor, power);
  } else {
    outputWS = this->convertViaTOF(m_inputUnit, inputWS);
  }

  // If the units conversion has flipped the ascending direction of X, reverse
  // all the vectors
  if (!outputWS->x(0).empty() &&
      (outputWS->x(0).front() > outputWS->x(0).back() ||
       outputWS->x(m_numberOfSpectra / 2).front() >
           outputWS->x(m_numberOfSpectra / 2).back())) {
    this->reverse(outputWS);
  }

  // Need to lop bins off if converting to energy transfer.
  // Don't do for EventWorkspaces, where you can easily rebin to recover the
  // situation without losing information
  /* This is an ugly test - could be made more general by testing for DBL_MAX
  values at the ends of all spectra, but that would be less efficient */
  if (m_outputUnit->unitID().find("Delta") == 0 && !m_inputEvents)
    outputWS = this->removeUnphysicalBins(outputWS);

  // Rebin the data to common bins if requested, and if necessary
  bool alignBins = getProperty("AlignBins");
  if (alignBins && !WorkspaceHelpers::commonBoundaries(outputWS))
    outputWS = this->alignBins(outputWS);

  // If appropriate, put back the bin width division into Y/E.
  if (m_distribution && !m_inputEvents) // Never do this for event workspaces
  {
    this->putBackBinWidth(outputWS);
  }

  return outputWS;
}
void ApplyAbsorptionCorrections::run() {
  setRunIsRunning(true);

  // Create / Initialize algorithm
  API::BatchAlgorithmRunner::AlgorithmRuntimeProps absCorProps;
  IAlgorithm_sptr applyCorrAlg =
      AlgorithmManager::Instance().create("ApplyPaalmanPingsCorrection");
  applyCorrAlg->initialize();

  // get Sample Workspace
  MatrixWorkspace_sptr sampleWs =
      AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(
          m_sampleWorkspaceName);
  absCorProps["SampleWorkspace"] = m_sampleWorkspaceName;

  const bool useCan = m_uiForm.ckUseCan->isChecked();
  // Get Can and Clone
  MatrixWorkspace_sptr canClone;
  if (useCan) {
    const auto canName =
        m_uiForm.dsContainer->getCurrentDataName().toStdString();
    const auto cloneName = "__algorithm_can";
    IAlgorithm_sptr clone =
        AlgorithmManager::Instance().create("CloneWorkspace");
    clone->initialize();
    clone->setProperty("InputWorkspace", canName);
    clone->setProperty("Outputworkspace", cloneName);
    clone->execute();

    canClone =
        AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(cloneName);
    // Check for same binning across sample and container
    if (!checkWorkspaceBinningMatches(sampleWs, canClone)) {
      const char *text = "Binning on sample and container does not match."
                         "Would you like to enable rebinning of the container?";

      int result = QMessageBox::question(nullptr, tr("Rebin sample?"), tr(text),
                                         QMessageBox::Yes, QMessageBox::No,
                                         QMessageBox::NoButton);

      if (result == QMessageBox::Yes) {
        m_uiForm.ckRebinContainer->setChecked(true);
      } else {
        m_batchAlgoRunner->clearQueue();
        setRunIsRunning(false);
        setPlotSpectrumEnabled(false);
        setPlotContourEnabled(false);
        setSaveResultEnabled(false);
        g_log.error("Cannot apply absorption corrections "
                    "using a sample and "
                    "container with different binning.");
        return;
      }
    }

    absCorProps["CanWorkspace"] = cloneName;

    const bool useCanScale = m_uiForm.ckScaleCan->isChecked();
    if (useCanScale) {
      const double canScaleFactor = m_uiForm.spCanScale->value();
      applyCorrAlg->setProperty("CanScaleFactor", canScaleFactor);
    }
    if (m_uiForm.ckShiftCan->isChecked()) { // If container is shifted
      const double canShiftFactor = m_uiForm.spCanShift->value();
      applyCorrAlg->setProperty("canShiftFactor", canShiftFactor);
    }
    const bool rebinContainer = m_uiForm.ckRebinContainer->isChecked();
    applyCorrAlg->setProperty("RebinCanToSample", rebinContainer);
  }

  QString correctionsWsName = m_uiForm.dsCorrections->getCurrentDataName();

  WorkspaceGroup_sptr corrections =
      AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>(
          correctionsWsName.toStdString());
  bool interpolateAll = false;
  for (size_t i = 0; i < corrections->size(); i++) {
    MatrixWorkspace_sptr factorWs =
        boost::dynamic_pointer_cast<MatrixWorkspace>(corrections->getItem(i));

    // Check for matching binning
    if (sampleWs && (factorWs->blocksize() != sampleWs->blocksize() &&
                     factorWs->blocksize() != 1)) {
      int result;
      if (interpolateAll) {
        result = QMessageBox::Yes;
      } else {
        std::string text = "Number of bins on sample and " +
                           factorWs->getName() +
                           " workspace does not match.\n" +
                           "Would you like to interpolate this workspace to "
                           "match the sample?";

        result = QMessageBox::question(nullptr, tr("Interpolate corrections?"),
                                       tr(text.c_str()), QMessageBox::YesToAll,
                                       QMessageBox::Yes, QMessageBox::No);
      }

      switch (result) {
      case QMessageBox::YesToAll:
        interpolateAll = true;
      // fall through
      case QMessageBox::Yes:
        addInterpolationStep(factorWs, absCorProps["SampleWorkspace"]);
        break;
      default:
        m_batchAlgoRunner->clearQueue();
        setRunIsRunning(false);
        setPlotSpectrumEnabled(false);
        setPlotContourEnabled(false);
        setSaveResultEnabled(false);
        g_log.error(
            "ApplyAbsorptionCorrections cannot run with corrections that do "
            "not match sample binning.");
        return;
      }
    }

    applyCorrAlg->setProperty("CorrectionsWorkspace",
                              correctionsWsName.toStdString());
  }

  // Generate output workspace name
  auto QStrSampleWsName = QString::fromStdString(m_sampleWorkspaceName);
  int nameCutIndex = QStrSampleWsName.lastIndexOf("_");
  if (nameCutIndex == -1)
    nameCutIndex = QStrSampleWsName.length();

  QString correctionType;
  switch (m_uiForm.cbGeometry->currentIndex()) {
  case 0:
    correctionType = "flt";
    break;
  case 1:
    correctionType = "cyl";
    break;
  case 2:
    correctionType = "anl";
    break;
  }

  QString outputWsName = QStrSampleWsName.left(nameCutIndex);
  outputWsName += "_" + correctionType + "_Corrected";

  // Using container
  if (m_uiForm.ckUseCan->isChecked()) {
    const auto canName =
        m_uiForm.dsContainer->getCurrentDataName().toStdString();
    MatrixWorkspace_sptr containerWs =
        AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(canName);
    auto run = containerWs->run();
    if (run.hasProperty("run_number")) {
      outputWsName +=
          "_" + QString::fromStdString(run.getProperty("run_number")->value());
    } else {
      auto canCutIndex = QString::fromStdString(canName).indexOf("_");
      outputWsName += "_" + QString::fromStdString(canName).left(canCutIndex);
    }
  }

  outputWsName += "_red";

  applyCorrAlg->setProperty("OutputWorkspace", outputWsName.toStdString());

  // Add corrections algorithm to queue
  m_batchAlgoRunner->addAlgorithm(applyCorrAlg, absCorProps);

  // Run algorithm queue
  connect(m_batchAlgoRunner, SIGNAL(batchComplete(bool)), this,
          SLOT(absCorComplete(bool)));
  m_batchAlgoRunner->executeBatchAsync();

  // Set the result workspace for Python script export
  m_pythonExportWsName = outputWsName.toStdString();
  // m_containerWorkspaceName = m_uiForm.dsContainer->getCurrentDataName();
  // updateContainer();
}
  /**
   * Start fitting process.
   */
  void MuonSequentialFitDialog::startFit()
  {
    if ( m_state != Stopped )
      throw std::runtime_error("Couln't start: already running");

    setState(Preparing);

    // Explicitly run the file search. This might be needed when Start is clicked straigh after 
    // editing the run box. In that case, lost focus event might not be processed yet and search
    // might not have been started yet. Otherwise, search is not done as the widget sees that it
    // has not been changed. Taken from LoadDialog.cpp:124.
    m_ui.runs->findFiles();

    // Wait for file search to finish.
    while ( m_ui.runs->isSearching() )
    {
      QApplication::processEvents();
    }

    // To process events from the finished thread
    QApplication::processEvents();

    // Validate input fields
    if ( ! isInputValid() )
    {
      QMessageBox::critical(this, "Input is not valid", 
        "One or more input fields are invalid.\n\nInvalid fields are marked with a '*'.");
      setState(Stopped);
      return;
    }

    QStringList runFilenames = m_ui.runs->getFilenames();

    const std::string label = m_ui.labelInput->text().toStdString();
    const std::string labelGroupName = SEQUENTIAL_PREFIX + label;

    AnalysisDataServiceImpl& ads = AnalysisDataService::Instance();

    if ( ads.doesExist(labelGroupName) )
    {
      QMessageBox::StandardButton answer = QMessageBox::question(this, "Label already exists", 
          "Label you specified was used for one of the previous fits. Do you want to overwrite it?", 
          QMessageBox::Yes | QMessageBox::Cancel);

      if ( answer != QMessageBox::Yes )
      {
        setState(Stopped);
        return;
      }

      ads.deepRemoveGroup(labelGroupName);
    }
   
    // Create a group for label
    ads.add(labelGroupName, boost::make_shared<WorkspaceGroup>());

    // Tell progress bar how many iterations we will need to make and reset it
    m_ui.progress->setRange( 0, runFilenames.size() );
    m_ui.progress->setFormat("%p%");
    m_ui.progress->setValue(0);

    // Clear diagnosis table for new fit
    m_ui.diagnosisTable->setRowCount(0);

    // Get fit function as specified by user in the fit browser
    IFunction_sptr fitFunction = FunctionFactory::Instance().createInitialized(
        m_fitPropBrowser->getFittingFunction()->asString() );

    // Whether we should use initial function for every fit
    bool useInitFitFunction = (m_ui.paramTypeGroup->checkedButton() == m_ui.paramTypeInitial);

    setState(Running);
    m_stopRequested = false;

    for ( auto fileIt = runFilenames.constBegin(); fileIt != runFilenames.constEnd(); ++fileIt )
    {
      // Process events (so that Stop button press is processed)
      QApplication::processEvents();

      // Stop if requested by user
      if ( m_stopRequested )
        break;

      MatrixWorkspace_sptr ws;

      auto load = boost::dynamic_pointer_cast<AlgorithmProxy>( AlgorithmManager::Instance().create("MuonLoad") );
      load->setChild(true);
      load->setRethrows(true);
      load->copyPropertiesFrom(*m_loadAlg);

      try
      {
        load->initialize();

        load->setPropertyValue( "Filename", fileIt->toStdString() );
        load->setPropertyValue( "OutputWorkspace", "__YouDontSeeMeIAmNinja" ); // Is not used

        if ( m_fitPropBrowser->rawData() ) // TODO: or vice verca?
          load->setPropertyValue( "RebinParams", "" );

        load->execute();

        ws = load->getProperty("OutputWorkspace");
      }
      catch(...)
      {
        QMessageBox::critical(this, "Loading failed", 
            "Unable to load one of the files.\n\nCheck log for details");
        break;
      }

      const std::string runTitle = getRunTitle(ws);
      const std::string wsBaseName = labelGroupName + "_" + runTitle; 

      IFunction_sptr functionToFit;

      if ( useInitFitFunction )
        // Create a copy so that the original function is not changed
        functionToFit = FunctionFactory::Instance().createInitialized( fitFunction->asString() );
      else
        // Use the same function over and over, so that previous fitted params are used for the next fit
        functionToFit = fitFunction;

      IAlgorithm_sptr fit = AlgorithmManager::Instance().create("Fit");
      fit->setRethrows(true);

      try 
      {

        // Set function. Gets updated when fit is done. 
        fit->setProperty("Function", functionToFit);

        fit->setProperty("InputWorkspace", ws);
        fit->setProperty("Output", wsBaseName);

        // We should have one spectra only in the workspace, so use the first one.
        fit->setProperty("WorkspaceIndex", 0);

        // Various properties from the fit prop. browser
        fit->setProperty("StartX", m_fitPropBrowser->startX());
        fit->setProperty("EndX", m_fitPropBrowser->endX());
        fit->setProperty("Minimizer", m_fitPropBrowser->minimizer());
        fit->setProperty("CostFunction", m_fitPropBrowser->costFunction());

        fit->execute();
      }
      catch(...)
      {
        QMessageBox::critical(this, "Fitting failed", 
            "Unable to fit one of the files.\n\nCheck log for details");
        break;
      }

      // Make sure created fit workspaces end-up in the group
      // TODO: this really should use loop
      ads.addToGroup(labelGroupName, wsBaseName + "_NormalisedCovarianceMatrix");
      ads.addToGroup(labelGroupName, wsBaseName + "_Parameters");
      ads.addToGroup(labelGroupName, wsBaseName + "_Workspace");

      // Copy log values
      auto fitWs = ads.retrieveWS<MatrixWorkspace>(wsBaseName + "_Workspace");
      fitWs->copyExperimentInfoFrom(ws.get());

      // Add information about the fit to the diagnosis table
      addDiagnosisEntry(runTitle, fit->getProperty("OutputChi2OverDof"), functionToFit); 

      // Update progress
      m_ui.progress->setFormat("%p% - " + QString::fromStdString(runTitle) );
      m_ui.progress->setValue( m_ui.progress->value() + 1 );
    }

    setState(Stopped);
  }
Beispiel #14
0
/** Carries out the bin-by-bin normalization
 *  @param inputWorkspace The input workspace
 *  @param outputWorkspace The result workspace
 */
void NormaliseToMonitor::normaliseBinByBin(
    const MatrixWorkspace_sptr &inputWorkspace,
    MatrixWorkspace_sptr &outputWorkspace) {
  EventWorkspace_sptr inputEvent =
      boost::dynamic_pointer_cast<EventWorkspace>(inputWorkspace);

  // Only create output workspace if different to input one
  if (outputWorkspace != inputWorkspace) {
    if (inputEvent) {
      outputWorkspace = inputWorkspace->clone();
    } else
      outputWorkspace = create<MatrixWorkspace>(*inputWorkspace);
  }
  auto outputEvent =
      boost::dynamic_pointer_cast<EventWorkspace>(outputWorkspace);

  const auto &inputSpecInfo = inputWorkspace->spectrumInfo();
  const auto &monitorSpecInfo = m_monitor->spectrumInfo();

  const auto specLength = inputWorkspace->blocksize();
  for (auto &workspaceIndex : m_workspaceIndexes) {
    // Get hold of the monitor spectrum
    const auto &monX = m_monitor->binEdges(workspaceIndex);
    auto monY = m_monitor->counts(workspaceIndex);
    auto monE = m_monitor->countStandardDeviations(workspaceIndex);
    size_t timeIndex = 0;
    if (m_scanInput)
      timeIndex = monitorSpecInfo.spectrumDefinition(workspaceIndex)[0].second;
    // Calculate the overall normalization just the once if bins are all
    // matching
    if (m_commonBins)
      this->normalisationFactor(monX, monY, monE);

    const size_t numHists = inputWorkspace->getNumberHistograms();
    // Flag set when a division by 0 is found
    bool hasZeroDivision = false;
    Progress prog(this, 0.0, 1.0, numHists);
    // Loop over spectra
    PARALLEL_FOR_IF(
        Kernel::threadSafe(*inputWorkspace, *outputWorkspace, *m_monitor))
    for (int64_t i = 0; i < int64_t(numHists); ++i) {
      PARALLEL_START_INTERUPT_REGION
      prog.report();

      const auto &specDef = inputSpecInfo.spectrumDefinition(i);
      if (!spectrumDefinitionsMatchTimeIndex(specDef, timeIndex))
        continue;

      const auto &X = inputWorkspace->binEdges(i);
      // If not rebinning, just point to our monitor spectra, otherwise create
      // new vectors

      auto Y = (m_commonBins ? monY : Counts(specLength));
      auto E = (m_commonBins ? monE : CountStandardDeviations(specLength));

      if (!m_commonBins) {
        // ConvertUnits can give X vectors of all zeros - skip these, they
        // cause
        // problems
        if (X.back() == 0.0 && X.front() == 0.0)
          continue;
        // Rebin the monitor spectrum to match the binning of the current data
        // spectrum
        VectorHelper::rebinHistogram(
            monX.rawData(), monY.mutableRawData(), monE.mutableRawData(),
            X.rawData(), Y.mutableRawData(), E.mutableRawData(), false);
        // Recalculate the overall normalization factor
        this->normalisationFactor(X, Y, E);
      }

      if (inputEvent) {
        // --- EventWorkspace ---
        EventList &outEL = outputEvent->getSpectrum(i);
        outEL.divide(X.rawData(), Y.mutableRawData(), E.mutableRawData());
      } else {
        // --- Workspace2D ---
        auto &YOut = outputWorkspace->mutableY(i);
        auto &EOut = outputWorkspace->mutableE(i);
        const auto &inY = inputWorkspace->y(i);
        const auto &inE = inputWorkspace->e(i);
        outputWorkspace->setSharedX(i, inputWorkspace->sharedX(i));

        // The code below comes more or less straight out of Divide.cpp
        for (size_t k = 0; k < specLength; ++k) {
          // Get the input Y's
          const double leftY = inY[k];
          const double rightY = Y[k];

          if (rightY == 0.0) {
            hasZeroDivision = true;
          }

          // Calculate result and store in local variable to avoid overwriting
          // original data if output workspace is same as one of the input
          // ones
          const double newY = leftY / rightY;

          if (fabs(rightY) > 1.0e-12 && fabs(newY) > 1.0e-12) {
            const double lhsFactor = (inE[k] < 1.0e-12 || fabs(leftY) < 1.0e-12)
                                         ? 0.0
                                         : pow((inE[k] / leftY), 2);
            const double rhsFactor =
                E[k] < 1.0e-12 ? 0.0 : pow((E[k] / rightY), 2);
            EOut[k] = std::abs(newY) * sqrt(lhsFactor + rhsFactor);
          }

          // Now store the result
          YOut[k] = newY;
        } // end Workspace2D case
      }   // end loop over current spectrum

      PARALLEL_END_INTERUPT_REGION
    } // end loop over spectra
    PARALLEL_CHECK_INTERUPT_REGION

    if (hasZeroDivision) {
      g_log.warning() << "Division by zero in some of the bins.\n";
    }
    if (inputEvent)
      outputEvent->clearMRU();
  }
}
/**  Populate output workspace with results
*   @param outWS :: [input/output] Output workspace to populate
*   @param nplots :: [input] Number of histograms
*/
void PlotAsymmetryByLogValue::saveResultsToADS(MatrixWorkspace_sptr &outWS,
                                               int nplots) {

  if (nplots == 2) {
    size_t i = 0;
    for (auto it = m_logValue.begin(); it != m_logValue.end(); ++it) {
      size_t run = it->first;
      outWS->dataX(0)[i] = static_cast<double>(run); // run number
      outWS->dataY(0)[i] = it->second;               // log value
      outWS->dataY(1)[i] = m_redY[run];              // redY
      outWS->dataE(1)[i] = m_redE[run];              // redE
      i++;
    }
  } else {
    size_t i = 0;
    for (auto it = m_logValue.begin(); it != m_logValue.end(); ++it) {
      size_t run = it->first;
      outWS->dataX(0)[i] = static_cast<double>(run); // run number
      outWS->dataY(0)[i] = it->second;               // log value
      outWS->dataY(1)[i] = m_diffY[run];             // diffY
      outWS->dataE(1)[i] = m_diffE[run];             // diffE
      outWS->dataY(2)[i] = m_redY[run];              // redY
      outWS->dataE(2)[i] = m_redE[run];              // redE
      outWS->dataY(3)[i] = m_greenY[run];            // greenY
      outWS->dataE(3)[i] = m_greenE[run];            // greenE
      outWS->dataY(4)[i] = m_sumY[run];              // sumY
      outWS->dataE(4)[i] = m_sumE[run];              // sumE
      i++;
    }
  }
  // Set the title!
  outWS->setTitle(m_allProperties);

  // Save results to ADS
  // We can't set an output property to store the results as this algorithm
  // is executed as a child algorithm in the Muon ALC interface
  // If current results were saved as a property we couln't used
  // the functionality to re-use previous results in ALC
  AnalysisDataService::Instance().addOrReplace(m_currResName, outWS);
}
Beispiel #16
0
void SavePHX::exec() {
 
  // Get the input workspace
  MatrixWorkspace_sptr inputWorkspace = getProperty("InputWorkspace");

  // Get the sample position
  const Kernel::V3D samplePos =
      inputWorkspace->getInstrument()->getSample()->getPos();

  // Retrieve the filename from the properties
  const std::string filename = getProperty("Filename");

  // Get a pointer to the sample
  IObjComponent_const_sptr sample =
      inputWorkspace->getInstrument()->getSample();

  std::ofstream outPHX_file(filename.c_str());

  if (!outPHX_file) {
    g_log.error("Failed to open (PHX) file:" + filename);
    throw Kernel::Exception::FileError("Failed to open (PHX) file:",
        filename);
  }

   // execute the subalgorithm to calculate the detector's parameters;
       IAlgorithm_sptr   spCalcDetPar = this->createSubAlgorithm("FindDetectorsPar", 0, 1, true, 1);
       spCalcDetPar->initialize();
       spCalcDetPar->setPropertyValue("InputWorkspace", inputWorkspace->getName());
       spCalcDetPar->setPropertyValue("ReturnLinearRanges", "0");
       // in test mode, request the subalgortithm to create output workspace and add it to dataservice
       if(!det_par_ws_name.empty()){
           spCalcDetPar->setPropertyValue("OutputParTable",det_par_ws_name);
       }

        // let's not do this for the time being
 /* std::string parFileName = this->getPropertyValue("ParFile");
     if(!(parFileName.empty()||parFileName=="not_used.par")){
               spCalcDetPar->setPropertyValue("ParFile",parFileName);
                   }*/
      spCalcDetPar->execute();
      //
     FindDetectorsPar * pCalcDetPar = dynamic_cast<FindDetectorsPar *>(spCalcDetPar.get());
     if(!pCalcDetPar){	  // "can not get pointer to FindDetectorsPar algorithm"
          throw(std::bad_cast());
      }
      const std::vector<double> & azimuthal           = pCalcDetPar->getAzimuthal();
      const std::vector<double> & polar               = pCalcDetPar->getPolar();
      const std::vector<double> & azimuthal_width     = pCalcDetPar->getAzimWidth();
      const std::vector<double> & polar_width         = pCalcDetPar->getPolarWidth();
      const std::vector<double> & secondary_flightpath= pCalcDetPar->getFlightPath();
      const std::vector<size_t> & det_ID              = pCalcDetPar->getDetID();


      size_t nDetectors = pCalcDetPar->getNDetectors();

  
   // Write the number of detectors to the file.
     outPHX_file <<" "<< nDetectors << std::endl;

   for (size_t i = 0; i < nDetectors; ++i) {
    // verify if no detector defined;
    volatile double NanID = azimuthal[i];
    if(NanID !=azimuthal[i] )continue; // skip NaN -s

      // Now write all the detector info.
      outPHX_file << std::fixed << std::setprecision(3);
      outPHX_file <<" "<<secondary_flightpath[i]<<"\t 0 \t\t" << polar[i] << " \t" << azimuthal[i] << " \t"
          << polar_width[i] << " \t" << azimuthal_width[i] << " \t\t"
          << det_ID[i] << std::endl;

  }

  // Close the file
  outPHX_file.close();
}
/**  Calculate the integral asymmetry for a pair of workspaces (red & green).
*   @param ws_red :: The red workspace
*   @param ws_green :: The green workspace
*   @param Y :: Reference to a variable receiving the value of asymmetry
*   @param E :: Reference to a variable receiving the value of the error
*/
void PlotAsymmetryByLogValue::calcIntAsymmetry(MatrixWorkspace_sptr ws_red,
                                               MatrixWorkspace_sptr ws_green,
                                               double &Y, double &E) {
  if (!m_int) { //  "Differential asymmetry"

    MatrixWorkspace_sptr tmpWS = WorkspaceFactory::Instance().create(
        ws_red, 1, ws_red->readX(0).size(), ws_red->readY(0).size());

    for (size_t i = 0; i < tmpWS->dataY(0).size(); i++) {
      double FNORM = ws_green->readY(0)[i] + ws_red->readY(0)[i];
      FNORM = FNORM != 0.0 ? 1.0 / FNORM : 1.0;
      double BNORM = ws_green->readY(1)[i] + ws_red->readY(1)[i];
      BNORM = BNORM != 0.0 ? 1.0 / BNORM : 1.0;
      double ZF = (ws_green->readY(0)[i] - ws_red->readY(0)[i]) * FNORM;
      double ZB = (ws_green->readY(1)[i] - ws_red->readY(1)[i]) * BNORM;
      tmpWS->dataY(0)[i] = ZB - ZF;
      tmpWS->dataE(0)[i] = (1.0 + ZF * ZF) * FNORM + (1.0 + ZB * ZB) * BNORM;
    }

    IAlgorithm_sptr integr = createChildAlgorithm("Integration");
    integr->setProperty("InputWorkspace", tmpWS);
    integr->setProperty("RangeLower", m_minTime);
    integr->setProperty("RangeUpper", m_maxTime);
    integr->execute();
    MatrixWorkspace_sptr out = integr->getProperty("OutputWorkspace");

    Y = out->readY(0)[0] / static_cast<double>(tmpWS->dataY(0).size());
    E = out->readE(0)[0] / static_cast<double>(tmpWS->dataY(0).size());
  } else {
    //  "Integral asymmetry"
    IAlgorithm_sptr integr = createChildAlgorithm("Integration");
    integr->setProperty("InputWorkspace", ws_red);
    integr->setProperty("RangeLower", m_minTime);
    integr->setProperty("RangeUpper", m_maxTime);
    integr->execute();
    MatrixWorkspace_sptr intWS_red = integr->getProperty("OutputWorkspace");

    integr = createChildAlgorithm("Integration");
    integr->setProperty("InputWorkspace", ws_green);
    integr->setProperty("RangeLower", m_minTime);
    integr->setProperty("RangeUpper", m_maxTime);
    integr->execute();
    MatrixWorkspace_sptr intWS_green = integr->getProperty("OutputWorkspace");

    double YIF = (intWS_green->readY(0)[0] - intWS_red->readY(0)[0]) /
                 (intWS_green->readY(0)[0] + intWS_red->readY(0)[0]);
    double YIB = (intWS_green->readY(1)[0] - intWS_red->readY(1)[0]) /
                 (intWS_green->readY(1)[0] + intWS_red->readY(1)[0]);

    Y = YIB - YIF;

    double VARIF =
        (1.0 + YIF * YIF) / (intWS_green->readY(0)[0] + intWS_red->readY(0)[0]);
    double VARIB =
        (1.0 + YIB * YIB) / (intWS_green->readY(1)[0] + intWS_red->readY(1)[0]);

    E = sqrt(VARIF + VARIB);
  }
}
Beispiel #18
0
void SmoothData::exec()
{
  // Get the input properties
  MatrixWorkspace_const_sptr inputWorkspace = getProperty("InputWorkspace");

  int npts = getProperty("NPoints");
  // Number of smoothing points must always be an odd number, so add 1 if it isn't.
  if (!(npts%2))
  {
    g_log.information("Adding 1 to number of smoothing points, since it must always be odd");
    ++npts;
  }

  // Check that the number of points in the smoothing isn't larger than the spectrum length
  const int vecSize = static_cast<int>(inputWorkspace->blocksize());
  if ( npts >= vecSize )
  {
    g_log.error("The number of averaging points requested is larger than the spectrum length");
    throw std::out_of_range("The number of averaging points requested is larger than the spectrum length");
  }
  const int halfWidth = (npts-1)/2;

  // Create the output workspace
  MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create(inputWorkspace);

  Progress progress(this,0.0,1.0,inputWorkspace->getNumberHistograms());
  PARALLEL_FOR2(inputWorkspace,outputWorkspace)
  // Loop over all the spectra in the workspace
  for (int i = 0; i < static_cast<int>(inputWorkspace->getNumberHistograms()); ++i)
  {
    PARALLEL_START_INTERUPT_REGION
    // Copy the X data over. Preserves data sharing if present in input workspace.
    outputWorkspace->setX(i,inputWorkspace->refX(i));

    // Now get references to the Y & E vectors in the input and output workspaces
    const MantidVec &Y = inputWorkspace->readY(i);
    const MantidVec &E = inputWorkspace->readE(i);
    MantidVec &newY = outputWorkspace->dataY(i);
    MantidVec &newE = outputWorkspace->dataE(i);

    // Use total to help hold our moving average
    double total = 0.0, totalE = 0.0;
    // First push the values ahead of the current point onto total
    for (int i = 0; i < halfWidth; ++i)
    {
      if ( Y[i] == Y[i] ) total += Y[i]; // Exclude if NaN
      totalE += E[i]*E[i];
    }
    // Now calculate the smoothed values for the 'end' points, where the number contributing
    // to the smoothing will be less than NPoints
    for (int j = 0; j <= halfWidth; ++j)
    {
      const int index = j+halfWidth;
      if ( Y[index] == Y[index] ) total += Y[index]; // Exclude if NaN
      newY[j] = total/(index+1);
      totalE += E[index]*E[index];
      newE[j] = sqrt(totalE)/(index+1);
    }
    // This is the main part, where each data point is the average of NPoints points centred on the
    // current point. Note that the statistical error will be reduced by sqrt(npts) because more
    // data is now contributing to each point.
    for (int k = halfWidth+1; k < vecSize-halfWidth; ++k)
    {
      const int kp = k+halfWidth;
      const int km = k-halfWidth-1;
      total += (Y[kp]!=Y[kp] ? 0.0 : Y[kp]) - (Y[km]!=Y[km] ? 0.0 : Y[km]); // Exclude if NaN
      newY[k] = total/npts;
      totalE += E[kp]*E[kp] - E[km]*E[km];
      // Use of a moving average can lead to rounding error where what should be 
      // zero actually comes out as a tiny negative number - bad news for sqrt so protect
      newE[k] = std::sqrt(std::abs(totalE))/npts;
    }
    // This deals with the 'end' at the tail of each spectrum
    for (int l = vecSize-halfWidth; l < vecSize; ++l)
    {
      const int index = l-halfWidth;
      total -= (Y[index-1]!=Y[index-1] ? 0.0 : Y[index-1]); // Exclude if NaN
      newY[l] = total/(vecSize-index);
      totalE -= E[index-1]*E[index-1];
      newE[l] = std::sqrt(std::abs(totalE))/(vecSize-index);
    }
    progress.report();
    PARALLEL_END_INTERUPT_REGION
  } // Loop over spectra
  PARALLEL_CHECK_INTERUPT_REGION

  // Set the output workspace to its property
  setProperty("OutputWorkspace", outputWorkspace);
}
/** Execute the algorithm.
 */
void ConvertToDetectorFaceMD::exec() {
  // TODO convert matrix to event as needed
  MatrixWorkspace_sptr mws = this->getProperty("InputWorkspace");

  in_ws = boost::dynamic_pointer_cast<EventWorkspace>(mws);
  if (!in_ws)
    throw std::runtime_error("InputWorkspace is not an EventWorkspace");

  // Fill the map, throw if there are grouped pixels.
  m_detID_to_WI =
      in_ws->getDetectorIDToWorkspaceIndexVector(m_detID_to_WI_offset, true);

  // Get the map of the banks we'll display
  std::map<int, RectangularDetector_const_sptr> banks = this->getBanks();

  // Find the size in the TOF dimension
  double tof_min, tof_max;
  Axis *ax0 = in_ws->getAxis(0);
  in_ws->getXMinMax(tof_min, tof_max);
  if (ax0->getValue(0) < tof_min)
    tof_min = ax0->getValue(0);
  if (ax0->getValue(ax0->length() - 1) > tof_max)
    tof_max = ax0->getValue(ax0->length() - 1);

  // Get MDFrame of General Frame type
  Mantid::Geometry::GeneralFrame framePixel(
      Mantid::Geometry::GeneralFrame::GeneralFrameName, "pixel");
  Mantid::Geometry::GeneralFrame frameTOF(
      Mantid::Geometry::GeneralFrame::GeneralFrameName, ax0->unit()->label());

  // ------------------ Build all the dimensions ----------------------------
  MDHistoDimension_sptr dimX(
      new MDHistoDimension("x", "x", framePixel, static_cast<coord_t>(0),
                           static_cast<coord_t>(m_numXPixels), m_numXPixels));
  MDHistoDimension_sptr dimY(
      new MDHistoDimension("y", "y", framePixel, static_cast<coord_t>(0),
                           static_cast<coord_t>(m_numYPixels), m_numYPixels));
  std::string TOFname = ax0->title();
  if (TOFname.empty())
    TOFname = ax0->unit()->unitID();
  MDHistoDimension_sptr dimTOF(new MDHistoDimension(
      TOFname, TOFname, frameTOF, static_cast<coord_t>(tof_min),
      static_cast<coord_t>(tof_max), ax0->length()));

  std::vector<IMDDimension_sptr> dims{dimX, dimY, dimTOF};

  if (banks.size() > 1) {
    Mantid::Geometry::GeneralFrame frameNumber(
        Mantid::Geometry::GeneralFrame::GeneralFrameName, "number");
    int min = banks.begin()->first;
    int max = banks.rbegin()->first + 1;
    MDHistoDimension_sptr dimBanks(new MDHistoDimension(
        "bank", "bank", frameNumber, static_cast<coord_t>(min),
        static_cast<coord_t>(max), max - min));
    dims.push_back(dimBanks);
  }

  // --------- Create the workspace with the right number of dimensions
  // ----------
  size_t nd = dims.size();
  IMDEventWorkspace_sptr outWS =
      MDEventFactory::CreateMDWorkspace(nd, "MDEvent");
  outWS->initGeometry(dims);
  outWS->initialize();
  this->setBoxController(outWS->getBoxController(), mws->getInstrument());
  outWS->splitBox();

  MDEventWorkspace3::sptr outWS3 =
      boost::dynamic_pointer_cast<MDEventWorkspace3>(outWS);
  MDEventWorkspace4::sptr outWS4 =
      boost::dynamic_pointer_cast<MDEventWorkspace4>(outWS);

  // Copy ExperimentInfo (instrument, run, sample) to the output WS
  ExperimentInfo_sptr ei(in_ws->cloneExperimentInfo());
  uint16_t runIndex = outWS->addExperimentInfo(ei);

  // ---------------- Convert each bank --------------------------------------
  for (auto &bank : banks) {
    int bankNum = bank.first;
    RectangularDetector_const_sptr det = bank.second;
    for (int x = 0; x < det->xpixels(); x++)
      for (int y = 0; y < det->ypixels(); y++) {
        // Find the workspace index for this pixel coordinate
        detid_t detID = det->getDetectorIDAtXY(x, y);
        size_t wi = m_detID_to_WI[detID + m_detID_to_WI_offset];
        if (wi >= in_ws->getNumberHistograms())
          throw std::runtime_error("Invalid workspace index found in bank " +
                                   det->getName() + "!");

        coord_t xPos = static_cast<coord_t>(x);
        coord_t yPos = static_cast<coord_t>(y);
        coord_t bankPos = static_cast<coord_t>(bankNum);

        EventList &el = in_ws->getSpectrum(wi);

        // We want to bind to the right templated function, so we have to know
        // the type of TofEvent contained in the EventList.
        boost::function<void()> func;
        switch (el.getEventType()) {
        case TOF:
          if (nd == 3)
            this->convertEventList<TofEvent, MDEvent<3>, 3>(
                outWS3, wi, xPos, yPos, bankPos, runIndex, detID);
          else if (nd == 4)
            this->convertEventList<TofEvent, MDEvent<4>, 4>(
                outWS4, wi, xPos, yPos, bankPos, runIndex, detID);
          break;
        case WEIGHTED:
          if (nd == 3)
            this->convertEventList<WeightedEvent, MDEvent<3>, 3>(
                outWS3, wi, xPos, yPos, bankPos, runIndex, detID);
          else if (nd == 4)
            this->convertEventList<WeightedEvent, MDEvent<4>, 4>(
                outWS4, wi, xPos, yPos, bankPos, runIndex, detID);
          break;
        case WEIGHTED_NOTIME:
          if (nd == 3)
            this->convertEventList<WeightedEventNoTime, MDEvent<3>, 3>(
                outWS3, wi, xPos, yPos, bankPos, runIndex, detID);
          else if (nd == 4)
            this->convertEventList<WeightedEventNoTime, MDEvent<4>, 4>(
                outWS4, wi, xPos, yPos, bankPos, runIndex, detID);
          break;
        default:
          throw std::runtime_error("EventList had an unexpected data type!");
        }
      }
  }

  // ---------------------- Perform all box splitting ---------------
  ThreadScheduler *ts = new ThreadSchedulerLargestCost();
  ThreadPool tp(ts);
  outWS->splitAllIfNeeded(ts);
  tp.joinAll();
  outWS->refreshCache();

  // Save the output workspace
  this->setProperty("OutputWorkspace", outWS);
}
Beispiel #20
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;
}
/**  Calculate the integral asymmetry for a workspace.
*   The calculation is done by MuonAsymmetryCalc and SimpleIntegration algorithms.
*   @param ws :: The workspace
*   @param Y :: Reference to a variable receiving the value of asymmetry
*   @param E :: Reference to a variable receiving the value of the error
*/
void PlotAsymmetryByLogValue::calcIntAsymmetry(API::MatrixWorkspace_sptr ws, double& Y, double& E)
{
    Property* startXprop = getProperty("TimeMin");
    Property* endXprop = getProperty("TimeMax");
    bool setX = !startXprop->isDefault() && !endXprop->isDefault();
    double startX(0.0),endX(0.0);
    if (setX)
    {
        startX = getProperty("TimeMin");
        endX = getProperty("TimeMax");
    }
    if (!m_int)
    {   //  "Differential asymmetry"
        IAlgorithm_sptr asym = createChildAlgorithm("AsymmetryCalc");
        asym->initialize();
        asym->setProperty("InputWorkspace",ws);
        asym->setPropertyValue("OutputWorkspace","tmp");
        if ( !m_autogroup )
        {
            asym->setProperty("ForwardSpectra",m_forward_list);
            asym->setProperty("BackwardSpectra",m_backward_list);
        }
        asym->execute();
        MatrixWorkspace_sptr asymWS = asym->getProperty("OutputWorkspace");

        IAlgorithm_sptr integr = createChildAlgorithm("Integration");
        integr->setProperty("InputWorkspace",asymWS);
        integr->setPropertyValue("OutputWorkspace","tmp");
        if (setX)
        {
            integr->setProperty("RangeLower",startX);
            integr->setProperty("RangeUpper",endX);
        }
        integr->execute();
        API::MatrixWorkspace_sptr out = integr->getProperty("OutputWorkspace");

        Y = out->readY(0)[0];
        E = out->readE(0)[0];
    }
    else
    {
        //  "Integral asymmetry"
        IAlgorithm_sptr integr = createChildAlgorithm("Integration");
        integr->setProperty("InputWorkspace", ws);
        integr->setPropertyValue("OutputWorkspace","tmp");
        if (setX)
        {
            integr->setProperty("RangeLower",startX);
            integr->setProperty("RangeUpper",endX);
        }
        integr->execute();
        API::MatrixWorkspace_sptr intWS = integr->getProperty("OutputWorkspace");

        IAlgorithm_sptr asym = createChildAlgorithm("AsymmetryCalc");
        asym->initialize();
        asym->setProperty("InputWorkspace",intWS);
        asym->setPropertyValue("OutputWorkspace","tmp");
        if ( !m_autogroup )
        {
            asym->setProperty("ForwardSpectra",m_forward_list);
            asym->setProperty("BackwardSpectra",m_backward_list);
        }
        asym->execute();
        MatrixWorkspace_sptr out = asym->getProperty("OutputWorkspace");

        Y = out->readY(0)[0];
        E = out->readE(0)[0];

    }


}
Beispiel #22
0
void SofQWCentre::exec() {
  using namespace Geometry;

  MatrixWorkspace_const_sptr inputWorkspace = getProperty("InputWorkspace");

  // Do the full check for common binning
  if (!WorkspaceHelpers::commonBoundaries(*inputWorkspace)) {
    g_log.error(
        "The input workspace must have common binning across all spectra");
    throw std::invalid_argument(
        "The input workspace must have common binning across all spectra");
  }

  std::vector<double> verticalAxis;
  MatrixWorkspace_sptr outputWorkspace = setUpOutputWorkspace(
      inputWorkspace, getProperty("QAxisBinning"), verticalAxis);
  setProperty("OutputWorkspace", outputWorkspace);

  // Holds the spectrum-detector mapping
  std::vector<specnum_t> specNumberMapping;
  std::vector<detid_t> detIDMapping;

  m_EmodeProperties.initCachedValues(*inputWorkspace, this);
  int emode = m_EmodeProperties.m_emode;

  // Get a pointer to the instrument contained in the workspace
  Instrument_const_sptr instrument = inputWorkspace->getInstrument();

  // Get the distance between the source and the sample (assume in metres)
  IComponent_const_sptr source = instrument->getSource();
  IComponent_const_sptr sample = instrument->getSample();
  V3D beamDir = sample->getPos() - source->getPos();
  beamDir.normalize();

  try {
    double l1 = source->getDistance(*sample);
    g_log.debug() << "Source-sample distance: " << l1 << '\n';
  } catch (Exception::NotFoundError &) {
    g_log.error("Unable to calculate source-sample distance");
    throw Exception::InstrumentDefinitionError(
        "Unable to calculate source-sample distance",
        inputWorkspace->getTitle());
  }

  // Conversion constant for E->k. k(A^-1) = sqrt(energyToK*E(meV))
  const double energyToK = 8.0 * M_PI * M_PI * PhysicalConstants::NeutronMass *
                           PhysicalConstants::meV * 1e-20 /
                           (PhysicalConstants::h * PhysicalConstants::h);

  // Loop over input workspace bins, reassigning data to correct bin in output
  // qw workspace
  const size_t numHists = inputWorkspace->getNumberHistograms();
  const size_t numBins = inputWorkspace->blocksize();
  Progress prog(this, 0.0, 1.0, numHists);
  for (int64_t i = 0; i < int64_t(numHists); ++i) {
    try {
      // Now get the detector object for this histogram
      IDetector_const_sptr spectrumDet = inputWorkspace->getDetector(i);
      if (spectrumDet->isMonitor())
        continue;

      const double efixed = m_EmodeProperties.getEFixed(*spectrumDet);

      // For inelastic scattering the simple relationship q=4*pi*sinTheta/lambda
      // does not hold. In order to
      // be completely general we must calculate the momentum transfer by
      // calculating the incident and final
      // wave vectors and then use |q| = sqrt[(ki - kf)*(ki - kf)]
      DetectorGroup_const_sptr detGroup =
          boost::dynamic_pointer_cast<const DetectorGroup>(spectrumDet);
      std::vector<IDetector_const_sptr> detectors;
      if (detGroup) {
        detectors = detGroup->getDetectors();
      } else {
        detectors.push_back(spectrumDet);
      }

      const size_t numDets = detectors.size();
      // cache to reduce number of static casts
      const double numDets_d = static_cast<double>(numDets);
      const auto &Y = inputWorkspace->y(i);
      const auto &E = inputWorkspace->e(i);
      const auto &X = inputWorkspace->x(i);

      // Loop over the detectors and for each bin calculate Q
      for (size_t idet = 0; idet < numDets; ++idet) {
        IDetector_const_sptr det = detectors[idet];
        // Calculate kf vector direction and then Q for each energy bin
        V3D scatterDir = (det->getPos() - sample->getPos());
        scatterDir.normalize();
        for (size_t j = 0; j < numBins; ++j) {
          const double deltaE = 0.5 * (X[j] + X[j + 1]);
          // Compute ki and kf wave vectors and therefore q = ki - kf
          double ei(0.0), ef(0.0);
          if (emode == 1) {
            ei = efixed;
            ef = efixed - deltaE;
            if (ef < 0) {
              std::string mess =
                  "Energy transfer requested in Direct mode exceeds incident "
                  "energy.\n Found for det ID: " +
                  std::to_string(idet) + " bin No " + std::to_string(j) +
                  " with Ei=" + boost::lexical_cast<std::string>(efixed) +
                  " and energy transfer: " +
                  boost::lexical_cast<std::string>(deltaE);
              throw std::runtime_error(mess);
            }
          } else {
            ei = efixed + deltaE;
            ef = efixed;
            if (ef < 0) {
              std::string mess =
                  "Incident energy of a neutron is negative. Are you trying to "
                  "process Direct data in Indirect mode?\n Found for det ID: " +
                  std::to_string(idet) + " bin No " + std::to_string(j) +
                  " with efied=" + boost::lexical_cast<std::string>(efixed) +
                  " and energy transfer: " +
                  boost::lexical_cast<std::string>(deltaE);
              throw std::runtime_error(mess);
            }
          }

          if (ei < 0)
            throw std::runtime_error(
                "Negative incident energy. Check binning.");

          const V3D ki = beamDir * sqrt(energyToK * ei);
          const V3D kf = scatterDir * (sqrt(energyToK * (ef)));
          const double q = (ki - kf).norm();

          // Test whether it's in range of the Q axis
          if (q < verticalAxis.front() || q > verticalAxis.back())
            continue;
          // Find which q bin this point lies in
          const MantidVec::difference_type qIndex =
              std::upper_bound(verticalAxis.begin(), verticalAxis.end(), q) -
              verticalAxis.begin() - 1;

          // Add this spectra-detector pair to the mapping
          specNumberMapping.push_back(
              outputWorkspace->getSpectrum(qIndex).getSpectrumNo());
          detIDMapping.push_back(det->getID());

          // And add the data and it's error to that bin, taking into account
          // the number of detectors contributing to this bin
          outputWorkspace->mutableY(qIndex)[j] += Y[j] / numDets_d;
          // Standard error on the average
          outputWorkspace->mutableE(qIndex)[j] =
              sqrt((pow(outputWorkspace->e(qIndex)[j], 2) + pow(E[j], 2)) /
                   numDets_d);
        }
      }

    } catch (Exception::NotFoundError &) {
      // Get to here if exception thrown when calculating distance to detector
      // Presumably, if we get to here the spectrum will be all zeroes anyway
      // (from conversion to E)
      continue;
    }
    prog.report();
  }

  // If the input workspace was a distribution, need to divide by q bin width
  if (inputWorkspace->isDistribution())
    this->makeDistribution(outputWorkspace, verticalAxis);

  // Set the output spectrum-detector mapping
  SpectrumDetectorMapping outputDetectorMap(specNumberMapping, detIDMapping);
  outputWorkspace->updateSpectraUsing(outputDetectorMap);

  // Replace any NaNs in outputWorkspace with zeroes
  if (this->getProperty("ReplaceNaNs")) {
    auto replaceNans = this->createChildAlgorithm("ReplaceSpecialValues");
    replaceNans->setChild(true);
    replaceNans->initialize();
    replaceNans->setProperty("InputWorkspace", outputWorkspace);
    replaceNans->setProperty("OutputWorkspace", outputWorkspace);
    replaceNans->setProperty("NaNValue", 0.0);
    replaceNans->setProperty("InfinityValue", 0.0);
    replaceNans->setProperty("BigNumberThreshold", DBL_MAX);
    replaceNans->execute();
  }
}
Beispiel #23
0
API::MatrixWorkspace_sptr
CreateFloodWorkspace::removeBackground(API::MatrixWorkspace_sptr ws) {
  g_log.information() << "Remove background "
                      << getPropertyValue(Prop::BACKGROUND) << '\n';
  auto fitWS = transpose(ws);
  auto const &x = fitWS->x(0);

  // Define the fitting interval
  double startX = getProperty(Prop::START_X);
  double endX = getProperty(Prop::END_X);
  std::vector<double> excludeFromFit;
  if (isDefault(Prop::START_X)) {
    startX = x.front();
  } else {
    excludeFromFit.push_back(x.front());
    excludeFromFit.push_back(startX);
  }
  if (isDefault(Prop::END_X)) {
    endX = x.back();
  } else {
    excludeFromFit.push_back(endX);
    excludeFromFit.push_back(x.back());
  }

  // Exclude any bad detectors.
  for (auto i : m_excludedSpectra) {
    excludeFromFit.push_back(i);
    excludeFromFit.push_back(i);
  }

  std::string const function = getBackgroundFunction();

  // Fit the data to determine unwanted background
  auto alg = createChildAlgorithm("Fit", 0.9, 0.99);
  alg->setProperty("Function", function);
  alg->setProperty("InputWorkspace", fitWS);
  alg->setProperty("WorkspaceIndex", 0);
  if (!excludeFromFit.empty()) {
    alg->setProperty("Exclude", excludeFromFit);
  }
  alg->setProperty("Output", "fit");
  alg->execute();

  IFunction_sptr func = alg->getProperty("Function");
  g_log.information() << "Background function parameters:\n";
  for (size_t i = 0; i < func->nParams(); ++i) {
    g_log.information() << "    " << func->parameterName(i) << ": "
                        << func->getParameter(i) << '\n';
  }

  // Divide the workspace by the fitted curve to remove the background
  // and scale to values around 1
  MatrixWorkspace_sptr bkgWS = alg->getProperty("OutputWorkspace");
  auto const &bkg = bkgWS->y(1);
  auto const nHisto = static_cast<int>(ws->getNumberHistograms());
  PARALLEL_FOR_IF(Kernel::threadSafe(*ws, *bkgWS))
  for (int i = 0; i < nHisto; ++i) {
    PARALLEL_START_INTERUPT_REGION
    auto const xVal = x[i];
    if (isExcludedSpectrum(xVal)) {
      ws->mutableY(i)[0] = VERY_BIG_VALUE;
      ws->mutableE(i)[0] = 0.0;
    } else if (xVal >= startX && xVal <= endX) {
      auto const background = bkg[i];
      if (background <= 0.0) {
        throw std::runtime_error(
            "Background is expected to be positive, found value " +
            std::to_string(background) + " at spectrum with workspace index " +
            std::to_string(i));
      }
      ws->mutableY(i)[0] /= background;
      ws->mutableE(i)[0] /= background;
    } else {
      ws->mutableY(i)[0] = 1.0;
      ws->mutableE(i)[0] = 0.0;
    }
    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION

  // Remove the logs
  ws->setSharedRun(make_cow<Run>());

  return ws;
}
  /**
   * Determine the instrument from the various input parameters.
   *
   * @return The correct instrument.
   */
  Instrument_const_sptr CreateChunkingFromInstrument::getInstrument()
  {
    // try the input workspace
    MatrixWorkspace_sptr inWS = getProperty(PARAM_IN_WKSP);
    if (inWS)
    {
      return inWS->getInstrument();
    }

    // temporary workspace to hang everything else off of
    MatrixWorkspace_sptr tempWS(new Workspace2D());
    // name of the instrument
    string instName = getPropertyValue(PARAM_INST_NAME);

    // see if there is an input file
    string filename = getPropertyValue(PARAM_IN_FILE);
    if (!filename.empty())
    {
      string top_entry_name("entry"); // TODO make more flexible

      // get the instrument name from the filename
      size_t n = filename.rfind('/');
      if (n != std::string::npos)
      {
        std::string temp = filename.substr(n+1, filename.size()-n-1);
        n = temp.find('_');
        if (n != std::string::npos && n > 0)
        {
          instName = temp.substr(0, n);
        }
      }

      // read information from the nexus file itself
      try {
        NeXus::File nxsfile(filename);

        // get the run start time
        string start_time;
        nxsfile.openGroup(top_entry_name, "NXentry");
        nxsfile.readData("start_time", start_time);
        tempWS->mutableRun().addProperty("run_start", DateAndTime(start_time).toISO8601String(), true );

        // get the instrument name
        nxsfile.openGroup("instrument", "NXinstrument");
        nxsfile.readData("name", instName);
        nxsfile.closeGroup();

        // Test if IDF exists in file, move on quickly if not
        nxsfile.openPath("instrument/instrument_xml");
        nxsfile.close();
        IAlgorithm_sptr loadInst= createChildAlgorithm("LoadIDFFromNexus",0.0,0.2);
        // Now execute the Child Algorithm. Catch and log any error, but don't stop.
        try
        {
          loadInst->setPropertyValue("Filename", filename);
          loadInst->setProperty<MatrixWorkspace_sptr> ("Workspace", tempWS);
          loadInst->setPropertyValue("InstrumentParentPath",top_entry_name);
          loadInst->execute();
        }
        catch( std::invalid_argument&)
        {
          g_log.error("Invalid argument to LoadIDFFromNexus Child Algorithm ");
        }
        catch (std::runtime_error&)
        {
          g_log.debug("No instrument definition found in "+filename+" at "+top_entry_name+"/instrument");
        }

        if ( loadInst->isExecuted() )
          return tempWS->getInstrument();
        else
          g_log.information("No IDF loaded from Nexus file.");

      } catch (::NeXus::Exception&) {
        g_log.information("No instrument definition found in "+filename+" at "+top_entry_name+"/instrument");
      }
    }

    // run LoadInstrument if other methods have not run
    string instFilename = getPropertyValue(PARAM_INST_FILE);

    Algorithm_sptr childAlg = createChildAlgorithm("LoadInstrument",0.0,0.2);
    childAlg->setProperty<MatrixWorkspace_sptr>("Workspace", tempWS);
    childAlg->setPropertyValue("Filename", instFilename);
    childAlg->setPropertyValue("InstrumentName", instName);
    childAlg->executeAsChildAlg();
    return tempWS->getInstrument();
  }
Beispiel #25
0
void FFTDerivative::execRealFFT()
{

  MatrixWorkspace_sptr inWS = getProperty("InputWorkspace");
  MatrixWorkspace_sptr outWS;

  size_t n = inWS->getNumberHistograms();
  API::Progress progress(this,0,1,n);

  size_t ny = inWS->readY(0).size();
  size_t nx = inWS->readX(0).size();

  // Workspace for holding a copy of a spectrum. Each spectrum is symmetrized to minimize
  // possible edge effects.
  MatrixWorkspace_sptr copyWS = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>
    (Mantid::API::WorkspaceFactory::Instance().create(inWS,1,nx+ny,ny+ny));

  bool isHist = (nx != ny);

  for(size_t spec = 0; spec < n; ++spec)
  {

    const Mantid::MantidVec& x0 = inWS->readX(spec);
    const Mantid::MantidVec& y0 = inWS->readY(spec);

    Mantid::MantidVec& x1 = copyWS->dataX(0);
    Mantid::MantidVec& y1 = copyWS->dataY(0);

    double xx = 2*x0[0];

    x1[ny] = x0[0];
    y1[ny] = y0[0];

    for(size_t i = 1; i < ny; ++i)
    {
      size_t j1 = ny - i;
      size_t j2 = ny + i;
      x1[j1] = xx - x0[i];
      x1[j2] = x0[i];
      y1[j1] = y1[j2] = y0[i];
    }

    x1[0] = 2*x1[1] - x1[2];
    y1[0] = y0.back();

    if (isHist)
    {
      x1[y1.size()] = x0[ny];
    }

    // Transform symmetrized spectrum
    IAlgorithm_sptr fft = createSubAlgorithm("RealFFT");
    fft->setProperty("InputWorkspace",copyWS);
    fft->setProperty("WorkspaceIndex",0);
    fft->setProperty("Transform","Forward");
    fft->execute();

    MatrixWorkspace_sptr transWS = fft->getProperty("OutputWorkspace");

    Mantid::MantidVec& nu = transWS->dataX(0);
    Mantid::MantidVec& re = transWS->dataY(0);
    Mantid::MantidVec& im = transWS->dataY(1);

    int dn = getProperty("Order");
    bool swap_re_im = dn % 2 != 0;
    int sign_re =  1;
    int sign_im = -1;
    switch(dn % 4)
    {
    case 1: sign_re =  1; sign_im = -1; break;
    case 2: sign_re = -1; sign_im = -1; break;
    case 3: sign_re = -1; sign_im =  1; break;
    }
    // Multiply the transform by (2*pi*i*w)**dn
    for(size_t j=0; j < re.size(); ++j)
    {
      double w = 2 * M_PI * nu[j];
      double ww = w;
      for(int k = dn; k > 1; --k)
      {
        ww *= w;
      }
      double a = sign_re * re[j]*ww;
      double b = sign_im * im[j]*ww;
      if (swap_re_im)
      {
        re[j] = b;
        im[j] = a;
      }
      else
      {
        re[j] = a;
        im[j] = b;
      }
    }

    // Inverse transform
    fft = createSubAlgorithm("RealFFT");
    fft->setProperty("InputWorkspace",transWS);
    fft->setProperty("Transform","Backward");
    fft->execute();

    transWS = fft->getProperty("OutputWorkspace");

    size_t m2 = transWS->readY(0).size() / 2;
    size_t my = m2 + (transWS->readY(0).size() % 2 ? 1 : 0);
    size_t mx = my + (transWS->isHistogramData() ? 1 : 0);

    if (!outWS)
    {
      outWS = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>
        (Mantid::API::WorkspaceFactory::Instance().create(inWS,n,mx,my));
    }

    // Save the upper half of the inverse transform for output
    Mantid::MantidVec& x = outWS->dataX(spec);
    Mantid::MantidVec& y = outWS->dataY(spec);
    double dx = x1[0];
    std::copy(transWS->dataX(0).begin() + m2,transWS->dataX(0).end(),x.begin());
    std::transform(x.begin(),x.end(),x.begin(),std::bind2nd(std::plus<double>(),dx));
    std::copy(transWS->dataY(0).begin() + m2,transWS->dataY(0).end(),y.begin());

    // shift the data to make x and x0 match. using linear interpolation.
    if (x.size() != x0.size() && false)// TODO: doesn't work at the moment. needs to be working
    {
      std::cerr << "(my != x0.size()) " << x0[0] << "!=" << x[0] << std::endl;
      dx = x0[0] - x[0];
      assert(dx > 0.0);
      double f = (x0[0] - x[0]) / (x0[1] - x0[0]);
      for(size_t i = 0; i < my - 1; ++i)
      {
        y[i] += (y[i+1] - y[i]) * f;
        x[i] = x0[i];
      }
      x.back() += dx;

    }

    progress.report();

  }

  setProperty("OutputWorkspace",outWS);

}
/**  Checks input properties and compares them to previous values
*   @param is :: [output] Number of the first run
*   @param ie :: [output] Number of the last run
*/
void PlotAsymmetryByLogValue::checkProperties(size_t &is, size_t &ie) {

  // Log Value
  m_logName = getPropertyValue("LogValue");
  // Get function to apply to logValue
  m_logFunc = getPropertyValue("Function");
  // Get type of computation
  m_int = (getPropertyValue("Type") == "Integral");
  // Get grouping properties
  m_forward_list = getProperty("ForwardSpectra");
  m_backward_list = getProperty("BackwardSpectra");
  // Get green and red periods
  m_red = getProperty("Red");
  m_green = getProperty("Green");
  // Get time min and time max
  m_minTime = getProperty("TimeMin");
  m_maxTime = getProperty("TimeMax");
  // Get type of dead-time corrections
  m_dtcType = getPropertyValue("DeadTimeCorrType");
  m_dtcFile = getPropertyValue("DeadTimeCorrFile");
  // Get runs
  std::string firstFN = getProperty("FirstRun");
  std::string lastFN = getProperty("LastRun");

  // Parse run names and get the number of runs
  parseRunNames(firstFN, lastFN, m_filenameBase, m_filenameExt,
                m_filenameZeros);
  is = atoi(firstFN.c_str()); // starting run number
  ie = atoi(lastFN.c_str());  // last run number
  if (ie < is) {
    throw std::runtime_error(
        "First run number is greater than last run number");
  }

  // Create a string holding all the properties
  std::ostringstream ss;
  ss << m_filenameBase << "," << m_filenameExt << "," << m_filenameZeros << ",";
  ss << m_dtcType << "," << m_dtcFile << ",";
  ss << getPropertyValue("ForwardSpectra") << ","
     << getPropertyValue("BackwardSpectra") << ",";
  ss << m_int << "," << m_minTime << "," << m_maxTime << ",";
  ss << m_red << "," << m_green << ",";
  ss << m_logName << ", " << m_logFunc;
  m_allProperties = ss.str();

  // Check if we can re-use results from previous run
  // We can reuse results if:
  // 1. There is a ws in the ADS with name m_currResName
  // 2. It is a MatrixWorkspace
  // 3. It has a title equatl to m_allProperties
  // This ws stores previous results as described below
  if (AnalysisDataService::Instance().doesExist(m_currResName)) {
    MatrixWorkspace_sptr prevResults =
        AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(
            m_currResName);
    if (prevResults) {
      if (m_allProperties == prevResults->getTitle()) {
        // We can re-use results
        size_t nPoints = prevResults->blocksize();
        size_t nHisto = prevResults->getNumberHistograms();

        if (nHisto == 2) {
          // Only 'red' data
          for (size_t i = 0; i < nPoints; i++) {
            // The first spectrum contains: X -> run number, Y -> log value
            // The second spectrum contains: Y -> redY, E -> redE
            size_t run = static_cast<size_t>(prevResults->readX(0)[i]);
            if ((run >= is) && (run <= ie)) {
              m_logValue[run] = prevResults->readY(0)[i];
              m_redY[run] = prevResults->readY(1)[i];
              m_redE[run] = prevResults->readE(1)[i];
            }
          }
        } else {
          // 'Red' and 'Green' data
          for (size_t i = 0; i < nPoints; i++) {
            // The first spectrum contains: X -> run number, Y -> log value
            // The second spectrum contains: Y -> diffY, E -> diffE
            // The third spectrum contains: Y -> redY, E -> redE
            // The fourth spectrum contains: Y -> greenY, E -> greeE
            // The fifth spectrum contains: Y -> sumY, E -> sumE
            size_t run = static_cast<size_t>(prevResults->readX(0)[i]);
            if ((run >= is) && (run <= ie)) {
              m_logValue[run] = prevResults->readY(0)[i];
              m_diffY[run] = prevResults->readY(1)[i];
              m_diffE[run] = prevResults->readE(1)[i];
              m_redY[run] = prevResults->readY(2)[i];
              m_redE[run] = prevResults->readE(2)[i];
              m_greenY[run] = prevResults->readY(3)[i];
              m_greenE[run] = prevResults->readE(3)[i];
              m_sumY[run] = prevResults->readY(4)[i];
              m_sumE[run] = prevResults->readE(4)[i];
            }
          }
        }
      }
    }
  }
}
Beispiel #27
0
    /**
    *   Executes the algorithm.
    */
    void LoadSpec::exec()
    {
	  std::string filename = getProperty("Filename");
	  std::string separator = " "; //separator can be 1 or more spaces
	  std::ifstream file(filename.c_str());

	  file.seekg (0, std::ios::end);
	  Progress progress(this,0,1,static_cast<int>(file.tellg()));
	  file.seekg (0, std::ios::beg);

	  std::string str;

	  std::vector<DataObjects::Histogram1D> spectra;
	  //size_t iLine=0;    // line number
	  size_t ncols = 3;  // number of columns
	  int nSpectra = 0;
	  int nBins = 0; //number of rows
	  std::string first_character;
	  std::string axes_infos;

	  //bool numeric = true;
	  std::vector<double> input;

	  //determine the number of lines starting by #L
	  //as there is one per set of data
	  int spectra_nbr = 0;
	  while(getline(file,str))
	  {
		 if (str[0] == '#' && str[1] == 'L')
		 {
		   spectra_nbr++;
		 }
	  }

	  spectra.resize(spectra_nbr);
	  file.clear(); //end of file has been reached so we need to clear file state
	  file.seekg (0, std::ios::beg); //go back to beginning of file

	  int working_with_spectrum_nbr = -1; //spectrum number
	  while(getline(file,str))
	  {
	    progress.report(static_cast<int>(file.tellg()));

	    //line with data, need to be parsed by white spaces
	    if (!str.empty() && str[0] != '#')
	    {
	      typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
		  boost::char_separator<char> sep(" ");
		  tokenizer tok(str, sep);
		  ncols = 0;
		  for (tokenizer::iterator beg=tok.begin(); beg!=tok.end(); ++beg)
		  {
		    std::stringstream ss;
		    ss << *beg;
		    double d;
		    ss >> d;
  		    input.push_back(d);
		  }
	    }

	    if (str.empty())
	    {
		  if (working_with_spectrum_nbr != -1)
		  {
		    for(int j=0; j<static_cast<int>(input.size()-1); j++)
		    {
		      spectra[working_with_spectrum_nbr].dataX().push_back(input[j]);
			  j++;
			  spectra[working_with_spectrum_nbr].dataY().push_back(input[j]);
			  j++;
			  spectra[working_with_spectrum_nbr].dataE().push_back(input[j]);
			  nBins = j/3;
		    }
		  }
		  working_with_spectrum_nbr++;
		  input.clear();
	    }

	  } //end of read file

	  try
	  {
	    if (spectra_nbr == 0)
	      throw "Undefined number of spectra";

		if (working_with_spectrum_nbr == (spectra_nbr-1))
		{
		  for(int j=0; j<static_cast<int>(input.size()-1); j++)
		  {
		    spectra[working_with_spectrum_nbr].dataX().push_back(input[j]);
			j++;
			spectra[working_with_spectrum_nbr].dataY().push_back(input[j]);
			j++;
			spectra[working_with_spectrum_nbr].dataE().push_back(input[j]);
			nBins = j/3;
		  }
	    }
	  }
	  catch (...)
	  {
   	  }

	  try
	  {
	    nSpectra = spectra_nbr;
	    MatrixWorkspace_sptr localWorkspace = boost::dynamic_pointer_cast<MatrixWorkspace>
  	    (WorkspaceFactory::Instance().create("Workspace2D",nSpectra,nBins,nBins));

	    localWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create(getProperty("Unit"));

	    for(int i=0;i<nSpectra;i++)
	    {
		    localWorkspace->dataX(i) = spectra[i].dataX();
		    localWorkspace->dataY(i) = spectra[i].dataY();
		    localWorkspace->dataE(i) = spectra[i].dataE();
		    // Just have spectrum number start at 1 and count up
		    localWorkspace->getAxis(1)->spectraNo(i) = i+1;
	    }

	    setProperty("OutputWorkspace",localWorkspace);
	  }
	  catch (Exception::NotFoundError&)
	  {
	    // Asked for dimensionless workspace (obviously not in unit factory)
	  }

    }
/**  Populate output workspace with results
*   @param outWS :: [input/output] Output workspace to populate
*   @param nplots :: [input] Number of histograms
*/
void PlotAsymmetryByLogValue::populateOutputWorkspace(
    MatrixWorkspace_sptr &outWS, int nplots) {

  TextAxis *tAxis = new TextAxis(nplots);
  if (nplots == 1) {
    size_t i = 0;
    for (auto it = m_logValue.begin(); it != m_logValue.end(); ++it) {
      outWS->dataX(0)[i] = it->second;
      outWS->dataY(0)[i] = m_redY[it->first];
      outWS->dataE(0)[i] = m_redE[it->first];
      i++;
    }
    tAxis->setLabel(0, "Asymmetry");

  } else {
    size_t i = 0;
    for (auto it = m_logValue.begin(); it != m_logValue.end(); ++it) {
      outWS->dataX(0)[i] = it->second;
      outWS->dataY(0)[i] = m_diffY[it->first];
      outWS->dataE(0)[i] = m_diffE[it->first];
      outWS->dataX(1)[i] = it->second;
      outWS->dataY(1)[i] = m_redY[it->first];
      outWS->dataE(1)[i] = m_redE[it->first];
      outWS->dataX(2)[i] = it->second;
      outWS->dataY(2)[i] = m_greenY[it->first];
      outWS->dataE(2)[i] = m_greenE[it->first];
      outWS->dataX(3)[i] = it->second;
      outWS->dataY(3)[i] = m_sumY[it->first];
      outWS->dataE(3)[i] = m_sumE[it->first];
      i++;
    }
    tAxis->setLabel(0, "Red-Green");
    tAxis->setLabel(1, "Red");
    tAxis->setLabel(2, "Green");
    tAxis->setLabel(3, "Red+Green");
  }
  outWS->replaceAxis(1, tAxis);
  outWS->getAxis(0)->title() = m_logName;
  outWS->setYUnitLabel("Asymmetry");
}
Beispiel #29
0
/** Load an individual "<SASentry>" element into a new workspace. It extends the
*LoadCanSAS1D
* in the direction of loading the SAStransmission_spectrum as well. (which was
*introduced in version 1.1)
*
* @param[in] workspaceData points to a "<SASentry>" element
* @param[out] runName the name this workspace should take
* @return dataWS this workspace will be filled with data
* @throw NotFoundError if any expected elements couldn't be read
* @throw NotImplementedError if the entry doesn't contain exactly one run
*/
MatrixWorkspace_sptr
LoadCanSAS1D2::loadEntry(Poco::XML::Node *const workspaceData,
                         std::string &runName) {
  MatrixWorkspace_sptr main_out =
      LoadCanSAS1D::loadEntry(workspaceData, runName);
  bool loadTrans = getProperty("LoadTransmission");
  if (!loadTrans)
    return main_out; // all done. It is not to load the transmission, nor check
                     // if it exists.

  Element *workspaceElem = dynamic_cast<Element *>(workspaceData);
  //  check(workspaceElem, "<SASentry>"); // already done at
  //  LoadCanSAS1D::loadEntry
  Poco::AutoPtr<NodeList> sasTransList =
      workspaceElem->getElementsByTagName("SAStransmission_spectrum");
  if (!sasTransList->length()) {
    g_log.warning() << "There is no transmission data for this file "
                    << getPropertyValue("Filename") << std::endl;
    return main_out;
  }

  for (unsigned short trans_index = 0; trans_index < sasTransList->length();
       trans_index++) {
    // foreach SAStransmission_spectrum
    Node *idataElem = sasTransList->item(trans_index);
    Element *sasTrasElem = dynamic_cast<Element *>(idataElem);
    if (!sasTrasElem)
      continue;
    std::vector<API::MatrixWorkspace_sptr> &group =
        (sasTrasElem->getAttribute("name") == "sample") ? trans_gp
                                                        : trans_can_gp;

    // getting number of Tdata elements in the xml file
    Poco::AutoPtr<NodeList> tdataElemList =
        sasTrasElem->getElementsByTagName("Tdata");
    size_t nBins = tdataElemList->length();

    MatrixWorkspace_sptr dataWS =
        WorkspaceFactory::Instance().create("Workspace2D", 1, nBins, nBins);

    createLogs(workspaceElem, dataWS);

    std::string title = main_out->getTitle();
    title += ":trans";
    title += sasTrasElem->getAttribute("name");
    dataWS->setTitle(title);
    dataWS->isDistribution(true);
    dataWS->setYUnit("");

    // load workspace data
    MantidVec &X = dataWS->dataX(0);
    MantidVec &Y = dataWS->dataY(0);
    MantidVec &E = dataWS->dataE(0);
    int vecindex = 0;
    // iterate through each Tdata element  and get the values of "Lambda",
    //"T" and "Tdev" text nodes and fill X,Y,E vectors
    for (unsigned long index = 0; index < nBins; ++index) {
      Node *idataElem = tdataElemList->item(index);
      Element *elem = dynamic_cast<Element *>(idataElem);
      if (elem) {
        // setting X vector
        std::string nodeVal;
        Element *qElem = elem->getChildElement("Lambda");
        check(qElem, "Lambda");
        nodeVal = qElem->innerText();
        std::stringstream x(nodeVal);
        double d;
        x >> d;
        X[vecindex] = d;

        // setting Y vector
        Element *iElem = elem->getChildElement("T");
        check(qElem, "T");
        nodeVal = iElem->innerText();
        std::stringstream y(nodeVal);
        y >> d;
        Y[vecindex] = d;

        // setting the error vector
        Element *idevElem = elem->getChildElement("Tdev");
        check(qElem, "Tdev");
        nodeVal = idevElem->innerText();
        std::stringstream e(nodeVal);
        e >> d;
        E[vecindex] = d;
        ++vecindex;
      }
    }

    runLoadInstrument(main_out->getInstrument()->getName(), dataWS);
    dataWS->getAxis(0)->setUnit("Wavelength");

    // add to group
    group.push_back(dataWS);
  }
  return main_out;
}
Beispiel #30
0
/**
 * Read histogram data
 * @param histogramEntries map of the file entries that have histogram
 * @param outputGroup pointer to the workspace group
 * @param nxFile Reads data from inside first first top entry
 */
void LoadMcStas::readHistogramData(
    const std::map<std::string, std::string> &histogramEntries,
    WorkspaceGroup_sptr &outputGroup, ::NeXus::File &nxFile) {

  std::string nameAttrValueYLABEL;

  for (const auto &histogramEntry : histogramEntries) {
    const std::string &dataName = histogramEntry.first;
    const std::string &dataType = histogramEntry.second;

    // open second level entry
    nxFile.openGroup(dataName, dataType);

    // grap title to use to e.g. create workspace name
    std::string nameAttrValueTITLE;
    nxFile.getAttr("filename", nameAttrValueTITLE);

    if (nxFile.hasAttr("ylabel")) {
      nxFile.getAttr("ylabel", nameAttrValueYLABEL);
    }

    // Find the axis names
    auto nxdataEntries = nxFile.getEntries();
    std::string axis1Name, axis2Name;
    for (auto &nxdataEntry : nxdataEntries) {
      if (nxdataEntry.second == "NXparameters")
        continue;
      if (nxdataEntry.first == "ncount")
        continue;
      nxFile.openData(nxdataEntry.first);

      if (nxFile.hasAttr("axis")) {
        int axisNo(0);
        nxFile.getAttr("axis", axisNo);
        if (axisNo == 1)
          axis1Name = nxdataEntry.first;
        else if (axisNo == 2)
          axis2Name = nxdataEntry.first;
        else
          throw std::invalid_argument("Unknown axis number");
      }
      nxFile.closeData();
    }

    std::vector<double> axis1Values, axis2Values;
    nxFile.readData<double>(axis1Name, axis1Values);
    if (axis2Name.length() == 0) {
      axis2Name = nameAttrValueYLABEL;
      axis2Values.push_back(0.0);
    } else {
      nxFile.readData<double>(axis2Name, axis2Values);
    }

    const size_t axis1Length = axis1Values.size();
    const size_t axis2Length = axis2Values.size();
    g_log.debug() << "Axis lengths=" << axis1Length << " " << axis2Length
                  << '\n';

    // Require "data" field
    std::vector<double> data;
    nxFile.readData<double>("data", data);

    // Optional errors field
    std::vector<double> errors;
    try {
      nxFile.readData<double>("errors", errors);
    } catch (::NeXus::Exception &) {
      g_log.information() << "Field " << dataName
                          << " contains no error information.\n";
    }

    // close second level entry
    nxFile.closeGroup();

    MatrixWorkspace_sptr ws = WorkspaceFactory::Instance().create(
        "Workspace2D", axis2Length, axis1Length, axis1Length);
    Axis *axis1 = ws->getAxis(0);
    axis1->title() = axis1Name;
    // Set caption
    auto lblUnit = boost::make_shared<Units::Label>();
    lblUnit->setLabel(axis1Name, "");
    axis1->unit() = lblUnit;

    Axis *axis2 = new NumericAxis(axis2Length);
    axis2->title() = axis2Name;
    // Set caption
    lblUnit = boost::make_shared<Units::Label>();
    lblUnit->setLabel(axis2Name, "");
    axis2->unit() = lblUnit;

    ws->setYUnit(axis2Name);
    ws->replaceAxis(1, axis2);

    for (size_t wsIndex = 0; wsIndex < axis2Length; ++wsIndex) {
      auto &dataY = ws->dataY(wsIndex);
      auto &dataE = ws->dataE(wsIndex);
      auto &dataX = ws->dataX(wsIndex);

      for (size_t j = 0; j < axis1Length; ++j) {
        // Data is stored in column-major order so we are translating to
        // row major for Mantid
        const size_t fileDataIndex = j * axis2Length + wsIndex;

        dataY[j] = data[fileDataIndex];
        dataX[j] = axis1Values[j];
        if (!errors.empty())
          dataE[j] = errors[fileDataIndex];
      }
      axis2->setValue(wsIndex, axis2Values[wsIndex]);
    }

    // set the workspace title
    ws->setTitle(nameAttrValueTITLE);

    // use the workspace title to create the workspace name
    std::replace(nameAttrValueTITLE.begin(), nameAttrValueTITLE.end(), ' ',
                 '_');

    // ensure that specified name is given to workspace (eventWS) when added to
    // outputGroup
    std::string nameOfGroupWS = getProperty("OutputWorkspace");
    std::string nameUserSee = nameAttrValueTITLE + "_" + nameOfGroupWS;
    std::string extraProperty =
        "Outputworkspace_dummy_" + std::to_string(m_countNumWorkspaceAdded);
    declareProperty(Kernel::make_unique<WorkspaceProperty<Workspace>>(
        extraProperty, nameUserSee, Direction::Output));
    setProperty(extraProperty, boost::static_pointer_cast<Workspace>(ws));
    m_countNumWorkspaceAdded++; // need to increment to ensure extraProperty are
                                // unique

    // Make Mantid store the workspace in the group
    outputGroup->addWorkspace(ws);
  }
  nxFile.closeGroup();

} // finish