Skip to content

Commit

Permalink
Merge pull request #93 from arcadelab/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
benjamindkilleen committed Jul 14, 2023
2 parents 846e701 + ae1bb9b commit 2c45632
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 97 deletions.
42 changes: 30 additions & 12 deletions deepdrr/annotations/line_annotation.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import json
import pyvista as pv

from .fiducials import FiducialList
from .. import geo, utils
from ..vol import Volume

Expand Down Expand Up @@ -50,18 +51,16 @@ def __init__(
self.endpoint = geo.point(endpoint)
self.volume = volume
if volume is None:
assert (
world_from_anatomical is not None
and anatomical_coordinate_system.upper() in ["RAS", "LPS"]
)
assert world_from_anatomical is not None and anatomical_coordinate_system.upper() in [
"RAS",
"LPS",
]
self._anatomical_coordinate_system = anatomical_coordinate_system.upper()
self._world_from_anatomical = geo.frame_transform(world_from_anatomical)
else:
self.volume = volume

assert (
self.startpoint.dim == self.endpoint.dim
), "annotation points must have matching dim"
assert self.startpoint.dim == self.endpoint.dim, "annotation points must have matching dim"

def __str__(self):
return f"LineAnnotation({self.startpoint}, {self.endpoint})"
Expand Down Expand Up @@ -93,8 +92,7 @@ def from_json(

if volume is None:
assert (
world_from_anatomical is not None
and anatomical_coordinate_system is not None
world_from_anatomical is not None and anatomical_coordinate_system is not None
), "must supply the anatomical transform"
else:
anatomical_coordinate_system = volume.anatomical_coordinate_system
Expand Down Expand Up @@ -140,6 +138,25 @@ def from_json(
def from_markup(cls, *args, **kwargs):
return cls.from_json(*args, **kwargs)

@classmethod
def from_fcsv(cls, path: Path, **kwargs) -> LineAnnotation:
"""Load a LineAnnotation from a .fcsv file.
Args:
path (Path): Path to the .fcsv file.
world_from_anatomical (Optional[geo.FrameTransform], optional): The pose of the volume in world coordinates. Defaults to None.
Returns:
LineAnnotation: The loaded annotation.
"""
fiducial_list = FiducialList.from_fcsv(path)
assert len(fiducial_list) == 2, "fcsv file must contain exactly two points"
return cls(
fiducial_list[0],
fiducial_list[1],
**kwargs,
)

def save(
self,
path: str,
Expand Down Expand Up @@ -287,6 +304,9 @@ def trajectory_in_world(self) -> geo.Vector3D:
def direction_in_world(self) -> geo.Vector3D:
return self.trajectory_in_world.normalized()

def get_direction(self) -> geo.Vector3D:
return self.direction_in_world

def get_mesh(self):
"""Get the mesh in anatomical coordinates."""
u = self.startpoint
Expand All @@ -297,9 +317,7 @@ def get_mesh(self):
mesh += pv.Sphere(2.5, v)
return mesh

def get_mesh_in_world(
self, full: bool = True, use_cached: bool = False
) -> pv.PolyData:
def get_mesh_in_world(self, full: bool = True, use_cached: bool = False) -> pv.PolyData:
u = self.startpoint_in_world
v = self.endpoint_in_world

Expand Down
4 changes: 2 additions & 2 deletions deepdrr/device/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,8 @@ def get_mesh_in_world(self, full=False, use_cached=True):
+ pv.Line(s, ur)
+ pv.Line(s, bl)
+ pv.Line(s, br)
+ pv.Line(c, s)
+ pv.Sphere(5, c)
# + pv.Line(c, s) # Line along principle ray
# + pv.Sphere(5, c) # Sphere in center of image.
)
mesh.transform(geo.get_data(self.world_from_camera3d), inplace=True)
return mesh
6 changes: 5 additions & 1 deletion deepdrr/projector/projector.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,14 @@

# import pycuda.autoinit # causes problems when running with pytorch concurrently
import pycuda.driver as cuda
from pycuda.autoinit import context

# from pycuda.autoinit import context # also causes problems
from pycuda.autoprimaryctx import context # retains context across multiple calls
from pycuda.compiler import SourceModule
except ImportError:
log.warning(f"Running without pycuda: projector operations will fail.")
except RuntimeError as e:
log.warning(f"Running without pycuda, possibly in subprocess: {e}")


def import_pycuda():
Expand Down
11 changes: 6 additions & 5 deletions deepdrr/utils/mesh_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,12 @@ def voxelize(
ijk_from_world = world_from_ijk.inv

data = np.zeros((x, y, z), dtype=np.uint8)
for p in track(voxels.points, "Rasterizing..."):
p = geo.point(p)
ijk = ijk_from_world @ p
i, j, k = np.array(ijk).astype(int)
data[i, j, k] = 1
vectors = np.array(voxels.points)
A_h = np.hstack((vectors, np.ones((vectors.shape[0], 1))))
transform = np.array(ijk_from_world)
B = (transform @ A_h.T).T[:, :3]
B = np.round(B).astype(int)
data[B[:, 0], B[:, 1], B[:, 2]] = 1

return data, world_from_ijk

Expand Down
4 changes: 2 additions & 2 deletions deepdrr/vol/kwire.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@


class KWire(Volume):
_mesh_material = "titanium"
_mesh_material = "iron"

diameter = 2.0 # mm
tip_in_IJK: geo.Point3D
Expand Down Expand Up @@ -54,7 +54,7 @@ def from_example(
Returns:
KWire: The example KWire built into DeepDRR.
"""
url = "https://livejohnshopkins-my.sharepoint.com/:u:/g/personal/bkillee1_jh_edu/Ec2XGMXg_ItGtYWR_FfqHmUBwXJ1LmLBbbs4J_-3rJJQZg?e=fFWq6f&download=1"
url = "https://livejohnshopkins-my.sharepoint.com/:u:/g/personal/bkillee1_jh_edu/ERoEsDbaFj9InktoRKnrT-MBSF2oCOrZ9uyOeWViRx4-Qg?e=s5fofv&download=1"
md5 = "83ba7b63ebc0912d34ed5880460f81bd"
filename = "Kwire2.nii.gz"
path = data_utils.download(url, filename, md5=md5)
Expand Down
Loading

0 comments on commit 2c45632

Please sign in to comment.