def generate_atom_lists(complex_st, zeo_st, cmd_args):
    """
    Generate various list of atom indices.

    @param complex_st:  Merged structure of the zeolite and guest molecules.
    @type complex_st:   L{structure.Structure}

    @param zeo_st:  Original zeolite input structure.
    @type zeo_st:   L{structure.Structure}

    @param cmd_args:  All script arguments and options.
    @type cmd_args:  class:`argparse.Namespace`

    @return:  List of close atoms, silicon atoms, oxygen atoms, guest atoms and
    all atoms in the structure
    @rtype:  list, list, list, list, list
    """

    first_guest_atom = zeo_st.atom_total + 1
    last_guest_atom = complex_st.atom_total + 1

    all_atom_list = list(range(1, last_guest_atom))
    guest_atom_list = list(range(first_guest_atom, last_guest_atom))

    atoms_asl = "(atom.num %s)" % ', '.join(map(str, guest_atom_list))
    close_asl = "(within %s %s)" % (str(cmd_args.cutoff), atoms_asl)
    silicon_asl = "atom.element Si"
    oxygen_asl = "atom.element O"

    close_atom_list = analyze.evaluate_asl(complex_st, close_asl)
    silicon_atom_list = analyze.evaluate_asl(complex_st, silicon_asl)
    oxygen_atom_list = analyze.evaluate_asl(complex_st, oxygen_asl)

    return close_atom_list, silicon_atom_list, oxygen_atom_list, \
        guest_atom_list, all_atom_list
예제 #2
0
def RMSD(input, template):
    prototipe = []
    molecules_rmsd = []
    for structure in st.StructureReader(input):
        if structure.title == template[0]:
            core_atoms = ssa.evaluate_asl(structure, template[1])
            for atom in list(structure.atom):
                if atom.index in core_atoms:
                    raX = atom.x
                    raY = atom.y
                    raZ = atom.z
                    prototipe.append((raX, raY, raZ))
    for structure in st.StructureReader(input):
        if structure.title != template[0]:
            core_atoms = ssa.evaluate_asl(structure, template[1])
            rmsd = 0
            for atom in list(structure.atom):
                tmp_len = []
                if atom.index in core_atoms:
                    for pa in prototipe:
                        atoms_len = sqrt(
                            (pa[0] - atom.x) * (pa[0] - atom.x)
                            + (pa[1] - atom.y) * (pa[1] - atom.y)
                            + (pa[2] - atom.z) * (pa[2] - atom.z)
                        )
                        tmp_len.append(atoms_len)
                    rmsd += min(tmp_len)
        molecules_rmsd.append((structure.title, rmsd))
    return sorted(set(molecules_rmsd), key=lambda x: x[1])
예제 #3
0
def extract_st(cms_file, trj_dir, asl='all', frames=1):
    """
    Extract N frames from the trajectory and save them in structure.Structure

    :param cms_file:
    :param trj_dir:
    :param asl:
    :param frames: if int: number of frames uniformly distributed, if iterable: list fo frames
    :return structures: list of schrodinger.structure.Structure
    :type structures: list
    """
    structures = []
    msys_model, cms_model = topo.read_cms(cms_file)
    frame_arch = traj.read_traj(trj_dir)
    if type(frames) == int:
        for f in np.linspace(0, len(frame_arch) - 1, frames).astype(int):
            st = topo.update_cms(cms_model, frame_arch[f])
            st = st.extract(evaluate_asl(cms_model, asl))
            st.title = 'Frame {}'.format(f)
            structures.append(st)
    else:
        try:
            for f in frames:
                st = topo.update_cms(cms_model, frame_arch[f])
                st = st.extract(asl)
                st.title = 'Frame {}'.format(f)
                structures.append(st)
        except Exception as e:
            raise RuntimeError(e)

    return structures
예제 #4
0
def get_residues_from_radius(radius, ref):
    asl = 'fillres ((within %i ligand ) and not (res.ptype "T3P"))' % (int(float(radius)))
    st=StructureReader(ref).next()
    atoms=evaluate_asl(st, asl)
    if len(atoms)==0:
        print "NO LIGAND IN REFERENCE FILE"
        print "no ligand in reference file"
        sys.exit()
    pocket=st.extract(atoms)
    resnames=[i.pdbres for i in pocket.residue]
    resnums=[i.resnum for i in pocket.residue]
    chains=[i.chain for i in pocket.residue]
    data=dict()
    for chain in set(chains):
        for (n,c) in zip(resnums, chains):
            if c not in data.keys():
                data[c]=[]
            if str(n) not in data[c]:
                data[c].append(str(n))
    selection=[]
    for chain in data.keys():
        selection.append(','.join(data[chain]) + '.%s' % chain)
    if len(selection)==1:
        selection=[selection,]
    return selection
