예제 #1
0
    def _init_figure(self, x, y, z, triangles, figsize, figlims):
        """
        Initialize the figure by plotting the surface without any overlay.

        x: x coordinates of vertices (V x 1 numpy array)
        y: y coordinates of vertices (V x 1 numpy array)
        z: z coordinates of vertices (V x 1 numpy array)
        triangles: triangle specifications (T x 3 numpy array, where
        T=#triangles)
        figsize: 2x1 list of integers
        figlims: 3x2 list of integers
        """
        self.fig = p3.figure(width=figsize[0], height=figsize[1])
        self.fig.camera_fov = 1
        self.fig.style = {
            "axes": {
                "color": "black",
                "label": {"color": "black"},
                "ticklabel": {"color": "black"},
                "visible": False,
            },
            "background-color": "white",
            "box": {"visible": False},
        }
        self.fig.xlim = (figlims[0][0], figlims[0][1])
        self.fig.ylim = (figlims[1][0], figlims[1][1])
        self.fig.zlim = (figlims[2][0], figlims[2][1])

        # draw the tetrahedron
        p3.plot_trisurf(
            x, y, z, triangles=triangles, color=np.ones((len(x), 3))
        )
예제 #2
0
    def plot_group_brain_activation(self, radius=12.5, freq_range=(40, 200), clim=None, cmap='RdBu_r'):
        """
        Plots brain surface based on the mean activity across the group. Uses ipyvolume to plot

        Parameters
        ----------
        radius: float
            Maximum distance between an electrode and a vertex to be counted as data for that vertex
        freq_range: list
            2 element list defining minimum and maximum frequncies to average.
        clim: float
            Maximum/minumum value of the colormap. Will be centered at zero. If not given, will use the maximum absolute
            value of the data.
        cmap: str
            matplotlib colormap to use

        Returns
        -------
        left hemisphere and right hemisphere activation maps
        """

        # load brain mesh
        l_coords, l_faces, r_coords, r_faces = self.load_brain_mesh()

        # compute mean activation
        l_vert_mean, r_vert_mean = self.compute_surface_map(radius, freq_range)

        # define colormap range
        if clim is None:
            clim = np.max([np.nanmax(np.abs(l_vert_mean)), np.nanmax(np.abs(r_vert_mean))])
        c_norm = plt.Normalize(vmin=-clim, vmax=clim)
        c_mappable = cmx.ScalarMappable(norm=c_norm, cmap=plt.get_cmap(cmap))

        # compute surface colors for left
        valid_l_inds = ~np.isnan(l_vert_mean)
        l_colors = np.full((l_vert_mean.shape[0], 4), 0.)
        l_colors[valid_l_inds] = c_mappable.to_rgba(l_vert_mean[valid_l_inds])

        # and right
        valid_r_inds = ~np.isnan(r_vert_mean)
        r_colors = np.full((r_vert_mean.shape[0], 4), 0.)
        r_colors[valid_r_inds] = c_mappable.to_rgba(r_vert_mean[valid_r_inds])

        # plot it!
        fig = p3.figure(width=800, height=800, lighting=True)
        brain_l = p3.plot_trisurf(l_coords[:, 0], l_coords[:, 1], l_coords[:, 2], triangles=l_faces, color=l_colors)
        brain_r = p3.plot_trisurf(r_coords[:, 0], r_coords[:, 1], r_coords[:, 2], triangles=r_faces, color=r_colors)

        # turn off axis and make square
        ipv.squarelim()
        ipv.style.box_off()
        ipv.style.axes_off()
        p3.show()

        return fig
예제 #3
0
    def plot(self,
             plot_mesh=True,
             plot_voxels=True,
             width=800,
             height=600,
             voxel_count_offset=0,
             voxel_limit=None,
             use_centroids_instead=False,
             scaling=1,
             mesh_color='red',
             **kwargs):
        """
        This method needs better documentation.

        :param **kwargs: Is used in ipyvolume.pylab.scatter() or ipyvolume.pylab.plot() depending on whether use_centroids_instead
        is set to true or not.
        """
        if plot_mesh:
            if self.triangles is None:
                raise ValueError(
                    "There is no triangle data stored for this mesh!")
            else:
                fig = p3.figure(width=width, height=height)
                p3.plot_trisurf(*self.vertices.T * scaling,
                                self.triangles,
                                color=mesh_color)
                if plot_voxels:
                    self.voxels.plot(
                        width=width,
                        height=height,
                        voxel_count_offset=voxel_count_offset,
                        voxel_limit=voxel_limit,
                        use_centroids_instead=use_centroids_instead,
                        ipyvol_fig=fig,
                        scaling=scaling,
                        **kwargs)
                else:
                    p3.squarelim()
                    p3.show()
        elif plot_voxels:
            try:
                fig = p3.figure(width=width, height=height)
                self.voxels.plot(width=width,
                                 height=height,
                                 voxel_count_offset=voxel_count_offset,
                                 voxel_limit=voxel_limit,
                                 use_centroids_instead=use_centroids_instead,
                                 ipyvol_fig=fig,
                                 scaling=scaling,
                                 **kwargs)
            except AttributeError:
                raise AttributeError(
                    "This object does not have a Voxels object, you must initialize the voxel mesh with a Voxels object or run voxelize() to generate new voxels."
                )
