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", + " | WL_air(A) | \n", + "log_gf | \n", + "e_low | \n", + "j_lo | \n", + "e_up | \n", + "j_up | \n", + "lande_lower | \n", + "lande_upper | \n", + "lande_mean | \n", + "rad | \n", + "stark | \n", + "waals | \n", + "chemical | \n", + "ion_charge | \n", + "wavelength | \n", + "atomic_number | \n", + "
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | \n", + "4100.00538 | \n", + "-1.169 | \n", + "8.1293 | \n", + "2.0 | \n", + "11.1524 | \n", + "3.0 | \n", + "1.04 | \n", + "1.00 | \n", + "0.96 | \n", + "8.70 | \n", + "-6.47 | \n", + "-7.860 | \n", + "Mn | \n", + "1 | \n", + "4101.162586 | \n", + "25 | \n", + "
1 | \n", + "4100.04321 | \n", + "-5.992 | \n", + "10.4673 | \n", + "1.5 | \n", + "13.4904 | \n", + "2.5 | \n", + "2.28 | \n", + "1.54 | \n", + "0.99 | \n", + "8.94 | \n", + "-5.86 | \n", + "-7.630 | \n", + "Fe | \n", + "1 | \n", + "4101.200426 | \n", + "26 | \n", + "
2 | \n", + "4100.04405 | \n", + "-0.440 | \n", + "16.8273 | \n", + "2.0 | \n", + "19.8504 | \n", + "1.0 | \n", + "1.40 | \n", + "1.48 | \n", + "1.36 | \n", + "9.48 | \n", + "-5.99 | \n", + "-7.710 | \n", + "Ti | \n", + "2 | \n", + "4101.201266 | \n", + "22 | \n", + "
3 | \n", + "4100.04800 | \n", + "-0.725 | \n", + "51.0168 | \n", + "3.5 | \n", + "54.0399 | \n", + "4.5 | \n", + "99.00 | \n", + "99.00 | \n", + "99.00 | \n", + "10.00 | \n", + "0.00 | \n", + "0.000 | \n", + "He | \n", + "1 | \n", + "4101.205217 | \n", + "2 | \n", + "
4 | \n", + "4100.04910 | \n", + "-7.287 | \n", + "15.2375 | \n", + "2.0 | \n", + "18.2606 | \n", + "1.0 | \n", + "1.47 | \n", + "3.00 | \n", + "0.71 | \n", + "9.47 | \n", + "-6.35 | \n", + "-7.850 | \n", + "Fe | \n", + "2 | \n", + "4101.206318 | \n", + "26 | \n", + "
... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "
990 | \n", + "4109.94851 | \n", + "-5.428 | \n", + "3.8470 | \n", + "2.0 | \n", + "6.8628 | \n", + "3.0 | \n", + "1.16 | \n", + "0.95 | \n", + "0.75 | \n", + "8.10 | \n", + "-6.16 | \n", + "-7.750 | \n", + "Cr | \n", + "0 | \n", + "4111.108321 | \n", + "24 | \n", + "
991 | \n", + "4109.94900 | \n", + "-1.227 | \n", + "10.6900 | \n", + "1.5 | \n", + "13.7058 | \n", + "2.5 | \n", + "99.00 | \n", + "99.00 | \n", + "99.00 | \n", + "0.00 | \n", + "0.00 | \n", + "-7.419 | \n", + "N | \n", + "0 | \n", + "4111.108811 | \n", + "7 | \n", + "
992 | \n", + "4109.95324 | \n", + "-2.671 | \n", + "4.6244 | \n", + "2.0 | \n", + "7.6402 | \n", + "1.0 | \n", + "1.00 | \n", + "0.83 | \n", + "1.08 | \n", + "7.47 | \n", + "-2.75 | \n", + "-6.710 | \n", + "Ca | \n", + "0 | \n", + "4111.113052 | \n", + "20 | \n", + "
993 | \n", + "4109.96777 | \n", + "-4.848 | \n", + "13.9360 | \n", + "5.0 | \n", + "16.9518 | \n", + "5.0 | \n", + "1.38 | \n", + "1.20 | \n", + "1.29 | \n", + "8.44 | \n", + "-5.18 | \n", + "-7.500 | \n", + "Cu | \n", + "1 | \n", + "4111.127586 | \n", + "29 | \n", + "
994 | \n", + "4109.98163 | \n", + "-3.441 | \n", + "4.5351 | \n", + "4.0 | \n", + "7.5509 | \n", + "3.0 | \n", + "1.07 | \n", + "1.25 | \n", + "0.79 | \n", + "7.61 | \n", + "-4.43 | \n", + "-7.320 | \n", + "Cr | \n", + "0 | \n", + "4111.141449 | \n", + "24 | \n", + "
995 rows × 16 columns
\n", + "\n", + " | atomic_number | \n", + "ion_charge | \n", + "wavelength | \n", + "log_gf | \n", + "e_low | \n", + "e_up | \n", + "j_lo | \n", + "j_up | \n", + "rad | \n", + "stark | \n", + "waals | \n", + "
---|---|---|---|---|---|---|---|---|---|---|---|
0 | \n", + "25 | \n", + "1 | \n", + "4101.162586 | \n", + "-1.169 | \n", + "8.1293 | \n", + "11.1524 | \n", + "2.0 | \n", + "3.0 | \n", + "8.70 | \n", + "-6.47 | \n", + "-7.860 | \n", + "
1 | \n", + "26 | \n", + "1 | \n", + "4101.200426 | \n", + "-5.992 | \n", + "10.4673 | \n", + "13.4904 | \n", + "1.5 | \n", + "2.5 | \n", + "8.94 | \n", + "-5.86 | \n", + "-7.630 | \n", + "
2 | \n", + "22 | \n", + "2 | \n", + "4101.201266 | \n", + "-0.440 | \n", + "16.8273 | \n", + "19.8504 | \n", + "2.0 | \n", + "1.0 | \n", + "9.48 | \n", + "-5.99 | \n", + "-7.710 | \n", + "
3 | \n", + "2 | \n", + "1 | \n", + "4101.205217 | \n", + "-0.725 | \n", + "51.0168 | \n", + "54.0399 | \n", + "3.5 | \n", + "4.5 | \n", + "10.00 | \n", + "0.00 | \n", + "0.000 | \n", + "
4 | \n", + "26 | \n", + "2 | \n", + "4101.206318 | \n", + "-7.287 | \n", + "15.2375 | \n", + "18.2606 | \n", + "2.0 | \n", + "1.0 | \n", + "9.47 | \n", + "-6.35 | \n", + "-7.850 | \n", + "
... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "
990 | \n", + "24 | \n", + "0 | \n", + "4111.108321 | \n", + "-5.428 | \n", + "3.8470 | \n", + "6.8628 | \n", + "2.0 | \n", + "3.0 | \n", + "8.10 | \n", + "-6.16 | \n", + "-7.750 | \n", + "
991 | \n", + "7 | \n", + "0 | \n", + "4111.108811 | \n", + "-1.227 | \n", + "10.6900 | \n", + "13.7058 | \n", + "1.5 | \n", + "2.5 | \n", + "0.00 | \n", + "0.00 | \n", + "-7.419 | \n", + "
992 | \n", + "20 | \n", + "0 | \n", + "4111.113052 | \n", + "-2.671 | \n", + "4.6244 | \n", + "7.6402 | \n", + "2.0 | \n", + "1.0 | \n", + "7.47 | \n", + "-2.75 | \n", + "-6.710 | \n", + "
993 | \n", + "29 | \n", + "1 | \n", + "4111.127586 | \n", + "-4.848 | \n", + "13.9360 | \n", + "16.9518 | \n", + "5.0 | \n", + "5.0 | \n", + "8.44 | \n", + "-5.18 | \n", + "-7.500 | \n", + "
994 | \n", + "24 | \n", + "0 | \n", + "4111.141449 | \n", + "-3.441 | \n", + "4.5351 | \n", + "7.5509 | \n", + "4.0 | \n", + "3.0 | \n", + "7.61 | \n", + "-4.43 | \n", + "-7.320 | \n", + "
995 rows × 11 columns
\n", + "