Scipy cKD_Tree bug

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
schneitzmaster
User
Beiträge: 94
Registriert: Freitag 26. Oktober 2012, 15:35
Wohnort: Hamburg

Hallo Leute,

ich habe eine Funktion geschrieben, mit der ich aus einem numpy-array von 3d koordinaten doppelt auftretende punkte eliminiere.
Dazu benutze ich den cKD_Tree von scipy (version 0.15.1) und die funktion "query_pairs". Im Großen und Ganzen funktioniert das Ganze. Werden die Listen der Knoten-Koordinaten jedoch groß
treten vermehrt fehler auf. Hier mein Beispiel Code (dazu benötigt wird die Liste der knoten https://www.dropbox.com/s/orkj868iuh01g ... s.txt?dl=0 ):

Code: Alles auswählen

import numpy as np
import scipy.spatial

def rm_coincident_nodes(nodes,delta=10**-9):
    cKD_TREE        = scipy.spatial.cKDTree( nodes )                        # BUILD KD_TREE
    coincident_pairs= np.array( list(cKD_TREE.query_pairs( delta )) ) # GET ALL PAIRS WITH A SMALLER DISTANCE THAN delta
    idx             = np.arange( 0, len(nodes) )                                 # INITIALIZE INDEX CORRELATION ARRAY    
    idx[coincident_pairs[:,1]] = coincident_pairs[:,0]                       # CORRELATE COINCIDENT PAIRS WITH INDEX
    unique_ids      = np.unique(idx)                                              # FILTER UNIQUE NODE IDS
    nodes           = nodes[unique_ids]                                          # GET UNIQUE NODES
    return nodes

nodes = np.genfromtxt('nodes.txt')                          # READ NODES

new_nodes = rm_coincident_nodes(nodes,delta=10**-9)         # REMOVE COINCIDENT NODES
print 'Number of new_nodes ',len(new_nodes)
print 'node 29700',new_nodes[29700]
print 'node 3733',new_nodes[3733]

new_new_nodes = rm_coincident_nodes(new_nodes,delta=10**-9) # REMOVE COINCIDENT NODES
print 'Number of new_new_nodes ',len(new_new_nodes)
Ausgabe davon ist:

Code: Alles auswählen

>>> Number of new_nodes  32045
>>> node 29700 [ 1.        0.793401  1.      ]
>>> node 3733 [ 1.        0.793401  1.      ]
>>> Number of new_new_nodes  32038
Das heißt beim ersten mal wurden nicht alle Pärchen gefunden. Ist das ein Fehler im Scipy-code oder habe ich etwas übersehen?

P.S: Kann man hier auch Anhänge hochladen?
BlackJack

@schneitzmaster: Ohne mich damit jetzt näher befasst zu haben: Was passiert wenn es drei gleiche Punkte gibt, die Paarfunktion zwei davon als Paar liefert und Du von diesem Paar einen entfernst. Wieviele gleiche bleiben über? Kann es das sein?
schneitzmaster
User
Beiträge: 94
Registriert: Freitag 26. Oktober 2012, 15:35
Wohnort: Hamburg

@BlackJack: Danke für die schnelle Antwort. Ich hab den Wald vor lauter Bäumen nicht gesehen. Wenn ich

Code: Alles auswählen

nodes = np.array([[1.,2.,3.],                  
                  [1.,2.,3.],
                  [1.,2.,4.],
                  [1.,2.,3.]])
setze kann ich den Fehler reproduzieren. Ich hab mich beim indizieren vertan... werd das gleich beheben.
Danke für den Hinweis!
schneitzmaster
User
Beiträge: 94
Registriert: Freitag 26. Oktober 2012, 15:35
Wohnort: Hamburg

ich hab das ganze jetzt über eine Schleife, die nach mehrfach auftretenden punkten in den spalten des 'coincident_pairs' arrays sucht gelöst:

Code: Alles auswählen

import numpy as np
import scipy.spatial
import scipy.version
def rm_coincident_nodes(nodes,delta=10**-9):
    cKD_TREE        = scipy.spatial.cKDTree( nodes )                  # BUILD KD_TREE
    coincident_pairs= np.array( list(cKD_TREE.query_pairs( delta )) ) # GET ALL PAIRS WITH A SMALLER DISTANCE THAN delta
    idx             = np.arange( 0, len(nodes) )                      # INITIALIZE INDEX CORRELATION ARRAY
    # SEARCH FOR MULTIPLE OCCURING POINTS IN THE COLUMNS OF coincident_pairs
    for pair_i in coincident_pairs:
        id_ch = np.where( coincident_pairs[:,1]==pair_i[0] )[0]
        if len(id_ch)>0:
            pair_i[0] = coincident_pairs[id_ch[0]][0]    
    idx[coincident_pairs[:,1]] = coincident_pairs[:,0]                # CORRELATE COINCIDENT PAIRS WITH INDEX    
    unique_ids      = np.unique(idx)                                  # FILTER UNIQUE NODE IDS
    nodes           = nodes[unique_ids]                               # GET UNIQUE NODES
    return nodes
Antworten