Beispiel #1
0
    def test_detector_coord(self):
        """CylindricalDetector.get_detector_coordinates()"""
        det = self.det
        func = det.get_detector_coordinates
        #Invalid parameter errors
        self.assertRaises(ValueError, func, np.zeros( (2,10) ))
        self.assertRaises(ValueError, func, np.zeros(3) )

        beam = column([10.0, 0.0, 0.0])*2*pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(wl, 0.1), "Correct wavelength"

        beam = column([1.0, 0.0, 1.0])*2*pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(h, 0 * np.pi / 4, atol=1e-5), "H is right in the middle of the detector."
        assert np.allclose(v, 0.0), "V is right in the middle of the detector."
        assert np.allclose(distance, 200.0), "Distance is equal to the detector radius."
        assert np.all(hits_it), "... and it hits it."
        
        beam = column([-1.0, 0.0, 1.0])*2*pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(h, +6 * 200 * np.pi / 4), "H is off to the right"
        assert np.allclose(v, 0.0), "V is right in the middle of the detector."
        assert not np.all(hits_it), "... and it misses."

        beam = column([1.0, 0.0, -1.0])*2*pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(h, 2 * 200 * np.pi / 4), "H is off to the left"
        assert np.allclose(v, 0.0), "V is right in the middle of the detector."
        assert not np.all(hits_it), "... and it misses."
Beispiel #2
0
    def test_detector_coord_vertical(self):
        """CylindricalDetector.get_detector_coordinates()"""
        det = self.det

        beam = column([0., 1., 1.])
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(h, -200 * np.pi / 4), "H is on the edge"
        assert np.allclose(v, 200.0), "V is 200 mm above horizontal"
        assert np.allclose(distance,
                           np.sqrt(2 * 200.**2)), "Distance is correct"
        assert np.all(hits_it), "... and it hits it."

        beam = column([0., -1., 1.])
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(h, -200 * np.pi / 4), "H is on the edge"
        assert np.allclose(v, -200.0), "V is 200 mm below horizontal"
        assert np.allclose(distance,
                           np.sqrt(2 * 200.**2)), "Distance is correct"
        assert np.all(hits_it), "... and it hits it."

        beam = column([0., 2., 1.])
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(h, -200 * np.pi / 4), "H is on the edge"
        assert np.allclose(v, 400.0), "V is 400 mm above horizontal"
        assert not np.all(hits_it), "... and it misses."

        beam = column([0., -2., 1.])
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(h, -200 * np.pi / 4), "H is on the edge"
        assert np.allclose(v, -400.0), "V is 400 mm below horizontal"
        assert not np.all(hits_it), "... and it misses."
Beispiel #3
0
    def test_detector_coord_vertical(self):
        """CylindricalDetector.get_detector_coordinates()"""
        det = self.det

        beam = column([0., 1., 1.]) 
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(h, -200 * np.pi / 4), "H is on the edge"
        assert np.allclose(v, 200.0), "V is 200 mm above horizontal"
        assert np.allclose(distance, np.sqrt(2*200.**2)), "Distance is correct"
        assert np.all(hits_it), "... and it hits it."

        beam = column([0., -1., 1.]) 
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(h, -200 * np.pi / 4), "H is on the edge"
        assert np.allclose(v, -200.0), "V is 200 mm below horizontal"
        assert np.allclose(distance, np.sqrt(2*200.**2)), "Distance is correct"
        assert np.all(hits_it), "... and it hits it."

        beam = column([0., 2., 1.]) 
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(h, -200 * np.pi / 4), "H is on the edge"
        assert np.allclose(v, 400.0), "V is 400 mm above horizontal"
        assert not np.all(hits_it), "... and it misses."
        
        beam = column([0., -2., 1.]) 
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(h, -200 * np.pi / 4), "H is on the edge"
        assert np.allclose(v, -400.0), "V is 400 mm below horizontal"
        assert not np.all(hits_it), "... and it misses."
Beispiel #4
0
    def test_calculate_pixel_angles(self):
        """Detector.calculate_pixel_angles() tests."""
        #Smaller size
        self.det.xpixels = 16
        self.det.ypixels = 10
        self.det.calculate_pixel_angles()

        #Check some shapes
        assert self.det.pixels.shape == (3, 10, 16)
        assert self.det.azimuthal_angle.shape == (10, 16)

        #What we expect
        az = np.fromstring("-0.12435499 -0.10791249 -0.0914112  -0.07485985 -0.0582673  -0.04164258 -0.02499479 -0.00833314  0.00833314  0.02499479  0.04164258  0.0582673  0.07485985  0.0914112   0.10791249  0.12435499", sep=" ")
        elev_x = np.fromstring("-0.12340447 -0.123639   -0.1238411  -0.12401028 -0.12414612 -0.12424829 -0.12431655 -0.12435072 -0.12435072 -0.12431655 -0.12424829 -0.12414612 -0.12401028 -0.1238411  -0.123639   -0.12340447", sep=" ")
        elev_y = np.fromstring("-0.12340447 -0.09617384 -0.06879943 -0.04132138 -0.01378076  0.01378076  0.04132138  0.06879943  0.09617384  0.12340447", sep=" ")
        assert np.allclose(az, self.det.azimuthal_angle[0, :]), "Azimuthal angles match."
        assert np.allclose(elev_x, self.det.elevation_angle[0, :]), "elevation angles match along x."
        assert np.allclose(elev_y, self.det.elevation_angle[:, 0]), "elevation angles match along y."
        #All azimuthal angle with same x index match
        for iy in xrange(1, self.det.ypixels):
            assert np.allclose(az, self.det.azimuthal_angle[iy, :]), "Azimuthal angles match in all y values."
        #But there is a difference in elev. angles
        assert np.all( abs(self.det.elevation_angle[:, 0] - self.det.elevation_angle[:, 1]) > 0), "Some small difference in elevation angles as you change x."

        #Corners is set
        assert np.allclose(self.det.corners[0], [ -50.,  -50.,  400.])
        assert np.allclose(self.det.corners[1], [  50.,  -50.,  400.])
        assert np.allclose(self.det.corners[2], [  50.,   50.,  400.])
        assert np.allclose(self.det.corners[3], [ -50.,   50.,  400.])

        assert np.allclose(self.det.base_point, column([0, 0, 400])), "Base point is in the center of the detector.";
        
        #Orientation vectors
        assert np.allclose( self.det.horizontal, column([1, 0, 0]) ), "Horizontal orientation vector is correct."
        assert np.allclose( self.det.vertical, column([0, 1, 0]) ), "Vertical orientation vector is correct."
