Example #1
0
/// Retrieve and check the Start/EndX parameters, if set
void Linear::setRange(const MantidVec& X, const MantidVec& Y)
{
  //read in the values that the user selected
  double startX = getProperty("StartX");
  double endX = getProperty("EndX");
  //If the user didn't a start default to the start of the data
  if ( isEmpty(startX) ) startX = X.front();
  //the default for the end is the end of the data
  if ( isEmpty(endX) ) endX = X.back();

  // Check the validity of startX
  if ( startX < X.front() )
  {
    g_log.warning("StartX out of range! Set to start of frame.");
    startX = X.front();
  }
  // Now get the corresponding bin boundary that comes before (or coincides with) this value
  for (m_minX = 0; X[m_minX+1] < startX; ++m_minX) {}

  // Check the validity of endX and get the bin boundary that come after (or coincides with) it
  if ( endX >= X.back() || endX < startX )
  {
    if ( endX != X.back() )
    {
      g_log.warning("EndX out of range! Set to end of frame");
      endX = X.back();
    }
    m_maxX = static_cast<int>(Y.size());
  }
  else
  {
    for (m_maxX = m_minX; X[m_maxX] < endX; ++m_maxX) {}
  }  
}
Example #2
0
/** Calculates the rebin parameters in the case where the range of the second
 * workspace is
 *  entirely within that of the first workspace.
 *  'Inclusion' is used in the sense of a set being included in anothre.
 *  @param X1 ::     The bin boundaries from the first workspace
 *  @param i ::      Indicates the index in X1 immediately before the overlap
 * region starts
 *  @param X2 ::     The bin boundaries from the second workspace
 *  @param params :: A reference to the vector of rebinning parameters
 */
void MergeRuns::inclusionParams(const MantidVec &X1, int64_t &i,
                                const MantidVec &X2,
                                std::vector<double> &params) const {
    // First calculate the number of bins in each workspace that are in the
    // overlap region
    int64_t overlapbins1, overlapbins2;
    for (overlapbins1 = 1; X1[i + overlapbins1] < X2.back(); ++overlapbins1) {
    }
    //++overlapbins1;
    overlapbins2 = X2.size() - 1;

    // In the overlap region, we want to use whichever one has the larger bins (on
    // average)
    if (overlapbins1 + 1 <= overlapbins2) {
        // In the case where the first workspace has larger bins it's easy
        // - just add the rest of X1's bins
        for (; i < static_cast<int64_t>(X1.size()); ++i) {
            params.push_back(X1[i] - X1[i - 1]);
            params.push_back(X1[i]);
        }
    } else {
        // In this case we want all of X2's bins first (without the first and last
        // boundaries)
        for (size_t j = 1; j < X2.size() - 1; ++j) {
            params.push_back(X2[j] - params.back());
            params.push_back(X2[j]);
        }
        // And now those from X1 that lie above the overlap region
        i += overlapbins1;
        for (; i < static_cast<int64_t>(X1.size()); ++i) {
            params.push_back(X1[i] - params.back());
            params.push_back(X1[i]);
        }
    }
}
Example #3
0
/** Calculates the rebin parameters in the case where the bins of the two
 * workspaces intersect.
 *  'Intersect' is used in the sense of two intersecting sets.
 *  @param X1 ::     The bin boundaries from the first workspace
 *  @param i ::      Indicates the index in X1 immediately before the overlap
 * region starts
 *  @param X2 ::     The bin boundaries from the second workspace
 *  @param params :: A reference to the vector of rebinning parameters
 */
void MergeRuns::intersectionParams(const MantidVec &X1, int64_t &i,
                                   const MantidVec &X2,
                                   std::vector<double> &params) const {
    // First calculate the number of bins in each workspace that are in the
    // overlap region
    int64_t overlapbins1, overlapbins2;
    overlapbins1 = X1.size() - i;
    for (overlapbins2 = 0; X2[overlapbins2] < X1.back(); ++overlapbins2) {
    }

    // We want to use whichever one has the larger bins (on average)
    if (overlapbins1 < overlapbins2) {
        // In this case we want the rest of the bins from the first workspace.....
        for (; i < static_cast<int64_t>(X1.size()); ++i) {
            params.push_back(X1[i] - X1[i - 1]);
            params.push_back(X1[i]);
        }
        // Now remove the last bin & boundary
        params.pop_back();
        params.pop_back();
        // ....and then the non-overlap ones from the second workspace
        for (size_t j = overlapbins2; j < X2.size(); ++j) {
            params.push_back(X2[j] - params.back());
            params.push_back(X2[j]);
        }
    } else {
        // In this case we just have to add all the bins from the second workspace
        for (size_t j = 1; j < X2.size(); ++j) {
            params.push_back(X2[j] - params.back());
            params.push_back(X2[j]);
        }
    }
}
Example #4
0
/** Calculates the rebin paramters in the case where the two input workspaces do
 * not overlap at all.
 *  @param X1 ::     The bin boundaries from the first workspace
 *  @param X2 ::     The bin boundaries from the second workspace
 *  @param params :: A reference to the vector of rebinning parameters
 */
