Quick start look into sBART#

The sBART pipeline provides the user with all the necessary pieces to construct a template matching algorithm, by selecting the Stellar and Telluric templates, the underlying RV model and the method with which new, tentative RVs, are given to the model.

In this Section we showcase a small example of building a RV model from the different parts of SBART. At the root of the repository it is also possible to find a sbart_example.py which contains the code from this notebook as a single python script

Note: it is highly advised to not run SBART inside jupyter notebooks, as one might run into issues due to terminal logging.

Specifying the input and output paths#

Note: the disk files are not present in the GB repository due to space limitations

[3]:
from SBART.Instruments import ESPRESSO, HARPS
from pathlib import Path


# Either define the path to a text file where each line is a complete path to a S2D file
input_filepath = ""

# or give a list of disk files
input_filepath = [i.as_posix() for i in Path("/home/amiguel/phd/tools/sBART_private/tests/resources").glob("*.fits")]

instrument = ESPRESSO

# Folder in which SBART will store its outputs
storage_path = Path("/home/amiguel/phd/tools/sBART_private/tests/documentation_outputs")
[4]:
# To check the available configurations of ESPRESSO data:
ESPRESSO.config_help()
Configurations:

Name:: bypass_QualCheck
        Description:: None
        Mandatory:: False
        Default value:: False
        Constraints:: Value from dtype <(<class 'bool'>,)>

Name:: open_without_BervCorr
        Description:: Ensure that the Frame is not BERV corrected, independently of correction being applied or not in the official pipeline
        Mandatory:: False
        Default value:: False
        Constraints:: Value from dtype <(<class 'bool'>,)>

Name:: apply_FluxCorr
        Description:: Apply the blue-red flux correction due to the wavelength dependence of the atmospheric extinction. Only available on data from ESO pipeline (ESPRESSO)
        Mandatory:: False
        Default value:: False
        Constraints:: Value from dtype <(<class 'bool'>,)>

Name:: use_air_wavelengths
        Description:: Use air wavelengths, instead of the vacuum ones
        Mandatory:: False
        Default value:: False
        Constraints:: Value from dtype <(<class 'bool'>,)>

Name:: apply_FluxBalance_Norm
        Description:: None
        Mandatory:: False
        Default value:: False
        Constraints:: Value from dtype <(<class 'bool'>,)>

Name:: reject_order_percentage
        Description:: None
        Mandatory:: False
        Default value:: 0.25
        Constraints:: Value inside interval <(0, 1)>; Edges: True

Name:: minimum_order_SNR
        Description:: SNR threshold under which the spectral order is rejected
        Mandatory:: False
        Default value:: 5
        Constraints:: Value inside interval <[0, inf]>; Edges: True

Name:: bypass_ST_designation
        Description:: None
        Mandatory:: False
        Default value:: None
        Constraints:: Value from list <(None, 'S2D', 'S1D')>

Name:: Telluric_Corrected
        Description:: The Frame was already corrected from telluric features
        Mandatory:: False
        Default value:: False
        Constraints:: Value from dtype <(<class 'bool'>,)>

Name:: UseMolecfit
        Description:: None
        Mandatory:: False
        Default value:: False
        Constraints:: Value from dtype <(<class 'bool'>,)>

Name:: use_old_pipeline
        Description:: Use data from the old pipeline. Only available to selected instruments
        Mandatory:: False
        Default value:: False
        Constraints:: Value from dtype <(<class 'bool'>,)>

Name:: SCIRED_CHECK_IS_FATAL
        Description:: Automatically reject frames with QC SCIRED CHECK = 0
        Mandatory:: False
        Default value:: True
        Constraints:: Value from dtype <(<class 'bool'>,)>


Configure the pipeline#

[5]:
from SBART.utils.units import meter_second

rv_method = "classical"  # Either classical or Laplace

# Define the step that will be used for numerical calculations near max/min points
RVstep = 0.1 * meter_second

# Define the window, around the CCF RV, inside which the models can search for the optimal RV
RV_limits = [200 * meter_second, 200 * meter_second]


# List with orders to "throw" away
orders_to_skip = []

# Number of cores to use
N_cores = 10

Configure the different settings of SBART#

[6]:
# For the S2D loading stage
inst_options = {}

# For the creation of the Telluric Model (i.e. the "template generator")
telluric_model_configs = {"CREATION_MODE": "telfit"}

# For the creation of the individual Telluric templates
telluric_template_genesis_configs = {}


# For the creation of the Stellar Model (i.e. the "template generator")

stellar_model_configs = {}

# For the creation of the individual Stellar templates
stellar_template_genesis_configs = {"MINIMUM_NUMBER_OBS": 2}