Beispiel #5
0
    def test_detector_coord(self):
        """CylindricalDetector.get_detector_coordinates()"""
        det = self.det
        func = det.get_detector_coordinates
        #Invalid parameter errors
        self.assertRaises(ValueError, func, np.zeros((2, 10)))
        self.assertRaises(ValueError, func, np.zeros(3))

        beam = column([10.0, 0.0, 0.0]) * 2 * pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(wl, 0.1), "Correct wavelength"

        beam = column([1.0, 0.0, 1.0]) * 2 * pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(
            h, 0 * np.pi / 4,
            atol=1e-5), "H is right in the middle of the detector."
        assert np.allclose(v, 0.0), "V is right in the middle of the detector."
        assert np.allclose(distance,
                           200.0), "Distance is equal to the detector radius."
        assert np.all(hits_it), "... and it hits it."

        beam = column([-1.0, 0.0, 1.0]) * 2 * pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(h, +6 * 200 * np.pi / 4), "H is off to the right"
        assert np.allclose(v, 0.0), "V is right in the middle of the detector."
        assert not np.all(hits_it), "... and it misses."

        beam = column([1.0, 0.0, -1.0]) * 2 * pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(h, 2 * 200 * np.pi / 4), "H is off to the left"
        assert np.allclose(v, 0.0), "V is right in the middle of the detector."
        assert not np.all(hits_it), "... and it misses."
Beispiel #6
0
 def test_calculate_pixel_angles_with_rotation(self):
     """Detector.calculate_pixel_angles() where the detector has a rotation angle."""
     #Smaller size
     self.det.xpixels = 16
     self.det.ypixels = 10
     self.det.rotation = np.deg2rad(45)
     self.det.calculate_pixel_angles()
     assert np.allclose( self.det.horizontal, np.sqrt(2)/2 * column([1, 1, 0]) ), "Orientation vector is correct, rotated 45 deg."
     assert np.allclose( self.det.vertical, np.sqrt(2)/2 * column([-1, 1, 0]) ), "Vertical orientation vector is correct, rotated."
 def test_constructor(self):
     """Reflection->Test the constructor"""
     ref = self.ref
     assert ref.h == 1
     assert ref.k == 2
     assert ref.l == 3
     assert np.all(ref.hkl == column([1,2,3]))
     assert np.allclose(ref.q_vector, column([1.0, 0.5, 1.0/3])), "q-vector was set to %s" % ref.q_vector
     assert isinstance(ref.measurements, list), "Made a list."
     assert len(ref.measurements) == 0, "No items in list."
Beispiel #8
0
    def test_calculate_pixel_angles(self):
        """Detector.calculate_pixel_angles() tests."""
        #Smaller size
        self.det.xpixels = 16
        self.det.ypixels = 10
        self.det.calculate_pixel_angles()

        #Check some shapes
        assert self.det.pixels.shape == (3, 10, 16)
        assert self.det.azimuthal_angle.shape == (10, 16)

        #What we expect
        az = np.fromstring(
            "-0.12435499 -0.10791249 -0.0914112  -0.07485985 -0.0582673  -0.04164258 -0.02499479 -0.00833314  0.00833314  0.02499479  0.04164258  0.0582673  0.07485985  0.0914112   0.10791249  0.12435499",
            sep=" ")
        elev_x = np.fromstring(
            "-0.12340447 -0.123639   -0.1238411  -0.12401028 -0.12414612 -0.12424829 -0.12431655 -0.12435072 -0.12435072 -0.12431655 -0.12424829 -0.12414612 -0.12401028 -0.1238411  -0.123639   -0.12340447",
            sep=" ")
        elev_y = np.fromstring(
            "-0.12340447 -0.09617384 -0.06879943 -0.04132138 -0.01378076  0.01378076  0.04132138  0.06879943  0.09617384  0.12340447",
            sep=" ")
        assert np.allclose(
            az, self.det.azimuthal_angle[0, :]), "Azimuthal angles match."
        assert np.allclose(
            elev_x,
            self.det.elevation_angle[0, :]), "elevation angles match along x."
        assert np.allclose(
            elev_y,
            self.det.elevation_angle[:, 0]), "elevation angles match along y."
        #All azimuthal angle with same x index match
        for iy in xrange(1, self.det.ypixels):
            assert np.allclose(az, self.det.azimuthal_angle[
                iy, :]), "Azimuthal angles match in all y values."
        #But there is a difference in elev. angles
        assert np.all(
            abs(self.det.elevation_angle[:, 0] -
                self.det.elevation_angle[:, 1]) > 0
        ), "Some small difference in elevation angles as you change x."

        #Corners is set
        assert np.allclose(self.det.corners[0], [-50., -50., 400.])
        assert np.allclose(self.det.corners[1], [50., -50., 400.])
        assert np.allclose(self.det.corners[2], [50., 50., 400.])
        assert np.allclose(self.det.corners[3], [-50., 50., 400.])

        assert np.allclose(self.det.base_point, column(
            [0, 0, 400])), "Base point is in the center of the detector."

        #Orientation vectors
        assert np.allclose(self.det.horizontal, column(
            [1, 0, 0])), "Horizontal orientation vector is correct."
        assert np.allclose(self.det.vertical, column(
            [0, 1, 0])), "Vertical orientation vector is correct."
