Пример #1
0
def add_btnextgen(input_path, database, wl_bound, teff_bound, specres):
    """
    Function for adding the BT-NextGen atmospheric models to the database.

    Parameters
    ----------
    input_path : str
        Folder where the data is located.
    database : h5py._hl.files.File
        Database.
    wl_bound : tuple(float, float)
        Wavelength range (micron).
    teff_bound : tuple(float, float), None
        Effective temperature range (K).
    specres : float
        Spectral resolution.

    Returns
    -------
    NoneType
        None
    """

    if not wl_bound:
        wl_bound = (1e-2, 1e2)

    if not os.path.exists(input_path):
        os.makedirs(input_path)

    data_folder = os.path.join(input_path, 'bt-nextgen/')

    files = [
        'BT-NextGen_M-0.0_a+0.0_hot.tar', 'BT-NextGen_M+0.3_a+0.0_hot.tar',
        'BT-NextGen_M+0.5_a+0.0_hot.tar'
    ]

    urls = [
        'https://phoenix.ens-lyon.fr/Grids/BT-NextGen/SPECTRA/BT-NextGen_M-0.0_a+0.0_hot.tar',
        'https://phoenix.ens-lyon.fr/Grids/BT-NextGen/SPECTRA/BT-NextGen_M+0.3_a+0.0_hot.tar',
        'https://phoenix.ens-lyon.fr/Grids/BT-NextGen/SPECTRA/BT-NextGen_M+0.5_a+0.0_hot.tar'
    ]

    labels = [
        '[Fe/H]=0.0 (5.9 GB)', '[Fe/H]=0.3 (6.2 GB)', '[Fe/H]=0.5 (6.4 GB)'
    ]

    for i, item in enumerate(files):
        data_file = os.path.join(input_path, item)

        if not os.path.isfile(data_file):
            sys.stdout.write('Downloading BT-NextGen model spectra ' +
                             labels[i] + '...')
            sys.stdout.flush()

            urlretrieve(urls[i], data_file)

            sys.stdout.write(' [DONE]\n')
            sys.stdout.flush()

        sys.stdout.write('Unpacking BT-NextGen model spectra ' + labels[i] +
                         '...')
        sys.stdout.flush()

        tar = tarfile.open(data_file)
        tar.extractall(data_folder)
        tar.close()

        sys.stdout.write(' [DONE]\n')
        sys.stdout.flush()

    teff = []
    logg = []
    feh = []
    flux = []

    wavelength = [wl_bound[0]]

    while wavelength[-1] <= wl_bound[1]:
        wavelength.append(wavelength[-1] + wavelength[-1] / specres)

    wavelength = np.asarray(wavelength[:-1])

    for _, _, file_list in os.walk(data_folder):
        for filename in sorted(file_list):

            if filename.startswith('lte') and filename.endswith('.7.bz2'):
                sys.stdout.write('\rAdding BT-NextGen model spectra... ' +
                                 filename)
                sys.stdout.flush()

                teff_val = float(filename[3:6]) * 100.

                if teff_bound is not None:

                    if teff_bound[0] <= teff_val <= teff_bound[1]:
                        teff.append(teff_val)
                        logg.append(float(filename[7:9]))
                        feh.append(float(filename[11:14]))

                    else:
                        continue

                dataf = pd.pandas.read_csv(data_folder + filename,
                                           usecols=[0, 1],
                                           names=['wavelength', 'flux'],
                                           header=None,
                                           dtype={
                                               'wavelength': str,
                                               'flux': str
                                           },
                                           delim_whitespace=True,
                                           compression='bz2')

                dataf['wavelength'] = dataf['wavelength'].str.replace('D', 'E')
                dataf['flux'] = dataf['flux'].str.replace('D', 'E')

                dataf = dataf.apply(pd.to_numeric)
                data = dataf.values

                # [Angstrom] -> [micron]
                data_wavel = data[:, 0] * 1e-4

                # See https://phoenix.ens-lyon.fr/Grids/FORMAT
                data_flux = 10.**(data[:, 1] - 8.)  # [erg s-1 cm-2 Angstrom-1]

                # [erg s-1 cm-2 Angstrom-1] -> [W m-2 micron-1]
                data_flux = data_flux * 1e-7 * 1e4 * 1e4

                data = np.stack((data_wavel, data_flux), axis=0)

                index_sort = np.argsort(data[0, :])
                data = data[:, index_sort]

                if np.all(np.diff(data[0, :]) < 0):
                    raise ValueError(
                        'The wavelengths are not all sorted by increasing value.'
                    )

                indices = np.where((data[0, :] >= wl_bound[0])
                                   & (data[0, :] <= wl_bound[1]))[0]

                data = data[:, indices]

                flux_interp = interp1d(data[0, :],
                                       data[1, :],
                                       kind='linear',
                                       bounds_error=False,
                                       fill_value=1e-100)

                flux.append(flux_interp(wavelength))

    data_sorted = data_util.sort_data(np.asarray(teff), np.asarray(logg),
                                      np.asarray(feh), wavelength,
                                      np.asarray(flux))

    data_util.write_data('bt-nextgen', ('teff', 'logg', 'feh'), database,
                         data_sorted)

    sys.stdout.write('\rAdding BT-NextGen model spectra... [DONE]'
                     '                              \n')

    sys.stdout.flush()
