PerlMol - Example: PDB viewer
PDB viewer using OpenGL
Taken from OpenGL-Simple-Viewer-0.03 by Jonathan Chin.
Based on an example by Simon Cozens, published on The Perl Journal (Cozens, S. Molecular Biology With Perl. The Perl Journal 2004, 8[8], 15-19).
Note: this requires additonal modules such as OpenGL::Simple::Viewer, which may not be easy to install (I have only been able to make it work under Linux). The code itself is more useful as an OpenGL tutorial than as a PerlMol tutorial, but I include it as it may be of interest to PerlMol users.
Files
- pdbviewer.pl - the program
- example.pdb - sample file
Code
#!/usr/bin/env perl # Adapted from an original script by Simon Cozens. use strict; use warnings; use OpenGL::Simple qw(:all); use OpenGL::Simple::GLUT qw(:all); use OpenGL::Simple::Viewer; use Chemistry::File::PDB; use Chemistry::Bond::Find ':all'; my ($mass_scale,$sphericity) = (10,20); my %colour = ( red => [ 1, 0, 0, 1 ], yellow => [ 1, 1, 0, 1 ], orange => [ 1, 0.5, 0, 1 ], green => [ 0, 1, 0, 1 ], cyan => [ 0, 1, 1, 1 ], blue => [ 0, 0, 1, 1 ], magenta => [ 1, 0, 1, 1 ], grey => [ 0.5, 0.5, 0.5, 1 ], white => [ 1, 1, 1, 1 ], ); my %ccache; my @colours = values %colour; my $iter = 0; my %element_colours = ( C => $colour{grey}, O => $colour{red}, N => $colour{blue}, H => $colour{white}, S => $colour{yellow}, P => $colour{orange}, ); my @ballpoints = (); my @ballsticks = (); $|=1; my $filename = shift or die("Need PDB filename"); print "Reading molecule.."; my $mol = Chemistry::MacroMol->read($filename); print " finding bonds.."; find_bonds($mol); print " done.\n"; my $displaylist; glutInit; my $v = new OpenGL::Simple::Viewer( title => 'PerlMol', draw_geometry => sub { if (!$displaylist) { build_displaylist(); } glCallList($displaylist); }, screenx => 512, screeny => 512, ); glClearColor(1,1,1,1); glutMainLoop; exit 0; sub recenter { my @center; my @atoms = $mol->atoms; for (@atoms) { my @coords = $_->coords->array; $center[$_] += $coords[$_] for 0..2; } $center[$_] /= @atoms for 0..2; my $center_v = Math::VectorReal->new(@center); for (@atoms) { $_->coords($_->coords - $center_v) } } sub make_model { my $i = 0; recenter(); my @atoms = $mol->atoms; for my $atom ( @atoms ) { my $mass = log( 1 + $atom->mass ) / $mass_scale; my $color = $element_colours{ $atom->symbol } || $colour{cyan}; my @coords = $atom->coords->array; push @ballpoints, [ $color, $mass, @coords ]; } for my $bond ( $mol->bonds ) { my ( $from, $to ) = $bond->atoms; my @from = $from->coords->array; my @to = $to->coords->array; push @ballsticks, [ \@from, \@to ]; } } sub visualize { if ( !@ballpoints ) { make_model() } for (@ballpoints) { my ( $color, $mass, @coords ) = @$_; glColor(@$color); glPushMatrix; glTranslate(@coords); glutSolidSphere( $mass , $sphericity, $sphericity); glPopMatrix; } glColor( @{ $colour{'grey'} } ); glLineWidth(4); for (@ballsticks) { glBegin(GL_LINES); glVertex(@$_) for @$_; glEnd; } } sub build_displaylist { $displaylist = glGenLists(1); glNewList($displaylist,GL_COMPILE); visualize(); glEndList(); }