Hi, I have written a number of functions in C++ for structural analysis that I was hoping to interface with Modeller via the Modeller API. Specifically, I want to transfer coordinates backwards and forwards between a 'model' object and an external representation of coordinate data without having to write out a PDB file and then re-read it in in either direction, to avoid slow and unnecessary I/O and string conversion. Is this possible? From the structs in mod_types.h it looks as though it should be, but would it suffice to read and write into mod_model.mod_coordinates and mod_model.mod_sequence (my_model.cd.[x,y,z etc.] and my_model.seq.[irestyp, etc.])? If anyone has some code (in any language) or suggestions about the best way to go about this, I would greatly appreciate it. Thanks! James
Hi all, Apologies for my previous post, it was a bit premature - I've answered my own question, after finding the 'cdpt' member of the python model class (in model.py). It's is a pointer to the mod_coordinates struct in C containing the coordinate information, so I've been able to write a quick C++ function, called from python using the my_model.cdpt pointer, that reads and changes x,y,z coordinates. Provided changes are made sensibly and consistently, is this safe to do? I'm assuming any manipulations at this level would be equivalent to calling model.read() in the presence of existing coordinate data? Thanks, James
2009/1/4 James Irving james.irving@med.monash.edu.au
> Hi, > I have written a number of functions in C++ for structural analysis that I > was hoping to interface with Modeller via the Modeller API. Specifically, I > want to transfer coordinates backwards and forwards between a 'model' object > and an external representation of coordinate data without having to write > out a PDB file and then re-read it in in either direction, to avoid slow and > unnecessary I/O and string conversion. Is this possible? From the structs > in mod_types.h it looks as though it should be, but would it suffice to read > and write into mod_model.mod_coordinates and mod_model.mod_sequence > (my_model.cd.[x,y,z etc.] and my_model.seq.[irestyp, etc.])? If anyone has > some code (in any language) or suggestions about the best way to go about > this, I would greatly appreciate it. > Thanks! > James > >
James Irving wrote: > Apologies for my previous post, it was a bit premature - I've answered > my own question, after finding the 'cdpt' member of the python model > class (in model.py). It's is a pointer to the mod_coordinates struct in > C containing the coordinate information, so I've been able to write a > quick C++ function, called from python using the my_model.cdpt pointer, > that reads and changes x,y,z coordinates. Provided changes are made > sensibly and consistently, is this safe to do? I'm assuming any > manipulations at this level would be equivalent to calling model.read() > in the presence of existing coordinate data?
Yes, that should be fine. Both mod_model and mod_structure (the latter is a template structure in an alignment) contain a mod_coordinates structure that contains the atom coordinates. As you discovered, the Python interface maintains a pointer to this structure internally. There are a couple of points to be aware of though. 1- the arrays are all Fortran pointer arrays, but I guess you already discovered the accessor methods to get to these from C code (e.g. mod_float1_pt, mod_float1_get, mod_float1_set). 2- there are currently no methods available to redimension the model structure, so you can't for example add additional residues or atoms. But you can certainly change the xyz coordinates without worrying about ill effects. Do you have a specific goal in mind? I may be able to suggest additional places to look.
Ben Webb, Modeller Caretaker
Dear Ben,
Thanks very much for your reply, I did find the accessor methods in mod_core.h, thanks. My goal is a very general one - being able to readily interface directly between existing code that I have (or code that I will write) in C++ and the modeller data structures, for repetitive and iterative calculations.
I encountered one pitfall that I did not find a reference to anywhere (there's a bad pun in this I'm sure), which may be implicitly obvious to C programmers but escaped my C++-string oriented brain until I'd reassured myself I wasn't botching reference counting in Python. I was accessing the 'atom type' and 'atom element' members of the mod_coordinates struct using the "mod_coordinates_xxxx_get" methods, and passing this to a C++ string. My humble program was consuming vast quantities of memory. Eventually I realised that this method must be "mallocing" the char* rather than simply returning a reference to static data. So I replaced: string ele = mod_coordinates_atmnam_get(&mod.cd, idx) with char* buf = mod_coordinates_atmnam_get(&mod.cd, idx) string ele=buf free(buf) and this seemed to do the trick.
Am I on the right track? If so, it might be useful to include a comment to this effect either in the API section of the modeller manual or in the header file itself.
Thanks again! James
> I encountered one pitfall that I did not find a reference to anywhere > (there's a bad pun in this I'm sure), which may be implicitly obvious to > C programmers but escaped my C++-string oriented brain until I'd > reassured myself I wasn't botching reference counting in Python. I was > accessing the 'atom type' and 'atom element' members of the > mod_coordinates struct using the "mod_coordinates_xxxx_get" methods, and > passing this to a C++ string. My humble program was consuming vast > quantities of memory. Eventually I realised that this method must be > "mallocing" the char* rather than simply returning a reference to static > data. So I replaced: > string ele = mod_coordinates_atmnam_get(&mod.cd, idx) > with > char* buf = mod_coordinates_atmnam_get(&mod.cd, idx) > string ele=buf > free(buf) > and this seemed to do the trick. > > Am I on the right track? If so, it might be useful to include a comment > to this effect either in the API section of the modeller manual or in > the header file itself.
That is correct - most of the API functions return a malloc'd buffer rather than a pointer to the structures themselves because 1) the actual data is Fortran strings, which are not null-terminated (so we have to make a copy anyway which is) and 2) this should avoid any thread safety problems (although Modeller as a whole has not been well tested for thread safety). In the few cases where a pointer to static data *is* returned, the return type is const char * to indicate that 1) you shouldn't try to write into that data and 2) you don't need to free it.
All of the argument and return types are documented in the main header file, modeller.h.
Ben Webb, Modeller Caretaker
participants (2)
-
James Irving
-
Modeller Caretaker