Source code for pyne.dbgen.materials_library
"""Module handles the construction of a reference materials library in nuc_data.h5.
This currently consists to natural element materials and those coming from PNNL's
`Materials Compendium`_.
.. _Materials Compendium: http://www.pnnl.gov/main/publications/external/technical_reports/PNNL-15870Rev1.pdf
"""
from __future__ import print_function
import re
import os
import csv
import sys
from itertools import takewhile, groupby
from pyne.utils import QA_warn
import tables as tb
from pyne import nucname
from pyne.data import natural_abund, natural_abund_map
from pyne.material import Material
from pyne.material_library import MaterialLibrary
QA_warn(__name__)
[docs]def make_elements():
"""Make natural elemental materials based on isotopic abundances.
Returns
-------
eltsdict : dict from str to pyne.material.Material
Natural elements as materials.
"""
natural_abund("H1") # initialize natural_abund_map
# get rid of elemental total abundances and empty isotopic abundances
abunds_no_trivial = [abund for abund in natural_abund_map.items() if
nucname.anum(abund[0]) != 0 and abund[1] != 0]
sorted_abunds = sorted(abunds_no_trivial)
grouped_abunds = groupby(sorted_abunds, lambda abund: nucname.znum(abund[0]))
# filter out 111, 113, 115, 117, 118 - the ones with no names
elts = (Material(dict(abunds), metadata={"name": nucname.name(zz)})
for zz, abunds in grouped_abunds if zz in nucname.zz_name.keys())
eltsdict = dict(((elt.metadata["name"], elt) for elt in elts))
return eltsdict
# Parses data from .csv
[docs]def grab_materials_compendium(location='materials_compendium.csv'):
"""Parses data from a materials compendium csv file.
Parameters
----------
location : str
The file to read in compendium from.
Returns
-------
mats : list of pyne.material.Material
The materials in the compendium.
"""
natural_abund("H1") # initialize natural_abund_map
if sys.version_info[0] > 2:
f = open(location, 'r', newline='', encoding="utf-8")
else:
f = open(location, 'rb')
reader = csv.reader(f, delimiter=',', quotechar='"')
lines = list(filter(is_comp_matname_or_density, reader))
mats = parse_materials({}, lines)
f.close()
return mats
comp_matname_or_density_re = re.compile(r'\d+. +$|[A-Za-z]{1,2}-?(\d{1,3})?$')
[docs]def is_comp_matname_or_density(line):
"""Detect composition, material name, or density lines.
Parameters
----------
line : list of str
The input line.
Returns
-------
result : bool
True if the input line has composition, material name, or density data.
False otherwise.
"""
if not line[0]:
return False
if line[0] == "Density (g/cm3) =":
return True
if comp_matname_or_density_re.match(line[0]):
return True
return False
first_line_re = re.compile(r"^\d+. +")
[docs]def parse_materials(mats, lines):
"""Take first material from ``lines`` and append to ``mats``.
Parameters
----------
mats : dict from str to pyne.material.Material
The growing dict of materials.
lines: list of list of str
The shrinking list of lines.
"""
if len(lines) == 0:
return mats
material_lines = list(takewhile(lambda l: first_line_re.match(l[0]) is None,
lines[2:]))
material_length = len(material_lines) + 2
mat = sum((Material({l[0]: float(l[3])}) for l in material_lines))
mat.density = float(lines[1][2])
name = lines[0][1]
mat.metadata = {"name": name}
mat.normalize()
mat = mat.expand_elements()
mat.comp = dict((frac for frac in mat.comp.items() if frac[1] != 0))
mats.update({name: mat})
return parse_materials(mats, lines[material_length:])
# Writes to file
[docs]def make_materials_compendium(nuc_data, matslib):
"""Adds materials compendium to nuc_data.h5."""
matslib.write_hdf5(nuc_data, datapath="/material_library/materials",
nucpath="/material_library/nucid")
[docs]def make_matslib(fname):
"""Make a pyne.material.MaterialLibrary. First makes elements, then
materials from compendium.
Parameters
----------
fname : str
Path to materials compendium.
Returns
-------
matslib : pyne.material.MaterialLibrary
All the materials you could want, in a handy MaterialLibrary instance.
"""
matslib = MaterialLibrary(make_elements())
matsdict = grab_materials_compendium(fname)
matslib.update(matsdict)
return matslib
[docs]def make_materials_library(args):
"""Controller function for adding materials library."""
nuc_data = args.nuc_data
if os.path.exists(nuc_data):
with tb.open_file(nuc_data, 'r') as f:
if '/material_library' in f:
print("skipping materials library data table creation; already exists.")
return
print("Making materials library...")
matslib = make_matslib(os.path.join(os.path.split(__file__)[0],
'materials_compendium.csv'))
make_materials_compendium(nuc_data, matslib)