Пример #1
0
 def testconvert_parse(self):
     handler = KRatioAnalysisHDF5Handler()
     detector = self.create_basic_photondetector()
     standard_materials = {29: Material.from_formula('CuZn'),
                           28: Material.from_formula('NiAl')}
     analysis = KRatioAnalysis(detector, standard_materials)
     analysis2 = self.convert_parse_hdf5handler(handler, analysis)
     self.assertEqual(analysis2, analysis)
Пример #2
0
def test_substratesample_getparameters(sample):
    parameters = sample.get_parameters(lambda options: sample)
    assert len(parameters) == 1

    sample.material = Material.from_formula("CaSiO3")
    parameters = sample.get_parameters(lambda options: sample)
    assert len(parameters) == 4
Пример #3
0
def create_model_sample(data, density_start = None, density_end = None):
    elements_data = get_elements_data(data)
    
    colors = generate_colors(steps = len(data) - 1)
    densities = generate_densities(elements_data, density_start, density_end)
    
    material_start, material_end = generate_end_materials(elements_data, colors, density_start, density_end)
    
    sample = VerticalLayerSample(material_start, material_end)
    
    # Iterate through all regions
    for i in range(1, len(data) - 1): # create the remaining regions (in the middle)
        density = densities[i]
        color = colors[i]
        material = Material(
                            name = f'region_{i}',
                            composition = to_weight_fraction(dict(elements_data.iloc[i])),
                            density_kg_per_m3 = density,
                            color = color)
        sample.add_layer(material, thickness_m = data[THICKNESS].iloc[i] / 1e6) # thickness is in micrometer
        
    # creating dummy materials to match template
    dummy_material = Material.from_formula('H', color = None, density_kg_per_m3 = MIN_DENSITY)
    for i in range(TEMPLATE_NUM_REGIONS - len(data)):
        sample.add_layer(dummy_material, thickness_m = MIN_THICKNESS)
    
    return sample
Пример #4
0
 def materials(self):
     try:
         formula = self.field_formula.formula()
         density_kg_per_m3 = self.field_density.density_kg_per_m3()
         color = self.field_color.color()
         return (Material.from_formula(formula, density_kg_per_m3, color), )
     except:
         return ()
 def from_formula(cls, formula, density_kg_m3=None, absorption_energy_eV=None,
                  elastic_scattering=(0.0, 0.0),
                  cutoff_energy_inelastic_eV=50.0,
                  cutoff_energy_bremsstrahlung_eV=50.0,
                  interaction_forcings=None, maximum_step_length_m=1e20):
     mat = _Material.from_formula(formula, density_kg_m3, absorption_energy_eV)
     return cls(mat.composition, mat.name, mat.density_kg_m3, mat.absorption_energy_eV,
                elastic_scattering, cutoff_energy_inelastic_eV, cutoff_energy_bremsstrahlung_eV,
                interaction_forcings, maximum_step_length_m)
Пример #6
0
    def testfrom_formula(self):
        m = Material.from_formula('SiO2', 1250.0)

        self.assertEqual('SiO2', str(m))

        self.assertIn(14, m.composition)
        self.assertAlmostEqual(0.4674, m.composition[14], 4)

        self.assertIn(8, m.composition)
        self.assertAlmostEqual(0.5326, m.composition[8], 4)

        self.assertAlmostEqual(1.25, m.density_kg_per_m3 / 1000.0, 4)
        self.assertAlmostEqual(1.25, m.density_g_per_cm3, 4)
Пример #7
0
def test_material_from_formula():
    material = Material.from_formula("SiO2", 1250.0)

    assert str(material) == "SiO2"
    assert material.name == "SiO2"

    assert 14 in material.composition
    assert material.composition[14] == pytest.approx(0.4674, abs=1e-4)

    assert 8 in material.composition
    assert material.composition[8] == pytest.approx(0.5326, abs=1e-4)

    assert material.density_kg_per_m3 == pytest.approx(1250.0, abs=1e-4)
    assert material.density_g_per_cm3 == pytest.approx(1.25, abs=1e-4)
