Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
37e82f9
Revise README for Python versions and clarity
giovannivolpe Jun 16, 2026
cbef6b9
Update README.md
giovannivolpe Jun 16, 2026
69efedc
DTGS171A
giovannivolpe Jun 16, 2026
9d5acf7
DTGS171B > DTGS172
giovannivolpe Jun 16, 2026
4cc530f
Update DTGS172_bacteria.ipynb
giovannivolpe Jun 16, 2026
d543143
DTAT311 eliminated
giovannivolpe Jun 16, 2026
d927772
optical update
giovannivolpe Jun 16, 2026
fbf87b2
DTAT321 > DTATop1
giovannivolpe Jun 16, 2026
9c7f52a
DTAT323 > DTATop2
giovannivolpe Jun 16, 2026
266a696
u
giovannivolpe Jun 16, 2026
eb35e3b
DTAT324 > DTATo30
giovannivolpe Jun 16, 2026
e5f2926
DTAT325 > DTATo40
giovannivolpe Jun 16, 2026
cf90e3c
DTAT327 > DTATo50
giovannivolpe Jun 16, 2026
5835b62
DTAT329 > DTATo60
giovannivolpe Jun 16, 2026
3e6a0ef
DTAT381 > DTATo90
giovannivolpe Jun 16, 2026
0c0ff4d
DTAT306 > DTAT311
giovannivolpe Jun 16, 2026
7356a93
DTAT341 > DTAT321
giovannivolpe Jun 16, 2026
306cf39
DTAT321 > DTAT331
giovannivolpe Jun 16, 2026
f6f3744
Create DTAT321_wrappers.ipynb
giovannivolpe Jun 16, 2026
f3f7fb6
u
giovannivolpe Jun 16, 2026
f07ec78
u
giovannivolpe Jun 16, 2026
a3a31ee
u
giovannivolpe Jun 16, 2026
c6247d8
Fix 0-sliced volume edge cases and skip Mie autograd tests on old tor…
cmanzo Jun 16, 2026
a6c113a
Update tutorial links to include 'optical' prefix
giovannivolpe Jun 16, 2026
332ea92
Update features.py
giovannivolpe Jun 17, 2026
24b472d
Update DTGS101_intro.ipynb
giovannivolpe Jun 17, 2026
3ae5dae
u
giovannivolpe Jun 17, 2026
0625a85
Update DTGS106_particle_image_modalities.ipynb
giovannivolpe Jun 17, 2026
d2a6327
Update DTGS101_intro.ipynb
giovannivolpe Jun 18, 2026
0affd25
Update DTGS106_particle_image_modalities.ipynb
giovannivolpe Jun 18, 2026
8e40ab8
Update DTGS111_datafiles.ipynb
giovannivolpe Jun 18, 2026
4c2ef66
Update DTGS121_tracking_particle_cnn.ipynb
giovannivolpe Jun 18, 2026
b6f14d9
Update DTGS126_characterizing_aberrations_cnn.ipynb
giovannivolpe Jun 18, 2026
44eb0c0
Update DTGS127_characterizing_aberrations_optuna.ipynb
giovannivolpe Jun 18, 2026
de32bf0
changes for ISCAT backcompatibility
cmanzo Jun 19, 2026
400ad58
Merge branch 'gv/final/features2' of https://github.com/DeepTrackAI/D…
cmanzo Jun 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 26 additions & 28 deletions README-pypi.md

Large diffs are not rendered by default.

82 changes: 42 additions & 40 deletions README.md

Large diffs are not rendered by default.

61 changes: 20 additions & 41 deletions deeptrack/backend/mie.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Mie scattering calculations.

This module provides functions to perform Mie scattering calculations,
including computation of spherical harmonics coefficients and related
This module provides functions to perform Mie scattering calculations,
including computation of spherical harmonics coefficients and related
operations.

Module Structure
Expand Down Expand Up @@ -32,9 +32,6 @@

