Beispiel #1
0
    def _validate_sample_inclusion(self, sample, options, erracc):
        self._validate_sample(sample, options, erracc)

        # Substrate material
        substrate_material = apply_lazy(sample.substrate_material, sample,
                                        options)

        if substrate_material is VACUUM:
            exc = ValueError("Substrate material cannot be VACUUM.")
            erracc.add_exception(exc)

        self._validate_material(substrate_material, options, erracc)

        # Inclusion material
        inclusion_material = apply_lazy(sample.inclusion_material, sample,
                                        options)

        if inclusion_material is VACUUM:
            exc = ValueError("Substrate material cannot be VACUUM.")
            erracc.add_exception(exc)

        self._validate_material(inclusion_material, options, erracc)

        # Inclusion diameter
        inclusion_diameter_m = apply_lazy(sample.inclusion_diameter_m, sample,
                                          options)

        if inclusion_diameter_m <= 0:
            exc = ValueError(
                "Diameter ({0:g} m) must be greater than 0.".format(
                    inclusion_diameter_m))
            erracc.add_exception(exc)
Beispiel #2
0
    def _export_sample_horizontallayers(self, sample, options, erracc, simdata, simops):
        self._validate_sample_horizontallayers(sample, options, erracc)

        regionops = simdata.getRegionOptions()
        layers = apply_lazy(sample.layers, sample, options)
        zpositions_m = sample.layers_zpositions_m

        for i, (layer, zposition_m) in enumerate(zip(layers, zpositions_m)):
            region = regionops.getRegion(i)
            self._export_material(layer.material, options, erracc, region)

            zmin_m, zmax_m = zposition_m
            parameters = [abs(zmax_m) * 1e9, abs(zmin_m) * 1e9, 0.0, 0.0]
            region.setParameters(parameters)

        if sample.has_substrate():
            substrate_material = apply_lazy(sample.substrate_material, sample, options)

            region = regionops.getRegion(regionops.getNumberRegions() - 1)
            self._export_material(substrate_material, options, erracc, region)

            zmin_m, _zmax_m = zpositions_m[-1]
            parameters = region.getParameters()
            parameters[0] = abs(zmin_m) * 1e9
            parameters[2] = parameters[0] + 10.0
            region.setParameters(parameters)
        else:
            zmin_m, _zmax_m = zpositions_m[-1]
            simops.setTotalThickness_nm(abs(zmin_m) * 1e9)
Beispiel #3
0
    def _validate_sample_verticallayers(self, sample, options, erracc):
        self._validate_sample(sample, options, erracc)

        # Left material
        left_material = apply_lazy(sample.left_material, sample, options)

        if left_material is VACUUM:
            exc = ValueError("Left material cannot be VACUUM.")
            erracc.add_exception(exc)

        self._validate_material(left_material, options, erracc)

        # Layers
        layers = apply_lazy(sample.layers, sample, options)

        for layer in layers:
            self._validate_layer(layer, options, erracc)

        # Right material
        right_material = apply_lazy(sample.right_material, sample, options)

        if right_material is VACUUM:
            exc = ValueError("Right material cannot be VACUUM.")
            erracc.add_exception(exc)

        self._validate_material(right_material, options, erracc)
Beispiel #4
0
    def apply(self, parent_option, options):
        xrayline = base.apply_lazy(self.xrayline, self, options)
        c1 = base.apply_lazy(self.c1, self, options)
        c2 = base.apply_lazy(self.c2, self, options)
        beam_energy_eV = base.apply_lazy(options.beam.energy_eV, options.beam,
                                         options)
        beam_particle = base.apply_lazy(options.beam.particle, options.beam,
                                        options)

        xrayline_energy_eV = max(xrayline.energy_eV - 100, 0.0)

        if beam_particle == Particle.ELECTRON:
            eabs_electron_eV = eabs_photon_eV = xrayline_energy_eV
            eabs_positron_eV = beam_energy_eV
        elif beam_particle == Particle.PHOTON:
            eabs_electron_eV = eabs_photon_eV = eabs_positron_eV = xrayline_energy_eV
        elif beam_particle == Particle.POSITRON:
            eabs_electron_eV = beam_energy_eV
            eabs_photon_eV = eabs_positron_eV = xrayline_energy_eV
        else:
            eabs_electron_eV = eabs_photon_eV = eabs_positron_eV = beam_energy_eV

        return SimulationParameters(
            eabs_electron_eV=eabs_electron_eV,
            eabs_photon_eV=eabs_photon_eV,
            eabs_positron_eV=eabs_positron_eV,
            c1=c1,
            c2=c2,
            wcc_eV=xrayline_energy_eV,
            wcr_eV=xrayline_energy_eV,
        )
