mirror of
https://github.com/pim-n/pg-rad
synced 2026-03-22 21:48:11 +01:00
Compare commits
2 Commits
09e74051f0
...
1e81570cf4
| Author | SHA1 | Date | |
|---|---|---|---|
| 1e81570cf4 | |||
| 1dc553d2e2 |
@ -1 +0,0 @@
|
||||
__all__ = []
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
ATTENUATION_TABLE = 'attenuation_table.csv'
|
||||
ISOTOPE_TABLE = 'isotopes.csv'
|
||||
TEST_EXP_DATA = 'test_path_coords.csv'
|
||||
LOGGING_CONFIG = 'logging.yml'
|
||||
|
||||
@ -1 +0,0 @@
|
||||
__all__ = []
|
||||
|
||||
6
src/pg_rad/data/isotopes.csv
Normal file
6
src/pg_rad/data/isotopes.csv
Normal 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,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']
|
||||
|
||||
@ -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']
|
||||
|
||||
0
src/pg_rad/inputparser/__init__.py
Normal file
0
src/pg_rad/inputparser/__init__.py
Normal file
@ -11,6 +11,7 @@ from pg_rad.exceptions.exceptions import (
|
||||
InvalidYAMLError
|
||||
)
|
||||
from pg_rad.configs import defaults
|
||||
from pg_rad.isotopes.isotope import get_isotope
|
||||
|
||||
from .specs import (
|
||||
MetadataSpec,
|
||||
@ -276,7 +277,9 @@ class ConfigParser:
|
||||
specs: List[PointSourceSpec] = []
|
||||
|
||||
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):
|
||||
raise InvalidConfigValueError(
|
||||
f"sources.{name} is not defined correctly."
|
||||
@ -288,7 +291,10 @@ class ConfigParser:
|
||||
raise MissingConfigKeyError(name, missing)
|
||||
|
||||
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:
|
||||
raise InvalidConfigValueError(
|
||||
|
||||
@ -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']
|
||||
|
||||
@ -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.physics.attenuation import get_mass_attenuation_coeff
|
||||
|
||||
@ -30,22 +33,35 @@ class Isotope:
|
||||
self.mu_mass_air = get_mass_attenuation_coeff(E / 1000)
|
||||
|
||||
|
||||
class CS137(Isotope):
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
name="Cs-137",
|
||||
E=661.66,
|
||||
b=0.851
|
||||
def get_isotope(isotope: str, energy_gamma_keV: float) -> Isotope:
|
||||
"""Lazy factory function to create isotope objects."""
|
||||
path = files('pg_rad.data').joinpath(ISOTOPE_TABLE)
|
||||
df = read_csv(path)
|
||||
|
||||
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}"
|
||||
)
|
||||
|
||||
|
||||
preset_isotopes: Dict[str, Type[Isotope]] = {
|
||||
"Cs137": CS137
|
||||
}
|
||||
|
||||
|
||||
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]()
|
||||
matched_row = closest_energy.iloc[0]
|
||||
return Isotope(
|
||||
name=isotope,
|
||||
E=matched_row['gamma_energy_keV'],
|
||||
b=matched_row['branching_ratio']
|
||||
)
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
from pg_rad.logger import logger
|
||||
|
||||
from pg_rad.logger.logger import (setup_logger,)
|
||||
|
||||
__all__ = ['logger', 'setup_logger']
|
||||
|
||||
@ -59,7 +59,7 @@ def main():
|
||||
length: 1000
|
||||
segments:
|
||||
- straight
|
||||
- turn_left
|
||||
- turn_left: 45
|
||||
direction: negative
|
||||
|
||||
sources:
|
||||
@ -67,6 +67,7 @@ def main():
|
||||
activity_MBq: 100
|
||||
position: [250, 100, 0]
|
||||
isotope: Cs137
|
||||
gamma_energy_keV: 661
|
||||
|
||||
detector:
|
||||
name: dummy
|
||||
|
||||
@ -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']
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import logging
|
||||
|
||||
from .objects import BaseObject
|
||||
from pg_rad.isotopes.isotope import Isotope, get_isotope
|
||||
from pg_rad.isotopes.isotope import Isotope
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -12,7 +12,7 @@ class PointSource(BaseObject):
|
||||
def __init__(
|
||||
self,
|
||||
activity_MBq: int,
|
||||
isotope: str,
|
||||
isotope: Isotope,
|
||||
position: tuple[float, float, float] = (0, 0, 0),
|
||||
name: str | None = None,
|
||||
color: str = 'red'
|
||||
@ -40,7 +40,7 @@ class PointSource(BaseObject):
|
||||
super().__init__(position, name, color)
|
||||
|
||||
self.activity = activity_MBq
|
||||
self.isotope: Isotope = get_isotope(isotope)
|
||||
self.isotope = isotope
|
||||
|
||||
logger.debug(f"Source created: {self.name}")
|
||||
|
||||
|
||||
@ -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']
|
||||
|
||||
@ -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']
|
||||
|
||||
@ -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']
|
||||
|
||||
@ -105,7 +105,7 @@ class ResultPlotter:
|
||||
data = [
|
||||
[
|
||||
s.name,
|
||||
s.isotope,
|
||||
s.isotope+f" ({s.primary_gamma} keV)",
|
||||
s.activity,
|
||||
"("+", ".join(f"{val:.2f}" for val in s.position)+")",
|
||||
round(s.dist_from_path, 2)
|
||||
|
||||
@ -62,6 +62,7 @@ class SimulationEngine:
|
||||
SourceOutput(
|
||||
s.name,
|
||||
s.isotope.name,
|
||||
s.isotope.E,
|
||||
s.activity,
|
||||
s.pos,
|
||||
dist_to_path)
|
||||
|
||||
@ -13,6 +13,7 @@ class CountRateOutput:
|
||||
class SourceOutput:
|
||||
name: str
|
||||
isotope: str
|
||||
primary_gamma: float
|
||||
activity: float
|
||||
position: Tuple[float, float, float]
|
||||
dist_from_path: float
|
||||
|
||||
Reference in New Issue
Block a user