Esempio n. 1
0
    def test_gnomonic_projection(self):
        """Testing the gnomonic_projection function on a complete image."""
        # incident beam
        ksi = 0.4  # deg
        Xu = np.array(
            [np.cos(ksi * np.pi / 180), 0.,
             np.sin(ksi * np.pi / 180)])

        # create our detector
        detector = RegArrayDetector2d(size=(919, 728),
                                      u_dir=[0, -1, 0],
                                      v_dir=[0, 0, -1])
        detector.pixel_size = 0.254  # mm binning 2x2
        detector.ucen = 445
        detector.vcen = 380
        detector.ref_pos = np.array([127.8, 0., 0.]) + \
                           (detector.size[0] / 2 - detector.ucen) * detector.u_dir * detector.pixel_size + \
                           (detector.size[1] / 2 - detector.vcen) * detector.v_dir * detector.pixel_size  # mm
        OC = detector.project_along_direction(
            Xu)  # C is the intersection of the direct beam with the detector
        # create test image
        pattern = np.zeros(detector.size, dtype=np.uint8)
        for i in range(self.spots.shape[0]):
            # light corresponding pixels
            pattern[self.spots[i, 0], self.spots[i, 1]] = 255
        detector.data = pattern
        gnom = gnomonic_projection(detector, pixel_size=4, OC=OC)
        import os
        test_dir = os.path.dirname(os.path.realpath(__file__))
        ref_gnom_data = np.load(os.path.join(test_dir, 'ref_gnom_data.npy'))
        self.assertTrue(np.array_equal(gnom.data, ref_gnom_data))
        pass
Esempio n. 2
0
 def test_add_detector(self):
     detector = RegArrayDetector2d(size=(512, 512))
     self.assertEqual(self.experiment.get_number_of_detectors(), 0)
     self.experiment.add_detector(detector)
     self.assertEqual(self.experiment.get_number_of_detectors(), 1)
     self.assertTrue(self.experiment.sample.microstructure.autodelete)
     del self.experiment
Esempio n. 3
0
 def setUp(self):
     """testing the detectors module:"""
     self.detector = RegArrayDetector2d(size=(1024, 512))
     self.detector.pixel_size = 0.1  # mm
     self.detector.ref_pos = np.array([
         100., 0., 0.
     ])  # position in the laboratory frame of the middle of the detector
Esempio n. 4
0
    def test_detector_tilt(self):
        """Verify the tilted coordinate frame """
        for tilt in [1, 5, 10, 15]:
            # Detector tilt alpha/X ; beta/Y ; gamma/Z
            alpha = np.radians(tilt)  # degree to rad, rotate around X axis
            beta = np.radians(tilt)  # degree to rad, rotate around Y axis
            gamma = np.radians(tilt)  # degree to rad, rotate around Z axis

            u1 = np.sin(gamma) * np.cos(beta)
            u2 = -np.cos(gamma) * np.cos(alpha) + np.sin(gamma) * np.sin(
                beta) * np.sin(alpha)
            u3 = -np.cos(gamma) * np.sin(alpha) - np.sin(gamma) * np.sin(
                beta) * np.cos(alpha)

            v1 = -np.sin(beta)
            v2 = np.cos(beta) * np.sin(alpha)
            v3 = -np.cos(beta) * np.cos(alpha)

            det_tilt = RegArrayDetector2d(size=(487, 619),
                                          u_dir=[u1, u2, u3],
                                          v_dir=[v1, v2, v3])

            # compute w using trigonometry
            w1 = np.cos(gamma) * np.cos(beta)
            w2 = np.cos(gamma) * np.sin(beta) * np.sin(alpha) + np.sin(
                gamma) * np.cos(alpha)
            w3 = np.sin(gamma) * np.sin(alpha) - np.cos(gamma) * np.sin(
                beta) * np.cos(alpha)

            self.assertAlmostEqual(w1, det_tilt.w_dir[0], 7)
            self.assertAlmostEqual(w2, det_tilt.w_dir[1], 7)
            self.assertAlmostEqual(w3, det_tilt.w_dir[2], 7)