Пример #2
0
def add_btsettl(input_path: str, database: h5py._hl.files.File,
                wavel_range: Optional[Tuple[float, float]],
                teff_range: Optional[Tuple[float, float]],
                spec_res: Optional[float]) -> None:
    """
    Function for adding the BT-Settl atmospheric models (solar metallicity) to the database.
    The spectra had been downloaded from the Theoretical spectra web server
    (http://svo2.cab.inta-csic.es/svo/theory/newov2/index.php?models=bt-settl) and resampled
    to a spectral resolution of 5000 from 0.1 to 100 um.

    Parameters
    ----------
    input_path : str
        Folder where the data is located.
    database : h5py._hl.files.File
        Database.
    wavel_range : tuple(float, float), None
        Wavelength range (um). The original wavelength points are used if set to ``None``.
    teff_range : tuple(float, float), None
        Effective temperature range (K). All temperatures are selected if set to ``None``.
    spec_res : float, None
        Spectral resolution. Not used if ``wavel_range`` is set to ``None``.

    Returns
    -------
    NoneType
        None
    """

    if not os.path.exists(input_path):
        os.makedirs(input_path)

    input_file = 'bt-settl.tgz'

    data_folder = os.path.join(input_path, 'bt-settl/')
    data_file = os.path.join(input_path, input_file)

    if not os.path.exists(data_folder):
        os.makedirs(data_folder)

    url = 'https://people.phys.ethz.ch/~ipa/tstolker/bt-settl.tgz'

    if not os.path.isfile(data_file):
        print('Downloading Bt-Settl model spectra (130 MB)...',
              end='',
              flush=True)
        urllib.request.urlretrieve(url, data_file)
        print(' [DONE]')

    print('Unpacking BT-Settl model spectra (130 MB)...', end='', flush=True)
    tar = tarfile.open(data_file)
    tar.extractall(data_folder)
    tar.close()
    print(' [DONE]')

    teff = []
    logg = []
    flux = []

    if wavel_range is not None and spec_res is not None:
        wavelength = read_util.create_wavelengths(wavel_range, spec_res)
    else:
        wavelength = None

    for _, _, file_list in os.walk(data_folder):
        for filename in sorted(file_list):
            if filename[:9] == 'bt-settl_':
                file_split = filename.split('_')

                teff_val = float(file_split[2])
                logg_val = float(file_split[4])

                if teff_range is not None:
                    if teff_val < teff_range[0] or teff_val > teff_range[1]:
                        continue

                print_message = f'Adding BT-Settl model spectra... {filename}'
                print(f'\r{print_message:<69}', end='')

                data_wavel, data_flux = np.loadtxt(os.path.join(
                    data_folder, filename),
                                                   unpack=True)

                teff.append(teff_val)
                logg.append(logg_val)

                if wavel_range is None or spec_res is None:
                    if wavelength is None:
                        wavelength = np.copy(data_wavel)  # (um)

                    if np.all(np.diff(wavelength) < 0):
                        raise ValueError(
                            'The wavelengths are not all sorted by increasing value.'
                        )

                    flux.append(data_flux)  # (W m-2 um-1)

                else:
                    flux_resample = spectres.spectres(wavelength,
                                                      data_wavel,
                                                      data_flux,
                                                      spec_errs=None,
                                                      fill=np.nan,
                                                      verbose=False)

                    if np.isnan(np.sum(flux_resample)):
                        raise ValueError(
                            f'Resampling is only possible if the new wavelength '
                            f'range ({wavelength[0]} - {wavelength[-1]} um) falls '
                            f'sufficiently far within the wavelength range '
                            f'({data_wavel[0]} - {data_wavel[-1]} um) of the input '
                            f'spectra.')

                    flux.append(flux_resample)  # (W m-2 um-1)

    print_message = 'Adding BT-Settl model spectra... [DONE]'
    print(f'\r{print_message:<69}')

    data_sorted = data_util.sort_data(np.asarray(teff), np.asarray(logg), None,
                                      None, None, wavelength, np.asarray(flux))

    data_util.write_data('bt-settl', ['teff', 'logg'], database, data_sorted)
