Chemical Abundance File Parser

This Python script is designed to parse chemical abundance files, specifically those detailing the abundance ratios and relative abundances of different elements within a sample. The script intakes a file detailing these chemical abundances, parses the data into a structured dictionary format, and then calculates mass fractions based on the given chemical abundance values. This tool is particularly useful in the fields of chemistry and astrophysics for analyzing the composition of various materials or cosmic objects.

import re
import argparse
import numpy as np
 
def chem_to_mass_frac(chem, mass, X):
    return X*(mass/1.008)*10**(chem-12)
 
def parse(contents):
    contentMap = [
            [
                'STD',
                '[Fe/H]',
                '[alpha/Fe]',
                '[C/Fe]',
                '[N/Fe]',
                '[O/Fe]',
                '[r/Fe]',
                '[s/Fe]',
                'C/O',
                'X',
                'Y',
                'Z'
            ],
            [
                ('H', 1.008),
                ('He', 4.003),
                ('Li', 6.941),
                ('Be', 9.012),
                ('B', 10.81),
                ('C', 12.01),
                ('N', 14.01),
                ('O', 16.00),
                ('F', 19.00),
                ('Ne', 20.18)
            ],
            [
                ('Na', 22.99),
                ('Mg', 24.31),
                ('Al', 26.98),
                ('Si', 28.09),
                ('P', 30.97),
                ('S', 32.07),
                ('Cl', 35.45),
                ('Ar', 39.95),
                ('K', 39.10),
                ('Ca', 40.08)
            ],
            [
                ('Sc', 44.96),
                ('Ti', 47.87),
                ('V', 50.94),
                ('Cr', 52.00),
                ('Mn', 54.94),
                ('Fe', 55.85),
                ('Co', 58.93),
                ('Ni', 58.69),
                ('Cu', 63.55),
                ('Zn', 65.38)
            ],
            [
                ('Ga', 69.72),
                ('Ge', 72.63),
                ('As', 74.92),
                ('Se', 78.97),
                ('Br', 79.90),
                ('Kr', 83.80),
                ('Rb', 85.47),
                ('Sr', 87.62),
                ('Y', 88.91),
                ('Zr', 91.22)
            ],
            [
                ('Nb', 92.91),
                ('Mo', 95.95),
                ('Tc', 98.00),
                ('Ru', 101.1),
                ('Rh', 102.9),
                ('Pd', 106.4),
                ('Ag', 107.9),
                ('Cd', 112.4),
                ('In', 1148),
                ('Sn', 118.7)
            ],
            [
                ('Sb', 121.8),
                ('Te', 127.6),
                ('I', 126.9),
                ('Xe', 131.3),
                ('Cs', 132.9),
                ('Ba', 137.3),
                ('La', 138.6),
                ('Ce', 140.1),
                ('Pr', 149.9),
                ('Nd', 144.2)
            ],
            [
                ('Pm', 145.0),
                ('Sm', 150.4),
                ('Eu', 152.0),
                ('Gd', 157.3),
                ('Tb', 158.9),
                ('Dy', 162.5),
                ('Ho', 164.9),
                ('Er', 167.3),
                ('Tm', 168.9),
                ('Yb', 173.04)
            ],
            [
                ('Lu', 175.0),
                ('Hf', 178.5),
                ('Ta', 180.9),
                ('W', 183.8),
                ('Re', 186.2),
                ('Os', 190.2),
                ('Ir', 192.2),
                ('Pt', 195.1),
                ('Au', 197.0),
                ('Hg', 200.6)
            ],
            [
                ('Tl', 204.4),
                ('Pb', 207.2),
                ('Bi', 209.0),
                ('Po', 209),
                ('At', 210),
                ('Rn', 222),
                ('Fr', 223),
                ('Ra', 226),
                ('Ac', 227),
                ('Th', 232)
            ],
            [
                ('Pa', 231),
                ('U', 238)
            ]
        ]
    extracted = {'AbundanceRatio': dict(), 'RelativeAbundance': dict()}
    for rowID, (row,target) in enumerate(zip(contents, contentMap)):
        for colID, (element, targetElement) in enumerate(zip(row, target)):
            if rowID == 0:
                if colID != 0:
                    element = float(element)
                extracted['AbundanceRatio'][targetElement] = element
            else:
                element = float(element)
                extracted['RelativeAbundance'][targetElement[0]] = {"a": element,
                                               "m_f": chem_to_mass_frac(element,
                                                                        targetElement[1],
                                                                        extracted['AbundanceRatio']['X']
                                                                       )
                                              }
    return extracted
 
 
def open_chm_file(path):
    with open(path, 'r') as f:
        contents = filter(lambda x: x != '', f.read().split('\n'))
        contents = filter(lambda x: x[0] != '#', contents)
    contents = [re.split(' |,', x) for x in contents]
    return contents
 
if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Parse chemical abundance file")
    parser.add_argument("path", help="Path to chemical abundance file", type=str)
 
    args=parser.parse_args()
    contents = open_chm_file(args.path)
    extracted = parse(contents)
    print(extracted)