예제 #5
0
def get_residues_from_radius(radius, ref):
    asl = 'fillres ((within %i ligand ) and not (res.ptype "T3P"))' % (int(
        float(radius)))
    st = StructureReader(ref).next()
    atoms = evaluate_asl(st, asl)
    if len(atoms) == 0:
        print "NO LIGAND IN REFERENCE FILE"
        print "no ligand in reference file"
        sys.exit()
    pocket = st.extract(atoms)
    resnames = [i.pdbres for i in pocket.residue]
    resnums = [i.resnum for i in pocket.residue]
    chains = [i.chain for i in pocket.residue]
    data = dict()
    for chain in set(chains):
        for (n, c) in zip(resnums, chains):
            if c not in data.keys():
                data[c] = []
            if str(n) not in data[c]:
                data[c].append(str(n))
    selection = []
    for chain in data.keys():
        selection.append(','.join(data[chain]) + '.%s' % chain)
    if len(selection) == 1:
        selection = [
            selection,
        ]
    return selection
예제 #6
0
def check_selection_boolean(ref, target):
    st = StructureReader(ref).next()
    atoms = evaluate_asl(st, 'all')
    sub = st.extract(atoms)
    resnames = [i.pdbres.rstrip() for i in sub.residue]
    if target in resnames:
        verdict = True
    else:
        verdict = False
    return verdict
예제 #7
0
def check_selection_boolean(ref, target):
    st=StructureReader(ref).next()
    atoms=evaluate_asl(st, 'all')
    sub=st.extract(atoms)
    resnames=[i.pdbres.rstrip() for i in sub.residue]
    if target in resnames:
        verdict=True
    else:
        verdict=False
    return verdict
def extract_ct(csim, frameno, filename, asl=None):
    st = csim.getFrameStructure(frameno)
    if asl:
        selected_indices = evaluate_asl(st, asl)
        st = st.extract(selected_indices, copy_props=True)

    # delete obsolete properties
    properties = ['s_chorus_trajectory_file', 's_m_original_cms_file', 's_ffio_ct_type']
    for prop in properties:
        if prop in st.property:
            del st.property[prop]

    return st
예제 #9
0
def preprocess_rms(api, dataset, data_type=None, no_ligand=False):
    """

    :param api:
    :type api: pldbclient.api_client.Api
    :param dataset:
    :type dataset: pandas.Dataframe
    :param data_type: Placeholder
    :param no_lignad: Placeholder
    :return:
    """

    if api is None:
        dataset.dropna(axis=0, subset=['desmond_cms', 'trj_rms'], inplace=True)

    df_rms = pd.DataFrame(index=dataset.structure_id)

    for index, stid in zip(dataset.index, dataset.structure_id):
        with tempfile.TemporaryDirectory() as tempdir:
            if api is None:
                msys_model, cms_model = topo.read_cms(
                    dataset.loc[index, 'desmond_cms'])
                with open(dataset.loc[index, 'trj_rms'], 'r') as fh:
                    trj_rms = json.load(fh)
            else:
                # Load desomd cms
                msys_model, cms_model = get_desmond_cms(api, stid, dir=tempdir)
                # Load trj_rms
                trj_rms = get_trj_rms(api, stid, dir=tempdir)

        # Preprocess data
        for data in trj_rms:
            if data['name'] == 'calpha rmsd':
                df_rms.loc[stid, 'mean_rmsd'] = np.mean(data['results'])
            if data['name'] == 'calpha rmsf':
                for aid, x in zip(data['atom_ids'], data['results']):
                    df_rms.loc[stid, '{}:{}'.format(*aid[:-1])] = x
            if data['name'] == 'ligand_rmsf':
                aid2an = {}
                for n in evaluate_asl(cms_model, 'ligand and not a.element H'):
                    aid2an['{}:{}'.format(
                        str(cms_model.atom[n].resnum),
                        cms_model.atom[n].pdbname.strip())] = n
                for aid, x in zip(data['atom_ids'], data['results']):
                    an = aid2an.get('{}:{}'.format(*aid[1:]))
                    if an is None:  # Legacy check, this is true if calculation included pseudoatoms
                        continue
                    label = '#{}'.format(an)
                    df_rms.loc[stid, label] = x
    return df_rms
