Giter Site home page Giter Site logo

Comments (5)

pascalisfort avatar pascalisfort commented on May 25, 2024 1

I try the MainWindow class from pyvistaqt and the same error appear, but when I add self.signal_close.connect(self.plotter.close) every thing works.

Thank a lot for your help
Pascal

from pyvistaqt.

GuillaumeFavelier avatar GuillaumeFavelier commented on May 25, 2024

Thank you @pascalisfort for reporting. What plotter do you use? Does it happen even for a minimal code snippet like the following:

import pyvista
from pyvistaqt import BackgroundPlotter
plotter = BackgroundPlotter()
plotter.add_mesh(pyvista.Cone())

I remember this happening in the past and I thought it was fixed for good 😓

Also, could you share your configuration:

$ python -c "import pyvista; print(pyvista.Report())"

It will be helpful to understand the underlying issue.

from pyvistaqt.

pascalisfort avatar pascalisfort commented on May 25, 2024

Thank you @GuillaumeFavelier
I try the minimal code you give me in your message and it works well...

This is my simplified code with the principal function i used for the viewing, can you have an idea where I begin to search to solve the problem. This is not a major problem but I interested to understand and solve it

import sys
# Setting the Qt bindings for QtPy
import os
os.environ["QT_API"] = "pyqt5"

from qtpy import QtWidgets
from qtpy.QtWidgets import QMainWindow, QFileDialog
import laspy#permet de lire les fichiers las
import time
import numpy as np
import pickle #permet de sauvegarder des variables
import easygui #permet d'afficher un message box
import pyvista as pv
from pyvistaqt import QtInteractor
#from pyvista.plotting.theme import rcParams
#from sklearn.neighbors import KDTree
from matplotlib import colors as color_lib
import matplotlib.pyplot as plt
from shapely.geometry import Polygon
from scipy.spatial import cKDTree, ConvexHull
from dbfread import DBF

        

