Physics

Ion physics: RDD, LET, CSDA range, and energy-loss utilities.

tracketch.physics.get_RDD_Gy(r_m: ndarray, E_MeV_u: float, particle_name: str, RDD_name: str = 'Cucinotta', material_name: str = 'CR39', core_nm: float | None = None, normalise_to_LET: bool | None = None, LET_source: str = 'SRIM', verbose: bool = False) ndarray[source]

Radial dose distribution scaled to material_name.

The RDD is computed for water (via libamtrack) and then corrected:

  1. Radii are density-scaled to account for different electron ranges.

  2. A dose correction restores the radial integral after the range shift.

  3. A stopping-power ratio (SPR) converts dose-to-water into dose-to- target-material.

  4. Optionally, the profile is renormalised so that its radial integral equals the target-material LET.

Parameters:
  • r_m (ndarray) – Radial distances in metres.

  • E_MeV_u (float) – Kinetic energy in MeV/u.

  • particle_name (str) – Ion species.

  • RDD_name (str) – RDD model name (default "Cucinotta").

  • material_name (str) – Target material (default "CR39").

  • core_nm (float or None) – Core radius override in nm.

  • normalise_to_LET (bool or None) – Force LET normalisation. None uses the model default.

  • LET_source (str) – Stopping-power source for the SPR (default "SRIM").

  • verbose (bool) – Print diagnostic information.

Returns:

Dose in Gy at each radius.

Return type:

ndarray

tracketch.physics.get_LET_keV_um(energy_MeV_u: float | ndarray, particle_name: str, material_name: str, source: str = 'SRIM') float | ndarray[source]

Return LET in keV/um from the chosen stopping-power database.

Parameters:
  • energy_MeV_u (float or ndarray) – Kinetic energy in MeV per nucleon.

  • particle_name (str) – Ion species, e.g. "12C".

  • material_name (str) – Target material, e.g. "CR39".

  • source (str) – "SRIM" (default) or "libamtrack".

Returns:

LET in keV/um.

Return type:

float or ndarray

Raises:

ValueError – If source or material_name are not recognised.

tracketch.physics.get_CSDA_um(energy_MeV_u: float, particle_name: str, material_name: str, source: str = 'SRIM') float[source]

Return the CSDA range in um from the chosen stopping-power database.

Parameters:
  • energy_MeV_u (float) – Kinetic energy in MeV/u.

  • particle_name (str) – Ion species.

  • material_name (str) – Target material.

  • source (str) – "SRIM" (default) or "libamtrack".

Returns:

CSDA range in um.

Return type:

float

Raises:

ValueError – If source or material_name are not recognised.

tracketch.physics.get_dose_map_Gy(z_um: ndarray, r_um: ndarray, energy_MeV_u_array: ndarray, particle_name: str, material_name: str = 'CR39', RDD_name: str = 'Cucinotta', LET_source: str = 'SRIM', core_radius_nm: float | None = None, normalise_to_LET: bool | None = None, verbose: bool = False, n_jobs: int = 1) ndarray[source]

Build a 2-D dose map by evaluating the RDD at each depth step.

Parameters:
  • z_um (ndarray, shape (n_z,)) – Depth coordinates in um.

  • r_um (ndarray, shape (n_r,)) – Radial coordinates in um.

  • energy_MeV_u_array (ndarray, shape (n_z,)) – Ion energy at each depth (from get_LET_energy_profile()).

  • particle_name (str) – Ion species.

  • material_name (str) – Target material.

  • RDD_name (str) – RDD model name.

  • LET_source (str) – Stopping-power source.

  • core_radius_nm (float or None) – Core radius override.

  • normalise_to_LET (bool or None) – Force LET normalisation.

  • verbose (bool) – Print diagnostics.

  • n_jobs (int) – Number of parallel workers for RDD evaluation. -1 uses all available CPU cores (via joblib). Default 1 runs sequentially.

Returns:

Local dose in Gy.

