Пример #1
0
 def _onSelect(self, event):
     """
     """
     coordinates = np.asarray(label2worldcoordinates(self.label),
                              dtype=np.float32)  # x,y,z
     n = tuple(coordinates.flat)
     self.points.append(n)
     scale = 0.25
     alpha = 1
     # create object sphere for point
     view = self.ax.GetView()
     #todo: plot instead of solidShere? better vis?
     # graph.Draw(mc='r', mw = 10, lc='y')
     # point = vv.plot(point[0], point[1], point[2],
     #                 mc = 'm', ms = 'o', mw = 8, alpha=0.5)
     node_point = vv.solidSphere(translation=(n),
                                 scaling=(scale, scale, scale))
     node_point.faceColor = (0, 1, 0, alpha)  # 'g' but with alpha
     node_point.visible = True
     node_point.node = n
     node_point.nr = self.pointindex
     self.ax.SetView(view)
     # store
     self.graph.add_node(n, number=self.pointindex)
     self.nodepoints.append(node_point)
     # update index of total selected points
     self.pointindex += 1
     self._updateTextIndex()
Пример #2
0
def create_node_points_with_amplitude(graph, scale=0.4, **kwargs):
    """ create node objects for gui and calculate motion amplitude for each node
    """
    from stentseg.motion.displacement import _calculateAmplitude
    pointsDeforms = []
    node_points = []
    for i, node in enumerate(sorted(graph.nodes())):
        node_point = vv.solidSphere(translation=(node),
                                    scaling=(scale, scale, scale))
        node_point.faceColor = (0, 0, 1, alpha)  # 'b' but with alpha
        node_point.visible = False
        node_point.node = node
        node_point.nr = i
        nodeDeforms = graph.node[node]['deforms']
        dmax_xyz = _calculateAmplitude(nodeDeforms,
                                       dim='xyz')  # [dmax, p1, p2]
        dmax_z = _calculateAmplitude(nodeDeforms, dim='z')
        dmax_y = _calculateAmplitude(nodeDeforms, dim='y')
        dmax_x = _calculateAmplitude(nodeDeforms, dim='x')
        pointsDeforms.append(nodeDeforms)
        node_point.amplXYZ = dmax_xyz  # amplitude xyz = [0]
        node_point.amplZ = dmax_z
        node_point.amplY = dmax_y
        node_point.amplX = dmax_x
        node_points.append(node_point)
    return node_points, pointsDeforms
Пример #3
0
    def test_gui(self):
        pp = Pointset(3)
        pp.append(0, 0, 0)
        pp.append(0, 1, 0)
        pp.append(1, 2, 0)
        pp.append(0, 2, 1)

        # Create all solids
        vv.solidBox((0, 0, 0))
        sphere = vv.solidSphere((3, 0, 0))
        cone = vv.solidCone((6, 0, 0))
        # a cone with 4 faces is a pyramid
        pyramid = vv.solidCone((9, 0, 0), N=4)
        vv.solidCylinder((0, 3, 0), (1, 1, 2))
        ring = vv.solidRing((3, 3, 0))
        vv.solidTeapot((6, 3, 0))
        vv.solidLine(pp+Point(9, 3, 0), radius=0.2)

        # Make the ring green
        ring.faceColor = 'g'

        # Make the sphere dull
        sphere.specular = 0
        sphere.diffuse = 0.4

        # Show lines in yellow pyramid
        pyramid.faceColor = 'r'
        pyramid.edgeShading = 'plain'

        # Colormap example
        N = cone._vertices.shape[0]
        cone.SetValues(np.linspace(0, 1, N))
        cone.colormap = vv.CM_JET
Пример #4
0
 def __init__(self, xy, v):
     #global w
     """:param xy: Initial position, :param v: Initial velocity. """
     # cast inputs as 2-d numpy arrays
     self.xy = xy.reshape((1,3)) #np.array(xy)
     self.v = v.reshape((1,3))  #np.array(v)
     
     # generate sphere data and colors.
     self.object = vv.solidSphere(vv.Point(self.xy), scaling=(0.05, 0.05, 0.05))
     self.object.faceColor = [random(), random(), random()]
     self.trans = self.object.transformations[0]
Пример #5
0
def interactive_node_points(graph, scale=0.4, **kwargs):
    """ create node objects for gui
    """
    node_points = []
    for i, node in enumerate(sorted(graph.nodes())):
        node_point = vv.solidSphere(translation=(node),
                                    scaling=(scale, scale, scale))
        node_point.faceColor = (0, 0, 1, alpha)  # 'b' but with alpha
        node_point.visible = False
        node_point.node = node
        node_point.nr = i
        node_points.append(node_point)
    return node_points
Пример #6
0
    def show(self):
        for projection_name in self.rsa_assessment.projection_list():
            rsa_projection = self.rsa_assessment.projection(projection_name)

            # projection = self.assessment.projection(i)
            # projector = self.projectors[i]
            self.plot_image_data(rsa_projection.image,
                                 rsa_projection.t,
                                 sampling=0.1)

            for image_segment_name in rsa_projection.image_segment_list():
                try:
                    rsa_image_segment = rsa_projection.image_segment(
                        image_segment_name)
                except NotImplementedError:
                    continue

                for line in rsa_projection.segment_point_lines(
                        rsa_image_segment):
                    ps = vv.Pointset(3)
                    ps.append(*list(line.a[:3]))
                    ps.append(*list(line.b[:3]))
                    vl = vv.solidLine(ps, radius=self.lineSize, N=self.lineN)
                    vl.faceColor = self.lineColor

        for scene_segment_name in self.rsa_assessment.scene_segment_list():
            try:
                scene_segment = self.rsa_assessment.scene_segment(
                    scene_segment_name)
            except NotImplementedError:
                continue

            scene_segment.match_crossing_lines()
            for i in range(len(scene_segment.points)):
                vs = vv.solidSphere(translation=tuple(
                    scene_segment.points[i][:3]),
                                    scaling=([self.pointSize] * 3),
                                    N=self.sphereN,
                                    M=self.sphereM)
                vs.faceColor = self.pointColor

        # Enter main loop
        app = vv.use()
        app.Run()
Пример #7
0
    if axes is None:
        axes = vv.gca()

    # Create mesh
    m = vv.OrientableMesh(axes, vertices, indices, normals, texcords, 4)
    #
    if translation is not None:
        m.translation = translation
    if scaling is not None:
        m.scaling = scaling
    if direction is not None:
        m.direction = direction
    if rotation is not None:
        m.rotation = rotation

    # Adjust axes
    if axesAdjust:
        if axes.daspectAuto is None:
            axes.daspectAuto = False
        axes.cameraType = '3d'
        axes.SetLimits()

    # Done
    axes.Draw()
    return m


if __name__ == '__main__':
    m = vv.solidSphere(scaling=(1, 1, 1.5), direction=(1, 1, 3))
    m.SetTexture(vv.imread('lena.png'))
