Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic Regression Data Setup #213

Merged
merged 18 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/actions/setup_env/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: "Setup environment"
description: "Sets up environment for stardis and caches it"

inputs:
os-label:
description: "os label for lock file, default linux"
required: true
default: "linux-64"

runs:
using: "composite"
steps:
- name: Download Lock File
run: wget -q https://raw.githubusercontent.com/tardis-sn/stardis/main/conda-${{ inputs.os-label }}.lock
shell: bash

- name: Generate Cache Key
run: |
file_hash=$(cat conda-${{ inputs.os-label }}.lock | shasum -a 256 | cut -d' ' -f1)
echo "file_hash=$file_hash" >> "${GITHUB_OUTPUT}"
id: cache-environment-key
shell: bash

- uses: mamba-org/setup-micromamba@v1
with:
environment-file: conda-${{ inputs.os-label }}.lock
cache-environment-key: ${{ steps.cache-environment-key.outputs.file_hash }}
cache-downloads-key: ${{ steps.cache-environment-key.outputs.file_hash }}
environment-name: stardis
cache-environment: true
cache-downloads: true
52 changes: 52 additions & 0 deletions .github/actions/setup_lfs/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: "Setup LFS"
description: "Pull LFS repositories and caches them"


inputs:
regression-data-repo:
description: "stardis regression data repository"
required: false
default: "tardis-sn/stardis-regression-data"

runs:
using: "composite"
steps:
- name: Clone tardis-sn/stardis-regression-data
uses: actions/checkout@v4
with:
repository: ${{ inputs.regression-data-repo }}
path: stardis-regression-data

- name: Create LFS file list
run: git lfs ls-files -l | cut -d' ' -f1 | sort > .lfs-assets-id
working-directory: stardis-regression-data
shell: bash

- name: Restore LFS cache
uses: actions/cache/restore@v4
id: lfs-cache-regression-data
with:
path: stardis-regression-data/.git/lfs
key: ${{ runner.os }}-lfs-${{ hashFiles('stardis-regression-data/.lfs-assets-id') }}-v1

- name: Git LFS Pull
run: git lfs pull
working-directory: stardis-regression-data
if: steps.lfs-cache-regression-data.outputs.cache-hit != 'true'
shell: bash

- name: Git LFS Checkout
run: git lfs checkout
working-directory: stardis-regression-data
if: steps.lfs-cache-regression-data.outputs.cache-hit == 'true'
shell: bash

- name: Save LFS cache if not found
# uses fake ternary
# for reference: https://github.com/orgs/community/discussions/26738#discussioncomment-3253176
if: ${{ steps.lfs-cache-regression-data.outputs.cache-hit != 'true' && !contains(github.ref, 'merge') && always() || false }}
uses: actions/cache/save@v4
id: lfs-cache-regression-data-save
with:
path: stardis-regression-data/.git/lfs
key: ${{ runner.os }}-lfs-${{ hashFiles('stardis-regression-data/.lfs-assets-id') }}-v1
41 changes: 13 additions & 28 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@ name: tests

on:
push:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:

env:
CACHE_NUMBER: 0 # increase to reset cache manually
PYTEST_FLAGS: --cov=stardis --cov-report=xml --cov-report=html
PYTEST_FLAGS: --cov=stardis --cov-report=xml --cov-report=html --stardis-regression-data=${{ github.workspace }}/stardis-regression-data
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

defaults:
Expand All @@ -16,19 +20,16 @@ defaults:

jobs:
build:
# if: github.repository_owner == 'tardis-sn'
if: github.repository_owner == 'tardis-sn'
strategy:
matrix:
include:

- os: ubuntu-latest
label: linux-64
prefix: /usr/share/miniconda3/envs/stardis

# - os: ubuntu-latest
# label: linux-64-cuda
# prefix: /usr/share/miniconda3/envs/stardis

- os: macos-latest
label: osx-64
prefix: /Users/runner/miniconda3/envs/stardis
Expand All @@ -37,39 +38,23 @@ jobs:
runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v2

- name: Setup Mambaforge
uses: conda-incubator/setup-miniconda@v2
with:
miniforge-variant: Mambaforge
miniforge-version: latest
activate-environment: stardis
use-mamba: true
- uses: actions/checkout@v4


