GeometryInfoFactory::GeometryInfoFactory(const MatrixWorkspace &workspace) : m_workspace(workspace), m_instrument(workspace.getInstrument()) { // Note: This does not seem possible currently (the instrument objects is // always allocated, even if it is empty), so this will not fail. if (!m_instrument) throw std::runtime_error("Workspace " + workspace.getName() + " does not contain an instrument!"); }
/** Calculate smoothing of the data using the spline * Wraps CubicSpline function1D * * @param inputWorkspace :: The input workspace * @param outputWorkspace :: The output workspace * @param row :: The row of spectra to use */ void SplineSmoothing::calculateSmoothing(const MatrixWorkspace &inputWorkspace, MatrixWorkspace &outputWorkspace, size_t row) const { // define the spline's parameters const auto &xIn = inputWorkspace.x(row); const size_t nData = xIn.size(); const double *xValues = &(xIn[0]); double *yValues = &(outputWorkspace.mutableY(row)[0]); // calculate the smoothing m_cspline->function1D(yValues, xValues, nData); }
MatrixWorkspace_sptr MonteCarloAbsorption::createOutputWorkspace( const MatrixWorkspace &inputWS) const { MatrixWorkspace_sptr outputWS = inputWS.clone(); // The algorithm computes the signal values at bin centres so they should // be treated as a distribution outputWS->setDistribution(true); outputWS->setYUnit(""); outputWS->setYUnitLabel("Attenuation factor"); return outputWS; }
/** Calculate the derivatives of the newly smoothed data using the spline * Wraps CubicSpline derivative1D * * @param inputWorkspace :: The input workspace * @param outputWorkspace :: The output workspace * @param order :: The order of derivatives to calculate * @param row :: The row of spectra to use */ void SplineSmoothing::calculateDerivatives( const MatrixWorkspace &inputWorkspace, API::MatrixWorkspace &outputWorkspace, const int order, const size_t row) const { const auto &xIn = inputWorkspace.x(row); const double *xValues = &(xIn[0]); double *yValues = &(outputWorkspace.mutableY(order - 1)[0]); const size_t nData = xIn.size(); m_cspline->derivative1D(yValues, xValues, nData, order); }
/** * Get log value from a workspace. Convert to double if possible. * * @param ws :: [Input] The input workspace. * @return :: Log value. * @throw :: std::invalid_argument if the log cannot be converted to a double or *doesn't exist. */ double PlotAsymmetryByLogValue::getLogValue(MatrixWorkspace &ws) { const Run &run = ws.run(); // Get the start & end time for the run Mantid::Kernel::DateAndTime start, end; if (run.hasProperty("run_start") && run.hasProperty("run_end")) { start = run.getProperty("run_start")->value(); end = run.getProperty("run_end")->value(); } auto *property = run.getLogData(m_logName); if (!property) { throw std::invalid_argument("Log " + m_logName + " does not exist."); } property->filterByTime(start, end); double value = 0; // try different property types if (convertLogToDouble<double>(property, value, m_logFunc)) return value; if (convertLogToDouble<float>(property, value, m_logFunc)) return value; if (convertLogToDouble<int>(property, value, m_logFunc)) return value; if (convertLogToDouble<long>(property, value, m_logFunc)) return value; if (convertLogToDouble<long long>(property, value, m_logFunc)) return value; if (convertLogToDouble<unsigned int>(property, value, m_logFunc)) return value; if (convertLogToDouble<unsigned long>(property, value, m_logFunc)) return value; if (convertLogToDouble<unsigned long long>(property, value, m_logFunc)) return value; // try if it's a string and can be lexically cast to double auto slog = dynamic_cast<const Mantid::Kernel::PropertyWithValue<std::string> *>( property); if (slog) { try { value = boost::lexical_cast<double>(slog->value()); return value; } catch (std::exception &) { // do nothing, goto throw } } throw std::invalid_argument("Log " + m_logName + " cannot be converted to a double type."); }
/** * Fully masks one component named componentName * @param ws :: workspace with the respective instrument assigned * @param componentName :: must be a known CompAssembly. */ void CalculateEfficiency::maskComponent(MatrixWorkspace &ws, const std::string &componentName) { auto instrument = ws.getInstrument(); try { boost::shared_ptr<const Geometry::ICompAssembly> component = boost::dynamic_pointer_cast<const Geometry::ICompAssembly>( instrument->getComponentByName(componentName)); if (!component) { g_log.warning("Component " + componentName + " expected to be a CompAssembly, e.g., a bank. Component " + componentName + " not masked!"); return; } std::vector<detid_t> detectorList; for (int x = 0; x < component->nelements(); x++) { boost::shared_ptr<Geometry::ICompAssembly> xColumn = boost::dynamic_pointer_cast<Geometry::ICompAssembly>((*component)[x]); for (int y = 0; y < xColumn->nelements(); y++) { boost::shared_ptr<Geometry::Detector> detector = boost::dynamic_pointer_cast<Geometry::Detector>((*xColumn)[y]); if (detector) { auto detID = detector->getID(); detectorList.push_back(detID); } } } auto indexList = ws.getIndicesFromDetectorIDs(detectorList); auto &spectrumInfo = ws.mutableSpectrumInfo(); for (const auto &idx : indexList) { ws.getSpectrum(idx).clearData(); spectrumInfo.setMasked(idx, true); } } catch (std::exception &) { g_log.warning("Expecting the component " + componentName + " to be a CompAssembly, e.g., a bank. Component not masked!"); } }
/** * Checks if the spectra at the given index of either input workspace is masked. * If so then the output spectra has zeroed data * and is also masked. * @param lhsSpectrumInfo :: The LHS spectrum info object * @param rhsSpectrumInfo :: The RHS spectrum info object * @param index :: The workspace index to check * @param out :: A pointer to the output workspace * @param outSpectrumInfo :: The spectrum info object of `out` * @returns True if further processing is not required on the spectra, false if * the binary operation should be performed. */ bool BinaryOperation::propagateSpectraMask(const SpectrumInfo &lhsSpectrumInfo, const SpectrumInfo &rhsSpectrumInfo, const int64_t index, MatrixWorkspace &out, SpectrumInfo &outSpectrumInfo) { bool continueOp(true); if ((lhsSpectrumInfo.hasDetectors(index) && lhsSpectrumInfo.isMasked(index)) || (rhsSpectrumInfo.hasDetectors(index) && rhsSpectrumInfo.isMasked(index))) { continueOp = false; out.getSpectrum(index).clearData(); PARALLEL_CRITICAL(setMasked) { outSpectrumInfo.setMasked(index, true); } }
void addFullInstrumentToWorkspace(MatrixWorkspace &workspace, bool includeMonitors, bool startYNegative, const std::string &instrumentName) { auto instrument = boost::make_shared<Instrument>(instrumentName); instrument->setReferenceFrame( boost::make_shared<ReferenceFrame>(Y, Z, Right, "")); workspace.setInstrument(instrument); const double pixelRadius(0.05); Object_sptr pixelShape = ComponentCreationHelper::createCappedCylinder( pixelRadius, 0.02, V3D(0.0, 0.0, 0.0), V3D(0., 1.0, 0.), "tube"); const double detZPos(5.0); // Careful! Do not use size_t or auto, the unisgned will break the -=2 below. int ndets = static_cast<int>(workspace.getNumberHistograms()); if (includeMonitors) ndets -= 2; for (int i = 0; i < ndets; ++i) { std::ostringstream lexer; lexer << "pixel-" << i << ")"; Detector *physicalPixel = new Detector(lexer.str(), workspace.getAxis(1)->spectraNo(i), pixelShape, instrument.get()); int ycount(i); if (startYNegative) ycount -= 1; const double ypos = ycount * 2.0 * pixelRadius; physicalPixel->setPos(0.0, ypos, detZPos); instrument->add(physicalPixel); instrument->markAsDetector(physicalPixel); workspace.getSpectrum(i).setDetectorID(physicalPixel->getID()); } // Monitors last if (includeMonitors) // These occupy the last 2 spectra { Detector *monitor1 = new Detector("mon1", workspace.getAxis(1)->spectraNo(ndets), Object_sptr(), instrument.get()); monitor1->setPos(0.0, 0.0, -9.0); instrument->add(monitor1); instrument->markAsMonitor(monitor1); workspace.getSpectrum(ndets).setDetectorID(ndets + 1); Detector *monitor2 = new Detector("mon2", workspace.getAxis(1)->spectraNo(ndets) + 1, Object_sptr(), instrument.get()); monitor2->setPos(0.0, 0.0, -2.0); instrument->add(monitor2); instrument->markAsMonitor(monitor2); workspace.getSpectrum(ndets + 1).setDetectorID(ndets + 2); } // Define a source and sample position // Define a source component ObjComponent *source = new ObjComponent( "moderator", ComponentCreationHelper::createSphere(0.1, V3D(0, 0, 0), "1"), instrument.get()); source->setPos(V3D(0.0, 0.0, -20.0)); instrument->add(source); instrument->markAsSource(source); // Define a sample as a simple sphere ObjComponent *sample = new ObjComponent( "samplePos", ComponentCreationHelper::createSphere(0.1, V3D(0, 0, 0), "1"), instrument.get()); instrument->setPos(0.0, 0.0, 0.0); instrument->add(sample); instrument->markAsSamplePos(sample); // chopper position Component *chop_pos = new Component("chopper-position", Kernel::V3D(0, 0, -10), instrument.get()); instrument->add(chop_pos); }
/** Defines the points used to make the spline by iteratively creating more *smoothing points * until all smoothing points fall within a certain error tolerance * * @param inputWorkspace :: The input workspace containing noisy data * @param row :: The row of spectra to use */ void SplineSmoothing::selectSmoothingPoints( const MatrixWorkspace &inputWorkspace, const size_t row) { std::set<int> smoothPts; const auto &xs = inputWorkspace.x(row); const auto &ys = inputWorkspace.y(row); // retrieving number of breaks int maxBreaks = static_cast<int>(getProperty("MaxNumberOfBreaks")); int xSize = static_cast<int>(xs.size()); // evenly space initial points over data set int delta; // if retrieved value is default zero/default bool incBreaks = false; if (maxBreaks != 0) { // number of points to start with int numSmoothPts(maxBreaks); delta = xSize / numSmoothPts; // include maxBreaks when != 0 incBreaks = true; } else { int numSmoothPts(M_START_SMOOTH_POINTS); delta = xSize / numSmoothPts; } for (int i = 0; i < xSize; i += delta) { smoothPts.insert(i); } smoothPts.insert(xSize - 1); bool resmooth(true); while (resmooth) { if (incBreaks) { if (smoothPts.size() > static_cast<unsigned>(maxBreaks + 2)) { break; } } else if (!incBreaks) { if (smoothPts.size() >= xs.size() - 1) { break; } } addSmoothingPoints(smoothPts, &xs[0], &ys[0]); resmooth = false; // calculate the spline and retrieve smoothed points boost::shared_array<double> ysmooth(new double[xSize]); m_cspline->function1D(ysmooth.get(), &xs[0], xSize); // iterate over smoothing points auto iter = smoothPts.cbegin(); int start = *iter; for (++iter; iter != smoothPts.cend(); ++iter) { int end = *iter; // check each point falls within our range of error. bool accurate = checkSmoothingAccuracy(start, end, &ys[0], ysmooth.get()); // if not, flag for resmoothing and add another point between these two // data points if (!accurate) { resmooth = true; smoothPts.insert((start + end) / 2); } start = end; } } }
/** Initialize a workspace from its parent * This sets values such as title, instrument, units, sample, spectramap. * This does NOT copy any data. * * @deprecated Replaced by functions in MantidDataObjects/WorkspaceCreation.h * @param parent :: the parent workspace * @param child :: the child workspace * @param differentSize :: A flag to indicate if the two workspace will be *different sizes */ void WorkspaceFactoryImpl::initializeFromParent( const MatrixWorkspace &parent, MatrixWorkspace &child, const bool differentSize) const { child.setTitle(parent.getTitle()); child.setComment(parent.getComment()); child.copyExperimentInfoFrom(&parent); child.setYUnit(parent.m_YUnit); child.setYUnitLabel(parent.m_YUnitLabel); child.setDistribution(parent.isDistribution()); // Only copy the axes over if new sizes are not given if (!differentSize) { // Only copy mask map if same size for now. Later will need to check // continued validity. child.m_masks = parent.m_masks; } // Same number of histograms = copy over the spectra data if (parent.getNumberHistograms() == child.getNumberHistograms()) { child.m_isInitialized = false; for (size_t i = 0; i < parent.getNumberHistograms(); ++i) child.getSpectrum(i).copyInfoFrom(parent.getSpectrum(i)); child.m_isInitialized = true; // We use this variant without ISpectrum update to avoid costly rebuilds // triggered by setIndexInfo(). ISpectrum::copyInfoFrom sets invalid flags // for spectrum definitions, so it is important to call this *afterwards*, // since it clears the flags: child.setIndexInfoWithoutISpectrumUpdate(parent.indexInfo()); } // deal with axis for (size_t i = 0; i < parent.m_axes.size(); ++i) { if (parent.m_axes[i]->isSpectra()) { // By default the child already has a spectra axis which // does not need to get cloned from the parent. continue; } const bool isBinEdge = dynamic_cast<const BinEdgeAxis *const>(parent.m_axes[i]) != nullptr; const size_t newAxisLength = child.m_axes[i]->length() + (isBinEdge ? 1 : 0); const size_t oldAxisLength = parent.m_axes[i]->length(); // Need to delete the existing axis created in init above delete child.m_axes[i]; child.m_axes[i] = nullptr; if (newAxisLength == oldAxisLength) { // Now set to a copy of the parent workspace's axis child.m_axes[i] = parent.m_axes[i]->clone(&child); } else { // Call the 'different length' clone variant child.m_axes[i] = parent.m_axes[i]->clone(newAxisLength, &child); } } }