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 warnings import warn
from pyne.utils import QAWarning
import tables as tb
from pyne import nucname
from pyne.data import natural_abund, natural_abund_map
from pyne.material import Material, MaterialLibrary
warn(__name__ + " is not yet QA compliant.", QAWarning)
[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)