Exemplo n.º 1
0
def Slicer2d(volume, levels=(None, None), size=(900, 900), bg='k9', zoom=1.2):
    """
    Create a 2D window with a single slice of a Volume,
    wich can be oriented arbitrarily in space.

    :param list wl: window and color levels
    """
    vsl = vedo.volume.VolumeSlice(
        volume)  # reuse the same underlying data as in vol

    # no argument will grab the existing cmap in vol (or use buildLUT())
    vsl.colorize()

    if levels[0] and levels[1]:
        vsl.lighting(window=levels[0], level=levels[1])

    usage = Text2D(
        f"SHIFT+Left click   \rightarrow rotate camera for oblique slicing\n"
        f"SHIFT+Middle click \rightarrow slice perpendicularly through image\n"
        f"Left click & drag  \rightarrow modify luminosity and contrast\n"
        f"R                  \rightarrow Reset the Window/Color levels\n"
        f"X                  \rightarrow Reset to sagittal view\n"
        f"Y                  \rightarrow Reset to coronal view\n"
        f"Z                  \rightarrow Reset to axial view",
        font="Calco",
        pos="top-left",
        s=0.8,
        bg='yellow',
        alpha=0.25)

    custom_shape = [  # define here the 2 rendering rectangle spaces
        dict(bottomleft=(0.0, 0.0), topright=(1, 1),
             bg='k9'),  # the full window
        dict(bottomleft=(0.8, 0.8), topright=(1, 1), bg='k8', bg2='lb'),
    ]

    axes = 11
    if settings.vtk_version[0] == 9:
        axes = 0

    hist = cornerHistogram(volume.pointdata[0],
                           bins=25,
                           logscale=1,
                           pos=(0.02, 0.02),
                           s=0.175,
                           c='dg',
                           bg='k',
                           alpha=1)

    plt = vedo.show([(vsl, usage, hist), volume],
                    shape=custom_shape,
                    mode="image",
                    title=volume.filename[:80],
                    size=size,
                    bg=bg,
                    zoom=zoom,
                    axes=axes,
                    interactive=0)
    return plt
Exemplo n.º 2
0
    def __init__(self, mesh1, mesh2, n):  ############################### init

        self.n = n  # desired nr. of intermediate shapes
        self.mode = '2d'
        self.mesh1 = mesh1
        self.mesh2 = mesh2
        self.merged_meshes = merge(mesh1, mesh2)
        self.mesh1.lw(4).c('grey2').pickable(False)
        self.mesh2.lw(4).c('grey1').pickable(False)

        self.arrow_starts = []
        self.arrow_stops = []
        self.dottedln = None
        self.toggle = False
        self.instructions = (
            "Click to add arrows interactively on the left panel\n"
            "right-click to remove last arrow. Then press:\n"
            "- m to morph the plane\n"
            "- c to clear\n"
            "- g to generate interpolation")
        self.msg1 = Text2D(self.instructions,
                           pos='top-left',
                           font="VictorMono",
                           bg='g2',
                           alpha=0.6)
        self.msg2 = Text2D('[output will show here]',
                           pos='top-left',
                           font="VictorMono")

        sz = self.merged_meshes.diagonalSize()
        self.plane1 = Grid(sx=sz, sy=sz, resx=50,
                           resy=50).pos(self.merged_meshes.centerOfMass())
        self.plane1.wireframe(False).alpha(1).lineWidth(0.1).c('white').lc(
            'grey5')
        self.plane2 = self.plane1.clone().pickable(False)

        self.plotter = Plotter(N=2, bg='light blue', size=(2000, 1000))
        self.plotter.addCallback('left click', self.onleftclick)
        self.plotter.addCallback('right click', self.onrightclick)
        self.plotter.addCallback('key press', self.onkeypress)
Exemplo n.º 3
0
    def __init__(
        self,
        mesh,
        splined=True,
        font="Bongas",
        alpha=0.9,
        lw=4,
        lc="red5",
        pc="red4",
        c="green3",
        tc="k9",
        tol=0.008,
    ):

        if not isinstance(mesh, Points):
            printc("FreeHandCutPlotter input must be Points or Mesh.", c='r')
            raise RuntimeError()

        Plotter.__init__(self, title="Free-hand mesh cutter")

        self.mesh = mesh
        self.mesh_prev = mesh
        self.splined = splined
        self.linecolor = lc
        self.linewidth = lw
        self.pointcolor = pc
        self.color = c
        self.alpha = alpha

        self.msg = "Right-click and move to draw line\n"
        self.msg += "Second right-click to stop drawing\n"
        self.msg += "Press L to extract largest surface\n"
        self.msg += "        z/Z to cut mesh (s to save)\n"
        self.msg += "        c to clear points, u to undo"
        self.txt2d = Text2D(self.msg, pos='top-left', font=font, s=0.9)
        self.txt2d.c(tc).background(c, alpha).frame()

        self.idkeypress = self.addCallback('KeyPress', self._onKeyPress)
        self.idrightclck = self.addCallback('RightButton', self._onRightClick)
        self.idmousemove = self.addCallback('MouseMove', self._onMouseMove)
        self.drawmode = False
        self.tol = tol  # tolerance of point distance
        self.cpoints = []
        self.points = None
        self.spline = None
        self.jline = None
        self.topline = None
        self.top_pts = []
