Blue loop Analyzer and Cross Counter

mesalab.bluelooptools.blue_loop_analyzer.safe_duration(start, end)[source]

Safely computes the duration between two time points, ensuring both are valid and ordered.

Parameters:
  • start (float) – Starting time value (e.g., age in years).

  • end (float) – Ending time value.

Returns:

Duration (end - start) if both values are non-NaN and end > start; otherwise NaN.

Return type:

float

mesalab.bluelooptools.blue_loop_analyzer.is_in_instability_strip(log_Teff, log_L)[source]

Checks if a given stellar point (log_Teff, log_L) is inside the predefined Instability Strip.

The instability strip is defined by a hardcoded polygon (instability_path) in the HR Diagram (log_Teff vs log_L). The log_Teff axis is assumed to be inverted as is common in HR diagrams.

Parameters:
  • log_Teff (float) – Logarithm of the effective temperature (log10(Teff)).

  • log_L (float) – Logarithm of the luminosity (log10(L/L_solar)).

Returns:

True if the point is inside the instability strip, False otherwise.

Return type:

bool

Example

>>> # Assuming instability_path is globally defined or accessible
>>> # (defined at the module level in this file)
>>> is_in_instability_strip(3.7, 3.0) # Example point inside the strip
True
>>> is_in_instability_strip(4.0, 3.0) # Example point outside
False
mesalab.bluelooptools.blue_loop_analyzer.compute_true_instability_duration(df: DataFrame, is_in_is_series: Series) float[source]

Computes the total time the star spends inside the Instability Strip, by summing all entry-exit intervals within the provided phase.

Parameters:
  • df (pd.DataFrame) – DataFrame containing ‘star_age’ column.

  • is_in_is_series (pd.Series) – Boolean Series indicating IS membership per row.

Returns:

Total duration spent inside the Instability Strip (in years).

Return type:

float

mesalab.bluelooptools.blue_loop_analyzer.analyze_blue_loop_and_instability(history_df: DataFrame, initial_mass: float, initial_Z: float, initial_Y: float)[source]

Analyzes MESA history data for blue loop characteristics and Instability Strip crossings, applying physical criteria to differentiate true blue loops from other IS crossings.

Parameters:
  • history_df (pd.DataFrame) – DataFrame containing MESA history data. Must include ‘log_Teff’, ‘log_L’, ‘center_h1’, ‘star_age’, ‘model_number’, ‘log_g’, ‘center_he4’.

  • initial_mass (float) – Initial mass of the star.

  • initial_Z (float) – Initial metallicity (Z) of the star.

  • initial_Y (float) – Initial helium abundance (Y) of the star.

Returns:

A dictionary containing analysis results, including:
  • ’crossing_count’: Number of times the star enters the Instability Strip during its relevant phase.

  • ’state_times’: Dictionary of specific ages (MS end, min Teff post-MS, IS entries/exits).

  • ’blue_loop_detail_df’: DataFrame with detailed data points during the relevant blue loop phase,

    filtered to include only points inside or to the blue of the IS.

Returns a dictionary with NaN values if analysis cannot be performed (e.g., missing columns, no relevant phase).

Return type:

dict

Example

>>> from mesalab.bluelooptools.blue_loop_analyzer import analyze_blue_loop_and_instability
>>> import pandas as pd
>>> import os
# Load data from a MESA history.data file for a star that exhibits a blue loop.
# This is the recommended approach for this function.
# For this example, we'll assume 'history.data' is a pre-existing, valid file.
>>> file_path = 'path/to/your/history.data'
>>> if os.path.exists(file_path):
...     history_df = pd.read_csv(file_path, delim_whitespace=True, skiprows=5)
...     # Set initial parameters based on the MESA run, like:
...     initial_mass = 5.0
...     initial_Z = 0.006
...     initial_Y = 0.28
...     result = analyze_blue_loop_and_instability(history_df, initial_mass, initial_Z, initial_Y)
...     print(f"Crossing count: {result['crossing_count']}")
... else:
...     print("MESA history.data file not found. Please provide a valid file.")

Blue loop CMD Plotting and Bolometric Corrections

mesalab.bluelooptools.blue_loop_cmd_plotter.z_to_feh(Z)[source]

Converts metallicity Z to [Fe/H] (logarithmic iron-to-hydrogen ratio).

Uses a solar metallicity (Z_sun = 0.0152). Returns NaN for non-positive Z values.