Пример #8
0
    def testcalculate(self):
        # Create options
        beam = GaussianBeam(20e3, 10.e-9)
        sample = SubstrateSample(Material.from_formula('CaSiO4'))
        limit = ShowersLimit(100)
        unkoptions = Options(self.program, beam, sample, [self.a], [limit])

        list_standard_options = self.a.apply(unkoptions)
        self.assertEqual(3, len(list_standard_options))

        # Create simulations
        def create_simulation(options):
            builder = EmittedPhotonIntensityResultBuilder(self.a)
            for z, wf in options.sample.material.composition.items():
                builder.add_intensity((z, 'Ka'), wf * 1e3, math.sqrt(wf * 1e3))
            result = builder.build()
            return Simulation(options, [result])

        unksim = create_simulation(unkoptions)
        stdsims = [
            create_simulation(options) for options in list_standard_options
        ]
        sims = stdsims + [unksim]

        # Calculate
        newresult = self.a.calculate(unksim, sims)
        self.assertTrue(newresult)

        newresult = self.a.calculate(unksim, sims)
        self.assertFalse(newresult)

        # Test
        results = unksim.find_result(KRatioResult)
        self.assertEqual(1, len(results))

        result = results[0]
        self.assertEqual(3, len(result))

        q = result[('Ca', 'Ka')]
        self.assertAlmostEqual(0.303262, q.n, 4)
        self.assertAlmostEqual(0.019880, q.s, 4)

        q = result[('Si', 'Ka')]
        self.assertAlmostEqual(0.212506, q.n, 4)
        self.assertAlmostEqual(0.016052, q.s, 4)

        q = result[('O', 'Ka')]
        self.assertAlmostEqual(0.484232 / 0.470749, q.n, 4)
        self.assertAlmostEqual(0.066579, q.s, 4)
Пример #9
0
 def from_formula(cls,
                  formula,
                  density_kg_m3=None,
                  absorption_energy_eV=None,
                  elastic_scattering=(0.0, 0.0),
                  cutoff_energy_inelastic_eV=50.0,
                  cutoff_energy_bremsstrahlung_eV=50.0,
                  interaction_forcings=None,
                  maximum_step_length_m=1e20):
     mat = _Material.from_formula(formula, density_kg_m3,
                                  absorption_energy_eV)
     return cls(mat.composition, mat.name, mat.density_kg_m3,
                mat.absorption_energy_eV, elastic_scattering,
                cutoff_energy_inelastic_eV, cutoff_energy_bremsstrahlung_eV,
                interaction_forcings, maximum_step_length_m)
Пример #10
0
def test_material_getparameters_compound():
    material = Material.from_formula("CaSiO3")
    parameters = material.get_parameters(lambda options: material)

    assert len(parameters) == 3
    assert parameters[0].get_value(None) == pytest.approx(
        material.composition[20], abs=1e-6)
    assert parameters[1].get_value(None) == pytest.approx(
        material.composition[14], abs=1e-6)
    assert parameters[2].get_value(None) == pytest.approx(
        material.composition[8], abs=1e-6)

    parameters[0].type_ = ParameterType.UNKNOWN
    parameters[0].set_value(None, 0.5)
    assert parameters[0].get_value(None) == pytest.approx(0.5, abs=1e-6)
    assert material.composition[20] == pytest.approx(0.5, abs=1e-6)