예제 #4
0
def _create_mesh(points,
                 color="black",
                 solid=False,
                 lines=True,
                 triangle_indices=None,
                 line_indices=None):
    """ create an ipyvolume mesh from a number of points

    Parameters
    ----------
    points: list
        [[x, y, z], ...]
    color: str
    solid: bool
    triangle_indices: list or None
        [[i, j, k], ...], if None then computed from scipy.spatial.qhull.ConvexHull triangles
    line_indices: list or None
        [[i, j], ...], if None then computed from scipy.spatial.qhull.ConvexHull triangles

    Returns
    -------

    """
    x, y, z = np.array(points).T
    try:
        hull = ConvexHull(points)
    except:
        hull = ConvexHull(points, qhull_options='QJ')
    if triangle_indices is None:
        triangle_indices = hull.simplices.tolist()
    if line_indices is None:
        line_indices = []
        for i, j, k in hull.simplices.tolist():
            line_indices += [[i, j], [i, k], [j, k]]

    mesh = p3.plot_trisurf(x,
                           y,
                           z,
                           triangles=triangle_indices,
                           lines=line_indices,
                           color=color)
    if not solid:
        mesh.visible_faces = False
    if not lines:
        mesh.visible_lines = False
    return mesh
예제 #5
0
def showSurface(surface,overlay=None,frame=0,newfigure=True,colormap='summer',figsize=np.array([300,400]),
                figlims=np.array([[-75,75],[-75,75],[-75,75]])):
    '''
    Displays a surface mesh in gifti or FreeSurfer (FS) surface format with/without an overlay inside
    Jupyter notebook for interactive visualization.

    Parameters
    ----------
    surface: str, gifti opject
        Path to surface file in gifti or FS surface format or an already loaded gifti object of surface
    overlay: str, gifti opject
        Path to overlay file in gifti or FS annot or anaotimcal (.curv,.sulc,.thickness) format or an already loaded
        gifti object of overlay, default None
    frame: int
        indice of the frame (timepoint or functional data frame) to show
    newfigure: bool
        Create a new figure else prints into the last figure (in order to visualize both hemispheres in
        one plot), default True
    colormap: string
        A matplotlib colormap, default summer
    figsize: ndarray
        Size of the figure to display, default [600,600]
    figLims: ndarray
        x,y and z limits of the axes, default [[-100,100],[-100,100],[-100,100]])

    '''

    if isinstance(surface,str):
        if not os.path.exists(surface):
            error('File does not exist, please provide a valid file path to a gifti or FreeSurfer file.')
        filename, file_extension = os.path.splitext(surface)
        if file_extension is '.gii':
            surface = nb.load(surface)
        else:
            fsgeometry = nb.freesurfer.read_geometry(surface)
            x,y,z = fsgeometry[0].T
            vertex_edges=fsgeometry[1]

    if isinstance(surface,nb.gifti.gifti.GiftiImage):
        try:
            vertex_spatial=surface.darrays[0]
            vertex_edges=surface.darrays[1]
            x, y, z = vertex_spatial.data.T
        except:
            raise ValueError('Please provide a valid gifti file.')

    if not isinstance(frame,int):
        ValueError('Please provide a valid integer frame index.')

    if isinstance(overlay,list):
        if frame>len(overlay) or frame < 0:
            error('Frame index out of bounds, please provide a valid frame index.')
        overlay = overlay[frame]

    if isinstance(overlay,str):
        if not os.path.exists(overlay):
            error('File does not exist, please provide a valid file path to a gifti or FreeSurfer file.')
        filename, file_extension = os.path.splitext(overlay)

        if file_extension is '.gii':
            overlay = nb.load(overlay)
        elif (file_extension in ('.annot','')):
            annot = nb.freesurfer.read_annot(overlay)
            activation = annot[0]
        elif (file_extension in ('.curv','.thickness','.sulc')):
            activation = nb.freesurfer.read_morph_data(overlay)

    if isinstance(overlay,nb.gifti.gifti.GiftiImage):
        try:
            activation=overlay.darrays[0].data
        except:
            raise ValueError('Please provide a valid gifti file')


    if newfigure:

        fig = p3.figure(width=figsize[0], height=figsize[1])
        fig.camera_fov = 1
        fig.style = {'axes': {'color': 'black',
          'label': {'color': 'black'},
          'ticklabel': {'color': 'black'},
          'visible': False},
         'background-color': 'white',
         'box': {'visible': False}}
        fig.xlim = (figlims[0][0], figlims[0][1])
        fig.ylim = (figlims[1][0], figlims[1][1])
        fig.zlim = (figlims[2][0], figlims[2][1])


    # plot surface
    if overlay is None:
        p3.plot_trisurf(x, y, z, triangles=vertex_edges.data)
    else:
        my_color = plt.cm.get_cmap(colormap)
        colors=my_color((activation-min(activation))/(max(activation)-min(activation)))
        p3.plot_trisurf(x, y, z, triangles=vertex_edges.data, color=colors[:,:3])

    if newfigure:
        p3.show()
