Example #1
0
/**
* Main work portion of algorithm. Calculates mean of standard deviation,
* ignoring
* the detectors marked as "bad", then determines if any of the detectors are
* "bad".
* @param progress :: progress indicator
* @param valid :: eventual output workspace, holding 0 for bad and 1 for good
* @param values :: stddeviations of each spectra (I think)
*/
void IdentifyNoisyDetectors::getStdDev(API::Progress &progress,
                                       MatrixWorkspace_sptr valid,
                                       MatrixWorkspace_sptr values) {
  const int nhist = static_cast<int>(valid->getNumberHistograms());
  int count = 0;
  double mean = 0.0;
  double mean2 = 0.0;

  for (int i = 0; i < nhist; i++) {
    if (valid->readY(i)[0] > 0) {
      mean += values->readY(i)[0];
      mean2 += std::pow(values->readY(i)[0], 2);
      count++;
    }

    progress.report();
  }

  if (0 == count) {
    // all values are zero, no need to loop
    return;
  }

  mean = mean / count;
  double stddev = sqrt((mean2 / count) - std::pow(mean, 2));

  double upper = mean + 3 * stddev;
  double lower = mean - 3 * stddev;
  double min = mean * 0.0001;

  for (int i = 0; i < nhist; i++) {
    double value = values->readY(i)[0];
    if (value > upper) {
      valid->dataY(i)[0] = 0.0;
    } else if (value < lower) {
      valid->dataY(i)[0] = 0.0;
    } else if (value < min) {
      valid->dataY(i)[0] = 0.0;
    }

    progress.report("Calculating StdDev...");
  }
}
Example #2
0
void SumRowColumn::exec()
{
  // First task is to integrate the input workspace
  MatrixWorkspace_const_sptr integratedWS = integrateWorkspace();

  const size_t numSpec = integratedWS->getNumberHistograms();
  // Check number of spectra is 128*128 or 192*192. Print warning if not.
  if (numSpec != 16384 && numSpec != 36864)
  {
    g_log.warning() << "The input workspace has " << numSpec << " spectra."
      << "This is not 128*128 or 192*192 - did you make a mistake?\n";
  }

  // This is the dimension if all rows/columns are included
  const int dim = static_cast<int>( std::sqrt(static_cast<double>(numSpec)) );

  // Check the column range properties
  int start = getProperty("HOverVMin");
  int end = getProperty("HOverVMax");
  if ( isEmpty(start) ) start = 0;
  if ( isEmpty(end) || end > dim-1 ) end = dim-1;
  if ( start > end )
  {
    g_log.error("H/V_Min must be less than H/V_Max");
    throw std::out_of_range("H/V_Min must be less than H/V_Max");
  }

  MatrixWorkspace_sptr outputWS = WorkspaceFactory::Instance().create(integratedWS,1,dim,dim);
  // Remove the unit
  outputWS->getAxis(0)->unit().reset();

  // Get references to the vectors for the results
  MantidVec& X = outputWS->dataX(0);
  MantidVec& Y = outputWS->dataY(0);

  // Get the orientation
  const std::string orientation = getProperty("Orientation");
  const bool horizontal = ( orientation=="D_H" ? 1 : 0 );

  Progress progress(this,0,1,dim);
  for (int i = 0; i < dim; ++i)
  {
    // Copy X values
    X[i] = i;

    // Now loop over calculating Y's
    for (int j = start; j <= end; ++j)
    {
      const int index = ( horizontal ? ( i + j*dim) : ( i*dim + j) );
      Y[i] += integratedWS->readY(index)[0];
    }
  }

  setProperty("OutputWorkspace",outputWS);
}
Example #3
0
/** Creates the output workspace, setting the X vector to the bins boundaries in Qx.
 *  @return A pointer to the newly-created workspace
 */
API::MatrixWorkspace_sptr Qxy::setUpOutputWorkspace(API::MatrixWorkspace_const_sptr inputWorkspace)
{
  const double max = getProperty("MaxQxy");
  const double delta = getProperty("DeltaQ");
  
  int bins = static_cast<int>(max/delta);
  if ( bins*delta != max ) ++bins; // Stop at first boundary past MaxQxy if max is not a multiple of delta
  const double startVal = -1.0*delta*bins;
  bins *= 2; // go from -max to +max
  bins += 1; // Add 1 - this is a histogram
  
  // Create an output workspace with the same meta-data as the input
  MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create(inputWorkspace,bins-1,bins,bins-1);
  // ... but clear the masking from the parameter map as we don't want to carry that over since this is essentially
  // a 2D rebin
  ParameterMap & pmap = outputWorkspace->instrumentParameters();
  pmap.clearParametersByName("masked");

  // Create a numeric axis to replace the vertical one
  Axis* verticalAxis = new NumericAxis(bins);
  outputWorkspace->replaceAxis(1,verticalAxis);

  // Build up the X values
  Kernel::cow_ptr<MantidVec> axis;
  MantidVec& horizontalAxisRef = axis.access();
  horizontalAxisRef.resize(bins);
  for (int i = 0; i < bins; ++i)
  {
    const double currentVal = startVal + i*delta;
    // Set the X value
    horizontalAxisRef[i] = currentVal;
    // Set the Y value on the axis
    verticalAxis->setValue(i,currentVal);
  }
  
  // Fill the X vectors in the output workspace
  for (int i=0; i < bins-1; ++i)
  {
    outputWorkspace->setX(i,axis);
    for (int j=0; j < bins-j; ++j)
    {
      outputWorkspace->dataY(i)[j] = std::numeric_limits<double>::quiet_NaN();
      outputWorkspace->dataE(i)[j] = std::numeric_limits<double>::quiet_NaN();
    }
  }

  // Set the axis units
  outputWorkspace->getAxis(1)->unit() = outputWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create("MomentumTransfer");
  // Set the 'Y' unit (gets confusing here...this is probably a Z axis in this case)
  outputWorkspace->setYUnitLabel("Cross Section (1/cm)");

  setProperty("OutputWorkspace",outputWorkspace);
  return outputWorkspace;
}
/// Get the counting time from a workspace
/// @param inputWS :: workspace to read the counting time from
double
HFIRDarkCurrentSubtraction::getCountingTime(MatrixWorkspace_sptr inputWS) {
    // First, look whether we have the information in the log
    if (inputWS->run().hasProperty("timer")) {
        return inputWS->run().getPropertyValueAsType<double>("timer");
    } else {
        // If we don't have the information in the log, use the default timer
        // spectrum
        MantidVec &timer = inputWS->dataY(DEFAULT_TIMER_ID);
        return timer[0];
    }
}
Example #5
0
/**  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) {

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

  } else {
    size_t i = 0;
    for (auto &value : m_logValue) {
      outWS->dataX(0)[i] = value.second;
      outWS->dataY(0)[i] = m_diffY[value.first];
      outWS->dataE(0)[i] = m_diffE[value.first];
      outWS->dataX(1)[i] = value.second;
      outWS->dataY(1)[i] = m_redY[value.first];
      outWS->dataE(1)[i] = m_redE[value.first];
      outWS->dataX(2)[i] = value.second;
      outWS->dataY(2)[i] = m_greenY[value.first];
      outWS->dataE(2)[i] = m_greenE[value.first];
      outWS->dataX(3)[i] = value.second;
      outWS->dataY(3)[i] = m_sumY[value.first];
      outWS->dataE(3)[i] = m_sumE[value.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");
}
Example #6
0
/**  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 &value : m_logValue) {
      size_t run = value.first;
      outWS->dataX(0)[i] = static_cast<double>(run); // run number
      outWS->dataY(0)[i] = value.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 &value : m_logValue) {
      size_t run = value.first;
      outWS->dataX(0)[i] = static_cast<double>(run); // run number
      outWS->dataY(0)[i] = value.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);
}
/**
 * Share the given input counts into the output array bins proportionally
 * according to how much the bins overlap the given lambda range.
 * outputX.size() must equal outputY.size() + 1
 *
 * @param inputCounts [in] :: the input counts to share out
 * @param inputErr [in] :: the input errors to share out
 * @param bLambda [in] :: the bin width in lambda
 * @param lambdaMin [in] :: the start of the range to share counts to
 * @param lambdaMax [in] :: the end of the range to share counts to
 * @param outSpecIdx [in] :: the spectrum index to be updated in the output
 * workspace
 * @param IvsLam [in,out] :: the output workspace
 * @param outputE [in,out] :: the projected E values
 */
