Compare commits

..

2 Commits

20 changed files with 57 additions and 97 deletions

View File

@ -1 +0,0 @@
__all__ = []

View File

@ -1,3 +1,4 @@
ATTENUATION_TABLE = 'attenuation_table.csv' ATTENUATION_TABLE = 'attenuation_table.csv'
ISOTOPE_TABLE = 'isotopes.csv'
TEST_EXP_DATA = 'test_path_coords.csv' TEST_EXP_DATA = 'test_path_coords.csv'
LOGGING_CONFIG = 'logging.yml' LOGGING_CONFIG = 'logging.yml'

View File

@ -1 +0,0 @@
__all__ = []

View File

@ -0,0 +1,6 @@
isotope,gamma_energy_keV,branching_ratio
Cs134,604.7,0.976
Cs134,795.9,0.855
Cs137,661.657,0.851
Co60,1173.228,1.0
Co60,1332.5,1.0
1 isotope gamma_energy_keV branching_ratio
2 Cs134 604.7 0.976
3 Cs134 795.9 0.855
4 Cs137 661.657 0.851
5 Co60 1173.228 1.0
6 Co60 1332.5 1.0

View File

@ -1,8 +0,0 @@
# do not expose internal logger when running mkinit
__ignore__ = ["logger"]
from pg_rad.dataloader import dataloader
from pg_rad.dataloader.dataloader import (load_data,)
__all__ = ['dataloader', 'load_data']

View File

@ -1,10 +0,0 @@
# do not expose internal logger when running mkinit
__ignore__ = ["logger"]
from pg_rad.exceptions import exceptions
from pg_rad.exceptions.exceptions import (ConvergenceError, DataLoadError,
InvalidCSVError, OutOfBoundsError,)
__all__ = ['ConvergenceError', 'DataLoadError', 'InvalidCSVError',
'OutOfBoundsError', 'exceptions']

View File

View File

