Module pept.utilities.traverse
Source code
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# File : __init__.py
# License: GNU v3.0
# Author : Andrei Leonard Nicusan <a.l.nicusan@bham.ac.uk>
# Date : 14.01.2020
from .traverse2d import traverse2d
from .traverse3d import traverse3d
__all__ = [
"traverse2d",
"traverse3d",
]
__author__ = "Andrei Leonard Nicusan"
__credits__ = ["Andrei Leonard Nicusan", "Kit Windows-Yule", "Sam Manger"]
__license__ = "GNU v3.0"
__maintainer__ = "Andrei Leonard Nicusan"
__email__ = "a.l.nicusan@bham.ac.uk"
__status__ = "Development"
Functions
def traverse2d(...)-
Fast voxel traversal for 2D lines (or LoRs).
Function Signature: traverse3d( long[:, :] pixels, # Initialised to zero! double[:, :] lines, # Has exactly 7 columns! double[:] grid_x, # Has pixels.shape[0] + 1 elements! double[:] grid_y, # Has pixels.shape[1] + 1 elements! )
This function computes the number of lines that passes through each pixel, saving the result in
pixels. It does so in an efficient manner, in which for every line, only the pixels that it passes through are traversed.As it is highly optimised, this function does not perform any checks on the validity of the input data. Please check the parameters before calling
traverse2d(), as it WILL segfault on wrong input data. Details are given below, along with an example call.Parameters
pixels : numpy.ndarray(dtype = numpy.int64, ndim = 2) The `pixels` parameter is a numpy.ndarray of shape (X, Y) that has been initialised to zeros before the function call. The values will be modified in-place in the function to reflect the number of lines that pass through each pixel. lines : numpy.ndarray(dtype = numpy.float64, ndim = 2) The `lines` parameter is a numpy.ndarray of shape(N, 5), where each row is formatted as [time, x1, y1, x2, y2]. Only indices 1:5 will be used as the two points P1 = [x1, y1] and P2 = [x2, y2] defining the line (or LoR). grid_x : numpy.ndarray(dtype = numpy.float64, ndim = 1) The grid_x parameter is a one-dimensional grid that delimits the pixels in the x-dimension. It must be *sorted* in ascending order with *equally-spaced* numbers and length X + 1 (pixels.shape[0] + 1). grid_y : numpy.ndarray(dtype = numpy.float64, ndim = 1) The grid_y parameter is a one-dimensional grid that delimits the pixels in the y-dimension. It must be *sorted* in ascending order with *equally-spaced* numbers and length Y + 1 (pixels.shape[1] + 1).Example usage
The input parameters can be easily generated using numpy before calling the function. For example, if a plane of 300 x 400 is split into 30 x 40 pixels, a possible code would be:
>>> import numpy as np >>> from pept.utilities.traverse import traverse2d >>> >>> plane = [300, 400] >>> number_of_pixels = [30, 40] >>> pixels = np.zeros(number_of_pixels)The grid has one extra element than the number of pixels. For example, 5 pixels between 0 and 5 would be delimited by the grid [0, 1, 2, 3, 4, 5] which has 6 elements (see off-by-one errors - story of my life).
>>> grid_x = np.linspace(0, plane[0], number_of_pixels[0] + 1) >>> grid_y = np.linspace(0, plane[1], number_of_pixels[1] + 1) >>> >>> random_lines = np.random.random((100, 5)) * 100Calling
traverse2d()will modifypixelsin-place.>>> traverse2d(pixels, random_lines, grid_x, grid_y)Note
This function is an adaptation of a widely-used algorithm [1], optimised for PEPT LoRs traversal.
.. [1] Amanatides J, Woo A. A fast voxel traversal algorithm for ray tracing. InEurographics 1987 Aug 24 (Vol. 87, No. 3, pp. 3-10)..
def traverse3d(...)-
Fast voxel traversal for 3D lines (or LoRs).
Function Signature: traverse3d( long[:, :, :] voxels, # Initialised to zero! double[:, :] lines, # Has exactly 7 columns! double[:] grid_x, # Has voxels.shape[0] + 1 elements! double[:] grid_y, # Has voxels.shape[1] + 1 elements! double[:] grid_z # Has voxels.shape[2] + 1 elements! )
This function computes the number of lines that passes through each voxel, saving the result in
voxels. It does so in an efficient manner, in which for every line, only the voxels that is passes through are traversed.As it is highly optimised, this function does not perform any checks on the validity of the input data. Please check the parameters before calling
traverse3d(), as it WILL segfault on wrong input data. Details are given below, along with an example call.Parameters
voxels : numpy.ndarray(dtype = numpy.int64, ndim = 3) The `voxels` parameter is a numpy.ndarray of shape (X, Y, Z) that has been initialised to zeros before the function call. The values will be modified in-place in the function to reflect the number of lines that pass through each voxel. lines : numpy.ndarray(dtype = numpy.float64, ndim = 2) The `lines` parameter is a numpy.ndarray of shape(N, 7), where each row is formatted as [time, x1, y1, z1, x2, y2, z2]. Only indices 1:7 will be used as the two points P1 = [x1, y1, z2] and P2 = [x2, y2, z2] defining the line (or LoR). grid_x : numpy.ndarray(dtype = numpy.float64, ndim = 1) The grid_x parameter is a one-dimensional grid that delimits the voxels in the x-dimension. It must be *sorted* in ascending order with *equally-spaced* numbers and length X + 1 (voxels.shape[0] + 1). grid_y : numpy.ndarray(dtype = numpy.float64, ndim = 1) The grid_y parameter is a one-dimensional grid that delimits the voxels in the y-dimension. It must be *sorted* in ascending order with *equally-spaced* numbers and length Y + 1 (voxels.shape[1] + 1). grid_z : numpy.ndarray(dtype = numpy.float64, ndim = 1) The grid_z parameter is a one-dimensional grid that delimits the voxels in the z-dimension. It must be *sorted* in ascending order with *equally-spaced* numbers and length Z + 1 (voxels.shape[2] + 1).Example usage
The input parameters can be easily generated using numpy before calling the function. For example, if a volume of 300 x 400 x 500 is split into 30 x 40 x 50 voxels, a possible code would be:
>>> import numpy as np >>> from pept.utilities.traverse import traverse3d >>> >>> volume = [300, 400, 500] >>> number_of_voxels = [30, 40, 50] >>> voxels = np.zeros(number_of_voxels)The grid has one extra element than the number of voxels. For example, 5 voxels between 0 and 5 would be delimited by the grid [0, 1, 2, 3, 4, 5] which has 6 elements (see off-by-one errors - story of my life).
>>> grid_x = np.linspace(0, volume[0], number_of_voxels[0] + 1) >>> grid_y = np.linspace(0, volume[1], number_of_voxels[1] + 1) >>> grid_z = np.linspace(0, volume[2], number_of_voxels[2] + 1) >>> >>> random_lines = np.random.random((100, 7)) * 300Calling
traverse3d()will modifyvoxelsin-place.>>> traverse3d(voxels, random_lines, grid_x, grid_y, grid_z)Note
This function is an adaptation of a widely-used algorithm [1], optimised for PEPT LoRs traversal.
.. [1] Amanatides J, Woo A. A fast voxel traversal algorithm for ray tracing. InEurographics 1987 Aug 24 (Vol. 87, No. 3, pp. 3-10)..