img_phy_sim.math

Mathematical and Geometric Utility Functions

This module provides lightweight mathematical helper functions for 2D geometry and angle-based computations. It is designed to support higher-level operations such as beam tracing, image-based simulations, and coordinate normalization.

The functions focus on conversions between angular and Cartesian representations, as well as normalization and denormalization of image coordinates.

Main features:

  • Generate evenly spaced degree ranges for directional sampling
  • Convert between degrees and 2D unit vectors
  • Convert 2D vectors back to degree angles
  • Normalize and denormalize 2D points for image-based coordinate systems

Typical use cases:

  • Generating input directions for beam tracing or ray simulation
  • Converting between angular and vector representations in geometric algorithms
  • Preparing coordinates for normalized image processing workflows

Dependencies:

  • math
  • numpy

Example:

import img_phy_sim as ips

# Generate sample directions
directions = ips.math.get_linear_degree_range(step_size=45)

# Convert each to a 2D vector
vectors = [ips.math.degree_to_vector(d) for d in directions]

# Convert back to degrees
recovered = [ips.math.vector_to_degree(v) for v in vectors]

# Normalize and denormalize a point
p_norm = ips.math.normalize_point((128, 64), width=256, height=128)
p_pixel = ips.math.denormalize_point(p_norm, width=256, height=128)

