Chemistry-MidasPattern
view release on metacpan or search on metacpan
lib/Chemistry/MidasPattern.pm view on Meta::CPAN
package Chemistry::MidasPattern;
$VERSION = '0.11';
# $Id: MidasPattern.pm,v 1.3 2005/05/16 23:03:37 itubert Exp $
=head1 NAME
Chemistry::MidasPattern - Select atoms in macromolecules
=head1 SYNOPSIS
use Chemistry::MidasPattern;
use Chemistry::File::PDB;
# read a molecule
my $mol = Chemistry::MacroMol->read("test.pdb");
# define a pattern matching carbons alpha and beta
# in all valine residues
my $str = ':VAL@CA,CB';
my $patt = Chemistry::MidasPattern->new($str);
# apply the pattern to the molecule
$patt->match($mol);
# extract the results
for my $atom ($patt->atom_map) {
printf "%s\t%s\n", $atom->attr("pdb/residue_name"), $atom->name;
}
printf "FOUND %d atoms\n", scalar($patt->atom_map);
=head1 DESCRIPTION
This module partially implements a pattern matching engine for selecting atoms
in macromolecules by using Midas/Chimera patterns. See
L<http://www.cmpharm.ucsf.edu/~troyer/troff2html/midas/Midas-uh-3.html#sh-2.1>
for a detailed description of this language.
This module shares the same interface as L<Chemistry::Pattern>; to perform a
pattern matching operation on a molecule, follow these steps.
1) Create a pattern object, by parsing a string. Let's assume that the pattern
object is stored in $patt and that the molecule is $mol.
2) Execute the pattern on the molecule by calling $patt->match($mol).
3) If $patt->match() returns true, extract the "map" that relates the pattern
to the molecule by calling $patt->atom_map. These method returns a list of the
atoms in the molecule that are matched by the pattern. Thus $patt->atom_map(1)
would be analogous to the $1 special variable used for regular expresion
matching. The difference between Chemistry::Pattern and Perl regular
expressions is that atoms are always captured, and that each atom always uses
one "slot".
=head1 MIDAS ATOM SPECIFICATION LANGUAGE QUICK SUMMARY
The current implementation does not have the concept of a model, only of
residues and atoms.
What follows is not exactly a formal grammar specification, but it should give
a general idea:
SELECTOR = ((:RESIDUE(.CHAIN)?)*(@ATOM)*)*
The star here means "zero or more", the question mark means "zero or one", and
the parentheses are used to delimit the effect of the star. All other
characters are used verbatim.
RESIDUE can be a name (e.g., LYS), a sequence number (e.g., 108), a range
(e.g., 1-10), or a comma-separated list of RESIDUEs (e.g. 1-10,6,LYS).
ATOM is an atom name, a serial number (this is a non-standard extension) or a
comma-separated list of ATOMs.
Names can have wildcards: * matches the whole name; ? matches one character;
and = matches zero or more characters. An @ATOM specification is asociated with
the closest preceding residue specification.
DISTANCE_SELECTOR = SELECTOR za< DISTANCE
Atoms within a certain distance of those that are matched by a selector can be
selected by using the za< operator, where DISTANCE is a number in Angstroms.
EXPR = ( SELECTOR | DISTANCE_SELECTOR ) (& (SELECTOR | DISTANCE_SELECTOR))*
The result of two or more selectors can be intersected using the & operator.
=head1 EXAMPLES
:ARG All arginine atoms
:ARG.A All arginine atoms in chain 'A'
:ARG@* All arginine atoms
@CA All alpha carbons
:*@CA All alpha carbons
:ARG@CA Arginine alpha carbons
:VAL@C= Valine carbons
:VAL@C? Valine carbons with two-letter names
:ARG,VAL@CA Arginine and valine alpha carbons
:ARG:VAL@CA All arginine atoms and valine alpha carbons
:ARG@CA,CB Arginine alpha and beta carbons
:ARG@CA@CB Arginine alpha and beta carbons
:1-10 Atoms in residues 1 to 10
:48-* Atoms in residues 11 to the last one
:30-40@CA & :ARG Alpha carbons in residues 1-10 which are
also arginines.
@123 Atom 123
@123 za<5.0 Atoms within 5.0 Angstroms of atom 123
@123 za>30.0 Atoms not within 30.0 Angstroms of atom 123
@CA & @123 za<5.0 Alpha carbons within 5.0 Angstroms of atom 123
=cut
use strict;
use warnings;
use Chemistry::MacroMol;
use Carp;
use base "Chemistry::Pattern";
our $DEBUG = 0;
sub new {
my ($class, $str) = @_;
my $self = bless {
atom_map => [],
options => {},
matched => 0,
name => $str,
}, ref $class || $class;
$self->parse_midas_pattern($str);
$self;
}
sub atom_map {
my ($self) = @_;
@{$self->{atom_map}};
}
sub bond_map { () }
sub options {
my $self = shift;
$self->{options} = {@_};
$self;
}
# residue specifier: name | range | number | *
# atom specifier: name | number | *
# names may have ? and = as wildcards (equivalent to . and .*)
sub parse_midas_pattern {
my ($self, $string) = @_;
my $tree = [];
$self->{tree} = $tree;
for my $str (split / +& +/, $string) {
my $node = { type => 'normal' };
if ($str =~ s/ +z(.?)([<>])\s*(\d+(\.\d+)?)//) {
$node->{type} = 'zone_' . ($1 || 'r');
$node->{zone_op} = $2;
$node->{zone_val} = $3;
}
push @$tree, $node;
my $conditions = [];
$node->{conditions} = $conditions;
$str =~ s/\s+//g; # ignore whitespace
$str = ":*$str" unless $str =~ /^:/; # add implicit "every residue"
my (undef, @residues) = split ':', $str;# =~ /:([^:]+)/g;
for my $residue (@residues) {
my ($res_base, $atom_base) = split '@', $residue, 2;
#print "res_base = $res_base\n";
my @res = map { parse_res($_) } split ',', $res_base;
my $res_node = { residue => \@res };
push @$conditions, $res_node;
my (@atoms) = map { parse_atom($_) } split /[\@,]/, $atom_base||'*';
( run in 0.340 second using v1.01-cache-2.11-cpan-39bf76dae61 )