Пример #3
0
def add_drift_phoenix(input_path: str,
                      database: h5py._hl.files.File,
                      wavel_range: Optional[Tuple[float, float]] = None,
                      teff_range: Optional[Tuple[float, float]] = None,
                      spec_res: float = None) -> None:
    """
    Function for adding the DRIFT-PHOENIX atmospheric models to the database. The original spectra
    were downloaded from http://svo2.cab.inta-csic.es/theory/newov2/index.php?models=drift and have
    been resampled to a spectral resolution of R = 2000 from 0.1 to 50 um.

    Parameters
    ----------
    input_path : str
        Folder where the data is located.
    database : h5py._hl.files.File
        Database.
    wavel_range : tuple(float, float), None
        Wavelength range (um). The full wavelength range (0.1-50 um) is stored if set to ``None``.
        Only used in combination with ``spec_res``.
    teff_range : tuple(float, float), None
        Effective temperature range (K). All available temperatures are stored if set to ``None``.
    spec_res : float, None
        Spectral resolution. The data is stored with the spectral resolution of the input spectra
        (R = 2000) if set to ``None``. Only used in combination with ``wavel_range``.

    Returns
    -------
    NoneType
        None
    """

    if not os.path.exists(input_path):
        os.makedirs(input_path)

    input_file = 'drift-phoenix.tgz'
    url = 'https://people.phys.ethz.ch/~ipa/tstolker/drift-phoenix.tgz'

    data_folder = os.path.join(input_path, 'drift-phoenix/')
    data_file = os.path.join(input_path, input_file)

    if not os.path.exists(data_folder):
        os.makedirs(data_folder)

    if not os.path.isfile(data_file):
        print('Downloading DRIFT-PHOENIX model spectra (229 MB)...',
              end='',
              flush=True)
        urllib.request.urlretrieve(url, data_file)
        print(' [DONE]')

    print('Unpacking DRIFT-PHOENIX model spectra (229 MB)...',
          end='',
          flush=True)
    tar = tarfile.open(data_file)
    tar.extractall(data_folder)
    tar.close()
    print(' [DONE]')

    teff = []
    logg = []
    feh = []
    flux = []

    if wavel_range is not None and spec_res is not None:
        wavelength = read_util.create_wavelengths(wavel_range, spec_res)
    else:
        wavelength = None

    for _, _, files in os.walk(data_folder):
        for filename in files:
            if filename[:14] == 'drift-phoenix_':
                file_split = filename.split('_')

                teff_val = float(file_split[2])
                logg_val = float(file_split[4])
                feh_val = float(file_split[6])

                if teff_range is not None:
                    if teff_val < teff_range[0] or teff_val > teff_range[1]:
                        continue

                print_message = f'Adding DRIFT-PHOENIX model spectra... {filename}'
                print(f'\r{print_message:<88}', end='')

                data_wavel, data_flux = np.loadtxt(os.path.join(
                    data_folder, filename),
                                                   unpack=True)

                teff.append(teff_val)
                logg.append(logg_val)
                feh.append(feh_val)

                if wavel_range is None or spec_res is None:
                    if wavelength is None:
                        wavelength = np.copy(data_wavel)  # (um)

                    if np.all(np.diff(wavelength) < 0):
                        raise ValueError(
                            'The wavelengths are not all sorted by increasing value.'
                        )

                    flux.append(data_flux)  # (W m-2 um-1)

                else:
                    flux_resample = spectres.spectres(wavelength,
                                                      data_wavel,
                                                      data_flux,
                                                      spec_errs=None,
                                                      fill=np.nan,
                                                      verbose=False)

                    if np.isnan(np.sum(flux_resample)):
                        raise ValueError(
                            f'Resampling is only possible if the new wavelength '
                            f'range ({wavelength[0]} - {wavelength[-1]} um) falls '
                            f'sufficiently far within the wavelength range '
                            f'({data_wavel[0]} - {data_wavel[-1]} um) of the input '
                            f'spectra.')

                    flux.append(flux_resample)  # (W m-2 um-1)

    print_message = 'Adding DRIFT-PHOENIX model spectra... [DONE]'
    print(f'\r{print_message:<88}')

    data_sorted = data_util.sort_data(np.asarray(teff), np.asarray(logg),
                                      np.asarray(feh), None, None, wavelength,
                                      np.asarray(flux))

    data_util.write_data('drift-phoenix', ['teff', 'logg', 'feh'], database,
                         data_sorted)
Пример #4
0
def add_ames_dusty(input_path: str,
                   database: h5py._hl.files.File,
                   wavel_range: Optional[Tuple[float, float]] = None,
                   teff_range: Optional[Tuple[float, float]] = None,
                   spec_res: float = None) -> None:
    """
    Function for adding the AMES-Dusty atmospheric models to the database. The original spectra
    have been resampled to a spectral resolution of R = 2000 from 0.5 to 40 um. Note that a few
    of the spectra contain NaNs due to their limited, original wavelength coverage.

    Parameters
    ----------
    input_path : str
        Folder where the data is located.
    database : h5py._hl.files.File
        Database.
    wavel_range : tuple(float, float), None
        Wavelength range (um). The full wavelength range (0.5-40 um) is stored if set to ``None``.
        Only used in combination with ``spec_res``.
    teff_range : tuple(float, float), None
        Effective temperature range (K). All available temperatures are stored if set to ``None``.
    spec_res : float, None
        Spectral resolution. The data is stored with the spectral resolution of the input spectra
        (R = 2000) if set to ``None``. Only used in combination with ``wavel_range``.

    Returns
    -------
    NoneType
        None
    """

    if not os.path.exists(input_path):
        os.makedirs(input_path)

    input_file = 'ames-dusty.tgz'
    url = 'https://people.phys.ethz.ch/~ipa/tstolker/ames-dusty.tgz'

    data_folder = os.path.join(input_path, 'ames-dusty/')
    data_file = os.path.join(input_path, input_file)

    if not os.path.exists(data_folder):
        os.makedirs(data_folder)

    if not os.path.isfile(data_file):
        print('Downloading AMES-Dusty model spectra (59 MB)...', end='', flush=True)
        urllib.request.urlretrieve(url, data_file)
        print(' [DONE]')

    print('Unpacking AMES-Dusty model spectra (59 MB)...', end='', flush=True)
    tar = tarfile.open(data_file)
    tar.extractall(data_folder)
    tar.close()
    print(' [DONE]')

    teff = []
    logg = []
    flux = []

    if wavel_range is not None and spec_res is not None:
        wavelength = read_util.create_wavelengths(wavel_range, spec_res)
    else:
        wavelength = None

    for _, _, files in os.walk(data_folder):
        for filename in files:
            if filename[:11] == 'ames-dusty_':
                file_split = filename.split('_')

                teff_val = float(file_split[2])
                logg_val = float(file_split[4])

                if teff_range is not None:
                    if teff_val < teff_range[0] or teff_val > teff_range[1]:
                        continue

                print_message = f'Adding AMES-Dusty model spectra... {filename}'
                print(f'\r{print_message:<73}', end='')

                data_wavel, data_flux = np.loadtxt(os.path.join(data_folder, filename), unpack=True)

                teff.append(teff_val)
                logg.append(logg_val)

                if wavel_range is None or spec_res is None:
                    if wavelength is None:
                        wavelength = np.copy(data_wavel)  # (um)

                    if np.all(np.diff(wavelength) < 0):
                        raise ValueError('The wavelengths are not all sorted by increasing value.')

                    # if np.isnan(np.sum(data_flux)):
                        # Three of the files contain partially NaNs due to a more limited
                        # wavelength coverage in the original spectra (before using spectres)
                        # data_flux = np.full(data_wavel.shape[0], np.nan)

                    flux.append(data_flux)  # (W m-2 um-1)

                else:
                    flux_resample = spectres.spectres(wavelength,
                                                      data_wavel,
                                                      data_flux,
                                                      spec_errs=None,
                                                      fill=np.nan,
                                                      verbose=False)

                    if np.isnan(np.sum(flux_resample)):
                        raise ValueError(f'Resampling is only possible if the new wavelength '
                                         f'range ({wavelength[0]} - {wavelength[-1]} um) falls '
                                         f'sufficiently far within the wavelength range '
                                         f'({data_wavel[0]} - {data_wavel[-1]} um) of the input '
                                         f'spectra.')

                    flux.append(flux_resample)  # (W m-2 um-1)

    print_message = 'Adding AMES-Dusty model spectra... [DONE]'
    print(f'\r{print_message:<73}')

    data_sorted = data_util.sort_data(np.asarray(teff),
                                      np.asarray(logg),
                                      None,
                                      None,
                                      None,
                                      wavelength,
                                      np.asarray(flux))

    data_util.write_data('ames-dusty',
                         ['teff', 'logg'],
                         database,
                         data_sorted)