Return type:

ndarray, shape (n_z, n_r)

tracketch.physics.get_mean_core_value(metric_map: ndarray, r_um: ndarray, core_r_threshold_um: float = 0.1, min_core_r_um: float = 0.001) ndarray[source]

Average a map over the track core (small-r region) at each depth.

Parameters:
  • metric_map (ndarray, shape (n_z, n_r)) – Dose or etch-rate map.

  • r_um (ndarray, shape (n_r,)) – Radial coordinates in um.

  • core_r_threshold_um (float) – Outer boundary of the core region in um.

  • min_core_r_um (float) – Inner boundary of the core region in um.

Returns:

Mean value within the core at each depth. nan where no valid data exists.

Return type:

ndarray, shape (n_z,)

tracketch.physics.RDD_integral(r_m: ndarray, D_Gy: ndarray, density_g_cm3: float | None = None) float[source]

Radial integral of the dose distribution.

Computes

\[\int 2\pi\, r\, D(r)\, \mathrm{d}r\]

and converts to keV/um (per unit density) via standard unit factors.

Parameters:
  • r_m (ndarray) – Radial positions in metres.

  • D_Gy (ndarray) – Dose in Gy at each radius.

  • density_g_cm3 (float or None) – If given, multiply by the density in kg/m^3.

Returns:

Integral value (keV/um if density is provided in kg/m^3 upstream).

Return type:

float

tracketch.physics.convert_MeV_to_MeV_u(Energy_MeV: float, particle_name: str) float[source]

Convert total kinetic energy (MeV) to energy per nucleon (MeV/u).

Parameters:
  • Energy_MeV (float) – Total kinetic energy in MeV.

  • particle_name (str) – Ion species identifier.

Returns:

Energy in MeV/u.

Return type:

float

tracketch.physics.convert_MeV_u_to_MeV(Energy_MeV_u: float, particle_name: str) float[source]

Convert energy per nucleon (MeV/u) to total kinetic energy (MeV).

Parameters:
  • Energy_MeV_u (float) – Energy in MeV per nucleon.

  • particle_name (str) – Ion species identifier.

Returns:

Total kinetic energy in MeV.

Return type:

float

tracketch.physics.get_energy_after_slab_MeV_u(E_initial_MeV_u: float, particle_name: str, slab_thickness_um: float, material_name: str = 'CR39', source: str = 'SRIM') float[source]

Residual energy after traversing a slab of given thickness.

Steps through the slab in small increments, computing the LET at each step to update the energy.

Parameters:
  • E_initial_MeV_u (float) – Incident energy in MeV/u.

  • particle_name (str) – Ion species.

  • slab_thickness_um (float) – Slab thickness in um.

  • material_name (str) – Target material (default "CR39").

  • source (str) – Stopping-power source (default "SRIM").

Returns:

Residual energy in MeV/u (0 if the ion stops).

Return type:

float

tracketch.physics.apply_range_straggling(dz_um_list: ndarray, metric: ndarray, longitudinal_straggling_um: float, n_sigma: float = 1) ndarray[source]

Broaden a depth profile by Gaussian range-straggling convolution.

Parameters:
  • dz_um_list (ndarray) – Depth grid in um (assumed uniform spacing).

  • metric (ndarray) – Profile to broaden (same length as dz_um_list).

  • longitudinal_straggling_um (float) – 1-sigma straggling width in um.

  • n_sigma (float) – Number of sigma to apply (0 = no straggling).

Returns:

Broadened profile.

Return type:

ndarray

tracketch.physics.get_range_straggling_um(energy_MeV_u: float, particle_name: str, material_name: str) float[source]

Longitudinal range straggling from SRIM data.

Parameters:
  • energy_MeV_u (float) – Kinetic energy in MeV/u.

  • particle_name (str) – Ion species.

  • material_name (str) – Target material.

Returns:

Straggling in um. Returns 0 if the particle is not available in SRIM (justified for heavy ions with negligible straggling).

