Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scripts to project 3D and 4D maps to streamline points and perform math operations in space of streamline points #810

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
2ff0002
project maps to streamline points and do math
Nov 16, 2023
7eef429
fixed pep8
Nov 23, 2023
4d64eb6
fixed logging line
Nov 23, 2023
2fb63cd
fixed trailing whitespace
Nov 23, 2023
ba5a516
removed print statements
Nov 23, 2023
797bd95
removed useless assert resolution
Nov 23, 2023
cf12dc7
changed to voxel world coords for interpolation
Nov 24, 2023
5d014a8
fixed dimension error on endpoints only single val
Nov 24, 2023
6de542c
remove deepcopy
Nov 24, 2023
ba839fb
fixed too long lines
Nov 24, 2023
a4af4ac
fixed indent
Nov 24, 2023
fb0d9af
fixexed indents
Nov 24, 2023
76a78c4
update output dpp name
Nov 29, 2023
0e6fb5a
moved project_metrics func to module
grahamlittlephd Dec 14, 2023
53ec9cc
moved streamline ops to module
grahamlittlephd Dec 14, 2023
061f399
added blank unit tests
grahamlittlephd Dec 14, 2023
c8b3889
added script test
grahamlittlephd Dec 14, 2023
1f0ac45
renamed scripts
grahamlittlephd Dec 14, 2023
44fe697
update naming in tests
grahamlittlephd Dec 14, 2023
24d193e
update master
Jan 10, 2024
16e3084
add blank unit tests to streamline operations
Jan 10, 2024
b5660fd
pep errors
grahamlittlephd Jan 11, 2024
a0fc992
pep errors 2
grahamlittlephd Jan 11, 2024
f378999
Merge branch 'master' into Project-endpoint-data-to-streamlines
Jan 12, 2024
e1795fb
tests passed
Jan 15, 2024
dded388
added test for point math
Jan 15, 2024
7592d60
changed arg name for point math output
Jan 15, 2024
8a6973d
pep 8 long lines
Jan 15, 2024
62c103c
updated function names in stream_ops
Jan 15, 2024
ffc2c88
Fixed for loops and added multi input
Jan 25, 2024
89f40d2
updated projection tests with new required args
Jan 25, 2024
ed059af
Merge remote-tracking branch 'origin/master' into Project-endpoint-da…
Jan 25, 2024
e8bcadd
updated point math test with req args
Jan 25, 2024
212975b
added test for point math correlation
Jan 25, 2024
bdcf750
pep8 fix
Jan 26, 2024
4c2d844
Updated doc and logging in point_math
grahamlittlephd Jan 29, 2024
67873b9
added dpp and dpp mode argument
Jan 29, 2024
154f8ed
added overwrite functionality
Jan 29, 2024
e7b5f0b
simplify overwrite
Jan 30, 2024
39f65ef
remove append option
Jan 30, 2024
6b33f7c
arg multiinput just narg+
Jan 30, 2024
776e04d
Merge branch 'master' into Project-endpoint-data-to-streamlines
Jan 30, 2024
e679fa1
fixed project map tests
Jan 30, 2024
4046cc1
rm doc reference to endpoints
Jan 30, 2024
0c5cdd3
update test tractogram point math new args
Jan 30, 2024
0963198
updated name of to dpp_math
Jan 30, 2024
ff8c377
update doc for clearer on what happens in 4D case
Jan 30, 2024
d3fd65a
remove print
Jan 30, 2024
0778e96
moved project func to new file
Feb 5, 2024
918d4c2
changed metric to map
Feb 5, 2024
ce94ab0
changed metric to map
Feb 5, 2024
75a54bf
added dummy test for dpp management
Feb 5, 2024
74d6a87
4D dps math - now outputs array per streamline
Feb 5, 2024
507df9f
pep8 issues
Feb 5, 2024
0c19111
Merge branch 'master' into Project-endpoint-data-to-streamlines
Feb 7, 2024
3a59f6a
pep8
Feb 7, 2024
1f69f94
remove py version file
Feb 7, 2024
47d4a21
added utf header
Feb 7, 2024
8e8bb69
removed py version file
grahamlittlephd Feb 8, 2024
bc52040
Merge branch 'master' into Project-endpoint-data-to-streamlines
grahamlittlephd Feb 8, 2024
9ea5ec0
added back py ver file in root
grahamlittlephd Feb 8, 2024
03efce2
Merge branch 'master' into Project-endpoint-data-to-streamlines
Feb 19, 2024
d0410dd
remove unused StatefulTractogram
Feb 19, 2024
ced0217
removed extra spaces
Feb 19, 2024
0c8e07b
removed default false
Feb 19, 2024
e401f55
changed to nib.load
Feb 19, 2024
0f0abcc
added dual keep_dpp and ovewrite args
Feb 19, 2024
3fed0f1
changed map to map_volume
Feb 19, 2024
691c620
updated logging in project_map
Feb 19, 2024
172e821
remove if statement
Feb 19, 2024
d4c4f57
fixed comments in dpp_math
Feb 19, 2024
0a4966a
updated to mode required argument
Feb 19, 2024
efa733a
added keep_all_dpp_dps option
Feb 19, 2024
f4b4e39
moved streamline ops to dps_and_dpp
Feb 19, 2024
e0e70a3
blank tests to dps_dpp module
Feb 19, 2024
6d752e5
pep8
Feb 19, 2024
a21aa16
4D data stored as shape (#,) fixed checks
Feb 19, 2024
8db77a9
fixed dimension on tuple
Feb 19, 2024
47f287b
updated dimension on data_shape
Feb 19, 2024
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 .python-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.10
3.10
204 changes: 204 additions & 0 deletions scilpy/tractograms/dps_and_dpp_management.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
# -*- coding: utf-8 -*-
import numpy as np


def project_map_to_streamlines(sft, map_volume, endpoints_only=False):
"""
Projects a map onto the points of streamlines.

Parameters
----------
sft: StatefulTractogram
Input tractogram.
map_volume: DataVolume
Input map.

Optional:
---------
endpoints_only: bool
If True, will only project the map_volume onto the endpoints of the
streamlines (all values along streamlines set to zero). If False,
will project the map_volume onto all points of the streamlines.

Returns
-------
streamline_data:
map_volume projected to each point of the streamlines.
"""
if len(map_volume.data.shape) == 4:
dimension = map_volume.data.shape[3]
else:
dimension = 1

streamline_data = []
if endpoints_only:
for s in sft.streamlines:
p1_data = map_volume.get_value_at_coordinate(
s[0][0], s[0][1], s[0][2],
space=sft.space, origin=sft.origin)
p2_data = map_volume.get_value_at_coordinate(
s[-1][0], s[-1][1], s[-1][2],
space=sft.space, origin=sft.origin)

thisstreamline_data = np.ones((len(s), dimension)) * np.nan

thisstreamline_data[0] = p1_data
thisstreamline_data[-1] = p2_data
thisstreamline_data = np.asarray(thisstreamline_data)

streamline_data.append(
np.reshape(thisstreamline_data,
(len(thisstreamline_data), dimension)))
else:
for s in sft.streamlines:
thisstreamline_data = []
for p in s:
thisstreamline_data.append(map_volume.get_value_at_coordinate(
p[0], p[1], p[2], space=sft.space, origin=sft.origin))

streamline_data.append(
np.reshape(thisstreamline_data,
(len(thisstreamline_data), dimension)))

return streamline_data


def perform_streamline_operation_per_point(op_name, sft, dpp_name='metric',
endpoints_only=False):
"""Peforms an operation per point for all streamlines.

Parameters
----------
op_name: str
A callable that takes a list of streamline data per point (4D) and
returns a list of streamline data per point.
sft: StatefulTractogram
The streamlines used in the operation.
dpp_name: str
The name of the data per point to be used in the operation.
endpoints_only: bool
If True, will only perform operation on endpoints

Returns
-------
new_sft: StatefulTractogram
sft with data per streamline resulting from the operation.
"""

# Performing operation
call_op = OPERATIONS[op_name]
if endpoints_only:
new_data_per_point = []
for s in sft.data_per_point[dpp_name]:
this_data_per_point = np.nan * np.ones((len(s), 1))
this_data_per_point[0] = call_op(s[0])
this_data_per_point[-1] = call_op(s[-1])
new_data_per_point.append(
np.reshape(this_data_per_point, (len(this_data_per_point), 1)))
else:
new_data_per_point = []
for s in sft.data_per_point[dpp_name]:
this_data_per_point = []
for p in s:
this_data_per_point.append(call_op(p))
new_data_per_point.append(
np.reshape(this_data_per_point, (len(this_data_per_point), 1)))

# Extracting streamlines
return new_data_per_point


def perform_operation_per_streamline(op_name, sft, dpp_name='metric',
endpoints_only=False):
"""Performs an operation across all data points for each streamline.

Parameters
----------
op_name: str
A callable that takes a list of streamline data per streamline and
returns a list of data per streamline.
sft: StatefulTractogram
The streamlines used in the operation.
dpp_name: str
The name of the data per point to be used in the operation.
endpoints_only: bool
If True, will only perform operation on endpoints

Returns
-------
new_sft: StatefulTractogram
sft with data per streamline resulting from the operation.
"""
# Performing operation
call_op = OPERATIONS[op_name]
if endpoints_only:
new_data_per_streamline = []
for s in sft.data_per_point[dpp_name]:
start = s[0]
end = s[-1]
concat = np.concatenate((start[:], end[:]))
new_data_per_streamline.append(call_op(concat))
else:
new_data_per_streamline = []
for s in sft.data_per_point[dpp_name]:
s_np = np.asarray(s)
new_data_per_streamline.append(call_op(s_np))

return new_data_per_streamline


def perform_pairwise_streamline_operation_on_endpoints(op_name, sft,
dpp_name='metric'):
"""Peforms an operation across endpoints for each streamline.

Parameters
----------
op_name: str
A callable that takes a list of streamline data per streamline and
returns a list of data per streamline.
sft: StatefulTractogram
The streamlines used in the operation.
dpp_name: str
The name of the data per point to be used in the operation.

Returns
-------
new_sft: StatefulTractogram
sft with data per streamline resulting from the operation.
"""
# Performing operation
call_op = OPERATIONS[op_name]
new_data_per_streamline = []
for s in sft.data_per_point[dpp_name]:
new_data_per_streamline.append(call_op(s[0], s[-1])[0, 1])

return new_data_per_streamline


def stream_mean(array):
return np.squeeze(np.mean(array, axis=0))


def stream_sum(array):
return np.squeeze(np.sum(array, axis=0))


def stream_min(array):
return np.squeeze(np.min(array, axis=0))


def stream_max(array):
return np.squeeze(np.max(array, axis=0))


def stream_correlation(array1, array2):
return np.corrcoef(array1, array2)


OPERATIONS = {
'mean': stream_mean,
'sum': stream_sum,
'min': stream_min,
'max': stream_max,
'correlation': stream_correlation,
}
1 change: 0 additions & 1 deletion scilpy/tractograms/streamline_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ def _get_point_on_line(first_point, second_point, vox_lower_corner):

return first_point + ray * (t0 + t1) / 2.


def filter_streamlines_by_length(sft, min_length=0., max_length=np.inf):
"""
Filter streamlines using minimum and max length.
Expand Down
18 changes: 18 additions & 0 deletions scilpy/tractograms/tests/test_dps_and_dpp_management.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
def test_project_map_to_streamlines():
# toDo
pass


def test_perform_streamline_operation_per_point():
# toDo
pass


def test_perform_operation_per_streamline():
# toDo
pass


def test_perform_streamline_operation_on_endpoints():
# toDo
pass
Loading