class MainWindow(QMainWindow):

    def __init__(self, parent=None, show=True):
        
      
        QtWidgets.QMainWindow.__init__(self, parent)
        
        # create the frame
        self.frame = QtWidgets.QFrame()
        
        vlayout = QtWidgets.QVBoxLayout()

        self.plotter = QtInteractor(shape="1|2")


        vlayout.addWidget(self.plotter.interactor)

        self.frame.setLayout(vlayout)
        self.setCentralWidget(self.frame)
        

        # simple menu to demo functions
        mainMenu = self.menuBar()
        fileMenu = mainMenu.addMenu('File')
        self.add_point_action = QtWidgets.QAction('ouvrir fichier las', self) #creation du bouton
        self.add_point_action.triggered.connect(self.add_point) # creation de l,action a faire par le bouton
      
        
        
        exitButton = QtWidgets.QAction('Exit', self)
        exitButton.setShortcut('Ctrl+Q')
        exitButton.triggered.connect(self.close)
        fileMenu.addAction(self.add_point_action) #ajout du bouton dans le menu filemenu
     
        fileMenu.addAction(exitButton)

        
        #initialisation des variables que l'on utilisera tout au long du program
        self.nom_output =""
        self.rep_base ='c:/data isfort 2/philippe/mffp big data/7601502902/aller/clean_by_R'
        self.rep_base ='D:/data isfort 2/philippe/mffp big data'
        self.bloc_tranche= pv.MultiBlock()
        
        
        # preparation du colormap pour les 1023 premiere tige (si plus de 1023 tiges valider 
        self.list_couleur = ['#FFFFFF']
        np.random.seed(0)
        aleat= np.random.choice(range(147), 147, replace=False)
        aa=plt.cm.get_cmap('gist_rainbow', 147)
        dict_color = []
        for i in range(0,len(aleat)):
            bb = aleat[i]                        
            hex_a = color_lib.rgb2hex(aa(bb))
            dict_color.append(hex_a) 
        self.list_couleur = self.list_couleur+(7*dict_color)
        
        #preparation des bouton et widget
        self.plotter.subplot(0, 0)
        self.reset_slider_bool = 1 #condition pour ne pas que la fct ch_cluster s'active
        self.slide_cluster = self.plotter.add_slider_widget(self.ch_cluster, value = 0.02, rng=[0.001, 0.03], title="distance clustering", pointa=(.025, .1), pointb=(.80, .1))
        self.plotter.subplot(1, 0)
        self.slide_haut_dhp = self.plotter.add_slider_widget(self.ch_haut_dhp, value = 1.3, rng=[0.85, 2.85], title="Hauteur du DHP", pointa=(.025, .1), pointb=(.95, .1))
        self.plotter.subplot(2, 0)
        self.write_dhp(0,0)
        self.btn_enr=self.plotter.add_checkbox_button_widget(self.save_tree, value= False, position=(10,20), size=30,color_on='green',color_off='red')
        self.reset_slider_bool = 0
        #bouton pour enregistrer les images activé le au besoin
       
        
        
        if show:
            self.show()
      
        

    def add_point(self):       
        fname, _ = QFileDialog.getOpenFileName(self, 'Open file', self.rep_base,"LAS file (*.las)")# ouvre une fenetre open file et produit un genre de array a 2 valeur dans cette ligne je ne prend que la 1er valeur
        if fname:
            data = laspy.file.File(fname, mode="r")
            #verif si le fichier las a la variable id_tree
            for spec in data.point_format:
                if spec.name == "id_tree": 
                    self.scalar_las= data.id_tree 
                    break
                else:
                    self.scalar_las= np.array([1]*len(data))
            self.xyz = np.c_[data.x, data.y, data.z]
            data.close()
            self.point_cloud = pv.PolyData(self.xyz)
            self.point_cloud["id_arbre"]= self.scalar_las
            self.point_cloud["graph"]= np.array([0]*self.point_cloud.n_points)
            #self.tree = Cluster(self.point_cloud.points)
            self.plotter.subplot(0, 0)#attention il faut remplir les subplot en ordre sinon ils s'efface
            couleur=self.list_couleur[:max(self.point_cloud["id_arbre"])]
            self.plot_princ = self.plotter.add_mesh(self.point_cloud , scalars="id_arbre", categories=True, point_size=1, cmap=couleur, show_scalar_bar= False)
            self.plotter.enable_eye_dome_lighting()
            self.plotter.enable_point_picking(self.clicker, use_mesh=True, show_message=False )
            
    def clicker(self, ptc, pid):
        try: 
            self.arbre
            if not self.arbre.enregistrement_arbre:
                if easygui.ynbox("Vous n'avez pas enregistrer votre dernier arbre voulez-vous continuer?", 'Enregistrement', ('Oui', 'Non')):
                    pass
                else:
                    return
        except:
            pass
        if ptc["graph"][0]==0:
            self.choix_arbre_princ(ptc, pid)
            self.dernier_click=0
        elif ptc["graph"][0]==1:
            self.choix_arbre_sec(ptc, pid)
            self.dernier_click=1
    def choix_arbre_princ(self, ptc, pid):
        self.reset_slider()
        if self.point_cloud["id_arbre"][pid]== 1:
            
            pt_cluster = self.tree.Clusterisation(pid, ptc)         
            id_arbre = max(self.point_cloud["id_arbre"])+1
            self.point_cloud["id_arbre"][pt_cluster]= id_arbre
            self.redraw_graph("princ")            
            self.point_cloud_sec = self.point_cloud.extract_cells(pt_cluster)

        else:
            id_arbre = self.point_cloud["id_arbre"][pid]
            self.point_cloud_sec= self.point_cloud.clip_scalar(scalars='id_arbre',invert=False, value=id_arbre)
            pt_cluster = self.point_cloud_sec["vtkOriginalCellIds"]#une facon d'avoir les id des points qui sont dans le cluster 
        pt_depart=ptc.points[pid]
        bounds= self.point_cloud_sec.bounds
        
        self.arbre= tree_info(id_arbre, pt_cluster, 1.3, 0.02, bounds, pt_depart) #creation de l'objet arbre contenant les info de l'arbre actif
        self.btn_enr.GetRepresentation().SetState(0)

        self.point_cloud_sec["graph"]= np.array([1]*self.point_cloud_sec.n_points)# ajout de l'identifiant de quel graphique il s'agit utilisex dans l'action clicker

        self.point_cloud_sec['couleur']=np.where(abs(self.point_cloud_sec.points[:,2]-self.arbre.haut_dhp)<0.1, 2, 1)#ajout de la bande rouge du dhp
        
        self.redraw_graph("sec")
        self.point_cloud_ter= self.point_cloud_sec.clip_scalar(scalars='couleur',invert=False, value=2)#extraction des points pour creer la galette
        self.coord_pourtour = self.arbre.calc_dhp(self.point_cloud_ter)
        self.redraw_graph("ter")
        
    def choix_arbre_sec(self, ptc, pid):
        #easygui.msgbox(pid, title="arbre secondaire")
        pt_cluster = self.tree.Clusterisation_sec(pid, ptc, self.arbre.haut_dhp)
        
        self.arbre.pt_depart=ptc.points[pid]
        self.point_cloud_ter = self.point_cloud_sec.extract_cells(pt_cluster)
        self.coord_pourtour = self.arbre.calc_dhp(self.point_cloud_ter)
        self.redraw_graph("ter")
        
    def redraw_graph(self, graph):
        if graph=="princ":
            self.plotter.subplot(0, 0)
            cpos = self.plotter.camera_position
            try:
                self.plotter.remove_actor(self.plot_princ)
                self.plotter.remove_actor(self.bord_princ)
            except:
                pass
            couleur=self.list_couleur[:max(self.point_cloud["id_arbre"])]
            self.plot_princ = self.plotter.add_mesh(self.point_cloud , scalars="id_arbre", categories=True, point_size=1, cmap=self.list_couleur, show_scalar_bar= False)
            try: 
                self.bord_princ = self.plotter.add_mesh(self.bordure , color="red", show_edges=True, style="wireframe", line_width=3)
            except:
                pass
            self.plotter.camera_position = cpos
        elif graph=="sec":
            self.plotter.subplot(1)
            try:
                self.plotter.remove_actor(self.plot_sec)
            except:
                pass
            if(len(self.point_cloud_sec.points)<50): return#ne rien afficher et calculé si il reste moin de 50 points
            self.plot_sec = self.plotter.add_mesh(self.point_cloud_sec , scalars="couleur", clim=[1,2], point_size=1, cmap=['white','red'], show_scalar_bar= False)
            self.plotter.set_focus(self.point_cloud_sec.center)
        elif graph=="ter":    
            self.plotter.subplot(2, 0)
            try:
                self.plotter.remove_actor(self.plot_ter)
                self.plotter.remove_actor(self.ligne_perimetre)
            except:
                pass
            if(len(self.point_cloud_ter.points)<50): return#ne rien afficher et calculé si il reste moin de 50 points
            pc_ter = self.point_cloud_ter.copy()
            pc_ter.points[:,2]=0 #retire la 3e dimension donc tout les points sont remis sur xy
            self.plot_ter = self.plotter.add_mesh(pc_ter , color='red', point_size=3)#affichage des points
            self.ligne_perimetre= self.plotter.add_lines(self.coord_pourtour, color='green', width=3)
            self.write_dhp(self.arbre.dhp, self.arbre.id)
            
    def reset_slider(self):
        self.reset_slider_bool = 1
        self.plotter.subplot(0)
        try:
            self.slide_cluster.Off()
        except:
            pass
        self.slide_cluster = self.plotter.add_slider_widget(self.ch_cluster, value = 0.02, rng=[0.001, 0.03], title="distance clustering", pointa=(.025, .1), pointb=(.80, .1))
        self.plotter.subplot(1)
        try:
            self.slide_haut_dhp.Off()
        except:
            pass 
        self.slide_haut_dhp = self.plotter.add_slider_widget(self.ch_haut_dhp, value = 1.3, rng=[0.85, 2.85], title="Hauteur du DHP", pointa=(.025, .1), pointb=(.95, .1))
        self.reset_slider_bool = 0
        
    def ch_cluster(self, dist_c):
        if hasattr(self, 'tree') and not(self.reset_slider_bool):   
            
            #pt_cluster_tranche = self.tree.modif_Clusterisationold(self.point_cloud_ter, dist_c, self.arbre.haut_dhp)
            #self.arbre.treshold=dist_c
            #if(self.dernier_click):#dernier click vient de l'image originale
            self.point_cloud_sec = self.tree.modif_Clusterisation(self.point_cloud_sec, dist_c, self.arbre.treshold, self.arbre.pt_depart, self.arbre.orig_bounds)
            
            #self.temp_sec = self.point_cloud_sec.copy()
            self.arbre.treshold=dist_c
            self.point_cloud_sec["id_arbre"]= np.array([self.arbre.id]*self.point_cloud_sec.n_points)
            self.point_cloud_sec["graph"]= np.array([1]*self.point_cloud_sec.n_points)
            self.point_cloud_sec["couleur"]=np.where(abs(self.point_cloud_sec.points[:,2]-self.arbre.haut_dhp)<0.1, 2, 1)#ajout de la bande rouge du dhp
            cond=self.point_cloud_sec["couleur"]==2#condition pour extraire la galette
            if (not any(cond)): #sortir de la condition si il n'y a pas de points suite au changement de cluster et redessiner le 2e et 3e graph
                self.redraw_graph("sec")
                self.redraw_graph("ter")
                return                
            self.point_cloud_ter= self.point_cloud_sec.extract_cells(cond)#extraction des points pour creer la galette
            self.redraw_graph("sec")#mettre cette commande car la commande précédente fait changer la couleur de tout le nuage de points???
            self.coord_pourtour = self.arbre.calc_dhp(self.point_cloud_ter)
            self.redraw_graph("ter")
      
            #self.point_cloud_ter_orig= self.point_cloud.extract_cells(pt_cluster)
        # try:
            # pt_cluster = self.tree.modif_Clusterisation()
        # except:
            # pass
    def ch_haut_dhp(self, haut_dhp):
        try:
            self.arbre.haut_dhp = haut_dhp
            self.point_cloud_sec['couleur']=np.where(abs(self.point_cloud_sec.points[:,2]-haut_dhp)<0.1, 2, 1)
            self.redraw_graph("sec")
            self.point_cloud_ter= self.point_cloud_sec.clip_scalar(scalars='couleur',invert=False, value=2)
            
            self.coord_pourtour = self.arbre.calc_dhp(self.point_cloud_ter)
            self.redraw_graph("ter")
        except:
            pass    
    def save_tree(self, arg):
        #easygui.msgbox("arbre sauve", title="simple gui")
        if self.nom_output=="":
            self.nom_output, _ = QFileDialog.getSaveFileName(window, 'Open file', self.rep_base,"txt file (*.txt)")
        f = open(self.nom_output, "a")
        f.write(str(self.arbre))
        f.close()
        self.arbre.enregistrement_arbre=True
        
        
        #ajout des points de la tranche dans un multibloc pour enregistrement futur
        self.bloc_tranche.append(self.point_cloud_ter)


 
    def write_dhp(self, dhp,idtree):
        self.plotter.subplot(2)
        try: 
            self.plotter.remove_actor(self.txt_dhp)
        except:
            pass
        self.txt_dhp = self.plotter.add_text("DHP= {}cm,          ID= {}".format(round(dhp,1),idtree) , position= 'upper_left', font_size=10)
        


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow()
    window.setWindowTitle("LIDAR Identree")# a modifie
    #window.resize(700,700)#grandeur de la fenetre
    window.showMaximized()

    sys.exit(app.exec_())