Exemplo n.º 4
0
def Slicer(
    volume,
    alpha=1,
    cmaps=('gist_ncar_r', "hot_r", "bone_r", "jet", "Spectral_r"),
    map2cells=False,  # buggy
    clamp=True,
    useSlider3D=False,
    size=(850, 700),
    screensize="auto",
    title="",
    bg="white",
    bg2="lightblue",
    axes=7,
    showHisto=True,
    showIcon=True,
    draggable=False,
    verbose=True,
):
    """
    Generate a ``Plotter`` window with slicing planes for the input Volume.
    Returns the ``Plotter`` object.

    :param float alpha: transparency of the slicing planes
    :param list cmaps: list of color maps names to cycle when clicking button
    :param bool map2cells: scalars are mapped to cells, not intepolated.
    :param bool clamp: clamp scalar to reduce the effect of tails in color mapping
    :param bool useSlider3D: show sliders attached along the axes
    :param list size: rendering window size in pixels
    :param list screensize: size of the screen can be specified
    :param str title: window title
    :param bg: background color
    :param bg2: background gradient color
    :param int axes: axis type number
    :param bool showHisto: show histogram on bottom left
    :param bool showIcon: show a small 3D rendering icon of the volume
    :param bool draggable: make the icon draggable
    """
    global _cmap_slicer

    if verbose: printc("Slicer tool", invert=1, c="m")
    ################################
    vp = Plotter(
        bg=bg,
        bg2=bg2,
        size=size,
        screensize=screensize,
        title=title,
        interactive=False,
    )

    ################################
    box = volume.box().wireframe().alpha(0)

    vp.show(box, viewup="z", axes=axes)
    if showIcon:
        vp.addInset(volume,
                    pos=(.85, .85),
                    size=0.15,
                    c='w',
                    draggable=draggable)

    # inits
    la, ld = 0.7, 0.3  #ambient, diffuse
    dims = volume.dimensions()
    data = volume.getPointArray()
    rmin, rmax = volume.imagedata().GetScalarRange()
    if clamp:
        hdata, edg = np.histogram(data, bins=50)
        logdata = np.log(hdata + 1)
        # mean  of the logscale plot
        meanlog = np.sum(np.multiply(edg[:-1], logdata)) / np.sum(logdata)
        rmax = min(rmax, meanlog + (meanlog - rmin) * 0.9)
        rmin = max(rmin, meanlog - (rmax - meanlog) * 0.9)
        if verbose:
            printc('scalar range clamped to: (' + precision(rmin, 3) + ', ' +
                   precision(rmax, 3) + ')',
                   c='m',
                   bold=0)
    _cmap_slicer = cmaps[0]
    visibles = [None, None, None]
    msh = volume.zSlice(int(dims[2] / 2))
    msh.alpha(alpha).lighting('', la, ld, 0)
    msh.cmap(_cmap_slicer, vmin=rmin, vmax=rmax)
    if map2cells: msh.mapPointsToCells()
    vp.renderer.AddActor(msh)
    visibles[2] = msh
    addScalarBar(msh, pos=(0.04, 0.0), horizontal=True, titleFontSize=0)

    def sliderfunc_x(widget, event):
        i = int(widget.GetRepresentation().GetValue())
        msh = volume.xSlice(i).alpha(alpha).lighting('', la, ld, 0)
        msh.cmap(_cmap_slicer, vmin=rmin, vmax=rmax)
        if map2cells: msh.mapPointsToCells()
        vp.renderer.RemoveActor(visibles[0])
        if i and i < dims[0]: vp.renderer.AddActor(msh)
        visibles[0] = msh

    def sliderfunc_y(widget, event):
        i = int(widget.GetRepresentation().GetValue())
        msh = volume.ySlice(i).alpha(alpha).lighting('', la, ld, 0)
        msh.cmap(_cmap_slicer, vmin=rmin, vmax=rmax)
        if map2cells: msh.mapPointsToCells()
        vp.renderer.RemoveActor(visibles[1])
        if i and i < dims[1]: vp.renderer.AddActor(msh)
        visibles[1] = msh

    def sliderfunc_z(widget, event):
        i = int(widget.GetRepresentation().GetValue())
        msh = volume.zSlice(i).alpha(alpha).lighting('', la, ld, 0)
        msh.cmap(_cmap_slicer, vmin=rmin, vmax=rmax)
        if map2cells: msh.mapPointsToCells()
        vp.renderer.RemoveActor(visibles[2])
        if i and i < dims[2]: vp.renderer.AddActor(msh)
        visibles[2] = msh

    cx, cy, cz, ch = 'dr', 'dg', 'db', (0.3, 0.3, 0.3)
    if np.sum(vp.renderer.GetBackground()) < 1.5:
        cx, cy, cz = 'lr', 'lg', 'lb'
        ch = (0.8, 0.8, 0.8)

    if not useSlider3D:
        vp.addSlider2D(sliderfunc_x,
                       0,
                       dims[0],
                       title='X',
                       titleSize=0.5,
                       pos=[(0.8, 0.12), (0.95, 0.12)],
                       showValue=False,
                       c=cx)
        vp.addSlider2D(sliderfunc_y,
                       0,
                       dims[1],
                       title='Y',
                       titleSize=0.5,
                       pos=[(0.8, 0.08), (0.95, 0.08)],
                       showValue=False,
                       c=cy)
        vp.addSlider2D(sliderfunc_z,
                       0,
                       dims[2],
                       title='Z',
                       titleSize=0.6,
                       value=int(dims[2] / 2),
                       pos=[(0.8, 0.04), (0.95, 0.04)],
                       showValue=False,
                       c=cz)
    else:  # 3d sliders attached to the axes bounds
        bs = box.bounds()
        vp.addSlider3D(
            sliderfunc_x,
            pos1=(bs[0], bs[2], bs[4]),
            pos2=(bs[1], bs[2], bs[4]),
            xmin=0,
            xmax=dims[0],
            t=box.diagonalSize() / mag(box.xbounds()) * 0.6,
            c=cx,
            showValue=False,
        )
        vp.addSlider3D(
            sliderfunc_y,
            pos1=(bs[1], bs[2], bs[4]),
            pos2=(bs[1], bs[3], bs[4]),
            xmin=0,
            xmax=dims[1],
            t=box.diagonalSize() / mag(box.ybounds()) * 0.6,
            c=cy,
            showValue=False,
        )
        vp.addSlider3D(
            sliderfunc_z,
            pos1=(bs[0], bs[2], bs[4]),
            pos2=(bs[0], bs[2], bs[5]),
            xmin=0,
            xmax=dims[2],
            value=int(dims[2] / 2),
            t=box.diagonalSize() / mag(box.zbounds()) * 0.6,
            c=cz,
            showValue=False,
        )

    #################
    def buttonfunc():
        global _cmap_slicer
        bu.switch()
        _cmap_slicer = bu.status()
        for mesh in visibles:
            if mesh:
                mesh.cmap(_cmap_slicer, vmin=rmin, vmax=rmax)
                if map2cells:
                    mesh.mapPointsToCells()
        vp.renderer.RemoveActor(mesh.scalarbar)
        mesh.scalarbar = addScalarBar(mesh,
                                      pos=(0.04, 0.0),
                                      horizontal=True,
                                      titleFontSize=0)
        vp.renderer.AddActor(mesh.scalarbar)

    bu = vp.addButton(
        buttonfunc,
        pos=(0.27, 0.005),
        states=cmaps,
        c=["db"] * len(cmaps),
        bc=["lb"] * len(cmaps),  # colors of states
        size=14,
        bold=True,
    )

    #################
    hist = None
    if showHisto:
        hist = cornerHistogram(data,
                               s=0.2,
                               bins=25,
                               logscale=1,
                               pos=(0.02, 0.02),
                               c=ch,
                               bg=ch,
                               alpha=0.7)

    comment = None
    if verbose:
        comment = Text2D(
            "Use sliders to slice volume\nClick button to change colormap",
            font='',
            s=0.8)

    vp.show(msh, hist, comment, interactive=False)
    vp.interactive = True
    if verbose:
        printc("Press button to cycle through color maps,", c="m")
        printc("Use sliders to select the slicing planes.", c="m")
    return vp