Functions:

  • get_linear_degree_range(...) - Generate evenly spaced degrees within a range.
  • degree_to_vector(...) - Convert a degree angle to a 2D unit vector.
  • vector_to_degree(...) - Convert a 2D vector into its corresponding degree.
  • normalize_point(...) - Normalize a 2D point to [0, 1] range.
  • denormalize_point(...) - Denormalize a 2D point to pixel coordinates.
  • numpy_info(...) - Get statistics about an numpy array.
  1"""
  2**Mathematical and Geometric Utility Functions**
  3
  4This module provides lightweight mathematical helper functions for 2D geometry
  5and angle-based computations. It is designed to support higher-level operations
  6such as beam tracing, image-based simulations, and coordinate normalization.
  7
  8The functions focus on conversions between angular and Cartesian representations,
  9as well as normalization and denormalization of image coordinates.
 10
 11Main features:
 12- Generate evenly spaced degree ranges for directional sampling
 13- Convert between degrees and 2D unit vectors
 14- Convert 2D vectors back to degree angles
 15- Normalize and denormalize 2D points for image-based coordinate systems
 16
 17Typical use cases:
 18- Generating input directions for beam tracing or ray simulation
 19- Converting between angular and vector representations in geometric algorithms
 20- Preparing coordinates for normalized image processing workflows
 21
 22Dependencies:
 23- math
 24- numpy
 25
 26Example:
 27```python
 28import img_phy_sim as ips
 29
 30# Generate sample directions
 31directions = ips.math.get_linear_degree_range(step_size=45)
 32
 33# Convert each to a 2D vector
 34vectors = [ips.math.degree_to_vector(d) for d in directions]
 35
 36# Convert back to degrees
 37recovered = [ips.math.vector_to_degree(v) for v in vectors]
 38
 39# Normalize and denormalize a point
 40p_norm = ips.math.normalize_point((128, 64), width=256, height=128)
 41p_pixel = ips.math.denormalize_point(p_norm, width=256, height=128)
 42```
 43
 44Functions:
 45- get_linear_degree_range(...) - Generate evenly spaced degrees within a range.
 46- degree_to_vector(...)        - Convert a degree angle to a 2D unit vector.
 47- vector_to_degree(...)        - Convert a 2D vector into its corresponding degree.
 48- normalize_point(...)         - Normalize a 2D point to [0, 1] range.
 49- denormalize_point(...)       - Denormalize a 2D point to pixel coordinates.
 50- numpy_info(...)              - Get statistics about an numpy array.
 51"""
 52
 53
 54
 55# ---------------
 56# >>> Imports <<<
 57# ---------------
 58import math
 59import numpy as np
 60
 61import numba
 62
 63
 64
 65# -----------------
 66# >>> Constants <<<
 67# -----------------
 68_DEG2RAD = math.pi / 180.0
 69_RAD2DEG = 180.0 / math.pi
 70
 71
 72
 73# -----------------
 74# >>> Functions <<<
 75# -----------------
 76def get_linear_degree_range(start=0, stop=360, step_size=10, offset=0):
 77    """
 78    Generate a list of degrees within a linear range.
 79
 80    Parameters:
 81    - start (int, optional): Starting degree (default is 0).
 82    - stop (int, optional): Ending degree (default is 360).
 83    - step_size (int, optional): Step size between degrees (default is 10).
 84    - offset (int, optional): Offset to add to each degree value (default is 0).
 85
 86    Returns:
 87    - list: List of degree values adjusted by offset and modulo 360.
 88    """
 89    degree_range = np.arange(start=start, stop=stop, step=step_size).tolist() # list(range(0, 360, step_size))
 90    return list(map(lambda x: (x+offset) % 360, degree_range))
 91
 92
 93
 94def degree_to_vector(degree):
 95    """
 96    Convert a degree angle to a 2D unit vector.
 97
 98    Parameters:
 99    - degree (float): Angle in degrees.
100
101    Returns:
102    - list: 2D vector [cos(degree), sin(degree)].
103    """
104    # rad = math.radians(degree)
105    # return [math.cos(rad), math.sin(rad)]
106    rad = degree * _DEG2RAD
107    return (math.cos(rad), math.sin(rad))
108
109
110
111
112def vector_to_degree(x, y):
113    """
114    Convert a 2D vector into its corresponding degree angle.
115
116    Parameters:
117    - vector (tuple): 2D vector (x, y).
118
119    Returns:
120    - int: Angle in degrees within the range [0, 360).
121    """
122    # x, y = vector
123    # degree = math.degrees(math.atan2(y, x))  # atan2 returns angles between -180° and 180°
124    # return int( degree % 360 ) 
125    deg = math.atan2(y, x) * _RAD2DEG
126    return int(deg % 360.0)
127
128
129
130def normalize_point(x, y, width, height):
131    """
132    Normalize a 2D point to the range [0, 1].
133
134    Parameters:
135    - point (tuple): (x, y) coordinates of the point.
136    - width (int): Image or grid width.
137    - height (int): Image or grid height.
138
139    Returns:
140    - tuple: Normalized point (x / (width - 1), y / (height - 1)).
141    """
142    # return (x / (width - 1), y / (height - 1))
143    return ( (1.0 / (width - 1.0))*x, 
144             (1.0 / (height - 1.0))*y)
145
146
147
148
149def denormalize_point(x, y, width, height):
150    """
151    Denormalize a 2D point from normalized coordinates back to pixel coordinates.
152
153    Parameters:
154    - point (tuple): Normalized (x, y) coordinates.
155    - width (int): Image or grid width.
156    - height (int): Image or grid height.
157
158    Returns:
159    - tuple: Denormalized point (x * (width - 1), y * (height - 1)).
160    """
161    return (x * (width - 1.0), y * (height - 1.0))
162
163
164
165def numpy_info(numpy_array, should_print=True):
166    """
167    Print and return basic statistical information about a NumPy array.
168
169    Computes common descriptive statistics such as mean, median, standard
170    deviation, variance, minimum, maximum, and array shape. This function is
171    primarily intended for quick debugging and inspection of intermediate
172    results in numerical or image-processing pipelines.
173
174    Parameters:
175    - numpy_array (np.ndarray): Input NumPy array to analyze.
176    - should_print (bool): If True, print the statistics to stdout.
177
178    Returns:
179    - str: A formatted string containing the computed statistics.
180    """
181    result = "Array Statistics:"
182    result += f"\n    - mean = {numpy_array.mean():.2f}"
183    result += f"\n    - median = {np.median(numpy_array):.2f}"
184    # result += f"\n    - percentile = {np.percentile(numpy_array, [25, 50, 75])}"
185    result += f"\n    - std = {numpy_array.std():.2f}"
186    result += f"\n    - var = {numpy_array.var():.2f}"
187    result += f"\n    - min = {numpy_array.min():.2f}"
188    result += f"\n    - max = {numpy_array.max():.2f}"
189    result += f"\n    - shape = {numpy_array.shape}"
190    
191    if should_print:
192        print(result)
193    return result
194
195
196
197# -----------------------
198# >>> Numba Functions <<<
199# -----------------------
200degree_to_vector_numba = numba.njit(cache=True, fastmath=True)(degree_to_vector)
201vector_to_degree_numba = numba.njit(cache=True, fastmath=True)(vector_to_degree)
202normalize_point_numba = numba.njit(cache=True, fastmath=True)(normalize_point)
203denormalize_point_numba = numba.njit(cache=True, fastmath=True)(denormalize_point)
def get_linear_degree_range(start=0, stop=360, step_size=10, offset=0):
77def get_linear_degree_range(start=0, stop=360, step_size=10, offset=0):
78    """
79    Generate a list of degrees within a linear range.
80
81    Parameters:
82    - start (int, optional): Starting degree (default is 0).
83    - stop (int, optional): Ending degree (default is 360).
84    - step_size (int, optional): Step size between degrees (default is 10).
85    - offset (int, optional): Offset to add to each degree value (default is 0).
86
87    Returns:
88    - list: List of degree values adjusted by offset and modulo 360.
89    """
90    degree_range = np.arange(start=start, stop=stop, step=step_size).tolist() # list(range(0, 360, step_size))
91    return list(map(lambda x: (x+offset) % 360, degree_range))