Beispiel #5
0
    def _export_detector_photon(self, detector, options, erracc, simdata, simops):
        self._validate_detector_photon(detector, options, erracc)

        elevation_deg = apply_lazy(detector.elevation_deg, detector, options)
        simops.TOA = elevation_deg

        azimuth_deg = apply_lazy(detector.azimuth_deg, detector, options)
        simops.PhieRX = azimuth_deg

        simops.FEmissionRX = 1  # Simulate x-rays
Beispiel #6
0
def test_lazymaterial(material, lazy_material):
    assert lazy_material == lazy_material
    assert material != lazy_material

    density_kg_per_m3 = base.apply_lazy(lazy_material.density_kg_per_m3,
                                        lazy_material, None)
    assert density_kg_per_m3 == pytest.approx(8960.0, abs=1e-4)

    density_g_per_cm3 = base.apply_lazy(lazy_material.density_g_per_cm3,
                                        lazy_material, None)
    assert density_g_per_cm3 == pytest.approx(8.9600, abs=1e-4)
Beispiel #7
0
    def _validate_sample(self, sample, options, erracc):
        super()._validate_sample(sample, options, erracc)

        tilt_rad = apply_lazy(sample.tilt_rad, sample, options)
        if tilt_rad != 0.0:
            exc = ValueError("Sample tilt is not supported.")
            erracc.add_exception(exc)

        azimuth_rad = apply_lazy(sample.azimuth_rad, sample, options)
        if azimuth_rad != 0.0:
            exc = ValueError("Sample azimuth is not supported.")
            erracc.add_exception(exc)
Beispiel #8
0
    def _export_beam_pencil(self, beam, options, erracc, simdata, simops):
        self._validate_beam_pencil(beam, options, erracc)

        # Energy
        energy_eV = apply_lazy(beam.energy_eV, beam, options)
        simops.setIncidentEnergy_keV(energy_eV / 1000.0)  # keV

        # Position
        x0_m = apply_lazy(beam.x0_m, beam, options)
        simops.setPosition(x0_m * 1e9)  # nm

        # Diameter
        simops.Beam_Diameter = 0.0
        simops.Beam_angle = 0.0
Beispiel #9
0
    def _validate_material(self, material, options, erracc):
        if material is VACUUM:
            return

        # Name
        name = apply_lazy(material.name, material, options).strip()

        if not name:
            exc = ValueError(
                "Name ({0:s}) must be at least one character.".format(name))
            erracc.add_exception(exc)

        # Composition
        composition = apply_lazy(material.composition, material, options)

        for z, wf in composition.items():
            try:
                pyxray.descriptor.Element(z)
            except (ValueError, TypeError) as exc:
                erracc.add_exception(exc)

            if wf <= 0.0 or wf > 1.0:
                exc = ValueError(
                    "Weight fraction ({0:g}) must be between ]0.0, 1.0]")
                erracc.add_exception(exc)

        total = sum(composition.values())
        if not math.isclose(
                total, 1.0, abs_tol=Material.WEIGHT_FRACTION_TOLERANCE):
            exc = ValueError(
                "Total weight fraction ({0:g}) does not equal 1.0.".format(
                    total))
            erracc.add_exception(exc)

        # Density
        density_kg_per_m3 = apply_lazy(material.density_kg_per_m3, material,
                                       options)

        if density_kg_per_m3 <= 0:
            exc = ValueError(
                "Density ({0:g}kg/m3) must be greater or equal to 0.".format(
                    density_kg_per_m3))
            erracc.add_exception(exc)

        # Color
        color = apply_lazy(material.color, material, options)

        if not matplotlib.colors.is_color_like(color):
            exc = ValueError("Color ({}) is not a valid color.".format(color))
            erracc.add_exception(exc)
Beispiel #10
0
    def apply(self, parent_option, options):
        # Check that x-ray line exists in material
        xrayline = self.xrayline
        if (
            hasattr(xrayline, "atomic_number")
            and xrayline.atomic_number not in options.sample.atomic_numbers
        ):
            minimum_energy_eV = xrayline.energy_eV or 100.0
            xrayline = LazyLowestEnergyXrayLine(minimum_energy_eV)

        xrayline = base.apply_lazy(xrayline, self, options)
        photon_detector = self._find_detector(options)
        relative_uncertainty = base.apply_lazy(self.relative_uncertainty, self, options)
        return ReferenceLine(xrayline, photon_detector, relative_uncertainty)