Return type:

float

tracketch.physics.get_LET_energy_profile(dz_um_list: ndarray, energy_MeV_u: float, particle_name: str, material_name: str, range_straggling: bool = True, n_straggling_sigma: float = 1, source: str = 'SRIM') tuple[ndarray, ndarray][source]

Compute energy and LET profiles along depth.

For source="SRIM" the profiles are computed analytically by inverting the CSDA-range table (vectorised, no stepping loop). For source="libamtrack" the original iterative stepping is used.

Optionally applies longitudinal range straggling as a Gaussian convolution.

Parameters:
  • dz_um_list (ndarray) – Depth grid in um.

  • energy_MeV_u (float) – Incident energy in MeV/u.

  • particle_name (str) – Ion species.

  • material_name (str) – Target material.

  • range_straggling (bool) – Apply Gaussian straggling (default True).

  • n_straggling_sigma (float) – Number of straggling sigma (default 1).

  • source (str) – Stopping-power database (default "SRIM").

Returns:

  • energy_profile (ndarray) – Kinetic energy in MeV/u at each depth.

  • LET_profile (ndarray) – LET in keV/um at each depth.

Interface to libamtrack for RDD, LET, and CSDA calculations.

CR-39 is not defined in libamtrack. All calculations are performed for water (or PMMA for density-matching) and then scaled to CR-39 by the caller.

tracketch.physics.libamtrack.get_material_number_and_density(density_g_cm3: float) tuple[int, float][source]

Return the libamtrack material number closest to the requested density.

Parameters:

density_g_cm3 (float) – Target density in g/cm^3. Must be in (0, 10].

Returns:

  • material_no (int) – libamtrack material number.

  • material_density_g_cm3 (float) – Actual density of the matched material.

Raises:

ValueError – If density_g_cm3 is outside (0, 10].

tracketch.physics.libamtrack.get_LET_keV_um_libam(particle_name: str, E_MeV_u: float, density_g_cm3: float = 1.31) float[source]

Compute LET in keV/um for a given ion and energy via libamtrack.

The stopping power is computed for the closest libamtrack material and then linearly scaled to density_g_cm3.

Parameters:
  • particle_name (str) – Ion species, e.g. "12C".

  • E_MeV_u (float) – Kinetic energy in MeV per nucleon.

  • density_g_cm3 (float) – Target material density (default 1.31, CR-39).

Returns:

LET in keV/um.

Return type:

float

tracketch.physics.libamtrack.RDD_libamtrack_Gy(r_m: ndarray, E_MeV_u: float, particle_name: str, RDD_name: str = 'Cucinotta', core_nm: float | None = None) ndarray[source]

Compute radial dose distribution in Gy at radii r_m (metres).

Uses libamtrack for water. Material scaling must be done by the caller (see tracketch.physics.get_RDD_Gy()).

Parameters:
  • r_m (ndarray) – Radial distances in metres.

  • E_MeV_u (float) – Kinetic energy in MeV/u.

  • particle_name (str) – Ion species.

  • RDD_name (str) – RDD model name (default "Cucinotta").

  • core_nm (float or None) – Core radius override in nm. None uses the model default.

Returns:

Dose in Gy. Values below d_min_Gy are set to nan.

Return type:

ndarray

Raises:

ValueError – If RDD_name is not defined in the configuration.

tracketch.physics.libamtrack.get_energy_after_slab_MeV_um_libam(E_initial_MeV_u: float, particle_name: str, slab_thickness_um: float, material_name: str) float[source]

Residual energy after traversing a slab, computed via libamtrack.

Only works for materials defined in libamtrack ("Liquid, Water" or "PMMA").

Parameters:
  • E_initial_MeV_u (float) – Incident energy in MeV/u.

  • particle_name (str) – Ion species.

  • slab_thickness_um (float) – Slab thickness in um.

  • material_name (str) – "Liquid, Water" or "PMMA".

Returns:

Energy after the slab in MeV/u.

Return type:

float

Raises:

ValueError – If material_name is not supported.

tracketch.physics.libamtrack.get_CSDA_range_um_libam(particle_name: str, E_MeV_u: float, density_g_cm3: float = 1.31) float[source]

CSDA range in um via libamtrack, scaled to the target density.

libamtrack returns a density-normalised range (g/cm^2), which is converted to um using density_g_cm3.

Parameters:
  • particle_name (str) – Ion species.

  • E_MeV_u (float) – Kinetic energy in MeV/u.

  • density_g_cm3 (float) – Target material density (default 1.31, CR-39).

Returns:

CSDA range in um.

Return type:

float

High-level ion-physics utilities.

Wrappers around SRIM tables and libamtrack that provide:

  • LET and CSDA range lookups (multi-source),

  • radial dose distributions (RDD) scaled to arbitrary materials,

  • dose-map construction,

  • energy-loss stepping, and

  • longitudinal range-straggling convolution.

tracketch.physics.utils_ions.get_material_config()[source]

Return the materials section of the material configuration (cached).

tracketch.physics.utils_ions.get_LET_keV_um(energy_MeV_u: float | ndarray, particle_name: str, material_name: str, source: str = 'SRIM') float | ndarray[source]

Return LET in keV/um from the chosen stopping-power database.

Parameters:
  • energy_MeV_u (float or ndarray) – Kinetic energy in MeV per nucleon.

  • particle_name (str) – Ion species, e.g. "12C".

  • material_name (str) – Target material, e.g. "CR39".

  • source (str) – "SRIM" (default) or "libamtrack".

Returns:

LET in keV/um.

Return type:

float or ndarray

Raises:

ValueError – If source or material_name are not recognised.

tracketch.physics.utils_ions.get_RDD_Gy(r_m: ndarray, E_MeV_u: float, particle_name: str, RDD_name: str = 'Cucinotta', material_name: str = 'CR39', core_nm: float | None = None, normalise_to_LET: bool | None = None, LET_source: str = 'SRIM', verbose: bool = False) ndarray[source]

Radial dose distribution scaled to material_name.

The RDD is computed for water (via libamtrack) and then corrected:

  1. Radii are density-scaled to account for different electron ranges.

  2. A dose correction restores the radial integral after the range shift.

  3. A stopping-power ratio (SPR) converts dose-to-water into dose-to- target-material.

  4. Optionally, the profile is renormalised so that its radial integral equals the target-material LET.

Parameters:
  • r_m (ndarray) – Radial distances in metres.

  • E_MeV_u (float) – Kinetic energy in MeV/u.

  • particle_name (str) – Ion species.

  • RDD_name (str) – RDD model name (default "Cucinotta").

  • material_name (str) – Target material (default "CR39").

  • core_nm (float or None) – Core radius override in nm.

  • normalise_to_LET (bool or None) – Force LET normalisation. None uses the model default.

  • LET_source (str) – Stopping-power source for the SPR (default "SRIM").

  • verbose (bool) – Print diagnostic information.

Returns:

Dose in Gy at each radius.

Return type:

ndarray

tracketch.physics.utils_ions.RDD_integral(r_m: ndarray, D_Gy: ndarray, density_g_cm3: float | None = None) float[source]

Radial integral of the dose distribution.

Computes

\[\int 2\pi\, r\, D(r)\, \mathrm{d}r\]

and converts to keV/um (per unit density) via standard unit factors.

Parameters:
  • r_m (ndarray) – Radial positions in metres.

  • D_Gy (ndarray) – Dose in Gy at each radius.

  • density_g_cm3 (float or None) – If given, multiply by the density in kg/m^3.

Returns:

Integral value (keV/um if density is provided in kg/m^3 upstream).

Return type:

float

tracketch.physics.utils_ions.get_CSDA_um(energy_MeV_u: float, particle_name: str, material_name: str, source: str = 'SRIM') float[source]