void MergeRuns::noOverlapParams(const MantidVec &X1, const MantidVec &X2,
                                std::vector<double> &params) const {
    // Add all the bins from the first workspace
    for (size_t i = 1; i < X1.size(); ++i) {
        params.push_back(X1[i - 1]);
        params.push_back(X1[i] - X1[i - 1]);
    }
    // Put a single bin in the 'gap' (but check first the 'gap' isn't zero)
    if (X1.back() < X2.front()) {
        params.push_back(X1.back());
        params.push_back(X2.front() - X1.back());
    }
    // Now add all the bins from the second workspace
    for (size_t j = 1; j < X2.size(); ++j) {
        params.push_back(X2[j - 1]);
        params.push_back(X2[j] - X2[j - 1]);
    }
    params.push_back(X2.back());
}
Example #5
0
/** Calculates the overall normalization factor.
 *  This multiplies result by (bin width * sum of monitor counts) / total frame
 * width.
 *  @param X The X vector
 *  @param Y The data vector
 *  @param E The error vector
 */
void NormaliseToMonitor::normalisationFactor(const MantidVec &X, MantidVec *Y,
                                             MantidVec *E) {
  const double monitorSum = std::accumulate(Y->begin(), Y->end(), 0.0);
  const double range = X.back() - X.front();
  MantidVec::size_type specLength = Y->size();
  for (MantidVec::size_type j = 0; j < specLength; ++j) {
    const double factor = range / ((X[j + 1] - X[j]) * monitorSum);
    (*Y)[j] *= factor;
    (*E)[j] *= factor;
  }
}
Example #6
0
/**
 * @param tofMin Return value for minimum tof to be masked
 * @param tofMax Return value for maximum tof to be masked
 * @param tofPeak time-of-flight of the single crystal peak
 * @param tof tof-of-flight axis for the spectrum where the peak supposedly
 * exists
 */
void MaskPeaksWorkspace::getTofRange(double &tofMin, double &tofMax,
                                     const double tofPeak,
                                     const MantidVec &tof) {
  tofMin = tof.front();
  tofMax = tof.back() - 1;
  if (!isEmpty(m_tofMin)) {
    tofMin = tofPeak + m_tofMin;
  }
  if (!isEmpty(m_tofMax)) {
    tofMax = tofPeak + m_tofMax;
  }
}
Example #7
0
/**
 * Get the start and end of the x-interval.
 * @param X :: The x-vector of a spectrum.
 * @param isHistogram :: Is the x-vector comming form a histogram? If it's true
 * the bin
 *   centres are used.
 * @return :: A pair of start x and end x.
 */
std::pair<double, double> WienerSmooth::getStartEnd(const MantidVec &X,
                                                    bool isHistogram) const {
  const size_t n = X.size();
  if (n < 3) {
    // 3 is the smallest number for this method to work without breaking
    throw std::runtime_error(
        "Number of bins/data points cannot be smaller than 3.");
  }
  if (isHistogram) {
    return std::make_pair((X[0] + X[1]) / 2, (X[n - 1] + X[n - 2]) / 2);
  }
  // else
  return std::make_pair(X.front(), X.back());
}
Example #8
0
/**
 * Use the binning information to generate a x-axis.
 *
 * @param xValues The new x-axis.
 * @param xmin The x-min to be used.
 * @param xmax The x-max to be used.
 *
 * @return The final delta value (absolute value).
 */