Beispiel #11
0
    def _validate_layer(self, layer, options, erracc):
        # Material
        material = apply_lazy(layer.material, layer, options)

        self._validate_material(material, options, erracc)

        # Thickness
        thickness_m = apply_lazy(layer.thickness_m, layer, options)

        if thickness_m <= 0:
            exc = ValueError(
                "Thickness ({0:g} m) must be greater than 0.".format(
                    thickness_m))
            erracc.add_exception(exc)
Beispiel #12
0
    def _export_material(self, material, options, erracc, index):
        self._validate_material(material, options, erracc)

        name = apply_lazy(material.name, material, options)
        filename = "mat{:02d}.mat".format(index)
        composition = apply_lazy(material.composition, material, options)
        density_g_per_cm3 = apply_lazy(material.density_g_per_cm3, material,
                                       options)
        penmaterial = PenelopeMaterial(name,
                                       composition,
                                       density_g_per_cm3,
                                       filename=filename)

        return penmaterial
Beispiel #13
0
    def _validate_sample_horizontallayers(self, sample, options, erracc):
        self._validate_sample(sample, options, erracc)

        # Layers
        layers = apply_lazy(sample.layers, sample, options)

        for layer in layers:
            self._validate_layer(layer, options, erracc)

        # Substrate material
        substrate_material = apply_lazy(sample.substrate_material, sample,
                                        options)

        self._validate_material(substrate_material, options, erracc)
Beispiel #14
0
    def _validate_sample(self, sample, options, erracc):
        # Tilt
        tilt_rad = apply_lazy(sample.tilt_rad, sample, options)

        if not math.isfinite(tilt_rad):
            exc = ValueError("Sample tilt must be a finite number.")
            erracc.add_exception(exc)

        # Azimuth
        azimuth_rad = apply_lazy(sample.azimuth_rad, sample, options)

        if not math.isfinite(azimuth_rad):
            exc = ValueError("Sample azimuth must be a finite number.")
            erracc.add_exception(exc)
Beispiel #15
0
    def _validate_beam_pencil(self, beam, options, erracc):
        self._validate_beam(beam, options, erracc)

        # Position
        x0_m = apply_lazy(beam.x0_m, beam, options)

        if not math.isfinite(x0_m):
            exc = ValueError("Initial x position must be a finite number.")
            erracc.add_exception(exc)

        y0_m = apply_lazy(beam.y0_m, beam, options)

        if not math.isfinite(y0_m):
            exc = ValueError("Initial y position must be a finite number.")
            erracc.add_exception(exc)
Beispiel #16
0
    def _validate_beam(self, beam, options, erracc):
        # Energy
        energy_eV = apply_lazy(beam.energy_eV, beam, options)

        if energy_eV <= 0.0:
            exc = ValueError(
                "Energy ({0:g} eV) must be greater than 0.0.".format(
                    energy_eV))
            erracc.add_exception(exc)

        # Particle
        particle = apply_lazy(beam.particle, beam, options)

        if not isinstance(particle, Particle):
            exc = ValueError("Unknown particle: {0}.".format(particle))
            erracc.add_exception(exc)
Beispiel #17
0
    def _export_sample_inclusion(self, sample, options, erracc, geometry,
                                 dsmaxs):
        self._validate_sample_inclusion(sample, options, erracc)

        # Surface
        inclusion_diameter_m = apply_lazy(sample.inclusion_diameter_m, sample,
                                          options)

        surface_cylinder = cylinder(100.0)  # 100 cm radius
        surface_top = zplane(0.0)  # z = 0
        surface_bottom = zplane(-100.0)  # z = -100 cm
        surface_sphere = sphere(inclusion_diameter_m / 2.0 * 100.0)

        # Inclusion module
        inclusion_material = apply_lazy(sample.inclusion_material, sample,
                                        options)
        penmaterial = self._export_material(inclusion_material,
                                            options,
                                            erracc,
                                            index=1)

        module_inclusion = Module(penmaterial, "Inclusion")
        module_inclusion.add_surface(surface_top, SidePointer.NEGATIVE)
        module_inclusion.add_surface(surface_sphere, SidePointer.NEGATIVE)

        dsmaxs[module_inclusion] = inclusion_diameter_m

        # Substrate module
        substrate_material = apply_lazy(sample.substrate_material, sample,
                                        options)
        penmaterial = self._export_material(substrate_material,
                                            options,
                                            erracc,
                                            index=2)

        module_substrate = Module(penmaterial, "Substrate")
        module_substrate.add_surface(surface_cylinder, SidePointer.NEGATIVE)
        module_substrate.add_surface(surface_top, SidePointer.NEGATIVE)
        module_substrate.add_surface(surface_bottom, SidePointer.POSITIVE)
        module_substrate.add_module(module_inclusion)

        # Geometry
        geometry.title = "Inclusion"
        geometry.add_module(module_substrate)
        geometry.add_module(module_inclusion)
        geometry.tilt_rad = apply_lazy(sample.tilt_rad, sample, options)
        geometry.rotation_rad = apply_lazy(sample.azimuth_rad, sample, options)