Esempio n. 5
0
 def test_save(self):
     if os.path.exists('experiment.txt'):
         os.remove('experiment.txt')
     detector1 = RegArrayDetector2d(size=(512, 512))
     detector1.pixel_size = 0.1
     detector1.ref_pos[0] = 100.
     self.experiment.add_detector(detector1)
     # set a second detector above the sample in the horizontal plane
     detector2 = RegArrayDetector2d(size=(512, 512))
     detector2.pixel_size = 0.1
     detector2.set_v_dir([0, -90, 0])
     detector2.ref_pos[2] = 100.
     self.experiment.add_detector(detector2)
     self.experiment.active_detector_id = 0
     self.experiment.save()
     self.assertTrue(os.path.exists('experiment.txt'))
     exp = Experiment.load('experiment.txt')
     self.assertTrue(exp.get_source().max_energy == 120.)
Esempio n. 6
0
def gnomonic_projection(detector, pixel_size=None, OC=None, verbose=False):
    """This function carries out the gnomonic projection of the detector image.
    
    The data must be of uint8 type (between 0 and 255) with diffraction spots equals to 255.
    The function create a new detector instance (think of it as a virtual detector) located at the same position 
    as the given detector and with an inverse pixel size. The gnomonic projection is stored into this new detector data.
    The gnomonic projection of each white pixel (value at 255) is computed. The projection is carried out with respect 
    to the center detector (ucen, vcen) point.
    
    :param RegArrayDetector2d detector: the detector instance with the data from which to compute the projection.
    :param float pixel_size: pixel size to use in the virtual detector for the gnomonic projection.
    :param tuple OC: coordinates of the center of the gnomonic projection in the laboratory frame.
    :param bool verbose: flag to activate verbose mode.
    :returns RegArrayDetector2d gnom: A virtual detector with the gnomonic projection as its data.
    """
    assert detector.data.dtype == np.uint8
    dif = detector.data == 255  # boolean array used to select pixels with diffracted intensity
    dif_indices = np.where(
        dif)  # (ui, vi) tuple with 1D arrays of the coordinates u and v
    n = dif_indices[0].shape
    if verbose:
        print('%d points in the gnomonic projection' % n)
        print('center of the projection: %s' % OC)
    uv_mm = detector.pixel_to_lab(dif_indices[0], dif_indices[1])
    uvg_mm = gnomonic_projection_point(uv_mm, OC)  # mm
    print(uvg_mm.shape)

    # create the new virtual detector
    from pymicro.xray.detectors import RegArrayDetector2d
    gnom = RegArrayDetector2d(size=np.array(detector.size))
    gnom.ref_pos = detector.ref_pos  # same ref position as the actual detector
    if not pixel_size:
        gnom.pixel_size = 1. / detector.pixel_size  # mm
    else:
        gnom.pixel_size = pixel_size  # mm
    # TODO remove the next two lines
    gnom.ucen = detector.ucen
    gnom.vcen = detector.vcen

    # create the gnom.data array (zeros with pixels set to 1 for gnomonic projection points)
    gnom.data = np.zeros(gnom.size, dtype=np.uint8)
    # uvg_px = gnom.lab_to_pixel(uvg_mm)
    uvg_px = np.zeros((uvg_mm.shape[0], 2), dtype=np.int)
    for i in range(uvg_mm.shape[0]):
        uvg_px[i, :] = gnom.lab_to_pixel(uvg_mm[i, :])
    # filter out point outside the virtual detector
    detin = (uvg_px[:, 0] >= 0) & (uvg_px[:, 0] <= gnom.size[0] - 1) & \
            (uvg_px[:, 1] >= 0) & (uvg_px[:, 1] <= gnom.size[1] - 1)
    gnom.data[uvg_px[detin, 0], uvg_px[detin, 1]] = 1
    return gnom