Пример #5
0
def add_exo_rem(input_path: str,
                database: h5py._hl.files.File,
                wavel_range: Optional[Tuple[float, float]] = None,
                teff_range: Optional[Tuple[float, float]] = None,
                spec_res: Optional[float] = None) -> None:
    """
    Function for adding the Exo-REM atmospheric models to the database.

    Parameters
    ----------
    input_path : str
        Folder where the data is located.
    database : h5py._hl.files.File
        Database.
    wavel_range : tuple(float, float), None
        Wavelength range (um). The original wavelength points with a spectral resolution of 5000
        are used if set to ``None``.
    teff_range : tuple(float, float), None
        Effective temperature range (K). All temperatures are selected if set to ``None``.
    spec_res : float, None
        Spectral resolution. Not used if ``wavel_range`` is set to ``None``.

    Returns
    -------
    NoneType
        None
    """

    if not os.path.exists(input_path):
        os.makedirs(input_path)

    input_file = 'exo-rem.tgz'
    url = 'https://people.phys.ethz.ch/~ipa/tstolker/exo-rem.tgz'

    data_folder = os.path.join(input_path, 'exo-rem/')
    data_file = os.path.join(data_folder, input_file)

    if not os.path.exists(data_folder):
        os.makedirs(data_folder)

    if not os.path.isfile(data_file):
        print('Downloading Exo-REM model spectra (790 MB)...',
              end='',
              flush=True)
        urllib.request.urlretrieve(url, data_file)
        print(' [DONE]')

    print('Unpacking Exo-REM model spectra (790 MB)...', end='', flush=True)
    tar = tarfile.open(data_file)
    tar.extractall(data_folder)
    tar.close()
    print(' [DONE]')

    teff = []
    logg = []
    feh = []
    co_ratio = []
    flux = []

    if wavel_range is not None and spec_res is not None:
        wavelength = read_util.create_wavelengths(wavel_range, spec_res)
    else:
        wavelength = None

    for _, _, files in os.walk(data_folder):
        for filename in files:
            if filename[:8] == 'exo-rem_':
                file_split = filename.split('_')

                teff_val = float(file_split[2])
                logg_val = float(file_split[4])
                feh_val = float(file_split[6])
                co_val = float(file_split[8])

                if logg_val == 5.:
                    continue

                if co_val in [0.8, 0.85]:
                    continue

                if teff_range is not None:
                    if teff_val < teff_range[0] or teff_val > teff_range[1]:
                        continue

                print_message = f'Adding Exo-REM model spectra... {filename}'
                print(f'\r{print_message:<84}', end='')

                data_wavel, data_flux = np.loadtxt(os.path.join(
                    data_folder, filename),
                                                   unpack=True)

                teff.append(teff_val)
                logg.append(logg_val)
                feh.append(feh_val)
                co_ratio.append(co_val)

                if wavel_range is None or spec_res is None:
                    if wavelength is None:
                        wavelength = np.copy(data_wavel)  # (um)

                    if np.all(np.diff(wavelength) < 0):
                        raise ValueError(
                            'The wavelengths are not all sorted by increasing value.'
                        )

                    flux.append(data_flux)  # (W m-2 um-1)

                else:
                    flux_resample = spectres.spectres(wavelength,
                                                      data_wavel,
                                                      data_flux,
                                                      spec_errs=None,
                                                      fill=np.nan,
                                                      verbose=False)

                    if np.isnan(np.sum(flux_resample)):
                        raise ValueError(
                            f'Resampling is only possible if the new wavelength '
                            f'range ({wavelength[0]} - {wavelength[-1]} um) falls '
                            f'sufficiently far within the wavelength range '
                            f'({data_wavel[0]} - {data_wavel[-1]} um) of the input '
                            f'spectra.')

                    flux.append(flux_resample)  # (W m-2 um-1)

    print_message = 'Adding Exo-REM model spectra... [DONE]'
    print(f'\r{print_message:<84}')

    print('Grid points with the following parameters have been excluded:')
    print('   - log(g) = 5')
    print('   - C/O = 0.8')
    print('   - C/O = 0.85')

    data_sorted = data_util.sort_data(np.asarray(teff), np.asarray(logg),
                                      np.asarray(feh), np.asarray(co_ratio),
                                      None, wavelength, np.asarray(flux))

    data_util.write_data('exo-rem', ['teff', 'logg', 'feh', 'co'], database,
                         data_sorted)