예제 #6
0
    def plot_group_brain_activation(self, radius=12.5, freq_range=(40, 200), clim=None, cmap='RdBu_r', n_perms=100,
                                    min_n=5, res_key='t-stat'):
        """
        Plots brain surface based on the mean activity across the group. Uses ipyvolume to plot

        Parameters
        ----------
        radius: float
            Maximum distance between an electrode and a vertex to be counted as data for that vertex
        freq_range: list
            2 element list defining minimum and maximum frequncies to average.
        clim: float
            Maximum/minumum value of the colormap. Will be centered at zero. If not given, will use the maximum absolute
            value of the data.
        cmap: str
            matplotlib colormap to use
        n_perms: int
            Number of permutations to do when computing our t-statistic significance thresholds
        min_n: int
            Vertices with less than this number of subjects will be plotted in gray, regardless of the significance val
        res_key: str
            Column name of dataframe to use as the metric

        Returns
        -------
        left hemisphere and right hemisphere activation maps
        """

        # load brain mesh
        l_coords, l_faces, r_coords, r_faces = self.load_brain_mesh()

        # compute mean activation. First get vertex x subject arrays
        l_vert_vals, r_vert_vals = self.compute_surface_map(radius, freq_range, res_key)

        # we will actually be plotting t-statistics, so compute those
        l_ts, l_ps = ttest_1samp(l_vert_vals, 0, axis=1, nan_policy='omit')
        r_ts, r_ps = ttest_1samp(r_vert_vals, 0, axis=1, nan_policy='omit')

        # not let's compute our significance thresholds via non-parametric permutation procedure
        sig_thresh = self.compute_permute_dist_par(l_vert_vals, r_vert_vals, n_perms=n_perms)

        # define colormap range
        if clim is None:
            clim = np.max([np.nanmax(np.abs(l_ts)), np.nanmax(np.abs(r_ts))])
        c_norm = plt.Normalize(vmin=-clim, vmax=clim)
        c_mappable = cmx.ScalarMappable(norm=c_norm, cmap=plt.get_cmap(cmap))

        # compute surface colors for left
        valid_l_inds = ~np.isnan(l_ts) & (np.sum(np.isnan(l_vert_vals), axis=1) >= min_n)
        l_colors = np.full((l_ts.shape[0], 4), 0.)
        l_colors[valid_l_inds] = c_mappable.to_rgba(l_ts[valid_l_inds])

        # and right
        valid_r_inds = ~np.isnan(r_ts) & (np.sum(np.isnan(r_vert_vals), axis=1) >= min_n)
        r_colors = np.full((r_ts.shape[0], 4), 0.)
        r_colors[valid_r_inds] = c_mappable.to_rgba(r_ts[valid_r_inds])

        # lastly, mask out vertices that do not meet our significance thresh
        sig_l = (l_ts < sig_thresh[0]) | (l_ts > sig_thresh[1])
        sig_r = (r_ts < sig_thresh[0]) | (r_ts > sig_thresh[1])
        l_colors[~sig_l] = [.7, .7, .7, 0.]
        r_colors[~sig_r] = [.7, .7, .7, 0.]

        # plot it!
        fig = p3.figure(width=800, height=800, lighting=True)
        brain_l = p3.plot_trisurf(l_coords[:, 0], l_coords[:, 1], l_coords[:, 2], triangles=l_faces, color=l_colors)
        brain_r = p3.plot_trisurf(r_coords[:, 0], r_coords[:, 1], r_coords[:, 2], triangles=r_faces, color=r_colors)

        # turn off axis and make square
        ipv.squarelim()
        ipv.style.box_off()
        ipv.style.axes_off()
        p3.show()

        return fig