Return the CSDA range in um from the chosen stopping-power database.

Parameters:
  • energy_MeV_u (float) – Kinetic energy in MeV/u.

  • particle_name (str) – Ion species.

  • material_name (str) – Target material.

  • source (str) – "SRIM" (default) or "libamtrack".

Returns:

CSDA range in um.

Return type:

float

Raises:

ValueError – If source or material_name are not recognised.

tracketch.physics.utils_ions.convert_MeV_to_MeV_u(Energy_MeV: float, particle_name: str) float[source]

Convert total kinetic energy (MeV) to energy per nucleon (MeV/u).

Parameters:
  • Energy_MeV (float) – Total kinetic energy in MeV.

  • particle_name (str) – Ion species identifier.

Returns:

Energy in MeV/u.

Return type:

float

tracketch.physics.utils_ions.convert_MeV_u_to_MeV(Energy_MeV_u: float, particle_name: str) float[source]

Convert energy per nucleon (MeV/u) to total kinetic energy (MeV).

Parameters:
  • Energy_MeV_u (float) – Energy in MeV per nucleon.

  • particle_name (str) – Ion species identifier.

Returns:

Total kinetic energy in MeV.

Return type:

float

tracketch.physics.utils_ions.get_energy_after_slab_MeV_u(E_initial_MeV_u: float, particle_name: str, slab_thickness_um: float, material_name: str = 'CR39', source: str = 'SRIM') float[source]

Residual energy after traversing a slab of given thickness.

Steps through the slab in small increments, computing the LET at each step to update the energy.

Parameters:
  • E_initial_MeV_u (float) – Incident energy in MeV/u.

  • particle_name (str) – Ion species.

  • slab_thickness_um (float) – Slab thickness in um.

  • material_name (str) – Target material (default "CR39").

  • source (str) – Stopping-power source (default "SRIM").

Returns:

Residual energy in MeV/u (0 if the ion stops).

Return type:

float

tracketch.physics.utils_ions.get_dose_map_Gy(z_um: ndarray, r_um: ndarray, energy_MeV_u_array: ndarray, particle_name: str, material_name: str = 'CR39', RDD_name: str = 'Cucinotta', LET_source: str = 'SRIM', core_radius_nm: float | None = None, normalise_to_LET: bool | None = None, verbose: bool = False, n_jobs: int = 1) ndarray[source]

Build a 2-D dose map by evaluating the RDD at each depth step.

Parameters:
  • z_um (ndarray, shape (n_z,)) – Depth coordinates in um.

  • r_um (ndarray, shape (n_r,)) – Radial coordinates in um.

  • energy_MeV_u_array (ndarray, shape (n_z,)) – Ion energy at each depth (from get_LET_energy_profile()).

  • particle_name (str) – Ion species.

  • material_name (str) – Target material.

  • RDD_name (str) – RDD model name.

  • LET_source (str) – Stopping-power source.

  • core_radius_nm (float or None) – Core radius override.

  • normalise_to_LET (bool or None) – Force LET normalisation.

  • verbose (bool) – Print diagnostics.

  • n_jobs (int) – Number of parallel workers for RDD evaluation. -1 uses all available CPU cores (via joblib). Default 1 runs sequentially.

Returns:

Local dose in Gy.

Return type:

ndarray, shape (n_z, n_r)

tracketch.physics.utils_ions.get_mean_core_value(metric_map: ndarray, r_um: ndarray, core_r_threshold_um: float = 0.1, min_core_r_um: float = 0.001) ndarray[source]

Average a map over the track core (small-r region) at each depth.

Parameters:
  • metric_map (ndarray, shape (n_z, n_r)) – Dose or etch-rate map.

  • r_um (ndarray, shape (n_r,)) – Radial coordinates in um.

  • core_r_threshold_um (float) – Outer boundary of the core region in um.

  • min_core_r_um (float) – Inner boundary of the core region in um.

Returns:

Mean value within the core at each depth. nan where no valid data exists.

