/**
   * Constructor helper
   * @param workspace :: MDWorkspace
   * @param function :: implicit function or NULL for none. Gains ownership of the pointer.
   * @param beginPos :: Start position
   * @param endPos :: End position
   */
  void MDHistoWorkspaceIterator::init(const MDHistoWorkspace * workspace,
      Mantid::Geometry::MDImplicitFunction * function,
      size_t beginPos, size_t endPos)
  {
    m_ws = workspace;
    if (m_ws == NULL)
      throw std::invalid_argument("MDHistoWorkspaceIterator::ctor(): NULL workspace given.");

    m_begin = beginPos;
    m_pos = m_begin;
    m_function = function;

    m_max = endPos;
    if (m_max > m_ws->getNPoints())
      m_max = m_ws->getNPoints();
    if (m_max < m_pos)
      throw std::invalid_argument("MDHistoWorkspaceIterator::ctor(): End point given is before the start point.");

    m_nd = m_ws->getNumDims();
    m_center = new coord_t[m_nd];
    m_origin = new coord_t[m_nd];
    m_binWidth = new coord_t[m_nd];
    m_index = new size_t[m_nd];
    m_indexMax = new size_t[m_nd];
    m_indexMaker = new size_t[m_nd];
    Utils::NestedForLoop::SetUp(m_nd, m_index, 0);
    // Initalize all these values
    for (size_t d=0; d<m_nd; d++)
    {
      IMDDimension_const_sptr dim = m_ws->getDimension(d);
      m_center[d] = 0;
      m_origin[d] = dim->getMinimum();
      m_binWidth[d] = dim->getBinWidth();
      m_indexMax[d] = dim->getNBins();
    }
    Utils::NestedForLoop::SetUpIndexMaker(m_nd, m_indexMaker, m_indexMax);

    // Initialize the current index from the start position.
    Utils::NestedForLoop::GetIndicesFromLinearIndex(m_nd, m_pos, m_indexMaker, m_indexMax,
        m_index);

    // Make sure that the first iteration is at a point inside the implicit function
    if (m_function)
    {
      // Calculate the center of the 0-th bin
      for (size_t d=0; d<m_nd; d++)
        m_center[d] = m_origin[d] + 0.5f * m_binWidth[d];
      // Skip on if the first point is NOT contained
      if (!m_function->isPointContained(m_center))
        next();
    }
  }
/*
Extract the geometry and function information
@param eventWs : event workspace to get the information from.
*/
void MDEWLoadingPresenter::extractMetadata(
    Mantid::API::IMDEventWorkspace_sptr eventWs) {
    using namespace Mantid::Geometry;
    MDGeometryBuilderXML<NoDimensionPolicy> refresh;
    xmlBuilder = refresh; // Reassign.
    std::vector<MDDimensionExtents<coord_t>> ext =
            eventWs->getMinimumExtents(5);
    std::vector<IMDDimension_sptr> dimensions;
    size_t nDimensions = eventWs->getNumDims();
    for (size_t d = 0; d < nDimensions; d++) {
        IMDDimension_const_sptr inDim = eventWs->getDimension(d);
        coord_t min = ext[d].getMin();
        coord_t max = ext[d].getMax();
        if (min > max) {
            min = 0.0;
            max = 1.0;
        }
        // std::cout << "dim " << d << min << " to " <<  max << std::endl;
        axisLabels.push_back(makeAxisTitle(inDim));
        MDHistoDimension_sptr dim(new MDHistoDimension(
                                      inDim->getName(), inDim->getName(), inDim->getMDFrame(), min, max,
                                      inDim->getNBins()));
        dimensions.push_back(dim);
    }

    // Configuring the geometry xml builder allows the object panel associated
    // with this reader to later
    // determine how to display all geometry related properties.
    if (nDimensions > 0) {
        xmlBuilder.addXDimension(dimensions[0]);
    }
    if (nDimensions > 1) {
        xmlBuilder.addYDimension(dimensions[1]);
    }
    if (nDimensions > 2) {
        xmlBuilder.addZDimension(dimensions[2]);
    }
    if (nDimensions > 3) {
        tDimension = dimensions[3];
        xmlBuilder.addTDimension(tDimension);
    }
    m_isSetup = true;
}
Beispiel #3
0
/** Get ordered list of boundaries in position-along-the-line coordinates
 *
 * @param start :: start of the line
 * @param end :: end of the line
 * @param nd :: number of dimensions
 * @param dir :: vector of the direction
 * @param length :: unit-vector of the direction
 * @returns :: ordered list of boundaries
 */
