Skip to content

Commit

Permalink
Some style fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
gipert committed Nov 14, 2024
1 parent b609551 commit 34b6764
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 61 deletions.
55 changes: 27 additions & 28 deletions src/legendhpges/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,18 @@ def __repr__(self) -> str:
return f"{self.__class__.__name__}({self.metadata})"

def _g4_solid(self) -> geant4.solid.SolidBase:
"""Build (by default) a :class:`pyg4ometry.solid.GenericPolycone` instance from the (r, z) information.
"""Build a :class:`pyg4ometry.solid.GenericPolycone` instance from the ``(r, z)`` information.
Returns
-------
g4_solid
A derived class of :class:`pyg4ometry.solid.SolidBase` to be used to construct the logical volume.
A derived class of :class:`pyg4ometry.solid.SolidBase` to be used
to construct the logical volume.
Note
----
Detectors with a special geometry can have this method overridden in their class definition.
Detectors with a special geometry can have this method overridden
in their class definition.
"""
# return ordered r,z lists, default unit [mm]
r, z = self._decode_polycone_coord()
Expand All @@ -104,7 +106,7 @@ def _decode_polycone_coord(self) -> tuple[list[float], list[float]]:
Returns
-------
(r, z)
two lists of r and z coordinates, respectively.
two lists of `r` and `z` coordinates, respectively.
Note
----
Expand All @@ -117,7 +119,7 @@ def get_profile(self) -> tuple[list[float], list[float]]:
Returns
-------
(r.z)
two lists of r and z coordinates, respectively.
two lists of `r` and `z` coordinates, respectively.
Note
-----
Expand All @@ -138,18 +140,16 @@ def get_profile(self) -> tuple[list[float], list[float]]:
return r, z

def is_inside(self, coords: ArrayLike, tol: float = 1e-11) -> NDArray[bool]:
"""Compute whether each point is inside the shape
"""Compute whether each point is inside the volume.
Parameters
----------
coords
2D array of shape `(n,3)` of `(x,y,z)` coordinates for each of `n` points, second index corresponds to `(x,y,z)`.
2D array of shape `(n,3)` of `(x,y,z)` coordinates for each of `n`
points, second index corresponds to `(x,y,z)`.
tol
distance outside the surface which is considered inside.
Returns
-------
numpy array of booleans.
distance outside the surface which is considered inside. Should be
on the order of numerical precision of the floating point representation.
"""