- name: Cache lockfile
uses: actions/cache@v2
- name: Setup LFS
uses: ./.github/actions/setup_lfs

- name: Setup STARDIS
uses: ./.github/actions/setup_env
with:
path: ${{ matrix.prefix }}
key: conda-${{ matrix.label }}-${{ hashFiles(format('conda-{0}.lock', matrix.label)) }}-${{ env.CACHE_NUMBER }}
id: cache-conda

- name: Update Conda Environment
id: update-env
run: |
mamba update -n stardis --file conda-${{ matrix.label }}.lock
if: steps.cache-conda.outputs.cache-hit != 'true'
os-label: ${{ matrix.label }}

- name: Install TARDIS
id: install-tardis
# shell: bash -l {0}
run: |
pip install git+https://github.com/tardis-sn/tardis.git@release-2024.08.25

- name: Install STARDIS
id: install-stardis
# shell: bash -l {0}
run: |
pip install -e .[test]

Expand Down
35 changes: 34 additions & 1 deletion stardis/conftest.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import os
import pytest
from pathlib import Path
import numpy as np
from astropy import units as u

from tardis.io.atom_data.base import AtomData
from tardis.io.atom_data.util import download_atom_data
from tardis.io.atom_data import download_atom_data
from tardis.io.configuration.config_validator import validate_yaml
from tardis.io.configuration.config_reader import Configuration
from stardis.io.model.marcs import read_marcs_model
Expand All @@ -15,6 +16,8 @@
from stardis.radiation_field.source_functions.blackbody import blackbody_flux_at_nu
from stardis import STARDISOutput
from stardis.io.base import SCHEMA_PATH
from stardis.util import regression_data


EXAMPLE_CONF_PATH = Path(__file__).parent / "tests" / "stardis_test_config.yml"
EXAMPLE_CONF_PATH_BROADENING = (
Expand All @@ -24,6 +27,27 @@
Path(__file__).parent / "tests" / "stardis_test_config_parallel.yml"
)

# ensuring that regression_data is not removed by ruff
assert regression_data is not None

pytest_plugins = [
"stardis.util.regression_data",
]


def pytest_addoption(parser):
parser.addoption(
"--stardis-regression-data",
default=None,
help="Path to the stardis regression data directory",
)
parser.addoption(
"--generate-reference",
action="store_true",
default=False,
help="generate reference data instead of testing",
)


@pytest.fixture(scope="session")
def example_tracing_nus():
Expand Down Expand Up @@ -281,3 +305,12 @@ def example_stardis_output_parallel(
example_stellar_plasma,
example_stellar_radiation_field_parallel,
)


@pytest.fixture(scope="session")
def stardis_regression_path(request):
stardis_regression_path = request.config.getoption("--stardis-regression-data")
if stardis_regression_path is None:
pytest.skip("--stardis-regression-data was not specified")
else:
return Path(os.path.expandvars(os.path.expanduser(stardis_regression_path)))
7 changes: 6 additions & 1 deletion stardis/model/base.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
class StellarModel:
from tardis.io.util import HDFWriterMixin


class StellarModel(HDFWriterMixin):
"""
Class containing information about the stellar model.

Expand All @@ -20,6 +23,8 @@ class StellarModel:
Class attribute to be easily accessible for initializing arrays that need to match the shape of the model.
"""

hdf_properties = ["temperatures", "geometry", "composition"]

def __init__(self, temperatures, geometry, composition):
self.temperatures = temperatures
self.geometry = geometry
Expand Down
6 changes: 5 additions & 1 deletion stardis/model/geometry/radial1d.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
class Radial1DGeometry:
from tardis.io.util import HDFWriterMixin

atharva-2001 marked this conversation as resolved.
Show resolved Hide resolved

class Radial1DGeometry:
"""
Holds information about model geometry (distribution of depth points) for radial 1D models.

Expand All @@ -15,6 +17,8 @@ class Radial1DGeometry:
distance to the next depth point
"""

hdf_properties = ["r"]

atharva-2001 marked this conversation as resolved.
Show resolved Hide resolved
def __init__(self, r):
self.r = r

