def estimate_surface_area(self): """ Estimate the surface area by summing the areas of a trianglation of the nodules surface in 3d. Returned units are mm^2. """ mask = self.get_boolean_mask() mask = np.pad(mask, [(1,1), (1,1), (1,1)], 'constant') # Cap the ends. dist = dtrans(mask) - dtrans(~mask) rxy = self.scan.pixel_spacing rz = self.scan.slice_thickness verts, faces, _, _ = marching_cubes(dist, 0, spacing=(rxy, rxy, rz)) return mesh_surface_area(verts, faces)
def visualize_in_3d(self, edgecolor='0.2', cmap='viridis'): """ Visualize in 3d a triangulation of the nodule's surface. edgecolor: string color or rgb 3-tuple Sets edgecolors of triangulation. cmap: matplotlib colormap string. Sets the facecolors of the triangulation. See `matplotlib.cm.cmap_d.keys()` for all available. Example: >>> ann = pl.query(pl.Annotation).first() >>> ann.visualize_in_3d(edgecolor='green', cmap='autumn') """ if cmap not in plt.cm.cmap_d.keys(): raise ValueError("Invalid `cmap`. See `plt.cm.cmap_d.keys()`.") mask = self.get_boolean_mask() mask = np.pad(mask, [(1, 1), (1, 1), (1, 1)], 'constant') # Cap the ends. dist = dtrans(mask) - dtrans(~mask) rxy = self.scan.pixel_spacing rz = self.scan.slice_thickness verts, faces, _, _ = marching_cubes(dist, 0, spacing=(rxy, rxy, rz)) maxes = np.ceil(verts.max(axis=0)) fig = plt.figure() ax = fig.add_subplot(111, projection='3d') t = np.linspace(0, 1, faces.shape[0]) mesh = Poly3DCollection(verts[faces], edgecolor=edgecolor, facecolors=plt.cm.cmap_d[cmap](t)) ax.add_collection3d(mesh) ax.set_xlim(0, maxes[0]) ax.set_xlabel('length (mm)') ax.set_ylim(0, maxes[1]) ax.set_ylabel('length (mm)') ax.set_zlim(0, maxes[2]) ax.set_zlabel('length (mm)') plt.tight_layout() plt.show()
def visualize_in_3d(self, edgecolor='0.2', cmap='viridis', backend='matplotlib'): """ Visualize in 3d a triangulation of the nodule's surface. edgecolor: string color or rgb 3-tuple Sets edgecolors of triangulation. Ignored if backend != matplotlib. cmap: matplotlib colormap string. Sets the facecolors of the triangulation. See `matplotlib.cm.cmap_d.keys()` for all available. Ignored if backend != matplotlib. backend: string The backend for visualization. Default is matplotlib. Execute `from pylidc.Annotation import viz3dbackends` to see available backends. Example: >>> ann = pl.query(pl.Annotation).first() >>> ann.visualize_in_3d(edgecolor='green', cmap='autumn') >>> ann.visualize_in_3d(backend='mayavi') # If mayavi available. """ if backend not in viz3dbackends: raise ValueError("backend should be in %s." % viz3dbackends) if backend == 'matplotlib': if cmap not in plt.cm.cmap_d.keys(): raise ValueError("Invalid `cmap`. See `plt.cm.cmap_d.keys()`.") mask = self.get_boolean_mask() mask = np.pad(mask, [(1,1), (1,1), (1,1)], 'constant') # Cap the ends. # The zero set of the distance transform # makes for a little nicer surface. dist = dtrans(mask) - dtrans(~mask) rxy = self.scan.pixel_spacing rz = self.scan.slice_thickness if backend == 'matplotlib': verts, faces, _, _= marching_cubes(dist, 0, spacing=(rxy, rxy, rz)) maxes = np.ceil(verts.max(axis=0)) fig = plt.figure() ax = fig.add_subplot(111, projection='3d') t = np.linspace(0, 1, faces.shape[0]) mesh = Poly3DCollection(verts[faces], edgecolor=edgecolor, facecolors=plt.cm.cmap_d[cmap](t)) ax.add_collection3d(mesh) ax.set_xlim(0, maxes[0]) ax.set_xlabel('length (mm)') ax.set_ylim(0, maxes[1]) ax.set_ylabel('length (mm)') ax.set_zlim(0, maxes[2]) ax.set_zlabel('length (mm)') plt.tight_layout() plt.show() elif backend == 'mayavi': try: from mayavi import mlab sf = mlab.pipeline.scalar_field(dist) sf.spacing = [rxy, rxy, rz] mlab.pipeline.iso_surface(sf, contours=[0.0]) mlab.show() except ImportError: print("Mayavi could not be imported. Is it installed?")