Beispiel #9
0
    def calculate_pixel_angles_using_vectors(self, center, base, up):
        """Calculate the pixels using specified vectors:
        Parameters
            center: position of center in mm
            base: horizontal direction
            up: vertical direction
        """
        #Normalize
        base /= vector_length(base)
        up /= vector_length(up)
        #Save the vectors
        self.base_point = column(center)
        self.horizontal = column(base)
        self.vertical = column(up)
        #Calculate the normal vector
        self.normal = np.cross(self.vertical.flatten(),
                               self.horizontal.flatten())
        self.normal /= vector_length(self.normal)
        self.normal = column(self.normal)
        assert np.allclose(vector_length(self.normal),
                           1.0), "Normal vector is normalized to length 1.0"

        #Now let's make the pixels
        x = np.linspace(-self.width / 2, self.width / 2, self.xpixels)
        y = np.linspace(-self.height / 2, self.height / 2, self.ypixels)
        #Starting x, y, z position
        (px, py) = np.meshgrid(x, y)

        #XY is the horizontal, vertical position
        px = px.flatten()
        py = py.flatten()

        #Multiply by the base vectors and add the center
        pixels = px * self.horizontal + py * self.vertical + self.base_point

        #Save em - for plotting, mostly. Indices go Z, Y, X
        self.pixels = np.reshape(pixels, (3, self.ypixels, self.xpixels))

        #Save the corners
        self.corners = list()
        self.corners.append(self.pixels[:, 0, 0])  #One corner
        self.corners.append(self.pixels[:, 0, -1])  #The end in X
        self.corners.append(self.pixels[:, -1, -1])  #Max x and Y
        self.corners.append(self.pixels[:, -1, 0])  #The end in Y

        #Now, we calculate the azimuth and elevation angle of each pixel.
        x = pixels[0, :]
        y = pixels[1, :]
        z = pixels[2, :]
        self.azimuthal_angle = np.reshape(np.arctan2(x, z),
                                          (self.ypixels, self.xpixels))
        self.elevation_angle = np.reshape(np.arctan(y / np.sqrt(x**2 + z**2)),
                                          (self.ypixels, self.xpixels))
 def test_get_hkl_from_q(self):
     lat = ( 5.0,  10.0,  20.0)
     lat_inverse = (0.2, 0.1, 0.05)
     angles = tuple( np.deg2rad( [90, 90, 90]))
     (a,b,c) = make_reciprocal_lattice(lat, angles)
     rec = vectors_to_matrix(a,b,c)
     hkl = get_hkl_from_q(column([0.2, 0, 0])*2*pi, rec)
     assert np.allclose(vector(hkl), vector([1,0,0])), "get_hkl_from_q (1,0,0)."
     #Sanity check
     for i in xrange(10):
         val = column(np.random.rand(3))
         q = get_q_from_hkl(val, a, b, c)
         hkl = get_hkl_from_q(q, rec)
         assert np.allclose(vector(hkl), vector(val)), "get_hkl_from_q vs get_q_from_hkl for random values."
 def test_scattered_beam(self):
     """cystal_calc module: get_scattered_q_vector() tests."""
     #Easy UB matrix test
     UB = np.identity(3)
     rot_matrix = rotation_matrix(0, 0, 0)
     #Single vector
     hkl = column([1,2,3])
     scattered_q = get_scattered_q_vector(hkl, rot_matrix, UB)
     assert scattered_q.shape==(3,1), "Returns column-wise vector."
     assert np.allclose(scattered_q, column([1.,2.,3.])), "Identity operation."
     #Several vectors
     hkl = column([1,2,3]) + np.arange(0, 10)
     scattered_q = get_scattered_q_vector(hkl, rot_matrix, UB)
     assert scattered_q.shape==(3,10), "Returns column-wise array."
Beispiel #12
0
 def test_calculate_pixel_angles_with_elevation(self):
     """Detector.calculate_pixel_angles() where the detector has an elevation angle."""
     #Smaller size
     self.det.xpixels = 16
     self.det.ypixels = 10
     self.det.elevation_center = np.deg2rad(45)
     self.det.rotation = np.deg2rad(0)
     self.det.calculate_pixel_angles()
     assert np.allclose(self.det.horizontal, column(
         [1, 0, 0])), "Orientation vector is correct, elevation angle."
     assert np.allclose(
         self.det.vertical,
         np.sqrt(2) / 2 * column([0, 1, -1])
     ), "Vertical orientation vector is correct, elevation angle."
