Seite 1 von 1

float(1) durch int(1) in liste ersetzen

Verfasst: Montag 8. August 2011, 13:02
von mushroom
Hallo,

ich möchte gerne in meiner Liste an aus einer float(1) eine int(1) machen. Leider funktioniert dies nicht so zusammen mit meinem Dictionary wie ich erhofft hatte, wie im Beispiel mit der Liste x. Wo liegt da der Fehler?

Code: Alles auswählen

import numpy as np

an=[6,1]
print an

radiusdic = {1: 25.0, 6: 70.0} #{atomic number: radius}
for i in range(0,len(an)):#replace atomic number by atomic radius
    if an[i] in radiusdic:
        an[i] = radiusdic[an[i]]
an = an/np.max(an) #normalize
print an

for i in range(0,len(an)): #replace float(1) by int(1)
    if an[i] == float(1):
        print an[i]
        an[i] = int(1)
        print an[i]
print an #doesn't work

print '--------'

x = [1.,2.,3.,4.] #works
for i in range(0,len(x)):
    if x[i] == float(1):
        x[i] = int(1)
print x

Re: float(1) durch int(1) in liste ersetzen

Verfasst: Montag 8. August 2011, 13:29
von CM
Das hat nichts mit dem dict zu tun, sondern damit, daß Du versuchst unterschiedliche Typen in ein numpy.ndarray zu stecken.

Im Übrigen gehen manche Operationen um Einiges einfacher. Nur mal als Beispiel:

Code: Alles auswählen

In [3]: radii = {1: 25.0, 6: 70.0}

In [4]: an = [r for n, r in sorted(radii.iteritems())]
Den Rest überlasse ich Dir fürs Erste ;-).

Wieso willst Du Integer an der Stelle? Du solltest außerdem bedenken, daß 1 == int(1). Also kannst Du auch schreiben an = 1. Das allerdings ist auch rel. kompliziert ausgedrückt, denn wenn Du wirklich einen Index brauchst geht auch:

Code: Alles auswählen

for index, value in enumerate(iterable):
Aber auch das brauchst Du eigentlich nicht, denn numpy.where und Konsorten bieten Dir einfache Selektionsalternativen. Dann aber wieder: Zwei versch. Typen in einem ndarray ...

Gruß,
Christian

Re: float(1) durch int(1) in liste ersetzen

Verfasst: Montag 8. August 2011, 13:51
von CM
PS Wenn der Radius in Pikometern bzgl. Genauigkeit à la Wikipedia ausreichend genau ist, kannst Du natürlich auch von Anfang an Integer verwenden.

Re: float(1) durch int(1) in liste ersetzen

Verfasst: Montag 8. August 2011, 20:11
von mushroom
Danke schonmal für die Antwort. Hintergrund ist die Visualisierung von Molekülen und speziell hier das vierte Argument s in mlab.points3d(x,y,z,s) [1] für die Größe der Kugeln. Wenn ich das richtig ausprobiert habe, dann muß das array s die Form haben, daß eine 1 als Integer drin ist und entsprechend Dezimalzahlen kleiner 1.

[1] from enthought.mayavi import mlab

Re: float(1) durch int(1) in liste ersetzen

Verfasst: Montag 8. August 2011, 20:32
von mushroom
CM hat geschrieben:Das hat nichts mit dem dict zu tun, sondern damit, daß Du versuchst unterschiedliche Typen in ein numpy.ndarray zu stecken.
Mein array wird ja scheinbar durch die Zeile

Code: Alles auswählen

an = an/np.max(an) #normalize
zu einem numpy.ndarray. Gibt es denn eine Möglichkeit mein array wieder zu ent-numpysieren?

Nachtrag: Habe nochmal ein wenig rumprobiert und dabei gesehen, daß mein voriger post Unsinn ist. Verstehe dann aber in meinem folgenden Code nicht, warum die H-Atome (Radius 25 im an-array) nicht gezeichnet werden.

Code: Alles auswählen

from enthought.mayavi import mlab

x = [0.0,0.5]
y = [0.0,0.5]
z = [0.0,0.5]
an = [70, 25]
mlab.points3d(x, y, z, an, color=(1,0.5,1))
mlab.show()

Re: float(1) durch int(1) in liste ersetzen

Verfasst: Montag 8. August 2011, 21:06
von BlackJack
@mushroom: Warum willst Du das tun? Ob Du da ein Array mit Gleitpunktzahlen übergibst, oder eine Liste mit den gleichen Gleitpunktzahlen bei denen die 1.0en durch Ganzzahl 1en ersetzt sind, macht keinen Unterschied. Wichtig sind die Werte und nicht die Typen, und da gilt ``1 == 1.0``.

Re: float(1) durch int(1) in liste ersetzen

Verfasst: Dienstag 9. August 2011, 07:57
von CM
Hinweis: Du solltest mit den Einheiten aufpassen: Deine Radien: Pikometer. Deine Displazierung im karthesischen Raum *wahrscheinlich* Nanometer oder Ångström. Je nachdem, was Du erreichen willst, werden Deine Moleküle mit den Radien ziemlich nackisch aussehen.

