Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
1c2eb04
start allowing mixed bundle defs
36000 Jan 27, 2026
6e2bb56
finish up wmgmi seeding changes
36000 Jan 28, 2026
0545fa7
more mixed ROI fixes
36000 Jan 28, 2026
643395d
BFs
36000 Jan 28, 2026
03dc8b0
return to setting logging to info
36000 Jan 28, 2026
b0ce1a0
minor docs fixes from copilot
36000 Jan 28, 2026
bdf4b58
toy with vof
36000 Jan 29, 2026
806e53d
much needed speedups in bundle recognition
36000 Jan 29, 2026
cc725ca
tighter node thresh
36000 Jan 30, 2026
77635ce
bring back parietal endpoint ROIs
36000 Jan 30, 2026
bb9b9b7
Add projection to node threshold
36000 Feb 2, 2026
bc80083
for large tractographies, this 5 percent rule may be necessary
36000 Feb 2, 2026
b0e33f2
add exclude ROI to pAF
36000 Feb 2, 2026
bf37ca4
update montage code
36000 Feb 3, 2026
13740dd
fix participant montage
36000 Feb 4, 2026
78f8c17
improve participant montage
36000 Feb 4, 2026
3d582c6
More participant montage improvements
36000 Feb 4, 2026
2e8ca2e
add more options to p montage
36000 Feb 4, 2026
944509b
remove warnings from segmentedsft
36000 Feb 6, 2026
5d82e9e
bf
36000 Feb 9, 2026
4a6bfe4
viz bug fix
36000 Feb 9, 2026
e500d0c
further restrict pAF
36000 Feb 9, 2026
df40e59
try more constrained pAF/ARC defs
36000 Feb 9, 2026
6d80a65
try this
36000 Feb 9, 2026
24c810f
tighten ILF constraint
36000 Feb 9, 2026
1ba3f61
solve pAF issues with new exclusion ROI
36000 Feb 9, 2026
1a892ab
return to strict VOF seg
36000 Feb 9, 2026
43fddd2
return to stricter cleaning
36000 Feb 10, 2026
2746f1b
cleaning by other core requires higher levels of precision
36000 Feb 10, 2026
d40464b
bf
36000 Feb 10, 2026
ee49598
maybe we can do this after clustering
36000 Feb 10, 2026
adb5310
Major registration overhaul
36000 Feb 11, 2026
4632c37
the transform points direction is opposite for some reason
36000 Feb 11, 2026
a5d2fcf
verfified
36000 Feb 11, 2026
15a2d06
this should be not the inverse
36000 Feb 11, 2026
926e16b
add ROI transformation fix
36000 Feb 12, 2026
9b73571
cleanup some minor bugs from tests
36000 Feb 12, 2026
8ca8fa4
add documentation and tests for mixed bundle definitions
36000 Feb 12, 2026
838bb34
actually transform points / transform inverse points makes sense
36000 Feb 12, 2026
fbc09e8
BFs
36000 Feb 12, 2026
627646d
BFs
36000 Feb 12, 2026
2cf377b
fix roi dist priority
36000 Feb 12, 2026
4e8cf4d
tweaks
36000 Feb 12, 2026
16b2145
small BF
36000 Feb 12, 2026
3b8b33a
put this back
36000 Feb 12, 2026
00ee038
implement moving streamlines with new mapping system
36000 Feb 14, 2026
3e385d9
add ORG VOF subclusters
36000 Feb 14, 2026
184bcad
put this back
36000 Feb 14, 2026
4aea960
fix up reco
36000 Feb 15, 2026
3b884c8
color new bundles
36000 Feb 16, 2026
95feb98
VOF refinements
36000 Feb 18, 2026
a110d04
push model centroids closer together
36000 Feb 19, 2026
e21f920
make the VOF 3 relative to IFOF again
36000 Feb 19, 2026
aa47b55
binary dilation deprecated
36000 Feb 19, 2026
05a51eb
further modifications to VOF subbundling, formalization
36000 Feb 20, 2026
fcf5d59
Refine VOF definition
36000 Feb 23, 2026
f02cf7b
bundle montage updates
36000 Feb 23, 2026
070df1d
further refined VOF
36000 Feb 23, 2026
21cbb9e
more tweaks
36000 Feb 23, 2026
ee5e052
reduce default chunk size on GPU
36000 Feb 24, 2026
99c130d
better gif maker
36000 Feb 24, 2026
5706c0e
recog in rasmm
36000 Feb 24, 2026
b2fdb54
more refinements to VOF, more refinements to RASMM segmenting
36000 Feb 25, 2026
7cb61b6
new gpu streamlines minmaxlen api
36000 Feb 25, 2026
9d3fa01
BFs
36000 Feb 25, 2026
c53362b
loosen cleaning
36000 Feb 25, 2026
81b4088
add color fa, update docs
36000 Feb 25, 2026
c44f8c0
the vof is lateral to ifof
36000 Feb 25, 2026
c0ee04e
tiny tweaks
36000 Feb 25, 2026
62c43f1
more onnx option
36000 Feb 27, 2026
e1a0a44
bf
36000 Feb 27, 2026
73fa4a2
dont force dwi load
36000 Feb 27, 2026
9e78c55
odf calc is helper function not part of plan
36000 Feb 27, 2026
7454a4e
make this default
36000 Feb 27, 2026
2a07998
test update
36000 Feb 27, 2026
6f044b3
refine paf, begin mdlf
36000 Mar 2, 2026
9384d52
update tests
36000 Mar 2, 2026
1af58b1
tweaking definitions of paf/vof
36000 Mar 3, 2026
c103695
bf
36000 Mar 3, 2026
193bb4f
bf
36000 Mar 3, 2026
6ed7a88
for large tractograms, trx is much much better
36000 Mar 3, 2026
671c380
better name for this
36000 Mar 3, 2026
c693df9
update test to trx
36000 Mar 3, 2026
44d564b
settings for length threshold removal
36000 Mar 3, 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
2 changes: 1 addition & 1 deletion .codespellrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[codespell]
skip = [setup.cfg]
ignore-words-list = Reson, DNE, ACI, FPT, sagital, saggital, abd, Joo, Mapp, Commun, vor, Claus
ignore-words-list = Reson, DNE, ACI, FPT, sagital, saggital, abd, Joo, Mapp, Commun, vor, Claus, coo
123 changes: 116 additions & 7 deletions AFQ/_fixes.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
from math import radians

import numpy as np
from dipy.align import vector_fields as vfu
from dipy.align.imwarp import DiffeomorphicMap, mult_aff
from dipy.data import default_sphere
from dipy.reconst.gqi import squared_radial_component
from dipy.tracking.streamline import set_number_of_points
Expand All @@ -15,6 +17,75 @@
logger = logging.getLogger("AFQ")


def get_simplified_transform(self):
"""Constructs a simplified version of this Diffeomorhic Map

The simplified version incorporates the pre-align transform, as well as
the domain and codomain affine transforms into the displacement field.
The resulting transformation may be regarded as operating on the
image spaces given by the domain and codomain discretization. As a
result, self.prealign, self.disp_grid2world, self.domain_grid2world and
self.codomain affine will be None (denoting Identity) in the resulting
diffeomorphic map.
"""
if self.dim == 2:
simplify_f = vfu.simplify_warp_function_2d
else:
simplify_f = vfu.simplify_warp_function_3d
# Simplify the forward transform
D = self.domain_grid2world
P = self.prealign
Rinv = self.disp_world2grid
Cinv = self.codomain_world2grid

# this is the matrix which we need to multiply the voxel coordinates
# to interpolate on the forward displacement field ("in"side the
# 'forward' brackets in the expression above)
affine_idx_in = mult_aff(Rinv, mult_aff(P, D))

