Source code for pyne.dbgen.eaf

"""Module handles parsing EAF formatted cross section files and adding
the data to PyNE's HDF5 storage.  The data here is autonatically grabbed from
the IAEA. 
"""
from __future__ import print_function
import re
import os
from pyne.utils import QA_warn

try:
    import urllib.request as urllib
except ImportError:
    import urllib
from gzip import GzipFile

import numpy as np
import tables as tb

from .. import nucname
from .api import BASIC_FILTERS

QA_warn(__name__)

[docs]def grab_eaf_data(build_dir=""): """Grabs the EAF activation data files if not already present. Parameters ---------- build_dir : str Major directory to place EAF data file(s) in. 'EAF/' will be appended. """ # Add EAF to build_dir build_dir = os.path.join(build_dir, 'EAF') try: os.makedirs(build_dir) print("{0} created".format(build_dir)) except OSError: pass # Grab ENSDF files and unzip them. # This link was taken from 'http://www-nds.iaea.org/fendl/fen-activation.htm' iaea_url = 'http://www-nds.iaea.org/fendl2/activation/processed/vitj_e/libout/fendlg-2.0_175-gz' cf_base_url = 'https://github.com/pyne/data/raw/master/' eaf_gzip = 'fendlg-2.0_175-gz' fpath = os.path.join(build_dir, eaf_gzip) if eaf_gzip not in os.listdir(build_dir): print(" grabbing {0} and placing it in {1}".format(eaf_gzip, fpath)) try: urllib.urlretrieve(iaea_url, fpath) except (OSError, IOError): open(fpath, 'a').close() # touch the file if os.path.getsize(fpath) < 3215713: print(" could not get {0} from IAEA; trying S3 mirror".format(eaf_gzip)) os.remove(fpath) try: urllib.urlretrieve(cf_base_url + eaf_gzip, fpath) except (OSError, IOError): open(fpath, 'a').close() # touch the file if os.path.getsize(fpath) < 3215713: print(" could not get {0} from S3 mirror".format(eaf_gzip)) return False # Write contents of single-file gzip archive to a new file try: gf = GzipFile(fpath) ofile = os.path.join(build_dir, 'fendlg-2.0_175') with open(ofile, 'w') as fw: for line in gf: fw.write(line.decode("us-ascii")) finally: gf.close() return True
# numpy array row storage information for EAF data eaf_dtype = np.dtype([ ('nuc_zz', int ), ('rxnum', 'S7' ), ('rxstr', 'S7' ), ('daughter', 'S7' ), ('xs', float, (175,)) ]) # Regular expression for parsing an individual set of EAF data. # Includes some groupnames that are currently unused. eaf_info_pattern = \ "(?P<iso>\d{5,7})\s*" + \ "(?P<rxnum>\d{2,4})\s*" + \ "(?P<ngrps>\d{1,3})\s*" + \ "(?P<parent>[a-zA-Z]{1,2}\s{0,3}\d{1,3}[M ][12 ])" + \ "(?P<rxstr>\(N,[\w\s]{3}\))" + \ "(?P<daugh>[a-zA-Z.]{1,2}\s{0,3}\d{1,3}[MG]{0,1}\d{0,1})" + \ "(.*?)" eaf_bin_pattern = "(?P<xs>(\d\.\d{5}E[-+]\d{2}\s*){1,175})"
[docs]def parse_eaf_xs(build_file): """Create numpy array by parsing EAF data using regular expressions Parameters ---------- build_file : str Path where EAF data is stored. Returns ------- eaf_array : numpy array Numpy array with a row for each isotope+reaction combination found in the EAF data. """ with open(build_file, 'r') as f: raw_data = f.read() eaf_data = list() eaf_pattern = eaf_info_pattern + eaf_bin_pattern # Iterate over all iso/rx combinations in file for m in re.finditer(eaf_pattern, raw_data, re.DOTALL): md = m.groupdict() xs_list = [float(x) for x in md['xs'].split()] xs_list += (175-len(xs_list))*[0.0] # Store information in new row of array. eafrow = ( nucname.id(md['iso']), md['rxnum'], md['rxstr'], md['daugh'], xs_list ) eaf_data.append(eafrow) eaf_array = np.array(eaf_data, dtype=eaf_dtype) print("Read in {0} sets of EAF data.".format(len(eaf_array))) return eaf_array
[docs]def make_eaf_table(nuc_data, build_path=""): """Function for adding EAF group and table to HDF5 storage. Parameters ---------- nuc_data : str Path to nuclide data file. build_path : str Directory where EAF data is located. """ print("Grabbing the EAF activation data.") eaf_array = parse_eaf_xs(build_path) # Open the HDF5 file db = tb.open_file(nuc_data, 'a', filters=BASIC_FILTERS) # Ensure that the appropriate file structure is present if not hasattr(db.root, 'neutron'): neutron_group = db.create_group('/', 'neutron', \ 'Neutron Interaction Data') # Create eaf_xs group if not hasattr(db.root.neutron, 'eaf_xs'): eaf_group = db.create_group("/neutron", "eaf_xs", \ "EAF 175-Group Neutron Activation Cross Section Data") eaf_table = db.create_table("/neutron/eaf_xs", "eaf_xs", \ np.empty(0, dtype=eaf_dtype), \ "EAF Activation Cross Section Data [barns]", \ expectedrows=len(eaf_array)) # Put eaf_array in the table eaf_table.append(eaf_array) # Write the table eaf_table.flush() # Add group structure by calling placeholder function to get boundaries db.create_array('/neutron/eaf_xs', 'E_g', _get_eaf_groups(), \ 'Neutron energy group bounds [MeV]') # Close the HDF5 file db.close()
def _get_eaf_groups(): """Function for retrieving EAF group structure. Note, energies are entered high to low in the HDF5 storage. This is used as a placeholder for a future PyNE implementation of a database storing group structures. This hypothetical database would return the group structure like this method does. Returns ---------- eaf_E_g_array : 1D list List of energy group boundaries from high to low. """ eaf_E_g_array = [0.0, 1.0000E-07, 4.1399E-07, 5.3158E-07, 6.8256E-07, 8.7643E-07, 1.1254E-06, 1.4450E-06, 1.8554E-06, 2.3824E-06, 3.0590E-06, 3.9279E-06, 5.0435E-06, 6.4760E-06, 8.3153E-06, 1.0677E-05, 1.3710E-05, 1.7604E-05, 2.2603E-05, 2.9023E-05, 3.7267E-05, 4.7851E-05, 6.1442E-05, 7.8893E-05, 1.0130E-04, 1.3007E-04, 1.6702E-04, 2.1445E-04, 2.7536E-04, 3.5358E-04, 4.5400E-04, 5.8295E-04, 7.4852E-04, 9.6112E-04, 1.2341E-03, 1.5846E-03, 2.0347E-03, 2.2487E-03, 2.4852E-03, 2.6126E-03, 2.7465E-03, 3.0354E-03, 3.3546E-03, 3.7074E-03, 4.3074E-03, 5.5308E-03, 7.1017E-03, 9.1188E-03, 1.0595E-02, 1.1709E-02, 1.5034E-02, 1.9305E-02, 2.1875E-02, 2.3579E-02, 2.4176E-02, 2.4788E-02, 2.6058E-02, 2.7000E-02, 2.8501E-02, 3.1828E-02, 3.4307E-02, 4.0868E-02, 4.6309E-02, 5.2475E-02, 5.6562E-02, 6.7380E-02, 7.2025E-02, 7.9499E-02, 8.2503E-02, 8.6517E-02, 9.8037E-02, 1.1109E-01, 1.1679E-01, 1.2277E-01, 1.2907E-01, 1.3569E-01, 1.4264E-01, 1.4996E-01, 1.5764E-01, 1.6573E-01, 1.7422E-01, 1.8316E-01, 1.9255E-01, 2.0242E-01, 2.1280E-01, 2.2371E-01, 2.3518E-01, 2.4724E-01, 2.7324E-01, 2.8725E-01, 2.9452E-01, 2.9721E-01, 2.9849E-01, 3.0197E-01, 3.3373E-01, 3.6883E-01, 3.8774E-01, 4.0762E-01, 4.5049E-01, 4.9787E-01, 5.2340E-01, 5.5023E-01, 5.7844E-01, 6.0810E-01, 6.3928E-01, 6.7206E-01, 7.0651E-01, 7.4274E-01, 7.8082E-01, 8.2085E-01, 8.6294E-01, 9.0718E-01, 9.6167E-01, 1.0026E+00, 1.1080E+00, 1.1648E+00, 1.2246E+00, 1.2874E+00, 1.3534E+00, 1.4227E+00, 1.4957E+00, 1.5724E+00, 1.6530E+00, 1.7377E+00, 1.8268E+00, 1.9205E+00, 2.0190E+00, 2.1225E+00, 2.2313E+00, 2.3069E+00, 2.3457E+00, 2.3653E+00, 2.3851E+00, 2.4660E+00, 2.5924E+00, 2.7253E+00, 2.8651E+00, 3.0119E+00, 3.1664E+00, 3.3287E+00, 3.6788E+00, 4.0657E+00, 4.4933E+00, 4.7237E+00, 4.9659E+00, 5.2205E+00, 5.4881E+00, 5.7695E+00, 6.0653E+00, 6.3763E+00, 6.5924E+00, 6.7032E+00, 7.0469E+00, 7.4082E+00, 7.7880E+00, 8.1873E+00, 8.6071E+00, 9.0484E+00, 9.5123E+00, 1.0000E+01, 1.0513E+01, 1.1052E+01, 1.1618E+01, 1.2214E+01, 1.2523E+01, 1.2840E+01, 1.3499E+01, 1.3840E+01, 1.4191E+01, 1.4550E+01, 1.4918E+01, 1.5683E+01, 1.6487E+01, 1.6905E+01, 1.7333E+01, 1.9640E+01] eaf_E_g_array.reverse() return eaf_E_g_array
[docs]def make_eaf(args): """Controller function for adding cross section data from EAF format file. """ nuc_data, build_dir, datapath = args.nuc_data, args.build_dir, args.datapath # Check if the table already exists with tb.open_file(nuc_data, 'a', filters=BASIC_FILTERS) as f: if hasattr(f.root, 'neutron') and hasattr(f.root.neutron, 'eaf_xs'): print("skipping EAF activation data table creation; already exists.") return # grab the EAF data print("Grabbing the EAF activation data from IAEA") grabbed = grab_eaf_data(build_dir) if not grabbed: return build_filename = os.path.join(build_dir, 'EAF/fendlg-2.0_175') if os.path.exists(build_filename): build_path = build_filename else: return # print("Making EAF activation data table.") make_eaf_table(nuc_data, build_path)