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()
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)
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)
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)
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)
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()
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()
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)
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)
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)