https://pymolwiki.org/index.php?title=Flatten_obj&feed=atom&action=history
Flatten obj - Revision history
2024-03-29T11:01:48Z
Revision history for this page on the wiki
MediaWiki 1.35.7
https://pymolwiki.org/index.php?title=Flatten_obj&diff=12204&oldid=prev
Sbliven: Removing incorrect API section
2015-11-03T13:29:20Z
<p>Removing incorrect API section</p>
<table class="diff diff-contentalign-left diff-editfont-monospace" data-mw="interface">
<col class="diff-marker" />
<col class="diff-content" />
<col class="diff-marker" />
<col class="diff-content" />
<tr class="diff-title" lang="en">
<td colspan="2" style="background-color: #fff; color: #202122; text-align: center;">← Older revision</td>
<td colspan="2" style="background-color: #fff; color: #202122; text-align: center;">Revision as of 13:29, 3 November 2015</td>
</tr><tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l59" >Line 59:</td>
<td colspan="2" class="diff-lineno">Line 59:</td></tr>
<tr><td class='diff-marker'> </td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> flatten_obj flat, nmrObj</div></td><td class='diff-marker'> </td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> flatten_obj flat, nmrObj</div></td></tr>
<tr><td class='diff-marker'> </td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> flatten_obj ( obj1 or obj2 )</div></td><td class='diff-marker'> </td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> flatten_obj ( obj1 or obj2 )</div></td></tr>
<tr><td class='diff-marker'>−</td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div><del style="font-weight: bold; text-decoration: none;"></del></div></td><td colspan="2"> </td></tr>
<tr><td class='diff-marker'>−</td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div><del style="font-weight: bold; text-decoration: none;">= PyMol API =</del></div></td><td colspan="2"> </td></tr>
<tr><td class='diff-marker'>−</td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div><del style="font-weight: bold; text-decoration: none;"></del></div></td><td colspan="2"> </td></tr>
<tr><td class='diff-marker'>−</td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div><del style="font-weight: bold; text-decoration: none;"> cmd.flatten_obj(string name, string selection)</del></div></td><td colspan="2"> </td></tr>
<tr><td class='diff-marker'>−</td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div><del style="font-weight: bold; text-decoration: none;"></del></div></td><td colspan="2"> </td></tr>
<tr><td class='diff-marker'> </td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"></td><td class='diff-marker'> </td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"></td></tr>
<tr><td class='diff-marker'> </td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>= See Also =</div></td><td class='diff-marker'> </td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>= See Also =</div></td></tr>
</table>
Sbliven
https://pymolwiki.org/index.php?title=Flatten_obj&diff=12193&oldid=prev
Sbliven: Replacing code with github link
2015-10-30T15:59:00Z
<p>Replacing code with github link</p>
<a href="//pymolwiki.org/index.php?title=Flatten_obj&diff=12193&oldid=12192">Show changes</a>
Sbliven
https://pymolwiki.org/index.php?title=Flatten_obj&diff=12192&oldid=prev
Sbliven: Creating page
2015-10-30T14:15:33Z
<p>Creating page</p>
<p><b>New page</b></p><div>{{Infobox script-repo<br />
|type = script<br />
|download = Submitted to the [[Git_intro|Pymol-script-repo]] as flatten_obj.py<br />
|author = [[User:sbliven|Spencer Bliven]]<br />
|license = Public Domain<br />
}}<br />
<br />
= Description =<br />
<br />
The <code>flatten_obj</code> python script combines multiple objects or states into a single object,<br />
renaming chains where required.<br />
<br />
This is particularly useful for dealing with biological assemblies, which are<br />
loaded as multi-state objects when fetched using <code>[[fetch]] PDBID, type=pdb1</code>. It<br />
can also be used as a quick way to combine multiple objects without causing<br />
collisions between chain identifiers.<br />
<br />
The command re-letters chains to avoid collisions. Older versions of PyMOL<br />
restrict the chain id to a single character, so the script will fail for<br />
assemblies with >62 chains. With more recent versions, this problem is solved<br />
with multi-character chain IDs. Several options are available for how<br />
re-lettering should occur.<br />
<br />
= Usage =<br />
<br />
flatten_obj name, selection[, state[, rename[, quiet[, chain_map]]]]<br />
<br />
= Arguments =<br />
<br />
* name = a unique name for the flattened object {default: flat}<br />
<br />
* selection = the set of objects to include in the flattening. The selection will be expanded to include all atoms of objects. {default: all}<br />
<br />
* state = the source state to select. Use 0 or -1 to flatten all states {default: 0}<br />
<br />
* rename = The scheme to use for renaming chains: {default: 0}<br />
** (0) preserve chains IDs where possible, rename other chains alphabetically<br />
** (1) rename all chains alphabetically<br />
** (2) rename chains using the original chain letter, object name, and state<br />
<br />
* quiet = If set to 0, print some additional information about progress and chain renaming {default: 1}<br />
<br />
* chain_map = An attribute name for the 'stored' scratch object. If specified, `stored.<chain_map>` will be populated with a dictionary mapping the new chain names to a tuple giving the originated object, state, and chainID. {default: ""}<br />
<br />
= Notes = <br />
<br />
Like the select command, if name is omitted then the default object name<br />
("flat") is used as the name argument.<br />
<br />
Chain renaming is tricky. PDB files originally limited chains to single<br />
letter identifiers containing [A-Za-z0-9]. When this was found to be<br />
limiting, multi-letter chains (ideally < 4 chars) were allowed. This is<br />
supported as of PyMOL 1.7. Earlier versions do not accept rename=2, and<br />
will raise an exception when flattening a structure with more than 62<br />
chains.<br />
<br />
= Examples = <br />
<br />
flatten_obj flat, nmrObj<br />
flatten_obj ( obj1 or obj2 )<br />
<br />
= PyMol API =<br />
<br />
cmd.flatten_obj(string name, string selection)<br />
<br />
<br />
<br />
= Code =<br />
<br />
<syntaxhighlight lang="python"><br />
"""<br />
flatten_obj.py - Flatten multi-state pymol objects into a single state.<br />
<br />
This is particularly useful for dealing with biological assemblies, which are<br />
loaded as multi-state objects when fetched using `fetch PDBID, type=pdb1`. It<br />
can also be used as a quick way to combine multiple objects without causing<br />
collisions between chain identifiers.<br />
<br />
The command re-letters chains to avoid collisions. Older versions of PyMOL<br />
restrict the chain id to a single character, so the script will fail for<br />
assemblies with >62 chains. With more recent versions, this problem is solved<br />
with multi-character chain IDs. Several options are available for how<br />
re-lettering should occur.<br />
<br />
Author: Spencer Bliven <spencer.bliven@gmail.com><br />
Date: October 30, 2015<br />
Version: 1.0<br />
License: Public Domain<br />
"""<br />
from pymol import cmd, stored<br />
import re<br />
try:<br />
from collections import OrderedDict<br />
_orderedDict = True<br />
except ImportError:<br />
_orderedDict = False<br />
<br />
# PyMOL 1.7.4 introduces support for multi-letter chains, so we can afford to<br />
# use a smaller alphabet. In earlier versions, use lower-case letters if needed<br />
# (requires running `set ignore_case, 0`)<br />
_long_chains = cmd.get_version()[1] >= 1.74<br />
_default_base = 36 if _long_chains else 62<br />
<br />
class OutOfChainsError(Exception):<br />
def __init__(self,msg):<br />
self.msg=msg<br />
def __str__(self):<br />
return str(self.msg)<br />
<br />
class ChainSet(object):<br />
"""<br />
Base class for various methods to rename chains<br />
<br />
Contains _chains, which maps from the renamed chain to a tuple with the<br />
original (object,state,chain). All dict-like accessors work on ChainSets,<br />
e.g.<br />
chain_set["A"] -> ("obj",1,"A")<br />
<br />
"""<br />
def __init__(self):<br />
# Use an OrderedDict in Python >= 1.7 for better printing<br />
if _orderedDict:<br />
self._chains = OrderedDict()<br />
else:<br />
self._chains = dict()<br />
<br />
def map_chain(self, obj, state, origChain ):<br />
"""<br />
map_chain(string obj,int state, string chain]]) -> string<br />
<br />
Maps a chain letter to a unique chainID. Results are unique within each<br />
instance, and can be used as keys on this chain set.<br />
"""<br />
raise NotImplementedError("Base class")<br />
<br />
# delegate most methods to _chains<br />
def __getattr__(self,at):<br />
if at in "pop popitem update setdefault".split():<br />
raise AttributeError("type object '%s' has no attribute '%s'"%(type(self),at))<br />
return getattr(self._chains,at)<br />
def __cmp__(self,other): return self._chains.__cmp__(other)<br />
def __eq__(self,other): return self._chains.__eq__(other)<br />
def __ge__(self,other): return self._chains.__ge__(other)<br />
def __gt__(self,other): return self._chains.__gt__(other)<br />
def __le__(self,other): return self._chains.__le__(other)<br />
def __lt__(self,other): return self._chains.__lt__(other)<br />
def __ne__(self,other): return self._chains.__ne__(other)<br />
def __len__(self): return self._chains.__len__()<br />
def __contains__(self,key): return self._chains.__contains__(key)<br />
def __getitem__(self,key): return self._chains.__getitem__(key)<br />
def __iter__(self): return self._chains.__iter__()<br />
def __str__(self): return str(self._chains)<br />
<br />
@staticmethod<br />
def _int_to_chain(i,base=_default_base):<br />
"""<br />
_int_to_chain(int,int) -> str<br />
<br />
Converts a positive integer to a chain ID. Chain IDs include uppercase<br />
characters, numbers, and optionally lowercase letters.<br />
<br />
i = a positive integer to convert<br />
base = the alphabet size to include. Typically 36 or 62.<br />
"""<br />
if i < 0:<br />
raise ValueError("positive integers only")<br />
if base < 0 or 62 < base:<br />
raise ValueError("Invalid base")<br />
<br />
quot = int(i)/base<br />
rem = i%base<br />
if rem < 26:<br />
letter = chr( ord("A") + rem)<br />
elif rem < 36:<br />
letter = str( rem-26)<br />
else:<br />
letter = chr( ord("a") + rem - 36)<br />
if quot == 0:<br />
return letter<br />
else:<br />
return ChainSet._int_to_chain(quot-1,base) + letter<br />
<br />
<br />
class DefaultChainSet(ChainSet):<br />
"""<br />
Avoids relettering chains if possible. If a chain has been used, uses the<br />
next available chain letter. Note that this can potentially lead to<br />
cascading renames, e.g. if chains are sorted alphabetically rather than by<br />
object.<br />
<br />
Used for rename = 0.<br />
"""<br />
def __init__(self):<br />
super(DefaultChainSet,self).__init__()<br />
self._next_chain = 0<br />
def map_chain(self, obj, state, origChain ):<br />
# Keep _next_chain up-to-date<br />
while ChainSet._int_to_chain(self._next_chain) in self:<br />
self._next_chain += 1<br />
# Map this chain<br />
if origChain in self:<br />
# Rename<br />
next_chain = ChainSet._int_to_chain(self._next_chain)<br />
self._next_chain += 1<br />
else:<br />
next_chain = origChain<br />
self._chains[next_chain] = (obj,state,origChain)<br />
return next_chain<br />
<br />
class SequentialChainSet(ChainSet):<br />
"""<br />
Renumbers all chains starting at A, continuing through the capital letters<br />
and numbers, and then adding additional letters through 9999 (the last<br />
valid chain for mmCIF) and beyond.<br />
<br />
Used for rename=1<br />
"""<br />
def __init__(self):<br />
super(SequentialChainSet,self).__init__()<br />
self._next_chain = 0<br />
<br />
def map_chain(self, obj, state, origChain ):<br />
next_chain = ChainSet._int_to_chain(self._next_chain)<br />
self._chains[next_chain] = (obj,state,origChain)<br />
self._next_chain += 1<br />
return next_chain<br />
<br />
class LongChainSet(ChainSet):<br />
"""<br />
Uses long strings for the chain names. Chains are renamed like<br />
"%s_%s_%04d"%(original_chainid,objectname,state).<br />
<br />
Used for rename=2<br />
"""<br />
def map_chain(self, obj, state, origChain ):<br />
ch = "%s_%s_%04d"%(origChain,obj,state)<br />
if self.has_key(ch):<br />
raise ValueError("Duplicate chain %s"%(ch))<br />
self._chains[ch] = (obj,state,origChain)<br />
return ch<br />
<br />
<br />
<br />
<br />
def flatten_obj(name="",selection="",state=0,rename=0,quiet=1,chain_map=""):<br />
"""<br />
DESCRIPTION<br />
<br />
"flatten_obj" combines multiple objects or states into a single object,<br />
renaming chains where required<br />
<br />
USAGE<br />
<br />
flatten_obj name, selection[, state[, rename[, quiet[, chain_map]]]]<br />
<br />
ARGUMENTS<br />
<br />
name = a unique name for the flattened object {default: flat}<br />
<br />
selection = the set of objects to include in the flattening. The selection<br />
will be expanded to include all atoms of objects. {default: all}<br />
<br />
state = the source state to select. Use 0 or -1 to flatten all states {default: 0}<br />
<br />
rename = The scheme to use for renaming chains: {default: 0}<br />
(0) preserve chains IDs where possible, rename other chains<br />
alphabetically<br />
(1) rename all chains alphabetically<br />
(2) rename chains using the original chain letter, object name, and state<br />
<br />
quiet = If set to 0, print some additional information about progress and<br />
chain renaming {default: 1}<br />
<br />
chain_map = An attribute name for the 'stored' scratch object. If<br />
specified, `stored.<chain_map>` will be populated with a dictionary<br />
mapping the new chain names to a tuple giving the originated object,<br />
state, and chainID. {default: ""}<br />
<br />
NOTES<br />
<br />
Like the select command, if name is omitted then the default object name<br />
("flat") is used as the name argument.<br />
<br />
Chain renaming is tricky. PDB files originally limited chains to single<br />
letter identifiers containing [A-Za-z0-9]. When this was found to be<br />
limiting, multi-letter chains (ideally < 4 chars) were allowed. This is<br />
supported as of PyMOL 1.7. Earlier versions do not accept rename=2, and<br />
will raise an exception when flattening a structure with more than 62<br />
chains.<br />
<br />
EXAMPLES<br />
<br />
flatten_obj flat, nmrObj<br />
flatten_obj ( obj1 or obj2 )<br />
<br />
PYMOL API<br />
<br />
cmd.flatten_obj(string name, string selection)<br />
<br />
SEE ALSO<br />
<br />
split_states<br />
<br />
"""<br />
<br />
# arguments<br />
<br />
# Single argument; treat as selection<br />
if name and not selection:<br />
selection = name<br />
name = ""<br />
# default name and selection<br />
if not name:<br />
name = "flat"<br />
if not selection:<br />
selection = "(all)"<br />
<br />
state = int(state)<br />
rename = int(rename)<br />
quiet = int(quiet)<br />
<br />
# Wrap in extra parantheses for get_object_list<br />
selection = "( %s )" % selection<br />
<br />
if rename == 0:<br />
chainSet = DefaultChainSet()<br />
elif rename == 1:<br />
chainSet = SequentialChainSet()<br />
elif rename == 2:<br />
chainSet = LongChainSet()<br />
else:<br />
raise ValueError("Unrecognized rename option (Valid: 0,1,2)")<br />
<br />
metaprefix = "temp" #TODO unique prefix<br />
<br />
# store original value of retain_order, which causes weird interleaving of<br />
# structures if enabled.<br />
retain_order = cmd.get("retain_order")<br />
try:<br />
cmd.set("retain_order",0)<br />
<br />
# create new object for each state<br />
for obj in cmd.get_object_list(selection):<br />
<br />
if state <= 0:<br />
# all states<br />
prefix = "%s_%s_"%(metaprefix,obj)<br />
cmd.split_states(obj,prefix=prefix)<br />
else:<br />
prefix = "%s_%s_%04d"%(metaprefix,obj,state)<br />
cmd.create(prefix, obj, state, 1)<br />
<br />
# renumber all states<br />
statere = re.compile("^%s_(.*)_(\d+)$" % metaprefix) # matches split object names<br />
<br />
warn_lowercase = False<br />
<br />
# Iterate over all objects with metaprefix<br />
try:<br />
for obj in cmd.get_object_list("(%s_*)"%(metaprefix) ):<br />
m = statere.match(obj)<br />
if m is None:<br />
print("Failed to match object %s" %obj)<br />
continue<br />
origobj = m.group(1)<br />
statenum = int(m.group(2))<br />
<br />
chains = set([atom.chain for atom in cmd.get_model(obj).atom])<br />
<br />
rev_chain_map = {} #old -> new, for this obj only<br />
for chain in sorted(chains):<br />
new_chain = chainSet.map_chain(origobj,statenum,chain)<br />
rev_chain_map[chain] = new_chain<br />
if not quiet:<br />
print(" %s state %d chain %s -> %s"%(origobj,statenum,chain, new_chain) )<br />
if not _long_chains:<br />
if len(new_chain) > 1:<br />
raise OutOfChainsError("No additional chains available (max 62).")<br />
<br />
try:<br />
stored_name = stored.get_unused_name()<br />
except AttributeError:<br />
# backup solution for PyMOL < 1.6<br />
stored_name = "_flatten_obj_chainMapping"<br />
<br />
setattr(stored,stored_name,rev_chain_map)<br />
cmd.alter(obj,"chain = stored.%s[chain]"%stored_name)<br />
delattr(stored,stored_name)<br />
<br />
print("Creating object from %s_*"%metaprefix)<br />
# Recombine into a single object<br />
cmd.create(name,"%s_*"%metaprefix)<br />
<br />
# Set chain_map<br />
if chain_map:<br />
setattr(stored,chain_map,chainSet)<br />
<br />
# Warn if lowercase chains were generated <br />
if cmd.get("ignore_case") == "on" and any([c.upper() != c for c in chainSet.keys()]):<br />
print("Warning: using lower-case chain IDs. Consider running the "<br />
"following command:\n set ignore_case, 0" )<br />
<br />
finally:<br />
# Clean up<br />
print("Cleaning up intermediates")<br />
cmd.delete("%s_*"%metaprefix)<br />
finally:<br />
# restore original parameters<br />
print("Resetting variables")<br />
cmd.set("retain_order",retain_order)<br />
<br />
<br />
cmd.extend('flatten_obj', flatten_obj)<br />
<br />
# tab-completion of arguments<br />
cmd.auto_arg[0]['flatten_obj'] = [ cmd.object_sc, 'name or selection', '']<br />
cmd.auto_arg[1]['flatten_obj'] = [ cmd.object_sc, 'selection', '']<br />
</syntaxhighlight><br />
<br />
= See Also =<br />
<br />
* [[split_states]]<br />
<br />
<br />
[[Category:Script_Library]] [[Category:ObjSel_Scripts]]</div>
Sbliven