Pagina 1 di 1

"type double" e python

Inviato: giovedì 11 settembre 2008, 15:07
da marrano00
Salve a tutti avrei bisogno di un aiutino con un pezzo di codice python.
Dunque cerco di usare un modulo che si interfaccia con una libreria scritta in C++. Importo il modulo correttamente e sono in grado di sfruttare quasi tutte le funzioni; il problema arriva con alcuni metodi che sembrano richiedere come argomento un vettore od un array. L'errore che ottengo è:

Codice: Seleziona tutto

TypeError: in method 'OBMol_AddConformer', argument 2 of type 'double *'
Penso di aver capito che è un errore dovuto al tipo della variabile ma non soproprio come risolverlo, o quale modulo (o santo :)) invocare.

Se qualcuno ha una soluzione è ben accetta.

Re: "type double" e python

Inviato: giovedì 11 settembre 2008, 16:33
da Markon
Ciao!

Avresti potuto almeno dire di che libreria si tratta e/o postare un pezzo di codice.

Considerando che dalle API di openbabel risulta che la funzione AddConformer prende puntatore a un double, non ti saprei dire che cosa sbagli.

Ciao

Re: "type double" e python

Inviato: giovedì 11 settembre 2008, 19:10
da marrano00
Markon ha scritto: Avresti potuto almeno dire di che libreria si tratta e/o postare un pezzo di codice.
Salve ancora, hai ragione Markon sono stato impreciso, mi scuso per l'errore sono adato troppo di fretta.

Comunque la libreria è openBabel§ di cui è disponibile il binding per il python, quello che mi interessava fare era leggere l'output di un'analisi conformazionale eseguita con MacroModel§§.
Quello che faccio è prima far leggere le caratteristiche della molecola, tipi di atomi, connettività, residui e quant'altro, e fino a qui nessun problema ci sono funzioni che secondo la documentazione (disponibile per la libreria c++) richiedono variabili di tipo double e vengono prese tranquillamente, es.:

atm.SetVector(float(m.group('x_coord')), float(m.group('y_coord')), float(m.group('z_coord')))

Il problema viene quando vado a usare funzioni che invece richiedono variabili di tipo "double *"
come appunto AddConformer definita dalla documentazione come:
void AddConformer  (double *  f )  [inline]

Add a new set of coordinates f as a new conformer.

Referenced by OBForceField::WeightedRotorSearch().
Ho provato ad usare prima liste, poi array poi infine sull'onda della disperazione anche array generati con ctypes. ma nulla sempre TypeError.
Penso che il mio problema non riguardi la libreria openbabel in se quando la mia non conoscenza di come rendere con il python una variabile di tipo double*.

Spero di essere stato un pò più chiaro.

note:
§    Software di conversione tra formati di molecole di cui è disponibile anche una verione nei repository, è possibile usare anche un binding per python.
§§  Software proprietario per lavori di molecular modeling. Prevalentemente orientato alla meccanica molecolare.

Re: "type double" e python

Inviato: giovedì 11 settembre 2008, 22:04
da Markon
Ciao!

Allora, l'header della funzione SetVector è questo:

Codice: Seleziona tutto

void SetVector(const double x, const double y, const double z) 	
E tu gli passi giustamente tre float.

Hai provato a fare la stessa cosa con AddConformer?
Perchè gli hai passato una lista? Come può essere questa convertita in un double * ?

Penso che tu gli debba passare semplicemente un valore float.

C'hai provato?

Ciao

Re: "type double" e python

Inviato: giovedì 11 settembre 2008, 22:35
da marrano00
Ho provato con un singolo valore float ma da comunque lo stesso errore:

Codice: Seleziona tutto

TypeError: in method 'OBMol_AddConformer', argument 2 of type 'double *'
L'idea della lista è dovuta al fatto che la funzione dovrebbe ricevere un intero set di coordinate quindi almeno tre valori, ma richiede solo un argomento quindi ho pensato ad un vettore od un array.