Esempio n. 7
0
 def test_detector_tilt(self):
     """Verify the tilted coordinate frame calculation.
     
     The local frame is calculated by composing 3 rotations and the definition of the detector-to-pixel conversion.
     We have verified that:
     u[0] == np.cos(delta) * np.sin(omega)
     u[1] == -np.cos(kappa) * np.cos(omega) + np.sin(kappa) * np.sin(delta) * np.sin(omega)
     u[2] == -np.sin(kappa) * np.cos(omega) - np.cos(kappa) * np.sin(delta) * np.sin(omega)
     v[0] == -np.sin(delta)
     v[1] == np.sin(kappa) * np.cos(delta)
     v[2] == -np.cos(kappa) * np.cos(delta)
     w[0] == np.cos(omega) * np.cos(delta)
     w[1] == np.cos(omega) * np.sin(delta) * np.sin(kappa) + np.sin(omega) * np.cos(kappa)
     w[2] == np.sin(omega) * np.sin(kappa) - np.cos(omega) * np.sin(delta) * np.cos(kappa)
     
     so the test chack that the matrix composition gives the final result.
     """
     for tilt in [1, 5, 10, 15]:  # degrees
         # Detector tilt kappa/X ; delta/Y ; omega/Z
         det_tilt = RegArrayDetector2d(size=(487, 619),
                                       tilts=(tilt, tilt, tilt))
         kappa, delta, omega = np.radians([tilt, tilt, tilt])
         # compute u, v, w using trigonometry
         u1 = np.cos(delta) * np.sin(omega)
         u2 = -np.cos(kappa) * np.cos(omega) + np.sin(kappa) * np.sin(
             delta) * np.sin(omega)
         u3 = -np.sin(kappa) * np.cos(omega) - np.cos(kappa) * np.sin(
             delta) * np.sin(omega)
         v1 = -np.sin(delta)
         v2 = np.sin(kappa) * np.cos(delta)
         v3 = -np.cos(kappa) * np.cos(delta)
         w1 = np.cos(omega) * np.cos(delta)
         w2 = np.cos(omega) * np.sin(delta) * np.sin(kappa) + np.sin(
             omega) * np.cos(kappa)
         w3 = np.sin(omega) * np.sin(kappa) - np.cos(omega) * np.sin(
             delta) * np.cos(kappa)
         self.assertAlmostEqual(u1, det_tilt.u_dir[0], 7)
         self.assertAlmostEqual(u2, det_tilt.u_dir[1], 7)
         self.assertAlmostEqual(u3, det_tilt.u_dir[2], 7)
         self.assertAlmostEqual(v1, det_tilt.v_dir[0], 7)
         self.assertAlmostEqual(v2, det_tilt.v_dir[1], 7)
         self.assertAlmostEqual(v3, det_tilt.v_dir[2], 7)
         self.assertAlmostEqual(w1, det_tilt.w_dir[0], 7)
         self.assertAlmostEqual(w2, det_tilt.w_dir[1], 7)
         self.assertAlmostEqual(w3, det_tilt.w_dir[2], 7)
Esempio n. 8
0
    def test_gnomonic_projection_point(self):
        """Verify that the gnomonic projection of two diffracted points on a detector give access to the angle 
        between the lattice plane normals."""
        olivine = Lattice.orthorhombic(
            1.022, 0.596, 0.481)  # nm Barret & Massalski convention
        orientation = Orientation.cube()
        p1 = HklPlane(2, 0, -3, olivine)
        p2 = HklPlane(3, -1, -3, olivine)
        detector = RegArrayDetector2d(size=(512, 512),
                                      u_dir=[0, -1, 0],
                                      v_dir=[0, 0, -1])
        detector.pixel_size = 0.200  # mm, 0.1 mm with factor 2 binning
        detector.ucen = 235
        detector.vcen = 297
        detector.ref_pos = np.array([131., 0., 0.]) + \
                           (detector.size[0] / 2 - detector.ucen) * detector.u_dir * detector.pixel_size + \
                           (detector.size[1] / 2 - detector.vcen) * detector.v_dir * detector.pixel_size  # mm

        angle = 180 / np.pi * np.arccos(np.dot(p1.normal(), p2.normal()))
        # test the gnomonic projection for normal and not normal X-ray incidence
        for ksi in [0.0, 1.0]:  # deg
            Xu = np.array(
                [np.cos(ksi * np.pi / 180), 0.,
                 np.sin(ksi * np.pi / 180)])
            OC = detector.project_along_direction(
                Xu
            )  # C is the intersection of the direct beam with the detector
            K1 = diffracted_vector(p1, orientation, Xu=Xu)
            K2 = diffracted_vector(p2, orientation, Xu=Xu)
            R1 = detector.project_along_direction(K1, origin=[0., 0., 0.])
            R2 = detector.project_along_direction(K2, origin=[0., 0., 0.])
            OP1 = gnomonic_projection_point(R1, OC=OC)[0]
            OP2 = gnomonic_projection_point(R2, OC=OC)[0]
            hkl_normal1 = OP1 / np.linalg.norm(OP1)
            hkl_normal2 = (OP2 / np.linalg.norm(OP2))
            # the projection must give the normal to the diffracting plane
            for i in range(3):
                self.assertAlmostEqual(hkl_normal1[i], p1.normal()[i], 6)
                self.assertAlmostEqual(hkl_normal2[i], p2.normal()[i], 6)
            angle_gp = 180 / np.pi * np.arccos(np.dot(hkl_normal1,
                                                      hkl_normal2))
            self.assertAlmostEqual(angle, angle_gp, 6)
