Source code for monte_carlo_analysis.utils.numba_utils
"""
**Author** : Robin Camarasa
**Institution** : Erasmus Medical Center
**Position** : PhD student
**Contact** : r.camarasa@erasmusmc.nl
**Date** : 2020-10-23
**Project** : monte_carlo_analysis
** Implement numba util functions **
Numba histogram
- Code adapted from: https://numba.pydata.org/numba-examples/examples/density_estimation/histogram/results.html
"""
import numba
import numpy as np
[docs]@numba.jit(nopython=True)
def get_bin_edges(bins: int, min_value: float, max_value: float) -> np.array:
"""
Compute the number of bins
:param bins: Number of bin in the histogram
:param min_value: Minimum value of the histogram
:param max_value: Minimum value of the histogram
"""
bin_edges = np.zeros((bins+1,), dtype=np.float64)
delta = (max_value - min_value) / bins
for i in range(bin_edges.shape[0]):
bin_edges[i] = min_value + i * delta
bin_edges[-1] = max_value # Avoid roundoff error on last point
return bin_edges
[docs]@numba.jit(nopython=True)
def compute_bin(
x: np.array, bin_edges: np.array,
min_value: float, max_value: float
) -> np.array:
"""
Compute the histogram bins
:param x: Flat array
:param bin_edges: Edges of the bin
:param min_value: Minimum value of the histogram
:param max_value: Minimum value of the histogram
"""
# assuming uniform bins for now
n = bin_edges.shape[0] - 1
# special case to mirror NumPy behavior for last bin
if x == max_value:
return n - 1 # max_value always in last bin
bin = int(n * (x - min_value) / (max_value - min_value))
if bin < 0 or bin >= n:
return None
else:
return bin
[docs]@numba.jit(nopython=True)
def numba_histogram(
a: np.array, bins: int, min_value: float = None,
max_value: float = None, normalized: bool = False
) -> tuple:
"""
Compute an histogram using numba
:param a: array to transform to histogram
:param bins: Number of bins
:param min_value: Minimum value of the histogram
:param max_value: Minimum value of the histogram
:param normalized: Set normalization of the array
"""
if min_value is None:
min_value = a.min()
if max_value is None:
max_value = a.max()
hist = np.zeros((bins,))
bin_edges = get_bin_edges(
bins, min_value, max_value
)
if normalized:
increment = 1. / a.shape[0]
else:
increment = 1.
for x in a.flat:
bin = compute_bin(
x, bin_edges, min_value,
max_value
)
if bin is not None:
hist[int(bin)] += increment
return hist, bin_edges
[docs]@numba.jit(nopython=True)
def numba_cumul_histogram(
a: np.array, bins: int, min_value: float = None,
max_value: float = None, normalized: bool = False
) -> tuple:
"""
Compute a cumulated histogram using numba
:param a: array to transform to histogram
:param bins: Number of bins
:param min_value: Minimum value of the histogram
:param max_value: Minimum value of the histogram
:param normalized: Set normalization of the array
"""
if min_value is None:
min_value = a.min()
if max_value is None:
max_value = a.max()
hist = np.zeros((bins,))
bin_edges = get_bin_edges(
bins, min_value, max_value
)
if normalized:
increment = 1. / a.shape[0]
else:
increment = 1.
for x in a.flat:
bin = compute_bin(
x, bin_edges, min_value,
max_value
)
if bin is not None:
hist[int(bin)] += increment
for i in range(1, bins):
hist[i] = hist[i - 1] + hist[i]
return hist, bin_edges