예제 #10
0
def extract_ct(csim, frameno, filename, asl=None):
    st = csim.getFrameStructure(frameno)
    if asl:
        selected_indices = evaluate_asl(st, asl)
        st = st.extract(selected_indices, copy_props=True)

    # delete obsolete properties
    properties = [
        's_chorus_trajectory_file', 's_m_original_cms_file', 's_ffio_ct_type'
    ]
    for prop in properties:
        if prop in st.property:
            del st.property[prop]

    return st
def create_zmat_file(complex_st, final_cap_at, cmd_args):
    """
    For the final structure, create a Jaguar input file with the OH atoms
    constrained.

    @param complex_st:  Merged structure of the zeolite and guest molecules.
    @type complex_st:   L{structure.Structure}

    @param final_cap_at:  List of the final capping atoms.
    @type final_cap_at:  list

    @param cmd_args:  All script arguments and options.
    @type cmd_args:  class:`argparse.Namespace`
    """

    hydrogen_asl = "atom.element 'H'"

    hydrogen_atom_list = analyze.evaluate_asl(complex_st, hydrogen_asl)

    jag_file = fileutils.get_basename(cmd_args.outfile) + ".in"

    jag_obj = input.JaguarInput(structure=complex_st)

    # For each hydrogen, test to see if this is a capping atom. If this is
    # True and that it is bonded to an oxygen, then constrain both atoms.
    # This should ignore OH group in the guest as these atoms should not be
    # in the list of capping atoms.

    for atom in hydrogen_atom_list:
        if atom in set(final_cap_at):
            bonded_atoms = complex_st.atom[atom].bonded_atoms

            for bond_at in bonded_atoms:
                if bond_at.element == 'O':
                    final_cap_at.append(bond_at.index)

    for cap_at in final_cap_at:
        jag_obj.constrainAtomXYZ(complex_st.atom[cap_at])

        complex_st.atom[cap_at].property['b_m_freeze_x'] = 1
        complex_st.atom[cap_at].property['b_m_freeze_y'] = 1
        complex_st.atom[cap_at].property['b_m_freeze_z'] = 1

    jag_obj.saveAs(jag_file)
예제 #12
0
파일: merge.py 프로젝트: SchifferLab/ROBUST
def get_min_common_substructure(structures,
                                ligand_ids=None,
                                return_st=True,
                                mcs_color=(139, 0, 139),
                                return_common_atoms=False):
    """
    Find the minimum common substructure
    :param structures: List of schrodinger.structure.Structure to calculate the mcs from
    :type structures: [schrodinger.structure.Structure]
    :param return_st: Boolean If True the substructure will be returned
    :param mcs_color: Maximum common substructure will be colored according to RGB values
    :param return_common_atoms: If True return only the list of common atoms
    :return:
    """
    for st in structures:
        set_original_atom_index(st)

    ligand_structures = []
    if ligand_ids is None:
        for st in structures:
            ligand_atoms = get_ligand_atoms(st)
            ligand_structures.append(st.extract(ligand_atoms, copy_props=True))
    else:
        for st, r, c in zip(structures, ligand_ids['ligand_resnum'],
                            ligand_ids['ligand_chain']):
            ligand_structures.append(
                st.extract(evaluate_asl(
                    st,
                    'r. {} and c. {} and not a.element H'.format(int(r), c)),
                           copy_props=True))

    default_color = (211, 211, 211)  # light grey
    substructures = find_common_substructure(ligand_structures,
                                             atomTyping=12,
                                             allow_broken_rings=True)
    common_atoms = []
    for j, subst in enumerate(substructures):
        if not len(subst) == 1:
            st = ligand_structures[j]
            ligand_atoms = [a.index for a in st.atom]
            com_distances = []
            for match in subst:
                com_distances.append(
                    com_distance(st, ligand_atoms, atoms2=match))
            common_atoms.append(subst[np.argmin(com_distance)])
        else:
            common_atoms.append(subst[0])

    orig_atoms = [
        get_original_atom_index(st, atom_ids)
        for st, atom_ids in zip(ligand_structures, common_atoms)
    ]
    if return_common_atoms and not return_st:
        return orig_atoms
    elif return_common_atoms and return_st:
        superimposer = Superimposer()
        for i, (catm, st) in enumerate(zip(common_atoms, ligand_structures)):
            if i == 0:
                reference_coord = np.array([st.atom[x].xyz for x in catm])
            else:
                mobile_coord = np.array([st.atom[x].xyz for x in catm])
                superimposer.fit(reference_coord, mobile_coord)
                st.setXYZ(superimposer.transform(st.getXYZ()))
            for atm in st.atom:  # Color all atoms in base gray
                atm.setColorRGB(*default_color)
                atm.temperature_factor = 0.
                atm.label_user_text = ''
                atm.label_color = 1
                atm.label_format = ''
            for i, aid in enumerate(catm):
                atm = st.atom[aid]  # type: structure._StructureAtom
                atm.setColorRGB(*mcs_color)
                atm.temperature_factor = 1.
                atm.label_user_text = str(i + 1)
                atm.label_color = 10
                atm.label_format = '%UT'
        return orig_atoms, ligand_structures

    mcs = np.min(list(map(len, common_atoms)))
    if not return_st:
        return mcs
    else:
        for catm, st in zip(common_atoms, ligand_structures):
            for atm in st.atom:  # Color all atoms in base gray
                atm.setColorRGB(*default_color)
                atm.temperature_factor = 0.
                atm.label_user_text = ''
                atm.label_color = 1
                atm.label_format = ''
            for i, aid in enumerate(catm):
                atm = st.atom[aid]  # type: structure._StructureAtom
                atm.setColorRGB(*mcs_color)
                atm.temperature_factor = 1.
                atm.label_user_text = str(i + 1)
                atm.label_color = 10
                atm.label_format = '%UT'
        return mcs, ligand_structures
예제 #13
0
def _process(structure_dict):
    """

    :param structure_dict:
    :return:
    """
    t = time.time()

    fork = None
    # Check if transformers is called as part of a pipeline
    if 'pipeline' in structure_dict['custom']:
        pipeline = structure_dict['custom']['pipeline']
        fork = [pipeline[0], ]
        if len(pipeline) == 1:
            del (structure_dict['custom']['pipeline'])
        else:
            structure_dict['custom']['pipeline'] = pipeline[1:]

    structure_code = structure_dict['structure']['code']

    logger.info('Load simulation files')

    cms_file = structure_dict['files']['desmond_cms']

    msys_model, cms_model = topo.read_cms(str(cms_file))

    trjtar = structure_dict['files']['desmond_trjtar']

    # If run from command line it does not make sense to provide a tarfile
    if os.path.isdir(trjtar):
        trj_dir = trjtar
    elif tarfile.is_tarfile(trjtar):
        with tarfile.open(name=trjtar, mode='r:gz') as tfile:
            tfile.extractall()
            trj_dir = tfile.getnames()[0]
    else:
        raise RuntimeError('trjtar is neither a directory nor a tarfile')

    frame_list = traj.read_traj(str(trj_dir))
    frame_list = [frame_list[i] for i in range(0, len(frame_list), STEP)]

    logger.info('Calculating torsion angles')

    cms_model = set_original_atom_index(cms_model)
    ligand_ct = cms_model.extract(evaluate_asl(cms_model, 'ligand'), copy_props=True)

    torsion_list = get_hetero_torsion_atoms(ligand_ct, element_priority=ELEMENT_PRIORITY)
    torsion_list.extend(get_protein_torsion_atoms(cms_model))

    analyzers = []

    torsion_ids = pd.DataFrame(columns=['index', 'aid1', 'aid2', 'aid3', 'aid4'])
    torsion_ids.set_index('index', inplace=True)

    for i, atom_set in enumerate(torsion_list):
        atom_set = list(map(get_original_atom_index, atom_set))
        analyzers.append(Torsion(msys_model, cms_model, *atom_set))
        torsion_ids.loc[i, ['aid1', 'aid2', 'aid3', 'aid4']] = atom_set

    results = analyze(frame_list, *analyzers,
                      **{"progress_feedback": functools.partial(print_iframe, logger=logger)})

    out_arch = '{}_torsion.tar.gz'.format(structure_code)
    with tarfile.open(out_arch, 'w:gz') as tar:
        torsion_ids.to_csv('torsion_ids.csv', sep=',')
        tar.add('torsion_ids.csv')
        for i, timeseries in enumerate(results):
            fname = 'torsion_{}.csv'.format(i)
            np.savetxt(fname, timeseries, delimiter=',')
            tar.add(fname)

    logger.info('Calculated torsion angles in {:.0f} seconds'.format(time.time() - t))
    # Return structure dict
    transformer_dict = {
        'structure': {
            'parent_structure_id':
                structure_dict['structure']['structure_id'],
            'searchable': False
        },
        'files': {'trj_torsion': out_arch},
        'custom': structure_dict['custom']
    }
    if fork is not None:
        logger.info('Forking pipeline: ' + ' '.join(fork))
        transformer_dict['control'] = {'forks': fork}
    yield transformer_dict
예제 #14
0
def get_protein_torsion_atoms(st, asl='protein', bb=True, chi=True):
    """
    return torsion angles for all residues defined by asl.
    By default only PHI and PSI will be returned.
    Optional a list of Chi angles can be provided.
    !!!CHI list must start from 0!!!
    PHI and PSI will not be returned if no_bb==True
    :param st:
    :param asl:
    :param chi:
    :param bb:
    :return:
    """

    def get_atm(residue, pdbname):
        """
        Return pythonic index of the first atom in residue that has the pdb atom name atm_pdbname
        Raise RuntimeError if no atom was found.
        :param residue:
        :param pdbname:
        :return:
        """
        for atm in residue.atom:
            if atm.pdbname.strip() == pdbname:  # check whether atomname equals pdbname
                return atm

    torsion_list = []
    # sanity checks
    if not chi and not bb:
        raise RuntimeError("Not torsion angles specified")

    atom_ids = evaluate_asl(st, asl)  # get atom ids
    reslist = [r for r in st.residue]  # get list of residue objects
    for i, r0 in enumerate(reslist):
        if r0.isStandardResidue() and r0.getCode().strip() in CHI_DEFINITIONS.keys():
            if any([aid.index in atom_ids for aid in r0.atom]):  # check whether asl includes r0
                if bb:  # fetch phi and psi angles
                    bb_topo = []  # determine backbone topology
                    if i - 1 >= 0:
                        if reslist[i - 1].isStandardResidue() and reslist[i - 1].isConnectedToResidue(
                                r0):  # if r-1 is a standard residue connected to r0 store phi
                            bb_topo.append('PHI')
                    if i + 1 < len(reslist):
                        if reslist[i + 1].isStandardResidue() and r0.isConnectedToResidue(
                                reslist[i + 1]):  # if r+1 is standard residue connected to r0 store psi
                            bb_topo.append('PSI')
                    if not bb_topo:  # sanity check
                        raise RuntimeError(
                            'Unable to determine backbone topology for residue {}:{}'.format(r0.resnum, r0.chain))
                    for angle in bb_topo:
                        torsion = []
                        for res_pos, atm_name in BACKBONE[angle]:
                            torsion.append(get_atm(reslist[i + res_pos], atm_name))
                        torsion_list.append(torsion)
                if chi:  # if chi_angle list is provided
                    r0_pdbcode = r0.getCode().strip()  # get oneletter code
                    for chii in range(4):  # At most there can be four chi torsion angles
                        if len(CHI_DEFINITIONS[r0_pdbcode]) > chii:  # check wether r0 has a chiX angle
                            torsion = []
                            for res_pos, atm_name in CHI_DEFINITIONS[r0_pdbcode][chii]:
                                torsion.append(get_atm(reslist[i + res_pos], atm_name))
                            torsion_list.append(torsion)
    return torsion_list
예제 #15
0
#this is a script for comparing the rmsd of the Glide ligand poses for each method to the original coxtal ligand pose (PDBID: 5QC4)

from schrodinger import structure as struct
from schrodinger.structutils import analyze
from schrodinger.structutils import rmsd

