Package: xrd-simulator
Simulate X-ray Diffraction from Polycrystals in 3D.TheX-RayDiffractionSIMULATORpackage defines polycrystals as a mesh of tetrahedral single crystals
and simulates diffraction as collected by a 2D discretized detector array while the sample is rocked
around an arbitrary rotation axis.xrd_simulatorwas originally developed with the hope to answer questions about measurement optimization in
scanning x-ray diffraction experiments. However,xrd_simulatorcan simulate a wide range of experimental
diffraction setups. The essential idea is that the sample and beam topology can be arbitrarily specified,
and their interaction simulated as the sample is rocked. This means that standard “non-powder” experiments
such asscanning-3dxrdand full-field3dxrd(or HEDM if you like) can be simulated as well as more advanced
measurement sequences such as helical scans for instance. It is also possible to simulatepowder likescenarios using orientation density functions as input.IntroductionBefore reading all the boring documentation (which is hosted here) let’s dive into some end to end
examples to get us started on a good flavour.Thexrd_simulatoris built around four python objects which reflect a diffraction experiment:Abeamof x-rays (using thexrd_simulator.beammodule)A 2D areadetector(using thexrd_simulator.detectormodule)A 3Dpolycrystalsample (using thexrd_simulator.polycrystalmodule)A rigid body samplemotion(using thexrd_simulator.motionmodule)Once these objects are defined it is possible to let thedetectorcollect scattering of thepolycrystalas the sample undergoes the prescribed rigid bodymotionwhile being illuminated by the xraybeam.Let’s go ahead and build ourselves some x-rays:importnumpyasnpfromxrd_simulator.beamimportBeam# The beam of xrays is represented as a convex polyhedron# We specify the vertices in a numpy array.beam_vertices=np.array([[-1e6,-500.,-500.],[-1e6,500.,-500.],[-1e6,500.,500.],[-1e6,-500.,500.],[1e6,-500.,-500.],[1e6,500.,-500.],[1e6,500.,500.],[1e6,-500.,500.]])beam=Beam(beam_vertices,xray_propagation_direction=np.array([1.,0.,0.]),wavelength=0.28523,polarization_vector=np.array([0.,1.,0.]))We will also need to define a detector:fromxrd_simulator.detectorimportDetector# The detector plane is defined by it's corner coordinates det_corner_0,det_corner_1,det_corner_2detector=Detector(pixel_size_z=75.0,pixel_size_y=55.0,det_corner_0=np.array([142938.3,-38400.,-38400.]),det_corner_1=np.array([142938.3,38400.,-38400.]),det_corner_2=np.array([142938.3,-38400.,38400.]))Next we go ahead and produce a sample, to do this we need to first define a mesh that
describes the topology of the sample, in this example we make the sample shaped as a ball:fromxrd_simulator.meshimportTetraMesh# xrd_simulator supports several ways to generate a mesh, here we# generate meshed solid sphere using a level set.mesh=TetraMesh.generate_mesh_from_levelset(level_set=lambdax:np.linalg.norm(x)-768.0,bounding_radius=769.0,max_cell_circumradius=450.)Every element in the sample is composed of some material, or “phase”, we define the present phases
in a list ofxrd_simulator.phase.Phaseobjects, in this example only a single phase is present:fromxrd_simulator.phaseimportPhasequartz=Phase(unit_cell=[4.926,4.926,5.4189,90.,90.,120.],sgname='P3221',# (Quartz)path_to_cif_file=None# phases can be defined from crystalographic information files)The polycrystal sample can now be created. In this example the crystal elements have random orientations
and the strain is uniformly zero in the sample:fromscipy.spatial.transformimportRotationasRfromxrd_simulator.polycrystalimportPolycrystalorientation=R.random(mesh.number_of_elements).as_matrix()polycrystal=Polycrystal(mesh,orientation,strain=np.zeros((3,3)),phases=quartz,element_phase_map=None)We may save the polycrystal to disc by using the builtinsave()command aspolycrystal.save('my_polycrystal',save_mesh_as_xdmf=True)We can visualize the sample by loading the .xdmf file into your favorite 3D rendering program.
Inparaviewthe sampled colored by one of its Euler angles looks like this:We can now define some motion of the sample over which to integrate the diffraction signal:fromxrd_simulator.motionimportRigidBodyMotionmotion=RigidBodyMotion(rotation_axis=np.array([0,1/np.sqrt(2),-1/np.sqrt(2)]),rotation_angle=np.radians(1.0),translation=np.array([123,-153.3,3.42]))Now that we have an experimental setup we may collect diffraction by letting the beam and detector
interact with the sample:polycrystal.diffract(beam,detector,motion)diffraction_pattern=detector.render(frames_to_render=0,lorentz=False,polarization=False,structure_factor=False,method="project")The resulting rendered detector frame will look something like the below. Note that the positions of the diffraction spots may vary as the crystal orientations were randomly generated!:importmatplotlib.pyplotaspltfig,ax=plt.subplots(1,1)ax.imshow(diffraction_pattern,cmap='gray')plt.show()To compute several frames simply change the motion and collect the diffraction again. The sample may be moved before
each computation using the same or another motion.polycrystal.transform(motion,time=1.0)polycrystal.diffract(beam,detector,motion)Many more options for experimental setups and intensity rendering exist, have fun experimenting!
The above example code can be found as asingle .py file here.InstallationAnaconda installation (Linux and Macos)xrd_simulatoris distributed on theconda-forge channeland the preferred way to install
the xrd_simulator package is viaAnaconda:conda install -c conda-forge xrd_simulator
conda create -n xrd_simulator
conda activate xrd_simulatorThis is meant to work across OS-systems and requires anAnacondainstallation.(The conda-forge feedstock ofxrd_simulatorcan be found here.)Anaconda installation (Windows)To install with anaconda on windows you must make sure that external dependencies ofpygalmeshare preinstalled
on your system. Documentation on installing these packagecan be found elsewhere.Pip InstallationPip installation is possible, however, external dependencies ofpygalmeshmust the be preinstalled
on your system. Installation of these will be OS dependent and documentationcan be found elsewhere.:pip install xrd-simulatorSource installationNaturally one may also install from the sources:git clone https://github.com/FABLE-3DXRD/xrd_simulator.git
cd xrd_simulator
python setup.py installThis will then again require thepygalmeshdependencies to be resolved beforehand.Creditsxrd_simulatormakes good use of xfab and pygalmesh. The source code of these repos can be found here:https://github.com/FABLE-3DXRD/xfabhttps://github.com/nschloe/pygalmesh