Parameters:

Z (float) – The metallicity value (mass fraction of elements heavier than H and He).

Returns:

The [Fe/H] value, or np.nan if Z is not positive.

Return type:

float

Example

>>> from mesalab.bluelooptools import z_to_feh
>>> z_to_feh(0.0152)
0.0
>>> z_to_feh(0.0076)
-0.3010299956639812
>>> z_to_feh(0)
nan
mesalab.bluelooptools.blue_loop_cmd_plotter.generate_blue_loop_plots_with_bc(combined_df_all_data, output_dir, output_type_label='all_blue_loop_data', plot_cfg=None)[source]

Analyzes MESA history data for stellar blue loop characteristics and Instability Strip crossings, and generates HRD, CMD, and LogL-LogG plots with bolometric corrections.

This function expects a DataFrame that combines MESA history data from one or more evolutionary tracks. It requires specific columns to perform its analysis and plotting.

Parameters:
  • combined_df_all_data (pandas.DataFrame) – DataFrame containing combined MESA history data. Required columns are: - ‘log_Teff’ (Logarithm of effective temperature) - ‘log_L’ (Logarithm of luminosity in solar units) - ‘log_g’ (Logarithm of surface gravity) - ‘initial_Z’ (or ‘Z’ as a fallback, Initial metallicity) - Other MESA history columns are useful but not strictly required.

  • output_dir (str) – The directory where the generated plots will be saved.

  • output_type_label (str) – A label used in the filenames to categorize the output plots.

  • plot_cfg (dict, optional) – A dictionary of plotting configurations. If None, default configurations from ‘plot_config.py’ will be used.

Example

>>> import pandas as pd
>>> import os
>>> from mesalab.bluelooptools import generate_blue_loop_plots_with_bc
>>> # Create a simple, yet realistic, dummy DataFrame.
>>> # The rows simulate a short evolutionary phase.
>>> dummy_data = {
...     'log_Teff': [3.78, 3.82, 3.75],
...     'log_L': [2.8, 3.0, 3.2],
...     'log_g': [3.5, 3.2, 3.0],
...     'initial_Z': [0.008, 0.008, 0.008]
... }
>>> dummy_df = pd.DataFrame(dummy_data)
>>> # Call the function with the data and an output directory.
>>> generate_blue_loop_plots_with_bc(dummy_df, "temp_plot_output")
Calculating BCs serially: 100%|███████████████████████████████████████| 3/3 [00:04<00:00,  1.65s/it]
mesalab.bluelooptools.blue_loop_cmd_plotter.load_and_group_data(input_dir)[source]

This function expects CSV files to contain stellar evolution data. It checks for ‘initial_Z’ or ‘Z’ and ‘initial_mass’ columns.

Parameters:

input_dir (str) – The path to the directory containing the CSV files.

Returns:

A concatenated DataFrame of all valid CSV data, or an empty

DataFrame if no files are found or critical columns are missing.

Return type:

pd.DataFrame

Example

>>> import pandas as pd
>>> import os
>>> import tempfile
>>> from mesalab.bluelooptools import blue_loop_cmd_plotter as bcmd
>>> # Create a temporary directory and some dummy CSV files for the example
>>> with tempfile.TemporaryDirectory() as temp_dir:
...     # File 1: Correct data
...     df1 = pd.DataFrame({'initial_mass': [1.0], 'initial_Z': [0.014], 'log_Teff': [3.7]})
...     df1.to_csv(os.path.join(temp_dir, 'run_1.csv'), index=False)
...     # File 2: Missing 'initial_Z', but has 'Z'
...     df2 = pd.DataFrame({'initial_mass': [1.5], 'Z': [0.008], 'log_Teff': [3.8]})
...     df2.to_csv(os.path.join(temp_dir, 'run_2.csv'), index=False)
...     # Load and process the data
...     combined_df = bcmd.load_and_group_data(temp_dir)
...     # The combined DataFrame should have 2 rows and 3 columns
...     print(f"Combined DataFrame shape: {combined_df.shape}")
...     print(f"Columns: {combined_df.columns.tolist()}")
...     print(f"First row's mass: {combined_df['initial_mass'].iloc[0]}")
...
Combined DataFrame shape: (2, 4)
Columns: ['initial_mass', 'initial_Z', 'log_Teff']
First row's mass: 1.0