#calculating rmsd of core structures for blind docking
docktype = 'XP'
methods = ['TICA', 'TICA_CBA', 'PCA', 'PCA_CBA', 'GROMOS', 'GROMOS_CBA']
path = '/home/jegan/GLIDE_' + docktype + '_docking/'
home = '/home/jegan/pose_analysis/'

xtal = struct.Structure.read(home + '5QC4_holo.maegz', index=1)
#xtal_rec = analyze.evaluate_asl(xtal, '(( backbone ) ) AND (res.num 0-217)')
xtal_rec = analyze.evaluate_asl(
    xtal, '(( backbone ) ) AND (res.num 0-84)'
)  #for the holo because that one residue is still not fixed in this docking yet

for method in methods:
    input_file = path + method + '_' + docktype + '_epv.maegz'
    with open(
            home + 'lig_core_rmsd/GLIDE_' + docktype + '_docking/' + method +
            '_rmsd.csv', 'w') as datafile:
        datafile.write(
            'Ligand, Receptor number, Score, RMSD of Core structure from XTAL Ligand\n'
        )
        data = []
        for lig in struct.StructureReader(input_file, index=11):
            #structure = struct._StructureProperty(lig) #finding the properties in the project table
            #print(structure.keys()) #printing out all available properties
예제 #16
0
for filename in files:
    print filename
    known = pdbKeys[filename]
    knownCpx = SS.StructureReader('scoring/' + known[0] + '.pdb').next()
    #print known.replace('-clean','Lig')
    #knownLig = SS.StructureReader(known.replace('-clean','Lig')).next()
    #print knownPtn, knownLig
    #knownCpx = knownPtn.merge(knownLig)
    #my_sw = SS.StructureWriter(known.replace('-clean.pdb','-complex.mae'))
    #my_sw.append(knownCpx)
    #my_sw.close()
    #searcher = SSUA.AslLigandSearcher()
    #searcher.search(knownCpx)
    #print searcher.getAsl()
    #within5 = SSUA.evaluate_asl(knownCpx,'fillres within 5 (%s) ' %(searcher.getAsl()))
    within5 = SSUA.evaluate_asl(
        knownCpx, 'fillres within 5 (res.ptype "%s") ' % (known[1]))
    ligand = SSUA.evaluate_asl(knownCpx, 'res.ptype "%s" ' % (known[1]))
    #print knownCpx.atom[ligand].smiles
    knownSet = set([str(knownCpx.atom[i].getResidue()) for i in within5])
    #print knownSet
    #1/0
    my_SR = SS.StructureReader(filename)
    guessSets = []
    #try:
    if 1:
        protein = my_SR.next()
        for i in range(3):
            #if 1:
            try:
                print 'ligand %i' % (i)
                ligand = my_SR.next()
예제 #17
0
#code to calculate the core rmsd of the OE Xtal docked poses, using schrodinger because mdtraj can't recognize SMILES strings :(((((

from schrodinger import structure as struct
from schrodinger.structutils import analyze
from schrodinger.structutils import rmsd
import glob

#calculating rmsd of core structures for blind docking
home = '/home/jegan/pose_analysis/'
path = '/home/jegan/bccgc4/OE_new_docking/'

xtal = struct.Structure.read(home + '5QC4_lig_maestro.pdb', index=1)
xtal_rec = analyze.evaluate_asl(xtal, '(( backbone ) ) AND (res.num 1-216)')
print(len(xtal_rec))

with open(home + 'lig_core_rmsd/OE_docking/XTAL_rmsd.csv', 'w') as datafile:
    datafile.write(
        'Ligand, Receptor number, Score, RMSD of Core structure from XTAL Ligand\n'
    )
    data = []

    with open(path + 'XTAL_docking/Scores.csv', 'r') as ligands:

        ligands = ligands.readlines()
        for line in ligands[1:]:
            items = line.split(',')

            ligand = items[0]
            print(ligand)
            score = items[2].rstrip()
            cen_num = 0  #there's only one receptor because this is the OE xtal docking
