28namespace SolidAngleMethods {
37using namespace Kernel;
39using namespace Geometry;
40using namespace SolidAngleMethods;
42namespace SolidAngleHelpers {
57 auto inPlane = sampleDetVec;
59 return sampleDetVec.cosAngle(inPlane);
84 const double pixelArea)
87 if (method.find(
"Vertical") != std::string::npos) {
89 }
else if (method.find(
"Horizontal") != std::string::npos) {
108 const double pixelArea,
const int numberOfCylinderSlices)
126 const double scaledPixelArea =
m_pixelArea * scaleFactor[0] * scaleFactor[1];
127 return scaledPixelArea * cosTheta / (
l2 *
l2);
137 const double scaledPixelArea =
m_pixelArea * scaleFactor[0] * scaleFactor[1];
138 return scaledPixelArea * cosAlpha / (
l2 *
l2);
150 const double scaledPixelArea =
m_pixelArea * scaleFactor[0] * scaleFactor[1];
151 return scaledPixelArea * cosAlpha * cosAlpha * cosAlpha / (
l2 *
l2 * cosTheta * cosTheta);
160 std::make_shared<InstrumentValidator>()),
161 "This workspace is used to identify the instrument to use "
163 "spectra to create a solid angle for. If the Max and Min "
164 "spectra values are\n"
165 "not provided one solid angle will be created for each "
166 "spectra in the input\n"
169 "The name of the workspace to be created as the output of "
170 "the algorithm. A workspace of this name will be created "
171 "and stored in the Analysis Data Service.");
173 auto mustBePositive = std::make_shared<BoundedValidator<int>>();
174 mustBePositive->setLower(0);
176 "The index number of the first spectrum for which to find "
180 "The index of the last spectrum whose solid angle is to be "
181 "found (default: the\n"
182 "last spectrum in the workspace)");
187 "Select the method to calculate the Solid Angle.");
189 auto greaterThanTwo = std::make_shared<BoundedValidator<int>>();
190 greaterThanTwo->setLower(3);
192 "The number of angular slices used when triangulating a cylinder in order to calculate the solid "
193 "angle of a tube detector.");
201 int m_MinSpec =
getProperty(
"StartWorkspaceIndex");
204 const auto numberOfSpectra =
static_cast<int>(inputWS->getNumberHistograms());
207 if (m_MinSpec > numberOfSpectra) {
208 g_log.
warning(
"StartWorkspaceIndex out of range! Set to 0.");
212 m_MaxSpec = numberOfSpectra - 1;
213 if (m_MaxSpec > numberOfSpectra - 1 || m_MaxSpec < m_MinSpec) {
214 g_log.
warning(
"EndWorkspaceIndex out of range! Set to max detector number");
215 m_MaxSpec = numberOfSpectra - 1;
220 outputWS->setDistribution(
true);
221 outputWS->setYUnit(
"");
222 outputWS->setYUnitLabel(
"Steradian");
225 const auto &spectrumInfo = inputWS->spectrumInfo();
226 const auto &detectorInfo = inputWS->detectorInfo();
227 const auto &componentInfo = inputWS->componentInfo();
231 double pixelArea = 0.;
234 using namespace SolidAngleHelpers;
236 const auto instrument = inputWS->getInstrument();
237 if (instrument->hasParameter(
"x-pixel-size") && instrument->hasParameter(
"y-pixel-size")) {
238 const double pixelSizeX = instrument->getNumberParameter(
"x-pixel-size")[0] * MM_TO_METERS;
239 const double pixelSizeY = instrument->getNumberParameter(
"y-pixel-size")[0] * MM_TO_METERS;
240 pixelArea = pixelSizeX * pixelSizeY;
243 throw std::runtime_error(
"Missing necessary instrument parameters for non generic shape: "
244 "x-pixel-size and y-pixel-size [in mm].");
248 int numberOfCylinderSlices =
getProperty(
"NumberOfCylinderSlices");
249 std::unique_ptr<SolidAngleCalculator> solidAngleCalculator;
251 solidAngleCalculator =
252 std::make_unique<GenericShape>(componentInfo, detectorInfo, method, pixelArea, numberOfCylinderSlices);
254 solidAngleCalculator = std::make_unique<Rectangle>(componentInfo, detectorInfo, method, pixelArea);
256 solidAngleCalculator = std::make_unique<Tube>(componentInfo, detectorInfo, method, pixelArea);
258 solidAngleCalculator = std::make_unique<Wing>(componentInfo, detectorInfo, method, pixelArea);
261 std::atomic<size_t> failCount{0};
262 Progress prog(
this, 0.0, 1.0, numberOfSpectra);
265 for (
int j = m_MinSpec; j <= m_MaxSpec; ++j) {
268 if (spectrumInfo.hasDetectors(j)) {
269 double solidAngle = 0.0;
270 for (
const auto detID : inputWS->getSpectrum(j).getDetectorIDs()) {
271 const auto index = detectorInfo.indexOf(detID);
272 if (!detectorInfo.isMasked(
index) && !detectorInfo.isMonitor(
index)) {
273 solidAngle += solidAngleCalculator->solidAngle(
index);
276 outputWS->mutableY(j)[0] = solidAngle;
284 g_log.
warning() <<
"min max total" << m_MinSpec <<
" " << m_MaxSpec <<
" " << numberOfSpectra;
286 auto &outputSpectrumInfo = outputWS->mutableSpectrumInfo();
288 for (
int j = 0; j < m_MinSpec; ++j) {
291 outputSpectrumInfo.setMasked(j,
true);
296 for (
int j = m_MaxSpec + 1; j < numberOfSpectra; ++j) {
299 outputSpectrumInfo.setMasked(j,
true);
303 if (failCount != 0) {
305 <<
" spectra. The solid angle will be set to zero for "
306 "those detectors.\n";
315 outputWS.
mutableX(wsIndex)[0] = inputWS.
x(wsIndex).front();
316 outputWS.
mutableX(wsIndex)[1] = inputWS.
x(wsIndex).back();
#define DECLARE_ALGORITHM(classname)
std::map< DeltaEMode::Type, std::string > index
#define PARALLEL_START_INTERRUPT_REGION
Begins a block to skip processing is the algorithm has been interupted Note the end of the block if n...
#define PARALLEL_END_INTERRUPT_REGION
Ends a block to skip processing is the algorithm has been interupted Note the start of the block if n...
#define PARALLEL_FOR_IF(condition)
Empty definitions - to enable set your complier to enable openMP.
#define PARALLEL_CHECK_INTERRUPT_REGION
Adds a check after a Parallel region to see if it was interupted.
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
static bool isEmpty(const NumT toCheck)
checks that the value was not set by users, uses the value in empty double/int.
Base MatrixWorkspace Abstract Class.
HistogramData::HistogramX & mutableX(const size_t index) &
const HistogramData::HistogramX & x(const size_t index) const
HistogramData::HistogramE & mutableE(const size_t index) &
HistogramData::HistogramY & mutableY(const size_t index) &
Helper class for reporting progress from algorithms.
A property class for workspaces.
void initSpectrum(const API::MatrixWorkspace &input, API::MatrixWorkspace &output, const size_t j)
SolidAngle::initSpectrum Sets the default value for the spectra for which solid angle is not calculat...
void exec() override
Executes the algorithm.
void init() override
Initialisation method.
ComponentInfo : Provides a component centric view on to the instrument.
Kernel::V3D scaleFactor(const size_t componentIndex) const
Geometry::DetectorInfo is an intermediate step towards a DetectorInfo that is part of Instrument-2....
double l2(const size_t index) const
Returns L2 (distance from sample to spectrum).
Kernel::V3D position(const size_t index) const
Returns the position of the detector with given index.
const Geometry::IDetector & detector(const size_t index) const
Return a const reference to the detector with given index.
virtual double solidAngle(const Geometry::SolidAngleParams ¶ms) const =0
Finds the approximate solid angle covered by the component when viewed from the point given.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void warning(const std::string &msg)
Logs at warning level.
void information(const std::string &msg)
Logs at information level.
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
void setX(const double xx) noexcept
Set is x position.
double cosAngle(const V3D &) const
cos(Angle) between this and another vector
void setY(const double yy) noexcept
Set is y position.
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
constexpr double MM_TO_METERS
static const std::string HORIZONTAL_WING
static const std::string VERTICAL_TUBE
static const std::string GENERIC_SHAPE
static const std::string HORIZONTAL_TUBE
static const std::string RECTANGLE
static const std::string VERTICAL_WING
std::enable_if< std::is_pointer< Arg >::value, bool >::type threadSafe(Arg workspace)
Thread-safety check Checks the workspace to ensure it is suitable for multithreaded access.
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
Returns the angle between the sample-to-pixel vector and its projection on the X-Z (vertical tube) or...
virtual ~AlphaAngleCalculator()=default
AlphaAngleCalculator(const DetectorInfo &detectorInfo)
virtual void project(V3D &v) const =0
double getAlpha(size_t index) const
const DetectorInfo & m_detectorInfo
void project(V3D &v) const override
void project(V3D &v) const override
double solidAngle(size_t index) const override
int m_numberOfCylinderSlices
GenericShape(const ComponentInfo &componentInfo, const DetectorInfo &detectorInfo, const std::string &method, const double pixelArea, const int numberOfCylinderSlices)
double solidAngle(size_t index) const override
Creates the solid angle calculator based on the selected method.
virtual ~SolidAngleCalculator()=default
const DetectorInfo & m_detectorInfo
std::unique_ptr< const AlphaAngleCalculator > m_alphaAngleCalculator
const ComponentInfo & m_componentInfo
virtual double solidAngle(size_t index) const =0
SolidAngleCalculator(const ComponentInfo &componentInfo, const DetectorInfo &detectorInfo, const std::string &method, const double pixelArea)
double solidAngle(size_t index) const override
double solidAngle(size_t index) const override
@ Input
An input workspace.
@ Output
An output workspace.