Пример #6
0
def add_ames_dusty(input_path, database, wl_bound, teff_bound, specres):
    """
    Function for adding the AMES-Dusty atmospheric models to the database.

    Parameters
    ----------
    input_path : str
        Folder where the data is located.
    database : h5py._hl.files.File
        Database.
    wl_bound : tuple(float, float)
        Wavelength range (micron).
    teff_bound : tuple(float, float), None
        Effective temperature range (K).
    specres : float
        Spectral resolution.

    Returns
    -------
    NoneType
        None
    """

    if not wl_bound:
        wl_bound = (1e-2, 1e2)

    if not os.path.exists(input_path):
        os.makedirs(input_path)

    data_folder = os.path.join(input_path, 'ames-dusty/')

    if not os.path.exists(data_folder):
        os.makedirs(data_folder)

    input_file = 'SPECTRA.tar'
    label = '[Fe/H]=0.0 (106 MB)'

    url = 'https://phoenix.ens-lyon.fr/Grids/AMES-Dusty/SPECTRA.tar'

    data_file = os.path.join(data_folder, input_file)

    if not os.path.isfile(data_file):
        sys.stdout.write(f'Downloading AMES-Dusty model spectra {label}...')
        sys.stdout.flush()

        urlretrieve(url, data_file)

        sys.stdout.write(' [DONE]\n')
        sys.stdout.flush()

    sys.stdout.write(f'Unpacking AMES-Dusty model spectra {label}...')
    sys.stdout.flush()

    tar = tarfile.open(data_file)
    tar.extractall(data_folder)
    tar.close()

    sys.stdout.write(' [DONE]\n')
    sys.stdout.flush()

    data_folder += 'SPECTRA/'

    teff = []
    logg = []
    flux = []

    wavelength = [wl_bound[0]]

    while wavelength[-1] <= wl_bound[1]:
        wavelength.append(wavelength[-1] + wavelength[-1] / specres)

    wavelength = np.asarray(wavelength[:-1])

    for _, _, file_list in os.walk(data_folder):
        for filename in sorted(file_list):

            if filename.startswith('lte') and filename.endswith('.7.gz'):
                sys.stdout.write('\rAdding AMES-Dusty model spectra... ' +
                                 filename + '   ')
                sys.stdout.flush()

                teff_val = float(filename[3:5]) * 100.
                logg_val = float(filename[6:9])
                feh_val = float(filename[10:13])

                if feh_val != 0.:
                    continue

                if teff_bound is not None:
                    if teff_val < teff_bound[0] or teff_val > teff_bound[1]:
                        continue

                data_wavel = []
                data_flux = []

                with gzip.open(data_folder + filename, 'rt') as gz_file:
                    for line in gz_file:
                        line_split = line.split()

                        if len(line_split) > 1:
                            tmp_wavel = line_split[0].strip()
                            tmp_flux = line_split[1].strip()

                            if len(tmp_wavel) == 21 and tmp_wavel[-4] == 'D' \
                                    and tmp_flux[-4] == 'D':
                                data_wavel.append(
                                    float(line[1:23].replace('D', 'E')))
                                data_flux.append(
                                    float(line[25:35].replace('D', 'E')))

                # See https://phoenix.ens-lyon.fr/Grids/FORMAT
                data_wavel = np.asarray(
                    data_wavel) * 1e-4  # [Angstrom] -> [micron]
                data_flux = 10.**(np.asarray(data_flux) - 8.
                                  )  # [erg s-1 cm-2 Angstrom-1]

                # [erg s-1 cm-2 Angstrom-1] -> [W m-2 micron-1]
                data_flux = data_flux * 1e-7 * 1e4 * 1e4

                data = np.stack((data_wavel, data_flux), axis=1)

                index_sort = np.argsort(data[:, 0])
                data = data[index_sort, :]

                if np.all(np.diff(data[:, 0]) < 0):
                    raise ValueError(
                        'The wavelengths are not all sorted by increasing value.'
                    )

                indices = np.where((data[:, 0] >= wl_bound[0])
                                   & (data[:, 0] <= wl_bound[1]))[0]

                if indices.size > 0:
                    teff.append(teff_val)
                    logg.append(logg_val)

                    data = data[indices, :]

                    flux_interp = interp1d(data[:, 0],
                                           data[:, 1],
                                           kind='linear',
                                           bounds_error=False,
                                           fill_value=1e-100)

                    flux.append(flux_interp(wavelength))

    data_sorted = data_util.sort_data(np.asarray(teff), np.asarray(logg), None,
                                      wavelength, np.asarray(flux))

    data_util.write_data('ames-dusty', ('teff', 'logg'), database, data_sorted)

    sys.stdout.write('\rAdding AMES-Dusty model spectra... [DONE]'
                     '                                  \n')

    sys.stdout.flush()