Beispiel #18
0
    def _export_material(self, material, options, erracc, region):
        region.removeAllElements()

        composition = apply_lazy(material.composition, material, options)

        for z, fraction in composition.items():
            region.addElement(pyxray.element_symbol(z), weight_fraction=fraction)

        region.update()  # Calculate number of elements, mean atomic number

        region.User_Density = True

        density_g_per_cm3 = apply_lazy(material.density_g_per_cm3, material, options)
        region.Rho = density_g_per_cm3

        name = apply_lazy(material.name, material, options).strip()
        region.Name = name
Beispiel #19
0
    def _export_beam_pencil(self, beam, options, erracc, input):
        self._validate_beam_pencil(beam, options, erracc)

        particle = apply_lazy(beam.particle, beam, options)
        input.SKPAR.set(PARTICLE_INDEX[particle])

        energy_eV = apply_lazy(beam.energy_eV, beam, options)
        input.SENERG.set(energy_eV)

        x0_m = apply_lazy(beam.x0_m, beam, options)
        y0_m = apply_lazy(beam.y0_m, beam, options)
        input.SPOSIT.set(x0_m * 1e2, y0_m * 1e2, 1.0)  # cm

        input.SRADI.set(0.0)  # cm

        input.SDIREC.set(180.0, 0.0)  # pointing downwards
        input.SAPERT.set(0.0)
Beispiel #20
0
    def _export_sample_substrate(self, sample, options, erracc, simdata, simops):
        self._validate_sample_substrate(sample, options, erracc)

        regionops = simdata.getRegionOptions()
        region = regionops.getRegion(0)

        material = apply_lazy(sample.material, sample, options)
        self._export_material(material, options, erracc, region)
Beispiel #21
0
    def _validate_detector(self, detector, options, erracc):
        # Name
        name = apply_lazy(detector.name, detector, options).strip()

        if not name:
            exc = ValueError(
                "Detector name ({0:s}) must be at least one character.".format(
                    name))
            erracc.add_exception(exc)
Beispiel #22
0
    def _validate_beam_pencil(self, beam, options, erracc):
        super()._validate_beam_pencil(beam, options, erracc)

        # Position
        y0_m = apply_lazy(beam.y0_m, beam, options)

        if y0_m != 0.0:
            exc = ValueError("Beam initial y position ({0:g}) must be 0.0".format(y0_m))
            erracc.add_exception(exc)
Beispiel #23
0
    def _validate_detector_photon(self, detector, options, erracc):
        self._validate_detector(detector, options, erracc)

        # Elevation
        elevation_rad = apply_lazy(detector.elevation_rad, detector, options)

        if elevation_rad < -math.pi / 2 or elevation_rad > math.pi / 2:
            exc = ValueError(
                "Elevation ({0:g} rad) must be between [-pi/2,pi/2].".format(
                    elevation_rad))
            erracc.add_exception(exc)

        # Azimuth
        azimuth_rad = apply_lazy(detector.azimuth_rad, detector, options)

        if azimuth_rad < 0 or azimuth_rad >= 2 * math.pi:
            exc = ValueError(
                "Azimuth ({0:g} rad) must be between [0, 2pi[.".format(
                    azimuth_rad))
            erracc.add_exception(exc)
Beispiel #24
0
    def _validate_sample_sphere(self, sample, options, erracc):
        self._validate_sample(sample, options, erracc)

        # Material
        material = apply_lazy(sample.material, sample, options)

        if material is VACUUM:
            exc = ValueError("Material cannot be VACUUM.")
            erracc.add_exception(exc)

        self._validate_material(material, options, erracc)

        # Diameter
        diameter_m = apply_lazy(sample.diameter_m, sample, options)

        if diameter_m <= 0:
            exc = ValueError(
                "Diameter ({0:g} m) must be greater than 0.".format(
                    diameter_m))
            erracc.add_exception(exc)
