def showPairDeformationDist(model, coords, ind1, ind2, *args, **kwargs): """Show distribution of deformations in distance contributed by each mode for selected pair of residues *ind1* *ind2* using :func:`~matplotlib.pyplot.plot`. """ import matplotlib import matplotlib.pyplot as plt if not isinstance(model, NMA): raise TypeError('model must be a NMA instance, ' 'not {0}'.format(type(model))) elif not model.is3d(): raise TypeError('model must be a 3-dimensional NMA instance') elif len(model) == 0: raise ValueError('model must have normal modes calculated') elif model.getStiffness() is None: raise ValueError('model must have stiffness matrix calculated') d_pair = calcPairDeformationDist(model, coords, ind1, ind2) with plt.style.context('fivethirtyeight'): matplotlib.rcParams['font.size'] = '16' fig = plt.figure(num=None, figsize=(12,8), dpi=100, facecolor='w') #plt.title(str(model)) plt.plot(d_pair[0], d_pair[1], 'k-', linewidth=1.5, *args, **kwargs) plt.xlabel('mode (k)', fontsize = '18') plt.ylabel('d$^k$' '($\AA$)', fontsize = '18') if SETTINGS['auto_show']: showFigure() return plt.show
def showNormDistFunct(model, coords, *args, **kwargs): """Show normalized distance fluctuation matrix using :func:`~matplotlib.pyplot.imshow`. By default, *origin=lower* keyword arguments are passed to this function, but user can overwrite these parameters.""" import math import matplotlib import matplotlib.pyplot as plt normdistfunct = model.getNormDistFluct(coords) if not 'origin' in kwargs: kwargs['origin'] = 'lower' matplotlib.rcParams['font.size'] = '14' fig = plt.figure(num=None, figsize=(10,8), dpi=100, facecolor='w') show = plt.imshow(normdistfunct, *args, **kwargs), plt.colorbar() plt.clim(math.floor(np.min(normdistfunct[np.nonzero(normdistfunct)])), \ round(np.amax(normdistfunct),1)) plt.title('Normalized Distance Fluctution Matrix') plt.xlabel('Indices', fontsize='16') plt.ylabel('Indices', fontsize='16') if SETTINGS['auto_show']: showFigure() return show
def showLinkage(V, **kwargs): """Shows the dendrogram of hierarchical clustering on *V*. See :func:`scipy.cluster.hierarchy.dendrogram` for details. :arg V: row-normalized eigenvectors for the purpose of clustering. :type V: :class:`numpy.ndarray` """ from .functions import _getEigvecs V = _getEigvecs(V, row_norm=True) try: from scipy.cluster.hierarchy import linkage, fcluster, dendrogram except ImportError: raise ImportError('Use of this function (showLinkage) requires the ' 'installation of scipy.') method = kwargs.pop('method', 'single') metric = kwargs.pop('metric', 'euclidean') Z = linkage(V, method=method, metric=metric) no_labels = kwargs.pop('no_labels', True) dendrogram(Z, no_labels=no_labels, **kwargs) if SETTINGS['auto_show']: showFigure() return Z
def showScaledSqFlucts(modes, *args, **kwargs): """Show scaled square fluctuations using :func:`~matplotlib.pyplot.plot`. Modes or mode sets given as additional arguments will be scaled to have the same mean squared fluctuations as *modes*.""" import matplotlib.pyplot as plt sqf = calcSqFlucts(modes) mean = sqf.mean() args = list(args) modesarg = [] i = 0 while i < len(args): if isinstance(args[i], (VectorBase, ModeSet, NMA)): modesarg.append(args.pop(i)) else: i += 1 show = [plt.plot(sqf, *args, label=str(modes), **kwargs)] plt.xlabel('Indices') plt.ylabel('Square fluctuations') for modes in modesarg: sqf = calcSqFlucts(modes) scalar = mean / sqf.mean() show.append(plt.plot(sqf * scalar, *args, label='{0} (x{1:.2f})'.format(str(modes), scalar), **kwargs)) if SETTINGS['auto_show']: showFigure() return show
def showNormedSqFlucts(modes, *args, **kwargs): """Show normalized square fluctuations via :func:`~matplotlib.pyplot.plot`. """ import matplotlib.pyplot as plt sqf = calcSqFlucts(modes) args = list(args) modesarg = [] i = 0 while i < len(args): if isinstance(args[i], (VectorBase, ModeSet, NMA)): modesarg.append(args.pop(i)) else: i += 1 show = [ plt.plot(sqf / (sqf**2).sum()**0.5, *args, label='{0}'.format(str(modes)), **kwargs) ] plt.xlabel('Indices') plt.ylabel('Square fluctuations') for modes in modesarg: sqf = calcSqFlucts(modes) show.append( plt.plot(sqf / (sqf**2).sum()**0.5, *args, label='{0}'.format(str(modes)), **kwargs)) if SETTINGS['auto_show']: showFigure() return show
def showOverlapTable(modes_x, modes_y, **kwargs): """Show overlap table using :func:`~matplotlib.pyplot.pcolor`. *modes_x* and *modes_y* are sets of normal modes, and correspond to x and y axes of the plot. Note that mode indices are incremented by 1. List of modes is assumed to contain a set of contiguous modes from the same model. Default arguments for :func:`~matplotlib.pyplot.pcolor`: * ``cmap=plt.cm.jet`` * ``norm=matplotlib.colors.Normalize(0, 1)``""" import matplotlib.pyplot as plt overlap = abs(calcOverlap(modes_y, modes_x)) if overlap.ndim == 0: overlap = np.array([[overlap]]) elif overlap.ndim == 1: overlap = overlap.reshape((modes_y.numModes(), modes_x.numModes())) cmap = kwargs.pop('cmap', plt.cm.jet) norm = kwargs.pop('norm', matplotlib.colors.Normalize(0, 1)) show = (plt.pcolor(overlap, cmap=cmap, norm=norm, **kwargs), plt.colorbar()) x_range = np.arange(1, modes_x.numModes() + 1) plt.xticks(x_range - 0.5, x_range) plt.xlabel(str(modes_x)) y_range = np.arange(1, modes_y.numModes() + 1) plt.yticks(y_range - 0.5, y_range) plt.ylabel(str(modes_y)) plt.axis([0, modes_x.numModes(), 0, modes_y.numModes()]) if SETTINGS['auto_show']: showFigure() return show
def showNormDistFunct(model, coords, *args, **kwargs): """Show normalized distance fluctuation matrix using :func:`~matplotlib.pyplot.imshow`. By default, *origin=lower* keyword arguments are passed to this function, but user can overwrite these parameters.""" import math import matplotlib import matplotlib.pyplot as plt normdistfunct = model.getNormDistFluct(coords) if not 'origin' in kwargs: kwargs['origin'] = 'lower' matplotlib.rcParams['font.size'] = '14' fig = plt.figure(num=None, figsize=(10, 8), dpi=100, facecolor='w') show = plt.imshow(normdistfunct, *args, **kwargs), plt.colorbar() plt.clim(math.floor(np.min(normdistfunct[np.nonzero(normdistfunct)])), \ round(np.amax(normdistfunct),1)) plt.title('Normalized Distance Fluctution Matrix') plt.xlabel('Indices', fontsize='16') plt.ylabel('Indices', fontsize='16') if SETTINGS['auto_show']: showFigure() return show
def showMechStiff(model, coords, *args, **kwargs): """Show mechanical stiffness matrix using :func:`~matplotlib.pyplot.imshow`. By default, *origin=lower* keyword arguments are passed to this function, but user can overwrite these parameters.""" import math import matplotlib import matplotlib.pyplot as plt arange = np.arange(model.numAtoms()) model.buildMechStiff(coords) if not 'origin' in kwargs: kwargs['origin'] = 'lower' if 'jet_r' in kwargs: import matplotlib.cm as plt kwargs['jet_r'] = 'cmap=cm.jet_r' MechStiff = model.getStiffness() matplotlib.rcParams['font.size'] = '14' fig = plt.figure(num=None, figsize=(10, 8), dpi=100, facecolor='w') show = plt.imshow(MechStiff, *args, **kwargs), plt.colorbar() plt.clim(math.floor(np.min(MechStiff[np.nonzero(MechStiff)])), \ round(np.amax(MechStiff),1)) #plt.title('Mechanical Stiffness Matrix')# for {0}'.format(str(model))) plt.xlabel('Indices', fontsize='16') plt.ylabel('Indices', fontsize='16') if SETTINGS['auto_show']: showFigure() return show
def showPairDeformationDist(model, coords, ind1, ind2, *args, **kwargs): """Show distribution of deformations in distance contributed by each mode for selected pair of residues *ind1* *ind2* using :func:`~matplotlib.pyplot.plot`. """ import matplotlib import matplotlib.pyplot as plt if not isinstance(model, NMA): raise TypeError('model must be a NMA instance, ' 'not {0}'.format(type(model))) elif not model.is3d(): raise TypeError('model must be a 3-dimensional NMA instance') elif len(model) == 0: raise ValueError('model must have normal modes calculated') elif model.getStiffness() is None: raise ValueError('model must have stiffness matrix calculated') d_pair = calcPairDeformationDist(model, coords, ind1, ind2) with plt.style.context('fivethirtyeight'): matplotlib.rcParams['font.size'] = '16' fig = plt.figure(num=None, figsize=(12, 8), dpi=100, facecolor='w') #plt.title(str(model)) plt.plot(d_pair[0], d_pair[1], 'k-', linewidth=1.5, *args, **kwargs) plt.xlabel('mode (k)', fontsize='18') plt.ylabel('d$^k$' '($\AA$)', fontsize='18') if SETTINGS['auto_show']: showFigure() return plt.show
def showCumulFractVars(modes, *args, **kwargs): """Show fraction of variances of *modes* using :func:`~matplotlib.pyplot. plot`. Note that mode indices are incremented by 1. See also :func:`.showFractVars` function.""" import matplotlib.pyplot as plt if not isinstance(modes, (Mode, NMA, ModeSet)): raise TypeError('modes must be a Mode, NMA, or ModeSet instance, ' 'not {0}'.format(type(modes))) if isinstance(modes, Mode): indices = modes.getIndices() + 0.5 modes = [modes] elif isinstance(modes, ModeSet): indices = modes.getIndices() + 0.5 else: indices = np.arange(len(modes)) + 0.5 fracts = calcFractVariance(modes).cumsum() show = plt.plot(indices, fracts, *args, **kwargs) axis = list(plt.axis()) axis[0] = 0.5 axis[2] = 0 axis[3] = 1 plt.axis(axis) plt.xlabel('Mode index') plt.ylabel('Fraction of variance') if SETTINGS['auto_show']: showFigure() return show
def showMode(mode, *args, **kwargs): """Show mode array using :func:`~matplotlib.pyplot.plot`.""" import matplotlib.pyplot as plt show_hinge = kwargs.pop('hinge', True) show_zero = kwargs.pop('zero', False) if not isinstance(mode, Mode): raise TypeError('mode must be a Mode instance, ' 'not {0}'.format(type(mode))) if mode.is3d(): a3d = mode.getArrayNx3() show = plt.plot(a3d[:, 0], *args, label='x-component', **kwargs) plt.plot(a3d[:, 1], *args, label='y-component', **kwargs) plt.plot(a3d[:, 2], *args, label='z-component', **kwargs) else: a1d = mode._getArray() show = plt.plot(a1d, *args, **kwargs) if show_hinge: hinges = mode.getHinges() if hinges is not None: plt.plot(hinges, a1d[hinges], 'r*') plt.title(str(mode)) plt.xlabel('Indices') if show_zero: plt.plot(plt.xlim(), (0,0), 'r--') if SETTINGS['auto_show']: showFigure() return show
def showMeanMechStiff(model, coords, header, chain='A', *args, **kwargs): """Show mean value of effective spring constant with secondary structure taken from MechStiff. Header is needed to obatin secondary structure range. Using ``'jet_r'`` as argument color map will be reverse (similar to VMD program coding). """ meanStiff = np.array([np.mean(model.getStiffness(), axis=0)]) import matplotlib import matplotlib.pyplot as plt import matplotlib.patches as patches fig = plt.figure(figsize=[18, 6], facecolor='w', dpi=100) if 'jet_r' in kwargs: import matplotlib.cm as plt kwargs['jet_r'] = 'cmap=cm.jet_r' if 'nearest' in kwargs: kwargs['nearest'] = 'interpolation=nearest' with plt.style.context('fivethirtyeight'): ax = fig.add_subplot(111) matplotlib.rcParams['font.size'] = '24' plt.plot(np.arange(len(meanStiff[0])) + coords.getResnums()[0], meanStiff[0], 'k-', linewidth=3) plt.xlim(coords.getResnums()[0], coords.getResnums()[-1]) ax_top = round( np.max(meanStiff[0]) + ((np.max(meanStiff[0]) - np.min(meanStiff[0])) / 3)) ax_bottom = np.floor(np.min(meanStiff[0])) LOGGER.info( 'The range of mean effective force constant is: {0} to {1}.'. format(min(meanStiff[0]), max(meanStiff[0]))) plt.ylim(ax_bottom, ax_top) plt.xlabel('residue', fontsize='22') plt.ylabel('mean $\kappa$ [a.u.]', fontsize='22') ax = fig.add_subplot(411, aspect='equal') plt.imshow(meanStiff, *args, **kwargs) header_ss = header['sheet_range'] + header['helix_range'] for i in range(len(header_ss)): if header_ss[i][1] == chain: beg = int(header_ss[i][-2]) - coords.getResnums()[0] end = int(header_ss[i][-1]) - coords.getResnums()[0] add_beg = end - beg if header_ss[i][0] == 'H': ax.add_patch(patches.Rectangle((beg-1,-0.7),add_beg,\ 1.4,fill=False, linestyle='solid',edgecolor='#b22683', linewidth=2)) elif header_ss[i][0] == 'E': if header_ss[i][2] == -1: ax.add_patch(patches.Arrow(beg-1,0,add_beg,0,width=4.65, \ fill=False, linestyle='solid',edgecolor='black', linewidth=2)) else: ax.add_patch(patches.Arrow(end-1,0,add_beg*(-1),0,width=4.65, \ fill=False, linestyle='solid',edgecolor='black', linewidth=2)) plt.axis('off') ax.set_ylim(-1.7, 1.7) if SETTINGS['auto_show']: showFigure() return plt.show
def showOverlapTable(modes_x, modes_y, **kwargs): """Show overlap table using :func:`~matplotlib.pyplot.pcolor`. *modes_x* and *modes_y* are sets of normal modes, and correspond to x and y axes of the plot. Note that mode indices are incremented by 1. List of modes is assumed to contain a set of contiguous modes from the same model. Default arguments for :func:`~matplotlib.pyplot.pcolor`: * ``cmap=plt.cm.jet`` * ``norm=plt.normalize(0, 1)``""" import matplotlib.pyplot as plt overlap = abs(calcOverlap(modes_y, modes_x)) if overlap.ndim == 0: overlap = np.array([[overlap]]) elif overlap.ndim == 1: overlap = overlap.reshape((modes_y.numModes(), modes_x.numModes())) cmap = kwargs.pop('cmap', plt.cm.jet) norm = kwargs.pop('norm', plt.normalize(0, 1)) show = (plt.pcolor(overlap, cmap=cmap, norm=norm, **kwargs), plt.colorbar()) x_range = np.arange(1, modes_x.numModes() + 1) plt.xticks(x_range-0.5, x_range) plt.xlabel(str(modes_x)) y_range = np.arange(1, modes_y.numModes() + 1) plt.yticks(y_range-0.5, y_range) plt.ylabel(str(modes_y)) plt.axis([0, modes_x.numModes(), 0, modes_y.numModes()]) if SETTINGS['auto_show']: showFigure() return show
def showMode(mode, *args, **kwargs): """Show mode array using :func:`~matplotlib.pyplot.plot`.""" import matplotlib.pyplot as plt show_hinge = kwargs.pop('hinge', True) show_zero = kwargs.pop('zero', False) if not isinstance(mode, Mode): raise TypeError('mode must be a Mode instance, ' 'not {0}'.format(type(mode))) if mode.is3d(): a3d = mode.getArrayNx3() show = plt.plot(a3d[:, 0], *args, label='x-component', **kwargs) plt.plot(a3d[:, 1], *args, label='y-component', **kwargs) plt.plot(a3d[:, 2], *args, label='z-component', **kwargs) else: a1d = mode._getArray() show = plt.plot(a1d, *args, **kwargs) if show_hinge: hinges = mode.getHinges() if hinges is not None: plt.plot(hinges, a1d[hinges], 'r*') plt.title(str(mode)) plt.xlabel('Indices') if show_zero: plt.plot(plt.xlim(), (0, 0), 'r--') if SETTINGS['auto_show']: showFigure() return show
def showNormedSqFlucts(modes, *args, **kwargs): """Show normalized square fluctuations via :func:`~matplotlib.pyplot.plot`. """ import matplotlib.pyplot as plt sqf = calcSqFlucts(modes) args = list(args) modesarg = [] i = 0 while i < len(args): if isinstance(args[i], (VectorBase, ModeSet, NMA)): modesarg.append(args.pop(i)) else: i += 1 show = [plt.plot(sqf/(sqf**2).sum()**0.5, *args, label='{0}'.format(str(modes)), **kwargs)] plt.xlabel('Indices') plt.ylabel('Square fluctuations') for modes in modesarg: sqf = calcSqFlucts(modes) show.append(plt.plot(sqf/(sqf**2).sum()**0.5, *args, label='{0}'.format(str(modes)), **kwargs)) if SETTINGS['auto_show']: showFigure() return show
def showScaledSqFlucts(modes, *args, **kwargs): """Show scaled square fluctuations using :func:`~matplotlib.pyplot.plot`. Modes or mode sets given as additional arguments will be scaled to have the same mean squared fluctuations as *modes*.""" import matplotlib.pyplot as plt sqf = calcSqFlucts(modes) mean = sqf.mean() args = list(args) modesarg = [] i = 0 while i < len(args): if isinstance(args[i], (VectorBase, ModeSet, NMA)): modesarg.append(args.pop(i)) else: i += 1 show = [plt.plot(sqf, *args, label=str(modes), **kwargs)] plt.xlabel('Indices') plt.ylabel('Square fluctuations') for modes in modesarg: sqf = calcSqFlucts(modes) scalar = mean / sqf.mean() show.append( plt.plot(sqf * scalar, *args, label='{0} (x{1:.2f})'.format(str(modes), scalar), **kwargs)) if SETTINGS['auto_show']: showFigure() return show
def showOverlap(mode, modes, *args, **kwargs): """Show overlap :func:`~matplotlib.pyplot.bar`. :arg mode: a single mode/vector :type mode: :class:`.Mode`, :class:`.Vector` :arg modes: multiple modes :type modes: :class:`.ModeSet`, :class:`.ANM`, :class:`.GNM`, :class:`.PCA` """ import matplotlib.pyplot as plt if not isinstance(mode, (Mode, Vector)): raise TypeError('mode must be Mode or Vector, not {0}' .format(type(mode))) if not isinstance(modes, (NMA, ModeSet)): raise TypeError('modes must be NMA or ModeSet, not {0}' .format(type(modes))) overlap = abs(calcOverlap(mode, modes)) if isinstance(modes, NMA): arange = np.arange(0.5, len(modes)+0.5) else: arange = modes.getIndices() + 0.5 show = plt.bar(arange, overlap, *args, **kwargs) plt.title('Overlap with {0}'.format(str(mode))) plt.xlabel('{0} mode index'.format(modes)) plt.ylabel('Overlap') if SETTINGS['auto_show']: showFigure() return show
def showCumulOverlap(mode, modes, *args, **kwargs): """Show cumulative overlap using :func:`~matplotlib.pyplot.plot`. :type mode: :class:`.Mode`, :class:`.Vector` :arg modes: multiple modes :type modes: :class:`.ModeSet`, :class:`.ANM`, :class:`.GNM`, :class:`.PCA` """ import matplotlib.pyplot as plt if not isinstance(mode, (Mode, Vector)): raise TypeError('mode must be NMA, ModeSet, Mode or Vector, not {0}' .format(type(mode))) if not isinstance(modes, (NMA, ModeSet)): raise TypeError('modes must be NMA, ModeSet, or Mode, not {0}' .format(type(modes))) cumov = (calcOverlap(mode, modes) ** 2).cumsum() ** 0.5 if isinstance(modes, NMA): arange = np.arange(0.5, len(modes)+0.5) else: arange = modes.getIndices() + 0.5 show = plt.plot(arange, cumov, *args, **kwargs) plt.title('Cumulative overlap with {0}'.format(str(mode))) plt.xlabel('{0} mode index'.format(modes)) plt.ylabel('Cumulative overlap') plt.axis((arange[0]-0.5, arange[-1]+0.5, 0, 1)) if SETTINGS['auto_show']: showFigure() return show
def showMechStiff(model, coords, *args, **kwargs): """Show mechanical stiffness matrix using :func:`~matplotlib.pyplot.imshow`. By default, *origin=lower* keyword arguments are passed to this function, but user can overwrite these parameters.""" import math import matplotlib import matplotlib.pyplot as plt arange = np.arange(model.numAtoms()) model.buildMechStiff(coords) if not 'origin' in kwargs: kwargs['origin'] = 'lower' if 'jet_r' in kwargs: import matplotlib.cm as plt kwargs['jet_r'] = 'cmap=cm.jet_r' MechStiff = model.getStiffness() matplotlib.rcParams['font.size'] = '14' fig = plt.figure(num=None, figsize=(10,8), dpi=100, facecolor='w') show = plt.imshow(MechStiff, *args, **kwargs), plt.colorbar() plt.clim(math.floor(np.min(MechStiff[np.nonzero(MechStiff)])), \ round(np.amax(MechStiff),1)) #plt.title('Mechanical Stiffness Matrix')# for {0}'.format(str(model))) plt.xlabel('Indices', fontsize='16') plt.ylabel('Indices', fontsize='16') if SETTINGS['auto_show']: showFigure() return show
def showCumulOverlap(mode, modes, *args, **kwargs): """Show cumulative overlap using :func:`~matplotlib.pyplot.plot`. :type mode: :class:`.Mode`, :class:`.Vector` :arg modes: multiple modes :type modes: :class:`.ModeSet`, :class:`.ANM`, :class:`.GNM`, :class:`.PCA` """ import matplotlib.pyplot as plt if not isinstance(mode, (Mode, Vector)): raise TypeError( 'mode must be NMA, ModeSet, Mode or Vector, not {0}'.format( type(mode))) if not isinstance(modes, (NMA, ModeSet)): raise TypeError('modes must be NMA, ModeSet, or Mode, not {0}'.format( type(modes))) cumov = (calcOverlap(mode, modes)**2).cumsum()**0.5 if isinstance(modes, NMA): arange = np.arange(0.5, len(modes) + 0.5) else: arange = modes.getIndices() + 0.5 show = plt.plot(arange, cumov, *args, **kwargs) plt.title('Cumulative overlap with {0}'.format(str(mode))) plt.xlabel('{0} mode index'.format(modes)) plt.ylabel('Cumulative overlap') plt.axis((arange[0] - 0.5, arange[-1] + 0.5, 0, 1)) if SETTINGS['auto_show']: showFigure() return show
def showOverlap(mode, modes, *args, **kwargs): """Show overlap :func:`~matplotlib.pyplot.bar`. :arg mode: a single mode/vector :type mode: :class:`.Mode`, :class:`.Vector` :arg modes: multiple modes :type modes: :class:`.ModeSet`, :class:`.ANM`, :class:`.GNM`, :class:`.PCA` """ import matplotlib.pyplot as plt if not isinstance(mode, (Mode, Vector)): raise TypeError('mode must be Mode or Vector, not {0}'.format( type(mode))) if not isinstance(modes, (NMA, ModeSet)): raise TypeError('modes must be NMA or ModeSet, not {0}'.format( type(modes))) overlap = abs(calcOverlap(mode, modes)) if isinstance(modes, NMA): arange = np.arange(0.5, len(modes) + 0.5) else: arange = modes.getIndices() + 0.5 show = plt.bar(arange, overlap, *args, **kwargs) plt.title('Overlap with {0}'.format(str(mode))) plt.xlabel('{0} mode index'.format(modes)) plt.ylabel('Overlap') if SETTINGS['auto_show']: showFigure() return show
def showSignatureVariances(mode_ensemble, **kwargs): """ Show the distribution of signature variances using :func:`~matplotlib.pyplot.hist`. """ from matplotlib.pyplot import figure, hist, annotate, legend, xlabel, ylabel from matplotlib.figure import Figure fig = kwargs.pop('figure', None) if isinstance(fig, Figure): fig_num = fig.number elif fig is None or isinstance(fig, (int, str)): fig_num = fig else: raise TypeError('figure can be either an instance of matplotlib.figure.Figure ' 'or a figure number.') if SETTINGS['auto_show']: figure(fig_num) elif fig_num is not None: figure(fig_num) fract = kwargs.pop('fraction', True) show_legend = kwargs.pop('legend', True) if fract: sig = calcSignatureFractVariance(mode_ensemble) else: sig = mode_ensemble.getVariances() W = sig.getArray()[:, ::-1] # reversed to accommodate with matplotlib.pyplot.hist weights = np.ones_like(W)/float(len(W)) indices = mode_ensemble.getIndices()[0] legends = ['mode %d'%(i+1) for i in indices][::-1] bins = kwargs.pop('bins', 'auto') if bins == 'auto': _, bins = np.histogram(W.flatten(), bins='auto') elif np.isscalar(bins) and isinstance(bins, (int, np.integer)): step = (W.max() - W.min())/bins bins = np.arange(W.min(), W.max(), step) histtype = kwargs.pop('histtype', 'stepfilled') label = kwargs.pop('label', legends) weights = kwargs.pop('weights', weights) n, bins, patches = hist(W, bins=bins, weights=weights, histtype=histtype, label=label, **kwargs) if show_legend: legend() xlabel('Variance') ylabel('Probability') if SETTINGS['auto_show']: showFigure() return n, bins, patches
def showMeanMechStiff(model, coords, header, chain='A', *args, **kwargs): """Show mean value of effective spring constant with secondary structure taken from MechStiff. Header is needed to obatin secondary structure range. Using ``'jet_r'`` as argument color map will be reverse (similar to VMD program coding). """ meanStiff = np.array([np.mean(model.getStiffness(), axis=0)]) import matplotlib import matplotlib.pyplot as plt import matplotlib.patches as patches fig=plt.figure(figsize=[18,6], facecolor='w', dpi=100) if 'jet_r' in kwargs: import matplotlib.cm as plt kwargs['jet_r'] = 'cmap=cm.jet_r' if 'nearest' in kwargs: kwargs['nearest'] = 'interpolation=nearest' with plt.style.context('fivethirtyeight'): ax = fig.add_subplot(111) matplotlib.rcParams['font.size'] = '24' plt.plot(np.arange(len(meanStiff[0]))+coords.getResnums()[0],meanStiff[0], 'k-', linewidth = 3) plt.xlim(coords.getResnums()[0], coords.getResnums()[-1]) ax_top=round(np.max(meanStiff[0])+((np.max(meanStiff[0])-np.min(meanStiff[0]))/3)) ax_bottom=np.floor(np.min(meanStiff[0])) LOGGER.info('The range of mean effective force constant is: {0} to {1}.' .format(min(meanStiff[0]), max(meanStiff[0]))) plt.ylim(ax_bottom,ax_top) plt.xlabel('residue', fontsize = '22') plt.ylabel('mean $\kappa$ [a.u.]', fontsize = '22') ax = fig.add_subplot(411, aspect='equal') plt.imshow(meanStiff, *args, **kwargs) header_ss = header['sheet_range'] + header['helix_range'] for i in range(len(header_ss)): if header_ss[i][1] == chain: beg = int(header_ss[i][-2])-coords.getResnums()[0] end = int(header_ss[i][-1])-coords.getResnums()[0] add_beg = end - beg if header_ss[i][0] == 'H': ax.add_patch(patches.Rectangle((beg-1,-0.7),add_beg,\ 1.4,fill=False, linestyle='solid',edgecolor='#b22683', linewidth=2)) elif header_ss[i][0] == 'E': if header_ss[i][2] == -1: ax.add_patch(patches.Arrow(beg-1,0,add_beg,0,width=4.65, \ fill=False, linestyle='solid',edgecolor='black', linewidth=2)) else: ax.add_patch(patches.Arrow(end-1,0,add_beg*(-1),0,width=4.65, \ fill=False, linestyle='solid',edgecolor='black', linewidth=2)) plt.axis('off') ax.set_ylim(-1.7,1.7) if SETTINGS['auto_show']: showFigure() return plt.show
def showSqFlucts(modes, *args, **kwargs): """Show square fluctuations using :func:`~matplotlib.pyplot.plot`. See also :func:`.calcSqFlucts`.""" import matplotlib.pyplot as plt sqf = calcSqFlucts(modes) if not 'label' in kwargs: kwargs['label'] = str(modes) show = plt.plot(sqf, *args, **kwargs) plt.xlabel('Indices') plt.ylabel('Square fluctuations') plt.title(str(modes)) if SETTINGS['auto_show']: showFigure() return show
def showContactMap(enm, *args, **kwargs): """Show Kirchhoff matrix using :func:`~matplotlib.pyplot.spy`.""" import matplotlib.pyplot as plt if not isinstance(enm, GNMBase): raise TypeError('model argument must be an ENM instance') kirchhoff = enm.getKirchhoff() if kirchhoff is None: LOGGER.warning('kirchhoff matrix is not set') return None show = plt.spy(kirchhoff, *args, **kwargs) plt.title('{0} contact map'.format(enm.getTitle())) plt.xlabel('Residue index') plt.ylabel('Residue index') if SETTINGS['auto_show']: showFigure() return show
def showDiffMatrix(matrix1, matrix2, *args, **kwargs): """Show the difference between two cross-correlation matrices from different models. For given *matrix1* and *matrix2* show the difference between them in the form of (matrix2 - matrix1) and plot the difference matrix using :func:`~matplotlib.pyplot.imshow`. When :class:`.NMA` models are passed instead of matrices, the functions could call :func:`.calcCrossCorr` function to calculate the matrices for given modes. To display the absolute values in the difference matrix, user could set *abs* keyword argument **True**. By default, *origin=lower* and *interpolation=bilinear* keyword arguments are passed to this function, but user can overwrite these parameters. """ import matplotlib.pyplot as plt try: dim1, shape1 = matrix1.ndim, matrix1.shape except AttributeError: matrix1 = calcCrossCorr(matrix1) dim1, shape1 = matrix1.ndim, matrix1.shape try: dim2, shape2 = matrix2.ndim, matrix2.shape except AttributeError: matrix2 = calcCrossCorr(matrix2) dim2, shape2 = matrix2.ndim, matrix2.shape if not ((dim1 == dim2 == 2) and (shape1 == shape2)): raise ValueError("Matrices must have same square shape.") if shape1[0] * shape1[1] == 0: raise ValueError("There are no data in matrices.") diff = matrix2 - matrix1 if not "interpolation" in kwargs: kwargs["interpolation"] = "bilinear" if not "origin" in kwargs: kwargs["origin"] = "lower" if kwargs.pop("abs", False): diff = np.abs(diff) show = plt.imshow(diff, *args, **kwargs), plt.colorbar() plt.axis([-0.5, shape1[1] - 0.5, -0.5, shape1[0] - 0.5]) plt.title("Difference Matrix") if SETTINGS["auto_show"]: showFigure() plt.xlabel("Indices") plt.ylabel("Indices") return show
def showDiffMatrix(matrix1, matrix2, *args, **kwargs): """Show the difference between two cross-correlation matrices from different models. For given *matrix1* and *matrix2* show the difference between them in the form of (matrix2 - matrix1) and plot the difference matrix using :func:`~matplotlib.pyplot.imshow`. When :class:`.NMA` models are passed instead of matrices, the functions could call :func:`.calcCrossCorr` function to calculate the matrices for given modes. To display the absolute values in the difference matrix, user could set *abs* keyword argument **True**. By default, *origin=lower* and *interpolation=bilinear* keyword arguments are passed to this function, but user can overwrite these parameters. """ import matplotlib.pyplot as plt try: dim1, shape1 = matrix1.ndim, matrix1.shape except AttributeError: matrix1 = calcCrossCorr(matrix1) dim1, shape1 = matrix1.ndim, matrix1.shape try: dim2, shape2 = matrix2.ndim, matrix2.shape except AttributeError: matrix2 = calcCrossCorr(matrix2) dim2, shape2 = matrix2.ndim, matrix2.shape if (not ((dim1 == dim2 == 2) and (shape1 == shape2))): raise ValueError('Matrices must have same square shape.') if shape1[0] * shape1[1] == 0: raise ValueError('There are no data in matrices.') diff = matrix2 - matrix1 if not 'interpolation' in kwargs: kwargs['interpolation'] = 'bilinear' if not 'origin' in kwargs: kwargs['origin'] = 'lower' if kwargs.pop('abs', False): diff = np.abs(diff) show = plt.imshow(diff, *args, **kwargs), plt.colorbar() plt.axis([-.5, shape1[1] - .5, -.5, shape1[0] - .5]) plt.title('Difference Matrix') if SETTINGS['auto_show']: showFigure() plt.xlabel('Indices') plt.ylabel('Indices') return show
def showDomains(domains, linespec='-', **kwargs): """A convenient function that can be used to visualize Hi-C structural domains. *kwargs* will be passed to :func:`matplotlib.pyplot.plot`. :arg domains: a 2D array of Hi-C domains, such as [[start1, end1], [start2, end2], ...]. :type domains: :class:`numpy.ndarray` """ domains = np.array(domains) shape = domains.shape if len(shape) < 2: # convert to domain list if labels are provided indicators = np.diff(domains) indicators = np.append(1., indicators) indicators[-1] = 1 sites = np.where(indicators != 0)[0] starts = sites[:-1] ends = sites[1:] domains = np.array([starts, ends]).T from matplotlib.pyplot import figure, plot x = [] y = [] lwd = kwargs.pop('linewidth', 1) lwd = kwargs.pop('lw', lwd) linewidth = np.abs(lwd) for i in range(len(domains)): domain = domains[i] start = domain[0] end = domain[1] if lwd > 0: x.extend([start, end, end]) y.extend([start, start, end]) else: x.extend([start, start, end]) y.extend([start, end, end]) plt = plot(x, y, linespec, linewidth=linewidth, **kwargs) if SETTINGS['auto_show']: showFigure() return plt
def showMode(mode, *args, **kwargs): """Show mode array using :func:`~matplotlib.pyplot.plot`.""" import matplotlib.pyplot as plt if not isinstance(mode, Mode): raise TypeError('mode must be a Mode instance, ' 'not {0}'.format(type(mode))) if mode.is3d(): a3d = mode.getArrayNx3() show = plt.plot(a3d[:, 0], *args, label='x-component', **kwargs) plt.plot(a3d[:, 1], *args, label='y-component', **kwargs) plt.plot(a3d[:, 2], *args, label='z-component', **kwargs) else: show = plt.plot(mode._getArray(), *args, **kwargs) plt.title(str(mode)) plt.xlabel('Indices') if SETTINGS['auto_show']: showFigure() return show
def showSqFlucts(modes, *args, **kwargs): """Show square fluctuations using :func:`~matplotlib.pyplot.plot`. See also :func:`.calcSqFlucts`.""" import matplotlib.pyplot as plt show_hinge = kwargs.pop('hinge', True) sqf = calcSqFlucts(modes) if not 'label' in kwargs: kwargs['label'] = str(modes) show = plt.plot(sqf, *args, **kwargs) plt.xlabel('Indices') plt.ylabel('Square fluctuations') plt.title(str(modes)) if show_hinge and not modes.is3d(): hinges = modes.getHinges() if hinges is not None: plt.plot(hinges, sqf[hinges], 'r*') if SETTINGS['auto_show']: showFigure() return show
def showOccupancies(pdbensemble, *args, **kwargs): """Show occupancies for the PDB ensemble using :func:`~matplotlib.pyplot. plot`. Occupancies are calculated using :meth:`calcOccupancies`.""" import matplotlib.pyplot as plt if not isinstance(pdbensemble, PDBEnsemble): raise TypeError('pdbensemble must be a PDBEnsemble instance') weights = calcOccupancies(pdbensemble) if weights is None: return None show = plt.plot(weights, *args, **kwargs) axis = list(plt.axis()) axis[2] = 0 axis[3] += 1 plt.axis(axis) plt.xlabel('Atom index') plt.ylabel('Sum of weights') if SETTINGS['auto_show']: showFigure() return show
def showDomains(domains, linespec='r-', **kwargs): """A convenient function that can be used to visualize Hi-C structural domains. *kwargs* will be passed to :func:`matplotlib.pyplot.plot`. :arg domains: a 2D array of Hi-C domains, such as [[start1, end1], [start2, end2], ...]. :type domains: :class:`numpy.ndarray` """ domains = np.array(domains) shape = domains.shape if len(shape) < 2: # convert to domain list if labels are provided indicators = np.diff(domains) indicators = np.append(1., indicators) indicators[-1] = 1 sites = np.where(indicators != 0)[0] starts = sites[:-1] ends = sites[1:] domains = np.array([starts, ends]).T from matplotlib.pyplot import figure, plot x = []; y = [] lwd = kwargs.pop('linewidth', 1) linewidth = np.abs(lwd) for i in range(len(domains)): domain = domains[i] start = domain[0]; end = domain[1] if lwd > 0: x.extend([start, end, end]) y.extend([start, start, end]) else: x.extend([start, start, end]) y.extend([start, end, end]) plt = plot(x, y, linespec, linewidth=linewidth, **kwargs) if SETTINGS['auto_show']: showFigure() return plt
def showMap(map, spec='', **kwargs): """A convenient function that can be used to visualize Hi-C contact map. *kwargs* will be passed to :func:`matplotlib.pyplot.imshow`. :arg map: a Hi-C contact map. :type map: :class:`numpy.ndarray` :arg spec: a string specifies how to preprocess the matrix. Blank for no preprocessing, 'p' for showing only data from *p*-th to *100-p*-th percentile. '_' is to suppress creating a new figure and paint to the current one instead. The letter specifications can be applied sequentially, e.g. 'p_'. :type spec: str :arg p: specifies the percentile threshold. :type p: double """ assert isinstance(map, np.ndarray), 'map must be a numpy.ndarray.' from matplotlib.pyplot import figure, imshow if not '_' in spec: figure() if 'p' in spec: p = kwargs.pop('p', 5) lp = kwargs.pop('lp', p) hp = kwargs.pop('hp', 100 - p) vmin = np.percentile(map, lp) vmax = np.percentile(map, hp) else: vmin = vmax = None im = imshow(map, vmin=vmin, vmax=vmax, **kwargs) if SETTINGS['auto_show']: showFigure() return im
def showFractVars(modes, *args, **kwargs): """Show fraction of variances using :func:`~matplotlib.pyplot.bar`. Note that mode indices are incremented by 1.""" import matplotlib.pyplot as plt if not isinstance(modes, (ModeSet, NMA)): raise TypeError('modes must be NMA, or ModeSet, not {0}'.format( type(modes))) fracts = calcFractVariance(modes) fracts = [(int(mode), fract) for mode, fract in zip(modes, fracts)] fracts = np.array(fracts) show = plt.bar(fracts[:, 0] + 0.5, fracts[:, 1], *args, **kwargs) axis = list(plt.axis()) axis[0] = 0.5 axis[2] = 0 axis[3] = 1 plt.axis(axis) plt.xlabel('Mode index') plt.ylabel('Fraction of variance') if SETTINGS['auto_show']: showFigure() return show
def showFractVars(modes, *args, **kwargs): """Show fraction of variances using :func:`~matplotlib.pyplot.bar`. Note that mode indices are incremented by 1.""" import matplotlib.pyplot as plt if not isinstance(modes, (ModeSet, NMA)): raise TypeError('modes must be NMA, or ModeSet, not {0}' .format(type(modes))) fracts = calcFractVariance(modes) fracts = [(int(mode), fract) for mode, fract in zip(modes, fracts)] fracts = np.array(fracts) show = plt.bar(fracts[:,0]+0.5, fracts[:,1], *args, **kwargs) axis = list(plt.axis()) axis[0] = 0.5 axis[2] = 0 axis[3] = 1 plt.axis(axis) plt.xlabel('Mode index') plt.ylabel('Fraction of variance') if SETTINGS['auto_show']: showFigure() return show
def showCrossCorr(modes, *args, **kwargs): """Show cross-correlations using :func:`~matplotlib.pyplot.imshow`. By default, *origin=lower* and *interpolation=bilinear* keyword arguments are passed to this function, but user can overwrite these parameters. See also :func:`.calcCrossCorr`.""" import matplotlib.pyplot as plt arange = np.arange(modes.numAtoms()) cross_correlations = np.zeros((arange[-1]+2, arange[-1]+2)) cross_correlations[arange[0]+1:, arange[0]+1:] = calcCrossCorr(modes) if not 'interpolation' in kwargs: kwargs['interpolation'] = 'bilinear' if not 'origin' in kwargs: kwargs['origin'] = 'lower' show = plt.imshow(cross_correlations, *args, **kwargs), plt.colorbar() plt.axis([arange[0]+0.5, arange[-1]+1.5, arange[0]+0.5, arange[-1]+1.5]) plt.title('Cross-correlations for {0}'.format(str(modes))) plt.xlabel('Indices') plt.ylabel('Indices') if SETTINGS['auto_show']: showFigure() return show
def showCrossCorr(modes, *args, **kwargs): """Show cross-correlations using :func:`~matplotlib.pyplot.imshow`. By default, *origin=lower* and *interpolation=bilinear* keyword arguments are passed to this function, but user can overwrite these parameters. See also :func:`.calcCrossCorr`.""" import matplotlib.pyplot as plt arange = np.arange(modes.numAtoms()) cross_correlations = np.zeros((arange[-1] + 2, arange[-1] + 2)) cross_correlations[arange[0] + 1:, arange[0] + 1:] = calcCrossCorr(modes) if not 'interpolation' in kwargs: kwargs['interpolation'] = 'bilinear' if not 'origin' in kwargs: kwargs['origin'] = 'lower' show = plt.imshow(cross_correlations, *args, **kwargs), plt.colorbar() plt.axis( [arange[0] + 0.5, arange[-1] + 1.5, arange[0] + 0.5, arange[-1] + 1.5]) plt.title('Cross-correlations for {0}'.format(str(modes))) plt.xlabel('Indices') plt.ylabel('Indices') if SETTINGS['auto_show']: showFigure() return show
def showLinkage(V, **kwargs): """Shows the dendrogram of hierarchical clustering on *V*. See :func:`scipy.cluster.hierarchy.dendrogram` for details. :arg V: row-normalized eigenvectors for the purpose of clustering. :type V: :class:`numpy.ndarray` """ V, _ = _getEigvecs(V, row_norm=True, remove_zero_rows=True) try: from scipy.cluster.hierarchy import linkage, dendrogram except ImportError: raise ImportError('Use of this function (showLinkage) requires the ' 'installation of scipy.') method = kwargs.pop('method', 'single') metric = kwargs.pop('metric', 'euclidean') Z = linkage(V, method=method, metric=metric) no_labels = kwargs.pop('no_labels', True) dendrogram(Z, no_labels=no_labels, **kwargs) if SETTINGS['auto_show']: showFigure() return Z
def showProtein(*atoms, **kwargs): """Show protein representation using :meth:`~mpl_toolkits.mplot3d.Axes3D`. This function is designed for generating a quick view of the contents of a :class:`~.AtomGroup` or :class:`~.Selection`. Protein atoms matching ``"calpha"`` selection are displayed using solid lines by picking a random and unique color per chain. Line with can be adjusted using *lw* argument, e.g. ``lw=12``. Default width is 4. Chain colors can be overwritten using chain identifier as in ``A='green'``. Water molecule oxygen atoms are represented by red colored circles. Color can be changed using *water* keyword argument, e.g. ``water='aqua'``. Water marker and size can be changed using *wmarker* and *wsize* keywords, defaults values are ``wmarker='.', wsize=6``. Hetero atoms matching ``"hetero and noh"`` selection are represented by circles and unique colors are picked at random on a per residue basis. Colors can be customized using residue name as in ``NAH='purple'``. Note that this will color all distinct residues with the same name in the same color. Hetero atom marker and size can be changed using *hmarker* and *hsize* keywords, default values are ``hmarker='o', hsize=6``. ProDy will set the size of axis so the representation is not distorted when the shape of figure window is close to a square. Colors are picked at random, except for water oxygens which will always be colored red.""" alist = atoms for atoms in alist: if not isinstance(atoms, Atomic): raise TypeError('atoms must be an Atomic instance') import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D cf = plt.gcf() show = None for child in cf.get_children(): if isinstance(child, Axes3D): show = child break if show is None: show = Axes3D(cf) from matplotlib import colors cnames = dict(colors.cnames) wcolor = kwargs.get('water', 'red').lower() avoid = np.array(colors.hex2color(cnames.pop(wcolor, cnames.pop('red')))) for cn, val in cnames.items(): # PY3K: OK clr = np.array(colors.hex2color(val)) if clr.sum() > 2.4: cnames.pop(cn) elif np.abs(avoid - clr).sum() <= 0.6: cnames.pop(cn) cnames = list(cnames) import random random.shuffle(cnames) min_ = list() max_ = list() for atoms in alist: if isinstance(atoms, AtomGroup): title = atoms.getTitle() else: title = atoms.getAtomGroup().getTitle() calpha = atoms.select('calpha') if calpha: for ch in HierView(calpha, chain=True): xyz = ch._getCoords() chid = ch.getChid() show.plot(xyz[:, 0], xyz[:, 1], xyz[:, 2], label=title + '_' + chid, color=kwargs.get(chid, cnames.pop()).lower(), lw=kwargs.get('lw', 4)) water = atoms.select('water and noh') if water: xyz = atoms.select('water')._getCoords() show.plot(xyz[:, 0], xyz[:, 1], xyz[:, 2], label=title + '_water', color=wcolor, ls='None', marker=kwargs.get('wmarker', '.'), ms=kwargs.get('wsize', 6)) hetero = atoms.select('not protein and not nucleic and not water') if hetero: for res in HierView(hetero).iterResidues(): xyz = res._getCoords() resname = res.getResname() resnum = str(res.getResnum()) chid = res.getChid() show.plot(xyz[:, 0], xyz[:, 1], xyz[:, 2], ls='None', color=kwargs.get(resname, cnames.pop()).lower(), label=title + '_' + chid + '_' + resname + resnum, marker=kwargs.get('hmarker', 'o'), ms=kwargs.get('hsize', 6)) xyz = atoms._getCoords() min_.append(xyz.min(0)) max_.append(xyz.max(0)) show.set_xlabel('x') show.set_ylabel('y') show.set_zlabel('z') min_ = np.array(min_).min(0) max_ = np.array(max_).max(0) center = (max_ + min_) / 2 half = (max_ - min_).max() / 2 show.set_xlim3d(center[0]-half, center[0]+half) show.set_ylim3d(center[1]-half, center[1]+half) show.set_zlim3d(center[2]-half, center[2]+half) if kwargs.get('legend', False): show.legend(prop={'size': 10}) if SETTINGS['auto_show']: showFigure() return show
def showEllipsoid(modes, onto=None, n_std=2, scale=1., *args, **kwargs): """Show an ellipsoid using :meth:`~mpl_toolkits.mplot3d.Axes3D .plot_wireframe`. Ellipsoid volume gives an analytical view of the conformational space that given modes describe. :arg modes: 3 modes for which ellipsoid will be drawn. :type modes: :class:`.ModeSet`, :class:`.PCA`, :class:`.ANM`, :class:`.NMA` :arg onto: 3 modes onto which ellipsoid will be projected. :type modes: :class:`.ModeSet`, :class:`.PCA`, :class:`.ANM`, :class:`.NMA` :arg n_std: Number of standard deviations to scale the ellipsoid. :type n_std: float :arg scale: Used for scaling the volume of ellipsoid. This can be obtained from :func:`.sampleModes`. :type scale: float""" import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D if not isinstance(modes, (NMA, ModeSet)): raise TypeError('modes must be a NMA or ModeSet instance, ' 'not {0}'.format(type(modes))) if not modes.is3d(): raise ValueError('modes must be from a 3-dimensional model') if len(modes) != 3: raise ValueError('length of modes is not equal to 3') if onto is not None: if not isinstance(onto, (NMA, ModeSet)): raise TypeError('onto must be a NMA or ModeSet instance, ' 'not {0}'.format(type(onto))) if not onto.is3d(): raise ValueError('onto must be from a 3-dimensional model') if len(onto) != 3: raise ValueError('length of onto is not equal to 3') if onto.numAtoms() != modes.numAtoms(): raise ValueError('modes and onto must have same number of atoms') u = np.linspace(0, 2 * np.pi, 100) v = np.linspace(0, np.pi, 100) var = modes.getVariances() #randn = np.random.standard_normal((1000, 3)) #coef = ((randn ** 2 * var).sum(1) ** 0.5).mean() #scale=float(n_std)*modes.numAtoms()**.5 * float(rmsd) / coef * var **.5 scale = float(n_std) * scale * var**0.5 #scale=float(n_std)*modes.numAtoms()**.5*float(rmsd)/var.sum()**.5*var**.5 x = scale[0] * np.outer(np.cos(u), np.sin(v)) y = scale[1] * np.outer(np.sin(u), np.sin(v)) z = scale[2] * np.outer(np.ones(np.size(u)), np.cos(v)) if onto is not None: change_of_basis = np.dot(modes._getArray().T, onto._getArray()) xyz = np.array([x.flatten(), y.flatten(), z.flatten()]) xyz = np.dot(xyz.T, change_of_basis) x = xyz[:, 0].reshape((100, 100)) y = xyz[:, 1].reshape((100, 100)) z = xyz[:, 2].reshape((100, 100)) cf = plt.gcf() show = None for child in cf.get_children(): if isinstance(child, Axes3D): show = child break if show is None: show = Axes3D(cf) show.plot_wireframe(x, y, z, rstride=6, cstride=6, *args, **kwargs) if onto is not None: onto = list(onto) show.set_xlabel('Mode {0} coordinate'.format(int(onto[0]) + 1)) show.set_ylabel('Mode {0} coordinate'.format(int(onto[1]) + 1)) show.set_zlabel('Mode {0} coordinate'.format(int(onto[2]) + 1)) else: modes = list(modes) show.set_xlabel('Mode {0} coordinate'.format(int(modes[0]) + 1)) show.set_ylabel('Mode {0} coordinate'.format(int(modes[1]) + 1)) show.set_zlabel('Mode {0} coordinate'.format(int(modes[2]) + 1)) if SETTINGS['auto_show']: showFigure() return show
def showProtein(*atoms, **kwargs): """Show protein representation using :meth:`~mpl_toolkits.mplot3d.Axes3D`. This function is designed for generating a quick view of the contents of a :class:`~.AtomGroup` or :class:`~.Selection`. Protein atoms matching ``"calpha"`` selection are displayed using solid lines by picking a random and unique color per chain. Line with can be adjusted using *lw* argument, e.g. ``lw=12``. Default width is 4. Chain colors can be overwritten using chain identifier as in ``A='green'``. Water molecule oxygen atoms are represented by red colored circles. Color can be changed using *water* keyword argument, e.g. ``water='aqua'``. Water marker and size can be changed using *wmarker* and *wsize* keywords, defaults values are ``wmarker='.', wsize=6``. Hetero atoms matching ``"hetero and noh"`` selection are represented by circles and unique colors are picked at random on a per residue basis. Colors can be customized using residue name as in ``NAH='purple'``. Note that this will color all distinct residues with the same name in the same color. Hetero atom marker and size can be changed using *hmarker* and *hsize* keywords, default values are ``hmarker='o', hsize=6``. ProDy will set the size of axis so the representation is not distorted when the shape of figure window is close to a square. Colors are picked at random, except for water oxygens which will always be colored red. *** Interactive 3D Rendering in Jupyter Notebook *** If py3Dmol has been imported then it will be used instead to display an interactive viewer. See :func:`view3D` """ from prody.dynamics.mode import Mode method = kwargs.pop('draw', None) modes = kwargs.get('mode', None) scale = kwargs.get('scale', 100) # modes need to be specifically a list or a tuple (cannot be an array) if modes is None: n_modes = 0 else: modes = wrapModes(modes) n_modes = len(modes) if method is None: import sys if 'py3Dmol' in sys.modules: method = 'py3Dmol' else: method = 'matplotlib' method = method.lower() alist = atoms for atoms in alist: if not isinstance(atoms, Atomic): raise TypeError('atoms must be an Atomic instance') if n_modes and n_modes != len(alist): raise RuntimeError('the number of proteins ({0}) does not match that of the modes ({1}).' .format(len(alist), n_modes)) if '3dmol' in method: mol = view3D(*alist, **kwargs) return mol else: import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D cf = plt.gcf() show = None for child in cf.get_children(): if isinstance(child, Axes3D): show = child break if show is None: show = Axes3D(cf) from matplotlib import colors cnames = dict(colors.cnames) wcolor = kwargs.get('water', 'red').lower() avoid = np.array(colors.hex2color(cnames.pop(wcolor, cnames.pop('red')))) for cn, val in cnames.copy().items(): # PY3K: OK clr = np.array(colors.hex2color(val)) if clr.sum() > 2.4: cnames.pop(cn) elif np.abs(avoid - clr).sum() <= 0.6: cnames.pop(cn) cnames = list(cnames) import random random.shuffle(cnames) cnames_copy = list(cnames) min_ = list() max_ = list() for i, atoms in enumerate(alist): if isinstance(atoms, AtomGroup): title = atoms.getTitle() else: title = atoms.getAtomGroup().getTitle() calpha = atoms.select('calpha') if calpha: partition = False mode = modes[i] if n_modes else None if mode is not None: is3d = False try: arr = mode.getArray() is3d = mode.is3d() n_nodes = mode.numAtoms() except AttributeError: arr = mode is3d = len(arr) == len(calpha)*3 n_nodes = len(arr)//3 if is3d else len(arr) if n_nodes != len(calpha): raise RuntimeError('size mismatch between the protein ({0} residues) and the mode ({1} nodes).' .format(len(calpha), n_nodes)) partition = not is3d if partition: xyz = calpha._getCoords() chids = calpha.getChids() rbody = [] last_sign = np.sign(arr[0]) last_chid = chids[0] rcolor = ['red', 'red', 'blue'] n = 1 for i,a in enumerate(arr): s = np.sign(a) ch = chids[i] if s == 0: s = last_sign if last_sign != s or i == len(arr)-1 or last_chid != ch: if last_chid == ch: rbody.append(i) show.plot(xyz[rbody, 0], xyz[rbody, 1], xyz[rbody, 2], label=title + '_regid%d'%n, color=rcolor[int(last_sign+1)], lw=kwargs.get('lw', 4)) rbody = [] n += 1 last_sign = s last_chid = ch rbody.append(i) else: for ch in HierView(calpha, chain=True): xyz = ch._getCoords() chid = ch.getChid() if len(cnames) == 0: cnames = list(cnames_copy) show.plot(xyz[:, 0], xyz[:, 1], xyz[:, 2], label=title + '_' + chid, color=kwargs.get(chid, cnames.pop()).lower(), lw=kwargs.get('lw', 4)) if mode is not None: from prody.utilities.drawtools import drawArrow3D XYZ = calpha._getCoords() arr = arr.reshape((n_nodes, 3)) XYZ2 = XYZ + arr * scale for i, xyz in enumerate(XYZ): xyz2 = XYZ2[i] mutation_scale = kwargs.pop('mutation_scale', 10) drawArrow3D(xyz, xyz2, mutation_scale=mutation_scale, **kwargs) water = atoms.select('water and noh') if water: xyz = atoms.select('water')._getCoords() show.plot(xyz[:, 0], xyz[:, 1], xyz[:, 2], label=title + '_water', color=wcolor, ls='None', marker=kwargs.get('wmarker', '.'), ms=kwargs.get('wsize', 6)) hetero = atoms.select('not protein and not nucleic and not water') if hetero: for res in HierView(hetero).iterResidues(): xyz = res._getCoords() resname = res.getResname() resnum = str(res.getResnum()) chid = res.getChid() if len(cnames) == 0: cnames = list(cnames_copy) show.plot(xyz[:, 0], xyz[:, 1], xyz[:, 2], ls='None', color=kwargs.get(resname, cnames.pop()).lower(), label=title + '_' + chid + '_' + resname + resnum, marker=kwargs.get('hmarker', 'o'), ms=kwargs.get('hsize', 6)) xyz = atoms._getCoords() min_.append(xyz.min(0)) max_.append(xyz.max(0)) show.set_xlabel('x') show.set_ylabel('y') show.set_zlabel('z') min_ = np.array(min_).min(0) max_ = np.array(max_).max(0) center = (max_ + min_) / 2 half = (max_ - min_).max() / 2 show.set_xlim3d(center[0]-half, center[0]+half) show.set_ylim3d(center[1]-half, center[1]+half) show.set_zlim3d(center[2]-half, center[2]+half) if kwargs.get('legend', False): show.legend(prop={'size': 10}) if SETTINGS['auto_show']: showFigure() return show
def showDomains(domains, linespec='-', **kwargs): """A convenient function that can be used to visualize Hi-C structural domains. *kwargs* will be passed to :func:`matplotlib.pyplot.plot`. :arg domains: a 2D array of Hi-C domains, such as [[start1, end1], [start2, end2], ...]. :type domains: :class:`numpy.ndarray` """ fill_ends = kwargs.pop('fill_ends', 'close') domains = np.array(domains) shape = domains.shape if len(shape) == 1: # convert to domain list if labels are provided indicators = np.diff(domains) length = len(domains) if fill_ends in ['open', 'close']: indicators = np.append(1., indicators) indicators[-1] = 1 elif fill_ends == 'skip': indicators = np.append(0., indicators) else: raise ValueError('invalid fill_ends mode: %s'%str(fill_ends)) sites = np.where(indicators != 0)[0] starts = sites[:-1] ends = sites[1:] domains = np.array([starts, ends]).T consecutive = True elif len(shape) == 2: if domains.dtype == bool: length = domains.shape[1] domains_ = [] for h in domains: start = None for i, b in enumerate(h): if b: if start is None: # start start = i else: if start is not None: # end domains_.append([start, i-1]) start = None if start is not None: domains_.append([start, i]) domains = np.array(domains_) else: length = domains.max() consecutive = False else: raise ValueError('domains must be either one or two dimensions') from matplotlib.pyplot import figure, plot a = []; b = [] lwd = kwargs.pop('linewidth', 1) lwd = kwargs.pop('lw', lwd) linewidth = np.abs(lwd) if fill_ends == 'open' and len(domains) == 1: domains = [] for i in range(len(domains)): domain = domains[i] start = domain[0]; end = domain[1] if fill_ends == 'open' and start == 0: a.extend([end, end]) b.extend([start, end]) elif fill_ends == 'open' and end == length-1: a.extend([start, end]) b.extend([start, start]) else: a.extend([start, end, end]) b.extend([start, start, end]) if not consecutive: a.append(np.nan) b.append(np.nan) if lwd > 0: x = a; y = b else: x = b; y = a plt = plot(x, y, linespec, linewidth=linewidth, **kwargs) if SETTINGS['auto_show']: showFigure() return plt
def showProjection(ensemble, modes, *args, **kwargs): """Show a projection of conformational deviations onto up to three normal modes from the same model. :arg ensemble: an ensemble, trajectory or a conformation for which deviation(s) will be projected, or a deformation vector :type ensemble: :class:`.Ensemble`, :class:`.Conformation`, :class:`.Vector`, :class:`.Trajectory` :arg modes: up to three normal modes :type modes: :class:`.Mode`, :class:`.ModeSet`, :class:`.NMA` :arg color: a color name or a list of color name, default is ``'blue'`` :type color: str, list :arg label: label or a list of labels :type label: str, list :arg marker: a marker or a list of markers, default is ``'o'`` :type marker: str, list :arg linestyle: line style, default is ``'None'`` :type linestyle: str :arg text: list of text labels, one for each conformation :type text: list :arg fontsize: font size for text labels :type fontsize: int The projected values are by default converted to RMSD. Pass ``rmsd=False`` to use projection itself. Matplotlib function used for plotting depends on the number of modes: * 1 mode: :func:`~matplotlib.pyplot.hist` * 2 modes: :func:`~matplotlib.pyplot.plot` * 3 modes: :meth:`~mpl_toolkits.mplot3d.Axes3D.plot`""" import matplotlib.pyplot as plt projection = calcProjection(ensemble, modes, kwargs.pop('rmsd', True)) if projection.ndim == 1 or projection.shape[1] == 1: show = plt.hist(projection.flatten(), *args, **kwargs) plt.xlabel('{0} coordinate'.format(str(modes))) plt.ylabel('Number of conformations') return show elif projection.shape[1] > 3: raise ValueError('Projection onto up to 3 modes can be shown. ' 'You have given {0} mode.'.format(len(modes))) num = projection.shape[0] markers = kwargs.pop('marker', 'o') if isinstance(markers, str) or markers is None: markers = [markers] * num elif isinstance(markers, list): if len(markers) != num: raise ValueError('length of marker must be {0}'.format(num)) else: raise TypeError('marker must be a string or a list') colors = kwargs.pop('color', 'blue') if isinstance(colors, str) or colors is None: colors = [colors] * num elif isinstance(colors, list): if len(colors) != num: raise ValueError('length of color must be {0}'.format(num)) else: raise TypeError('color must be a string or a list') labels = kwargs.pop('label', None) if isinstance(labels, str) or labels is None: labels = [labels] * num elif isinstance(labels, list): if len(labels) != num: raise ValueError('length of label must be {0}'.format(num)) elif labels is not None: raise TypeError('label must be a string or a list') kwargs['ls'] = kwargs.pop('linestyle', None) or kwargs.pop('ls', 'None') texts = kwargs.pop('text', None) if texts: if not isinstance(texts, list): raise TypeError('text must be a list') elif len(texts) != num: raise TypeError('length of text must be {0}'.format(num)) size = kwargs.pop('fontsize', None) or kwargs.pop('size', None) modes = [m for m in modes] if len(modes) == 2: plot = plt.plot show = plt.gcf() text = plt.text else: from mpl_toolkits.mplot3d import Axes3D cf = plt.gcf() show = None for child in cf.get_children(): if isinstance(child, Axes3D): show = child break if show is None: show = Axes3D(cf) plot = show.plot text = show.text indict = defaultdict(list) for i, opts in enumerate(zip(markers, colors, labels)): # PY3K: OK indict[opts].append(i) args = list(args) for opts, indices in indict.items(): # PY3K: OK marker, color, label = opts kwargs['marker'] = marker kwargs['color'] = color if label: kwargs['label'] = label else: kwargs.pop('label', None) plot(*(list(projection[indices].T) + args), **kwargs) if texts: kwargs = {} if size: kwargs['size'] = size for args in zip(*(list(projection.T) + [texts])): text(*args, **kwargs) if len(modes) == 2: plt.xlabel('{0} coordinate'.format(int(modes[0])+1)) plt.ylabel('{0} coordinate'.format(int(modes[1])+1)) elif len(modes) == 3: show.set_xlabel('Mode {0} coordinate'.format(int(modes[0])+1)) show.set_ylabel('Mode {0} coordinate'.format(int(modes[1])+1)) show.set_zlabel('Mode {0} coordinate'.format(int(modes[2])+1)) if SETTINGS['auto_show']: showFigure() return show
def showEmbedding(modes, labels=None, trace=True, headtail=True, cmap='prism'): """Visualizes Laplacian embedding of Hi-C data. :arg modes: modes in which loci are embedded. It can only have 2 or 3 modes for the purpose of visualization. :type modes: :class:`ModeSet` :arg labels: a list of integers indicating the segmentation of the sequence. :type labels: list :arg trace: if **True** then the trace of the sequence will be indicated by a grey dashed line. :type trace: bool :arg headtail: if **True** then a star and a closed circle will indicate the head and the tail of the sequence respectively. :type headtail: bool :arg cmap: the color map used to render the *labels*. :type cmap: str """ V, mask = _getEigvecs(modes, True) m,n = V.shape if labels is not None: if len(labels) != m: raise ValueError('Modes (%d) and the Hi-C map (%d) should have the same number' ' of atoms. Turn off "masked" if you intended to apply the' ' modes to the full map.' %(m, len(labels))) if n > 3: raise ValueError('This function can only visualize the embedding of 2 or 3 modes.') from matplotlib.pyplot import figure, plot, scatter from mpl_toolkits.mplot3d import Axes3D if n == 2: la = importLA() X, Y = V[:,:2].T R = np.array(range(len(X))) R = R / la.norm(R) X *= R; Y *= R f = figure() if trace: plot(X, Y, ':', color=[0.3, 0.3, 0.3]) if labels is None: C = 'b' else: C = labels scatter(X, Y, s=30, c=C, cmap=cmap) if headtail: plot(X[:1], Y[:1], 'k*', markersize=12) plot(X[-1:], Y[-1:], 'ko', markersize=12) elif n == 3: X, Y, Z = V[:,:3].T f = figure() ax = Axes3D(f) if trace: ax.plot(X, Y, Z, ':', color=[0.3, 0.3, 0.3]) if labels is None: C = 'b' else: C = labels ax.scatter(X, Y, Z, s=30, c=C, depthshade=True, cmap=cmap) if headtail: ax.plot(X[:1], Y[:1], Z[:1], 'k*', markersize=12) ax.plot(X[-1:], Y[-1:], Z[-1:], 'ko', markersize=12) if SETTINGS['auto_show']: showFigure() return f
def showProtein(*atoms, **kwargs): """Show protein representation using :meth:`~mpl_toolkits.mplot3d.Axes3D`. This function is designed for generating a quick view of the contents of a :class:`~.AtomGroup` or :class:`~.Selection`. Protein atoms matching ``"calpha"`` selection are displayed using solid lines by picking a random and unique color per chain. Line with can be adjusted using *lw* argument, e.g. ``lw=12``. Default width is 4. Chain colors can be overwritten using chain identifier as in ``A='green'``. Water molecule oxygen atoms are represented by red colored circles. Color can be changed using *water* keyword argument, e.g. ``water='aqua'``. Water marker and size can be changed using *wmarker* and *wsize* keywords, defaults values are ``wmarker='.', wsize=6``. Hetero atoms matching ``"hetero and noh"`` selection are represented by circles and unique colors are picked at random on a per residue basis. Colors can be customized using residue name as in ``NAH='purple'``. Note that this will color all distinct residues with the same name in the same color. Hetero atom marker and size can be changed using *hmarker* and *hsize* keywords, default values are ``hmarker='o', hsize=6``. ProDy will set the size of axis so the representation is not distorted when the shape of figure window is close to a square. Colors are picked at random, except for water oxygens which will always be colored red. *** Interactive 3D Rendering in Jupyter Notebook *** If py3Dmol has been imported then it will be used instead to display an interactive viewer. See :func:`view3D` """ from prody.dynamics.mode import Mode method = kwargs.pop('draw', None) modes = kwargs.get('mode', None) scale = kwargs.get('scale', 100) # modes need to be specifically a list or a tuple (cannot be an array) if modes is None: n_modes = 0 else: modes = wrapModes(modes) n_modes = len(modes) if method is None: import sys if 'py3Dmol' in sys.modules: method = 'py3Dmol' else: method = 'matplotlib' method = method.lower() alist = atoms for atoms in alist: if not isinstance(atoms, Atomic): raise TypeError('atoms must be an Atomic instance') if n_modes and n_modes != len(alist): raise RuntimeError( 'the number of proteins ({0}) does not match that of the modes ({1}).' .format(len(alist), n_modes)) if '3dmol' in method: mol = view3D(*alist, **kwargs) return mol else: kwargs.pop('mode', None) kwargs.pop('scale', 100) import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D cf = plt.gcf() show = None for child in cf.get_children(): if isinstance(child, Axes3D): show = child break if show is None: show = Axes3D(cf) from matplotlib import colors cnames = dict(colors.cnames) wcolor = kwargs.get('water', 'red').lower() avoid = np.array( colors.hex2color(cnames.pop(wcolor, cnames.pop('red')))) for cn, val in cnames.copy().items(): # PY3K: OK clr = np.array(colors.hex2color(val)) if clr.sum() > 2.4: cnames.pop(cn) elif np.abs(avoid - clr).sum() <= 0.6: cnames.pop(cn) cnames = list(cnames) import random random.shuffle(cnames) cnames_copy = list(cnames) min_ = list() max_ = list() for i, atoms in enumerate(alist): if isinstance(atoms, AtomGroup): title = atoms.getTitle() else: title = atoms.getAtomGroup().getTitle() calpha = atoms.select('calpha') if calpha: partition = False mode = modes[i] if n_modes else None if mode is not None: is3d = False try: arr = mode.getArray() is3d = mode.is3d() n_nodes = mode.numAtoms() except AttributeError: arr = mode is3d = len(arr) == len(calpha) * 3 n_nodes = len(arr) // 3 if is3d else len(arr) if n_nodes != len(calpha): raise RuntimeError( 'size mismatch between the protein ({0} residues) and the mode ({1} nodes).' .format(len(calpha), n_nodes)) partition = not is3d if partition: xyz = calpha._getCoords() chids = calpha.getChids() rbody = [] last_sign = np.sign(arr[0]) last_chid = chids[0] rcolor = ['red', 'red', 'blue'] n = 1 for i, a in enumerate(arr): s = np.sign(a) ch = chids[i] if s == 0: s = last_sign if last_sign != s or i == len( arr) - 1 or last_chid != ch: if last_chid == ch: rbody.append(i) show.plot(xyz[rbody, 0], xyz[rbody, 1], xyz[rbody, 2], label=title + '_regid%d' % n, color=rcolor[int(last_sign + 1)], lw=kwargs.get('lw', 4)) rbody = [] n += 1 last_sign = s last_chid = ch rbody.append(i) else: for ch in HierView(calpha, chain=True): xyz = ch._getCoords() chid = ch.getChid() if len(cnames) == 0: cnames = list(cnames_copy) show.plot(xyz[:, 0], xyz[:, 1], xyz[:, 2], label=title + '_' + chid, color=kwargs.get(chid, cnames.pop()).lower(), lw=kwargs.get('lw', 4)) if mode is not None: from prody.utilities.drawtools import drawArrow3D XYZ = calpha._getCoords() arr = arr.reshape((n_nodes, 3)) XYZ2 = XYZ + arr * scale for i, xyz in enumerate(XYZ): xyz2 = XYZ2[i] mutation_scale = kwargs.pop('mutation_scale', 10) drawArrow3D(xyz, xyz2, mutation_scale=mutation_scale, **kwargs) water = atoms.select('water and noh') if water: xyz = atoms.select('water')._getCoords() show.plot(xyz[:, 0], xyz[:, 1], xyz[:, 2], label=title + '_water', color=wcolor, ls='None', marker=kwargs.get('wmarker', '.'), ms=kwargs.get('wsize', 6)) hetero = atoms.select( 'not protein and not nucleic and not water and not dummy') if hetero: for res in HierView(hetero).iterResidues(): xyz = res._getCoords() resname = res.getResname() resnum = str(res.getResnum()) chid = res.getChid() if len(cnames) == 0: cnames = list(cnames_copy) show.plot(xyz[:, 0], xyz[:, 1], xyz[:, 2], ls='None', color=kwargs.get(resname, cnames.pop()).lower(), label=title + '_' + chid + '_' + resname + resnum, marker=kwargs.get('hmarker', 'o'), ms=kwargs.get('hsize', 6)) xyz = atoms._getCoords() min_.append(xyz.min(0)) max_.append(xyz.max(0)) show.set_xlabel('x') show.set_ylabel('y') show.set_zlabel('z') min_ = np.array(min_).min(0) max_ = np.array(max_).max(0) center = (max_ + min_) / 2 half = (max_ - min_).max() / 2 show.set_xlim3d(center[0] - half, center[0] + half) show.set_ylim3d(center[1] - half, center[1] + half) show.set_zlim3d(center[2] - half, center[2] + half) if kwargs.get('legend', False): show.legend(prop={'size': 10}) if SETTINGS['auto_show']: showFigure() return show
def showEmbedding(modes, labels=None, trace=True, headtail=True, cmap='prism'): """Visualizes Laplacian embedding of Hi-C data. :arg modes: modes in which loci are embedded. It can only have 2 or 3 modes for the purpose of visualization. :type modes: :class:`ModeSet` :arg labels: a list of integers indicating the segmentation of the sequence. :type labels: list :arg trace: if **True** then the trace of the sequence will be indicated by a grey dashed line. :type trace: bool :arg headtail: if **True** then a star and a closed circle will indicate the head and the tail of the sequence respectively. :type headtail: bool :arg cmap: the color map used to render the *labels*. :type cmap: str """ V, _ = _getEigvecs(modes, True) m, n = V.shape if labels is not None: if len(labels) != m: raise ValueError( 'Modes (%d) and the Hi-C map (%d) should have the same number' ' of atoms. Turn off "masked" if you intended to apply the' ' modes to the full map.' % (m, len(labels))) if n > 3: raise ValueError( 'This function can only visualize the embedding of 2 or 3 modes.') from matplotlib.pyplot import figure, plot, scatter from mpl_toolkits.mplot3d import Axes3D if n == 2: la = importLA() X, Y = V[:, :2].T R = np.array(range(len(X))) R = R / la.norm(R) X *= R Y *= R f = figure() if trace: plot(X, Y, ':', color=[0.3, 0.3, 0.3]) if labels is None: C = 'b' else: C = labels scatter(X, Y, s=30, c=C, cmap=cmap) if headtail: plot(X[:1], Y[:1], 'k*', markersize=12) plot(X[-1:], Y[-1:], 'ko', markersize=12) elif n == 3: X, Y, Z = V[:, :3].T f = figure() ax = Axes3D(f) if trace: ax.plot(X, Y, Z, ':', color=[0.3, 0.3, 0.3]) if labels is None: C = 'b' else: C = labels ax.scatter(X, Y, Z, s=30, c=C, depthshade=True, cmap=cmap) if headtail: ax.plot(X[:1], Y[:1], Z[:1], 'k*', markersize=12) ax.plot(X[-1:], Y[-1:], Z[-1:], 'ko', markersize=12) if SETTINGS['auto_show']: showFigure() return f
def showCrossProjection(ensemble, mode_x, mode_y, scale=None, *args, **kwargs): """Show a projection of conformational deviations onto modes from different models using :func:`~matplotlib.pyplot.plot`. This function differs from :func:`.showProjection` by accepting modes from two different models. :arg ensemble: an ensemble or a conformation for which deviation(s) will be projected, or a deformation vector :type ensemble: :class:`.Ensemble`, :class:`.Conformation`, :class:`.Vector`, :class:`.Trajectory` :arg mode_x: projection onto this mode will be shown along x-axis :type mode_x: :class:`.Mode`, :class:`.Vector` :arg mode_y: projection onto this mode will be shown along y-axis :type mode_y: :class:`.Mode`, :class:`.Vector` :arg scale: scale width of the projection onto mode ``x`` or ``y``, best scaling factor will be calculated and printed on the console, absolute value of scalar makes the with of two projection same, sign of scalar makes the projections yield a positive correlation :type scale: str :arg scalar: scalar factor for projection onto selected mode :type scalar: float :arg color: a color name or a list of color name, default is ``'blue'`` :type color: str, list :arg label: label or a list of labels :type label: str, list :arg marker: a marker or a list of markers, default is ``'o'`` :type marker: str, list :arg linestyle: line style, default is ``'None'`` :type linestyle: str :arg text: list of text labels, one for each conformation :type text: list :arg fontsize: font size for text labels :type fontsize: int The projected values are by default converted to RMSD. Pass ``rmsd=False`` to calculate raw projection values. See :ref:`pca-xray-plotting` for a more elaborate example.""" import matplotlib.pyplot as plt xcoords, ycoords = calcCrossProjection(ensemble, mode_x, mode_y, scale=scale, **kwargs) num = len(xcoords) markers = kwargs.pop('marker', 'o') if isinstance(markers, str) or markers is None: markers = [markers] * num elif isinstance(markers, list): if len(markers) != num: raise ValueError('length of marker must be {0}'.format(num)) else: raise TypeError('marker must be a string or a list') colors = kwargs.pop('color', 'blue') if isinstance(colors, str) or colors is None: colors = [colors] * num elif isinstance(colors, list): if len(colors) != num: raise ValueError('length of color must be {0}'.format(num)) else: raise TypeError('color must be a string or a list') labels = kwargs.pop('label', None) if isinstance(labels, str) or labels is None: labels = [labels] * num elif isinstance(labels, list): if len(labels) != num: raise ValueError('length of label must be {0}'.format(num)) elif labels is not None: raise TypeError('label must be a string or a list') kwargs['ls'] = kwargs.pop('linestyle', None) or kwargs.pop('ls', 'None') texts = kwargs.pop('text', None) if texts: if not isinstance(texts, list): raise TypeError('text must be a list') elif len(texts) != num: raise TypeError('length of text must be {0}'.format(num)) size = kwargs.pop('fontsize', None) or kwargs.pop('size', None) indict = defaultdict(list) for i, opts in enumerate(zip(markers, colors, labels)): # PY3K: OK indict[opts].append(i) for opts, indices in indict.items(): # PY3K: OK marker, color, label = opts kwargs['marker'] = marker kwargs['color'] = color if label: kwargs['label'] = label else: kwargs.pop('label', None) show = plt.plot(xcoords[indices], ycoords[indices], *args, **kwargs) if texts: kwargs = {} if size: kwargs['size'] = size for x, y, t in zip(xcoords, ycoords, texts): plt.text(x, y, t, **kwargs) plt.xlabel('{0} coordinate'.format(mode_x)) plt.ylabel('{0} coordinate'.format(mode_y)) if SETTINGS['auto_show']: showFigure() return show
def showProtein(*atoms, **kwargs): """Show protein representation using :meth:`~mpl_toolkits.mplot3d.Axes3D`. This function is designed for generating a quick view of the contents of a :class:`~.AtomGroup` or :class:`~.Selection`. Protein atoms matching ``"calpha"`` selection are displayed using solid lines by picking a random and unique color per chain. Line with can be adjusted using *lw* argument, e.g. ``lw=12``. Default width is 4. Chain colors can be overwritten using chain identifier as in ``A='green'``. Water molecule oxygen atoms are represented by red colored circles. Color can be changed using *water* keyword argument, e.g. ``water='aqua'``. Water marker and size can be changed using *wmarker* and *wsize* keywords, defaults values are ``wmarker='.', wsize=6``. Hetero atoms matching ``"hetero and noh"`` selection are represented by circles and unique colors are picked at random on a per residue basis. Colors can be customized using residue name as in ``NAH='purple'``. Note that this will color all distinct residues with the same name in the same color. Hetero atom marker and size can be changed using *hmarker* and *hsize* keywords, default values are ``hmarker='o', hsize=6``. ProDy will set the size of axis so the representation is not distorted when the shape of figure window is close to a square. Colors are picked at random, except for water oxygens which will always be colored red.""" alist = atoms for atoms in alist: if not isinstance(atoms, Atomic): raise TypeError('atoms must be an Atomic instance') import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D cf = plt.gcf() show = None for child in cf.get_children(): if isinstance(child, Axes3D): show = child break if show is None: show = Axes3D(cf) from matplotlib import colors cnames = dict(colors.cnames) wcolor = kwargs.get('water', 'red').lower() avoid = np.array(colors.hex2color(cnames.pop(wcolor, cnames.pop('red')))) for cn, val in cnames.items(): # PY3K: OK clr = np.array(colors.hex2color(val)) if clr.sum() > 2.4: cnames.pop(cn) elif np.abs(avoid - clr).sum() <= 0.6: cnames.pop(cn) cnames = list(cnames) import random random.shuffle(cnames) min_ = list() max_ = list() for atoms in alist: if isinstance(atoms, AtomGroup): title = atoms.getTitle() else: title = atoms.getAtomGroup().getTitle() calpha = atoms.select('calpha') if calpha: for ch in HierView(calpha, chain=True): xyz = ch._getCoords() chid = ch.getChid() show.plot(xyz[:, 0], xyz[:, 1], xyz[:, 2], label=title + '_' + chid, color=kwargs.get(chid, cnames.pop()).lower(), lw=kwargs.get('lw', 4)) water = atoms.select('water and noh') if water: xyz = atoms.select('water')._getCoords() show.plot(xyz[:, 0], xyz[:, 1], xyz[:, 2], label=title + '_water', color=wcolor, ls='None', marker=kwargs.get('wmarker', '.'), ms=kwargs.get('wsize', 6)) hetero = atoms.select('not protein and not nucleic and not water') if hetero: for res in HierView(hetero).iterResidues(): xyz = res._getCoords() resname = res.getResname() resnum = str(res.getResnum()) chid = res.getChid() show.plot(xyz[:, 0], xyz[:, 1], xyz[:, 2], ls='None', color=kwargs.get(resname, cnames.pop()).lower(), label=title + '_' + chid + '_' + resname + resnum, marker=kwargs.get('hmarker', 'o'), ms=kwargs.get('hsize', 6)) xyz = atoms._getCoords() min_.append(xyz.min(0)) max_.append(xyz.max(0)) show.set_xlabel('x') show.set_ylabel('y') show.set_zlabel('z') min_ = np.array(min_).min(0) max_ = np.array(max_).max(0) center = (max_ + min_) / 2 half = (max_ - min_).max() / 2 show.set_xlim3d(center[0] - half, center[0] + half) show.set_ylim3d(center[1] - half, center[1] + half) show.set_zlim3d(center[2] - half, center[2] + half) if kwargs.get('legend', False): show.legend(prop={'size': 10}) if SETTINGS['auto_show']: showFigure() return show
def showProjection(ensemble, modes, *args, **kwargs): """Show a projection of conformational deviations onto up to three normal modes from the same model. :arg ensemble: an ensemble, trajectory or a conformation for which deviation(s) will be projected, or a deformation vector :type ensemble: :class:`.Ensemble`, :class:`.Conformation`, :class:`.Vector`, :class:`.Trajectory` :arg modes: up to three normal modes :type modes: :class:`.Mode`, :class:`.ModeSet`, :class:`.NMA` :arg color: a color name or a list of color name, default is ``'blue'`` :type color: str, list :arg label: label or a list of labels :type label: str, list :arg marker: a marker or a list of markers, default is ``'o'`` :type marker: str, list :arg linestyle: line style, default is ``'None'`` :type linestyle: str :arg text: list of text labels, one for each conformation :type text: list :arg fontsize: font size for text labels :type fontsize: int The projected values are by default converted to RMSD. Pass ``rmsd=False`` to use projection itself. Matplotlib function used for plotting depends on the number of modes: * 1 mode: :func:`~matplotlib.pyplot.hist` * 2 modes: :func:`~matplotlib.pyplot.plot` * 3 modes: :meth:`~mpl_toolkits.mplot3d.Axes3D.plot`""" import matplotlib.pyplot as plt projection = calcProjection(ensemble, modes, kwargs.pop('rmsd', True)) if projection.ndim == 1 or projection.shape[1] == 1: show = plt.hist(projection.flatten(), *args, **kwargs) plt.xlabel('{0} coordinate'.format(str(modes))) plt.ylabel('Number of conformations') return show elif projection.shape[1] > 3: raise ValueError('Projection onto up to 3 modes can be shown. ' 'You have given {0} mode.'.format(len(modes))) num = projection.shape[0] markers = kwargs.pop('marker', 'o') if isinstance(markers, str) or markers is None: markers = [markers] * num elif isinstance(markers, list): if len(markers) != num: raise ValueError('length of marker must be {0}'.format(num)) else: raise TypeError('marker must be a string or a list') colors = kwargs.pop('color', 'blue') if isinstance(colors, str) or colors is None: colors = [colors] * num elif isinstance(colors, list): if len(colors) != num: raise ValueError('length of color must be {0}'.format(num)) else: raise TypeError('color must be a string or a list') labels = kwargs.pop('label', None) if isinstance(labels, str) or labels is None: labels = [labels] * num elif isinstance(labels, list): if len(labels) != num: raise ValueError('length of label must be {0}'.format(num)) elif labels is not None: raise TypeError('label must be a string or a list') kwargs['ls'] = kwargs.pop('linestyle', None) or kwargs.pop('ls', 'None') texts = kwargs.pop('text', None) if texts: if not isinstance(texts, list): raise TypeError('text must be a list') elif len(texts) != num: raise TypeError('length of text must be {0}'.format(num)) size = kwargs.pop('fontsize', None) or kwargs.pop('size', None) modes = [m for m in modes] if len(modes) == 2: plot = plt.plot show = plt.gcf() text = plt.text else: from mpl_toolkits.mplot3d import Axes3D cf = plt.gcf() show = None for child in cf.get_children(): if isinstance(child, Axes3D): show = child break if show is None: show = Axes3D(cf) plot = show.plot text = show.text indict = defaultdict(list) for i, opts in enumerate(zip(markers, colors, labels)): # PY3K: OK indict[opts].append(i) args = list(args) for opts, indices in indict.items(): # PY3K: OK marker, color, label = opts kwargs['marker'] = marker kwargs['color'] = color if label: kwargs['label'] = label else: kwargs.pop('label', None) plot(*(list(projection[indices].T) + args), **kwargs) if texts: kwargs = {} if size: kwargs['size'] = size for args in zip(*(list(projection.T) + [texts])): text(*args, **kwargs) if len(modes) == 2: plt.xlabel('{0} coordinate'.format(int(modes[0]) + 1)) plt.ylabel('{0} coordinate'.format(int(modes[1]) + 1)) elif len(modes) == 3: show.set_xlabel('Mode {0} coordinate'.format(int(modes[0]) + 1)) show.set_ylabel('Mode {0} coordinate'.format(int(modes[1]) + 1)) show.set_zlabel('Mode {0} coordinate'.format(int(modes[2]) + 1)) if SETTINGS['auto_show']: showFigure() return show
def showEllipsoid(modes, onto=None, n_std=2, scale=1., *args, **kwargs): """Show an ellipsoid using :meth:`~mpl_toolkits.mplot3d.Axes3D .plot_wireframe`. Ellipsoid volume gives an analytical view of the conformational space that given modes describe. :arg modes: 3 modes for which ellipsoid will be drawn. :type modes: :class:`.ModeSet`, :class:`.PCA`, :class:`.ANM`, :class:`.NMA` :arg onto: 3 modes onto which ellipsoid will be projected. :type modes: :class:`.ModeSet`, :class:`.PCA`, :class:`.ANM`, :class:`.NMA` :arg n_std: Number of standard deviations to scale the ellipsoid. :type n_std: float :arg scale: Used for scaling the volume of ellipsoid. This can be obtained from :func:`.sampleModes`. :type scale: float""" import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D if not isinstance(modes, (NMA, ModeSet)): raise TypeError('modes must be a NMA or ModeSet instance, ' 'not {0}'.format(type(modes))) if not modes.is3d(): raise ValueError('modes must be from a 3-dimensional model') if len(modes) != 3: raise ValueError('length of modes is not equal to 3') if onto is not None: if not isinstance(onto, (NMA, ModeSet)): raise TypeError('onto must be a NMA or ModeSet instance, ' 'not {0}'.format(type(onto))) if not onto.is3d(): raise ValueError('onto must be from a 3-dimensional model') if len(onto) != 3: raise ValueError('length of onto is not equal to 3') if onto.numAtoms() != modes.numAtoms(): raise ValueError('modes and onto must have same number of atoms') u = np.linspace(0, 2 * np.pi, 100) v = np.linspace(0, np.pi, 100) var = modes.getVariances() #randn = np.random.standard_normal((1000, 3)) #coef = ((randn ** 2 * var).sum(1) ** 0.5).mean() #scale=float(n_std)*modes.numAtoms()**.5 * float(rmsd) / coef * var **.5 scale = float(n_std) * scale * var ** 0.5 #scale=float(n_std)*modes.numAtoms()**.5*float(rmsd)/var.sum()**.5*var**.5 x = scale[0] * np.outer(np.cos(u), np.sin(v)) y = scale[1] * np.outer(np.sin(u), np.sin(v)) z = scale[2] * np.outer(np.ones(np.size(u)), np.cos(v)) if onto is not None: change_of_basis = np.dot(modes._getArray().T, onto._getArray()) xyz = np.array([x.flatten(), y.flatten(), z.flatten()]) xyz = np.dot(xyz.T, change_of_basis) x = xyz[:,0].reshape((100,100)) y = xyz[:,1].reshape((100,100)) z = xyz[:,2].reshape((100,100)) cf = plt.gcf() show = None for child in cf.get_children(): if isinstance(child, Axes3D): show = child break if show is None: show = Axes3D(cf) show.plot_wireframe(x, y, z, rstride=6, cstride=6, *args, **kwargs) if onto is not None: onto = list(onto) show.set_xlabel('Mode {0} coordinate'.format(int(onto[0])+1)) show.set_ylabel('Mode {0} coordinate'.format(int(onto[1])+1)) show.set_zlabel('Mode {0} coordinate'.format(int(onto[2])+1)) else: modes = list(modes) show.set_xlabel('Mode {0} coordinate'.format(int(modes[0])+1)) show.set_ylabel('Mode {0} coordinate'.format(int(modes[1])+1)) show.set_zlabel('Mode {0} coordinate'.format(int(modes[2])+1)) if SETTINGS['auto_show']: showFigure() return show