Пример #8
0
def view(mol, viewer='native'):
    '''Render the molecule

    The mayavi backend doesn't work under python 3. The native backend uses
    visvis to render the molecule. This is very slow.
    It's better to use the molecular viewer.

    Args:
        mol (molecule.Molecule): The molecule instance to render
        viewer: The backend to use. Valid choices are 'native', 'maya'
        and, 'avogadro' (default: native).

    Rturns:
        None
    '''
    # mayavi
    if viewer == 'maya':
        from mayavi import mlab
        for atom in mol.atoms:
            pts = mlab.points3d(atom.r[0], atom.r[1], atom.r[2],
                                scale_factor=0.75,
                                scale_mode='none',
                                resolution=20,
                                color=atom.color())
        for i, j in mol.bonds():
            mlab.plot3d([mol.atoms[i].r[0], mol.atoms[j].r[0]],
                        [mol.atoms[i].r[1], mol.atoms[j].r[1]],
                        [mol.atoms[i].r[2], mol.atoms[j].r[2]],
                        tube_radius=0.1,
                        tube_sides=20)
        mlab.show()

    # avogadro
    if viewer == 'avogadro':
        from subprocess import call
        write_xyz(mol, 'avogadro.xyz')
        call(['avogadro', 'avogadro.xyz'])
        call(['rm', 'avogadro.xyz'])

    # visvis
    if viewer == 'native':
        import visvis as vv

        for atom in mol.atoms:
            x, y, z = atom.r
            at = vv.solidSphere((x, y, z), atom.radius()*0.25)
            at.faceColor = atom.color()

        for bond in mol.bonds():
            pp = vv.Pointset(3)
            pp.append(bond.atoms[0].r)
            pp.append(bond.atoms[1].r)
            vv.solidLine(pp, radius=0.15, N=16)

        pp = vv.Pointset(3)
        pp.append([3, 3, 3])
        pp.append([4, 3, 3])
        x = vv.solidLine(pp, radius=0.05)
        x.faceColor = 'r'
        conex = vv.solidCone([4, 3, 3], scaling=[0.1, 0.1, 0.1], direction=[1, 0, 0])
        conex.faceColor = 'r'

        pp = vv.Pointset(3)
        pp.append([3, 3, 3])
        pp.append([3, 4, 3])
        y = vv.solidLine(pp, radius=0.05)
        y.faceColor = 'g'
        coney = vv.solidCone([3, 4, 3], scaling=[0.1, 0.1, 0.1], direction=[0, 1, 0])
        coney.faceColor = 'g'

        pp = vv.Pointset(3)
        pp.append([3, 3, 3])
        pp.append([3, 3, 4])
        z = vv.solidLine(pp, radius=0.05)
        z.faceColor = 'b'
        conez = vv.solidCone([3, 3, 4], scaling=[0.1, 0.1, 0.1], direction=[0, 0, 1])
        conez.faceColor = 'b'

        # Set axes settings
        axes = vv.gca()
        axes.SetLimits(rangeX=(-5, 5), rangeY=(-5, 5), rangeZ=(-5, 5))
        vv.axis('off')
        app = vv.use()
        app.Run()
