Beispiel #1
0
def expand_crystal(structure, n=1, name='XTAL'):
    """Expands the contents of a structure to a crystal of a given size. Returns
    a `` StructureHolder`` entity instance. 

    Arguments:
    
        - structure: ``Structure`` entity instance. 
        - n: number number of unit-cell layers.
        - name: optional name.

    Requires a PDB file with correct CRYST1 field and space group information.
    """
    sh = structure.header
    sn = structure.name
    fmx = sh['uc_fmx']
    omx = sh['uc_omx']
    # get initial coorinates
    atoms = einput(structure, 'A')
    coords = array([atoms.getData('coords')]) # fake 3D
    # expand the coordinates to crystal
    all_coords = coords_to_crystal(coords, fmx, omx, n)
    structures = StructureHolder(name)
    rng = range(-n, n + 1) # a range like -2, -1, 0, 1, 2
    vectors = [(x, y, z) for x in rng for y in rng for z in rng]
    for i, (u, v, w) in enumerate(vectors):
        new_structure = copy(structure)
        new_atoms = einput(new_structure, 'A')
        new_coords = all_coords[i, 0]
        for (atom_id, new_coord) in izip(atoms.keys(), new_coords):
            new_atoms[atom_id].coords = new_coord
        new_structure.setName("%s_%s%s%s" % (sn, u, v, w))
        structures.addChild(new_structure)
    return structures
Beispiel #2
0
 def setUp(self):
     self.structure = FromFilenameStructureParser('data/1A1X.pdb')
     self.residues = einput(self.structure, 'R')
     self.atoms = einput(self.structure, 'A')
     self.residue8 = self.residues.values()[8]
     self.atom17 = self.atoms.values()[17]
     self.atom23 = self.atoms.values()[23]
Beispiel #3
0
    def test_xtradata(self):
        """tests if an full_id's in the data dict are correctly parsed."""

        structure = einput(self.input_structure, 'S')[('2E12',)]
        model = einput(self.input_structure, 'M')[('2E12', 0)]
        chain = einput(self.input_structure, 'C')[('2E12', 0, 'B')]
        residue = einput(self.input_structure, 'R')[('2E12', 0, 'B', ('LEU', 24, ' '))]
        atom = einput(self.input_structure, 'A')[('2E12', 0, 'B', ('LEU', 24, ' '), ('CD1', ' '))]

        data_model = {(None, 0):{'model':1}}
        xtradata(data_model, structure)
        self.assertEquals(model.xtra, {'model': 1})

        data_chain = {(None, None, 'B'):{'chain':1}}
        xtradata(data_chain, model)
        self.assertEquals(chain.xtra, {'chain': 1})

        data_chain = {(None, 0, 'B'):{'chain': 2}}
        xtradata(data_chain, structure)
        self.assertEquals(chain.xtra['chain'], 2)

        data_residue = {(None, None, 'B', ('LEU', 24, ' ')):{'residue':1}}
        xtradata(data_residue, model)
        self.assertEquals(residue.xtra, {'residue': 1})

        data_residue = {(None, 0, 'B', ('LEU', 24, ' ')):{'residue':2}}
        xtradata(data_residue, structure)
        self.assertEquals(residue.xtra, {'residue': 2})
Beispiel #4
0
def PDBXWriter(f, entities, level, b_key, b_mode=None, b_val=0.0, q_key=None, q_mode=None, q_val=0.0):
    """Writes data from the ``xtra`` dictionary into B and Q columns of a 
    PDB file. The level from which the dictionary is taken can be specified.
    The b_key and q_key specifies should be a key in the dictionaries, b_val and
    q_val are the default values, b_mode and q_mode can be "number" - 
    ``float`` will be called to transform the data or "iterable" which will 
    return the length (``len``) of the sequence.
    The B and Q columns can contain only numeric values, thus any data which we 
    wish to store in those columns needs to be converted. The following 
    functions convert data to numeric form. boolean type can also be treated as
    number.
    """

    b_mode = b_mode or "number"  # B
    q_mode = q_mode or "number"  # Q

    entities = einput(entities, level)

    for entity in entities:
        q_data = eval(q_mode)(entity.xtra.get(q_key), b_val)  # occupancy
        b_data = eval(b_mode)(entity.xtra.get(b_key), q_val)  # b-factor

        if level != "A":
            atoms = einput(entity, "A")
            for atom in atoms:
                if b_key:
                    atom.setBfactor(b_data)
                if q_key:
                    atom.setOccupancy(q_data)
        else:
            if b_key:
                entity.setBfactor(b_data)
            if q_key:
                entity.setOccupancy(q_data)
    PDBWriter(f, entities)  # we try to preserve the headers
Beispiel #5
0
def expand_crystal(structure, n=1, name='XTAL'):
    """Expands the contents of a structure to a crystal of a given size. Returns
    a `` StructureHolder`` entity instance. 

    Arguments:
    
        - structure: ``Structure`` entity instance. 
        - n: number number of unit-cell layers.
        - name: optional name.

    Requires a PDB file with correct CRYST1 field and space group information.
    """
    sh = structure.header
    sn = structure.name
    fmx = sh['uc_fmx']
    omx = sh['uc_omx']
    # get initial coorinates
    atoms = einput(structure, 'A')
    coords = array([atoms.getData('coords')])  # fake 3D
    # expand the coordinates to crystal
    all_coords = coords_to_crystal(coords, fmx, omx, n)
    structures = StructureHolder(name)
    rng = range(-n, n + 1)  # a range like -2, -1, 0, 1, 2
    vectors = [(x, y, z) for x in rng for y in rng for z in rng]
    for i, (u, v, w) in enumerate(vectors):
        new_structure = copy(structure)
        new_atoms = einput(new_structure, 'A')
        new_coords = all_coords[i, 0]
        for (atom_id, new_coord) in izip(atoms.keys(), new_coords):
            new_atoms[atom_id].coords = new_coord
        new_structure.setName("%s_%s%s%s" % (sn, u, v, w))
        structures.addChild(new_structure)
    return structures
Beispiel #6
0
 def setUp(self):
     self.structure = FromFilenameStructureParser('data/1A1X.pdb')
     self.residues = einput(self.structure, 'R')
     self.atoms = einput(self.structure, 'A')
     self.residue8 = self.residues.values()[8]
     self.atom17 = self.atoms.values()[17]
     self.atom23 = self.atoms.values()[23]
