diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..e74a129 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,93 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ "activ_dev", "main*" ] + pull_request: + branches: [ "activ_dev", "main*" ] + schedule: + - cron: '24 12 * * 2' + +jobs: + analyze: + name: Analyze (${{ matrix.language }}) + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners (GitHub.com only) + # Consider using larger runners or machines with greater resources for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} + permissions: + # required for all workflows + security-events: write + + # required to fetch internal or private CodeQL packs + packages: read + + # only required for workflows in private repositories + actions: read + contents: read + + strategy: + fail-fast: false + matrix: + include: + - language: python + build-mode: none + # CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' + # Use `c-cpp` to analyze code written in C, C++ or both + # Use 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, + # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. + # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how + # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + # If the analyze step fails for one of the languages you are analyzing with + # "We were unable to automatically build your code", modify the matrix above + # to set the build mode to "manual" for that language. Then modify this step + # to build your code. + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + - if: matrix.build-mode == 'manual' + shell: bash + run: | + echo 'If you are using a "manual" build mode for one or more of the' \ + 'languages you are analyzing, replace this with the commands to build' \ + 'your code, for example:' + echo ' make bootstrap' + echo ' make release' + exit 1 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" diff --git a/readthedocs.yml b/.readthedocs.yaml similarity index 50% rename from readthedocs.yml rename to .readthedocs.yaml index 36acb0a..d27f814 100644 --- a/readthedocs.yml +++ b/.readthedocs.yaml @@ -8,13 +8,26 @@ version: 2 # Build documentation in the docs/ directory with Sphinx sphinx: - configuration: docs/source/conf.py + configuration: docs/conf.py + +# Set the OS, Python version and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.11" + # You can also specify other tool versions: + # nodejs: "20" + # rust: "1.70" + # golang: "1.20" + + # Optionally set the version of Python and requirements required to build your docs python: install: - requirements: requirements.txt - system_packages: True - -submodules: - include: all \ No newline at end of file + - requirements: docs/requirements.txt +# system_packages: True +# +#submodules: +# include: all \ No newline at end of file diff --git a/ForMoSA.egg-info/PKG-INFO b/ForMoSA.egg-info/PKG-INFO index 4a56e94..fdedc95 100644 --- a/ForMoSA.egg-info/PKG-INFO +++ b/ForMoSA.egg-info/PKG-INFO @@ -1,11 +1,11 @@ Metadata-Version: 2.1 Name: ForMoSA -Version: 2.0.0 +Version: 1.1.3 Summary: ForMoSA: Forward Modeling Tool for Spectral Analysis Home-page: https://github.com/exoAtmospheres/ForMoSA Author: P. Palma-Bifani, S. Petrus, M. Ravet, A. Denis, M. Bonnefoy, G. Chauvin Author-email: paulina.palma-bifani@oca.eu -License: BSD 2-Clause License +License: BSD 3-Clause License License-File: LICENSE Requires-Dist: numpy Requires-Dist: matplotlib @@ -18,5 +18,11 @@ Requires-Dist: nestle Requires-Dist: PyAstronomy Requires-Dist: spectres Requires-Dist: pyyaml +Requires-Dist: tqdm Requires-Dist: importlib-metadata==4.13.0 Requires-Dist: xarray==2023.10.1 + +Welcome to ForMoSA, an open-source Python package. +We designed this tool to model exoplanetary atmospheres with a forward modeling approach. + +We encourage the community to exploit its capabilities! diff --git a/ForMoSA.egg-info/requires.txt b/ForMoSA.egg-info/requires.txt index e29281c..6c4410b 100644 --- a/ForMoSA.egg-info/requires.txt +++ b/ForMoSA.egg-info/requires.txt @@ -9,5 +9,6 @@ nestle PyAstronomy spectres pyyaml +tqdm importlib-metadata==4.13.0 xarray==2023.10.1 diff --git a/ForMoSA/__init__.py b/ForMoSA/__init__.py index fd9425a..c9a7955 100644 --- a/ForMoSA/__init__.py +++ b/ForMoSA/__init__.py @@ -1,5 +1,5 @@ import os -__version__ = "2.0.0" +__version__ = "1.1.3" __all__ = ['adapt', 'nested_sampling','plotting'] \ No newline at end of file diff --git a/ForMoSA/adapt/adapt_grid.py b/ForMoSA/adapt/adapt_grid.py index 53e807a..b35cc36 100755 --- a/ForMoSA/adapt/adapt_grid.py +++ b/ForMoSA/adapt/adapt_grid.py @@ -2,7 +2,9 @@ import numpy as np import xarray as xr import time -import os +import os, sys + +sys.path.insert(0, os.path.abspath('../')) from adapt.extraction_functions import adapt_model, decoupe @@ -15,7 +17,7 @@ def adapt_grid(global_params, wav_obs_spectro, wav_obs_photo, res_mod_obs_merge, Adapt the synthetic spectra of a grid to make them comparable with the data. Args: - global_params (object): Class containing each parameter + global_params (object): Class containing each parameter wav_obs_spectro (array): Merged wavelength grid of the data wav_obs_photo (array): Wavelengths of the photometry points obs_name (str): Name of the current observation looping @@ -23,7 +25,7 @@ def adapt_grid(global_params, wav_obs_spectro, wav_obs_photo, res_mod_obs_merge, Returns: None - Author: Simon Petrus / Adapted: Matthieu Ravet & Paulina Palma-Bifani + Author: Simon Petrus, Matthieu Ravet and Paulina Palma-Bifani """ ds = xr.open_dataset(global_params.model_path, decode_cf=False, engine="netcdf4") diff --git a/ForMoSA/adapt/adapt_obs_mod.py b/ForMoSA/adapt/adapt_obs_mod.py index fdf4bcd..ba0002b 100755 --- a/ForMoSA/adapt/adapt_obs_mod.py +++ b/ForMoSA/adapt/adapt_obs_mod.py @@ -1,14 +1,15 @@ from __future__ import print_function, division import numpy as np -import os +import os,sys import xarray as xr from scipy.interpolate import interp1d +sys.path.insert(0, os.path.abspath('../')) + from adapt.extraction_functions import extract_observation from adapt.adapt_grid import adapt_grid from main_utilities import diag_mat import glob -# import matplotlib.pyplot as plt # ---------------------------------------------------------------------------------------------------------------------- @@ -22,7 +23,7 @@ def launch_adapt(global_params, justobs='no'): Returns: None - Author: Simon Petrus / Adapted: Matthieu Ravet, Paulina Palma-Bifani and Allan Denis + Author: Simon Petrus, Matthieu Ravet, Paulina Palma-Bifani and Allan Denis """ # Get back the grid information from the config file diff --git a/ForMoSA/adapt/extraction_functions.py b/ForMoSA/adapt/extraction_functions.py index 993ded1..eae8173 100755 --- a/ForMoSA/adapt/extraction_functions.py +++ b/ForMoSA/adapt/extraction_functions.py @@ -5,7 +5,6 @@ from scipy.interpolate import interp1d from spectres import spectres import os -import matplotlib.pyplot as plt # ---------------------------------------------------------------------------------------------------------------------- @@ -16,7 +15,9 @@ def decoupe(second): Args: second (float): number of second Returns: - hour, minute, second (float, float, float): hours-minutes-seconds format + - float : hours + - float : minutes + - float : seconds Author: Simon Petrus """ @@ -39,7 +40,7 @@ def find_nearest(array, value): array (array): Array to explore value (float): Desire value Returns: - idx (int): Indice of the closest values from the desire value + - idx (int) : Indice of the closest values from the desire value Author: Simon Petrus """ @@ -62,19 +63,15 @@ def extract_observation(global_params, wav_mod_nativ, res_mod_nativ, cont='no', cont (str): Boolean string. If the function is used to estimate the continuum cont='yes' obs_name (str): Name of the current observation looping indobs (int): Index of the current observation looping + Returns: - obs_spectro (n-array): List containing the sub-spectra defined by the parameter "wav_for_adapt" with decreased resolution - [[wav_1, flx_1, err_1, reso_1], ..., [wav_n, flx_n, err_n, reso_n]] - obs_photo (array): List containing the photometry (0 replace the spectral resolution here). - [wav_phot, flx_phot, err_phot, 0] - obs_spectro_ins (array): List containing different instruments used for the data (1 per wavelength). - [[instru_range_1], ..., [instru_range_n]] - obs_photo_ins (array): List containing different filters used for the data (1 per photometric point). - [filter_phot_1, filter_phot_2, ..., filter_phot_n] - obs_opt (n-array): List containing the optional sub-arrays defined by the parameter "wav_for_adapt". - [[cov_1, tran_1, star_1], ..., [cov_n, tran_n, star_n]] - - Author: Simon Petrus / Adapted: Matthieu Ravet + - obs_spectro (n-array) : List containing the sub-spectra defined by the parameter "wav_for_adapt" with decreased resolution [[wav_1, flx_1, err_1, reso_1], ..., [wav_n, flx_n, err_n, reso_n]] + - obs_photo (array) : List containing the photometry (0 replace the spectral resolution here). [wav_phot, flx_phot, err_phot, 0] + - obs_spectro_ins(array) : List containing different instruments used for the data (1 per wavelength). [[instru_range_1], ..., [instru_range_n]] + - obs_photo_ins (array) : List containing different filters used for the data (1 per photometric point). [filter_phot_1, filter_phot_2, ..., filter_phot_n] + - obs_opt (n-array) : List containing the optional sub-arrays defined by the parameter "wav_for_adapt". [[cov_1, tran_1, star_1], ..., [cov_n, tran_n, star_n]] + + Author: Simon Petrus, Matthieu Ravet """ # Extract the wavelengths, flux, errors, spectral resolution, and instrument/filter names from the observation file. @@ -93,10 +90,10 @@ def extract_observation(global_params, wav_mod_nativ, res_mod_nativ, cont='no', # If we want to decrease the resolution of the data: (if by_sample, the data don't need to be adapted) if global_params.adapt_method[indobs] == 'by_reso': obs_spectro[c][1] = resolution_decreasing(global_params, cut[0], cut[1], cut[3], wav_mod_nativ, [], res_mod_obs, - 'obs', obs_name=obs_name, indobs=indobs) + 'obs', indobs=indobs) if cont == 'yes': # If we want to estimate and substract the continuum of the data: - obs_spectro[c][1] -= continuum_estimate(global_params, cut[0], cut[1], cut[3], obs_name=obs_name, indobs=indobs) + obs_spectro[c][1] -= continuum_estimate(global_params, cut[0], cut[1], cut[3], indobs=indobs) return obs_spectro, obs_photo, obs_spectro_ins, obs_photo_ins, obs_opt @@ -112,17 +109,13 @@ def adapt_observation_range(global_params, obs_name='', indobs=0): global_params (object): Class containing each parameter obs_name (str): Name of the current observation looping indobs (int): Index of the current observation looping + Returns: - obs_spectro (n-array): List containing the sub-spectra defined by the parameter "wav_for_adapt". - [[wav_1, flx_1, err_1, reso_1], ..., [wav_n, flx_n, err_n, reso_n]] - obs_photo (array): List containing the photometry (0 replace the spectral resolution here). - [wav_phot, flx_phot, err_phot, 0] - obs_spectro_ins (array): List containing different instruments used for the data (1 per wavelength). - [[instru_1], ..., [instru_n]] - obs_photo_ins (array): List containing different filters used for the data (1 per photometric point). - [filter_phot_1, filter_phot_2, ..., filter_phot_n] - obs_opt (n-array): List containing the optional sub-arrays defined by the parameter "wav_for_adapt". - [[cov_1, tran_1, star_1], ..., [cov_n, tran_n, star_n]] + - obs_spectro (n-array) : List containing the sub-spectra defined by the parameter "wav_for_adapt" with decreased resolution [[wav_1, flx_1, err_1, reso_1], ..., [wav_n, flx_n, err_n, reso_n]] + - obs_photo (array) : List containing the photometry (0 replace the spectral resolution here). [wav_phot, flx_phot, err_phot, 0] + - obs_spectro_ins(array) : List containing different instruments used for the data (1 per wavelength). [[instru_range_1], ..., [instru_range_n]] + - obs_photo_ins (array) : List containing different filters used for the data (1 per photometric point). [filter_phot_1, filter_phot_2, ..., filter_phot_n] + - obs_opt (n-array) : List containing the optional sub-arrays defined by the parameter "wav_for_adapt". [[cov_1, tran_1, star_1], ..., [cov_n, tran_n, star_n]] Author: Simon Petrus, Matthieu Ravet and Allan Denis """ @@ -316,16 +309,16 @@ def adapt_model(global_params, wav_mod_nativ, flx_mod_nativ, res_mod_obs_merge, obs_name (str): Name of the current observation looping indobs (int): Index of the current observation looping Returns: - flx_mod_extract (array): Flux of the spectrum with a decreased spectral resolution, re-sampled on the data wavelength grid - mod_photo (array): List containing the photometry ('0' replace the spectral resolution here). + - mod_spectro (array) : Flux of the spectrum with a decreased spectral resolution, re-sampled on the data wavelength grid + - mod_photo (array) : List containing the photometry ('0' replace the spectral resolution here). Author: Simon Petrus """ # Estimate and subtract the continuum (if needed) if global_params.continuum_sub[indobs] != 'NA': - mod_spectro, mod_photo = extract_model(global_params, wav_mod_nativ, flx_mod_nativ, res_mod_obs_merge, cont='yes', obs_name=obs_name) + mod_spectro, mod_photo = extract_model(global_params, wav_mod_nativ, flx_mod_nativ, res_mod_obs_merge, cont='yes', obs_name=obs_name, indobs=indobs) else: - mod_spectro, mod_photo = extract_model(global_params, wav_mod_nativ, flx_mod_nativ, res_mod_obs_merge, obs_name=obs_name) + mod_spectro, mod_photo = extract_model(global_params, wav_mod_nativ, flx_mod_nativ, res_mod_obs_merge, obs_name=obs_name, indobs=indobs) return mod_spectro, mod_photo @@ -346,8 +339,8 @@ def extract_model(global_params, wav_mod_nativ, flx_mod_nativ, res_mod_obs_merge obs_name (str): Name of the current observation looping indobs (int): Index of the current observation looping Returns: - mod_spectro (array): List containing the sub-spectra defined by the parameter "wav_for_adapt". - mod_photo (array): List containing the photometry ('0' replace the spectral resolution here). + - mod_spectro (array) : List containing the sub-spectra defined by the parameter "wav_for_adapt". + - mod (array) : List containing the photometry ('0' replace the spectral resolution here). Author: Simon Petrus """ @@ -362,13 +355,13 @@ def extract_model(global_params, wav_mod_nativ, flx_mod_nativ, res_mod_obs_merge # If we want to decrease the resolution of the data: if global_params.adapt_method[indobs] == 'by_reso': mod_cut_flx = resolution_decreasing(global_params, cut[0], [], cut[3], wav_mod_nativ, flx_mod_nativ, res_mod_obs_merge[c], - 'mod', obs_name=obs_name, indobs=indobs) + 'mod', indobs=indobs) else: mod_cut_flx = spectres(cut[0], wav_mod_nativ, flx_mod_nativ) # If we want to estimate the continuum of the data: if cont == 'yes': - continuum = continuum_estimate(global_params, cut[0], mod_cut_flx, res_mod_obs_merge[c], obs_name=obs_name, indobs=indobs) + continuum = continuum_estimate(global_params, cut[0], mod_cut_flx, res_mod_obs_merge[c], indobs=indobs) mod_cut_flx -= continuum # Concatenate to speed up the code @@ -411,7 +404,7 @@ def convolve_and_sample(wv_channels, sigmas_wvs, model_wvs, model_fluxes, num_si model_fluxes (array): the fluxes of the model num_sigma (float): number of +/- sigmas to evaluate the LSF to. Returns: - output_model (array): the fluxes in each of the wavelength channels + - output_model (array) : the fluxes in each of the wavelength channels Author: Jason Wang """ @@ -442,7 +435,7 @@ def convolve_and_sample(wv_channels, sigmas_wvs, model_wvs, model_fluxes, num_si # ---------------------------------------------------------------------------------------------------------------------- -def resolution_decreasing(global_params, wav_obs, flx_obs, res_obs, wav_mod_nativ, flx_mod_nativ, res_mod_obs, obs_or_mod, obs_name='', indobs=0): +def resolution_decreasing(global_params, wav_obs, flx_obs, res_obs, wav_mod_nativ, flx_mod_nativ, res_mod_obs, obs_or_mod, indobs=0): """ Decrease the resolution of a spectrum (data or model). The function calculates the FWHM as a function of the wavelengths for the data, the model, and for a custom spectral resolution (optional) and estimates the highest one @@ -459,12 +452,11 @@ def resolution_decreasing(global_params, wav_obs, flx_obs, res_obs, wav_mod_nati flx_mod_nativ (array): Flux of the model res_mod_obs (array): Spectral resolution of the model as a function of the wavelength grid of the data obs_or_mod (str): Parameter to identify if you want to manage a data or a model spectrum. 'obs' or 'mod' - obs_name (str): Name of the current observation looping indobs (int): Index of the current observation looping Returns: - flx_obs_final (array): Flux of the spectrum with a decreased spectral resolution, re-sampled on the data wavelength grid + - flx_obs_final (array) : Flux of the spectrum with a decreased spectral resolution, re-sampled on the data wavelength grid - Author: Simon Petrus / Adapted: Matthieu Ravet + Author: Simon Petrus, Matthieu Ravet """ # Estimate of the FWHM of the data as a function of the wavelength fwhm_obs = 2 * wav_obs / res_obs @@ -494,7 +486,7 @@ def resolution_decreasing(global_params, wav_obs, flx_obs, res_obs, wav_mod_nati # ---------------------------------------------------------------------------------------------------------------------- -def continuum_estimate(global_params, wav, flx, res, obs_name='', indobs=0): +def continuum_estimate(global_params, wav, flx, res, indobs=0): """ Decrease the resolution of a spectrum (data or model). The function calculates the FWHM as a function of the wavelengths of the custom spectral resolution (estimated for the continuum). It then calculates a sigma to decrease @@ -506,12 +498,11 @@ def continuum_estimate(global_params, wav, flx, res, obs_name='', indobs=0): wav (array): Wavelength grid of the spectrum for which you want to estimate the continuum flx (array): Flux of the spectrum for which you want to estimate the continuum res (int): Spectral resolution of the spectrum for which you want to estimate the continuum - obs_name (str): Name of the current observation looping indobs (int): Index of the current observation looping Returns: - continuum (array): Estimated continuum of the spectrum re-sampled on the data wavelength grid + - continuum (array) : Estimated continuum of the spectrum re-sampled on the data wavelength grid - Author: Simon Petrus / Adapted: Matthieu Ravet + Author: Simon Petrus, Matthieu Ravet """ diff --git a/ForMoSA/main_utilities.py b/ForMoSA/main_utilities.py index e430279..7562bc2 100755 --- a/ForMoSA/main_utilities.py +++ b/ForMoSA/main_utilities.py @@ -3,12 +3,15 @@ # ---------------------------------------------------------------------------------------------------------------------- def yesno(text): - ''' Function to interact with the terminal and decide for different options when running ForMoSA + ''' + Function to interact with the terminal and decide for different options when running ForMoSA (Loop to repeat question if answer is different to 'y' or 'n). + Args: text (str): (y/n) answer in the terminall in interactive mode Returns: asw (str): answer y or n - (Loop to repeat question if answer is different to 'y' or 'n) + + Author: Simon Petrus ''' print(text) asw = input() @@ -19,15 +22,17 @@ def yesno(text): # ---------------------------------------------------------------------------------------------------------------------- def diag_mat(rem=[], result=np.empty((0, 0))): - ''' Function to concatenate and align iterativly block matrices (usefull during the extraction and the inversion) - Parameters: + ''' + Function to concatenate and align iterativly block matrices (usefull during the extraction and the inversion). + + Args: rem (list): matrices to be add iterativly (use diag([mat1, mat2])) result (array): final array with each sub-matrices aligned allong the diagonal Returns: diag_mat (matrix): Generated diagonal matrix (If rem input is empty, it wull return an empy array) - Credits : ishigoya, Stack-overflow : https://stackoverflow.com/questions/42154606/python-numpy-how-to-construct-a-big-diagonal-arraymatrix-from-two-small-array + Author : Ishigoya, Stack-overflow : https://stackoverflow.com/questions/42154606/python-numpy-how-to-construct-a-big-diagonal-arraymatrix-from-two-small-array ''' if not rem: return result @@ -45,7 +50,7 @@ def diag_mat(rem=[], result=np.empty((0, 0))): class GlobFile: ''' - Import all the parameters from the config file and make them GLOBAL FORMOSA VARIABLES + Class that import all the parameters from the config file and make them GLOBAL FORMOSA VARIABLES. Author: Paulina Palma-Bifani ''' @@ -143,7 +148,7 @@ def __init__(self, config_file_path): # self.p_context = eval(config['config_pymultinest']['context']) # self.p_write_output = config['config_pymultinest']['write_output'] # self.p_log_zero = eval(config['config_pymultinest']['log_zero']) - # self.p_max_iter = eval(config['config_pymultinest']['max_iter']) + # self.p_max_iter = eval(config['config_pymultinest']['max_iter']) # self.p_init_MPI = config['config_pymultinest']['init_MPI'] # self.p_dump_callback = config['config_pymultinest']['dump_callback'] # self.p_use_MPI = config['config_pymultinest']['use_MPI'] @@ -172,7 +177,7 @@ def __init__(self, config_file_path): # print() # # config_current = self.result_path + '/past_config.ini' - config.filename = ' ' + # config.filename = ' ' # config['config_path']['stock_interp_grid'] = stock_interp_grid # config['config_path']['stock_result'] = stock_result_subsub_dir # config.write() diff --git a/ForMoSA/nested_sampling/nested_logL_functions.py b/ForMoSA/nested_sampling/nested_logL_functions.py index 3dab1d9..6e581b3 100755 --- a/ForMoSA/nested_sampling/nested_logL_functions.py +++ b/ForMoSA/nested_sampling/nested_logL_functions.py @@ -3,13 +3,13 @@ def logL_chi2_classic(delta_flx, err): """ Function to compute logL based on the classical chi2 - under the assumption of gaussian and spectrally uncorrelated noise + under the assumption of gaussian and spectrally uncorrelated noise. Args: - delta_flx : residual data-model as a function of wavelength - err : error (=standard deviation) of the observed spectrum as a function of wavelength + delta_flx (array): residual data-model as a function of wavelength + err (array): error (=standard deviation) of the observed spectrum as a function of wavelength Returns: - logL : the loglikelihood value + - logL (float) : the loglikelihood value Author: Matthieu Ravet """ @@ -23,13 +23,13 @@ def logL_chi2_classic(delta_flx, err): def logL_chi2_covariance(delta_flx, inv_cov): """ Function to compute logL based on the generalized chi2 - under the assumption of gaussian and spectrally correlated noise + under the assumption of gaussian and spectrally correlated noise. Args: - delta_flx : residual data-model as a function of wavelength - inv_cov : inverse of the covariance matrix of the observed spectrum as a function of wavelength + delta_flx (array): residual data-model as a function of wavelength + inv_cov (n-array): inverse of the covariance matrix of the observed spectrum as a function of wavelength Returns: - logL : the loglikelihood value + - logL (float) : the loglikelihood value Author: Matthieu Ravet """ @@ -43,13 +43,13 @@ def logL_chi2_covariance(delta_flx, inv_cov): def logL_chi2_extended(delta_flx, err): """ Function to compute logL based on the extended chi2 - under the assumption of gaussian and spectrally uncorrelated noise + under the assumption of gaussian and spectrally uncorrelated noise. Args: - delta_flx : residual data-model as a function of wavelength - err : error (=standard deviation) of the observed spectrum as a function of wavelength + delta_flx (array): residual data-model as a function of wavelength + err (array): error (=standard deviation) of the observed spectrum as a function of wavelength Returns: - logL : the loglikelihood value + - logL (float) : the loglikelihood value Author: Allan Denis """ @@ -65,13 +65,13 @@ def logL_chi2_extended(delta_flx, err): def logL_chi2_extended_covariance(delta_flx, inv_cov): """ Function to compute logL based on the extended chi2 - under the assumption of gaussian and spectrally uncorrelated noise + under the assumption of gaussian and spectrally uncorrelated noise. Args: - delta_flx : residual data-model as a function of wavelength - err : error (=standard deviation) of the observed spectrum as a function of wavelength + delta_flx (array): residual data-model as a function of wavelength + err (array): error (=standard deviation) of the observed spectrum as a function of wavelength Returns: - logL : the loglikelihood value + - logL (float) : the loglikelihood value Author: Allan Denis """ @@ -89,13 +89,13 @@ def logL_full_covariance(delta_flx, inv_cov): """ Function to compute logL under the assumption of gaussian and spectrally correlated noise. This function is a generalized version of the logL_chi2_covariance and is to be used when dealing - with GP extimation of the covariance matrix + with GP extimation of the covariance matrix. Args: - delta_flx : residual data-model as a function of wavelength - inv_cov : inverse of the covariance matrix of the observed spectrum as a function of wavelength + delta_flx (array): residual data-model as a function of wavelength + inv_cov (n-array): inverse of the covariance matrix of the observed spectrum as a function of wavelength Returns: - logL : the loglikelihood value + - logL (float) : the loglikelihood value Author: Matthieu Ravet """ @@ -108,13 +108,13 @@ def logL_full_covariance(delta_flx, inv_cov): def logL_CCF_Brogi(flx_obs, flx_mod): """ Function to compute logL based on the CCF mapping from Brogi et al. 2019 - under the assumption of gaussian and spectrally constant noise + under the assumption of gaussian and spectrally constant noise. Args: - flx_obs : flux of the observation as a function of wavelength - flx_mod : flux of the model as a function of wavelength + flx_obs (array): flux of the observation as a function of wavelength + flx_mod (array): flux of the model as a function of wavelength Returns: - logL : the loglikelihood value + - logL (float) : the loglikelihood value Author: Matthieu Ravet """ @@ -132,13 +132,13 @@ def logL_CCF_Brogi(flx_obs, flx_mod): def logL_CCF_Zucker(flx_obs, flx_mod): """ Function to compute logL based on the CCF mapping from Zucker 2003 - under the assumption of gaussian and spectrally constant noise + under the assumption of gaussian and spectrally constant noise. Args: - flx_obs : flux of the observation as a function of wavelength - flx_mod : flux of the model as a function of wavelength + flx_obs (array): flux of the observation as a function of wavelength + flx_mod (array): flux of the model as a function of wavelength Returns: - logL : the loglikelihood value + - logL (float) : the loglikelihood value Author: Matthieu Ravet """ @@ -157,14 +157,14 @@ def logL_CCF_Zucker(flx_obs, flx_mod): def logL_CCF_custom(flx_obs, flx_mod, err_obs): """ Function to compute logL based on the custom CCF mapping from Me - under the assumption of gaussian and spectrally constant noise + under the assumption of gaussian and spectrally constant noise. Args: - flx_obs : flux of the observation as a function of wavelength - flx_mod : flux of the model as a function of wavelength - err_obs : errors of the observation as a function of wavelength + flx_obs (array): flux of the observation as a function of wavelength + flx_mod (array): flux of the model as a function of wavelength + err_obs (array): errors of the observation as a function of wavelength Returns: - logL : the loglikelihood value + - logL (float) : the loglikelihood value Author: Matthieu Ravet """ diff --git a/ForMoSA/nested_sampling/nested_modif_spec.py b/ForMoSA/nested_sampling/nested_modif_spec.py index d849599..cea9c65 100755 --- a/ForMoSA/nested_sampling/nested_modif_spec.py +++ b/ForMoSA/nested_sampling/nested_modif_spec.py @@ -1,12 +1,9 @@ import numpy as np -import xarray as xr import extinction from scipy.interpolate import interp1d import astropy.units as u import astropy.constants as const -from PyAstronomy.pyasl import dopplerShift, rotBroad, fastRotBroad -from adapt.extraction_functions import resolution_decreasing, convolve_and_sample -import scipy.ndimage as ndi +from PyAstronomy.pyasl import rotBroad, fastRotBroad import scipy.signal as sg import scipy.optimize as optimize import matplotlib.pyplot as plt @@ -20,19 +17,22 @@ def lsq_fct(global_params, wave, indobs, flx_obs_spectro, err_obs_spectro, star_ Estimation of the contribution of the planet and of the star to a spectrum (Used for HiRISE data) Args: - flx_obs_spectro : Flux of the data (spectroscopy) - err_obs_spectro : Error of the data (spectroscopy) - star_flx_obs : Flux of star observation data (spectroscopy) - transm_obs : Transmission (Atmospheric + Instrumental) - system_obs : Systematics of the data (spectroscopy) - flx_mod_spectro : Flux of interpolated synthetic spectrum (spectroscopy) - + flx_obs_spectro (array): Flux of the data (spectroscopy) + err_obs_spectro (array): Error of the data (spectroscopy) + star_flx_obs (n-array): Flux of star observation data (spectroscopy) + transm_obs (array): Transmission (Atmospheric + Instrumental) + system_obs (n-array): Systematics of the data (spectroscopy) + flx_mod_spectro (array): Flux of interpolated synthetic spectrum (spectroscopy) Returns: - cp : Planetary contribution to the data (Spectroscopy) - cs : Stellar contribution to the data (Spectroscopy) - flx_mod_spectro : New model of the companion - flx_obs_spectro : New flux of the data - star_flx_obs : New star flux of the data + - cp (array) : Planetary contribution to the data (Spectroscopy) + - cs (array) : Stellar contribution to the data (Spectroscopy) + - flx_mod_spectro (array) : New model of the companion + - flx_obs_spectro (array) : New flux of the data + - star_flx_obs (n-array) : New star flux of the data + - systematics (array) : The systematics + + Author : Allan Denis + """ wave_final, cp_final, cs_final, flx_mod_spectro_final, flx_obs_spectro_final, star_flx_obs_final, systematics_final, flx_mod_spectro_nativ, err_obs_spectro_final = np.array([]), np.array([]), np.array([]), np.array([]), np.array([]), np.array([]), np.array([]), np.array([]), np.array([]) @@ -141,28 +141,28 @@ def calc_ck(flx_obs_spectro, err_obs_spectro, flx_mod_spectro, flx_obs_photo, er and distance or analytically). Args: - flx_obs_spectro : Flux of the data (spectroscopy) - err_obs_spectro : Error of the data (spectroscopy) - flx_mod_spectro : Flux of the interpolated synthetic spectrum (spectroscopy) - flx_obs_photo : Flux of the data (photometry) - err_obs_photo : Error of the data (photometry) - flx_mod_photo : Flux of the interpolated synthetic spectrum (photometry) - r_picked : Radius randomly picked by the nested sampling (in RJup) - d_picked : Distance randomly picked by the nested sampling (in pc) - alpha : Manual scaling factor (set to 1 by default) such that ck = alpha * (r/d)² - analytic : = 'yes' if Ck needs to be calculated analytically by the formula from Cushing et al. (2008) + flx_obs_spectro (array): Flux of the data (spectroscopy) + err_obs_spectro (array): Error of the data (spectroscopy) + flx_mod_spectro (array): Flux of the interpolated synthetic spectrum (spectroscopy) + flx_obs_photo (array): Flux of the data (photometry) + err_obs_photo (array): Error of the data (photometry) + flx_mod_photo (array): Flux of the interpolated synthetic spectrum (photometry) + r_picked (float): Radius randomly picked by the nested sampling (in RJup) + d_picked (float): Distance randomly picked by the nested sampling (in pc) + alpha (float): Manual scaling factor (set to 1 by default) such that ck = alpha * (r/d)² + analytic (str): = 'yes' if Ck needs to be calculated analytically by the formula from Cushing et al. (2008) Returns: - flx_mod_spectro : Re-normalysed model spectrum - flx_mod_photo : Re-normalysed model photometry - ck : Ck calculated + - flx_mod_spectro (array) : Re-normalysed model spectrum + - flx_mod_photo (array) : Re-normalysed model photometry + - ck (float) : Ck calculated Author: Simon Petrus """ # Calculation of the dilution factor ck as a function of the radius and distance if analytic == 'no': - r_picked *= 69911 - d_picked *= 3.086e+13 - ck = alpha * (r_picked/d_picked)**2 + r_picked *= u.Rjup + d_picked *= u.pc + ck = alpha * (r_picked.value/d_picked.value)**2 # Calculation of the dilution factor ck analytically else: if len(flx_obs_spectro) != 0: @@ -197,37 +197,25 @@ def doppler_fct(wav_obs_spectro, flx_obs_spectro, err_obs_spectro, flx_mod_spect Note: Observation can change due to side effects of the shifting. Args: - wav_obs_spectro : Wavelength grid of the data - flx_obs_spectro : Flux of the data - err_obs_spectro : Error of the data - flx_mod_spectro : Flux of the interpolated synthetic spectrum - rv_picked : Radial velocity randomly picked by the nested sampling (in km.s-1) + wav_obs_spectro (array): Wavelength grid of the data + flx_obs_spectro (array): Flux of the data + err_obs_spectro (array): Error of the data + flx_mod_spectro (array): Flux of the interpolated synthetic spectrum + rv_picked (float): Radial velocity randomly picked by the nested sampling (in km.s-1) Returns: - wav_obs_spectro : New wavelength grid of the data - flx_obs_spectro : New flux of the data - err_obs_spectro : New error of the data - flx_post_doppler : New flux of the interpolated synthetic spectrum + - wav_obs_spectro (array) : New wavelength grid of the data + - flx_obs_spectro (array) : New flux of the data + - err_obs_spectro (array) : New error of the data + - flx_post_doppler (array) : New flux of the interpolated synthetic spectrum Author: Simon Petrus """ - # wav_doppler = wav_obs_spectro*10000 - # flx_post_doppler, wav_post_doppler = dopplerShift(wav_doppler, flx_mod_spectro, rv_picked) - new_wav = wav_obs_spectro * ((rv_picked / 299792.458) + 1) + new_wav = wav_obs_spectro * ((rv_picked / const.c.to(u.km/u.s).value) + 1) rv_interp = interp1d(new_wav, flx_mod_spectro, fill_value="extrapolate") flx_post_doppler = rv_interp(wav_obs_spectro) return wav_obs_spectro, flx_obs_spectro, err_obs_spectro, flx_post_doppler - # return Spectrum1d.from_array(new_wavelength, new_flux) - # # Side effects - # ind_nonan = np.argwhere(~np.isnan(flx_post_doppler)) - # wav_obs_spectro = wav_obs_spectro[ind_nonan[:, 0]] - # flx_obs_spectro = flx_obs_spectro[ind_nonan[:, 0]] - # err_obs_spectro = err_obs_spectro[ind_nonan[:, 0]] - # flx_post_doppler = flx_post_doppler[ind_nonan[:, 0]] - - # return wav_obs_spectro, flx_obs_spectro, err_obs_spectro, flx_post_doppler - # ---------------------------------------------------------------------------------------------------------------------- @@ -237,14 +225,14 @@ def reddening_fct(wav_obs_spectro, wav_obs_photo, flx_mod_spectro, flx_mod_photo extinction.fm07. Args: - wav_obs_spectro : Wavelength grid of the data (spectroscopy) - wav_obs_photo : Wavelength of the data (photometry) - flx_mod_spectro : Flux of the interpolated synthetic spectrum (spectroscopy) - flx_mod_photo : Flux of the interpolated synthetic spectrum (photometry) - av_picked : Extinction randomly picked by the nested sampling (in mag) + wav_obs_spectro (array): Wavelength grid of the data (spectroscopy) + wav_obs_photo (array): Wavelength of the data (photometry) + flx_mod_spectro (array): Flux of the interpolated synthetic spectrum (spectroscopy) + flx_mod_photo (array): Flux of the interpolated synthetic spectrum (photometry) + av_picked (float): Extinction randomly picked by the nested sampling (in mag) Returns: - flx_mod_spectro : New flux of the interpolated synthetic spectrum (spectroscopy) - flx_mod_photo : New flux of the interpolated synthetic spectrum (photometry) + - flx_mod_spectro (array) : New flux of the interpolated synthetic spectrum (spectroscopy) + - flx_mod_photo (array) : New flux of the interpolated synthetic spectrum (photometry) Author: Simon Petrus """ @@ -266,12 +254,12 @@ def vsini_fct_rot_broad(wav_obs_spectro, flx_mod_spectro, ld_picked, vsini_picke extinction.fm07. Args: - wav_obs_spectro : Wavelength grid of the data - flx_mod_spectro : Flux of the interpolated synthetic spectrum - ld_picked : Limd darkening randomly picked by the nested sampling - vsini_picked : v.sin(i) randomly picked by the nested sampling (in km.s-1) + wav_obs_spectro (array): Wavelength grid of the data + flx_mod_spectro (array): Flux of the interpolated synthetic spectrum + ld_picked (float): Limd darkening randomly picked by the nested sampling + vsini_picked (float): v.sin(i) randomly picked by the nested sampling (in km.s-1) Returns: - flx_mod_spectro : New flux of the interpolated synthetic spectrum + - flx_mod_spectro (array) : New flux of the interpolated synthetic spectrum Author: Simon Petrus """ @@ -297,12 +285,12 @@ def vsini_fct_fast_rot_broad(wav_obs_spectro, flx_mod_spectro, ld_picked, vsini_ extinction.fm07. Args: - wav_obs_spectro : Wavelength grid of the data - flx_mod_spectro : Flux of the interpolated synthetic spectrum - ld_picked : Limd darkening randomly picked by the nested sampling - vsini_picked : v.sin(i) randomly picked by the nested sampling (in km.s-1) + wav_obs_spectro (array): Wavelength grid of the data + flx_mod_spectro (array): Flux of the interpolated synthetic spectrum + ld_picked (float): Limd darkening randomly picked by the nested sampling + vsini_picked (float): v.sin(i) randomly picked by the nested sampling (in km.s-1) Returns: - flx_mod_spectro : New flux of the interpolated synthetic spectrum + - flx_mod_spectro (array) : New flux of the interpolated synthetic spectrum Author: Simon Petrus """ @@ -324,31 +312,25 @@ def vsini_fct_fast_rot_broad(wav_obs_spectro, flx_mod_spectro, ld_picked, vsini_ def vsini_fct_accurate(wave_obs_merge, flx_mod_spectro, ld_picked, vsini_picked, nr=50, ntheta=100, dif=0.0): ''' A routine to quickly rotationally broaden a spectrum in linear time. + Adapted from Carvalho & Johns-Krull 2023 https://ui.adsabs.harvard.edu/abs/2023RNAAS...7...91C/abstract - Carvalho & Johns-Krull 2023 - https://ui.adsabs.harvard.edu/abs/2023RNAAS...7...91C/abstract - - ARGS: - wav_obs_spectro : Wavelength grid of the data - flx_mod_spectro : Flux of the interpolated synthetic spectrum - ld_picked : Limd darkening randomly picked by the nested sampling - vsini_picked : v.sin(i) randomly picked by the nested sampling (in km.s-1) - + Args: + wav_obs_spectro (array): Wavelength grid of the data + flx_mod_spectro (array): Flux of the interpolated synthetic spectrum + ld_picked (float): Limd darkening randomly picked by the nested sampling + vsini_picked (float): v.sin(i) randomly picked by the nested sampling (in km.s-1) + nr (int): (default = 10) The number of radial bins on the projected disk + ntheta (int): (default = 100) The number of azimuthal bins in the largest radial annulus + note: the number of bins at each r is int(r*ntheta) where r < 1 + dif (float): (default = 0) The differential rotation coefficient, applied according to the law Omeg(th)/Omeg(eq) = (1 - dif/2 - (dif/2) cos(2 th)). + Dif = .675 nicely reproduces the law proposed by Smith, 1994, A&A, Vol. 287, p. 523-534, to unify WTTS and CTTS. + Dif = .23 is similar to observed solar differential rotation. Note: the th in the above expression is the stellar co-latitude, not the same as the integration variable used below. + This is a disk integration routine. Returns: - flx_mod_spectro : New flux of the interpolated synthetic spectrum + - flx_mod_spectro (array) : New flux of the interpolated synthetic spectrum - OPTIONAL ARGS: - nr (default = 10) : The number of radial bins on the projected disk - ntheta (default = 100) : The number of azimuthal bins in the largest radial annulus - note: the number of bins at each r is int(r*ntheta) where r < 1 - - dif (default = 0) : The differential rotation coefficient, applied according to the law - Omeg(th)/Omeg(eq) = (1 - dif/2 - (dif/2) cos(2 th)). Dif = .675 nicely reproduces the law - proposed by Smith, 1994, A&A, Vol. 287, p. 523-534, to unify WTTS and CTTS. Dif = .23 is - similar to observed solar differential rotation. Note: the th in the above expression is - the stellar co-latitude, not the same as the integration variable used below. This is a - disk integration routine. - ''' + Author: Allan Denis + ''' ns = np.copy(flx_mod_spectro)*0.0 tarea = 0.0 @@ -360,11 +342,11 @@ def vsini_fct_accurate(wave_obs_merge, flx_mod_spectro, ld_picked, vsini_picked, th = np.pi/int(ntheta*r) + k * 2.0*np.pi/int(ntheta*r) if dif != 0: vl = vsini_picked * r * np.sin(th) * (1.0 - dif/2.0 - dif/2.0*np.cos(2.0*np.arccos(r*np.cos(th)))) - ns += area * np.interp(wave_obs_merge + wave_obs_merge*vl/2.9979e5, wave_obs_merge, flx_mod_spectro) + ns += area * np.interp(wave_obs_merge + wave_obs_merge*vl/const.c.to(u.km/u.s).value, wave_obs_merge, flx_mod_spectro) tarea += area else: vl = r * vsini_picked * np.sin(th) - ns += area * np.interp(wave_obs_merge + wave_obs_merge*vl/2.9979e5, wave_obs_merge, flx_mod_spectro) + ns += area * np.interp(wave_obs_merge + wave_obs_merge*vl/const.c.to(u.km/u.s).value, wave_obs_merge, flx_mod_spectro) tarea += area flx_mod_spectro = ns / tarea @@ -373,20 +355,21 @@ def vsini_fct_accurate(wave_obs_merge, flx_mod_spectro, ld_picked, vsini_picked, # ---------------------------------------------------------------------------------------------------------------------- def bb_cpd_fct(wav_obs_spectro, wav_obs_photo, flx_mod_spectro, flx_mod_photo, distance, bb_T_picked, bb_R_picked): - ''' Function to add the effect of a cpd (circum planetary disc) to the models - Args: - wav_obs_spectro : Wavelength grid of the data (spectroscopy) - wav_obs_photo : Wavelength of the data (photometry) - flx_mod_spectro : Flux of the interpolated synthetic spectrum (spectroscopy) - flx_mod_photo : Flux of the interpolated synthetic spectrum (photometry) - bb_temp : Temperature value randomly picked by the nested sampling in K units - bb_rad : Radius randomly picked by the nested sampling in units of planetary radius + ''' + Function to add the effect of a cpd (circum planetary disc) to the models. + Args: + wav_obs_spectro (array): Wavelength grid of the data (spectroscopy) + wav_obs_photo (array): Wavelength of the data (photometry) + flx_mod_spectro (array): Flux of the interpolated synthetic spectrum (spectroscopy) + flx_mod_photo (array): Flux of the interpolated synthetic spectrum (photometry) + bb_temp (float): Temperature value randomly picked by the nested sampling in K units + bb_rad (float): Radius randomly picked by the nested sampling in units of planetary radius Returns: - flx_mod_spectro : New flux of the interpolated synthetic spectrum (spectroscopy) - flx_mod_photo : New flux of the interpolated synthetic spectrum (photometry) + - flx_mod_spectro (array) : New flux of the interpolated synthetic spectrum (spectroscopy) + - flx_mod_photo (array) : New flux of the interpolated synthetic spectrum (photometry) - Author: P. Palma-Bifani + Author: Paulina Palma-Bifani ''' bb_T_picked *= u.K @@ -402,12 +385,8 @@ def planck(wav, T): bb_intensity = planck(wav_obs_spectro*u.um, bb_T_picked) bb_intensity_f = planck(wav_obs_photo*u.um, bb_T_picked) - #flux_bb_lambda = ( np.pi * (bb_R_picked)**2 / ( ck*u.km **2) * bb_intensity ).to(u.W/u.m**2/u.micron) - flux_bb_lambda = ( 4*np.pi*bb_R_picked**2/(distance**2) * bb_intensity ).to(u.W/u.m**2/u.micron) - - #flux_bb_lambda_f = ( np.pi * (bb_R_picked)**2 / ( ck*u.km **2) * bb_intensity_f ).to(u.W/u.m**2/u.micron) - flux_bb_lambda_f = ( 4*np.pi*bb_R_picked**2/(distance**2) * bb_intensity_f ).to(u.W/u.m**2/u.micron) - + flux_bb_lambda = ( np.pi*bb_R_picked**2/(distance**2) * bb_intensity ).to(u.W/u.m**2/u.micron) + flux_bb_lambda_f = ( np.pi*bb_R_picked**2/(distance**2) * bb_intensity_f ).to(u.W/u.m**2/u.micron) # add to model flux of the atmosphere flx_mod_spectro += flux_bb_lambda.value @@ -419,82 +398,41 @@ def planck(wav, T): # ---------------------------------------------------------------------------------------------------------------------- -def reso_fct(global_params, theta, theta_index, wav_obs_spectro, flx_mod_spectro, reso_picked): - """ - WORKING! - Function to scale the spectral resolution of the synthetic spectra. This option is currently in test and make use - of the functions defined in the 'adapt' section of ForMoSA, meaning that they will significantly decrease the speed of - your inversion as the grid needs to be re-interpolated - - Args: - global_params : Class containing each parameter - theta : Parameter values randomly picked by the nested sampling - theta_index : Parameter index identificator - wav_obs_spectro : Wavelength grid of the data - flx_mod_spectro : Flux of the interpolated synthetic spectrum - reso_picked : Spectral resolution randomly picked by the nested sampling - Returns: - None - - Author: Matthieu Ravet - """ - - # Import the grid and set it with the right parameters - ds = xr.open_dataset(global_params.model_path, decode_cf=False, engine="netcdf4") - wav_mod_nativ = ds["wavelength"].values - grid = ds['grid'] - attr = ds.attrs - grid_np = grid.to_numpy() - model_to_adapt = grid_np[:, theta] - - # Modify the spectrum with the wanted spectral resolution - flx_mod_extract, mod_pho = adapt_model(global_params, wav_mod_nativ, model_to_adapt, attr['res'], obs_name=obs_name, - indobs=indobs) - - return - - -# ---------------------------------------------------------------------------------------------------------------------- - - def modif_spec(global_params, theta, theta_index, wav_obs_spectro, flx_obs_spectro, err_obs_spectro, flx_mod_spectro, wav_obs_photo, flx_obs_photo, err_obs_photo, flx_mod_photo, transm_obs = [], star_flx_obs = [], system_obs = [], indobs=0): """ - Modification of the interpolated synthetic spectra with the different extra-grid parameters: - - Re-calibration on the data - - Doppler shifting - - Application of a substellar extinction - - Application of a rotational velocity - - Application of a circumplanetary disk (CPD) + Modification of the interpolated synthetic spectra with the different extra-grid parameters. + It can perform : Re-calibration on the data, Doppler shifting, Application of a substellar extinction, Application of a rotational velocity, + Application of a circumplanetary disk (CPD). Args: - global_params : Class containing each parameter - theta : Parameter values randomly picked by the nested sampling - theta_index : Parameter index identificator - wav_obs_spectro : Wavelength grid of the data (spectroscopy) - flx_obs_spectro : Flux of the data (spectroscopy) - err_obs_spectro : Error of the data (spectroscopy) - flx_mod_spectro : Flux of the interpolated synthetic spectrum (spectroscopy) - wav_obs_photo : Wavelength grid of the data (photometry) - flx_obs_photo : Flux of the data (photometry) - err_obs_photo : Error of the data (photometry) - flx_mod_photo : Flux of the interpolated synthetic spectrum (photometry) - transm_obs : Transmission (Atmospheric + Instrumental) - star_flx_obs : Flux of star observation data (spectroscopy) - system_obs : Systematics of the data (spectroscopy) - indobs (int): Index of the current observation looping + global_params (object): Class containing each parameter + theta (list): Parameter values randomly picked by the nested sampling + theta_index (list): Parameter index identificator + wav_obs_spectro (array): Wavelength grid of the data (spectroscopy) + flx_obs_spectro (array): Flux of the data (spectroscopy) + err_obs_spectro (array): Error of the data (spectroscopy) + flx_mod_spectro (array): Flux of the interpolated synthetic spectrum (spectroscopy) + wav_obs_photo (array): Wavelength grid of the data (photometry) + flx_obs_photo (array): Flux of the data (photometry) + err_obs_photo (array): Error of the data (photometry) + flx_mod_photo (array): Flux of the interpolated synthetic spectrum (photometry) + transm_obs (array): Transmission (Atmospheric + Instrumental) + star_flx_obs (n-array): Flux of star observation data (spectroscopy) + system_obs (n-array): Systematics of the data (spectroscopy) + indobs (int): Index of the current observation looping Returns: - wav_obs_spectro : New wavelength grid of the data (may change with the Doppler shift) - flx_obs_spectro : New flux of the data (may change with the Doppler shift) - err_obs_spectro : New error of the data (may change with the Doppler shift) - flx_mod_spectro : New flux of the interpolated synthetic spectrum (spectroscopy) - wav_obs_photo : Wavelength grid of the data (photometry) - flx_obs_photo : Flux of the data (photometry) - err_obs_photo : Error of the data (photometry) - flx_mod_photo : New flux of the interpolated synthetic spectrum (photometry) + - wav_obs_spectro (array) : New wavelength grid of the data (may change with the Doppler shift) + - flx_obs_spectro (array) : New flux of the data (may change with the Doppler shift) + - err_obs_spectro (array) : New error of the data (may change with the Doppler shift) + - flx_mod_spectro (array) : New flux of the interpolated synthetic spectrum (spectroscopy) + - wav_obs_photo (array) : Wavelength grid of the data (photometry) + - flx_obs_photo (array) : Flux of the data (photometry) + - err_obs_photo (array) : Error of the data (photometry) + - flx_mod_photo (array) : New flux of the interpolated synthetic spectrum (photometry) - Author: Simon Petrus and Paulina Palma-Bifani + Author: Simon Petrus, Paulina Palma-Bifani, Allan Denis and Matthieu Ravet """ # Correction of the radial velocity of the interpolated synthetic spectrum. if len(flx_obs_spectro) != 0: diff --git a/ForMoSA/nested_sampling/nested_prior_function.py b/ForMoSA/nested_sampling/nested_prior_function.py index d782458..a107ff3 100755 --- a/ForMoSA/nested_sampling/nested_prior_function.py +++ b/ForMoSA/nested_sampling/nested_prior_function.py @@ -3,14 +3,15 @@ def uniform_prior(prior_fct_arg, theta): ''' - Uniform prior for nested sampling + Uniform prior for nested sampling. Args: prior_fct_arg (list): Two-values list with uniform prior boundaries. theta (list): Parameter values randomly picked by the nested sampling - Returns: - Evaluated (float): Evaluated prior + - Evaluated (float): Evaluated prior + + Author: Simon Petrus ''' arg1 = float(prior_fct_arg[0]) arg2 = float(prior_fct_arg[1]) @@ -19,13 +20,15 @@ def uniform_prior(prior_fct_arg, theta): def gaussian_prior(prior_fct_arg, theta): ''' - Gaussian prior for nested sampling + Gaussian prior for nested sampling. Args: prior_fct_arg (list): Two-values list with uniform prior boundaries. theta (list): Parameter values randomly picked by the nested sampling Returns: - Evaluated (float): Evaluated prior + - Evaluated (float): Evaluated prior + + Author: Simon Petrus ''' arg1 = float(prior_fct_arg[0]) arg2 = float(prior_fct_arg[1]) diff --git a/ForMoSA/nested_sampling/nested_sampling.py b/ForMoSA/nested_sampling/nested_sampling.py index 9915229..72f3f32 100755 --- a/ForMoSA/nested_sampling/nested_sampling.py +++ b/ForMoSA/nested_sampling/nested_sampling.py @@ -1,18 +1,17 @@ import numpy as np -import os +import os, sys import glob import nestle import time import xarray as xr import pickle +sys.path.insert(0, os.path.abspath('../')) + from nested_sampling.nested_modif_spec import modif_spec from nested_sampling.nested_prior_function import uniform_prior, gaussian_prior from nested_sampling.nested_logL_functions import * from main_utilities import diag_mat -import matplotlib.pyplot as plt - -c = 299792.458 # Speed of light in km/s def import_obsmod(global_params): @@ -23,7 +22,7 @@ def import_obsmod(global_params): global_params (object): Class containing every input from the .ini file. Returns: - main_file (list(array)): return a list of lists with the wavelengths, flux, errors, covariance matrix, + - main_file (list(array)): Return a list of lists with the wavelengths, flux, errors, covariance matrix, transmission, star flux, systematics and the grids for both spectroscopic and photometric data. Authors: Simon Petrus, Matthieu Ravet and Allan Denis @@ -76,6 +75,7 @@ def loglike(theta, theta_index, global_params, main_file, for_plot='no'): """ Function that calculates the logarithm of the likelihood. The evaluation depends on the choice of likelihood. + (If this function is used on the plotting module, it returns the outputs of the modif_spec function) Args: theta (list): Parameter values randomly picked by the nested sampling @@ -85,8 +85,7 @@ def loglike(theta, theta_index, global_params, main_file, for_plot='no'): for_plot (str): Default is 'no'. When this function is called from the plotting functions module, we use 'yes' Returns: - FINAL_logL (float): Final evaluated loglikelihood for both spectra and photometry. - (If this function is used on the plotting module, it returns the outputs of the modif_spec function) + - FINAL_logL (float): Final evaluated loglikelihood for both spectra and photometry. Authors: Simon Petrus, Matthieu Ravet and Allan Denis """ @@ -301,9 +300,9 @@ def prior_transform(theta, theta_index, lim_param_grid, global_params): global_params (object): Class containing every input from the .ini file. Returns: - prior (list): List containing all the prior information + - prior (list): List containing all the prior information - Author: Simon Petrus + Author: Simon Petrus, Matthieu Ravet, Allan Denis """ prior = [] if global_params.par1 != 'NA': @@ -752,46 +751,46 @@ def launch_nested_sampling(global_params): print('%15s : %.3f +- %.3f' % (name, col.mean(), col.std())) print('\n') - if global_params.ns_algo == 'ultranest': - import ultranest, ultranest.stepsampler + # if global_params.ns_algo == 'ultranest': + # import ultranest, ultranest.stepsampler - tmpstot1 = time.time() + # tmpstot1 = time.time() - loglike_gp = lambda theta: loglike(theta, theta_index, global_params) - - prior_transform_gp = lambda theta: prior_transform(theta, theta_index, lim_param_grid, global_params) - - sampler = ultranest.ReactiveNestedSampler(theta_index,loglike=loglike_gp, transform=prior_transform_gp, - wrapped_params=[False, False, False, False])#, - #log_dir=global_params.result_path, resume=True) - #result = sampler.run(min_num_live_points=100, max_ncalls=100000) - - # have to choose the number of steps the slice sampler should take - # after first results, this should be increased and checked for consistency. - nsteps = 2 * len(theta_index) - # create step sampler: - sampler.stepsampler = ultranest.stepsampler.SliceSampler(nsteps=nsteps, - generate_direction=ultranest.stepsampler.generate_mixture_random_direction, - # adaptive_nsteps=False, - # max_nsteps=40 - ) - sampler.print_results() - #sampler.plot_corner() - - tmpstot2 = time.time()-tmpstot1 - print(' ') - print('- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -') - print('-> Ultranest ') - print(' ') - print('The code spent ' + str(tmpstot2) + ' sec to run.') - print(result.summary()) - print('\n') + # loglike_gp = lambda theta: loglike(theta, theta_index, global_params) + + # prior_transform_gp = lambda theta: prior_transform(theta, theta_index, lim_param_grid, global_params) + + # sampler = ultranest.ReactiveNestedSampler(theta_index,loglike=loglike_gp, transform=prior_transform_gp, + # wrapped_params=[False, False, False, False])#, + # #log_dir=global_params.result_path, resume=True) + # #result = sampler.run(min_num_live_points=100, max_ncalls=100000) + + # # have to choose the number of steps the slice sampler should take + # # after first results, this should be increased and checked for consistency. + # nsteps = 2 * len(theta_index) + # # create step sampler: + # sampler.stepsampler = ultranest.stepsampler.SliceSampler(nsteps=nsteps, + # generate_direction=ultranest.stepsampler.generate_mixture_random_direction, + # # adaptive_nsteps=False, + # # max_nsteps=40 + # ) + # sampler.print_results() + # #sampler.plot_corner() + + # tmpstot2 = time.time()-tmpstot1 + # print(' ') + # print('- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -') + # print('-> Ultranest ') + # print(' ') + # print('The code spent ' + str(tmpstot2) + ' sec to run.') + # print(result.summary()) + # print('\n') - if global_params.ns_algo == 'dynesty': - from dynesty import NestedSampler + # if global_params.ns_algo == 'dynesty': + # from dynesty import NestedSampler - # initialize our nested sampler - #sampler = NestedSampler(loglike, ptform, ndim) + # initialize our nested sampler + # sampler = NestedSampler(loglike, ptform, ndim) result_reformat = {"samples": samples, "weights": weights, diff --git a/ForMoSA/plotting/plotting_class.py b/ForMoSA/plotting/plotting_class.py index acc73f1..a717e0a 100644 --- a/ForMoSA/plotting/plotting_class.py +++ b/ForMoSA/plotting/plotting_class.py @@ -1,22 +1,16 @@ from __future__ import print_function, division -import sys, os, yaml, time +import os, glob, sys import numpy as np import matplotlib.pyplot as plt -import matplotlib -from matplotlib.figure import Figure -import astropy.constants as const -import astropy.units as u +from matplotlib.backends.backend_pdf import PdfPages +from scipy.interpolate import interp1d import corner import xarray as xr import pickle -import scipy.signal as sg -from scipy.interpolate import interp1d -import extinction -from PyAstronomy.pyasl import dopplerShift, rotBroad -from spectres import spectres from tqdm import tqdm -import glob + +sys.path.insert(0, os.path.abspath('../')) import scipy.signal as sg # Import ForMoSA @@ -27,7 +21,7 @@ from nested_sampling.nested_modif_spec import vsini_fct_accurate from adapt.extraction_functions import resolution_decreasing, adapt_model, decoupe from adapt.extraction_functions import adapt_observation_range -from matplotlib.backends.backend_pdf import PdfPages + @@ -35,16 +29,16 @@ def bin_data(wave, data, bin_size): ''' Function to bin data given a bin size - Parameters - ---------- - wave : wavelength of the data - data : data - bin_size : size of the bin to apply + Args: + wave (array): wavelength of the data + data (array): data + bin_size (int): size of the bin to apply + + Returns: + - wave_binned (array): binned wavelength + - data_binned (array): binned data - Returns - ------- - wave_binned : binned wavelength - data_binned : binned data + Author: Allan Denis ''' # First quick check that len of data is a multpiple of bin_size while(len(data)%bin_size != 0): @@ -62,12 +56,25 @@ def bin_data(wave, data, bin_size): # ---------------------------------------------------------------------------------------------------------------------- class ComplexRadar(): ''' - Original from Damian Cummins: https://github.com/DamianCummins/statsbomb-football-event-visualisations/blob/master/Statsbomb%20Womens%20World%20Cup%202019%20visualisation.ipynb - - Adapted by: P. Palma-Bifani + Class to create Radar plots with asymmetric error bars. + + Author: Paulina Palma-Bifani + Adapted from Damian Cummins: https://github.com/DamianCummins/statsbomb-football-event-visualisations/blob/master/Statsbomb%20Womens%20World%20Cup%202019%20visualisation.ipynb + ''' def __init__(self, fig, variables, ranges, n_ordinate_levels=6): + ''' + Initialize class. + + Args: + fig (object): matplotlib figure object + variables (list): list of parameters to plot + ranges (list(tuple)): upper and lower limits for each parameters + n_ordinate_levels (int): (default = 6) number of gridlines in the plot + Returns: + None + ''' angles = np.arange(0, 360, 360./len(variables)) axes = [fig.add_axes([0.1,0.1,0.9,0.9], polar=True, label = "axes{}".format(i)) for i in range(len(variables))] @@ -98,20 +105,61 @@ def __init__(self, fig, variables, ranges, n_ordinate_levels=6): self.ax = axes[0] def plot(self, data, *args, **kw): + ''' + Function to display the plot. + + Args: + data (list): best value for each parameter + *args : Variable length argument list. + **kw : Arbitrary keyword arguments. + Returns: + None + ''' sdata = self.scale_data(data, self.ranges) self.ax.plot(self.angle, np.r_[sdata, sdata[0]], *args, **kw) def fill(self, data, *args, **kw): + ''' + Add symmetric error bars to the plot. + + Args: + data (list): best value for each parameter + *args : Variable length argument list. + **kw : Arbitrary keyword arguments. + Returns: + None + ''' sdata = self.scale_data(data, self.ranges) self.ax.fill(self.angle, np.r_[sdata, sdata[0]], *args, **kw) def fill_between(self, list_down, list_up, *args, **kw): + ''' + Add asymmetric error bars to the plot. + + Args: + list_down (list): list of lower error bars + list_up (list): list of upper error bars + *args : Variable length argument list. + **kw : Arbitrary keyword arguments. + Returns: + None + ''' sdata_down = self.scale_data(list_down, self.ranges) sdata_up = self.scale_data(list_up, self.ranges) self.ax.fill_between(self.angle,np.r_[sdata_down,sdata_down[0]], np.r_[sdata_up,sdata_up[0]], *args, **kw) def scale_data(self, data, ranges): - """scales data[1:] to ranges[0]""" + ''' + Function to check that lower and upper limits are correctly ordered. It scales data[1:] to ranges[0] + + Args: + data (list): best value for each parameter + ranges (list(tuple)): upper and lower limits for each parameters + *args : Variable length argument list. + **kw : Arbitrary keyword arguments. + Returns: + None + ''' for d, (y1, y2) in zip(data[1:], ranges[1:]): assert (y1 <= d <= y2) or (y2 <= d <= y1) x1, x2 = ranges[0] @@ -130,45 +178,47 @@ def scale_data(self, data, ranges): # ---------------------------------------------------------------------------------------------------------------------- class PlottingForMoSA(): ''' - Here all the plotting functionalities of ForMoSA to see the + Class containing all the plotting functionalities of ForMoSA. - Author: Paulina Palma-Bifani + Author: Paulina Palma-Bifani, Simon Petrus, Matthieu Ravet and Allan Denis ''' def __init__(self, config_file_path, color_out): ''' - Plotting class initializer + Initialize class by inheriting the global parameter class of ForMoSA. + + Args: + config_file_path (str): path to the config.ini file currently used + color_out (str): color to use for the model + Returns: + None ''' self.global_params = GlobFile(config_file_path) self.color_out = color_out - def _get_posteriors(self): ''' - Function to get the posteriors, including luminosity derivation and corvengence parameters logz + Function to get the posteriors, including luminosity derivation and Bayesian evidence logz. - (Adapted from Simon Petrus plotting functions) + Args: + None + Returns: + None ''' with open(self.global_params.result_path + '/result_' + self.global_params.ns_algo + '.pic', 'rb') as open_pic: result = pickle.load(open_pic) - # self.samples = result.samples self.samples = result['samples'] - # self.weights = result.weights self.weights = result['weights'] # To test the quality of the fit - # self.logl=result.logl self.logl=result['logl'] ind = np.where(self.logl==max(self.logl)) self.theta_best = self.samples[ind][0] - # self.sample_logz = round(result['logz'],1) - # self.sample_logzerr = round(result['logzerr'],1) self.sample_logz = round(result['logz'][0],1) self.sample_logzerr = round(result['logz'][1],1) - # self.outputs_string = 'logz = '+ str(self.sample_logz)+' ± '+str(self.sample_logzerr)+ ' ; h = '+str(self.sample_h) self.outputs_string = 'logz = '+ str(self.sample_logz)+' ± '+str(self.sample_logzerr) ds = xr.open_dataset(self.global_params.model_path, decode_cf=False, engine='netcdf4') @@ -291,7 +341,15 @@ def _get_posteriors(self): def plot_corner(self, levels_sig=[0.997, 0.95, 0.68], bins=100, quantiles=(0.16, 0.5, 0.84), burn_in=0): ''' - See the corner plots + Function to display the corner plot + + Args: + levels_sig (list): (default = [0.997, 0.95, 0.68]) 1, 2 and 3 sigma contour levels of the corner plot + bins (int): (default = 100) number of bins for the posteriors + quantiles (list): (default = (0.16, 0.5, 0.84)) mean +- sigma to report the posterior values + burn_in (int): (default = 0) number of steps to remove from the plot + Returns: + - fig (object): matplotlib figure object ''' print('ForMoSA - Corner plot') @@ -324,10 +382,16 @@ def plot_corner(self, levels_sig=[0.997, 0.95, 0.68], bins=100, quantiles=(0.16, return fig - def plot_chains(self,figsize=(7,15)): + def plot_chains(self, figsize=(7,15)): ''' - To check the convergence of the chains + Plot to check the convergence of the posterior chains. + Multiple (sub-)axis plot. + Args: + figsize (tuple): (default = (7, 15)) size of the plot + Returns: + - fig (object) : matplotlib figure object + - ax (object) : matplotlib axes objects ''' print('ForMoSA - Posteriors chains for each parameter') @@ -353,12 +417,19 @@ def plot_chains(self,figsize=(7,15)): return fig, axs - def plot_radar(self,ranges,label='',quantiles=[0.16, 0.5, 0.84],chiffres=[0,2,2,2]): + def plot_radar(self, ranges, label='', quantiles=[0.16, 0.5, 0.84]): ''' - To check overall the distribution of the parameters + Radar plot to check the distribution of the parameters. + Useful to compare different models. + + Args: + ranges (list(tuple)): upper and lower limits for each parameters + label (str): (default = '') label of the plot + quantiles (list): (default = (0.16, 0.5, 0.84)) mean +- sigma to report the posterior values + Returns: + - fig (object) : matplotlib figure object + - radar.ax (object) : matplotlib radar class axes object - Inputs: - ranges ''' print('ForMoSA - Radar plot') @@ -374,23 +445,30 @@ def plot_radar(self,ranges,label='',quantiles=[0.16, 0.5, 0.84],chiffres=[0,2,2, list_uncert_down.append(q16) list_uncert_up.append(q84) - fig1 = plt.figure(figsize=(6, 6)) - radar = ComplexRadar(fig1, self.posteriors_names, ranges) + fig = plt.figure(figsize=(6, 6)) + radar = ComplexRadar(fig, self.posteriors_names, ranges) radar.plot(list_posteriors, 'o-', color=self.color_out, label=label) radar.fill_between(list_uncert_down,list_uncert_up, color=self.color_out, alpha=0.2) radar.ax.legend(loc='center', bbox_to_anchor=(0.5, -0.20),frameon=False, ncol=2) - return fig1, radar.ax + return fig, radar.ax def _get_spectra(self,theta,return_model=False): ''' - To get the data and best model asociated - Use numba: https://numba.pydata.org/ + Function to get the data and best model asociated. - (Adapted from Simon Petrus) + Args: + theta (list): best parameter values + Returns: + - modif_spec_chi2 list(n-array): list containing the spectroscopic wavelength, spectroscopic fluxes of the data, + spectroscopic errors of the data, spectroscopic fluxes of the model, + photometric wavelength, photometric fluxes of the data, photometric errors of the data, + spectroscopic fluxes of the model, + planet transmission, star fluxes, systematics + - ck list(floats): list scaling factor(s) ''' # Get the posteriors self._get_posteriors() @@ -498,24 +576,21 @@ def _get_spectra(self,theta,return_model=False): return modif_spec_chi2, ck - def get_FULL_spectra(self, theta, grid_used = 'original', wavelengths=[], res_out=1000, re_interp=False, int_method="linear"): + def get_FULL_spectra(self, theta, grid_used = 'original', wavelengths=[], N_points=1000, re_interp=False, int_method="linear"): ''' - To get the data and best model asociated - Use numba: https://numba.pydata.org/. + Extract a model spectrum from another grid. Args: - theta: List of model and extra-model parameters. - grid_used: Default 'original' will use the raw grid. Else, input the path to your desired grid. - wavelengths: Default [] will use max values of the wav_for_adapt range to create a model spectrum. - Else, input the desired wavelength range. - res_out: Default 1000 will be the resolution of your model spectrum. Else, input the desired resolution. - re_interp: Default False. If true, will re-interpolate the grid's hole (WARNING, time consumming...). - int_method: Default "linear" will be the interpolation method use for the grid. Else, input the desired interpolation method. + theta: (list): best parameter values + grid_used: (str): (default = 'original') Path to the grid from where to extract the spectrum. If 'original', the current grid will be used. + wavelengths: (list): (default = []) Desired wavelength range. If [] max and min values of wav_for_adapt range will be use to create the wavelength range. + N_points: (int): (default = 1000) Number of points. + re_interp: (boolean): (default = False). Option to reinterpolate or not the grid. + int_method: (str): (default = "linear") Interpolation method for the grid (if reinterpolated). Returns: - fig, ax, axr, axr2 - - - Authors: Paulina Palma-Bifani and Matthieu Ravet + - wav_final (array): Wavelength array of the full model + - flx_final (array): Flux array of the full model + - ck (float): Scaling factor of the full model ''' self._get_posteriors() @@ -529,9 +604,9 @@ def get_FULL_spectra(self, theta, grid_used = 'original', wavelengths=[], res_ou else: wav = np.concatenate((wav, wav_ind)) wav = np.sort(wav) - wavelengths = np.linspace(wav[0],wav[-1],res_out) + wavelengths = np.linspace(wav[0],wav[-1],N_points) else: - wavelengths = np.linspace(wavelengths[0],wavelengths[-1],res_out) + wavelengths = np.linspace(wavelengths[0],wavelengths[-1],N_points) # Recover the original grid if grid_used == 'original': @@ -590,16 +665,17 @@ def plot_fit(self, figsize=(10, 5), uncert='no', trans='no', logx='no', logy='no Plot the best fit comparing with the data. Args: - figsize: x/y size of the plot - uncert: 'yes' or 'no' to plot spectra with associated error bars - trans: 'yes' or 'no' to plot transmision curves for photometry - logx: 'yes' or 'no' to plot the wavelength in log scale - logy: 'yes' or 'no' to plot the flux in log scale - norm: 'yes' or 'no' to plot the normalized spectra + figsize (tuple): (default = (10, 5)) Size of the plot + uncert (str): (default = no) 'yes' or 'no' to plot spectra with associated error bars + trans (str): (default = no) 'yes' or 'no' to plot transmision curves for photometry + logx (str): (default = no) 'yes' or 'no' to plot the wavelength in log scale + logy (str): (default = no) 'yes' or 'no' to plot the flux in log scale + norm (str): (default = no) 'yes' or 'no' to plot the normalized spectra Returns: - fig, ax, axr, axr2 - - Author: Paulina Palma-Bifani and Matthieu Ravet + - fig (object) : matplotlib figure object + - ax (object) : matplotlib axes objects, main spectra plot + - axr (object) : matplotlib axes objects, residuals + - axr2 (object) : matplotlib axes objects, right side density histogram ''' print('ForMoSA - Best fit and residuals plot') @@ -695,8 +771,6 @@ def plot_fit(self, figsize=(10, 5), uncert='no', trans='no', logx='no', logy='no iobs_photo = -1 - - # Set xlog-scale if logx == 'yes': ax.set_xscale('log') @@ -720,26 +794,24 @@ def plot_fit(self, figsize=(10, 5), uncert='no', trans='no', logx='no', logy='no # define the data as global self.spectra = spectra - #self.residuals = residuals return fig, ax, axr, axr2 def plot_fit_HiRes(self, figsize=(10, 5), uncert='no', trans='no', logx='no', logy='no', norm='no'): ''' - Plot the best fit comparing with the data. + Same as plot_fit but with the stellar and planetary models for high-resolution spectroscopy. Does not include residuals in a sub-axis. Args: - figsize: x/y size of the plot - uncert: 'yes' or 'no' to plot spectra with associated error bars - trans: 'yes' or 'no' to plot transmision curves for photometry - logx: 'yes' or 'no' to plot the wavelength in log scale - logy: 'yes' or 'no' to plot the flux in log scale - norm: 'yes' or 'no' to plot the normalized spectra + figsize (tuple): (default = (10, 5)) Size of the plot + uncert (str): (default = no) 'yes' or 'no' to plot spectra with associated error bars + trans (str): (default = no) 'yes' or 'no' to plot transmision curves for photometry + logx (str): (default = no) 'yes' or 'no' to plot the wavelength in log scale + logy (str): (default = no) 'yes' or 'no' to plot the flux in log scale + norm (str): (default = no) 'yes' or 'no' to plot the normalized spectra Returns: - fig, ax, axr, axr2 - - Author: Paulina Palma-Bifani and Matthieu Ravet + - fig (object) : matplotlib figure object + - ax (object) : matplotlib axes objects ''' print('ForMoSA - Best fit and residuals plot') @@ -825,35 +897,29 @@ def plot_fit_HiRes(self, figsize=(10, 5), uncert='no', trans='no', logx='no', lo else: ax1.set_ylabel(r'Normalised flux (W m-2 µm-1)') - ax1.set_xlabel('wavelength ($ \mu $m)') + ax1.set_xlabel(r'wavelength ($ \mu $m)') - fig1.legend(fontsize=18) - #ax.legend(frameon=False) + fig1.legend() plt.figure(fig1) plt.savefig(self.global_params.result_path + 'full_data.pdf') # define the data as global self.spectra = spectra - #self.residuals = residuals return fig1, ax1 - def plot_HiRes_comp_model(self, figsize=(10, 5), trans='no', logx='no', logy='no', norm='no', data_resolution = 0): + def plot_HiRes_comp_model(self, figsize=(10, 5), norm='no', data_resolution = 0): ''' - Plot the best fit comparing with the data. + Specific function to plot the best fit comparing with the data for high-resolution spectroscopy. Args: - figsize: x/y size of the plot - uncert: 'yes' or 'no' to plot spectra with associated error bars - trans: 'yes' or 'no' to plot transmision curves for photometry - logx: 'yes' or 'no' to plot the wavelength in log scale - logy: 'yes' or 'no' to plot the flux in log scale - norm: 'yes' or 'no' to plot the normalized spectra + figsize (tuple): (default = (10, 5)) Size of the plot + norm (str): (default = no) 'yes' or 'no' to plot the normalized spectra + data_resolution (int): (default = 0) Custom resolution to broadened data Returns: - fig, ax, axr, axr2 - - Author: Paulina Palma-Bifani and Matthieu Ravet + - fig1 (object) : matplotlib figure object + - ax1 (object) : matplotlib axes objects ''' print('ForMoSA - Planet model and data') @@ -906,8 +972,8 @@ def plot_HiRes_comp_model(self, figsize=(10, 5), trans='no', logx='no', logy='no ax.plot(wave, data_broadened, c='k') ax.plot(wave, planet_model_broadened, c='r') - ax.set_xlabel('wavelength ($\mu$m)', fontsize=18) - ax.set_ylabel('Flux (ADU)', fontsize=18) + ax.set_xlabel(r'wavelength ($\mu$m)') + ax.set_ylabel('Flux (ADU)') ax1.plot(wave, data, c='k') ax1.plot(wave, planet_model, c = 'r') @@ -917,21 +983,38 @@ def plot_HiRes_comp_model(self, figsize=(10, 5), trans='no', logx='no', logy='no else: legend_data = 'data' - ax.legend([legend_data, 'planet model'], fontsize=18) - ax.tick_params(axis='both', labelsize=18) + ax.legend([legend_data, 'planet model']) + ax.tick_params(axis='both') - ax1.legend([legend_data, "planet model"], fontsize = 18) - ax1.set_xlabel('wavelength ($ \mu $m)', fontsize=18) - ax1.tick_params(axis='both', labelsize=18) + ax1.legend([legend_data, "planet model"]) + ax1.set_xlabel('wavelength ($ \mu $m)') + ax1.tick_params(axis='both') return fig1, ax1, fig, ax def plot_ccf(self, rv_grid = [-300,300], rv_step = 0.5, figsize = (10,5), norm = 'no', window_normalisation = 100, model_spectra = [], model_wavelength = [], model_resolution = [], data_resolution = 0, model_name = 'Full', rv_cor=0, data_ccf = [], wave_ccf = [], star_ccf = [], transm_ccf = [], system_ccf = []): ''' - Plot the ccf (used for high resolution data such as CRIRES+ / HiRISE) - + Plot the cross-correlation function. It is used for high resolution spectroscopy. + + Args: + figsize (tuple): (default = (10, 5)) Size of the plot + rv_grid (list): (default = [-300,300]) Maximum and minumum values of the radial velocity shift (in km/s) + rv_step (float): (default = 0.5) Radial velocity shift steps (in km/s) + window_normalisation (int): (default = 100) ? + model_wavelength (list): (default = []) ? + model_spectra = (list): (default = []) ? + model_resolution (list): (default = []) ? + model_name (str): (default = 'Full') ? + rv_cor (int): (default = 0) ? + Returns: + - fig1 (object) : matplotlib figure object + - ax1 (object) : matplotlib axes objects + - rv_grid (list): Radial velocity grid + - ccf (list): Cross-correlation function + - acf (list): Auto-correlation function + Author: Allan Denis ''' print('ForMoSA - CCF plot') @@ -1071,17 +1154,24 @@ def plot_ccf(self, rv_grid = [-300,300], rv_step = 0.5, figsize = (10,5), norm = #ax1.set_title(f'SNR = {np.nanmax(ccf_norm):.1f}, RV = {rv_grid[np.argmax(ccf_norm)]:.1f} km/s') plt.figure(fig1) plt.savefig(self.global_params.result_path + 'ccf_' + model_name + '.pdf') - - return rv_grid, ccf_norm, acf_norm + + return fig1, ax1, rv_grid, ccf, acf - def plot_PT(self,path_temp_profile, figsize=(6,5), model = 'ExoREM'): - ''' - Plot the Pressure-Temperature profiles - Calculates the most probable temperature profile - Return: fig, ax - Author: Nathan Zimniak and Paulina Palma-Bifani + + def plot_PT(self, path_temp_profile, figsize=(6,5), model = 'ExoREM'): + ''' + Function to plot the Pressure-Temperature profiles. + Adpated from Nathan Zimniak. + + Args: + path_temp_profile (str): Path to the temperature profile grid + figsize (tuple): (default = (6, 5)) Size of the plot + model (str): (default = 'ExoREM') Name of the model grid + Returns: + - fig (object) : matplotlib figure object + - ax (object) : matplotlib axes objects ''' print('ForMoSA - Pressure-Temperature profile') @@ -1176,34 +1266,34 @@ def plot_PT(self,path_temp_profile, figsize=(6,5), model = 'ExoREM'): def plot_Clouds(self, cloud_prop, path_cloud_profile, figsize=(6,5)): ''' - Cloud profiles calculations - - Inputs: - - cloud_prop (str) : choose the cloud - 'eddy_diffusion_coefficient', - 'vmr_CH4', - 'vmr_CO', - 'vmr_CO2', - 'vmr_FeH', - 'vmr_H2O', - 'vmr_H2S', - 'vmr_HCN', - 'vmr_K', - 'vmr_Na', - 'vmr_NH3', - 'vmr_PH3', - 'vmr_TiO', - 'vmr_VO', - 'cloud_opacity_Fe', - 'cloud_opacity_Mg2SiO4', - 'cloud_particle_radius_Fe', - 'cloud_particle_radius_Mg2SiO4', - 'cloud_vmr_Fe', - 'cloud_vmr_Mg2SiO4' - - Return: fig, ax - - Author: Nathan Zimniak and Paulina Palma-Bifani + Function to plot cloud profiles. + Adapted from Nathan Zimniak + + Args: + cloud_prop (str) : Choose the cloud species. The options are + ['eddy_diffusion_coefficient', + 'vmr_CH4', + 'vmr_CO', + 'vmr_CO2', + 'vmr_FeH', + 'vmr_H2O', + 'vmr_H2S', + 'vmr_HCN', + 'vmr_K', + 'vmr_Na', + 'vmr_NH3', + 'vmr_PH3', + 'vmr_TiO', + 'vmr_VO', + 'cloud_opacity_Fe', + 'cloud_opacity_Mg2SiO4', + 'cloud_particle_radius_Fe', + 'cloud_particle_radius_Mg2SiO4', + 'cloud_vmr_Fe', + 'cloud_vmr_Mg2SiO4'] + Returns: + - fig (object) : matplotlib figure object + - ax (object) : matplotlib axes objects ''' print('ForMoSA - Cloud profile') @@ -1254,7 +1344,7 @@ def plot_Clouds(self, cloud_prop, path_cloud_profile, figsize=(6,5)): propsup95.append(np.percentile(cloud_prop_profiles[:, i], 98)) # Plot le profil le plus probable et les percentiles associés - fig = plt.figure() + fig = plt.figure(figsize=figsize) ax = plt.axes() ax.fill_betweenx(P, propinf95, propsup95, color=self.color_out, alpha=0.1, label=r'2 $\sigma$') diff --git a/LICENSE b/LICENSE index c932307..2394e35 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ -BSD 2-Clause License +BSD 3-Clause License -Copyright (c) 2022, exoAtmospheres +Copyright (c) 2022 - 2024, Paulina Palma-Bifani, Simon Petrus, Mickaël Bonnefoy, and Gaël Chauvin All rights reserved. Redistribution and use in source and binary forms, with or without @@ -13,6 +13,10 @@ modification, are permitted provided that the following conditions are met: this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE diff --git a/README.md b/README.md index 61d7763..8e7cfe3 100644 --- a/README.md +++ b/README.md @@ -1,84 +1,18 @@ -

ForMoSA

+

ForMoSA

-*** -Installation -=== - -We strongly recommend using a ``conda`` environment ([learn more here](https://conda.io/docs/user-guide/tasks/manage-environments.html)). - -To install and use our package in macOS with an M1 chip, proceed with the following sequence of commands: - -1/ To run parallelization without warnings, make sure you are building your environment under an OSX-ARM64 architecture ([learn more here](https://stackoverflow.com/questions/65415996/how-to-specify-the-architecture-or-platform-for-a-new-conda-environment-apple)). - - $ CONDA_SUBDIR=osx-arm64 conda create -n env_formosa python=3.11 numpy -c conda-forge - - $ conda activate env_formosa - - $ conda config --env --set subdir osx-arm64 - -2/ Install the following packages in your environment with pip install: - - $ pip install numpy matplotlib corner astropy scipy configobj extinction nestle PyAstronomy spectres pyyaml importlib-metadata==4.13.0 xarray==2023.10.1 - - -3/ To solve a standard error, run the following line in your environment: - - $ conda install xarray dask netCDF4 bottleneck - -4/ If you want to use Pymultinest to run your inversion, follow the installation instructions from [PyMultinest](https://johannesbuchner.github.io/PyMultiNest/install.html), detailed below. - -If you don't need PyMultinest, you can directly go to point 5/. - -First. Clone PyMultinest from GitHub and install it. - - $ git clone https://github.com/JohannesBuchner/PyMultiNest/ - $ cd PyMultiNest - $ python setup.py install - -Second. Make sure your system has a C++ and a Fortran interpreter. If you need to install brew, follow [these instructions](https://brew.sh/). - - $ brew install cmake - $ brew install gcc - $ brew install open-mpi +Welcome to ForMoSA, an open-source Python package. -Third. In your ForMoSA environment, install mpi4pi as: - - $ pip install mpi4py +We designed this tool to model exoplanetary atmospheres with a forward modeling approach. +We encourage you to exploit its capabilities! -Fourth. Install MultiNest by cloning the GitHub repository and building it. Make sure you empty the build folder if you run this step more than once. - - $ git clone https://github.com/JohannesBuchner/MultiNest - $ cd MultiNest/build - $ cmake .. - $ make - -Finally, copy the files that were generated by building MultiNest onto your conda (may be miniconda) environment by doing: - - $ cp -v ~/YOUR_PATH/MultiNest/lib/* /YOUR_PATH/opt/anaconda3/envs/env_formosa/lib/ - - -5/ The last instalation step is to actually get ForMoSA. ForMoSA can be installed throgh pip, however, to work on the final released version, please clone the main branch from our GitHub repository. You can do it by moving to the desired directory on your terminal and writing: - - $ git clone https://github.com/exoAtmospheres/ForMoSA.git - - -*** -Running the code -=== - -Follow the instructions in ForMoSA/DEMO +Get started at [https://formosa.readthedocs.io](https://formosa.readthedocs.io) *** -Issues? -=== - -If you encounter any other problem, please create an issue on GitHub ([https://github.com/exoAtmospheres/ForMoSA/issues](https://github.com/exoAtmospheres/ForMoSA/issues/new)). - -*** - -[![Documentation Status](https://readthedocs.org/projects/formosa/badge/?version=latest)](https://formosa.readthedocs.io/en/latest/?badge=latest) + [![PyPI version](https://badge.fury.io/py/formosa.svg)](https://badge.fury.io/py/formosa) [![PyPI downloads](https://img.shields.io/pypi/dm/formosa.svg)](https://pypistats.org/packages/formosa) -[![License](https://img.shields.io/badge/License-BSD_2--Clause-orange.svg)](https://opensource.org/licenses/BSD-2-Clause) +[![Documentation Status](https://readthedocs.org/projects/formosa/badge/?version=latest)](https://formosa.readthedocs.io/en/latest/?badge=latest) +[![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) [![A rectangular badge, half black half purple containing the text made at Code Astro](https://img.shields.io/badge/Made%20at-Code/Astro-blueviolet.svg)](https://semaphorep.github.io/codeastro/) + diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 9666866..59f2c0a 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -331,13 +331,63 @@ Tests that have been done to checkup the changes: - Different high resolution datasets - Datasets combining photometric and spectroscopic data points - + + + +- - - + +28/07/2024 + +Paulina Palma-Bifani, Matthieu Ravet + +Comments: + - Commenting all functions + - Replacing physical constants with astropy ones + +Tests: + None + + +- - - + +02/08/2024 + +Paulina Palma-Bifani + +Comments: + - Adapted docstrings returns in some functions (not all) + - Generated documentation for the webpage + - This is a test. I will do a second commit afterwards with the complete updated docs. + +Tests: + Webpage API is generating without issues locally (make html) + + + +- - - + +08/08/2024 + +Matthieu Ravet + +Comments: + - Correcting for the HiRISE type data merging when using cuts (i.e. remplacing axis=0 by axis=1). In the future, it would be + nice to create a more simple version of the star and systematic matrix (for now its (1, lambda, sys/star) it would be best to + have (lambda, sys/star) to avoid keeping large matrices accross the inversion) + +Tests: + - Test with CRIRES+ datasets with cuts in the adapt and in the fit + + +- - - 29/08/2024 +Allan Denis + Comments: - New approach in the adaptation of the data in the case where the user defined separated windows in 'wave_for_adapt' (eg : '1.4, 1.5 / 1.6, 1.7 / 1.8, 1.9 / ... '). Instead of making a loop on each sub-interval, we now combine the data in one array and do the adaptation on one array - New approach in the lsq function, we can now use the lsq in each sub wavelength separatly (eg. '1.4, 1.5', '1.6, 1.7', '1.8, 1.9' ...) and merge the results into a single array to compute the loglikelihood on one array only. This gives the advantage of limiting flux error calibration that can arrise between order for data such as CRIRES, HiRISE ... and being fast at the same time. Previously, the use had to define separated windows in 'wave_fit' (eg : '1.4, 1.5', '1.6, 1.7', '1.8, 1.9' ...) and one loglikelihood one computed for each of these windows. Now the user has to define separated windows in the format '1.4, 1.5 / 1.6, 1.7 / 1.8, 1.9 / ...' Tests tha have been done to checkup the changes: - - High resolution datasets (HiRISE, CRIRES) + - High resolution datasets (HiRISE, CRIRES) \ No newline at end of file diff --git a/build/lib/ForMoSA/__init__.py b/build/lib/ForMoSA/__init__.py index fd9425a..c9a7955 100644 --- a/build/lib/ForMoSA/__init__.py +++ b/build/lib/ForMoSA/__init__.py @@ -1,5 +1,5 @@ import os -__version__ = "2.0.0" +__version__ = "1.1.3" __all__ = ['adapt', 'nested_sampling','plotting'] \ No newline at end of file diff --git a/build/lib/ForMoSA/adapt/adapt_grid.py b/build/lib/ForMoSA/adapt/adapt_grid.py index f083b2e..b35cc36 100644 --- a/build/lib/ForMoSA/adapt/adapt_grid.py +++ b/build/lib/ForMoSA/adapt/adapt_grid.py @@ -2,7 +2,9 @@ import numpy as np import xarray as xr import time -import os +import os, sys + +sys.path.insert(0, os.path.abspath('../')) from adapt.extraction_functions import adapt_model, decoupe @@ -10,20 +12,20 @@ # ---------------------------------------------------------------------------------------------------------------------- -def adapt_grid(global_params, wav_obs_spec, wav_obs_phot, obs_name='', indobs=0): +def adapt_grid(global_params, wav_obs_spectro, wav_obs_photo, res_mod_obs_merge, obs_name='', indobs=0): """ Adapt the synthetic spectra of a grid to make them comparable with the data. Args: - global_params (object): Class containing each parameter - wav_obs_spec (array): Merged wavelength grid of the data - wav_obs_phot (array): Wavelengths of the photometry points - obs_name (str): Name of the current observation looping - indobs (int): Index of the current observation looping + global_params (object): Class containing each parameter + wav_obs_spectro (array): Merged wavelength grid of the data + wav_obs_photo (array): Wavelengths of the photometry points + obs_name (str): Name of the current observation looping + indobs (int): Index of the current observation looping Returns: None - Author: Simon Petrus / Adapted: Matthieu Ravet & Paulina Palma-Bifani + Author: Simon Petrus, Matthieu Ravet and Paulina Palma-Bifani """ ds = xr.open_dataset(global_params.model_path, decode_cf=False, engine="netcdf4") @@ -31,68 +33,46 @@ def adapt_grid(global_params, wav_obs_spec, wav_obs_phot, obs_name='', indobs=0) grid = ds['grid'] attr = ds.attrs grid_np = grid.to_numpy() - - # Prepare the low resolution wavelength array if the continuum is to be estimated - if global_params.continuum_sub[indobs] != 'NA': - for w_ind, wav_for_cont in enumerate(global_params.wav_for_continuum[indobs].split('/')): - wav_mod_for_cont_ind = np.where((float(wav_for_cont.split(',')[0]) < wav_mod_nativ) & - (wav_mod_nativ < float(wav_for_cont.split(',')[1]))) - if w_ind == 0: - wav_mod_for_cont = wav_mod_nativ[wav_mod_for_cont_ind] - else: - wav_mod_for_cont = np.concatenate((wav_mod_for_cont, wav_mod_nativ[wav_mod_for_cont_ind])) - - wav_reso = min(wav_mod_for_cont) - n = 0 - while wav_reso < max(wav_mod_for_cont): - last_wav_reso = wav_reso - wav_reso += wav_reso / float(global_params.continuum_sub[indobs]) - n += 1 - - wav_min = min(wav_mod_for_cont) - wav_reso_tab = np.logspace(np.log10(wav_min), np.log10(last_wav_reso), num = n) - else: - wav_reso_tab = [] if len(attr['par']) == 2: - grid_new_np = np.full((len(wav_obs_spec), + grid_spectro_np = np.full((len(wav_obs_spectro), len(grid["par1"].values), len(grid["par2"].values)), np.nan) - grid_phot_new_np = np.full((len(wav_obs_phot), + grid_photo_np = np.full((len(wav_obs_photo), len(grid["par1"].values), len(grid["par2"].values)), np.nan) tot_par = len(grid["par1"].values) * len(grid["par2"].values) if len(attr['par']) == 3: - grid_new_np = np.full((len(wav_obs_spec), + grid_spectro_np = np.full((len(wav_obs_spectro), len(grid["par1"].values), len(grid["par2"].values), len(grid["par3"].values)), np.nan) - grid_phot_new_np = np.full((len(wav_obs_phot), + grid_photo_np = np.full((len(wav_obs_photo), len(grid["par1"].values), len(grid["par2"].values), len(grid["par3"].values)), np.nan) tot_par = len(grid["par1"].values) * len(grid["par2"].values) * len(grid["par3"].values) if len(attr['par']) == 4: - grid_new_np = np.full((len(wav_obs_spec), + grid_spectro_np = np.full((len(wav_obs_spectro), len(grid["par1"].values), len(grid["par2"].values), len(grid["par3"].values), len(grid["par4"].values)), np.nan) - grid_phot_new_np = np.full((len(wav_obs_phot), + grid_photo_np = np.full((len(wav_obs_photo), len(grid["par1"].values), len(grid["par2"].values), len(grid["par3"].values), len(grid["par4"].values)), np.nan) tot_par = len(grid["par1"].values) * len(grid["par2"].values) * len(grid["par3"].values) * len(grid["par4"].values) if len(attr['par']) == 5: - grid_new_np = np.full((len(wav_obs_spec), + grid_spectro_np = np.full((len(wav_obs_spectro), len(grid["par1"].values), len(grid["par2"].values), len(grid["par3"].values), len(grid["par4"].values), len(grid["par5"].values)), np.nan) - grid_phot_new_np = np.full((len(wav_obs_phot), + grid_photo_np = np.full((len(wav_obs_photo), len(grid["par1"].values), len(grid["par2"].values), len(grid["par3"].values), @@ -115,10 +95,10 @@ def adapt_grid(global_params, wav_obs_spec, wav_obs_phot, obs_name='', indobs=0) model_to_adapt = grid_np[:, p1_i, p2_i, p3_i, p4_i, p5_i] nan_mod_ind = ~np.isnan(model_to_adapt) if len(np.where(nan_mod_ind is False)[0]) == 0: - flx_mod_extract, mod_pho = adapt_model(global_params, wav_mod_nativ, wav_reso_tab, - model_to_adapt, attr['res'], obs_name=obs_name, indobs=indobs) - grid_new_np[:, p1_i, p2_i, p3_i, p4_i, p5_i] = flx_mod_extract - grid_phot_new_np[:, p1_i, p2_i, p3_i, p4_i, p5_i] = mod_pho + mod_spectro, mod_photo = adapt_model(global_params, wav_mod_nativ, model_to_adapt, + res_mod_obs_merge, obs_name=obs_name, indobs=indobs) + grid_spectro_np[:, p1_i, p2_i, p3_i, p4_i, p5_i] = mod_spectro + grid_photo_np[:, p1_i, p2_i, p3_i, p4_i, p5_i] = mod_photo else: print('The extraction of the model : '+attr['title'][0]+'=' + str(p1) + @@ -146,11 +126,11 @@ def adapt_grid(global_params, wav_obs_spec, wav_obs_phot, obs_name='', indobs=0) model_to_adapt = grid_np[:, p1_i, p2_i, p3_i, p4_i] nan_mod_ind = ~np.isnan(model_to_adapt) if len(np.where(nan_mod_ind is False)[0]) == 0: - flx_mod_extract, mod_pho = adapt_model(global_params, wav_mod_nativ, wav_reso_tab, model_to_adapt, attr['res'], obs_name=obs_name, - indobs=indobs) + mod_spectro, mod_photo = adapt_model(global_params, wav_mod_nativ, model_to_adapt, + res_mod_obs_merge, obs_name=obs_name, indobs=indobs) - grid_new_np[:, p1_i, p2_i, p3_i, p4_i] = flx_mod_extract - grid_phot_new_np[:, p1_i, p2_i, p3_i, p4_i] = mod_pho + grid_spectro_np[:, p1_i, p2_i, p3_i, p4_i] = mod_spectro + grid_photo_np[:, p1_i, p2_i, p3_i, p4_i] = mod_photo else: print('The extraction of the model : ' + attr['title'][0] + '=' + str(p1) + @@ -178,11 +158,11 @@ def adapt_grid(global_params, wav_obs_spec, wav_obs_phot, obs_name='', indobs=0) model_to_adapt = grid_np[:, p1_i, p2_i, p3_i] nan_mod_ind = ~np.isnan(model_to_adapt) if len(np.where(nan_mod_ind is False)[0]) == 0: - flx_mod_extract, mod_pho = adapt_model(global_params, wav_mod_nativ, wav_reso_tab, model_to_adapt, - attr['res'], obs_name=obs_name, indobs=indobs) + mod_spectro, mod_photo = adapt_model(global_params, wav_mod_nativ, model_to_adapt, + res_mod_obs_merge, obs_name=obs_name, indobs=indobs) - grid_new_np[:, p1_i, p2_i, p3_i] = flx_mod_extract - grid_phot_new_np[:, p1_i, p2_i, p3_i] = mod_pho + grid_spectro_np[:, p1_i, p2_i, p3_i] = mod_spectro + grid_photo_np[:, p1_i, p2_i, p3_i] = mod_photo else: print('The extraction of the model : ' + attr['title'][0] + '=' + str(p1) + @@ -208,9 +188,10 @@ def adapt_grid(global_params, wav_obs_spec, wav_obs_phot, obs_name='', indobs=0) model_to_adapt = grid_np[:, p1_i, p2_i] nan_mod_ind = ~np.isnan(model_to_adapt) if len(np.where(nan_mod_ind is False)[0]) == 0: - flx_mod_extract, mod_pho = adapt_model(global_params, wav_mod_nativ, wav_reso_tab, model_to_adapt, attr['res'], obs_name=obs_name, indobs=indobs) - grid_new_np[:, p1_i, p2_i] = flx_mod_extract - grid_phot_new_np[:, p1_i, p2_i] = mod_pho + mod_spectro, mod_photo = adapt_model(global_params, wav_mod_nativ, model_to_adapt, + res_mod_obs_merge, obs_name=obs_name, indobs=indobs) + grid_spectro_np[:, p1_i, p2_i] = mod_spectro + grid_photo_np[:, p1_i, p2_i] = mod_photo else: print('The extraction of the model : ' + attr['title'][0] + '=' + str(p1) + @@ -231,40 +212,40 @@ def adapt_grid(global_params, wav_obs_spec, wav_obs_phot, obs_name='', indobs=0) i_tot += 1 if len(attr['par']) == 2: - ds_new = xr.Dataset(data_vars=dict(grid=(["wavelength", "par1", "par2"], grid_new_np)), - coords={"wavelength": wav_obs_spec, + ds_spectro_new = xr.Dataset(data_vars=dict(grid=(["wavelength", "par1", "par2"], grid_spectro_np)), + coords={"wavelength": wav_obs_spectro, "par1": grid["par1"].values, "par2": grid["par2"].values}, attrs=attr) - ds_new_phot = xr.Dataset(data_vars=dict(grid=(["wavelength", "par1", "par2"], grid_phot_new_np)), - coords={"wavelength": wav_obs_phot, + ds_photo_new = xr.Dataset(data_vars=dict(grid=(["wavelength", "par1", "par2"], grid_photo_np)), + coords={"wavelength": wav_obs_photo, "par1": grid["par1"].values, "par2": grid["par2"].values}, attrs=attr) if len(attr['par']) == 3: - ds_new = xr.Dataset(data_vars=dict(grid=(["wavelength", "par1", "par2", "par3"], grid_new_np)), - coords={"wavelength": wav_obs_spec, + ds_spectro_new = xr.Dataset(data_vars=dict(grid=(["wavelength", "par1", "par2", "par3"], grid_spectro_np)), + coords={"wavelength": wav_obs_spectro, "par1": grid["par1"].values, "par2": grid["par2"].values, "par3": grid["par3"].values}, attrs=attr) - ds_new_phot = xr.Dataset(data_vars=dict(grid=(["wavelength", "par1", "par2", "par3"], grid_phot_new_np)), - coords={"wavelength": wav_obs_phot, + ds_photo_new = xr.Dataset(data_vars=dict(grid=(["wavelength", "par1", "par2", "par3"], grid_photo_np)), + coords={"wavelength": wav_obs_photo, "par1": grid["par1"].values, "par2": grid["par2"].values, "par3": grid["par3"].values}, attrs=attr) if len(attr['par']) == 4: - ds_new = xr.Dataset(data_vars=dict(grid=(["wavelength", "par1", "par2", "par3", "par4"], grid_new_np)), - coords={"wavelength": wav_obs_spec, + ds_spectro_new = xr.Dataset(data_vars=dict(grid=(["wavelength", "par1", "par2", "par3", "par4"], grid_spectro_np)), + coords={"wavelength": wav_obs_spectro, "par1": grid["par1"].values, "par2": grid["par2"].values, "par3": grid["par3"].values, "par4": grid["par4"].values}, attrs=attr) - ds_new_phot = xr.Dataset(data_vars=dict(grid=(["wavelength", "par1", "par2", "par3", "par4"], - grid_phot_new_np)), - coords={"wavelength": wav_obs_phot, + ds_photo_new = xr.Dataset(data_vars=dict(grid=(["wavelength", "par1", "par2", "par3", "par4"], + grid_photo_np)), + coords={"wavelength": wav_obs_photo, "par1": grid["par1"].values, "par2": grid["par2"].values, "par3": grid["par3"].values, @@ -272,17 +253,17 @@ def adapt_grid(global_params, wav_obs_spec, wav_obs_phot, obs_name='', indobs=0) attrs=attr) if len(attr['par']) == 5: - ds_new = xr.Dataset(data_vars=dict(grid=(["wavelength", "par1", "par2", "par3", "par4", "par5"], grid_new_np)), - coords={"wavelength": wav_obs_spec, + ds_spectro_new = xr.Dataset(data_vars=dict(grid=(["wavelength", "par1", "par2", "par3", "par4", "par5"], grid_spectro_np)), + coords={"wavelength": wav_obs_spectro, "par1": grid["par1"].values, "par2": grid["par2"].values, "par3": grid["par3"].values, "par4": grid["par4"].values, "par5": grid["par5"].values}, attrs=attr) - ds_new_phot = xr.Dataset(data_vars=dict(grid=(["wavelength", "par1", "par2", "par3", "par4", "par5"], - grid_phot_new_np)), - coords={"wavelength": wav_obs_phot, + ds_photo_new = xr.Dataset(data_vars=dict(grid=(["wavelength", "par1", "par2", "par3", "par4", "par5"], + grid_photo_np)), + coords={"wavelength": wav_obs_photo, "par1": grid["par1"].values, "par2": grid["par2"].values, "par3": grid["par3"].values, @@ -295,16 +276,16 @@ def adapt_grid(global_params, wav_obs_spec, wav_obs_phot, obs_name='', indobs=0) print() for key_ind, key in enumerate(attr['key']): print(str(key_ind+1) + '/' + str(len(attr['key']))) - ds_new = ds_new.interpolate_na(dim=key, method="linear", fill_value="extrapolate", limit=None, + ds_spectro_new = ds_spectro_new.interpolate_na(dim=key, method="linear", fill_value="extrapolate", limit=None, max_gap=None) - ds_new_phot = ds_new_phot.interpolate_na(dim=key, method="linear", fill_value="extrapolate", limit=None, + ds_photo_new = ds_photo_new.interpolate_na(dim=key, method="linear", fill_value="extrapolate", limit=None, max_gap=None) - ds_new.to_netcdf(os.path.join(global_params.adapt_store_path, f'adapted_grid_spectro_{global_params.grid_name}_{obs_name}_nonan.nc'), + ds_spectro_new.to_netcdf(os.path.join(global_params.adapt_store_path, f'adapted_grid_spectro_{global_params.grid_name}_{obs_name}_nonan.nc'), format='NETCDF4', engine='netcdf4', mode='w') - ds_new_phot.to_netcdf(os.path.join(global_params.adapt_store_path, f'adapted_grid_photo_{global_params.grid_name}_{obs_name}_nonan.nc'), + ds_photo_new.to_netcdf(os.path.join(global_params.adapt_store_path, f'adapted_grid_photo_{global_params.grid_name}_{obs_name}_nonan.nc'), format='NETCDF4', engine='netcdf4', mode='w') diff --git a/build/lib/ForMoSA/adapt/adapt_obs_mod.py b/build/lib/ForMoSA/adapt/adapt_obs_mod.py index 8be38f1..016af49 100644 --- a/build/lib/ForMoSA/adapt/adapt_obs_mod.py +++ b/build/lib/ForMoSA/adapt/adapt_obs_mod.py @@ -1,8 +1,10 @@ from __future__ import print_function, division import numpy as np -import os +import os,sys import xarray as xr -# import matplotlib.pyplot as plt +from scipy.interpolate import interp1d + +sys.path.insert(0, os.path.abspath('../')) from adapt.extraction_functions import extract_observation from adapt.adapt_grid import adapt_grid @@ -17,17 +19,18 @@ def launch_adapt(global_params, justobs='no'): Args: global_params (object): Class containing each parameter - justobs ('yes'/'no'): 'no' by default to also adapt the grid + justobs ('yes'/'no'): 'no' by default to also adapt the grid Returns: None - Author: Simon Petrus / Adapted: Matthieu Ravet, Paulina Palma-Bifani and Allan Denis + Author: Simon Petrus, Matthieu Ravet, Paulina Palma-Bifani and Allan Denis """ - # Get back information from the config file + # Get back the grid information from the config file ds = xr.open_dataset(global_params.model_path, decode_cf=False, engine="netcdf4") wav_mod_nativ = ds["wavelength"].values attr = ds.attrs + res_mod_nativ = attr['res'] ds.close() # Extract the data from the observation files @@ -38,68 +41,90 @@ def launch_adapt(global_params, justobs='no'): global_params.observation_path = obs obs_name = os.path.splitext(os.path.basename(global_params.observation_path))[0] - - obs_spectro, obs_photo, obs_spectro_ins, obs_photo_ins, obs_opt = extract_observation(global_params, wav_mod_nativ, attr['res'], obs_name=obs_name, - indobs=indobs) - # Estimate and subtraction of the continuum (if needed) + check-ups + # Estimate and subtract the continuum (if needed) + check-ups if global_params.continuum_sub[indobs] != 'NA': print() print(obs_name + ' will have a R=' + global_params.continuum_sub[indobs] + ' continuum removed using a ' + global_params.wav_for_continuum[indobs] + ' wavelength range') print() - if global_params.continuum_sub[indobs] != 'NA': - obs_spectro_c, obs_photo_c, obs_spectro_ins_c, obs_photo_ins_c, obs_opt_c = extract_observation(global_params, wav_mod_nativ, - attr['res'], 'yes', obs_name=obs_name, indobs=indobs) - for c, cut in enumerate(obs_spectro): - obs_spectro[c][1] -= obs_spectro_c[c][1] + obs_spectro, obs_photo, obs_spectro_ins, obs_photo_ins, obs_opt = extract_observation(global_params, wav_mod_nativ, res_mod_nativ, 'yes', + obs_name=obs_name, indobs=indobs) + else: + obs_spectro, obs_photo, obs_spectro_ins, obs_photo_ins, obs_opt = extract_observation(global_params, wav_mod_nativ, res_mod_nativ, + obs_name=obs_name, indobs=indobs) + - # Merging of each sub-spectrum + # Merging of each sub-spectrum and interpolating the grid for c, cut in enumerate(obs_spectro): - if c == 0: - wav_obs_extract = obs_spectro[c][0] - flx_obs_extract = obs_spectro[c][1] - err_obs_extract = obs_spectro[c][2] - res_obs_extract = obs_spectro[c][3] - cov_obs_extract = obs_opt[c][0] - transm_obs_extract = obs_opt[c][1] - star_flx_obs_extract = obs_opt[c][2] - else: - wav_obs_extract = np.concatenate((wav_obs_extract, obs_spectro[c][0])) - flx_obs_extract = np.concatenate((flx_obs_extract, obs_spectro[c][1])) - err_obs_extract = np.concatenate((err_obs_extract, obs_spectro[c][2])) - res_obs_extract = np.concatenate((res_obs_extract, obs_spectro[c][3])) + if len(cut[0]) > 0: + # Interpolate the resolution onto the wavelength of the data + ind_mod_obs = np.where((wav_mod_nativ <= cut[0][-1]) & (wav_mod_nativ > cut[0][0])) + wav_mod_cut = wav_mod_nativ[ind_mod_obs] + res_mod_cut = res_mod_nativ[ind_mod_obs] + interp_mod_to_obs = interp1d(wav_mod_cut, res_mod_cut, fill_value='extrapolate') + res_mod_cut = interp_mod_to_obs(cut[0]) + + if c == 0: + wav_obs_extract = obs_spectro[c][0] + flx_obs_extract = obs_spectro[c][1] + err_obs_extract = obs_spectro[c][2] + res_obs_extract = obs_spectro[c][3] + cov_obs_extract = obs_opt[c][0] + transm_obs_extract = obs_opt[c][1] + star_flx_obs_extract = obs_opt[c][2] + system_obs_extract = obs_opt[c][3] + # Save the interpolated resolution of the grid + res_mod_obs_merge = [res_mod_cut] + + else: + wav_obs_extract = np.concatenate((wav_obs_extract, obs_spectro[c][0])) + flx_obs_extract = np.concatenate((flx_obs_extract, obs_spectro[c][1])) + err_obs_extract = np.concatenate((err_obs_extract, obs_spectro[c][2])) + res_obs_extract = np.concatenate((res_obs_extract, obs_spectro[c][3])) + if len(cov_obs_extract) != 0: + cov_obs_extract = diag_mat([cov_obs_extract, obs_opt[c][0]]) + if len(transm_obs_extract) != 0: + transm_obs_extract = np.concatenate((transm_obs_extract, obs_opt[c][1])) + if len(star_flx_obs_extract) != 0: + star_flx_obs_extract = np.concatenate((star_flx_obs_extract, obs_opt[c][2])) + if len(system_obs_extract) != 0: + system_obs_extract = np.concatenate((system_obs_extract, obs_opt[c][3]), axis=0) + # Save the interpolated resolution of the grid + res_mod_obs_merge.append(res_mod_cut) + + + # Compute the inverse of the merged covariance matrix (note: inv(C1, C2) = (in(C1), in(C2)) if C1 and C2 are block matrix on the diagonal) + # if necessary if len(cov_obs_extract) != 0: - cov_obs_extract = diag_mat([cov_obs_extract, obs_opt[c][0]]) - if len(transm_obs_extract) != 0: - transm_obs_extract = np.concatenate((transm_obs_extract, obs_opt[c][1])) - if len(star_flx_obs_extract) != 0: - star_flx_obs_extract = np.concatenate((star_flx_obs_extract, obs_opt[c][2])) - - - # Compute the inverse of the merged covariance matrix (note: inv(C1, C2) = (in(C1), in(C2)) if C1 and C2 are block matrix on the diagonal) - # if necessary - if len(cov_obs_extract) != 0: - inv_cov_obs_extract = np.linalg.inv(cov_obs_extract) + inv_cov_obs_extract = np.linalg.inv(cov_obs_extract) + else: + inv_cov_obs_extract = np.asarray([]) + + # Check-ups and warnings for negative values in the diagonal of the covariance matrix + if len(cov_obs_extract) != 0 and any(np.diag(cov_obs_extract) < 0): + print() + print("WARNING: Negative value(s) is(are) present on the diagonal of the covariance matrix.") + print("Operation aborted.") + print() + exit() + else: - inv_cov_obs_extract = np.asarray([]) - - # Compile everything and changing data type to object to allow for different array sizes - obs_spectro_merge = np.asarray([wav_obs_extract, flx_obs_extract, err_obs_extract, res_obs_extract]) - obs_spectro = np.asarray(obs_spectro, dtype=object) - obs_spectro_ins = np.asarray(obs_spectro_ins, dtype=object) - obs_photo = np.asarray(obs_photo, dtype=object) - obs_photo_ins = np.asarray(obs_photo_ins, dtype=object) - obs_opt_merge = np.asarray([inv_cov_obs_extract, transm_obs_extract, star_flx_obs_extract], dtype=object) - - # Check-ups and warnings for negative values in the diagonal of the covariance matrix - if len(cov_obs_extract) != 0 and any(np.diag(cov_obs_extract) < 0): - print() - print("WARNING: Negative value(s) is(are) present on the diagonal of the covariance matrix.") - print("Operation aborted.") - print() - exit() + wav_obs_extract, flx_obs_extract, err_obs_extract, res_obs_extract = [], [], [], [] + inv_cov_obs_extract, transm_obs_extract, star_flx_obs_extract, system_obs_extract = [], [], [], [] + res_mod_obs_merge = res_mod_nativ + + # Compile everything and changing data type to object to allow for different array sizes + obs_spectro_merge = np.asarray([wav_obs_extract, flx_obs_extract, err_obs_extract, res_obs_extract]) + obs_spectro = np.asarray(obs_spectro, dtype=object) + obs_spectro_ins = np.asarray(obs_spectro_ins, dtype=object) + obs_photo = np.asarray(obs_photo, dtype=object) + obs_photo_ins = np.asarray(obs_photo_ins, dtype=object) + obs_opt_merge = np.asarray([inv_cov_obs_extract, transm_obs_extract, star_flx_obs_extract, system_obs_extract], dtype=object) + + + # Save the new data spectrum np.savez(os.path.join(global_params.result_path, f'spectrum_obs_{obs_name}.npz'), @@ -129,8 +154,8 @@ def launch_adapt(global_params, justobs='no'): print('- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -') print(f"-> Sarting the adaptation of {obs_name}") - adapt_grid(global_params, obs_spectro_merge[0], obs_photo[0], obs_name=obs_name, indobs=indobs) - + adapt_grid(global_params, obs_spectro_merge[0], obs_photo[0], res_mod_obs_merge, obs_name=obs_name, indobs=indobs) + # ---------------------------------------------------------------------------------------------------------------------- diff --git a/build/lib/ForMoSA/adapt/extraction_functions.py b/build/lib/ForMoSA/adapt/extraction_functions.py index c118a37..4964568 100644 --- a/build/lib/ForMoSA/adapt/extraction_functions.py +++ b/build/lib/ForMoSA/adapt/extraction_functions.py @@ -5,7 +5,6 @@ from scipy.interpolate import interp1d from spectres import spectres import os - # ---------------------------------------------------------------------------------------------------------------------- @@ -16,7 +15,9 @@ def decoupe(second): Args: second (float): number of second Returns: - hour, minute, second (float, float, float): hours-minutes-seconds format + - float : hours + - float : minutes + - float : seconds Author: Simon Petrus """ @@ -39,7 +40,7 @@ def find_nearest(array, value): array (array): Array to explore value (float): Desire value Returns: - idx (int): Indice of the closest values from the desire value + - idx (int) : Indice of the closest values from the desire value Author: Simon Petrus """ @@ -62,19 +63,15 @@ def extract_observation(global_params, wav_mod_nativ, res_mod_nativ, cont='no', cont (str): Boolean string. If the function is used to estimate the continuum cont='yes' obs_name (str): Name of the current observation looping indobs (int): Index of the current observation looping + Returns: - obs_spectro (n-array): List containing the sub-spectra defined by the parameter "wav_for_adapt" with decreased resolution - [[wav_1, flx_1, err_1, reso_1], ..., [wav_n, flx_n, err_n, reso_n]] - obs_photo (array): List containing the photometry (0 replace the spectral resolution here). - [wav_phot, flx_phot, err_phot, 0] - obs_spectro_ins (array): List containing different instruments used for the data (1 per wavelength). - [[instru_range_1], ..., [instru_range_n]] - obs_photo_ins (array): List containing different filters used for the data (1 per photometric point). - [filter_phot_1, filter_phot_2, ..., filter_phot_n] - obs_opt (n-array): List containing the optional sub-arrays defined by the parameter "wav_for_adapt". - [[cov_1, tran_1, star_1], ..., [cov_n, tran_n, star_n]] - - Author: Simon Petrus / Adapted: Matthieu Ravet + - obs_spectro (n-array) : List containing the sub-spectra defined by the parameter "wav_for_adapt" with decreased resolution [[wav_1, flx_1, err_1, reso_1], ..., [wav_n, flx_n, err_n, reso_n]] + - obs_photo (array) : List containing the photometry (0 replace the spectral resolution here). [wav_phot, flx_phot, err_phot, 0] + - obs_spectro_ins(array) : List containing different instruments used for the data (1 per wavelength). [[instru_range_1], ..., [instru_range_n]] + - obs_photo_ins (array) : List containing different filters used for the data (1 per photometric point). [filter_phot_1, filter_phot_2, ..., filter_phot_n] + - obs_opt (n-array) : List containing the optional sub-arrays defined by the parameter "wav_for_adapt". [[cov_1, tran_1, star_1], ..., [cov_n, tran_n, star_n]] + + Author: Simon Petrus, Matthieu Ravet """ # Extract the wavelengths, flux, errors, spectral resolution, and instrument/filter names from the observation file. @@ -83,46 +80,21 @@ def extract_observation(global_params, wav_mod_nativ, res_mod_nativ, cont='no', # Reduce the spectral resolution for each sub-spectrum. for c, cut in enumerate(obs_spectro): - # If we want to decrease the resolution of the data: if len(cut[0]) != 0: - if cont == 'no': - if global_params.adapt_method[indobs] == 'by_reso': - obs_spectro[c][1] = resolution_decreasing(global_params, cut, wav_mod_nativ, [], res_mod_nativ, - 'obs', obs_name=obs_name, indobs=indobs) - # If we want to estimate the continuum of the data: - else: - for w_ind, wav_for_cont in enumerate(global_params.wav_for_continuum[indobs].split('/')): - wav_obs_for_cont_ind = np.where((float(wav_for_cont.split(',')[0]) < cut[0]) & - (cut[0] < float(wav_for_cont.split(',')[1]))) - if w_ind == 0: - wav_obs_for_cont = cut[0][wav_obs_for_cont_ind] - flx_obs_for_cont = cut[1][wav_obs_for_cont_ind] - else: - wav_obs_for_cont = np.concatenate((wav_obs_for_cont, cut[0][wav_obs_for_cont_ind])) - flx_obs_for_cont = np.concatenate((flx_obs_for_cont, cut[1][wav_obs_for_cont_ind])) - wav_reso_tab = [] - wav_reso = min(wav_obs_for_cont) - while wav_reso < max(wav_obs_for_cont): - wav_reso_tab.append(wav_reso) - wav_reso += wav_reso / float(global_params.continuum_sub[indobs]) - wav_reso_tab = np.asarray(wav_reso_tab) - - flx_obs_cont = spectres(wav_reso_tab, wav_obs_for_cont, flx_obs_for_cont, fill=np.nan, verbose=False) - for w_ind, wav_for_cont in enumerate(global_params.wav_for_continuum[indobs].split('/')): - wav_final_cont_ind = np.where((float(wav_for_cont.split(',')[0]) < wav_reso_tab) & - (wav_reso_tab < float(wav_for_cont.split(',')[1]))) - if w_ind == 0: - wav_final_cont = wav_reso_tab[wav_final_cont_ind] - flx_final_cont = flx_obs_cont[wav_final_cont_ind] - else: - wav_final_cont = np.concatenate((wav_final_cont, wav_reso_tab[wav_final_cont_ind])) - flx_final_cont = np.concatenate((flx_final_cont, flx_obs_cont[wav_final_cont_ind])) + # Interpolate the resolution of the model onto the wavelength of the data to properly decrease the resolution if necessary + ind_mod_obs = np.where((wav_mod_nativ <= cut[0][-1]) & (wav_mod_nativ > cut[0][0])) + wav_mod_obs = wav_mod_nativ[ind_mod_obs] + res_mod_obs = res_mod_nativ[ind_mod_obs] + interp_mod_to_obs = interp1d(wav_mod_obs, res_mod_obs, fill_value='extrapolate') + res_mod_obs = interp_mod_to_obs(cut[0]) + # If we want to decrease the resolution of the data: (if by_sample, the data don't need to be adapted) + if global_params.adapt_method[indobs] == 'by_reso': + obs_spectro[c][1] = resolution_decreasing(global_params, cut[0], cut[1], cut[3], wav_mod_nativ, [], res_mod_obs, + 'obs', indobs=indobs) + if cont == 'yes': + # If we want to estimate and substract the continuum of the data: + obs_spectro[c][1] -= continuum_estimate(global_params, cut[0], cut[1], cut[3], indobs=indobs) - interp_reso = interp1d(wav_final_cont[~np.isnan(flx_final_cont)], flx_final_cont[~np.isnan(flx_final_cont)], fill_value="extrapolate") - flx_obs_cont = interp_reso(cut[0]) - obs_spectro[c][1] = flx_obs_cont - - return obs_spectro, obs_photo, obs_spectro_ins, obs_photo_ins, obs_opt # ---------------------------------------------------------------------------------------------------------------------- @@ -137,17 +109,13 @@ def adapt_observation_range(global_params, obs_name='', indobs=0): global_params (object): Class containing each parameter obs_name (str): Name of the current observation looping indobs (int): Index of the current observation looping + Returns: - obs_spectro (n-array): List containing the sub-spectra defined by the parameter "wav_for_adapt". - [[wav_1, flx_1, err_1, reso_1], ..., [wav_n, flx_n, err_n, reso_n]] - obs_photo (array): List containing the photometry (0 replace the spectral resolution here). - [wav_phot, flx_phot, err_phot, 0] - obs_spectro_ins (array): List containing different instruments used for the data (1 per wavelength). - [[instru_1], ..., [instru_n]] - obs_photo_ins (array): List containing different filters used for the data (1 per photometric point). - [filter_phot_1, filter_phot_2, ..., filter_phot_n] - obs_opt (n-array): List containing the optional sub-arrays defined by the parameter "wav_for_adapt". - [[cov_1, tran_1, star_1], ..., [cov_n, tran_n, star_n]] + - obs_spectro (n-array) : List containing the sub-spectra defined by the parameter "wav_for_adapt" with decreased resolution [[wav_1, flx_1, err_1, reso_1], ..., [wav_n, flx_n, err_n, reso_n]] + - obs_photo (array) : List containing the photometry (0 replace the spectral resolution here). [wav_phot, flx_phot, err_phot, 0] + - obs_spectro_ins(array) : List containing different instruments used for the data (1 per wavelength). [[instru_range_1], ..., [instru_range_n]] + - obs_photo_ins (array) : List containing different filters used for the data (1 per photometric point). [filter_phot_1, filter_phot_2, ..., filter_phot_n] + - obs_opt (n-array) : List containing the optional sub-arrays defined by the parameter "wav_for_adapt". [[cov_1, tran_1, star_1], ..., [cov_n, tran_n, star_n]] Author: Simon Petrus, Matthieu Ravet and Allan Denis """ @@ -167,21 +135,59 @@ def adapt_observation_range(global_params, obs_name='', indobs=0): err = np.sqrt(np.diag(np.abs(cov))) try: transm = hdul[1].data['TRANSM'] - star_flx = hdul[1].data['STAR FLX'] except: transm = np.asarray([]) - star_flx = np.asarray([]) - + try: + star_flx = hdul[1].data['STAR_FLX1'][:,np.newaxis] + is_star = True + except: + star_flx = np.asarray([]) + is_star = False + try: + star_flx = hdul[1].data['STAR FLX'][:,np.newaxis] + except: + pass + try: + is_system = True + system = hdul[1].data['SYSTEMATICS1'][:,np.newaxis] + except: + is_system = False + system = np.asarray([]) + + if is_system: + i = 2 + while True: # In case there is multiple systematics + try: + system = np.concatenate((system, hdul[1].data['SYSTEMATICS' + str(i)][:,np.newaxis]),axis=1) + i += 1 + except: + break + + if is_star: + i = 2 + while True: + try: + star_flx = np.concatenate((star_flx, hdul[1].data['STAR_FLX' + str(i)][:,np.newaxis]),axis=1) + i += 1 + except: + break # Only take the covariance if you use the chi2_covariance likelihood function (will need to be change when new likelihood functions using the # covariance matrix will come) if global_params.logL_type[indobs] != 'chi2_covariance': cov = np.asarray([]) - # Filter the NaN values - if len(transm) != 0 and len(star_flx) != 0: - nan_mod_ind = (~np.isnan(flx)) & (~np.isnan(transm)) & (~np.isnan(star_flx)) & (~np.isnan(err)) + # Filter the NaN and inf values + if len(transm) != 0: + nan_mod_ind = (~np.isnan(flx)) & (~np.isnan(transm)) & (~np.isnan(err)) & (np.isfinite(flx)) & (np.isfinite(transm)) & (np.isfinite(err)) else: - nan_mod_ind = (~np.isnan(flx)) + nan_mod_ind = (~np.isnan(flx)) & (~np.isnan(err)) & (np.isfinite(flx)) & (np.isfinite(err)) + if len(star_flx) != 0: + for i in range(len(star_flx[0])): + nan_mod_ind = (nan_mod_ind) & (~np.isnan(star_flx.T[i])) & (np.isfinite(star_flx.T[i])) + if len(system) != 0: + for i in range(len(system[0])): + nan_mod_ind = (nan_mod_ind) & (~np.isnan(system.T[i])) & (np.isfinite(system.T[i])) + wav = wav[nan_mod_ind] flx = flx[nan_mod_ind] res = res[nan_mod_ind] @@ -191,8 +197,11 @@ def adapt_observation_range(global_params, obs_name='', indobs=0): cov = np.transpose(np.transpose(cov[nan_mod_ind])[nan_mod_ind]) if len(transm) != 0 and len(star_flx) != 0: transm = transm[nan_mod_ind] - star_flx = star_flx[nan_mod_ind] - + if len(star_flx) != 0: + star_flx = np.delete(star_flx, np.where(~nan_mod_ind), axis=0) + if len(system) != 0: + system = np.delete(system, np.where(~nan_mod_ind), axis=0) + # Select the wavelength range(s) for the extraction if global_params.wav_for_adapt == '': wav_for_adapt_tab = [str(min(wav)) + ',' + str(max(wav))] @@ -235,22 +244,19 @@ def adapt_observation_range(global_params, obs_name='', indobs=0): transm_spectro = np.asarray([]) if len(star_flx) != 0: - star_flx_spectro = np.delete(star_flx[ind], ind_photometry) + star_flx_spectro = np.delete(star_flx[ind,:], ind_photometry, axis=0) else: star_flx_spectro = np.asarray([]) + + if len(system) != 0: + system_spectro = np.delete(system[ind,:], ind_photometry, axis=0) + else: + system_spectro = np.asarray([]) # Merge spectroscopic data obs_spectro[range_ind] = [wav_spectro, flx_spectro, err_spectro, res_spectro] - obs_opt[range_ind] = [cov_spectro, transm_spectro, star_flx_spectro] + obs_opt[range_ind] = [cov_spectro, transm_spectro, star_flx_spectro, system_spectro] obs_spectro_ins[range_ind] = ins_spectro - # if range_ind == 0: - # obs_spectro = [[wav_spectro, flx_spectro, err_spectro, res_spectro]] - # obs_opt = [[cov_spectro, transm_spectro, star_flx_spectro]] # Optional arrays - # obs_spectro_ins = [[ins_spectro]] - # else: - # obs_spectro.append([wav_spectro, flx_spectro, err_spectro, res_spectro]) - # obs_opt.append([cov_spectro, transm_spectro, star_flx_spectro]) # Optional arrays - # obs_spectro_ins.append([ins_spectro]) return obs_spectro, obs_photo, obs_spectro_ins, obs_photo_ins, obs_opt @@ -258,7 +264,7 @@ def adapt_observation_range(global_params, obs_name='', indobs=0): # ---------------------------------------------------------------------------------------------------------------------- -def adapt_model(global_params, wav_mod_nativ, wave_reso_tab, flx_mod_nativ, res_mod_nativ, obs_name='', indobs=0): +def adapt_model(global_params, wav_mod_nativ, flx_mod_nativ, res_mod_obs_merge, obs_name='', indobs=0): """ Extracts a synthetic spectrum from a grid and decreases its spectral resolution. The photometry points are calculated too. Then each sub-spectrum are merged. @@ -272,59 +278,23 @@ def adapt_model(global_params, wav_mod_nativ, wave_reso_tab, flx_mod_nativ, res_ obs_name (str): Name of the current observation looping indobs (int): Index of the current observation looping Returns: - flx_mod_extract (array): Flux of the spectrum with a decreased spectral resolution, re-sampled on the data wavelength grid - mod_photo (array): List containing the photometry ('0' replace the spectral resolution here). + - mod_spectro (array) : Flux of the spectrum with a decreased spectral resolution, re-sampled on the data wavelength grid + - mod_photo (array) : List containing the photometry ('0' replace the spectral resolution here). Author: Simon Petrus """ - # Extract the synthetic spectra from the model grid - mod_spectro, mod_photo, obs_spectro = extract_model(global_params, wav_mod_nativ, flx_mod_nativ, res_mod_nativ, obs_name=obs_name) - # Estimate and subtraction of the continuum (if needed) + # Estimate and subtract the continuum (if needed) if global_params.continuum_sub[indobs] != 'NA': - for c, cut in enumerate(obs_spectro): - #mod_cut_c, mod_pho_c = extract_model(global_params, wav_mod_nativ, flx_mod_nativ, res_mod_nativ, 'yes') - for w_ind, wav_for_cont in enumerate(global_params.wav_for_continuum[indobs].split('/')): - wav_mod_for_cont_ind = np.where((float(wav_for_cont.split(',')[0]) < wav_mod_nativ) & - (wav_mod_nativ < float(wav_for_cont.split(',')[1]))) - if w_ind == 0: - wav_mod_for_cont = wav_mod_nativ[wav_mod_for_cont_ind] - flx_mod_for_cont = flx_mod_nativ[wav_mod_for_cont_ind] - else: - wav_mod_for_cont = np.concatenate((wav_mod_for_cont, wav_mod_nativ[wav_mod_for_cont_ind])) - flx_mod_for_cont = np.concatenate((flx_mod_for_cont, flx_mod_nativ[wav_mod_for_cont_ind])) - - flx_obs_cont = spectres(wave_reso_tab, wav_mod_for_cont, flx_mod_for_cont, fill=np.nan, verbose=False) - for w_ind, wav_for_cont in enumerate(global_params.wav_for_continuum[indobs].split('/')): - wav_final_cont_ind = np.where((float(wav_for_cont.split(',')[0]) < wave_reso_tab) & - (wave_reso_tab < float(wav_for_cont.split(',')[1]))) - if w_ind == 0: - wav_final_cont = wave_reso_tab[wav_final_cont_ind] - flx_final_cont = flx_obs_cont[wav_final_cont_ind] - else: - wav_final_cont = np.concatenate((wav_final_cont, wave_reso_tab[wav_final_cont_ind])) - flx_final_cont = np.concatenate((flx_final_cont, flx_obs_cont[wav_final_cont_ind])) - if len(flx_final_cont[~np.isnan(flx_final_cont)]) != 0: - interp_reso = interp1d(wav_final_cont[~np.isnan(flx_final_cont)], flx_final_cont[~np.isnan(flx_final_cont)], - fill_value="extrapolate") - flx_obs_cont = interp_reso(obs_spectro[c][0]) - else: - flx_obs_cont = obs_spectro[c][0]*np.nan - - mod_spectro[c] -= flx_obs_cont - - # Merging of each sub-spectrum - for c, cut in enumerate(mod_spectro): - if c == 0: - flx_mod_extract = mod_spectro[c] - else: - flx_mod_extract = np.concatenate((flx_mod_extract, mod_spectro[c])) + mod_spectro, mod_photo = extract_model(global_params, wav_mod_nativ, flx_mod_nativ, res_mod_obs_merge, cont='yes', obs_name=obs_name, indobs=indobs) + else: + mod_spectro, mod_photo = extract_model(global_params, wav_mod_nativ, flx_mod_nativ, res_mod_obs_merge, obs_name=obs_name, indobs=indobs) - return flx_mod_extract, mod_photo + return mod_spectro, mod_photo # ---------------------------------------------------------------------------------------------------------------------- -def extract_model(global_params, wav_mod_nativ, flx_mod_nativ, res_mod_nativ, cont='no', obs_name='', indobs=0): +def extract_model(global_params, wav_mod_nativ, flx_mod_nativ, res_mod_obs_merge, cont='no', obs_name='', indobs=0): """ Extracts a synthetic spectrum from a grid and decreases its spectral resolution. The photometry points are calculated too. @@ -338,8 +308,8 @@ def extract_model(global_params, wav_mod_nativ, flx_mod_nativ, res_mod_nativ, co obs_name (str): Name of the current observation looping indobs (int): Index of the current observation looping Returns: - mod_spectro (array): List containing the sub-spectra defined by the parameter "wav_for_adapt". - mod_photo (array): List containing the photometry ('0' replace the spectral resolution here). + - mod_spectro (array) : List containing the sub-spectra defined by the parameter "wav_for_adapt". + - mod (array) : List containing the photometry ('0' replace the spectral resolution here). Author: Simon Petrus """ @@ -347,37 +317,30 @@ def extract_model(global_params, wav_mod_nativ, flx_mod_nativ, res_mod_nativ, co spectrum_obs = np.load(os.path.join(global_params.result_path, f'spectrum_obs_{obs_name}.npz'), allow_pickle=True) obs_spectro = spectrum_obs['obs_spectro'] obs_photo_ins = spectrum_obs['obs_photo_ins'] - + mod_spectro, mod_photo = [], [] # Reduce the spectral resolution for each sub-spectrum. - mod_spectro = [] for c, cut in enumerate(obs_spectro): - # If we want to decrease the resolution of the data: if len(cut[0]) != 0: - if cont == 'no': - if global_params.adapt_method[indobs] == 'by_reso': - mod_cut_flx = resolution_decreasing(global_params, cut, wav_mod_nativ, flx_mod_nativ, res_mod_nativ, - 'mod', obs_name=obs_name, indobs=indobs) # Conversion of the cuts to floats for the np computations - else: - res_tab = cut[3] - wave_reso_tab = [] - wav_reso = min(cut[0]) - while wav_reso < max(cut[0]): - wave_reso_tab.append(wav_reso) - wav_reso += wav_reso/res_tab[find_nearest(cut[0], wav_reso)] - wave_reso_tab = np.asarray(wave_reso_tab) - mod_cut_flx = spectres(wave_reso_tab, wav_mod_nativ, flx_mod_nativ) - interp_reso = interp1d(wave_reso_tab, mod_cut_flx, fill_value="extrapolate") - mod_cut_flx = interp_reso(cut[0]) + # If we want to decrease the resolution of the data: + if global_params.adapt_method[indobs] == 'by_reso': + mod_cut_flx = resolution_decreasing(global_params, cut[0], [], cut[3], wav_mod_nativ, flx_mod_nativ, res_mod_obs_merge[c], + 'mod', indobs=indobs) + else: + mod_cut_flx = spectres(cut[0], wav_mod_nativ, flx_mod_nativ) + # If we want to estimate the continuum of the data: + if cont == 'yes': + continuum = continuum_estimate(global_params, cut[0], mod_cut_flx, res_mod_obs_merge[c], indobs=indobs) + mod_cut_flx -= continuum + + # Concatenate to speed up the code + if c==0: + mod_spectro = mod_cut_flx else: - mod_cut_flx = continuum_estimate(global_params, cut[0], wav_mod_nativ, flx_mod_nativ, res_mod_nativ, - 'mod', obs_name=obs_name, indobs=indobs) - else: - mod_cut_flx = [] - mod_spectro.append(mod_cut_flx) + mod_spectro = np.concatenate((mod_spectro, mod_cut_flx)) + # Calculate each photometry point. - mod_photo = [] for pho_ind, pho in enumerate(obs_photo_ins): path_list = __file__.split("/")[:-2] separator = '/' @@ -393,7 +356,7 @@ def extract_model(global_params, wav_mod_nativ, flx_mod_nativ, res_mod_nativ, co flx_filt = flx_filt / y_filt_tot mod_photo.append(flx_filt) - return mod_spectro, mod_photo, obs_spectro + return mod_spectro, mod_photo # ---------------------------------------------------------------------------------------------------------------------- @@ -410,7 +373,7 @@ def convolve_and_sample(wv_channels, sigmas_wvs, model_wvs, model_fluxes, num_si model_fluxes (array): the fluxes of the model num_sigma (float): number of +/- sigmas to evaluate the LSF to. Returns: - output_model (array): the fluxes in each of the wavelength channels + - output_model (array) : the fluxes in each of the wavelength channels Author: Jason Wang """ @@ -422,9 +385,12 @@ def convolve_and_sample(wv_channels, sigmas_wvs, model_wvs, model_fluxes, num_si filter_coords = np.tile(filter_coords, [wv_channels.shape[0], 1]) # shape of (N_output, filter_size) filter_wv_coords = filter_coords * sigmas_wvs[:, None] + wv_channels[:, None] # model wavelengths we want + lsf = np.exp(-filter_coords ** 2 / 2) / np.sqrt(2 * np.pi) - if np.sum(lsf) != 0: + + if np.sum(lsf) != 0: + model_interp = interp1d(model_wvs, model_fluxes, kind='cubic', bounds_error=False) filter_model = model_interp(filter_wv_coords) @@ -438,7 +404,7 @@ def convolve_and_sample(wv_channels, sigmas_wvs, model_wvs, model_fluxes, num_si # ---------------------------------------------------------------------------------------------------------------------- -def resolution_decreasing(global_params, cut, wav_mod_nativ, flx_mod_nativ, res_mod_nativ, obs_or_mod, obs_name='', indobs=0): +def resolution_decreasing(global_params, wav_obs, flx_obs, res_obs, wav_mod_nativ, flx_mod_nativ, res_mod_obs, obs_or_mod, indobs=0): """ Decrease the resolution of a spectrum (data or model). The function calculates the FWHM as a function of the wavelengths for the data, the model, and for a custom spectral resolution (optional) and estimates the highest one @@ -448,58 +414,49 @@ def resolution_decreasing(global_params, cut, wav_mod_nativ, flx_mod_nativ, res_ Args: global_params (object): Class containing each parameter used in ForMoSA - cut (list): Sub-spectra defined by the parameter "wav_for_adapt". - [[wav_1, flx_1, err_1, reso_1], ..., [wav_n, flx_n, err_n, reso_n]] + wav_obs (array): Wavelength grid of the data + flx_obs (array): Flux of the data + res_obs (array): Spectral resolution of the data wav_mod_nativ (array): Wavelength grid of the model flx_mod_nativ (array): Flux of the model - res_mod_nativ (array): Spectral resolution of the model as a function of the wavelength grid + res_mod_obs (array): Spectral resolution of the model as a function of the wavelength grid of the data obs_or_mod (str): Parameter to identify if you want to manage a data or a model spectrum. 'obs' or 'mod' - obs_name (str): Name of the current observation looping indobs (int): Index of the current observation looping Returns: - flx_obs_final (array): Flux of the spectrum with a decreased spectral resolution, re-sampled on the data wavelength grid + - flx_obs_final (array) : Flux of the spectrum with a decreased spectral resolution, re-sampled on the data wavelength grid - Author: Simon Petrus / Adapted: Matthieu Ravet + Author: Simon Petrus, Matthieu Ravet """ # Estimate of the FWHM of the data as a function of the wavelength - fwhm_obs = 2 * cut[0] / cut[3] - + fwhm_obs = 2 * wav_obs / res_obs # Estimate of the FWHM of the model as a function of the wavelength - ind_mod_obs = np.where((wav_mod_nativ <= cut[0][-1]) & (wav_mod_nativ > cut[0][0])) - wav_mod_obs = wav_mod_nativ[ind_mod_obs] - res_mod_obs = res_mod_nativ[ind_mod_obs] - interp_mod_to_obs = interp1d(wav_mod_obs, res_mod_obs, fill_value='extrapolate') - res_mod_obs = interp_mod_to_obs(cut[0]) - fwhm_mod = 2 * cut[0] / res_mod_obs + fwhm_mod = 2 * wav_obs / res_mod_obs # Estimate of the FWHM of the custom resolution (if defined) as a function of the wavelength if global_params.custom_reso[indobs] != 'NA': - fwhm_custom = 2 * cut[0] / float(global_params.custom_reso[indobs]) + fwhm_custom = 2 * wav_obs / float(global_params.custom_reso[indobs]) else: - fwhm_custom = cut[0] * np.nan + fwhm_custom = wav_obs * np.nan + # Estimate of the sigma for the convolution as a function of the wavelength and decrease the resolution max_fwhm = np.nanmax([fwhm_obs, fwhm_mod, fwhm_custom], axis=0) if obs_or_mod == 'obs': fwhm_conv = np.sqrt(max_fwhm ** 2 - fwhm_obs ** 2) sigma_conv = fwhm_conv / 2.355 - flx_obs_final = convolve_and_sample(cut[0], sigma_conv, cut[0], cut[1]) + flx_obs_final = convolve_and_sample(wav_obs, sigma_conv, wav_obs, flx_obs) else: fwhm_conv = np.sqrt(max_fwhm ** 2 - fwhm_mod ** 2) sigma_conv = fwhm_conv / 2.355 - flx_obs_final = convolve_and_sample(cut[0], sigma_conv, wav_mod_nativ, flx_mod_nativ) + flx_obs_final = convolve_and_sample(wav_obs, sigma_conv, wav_mod_nativ, flx_mod_nativ) return flx_obs_final # ---------------------------------------------------------------------------------------------------------------------- -def continuum_estimate(global_params, wav_cut, wav, flx, res, obs_or_mod, obs_name='', indobs=0): +def continuum_estimate(global_params, wav, flx, res, indobs=0): """ - - NOT USED ANYMORE !!!!!! - - Decrease the resolution of a spectrum (data or model). The function calculates the FWHM as a function of the wavelengths of the custom spectral resolution (estimated for the continuum). It then calculates a sigma to decrease the resolution of the spectrum to this custom FWHM for each wavelength using a gaussian filter and resample it on @@ -507,38 +464,22 @@ def continuum_estimate(global_params, wav_cut, wav, flx, res, obs_or_mod, obs_na Args: global_params (object): Class containing each parameter used in ForMoSA - wav_cut (array): Wavelength grid of the sub-spectrum data wav (array): Wavelength grid of the spectrum for which you want to estimate the continuum flx (array): Flux of the spectrum for which you want to estimate the continuum res (int): Spectral resolution of the spectrum for which you want to estimate the continuum - obs_or_mod (str): Parameter to identify if you want to manage a data or a model spectrum. 'obs' or 'mod' - obs_name (str): Name of the current observation looping indobs (int): Index of the current observation looping Returns: - continuum (array): Estimated continuum of the spectrum re-sampled on the data wavelength grid + - continuum (array) : Estimated continuum of the spectrum re-sampled on the data wavelength grid - Author: Simon Petrus / Adapted: Matthieu Ravet + Author: Simon Petrus, Matthieu Ravet """ - # Adapt the model to the data grid wavelength - if obs_or_mod == 'mod': - interp_mod_to_obs = interp1d(wav, flx, kind='cubic', bounds_error=False) - flx = interp_mod_to_obs(wav_cut) - interp_mod_to_obs = interp1d(wav, res, kind='cubic', bounds_error=False) - res = interp_mod_to_obs(wav_cut) - wav = wav_cut # Redifined a spectrum only composed by the wavelength ranges used to estimate the continuum wav_for_continuum = global_params.wav_for_continuum[indobs].split('/') for wav_for_cont_cut_ind, wav_for_cont_cut in enumerate(wav_for_continuum): wav_for_cont_cut = wav_for_cont_cut.split(',') - if wav_for_cont_cut_ind == 0: - ind_cont_cut = np.where(wav <= float(wav_for_cont_cut[1])) - elif wav_for_cont_cut_ind == len(wav_for_continuum)-1: - ind_cont_cut = np.where(float(wav_for_cont_cut[0]) <= wav) - else: - ind_cont_cut = np.where((float(wav_for_cont_cut[0]) <= wav) & - (wav <= float(wav_for_cont_cut[1]))) + ind_cont_cut = np.where((float(wav_for_cont_cut[0]) <= wav) & (wav <= float(wav_for_cont_cut[1]))) if wav_for_cont_cut_ind == 0: wav_for_cont_final = wav[ind_cont_cut] flx_for_cont_final = flx[ind_cont_cut] @@ -549,19 +490,20 @@ def continuum_estimate(global_params, wav_cut, wav, flx, res, obs_or_mod, obs_na model_interp = interp1d(wav_for_cont_final, flx_for_cont_final, kind='linear', bounds_error=False) flx = model_interp(wav) - # To limit the computing time, the sigma for the convolution is not as a function of the wavelength but calculated + # # To limit the computing time, the convolution is not as a function of the wavelength but calculated # from the median wavelength. We just want an estimate of the continuum here. wav_median = np.median(wav) - ind_wav_median_obs = find_nearest(wav, wav_median) - dwav = wav[ind_wav_median_obs+1] - wav[ind_wav_median_obs] + dwav_median = np.median(np.abs(wav - np.roll(wav, 1))) # Estimated the median wavelength separation instead of taking wav_median - (wav_median+1) that could be on a border fwhm = 2 * wav_median / np.median(res) fwhm_continuum = 2 * wav_median / float(global_params.continuum_sub[indobs]) fwhm_conv = np.sqrt(fwhm_continuum**2 - fwhm**2) - sigma = fwhm_conv / (dwav * 2.355) + sigma = fwhm_conv / (dwav_median * 2.355) continuum = gaussian_filter(flx, sigma) + # import scipy.signal as sg + # continuum = sg.savgol_filter(flx, 3001, 2) return continuum diff --git a/build/lib/ForMoSA/nested_sampling/nested_logL_functions.py b/build/lib/ForMoSA/nested_sampling/nested_logL_functions.py index 4e93b16..6e581b3 100644 --- a/build/lib/ForMoSA/nested_sampling/nested_logL_functions.py +++ b/build/lib/ForMoSA/nested_sampling/nested_logL_functions.py @@ -3,13 +3,13 @@ def logL_chi2_classic(delta_flx, err): """ Function to compute logL based on the classical chi2 - under the assumption of gaussian and spectrally uncorrelated noise + under the assumption of gaussian and spectrally uncorrelated noise. Args: - delta_flx : residual data-model as a function of wavelength - err : error (=standard deviation) of the observed spectrum as a function of wavelength + delta_flx (array): residual data-model as a function of wavelength + err (array): error (=standard deviation) of the observed spectrum as a function of wavelength Returns: - logL : the loglikelihood value + - logL (float) : the loglikelihood value Author: Matthieu Ravet """ @@ -23,13 +23,13 @@ def logL_chi2_classic(delta_flx, err): def logL_chi2_covariance(delta_flx, inv_cov): """ Function to compute logL based on the generalized chi2 - under the assumption of gaussian and spectrally correlated noise + under the assumption of gaussian and spectrally correlated noise. Args: - delta_flx : residual data-model as a function of wavelength - inv_cov : inverse of the covariance matrix of the observed spectrum as a function of wavelength + delta_flx (array): residual data-model as a function of wavelength + inv_cov (n-array): inverse of the covariance matrix of the observed spectrum as a function of wavelength Returns: - logL : the loglikelihood value + - logL (float) : the loglikelihood value Author: Matthieu Ravet """ @@ -39,17 +39,63 @@ def logL_chi2_covariance(delta_flx, inv_cov): return logL + +def logL_chi2_extended(delta_flx, err): + """ + Function to compute logL based on the extended chi2 + under the assumption of gaussian and spectrally uncorrelated noise. + + Args: + delta_flx (array): residual data-model as a function of wavelength + err (array): error (=standard deviation) of the observed spectrum as a function of wavelength + Returns: + - logL (float) : the loglikelihood value + + Author: Allan Denis + """ + + N = len(delta_flx) + chi2 = np.nansum((delta_flx / err) ** 2) + s2 = 1/N * chi2 + logL = -(chi2 / (2*s2) + N/2 * np.log(2*np.pi*s2) + 1/2 * np.log(np.dot(err,err))) + + return logL + + +def logL_chi2_extended_covariance(delta_flx, inv_cov): + """ + Function to compute logL based on the extended chi2 + under the assumption of gaussian and spectrally uncorrelated noise. + + Args: + delta_flx (array): residual data-model as a function of wavelength + err (array): error (=standard deviation) of the observed spectrum as a function of wavelength + Returns: + - logL (float) : the loglikelihood value + + Author: Allan Denis + """ + + cov = np.linalg.inv(inv_cov) + N = len(delta_flx) + chi2 = np.dot(delta_flx, np.dot(inv_cov, delta_flx)) + s2 = 1/N * chi2 + logL = -chi2 / (2*s2) - 1/2 * np.log(np.linalg.det(cov)) + + return logL + + def logL_full_covariance(delta_flx, inv_cov): """ Function to compute logL under the assumption of gaussian and spectrally correlated noise. This function is a generalized version of the logL_chi2_covariance and is to be used when dealing - with GP extimation of the covariance matrix + with GP extimation of the covariance matrix. Args: - delta_flx : residual data-model as a function of wavelength - inv_cov : inverse of the covariance matrix of the observed spectrum as a function of wavelength + delta_flx (array): residual data-model as a function of wavelength + inv_cov (n-array): inverse of the covariance matrix of the observed spectrum as a function of wavelength Returns: - logL : the loglikelihood value + - logL (float) : the loglikelihood value Author: Matthieu Ravet """ @@ -62,13 +108,13 @@ def logL_full_covariance(delta_flx, inv_cov): def logL_CCF_Brogi(flx_obs, flx_mod): """ Function to compute logL based on the CCF mapping from Brogi et al. 2019 - under the assumption of gaussian and spectrally constant noise + under the assumption of gaussian and spectrally constant noise. Args: - flx_obs : flux of the observation as a function of wavelength - flx_mod : flux of the model as a function of wavelength + flx_obs (array): flux of the observation as a function of wavelength + flx_mod (array): flux of the model as a function of wavelength Returns: - logL : the loglikelihood value + - logL (float) : the loglikelihood value Author: Matthieu Ravet """ @@ -86,13 +132,13 @@ def logL_CCF_Brogi(flx_obs, flx_mod): def logL_CCF_Zucker(flx_obs, flx_mod): """ Function to compute logL based on the CCF mapping from Zucker 2003 - under the assumption of gaussian and spectrally constant noise + under the assumption of gaussian and spectrally constant noise. Args: - flx_obs : flux of the observation as a function of wavelength - flx_mod : flux of the model as a function of wavelength + flx_obs (array): flux of the observation as a function of wavelength + flx_mod (array): flux of the model as a function of wavelength Returns: - logL : the loglikelihood value + - logL (float) : the loglikelihood value Author: Matthieu Ravet """ @@ -111,14 +157,14 @@ def logL_CCF_Zucker(flx_obs, flx_mod): def logL_CCF_custom(flx_obs, flx_mod, err_obs): """ Function to compute logL based on the custom CCF mapping from Me - under the assumption of gaussian and spectrally constant noise + under the assumption of gaussian and spectrally constant noise. Args: - flx_obs : flux of the observation as a function of wavelength - flx_mod : flux of the model as a function of wavelength - err_obs : errors of the observation as a function of wavelength + flx_obs (array): flux of the observation as a function of wavelength + flx_mod (array): flux of the model as a function of wavelength + err_obs (array): errors of the observation as a function of wavelength Returns: - logL : the loglikelihood value + - logL (float) : the loglikelihood value Author: Matthieu Ravet """ diff --git a/build/lib/ForMoSA/nested_sampling/nested_modif_spec.py b/build/lib/ForMoSA/nested_sampling/nested_modif_spec.py index 95bb39a..a5157a2 100644 --- a/build/lib/ForMoSA/nested_sampling/nested_modif_spec.py +++ b/build/lib/ForMoSA/nested_sampling/nested_modif_spec.py @@ -1,115 +1,135 @@ import numpy as np -import xarray as xr import extinction from scipy.interpolate import interp1d import astropy.units as u import astropy.constants as const -from PyAstronomy.pyasl import dopplerShift, rotBroad -from adapt.extraction_functions import resolution_decreasing, convolve_and_sample -import scipy.ndimage as ndi +from PyAstronomy.pyasl import rotBroad, fastRotBroad +import scipy.signal as sg import scipy.optimize as optimize -import matplotlib.pyplot as plt -import time # ---------------------------------------------------------------------------------------------------------------------- -def lsq_fct(flx_obs_merge, err_obs_merge, star_flx_obs_merge, transm_obs_merge, new_flx_merge, ccf_method = 'continuum_unfiltered'): +def lsq_fct(flx_obs_spectro, err_obs_spectro, star_flx_obs, transm_obs, flx_mod_spectro, system_obs, ccf_method = 'continuum_unfiltered'): """ Estimation of the contribution of the planet and of the star to a spectrum (Used for HiRISE data) Args: - flx_obs_merge: Flux of the data (spectroscopy) - err_obs_merge: Error of the data (spectroscopy) - star_flx_obs_merge: Flux of star observation data (spectroscopy) - transm_obs_merge: Transmission (Atmospheric + Instrumental) - new_flx_merge: Flux of interpolated synthetic spectrum (spectroscopy) - wav_obs_merge : Wavelength grid of the data (spectroscopy) - + flx_obs_spectro (array): Flux of the data (spectroscopy) + err_obs_spectro (array): Error of the data (spectroscopy) + star_flx_obs (n-array): Flux of star observation data (spectroscopy) + transm_obs (array): Transmission (Atmospheric + Instrumental) + system_obs (n-array): Systematics of the data (spectroscopy) + flx_mod_spectro (array): Flux of interpolated synthetic spectrum (spectroscopy) Returns: - cp : Planetary contribution to the data (Spectroscopy) - cs : Stellar contribution to the data (Spectroscopy) - new_flx_merge : New model of the companion - flx_obs_merge : New flux of the data - star_flx_obs_merge : New star flux of the data + - cp (array) : Planetary contribution to the data (Spectroscopy) + - cs (array) : Stellar contribution to the data (Spectroscopy) + - flx_mod_spectro (array) : New model of the companion + - flx_obs_spectro (array) : New flux of the data + - star_flx_obs (n-array) : New star flux of the data + - systematics (array) : The systematics + + Author : Allan Denis + """ - new_flx_merge = new_flx_merge * transm_obs_merge - + flx_mod_spectro *= transm_obs + star_flx_0 = star_flx_obs[0,:,len(star_flx_obs[0][0]) // 2] + # # # # # Continuum estimation with lowpass filtering # # Low-pass filtering - flx_obs_merge_continuum = ndi.gaussian_filter(flx_obs_merge, 300) - star_flx_obs_merge_continuum = ndi.gaussian_filter(star_flx_obs_merge, 300) - new_flx_merge_continuum = ndi.gaussian_filter(new_flx_merge, 300) + flx_obs_spectro_continuum = sg.savgol_filter(flx_obs_spectro, 301, 2) + star_flx_obs_continuum = sg.savgol_filter(star_flx_0, 301, 2) + flx_mod_spectro_continuum = sg.savgol_filter(flx_mod_spectro, 301, 2) # # # # # # if ccf_method == 'continuum_filtered': # Removal of low-pass filtered data - flx_obs_merge = flx_obs_merge - flx_obs_merge_continuum + np.nanmedian(flx_obs_merge) - star_flx_obs_merge = star_flx_obs_merge - star_flx_obs_merge_continuum + np.nanmedian(star_flx_obs_merge) - new_flx_merge = new_flx_merge - new_flx_merge_continuum + np.nanmedian(new_flx_merge) + flx_obs_spectro = flx_obs_spectro - flx_obs_spectro_continuum + np.nanmedian(flx_obs_spectro) + star_flx_obs = star_flx_obs - star_flx_obs_continuum + np.nanmedian(star_flx_obs) + flx_mod_spectro = flx_mod_spectro - flx_mod_spectro_continuum + np.nanmedian(flx_mod_spectro) elif ccf_method == 'continuum_unfiltered': - star_flx_obs_merge = star_flx_obs_merge * flx_obs_merge_continuum / star_flx_obs_merge_continuum - new_flx_merge = new_flx_merge - new_flx_merge_continuum * star_flx_obs_merge / star_flx_obs_merge_continuum + flx_mod_spectro = flx_mod_spectro - flx_mod_spectro_continuum * star_flx_0 / star_flx_obs_continuum + for i in range(len(star_flx_obs[0][0])): + star_flx_obs[0,:,i] = star_flx_obs[0,:,i] * flx_obs_spectro_continuum / star_flx_obs_continuum # # # # # Least squares estimation # # Construction of the matrix - - A_matrix = np.zeros([np.size(flx_obs_merge), 2]) - A_matrix[:,0] = new_flx_merge * err_obs_merge - A_matrix[:,1] = star_flx_obs_merge * err_obs_merge + if len(system_obs) > 0: + A_matrix = np.zeros([np.size(flx_obs_spectro), 1 + len(star_flx_obs[0][0]) + len(system_obs[0][0])]) + for j in range(len(system_obs[0][0])): + A_matrix[:,1+len(star_flx_obs[0][0])+j] = system_obs[0][:,j] * err_obs_spectro + else: + A_matrix = np.zeros([np.size(flx_obs_spectro), 1 + len(star_flx_obs[0][0])]) + + for j in range(len(star_flx_obs[0][0])): + A_matrix[:,1+j] = star_flx_obs[0][:,j] * err_obs_spectro + + A_matrix[:,0] = flx_mod_spectro * err_obs_spectro # Least square - res = optimize.lsq_linear(A_matrix, flx_obs_merge * err_obs_merge) - cp, cs = res.x[0], res.x[1] + res = optimize.lsq_linear(A_matrix, flx_obs_spectro * err_obs_spectro, bounds=([0]*len(A_matrix[0]), [1]*len(A_matrix[0]))) + cp = res.x[0] + + cs = np.array([]) + for i in range(len(star_flx_obs[0][0])): + cs = np.append(cs, res.x[i+1]) + + systematics_c = np.array([]) + systematics = np.asarray([]) + if len(system_obs) > 0: + for i in range(len(system_obs[0][0])): + systematics_c = np.append(systematics_c, res.x[1+len(star_flx_obs[0][0])+i]) + + systematics = np.dot(systematics_c, system_obs[0].T) # # # # # # - return cp, cs, new_flx_merge, flx_obs_merge, star_flx_obs_merge + return cp, cs, flx_mod_spectro, flx_obs_spectro, star_flx_obs, systematics -def calc_ck(flx_obs_merge, err_obs_merge, new_flx_merge, flx_obs_phot, err_obs_phot, new_flx_phot, r_picked, d_picked, +def calc_ck(flx_obs_spectro, err_obs_spectro, flx_mod_spectro, flx_obs_photo, err_obs_photo, flx_mod_photo, r_picked, d_picked, alpha=1, analytic='no'): """ Calculation of the dilution factor Ck and re-normalization of the interpolated synthetic spectrum (from the radius and distance or analytically). Args: - flx_obs_merge : Flux of the data (spectroscopy) - err_obs_merge : Error of the data (spectroscopy) - new_flx_merge : Flux of the interpolated synthetic spectrum (spectroscopy) - flx_obs_phot : Flux of the data (photometry) - err_obs_phot : Error of the data (photometry) - new_flx_phot : Flux of the interpolated synthetic spectrum (photometry) - r_picked : Radius randomly picked by the nested sampling (in RJup) - d_picked : Distance randomly picked by the nested sampling (in pc) - alpha : Manual scaling factor (set to 1 by default) such that ck = alpha * (r/d)² - analytic : = 'yes' if Ck needs to be calculated analytically by the formula from Cushing et al. (2008) + flx_obs_spectro (array): Flux of the data (spectroscopy) + err_obs_spectro (array): Error of the data (spectroscopy) + flx_mod_spectro (array): Flux of the interpolated synthetic spectrum (spectroscopy) + flx_obs_photo (array): Flux of the data (photometry) + err_obs_photo (array): Error of the data (photometry) + flx_mod_photo (array): Flux of the interpolated synthetic spectrum (photometry) + r_picked (float): Radius randomly picked by the nested sampling (in RJup) + d_picked (float): Distance randomly picked by the nested sampling (in pc) + alpha (float): Manual scaling factor (set to 1 by default) such that ck = alpha * (r/d)² + analytic (str): = 'yes' if Ck needs to be calculated analytically by the formula from Cushing et al. (2008) Returns: - new_flx_merge : Re-normalysed model spectrum - new_flx_phot : Re-normalysed model photometry - ck : Ck calculated + - flx_mod_spectro (array) : Re-normalysed model spectrum + - flx_mod_photo (array) : Re-normalysed model photometry + - ck (float) : Ck calculated Author: Simon Petrus """ # Calculation of the dilution factor ck as a function of the radius and distance if analytic == 'no': - r_picked *= 69911 - d_picked *= 3.086e+13 - ck = alpha * (r_picked/d_picked)**2 + r_picked *= u.Rjup + d_picked *= u.pc + ck = alpha * (r_picked.value/d_picked.value)**2 # Calculation of the dilution factor ck analytically else: - if len(flx_obs_merge) != 0: - ck_top_merge = np.sum((new_flx_merge * flx_obs_merge) / (err_obs_merge * err_obs_merge)) - ck_bot_merge = np.sum((new_flx_merge / err_obs_merge)**2) + if len(flx_obs_spectro) != 0: + ck_top_merge = np.sum((flx_mod_spectro * flx_obs_spectro) / (err_obs_spectro * err_obs_spectro)) + ck_bot_merge = np.sum((flx_mod_spectro / err_obs_spectro)**2) else: ck_top_merge = 0 ck_bot_merge = 0 - if len(flx_obs_phot) != 0: - ck_top_phot = np.sum((new_flx_phot * flx_obs_phot) / (err_obs_phot * err_obs_phot)) - ck_bot_phot = np.sum((new_flx_phot / err_obs_phot)**2) + if len(flx_obs_photo) != 0: + ck_top_phot = np.sum((flx_mod_photo * flx_obs_photo) / (err_obs_photo * err_obs_photo)) + ck_bot_phot = np.sum((flx_mod_photo / err_obs_photo)**2) else: ck_top_phot = 0 ck_bot_phot = 0 @@ -117,146 +137,158 @@ def calc_ck(flx_obs_merge, err_obs_merge, new_flx_merge, flx_obs_phot, err_obs_p ck = (ck_top_merge + ck_top_phot) / (ck_bot_merge + ck_bot_phot) # Re-normalization of the interpolated synthetic spectra with ck - if len(new_flx_merge) != 0: - new_flx_merge *= ck - if len(new_flx_phot) != 0: - new_flx_phot *= ck + if len(flx_mod_spectro) != 0: + flx_mod_spectro *= ck + if len(flx_mod_photo) != 0: + flx_mod_photo *= ck - return new_flx_merge, new_flx_phot, ck + return flx_mod_spectro, flx_mod_photo, ck # ---------------------------------------------------------------------------------------------------------------------- -def doppler_fct(wav_obs_merge, flx_obs_merge, err_obs_merge, new_flx_merge, rv_picked): +def doppler_fct(wav_obs_spectro, flx_obs_spectro, err_obs_spectro, flx_mod_spectro, rv_picked): """ Application of a Doppler shifting to the interpolated synthetic spectrum using the function pyasl.dopplerShift. Note: Observation can change due to side effects of the shifting. Args: - wav_obs_merge : Wavelength grid of the data - flx_obs_merge : Flux of the data - err_obs_merge : Error of the data - new_flx_merge : Flux of the interpolated synthetic spectrum - rv_picked : Radial velocity randomly picked by the nested sampling (in km.s-1) + wav_obs_spectro (array): Wavelength grid of the data + flx_obs_spectro (array): Flux of the data + err_obs_spectro (array): Error of the data + flx_mod_spectro (array): Flux of the interpolated synthetic spectrum + rv_picked (float): Radial velocity randomly picked by the nested sampling (in km.s-1) Returns: - wav_obs_merge : New wavelength grid of the data - flx_obs_merge : New flux of the data - err_obs_merge : New error of the data - flx_post_doppler : New flux of the interpolated synthetic spectrum + - wav_obs_spectro (array) : New wavelength grid of the data + - flx_obs_spectro (array) : New flux of the data + - err_obs_spectro (array) : New error of the data + - flx_post_doppler (array) : New flux of the interpolated synthetic spectrum Author: Simon Petrus """ - # wav_doppler = wav_obs_merge*10000 - # flx_post_doppler, wav_post_doppler = dopplerShift(wav_doppler, new_flx_merge, rv_picked) - new_wav = wav_obs_merge * ((rv_picked / 299792.458) + 1) + new_wav = wav_obs_spectro * ((rv_picked / const.c.to(u.km/u.s).value) + 1) + rv_interp = interp1d(new_wav, flx_mod_spectro, fill_value="extrapolate") + flx_post_doppler = rv_interp(wav_obs_spectro) + + return wav_obs_spectro, flx_obs_spectro, err_obs_spectro, flx_post_doppler - rv_interp = interp1d(new_wav, new_flx_merge, fill_value="extrapolate") - flx_post_doppler = rv_interp(wav_obs_merge) +# ---------------------------------------------------------------------------------------------------------------------- + + +def reddening_fct(wav_obs_spectro, wav_obs_photo, flx_mod_spectro, flx_mod_photo, av_picked): + """ + Application of a sythetic interstellar extinction to the interpolated synthetic spectrum using the function + extinction.fm07. - return wav_obs_merge, flx_obs_merge, err_obs_merge, flx_post_doppler + Args: + wav_obs_spectro (array): Wavelength grid of the data (spectroscopy) + wav_obs_photo (array): Wavelength of the data (photometry) + flx_mod_spectro (array): Flux of the interpolated synthetic spectrum (spectroscopy) + flx_mod_photo (array): Flux of the interpolated synthetic spectrum (photometry) + av_picked (float): Extinction randomly picked by the nested sampling (in mag) + Returns: + - flx_mod_spectro (array) : New flux of the interpolated synthetic spectrum (spectroscopy) + - flx_mod_photo (array) : New flux of the interpolated synthetic spectrum (photometry) - # return Spectrum1d.from_array(new_wavelength, new_flux) - # # Side effects - # ind_nonan = np.argwhere(~np.isnan(flx_post_doppler)) - # wav_obs_merge = wav_obs_merge[ind_nonan[:, 0]] - # flx_obs_merge = flx_obs_merge[ind_nonan[:, 0]] - # err_obs_merge = err_obs_merge[ind_nonan[:, 0]] - # flx_post_doppler = flx_post_doppler[ind_nonan[:, 0]] + Author: Simon Petrus + """ + if len(wav_obs_spectro) != 0: + dered_merge = extinction.fm07(wav_obs_spectro * 10000, av_picked, unit='aa') + flx_mod_spectro *= 10**(-0.4*dered_merge) + if len(wav_obs_photo) != 0: + dered_phot = extinction.fm07(wav_obs_photo * 10000, av_picked, unit='aa') + flx_mod_photo *= 10**(-0.4*dered_phot) - # return wav_obs_merge, flx_obs_merge, err_obs_merge, flx_post_doppler + return flx_mod_spectro, flx_mod_photo # ---------------------------------------------------------------------------------------------------------------------- -def reddening_fct(wav_obs_merge, wav_obs_phot, new_flx_merge, new_flx_phot, av_picked): +def vsini_fct_rot_broad(wav_obs_spectro, flx_mod_spectro, ld_picked, vsini_picked): """ - Application of a sythetic interstellar extinction to the interpolated synthetic spectrum using the function + Application of a rotation velocity (line broadening) to the interpolated synthetic spectrum using the function extinction.fm07. Args: - wav_obs_merge : Wavelength grid of the data (spectroscopy) - wav_obs_phot : Wavelength of the data (photometry) - new_flx_merge : Flux of the interpolated synthetic spectrum (spectroscopy) - new_flx_phot : Flux of the interpolated synthetic spectrum (photometry) - av_picked : Extinction randomly picked by the nested sampling (in mag) + wav_obs_spectro (array): Wavelength grid of the data + flx_mod_spectro (array): Flux of the interpolated synthetic spectrum + ld_picked (float): Limd darkening randomly picked by the nested sampling + vsini_picked (float): v.sin(i) randomly picked by the nested sampling (in km.s-1) Returns: - new_flx_merge : New flux of the interpolated synthetic spectrum (spectroscopy) - new_flx_phot : New flux of the interpolated synthetic spectrum (photometry) + - flx_mod_spectro (array) : New flux of the interpolated synthetic spectrum Author: Simon Petrus """ - if len(wav_obs_merge) != 0: - dered_merge = extinction.fm07(wav_obs_merge * 10000, av_picked, unit='aa') - new_flx_merge *= 10**(-0.4*dered_merge) - if len(wav_obs_phot) != 0: - dered_phot = extinction.fm07(wav_obs_phot * 10000, av_picked, unit='aa') - new_flx_phot *= 10**(-0.4*dered_phot) + # Correct irregulatities in the wavelength grid + wav_interval = wav_obs_spectro[1:] - wav_obs_spectro[:-1] + wav_to_vsini = np.arange(min(wav_obs_spectro), max(wav_obs_spectro), min(wav_interval) * 2/3) + vsini_interp = interp1d(wav_obs_spectro, flx_mod_spectro, fill_value="extrapolate") + flx_to_vsini = vsini_interp(wav_to_vsini) + # Apply the v.sin(i) + new_flx = rotBroad(wav_to_vsini, flx_to_vsini, ld_picked, vsini_picked) + vsini_interp = interp1d(wav_to_vsini, new_flx, fill_value="extrapolate") + flx_mod_spectro = vsini_interp(wav_obs_spectro) + + return flx_mod_spectro - return new_flx_merge, new_flx_phot # ---------------------------------------------------------------------------------------------------------------------- -def vsini_fct(wav_obs_merge, new_flx_merge, ld_picked, vsini_picked): +def vsini_fct_fast_rot_broad(wav_obs_spectro, flx_mod_spectro, ld_picked, vsini_picked): """ Application of a rotation velocity (line broadening) to the interpolated synthetic spectrum using the function extinction.fm07. Args: - wav_obs_merge : Wavelength grid of the data - new_flx_merge : Flux of the interpolated synthetic spectrum - ld_picked : Limd darkening randomly picked by the nested sampling - vsini_picked : v.sin(i) randomly picked by the nested sampling (in km.s-1) + wav_obs_spectro (array): Wavelength grid of the data + flx_mod_spectro (array): Flux of the interpolated synthetic spectrum + ld_picked (float): Limd darkening randomly picked by the nested sampling + vsini_picked (float): v.sin(i) randomly picked by the nested sampling (in km.s-1) Returns: - new_flx_merge : New flux of the interpolated synthetic spectrum + - flx_mod_spectro (array) : New flux of the interpolated synthetic spectrum Author: Simon Petrus """ # Correct irregulatities in the wavelength grid - wav_interval = wav_obs_merge[1:] - wav_obs_merge[:-1] - wav_to_vsini = np.arange(min(wav_obs_merge), max(wav_obs_merge), min(wav_interval) * 2/3) - vsini_interp = interp1d(wav_obs_merge, new_flx_merge, fill_value="extrapolate") + wav_interval = wav_obs_spectro[1:] - wav_obs_spectro[:-1] + wav_to_vsini = np.arange(min(wav_obs_spectro), max(wav_obs_spectro), min(wav_interval) * 2/3) + vsini_interp = interp1d(wav_obs_spectro, flx_mod_spectro, fill_value="extrapolate") flx_to_vsini = vsini_interp(wav_to_vsini) # Apply the v.sin(i) - new_flx = rotBroad(wav_to_vsini, flx_to_vsini, ld_picked, vsini_picked) + new_flx = fastRotBroad(wav_to_vsini, flx_to_vsini, ld_picked, vsini_picked) vsini_interp = interp1d(wav_to_vsini, new_flx, fill_value="extrapolate") - new_flx_merge = vsini_interp(wav_obs_merge) + flx_mod_spectro = vsini_interp(wav_obs_spectro) - return new_flx_merge + return flx_mod_spectro # ---------------------------------------------------------------------------------------------------------------------- -def vsini_fct_new(wave_obs_merge, new_flx_merge, ld_picked, vsini_picked, nr=50, ntheta=100, dif=0.0): +def vsini_fct_accurate(wave_obs_merge, flx_mod_spectro, ld_picked, vsini_picked, nr=50, ntheta=100, dif=0.0): ''' A routine to quickly rotationally broaden a spectrum in linear time. + Adapted from Carvalho & Johns-Krull 2023 https://ui.adsabs.harvard.edu/abs/2023RNAAS...7...91C/abstract - Carvalho & Johns-Krull 2023 - https://ui.adsabs.harvard.edu/abs/2023RNAAS...7...91C/abstract - - ARGS: - wav_obs_merge : Wavelength grid of the data - new_flx_merge : Flux of the interpolated synthetic spectrum - ld_picked : Limd darkening randomly picked by the nested sampling - vsini_picked : v.sin(i) randomly picked by the nested sampling (in km.s-1) - + Args: + wav_obs_spectro (array): Wavelength grid of the data + flx_mod_spectro (array): Flux of the interpolated synthetic spectrum + ld_picked (float): Limd darkening randomly picked by the nested sampling + vsini_picked (float): v.sin(i) randomly picked by the nested sampling (in km.s-1) + nr (int): (default = 10) The number of radial bins on the projected disk + ntheta (int): (default = 100) The number of azimuthal bins in the largest radial annulus + note: the number of bins at each r is int(r*ntheta) where r < 1 + dif (float): (default = 0) The differential rotation coefficient, applied according to the law Omeg(th)/Omeg(eq) = (1 - dif/2 - (dif/2) cos(2 th)). + Dif = .675 nicely reproduces the law proposed by Smith, 1994, A&A, Vol. 287, p. 523-534, to unify WTTS and CTTS. + Dif = .23 is similar to observed solar differential rotation. Note: the th in the above expression is the stellar co-latitude, not the same as the integration variable used below. + This is a disk integration routine. Returns: - new_flx_merge : New flux of the interpolated synthetic spectrum + - flx_mod_spectro (array) : New flux of the interpolated synthetic spectrum - OPTIONAL ARGS: - nr (default = 10) - the number of radial bins on the projected disk - ntheta (default = 100) - the number of azimuthal bins in the largest radial annulus - note: the number of bins at each r is int(r*ntheta) where r < 1 - - dif (default = 0) - the differential rotation coefficient, applied according to the law - Omeg(th)/Omeg(eq) = (1 - dif/2 - (dif/2) cos(2 th)). Dif = .675 nicely reproduces the law - proposed by Smith, 1994, A&A, Vol. 287, p. 523-534, to unify WTTS and CTTS. Dif = .23 is - similar to observed solar differential rotation. Note: the th in the above expression is - the stellar co-latitude, not the same as the integration variable used below. This is a - disk integration routine. - ''' + Author: Allan Denis + ''' - ns = np.copy(new_flx_merge)*0.0 + ns = np.copy(flx_mod_spectro)*0.0 tarea = 0.0 dr = 1./nr for j in range(0, nr): @@ -266,33 +298,34 @@ def vsini_fct_new(wave_obs_merge, new_flx_merge, ld_picked, vsini_picked, nr=50, th = np.pi/int(ntheta*r) + k * 2.0*np.pi/int(ntheta*r) if dif != 0: vl = vsini_picked * r * np.sin(th) * (1.0 - dif/2.0 - dif/2.0*np.cos(2.0*np.arccos(r*np.cos(th)))) - ns += area * np.interp(wave_obs_merge + wave_obs_merge*vl/2.9979e5, wave_obs_merge, new_flx_merge) + ns += area * np.interp(wave_obs_merge + wave_obs_merge*vl/const.c.to(u.km/u.s).value, wave_obs_merge, flx_mod_spectro) tarea += area else: vl = r * vsini_picked * np.sin(th) - ns += area * np.interp(wave_obs_merge + wave_obs_merge*vl/2.9979e5, wave_obs_merge, new_flx_merge) + ns += area * np.interp(wave_obs_merge + wave_obs_merge*vl/const.c.to(u.km/u.s).value, wave_obs_merge, flx_mod_spectro) tarea += area - new_flx_merge = ns / tarea - return new_flx_merge + flx_mod_spectro = ns / tarea + return flx_mod_spectro # ---------------------------------------------------------------------------------------------------------------------- -def bb_cpd_fct(wav_obs_merge, wav_obs_phot, new_flx_merge, new_flx_phot, distance, bb_T_picked, bb_R_picked): - ''' Function to add the effect of a cpd (circum planetary disc) to the models - Args: - wav_obs_merge : Wavelength grid of the data (spectroscopy) - wav_obs_phot : Wavelength of the data (photometry) - new_flx_merge : Flux of the interpolated synthetic spectrum (spectroscopy) - new_flx_phot : Flux of the interpolated synthetic spectrum (photometry) - bb_temp : Temperature value randomly picked by the nested sampling in K units - bb_rad : Radius randomly picked by the nested sampling in units of planetary radius +def bb_cpd_fct(wav_obs_spectro, wav_obs_photo, flx_mod_spectro, flx_mod_photo, distance, bb_T_picked, bb_R_picked): + ''' + Function to add the effect of a cpd (circum planetary disc) to the models. + Args: + wav_obs_spectro (array): Wavelength grid of the data (spectroscopy) + wav_obs_photo (array): Wavelength of the data (photometry) + flx_mod_spectro (array): Flux of the interpolated synthetic spectrum (spectroscopy) + flx_mod_photo (array): Flux of the interpolated synthetic spectrum (photometry) + bb_temp (float): Temperature value randomly picked by the nested sampling in K units + bb_rad (float): Radius randomly picked by the nested sampling in units of planetary radius Returns: - new_flx_merge : New flux of the interpolated synthetic spectrum (spectroscopy) - new_flx_phot : New flux of the interpolated synthetic spectrum (photometry) + - flx_mod_spectro (array) : New flux of the interpolated synthetic spectrum (spectroscopy) + - flx_mod_photo (array) : New flux of the interpolated synthetic spectrum (photometry) - Author: P. Palma-Bifani + Author: Paulina Palma-Bifani ''' bb_T_picked *= u.K @@ -305,104 +338,60 @@ def planck(wav, T): intensity = a/ ( (wav**5) * (np.exp(b) - 1.0) ) return intensity - bb_intensity = planck(wav_obs_merge*u.um, bb_T_picked) - bb_intensity_f = planck(wav_obs_phot*u.um, bb_T_picked) - - #flux_bb_lambda = ( np.pi * (bb_R_picked)**2 / ( ck*u.km **2) * bb_intensity ).to(u.W/u.m**2/u.micron) - flux_bb_lambda = ( 4*np.pi*bb_R_picked**2/(distance**2) * bb_intensity ).to(u.W/u.m**2/u.micron) - - #flux_bb_lambda_f = ( np.pi * (bb_R_picked)**2 / ( ck*u.km **2) * bb_intensity_f ).to(u.W/u.m**2/u.micron) - flux_bb_lambda_f = ( 4*np.pi*bb_R_picked**2/(distance**2) * bb_intensity_f ).to(u.W/u.m**2/u.micron) + bb_intensity = planck(wav_obs_spectro*u.um, bb_T_picked) + bb_intensity_f = planck(wav_obs_photo*u.um, bb_T_picked) + flux_bb_lambda = ( np.pi*bb_R_picked**2/(distance**2) * bb_intensity ).to(u.W/u.m**2/u.micron) + flux_bb_lambda_f = ( np.pi*bb_R_picked**2/(distance**2) * bb_intensity_f ).to(u.W/u.m**2/u.micron) # add to model flux of the atmosphere - new_flx_merge += flux_bb_lambda.value - new_flx_phot += flux_bb_lambda_f.value + flx_mod_spectro += flux_bb_lambda.value + flx_mod_photo += flux_bb_lambda_f.value # - return new_flx_merge, new_flx_phot - - -# ---------------------------------------------------------------------------------------------------------------------- - - -def reso_fct(global_params, theta, theta_index, wav_obs_merge, new_flx_merge, reso_picked): - """ - WORKING! - Function to scale the spectral resolution of the synthetic spectra. This option is currently in test and make use - of the functions defined in the 'adapt' section of ForMoSA, meaning that they will significantly decrease the speed of - your inversion as the grid needs to be re-interpolated - - Args: - global_params : Class containing each parameter - theta : Parameter values randomly picked by the nested sampling - theta_index : Parameter index identificator - wav_obs_merge : Wavelength grid of the data - new_flx_merge : Flux of the interpolated synthetic spectrum - reso_picked : Spectral resolution randomly picked by the nested sampling - Returns: - None - - Author: Matthieu Ravet - """ - - # Import the grid and set it with the right parameters - ds = xr.open_dataset(global_params.model_path, decode_cf=False, engine="netcdf4") - wav_mod_nativ = ds["wavelength"].values - grid = ds['grid'] - attr = ds.attrs - grid_np = grid.to_numpy() - model_to_adapt = grid_np[:, theta] - - # Modify the spectrum with the wanted spectral resolution - flx_mod_extract, mod_pho = adapt_model(global_params, wav_mod_nativ, model_to_adapt, attr['res'], obs_name=obs_name, - indobs=indobs) - - return + return flx_mod_spectro, flx_mod_photo # ---------------------------------------------------------------------------------------------------------------------- def modif_spec(global_params, theta, theta_index, - wav_obs_merge, flx_obs_merge, err_obs_merge, new_flx_merge, - wav_obs_phot, flx_obs_phot, err_obs_phot, new_flx_phot, transm_obs_merge = [], star_flx_obs_merge = [], indobs=0): + wav_obs_spectro, flx_obs_spectro, err_obs_spectro, flx_mod_spectro, + wav_obs_photo, flx_obs_photo, err_obs_photo, flx_mod_photo, transm_obs = [], star_flx_obs = [], system_obs = [], indobs=0): """ - Modification of the interpolated synthetic spectra with the different extra-grid parameters: - - Re-calibration on the data - - Doppler shifting - - Application of a substellar extinction - - Application of a rotational velocity - - Application of a circumplanetary disk (CPD) + Modification of the interpolated synthetic spectra with the different extra-grid parameters. + It can perform : Re-calibration on the data, Doppler shifting, Application of a substellar extinction, Application of a rotational velocity, + Application of a circumplanetary disk (CPD). Args: - global_params : Class containing each parameter - theta : Parameter values randomly picked by the nested sampling - theta_index : Parameter index identificator - wav_obs_merge : Wavelength grid of the data (spectroscopy) - flx_obs_merge : Flux of the data (spectroscopy) - err_obs_merge : Error of the data (spectroscopy) - new_flx_merge : Flux of the interpolated synthetic spectrum (spectroscopy) - wav_obs_phot : Wavelength grid of the data (photometry) - flx_obs_phot : Flux of the data (photometry) - err_obs_phot : Error of the data (photometry) - new_flx_phot : Flux of the interpolated synthetic spectrum (photometry) - transm_obs_merge: Transmission (Atmospheric + Instrumental) - star_flx_obs_merge: Flux of star observation data (spectroscopy) - indobs (int): Index of the current observation looping + global_params (object): Class containing each parameter + theta (list): Parameter values randomly picked by the nested sampling + theta_index (list): Parameter index identificator + wav_obs_spectro (array): Wavelength grid of the data (spectroscopy) + flx_obs_spectro (array): Flux of the data (spectroscopy) + err_obs_spectro (array): Error of the data (spectroscopy) + flx_mod_spectro (array): Flux of the interpolated synthetic spectrum (spectroscopy) + wav_obs_photo (array): Wavelength grid of the data (photometry) + flx_obs_photo (array): Flux of the data (photometry) + err_obs_photo (array): Error of the data (photometry) + flx_mod_photo (array): Flux of the interpolated synthetic spectrum (photometry) + transm_obs (array): Transmission (Atmospheric + Instrumental) + star_flx_obs (n-array): Flux of star observation data (spectroscopy) + system_obs (n-array): Systematics of the data (spectroscopy) + indobs (int): Index of the current observation looping Returns: - wav_obs_merge : New wavelength grid of the data (may change with the Doppler shift) - flx_obs_merge : New flux of the data (may change with the Doppler shift) - err_obs_merge : New error of the data (may change with the Doppler shift) - new_flx_merge : New flux of the interpolated synthetic spectrum (spectroscopy) - wav_obs_phot : Wavelength grid of the data (photometry) - flx_obs_phot : Flux of the data (photometry) - err_obs_phot : Error of the data (photometry) - new_flx_phot : New flux of the interpolated synthetic spectrum (photometry) + - wav_obs_spectro (array) : New wavelength grid of the data (may change with the Doppler shift) + - flx_obs_spectro (array) : New flux of the data (may change with the Doppler shift) + - err_obs_spectro (array) : New error of the data (may change with the Doppler shift) + - flx_mod_spectro (array) : New flux of the interpolated synthetic spectrum (spectroscopy) + - wav_obs_photo (array) : Wavelength grid of the data (photometry) + - flx_obs_photo (array) : Flux of the data (photometry) + - err_obs_photo (array) : Error of the data (photometry) + - flx_mod_photo (array) : New flux of the interpolated synthetic spectrum (photometry) - Author: Simon Petrus and Paulina Palma-Bifani + Author: Simon Petrus, Paulina Palma-Bifani, Allan Denis and Matthieu Ravet """ # Correction of the radial velocity of the interpolated synthetic spectrum. - if len(flx_obs_merge) != 0: + if len(flx_obs_spectro) != 0: if len(global_params.rv) > 3: # If you want separate rv for each observations if global_params.rv[indobs*3] != "NA": if global_params.rv[indobs*3] == "constant": @@ -410,8 +399,8 @@ def modif_spec(global_params, theta, theta_index, else: ind_theta_rv = np.where(theta_index == f'rv_{indobs}') rv_picked = theta[ind_theta_rv[0][0]] - wav_obs_merge, flx_obs_merge, err_obs_merge, new_flx_merge = doppler_fct(wav_obs_merge, flx_obs_merge, - err_obs_merge, new_flx_merge, + wav_obs_spectro, flx_obs_spectro, err_obs_spectro, flx_mod_spectro = doppler_fct(wav_obs_spectro, flx_obs_spectro, + err_obs_spectro, flx_mod_spectro, rv_picked) else: # If you want 1 common rv for all observations if global_params.rv != "NA": @@ -420,8 +409,8 @@ def modif_spec(global_params, theta, theta_index, else: ind_theta_rv = np.where(theta_index == 'rv') rv_picked = theta[ind_theta_rv[0][0]] - wav_obs_merge, flx_obs_merge, err_obs_merge, new_flx_merge = doppler_fct(wav_obs_merge, flx_obs_merge, - err_obs_merge, new_flx_merge, + wav_obs_spectro, flx_obs_spectro, err_obs_spectro, flx_mod_spectro = doppler_fct(wav_obs_spectro, flx_obs_spectro, + err_obs_spectro, flx_mod_spectro, rv_picked) # Application of a synthetic interstellar extinction to the interpolated synthetic spectrum. @@ -431,30 +420,63 @@ def modif_spec(global_params, theta, theta_index, else: ind_theta_av = np.where(theta_index == 'av') av_picked = theta[ind_theta_av[0][0]] - new_flx_merge, new_flx_phot = reddening_fct(wav_obs_merge, wav_obs_phot, new_flx_merge, new_flx_phot, av_picked) + flx_mod_spectro, flx_mod_photo = reddening_fct(wav_obs_spectro, wav_obs_photo, flx_mod_spectro, flx_mod_photo, av_picked) # Correction of the rotational velocity of the interpolated synthetic spectrum. - if len(flx_obs_merge) != 0: - if global_params.vsini != "NA" and global_params.ld != "NA": - if global_params.vsini[0] == 'constant': - vsini_picked = float(global_params.vsini[1]) - else: - ind_theta_vsini = np.where(theta_index == 'vsini') - vsini_picked = theta[ind_theta_vsini[0][0]] - if global_params.ld[0] == 'constant': - ld_picked = float(global_params.ld[1]) + if len(flx_obs_spectro) != 0: + if len(global_params.vsini) > 4 and len(global_params.ld) > 3: # If you want separate vsini/ld for each observations + if global_params.vsini[indobs*4] != "NA" and global_params.ld[indobs*3] != "NA": + if global_params.vsini[indobs*4] == 'constant': + vsini_picked = float(global_params.vsini[indobs*3+1]) + else: + ind_theta_vsini = np.where(theta_index == f'vsini_{indobs}') + vsini_picked = theta[ind_theta_vsini[0][0]] + if global_params.ld[indobs*3] == 'constant': + ld_picked = float(global_params.ld[indobs*3+1]) + else: + ind_theta_ld = np.where(theta_index == f'ld_{indobs}') + ld_picked = theta[ind_theta_ld[0][0]] + + if global_params.vsini[indobs*4 + 3] == 'RotBroad': + flx_mod_spectro = vsini_fct_rot_broad(wav_obs_spectro, flx_mod_spectro, ld_picked, vsini_picked) + if global_params.vsini[indobs*4 + 3] == 'FastRotBroad': + flx_mod_spectro = vsini_fct_fast_rot_broad(wav_obs_spectro, flx_mod_spectro, ld_picked, vsini_picked) + if global_params.vsini[indobs*4 + 3] == 'Accurate': + flx_mod_spectro = vsini_fct_accurate(wav_obs_spectro, flx_mod_spectro, ld_picked, vsini_picked) + + elif global_params.vsini[indobs*4] == "NA" and global_params.ld[indobs*3] == "NA": + pass + else: - ind_theta_ld = np.where(theta_index == 'ld') - ld_picked = theta[ind_theta_ld[0][0]] + print(f'WARNING: You need to define a v.sin(i) AND a limb darkening, or set them both to NA for observation {indobs}') + exit() + + else:# If you want 1 common vsini/ld for all observations + if global_params.vsini != "NA" and global_params.ld != "NA": + if global_params.vsini[0] == 'constant': + vsini_picked = float(global_params.vsini[1]) + else: + ind_theta_vsini = np.where(theta_index == 'vsini') + vsini_picked = theta[ind_theta_vsini[0][0]] + if global_params.ld[0] == 'constant': + ld_picked = float(global_params.ld[1]) + else: + ind_theta_ld = np.where(theta_index == 'ld') + ld_picked = theta[ind_theta_ld[0][0]] - new_flx_merge = vsini_fct_new(wav_obs_merge, new_flx_merge, ld_picked, vsini_picked) + if global_params.vsini[3] == 'RotBroad': + flx_mod_spectro = vsini_fct_rot_broad(wav_obs_spectro, flx_mod_spectro, ld_picked, vsini_picked) + if global_params.vsini[3] == 'FastRotBroad': + flx_mod_spectro = vsini_fct_fast_rot_broad(wav_obs_spectro, flx_mod_spectro, ld_picked, vsini_picked) + if global_params.vsini[3] == 'Accurate': + flx_mod_spectro = vsini_fct_accurate(wav_obs_spectro, flx_mod_spectro, ld_picked, vsini_picked) - elif global_params.vsini == "NA" and global_params.ld == "NA": - pass + elif global_params.vsini == "NA" and global_params.ld == "NA": + pass - else: - print('WARNING: You need to define a v.sin(i) AND a limb darkening, or set them both to NA') - exit() + else: + print('WARNING: You need to define a v.sin(i) AND a limb darkening, or set them both to NA') + exit() # Adding a CPD if global_params.bb_T != "NA" and global_params.bb_R != "NA": @@ -474,7 +496,7 @@ def modif_spec(global_params, theta, theta_index, ind_theta_d = np.where(theta_index == 'd') d_picked = theta[ind_theta_d[0][0]] - new_flx_merge, new_flx_phot = bb_cpd_fct(wav_obs_merge, wav_obs_phot, new_flx_merge, new_flx_phot, d_picked, bb_T_picked, bb_R_picked) + flx_mod_spectro, flx_mod_photo = bb_cpd_fct(wav_obs_spectro, wav_obs_photo, flx_mod_spectro, flx_mod_photo, d_picked, bb_T_picked, bb_R_picked) elif global_params.bb_T == "NA" and global_params.bb_R == "NA": pass @@ -485,8 +507,8 @@ def modif_spec(global_params, theta, theta_index, # Calculation of the dilution factor Ck and re-normalization of the interpolated synthetic spectrum. # From the radius and the distance. + if global_params.r != "NA" and global_params.d != "NA": - planet_contribution, stellar_contribution = 1, 1 if global_params.r[0] == "constant": r_picked = float(global_params.r[1]) else: @@ -506,12 +528,12 @@ def modif_spec(global_params, theta, theta_index, else: ind_theta_alpha = np.where(theta_index == f'alpha_{indobs}') alpha_picked = theta[ind_theta_alpha[0][0]] - new_flx_merge, new_flx_phot, ck = calc_ck(flx_obs_merge, err_obs_merge, new_flx_merge, - flx_obs_phot, err_obs_phot, new_flx_phot, r_picked, d_picked, + flx_mod_spectro, flx_mod_photo, ck = calc_ck(flx_obs_spectro, err_obs_spectro, flx_mod_spectro, + flx_obs_photo, err_obs_photo, flx_mod_photo, r_picked, d_picked, alpha=alpha_picked) else: # Without the extra alpha scaling - new_flx_merge, new_flx_phot, ck = calc_ck(flx_obs_merge, err_obs_merge, new_flx_merge, - flx_obs_phot, err_obs_phot, new_flx_phot, r_picked, d_picked) + flx_mod_spectro, flx_mod_photo, ck = calc_ck(flx_obs_spectro, err_obs_spectro, flx_mod_spectro, + flx_obs_photo, err_obs_photo, flx_mod_photo, r_picked, d_picked) else: # If you want 1 common alpha for all observations if global_params.alpha != "NA": if global_params.alpha[0] == "constant": @@ -519,38 +541,39 @@ def modif_spec(global_params, theta, theta_index, else: ind_theta_alpha = np.where(theta_index == 'alpha') alpha_picked = theta[ind_theta_alpha[0][0]] - new_flx_merge, new_flx_phot, ck = calc_ck(flx_obs_merge, err_obs_merge, new_flx_merge, - flx_obs_phot, err_obs_phot, new_flx_phot, r_picked, d_picked, + flx_mod_spectro, flx_mod_photo, ck = calc_ck(flx_obs_spectro, err_obs_spectro, flx_mod_spectro, + flx_obs_photo, err_obs_photo, flx_mod_photo, r_picked, d_picked, alpha=alpha_picked) else: # Without the extra alpha scaling - new_flx_merge, new_flx_phot, ck = calc_ck(flx_obs_merge, err_obs_merge, new_flx_merge, - flx_obs_phot, err_obs_phot, new_flx_phot, r_picked, d_picked) - + flx_mod_spectro, flx_mod_photo, ck = calc_ck(flx_obs_spectro, err_obs_spectro, flx_mod_spectro, + flx_obs_photo, err_obs_photo, flx_mod_photo, r_picked, d_picked) + # Set HiRES contribution to 1 if not used + planet_contribution, stellar_contribution, systematics = 1, 1, 1 # Analytically # If MOSAIC elif global_params.r == "NA" and global_params.d == "NA" and global_params.use_lsqr[indobs] == 'False': - new_flx_merge, new_flx_phot, ck = calc_ck(flx_obs_merge, err_obs_merge, new_flx_merge, - flx_obs_phot, err_obs_phot, new_flx_phot, 0, 0, 0, + flx_mod_spectro, flx_mod_photo, ck = calc_ck(flx_obs_spectro, err_obs_spectro, flx_mod_spectro, + flx_obs_photo, err_obs_photo, flx_mod_photo, 0, 0, 0, analytic='yes') - planet_contribution, stellar_contribution = 1, 1 + planet_contribution, stellar_contribution, systematics = 1, 1, 1 elif global_params.r == "NA" and global_params.d == "NA" and global_params.use_lsqr[indobs] == 'True': # global_params.use_lsqr = 'True', so no need to re-normalize the interpolated sythetic spectrum because the least squares automatically does it - _, new_flx_phot, ck = calc_ck(flx_obs_merge, err_obs_merge, np.copy(new_flx_merge), - flx_obs_phot, err_obs_phot, new_flx_phot, 0, 0, 0, + _, flx_mod_photo, ck = calc_ck(flx_obs_spectro, err_obs_spectro, np.copy(flx_mod_spectro), + flx_obs_photo, err_obs_photo, flx_mod_photo, 0, 0, 0, analytic='yes') - planet_contribution, stellar_contribution, new_flx_merge, flx_obs_merge, star_flx_obs_merge = lsq_fct(flx_obs_merge, err_obs_merge, star_flx_obs_merge, transm_obs_merge, new_flx_merge) + planet_contribution, stellar_contribution, flx_mod_spectro, flx_obs_spectro, star_flx_obs, systematics = lsq_fct(flx_obs_spectro, err_obs_spectro, star_flx_obs, transm_obs, flx_mod_spectro, system_obs) else: # either global_params.r or global_params.d is set to 'NA' print('WARNING: You need to define a radius AND a distance, or set them both to "NA"') exit() - return wav_obs_merge, flx_obs_merge, err_obs_merge, new_flx_merge, wav_obs_phot, flx_obs_phot, err_obs_phot, new_flx_phot, ck, planet_contribution, stellar_contribution, star_flx_obs_merge + return wav_obs_spectro, flx_obs_spectro, err_obs_spectro, flx_mod_spectro, wav_obs_photo, flx_obs_photo, err_obs_photo, flx_mod_photo, ck, planet_contribution, stellar_contribution, star_flx_obs, systematics, transm_obs diff --git a/build/lib/ForMoSA/nested_sampling/nested_prior_function.py b/build/lib/ForMoSA/nested_sampling/nested_prior_function.py index d782458..a107ff3 100644 --- a/build/lib/ForMoSA/nested_sampling/nested_prior_function.py +++ b/build/lib/ForMoSA/nested_sampling/nested_prior_function.py @@ -3,14 +3,15 @@ def uniform_prior(prior_fct_arg, theta): ''' - Uniform prior for nested sampling + Uniform prior for nested sampling. Args: prior_fct_arg (list): Two-values list with uniform prior boundaries. theta (list): Parameter values randomly picked by the nested sampling - Returns: - Evaluated (float): Evaluated prior + - Evaluated (float): Evaluated prior + + Author: Simon Petrus ''' arg1 = float(prior_fct_arg[0]) arg2 = float(prior_fct_arg[1]) @@ -19,13 +20,15 @@ def uniform_prior(prior_fct_arg, theta): def gaussian_prior(prior_fct_arg, theta): ''' - Gaussian prior for nested sampling + Gaussian prior for nested sampling. Args: prior_fct_arg (list): Two-values list with uniform prior boundaries. theta (list): Parameter values randomly picked by the nested sampling Returns: - Evaluated (float): Evaluated prior + - Evaluated (float): Evaluated prior + + Author: Simon Petrus ''' arg1 = float(prior_fct_arg[0]) arg2 = float(prior_fct_arg[1]) diff --git a/build/lib/ForMoSA/nested_sampling/nested_sampling.py b/build/lib/ForMoSA/nested_sampling/nested_sampling.py index 4e5702e..b2c1232 100644 --- a/build/lib/ForMoSA/nested_sampling/nested_sampling.py +++ b/build/lib/ForMoSA/nested_sampling/nested_sampling.py @@ -1,18 +1,17 @@ import numpy as np -import os +import os, sys import glob import nestle import time import xarray as xr import pickle +sys.path.insert(0, os.path.abspath('../')) + from nested_sampling.nested_modif_spec import modif_spec from nested_sampling.nested_prior_function import uniform_prior, gaussian_prior from nested_sampling.nested_logL_functions import * from main_utilities import diag_mat -import matplotlib.pyplot as plt - -c = 299792.458 # Speed of light in km/s def import_obsmod(global_params): @@ -23,8 +22,8 @@ def import_obsmod(global_params): global_params (object): Class containing every input from the .ini file. Returns: - main_file (list(array)): return a list of lists with the wavelengths, flux, errors, covariance matrix, - transmission, star flux and the grids for both spectroscopic and photometric data. + - main_file (list(array)): Return a list of lists with the wavelengths, flux, errors, covariance matrix, + transmission, star flux, systematics and the grids for both spectroscopic and photometric data. Authors: Simon Petrus, Matthieu Ravet and Allan Denis """ @@ -38,34 +37,36 @@ def import_obsmod(global_params): obs_name = os.path.splitext(os.path.basename(global_params.observation_path))[0] spectrum_obs = np.load(os.path.join(global_params.result_path, f'spectrum_obs_{obs_name}.npz'), allow_pickle=True) - wav_obs_merge = np.asarray(spectrum_obs['obs_spectro_merge'][0], dtype=float) - flx_obs_merge = np.asarray(spectrum_obs['obs_spectro_merge'][1], dtype=float) - err_obs_merge = np.asarray(spectrum_obs['obs_spectro_merge'][2], dtype=float) + wav_obs_spectro = np.asarray(spectrum_obs['obs_spectro_merge'][0], dtype=float) + flx_obs_spectro = np.asarray(spectrum_obs['obs_spectro_merge'][1], dtype=float) + err_obs_spectro = np.asarray(spectrum_obs['obs_spectro_merge'][2], dtype=float) # Optional arrays - inv_cov_obs_merge = np.asarray(spectrum_obs['obs_opt_merge'][0], dtype=float) - transm_obs_merge = np.asarray(spectrum_obs['obs_opt_merge'][1], dtype=float) - star_flx_obs_merge = np.asarray(spectrum_obs['obs_opt_merge'][2], dtype=float) + inv_cov_obs = np.asarray(spectrum_obs['obs_opt_merge'][0], dtype=float) + transm_obs = np.asarray(spectrum_obs['obs_opt_merge'][1], dtype=float) + star_flx_obs = np.asarray(spectrum_obs['obs_opt_merge'][2], dtype=float) + system_obs = np.asarray(spectrum_obs['obs_opt_merge'][3], dtype=float) if 'obs_photo' in spectrum_obs.keys(): - wav_obs_phot = np.asarray(spectrum_obs['obs_photo'][0], dtype=float) - flx_obs_phot = np.asarray(spectrum_obs['obs_photo'][1], dtype=float) - err_obs_phot = np.asarray(spectrum_obs['obs_photo'][2], dtype=float) + wav_obs_photo = np.asarray(spectrum_obs['obs_photo'][0], dtype=float) + flx_obs_photo = np.asarray(spectrum_obs['obs_photo'][1], dtype=float) + err_obs_photo = np.asarray(spectrum_obs['obs_photo'][2], dtype=float) else: - wav_obs_phot = np.asarray([], dtype=float) - flx_obs_phot = np.asarray([], dtype=float) - err_obs_phot = np.asarray([], dtype=float) + wav_obs_photo = np.asarray([], dtype=float) + flx_obs_photo = np.asarray([], dtype=float) + err_obs_photo = np.asarray([], dtype=float) # Recovery of the spectroscopy and photometry model - path_grid_m = os.path.join(global_params.adapt_store_path, f'adapted_grid_spectro_{global_params.grid_name}_{obs_name}_nonan.nc') - path_grid_p = os.path.join(global_params.adapt_store_path, f'adapted_grid_photo_{global_params.grid_name}_{obs_name}_nonan.nc') - ds = xr.open_dataset(path_grid_m, decode_cf=False, engine='netcdf4') - grid_merge = ds['grid'] + path_grid_spectro = os.path.join(global_params.adapt_store_path, f'adapted_grid_spectro_{global_params.grid_name}_{obs_name}_nonan.nc') + path_grid_photo = os.path.join(global_params.adapt_store_path, f'adapted_grid_photo_{global_params.grid_name}_{obs_name}_nonan.nc') + ds = xr.open_dataset(path_grid_spectro, decode_cf=False, engine='netcdf4') + grid_spectro = ds['grid'] ds.close() - ds = xr.open_dataset(path_grid_p, decode_cf=False, engine='netcdf4') - grid_phot = ds['grid'] + ds = xr.open_dataset(path_grid_photo, decode_cf=False, engine='netcdf4') + grid_photo = ds['grid'] ds.close() + - main_file.append([[wav_obs_merge, wav_obs_phot], [flx_obs_merge, flx_obs_phot], [err_obs_merge, err_obs_phot], inv_cov_obs_merge, transm_obs_merge, star_flx_obs_merge, grid_merge, grid_phot]) + main_file.append([[wav_obs_spectro, wav_obs_photo], [flx_obs_spectro, flx_obs_photo], [err_obs_spectro, err_obs_photo], inv_cov_obs, transm_obs, star_flx_obs, system_obs, grid_spectro, grid_photo]) return main_file @@ -74,6 +75,7 @@ def loglike(theta, theta_index, global_params, main_file, for_plot='no'): """ Function that calculates the logarithm of the likelihood. The evaluation depends on the choice of likelihood. + (If this function is used on the plotting module, it returns the outputs of the modif_spec function) Args: theta (list): Parameter values randomly picked by the nested sampling @@ -83,8 +85,7 @@ def loglike(theta, theta_index, global_params, main_file, for_plot='no'): for_plot (str): Default is 'no'. When this function is called from the plotting functions module, we use 'yes' Returns: - FINAL_logL (float): Final evaluated loglikelihood for both spectra and photometry. - (If this function is used on the plotting module, it returns the outputs of the modif_spec function) + - FINAL_logL (float): Final evaluated loglikelihood for both spectra and photometry. Authors: Simon Petrus, Matthieu Ravet and Allan Denis """ @@ -97,157 +98,171 @@ def loglike(theta, theta_index, global_params, main_file, for_plot='no'): for indobs, obs in enumerate(sorted(glob.glob(main_obs_path))): # Recovery of spectroscopy and photometry data - wav_obs_merge = main_file[indobs][0][0] - wav_obs_phot = main_file[indobs][0][1] - flx_obs_merge = main_file[indobs][1][0] - flx_obs_phot = main_file[indobs][1][1] - err_obs_merge = main_file[indobs][2][0] - err_obs_phot = main_file[indobs][2][1] - inv_cov_obs_merge = main_file[indobs][3] - transm_obs_merge = main_file[indobs][4] - star_flx_obs_merge = main_file[indobs][5] - + wav_obs_spectro = main_file[indobs][0][0] + wav_obs_photo = main_file[indobs][0][1] + flx_obs_spectro = main_file[indobs][1][0] + flx_obs_photo = main_file[indobs][1][1] + err_obs_spectro = main_file[indobs][2][0] + err_obs_photo = main_file[indobs][2][1] + inv_cov_obs = main_file[indobs][3] + transm_obs = main_file[indobs][4] + star_flx_obs = main_file[indobs][5] + system_obs = main_file[indobs][6] + + # Recovery of the spectroscopy and photometry model - grid_merge = main_file[indobs][6] - grid_phot = main_file[indobs][7] + grid_spectro = main_file[indobs][7] + grid_photo = main_file[indobs][8] # Calculation of the likelihood for each sub-spectrum defined by the parameter 'wav_fit' for ns_u_ind, ns_u in enumerate(global_params.wav_fit[indobs].split('/')): min_ns_u = float(ns_u.split(',')[0]) max_ns_u = float(ns_u.split(',')[1]) - ind_grid_merge_sel = np.where((grid_merge['wavelength'] >= min_ns_u) & (grid_merge['wavelength'] <= max_ns_u)) - ind_grid_phot_sel = np.where((grid_phot['wavelength'] >= min_ns_u) & (grid_phot['wavelength'] <= max_ns_u)) + ind_grid_spectro_sel = np.where((grid_spectro['wavelength'] >= min_ns_u) & (grid_spectro['wavelength'] <= max_ns_u)) + ind_grid_photo_sel = np.where((grid_photo['wavelength'] >= min_ns_u) & (grid_photo['wavelength'] <= max_ns_u)) # Cutting of the grid on the wavelength grid defined by the parameter 'wav_fit' - grid_merge_cut = grid_merge.sel(wavelength=grid_merge['wavelength'][ind_grid_merge_sel]) - grid_phot_cut = grid_phot.sel(wavelength=grid_phot['wavelength'][ind_grid_phot_sel]) + grid_spectro_cut = grid_spectro.sel(wavelength=grid_spectro['wavelength'][ind_grid_spectro_sel]) + grid_photo_cut = grid_photo.sel(wavelength=grid_photo['wavelength'][ind_grid_photo_sel]) # Interpolation of the grid at the theta parameters set if global_params.par3 == 'NA': - if len(grid_merge_cut['wavelength']) != 0: - flx_mod_merge_cut = np.asarray(grid_merge_cut.interp(par1=theta[0], par2=theta[1], + if len(grid_spectro_cut['wavelength']) != 0: + flx_mod_spectro_cut = np.asarray(grid_spectro_cut.interp(par1=theta[0], par2=theta[1], method="linear", kwargs={"fill_value": "extrapolate"})) else: - flx_mod_merge_cut = np.asarray([]) - if len(grid_phot_cut['wavelength']) != 0: - flx_mod_phot_cut = np.asarray(grid_phot_cut.interp(par1=theta[0], par2=theta[1], + flx_mod_spectro_cut = np.asarray([]) + if len(grid_photo_cut['wavelength']) != 0: + flx_mod_photo_cut = np.asarray(grid_photo_cut.interp(par1=theta[0], par2=theta[1], method="linear", kwargs={"fill_value": "extrapolate"})) else: - flx_mod_phot_cut = np.asarray([]) + flx_mod_photo_cut = np.asarray([]) elif global_params.par4 == 'NA': - if len(grid_merge_cut['wavelength']) != 0: - flx_mod_merge_cut = np.asarray(grid_merge_cut.interp(par1=theta[0], par2=theta[1], par3=theta[2], + if len(grid_spectro_cut['wavelength']) != 0: + flx_mod_spectro_cut = np.asarray(grid_spectro_cut.interp(par1=theta[0], par2=theta[1], par3=theta[2], method="linear", kwargs={"fill_value": "extrapolate"})) else: - flx_mod_merge_cut = np.asarray([]) - if len(grid_phot_cut['wavelength']) != 0: - flx_mod_phot_cut = np.asarray(grid_phot_cut.interp(par1=theta[0], par2=theta[1], par3=theta[2], + flx_mod_spectro_cut = np.asarray([]) + if len(grid_photo_cut['wavelength']) != 0: + flx_mod_photo_cut = np.asarray(grid_photo_cut.interp(par1=theta[0], par2=theta[1], par3=theta[2], method="linear", kwargs={"fill_value": "extrapolate"})) else: - flx_mod_phot_cut = np.asarray([]) + flx_mod_photo_cut = np.asarray([]) elif global_params.par5 == 'NA': - if len(grid_merge_cut['wavelength']) != 0: - flx_mod_merge_cut = np.asarray(grid_merge_cut.interp(par1=theta[0], par2=theta[1], par3=theta[2], par4=theta[3], + if len(grid_spectro_cut['wavelength']) != 0: + flx_mod_spectro_cut = np.asarray(grid_spectro_cut.interp(par1=theta[0], par2=theta[1], par3=theta[2], par4=theta[3], method="linear", kwargs={"fill_value": "extrapolate"})) else: - flx_mod_merge_cut = np.asarray([]) - if len(grid_phot_cut['wavelength']) != 0: - flx_mod_phot_cut = np.asarray(grid_phot_cut.interp(par1=theta[0], par2=theta[1], par3=theta[2], par4=theta[3], + flx_mod_spectro_cut = np.asarray([]) + if len(grid_photo_cut['wavelength']) != 0: + flx_mod_photo_cut = np.asarray(grid_photo_cut.interp(par1=theta[0], par2=theta[1], par3=theta[2], par4=theta[3], method="linear", kwargs={"fill_value": "extrapolate"})) else: - flx_mod_phot_cut = np.asarray([]) + flx_mod_photo_cut = np.asarray([]) else: - if len(grid_merge_cut['wavelength']) != 0: - flx_mod_merge_cut = np.asarray(grid_merge_cut.interp(par1=theta[0], par2=theta[1], par3=theta[2], par4=theta[3], + if len(grid_spectro_cut['wavelength']) != 0: + flx_mod_spectro_cut = np.asarray(grid_spectro_cut.interp(par1=theta[0], par2=theta[1], par3=theta[2], par4=theta[3], par5=theta[4], method="linear", kwargs={"fill_value": "extrapolate"})) else: - flx_mod_merge_cut = np.asarray([]) - if len(grid_phot_cut['wavelength']) != 0: - flx_mod_phot_cut = np.asarray(grid_phot_cut.interp(par1=theta[0], par2=theta[1], par3=theta[2], par4=theta[3], + flx_mod_spectro_cut = np.asarray([]) + if len(grid_photo_cut['wavelength']) != 0: + flx_mod_photo_cut = np.asarray(grid_photo_cut.interp(par1=theta[0], par2=theta[1], par3=theta[2], par4=theta[3], par5=theta[4], method="linear", kwargs={"fill_value": "extrapolate"})) else: - flx_mod_phot_cut = np.asarray([]) + flx_mod_photo_cut = np.asarray([]) # Re-merging of the data and interpolated synthetic spectrum to a wavelength grid defined by the parameter 'wav_fit' - ind_merge = np.where((wav_obs_merge >= min_ns_u) & (wav_obs_merge <= max_ns_u)) - ind_phot = np.where((wav_obs_phot >= min_ns_u) & (wav_obs_phot <= max_ns_u)) + ind_spectro = np.where((wav_obs_spectro >= min_ns_u) & (wav_obs_spectro <= max_ns_u)) + ind_photo = np.where((wav_obs_photo >= min_ns_u) & (wav_obs_photo <= max_ns_u)) if ns_u_ind == 0: - wav_obs_merge_ns_u = wav_obs_merge[ind_merge] - flx_obs_merge_ns_u = flx_obs_merge[ind_merge] - err_obs_merge_ns_u = err_obs_merge[ind_merge] - flx_mod_merge_ns_u = flx_mod_merge_cut - if len(inv_cov_obs_merge) != 0: # Add covariance in the loop (if necessary) - inv_cov_obs_merge_ns_u = inv_cov_obs_merge[np.ix_(ind_merge[0],ind_merge[0])] + wav_obs_spectro_ns_u = wav_obs_spectro[ind_spectro] + flx_obs_spectro_ns_u = flx_obs_spectro[ind_spectro] + err_obs_spectro_ns_u = err_obs_spectro[ind_spectro] + flx_mod_spectro_ns_u = flx_mod_spectro_cut + if len(inv_cov_obs) != 0: # Add covariance in the loop (if necessary) + inv_cov_obs_ns_u = inv_cov_obs[np.ix_(ind_spectro[0],ind_spectro[0])] + else: + inv_cov_obs_ns_u = np.asarray([]) + if len(transm_obs) != 0: # Add the transmission (if necessary) + transm_obs_ns_u = transm_obs[ind_spectro] else: - inv_cov_obs_merge_ns_u = np.asarray([]) - if len(transm_obs_merge) != 0: # Add the transmission (if necessary) - transm_obs_merge_ns_u = transm_obs_merge[ind_merge] + transm_obs_ns_u = np.asarray([]) + if len(star_flx_obs) != 0: # Add star flux (if necessary) + star_flx_obs_ns_u = star_flx_obs[0,ind_spectro] else: - transm_obs_merge_ns_u = np.asarray([]) - if len(star_flx_obs_merge) != 0: # Add star flux (if necessary) - star_flx_obs_merge_ns_u = star_flx_obs_merge[ind_merge] + star_flx_obs_ns_u = np.asarray([]) + if len(system_obs) != 0: # Add systematics model (if necessary) + system_obs_ns_u = system_obs[0,ind_spectro] else: - star_flx_obs_merge_ns_u = np.asarray([]) - wav_obs_phot_ns_u = wav_obs_phot[ind_phot] - flx_obs_phot_ns_u = flx_obs_phot[ind_phot] - err_obs_phot_ns_u = err_obs_phot[ind_phot] - flx_mod_phot_ns_u = flx_mod_phot_cut + system_obs_ns_u = np.asarray([]) + wav_obs_photo_ns_u = wav_obs_photo[ind_photo] + flx_obs_photo_ns_u = flx_obs_photo[ind_photo] + err_obs_photo_ns_u = err_obs_photo[ind_photo] + flx_mod_photo_ns_u = flx_mod_photo_cut else: - wav_obs_merge_ns_u = np.concatenate((wav_obs_merge_ns_u, wav_obs_merge[ind_merge])) - flx_obs_merge_ns_u = np.concatenate((flx_obs_merge_ns_u, flx_obs_merge[ind_merge])) - err_obs_merge_ns_u = np.concatenate((err_obs_merge_ns_u, err_obs_merge[ind_merge])) - flx_mod_merge_ns_u = np.concatenate((flx_mod_merge_ns_u, flx_mod_merge_cut)) - if len(inv_cov_obs_merge_ns_u) != 0: # Merge the covariance matrices (if necessary) - inv_cov_obs_merge_ns_u = diag_mat([inv_cov_obs_merge_ns_u, inv_cov_obs_merge[np.ix_(ind_merge[0],ind_merge[0])]]) - if len(transm_obs_merge_ns_u) != 0: # Merge the transmissions (if necessary) - transm_obs_merge_ns_u = np.concatenate((transm_obs_merge_ns_u, transm_obs_merge[ind_merge])) - if len(star_flx_obs_merge_ns_u) != 0: # Merge star fluxes (if necessary) - star_flx_obs_merge_ns_u = np.concatenate((star_flx_obs_merge_ns_u, star_flx_obs_merge[ind_grid_merge_sel])) - wav_obs_phot_ns_u = np.concatenate((wav_obs_phot_ns_u, wav_obs_phot[ind_phot])) - flx_obs_phot_ns_u = np.concatenate((flx_obs_phot_ns_u, flx_obs_phot[ind_phot])) - err_obs_phot_ns_u = np.concatenate((err_obs_phot_ns_u, err_obs_phot[ind_phot])) - flx_mod_phot_ns_u = np.concatenate((flx_mod_phot_ns_u, flx_mod_phot_cut)) + wav_obs_spectro_ns_u = np.concatenate((wav_obs_spectro_ns_u, wav_obs_spectro[ind_spectro])) + flx_obs_spectro_ns_u = np.concatenate((flx_obs_spectro_ns_u, flx_obs_spectro[ind_spectro])) + err_obs_spectro_ns_u = np.concatenate((err_obs_spectro_ns_u, err_obs_spectro[ind_spectro])) + flx_mod_spectro_ns_u = np.concatenate((flx_mod_spectro_ns_u, flx_mod_spectro_cut)) + if len(inv_cov_obs_ns_u) != 0: # Merge the covariance matrices (if necessary) + inv_cov_obs_ns_u = diag_mat([inv_cov_obs_ns_u, inv_cov_obs[np.ix_(ind_spectro[0],ind_spectro[0])]]) + if len(transm_obs_ns_u) != 0: # Merge the transmissions (if necessary) + transm_obs_ns_u = np.concatenate((transm_obs_ns_u, transm_obs[ind_spectro])) + if len(star_flx_obs_ns_u) != 0: # Merge star fluxes (if necessary) + star_flx_obs_ns_u = np.concatenate((star_flx_obs_ns_u, star_flx_obs[0,ind_grid_spectro_sel]),axis=0) + if len(system_obs) != 0: # Merge systematics model (if necessary) + system_obs_ns_u = np.concatenate((system_obs_ns_u, system_obs[0,ind_grid_spectro_sel]), axis=0) + wav_obs_photo_ns_u = np.concatenate((wav_obs_photo_ns_u, wav_obs_photo[ind_photo])) + flx_obs_photo_ns_u = np.concatenate((flx_obs_photo_ns_u, flx_obs_photo[ind_photo])) + err_obs_photo_ns_u = np.concatenate((err_obs_photo_ns_u, err_obs_photo[ind_photo])) + flx_mod_photo_ns_u = np.concatenate((flx_mod_photo_ns_u, flx_mod_photo_cut)) # Modification of the synthetic spectrum with the extra-grid parameters modif_spec_LL = modif_spec(global_params, theta, theta_index, - wav_obs_merge_ns_u, flx_obs_merge_ns_u, err_obs_merge_ns_u, flx_mod_merge_ns_u, - wav_obs_phot_ns_u, flx_obs_phot_ns_u, err_obs_phot_ns_u, flx_mod_phot_ns_u, - transm_obs_merge_ns_u, star_flx_obs_merge_ns_u, indobs=indobs) + wav_obs_spectro_ns_u, flx_obs_spectro_ns_u, err_obs_spectro_ns_u, flx_mod_spectro_ns_u, + wav_obs_photo_ns_u, flx_obs_photo_ns_u, err_obs_photo_ns_u, flx_mod_photo_ns_u, + transm_obs_ns_u, star_flx_obs_ns_u, system_obs_ns_u, indobs=indobs) - flx_obs, flx_obs_phot = modif_spec_LL[1], modif_spec_LL[5] - flx_mod, flx_mod_phot = modif_spec_LL[3], modif_spec_LL[7] - err, err_phot = modif_spec_LL[2], modif_spec_LL[6] - inv_cov = inv_cov_obs_merge_ns_u + flx_obs_spectro_modif, flx_obs_photo_modif = modif_spec_LL[1], modif_spec_LL[5] + flx_mod_spectro_modif, flx_mod_photo_modif = modif_spec_LL[3], modif_spec_LL[7] + err_obs_spectro_modif, err_obs_photo_modif = modif_spec_LL[2], modif_spec_LL[6] + inv_cov_obs_modif = inv_cov_obs_ns_u ck = modif_spec_LL[8] - planet_contribution, stellar_contribution, star_flx_obs_merge = modif_spec_LL[9], modif_spec_LL[10], modif_spec_LL[11] + planet_contribution, stellar_contribution, star_flx_obs, systematics = modif_spec_LL[9], modif_spec_LL[10], modif_spec_LL[11], modif_spec_LL[12] if global_params.use_lsqr[indobs] == 'True': # If our data is contaminated by starlight difraction, the model is the sum of the estimated stellar contribution + planet model - flx_mod = planet_contribution * flx_mod + stellar_contribution * star_flx_obs_merge - + flx_mod_spectro_modif = planet_contribution * flx_mod_spectro_modif + np.dot(stellar_contribution, star_flx_obs[0].T) + if len(systematics) > 0: + flx_mod_spectro_modif += systematics + # Computation of the photometry logL - if len(flx_mod_phot) != 0: - logL_phot = logL_chi2_classic(flx_obs_phot-flx_mod_phot, err_phot) + if len(flx_obs_photo_modif) != 0: + logL_photo = logL_chi2_classic(flx_obs_photo_modif-flx_mod_photo_modif, err_obs_photo_modif) else: - logL_phot = 0 + logL_photo = 0 # Computation of the spectroscopy logL - if len(flx_obs) != 0: + if len(flx_obs_spectro_modif) != 0: if global_params.logL_type[indobs] == 'chi2_classic': - logL_spec = logL_chi2_classic(flx_obs-flx_mod, err) - elif global_params.logL_type[indobs] == 'chi2_covariance' and len(inv_cov) != 0: - logL_spec = logL_chi2_covariance(flx_obs-flx_mod, inv_cov) + logL_spectro = logL_chi2_classic(flx_obs_spectro_modif-flx_mod_spectro_modif, err_obs_spectro_modif) + elif global_params.logL_type[indobs] == 'chi2_covariance' and len(inv_cov_obs_modif) != 0: + logL_spectro = logL_chi2_covariance(flx_obs_spectro_modif-flx_mod_spectro_modif, inv_cov_obs_modif) elif global_params.logL_type[indobs] == 'CCF_Brogi': - logL_spec = logL_CCF_Brogi(flx_obs, flx_mod) + logL_spectro = logL_CCF_Brogi(flx_obs_spectro_modif, flx_mod_spectro_modif) elif global_params.logL_type[indobs] == 'CCF_Zucker': - logL_spec = logL_CCF_Zucker(flx_obs, flx_mod) + logL_spectro = logL_CCF_Zucker(flx_obs_spectro_modif, flx_mod_spectro_modif) elif global_params.logL_type[indobs] == 'CCF_custom': - logL_spec = logL_CCF_custom(flx_obs, flx_mod, err) + logL_spectro = logL_CCF_custom(flx_obs_spectro_modif, flx_mod_spectro_modif, err_obs_spectro_modif) + elif global_params.logL_type[indobs] == 'chi2_extended': + logL_spectro = logL_chi2_extended(flx_obs_spectro_modif-flx_mod_spectro_modif, err_obs_spectro_modif) + elif global_params.logL_type[indobs] == 'chi2_extended_covariance' and len(inv_cov_obs_modif) != 0: + logL_spectro = logL_chi2_extended_covariance(flx_obs_spectro_modif-flx_mod_spectro_modif, inv_cov_obs_modif) else: print() print('WARNING: One or more dataset are not included when performing the inversion.') @@ -255,10 +270,10 @@ def loglike(theta, theta_index, global_params, main_file, for_plot='no'): print() exit() else: - logL_spec = 0 + logL_spectro = 0 # Compute the final logL (sum of all likelihood under the hypothesis of independent instruments) - FINAL_logL = logL_phot + logL_spec + FINAL_logL + FINAL_logL = logL_photo + logL_spectro + FINAL_logL if for_plot == 'no': return FINAL_logL @@ -278,9 +293,9 @@ def prior_transform(theta, theta_index, lim_param_grid, global_params): global_params (object): Class containing every input from the .ini file. Returns: - prior (list): List containing all the prior information + - prior (list): List containing all the prior information - Author: Simon Petrus + Author: Simon Petrus, Matthieu Ravet, Allan Denis """ prior = [] if global_params.par1 != 'NA': @@ -412,6 +427,50 @@ def prior_transform(theta, theta_index, lim_param_grid, global_params): if prior_law == 'gaussian': prior_rv = gaussian_prior([float(global_params.rv[1]), float(global_params.rv[2])], theta[ind_theta_rv[0][0]]) prior.append(prior_rv) + if len(global_params.vsini) > 4: # If you want separate vsini for each observations + main_obs_path = global_params.main_observation_path + for indobs, obs in enumerate(sorted(glob.glob(main_obs_path))): + if global_params.vsini[indobs*4] != 'NA': + prior_law = global_params.vsini[indobs*4] # Prior laws should be separeted by 2 values (need to be upgraded) + if prior_law != 'constant': + ind_theta_vsini = np.where(theta_index == f'vsini_{indobs}') + if prior_law == 'uniform': + prior_vsini = uniform_prior([float(global_params.vsini[indobs*4+1]), float(global_params.vsini[indobs*4+2])], theta[ind_theta_vsini[0][0]]) # Prior values should be by two + if prior_law == 'gaussian': + prior_vsini = gaussian_prior([float(global_params.vsini[indobs*4+1]), float(global_params.vsini[indobs*4+2])], theta[ind_theta_vsini[0][0]]) + prior.append(prior_vsini) + else: # If you want 1 common vsini for all observations + if global_params.vsini != 'NA': + prior_law = global_params.vsini[0] + if prior_law != 'constant': + ind_theta_vsini = np.where(theta_index == 'vsini') + if prior_law == 'uniform': + prior_vsini = uniform_prior([float(global_params.vsini[1]), float(global_params.vsini[2])], theta[ind_theta_vsini[0][0]]) + if prior_law == 'gaussian': + prior_vsini = gaussian_prior([float(global_params.vsini[1]), float(global_params.vsini[2])], theta[ind_theta_vsini[0][0]]) + prior.append(prior_vsini) + if len(global_params.ld) > 3: # If you want separate ld for each observations + main_obs_path = global_params.main_observation_path + for indobs, obs in enumerate(sorted(glob.glob(main_obs_path))): + if global_params.ld[indobs*3] != 'NA': + prior_law = global_params.ld[indobs*3] # Prior laws should be separeted by 2 values (need to be upgraded) + if prior_law != 'constant': + ind_theta_ld = np.where(theta_index == f'ld_{indobs}') + if prior_law == 'uniform': + prior_ld = uniform_prior([float(global_params.ld[indobs*3+1]), float(global_params.ld[indobs*3+2])], theta[ind_theta_ld[0][0]]) # Prior values should be by two + if prior_law == 'gaussian': + prior_ld = gaussian_prior([float(global_params.ld[indobs*3+1]), float(global_params.ld[indobs*3+2])], theta[ind_theta_ld[0][0]]) + prior.append(prior_ld) + else: # If you want 1 common ld for all observations + if global_params.ld != 'NA': + prior_law = global_params.ld[0] + if prior_law != 'constant': + ind_theta_ld = np.where(theta_index == 'ld') + if prior_law == 'uniform': + prior_ld = uniform_prior([float(global_params.ld[1]), float(global_params.ld[2])], theta[ind_theta_ld[0][0]]) + if prior_law == 'gaussian': + prior_ld = gaussian_prior([float(global_params.ld[1]), float(global_params.ld[2])], theta[ind_theta_ld[0][0]]) + prior.append(prior_ld) # - - - - - - - - - - - - - - - - - - - - - @@ -424,24 +483,6 @@ def prior_transform(theta, theta_index, lim_param_grid, global_params): if prior_law == 'gaussian': prior_av = gaussian_prior([float(global_params.av[1]), float(global_params.av[2])], theta[ind_theta_av[0][0]]) prior.append(prior_av) - if global_params.vsini != 'NA': - prior_law = global_params.vsini[0] - if prior_law != 'constant': - ind_theta_vsini = np.where(theta_index == 'vsini') - if prior_law == 'uniform': - prior_vsini = uniform_prior([float(global_params.vsini[1]), float(global_params.vsini[2])], theta[ind_theta_vsini[0][0]]) - if prior_law == 'gaussian': - prior_vsini = gaussian_prior([float(global_params.vsini[1]), float(global_params.vsini[2])], theta[ind_theta_vsini[0][0]]) - prior.append(prior_vsini) - if global_params.ld != 'NA': - prior_law = global_params.ld[0] - if prior_law != 'constant': - ind_theta_ld = np.where(theta_index == 'ld') - if prior_law == 'uniform': - prior_ld = uniform_prior([float(global_params.ld[1]), float(global_params.ld[2])], theta[ind_theta_ld[0][0]]) - if prior_law == 'gaussian': - prior_ld = gaussian_prior([float(global_params.ld[1]), float(global_params.ld[2])], theta[ind_theta_ld[0][0]]) - prior.append(prior_ld) ## adding the CPD params, bb_T and bb_R if global_params.bb_T != 'NA': prior_law = global_params.bb_T[0] @@ -564,18 +605,32 @@ def launch_nested_sampling(global_params): if global_params.rv != 'NA' and global_params.rv[0] != 'constant': n_free_parameters += 1 theta_index.append(f'rv') + if len(global_params.vsini) > 4: + main_obs_path = global_params.main_observation_path + for indobs, obs in enumerate(sorted(glob.glob(main_obs_path))): + if global_params.vsini[indobs*4] != 'NA' and global_params.vsini[indobs*4] != 'constant': # Check if the idobs is different from constant + n_free_parameters += 1 + theta_index.append(f'vsini_{indobs}') + else: + if global_params.vsini != 'NA' and global_params.vsini[0] != 'constant': + n_free_parameters += 1 + theta_index.append('vsini') + if len(global_params.ld) > 3: + main_obs_path = global_params.main_observation_path + for indobs, obs in enumerate(sorted(glob.glob(main_obs_path))): + if global_params.ld[indobs*3] != 'NA' and global_params.ld[indobs*3] != 'constant': # Check if the idobs is different from constant + n_free_parameters += 1 + theta_index.append(f'ld_{indobs}') + else: + if global_params.ld != 'NA' and global_params.ld[0] != 'constant': + n_free_parameters += 1 + theta_index.append('ld') # - - - - - - - - - - - - - - - - - - - - - if global_params.av != 'NA' and global_params.av[0] != 'constant': n_free_parameters += 1 theta_index.append('av') - if global_params.vsini != 'NA' and global_params.vsini[0] != 'constant': - n_free_parameters += 1 - theta_index.append('vsini') - if global_params.ld != 'NA' and global_params.ld[0] != 'constant': - n_free_parameters += 1 - theta_index.append('ld') ## adding cpd if global_params.bb_T != 'NA' and global_params.bb_T[0] != 'constant': n_free_parameters += 1 @@ -689,46 +744,46 @@ def launch_nested_sampling(global_params): print('%15s : %.3f +- %.3f' % (name, col.mean(), col.std())) print('\n') - if global_params.ns_algo == 'ultranest': - import ultranest, ultranest.stepsampler + # if global_params.ns_algo == 'ultranest': + # import ultranest, ultranest.stepsampler - tmpstot1 = time.time() + # tmpstot1 = time.time() - loglike_gp = lambda theta: loglike(theta, theta_index, global_params) - - prior_transform_gp = lambda theta: prior_transform(theta, theta_index, lim_param_grid, global_params) - - sampler = ultranest.ReactiveNestedSampler(theta_index,loglike=loglike_gp, transform=prior_transform_gp, - wrapped_params=[False, False, False, False])#, - #log_dir=global_params.result_path, resume=True) - #result = sampler.run(min_num_live_points=100, max_ncalls=100000) - - # have to choose the number of steps the slice sampler should take - # after first results, this should be increased and checked for consistency. - nsteps = 2 * len(theta_index) - # create step sampler: - sampler.stepsampler = ultranest.stepsampler.SliceSampler(nsteps=nsteps, - generate_direction=ultranest.stepsampler.generate_mixture_random_direction, - # adaptive_nsteps=False, - # max_nsteps=40 - ) - sampler.print_results() - #sampler.plot_corner() - - tmpstot2 = time.time()-tmpstot1 - print(' ') - print('- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -') - print('-> Ultranest ') - print(' ') - print('The code spent ' + str(tmpstot2) + ' sec to run.') - print(result.summary()) - print('\n') + # loglike_gp = lambda theta: loglike(theta, theta_index, global_params) + + # prior_transform_gp = lambda theta: prior_transform(theta, theta_index, lim_param_grid, global_params) + + # sampler = ultranest.ReactiveNestedSampler(theta_index,loglike=loglike_gp, transform=prior_transform_gp, + # wrapped_params=[False, False, False, False])#, + # #log_dir=global_params.result_path, resume=True) + # #result = sampler.run(min_num_live_points=100, max_ncalls=100000) + + # # have to choose the number of steps the slice sampler should take + # # after first results, this should be increased and checked for consistency. + # nsteps = 2 * len(theta_index) + # # create step sampler: + # sampler.stepsampler = ultranest.stepsampler.SliceSampler(nsteps=nsteps, + # generate_direction=ultranest.stepsampler.generate_mixture_random_direction, + # # adaptive_nsteps=False, + # # max_nsteps=40 + # ) + # sampler.print_results() + # #sampler.plot_corner() + + # tmpstot2 = time.time()-tmpstot1 + # print(' ') + # print('- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -') + # print('-> Ultranest ') + # print(' ') + # print('The code spent ' + str(tmpstot2) + ' sec to run.') + # print(result.summary()) + # print('\n') - if global_params.ns_algo == 'dynesty': - from dynesty import NestedSampler + # if global_params.ns_algo == 'dynesty': + # from dynesty import NestedSampler - # initialize our nested sampler - #sampler = NestedSampler(loglike, ptform, ndim) + # initialize our nested sampler + # sampler = NestedSampler(loglike, ptform, ndim) result_reformat = {"samples": samples, "weights": weights, diff --git a/build/lib/ForMoSA/plotting/plotting_class.py b/build/lib/ForMoSA/plotting/plotting_class.py index 23259fe..19248d9 100644 --- a/build/lib/ForMoSA/plotting/plotting_class.py +++ b/build/lib/ForMoSA/plotting/plotting_class.py @@ -1,38 +1,79 @@ from __future__ import print_function, division -import sys, os, yaml, time +import os, glob, sys import numpy as np import matplotlib.pyplot as plt -import matplotlib -from matplotlib.figure import Figure -import astropy.constants as const -import astropy.units as u +from matplotlib.backends.backend_pdf import PdfPages +from scipy.interpolate import interp1d import corner import xarray as xr import pickle -from scipy.interpolate import interp1d -import extinction -from PyAstronomy.pyasl import dopplerShift, rotBroad -from spectres import spectres from tqdm import tqdm -import glob + +sys.path.insert(0, os.path.abspath('../')) # Import ForMoSA from main_utilities import GlobFile from nested_sampling.nested_modif_spec import modif_spec -from adapt.extraction_functions import resolution_decreasing,adapt_model, decoupe +from nested_sampling.nested_modif_spec import doppler_fct +from nested_sampling.nested_modif_spec import lsq_fct +from nested_sampling.nested_modif_spec import vsini_fct_accurate +from adapt.extraction_functions import resolution_decreasing, adapt_model, decoupe +from adapt.extraction_functions import adapt_observation_range + + + + +def bin_data(wave, data, bin_size): + ''' + Function to bin data given a bin size + + Args: + wave (array): wavelength of the data + data (array): data + bin_size (int): size of the bin to apply + Returns: + - wave_binned (array): binned wavelength + - data_binned (array): binned data + + Author: Allan Denis + ''' + # First quick check that len of data is a multpiple of bin_size + while(len(data)%bin_size != 0): + wave, data = wave[:-1], data[:-1] + + bins = np.arange(0, len(wave), bin_size) + wave_binned = np.add.reduceat(wave, bins) / bin_size + data_binned = np.add.reduceat(data, bins) + + return wave_binned, data_binned + + # ---------------------------------------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------------------------- class ComplexRadar(): ''' - Original from Damian Cummins: https://github.com/DamianCummins/statsbomb-football-event-visualisations/blob/master/Statsbomb%20Womens%20World%20Cup%202019%20visualisation.ipynb - - Adapted by: P. Palma-Bifani + Class to create Radar plots with asymmetric error bars. + + Author: Paulina Palma-Bifani + Adapted from Damian Cummins: https://github.com/DamianCummins/statsbomb-football-event-visualisations/blob/master/Statsbomb%20Womens%20World%20Cup%202019%20visualisation.ipynb + ''' def __init__(self, fig, variables, ranges, n_ordinate_levels=6): + ''' + Initialize class. + + Args: + fig (object): matplotlib figure object + variables (list): list of parameters to plot + ranges (list(tuple)): upper and lower limits for each parameters + n_ordinate_levels (int): (default = 6) number of gridlines in the plot + Returns: + None + ''' angles = np.arange(0, 360, 360./len(variables)) axes = [fig.add_axes([0.1,0.1,0.9,0.9], polar=True, label = "axes{}".format(i)) for i in range(len(variables))] @@ -63,20 +104,61 @@ def __init__(self, fig, variables, ranges, n_ordinate_levels=6): self.ax = axes[0] def plot(self, data, *args, **kw): + ''' + Function to display the plot. + + Args: + data (list): best value for each parameter + *args : Variable length argument list. + **kw : Arbitrary keyword arguments. + Returns: + None + ''' sdata = self.scale_data(data, self.ranges) self.ax.plot(self.angle, np.r_[sdata, sdata[0]], *args, **kw) def fill(self, data, *args, **kw): + ''' + Add symmetric error bars to the plot. + + Args: + data (list): best value for each parameter + *args : Variable length argument list. + **kw : Arbitrary keyword arguments. + Returns: + None + ''' sdata = self.scale_data(data, self.ranges) self.ax.fill(self.angle, np.r_[sdata, sdata[0]], *args, **kw) def fill_between(self, list_down, list_up, *args, **kw): + ''' + Add asymmetric error bars to the plot. + + Args: + list_down (list): list of lower error bars + list_up (list): list of upper error bars + *args : Variable length argument list. + **kw : Arbitrary keyword arguments. + Returns: + None + ''' sdata_down = self.scale_data(list_down, self.ranges) sdata_up = self.scale_data(list_up, self.ranges) self.ax.fill_between(self.angle,np.r_[sdata_down,sdata_down[0]], np.r_[sdata_up,sdata_up[0]], *args, **kw) def scale_data(self, data, ranges): - """scales data[1:] to ranges[0]""" + ''' + Function to check that lower and upper limits are correctly ordered. It scales data[1:] to ranges[0] + + Args: + data (list): best value for each parameter + ranges (list(tuple)): upper and lower limits for each parameters + *args : Variable length argument list. + **kw : Arbitrary keyword arguments. + Returns: + None + ''' for d, (y1, y2) in zip(data[1:], ranges[1:]): assert (y1 <= d <= y2) or (y2 <= d <= y1) x1, x2 = ranges[0] @@ -95,46 +177,47 @@ def scale_data(self, data, ranges): # ---------------------------------------------------------------------------------------------------------------------- class PlottingForMoSA(): ''' - Here all the plotting functionalities of ForMoSA to see the + Class containing all the plotting functionalities of ForMoSA. - Author: Paulina Palma-Bifani + Author: Paulina Palma-Bifani, Simon Petrus, Matthieu Ravet and Allan Denis ''' def __init__(self, config_file_path, color_out): ''' - Plotting class initializer + Initialize class by inheriting the global parameter class of ForMoSA. + + Args: + config_file_path (str): path to the config.ini file currently used + color_out (str): color to use for the model + Returns: + None ''' self.global_params = GlobFile(config_file_path) self.color_out = color_out - def _get_posteriors(self): ''' - Function to get the posteriors, including luminosity derivation and corvengence parameters logz + Function to get the posteriors, including luminosity derivation and Bayesian evidence logz. - (Adapted from Simon Petrus plotting functions) + Args: + None + Returns: + None ''' with open(self.global_params.result_path + '/result_' + self.global_params.ns_algo + '.pic', 'rb') as open_pic: result = pickle.load(open_pic) - # self.samples = result.samples self.samples = result['samples'] - # self.weights = result.weights self.weights = result['weights'] # To test the quality of the fit - # self.logl=result.logl self.logl=result['logl'] ind = np.where(self.logl==max(self.logl)) self.theta_best = self.samples[ind][0] - # self.sample_logz = round(result['logz'],1) - # self.sample_logzerr = round(result['logzerr'],1) self.sample_logz = round(result['logz'][0],1) self.sample_logzerr = round(result['logz'][1],1) - # self.sample_h = round(result['h'],1) - # self.outputs_string = 'logz = '+ str(self.sample_logz)+' ± '+str(self.sample_logzerr)+ ' ; h = '+str(self.sample_h) self.outputs_string = 'logz = '+ str(self.sample_logz)+' ± '+str(self.sample_logzerr) ds = xr.open_dataset(self.global_params.model_path, decode_cf=False, engine='netcdf4') @@ -201,18 +284,32 @@ def _get_posteriors(self): if self.global_params.rv != 'NA' and self.global_params.rv != 'constant': tot_list_param_title.append(extra_parameters[3][1] + ' ' + extra_parameters[3][2]) theta_index.append('rv') + if len(self.global_params.vsini) > 4: # If you want separate vsini for each observations + main_obs_path = self.global_params.main_observation_path + for indobs, obs in enumerate(sorted(glob.glob(main_obs_path))): + if self.global_params.vsini[indobs*4] != 'NA' and self.global_params.vsini[indobs*4] != 'constant': # Check if the idobs is different from constant + tot_list_param_title.append(extra_parameters[5][1] + fr'$_{indobs}$' + ' ' + extra_parameters[5][2]) + theta_index.append(f'vsini_{indobs}') + else: # If you want 1 common vsini for all observations + if self.global_params.vsini != 'NA' and self.global_params.vsini != 'constant': + tot_list_param_title.append(extra_parameters[5][1] + ' ' + extra_parameters[5][2]) + theta_index.append('vsini') + if len(self.global_params.ld) > 3: # If you want separate ld for each observations + main_obs_path = self.global_params.main_observation_path + for indobs, obs in enumerate(sorted(glob.glob(main_obs_path))): + if self.global_params.ld[indobs*3] != 'NA' and self.global_params.ld[indobs*3] != 'constant': # Check if the idobs is different from constant + tot_list_param_title.append(extra_parameters[6][1] + fr'$_{indobs}$' + ' ' + extra_parameters[6][2]) + theta_index.append(f'ld_{indobs}') + else: # If you want 1 common vsini for all observations + if self.global_params.ld != 'NA' and self.global_params.ld != 'constant': + tot_list_param_title.append(extra_parameters[6][1] + ' ' + extra_parameters[6][2]) + theta_index.append('ld') # - - - - - - - - - - - - - - - - - - - - - if self.global_params.av != 'NA' and self.global_params.av[0] != 'constant': tot_list_param_title.append(extra_parameters[4][1] + ' ' + extra_parameters[4][2]) theta_index.append('av') - if self.global_params.vsini != 'NA' and self.global_params.vsini[0] != 'constant': - tot_list_param_title.append(extra_parameters[5][1] + ' ' + extra_parameters[5][2]) - theta_index.append('vsini') - if self.global_params.ld != 'NA' and self.global_params.ld[0] != 'constant': - tot_list_param_title.append(extra_parameters[6][1] + ' ' + extra_parameters[6][2]) - theta_index.append('ld') ## cpd bb if self.global_params.bb_T != 'NA' and self.global_params.bb_T[0] != 'constant': tot_list_param_title.append(extra_parameters[7][1] + ' ' + extra_parameters[7][2]) @@ -243,7 +340,15 @@ def _get_posteriors(self): def plot_corner(self, levels_sig=[0.997, 0.95, 0.68], bins=100, quantiles=(0.16, 0.5, 0.84), burn_in=0): ''' - See the corner plots + Function to display the corner plot + + Args: + levels_sig (list): (default = [0.997, 0.95, 0.68]) 1, 2 and 3 sigma contour levels of the corner plot + bins (int): (default = 100) number of bins for the posteriors + quantiles (list): (default = (0.16, 0.5, 0.84)) mean +- sigma to report the posterior values + burn_in (int): (default = 0) number of steps to remove from the plot + Returns: + - fig (object): matplotlib figure object ''' print('ForMoSA - Corner plot') @@ -264,20 +369,27 @@ def plot_corner(self, levels_sig=[0.997, 0.95, 0.68], bins=100, quantiles=(0.16, fill_contours=True, show_titles=True, title_fmt='.2f', - title_kwargs=dict(fontsize=10), + title_kwargs=dict(fontsize=14), contour_kwargs=dict(colors=self.color_out, linewidths=0.7), pcolor_kwargs=dict(color='red'), - label_kwargs=dict(fontsize=10)) + label_kwargs=dict(fontsize=14)) + fig.supxlabel(self.outputs_string, va='top') return fig - def plot_chains(self,figsize=(7,15)): + def plot_chains(self, figsize=(7,15)): ''' - To check the convergence of the chains + Plot to check the convergence of the posterior chains. + Multiple (sub-)axis plot. + Args: + figsize (tuple): (default = (7, 15)) size of the plot + Returns: + - fig (object) : matplotlib figure object + - ax (object) : matplotlib axes objects ''' print('ForMoSA - Posteriors chains for each parameter') @@ -303,12 +415,19 @@ def plot_chains(self,figsize=(7,15)): return fig, axs - def plot_radar(self,ranges,label='',quantiles=[0.16, 0.5, 0.84],chiffres=[0,2,2,2]): + def plot_radar(self, ranges, label='', quantiles=[0.16, 0.5, 0.84]): ''' - To check overall the distribution of the parameters + Radar plot to check the distribution of the parameters. + Useful to compare different models. + + Args: + ranges (list(tuple)): upper and lower limits for each parameters + label (str): (default = '') label of the plot + quantiles (list): (default = (0.16, 0.5, 0.84)) mean +- sigma to report the posterior values + Returns: + - fig (object) : matplotlib figure object + - radar.ax (object) : matplotlib radar class axes object - Inputs: - ranges ''' print('ForMoSA - Radar plot') @@ -324,23 +443,30 @@ def plot_radar(self,ranges,label='',quantiles=[0.16, 0.5, 0.84],chiffres=[0,2,2, list_uncert_down.append(q16) list_uncert_up.append(q84) - fig1 = plt.figure(figsize=(6, 6)) - radar = ComplexRadar(fig1, self.posteriors_names, ranges) + fig = plt.figure(figsize=(6, 6)) + radar = ComplexRadar(fig, self.posteriors_names, ranges) radar.plot(list_posteriors, 'o-', color=self.color_out, label=label) radar.fill_between(list_uncert_down,list_uncert_up, color=self.color_out, alpha=0.2) radar.ax.legend(loc='center', bbox_to_anchor=(0.5, -0.20),frameon=False, ncol=2) - return fig1, radar.ax + return fig, radar.ax def _get_spectra(self,theta): ''' - To get the data and best model asociated - Use numba: https://numba.pydata.org/ + Function to get the data and best model asociated. - (Adapted from Simon Petrus) + Args: + theta (list): best parameter values + Returns: + - modif_spec_chi2 list(n-array): list containing the spectroscopic wavelength, spectroscopic fluxes of the data, + spectroscopic errors of the data, spectroscopic fluxes of the model, + photometric wavelength, photometric fluxes of the data, photometric errors of the data, + spectroscopic fluxes of the model, + planet transmission, star fluxes, systematics + - ck list(floats): list scaling factor(s) ''' # Get the posteriors self._get_posteriors() @@ -355,82 +481,83 @@ def _get_spectra(self,theta): obs_name = os.path.splitext(os.path.basename(self.global_params.observation_path))[0] spectrum_obs = np.load(os.path.join(self.global_params.result_path, f'spectrum_obs_{obs_name}.npz'), allow_pickle=True) - wav_obs_merge = np.asarray(spectrum_obs['obs_spectro_merge'][0], dtype=float) - flx_obs_merge = np.asarray(spectrum_obs['obs_spectro_merge'][1], dtype=float) - err_obs_merge = np.asarray(spectrum_obs['obs_spectro_merge'][2], dtype=float) - transm_obs_merge = np.asarray(spectrum_obs['obs_opt_merge'][1], dtype=float) - star_flx_obs_merge = np.asarray(spectrum_obs['obs_opt_merge'][2], dtype=float) + wav_obs_spectro = np.asarray(spectrum_obs['obs_spectro_merge'][0], dtype=float) + flx_obs_spectro = np.asarray(spectrum_obs['obs_spectro_merge'][1], dtype=float) + err_obs_spectro = np.asarray(spectrum_obs['obs_spectro_merge'][2], dtype=float) + transm_obs = np.asarray(spectrum_obs['obs_opt_merge'][1], dtype=float) + star_flx_obs = np.asarray(spectrum_obs['obs_opt_merge'][2], dtype=float) + system_obs = np.asarray(spectrum_obs['obs_opt_merge'][3], dtype=float) if 'obs_photo' in spectrum_obs.keys(): - wav_obs_phot = np.asarray(spectrum_obs['obs_photo'][0], dtype=float) - flx_obs_phot = np.asarray(spectrum_obs['obs_photo'][1], dtype=float) - err_obs_phot = np.asarray(spectrum_obs['obs_photo'][2], dtype=float) + wav_obs_photo = np.asarray(spectrum_obs['obs_photo'][0], dtype=float) + flx_obs_photo = np.asarray(spectrum_obs['obs_photo'][1], dtype=float) + err_obs_photo = np.asarray(spectrum_obs['obs_photo'][2], dtype=float) else: - wav_obs_phot = np.asarray([], dtype=float) - flx_obs_phot = np.asarray([], dtype=float) - err_obs_phot = np.asarray([], dtype=float) + wav_obs_photo = np.asarray([], dtype=float) + flx_obs_photo = np.asarray([], dtype=float) + err_obs_photo = np.asarray([], dtype=float) # Recovery of the spectroscopy and photometry model - path_grid_m = os.path.join(self.global_params.adapt_store_path, f'adapted_grid_spectro_{self.global_params.grid_name}_{obs_name}_nonan.nc') - path_grid_p = os.path.join(self.global_params.adapt_store_path, f'adapted_grid_photo_{self.global_params.grid_name}_{obs_name}_nonan.nc') - ds = xr.open_dataset(path_grid_m, decode_cf=False, engine='netcdf4') - grid_merge = ds['grid'] + path_grid_spectro = os.path.join(self.global_params.adapt_store_path, f'adapted_grid_spectro_{self.global_params.grid_name}_{obs_name}_nonan.nc') + path_grid_photo = os.path.join(self.global_params.adapt_store_path, f'adapted_grid_photo_{self.global_params.grid_name}_{obs_name}_nonan.nc') + ds = xr.open_dataset(path_grid_spectro, decode_cf=False, engine='netcdf4') + grid_spectro = ds['grid'] ds.close() - ds = xr.open_dataset(path_grid_p, decode_cf=False, engine='netcdf4') - grid_phot = ds['grid'] + ds = xr.open_dataset(path_grid_photo, decode_cf=False, engine='netcdf4') + grid_photo = ds['grid'] ds.close() if self.global_params.par3 == 'NA': - if len(grid_merge['wavelength']) != 0: - flx_mod_merge = np.asarray(grid_merge.interp(par1=theta[0], par2=theta[1], + if len(grid_spectro['wavelength']) != 0: + flx_mod_spectro = np.asarray(grid_spectro.interp(par1=theta[0], par2=theta[1], method="linear", kwargs={"fill_value": "extrapolate"})) else: - flx_mod_merge = np.asarray([]) - if len(grid_phot['wavelength']) != 0: - flx_mod_phot = np.asarray(grid_phot.interp(par1=theta[0], par2=theta[1], + flx_mod_spectro = np.asarray([]) + if len(grid_photo['wavelength']) != 0: + flx_mod_photo = np.asarray(grid_photo.interp(par1=theta[0], par2=theta[1], method="linear", kwargs={"fill_value": "extrapolate"})) else: - flx_mod_phot = np.asarray([]) + flx_mod_photo = np.asarray([]) elif self.global_params.par4 == 'NA': - if len(grid_merge['wavelength']) != 0: - flx_mod_merge = np.asarray(grid_merge.interp(par1=theta[0], par2=theta[1], par3=theta[2], + if len(grid_spectro['wavelength']) != 0: + flx_mod_spectro = np.asarray(grid_spectro.interp(par1=theta[0], par2=theta[1], par3=theta[2], method="linear", kwargs={"fill_value": "extrapolate"})) else: - flx_mod_merge = np.asarray([]) - if len(grid_phot['wavelength']) != 0: - flx_mod_phot = np.asarray(grid_phot.interp(par1=theta[0], par2=theta[1], par3=theta[2], + flx_mod_spectro = np.asarray([]) + if len(grid_photo['wavelength']) != 0: + flx_mod_photo = np.asarray(grid_photo.interp(par1=theta[0], par2=theta[1], par3=theta[2], method="linear", kwargs={"fill_value": "extrapolate"})) else: - flx_mod_phot = np.asarray([]) + flx_mod_photo = np.asarray([]) elif self.global_params.par5 == 'NA': - if len(grid_merge['wavelength']) != 0: - flx_mod_merge = np.asarray(grid_merge.interp(par1=theta[0], par2=theta[1], par3=theta[2], par4=theta[3], + if len(grid_spectro['wavelength']) != 0: + flx_mod_spectro = np.asarray(grid_spectro.interp(par1=theta[0], par2=theta[1], par3=theta[2], par4=theta[3], method="linear", kwargs={"fill_value": "extrapolate"})) else: - flx_mod_merge = np.asarray([]) - if len(grid_phot['wavelength']) != 0: - flx_mod_phot = np.asarray(grid_phot.interp(par1=theta[0], par2=theta[1], par3=theta[2], par4=theta[3], + flx_mod_spectro = np.asarray([]) + if len(grid_photo['wavelength']) != 0: + flx_mod_photo = np.asarray(grid_photo.interp(par1=theta[0], par2=theta[1], par3=theta[2], par4=theta[3], method="linear", kwargs={"fill_value": "extrapolate"})) else: - flx_mod_phot = np.asarray([]) + flx_mod_photo = np.asarray([]) else: - if len(grid_merge['wavelength']) != 0: - flx_mod_merge = np.asarray(grid_merge.interp(par1=theta[0], par2=theta[1], par3=theta[2], par4=theta[3], + if len(grid_spectro['wavelength']) != 0: + flx_mod_spectro = np.asarray(grid_spectro.interp(par1=theta[0], par2=theta[1], par3=theta[2], par4=theta[3], par5=theta[4], method="linear", kwargs={"fill_value": "extrapolate"})) else: - flx_mod_merge = np.asarray([]) - if len(grid_phot['wavelength']) != 0: - flx_mod_phot = np.asarray(grid_phot.interp(par1=theta[0], par2=theta[1], par3=theta[2], par4=theta[3], + flx_mod_spectro = np.asarray([]) + if len(grid_photo['wavelength']) != 0: + flx_mod_photo = np.asarray(grid_photo.interp(par1=theta[0], par2=theta[1], par3=theta[2], par4=theta[3], par5=theta[4], method="linear", kwargs={"fill_value": "extrapolate"})) else: - flx_mod_phot = np.asarray([]) + flx_mod_photo = np.asarray([]) # Modification of the synthetic spectrum with the extra-grid parameters modif_spec_chi2 = modif_spec(self.global_params, theta, self.theta_index, - wav_obs_merge, flx_obs_merge, err_obs_merge, flx_mod_merge, - wav_obs_phot, flx_obs_phot, err_obs_phot, flx_mod_phot, - transm_obs_merge, star_flx_obs_merge, indobs=indobs) + wav_obs_spectro, flx_obs_spectro, err_obs_spectro, flx_mod_spectro, + wav_obs_photo, flx_obs_photo, err_obs_photo, flx_mod_photo, + transm_obs, star_flx_obs, system_obs, indobs=indobs) ck = modif_spec_chi2[8] modif_spec_MOSAIC.append(modif_spec_chi2) @@ -442,24 +569,21 @@ def _get_spectra(self,theta): return modif_spec_chi2, ck - def get_FULL_spectra(self, theta, grid_used = 'original', wavelengths=[], res_out=1000, re_interp=False, int_method="linear"): + def get_FULL_spectra(self, theta, grid_used = 'original', wavelengths=[], N_points=1000, re_interp=False, int_method="linear"): ''' - To get the data and best model asociated - Use numba: https://numba.pydata.org/. + Extract a model spectrum from another grid. Args: - theta: List of model and extra-model parameters. - grid_used: Default 'original' will use the raw grid. Else, input the path to your desired grid. - wavelengths: Default [] will use max values of the wav_for_adapt range to create a model spectrum. - Else, input the desired wavelength range. - res_out: Default 1000 will be the resolution of your model spectrum. Else, input the desired resolution. - re_interp: Default False. If true, will re-interpolate the grid's hole (WARNING, time consumming...). - int_method: Default "linear" will be the interpolation method use for the grid. Else, input the desired interpolation method. + theta: (list): best parameter values + grid_used: (str): (default = 'original') Path to the grid from where to extract the spectrum. If 'original', the current grid will be used. + wavelengths: (list): (default = []) Desired wavelength range. If [] max and min values of wav_for_adapt range will be use to create the wavelength range. + N_points: (int): (default = 1000) Number of points. + re_interp: (boolean): (default = False). Option to reinterpolate or not the grid. + int_method: (str): (default = "linear") Interpolation method for the grid (if reinterpolated). Returns: - fig, ax, axr, axr2 - - - Authors: Paulina Palma-Bifani and Matthieu Ravet + - wav_final (array): Wavelength array of the full model + - flx_final (array): Flux array of the full model + - ck (float): Scaling factor of the full model ''' self._get_posteriors() @@ -473,9 +597,9 @@ def get_FULL_spectra(self, theta, grid_used = 'original', wavelengths=[], res_ou else: wav = np.concatenate((wav, wav_ind)) wav = np.sort(wav) - wavelengths = np.linspace(wav[0],wav[-1],res_out) + wavelengths = np.linspace(wav[0],wav[-1],N_points) else: - wavelengths = np.linspace(wavelengths[0],wavelengths[-1],res_out) + wavelengths = np.linspace(wavelengths[0],wavelengths[-1],N_points) # Recover the original grid if grid_used == 'original': @@ -521,7 +645,7 @@ def get_FULL_spectra(self, theta, grid_used = 'original', wavelengths=[], res_ou #print(flx_mod_final[100],ck) err_mod_final_calib = flx_mod_final_calib*0.1 - wav_final, _, _, flx_final, _, _, _, _, _ = modif_spec(self.global_params, theta, self.theta_index, + wav_final, _, _, flx_final, _, _, _, _, _, _, _, _, _ = modif_spec(self.global_params, theta, self.theta_index, wavelengths, flx_mod_final_calib, err_mod_final_calib, flx_mod_final_calib/ck, [], [], [], [], [], []) @@ -534,16 +658,17 @@ def plot_fit(self, figsize=(10, 5), uncert='no', trans='no', logx='no', logy='no Plot the best fit comparing with the data. Args: - figsize: x/y size of the plot - uncert: 'yes' or 'no' to plot spectra with associated error bars - trans: 'yes' or 'no' to plot transmision curves for photometry - logx: 'yes' or 'no' to plot the wavelength in log scale - logy: 'yes' or 'no' to plot the flux in log scale - norm: 'yes' or 'no' to plot the normalized spectra + figsize (tuple): (default = (10, 5)) Size of the plot + uncert (str): (default = no) 'yes' or 'no' to plot spectra with associated error bars + trans (str): (default = no) 'yes' or 'no' to plot transmision curves for photometry + logx (str): (default = no) 'yes' or 'no' to plot the wavelength in log scale + logy (str): (default = no) 'yes' or 'no' to plot the flux in log scale + norm (str): (default = no) 'yes' or 'no' to plot the normalized spectra Returns: - fig, ax, axr, axr2 - - Author: Paulina Palma-Bifani and Matthieu Ravet + - fig (object) : matplotlib figure object + - ax (object) : matplotlib axes objects, main spectra plot + - axr (object) : matplotlib axes objects, residuals + - axr2 (object) : matplotlib axes objects, right side density histogram ''' print('ForMoSA - Best fit and residuals plot') @@ -556,11 +681,17 @@ def plot_fit(self, figsize=(10, 5), uncert='no', trans='no', logx='no', logy='no spectra, ck = self._get_spectra(self.theta_best) + iobs_spectro = 0 + iobs_photo = 0 # Scale or not in absolute flux if norm != 'yes': - ck = np.full(len(spectra[0][0]), 1) + if len(spectra[0][0]) != 0: + ck = np.full(len(spectra[0][0]), 1) + else: + ck = np.full(len(spectra[0][4]), 1) + for indobs, obs in enumerate(sorted(glob.glob(self.global_params.main_observation_path))): @@ -570,9 +701,14 @@ def plot_fit(self, figsize=(10, 5), uncert='no', trans='no', logx='no', logy='no spectra = list(spectra) # Transform spectra to a list so that we can modify its values spectra[indobs] = list(spectra[indobs]) model, planet_contribution, stellar_contribution, star_flx = spectra[indobs][3], spectra[indobs][9], spectra[indobs][10], spectra[indobs][11] - spectra[indobs][3] = planet_contribution * model + stellar_contribution * star_flx + spectra[indobs][3] = planet_contribution * model + np.dot(stellar_contribution, star_flx[0].T) + systematics = spectra[indobs][12] + if len(systematics) > 0: + spectra[indobs][3] += systematics if len(spectra[indobs][0]) != 0: + iobs_spectro += 1 + iobs_photo += 1 if uncert=='yes': ax.errorbar(spectra[indobs][0], spectra[indobs][1]/ck[indobs], yerr=spectra[indobs][2]/ck[indobs], c='k', alpha=0.2) ax.plot(spectra[indobs][0], spectra[indobs][1]/ck[indobs], c='k') @@ -586,14 +722,19 @@ def plot_fit(self, figsize=(10, 5), uncert='no', trans='no', logx='no', logy='no axr2.hist(residuals/sigma_res, bins=100 ,color=self.color_out, alpha=0.5, density=True, orientation='horizontal') axr2.legend(frameon=False,handlelength=0) - if indobs == 0: + if indobs == iobs_spectro-1: # Add labels out of the loops - ax.plot(spectra[0][0], np.empty(len(spectra[0][0]))*np.nan, c='k', label='data') - ax.plot(spectra[0][0], np.empty(len(spectra[0][0]))*np.nan, c=self.color_out, label='model') - axr.plot(spectra[0][0], np.empty(len(spectra[0][0]))*np.nan, c=self.color_out, label='model-data') + ax.plot(spectra[0][0], np.empty(len(spectra[0][0]))*np.nan, c='k', label='Spectroscopic data') + ax.plot(spectra[0][0], np.empty(len(spectra[0][0]))*np.nan, c=self.color_out, label='Spectroscopic model') + axr.plot(spectra[0][0], np.empty(len(spectra[0][0]))*np.nan, c=self.color_out, label='Spectroscopic model-data') axr2.hist(residuals/sigma_res, bins=100 ,color=self.color_out, alpha=0.5, density=True, orientation='horizontal', label='density') + + iobs_spectro = -1 + if len(spectra[indobs][4]) != 0: + iobs_photo += 1 + iobs_spectro += 1 # If you want to plot the transmission filters if trans == 'yes': self.global_params.observation_path = obs @@ -606,8 +747,8 @@ def plot_fit(self, figsize=(10, 5), uncert='no', trans='no', logx='no', logy='no filter_pho = np.load(separator.join(path_list) + '/phototeque/' + pho + '.npz') ax.fill_between(filter_pho['x_filt'], filter_pho['y_filt']*0.8*min(spectra[indobs][5]/ck[indobs]),color=self.color_out, alpha=0.3) ax.text(np.mean(filter_pho['x_filt']), np.mean(filter_pho['y_filt']*0.4*min(spectra[indobs][5]/ck[indobs])), pho, horizontalalignment='center', c='gray') - ax.plot(spectra[indobs][4], spectra[indobs][5]/ck[indobs], 'ko', alpha=0.7) - ax.plot(spectra[indobs][4], spectra[indobs][7]/ck[indobs], 'o', color=self.color_out) + ax.plot(spectra[indobs][4], spectra[indobs][5] / ck[indobs], 'ko', alpha=0.7) + ax.plot(spectra[indobs][4], spectra[indobs][7] / ck[indobs], 'o', color=self.color_out) residuals_phot = spectra[indobs][7]-spectra[indobs][5] @@ -615,12 +756,14 @@ def plot_fit(self, figsize=(10, 5), uncert='no', trans='no', logx='no', logy='no axr.plot(spectra[indobs][4], residuals_phot/sigma_res, 'o', c=self.color_out, alpha=0.8) axr.axhline(y=0, color='k', alpha=0.5, linestyle='--') - if indobs == 0: + if indobs == iobs_photo-1: # Add labels out of the loops ax.plot(spectra[0][4], np.empty(len(spectra[0][4]))*np.nan, 'ko', label='Photometry data') ax.plot(spectra[0][4], np.empty(len(spectra[0][4]))*np.nan, 'o', c=self.color_out, label='Photometry model') axr.plot(spectra[0][4], np.empty(len(spectra[0][4]))*np.nan, 'o', c=self.color_out, label='Photometry model-data') - + + iobs_photo = -1 + # Set xlog-scale if logx == 'yes': ax.set_xscale('log') @@ -644,127 +787,357 @@ def plot_fit(self, figsize=(10, 5), uncert='no', trans='no', logx='no', logy='no # define the data as global self.spectra = spectra - #self.residuals = residuals - return spectra + return fig, ax, axr, axr2 + + + def plot_fit_HiRes(self, figsize=(10, 5), uncert='no', trans='no', logx='no', logy='no', norm='no'): + ''' + Same as plot_fit but with the stellar and planetary models for high-resolution spectroscopy. Does not include residuals in a sub-axis. + + Args: + figsize (tuple): (default = (10, 5)) Size of the plot + uncert (str): (default = no) 'yes' or 'no' to plot spectra with associated error bars + trans (str): (default = no) 'yes' or 'no' to plot transmision curves for photometry + logx (str): (default = no) 'yes' or 'no' to plot the wavelength in log scale + logy (str): (default = no) 'yes' or 'no' to plot the flux in log scale + norm (str): (default = no) 'yes' or 'no' to plot the normalized spectra + Returns: + - fig (object) : matplotlib figure object + - ax (object) : matplotlib axes objects + ''' + print('ForMoSA - Best fit and residuals plot') + + fig1, ax1 = plt.subplots(1,1, figsize=figsize) + + spectra, ck = self._get_spectra(self.theta_best) + iobs_spectro = 0 + + + # Scale or not in absolute flux + if norm != 'yes': + ck = np.full(len(spectra[0][0]), 1) + + for indobs, obs in enumerate(sorted(glob.glob(self.global_params.main_observation_path))): + + if self.global_params.use_lsqr[indobs] == 'True': + # If we used the lsq function, it means that our data is contaminated by the starlight difraction + # so the model is the sum of the planet model + the estimated stellar contribution + spectra = list(spectra) # Transform spectra to a list so that we can modify its values + spectra[indobs] = list(spectra[indobs]) + model, planet_contribution, stellar_contribution, star_flx, systematics = spectra[indobs][3], spectra[indobs][9], spectra[indobs][10], spectra[indobs][11], spectra[indobs][12] + transm = spectra[indobs][13] + spectra[indobs][3] = planet_contribution * model + np.dot(stellar_contribution, star_flx[0].T) + if len(systematics) > 0: + spectra[indobs][3] += systematics + + if len(spectra[indobs][0]) != 0: + iobs_spectro += 1 + if uncert=='yes': + ax1.errorbar(spectra[indobs][0], spectra[indobs][1]/ck[indobs], yerr=spectra[indobs][2]/ck[indobs], c='k', alpha=0.2) + ax1.plot(spectra[indobs][0], spectra[indobs][1] - spectra[indobs][3], 'o', alpha = 0.2, color='g') + ax1.plot(spectra[indobs][0], spectra[indobs][1]/ck[indobs], c='k') + ax1.plot(spectra[indobs][0], spectra[indobs][3]/ck[indobs], c='r') + ax1.plot(spectra[indobs][0], np.dot(stellar_contribution, star_flx[0].T), c='b') + ax1.plot(spectra[indobs][0], planet_contribution * model, c='purple') + + + if indobs == iobs_spectro - 1: + # Add labels out of the loops + ax1.plot(spectra[0][0], np.empty(len(spectra[0][0]))*np.nan, c='k', label='residuals') + ax1.plot(spectra[0][0], np.empty(len(spectra[0][0]))*np.nan, c='k', label='data') + ax1.plot(spectra[0][0], np.empty(len(spectra[0][0]))*np.nan, c=self.color_out, label='full model') + ax1.plot(spectra[0][0], np.empty(len(spectra[0][0]))*np.nan, c='k', label='stellar model') + ax1.plot(spectra[0][0], np.empty(len(spectra[0][0]))*np.nan, c='k', label='planetary model') + + iobs_spectro = -1 + + if len(spectra[indobs][4]) != 0: + # If you want to plot the transmission filters + if trans == 'yes': + self.global_params.observation_path = obs + obs_name = os.path.splitext(os.path.basename(self.global_params.observation_path))[0] + spectrum_obs = np.load(os.path.join(self.global_params.result_path, f'spectrum_obs_{obs_name}.npz'), allow_pickle=True) + obs_photo_ins = spectrum_obs['obs_photo_ins'] + for pho_ind, pho in enumerate(obs_photo_ins): + path_list = __file__.split("/")[:-2] + separator = '/' + filter_pho = np.load(separator.join(path_list) + '/phototeque/' + pho + '.npz') + ax1.fill_between(filter_pho['x_filt'], filter_pho['y_filt']*0.8*min(spectra[indobs][5]/ck[indobs]),color=self.color_out, alpha=0.3) + ax1.text(np.mean(filter_pho['x_filt']), np.mean(filter_pho['y_filt']*0.4*min(spectra[indobs][5]/ck[indobs])), pho, horizontalalignment='center', c='gray') + ax1.plot(spectra[indobs][4], spectra[indobs][5]/ck[indobs], 'ko', alpha=0.7) + ax1.plot(spectra[indobs][4], spectra[indobs][7]/ck[indobs], 'o', color=self.color_out) + + + residuals_phot = spectra[indobs][7]-spectra[indobs][5] + sigma_res = np.std(residuals_phot) + + + if indobs == 0: + # Add labels out of the loops + ax1.plot(spectra[0][4], np.empty(len(spectra[0][4]))*np.nan, 'ko', label='Photometry data') + ax1.plot(spectra[0][4], np.empty(len(spectra[0][4]))*np.nan, 'o', c=self.color_out, label='Photometry model') + + # Set xlog-scale + if logx == 'yes': + ax1.set_xscale('log') + # Set xlog-scale + if logy == 'yes': + ax1.set_yscale('log') + # Remove the xticks from the first ax + ax1.set_xticks([]) + # Labels + if norm != 'yes': + ax1.set_ylabel(r'Flux (ADU)') + else: + ax1.set_ylabel(r'Normalised flux (W m-2 µm-1)') + + ax1.set_xlabel(r'wavelength ($ \mu $m)') + + fig1.legend() + plt.figure(fig1) + plt.savefig(self.global_params.result_path + 'full_data.pdf') + + # define the data as global + self.spectra = spectra + + return fig1, ax1 - def plot_ccf(self, rv_grid = [-300,300], rv_step = 0.5, figsize = (10,5)): + def plot_HiRes_comp_model(self, figsize=(10, 5), norm='no', data_resolution = 0): ''' - Plot the ccf (used for high resolution data such as CRIRES+ / HiRISE) + Specific function to plot the best fit comparing with the data for high-resolution spectroscopy. + + Args: + figsize (tuple): (default = (10, 5)) Size of the plot + norm (str): (default = no) 'yes' or 'no' to plot the normalized spectra + data_resolution (int): (default = 0) Custom resolution to broadened data + Returns: + - fig1 (object) : matplotlib figure object + - ax1 (object) : matplotlib axes objects + ''' + print('ForMoSA - Planet model and data') + + spectra, ck = self._get_spectra(self.theta_best) + fig1, ax1 = plt.subplots(1, 1, figsize = figsize) + fig, ax = plt.subplots(1, 1, figsize = figsize) + + # Scale or not in absolute flux + if norm != 'yes': + ck = np.full(len(spectra[0][0]), 1) + + pdf = PdfPages(self.global_params.result_path + 'PLanet_model_and_data_resolution_degraded.pdf') + plt.ioff() + + for indobs, obs in enumerate(sorted(glob.glob(self.global_params.main_observation_path))): + + + if self.global_params.use_lsqr[indobs] == 'True': + # If we used the lsq function, it means that our data is contaminated by the starlight difraction + # so the model is the sum of the planet model + the estimated stellar contribution + spectra = list(spectra) # Transform spectra to a list so that we can modify its values + spectra[indobs] = list(spectra[indobs]) + model, planet_contribution, stellar_contribution, star_flx, systematics, transm = spectra[indobs][3], spectra[indobs][9], spectra[indobs][10], spectra[indobs][11], spectra[indobs][12], spectra[indobs][13] + + if len(spectra[indobs][0]) != 0: + + if (len(systematics) > 0) and (len(star_flx) > 0): + data = spectra[indobs][1] - np.dot(stellar_contribution, star_flx[0].T) - systematics + elif (len(star_flx) > 0): # if len(systematics) = 0 but len(star_flx) > 0 + data = spectra[indobs][1] - np.dot(stellar_contribution, star_flx[0].T) + elif (len(systematics) > 0): # if len(star_flx) = 0 but len(systematics) > 0 + data = spectra[indobs][1] - systematics + else: # if len(star_flx) = 0 and len(systematics) = 0 + data = spectra[indobs][1] + + wave = spectra[indobs][0] + planet_model = planet_contribution * model + + # Compute intrinsic resolution of the data because of the v.sini + resolution = 3.0*1e5 / (self.theta_best[self.theta_index == 'vsini']) + resolution = resolution * np.ones(len(wave)) + + if data_resolution > 0: + self.global_params.custom_reso[indobs] = 'NA' + resolution_data = data_resolution * np.ones(len(wave)) + data_broadened = vsini_fct_accurate(wave, data, 0.6, self.theta_best[self.theta_index == 'vsini']) + data_broadened = resolution_decreasing(self.global_params, wave, [], resolution, wave, data, resolution_data, 'mod') + planet_model_broadened = resolution_decreasing(self.global_params, wave, [], resolution, wave, planet_model, resolution_data, 'mod') + + + fig = plt.figure('comp_model', figsize=figsize) + fig.clf() + ax = fig.add_subplot(111) + + ax.plot(wave, data_broadened, c='k') + ax.plot(wave, planet_model_broadened, c='r') + + ax.set_xlabel(r'wavelength ($\mu$m)') + ax.set_ylabel('Flux (ADU)') + + ax1.plot(wave, data, c='k') + ax1.plot(wave, planet_model, c = 'r') + + if self.global_params.use_lsqr[indobs] == 'True': + legend_data = 'data - star' + else: + legend_data = 'data' + + ax.legend([legend_data, 'planet model']) + + pdf.savefig() + + pdf.close() + + ax1.legend([legend_data, "planet model"], fontsize = 18) + ax1.set_xlabel(r'wavelength ($ \mu $m)', fontsize=18) + ax1.set_ylabel('Flux (ADU)', fontsize=18) + plt.figure(fig1) + plt.savefig(self.global_params.result_path + 'Planet_model_and_data.pdf') + + return fig1, ax1 + + + def plot_ccf(self, figsize = (10,5), rv_grid = [-300,300], rv_step = 0.5, window_normalisation = 100, model_wavelength = [], model_spectra = [], model_resolution = [], model_name = 'Full', rv_cor=0): + ''' + Plot the cross-correlation function. It is used for high resolution spectroscopy. + + Args: + figsize (tuple): (default = (10, 5)) Size of the plot + rv_grid (list): (default = [-300,300]) Maximum and minumum values of the radial velocity shift (in km/s) + rv_step (float): (default = 0.5) Radial velocity shift steps (in km/s) + window_normalisation (int): (default = 100) ? + model_wavelength (list): (default = []) ? + model_spectra = (list): (default = []) ? + model_resolution (list): (default = []) ? + model_name (str): (default = 'Full') ? + rv_cor (int): (default = 0) ? + Returns: + - fig1 (object) : matplotlib figure object + - ax1 (object) : matplotlib axes objects + - rv_grid (list): Radial velocity grid + - ccf (list): Cross-correlation function + - acf (list): Auto-correlation function + Author: Allan Denis ''' print('ForMoSA - CCF plot') - self._get_posteriors() - theta = self.theta_best - theta_index = self.theta_index - # Recovery of the spectroscopy data - spectrum_obs = np.load(self.global_params.result_path + '/spectrum_obs.npz', allow_pickle=True) - wav_obs_merge = spectrum_obs['obs_spectro_merge'][0] - flx_obs_merge = spectrum_obs['obs_spectro_merge'][1] - err_obs_merge = spectrum_obs['obs_spectro_merge'][2] - transm_obs_merge = spectrum_obs['obs_opt_merge'][1] - star_flx_obs_merge = spectrum_obs['obs_opt_merge'][2] - - # Recovery of the spectroscopy and photometry model - path_grid_m = self.global_params.adapt_store_path + '/adapted_grid_merge_' + self.global_params.grid_name + '_nonan.nc' - ds = xr.open_dataset(path_grid_m, decode_cf=False, engine='netcdf4') - grid_merge = ds['grid'] - ds.close() - - if self.global_params.par3 == 'NA': - if len(grid_merge['wavelength']) != 0: - flx_mod_merge = np.asarray(grid_merge.interp(par1=theta[0], par2=theta[1], - method="linear", kwargs={"fill_value": "extrapolate"})) - else: - flx_mod_merge = np.asarray([]) - elif self.global_params.par4 == 'NA': - if len(grid_merge['wavelength']) != 0: - flx_mod_merge = np.asarray(grid_merge.interp(par1=theta[0], par2=theta[1], par3=theta[2], - method="linear", kwargs={"fill_value": "extrapolate"})) - else: - flx_mod_merge = np.asarray([]) - elif self.global_params.par5 == 'NA': - if len(grid_merge['wavelength']) != 0: - flx_mod_merge = np.asarray(grid_merge.interp(par1=theta[0], par2=theta[1], par3=theta[2], par4=theta[3], - method="linear", kwargs={"fill_value": "extrapolate"})) - else: - flx_mod_merge = np.asarray([]) - else: - if len(grid_merge['wavelength']) != 0: - flx_mod_merge = np.asarray(grid_merge.interp(par1=theta[0], par2=theta[1], par3=theta[2], par4=theta[3], - par5=theta[4], - method="linear", kwargs={"fill_value": "extrapolate"})) - else: - flx_mod_merge = np.asarray([]) + fig1, ax1 = plt.subplots(1,1, figsize=figsize) rv_grid = np.arange(rv_grid[0], rv_grid[1], rv_step) - cp, cs = np.ones(len(rv_grid)), np.ones(len(rv_grid)) - i = 0 + ccf = np.array([]) + acf = np.array([]) - self.global_params.rv = "NA" - self.global_params.use_lsqr = "False" - modif_spec_chi2 = modif_spec(self.global_params, theta, self.theta_index, - wav_obs_merge, flx_obs_merge, err_obs_merge, flx_mod_merge, - [], [], [], [], - transm_obs_merge, star_flx_obs_merge) - - flx_mod_merge = modif_spec_chi2[3] / modif_spec_chi2[8] + spectra, ck = self._get_spectra(self.theta_best) - # # Making sure we only call the doppler correction function and the lsq function - # # because we want to plot the cross correlation as a function of the radial velocity - self.global_params.rv = "uniform" - self.global_params.av = "NA" - self.global_params.vsini, self.global_params.ld = "NA", "NA" - self.global_params.bb_T, self.global_params.bb_R = "NA", "NA" - self.global_params.r, self.global_params.T = "NA", "NA" - self.global_params.ccf_method = 'continuum_unfiltered' - self.global_params.use_lsqr = 'True' + model_array = np.array([]) + wave_array = np.array([]) + err_array = np.array([]) + transm_array = np.array([]) + data_array = np.array([]) - for rv_i in tqdm(rv_grid): - theta[theta_index == 'rv'] = rv_i - - modif_spec_chi2 = modif_spec(self.global_params, theta, self.theta_index, - np.copy(wav_obs_merge), np.copy(flx_obs_merge), np.copy(err_obs_merge), np.copy(flx_mod_merge), - [], [], [], [], - transm_obs_merge, np.copy(star_flx_obs_merge)) + for indobs, obs in enumerate(sorted(glob.glob(self.global_params.main_observation_path))): - cp[i] = modif_spec_chi2[9] - cs[i] = modif_spec_chi2[10] + if self.global_params.use_lsqr[indobs] == 'True': + # If we used the lsq function, it means that our data is contaminated by the starlight difraction + # so the model is the sum of the planet model + the estimated stellar contribution + spectra = list(spectra) # Transform spectra to a list so that we can modify its values + spectra[indobs] = list(spectra[indobs]) + wavelength, err, model, stellar_contribution, star_flx, systematics = spectra[indobs][0], spectra[indobs][2], spectra[indobs][3], spectra[indobs][10], spectra[indobs][11], spectra[indobs][12] + transm = spectra[indobs][13] + - i += 1 + if len(spectra[indobs][0]) != 0: + + if (len(systematics) > 0) and (len(star_flx) > 0): + data = spectra[indobs][1] - np.dot(stellar_contribution, star_flx[0].T) - systematics + elif (len(star_flx) > 0): # if len(systematics) = 0 but len(star_flx) > 0 + data = spectra[indobs][1] - np.dot(stellar_contribution, star_flx[0].T) + elif (len(systematics) > 0): # if len(star_flx) = 0 but len(systematics) > 0 + data = spectra[indobs][1] - systematics + else: # if len(star_flx) = 0 and len(systematics) = 0 + data = spectra[indobs][1] + + _, _, _, model = doppler_fct(wavelength, data, err, model, -self.theta_best[self.theta_index == 'rv']) + + if len(model_spectra) == 0: + model_array = np.append(model_array, model) + else: + obs_spectro, _, _, _, _ = adapt_observation_range(self.global_params, indobs=indobs) + res_obs = obs_spectro[0][3] + res_obs_interp = interp1d(obs_spectro[0][0], res_obs, fill_value = 'extrapolate') + res_obs = res_obs_interp(wavelength) + + ind = np.where((model_wavelength >= wavelength[0]) & (model_wavelength <= wavelength[-1])) + model_wavelength_adapt, model_resolution_adapt, model_spectra_adapt = model_wavelength[ind], model_resolution[ind], model_spectra[ind] + model_resolution_interp = interp1d(model_wavelength_adapt, model_resolution_adapt, fill_value = 'extrapolate') + model_resolution_adapt = model_resolution_interp(wavelength) + model_adapted = resolution_decreasing(self.global_params, wavelength, [], res_obs, model_wavelength_adapt, model_spectra_adapt, model_resolution_adapt, + 'mod', indobs=indobs) + + + if len(transm) > 0: + _, _, model_adapted, _, _, _ = lsq_fct(spectra[indobs][1], err, star_flx, transm, model_adapted, systematics) + + model_adapted = vsini_fct_accurate(wavelength, model_adapted, 0.6, self.theta_best[self.theta_index=='vsini']) + + model_array = np.append(model_array, model_adapted) + + wave_array = np.append(wave_array, wavelength) + data_array = np.append(data_array, data) + transm_array = np.append(transm_array, transm) + err_array = np.append(err_array, err) + + max_ccf = 0 + for rv in tqdm(rv_grid): + _, _, _, model_doppler = doppler_fct(wave_array, data_array, err_array, model_array, rv+rv_cor) + ccf = np.append(ccf, np.nansum(model_doppler * data_array)) + acf = np.append(acf, np.nansum(model_doppler * model_array)) + if np.nansum(model_doppler * data_array) > max_ccf: + max_ccf = np.nansum(model_doppler * data_array) + model_max_ccf = model_doppler - normalization_limit = 100 + # Rescaling cross-correlation function to estimate a SNR + acf_norm = acf - np.median(acf[(np.abs(rv_grid) > window_normalisation)]) + ccf_norm = ccf - np.median(ccf[(np.abs(rv_grid-rv_grid[np.argmax(ccf)]) > window_normalisation)]) + ccf_noise = np.std(ccf_norm[(np.abs(rv_grid-rv_grid[np.argmax(ccf)]) > window_normalisation)]) + ccf_norm = ccf_norm / ccf_noise + # Rescaling autocorrelation function to make comparable with cross-correlation function + acf_norm = acf_norm / np.max(acf_norm) * np.max(ccf_norm) - fig, ax = plt.subplots(figsize = figsize) - fig.tight_layout() - - cp_norm = cp - np.median(cp[(np.abs(rv_grid-rv_grid[np.argmax(cp)]) > normalization_limit)]) - cp_noise = np.std(cp_norm[(np.abs(rv_grid-rv_grid[np.argmax(cp)]) > normalization_limit)]) - ccf_norm = cp_norm / cp_noise - - ax.plot(rv_grid, ccf_norm) - ax.set_xlabel('rv (km/s)') - ax.set_ylabel('ccf signal') - - return - - + ax1.plot(rv_grid, ccf_norm, label = 'ccf') + ax1.plot(rv_grid + rv_grid[np.argmax(ccf_norm)] + rv_cor, acf_norm) + ax1.axvline(x = rv_grid[np.argmax(ccf_norm)], linestyle = '--', c='C3') + ax1.set_xlabel('RV (km/s)') + ax1.set_ylabel('S/N') + ax1.legend(['ccf', 'acf']) + print(f'SNR = {np.nanmax(ccf_norm):.1f}, RV = {rv_grid[np.argmax(ccf_norm)]:.1f} km/s') + #ax1.set_title(f'SNR = {np.nanmax(ccf_norm):.1f}, RV = {rv_grid[np.argmax(ccf_norm)]:.1f} km/s') + plt.figure(fig1) + plt.savefig(self.global_params.result_path + 'ccf_' + model_name + '.pdf') + + return fig1, ax1, rv_grid, ccf, acf + - def plot_PT(self,path_temp_profile, figsize=(6,5), model = 'ExoREM'): + + def plot_PT(self, path_temp_profile, figsize=(6,5), model = 'ExoREM'): ''' - Plot the Pressure-Temperature profiles - Calculates the most probable temperature profile - - Return: fig, ax + Function to plot the Pressure-Temperature profiles. + Adpated from Nathan Zimniak. - Author: Nathan Zimniak and Paulina Palma-Bifani + Args: + path_temp_profile (str): Path to the temperature profile grid + figsize (tuple): (default = (6, 5)) Size of the plot + model (str): (default = 'ExoREM') Name of the model grid + Returns: + - fig (object) : matplotlib figure object + - ax (object) : matplotlib axes objects ''' print('ForMoSA - Pressure-Temperature profile') @@ -859,34 +1232,34 @@ def plot_PT(self,path_temp_profile, figsize=(6,5), model = 'ExoREM'): def plot_Clouds(self, cloud_prop, path_cloud_profile, figsize=(6,5)): ''' - Cloud profiles calculations - - Inputs: - - cloud_prop (str) : choose the cloud - 'eddy_diffusion_coefficient', - 'vmr_CH4', - 'vmr_CO', - 'vmr_CO2', - 'vmr_FeH', - 'vmr_H2O', - 'vmr_H2S', - 'vmr_HCN', - 'vmr_K', - 'vmr_Na', - 'vmr_NH3', - 'vmr_PH3', - 'vmr_TiO', - 'vmr_VO', - 'cloud_opacity_Fe', - 'cloud_opacity_Mg2SiO4', - 'cloud_particle_radius_Fe', - 'cloud_particle_radius_Mg2SiO4', - 'cloud_vmr_Fe', - 'cloud_vmr_Mg2SiO4' - - Return: fig, ax - - Author: Nathan Zimniak and Paulina Palma-Bifani + Function to plot cloud profiles. + Adapted from Nathan Zimniak + + Args: + cloud_prop (str) : Choose the cloud species. The options are + ['eddy_diffusion_coefficient', + 'vmr_CH4', + 'vmr_CO', + 'vmr_CO2', + 'vmr_FeH', + 'vmr_H2O', + 'vmr_H2S', + 'vmr_HCN', + 'vmr_K', + 'vmr_Na', + 'vmr_NH3', + 'vmr_PH3', + 'vmr_TiO', + 'vmr_VO', + 'cloud_opacity_Fe', + 'cloud_opacity_Mg2SiO4', + 'cloud_particle_radius_Fe', + 'cloud_particle_radius_Mg2SiO4', + 'cloud_vmr_Fe', + 'cloud_vmr_Mg2SiO4'] + Returns: + - fig (object) : matplotlib figure object + - ax (object) : matplotlib axes objects ''' print('ForMoSA - Cloud profile') @@ -937,7 +1310,7 @@ def plot_Clouds(self, cloud_prop, path_cloud_profile, figsize=(6,5)): propsup95.append(np.percentile(cloud_prop_profiles[:, i], 98)) # Plot le profil le plus probable et les percentiles associés - fig = plt.figure() + fig = plt.figure(figsize=figsize) ax = plt.axes() ax.fill_betweenx(P, propinf95, propsup95, color=self.color_out, alpha=0.1, label=r'2 $\sigma$') @@ -996,5 +1369,6 @@ def plot_Clouds(self, cloud_prop, path_cloud_profile, figsize=(6,5)): ax.legend(frameon=False) return fig, ax + diff --git a/dist/ForMoSA-1.1.3-py3-none-any.whl b/dist/ForMoSA-1.1.3-py3-none-any.whl new file mode 100644 index 0000000..bbe3356 Binary files /dev/null and b/dist/ForMoSA-1.1.3-py3-none-any.whl differ diff --git a/dist/ForMoSA-1.1.3.tar.gz b/dist/ForMoSA-1.1.3.tar.gz new file mode 100644 index 0000000..729b20e Binary files /dev/null and b/dist/ForMoSA-1.1.3.tar.gz differ diff --git a/dist/ForMoSA-2.0.0-py3-none-any.whl b/dist/ForMoSA-2.0.0-py3-none-any.whl deleted file mode 100644 index 028da97..0000000 Binary files a/dist/ForMoSA-2.0.0-py3-none-any.whl and /dev/null differ diff --git a/dist/formosa-2.0.0.tar.gz b/dist/formosa-2.0.0.tar.gz deleted file mode 100644 index 3ced85e..0000000 Binary files a/dist/formosa-2.0.0.tar.gz and /dev/null differ diff --git a/docs/build/html/_images/ForMoSA.png b/docs/ForMoSA.png similarity index 100% rename from docs/build/html/_images/ForMoSA.png rename to docs/ForMoSA.png diff --git a/docs/Makefile b/docs/Makefile index d0c3cbf..d4bb2cb 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -5,8 +5,8 @@ # from the environment for the first two. SPHINXOPTS ?= SPHINXBUILD ?= sphinx-build -SOURCEDIR = source -BUILDDIR = build +SOURCEDIR = . +BUILDDIR = _build # Put it first so that "make" without argument is like "make help". help: diff --git a/docs/_build/doctrees/adapt.doctree b/docs/_build/doctrees/adapt.doctree new file mode 100644 index 0000000..3835c3f Binary files /dev/null and b/docs/_build/doctrees/adapt.doctree differ diff --git a/docs/_build/doctrees/api.doctree b/docs/_build/doctrees/api.doctree new file mode 100644 index 0000000..2578554 Binary files /dev/null and b/docs/_build/doctrees/api.doctree differ diff --git a/docs/_build/doctrees/atm_grids.doctree b/docs/_build/doctrees/atm_grids.doctree new file mode 100644 index 0000000..0067136 Binary files /dev/null and b/docs/_build/doctrees/atm_grids.doctree differ diff --git a/docs/_build/doctrees/demo.doctree b/docs/_build/doctrees/demo.doctree new file mode 100644 index 0000000..08a80d7 Binary files /dev/null and b/docs/_build/doctrees/demo.doctree differ diff --git a/docs/_build/doctrees/demo_basic.doctree b/docs/_build/doctrees/demo_basic.doctree new file mode 100644 index 0000000..3322e91 Binary files /dev/null and b/docs/_build/doctrees/demo_basic.doctree differ diff --git a/docs/_build/doctrees/demo_classic.doctree b/docs/_build/doctrees/demo_classic.doctree new file mode 100644 index 0000000..853c019 Binary files /dev/null and b/docs/_build/doctrees/demo_classic.doctree differ diff --git a/docs/_build/doctrees/demoabpic.doctree b/docs/_build/doctrees/demoabpic.doctree new file mode 100644 index 0000000..c2ebb65 Binary files /dev/null and b/docs/_build/doctrees/demoabpic.doctree differ diff --git a/docs/_build/doctrees/environment.pickle b/docs/_build/doctrees/environment.pickle new file mode 100644 index 0000000..4c9a2ea Binary files /dev/null and b/docs/_build/doctrees/environment.pickle differ diff --git a/docs/_build/doctrees/index.doctree b/docs/_build/doctrees/index.doctree new file mode 100644 index 0000000..931e2ec Binary files /dev/null and b/docs/_build/doctrees/index.doctree differ diff --git a/docs/_build/doctrees/installation.doctree b/docs/_build/doctrees/installation.doctree new file mode 100644 index 0000000..63aba2f Binary files /dev/null and b/docs/_build/doctrees/installation.doctree differ diff --git a/docs/_build/doctrees/main_utilities.doctree b/docs/_build/doctrees/main_utilities.doctree new file mode 100644 index 0000000..c3b8f74 Binary files /dev/null and b/docs/_build/doctrees/main_utilities.doctree differ diff --git a/docs/_build/doctrees/nbsphinx/demoabpic.ipynb b/docs/_build/doctrees/nbsphinx/demoabpic.ipynb new file mode 100644 index 0000000..72a10ab --- /dev/null +++ b/docs/_build/doctrees/nbsphinx/demoabpic.ipynb @@ -0,0 +1,56 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# AB Pic demo" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + ".. toctree::\n", + " :maxdepth: 2\n", + " :titlesonly:\n", + "\n", + " demo_basic.rst\n", + "\n", + " tutorials/demo_basic.ipynb\n", + "\n", + " :doc:`tutorials/demo_basic.ipynb`" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "exo_formosa_multi3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/_build/doctrees/nbsphinx/tutorials/atmospheric_grid_info.ipynb b/docs/_build/doctrees/nbsphinx/tutorials/atmospheric_grid_info.ipynb new file mode 100644 index 0000000..5e240b0 --- /dev/null +++ b/docs/_build/doctrees/nbsphinx/tutorials/atmospheric_grid_info.ipynb @@ -0,0 +1,92 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Example on how to access to the atmospheric grid info to check the parameters and their ranges." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import xarray as xr" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Dimensions: (wavelength: 29922, par1: 33, par2: 5, par3: 4, par4: 15)\n", + "Coordinates:\n", + " * wavelength (wavelength) float64 0.6667 0.6667 0.6667 ... 245.4 248.4 251.6\n", + " * par1 (par1) float64 400.0 450.0 500.0 ... 1.9e+03 1.95e+03 2e+03\n", + " * par2 (par2) float64 3.0 3.5 4.0 4.5 5.0\n", + " * par3 (par3) float64 -0.5 0.0 0.5 1.0\n", + " * par4 (par4) float64 0.1 0.15 0.2 0.25 0.3 ... 0.6 0.65 0.7 0.75 0.8\n", + "Data variables:\n", + " grid (wavelength, par1, par2, par3, par4) float64 ...\n", + "Attributes:\n", + " key: ['par1', 'par2', 'par3', 'par4']\n", + " par: ['teff', 'logg', 'mh', 'co']\n", + " title: ['Teff', 'log(g)', '[M/H]', 'C/O']\n", + " unit: ['(K)', '(dex)', '', '']\n", + " res: [29999.50000004 29998.49999991 29997.50000002 ... 80.5\\n ...\n" + ] + } + ], + "source": [ + "# Here Exo-REM grid is used as example\n", + "grid_path = '/Users/ppalmabifani/Desktop/exoAtm/c0_ForMoSA/INPUTS/atm_grids/atm_grids_native/EXOREM_native.nc'\n", + "\n", + "ds = xr.open_dataset(grid_path, decode_cf=False)\n", + " \n", + "print(ds)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.7.13 ('exo_formosa')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.13" + }, + "vscode": { + "interpreter": { + "hash": "9aec1e17db1a1c759b18bf85d14c335cdcfb4080f740d60b236f2747bc3cb68f" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/_build/doctrees/nbsphinx/tutorials/demoabpic.ipynb b/docs/_build/doctrees/nbsphinx/tutorials/demoabpic.ipynb new file mode 100644 index 0000000..bfffa13 --- /dev/null +++ b/docs/_build/doctrees/nbsphinx/tutorials/demoabpic.ipynb @@ -0,0 +1,341 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# demo AB Pic b\n", + "\n", + "\n", + "This tutorial is intended as a quick start. \n", + "\n", + "\n", + "We will use medium resolution VLT/SINFONI K-band data of AB Pic b. These observations and example model were published in [P. Palma-Bifani et al (2023)](https://www.aanda.org/articles/aa/pdf/2023/02/aa44294-22.pdf).\n", + "\n", + "## Imports" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [], + "source": [ + "# Generic packages\n", + "import sys, time, os\n", + "import matplotlib.pyplot as plt\n", + "\n", + "# ForMoSA modules\n", + "sys.path.insert(0, os.path.abspath('/Users/ppalmabifani/opt/anaconda3/envs/exo_formosa_multi_pip2/lib/python3.11/site-packages/ForMoSA/'))\n", + "# For the interpolation & sampling\n", + "from ForMoSA.main_utilities import GlobFile\n", + "from ForMoSA.adapt.adapt_obs_mod import launch_adapt\n", + "from ForMoSA.nested_sampling.nested_sampling import launch_nested_sampling\n", + "# For the plots\n", + "from ForMoSA.plotting.plotting_class import PlottingForMoSA" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 0. Setup\n", + "\n", + "You need to create a config file with extension <.ini> and modify the parameters. Learn more about our config files in it's specific tutorial.\n", + "\n", + "To initialize ForMoSA we need to read the config.ini file and setup the outputs directory and global parameters as follows" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [], + "source": [ + "base_path = 'data_abpic/'\n", + "\n", + "# CONFIG_FILE \n", + "# reading and defining global parameters\n", + "config_file_path = base_path + 'config_ABPicb.ini'\n", + "global_params = GlobFile(config_file_path) \n", + "\n", + "# Optional: Add \"time_now\" and \"save_name\" to avoid overwriting results\n", + "time_now = time.strftime(\"%Y%m%d_%H%M%S\")\n", + "save_name = 'test'\n", + "\n", + "# Create directory to save the outputs \n", + "global_params.result_path = global_params.result_path+ save_name+'_t' + time_now+'/'\n", + "os.makedirs(global_params.result_path)\n", + "\n", + "# Overwrite some parameters\n", + "global_params.config.filename = global_params.result_path + 'config_used.ini'\n", + "global_params.config['config_path']['result_path']=global_params.result_path\n", + "global_params.config.write()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1. Interpolate the grid\n", + "\n", + "Once everything is setup, we start by adapting the models and observations. \n", + "\n", + "The grid of models is interpolated for this, but you don't need to repeat this step once you've adapted the grid for a specific dataset. \n", + "\n", + "(Answer 'no' only the first time)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "# Have you already interpolated the grids for this data? \n", + "y_n_par = 'yes'\n", + "#y_n_par = 'no' # Only answer no the first time, then comment to save time\n", + "\n", + "launch_adapt(global_params, justobs=y_n_par)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2. Lunch Nested Sampling \n", + "\n", + "Once the grid is interpolated, we proceed with the nested sampling. For this case we are using the Python package nestle. " + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n", + "-> Likelihood functions check-ups\n", + "\n", + "ABPicb_SINFONI_K will be computed with chi2_classic\n", + "\n", + "Done !\n", + "\n", + "\u001b[Kit= 1330 logz=-1071.92517042 \n", + "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n", + "-> Nestle \n", + " \n", + "The code spent 234.33751487731934 sec to run.\n", + "niter: 1331\n", + "ncall: 13109\n", + "nsamples: 1431\n", + "logz: -1071.101 +/- 0.347\n", + "h: 12.010\n", + "\n", + "\n", + " \n", + "-> Voilà, on est prêt\n" + ] + } + ], + "source": [ + "launch_nested_sampling(global_params)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 3. Plotting the outcomes\n", + "\n", + "ForMoSA has been designed with a plotting class. Bellow we show 4 main features: \n", + "\n", + "- Plotting corner-plots\n", + "- Plotting spectra and residuals\n", + "- Plotting chains \n", + "- Accessing the different parameters\n", + "\n", + "All plotting functions return the fig object. Therefore you can edit the axes, overplot text/curves, save, etc...\n", + "\n", + "We need to start by initializing the plotting class as follows." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [], + "source": [ + "# Path to output file created in the first step\n", + "config_file_path_pl = 'data_abpic/outputs/test_t20240807_005025'\n", + "\n", + "# Initialize the plotting class and set the color\n", + "plotForMoSA = PlottingForMoSA(config_file_path_pl+'/config_used.ini', 'red')\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### PLOT Corner" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ForMoSA - Corner plot\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA7MAAAPaCAYAAABF5Q/9AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy80BEi2AAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOzdd3xN9/8H8Ncd2XuKldgkhNhVsUptalc1tWtXB61RJLaivkqLqn6tUKXKt3ZRM/YOYjaLiMheN+Pee35/qPuTyrgrObnJ6/l43Mf3OudzPud1Q/rNO5/P+XwkgiAIICIiIiIiIjIhUrEDEBEREREREemKxSwRERERERGZHBazREREREREZHJYzBIREREREZHJYTFLREREREREJofFLBEREREREZkcFrNERERERERkcljMEhERERERkclhMUtEREREREQmh8UsERERERERmRwWs0Sks99//x3vvvsunJ2dIZFIEBERodV1UVFRGDRoEJycnGBjY4PmzZvj6dOn+bYdP348JBIJvv/+eyMmJyIiIqKygsUsEb2hffv22LRpU4HnMzIy0LZtW8ybN0/rPhMSEuDv7w9HR0ccO3YMt27dwpw5c2BhYfFG2/379+P8+fOoVKmSPvGJiIiIqBxgMVvK5ebmIigoCLVr14aFhQUkEgn27t1b5LnCCIKApk2bonPnzgbnu3//PuRyOdasWWNwX2Q6PvroI8yePRvt27fX+ppvvvkG1atXx/r169G0aVPUrFkTvXr1gqura552z58/x/jx47F161aYmZkZOTkRERERlRUsZg0gkUh0eunj22+/xdy5c1GpUiVMnToVgYGBqFevXpHnCrNlyxZcu3btjVG1iIgISCQSdO3aNd/rvvvuO0ilUnh6euL+/fsAgLp16+KDDz7A3LlzkZaWptdnNLbg4GCMHTsWzZo10xT5hY0yVqtWrcC/s38Xa5s2bSry77ljx45695+fp0+fYuXKlejcuTM8PT1hbm4ODw8P9O/fHxcvXsz3Gn1yFrd9+/ahSZMm6N+/P9zd3dG8eXP8/vvvb7QbMWIEJk+eDF9f3xLNR0RERESmRS52AFMWGBj4xrGVK1ciJSUl33P62L9/P2xtbXH06FGYm5trfa4garUaQUFBaNOmDd566y2tc8yZMwfz589HvXr18Oeff6Jq1aqac1999RWCg4OxatUq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fH19+cwsERERERWIz8yWQwsWLIBCocDq1asN7kupVGLRokXo3bs3C1kTNn36dEgkkkJf+REEAePGjUNUVBQ2bdpU6D3UajWaN2+OwMBANG7cGFOnTkXPnj3zTDsmIiIiItIWpxmXQ15eXti8eTOeP39ucF9RUVEYOnSo5llHMk1TpkzReYEtQRAwYcIEHDt2DKdPn9Zs/VQQDw8P1K1bN88xb29vnDt3Tte4REREREQsZsurQYMGGaWfGjVqICgoyCh9kXjc3NyKLEZfJwgCJk6ciAMHDuDUqVOoWrVqkde8/fbbePToUZ5jDx48gJeXl855iYiIiIg4zZiIdDZx4kT88ssv2L59O6ysrBAbG4vY2Fjk5ORo2nz//ffo2LGj5s+ff/45zp49i2+//RaPHj3CunXrsG/fPowfP17TJjExETdu3NDshXz37l3cuHEDiYmJJffhiIiIiMgkcAEoItJZQc/QnjhxAu3btwcABAUFYdOmTZrVmAFgz549+PrrrxEeHo46depg7ty56NOnj+b8pk2bMGLEiDf63bhxY7HsM0xEREREpovFLBEREREREZkcTjMmIiIiIiIik8NiloiIiIiIiEwOVzMuZmq1GjExMbCzsyvwOUOi8koQBKSlpaFSpUqQSvm7NSIiIiLSHovZYhYTE6PVtiVE5Vl0dDSqVKkidgwiIiIiMiEsZouZnZ0dgJc/rNvb24uchso7lUqFc+fOAXi576tMJjOova79/VtqaiqqVq2q+T4hIiIiItIWVzMuZqmpqXBwcEBKSgqLWaJ/4fcHEREREemLD6kRERERERGRyeE0Y6JyJDc3F+vXrwcAjBkzBmZmZga117U/IiIiIiJj4TTjYsZplFSaZGRkwNbWFgCQnp4OGxsbg9rr2t+/8fuDiIiIiPTFacZERERERERkcljMEhERERERkclhMUtEREREREQmh8UsERERERERmRwWs0RERERERGRyWMwSERERERGRyeE+s0TliIWFBfbv3695b2h7XfsjIiIiIjIW7jNbzLiPJlHB+P1BRERERPriNGMiIiIiIiIyOZxmTFSO5ObmYtu2bQCADz/8EGZmZga117U/IiIiIiJj4TTjYsZplFSaZGRkwNbWFgCQnp4OGxsbg9rr2t+/8fuDiIiIiPTFkVkiAgBERUUhPj4+zzGFQqF5f+PGDVhZWcHV1RWenp4lHY+IiIiIKA8Ws0SEqKgoeHt7IzMzs8A2/v7+AABra2uEhYWxoCUiIiIiUbGYJSLEx8cjMzMTwcHB8Pb21hxXKBSaIvbs2bOIiIhAQEAA4uPjWcwSERERkahYzBKRhre3N5o0aaL5c0ZGhua9n58frKysxIhFRERERPQGbs1DREREREREJofFLBEREREREZkcTjMmKkcsLCywc+dOzXtD2+vaHxERERGRsbCYJSpH5HI5Bg4caLT2uvZHRERERGQsnGZMREREREREJocjs0TliFKpxJ49ewAAffv2hVxe+H8C/t3e0P6IiIiIiIyFP3kSlSPZ2dkYNGgQACA9Pb3I4vPf7Q3tj4iIiIjIWDjNmIiIiIiIiEwOi1kiIiIiIiIyOSxmiYiIiIiIyOSwmCUiIiIiIiKTw2KWiIiIiIiITA6LWSIiIiIiIjI53EeDqBwxNzfHxo0bNe8Nba9rf0RERERExsJilqgcMTMzw/Dhw43WXtf+iIiIiIiMhdOMiYiIiIiIyORwZJaoHFEqlThy5AgAoEuXLpDLC/9PwL/bG9ofEREREZGx8CdPonIkOzsbPXv2BACkp6cXWXz+u72h/RERERERGQunGRMREREREZHJYTFLREREREREJofFLBEREREREZkcFrNERERERERkcljMEhERERERkclhMUtEREREREQmh/toEJUj5ubm+P777zXvDW2va39ERERERMbCYpaoHDEzM8PEiRON1l7X/oiIiIiIjIXTjImIiIiIiMjkcGSWqBxRqVQ4c+YMAKBNmzaQyWQ6tTe0PyIiIiIiY2ExS1SOZGVloUOHDgCA9PR02NjY6NTe0P6IiIiIiIyF04yJiIiIiIjI5LCYJSIiIiIiIpPDYpaIiIiIiIhMDotZIiIiIiIiMjksZomIiIiIiMjksJglIiIiIiIik8OteYjKETMzMyxdulTz3tD2uvZHRERERGQsLGaJyhFzc3N8+eWXRmuva39ERERERMbCacZERERERERkcjgyS1SOqFQqXLt2DQDQpEkTyGQyndob2h8RERERkbGwmCUqR7KystCiRQsAQHp6OmxsbHRqb2h/RERERETGwmnGREREREREZHJYzBIREREREZHJYTFLREREREREJofFLBEREREREZkcFrNERERERERkcljMEhERERERkcnh1jxE5YiZmRkCAwM17w1tr2t/RERERETGwmKWqBwxNzdHUFCQ0drr2h8RERERkbFwmjERERERERGZHI7MEpUjarUaYWFhAABvb29IpYX/Puvf7Q3tj4iIiIjIWFjMEpUjCoUCDRo0AACkp6fDxsZGp/aG9kdEREREZCwcRiEiIiIiIiKTw2KWiIiIiIiITA6LWSIiIiIiIjI5LGaJiIiIiIjI5LCYJSIiIiIiIpPDYpaIiIiIiIhMDrfmISpHzMzMMHXqVM17Q9vr2h8RERERkbGwmCUqR8zNzbFs2TKjtde1PyIiIiIiY+E0YyIiIiIiIjI5HJklKkfUajWioqIAAJ6enpBKC/991r/bvxIWFqY5HxsbCwDw8PDI05+rq2uea4iIiIiIjInFLFE5olAoUL16dQBAeno6bGxsdGrv6uoKa2trBAQEFHkva2trhIWFsaAlIiIiomLBYpaItObp6YmwsDDEx8cDeFns+vv7AwDOnj0LKysrAC9HbgMCAhAfH89iloiIiIiKBYtZItKJp6enpkDNyMjQHPfz8ytypJeIiIiIyFi4ABQRERERERGZHBazREREREREZHJYzBIREREREZHJYTFLREREREREJocLQBGVI3K5HBMmTNC8N7S9rv0RERERERkLf/okKkcsLCzwww8/GK29rv0RERERERkLpxkTERERERGRyeHILFE5IggC4uPjAQCurq6QSCQGtde1PyIiIiIiY2ExS1SOZGZmwt3dHQCQnp4OGxsbg9rr2h8RERERkbFwmjERERERERGZHBazREREREREZHJYzBIREREREZHJYTFLREREREREJofFLBEREREREZkcFrNERERERERkcrg1D1E5IpfLMWzYMM17Q9vr2h8RERERkbHwp0+icsTCwgKbNm0yWntd+yMiIiIiMhZOMyYiIiIiIiKTw5FZonJEEARkZmYCAKytrSGRSAxqr2t/RERERETGwpFZonIkMzMTtra2sLW11RShhrTXtT8iIiIiImNhMUtEREREREQmh8UsERERERERmRwWs0RERERERGRyWMwSERERERGRyWExS0RERERERCaHxSwRERERERGZHO4zS1SOyGQyDBgwQPPe0Pa69kdEREREZCwsZonKEUtLS+zatcto7XXtj4iIiIjIWDjNmIiIiIiIiEwOi1kiIiIiIiIyOSxmicqRjIwMSCQSSCQSZGRkGNxe1/6IiIiIiIyFxSwRERERERGZHBazREREREREZHJYzBIREREREZHJYTFLREREREREJofFLBEREREREZkcFrNERERERERkcuRiByCikiOTydC9e3fNe0Pb69ofEREREZGxsJglKkcsLS1x4MABo7XXtT8iIiIiImPhNGMiIiIiIiIyOSxmiYiIiIiIyOSwmCUqRzIyMmBjYwMbGxtkZGQY3F7X/oiIiIiIjIXPzBKVM5mZmUZtr2t/RERERETGwJFZIiIiIiIiMjksZomIiIiIiMjksJglIiIiIiIik8NiloiIiIiIiEwOi1kiIiIiIiIyOVzNmKgckUqlaNeunea9oe117Y+IiIiIyFhYzBKVI1ZWVjh58qTR2uvaHxERERGRsXAohYiIiIiIiEwOi1kiIiIiIiIyOSxmicqRjIwMuLm5wc3NDRkZGQa317U/IiIiIiJj4TOzROVMfHy8Udvr2h8RERERkTFwZJaIiIiIiIhMDotZIiIiIiIiMjksZomIiIiIiMjksJglIiIiIiIik8NiloiIiIiIiEwOVzMmKkekUimaNWumeW9oe137IyIiIiIyFhazROWIlZUVLl++bLT2uvZHRERERGQsHEohIiIiIiIik8NiloiIiIiIiEwOi1miciQzMxPVqlVDtWrVkJmZaXB7XfsjIiIiIjIWPjNLVI4IgoDIyEjNe0Pb69ofEREREZGxcGSWiIiIiIiITA6LWSIiIiIiIjI5LGaJiIiIiIjI5LCYJSIiIiIiIpPDBaCIyrioqCjEx8cDABQKheb4jRs3YGVlBQAICwsTJRsRERERkb5YzBKVYVFRUfD29s532xx/f/88f7a2toarq2ueYxKJBD4+Ppr3/1bUeSIiIiKi4sJilqgMi4+PR2ZmJoKDg+Ht7V1oW1dXV3h6euY5Zm1tjTt37hR4TVHniYiIiIiKC4tZonLA29sbTZo0ETsGEREREZHRcAEoIiIiIiIiMjksZonKkczMTNSvXx/169fP9zlaXdvr2h8RERERkbFwmjFROSIIAu7evat5b2h7XfsjIiIiIjIWjswSERERERGRyWExS0RERERERCaHxSwRERERERGZHBazREREREREZHJYzBIREREREZHJ4WrGROWIRCKBl5eX5r2h7XXtj4iIiIjIWFjMEpUj1tbWiIiIMFp7XfsjIiIiIjIW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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig = plotForMoSA.plot_corner(levels_sig=[0.997, 0.95, 0.68], bins=20, quantiles=(0.16, 0.5, 0.84), burn_in=1100)\n", + "#plt.savefig('') \n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### PLOT Spectrum and Residuals" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ForMoSA - Best fit and residuals plot\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/ppalmabifani/opt/anaconda3/envs/exo_formosa_multi_pip2/lib/python3.11/site-packages/ForMoSA/plotting/plotting_class.py:723: UserWarning: No artists with labels found to put in legend. Note that artists whose label start with an underscore are ignored when legend() is called with no argument.\n", + " axr2.legend(frameon=False,handlelength=0)\n" + ] + }, + { + "data": { + "image/png": "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ipiYGK688koOHTpkHmf16tX07duX6OhoYmJi6Nq1K8uWLTPX//HHH/Tp04eIiAhq1arFgAEDyMzMBKC4uJixY8eSlJSE2+2mV69eLF261Nx24cKFKIrCvHnz6NChA263m7PPPpt169aZbfy56n399decddZZuN1uEhISGD58eIWfzdSpU0lOTiY6Opobb7yRoqIiy/qlS5dy4YUXkpCQQGxsLL1792bFihXm+kDXdPv27QwbNozk5GSioqI466yz+Omnnyrsi+TUQgqn0wgx3kkikUgkEol/CgoKiIqKqpG/goKCoPpotP/yyy8pLi6usO2ECRMYMWIEq1evZtSoUVx11VVs3LgRgNLSUgYMGEB0dDSLFi3ijz/+ICoqiosvvpiSkhIAXnvtNe644w5uueUW1q5dy9y5c2nWrBmAKUxmzpzJgQMHLEJl27ZtfPbZZ3z++eesWrUKr9fLsGHDOHr0KL/++is//vgjO3bsYOTIkeY2o0aNon79+ixdupTly5fz0EMPERISAsCqVau44IILaNOmDX/99Re///47Q4YMwePxAPDAAw/w2Wef8c4777BixQqaNWvGgAEDOHr0qOV6jBs3jmnTprF06VISExMZMmQIpaWlfq/dvHnzGD58OIMGDWLlypUsWLCA7t27B7zWc+bMYdKkSUyePJlly5ZRt25dXn31VUub3NxcRo8eze+//87ff/9N8+bNGTRoELm5uRVe07y8PAYNGsSCBQtYuXIlF198MUOGDGHPnj0B+yM5xVD/gWRnZ6uAmp2dXdNdqZS0tDQVUAH14MGDNd0diUQikUhOefLy8sxn58n+y8vLC7qfn376qVqrVi3V7Xar55xzjjp+/Hh19erVljaAetttt1mW9ejRQx0zZoyqqqr63nvvqS1btlS9Xq+5vri4WA0PD1d/+OEHVVVVNSUlRX344YcD9gNQv/jiC8uyiRMnqiEhIWp6erq5bP78+arT6VT37NljLlu/fr0KqEuWLFFVVVWjo6PVWbNm+T3O1VdfrZ577rl+1+Xl5akhISHqBx98YC4rKSlRU1JS1GeeeUZVVVX95ZdfVED96KOPzDYZGRlqeHi4+vHHH6uqqqozZ85UY2NjzfU9e/ZUR40aFfDc7fTs2VO9/fbbLct69OihduzYMeA2Ho9HjY6OVr/++mtzmb9r6o+2bduqL730UtD9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ERER5azAwEBvF4FymEtZ9TIyMrB3715s2rQJmzdvxh9//IG7d++iVKlS6Ny5s01+e2d88803GDFiBObOnYtGjRph5syZaNu2LY4fP47ixYvbbJ+SkoLWrVujePHi+P7771GyZEmcO3cOhQsXdvm1iYiIiIhcFRAQ4O0ikBc4HTg99dRT2L59OxISElCiRAnExMTgo48+QkxMjDlNoztiY2MxYMAA9O3bFwAwd+5c/PLLL1iwYAHefvttm+0XLFiAmzdvYvv27fD39wcAREdHu/36eZXcy8QeJyIiIqKc07RpU28XgbzA6cCpcOHC+OCDDxATE4NKlSp55MVTUlKwb98+jB492nyfj48PWrVqhR07dug+Z9WqVWjcuDEGDx6MH3/8EREREejZsyfeeustm2wnquTkZCQnJ5tvx8fHe6T8RERERPTgiYyM9HYRyAucDpyWLl3q8Re/fv060tPTbQ6+yMhI/P3337rPOXPmDH777Tf06tULq1evxqlTpzBo0CCkpqZi/Pjxus+ZOnUqJk6c6PHyexN7nIiIiIi8IygoyNtFIC9wKjnEsmXLnN7hhQsX8Mcff7hdIEcyMjJQvHhxfP7556hfvz66d++OMWPGYO7cuYbPGT16NO7cuWP+uXDhQraVj4iIiIjyNwZODyanAqc5c+agWrVqmD59Oo4dO2bz+J07d7B69Wr07NkT9erVw40bN5x68WLFisHX1xdXr17V3H/16lVERUXpPuehhx5C5cqVNcPyqlWrhitXriAlJUX3OYGBgQgNDdX85HXscSIiIiLyDmbUezA5FTht2bIF77//PjZs2ICaNWsiNDQUlSpVQq1atVCqVCkULVoU/fr1Q5kyZXDkyBHzasmOBAQEoH79+ti4caP5voyMDGzcuNEw936TJk1w6tQpZGRkmO87ceIEHnroIWY4ISIiIqJsxx6nB5PTc5w6dOiADh064Pr169i2bRvOnTuHe/fuoVixYnj44Yfx8MMP2ywM5owRI0agd+/eaNCgARo2bIiZM2fi7t275ix7L730EkqWLImpU6cCAF577TV8+umnGDZsGF5//XWcPHkSU6ZMwdChQ11+7fyCPU5EREREOYeB04PJpXWcADG8rlOnTh4rQPfu3XHt2jWMGzcOV65cQd26dbF27Vpzwojz589rArLSpUtj3bp1GD58OGrXro2SJUti2LBheOuttzxWpryAwRIRERGRd9SuXdvbRSAvcDlwyg5DhgzBkCFDdB/bvHmzzX2NGzfGzp07s7lUeQeDKCIiIqLst337duzfvx8dO3b0dlHIC3JF4ESuY7BERERElLMaN25sOA+f8j/XJyVRrsMgioiIiIgoezFwIiIiIiIicsDlwOn+/fuGj12+fDlLhSHncR0nIiIiIqKc43LgVK9ePRw8eNDm/uXLlzPDiJcwcCIiIiIiyl4uB04tWrTAo48+ivfffx8AcPfuXfTp0wcvvvgi/vvf/3q8gKSPwRIRERERUc5xOave7Nmz8fTTT+Pll1/Gzz//jMuXLyM4OBi7d+9GzZo1s6OM5ACDKCIiIiKi7OVWOvKnnnoKXbp0wZw5c+Dn54effvqJQRMREREREeVbLg/VO336NBo3boyff/4Z69atw6hRo9ChQweMGjUKqamp2VFG0sHkEEREREREOcflwKlu3booV64cDh06hNatW+Pdd9/Fpk2bsGLFCjRs2DA7ykhERERERORVLgdOs2fPxrJly1C4cGHzfY899hgOHDiAevXqebJsZAd7nIiIiIiIco7LgdOLL76oe39ISAi++OKLLBeIiIiIiIgot3E5OcRXX31l+JjJZDIMrCj7sMeJiIiIiCh7uRw4DRs2THM7NTUVSUlJCAgIQMGCBRk45RAGS0REREREOcfloXq3bt3S/CQmJuL48eN4/PHHsXTp0uwoIznAIIqIiIiIKHu5HDjpqVSpEqZNm2bTG0XZh8ESEREREVHO8UjgBAB+fn64dOmSp3ZHLmAQRURERESUvVye47Rq1SrNbUVRcPnyZXz66ado0qSJxwpGRERERESUW7gcOHXq1Elz22QyISIiAk888QRmzJjhqXKRA1zHiYiIiIgo57gcOGVkZGRHOYiIiIiIiHItj81xopzFHiciIiIiopzjVI/TiBEjnN5hbGys24UhIiIiIiLKjZwKnA4cOODUztjz4R383ImIiIiIspdTgdOmTZuyuxzkIgZLREREREQ5x+k5TmfOnIGiKNlZFnITgygiIiIiouzldOBUqVIlXLt2zXy7e/fuuHr1arYUihxjcggiIiIiopzjdOBk3du0evVq3L171+MFIiIiIiIiym2YjjyPYo8TEREREVHOcTpwMplMNhV0VtiJiIiIiOhB4FRWPUAM1evTpw8CAwMBAPfv38fAgQNRqFAhzXYrVqzwbAnJIQawRERERETZy+nAqXfv3prbL7zwgscLQ85jsERERERElHOcDpwWLlyYneWgLGAQRURERESUvZgcIo9isERERERElHNyReA0a9YsREdHIygoCI0aNcLu3budet6yZctgMpnQqVOn7C1gLscgioiIiIgoe3k9cPrmm28wYsQIjB8/Hvv370edOnXQtm1bxMXF2X3e2bNnMXLkSDRt2jSHSkpERERERA8qrwdOsbGxGDBgAPr27Yvq1atj7ty5KFiwIBYsWGD4nPT0dPTq1QsTJ05E+fLlc7C0uQfXcSIiIiIiyjleDZxSUlKwb98+tGrVynyfj48PWrVqhR07dhg+b9KkSShevDj69+/v1OskJycjPj5e80NEREREROQsrwZO169fR3p6OiIjIzX3R0ZG4sqVK7rP2bZtG7744gvMmzfP6deZOnUqwsLCzD+lS5fOUrlzA/Y4ERERERHlHK8P1XNFQkICXnzxRcybNw/FihVz+nmjR4/GnTt3zD8XLlzIxlISEREREVF+4/Q6TtmhWLFi8PX1xdWrVzX3X716FVFRUTbbnz59GmfPnkX79u3N92VkZAAA/Pz8cPz4cVSoUMHmeYGBgQgMDPRw6XMP9jgREREREWUvr/Y4BQQEoH79+ti4caP5voyMDGzcuBGNGze22b5q1ao4fPgwDh48aP7p0KEDYmJicPDgwXwxBM9ZDJaIiIiIiHKOV3ucAGDEiBHo3bs3GjRogIYNG2LmzJm4e/cu+vbtCwB46aWXULJkSUydOhVBQUGoWbOm5vmFCxcGAJv7iYiIiIiIPMXrgVP37t1x7do1jBs3DleuXEHdunWxdu1ac8KI8+fPw8cnT03FyhHscSIiIiIiyjleD5wAYMiQIRgyZIjuY5s3b7b73EWLFnm+QHkMgygiIiIiouzFrhwiIiIiIiIHGDjlUexlIiIiIiLKOQyciIiIiIiIHGDglEexx4mIiIiIKOcwcMoHGEQREREREWUvBk5EREREREQOMHDKo9jLRERERESUcxg4EREREREROcDAKY9ijxMRERERUc5h4EREREREROQAAyciIiIiIiIHGDjlURyqR0RERESUcxg4EREREREROcDAKY9ijxMRERERUc5h4EREREREROQAA6c8ij1OREREREQ5h4FTPsAgioiIiIgoezFwIiIiIiIicoCBUx7FXiYiIiIiopzDwImIiIiIiMgBBk55FHuciIiIiIhyDgOnfIBBFBERERFR9mLgRERERERE5AADpzyKvUxERERERDmHgRMREREREZEDDJzyKPY4ERERERHlHAZOREREREREDjBwIiIiIiIicoCBUx7FoXpERERERDmHgRMREREREZEDDJzyKPY4ERERERHlHAZO+QCDKCIiIiKi7JUrAqdZs2YhOjoaQUFBaNSoEXbv3m247bx589C0aVMUKVIERYoUQatWrexun1/5+Fj+denp6V4sCRERERFR/uf1wOmbb77BiBEjMH78eOzfvx916tRB27ZtERcXp7v95s2b0aNHD2zatAk7duxA6dKl0aZNG/z77785XHLv8vPzM/+dmprqxZIQEREREeV/Xg+cYmNjMWDAAPTt2xfVq1fH3LlzUbBgQSxYsEB3+8WLF2PQoEGoW7cuqlativnz5yMjIwMbN27M4ZJ7lzw8LyUlxYslISIiIiLK/7waOKWkpGDfvn1o1aqV+T4fHx+0atUKO3bscGofSUlJSE1NRXh4uOE2ycnJiI+P1/zkJ+xxIiIiIiLKXl4NnK5fv4709HRERkZq7o+MjMSVK1ec2sdbb72FEiVKaIIva1OnTkVYWJj5p3Tp0lkqd27DHiciIiIiouzl9aF6WTFt2jQsW7YMP/zwA4KCggy3Gz16NO7cuWP+uXDhQg6WMvuxx4mIiIiIKHv5Od4k+xQrVgy+vr64evWq5v6rV68iKirK7nM//PBDTJs2Db/++itq165td9vAwEAEBgZmuby5FXuciIiIiIiyl1d7nAICAlC/fn1NYgc10UPjxo0Nnzd9+nRMnjwZa9euRYMGDXKiqLkae5yIiIiIiLKXV3ucAGDEiBHo3bs3GjRogIYNG2LmzJm4e/cu+vbtCwB46aWXULJkSUydOhUA8P7772PcuHFYsmQJoqOjzXOhgoODERwc7LX34U0MnIiIiIiIspfXA6fu3bvj2rVrGDduHK5cuYK6deti7dq15oQR58+f1yz2OmfOHKSkpKBr166a/YwfPx4TJkzIyaLnGhyqR0RERESUvUyKoijeLkROi4+PR1hYGO7cuYPQ0FBvF8dt6lpOnTt3xooVK7xcGiIiIiLKjfJL3dfb8nRWPRLY40RERERElL0YOOUDnONERERERJS9GDjlAxUqVPB2EYiIiIiI8jWvJ4cg923btg3/93//hylTpni7KERERERE+RqTQ3CCHBERERHlY6z7egaH6hERERERETnAwImIiIiIiMgBBk5EREREREQOMHAiIiIiIiJygIETERERERGRAwyciIiIiIiIHGDgRERERERE5AADJyIiIiIiIgcYOBERERERETng5+0CeIOiKADEKspERERERPmZWudV68DkngcycEpISAAAlC5d2sslISIiIiLKGQkJCQgLC/N2MfIsk/IAhp4ZGRm4dOkSQkJCYDKZvF0cIiIiIqJsoygKEhISUKJECfj4cKaOux7IwImIiIiIiMgVDDmJiIiIiIgcYOBERERERETkQJ4LnCZMmACTyaT5qVq1qreLRURERERE+ViezKpXo0YN/Prrr+bbfn558m0QEREREVEekScjDj8/P0RFRXm7GERERERE9IDIk4HTyZMnUaJECQQFBaFx48aYOnUqypQpY7h9cnIykpOTzbczMjJw8+ZNFC1alOnIiYiIiChfYzpyz8hz6cjXrFmDxMREVKlSBZcvX8bEiRPx77//4siRIwgJCdF9zoQJEzBx4sQcLikRERERUe5x4cIFlCpVytvFyLPyXOBk7fbt2yhbtixiY2PRv39/3W2se5zu3LmDMmXK4MKFCwgNDc2ponrWqVOA+n7btwdGjvRueYiIiIgoV4qPj0fp0qVx+/ZthIWFebs4eVaeHKonK1y4MCpXroxTp04ZbhMYGIjAwECb+0NDQ/Nu4BQcDPj6ir+DgoC8+j6IiIiIKEdwikrW5PlBjomJiTh9+jQeeughbxeFiIiIiIjyqTwXOI0cORJbtmzB2bNnsX37dnTu3Bm+vr7o0aOHt4uWs/L2CEsiIiIiojwlzw3Vu3jxInr06IEbN24gIiICjz/+OHbu3ImIiAhvF817GEQREREREWWrPBc4LVu2zNtFyB3kYImBExERERFRtspzQ/WIiIiIiIhyWpZ6nFJTU3HlyhUkJSUhIiIC4eHhnioXOcIeJyIiIiKiHONyj1NCQgLmzJmD5s2bIzQ0FNHR0ahWrRoiIiJQtmxZDBgwAHv27MmOshIREREREXmFS4FTbGwsoqOjsXDhQrRq1QorV67EwYMHceLECezYsQPjx49HWloa2rRpgyeffBInT57MrnITe5yIiIiIiHKMS0P19uzZ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WrRogbt372LPnj3YunUrKleujIiICDRv3tw8z2nz5s0oX748ypQpAwDYt28f2rdvjzJlyiAkJATNmzcHIOb0AEDdunVRrVo1c6/Tli1bEBcXh+eeew4AcOjQISQmJqJo0aIIDg42//zzzz+6ySfu3r2L06dPo3///prt3333XZvta9eubf77oYceAgDzMMLjx4+jYcOGmu2tb9sj77tQoUIIDQ0171vPvXv3EBQU5PT+ZTVq1ICPj+UyGRkZiVq1aplv+/r6omjRojavX6BAASQlJbn1mkRElHv5ebsAREQPuooVK6JUqVLYtGkTbt26ZQ6CSpQogdKlS2P79u3YtGkTnnjiCQAiiGnbti3atm2LxYsXIyIiAufPn0fbtm2RkpJi3m+vXr2wZMkSvP3221iyZAmefPJJFC1aFIDI3Gc9t0qlzjeSJSYmAhDzkxo1aqR5zNfXV3Pb39/f/LfJZAIg5l15grxvdf/29l2sWDHcunXL4X7T09Odei1nXv/mzZuIiIhw+JpERJS3MHAiIsoFYmJisHnzZty6dQtvvvmm+f5mzZphzZo12L17N1577TUAwN9//40bN25g2rRpKF26NABosvKpevbsiXfeeQf79u3D999/j7lz55ofq1evHq5cuQI/Pz9NUgQjkZGRKFGiBM6cOYNevXq5/T6rVKmCPXv2aO6zvh0QEKAbyLjj4Ycfxl9//WVz/9WrVzW3z5w545HXA4AjR47YpJInIqK8j0P1iIhygZiYGGzbtg0HDx409zgBQPPmzfHZZ58hJSXFnBiiTJkyCAgIwCeffIIzZ85g1apVmDx5ss0+o6Oj8dhjj6F///5IT09Hhw4dzI+1atUKjRs3RqdOnbB+/XqcPXsW27dvx5gxY3SDMEAkZpg6dSr+97//4cSJEzh8+DAWLlyI2NhYp9/n66+/jtWrVyM2NhYnT57EZ599hjVr1ph7ptRy//PPPzh48CCuX7+O5ORkp/dvrW3bttixY4dNIHblyhVMmjQJZ86cwfLly/H111/j1q1b+Pvvv91+LQBISkrCvn370KZNmyzth4iIch8GTkREuUBMTAzu3buHihUrIjIy0nx/8+bNkZCQYE5bDgARERFYtGgRvvvuO1SvXh3Tpk3Dhx9+qLvfXr164dChQ+jcuTMKFChgvt9kMmH16tVo1qwZ+vbti8qVK+P555/HuXPnNK8ve/nllzF//nwsXLgQtWrVQvPmzbFo0SKUK1fO6ffZpEkTzJ07F7GxsahTpw7Wrl2L4cOHa+YhPfvss3jyyScRExODiIgILF261On9W3vqqafg5+eHX3/9VXN/zZo1ceLECdSoUQNjx47F/PnzERAQgJEjR7r9WgDw448/okyZMmjatGmW9kNERLmPSVEUxduFICKiB9eAAQPw999/Z1sK71mzZmHVqlVYt24dALGO08qVK3Hw4EGPv9ajjz6KoUOHomfPnh7fNxEReRfnOBERUY768MMP0bp1axQqVAhr1qzBl19+qVlI19NeffVV3L59GwkJCQgJCcm217l+/Tq6dOmCHj16ZNtrEBGR97DHiYiIclS3bt2wefNmJCQkoHz58nj99dcxcODAHHv97OxxIiKi/IuBExERERERkQNMDkFEREREROQAAyciIiIiIiIHGDgRERERERE5wMCJiIiIiIjIAQZOREREREREDjBwIiIiIiIicoCBExERERERkQMMnIiIiIiIiBxg4EREREREROTA/wPuJoUtLe2MPAAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, ax, axr, axr2 = plotForMoSA.plot_fit(figsize=(10, 5), uncert='no')\n", + "\n", + "# You can modify the different axes and includ further plotting features\n", + "axr.set_ylim(-5,5)\n", + "\n", + "#plt.savefig('')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### PLOT Chains of posteriors" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ForMoSA - Posteriors chains for each parameter\n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, axs = plotForMoSA.plot_chains(figsize=(10,6))\n", + "#axs[i, j] #i=cols, j=0,1\n", + "#plt.savefig('')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Access information\n", + "\n", + "You can access different parametes since we are working with a class\n" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [], + "source": [ + "posteriors_chains = plotForMoSA.posterior_to_plot\n", + "posteriors_names = plotForMoSA.posteriors_names" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "exo_formosa_multi3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/_build/doctrees/nbsphinx/tutorials/exorem_info.ipynb b/docs/_build/doctrees/nbsphinx/tutorials/exorem_info.ipynb new file mode 100644 index 0000000..4e848cc --- /dev/null +++ b/docs/_build/doctrees/nbsphinx/tutorials/exorem_info.ipynb @@ -0,0 +1,140 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Exo-REM\n", + "\n", + "Example on how to access to the atmospheric grid info to check the parameters and their ranges.\n", + "\n", + "### Imports" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "import xarray as xr\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Open the grid\n", + "\n", + "You can check the free parameters names, ranges and units together with the wavelength range and spectral resolution." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Dimensions: (wavelength: 29922, par1: 33, par2: 5, par3: 4, par4: 15)\n", + "Coordinates:\n", + " * wavelength (wavelength) float64 0.6667 0.6667 0.6667 ... 245.4 248.4 251.6\n", + " * par1 (par1) float64 400.0 450.0 500.0 ... 1.9e+03 1.95e+03 2e+03\n", + " * par2 (par2) float64 3.0 3.5 4.0 4.5 5.0\n", + " * par3 (par3) float64 -0.5 0.0 0.5 1.0\n", + " * par4 (par4) float64 0.1 0.15 0.2 0.25 0.3 ... 0.6 0.65 0.7 0.75 0.8\n", + "Data variables:\n", + " grid (wavelength, par1, par2, par3, par4) float64 ...\n", + "Attributes:\n", + " key: ['par1', 'par2', 'par3', 'par4']\n", + " par: ['teff', 'logg', 'mh', 'co']\n", + " title: ['Teff', 'log(g)', '[M/H]', 'C/O']\n", + " unit: ['(K)', '(dex)', '', '']\n", + " res: [29999.50000004 29998.49999991 29997.50000002 ... 80.5\\n ...\n" + ] + } + ], + "source": [ + "grid_path = '/EXOREM_native.nc'\n", + "ds = xr.open_dataset(grid_path, decode_cf=False)\n", + "print(ds)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Get a spectrum for specific values" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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siRQb9680XgAKhEREZEpvXz50miPlpElgVI9FuDly5fS87GIiIiITCE8PBzFixdP8bFE+pIlgVJdtrO1tWUCRUREROnCmN2G2ImciIiISE9MoIiIiIj0xASKiIiISE9MoIiIiIj0xASKiIiISE9MoIiIiIj0xAQqGzp+/DgUCgWOHj0qdyhERESZkkIIIdJ7peHh4bCzs0NYWBjHgZJB4nEwZDj8RERE6coUeQfPQBERERHpiQlUNrF//354enryjBMREZERyPIoF0p/nTp1AgDUr19f5kiIiIgyP56BymZat24tdwhERESZHhOobO7MmTNQKpVyh0FERJSpMIHK5po2bYpNmzbJHQYREVGmwgSK4O3tLXcIREREmQoTKCIiIiI9MYEiIiIi0hMTKMKLFy/kDoGIiChTYQJFuHv3rtwhEBERZSpMoIiIiIj0xASKiIiISE9MoIiIiIj0xASKiIiISE9MoIiIiIj0xASKiIiISE9MoIiIiIj0xASKiIiISE9MoIiIiIj0xASKiIiISE9MoIiIiIj0xASKiIiISE9MoIiIiIj0xAQqAzl//jzOnz8vdxhERESUCgu5A6AvPn36hMaNGwMAoqKikCtXLpkjIiIiouTwDFQGERERIf0/KipKxkiIiIgoNUygiIiIiPTEBIqIiIhIT0ygsqCAgAC0adMGPj4+codCRESUJbETeQakVCrTtPw333yDixcv4ujRoxBCGCkqIiIiUuEZqAyoTZs2Bi97+/ZtXLx4Ua0srQkZERERqWMClQFdv37d4GWrV6+uUbZgwYK0hENERERJMIHK4g4dOoTp06fLHQYREVGWwgQqi2vfvr3cIRAREWU5TKCIiIiI9MQEKoNQKBRyh0BEREQ6YgJFREREpCcmUERERER6YgJFREREpCcmUAQAuH//vtwhEBERZRpMoLIApVKJs2fPIjQ01OA2Dh48aMSIiIiIsjYmUFnA5s2b4ebmBhcXF7lDISIiyhaYQGUBu3btAgA8e/ZM3kCIiIiyCSZQGURERISs6+c4VERERLpjApVBPHr0yOBlhRBGjISIiIhSwwQqg5D7DNDDhw9lXT8REVFmwgQqCzDGGaiNGzcaIRIiIqLsgQlUFsBLeEREROmLCRQRERGRnphAZQE8A0VERJS+mEBlEGnpRM4EioiIKH0xgcoCmEARERGlLyZQGQST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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Open the grid \n", + "grid = ds['grid']\n", + "\n", + "# get wavelength \n", + "wave = grid['wavelength'].values\n", + "\n", + "# for Exo-REM par1=Teff, par2=logg, par3=[M/H], par4=C/O\n", + "# get flux by selecting a value for each parameter\n", + "flux = grid.sel(par1=1700,par2=4.0, par3=0., par4=0.55, method=\"nearest\")\n", + "\n", + "# Plot the spectrum\n", + "plt.figure(figsize=(7,3))\n", + "plt.plot(wave, flux*wave, 'k')\n", + "plt.xlabel('Wavelength (µm)')\n", + "plt.ylabel('Flux')\n", + "plt.xlim(0.5,5) \n", + "plt.yticks([])\n", + "plt.title('Exo-REM at Teff=1700K, logg=4, and solar [M/H] and C/O')\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.7.13 ('exo_formosa')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.9" + }, + "vscode": { + "interpreter": { + "hash": "9aec1e17db1a1c759b18bf85d14c335cdcfb4080f740d60b236f2747bc3cb68f" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/_build/doctrees/nbsphinx/tutorials/inputs.ipynb b/docs/_build/doctrees/nbsphinx/tutorials/inputs.ipynb new file mode 100644 index 0000000..6162c18 --- /dev/null +++ b/docs/_build/doctrees/nbsphinx/tutorials/inputs.ipynb @@ -0,0 +1,43 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# INPUTS\n", + "\n", + "## Observations (.fits)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "plaintext" + } + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Config file (.ini)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/_build/doctrees/nbsphinx/tutorials_demoabpic_11_1.png b/docs/_build/doctrees/nbsphinx/tutorials_demoabpic_11_1.png new file mode 100644 index 0000000..025118f Binary files /dev/null and b/docs/_build/doctrees/nbsphinx/tutorials_demoabpic_11_1.png differ diff --git a/docs/_build/doctrees/nbsphinx/tutorials_demoabpic_13_2.png b/docs/_build/doctrees/nbsphinx/tutorials_demoabpic_13_2.png new file mode 100644 index 0000000..cf36f92 Binary files /dev/null and b/docs/_build/doctrees/nbsphinx/tutorials_demoabpic_13_2.png differ diff --git a/docs/_build/doctrees/nbsphinx/tutorials_demoabpic_15_1.png b/docs/_build/doctrees/nbsphinx/tutorials_demoabpic_15_1.png new file mode 100644 index 0000000..24963d4 Binary files /dev/null and b/docs/_build/doctrees/nbsphinx/tutorials_demoabpic_15_1.png differ diff --git a/docs/_build/doctrees/nbsphinx/tutorials_exorem_info_5_0.png b/docs/_build/doctrees/nbsphinx/tutorials_exorem_info_5_0.png new file mode 100644 index 0000000..76657a5 Binary files /dev/null and b/docs/_build/doctrees/nbsphinx/tutorials_exorem_info_5_0.png differ diff --git a/docs/_build/doctrees/nested_sampling.doctree b/docs/_build/doctrees/nested_sampling.doctree new file mode 100644 index 0000000..2073cc2 Binary files /dev/null and b/docs/_build/doctrees/nested_sampling.doctree differ diff --git a/docs/_build/doctrees/plotting.doctree b/docs/_build/doctrees/plotting.doctree new file mode 100644 index 0000000..56d38e6 Binary files /dev/null and b/docs/_build/doctrees/plotting.doctree differ diff --git a/docs/_build/doctrees/tutorials/atmospheric_grid_info.doctree b/docs/_build/doctrees/tutorials/atmospheric_grid_info.doctree new file mode 100644 index 0000000..6e0dc85 Binary files /dev/null and b/docs/_build/doctrees/tutorials/atmospheric_grid_info.doctree differ diff --git a/docs/_build/doctrees/tutorials/demoabpic.doctree b/docs/_build/doctrees/tutorials/demoabpic.doctree new file mode 100644 index 0000000..41e1655 Binary files /dev/null and b/docs/_build/doctrees/tutorials/demoabpic.doctree differ diff --git a/docs/_build/doctrees/tutorials/exorem_info.doctree b/docs/_build/doctrees/tutorials/exorem_info.doctree new file mode 100644 index 0000000..d11ef3f Binary files /dev/null and b/docs/_build/doctrees/tutorials/exorem_info.doctree differ diff --git a/docs/_build/doctrees/tutorials/inputs.doctree b/docs/_build/doctrees/tutorials/inputs.doctree new file mode 100644 index 0000000..f4e7014 Binary files /dev/null and b/docs/_build/doctrees/tutorials/inputs.doctree differ diff --git a/docs/build/html/.buildinfo b/docs/_build/html/.buildinfo similarity index 82% rename from docs/build/html/.buildinfo rename to docs/_build/html/.buildinfo index 5fdb911..2da4d42 100644 --- a/docs/build/html/.buildinfo +++ b/docs/_build/html/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 806cb0a2c1bc29933a5079b8fcb3af9f +config: 3d69bd81622fe4392ef94600d12c6fdb tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/source/ForMoSA.png b/docs/_build/html/_images/ForMoSA.png similarity index 100% rename from docs/source/ForMoSA.png rename to docs/_build/html/_images/ForMoSA.png diff --git a/docs/_build/html/_images/tutorials_demoabpic_11_1.png b/docs/_build/html/_images/tutorials_demoabpic_11_1.png new file mode 100644 index 0000000..025118f Binary files /dev/null and b/docs/_build/html/_images/tutorials_demoabpic_11_1.png differ diff --git a/docs/_build/html/_images/tutorials_demoabpic_13_2.png b/docs/_build/html/_images/tutorials_demoabpic_13_2.png new file mode 100644 index 0000000..cf36f92 Binary files /dev/null and b/docs/_build/html/_images/tutorials_demoabpic_13_2.png differ diff --git a/docs/_build/html/_images/tutorials_demoabpic_15_1.png b/docs/_build/html/_images/tutorials_demoabpic_15_1.png new file mode 100644 index 0000000..24963d4 Binary files /dev/null and b/docs/_build/html/_images/tutorials_demoabpic_15_1.png differ diff --git a/docs/_build/html/_images/tutorials_exorem_info_5_0.png b/docs/_build/html/_images/tutorials_exorem_info_5_0.png new file mode 100644 index 0000000..76657a5 Binary files /dev/null and b/docs/_build/html/_images/tutorials_exorem_info_5_0.png differ diff --git a/docs/build/html/_modules/ForMoSA/adapt/adapt_grid.html b/docs/_build/html/_modules/ForMoSA/adapt/adapt_grid.html similarity index 77% rename from docs/build/html/_modules/ForMoSA/adapt/adapt_grid.html rename to docs/_build/html/_modules/ForMoSA/adapt/adapt_grid.html index f3cbafa..984614e 100644 --- a/docs/build/html/_modules/ForMoSA/adapt/adapt_grid.html +++ b/docs/_build/html/_modules/ForMoSA/adapt/adapt_grid.html @@ -1,22 +1,24 @@ - + - ForMoSA.adapt.adapt_grid — ForMoSA documentation - - + ForMoSA.adapt.adapt_grid — ForMoSA 2.0.0 documentation + + + + - - - - - - + + + + + + @@ -33,9 +35,6 @@ ForMoSA -
- 1.0.3 -
@@ -44,9 +43,10 @@