Exemplo n.º 5
0
def plot(*inputobj, **options):
    """
    Plot the object(s) provided.

    Input can be any combination of: ``Mesh``, ``Volume``, ``dolfin.Mesh``,
    ``dolfin.MeshFunction``, ``dolfin.Expression`` or ``dolfin.Function``.

    :return: the current ``Plotter`` class instance.

    :param str mode: one or more of the following can be combined in any order

        - `mesh`/`color`, will plot the mesh, by default colored with a scalar if available
        - `displacement` show displaced mesh by solution
        - `arrows`, mesh displacements are plotted as scaled arrows.
        - `lines`, mesh displacements are plotted as scaled lines.
        - `tensors`, to be implemented

    :param bool add: add the input objects without clearing the already plotted ones
    :param float density: show only a subset of lines or arrows [0-1]
    :param bool wire[frame]: visualize mesh as wireframe [False]
    :param c[olor]: set mesh color [None]
    :param bool exterior: only show the outer surface of the mesh [False]
    :param float alpha: set object's transparency [1]
    :param float lw: line width of the mesh (set to zero to hide mesh) [0.5]
    :param float ps: set point size of mesh vertices [None]
    :param float z: add a constant to z-coordinate (useful to show 2D slices as function of time)
    :param str legend: add a legend to the top-right of window [None]
    :param bool scalarbar: add a scalarbar to the window ['vertical']
    :param float vmin: set the minimum for the range of the scalar [None]
    :param float vmax: set the maximum for the range of the scalar [None]
    :param float scale: add a scaling factor to arrows and lines sizes [1]
    :param str cmap: choose a color map for scalars
    :param str shading: mesh shading ['flat', 'phong', 'gouraud']
    :param str text: add a gray text comment to the top-left of the window [None]

    :param dict isolines: dictionary of isolines properties

        - n, (int) - add this number of isolines to the mesh
        - c, - isoline color
        - lw, (float) - isoline width
        - z, (float) - add to the isoline z coordinate to make them more visible


    :param dict streamlines: dictionary of streamlines properties

        - probes, (list, None) - custom list of points to use as seeds
        - tol, (float) - tolerance to reduce the number of seed points used in mesh
        - lw, (float) - line width of the streamline
        - direction, (str) - direction of integration ('forward', 'backward' or 'both')
        - maxPropagation, (float) - max propagation of the streamline
        - scalarRange, (list) - scalar range of coloring


   :param float warpZfactor: elevate z-axis by scalar value (useful for 2D geometries)
    :param float warpYfactor: elevate z-axis by scalar value (useful for 1D geometries)

    :param list scaleMeshFactors: rescale mesh by these factors [1,1,1]

    :param bool newPlotter: spawn a new instance of Plotter class, pops up a new window
    :param int at: renderer number to plot to
    :param list shape: subdvide window in (n,m) rows and columns
    :param int N: automatically subdvide window in N renderers
    :param list pos: (x,y) coordinates of the window position on screen
    :param size: window size (x,y)

    :param str title: window title
    :param bg: background color name of window
    :param bg2: second background color name to create a color gradient
    :param int style: choose a predefined style [0-4]

      - 0, `vedo`, style (blackboard background, rainbow color map)
      - 1, `matplotlib`, style (white background, viridis color map)
      - 2, `paraview`, style
      - 3, `meshlab`, style
      - 4, `bw`, black and white style.

    :param int axes: axes type number

      - 0,  no axes,
      - 1,  draw customizable grid axes (see below).
      - 2,  show cartesian axes from (0,0,0)
      - 3,  show positive range of cartesian axes from (0,0,0)
      - 4,  show a triad at bottom left
      - 5,  show a cube at bottom left
      - 6,  mark the corners of the bounding box
      - 7,  draw a simple ruler at the bottom of the window
      - 8,  show the `vtkCubeAxesActor` object,
      - 9,  show the bounding box outLine,
      - 10, show three circles representing the maximum bounding box,
      - 11, show a large grid on the x-y plane (use with zoom=8)
      - 12, show polar axes.

    Axes type-1 can be fully customized by passing a dictionary ``axes=dict()`` where:

        - `xtitle`,                ['x'], x-axis title text
        - `xrange`,               [None], x-axis range in format (xmin, ymin), default is automatic.
        - `numberOfDivisions`,    [None], approximate number of divisions on the longest axis
        - `axesLineWidth`,           [1], width of the axes lines
        - `gridLineWidth`,           [1], width of the grid lines
        - `reorientShortTitle`,   [True], titles shorter than 2 letter are placed horizontally
        - `originMarkerSize`,     [0.01], draw a small cube on the axis where the origin is
        - `titleDepth`,              [0], extrusion fractional depth of title text
        - `xyGrid`,               [True], show a gridded wall on plane xy
        - `yzGrid`,               [True], show a gridded wall on plane yz
        - `zxGrid`,               [True], show a gridded wall on plane zx
        - `zxGrid2`,             [False], show zx plane on opposite side of the bounding box
        - `xyGridTransparent`    [False], make grid plane completely transparent
        - `xyGrid2Transparent`   [False], make grid plane completely transparent on opposite side box
        - `xyPlaneColor`,       ['gray'], color of the plane
        - `xyGridColor`,        ['gray'], grid line color
        - `xyAlpha`,              [0.15], grid plane opacity
        - `xyFrameLine`,          [None], add a frame for the plane
        - `showTicks`,            [True], show major ticks
        - `xTitlePosition`,       [0.32], title fractional positions along axis
        - `xTitleOffset`,         [0.05], title fractional offset distance from axis line
        - `xTitleJustify`, ["top-right"], title justification
        - `xTitleRotation`,          [0], add a rotation of the axis title
        - `xLineColor`,      [automatic], color of the x-axis
        - `xTitleColor`,     [automatic], color of the axis title
        - `xTitleBackfaceColor`,  [None],  color of axis title on its backface
        - `xTitleSize`,          [0.025], size of the axis title
        - 'xTitleItalic',            [0], a bool or float to make the font italic
        - `xHighlightZero`,       [True], draw a line highlighting zero position if in range
        - `xHighlightZeroColor`, [autom], color of the line highlighting the zero position
        - `xTickLength`,         [0.005], radius of the major ticks
        - `xTickThickness`,     [0.0025], thickness of the major ticks along their axis
        - `xTickColor`,      [automatic], color of major ticks
        - `xMinorTicks`,             [1], number of minor ticks between two major ticks
        - `xPositionsAndLabels`       [], assign custom tick positions and labels [(pos1, label1), ...]
        - `xLabelPrecision`,         [2], nr. of significative digits to be shown
        - `xLabelSize`,          [0.015], size of the numeric labels along axis
        - `xLabelOffset`,        [0.025], offset of numeric labels
        - 'xFlipText'.           [False], flip axis title and numeric labels orientation
        - `tipSize`,              [0.01], size of the arrow tip
        - `limitRatio`,           [0.04], below this ratio don't plot small axis

    :param bool infinity: if True fugue point is set at infinity (no perspective effects)
    :param bool sharecam: if False each renderer will have an independent vtkCamera
    :param bool interactive: if True will stop after show() to allow interaction w/ window
    :param bool offscreen: if True will not show the rendering window

    :param float zoom: camera zooming factor
    :param viewup: camera view-up direction ['x','y','z', or a vector direction]
    :param float azimuth: add azimuth rotation of the scene, in degrees
    :param float elevation: add elevation rotation of the scene, in degrees
    :param float roll: add roll-type rotation of the scene, in degrees

    :param dict camera: Camera parameters can further be specified with a dictionary
        assigned to the ``camera`` keyword:
        (E.g. `show(camera={'pos':(1,2,3), 'thickness':1000,})`)

        - `pos`, `(list)`,
            the position of the camera in world coordinates

        - `focalPoint`, `(list)`,
            the focal point of the camera in world coordinates

        - `viewup`, `(list)`,
            the view up direction for the camera

        - `distance`, `(float)`,
            set the focal point to the specified distance from the camera position.

        - `clippingRange`, `(float)`,
            distance of the near and far clipping planes along the direction of projection.

        - `parallelScale`, `(float)`,
            scaling used for a parallel projection, i.e. the height of the viewport
            in world-coordinate distances. The default is 1. Note that the "scale" parameter works as
            an "inverse scale", larger numbers produce smaller images.
            This method has no effect in perspective projection mode.

        - `thickness`, `(float)`,
            set the distance between clipping planes. This method adjusts the far clipping
            plane to be set a distance 'thickness' beyond the near clipping plane.

        - `viewAngle`, `(float)`,
            the camera view angle, which is the angular height of the camera view
            measured in degrees. The default angle is 30 degrees.
            This method has no effect in parallel projection mode.
            The formula for setting the angle up for perfect perspective viewing is:
            angle = 2*atan((h/2)/d) where h is the height of the RenderWindow
            (measured by holding a ruler up to your screen) and d is the distance
            from your eyes to the screen.

    :param int interactorStyle: change the style of muose interaction of the scene
    :param bool q: exit python session after returning.
    """
    if len(inputobj) == 0:
        interactive()
        return

    if 'numpy' in str(type(inputobj[0])):
        from vedo.pyplot import plot as pyplot_plot
        return pyplot_plot(*inputobj, **options)

    mesh, u = _inputsort(inputobj)

    mode = options.pop("mode", 'mesh')
    ttime = options.pop("z", None)

    add = options.pop("add", False)

    wire = options.pop("wireframe", None)

    c = options.pop("c", None)
    color = options.pop("color", None)
    if color is not None:
        c = color

    lc = options.pop("lc", None)

    alpha = options.pop("alpha", 1)
    lw = options.pop("lw", 0.5)
    ps = options.pop("ps", None)
    legend = options.pop("legend", None)
    scbar = options.pop("scalarbar", 'v')
    vmin = options.pop("vmin", None)
    vmax = options.pop("vmax", None)
    cmap = options.pop("cmap", None)
    scale = options.pop("scale", 1)
    scaleMeshFactors = options.pop("scaleMeshFactors", [1, 1, 1])
    shading = options.pop("shading", 'phong')
    text = options.pop("text", None)
    style = options.pop("style", 'vtk')
    isolns = options.pop("isolines", dict())
    streamlines = options.pop("streamlines", dict())
    warpZfactor = options.pop("warpZfactor", None)
    warpYfactor = options.pop("warpYfactor", None)
    lighting = options.pop("lighting", None)
    exterior = options.pop("exterior", False)
    fast = options.pop("fast", False)
    returnActorsNoShow = options.pop("returnActorsNoShow", False)

    # refresh axes titles for axes type = 8 (vtkCubeAxesActor)
    settings.xtitle = options.pop("xtitle", 'x')
    settings.ytitle = options.pop("ytitle", 'y')
    settings.ztitle = options.pop("ztitle", 'z')
    if settings.plotter_instance:
        if settings.ytitle != 'x':
            if 'at' in options.keys():
                at = options['at']
            else:
                at = 0
            aet = settings.plotter_instance.axes_instances
            if len(aet) > at and isinstance(aet[at], vtk.vtkCubeAxesActor):
                aet[at].SetXTitle(settings.xtitle)
        if settings.ytitle != 'y':
            if 'at' in options.keys():
                at = options['at']
            else:
                at = 0
            aet = settings.plotter_instance.axes_instances
            if len(aet) > at and isinstance(aet[at], vtk.vtkCubeAxesActor):
                aet[at].SetYTitle(settings.ytitle)
        if settings.ytitle != 'z':
            if 'at' in options.keys():
                at = options['at']
            else:
                at = 0
            aet = settings.plotter_instance.axes_instances
            if len(aet) > at and isinstance(aet[at], vtk.vtkCubeAxesActor):
                aet[at].SetZTitle(settings.ztitle)

    # change some default to emulate standard behaviours
    options['verbose'] = False  # don't disturb
    if style == 0 or style == 'vtk':
        font = 'courier'
        axes = options.pop('axes', None)
        if axes is None:
            options['axes'] = {
                'xyGrid': False,
                'yzGrid': False,
                'zxGrid': False,
            }
        else:
            options['axes'] = axes  # put back
        if cmap is None:
            cmap = 'rainbow'
    elif style == 1 or style == 'matplotlib':
        font = 'courier'
        bg = options.pop('bg', None)
        if bg is None:
            options['bg'] = 'white'
        else:
            options['bg'] = bg
        axes = options.pop('axes', None)
        if axes is None:
            options['axes'] = {
                'xyGrid': False,
                'yzGrid': False,
                'zxGrid': False,
            }
        else:
            options['axes'] = axes  # put back
        if cmap is None:
            cmap = 'viridis'
    elif style == 2 or style == 'paraview':
        font = 'arial'
        bg = options.pop('bg', None)
        if bg is None:
            options['bg'] = (82, 87, 110)
        else:
            options['bg'] = bg
        if cmap is None:
            cmap = 'coolwarm'
    elif style == 3 or style == 'meshlab':
        font = 'courier'
        bg = options.pop('bg', None)
        if bg is None:
            options['bg'] = (8, 8, 16)
            options['bg2'] = (117, 117, 234)
        else:
            options['bg'] = bg
        axes = options.pop('axes', None)
        if axes is None:
            options['axes'] = 10
        else:
            options['axes'] = axes  # put back
        if cmap is None:
            cmap = 'afmhot'
    elif style == 4 or style == 'bw':
        font = 'courier'
        bg = options.pop('bg', None)
        if bg is None:
            options['bg'] = (217, 255, 238)
        else:
            options['bg'] = bg
        axes = options.pop('axes', None)
        if axes is None:
            options['axes'] = {
                'xyGrid': False,
                'yzGrid': False,
                'zxGrid': False,
            }
        else:
            options['axes'] = axes  # put back
        if cmap is None:
            cmap = 'binary'

    #################################################################
    actors = []
    if settings.plotter_instance:
        if add:
            actors = settings.plotter_instance.actors
        elif at == 0:  # just remove scalarbars
            for sb in settings.plotter_instance.scalarbars:
                settings.plotter_instance.renderer.RemoveActor(sb)

    if mesh and ('mesh' in mode or 'color' in mode or 'displace' in mode):

        actor = MeshActor(u, mesh, exterior=exterior, fast=fast)

        actor.wireframe(wire)
        actor.scale(scaleMeshFactors)
        if lighting:
            actor.lighting(lighting)
        if ttime:
            actor.z(ttime)
        if legend:
            actor.legend(legend)
        if c:
            actor.color(c)
        if lc:
            actor.lineColor(lc)
        if alpha:
            alpha = min(alpha, 1)
            actor.alpha(alpha * alpha)
        if lw:
            actor.lineWidth(lw)
            if wire and alpha:
                lw1 = min(lw, 1)
                actor.alpha(alpha * lw1)
        if ps:
            actor.pointSize(ps)
        if shading:
            if shading == 'phong':
                actor.phong()
            elif shading == 'flat':
                actor.flat()
            elif shading[0] == 'g':
                actor.gouraud()

        if 'displace' in mode: actor.move(u)

        if cmap and (actor.u_values is not None) and c is None:
            if u.value_rank() > 0:  # will show the size of the vector
                actor.pointColors(utils.mag(actor.u_values),
                                  vmin=vmin,
                                  vmax=vmax,
                                  cmap=cmap)
            else:
                actor.pointColors(actor.u_values,
                                  vmin=vmin,
                                  vmax=vmax,
                                  cmap=cmap)

        if warpYfactor:
            scals = actor.getPointArray()
            if len(scals):
                pts_act = actor.points(copy=False)
                pts_act[:, 1] = scals * warpYfactor * scaleMeshFactors[1]
        if warpZfactor:
            scals = actor.getPointArray()
            if len(scals):
                pts_act = actor.points(copy=False)
                pts_act[:, 2] = scals * warpZfactor * scaleMeshFactors[2]
        if warpYfactor or warpZfactor:
            actor.points(pts_act)
            if vmin is not None and vmax is not None:
                actor._mapper.SetScalarRange(vmin, vmax)

        if scbar and c is None:
            if '3d' in scbar:
                actor.addScalarBar3D()
            elif 'h' in scbar:
                actor.addScalarBar(horizontal=True)
            else:
                actor.addScalarBar(horizontal=False)

        if len(isolns) > 0:
            ison = isolns.pop("n", 10)
            isocol = isolns.pop("c", 'black')
            isoalpha = isolns.pop("alpha", 1)
            isolw = isolns.pop("lw", 1)

            isos = actor.isolines(
                n=ison).color(isocol).lw(isolw).alpha(isoalpha)

            isoz = isolns.pop("z", None)
            if isoz is not None:  # kind of hack to make isolines visible on flat meshes
                d = isoz
            else:
                d = actor.diagonalSize() / 400
            isos.z(actor.z() + d)
            actors.append(isos)

        actors.append(actor)

    #################################################################
    if 'streamline' in mode:
        mode = mode.replace('streamline', '')
        str_act = MeshStreamLines(u, **streamlines)
        actors.append(str_act)

    #################################################################
    if 'arrow' in mode or 'line' in mode:
        if 'arrow' in mode:
            arrs = MeshArrows(u, scale=scale)
        else:
            arrs = MeshLines(u, scale=scale)

        if arrs:
            if legend and 'mesh' not in mode:
                arrs.legend(legend)
            if c:
                arrs.color(c)
                arrs.color(c)
            if alpha:
                arrs.alpha(alpha)
            actors.append(arrs)

    #################################################################
    if 'tensor' in mode:
        pass  #todo

    #################################################################
    for ob in inputobj:
        inputtype = str(type(ob))
        if 'vedo' in inputtype:
            actors.append(ob)

    if text:
        textact = Text2D(text, font=font)
        actors.append(textact)

    if 'at' in options.keys() and 'interactive' not in options.keys():
        if settings.plotter_instance:
            N = settings.plotter_instance.shape[
                0] * settings.plotter_instance.shape[1]
            if options['at'] == N - 1:
                options['interactive'] = True

    if settings.plotter_instance:
        for a2 in settings.collectable_actors:
            if isinstance(a2, vtk.vtkCornerAnnotation):
                if 0 in a2.renderedAt:  # remove old message
                    settings.plotter_instance.remove(a2)
                    break

    if len(actors) == 0:
        print('Warning: no objects to show, check mode in plot(mode="...")')

    if returnActorsNoShow:
        return actors

    return show(actors, **options)