Beispiel #7
0
def asa_xtra(entities, mode='internal', xtra_key=None, **asa_kwargs):
    """Calculates accessible surface areas (ASA) and puts the results into the
    xtra dictionaries of entities.
    
    Arguments:
    
        - entities: an entity or sequence of entities
        - mode(str): 'internal' for calculations using the built-in cython code 
          or 'stride' if the stride binary should be called to do the job.
        - xtra_key(str): Key in the xtra dictionary to hold the result for each
          entity
    
    Additional keyworded arguments are passed to the ``_prepare_asa`` and 
    ``_run_asa`` functions.
    """
    xtra_key = xtra_key or 'ASA'
    structures = einput(entities, 'S')
    if len(structures.values()) > 1:
        raise ValueError(
            'Entities from multiple structures are not supported.')
    if mode == 'internal':
        _prepare_entities(entities)  # mask waters
        result = _prepare_asa(entities, **asa_kwargs)  # calculate ASA
        _postpare_entities(entities)  # unmask waters
        result = dict([(id, {xtra_key: v}) for id, v in result.iteritems()])
        xtradata(result, structures)
    elif mode == 'stride':
        models = einput(entities, 'M')
        stride_app = Stride()
        result = stride_app(entities)['StdOut'].readlines()
        result = stride_parser(result)
        xtradata(result, structures.values()[0][(0, )])
    else:
        raise ValueError('Not a valid mode: "%s"' % mode)
    return result
Beispiel #8
0
def asa_xtra(entities, mode='internal', xtra_key=None, **asa_kwargs):
    """Calculates accessible surface areas (ASA) and puts the results into the
    xtra dictionaries of entities.
    
    Arguments:
    
        - entities: an entity or sequence of entities
        - mode(str): 'internal' for calculations using the built-in cython code 
          or 'stride' if the stride binary should be called to do the job.
        - xtra_key(str): Key in the xtra dictionary to hold the result for each
          entity
    
    Additional keyworded arguments are passed to the ``_prepare_asa`` and 
    ``_run_asa`` functions.
    """
    xtra_key = xtra_key or 'ASA'
    structures = einput(entities, 'S')
    if len(structures.values()) > 1:
        raise ValueError('Entities from multiple structures are not supported.')
    if mode == 'internal':
        _prepare_entities(entities) # mask waters
        result = _prepare_asa(entities, **asa_kwargs) # calculate ASA
        _postpare_entities(entities) # unmask waters
        result = dict([(id, {xtra_key:v}) for id, v in result.iteritems()])
        xtradata(result, structures)
    elif mode == 'stride':
        models = einput(entities, 'M')
        stride_app = Stride()
        result = stride_app(entities)['StdOut'].readlines()
        result = stride_parser(result)
        xtradata(result, structures.values()[0][(0,)])
    else:
        raise ValueError('Not a valid mode: "%s"' % mode)
    return result
Beispiel #9
0
 def test_asa_xtra(self):
     """test internal asa"""
     self.input_file = os.path.join('data', '2E12.pdb')
     self.input_structure = PDBParser(open(self.input_file))
     self.assertRaises(ValueError, asa.asa_xtra, self.input_structure, mode='a')
     result = asa.asa_xtra(self.input_structure)
     a = einput(self.input_structure, 'A')
     for i in range(len(result)):
         self.assertEquals(result.values()[i]['ASA'], a[result.keys()[i]].xtra['ASA'])
     r = einput(self.input_structure, 'R')
     for water in  r.selectChildren('H_HOH', 'eq', 'name').values():
         self.assertFalse('ASA' in water.xtra)
     for residue in  r.selectChildren('H_HOH', 'ne', 'name').values():
         for a in residue:
             self.assertTrue('ASA' in a.xtra)
     result = asa.asa_xtra(self.input_structure, xtra_key='SASA')
     for residue in  r.selectChildren('H_HOH', 'ne', 'name').values():
         for a in residue:
             a.xtra['ASA'] == a.xtra['SASA']
Beispiel #10
0
def XYZRNWriter(f, entities, radius_type=None, header=None, trailer=None):
    """Function which writes XYZRN files from ``Entity`` instances."""
    radius_type = (radius_type or 'AREAIMOL_VDW_RADII')

    structure = einput(entities, level='A', name='structure')
    header = write_header(header)
    coords = write_coords(structure, radius_type)
    trailer = write_trailer(trailer)

    for part in chain(header, coords, trailer):
        f.writelines(part)
Beispiel #11
0
def XYZRNWriter(f, entities, radius_type=None, header=None, trailer=None):
    """Function which writes XYZRN files from ``Entity`` instances."""
    radius_type = (radius_type or 'AREAIMOL_VDW_RADII')

    structure = einput(entities, level='A', name='structure')
    header = write_header(header)
    coords = write_coords(structure, radius_type)
    trailer = write_trailer(trailer)

    for part in chain(header, coords, trailer):
        f.writelines(part)
Beispiel #12
0
 def test_uc(self):
     """compares asa within unit cell."""
     self.input_file = os.path.join('data', '2E12.pdb')
     self.input_structure = PDBParser(open(self.input_file))
     asa.asa_xtra(self.input_structure, symmetry_mode='uc', xtra_key='ASA_UC')
     asa.asa_xtra(self.input_structure)
     self.input_structure.propagateData(sum, 'A', 'ASA', xtra=True)
     self.input_structure.propagateData(sum, 'A', 'ASA_UC', xtra=True)
     residues = einput(self.input_structure, 'R')
     x = residues[('2E12', 0, 'B', ('GLU', 77, ' '))].xtra.values()
     self.assertTrue(x[0] != x[1])
Beispiel #13
0
 def test_stride_xtra(self):
     """tests if residues get annotated with parsed data."""
     stride_xtra(self.input_structure)
     self.assertEquals(\
         self.input_structure[(0,)][('A',)][(('H_HOH', 138, ' '),)].xtra, {})
     self.assertAlmostEquals(\
         self.input_structure[(0,)][('A',)][(('ILE', 86, ' '),)].xtra['STRIDE_ASA'], 13.9)
     self.input_structure[(0,)][('A',)].remove_hetero()
     self.input_structure[(0,)][('B',)].remove_hetero()
     all_residues = einput(self.input_structure, 'R')
     a = all_residues.data_children('STRIDE_ASA', xtra=True, forgiving=False)
Beispiel #14
0
 def test_surface_xtra(self):
     res = surface_xtra(self.input_structure)
     assert res.shape == (12658, 3) or res.shape == (25859, 3)
     assert res is self.input_structure.xtra['MSMS_SURFACE']
     chains = einput(self.input_structure, 'C')
     chainA, chainB = chains.sortedvalues()
     resA = surface_xtra(chainA)
     assert len(resA) == 6223 or len(resA) == 12965
     resB = surface_xtra(chainB)
     assert len(resB) == 6620 or len(resB) == 13390
     assert chainB.xtra['MSMS_SURFACE'] is resB is \
     self.input_structure[(0,)][('B',)].xtra['MSMS_SURFACE']
Beispiel #15
0
 def test_surface_xtra(self):
     res = surface_xtra(self.input_structure)
     assert res.shape == (12658, 3) or res.shape == (25859, 3)
     assert res is self.input_structure.xtra['MSMS_SURFACE']
     chains = einput(self.input_structure, 'C')
     chainA, chainB = chains.sortedvalues()
     resA = surface_xtra(chainA)
     assert len(resA) == 6223 or len(resA) == 12965
     resB = surface_xtra(chainB)
     assert len(resB) == 6620 or len(resB) == 13390
     assert chainB.xtra['MSMS_SURFACE'] is resB is \
     self.input_structure[(0,)][('B',)].xtra['MSMS_SURFACE']
