2017-08-16 5 views
0

Je veux incrémenter une matrice 3D (nparray) de compteurs d'un tableau 2D d'événements (x, y, t) le code ci-dessous fonctionne:Incrément Tableau 3D de compteurs de la liste 2D d'indices (x, y, z) utilisant: Python Numpy Slicing

TOF_cube=np.zeros((324,324,4095),np.int32) #initialise a 3d array for whole data set 

data = np.fromfile(f, dtype='<i2', count=no_I16) #read all events, x,y,t as 1D array 
data=data.reshape(events,cols) 
xpos=data[:,0] 
ypos=data[:,1] 
tpos=data[:,2] 
i=0 
while i < events:    
    TOF_cube[xpos[i],ypos[i],tpos[i]] += 1 
    i+=1 

Pour utiliser le découpage et l'indexation je remplace ma boucle while avec

TOF_cube[xpos,ypos,tpos] += 1 

Mais plutôt que de copier le numéro 4365520 correct des événements (via la boucle while et vérifié indépendamment) J'enregistre seulement 4365197.

Pourquoi la méthode de découpage perd-elle des événements? J'utilise exactement les mêmes tranches dans la boucle while et comme «argument» pour l'index.

+0

Qu'est-ce 'TOF_cube.max()' pour chaque méthode? –

Répondre

3

+= n'ajoute pas deux fois s'il y a des répétitions.

Pour obtenir une sortie équivalente d'une manière vectorisé, vous aurez besoin np.add.at:

np.add.at(TOF_cube, [xpos, ypos, tpos], 1) 
+0

Merci! C'était le problème, merci! Je suis surpris que 'np.add.at (TOF_cube, [xpos, ypos, tpos], 1) .' semble fonctionner beaucoup plus lentement que la version + =. (Je sais que je manquais quelques événements, mais très peu). On pourrait penser que '+ =' devrait faire un 'IF duplicated: ignore' vérifier où' np.add' ne fait que passer. Des pensées? D – poolz50

+0

La construction '+ =' n'est pas séquentielle comme 'np.add.at', c'est un appel parallèle (thread) pour incrémenter un ensemble d'emplacements de mémoire. C'est pourquoi il ne peut incrémenter quoi que ce soit une seule fois (et exécute les emplacements via 'set' pour s'assurer qu'il n'y a pas de doublons) - sinon ces threads individuels pourraient se verrouiller alors que deux essayaient d'incrémenter simultanément le même bit de mémoire. –

+0

N'oubliez pas de cocher la case si la réponse est ce que vous cherchiez. –

-1

Comme nous ne savons pas exactement à quoi ressemblent vos données, il est difficile de deviner quel est le problème réel. Si cela ne vous aide pas, donnez un exemple en indiquant que nous pouvons exécuter ourselvs (c'est-à-dire sans avoir le fichier f).

Supposons que vous ayez x_pos = [1,1,2,3,5]

a = np.zeros(10) 
for i in range(len(x_pos)): 
    a[x_pos[i]]+=1 
# gives a = array([ 0., 2., 1., 1., 0., 1., 0., 0., 0., 0.]) 

Cependant, l'autre code

a[x_pos]+=1 
# gives a = array([ 0., 1., 1., 1., 0., 1., 0., 0., 0., 0.]) 

Donc, si l'un des indices se produit deux fois il est mis à jour une fois que dans la version courte. Vérifiez si c'est effectivement le cas dans votre xpos etc.

PS: J'ai fait une version légèrement plus simple, avec une seule dimension, mais les règles restent les mêmes.

+0

Vous avez exactement identifié le problème, merci! Complètement corrigé avec suggestion 'np.add.at (TOF_cube, [xpos, ypos, tpos], 1)' – poolz50