Пример #11
0
class KRatioAnalysis(PhotonAnalysisBase):

    DEFAULT_NONPURE_STANDARD_MATERIALS = {
        7: Material.from_formula("BN", 2.1e3),
        8: Material.from_formula("Al2O3", 3.95e3),
        9: Material.from_formula("BaF2", 4.89e3),
        17: Material.from_formula("KCl", 1.98e3),
        36: Material.from_formula("KBr", 2.75e3),
        80: Material.from_formula("HgTe", 8.1e3),
    }

    def __init__(self, photon_detector, standard_materials=None):
        super().__init__(photon_detector)

        if standard_materials is None:
            standard_materials = {}
        self.standard_materials = standard_materials.copy()

    def __eq__(self, other):
        return super().__eq__(other) and base.are_mapping_equal(
            self.standard_materials, other.standard_materials)

    def add_standard_material(self, z, material):
        self.standard_materials[z] = material

    def get_standard_material(self, z):
        if z in self.standard_materials:
            return self.standard_materials[z]

        if z in self.DEFAULT_NONPURE_STANDARD_MATERIALS:
            return self.DEFAULT_NONPURE_STANDARD_MATERIALS[z]

        return Material.pure(z)

    def _create_standard_options(self, options):
        builder = OptionsBuilder(tags=[TAG_STANDARD])

        program = copy.copy(options.program)
        builder.add_program(program)

        beam = PencilBeam(energy_eV=options.beam.energy_eV,
                          particle=options.beam.particle)
        builder.add_beam(beam)

        for material in options.sample.materials:
            for z in material.composition:
                standard = self.get_standard_material(z)
                builder.add_sample(SubstrateSample(standard))

        analysis = PhotonIntensityAnalysis(self.photon_detector)
        builder.add_analysis(analysis)

        return builder.build()

    def apply(self, options):
        analysis = PhotonIntensityAnalysis(self.photon_detector)

        # Add photon analysis to options if missing
        if analysis not in options.analyses:
            options.analyses.append(analysis)

        # Construct standard options
        standard_options = self._create_standard_options(options)

        return super().apply(options) + standard_options

    def calculate(self, simulation, simulations):
        # If k-ratio result exists, return False, no new result
        for kratioresult in simulation.find_result(KRatioResult):
            if kratioresult.analysis == self:
                logger.debug("KRatioResult already calculated")
                return False

        # Find emitted photon intensity result(s)
        it = (r for r in simulation.find_result(EmittedPhotonIntensityResult)
              if r.analysis.photon_detector == self.photon_detector)
        unkresult = more_itertools.first(it, None)

        # If no result, return False, no new result
        if unkresult is None:
            return False

        # Find standard simulations
        stdoptions = self._create_standard_options(simulation.options)
        stdsimulations = [s for s in simulations if s.options in stdoptions]

        # Build cache of standard result
        stdresult_cache = {}
        for xrayline in unkresult:
            z = xrayline.atomic_number

            if z in stdresult_cache:
                continue

            stdmaterial = self.get_standard_material(z)
            it = (s for s in stdsimulations
                  if s.options.sample.material == stdmaterial)
            stdsimulation = more_itertools.first(it, None)
            if stdsimulation is None:
                logger.debug("No standard simulation found for Z={}".format(z))
                stdresult_cache[z] = None
                continue

            it = (r for r in stdsimulation.find_result(
                EmittedPhotonIntensityResult)
                  if r.analysis.photon_detector == self.photon_detector)
            stdresult = more_itertools.first(it, None)
            if stdresult is None:
                logger.debug("No standard result found for Z={}".format(z))
                stdresult_cache[z] = None
                continue

            stdresult_cache[z] = stdresult

        # Calculate k-ratios
        builder = KRatioResultBuilder(self)

        for xrayline, unkintensity in unkresult.items():
            z = xrayline.atomic_number

            stdresult = stdresult_cache.get(z)
            if stdresult is None:
                continue

            stdintensity = stdresult.get(xrayline, None)
            if stdintensity is None:
                logger.debug("No standard intensity for {}".format(xrayline))
                continue

            builder.add_kratio(xrayline, unkintensity, stdintensity)

        # Create result
        newresult = super().calculate(simulation, simulations)

        if builder.data:
            simulation.results.append(builder.build())
            newresult = True

        return newresult

    # region HDF5

    DATASET_ATOMIC_NUMBER = "atomic number"
    DATASET_STANDARDS = "standards"

    @classmethod
    def parse_hdf5(cls, group):
        detector = cls._parse_hdf5(group, cls.ATTR_DETECTOR)
        standard_materials = cls._parse_hdf5_standard_materials(group)
        return cls(detector, standard_materials)

    @classmethod
    def _parse_hdf5_standard_materials(cls, group):
        ds_z = group[cls.DATASET_ATOMIC_NUMBER]
        ds_standard = group[cls.DATASET_STANDARDS]
        return dict((z, cls._parse_hdf5_reference(group, reference))
                    for z, reference in zip(ds_z, ds_standard))

    def convert_hdf5(self, group):
        super().convert_hdf5(group)
        self._convert_hdf5_standard_materials(group, self.standard_materials)

    def _convert_hdf5_standard_materials(self, group, standard_materials):
        shape = (len(standard_materials), )
        ref_dtype = h5py.special_dtype(ref=h5py.Reference)
        ds_z = group.create_dataset(self.DATASET_ATOMIC_NUMBER,
                                    shape=shape,
                                    dtype=np.byte)
        ds_standard = group.create_dataset(self.DATASET_STANDARDS,
                                           shape=shape,
                                           dtype=ref_dtype)

        ds_z.make_scale()
        ds_standard.dims[0].label = self.DATASET_ATOMIC_NUMBER
        ds_standard.dims[0].attach_scale(ds_z)

        for i, (z, material) in enumerate(standard_materials.items()):
            ds_z[i] = z
            ds_standard[i] = self._convert_hdf5_reference(group, material)

    # endregion

    # region Document

    TABLE_STANDARD = "standard"

    def convert_document(self, builder):
        super().convert_document(builder)

        # Standards
        section = builder.add_section()
        section.add_title("Standard(s)")

        if self.standard_materials:
            table = section.require_table(self.TABLE_STANDARD)

            table.add_column("Element")
            table.add_column("Material")

            for z, material in self.standard_materials.items():
                row = {
                    "Element": pyxray.element_symbol(z),
                    "Material": material.name
                }
                table.add_row(row)

            section = builder.add_section()
            section.add_title("Materials")

            for material in self.standard_materials.values():
                section.add_entity(material)

        else:
            section.add_text("No standard defined")
