Changes

Jump to: navigation, search

PatternQuery:Principles

19 bytes added, 13:45, 25 April 2015
no edit summary
'''A new paradigm for describing structural fragments patterns in molecules'''
This text describes the basic principles of the '''MotiveQueryPatternQuery''' language for describing structural fragments patterns in molecules. First, the text puts two approaches for identifying molecular fragments patterns in contrast: the imperative approach, and the declarative one, taken by the '''MotiveQueryPatternQuery''' language. Next, basic principles of the language are illustrated on several examples and later described in a more formal way. Finally, the original example is revisited and explained in the terms of the newly introduced concepts.
==Example, Part One==
</syntaxhighlight>
Internally, the function <code>[[MotiveQueryPatternQuery:Language_Reference#AmbientAtoms | AmbientAtoms()]]</code> might run code similar to the imperative version. However, what is important is that this complexity is hidden from the user when the declarative approach is used.
Now, let’s extend our example even further: "all HET residues and atoms within 4A around them, where the entire structure contains at least one calcium atom".
We will not bother the reader with writing down the imperative version - implementing the condition "at least one calcium atom" is rather boring. However, using the declarative approach, the description of the fragment pattern becomes simply:
<syntaxhighlight lang="python">
===Intuitive Description===
As we've seen in the example above, it is very easy to ''compose'' our ideas about the final shape of the fragment pattern we are interested in. The way this works is that the input molecule is decomposed into a stream of fragmentspatterns. These streams can then be modified and combined into new streams, which can be modified and combined again.
As an example, take the query <code>Atoms('Ca')</code>. What the '''MotiveQueryPatternQuery''' language does is to extract all calcium atoms from the input molecule and represent them as a stream of sets containing one atom each as illustrated on the image below:
[[Image:MotiveQueryPatternQuery-Principles Atoms(Ca).png|center|600px]]
Now, each element of this stream can be modified, for example to include all atoms 4A within the original calcium atom. Now we have a stream of sets of atoms, where each set contains the original Ca atom and the atoms within the given radius. This would be represented by the query <code>Atoms('Ca').AmbientAtoms(4)</code> and is illustrated on the image bellow:
[[Image:MotiveQueryPatternQuery-Principles Atoms(Ca) surr.png|center|600px]]
In the next step, we might wish to keep only these fragments patterns that contain at least 6 atoms. This is achieved by looking at each fragmentpattern, counting the number of atoms and throwing away these fragments patterns that do not meet the criteria. Written as a query, this could be represented as <code>Atoms('Ca').AmbientAtoms(4).Filter(lambda m: m.Count(Atoms()) >= 6)</code>. In the graphical form:
[[Image:MotiveQueryPatternQuery-Principles Atoms(Ca) surr filt.png|center|600px]]
The previous filter query also demonstrates another interesting concept of the language: the ability to identify fragments patterns within fragmentspatterns, which is what the expression <code>m.Count(Atoms())</code> does - the <code>[[MotiveQueryPatternQuery:Language_Reference#Atoms | Atoms()]]</code> query is executed for each fragment pattern from the original input sequence provided by the expression <code>Atoms('Ca').AmbientAtoms(4)</code>, and creates a new sequence of fragments patterns that each contain a single atom. Then the Count function takes over and returns the number of fragments patterns produced by its argument. In this way, the query <code>[[MotiveQueryPatternQuery:Language_Reference#Atoms | Atoms()]]</code> inside the Count function can be replaced by any function that also produces a sequence of fragmentspatterns, for example <code>[[MotiveQueryPatternQuery:Language_Reference#Rings | Rings()]]</code>.
Finally, streams of fragments patterns can be combined. For example, let’s say we want to find all pairs of calcium atoms that are no further than 4A within each otherapart. This can be achieved using the query <code>Near(4, Atoms('Ca'), Atoms('Ca'))</code>. So this query takes as the input two identical streams of calcium atoms and for each pair of them determines if the atoms are closer than 4A to each other. For each pair that satisfies this condition, a new fragment pattern from the 2 atoms is created. Therefore, the result of the above <code>[[MotiveQueryPatternQuery:Language_Reference#Near | Near()]]</code> query is a stream of sets of atoms (fragmentspatterns) that each contain two calcium atoms that are no further than 4A from each other:
[[Image:PatternQuery-Principles-Near.png|center|600px]] With these basic types queries outline in the previous paragraphs, the sky's the limit. Due to the composable nature of the language if a new type of motif emerges, only a single function needs to be added to the language for it to work with all its other parts. As an example, assume we didn’t know that proteins had secondary structure called “sheet” and we just discovered it and a fancy algorithm to identify these "sheets". Now we would be interested in how this new type of protein substructure interacts with other parts of the molecule. All that would be needed is to add a function called <code>[[MotiveQuery:Language_Reference#Sheets | Sheets()]]</code> to the language and immediately we would be able to analyze and filter it’s neighborhood using the functions <code>[[MotiveQuery:Language_Reference#AmbientAtoms | AmbientAtoms()]]</code> and <code>[[MotiveQuery:Language_Reference#Filter | Filter()]]</code>.
With these basic types of queries outlined in the previous paragraphs, the sky's the limit. Due to the composable nature of the language if a new type of pattern emerges, only a single function needs to be added to the language for it to work with all its other parts. As an example, assume we didn’t know that proteins had secondary structure called “sheet” and we just discovered it and a fancy algorithm to identify these "sheets". Now we would be interested in how this new type of protein substructure interacts with other parts of the molecule. All that would be needed is to add a function called <code>[[PatternQuery:Language_Reference#Sheets | Sheets()]]</code> to the language and immediately we would be able to analyze and filter it’s neighborhood using the functions <code>[[PatternQuery:Language_Reference#AmbientAtoms | AmbientAtoms()]]</code> and <code>[[PatternQuery:Language_Reference#Filter | Filter()]]</code>.
===A More Formal Description===
There are two basic data structures that the language is built upon. These are:
* '''FragmentPattern'''. A fragment pattern is simple simply an arbitrary set of atoms.* '''Fragment Pattern Sequence'''. A sequence of fragmentspatterns. In mathematical terms, can be understood as a "set of fragmentspatterns" which is another way of saying "set of sets of atoms".
And on these data structures, there are three basic types of queries:
* '''Generator queries'''. Generator queries, as the name suggests, generate sequences of fragments patterns from the original input. They are the tool that transforms the input molecule into a stream of fragments patterns that can be later modified or combined. Examples of these queries include <code>[[MotiveQueryPatternQuery:Language_Reference#Atoms | Atoms()]]</code>, <code>[[MotiveQueryPatternQuery:Language_Reference#Residues | Residues()]]</code>, and <code>[[MotiveQueryPatternQuery:Language_Reference#RegularMotifs | RegularMotifs()]]</code>.* '''Modifier queries'''. These queries operate on individual fragments patterns and modify them or throw them away. Examples include <code>[[MotiveQueryPatternQuery:Language_Reference#AmbientAtoms | AmbientAtoms()]]</code>, <code>[[MotiveQueryPatternQuery:Language_Reference#ConnectedResidues | ConnectedResidues()]]</code>, and <code>[[MotiveQueryPatternQuery:Language_Reference#Filter | Filter()]]</code>.* '''Combinator queries'''. Combinatorial queries take as input two or more sequence of fragments patterns and combine them into a single new sequence that satisfies given criteria. Examples include <code>[[MotiveQueryPatternQuery:Language_Reference#Or | Or()]]</code>, <code>[[MotiveQueryPatternQuery:Language_Reference#Near | Near()]]</code>, and <code>[[MotiveQueryPatternQuery:Language_Reference#Path | Path()]]</code>.
==Example, Revised==
This corresponds to the following process.
# A generator query <code>[[MotiveQueryPatternQuery:Language_Reference#HetResidues | HetResidues()]]</code> is executed that produces a sequence of fragments patterns that are composed of atoms corresponding to HET residues.# Next, the original sequence is modified by adding atoms within 3 angstrom from any original atom to each fragmentpattern.# Finally, each fragment pattern in the modified sequence is examined: all “calcium atom fragments” patterns” are identified and counted. Only these fragments patterns that contain at least 1 Ca atom are kept.
Graphically:
<code>[[MotiveQueryPatternQuery:Language_Reference#HetResidues | HetResidues()]]</code>[[Image:MotiveQueryPatternQuery-Principles-HetResidues.png|none|500px]]
<code>[[MotiveQueryPatternQuery:Language_Reference#AmbientAtoms | .AmbientAtoms(3)]]</code>[[Image:MotiveQueryPatternQuery-Principles-AmbientAtoms.png|none|500px]]
<code>[[MotiveQueryPatternQuery:Language_Reference#Filter | .Filter(lambda l: l.Count(Atoms('Ca')) > 0)]]</code>[[Image:MotiveQueryPatternQuery-Principles-AmbientAtoms-filter.png|none|500px]]

Navigation menu