Ora i miei ricordi di C e C++ sono un pò remoti (il manuale di Bjarne Stroustrup non c'è mai quando serve) e non mi ricordo bene a cosa si riferisca l'asterisco nella dichiarazione delle variabili.

Re: "type double" e python

Inviato: venerdì 12 settembre 2008, 8:31
da Markon
L'asterisco è un puntatore a una variabile di tipo double in questo caso.

Tu gli puoi passare un riferimento o un array o un puntatore deferenziato.

Ma in Python questa cosa non saprei come gestirla... dato che non ci sono i puntatori.
Al massimo potresti fare una cosa:

prova a scrivere in un interprete:

Codice: Seleziona tutto

help(ModuloOpenBabel.AddConformer)
Dove ModuloOpenBabel è il modulo o classe in cui si trova AddConformer.

In genere quando si fanno i binding per un altro linguaggio viene scritta anche documentazione appropriata al linguaggio.

Vedi un po'...
Ciao ;)

Re: "type double" e python

Inviato: venerdì 12 settembre 2008, 10:04
da gaspa
Io non ho mai usato questa libreria.
Ma se ci sono i bindings in python, ci sara' anche qualuno che li usa.
Hai provato a cercare un altro sorgente che usi la funzione che stai cercando e vedere cosa fa?

Nota: magari copia un pezzetto di codice che non funziona, io personalmente  non ho capito come fai a generare l'errore.

Re: "type double" e python

Inviato: venerdì 12 settembre 2008, 11:06
da marrano00
Markon ha scritto: L'asterisco è un puntatore a una variabile di tipo double in questo caso.
Avevo questo sospetto, ho sempre odiato i puntatori.


Ecco il codice

Codice: Seleziona tutto

#!/usr/bin/python
import os
import gzip
import sys
import re
import pybel
import openbabel

obConversion = openbabel.OBConversion()
obConversion.SetInAndOutFormats("pdb", sys.argv[2])
file_out = 'tmp.'+sys.argv[2]

# apro il file mae di MacroModel
file_mae = open(sys.argv[1])

for linea in file_mae:
	m = re.match('.*(m_atom).*',linea)
	if m:
		break
	
ricerca = ' +(?P<ID>[-+]?\d+)'
lista_str = []
## legge il numero ed il tipo di variabili e genera la stringa di ricerca.
## prefissi dei nomi delle variabili nel file mae:
## i = numero intero
## r = numero reale (float)
## s = stringa (le stringe vuote a volte sono indicate da "")
for linea in file_mae:
	m = re.match(' +(.)_m_(.*)',linea)
	m2 = re.match('.*:::.*',linea)
	if not (m2 == None):
		break
	elif m:
		if (m.group(1) == 'i'):
			ricerca = ricerca+' +(?P<'+m.group(2)+'>[-+]?\d+)'
		elif (m.group(1) == 'r'):
			ricerca = ricerca+' +(?P<'+m.group(2)+'>[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?)'
		elif (m.group(1) == 's'):
			ricerca = ricerca+' +(?P<'+m.group(2)+'>(".*?")|(\w))'
			lista_str = [lista_str, m.group(2)]
	


ricerca = ricerca+'.*'

posa1 = openbabel.OBMol()
old_resnum = 0

coordinate = []