"""

#TODO ***??*** revise class docstring
#TODO ***??*** revise DTAT399E

from __future__ import annotations

import array_api_compat as apc
Expand Down Expand Up @@ -141,7 +138,6 @@ def _zeros(shape, dtype, reference=None):
return xp.zeros(shape, **kwargs)


#TODO ***??*** revise coefficients - torch, docstring, unit test
def coefficients(
m: float | complex,
a: float,
Expand All @@ -150,7 +146,7 @@ def coefficients(
"""Calculate the Mie scattering coefficients for a spherical particle.

These coefficients are used in the computation of the scattering
and absorption of light by the particle. The terms up to (and including)
and absorption of light by the particle. The terms up to (and including)
order L are calculated using Riccati-Bessel polynomials.

Parameters
Expand Down Expand Up @@ -192,30 +188,21 @@ def coefficients(
xix = ricbesh(l, a)
dxix = dricbesh(l, a)

A.append(
(m * Smx * dSx - Sx * dSmx)
/
(m * Smx * dxix - xix * dSmx)
)
B.append(
(Smx * dSx - m * Sx * dSmx)
/
(Smx * dxix - m * xix * dSmx)
)
A.append((m * Smx * dSx - Sx * dSmx) / (m * Smx * dxix - xix * dSmx))
B.append((Smx * dSx - m * Sx * dSmx) / (Smx * dxix - m * xix * dSmx))

return xp.stack(A), xp.stack(B)


#TODO ***??*** revise stratified_coefficients - torch, docstring, unit test
def stratified_coefficients(
m: list[complex],
a: list[float],
L: int,
) -> tuple[np.ndarray, np.ndarray]:
"""Calculate the Mie scattering coefficients for stratified spherical
"""Calculate the Mie scattering coefficients for stratified spherical
particles.

This function calculates the terms up to (and including) order L using
This function calculates the terms up to (and including) order L using
Riccati-Bessel polynomials.

Parameters
Expand Down Expand Up @@ -267,10 +254,7 @@ def stratified_coefficients(

if (p - q == 0) or (p - q == 1):
if i % 2 == 0:
if (
j < 2 * n_layers - 1
and (j == 0 or j % 2 == 1)
):
if j < 2 * n_layers - 1 and (j == 0 or j % 2 == 1):
A_ij = dricbesj(n + 1, m[p] * a[q])
elif j % 2 == 0:
A_ij = dricbesy(n + 1, m[p] * a[q])
Expand All @@ -282,10 +266,7 @@ def stratified_coefficients(
else:
C_ij = A_ij
else:
if (
j < 2 * n_layers - 1
and (j == 0 or j % 2 == 1)
):
if j < 2 * n_layers - 1 and (j == 0 or j % 2 == 1):
C_ij = ricbesj(n + 1, m[p] * a[q])
elif j % 2 == 0:
C_ij = ricbesy(n + 1, m[p] * a[q])
Expand Down Expand Up @@ -317,7 +298,6 @@ def stratified_coefficients(
return xp.stack(an), xp.stack(bn)


#TODO ***??*** revise harmonics - torch, docstring, unit test
def harmonics(
x: NDArray,
L: int,
Expand All @@ -329,17 +309,17 @@ def harmonics(
Parameters
----------
x : np.ndarray
An array representing the cosine of the polar angle (theta) for each
evaluation point relative to the scattering particle's center
(the origin).
The polar angle is the angle between the z-axis (aligned with the
direction of wave propagation) and the vector from the particle's
An array representing the cosine of the polar angle (theta) for each
evaluation point relative to the scattering particle's center
(the origin).
The polar angle is the angle between the z-axis (aligned with the
direction of wave propagation) and the vector from the particle's
center to the evaluation point.
Values in `x` should lie in the range [-1, 1], where `x = 1`

Values in `x` should lie in the range [-1, 1], where `x = 1`
corresponds to theta = 0° (point directly forward along the z-axis),
`x = -1` corresponds to theta = 180° (point directly backward along the
z-axis), and `x = 0` corresponds to theta = 90° (point perpendicular to
`x = -1` corresponds to theta = 180° (point directly backward along the
z-axis), and `x = 0` corresponds to theta = 90° (point perpendicular to
the z-axis).

L : int
Expand All @@ -348,7 +328,7 @@ def harmonics(
Returns
-------
Tuple[np.ndarray, np.ndarray]
A tuple containing arrays of harmonics PI and TAU of
A tuple containing arrays of harmonics PI and TAU of
shape (L, *x.shape).

"""
Expand All @@ -375,8 +355,7 @@ def harmonics(

for i in range(3, L + 1):
PI.append(
(2 * i - 1) / (i - 1) * x * PI[i - 2]
- i / (i - 1) * PI[i - 3]
(2 * i - 1) / (i - 1) * x * PI[i - 2] - i / (i - 1) * PI[i - 3]
)
TAU.append(i * x * PI[i - 1] - (i + 1) * PI[i - 2])

Expand Down
83 changes: 34 additions & 49 deletions deeptrack/backend/polynomials.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Bessel and Riccati-Bessel polynomials.

This module defines a set of functions for computing Bessel and Riccati-Bessel
polynomials and their derivatives. It expands the corresponding capabilities of
This module defines a set of functions for computing Bessel and Riccati-Bessel
polynomials and their derivatives. It expands the corresponding capabilities of
`scipy`.

Module Structure
Expand All @@ -18,11 +18,8 @@
- `dricbesy`: First derivative of the Riccati-Bessel polynomial of the 2nd kind.
- `ricbesh`: Riccati-Bessel polynomial of the 3rd kind.
- `dricbesh`: First derivative of the Riccati-Bessel polynomial of the 3rd kind.

"""

#TODO ***??*** revise class docstring
#TODO ***??*** revise DTAT399D
"""

from __future__ import annotations

Expand Down Expand Up @@ -82,9 +79,8 @@ def _dricbesj_array_api(l: int | float, x, namespace=None):
if l == 0:
return xp.cos(x)

return (
_ricbesj_array_api(l - 1, x, xp)
- l / x * _ricbesj_array_api(l, x, xp)
return _ricbesj_array_api(l - 1, x, xp) - l / x * _ricbesj_array_api(
l, x, xp
)


Expand Down Expand Up @@ -115,9 +111,8 @@ def _dricbesy_array_api(l: int | float, x, namespace=None):
if l == 0:
return -xp.sin(x)

return (
_ricbesy_array_api(l - 1, x, xp)
- l / x * _ricbesy_array_api(l, x, xp)
return _ricbesy_array_api(l - 1, x, xp) - l / x * _ricbesy_array_api(
l, x, xp
)


Expand All @@ -135,7 +130,6 @@ def _dricbesh_array_api(l: int | float, x, namespace=None):
return _dricbesj_array_api(l, x, xp) - 1j * _dricbesy_array_api(l, x, xp)


#TODO ***??*** revise besselj - torch, docstring, unit test
def besselj(
l: int | float,
x: int | float | NDArray,
Expand All @@ -159,11 +153,10 @@ def besselj(
return jv(l, x)


#TODO ***??*** revise dbesselj - torch, docstring, unit test
def dbesselj(
l: int | float,
x: int | float | NDArray,
) -> float | NDArray:
l: int | float,
x: int | float | NDArray,
) -> float | NDArray:
"""The first derivative of the Bessel polynomial of the 1st kind.

Parameters
Expand All @@ -183,11 +176,10 @@ def dbesselj(
return 0.5 * (besselj(l - 1, x) - besselj(l + 1, x))


#TODO ***??*** revise bessely - torch, docstring, unit test
def bessely(
l: int | float,
x: int | float | NDArray,
) -> float | NDArray:
l: int | float,
x: int | float | NDArray,
) -> float | NDArray:
"""The Bessel polynomial of the 2nd kind.

Parameters
Expand All @@ -207,11 +199,10 @@ def bessely(
return yv(l, x)


#TODO ***??*** revise dbessely - torch, docstring, unit test
def dbessely(
l: int | float,
x: int | float | NDArray,
) -> float | NDArray:
l: int | float,
x: int | float | NDArray,
) -> float | NDArray:
"""The first derivative of the Bessel polynomial of the 2nd kind.

Parameters
Expand All @@ -231,11 +222,10 @@ def dbessely(
return 0.5 * (bessely(l - 1, x) - bessely(l + 1, x))


#TODO ***??*** revise ricbesj - torch, docstring, unit test
def ricbesj(
l: int | float,
x: int | float | NDArray,
) -> float | NDArray:
l: int | float,
x: int | float | NDArray,
) -> float | NDArray:
"""The Riccati-Bessel polynomial of the 1st kind.

Parameters
Expand All @@ -259,11 +249,10 @@ def ricbesj(
return np.sqrt(np.pi * x / 2) * besselj(l + 0.5, x)


#TODO ***??*** revise dricbesj - torch, docstring, unit test
def dricbesj(
l: int | float,
x: int | float | NDArray,
) -> float | NDArray:
l: int | float,
x: int | float | NDArray,
) -> float | NDArray:
"""The first derivative of the Riccati-Bessel polynomial of the 1st kind.

Parameters
Expand All @@ -289,11 +278,10 @@ def dricbesj(
) * dbesselj(l + 0.5, x)


#TODO ***??*** revise ricbesy - torch, docstring, unit test
def ricbesy(
l: int | float,
x: int | float | NDArray,
) -> float | NDArray:
l: int | float,
x: int | float | NDArray,
) -> float | NDArray:
"""The Riccati-Bessel polynomial of the 2nd kind.

Parameters
Expand All @@ -317,11 +305,10 @@ def ricbesy(
return -np.sqrt(np.pi * x / 2) * bessely(l + 0.5, x)


#TODO ***??*** revise dricbesy - torch, docstring, unit test
def dricbesy(
l: int | float,
x: int | float | NDArray,
) -> float | NDArray:
l: int | float,
x: int | float | NDArray,
) -> float | NDArray:
"""The first derivative of the Riccati-Bessel polynomial of the 2nd kind.

Parameters
Expand All @@ -347,11 +334,10 @@ def dricbesy(
) * dbessely(l + 0.5, x)


#TODO ***??*** revise ricbesh - torch, docstring, unit test
def ricbesh(
l: int | float,
x: int | float | NDArray,
) -> float | NDArray:
l: int | float,
x: int | float | NDArray,
) -> float | NDArray:
"""The Riccati-Bessel polynomial of the 3rd kind.

Parameters
Expand All @@ -375,11 +361,10 @@ def ricbesh(
return np.sqrt(np.pi * x / 2) * h1vp(l + 0.5, x, False)


#TODO ***??*** revise dricbesh - torch, docstring, unit test
def dricbesh(
l: int | float,
x: int | float | NDArray,
) -> float | NDArray:
l: int | float,
x: int | float | NDArray,
) -> float | NDArray:
"""The first derivative of the Riccati-Bessel polynomial of the 3rd kind.

Parameters
Expand Down
14 changes: 8 additions & 6 deletions deeptrack/features.py
Original file line number Diff line number Diff line change
Expand Up @@ -1421,11 +1421,11 @@ def batch(
components = list(zip(*normalized))

# Stack each component along a new leading batch axis.
with config.with_backend(self._backend):
with config.with_backend(self._backend):
return tuple(
xp.stack([xp.asarray(x) for x in component])
for component in components
)
xp.stack([xp.asarray(x) for x in component])
for component in components
)

def _action(
self: Feature,
Expand Down Expand Up @@ -7659,7 +7659,9 @@ def get(
image = []
for img in raw:
if img.ndim == 3 and img.shape[-1] >= 3:
image.append(cv2.cvtColor(img, cv2.COLOR_BGR2RGB).copy())
image.append(
cv2.cvtColor(img, cv2.COLOR_BGR2RGB).copy()
)
else:
image.append(np.asarray(img).copy())

Expand Down Expand Up @@ -8532,7 +8534,7 @@ def get(
NumPy array or a PyTorch tensor.

"""

if TORCH_AVAILABLE and isinstance(inputs, torch.Tensor):
if axes is None:
axes = tuple(range(inputs.ndim - 1, -1, -1))
Expand Down
Loading
Loading