Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
mantidproject
mantid
Commits
e953d1f0
Commit
e953d1f0
authored
Jun 02, 2011
by
Janik Zikovsky
Browse files
Fixes #3129: Peak constructors giving the scattered Q vector instead of the detector.
parent
d68684e8
Changes
3
Hide whitespace changes
Inline
Side-by-side
Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/Peak.h
View file @
e953d1f0
#ifndef MANTID_DATAOBJECTS_PEAK_H_
#define MANTID_DATAOBJECTS_PEAK_H_
#include
"MantidKernel/System.h"
#include
"MantidGeometry/V3D.h"
#include
"MantidGeometry/Math/Matrix.h"
#include
"MantidGeometry/IInstrument.h"
#include
"MantidGeometry/Math/Matrix.h"
#include
"MantidGeometry/V3D.h"
#include
"MantidKernel/PhysicalConstants.h"
#include
"MantidKernel/System.h"
namespace
Mantid
...
...
@@ -24,14 +24,18 @@ namespace DataObjects
/// Allow PeakColumn class to directly access members.
friend
class
PeakColumn
;
Peak
(
Mantid
::
Geometry
::
IInstrument_sptr
m_inst
,
Mantid
::
Geometry
::
V3D
QSampleFrame
,
double
detectorDistance
=
1.0
);
Peak
(
Mantid
::
Geometry
::
IInstrument_sptr
m_inst
,
Mantid
::
Geometry
::
V3D
QSampleFrame
,
Mantid
::
Geometry
::
Matrix
<
double
>
goniometer
,
double
detectorDistance
=
1.0
);
Peak
(
Mantid
::
Geometry
::
IInstrument_sptr
m_inst
,
int
m_DetectorID
,
double
m_Wavelength
);
Peak
(
Mantid
::
Geometry
::
IInstrument_sptr
m_inst
,
int
m_DetectorID
,
double
m_Wavelength
,
Mantid
::
Geometry
::
V3D
HKL
);
Peak
(
Mantid
::
Geometry
::
IInstrument_sptr
m_inst
,
int
m_DetectorID
,
double
m_Wavelength
,
Mantid
::
Geometry
::
V3D
HKL
,
Mantid
::
Geometry
::
Matrix
<
double
>
goniometer
);
Peak
(
Mantid
::
Geometry
::
IInstrument_sptr
m_inst
,
int
m_DetectorID
,
double
m_Wavelength
,
Mantid
::
Geometry
::
V3D
HKL
,
Mantid
::
Geometry
::
Matrix
<
double
>
goniometer
);
// Copy constructor is compiler-provided.
// Peak(const Peak & other);
virtual
~
Peak
();
void
setInstrument
(
Mantid
::
Geometry
::
IInstrument_sptr
inst
);
int
getDetectorID
()
const
;
void
setDetectorID
(
int
m_DetectorID
);
Mantid
::
Geometry
::
IDetector_sptr
getDetector
()
const
;
...
...
@@ -53,6 +57,9 @@ namespace DataObjects
Mantid
::
Geometry
::
V3D
getQLabFrame
()
const
;
Mantid
::
Geometry
::
V3D
getQSampleFrame
()
const
;
void
setQSampleFrame
(
Mantid
::
Geometry
::
V3D
QSampleFrame
,
double
detectorDistance
=
1.0
);
void
setQLabFrame
(
Mantid
::
Geometry
::
V3D
QLabFrame
,
double
detectorDistance
=
1.0
);
void
setWavelength
(
double
wavelength
);
double
getWavelength
()
const
;
double
getDSpacing
()
const
;
...
...
Code/Mantid/Framework/DataObjects/src/Peak.cpp
View file @
e953d1f0
...
...
@@ -12,6 +12,53 @@ namespace DataObjects
{
//----------------------------------------------------------------------------------------------
/** Constructor that uses the Q position of the peak (in the lab frame).
* No detector ID is set.
*
* @param m_inst :: Shared pointer to the instrument for this peak detection
* @param QLabFrame :: Q of the center of the peak, in reciprocal space
* @param detectorDistance :: distance between the sample and the detector.
* Used to give a valid TOF. Default 1.0 meters.
*/
Peak
::
Peak
(
Mantid
::
Geometry
::
IInstrument_sptr
m_inst
,
Mantid
::
Geometry
::
V3D
QLabFrame
,
double
detectorDistance
)
:
m_H
(
0
),
m_K
(
0
),
m_L
(
0
),
m_Intensity
(
0
),
m_SigmaIntensity
(
0
),
m_BinCount
(
0
),
m_GoniometerMatrix
(
3
,
3
,
true
),
m_InverseGoniometerMatrix
(
3
,
3
,
true
),
m_RunNumber
(
0
)
{
this
->
setInstrument
(
m_inst
);
this
->
setQLabFrame
(
QLabFrame
,
detectorDistance
);
}
//----------------------------------------------------------------------------------------------
/** Constructor that uses the Q position of the peak (in the sample frame)
* and a goniometer rotation matrix.
* No detector ID is set.
*
* @param m_inst :: Shared pointer to the instrument for this peak detection
* @param QLabFrame :: Q of the center of the peak, in reciprocal space
* @param goniometer :: a 3x3 rotation matrix
* @param detectorDistance :: distance between the sample and the detector.
* Used to give a valid TOF. Default 1.0 meters.
*/
Peak
::
Peak
(
Mantid
::
Geometry
::
IInstrument_sptr
m_inst
,
Mantid
::
Geometry
::
V3D
QSampleFrame
,
Mantid
::
Geometry
::
Matrix
<
double
>
goniometer
,
double
detectorDistance
)
:
m_H
(
0
),
m_K
(
0
),
m_L
(
0
),
m_Intensity
(
0
),
m_SigmaIntensity
(
0
),
m_BinCount
(
0
),
m_GoniometerMatrix
(
goniometer
),
m_InverseGoniometerMatrix
(
goniometer
),
m_RunNumber
(
0
)
{
if
(
fabs
(
m_InverseGoniometerMatrix
.
Invert
())
<
1e-8
)
throw
std
::
invalid_argument
(
"Goniometer matrix must non-singular."
);
this
->
setInstrument
(
m_inst
);
this
->
setQSampleFrame
(
QSampleFrame
,
detectorDistance
);
}
//----------------------------------------------------------------------------------------------
/** Constructor
*
...
...
@@ -21,13 +68,13 @@ namespace DataObjects
* @return
*/
Peak
::
Peak
(
Mantid
::
Geometry
::
IInstrument_sptr
m_inst
,
int
m_DetectorID
,
double
m_Wavelength
)
:
m_inst
(
m_inst
),
m_H
(
0
),
m_K
(
0
),
m_L
(
0
),
:
m_H
(
0
),
m_K
(
0
),
m_L
(
0
),
m_Intensity
(
0
),
m_SigmaIntensity
(
0
),
m_BinCount
(
0
),
m_GoniometerMatrix
(
3
,
3
,
true
),
m_InverseGoniometerMatrix
(
3
,
3
,
true
),
m_RunNumber
(
0
)
{
this
->
setInstrument
(
m_inst
);
this
->
setDetectorID
(
m_DetectorID
);
this
->
setWavelength
(
m_Wavelength
);
}
...
...
@@ -42,14 +89,14 @@ namespace DataObjects
* @param HKL :: vector with H,K,L position of the peak
* @return
*/
Peak
::
Peak
(
Mantid
::
Geometry
::
IInstrument_sptr
m_inst
,
int
m_DetectorID
,
double
m_Wavelength
,
Mantid
::
Geometry
::
V3D
HKL
)
:
m_inst
(
m_inst
),
m_H
(
HKL
[
0
]),
m_K
(
HKL
[
1
]),
m_L
(
HKL
[
2
]),
Peak
::
Peak
(
Mantid
::
Geometry
::
IInstrument_sptr
m_inst
,
int
m_DetectorID
,
double
m_Wavelength
,
Mantid
::
Geometry
::
V3D
HKL
)
:
m_H
(
HKL
[
0
]),
m_K
(
HKL
[
1
]),
m_L
(
HKL
[
2
]),
m_Intensity
(
0
),
m_SigmaIntensity
(
0
),
m_BinCount
(
0
),
m_GoniometerMatrix
(
3
,
3
,
true
),
m_InverseGoniometerMatrix
(
3
,
3
,
true
),
m_RunNumber
(
0
)
{
this
->
setInstrument
(
m_inst
);
this
->
setDetectorID
(
m_DetectorID
);
this
->
setWavelength
(
m_Wavelength
);
}
...
...
@@ -64,8 +111,7 @@ namespace DataObjects
* @param goniometer :: a 3x3 rotation matrix
* @return
*/
Peak
::
Peak
(
Mantid
::
Geometry
::
IInstrument_sptr
m_inst
,
int
m_DetectorID
,
double
m_Wavelength
,
Mantid
::
Geometry
::
V3D
HKL
,
Mantid
::
Geometry
::
Matrix
<
double
>
goniometer
)
:
m_inst
(
m_inst
),
Peak
::
Peak
(
Mantid
::
Geometry
::
IInstrument_sptr
m_inst
,
int
m_DetectorID
,
double
m_Wavelength
,
Mantid
::
Geometry
::
V3D
HKL
,
Mantid
::
Geometry
::
Matrix
<
double
>
goniometer
)
:
m_H
(
HKL
[
0
]),
m_K
(
HKL
[
1
]),
m_L
(
HKL
[
2
]),
m_Intensity
(
0
),
m_SigmaIntensity
(
0
),
m_BinCount
(
0
),
m_GoniometerMatrix
(
goniometer
),
...
...
@@ -73,6 +119,7 @@ namespace DataObjects
m_RunNumber
(
0
)
{
if
(
fabs
(
m_InverseGoniometerMatrix
.
Invert
())
<
1e-8
)
throw
std
::
invalid_argument
(
"Goniometer matrix must non-singular."
);
this
->
setInstrument
(
m_inst
);
this
->
setDetectorID
(
m_DetectorID
);
this
->
setWavelength
(
m_Wavelength
);
}
...
...
@@ -86,8 +133,10 @@ namespace DataObjects
{
}
//----------------------------------------------------------------------------------------------
/** Set the incident wavelength of the neutron. Calculates the energy from this. Assumes elastic scattering.
/** Set the incident wavelength of the neutron. Calculates the energy from this.
* Assumes elastic scattering.
*
* @param wavelength :: wavelength in Angstroms.
*/
...
...
@@ -102,17 +151,17 @@ namespace DataObjects
m_FinalEnergy
=
m_InitialEnergy
;
}
//----------------------------------------------------------------------------------------------
/** Set the detector ID and look up and cache values related to it.
/** Set the instrument (and save the source/sample pos).
* Call setDetectorID AFTER this call.
*
* @param
m_DetectorID :: ID of detector at the center of the peak
* @param
inst :: Instrument sptr to use
*/
void
Peak
::
set
DetectorID
(
int
m_DetectorID
)
void
Peak
::
set
Instrument
(
Mantid
::
Geometry
::
IInstrument_sptr
inst
)
{
this
->
m_DetectorID
=
m_DetectorID
;
if
(
!
m_inst
)
throw
std
::
runtime_error
(
"No instrument is set!"
);
this
->
m_det
=
m_inst
->
getDetector
(
this
->
m_DetectorID
);
if
(
!
m_det
)
throw
std
::
runtime_error
(
"No detector was found!"
);
m_inst
=
inst
;
if
(
!
inst
)
throw
std
::
runtime_error
(
"No instrument is set!"
);
// Cache some positions
const
Geometry
::
IObjComponent_sptr
sourceObj
=
m_inst
->
getSource
();
...
...
@@ -124,6 +173,20 @@ namespace DataObjects
sourcePos
=
sourceObj
->
getPos
();
samplePos
=
sampleObj
->
getPos
();
}
//----------------------------------------------------------------------------------------------
/** Set the detector ID and look up and cache values related to it.
*
* @param m_DetectorID :: ID of detector at the center of the peak
*/
void
Peak
::
setDetectorID
(
int
m_DetectorID
)
{
this
->
m_DetectorID
=
m_DetectorID
;
if
(
!
m_inst
)
throw
std
::
runtime_error
(
"No instrument is set!"
);
this
->
m_det
=
m_inst
->
getDetector
(
this
->
m_DetectorID
);
if
(
!
m_det
)
throw
std
::
runtime_error
(
"No detector was found!"
);
detPos
=
m_det
->
getPos
();
// We now look for the row/column. -1 if not found.
...
...
@@ -192,7 +255,8 @@ namespace DataObjects
// In general case (2*pi/d)^2=k_i^2+k_f^2-2*k_i*k_f*cos(two_theta)
// E_i,f=k_i,f^2*hbar^2/(2 m)
return
1e10
*
PhysicalConstants
::
h
/
sqrt
(
2.0
*
PhysicalConstants
::
NeutronMass
*
PhysicalConstants
::
meV
)
/
sqrt
(
m_InitialEnergy
+
m_FinalEnergy
-
2.0
*
sqrt
(
m_InitialEnergy
*
m_FinalEnergy
)
*
cos
(
two_theta
));
return
1e10
*
PhysicalConstants
::
h
/
sqrt
(
2.0
*
PhysicalConstants
::
NeutronMass
*
PhysicalConstants
::
meV
)
/
sqrt
(
m_InitialEnergy
+
m_FinalEnergy
-
2.0
*
sqrt
(
m_InitialEnergy
*
m_FinalEnergy
)
*
cos
(
two_theta
));
}
//----------------------------------------------------------------------------------------------
...
...
@@ -237,6 +301,76 @@ namespace DataObjects
return
Qsample
;
}
//----------------------------------------------------------------------------------------------
/** Set the peak using the peak's position in reciprocal space, in the sample frame.
* The GoniometerMatrix will be used to find the Q in the lab frame, so it should
* be set beforehand.
*
* @param QSampleFrame :: Q of the center of the peak, in reciprocal space
* This is in inelastic convention: momentum transfer of the LATTICE!
* Also, q does NOT have a 2pi factor = it is equal to 1/wavelength.
* @param detectorDistance :: distance between the sample and the detector.
* Used to give a valid TOF. Default 1.0 meters.
*/
void
Peak
::
setQSampleFrame
(
Mantid
::
Geometry
::
V3D
QSampleFrame
,
double
detectorDistance
)
{
V3D
Qlab
=
m_GoniometerMatrix
*
QSampleFrame
;
this
->
setQLabFrame
(
Qlab
,
detectorDistance
);
}
//----------------------------------------------------------------------------------------------
/** Set the peak using the peak's position in reciprocal space, in the lab frame.
* The detector position will be determined.
* DetectorID, row and column will be set to -1 since they are not (necessarily) found.
*
* @param QLabFrame :: Q of the center of the peak, in reciprocal space.
* This is in inelastic convention: momentum transfer of the LATTICE!
* Also, q does NOT have a 2pi factor = it is equal to 1/wavelength (in Angstroms).
* @param detectorDistance :: distance between the sample and the detector.
* Used to give a valid TOF. Default 1.0 meters.
*/
void
Peak
::
setQLabFrame
(
Mantid
::
Geometry
::
V3D
QLabFrame
,
double
detectorDistance
)
{
// Clear out the detector = we can't know them
m_DetectorID
=
-
1
;
m_det
=
IDetector_sptr
();
m_Row
=
-
1
;
m_Col
=
-
1
;
m_BankName
=
"None"
;
// The q-vector direction of the peak is = goniometer * ub * hkl_vector
V3D
q
=
QLabFrame
;
/* The incident neutron wavevector is in the +Z direction, ki = 1/wl (in z direction).
* In the inelastic convention, q = ki - kf.
* The final neutron wavector kf = -qx in x; -qy in y; and (-qz+1/wl) in z.
* AND: norm(kf) = norm(ki) = 1.0/wavelength
* THEREFORE: 1/wl = norm(q)^2 / (2*qz)
*/
double
norm_q
=
q
.
norm
();
if
(
norm_q
==
0.0
)
throw
std
::
invalid_argument
(
"Peak::setQLabFrame(): Q cannot be 0,0,0."
);
if
(
q
.
Z
()
==
0.0
)
throw
std
::
invalid_argument
(
"Peak::setQLabFrame(): Q cannot be 0 in the Z (beam) direction."
);
double
one_over_wl
=
(
norm_q
*
norm_q
)
/
(
2.0
*
q
.
Z
());
double
wl
=
1.0
/
one_over_wl
;
// This is the scattered direction, kf = (-qx, -qy, 1/wl-qz)
V3D
beam
=
q
*
-
1.0
;
beam
.
setZ
(
one_over_wl
-
q
.
Z
());
beam
.
normalize
();
// Save the wavelength
this
->
setWavelength
(
wl
);
// Use the given detector distance to find the detector position.
detPos
=
beam
*
detectorDistance
;
}
//----------------------------------------------------------------------------------------------
...
...
Code/Mantid/Framework/DataObjects/test/PeakTest.h
View file @
e953d1f0
...
...
@@ -172,7 +172,6 @@ public:
void
test_getQSampleFrame
()
{
// Peak 3 is phi,chi,omega of 90,0,0; giving this matrix:
Matrix
<
double
>
r2
(
3
,
3
,
false
);
r2
[
0
][
2
]
=
1
;
...
...
@@ -193,6 +192,74 @@ public:
TS_ASSERT_EQUALS
(
qLab
,
qSampleRotated
);
}
//------------------------------------------------------------------------------------
/** Can't have Q = 0,0,0 or 0 in the Z direction when creating */
void
test_setQLabFrame_ThrowsIfQIsNull
()
{
Peak
p1
(
inst
,
10000
,
2.0
);
TS_ASSERT_THROWS_ANYTHING
(
Peak
p2
(
inst
,
V3D
(
0
,
0
,
0
),
1.0
));
TS_ASSERT_THROWS_ANYTHING
(
Peak
p2
(
inst
,
V3D
(
1
,
2
,
0
),
1.0
));
}
/** Compare two peaks, but not the detector IDs etc. */
void
comparePeaks
(
Peak
&
p1
,
Peak
&
p2
)
{
TS_ASSERT_EQUALS
(
p1
.
getQLabFrame
(),
p2
.
getQLabFrame
()
);
TS_ASSERT_EQUALS
(
p1
.
getQSampleFrame
(),
p2
.
getQSampleFrame
()
);
TS_ASSERT_EQUALS
(
p1
.
getDetPos
(),
p2
.
getDetPos
()
);
TS_ASSERT_EQUALS
(
p1
.
getHKL
(),
p2
.
getHKL
()
);
TS_ASSERT_DELTA
(
p1
.
getWavelength
(),
p2
.
getWavelength
(),
1e-5
);
TS_ASSERT_DELTA
(
p1
.
getL1
(),
p2
.
getL1
(),
1e-5
);
TS_ASSERT_DELTA
(
p1
.
getL2
(),
p2
.
getL2
(),
1e-5
);
TS_ASSERT_DELTA
(
p1
.
getTOF
(),
p2
.
getTOF
(),
1e-5
);
TS_ASSERT_DELTA
(
p1
.
getInitialEnergy
(),
p2
.
getInitialEnergy
(),
1e-5
);
TS_ASSERT_DELTA
(
p1
.
getFinalEnergy
(),
p2
.
getFinalEnergy
(),
1e-5
);
TS_ASSERT
(
p1
.
getGoniometerMatrix
().
equals
(
p2
.
getGoniometerMatrix
(),
1e-5
)
);
}
/** Create peaks using Q in the lab frame */
void
test_setQLabFrame
()
{
Peak
p1
(
inst
,
19999
,
2.0
);
V3D
Qlab1
=
p1
.
getQLabFrame
();
V3D
detPos1
=
p1
.
getDetPos
();
// Construct using just Q
Peak
p2
(
inst
,
Qlab1
,
detPos1
.
norm
());
comparePeaks
(
p1
,
p2
);
TS_ASSERT_EQUALS
(
p2
.
getBankName
(),
"None"
);
TS_ASSERT_EQUALS
(
p2
.
getRow
(),
-
1
);
TS_ASSERT_EQUALS
(
p2
.
getCol
(),
-
1
);
TS_ASSERT_EQUALS
(
p2
.
getDetectorID
(),
-
1
);
}
/** Create peaks using Q in sample frame + a goniometer rotation matrix*/
void
test_setQSampleFrame
()
{
// A goniometer rotation matrix
Matrix
<
double
>
r2
(
3
,
3
,
false
);
r2
[
0
][
2
]
=
1
;
r2
[
1
][
1
]
=
1
;
r2
[
2
][
0
]
=
-
1
;
Peak
p1
(
inst
,
19999
,
2.0
,
V3D
(
1
,
2
,
3
),
r2
);
V3D
q
=
p1
.
getQSampleFrame
();
V3D
detPos1
=
p1
.
getDetPos
();
// Construct using Q + rotation matrix
Peak
p2
(
inst
,
q
,
r2
,
detPos1
.
norm
());
p2
.
setHKL
(
V3D
(
1
,
2
,
3
));
// Make sure HKL matches too.
comparePeaks
(
p1
,
p2
);
TS_ASSERT_EQUALS
(
p2
.
getBankName
(),
"None"
);
TS_ASSERT_EQUALS
(
p2
.
getRow
(),
-
1
);
TS_ASSERT_EQUALS
(
p2
.
getCol
(),
-
1
);
TS_ASSERT_EQUALS
(
p2
.
getDetectorID
(),
-
1
);
}
};
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment