1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
# -*- coding: utf-8 -*-
u"""
Reflection from asymmetrically cut crystal
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A monochromatic beam of *E* = 2840 eV is diffracted by a Si111 crystal with
θ\ :sub:`B`\ = 44.132 deg and α = -20.054 deg, which results in *b* = -0.453.
The phase space volume in the beam before and after the crystal is indeed
invariant, whereas the linear and angular sizes have scaled with the ratio
equal to *b* or 1/*b*. The product FWHM(z)×FWHM(z') = 135 nmrad in both cases.
Notice also the deviation of the diffracted beam direction from the exact
departure angle 2θ\ :sub:`B` seen on the exit screen which is put normally to
2θ\ :sub:`B` (i.e. z'=0 at the exact departure at 2θ\ :sub:`B`\ ).
The ray-traced deviation -106 µrad is close to the calculated refractive shift
-105 µrad.
.. imagezoom:: _images/0-zzP-source,alpha=-0.350.png
.. imagezoom:: _images/2-zzP-afterXtal,alpha=-0.350.png
"""
__author__ = "Konstantin Klementiev"
__date__ = "2018/02/17"
import sys
import numpy as np
sys.path.append(r"C:\Ray-tracing")
import xrt.backends.raycing.sources as rsources
import xrt.backends.raycing.screens as rscreens
import xrt.backends.raycing.materials as rmats
import xrt.backends.raycing.oes as roes
import xrt.backends.raycing.run as rrun
import xrt.backends.raycing as raycing
import xrt.plotter as xrtplot
import xrt.runner as xrtrun
Ec = 2840
nrays = 1e6
crystalSi = rmats.CrystalSi(geom="Bragg")
#crystalSi = rmats.CrystalSi(geom="Laue", t=0.1)
alpha = -0.35
if crystalSi.geom.startswith("Laue"):
alpha += np.pi/2
def build_beamline():
beamLine = raycing.BeamLine()
beamLine.source = rsources.GeometricSource(
beamLine, center=[0, 0, 0],
dx=2, dz=1, dxprime=25e-06, dzprime=25e-06,
# distE=r"normal", energies=[Ec, 1],
energies=[Ec],
nrays=nrays)
beamLine.screenSource = rscreens.Screen(beamLine, center=[0, 2000, 0])
bragg = crystalSi.get_Bragg_angle(Ec) - crystalSi.get_dtheta(Ec, alpha)
b = -np.sin(bragg+alpha) / np.sin(bragg-alpha)
print('bragg={0:.3f}deg; alpha={1:.3f}deg, b={2:.3f}'.format(
np.degrees(bragg), np.degrees(alpha), b))
beamLine.bragg = bragg
beamLine.xtal = roes.OE(
bl=beamLine, center=[0, 2000, 0],
material=crystalSi, pitch=bragg+alpha, alpha=alpha)
p = 0
beamLine.screenXtal = rscreens.Screen(
beamLine, center=[0, 2000+p, p*np.tan(2*bragg)],
x=[1, 0, 0], z=[0, -np.sin(2*bragg), np.cos(2*bragg)])
beamLine.dbragg = crystalSi.get_refractive_correction(Ec, alpha=alpha)*1e6
print(u'refractive shift = {0} µrad'.format(beamLine.dbragg))
return beamLine
def run_process(beamLine):
beamSource = beamLine.source.shine()
beamScreenSource = beamLine.screenSource.expose(beamSource)
beamXtalGlobal, beamXtalLocal = beamLine.xtal.reflect(beamSource)
beamScreenXtal = beamLine.screenXtal.expose(beamXtalGlobal)
outDict = {'beamScreenSource': beamScreenSource,
'beamXtalLocal': beamXtalLocal,
'beamScreenXtal': beamScreenXtal}
return outDict
rrun.run_process = run_process
def define_plots(beamLine):
plots = []
plot = xrtplot.XYCPlot(
beam=r"beamScreenSource",
xaxis=xrtplot.XYCAxis(r"x", limits=[-5, 5]),
yaxis=xrtplot.XYCAxis(r"z", limits=[-5, 5]))
plot.saveName = ["0-xz-source.png".format(alpha)]
plots.append(plot)
plot = xrtplot.XYCPlot(
beam=r"beamScreenSource",
aspect='auto',
xaxis=xrtplot.XYCAxis(r"z", "mm", limits=[-5, 5], bins=256, ppb=1),
yaxis=xrtplot.XYCAxis(r"z'", u"µrad", limits=[-55, 55],
bins=256, ppb=1))
plot.saveName = ["0-zzP-source,alpha={0:.3f}.png".format(alpha)]
plotPhaseSpaceBefore = plot
plots.append(plot)
plot = xrtplot.XYCPlot(
beam=r"beamXtalLocal",
xaxis=xrtplot.XYCAxis(r"x", limits=[-5, 5]),
yaxis=xrtplot.XYCAxis(r"y", limits=[-5, 5]))
plot.saveName = ["1-xy-XtalLocal,alpha={0:.3f}.png".format(alpha)]
plots.append(plot)
plot = xrtplot.XYCPlot(
beam=r"beamScreenXtal",
xaxis=xrtplot.XYCAxis(r"x", limits=[-5, 5]),
yaxis=xrtplot.XYCAxis(r"z", limits=[-5, 5]))
plot.saveName = ["2-xz-afterXtal,alpha={0:.3f}.png".format(alpha)]
plots.append(plot)
ac = beamLine.dbragg
plot = xrtplot.XYCPlot(
beam=r"beamScreenXtal",
aspect='auto',
xaxis=xrtplot.XYCAxis(r"z", "mm", limits=[-5, 5], bins=256, ppb=1),
yaxis=xrtplot.XYCAxis(r"z'", u"µrad", limits=[ac-55, ac+55],
bins=256, ppb=1))
plot.saveName = ["2-zzP-afterXtal,alpha={0:.3f}.png".format(alpha)]
plotPhaseSpaceAfter = plot
plots.append(plot)
for plot in plots:
plot.caxis.offset = Ec
plot.caxis.limits = [Ec-1, Ec+1]
plot.xaxis.fwhmFormatStr = '%1.3f'
plot.yaxis.fwhmFormatStr = '%1.3f'
return plots, plotPhaseSpaceBefore, plotPhaseSpaceAfter
def afterScript(plotPhaseSpaceBefore, plotPhaseSpaceAfter, beamLine):
PhaseSpaceVolumeBefore = plotPhaseSpaceBefore.dx * plotPhaseSpaceBefore.dy
PhaseSpaceVolumeAfter = plotPhaseSpaceAfter.dx * plotPhaseSpaceAfter.dy
print(u"2θ = {0:.3f} deg".format(np.degrees(2*beamLine.bragg)))
print("phase space volume before and after = {0:.3f} nm and {1:.3f} nm".
format(PhaseSpaceVolumeBefore, PhaseSpaceVolumeAfter))
def main():
beamLine = build_beamline()
E0 = list(beamLine.source.energies)[0]
beamLine.alignE = E0
plots, plotPhaseSpaceBefore, plotPhaseSpaceAfter = define_plots(beamLine)
xrtrun.run_ray_tracing(
plots=plots, repeats=1, beamLine=beamLine,
afterScript=afterScript,
afterScriptArgs=[plotPhaseSpaceBefore, plotPhaseSpaceAfter, beamLine])
if __name__ == '__main__':
main()
|