New python script: Molecules (pdb-format) to Blender

Here comes my first try in blender scripting and python programming.
I just needed a tool for importing 3d molecular models in blender and since I didn’t find one I started programming.

It’s more a wizard than a conversion tool as the pdb-files only provides atom types and positions and connectivity tables. The script builds balls of different sizes for any atom with materials linked to the atom types. When chosen the atoms are connected by sticks with rounded ends.
http://www.malte-reimold.de/blender/images/c60s.jpghttp://www.malte-reimold.de/blender/images/dodecahedranes.jpghttp://www.malte-reimold.de/blender/images/dna2s.jpg
The tool is now working somehow. You can download it at http://www.malte-reimold.de/blender/pdb2blend.html as well as some pdb molecule files for testing purposes for those who are not familiar with molecule models.

I built this script with blender 2.41 and Python 2.4 on WinXP.

Please try the script and give me some feedback about functionality on other platforms or versions.

EDIT: pdb2blend v1.2 is available now! I hope those file format problems are fixed now!
I opened a new thread for v1.2: http://blenderartists.org/forum/showthread.php?t=81711

Sorry for pushing it up again - I changed the whole post and tried to point out more clearly, what this script is all about because I had the impression that I wrote it quite complicated the first time.
I also added some pictures to show how it works…

:smiley: hehehe nice images. I’ve also did some scripts to import PDB to Blender, but mine wouldn’t give that much options !

:stuck_out_tongue: glad to see I am not the only person who see some scientific interest in Blender.

PS : I will try to do some visuals with it. If something get published (you never know…), how would you like to be cited?

Hmmm it looks like it crashes… or it just takes really really long to import your example file.

It also looks like perhaps your 3 example files all link to the same dna.pdb

Perhaps nice to somehow print out some sort of progress in the console?

really nice though… I can see lots of potential for it.

I tried to also run the script on some pdb files from this site: http://sdmc.i2r.a-star.edu.sg/scorpion/Structure/Structure_pdb.pl

but even though it looks like the models are created they are not linked to the scene???

Flashbacks of using RasMol in my chemistry days. ARGH!

Looks good. I can imagine the meshes get quite big for complex molecules.

Any thoughts on things like showing van-der-waals radii?

It’s great that someone else need’s such kind of script too! :slight_smile:

If used in publications, you can cite it as: pdb2blend, Malte Reimold 2006.

Until now only a few atom types are supported (C,H,N,O,P,B) as I needed those but the list can be expanded easily. So if you need other nuclei, just tell me. (I wanted to expand the list anyway)

Atom radii are from literature. It can be discussed, if an option for Van der Waals radii would be interesting too.

However most interesting for me is, if the script works with other pdb files. If some problems arise using other pdb files please send them to me, so I can adjust the import function.

Ok. I corrected the links.

This DNA-file takes a long time when using standard refinement values. Just go to lower refinement values then it doesn’t take so long.
The other two example files are not as big and now the links work.

Does anyone really need VdW radii for visualisation purposes? If so, I would add this functionality…

The meshes are definetly linked to the scene. Sometimes they are far out of focus, and (I don’t know why) the screen does not refresh properly so you have to zoom (or move or change view or whatever) before seeing anything.

For those pdb-files from http://sdmc.i2r.a-star.edu.sg/scorpi…ructure_pdb.pl even hyper chem (a professional program for calculating molecular structures) doesn’t show anything.

I think adding a scene.update(); after adding the objects/meshes should solve the “having to zoom” problem. Just put that in before your Blender.Redraw()

Ah got the c60 molecule to work :wink: nice.

Would it be hard to create your own pdb file… I’d love a c60 shaped mesh with twice the molecules… that’s a basic shape I’ve been looking for… accidentally hehe

[edit] perhaps an option… don’t create a completely new object with a completely new mesh for each molecule/stick, but instead basicly create an object with the same mesh but just a different position/rotation.

That would save on a lot of data and would make it heaps easier to edit the result.[/edit]

Lots of helpful advices. Thanks.
I already tried out the refresh stuff and it works fine.

Is it true that one object can only contain one mesh? I tried to link more than one mesh to one object but then I only maintained the last mesh.
However. For the atoms it would be possible to use one mesh for all atoms of the same kind.
Is it true that material is linked to the mesh? So it is not possible to have different objects with different materials but the same mesh, right?

This is my first try in blender scripting and python programming so my insight into this stuff is not very deep. (and the Python API reference isn’t very helpful I have to say)

However - in the case of sticks they have to be different meshes anyway due to different bond length (they cannot be scaled because then the ends would look deformed).

Understanding Blender will make your job easier, so:

All blender objects have two parts. The Object part contains the location, size, and rotation data. The ObData part contains the geometry data for meshes, metaballs, curves, etc. The OOPS window or Outliner will show you this structure

The Object holds a link to the ObData. Any given ObData may be linked to many Objects. An ObData may hold multiple sets of geometry. ( create a mesh. go into edit mode and add more mesh stuff -> all one thing )