Beispiel #25
0
    def _validate_sample_substrate(self, sample, options, erracc):
        self._validate_sample(sample, options, erracc)

        # Material
        material = apply_lazy(sample.material, sample, options)

        if material is VACUUM:
            exc = ValueError("Material cannot be VACUUM.")
            erracc.add_exception(exc)

        self._validate_material(material, options, erracc)
Beispiel #26
0
    def _validate_beam(self, beam, options, erracc):
        super()._validate_beam(beam, options, erracc)

        # Particle
        particle = apply_lazy(beam.particle, beam, options)

        if particle is not Particle.ELECTRON:
            exc = ValueError(
                "Particle {0} is not supported. Only ELECTRON.".format(particle)
            )
            erracc.add_exception(exc)
Beispiel #27
0
    def _validate_beam_cylindrical(self, beam, options, erracc):
        self._validate_beam_pencil(beam, options, erracc)

        # Diameter
        diameter_m = apply_lazy(beam.diameter_m, beam, options)

        if diameter_m < 0.0:
            exc = ValueError(
                "Diameter ({0:g} m) must be greater or equal to 0.0.".format(
                    diameter_m))
            erracc.add_exception(exc)
Beispiel #28
0
    def _validate_analysis_kratio(self, analysis, options, erracc):
        standard_materials = apply_lazy(analysis.standard_materials, analysis,
                                        options)

        for z, material in standard_materials.items():
            self._validate_material(material, options, erracc)

            if z not in material.composition:
                exc = ValueError(
                    "Standard for element {0} does not have this element in its composition"
                    .format(pyxray.element_symbol(z)))
                erracc.add_exception(exc)
Beispiel #29
0
    def _export_sample_substrate(self, sample, options, erracc, geometry,
                                 dsmaxs):
        self._validate_sample_substrate(sample, options, erracc)

        # Geometry
        surface_cylinder = cylinder(100)  # 100 cm radius
        surface_top = zplane(0.0)  # z = 0
        surface_bottom = zplane(-100)  # z = -100 cm

        material = apply_lazy(sample.material, sample, options)
        penmaterial = self._export_material(material, options, erracc, index=1)

        module = Module(penmaterial, "Substrate")
        module.add_surface(surface_cylinder, SidePointer.NEGATIVE)
        module.add_surface(surface_top, SidePointer.NEGATIVE)
        module.add_surface(surface_bottom, SidePointer.POSITIVE)

        geometry.title = "Substrate"
        geometry.add_module(module)
        geometry.tilt_rad = apply_lazy(sample.tilt_rad, sample, options)
        geometry.rotation_rad = apply_lazy(sample.azimuth_rad, sample, options)
Beispiel #30
0
    def _export_detector_photon(self, detector, options, erracc, input):
        self._validate_detector_photon(detector, options, erracc)

        # Azimuthal angles
        if isinstance(options.sample,
                      (SubstrateSample, HorizontalLayerSample)):
            phi1 = 0
            phi2 = 360
        elif isinstance(options.sample, VerticalLayerSample):
            azimuth_deg = apply_lazy(detector.azimuth_deg, detector, options)
            azimuth_opening_deg = math.degrees(
                self.photon_detector_azimuth_opening_rad)
            phi1 = normalize_angle(
                math.radians(azimuth_deg - azimuth_opening_deg))
            phi2 = normalize_angle(
                math.radians(azimuth_deg + azimuth_opening_deg))
            phi1, phi2 = map(math.degrees, sorted([phi1, phi2]))
        else:
            phi1 = 0
            phi2 = 360

        # Elevation angles
        # Convert elevation angles (angle from the x-y plane) to theta angles used in PENEPMA,
        # defined as angle from the positive z-axis
        elevation_deg = apply_lazy(detector.elevation_deg, detector, options)
        elevation_opening_deg = math.degrees(
            self.photon_detector_elevation_opening_rad)
        theta1 = 90.0 - (elevation_deg + elevation_opening_deg)
        theta2 = 90.0 - (elevation_deg - elevation_opening_deg)

        # Energy windows
        # FIXME: Support spectrum
        # options.find_analyses(Spectrum, detector)
        ipsf = 0
        edel = 0.0
        edeu = options.beam.energy_eV
        nche = 10

        input.photon_detectors.add(theta1, theta2, phi1, phi2, ipsf, edel,
                                   edeu, nche)