Beispiel #16
0
def _prepare_entities(entities):
    """Prepares input entities for ASA calculation, which includes masking water
    molecules and water chains.
    """
    # First we mask all water residues and chains with all residues masked 
    # (water chains).
    lattice_residues = einput(entities, 'R')
    lattice_residues.maskChildren('H_HOH', 'eq', 'name')
    lattice_chains = einput(entities, 'C')
    lattice_chains.maskChildren([], 'eq', 'values', method=True)
    # if no residues or chains are left - no atoms to work with, 
    # abort with warning.
    if not lattice_chains.values():
        # the following makes sure that masking changes by the above
        # tests are reverted.
        lattice_structures = einput(entities, 'S')
        lattice_structures.setUnmasked(force=True)
        raise ValueError('No unmasked atoms to build lattice.')
    # these are all atoms we can work with
    lattice_atoms = einput(entities, 'A')
    lattice_atoms.dispatch('setRadius')
Beispiel #17
0
def stride_xtra(entities, **kwargs):
    """Runs the stride application and maps the result on the residue xtra
    dictionaries.
    """
    structures = einput(entities, 'S')
    if len(structures.values()) > 1:
        raise ValueError('Entities from multiple structures are not supported.')
    stride_app = Stride(**kwargs)
    result = stride_app(entities)['StdOut'].readlines()
    result = stride_parser(result)
    xtradata(result, structures.values()[0][(0,)])
    return result
Beispiel #18
0
def stride_xtra(entities, **kwargs):
    """Runs the stride application and maps the result on the residue xtra
    dictionaries.
    """
    structures = einput(entities, 'S')
    if len(structures.values()) > 1:
        raise ValueError('Entities from multiple structures are not supported.')
    stride_app = Stride(**kwargs)
    result = stride_app(entities)['StdOut'].readlines()
    result = stride_parser(result)
    xtradata(result, structures.values()[0][(0,)])
    return result
Beispiel #19
0
def _prepare_entities(entities):
    """Prepares input entities for ASA calculation, which includes masking water
    molecules and water chains.
    """
    # First we mask all water residues and chains with all residues masked
    # (water chains).
    lattice_residues = einput(entities, 'R')
    lattice_residues.maskChildren('H_HOH', 'eq', 'name')
    lattice_chains = einput(entities, 'C')
    lattice_chains.maskChildren([], 'eq', 'values', method=True)
    # if no residues or chains are left - no atoms to work with,
    # abort with warning.
    if not lattice_chains.values():
        # the following makes sure that masking changes by the above
        # tests are reverted.
        lattice_structures = einput(entities, 'S')
        lattice_structures.setUnmasked(force=True)
        raise ValueError('No unmasked atoms to build lattice.')
    # these are all atoms we can work with
    lattice_atoms = einput(entities, 'A')
    lattice_atoms.dispatch('setRadius')
Beispiel #20
0
 def test_stride_xtra(self):
     """tests if residues get annotated with parsed data."""
     stride_xtra(self.input_structure)
     self.assertEquals(\
         self.input_structure[(0,)][('A',)][(('H_HOH', 138, ' '),)].xtra, {})
     self.assertAlmostEquals(\
         self.input_structure[(0,)][('A',)][(('ILE', 86, ' '),)].xtra['STRIDE_ASA'], 13.9)
     self.input_structure[(0, )][('A', )].remove_hetero()
     self.input_structure[(0, )][('B', )].remove_hetero()
     all_residues = einput(self.input_structure, 'R')
     a = all_residues.data_children('STRIDE_ASA',
                                    xtra=True,
                                    forgiving=False)
 def test_1expand_crystal(self):
     """tests the expansion of a unit-cell to a crystal"""
     fh = open(fn, 'r')
     input_structure = PDBParser(fh)
     self.assertTrue(input_structure.values(), 4) # 4 models
     sh = expand_crystal(input_structure)
     self.assertTrue(len(sh) == 27)
     fd, fn2 = tempfile.mkstemp('.pdb')
     os.close(fd)
     fh = open(fn2, 'w')
     a1 = einput(input_structure, 'A')
     a2 = einput(sh.values()[3], 'A')
     k = a1.values()[99].getFull_id()
     name = sh.values()[3].name
     a1c = a1[k].coords
     a2c = a2[(name,) + k[1:]].coords
     self.assertTrue(len(a1), len(a2))
     self.assertRaises(AssertionError, self.assertFloatEqual, a1c, a2c)
     PDBWriter(fh, sh)
     fh.close()
     os.unlink(fn)
     os.unlink(fn2)
Beispiel #22
0
 def test_uc2(self):
     self.input_file = os.path.join('data', '1LJO.pdb')
     self.input_structure = PDBParser(open(self.input_file))
     asa.asa_xtra(self.input_structure, symmetry_mode='uc', xtra_key='ASA_XTAL')
     asa.asa_xtra(self.input_structure)
     self.input_structure.propagateData(sum, 'A', 'ASA', xtra=True)
     self.input_structure.propagateData(sum, 'A', 'ASA_XTAL', xtra=True)
     residues = einput(self.input_structure, 'R')
     r1 = residues[('1LJO', 0, 'A', ('ARG', 65, ' '))]
     r2 = residues[('1LJO', 0, 'A', ('ASN', 46, ' '))]
     self.assertFloatEqual(r1.xtra.values(),
                           [128.94081270529105, 22.807700865674093])
     self.assertFloatEqual(r2.xtra.values(),
                           [115.35738419425566, 115.35738419425566])
Beispiel #23
0
def expand_symmetry(model, mode='uc', name='UC', **kwargs):
    """Applies the symmetry operations defined by the header of the PDB files to
    the given ``Model`` entity instance. Returns a ``ModelHolder`` entity.
    
    Arguments:
    
        - model: model entity to expand
        - mode: 'uc', 'bio' or 'raw'
        - name: optional name of the ``ModelHolder`` instance.
    
    Requires a PDB file with a correct CRYST1 field and space group information.
    """
    structure = model.getParent('S')
    sh = structure.header
    fmx = sh['uc_fmx']
    omx = sh['uc_omx']
    mxs = sh['uc_mxs']
    # get initial coordinates
    atoms = einput(model, 'A')
    coords = array(atoms.getData('coords'))
    # expand the coordinates to symmetry
    all_coords = coords_to_symmetry(coords, fmx, omx, mxs, mode)
    models = ModelHolder(name)

    for i in xrange(0, len(mxs)):
        # copy model
        new_model = copy(model)  # with additional models which
        new_atoms = einput(new_model, 'A')
        # patch with coordinates
        new_coords = all_coords[i]
        for (atom_id, new_coord) in izip(atoms.keys(), new_coords):
            new_atoms[atom_id[1:]].coords = new_coord
        # give it an id: the models are numbered by the symmetry operations with
        # identity being the first model
        new_model.setName(i)
        models.addChild(new_model)
    return models