예제 #7
0
    def plot_group_brain_activation(self, radius=12.5, freq_range=(40, 200), clim=None, cmap='RdBu_r', n_perms=100,
                                    min_n=5):
        """
        Plots brain surface based on the mean activity across the group. Uses ipyvolume to plot

        Parameters
        ----------
        radius: float
            Maximum distance between an electrode and a vertex to be counted as data for that vertex
        freq_range: list
            2 element list defining minimum and maximum frequncies to average.
        clim: float
            Maximum/minumum value of the colormap. Will be centered at zero. If not given, will use the maximum absolute
            value of the data.
        cmap: str
            matplotlib colormap to use
        n_perms: int
            Number of permutations to do when computing our t-statistic significance thresholds
        min_n: int
            Vertices with less than this number of subjects will be plotted in gray, regardless of the significance val

        Returns
        -------
        left hemisphere and right hemisphere activation maps
        """

        # load brain mesh
        l_coords, l_faces, r_coords, r_faces = self.load_brain_mesh()

        # compute mean activation. First get vertex x subject arrays
        l_vert_vals, r_vert_vals = self.compute_surface_map(radius, freq_range)

        # we will actually be plotting t-statistics, so compute those
        l_ts, l_ps = ttest_1samp(l_vert_vals, 0, axis=1, nan_policy='omit')
        r_ts, r_ps = ttest_1samp(r_vert_vals, 0, axis=1, nan_policy='omit')

        # not let's compute our significance thresholds via non-parametric permutation procedure
        sig_thresh = self.compute_permute_dist_par(l_vert_vals, r_vert_vals, n_perms=n_perms)

        # define colormap range
        if clim is None:
            clim = np.max([np.nanmax(np.abs(l_ts)), np.nanmax(np.abs(r_ts))])
        c_norm = plt.Normalize(vmin=-clim, vmax=clim)
        c_mappable = cmx.ScalarMappable(norm=c_norm, cmap=plt.get_cmap(cmap))

        # compute surface colors for left
        valid_l_inds = ~np.isnan(l_ts) & (np.sum(np.isnan(l_vert_vals), axis=1) >= min_n)
        l_colors = np.full((l_ts.shape[0], 4), 0.)
        l_colors[valid_l_inds] = c_mappable.to_rgba(l_ts[valid_l_inds])

        # and right
        valid_r_inds = ~np.isnan(r_ts) & (np.sum(np.isnan(r_vert_vals), axis=1) >= min_n)
        r_colors = np.full((r_ts.shape[0], 4), 0.)
        r_colors[valid_r_inds] = c_mappable.to_rgba(r_ts[valid_r_inds])

        # lastly, mask out vertices that do not meet our significance thresh
        sig_l = (l_ts < sig_thresh[0]) | (l_ts > sig_thresh[1])
        sig_r = (r_ts < sig_thresh[0]) | (r_ts > sig_thresh[1])
        l_colors[~sig_l] = [.7, .7, .7, 0.]
        r_colors[~sig_r] = [.7, .7, .7, 0.]

        # plot it!
        fig = p3.figure(width=800, height=800, lighting=True)
        brain_l = p3.plot_trisurf(l_coords[:, 0], l_coords[:, 1], l_coords[:, 2], triangles=l_faces, color=l_colors)
        brain_r = p3.plot_trisurf(r_coords[:, 0], r_coords[:, 1], r_coords[:, 2], triangles=r_faces, color=r_colors)

        # turn off axis and make square
        ipv.squarelim()
        ipv.style.box_off()
        ipv.style.axes_off()
        p3.show()

        return fig
