Files
giant/tests/test_materials.py
T
lars 55332db67a
CI / Lint (ruff check) (push) Successful in 31s
CI / Format (ruff format) (push) Successful in 32s
CI / Sync project version with tag (push) Has been skipped
CI / Lint (ruff check) (pull_request) Successful in 26s
CI / Type check (ty) (push) Successful in 29s
CI / Format (ruff format) (pull_request) Successful in 33s
CI / Sync project version with tag (pull_request) Has been skipped
CI / Type check (ty) (pull_request) Successful in 35s
CI / Tests (pull_request) Successful in 3m47s
CI / Tests (push) Successful in 3m55s
Bump ruff line-length to 120 and reformat
Rejoins lines that only wrapped because they exceeded the old 88-char
limit; ruff check and the full test suite (725 passed) are unaffected.
2026-08-12 13:33:09 +02:00

102 lines
3.6 KiB
Python

import numpy as np
import pytest
from giant.materials import (
MaterialProperties,
MaterialPropertiesNotFilledError,
UnknownMaterialError,
get_material_properties,
material_properties_array,
)
def test_get_material_properties_unknown_name_raises():
with pytest.raises(UnknownMaterialError):
get_material_properties("G4_Unobtainium")
def test_get_material_properties_unfilled_entry_raises():
"""G4_LYSO is not a stock Geant4 NIST material (confirmed against the
vendored Geant4 11.4.1 build) and is the one entry still shipped unfilled."""
with pytest.raises(MaterialPropertiesNotFilledError):
get_material_properties("G4_LYSO")
def test_get_material_properties_returns_filled_entry_from_injected_table():
table = {"G4_Pb": MaterialProperties(z_eff=82.0, a_eff=207.2, density=11.35, x0=0.5612, lambda_int=17.59)}
props = get_material_properties("G4_Pb", table)
assert props.z_eff == 82.0
assert props.a_eff == 207.2
assert props.density == 11.35
assert props.x0 == 0.5612
assert props.lambda_int == 17.59
def test_material_properties_array_shape_and_values():
table = {
"G4_Pb": MaterialProperties(82.0, 207.2, 11.35, 0.5612, 17.59),
"G4_W": MaterialProperties(74.0, 183.84, 19.3, 0.3504, 9.95),
}
names = np.array(["G4_Pb", "G4_W", "G4_Pb"], dtype=object)
arr = material_properties_array(names, table)
assert arr.shape == (3, 5)
assert arr.dtype == np.float32
np.testing.assert_allclose(arr[0], [82.0, 207.2, 11.35, 0.5612, 17.59], rtol=1e-5)
np.testing.assert_allclose(arr[1], [74.0, 183.84, 19.3, 0.3504, 9.95], rtol=1e-5)
def test_all_known_materials_present_in_stub_table():
"""Every material referenced elsewhere in the repo must at least have a
stub entry (even if unfilled) -- an unknown name should never be the
failure mode a physicist hits when populating the table."""
from giant.materials import MATERIAL_PROPERTIES
expected = {
"G4_PbWO4",
"G4_CESIUM_IODIDE",
"G4_Pb",
"G4_W",
"G4_Cu",
"G4_Fe",
"G4_BRASS",
"G4_POLYSTYRENE",
"G4_PLASTIC_SC_VINYLTOLUENE",
"G4_BGO",
"G4_LYSO",
"G4_AIR",
"G4_lAr",
}
assert expected <= set(MATERIAL_PROPERTIES.keys())
def test_all_materials_filled_except_lyso():
"""G4_LYSO is the sole intentionally-unfilled entry (not a stock Geant4
NIST material); every other known material has real Geant4-derived
values -- see the module docstring for provenance."""
from giant.materials import MATERIAL_PROPERTIES
for name, props in MATERIAL_PROPERTIES.items():
if name == "G4_LYSO":
assert all(v is None for v in props)
else:
assert all(v is not None for v in props), f"{name} unexpectedly unfilled"
def test_elemental_material_z_eff_matches_atomic_number():
"""Single-element materials' z_eff must equal the element's real Z."""
pb = get_material_properties("G4_Pb")
assert pb.z_eff == pytest.approx(82.0)
w = get_material_properties("G4_W")
assert w.z_eff == pytest.approx(74.0)
fe = get_material_properties("G4_Fe")
assert fe.z_eff == pytest.approx(26.0)
def test_pbwo4_values_match_known_cms_ecal_reference():
"""PbWO4 (CMS ECAL crystal) has well-known reference values: X0~0.89cm,
density 8.28 g/cm^3 -- sanity check the Geant4-derived numbers land there."""
pbwo4 = get_material_properties("G4_PbWO4")
assert pbwo4.density == pytest.approx(8.28)
assert pbwo4.x0 == pytest.approx(0.89, abs=0.01)
assert pbwo4.z_eff == pytest.approx(31.33, abs=0.01)