Beispiel #24
0
def expand_symmetry(model, mode='uc', name='UC', **kwargs):
    """Applies the symmetry operations defined by the header of the PDB files to
    the given ``Model`` entity instance. Returns a ``ModelHolder`` entity.
    
    Arguments:
    
        - model: model entity to expand
        - mode: 'uc', 'bio' or 'raw'
        - name: optional name of the ``ModelHolder`` instance.
    
    Requires a PDB file with a correct CRYST1 field and space group information.
    """
    structure = model.getParent('S')
    sh = structure.header
    fmx = sh['uc_fmx']
    omx = sh['uc_omx']
    mxs = sh['uc_mxs']
    # get initial coordinates
    atoms = einput(model, 'A')
    coords = array(atoms.getData('coords'))
    # expand the coordinates to symmetry
    all_coords = coords_to_symmetry(coords, fmx, omx, mxs, mode)
    models = ModelHolder(name)

    for i in xrange(0, len(mxs)):
        # copy model
        new_model = copy(model) # with additional models which
        new_atoms = einput(new_model, 'A')
        # patch with coordinates
        new_coords = all_coords[i]
        for (atom_id, new_coord) in izip(atoms.keys(), new_coords):
            new_atoms[atom_id[1:]].coords = new_coord
        # give it an id: the models are numbered by the symmetry operations with
        # identity being the first model
        new_model.setName(i)
        models.addChild(new_model)
    return models
Beispiel #25
0
 def test_einput(self):
     """tests einput."""
     structures = einput(self.input_structure, 'S')
     models = einput(self.input_structure, 'M')
     chains = einput(self.input_structure, 'C')
     residues = einput(self.input_structure, 'R')
     atoms = einput(self.input_structure, 'A')
     self.assertEquals(structures.level, 'H')
     self.assertEquals(models.level, 'S')
     self.assertEquals(chains.level, 'M')
     self.assertEquals(residues.level, 'C')
     self.assertEquals(atoms.level, 'R')
     atoms2 = einput(models, 'A')
     self.assertEquals(atoms, atoms2)
     atoms3 = einput(chains, 'A')
     self.assertEquals(atoms, atoms3)
     structures2 = einput(atoms, 'S')
     self.assertEquals(self.input_structure, structures2.values()[0])
     residues2 = einput(atoms, 'R')
     self.assertEquals(residues, residues2)
Beispiel #26
0
 def test_einput(self):
     """tests einput."""
     structures = einput(self.input_structure, 'S')
     models = einput(self.input_structure, 'M')
     chains = einput(self.input_structure, 'C')
     residues = einput(self.input_structure, 'R')
     atoms = einput(self.input_structure, 'A')
     self.assertEquals(structures.level, 'H')
     self.assertEquals(models.level, 'S')
     self.assertEquals(chains.level, 'M')
     self.assertEquals(residues.level, 'C')
     self.assertEquals(atoms.level, 'R')
     atoms2 = einput(models, 'A')
     self.assertEquals(atoms, atoms2)
     atoms3 = einput(chains, 'A')
     self.assertEquals(atoms, atoms3)
     structures2 = einput(atoms, 'S')
     self.assertEquals(self.input_structure, structures2.values()[0])
     residues2 = einput(atoms, 'R')
     self.assertEquals(residues, residues2)
Beispiel #27
0
def PDBXWriter(f, entities, level, b_key, b_mode=None, b_val=0.0, q_key=None, \
               q_mode=None, q_val=0.0):
    """Writes data from the ``xtra`` dictionary into B and Q columns of a 
    PDB file. The level from which the dictionary is taken can be specified.
    The b_key and q_key specifies should be a key in the dictionaries, b_val and
    q_val are the default values, b_mode and q_mode can be "number" - 
    ``float`` will be called to transform the data or "iterable" which will 
    return the length (``len``) of the sequence.
    The B and Q columns can contain only numeric values, thus any data which we 
    wish to store in those columns needs to be converted. The following 
    functions convert data to numeric form. boolean type can also be treated as
    number.
    """

    b_mode = (b_mode or 'number')  # B
    q_mode = (q_mode or 'number')  # Q

    entities = einput(entities, level)

    for entity in entities:
        q_data = eval(q_mode)(entity.xtra.get(q_key), b_val)  # occupancy
        b_data = eval(b_mode)(entity.xtra.get(b_key), q_val)  # b-factor

        if level != 'A':
            atoms = einput(entity, 'A')
            for atom in atoms:
                if b_key:
                    atom.setBfactor(b_data)
                if q_key:
                    atom.setOccupancy(q_data)
        else:
            if b_key:
                entity.setBfactor(b_data)
            if q_key:
                entity.setOccupancy(q_data)
    PDBWriter(f, entities)  # we try to preserve the headers
Beispiel #28
0
 def _test_bio(self):
     """compares asa within a bio unit."""
     self.input_file = os.path.join('data', '1A1X.pdb')
     self.input_structure = PDBParser(open(self.input_file))
     asa.asa_xtra(self.input_structure, symmetry_mode='bio', xtra_key='ASA_BIO')
     asa.asa_xtra(self.input_structure)
     self.input_structure.propagateData(sum, 'A', 'ASA', xtra=True)
     self.input_structure.propagateData(sum, 'A', 'ASA_BIO', xtra=True)
     residues = einput(self.input_structure, 'R')
     r1 = residues[('1A1X', 0, 'A', ('GLU', 37, ' '))]
     r2 = residues[('1A1X', 0, 'A', ('TRP', 15, ' '))]
     self.assertFloatEqual(r1.xtra.values(), \
                             [20.583191467544726, 78.996394472066541])
     self.assertFloatEqual(r2.xtra.values(), \
                             [136.41436710386989, 136.41436710386989])
Beispiel #29
0
def PDBWriter(f, entities, header_=None, trailer_=None):
        structure = einput(entities, level='A', name='atoms')
        # hierarchy: args, dicts
        try:
            header = (header_ or entities.raw_header or entities.header)
        except AttributeError:
            header = header_
        try:
            trailer = (trailer_ or entities.raw_trailer or entities.trailer)
        except AttributeError:
            trailer = trailer_
        coords = write_coords(structure)
        header = write_header(header)
        trailer = write_trailer(trailer)
        for part in chain(header, coords, trailer):
            f.writelines(part)
Beispiel #30
0
def PDBWriter(f, entities, header_=None, trailer_=None):
    structure = einput(entities, level='A', name='atoms')
    # hierarchy: args, dicts
    try:
        header = (header_ or entities.raw_header or entities.header)
    except AttributeError:
        header = header_
    try:
        trailer = (trailer_ or entities.raw_trailer or entities.trailer)
    except AttributeError:
        trailer = trailer_
    coords = write_coords(structure)
    header = write_header(header)
    trailer = write_trailer(trailer)
    for part in chain(header, coords, trailer):
        f.writelines(part)