Und: Abgesehen davon, daß es bestimmt eine schöne Übung ist - Du weißt, daß es eine ganze Reihe von Mol.-Graphics-Viewern gibt? U. a. in Python?

Zu Deiner "versteckter Punkt"-Frage: Das ist in der Doku in der Tat etwas versteckt:

Code: Alles auswählen

mlab.points3d(x, y, z, an, color=(1,0.5,1), scale_factor = 1)
sollte das Problem beseitigen.

Wenn die Atome eine unterschiedliche Farbe haben sollen, empfiehlt sich ggf. eine eigene colormap.

HTH
Christian

edit: Das mit den Einheiten ist natürlich geraten.

Re: float(1) durch int(1) in liste ersetzen

Verfasst: Dienstag 9. August 2011, 08:00
von CM
PS

Ach, und bzgl. "ent-numpysieren": Numpy-Arrays haben eine tolist-Methode. Also:

Code: Alles auswählen

an.tolist()
Aber wie BJ schrieb ist das überhaupt nicht nötig. Und andererseits würde eine ListComprehension das "numpysieren" überflüssig machen.

Und: Wieso gleich kommst Du auf die Idee, dass da irgendwo eine 1 stehen muß?

Re: float(1) durch int(1) in liste ersetzen

Verfasst: Dienstag 9. August 2011, 09:10
von HerrHagen
Numpy-arrays können übrigens auch ihren Typ ändern:

Code: Alles auswählen

>>> import numpy
>>> a = numpy.array([1.1, 1.2, 1.3])
>>> a
0: array([ 1.1,  1.2,  1.3])
>>> a.dtype
1: dtype('float64')
>>> a.astype("int32")
2: array([1, 1, 1])

Re: float(1) durch int(1) in liste ersetzen

Verfasst: Dienstag 9. August 2011, 09:40
von BlackJack
@HerrHagen: Das ist aber etwas missverständlich formuliert, da Du nicht den Typ von dem Array geändert hast, sondern ein neues Array mit einem anderen Typ erstellt hast, in das die Werte aus dem Alten übertragen und dabei umgewandelt wurden.

Code: Alles auswählen

In [40]: a = np.array([1.1, 1.2, 1.3])

In [41]: b = a.astype('int32')

In [42]: a is b
Out[42]: False

Re: float(1) durch int(1) in liste ersetzen

Verfasst: Dienstag 9. August 2011, 13:09
von mushroom
@BlackJack, CM Bezüglich der Ersetzung von floats durch ints war ich einem Irrtum aufgesessen. Das hat sich erledigt.

@CM Jep, weiß daß es einige Viewer gibt :-) Den Viewer den ich mir bastel, ist Teil ein größeren Programms, daß automatisch Ergebnisse aus quantenchemischen Rechnungen aufarbeitet.
Die colormap kommt noch. :-)
Danke für den Hinweis mit den Einheiten, ist mir gar nicht mehr aufgefallen. Die Geometriedaten liegen tatsähclich in Angstrom vor und die Radien in Pikometern.

Problem ist jetzt nicht mehr meine ursprüngliche Fragestellung, sondern das, was ich im Post #5 geschrieben habe. Werde dafür aber einen neuen Thread aufmachen.

Danke für eure Hilfe.
Grüße
Markus

Re: float(1) durch int(1) in liste ersetzen

Verfasst: Dienstag 9. August 2011, 13:19
von CM
Ich habe mal bei einem Simulationsprogramm Radius und Durchmesser verwechselt und dann geschlagene 2 Wochen gerätselt, warum meine Ergebnisse ganz ok, aber immer um den Faktor 4 daneben waren (als ich den Fehler gefunden hatte, hatten die Kollegen ihren Spaß :evil: ). Beim aktuellen Projekt (allerdings in C++) schreibe ich eine expliziete Einheitentabelle in den Code (separate Datei), damit so etwas nicht mehr vorkommt und nicht irgendwelche komischen Konversionskonstanten in den Rechnungen rumfliegen, die ich nach ein paar Wochen sowieso nicht mehr verstehe. Vielleicht eine Idee für Dich?

Re: float(1) durch int(1) in liste ersetzen

Verfasst: Dienstag 9. August 2011, 16:04
von mushroom
CM hat geschrieben:
Zu Deiner "versteckter Punkt"-Frage: Das ist in der Doku in der Tat etwas versteckt:

Code: Alles auswählen

mlab.points3d(x, y, z, an, color=(1,0.5,1), scale_factor = 1)
sollte das Problem beseitigen.
Sorry, habe erst jetzt deinen post aufmerksam durchgelesen. Damit hat sich das Problem ja auch erledigt. Habe da auch noch eine andere Lösung gefunden:

Code: Alles auswählen

pts = mlab.points3d(x, y, z, s)
pts.glyph.glyph.clamping = False

Die Radien habe ich auch in einer separaten Textdatei ausgelagert. Falls da mal was geändert werden soll, dann geht das da deutlich einfacher.