Exemplo n.º 6
0
    def __init__(self, volume,
                 qtWidget,
                 alpha=1,
                 cmaps=('gist_ncar_r', "hot_r", "bone_r", "jet", "Spectral_r"),
                 map2cells=False,  # buggy
                 clamp=True,
                 useSlider3D=False,
                 size=(850,700),
                 screensize="auto",
                 title="",
                 bg="white",
                 bg2="lightblue",
                 axes=1,
                 draggable=False,
                 verbose=True):

        super().__init__(qtWidget=qtWidget, bg=bg, bg2=bg2,
                         size=size,
                         screensize=screensize,
                         title=title,
                         interactive=False,
                         offscreen=True,
                         verbose=verbose)
        ################################
        self.volume = volume
        self.volume_copy = volume.clone()
        self.cmap_slicer = cmaps[0]
        self.alpha = alpha
        self.alphas = [1 for i in range(100)]
        self.showing_mesh = False
        self.map2cells = map2cells

        dims = volume.dimensions()
        self.rmin, self.rmax = volume.imagedata().GetScalarRange()

        self.pos_slider = [dims[0], dims[1], int(volume.dimensions()[2]/2)]


        self.volume.mode(1).color(self.cmap_slicer).jittering(True)
        self.setOTF()

        self.box = volume.box().wireframe().alpha(0)
        self.add(self.box, render=False)

        # inits
        la, ld = 0.7, 0.3 #ambient, diffuse
        data = volume.getPointArray()

        if clamp:
            hdata, edg = np.histogram(data, bins=50)
            logdata = np.log(hdata+1)
            # mean  of the logscale plot
            meanlog = np.sum(np.multiply(edg[:-1], logdata))/np.sum(logdata)
            self.rmax = min(self.rmax, meanlog+(meanlog-self.rmin)*0.9)
            self.rmin = max(self.rmin, meanlog-(self.rmax-meanlog)*0.9)
            if verbose:
                printc('scalar range clamped to: (' +
                       precision(self.rmin, 3) +', '+  precision(self.rmax, 3)+')', c='m', bold=0)

        self.visibles = [None, None, None]
        self.all_slices = [[], [], []]
        self.scalar_msh = volume.zSlice(self.pos_slider[2])
        self.scalar_msh.alpha(self.alpha).lighting('', la, ld, 0)
        self.scalar_msh.pointColors(cmap=self.cmap_slicer, vmin=self.rmin, vmax=self.rmax, alpha=self.alphas)
        self.scalar_msh.SetVisibility(False)
        self.scalar_msh.scalarbar = addScalarBar(self.scalar_msh, pos=(0.04,0.0), horizontal=True, titleFontSize=0)

        self.add(self.scalar_msh)

        self.msh = self.scalar_msh.clone()
        if map2cells: self.msh.mapPointsToCells()
        self.renderer.AddActor(self.msh)
        self.visibles[2] = self.msh

        def sliderfunc_x(widget, event):
            """
            Event on change slider x
            """
            i = int(widget.GetRepresentation().GetValue())
            self.pos_slider[0] = i
            self.msh = self.volume.xSlice(i).alpha(self.alpha).lighting('', la, ld, 0)
            self.msh.pointColors(cmap=self.cmap_slicer, vmin=self.rmin, vmax=self.rmax, alpha=self.alphas)
            if map2cells: self.msh.mapPointsToCells()
            self.renderer.RemoveActor(self.visibles[0])
            if i<dims[0]: self.renderer.AddActor(self.msh)
            self.visibles[0] = self.msh

        def sliderfunc_y(widget, event):
            """
            Event on change slider y
            """
            i = int(widget.GetRepresentation().GetValue())
            self.pos_slider[1] = i
            self.msh = self.volume.ySlice(i).alpha(self.alpha).lighting('', la, ld, 0)
            self.msh.pointColors(cmap=self.cmap_slicer, vmin=self.rmin, vmax=self.rmax, alpha=self.alphas)
            if map2cells: self.msh.mapPointsToCells()
            self.renderer.RemoveActor(self.visibles[1])
            if i<dims[1]: self.renderer.AddActor(self.msh)
            self.visibles[1] = self.msh

        def sliderfunc_z(widget, event):
            """
            Event on change slider z
            """
            i = int(widget.GetRepresentation().GetValue())
            self.pos_slider[2] = i
            self.comment.SetText(4, "z="+str(self.pos_slider[2]))
            self.msh = self.volume.zSlice(i).alpha(self.alpha).lighting('', la, ld, 0)
            self.msh.pointColors(cmap=self.cmap_slicer, vmin=self.rmin, vmax=self.rmax, alpha=self.alphas)
            if map2cells: self.msh.mapPointsToCells()
            self.renderer.RemoveActor(self.visibles[2])
            if i<dims[2]: self.renderer.AddActor(self.msh)
            self.visibles[2] = self.msh

        cx, cy, cz, ch = 'dr', 'dg', 'db', (0.3,0.3,0.3)
        if np.sum(self.renderer.GetBackground()) < 1.5:
            cx, cy, cz = 'lr', 'lg', 'lb'
            ch = (0.8,0.8,0.8)

        self.addSlider2D(sliderfunc_x, 0, dims[0]+1, title='X', titleSize=0.5,
                         value=self.pos_slider[0],

                         pos=[(0.8,0.12), (0.95,0.12)], showValue=False, c=cx)
        self.addSlider2D(sliderfunc_y, 0, dims[1]+1, title='Y', titleSize=0.5,
                         value=self.pos_slider[1],
                         pos=[(0.8,0.08), (0.95,0.08)], showValue=False, c=cy)
        self.addSlider2D(sliderfunc_z, 0, dims[2]+1, title='Z', titleSize=0.6,
                         value=self.pos_slider[2],
                         pos=[(0.8,0.04), (0.95,0.04)], showValue=False, c=cz)
        self.scalar_thresh = self.addSlider2D(self.sliderThreshold, 0, 100, value=100, pos=[(0.04, 0.1), (0.2, 0.1)], showValue=True, title="Scalar")

        self.opacity_thresh = self.addSlider2D(self.sliderOpacityThreshold, 0, 100, value=0, pos=[(0.04, 0.2), (0.2, 0.2)], showValue=True, title="Opacity")



        #################
        def keyfunc(iren, event):
            """
            Keyboard events on the viewer
            s : save image
            x : display all slice on x axis
            y : display all slice on y axis
            z : display all slice on z axis
            v : display volume rendering
            """
            if not iren.GetKeyCode():
                return
            key = iren.GetKeySym()
            if key=='s':
                array = self.volume.getDataArray()
                index = self.pos_slider[2]
                if index < array.shape[2]:
                    image = self.volume.getDataArray()[..., index].T
                    fig, ax = plt.subplots(1,1)
                    ax.axis("off")
                    ax.imshow(image, cmap="gray")
                    plt.savefig("saved_fig.png", bbox_inches="tight", pad_inches=0)
            if key=='x':
                self.display_all_slices(0)
            if key=='y':
                self.display_all_slices(1)
            if key=='z':
                self.display_all_slices(2)
            if key=='v':
                self.showing_mesh = not self.showing_mesh
                if self.volume.GetBounds()[-1] == 0:
                    return
                if self.showing_mesh:
                    self.add(self.volume)
                    self.interactive = True
                else:
                    self.remove(self.volume)


        def buttonfunc(iren, event):
            """
            Mouse event
            Allows to change color map
            """
            clickPos = iren.GetEventPosition()

            picker = vtk.vtkPropPicker()
            picker.Pick(clickPos[0], clickPos[1], 0, self.renderer)
            if not picker.GetActor2D():
                return
            bu.switch()
            self.cmap_slicer = bu.status()
            self.refresh()
            # self.add(self.scalar_msh)


        bu = self.addButton(buttonfunc,
            pos=(0.27, 0.005),
            states=cmaps,
            c=["db"]*len(cmaps),
            bc=["lb"]*len(cmaps),  # colors of states
            size=14,
            bold=True,
        )
        self.interactor.AddObserver("KeyPressEvent", keyfunc)

        self.interactor.AddObserver("LeftButtonPressEvent", buttonfunc)

        #################

        self.comment = Text2D("z="+str(self.pos_slider[2]),pos=5,
                              font='Montserrat', s=0.6)
        self.add([self.msh, self.comment])
        if verbose:
            printc("Press button to cycle through color maps,", c="m")
            printc("Use sliders to select the slicing planes.", c="m")