Materials can be linked either to the ObData part or to the Object part. You can have up to 16 materials in the Materials list. See Editing context - F9.

There is only one link

However. For the atoms it would be possible to use one mesh for all atoms of the same kind.

Yes. Multiple Objects can be linked to the same ObData.

So it is not possible to have different objects with different materials but the same mesh, right?

Wrong.

Ok lemme think…

I recently wrote the Caliper script which is something completely different but does also deal with an issue you have.

The Caliper script creates an “arrow” between two points, which is basicly exactly what you’re doing with the struts… you might want to look at the way I did it. Though it’s a completely different approach.

Basicly what I did is:
Since I have 2 points I can figure out where the midpoint is so I create the arrow/strut object there.
Figure out the angle between the two points so that I can rotate the object so that it lines up between the two points.
Find the distance between the two points.
Create the mesh (half on each side of the object) and locate the verts + half the distance (or minus half depending on what side).

Thanks for helping me understanding blender!

The Object holds a link to the ObData. Any given ObData may be linked to many Objects. An ObData may hold multiple sets of geometry. ( create a mesh. go into edit mode and add more mesh stuff -> all one thing )

Works fine in Blender --> and leads to ONE Mesh-datablock. The question is, if I can build up severel sets of Mesh data and add those to an object in a python script?

However - your infos help a lot to optimize the script!

Since I have 2 points I can figure out where the midpoint is so I create the arrow/strut object there.
Figure out the angle between the two points so that I can rotate the object so that it lines up between the two points.
Find the distance between the two points.
Create the mesh (half on each side of the object) and locate the verts + half the distance (or minus half depending on what side).

This is mainly what my script does (in stick mode)! Calculating distances and angles between two connected atoms, building the “pill” of corresponding length (half of it upwards, the other half downwards) at the origin and moving/rotating it to the right position.

Thank you for working on this. I haven’t had the time or skills to work on something like this, but I have been looking for this for along time.

I look forward to seeing how this develops.

Thanks again
Dan

Maybe I misread how to run this script, but I haven’t got it working yet. Trying to import the file doesn’t seem to do anything. Pressing the cancel button just about always returns errors about invalid MVert tuples.

I’ll try again later today with recent cvs. Failing that, I’ll try to debug what is going on.

Aligorith

Just pressing import and choosing a pdb file should work. If not so there is definetly a problem. I can’t interpretate this error message so easily. It seems like the script would start to build up something, becoming stuck somehow.

Did you use the latest blender and python version? If not, please tell me which version you used.

Did you use one of the example pdb-files or did you use another one? In the latter case please send me the pdb file you used. Unfortunatly I had to figure out that this pdb format causes trouble in some cases. Sometimes values are not separated correctly, some values might miss sometimes and so on.

Ok, it was just the old version of Blender I was running it on (2.40). I guess it didn’t run due to a bug in 2.40, that got fixed by 2.41 (i tested it with cvs from early April 2006).

However, it does seem to be quite slow. I’ll have a look to see if there are any bits that can be optimized.

Aligorith

When incrementing counters (such as vcount), doing:
foo += n
is the same as doing
foo = foo + n

Maybe to make it easier to add new types of atoms, the settings for different atoms should be implemented as a dictionary. Getting the necessary things could be as simple as doing a lookup.

As you are using many loops that perform a bit of math on every run, there doesn’t seem to be very much you could do to optimize the speed. That said, you are doing some inefficient stuff in these loops everytime you add some more data.

Dot notation (i.e. me.faces.[somefunction]) is inefficient. To optimize your script, get make references to these functions (to save python having to find them everytime). for example:
currently you have


while b < 360:
   dz = radius*cos(a/90*pi)
   dx = radius*sin(a/90*pi)*sin(b/90*pi)
   dy = radius*sin(a/90*pi)*cos(b/90*pi)
   b = b + db
   me.verts.extend(dx, dy, dz)
   vcount = vcount + 1
   if vcount > 1:
      me.faces.extend([me.verts[0],me.verts[vcount],me.verts[vcount-1]])
    
   me.faces.extend([me.verts[0],me.verts[1],me.verts[vcount]])

this could be better written as (haven’t checked whether it actually works, but theoretrically it does)


mfcs = me.faces # me.faces
mvts = me.verts # me.verts

while b < 360:
   dz = radius*cos(a/90*pi)
   dx = radius*sin(a/90*pi)*sin(b/90*pi)
   dy = radius*sin(a/90*pi)*cos(b/90*pi)
   b += db
   mvts.extend(dx, dy, dz)
   vcount +=1
   if vcount > 1:
      mfcs.extend([mvts[0],mvts[vcount],mvts[vcount-1]])
    
   mfcs.extend([mvts[0],mvts[1],mvts[vcount]])

Aligorith

Thanks for looking through the script. Your suggestions will be implemented in the next release!

Keep working on this. This is great stuff.

Some people I have been working for have been tearing their hair out trying to create accurate mollecular models for a medical client in 3dsMax. Importing the pdb into Blender and then exporting as a .obj (with materials!) and importing to Max just made things a lot simpler.

+1 For open source! :smiley: