forked from UTFOIL/Vectorization-Public
-
Notifications
You must be signed in to change notification settings - Fork 0
/
visualize_edges_annuli.m
111 lines (84 loc) · 5.64 KB
/
visualize_edges_annuli.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
function visualize_edges_annuli( edge_subscripts, max_edge_energies, ellipsoid_radii_in_voxels, ...
vessel_wall_thickness_in_voxels, size_of_image, spheres_visual_file )
%% SAM 12/12/17
% adapted from the function with the same name in the folder AA
%
% V2, in which subpixel scales and locations are passed and the ellipsoids are
% sized and placed appropriately in the image.
%
% V02 in which the inputs are changed to be ammenable to the vectorize_V02 script 3/5/18 SAM
%
% V10 in which the negative laplacian is used (instead of just the value 1) as the fill value for
% each vertex sphere SAM 4/4/18
%
% function name changed from visualize_vertices to visualize_edges
%
% V11 which is exactly the same function as visualize_vertices_V10
%
% V12 in which the total mean_edge_energies are passed instead of the edge energies at every
% position along the trajectory. Trajectories are sorted by their total_mean_edge_energies from
% worst to best, and the better trajectories overwrite the worse trajectories in the resulting
% image, essentially plotting the maximum of the total_mean_edge_energies at every point in the
% space that belongs to the volume of a trajectory. Also the positions is now input as a cell array
% with entries corresponding to trajectories. SAM 5/5/18
%
% V160 in which the max_edge_energies are passed instead of the "total mean_edge_energies" (inspired
% by thinking about the trajectories as reaction pathways and the max being like the activation
% energy). Also combing the centerlines into this same function. % SAM 5/14/18
%
% V161 in which the position elements are constructed once into a look up table. SAM 5/14/18
%
% V180 in which the subscript inputs are allowed to be non integer
%
% This function renders the vessel walls by filling ellipsoidal objects in an image around each edge
% centerline location (whose size and shape is determined by the radius of the edge at that
% location, the thickness of the vessel wall, and the resolution of the image). It then zeros out
% ellipsoidal objects that are the same as the previous except smaller by the vessel wall thickness.
% SAM 7/21/19
padding_lenghts = ceil( vessel_wall_thickness_in_voxels );
size_of_image_padded = size_of_image + 2 * padding_lenghts ;
annuli_image = zeros( size_of_image_padded );
number_of_image_voxels = prod( size_of_image_padded );
number_of_edges = length( max_edge_energies );
% round the edge subscripts to integers
edge_subscripts = cellfun( @( v ) round( v + [ padding_lenghts, 0 ]), edge_subscripts, 'UniformOutput', false );
% edge_subscripts( :, 1 : 3 ) = edge_subscripts( :, 1 : 3 ) + padding_lenghts ;
% sorting trajectories by max energy in descending order (most negative at end)
[ max_edge_energies, indices_sorted_by_max ] = sort( max_edge_energies, 'descend' );
edge_subscripts = edge_subscripts( indices_sorted_by_max );
% pre-calculating all of the ellipsoidal structuring elements to be used to paint in the image
number_of_scales = size( ellipsoid_radii_in_voxels, 1 );
structuring_element_linear_indexing = cell( number_of_scales, 1 );
for painting_iteration = 1 : 2
% on the second time around, zero out the vessel lumens (leaving only the vessel wall)
if painting_iteration == 2, max_edge_energies( : ) = 0 ; vessel_wall_thickness_in_voxels = 0 ; end
for scale_index = 1 : number_of_scales
% find all pixel locations within the ellipsoid radii from the vertex position
structuring_element_linear_indexing{ scale_index } ...
= construct_structuring_element_V190( ellipsoid_radii_in_voxels( scale_index, : ) + vessel_wall_thickness_in_voxels, size_of_image_padded );
end % scale FOR
% loop through the edges
for edge_index = 1 : number_of_edges
subscripts_at_edge = edge_subscripts{ edge_index };
number_of_edge_positions = length( subscripts_at_edge( :, 1 ));
% loop through the positions in each edge
for edge_position_index = 1 : number_of_edge_positions
% find the linear index of the center pixel of the sphere that defines the edge at this
% position
edge_position_linear_index = sub2ind( size_of_image_padded, ...
subscripts_at_edge( edge_position_index, 1 ), ...
subscripts_at_edge( edge_position_index, 2 ), ...
subscripts_at_edge( edge_position_index, 3 ) );
annuli_image( max( min( edge_position_linear_index ...
+ structuring_element_linear_indexing{ subscripts_at_edge( edge_position_index, 4 )}, ...
number_of_image_voxels ), ...
1 )) ...
= - max_edge_energies( edge_index );
end % for position
end % for trajectory
end % FOR painting iteration
annuli_image = annuli_image( padding_lenghts( 1 ) + 1 : end - padding_lenghts( 1 ), ...
padding_lenghts( 2 ) + 1 : end - padding_lenghts( 2 ), ...
padding_lenghts( 3 ) + 1 : end - padding_lenghts( 3 ) );
mat2tif( uint16( annuli_image ), spheres_visual_file )
end % function