# this is the matrix which we need to multiply the voxel coordinates
# to add to the displacement ("out"side the 'forward' brackets in the
# expression above)
affine_idx_out = mult_aff(Cinv, mult_aff(P, D))

# this is the matrix which we need to multiply the displacement vector
# prior to adding to the transformed input point
affine_disp = Cinv

new_forward = simplify_f(
self.forward, affine_idx_in, affine_idx_out, affine_disp, self.domain_shape
)

# Simplify the backward transform
C = self.codomain_grid2world
Pinv = self.prealign_inv
Dinv = self.domain_world2grid

affine_idx_in = mult_aff(Rinv, C)
affine_idx_out = mult_aff(Dinv, mult_aff(Pinv, C))
affine_disp = mult_aff(Dinv, Pinv)
new_backward = simplify_f(
self.backward,
affine_idx_in,
affine_idx_out,
affine_disp,
self.codomain_shape,
)
simplified = DiffeomorphicMap(
dim=self.dim,
disp_shape=self.disp_shape,
disp_grid2world=None,
domain_shape=self.domain_shape,
domain_grid2world=None,
codomain_shape=self.codomain_shape,
codomain_grid2world=None,
prealign=None,
)
simplified.forward = new_forward
simplified.backward = new_backward
return simplified


def gwi_odf(gqmodel, data):
gqi_vector = np.real(
squared_radial_component(
Expand Down Expand Up @@ -243,7 +314,7 @@ def gaussian_weights(bundle, n_points=100, return_mahalnobis=False, stat=np.mean
return weights / np.sum(weights, 0)


def make_gif(show_m, out_path, n_frames=36, az_ang=-10):
def make_gif(show_m, out_path, n_frames=36, az_ang=-10, duration=150):
"""
Make a video from a Fury Show Manager.

Expand All @@ -263,22 +334,60 @@ def make_gif(show_m, out_path, n_frames=36, az_ang=-10):
The angle to rotate the camera around the
z-axis for each frame, in degrees.
Default: -10

duration : int
The duration of each frame in the output GIF, in milliseconds.
Default: 150
"""
video = []

show_m.render()
show_m.window.draw()

with tempfile.TemporaryDirectory() as tmp_dir:
for ii in tqdm(range(n_frames), desc="Generating GIF"):
for ii in tqdm(range(n_frames), desc="Generating GIF", leave=False):
frame_fname = f"{tmp_dir}/{ii}.png"
show_m.screens[0].controller.rotate((radians(az_ang), 0), None)
show_m.render()
show_m.window.draw()
show_m.snapshot(frame_fname)
video.append(frame_fname)

video = [Image.open(frame) for frame in video]
video[0].save(
out_path, save_all=True, append_images=video[1:], duration=300, loop=1
video.append(Image.open(frame_fname).convert("RGB"))

all_left, all_upper = float("inf"), float("inf")
all_right, all_lower = 0, 0

for img in video:
arr = np.array(img)
bg_color = arr[0, 0]

mask = np.any(arr != bg_color, axis=-1)

if np.any(mask):
rows = np.any(mask, axis=1)
cols = np.any(mask, axis=0)
ymin, ymax = np.where(rows)[0][[0, -1]]
xmin, xmax = np.where(cols)[0][[0, -1]]

all_left = min(all_left, xmin)
all_upper = min(all_upper, ymin)
all_right = max(all_right, xmax)
all_lower = max(all_lower, ymax)

if all_left < all_right:
crop_box = (
max(0, all_left),
max(0, all_upper),
min(video[0].width, all_right),
min(video[0].height, all_lower),
)
cropped_video = [img.crop(crop_box) for img in video]
else:
cropped_video = video

cropped_video[0].save(
out_path,
save_all=True,
append_images=cropped_video[1:],
duration=duration,
loop=1,
)
Loading
Loading