std::set<coord_t>
MDHistoWorkspace::getBinBoundariesOnLine(const VMD &start, const VMD &end,
                                         size_t nd, const VMD &dir,
                                         coord_t length) const {
  std::set<coord_t> boundaries;

  // Start with the start/end points, if they are within range.
  if (pointInWorkspace(this, start))
    boundaries.insert(0.0f);
  if (pointInWorkspace(this, end))
    boundaries.insert(length);

  // Next, we go through each dimension and see where the bin boundaries
  // intersect the line.
  for (size_t d = 0; d < nd; d++) {
    IMDDimension_const_sptr dim = getDimension(d);
    coord_t lineStartX = start[d];

    if (dir[d] != 0.0) {
      for (size_t i = 0; i <= dim->getNBins(); i++) {
        // Position in this coordinate
        coord_t thisX = dim->getX(i);
        // Position along the line. Is this between the start and end of it?
        coord_t linePos = (thisX - lineStartX) / dir[d];
        if (linePos >= 0 && linePos <= length) {
          // Full position
          VMD pos = start + (dir * linePos);
          // This is a boundary if the line point is inside the workspace
          if (pointInWorkspace(this, pos))
            boundaries.insert(linePos);
        }
      }
    }
  }
  return boundaries;
}
Beispiel #4
0
/** Obtain coordinates for a line plot through a MDWorkspace.
 * Cross the workspace from start to end points, recording the signal along the
 *lin at either bin boundaries, or halfway between bin boundaries (which is bin
 *centres if the line is dimension aligned). If recording halfway values then
 *omit points in masked bins.
 *
 * @param start :: coordinates of the start point of the line
 * @param end :: coordinates of the end point of the line
 * @param normalize :: how to normalize the signal
 * @returns :: LinePlot with x as the boundaries of the bins, relative
 * to start of the line, y set to the normalized signal for each bin with
 * Length = length(x) - 1 and e as the error vector for each bin.
 * @param bin_centres :: if true then record points halfway between bin
 *boundaries, otherwise record on bin boundaries
 */
IMDWorkspace::LinePlot MDHistoWorkspace::getLinePoints(
    const Mantid::Kernel::VMD &start, const Mantid::Kernel::VMD &end,
    Mantid::API::MDNormalization normalize, const bool bin_centres) const {
  LinePlot line;

  size_t nd = this->getNumDims();
  if (start.getNumDims() != nd)
    throw std::runtime_error("Start point must have the same number of "
                             "dimensions as the workspace.");
  if (end.getNumDims() != nd)
    throw std::runtime_error(
        "End point must have the same number of dimensions as the workspace.");

  // Unit-vector of the direction
  VMD dir = end - start;
  const auto length = dir.normalize();

// Vector with +1 where direction is positive, -1 where negative
#define sgn(x) ((x < 0) ? -1.0f : ((x > 0.) ? 1.0f : 0.0f))
  VMD dirSign(nd);
  for (size_t d = 0; d < nd; d++) {
    dirSign[d] = sgn(dir[d]);
  }
  const size_t BADINDEX = size_t(-1);

  // Dimensions of the workspace
  boost::scoped_array<size_t> index(new size_t[nd]);
  boost::scoped_array<size_t> numBins(new size_t[nd]);
  for (size_t d = 0; d < nd; d++) {
    IMDDimension_const_sptr dim = this->getDimension(d);
    index[d] = BADINDEX;
    numBins[d] = dim->getNBins();
  }

  const std::set<coord_t> boundaries =
      getBinBoundariesOnLine(start, end, nd, dir, length);

  if (boundaries.empty()) {
    this->makeSinglePointWithNaN(line.x, line.y, line.e);

    // Require x.size() = y.size()+1 if recording bin boundaries
    if (!bin_centres)
      line.x.push_back(length);

    return line;
  } else {
    // Get the first point
    std::set<coord_t>::iterator it;
    it = boundaries.cbegin();

    coord_t lastLinePos = *it;
    VMD lastPos = start + (dir * lastLinePos);
    if (!bin_centres) {
      line.x.push_back(lastLinePos);
    }

    ++it;
    coord_t linePos = 0;
    for (; it != boundaries.cend(); ++it) {
      // This is our current position along the line
      linePos = *it;

      // This is the full position at this boundary
      VMD pos = start + (dir * linePos);

      // Position in the middle of the bin
      VMD middle = (pos + lastPos) * 0.5;

      // Find the signal in this bin
      const auto linearIndex =
          this->getLinearIndexAtCoord(middle.getBareArray());

      if (bin_centres && !this->getIsMaskedAt(linearIndex)) {
        coord_t bin_centrePos =
            static_cast<coord_t>((linePos + lastLinePos) * 0.5);
        line.x.push_back(bin_centrePos);
      } else if (!bin_centres)
        line.x.push_back(linePos);

      if (linearIndex < m_length) {

        auto normalizer = getNormalizationFactor(normalize, linearIndex);
        // And add the normalized signal/error to the list too
        auto signal = this->getSignalAt(linearIndex) * normalizer;
        if (boost::math::isinf(signal)) {
          // The plotting library (qwt) doesn't like infs.
          signal = std::numeric_limits<signal_t>::quiet_NaN();
        }
        if (!bin_centres || !this->getIsMaskedAt(linearIndex)) {
          line.y.push_back(signal);
          line.e.push_back(this->getErrorAt(linearIndex) * normalizer);
        }
        // Save the position for next bin
        lastPos = pos;
      } else {
        // Invalid index. This shouldn't happen
        line.y.push_back(std::numeric_limits<signal_t>::quiet_NaN());
        line.e.push_back(std::numeric_limits<signal_t>::quiet_NaN());
      }

      lastLinePos = linePos;

    } // for each unique boundary

    // If all bins were masked
    if (line.x.size() == 0) {
      this->makeSinglePointWithNaN(line.x, line.y, line.e);
    }
  }
  return line;
}