Пример #9
0
"""

import numpy as np
import visvis as vv
from visvis import Point, Pointset
vv.figure()
a = vv.gca()

# Define points for the line
pp = Pointset(3)
pp.append(0,0,0); pp.append(0,1,0); pp.append(1,2,0); pp.append(0,2,1)

# Create all solids
box = vv.solidBox((0,0,0))
sphere = vv.solidSphere((3,0,0))
cone = vv.solidCone((6,0,0))
pyramid = vv.solidCone((9,0,0), N=4) # a cone with 4 faces is a pyramid
cylinder = vv.solidCylinder((0,3,0),(1,1,2))
ring = vv.solidRing((3,3,0))
teapot = vv.solidTeapot((6,3,0))
line = vv.solidLine(pp+Point(9,3,0), radius = 0.2)

# Let's put a face on that cylinder
# This works because 2D texture coordinates are automatically generated for
# the sphere, cone, cylinder and ring. 
im = vv.imread('lena.png')
cylinder.SetTexture(im)

# Make the ring green
ring.faceColor = 'g'
Пример #10
0
    vv.title('Dynamic model for patient %s at %s ' % (ptcode[7:], ctcode))
    
# viewringcrop = {'daspect': (1.0, 1.0, -1.0), 'azimuth': 32.9516129032258, 
# 'elevation': 14.162658990412158, 'roll': 0.0, 
# 'loc': (166.79323747325407, 162.4692971514962, 52.28745470591859), 
# 'fov': 0.0, 'zoom': 0.026156241036960133}
# m = vv.mesh(modelmesh)
# # m.faceColor = 'g'
# m.clim = 0, 5
# m.colormap = vv.CM_JET

# Add motion
pointsDeforms = []
node_points = []
for i, node in enumerate(sorted(model.nodes())):
    node_point = vv.solidSphere(translation = (node), scaling = (0.8,0.8,0.8))
    node_point.faceColor = 'b'
    node_point.visible = False
    node_point.node = node
    node_point.nr = i
    if meshWithColors:
        nodeDeforms = model.node[node]['deforms']
        dmax_xyz = _calculateAmplitude(nodeDeforms, dim='xyz') # [dmax, p1, p2]
        dmax_z = _calculateAmplitude(nodeDeforms, dim='z')
        dmax_y = _calculateAmplitude(nodeDeforms, dim='y')
        dmax_x = _calculateAmplitude(nodeDeforms, dim='x')
        pointsDeforms.append(nodeDeforms)
        node_point.amplXYZ = dmax_xyz # amplitude xyz = [0]
        node_point.amplZ = dmax_z 
        node_point.amplY = dmax_y  
        node_point.amplX = dmax_x 
Пример #11
0
def plot_reference_sphere(theta=0,
                          phi=0,
                          isometric=True,
                          ax=None,
                          azimuth=None,
                          elevation=None,
                          degrees=True,
                          labels=True,
                          light_ambient=.6,
                          zoom=1.4,
                          arrow_color=(.25, .95, .8),
                          close_figure=False):

    if azimuth is None:
        azimuth = DEFAULT_AZIMUTH
    if elevation is None:
        elevation = DEFAULT_ELEVATION

    import visvis as vv

    if ax is None:
        app = vv.use()
        fig = vv.figure()
        ax = vv.subplot(111)

    else:
        app = None
        fig = ax.GetFigure()

    ax.axis.visible = 0
    ax.axis.xLabel = 'x'
    ax.axis.yLabel = 'y'
    ax.axis.zLabel = 'z'

    # coordinate system
    length = 1.4
    cyl_diameter = .05
    for i in range(3):
        direction = np.zeros((3, ))
        direction[i] = 1
        cyl = vv.solidCylinder(translation=(0, 0, 0),
                               scaling=(cyl_diameter, cyl_diameter, length),
                               direction=tuple(direction),
                               axesAdjust=False,
                               axes=ax)
        cyl.faceColor = (.75, .75, .75)

        translation = np.zeros((3, ))
        translation[i] = length
        cone = vv.solidCone(translation=tuple(translation),
                            scaling=(.1, .1, .2),
                            direction=tuple(direction),
                            axesAdjust=False,
                            axes=ax)
        cone.faceColor = (.75, .75, .75)

    # example direction
    length = 1
    shrink = .825
    direction = sph2cart(1, theta, phi, degrees=degrees).ravel()
    cyl = vv.solidCylinder(translation=(0, 0, 0),
                           scaling=(.05, .05, shrink * length),
                           direction=tuple(direction),
                           axesAdjust=False,
                           axes=ax)
    cyl.faceColor = arrow_color

    translation = direction * shrink
    cone = vv.solidCone(translation=tuple(translation),
                        scaling=(.1, .1, .2),
                        direction=tuple(direction),
                        axesAdjust=False,
                        axes=ax)
    cone.faceColor = arrow_color

    # indicate unit sphere
    sphere = vv.solidSphere((0, 0, 0), N=100, M=100)
    sphere.faceColor = (.5, .5, .5, .25)

    # some lines on sphere indicating main axes
    phi = np.linspace(0, 2 * np.pi, 100)
    theta = np.ones_like(phi) * np.pi / 2.
    r = np.ones_like(phi)
    xyz = sph2cart(r, theta, phi, degrees=False)
    vv.plot(xyz[:, 0],
            xyz[:, 1],
            xyz[:, 2],
            lw=1,
            lc=(.5, .5, .5),
            ls="-",
            mc='b',
            axesAdjust=False,
            axes=ax)

    theta = np.linspace(-np.pi, np.pi, 100)
    phi = np.ones_like(theta) * 0
    r = np.ones_like(phi)
    xyz = sph2cart(r, theta, phi, degrees=False)
    vv.plot(xyz[:, 0],
            xyz[:, 1],
            xyz[:, 2],
            lw=1,
            lc=(.5, .5, .5),
            ls="-",
            mc='b',
            axesAdjust=False,
            axes=ax)

    theta = np.linspace(-np.pi, np.pi, 100)
    phi = np.ones_like(theta) * np.pi / 2.
    r = np.ones_like(phi)
    xyz = sph2cart(r, theta, phi, degrees=False)
    vv.plot(xyz[:, 0],
            xyz[:, 1],
            xyz[:, 2],
            lw=1,
            lc=(.5, .5, .5),
            ls="-",
            mc='b',
            axesAdjust=False,
            axes=ax)

    # add pitch and roll axes
    aa = np.deg2rad(np.linspace(45, 315, 100) - 90)
    r = .25 + .025
    d = 1.25 + .05
    color = (.25, .25, .25)

    # pitch rotation (in x/z plane, i.e. around y-axis)
    xx = r * np.cos(aa)
    zz = r * np.sin(aa)
    yy = d * np.ones_like(xx)
    vv.plot(xx, yy, zz, lw=5, lc=color, ls="-", axesAdjust=False, axes=ax)

    translation = (xx[0], yy[0], zz[0])
    direction = (xx[0] - xx[1], yy[0] - yy[1], zz[0] - zz[1])
    cone = vv.solidCone(translation=translation,
                        scaling=(.05, .05, .1),
                        direction=direction,
                        axesAdjust=False,
                        axes=ax)
    cone.faceColor = color

    if labels:
        vv.Text(ax, 'Pitch', x=0, y=1.25 * d, z=.25, fontSize=28, color=color)

    # roll rotation (in y/z plane, i.e. around x-axis)
    yy = r * np.cos(aa)
    zz = r * np.sin(aa)
    xx = d * np.ones_like(xx)
    vv.plot(xx, yy, zz, lw=5, lc=color, ls="-", axesAdjust=False, axes=ax)

    translation = (xx[-1], yy[-1], zz[-1])
    direction = (xx[-1] - xx[-2], yy[-1] - yy[-2], zz[-1] - zz[-2])
    cone = vv.solidCone(translation=translation,
                        scaling=(.05, .05, .1),
                        direction=direction,
                        axesAdjust=False,
                        axes=ax)
    cone.faceColor = color

    if labels:
        vv.Text(ax, 'Roll', x=1.25 * d, y=-.8, z=0, fontSize=28, color=color)

    # set camera view
    zoom_ = vv.view()['zoom']
    if isometric:
        vv.view(dict(azimuth=90 + ISO_AZIMUTH, elevation=ISO_ELEVATION),
                zoom=zoom * zoom_,
                axes=ax)
    else:
        vv.view(dict(azimuth=90 + azimuth, elevation=elevation),
                zoom=zoom * zoom_,
                _axes=ax)

    ax.light0.ambient = light_ambient
    ax.light0.specular = .5

    fig.DrawNow()

    if app is not None:
        app.ProcessEvents()

    img = vv.screenshot(None, ob=ax, sf=2, bg=None, format=None)

    if close_figure:
        vv.close(fig)
        fig = None

    return fig, img
Пример #12
0
# light0 is always on, and is attached to the camera shining straight ahead
a = vv.gca()
a.light0.ambient = 0.2  # 0.2 is default for light 0
a.light0.diffuse = 1.0  # 1.0 is default

# The other lights are off by default and are positioned at the origin
light1 = a.lights[1]
light1.On()
light1.ambient = 0.0  # 0.0 is default for other lights
light1.color = (1, 0, 0)  # this light is red

# Create spheres
for i in range(len(shading)):
    for j in range(ndiffuse):
        s = vv.solidSphere((i, j, 0), (0.3, 0.3, 0.3))
        s.faceShading, s.edgeShading = shading[i]
        s.faceColor = (0.8, 0.8, 1.0)
        s.edgeColor = (0.8, 0.8, 1.0)
        s.diffuse = float(j) / ndiffuse

# Set settings for axes
a = vv.gca()
a.axis.xTicks = [str(x) for x in shading]
a.axis.xLabel = 'face- and edgeshading'
a.axis.yTicks = [str(float(j) / ndiffuse) for j in range(ndiffuse)]
a.axis.yLabel = 'diffuse reflection'

# Set back bg
a.bgcolor = 'k'
a.axis.axisColor = 'w'
Пример #13
0
    def plot3d(self,
               img,
               bodies={
                   'pose3d': np.empty((0, 13, 3)),
                   'pose2d': np.empty((0, 13, 2))
               },
               hands={
                   'pose3d': np.empty((0, 21, 3)),
                   'pose2d': np.empty((0, 21, 2))
               },
               faces={
                   'pose3d': np.empty((0, 84, 3)),
                   'pose2d': np.empty((0, 84, 2))
               },
               body_with_wrists=[],
               body_with_head=[],
               interactive=False):
        """
        :param img: a HxWx3 numpy array
        :param bodies: dictionnaroes with 'pose3d' (resp 'pose2d') with the body 3D (resp 2D) pose
        :param faces: same with face pose
        :param hands: same with hand pose
        :param body_with_wrists: list with for each body, a tuple (left_hand_id, right_hand_id) of the index of the hand detection attached to this body detection (-1 if none) for left and right hands
        :parma body_with_head: list with for each body, the index of the face detection attached to this body detection (-1 if none)
        :param interactive: whether to open the viewer in an interactive manner or not
        """

        # body pose do not use the same coordinate systems
        bodies['pose3d'][:, :, 0] *= -1
        bodies['pose3d'][:, :, 1] *= -1

        # Compute 3D scaled representation of each part, stored in "points3d"
        hands, bodies, faces = [copy.copy(s) for s in (hands, bodies, faces)]
        parts = (hands, bodies, faces)
        for part in parts:
            part['points3d'] = np.zeros_like(part['pose3d'])
            for part_idx in range(len(part['pose3d'])):
                points3d = scale_orthographic(part['pose3d'][part_idx],
                                              part['pose2d'][part_idx])
                part['points3d'][part_idx] = points3d

        # Various display tricks to make the 3D visualization of full-body nice
        # (1) for faces, add a Z offset to faces to align them with the body
        for body_id, face_id in enumerate(body_with_head):
            if face_id != -1:
                z_offset = bodies['points3d'][body_id, 12, 2] - np.mean(
                    faces['points3d'][face_id, :, 2])
                faces['points3d'][face_id, :, 2] += z_offset
        # (2) for hands, add a 3D offset to put them at the wrist location
        for body_id, (lwrist_id, rwrist_id) in enumerate(body_with_wrists):
            if lwrist_id != -1:
                hands['points3d'][lwrist_id, :, :] = bodies['points3d'][
                    body_id, 7, :] - hands['points3d'][lwrist_id, 0, :]
            if rwrist_id != -1:
                hands['points3d'][rwrist_id, :, :] = bodies['points3d'][
                    body_id, 6, :] - hands['points3d'][rwrist_id, 0, :]

        img = np.asarray(img)
        height, width = img.shape[:2]

        fig = vv.figure(1)
        fig.Clear()

        fig._SetPosition(0, 0, self.figsize[0], self.figsize[1])
        if not interactive:
            fig._enableUserInteraction = False

        axes = vv.gca()
        # Hide axis
        axes.axis.visible = False

        scaling_factor = 1.0 / height

        # Camera interaction is not intuitive along z axis
        # We reference every object to a parent frame that is rotated to circumvent the issue
        ref_frame = vv.Wobject(axes)
        ref_frame.transformations.append(vv.Transform_Rotate(-90, 1, 0, 0))
        ref_frame.transformations.append(
            vv.Transform_Translate(-0.5 * width * scaling_factor, -0.5, 0))

        # Draw image
        if self.display2d:
            # Display pose in 2D
            img = visu.visualize_bodyhandface2d(img,
                                                dict_poses2d={
                                                    'body': bodies['pose2d'],
                                                    'hand': hands['pose2d'],
                                                    'face': faces['pose2d']
                                                },
                                                lw=2,
                                                max_padding=0,
                                                bgr=False)

            XX, YY = np.meshgrid([0, width * scaling_factor], [0, 1])
            img_z_offset = 0.5
            ZZ = img_z_offset * np.ones(XX.shape)
            # Draw image
            embedded_img = vv.surf(XX, YY, ZZ, img)
            embedded_img.parent = ref_frame
            embedded_img.ambientAndDiffuse = 1.0

            # Draw a grid on the bottom floor to get a sense of depth
            XX, ZZ = np.meshgrid(
                np.linspace(0, width * scaling_factor, 10),
                img_z_offset - np.linspace(0, width * scaling_factor, 10))
            YY = np.ones_like(XX)
            grid3d = vv.surf(XX, YY, ZZ)
            grid3d.parent = ref_frame
            grid3d.edgeColor = (0.1, 0.1, 0.1, 1.0)
            grid3d.edgeShading = 'plain'
            grid3d.faceShading = None

        # Draw pose
        for part in parts:

            for part_idx in range(len(part['points3d'])):
                points3d = part['points3d'][part_idx] * scaling_factor
                # Draw bones
                J = len(points3d)
                is_body = (J == 13)
                ignore_neck = False if not is_body else body_with_head[
                    part_idx] != -1
                bones, bonecolors, pltcolors = visu._get_bones_and_colors(
                    J, ignore_neck=ignore_neck)
                for (kpt_id1, kpt_id2), color in zip(bones, bonecolors):
                    color = color[2], color[1], color[0]  # BGR vs RGB
                    p1 = visu._get_xyz(points3d, kpt_id1)
                    p2 = visu._get_xyz(points3d, kpt_id2)
                    pointset = vv.Pointset(3)
                    pointset.append(p1)
                    pointset.append(p2)

                    # Draw bones as solid capsules
                    bone_radius = 0.005
                    line = vv.solidLine(pointset, radius=bone_radius)
                    line.faceColor = color
                    line.ambientAndDiffuse = 1.0

                    line.parent = ref_frame

                # Draw keypoints, except for faces
                if J != 84:
                    keypoints_to_plot = points3d
                    if ignore_neck:
                        # for a nicer display, ignore head keypoint
                        keypoints_to_plot = keypoints_to_plot[:12, :]
                    # Use solid spheres
                    for i in range(len(keypoints_to_plot)):
                        kpt_wobject = vv.solidSphere(
                            translation=keypoints_to_plot[i, :].tolist(),
                            scaling=1.5 * bone_radius)
                        kpt_wobject.faceColor = (255, 0, 0)
                        kpt_wobject.ambientAndDiffuse = 1.0
                        kpt_wobject.parent = ref_frame

        # Use just an ambient lighting
        axes.light0.ambient = 0.8
        axes.light0.diffuse = 0.2
        axes.light0.specular = 0.0

        cam = vv.cameras.ThreeDCamera()
        axes.camera = cam
        #z axis
        cam.azimuth = -45
        cam.elevation = 20
        cam.roll = 0
        # Orthographic camera
        cam.fov = 0
        if self.camera_zoom is None:
            cam.zoom *= 1.3  # Zoom a bit more
        else:
            cam.zoom = self.camera_zoom
        if self.camera_location is not None:
            cam.loc = self.camera_location
        cam.SetView()

        if interactive:
            self.app.Run()
        else:
            fig._widget.update()
            self.app.ProcessEvents()

            img3d = vv.getframe(vv.gcf())
            img3d = np.clip(img3d * 255, 0, 255).astype(np.uint8)
            # Crop gray borders
            img3d = img3d[10:-10, 10:-10, :]

            return img3d, img
Пример #14
0
    if axes is None:
        axes = vv.gca()
    
    # Create mesh
    m = vv.OrientableMesh(axes, vertices, indices, normals, texcords, 4)
    #
    if translation is not None:
        m.translation = translation
    if scaling is not None:
        m.scaling = scaling
    if direction is not None:
        m.direction = direction
    if rotation is not None:
        m.rotation = rotation
    
    # Adjust axes
    if axesAdjust:
        if axes.daspectAuto is None:
            axes.daspectAuto = False
        axes.cameraType = '3d'
        axes.SetLimits()
    
    # Done
    axes.Draw()
    return m


if __name__ == '__main__':
    m = vv.solidSphere(scaling=(1,1,1.5), direction=(1,1,3))
    m.SetTexture( vv.imread('lena.png') )    
Пример #15
0
#!/usr/bin/env python
""" This example shows a ball that bounces on a surface and has
two balls rotating around it. It illustrates the use of timers
and how object hierarchy can be used to build (and move) complex
models consisting of multiple simple objects.
"""

import visvis as vv

# Create floor
floor = vv.solidBox((0,0,-1.5), (6,6,1))

# Create hierachy objects
sun = vv.solidSphere()
earth = vv.solidSphere((2,0,0),(0.3,0.3,0.2))
moon = vv.solidSphere((2,0,0),scaling=(0.2, 0.2, 0.3))
moon.parent = earth
earth.parent = sun

# Add transformations
sunTrans = sun.transformations[0]
earthRot = vv.Transform_Rotate(20)
moonRot = vv.Transform_Rotate(20)
earth.transformations.insert(0,earthRot)
moon.transformations.insert(0,moonRot)

# Set appearance
earth.faceColor = 'b'
moon.faceColor = 'y'
sun.faceColor = 'r'
Пример #16
0
# light0 is always on, and is attached to the camera shining straight ahead
a = vv.gca()
a.light0.ambient = 0.2 # 0.2 is default for light 0
a.light0.diffuse = 1.0 # 1.0 is default

# The other lights are off by default and are positioned at the origin
light1 = a.lights[1]
light1.On()
light1.ambient = 0.0 # 0.0 is default for other lights
light1.color = (1,0,0) # this light is red


# Create spheres
for i in range(len(shading)):
    for j in range(ndiffuse):
        s = vv.solidSphere((i,j,0), (0.3, 0.3, 0.3))
        s.faceShading, s.edgeShading = shading[i]
        s.faceColor = (0.8,0.8,1.0)
        s.edgeColor = (0.8,0.8,1.0)
        s.diffuse = float(j)/ndiffuse

# Set settings for axes
a = vv.gca()
a.axis.xTicks = [str(s) for s in shading]
a.axis.xLabel = 'face- and edgeshading'
a.axis.yTicks = [str(float(j)/ndiffuse) for j in range(ndiffuse)]
a.axis.yLabel = 'diffuse reflection'

# Set back bg
a.bgcolor = 'k'
a.axis.axisColor = 'w'
Пример #17
0
#!/usr/bin/env python
""" This example shows a ball that bounces on a surface and has
two balls rotating around it. It illustrates the use of timers
and how object hierarchy can be used to build (and move) complex
models consisting of multiple simple objects.
"""

import visvis as vv

# Create floor
floor = vv.solidBox((0, 0, -1.5), (6, 6, 1))

# Create hierachy objects
sun = vv.solidSphere()
earth = vv.solidSphere((2, 0, 0), (0.3, 0.3, 0.2))
moon = vv.solidSphere((2, 0, 0), scaling=(0.2, 0.2, 0.3))
moon.parent = earth
earth.parent = sun

# Add transformations
sunTrans = sun.transformations[0]
earthRot = vv.Transform_Rotate(20)
moonRot = vv.Transform_Rotate(20)
earth.transformations.insert(0, earthRot)
moon.transformations.insert(0, moonRot)

# Set appearance
earth.faceColor = 'b'
moon.faceColor = 'y'
sun.faceColor = 'r'
Пример #18
0
"""