void ReflectometryReductionOne2::sumInQShareCounts(
    const double inputCounts, const double inputErr, const double bLambda,
    const double lambdaMin, const double lambdaMax, const size_t outSpecIdx,
    MatrixWorkspace_sptr IvsLam, std::vector<double> &outputE) {
  // Check that we have histogram data
  const auto &outputX = IvsLam->dataX(outSpecIdx);
  auto &outputY = IvsLam->dataY(outSpecIdx);
  if (outputX.size() != outputY.size() + 1) {
    throw std::runtime_error(
        "Expected output array to be histogram data (got X len=" +
        std::to_string(outputX.size()) +
        ", Y len=" + std::to_string(outputY.size()) + ")");
  }

  const double totalWidth = lambdaMax - lambdaMin;

  // Get the first bin edge in the output X array that is within range.
  // There will probably be some overlap, so start from the bin edge before
  // this (unless we're already at the first bin edge).
  auto startIter = std::lower_bound(outputX.begin(), outputX.end(), lambdaMin);
  if (startIter != outputX.begin()) {
    --startIter;
  }

  // Loop through all overlapping output bins. Convert the iterator to an
  // index because we need to index both the X and Y arrays.
  const int xSize = static_cast<int>(outputX.size());
  for (auto outIdx = startIter - outputX.begin(); outIdx < xSize - 1;
       ++outIdx) {
    const double binStart = outputX[outIdx];
    const double binEnd = outputX[outIdx + 1];
    if (binStart > lambdaMax) {
      // No longer in the overlap region so we're finished
      break;
    }
    // Add a share of the input counts to this bin based on the proportion of
    // overlap.
    if (totalWidth > Tolerance) {
      // Share counts out proportionally based on the overlap of this range
      const double overlapWidth =
          std::min({bLambda, lambdaMax - binStart, binEnd - lambdaMin});
      const double fraction = overlapWidth / totalWidth;
      outputY[outIdx] += inputCounts * fraction;
      outputE[outIdx] += inputErr * fraction;
    } else {
      // Projection to a single value. Put all counts in the overlapping output
      // bin.
      outputY[outIdx] += inputCounts;
      outputE[outIdx] += inputCounts;
    }
  }
}
/// Get the counting time from a workspace
/// @param inputWS :: workspace to read the counting time from
double HFIRDarkCurrentSubtraction::getCountingTime(MatrixWorkspace_sptr inputWS)
{
  // First, look whether we have the information in the log
  if (inputWS->run().hasProperty("timer"))
  {
    Mantid::Kernel::Property* prop = inputWS->run().getProperty("timer");
    Mantid::Kernel::PropertyWithValue<double>* dp = dynamic_cast<Mantid::Kernel::PropertyWithValue<double>* >(prop);
    return *dp;
  } else {
    // If we don't have the information in the log, use the default timer spectrum
    MantidVec& timer = inputWS->dataY(DEFAULT_TIMER_ID);
    return timer[0];
  }
}
Example #9
0
/**
 * Rebin the input quadrilateral to the output grid
 * @param inputQ The input polygon
 * @param inputWS The input workspace containing the input intensity values
 * @param i The index in the vertical axis direction that inputQ references
 * @param j The index in the horizontal axis direction that inputQ references
 * @param outputWS A pointer to the output workspace that accumulates the data
 * @param verticalAxis A vector containing the output vertical axis bin boundaries
 */
void Rebin2D::rebinToOutput(const Geometry::Quadrilateral & inputQ, MatrixWorkspace_const_sptr inputWS,
                            const size_t i, const size_t j, MatrixWorkspace_sptr outputWS,
                            const std::vector<double> & verticalAxis)
{
    const MantidVec & X = outputWS->readX(0);
    size_t qstart(0), qend(verticalAxis.size()-1), en_start(0), en_end(X.size() - 1);
    if( !getIntersectionRegion(outputWS, verticalAxis, inputQ, qstart, qend, en_start, en_end)) return;

    for( size_t qi = qstart; qi < qend; ++qi )
    {
        const double vlo = verticalAxis[qi];
        const double vhi = verticalAxis[qi+1];
        for( size_t ei = en_start; ei < en_end; ++ei )
        {
            const V2D ll(X[ei], vlo);
            const V2D lr(X[ei+1], vlo);
            const V2D ur(X[ei+1], vhi);
            const V2D ul(X[ei], vhi);
            const Quadrilateral outputQ(ll, lr, ur, ul);

            double yValue = inputWS->readY(i)[j];
            if (boost::math::isnan(yValue))
            {
                continue;
            }
            try
            {
                ConvexPolygon overlap = intersectionByLaszlo(outputQ, inputQ);
                const double weight = overlap.area()/inputQ.area();
                yValue *= weight;
                double eValue = inputWS->readE(i)[j] * weight;
                const double overlapWidth = overlap.largestX() - overlap.smallestX();
                if(inputWS->isDistribution())
                {
                    yValue *= overlapWidth;
                    eValue *= overlapWidth;
                }
                eValue = eValue*eValue;
                PARALLEL_CRITICAL(overlap)
                {
                    outputWS->dataY(qi)[ei] += yValue;
                    outputWS->dataE(qi)[ei] += eValue;
                }
            }
            catch(Geometry::NoIntersectionException &)
            {}
        }
    }
}
Example #10
0
/**
 * Handles completion of the preview algorithm.
 *
 * @param error If the algorithm failed
 */