Beispiel #13
0
    def calculate_pixel_angles_using_vectors(self, center, base, up):
        """Calculate the pixels using specified vectors:
        Parameters
            center: position of center in mm
            base: horizontal direction
            up: vertical direction
        """
        #Normalize
        base /= vector_length(base)
        up /= vector_length(up)
        #Save the vectors
        self.base_point = column(center)
        self.horizontal = column(base)
        self.vertical = column(up)
        #Calculate the normal vector
        self.normal = np.cross(self.vertical.flatten(), self.horizontal.flatten())
        self.normal /= vector_length(self.normal)
        self.normal = column(self.normal)
        assert np.allclose(vector_length(self.normal), 1.0), "Normal vector is normalized to length 1.0"

        #Now let's make the pixels
        x = np.linspace(-self.width/2, self.width/2, self.xpixels)
        y = np.linspace(-self.height/2, self.height/2, self.ypixels)
        #Starting x, y, z position
        (px, py) = np.meshgrid(x,y)

        #XY is the horizontal, vertical position
        px = px.flatten()
        py = py.flatten()

        #Multiply by the base vectors and add the center
        pixels = px*self.horizontal + py*self.vertical + self.base_point

        #Save em - for plotting, mostly. Indices go Z, Y, X
        self.pixels = np.reshape(pixels, (3, self.ypixels, self.xpixels) )

        #Save the corners
        self.corners = list()
        self.corners.append(self.pixels[:,  0,  0]) #One corner
        self.corners.append(self.pixels[:,  0, -1]) #The end in X
        self.corners.append(self.pixels[:, -1, -1]) #Max x and Y
        self.corners.append(self.pixels[:, -1,  0]) #The end in Y

        #Now, we calculate the azimuth and elevation angle of each pixel.
        x=pixels[0,:]
        y=pixels[1,:]
        z=pixels[2,:]
        self.azimuthal_angle = np.reshape( np.arctan2(x, z), (self.ypixels, self.xpixels) )
        self.elevation_angle = np.reshape( np.arctan(y / np.sqrt(x**2 + z**2)), (self.ypixels, self.xpixels) )
    def test_get_q_from_hkl(self):
        lat = ( 5.0,  10.0,  20.0)
        lat_inverse = (0.2, 0.1, 0.05)
        angles = tuple( np.deg2rad( [90, 90, 90]))
        (a,b,c) = make_reciprocal_lattice(lat, angles)
        q = get_q_from_hkl(column([1., 0, 0]), a, b, c)
        assert np.allclose(vector(q), a), "Simple get_q_from_hkl a."
        q = get_q_from_hkl(column([1., 0, 0]), a, b, c)
        assert np.allclose(vector(q), vector([2*pi/5, 0, 0])), "Simple get_q_from_hkl a, comparing to value."
        q = get_q_from_hkl(column([0, 1., 0]), a, b, c)
        assert np.allclose(vector(q), b), "Simple get_q_from_hkl b."
        q = get_q_from_hkl(column([0, 0, 1.]), a, b, c)
        assert np.allclose(vector(q), c), "Simple get_q_from_hkl c."
        q = get_q_from_hkl(column([1, 2, 3.]), a, b, c)
        assert np.allclose(vector(q), a+2*b+3*c), "get_q_from_hkl (1,2,3)."

        hkl = np.ones( (3, 12) )
        q = get_q_from_hkl(hkl, a, b, c)
        assert q.shape == (3, 12), "get_q_from_hkl correct shape."
def make_lattice_vectors(lattice_lengths, lattice_angles):
    """Generate lattice vectors from lengths and angles.

    Parameters:
        lattice_lengths: tuple. the lattice lengths a,b,c in Angstroms.
        lattice_angles: tuple. the lattice lengths alpha, beta, gamma, in radians.
            alpha = angle between b and c; beta = angle between a and c; gamma = angle between b and c

    Returns:
        a_vec, b_vec, c_vec: 3 column-wise vectors
            If invalid angles are given, c-vector may have a NaN.
        V: volume of the unit cell
    """
    #Get the direct lattice parameters
    (a,b,c) = lattice_lengths
    (alpha, beta, gamma) = lattice_angles

    #Make the G metric matrix (tensor)
#        G =np.array( [ [a*a, a*b*cos(gamma), a*c*cos(beta)],
#                       [a*b*cos(gamma), b*b, b*c*cos(alpha)],
#                       [a*c*cos(beta), b*c*cos(alpha), c*c] ] )
    # V = np.sqrt( np.linalg.det( G ) )

    #Unit cell volume (Fundamentals of Crystallography, Giacovazzo editor, p.64)
    V = a*b*c * np.sqrt(1 - cos(alpha)**2 - cos(beta)**2 - cos(gamma)**2 + 2*cos(alpha)*cos(beta)*cos(gamma))

    #V can be nan if bad parameters are passed in!

    #We take the "a" direction to be parallel with the x axis.
    a_vec = column( [a, 0, 0] )
    #We take the b direction to be roughly towards +y, in the XY plane
    b_vec = column( [b*cos(gamma),  b*sin(gamma), 0] )
    #Finally, the c direction points towards z positive, but is not otherwise constrained
    #  solution from Fundamentals of Crystallography, Giacovazzo editor, p.64, and 68
    cos_alpha_star = (cos(beta)*cos(gamma)-cos(alpha)) / (sin(beta)*sin(gamma))
    c_star = (a*b*sin(gamma)) / V
    c_vec = column( [c*cos(beta), -c*sin(beta)*cos_alpha_star, 1/c_star] )

    return (a_vec, b_vec, c_vec, V)
def getq_python(azimuth, elevation, wl_output, rot_matrix, wl_input=None):
    """Find the q-vector corresponding to the azimuth, elevation and wavelength of the detector pixel.
    Uses only python and numpy code.

    Paramters:
        azimuth, elevation: azimuth, elevation angle of pixel(s). Can be an array, should be only 1-D though.
            Shapes of az and elev need to match.
        wl_output: output (scattered) wavelength considered; can be scalar or array matching az and elev.
        rot_matrix: The rotation matrix to apply to the q in the lab frame (should be the inverse of the goniometer rotation).
        wl_input: input (incident) wavelength; if not specified, defaults to wl_output

    Returns:
        q: q-vector, either a single column or a 3xn array depending on input size.
    """
    #The Ewald sphere has 1/wl radius
    inelastic = True
    if wl_input is None:
        inelastic = False
        wl_input = wl_output

    #The scattered beam emanates from the centre of this spher.
    #Find the intersection of the scattered beam and the sphere, in XYZ
    beam = column(az_elev_direction(azimuth, elevation)) / wl_output

    #And here is the incident beam direction: Along the z-axis, positive
    incident = np.array([0, 0, 1.0]).reshape(3,1) / wl_input

    #The wave vector difference between the two is the q vector
    q = 2*pi * (beam - incident)

    #Now we switch to the coordinate system of the crystal.
    #The scattered beam direction (the detector location) is rotated relative to the crystal
    #   because the sample is rotated.
    #So is the incident beam direction.
    #Therefore, the q-vector measured is simply rotated by the supplied rotation matrix (which has reversed angles)

    if inelastic:
        q_unrotated = q
        q = np.dot(rot_matrix, q_unrotated)
        return (q, q_unrotated)
    else:
        q = np.dot(rot_matrix, q)
        return q