Beispiel #31
0
 def test_compare(self):
     """compares internal asa to stride."""
     self.input_file = os.path.join('data', '2E12.pdb')
     self.input_structure = PDBParser(open(self.input_file))
     try:
         asa.asa_xtra(self.input_structure, mode='stride')
     except ApplicationNotFoundError: 
         return            
     asa.asa_xtra(self.input_structure)
     self.input_structure.propagateData(sum, 'A', 'ASA', xtra=True)
     residues = einput(self.input_structure, 'R')
     asa1 = []
     asa2 = []
     for residue in  residues.selectChildren('H_HOH', 'ne', 'name').values():
         asa1.append(residue.xtra['ASA'])
         asa2.append(residue.xtra['STRIDE_ASA'])
     self.assertAlmostEqual(correlation(asa1, asa2)[1], 0.)
Beispiel #32
0
 def test_compare(self):
     """compares internal asa to stride."""
     self.input_file = os.path.join('data', '2E12.pdb')
     self.input_structure = PDBParser(open(self.input_file))
     try:
         asa.asa_xtra(self.input_structure, mode='stride')
     except ApplicationNotFoundError:
         return
     asa.asa_xtra(self.input_structure)
     self.input_structure.propagateData(sum, 'A', 'ASA', xtra=True)
     residues = einput(self.input_structure, 'R')
     asa1 = []
     asa2 = []
     for residue in residues.selectChildren('H_HOH', 'ne', 'name').values():
         asa1.append(residue.xtra['ASA'])
         asa2.append(residue.xtra['STRIDE_ASA'])
     self.assertAlmostEqual(correlation(asa1, asa2)[1], 0.)
Beispiel #33
0
 def test_crystal(self):
     """compares asa within unit cell."""
     self.input_file = os.path.join('data', '2E12.pdb')
     self.input_structure = PDBParser(open(self.input_file))
     asa.asa_xtra(self.input_structure, symmetry_mode='uc', crystal_mode=2, xtra_key='ASA_XTAL')
     asa.asa_xtra(self.input_structure)
     self.input_structure.propagateData(sum, 'A', 'ASA', xtra=True)
     self.input_structure.propagateData(sum, 'A', 'ASA_XTAL', xtra=True)
     residues = einput(self.input_structure, 'R')
     r1 = residues[('2E12', 0, 'A', ('ALA', 42, ' '))]
     r2 = residues[('2E12', 0, 'A', ('VAL', 8, ' '))]
     r3 = residues[('2E12', 0, 'A', ('LEU', 25, ' '))]
     self.assertFloatEqual(r1.xtra.values(), \
                             [32.041070749038823, 32.041070749038823])
     self.assertFloatEqual(r3.xtra.values(), \
                            [0., 0.])
     self.assertFloatEqual(r2.xtra.values(), \
                             [28.873559956056916, 0.0])
Beispiel #34
0
def contacts_xtra(query, xtra_key=None, **cnt_kwargs):
    """Finds distance contacts between entities. This function searches for 
    contacts for query entities (query) either within the asymmetric unit,
    biological molecule, unit-cell or crystal.
    
    Arguments:
        
        - query (entitie[s]): query entity or sequence entities
        - xtra_key (str): name of the key
        
    Additional keyworded arguments are passed to the ``_prepare_contacts`` 
    functon.
    """
    xtra_key = xtra_key or 'CONTACTS'
    structures = einput(query, 'S')
    if len(structures.values()) > 1:
        raise ValueError('Entities from multiple structures are not supported.')
    result = _prepare_contacts(query, **cnt_kwargs) # calculate CONTACTS
    result = dict([(id, {xtra_key:v}) for id, v in result.iteritems()])
    xtradata(result, structures)
    return result
Beispiel #35
0
def contacts_xtra(query, xtra_key=None, **cnt_kwargs):
    """Finds distance contacts between entities. This function searches for 
    contacts for query entities (query) either within the asymmetric unit,
    biological molecule, unit-cell or crystal.
    
    Arguments:
        
        - query (entitie[s]): query entity or sequence entities
        - xtra_key (str): name of the key
        
    Additional keyworded arguments are passed to the ``_prepare_contacts`` 
    functon.
    """
    xtra_key = xtra_key or 'CONTACTS'
    structures = einput(query, 'S')
    if len(list(structures.values())) > 1:
        raise ValueError('Entities from multiple structures are not supported.')
    result = _prepare_contacts(query, **cnt_kwargs) # calculate CONTACTS
    result = dict([(id, {xtra_key:v}) for id, v in result.items()])
    xtradata(result, structures)
    return result
Beispiel #36
0
def _prepare_asa(entities, symmetry_mode=None, crystal_mode=None, points=960, \
                **kwargs):
    """Prepares the atomic solvent-accessible surface area (ASA) calculation.
    
    Arguments:
    
        - entities: input entities for ASA calculation (most commondly a 
          structure entity).
        - symmetry_mode (str): One of 'uc', 'bio' or 'table'. This defines the 
          transformations of applied to the coordinates of the input entities. 
          It is one of 'bio', 'uc' or 'table'. Where 'bio' and 'uc' are 
          transformations to create the biological molecule or unit-cell from 
          the PDB header. The 'table' uses transformation matrices derived from 
          space-group information only using crystallographic tables(requires 
          ``cctbx``).
        - crystal_mode (int): Defines the number of unit-cells to expand the 
          initial unit-cell into. The number of unit-cells in each direction 
          i.e. 1 is makes a total of 27 unit cells: (-1, 0, 1) == 3, 3^3 == 27
        - points: number of points on atom spheres higher is slower but more 
          accurate.    

    Additional keyworded arguments are passed to the ``_run_asa`` function.
    """
    # generate uniform points on the unit-sphere
    spoints = sphere_points(points)
    # prepare entities for asa calculation
    # free-floating area mode
    result = {}
    atoms = einput(entities, 'A')
    if not symmetry_mode and not crystal_mode:

        coords = array(atoms.getData('coords', forgiving=False))
        coords = array([[coords]])  # fake 3D and 4D
        idx_to_id = dict(enumerate(atoms.getData('getFull_id', \
                                                forgiving=False, method=True)))
        asas = _run_asa(atoms, coords, spoints, **kwargs)
        for idx in xrange(asas.shape[0]):
            result[idx_to_id[idx]] = asas[idx]
    # crystal-contact area mode
    elif symmetry_mode in ('table', 'uc'):
        structure = einput(entities, 'S').values()[0]
        sh = structure.header
        coords = array(atoms.getData('coords', forgiving=False))
        idx_to_id = dict(enumerate(atoms.getData('getFull_id', \
                                                forgiving=False, method=True)))
        # expand to unit-cell, real 3D
        coords = coords_to_symmetry(coords, \
                                            sh[symmetry_mode + '_fmx'], \
                                            sh[symmetry_mode + '_omx'], \
                                            sh[symmetry_mode + '_mxs'], \
                                            symmetry_mode)
        # expand to crystal, real 4D
        if crystal_mode:
            coords = coords_to_crystal(coords, \
                                               sh[symmetry_mode + '_fmx'], \
                                               sh[symmetry_mode + '_omx'], \
                                               crystal_mode) # real 4D
        else:
            coords = array([coords])  # fake 4D
        asas = _run_asa(atoms, coords, spoints, **kwargs)
        for idx in xrange(asas.shape[0]):
            result[idx_to_id[idx]] = asas[idx]

    # biological area mode
    elif symmetry_mode == 'bio':
        structure = einput(entities, 'S').values()[0]
        chains = einput(entities, 'C')
        sh = structure.header
        start = 0
        for chain_ids, mx_num in sh['bio_cmx']:
            sel = chains.selectChildren(chain_ids, 'contains', 'id').values()
            atoms = einput(sel, 'A')
            coords = array(atoms.getData('coords', forgiving=False))
            idx_to_id = dict(enumerate(atoms.getData('getFull_id', \
                                              forgiving=False, method=True)))
            stop = start + mx_num
            coords = coords_to_symmetry(coords, \
                                               sh['uc_fmx'], \
                                               sh['uc_omx'], \
                                               sh['bio_mxs'][start:stop], \
                                               symmetry_mode)
            coords = array([coords])
            start = stop
            asas = _run_asa(atoms, coords, spoints, **kwargs)
            for idx in xrange(asas.shape[0]):
                result[idx_to_id[idx]] = asas[idx]
    return result
Beispiel #37
0
def clean_ical(entities, pretend=True, mask=True):
    """Removes or masks entities with ambiguous (i)nsertion (c)odes or 
    (a)lternate (l)ocations.
    
    Arguments:
    
        - entities: universal input see: ``cogent.struct.selection.einput``
        - pretend: If ``True`` only reports icals and does not mask or remove 
          anything.
        - mask (boolean): If pretend is ``False`` masks entities instead of 
          removing them.
   
    This function does not check for occupancy. I retains the residue which is 
    first when sorted by id number, insertion code and finally name. Residues 
    without IC come first. Atoms within a retained residue are sorted according 
    to PDB rules and the first one is chosen. If The first entity has an IC or 
    alt_loc different from ' ' it will be changed to ' '.
    """
    conflicts = []
    changes = []
    residues = einput(entities, 'R')
    id_r = [[None, None, None]]
    for r in residues.sortedvalues():  # sort by id, ic, name
        id_a = [[None, None]]
        if r.res_id == id_r[0][1]:      # on collision choose first ...
            conflicts.append(r.getFull_id())
            if not pretend:
                if mask:
                    r.setMasked(True)
                else:
                    r.parent.delChild(r.id)
            continue                    # an entity could be in other holders
        # keep it there as-is
        for a in r.sortedvalues():     # sort by id, alt_loc (' ', 'A' ...)
            if a.at_id == id_a[0][0]:   # on collision choose first
                conflicts.append(a.getFull_id())
                if not pretend:
                    if mask:
                        a.setMasked(True)
                    else:
                        r.delChild(a.id)
            else:
                if a.id[0][1] != ' ':
                    changes.append((a.getFull_id(), ((a.id[0][0], ' '),)))
                    if not pretend:
                        a.setAlt_loc(' ')
                        try:
                            a.parent.updateIds()
                        except AttributeError:
                            pass
                id_a = a.id
        if r.id[0][2] != ' ':
            changes.append((r.getFull_id(), ((r.id[0][0], r.id[0][1], ' '),)))
            if not pretend:
                r.set_res_ic(' ')
                try:
                    r.parent.updateIds()
                except AttributeError:
                    pass
        id_r = r.id
    return (changes, conflicts)
Beispiel #38
0
def _postpare_entities(entities):
    """Restores entities after ASA calculation, which includes unmasking."""
    structures = einput(entities, 'S')
    structures.setUnmasked(force=True)
Beispiel #39
0
def _prepare_contacts(query, model=None, level='A', search_limit=6.0, \
                      contact_mode='diff_chain', symmetry_mode=None, \
                      crystal_mode=None, **kwargs):
    """Prepares distance contact calculations.
    
    Arguments:
    
        - query(entitie[s]): query entitie[s] for contact calculation 
          (most commonly a structure entity).
        - model(entity): a Model entity which will be transformed according to
          symmetry_mode and crystal_mode. (most commonly it is the same as the
          query)
        - level(str): The level in the hierarchy at which distances will be 
          calculated (most commonly 'A' for atoms) 
        - search_limit(float): maximum distance in Angstrom's
        - contact_mode(str): One of "diff_cell", "diff_sym", "diff_chain".
          Defines the allowed contacts i.e. requires that contacts are by 
          entities, which have: "diff_cell" different unit cells; "diff_sym" 
          different symmetry operators (if in the same unit cell) "diff_chain" 
          with different chain ids (if in the same unit cell and symmetry).
        - symmetry_mode (str): One of 'uc', 'bio' or 'table'. This defines the 
          transformations of applied to the coordinates of the input entities. 
          It is one of 'bio', 'uc' or 'table'. Where 'bio' and 'uc' are 
          transformations to create the biological molecule or unit-cell from 
          the PDB header. The 'table' uses transformation matrices derived from 
          space-group information only using crystallographic tables(requires 
          ``cctbx``).        
        - crystal_mode (int): Defines the number of unit-cells to expand the 
          initial unit-cell into. The number of unit cells in each direction 
          i.e. 1 is makes a total of 27 unit cells: (-1, 0, 1) == 3, 3^3 == 27
    
    Additional arguments are passed to the ``cnt_loop`` Cython function.
    """

    contact_mode = {
        'diff_asu': 0,
        'diff_sym': 1,
        'diff_chain': 2
    }[contact_mode]

    # determine unique structure
    structure = einput(query, 'S').values()[0]
    sh = structure.header
    # if not specified otherwise the lattice is the first model
    lattice = model or structure[(0, )]
    lents = einput(lattice, level)
    lents_ids = lents.getData('getFull_id', forgiving=False, method=True)
    lcoords = array(lents.getData('coords', forgiving=False))
    qents = einput(query, level)
    qents_ids = qents.getData('getFull_id', forgiving=False, method=True)
    qcoords = array(qents.getData('coords', forgiving=False))

    if symmetry_mode:
        if symmetry_mode == 'table':
            lcoords = coords_to_symmetry(lcoords, \
                                         sh['table_fmx'], \
                                         sh['table_omx'], \
                                         sh['table_mxs'], \
                                         symmetry_mode)
        elif symmetry_mode == 'uc':
            lcoords = coords_to_symmetry(lcoords, \
                                         sh['uc_fmx'], \
                                         sh['uc_omx'], \
                                         sh['uc_mxs'], \
                                         symmetry_mode)
        elif symmetry_mode == 'bio':
            # TODO see asa
            raise ValueError("Unsupported symmetry_mode: %s" % symmetry_mode)
        else:
            raise ValueError("Unsupported symmetry_mode: %s" % symmetry_mode)
    else:
        lcoords = array([lcoords])  # fake 3D
    if crystal_mode:
        zero_tra = {1: 13, 2: 62, 3: 171}[crystal_mode]
        # 0,0,0 translation is: Thickened cube numbers:
        # a(n)=n*(n^2+(n-1)^2)+(n-1)*2*n*(n-1).
        # 1, 14, 63, 172, 365, 666, 1099, 1688, 2457, 3430, 4631, 6084, 7813 ...
        if symmetry_mode == 'table':
            lcoords = coords_to_crystal(lcoords, \
                                        sh['table_fmx'], \
                                        sh['table_omx'], \
                                        crystal_mode)
        elif symmetry_mode == 'uc':
            lcoords = coords_to_crystal(lcoords, \
                                        sh['uc_fmx'], \
                                        sh['uc_omx'], \
                                        crystal_mode)
        else:
            raise ValueError('crystal_mode not possible for "bio" symmetry')
    else:
        zero_tra = 0
        lcoords = array([lcoords])  # fake 4D
    shape = lcoords.shape
    lcoords = lcoords.reshape((shape[0] * shape[1] * shape[2], shape[3]))
    box = r_[qcoords.min(axis=0) - search_limit, \
             qcoords.max(axis=0) + search_limit]
    lc = []  # lattice chain
    qc = []  # query chain
    lchains = [i[2] for i in lents_ids]
    qchains = [i[2] for i in qents_ids]
    allchains = set()
    allchains.update(lchains)
    allchains.update(qchains)
    chain2id = dict(zip(allchains, range(len(allchains))))
    for lent_id in lents_ids:
        lc.append(chain2id[lent_id[2]])
    for qent_id in qents_ids:
        qc.append(chain2id[qent_id[2]])
    lc = array(lc, dtype=int64)
    qc = array(qc, dtype=int64)
    # here we leave python
    (idxc, n_src, n_asu, n_sym, n_tra, n_dst) = cnt_loop(\
                            qcoords, lcoords, qc, lc, shape[1], shape[2], \
                            zero_tra, contact_mode, search_limit, box, \
                            **kwargs)

    result = defaultdict(dict)
    for contact in xrange(idxc):
        qent_id = qents_ids[n_src[contact]]
        lent_id = lents_ids[n_asu[contact]]
        result[qent_id][lent_id] = (sqrt(n_dst[contact]), n_tra[contact],
                                    n_sym[contact])
    return result