Esempio n. 9
0
 def load(file_path='experiment.txt'):
     with open(file_path, 'r') as f:
         dict_exp = json.load(f)
     sample = Sample()
     sample.set_name(dict_exp['Sample']['Name'])
     sample.set_position(dict_exp['Sample']['Position'])
     if 'Geometry' in dict_exp['Sample']:
         sample_geo = ObjectGeometry()
         sample_geo.set_type(dict_exp['Sample']['Geometry']['Type'])
         sample.set_geometry(sample_geo)
     if 'Material' in dict_exp['Sample']:
         a, b, c = dict_exp['Sample']['Material']['Lengths']
         alpha, beta, gamma = dict_exp['Sample']['Material']['Angles']
         centering = dict_exp['Sample']['Material']['Centering']
         symmetry = Symmetry.from_string(
             dict_exp['Sample']['Material']['Symmetry'])
         material = Lattice.from_parameters(a,
                                            b,
                                            c,
                                            alpha,
                                            beta,
                                            gamma,
                                            centering=centering,
                                            symmetry=symmetry)
         sample.set_material(material)
     if 'Microstructure' in dict_exp['Sample']:
         micro = Microstructure(
             dict_exp['Sample']['Microstructure']['Name'])
         for i in range(len(
                 dict_exp['Sample']['Microstructure']['Grains'])):
             dict_grain = dict_exp['Sample']['Microstructure']['Grains'][i]
             grain = Grain(
                 dict_grain['Id'],
                 Orientation.from_euler(
                     dict_grain['Orientation']['Euler Angles (degrees)']))
             grain.position = np.array(dict_grain['Position'])
             grain.volume = dict_grain['Volume']
             micro.grains.append(grain)
         sample.set_microstructure(micro)
     exp = Experiment()
     exp.set_sample(sample)
     source = XraySource()
     source.set_position(dict_exp['Source']['Position'])
     if 'Min Energy (keV)' in dict_exp['Source']:
         source.set_min_energy(dict_exp['Source']['Min Energy (keV)'])
     if 'Max Energy (keV)' in dict_exp['Source']:
         source.set_max_energy(dict_exp['Source']['Max Energy (keV)'])
     exp.set_source(source)
     for i in range(len(dict_exp['Detectors'])):
         dict_det = dict_exp['Detectors'][i]
         if dict_det['Class'] == 'Detector2d':
             det = Detector2d(size=dict_det['Size (pixels)'])
             det.ref_pos = dict_det['Reference Position (mm)']
         if dict_det['Class'] == 'RegArrayDetector2d':
             det = RegArrayDetector2d(size=dict_det['Size (pixels)'])
             det.pixel_size = dict_det['Pixel Size (mm)']
             det.ref_pos = dict_det['Reference Position (mm)']
             if 'Binning' in dict_det:
                 det.set_binning(dict_det['Binning'])
             det.u_dir = np.array(dict_det['u_dir'])
             det.v_dir = np.array(dict_det['v_dir'])
             det.w_dir = np.array(dict_det['w_dir'])
         exp.add_detector(det)
     return exp
Esempio n. 10
0
 def test_add_detector(self):
     detector = RegArrayDetector2d(size=(512, 512))
     self.assertEqual(self.experiment.get_number_of_detectors(), 0)
     self.experiment.add_detector(detector)
     self.assertEqual(self.experiment.get_number_of_detectors(), 1)