if not isinstance(self.solid, geant4.solid.GenericPolycone):
Expand Down Expand Up @@ -190,15 +190,14 @@ def distance_to_surface(
Parameters
----------
coords
2D array of shape `(n,3)` of `(x,y,z)` coordinates for each of `n` points, second index corresponds to `(x,y,z)`.
2D array of shape `(n,3)` of `(x,y,z)` coordinates for each of `n`
points, second index corresponds to `(x,y,z)`.
surface_indices
list of indices of surfaces to consider. If `None` (the default) all surfaces used.
list of indices of surfaces to consider. If ``None`` (the default)
all surfaces used.
tol
distance outside the surface which is considered inside.
Returns
-------
numpy array of the distance from each point to the nearest surface.
distance outside the surface which is considered inside. Should be
on the order of numerical precision of the floating point representation.
Note
----
Expand Down Expand Up @@ -249,24 +248,24 @@ def mass(self) -> Quantity:
"""Mass of the HPGe."""
return (self.volume * (self.material.density * u.g / u.cm**3)).to(u.g)

def surface_area(self, surface_indices: list | None = None) -> list[Quantity]:
def surface_area(
self, surface_indices: ArrayLike | None = None
) -> NDArray[Quantity]:
"""Surface area of the HPGe.
If a list of surface_indices is provided the area is computed only considering these surfaces,
from :math:`r_i` to :math:`r_{i+1}` and :math:`z_i` to :math:`z_{i+1}`. Else the full area is computed.
If a list of surface_indices is provided the area is computed only
considering these surfaces, from :math:`r_i` to :math:`r_{i+1}` and
:math:`z_i` to :math:`z_{i+1}`. Else the full area is computed.
Parameters
----------
surface_indices
list of indices or None.
Returns
-------
a pint Quantity of the surface area
list of indices or ``None``.
Note
----
Calculation is based on a polycone geometry so is incorrect for asymmetric detectors.
Calculation is based on a polycone geometry so is incorrect for
asymmetric detectors.
"""
if not isinstance(self.solid, geant4.solid.GenericPolycone):
logging.warning("The area is that of the solid without cut")
Expand Down
8 changes: 5 additions & 3 deletions src/legendhpges/build_utils.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
from __future__ import annotations

from collections.abc import Mapping

def make_pplus(geometry: dict) -> tuple[list, list, list]:
"""Make the pplus contact for BeGe and some ICPC

def make_pplus(geometry: Mapping) -> tuple[list, list, list]:
"""Make the pplus contact for BeGe and some ICPC.
Methods to avoid duplicating code.
Parameters
----------
geometry
Dictionary with the geometry information.
dictionary with the geometry information.
Returns
-------
Expand Down
66 changes: 36 additions & 30 deletions src/legendhpges/utils.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from __future__ import annotations

import numba
import numpy as np
from numba import njit
from numpy.typing import ArrayLike, NDArray


@njit
@numba.njit(cache=True)
def convert_coords(coords: ArrayLike) -> NDArray:
"""Converts (x,y,z) coordinates into (r,z)
Expand All @@ -32,14 +32,16 @@ def shortest_distance_to_plane(
) -> NDArray:
"""Get the shortest distance from a plane (constrained in r and z) to each point.
The equation of the plane is given by :math:`a_1x+a_2y+a_3z=d`. Where :math:`\\vec{a}=(a_1,a_2,a_3)`.
The equation of the plane is given by :math:`a_1x+a_2y+a_3z=d`. Where
:math:`\\vec{a}=(a_1,a_2,a_3)`.
The closest point on the plane to the point (:math:`y`) is then given by:
.. math::
x =y-(y*a-d)*a/||a||^2
The distance is then given by the length of the vector :math:`x-y`. This function also checks if the
intersection point is above rmax or inside the zrange, if not nan is returned for that point.
The distance is then given by the length of the vector :math:`x-y`. This
function also checks if the intersection point is above `rmax` or inside the
`zrange`, if not, ``numpy.nan`` is returned for that point.
Parameters
----------
Expand All @@ -53,10 +55,6 @@ def shortest_distance_to_plane(
maximum radius for the plane.
zrange
range in z for the plane.
Returns
-------
np.array of distance for each point.
"""

def _dot(a, b):
Expand Down Expand Up @@ -94,7 +92,7 @@ def _norm(a):

def get_line_segments(
r: ArrayLike, z: ArrayLike, surface_indices: ArrayLike = None
) -> tuple[ArrayLike, ArrayLike]:
) -> tuple[NDArray, NDArray]:
"""Extracts the line segments from a shape.
Parameters
Expand All @@ -104,12 +102,14 @@ def get_line_segments(
z
array or list of vertical positions defining the polycone.
surface_indices
list of integer indices of surfaces to consider. If `None` (the default) all surfaces used.
list of integer indices of surfaces to consider. If ``None`` (the
default) all surfaces used.
Returns
-------
tuple of (s1,s2) arrays describing the line segments, both `s1` and `s2` have shape `(n_segments,2)`
where the first axis represents thhe segment and the second `(r,z)`.
tuple of (s1,s2) arrays describing the line segments, both `s1` and
`s2` have shape `(n_segments,2)` where the first axis represents thhe
segment and the second `(r,z)`.
"""
# build lists of pairs of coordinates
s1 = np.array([np.array([r1, z1]) for r1, z1 in zip(r[:-1], z[:-1])])
Expand All @@ -118,55 +118,61 @@ def get_line_segments(
if surface_indices is not None:
s1 = s1[surface_indices]
s2 = s2[surface_indices]

return s1, s2


@njit(cache=True)
@numba.njit(cache=True)
def shortest_distance(
s1_list: NDArray,
s2_list: NDArray,
points: NDArray,
tol: float = 1e-11,
signed: bool = True,
) -> tuple[NDArray, NDArray]:
"""Get the shortest distance between each point and the line segments defined by `s1_list` and `s2_list`.
"""Get the shortest distance between each point and a line segment.
Based on vector algebra where the distance vector is given by:
.. math::
d = s_1 - p - ( (n · (s_1- p)) * n )
where:
- :math:`s_1` is a vector from which the distance is measured,
- `p` is a point vector,
- `n` is a unit direction vector from :math:`s_1` to :math:`s_2`,
- `a` is another point vector.
If the projection point lies inside the segment s1-s2. Else the closest point is either :math:`s_1` or :math:`s_2`.
The distance is the modulus of this vector and this calculation is performed for each point.
A sign is attached based on the cross product of the line vector and the distance vector.
To avoid numerical issues any point within the tolerance is considered inside.
- :math:`s_1` is a vector from which the distance is measured,
- `p` is a point vector,
- `n` is a unit direction vector from :math:`s_1` to :math:`s_2`,
- `a` is another point vector.
If the projection point lies inside the segment s1-s2. Else the closest
point is either :math:`s_1` or :math:`s_2`. The distance is the modulus of
this vector and this calculation is performed for each point. A sign is
attached based on the cross product of the line vector and the distance
vector. To avoid numerical issues any point within the tolerance is
considered inside.
Parameters
----------
s1_list
`(n_segments,2)` np.array of the first points in the line segment, for the second axis indices 0,1 correspond to r,z.
`(n_segments,2)` np.array of the first points in the line segment, for
the second axis indices `0,1` correspond to `r,z`.
s2_list
second points, same format as s1.
second points, same format as `s1_list`.
points
`(n_points,2)` array of points to compare, first axis corresponds to the point index and the second to `(r,z)`.
`(n_points,2)` array of points to compare, first axis corresponds to
the point index and the second to `(r,z)`.
tol
tolerance when computing sign, points within this distance to the surface are pushed inside.
tolerance when computing sign, points within this distance to the
surface are pushed inside.
signed
boolean flag to attach a sign to the distance (positive if inside).
Returns
-------
`(n_points,n_segments)` numpy array of the shortest distances for each segment.
``(n_points,n_segments)`` numpy array of the shortest distances for each segment.
"""

# helped functions
# helper functions
def _dot(a, b):
return np.sum(a * b, axis=1)

Expand Down

0 comments on commit 34b6764

Please sign in to comment.