Пример #7
0
def add_drift_phoenix(input_path, database):
    """
    Function for adding the DRIFT-PHOENIX atmospheric models to the database.

    Parameters
    ----------
    input_path : str
    database : h5py._hl.files.File

    Returns
    -------
    NoneType
        None
    """

    if not os.path.exists(input_path):
        os.makedirs(input_path)

    data_file = os.path.join(input_path, 'drift-phoenix.tgz')
    data_folder = os.path.join(input_path, 'drift-phoenix/')

    url = 'https://people.phys.ethz.ch/~stolkert/species/drift-phoenix.tgz'

    if not os.path.isfile(data_file):
        sys.stdout.write('Downloading DRIFT-PHOENIX model spectra (151 MB)...')
        sys.stdout.flush()

        urlretrieve(url, data_file)

        sys.stdout.write(' [DONE]\n')
        sys.stdout.flush()

    sys.stdout.write('Unpacking DRIFT-PHOENIX model spectra...')
    sys.stdout.flush()

    tar = tarfile.open(data_file)
    tar.extractall(input_path)
    tar.close()

    sys.stdout.write(' [DONE]\n')
    sys.stdout.flush()

    teff = []
    logg = []
    feh = []
    wavelength = None
    flux = []

    for _, _, file_list in os.walk(data_folder):
        for filename in sorted(file_list):

            if filename.startswith('lte_'):
                sys.stdout.write('\rAdding DRIFT-PHOENIX model spectra... ' +
                                 filename)
                sys.stdout.flush()

                teff.append(float(filename[4:8]))
                logg.append(float(filename[9:12]))
                feh.append(float(filename[12:16]))

                data = np.loadtxt(data_folder + filename)

                if wavelength is None:
                    # [Angstrom] -> [micron]
                    wavelength = data[:, 0] * 1e-4

                if np.all(np.diff(wavelength) < 0):
                    raise ValueError(
                        'The wavelengths are not all sorted by increasing value.'
                    )

                # [erg s-1 cm-2 Angstrom-1] -> [W m-2 micron-1]
                flux.append(data[:, 1] * 1e-7 * 1e4 * 1e4)

    data_sorted = data_util.sort_data(np.asarray(teff), np.asarray(logg),
                                      np.asarray(feh), wavelength,
                                      np.asarray(flux))

    data_util.write_data('drift-phoenix', ('teff', 'logg', 'feh'), database,
                         data_sorted)

    sys.stdout.write(
        '\rAdding DRIFT-PHOENIX model spectra... [DONE]                    \n')
    sys.stdout.flush()
Пример #8
0
def add_petitcode_hot_cloudy(input_path: str,
                             database: h5py._hl.files.File,
                             wavel_range: Optional[Tuple[float, float]] = None,
                             teff_range: Optional[Tuple[float, float]] = None,
                             spec_res: Optional[float] = 1000.) -> None:
    """
    Function for adding the petitCODE hot cloudy atmospheric models to the database.

    Parameters
    ----------
    input_path : str
        Folder where the data is located.
    database : h5py._hl.files.File
        Database.
    wavel_range : tuple(float, float), None
        Wavelength range (um). The original wavelength points are used if set to None.
    teff_range : tuple(float, float), None
        Effective temperature range (K). All temperatures are selected if set to None.
    spec_res : float, None
        Spectral resolution. Not used if ``wavel_range`` is set to None.

    Returns
    -------
    NoneType
        None
    """

    if not os.path.exists(input_path):
        os.makedirs(input_path)

    data_folder = os.path.join(input_path, 'petitcode-hot-cloudy/')

    url = 'https://people.phys.ethz.ch/~ipa/tstolker/petitcode-hot-cloudy.tgz'

    data_file = os.path.join(input_path, 'petitcode-hot-cloudy.tgz')

    if not os.path.isfile(data_file):
        print('Downloading petitCODE hot cloudy model spectra (276 MB)...',
              end='',
              flush=True)
        urllib.request.urlretrieve(url, data_file)
        print(' [DONE]')

    print('Unpacking petitCODE hot cloudy model spectra (276 MB)...',
          end='',
          flush=True)
    tar = tarfile.open(data_file)
    tar.extractall(data_folder)
    tar.close()
    print(' [DONE]')

    teff = []
    logg = []
    feh = []
    co_ratio = []
    fsed = []
    flux = []

    if wavel_range is not None:
        wavelength = read_util.create_wavelengths(wavel_range, spec_res)
    else:
        wavelength = None

    for _, _, files in os.walk(data_folder):
        for filename in files:
            file_split = filename.split('_')

            teff_val = float(file_split[2])
            logg_val = float(file_split[4])
            feh_val = float(file_split[6])
            co_ratio_val = float(file_split[8])
            fsed_val = float(file_split[10])

            if teff_range is not None:
                if teff_val < teff_range[0] or teff_val > teff_range[1]:
                    continue

            print_message = f'Adding petitCODE hot cloudy model spectra... {filename}'
            print(f'\r{print_message:<111}', end='')

            data = np.loadtxt(os.path.join(data_folder, filename))

            teff.append(teff_val)
            logg.append(logg_val)
            feh.append(feh_val)
            co_ratio.append(co_ratio_val)
            fsed.append(fsed_val)

            if wavel_range is None:
                if wavelength is None:
                    # (cm) -> (um)
                    wavelength = data[:, 0] * 1e4

                if np.all(np.diff(wavelength) < 0):
                    raise ValueError(
                        'The wavelengths are not all sorted by increasing value.'
                    )

                # (erg s-1 cm-2 Hz-1) -> (W m-2 um-1)
                flux.append(data[:, 1] * 1e-9 * constants.LIGHT /
                            (wavelength * 1e-6)**2)

            else:
                # (cm) -> (um)
                data_wavel = data[:, 0] * 1e4

                # (erg s-1 cm-2 Hz-1) -> (W m-2 um-1)
                data_flux = data[:, 1] * 1e-9 * constants.LIGHT / (data_wavel *
                                                                   1e-6)**2

                try:
                    flux.append(
                        spectres.spectres(wavelength, data_wavel, data_flux))
                except ValueError:
                    flux.append(np.zeros(wavelength.shape[0]))

                    warnings.warn(
                        'The wavelength range should fall within the range of the '
                        'original wavelength sampling. Storing zeros instead.')

    print_message = 'Adding petitCODE hot cloudy model spectra... [DONE]'
    print(f'\r{print_message:<111}')

    data_sorted = data_util.sort_data(np.asarray(teff), np.asarray(logg),
                                      np.asarray(feh), np.asarray(co_ratio),
                                      np.asarray(fsed), wavelength,
                                      np.asarray(flux))

    data_util.write_data('petitcode-hot-cloudy',
                         ['teff', 'logg', 'feh', 'co', 'fsed'], database,
                         data_sorted)
