Newer
Older
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2009 ISIS Rutherford Appleton Laboratory UKRI,
// NScD Oak Ridge National Laboratory, European Spallation Source,
// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
// SPDX - License - Identifier: GPL - 3.0 +
Federico Montesino Pouzols
committed
#include "MantidAPI/Algorithm.h"
#include "MantidGeometry/IDetector.h"
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
namespace Mantid {
namespace DataHandling {
/** file types currently supported by ASCII loader are:
*1) an ASCII Tobyfit par file
* Syntax:
* >> par = get_ascii_file(filename,['par'])
*
* filename name of par file
*
* par(5,ndet) contents of array
*
* 1st column sample-detector distance
* 2nd " scattering angle (deg)
* 3rd " azimuthal angle (deg)
* (west bank = 0 deg, north bank = -90 deg etc.)
* (Note the reversed sign convention cf .phx files)
* 4th " width (m)
* 5th " height (m)
*-----------------------------------------------------------------------
*2) load an ASCII phx file
*
*
* phx(7,ndet) contents of array
*
* Recall that only the 3,4,5,6 columns in the file (rows in the
* output of this routine) contain useful information
* 3rd column scattering angle (deg)
* 4th " azimuthal angle (deg)
* (west bank = 0 deg, north bank = 90 deg etc.)
* 5th " angular width (deg)
* 6th " angular height (deg)
*-----------------------------------------------------------------------
*/
enum fileTypes {
PAR_type, //< ASCII PAR file
PHX_type, //< ASCII phx file
SPE_type, //< spe file, this loader would not work with spe file, left for
// compartibility with old algorithms.
BIN_file, //< binary file is not an ASCII file, so ascii loader would not work
// on it
NumFileTypes
};
/**
* Description of the ASCII data header, common for all ASCII PAR and PHX
* files
*/
struct FileTypeDescriptor {
fileTypes Type;
std::streampos data_start_position; //< the position in the file where the
// data structure starts
size_t nData_records, //< number of data records -- actually nDetectors
nData_blocks; //< nEnergy bins for SPE file, 5 or 6 for PAR file and 7 for
// PHX file
char line_end; //< the character which ends line in current ASCII file 0x0A
//(LF)
// Unix, 0x0D (CR) Mac and 0x0D 0x0A (CR LF) Win, but the last is interpreted
// as 0x0A here
FileTypeDescriptor()
: Type(BIN_file), data_start_position(0), nData_records(0),
nData_blocks(0), line_end(0x0A) {}
};
/**
An algorithm to calculate the angular coordinates of the workspace's detectors,
as they can be viewed from a sample (par or phx data)
Properties:
<UL>
<LI> Workspace - The name of the input Workspace2D on which to perform the
algorithm.
Detectors or detectors groups have to be loaded into this workspace </LI>
<LI> OutputTable workspace name - if present, identify the name of the output
table workspace with provided detectors parameters </LI>
<LI> Par or phx file name - if present, used to define the detectors parameters
from the file instead of the parameters
calculated from the instrument description</LI>
</UL>
Output Properties:
Optional: OutputTableWorkspace - the workspace which contains five columns with
the following values:
<UL>
<LI> azimuthal - A columnt containing the detectors azimutal
angles</LI>
<LI> polar - A column containing the detectors polar
angles</LI>
<LI> secondary_flightpath - A column containing the distance from detectors to
the sample center</LI>
<LI> azimuthal_width - A column containing the detectors azimuthal
angular width</LI>
<LI> polar_width - A column containing the detectors polar angular
width</LI>
</UL>
When OutputTable workspace name is empty, the tabled workspace is not defined.
To get access to the resulting arrays,
the algorithm user has to deploy accessors (getAzimuthal(), getPolar() etc.),
defined below, which allows avoiding the
transformation of these arrays into strings.
@author Alex Buts ISIS; initially extracted from Stuart Campbell's SaveNXSPE
algorithm,
@date 17/05/2012
*/
// predefine class, used to cashe precalculated detector's parameters
class DetParameters;
class DLLExport FindDetectorsPar : public API::Algorithm {
/// Algorithm's name for identification overriding a virtual method
const std::string name() const override { return "FindDetectorsPar"; };
/// Summary of algorithms purpose
const std::string summary() const override {
return "The algorithm returns the angular parameters and second flight "
"path for a workspace detectors (data, usually availble in par or "
"phx file)";
}
/// Algorithm's version for identification overriding a virtual method
int version() const override { return 1; };
/// Algorithm's category for identification overriding a virtual method
const std::string category() const override {
return "DataHandling\\Instrument";
}
/// the accessors, used to return algorithm results when called as Child
/// Algorithm, without setting the properties;
std::vector<double> const &getAzimuthal() const { return azimuthal; }
std::vector<double> const &getPolar() const { return polar; }
std::vector<double> const &getAzimWidth() const { return azimuthalWidth; }
std::vector<double> const &getPolarWidth() const { return polarWidth; }
std::vector<double> const &getFlightPath() const {
return secondaryFlightpath;
}
std::vector<size_t> const &getDetID() const { return detID; }
/// number of real detectors, calculated by algorithm
size_t getNDetectors() const { return m_nDetectors; }
private:
// Implement abstract Algorithm methods
void init() override;
void exec() override;
/** the variable defines if algorithm needs to calculate linear ranges for
* the detectors (dX,dY)
* instead of azimuthal_width and polar_width */
bool m_SizesAreLinear = false;
// numner of real(valid and non-monitor) detectors calculated by the alvorithm
size_t m_nDetectors = 0;
// the vectors which represent detector's parameters as linear structure
std::vector<double> azimuthal;
std::vector<double> polar;
std::vector<double> azimuthalWidth;
std::vector<double> polarWidth;
std::vector<double> secondaryFlightpath;
std::vector<size_t> detID;
// calculate generic detectors parameters:
void calcDetPar(const Geometry::IDetector &det, const Kernel::V3D &Observer,
DetParameters &Detector);
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
/// if ASCII file is selected as the datasource, this structure describes the
/// type of this file.
FileTypeDescriptor current_ASCII_file;
/// internal function which sets the output table according to the algorithms
/// properties
void setOutputTable();
/// extract valid detectors parameters into vectors above
void extractAndLinearize(const std::vector<DetParameters> &detPar);
/// functions used to populate data from the phx or par file
void populate_values_from_file(const API::MatrixWorkspace_sptr &inputWS);
/// load data from par or phx file;
size_t loadParFile(const std::string &fileName);
protected: // for testing purposes
/**! function calculates number of colums in an ASCII file, assuming that
* colums are separated by spaces */
int count_changes(const char *const Buf, size_t buf_size);
/**! The function reads line from input stream and puts it into buffer.
* It behaves like std::ifstream getline but the getline reads additional
* symbol from a row in a Unix-formatted file under windows;*/
size_t get_my_line(std::ifstream &in, char *buf, size_t buf_size,
const char DELIM);
/// load file header and identify which file (PHX,PAR or SPE) it belongs to.
/// It also identifies the position of the begining of the data
FileTypeDescriptor get_ASCII_header(std::string const &fileName,
std::ifstream &data_stream);
/// load PAR or PHX file
void load_plain(std::ifstream &stream, std::vector<double> &Data,
FileTypeDescriptor const &FILE_TYPE);
};
/**Small helper class-holder used to precalculate the detectors parameters in
* spherical coordinate system */
class DetParameters {
public:
/// azimuthal detector's angle in spherical coordinate system alighned with
/// the beam
/// polar detector's angle in spherical coordinate system alighned with the
/// beam
double polarAngle;
/// scattering source -- detector' distance
double secondaryFlightPath;
/// linear or angular size of the bounding box encapsulating detector and
/// alighned tangentially to the constant scattering angle circle
double azimWidth, polarWidth;
/// the detector's ID
int64_t detID;
// default detector ID -- -1 means undefined
DetParameters()
: azimutAngle(0.), polarAngle(0.), secondaryFlightPath(0.), azimWidth(0.),
polarWidth(0.), detID(-1) {}
/** helper class-collection to keep together the parameters, which characterize
average composite detector
double m_AzimutSum;
double m_PolarSum;
double m_FlightPathSum;
// if azimuthal and polar sizes expressed in angular or linear units
bool m_useSphericalSizes;
double m_AzimMin, m_PolarMin, m_AzimMax, m_PolarMax;
/// numbr of primary detectors, contributing into this detector
size_t m_nComponents;
AvrgDetector()
: m_AzimutSum(0), m_PolarSum(0), m_FlightPathSum(0), m_AzimBase(0),
m_PolarBase(0), m_useSphericalSizes(false), m_AzimMin(FLT_MAX),
m_PolarMin(FLT_MAX), m_AzimMax(-FLT_MAX), m_PolarMax(-FLT_MAX),
m_nComponents(0) {}
void addDetInfo(const Geometry::IDetector &det, const Kernel::V3D &Observer);
Lamar Moore
committed
void returnAvrgDetPar(DetParameters &avrgDet);
void setUseSpherical(bool shouldWe = true) { m_useSphericalSizes = shouldWe; }
static double nearAngle(const double &baseAngle, const double &anAngle);