double ResampleX::determineBinning(MantidVec &xValues, const double xmin,
                                   const double xmax) {
  xValues.clear(); // clear out the x-values

  int numBoundaries(0);
  int reqNumBoundaries(m_numBins);
  int expNumBoundaries(m_numBins);
  if (m_isDistribution)
    reqNumBoundaries -= 1; // to get the VectorHelper to do the right thing
  else
    expNumBoundaries += 1; // should be one more bin boundary for histograms

  vector<double> params; // xmin, delta, xmax
  params.push_back(xmin);
  params.push_back(0.); // dummy delta value
  params.push_back(xmax);

  // constant binning is easy
  if (m_useLogBinning) {
    if (xmin == 0)
      throw std::invalid_argument("Cannot calculate log of xmin=0");
    if (xmax == 0)
      throw std::invalid_argument("Cannot calculate log of xmax=0");

    const int MAX_ITER(100); // things went wrong if we get this far

    // starting delta value assuming everything happens exactly
    double delta = (log(xmax) - log(xmin)) / static_cast<double>(m_numBins);
    double shift = .1;
    int sign = 0;
    for (int numIter = 0; numIter < MAX_ITER; ++numIter) {
      params[1] = -1. * delta;
      if (!m_isDistribution)
        params[2] = xmax + delta;
      numBoundaries =
          VectorHelper::createAxisFromRebinParams(params, xValues, true);

      if (numBoundaries == expNumBoundaries) {
        double diff = (xmax - xValues.back());
        if (diff != 0.) {
          g_log.debug()
              << "Didn't get the exact xmax value: [xmax - xValues.back()="
              << diff << "] [relative diff = " << fabs(100. * diff / xmax)
              << "%]\n";
          g_log.debug() << "Resetting final x-value to xmax\n";
          *(xValues.rbegin()) = xmax;
        }
        break;
      } else if (numBoundaries > expNumBoundaries) // too few points
      {
        delta *= (1. + shift);
        if (sign < 0)
          shift *= .9;
        sign = 1;
      } else // too many points
      {
        delta *= (1. - shift);
        if (sign > 0)
          shift *= .9;
        sign = -1;
      }
    }
  } else {
    params[1] = (xmax - xmin) / static_cast<double>(reqNumBoundaries);
    numBoundaries =
        VectorHelper::createAxisFromRebinParams(params, xValues, true);
  }

  if (numBoundaries != expNumBoundaries) {
    g_log.warning()
        << "Did not generate the requested number of bins: generated "
        << numBoundaries << " requested " << expNumBoundaries << "\n";
  }

  // return the delta value so the caller can do debug printing
  return params[1];
}
Example #9
0
/**
* Copy over the metadata from the input matrix workspace to output
*MDEventWorkspace
* @param mdEventWS :: The output MDEventWorkspace where metadata are copied to.
*The source of the metadata is the input matrix workspace
*
*/
void ConvertToMD::copyMetaData(API::IMDEventWorkspace_sptr &mdEventWS) const {

  // found detector which is not a monitor to get proper bin boundaries.
  size_t spectra_index(0);
  bool dector_found(false);
  for (size_t i = 0; i < m_InWS2D->getNumberHistograms(); ++i) {
    try {
      auto det = m_InWS2D->getDetector(i);
      if (!det->isMonitor()) {
        spectra_index = i;
        dector_found = true;
        g_log.debug() << "Using spectra N " << i << " as the source of the bin "
                                                    "boundaries for the "
                                                    "resolution corrections \n";
        break;
      }
    } catch (...) {
    }
  }
  if (!dector_found)
    g_log.warning() << "No detectors in the workspace are associated with "
                       "spectra. Using spectrum 0 trying to retrieve the bin "
                       "boundaries \n";

  // retrieve representative bin boundaries
  MantidVec binBoundaries = m_InWS2D->readX(spectra_index);
  // check if the boundaries transformation is necessary
  if (m_Convertor->getUnitConversionHelper().isUnitConverted()) {

    if (!dynamic_cast<DataObjects::EventWorkspace *>(m_InWS2D.get())) {
      g_log.information() << " ConvertToMD converts input workspace units, but "
                             "the bin boundaries are copied from the first "
                             "workspace spectra. The resolution estimates can "
                             "be incorrect if unit conversion depends on "
                             "spectra number.\n";

      UnitsConversionHelper &unitConv = m_Convertor->getUnitConversionHelper();
      unitConv.updateConversion(spectra_index);
      for (double &binBoundarie : binBoundaries) {
        binBoundarie = unitConv.convertUnits(binBoundarie);
      }
    }
    // sort bin boundaries in case if unit transformation have swapped them.
    if (binBoundaries[0] > binBoundaries.back()) {
      g_log.information() << "Bin boundaries are not arranged monotonously. "
                             "Sorting performed\n";
      std::sort(binBoundaries.begin(), binBoundaries.end());
    }
  }

  // Replacement for SpectraDetectorMap::createIDGroupsMap using the ISpectrum
  // objects instead
  auto mapping = boost::make_shared<det2group_map>();
  for (size_t i = 0; i < m_InWS2D->getNumberHistograms(); ++i) {
    const auto &dets = m_InWS2D->getSpectrum(i).getDetectorIDs();
    if (!dets.empty()) {
      mapping->emplace(*dets.begin(),
                       std::vector<detid_t>(dets.begin(), dets.end()));
    }
  }

  // The last experiment info should always be the one that refers
  // to latest converting workspace. All others should have had this
  // information set already
  uint16_t nexpts = mdEventWS->getNumExperimentInfo();
  if (nexpts > 0) {
    ExperimentInfo_sptr expt =
        mdEventWS->getExperimentInfo(static_cast<uint16_t>(nexpts - 1));
    expt->mutableRun().storeHistogramBinBoundaries(binBoundaries);
    expt->cacheDetectorGroupings(*mapping);
  }
}