Ejemplo n.º 1
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.)
Ejemplo n.º 2
0
 def __init__(self, verbose=False):
     super(LaueForwardSimulation, self).__init__('laue', verbose=verbose)
     self.hkl_planes = []
     self.max_miller = 5
     self.use_energy_limits = False
     self.exp = Experiment()
Ejemplo n.º 3
0
class LaueForwardSimulation(ForwardSimulation):
    """Class to represent a Forward Simulation."""
    def __init__(self, verbose=False):
        super(LaueForwardSimulation, self).__init__('laue', verbose=verbose)
        self.hkl_planes = []
        self.max_miller = 5
        self.use_energy_limits = False
        self.exp = Experiment()

    def set_experiment(self, experiment):
        """Attach an X-ray experiment to this simulation."""
        self.exp = experiment

    def set_use_energy_limits(self, use_energy_limits):
        """Activate or deactivate the use of energy limits."""
        self.use_energy_limits = use_energy_limits

    def set_hkl_planes(self, hkl_planes):
        self.hkl_planes = hkl_planes

    def setup(self, include_grains=None):
        """Setup the forward simulation."""
        pass

    @staticmethod
    def fsim_laue(orientation, hkl_planes, positions, source_position):
        """Simulate Laue diffraction conditions based on a crystal orientation, a set of lattice planes and physical
        positions.

        This function is the work horse of the forward model. It uses a set of HklPlane instances and the voxel
        coordinates to compute the diffraction quantities.

        :param Orientation orientation: the crystal orientation.
        :param list hkl_planes: a list of `HklPlane` instances.
        :param list positions: a list of (x, y, z) positions.
        :param tuple source_position: a (x, y, z) tuple describing the source position.
        """
        n_hkl = len(hkl_planes)
        n_vox = len(positions)
        gt = orientation.orientation_matrix().transpose()

        # here we use list comprehension to avoid for loops
        d_spacings = [hkl.interplanar_spacing()
                      for hkl in hkl_planes]  # size n_hkl
        G_vectors = [hkl.scattering_vector() for hkl in hkl_planes
                     ]  # size n_hkl, with 3 elements items
        Gs_vectors = [gt.dot(Gc)
                      for Gc in G_vectors]  # size n_hkl, with 3 elements items
        Xu_vectors = [
            (pos - source_position) / np.linalg.norm(pos - source_position)
            for pos in positions
        ]  # size n_vox
        thetas = [
            np.arccos(np.dot(Xu, Gs / np.linalg.norm(Gs))) - np.pi / 2
            for Xu in Xu_vectors for Gs in Gs_vectors
        ]  # size n_vox * n_hkl
        the_energies = [
            lambda_nm_to_keV(2 * d_spacings[i_hkl] *
                             np.sin(thetas[i_Xu * n_hkl + i_hkl]))
            for i_Xu in range(n_vox) for i_hkl in range(n_hkl)
        ]  # size n_vox * n_hkl
        X_vectors = [
            np.array(Xu_vectors[i_Xu]) / 1.2398 *
            the_energies[i_Xu * n_hkl + i_hkl] for i_Xu in range(n_vox)
            for i_hkl in range(n_hkl)
        ]  # size n_vox * n_hkl
        K_vectors = [
            X_vectors[i_Xu * n_hkl + i_hkl] + Gs_vectors[i_hkl]
            for i_Xu in range(n_vox) for i_hkl in range(n_hkl)
        ]  # size n_vox * n_hkl
        return Xu_vectors, thetas, the_energies, X_vectors, K_vectors

    def fsim_grain(self, gid=1):
        self.grain = self.exp.get_sample().get_microstructure().get_grain(gid)
        sample = self.exp.get_sample()
        lattice = sample.get_microstructure().get_lattice()
        source = self.exp.get_source()
        detector = self.exp.get_active_detector()
        data = np.zeros_like(detector.data)
        if self.verbose:
            print('Forward Simulation for grain %d' % self.grain.id)
        sample.geo.discretize_geometry(grain_id=self.grain.id)
        # we use either the hkl planes for this grain or the ones defined for the whole simulation
        if hasattr(self.grain,
                   'hkl_planes') and len(self.grain.hkl_planes) > 0:
            print('using hkl from the grain')
            hkl_planes = [
                HklPlane(h, k, l, lattice)
                for (h, k, l) in self.grain.hkl_planes
            ]
        else:
            if len(self.hkl_planes) == 0:
                print(
                    'warning: no reflection defined for this simulation, using all planes with max miller=%d'
                    % self.max_miller)
                self.set_hkl_planes(
                    build_list(lattice=lattice, max_miller=self.max_miller))
            hkl_planes = self.hkl_planes
        n_hkl = len(hkl_planes)
        positions = sample.geo.get_positions(
        )  # size n_vox, with 3 elements items
        n_vox = len(positions)
        Xu_vectors, thetas, the_energies, X_vectors, K_vectors = LaueForwardSimulation.fsim_laue(
            self.grain.orientation, hkl_planes, positions, source.position)
        OR_vectors = [
            detector.project_along_direction(
                origin=positions[i_vox],
                direction=K_vectors[i_vox * n_hkl + i_hkl])
            for i_vox in range(n_vox) for i_hkl in range(n_hkl)
        ]  # size nb_vox * n_hkl
        uv = [detector.lab_to_pixel(OR)[0].astype(np.int) for OR in OR_vectors]
        # now construct a boolean list to select the diffraction spots
        if source.min_energy is None and source.max_energy is None:
            # TODO use the use_energy_limits attribute
            energy_in = [True for k in range(len(the_energies))]
        else:
            energy_in = [
                source.min_energy < the_energies[k] < source.max_energy
                for k in range(len(the_energies))
            ]
        uv_in = [
            0 < uv[k][0] < detector.get_size_px()[0]
            and 0 < uv[k][1] < detector.get_size_px()[1]
            for k in range(len(uv))
        ]  # size n, diffraction located on the detector
        spot_in = [uv_in[k] and energy_in[k] for k in range(len(uv))]
        if self.verbose:
            print('%d diffraction events on the detector among %d' %
                  (sum(spot_in), len(uv)))

        # now sum the counts on the detector individual pixels
        for k in range(len(uv)):
            if spot_in[k]:
                data[uv[k][0], uv[k][1]] += 1
        return data

    def fsim(self):
        """run the forward simulation.

        If the sample has a CAD type of geometry, a single grain (the first from the list) is assumed. In the other
        cases all the grains from the microstructure are used. In particular, if the microstructure has a grain map,
        it can be used to carry out an extended sample simulation.
        """
        full_data = np.zeros_like(self.exp.get_active_detector().data)
        micro = self.exp.get_sample().get_microstructure()
        # for cad geometry we assume only one grain (the first in the list)
        if self.exp.get_sample().geo.geo_type == 'cad':
            full_data += self.fsim_grain(gid=micro.grains[0].id)
        else:
            # in the other cases, we use all the grains defined in the microstructure
            for grain in micro.grains:
                full_data += self.fsim_grain(gid=grain.id)
        return full_data
Ejemplo n.º 4
0
 def setUp(self):
     """testing the experiment module:"""
     self.experiment = Experiment()
     self.experiment.get_sample().set_name('test sample')
     self.experiment.get_source().set_max_energy(120.)
     print(self.experiment.get_sample().geo.geo_type)
Ejemplo n.º 5
0
class ExperimentTests(unittest.TestCase):
    def setUp(self):
        """testing the experiment module:"""
        self.experiment = Experiment()
        self.experiment.get_sample().set_name('test sample')
        self.experiment.get_source().set_max_energy(120.)
        print(self.experiment.get_sample().geo.geo_type)

    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

    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'))
        del self.experiment
        exp = Experiment.load('experiment.txt')
        self.assertTrue(exp.get_source().max_energy == 120.)