From d5cbe17da6b7779358ec53253bd23e96abc446dd Mon Sep 17 00:00:00 2001 From: James Krieger Date: Fri, 22 Nov 2024 13:21:11 +0100 Subject: [PATCH 1/8] add back padding --- prody/proteins/interactions.py | 41 +++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/prody/proteins/interactions.py b/prody/proteins/interactions.py index 1e05157ec..42c11e8ca 100644 --- a/prody/proteins/interactions.py +++ b/prody/proteins/interactions.py @@ -3805,6 +3805,20 @@ def showCumulativeInteractionTypes(self, **kwargs): default is False :type overwrite_energies: bool + :arg percentile: a percentile threshold to remove outliers, i.e. only showing data within *p*-th + to *100-p*-th percentile. Default is None, so no axis limits. + :type percentile: float + + :arg vmin: a minimum value threshold to remove outliers, i.e. only showing data greater than vmin + This overrides percentile. Default is None, so no axis limits and little padding at the + bottom when energy=True. + :type vmin: float + + :arg vmax: a maximum value threshold to remove outliers, i.e. only showing data less than vmax + This overrides percentile. Default is None, so no axis limits and a little padding for + interaction type labels. + :type vmax: float + 'IB_solv' and 'IB_nosolv' are derived from empirical potentials from O Keskin, I Bahar and colleagues from [OK98]_. @@ -3833,6 +3847,15 @@ def showCumulativeInteractionTypes(self, **kwargs): if not isinstance(energy, bool): raise TypeError('energy should be True or False') + p = kwargs.pop('percentile', None) + vmin = vmax = None + if p is not None: + vmin = np.percentile(matrix, p) + vmax = np.percentile(matrix, 100-p) + + vmin = kwargs.pop('vmin', vmin) + vmax = kwargs.pop('vmax', vmax) + ResNumb = atoms.select('protein and name CA').getResnums() ResName = atoms.select('protein and name CA').getResnames() ResChid = atoms.select('protein and name CA').getChids() @@ -3861,8 +3884,13 @@ def showCumulativeInteractionTypes(self, **kwargs): ax.bar(ResList, matrix_en_sum, width, color='blue') - #plt.xlim([ResList[0]-0.5, ResList[-1]+0.5]) - plt.ylim([min(matrix_en_sum)-1,0]) + if vmin is None: + vmin = np.min(matrix_en_sum) * 1.2 + + if vmax is None: + vmax = np.max(matrix_en_sum) + + plt.ylim([vmin, vmax]) plt.tight_layout() plt.xlabel('Residue') plt.ylabel('Cumulative Energy [kcal/mol]') @@ -3940,7 +3968,14 @@ def showCumulativeInteractionTypes(self, **kwargs): self._interactions_matrix = matrix_all ax.legend(ncol=7, loc='upper center') - plt.ylim([0,max(sum_matrix)+3]) + + if vmin is None: + vmin = np.min(sum_matrix) + + if vmax is None: + vmax = np.max(sum_matrix) * 1.5 + + plt.ylim([vmin, vmax]) plt.tight_layout() plt.xlabel('Residue') plt.ylabel('Number of counts') From de64e4cd082c2aecd2c76708871a0ecea5e0543a Mon Sep 17 00:00:00 2001 From: James Krieger Date: Fri, 22 Nov 2024 16:00:38 +0100 Subject: [PATCH 2/8] add units to docs --- prody/proteins/interactions.py | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/prody/proteins/interactions.py b/prody/proteins/interactions.py index 42c11e8ca..88a106307 100644 --- a/prody/proteins/interactions.py +++ b/prody/proteins/interactions.py @@ -277,9 +277,11 @@ def checkNonstandardResidues(atoms): 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' (non-solvent-mediated), 'IB_solv' (solvent-mediated) - are taken from [OK98]_ and 'CS' from InSty paper (under preparation). + The unit of energy is kcal/mol. The energies defined as 'IB_nosolv' (non-solvent-mediated) and + 'IB_solv' (solvent-mediated) are taken from [OK98]_ and 'CS' from InSty paper (under preparation). Protonation of residues is not distinguished. The protonation of residues is not distinguished. + 'IB_solv' and 'IB_nosolv' have RT units and 'CS' has units of kcal/mol. + Known residues such as HSD, HSE, HIE, and HID (used in MD simulations) are treated as HIS. :arg data: list with interactions from calcHydrogenBonds() or other types @@ -2133,9 +2135,9 @@ def calcStatisticsInteractions(data, **kwargs): (2) average distance of interactions for each pair [in Ang], (3) standard deviation [Ang.], (4) Energy [in kcal/mol] that is not distance dependent. Energy by default is solvent-mediated - from [OK98]_ ('IB_solv'). To use non-solvent-mediated entries ('IB_nosolv') from [OK98]_ or - solvent-mediated values obtained for InSty paper ('CS', under preparation) change - `energy_list_type` parameter. + from [OK98]_ ('IB_solv') in RT units. To use non-solvent-mediated (residue-mediated) entries ('IB_nosolv') + from [OK98]_ in RT units or solvent-mediated values obtained from MD for InSty paper ('CS', under preparation) + in kcal/mol, change `energy_list_type` parameter. If energy information is not available, please check whether the pair of residues is listed in the "tabulated_energies.txt" file, which is localized in the ProDy directory. @@ -3464,15 +3466,10 @@ def buildInteractionMatrixEnergy(self, **kwargs): :type energy_list_type: str 'IB_solv' and 'IB_nosolv' are derived from empirical potentials from - O Keskin, I Bahar and colleagues from [OK98]_. + O Keskin, I Bahar and colleagues from [OK98]_ and have RT units. 'CS' is from MD simulations of amino acid pairs from Carlos Simmerling - and Gary Wu. - - .. [OK98] Keskin O, Bahar I, Badretdinov AY, Ptitsyn OB, Jernigan RL, - Empirical solvent-mediated potentials hold for both intra-molecular - and inter-molecular inter-residue interactions - *Protein Sci* **1998** 7(12):2578-2586. + and Gary Wu in the InSty paper (under preparation) and have units of kcal/mol. """ import numpy as np @@ -3820,15 +3817,10 @@ def showCumulativeInteractionTypes(self, **kwargs): :type vmax: float 'IB_solv' and 'IB_nosolv' are derived from empirical potentials from - O Keskin, I Bahar and colleagues from [OK98]_. + O Keskin, I Bahar and colleagues from [OK98]_ and have RT units. 'CS' is from MD simulations of amino acid pairs from Carlos Simmerling - and Gary Wu. - - .. [OK98] Keskin O, Bahar I, Badretdinov AY, Ptitsyn OB, Jernigan RL, - Empirical solvent-mediated potentials hold for both intra-molecular - and inter-molecular inter-residue interactions - *Protein Sci* **1998** 7(12):2578-2586. + and Gary Wu for the InSty paper (under preparation) and have units kcal/mol. """ import numpy as np From ec245df15a9a6792461d68b131900870d39f1de4 Mon Sep 17 00:00:00 2001 From: James Krieger Date: Fri, 22 Nov 2024 16:16:49 +0100 Subject: [PATCH 3/8] update unit in graphs and logs --- prody/proteins/interactions.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/prody/proteins/interactions.py b/prody/proteins/interactions.py index 88a106307..eacd6c354 100644 --- a/prody/proteins/interactions.py +++ b/prody/proteins/interactions.py @@ -2194,6 +2194,7 @@ def calcStatisticsInteractions(data, **kwargs): } statistic = [] + unit = 'RT' if energy_list_type in ['IB_solv', 'IB_nosolv'] else 'kcal/mol' for key, value in stats.items(): if float(value['weight']) > weight_cutoff: LOGGER.info("Statistics for {0}:".format(key)) @@ -2201,7 +2202,7 @@ def calcStatisticsInteractions(data, **kwargs): LOGGER.info(" Standard deviation [Ang.]: {0}".format(value['stddev'])) LOGGER.info(" Weight: {0}".format(value['weight'])) try: - LOGGER.info(" Energy [kcal/mol]: {0}".format(value['energy'])) + LOGGER.info(" Energy [{0}]: {1}".format(unit, value['energy'])) statistic.append([key, value['weight'], value['mean'], value['stddev'], value['energy']]) except: statistic.append([key, value['weight'], value['mean'], value['stddev']]) @@ -3885,7 +3886,9 @@ def showCumulativeInteractionTypes(self, **kwargs): plt.ylim([vmin, vmax]) plt.tight_layout() plt.xlabel('Residue') - plt.ylabel('Cumulative Energy [kcal/mol]') + + unit = 'RT' if energy_list_type in ['IB_solv', 'IB_nosolv'] else 'kcal/mol' + plt.ylabel('Cumulative Energy [{0}]'.format(unit)) plt.show() return matrix_en_sum From b811e3c0011219aaff88bb525ae2d00dff46d5f3 Mon Sep 17 00:00:00 2001 From: James Krieger Date: Fri, 22 Nov 2024 16:18:01 +0100 Subject: [PATCH 4/8] add vmin vmax docs to showMatrix --- prody/utilities/catchall.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/prody/utilities/catchall.py b/prody/utilities/catchall.py index 94a9de640..9e9c766c2 100644 --- a/prody/utilities/catchall.py +++ b/prody/utilities/catchall.py @@ -610,6 +610,14 @@ def showMatrix(matrix, x_array=None, y_array=None, **kwargs): to *100-p*-th percentile :type percentile: float + :arg vmin: a minimum value threshold to remove outliers, i.e. only showing data greater than vmin + This overrides percentile. + :type vmin: float + + :arg vmax: a maximum value threshold to remove outliers, i.e. only showing data less than vmax + This overrides percentile. + :type vmax: float + :arg interactive: turn on or off the interactive options :type interactive: bool From 3724094778ff0bfaa6f2fd3a2a0feafa1e283700 Mon Sep 17 00:00:00 2001 From: James Krieger Date: Fri, 22 Nov 2024 18:10:48 +0100 Subject: [PATCH 5/8] add selstr to cum ints --- prody/proteins/interactions.py | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/prody/proteins/interactions.py b/prody/proteins/interactions.py index eacd6c354..183345a0e 100644 --- a/prody/proteins/interactions.py +++ b/prody/proteins/interactions.py @@ -21,7 +21,7 @@ from numpy import * from prody import LOGGER, SETTINGS, PY3K from prody.atomic import AtomGroup, Atom, Atomic, Selection, Select -from prody.atomic import flags +from prody.atomic import flags, sliceAtomicData from prody.utilities import importLA, checkCoords, showFigure, getCoords from prody.measure import calcDistance, calcAngle, calcCenter from prody.measure.contacts import findNeighbors @@ -3789,7 +3789,10 @@ def showCumulativeInteractionTypes(self, **kwargs): :arg DiBs: score per disulfide bond :type DiBs: int, float - + + :arg selstr: selection string for focusing the plot + :type selection: str + :arg energy: sum of the energy between residues default is False :type energy: bool @@ -3849,6 +3852,10 @@ def showCumulativeInteractionTypes(self, **kwargs): vmin = kwargs.pop('vmin', vmin) vmax = kwargs.pop('vmax', vmax) + selstr = kwargs.pop('selstr', None) + if selstr is not None: + atoms = atoms.select(selstr) + ResNumb = atoms.select('protein and name CA').getResnums() ResName = atoms.select('protein and name CA').getResnames() ResChid = atoms.select('protein and name CA').getChids() @@ -3872,6 +3879,10 @@ def showCumulativeInteractionTypes(self, **kwargs): fig, ax = plt.subplots(num=None, figsize=(20,6), facecolor='w') matplotlib.rcParams['font.size'] = '24' + if selstr is not None: + matrix_en_sum = sliceAtomicData(matrix_en_sum, + self._atoms.ca, selstr) + zeros_row = np.zeros(matrix_en_sum.shape) pplot(zeros_row, atoms=atoms.ca) @@ -3921,6 +3932,23 @@ def showCumulativeInteractionTypes(self, **kwargs): matrix_hph_sum = np.sum(matrix_hph, axis=0) matrix_dibs_sum = np.sum(matrix_dibs, axis=0) + all_ca = self._atoms.ca + if selstr is not None: + matrix_hbs_sum = sliceAtomicData(matrix_hbs_sum, + all_ca, selstr) + matrix_sbs_sum = sliceAtomicData(matrix_sbs_sum, + all_ca, selstr) + matrix_rib_sum = sliceAtomicData(matrix_rib_sum, + all_ca, selstr) + matrix_pistack_sum = sliceAtomicData(matrix_pistack_sum, + all_ca, selstr) + matrix_picat_sum = sliceAtomicData(matrix_picat_sum, + all_ca, selstr) + matrix_hph_sum = sliceAtomicData(matrix_hph_sum, + all_ca, selstr) + matrix_dibs_sum = sliceAtomicData(matrix_dibs_sum, + all_ca, selstr) + width = 0.8 fig, ax = plt.subplots(num=None, figsize=(20,6), facecolor='w') matplotlib.rcParams['font.size'] = '24' From 106e9c649d3eddf61d178e8f8d545279483b4286 Mon Sep 17 00:00:00 2001 From: James Krieger Date: Fri, 22 Nov 2024 18:43:42 +0100 Subject: [PATCH 6/8] add showSelectionMatrix --- prody/dynamics/plotting.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/prody/dynamics/plotting.py b/prody/dynamics/plotting.py index 867933572..3d9ea0de2 100644 --- a/prody/dynamics/plotting.py +++ b/prody/dynamics/plotting.py @@ -37,7 +37,7 @@ 'showPairDeformationDist','showMeanMechStiff', 'showPerturbResponse', 'showTree', 'showTree_networkx', 'showAtomicMatrix', 'pimshow', 'showAtomicLines', 'pplot', - 'showDomainBar'] + 'showDomainBar', 'showSelectionMatrix'] def showEllipsoid(modes, onto=None, n_std=2, scale=1., *args, **kwargs): @@ -2381,3 +2381,27 @@ def showTree_networkx(tree, node_size=20, node_color='red', node_shape='o', showFigure() return mpl.gca() + +def showSelectionMatrix(matrix, atoms, selstr_x=None, selstr_y=None, **kwargs): + """ + Show a matrix similarly to showAtomicMatrix but only for + selected atoms based on *selstr_x* and *selstr_y* + """ + atoms_x = atoms + atoms_y = atoms + + if selstr_x is not None: + if not isinstance(selstr_x, str): + raise TypeError('selstr_x should be a str') + + matrix = sliceAtomicData(matrix, atoms, selstr_x, axis=0) + _, atoms_x = sliceAtoms(atoms, selstr_x) + + if selstr_y is not None: + if not isinstance(selstr_y, str): + raise TypeError('selstr_y should be a str') + + matrix = sliceAtomicData(matrix, atoms, selstr_y, axis=1) + _, atoms_y = sliceAtoms(atoms, selstr_y) + + return showAtomicMatrix(matrix, atoms=[atoms_x, atoms_y], **kwargs) From bebaf7c625f2a5d64ec52faf7ea0ec73f3c10629 Mon Sep 17 00:00:00 2001 From: James Krieger Date: Mon, 25 Nov 2024 14:39:46 +0100 Subject: [PATCH 7/8] showCumulativeInteractionTypes pplot kwargs --- prody/proteins/interactions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prody/proteins/interactions.py b/prody/proteins/interactions.py index 183345a0e..51dd59e44 100644 --- a/prody/proteins/interactions.py +++ b/prody/proteins/interactions.py @@ -3884,7 +3884,7 @@ def showCumulativeInteractionTypes(self, **kwargs): self._atoms.ca, selstr) zeros_row = np.zeros(matrix_en_sum.shape) - pplot(zeros_row, atoms=atoms.ca) + pplot(zeros_row, atoms=atoms.ca, **kwargs) ax.bar(ResList, matrix_en_sum, width, color='blue') From 3a1f6b10162f4a76e2db4d1640c1cebf339a1830 Mon Sep 17 00:00:00 2001 From: James Krieger Date: Thu, 28 Nov 2024 12:35:33 +0100 Subject: [PATCH 8/8] doc selstr x and y more --- prody/dynamics/plotting.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/prody/dynamics/plotting.py b/prody/dynamics/plotting.py index 3d9ea0de2..145d9d066 100644 --- a/prody/dynamics/plotting.py +++ b/prody/dynamics/plotting.py @@ -2386,6 +2386,16 @@ def showSelectionMatrix(matrix, atoms, selstr_x=None, selstr_y=None, **kwargs): """ Show a matrix similarly to showAtomicMatrix but only for selected atoms based on *selstr_x* and *selstr_y* + + :arg selstr_x: a selection string used with sliceAtomicData with axis=0 + to slice the matrix in the x axis and label it with corresponding atoms + :type selstr_x: str + + :arg selstr_y: a selection string used with sliceAtomicData with axis=1 + to slice the matrix in the y axis and label it with corresponding atoms + :type selstr_y: str + + If either of these are left as *None*, then no slicing is performed in that direction. """ atoms_x = atoms atoms_y = atoms