From d5853ba516e10a85449d5637164317d6a4c1bf84 Mon Sep 17 00:00:00 2001 From: Joshua Shields <54691495+jvshields@users.noreply.github.com> Date: Mon, 11 Dec 2023 10:29:50 -0500 Subject: [PATCH] add vald shortlist parsing as well as handling for wavelength in vacuum/air and nm/aa (#386) * add shortlist parsing and handling for wavelength in vacuum/air and nm/AA * fix broken tests * add support for stellar linelists * add tests * cleanup * add example notebook with documentation * improve documentation * see if pathlib breaks tests * change os to pathlib * change paths to strings like os output * fix vald test bug, change regex pattern to constant naming convention * fix tests * remove VALD_URL * remove os import * put vald wavelength column handling in external function * make DATA_DIR_PATH constant in conftest.py * continue propagating data_dir --- carsus/conftest.py | 34 +- carsus/io/tests/test_output_tardis.py | 411 ++++++++----- carsus/io/tests/test_vald.py | 46 +- carsus/io/vald/vald.py | 167 ++++-- carsus/tests/data/vald_shortlist_test.dat | 100 ++++ docs/io/vald.ipynb | 667 ++++++++++++++++++++++ 6 files changed, 1211 insertions(+), 214 deletions(-) create mode 100644 carsus/tests/data/vald_shortlist_test.dat create mode 100644 docs/io/vald.ipynb diff --git a/carsus/conftest.py b/carsus/conftest.py index 00fbe3ce1..489a4a446 100644 --- a/carsus/conftest.py +++ b/carsus/conftest.py @@ -7,7 +7,7 @@ """ -import os +from pathlib import Path from astropy.version import version as astropy_version @@ -44,7 +44,7 @@ def pytest_configure(config): from . import __version__ - packagename = os.path.basename(os.path.dirname(__file__)) + packagename = Path(__file__).parent.name TESTED_VERSIONS[packagename] = __version__ @@ -67,6 +67,8 @@ def pytest_configure(config): from sqlalchemy.orm import Session from carsus import init_db +DATA_DIR_PATH = Path(__file__).parent / "tests" / "data" + def pytest_addoption(parser): parser.addoption( @@ -101,18 +103,13 @@ def memory_session(): return session -@pytest.fixture(scope="session") -def data_dir(): - return os.path.join(os.path.dirname(__file__), "tests", "data") - - @pytest.fixture(scope="session") def test_db_fname(request): test_db_fname = request.config.getoption("--test-db") if test_db_fname is None: pytest.skip("--testing database was not specified") else: - return os.path.expandvars(os.path.expanduser(test_db_fname)) + return str(Path(test_db_fname).expanduser().resolve()) @pytest.fixture(scope="session") @@ -121,25 +118,30 @@ def test_db_url(test_db_fname): @pytest.fixture(scope="session") -def gfall_fname(data_dir): - return os.path.join(data_dir, "gftest.all") # Be III, B IV, N VI +def gfall_fname(): + return str(DATA_DIR_PATH / "gftest.all") # Be III, B IV, N VI @pytest.fixture(scope="session") -def gfall_http(data_dir): +def gfall_http(): url = "https://raw.githubusercontent.com/tardis-sn/carsus/" url += "master/carsus/tests/data/gftest.all" return url @pytest.fixture(scope="session") -def vald_fname(data_dir): - return os.path.join(data_dir, "valdtest.dat") +def vald_fname(): + return str(DATA_DIR_PATH / "valdtest.dat") + + +@pytest.fixture(scope="session") +def vald_short_form_stellar_fname(): + return str(DATA_DIR_PATH / "vald_shortlist_test.dat") @pytest.fixture(scope="session") -def nndc_dirname(data_dir): - return os.path.join(data_dir, "nndc") # Mn-52, Ni-56 +def nndc_dirname(): + return str(DATA_DIR_PATH / "nndc") # Mn-52, Ni-56 @pytest.fixture(scope="session") @@ -179,4 +181,4 @@ def refdata_path(request): if refdata_path is None: pytest.skip("--refdata folder path was not specified") else: - return os.path.expandvars(os.path.expanduser(refdata_path)) + return str(Path(refdata_path).expanduser().resolve()) diff --git a/carsus/io/tests/test_output_tardis.py b/carsus/io/tests/test_output_tardis.py index 181bc590b..05273a148 100644 --- a/carsus/io/tests/test_output_tardis.py +++ b/carsus/io/tests/test_output_tardis.py @@ -9,25 +9,27 @@ from carsus.io.output.tardis_ import AtomData from carsus.model import DataSource, Ion +from carsus.conftest import DATA_DIR_PATH @pytest.fixture def atom_data(test_session, chianti_short_name): - atom_data = AtomData(test_session, - selected_atoms="He, Be, B, N, Si, Zn", - chianti_ions="He 1; N 5", - chianti_short_name=chianti_short_name - ) + atom_data = AtomData( + test_session, + selected_atoms="He, Be, B, N, Si, Zn", + chianti_ions="He 1; N 5", + chianti_short_name=chianti_short_name, + ) return atom_data @pytest.fixture def chianti_short_name(test_session): return ( - test_session. - query(DataSource.short_name). - filter(DataSource.short_name.like('chianti%')) - ).one()[0] + test_session.query(DataSource.short_name).filter( + DataSource.short_name.like("chianti%") + ) + ).one()[0] @pytest.fixture @@ -80,12 +82,14 @@ def zeta_data(atom_data): def levels_prepared(atom_data): return atom_data.levels_prepared + @pytest.fixture -def hdf5_path(request, data_dir): - hdf5_path = os.path.join(data_dir, "test_hdf.hdf5") +def hdf5_path(request): + hdf5_path = os.path.join(DATA_DIR_PATH, "test_hdf.hdf5") def fin(): - os.remove(hdf5_path) + os.remove(hdf5_path) + request.addfinalizer(fin) return hdf5_path @@ -95,11 +99,11 @@ def test_atom_data_init(memory_session): nist = DataSource.as_unique(memory_session, short_name="nist-asd") ch = DataSource.as_unique(memory_session, short_name="chianti_v8.0.2") ku = DataSource.as_unique(memory_session, short_name="ku_latest") - atom_data = AtomData(memory_session, - selected_atoms="He, Be, B, N", - chianti_ions="He 1; N 5") + atom_data = AtomData( + memory_session, selected_atoms="He, Be, B, N", chianti_ions="He 1; N 5" + ) assert set(atom_data.selected_atomic_numbers) == set([2, 4, 5, 7]) - assert set(atom_data.chianti_ions) == set([(2,1), (7,5)]) + assert set(atom_data.chianti_ions) == set([(2, 1), (7, 5)]) def test_atom_data_chianti_ions_subset(memory_session): @@ -107,9 +111,11 @@ def test_atom_data_chianti_ions_subset(memory_session): ch = DataSource.as_unique(memory_session, short_name="chianti_v8.0.2") ku = DataSource.as_unique(memory_session, short_name="ku_latest") with pytest.raises(ValueError): - atom_data = AtomData(memory_session, - selected_atoms="He, Be, B, N VI", - chianti_ions="He 1; N 5; Si 1") + atom_data = AtomData( + memory_session, + selected_atoms="He, Be, B, N VI", + chianti_ions="He 1; N 5; Si 1", + ) @pytest.mark.with_test_db @@ -120,122 +126,176 @@ def test_atom_data_wo_chianti_ions_attributes(atom_data_be, test_session): @pytest.mark.with_test_db def test_atom_data_only_be(atom_data_be): - assert all([atomic_number == 4 for atomic_number in - atom_data_be.atom_masses["atomic_number"].values.tolist()]) - assert all([atomic_number == 4 for atomic_number in - atom_data_be.ionization_energies["atomic_number"].values.tolist()]) - assert all([atomic_number == 4 for atomic_number in - atom_data_be.levels["atomic_number"].values.tolist()]) - assert all([atomic_number == 4 for atomic_number in - atom_data_be.lines["atomic_number"].values.tolist()]) + assert all( + [ + atomic_number == 4 + for atomic_number in atom_data_be.atom_masses[ + "atomic_number" + ].values.tolist() + ] + ) + assert all( + [ + atomic_number == 4 + for atomic_number in atom_data_be.ionization_energies[ + "atomic_number" + ].values.tolist() + ] + ) + assert all( + [ + atomic_number == 4 + for atomic_number in atom_data_be.levels["atomic_number"].values.tolist() + ] + ) + assert all( + [ + atomic_number == 4 + for atomic_number in atom_data_be.lines["atomic_number"].values.tolist() + ] + ) @pytest.mark.with_test_db def test_atom_data_join_on_chianti_ions_table(test_session, atom_data): - # This join operation leads to an empty chianti_ions list # # Possible cause: # test_session.query(atom_data.chianti_ions_table).all() -> encoding problem - chiatni_ions_q = test_session.query(Ion).join(atom_data.chianti_ions_table, - and_(Ion.atomic_number == atom_data.chianti_ions_table.c.atomic_number, - Ion.ion_charge == atom_data.chianti_ions_table.c.ion_charge)).\ - order_by(Ion.atomic_number, Ion.ion_charge) + chiatni_ions_q = ( + test_session.query(Ion) + .join( + atom_data.chianti_ions_table, + and_( + Ion.atomic_number == atom_data.chianti_ions_table.c.atomic_number, + Ion.ion_charge == atom_data.chianti_ions_table.c.ion_charge, + ), + ) + .order_by(Ion.atomic_number, Ion.ion_charge) + ) chianti_ions = [(ion.atomic_number, ion.ion_charge) for ion in chiatni_ions_q] - assert set(chianti_ions) == set([(2,1), (7,5)]) + assert set(chianti_ions) == set([(2, 1), (7, 5)]) @pytest.mark.with_test_db -def test_atom_data_two_instances_same_session( - test_session, - chianti_short_name): - +def test_atom_data_two_instances_same_session(test_session, chianti_short_name): atom_data1 = AtomData( - test_session, - selected_atoms="He, Be, B, N, Zn", - chianti_ions="He 1; N 5", - chianti_short_name=chianti_short_name) + test_session, + selected_atoms="He, Be, B, N, Zn", + chianti_ions="He 1; N 5", + chianti_short_name=chianti_short_name, + ) atom_data2 = AtomData( - test_session, - selected_atoms="He, Be, B, N, Zn", - chianti_ions="He 1; N 5", - chianti_short_name=chianti_short_name) + test_session, + selected_atoms="He, Be, B, N, Zn", + chianti_ions="He 1; N 5", + chianti_short_name=chianti_short_name, + ) atom_data1.chianti_ions_table atom_data2.chianti_ions_table @pytest.mark.with_test_db -@pytest.mark.parametrize("atomic_number, exp_mass", [ - (2, 4.002602 * u.u), - (4, 9.0121831 * u.u), - (5, (10.806 + 10.821)/2 * u.u), - (7, (14.00643 + 14.00728)/2 * u.u), - (14, (28.084 + 28.086)/2 *u.u), - (30, 65.38 *u.u) -]) +@pytest.mark.parametrize( + "atomic_number, exp_mass", + [ + (2, 4.002602 * u.u), + (4, 9.0121831 * u.u), + (5, (10.806 + 10.821) / 2 * u.u), + (7, (14.00643 + 14.00728) / 2 * u.u), + (14, (28.084 + 28.086) / 2 * u.u), + (30, 65.38 * u.u), + ], +) def test_create_atom_masses(atom_masses, atomic_number, exp_mass): atom_masses = atom_masses.set_index("atomic_number") - assert_quantity_allclose( - atom_masses.loc[atomic_number]["mass"] * u.u, - exp_mass - ) + assert_quantity_allclose(atom_masses.loc[atomic_number]["mass"] * u.u, exp_mass) @pytest.mark.with_test_db -@pytest.mark.parametrize("atomic_number, ion_number, exp_ioniz_energy", [ - (2, 1, 54.41776311 * u.eV), - (4, 2, 153.896198 * u.eV), - (5, 3, 259.3715 * u.eV), - (7, 5, 552.06731 * u.eV), - (14, 1, 16.345845 * u.eV), - (30, 19, 737.366 * u.eV) -]) -def test_create_ionizatinon_energies(ionization_energies, atomic_number, ion_number, exp_ioniz_energy): +@pytest.mark.parametrize( + "atomic_number, ion_number, exp_ioniz_energy", + [ + (2, 1, 54.41776311 * u.eV), + (4, 2, 153.896198 * u.eV), + (5, 3, 259.3715 * u.eV), + (7, 5, 552.06731 * u.eV), + (14, 1, 16.345845 * u.eV), + (30, 19, 737.366 * u.eV), + ], +) +def test_create_ionizatinon_energies( + ionization_energies, atomic_number, ion_number, exp_ioniz_energy +): ionization_energies = ionization_energies.set_index(["atomic_number", "ion_number"]) assert_quantity_allclose( - ionization_energies.loc[(atomic_number, ion_number)]["ionization_energy"] * u.eV, - exp_ioniz_energy + ionization_energies.loc[(atomic_number, ion_number)]["ionization_energy"] + * u.eV, + exp_ioniz_energy, ) @pytest.mark.with_test_db -@pytest.mark.parametrize("atomic_number, ion_number, ionization_energy",[ - (2, 1, 54.41776311 * u.eV), - (4, 2, 153.896198 * u.eV), - (5, 3, 259.3715 * u.eV), - (7, 5, 552.06731 * u.eV), - (14, 1, 16.345845 * u.eV) # In fact, only Si II has levels with energy > ionization potential -]) -def test_create_levels_filter_auto_ionizing_levels(levels, atomic_number, ion_number, ionization_energy): - levels_ion = levels.loc[(levels["atomic_number"] == atomic_number) & - (levels["ion_number"] == ion_number)].copy() +@pytest.mark.parametrize( + "atomic_number, ion_number, ionization_energy", + [ + (2, 1, 54.41776311 * u.eV), + (4, 2, 153.896198 * u.eV), + (5, 3, 259.3715 * u.eV), + (7, 5, 552.06731 * u.eV), + ( + 14, + 1, + 16.345845 * u.eV, + ), # In fact, only Si II has levels with energy > ionization potential + ], +) +def test_create_levels_filter_auto_ionizing_levels( + levels, atomic_number, ion_number, ionization_energy +): + levels_ion = levels.loc[ + (levels["atomic_number"] == atomic_number) + & (levels["ion_number"] == ion_number) + ].copy() levels_energies = levels_ion["energy"].values * u.eV assert all(levels_energies < ionization_energy) @pytest.mark.with_test_db -@pytest.mark.parametrize("atomic_number, ion_number, level_number, exp_energy, exp_g, exp_metastable_flag",[ - # Kurucz levels - (4, 2, 0, 0.0 * u.Unit("cm-1"), 1, True), - (4, 2, 1, 956501.9 * u.Unit("cm-1"), 3, True), - (4, 2, 6, 997455.0 * u.Unit("cm-1"), 3, False), - (14, 1, 0, 0.0 * u.Unit("cm-1"), 2, True), - (14, 1, 15, 81251.320 * u.Unit("cm-1"), 4, False), - # (14, 1, 16, 83801.950 * u.Unit("cm-1"), 2, 1), investigate the issue with this level (probably labels)! - # CHIANTI levels - # Theoretical values from CHIANTI aren't ingested!!! - (7, 5, 0, 0.0 * u.Unit("cm-1"), 1, True), - (7, 5, 7, 3991860.0 * u.Unit("cm-1"), 3, False), - (7, 5, 43, 4294670.00 * u.Unit("cm-1"), 5, False), - # NIST Ground level - (30, 19, 0, 0.0 * u.eV, 2, True) -]) -def test_create_levels(levels, atomic_number, ion_number, level_number, - exp_energy, exp_g, exp_metastable_flag): +@pytest.mark.parametrize( + "atomic_number, ion_number, level_number, exp_energy, exp_g, exp_metastable_flag", + [ + # Kurucz levels + (4, 2, 0, 0.0 * u.Unit("cm-1"), 1, True), + (4, 2, 1, 956501.9 * u.Unit("cm-1"), 3, True), + (4, 2, 6, 997455.0 * u.Unit("cm-1"), 3, False), + (14, 1, 0, 0.0 * u.Unit("cm-1"), 2, True), + (14, 1, 15, 81251.320 * u.Unit("cm-1"), 4, False), + # (14, 1, 16, 83801.950 * u.Unit("cm-1"), 2, 1), investigate the issue with this level (probably labels)! + # CHIANTI levels + # Theoretical values from CHIANTI aren't ingested!!! + (7, 5, 0, 0.0 * u.Unit("cm-1"), 1, True), + (7, 5, 7, 3991860.0 * u.Unit("cm-1"), 3, False), + (7, 5, 43, 4294670.00 * u.Unit("cm-1"), 5, False), + # NIST Ground level + (30, 19, 0, 0.0 * u.eV, 2, True), + ], +) +def test_create_levels( + levels, + atomic_number, + ion_number, + level_number, + exp_energy, + exp_g, + exp_metastable_flag, +): levels = levels.set_index(["atomic_number", "ion_number", "level_number"]) energy = levels.loc[(atomic_number, ion_number, level_number)]["energy"] * u.eV g = levels.loc[(atomic_number, ion_number, level_number)]["g"] - metastable_flag = levels.loc[(atomic_number, ion_number, level_number)]["metastable"] + metastable_flag = levels.loc[(atomic_number, ion_number, level_number)][ + "metastable" + ] # Convert the expected energy using equivalencies exp_energy = exp_energy.to(u.eV, equivalencies=u.spectral()) @@ -246,70 +306,108 @@ def test_create_levels(levels, atomic_number, ion_number, level_number, @pytest.mark.with_test_db -@pytest.mark.parametrize("atomic_number, ion_number, level_number_lower, level_number_upper, exp_wavelength, exp_loggf",[ - # Kurucz lines - (14, 1, 0, 57, 81.8575 * u.Unit("nm"), -1.92), - (14, 1, 1, 71, 80.5098 * u.Unit("nm"), -2.86), - # CHIANTI lines - # Note that energies are *not* sorted in the elvlc file! - (2, 1, 0, 1, 303.786 * u.Unit("angstrom"), np.log10(0.2772)), - (2, 1, 2, 16, 1084.920 * u.Unit("angstrom"), np.log10(0.027930)) -]) -def test_create_lines(lines, atomic_number, ion_number, level_number_lower, level_number_upper, - exp_wavelength, exp_loggf): - lines = lines.set_index(["atomic_number", "ion_number", - "level_number_lower", "level_number_upper"]) - wavelength = lines.loc[(atomic_number, ion_number, - level_number_lower, level_number_upper)]["wavelength"] * u.Unit("angstrom") - loggf = lines.loc[(atomic_number, ion_number, - level_number_lower, level_number_upper)]["loggf"] +@pytest.mark.parametrize( + "atomic_number, ion_number, level_number_lower, level_number_upper, exp_wavelength, exp_loggf", + [ + # Kurucz lines + (14, 1, 0, 57, 81.8575 * u.Unit("nm"), -1.92), + (14, 1, 1, 71, 80.5098 * u.Unit("nm"), -2.86), + # CHIANTI lines + # Note that energies are *not* sorted in the elvlc file! + (2, 1, 0, 1, 303.786 * u.Unit("angstrom"), np.log10(0.2772)), + (2, 1, 2, 16, 1084.920 * u.Unit("angstrom"), np.log10(0.027930)), + ], +) +def test_create_lines( + lines, + atomic_number, + ion_number, + level_number_lower, + level_number_upper, + exp_wavelength, + exp_loggf, +): + lines = lines.set_index( + ["atomic_number", "ion_number", "level_number_lower", "level_number_upper"] + ) + wavelength = lines.loc[ + (atomic_number, ion_number, level_number_lower, level_number_upper) + ]["wavelength"] * u.Unit("angstrom") + loggf = lines.loc[ + (atomic_number, ion_number, level_number_lower, level_number_upper) + ]["loggf"] assert_quantity_allclose(wavelength, exp_wavelength) assert_almost_equal(loggf, exp_loggf) @pytest.mark.with_test_db -@pytest.mark.parametrize("atomic_number, ion_number, level_number_lower, level_number_upper, exp_wavelength, exp_loggf",[ - # Kurucz lines with wavelength above 2000 Angstrom - (14, 1, 8, 83, 2015.574293 * u.Unit("angstrom"), -0.120), - (14, 1, 8, 82, 2017.305610 * u.Unit("angstrom"), 0.190) -]) -def test_create_lines_convert_air2vacuum(lines, atomic_number, ion_number, level_number_lower, level_number_upper, - exp_wavelength, exp_loggf): - lines = lines.set_index(["atomic_number", "ion_number", - "level_number_lower", "level_number_upper"]) - wavelength = lines.loc[(atomic_number, ion_number, - level_number_lower, level_number_upper)]["wavelength"] * u.Unit("angstrom") - loggf = lines.loc[(atomic_number, ion_number, - level_number_lower, level_number_upper)]["loggf"] +@pytest.mark.parametrize( + "atomic_number, ion_number, level_number_lower, level_number_upper, exp_wavelength, exp_loggf", + [ + # Kurucz lines with wavelength above 2000 Angstrom + (14, 1, 8, 83, 2015.574293 * u.Unit("angstrom"), -0.120), + (14, 1, 8, 82, 2017.305610 * u.Unit("angstrom"), 0.190), + ], +) +def test_create_lines_convert_air2vacuum( + lines, + atomic_number, + ion_number, + level_number_lower, + level_number_upper, + exp_wavelength, + exp_loggf, +): + lines = lines.set_index( + ["atomic_number", "ion_number", "level_number_lower", "level_number_upper"] + ) + wavelength = lines.loc[ + (atomic_number, ion_number, level_number_lower, level_number_upper) + ]["wavelength"] * u.Unit("angstrom") + loggf = lines.loc[ + (atomic_number, ion_number, level_number_lower, level_number_upper) + ]["loggf"] assert_quantity_allclose(wavelength, exp_wavelength) assert_almost_equal(loggf, exp_loggf) + @pytest.mark.with_test_db -@pytest.mark.parametrize("atomic_number, ion_number, level_number_lower, level_number_upper", [ - # Default loggf_threshold = -3 - # Kurucz lines - (14, 1, 3, 98), # loggf = -4.430 - (14, 1, 2, 83), # loggf = -4.140 - # CHIANTI lines - (7, 5, 3, 11), # loggf = -5.522589 - (7, 5, 6, 7), # loggf = -5.240106 -]) -def test_create_lines_loggf_treshold(lines, atomic_number, ion_number, level_number_lower, level_number_upper): - lines = lines.set_index(["atomic_number", "ion_number", - "level_number_lower", "level_number_upper"]) +@pytest.mark.parametrize( + "atomic_number, ion_number, level_number_lower, level_number_upper", + [ + # Default loggf_threshold = -3 + # Kurucz lines + (14, 1, 3, 98), # loggf = -4.430 + (14, 1, 2, 83), # loggf = -4.140 + # CHIANTI lines + (7, 5, 3, 11), # loggf = -5.522589 + (7, 5, 6, 7), # loggf = -5.240106 + ], +) +def test_create_lines_loggf_treshold( + lines, atomic_number, ion_number, level_number_lower, level_number_upper +): + lines = lines.set_index( + ["atomic_number", "ion_number", "level_number_lower", "level_number_upper"] + ) with pytest.raises(KeyError): - assert lines.loc[(atomic_number, ion_number, level_number_lower, level_number_upper)] + assert lines.loc[ + (atomic_number, ion_number, level_number_lower, level_number_upper) + ] @pytest.mark.with_test_db @pytest.mark.parametrize("atomic_number", [2, 14, 30]) def test_levels_create_artificial_fully_ionized(levels, atomic_number): levels = levels.set_index(["atomic_number", "ion_number", "level_number"]) - energy, g, metastable = levels.loc[(atomic_number, atomic_number, 0), ["energy", "g", "metastable"]] + energy, g, metastable = levels.loc[ + (atomic_number, atomic_number, 0), ["energy", "g", "metastable"] + ] assert_almost_equal(energy, 0.0) assert g == 1 assert metastable + # ToDo: Implement real tests @pytest.mark.with_test_db def test_create_collisions(collisions): @@ -327,19 +425,19 @@ def test_create_macro_atom_ref(macro_atom_references): @pytest.mark.with_test_db -@pytest.mark.parametrize("atomic_number, ion_number, source_level_number", [ - (2, 2, 0), - (5, 5, 0), - (30, 19, 0), - (30, 30, 0) -]) -def test_create_macro_atom_references_levels_wo_lines(macro_atom_references, atomic_number, - ion_number, source_level_number): +@pytest.mark.parametrize( + "atomic_number, ion_number, source_level_number", + [(2, 2, 0), (5, 5, 0), (30, 19, 0), (30, 30, 0)], +) +def test_create_macro_atom_references_levels_wo_lines( + macro_atom_references, atomic_number, ion_number, source_level_number +): macro_atom_references = macro_atom_references.set_index( ["atomic_number", "ion_number", "source_level_number"] ) count_up, count_down, count_total = macro_atom_references.loc[ - (atomic_number, ion_number, source_level_number), ("count_up", "count_down", "count_total") + (atomic_number, ion_number, source_level_number), + ("count_up", "count_down", "count_total"), ] assert all([count == 0 for count in [count_up, count_down, count_total]]) @@ -351,6 +449,13 @@ def test_create_zeta_data(zeta_data): @pytest.mark.with_test_db def test_atom_data_to_hdf(atom_data, hdf5_path): - atom_data.to_hdf(hdf5_path, store_atom_masses=True, store_ionization_energies=True, - store_levels=True, store_lines=True, store_macro_atom=True, - store_zeta_data=True, store_collisions=True) + atom_data.to_hdf( + hdf5_path, + store_atom_masses=True, + store_ionization_energies=True, + store_levels=True, + store_lines=True, + store_macro_atom=True, + store_zeta_data=True, + store_collisions=True, + ) diff --git a/carsus/io/tests/test_vald.py b/carsus/io/tests/test_vald.py index d2d5be6ad..f82438d07 100644 --- a/carsus/io/tests/test_vald.py +++ b/carsus/io/tests/test_vald.py @@ -39,6 +39,18 @@ def vald_linelist(vald_rdr): return vald_rdr.linelist +@pytest.fixture() +def vald_rdr_short_form_stellar(vald_short_form_stellar_fname): + return VALDReader( + fname=vald_short_form_stellar_fname, strip_molecules=False, shortlist=True + ) + + +@pytest.fixture() +def vald_linelist_short_form_stellar(vald_rdr_short_form_stellar): + return vald_rdr_short_form_stellar.linelist + + @pytest.mark.parametrize( "index, wl_air, log_gf, e_low, e_up", [ @@ -48,7 +60,7 @@ def vald_linelist(vald_rdr): ) def test_vald_reader_vald_raw(vald_raw, index, wl_air, log_gf, e_low, e_up): row = vald_raw.loc[index] - assert_almost_equal(row["wl_air"], wl_air) + assert_almost_equal(row["WL_air(A)"], wl_air) assert_allclose([row["log_gf"], row["e_low"], row["e_up"]], [log_gf, e_low, e_up]) @@ -61,7 +73,7 @@ def test_vald_reader_vald_raw(vald_raw, index, wl_air, log_gf, e_low, e_up): ) def test_vald_reader_vald(vald, index, wl_air, log_gf, e_low, e_up, ion_charge): row = vald.loc[index] - assert_almost_equal(row["wl_air"], wl_air) + assert_almost_equal(row["WL_air(A)"], wl_air) assert_allclose( [row["log_gf"], row["e_low"], row["e_up"], row["ion_charge"]], [log_gf, e_low, e_up, ion_charge], @@ -115,3 +127,33 @@ def test_vald_linelist(vald_linelist): ) # Test to see if any values have become nan in new columns assert ~vald_linelist.isna().values.any() + + +@pytest.mark.parametrize( + "index, wavelength, log_gf, e_low, v_mic, ion_charge", + [ + (73, 5001.40537184386, -1.563, 0.5786, 1, 0), + (17, 5001.397869850396, -6.421, 7.1801, 1, 0), + ], +) +def test_vald_short_stellar_linelist( + vald_linelist_short_form_stellar, + index, + wavelength, + log_gf, + e_low, + v_mic, + ion_charge, +): + assert len(vald_linelist_short_form_stellar) == 95 + row = vald_linelist_short_form_stellar.iloc[index] + assert_almost_equal(row["wavelength"], wavelength) + assert_allclose( + [ + row["log_gf"], + row["e_low"], + row["v_mic"], + row["ion_charge"], + ], + [log_gf, e_low, v_mic, ion_charge], + ) diff --git a/carsus/io/vald/vald.py b/carsus/io/vald/vald.py index 11db67a58..b7d3bbd40 100644 --- a/carsus/io/vald/vald.py +++ b/carsus/io/vald/vald.py @@ -9,10 +9,9 @@ ATOMIC_SYMBOLS_DATA, convert_symbol2atomic_number, ) +from astropy import units as u -VALD_URL = "https://media.githubusercontent.com/media/tardis-sn/carsus-db/master/vald/vald_sample.dat" - logger = logging.getLogger(__name__) @@ -25,19 +24,23 @@ class VALDReader(object): fname: str path to vald data file strip_molecules: bool - Whether to remove molecules from the data. + Whether to remove molecules from the data. Defaults to True. + shortlist: bool + Whether the parsed file is a shortlist or not. Methods -------- vald_raw: Return pandas DataFrame representation of vald + linelist: + Return pandas DataFrame representation of linelist properties necessary to compute line opacities """ vald_columns = [ "elm_ion", - "wl_air", + "wave_unprepared", # This is the wavelength column header before it is ingested overwritten with appropriate units "log_gf", "e_low", "j_lo", @@ -51,7 +54,20 @@ class VALDReader(object): "waals", ] - def __init__(self, fname=None, strip_molecules=True): + vald_shortlist_columns = [ + "elm_ion", + "wave_unprepared", # This is the wavelength column header before it is ingested overwritten with appropriate units + "e_low", + "log_gf", + "rad", + "stark", + "waals", + "lande_factor", + "central_depth", + "reference", + ] + + def __init__(self, fname=None, strip_molecules=True, shortlist=False): """ Parameters ---------- @@ -59,16 +75,26 @@ def __init__(self, fname=None, strip_molecules=True): Path to the vald file (http or local file). strip_molecules: bool Whether to remove molecules from the data. - + shortlist: bool + Whether the parsed file is a shortlist or not. """ - self.fname = VALD_URL if fname is None else fname + assert fname is not None, "fname must be specified" + self.fname = fname self._vald_raw = None self._vald = None self._linelist = None + self._stellar_linelist = False + + self._vald_columns = ( + self.vald_shortlist_columns.copy() + if shortlist + else self.vald_columns.copy() + ) self.strip_molecules = strip_molecules + self.shortlist = shortlist @property def vald_raw(self): @@ -126,17 +152,58 @@ def read_vald_raw(self, fname=None): # Elm Ion WL_air(A) log gf* E_low(eV) J lo E_up(eV) J up lower upper mean Rad. Stark Waals # 'TiO 1', 4100.00020, -11.472, 0.2011, 31.0, 3.2242, 32.0, 99.000, 99.000, 99.000, 6.962, 0.000, 0.000, - data_match = re.compile("'[a-zA-Z]+ \d+',[\s*-?\d+[\.\d+]+,]*") + DATA_RE_PATTERN = re.compile("'[a-zA-Z]+ \d+',[\s*-?\d+[\.\d+]+,]*") buffer, checksum = read_from_buffer(self.fname) + content = buffer.read().decode() + + # Need to identify the wavelength column header and overwrite the wavelength to obtain units and air or vacuum + # Also need to identify if Vmic is in the columns for correct column construction + for line in content.split("\n")[:10]: + if "WL" in line: + for column_header in line.split(): + if "WL" in column_header: + self._vald_columns[1] = column_header + logger.info(f"Found wavelength column header: {column_header}") + if "Vmicro" in line and self._stellar_linelist == False: + logger.info("Found Vmic column - This is a stellar vald linelist") + self._vald_columns.insert(3, "v_mic") + + self._stellar_linelist = True + vald = pd.read_csv( - StringIO("\n".join(data_match.findall(buffer.read().decode()))), - names=self.vald_columns, + StringIO("\n".join(DATA_RE_PATTERN.findall(content))), + names=self._vald_columns, index_col=False, ) + if self.shortlist: + del vald["reference"] + return vald, checksum + def check_wavelength_column_medium_and_units(self): + wave_col_name = self.vald_raw.columns[1] + if "air" in wave_col_name: + wave_air = True + elif "vac" in wave_col_name: + wave_air = False + else: + raise ValueError( + "Wavelength column header does not contain air or vac - Not sure what medium the wavelengths are in" + ) + if "(A)" in wave_col_name: + wave_units = u.AA + elif "(nm)" in wave_col_name: + wave_units = u.nm + elif "(cm-1)" in wave_col_name: + wave_units = u.cm**-1 + else: + raise ValueError( + "Wavelength column header does not contain units - Not sure what units the wavelengths are in" + ) + return wave_col_name, wave_air, wave_units + def parse_vald(self, vald_raw=None, strip_molecules=True): """ Parses raw vald DataFrame @@ -158,7 +225,18 @@ def parse_vald(self, vald_raw=None, strip_molecules=True): vald["elm_ion"] = vald["elm_ion"].str.replace("'", "") vald[["chemical", "ion_charge"]] = vald["elm_ion"].str.split(" ", expand=True) vald["ion_charge"] = vald["ion_charge"].astype(int) - 1 - vald["wavelength"] = convert_wavelength_air2vacuum(vald["wl_air"]) + + # Check units and medium of wavelength column and create wavelength column in angstroms in vacuum + ( + wave_col_name, + wave_air, + wave_units, + ) = self.check_wavelength_column_medium_and_units() + vald["wavelength"] = (vald[wave_col_name].values * wave_units).to(u.AA).value + if wave_air: + vald["wavelength"] = convert_wavelength_air2vacuum( + (vald["wavelength"].values * wave_units).to(u.AA).value + ) del vald["elm_ion"] @@ -191,40 +269,42 @@ def extract_linelist(self, vald): ------- pandas.DataFrame vald linelist containing only the following columns: - atomic_number or chemical, ion_charge, wavelength, log_gf, rad, stark, waals + atomic_number or chemical, ion_charge, wavelength, e_low, log_gf, rad, stark, waals + optionally: v_mic (if stellar linelist) and e_up, j_lo, j_up (if not shortlist) """ - if self.strip_molecules: - return vald[ - [ - "atomic_number", - "ion_charge", - "wavelength", - "log_gf", - "e_low", - "e_up", - "j_lo", - "j_up", - "rad", - "stark", - "waals", - ] - ].copy() + if self.shortlist: + linelist_mask = [ + "chemical", + "ion_charge", + "wavelength", + "log_gf", + "e_low", + "rad", + "stark", + "waals", + ] + if self._stellar_linelist: + linelist_mask.insert(5, "v_mic") + else: - return vald[ - [ - "chemical", - "ion_charge", - "wavelength", - "log_gf", - "e_low", - "e_up", - "j_lo", - "j_up", - "rad", - "stark", - "waals", - ] - ].copy() + linelist_mask = [ + "chemical", + "ion_charge", + "wavelength", + "log_gf", + "e_low", + "e_up", + "j_lo", + "j_up", + "rad", + "stark", + "waals", + ] + + if self.strip_molecules: + linelist_mask[0] = "atomic_number" + + return vald[linelist_mask].copy() def to_hdf(self, fname): """ @@ -236,3 +316,4 @@ def to_hdf(self, fname): with pd.HDFStore(fname, "w") as f: f.put("/vald_raw", self.vald_raw) f.put("/vald", self.vald) + f.put("/linelist", self.linelist) diff --git a/carsus/tests/data/vald_shortlist_test.dat b/carsus/tests/data/vald_shortlist_test.dat new file mode 100644 index 000000000..1009c7485 --- /dev/null +++ b/carsus/tests/data/vald_shortlist_test.dat @@ -0,0 +1,100 @@ + WARNING: Output was truncated to 100000 lines + 5000.00000, 5020.00000, 100000, 100001, 1.0 Wavelength region, lines selected, lines processed, Vmicro + Damping parameters Lande Central +Spec Ion WL_air(A) Excit(eV) Vmic log gf* Rad. Stark Waals factor depth Reference +'TiO 1', 5000.0000, 1.1873, 1.0, -5.080, 7.269, 0.000, 0.000, 99.000, 0.000, ' 1 wl:PPN2012 1 PPN2012 1 gf:PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 (46)TiO ' +'TiO 1', 5000.0001, 1.1480, 1.0, -1.272, 7.515, 0.000, 0.000, 99.000, 0.000, ' 2 wl:PPN2012 2 PPN2012 2 gf:PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 (47)TiO ' +'TiO 1', 5000.0004, 0.7571, 1.0, -7.569, 7.303, 0.000, 0.000, 99.000, 0.000, ' 1 wl:PPN2012 1 PPN2012 1 gf:PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 (46)TiO ' +'TiO 1', 5000.0005, 2.2125, 1.0, -1.061, 7.458, 0.000, 0.000, 99.000, 0.000, ' 3 wl:PPN2012 3 PPN2012 3 gf:PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 (50)TiO ' +'TiO 1', 5000.0006, 1.8815, 1.0, -2.902, 7.334, 0.000, 0.000, 99.000, 0.000, ' 1 wl:PPN2012 1 PPN2012 1 gf:PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 (46)TiO ' +'TiO 1', 5000.0009, 0.4940, 1.0, -7.607, 6.984, 0.000, 0.000, 99.000, 0.000, ' 4 wl:PPN2012 4 PPN2012 4 gf:PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 (49)TiO ' +'TiO 1', 5000.0012, 0.9250, 1.0, -1.004, 7.315, 0.000, 0.000, 99.000, 0.000, ' 2 wl:PPN2012 2 PPN2012 2 gf:PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 (47)TiO ' +'TiO 1', 5000.0014, 1.0868, 1.0, -2.705, 7.498, 0.000, 0.000, 99.000, 0.000, ' 4 wl:PPN2012 4 PPN2012 4 gf:PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 (49)TiO ' +'TiO 1', 5000.0015, 2.2232, 1.0, -3.025, 7.798, 0.000, 0.000, 99.000, 0.000, ' 3 wl:PPN2012 3 PPN2012 3 gf:PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 (50)TiO ' +'TiO 1', 5000.0016, 0.8186, 1.0, -8.442, 6.951, 0.000, 0.000, 99.000, 0.000, ' 3 wl:PPN2012 3 PPN2012 3 gf:PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 (50)TiO ' +'TiO 1', 5000.0018, 0.8480, 1.0, -5.064, 7.277, 0.000, 0.000, 99.000, 0.000, ' 4 wl:PPN2012 4 PPN2012 4 gf:PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 (49)TiO ' +'TiO 1', 5000.0022, 1.3819, 1.0, -2.434, 7.490, 0.000, 0.000, 99.000, 0.000, ' 4 wl:PPN2012 4 PPN2012 4 gf:PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 (49)TiO ' +'TiO 1', 5000.0025, 0.0222, 1.0, -5.438, 7.209, 0.000, 0.000, 99.000, 0.000, ' 5 wl:PPN2012 5 PPN2012 5 gf:PPN2012 5 PPN2012 5 PPN2012 5 PPN2012 5 PPN2012 (48)TiO ' +'TiO 1', 5000.0025, 1.9329, 1.0, -3.641, 7.384, 0.000, 0.000, 99.000, 0.000, ' 4 wl:PPN2012 4 PPN2012 4 gf:PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 (49)TiO ' +'TiO 1', 5000.0029, 0.8731, 1.0, -1.934, 7.283, 0.000, 0.000, 99.000, 0.000, ' 4 wl:PPN2012 4 PPN2012 4 gf:PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 (49)TiO ' +'TiO 1', 5000.0030, 1.7899, 1.0, -2.793, 7.690, 0.000, 0.000, 99.000, 0.000, ' 4 wl:PPN2012 4 PPN2012 4 gf:PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 (49)TiO ' +'TiO 1', 5000.0030, 0.6844, 1.0, -4.109, 7.361, 0.000, 0.000, 99.000, 0.000, ' 3 wl:PPN2012 3 PPN2012 3 gf:PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 (50)TiO ' +'Cu 1', 5000.0030, 7.1801, 1.0, -6.421, 7.860,-3.960,-7.130, 1.020, 0.000, ' 6 wl:K12 6 K12 6 gf:K12 6 K12 6 K12 6 K12 6 K12 Cu ' +'TiO 1', 5000.0031, 1.0656, 1.0, -2.764, 7.498, 0.000, 0.000, 99.000, 0.000, ' 3 wl:PPN2012 3 PPN2012 3 gf:PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 (50)TiO ' +'TiO 1', 5000.0032, 2.8890, 1.0, -4.657, 7.947, 0.000, 0.000, 99.000, 0.000, ' 1 wl:PPN2012 1 PPN2012 1 gf:PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 (46)TiO ' +'TiO 1', 5000.0035, 0.9717, 1.0, -1.857, 7.365, 0.000, 0.000, 99.000, 0.000, ' 1 wl:PPN2012 1 PPN2012 1 gf:PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 (46)TiO ' +'TiO 1', 5000.0035, 0.1495, 1.0, -1.117, 7.328, 0.000, 0.000, 99.000, 0.000, ' 1 wl:PPN2012 1 PPN2012 1 gf:PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 (46)TiO ' +'TiO 1', 5000.0035, 1.7827, 1.0, -2.620, 7.680, 0.000, 0.000, 99.000, 0.000, ' 1 wl:PPN2012 1 PPN2012 1 gf:PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 (46)TiO ' +'TiO 1', 5000.0035, 2.1819, 1.0, -1.796, 7.441, 0.000, 0.000, 99.000, 0.000, ' 4 wl:PPN2012 4 PPN2012 4 gf:PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 (49)TiO ' +'TiO 1', 5000.0035, 0.0604, 1.0, -3.872, 7.216, 0.000, 0.000, 99.000, 0.000, ' 4 wl:PPN2012 4 PPN2012 4 gf:PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 (49)TiO ' +'TiO 1', 5000.0036, 2.2082, 1.0, -1.237, 7.260, 0.000, 0.000, 99.000, 0.000, ' 2 wl:PPN2012 2 PPN2012 2 gf:PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 (47)TiO ' +'TiO 1', 5000.0038, 0.3914, 1.0, -4.348, 7.212, 0.000, 0.000, 99.000, 0.000, ' 5 wl:PPN2012 5 PPN2012 5 gf:PPN2012 5 PPN2012 5 PPN2012 5 PPN2012 5 PPN2012 (48)TiO ' +'TiO 1', 5000.0038, 1.2937, 1.0, -7.704, 4.872, 0.000, 0.000, 99.000, 0.000, ' 3 wl:PPN2012 3 PPN2012 3 gf:PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 (50)TiO ' +'TiO 1', 5000.0041, 2.1422, 1.0, -2.466, 7.647, 0.000, 0.000, 99.000, 0.000, ' 4 wl:PPN2012 4 PPN2012 4 gf:PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 (49)TiO ' +'TiO 1', 5000.0045, 0.9420, 1.0, -2.060, 7.238, 0.000, 0.000, 99.000, 0.000, ' 4 wl:PPN2012 4 PPN2012 4 gf:PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 (49)TiO ' +'TiO 1', 5000.0046, 1.5301, 1.0, -8.857, 7.293, 0.000, 0.000, 99.000, 0.000, ' 2 wl:PPN2012 2 PPN2012 2 gf:PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 (47)TiO ' +'TiO 1', 5000.0047, 2.1568, 1.0, -2.863, 7.629, 0.000, 0.000, 99.000, 0.000, ' 2 wl:PPN2012 2 PPN2012 2 gf:PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 (47)TiO ' +'TiO 1', 5000.0048, 1.0449, 1.0, -1.721, 7.383, 0.000, 0.000, 99.000, 0.000, ' 4 wl:PPN2012 4 PPN2012 4 gf:PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 (49)TiO ' +'TiO 1', 5000.0049, 1.3958, 1.0, -5.391, 7.244, 0.000, 0.000, 99.000, 0.000, ' 4 wl:PPN2012 4 PPN2012 4 gf:PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 (49)TiO ' +'TiO 1', 5000.0050, 0.9358, 1.0, -8.001, 6.937, 0.000, 0.000, 99.000, 0.000, ' 1 wl:PPN2012 1 PPN2012 1 gf:PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 (46)TiO ' +'TiO 1', 5000.0054, 1.8799, 1.0, -4.020, 7.139, 0.000, 0.000, 99.000, 0.000, ' 1 wl:PPN2012 1 PPN2012 1 gf:PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 (46)TiO ' +'TiO 1', 5000.0059, 0.0730, 1.0, -4.211, 7.214, 0.000, 0.000, 99.000, 0.000, ' 2 wl:PPN2012 2 PPN2012 2 gf:PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 (47)TiO ' +'TiO 1', 5000.0059, 0.5167, 1.0, -7.491, 7.006, 0.000, 0.000, 99.000, 0.000, ' 4 wl:PPN2012 4 PPN2012 4 gf:PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 (49)TiO ' +'TiO 1', 5000.0060, 1.3148, 1.0, -0.503, 7.189, 0.000, 0.000, 99.000, 0.000, ' 5 wl:PPN2012 5 PPN2012 5 gf:PPN2012 5 PPN2012 5 PPN2012 5 PPN2012 5 PPN2012 (48)TiO ' +'TiO 1', 5000.0061, 4.1499, 1.0, -6.524, 7.393, 0.000, 0.000, 99.000, 0.000, ' 1 wl:PPN2012 1 PPN2012 1 gf:PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 (46)TiO ' +'TiO 1', 5000.0062, 1.3234, 1.0, -1.814, 7.347, 0.000, 0.000, 99.000, 0.000, ' 3 wl:PPN2012 3 PPN2012 3 gf:PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 (50)TiO ' +'TiO 1', 5000.0065, 2.7222, 1.0, -1.868, 7.609, 0.000, 0.000, 99.000, 0.000, ' 4 wl:PPN2012 4 PPN2012 4 gf:PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 (49)TiO ' +'TiO 1', 5000.0066, 1.0951, 1.0, -2.656, 7.495, 0.000, 0.000, 99.000, 0.000, ' 1 wl:PPN2012 1 PPN2012 1 gf:PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 (46)TiO ' +'TiO 1', 5000.0069, 2.3015, 1.0, -6.752, 6.811, 0.000, 0.000, 99.000, 0.000, ' 2 wl:PPN2012 2 PPN2012 2 gf:PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 (47)TiO ' +'TiO 1', 5000.0070, 1.6527, 1.0, -3.433, 7.358, 0.000, 0.000, 99.000, 0.000, ' 4 wl:PPN2012 4 PPN2012 4 gf:PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 (49)TiO ' +'TiO 1', 5000.0070, 2.1596, 1.0, -2.977, 7.370, 0.000, 0.000, 99.000, 0.000, ' 3 wl:PPN2012 3 PPN2012 3 gf:PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 (50)TiO ' +'TiO 1', 5000.0071, 1.1374, 1.0, -0.551, 7.237, 0.000, 0.000, 99.000, 0.000, ' 2 wl:PPN2012 2 PPN2012 2 gf:PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 (47)TiO ' +'TiO 1', 5000.0072, 1.4953, 1.0, -0.751, 7.467, 0.000, 0.000, 99.000, 0.000, ' 1 wl:PPN2012 1 PPN2012 1 gf:PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 (46)TiO ' +'TiO 1', 5000.0073, 0.6243, 1.0, -5.450, 7.308, 0.000, 0.000, 99.000, 0.000, ' 2 wl:PPN2012 2 PPN2012 2 gf:PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 (47)TiO ' +'TiO 1', 5000.0075, 1.7202, 1.0, -0.834, 7.191, 0.000, 0.000, 99.000, 0.000, ' 2 wl:PPN2012 2 PPN2012 2 gf:PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 (47)TiO ' +'TiO 1', 5000.0080, 0.5374, 1.0, -9.519, 6.977, 0.000, 0.000, 99.000, 0.000, ' 5 wl:PPN2012 5 PPN2012 5 gf:PPN2012 5 PPN2012 5 PPN2012 5 PPN2012 5 PPN2012 (48)TiO ' +'TiO 1', 5000.0081, 1.4762, 1.0, -1.160, 7.519, 0.000, 0.000, 99.000, 0.000, ' 5 wl:PPN2012 5 PPN2012 5 gf:PPN2012 5 PPN2012 5 PPN2012 5 PPN2012 5 PPN2012 (48)TiO ' +'TiO 1', 5000.0082, 0.9679, 1.0, -4.282, 7.256, 0.000, 0.000, 99.000, 0.000, ' 2 wl:PPN2012 2 PPN2012 2 gf:PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 (47)TiO ' +'TiO 1', 5000.0084, 3.8727, 1.0, -7.626, 7.494, 0.000, 0.000, 99.000, 0.000, ' 2 wl:PPN2012 2 PPN2012 2 gf:PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 (47)TiO ' +'TiO 1', 5000.0084, 0.7659, 1.0, -3.071, 7.279, 0.000, 0.000, 99.000, 0.000, ' 5 wl:PPN2012 5 PPN2012 5 gf:PPN2012 5 PPN2012 5 PPN2012 5 PPN2012 5 PPN2012 (48)TiO ' +'TiO 1', 5000.0087, 1.1468, 1.0, -7.018, 4.855, 0.000, 0.000, 99.000, 0.000, ' 1 wl:PPN2012 1 PPN2012 1 gf:PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 (46)TiO ' +'TiO 1', 5000.0088, 3.0011, 1.0, -0.379, 7.205, 0.000, 0.000, 99.000, 0.000, ' 1 wl:PPN2012 1 PPN2012 1 gf:PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 (46)TiO ' +'TiO 1', 5000.0088, 2.4038, 1.0, -1.023, 7.392, 0.000, 0.000, 99.000, 0.000, ' 5 wl:PPN2012 5 PPN2012 5 gf:PPN2012 5 PPN2012 5 PPN2012 5 PPN2012 5 PPN2012 (48)TiO ' +'TiO 1', 5000.0089, 0.4643, 1.0, -8.038, 5.146, 0.000, 0.000, 99.000, 0.000, ' 5 wl:PPN2012 5 PPN2012 5 gf:PPN2012 5 PPN2012 5 PPN2012 5 PPN2012 5 PPN2012 (48)TiO ' +'TiO 1', 5000.0089, 2.3856, 1.0, -2.360, 7.227, 0.000, 0.000, 99.000, 0.000, ' 3 wl:PPN2012 3 PPN2012 3 gf:PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 (50)TiO ' +'TiO 1', 5000.0090, 2.1990, 1.0, -0.076, 7.328, 0.000, 0.000, 99.000, 0.000, ' 5 wl:PPN2012 5 PPN2012 5 gf:PPN2012 5 PPN2012 5 PPN2012 5 PPN2012 5 PPN2012 (48)TiO ' +'TiO 1', 5000.0090, 0.5995, 1.0, -7.462, 6.981, 0.000, 0.000, 99.000, 0.000, ' 4 wl:PPN2012 4 PPN2012 4 gf:PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 (49)TiO ' +'TiO 1', 5000.0093, 0.1395, 1.0, -0.262, 7.329, 0.000, 0.000, 99.000, 0.000, ' 5 wl:PPN2012 5 PPN2012 5 gf:PPN2012 5 PPN2012 5 PPN2012 5 PPN2012 5 PPN2012 (48)TiO ' +'TiO 1', 5000.0094, 0.3876, 1.0,-10.931, 7.003, 0.000, 0.000, 99.000, 0.000, ' 1 wl:PPN2012 1 PPN2012 1 gf:PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 (46)TiO ' +'TiO 1', 5000.0095, 2.1622, 1.0, -3.005, 7.631, 0.000, 0.000, 99.000, 0.000, ' 3 wl:PPN2012 3 PPN2012 3 gf:PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 (50)TiO ' +'TiO 1', 5000.0096, 1.1479, 1.0, -1.957, 7.513, 0.000, 0.000, 99.000, 0.000, ' 4 wl:PPN2012 4 PPN2012 4 gf:PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 (49)TiO ' +'TiO 1', 5000.0096, 0.6824, 1.0, -7.692, 7.310, 0.000, 0.000, 99.000, 0.000, ' 4 wl:PPN2012 4 PPN2012 4 gf:PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 (49)TiO ' +'TiO 1', 5000.0097, 2.7340, 1.0, -3.337, 7.915, 0.000, 0.000, 99.000, 0.000, ' 2 wl:PPN2012 2 PPN2012 2 gf:PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 (47)TiO ' +'TiO 1', 5000.0099, 3.8559, 1.0, -2.080, 7.199, 0.000, 0.000, 99.000, 0.000, ' 3 wl:PPN2012 3 PPN2012 3 gf:PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 (50)TiO ' +'TiO 1', 5000.0100, 0.6462, 1.0, -3.158, 7.353, 0.000, 0.000, 99.000, 0.000, ' 3 wl:PPN2012 3 PPN2012 3 gf:PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 (50)TiO ' +'TiO 1', 5000.0103, 0.1359, 1.0, -1.935, 7.286, 0.000, 0.000, 99.000, 0.000, ' 2 wl:PPN2012 2 PPN2012 2 gf:PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 (47)TiO ' +'TiO 1', 5000.0104, 0.9532, 1.0, -9.562, 6.642, 0.000, 0.000, 99.000, 0.000, ' 3 wl:PPN2012 3 PPN2012 3 gf:PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 (50)TiO ' +'TiO 1', 5000.0105, 3.7620, 1.0, -9.645, 7.459, 0.000, 0.000, 99.000, 0.000, ' 2 wl:PPN2012 2 PPN2012 2 gf:PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 (47)TiO ' +'MgH 1', 5000.0105, 0.5786, 1.0, -1.563, 7.060, 0.000, 0.000, 99.000, 0.000, ' 7 wl:KMGH 7 KMGH 7 gf:KMGH 7 KMGH 7 KMGH 7 KMGH 7 KMGH (24)MgH ' +'MgH 1', 5000.0105, 0.5786, 1.0, -1.607, 7.060, 0.000, 0.000, 99.000, 0.000, ' 7 wl:KMGH 7 KMGH 7 gf:KMGH 7 KMGH 7 KMGH 7 KMGH 7 KMGH (24)MgH ' +'TiO 1', 5000.0108, 0.4210, 1.0, -9.028, 5.127, 0.000, 0.000, 99.000, 0.000, ' 1 wl:PPN2012 1 PPN2012 1 gf:PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 (46)TiO ' +'TiO 1', 5000.0108, 1.6461, 1.0, -7.175, 7.223, 0.000, 0.000, 99.000, 0.000, ' 4 wl:PPN2012 4 PPN2012 4 gf:PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 (49)TiO ' +'TiO 1', 5000.0109, 0.4622, 1.0,-12.318, 6.989, 0.000, 0.000, 99.000, 0.000, ' 3 wl:PPN2012 3 PPN2012 3 gf:PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 (50)TiO ' +'TiO 1', 5000.0110, 0.0997, 1.0, -4.482, 7.212, 0.000, 0.000, 99.000, 0.000, ' 2 wl:PPN2012 2 PPN2012 2 gf:PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 (47)TiO ' +'TiO 1', 5000.0110, 1.5325, 1.0, -4.234, 7.183, 0.000, 0.000, 99.000, 0.000, ' 3 wl:PPN2012 3 PPN2012 3 gf:PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 (50)TiO ' +'TiO 1', 5000.0113, 3.4334, 1.0,-10.617, 7.427, 0.000, 0.000, 99.000, 0.000, ' 4 wl:PPN2012 4 PPN2012 4 gf:PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 (49)TiO ' +'TiO 1', 5000.0113, 1.6526, 1.0, -3.977, 7.311, 0.000, 0.000, 99.000, 0.000, ' 3 wl:PPN2012 3 PPN2012 3 gf:PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 (50)TiO ' +'TiO 1', 5000.0115, 0.6157, 1.0, -2.540, 7.344, 0.000, 0.000, 99.000, 0.000, ' 2 wl:PPN2012 2 PPN2012 2 gf:PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 (47)TiO ' +'TiO 1', 5000.0115, 0.6931, 1.0, -4.541, 7.295, 0.000, 0.000, 99.000, 0.000, ' 3 wl:PPN2012 3 PPN2012 3 gf:PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 (50)TiO ' +'TiO 1', 5000.0116, 1.0080, 1.0, -0.951, 7.260, 0.000, 0.000, 99.000, 0.000, ' 1 wl:PPN2012 1 PPN2012 1 gf:PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 1 PPN2012 (46)TiO ' +'TiO 1', 5000.0117, 0.4313, 1.0, -2.152, 7.243, 0.000, 0.000, 99.000, 0.000, ' 5 wl:PPN2012 5 PPN2012 5 gf:PPN2012 5 PPN2012 5 PPN2012 5 PPN2012 5 PPN2012 (48)TiO ' +'TiO 1', 5000.0119, 1.1631, 1.0, -4.933, 7.241, 0.000, 0.000, 99.000, 0.000, ' 3 wl:PPN2012 3 PPN2012 3 gf:PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 (50)TiO ' +'TiO 1', 5000.0120, 1.7689, 1.0, -8.282, 7.328, 0.000, 0.000, 99.000, 0.000, ' 2 wl:PPN2012 2 PPN2012 2 gf:PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 2 PPN2012 (47)TiO ' +'TiO 1', 5000.0120, 0.0328, 1.0, -4.684, 7.213, 0.000, 0.000, 99.000, 0.000, ' 4 wl:PPN2012 4 PPN2012 4 gf:PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 4 PPN2012 (49)TiO ' +'TiO 1', 5000.0120, 1.0451, 1.0, -1.817, 7.331, 0.000, 0.000, 99.000, 0.000, ' 3 wl:PPN2012 3 PPN2012 3 gf:PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 (50)TiO ' +'TiO 1', 5000.0121, 1.3185, 1.0, -3.583, 7.358, 0.000, 0.000, 99.000, 0.000, ' 3 wl:PPN2012 3 PPN2012 3 gf:PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 (50)TiO ' +'TiO 1', 5000.0121, 1.3328, 1.0,-11.820, 5.122, 0.000, 0.000, 99.000, 0.000, ' 3 wl:PPN2012 3 PPN2012 3 gf:PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 (50)TiO ' +'C2 1', 5000.0121, 1.4581, 1.0, -4.888, 6.770, 0.000, 0.000, 99.000, 0.000, ' 8 wl:BBSB 8 BBSB 8 gf:BBSB 8 BBSB 8 BBSB 8 BBSB 8 BBSB (12)C(12)C ' +'TiO 1', 5000.0129, 2.6943, 1.0, -3.443, 7.446, 0.000, 0.000, 99.000, 0.000, ' 3 wl:PPN2012 3 PPN2012 3 gf:PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 (50)TiO ' +'TiO 1', 5000.0129, 1.7099, 1.0, -5.479, 7.214, 0.000, 0.000, 99.000, 0.000, ' 3 wl:PPN2012 3 PPN2012 3 gf:PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 3 PPN2012 (50)TiO ' +'TiO 1', 5000.0131, 2.6873, 1.0, -0.135, 7.086, 0.000, 0.000, 99.000, 0.000, ' 5 wl:PPN2012 5 PPN2012 5 gf:PPN2012 5 PPN2012 5 PPN2012 5 PPN2012 5 PPN2012 (48)TiO ' diff --git a/docs/io/vald.ipynb b/docs/io/vald.ipynb new file mode 100644 index 000000000..d55541d97 --- /dev/null +++ b/docs/io/vald.ipynb @@ -0,0 +1,667 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## VALD\n", + "VALD is a database of atomic and molecular transitions used to create accurate synthetic spectra of many astrophysical systems. More information, as well as linelists can be downloaded from the [VALD website](http://vald.astro.uu.se/~vald/php/vald.ph).\n", + "\n", + "In this example, data was downloaded from the [VALD website](http://vald.astro.uu.se/) and extracted to /tmp/vald_sample_linelist.dat" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**_NOTE:_** " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from carsus.io.vald import VALDReader" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "vald_reader = VALDReader(fname='/tmp/vald_sample_linelist.dat')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Table information is parsed to a dataframe which can be accesed via the .vald attribute. The column information is described in https://articles.adsabs.harvard.edu/pdf/1995A%26AS..112..525P and is as follows:\n", + "\n", + "Wavelength - either air or vacuum and in nanometers or angstroms: Wavelength of the line\n", + "\n", + "log_gf: Log10 of the oscillator strength times the degeneracy of the lower level\n", + "\n", + "e_low: Excitation energy of the lower level in ergs\n", + "\n", + "j_lo: Principal quantum number of the lower level\n", + "\n", + "e_up: Excitation energy of the upper level in ergs\n", + "\n", + "j_up: Principal quantum number of the upper level\n", + "\n", + "lande_lower: Lande factor of the lower level\n", + "\n", + "lande_upper: Lande factor of the upper level\n", + "\n", + "lande_mean: Mean lande factor\n", + "\n", + "rad: log10 of the radiation damping constant in $(4\\pi s)^{-1}$\n", + "\n", + "stark: log10 of the Stark damping constant at 10,000K in $(4\\pi s N_e)^{-1}$\n", + "\n", + "waals: log10 of the Van Der Waals damping constant at 10,000K in $(4\\pi s N_H)^{-1}$" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[\u001b[1m carsus.io.vald.vald\u001b[0m][ \u001b[1;37mINFO\u001b[0m] - Parsing VALD from: /tmp/vald_sample_linelist.dat (\u001b[1mvald.py\u001b[0m:149)\n", + "[\u001b[1m carsus.io.vald.vald\u001b[0m][ \u001b[1;37mINFO\u001b[0m] - Found wavelength column header: WL_air(A) (\u001b[1mvald.py\u001b[0m:167)\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
WL_air(A)log_gfe_lowj_loe_upj_uplande_lowerlande_upperlande_meanradstarkwaalschemicalion_chargewavelengthatomic_number
04100.00538-1.1698.12932.011.15243.01.041.000.968.70-6.47-7.860Mn14101.16258625
14100.04321-5.99210.46731.513.49042.52.281.540.998.94-5.86-7.630Fe14101.20042626
24100.04405-0.44016.82732.019.85041.01.401.481.369.48-5.99-7.710Ti24101.20126622
34100.04800-0.72551.01683.554.03994.599.0099.0099.0010.000.000.000He14101.2052172
44100.04910-7.28715.23752.018.26061.01.473.000.719.47-6.35-7.850Fe24101.20631826
...................................................
9904109.94851-5.4283.84702.06.86283.01.160.950.758.10-6.16-7.750Cr04111.10832124
9914109.94900-1.22710.69001.513.70582.599.0099.0099.000.000.00-7.419N04111.1088117
9924109.95324-2.6714.62442.07.64021.01.000.831.087.47-2.75-6.710Ca04111.11305220
9934109.96777-4.84813.93605.016.95185.01.381.201.298.44-5.18-7.500Cu14111.12758629
9944109.98163-3.4414.53514.07.55093.01.071.250.797.61-4.43-7.320Cr04111.14144924
\n", + "

995 rows × 16 columns

\n", + "
" + ], + "text/plain": [ + " WL_air(A) log_gf e_low j_lo e_up j_up lande_lower \\\n", + "0 4100.00538 -1.169 8.1293 2.0 11.1524 3.0 1.04 \n", + "1 4100.04321 -5.992 10.4673 1.5 13.4904 2.5 2.28 \n", + "2 4100.04405 -0.440 16.8273 2.0 19.8504 1.0 1.40 \n", + "3 4100.04800 -0.725 51.0168 3.5 54.0399 4.5 99.00 \n", + "4 4100.04910 -7.287 15.2375 2.0 18.2606 1.0 1.47 \n", + ".. ... ... ... ... ... ... ... \n", + "990 4109.94851 -5.428 3.8470 2.0 6.8628 3.0 1.16 \n", + "991 4109.94900 -1.227 10.6900 1.5 13.7058 2.5 99.00 \n", + "992 4109.95324 -2.671 4.6244 2.0 7.6402 1.0 1.00 \n", + "993 4109.96777 -4.848 13.9360 5.0 16.9518 5.0 1.38 \n", + "994 4109.98163 -3.441 4.5351 4.0 7.5509 3.0 1.07 \n", + "\n", + " lande_upper lande_mean rad stark waals chemical ion_charge \\\n", + "0 1.00 0.96 8.70 -6.47 -7.860 Mn 1 \n", + "1 1.54 0.99 8.94 -5.86 -7.630 Fe 1 \n", + "2 1.48 1.36 9.48 -5.99 -7.710 Ti 2 \n", + "3 99.00 99.00 10.00 0.00 0.000 He 1 \n", + "4 3.00 0.71 9.47 -6.35 -7.850 Fe 2 \n", + ".. ... ... ... ... ... ... ... \n", + "990 0.95 0.75 8.10 -6.16 -7.750 Cr 0 \n", + "991 99.00 99.00 0.00 0.00 -7.419 N 0 \n", + "992 0.83 1.08 7.47 -2.75 -6.710 Ca 0 \n", + "993 1.20 1.29 8.44 -5.18 -7.500 Cu 1 \n", + "994 1.25 0.79 7.61 -4.43 -7.320 Cr 0 \n", + "\n", + " wavelength atomic_number \n", + "0 4101.162586 25 \n", + "1 4101.200426 26 \n", + "2 4101.201266 22 \n", + "3 4101.205217 2 \n", + "4 4101.206318 26 \n", + ".. ... ... \n", + "990 4111.108321 24 \n", + "991 4111.108811 7 \n", + "992 4111.113052 20 \n", + "993 4111.127586 29 \n", + "994 4111.141449 24 \n", + "\n", + "[995 rows x 16 columns]" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vald_reader.vald" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The specific relevant information is extracted and prepared as a linelist in the .linelist attribute.\n", + "\n", + "Note that the wavelengths here are reformated to Angstroms and in vacuum wavelengths." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
atomic_numberion_chargewavelengthlog_gfe_lowe_upj_loj_upradstarkwaals
02514101.162586-1.1698.129311.15242.03.08.70-6.47-7.860
12614101.200426-5.99210.467313.49041.52.58.94-5.86-7.630
22224101.201266-0.44016.827319.85042.01.09.48-5.99-7.710
3214101.205217-0.72551.016854.03993.54.510.000.000.000
42624101.206318-7.28715.237518.26062.01.09.47-6.35-7.850
....................................
9902404111.108321-5.4283.84706.86282.03.08.10-6.16-7.750
991704111.108811-1.22710.690013.70581.52.50.000.00-7.419
9922004111.113052-2.6714.62447.64022.01.07.47-2.75-6.710
9932914111.127586-4.84813.936016.95185.05.08.44-5.18-7.500
9942404111.141449-3.4414.53517.55094.03.07.61-4.43-7.320
\n", + "

995 rows × 11 columns

\n", + "
" + ], + "text/plain": [ + " atomic_number ion_charge wavelength log_gf e_low e_up j_lo \\\n", + "0 25 1 4101.162586 -1.169 8.1293 11.1524 2.0 \n", + "1 26 1 4101.200426 -5.992 10.4673 13.4904 1.5 \n", + "2 22 2 4101.201266 -0.440 16.8273 19.8504 2.0 \n", + "3 2 1 4101.205217 -0.725 51.0168 54.0399 3.5 \n", + "4 26 2 4101.206318 -7.287 15.2375 18.2606 2.0 \n", + ".. ... ... ... ... ... ... ... \n", + "990 24 0 4111.108321 -5.428 3.8470 6.8628 2.0 \n", + "991 7 0 4111.108811 -1.227 10.6900 13.7058 1.5 \n", + "992 20 0 4111.113052 -2.671 4.6244 7.6402 2.0 \n", + "993 29 1 4111.127586 -4.848 13.9360 16.9518 5.0 \n", + "994 24 0 4111.141449 -3.441 4.5351 7.5509 4.0 \n", + "\n", + " j_up rad stark waals \n", + "0 3.0 8.70 -6.47 -7.860 \n", + "1 2.5 8.94 -5.86 -7.630 \n", + "2 1.0 9.48 -5.99 -7.710 \n", + "3 4.5 10.00 0.00 0.000 \n", + "4 1.0 9.47 -6.35 -7.850 \n", + ".. ... ... ... ... \n", + "990 3.0 8.10 -6.16 -7.750 \n", + "991 2.5 0.00 0.00 -7.419 \n", + "992 1.0 7.47 -2.75 -6.710 \n", + "993 5.0 8.44 -5.18 -7.500 \n", + "994 3.0 7.61 -4.43 -7.320 \n", + "\n", + "[995 rows x 11 columns]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vald_reader.linelist" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "carsus", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.16" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +}