@staticmethod
def CoarseGrain(pdb_table):
    """ Selects DNA atoms from a pdb table and returns a table containing only the coarse-grained atoms for 3SPN2"""
    masses = {'H': 1.00794, 'C': 12.0107, 'N': 14.0067, 'O': 15.9994, 'P': 
        30.973762}
    CG = {"O5'": 'P', "C5'": 'S', "C4'": 'S', "O4'": 'S', "C3'": 'S', "O3'":
        'P', "C2'": 'S', "C1'": 'S', 'O5*': 'P', 'C5*': 'S', 'C4*': 'S',
        'O4*': 'S', 'C3*': 'S', 'O3*': 'P', 'C2*': 'S', 'C1*': 'S', 'N1':
        'B', 'C2': 'B', 'O2': 'B', 'N2': 'B', 'N3': 'B', 'C4': 'B', 'N4':
        'B', 'C5': 'B', 'C6': 'B', 'N9': 'B', 'C8': 'B', 'O6': 'B', 'N7':
        'B', 'N6': 'B', 'O4': 'B', 'C7': 'B', 'P': 'P', 'OP1': 'P', 'OP2':
        'P', 'O1P': 'P', 'O2P': 'P', 'OP3': 'P', "HO5'": 'P', "H5'": 'S',
        "H5''": 'S', "H4'": 'S', "H3'": 'S', "H2'": 'S', "H2''": 'S', "H1'":
        'S', 'H8': 'B', 'H61': 'B', 'H62': 'B', 'H2': 'B', 'H1': 'B', 'H21':
        'B', 'H22': 'B', 'H3': 'B', 'H71': 'B', 'H72': 'B', 'H73': 'B',
        'H6': 'B', 'H41': 'B', 'H42': 'B', 'H5': 'B', "HO3'": 'P'}
    cols = ['recname', 'serial', 'name', 'altLoc', 'resname', 'chainID',
        'resSeq', 'iCode', 'x', 'y', 'z', 'occupancy', 'tempFactor',
        'element', 'charge', 'type']
    temp = pdb_table.copy()
    temp = temp[temp['resname'].isin(['DA', 'DT', 'DG', 'DC'])]
    temp['group'] = temp['name'].replace(CG)
    temp = temp[temp['group'].isin(['P', 'S', 'B'])]
    for c in temp['chainID'].unique():
        sel = temp.loc[(temp['name'] == "O3'") & (temp['chainID'] == c),
            'resSeq']
        temp.loc[(temp['name'] == "O3'") & (temp['chainID'] == c), 'resSeq'
            ] = list(sel)[1:] + [-1]
        sel = temp.loc[(temp['name'] == "O3'") & (temp['chainID'] == c),
            'resname']
        temp.loc[(temp['name'] == "O3'") & (temp['chainID'] == c), 'resname'
            ] = list(sel)[1:] + [-1]
    temp = temp[temp['resSeq'] > 0]
    temp['element'] = temp['element'].str.strip()
    temp['mass'] = temp.element.replace(masses).astype(float)
    temp[['x', 'y', 'z']] = (temp[['x', 'y', 'z']].T * temp['mass']).T[['x',
        'y', 'z']]
    temp = temp[temp['element'] != 'H']
    Coarse = temp.groupby(['chainID', 'resSeq', 'resname', 'group']).sum(
        ).reset_index()
    Coarse[['x', 'y', 'z']] = (Coarse[['x', 'y', 'z']].T / Coarse['mass']).T[
        ['x', 'y', 'z']]
    Coarse['recname'] = 'ATOM'
    Coarse['name'] = Coarse['group']
    Coarse['altLoc'] = ''
    Coarse['iCode'] = ''
    Coarse['charge'] = ''
    mask = Coarse.name == 'B'
    Coarse.loc[mask, 'name'] = Coarse[mask].resname.str[-1]
    Coarse['type'] = Coarse['name']
    Coarse['element'] = Coarse['name'].replace({'P': 'P', 'S': 'H', 'A':
        'N', 'T': 'S', 'G': 'C', 'C': 'O'})
    drop_list = []
    for chain in Coarse.chainID.unique():
        sel = Coarse[Coarse.chainID == chain]
        drop_list += list(sel[(sel.resSeq == sel.resSeq.min()) & sel['name'
            ].isin(['P'])].index)
    Coarse = Coarse.drop(drop_list)
    Coarse.index = range(len(Coarse))
    Coarse['serial'] = Coarse.index
    return Coarse[cols]