Esempio n. 11
0
 def load(file_path='experiment.txt'):
     with open(file_path, 'r') as f:
         dict_exp = json.load(f)
     name = dict_exp['Sample']['Name']
     sample = Sample(name=name)
     sample.data_dir = dict_exp['Sample']['Data Dir']
     sample.set_position(dict_exp['Sample']['Position'])
     if 'Geometry' in dict_exp['Sample']:
         sample_geo = ObjectGeometry()
         sample_geo.set_type(dict_exp['Sample']['Geometry']['Type'])
         sample.set_geometry(sample_geo)
     if 'Material' in dict_exp['Sample']:
         a, b, c = dict_exp['Sample']['Material']['Lengths']
         alpha, beta, gamma = dict_exp['Sample']['Material']['Angles']
         centering = dict_exp['Sample']['Material']['Centering']
         symmetry = Symmetry.from_string(
             dict_exp['Sample']['Material']['Symmetry'])
         material = Lattice.from_parameters(a,
                                            b,
                                            c,
                                            alpha,
                                            beta,
                                            gamma,
                                            centering=centering,
                                            symmetry=symmetry)
         sample.set_material(material)
     if 'Microstructure' in dict_exp['Sample']:
         micro = Microstructure(
             name=dict_exp['Sample']['Microstructure']['Name'],
             file_path=os.path.dirname(file_path))
         # crystal lattice
         if 'Lattice' in dict_exp['Sample']['Microstructure']:
             a, b, c = dict_exp['Sample']['Microstructure']['Lattice'][
                 'Lengths']
             alpha, beta, gamma = dict_exp['Sample']['Microstructure'][
                 'Lattice']['Angles']
             centering = dict_exp['Sample']['Microstructure']['Lattice'][
                 'Centering']
             symmetry = Symmetry.from_string(
                 dict_exp['Sample']['Microstructure']['Lattice']
                 ['Symmetry'])
             lattice = Lattice.from_parameters(a,
                                               b,
                                               c,
                                               alpha,
                                               beta,
                                               gamma,
                                               centering=centering,
                                               symmetry=symmetry)
             micro.set_lattice(lattice)
         grain = micro.grains.row
         for i in range(len(
                 dict_exp['Sample']['Microstructure']['Grains'])):
             dict_grain = dict_exp['Sample']['Microstructure']['Grains'][i]
             grain['idnumber'] = int(dict_grain['Id'])
             euler = dict_grain['Orientation']['Euler Angles (degrees)']
             grain['orientation'] = Orientation.from_euler(euler).rod
             grain['center'] = np.array(dict_grain['Position'])
             grain['volume'] = dict_grain['Volume']
             #                if 'hkl_planes' in dict_grain:
             #                    grain.hkl_planes = dict_grain['hkl_planes']
             grain.append()
         micro.grains.flush()
         sample.set_microstructure(micro)
         sample.microstructure.autodelete = True
     # lazy behaviour, we load only the grain_ids path, the actual array is loaded in memory if needed
     sample.grain_ids_path = dict_exp['Sample']['Grain Ids Path']
     exp = Experiment()
     exp.set_sample(sample)
     source = XraySource()
     source.set_position(dict_exp['Source']['Position'])
     if 'Min Energy (keV)' in dict_exp['Source']:
         source.set_min_energy(dict_exp['Source']['Min Energy (keV)'])
     if 'Max Energy (keV)' in dict_exp['Source']:
         source.set_max_energy(dict_exp['Source']['Max Energy (keV)'])
     exp.set_source(source)
     for i in range(len(dict_exp['Detectors'])):
         dict_det = dict_exp['Detectors'][i]
         if dict_det['Class'] == 'Detector2d':
             det = Detector2d(size=dict_det['Size (pixels)'])
             det.ref_pos = dict_det['Reference Position (mm)']
         if dict_det['Class'] == 'RegArrayDetector2d':
             det = RegArrayDetector2d(size=dict_det['Size (pixels)'])
             det.pixel_size = dict_det['Pixel Size (mm)']
             det.ref_pos = dict_det['Reference Position (mm)']
             if 'Min Energy (keV)' in dict_exp['Detectors']:
                 det.tilt = dict_det['Tilts (deg)']
             if 'Binning' in dict_det:
                 det.set_binning(dict_det['Binning'])
             det.u_dir = np.array(dict_det['u_dir'])
             det.v_dir = np.array(dict_det['v_dir'])
             det.w_dir = np.array(dict_det['w_dir'])
         exp.add_detector(det)
     return exp