Shortcuts

Source code for tomopt.benchmarks.u_lorry.data

from typing import List, Tuple

import numpy as np
import torch
from torch import Tensor

from ...core import X0, RadLengthFunc
from ...optimisation.data.passives import AbsPassiveGenerator
from ...volume import Volume

__all__ = ["ULorryPassiveGenerator"]


[docs]class ULorryPassiveGenerator(AbsPassiveGenerator): r""" Research tested only: no unit tests """ def __init__( self, volume: Volume, u_volume: float, # [m3] u_prob: float = 0.5, fill_frac: float = 0.8, x0_lorry: float = X0["iron"], bkg_materials: List[str] = ["air", "iron"], ) -> None: super().__init__(volume=volume, materials=["iron", "uranium"]) self.u_volume, self.u_prob, self.fill_frac, self.x0_lorry, self.bkg_materials = u_volume, u_prob, fill_frac, x0_lorry, bkg_materials self.bkg_x0s = Tensor([X0[m] for m in self.bkg_materials], device=self.volume.device) self.n_u_voxels = np.max((1, np.round(self.u_volume / (self.size**3), decimals=3))) self.xy_shp = (self.lw / self.size).astype(int).tolist() self.bkg_z_range = ((self.z_range[0]) + self.size, self.fill_frac * self.z_range[1]) self._compute_sizes() def _compute_sizes(self) -> None: max_n = max((np.max(self.xy_shp), np.round((self.bkg_z_range[1] - self.bkg_z_range[0]) / self.size))) szs = torch.combinations(torch.arange(1, max_n + 1), r=3, with_replacement=True) self.szs = szs[szs.prod(-1) * (self.size**3) == self.u_volume].numpy().astype(float) if len(self.szs) == 0: raise ValueError(f"Unable to form blocks of specified volume ({self.u_volume}) from voxels of size {self.size}") def _get_block_coords(self) -> Tuple[np.ndarray, np.ndarray]: i = np.random.randint(len(self.szs)) block_size = np.random.choice(self.szs[i], size=3, replace=False) block_size[2] = block_size[2] * self.size block_low = np.hstack( ( int(np.random.uniform(0, self.xy_shp[0] - block_size[0])), # voxels int(np.random.uniform(0, self.xy_shp[1] - block_size[1])), # voxels np.random.uniform(self.bkg_z_range[0], self.bkg_z_range[1] - block_size[2]), # m ) ) block_high = block_low + block_size return block_low, block_high def _generate(self) -> Tuple[RadLengthFunc, Tensor]: block_present = torch.rand(1) < self.u_prob if block_present: block_low, block_high = self._get_block_coords() def generator(*, z: Tensor, lw: Tensor, size: float) -> Tensor: if z <= self.bkg_z_range[0]: x0 = self.x0_lorry * torch.ones(self.xy_shp) elif z > self.bkg_z_range[0] and z <= self.bkg_z_range[1]: x0 = self.bkg_x0s[torch.randint(high=len(self.bkg_x0s), size=(self.xy_shp[0] * self.xy_shp[1],), device=self.bkg_x0s.device)].reshape( self.xy_shp ) elif z > self.bkg_z_range[1]: x0 = X0["air"] * torch.ones(self.xy_shp) if block_present: if z > block_low[2] and z <= block_high[2]: x0[block_low[0].astype(int) : block_high[0].astype(int), block_low[1].astype(int) : block_high[1].astype(int)] = X0["uranium"] return x0 return generator, block_present.long()

Docs

Access comprehensive developer and user documentation for TomOpt

View Docs

Tutorials

Get tutorials for beginner and advanced researchers demonstrating many of the features of TomOpt

View Tutorials