Пример #12
0
 def testapply2(self):
     self.options.sample.material = Material.from_formula('Al2O3')
     list_options = self.a.apply(self.options)
     self.assertEqual(2, len(list_options))
Пример #13
0
# Create options
import pymontecarlo
from pymontecarlo.options.beam import GaussianBeam
from pymontecarlo.options.material import Material
from pymontecarlo.options.sample import HorizontalLayerSample, SubstrateSample, VerticalLayerSample
from pymontecarlo.options.detector import PhotonDetector
from pymontecarlo.options.analysis import KRatioAnalysis
from pymontecarlo.options.limit import ShowersLimit
from pymontecarlo.options.options import Options

program = pymontecarlo.settings.get_program('casino2')

beam = GaussianBeam(15e3, 10e-9)

mat1 = Material.pure(29)
mat2 = Material.from_formula('SiO2')
mat3 = Material('Stuff', {27: 0.5, 25: 0.2, 8: 0.3}, 4500.0)

sample = SubstrateSample(mat2)

#sample = HorizontalLayerSample(mat3)
#sample.add_layer(mat2, 10e-9)
#sample.add_layer(mat3, 25e-9)

#sample = VerticalLayerSample(mat1, mat2)
#sample.add_layer(mat3, 10e-9)

photon_detector = PhotonDetector('xray', math.radians(35.0))
analysis = KRatioAnalysis(photon_detector)