And my configuration is:

Date: Mon Apr 12 06:42:50 2021 Est (heure d’étĂ©)

            OS : Windows
        CPU(s) : 6
       Machine : AMD64
  Architecture : 64bit
           RAM : 7.8 GB
   Environment : Python
    GPU Vendor : Intel
  GPU Renderer : Intel(R) UHD Graphics 630
   GPU Version : 4.5.0 - Build 26.20.100.6952

Python 3.8.5 (default, Sep 3 2020, 21:29:08) [MSC v.1916 64 bit (AMD64)]

       pyvista : 0.27.4
           vtk : 9.0.1
         numpy : 1.19.5
       imageio : 2.9.0
       appdirs : 1.4.4
        scooby : 0.5.6
        meshio : 4.3.8
    matplotlib : 3.3.3
     pyvistaqt : 0.2.0
         PyQt5 : 5.12.3
       IPython : 7.19.0
      colorcet : 1.0.0
         scipy : 1.5.3
    itkwidgets : 0.32.0
          tqdm : 4.55.2

thank you so much
Pascal

from pyvistaqt.

GuillaumeFavelier avatar GuillaumeFavelier commented on May 25, 2024

Thanks for sharing your code snippet. Hm... I see that you use QtInteractor and inherits from QMainWindow đŸ€”

Would you give our MainWindow class a try?

...
from pyvistaqt import MainWindow

class MyMainWindow(MainWindow):
...

It's actually very light and has a builtin signal_close that can be connected to the interactor as follows:

        self.signal_close.connect(self.plotter.close)

I look forward to your reply :)

from pyvistaqt.

GuillaumeFavelier avatar GuillaumeFavelier commented on May 25, 2024

Great news! But it means that the doc should be updated then :)

from pyvistaqt.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.