Beispiel #17
0
    def get_pixel_direction(self, horizontal, vertical):
        """Return a 3x1 column vector giving the direction of a pixel
        on the face of the detector.

        Parameters:
            horizontal, vertical: position in mm on the face of the detector.
                0,0 = center of the detector

        Returns:
            3x1 column vector of the beam direction, normalized.
        """
        # Vertical position, relative to 0,0
        y = vertical + self.origin[1] + self.height / 2.
        # Position in the XZ plane
        angle = horizontal / self.radius + self.angle_start + self.width / 2.
        x = np.cos(angle) * self.radius
        z = np.sin(angle) * self.radius
        pixel = column([x, y, z])

        #Normalize
        pixel = pixel / vector_length(pixel)
        return pixel
Beispiel #18
0
    def get_pixel_direction(self, horizontal, vertical):
        """Return a 3x1 column vector giving the direction of a pixel
        on the face of the detector.

        Parameters:
            horizontal, vertical: position in mm on the face of the detector.
                0,0 = center of the detector

        Returns:
            3x1 column vector of the beam direction, normalized.
        """
        # Vertical position, relative to 0,0
        y = vertical + self.origin[1] + self.height/2.
        # Position in the XZ plane
        angle = horizontal / self.radius + self.angle_start + self.width/2.
        x = np.cos(angle) * self.radius
        z = np.sin(angle) * self.radius
        pixel = column([x, y, z])

        #Normalize
        pixel = pixel / vector_length(pixel)
        return pixel
def getq(az, elevation, wl_output, q_rot_matrix, wl_input=None):
    """Find the q-vector corresponding to the azimuth, elevation and wavelength of the detector pixel.
    Optimized for speed by using inline C code. Provides a ~45% time reduction for coverage calculation.

    Paramters:
        az, elevation: azimuth, elevation angle of pixel. Scalar only.
        wl_output: output (scattered) wavelength considered; can be scalar or array matching az and elev.
        q_rot_matrix: The q-rotation matrix; how the q-vector has to be rotated.
            This corresponds to the opposite angles of the sample orientation,
            so (-phi, -chi, -omega).
        wl_input: input (incident) wavelength; if not specified, defaults to wl_output

    Returns:
        q: q-vector, a single column
    """

    support = """
    #include <math.h>
    """
    #Ensure the right data types!
    az = float(az)
    elevation = float(elevation)
    wl_output = float(wl_output)
    rot_matrix = q_rot_matrix
    if wl_input is None:
        # -- elastic ---
        wl_input = wl_output
        q = weave.inline(getq_code, ['wl_input', 'wl_output', 'elevation', 'az', 'pi', 'rot_matrix'],compiler='gcc', support_code = support,libraries = ['m'])
        q = column([q[0],q[1],q[2]])
        return q
    else:
        #--- inelastic ---
        (q_both) =  weave.inline(getq_inelastic_code, ['wl_input', 'wl_output', 'elevation', 'az', 'pi', 'rot_matrix'],compiler='gcc', support_code = support,libraries = ['m'])
        q = np.array(q_both[0:3]).reshape(3,1)
        q_unrot = np.array(q_both[3:]).reshape(3,1)
        return (q, q_unrot)
Beispiel #20
0
    def test_detector_coord(self):
        """FlatDetector.detector_coord()"""
        det = self.det
        func = det.get_detector_coordinates
        #Invalid parameter errors
        self.assertRaises(ValueError, func, np.zeros( (2,10) ))
        self.assertRaises(ValueError, func, np.zeros(3) )

        beam = column([10.0, 0.0, 0.0])*2*pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose( wl, 0.1), "Correct wavelength for one"
        beam = column([10.0, 20.0, 30.0])*2*pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose( wl, 1/np.sqrt(1400)), "Correct wavelength 2"

        beam = np.ones( (3, 15) )*2*pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert h.shape == (15,), "Correct shape of h"
#
        beam = column([0.0, 0.0, 1.0])*2*pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose( wl, 1.0), "Correct wavelength for one"

        beam = column([1.0, 0.0, 0.0])*2*pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.isnan(h), "H and V are nan since the beam is parallel to the detector plane."
        assert not np.any(hits_it), "... and it doesn't hit, of course."

        beam = column([0.0, 1.0, 0.0])*2*pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.isnan(h), "H and V are nan since the beam is parallel to the detector plane."
        assert not np.any(hits_it), "... and it doesn't hit, of course."

        beam = column([0.0, 0.0, 1.0])*2*pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(h, 0.0), "H is right in the middle of the detector."
        assert np.allclose(v, 0.0), "V is right in the middle of the detector."
        assert np.allclose(distance, 400.0), "Distance is equal to the detector face distance."
        assert np.all(hits_it), "... and it hits it."

        beam = column([0.0, 0.05, 1.0])*2*pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(h, 0.0), "H is right in the middle of the detector."
        assert np.all(v > 0.0), "V is above the middle of the detector."
        assert np.all(hits_it), "... and it hits it."
        
        beam = column([0.0, -0.05, 1.0])*2*pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(h, 0.0), "H is right in the middle of the detector."
        assert np.all(v < 0.0), "V is below the middle of the detector."
        assert np.all(hits_it), "... and it hits it."

        beam = column([0.0, 0.13, 1.0])*2*pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(h, 0.0), "H is right in the middle of the detector."
        assert np.all(v > 50.0), "V is above the detector edge."
        assert not np.all(hits_it), "... and it misses it."

        beam = column([0.05, 0.0, 1.0])*2*pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.all(h > 0.0), "h is to the left of the middle of the detector."
        assert np.allclose(v, 0.0), "V is right in the middle of the detector."
        assert np.all(hits_it), "... and it hits it."

        beam = column([0.13, 0.0, 1.0])*2*pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.all(h > 50.0), "H is to the left of the detector edge."
        assert np.allclose(v, 0.0), "V is right in the middle of the detector."
        assert not np.all(hits_it), "... and it misses it."

        beam = column([0.0, 0.0, 0.0])*2*pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.isnan(h), "Scattered beam is 0,0,0."
        assert not np.any(hits_it), "... and it doesn't hit, of course."
        
        #-- opposite direction ---
        beam = column([0.0, 0.0, -1.0])*2*pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.isnan(h), "H misses since the beam points the other way."
        assert np.isnan(v), "H misses since the beam points the other way."
        assert not np.all(hits_it), "Does not hit because the beam is in the opposite direction."

        #--- Wavelength too small ----
        beam = column([0.0, 0.0, 1.0])*2*pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam, wl_min=2.0, wl_max=10.0)
        assert not np.all(hits_it), "Misses detector, wl is too small."

        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam, wl_min=0.1, wl_max=0.5)
        assert not np.all(hits_it), "Misses detector, wl is too large."
