text: user12036: I am currently implementing some metrics I could use for comparing two conformations of the same protein in Python.
  For example, I know I could use the RMSD of all protein ATOMS in BioPandas using this:
  biopandas.pdb.PandasPdb.rmsd(conformation1.df['ATOM'], conformation2.df['ATOM'])
  
  Are there some out-of-the-box tools in Python for measuring the RMSD between the side chains of the two conformations? When trying to do this manually, the main issue is how to identify side chain atoms, which is not clear for me. I know how to get all atoms from a residue using BioPandas:
  aminoacids = list(PandasPdb().read_pdb(my_pdb_filename).df['ATOM'].groupby(['chain_id', 'residue_number', 'residue_name']))
  
  Now aminoacids[i] is a dataframe containing all the atoms of the i-th aminoacid, like this:
  
  From here, it's not clear how to separate back bone atoms from side chain atoms. It's clear that the one with atom_number 'CA' will be the alpha-Carbon, but I am not sure how to identify the others. But once the separation is done, the side chain RMSD could be measure for example using Bio.SVDSuperimposer.SVDSuperimposer which works directly on the array of 3D coordinates of the atoms.
  Thanks!
  
  user12054: As you suggest one way of solving your problem would be by selecting all atoms that don't have backbone atoms names. In a pdb file I believe backbone atoms would be named 'CA', 'HA', 'N', 'HN' or 'H', 'C' and 'O'. Beware of the N-terminal (where the hydrogens would be named either 'H1', 'H2' & 'H3'; or 'HN1', 'HN2' and 'HN3') and the C-terminal (the other oxygen would be named 'OXT').
  One way of doing it is by using the handy selections from pandas dataframes. It's probably a more elegant way than making a list of dataframes.
  from biopandas.pdb import PandasPdb
  
  bpdf_1 = PandasPdb().fetch_pdb('1t48').df['ATOM']
  bpdf_2 = PandasPdb().fetch_pdb('1t49').df['ATOM']
  
  # Function returns a list of boolean. True when it's not a backbone atom.
  sel = lambda df: df['atom_name'].str.contains('[^(CA|HA|N|C|O|HN|H)]$')
  
  # The number of atom is not the same, so I only align the first 200
  sidechain_rmsd = PandasPdb.rmsd(bpdf_1[sel][:200], bpdf_2[sel][:200])
  
  The regex says something like "(not (CA or HA or …)) end of line". The end of line is important, otherwise any atom containing N, C, O or H in their name would be excluded (so most of them).
  Note that with this method it's still possible to use the PandasPdb selectors. For example, to only consider heavy atoms (no hydrogen):
  sidechain_rmsd = PandasPdb.rmsd(bpdf_1[sel][:200],
                                  bpdf_2[sel][:200],
                                  s='heavy')
  
  EDIT:
  Another way to do it would be:
  sidechain_rmsd = PandasPdb.rmsd(bpdf_1[:200],
                                  bpdf_2[:200],
                                  s='main chain',
                                  invert=True)
  
  You don't need any selection in this case, BUT this is a bad idea if you have hydrogens, as it will also align them (including the backbone ones).
  
original_text: 12036: <p>I am currently implementing some metrics I could use for comparing two conformations of the same protein in Python.</p>
  <p>For example, I know I could use the RMSD of all protein ATOMS in BioPandas using this:</p>
  <pre><code>biopandas.pdb.PandasPdb.rmsd(conformation1.df['ATOM'], conformation2.df['ATOM'])
  </code></pre>
  <p>Are there some out-of-the-box tools in Python for measuring the RMSD between the side chains of the two conformations? When trying to do this manually, the main issue is how to identify side chain atoms, which is not clear for me. I know how to get all atoms from a residue using BioPandas:</p>
  <pre><code>aminoacids = list(PandasPdb().read_pdb(my_pdb_filename).df['ATOM'].groupby(['chain_id', 'residue_number', 'residue_name']))
  </code></pre>
  <p>Now <code>aminoacids[i]</code> is a dataframe containing all the atoms of the i-th aminoacid, like this:</p>
  <p><a href="https://i.stack.imgur.com/9RnK2.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/9RnK2.png" alt="enter image description here" /></a></p>
  <p>From here, it's not clear how to separate back bone atoms from side chain atoms. It's clear that the one with atom_number 'CA' will be the alpha-Carbon, but I am not sure how to identify the others. But once the separation is done, the side chain RMSD could be measure for example using <code>Bio.SVDSuperimposer.SVDSuperimposer</code> which works directly on the array of 3D coordinates of the atoms.</p>
  <p>Thanks!</p>
   12054: <p>As you suggest one way of solving your problem would be by selecting all atoms that don't have backbone atoms names. In a pdb file I believe backbone atoms would be named 'CA', 'HA', 'N', 'HN' or 'H', 'C' and 'O'. Beware of the N-terminal (where the hydrogens would be named either 'H1', 'H2' &amp; 'H3'; or 'HN1', 'HN2' and 'HN3') and the C-terminal (the other oxygen would be named 'OXT').</p>
  <p>One way of doing it is by using the handy selections from pandas dataframes. It's probably a more elegant way than making a list of dataframes.</p>
  <pre class="lang-py prettyprint-override"><code>from biopandas.pdb import PandasPdb
  
  bpdf_1 = PandasPdb().fetch_pdb('1t48').df['ATOM']
  bpdf_2 = PandasPdb().fetch_pdb('1t49').df['ATOM']
  
  # Function returns a list of boolean. True when it's not a backbone atom.
  sel = lambda df: df['atom_name'].str.contains('[^(CA|HA|N|C|O|HN|H)]$')
  
  # The number of atom is not the same, so I only align the first 200
  sidechain_rmsd = PandasPdb.rmsd(bpdf_1[sel][:200], bpdf_2[sel][:200])
  </code></pre>
  <p>The regex says something like &quot;(not (CA or HA or …)) end of line&quot;. The end of line is important, otherwise any atom containing N, C, O or H in their name would be excluded (so most of them).</p>
  <p>Note that with this method it's still possible to use the PandasPdb selectors. For example, to only consider heavy atoms (no hydrogen):</p>
  <pre class="lang-py prettyprint-override"><code>sidechain_rmsd = PandasPdb.rmsd(bpdf_1[sel][:200],
                                  bpdf_2[sel][:200],
                                  s='heavy')
  </code></pre>
  <p><strong>EDIT:</strong></p>
  <p>Another way to do it would be:</p>
  <pre class="lang-py prettyprint-override"><code>sidechain_rmsd = PandasPdb.rmsd(bpdf_1[:200],
                                  bpdf_2[:200],
                                  s='main chain',
                                  invert=True)
  </code></pre>
  <p>You don't need any selection in this case, <strong>BUT</strong> this is a bad idea if you have hydrogens, as it will also align them (including the backbone ones).</p>
  