Beispiel #40
0
def _prepare_contacts(query, model=None, level='A', search_limit=6.0, \
                      contact_mode='diff_chain', symmetry_mode=None, \
                      crystal_mode=None, **kwargs):
    """Prepares distance contact calculations.
    
    Arguments:
    
        - query(entitie[s]): query entitie[s] for contact calculation 
          (most commonly a structure entity).
        - model(entity): a Model entity which will be transformed according to
          symmetry_mode and crystal_mode. (most commonly it is the same as the
          query)
        - level(str): The level in the hierarchy at which distances will be 
          calculated (most commonly 'A' for atoms) 
        - search_limit(float): maximum distance in Angstrom's
        - contact_mode(str): One of "diff_cell", "diff_sym", "diff_chain".
          Defines the allowed contacts i.e. requires that contacts are by 
          entities, which have: "diff_cell" different unit cells; "diff_sym" 
          different symmetry operators (if in the same unit cell) "diff_chain" 
          with different chain ids (if in the same unit cell and symmetry).
        - symmetry_mode (str): One of 'uc', 'bio' or 'table'. This defines the 
          transformations of applied to the coordinates of the input entities. 
          It is one of 'bio', 'uc' or 'table'. Where 'bio' and 'uc' are 
          transformations to create the biological molecule or unit-cell from 
          the PDB header. The 'table' uses transformation matrices derived from 
          space-group information only using crystallographic tables(requires 
          ``cctbx``).        
        - crystal_mode (int): Defines the number of unit-cells to expand the 
          initial unit-cell into. The number of unit cells in each direction 
          i.e. 1 is makes a total of 27 unit cells: (-1, 0, 1) == 3, 3^3 == 27
    
    Additional arguments are passed to the ``cnt_loop`` Cython function.
    """

    contact_mode = {'diff_asu'  :0,
                    'diff_sym' :1,
                    'diff_chain':2 }[contact_mode]

    # determine unique structure
    structure = einput(query, 'S').values()[0]
    sh = structure.header
    # if not specified otherwise the lattice is the first model
    lattice = model or structure[(0,)]
    lents = einput(lattice, level)
    lents_ids = lents.getData('getFull_id', forgiving=False, method=True)
    lcoords = array(lents.getData('coords', forgiving=False))
    qents = einput(query, level)
    qents_ids = qents.getData('getFull_id', forgiving=False, method=True)
    qcoords = array(qents.getData('coords', forgiving=False))

    if symmetry_mode:
        if symmetry_mode == 'table':
            lcoords = coords_to_symmetry(lcoords, \
                                         sh['table_fmx'], \
                                         sh['table_omx'], \
                                         sh['table_mxs'], \
                                         symmetry_mode)
        elif symmetry_mode == 'uc':
            lcoords = coords_to_symmetry(lcoords, \
                                         sh['uc_fmx'], \
                                         sh['uc_omx'], \
                                         sh['uc_mxs'], \
                                         symmetry_mode)
        elif symmetry_mode == 'bio':
            # TODO see asa
            raise ValueError("Unsupported symmetry_mode: %s" % symmetry_mode)
        else:
            raise ValueError("Unsupported symmetry_mode: %s" % symmetry_mode)
    else:
        lcoords = array([lcoords]) # fake 3D
    if crystal_mode:
        zero_tra = {1:13, 2:62, 3:171}[crystal_mode]
        # 0,0,0 translation is: Thickened cube numbers: 
        # a(n)=n*(n^2+(n-1)^2)+(n-1)*2*n*(n-1).
        # 1, 14, 63, 172, 365, 666, 1099, 1688, 2457, 3430, 4631, 6084, 7813 ...
        if symmetry_mode == 'table':
            lcoords = coords_to_crystal(lcoords, \
                                        sh['table_fmx'], \
                                        sh['table_omx'], \
                                        crystal_mode)
        elif symmetry_mode == 'uc':
            lcoords = coords_to_crystal(lcoords, \
                                        sh['uc_fmx'], \
                                        sh['uc_omx'], \
                                        crystal_mode)
        else:
            raise ValueError('crystal_mode not possible for "bio" symmetry')
    else:
        zero_tra = 0
        lcoords = array([lcoords]) # fake 4D
    shape = lcoords.shape
    lcoords = lcoords.reshape((shape[0] * shape[1] * shape[2], shape[3]))
    box = r_[qcoords.min(axis=0) - search_limit, \
             qcoords.max(axis=0) + search_limit]
    lc = [] # lattice chain
    qc = [] # query chain
    lchains = [i[2] for i in lents_ids]
    qchains = [i[2] for i in qents_ids]
    allchains = set()
    allchains.update(lchains)
    allchains.update(qchains)
    chain2id = dict(zip(allchains, range(len(allchains))))
    for lent_id in lents_ids:
        lc.append(chain2id[lent_id[2]])
    for qent_id in qents_ids:
        qc.append(chain2id[qent_id[2]])
    lc = array(lc, dtype=int64)
    qc = array(qc, dtype=int64)
    # here we leave python
    (idxc, n_src, n_asu, n_sym, n_tra, n_dst) = cnt_loop(\
                            qcoords, lcoords, qc, lc, shape[1], shape[2], \
                            zero_tra, contact_mode, search_limit, box, \
                            **kwargs)

    result = defaultdict(dict)
    for contact in xrange(idxc):
        qent_id = qents_ids[n_src[contact]]
        lent_id = lents_ids[n_asu[contact]]
        result[qent_id][lent_id] = (sqrt(n_dst[contact]), n_tra[contact], n_sym[contact])
    return result
