Quick Start & Examples

This guide shows you how to run a basic synthesis with SolRaT. We’ll use the multi-term atom model with a simple constant-property slab atmosphere.

Basic Stokes Profile Synthesis

This example demonstrates a minimal workflow for synthesizing the Stokes profiles of the He I D3 line using a built-in pre-configured model through the public API.

import numpy as np

from solrat.atom_model.model_registry import PreconfiguredModels
from solrat.atom_model.shared.common_api.constant_property_slab import ConstantPropertySlabAtmosphere
from solrat.atom_model.shared.common_api.multi_slab_atmosphere import MultiSlabAtmosphere
from solrat.atom_model.shared.object.angles import Angles
from solrat.atom_model.shared.object.stokes import Stokes
from solrat.atom_model.shared.utility.functions import get_frequencies_from_air_wavelength_range
from solrat.atom_model.shared.utility.log_setup import setup_logging
from solrat.atom_model.shared.utility.plot_stokes_profiles import StokesPlotter


def main():
    """
    This example demonstrates a minimal workflow for synthesizing the Stokes profiles of the He I D3 line
    using a built-in pre-configured model through the public API.

    To run this demo, SolRaT needs to be installed.
    The easiest way is to install SolRaT using "pip install solrat" command.

    You can also clone the repository and run _demos/start_here/demo_basic_stokes_profile_synthesis.py directly.
    The latter is recommended if you plan to extend available models or creating your own.
    """

    # Set up the logger. Use setup_logging(logging.DEBUG) for a verbose logging
    setup_logging()

    # Get a built-in pre-configured model for the D3 transition
    # You can browse PreconfiguredModels to see all available pre-configured transfer models.
    # Additionally, you can configure a transfer model for your own atom.
    # The latter can be easily done by direct analogy to pre-configured models.
    model = PreconfiguredModels.multi_term_atom_HeID3()
    reference_lambda_A_air = model.config.reference_lambda_A_air

    # The calculation itself needs frequency, but we will display the results in air wavelength.
    # Therefore, it is convenient to derive the frequencies from the wavelengths range of interest.
    # Note that SolRaT scales gracefully with the number of frequency points,
    # so feel free to request a high spectral resolution.
    nu = get_frequencies_from_air_wavelength_range(
        lower_wavelength_A=reference_lambda_A_air - 0.3,
        upper_wavelength_A=reference_lambda_A_air + 0.6,
        step_A=5e-3,
    )

    # Set up the observation geometry. See Fig. 5.9 in LL04 for reference
    # In short:
    # chi, theta, and gamma are the Euler angles for the Omega (LOS) vector.
    # chi_B and theta_B are the Euler angles for the magnetic field B vector.
    angles = Angles(
        chi=0,
        theta=np.pi / 4,
        gamma=0,
        chi_B=0,
        theta_B=0,
    )

    # Define the atmosphere parameters
    atmosphere_parameters = model.AtmosphereParameters(
        model_config=model.config,
        magnetic_field_gauss=1000,
        temperature_K=5000,
        delta_v_turbulent_cm_sm1=0,  # non-thermal temperature for additional Gaussian broadening
        macroscopic_velocity_cm_sm1=0,  # Doppler shift, typically used when multiple emission components are modeled
        voigt_a=0,  # Voigt damping coefficient
    )

    # Construct a radiation tensor from the built-in height-stratified parametrization
    # Here we use NLTE J tensor for the height of 30 arcsec above photosphere.
    # Another option is .fill_planck(self, temperature_K) - fill using LTE Planck distribution
    radiation_tensor = model.RadiationTensor.from_model_config(model.config).fill_NLTE_n_w_parametrized(h_arcsec=30)

    # Set up the initial Stokes vector: zero in this case, corresponding to a limb observation
    # Another option is .from_BP(nu_sm1, temperature_K) - fill using LTE Planck distribution
    initial_stokes = Stokes.from_zeros(nu_sm1=nu)

    # Define the atmosphere. Here we use a MultiSlabAtmosphere with a single slab
    atmosphere = MultiSlabAtmosphere(
        ConstantPropertySlabAtmosphere(
            model=model,
            radiation_tensor=radiation_tensor,
            line_delta_tau=0.1,  # optical depth of the slab in the line-center frequency
            continuum_delta_tau=0.001,  # optical depth in the far continuum
            angles=angles,
            atmosphere_parameters=atmosphere_parameters,
        ),
        # Subsequent slabs can be added here
    )

    # Set up a plotter for easier visualization of results
    plotter = StokesPlotter("Stokes profiles for the He I D3 line", reference_lambda_A_air=reference_lambda_A_air)

    # Calculate the emerging Stokes profiles and add them to the plot
    emerging_stokes = atmosphere.forward(initial_stokes=initial_stokes)

    # Plot the emerging Stokes profiles
    plotter.add_stokes(
        nu=nu,
        stokes=emerging_stokes,
        norm=plotter.Norm.MAX_I,  # Normalize using maximum I intensity. Other options: BY_REFERENCE, MAX_IpV_ImV, NONE
        # stokes_reference=initial_stokes # for on-disk observations, used when norm is BY_REFERENCE.
        label="$B=1000$ G",
    )

    # Show the plot
    plotter.show()


if __name__ == "__main__":
    main()

Custom Models

For customizing the models, please install SolRaT in the development mode:

git clone https://github.com/yakovkinii/SolRaT.git
cd SolRaT
pip install -e .

Then the models can be modified by following the examples of multi_term_atom, multi_term_atom_legacy, and multi_term_atom_lte models. The models can be independent like multi_term_atom, or introduce slight modifications while reusing most of the other model’s features like multi_term_atom_lte.

Next

For more examples, please explore the _demos/ and _tests/ directories in the GitHub repository. Also, check out the full API reference starting with the Built-in Models for detailed documentation.