Expand Down
5 changes: 4 additions & 1 deletion stardis/radiation_field/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
from stardis.radiation_field.opacities.opacities_solvers import calc_alphas
from stardis.radiation_field.radiation_field_solvers import raytrace
from stardis.radiation_field.source_functions.blackbody import blackbody_flux_at_nu
from tardis.io.util import HDFWriterMixin


class RadiationField:
class RadiationField(HDFWriterMixin):
"""
Class containing information about the radiation field.
###TODO Radiation field temperature should be a separate attribute, for the case of differing gas and radiation.
Expand All @@ -30,6 +31,8 @@ class RadiationField:
Radiation field fluxes at each frequency at each depth point. Initialized as zeros and calculated by a solver.
"""

hdf_properties = ["frequencies", "opacities", "F_nu"]

def __init__(self, frequencies, source_function, stellar_model):
self.frequencies = frequencies
self.source_function = source_function
Expand Down
4 changes: 4 additions & 0 deletions stardis/tests/stardis_test_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ opacity:
disable: False
broadening: []
no_of_thetas: 1
result_options:
return_model: true
return_plasma: true
return_radiation_field: true
95 changes: 95 additions & 0 deletions stardis/tests/test_stardis_regression.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import numpy as np
import pandas as pd

plasma_properties = [
"alpha_line",
"beta_rad",
"electron_densities",
"g",
"g_electron",
"general_level_boltzmann_factor",
"ion_number_density",
"ionization_data",
"level_boltzmann_factor",
"level_number_density",
"levels",
"lines",
"lines_lower_level_index",
"lines_upper_level_index",
"metastability",
"nlte_excitation_species",
"nlte_ionization_species",
"nu",
"number_density",
"partition_function",
"phi",
"selected_atoms",
"stimulated_emission_factor",
"t_electrons",
"t_rad",
"wavelength_cm",
]

plasma_properties_complex = []


def test_stardis_stellar_model(example_stardis_output, regression_data):
actual = example_stardis_output.stellar_model
expected = regression_data.sync_hdf_store(actual)

np.testing.assert_allclose(
actual.temperatures.value, expected["/stellar_model/temperatures"]
)


def test_stardis_stellar_model_geometry(example_stardis_output, regression_data):
actual = example_stardis_output.stellar_model.geometry.r.value
expected = regression_data.sync_ndarray(actual)
np.testing.assert_allclose(actual, expected)


def test_stardis_plasma(example_stardis_output, regression_data):
expected = regression_data.sync_hdf_store(example_stardis_output.stellar_plasma)
actual_plasma = example_stardis_output.stellar_plasma
for item in plasma_properties:
actual_item = getattr(actual_plasma, item)
expected_item = expected[f"plasma/{item}"]
if isinstance(actual_item, list):
actual_item = np.ndarray(actual_item)

if any(
isinstance(actual_item, object_type)
for object_type in [pd.MultiIndex, pd.Index]
):
expected_item = expected[f"plasma/{item}"].values.flatten()
np.testing.assert_array_equal(actual_item.values, expected_item)

elif isinstance(actual_item, np.ndarray):
np.testing.assert_allclose(
actual=actual_item,
desired=expected_item,
err_msg=f"Error encountered when comparing regression data for property- {item}",
)
elif isinstance(actual_item, pd.DataFrame):
pd.testing.assert_frame_equal(actual_item, expected_item)
elif isinstance(actual_item, pd.Series):
pd.testing.assert_series_equal(actual_item, expected_item)
else:
plasma_properties_complex.append(item)
if plasma_properties_complex:
raise AssertionError(
f"These properties were not tested- {plasma_properties_complex}"
)


def test_stardis_radiation_field(example_stardis_output, regression_data):
expected = regression_data.sync_hdf_store(
example_stardis_output.stellar_radiation_field
)
actual = example_stardis_output.stellar_radiation_field

np.testing.assert_allclose(
expected["/radiation_field/frequencies"].values, actual.frequencies.value
)

np.testing.assert_allclose(expected["/radiation_field/F_nu"].values, actual.F_nu)
Empty file added stardis/util/__init__.py
Empty file.
Loading
Loading