Source code for shadow4.beamline.optical_elements.refractors.s4_interface

"""
S4 refractive interface.
"""
import numpy

from syned.beamline.element_coordinates import ElementCoordinates
from syned.beamline.optical_elements.refractors.interface import Interface
from syned.beamline.shape import Rectangle, Ellipse

from dabax.dabax_xraylib import DabaxXraylib

from shadow4.beam.s4_beam import S4Beam
from shadow4.beamline.s4_beamline_element import S4BeamlineElement
from shadow4.beamline.s4_beamline_element_movements import S4BeamlineElementMovements
from shadow4.physical_models.prerefl.prerefl import PreRefl

[docs]class S4Interface(Interface): """ Shadow4 refractive interface class This is a base class for refractors. Use derived classes for Conic or other curved surfaces. Constructor. Parameters ---------- name : str, optional The name of the mirror. boundary_shape : instance of BoundaryShape, optional The boundary shape of the mirror. surface_shape : instance of SurfaceShape, optional The surface shape of the mirror. material_object : str, optional string with material symbol or formula (used when f_r_ind>3). material_image : str, optional string with material symbol or formula (used when f_r_ind>3). density_object : float, optional density for material_object (used when f_r_ind>3). density_image : float, optional density for material_image (used when f_r_ind>3). f_r_ind : int, optional source of optical constants, from constant value or PREREFL preprocessor (file): - (0) constant value in both object and image spaces, - (1) file in object space, constant value in image space, - (2) constant value in object space, file in image space, - (3) file in both object and image space. - (4) xraylib in object space, constant value in image space, - (5) constant value in object space, xraylib in image space, - (6) xraylib in both object and image space. - (7) dabax in object space, constant value in image space, - (8) constant value in object space, dabax in image space, - (9) dabax in both object and image space. r_ind_obj : float or numpy array (for f_r_ind=0,2): index of refraction (real) in object space. r_ind_ima : float or numpy array (for f_r_ind=0,1): index of refraction (real) in image space. r_attenuation_obj : float or numpy array (for f_r_ind=0,2): attenuation coefficient in object space. Units of m^(-1) r_attenuation_ima : float or numpy array (for f_r_ind=0,1): attenuation coefficient in image space. Units of m^(-1) file_r_ind_obj : str, optional (for f_r_ind=1,3): file generated by PREREFL preprocessor. file_r_ind_ima : str, optional (for f_r_ind=2,3): file generated by PREREFL preprocessor. dabax : None or instance of DabaxXraylib, The pointer to the dabax library (used for f_r_ind > 6). Returns ------- instance of S4Interface. """ def __init__(self, name = "Undefined", boundary_shape = None, surface_shape = None, material_object = None, material_image = None, density_object = 1.0, density_image = 1.0, f_r_ind = 0, r_ind_obj = 1.0, r_ind_ima = 1.0, r_attenuation_obj = 0.0, r_attenuation_ima = 0.0, file_r_ind_obj = "", file_r_ind_ima = "", dabax = None, ): Interface.__init__(self, name=name, surface_shape=surface_shape, boundary_shape=boundary_shape, material_object=material_object, material_image=material_image, ) self._f_r_ind = f_r_ind self._r_ind_obj = r_ind_obj self._r_ind_ima = r_ind_ima self._r_attenuation_obj = r_attenuation_obj self._r_attenuation_ima = r_attenuation_ima self._file_r_ind_obj = file_r_ind_obj self._file_r_ind_ima = file_r_ind_ima self._density_object = density_object self._density_image = density_image self._dabax = dabax
[docs] def get_info(self): """ Returns the specific information of the S4 refractive interface optical element. Returns ------- str """ txt = "\n\n" txt += "REFRACTOR (INTERFACE)\n" txt += "\n" "Source of material refraction indices:\n" if self._f_r_ind == 0: txt += " constant value in both object and image spaces\n" txt += " index of refraction in object space: %f \n" % self._r_ind_obj txt += " attenuation coeff in object space: %f \n" % self._r_attenuation_obj txt += " index of refraction in image space: %f \n" % self._r_ind_ima txt += " attenuation coeff in image space: %f \n" % self._r_attenuation_ima elif self._f_r_ind == 1: txt += " file in object space, constant value in image space\n" txt += " file generated by prerefl for object space: %s \n" % self._file_r_ind_obj txt += " index of refraction in image space: %f \n" % self._r_ind_ima txt += " attenuation coeff in image space: %f \n" % self._r_attenuation_ima elif self._f_r_ind == 2: txt += " constant value in object space, file in image space\n" txt += " index of refraction in object space: %f \n" % self._r_ind_obj txt += " attenuation coeff in object space: %f \n" % self._r_attenuation_obj txt += " file generated by prerefl for image space: %s \n" % self._file_r_ind_ima elif self._f_r_ind == 3: txt += " file in both object and image space\n" txt += " file generated by prerefl for object space: %s \n" % self._file_r_ind_obj txt += " file generated by prerefl for image space: %s \n" % self._file_r_ind_ima elif self._f_r_ind == 4: txt += " xraylib in object space, constant value in image space\n" txt += " index of refraction in image space: %f \n" % self._r_ind_ima txt += " attenuation coeff in image space: %f \n" % self._r_attenuation_ima elif self._f_r_ind == 5: txt += " constant value in object space, xraylib in image space\n" txt += " index of refraction in object space: %f \n" % self._r_ind_obj txt += " attenuation coeff in object space: %f \n" % self._r_attenuation_obj elif self._f_r_ind == 6: txt += " xraylib in both object and image space\n" elif self._f_r_ind == 7: txt += " dabax in object space, constant value in image space\n" txt += " index of refraction in image space: %f \n" % self._r_ind_ima txt += " attenuation coeff in image space: %f \n" % self._r_attenuation_ima elif self._f_r_ind == 8: txt += " constant value in object space, dabax in image space\n" txt += " index of refraction in object space: %f \n" % self._r_ind_obj txt += " attenuation coeff in object space: %f \n" % self._r_attenuation_obj elif self._f_r_ind == 9: txt += " dabax in both object and image space\n" txt += "\n" ss = self.get_surface_shape() if ss is None: txt += "Surface shape is: Plane (** UNDEFINED?? **)\n" else: txt += "Surface shape is: %s\n" % ss.__class__.__name__ txt += "\nParameters:\n %s\n" % ss.info() txt += self.get_optical_surface_instance().info() + "\n" boundary = self.get_boundary_shape() if boundary is None: txt += "Surface boundaries not considered (infinite)" else: txt += "Surface boundaries are: %s\n" % boundary.__class__.__name__ txt += " Limits: " + repr( boundary.get_boundaries()) + "\n" txt += boundary.info() return txt
[docs] def apply_interface_refraction(self, **kwargs): raise Exception("To be implemented in the children class")
[docs] def to_python_code(self, **kwargs): """ Creates the python code for defining the element. Parameters ---------- **kwargs Returns ------- str Python code. """ raise Exception("To be implemented in the children class")
[docs] def to_python_code_boundary_shape(self): """ Creates a code block with information of boundary shape. Returns ------- str The text with the code. """ txt = "" # "\nfrom shadow4.beamline.optical_elements.mirrors.s4_plane_mirror import S4PlaneMirror" bs = self._boundary_shape if bs is None: txt += "\nboundary_shape = None" elif isinstance(bs, Rectangle): txt += "\nfrom syned.beamline.shape import Rectangle" txt += "\nboundary_shape = Rectangle(x_left=%g, x_right=%g, y_bottom=%g, y_top=%g)" % bs.get_boundaries() elif isinstance(bs, Ellipse): txt += "\nfrom syned.beamline.shape import Ellipse" txt += "\nboundary_shape = Ellipse(a_axis_min=%g, a_axis_max=%g, b_axis_min=%g, b_axis_max=%g)" % bs.get_boundaries() return txt
[docs] def get_refraction_indices(self, photon_energy_eV=None): """ Calculates the real part refraction indices for a given energy or energy array from the input data. Parameters ---------- photon_energy_eV : float or numpy array, optional The photon energy in eV. Returns ------- tuple (refraction_index_object, refraction_index_image) with the real part of the refraction indices. """ # f_r_ind = 2, # source of optical constants, from constant value or PREREFL preprocessor (file): # (0) constant value in both object and image spaces # (1) file in object space, constant value in image space # (2) constant value in object space, file in image space # (3) file in both object and image space # r_ind_obj = 1.0, # (for f_r_ind=0,2): index of refraction in object space. # r_ind_ima = 1.0, # (for f_r_ind=0,1): index of refraction in image space. # r_attenuation_obj = 0.0, # (for f_r_ind=0,2): attenuation coefficient in object space. Units of UserUnitLength^(-1) # r_attenuation_ima = 0.0, # (for f_r_ind=0,1): attenuation coefficient in image space. Units of UserUnitLength^(-1) # file_r_ind_obj = "", # (for f_r_ind=1,3): file generated by PREREFL # file_r_ind_ima = "/nobackup/gurb1/srio/Oasys/Be.dat", # (for f_r_ind=2,3): file generated by PREREFL if self._f_r_ind == 0: refraction_index_object = self._r_ind_obj refraction_index_image = self._r_ind_ima elif self._f_r_ind == 1: preprefl1 = PreRefl() preprefl1.read_preprocessor_file(self._file_r_ind_obj) refraction_index_object = (preprefl1.get_refraction_index(photon_energy_eV)).real refraction_index_image = self._r_ind_ima * numpy.ones_like(refraction_index_object) elif self._f_r_ind == 2: preprefl2 = PreRefl() preprefl2.read_preprocessor_file(self._file_r_ind_ima) refraction_index_image = (preprefl2.get_refraction_index(photon_energy_eV)).real refraction_index_object = self._r_ind_obj * numpy.ones_like(refraction_index_image) elif self._f_r_ind == 3: preprefl1 = PreRefl() preprefl2 = PreRefl() preprefl1.read_preprocessor_file(self._file_r_ind_obj) preprefl2.read_preprocessor_file(self._file_r_ind_ima) refraction_index_object = (preprefl1.get_refraction_index(photon_energy_eV)).real refraction_index_image = (preprefl2.get_refraction_index(photon_energy_eV)).real elif self._f_r_ind == 4: refraction_index_object = PreRefl.get_refraction_index_real_external_xraylib(material=self.get_material_object(), photon_energy_ev=photon_energy_eV, density=self._density_object) refraction_index_image = self._r_ind_ima * numpy.ones_like(refraction_index_object) elif self._f_r_ind == 5: refraction_index_image = PreRefl.get_refraction_index_real_external_xraylib(material=self.get_material_image(), photon_energy_ev=photon_energy_eV, density=self._density_image) refraction_index_object = self._r_ind_obj * numpy.ones_like(refraction_index_image) elif self._f_r_ind == 6: refraction_index_object = PreRefl.get_refraction_index_real_external_xraylib(material=self.get_material_object(), photon_energy_ev=photon_energy_eV, density=self._density_object) refraction_index_image = PreRefl.get_refraction_index_real_external_xraylib(material=self.get_material_image(), photon_energy_ev=photon_energy_eV, density=self._density_image) elif self._f_r_ind == 7: refraction_index_object = PreRefl.get_refraction_index_real_external_dabax(material=self.get_material_object(), photon_energy_ev=photon_energy_eV, density=self._density_object, dabax=self._dabax) refraction_index_image = self._r_ind_ima * numpy.ones_like(refraction_index_object) elif self._f_r_ind == 8: refraction_index_image = PreRefl.get_refraction_index_real_external_dabax(material=self.get_material_image(), photon_energy_ev=photon_energy_eV, density=self._density_image, dabax=self._dabax) refraction_index_object = self._r_ind_obj * numpy.ones_like(refraction_index_image) elif self._f_r_ind == 9: refraction_index_object = PreRefl.get_refraction_index_real_external_dabax(material=self.get_material_object(), photon_energy_ev=photon_energy_eV, density=self._density_object, dabax=self._dabax) refraction_index_image = PreRefl.get_refraction_index_real_external_dabax(material=self.get_material_image(), photon_energy_ev=photon_energy_eV, density=self._density_image, dabax=self._dabax) return refraction_index_object, refraction_index_image
[docs] def get_attenuation_coefficients(self, photon_energy_eV=None): """ Calculates the attenuation coefficients for a given energy or energy array from the input data. Parameters ---------- photon_energy_eV : float or numpy array, optional The photon energy in eV. Returns ------- tuple (attenuation_coefficient_object, attenuation_coefficient_image) with the real part of the refraction indices. """ # f_r_ind = 2, # source of optical constants, from constant value or PREREFL preprocessor (file): # (0) constant value in both object and image spaces # (1) file in object space, constant value in image space # (2) constant value in object space, file in image space # (3) file in both object and image space # r_ind_obj = 1.0, # (for f_r_ind=0,2): index of refraction in object space. # r_ind_ima = 1.0, # (for f_r_ind=0,1): index of refraction in image space. # r_attenuation_obj = 0.0, # (for f_r_ind=0,2): attenuation coefficient in object space. Units of UserUnitLength^(-1) # r_attenuation_ima = 0.0, # (for f_r_ind=0,1): attenuation coefficient in image space. Units of UserUnitLength^(-1) # file_r_ind_obj = "", # (for f_r_ind=1,3): file generated by PREREFL # file_r_ind_ima = "/nobackup/gurb1/srio/Oasys/Be.dat", # (for f_r_ind=2,3): file generated by PREREFL if self._f_r_ind == 0: attenuation_coefficient_object = self._r_attenuation_obj # already in m^-1 attenuation_coefficient_image = self._r_attenuation_ima elif self._f_r_ind == 1: preprefl1 = PreRefl() preprefl1.read_preprocessor_file(self._file_r_ind_obj) attenuation_coefficient_object = (preprefl1.get_attenuation_coefficient(photon_energy_eV)) * 100 # in m^-1 attenuation_coefficient_image = self._r_attenuation_ima * numpy.ones_like(attenuation_coefficient_object) elif self._f_r_ind == 2: preprefl2 = PreRefl() preprefl2.read_preprocessor_file(self._file_r_ind_ima) attenuation_coefficient_image = (preprefl2.get_attenuation_coefficient(photon_energy_eV)) * 100 attenuation_coefficient_object = self._r_attenuation_obj * numpy.ones_like(attenuation_coefficient_image) elif self._f_r_ind == 3: preprefl1 = PreRefl() preprefl2 = PreRefl() preprefl1.read_preprocessor_file(self._file_r_ind_obj) preprefl2.read_preprocessor_file(self._file_r_ind_ima) attenuation_coefficient_object = (preprefl1.get_attenuation_coefficient(photon_energy_eV)) * 100 attenuation_coefficient_image = (preprefl2.get_attenuation_coefficient(photon_energy_eV)) * 100 elif self._f_r_ind == 4: attenuation_coefficient_object = PreRefl.get_attenuation_coefficient_external_xraylib( photon_energy_ev=photon_energy_eV, material=self.get_material_object(), density=self._density_object) * 100 # in m^-1 attenuation_coefficient_image = self._r_attenuation_ima * numpy.ones_like(attenuation_coefficient_object) elif self._f_r_ind == 5: attenuation_coefficient_image = PreRefl.get_attenuation_coefficient_external_xraylib( photon_energy_ev=photon_energy_eV, material=self.get_material_image(), density=self._density_image) * 100 # in m^-1 attenuation_coefficient_object = self._r_attenuation_obj * numpy.ones_like(attenuation_coefficient_image) elif self._f_r_ind == 6: attenuation_coefficient_object = PreRefl.get_attenuation_coefficient_external_xraylib( photon_energy_ev=photon_energy_eV, material=self.get_material_object(), density=self._density_object) * 100 # in m^-1 attenuation_coefficient_image = PreRefl.get_attenuation_coefficient_external_xraylib( photon_energy_ev=photon_energy_eV, material=self.get_material_image(), density=self._density_image) * 100 # in m^-1 elif self._f_r_ind == 7: attenuation_coefficient_object = PreRefl.get_attenuation_coefficient_external_dabax( photon_energy_ev=photon_energy_eV, material=self.get_material_object(), density=self._density_object, dabax=self._dabax) * 100 # in m^-1 attenuation_coefficient_image = self._r_attenuation_ima * numpy.ones_like(attenuation_coefficient_object) elif self._f_r_ind == 8: attenuation_coefficient_image = PreRefl.get_attenuation_coefficient_external_dabax( photon_energy_ev=photon_energy_eV, material=self.get_material_image(), density=self._density_image, dabax=self._dabax) * 100 # in m^-1 attenuation_coefficient_object = self._r_attenuation_obj * numpy.ones_like(attenuation_coefficient_image) elif self._f_r_ind == 9: attenuation_coefficient_object = PreRefl.get_attenuation_coefficient_external_dabax( photon_energy_ev=photon_energy_eV, material=self.get_material_object(), density=self._density_object, dabax=self._dabax) * 100 # in m^-1 attenuation_coefficient_image = PreRefl.get_attenuation_coefficient_external_dabax( photon_energy_ev=photon_energy_eV, material=self.get_material_image(), density=self._density_image, dabax=self._dabax) * 100 # in m^-1 return attenuation_coefficient_object, attenuation_coefficient_image
def _apply_interface_refraction(self, beam, refraction_index_object, refraction_index_image, mu_object, apply_attenuation=1): sur = self.get_optical_surface_instance() footprint, normal = sur.apply_refraction_on_beam(beam, refraction_index_object, refraction_index_image, apply_attenuation=apply_attenuation, linear_attenuation_coefficient=mu_object) return footprint, normal def _get_dabax_txt(self): if self._f_r_ind > 6: if isinstance(self._dabax, DabaxXraylib): dabax_txt = 'DabaxXraylib(file_f1f2="%s", file_CrossSec="%s")' % (self._dabax.get_file_f1f2(), self._dabax.get_file_CrossSec()) else: dabax_txt = "DabaxXraylib()" else: dabax_txt = "None" return dabax_txt
[docs]class S4InterfaceElement(S4BeamlineElement): """ Constructor. Parameters ---------- optical_element : instance of OpticalElement, optional The syned optical element. coordinates : instance of ElementCoordinates, optional The syned element coordinates. movements : instance of S4BeamlineElementMovements, optional The S4 element movements. input_beam : instance of S4Beam, optional The S4 incident beam. Returns ------- instance of S4InterfaceElement. """ def __init__(self, optical_element : S4Interface = None, coordinates : ElementCoordinates = None, movements: S4BeamlineElementMovements = None, input_beam : S4Beam = None): super().__init__(optical_element=optical_element if optical_element is not None else S4Interface(), coordinates=coordinates if coordinates is not None else ElementCoordinates(), movements=movements, input_beam=input_beam) self.__stored_optical_constants = None
[docs] def get_stored_optical_constants(self): """ When running trace_beam() the optical constants (refraction index and attenuation coefficients for media 1 and 2) are calculated. They are stored for accelerating further calls. This method permits to retrieve the stored optical constants. Returns ------- tuple (n1, mu1m n2, mu2) n1, n2: arrays with real part of the refraction indices for the object and image media, respectively. mu1, mu2: arrays with attenuation coefficient in m^(-1) for the object and image media, respectively. """ return self.__stored_optical_constants
[docs] def trace_beam(self, **params): """ Runs (ray tracing) the input beam through the element. Parameters ---------- **params Returns ------- tuple (output_beam, footprint) instances of S4Beam. """ flag_lost_value = params.get("flag_lost_value", -1) reused_stored_optical_constants = params.get("reused_stored_optical_constants", None) p = self.get_coordinates().p() q = self.get_coordinates().q() theta_grazing1 = numpy.pi / 2 - self.get_coordinates().angle_radial() theta_grazing2 = numpy.pi / 2 - self.get_coordinates().angle_radial_out() alpha1 = self.get_coordinates().angle_azimuthal() # input_beam = self.get_input_beam().duplicate() soe = self.get_optical_element() # retrieve and store optical constants if reused_stored_optical_constants is not None: n1, mu1, n2, mu2 = reused_stored_optical_constants else: energy1 = input_beam.get_photon_energy_eV() n1, n2 = soe.get_refraction_indices(energy1) mu1, mu2 = soe.get_attenuation_coefficients(energy1) # in m^-1 self.__stored_optical_constants = (n1, mu1, n2, mu2) # # put beam in mirror reference system # input_beam.rotate(alpha1, axis=2) input_beam.rotate(theta_grazing1, axis=1) input_beam.translation([0.0, -p * numpy.cos(theta_grazing1), p * numpy.sin(theta_grazing1)]) # mirror movement: movements = self.get_movements() if movements is not None: if movements.f_move: input_beam.rot_for(OFFX=movements.offset_x, OFFY=movements.offset_y, OFFZ=movements.offset_z, X_ROT=movements.rotation_x, Y_ROT=movements.rotation_y, Z_ROT=movements.rotation_z) # # refract beam in the mirror surface # # TODO (maybe): no check for total reflection is done... # TODO (maybe): implement correctly in shadow4 via Fresnel equations for the transmitted beam footprint, normal = soe._apply_interface_refraction(input_beam, n1, n2, mu1, apply_attenuation=1) # # apply mirror boundaries # footprint.apply_boundaries_syned(soe.get_boundary_shape(), flag_lost_value=flag_lost_value) # # from element reference system to image plane # output_beam = footprint.duplicate() output_beam.change_to_image_reference_system(theta_grazing2, q, refraction_index=n2, apply_attenuation=1, linear_attenuation_coefficient=mu2) return output_beam, footprint
if __name__ == "__main__": i = S4Interface() print(i.info()) print(i.get_surface_shape()) e = S4InterfaceElement(optical_element=i) # print(i.to_python_code())