def testphoton_range(self): material = Material.pure(29) xrayline = XrayLine(29, 'Ka1') actual = photon_range(20e3, material, xrayline, reference='perkins1991') self.assertAlmostEqual(8.42816e-7, actual, 10)
def testphoton_range(self): material = Material.pure(29) transition = Transition(29, siegbahn='Ka1') self.assertAlmostEqual(8.4064e-7, photon_range(20e3, material, transition), 10)
def _append_spatial_distribution(self, lines, options, geoinfo, matinfos, phdets_key_index, phdets_index_keys, *args): lines.append(self._COMMENT_SPATIALDIST()) # Photon depth detectors detectors = dict(options.detectors.iterclass(PhotonDepthDetector)) if not detectors: lines.append(self._COMMENT_SKIP()) return if len(detectors) != 1: raise ExporterException("PENEPMA can only have one photon depth detector") key, detector = next(iter(detectors.items())) ## Get materials materials = options.geometry.get_materials() ## Get transitions if not detector.transitions: zs = set() for material in materials: zs |= set(material.composition.keys()) energylow = min(mat.absorption_energy_eV[ELECTRON] for mat in materials) energyhigh = options.beam.energy_eV transitions = [] for z in zs: transitions += get_transitions(z, energylow, energyhigh) if not transitions: message = "No transition found for PRZ distribution with high enough probability" warnings.warn(message, ExporterWarning) else: transitions = list(detector.transitions) transitions.sort(key=attrgetter('probability'), reverse=True) ## Restrain number of transitions to maximum number of PRZ if len(transitions) > MAX_SPATIAL_DISTRIBUTION // 2: message = 'Too many transitions (%i). Only the most probable is/are kept.' % \ len(transitions) warnings.warn(message, ExporterWarning) transitions = transitions[:MAX_SPATIAL_DISTRIBUTION // 2] logging.debug('PRZ of the following transitions: %s', ', '.join(map(str, transitions))) ## Retrieve range e0 = options.beam.energy_eV safety_factor = 3.0 zmax_m = 1e-08 # PENPEMA forces the minimum depth to be 1e-6 cm for material in materials: for transition in transitions: tmpzmax_m = photon_range(e0, material, transition) * safety_factor zmax_m = max(zmax_m, tmpzmax_m) ## Create lines text = ' '.join(map(str, [-3, 3, 1])) lines.append(self._KEYWORD_GRIDX(text)) text = ' '.join(map(str, [-3, 3, 1])) lines.append(self._KEYWORD_GRIDY(text)) channels = min(100, detector.channels) # Maximum of 100 channels text = ' '.join(map(str, [-zmax_m * 1e2, 0, channels])) lines.append(self._KEYWORD_GRIDZ(text)) index = phdets_key_index[key] + 1 for transition in transitions: code = int(transition.z * 1e6 + \ transition.dest.index * 1e4 + \ transition.src.index * 1e2) text = ' '.join(map(str, [code, 0])) # No absorption lines.append(self._KEYWORD_XRLINE(text)) text = ' '.join(map(str, [code, index])) # With absorption lines.append(self._KEYWORD_XRLINE(text)) lines.append(self._COMMENT_SKIP())
def test_photon_range(): material = Material.pure(29) energy_eV = pyxray.xray_transition_energy_eV(29, "Ka1", reference="jeol") actual = photon_range(20e3, material, 29, energy_eV) assert actual == pytest.approx(8.4063e-7, abs=1e-10)
def _append_spatial_distribution(self, lines, options, geoinfo, matinfos, phdets_key_index, phdets_index_keys, *args): lines.append(self._COMMENT_SPATIALDIST()) # Photon depth detectors detectors = dict(options.detectors.iterclass(PhotonDepthDetector)) if not detectors: lines.append(self._COMMENT_SKIP()) return if len(detectors) != 1: raise ExporterException( "PENEPMA can only have one photon depth detector") key, detector = next(iter(detectors.items())) ## Get materials materials = options.geometry.get_materials() ## Get transitions if not detector.transitions: zs = set() for material in materials: zs |= set(material.composition.keys()) energylow = min(mat.absorption_energy_eV[ELECTRON] for mat in materials) energyhigh = options.beam.energy_eV transitions = [] for z in zs: transitions += get_transitions(z, energylow, energyhigh) if not transitions: message = "No transition found for PRZ distribution with high enough probability" warnings.warn(message, ExporterWarning) else: transitions = list(detector.transitions) transitions.sort(key=attrgetter('probability'), reverse=True) ## Restrain number of transitions to maximum number of PRZ if len(transitions) > MAX_SPATIAL_DISTRIBUTION // 2: message = 'Too many transitions (%i). Only the most probable is/are kept.' % \ len(transitions) warnings.warn(message, ExporterWarning) transitions = transitions[:MAX_SPATIAL_DISTRIBUTION // 2] logging.debug('PRZ of the following transitions: %s', ', '.join(map(str, transitions))) ## Retrieve range e0 = options.beam.energy_eV safety_factor = 3.0 zmax_m = 1e-08 # PENPEMA forces the minimum depth to be 1e-6 cm for material in materials: for transition in transitions: tmpzmax_m = photon_range(e0, material, transition) * safety_factor zmax_m = max(zmax_m, tmpzmax_m) ## Create lines text = ' '.join(map(str, [-3, 3, 1])) lines.append(self._KEYWORD_GRIDX(text)) text = ' '.join(map(str, [-3, 3, 1])) lines.append(self._KEYWORD_GRIDY(text)) channels = min(100, detector.channels) # Maximum of 100 channels text = ' '.join(map(str, [-zmax_m * 1e2, 0, channels])) lines.append(self._KEYWORD_GRIDZ(text)) index = phdets_key_index[key] + 1 for transition in transitions: code = int(transition.z * 1e6 + \ transition.dest.index * 1e4 + \ transition.src.index * 1e2) text = ' '.join(map(str, [code, 0])) # No absorption lines.append(self._KEYWORD_XRLINE(text)) text = ' '.join(map(str, [code, index])) # With absorption lines.append(self._KEYWORD_XRLINE(text)) lines.append(self._COMMENT_SKIP())