limit = ShowersLimit(1000)
Пример #14
0
class KRatioAnalysis(PhotonAnalysis):

    DEFAULT_NONPURE_STANDARD_MATERIALS = \
        {7: Material.from_formula('BN', 2.1e3),
         8: Material.from_formula('Al2O3', 3.95e3),
         9: Material.from_formula('BaF2', 4.89e3),
         17: Material.from_formula('KCl', 1.98e3),
         36: Material.from_formula('KBr', 2.75e3),
         80: Material.from_formula('HgTe', 8.1e3)}

    def __init__(self, photon_detector, standard_materials=None):
        super().__init__(photon_detector)

        if standard_materials is None:
            standard_materials = {}
        self.standard_materials = standard_materials

    def __eq__(self, other):
        return super().__eq__(other) and \
            are_mapping_equal(self.standard_materials, other.standard_materials)

    def add_standard_material(self, z, material):
        self.standard_materials[z] = material

    def get_standard_material(self, z):
        if z in self.standard_materials:
            return self.standard_materials[z]

        if z in self.DEFAULT_NONPURE_STANDARD_MATERIALS:
            return self.DEFAULT_NONPURE_STANDARD_MATERIALS[z]

        return Material.pure(z)

    def _create_standard_options(self, options):
        builder = OptionsBuilder()

        builder.add_program(options.program)

        beam = GaussianBeam(energy_eV=options.beam.energy_eV,
                            diameter_m=0.0,
                            particle=options.beam.particle)
        builder.add_beam(beam)

        for material in options.sample.materials:
            for z in material.composition:
                standard = self.get_standard_material(z)
                builder.add_sample(SubstrateSample(standard))

        for limit in options.limits:
            builder.add_limit(options.program, limit)

        for model in options.models:
            builder.add_model(options.program, model)

        analysis = PhotonIntensityAnalysis(self.photon_detector)
        builder.add_analysis(analysis)

        return builder.build()

    def apply(self, options):
        analysis = PhotonIntensityAnalysis(self.photon_detector)

        # Add photon analysis to options if missing
        if analysis not in options.analyses:
            options.analyses.append(analysis)

        # Construct standard options
        standard_options = self._create_standard_options(options)

        return super().apply(options) + standard_options

    def calculate(self, simulation, simulations):
        stdoptions = self._create_standard_options(simulation.options)
        stdsimulations = [s for s in simulations if s.options in stdoptions]

        newresult = super().calculate(simulation, simulations)

        for unkresult in simulation.find_result(EmittedPhotonIntensityResult):
            if unkresult.analysis.photon_detector != self.photon_detector:
                continue

            # Check if KRatioResult already exists
            kratioresult = next((r
                                 for r in simulation.find_result(KRatioResult)
                                 if r.analysis == self), None)
            if kratioresult is not None:
                if kratioresult.keys() == unkresult.keys():
                    logger.debug('KRatioResult already calculated')
                    continue

                simulation.results.remove(kratioresult)

            # Build cache of standard result
            stdresult_cache = {}
            for xrayline in unkresult:
                z = xrayline.atomic_number

                if z in stdresult_cache:
                    continue

                stdmaterial = self.get_standard_material(z)
                stdsimulation = \
                    next((s for s in stdsimulations
                          if s.options.sample.material == stdmaterial), None)
                if stdsimulation is None:
                    logger.debug(
                        'No standard simulation found for Z={}'.format(z))
                    stdresult_cache[z] = None
                    continue

                stdresult = \
                    next((r for r in stdsimulation.find_result(EmittedPhotonIntensityResult)
                         if r.analysis.photon_detector == self.photon_detector), None)
                if stdresult is None:
                    logger.debug('No standard result found for Z={}'.format(z))
                    stdresult_cache[z] = None
                    continue

                stdresult_cache[z] = stdresult

            # Calculate k-ratios
            builder = KRatioResultBuilder(unkresult.analysis)

            for xrayline, unkintensity in unkresult.items():
                z = xrayline.atomic_number

                stdresult = stdresult_cache.get(z)
                if stdresult is None:
                    continue

                stdintensity = stdresult.get(xrayline, None)
                if stdintensity is None:
                    logger.debug(
                        'No standard intensity for {}'.format(xrayline))
                    continue

                builder.add_kratio(xrayline, unkintensity, stdintensity)

            if builder.data:
                simulation.results.append(builder.build())
                newresult = True

        return newresult