diff --git a/modules/doc/intro-01.rst b/modules/doc/intro-01.rst new file mode 100644 index 0000000000000000000000000000000000000000..2b0f969e77a0936840e864a48e5c50be17366bdc --- /dev/null +++ b/modules/doc/intro-01.rst @@ -0,0 +1,226 @@ +Introduction to the :mod:`~ost.mol` Module +================================================================================ + +For the course of this tutorial, we assume that you have :ref:`DNG up and running<start-dng>`. + +Loading and inspecting a protein structure +-------------------------------------------------------------------------------- + +The code to load and save structures is not directly part of the mol module, but rather lives in a module dedicated to input and output of any kind of data: The +:mod:`~ost.io` module. We will be using functions if this module to load +structures. + +One of the most commonly used file formats for macromolecular structures are PDB +(Brookhaven Protein Databank) files. The official name for molecules stored in +a PDB file is an *entity* and we decided to follow this convention in +OpenStructure. You will hear this word all the time, but you can replace the +word entity with molecule (or most of the time even protein) in your head. + + +To load a PDB file, simply type + +.. code-block:: python + + fragment=io.LoadPDB('/path/to/examples/entity/fragment.pdb') + +This will load the fragment from the specified file 'fragment.pdb' and store the +result in fragment. The :func:`~ost.io.LoadPDB` has many option, which, for +simplicity will not be discussed here. If you want to know more about the +function, type: + +.. code-block:: python + + help(io.LoadPDB) + +or read the :func:`online documentation <ost.io.LoadPDB>`. + +The loaded structure is an instance of :class:`~ost.mol.EntityHandle` which offers a comprehensive interface to inspect an manipulate molecular structures. Now let's inspect what we just loaded: + +.. code-block:: python + + print len(fragment.chains), fragment.chains + print len(fragment.residues), fragment.residues + print len(fragment.atoms), fragment.atoms + +As you can see, our fragment consists of one peptide chain of 12 amino acids and +has 81 atoms in total. Now let's examine our fragment in more detail. Enter the +command + +.. code-block:: python + + for residue in fragment.residues: + print residue, 'has', len(residue.atoms), 'atom(s).' + for atom in residue.atoms: + print ' ', atom.name, atom.pos + + +This will group the atoms by residue. And, for completeness, we will first group them by chain, then by residues. + +.. code-block:: python + + for chain in fragments.chains: + print 'chain', chain.name, 'has', len(chain.residues), 'residue(s)' + for residue in chain.residues: + print ' ', residue, 'has', len(residue.atoms), 'atom(s).' + for atom in residue.atoms: + print ' ', atom.name, atom.pos + +A protein fragment would not be complete without bonds: Let's see +what bonds we have in there: + +.. code-block:: python + + for bond in fragment.bonds: + print bond + +From these short code examples we already see how the entity is structured: On +one hand we have a hierarchy of chains, residues and atoms. On the other hand, +we have bonds that form a network overlayed on the hierarchy. This is +illustrated in the picture on the left. An important feature of entities is that +we can always assume that the hierarchy is intact. You will never find an atom +without residues, no residue can exist without a parent chain and chains belong +always to an entity. + +Let There Be Shiny Graphics +-------------------------------------------------------------------------------- + +For visually inspecting the fragment, we now create a graphical representation +of the entity. The graphical representation os completely separate from the :class:`~ost.mol.EntityHandle` class. This is on purpose. When writing processing scripts, usually no graphical representation is required and things would be slowed down without any reason. The following code will take our fragment and initialise a :class:`gfx.Entity<ost.gfx.Entity>`, add it to the scene, and center the camera on it. + +.. code-block:: python + + go=gfx.Entity("Fragment", fragment) + scene.Add(go) + scene.CenterOn(go) + + +Now you will see the fragment in the 3D window. + +Use the mouse to rotate, zoom in an shift the camera. Double clicking on an atom +will center the camera on that atom. If you want to learn more about the +:mod:`~ost.gfx` module, you are encouraged to read :doc:`the gfx +intro<intro-03>` and the :mod:`gfx documentation<ost.gfx`. + +Introduction to Views +-------------------------------------------------------------------------------- + +Often during processing and visualisation of data, only parts of a protein +structure are of interest. This realisation has had a major impact on the design +of OpenStructure and is tied very deeply into the core of the framework. +Subparts of structure are modeled as so-called :class:`EntityViews +<ost.mol.EntityView>`. You can think of them as a selection of chains, residues, +atoms and bonds of an entity. A views has almost the same interface as the +underlying entity, making it very easy to mix entity views with handles in +Python due to the dynamic nature of the language. An algorithm that is written +for entities will almost always (with some care) also work for +:class:`EntityHandles <ost.mol.EntityHandle>`. This is referred to as +`duck-typing <http://en.wikipedia.org/wiki/Duck_typing>`_ (I don' t care if it +is a duck as long as it looks like a duck), a concept used all over the place in Python. + +The view consists of one chain, one residue and two atoms. Again the same rule +applies: No atom can be part of the view without it's residue. In this example, +no bonds are included, since there is at most one atom per bond in the original structure. + +To familiarize yourself with the concept of views, we will use the fragment in +the 3D window. + +We will use several ways to select parts of our fragment: + * By using a dedicated query language + * By manually constructing a view + +The Query Language +-------------------------------------------------------------------------------- + +The first way to select parts of a structure is with a dedicated mini-language, +called :doc:`the query language <mol/base/query>`. In the Python Shell, type + +.. code-block:: python + + go.selection=fragment.Select('') + +The code performs a selection on the fragment and assigns the resulting view to +the selection of the graphical object. A green halo will be displayed around the +selected parts (image in the middle). + +.. image:: sel.png + +As you can see the previous statement created a “full view”, containing all the +chains, residues, atoms and bonds. To select lysine residues, type + +.. code-block:: python + + go.selection=fragment.Select('rname=LYS') + + +As you can see (image on the right), the only lysine residue is now +highlighted in the 3D window, because it was the only one matching the predicate +"residue name must be equal to LYS". Several such predicates can be combined +with boolean operators such as *and* and *or*. To select residues with residue +number 1 to 3, the following statement will do the job: + +.. code-block:: python + + go.selection=fragment.Select('rnum>=1 and rnum<=3') + +but this is very cumbersome. That's why there is a shortcut to this statement. +You can specify a range of values. + +.. code-block:: python + + go.selection=fragment.Select('rnum=1:3') + +For a complete description of what you can do with the query language, have a +look at the :doc:`../mol/base/query`. + + +Constructing Views Manually +-------------------------------------------------------------------------------- + +Sometimes the query language Is Not Enough (TM). For these cases the +construction of manual entities becomes neccessary. This is pretty straight +forward: + +.. code-block:: python + + view=fragment.CreateEmptyView() + ca=fragment.FindAtom('A', mol.ResNum(1), 'CA') + cb=fragment.FindAtom('A', mol.ResNum(1), 'CB') + view.AddAtom(ca) + view.AddAtom(cb) + go.SetSelection(view) + +The last step sets our constructed view as the current selection, displaying it +in the 3D window. As you can see, C-alpha and C-beta of the first residue are +not connected by bonds, even though both atoms are in the view. You have either +to add the bond manually with + +.. code-block:: python + + ca_cb=ca.FindBondToAtom(cb) + view.AddBond(ca_cb) + +Or, as a very convenient shortcut +:meth:`view.AddAllInclusiveBonds()<ost.mol.EntityView.AddAllInclusiveBonds>` to +add all bonds that have both bonding partners in the view. + +Don't forget to update the selection of the graphics object to see what view you +have created. + +Saving an Entity +-------------------------------------------------------------------------------- + +Saving an entity (or a view) is a breeze: + +.. code-block:: python + + io.SavePDB(fragment, 'full.pdb') + +will save the full fragment. To save only the backbone atoms, we can first +select the backbone atoms and then save it: + +.. code-block:: python + + io.SavePDB(fragment.Select('aname=CA,C,N,O'), 'backbone.pdb') + +That's it for the mol module. Continue with :doc:`part two<intro-02>` of the +tutorial. diff --git a/modules/doc/intro-02.rst b/modules/doc/intro-02.rst new file mode 100644 index 0000000000000000000000000000000000000000..bfca96383d629ade80f7aecfb048d968b44444cc --- /dev/null +++ b/modules/doc/intro-02.rst @@ -0,0 +1,92 @@ +Introduction to the :mod:`~ost.img` Module +================================================================================ + +For the course of this tutorial, we assume that you have :ref:`DNG up and running<start-dng>`. + + +Loading Images and Density Maps +-------------------------------------------------------------------------------- + +Openstructure features a :mod:`~ost.img` module that is dedicated to the +manipulation of images/density maps. The images or density maps can either be +one-, two- or three-dimensional. The most common formats used in X-ray and +electron crystallography and atomic force microscope are supported in addition +to several general purpose image formats. See `supported file formats` for +details. The :mod:`~ost.img` module was originally developed as part of the +Image Processing Library & Toolbox IPLT. More documentation and examples can +also be found on the `IPLT website <http://www.iplt.org>`_. + +To load a density map, type + +.. code-block:: python + + map=io.LoadImage('/path/to/examples/map/1ppt.map') + +This will load the fragment density map from the specified file 'fragment.map' +and store the result in map. + +Now let's inspect what we just loaded: + +.. code-block:: python + + print map.GetPixelSampling(), map.GetSize() + +We can see that the sampling is set to 1.0 Angstroems in all three dimensions. The loaded map is an instance of :class:`~ost.img.ImageHandle`, a class to represent images in 1, 2 and 3 dimensions. + +Manipulating Images and Density Maps +-------------------------------------------------------------------------------- + +The algorithms used for manipulation of an image are found in the +:mod:`img.alg <ost.img.alg>` module. Therefore before using an algorithm we +first have to import the :mod:`img.alg <ost.img.alg>` module. + +.. code-block:: python + + from ost.img import alg + + +The :mod:`img.alg <ost.img.alg>` module provides a wide range of algorithm to +manipulate image data. Here for example we use a LowPassFilter to restrict the +resolution of the density map to frequencies lower than a treshold. + +.. code-block:: python + + map_filtered=map.Apply(alg.LowPassFilter(3.0)) + +The filtered map is stored in a new variable called `fragment_map_filtered`. A complete list of algorithms is available on the :doc:`img/alg/alg` page. + + +Displaying Images and Density Maps +-------------------------------------------------------------------------------- + +Now that we have a filtered map it's time to have a look at it. There are +fundamentally two ways to visualize 3-dimensional density maps. One is by +drawing isocontour surfaces. These are conceptually similar to contour lines +used in cartography: every point on an isosurface has the same density value. +Isosurfaces are easy to create in OpenStructure: + +.. code-block:: python + + go=gfx.MapIso("filtered", map_filtered,0.5) + scene.Add(go) + +The other way to visualize a 3-dimensional map is by showing one 2-dimensional +density slice at a time, allowing the user to move through the slices. In +OpenStructure this is achieved using a DataViewer :doc:`gui/image-viewer`). +A DataViewer showing the filtered map is created using the following command: + +.. code-block:: python + + gui.CreateDataViewer(map_filtered) + +This command displays a panel showing one slice of the density map lying on a +particular (x,y) plane in the coordinate reference system. +The `z` and `x` keys can be used to move to slices lying at a lower or higher +coordinate along the `z` axis, allowing the examination of +the full 3-dimensional volume. + +A more detailed explanation of the :mod:`~ost.img` module can be found in the +tutorial section for :mod:`~ost.img`. + + +Continue with :doc:`part three <intro-03>` of the tutorial. diff --git a/modules/doc/intro-03.rst b/modules/doc/intro-03.rst new file mode 100644 index 0000000000000000000000000000000000000000..5a6fc08aa7a7f8bdffb2248e2975f6d491d518c9 --- /dev/null +++ b/modules/doc/intro-03.rst @@ -0,0 +1,179 @@ +Introduction to the :mod:`~ost.gfx` Module +================================================================================ + +.. currentmodule:: ost.gfx + +For the course of this tutorial, we assume that you have :ref:`DNG up and +running<start-dng>`. + +As already mentioned in the :doc:`intro-01`, the basic representation of +molecular structures, sequences, images are completely independent from the +graphical rendering. Thus, to display it on the screen, we first have to create +a graphical representation of the object. This is illustrated for the entity +below, but follows a similar scheme for density maps, surfaces and other types +of data. + +.. code-block:: python + + pdb=io.LoadPDB('/path/to/molecule.pdb') + go=gfx.Entity('PROTEIN', pdb) + scene.Add(go) + scene.CenterOn(go) + +The last command is not mandatory, but very convenient to center the camera on the object. + + +The :class:`~ost.gfx.Scene` +-------------------------------------------------------------------------------- + + +The scene is the central registry for graphical objects and manages rendering +parameters. Among other parameters, it is used to setup the lighting, fog, +background color and the camera. The scene is a singleton, meaning that there is +only one scene available. The instance can be accessed via :func:`gfx.Scene`. +Because the scene is so important and commonly used, the scene is also available +as the `scene` variable in the interactive python shell as well as from scripts. +In fact, this is the preferred way to use functionality of the scene. As an easy example, let's change the background color: + +.. code-block:: python + + scene.background=gfx.WHITE + +Now, the color of the screen has changed to white. To set it back to black, simply assign :obj:`gfx.BLACK` to the background property. + +Objects are added to the scene by calling :meth:`Scene.Add`. Once added to the +scene, the objects will be rendered automatically. Since all the graphical +objects have a name that identifies them, they can be retrieved by name and +manipulated: + +.. code-block:: python + + # retrieving the previously added protein + obj=scene['PROTEIN'] + # set color of the protein to red + obj.SetColor(gfx.RED) + + +The last command assigns a uniform red coloring to all atoms. + + +The :class:`Graphical Entity <ost.gfx.Entity>` +-------------------------------------------------------------------------------- + +Now let's look at the graphical entity in more detail. The graphical entity is +responsible for the rendering of :class:`~ost.mol.EntityHandle` and +:class:`~ost.mol.EntityView` instances. + +Render Modes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Molecules are rendered in :ref:`different representations <render-mode>`. Some +representations show the structure at atomic detail (connectivity level display +styles), while others simplify the structure significantly (trace-based display +styles). + +To change the display mode of an entity programmatically, use the :meth:`Entity.SetRenderMode` method: + +.. code-block:: python + + # render the molecule with an interpolated line trace + obj.SetRenderMode(gfx.SLINE) + # switch back to simple line rendering + obj.SetRenderMode(gfx.SIMPLE) + # switch to helix-strand-coil cartoon + obj.SetRenderMode(gfx.HSC) + +It is also possible to change the render mode of only a part of the structure. +To display the ligand with balls and sticks and everything else in cartoon mode, +we make use of the query language to select everything that is not part of the +protein. Remember from above, that we stored our molecule in the `pdb` variable. + +.. code-block:: python + + not_protein=pdb.Select('peptide=false') + obj.SetRenderMode(gfx.HSC) + obj.SetRenderMode(gfx.CUSTOM, not_protein) + + +The Basics of Coloring +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The color of each atom can be set individually. The simplest coloring scheme is +to set all atoms to the same color: + +.. code-block:: python + + obj.SetColor(gfx.YELLOW) + +Assigning colors based on selections is also possible. To reproduce the +well-known `CPK coloring <http://en.wikipedia.org/wiki/CPK_coloring>`_, 4 +consecutive coloring operations are sufficient: + +.. code-block:: python + + obj.SetColor(gfx.WHITE, 'ele=C') + obj.SetColor(gfx.BLUE, 'ele=N') + obj.SetColor(gfx.RED, 'ele=O') + obj.SetColor(gfx.YELLOW, 'ele=S') + + +But because this is such a common task, the entity provides a built-in method to color the atoms by element: + +.. code-block:: python + + obj.ColorByElement() + +As already seen above, the coloring operations can be chained to achieve the desired effect. For example, sometimes one wants to apply conventional CPK coloring to the protein and then change the color of C-alpha atoms to pink: + +.. code-block:: python + + obj.ColorByElement() + obj.SetColor(gfx.Color(1, 0, 1), 'aname=CA and ele=C') + + + +Internally, the chain of calls to the coloring methods is stored as a list of +coloring operations that is reapplied sequentially. This makes sure that the +coloring remains when changing render modes or updating the geometry of the +molecule. This storage scheme has one drawback. Consider the following code: + +.. code-block:: python + + for i in range(100): + obj.SetColor(gfx.RED) + +While the code obviously achieves the desired effect, it is far for optimal +because all of the 100 color operations are applied every time the graphical +entity needs an update. When you see a slow down in rendering after playing +around with the coloring operations, consider calling +:meth:`Entity.ClearColorOps` and reapply only the set of coloring operations +that are required to achieve your rendering. + +Coloring the Entity By Property +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The most complex but also most powerful coloring method is +:meth:`Entity.ColorBy`, which allows to color atoms by a numeric property. This +property can either be built-in a property such as atomic b-factor, charge, +residue number or be :doc:`custom properties <../base/generic>` assigned by the +user or an algorithm and be defined at any level (chain, residue, atom). The +naming of the built-in properties is identical to the properties available in +:doc:`query language <../mol/base/query>`. For example, to achieve a heat-map +coloring for b-factors: + +.. code-block:: python + + # will color the atoms by the atomic b-factor, setting atoms with + # a temperature factor of 0 to blue and atoms with a temperature factor of + # 100 and higher to red. Values in between are linearly interpolated. + obj.ColorBy('abfac', gfx.BLUE, gfx.RED, 0, 100) + +Fine-tuning the Coloring +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The :obj:`HSC` render mode uses two colors to color the secondary structure +elements. The main color affects the top and bottom of extended and the outside +of helical elements. The detail color is used for the inner side of helices and +the rim of extended elements. This color is changed with +:meth:`Entity.SetDetailColor`. + \ No newline at end of file diff --git a/modules/doc/intro.rst b/modules/doc/intro.rst index abf6e6cf9fe1ac349a9af1a8d5fd63c686bf14b9..934398e682cc12f0fcbd762ba6560f9a863e6709 100644 --- a/modules/doc/intro.rst +++ b/modules/doc/intro.rst @@ -14,12 +14,19 @@ What will be covered in this tutorial? This tutorial is aimed at users that would like to get their hands dirty and execute commands in Python and write scripts rather clicking their way through a shiny user interface. The user interface of OpenStructure is in a very early -state anyway that you probably won't go far by clicking you way through... +state anyway that you probably won't go far by clicking your way through... -The first part of the tutorial is a walk-through of the basic functionality you -will be using in your everyday work. You will learn how to load structure -datasets, inspect, display them in the 3D window and save them. +The tutorial is divided into several parts. The first part of the tutorial is a +walk-through of the basic functionality you will be using in your everyday work, followed by an introduction to the :mod:`~ost.mol`, :mod:`~ost.img` and :mod:`~ost.seq` modules. +.. toctree:: + :maxdepth: 1 + + intro-01 + intro-02 + intro-03 + +.. _start-dng: Getting ready to rumble -------------------------------------------------------------------------------- @@ -59,310 +66,4 @@ be useful. For example: # get help for method Select help(mol.EntityView.Select) -Loading and inspecting a protein structure --------------------------------------------------------------------------------- - -OpenStructure has a module that is dedicated to deal with input and output of -data, including sequence alignment formats, protein structures and density data -and images. If you are reading this tutorial you most certainly have dealt with -protein structures before and you are most certainly aware that they are usually -stored in Brookhaven structure files (aka PDB files). The official name for -molecules stored in a PDB file is an entity. You will hear this word all the -time, but you can replace the word entity with molecule in your head. - - -To load a PDB file, type - - .. code-block:: python - - fragment=io.LoadPDB('/path/to/examples/entity/fragment.pdb') - -This will load the fragment from the specified file 'fragment.pdb' and store the result in fragment. For more information on the LoadPDB function, type - - .. code-block:: python - - help(io.LoadPDB) - -Now let's inspect what we just loaded: - - .. code-block:: python - - print fragment.chain_count - print fragment.residue_count - print fragment.atom_count - -As you can see, our fragment consists of one peptide chain of 12 amino acids and -has 81 atoms in total. Now let's examine our fragment in more detail. Enter the -command - - .. code-block:: python - - for residue in fragment.residues: - print residue - -This will print a list of all residues in the fragment. Similarly to get a list -of atoms, use: - - .. code-block:: python - - for atom in fragment.atoms: - print atom - -Of course, we can also get a list of atoms grouped by residues: - - .. code-block:: python - - for residue in fragment.residues: - print residue, 'has', residue.atom_count, 'atom(s).' - for atom in residue.atoms: - print ' ', atom.name, atom.pos - -And, for completeness, we will first group them by chain, then by residues. - - .. code-block:: python - - for chain in fragments.chains: - print 'chain', chain.name, 'has', chain.residue_count, 'residue(s)' - for residue in chain.residues: - print ' ', residue, 'has', residue.atom_count, 'atom(s).' - for atom in residue.atoms: - print ' ', atom.name, atom.pos - -Aah, wait! A protein fragment would not be complete without bonds: Let's see -what bonds we have in there: - - .. code-block:: python - - for bond in fragment.bonds: - print bond - -From these short code examples we already see how the entity is structured: On -one hand we have a hierarchy of chains, residues and atoms. On the other hand, -we have bonds that form a network overlayed on the hierarchy. This is -illustrated in the picture on the left. An important feature of entities is that -we can always assume that the hierarchy is intact. You will never find an atom -without residues, no residue can exist without a parent chain and chains belong -always to an entity. - -Let There Be Shiny Graphics --------------------------------------------------------------------------------- - -For visually inspecting the fragment, we now create a graphical representation -of the entity: - - .. code-block:: python - - go=gfx.Entity("Fragment", fragment) - scene.Add(go) - scene.CenterOn(go) - -Now you will see the fragment in the 3D window (left): - - - -Use the mouse to rotate, zoom in an shift the camera. Double clicking on an atom will center the camera on that atom. - -Introduction to Views --------------------------------------------------------------------------------- - -Often during processing and visualisation of data, only parts of a protein -structure are of interest. This realisation has had a major impact on the design -of OpenStructure and is tied very deeply into the core of the framework. -Subparts of structure are modeled as so-called :class:`EntityViews -<mol.EntityView>`. You can think of them as a selection of chains, residues, -atoms and bonds of an entity. A views has almost the same interface as the -underlying entity, making it very easy to mix entity views with handles in -Python due to the dynamic nature of the language. An algorithm that is written -for entities will almost always (with some care) also work for -:class:`EntityHandles <mol.EntityHandle>`. This is referred to as `duck-typing -<http://en.wikipedia.org/wiki/Duck_typing>`_ (I don' t care if it is a duck as -long as it looks like a duck), a concept used all over the place in Python. - -A typical view can be seen in the image on the left. The view consists of one -chain, one residue and two atoms. Again the same rule applies: No atom can be -part of the view without it's residue. In this example, no bonds are included, -since there is at most one atom per bond in the original structure. - -To familiarize yourself with the concept of views, we will use the fragment in -the 3D window. - -We will use several ways to select parts of our fragment: - * By using a dedicated query language - * By manually constructing a view - -The Query Language --------------------------------------------------------------------------------- - -The first way to select parts of a structure is with a dedicated mini-language, -called ["the query language”](docs/tut/query.html). In the Python Shell, type - - .. code-block:: python - - go.selection=fragment.Select('') - -A green halo will be displayed around the selected parts (image in the middle). - -As you can see the previous statement created a “full view”, containing all the -chains, residues, atoms and bonds. To select lysine residues, type - - .. code-block:: python - - go.selection=fragment.Select('rname=LYS') - - -As you can see (image in the middle), the only lysine residue is now -highlighted in the 3D window, because it was the only one matching the predicate -"residue name must be equal to LYS". Several such predicates can be combined -with boolean operators such as *and* and *or*. To select residues with residue -number 1 to 3, the following statement will do the job: - - .. code-block:: python - - go.selection=fragment.Select('rnum>=1 and rnum<=3') - -but this is very cumbersome. That's why there is a shortcut to this statement. -You can specify a range of values. - - .. code-block:: python - - go.selection=fragment.Select('rnum=1:3') - -For a complete description of what you can do with the query language, have a -look at the :doc:`../mol/base/query`. - - -Constructing Views Manually --------------------------------------------------------------------------------- - -Sometimes the query language Is Not Enough (TM). For these cases the -construction of manual entities becomes neccessary. This is pretty straight -forward: - - .. code-block:: python - - view=fragment.CreateEmptyView() - ca=fragment.FindAtom('A', mol.ResNum(1), 'CA') - cb=fragment.FindAtom('A', mol.ResNum(1), 'CB') - view.AddAtom(ca) - view.AddAtom(cb) - go.SetSelection(view) - -The last step sets our constructed view as the current selection, displaying it -in the 3D window. As you can see, C-alpha and C-beta of the first residue are -not connected by bonds, even though both atoms are in the view. You have either -to add the bond manually with - - .. code-block:: python - - ca_cb=ca.FindBondToAtom(cb) - view.AddBond(ca_cb) - -Or as a very convenient shortcut 'view.AddAllInclusiveBonds()' to add all bonds -that have both bonding partners in the view. - -Don't forget to call update the selection of the graphics object to see what -view you have created. - -Saving an Entity --------------------------------------------------------------------------------- - -Saving an entity (or a view) is a breeze: - -Type - - .. code-block:: python - - io.SavePDB(fragment, 'full.pdb') - -to save the full view. To save only the backbone atoms, we can first select the -backbone atoms and then save it: - - .. code-block:: python - - io.SavePDB(fragment.Select('aname=CA,C,N,O'), 'backbone.pdb') - - -Loading images and density maps --------------------------------------------------------------------------------- - -Openstructure features a :mod:`~ost.img` module that is dedicated to the -manipulation of -images/density maps. The images or density maps can either be one-, two- or -three-dimensional. The most common formats used in x-ray and electron -crystallography and atomic force microscope are supported in addition to several -general purpose image formats. See `supported file formats` for details. -The :mod:`~ost.img` module was originally developed as part of the Image -Processing Library & Toolbox IPLT. More documentation and examples can also be -found on the `IPLT website <http://www.iplt.org>`_. - -To load a density map, type - - .. code-block:: python - - map=io.LoadImage('/path/to/examples/map/1ppt.map') - -This will load the fragment density map from the specified file 'fragment.map' -and store the result in fragment_map. - -Now let's inspect what we just loaded: - - .. code-block:: python - - print map.GetPixelSampling() - -We can see that the sampling is set to 1.0 Angstroems in all three dimensions. - -Manipulating images and density maps --------------------------------------------------------------------------------- - -The algorithms used for manipulation of an image are found in the -:mod:`~ost.img` module. Therefore before using an algorithm we first have to -import the :mod:`~ost.img` module. - - .. code-block:: python - - from ost import img - - -The :mod:`~ost.img` module provides a wide range of algorithm to manipulate -image data. Here for the example we use a LowPassFilter to restrict the -resolution of the density map. - - .. code-block:: python - - map_filtered=map.Apply(img.alg.LowPassFilter(3.0)) - -The filtered map is stored in a new variable called fragment\_map\_filtered. - - -Displaying images and density maps --------------------------------------------------------------------------------- - -Now that we have a filtered map it's time to have a look at it. There are -fundamentally two ways to visualize 3-dimensional density maps. One is by -drawing isosurfaces. These are conceputally similar to contour lines used in -cartography: every point on an isosurface has the same density value. -Isosurfaces are easy to create in OpenStructure: - - .. code-block:: python - - go=gfx.MapIso("filtered", map_filtered,0.5) - scene.Add(go) - -The other way to visualize a 3-dimensional map is by showing one 2-dimensional -density slice at a time, allowing the user to move through the slices. In -OpenStructure this is achieved using a DataViewer docs/tut/imgdataviewer.html). -A DataViewer showing the filtered map is created using the following command: - - .. code-block:: python - - gui.CreateDataViewer(map_filtered) - -This command displays a panel showing one slice of the density map lying on a -particular (x,y) plane in the coordinate reference system. -The 'z' and 'x' keys can be used to move to slices lying at a lower or higher -coordinate along the 'z' axis, allowing the examination of -the full 3-dimensional volume. - -A more detailed explanation of the :mod:`~ost.img` module can be found in the -tutorial section for :mod:`~ost.img`. +Continue with :doc:`part one <intro-01>` diff --git a/modules/doc/sel.png b/modules/doc/sel.png new file mode 100644 index 0000000000000000000000000000000000000000..e5b3c80252ac121d9ec3a56f3730dbda8e91356d Binary files /dev/null and b/modules/doc/sel.png differ diff --git a/modules/gfx/doc/cpk.png b/modules/gfx/doc/cpk.png new file mode 100644 index 0000000000000000000000000000000000000000..38808e16817504447d7b260ff14f208cb8de30fe Binary files /dev/null and b/modules/gfx/doc/cpk.png differ diff --git a/modules/gfx/doc/custom.png b/modules/gfx/doc/custom.png new file mode 100644 index 0000000000000000000000000000000000000000..812c317d520a0e9fb66342050b77b74748c42cd3 Binary files /dev/null and b/modules/gfx/doc/custom.png differ diff --git a/modules/gfx/doc/entity.rst b/modules/gfx/doc/entity.rst new file mode 100644 index 0000000000000000000000000000000000000000..a3bf167194252e5c9d694ad7b3b37ec721bea282 --- /dev/null +++ b/modules/gfx/doc/entity.rst @@ -0,0 +1,196 @@ +The Graphical Entity +================================================================================ + +.. currentmodule:: ost.gfx + +.. note:: + + This document describes the API of the :class:`Entity` and related classes. + For an overview of the graphical entity, see :doc:`../intro-03`. + +.. _render-mode: + +Render Modes +-------------------------------------------------------------------------------- + +The entity supports different render modes. They are depicted in the following +images together with the options they support. To change the render mode of the +full entity or part of the entity, use the :meth:`Entity.SetRenderMode` method. + +Render Modes at the Connectivity Level +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. data:: SIMPLE + + .. image:: simple.png + + Renders bonds as lines and single atoms as crosses. + +.. data:: CPK + + .. image:: cpk.png + + + Renders atoms as spheres with radii proportional to their van-der-Waals + radius. + +.. data:: CUSTOM + + .. image:: custom.png + +Render Modes at the Trace Level +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. data:: TUBE + + .. image:: tube.png + + Renders a smooth backbone trace with circular profiles. + +.. data:: SLINE + + .. image:: sline.png + + Renders a smooth backbone trace with lines. + +.. data:: TRACE + + .. image:: trace.png + + Renders the Calpha atoms connected by tubes. + +.. data:: LINE_TRACE + + .. image:: line_trace.png + + Renders the Calpha connected bys lines. + +.. data:: HSC + + .. image:: hsc.png + + Renders a Helix/Strand/Coil Cartoon. + + +.. _render-options: + +Render Options +-------------------------------------------------------------------------------- + + +**line_width** + + The line width. Defaults to 1.0 + + :type: float + +**aa_lines** + + Controls whether antialiased lines are enabled. Only available when + compiled with shaders. Defaults to false. + + :type: bool + +**draw_bond_order** + + Controls whether double/triple bonds are drawn as multiple lines. This + requires that the bond order information has been assigned. As of now, + only the :class:`~ost.conop.RuleBasedBuilder` assigns this information. + + Defaults to off. + + :type: bool + +**bond_order_distance** + + The distance between the lines depicting higher order bonds. + +.. class:: Entity(name, entity) + Entity(name, render_mode, entity) + + Graphical representation of entitites. + + + .. attribute:: name + + The name of the entity. Read-only. Also available as :meth:`GetName` + + :type: str + + .. attribute:: selection + + The selection of the entity is rendered with a green halo. + + :type: :class:`~ost.mol.EntityView` + + .. attribute:: center + + The geometric center of the graphical entity. Read-only. + + :type: :class:`~ost.geom.Vec3` + + :param name: Name of the entity + :type name: str + :param render_mode: One of the :ref:`render-mode`. + Defaults to :obj:`SIMPLE`. + :param entity: The entity. Only atoms and bonds that part part of the entity + view (or handle) are rendered. + :type entity: :class:`~ost.mol.EntityView`, or :class:`~ost.mol.EntityHandle` + + .. method:: SetRenderMode(render_mode) + SetRenderMode(render_mode, view, keep=False) + + Changes the render mode of the graphical entity. The first signature changes + the render mode of all atoms and bonds, whereas the second only changes the + display of atoms/bonds that are part of the view. If `keep` is set to false, + the atoms and bonds that are part of the view will only be displayed in the + new render mode, if keep is set to true, the atoms and bonds will be + rendered with the new render mode in addition to whatever render mode they + were rendered previously. + + :param render_mode: One of the :ref:`render-mode`. + Defaults to :obj:`SIMPLE`. + :param view: A valid entity view + :type view: :class:`~ost.mol.EntityView` + + .. method:: SetColor(color, selection='') + + Sets the atoms matching the selection predicates to `color`. + + :param color: The new color + :type color: :class:`Color` + :param selection: A valid :doc:`query <../mol/base/query>` + :type selection: str + + .. method:: ColorByElement() + + Apply `CPK coloring <http://en.wikipedia.org/wiki/CPK_coloring>`_ coloring + to atoms. This will color the carbon atoms in white, nitrogen in blue, + oxygen in red, phosphorous in pink and sulfur in yellow. + + + .. method:: ColorBy(prop, color1, color2, min, max, hint='U') + ColorBy(prop, color1, color2, hint='U') + ColorBy(prop, gradient, min, max, hint='U') + ColorBy(prop, gradient, hint='U') + + Colors the entity by mapping a numeric property to a color. This property + can be a built-in a property such as atomic b-factor, charge, residue number + or be a :doc:`custom property <../base/generic>` assigned by the user or an + algorithm and be defined at any level (chain, residue, atom). The naming of + the built-in properties is identical to the properties available in + :doc:`query language <../mol/base/query>`. + + :param prop: The name of the numeric property + :type prop: str + :param color1: Color corresponding to min value + :type color1: :class:`Color` + :param color2: Color corresponding to max value + :type color2: :class:`Color` + :param gradient: The gradient to be used + :type gradient: :class:`Gradient` + :type min: Value mapped to `color1`, or the color at 0.0 in the gradient + :type max: Value mapped to `color2` or the color at 1.0 in the gradient + :param hint: When `prop` refers to a generic property, hint must be set to + the hierarchy level at which the property is defined. + :type hint: str diff --git a/modules/gfx/doc/gfx.rst b/modules/gfx/doc/gfx.rst new file mode 100644 index 0000000000000000000000000000000000000000..3535136fe6a633ce0abc783d60be0eef17887667 --- /dev/null +++ b/modules/gfx/doc/gfx.rst @@ -0,0 +1,10 @@ +:mod:`~ost.gfx` - Realtime 3D Rendering +================================================================================ + +.. module:: ost.gfx + :synopsis: Realtime 3D Rendering + +.. toctree:: + :maxdepth: 2 + + entity \ No newline at end of file diff --git a/modules/gfx/doc/hsc.png b/modules/gfx/doc/hsc.png new file mode 100644 index 0000000000000000000000000000000000000000..62ec72c8a392ad715481a64e70f4397e0be24e46 Binary files /dev/null and b/modules/gfx/doc/hsc.png differ diff --git a/modules/gfx/doc/line_trace.png b/modules/gfx/doc/line_trace.png new file mode 100644 index 0000000000000000000000000000000000000000..73e48987c6593ba9b43b9faaa99c09322728924a Binary files /dev/null and b/modules/gfx/doc/line_trace.png differ diff --git a/modules/gfx/doc/simple.png b/modules/gfx/doc/simple.png new file mode 100644 index 0000000000000000000000000000000000000000..e6a4d8cd8369fc8cc7c9151b1e0424138d9ba859 Binary files /dev/null and b/modules/gfx/doc/simple.png differ diff --git a/modules/gfx/doc/sline.png b/modules/gfx/doc/sline.png new file mode 100644 index 0000000000000000000000000000000000000000..79ee2f533764fda141b1783c3391b750de0a8f6d Binary files /dev/null and b/modules/gfx/doc/sline.png differ diff --git a/modules/gfx/doc/trace.png b/modules/gfx/doc/trace.png new file mode 100644 index 0000000000000000000000000000000000000000..8f7f5e6754c9d0d19ec3f357886bf2e65d84f6cb Binary files /dev/null and b/modules/gfx/doc/trace.png differ diff --git a/modules/gfx/doc/tube.png b/modules/gfx/doc/tube.png new file mode 100644 index 0000000000000000000000000000000000000000..5256aa3dd62bdfa24068114a442d84fd1b97fa13 Binary files /dev/null and b/modules/gfx/doc/tube.png differ diff --git a/modules/gfx/pymod/export_entity.cc b/modules/gfx/pymod/export_entity.cc index a81f8299ea0cdc549b1fb34b0255cdb66f4938d7..2e5a0f13f61d33a52fdb888308f2dfff83bc6202 100644 --- a/modules/gfx/pymod/export_entity.cc +++ b/modules/gfx/pymod/export_entity.cc @@ -186,7 +186,7 @@ void (Entity::*set_rm1)(RenderMode::Type, const mol::EntityView&, bool)=&Entity: void (Entity::*set_rm2)(RenderMode::Type)=&Entity::SetRenderMode; RenderOptionsPtr ent_trace_opts(Entity* ent) { - return ent->GetOptions(RenderMode::LINE_TRACE); + return ent->GetOptions(RenderMode::TRACE); } RenderOptionsPtr ent_simple_opts(Entity* ent) @@ -214,6 +214,11 @@ RenderOptionsPtr ent_cpk_opts(Entity* ent) return ent->GetOptions(RenderMode::CPK); } +RenderOptionsPtr ent_ltrace_opts(Entity* ent) +{ + return ent->GetOptions(RenderMode::LINE_TRACE); +} + } void export_Entity() @@ -273,6 +278,7 @@ void export_Entity() .add_property("cartoon_options", &ent_hsc_opts) .add_property("cpk_options", &ent_cpk_opts) .add_property("trace_options", &ent_trace_opts) + .add_property("line_trace_options", &ent_ltrace_opts) .def("ApplyOptions", &Entity::ApplyOptions) .def("SetOptions", &Entity::SetOptions) .def("Apply",&ent_apply_11) diff --git a/modules/gfx/pymod/export_render_options.cc b/modules/gfx/pymod/export_render_options.cc index b27e55c46f32ec9ac3fc3c3c166eb74d58cbc1fe..2c7277578fe50b20fd1e2345c693a67f3f8dc8c8 100644 --- a/modules/gfx/pymod/export_render_options.cc +++ b/modules/gfx/pymod/export_render_options.cc @@ -43,6 +43,10 @@ void export_RenderOptions() .def("GetLineWidth",&LineRenderOptions::GetLineWidth) .def("SetAALines",&LineRenderOptions::SetAALines) .def("GetAALines",&LineRenderOptions::GetAALines) + .add_property("aa_lines", &LineRenderOptions::GetAALines, + &LineRenderOptions::SetAALines) + .add_property("line_width", &LineRenderOptions::GetLineWidth, + &LineRenderOptions::SetLineWidth) ; class_<SimpleRenderOptions, boost::shared_ptr<SimpleRenderOptions>, bases<LineRenderOptions>, boost::noncopyable>("SimpleRenderOptions") @@ -50,6 +54,10 @@ void export_RenderOptions() .def("SetBondOrderDistance", &SimpleRenderOptions::SetBondOrderDistance) .def("GetBondOrderFlag", &SimpleRenderOptions::GetBondOrderFlag) .def("GetBondOrderDistance", &SimpleRenderOptions::GetBondOrderDistance) + .add_property("draw_bond_order", &SimpleRenderOptions::GetBondOrderFlag, + &SimpleRenderOptions::SetBondOrderFlag) + .add_property("bond_order_distance", &SimpleRenderOptions::GetBondOrderDistance, + &SimpleRenderOptions::SetBondOrderDistance) ; class_<LineTraceRenderOptions, boost::shared_ptr<LineTraceRenderOptions>, bases<LineRenderOptions>, boost::noncopyable>("LineTraceRenderOptions") @@ -65,6 +73,10 @@ void export_RenderOptions() .def("GetSphereDetail", &CPKRenderOptions::GetSphereDetail) .def("SetCPKMode", &CPKRenderOptions::SetCPKMode) .def("GetCPKMode", &CPKRenderOptions::GetCPKMode) + .add_property("cpk_mode", &CPKRenderOptions::GetCPKMode, + &CPKRenderOptions::SetCPKMode) + .add_property("sphere_detail", &CPKRenderOptions::GetSphereDetail, + &CPKRenderOptions::SetSphereDetail) ; class_<CustomRenderOptions, boost::shared_ptr<CustomRenderOptions>, bases<RenderOptions>, boost::noncopyable>("CustomRenderOptions") @@ -76,6 +88,11 @@ void export_RenderOptions() .def("GetSphereRad", &CustomRenderOptions::GetSphereRad) .def("SetBondRad", &CustomRenderOptions::SetBondRad) .def("GetBondRad", &CustomRenderOptions::GetBondRad) + .add_property("sphere_detail", &CustomRenderOptions::GetSphereDetail, &CustomRenderOptions::SetSphereDetail) + .add_property("bond_rad", &CustomRenderOptions::GetBondRad, &CustomRenderOptions::SetBondRad) + .add_property("sphere_rad", &CustomRenderOptions::GetSphereRad, &CustomRenderOptions::SetSphereRad) + .add_property("arc_detail", &CustomRenderOptions::GetArcDetail, + &CustomRenderOptions::SetArcDetail) ; class_<CartoonRenderOptions, boost::shared_ptr<CartoonRenderOptions>, bases<RenderOptions>, boost::noncopyable>("CartoonRenderOptions") @@ -119,6 +136,13 @@ void export_RenderOptions() .def("GetNormalSmoothFactor", &TraceRenderOptions::GetNormalSmoothFactor) .def("SetTubeRadius", &TraceRenderOptions::SetTubeRadius) .def("GetTubeRadius", &TraceRenderOptions::GetTubeRadius) + .add_property("tube_radius", &TraceRenderOptions::GetTubeRadius, + &TraceRenderOptions::SetTubeRadius) + .add_property("arc_detail", &TraceRenderOptions::GetArcDetail, + &TraceRenderOptions::SetArcDetail) + .add_property("normal_smooth_factor", + &TraceRenderOptions::GetNormalSmoothFactor, + &TraceRenderOptions::SetNormalSmoothFactor) ; } diff --git a/modules/gui/src/file_browser.cc b/modules/gui/src/file_browser.cc index 965e3321a03e305f511fbaa720b09d8adcebed7f..9c6885b1b263f0e29c0dfb8abe319f6ba66264bd 100644 --- a/modules/gui/src/file_browser.cc +++ b/modules/gui/src/file_browser.cc @@ -71,7 +71,9 @@ FileBrowser::FileBrowser(QWidget* parent): } # elif defined(__APPLE__) if (path.contains("DNG.app") || path=="/") { - QString example_path="/Applications/OpenStructure/Examples/entity"; + QDir dir(QCoreApplication::applicationDirPath()); + dir.cdUp(); + QString example_path=dir.path()+"/examples"; if (QDir(example_path).exists()) { path=example_path; } diff --git a/modules/index.rst b/modules/index.rst index c70e751c08e24eda54a2318c11ac46f829b97810..a9d779a20a79ba0afc6e6e26b6d9293426a68258 100644 --- a/modules/index.rst +++ b/modules/index.rst @@ -2,7 +2,7 @@ OpenStructure documentation ================================================================================ .. toctree:: - :maxdepth: 2 + :maxdepth: 1 Introduction -------------------------------------------------------------------------------- @@ -10,31 +10,38 @@ Introduction .. toctree:: :maxdepth: 2 - intro install - + intro + + Modules -------------------------------------------------------------------------------- .. toctree:: - :maxdepth: 2 + :maxdepth: 1 base/generic - img/base/img - img/alg/alg + base/base geom/geom - conop/conop + mol/base/mol + conop/conop + + img/base/img + img/alg/alg + seq/base/seq - base/base + io/io + + gfx/gfx gui/gui Extending OpenStructure -------------------------------------------------------------------------------- .. toctree:: - :maxdepth: 2 + :maxdepth: 1 newmodule external diff --git a/modules/mol/base/doc/query.rst b/modules/mol/base/doc/query.rst index 20c4b711a2a0e9c190efce278af82df16ac84ee1..ff8ff21a41613745e62df35bb648edfb72763ff1 100644 --- a/modules/mol/base/doc/query.rst +++ b/modules/mol/base/doc/query.rst @@ -1,93 +1,137 @@ Queries ================================================================================ -.. class:: Query +.. currentmodule:: ost.mol - Blabla - -It is often convenient to highlight or focus certain parts of the structure. OpenStructure includes a powerful query system that allows you to perform custom selections in a convenient way. -Please refer to the tutorial on the query language for an introduction. -The query language reference +The Basics -------------------------------------------------------------------------------- -The query consists of one or more predicates combined with boolean -operators. A predicate takes the form *prop op value*. Operators are -one of `` =, !=, >, >=, <=`` and ``<``. A predicate has the following form: -*PROPERTY - OPERATOR - ARGUMENT*. - -The following properties may be used in predicates. The supported type of the -value is given for each property. - - * ``rname`` residue name. type: string - * ``rnum`` residue number. currently only numeric part is honored. - type: int - * ``rtype`` residue type as given by the DSSP code, i.e. H for helix, E - for extended. type: string - * ``aname`` atom name. type: string - * ``ele`` element of atom. type: string - * ``cname`` chain name. type: string - * ``occ`` occupancy, between 0 and 1. type: float - * ``abfac`` B (temperature) factor of atom. type: float - * ``rbfac`` average B (temperature) factor of residue. type: float. - Note that this does not work for views as expected. When running a - second selection statement on a view, all atoms of the residue handle - and not the view are considered in the calculation - * ``ishetatm`` whether the atom is a hetorogenous atom. type: bool or int - (0 for false, 1 for true) - * ``peptide`` whether the residue is peptide linking. type: bool or int - (0 for false, 1 for true) - * ``x`` X coordinate of atom. type: float - * ``y`` Y coordinate of atom. type: float - * ``z`` Z coordinate of atom. type: float - * ``rindex`` index of residue in chain. This index is the same for views - and handles - * For :ref:`generic properties in queries <genprop-in-queries>` see below. - -Distance-based selections within a given atom position are supported by -the within statement. To select atoms within 5 Angstrom of the point -``{1, 2, 3}``, one would write: - -``5 <> {1,2,3}`` - -Negation of this expression is possible with the not operator, i.e. - -``not 5 <> {1,2,3}`` -will select atoms that are further than five Angstrom apart from ``{1, 2 , 3}`` - -Abbreviations +It is often convenient to highlight or focus certain parts of the structure. +OpenStructure includes a powerful query system that allows you to perform custom +selections in a convenient way. Selections are carried out mainly by calling the Select method made available by EntityHandle and :class:`EntityView` objects while providing a query string. Queries are written using a dedicated mini-language. For example, to select all arginine residues of a given structure, one would write: + +.. code-block:: python + + arginines=model.Select('rname=ARG') + +A simple selection query (called a predicate) consists in a property (here, +`rname`), a comparison operator (here, `=`) and an argument (here, `ARG`). The +return value of a call to the :meth:`EntityHandle.Select` method is always an +:class:`EntityView`. The :class:`EntityView` always contains a full hierarchy of +elements, never standalone separated elements. In the above example, the +:class:`EntityView` called `arginines` will contain all chains from the +structure called 'model' that have at least one arginine. In turn these chains +will contain all residues that have been identified as arginines. The residues +themselves will contain references to all of their atoms. Of course, queries are +not limited to selecting residues based on their type, it is also possible to +select atom by name: + +.. code-block:: python + + c_betas=model.Select('aname=CB') + +As before, c`betas is an instance of an :class:`EntityView` object and contains +a full hierarchy. The main difference to the previous example is that the +selected residues do not contain a list of all of their atoms but only the +C-beta. These examples clarify why the name 'view' was chosen for this result of +a :meth:`~EntityHandle.Select` statement. It represents a reduced, restrained +way of looking at the original structure. + +Both the selection statements that have been used so far take strings as their arguments. However, selection properties such as `rnum` (residue number), take numeric arguments. With numeric arguments it is possible to use identity operators ( `!=` and `=`). It is also possible to compare them using the `>`, `<`, `>=` and `<=` operators. For example, the 20 N-terminal residues of a protein can be selected with: + +.. code-block:: python + + n_term=model.Select('rnum<=20') + +Combining predicates ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Two abbreviations exist for convenience: +Selection predicates can be combined with boolean operators. For example , you might want to select all C atoms with crystallographic occupancy higher than 50. These atoms must match the predicate `ele=C` in addition to the predicate `occ>50`. In the query language this can be written as: -Instead of writing +.. code-block:: python -``aname=CA or aname=C or aname=O or aname=N``, + model.Select('ele=C and occ>50') + +Compact forms are available for several selection statements. For example, to select all arginines and aspargines, one could use a statement like: -one can write +.. code-block:: python + + arg_and_asn=model.Select('rname=ARG or rname=ASN') -``aname=CA,N,C,O``. +However, this is rather cumbersome as it requires the word `rname` to be typed twice. Since the only difference between the two parts of the selection is the argument that follows the word `rname`, the statement can also be written in an abbreviated form: -For integral value ranges, one can use the colon syntax: instead of +.. code-block:: python + + arg_and_asn=model.Select('rname=ARG,ASN') -``rnum>=10 and rnum<=20`` +Another example: to select residues with numbers in the range 130 to 200, one could use the following statement -one can write +.. code-block:: python + + center=model.Select('rnum>=130 and rnum<=200') + +or alternatively use the much nicer syntax: + +.. code-block:: python + + center=model.Select('rnum=130:200') + +This last statement is completely equivalent to the previous one. This syntax +can be used when the selection statement requires a range of integer values +within a closed interval. + +Distance Queries +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The query + +.. code-block:: python + + around_center=model.Select('5 <> {0,0,0}') + +selects all chains, residues and atoms that lie with 5 Å to the origin of the reference system ({0,0,0}). The `<>` operator is called the ‘within’ operator. +Instead of a point, the within statements can also be used to return a view containing all chains, residues and atoms within a radius of another selection statement applied to the same entity. Square brackets are used to delimit the inner query statement. + +.. code-block:: python + + around_hem=model.Select('5 <> [rname=HEM]') + model.Select('5 <> [rname=HEM and ele=C] and rname!=HEM') + +Bonds and Queries +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When an :class:`EntityView` is generated by a selection, it includes by default only bonds for which both connected atoms satisfy the query statement. This can be changed by passing the parameters `EXCLUSIVE_BONDS` or `NO_BONDS` when calling the Select method. `EXCLUSIVE_BONDS` adds bonds to the :class:`EntityView` when at least one of the two atoms falls within the boundary of the selection. `NO_BONDS` suppresses the bond inclusion step completely. + +Whole Residue Queries +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -``rnum=10:20`` +If the parameter `MATCH_RESIDUES` is passed when the Select method is called, the resulting :class:`EntityView` will include whole residues for which at least one atom satisfies the query. This means that if at least one atom in the residue falls within the boundaries of the selection, all atoms of the residue will be included in the View. + +More Query Usage +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The high level interface for queries are the Select methods of the +EntityHandle and :class:`EntityView` classes. By passing in a query string, a view +consisting of a subset of the elements is returned. + +Queries also offer a second interface: `IsAtomSelected()`, +`IsResidueSelected()` and `IsChainSelected()` take an atom, residue or +chain as their argument and return true or false, depending on whether the +element fulfills the predicates. .. _genprop-in-queries: Generic Properties in Queries --------------------------------------------------------------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The query language can also be used for numeric generic properties (i.e. float and int), but the syntax is slightly different. To access any generic properties, it needs to be specified that they are generic and at which level -they are defined. Therefore, all generic properties start with a ``g``, followed by an ``a``, ``r`` or ``c`` for atom, residue or chain level respectively. +they are defined. Therefore, all generic properties start with a `g`, followed by an `a`, `r` or `c` for atom, residue or chain level respectively. .. code-block:: python @@ -122,3 +166,92 @@ statement which can be done using a ':' character: Using this method, you will be warned if a generic property is not set for all atoms, residues or chains unless you specify a default value. So, be careful when you do. + +Available Properties +-------------------------------------------------------------------------------- + +The following properties may be used in predicates. The type is given for each property. + +Properties of Chains +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +**cname/chain** (str) :attr:`Chain name<ChainHandle.name>` + +Properties of Residues +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +**rname** (str): :attr:`Residue name<ResidueHandle.name>` + +**rnum** (int): :attr:`Residue number<ResidueHandle.number>`. Currently only the numeric part is honored. + +**rtype** (str): Residue type as given by the DSSP code, i.e. H for helix, E for extended. + +**rindex** (int): :attr:`Index<ResidueHandle.index>` of residue in chain. This +index is the same for views and handles. + +**ishetatm** (bool): Whether the atom is a :attr:`heterogenous<AtomHandle.is_hetatm>` atom. + +**peptide** (bool): Whether the residue is a :meth:`peptide <ResidueHandle.IsPeptideLinking>`. + +**rbfac** (float): average B (temperature) factor of residue + +Properties of Atoms +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +**aname** (str): :attr:`Atom name<AtomHandle.name>` + +**ele** (str): :attr:`Atom element<AtomHandle.element>` + + + +**occ** (float): :attr:`Atom occupancy<AtomHandle.occupancy>` + +**abfac** (float): :attr:`Atom B-factor<AtomHandle.b_factor>` + +**x** (float): :attr:`X<AtomHandle.pos>` coordinate of atom. + +**y** (float): :attr:`Y<AtomHandle.pos>` coordinate of atom. + +**z** (float): :attr:`Z<AtomHandle.pos>` coordinate of atom. + +Query API documentation +-------------------------------------------------------------------------------- + +.. class:: Query(string='') + + Create a new query from the given string. The constructor does not throw any + error in case the query contains syntax errors. Use :attr:`valid` to check + whether the query was valid. + + + .. attribute:: string + + The string used to create the query. + + :type: str + + .. attribute:: valid + + True, when the query could be compiled without syntax errors. + + :type: bool + + .. attribute:: error + + If :attr:`valid` is false, this attribute contains the error message. + Otherwise it is set to an empty string + + :type: str + .. method:: IsAtomSelected(atom) + + Returns true, when the given atom handle fulfills the predicates, false if + not. + + .. method:: IsChainSelected(chain) + + Return true if at least one of the atomso of the chain matches the + predicates. + + .. method:: IsResidueSelected(residue) + + Returns true, when at least one atom of the residue matches the predicates. diff --git a/modules/mol/base/pymod/export_query.cc b/modules/mol/base/pymod/export_query.cc index 2a301e0b3407b7f7a20f1a61bdf28954267ba864..40c729672f0204a5fdfb0262e504525e176e4fb7 100644 --- a/modules/mol/base/pymod/export_query.cc +++ b/modules/mol/base/pymod/export_query.cc @@ -29,6 +29,12 @@ void translate_QueryError(const QueryError& e) { PyErr_SetString(PyExc_RuntimeError, e.GetFormattedMessage().c_str()); } +String error_msg(Query& q) +{ + return QueryError(q.GetQueryString(), + q.GetErrorDescription()).GetFormattedMessage(); +} + void export_Query() { @@ -52,7 +58,9 @@ void export_Query() .def("IsAtomSelected", &Query::IsAtomSelected) .def("IsResidueSelected", &Query::IsResidueSelected) .def("IsChainSelected", &Query::IsChainSelected) - .add_property("String", + .add_property("valid", &Query::IsValid) + .add_property("error", &error_msg) + .add_property("string", make_function(&Query::GetQueryString, return_value_policy<copy_const_reference>())) .def("GetErrorDescription", &Query::GetErrorDescription,