Generate a list of degrees within a linear range.

Parameters:

  • start (int, optional): Starting degree (default is 0).
  • stop (int, optional): Ending degree (default is 360).
  • step_size (int, optional): Step size between degrees (default is 10).
  • offset (int, optional): Offset to add to each degree value (default is 0).

Returns:

  • list: List of degree values adjusted by offset and modulo 360.
def degree_to_vector(degree):
 95def degree_to_vector(degree):
 96    """
 97    Convert a degree angle to a 2D unit vector.
 98
 99    Parameters:
100    - degree (float): Angle in degrees.
101
102    Returns:
103    - list: 2D vector [cos(degree), sin(degree)].
104    """
105    # rad = math.radians(degree)
106    # return [math.cos(rad), math.sin(rad)]
107    rad = degree * _DEG2RAD
108    return (math.cos(rad), math.sin(rad))

Convert a degree angle to a 2D unit vector.

Parameters:

  • degree (float): Angle in degrees.

Returns:

  • list: 2D vector [cos(degree), sin(degree)].
def vector_to_degree(x, y):
113def vector_to_degree(x, y):
114    """
115    Convert a 2D vector into its corresponding degree angle.
116
117    Parameters:
118    - vector (tuple): 2D vector (x, y).
119
120    Returns:
121    - int: Angle in degrees within the range [0, 360).
122    """
123    # x, y = vector
124    # degree = math.degrees(math.atan2(y, x))  # atan2 returns angles between -180° and 180°
125    # return int( degree % 360 ) 
126    deg = math.atan2(y, x) * _RAD2DEG
127    return int(deg % 360.0)

Convert a 2D vector into its corresponding degree angle.

Parameters:

  • vector (tuple): 2D vector (x, y).

Returns:

  • int: Angle in degrees within the range [0, 360).
def normalize_point(x, y, width, height):
131def normalize_point(x, y, width, height):
132    """
133    Normalize a 2D point to the range [0, 1].
134
135    Parameters:
136    - point (tuple): (x, y) coordinates of the point.
137    - width (int): Image or grid width.
138    - height (int): Image or grid height.
139
140    Returns:
141    - tuple: Normalized point (x / (width - 1), y / (height - 1)).
142    """
143    # return (x / (width - 1), y / (height - 1))
144    return ( (1.0 / (width - 1.0))*x, 
145             (1.0 / (height - 1.0))*y)

Normalize a 2D point to the range [0, 1].

Parameters:

  • point (tuple): (x, y) coordinates of the point.
  • width (int): Image or grid width.
  • height (int): Image or grid height.

Returns:

  • tuple: Normalized point (x / (width - 1), y / (height - 1)).
def denormalize_point(x, y, width, height):
150def denormalize_point(x, y, width, height):
151    """
152    Denormalize a 2D point from normalized coordinates back to pixel coordinates.
153
154    Parameters:
155    - point (tuple): Normalized (x, y) coordinates.
156    - width (int): Image or grid width.
157    - height (int): Image or grid height.
158
159    Returns:
160    - tuple: Denormalized point (x * (width - 1), y * (height - 1)).
161    """
162    return (x * (width - 1.0), y * (height - 1.0))

Denormalize a 2D point from normalized coordinates back to pixel coordinates.

Parameters:

  • point (tuple): Normalized (x, y) coordinates.
  • width (int): Image or grid width.
  • height (int): Image or grid height.

Returns:

  • tuple: Denormalized point (x * (width - 1), y * (height - 1)).