Return type:

ndarray, shape (n_z,)

tracketch.physics.utils_ions.get_range_straggling_um(energy_MeV_u: float, particle_name: str, material_name: str) float[source]

Longitudinal range straggling from SRIM data.

Parameters:
  • energy_MeV_u (float) – Kinetic energy in MeV/u.

  • particle_name (str) – Ion species.

  • material_name (str) – Target material.

Returns:

Straggling in um. Returns 0 if the particle is not available in SRIM (justified for heavy ions with negligible straggling).

Return type:

float

tracketch.physics.utils_ions.apply_range_straggling(dz_um_list: ndarray, metric: ndarray, longitudinal_straggling_um: float, n_sigma: float = 1) ndarray[source]

Broaden a depth profile by Gaussian range-straggling convolution.

Parameters:
  • dz_um_list (ndarray) – Depth grid in um (assumed uniform spacing).

  • metric (ndarray) – Profile to broaden (same length as dz_um_list).

  • longitudinal_straggling_um (float) – 1-sigma straggling width in um.

  • n_sigma (float) – Number of sigma to apply (0 = no straggling).

Returns:

Broadened profile.

Return type:

ndarray

tracketch.physics.utils_ions.get_LET_energy_profile(dz_um_list: ndarray, energy_MeV_u: float, particle_name: str, material_name: str, range_straggling: bool = True, n_straggling_sigma: float = 1, source: str = 'SRIM') tuple[ndarray, ndarray][source]

Compute energy and LET profiles along depth.

For source="SRIM" the profiles are computed analytically by inverting the CSDA-range table (vectorised, no stepping loop). For source="libamtrack" the original iterative stepping is used.

Optionally applies longitudinal range straggling as a Gaussian convolution.

Parameters:
  • dz_um_list (ndarray) – Depth grid in um.

  • energy_MeV_u (float) – Incident energy in MeV/u.

  • particle_name (str) – Ion species.

  • material_name (str) – Target material.

  • range_straggling (bool) – Apply Gaussian straggling (default True).

  • n_straggling_sigma (float) – Number of straggling sigma (default 1).

  • source (str) – Stopping-power database (default "SRIM").

Returns:

  • energy_profile (ndarray) – Kinetic energy in MeV/u at each depth.

  • LET_profile (ndarray) – LET in keV/um at each depth.

tracketch.physics.utils_ions.get_f_dose_distribution(E_MeV_u: float, particle_name: str, RDD_name: str = 'Cucinotta', material_name: str = 'CR39', core_nm: float | None = None, LET_source: str = 'SRIM', f_cutoff: float = 1e-15, d_min_Gy: float = 1e-05, r_min_m: float = 5e-11, r_max_m: float = 0.01, npoints: int = 1000) tuple[ndarray, ndarray, ndarray][source]

Compute the local-dose probability density f(d) for an ion track.

The PDF describes the fraction of the track cross-section receiving a local dose between d and d + dd. Derived from the RDD by inverting r(d) and differentiating the cumulative area fraction.

Parameters:
  • E_MeV_u (float) – Kinetic energy in MeV/u.

  • particle_name (str) – Ion species.

  • RDD_name (str) – RDD model name.

  • material_name (str) – Target material.

  • core_nm (float or None) – Core radius override.

  • LET_source (str) – Stopping-power source.

  • f_cutoff (float) – Bins where f*d < f_cutoff are discarded.

  • d_min_Gy (float) – Minimum dose threshold.

  • r_min_m (float) – Inner radial sampling bound in metres.

  • r_max_m (float) – Outer radial sampling bound in metres.

  • npoints (int) – Number of radial sample points.

Returns:

  • f (ndarray) – Normalised dose PDF in Gy^{-1}.

  • midpoints_Gy (ndarray) – Dose bin midpoints in Gy.

  • dd_Gy (ndarray) – Dose bin widths in Gy.

Raises:

ValueError – If too few valid RDD points are found.