void IndirectSymmetrise::previewAlgDone(bool error) {
  if (error)
    return;

  QString workspaceName = m_uiForm.dsInput->getCurrentDataName();
  int spectrumNumber =
      static_cast<int>(m_dblManager->value(m_properties["PreviewSpec"]));

  MatrixWorkspace_sptr sampleWS =
      AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(
          workspaceName.toStdString());
  ITableWorkspace_sptr propsTable =
      AnalysisDataService::Instance().retrieveWS<ITableWorkspace>(
          "__SymmetriseProps_temp");
  MatrixWorkspace_sptr symmWS =
      AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(
          "__Symmetrise_temp");

  // Get the index of XCut on each side of zero
  int negativeIndex = propsTable->getColumn("NegativeXMinIndex")->cell<int>(0);
  int positiveIndex = propsTable->getColumn("PositiveXMinIndex")->cell<int>(0);

  // Get the Y values for each XCut and the difference between them
  double negativeY = sampleWS->dataY(0)[negativeIndex];
  double positiveY = sampleWS->dataY(0)[positiveIndex];
  double deltaY = fabs(negativeY - positiveY);

  // Show values in property tree
  m_dblManager->setValue(m_properties["NegativeYValue"], negativeY);
  m_dblManager->setValue(m_properties["PositiveYValue"], positiveY);
  m_dblManager->setValue(m_properties["DeltaY"], deltaY);

  // Set indicator positions
  m_uiForm.ppRawPlot->getRangeSelector("NegativeEMinYPos")
      ->setMinimum(negativeY);
  m_uiForm.ppRawPlot->getRangeSelector("PositiveEMinYPos")
      ->setMinimum(positiveY);

  // Plot preview plot
  size_t spectrumIndex = symmWS->getIndexFromSpectrumNumber(spectrumNumber);
  m_uiForm.ppPreviewPlot->clear();
  m_uiForm.ppPreviewPlot->addSpectrum("Symmetrised", "__Symmetrise_temp",
                                      spectrumIndex);

  // Don't want this to trigger when the algorithm is run for all spectra
  disconnect(m_batchAlgoRunner, SIGNAL(batchComplete(bool)), this,
             SLOT(previewAlgDone(bool)));
}
void ExtractFFTSpectrum::exec()
{
  MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace");
  MatrixWorkspace_sptr inputImagWS = getProperty("InputImagWorkspace");
  const int fftPart = getProperty("FFTPart");
  const int numHists = static_cast<int>(inputWS->getNumberHistograms());
  MatrixWorkspace_sptr outputWS = WorkspaceFactory::Instance().create(inputWS);

  Progress prog(this, 0.0, 1.0, numHists);

  PARALLEL_FOR1(outputWS)
  for ( int i = 0; i < numHists; i++ )
  {
    PARALLEL_START_INTERUPT_REGION

    IAlgorithm_sptr childFFT = createChildAlgorithm("FFT");
    childFFT->setProperty<MatrixWorkspace_sptr>("InputWorkspace", inputWS);
    childFFT->setProperty<int>("Real", i);
    if( inputImagWS )
    {
      childFFT->setProperty<MatrixWorkspace_sptr>("InputImagWorkspace", inputImagWS);
      childFFT->setProperty<int>("Imaginary", i);
    }
    childFFT->execute();
    MatrixWorkspace_const_sptr fftTemp = childFFT->getProperty("OutputWorkspace");

    outputWS->dataE(i) = fftTemp->readE(fftPart);
    outputWS->dataY(i) = fftTemp->readY(fftPart);
    outputWS->dataX(i) = fftTemp->readX(fftPart);

    prog.report();

    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION

  boost::shared_ptr<Kernel::Units::Label> lblUnit = boost::dynamic_pointer_cast<Kernel::Units::Label>(UnitFactory::Instance().create("Label"));
  lblUnit->setLabel("Time", "ns");
  outputWS->getAxis(0)->unit() = lblUnit;

  setProperty("OutputWorkspace", outputWS);
}
Example #12
0
/** Set up neutron event's TOF correction.
  * It can be (1) parsed from TOF-correction table workspace to vectors,
  * (2) created according to detector's position in instrument;
  * (3) or no correction,i.e., correction value is equal to 1.
  * Offset should be as F*TOF + B
  */
void FilterEvents::setupDetectorTOFCalibration() {
  // Set output correction workspace and set to output
  const size_t numhist = m_eventWS->getNumberHistograms();
  MatrixWorkspace_sptr corrws = boost::dynamic_pointer_cast<MatrixWorkspace>(
      WorkspaceFactory::Instance().create("Workspace2D", numhist, 2, 2));
  setProperty("OutputTOFCorrectionWorkspace", corrws);

  // Set up the size of correction and output correction workspace
  m_detTofOffsets.resize(numhist, 0.0); // unit of TOF
  m_detTofFactors.resize(numhist, 1.0); // multiplication factor

  // Set up detector values
  std::unique_ptr<TimeAtSampleStrategy> strategy;

  if (m_tofCorrType == CustomizedCorrect) {
    setupCustomizedTOFCorrection();
  } else if (m_tofCorrType == ElasticCorrect) {
    // Generate TOF correction from instrument's set up
    strategy.reset(setupElasticTOFCorrection());
  } else if (m_tofCorrType == DirectCorrect) {
    // Generate TOF correction for direct inelastic instrument
    strategy.reset(setupDirectTOFCorrection());
  } else if (m_tofCorrType == IndirectCorrect) {
    // Generate TOF correction for indirect elastic instrument
    strategy.reset(setupIndirectTOFCorrection());
  }
  if (strategy) {
    for (size_t i = 0; i < numhist; ++i) {
      if (!m_vecSkip[i]) {

        Correction correction = strategy->calculate(i);
        m_detTofOffsets[i] = correction.offset;
        m_detTofFactors[i] = correction.factor;

        corrws->dataY(i)[0] = correction.factor;
        corrws->dataY(i)[1] = correction.offset;
      }
    }
  }

  return;
}
/** Create output workspace
 * @brief GetSpiceDataRawCountsFromMD::createOutputWorkspace
 * @param vecX
 * @param vecY
 * @param xlabel :: only 'Degrees' can be applied to x-axis
 * @param ylabel
 * @return
 */
MatrixWorkspace_sptr GetSpiceDataRawCountsFromMD::createOutputWorkspace(
    const std::vector<double> &vecX, const std::vector<double> &vecY,
    const std::string &xlabel, const std::string &ylabel) {
  // Create MatrixWorkspace
  size_t sizex = vecX.size();
  size_t sizey = vecY.size();
  if (sizex != sizey || sizex == 0)
    throw std::runtime_error("Unable to create output matrix workspace.");

  MatrixWorkspace_sptr outws = boost::dynamic_pointer_cast<MatrixWorkspace>(
      WorkspaceFactory::Instance().create("Workspace2D", 1, sizex, sizey));
  if (!outws)
    throw std::runtime_error("Failed to create output matrix workspace.");

  // Set data
  MantidVec &dataX = outws->dataX(0);
  MantidVec &dataY = outws->dataY(0);
  MantidVec &dataE = outws->dataE(0);
  for (size_t i = 0; i < sizex; ++i) {
    dataX[i] = vecX[i];
    dataY[i] = vecY[i];
    if (dataY[i] > 1.)
      dataE[i] = sqrt(dataY[i]);
    else
      dataE[i] = 1.;
  }

  // Set label
  outws->setYUnitLabel(ylabel);
  if (xlabel.size() != 0) {
    try {
      outws->getAxis(0)->setUnit(xlabel);
    } catch (...) {
      g_log.information() << "Label " << xlabel << " for X-axis is not a unit "
                                                   "registered."
                          << "\n";
    }
  }

  return outws;
}
void ConvertTableToMatrixWorkspace::exec()
{
  ITableWorkspace_sptr inputWorkspace = getProperty("InputWorkspace");
  std::string columnX = getProperty("ColumnX");
  std::string columnY = getProperty("ColumnY");
  std::string columnE = getProperty("ColumnE");

  size_t nrows = inputWorkspace->rowCount();
  std::vector<double> X(nrows);
  std::vector<double> Y(nrows);
  std::vector<double> E(nrows);

  inputWorkspace->getColumn(columnX)->numeric_fill(X);
  inputWorkspace->getColumn(columnY)->numeric_fill(Y);

  if (!columnE.empty())
  {
    inputWorkspace->getColumn(columnE)->numeric_fill(E);
  }
  else
  {
    E.assign(X.size(),1.0);
  }

  MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create("Workspace2D",1,X.size(),X.size());
  outputWorkspace->dataX(0).assign(X.begin(),X.end());
  outputWorkspace->dataY(0).assign(Y.begin(),Y.end());
  outputWorkspace->dataE(0).assign(E.begin(),E.end());

  outputWorkspace->generateSpectraMap();
  boost::shared_ptr<Kernel::Units::Label> labelX = boost::dynamic_pointer_cast<Kernel::Units::Label>(
    Kernel::UnitFactory::Instance().create("Label")
    );
  labelX->setLabel(columnX);
  outputWorkspace->getAxis(0)->unit() = labelX;

  outputWorkspace->setYUnitLabel(columnY);

  setProperty("OutputWorkspace", outputWorkspace);

}
Example #15
0
/** Uses 'Linear' as a subalgorithm to fit the log of the exponential curve expected for the transmission.
 *  @param WS :: The single-spectrum workspace to fit
 *  @return A workspace containing the fit
 */
API::MatrixWorkspace_sptr CalculateTransmissionBeamSpreader::fitToData(API::MatrixWorkspace_sptr WS)
{
  g_log.information("Fitting the experimental transmission curve");
  Algorithm_sptr childAlg = createSubAlgorithm("Linear",0.6,1.0);
  childAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", WS);
  const double lambdaMin = getProperty("MinWavelength");
  const double lambdaMax = getProperty("MaxWavelength");
  childAlg->setProperty<double>("StartX",lambdaMin);
  childAlg->setProperty<double>("EndX",lambdaMax);
  childAlg->executeAsSubAlg();

  std::string fitStatus = childAlg->getProperty("FitStatus");
  if ( fitStatus != "success" )
  {
    g_log.error("Unable to successfully fit the data: " + fitStatus);
    throw std::runtime_error("Unable to successfully fit the data");
  }
 
  // Only get to here if successful
  MatrixWorkspace_sptr result = childAlg->getProperty("OutputWorkspace");

  if (logFit)
  {
    // Need to transform back to 'unlogged'
    double b = childAlg->getProperty("FitIntercept");
    double m = childAlg->getProperty("FitSlope");
    b = std::pow(10,b);
    m = std::pow(10,m);

    const MantidVec & X = result->readX(0);
    MantidVec & Y = result->dataY(0);
    MantidVec & E = result->dataE(0);
    for (size_t i = 0; i < Y.size(); ++i)
    {
      Y[i] = b*(std::pow(m,0.5*(X[i]+X[i+1])));
      E[i] = std::abs(E[i]*Y[i]);
    }
  }

  return result;
}
Example #16
0
void FlatBackground::exec()
{
  // Retrieve the input workspace
  MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace");
  // Copy over all the data
  const int numHists = static_cast<int>(inputWS->getNumberHistograms());
  const int blocksize = static_cast<int>(inputWS->blocksize());

  // Get the required X range
  double startX,endX;
  this->checkRange(startX,endX);

  std::vector<int> specInds = getProperty("WorkspaceIndexList");
  // check if the user passed an empty list, if so all of spec will be processed
  this->getSpecInds(specInds, numHists);
 
  // Are we removing the background?
  const bool removeBackground =
    std::string(getProperty("outputMode")) == "Subtract Background";

  // Initialise the progress reporting object
  m_progress = new Progress(this,0.0,0.2,numHists); 

  MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace");
  // If input and output workspaces are not the same, create a new workspace for the output
  if (outputWS != inputWS )
  {
    outputWS = WorkspaceFactory::Instance().create(inputWS);
    PARALLEL_FOR2(inputWS,outputWS)
    for (int i = 0; i < numHists; ++i)
    {
      PARALLEL_START_INTERUPT_REGION
      outputWS->dataX(i) = inputWS->readX(i);
      outputWS->dataY(i) = inputWS->readY(i);
      outputWS->dataE(i) = inputWS->readE(i);
      m_progress->report();
      PARALLEL_END_INTERUPT_REGION
    }
    PARALLEL_CHECK_INTERUPT_REGION
  }
Example #17
0
 /**
  * Add -1.*minValue on each spectra.
  *
  * @param minWS A workspace of minimum values for each spectra. This is calculated in
  * the @see exec portion of the algorithm.
  * @param wksp The workspace to modify.
  * @param prog The progress.
  */
 void ResetNegatives::pushMinimum(MatrixWorkspace_const_sptr minWS, MatrixWorkspace_sptr wksp, Progress &prog)
 {
   int64_t nHist = minWS->getNumberHistograms();
   PARALLEL_FOR2(wksp, minWS)
   for (int64_t i = 0; i < nHist; i++)
   {
     PARALLEL_START_INTERUPT_REGION
     double minValue = minWS->readY(i)[0];
     if (minValue <= 0)
     {
       minValue *= -1.;
       MantidVec & y = wksp->dataY(i);
       for (MantidVec::iterator it = y.begin(); it != y.end(); ++it)
       {
         *it = fixZero(*it + minValue);
       }
     }
     prog.report();
     PARALLEL_END_INTERUPT_REGION
   }
   PARALLEL_CHECK_INTERUPT_REGION
 }
Example #18
0
/** Reads from the third line of the input file to the end assuming it contains
*  2D data
*  @param firstLine :: the second line in the file
*  @return a workspace containing the loaded data
*  @throw NotFoundError if there is compulsulary data is missing from the file
*  @throw invalid_argument if there is an inconsistency in the header information
*/
const MatrixWorkspace_sptr LoadRKH::read2D(const std::string & firstLine)
{
    g_log.information() << "file appears to contain 2D information, reading in 2D data mode\n";

    MatrixWorkspace_sptr outWrksp;
    MantidVec axis0Data;
    Progress prog(  read2DHeader(firstLine, outWrksp, axis0Data) );
    const size_t nAxis1Values = outWrksp->getNumberHistograms();

    for ( size_t i = 0; i < nAxis1Values; ++i )
    {
        //set the X-values to the common bin values we read above
        MantidVecPtr toPass;
        toPass.access() = axis0Data;
        outWrksp->setX(i, toPass);

        //now read in the Y values
        MantidVec & YOut = outWrksp->dataY(i);
        for (MantidVec::iterator it = YOut.begin(), end=YOut.end(); it != end; ++it)
        {
            m_fileIn >> *it;
        }
        prog.report("Loading Y data");
    }// loop on to the next spectrum

    // the error values form one big block after the Y-values
    for ( size_t i = 0; i < nAxis1Values; ++i )
    {
        MantidVec & EOut = outWrksp->dataE(i);
        for (MantidVec::iterator it = EOut.begin(), end=EOut.end(); it != end; ++it)
        {
            m_fileIn >> *it;
        }
        prog.report("Loading error estimates");
    }// loop on to the next spectrum

    return outWrksp;
}
Example #19
0
/**
 * Sets a new preview spectrum for the mini plot.
 *
 * @param value workspace index
 */
void ResNorm::previewSpecChanged(int value) {
  m_previewSpec = value;

  // Update vanadium plot
  if (m_uiForm.dsVanadium->isValid())
    m_uiForm.ppPlot->addSpectrum(
        "Vanadium", m_uiForm.dsVanadium->getCurrentDataName(), m_previewSpec);

  // Update fit plot
  std::string fitWsGroupName(m_pythonExportWsName + "_Fit_Workspaces");
  std::string fitParamsName(m_pythonExportWsName + "_Fit");
  if (AnalysisDataService::Instance().doesExist(fitWsGroupName)) {
    WorkspaceGroup_sptr fitWorkspaces =
        AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>(
            fitWsGroupName);
    ITableWorkspace_sptr fitParams =
        AnalysisDataService::Instance().retrieveWS<ITableWorkspace>(
            fitParamsName);
    if (fitWorkspaces && fitParams) {
      Column_const_sptr scaleFactors = fitParams->getColumn("Scaling");
      std::string fitWsName(fitWorkspaces->getItem(m_previewSpec)->name());
      MatrixWorkspace_const_sptr fitWs =
          AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(
              fitWsName);

      MatrixWorkspace_sptr fit = WorkspaceFactory::Instance().create(fitWs, 1);
      fit->setX(0, fitWs->readX(1));
      fit->getSpectrum(0)->setData(fitWs->readY(1), fitWs->readE(1));

      for (size_t i = 0; i < fit->blocksize(); i++)
        fit->dataY(0)[i] /= scaleFactors->cell<double>(m_previewSpec);

      m_uiForm.ppPlot->addSpectrum("Fit", fit, 0, Qt::red);
    }
  }
}
Example #20
0
/**
 * Groups the workspace according to grouping provided.
 *
 * @param ws :: Workspace to group
 * @param  g :: The grouping information
 * @return Sptr to created grouped workspace
 */
MatrixWorkspace_sptr groupWorkspace(MatrixWorkspace_const_sptr ws, const Grouping& g)
{
  // As I couldn't specify multiple groups for GroupDetectors, I am going down quite a complicated
  // route - for every group distinct grouped workspace is created using GroupDetectors. These
  // workspaces are then merged into the output workspace.

  // Create output workspace
  MatrixWorkspace_sptr outWs =
    WorkspaceFactory::Instance().create(ws, g.groups.size(), ws->readX(0).size(), ws->blocksize());

  for(size_t gi = 0; gi < g.groups.size(); gi++)
  {
    Mantid::API::IAlgorithm_sptr alg = AlgorithmManager::Instance().create("GroupDetectors");
    alg->setChild(true); // So Output workspace is not added to the ADS
    alg->initialize();
    alg->setProperty("InputWorkspace", boost::const_pointer_cast<MatrixWorkspace>(ws));
    alg->setPropertyValue("SpectraList", g.groups[gi]);
    alg->setPropertyValue("OutputWorkspace", "grouped"); // Is not actually used, just to make validators happy
    alg->execute();

    MatrixWorkspace_sptr grouped = alg->getProperty("OutputWorkspace");

    // Copy the spectrum
    *(outWs->getSpectrum(gi)) = *(grouped->getSpectrum(0));

    // Update spectrum number
    outWs->getSpectrum(gi)->setSpectrumNo(static_cast<specid_t>(gi));

    // Copy to the output workspace
    outWs->dataY(gi) = grouped->readY(0);
    outWs->dataX(gi) = grouped->readX(0);
    outWs->dataE(gi) = grouped->readE(0);
  }

  return outWs;
}
Example #21
0
    /** Execute the ghost correction on all events in the input workspace **/
    void GhostCorrection::exec()
    {

      // Get the input workspace
      this->inputW = getProperty("InputWorkspace");

      //Load the grouping
      GroupingWorkspace_sptr groupWS = getProperty("GroupingWorkspace");
      groupWS->makeDetectorIDToGroupMap(detId_to_group, nGroups);
      if (this->nGroups <= 0)
        throw std::runtime_error("The # of groups found in the Grouping file is 0.");

      // Now the offsets
      OffsetsWorkspace_sptr offsetsWS = getProperty("OffsetsWorkspace");

      //Make the X axis to bin to.
      MantidVecPtr XValues_new;
      const int64_t numbins = VectorHelper::createAxisFromRebinParams(getProperty("BinParams"), XValues_new.access());

      //Prepare the binfinder class
      BinFinder binner( getProperty("BinParams") );
      if (binner.lastBinIndex() != static_cast<int>(XValues_new.access().size()-1))
      {
        std::stringstream msg;
        msg << "GhostCorrection: The binner found " << binner.lastBinIndex()+1 << " bins, but the X axis has "
            << XValues_new.access().size() << ". Try different binning parameters.";
        throw std::runtime_error(msg.str());
      }

      //Create an output Workspace2D with group # of output spectra
      MatrixWorkspace_sptr outputW = WorkspaceFactory::Instance().create("Workspace2D", this->nGroups-1, numbins, numbins-1);
      WorkspaceFactory::Instance().initializeFromParent(inputW, outputW,  true);

      //Set the X bins in the output WS.
      Workspace2D_sptr outputWS2D = boost::dynamic_pointer_cast<Workspace2D>(outputW);
      for (std::size_t i=0; i < outputWS2D->getNumberHistograms(); i++)
        outputWS2D->setX(i, XValues_new);

      //Prepare the maps you need
      input_detectorIDToWorkspaceIndexMap = inputW->getDetectorIDToWorkspaceIndexMap(true);

      //Load the ghostmapping file
      this->loadGhostMap( getProperty("GhostCorrectionFilename") );

      //Initialize progress reporting.
      int64_t numsteps = 0; //count how many steps
      for (int64_t gr=1; gr < this->nGroups; ++gr)
        numsteps += this->groupedGhostMaps[gr]->size();
      Progress prog(this, 0.0, 1.0, numsteps);

      //Set up the tof-to-d_spacing map for all pixel ids.
      this->tof_to_d = Mantid::Algorithms::AlignDetectors::calcTofToD_ConversionMap(inputW, offsetsWS);

      // Set the final unit that our output workspace will have
      outputW->getAxis(0)->unit() = UnitFactory::Instance().create("dSpacing");

      //Go through the groups, starting at #1!
      PARALLEL_FOR2(inputW, outputW)
      for (int64_t gr=1; gr < this->nGroups; ++gr)
      {
        PARALLEL_START_INTERUPT_REGION

        //TODO: Convert between group # and workspace index. Sigh.
        //Groups normally start at 1 and so the workspace index will be one below that.
        int64_t outputWorkspaceIndex = gr-1;

        //Start by making sure the Y and E values are 0.
        MantidVec& Y = outputW->dataY(outputWorkspaceIndex);
        MantidVec& E = outputW->dataE(outputWorkspaceIndex);
        Y.assign(Y.size(), 0.0);
        E.assign(E.size(), 0.0);

        //Perform the GhostCorrection

        //Ok, this map has as keys the source workspace indices
        GhostSourcesMap * thisGroupsGhostMap = this->groupedGhostMaps[gr];
        GhostSourcesMap::iterator it;
        for (it = thisGroupsGhostMap->begin(); it != thisGroupsGhostMap->end(); ++it)
        {
          //This workspace index is causing 16 ghosts in this group.
          int64_t inputWorkspaceIndex = it->first;
          int64_t inputDetectorID = it->second;

          //This is the events in the pixel CAUSING the ghost.
          const EventList & sourceEventList = inputW->getEventList(inputWorkspaceIndex);

          //Now get the actual vector of tofevents
          const std::vector<TofEvent>& events = sourceEventList.getEvents();
          size_t numEvents = events.size();

          //Go through all events.
          for (size_t i=0; i < numEvents; i++)
          {
            const TofEvent& event = events[i];

            for (int64_t g=0; g < NUM_GHOSTS; g++)
            {
              //Find the ghost correction
              int64_t fileIndex = inputDetectorID * NUM_GHOSTS + g;
              GhostDestinationValue ghostVal = (*rawGhostMap)[fileIndex];

              //Convert to d-spacing using the factor of the GHOST pixel id
              double d_spacing = event.tof() * (*tof_to_d)[ghostVal.pixelId];

              //Find the bin for this d-spacing
              int64_t binIndex = binner.bin(d_spacing);

              if (binIndex >= 0)
              {
                //Slap it in the Y array for this group; use the weight.
                Y[binIndex] += ghostVal.weight;
              }

            } //for each ghost

          } //for each event


          //Report progress
          prog.report();
        }


        PARALLEL_END_INTERUPT_REGION
      }

      PARALLEL_CHECK_INTERUPT_REGION

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


    }
Example #22
0
/**
  @ throw invalid_argument if the workspaces are not mututially compatible
*/
void Q1D2::exec()
{
  m_dataWS = getProperty("DetBankWorkspace");
  MatrixWorkspace_const_sptr waveAdj = getProperty("WavelengthAdj");
  MatrixWorkspace_const_sptr pixelAdj = getProperty("PixelAdj");
  MatrixWorkspace_const_sptr wavePixelAdj = getProperty("WavePixelAdj");
  const bool doGravity = getProperty("AccountForGravity");
  m_doSolidAngle = getProperty("SolidAngleWeighting");

  //throws if we don't have common binning or another incompatibility
  Qhelper helper;
  helper.examineInput(m_dataWS, waveAdj, pixelAdj);
  // FIXME: how to examine the wavePixelAdj? 
  g_log.debug() << "All input workspaces were found to be valid\n";
  // normalization as a function of wavelength (i.e. centers of x-value bins)
  double const * const binNorms = waveAdj ? &(waveAdj->readY(0)[0]) : NULL;
  // error on the wavelength normalization
  double const * const binNormEs = waveAdj ? &(waveAdj->readE(0)[0]) : NULL;

  //define the (large number of) data objects that are going to be used in all iterations of the loop below

  // this will become the output workspace from this algorithm
  MatrixWorkspace_sptr outputWS = setUpOutputWorkspace(getProperty("OutputBinning"));

  const MantidVec & QOut = outputWS->readX(0);
  MantidVec & YOut = outputWS->dataY(0);
  MantidVec & EOutTo2 = outputWS->dataE(0);
  // normalisation that is applied to counts in each Q bin
  MantidVec normSum(YOut.size(), 0.0);
  // the error on the normalisation
  MantidVec normError2(YOut.size(), 0.0);

  const int numSpec = static_cast<int>(m_dataWS->getNumberHistograms());
  Progress progress(this, 0.05, 1.0, numSpec+1);

  PARALLEL_FOR3(m_dataWS, outputWS, pixelAdj)
  for (int i = 0; i < numSpec; ++i)
  {
    PARALLEL_START_INTERUPT_REGION
    // Get the pixel relating to this spectrum
    IDetector_const_sptr det;
    try {
      det = m_dataWS->getDetector(i);
    } catch (Exception::NotFoundError&) {
      g_log.warning() << "Workspace index " << i << " (SpectrumIndex = " << m_dataWS->getSpectrum(i)->getSpectrumNo() << ") 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 detector is masked shouldn't be included skip onto the next spectrum
    if ( !det || det->isMonitor() || det->isMasked() )
    {
      continue;
    }

    //get the bins that are included inside the RadiusCut/WaveCutcut off, those to calculate for
    //const size_t wavStart = waveLengthCutOff(i);
    const size_t wavStart = helper.waveLengthCutOff(m_dataWS, getProperty("RadiusCut"), getProperty("WaveCut"), i);
    if (wavStart >=  m_dataWS->readY(i).size())
    {
      // all the spectra in this detector are out of range
      continue;
    }
    
    const size_t numWavbins = m_dataWS->readY(i).size()-wavStart;
    // make just one call to new to reduce CPU overhead on each thread, access to these 
    // three "arrays" is via iterators
    MantidVec _noDirectUseStorage_(3*numWavbins);
    //normalization term
    MantidVec::iterator norms = _noDirectUseStorage_.begin();
    // the error on these weights, it contributes to the error calculation on the output workspace
    MantidVec::iterator normETo2s = norms + numWavbins;
    // the Q values calculated from input wavelength workspace
    MantidVec::iterator QIn = normETo2s + numWavbins;

    // the weighting for this input spectrum that is added to the normalization
    calculateNormalization(wavStart, i, pixelAdj, wavePixelAdj, binNorms, binNormEs, norms, normETo2s);

    // now read the data from the input workspace, calculate Q for each bin
    convertWavetoQ(i, doGravity, wavStart, QIn);

    // Pointers to the counts data and it's error
    MantidVec::const_iterator YIn = m_dataWS->readY(i).begin()+wavStart;
    MantidVec::const_iterator EIn = m_dataWS->readE(i).begin()+wavStart;

    //when finding the output Q bin remember that the input Q bins (from the convert to wavelength) start high and reduce
    MantidVec::const_iterator loc = QOut.end();
    // sum the Q contributions from each individual spectrum into the output array
    const MantidVec::const_iterator end = m_dataWS->readY(i).end();
    for( ; YIn != end; ++YIn, ++EIn, ++QIn, ++norms, ++normETo2s)
    {
      //find the output bin that each input y-value will fall into, remembering there is one more bin boundary than bins
      getQBinPlus1(QOut, *QIn, loc);
      // ignore counts that are out of the output range
      if ( (loc != QOut.begin()) && (loc != QOut.end()) )
      {
        // the actual Q-bin to add something to
        const size_t bin = loc - QOut.begin() - 1;
        PARALLEL_CRITICAL(q1d_counts_sum)
        {
          YOut[bin] += *YIn;
          normSum[bin] += *norms;
          //these are the errors squared which will be summed and square rooted at the end
          EOutTo2[bin] += (*EIn)*(*EIn);
          normError2[bin] += *normETo2s;
        }
      }
    }
    
    PARALLEL_CRITICAL(q1d_spectra_map)
    {
      progress.report("Computing I(Q)");

      // Add up the detector IDs in the output spectrum at workspace index 0
      const ISpectrum * inSpec = m_dataWS->getSpectrum(i);
      ISpectrum * outSpec = outputWS->getSpectrum(0);
      outSpec->addDetectorIDs( inSpec->getDetectorIDs() );
    }

    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION

  bool doOutputParts = getProperty("OutputParts");
  if (doOutputParts)
  {
      MatrixWorkspace_sptr ws_sumOfCounts = WorkspaceFactory::Instance().create(outputWS);
      ws_sumOfCounts->dataX(0) = outputWS->dataX(0);
      ws_sumOfCounts->dataY(0) = outputWS->dataY(0);
      for (size_t i = 0; i < outputWS->dataE(0).size(); i++)
      {
        ws_sumOfCounts->dataE(0)[i] = sqrt(outputWS->dataE(0)[i]);
      }      

      MatrixWorkspace_sptr ws_sumOfNormFactors = WorkspaceFactory::Instance().create(outputWS);
      ws_sumOfNormFactors->dataX(0) = outputWS->dataX(0);
      for (size_t i = 0; i < ws_sumOfNormFactors->dataY(0).size(); i++)
      {
        ws_sumOfNormFactors->dataY(0)[i] = normSum[i];
        ws_sumOfNormFactors->dataE(0)[i] = sqrt(normError2[i]);
      }

      helper.outputParts(this, ws_sumOfCounts, ws_sumOfNormFactors);
  }


  progress.report("Normalizing I(Q)");
  //finally divide the number of counts in each output Q bin by its weighting
  normalize(normSum, normError2, YOut, EOutTo2);

  outputWS->updateSpectraUsingMap();

  setProperty("OutputWorkspace",outputWS);
}
Example #23
0
/** Execute the algorithm.
 */
void LoadNXSPE::exec() {
  std::string filename = getProperty("Filename");
  // quicly check if it's really nxspe
  try {
    ::NeXus::File file(filename);
    std::string mainEntry = (*(file.getEntries().begin())).first;
    file.openGroup(mainEntry, "NXentry");
    file.openData("definition");
    if (identiferConfidence(file.getStrData()) < 1) {
      throw std::invalid_argument("Not NXSPE");
    }
    file.close();
  } catch (...) {
    throw std::invalid_argument("Not NeXus or not NXSPE");
  }

  // Load the data
  ::NeXus::File file(filename);

  std::string mainEntry = (*(file.getEntries().begin())).first;
  file.openGroup(mainEntry, "NXentry");

  file.openGroup("NXSPE_info", "NXcollection");
  std::map<std::string, std::string> entries = file.getEntries();
  std::vector<double> temporary;
  double fixed_energy, psi = 0.;

  if (!entries.count("fixed_energy")) {
    throw std::invalid_argument("fixed_energy field was not found");
  }
  file.openData("fixed_energy");
  file.getData(temporary);
  fixed_energy = temporary.at(0);
  file.closeData();

  if (entries.count("psi")) {
    file.openData("psi");
    file.getData(temporary);
    psi = temporary.at(0);
    file.closeData();
  }

  int kikfscaling = 0;
  if (entries.count("ki_over_kf_scaling")) {
    file.openData("ki_over_kf_scaling");
    std::vector<int> temporaryint;
    file.getData(temporaryint);
    kikfscaling = temporaryint.at(0);
    file.closeData();
  }

  file.closeGroup(); // NXSPE_Info

  file.openGroup("data", "NXdata");
  entries = file.getEntries();

  if (!entries.count("data")) {
    throw std::invalid_argument("data field was not found");
  }
  file.openData("data");
  ::NeXus::Info info = file.getInfo();
  std::size_t numSpectra = static_cast<std::size_t>(info.dims.at(0));
  std::size_t numBins = static_cast<std::size_t>(info.dims.at(1));
  std::vector<double> data;
  file.getData(data);
  file.closeData();

  if (!entries.count("error")) {
    throw std::invalid_argument("error field was not found");
  }
  file.openData("error");
  std::vector<double> error;
  file.getData(error);
  file.closeData();

  if (!entries.count("energy")) {
    throw std::invalid_argument("energy field was not found");
  }
  file.openData("energy");
  std::vector<double> energies;
  file.getData(energies);
  file.closeData();

  if (!entries.count("azimuthal")) {
    throw std::invalid_argument("azimuthal field was not found");
  }
  file.openData("azimuthal");
  std::vector<double> azimuthal;
  file.getData(azimuthal);
  file.closeData();

  if (!entries.count("azimuthal_width")) {
    throw std::invalid_argument("azimuthal_width field was not found");
  }
  file.openData("azimuthal_width");
  std::vector<double> azimuthal_width;
  file.getData(azimuthal_width);
  file.closeData();

  if (!entries.count("polar")) {
    throw std::invalid_argument("polar field was not found");
  }
  file.openData("polar");
  std::vector<double> polar;
  file.getData(polar);
  file.closeData();

  if (!entries.count("polar_width")) {
    throw std::invalid_argument("polar_width field was not found");
  }
  file.openData("polar_width");
  std::vector<double> polar_width;
  file.getData(polar_width);
  file.closeData();

  // distance might not have been saved in all NXSPE files
  std::vector<double> distance;
  if (entries.count("distance")) {
    file.openData("distance");
    file.getData(distance);
    file.closeData();
  }

  file.closeGroup(); // data group
  file.closeGroup(); // Main entry
  file.close();

  // check if dimensions of the vectors are correct
  if ((error.size() != data.size()) || (azimuthal.size() != numSpectra) ||
      (azimuthal_width.size() != numSpectra) || (polar.size() != numSpectra) ||
      (polar_width.size() != numSpectra) ||
      ((energies.size() != numBins) && (energies.size() != numBins + 1))) {
    throw std::invalid_argument(
        "incompatible sizes of fields in the NXSPE file");
  }

  MatrixWorkspace_sptr outputWS = boost::dynamic_pointer_cast<MatrixWorkspace>(
      WorkspaceFactory::Instance().create("Workspace2D", numSpectra,
                                          energies.size(), numBins));
  // Need to get hold of the parameter map
  outputWS->getAxis(0)->unit() = UnitFactory::Instance().create("DeltaE");
  outputWS->setYUnit("SpectraNumber");

  // add logs
  outputWS->mutableRun().addLogData(
      new PropertyWithValue<double>("Ei", fixed_energy));
  outputWS->mutableRun().addLogData(new PropertyWithValue<double>("psi", psi));
  outputWS->mutableRun().addLogData(new PropertyWithValue<std::string>(
      "ki_over_kf_scaling", kikfscaling == 1 ? "true" : "false"));

  // Set Goniometer
  Geometry::Goniometer gm;
  gm.pushAxis("psi", 0, 1, 0, psi);
  outputWS->mutableRun().setGoniometer(gm, true);

  // generate instrument
  Geometry::Instrument_sptr instrument(new Geometry::Instrument("NXSPE"));
  outputWS->setInstrument(instrument);

  Geometry::ObjComponent *source = new Geometry::ObjComponent("source");
  source->setPos(0.0, 0.0, -10.0);
  instrument->add(source);
  instrument->markAsSource(source);
  Geometry::ObjComponent *sample = new Geometry::ObjComponent("sample");
  instrument->add(sample);
  instrument->markAsSamplePos(sample);

  Geometry::Object_const_sptr cuboid(
      createCuboid(0.1, 0.1, 0.1)); // FIXME: memory hog on rendering. Also,
                                    // make each detector separate size
  for (std::size_t i = 0; i < numSpectra; ++i) {
    double r = 1.0;
    if (!distance.empty()) {
      r = distance.at(i);
    }

    Kernel::V3D pos;
    pos.spherical(r, polar.at(i), azimuthal.at(i));

    Geometry::Detector *det =
        new Geometry::Detector("pixel", static_cast<int>(i + 1), sample);
    det->setPos(pos);
    det->setShape(cuboid);
    instrument->add(det);
    instrument->markAsDetector(det);
  }

  Geometry::ParameterMap &pmap = outputWS->instrumentParameters();
  std::vector<double>::iterator itdata = data.begin(), iterror = error.begin(),
                                itdataend, iterrorend;
  API::Progress prog = API::Progress(this, 0.0, 0.9, numSpectra);
  for (std::size_t i = 0; i < numSpectra; ++i) {
    itdataend = itdata + numBins;
    iterrorend = iterror + numBins;
    outputWS->dataX(i) = energies;
    if ((!boost::math::isfinite(*itdata)) || (*itdata <= -1e10)) // masked bin
    {
      outputWS->dataY(i) = std::vector<double>(numBins, 0);
      outputWS->dataE(i) = std::vector<double>(numBins, 0);
      pmap.addBool(outputWS->getDetector(i)->getComponentID(), "masked", true);
    } else {
      outputWS->dataY(i) = std::vector<double>(itdata, itdataend);
      outputWS->dataE(i) = std::vector<double>(iterror, iterrorend);
    }
    itdata = (itdataend);
    iterror = (iterrorend);
    prog.report();
  }

  setProperty("OutputWorkspace", outputWS);
}
Example #24
0
/** Executes the algorithm
 *
 *  @throw runtime_error Thrown if algorithm cannot execute
 */
void MaxMin::exec()
{
  // Try and retrieve the optional properties
  m_MinRange = getProperty("RangeLower");
  m_MaxRange = getProperty("RangeUpper");
  m_MinSpec = getProperty("StartWorkspaceIndex");
  m_MaxSpec = getProperty("EndWorkspaceIndex");
  showMin = getProperty("ShowMin");

  // Get the input workspace
  MatrixWorkspace_const_sptr localworkspace = getProperty("InputWorkspace");

  const int numberOfSpectra = static_cast<int>(localworkspace->getNumberHistograms());

  // Check 'StartSpectrum' is in range 0-numberOfSpectra
  if ( m_MinSpec > numberOfSpectra )
  {
    g_log.warning("StartSpectrum out of range! Set to 0.");
    m_MinSpec = 0;
  }
  if ( isEmpty(m_MaxSpec) ) m_MaxSpec = numberOfSpectra-1;
  if ( m_MaxSpec > numberOfSpectra-1 || m_MaxSpec < m_MinSpec )
  {
    g_log.warning("EndSpectrum out of range! Set to max detector number");
    m_MaxSpec = numberOfSpectra;
  }
  if ( m_MinRange > m_MaxRange )
  {
    g_log.warning("Range_upper is less than Range_lower. Will integrate up to frame maximum.");
    m_MaxRange = 0.0;
  }

  // Create the 1D workspace for the output
  MatrixWorkspace_sptr outputWorkspace = API::WorkspaceFactory::Instance().create(localworkspace,m_MaxSpec-m_MinSpec+1,2,1);


  Progress progress(this,0,1,(m_MaxSpec-m_MinSpec+1));
  PARALLEL_FOR2(localworkspace,outputWorkspace)
  // Loop over spectra
  for (int i = m_MinSpec; i <= m_MaxSpec; ++i)
  {
    PARALLEL_START_INTERUPT_REGION
    int newindex=i-m_MinSpec;
    // Copy over spectrum and detector number info
    outputWorkspace->getSpectrum(newindex)->copyInfoFrom(*localworkspace->getSpectrum(i));

    // Retrieve the spectrum into a vector
    const MantidVec& X = localworkspace->readX(i);
    const MantidVec& Y = localworkspace->readY(i);

    // Find the range [min,max]
    MantidVec::const_iterator lowit, highit;
    if (m_MinRange == EMPTY_DBL()) lowit=X.begin();
    else lowit=std::lower_bound(X.begin(),X.end(),m_MinRange);

    if (m_MaxRange == EMPTY_DBL()) highit=X.end();
    else highit=std::find_if(lowit,X.end(),std::bind2nd(std::greater<double>(),m_MaxRange));

    // If range specified doesn't overlap with this spectrum then bail out
    if ( lowit == X.end() || highit == X.begin() ) continue;

    --highit; // Upper limit is the bin before, i.e. the last value smaller than MaxRange

    MantidVec::difference_type distmin=std::distance(X.begin(),lowit);
    MantidVec::difference_type distmax=std::distance(X.begin(),highit);

    MantidVec::const_iterator maxY;
    // Find the max/min element
    if (showMin==true)
    {
      maxY=std::min_element(Y.begin()+distmin,Y.begin()+distmax);
    }
    else
    {
      maxY=std::max_element(Y.begin()+distmin,Y.begin()+distmax);
    }
    MantidVec::difference_type d=std::distance(Y.begin(),maxY);
    // X boundaries for the max/min element
    outputWorkspace->dataX(newindex)[0]=*(X.begin()+d);
    outputWorkspace->dataX(newindex)[1]=*(X.begin()+d+1); //This is safe since X is of dimension Y+1
    outputWorkspace->dataY(newindex)[0]=*maxY;
    progress.report();
    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION

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

  return;
}
Example #25
0
void TOFSANSResolution::exec()
{
  Workspace2D_sptr iqWS = getProperty("InputWorkspace");
  MatrixWorkspace_sptr reducedWS = getProperty("ReducedWorkspace");
  EventWorkspace_sptr reducedEventWS = boost::dynamic_pointer_cast<EventWorkspace>(reducedWS);
  const double min_wl = getProperty("MinWavelength");
  const double max_wl = getProperty("MaxWavelength");
  double pixel_size_x = getProperty("PixelSizeX");
  double pixel_size_y = getProperty("PixelSizeY");
  double R1 = getProperty("SourceApertureRadius");
  double R2 = getProperty("SampleApertureRadius");
  // Convert to meters
  pixel_size_x /= 1000.0;
  pixel_size_y /= 1000.0;
  R1 /= 1000.0;
  R2 /= 1000.0;
  wl_resolution = getProperty("DeltaT");

  // Although we want the 'ReducedWorkspace' to be an event workspace for this algorithm to do
  // anything, we don't want the algorithm to 'fail' if it isn't
  if (!reducedEventWS)
  {
    g_log.warning() << "An Event Workspace is needed to compute dQ. Calculation skipped." << std::endl;
    return;
  }

  // Calculate the output binning
  const std::vector<double> binParams = getProperty("OutputBinning");

  // Count histogram for normalization
  const int xLength = static_cast<int>(iqWS->readX(0).size());
  std::vector<double> XNorm(xLength-1, 0.0);

  // Create workspaces with each component of the resolution for debugging purposes
  MatrixWorkspace_sptr thetaWS = WorkspaceFactory::Instance().create(iqWS);
  declareProperty(new WorkspaceProperty<>("ThetaError","",Direction::Output));
  setPropertyValue("ThetaError","__"+iqWS->getName()+"_theta_error");
  setProperty("ThetaError",thetaWS);
  thetaWS->setX(0,iqWS->readX(0));
  MantidVec& ThetaY = thetaWS->dataY(0);

  MatrixWorkspace_sptr tofWS = WorkspaceFactory::Instance().create(iqWS);
  declareProperty(new WorkspaceProperty<>("TOFError","",Direction::Output));
  setPropertyValue("TOFError","__"+iqWS->getName()+"_tof_error");
  setProperty("TOFError",tofWS);
  tofWS->setX(0,iqWS->readX(0));
  MantidVec& TOFY = tofWS->dataY(0);

  // Initialize Dq
  MantidVec& DxOut = iqWS->dataDx(0);
  for ( int i = 0; i<xLength-1; i++ ) DxOut[i] = 0.0;

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

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

  PARALLEL_FOR2(reducedEventWS, iqWS)
  for (int i = 0; i < numberOfSpectra; i++)
  {
    PARALLEL_START_INTERUPT_REGION
    IDetector_const_sptr det;
    try {
      det = reducedEventWS->getDetector(i);
    } catch (Exception::NotFoundError&) {
      g_log.warning() << "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 scattered_flight_path = det->getPos() - samplePos;

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

    EventList& el = reducedEventWS->getEventList(i);
    el.switchTo(WEIGHTED);

    std::vector<WeightedEvent>::iterator itev;
    std::vector<WeightedEvent>::iterator itev_end = el.getWeightedEvents().end();

    for (itev = el.getWeightedEvents().begin(); itev != itev_end; ++itev)
    {
      if ( itev->m_weight != itev->m_weight ) continue;
      if (std::abs(itev->m_weight) == std::numeric_limits<double>::infinity()) continue;
      if ( !isEmpty(min_wl) && itev->m_tof < min_wl ) continue;
      if ( !isEmpty(max_wl) && itev->m_tof > max_wl ) continue;

      const double q = factor/itev->m_tof;
      int iq = 0;

      // Bin assignment depends on whether we have log or linear bins
      if(binParams[1]>0.0)
      {
        iq = (int)floor( (q-binParams[0])/ binParams[1] );
      } else {
        iq = (int)floor(log(q/binParams[0])/log(1.0-binParams[1]));
      }

      const double L2 = scattered_flight_path.norm();
      const double src_to_pixel = L1+L2;
      const double dTheta2 = ( 3.0*R1*R1/(L1*L1) + 3.0*R2*R2*src_to_pixel*src_to_pixel/(L1*L1*L2*L2)
            + 2.0*(pixel_size_x*pixel_size_x+pixel_size_y*pixel_size_y)/(L2*L2) )/12.0;

      const double dwl_over_wl = 3.9560*getTOFResolution(itev->m_tof)/(1000.0*(L1+L2)*itev->m_tof);
      const double dq_over_q = std::sqrt(dTheta2/(theta*theta)+dwl_over_wl*dwl_over_wl);

      PARALLEL_CRITICAL(iq)    /* Write to shared memory - must protect */
      if (iq>=0 && iq < xLength-1 && !dq_over_q!=dq_over_q && dq_over_q>0)
      {
        DxOut[iq] += q*dq_over_q*itev->m_weight;
        XNorm[iq] += itev->m_weight;
        TOFY[iq] += q*std::fabs(dwl_over_wl)*itev->m_weight;
        ThetaY[iq] += q*std::sqrt(dTheta2)/theta*itev->m_weight;
      }
    }

    progress.report("Computing Q resolution");
    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION
  // Normalize according to the chosen weighting scheme
  for ( int i = 0; i<xLength-1; i++ )
  {
    if (XNorm[i]>0)
    {
      DxOut[i] /= XNorm[i];
      TOFY[i] /= XNorm[i];
      ThetaY[i] /= XNorm[i];
    }
  }
}
Example #26
0
/** Read a data file that contains only one spectrum into a workspace
*  @return the new workspace
*/
const API::MatrixWorkspace_sptr LoadRKH::read1D()
{
    g_log.information() << "file appears to contain 1D information, reading in 1D data mode\n";

    //The 3rd line contains information regarding the number of points in the file and
    // start and end reading points
    int totalPoints(0), readStart(0), readEnd(0), buried(0);
    std::string fileline;

    getline(m_fileIn, fileline);
    std::istringstream is(fileline);
    //Get data information
    for( int counter = 1; counter < 8; ++counter )
    {
        switch( counter )
        {
        case 1:
            is >> totalPoints;
            break;
        case 5:
            is >> readStart;
            break;
        case 6:
            is >> readEnd;
            break;
        default:
            is >> buried;
            break;
        }
    }

    g_log.information() << "Total number of data points declared to be in the data file: "
                        << totalPoints << "\n";

    //What are we reading?
    std::string firstColVal = getProperty("FirstColumnValue");
    bool colIsUnit(true);
    if( m_RKHKeys.find( firstColVal ) != m_RKHKeys.end() )
    {
        colIsUnit = false;
        readStart = 1;
        readEnd = totalPoints;
    }

    if( readStart < 1 || readEnd < 1 || readEnd < readStart ||
            readStart > totalPoints || readEnd > totalPoints )
    {
        g_log.error("Invalid data range specfied.");
        m_fileIn.close();
        throw std::invalid_argument("Invalid data range specfied.");
    }

    g_log.information() << "Reading started on data line: "  << readStart << "\n";
    g_log.information() << "Reading finished on data line: " << readEnd << "\n";

    //The 4th and 5th line do not contain useful information either
    skipLines(m_fileIn, 2);

    int pointsToRead = readEnd - readStart + 1;
    //Now stream sits at the first line of data
    fileline = "";
    std::vector<double> columnOne, ydata, errdata;
    columnOne.reserve(readEnd);
    ydata.reserve(readEnd);
    errdata.reserve(readEnd);

    Progress prog(this,0.0,1.0,readEnd);
    for( int index = 1; index <= readEnd; ++index )
    {
        getline(m_fileIn, fileline);
        if( index < readStart ) continue;
        double x(0.), y(0.), yerr(0.);
        std::istringstream datastr(fileline);
        datastr >> x >> y >> yerr;
        columnOne.push_back(x);
        ydata.push_back(y);
        errdata.push_back(yerr);
        prog.report();
    }
    m_fileIn.close();

    assert( pointsToRead == static_cast<int>(columnOne.size()) );
    assert( pointsToRead == static_cast<int>(ydata.size()) );
    assert( pointsToRead == static_cast<int>(errdata.size()) );

    if( colIsUnit )
    {
        MatrixWorkspace_sptr localworkspace =
            WorkspaceFactory::Instance().create("Workspace2D", 1, pointsToRead, pointsToRead);
        localworkspace->getAxis(0)->unit() = UnitFactory::Instance().create(firstColVal);
        localworkspace->dataX(0) = columnOne;
        localworkspace->dataY(0) = ydata;
        localworkspace->dataE(0) = errdata;

        return localworkspace;
    }
    else
    {
        MatrixWorkspace_sptr localworkspace =
            WorkspaceFactory::Instance().create("Workspace2D", pointsToRead, 1, 1);
        //Set the appropriate values
        for( int index = 0; index < pointsToRead; ++index )
        {
            localworkspace->getAxis(1)->setValue(index, static_cast<int>(columnOne[index]));
            localworkspace->dataY(index)[0] = ydata[index];
            localworkspace->dataE(index)[0] = errdata[index];
        }
        return localworkspace;
    }

}
Example #27
0
void Linear::exec()
{
  // Get the input workspace
  MatrixWorkspace_const_sptr inputWorkspace = getProperty("InputWorkspace");
  // Get the spectrum to fit
  const int histNumber = getProperty("WorkspaceIndex");
  // Check validity
  if ( histNumber >= static_cast<int>(inputWorkspace->getNumberHistograms()) )
  {
    g_log.error() << "WorkspaceIndex set to an invalid value of " << histNumber << std::endl;
    throw Exception::IndexError(histNumber,inputWorkspace->getNumberHistograms(),"Linear WorkspaceIndex property");
  }

  // Get references to the data in the chosen spectrum
  const MantidVec& X = inputWorkspace->dataX(histNumber);
  const MantidVec& Y = inputWorkspace->dataY(histNumber);
  const MantidVec& E = inputWorkspace->dataE(histNumber);
  // Check if this spectrum has errors
  double errorsCount = 0.0;

  // Retrieve the Start/EndX properties, if set
  this->setRange(X,Y);
  
  const bool isHistogram = inputWorkspace->isHistogramData();
  // If the spectrum to be fitted has masked bins, we want to exclude them (even if only partially masked)
  const MatrixWorkspace::MaskList * const maskedBins = 
    ( inputWorkspace->hasMaskedBins(histNumber) ? &(inputWorkspace->maskedBins(histNumber)) : NULL );
  // Put indices of masked bins into a set for easy searching later
  std::set<size_t> maskedIndices;
  if (maskedBins)
  {
    MatrixWorkspace::MaskList::const_iterator it;
    for (it = maskedBins->begin(); it != maskedBins->end(); ++it)
      maskedIndices.insert(it->first);
  }
  
  progress(0);

  // Declare temporary vectors and reserve enough space if they're going to be used
  std::vector<double> XCen, unmaskedY, weights;
  int numPoints = m_maxX - m_minX;
  if (isHistogram) XCen.reserve(numPoints);
  if (maskedBins) unmaskedY.reserve(numPoints);
  weights.reserve(numPoints);

  for (int i = 0; i < numPoints; ++i)
  {
    // If the current bin is masked, skip it
    if ( maskedBins && maskedIndices.count(m_minX+i) ) continue;
    // Need to adjust X to centre of bin, if a histogram
    if (isHistogram) XCen.push_back( 0.5*(X[m_minX+i]+X[m_minX+i+1]) );
    // If there are masked bins present, we need to copy the unmasked Y values
    if (maskedBins) unmaskedY.push_back(Y[m_minX+i]);
    // GSL wants the errors as weights, i.e. 1/sigma^2
    // We need to be careful if E is zero because that would naively lead to an infinite weight on the point.
    // Solution taken here is to zero weight if error is zero, which typically means Y is zero
    //   (so it is effectively excluded from the fit).
    const double& currentE = E[m_minX+i];
    weights.push_back( currentE ? 1.0/(currentE*currentE) : 0.0 );
    // However, if the spectrum given has all errors of zero, then we should use the gsl function that
    //   doesn't take account of the errors.
    if ( currentE ) ++errorsCount;
  }
  progress(0.3);
  
  // If masked bins present, need to recalculate numPoints here
  if (maskedBins) numPoints = static_cast<int>(unmaskedY.size());
  // If no points left for any reason, bail out
  if (numPoints == 0)
  {
    g_log.error("No points in this range to fit");
    throw std::runtime_error("No points in this range to fit");
  }

  // Set up pointer variables to pass to gsl, pointing them to the right place
  const double * const xVals = ( isHistogram ? &XCen[0] : &X[m_minX] );
  const double * const yVals = ( maskedBins ? &unmaskedY[0] : &Y[m_minX] );

  // Call the gsl fitting function
  // The stride value of 1 reflects that fact that we want every element of our input vectors
  const int stride = 1;
  double *c0(new double),*c1(new double),*cov00(new double),*cov01(new double),*cov11(new double),*chisq(new double);
  int status;
  // Unless our spectrum has error values for vast majority of points, 
  //   call the gsl function that doesn't use errors
  if ( errorsCount/numPoints < 0.9 )
  {
    g_log.debug("Calling gsl_fit_linear (doesn't use errors in fit)");
    status = gsl_fit_linear(xVals,stride,yVals,stride,numPoints,c0,c1,cov00,cov01,cov11,chisq);
  }
  // Otherwise, call the one that does account for errors on the data points
  else
  {
    g_log.debug("Calling gsl_fit_wlinear (uses errors in fit)");
    status = gsl_fit_wlinear(xVals,stride,&weights[0],stride,yVals,stride,numPoints,c0,c1,cov00,cov01,cov11,chisq);
  }
  progress(0.8);

  // Check that the fit succeeded
  std::string fitStatus = gsl_strerror(status);
  // For some reason, a fit where c0,c1 & chisq are all infinity doesn't report as a 
  //   failure, so check explicitly.
  if ( !gsl_finite(*chisq) || !gsl_finite(*c0) || !gsl_finite(*c1) )
    fitStatus = "Fit gives infinities";
  if (fitStatus != "success") g_log.error() << "The fit failed: " << fitStatus << "\n";
  else
    g_log.information() << "The fit succeeded, giving y = " << *c0 << " + " << *c1 << "*x, with a Chi^2 of " << *chisq << "\n";
  
  // Set the fit result output properties
  setProperty("FitStatus",fitStatus);
  setProperty("FitIntercept",*c0);
  setProperty("FitSlope",*c1);
  setProperty("Cov00",*cov00);
  setProperty("Cov11",*cov11);
  setProperty("Cov01",*cov01);
  setProperty("Chi2",*chisq);
  
  // Create and fill a workspace2D with the same bins as the fitted spectrum and the value of the fit for the centre of each bin
  const size_t YSize = Y.size();
  MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create(inputWorkspace,1,X.size(),YSize);
  
  // Copy over the X bins
  outputWorkspace->dataX(0).assign(X.begin(),X.end());
  // Now loop over the spectrum and use gsl function to calculate the Y & E values for the function
  for (size_t i = 0; i < YSize; ++i)
  {
    const double x = ( isHistogram ? 0.5*(X[i]+X[i+1]) : X[i] );
    const int err = gsl_fit_linear_est(x,*c0,*c1,*cov00,*cov01,*cov11,&(outputWorkspace->dataY(0)[i]),&(outputWorkspace->dataE(0)[i]));
    if (err) g_log.warning() << "Problem in filling the output workspace: " << gsl_strerror(err) << std::endl;
  }
  setProperty("OutputWorkspace",outputWorkspace);
  progress(1);
  // Clean up
  delete c0;
  delete c1;
  delete cov00;
  delete cov01;
  delete cov11;
  delete chisq;
}
void SANSSolidAngleCorrection::exec() {
  // Reduction property manager
  const std::string reductionManagerName = getProperty("ReductionProperties");
  boost::shared_ptr<PropertyManager> reductionManager;
  if (PropertyManagerDataService::Instance().doesExist(reductionManagerName)) {
    reductionManager =
        PropertyManagerDataService::Instance().retrieve(reductionManagerName);
  } else {
    reductionManager = boost::make_shared<PropertyManager>();
    PropertyManagerDataService::Instance().addOrReplace(reductionManagerName,
                                                        reductionManager);
  }

  // If the solid angle algorithm isn't in the reduction properties, add it
  if (!reductionManager->existsProperty("SolidAngleAlgorithm")) {
    AlgorithmProperty *algProp = new AlgorithmProperty("SolidAngleAlgorithm");
    algProp->setValue(toString());
    reductionManager->declareProperty(algProp);
  }

  MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace");
  DataObjects::EventWorkspace_const_sptr inputEventWS =
      boost::dynamic_pointer_cast<const EventWorkspace>(inputWS);
  if (inputEventWS)
    return execEvent();

  // Now create the output workspace
  MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace");
  if (outputWS != inputWS) {
    outputWS = WorkspaceFactory::Instance().create(inputWS);
    outputWS->isDistribution(true);
    outputWS->setYUnit("");
    outputWS->setYUnitLabel("Steradian");
    setProperty("OutputWorkspace", outputWS);
  }

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

  // Number of X bins
  const int xLength = static_cast<int>(inputWS->readY(0).size());

  PARALLEL_FOR2(outputWS, inputWS)
  for (int i = 0; i < numHists; ++i) {
    PARALLEL_START_INTERUPT_REGION
    outputWS->dataX(i) = inputWS->readX(i);

    IDetector_const_sptr det;
    try {
      det = inputWS->getDetector(i);
    } catch (Exception::NotFoundError &) {
      g_log.warning() << "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, skip onto the next spectrum
    if (!det)
      continue;

    // Skip if we have a monitor or if the detector is masked.
    if (det->isMonitor() || det->isMasked())
      continue;

    const MantidVec &YIn = inputWS->readY(i);
    const MantidVec &EIn = inputWS->readE(i);

    MantidVec &YOut = outputWS->dataY(i);
    MantidVec &EOut = outputWS->dataE(i);

    // Compute solid angle correction factor
    const bool is_tube = getProperty("DetectorTubes");
    const double tanTheta = tan(inputWS->detectorTwoTheta(det));
    const double theta_term = sqrt(tanTheta * tanTheta + 1.0);
    double corr;
    if (is_tube) {
      const double tanAlpha = tan(getYTubeAngle(det, inputWS));
      const double alpha_term = sqrt(tanAlpha * tanAlpha + 1.0);
      corr = alpha_term * theta_term * theta_term;
    } else {
      corr = theta_term * theta_term * theta_term;
    }

    // Correct data for all X bins
    for (int j = 0; j < xLength; j++) {
      YOut[j] = YIn[j] * corr;
      EOut[j] = fabs(EIn[j] * corr);
    }
    progress.report("Solid Angle Correction");
    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION
  setProperty("OutputMessage", "Solid angle correction applied");
}
Example #29
0
/** Filter non-background data points out and create a background workspace
  */
Workspace2D_sptr
ProcessBackground::filterForBackground(BackgroundFunction_sptr bkgdfunction) {
  double posnoisetolerance = getProperty("NoiseTolerance");
  double negnoisetolerance = getProperty("NegativeNoiseTolerance");
  if (isEmpty(negnoisetolerance))
    negnoisetolerance = posnoisetolerance;

  // Calcualte theoretical values
  const std::vector<double> x = m_dataWS->readX(m_wsIndex);
  API::FunctionDomain1DVector domain(x);
  API::FunctionValues values(domain);
  bkgdfunction->function(domain, values);

  g_log.information() << "Function used to select background points : "
                      << bkgdfunction->asString() << "\n";

  // Optional output
  string userbkgdwsname = getPropertyValue("UserBackgroundWorkspace");
  if (userbkgdwsname.size() == 0)
    throw runtime_error("In mode SelectBackgroundPoints, "
                        "UserBackgroundWorkspace must be given!");

  size_t sizex = domain.size();
  size_t sizey = values.size();
  MatrixWorkspace_sptr visualws = boost::dynamic_pointer_cast<MatrixWorkspace>(
      WorkspaceFactory::Instance().create("Workspace2D", 4, sizex, sizey));
  for (size_t i = 0; i < sizex; ++i) {
    for (size_t j = 0; j < 4; ++j) {
      visualws->dataX(j)[i] = domain[i];
    }
  }
  for (size_t i = 0; i < sizey; ++i) {
    visualws->dataY(0)[i] = values[i];
    visualws->dataY(1)[i] = m_dataWS->readY(m_wsIndex)[i] - values[i];
    visualws->dataY(2)[i] = posnoisetolerance;
    visualws->dataY(3)[i] = -negnoisetolerance;
  }
  setProperty("UserBackgroundWorkspace", visualws);

  // Filter for background
  std::vector<double> vecx, vecy, vece;
  for (size_t i = 0; i < domain.size(); ++i) {
    // double y = m_dataWS->readY(m_wsIndex)[i];
    // double theoryy = values[i]; y-theoryy
    double purey = visualws->readY(1)[i];
    if (purey < posnoisetolerance && purey > -negnoisetolerance) {
      // Selected
      double x = domain[i];
      double y = m_dataWS->readY(m_wsIndex)[i];
      double e = m_dataWS->readE(m_wsIndex)[i];
      vecx.push_back(x);
      vecy.push_back(y);
      vece.push_back(e);
    }
  }
  g_log.information() << "Found " << vecx.size() << " background points out of "
                      << m_dataWS->readX(m_wsIndex).size()
                      << " total data points. "
                      << "\n";

  // Build new workspace for OutputWorkspace
  size_t nspec = 3;
  Workspace2D_sptr outws =
      boost::dynamic_pointer_cast<DataObjects::Workspace2D>(
          API::WorkspaceFactory::Instance().create("Workspace2D", nspec,
                                                   vecx.size(), vecy.size()));
  for (size_t i = 0; i < vecx.size(); ++i) {
    for (size_t j = 0; j < nspec; ++j)
      outws->dataX(j)[i] = vecx[i];
    outws->dataY(0)[i] = vecy[i];
    outws->dataE(0)[i] = vece[i];
  }

  return outws;
}
void TOFSANSResolutionByPixel::exec() {
  MatrixWorkspace_sptr inOutWS = getProperty("Workspace");
  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 MatrixWorkspace_sptr sigmaModeratorVSwavelength =
      getProperty("SigmaModerator");

  // create interpolation table from sigmaModeratorVSwavelength
  Kernel::Interpolation lookUpTable;

  const MantidVec xInterpolate = sigmaModeratorVSwavelength->readX(0);
  const MantidVec yInterpolate = sigmaModeratorVSwavelength->readY(0);

  // prefer the input to be a pointworkspace and create interpolation function
  if (sigmaModeratorVSwavelength->isHistogramData()) {
    g_log.notice() << "mid-points of SigmaModerator histogram bins will be "
                      "used for interpolation.";

    for (size_t i = 0; i < xInterpolate.size() - 1; ++i) {
      const double midpoint = xInterpolate[i + 1] - xInterpolate[i];
      lookUpTable.addPoint(midpoint, yInterpolate[i]);
    }
  } else {
    for (size_t i = 0; i < xInterpolate.size(); ++i) {
      lookUpTable.addPoint(xInterpolate[i], yInterpolate[i]);
    }
  }

  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);

  for (int i = 0; i < numberOfSpectra; i++) {
    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;
    }
    // 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 each wavelenght bin of each pixel calculate a q-resolution
    for (size_t j = 0; j < xLength - 1; j++) {
      // use the midpoint of each bin
      const double wl = (xIn[j + 1] + xIn[j]) / 2.0;
      // Calculate q. Alternatively q could be calculated using ConvertUnit
      const double q = factor / wl;

      // wavelenght spread from bin assumed to be
      const double sigmaSpreadFromBin = xIn[j + 1] - xIn[j];

      // wavelenght spread from moderatorm, converted from microseconds to
      // wavelengths
      const double sigmaModerator =
          lookUpTable.value(wl) * 3.9560 / (1000.0 * Lsum);

      // calculate wavelenght resolution from moderator and histogram time bin
      const double sigmaLambda =
          std::sqrt(sigmaSpreadFromBin * sigmaSpreadFromBin / 12.0 +
                    sigmaModerator * sigmaModerator);

      // 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");
  }
}