Пример #9
0
def add_petitcode_hot_clear(input_path: str,
                            database: h5py._hl.files.File,
                            data_folder: str,
                            wavel_range: Optional[Tuple[float, float]] = None,
                            teff_range: Optional[Tuple[float, float]] = None,
                            spec_res: Optional[float] = 1000.) -> None:
    """
    Function for adding the petitCODE hot clear atmospheric models to the database.

    Parameters
    ----------
    input_path : str
        Folder where the data is located.
    database : h5py._hl.files.File
        Database.
    data_folder : str
        Path with input data.
    wavel_range : tuple(float, float), None
        Wavelength range (um). The original wavelength points are used if set to None.
    teff_range : tuple(float, float), None
        Effective temperature range (K). All temperatures are selected if set to None.
    spec_res : float, None
        Spectral resolution. Not used if ``wavel_range`` is set to None.

    Returns
    -------
    NoneType
        None
    """

    if not os.path.exists(input_path):
        os.makedirs(input_path)

    teff = []
    logg = []
    feh = []
    co_ratio = []
    flux = []

    if wavel_range is not None:
        wavelength = read_util.create_wavelengths(wavel_range, spec_res)
    else:
        wavelength = None

    for _, _, files in os.walk(data_folder):
        for filename in files:
            teff_val = float(filename[9:13])
            logg_val = float(filename[19:23])
            feh_val = float(filename[28:32])
            co_ratio_val = float(filename[36:40])

            if teff_range is not None:
                if teff_val < teff_range[0] or teff_val > teff_range[1]:
                    continue

            print_message = f'Adding petitCODE hot clear model spectra... {filename}'
            print(f'\r{print_message:<100}', end='')

            data = np.loadtxt(os.path.join(data_folder, filename))

            teff.append(teff_val)
            logg.append(logg_val)
            feh.append(feh_val)
            co_ratio.append(co_ratio_val)

            if wavel_range is None:
                if wavelength is None:
                    # (cm) -> (um)
                    wavelength = data[:, 0] * 1e4

                if np.all(np.diff(wavelength) < 0):
                    raise ValueError(
                        'The wavelengths are not all sorted by increasing value.'
                    )

                # (erg s-1 cm-2 Hz-1) -> (W m-2 um-1)
                flux.append(data[:, 1] * 1e-9 * constants.LIGHT /
                            (wavelength * 1e-6)**2)

            else:
                # (cm) -> (um)
                data_wavel = data[:, 0] * 1e4

                # (erg s-1 cm-2 Hz-1) -> (W m-2 um-1)
                data_flux = data[:, 1] * 1e-9 * constants.LIGHT / (data_wavel *
                                                                   1e-6)**2

                try:
                    flux.append(
                        spectres.spectres(wavelength, data_wavel, data_flux))
                except ValueError:
                    flux.append(np.zeros(wavelength.shape[0]))

                    warnings.warn(
                        'The wavelength range should fall within the range of the '
                        'original wavelength sampling. Storing zeros instead.')

    print_message = 'Adding petitCODE hot clear model spectra... [DONE]'
    print(f'\r{print_message:<100}')

    data_sorted = data_util.sort_data(np.asarray(teff), np.asarray(logg),
                                      np.asarray(feh), np.asarray(co_ratio),
                                      None, wavelength, np.asarray(flux))

    data_util.write_data('petitcode-hot-clear', ['teff', 'logg', 'feh', 'co'],
                         database, data_sorted)