confsRV = {"MEMORY_SAVE_MODE": True}

Setting up the library#

By default, SBART’s logger is disabled and it will not:

  • print information to the terminal

  • store a log file to disk

To do so, we must enable the logging interface:

[7]:
from SBART.outside_tools.create_logger import setup_SBART_logger

setup_SBART_logger(
    storage_path=storage_path / "logs",
    RV_method=rv_method,
    instrument=instrument,
    log_to_terminal=False,  # Set to True if you want to have logs showing on the terminal,
    write_to_file=True,
)

Loading data#

We start by “pointing” sBART towards a few observations:

[8]:
from SBART.data_objects import DataClassManager

manager = DataClassManager()
manager.start()

data = manager.DataClass(
    input_filepath,
    storage_path=storage_path,
    instrument=instrument,
    instrument_options=inst_options,
)

Pre-processing the data#

Removing activity-sensitive lines

[9]:
from SBART.Quality_Control.activity_indicators import Indicators

inds = Indicators()
data.remove_activity_lines(inds)

Creating a telluric model to remove those features#

[10]:
from SBART.template_creation.TelluricModel import TelluricModel

ModelTell = TelluricModel(
    usage_mode="individual",
    user_configs=telluric_model_configs,
    root_folder_path=storage_path,
)

ModelTell.Generate_Model(
    dataClass=data,
    telluric_configs=telluric_template_genesis_configs,
    force_computation=False,
    store_templates=True,
)
data.remove_telluric_features(ModelTell)

Creating the stellar templates#

[11]:
from SBART.template_creation.StellarModel import StellarModel

ModelStell = StellarModel(user_configs=stellar_model_configs, root_folder_path=storage_path)

When creating the stellar templates we can also reject, temporarily, some observations. They will not be used to create the stellar template, but they will still be used during the RV extraction.

[12]:
from SBART.utils.spectral_conditions import Empty_condition

StellarTemplateConditions = Empty_condition()

ModelStell.Generate_Model(
    data,
    stellar_template_genesis_configs,
    StellarTemplateConditions,
    force_computation=False,
)

ModelStell.store_templates_to_disk(storage_path)

data.ingest_StellarModel(ModelStell)

Extracting Radial Velocities#

Lastly, we only need to define the RV model that we want to use

[13]:
from SBART.rv_calculation.RV_Bayesian.RV_Bayesian import RV_Bayesian
from SBART.rv_calculation.rv_stepping.RV_step import RV_step
from SBART.Samplers import chi_squared_sampler, Laplace_approx
import os


if rv_method == "classical":
    sampler = chi_squared_sampler(RVstep, RV_limits)
    rv_model = RV_step(
        processes=N_cores,
        RV_configs=confsRV,
        sampler=sampler,
    )

    orders = orders_to_skip
elif rv_method == "Laplace":
    sampler = Laplace_approx(RVstep, RV_limits)
    rv_model = RV_Bayesian(
        processes=N_cores,
        RV_configs=confsRV,
        sampler=sampler,
    )
    orders = os.path.join(storage_path, "Iteration_0/RV_step")
else:
    raise Exception

# warning is raised as this was ran over simulated data and we used a non-existing target name
rv_model.run_routine(data, storage_path, orders)
/home/amiguel/phd/tools/sBART_private/src/SBART/data_objects/RV_cube.py:792: RuntimeWarning: invalid value encountered in divide
  empty_array /= np.max(empty_array, axis=1)[:, None]  # normalize across the orders
/home/amiguel/phd/tools/sBART_private/src/SBART/utils/math_tools/weighted_mean.py:13: RuntimeWarning: invalid value encountered in divide
  final_RV = np.nansum(np.multiply(weights, orders_RV), axis=1) / sum_weights
/home/amiguel/phd/tools/sBART_private/src/SBART/utils/math_tools/weighted_mean.py:17: RuntimeWarning: divide by zero encountered in divide
  final_error = np.sqrt(1 / (sum_weights))
/home/amiguel/phd/tools/sBART_private/src/SBART/data_objects/RV_cube.py:792: RuntimeWarning: invalid value encountered in divide
  empty_array /= np.max(empty_array, axis=1)[:, None]  # normalize across the orders
/home/amiguel/phd/tools/sBART_private/.venv/lib/python3.8/site-packages/matplotlib/axes/_axes.py:1148: RuntimeWarning: All-NaN axis encountered
  miny = np.nanmin(masked_verts[..., 1])
/home/amiguel/phd/tools/sBART_private/.venv/lib/python3.8/site-packages/matplotlib/axes/_axes.py:1149: RuntimeWarning: All-NaN axis encountered
  maxy = np.nanmax(masked_verts[..., 1])