diff --git a/MANIFEST.in b/MANIFEST.in index c58a255b9..8aeafdcd4 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -9,6 +9,7 @@ include prody/*/*.cpp include prody/*/*/*.cpp include prody/*/*.h include prody/*/*/*.h +include prody/*/*/*/*.so include prody/tests/*/*.py include prody/tests/datafiles/*.coo include prody/tests/datafiles/*.dcd @@ -20,3 +21,4 @@ include prody/utilities/datafiles/*.dat include prody/utilities/datafiles/*.txt include scripts/prody* include scripts/evol* +include prody/protein/tabulated_energies.txt \ No newline at end of file diff --git a/docs/about/people.rst b/docs/about/people.rst index a46c0516a..a092a2098 100644 --- a/docs/about/people.rst +++ b/docs/about/people.rst @@ -21,10 +21,12 @@ Development Team `James Krieger`_ was helping develop *ProDy* from 2017 and became the main overseer and developer in mid 2020. -`Hongchun Li`_ is currently maintaining and developing ANM and GNM servers, +`Hongchun Li`_ has helped maintain and develop ANM and GNM servers, and made significant contributions to :mod:`.database` and :mod:`.dynamics` including *SignDy* and Adaptive ANM. +`JiYoung Lee`_ is the main developer of :mod:`.Pharmmaker`, for constructing pharmacophore models using the outputs from :mod:`.DruGUI`. + `Yan Zhang`_ contributed significantly to the development of the *cryo-EM* module, :mod:`.protein.emdmap`. @@ -32,9 +34,9 @@ the *cryo-EM* module, :mod:`.protein.emdmap`. :mod:`.domain_decomposition`, :mod:`.dynamics.essa`, and :mod:`.dynamics.clustenm`. -`Karolina Mikulska-Ruminska`_ contributed significantly to the development of +`Karolina Mikulska-Ruminska`_ is one of the main developers since 2022, with the addition of the new modules :mod:`.protein.interactions` (*InSty*), :mod:`.protein.waterbridges` -(*WatFinder*), and :mod:`.dynamics.mechstiff` (*MechStiff*). +(*WatFinder*), in addition to being the developer of :mod:`.dynamics.mechstiff` (*MechStiff*). `Anthony Bogetti`_ is overseeing the overall development of *ProDy* since 2024. @@ -50,6 +52,12 @@ Blocks and Membrane ENM. `Lidio Meireles`_ provided insightful comments on the design of *ProDy*, and contributed to the development of :ref:`prody-apps`. +`Mustafa Tekpinar`_ contributed to the development of MechStiff. + +`Luca Ponzoni`_ contributed to the development of SignDy. + +`David Koes`_ contributed to the development of drug discovery tools. + Contributors ------------ @@ -67,7 +75,6 @@ contributions and feedback from the following individuals: insights. - .. _Ahmet Bakan: https://scholar.google.com/citations?user=-QAYVgMAAAAJ&hl=en .. _Cihan Kaya: https://www.linkedin.com/in/cihan-kaya/ .. _Bahar Lab: http://www.bahargroup.org/Faculty/bahar/ @@ -75,9 +82,9 @@ insights. .. _Anindita Dutta: http://www.linkedin.com/pub/anindita-dutta/5a/568/a90 .. _Wenzhi Mao: http://www.linkedin.com/pub/wenzhi-mao/2a/29a/29 .. _Lidio Meireles: http://www.linkedin.com/in/lidio -.. _Ying Liu: http://www.linkedin.com/pub/ying-liu/15/48b/5a9 +.. _Ying Liu: https://www.linkedin.com/in/yingliu03/ .. _Kian Ho: https://github.com/kianho -.. _Gökçen Eraslan: http://blog.yeredusuncedernegi.com/ +.. _Gökçen Eraslan: https://github.com/gokceneraslan .. _Tim Lezon: https://scholar.google.pl/citations?user=1MwNI3EAAAAJ&hl=pl&oi=ao .. _Chakra Chennubhotla: http://www.csb.pitt.edu/Faculty/Chakra/ .. _She (John) Zhang: https://www.linkedin.com/in/she-zhang-49164399/ @@ -87,4 +94,8 @@ insights. .. _Burak Kaynak: https://scholar.google.pl/citations?user=gP8RokwAAAAJ&hl=pl&oi=ao .. _Karolina Mikulska-Ruminska: https://scholar.google.pl/citations?user=IpyPHRwAAAAJ&hl=pl .. _Anthony Bogetti: https://scholar.google.pl/citations?hl=pl&user=9qQClIcAAAAJ -.. _Frane Doljanin: https://github.com/fdoljanin \ No newline at end of file +.. _Frane Doljanin: https://github.com/fdoljanin +.. _JiYoung Lee: https://scholar.google.com/citations?user=odKQmZcAAAAJ&hl=en +.. _David Koes: https://bits.csb.pitt.edu/ +.. _Luca Ponzoni: https://scholar.google.it/citations?user=8vfPOYUAAAAJ&hl=en +.. _Mustafa Tekpinar: https://scholar.google.com/citations?user=qeVv6o8AAAAJ&hl=en diff --git a/docs/devel/website.rst b/docs/devel/website.rst index e1ef59965..3de4d9bb4 100644 --- a/docs/devel/website.rst +++ b/docs/devel/website.rst @@ -14,7 +14,7 @@ This is a short guide for building the ProDy website. Environment Setup -------------- -First log in to the ProDy webserver (prody.csb.pitt.edu) then run the following:: +First log in to your ProDy webserver and then run the following:: $ conda deactivate @@ -34,7 +34,7 @@ ProDy-website-workdir. You can then copy files back over afterwards. It's recommended to have the symbolic link called test_prody pointing to your build directory instead and then you can monitor changes by going to -http://prody.csb.pitt.edu/test_prody/_build/html/ in your web browser. +http://yourdomainname/test_prody/_build/html/ in your web browser. Updating from GitHub diff --git a/docs/docs b/docs/docs index 945c9b46d..7099f6ab8 120000 --- a/docs/docs +++ b/docs/docs @@ -1 +1 @@ -. \ No newline at end of file +ProDy/docs \ No newline at end of file diff --git a/docs/reference/proteins/waterbridges.rst b/docs/reference/proteins/waterbridges.rst index a41a8e09b..148fab777 100644 --- a/docs/reference/proteins/waterbridges.rst +++ b/docs/reference/proteins/waterbridges.rst @@ -3,4 +3,4 @@ Water bridge finder (WatFinder) .. automodule:: prody.proteins.waterbridges :members: - :undoc-members: \ No newline at end of file + :undoc-members: diff --git a/docs/release/index.rst b/docs/release/index.rst index cfe0dfaff..f838d806b 100644 --- a/docs/release/index.rst +++ b/docs/release/index.rst @@ -9,7 +9,8 @@ Release Notes .. toctree:: :maxdepth: 2 :glob: - + + v2.5_series v2.4_series v2.3_series v2.2_series diff --git a/prody/chromatin/functions.py b/prody/chromatin/functions.py index a9ed3a472..314fea2f3 100644 --- a/prody/chromatin/functions.py +++ b/prody/chromatin/functions.py @@ -212,7 +212,7 @@ def showEmbedding(modes, labels=None, trace=True, headtail=True, cmap='prism'): X, Y, Z = V[:,:3].T f = figure() - ax = f.add_subplot(projection="3d") + ax = f.add_subplot(1,1,1,projection="3d") if trace: ax.plot(X, Y, Z, ':', color=[0.3, 0.3, 0.3]) if labels is None: @@ -240,4 +240,4 @@ def getDomainList(labels): ends = sites[1:] domains = np.array([starts, ends]).T - return domains \ No newline at end of file + return domains diff --git a/prody/dynamics/plotting.py b/prody/dynamics/plotting.py index 3a87ee4dc..867933572 100644 --- a/prody/dynamics/plotting.py +++ b/prody/dynamics/plotting.py @@ -110,7 +110,7 @@ def showEllipsoid(modes, onto=None, n_std=2, scale=1., *args, **kwargs): show = child break if show is None: - show = cf.add_subplot(projection="3d") + show = cf.add_subplot(111,projection="3d") show.plot_wireframe(x, y, z, rstride=6, cstride=6, *args, **kwargs) if onto is not None: onto = list(onto) @@ -421,7 +421,7 @@ def showProjection(ensemble=None, modes=None, projection=None, *args, **kwargs): show = child break if show is None: - show = cf.add_subplot(projection="3d") + show = cf.add_subplot(111,projection="3d") plot = show.plot text = show.text diff --git a/prody/dynamics/sampling.py b/prody/dynamics/sampling.py index dd2c66453..272b230bd 100644 --- a/prody/dynamics/sampling.py +++ b/prody/dynamics/sampling.py @@ -51,9 +51,10 @@ def sampleModes(modes, atoms=None, n_confs=1000, rmsd=1.0): RMSD of the new conformation from :math:`R_0` can be calculated as + .. math:: - RMSD^k = \\sqrt{ {\\left( s \\sum_{i=1}^{m} r_i^k \\lambda^{-0.5}_i u_i \\right)}^{2} / N } = \\frac{s}{ \\sqrt{N}} \\sqrt{ \\sum_{i=1}^{m} (r_i^k)^2 \\lambda^{-1}_i } + RMSD^k = \\sqrt{ \\left[ s \\sum_{i=1}^{m} r_i^k \\lambda^{-0.5}_i u_i \\right] ^{2} / N } = \\frac{s}{ \\sqrt{N}} \\sqrt{ \\sum_{i=1}^{m} (r_i^k)^2 \\lambda^{-1}_i } Average :math:`RMSD` of the generated conformations from the initial conformation is: diff --git a/prody/proteins/functions.py b/prody/proteins/functions.py index 1cf051a7c..a07dcb1c1 100644 --- a/prody/proteins/functions.py +++ b/prody/proteins/functions.py @@ -266,7 +266,7 @@ def showProtein(*atoms, **kwargs): show = child break if show is None: - show = cf.add_subplot(projection="3d") + show = cf.add_subplot(1,1,1,projection="3d") from matplotlib import colors cnames = dict(colors.cnames) wcolor = kwargs.get('water', 'red').lower() diff --git a/prody/proteins/interactions.py b/prody/proteins/interactions.py index 40f3dd3d6..82c8fd18c 100644 --- a/prody/proteins/interactions.py +++ b/prody/proteins/interactions.py @@ -46,7 +46,7 @@ 'calcHydrogenBondsTrajectory', 'calcHydrophobicOverlapingAreas', 'Interactions', 'InteractionsTrajectory', 'LigandInteractionsTrajectory', 'calcSminaBindingAffinity', 'calcSminaPerAtomInteractions', 'calcSminaTermValues', - 'showSminaTermValues'] + 'showSminaTermValues', 'showPairEnergy'] def cleanNumbers(listContacts): @@ -153,6 +153,63 @@ def filterInteractions(list_of_interactions, atoms, **kwargs): return final +def get_energy(pair, source): + """Return energies based on the pairs of interacting residues (without distance criteria) + Taking information from tabulated_energies.txt file""" + + import numpy as np + import importlib.resources as pkg_resources + + try: + # Python 3 + with pkg_resources.path('prody.proteins', 'tabulated_energies.txt') as file_path: + data = np.loadtxt(file_path, skiprows=1, dtype=str) + except: + # Python 2.7 + import pkg_resources + file_path = pkg_resources.resource_filename('prody.proteins', 'tabulated_energies.txt') + with open(file_path) as f: + data = np.loadtxt(f, skiprows=1, dtype=str) + + + sources = ["IB_nosolv", "IB_solv", "CS"] + aa_pairs = [] + + for row in data: + aa_pairs.append(row[0]+row[1]) + + lookup = pair[0]+pair[1] + + return data[np.where(np.array(aa_pairs)==lookup)[0]][0][2:][np.where(np.array(sources)==source)][0] + + +def showPairEnergy(data, **kwargs): + """Return energies when a list of interactions is given. Energies will be added to each pair of residues + at the last position in the list. Energy is based on the residue types and not on the distances. + The unit of energy is kcal/mol. The energies defined as 'IB_nosolv', 'IB_solv' are taken from XX and + 'CS' from YY. + + :arg data: list with interactions from calcHydrogenBonds() or other types + :type data: list + + :arg energy_list_type: name of the list with energies + default is 'IB_solv' + :type energy_list_type: 'IB_nosolv', 'IB_solv', 'CS' + """ + + if not isinstance(data, list): + raise TypeError('list_of_interactions must be a list of interactions.') + + energy_list_type = kwargs.pop('energy_list_type', 'IB_solv') + + for i in data: + energy = get_energy([i[0][:3], i[3][:3]], energy_list_type) + i.append(float(energy)) + + return data + + + def calcHydrophobicOverlapingAreas(atoms, **kwargs): """Provide information about hydrophobic contacts between pairs of residues based on the regsurf program. To use this function compiled hpb.so is needed. @@ -163,7 +220,7 @@ def calcHydrophobicOverlapingAreas(atoms, **kwargs): :arg selection: selection string of hydrophobic residues :type selection: str - :arg hpb_cutoff: cutoff for hydrophobic overlaping area values + :arg hpb_cutoff: cutoff for hydrophobic overlapping area values default is 0.0 :type hpb_cutoff: float, int @@ -200,7 +257,7 @@ def calcHydrophobicOverlapingAreas(atoms, **kwargs): lA = [ [x[i] + str(y[i]), z[i] +'_'+ str(w[i]), ch[i]] for i in range(len(x))] output = hpb.hpb((lB,lA)) - LOGGER.info("Hydrophobic Overlaping Areas are computed.") + LOGGER.info("Hydrophobic Overlapping Areas are computed.") output_final = [i for i in output if i[-1] >= hpb_cutoff] if cumulative_values == None: @@ -1000,11 +1057,11 @@ def calcHydrophobic(atoms, **kwargs): non_standard works too :type non_standard_Hph: dict - :arg zerosHPh: zero values of hydrophobic overlaping areas included + :arg zerosHPh: zero values of hydrophobic overlapping areas included default is False :type zerosHPh: bool - Last value in the output corresponds to the total hydrophobic overlaping area for two residues + Last value in the output corresponds to the total hydrophobic overlapping area for two residues not only for the atoms that are included in the list. Atoms that which are listed are the closest between two residues and they will be inluded to draw the line in VMD_. @@ -1065,7 +1122,7 @@ def calcHydrophobic(atoms, **kwargs): aromatic_nr = list(set(zip(atoms.aromatic.getResnums(),atoms.aromatic.getChids()))) aromatic = list(set(atoms.aromatic.getResnames())) - # Computing hydrophobic overlaping areas for pairs of residues: + # Computing hydrophobic overlapping areas for pairs of residues: try: hpb_overlaping_results = calcHydrophobicOverlapingAreas(atoms_hydrophobic, cumulative_values='pairs') except: @@ -1816,11 +1873,16 @@ def showInteractionsGraph(statistics, **kwargs): 'HIS': 'H', 'HSD': 'H','HSE': 'H', 'LEU': 'L', 'ARG': 'R', 'TRP': 'W', 'ALA': 'A', 'VAL':'V', 'GLU': 'E', 'TYR': 'Y', 'MET': 'M'} - if len(statistics[0]) != 4: - raise TypeError('data must be a list obtained from calcStatisticsInteractions') + + if isinstance(statistics, int) or isinstance(statistics, str) or isinstance(statistics, Atomic): + raise TypeError('input data must be a list, use calcStatisticsInteractions to obtain statistics for a particular interaction type') + + if isinstance(statistics, InteractionsTrajectory) or isinstance(statistics, Interactions): + raise TypeError('use calcStatisticsInteractions to obtain statistics for a particular interaction type') + else: - if isinstance(statistics, int) or isinstance(statistics, str): - raise TypeError('node_size must be a list') + if len(statistics[0]) != 5: + raise TypeError('input data must be a list obtained from calcStatisticsInteractions') code = kwargs.pop('code', None) if code is None: @@ -1898,6 +1960,11 @@ def calcStatisticsInteractions(data, **kwargs): default value is 0.2 (in 20% of conformations contact appeared) :type weight_cutoff: int, float + :arg energy_list_type: name of the list with energies + default is 'IB_solv' + :type energy_list_type: 'IB_nosolv', 'IB_solv', 'CS' + + Example of usage: >>> atoms = parsePDB('PDBfile.pdb') >>> dcd = Trajectory('DCDfile.dcd') @@ -1912,6 +1979,7 @@ def calcStatisticsInteractions(data, **kwargs): interactions_list = [ (jj[0]+jj[2]+'-'+jj[3]+jj[5], jj[6]) for ii in data for jj in ii] weight_cutoff = kwargs.pop('weight_cutoff', 0.2) + energy_list_type = kwargs.pop('energy_list_type', 'IB_solv') import numpy as np elements = [t[0] for t in interactions_list] @@ -1923,7 +1991,8 @@ def calcStatisticsInteractions(data, **kwargs): stats[element] = { "stddev": np.round(np.std(values),6), "mean": np.round(np.mean(values),6), - "weight": np.round(float(len(values))/len(data), 6) + "weight": np.round(float(len(values))/len(data), 6), + "energy": get_energy([element.split('-')[0][:3], element.split('-')[1][:3]], energy_list_type) } statistic = [] @@ -1933,7 +2002,8 @@ def calcStatisticsInteractions(data, **kwargs): LOGGER.info(" Average [Ang.]: {}".format(value['mean'])) LOGGER.info(" Standard deviation [Ang.]: {0}".format(value['stddev'])) LOGGER.info(" Weight: {0}".format(value['weight'])) - statistic.append([key, value['weight'], value['mean'], value['stddev']]) + LOGGER.info(" Energy [kcal/mol]: {0}".format(value['energy'])) + statistic.append([key, value['weight'], value['mean'], value['stddev'], value['energy']]) else: pass statistic.sort(key=lambda x: x[1], reverse=True) @@ -2688,6 +2758,7 @@ def __init__(self, title='Unknown'): self._atoms = None self._interactions = None self._interactions_matrix = None + self._interactions_matrix_en = None self._hbs = None self._sbs = None self._rib = None @@ -3087,6 +3158,42 @@ def buildInteractionMatrix(self, **kwargs): return InteractionsMap + def buildInteractionMatrixEnergy(self, **kwargs): + """Build matrix with interaction energy comming from energy of pairs of specific residues. + + :arg energy_list_type: name of the list with energies + default is 'IB_solv' + :type energy_list_type: 'IB_nosolv', 'IB_solv', 'CS' + """ + + import numpy as np + import matplotlib + import matplotlib.pyplot as plt + from prody.dynamics.plotting import pplot + + atoms = self._atoms + interactions = self._interactions + energy_list_type = kwargs.pop('energy_list_type', 'IB_solv') + + LOGGER.info('Calculating interactions') + InteractionsMap = np.zeros([atoms.select('name CA').numAtoms(),atoms.select('name CA').numAtoms()]) + resIDs = list(atoms.select('name CA').getResnums()) + resChIDs = list(atoms.select('name CA').getChids()) + resIDs_with_resChIDs = list(zip(resIDs, resChIDs)) + + for nr_i,i in enumerate(interactions): + if i != []: + for ii in i: + m1 = resIDs_with_resChIDs.index((int(ii[0][3:]),ii[2])) + m2 = resIDs_with_resChIDs.index((int(ii[3][3:]),ii[5])) + scoring = get_energy([ii[0][:3], ii[3][:3]], energy_list_type) + InteractionsMap[m1][m2] = InteractionsMap[m2][m1] = InteractionsMap[m1][m2] + float(scoring) + + self._interactions_matrix_en = InteractionsMap + + return InteractionsMap + + def showInteractors(self, **kwargs): """Display protein residues and their number of potential interactions with other residues from protein structure. """ @@ -3127,23 +3234,37 @@ def saveInteractionsPDB(self, **kwargs): :arg filename: name of the PDB file which will be saved for visualization, it will contain the results in occupancy column. - :type filename: str """ + :type filename: str + + :arg energy: sum of the energy between residues + default is False + :type energy: True, False + """ if not hasattr(self, '_interactions_matrix') or self._interactions_matrix is None: raise ValueError('Please calculate interactions matrix first.') - + import numpy as np + from collections import Counter + + energy = kwargs.pop('energy', False) + + atoms = self._atoms interaction_matrix = self._interactions_matrix - atoms = self._atoms - freq_contacts_residues = np.sum(interaction_matrix, axis=0) + interaction_matrix_en = self._interactions_matrix_en - from collections import Counter - lista_ext = [] atoms = atoms.select("protein and noh") + lista_ext = [] aa_counter = Counter(atoms.getResindices()) calphas = atoms.select('name CA') + for i in range(calphas.numAtoms()): - lista_ext.extend(list(aa_counter.values())[i]*[round(freq_contacts_residues[i], 8)]) + if energy == True: + matrix_en_sum = np.sum(interaction_matrix_en, axis=0) + lista_ext.extend(list(aa_counter.values())[i]*[round(matrix_en_sum[i], 8)]) + else: + freq_contacts_residues = np.sum(interaction_matrix, axis=0) + lista_ext.extend(list(aa_counter.values())[i]*[round(freq_contacts_residues[i], 8)]) kw = {'occupancy': lista_ext} if 'filename' in kwargs: @@ -3153,6 +3274,7 @@ def saveInteractionsPDB(self, **kwargs): writePDB('filename', atoms, **kw) LOGGER.info('PDB file saved.') + def getFrequentInteractors(self, contacts_min=3): """Provide a list of residues with the most frequent interactions based on the following interactions: @@ -3292,7 +3414,12 @@ def showCumulativeInteractionTypes(self, **kwargs): :type HPh: int, float :arg DiBs: score per disulfide bond - :type DiBs: int, float """ + :type DiBs: int, float + + :arg energy: sum of the energy between residues + default is False + :type energy: True, False + """ import numpy as np import matplotlib @@ -3305,87 +3432,109 @@ def showCumulativeInteractionTypes(self, **kwargs): 'ALA': 'A', 'VAL':'V', 'GLU': 'E', 'TYR': 'Y', 'MET': 'M', 'HSE': 'H', 'HSD': 'H'} atoms = self._atoms + energy = kwargs.pop('energy', False) ResNumb = atoms.select('protein and name CA').getResnums() ResName = atoms.select('protein and name CA').getResnames() ResChid = atoms.select('protein and name CA').getChids() ResList = [ i[0]+str(i[1])+i[2] for i in list(zip([ aa_dic[i] for i in ResName ], ResNumb, ResChid)) ] - replace_matrix = kwargs.get('replace_matrix', False) - matrix_all = self._interactions_matrix - - HBs = kwargs.get('HBs', 1) - SBs = kwargs.get('SBs', 1) - RIB = kwargs.get('RIB', 1) - PiStack = kwargs.get('PiStack', 1) - PiCat = kwargs.get('PiCat', 1) - HPh = kwargs.get('HPh', 1) - DiBs = kwargs.get('DiBs', 1) - - matrix_hbs = self.buildInteractionMatrix(HBs=HBs, SBs=0, RIB=0,PiStack=0,PiCat=0,HPh=0,DiBs=0) - matrix_sbs = self.buildInteractionMatrix(HBs=0, SBs=SBs, RIB=0,PiStack=0,PiCat=0,HPh=0,DiBs=0) - matrix_rib = self.buildInteractionMatrix(HBs=0, SBs=0, RIB=RIB,PiStack=0,PiCat=0,HPh=0,DiBs=0) - matrix_pistack = self.buildInteractionMatrix(HBs=0, SBs=0, RIB=0,PiStack=PiStack,PiCat=0,HPh=0,DiBs=0) - matrix_picat = self.buildInteractionMatrix(HBs=0, SBs=0, RIB=0,PiStack=0,PiCat=PiCat,HPh=0,DiBs=0) - matrix_hph = self.buildInteractionMatrix(HBs=0, SBs=0, RIB=0,PiStack=0,PiCat=0,HPh=HPh,DiBs=0) - matrix_dibs = self.buildInteractionMatrix(HBs=0, SBs=0, RIB=0,PiStack=0,PiCat=0,HPh=0,DiBs=DiBs) - - matrix_hbs_sum = np.sum(matrix_hbs, axis=0) - matrix_sbs_sum = np.sum(matrix_sbs, axis=0) - matrix_rib_sum = np.sum(matrix_rib, axis=0) - matrix_pistack_sum = np.sum(matrix_pistack, axis=0) - matrix_picat_sum = np.sum(matrix_picat, axis=0) - matrix_hph_sum = np.sum(matrix_hph, axis=0) - matrix_dibs_sum = np.sum(matrix_dibs, axis=0) - - width = 0.8 - fig, ax = plt.subplots(num=None, figsize=(20,6), facecolor='w') - matplotlib.rcParams['font.size'] = '24' - - sum_matrix = np.zeros(matrix_hbs_sum.shape) - pplot(sum_matrix, atoms=atoms.ca) - - if HBs != 0: - ax.bar(ResList, matrix_hbs_sum, width, color = 'blue', bottom = 0, label='HBs') - sum_matrix += matrix_hbs_sum - - if SBs != 0: - ax.bar(ResList, matrix_sbs_sum, width, color = 'yellow', bottom = sum_matrix, label='SBs') - sum_matrix += matrix_sbs_sum - - if HPh != 0: - ax.bar(ResList, matrix_hph_sum, width, color = 'silver', bottom = sum_matrix, label='HPh') - sum_matrix += matrix_hph_sum - - if RIB != 0: - ax.bar(ResList, matrix_rib_sum, width, color = 'red', bottom = sum_matrix, label='RIB') - sum_matrix += matrix_rib_sum - - if PiStack != 0: - ax.bar(ResList, matrix_pistack_sum, width, color = 'green', bottom = sum_matrix, label='PiStack') - sum_matrix += matrix_pistack_sum - - if PiCat != 0: - ax.bar(ResList, matrix_picat_sum, width, color = 'orange', bottom = sum_matrix, label='PiCat') - sum_matrix += matrix_picat_sum - - if DiBs != 0: - ax.bar(ResList, matrix_dibs_sum, width, color = 'black', bottom = sum_matrix, label='DiBs') - sum_matrix += matrix_dibs_sum - - if replace_matrix: - self._interactions_matrix = np.sum([matrix_hbs, matrix_sbs, matrix_rib, matrix_pistack, - matrix_picat, matrix_hph, matrix_dibs], axis=0) + + if energy == True: + matrix_en = self._interactions_matrix_en + matrix_en_sum = np.sum(matrix_en, axis=0) + + width = 0.8 + fig, ax = plt.subplots(num=None, figsize=(20,6), facecolor='w') + matplotlib.rcParams['font.size'] = '24' + + ax.bar(ResNumb, matrix_en_sum, width, color='blue') + + plt.xlim([ResNumb[0]-0.5, ResNumb[-1]+0.5]) + plt.tight_layout() + plt.xlabel('Residue') + plt.ylabel('Cumulative Energy [kcal/mol]') + plt.show() + + return matrix_en_sum + + else: - self._interactions_matrix = matrix_all + replace_matrix = kwargs.get('replace_matrix', False) + matrix_all = self._interactions_matrix + + HBs = kwargs.get('HBs', 1) + SBs = kwargs.get('SBs', 1) + RIB = kwargs.get('RIB', 1) + PiStack = kwargs.get('PiStack', 1) + PiCat = kwargs.get('PiCat', 1) + HPh = kwargs.get('HPh', 1) + DiBs = kwargs.get('DiBs', 1) + + matrix_hbs = self.buildInteractionMatrix(HBs=HBs, SBs=0, RIB=0,PiStack=0,PiCat=0,HPh=0,DiBs=0) + matrix_sbs = self.buildInteractionMatrix(HBs=0, SBs=SBs, RIB=0,PiStack=0,PiCat=0,HPh=0,DiBs=0) + matrix_rib = self.buildInteractionMatrix(HBs=0, SBs=0, RIB=RIB,PiStack=0,PiCat=0,HPh=0,DiBs=0) + matrix_pistack = self.buildInteractionMatrix(HBs=0, SBs=0, RIB=0,PiStack=PiStack,PiCat=0,HPh=0,DiBs=0) + matrix_picat = self.buildInteractionMatrix(HBs=0, SBs=0, RIB=0,PiStack=0,PiCat=PiCat,HPh=0,DiBs=0) + matrix_hph = self.buildInteractionMatrix(HBs=0, SBs=0, RIB=0,PiStack=0,PiCat=0,HPh=HPh,DiBs=0) + matrix_dibs = self.buildInteractionMatrix(HBs=0, SBs=0, RIB=0,PiStack=0,PiCat=0,HPh=0,DiBs=DiBs) + + matrix_hbs_sum = np.sum(matrix_hbs, axis=0) + matrix_sbs_sum = np.sum(matrix_sbs, axis=0) + matrix_rib_sum = np.sum(matrix_rib, axis=0) + matrix_pistack_sum = np.sum(matrix_pistack, axis=0) + matrix_picat_sum = np.sum(matrix_picat, axis=0) + matrix_hph_sum = np.sum(matrix_hph, axis=0) + matrix_dibs_sum = np.sum(matrix_dibs, axis=0) + + width = 0.8 + fig, ax = plt.subplots(num=None, figsize=(20,6), facecolor='w') + matplotlib.rcParams['font.size'] = '24' + + sum_matrix = np.zeros(matrix_hbs_sum.shape) + pplot(sum_matrix, atoms=atoms.ca) + + if HBs != 0: + ax.bar(ResList, matrix_hbs_sum, width, color = 'blue', bottom = 0, label='HBs') + sum_matrix += matrix_hbs_sum + + if SBs != 0: + ax.bar(ResList, matrix_sbs_sum, width, color = 'yellow', bottom = sum_matrix, label='SBs') + sum_matrix += matrix_sbs_sum + + if HPh != 0: + ax.bar(ResList, matrix_hph_sum, width, color = 'silver', bottom = sum_matrix, label='HPh') + sum_matrix += matrix_hph_sum + + if RIB != 0: + ax.bar(ResList, matrix_rib_sum, width, color = 'red', bottom = sum_matrix, label='RIB') + sum_matrix += matrix_rib_sum - ax.legend(ncol=7, loc='upper center') - plt.ylim([0,max(sum_matrix)+3]) - plt.tight_layout() - plt.xlabel('Residue') - plt.ylabel('Number of counts') - - return matrix_hbs_sum, matrix_sbs_sum, matrix_rib_sum, matrix_pistack_sum, matrix_picat_sum, matrix_hph_sum, matrix_dibs_sum + if PiStack != 0: + ax.bar(ResList, matrix_pistack_sum, width, color = 'green', bottom = sum_matrix, label='PiStack') + sum_matrix += matrix_pistack_sum + + if PiCat != 0: + ax.bar(ResList, matrix_picat_sum, width, color = 'orange', bottom = sum_matrix, label='PiCat') + sum_matrix += matrix_picat_sum + + if DiBs != 0: + ax.bar(ResList, matrix_dibs_sum, width, color = 'black', bottom = sum_matrix, label='DiBs') + sum_matrix += matrix_dibs_sum + + if replace_matrix: + self._interactions_matrix = np.sum([matrix_hbs, matrix_sbs, matrix_rib, matrix_pistack, + matrix_picat, matrix_hph, matrix_dibs], axis=0) + else: + self._interactions_matrix = matrix_all + + ax.legend(ncol=7, loc='upper center') + plt.ylim([0,max(sum_matrix)+3]) + plt.tight_layout() + plt.xlabel('Residue') + plt.ylabel('Number of counts') + + return matrix_hbs_sum, matrix_sbs_sum, matrix_rib_sum, matrix_pistack_sum, matrix_picat_sum, matrix_hph_sum, matrix_dibs_sum class InteractionsTrajectory(object): diff --git a/prody/proteins/tabulated_energies.txt b/prody/proteins/tabulated_energies.txt new file mode 100644 index 000000000..009c8c1b5 --- /dev/null +++ b/prody/proteins/tabulated_energies.txt @@ -0,0 +1,400 @@ +GLY GLY -0.27 -1.77 0.0 +GLY ALA 0.08 -2.24 0.0 +GLY VAL 0.17 -2.77 0.0 +GLY ILE 0.05 -3.5 0.0 +GLY LEU 0.33 -3.79 0.0 +GLY CYS -0.26 -3.43 0.0 +GLY MET 0.31 -3.02 0.0 +GLY PHE -0.15 -3.76 0.0 +GLY TYR -0.21 -3.34 0.0 +GLY TRP -0.31 -3.77 0.0 +GLY SER 0.08 -1.68 0.0 +GLY THR -0.11 -1.81 0.0 +GLY ASP 0.11 -1.84 0.0 +GLY ASN -0.09 -1.63 0.0 +GLY GLU 0.5 -1.58 0.0 +GLY GLN -0.11 -3.02 0.0 +GLY LYS -0.17 -1.32 0.0 +GLY ARG -0.1 -2.71 0.0 +GLY HIS 0.01 -2.47 0.0 +GLY PRO 0.13 -1.01 0.0 +ALA GLY 0.08 -2.24 0.0 +ALA ALA -0.38 -3.51 0.0 +ALA VAL -0.11 -3.86 0.0 +ALA ILE -0.08 -4.45 0.0 +ALA LEU -0.09 -5.02 0.0 +ALA CYS 0.0 -3.99 0.0 +ALA MET -0.27 -4.42 0.0 +ALA PHE 0.01 -4.43 0.0 +ALA TYR 0.0 -3.96 0.0 +ALA TRP -0.38 -4.66 0.0 +ALA SER 0.08 -2.49 0.0 +ALA THR 0.14 -2.38 0.0 +ALA ASP 0.02 -2.74 0.0 +ALA ASN 0.31 -2.06 0.0 +ALA GLU 0.2 -2.69 0.0 +ALA GLN 0.08 -3.65 0.0 +ALA LYS 0.06 -1.91 0.0 +ALA ARG 0.16 -3.26 0.0 +ALA HIS 0.01 -3.29 0.0 +ALA PRO 0.19 -1.78 0.0 +VAL GLY 0.17 -2.77 0.0 +VAL ALA -0.11 -3.86 0.0 +VAL VAL -0.49 -4.86 -1.0 +VAL ILE -0.33 -5.31 -1.2 +VAL LEU -0.48 -6.03 -1.0 +VAL CYS -0.22 -4.82 -0.4 +VAL MET -0.4 -5.16 -0.6 +VAL PHE -0.27 -5.33 -1.2 +VAL TYR 0.03 -4.54 -0.8 +VAL TRP 0.2 -4.7 -1.0 +VAL SER 0.25 -2.95 -1.0 +VAL THR 0.27 -2.87 -0.7 +VAL ASP 0.11 -3.28 0.0 +VAL ASN 0.22 -2.76 -0.5 +VAL GLU 0.3 -3.2 -0.2 +VAL GLN 0.05 -4.29 -1.1 +VAL LYS 0.4 -2.19 -1.1 +VAL ARG 0.35 -3.7 0.0 +VAL HIS -0.23 -4.14 -1.1 +VAL PRO 0.16 -2.43 0.0 +ILE GLY 0.05 -3.5 0.0 +ILE ALA -0.08 -4.45 0.0 +ILE VAL -0.33 -5.31 -1.2 +ILE ILE -0.37 -5.97 -0.6 +ILE LEU -0.5 -6.67 -1.1 +ILE CYS -0.3 -5.53 -0.4 +ILE MET 0.0 -5.37 -0.7 +ILE PHE -0.44 -6.11 -0.5 +ILE TYR -0.12 -5.39 -0.5 +ILE TRP -0.26 -5.79 -1.0 +ILE SER 0.33 -3.47 -0.9 +ILE THR 0.14 -3.61 -0.7 +ILE ASP 0.54 -3.46 -0.2 +ILE ASN 0.16 -3.42 -0.5 +ILE GLU 0.13 -3.99 -0.2 +ILE GLN 0.33 -4.65 -0.6 +ILE LYS 0.32 -2.88 -1.1 +ILE ARG 0.37 -4.29 0.0 +ILE HIS -0.02 -4.55 -1.1 +ILE PRO 0.11 -3.09 0.0 +LEU GLY 0.33 -3.79 0.0 +LEU ALA -0.09 -5.02 0.0 +LEU VAL -0.48 -6.03 -1.0 +LEU ILE -0.5 -6.67 -1.1 +LEU LEU -0.42 -7.16 -0.8 +LEU CYS -0.34 -6.13 -0.4 +LEU MET -0.3 -6.24 -0.6 +LEU PHE -0.4 -6.65 -1.2 +LEU TYR 0.08 -5.67 -1.3 +LEU TRP -0.31 -6.4 -1.0 +LEU SER 0.26 -4.12 -0.9 +LEU THR 0.04 -4.28 -0.7 +LEU ASP 0.41 -4.16 -0.2 +LEU ASN 0.23 -3.94 -0.5 +LEU GLU 0.34 -4.35 -0.2 +LEU GLN 0.17 -5.36 -1.1 +LEU LYS 0.52 -3.24 -1.1 +LEU ARG 0.21 -5.01 0.0 +LEU HIS 0.25 -4.85 -1.1 +LEU PRO 0.01 -3.75 0.0 +CYS GLY -0.26 -3.43 0.0 +CYS ALA 0.0 -3.99 0.0 +CYS VAL -0.22 -4.82 -0.4 +CYS ILE -0.3 -5.53 -0.4 +CYS LEU -0.34 -6.13 -0.4 +CYS CYS -2.38 -7.23 0.0 +CYS MET -0.08 -5.07 -0.4 +CYS PHE 0.49 -4.81 -1.3 +CYS TYR 0.1 -4.71 -1.3 +CYS TRP 0.44 4.7 -0.6 +CYS SER 0.02 -3.41 0.0 +CYS THR 0.46 -2.92 -0.8 +CYS ASP 0.06 -3.56 -0.2 +CYS ASN 1.46 -1.76 -0.9 +CYS GLU 0.72 -3.02 -0.2 +CYS GLN 0.21 -4.37 -0.9 +CYS LYS -0.5 -2.28 -0.2 +CYS ARG -0.12 -4.41 -0.2 +CYS HIS -0.64 -4.79 -0.8 +CYS PRO -0.15 -2.97 0.0 +MET GLY 0.31 -3.02 0.0 +MET ALA -0.27 -4.42 0.0 +MET VAL -0.4 -5.16 -0.6 +MET ILE 0.0 -5.37 -0.7 +MET LEU -0.3 -6.24 -0.6 +MET CYS -0.08 -5.07 -0.4 +MET MET -0.74 -5.89 -0.7 +MET PHE -0.14 -5.58 -0.8 +MET TYR -0.05 -5.01 -1.2 +MET TRP -0.2 -5.49 -1.0 +MET SER 0.25 -3.33 -0.6 +MET THR 0.19 -3.33 -1.0 +MET ASP 0.09 -3.69 0.0 +MET ASN 0.32 -3.05 -0.8 +MET GLU 0.13 -3.76 -0.2 +MET GLN 0.27 -4.46 -0.5 +MET LYS 0.61 -2.36 0.0 +MET ARG 0.3 -4.13 -0.8 +MET HIS -0.17 -4.47 -0.5 +MET PRO -0.14 -3.11 0.0 +PHE GLY -0.15 -3.76 0.0 +PHE ALA 0.01 -4.43 0.0 +PHE VAL -0.27 -5.33 -1.2 +PHE ILE -0.44 -6.11 -0.5 +PHE LEU -0.4 -6.65 -1.2 +PHE CYS 0.49 -4.81 -1.3 +PHE MET -0.14 -5.58 -0.8 +PHE PHE -0.71 -6.45 -1.2 +PHE TYR -0.07 -5.33 -1.2 +PHE TRP -0.13 -5.72 -1.2 +PHE SER -0.14 -4.01 -0.6 +PHE THR -0.02 -3.85 0.0 +PHE ASP 0.55 -3.52 0.0 +PHE ASN -0.22 -3.89 -0.2 +PHE GLU 0.09 -4.1 -0.4 +PHE GLN 0.14 -4.89 -1.7 +PHE LYS 0.57 -2.7 -0.9 +PHE ARG 0.22 -4.51 -1.1 +PHE HIS 0.79 -3.82 -0.6 +PHE PRO -0.19 -3.46 0.0 +TYR GLY -0.21 -3.34 0.0 +TYR ALA 0.0 -3.96 0.0 +TYR VAL 0.03 -4.54 -0.8 +TYR ILE -0.12 -5.39 -0.5 +TYR LEU 0.08 -5.67 -1.3 +TYR CYS 0.1 -4.71 -1.3 +TYR MET -0.05 -5.01 -1.2 +TYR PHE -0.07 -5.33 -1.2 +TYR TYR 0.2 -4.58 -1.5 +TYR TRP -0.02 -5.12 -1.2 +TYR SER -0.03 -3.43 -0.2 +TYR THR 0.0 -3.33 -0.6 +TYR ASP -0.04 -3.63 -0.6 +TYR ASN 0.04 -3.14 0.0 +TYR GLU 0.08 -3.62 -0.6 +TYR GLN -0.21 -4.75 -0.7 +TYR LYS 0.14 -2.64 -0.1 +TYR ARG -0.07 -4.32 -2.1 +TYR HIS 0.34 -3.78 -1.1 +TYR PRO -0.13 -2.92 0.0 +TRP GLY -0.31 -3.77 0.0 +TRP ALA -0.38 -4.66 0.0 +TRP VAL 0.2 -4.7 -1.0 +TRP ILE -0.26 -5.79 -1.0 +TRP LEU -0.31 -6.4 -1.0 +TRP CYS 0.44 4.7 -0.6 +TRP MET -0.2 -5.49 -1.0 +TRP PHE -0.13 -5.72 -1.2 +TRP TYR -0.02 -5.12 -1.2 +TRP TRP 0.27 -5.16 -1.2 +TRP SER 0.86 -2.86 -0.9 +TRP THR 0.18 -3.48 -0.9 +TRP ASP 0.11 -3.81 -0.5 +TRP ASN 0.2 -3.31 -1.3 +TRP GLU 0.2 -3.84 -0.5 +TRP GLN 0.01 -4.87 -1.3 +TRP LYS 1.0 -3.12 -1.2 +TRP ARG 0.04 -4.54 -1.8 +TRP HIS -0.05 -4.5 -1.7 +TRP PRO -0.85 -3.96 0.0 +SER GLY 0.08 -1.68 0.0 +SER ALA 0.08 -2.49 0.0 +SER VAL 0.25 -2.95 -1.0 +SER ILE 0.33 -3.47 -0.9 +SER LEU 0.26 -4.12 -0.9 +SER CYS 0.02 -3.41 0.0 +SER MET 0.25 -3.33 -0.6 +SER PHE -0.14 -4.01 -0.6 +SER TYR -0.03 -3.43 -0.2 +SER TRP 0.86 -2.86 -0.9 +SER SER -0.14 -2.14 -0.4 +SER THR -0.27 -2.22 -0.9 +SER ASP -0.13 -2.34 -0.2 +SER ASN -0.32 -2.13 0.2 +SER GLU -0.25 -2.57 -0.2 +SER GLN 0.1 -3.06 0.2 +SER LYS -0.5 -1.91 -1.2 +SER ARG 0.08 -2.78 -0.1 +SER HIS -0.38 -3.12 -0.5 +SER PRO -0.15 -1.56 0.0 +THR GLY -0.11 -1.81 0.0 +THR ALA 0.14 -2.38 0.0 +THR VAL 0.27 -2.87 -0.7 +THR ILE 0.14 -3.61 -0.7 +THR LEU 0.04 -4.28 -0.7 +THR CYS 0.46 -2.92 -0.8 +THR MET 0.19 -3.33 -1.0 +THR PHE -0.02 -3.85 0.0 +THR TYR 0.0 -3.33 -0.6 +THR TRP 0.18 -3.48 -0.9 +THR SER -0.27 -2.22 -0.9 +THR THR -0.22 -2.12 -0.9 +THR ASP -0.26 -2.41 -0.2 +THR ASN -0.3 -2.05 0.2 +THR GLU -0.07 -2.34 -0.5 +THR GLN -0.32 -3.44 0.2 +THR LYS -0.29 -1.64 -1.2 +THR ARG 0.38 -2.43 0.4 +THR HIS -0.05 -2.73 -0.5 +THR PRO 0.11 -1.24 0.0 +ASP GLY 0.11 -1.84 0.0 +ASP ALA 0.02 -2.74 0.0 +ASP VAL 0.11 -3.28 0.0 +ASP ILE 0.54 -3.46 -0.2 +ASP LEU 0.41 -4.16 -0.2 +ASP CYS 0.06 -3.56 -0.2 +ASP MET 0.09 -3.69 0.0 +ASP PHE 0.55 -3.52 0.0 +ASP TYR -0.04 -3.63 -0.6 +ASP TRP 0.11 -3.81 -0.5 +ASP SER -0.13 -2.34 -0.2 +ASP THR -0.26 -2.41 -0.2 +ASP ASP -0.07 -2.47 0.3 +ASP ASN -0.51 -2.5 -0.2 +ASP GLU 0.17 -2.35 0.3 +ASP GLN 0.21 -3.15 -0.2 +ASP LYS -0.87 -2.47 -1.4 +ASP ARG -0.87 -3.92 -1.4 +ASP HIS 0.0 -2.93 -0.4 +ASP PRO 0.36 -1.24 0.0 +ASN GLY -0.09 -1.63 0.0 +ASN ALA 0.31 -2.06 0.0 +ASN VAL 0.22 -2.76 -0.5 +ASN ILE 0.16 -3.42 -0.5 +ASN LEU 0.23 -3.94 -0.5 +ASN CYS 1.46 -1.76 -0.9 +ASN MET 0.32 -3.05 -0.8 +ASN PHE -0.22 -3.89 -0.2 +ASN TYR 0.04 -3.14 0.0 +ASN TRP 0.2 -3.31 -1.3 +ASN SER -0.32 -2.13 0.2 +ASN THR -0.3 -2.05 0.2 +ASN ASP -0.51 -2.5 -0.2 +ASN ASN -0.4 -1.99 -0.1 +ASN GLU -0.3 -2.43 0.1 +ASN GLN -0.05 -3.0 -0.1 +ASN LYS -0.44 -1.63 0.1 +ASN ARG -0.02 -2.67 0.2 +ASN HIS -0.52 -3.05 -1.2 +ASN PRO 0.19 -1.01 0.0 +GLU GLY 0.5 -1.58 0.0 +GLU ALA 0.2 -2.69 0.0 +GLU VAL 0.3 -3.2 -0.2 +GLU ILE 0.13 -3.99 -0.2 +GLU LEU 0.34 -4.35 -0.2 +GLU CYS 0.72 -3.02 -0.2 +GLU MET 0.13 -3.76 -0.2 +GLU PHE 0.09 -4.1 -0.4 +GLU TYR 0.08 -3.62 -0.6 +GLU TRP 0.2 -3.84 -0.5 +GLU SER -0.25 -2.57 -0.2 +GLU THR -0.07 -2.34 -0.5 +GLU ASP 0.17 -2.35 0.3 +GLU ASN -0.3 -2.43 0.1 +GLU GLU -0.2 -2.85 0.3 +GLU GLN 0.03 -3.45 0.1 +GLU LYS -1.11 -2.83 -1.0 +GLU ARG -0.87 -4.05 -1.6 +GLU HIS -0.1 -3.15 -0.4 +GLU PRO 0.01 -1.7 0.0 +GLN GLY -0.11 -3.02 0.0 +GLN ALA 0.08 -3.65 0.0 +GLN VAL 0.05 -4.29 -1.1 +GLN ILE 0.33 -4.65 -0.6 +GLN LEU 0.17 -5.36 -1.1 +GLN CYS 0.21 -4.37 -0.9 +GLN MET 0.27 -4.46 -0.5 +GLN PHE 0.14 -4.89 -1.7 +GLN TYR -0.21 -4.75 -0.7 +GLN TRP 0.01 -4.87 -1.3 +GLN SER 0.1 -3.06 0.2 +GLN THR -0.32 -3.44 0.2 +GLN ASP 0.21 -3.15 -0.2 +GLN ASN -0.05 -3.0 -0.1 +GLN GLU 0.03 -3.45 0.1 +GLN GLN -0.38 -4.71 -0.1 +GLN LYS 0.0 -2.56 0.1 +GLN ARG -0.11 -4.13 0.2 +GLN HIS -0.31 -4.2 -1.2 +GLN PRO -0.11 -2.67 0.0 +LYS GLY -0.17 -1.32 0.0 +LYS ALA 0.06 -1.91 0.0 +LYS VAL 0.4 -2.19 -1.1 +LYS ILE 0.32 -2.88 -1.1 +LYS LEU 0.52 -3.24 -1.1 +LYS CYS -0.5 -2.28 -0.2 +LYS MET 0.61 -2.36 0.0 +LYS PHE 0.57 -2.7 -0.9 +LYS TYR 0.14 -2.64 -0.1 +LYS TRP 1.0 -3.12 -1.2 +LYS SER -0.5 -1.91 -1.2 +LYS THR -0.29 -1.64 -1.2 +LYS ASP -0.87 -2.47 -1.4 +LYS ASN -0.44 -1.63 0.1 +LYS GLU -1.11 -2.83 -1.0 +LYS GLN 0.0 -2.56 0.1 +LYS LYS -0.22 -1.02 0.2 +LYS ARG 0.15 -2.11 0.0 +LYS HIS -0.01 -2.14 0.0 +LYS PRO 0.3 -0.5 0.0 +ARG GLY -0.1 -2.71 0.0 +ARG ALA 0.16 -3.26 0.0 +ARG VAL 0.35 -3.7 0.0 +ARG ILE 0.37 -4.29 0.0 +ARG LEU 0.21 -5.01 0.0 +ARG CYS -0.12 -4.41 -0.2 +ARG MET 0.3 -4.13 -0.8 +ARG PHE 0.22 -4.51 -1.1 +ARG TYR -0.07 -4.32 -2.1 +ARG TRP 0.04 -4.54 -1.8 +ARG SER 0.08 -2.78 -0.1 +ARG THR 0.38 -2.43 0.4 +ARG ASP -0.87 -3.92 -1.4 +ARG ASN -0.02 -2.67 0.2 +ARG GLU -0.87 -4.05 -1.6 +ARG GLN -0.11 -4.13 0.2 +ARG LYS 0.15 -2.11 0.0 +ARG ARG -0.26 -3.98 -0.6 +ARG HIS 0.35 -3.24 -0.4 +ARG PRO -0.17 -2.43 0.0 +HIS GLY 0.01 -2.47 0.0 +HIS ALA 0.01 -3.29 0.0 +HIS VAL -0.23 -4.14 -1.1 +HIS ILE -0.02 -4.55 -1.1 +HIS LEU 0.25 -4.85 -1.1 +HIS CYS -0.64 -4.79 -0.8 +HIS MET -0.17 -4.47 -0.5 +HIS PHE 0.79 -3.82 -0.6 +HIS TYR 0.34 -3.78 -1.1 +HIS TRP -0.05 -4.5 -1.7 +HIS SER -0.38 -3.12 -0.5 +HIS THR -0.05 -2.73 -0.5 +HIS ASP 0.0 -2.93 -0.4 +HIS ASN -0.52 -3.05 -1.2 +HIS GLU -0.1 -3.15 -0.4 +HIS GLN -0.31 -4.2 -1.2 +HIS LYS -0.01 -2.14 0.0 +HIS ARG 0.35 -3.24 -0.4 +HIS HIS 0.38 -3.08 -0.5 +HIS PRO 0.33 -1.8 0.0 +PRO GLY 0.13 -1.01 0.0 +PRO ALA 0.19 -1.78 0.0 +PRO VAL 0.16 -2.43 0.0 +PRO ILE 0.11 -3.09 0.0 +PRO LEU 0.01 -3.75 0.0 +PRO CYS -0.15 -2.97 0.0 +PRO MET -0.14 -3.11 0.0 +PRO PHE -0.19 -3.46 0.0 +PRO TYR -0.13 -2.92 0.0 +PRO TRP -0.85 -3.96 0.0 +PRO SER -0.15 -1.56 0.0 +PRO THR 0.11 -1.24 0.0 +PRO ASP 0.36 -1.24 0.0 +PRO ASN 0.19 -1.01 0.0 +PRO GLU 0.01 -1.7 0.0 +PRO GLN -0.11 -2.67 0.0 +PRO LYS 0.3 -0.5 0.0 +PRO ARG -0.17 -2.43 0.0 +PRO HIS 0.33 -1.8 0.0 +PRO PRO -0.03 -0.83 0.0 diff --git a/prody/proteins/waterbridges.py b/prody/proteins/waterbridges.py index a247e07b5..75510b612 100644 --- a/prody/proteins/waterbridges.py +++ b/prody/proteins/waterbridges.py @@ -15,7 +15,18 @@ from itertools import combinations from collections import deque -from enum import Enum, auto + +from prody import PY3K +if PY3K: + from enum import Enum, auto +else: + from enum import Enum + import enum + from itertools import count + def auto(it=count()): + return next(it) + enum.auto=auto + from copy import copy from prody import LOGGER, SETTINGS @@ -263,8 +274,10 @@ def getInfoOutput(waterBridgesAtomic): bridgeOutput = [] for atom in bridge.proteins: - residueInfo = f"{atom.getResname()}{atom.getResnum()}" - atomInfo = f"{atom.getName()}_{atom.getIndex()}" + residueInfo = "{0}{1}".format(atom.getResname(), + atom.getResnum()) + atomInfo = "{0}_{1}".format(atom.getName(), + atom.getIndex()) chainInfo = atom.getChid() bridgeOutput += [residueInfo, atomInfo, chainInfo] @@ -273,7 +286,9 @@ def getInfoOutput(waterBridgesAtomic): bridgeOutput += [len(bridge.waters)] bridgeOutput += [ - list(map(lambda w: f"{w.getChid()}_{w.getIndex()}", bridge.waters))] + list(map(lambda w: "{0}_{1}".format(w.getChid(), + w.getIndex()), + bridge.waters))] output.append(bridgeOutput) @@ -314,7 +329,7 @@ def getAtomicOutput(waterBridges, relations): def getElementsRegex(elements): - return f'[{"|".join(elements)}].*' + return '[{0}].*'.format("|".join(elements)) def calcWaterBridges(atoms, **kwargs): @@ -417,7 +432,7 @@ def calcWaterBridges(atoms, **kwargs): relations = RelationList(len(atoms)) tooFarAtoms = atoms.select( - f'water and not within {distWR} of protein') + 'water and not within {0} of protein'.format(distWR)) if tooFarAtoms is None: consideredAtoms = atoms else: @@ -434,9 +449,10 @@ def calcWaterBridges(atoms, **kwargs): relations[oxygen].hydrogens.append(hydrogen) proteinHydrophilic = consideredAtoms.select( - f'protein and name "{getElementsRegex(set(donors+acceptors))}" and within {distWR} of water') + 'protein and name "{0}" and within {1} of water'.format( + getElementsRegex(set(donors+acceptors)), distWR)) - proteinHydrogens = consideredAtoms.select(f'protein and hydrogen') or [] + proteinHydrogens = consideredAtoms.select('protein and hydrogen') or [] proteinHydroPairs = findNeighbors( proteinHydrophilic, DIST_COVALENT_H, proteinHydrogens) if proteinHydrogens else [] for hydrophilic in proteinHydrophilic: @@ -474,7 +490,8 @@ def calcWaterBridges(atoms, **kwargs): waterBridgesWithIndices = getUniqueElements( waterBridgesWithIndices, getChainBridgeTuple) - log_string = f'{len(waterBridgesWithIndices)} water bridges detected using method {method}' + log_string = '{0} water bridges detected using method {1}'.format( + len(waterBridgesWithIndices), method) if prefix != '': log_string += ' for ' + prefix LOGGER.info(log_string) @@ -715,7 +732,7 @@ def getResInfo(atoms): chids = atoms.select('protein').getChids() for i, num in enumerate(nums): - dict[num] = f"{names[i]}{num}{chids[i]}" + dict[num] = "{names[i]}{num}{chids[i]}" return dict @@ -796,7 +813,8 @@ def calcWaterBridgesStatistics(frames, trajectory, **kwargs): interactionCount.removeDuplicateKeys( lambda keys, key: (key[1], key[0]) in keys) - tableHeader = f'{"RES1":<15}{"RES2":<15}{"PERC":<10}{"DIST_AVG":<10}{"DIST_STD":<10}' + tableHeader = '{0:<15}{1:<15}{2:<10}{3:<10}{4:<10}'.format( + "RES1", "RES2", "PERC", "DIST_AVG", "DIST_STD") LOGGER.info(tableHeader) info = {} file = open(filename, 'w') if filename else None @@ -819,7 +837,8 @@ def calcWaterBridgesStatistics(frames, trajectory, **kwargs): key1, key2 = (x, y), (y, x) info[key1], info[key2] = pairInfo, pairInfo - tableRow = f'{resNames[x]:<15}{resNames[y]:<15}{percentage:<10.3f}{distAvg:<10.3f}{distStd:<10.3f}' + tableRow = '{0:<15}{1:<15}{2:<10.3f}{3:<10.3f}{4:<10.3f}'.format( + resNames[x], resNames[y], percentage, distAvg, distStd) LOGGER.info(tableRow) if file: file.write(tableRow + '\n') @@ -885,7 +904,7 @@ def mofifyBeta(bridgeFrames, atoms): atoms.setBetas(0) for resnum, value in residueOccurances.items(): residueAtoms = atoms.select( - f'resnum {resnum}') + 'resnum {0}'.format(resnum)) beta = value/len(bridgeFrames) residueAtoms.setBetas(beta) @@ -1075,7 +1094,7 @@ def calcWaterBridgesDistribution(frames, res_a, res_b=None, **kwargs): plt.hist(result, rwidth=0.95, density=True) plt.xlabel('Value') plt.ylabel('Probability') - plt.title(f'Distribution: {metric}') + plt.title('Distribution: {0}'.format(metric)) if SETTINGS['auto_show']: showFigure() @@ -1108,7 +1127,8 @@ def savePDBWaterBridges(bridges, atoms, filename): waterOxygens = reduceTo1D( bridges, lambda w: w.getIndex(), lambda b: b.waters) waterAtoms = atoms.select( - f'same residue as water within 1.6 of index {" ".join(map(str, waterOxygens))}') + 'same residue as water within 1.6 of index {0}'.format( + " ".join(map(str, waterOxygens)))) atomsToSave = proteinAtoms.toAtomGroup() + waterAtoms.toAtomGroup() return writePDB(filename, atomsToSave) @@ -1147,21 +1167,23 @@ def saveBridgesFrame(trajectory, atoms, frameIndex, frame): waterAtoms = reduceTo1D(frame, sublistSel=lambda b: b.waters) waterResidues = atoms.select( - f'same residue as water within 1.6 of index {" ".join(map(lambda a: str(a.getIndex()), waterAtoms))}') + 'same residue as water within 1.6 of index {0}'.format( + " ".join(map(lambda a: str(a.getIndex()), waterAtoms)))) bridgeProteinAtoms = reduceTo1D( frame, lambda p: p.getResnum(), lambda b: b.proteins) atoms.setOccupancies(0) - atoms.select( - f'resid {" ".join(map(str, bridgeProteinAtoms))}').setOccupancies(1) + atoms.select('resid {0}'.format( + " ".join(map(str, bridgeProteinAtoms)))).setOccupancies(1) atomsToSave = atoms.select( 'protein').toAtomGroup() + waterResidues.toAtomGroup() if trajectory: - writePDB(f'{filename}_{frameIndex}.pdb', atomsToSave) + writePDB('{0}_{1}.pdb'.format(filename, frameIndex), + atomsToSave) else: - writePDB(f'{filename}_{frameIndex}.pdb', + writePDB('{0}_{1}.pdb'.format(filename, frameIndex), atomsToSave, csets=frameIndex) if max_proc == 1: @@ -1210,7 +1232,7 @@ def saveWaterBridges(atomicBridges, filename): if isInfoOutput: info = getWaterBridgesInfoOutput(atomicBridges) for frameIndex, frame in enumerate(info): - file.write(f'FRAME {frameIndex}\n') + file.write('FRAME {0}\n'.format(frameIndex)) for bridge in frame: file.write(' '.join(map(str, bridge)) + '\n') diff --git a/prody/tests/proteins/test_insty.py b/prody/tests/proteins/test_insty.py index 5e518badf..d637fab73 100644 --- a/prody/tests/proteins/test_insty.py +++ b/prody/tests/proteins/test_insty.py @@ -12,6 +12,8 @@ from prody.proteins.interactions import calcPiCationTrajectory, calcHydrophobicTrajectory from prody.proteins.interactions import calcDisulfideBondsTrajectory, calcProteinInteractions +import sys + class TestInteractions(unittest.TestCase): def setUp(self): @@ -150,6 +152,23 @@ def testDisulfideBondsSave(self): data_test = np.load('test_2k39_disu.npy', allow_pickle=True) assert_equal(sorted([i[-1][-1] for i in data_test if i]), sorted([i[-1][-1] for i in self.DISU_INTERACTIONS if i]), 'failed to get correct disulfide bonds from saving and loading') + + def testImportHpb(self): + + try: + import prody.proteins.hpb as hpb + imported_hpb = True + except ImportError: + try: + import hpb + imported_hpb = True + except ImportError: + imported_hpb = False + + if sys.version_info[1] < 11: + self.assertTrue(imported_hpb) + else: + self.assertFalse(imported_hpb) @classmethod def tearDownClass(cls): diff --git a/setup.py b/setup.py index 4c8e3a9e2..f85413b04 100644 --- a/setup.py +++ b/setup.py @@ -7,6 +7,8 @@ from setuptools import setup from setuptools import Extension +import shutil + if sys.version_info[:2] < (2, 7): sys.stderr.write('Python 2.6 and older is not supported\n') sys.exit() @@ -85,7 +87,8 @@ 'datafiles/dcd*.dcd', 'datafiles/xml*.xml', 'datafiles/msa*', - 'datafiles/mmcif*cif',] + 'datafiles/mmcif*cif',], + 'prody.proteins': ['tabulated_energies.txt'], } PACKAGE_DIR = {} @@ -94,7 +97,15 @@ from glob import glob tntDir = join('prody', 'utilities', 'tnt') -hpbDir = join('prody', 'proteins', 'hpbmodule') +hpbSoDir = join('prody', 'proteins', 'hpbmodule', + 'hpb_Python{0}.{1}'.format(sys.version_info[0], + sys.version_info[1])) +proteinsDir = join('prody', 'proteins') + +try: + shutil.copy(hpbSoDir + "/hpb.so", proteinsDir) +except FileNotFoundError: + pass EXTENSIONS = [ Extension('prody.dynamics.rtbtools', @@ -164,8 +175,8 @@ setup( name='ProDy', version=__version__, - author='James Krieger, She Zhang, Hongchun Li, Cihan Kaya, Ahmet Bakan, and others', - author_email='kriegerj@pitt.edu', + author='James Krieger, Karolina Mikulska-Ruminska, She Zhang, Hongchun Li, Cihan Kaya, Ahmet Bakan, and others', + author_email='jamesmkrieger@gmail.com', description='A Python Package for Protein Dynamics Analysis', long_description=long_description, url='http://www.csb.pitt.edu/ProDy',