예제 #18
0
def rmsdRef():
    lines = []
    with open('v92.finalResult', 'r') as f:
        lines = f.readlines()[1:]
    seeds = []
    energies = []
    nativeRMSDs = []
    for line in lines:
        terms = line.split()
        seeds.append(int(terms[0]))
        energies.append(float(terms[8]))
        nativeRMSDs.append(terms[9])
    energies, seeds, nativeRMSDs = (list(t) for t in \
    zip(*sorted(zip(energies, seeds, nativeRMSDs))))

    cwd = os.getcwd()

    pattern = None
    with open('v92.con', 'r') as f:
        conLines = f.readlines()
    for line in conLines:
        if 'subjob_control' in line:
            terms = line.split()
            pattern = terms[2]

    structs = []
    for i in range(len(seeds)):
        for dir in os.listdir(os.path.join(cwd, 'subJobs')):
            if dir.split('_')[0] == str(seeds[i]):
                os.chdir(os.path.join(cwd, 'subJobs', dir))
                if 'plop.stdout' in os.listdir('.'):
                    stName = '4KUZ-p' + str(
                        pattern) + '-' + nativeRMSDs[i] + '_template.maegz'
                    structs.append(next(structure.StructureReader(stName)))
                os.chdir(cwd)
    minStruct = copy.deepcopy(structs[0])

    ALLINDICES = analyze.evaluate_asl(minStruct, ALLINDICES_asl)
    LOOPENVINDICES = analyze.evaluate_asl(minStruct, LOOPENVINDICES_asl)
    NONLOOPINDICES = analyze.evaluate_asl(minStruct, NONLOOPINDICES_asl)

    rmsds = []
    for i in range(0, len(structs)):
        curStruct = structs[i]
        rmsd.superimpose(minStruct, NONLOOPINDICES, curStruct, NONLOOPINDICES)
        RMSD = rmsd.calculate_in_place_rmsd(minStruct, LOOPENVINDICES,
                                            curStruct, LOOPENVINDICES)
        rmsds.append(RMSD)

    # What about Hbond patterns?
    hbonds = []
    for i in range(0, len(structs)):
        curStruct = structs[i]
        hbonds.append(hbond.get_hydrogen_bonds(curStruct, LOOPENVINDICES))

    hbondIndices = []
    for i in range(0, len(hbonds)):
        structIndices = []
        hbondIndices.append(structIndices)
        for j in range(0, len(hbonds[i])):
            pairIndices = []
            hbondIndices[i].append(pairIndices)
            for k in range(0, 2):
                hbondIndices[i][j].append(hbonds[i][j][k].index)

    min_hb_indices = copy.deepcopy(hbondIndices[0])
    hbond_overlaps = []
    for i in range(0, len(hbondIndices)):
        li1 = [tuple(lst) for lst in min_hb_indices]
        li2 = [tuple(lst) for lst in hbondIndices[i]]

        overlap = []
        for pair in li1:
            if pair in li2:
                overlap.append(pair)
        sm = difflib.SequenceMatcher(None, li1, li2)
        hbond_overlaps.append(round(sm.ratio(), 5))

    # What about salt bridge interactions?
    bridges = []
    for i in range(0, len(structs)):
        curStruct = structs[i]
        bridges.append(salt_bridge.get_salt_bridges(curStruct, LOOPENVINDICES))

    bridgeIndices = []
    for i in range(0, len(bridges)):
        structIndices = []
        bridgeIndices.append(structIndices)
        for j in range(0, len(bridges[i])):
            pairIndices = []
            bridgeIndices[i].append(pairIndices)
            for k in range(0, 2):
                bridgeIndices[i][j].append(bridges[i][j][k].index)

    min_bridge_indices = copy.deepcopy(bridgeIndices[0])
    salt_bridge_overlaps = []
    for i in range(0, len(bridgeIndices)):
        li1 = [tuple(lst) for lst in min_bridge_indices]
        li2 = [tuple(lst) for lst in bridgeIndices[i]]

        overlap = []
        for pair in li1:
            if pair in li2:
                overlap.append(pair)
        sm = difflib.SequenceMatcher(None, li1, li2)
        salt_bridge_overlaps.append(round(sm.ratio(), 5))

    # Hydrophobic interactions

    print('SEED\t\tRMSD\t\tHBOND_OVERLAP\tSALTBR_OVERLAP\tENERGY')
    for i in range(0, len(rmsds)):
        print(
            str(seeds[i]) + '\t\t' + str(round(rmsds[i], 3)) + '\t\t' +
            str(hbond_overlaps[i] * 100) + '\t\t' +
            str(salt_bridge_overlaps[i] * 100) + '\t\t' + str(energies[i]))