<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.pymol.org/index.php?action=history&amp;feed=atom&amp;title=Flatten_obj</id>
	<title>Flatten obj - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.pymol.org/index.php?action=history&amp;feed=atom&amp;title=Flatten_obj"/>
	<link rel="alternate" type="text/html" href="https://wiki.pymol.org/index.php?title=Flatten_obj&amp;action=history"/>
	<updated>2026-07-18T08:28:58Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.35.1</generator>
	<entry>
		<id>https://wiki.pymol.org/index.php?title=Flatten_obj&amp;diff=13311&amp;oldid=prev</id>
		<title>Bell: 2 revisions</title>
		<link rel="alternate" type="text/html" href="https://wiki.pymol.org/index.php?title=Flatten_obj&amp;diff=13311&amp;oldid=prev"/>
		<updated>2015-11-16T05:01:05Z</updated>

		<summary type="html">&lt;p&gt;2 revisions&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left diff-editfont-monospace&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 05:01, 16 November 2015&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Bell</name></author>
	</entry>
	<entry>
		<id>https://wiki.pymol.org/index.php?title=Flatten_obj&amp;diff=13310&amp;oldid=prev</id>
		<title>Sbliven: Removing incorrect API section</title>
		<link rel="alternate" type="text/html" href="https://wiki.pymol.org/index.php?title=Flatten_obj&amp;diff=13310&amp;oldid=prev"/>
		<updated>2015-11-03T13:29:20Z</updated>

		<summary type="html">&lt;p&gt;Removing incorrect API section&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left diff-editfont-monospace&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 13:29, 3 November 2015&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l59&quot; &gt;Line 59:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 59:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;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;&quot;&gt;&lt;div&gt;     flatten_obj flat, nmrObj&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;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;&quot;&gt;&lt;div&gt;     flatten_obj flat, nmrObj&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;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;&quot;&gt;&lt;div&gt;     flatten_obj ( obj1 or obj2 )&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;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;&quot;&gt;&lt;div&gt;     flatten_obj ( obj1 or obj2 )&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;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;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot;&gt; &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;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;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;= PyMol API =&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot;&gt; &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;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;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot;&gt; &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;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;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;    cmd.flatten_obj(string name, string selection)&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot;&gt; &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;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;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot;&gt; &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;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;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;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;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;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;&quot;&gt;&lt;div&gt;= See Also =&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;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;&quot;&gt;&lt;div&gt;= See Also =&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Sbliven</name></author>
	</entry>
	<entry>
		<id>https://wiki.pymol.org/index.php?title=Flatten_obj&amp;diff=13309&amp;oldid=prev</id>
		<title>Sbliven: Replacing code with github link</title>
		<link rel="alternate" type="text/html" href="https://wiki.pymol.org/index.php?title=Flatten_obj&amp;diff=13309&amp;oldid=prev"/>
		<updated>2015-10-30T15:59:00Z</updated>

		<summary type="html">&lt;p&gt;Replacing code with github link&lt;/p&gt;
&lt;a href=&quot;//wiki.pymol.org/index.php?title=Flatten_obj&amp;amp;diff=13309&amp;amp;oldid=13109&quot;&gt;Show changes&lt;/a&gt;</summary>
		<author><name>Sbliven</name></author>
	</entry>
	<entry>
		<id>https://wiki.pymol.org/index.php?title=Flatten_obj&amp;diff=13109&amp;oldid=prev</id>
		<title>Bell: 1 revision</title>
		<link rel="alternate" type="text/html" href="https://wiki.pymol.org/index.php?title=Flatten_obj&amp;diff=13109&amp;oldid=prev"/>
		<updated>2015-10-30T15:53:35Z</updated>

		<summary type="html">&lt;p&gt;1 revision&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left diff-editfont-monospace&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 15:53, 30 October 2015&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Bell</name></author>
	</entry>
	<entry>
		<id>https://wiki.pymol.org/index.php?title=Flatten_obj&amp;diff=13108&amp;oldid=prev</id>
		<title>Sbliven: Creating page</title>
		<link rel="alternate" type="text/html" href="https://wiki.pymol.org/index.php?title=Flatten_obj&amp;diff=13108&amp;oldid=prev"/>
		<updated>2015-10-30T14:15:33Z</updated>

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