77import json
88import pyvista as pv
99
10+ from .fiducials import FiducialList
1011from .. import geo , utils
1112from ..vol import Volume
1213
@@ -50,18 +51,16 @@ def __init__(
5051 self .endpoint = geo .point (endpoint )
5152 self .volume = volume
5253 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+ ]
5758 self ._anatomical_coordinate_system = anatomical_coordinate_system .upper ()
5859 self ._world_from_anatomical = geo .frame_transform (world_from_anatomical )
5960 else :
6061 self .volume = volume
6162
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"
6564
6665 def __str__ (self ):
6766 return f"LineAnnotation({ self .startpoint } , { self .endpoint } )"
@@ -93,8 +92,7 @@ def from_json(
9392
9493 if volume is None :
9594 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
9896 ), "must supply the anatomical transform"
9997 else :
10098 anatomical_coordinate_system = volume .anatomical_coordinate_system
@@ -140,6 +138,25 @@ def from_json(
140138 def from_markup (cls , * args , ** kwargs ):
141139 return cls .from_json (* args , ** kwargs )
142140
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+
143160 def save (
144161 self ,
145162 path : str ,
@@ -287,6 +304,9 @@ def trajectory_in_world(self) -> geo.Vector3D:
287304 def direction_in_world (self ) -> geo .Vector3D :
288305 return self .trajectory_in_world .normalized ()
289306
307+ def get_direction (self ) -> geo .Vector3D :
308+ return self .direction_in_world
309+
290310 def get_mesh (self ):
291311 """Get the mesh in anatomical coordinates."""
292312 u = self .startpoint
@@ -297,9 +317,7 @@ def get_mesh(self):
297317 mesh += pv .Sphere (2.5 , v )
298318 return mesh
299319
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 :
303321 u = self .startpoint_in_world
304322 v = self .endpoint_in_world
305323
0 commit comments