Пример #10
0
def add_model_grid(
    model_name: str,
    input_path: str,
    database: h5py._hl.files.File,
    wavel_range: Optional[Tuple[float, float]],
    teff_range: Optional[Tuple[float, float]],
    spec_res: Optional[float],
) -> None:
    """
    Function for adding a grid of model spectra to the database.
    The original spectra had been resampled to logarithmically-
    spaced wavelengths, so at a constant resolution,
    :math:`\\lambda/\\Delta\\lambda`. This function downloads
    the model grid, unpacks the tar file, and adds the spectra
    and parameters to the database.

    Parameters
    ----------
    model_name : str
        Name of the model grid.
    input_path : str
        Folder where the data is located.
    database : h5py._hl.files.File
        Database.
    wavel_range : tuple(float, float), None
        Wavelength range (um). The original wavelength
        points are used if set to ``None``.
    teff_range : tuple(float, float), None
        Effective temperature range (K). All temperatures
        are selected if set to ``None``.
    spec_res : float, None
        Spectral resolution for resampling. Not used if
        ``wavel_range`` is set to ``None`` and/or
        ``spec_res`` is set to ``None``

    Returns
    -------
    NoneType
        None
    """

    data_file = pathlib.Path(__file__).parent.resolve() / "model_data.json"

    with open(data_file, "r", encoding="utf-8") as json_file:
        model_data = json.load(json_file)

    if model_name in model_data.keys():
        model_info = model_data[model_name]

    else:
        raise ValueError(
            f"The {model_name} atmospheric model is not available. "
            f"Please choose one of the following models: "
            f"'ames-cond', 'ames-dusty', 'atmo', 'bt-settl', "
            f"'bt-nextgen', 'drift-phoexnix', 'petitcode-cool-clear', "
            f"'petitcode-cool-cloudy', 'petitcode-hot-clear', "
            f"'petitcode-hot-cloudy', 'exo-rem', 'bt-settl-cifist', "
            f"'bt-cond', 'bt-cond-feh', 'blackbody', 'sonora-cholla', "
            f"'sonora-bobcat', 'sonora-bobcat-co', 'koester-wd'")

    if model_name == "bt-settl":
        warnings.warn("It is recommended to use the CIFIST "
                      "grid of the BT-Settl, because it is "
                      "a newer version. In that case, set "
                      "model='bt-settl-cifist' when using "
                      "add_model of Database.")

    if not os.path.exists(input_path):
        os.makedirs(input_path)

    input_file = f"{model_name}.tgz"

    data_folder = os.path.join(input_path, model_name)
    data_file = os.path.join(input_path, input_file)

    if not os.path.exists(data_folder):
        os.makedirs(data_folder)

    url = f"https://home.strw.leidenuniv.nl/~stolker/species/{model_name}.tgz"

    if not os.path.isfile(data_file):
        print(
            f"Downloading {model_info['name']} model "
            f"spectra ({model_info['file size']})...",
            end="",
            flush=True,
        )
        urllib.request.urlretrieve(url, data_file)
        print(" [DONE]")

    print(
        f"Unpacking {model_info['name']} model "
        f"spectra ({model_info['file size']})...",
        end="",
        flush=True,
    )
    tar = tarfile.open(data_file)
    tar.extractall(data_folder)
    tar.close()
    print(" [DONE]")

    if "information" in model_info:
        print(f"Model information: {model_info['information']}")

    if "reference" in model_info:
        print(f"Please cite {model_info['reference']} when "
              f"using {model_info['name']} in a publication")

    if "url" in model_info:
        print(f"Reference URL: {model_info['url']}")

    teff = []

    if "logg" in model_info["parameters"]:
        logg = []
    else:
        logg = None

    if "feh" in model_info["parameters"]:
        feh = []
    else:
        feh = None

    if "c_o_ratio" in model_info["parameters"]:
        c_o_ratio = []
    else:
        c_o_ratio = None

    if "fsed" in model_info["parameters"]:
        fsed = []
    else:
        fsed = None

    if "log_kzz" in model_info["parameters"]:
        log_kzz = []
    else:
        log_kzz = None

    flux = []

    if wavel_range is not None and spec_res is not None:
        wavelength = read_util.create_wavelengths(wavel_range, spec_res)
        print(f"Wavelength range (um) = {wavel_range[0]} - {wavel_range[1]}")
        print(f"Spectral resolution = {spec_res}")

    else:
        wavelength = None
        print(f"Wavelength range (um) = "
              f"{model_info['wavelength range'][0]} - "
              f"{model_info['wavelength range'][1]}")
        print(f"Spectral resolution = {model_info['resolution']}")

    if teff_range is None:
        print(
            f"Teff range (K) = {model_info['teff range'][0]} - {model_info['teff range'][1]}"
        )
    else:
        print(f"Teff range (K) = {teff_range[0]} - {teff_range[1]}")

    print_message = ""

    for _, _, file_list in os.walk(data_folder):
        for filename in sorted(file_list):

            if filename[:len(model_name)] == model_name:
                file_split = filename.split("_")

                param_index = file_split.index("teff") + 1
                teff_val = float(file_split[param_index])

                if teff_range is not None:
                    if teff_val < teff_range[0] or teff_val > teff_range[1]:
                        continue

                teff.append(teff_val)

                if logg is not None:
                    param_index = file_split.index("logg") + 1
                    logg.append(float(file_split[param_index]))

                if feh is not None:
                    param_index = file_split.index("feh") + 1
                    feh.append(float(file_split[param_index]))

                if c_o_ratio is not None:
                    param_index = file_split.index("co") + 1
                    c_o_ratio.append(float(file_split[param_index]))

                if fsed is not None:
                    param_index = file_split.index("fsed") + 1
                    fsed.append(float(file_split[param_index]))

                if log_kzz is not None:
                    param_index = file_split.index("logkzz") + 1
                    log_kzz.append(float(file_split[param_index]))

                empty_message = len(print_message) * " "
                print(f"\r{empty_message}", end="")

                print_message = (
                    f"Adding {model_info['name']} model spectra... {filename}")
                print(f"\r{print_message}", end="")

                data_wavel, data_flux = np.loadtxt(os.path.join(
                    data_folder, filename),
                                                   unpack=True)

                if wavel_range is None or spec_res is None:
                    if wavelength is None:
                        wavelength = np.copy(data_wavel)  # (um)

                    if np.all(np.diff(wavelength) < 0):
                        raise ValueError(
                            "The wavelengths are not all sorted by increasing value."
                        )

                    flux.append(data_flux)  # (W m-2 um-1)

                else:
                    flux_resample = spectres.spectres(
                        wavelength,
                        data_wavel,
                        data_flux,
                        spec_errs=None,
                        fill=np.nan,
                        verbose=False,
                    )

                    if np.isnan(np.sum(flux_resample)):
                        raise ValueError(
                            f"Resampling is only possible if the new wavelength "
                            f"range ({wavelength[0]} - {wavelength[-1]} um) falls "
                            f"sufficiently far within the wavelength range "
                            f"({data_wavel[0]} - {data_wavel[-1]} um) of the input "
                            f"spectra.")

                    flux.append(flux_resample)  # (W m-2 um-1)

    empty_message = len(print_message) * " "
    print(f"\r{empty_message}", end="")

    print_message = f"Adding {model_info['name']} model spectra... [DONE]"
    print(f"\r{print_message}")

    if logg is not None:
        logg = np.asarray(logg)

    if feh is not None:
        feh = np.asarray(feh)

    if c_o_ratio is not None:
        c_o_ratio = np.asarray(c_o_ratio)

    if fsed is not None:
        fsed = np.asarray(fsed)

    if log_kzz is not None:
        log_kzz = np.asarray(log_kzz)

    data_sorted = data_util.sort_data(
        np.asarray(teff),
        logg,
        feh,
        c_o_ratio,
        fsed,
        log_kzz,
        wavelength,
        np.asarray(flux),
    )

    data_util.write_data(model_name, model_info["parameters"], database,
                         data_sorted)