Beispiel #21
0
    def test_detector_coord(self):
        """FlatDetector.detector_coord()"""
        det = self.det
        func = det.get_detector_coordinates
        #Invalid parameter errors
        self.assertRaises(ValueError, func, np.zeros((2, 10)))
        self.assertRaises(ValueError, func, np.zeros(3))

        beam = column([10.0, 0.0, 0.0]) * 2 * pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(wl, 0.1), "Correct wavelength for one"
        beam = column([10.0, 20.0, 30.0]) * 2 * pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(wl, 1 / np.sqrt(1400)), "Correct wavelength 2"

        beam = np.ones((3, 15)) * 2 * pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert h.shape == (15, ), "Correct shape of h"
        #
        beam = column([0.0, 0.0, 1.0]) * 2 * pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(wl, 1.0), "Correct wavelength for one"

        beam = column([1.0, 0.0, 0.0]) * 2 * pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.isnan(
            h
        ), "H and V are nan since the beam is parallel to the detector plane."
        assert not np.any(hits_it), "... and it doesn't hit, of course."

        beam = column([0.0, 1.0, 0.0]) * 2 * pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.isnan(
            h
        ), "H and V are nan since the beam is parallel to the detector plane."
        assert not np.any(hits_it), "... and it doesn't hit, of course."

        beam = column([0.0, 0.0, 1.0]) * 2 * pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(h, 0.0), "H is right in the middle of the detector."
        assert np.allclose(v, 0.0), "V is right in the middle of the detector."
        assert np.allclose(
            distance,
            400.0), "Distance is equal to the detector face distance."
        assert np.all(hits_it), "... and it hits it."

        beam = column([0.0, 0.05, 1.0]) * 2 * pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(h, 0.0), "H is right in the middle of the detector."
        assert np.all(v > 0.0), "V is above the middle of the detector."
        assert np.all(hits_it), "... and it hits it."

        beam = column([0.0, -0.05, 1.0]) * 2 * pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(h, 0.0), "H is right in the middle of the detector."
        assert np.all(v < 0.0), "V is below the middle of the detector."
        assert np.all(hits_it), "... and it hits it."

        beam = column([0.0, 0.13, 1.0]) * 2 * pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.allclose(h, 0.0), "H is right in the middle of the detector."
        assert np.all(v > 50.0), "V is above the detector edge."
        assert not np.all(hits_it), "... and it misses it."

        beam = column([0.05, 0.0, 1.0]) * 2 * pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.all(
            h > 0.0), "h is to the left of the middle of the detector."
        assert np.allclose(v, 0.0), "V is right in the middle of the detector."
        assert np.all(hits_it), "... and it hits it."

        beam = column([0.13, 0.0, 1.0]) * 2 * pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.all(h > 50.0), "H is to the left of the detector edge."
        assert np.allclose(v, 0.0), "V is right in the middle of the detector."
        assert not np.all(hits_it), "... and it misses it."

        beam = column([0.0, 0.0, 0.0]) * 2 * pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.isnan(h), "Scattered beam is 0,0,0."
        assert not np.any(hits_it), "... and it doesn't hit, of course."

        #-- opposite direction ---
        beam = column([0.0, 0.0, -1.0]) * 2 * pi
        (h, v, wl, distance, hits_it) = det.get_detector_coordinates(beam)
        assert np.isnan(h), "H misses since the beam points the other way."
        assert np.isnan(v), "H misses since the beam points the other way."
        assert not np.all(
            hits_it
        ), "Does not hit because the beam is in the opposite direction."

        #--- Wavelength too small ----
        beam = column([0.0, 0.0, 1.0]) * 2 * pi
        (h, v, wl, distance,
         hits_it) = det.get_detector_coordinates(beam, wl_min=2.0, wl_max=10.0)
        assert not np.all(hits_it), "Misses detector, wl is too small."

        (h, v, wl, distance,
         hits_it) = det.get_detector_coordinates(beam, wl_min=0.1, wl_max=0.5)
        assert not np.all(hits_it), "Misses detector, wl is too large."
