Hi Arthur & Jerome,

I wrote a basic PDBML importer for PyMOL, see attached script which adds a 
"load_pdbml" command. I meant to assess the complexity of such a project and 
ended up writing the entire thing. So far, this only reads atoms and symmetry 
information. If you find this useful we can include that in the next PyMOL 
release.

Cheers,
  Thomas

'''
Adds a "load_pdbml" command to PyMOL.

(c) Thomas Holder, Schrodinger, LLC
'''

import os
from pymol import cmd

@cmd.extend
def load_pdbml(filename, object='', discrete=0, multiplex=1, zoom=-1, quiet=1, _self=cmd):
    '''
DESCRIPTION

    Load a PDBML formatted structure file
    '''
    from lxml import etree
    from chempy import Atom, models
    from collections import defaultdict

    multiplex, discrete = int(multiplex), int(discrete)

    try:
        root = etree.parse(filename).getroot()
        atom_site_list = root.xpath('./PDBx:atom_siteCategory/PDBx:atom_site', namespaces=root.nsmap)
    except etree.XMLSyntaxError:
        print " Error: File doesn't look like XML"
        return
    except etree.XPathEvalError:
        print " Error: XML file doesn't look like a PDBML file"
        return

    if not atom_site_list:
        print ' Error: no PDBx:atom_site nodes found in XML file'
        return

    # state -> model dictionary
    model_dict = defaultdict(models.Indexed)

    # atoms
    for atom_site in atom_site_list:
        atom = Atom()
        atom.coord = [None, None, None]

        model_num = 1

        for child in atom_site:
            tag = etree.QName(child).localname

            if tag == 'Cartn_x':
                atom.coord[0] = float(child.text)
            elif tag == 'Cartn_y':
                atom.coord[1] = float(child.text)
            elif tag == 'Cartn_z':
                atom.coord[2] = float(child.text)
            elif tag == 'B_iso_or_equiv':
                atom.b = float(child.text)
            elif tag == 'auth_asym_id':
                atom.chain = child.text or ''
            elif tag == 'auth_atom_id':
                atom.name = child.text or ''
            elif tag == 'auth_comp_id':
                atom.resn = child.text or ''
            elif tag == 'auth_seq_id':
                atom.resi = child.text or ''
            elif tag == 'label_alt_id':
                atom.resi = child.text or ''
            elif tag == 'label_asym_id':
                atom.segi = child.text or ''
            elif tag == 'label_atom_id':
                if not atom.name:
                    atom.name = child.text or ''
            elif tag == 'label_comp_id':
                if not atom.resn:
                    atom.resn = child.text or ''
            elif tag == 'label_seq_id':
                if not atom.resi:
                    atom.resi = child.text or ''
            elif tag == 'label_entity_id':
                atom.properties['entity_id'] = child.text or ''
            elif tag == 'occupancy':
                atom.q = float(child.text)
            elif tag == 'pdbx_PDB_model_num':
                model_num = int(child.text)
            elif tag == 'type_symbol':
                atom.symbol = child.text or ''
            elif tag == 'group_PDB':
                atom.hetatm = (child.text == 'HETATM')

        if None not in atom.coord:
            model_dict[model_num].add_atom(atom)

    # symmetry and cell
    try:
        node = root.xpath('./PDBx:cellCategory/PDBx:cell', namespaces=root.nsmap)[0]
        cell = [float(node.xpath('./PDBx:' + a + '/text()', namespaces=root.nsmap)[0])
                for a in ['length_a', 'length_b', 'length_c',
                    'angle_alpha', 'angle_beta', 'angle_gamma']]

        spacegroup = root.xpath(
                './PDBx:symmetryCategory/PDBx:symmetry/PDBx:space_group_name_H-M/text()',
                namespaces=root.nsmap)[0]
    except IndexError:
        cell = None
        spacegroup = ''

    # object name
    if not object:
        object = os.path.basename(filename).split('.', 1)[0]

    # only multiplex if more than one model/state
    multiplex = multiplex and len(model_dict) > 1

    # load models as objects or states
    for model_num in sorted(model_dict):
        if model_num < 1:
            print " Error: model_num < 1 not supported"
            continue

        model = model_dict[model_num]
        model.connect_mode = 3

        if cell:
            model.cell = cell
            model.spacegroup = spacegroup

        if multiplex:
            oname = '%s_%04d' % (object , model_num)
            model_num = 1
        else:
            oname = object

        _self.load_model(model, oname,
                state=model_num, zoom=zoom,
                discrete=discrete)
On 23 Sep 2015, at 03:27, Arthur Zalevsky <aozalev...@fbb.msu.ru> wrote:

> Sorry for bumping old thread, but is support for pdbml still 
> unimplemented? In such case i think it's a good project for our 
> students.
> 
> Regards,
> Arthur
> 
>> From: Thomas Holder <speleo3@us...> - 2013-12-02 19:23:18
>> Hi Jerome,
>> 
>> I think the simple reason is that nobody ever wrote a PDBML parser for 
>> PyMOL. Is that a good reason?
>> 
>> Cheers,
>> Thomas
>> 
>>> On 28 Nov 2013, at 13:21, Jerome BENOIT <g6299304p@...> wrote:
>>> Hello List,
>>> 
>>> is there any good reason why PyMOL can not read PDBML data files ?
>>> 
>>> Cheers,
>>> Jerome

-- 
Thomas Holder
PyMOL Principal Developer
Schrödinger, Inc.
------------------------------------------------------------------------------
_______________________________________________
PyMOL-users mailing list (PyMOL-users@lists.sourceforge.net)
Info Page: https://lists.sourceforge.net/lists/listinfo/pymol-users
Archives: http://www.mail-archive.com/pymol-users@lists.sourceforge.net

Reply via email to