7
7
import json
8
8
import pyvista as pv
9
9
10
+ from .fiducials import FiducialList
10
11
from .. import geo , utils
11
12
from ..vol import Volume
12
13
@@ -50,18 +51,16 @@ def __init__(
50
51
self .endpoint = geo .point (endpoint )
51
52
self .volume = volume
52
53
if volume is None :
53
- assert (
54
- world_from_anatomical is not None
55
- and anatomical_coordinate_system . upper () in [ "RAS" , " LPS"]
56
- )
54
+ assert world_from_anatomical is not None and anatomical_coordinate_system . upper () in [
55
+ "RAS" ,
56
+ " LPS",
57
+ ]
57
58
self ._anatomical_coordinate_system = anatomical_coordinate_system .upper ()
58
59
self ._world_from_anatomical = geo .frame_transform (world_from_anatomical )
59
60
else :
60
61
self .volume = volume
61
62
62
- assert (
63
- self .startpoint .dim == self .endpoint .dim
64
- ), "annotation points must have matching dim"
63
+ assert self .startpoint .dim == self .endpoint .dim , "annotation points must have matching dim"
65
64
66
65
def __str__ (self ):
67
66
return f"LineAnnotation({ self .startpoint } , { self .endpoint } )"
@@ -93,8 +92,7 @@ def from_json(
93
92
94
93
if volume is None :
95
94
assert (
96
- world_from_anatomical is not None
97
- and anatomical_coordinate_system is not None
95
+ world_from_anatomical is not None and anatomical_coordinate_system is not None
98
96
), "must supply the anatomical transform"
99
97
else :
100
98
anatomical_coordinate_system = volume .anatomical_coordinate_system
@@ -140,6 +138,25 @@ def from_json(
140
138
def from_markup (cls , * args , ** kwargs ):
141
139
return cls .from_json (* args , ** kwargs )
142
140
141
+ @classmethod
142
+ def from_fcsv (cls , path : Path , ** kwargs ) -> LineAnnotation :
143
+ """Load a LineAnnotation from a .fcsv file.
144
+
145
+ Args:
146
+ path (Path): Path to the .fcsv file.
147
+ world_from_anatomical (Optional[geo.FrameTransform], optional): The pose of the volume in world coordinates. Defaults to None.
148
+
149
+ Returns:
150
+ LineAnnotation: The loaded annotation.
151
+ """
152
+ fiducial_list = FiducialList .from_fcsv (path )
153
+ assert len (fiducial_list ) == 2 , "fcsv file must contain exactly two points"
154
+ return cls (
155
+ fiducial_list [0 ],
156
+ fiducial_list [1 ],
157
+ ** kwargs ,
158
+ )
159
+
143
160
def save (
144
161
self ,
145
162
path : str ,
@@ -287,6 +304,9 @@ def trajectory_in_world(self) -> geo.Vector3D:
287
304
def direction_in_world (self ) -> geo .Vector3D :
288
305
return self .trajectory_in_world .normalized ()
289
306
307
+ def get_direction (self ) -> geo .Vector3D :
308
+ return self .direction_in_world
309
+
290
310
def get_mesh (self ):
291
311
"""Get the mesh in anatomical coordinates."""
292
312
u = self .startpoint
@@ -297,9 +317,7 @@ def get_mesh(self):
297
317
mesh += pv .Sphere (2.5 , v )
298
318
return mesh
299
319
300
- def get_mesh_in_world (
301
- self , full : bool = True , use_cached : bool = False
302
- ) -> pv .PolyData :
320
+ def get_mesh_in_world (self , full : bool = True , use_cached : bool = False ) -> pv .PolyData :
303
321
u = self .startpoint_in_world
304
322
v = self .endpoint_in_world
305
323
0 commit comments