@ -11,6 +11,7 @@ from pg_rad.exceptions.exceptions import (
InvalidYAMLError InvalidYAMLError
) )
from pg_rad.configs import defaults from pg_rad.configs import defaults
from pg_rad.isotopes.isotope import get_isotope
from .specs import ( from .specs import (
MetadataSpec, MetadataSpec,
@ -276,7 +277,9 @@ class ConfigParser:
specs: List[PointSourceSpec] = [] specs: List[PointSourceSpec] = []
for name, params in source_dict.items(): for name, params in source_dict.items():
required = {"activity_MBq", "isotope", "position"} required = {
"activity_MBq", "isotope", "position", "gamma_energy_keV"
}
if not isinstance(params, dict): if not isinstance(params, dict):
raise InvalidConfigValueError( raise InvalidConfigValueError(
f"sources.{name} is not defined correctly." f"sources.{name} is not defined correctly."
@ -288,7 +291,10 @@ class ConfigParser:
raise MissingConfigKeyError(name, missing) raise MissingConfigKeyError(name, missing)
activity = params.get("activity_MBq") activity = params.get("activity_MBq")
isotope = params.get("isotope") isotope_name = params.get("isotope")
gamma_energy_keV = params.get("gamma_energy_keV")
isotope = get_isotope(isotope_name, gamma_energy_keV)
if not isinstance(activity, int | float) or activity <= 0: if not isinstance(activity, int | float) or activity <= 0:
raise InvalidConfigValueError( raise InvalidConfigValueError(

View File

@ -1,9 +0,0 @@
# do not expose internal logger when running mkinit
__ignore__ = ["logger"]
from pg_rad.isotopes import isotope
from pg_rad.isotopes.isotope import (CS137, Isotope, get_isotope,
preset_isotopes,)
__all__ = ['CS137', 'Isotope', 'get_isotope', 'isotope', 'preset_isotopes']

View File

@ -1,5 +1,8 @@
from typing import Dict, Type from importlib.resources import files
from pandas import read_csv
from pg_rad.configs.filepaths import ISOTOPE_TABLE
from pg_rad.exceptions.exceptions import InvalidIsotopeError from pg_rad.exceptions.exceptions import InvalidIsotopeError
from pg_rad.physics.attenuation import get_mass_attenuation_coeff from pg_rad.physics.attenuation import get_mass_attenuation_coeff
@ -30,22 +33,35 @@ class Isotope:
self.mu_mass_air = get_mass_attenuation_coeff(E / 1000) self.mu_mass_air = get_mass_attenuation_coeff(E / 1000)
class CS137(Isotope): def get_isotope(isotope: str, energy_gamma_keV: float) -> Isotope:
def __init__(self): """Lazy factory function to create isotope objects."""
super().__init__( path = files('pg_rad.data').joinpath(ISOTOPE_TABLE)
name="Cs-137", df = read_csv(path)
E=661.66,
b=0.851 isotope_df = df[df['isotope'] == isotope]
if isotope_df.empty:
raise InvalidIsotopeError(f"No data available for isotope {isotope}.")
tol = 0.01 * energy_gamma_keV
closest_energy = isotope_df[
(isotope_df['gamma_energy_keV'] >= energy_gamma_keV - tol) &
(isotope_df['gamma_energy_keV'] <= energy_gamma_keV + tol)
]
if closest_energy.empty:
available_gammas = ', '.join(
str(x)+' keV' for x in isotope_df['gamma_energy_keV'].to_list()
)
raise InvalidIsotopeError(
f"No gamma of {energy_gamma_keV}±{tol} keV "
f"found for isotope {isotope}. "
f"Available gammas are: {available_gammas}"
) )
matched_row = closest_energy.iloc[0]
preset_isotopes: Dict[str, Type[Isotope]] = { return Isotope(
"Cs137": CS137 name=isotope,
} E=matched_row['gamma_energy_keV'],
b=matched_row['branching_ratio']
)
def get_isotope(isotope_str: str) -> Isotope:
"""Lazy factory function to create isotope objects."""
if isotope_str not in preset_isotopes:
raise InvalidIsotopeError(f"Unknown isotope: {isotope_str}")
return preset_isotopes[isotope_str]()

View File

@ -1,5 +0,0 @@
from pg_rad.logger import logger
from pg_rad.logger.logger import (setup_logger,)
__all__ = ['logger', 'setup_logger']

View File

@ -59,7 +59,7 @@ def main():
length: 1000 length: 1000
segments: segments:
- straight - straight
- turn_left - turn_left: 45
direction: negative direction: negative
sources: sources:
@ -67,6 +67,7 @@ def main():
activity_MBq: 100 activity_MBq: 100
position: [250, 100, 0] position: [250, 100, 0]
isotope: Cs137 isotope: Cs137
gamma_energy_keV: 661
detector: detector:
name: dummy name: dummy

View File

@ -1,11 +0,0 @@
# do not expose internal logger when running mkinit
__ignore__ = ["logger"]
from pg_rad.objects import objects
from pg_rad.objects import sources
from pg_rad.objects.objects import (BaseObject,)
from pg_rad.objects.sources import (PointSource,)
__all__ = ['BaseObject', 'PointSource', 'objects',
'sources']

View File

@ -1,7 +1,7 @@
import logging import logging
from .objects import BaseObject from .objects import BaseObject
from pg_rad.isotopes.isotope import Isotope, get_isotope from pg_rad.isotopes.isotope import Isotope
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -12,7 +12,7 @@ class PointSource(BaseObject):
def __init__( def __init__(
self, self,
activity_MBq: int, activity_MBq: int,
isotope: str, isotope: Isotope,
position: tuple[float, float, float] = (0, 0, 0), position: tuple[float, float, float] = (0, 0, 0),
name: str | None = None, name: str | None = None,
color: str = 'red' color: str = 'red'
@ -40,7 +40,7 @@ class PointSource(BaseObject):
super().__init__(position, name, color) super().__init__(position, name, color)
self.activity = activity_MBq self.activity = activity_MBq
self.isotope: Isotope = get_isotope(isotope) self.isotope = isotope
logger.debug(f"Source created: {self.name}") logger.debug(f"Source created: {self.name}")

View File

@ -1,8 +0,0 @@
# do not expose internal logger when running mkinit
__ignore__ = ["logger"]
from pg_rad.path import path
from pg_rad.path.path import (Path, PathSegment, path_from_RT90,)
__all__ = ['Path', 'PathSegment', 'path', 'path_from_RT90']

View File

@ -1,12 +0,0 @@
# do not expose internal logger when running mkinit
__ignore__ = ["logger"]
from pg_rad.physics import attenuation
from pg_rad.physics import fluence
from pg_rad.physics.attenuation import (get_mass_attenuation_coeff,)
from pg_rad.physics.fluence import (calculate_fluence_along_path,
calculate_fluence_at, phi,)
__all__ = ['attenuation', 'calculate_fluence_along_path',
'calculate_fluence_at', 'fluence', 'get_mass_attenuation_coeff',
'phi']

View File

@ -1,7 +0,0 @@
# do not expose internal logger when running mkinit
__ignore__ = ["logger"]
from pg_rad.plotting import landscape_plotter
from pg_rad.plotting.landscape_plotter import (LandscapeSlicePlotter,)
__all__ = ['LandscapeSlicePlotter', 'landscape_plotter']

View File

@ -105,7 +105,7 @@ class ResultPlotter:
data = [ data = [
[ [
s.name, s.name,
s.isotope, s.isotope+f" ({s.primary_gamma} keV)",
s.activity, s.activity,
"("+", ".join(f"{val:.2f}" for val in s.position)+")", "("+", ".join(f"{val:.2f}" for val in s.position)+")",
round(s.dist_from_path, 2) round(s.dist_from_path, 2)

View File

@ -62,6 +62,7 @@ class SimulationEngine:
SourceOutput( SourceOutput(
s.name, s.name,
s.isotope.name, s.isotope.name,
s.isotope.E,
s.activity, s.activity,
s.pos, s.pos,
dist_to_path) dist_to_path)

View File

@ -13,6 +13,7 @@ class CountRateOutput:
class SourceOutput: class SourceOutput:
name: str name: str
isotope: str isotope: str
primary_gamma: float
activity: float activity: float
position: Tuple[float, float, float] position: Tuple[float, float, float]
dist_from_path: float dist_from_path: float