def numpy_info(numpy_array, should_print=True):
166def numpy_info(numpy_array, should_print=True):
167    """
168    Print and return basic statistical information about a NumPy array.
169
170    Computes common descriptive statistics such as mean, median, standard
171    deviation, variance, minimum, maximum, and array shape. This function is
172    primarily intended for quick debugging and inspection of intermediate
173    results in numerical or image-processing pipelines.
174
175    Parameters:
176    - numpy_array (np.ndarray): Input NumPy array to analyze.
177    - should_print (bool): If True, print the statistics to stdout.
178
179    Returns:
180    - str: A formatted string containing the computed statistics.
181    """
182    result = "Array Statistics:"
183    result += f"\n    - mean = {numpy_array.mean():.2f}"
184    result += f"\n    - median = {np.median(numpy_array):.2f}"
185    # result += f"\n    - percentile = {np.percentile(numpy_array, [25, 50, 75])}"
186    result += f"\n    - std = {numpy_array.std():.2f}"
187    result += f"\n    - var = {numpy_array.var():.2f}"
188    result += f"\n    - min = {numpy_array.min():.2f}"
189    result += f"\n    - max = {numpy_array.max():.2f}"
190    result += f"\n    - shape = {numpy_array.shape}"
191    
192    if should_print:
193        print(result)
194    return result

Print and return basic statistical information about a NumPy array.

Computes common descriptive statistics such as mean, median, standard deviation, variance, minimum, maximum, and array shape. This function is primarily intended for quick debugging and inspection of intermediate results in numerical or image-processing pipelines.

Parameters:

  • numpy_array (np.ndarray): Input NumPy array to analyze.
  • should_print (bool): If True, print the statistics to stdout.

Returns:

  • str: A formatted string containing the computed statistics.
def degree_to_vector_numba(degree):
 95def degree_to_vector(degree):
 96    """
 97    Convert a degree angle to a 2D unit vector.
 98
 99    Parameters:
100    - degree (float): Angle in degrees.
101
102    Returns:
103    - list: 2D vector [cos(degree), sin(degree)].
104    """
105    # rad = math.radians(degree)
106    # return [math.cos(rad), math.sin(rad)]
107    rad = degree * _DEG2RAD
108    return (math.cos(rad), math.sin(rad))

Convert a degree angle to a 2D unit vector.

Parameters:

  • degree (float): Angle in degrees.

Returns:

  • list: 2D vector [cos(degree), sin(degree)].
def vector_to_degree_numba(x, y):
113def vector_to_degree(x, y):
114    """
115    Convert a 2D vector into its corresponding degree angle.
116
117    Parameters:
118    - vector (tuple): 2D vector (x, y).
119
120    Returns:
121    - int: Angle in degrees within the range [0, 360).
122    """
123    # x, y = vector
124    # degree = math.degrees(math.atan2(y, x))  # atan2 returns angles between -180° and 180°
125    # return int( degree % 360 ) 
126    deg = math.atan2(y, x) * _RAD2DEG
127    return int(deg % 360.0)

Convert a 2D vector into its corresponding degree angle.

Parameters:

  • vector (tuple): 2D vector (x, y).

Returns:

  • int: Angle in degrees within the range [0, 360).
def normalize_point_numba(x, y, width, height):
131def normalize_point(x, y, width, height):
132    """
133    Normalize a 2D point to the range [0, 1].
134
135    Parameters:
136    - point (tuple): (x, y) coordinates of the point.
137    - width (int): Image or grid width.
138    - height (int): Image or grid height.
139
140    Returns:
141    - tuple: Normalized point (x / (width - 1), y / (height - 1)).
142    """
143    # return (x / (width - 1), y / (height - 1))
144    return ( (1.0 / (width - 1.0))*x, 
145             (1.0 / (height - 1.0))*y)

Normalize a 2D point to the range [0, 1].

Parameters:

  • point (tuple): (x, y) coordinates of the point.
  • width (int): Image or grid width.
  • height (int): Image or grid height.

Returns:

  • tuple: Normalized point (x / (width - 1), y / (height - 1)).
def denormalize_point_numba(x, y, width, height):
150def denormalize_point(x, y, width, height):
151    """
152    Denormalize a 2D point from normalized coordinates back to pixel coordinates.
153
154    Parameters:
155    - point (tuple): Normalized (x, y) coordinates.
156    - width (int): Image or grid width.
157    - height (int): Image or grid height.
158
159    Returns:
160    - tuple: Denormalized point (x * (width - 1), y * (height - 1)).
161    """
162    return (x * (width - 1.0), y * (height - 1.0))

Denormalize a 2D point from normalized coordinates back to pixel coordinates.

Parameters:

  • point (tuple): Normalized (x, y) coordinates.
  • width (int): Image or grid width.
  • height (int): Image or grid height.

Returns:

  • tuple: Denormalized point (x * (width - 1), y * (height - 1)).