import numpy as np
import visvis as vv
from visvis import Point, Pointset
vv.figure()
a = vv.gca()

# Define points for the line
pp = Pointset(3)
pp.append(0,0,0); pp.append(0,1,0); pp.append(1,2,0); pp.append(0,2,1)

# Create all solids
box = vv.solidBox((0,0,0))
sphere = vv.solidSphere((3,0,0))
cone = vv.solidCone((6,0,0))
pyramid = vv.solidCone((9,0,0), N=4) # a cone with 4 faces is a pyramid
cylinder = vv.solidCylinder((0,3,0),(1,1,2))
ring = vv.solidRing((3,3,0))
teapot = vv.solidTeapot((6,3,0))
line = vv.solidLine(pp+Point(9,3,0), radius = 0.2)

# Let's put a face on that cylinder
# This works because 2D texture coordinates are automatically generated for
# the sphere, cone, cylinder and ring.
im = vv.imread('astronaut.png')
cylinder.SetTexture(im)

# Make the ring green
ring.faceColor = 'g'
Пример #19
0
    def __init__(self,ptcode,ctcode,allcenterlines,basedir):
        """
        Script to show the stent plus centerline model and select points on 
        centerlines for motion analysis 
        """
        import os, time
        import pirt
        import visvis as vv
        import numpy as np
        import math
        import itertools
        import xlsxwriter
        from datetime import datetime

                
        from stentseg.utils.datahandling import select_dir, loadvol, loadmodel
        from stentseg.utils.new_pointset import PointSet
        from stentseg.stentdirect.stentgraph import create_mesh
        from stentseg.motion.vis import create_mesh_with_abs_displacement
        from stentseg.utils.visualization import show_ctvolume
        from pirt.utils.deformvis import DeformableTexture3D, DeformableMesh
        from stentseg.utils import PointSet
        from stentseg.stentdirect import stentgraph
        from visvis import Pointset # for meshes
        from stentseg.stentdirect.stentgraph import create_mesh
        from visvis.processing import lineToMesh, combineMeshes
        from visvis import ssdf
        from stentseg.utils.picker import pick3d
        try:
            from PyQt4 import QtCore, QtGui # PyQt5
        except ImportError:
            from PySide import QtCore, QtGui # PySide2
        from stentseg.apps.ui_dialog import MyDialog
        from stentseg.utils.centerline import dist_over_centerline # added for Mirthe 
        import copy
        
        
        cropname = 'prox'
        
        exceldir = os.path.join(basedir,ptcode)
        
        # Load deformations and avg ct (forward for mesh)
        # centerlines combined in 1 model
        m = loadmodel(basedir, ptcode, ctcode, cropname, modelname = 'centerline_total_modelavgreg_deforms') 
        model = m.model
        # centerlines separated in a model for each centerline
        # m_sep = loadmodel(basedir, ptcode, ctcode, cropname, modelname = 'centerline_modelavgreg_deforms')
        s = loadvol(basedir, ptcode, ctcode, cropname, what='avgreg')
        vol_org = copy.deepcopy(s.vol)
        s.vol.sampling = [vol_org.sampling[1], vol_org.sampling[1], vol_org.sampling[2]]
        s.sampling = s.vol.sampling
        vol = s.vol
        
        # Start visualization and GUI
        
        fig = vv.figure(30); vv.clf()
        
        fig.position = 0.00, 30.00,  944.00, 1002.00
        a = vv.gca()
        a.axis.axisColor = 1,1,1
        a.axis.visible = True
        a.bgcolor = 0,0,0
        a.daspect = 1, 1, -1
        lim = 2500
        t = vv.volshow(vol, clim=(0, lim), renderStyle='mip')
        pick3d(vv.gca(), vol)
        b = model.Draw(mc='b', mw = 0, lc='g', alpha = 0.5)
        vv.xlabel('x (mm)');vv.ylabel('y (mm)');vv.zlabel('z (mm)')
        vv.title('Model for LSPEAS %s  -  %s' % (ptcode[7:], ctcode))
        
        # Add clickable nodes
        t0 = time.time()
        node_points = []
        for i, node in enumerate(sorted(model.nodes())):
            node_point = vv.solidSphere(translation = (node), scaling = (0.6,0.6,0.6))
            node_point.faceColor = 'b'
            node_point.alpha = 0.5
            node_point.visible = True
            node_point.node = node
            node_point.nr = i
            node_points.append(node_point)
        t1 = time.time()
        print('Clickable nodes created, which took %1.2f min.' % ((t1-t0)/60))
        
        # list of correctly clicked nodes
        selected_nodes_sum = set()
        
        # Initialize labels
        t0 = vv.Label(a, '\b{Node nr|location}: ', fontSize=11, color='w')
        t0.position = 0.1, 25, 0.5, 20  # x (frac w), y, w (frac), h
        t0.bgcolor = None
        t0.visible = True
        t1 = vv.Label(a, '\b{Nodepair}: ', fontSize=11, color='w')
        t1.position = 0.1, 45, 0.5, 20
        t1.bgcolor = None
        t1.visible = True
        
        # Initialize output variable to store pulsatility analysis
        storeOutput = list()
        
        
        def on_key(event): 
            if event.key == vv.KEY_ENTER:
                
                # mogenlijkheden aantal nodes 
                    # 1 voor relative beweging vanuit avg punt
                    # 2 voor onderlinge beweging tussen twee punten
                    # 3 voor hoek in punt 2 van punt 1 naar punt 3
                    
                if len(selected_nodes) == 1:
                    selectn1 = selected_nodes[0].node
                    n1index = selected_nodes[0].nr
                    n1Deforms = model.node[selectn1]['deforms']
                    output = point_pulsatility(selectn1, n1Deforms)
                    output['NodesIndex'] = [n1index]
                    
                    # Store output with name
                    dialog_output = get_index_name()
                    output['Name'] = dialog_output
                    storeOutput.append(output)
                    
                    # update labels
                    t1.text = '\b{Node}: %i' % (n1index)
                    t1.visible = True
                    print('selection of 1 node stored')

                if len(selected_nodes) == 2:
                    # get nodes
                    selectn1 = selected_nodes[0].node
                    selectn2 = selected_nodes[1].node
                    # get index of nodes which are in fixed order
                    n1index = selected_nodes[0].nr
                    n2index = selected_nodes[1].nr
                    nindex = [n1index, n2index]
                    # get deforms of nodes
                    n1Deforms = model.node[selectn1]['deforms']
                    n2Deforms = model.node[selectn2]['deforms']
                    # get pulsatility
                    cl_merged = append_centerlines(allcenterlines) 
                    output = point_to_point_pulsatility(cl_merged, selectn1, 
                                        n1Deforms, selectn2, n2Deforms, type='euclidian')
                    output['NodesIndex'] = nindex
                    
                    # get distance_centerline
                   
                    #dist_cl = dist_over_centerline(cl_merged, selectn1, selectn2, type='euclidian') # toegevoegd Mirthe
                    
                    #dist_cl = dist_centerline_total(cl_merged, selectn1, 
                    #                    n1Deforms, selectn2, n2Deforms, type='euclidian')
                    
                    # Store output with name
                    dialog_output = get_index_name()
                    output['Name'] = dialog_output
                    storeOutput.append(output)  
                   
                    # update labels
                    t1.text = '\b{Node pair}: %i - %i' % (nindex[0], nindex[1])
                    t1.visible = True
                    print('selection of 2 nodes stored')
                        
                if len(selected_nodes) == 3:
                    # get nodes
                    selectn1 = selected_nodes[0].node
                    selectn2 = selected_nodes[1].node
                    selectn3 = selected_nodes[2].node
                    # get index of nodes which are in fixed order
                    n1index = selected_nodes[0].nr
                    n2index = selected_nodes[1].nr
                    n3index = selected_nodes[2].nr
                    nindex = [n1index, n2index, n3index]
                    # get deforms of nodes
                    n1Deforms = model.node[selectn1]['deforms']
                    n2Deforms = model.node[selectn2]['deforms']
                    n3Deforms = model.node[selectn3]['deforms']
                    # get angulation
                    output = line_line_angulation(selectn1, 
                                        n1Deforms, selectn2, n2Deforms, selectn3, n3Deforms)
                    output['NodesIndex'] = nindex
                    
                    # Store output with name
                    dialog_output = get_index_name()
                    output['Name'] = dialog_output
                    storeOutput.append(output)
                    
                    # update labels
                    t1.text = '\b{Nodes}: %i - %i - %i' % (nindex[0], nindex[1], nindex[2])
                    t1.visible = True
                    print('selection of 3 nodes stored')
                    
                if len(selected_nodes) > 3:
                    for node in selected_nodes:
                        node.faceColor = 'b'
                    selected_nodes.clear()
                    print('to many nodes selected, select 1,2 or 3 nodes')
                if len(selected_nodes) < 1:
                    for node in selected_nodes:
                        node.faceColor = 'b'
                    selected_nodes.clear()
                    print('to few nodes selected, select 1,2 or 3 nodes')                
                
                # Visualize analyzed nodes and deselect
                for node in selected_nodes:
                    selected_nodes_sum.add(node)

                for node in selected_nodes_sum:
                    node.faceColor = 'g'  # make green when analyzed
                selected_nodes.clear()
                
            if event.key == vv.KEY_ESCAPE:
                # FINISH MODEL, STORE TO EXCEL
                
                # Store to EXCEL
                storeOutputToExcel(storeOutput, exceldir)
                vv.close(fig)
                print('output stored to excel')
     
        selected_nodes = list()
        def select_node(event):
            """ select and deselect nodes by Double Click
            """
            if event.owner not in selected_nodes:
                event.owner.faceColor = 'r'
                selected_nodes.append(event.owner)
            elif event.owner in selected_nodes:
                event.owner.faceColor = 'b'
                selected_nodes.remove(event.owner)
        
        def pick_node(event):
            nodenr = event.owner.nr
            node = event.owner.node
            t0.text = '\b{Node nr|location}: %i | x=%1.3f y=%1.3f z=%1.3f' % (nodenr,node[0],node[1],node[2])
        
        def unpick_node(event):
            t0.text = '\b{Node nr|location}: '
        
        def point_pulsatility(point1, point1Deforms):
            n1Indices = point1 + point1Deforms
            pos_combinations = list(itertools.combinations(range(len(point1Deforms)),2))
            distances = []
            for i in pos_combinations:
                v = point1Deforms[i[0]] - point1Deforms[i[1]]
                distances.append(((v[0]**2 + v[1]**2 + v[2]**2)**0.5 ))
            distances = np.array(distances)
            
            # get max distance between phases
            point_phase_max = distances.max()
            point_phase_max = [point_phase_max, [x*10 for x in (pos_combinations[list(distances).index(point_phase_max)])]]
            
            # get min distance between phases
            point_phase_min = distances.min()
            point_phase_min = [point_phase_min, [x*10 for x in (pos_combinations[list(distances).index(point_phase_min)])]]
            
            return {'point_phase_min':point_phase_min,'point_phase_max': point_phase_max, 'Node1': [point1, point1Deforms]}

        def point_to_point_pulsatility(cl, point1, point1Deforms, 
                                            point2, point2Deforms,type='euclidian'):
            
            import numpy as np
            
            n1Indices = point1 + point1Deforms
            n2Indices = point2 + point2Deforms
            # define vector between nodes
            v = n1Indices - n2Indices
            distances = ( (v[:,0]**2 + v[:,1]**2 + v[:,2]**2)**0.5 ).reshape(-1,1)
            # get min and max distance
            point_to_pointMax = distances.max()
            point_to_pointMin = distances.min()
            # add phase in cardiac cycle where min and max where found (5th = 50%)
            point_to_pointMax = [point_to_pointMax, (list(distances).index(point_to_pointMax) )*10]
            point_to_pointMin = [point_to_pointMin, (list(distances).index(point_to_pointMin) )*10]
            # get median of distances
            point_to_pointMedian = np.percentile(distances, 50) # Q2
            # median of the lower half, Q1 and upper half, Q3
            point_to_pointQ1 = np.percentile(distances, 25)
            point_to_pointQ3 = np.percentile(distances, 75)
            # Pulsatility min max distance point to point
            point_to_pointP = point_to_pointMax[0] - point_to_pointMin[0]
            # add % change to pulsatility
            point_to_pointP = [point_to_pointP, (point_to_pointP/point_to_pointMin[0])*100 ]
            
            # find index of point on cll and calculate length change cll ???
            if isinstance(cl, PointSet):
                cl = np.asarray(cl).reshape((len(cl),3))
                
            indpoint1 = np.where( np.all(cl == point1, axis=-1) )[0] # -1 counts from last to the first axis
            indpoint2 = np.where( np.all(cl == point2, axis=-1) )[0] # renal point
            n1Indices = point1 + point1Deforms
            n2Indices = point2 + point2Deforms
            
            clDeforms = []
            clpart_deformed = []
            vectors = []
            clpart = []
            d = []
            dist_cl = []   
            clpartDeforms = []
            clpart_deformed_test = []
            
            for i in range(len(cl)):
                clDeforms1 = model.node[cl[i,0], cl[i,1], cl[i,2]]['deforms']
                clDeforms.append(clDeforms1)
                clpart_deformed1 = cl[i] + clDeforms1
                clpart_deformed.append(clpart_deformed1)
            
            # clpart = cl[min(indpoint1[0], indpoint2[0]):max(indpoint1[0], indpoint2[0])+1]
            
            clpart = clpart_deformed[min(indpoint1[0], indpoint2[0]):max(indpoint1[0], indpoint2[0])+1]
            
            # for i in range(len(clpart)):
            #     clpartDeforms1 = model.node[clpart[i,0], clpart[i,1], clpart[i,2]]['deforms']
            #     clpartDeforms.append(clpartDeforms1)
            #     clpart_deformed1_test = cl[i] + clpartDeforms1
            #     clpart_deformed_test.append(clpart_deformed1_test)
                
            # for k in range(len(n1Indices)):
            #     vectors_phases = np.vstack([clpart_deformed_test[i+1][k]-clpart_deformed_test[i][k] for i in range(len(clpart)-1)])
            #     vectors.append(vectors_phases)
                
            for k in range(len(n1Indices)):
                vectors_phases = np.vstack([clpart[i+1][k]-clpart[i][k] for i in range(len(clpart)-1)])
                vectors.append(vectors_phases)
            
            for i in range(len(vectors)):
                if type == 'euclidian':
                    d1 = (vectors[i][:,0]**2 + vectors[i][:,1]**2 + vectors[i][:,2]**2)**0.5  # 3Dvector length in mm
                    d.append(d1)
                elif type == 'z':
                    d = abs(vectors[i][:,2])  # x,y,z ; 1Dvector length in mm
             
            for i in range(len(d)):
                dist = d[i].sum()
                dist_cl.append(dist)
               
            #if indpoint2 > indpoint1: # stent point proximal to renal on centerline: positive
                #dist_cl*=-1
                
            cl_min_index1 = np.argmin(dist_cl)   
            cl_min_index = cl_min_index1*10
            cl_min = min(dist_cl)
            cl_max_index1 = np.argmax(dist_cl)   
            cl_max_index = cl_max_index1*10
            cl_max = max(dist_cl)
            
            print ([dist_cl])
            print ([point1, point2])
            
            return {'point_to_pointMin': point_to_pointMin, 
            'point_to_pointQ1': point_to_pointQ1, 
            'point_to_pointMedian': point_to_pointMedian, 
            'point_to_pointQ3': point_to_pointQ3, 
            'point_to_pointMax': point_to_pointMax, 
            'point_to_pointP': point_to_pointP, 
            'Node1': [point1, point1Deforms], 
            'Node2': [point2, point2Deforms], 'distances': distances, 
            'dist_cl': dist_cl, 'cl_min_index': cl_min_index, 
            'cl_max_index': cl_max_index, 'cl_min': cl_min, 'cl_max': cl_max}
            
        
        def line_line_angulation(point1, point1Deforms, point2, point2Deforms, point3, point3Deforms):
            n1Indices = point1 + point1Deforms
            n2Indices = point2 + point2Deforms
            n3Indices = point3 + point3Deforms
            
            # get vectors
            v1 = n1Indices - n2Indices
            v2 = n3Indices - n2Indices
            
            # get angles
            angles = []
            for i in range(len(v1)):
                angles.append(math.degrees(math.acos((np.dot(v1[i],v2[i]))/
                (np.linalg.norm(v1[i])*np.linalg.norm(v2[i])))))
            angles = np.array(angles)
            
            # get all angle differences of all phases
            pos_combinations = list(itertools.combinations(range(len(v1)),2))
            angle_diff = []
            for i in pos_combinations:
                v = point1Deforms[i[0]] - point1Deforms[i[1]]
                angle_diff.append(abs(angles[i[0]] - angles[i[1]]))
            angle_diff = np.array(angle_diff)
            
            # get max angle differences
            point_angle_diff_max = angle_diff.max()
            point_angle_diff_max = [point_angle_diff_max, [x*10 for x in
            (pos_combinations[list(angle_diff).index(point_angle_diff_max)])]]
            
            # get min angle differences
            point_angle_diff_min = angle_diff.min()
            point_angle_diff_min = [point_angle_diff_min, [x*10 for x in 
            (pos_combinations[list(angle_diff).index(point_angle_diff_min)])]]
            
            return {'point_angle_diff_min':point_angle_diff_min,
            'point_angle_diff_max': point_angle_diff_max, 'angles': angles, 
            'Node1': [point1, point1Deforms], 'Node2': [point2, point2Deforms], 
            'Node3': [point3, point1Deforms]}
            
        
        def append_centerlines(allcenterlines):
            """ Merge seperated PointSet centerlines into one PointSet
            """
            # cl_merged = allcenterlines[0]
            cl_merged = PointSet(3)
            for i in range(0,len(allcenterlines)):
                for point in allcenterlines[i]:
                    cl_merged.append(point)
            return cl_merged
            
            
        def get_index_name():
                # Gui for input name
                app = QtGui.QApplication([])
                m = MyDialog()
                m.show()
                m.exec_()
                dialog_output = m.edit.text()
                return dialog_output  
            
       
        def storeOutputToExcel(storeOutput, exceldir):
            """Create file and add a worksheet or overwrite existing
            """
            # https://pypi.python.org/pypi/XlsxWriter
            workbook = xlsxwriter.Workbook(os.path.join(exceldir,'storeOutput.xlsx'))
            worksheet = workbook.add_worksheet('General')
            # set column width
            worksheet.set_column('A:A', 35)
            worksheet.set_column('B:B', 30)
            # add a bold format to highlight cells
            bold = workbook.add_format({'bold': True})
            # write title and general tab
            worksheet.write('A1', 'Output ChEVAS dynamic CT, 10 Phases', bold)
            analysisID = '%s_%s_%s' % (ptcode, ctcode, cropname)
            worksheet.write('A2', 'Filename:', bold)
            worksheet.write('B2', analysisID)
            worksheet.write('A3', 'Date and Time:', bold)
            date_time = datetime.now() #strftime("%d-%m-%Y %H:%M")
            date_format_str = 'dd-mm-yyyy hh:mm'
            date_format = workbook.add_format({'num_format': date_format_str,
                                      'align': 'left'})
            worksheet.write_datetime('B3', date_time, date_format)
            # write 'storeOutput'
            sort_index = []
            for i in range(len(storeOutput)):
                type = len(storeOutput[i]['NodesIndex'])
                sort_index.append([i, type])
            sort_index = np.array(sort_index)
            sort_index = sort_index[sort_index[:,1].argsort()]
            
            for i, n in sort_index:
                worksheet = workbook.add_worksheet(storeOutput[i]['Name'])
                worksheet.set_column('A:A', 35)
                worksheet.set_column('B:B', 20)
                worksheet.write('A1', 'Name:', bold)
                worksheet.write('B1', storeOutput[i]['Name'])
                if n == 1:
                    worksheet.write('A2', 'Type:', bold)
                    worksheet.write('B2', '1 Node')
                    
                    worksheet.write('A3', 'Minimum translation (mm, Phases)',bold)
                    worksheet.write('B3', storeOutput[i]['point_phase_min'][0])
                    worksheet.write_row('C3', list(storeOutput[i]['point_phase_min'][1]))
                    
                    worksheet.write('A4', 'Maximum translation (mm, Phases)',bold)
                    worksheet.write('B4', storeOutput[i]['point_phase_max'][0])
                    worksheet.write_row('C4', list(storeOutput[i]['point_phase_max'][1]))
                    
                    worksheet.write('A5', 'Avg node position and deformations', bold)
                    worksheet.write('B5', str(list(storeOutput[i]['Node1'][0])))
                    worksheet.write_row('C5', [str(x)for x in list(storeOutput[i]['Node1'][1])])
                    
                    worksheet.write('A6', 'Node Index Number', bold)
                    worksheet.write_row('B6', list(storeOutput[i]['NodesIndex'])) 
                                       
                elif n == 2:
                    worksheet.write('A2', 'Type:', bold)
                    worksheet.write('B2', '2 Nodes')
                    
                    worksheet.write('A3', 'Minimum distance (mm, Phases)',bold)
                    worksheet.write('B3', storeOutput[i]['point_to_pointMin'][0])
                    worksheet.write('C3', storeOutput[i]['point_to_pointMin'][1])
                    
                    worksheet.write('A4', 'Q1 distance (mm)',bold)
                    worksheet.write('B4', storeOutput[i]['point_to_pointQ1'])

                    worksheet.write('A5', 'Median distance (mm)',bold)
                    worksheet.write('B5', storeOutput[i]['point_to_pointMedian'])
                    
                    worksheet.write('A6', 'Q3 distance (mm)',bold)
                    worksheet.write('B6', storeOutput[i]['point_to_pointQ3'])
                    
                    worksheet.write('A7', 'Maximum distance (mm, phases)',bold)
                    worksheet.write('B7', storeOutput[i]['point_to_pointMax'][0])
                    worksheet.write('C7', storeOutput[i]['point_to_pointMax'][1])
                    
                    worksheet.write('A8', 'Maximum distance difference (mm)', bold)
                    worksheet.write('B8', storeOutput[i]['point_to_pointP'][0])
                    
                    worksheet.write('A9', 'Distances for each phase', bold)
                    worksheet.write_row('B9', [str(x) for x in list(storeOutput[i]['distances'])])
                    
                    worksheet.write('A10', 'Avg node1 position and deformations', bold)
                    worksheet.write('B10', str(list(storeOutput[i]['Node1'][0])))
                    worksheet.write_row('C10', [str(x) for x in list(storeOutput[i]['Node1'][1])])
                    
                    worksheet.write('A11', 'Avg node2 position and deformations', bold)
                    worksheet.write('B11', str(list(storeOutput[i]['Node2'][0])))
                    worksheet.write_row('C11', [str(x) for x in list(storeOutput[i]['Node2'][1])])
                    
                    worksheet.write('A12', 'Node Index Number', bold)
                    worksheet.write_row('B12', list(storeOutput[i]['NodesIndex'])) 
                    
                    worksheet.write('A13', 'Length centerline', bold) 
                    worksheet.write('B13', str(list(storeOutput[i]['dist_cl']))) 
                    
                    worksheet.write('A14', 'Minimum length centerline', bold) 
                    worksheet.write('B14', storeOutput[i]['cl_min']) 
                    worksheet.write('C14', storeOutput[i]['cl_min_index']) 
                    
                    worksheet.write('A15', 'Maximum length centerline', bold) 
                    worksheet.write('B15', storeOutput[i]['cl_max'])  
                    worksheet.write('C15', storeOutput[i]['cl_max_index']) 
                
                elif n == 3:
                    worksheet.write('A2', 'Type:', bold)
                    worksheet.write('B2', '3 Nodes')
                    
                    worksheet.write('A3', 'Minimum angle difference (degrees, Phases)',bold)
                    worksheet.write('B3', storeOutput[i]['point_angle_diff_min'][0])
                    worksheet.write_row('C3', list(storeOutput[i]['point_angle_diff_min'][1]))
                    
                    worksheet.write('A4', 'Maximum angle difference (degrees, Phases)',bold)
                    worksheet.write('B4', storeOutput[i]['point_angle_diff_max'][0])
                    worksheet.write_row('C4', list(storeOutput[i]['point_angle_diff_max'][1]))
                    
                    worksheet.write('A5', 'Angles for each phase (degrees)',bold)
                    worksheet.write_row('B5', list(storeOutput[i]['angles']))
                    
                    worksheet.write('A6', 'Avg node1 position and deformations', bold)
                    worksheet.write('B6', str(list(storeOutput[i]['Node1'][0])))
                    worksheet.write_row('C6', [str(x) for x in list(storeOutput[i]['Node1'][1])])
                    
                    worksheet.write('A7', 'Avg node2 position and deformations', bold)
                    worksheet.write('B7', str(list(storeOutput[i]['Node2'][0])))
                    worksheet.write_row('C7', [str(x) for x in list(storeOutput[i]['Node2'][1])])
                    
                    worksheet.write('A8', 'Avg node2 position and deformations', bold)
                    worksheet.write('B8', str(list(storeOutput[i]['Node3'][0])))
                    worksheet.write_row('C8', [str(x) for x in list(storeOutput[i]['Node3'][1])])
                    
                    worksheet.write('A9', 'Node Index Number', bold)
                    worksheet.write_row('B9', list(storeOutput[i]['NodesIndex']))   
                    
            workbook.close()
        
        # Bind event handlers
        fig.eventKeyDown.Bind(on_key)
        for node_point in node_points:
            node_point.eventDoubleClick.Bind(select_node)
            node_point.eventEnter.Bind(pick_node)
            node_point.eventLeave.Bind(unpick_node)