# Legge coordinate e valori per ogni atomo del primo conformero
print 'Inizio a leggere le coordinate del primo conformero'
for linea in file_mae:
	m = re.match(str(ricerca),linea)
	if m:
		new_resnum = int(m.group('residue_number'))
		if (old_resnum != new_resnum):
			old_resnum = new_resnum
			res = posa1.NewResidue()
			res.SetName(m.group('pdb_residue_name').strip('" '))
			res.SetNum(new_resnum)
			res.SetChain(m.group('chain_name').strip('" '))
		
		
		atm = posa1.NewAtom()
		atm.AddResidue(res)
		atm.SetAtomicNum(int(m.group('atomic_number')))
		#atm.SetVector(float(m.group('x_coord')), float(m.group('y_coord')), float(m.group('z_coord'))) #rimpiazzata dall'aggiunta delle coordinate dei conformeri
		coordinate.append(float(m.group('x_coord')))
		coordinate.append(float(m.group('y_coord')))
		coordinate.append(float(m.group('z_coord')))
		atm.SetType(m.group('pdb_atom_name').strip('" '))
		atm.SetFormalCharge(int(m.group('formal_charge')))
	m2 = re.match('.*:::.*',linea)
	#uscita nel caso finiscano gli atomi
	if not (m2 == None):
		break
	
print 'lette le coordinate del primo conformero'
print 'inizio a leggere i legami'

# ricerca dei legami
ricerca = ' +(?P<ID_bond>[-+]?\d+)'
for linea in file_mae:
	m = re.match(' +(.)_m_(.*)',linea)  #match per le variabili associate hai legami
	m2 = re.match('.*:::.*',linea)      #match per ::: che danno inizio alla definizione dei legami.
	if not (m2 == None):
		break
	elif m:		# forse non c'è bisogno di questa parte ma assicura il funzionamento anche con file mae leggermente diversi
		if (m.group(1) == 'i'):
			ricerca = ricerca+' +(?P<'+m.group(2)+'>[-+]?\d+)'
		elif (m.group(1) == 'r'):
			ricerca = ricerca+' +(?P<'+m.group(2)+'>[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?)'
		elif (m.group(1) == 's'):
			ricerca = ricerca+' +(?P<'+m.group(2)+'>(".*?")|(\w))'
			lista_str = [lista_str, m.group(2)]
		
# lettura dei legami 
for linea in file_mae:
	m = re.match(str(ricerca),linea)
	if m:
		posa1.AddBond(int(m.group('from')), int(m.group('to')), int(m.group('order')))
		

#os.remove(file_out)


posa1.AddConformer(coordinate) #inserimento delle coordinate del primo conformero
#posa1.DeleteHydrogens()

obConversion.WriteFile(posa1, file_out)



file_mae.close()
La funzione AddConformer si trova verso la fine è il terzultimo comando.

Comunque mi sono fatto l'idea che il problema sia la conversione di una lista od un'altra variabile python in un array C++. Googlando in giro ho visto che è un problema piuttosto diffuso ora vedo se trovo qualcosa. se qualcuno di voi ha delle soluzioni per un problema analogo le accetto volentieri.

edito: Ho provato ad usare struct.pack visto che aveveo letto che struct.unpack poteva convertire array C in liste python  ma senza risultati.
Es:

Codice: Seleziona tutto

>>> import openbabel as OB
>>> import struct
>>> mol = OB.OBMol()
>>> atomo = mol.NewAtom()
>>> mol.AddConformer(struct.pack('3d',4.1,2.5,6.3))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: in method 'OBMol_AddConformer', argument 2 of type 'double *'

Re: "type double" e python

Inviato: martedì 16 settembre 2008, 12:08
da gaspa
I puntatori in C e gli array in python son cose non compatibili tra loro.
Ribadisco che piuttosto che andare a caso, potresti cercare in un forum specifico della tua libreria, oppure mandare una mail  (avra' una maliing list?), oppure guardare codice scritto da altri.

Re: "type double" e python

Inviato: martedì 16 settembre 2008, 12:09
da gaspa
per esempio:
$ apt-cache rdepends python-openbabel
python-openbabel
Reverse Depends:
  science-chemistry

Re: "type double" e python

Inviato: martedì 16 settembre 2008, 12:14
da gaspa
Qua mi pare che usi numpy.array...
guarda se fa al caso tuo.
http://cclib.svn.sourceforge.net/viewvc ... iew=markup