19#include "MantidHistogramData/HistogramIterator.h"
22#include <Poco/DOM/AutoPtr.h>
23#include <Poco/DOM/Document.h>
35 return std::all_of(detIDs.cbegin() + 1, detIDs.cend(), [&](
const auto &detID) { return e == info.getEFixed(detID); });
38constexpr double R = 1.0;
49 double minLat, maxLat, minLong, maxLong;
50 std::tie(minLat, maxLat, minLong, maxLong) =
extremeAngles(modelWS);
51 m_gridDef = std::make_unique<Algorithms::DetectorGridDefinition>(minLat, maxLat, rows, minLong, maxLong, columns);
52 if ((rows < 3) || (columns < 3)) {
53 g_log.
warning(
"Can't calculate errors on a sparse workspace with lat or "
54 "long dimension < 3");
56 const size_t numSpectra = rows * columns;
61 auto instrument = std::make_shared<Geometry::Instrument>(
"MC_simulation_instrument");
62 const auto refFrame = modelWS.
getInstrument()->getReferenceFrame();
64 instrument->setReferenceFrame(std::make_shared<Geometry::ReferenceFrame>(*refFrame));
67 auto sample = std::make_unique<Geometry::Component>(
"sample", instrument.get());
69 instrument->add(
sample.get());
70 instrument->markAsSamplePos(
sample.release());
74 p[refFrame->pointingAlongBeam()] = -2.0 * R;
77 auto source = std::make_unique<Geometry::ObjComponent>(
"source",
nullptr, instrument.get());
78 source->setPos(sourcePos);
79 instrument->add(source.get());
80 instrument->markAsSource(source.release());
83 for (
size_t col = 0; col < columns; ++col) {
84 const auto lon =
m_gridDef->longitudeAt(col);
85 for (
size_t row = 0; row < rows; ++row) {
86 const auto lat =
m_gridDef->latitudeAt(row);
87 const size_t index = col * rows + row;
88 const auto detID =
static_cast<int>(
index);
89 std::ostringstream detName;
90 detName <<
"det-" << detID;
91 auto det = std::make_unique<Geometry::Detector>(detName.str(), detID, detShape, instrument.get());
94 p[refFrame->pointingHorizontal()] = R * std::sin(lon) * std::cos(lat);
95 p[refFrame->pointingUp()] = R * std::sin(lat);
96 p[refFrame->pointingAlongBeam()] = R * std::cos(lon) * std::cos(lat);
101 instrument->add(det.get());
102 instrument->markAsDetector(det.release());
111 const auto modelSource = modelWS.
getInstrument()->getSource();
112 const auto parametrizedSource = parametrizedInstrument->getSource();
113 const auto beamShapeParam = modelSource->getParameterAsString(
"beam-shape");
114 if (!beamShapeParam.empty())
115 paramMap.add(
"string", parametrizedSource.get(),
"beam-shape", beamShapeParam);
116 const auto beamWidthParam = modelSource->getNumberParameter(
"beam-width");
117 const auto beamHeightParam = modelSource->getNumberParameter(
"beam-height");
118 if (beamWidthParam.size() == 1 && beamHeightParam.size() == 1) {
119 paramMap.add(
"double", parametrizedSource.get(),
"beam-width", beamWidthParam[0]);
120 paramMap.add(
"double", parametrizedSource.get(),
"beam-height", beamHeightParam[0]);
122 const auto beamRadiusParam = modelSource->getNumberParameter(
"beam-radius");
123 if (beamRadiusParam.size() == 1) {
124 paramMap.add(
"double", parametrizedSource.get(),
"beam-radius", beamRadiusParam[0]);
127 const auto eMode = modelWS.
getEMode();
132 std::vector<detid_t> detIDs;
137 if (!modelInstrument->isMonitor(specDetIDs))
138 detIDs.insert(detIDs.end(), specDetIDs.begin(), specDetIDs.end());
140 if (detIDs.empty()) {
141 throw std::runtime_error(
"Sparse instrument: no non-monitor detectors found for Indirect mode.");
143 if (!constantIndirectEFixed(modelWS, detIDs)) {
144 throw std::runtime_error(
"Sparse instrument with variable EFixed not supported.");
148 for (
int sparseDetID : sparseDetIDs) {
165 double minLat = std::numeric_limits<double>::max();
166 double maxLat = std::numeric_limits<double>::lowest();
167 double minLong = std::numeric_limits<double>::max();
168 double maxLong = std::numeric_limits<double>::lowest();
187 return std::make_tuple(minLat, maxLat, minLong, maxLong);
195 double currentMin = std::numeric_limits<double>::max();
196 double currentMax = std::numeric_limits<double>::lowest();
199 const auto first =
h.begin();
200 currentMin = std::min(first->center(), currentMin);
201 const auto last = std::prev(
h.end());
202 currentMax = std::max(last->center(), currentMax);
204 return std::make_tuple(currentMin, currentMax);
213 const size_t wavelengthPoints) {
214 double minWavelength, maxWavelength;
216 HistogramData::Frequencies ys(wavelengthPoints, 0.0);
217 HistogramData::FrequencyVariances es(wavelengthPoints, 0.0);
218 HistogramData::Points ps(wavelengthPoints, 0.0);
219 HistogramData::Histogram
h(ps, ys, es);
220 auto &xs =
h.mutableX();
221 if (wavelengthPoints > 1) {
222 const double step = (maxWavelength - minWavelength) /
static_cast<double>(wavelengthPoints - 1);
223 for (
size_t i = 0; i < xs.size() - 1; ++i) {
224 xs[i] = minWavelength + step *
static_cast<double>(i);
228 xs.back() = maxWavelength;
230 xs.front() = (minWavelength + maxWavelength) / 2.0;
240 const double dimension = 0.05;
241 AutoPtr<Document> shapeDescription =
new Document;
242 AutoPtr<Element> typeElement = shapeDescription->createElement(
"type");
243 typeElement->setAttribute(
"name",
"detector");
244 AutoPtr<Element> shapeElement = shapeDescription->createElement(
"cuboid");
245 shapeElement->setAttribute(
"id",
"cube");
248 AutoPtr<Element> element = shapeDescription->createElement(
"left-front-bottom-point");
249 element->setAttribute(
"x", negCoord);
250 element->setAttribute(
"y", negCoord);
251 element->setAttribute(
"z", posCoord);
252 shapeElement->appendChild(element);
253 element = shapeDescription->createElement(
"left-front-top-point");
254 element->setAttribute(
"x", negCoord);
255 element->setAttribute(
"y", posCoord);
256 element->setAttribute(
"z", posCoord);
257 shapeElement->appendChild(element);
258 element = shapeDescription->createElement(
"left-back-bottom-point");
259 element->setAttribute(
"x", negCoord);
260 element->setAttribute(
"y", negCoord);
261 element->setAttribute(
"z", negCoord);
262 shapeElement->appendChild(element);
263 element = shapeDescription->createElement(
"right-front-bottom-point");
264 element->setAttribute(
"x", posCoord);
265 element->setAttribute(
"y", negCoord);
266 element->setAttribute(
"z", posCoord);
267 shapeElement->appendChild(element);
268 typeElement->appendChild(shapeElement);
269 AutoPtr<Element> algebraElement = shapeDescription->createElement(
"algebra");
270 algebraElement->setAttribute(
"val",
"cube");
271 typeElement->appendChild(algebraElement);
284 const double long2) {
285 const double latD = std::sin((lat2 - lat1) / 2.0);
286 const double longD = std::sin((long2 - long1) / 2.0);
287 const double S = latD * latD + std::cos(lat1) * std::cos(lat2) * longD * longD;
288 return 2.0 * std::asin(std::sqrt(S));
296 std::array<double, 4> weights;
297 for (
size_t i = 0; i < weights.size(); ++i) {
298 if (distances[i] == 0.0) {
303 weights[i] = 1.0 / distances[i] / distances[i];
314 const double distanceStep)
const {
315 HistogramData::HistogramY avgSecondDeriv(
blocksize());
317 HistogramData::HistogramY sumSecondDeriv(
blocksize());
318 auto firstDerivB = (
y(indices[2]) -
y(indices[1])) / distanceStep;
319 auto firstDerivA = (
y(indices[1]) -
y(indices[0])) / distanceStep;
320 auto secondDerivA = (firstDerivB - firstDerivA) / distanceStep;
331 const auto indices =
m_gridDef->nearestNeighbourIndices(lat, lon);
335 std::array<double, 4> distances;
336 for (
size_t i = 0; i < 4; ++i) {
337 double detLat, detLong;
342 auto weightSum = weights[0];
343 h.mutableY() = weights[0] *
y(indices[0]);
344 for (
size_t i = 1; i < 4; ++i) {
345 weightSum += weights[i];
346 h.mutableY() += weights[i] *
y(indices[i]);
348 h.mutableY() /= weightSum;
363 std::transform(
e.cbegin(),
e.cend(),
e.begin(), [](
double f) ->
double { return sqrt(f); });
377 const double lon)
const {
379 size_t nearestLatIndex, nearestLonIndex;
380 std::tie(nearestLatIndex, nearestLonIndex) =
m_gridDef->getNearestVertex(lat, lon);
382 std::array<std::array<size_t, 2>, 2> detIndices;
383 for (
size_t i = 0; i < 2; i++) {
384 for (
size_t j = 0; j < 2; j++) {
385 detIndices[i][j] =
m_gridDef->getDetectorIndex(nearestLatIndex + j, nearestLonIndex + i);
389 double latLow, longLow, latHigh, longHigh;
394 auto ylat1 = ((longHigh - lon) *
y(detIndices[0][0]) + (lon - longLow) *
y(detIndices[1][0])) / (longHigh - longLow);
395 auto errLat1 =
esqrt(
esq((longHigh - lon) *
e(detIndices[0][0])) +
esq((lon - longLow) *
e(detIndices[1][0]))) /
396 (longHigh - longLow);
398 auto ylat2 = ((longHigh - lon) *
y(detIndices[0][1]) + (lon - longLow) *
y(detIndices[1][1])) / (longHigh - longLow);
399 auto errLat2 =
esqrt(
esq((longHigh - lon) *
e(detIndices[0][1])) +
esq((lon - longLow) *
e(detIndices[1][1]))) /
400 (longHigh - longLow);
403 auto interpY = ((latHigh - lat) * ylat1 + (lat - latLow) * ylat2) / (latHigh - latLow);
404 auto errFromSourcePoints =
esqrt(
esq((latHigh - lat) * errLat1) +
esq((lat - latLow) * errLat2)) / (latHigh - latLow);
407 HistogramData::HistogramE interpolationError(
e(0).
size(), 0);
411 auto nearestLatIndexSec = nearestLatIndex > 0 ? nearestLatIndex - 1 : 0;
412 auto nearestLonIndexSec = nearestLonIndex > 0 ? nearestLonIndex - 1 : 0;
413 std::array<size_t, 3> threeIndices;
416 for (
int i = 0; i < 3; i++) {
417 threeIndices[i] =
m_gridDef->getDetectorIndex(nearestLatIndex, nearestLonIndexSec + i);
419 auto avgSecondDerivLong =
secondDerivative(threeIndices, longHigh - longLow);
422 for (
int i = 0; i < 3; i++) {
423 threeIndices[i] =
m_gridDef->getDetectorIndex(nearestLatIndexSec + i, nearestLonIndex);
430 HistogramData::HistogramY interpolationErrorAsYData =
431 0.5 * (lon - longLow) * (longHigh - lon) * avgSecondDerivLong +
432 0.5 * (lat - latLow) * (latHigh - lat) * avgSecondDerivLat;
434 interpolationError = interpolationErrorAsYData.rawData();
438 h.mutableY() = interpY;
442 h.mutableE() =
esqrt(
esq(interpolationError) +
esq(errFromSourcePoints));
std::map< DeltaEMode::Type, std::string > index
This class is shared by a few Workspace types and holds information related to a particular experimen...
Run & mutableRun()
Writable version of the run object.
const SpectrumInfo & spectrumInfo() const
Return a reference to the SpectrumInfo object.
const Geometry::DetectorInfo & detectorInfo() const
Return a const reference to the DetectorInfo object.
double getEFixed(const detid_t detID) const
Easy access to the efixed value for this run & detector ID.
Geometry::Instrument_const_sptr getInstrument() const
Returns the parameterized instrument.
Kernel::DeltaEMode::Type getEMode() const
Returns the emode for this run.
const Sample & sample() const
Sample accessors.
void setEFixed(const detid_t detID, const double value)
Set the efixed value for a given detector ID.
const Geometry::ParameterMap & instrumentParameters() const
Returns the set of parameters modifying the base instrument (const-version)
void setInstrument(const Geometry::Instrument_const_sptr &instr)
Instrument accessors.
void setDetectorID(const detid_t detID)
Clear the list of detector IDs, then add one.
const std::set< detid_t > & getDetectorIDs() const
Get a const reference to the detector IDs set.
void addProperty(Kernel::Property *prop, bool overwrite=false)
Add data to the object in the form of a property.
Base MatrixWorkspace Abstract Class.
virtual ISpectrum & getSpectrum(const size_t index)=0
Return the underlying ISpectrum ptr at the given workspace index.
const HistogramData::HistogramE & e(const size_t index) const
void initialize(const std::size_t &NVectors, const std::size_t &XLength, const std::size_t &YLength)
Initialize the workspace.
virtual std::size_t getNumberHistograms() const =0
Returns the number of histograms in the workspace.
HistogramData::Histogram histogram(const size_t index) const
Returns the Histogram at the given workspace index.
bool hasDetectors(const size_t index) const
Returns true if the spectrum is associated with detectors in the instrument.
std::pair< double, double > geographicalAngles(const size_t index) const
Calculate latitude and longitude for given spectrum index.
DetectorGridDefinition is a helper class for building the sparse instrument in MonteCarloAbsorption.
Defines functions and utilities to create and deal with sparse instruments.
static std::array< double, 4 > inverseDistanceWeights(const std::array< double, 4 > &distances)
Calculate the inverse distance weights for the given distances.
HistogramData::HistogramE esq(const HistogramData::HistogramE &e) const
Square the error values in a histogram.
static std::tuple< double, double > extremeWavelengths(const API::MatrixWorkspace &ws)
Find the maximum and minimum wavelength points over the entire workpace.
static HistogramData::Histogram modelHistogram(const API::MatrixWorkspace &modelWS, const size_t wavelengthPoints)
Create a template histogram for the sparse instrument workspace.
HistogramData::HistogramY secondDerivative(const std::array< size_t, 3 > &indices, const double distanceStep) const
Calculate the second derivative of a histogram along a row of indices.
std::unique_ptr< Algorithms::DetectorGridDefinition > m_gridDef
static double greatCircleDistance(const double lat1, const double long1, const double lat2, const double long2)
Calculate the distance between two points on a unit sphere.
HistogramData::HistogramE esqrt(HistogramData::HistogramE e) const
Square root the error values in a histogram.
static std::tuple< double, double, double, double > extremeAngles(const API::MatrixWorkspace &ws)
Find the latitude and longitude intervals the detectors of the given workspace span as seen from the ...
Mantid::Geometry::IObject_sptr makeCubeShape()
Creates a rectangular cuboid shape.
virtual HistogramData::Histogram interpolateFromDetectorGrid(const double lat, const double lon) const
Spatially interpolate a single histogram from nearby detectors.
SparseWorkspace * doClone() const override
Virtual clone method. Not implemented to force implementation in children.
virtual HistogramData::Histogram bilinearInterpolateFromDetectorGrid(const double lat, const double lon) const
Spatially interpolate a single histogram from nearby detectors using bilinear interpolation method.
SparseWorkspace(const API::MatrixWorkspace &modelWS, const size_t wavelengthPoints, const size_t rows, const size_t columns)
Concrete workspace implementation.
std::size_t size() const override
get pseudo size
Histogram1D & getSpectrum(const size_t index) override
Return the underlying ISpectrum ptr at the given workspace index.
std::size_t blocksize() const override
get the size of each vector
const std::vector< detid_t > & detectorIDs() const
Returns a sorted vector of all detector IDs.
Class originally intended to be used with the DataHandling 'LoadInstrument' algorithm.
std::shared_ptr< CSGObject > createShape(Poco::XML::Element *pElem)
Creates a geometric object from a DOM-element-node pointing to an element whose child nodes contain t...
The Logger class is in charge of the publishing messages from the framework through various channels.
void warning(const std::string &msg)
Logs at warning level.
Kernel::Logger g_log("DetermineSpinStateOrder")
std::shared_ptr< IObject > IObject_sptr
Typdef for a shared pointer.
static constexpr double h
Planck constant in J*s.
std::string to_string(const wide_integer< Bits, Signed > &n)
static std::string asString(const Type mode)
Return a string representation of the given mode.