예제 #8
0
def fermi3D(procar,
            outcar,
            bands=-1,
            scale=1,
            mode="plain",
            st=False,
            **kwargs):
    """
    This function plots 3d fermi surface
    list of acceptable kwargs :
        plotting_package
        nprocess
        face_colors
        arrow_colors 
        arrow_spin
        atom
        orbital
        spin
        
    """
    welcome()

    # Initilizing the arguments :

    if "plotting_package" in kwargs:
        plotting_package = kwargs["plotting_package"]
    else:
        plotting_package = "mayavi"

    if "nprocess" in kwargs:
        nprocess = kwargs["nprocess"]
    else:
        nprocess = 2

    if "face_colors" in kwargs:
        face_colors = kwargs["face_colors"]
    else:
        face_colors = None
    if "cmap" in kwargs:
        cmap = kwargs["cmap"]
    else:
        cmap = "jet"
    if "atoms" in kwargs:
        atoms = kwargs["atoms"]
    else:
        atoms = [-1]  # project all atoms
    if "orbitals" in kwargs:
        orbitals = kwargs["orbitals"]
    else:
        orbitals = [-1]

    if "spin" in kwargs:
        spin = kwargs["spin"]
    else:
        spin = [0]
    if "mask_points" in kwargs:
        mask_points = kwargs["mask_points"]
    else:
        mask_points = 1
    if "energy" in kwargs:
        energy = kwargs["energy"]
    else:
        energy = 0
    if "transparent" in kwargs:
        transparent = kwargs["transparent"]
    else:
        transparent = False

    if "arrow_projection" in kwargs:
        arrow_projection = kwargs["arrow_projection"]
    else:
        arrow_projection = 2

    if plotting_package == "mayavi":
        try:
            from mayavi import mlab
            from tvtk.api import tvtk
        except:
            print(
                "You have selected mayavi as plottin package. please install mayavi or choose a different package"
            )
            return
    elif plotting_package == "plotly":
        try:
            import plotly.plotly as py
            import plotly.figure_factory as ff
            import plotly.graph_objs as go

            cmap = mpl.cm.get_cmap(cmap)
            figs = []

        except:
            print(
                "You have selected plotly as plottin package. please install plotly or choose a different package"
            )
            return
    elif plotting_package == "matplotlib":
        try:
            import matplotlib.pylab as plt
            from mpl_toolkits.mplot3d.art3d import Poly3DCollection
        except:
            print(
                "You have selected matplotlib as plotting package. please install matplotlib or choose a different package"
            )
            return
    elif plotting_package == "ipyvolume":
        try:
            import ipyvolume.pylab as ipv
        except:
            print(
                "You have selected ipyvolume as plotting package. please install ipyvolume or choose a different package"
            )
            return
    permissive = False

    # get fermi from outcar
    outcarparser = UtilsProcar()
    e_fermi = outcarparser.FermiOutcar(outcar)
    print("Fermi=", e_fermi)
    e_fermi += energy
    # get reciprocal lattice from outcar
    recLat = outcarparser.RecLatOutcar(outcar)

    # parsing the Procar file
    procarFile = ProcarParser()
    procarFile.readFile(procar, permissive)

    poly = get_wigner_seitz(recLat)
    # plot brilliouin zone
    if plotting_package == "mayavi":
        brillouin_point = []
        brillouin_faces = []
        point_count = 0
        for iface in poly:
            single_face = []
            for ipoint in iface:
                single_face.append(point_count)
                brillouin_point.append(list(ipoint))
                point_count += 1
            brillouin_faces.append(single_face)
        polydata_br = tvtk.PolyData(points=brillouin_point,
                                    polys=brillouin_faces)
        mlab.pipeline.surface(
            polydata_br,
            representation="wireframe",
            color=(0, 0, 0),
            line_width=4,
            name="BRZ",
        )
    elif plotting_package == "plotly":

        for iface in poly:
            iface = np.pad(iface, ((0, 1), (0, 0)), "wrap")
            x, y, z = iface[:, 0], iface[:, 1], iface[:, 2]
            plane = go.Scatter3d(x=x,
                                 y=y,
                                 z=z,
                                 mode="lines",
                                 line=dict(color="black", width=4))
            figs.append(plane)

    elif plotting_package == "matplotlib":
        fig = plt.figure()
        ax = fig.add_subplot(111, projection="3d")
        brillouin_zone = Poly3DCollection(poly,
                                          facecolors=["None"] * len(poly),
                                          alpha=1,
                                          linewidth=4)
        brillouin_zone.set_edgecolor("k")
        ax.add_collection3d(brillouin_zone, zs=0, zdir="z")

    br_points = []
    for iface in poly:
        for ipoint in iface:
            br_points.append(ipoint)
    br_points = np.unique(br_points, axis=0)
    print("Number of bands: %d" % procarFile.bandsCount)
    print("Number of koints %d" % procarFile.kpointsCount)
    print("Number of ions: %d" % procarFile.ionsCount)
    print("Number of orbitals: %d" % procarFile.orbitalCount)
    print("Number of spins: %d" % procarFile.ispin)

    # selecting the data
    data = ProcarSelect(procarFile, deepCopy=True)
    if bands == -1:
        bands = range(data.bands.shape[1])

    kvector = data.kpoints
    kmax = np.max(kvector)
    kmin = np.min(kvector)

    if abs(kmax) != abs(kmin):
        print("The mesh provided is gamma center, symmetrizing data")
        print("For a better fermi surface, use a non-gamma centered k-mesh")
        data = symmetrize(data)
        kvector = data.kpoints

    kvector_red = data.kpoints.copy()
    kvector_cart = np.dot(kvector_red, recLat)

    # This section finds points that are outside of the 1st BZ and and creates those points in the 1st BZ
    kvector_cart, kvector_red, has_points_out = bring_pnts_to_BZ(
        recLat, kvector_cart, kvector_red, br_points)
    #    has_points_out = False

    # getting the mesh grid in each dirrection
    kx_red = np.unique(kvector_red[:, 0])
    ky_red = np.unique(kvector_red[:, 1])
    kz_red = np.unique(kvector_red[:, 2])

    # getting the lengths between kpoints in each direction
    klength_x = np.abs(kx_red[-1] - kx_red[-2])
    klength_y = np.abs(ky_red[-1] - ky_red[-2])
    klength_z = np.abs(kz_red[-1] - kz_red[-2])
    klengths = [klength_x, klength_y, klength_z]

    # getting number of kpoints in each direction with the addition of kpoints needed to sample the 1st BZ fully (in reduced)
    nkx_red = kx_red.shape[0]
    nky_red = ky_red.shape[0]
    nkz_red = kz_red.shape[0]

    # getting numner of kpoints in each direction provided by vasp
    nkx_orig = np.unique(kvector[:, 0]).shape[0]
    nky_orig = np.unique(kvector[:, 1]).shape[0]
    nkz_orig = np.unique(kvector[:, 2]).shape[0]

    # Amount of kpoints needed to add on to fully sample 1st BZ
    padding_x = (nkx_red - nkx_orig) // 2
    padding_y = (nky_red - nky_orig) // 2
    padding_z = (nkz_red - nkz_orig) // 2

    if mode == "parametric":
        data.selectIspin(spin)
        data.selectAtoms(atoms, fortran=False)
        data.selectOrbital(orbitals)
    elif mode == "external":
        if "color_file" in kwargs:
            rf = open(kwargs["color_file"])

            lines = rf.readlines()
            counter = 0
            color_kvector = []
            color_eigen = []
            for iline in lines:
                if counter < 2:
                    if "band" in iline:
                        counter += 1
                        continue
                    temp = [float(x) for x in iline.split()]
                    color_kvector.append([temp[0], temp[1], temp[2]])
            counter = -1
            for iline in lines:
                if "band" in iline:
                    counter += 1
                    iband = int(iline.split()[-1])
                    color_eigen.append([])
                    continue
                color_eigen[counter].append(float(iline.split()[-1]))
            rf.close()

            color_kvector = np.array(color_kvector)
            color_kvector_red = color_kvector.copy()
            color_kvector_cart = np.dot(color_kvector, recLat)
            if has_points_out:

                color_kvector_cart, color_kvector_red, temp = bring_pnts_to_BZ(
                    recLat, color_kvector_cart, color_kvector_red, br_points)
        else:
            print(
                "mode selected was external, but no color_file name was provided"
            )
            return
    if st:

        dataX = ProcarSelect(procarFile, deepCopy=True)
        dataY = ProcarSelect(procarFile, deepCopy=True)
        dataZ = ProcarSelect(procarFile, deepCopy=True)

        dataX.kpoints = data.kpoints
        dataY.kpoints = data.kpoints
        dataZ.kpoints = data.kpoints

        dataX.spd = data.spd
        dataY.spd = data.spd
        dataZ.spd = data.spd

        dataX.bands = data.bands
        dataY.bands = data.bands
        dataZ.bands = data.bands

        dataX.selectIspin([1])
        dataY.selectIspin([2])
        dataZ.selectIspin([3])

        dataX.selectAtoms(atoms, fortran=False)
        dataY.selectAtoms(atoms, fortran=False)
        dataZ.selectAtoms(atoms, fortran=False)

        dataX.selectOrbital(orbitals)
        dataY.selectOrbital(orbitals)
        dataZ.selectOrbital(orbitals)
    ic = 0
    for iband in bands:

        print("Plotting band %d" % iband)

        eigen = data.bands[:, iband]

        # mapping the eigen values on the mesh grid to a matrix
        mapped_func, kpoint_matrix = mapping_func(kvector, eigen)

        # adding the points from the 2nd BZ to 1st BZ to fully sample the BZ. Check np.pad("wrap") for more information
        mapped_func = np.pad(
            mapped_func,
            ((padding_x, padding_x), (padding_y, padding_y),
             (padding_z, padding_z)),
            "wrap",
        )

        # Fourier interpolate the mapped function E(x,y,z)
        surf_equation = fft_interpolate(mapped_func, scale)

        # after the FFT we loose the center of the BZ, using numpy roll we bring back the center of the BZ
        surf_equation = np.roll(surf_equation, (scale) // 2, axis=[0, 1, 2])

        try:
            # creating the isosurface if possible
            verts, faces, normals, values = measure.marching_cubes_lewiner(
                surf_equation, e_fermi)

        except:

            print("No isosurface for this band")
            continue
        # the vertices provided are scaled and shifted to start from zero
        # we center them to zero, and rescale them to fit the real BZ by multiplying by the klength in each direction
        for ix in range(3):
            verts[:, ix] -= verts[:, ix].min()
            verts[:, ix] -= (verts[:, ix].max() - verts[:, ix].min()) / 2
            verts[:, ix] *= klengths[ix] / scale

        # the vertices need to be transformed to reciprocal spcae from recuded space, to find the points that are
        # in 2nd BZ, to be removed
        verts = np.dot(verts, recLat)

        # identifying the points in 2nd BZ and removing them
        if has_points_out:
            args = []
            for ivert in range(len(verts)):
                args.append([br_points, verts[ivert]])

            p = Pool(nprocess)
            results = np.array(p.map(is_outside, args))
            p.close()
            out_verts = np.arange(0, len(results))[results]
            new_faces = []
            #            outs_bool_mat = np.zeros(shape=faces.shape,dtype=np.bool)

            for iface in faces:
                remove = False
                for ivert in iface:
                    if ivert in out_verts:
                        remove = True

                        continue

                if not remove:
                    new_faces.append(iface)
            faces = np.array(new_faces)

        print("done removing")
        # At this point we have the plain Fermi surface, we can color the surface depending on the projection
        # We create the center of faces by averaging coordinates of corners

        if mode == "parametric":

            character = data.spd[:, iband]

            centers = np.zeros(shape=(len(faces), 3))
            for iface in range(len(faces)):
                centers[iface, 0:3] = np.average(verts[faces[iface]], axis=0)

            colors = interpolate.griddata(kvector_cart,
                                          character,
                                          centers,
                                          method="nearest")
        elif mode == "external":
            character = np.array(color_eigen[ic])
            ic += 1
            centers = np.zeros(shape=(len(faces), 3))
            for iface in range(len(faces)):
                centers[iface, 0:3] = np.average(verts[faces[iface]], axis=0)

            colors = interpolate.griddata(color_kvector_cart,
                                          character,
                                          centers,
                                          method="nearest")

        if st:
            projection_x = dataX.spd[:, iband]
            projection_y = dataY.spd[:, iband]
            projection_z = dataZ.spd[:, iband]

            verts_spin, faces_spin, normals, values = measure.marching_cubes_lewiner(
                mapped_func, e_fermi)

            for ix in range(3):
                verts_spin[:, ix] -= verts_spin[:, ix].min()
                verts_spin[:, ix] -= (verts_spin[:, ix].max() -
                                      verts_spin[:, ix].min()) / 2
                verts_spin[:, ix] *= klengths[ix]
            verts_spin = np.dot(verts_spin, recLat)

            if has_points_out:
                args = []
                for ivert in range(len(verts_spin)):
                    args.append([br_points, verts_spin[ivert]])

                p = Pool(nprocess)
                results = np.array(p.map(is_outside, args))
                p.close()
                out_verts = np.arange(0, len(results))[results]

                new_faces = []
                for iface in faces_spin:
                    remove = False
                    for ivert in iface:
                        if ivert in out_verts:
                            remove = True
                            continue
                    if not remove:
                        new_faces.append(iface)
                faces_spin = np.array(new_faces)

            centers = np.zeros(shape=(len(faces_spin), 3))
            for iface in range(len(faces_spin)):
                centers[iface, 0:3] = np.average(verts_spin[faces_spin[iface]],
                                                 axis=0)

            colors1 = interpolate.griddata(kvector_cart,
                                           projection_x,
                                           centers,
                                           method="linear")
            colors2 = interpolate.griddata(kvector_cart,
                                           projection_y,
                                           centers,
                                           method="linear")
            colors3 = interpolate.griddata(kvector_cart,
                                           projection_z,
                                           centers,
                                           method="linear")
            spin_arrows = np.vstack((colors1, colors2, colors3)).T

        if plotting_package == "mayavi":
            polydata = tvtk.PolyData(points=verts, polys=faces)

            if face_colors != None:
                mlab.pipeline.surface(
                    polydata,
                    representation="surface",
                    color=face_colors[ic],
                    opacity=1,
                    name="band-" + str(iband),
                )
                ic += 1
            else:
                if mode == "plain":
                    if not (transparent):
                        s = mlab.pipeline.surface(
                            polydata,
                            representation="surface",
                            color=(0, 0.5, 1),
                            opacity=1,
                            name="band-" + str(iband),
                        )

                elif mode == "parametric" or mode == "external":

                    polydata.cell_data.scalars = colors
                    polydata.cell_data.scalars.name = "celldata"
                    mlab.pipeline.surface(polydata,
                                          vmin=0,
                                          vmax=colors.max(),
                                          colormap=cmap)
                    cb = mlab.colorbar(orientation="vertical")

            if st:
                x, y, z = list(zip(*centers))
                u, v, w = list(zip(*spin_arrows))

                pnts = mlab.quiver3d(
                    x,
                    y,
                    z,
                    u,
                    v,
                    w,
                    line_width=5,
                    mode="arrow",
                    resolution=25,
                    reset_zoom=False,
                    name="spin-" + str(iband),
                    mask_points=mask_points,
                    scalars=spin_arrows[:, arrow_projection],
                    vmin=-1,
                    vmax=1,
                    colormap=cmap,
                )
                pnts.glyph.color_mode = "color_by_scalar"
                pnts.glyph.glyph_source.glyph_source.shaft_radius = 0.05
                pnts.glyph.glyph_source.glyph_source.tip_radius = 0.1

        elif plotting_package == "plotly":
            if mode == "plain":
                if not (transparent):
                    x, y, z = zip(*verts)
                    fig = ff.create_trisurf(
                        x=x,
                        y=y,
                        z=z,
                        plot_edges=False,
                        simplices=faces,
                        title="band-%d" % ic,
                    )

                    figs.append(fig["data"][0])

            elif mode == "parametric" or mode == "external":

                face_colors = cmap(colors)
                colormap = [
                    "rgb(%i,%i,%i)" % (x[0], x[1], x[2])
                    for x in (face_colors * 255).round()
                ]
                x, y, z = zip(*verts)
                fig = ff.create_trisurf(
                    x=x,
                    y=y,
                    z=z,
                    plot_edges=False,
                    colormap=colormap,
                    simplices=faces,
                    show_colorbar=True,
                    title="band-%d" % ic,
                )

                figs.append(fig["data"][0])
        elif plotting_package == "matplotlib":
            if mode == "plain":
                x, y, z = zip(*verts)
                ax.plot_trisurf(x,
                                y,
                                faces,
                                z,
                                linewidth=0.2,
                                antialiased=True)
            elif mode == "parametric" or mode == "external":
                print(
                    "coloring the faces is not implemented in matplot lib, please use another plotting package.we recomend mayavi."
                )
        elif plotting_package == "ipyvolume":
            if mode == "plain":
                ipv.figure()
                ipv.plot_trisurf(verts[:, 0],
                                 verts[:, 1],
                                 verts[:, 2],
                                 triangles=faces)

            elif mode == "paramteric" or mode == "external":
                face_colors = cmap(colors)
                colormap = [
                    "rgb(%i,%i,%i)" % (x[0], x[1], x[2])
                    for x in (face_colors * 255).round()
                ]
                ipv.figure()
                ipv.plot_trisurf(verts[:, 0],
                                 verts[:, 1],
                                 verts[:, 2],
                                 triangles=faces,
                                 color=cmap)

    if plotting_package == "mayavi":
        mlab.colorbar(orientation="vertical")  # ,label_fmt='%.1f')
        mlab.show()
    elif plotting_package == "plotly":
        layout = go.Layout(showlegend=False)

        fig = go.Figure(data=figs, layout=layout)
        py.iplot(fig)
    elif plotting_package == "matplotlib":
        plt.show()
    elif plotting_package == "ipyvolume":
        ipv.show()

    return