Beispiel #22
0
    def calculate_pixel_angles(self):
        """Given the center angle and other geometry of the detector, calculate the
        azimuth and elevation angle of every pixel."""

        x = np.linspace(-self.width / 2, self.width / 2, self.xpixels)
        y = np.linspace(-self.height / 2, self.height / 2, self.ypixels)
        #Starting x, y, z position
        (px, py) = np.meshgrid(x, y)

        #Start with a Z equal to the given distance
        pz = np.zeros(px.shape) + self.distance

        #Reshape into a nx3 buncha columns, where the columns are the pixels XYZ positions
        num = self.xpixels * self.ypixels
        pixels = np.array([px.flatten(), py.flatten(), pz.flatten()])

        #Ok, first rotate the detector around its center by angle.
        #Since this is rotation around z axis, it is a chi angle
        rot = rotation_matrix(0, self.rotation, 0)

        #Now do the elevation rotation, by rotating around the x axis.
        #   Elevation is positive above the horizontal plane - means the x_rotation angle has to be negative
        rot = np.dot(x_rotation_matrix(-self.elevation_center), rot)

        #Finally add an azimuthal rotation (around the y axis, or phi)
        rot = np.dot(rotation_matrix(self.azimuth_center, 0, 0), rot)

        #Save it for later
        self.pixel_rotation_matrix = rot

        #This applies to the pixels
        pixels = np.dot(rot, pixels)

        #Save em - for plotting, mostly. Indices go Z, Y, X
        self.pixels = np.reshape(pixels, (3, self.ypixels, self.xpixels))

        #Save the corners
        self.corners = list()
        self.corners.append(self.pixels[:, 0, 0])  #One corner
        self.corners.append(self.pixels[:, 0, -1])  #The end in X
        self.corners.append(self.pixels[:, -1, -1])  #Max x and Y
        self.corners.append(self.pixels[:, -1, 0])  #The end in Y

        #This is the base point - the center of the detector
        base_pixel = column([0, 0, self.distance])
        #Do the same rotation as the rest of the pixels
        base_pixel = np.dot(rot, base_pixel)
        self.base_point = column(base_pixel)

        #Horizontal and vertical vector
        self.horizontal = column(self.corners[1] - self.corners[0])
        self.vertical = column(self.corners[3] - self.corners[0])
        #Normalize them
        self.vertical /= vector_length(self.vertical)
        self.horizontal /= vector_length(self.horizontal)

        #Normal vector: take a vector pointing in positive Z, and the do the same rotation as all the pixels.
        self.normal = column(
            np.cross(self.horizontal.flatten(), self.vertical.flatten()))
        assert np.allclose(vector_length(self.normal),
                           1.0), "normal vector is normalized."
        #Another way to calculate the normal. Compare it
        other_normal = np.dot(rot, column([0, 0, 1])).flatten()
        assert np.allclose(
            self.normal.flatten(), other_normal
        ), "Match between two methods of calculating normals. %s vs %s" % (
            self.normal.flatten(), other_normal)

        #Now, we calculate the azimuth and elevation angle of each pixel.
        x = pixels[0, :]
        y = pixels[1, :]
        z = pixels[2, :]

        self.azimuthal_angle = np.reshape(np.arctan2(x, z),
                                          (self.ypixels, self.xpixels))
        self.elevation_angle = np.reshape(np.arctan(y / np.sqrt(x**2 + z**2)),
                                          (self.ypixels, self.xpixels))
 def setUp(self):
     hkl = column([1.0,2,3])
     q_vector = 1.0/hkl
     self.ref = Reflection(hkl, q_vector)
        UB = make_UB_matrix(lat, angles, np.deg2rad(90), np.deg2rad(0), np.deg2rad(0))
        M = np.array([[0,0,0.05], [0,0.1,0], [-0.2,0,0]]) * 2 * pi
        assert np.allclose(M, UB), "UB matrix for orthorombic lattice, phi=+90"
        UB = make_UB_matrix(lat, angles, np.deg2rad(0), np.deg2rad(90), np.deg2rad(0))
        M = np.array([[0,-0.1,0], [0.2,0,0], [0,0,0.05]]) * 2 * pi
        assert np.allclose(M, UB), "UB matrix for orthorombic lattice, chi=+90"

    def test_get_sample_rotation_matrix_to_get_beam(self):
        beam_wanted = column([0,1,0])
        ub_matrix = np.identity(3)
        hkl = column([0,1,1])
        (R, wl) = get_sample_rotation_matrix_to_get_beam(beam_wanted, hkl, ub_matrix)
        assert np.allclose(R, np.array([[1,0,0],[0,0,1],[0,-1,0]])), "get_sample_rotation_matrix, case 1"
#        #Lets give it a starting matrix
#        start_R = rotation_matrix(0,np.pi/4, 0)
#        (R, wl) = get_sample_rotation_matrix_to_get_beam(beam_wanted, hkl, ub_matrix, start_R)
#        assert np.allclose(R, np.array([[1,0,0],[0,0,1],[0,-1,0]])), "get_sample_rotation_matrix, with a starting matrix. We got %s" % R
        

#---------------------------------------------------------------------
if __name__ == "__main__":
    rot_matrix = numpy_utils.rotation_matrix(np.rad2deg(45), np.rad2deg(90), 0)
    print rot_matrix

    start = column([-1,0,0])
    print start
    
    rot = np.dot(rot_matrix, start)
    print rot
    #unittest.main()
