/** Constructor with normal and point * * @param normal :: normal to the plane. Points that are in the direction of the *normal of the plane are considered to be bounded by it. * @param point :: any point that is on the plane */ MDPlane::MDPlane(const Mantid::Kernel::VMD &normal, const Mantid::Kernel::VMD &point) { m_nd = normal.getNumDims(); if ((m_nd < 1) || (m_nd > 100)) throw std::invalid_argument( "MDPlane::ctor(): Invalid number of dimensions in the normal vector !"); if (point.getNumDims() != normal.getNumDims()) throw std::invalid_argument("MDPlane::ctor(): Inconsistent number of " "dimensions in the normal/point vectors!"); construct(normal, point); }
/** Constructor * * @param workspace :: IMDWorkspace to plot * @param logScale :: true to plot Y in log scale * @param start :: start point in N-dimensions of the line * @param end :: end point in N-dimensions of the line * @param normalize :: method for normalizing the line * @param isDistribution :: is this a distribution (divide by bin width?) * @return */ MantidQwtIMDWorkspaceData::MantidQwtIMDWorkspaceData(Mantid::API::IMDWorkspace_const_sptr workspace, const bool logScale, Mantid::Kernel::VMD start, Mantid::Kernel::VMD end, Mantid::API::MDNormalization normalize, bool isDistribution) : m_workspace(workspace), m_logScale(logScale), m_minPositive(0), m_preview(false), m_start(start), m_end(end), m_normalization(normalize), m_isDistribution(isDistribution), m_transform(NULL), m_plotAxis(PlotDistance), m_currentPlotAxis(PlotDistance) { if (start.getNumDims() == 1 && end.getNumDims() == 1) { if (start[0] == 0.0 && end[0] == 0.0) { // Default start and end. Find the limits Mantid::Geometry::VecIMDDimension_const_sptr nonIntegDims = m_workspace->getNonIntegratedDimensions(); std::string alongDim = ""; if (!nonIntegDims.empty()) alongDim = nonIntegDims[0]->getName(); else alongDim = m_workspace->getDimension(0)->getName(); size_t nd = m_workspace->getNumDims(); m_start = VMD(nd); m_end = VMD(nd); for (size_t d=0; d<nd; d++) { IMDDimension_const_sptr dim = m_workspace->getDimension(d); if (dim->getDimensionId() == alongDim) { // All the way through in the single dimension m_start[d] = dim->getMinimum(); m_end[d] = dim->getMaximum(); } else { // Mid point along each dimension m_start[d] = (dim->getMaximum() + dim->getMinimum()) / 2.0f; m_end[d] = m_start[d]; } } } } // Unit direction of the line m_dir = m_end - m_start; m_dir.normalize(); // And cache the X/Y values this->cacheLinePlot(); }
/** Set the width of the line in each dimensions * @param width :: vector for the width in each dimension. X dimension stands in for the XY plane width */ void LineViewer::setThickness(Mantid::Kernel::VMD width) { if (m_ws && width.getNumDims() != m_ws->getNumDims()) throw std::runtime_error("LineViewer::setThickness(): Invalid number of dimensions in the width vector."); m_thickness = width; updateStartEnd(); }
/** Set the end point of the line to integrate * @param end :: vector for the end point */ void LineViewer::setEnd(Mantid::Kernel::VMD end) { if (m_ws && end.getNumDims() != m_ws->getNumDims()) throw std::runtime_error("LineViewer::setEnd(): Invalid number of dimensions in the end vector."); m_end = end; updateStartEnd(); }
/** Set the start point of the line to integrate * @param start :: vector for the start point */ void LineViewer::setStart(Mantid::Kernel::VMD start) { if (m_ws && start.getNumDims() != m_ws->getNumDims()) throw std::runtime_error("LineViewer::setStart(): Invalid number of dimensions in the start vector."); m_start = start; updateStartEnd(); }
/** Apply the transformation to an input vector (as a VMD type). * This wraps the apply(in,out) method (and will be slower!) * * @param inputVector :: an inD-length vector * @return the output vector as VMD */ Mantid::Kernel::VMD CoordTransform::applyVMD(const Mantid::Kernel::VMD &inputVector) const { if (inputVector.getNumDims() != inD) throw std::runtime_error("CoordTransform::apply(): inputVector has the " "wrong number of coordinates!"); coord_t *outArray = new coord_t[outD]; this->apply(inputVector.getBareArray(), outArray); VMD out(outD, outArray); delete[] outArray; return out; }
/** 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; }