Beispiel #41
0
def _postpare_entities(entities):
    """Restores entities after ASA calculation, which includes unmasking."""
    structures = einput(entities, 'S')
    structures.setUnmasked(force=True)
Beispiel #42
0
def _prepare_asa(entities, symmetry_mode=None, crystal_mode=None, points=960, \
                **kwargs):
    """Prepares the atomic solvent-accessible surface area (ASA) calculation.
    
    Arguments:
    
        - entities: input entities for ASA calculation (most commondly a 
          structure entity).
        - symmetry_mode (str): One of 'uc', 'bio' or 'table'. This defines the 
          transformations of applied to the coordinates of the input entities. 
          It is one of 'bio', 'uc' or 'table'. Where 'bio' and 'uc' are 
          transformations to create the biological molecule or unit-cell from 
          the PDB header. The 'table' uses transformation matrices derived from 
          space-group information only using crystallographic tables(requires 
          ``cctbx``).
        - crystal_mode (int): Defines the number of unit-cells to expand the 
          initial unit-cell into. The number of unit-cells in each direction 
          i.e. 1 is makes a total of 27 unit cells: (-1, 0, 1) == 3, 3^3 == 27
        - points: number of points on atom spheres higher is slower but more 
          accurate.    

    Additional keyworded arguments are passed to the ``_run_asa`` function.
    """
    # generate uniform points on the unit-sphere
    spoints = sphere_points(points)
    # prepare entities for asa calculation
    # free-floating area mode
    result = {}
    atoms = einput(entities, 'A')
    if not symmetry_mode and not crystal_mode:

        coords = array(atoms.getData('coords', forgiving=False))
        coords = array([[coords]]) # fake 3D and 4D
        idx_to_id = dict(enumerate(atoms.getData('getFull_id', \
                                                forgiving=False, method=True)))
        asas = _run_asa(atoms, coords, spoints, **kwargs)
        for idx in xrange(asas.shape[0]):
            result[idx_to_id[idx]] = asas[idx]
    # crystal-contact area mode    
    elif symmetry_mode in ('table', 'uc'):
        structure = einput(entities, 'S').values()[0]
        sh = structure.header
        coords = array(atoms.getData('coords', forgiving=False))
        idx_to_id = dict(enumerate(atoms.getData('getFull_id', \
                                                forgiving=False, method=True)))
        # expand to unit-cell, real 3D
        coords = coords_to_symmetry(coords, \
                                            sh[symmetry_mode + '_fmx'], \
                                            sh[symmetry_mode + '_omx'], \
                                            sh[symmetry_mode + '_mxs'], \
                                            symmetry_mode)
        # expand to crystal, real 4D
        if crystal_mode:
            coords = coords_to_crystal(coords, \
                                               sh[symmetry_mode + '_fmx'], \
                                               sh[symmetry_mode + '_omx'], \
                                               crystal_mode) # real 4D
        else:
            coords = array([coords]) # fake 4D
        asas = _run_asa(atoms, coords, spoints, **kwargs)
        for idx in xrange(asas.shape[0]):
            result[idx_to_id[idx]] = asas[idx]

     # biological area mode
    elif symmetry_mode == 'bio':
        structure = einput(entities, 'S').values()[0]
        chains = einput(entities, 'C')
        sh = structure.header
        start = 0
        for chain_ids, mx_num in sh['bio_cmx']:
            sel = chains.selectChildren(chain_ids, 'contains', 'id').values()
            atoms = einput(sel, 'A')
            coords = array(atoms.getData('coords', forgiving=False))
            idx_to_id = dict(enumerate(atoms.getData('getFull_id', \
                                              forgiving=False, method=True)))
            stop = start + mx_num
            coords = coords_to_symmetry(coords, \
                                               sh['uc_fmx'], \
                                               sh['uc_omx'], \
                                               sh['bio_mxs'][start:stop], \
                                               symmetry_mode)
            coords = array([coords])
            start = stop
            asas = _run_asa(atoms, coords, spoints, **kwargs)
            for idx in xrange(asas.shape[0]):
                result[idx_to_id[idx]] = asas[idx]
    return result
Beispiel #43
0
def clean_ical(entities, pretend=True, mask=True):
    """Removes or masks entities with ambiguous (i)nsertion (c)odes or 
    (a)lternate (l)ocations.
    
    Arguments:
    
        - entities: universal input see: ``cogent.struct.selection.einput``
        - pretend: If ``True`` only reports icals and does not mask or remove 
          anything.
        - mask (boolean): If pretend is ``False`` masks entities instead of 
          removing them.
   
    This function does not check for occupancy. I retains the residue which is 
    first when sorted by id number, insertion code and finally name. Residues 
    without IC come first. Atoms within a retained residue are sorted according 
    to PDB rules and the first one is chosen. If The first entity has an IC or 
    alt_loc different from ' ' it will be changed to ' '.
    """
    conflicts = []
    changes = []
    residues = einput(entities, 'R')
    id_r = [[None, None, None]]
    for r in residues.sortedvalues():  # sort by id, ic, name
        id_a = [[None, None]]
        if r.res_id == id_r[0][1]:  # on collision choose first ...
            conflicts.append(r.getFull_id())
            if not pretend:
                if mask:
                    r.setMasked(True)
                else:
                    r.parent.delChild(r.id)
            continue  # an entity could be in other holders
        # keep it there as-is
        for a in r.sortedvalues():  # sort by id, alt_loc (' ', 'A' ...)
            if a.at_id == id_a[0][0]:  # on collision choose first
                conflicts.append(a.getFull_id())
                if not pretend:
                    if mask:
                        a.setMasked(True)
                    else:
                        r.delChild(a.id)
            else:
                if a.id[0][1] != ' ':
                    changes.append((a.getFull_id(), ((a.id[0][0], ' '), )))
                    if not pretend:
                        a.setAlt_loc(' ')
                        try:
                            a.parent.updateIds()
                        except AttributeError:
                            pass
                id_a = a.id
        if r.id[0][2] != ' ':
            changes.append((r.getFull_id(), ((r.id[0][0], r.id[0][1], ' '), )))
            if not pretend:
                r.set_res_ic(' ')
                try:
                    r.parent.updateIds()
                except AttributeError:
                    pass
        id_r = r.id
    return (changes, conflicts)