Beispiel #25
0
    def calculate_pixel_angles(self):
        """Given the center angle and other geometry of the detector, calculate the
        azimuth and elevation angle of every pixel."""

        x = np.linspace(-self.width/2, self.width/2, self.xpixels)
        y = np.linspace(-self.height/2, self.height/2, self.ypixels)
        #Starting x, y, z position
        (px, py) = np.meshgrid(x,y)

        #Start with a Z equal to the given distance
        pz = np.zeros( px.shape ) + self.distance

        #Reshape into a nx3 buncha columns, where the columns are the pixels XYZ positions
        num = self.xpixels * self.ypixels
        pixels = np.array( [ px.flatten(), py.flatten(), pz.flatten()] )

        #Ok, first rotate the detector around its center by angle.
        #Since this is rotation around z axis, it is a chi angle
        rot = rotation_matrix(0, self.rotation, 0)

        #Now do the elevation rotation, by rotating around the x axis.
        #   Elevation is positive above the horizontal plane - means the x_rotation angle has to be negative
        rot = np.dot(x_rotation_matrix(-self.elevation_center), rot)

        #Finally add an azimuthal rotation (around the y axis, or phi)
        rot = np.dot(rotation_matrix(self.azimuth_center, 0, 0), rot)

        #Save it for later
        self.pixel_rotation_matrix = rot

        #This applies to the pixels
        pixels = np.dot(rot, pixels)

        #Save em - for plotting, mostly. Indices go Z, Y, X
        self.pixels = np.reshape(pixels, (3, self.ypixels, self.xpixels) )

        #Save the corners
        self.corners = list()
        self.corners.append(self.pixels[:,  0,  0]) #One corner
        self.corners.append(self.pixels[:,  0, -1]) #The end in X
        self.corners.append(self.pixels[:, -1, -1]) #Max x and Y
        self.corners.append(self.pixels[:, -1,  0]) #The end in Y

        #This is the base point - the center of the detector
        base_pixel = column([0, 0, self.distance])
        #Do the same rotation as the rest of the pixels
        base_pixel = np.dot(rot, base_pixel)
        self.base_point = column(base_pixel)

        #Horizontal and vertical vector
        self.horizontal = column(self.corners[1] - self.corners[0])
        self.vertical = column(self.corners[3] - self.corners[0])
        #Normalize them
        self.vertical /= vector_length(self.vertical)
        self.horizontal /= vector_length(self.horizontal)

        #Normal vector: take a vector pointing in positive Z, and the do the same rotation as all the pixels.
        self.normal = column(np.cross(self.horizontal.flatten(), self.vertical.flatten() ))
        assert np.allclose(vector_length(self.normal), 1.0), "normal vector is normalized."
        #Another way to calculate the normal. Compare it
        other_normal = np.dot(rot,  column([0,0,1])).flatten()
        assert np.allclose(self.normal.flatten(), other_normal), "Match between two methods of calculating normals. %s vs %s" % (self.normal.flatten(), other_normal)

        #Now, we calculate the azimuth and elevation angle of each pixel.
        x=pixels[0,:]
        y=pixels[1,:]
        z=pixels[2,:]

        self.azimuthal_angle = np.reshape( np.arctan2(x, z), (self.ypixels, self.xpixels) )
        self.elevation_angle = np.reshape( np.arctan(y / np.sqrt(x**2 + z**2)), (self.ypixels, self.xpixels) )
    def test_getq_vs_get_scattered_beam(self):
        "test_getq_vs_get_scattered_beam: getq and get_scattered_beam should give compatible results."
        #Test depends on test_make_UB_matrix() and on test_get_q_from_hkl()
        
        #Make up a simple lattice - cubic
        lat = ( 1.0,  1.0,  1.0)
        angles = tuple( np.deg2rad( [90, 90, 90]))
        UB = make_UB_matrix(lat, angles, 0, 0, 0)
        #No sample rotation
        rot_matrix = np.identity(3)

        #Let's try a non-scattered beam. q=0,0,0
        hkl = column([0.,0.,0.])
        scattered_q = get_scattered_q_vector(hkl, rot_matrix, UB)
        assert np.allclose(scattered_q, [0,0,0]), "Non-scattered q-vector matches hkl 0,0,0"
        beam = get_scattered_beam(hkl, rot_matrix, UB)
        assert np.any(np.isnan(beam)), "Non-scattered beam direction is nan: %s" % beam.flatten()

        #Let's try a back-scattered beam.
        # So its q = 2 * (2*pi* 1/incident_wavelength) in the negative Z
        wl = 1.0 #1 Angstrom wl
        q1 = getq( -pi, 0, wl, rot_matrix)
        #Since the lattice is also 1 Angstrom, the reciprocal lattice is 2pi, so an l = -2
        hkl = column([0.,0.,-2.])
        scattered_q = get_scattered_q_vector(hkl, rot_matrix, UB)
        assert np.allclose(scattered_q, q1), "Back-scattered q-vector matches hkl %s" % hkl.flatten()
        beam = get_scattered_beam(hkl, rot_matrix, UB)
        answer = column([0,0,-1.0]) * (2*pi/wl)
        assert np.allclose(beam, answer), "Back-scattered beam direction is correct: %s" % answer.flatten()

        #Let's try a back-scattered beam at twice the wavelength
        wl = 2.0
        q1 = getq( -pi, 0, wl, rot_matrix)
        #Now a closer l should see it
        hkl = column([0.,0.,-1.])
        scattered_q = get_scattered_q_vector(hkl, rot_matrix, UB)
        assert np.allclose(scattered_q, q1), "Back-scattered q-vector matches hkl %s" % hkl.flatten()
        beam = get_scattered_beam(hkl, rot_matrix, UB)
        answer = column([0,0,-1.0]) * (2*pi/wl)
        assert np.allclose(beam, answer), "Back-scattered beam direction is correct: %s" % answer.flatten()

        #Opposite hkl
        hkl = column([0.,0.,+1.])
        beam = get_scattered_beam(hkl, rot_matrix, UB)
        assert np.any(np.isnan(beam)), "No beam for an hkl of (0,0,1)"

        #Vertical q?
        wl = 1.0
        q1 = getq( 0, np.pi/2, wl, rot_matrix)
        hkl = column([0.,+1.,-1.])
        scattered_q = get_scattered_q_vector(hkl, rot_matrix, UB)
        assert np.allclose(scattered_q, q1), "Vertically-scattered q-vector matches hkl %s" % hkl.flatten()
        beam = get_scattered_beam(hkl, rot_matrix, UB)
        answer = column([0,+1.0,0.0]) * (2*pi/wl)
        assert np.allclose(beam, answer), "Vertically-scattered beam direction is correct: %s" % answer.flatten()

        #Down q
        q1 = getq( 0, -np.pi/2, 1.0, rot_matrix)
        hkl = column([0.,-1.,-1.])
        scattered_q = get_scattered_q_vector(hkl, rot_matrix, UB)
        assert np.allclose(scattered_q, q1), "Vertically-down-scattered q-vector matches hkl %s" % hkl.flatten()
        beam = get_scattered_beam(hkl, rot_matrix, UB)
        answer = column([0,-1.0,0.0]) * (2*pi/wl)
        assert np.allclose(beam, answer), "Vertically-down-scattered beam direction is correct: %s" % answer.flatten()
 def test_get_sample_rotation_matrix_to_get_beam(self):
     beam_wanted = column([0,1,0])
     ub_matrix = np.identity(3)
     hkl = column([0,1,1])
     (R, wl) = get_sample_rotation_matrix_to_get_beam(beam_wanted, hkl, ub_matrix)
     assert np.allclose(R, np.array([[1,0,0],[0,0,1],[0,-1,0]])), "get_sample_rotation_matrix, case 1"