def getTicks(self, idx): """ This is essentially a wrapper around getProfileTicks to accomdate the fact that each column has its own ticks. """ xticks, xtickslabel = getProfileTicks(self.hm, self.reference_point_label[idx], self.start_label[idx], self.end_label[idx], idx) return xticks, xtickslabel
def __init__(self, hm, out_file_name, plot_title='', y_axis_label='', y_min=None, y_max=None, averagetype='median', reference_point_label='TSS', start_label='TSS', end_label="TES", plot_height=7, plot_width=11, per_group=False, plot_type='simple', image_format=None, color_list=None, legend_location='auto', plots_per_row=8): """ Using the hm matrix, makes a line plot either per group or per sample using the specified parameters. Args: hm: heatmapper object out_file_name: string plot_title: string y_axis_label: list y_min: int y_max: int averagetype: mean, sum, median reference_point_label: string start_label: string end_label: string plot_height: in cm plot_width: in cm per_group: bool plot_type: string image_format: string color_list: list legend_location: plots_per_row: int Returns: """ self.hm = hm self.out_file_name = out_file_name self.plot_title = plot_title self.y_axis_label = y_axis_label self.y_min = y_min self.y_max = y_max self.averagetype = averagetype self.reference_point_label = reference_point_label self.start_label = start_label self.end_label = end_label self.plot_height = plot_height self.plot_width = plot_width self.per_group = per_group self.plot_type = plot_type self.image_format = image_format self.color_list = color_list self.legend_location = legend_location self.plots_per_row = plots_per_row # decide how many plots are needed if self.per_group: self.numplots = self.hm.matrix.get_num_groups() self.numlines = self.hm.matrix.get_num_samples() else: self.numplots = self.hm.matrix.get_num_samples() self.numlines = self.hm.matrix.get_num_groups() if self.numplots > self.plots_per_row: rows = np.ceil(self.numplots / self.plots_per_row).astype(int) cols = self.plots_per_row else: rows = 1 cols = self.numplots self.grids = gridspec.GridSpec(rows, cols) plt.rcParams['font.size'] = 10.0 self.font_p = FontProperties() self.font_p.set_size('small') # convert cm values to inches plot_height_inches = rows * self.cm2inch(self.plot_height)[0] self.fig = plt.figure(figsize=self.cm2inch(cols * self.plot_width, rows * self.plot_height)) self.fig.suptitle(self.plot_title, y=(1 - (0.06 / plot_height_inches))) self.xticks, self.xtickslabel = getProfileTicks( self.hm, self.reference_point_label, self.start_label, self.end_label)
def plotMatrix(hm, outFileName, colorMapDict={'colorMap': 'binary', 'missingDataColor': 'black'}, plotTitle='', xAxisLabel='', yAxisLabel='', regionsLabel='', zMin=None, zMax=None, yMin=None, yMax=None, averageType='median', reference_point_label='TSS', startLabel='TSS', endLabel="TES", heatmapHeight=25, heatmapWidth=7.5, perGroup=False, whatToShow='plot, heatmap and colorbar', plotType='simple', image_format=None, legend_location='upper-left'): matrix_flatten = None if zMin is None: matrix_flatten = hm.matrix.flatten() # try to avoid outliers by using np.percentile zMin = np.percentile(matrix_flatten, 1.0) if np.isnan(zMin): zMin = None if zMax is None: if matrix_flatten is None: matrix_flatten = hm.matrix.flatten() # try to avoid outliers by using np.percentile zMax = np.percentile(matrix_flatten, 98.0) if np.isnan(zMax): zMax = None plt.rcParams['font.size'] = 8.0 fontP = FontProperties() # fontP.set_size('small') showSummaryPlot = False showColorbar = False if whatToShow == 'plot and heatmap': showSummaryPlot = True elif whatToShow == 'heatmap and colorbar': showColorbar = True elif whatToShow == 'plot, heatmap and colorbar': showSummaryPlot = True showColorbar = True grids = prepare_layout(hm.matrix, (heatmapWidth, heatmapHeight), showSummaryPlot, showColorbar, perGroup) # figsize: w,h tuple in inches figwidth = heatmapWidth / 2.54 figheight = heatmapHeight / 2.54 if showSummaryPlot: # the summary plot ocupies a height # equal to the fig width figheight += figwidth numsamples = hm.matrix.get_num_samples() total_figwidth = figwidth * numsamples if showColorbar: total_figwidth += 1 / 2.54 fig = plt.figure(figsize=(total_figwidth, figheight)) hm.parameters['upstream'] hm.parameters['downstream'] hm.parameters['body'] hm.parameters['bin size'] xticks, xtickslabel = getProfileTicks(hm, reference_point_label, startLabel, endLabel) xticks_heat, xtickslabel_heat = get_heatmap_ticks(hm, reference_point_label, startLabel, endLabel) fig.suptitle(plotTitle, y=1 - (0.06 / figheight)) # colormap for the heatmap if colorMapDict['colorMap']: cmap = plt.get_cmap(colorMapDict['colorMap']) if colorMapDict['colorList'] and len(colorMapDict['colorList']) > 0: cmap = matplotlib.colors.LinearSegmentedColormap.from_list( 'my_cmap', colorMapDict['colorList'], N=colorMapDict['colorNumber']) # color map for the summary plot (profile) on top of the heatmap cmap_plot = plt.get_cmap('jet') numgroups = hm.matrix.get_num_groups() if perGroup: color_list = cmap_plot(np.arange(hm.matrix.get_num_samples()) / hm.matrix.get_num_samples()) else: color_list = cmap_plot(np.arange(numgroups) / numgroups) cmap.set_bad(colorMapDict['missingDataColor']) # nans are printed using this color # check if matrix is reference-point based using the upstream >0 value # and is sorted by region length. If this is # the case, prepare the data to plot a border at the regions end if hm.parameters['upstream'] > 0 and \ hm.matrix.sort_using == 'region_length' and \ hm.matrix.sort_method != 'no': _regions = hm.matrix.get_regions() regions_length_in_bins = [] for _group in _regions: _reg_len = [] for ind_reg in _group: _len = ind_reg['end'] - ind_reg['start'] _reg_len.append((hm.parameters['upstream'] + _len) / hm.parameters['bin size']) # print hm.parameters['upstream'] + (_len / hm.parameters['bin size']) regions_length_in_bins.append(_reg_len) else: regions_length_in_bins = None first_group = 0 # helper variable to place the title per sample/group for sample in range(hm.matrix.get_num_samples()): sample_idx = sample for group in range(numgroups): group_idx = group # add the respective profile to the # summary plot sub_matrix = hm.matrix.get_matrix(group, sample) if showSummaryPlot: if perGroup: sample_idx = sample + 2 # plot + spacer else: group += 2 # plot + spacer first_group = 1 if perGroup: ax = fig.add_subplot(grids[sample_idx, group]) else: ax = fig.add_subplot(grids[group, sample]) if group == first_group and not showSummaryPlot and not perGroup: title = hm.matrix.sample_labels[sample] ax.set_title(title) rows, cols = sub_matrix['matrix'].shape interpolation_type = None if rows >= 1000 and cols >= 200 else 'nearest' img = ax.imshow(sub_matrix['matrix'], aspect='auto', interpolation=interpolation_type, origin='upper', vmin=zMin, vmax=zMax, cmap=cmap, extent=[0, cols, rows, 0]) # plot border at the end of the regions # if ordered by length if regions_length_in_bins is not None: x_lim = ax.get_xlim() y_lim = ax.get_ylim() ax.plot(regions_length_in_bins[group_idx], np.arange(len(regions_length_in_bins[group_idx])), '--', color='black', linewidth=0.5, dashes=(3, 2)) ax.set_xlim(x_lim) ax.set_ylim(y_lim) if perGroup: ax.axes.set_xlabel(sub_matrix['group']) if sample < hm.matrix.get_num_samples() - 1: ax.axes.get_xaxis().set_visible(False) else: ax.axes.get_xaxis().set_visible(False) ax.axes.set_xlabel(xAxisLabel) ax.axes.set_yticks([]) if perGroup and group == 0: ax.axes.set_ylabel(sub_matrix['sample']) elif not perGroup and sample == 0: ax.axes.set_ylabel(sub_matrix['group']) # add xticks to the bottom heatmap (last group) ax.axes.get_xaxis().set_visible(True) ax.axes.set_xticks(xticks_heat) ax.axes.set_xticklabels(xtickslabel_heat, size=8) # align the first and last label # such that they don't fall off # the heatmap sides ticks = ax.xaxis.get_major_ticks() ticks[0].label1.set_horizontalalignment('left') ticks[-1].label1.set_horizontalalignment('right') ax.get_xaxis().set_tick_params( which='both', top='off', direction='out') # plot the profiles on top of the heatmaps if showSummaryPlot: ax_list = [] if perGroup: iterNum = numgroups else: iterNum = hm.matrix.get_num_samples() # plot each of the profiles for sample_id in range(iterNum): if perGroup: title = hm.matrix.group_labels[sample_id] else: title = hm.matrix.sample_labels[sample_id] if sample_id > 0: ax_profile = fig.add_subplot(grids[0, sample_id], sharey=ax_list[0]) else: ax_profile = fig.add_subplot(grids[0, sample_id]) ax_profile.set_title(title) if perGroup: iterNum2 = hm.matrix.get_num_samples() else: iterNum2 = numgroups for group in range(iterNum2): if perGroup: sub_matrix = hm.matrix.get_matrix(sample_id, group) line_label = sub_matrix['sample'] else: sub_matrix = hm.matrix.get_matrix(group, sample_id) line_label = sub_matrix['group'] plot_single(ax_profile, sub_matrix['matrix'], averageType, color_list[group], line_label, plot_type='simple') if sample_id > 0: plt.setp(ax_profile.get_yticklabels(), visible=False) if sample_id == 0 and yAxisLabel != '': ax_profile.set_ylabel(yAxisLabel) ax_profile.axes.set_xticks(xticks) ax_profile.axes.set_xticklabels(xtickslabel) ax_list.append(ax_profile) # align the first and last label # such that they don't fall off # the heatmap sides ticks = ax_profile.xaxis.get_major_ticks() ticks[0].label1.set_horizontalalignment('left') ticks[-1].label1.set_horizontalalignment('right') # reduce the number of yticks by half ax_list[0].set_ylim(yMin, yMax) num_ticks = len(ax_list[0].get_yticks()) yticks = [ax_list[0].get_yticks()[i] for i in range(1, num_ticks, 2)] ax_list[0].set_yticks(yticks) if legend_location != 'none': ax_list[-1].legend(loc=legend_location.replace('-', ' '), ncol=1, prop=fontP, frameon=False, markerscale=0.5) if showColorbar: if showSummaryPlot: # we dont want to colorbar to extend # over the profiles row grid_start = 2 else: grid_start = 0 ax = fig.add_subplot(grids[grid_start:, -1]) fig.colorbar(img, cax=ax) plt.subplots_adjust(wspace=0.10, hspace=0.025, top=0.85, bottom=0, left=0.04, right=0.96) plt.savefig(outFileName, bbox_inches='tight', pdd_inches=0, dpi=200, format=image_format)
def plotMatrix(hm, outFileName, colorMapDict={ 'colorMap': ['binary'], 'missingDataColor': 'black', 'alpha': 1.0 }, plotTitle='', xAxisLabel='', yAxisLabel='', regionsLabel='', zMin=None, zMax=None, yMin=None, yMax=None, averageType='median', reference_point_label='TSS', startLabel='TSS', endLabel="TES", heatmapHeight=25, heatmapWidth=7.5, perGroup=False, whatToShow='plot, heatmap and colorbar', image_format=None, legend_location='upper-left', box_around_heatmaps=True, dpi=200): matrix_flatten = None if zMin is None: matrix_flatten = hm.matrix.flatten() # try to avoid outliers by using np.percentile zMin = np.percentile(matrix_flatten, 1.0) if np.isnan(zMin): zMin = [None] else: zMin = [zMin] # convert to list to support multiple entries if zMax is None: if matrix_flatten is None: matrix_flatten = hm.matrix.flatten() # try to avoid outliers by using np.percentile zMax = np.percentile(matrix_flatten, 98.0) if np.isnan(zMax): zMax = [None] else: zMax = [zMax] plt.rcParams['font.size'] = 8.0 fontP = FontProperties() showSummaryPlot = False showColorbar = False if whatToShow == 'plot and heatmap': showSummaryPlot = True elif whatToShow == 'heatmap and colorbar': showColorbar = True elif whatToShow == 'plot, heatmap and colorbar': showSummaryPlot = True showColorbar = True # colormap for the heatmap if colorMapDict['colorMap']: cmap = [] for color_map in colorMapDict['colorMap']: cmap.append(plt.get_cmap(color_map)) cmap[-1].set_bad(colorMapDict['missingDataColor'] ) # nans are printed using this color if colorMapDict['colorList'] and len(colorMapDict['colorList']) > 0: # make a cmap for each color list given cmap = [] for color_list in colorMapDict['colorList']: cmap.append( matplotlib.colors.LinearSegmentedColormap.from_list( 'my_cmap', color_list.replace(' ', '').split(","), N=colorMapDict['colorNumber'])) cmap[-1].set_bad(colorMapDict['missingDataColor'] ) # nans are printed using this color if len(cmap) > 1 or len(zMin) > 1 or len(zMax) > 1: # position color bar below heatmap when more than one # heatmap color is given colorbar_position = 'below' else: colorbar_position = 'side' grids = prepare_layout(hm.matrix, (heatmapWidth, heatmapHeight), showSummaryPlot, showColorbar, perGroup, colorbar_position) # figsize: w,h tuple in inches figwidth = heatmapWidth / 2.54 figheight = heatmapHeight / 2.54 if showSummaryPlot: # the summary plot ocupies a height # equal to the fig width figheight += figwidth numsamples = hm.matrix.get_num_samples() if perGroup: num_cols = hm.matrix.get_num_groups() else: num_cols = numsamples total_figwidth = figwidth * num_cols if showColorbar: if colorbar_position == 'below': figheight += 1 / 2.54 else: total_figwidth += 1 / 2.54 fig = plt.figure(figsize=(total_figwidth, figheight)) xticks, xtickslabel = getProfileTicks(hm, reference_point_label, startLabel, endLabel) xticks_heat, xtickslabel_heat = get_heatmap_ticks(hm, reference_point_label, startLabel, endLabel) fig.suptitle(plotTitle, y=1 - (0.06 / figheight)) # color map for the summary plot (profile) on top of the heatmap cmap_plot = plt.get_cmap('jet') numgroups = hm.matrix.get_num_groups() if perGroup: color_list = cmap_plot( np.arange(hm.matrix.get_num_samples()) / hm.matrix.get_num_samples()) else: color_list = cmap_plot(np.arange(numgroups) / numgroups) alpha = colorMapDict['alpha'] # check if matrix is reference-point based using the upstream >0 value # and is sorted by region length. If this is # the case, prepare the data to plot a border at the regions end if hm.parameters['upstream'] > 0 and \ hm.matrix.sort_using == 'region_length' and \ hm.matrix.sort_method != 'no': _regions = hm.matrix.get_regions() regions_length_in_bins = [] for _group in _regions: _reg_len = [] for ind_reg in _group: _len = ind_reg['end'] - ind_reg['start'] _reg_len.append((hm.parameters['upstream'] + _len) / hm.parameters['bin size']) regions_length_in_bins.append(_reg_len) else: regions_length_in_bins = None first_group = 0 # helper variable to place the title per sample/group for sample in range(hm.matrix.get_num_samples()): sample_idx = sample for group in range(numgroups): group_idx = group # add the respective profile to the # summary plot sub_matrix = hm.matrix.get_matrix(group, sample) if showSummaryPlot: if perGroup: sample_idx = sample + 2 # plot + spacer else: group += 2 # plot + spacer first_group = 1 if perGroup: ax = fig.add_subplot(grids[sample_idx, group]) # the remainder (%) is used to iterate # over the available color maps (cmap). # if the user only provided, lets say two # and there are 10 groups, colormaps they are reused every # two groups. cmap_idx = group_idx % len(cmap) zmin_idx = group_idx % len(zMin) zmax_idx = group_idx % len(zMax) else: ax = fig.add_subplot(grids[group, sample]) # see above for the use of '%' cmap_idx = sample % len(cmap) zmin_idx = sample % len(zMin) zmax_idx = sample % len(zMax) if group == first_group and not showSummaryPlot and not perGroup: title = hm.matrix.sample_labels[sample] ax.set_title(title) if box_around_heatmaps is False: # Turn off the boxes around the individual heatmaps ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) ax.spines['bottom'].set_visible(False) ax.spines['left'].set_visible(False) rows, cols = sub_matrix['matrix'].shape interpolation_type = None if rows >= 1000 and cols >= 200 else 'nearest' img = ax.imshow(sub_matrix['matrix'], aspect='auto', interpolation=interpolation_type, origin='upper', vmin=zMin[zmin_idx], vmax=zMax[zmax_idx], cmap=cmap[cmap_idx], alpha=alpha, extent=[0, cols, rows, 0]) img.set_rasterized(True) # plot border at the end of the regions # if ordered by length if regions_length_in_bins is not None: x_lim = ax.get_xlim() y_lim = ax.get_ylim() ax.plot(regions_length_in_bins[group_idx], np.arange(len(regions_length_in_bins[group_idx])), '--', color='black', linewidth=0.5, dashes=(3, 2)) ax.set_xlim(x_lim) ax.set_ylim(y_lim) if perGroup: ax.axes.set_xlabel(sub_matrix['group']) if sample < hm.matrix.get_num_samples() - 1: ax.axes.get_xaxis().set_visible(False) else: ax.axes.get_xaxis().set_visible(False) ax.axes.set_xlabel(xAxisLabel) ax.axes.set_yticks([]) if perGroup and group == 0: ax.axes.set_ylabel(sub_matrix['sample']) elif not perGroup and sample == 0: ax.axes.set_ylabel(sub_matrix['group']) # add labels to last block in a column if (perGroup and sample == numsamples - 1) or \ (not perGroup and group_idx == numgroups - 1): # add xticks to the bottom heatmap (last group) ax.axes.get_xaxis().set_visible(True) ax.axes.set_xticks(xticks_heat) ax.axes.set_xticklabels(xtickslabel_heat, size=8) # align the first and last label # such that they don't fall off # the heatmap sides ticks = ax.xaxis.get_major_ticks() ticks[0].label1.set_horizontalalignment('left') ticks[-1].label1.set_horizontalalignment('right') ax.get_xaxis().set_tick_params(which='both', top='off', direction='out') if showColorbar and colorbar_position == 'below': # draw a colormap per each heatmap below the last block if perGroup: col = group_idx else: col = sample ax = fig.add_subplot(grids[-1, col]) tick_locator = ticker.MaxNLocator(nbins=3) cbar = fig.colorbar(img, cax=ax, alpha=alpha, orientation='horizontal', ticks=tick_locator) labels = cbar.ax.get_xticklabels() ticks = cbar.ax.get_xticks() if ticks[0] == 0: # if the label is at the start of the colobar # move it a bit inside to avoid overlapping # with other labels labels[0].set_horizontalalignment('left') if ticks[-1] == 1: # if the label is at the end of the colobar # move it a bit inside to avoid overlapping # with other labels labels[-1].set_horizontalalignment('right') # cbar.ax.set_xticklabels(labels, rotation=90) # plot the profiles on top of the heatmaps if showSummaryPlot: ax_list = [] if perGroup: iterNum = numgroups else: iterNum = hm.matrix.get_num_samples() # plot each of the profiles for sample_id in range(iterNum): if perGroup: title = hm.matrix.group_labels[sample_id] else: title = hm.matrix.sample_labels[sample_id] if sample_id > 0: ax_profile = fig.add_subplot(grids[0, sample_id], sharey=ax_list[0]) else: ax_profile = fig.add_subplot(grids[0, sample_id]) ax_profile.set_title(title) if perGroup: iterNum2 = hm.matrix.get_num_samples() else: iterNum2 = numgroups for group in range(iterNum2): if perGroup: sub_matrix = hm.matrix.get_matrix(sample_id, group) line_label = sub_matrix['sample'] else: sub_matrix = hm.matrix.get_matrix(group, sample_id) line_label = sub_matrix['group'] plot_single(ax_profile, sub_matrix['matrix'], averageType, color_list[group], line_label, plot_type='simple') if sample_id > 0: plt.setp(ax_profile.get_yticklabels(), visible=False) if sample_id == 0 and yAxisLabel != '': ax_profile.set_ylabel(yAxisLabel) ax_profile.axes.set_xticks(xticks) ax_profile.axes.set_xticklabels(xtickslabel) ax_list.append(ax_profile) # align the first and last label # such that they don't fall off # the heatmap sides ticks = ax_profile.xaxis.get_major_ticks() ticks[0].label1.set_horizontalalignment('left') ticks[-1].label1.set_horizontalalignment('right') # It turns out that set_ylim only takes np.float64s if yMin: yMin = np.float64(yMin) if yMax: yMax = np.float64(yMax) ax_list[0].set_ylim(yMin, yMax) # reduce the number of yticks by half num_ticks = len(ax_list[0].get_yticks()) yticks = [ax_list[0].get_yticks()[i] for i in range(1, num_ticks, 2)] ax_list[0].set_yticks(yticks) if legend_location != 'none': ax_list[-1].legend(loc=legend_location.replace('-', ' '), ncol=1, prop=fontP, frameon=False, markerscale=0.5) if showColorbar and colorbar_position != 'below': if showSummaryPlot: # we don't want to colorbar to extend # over the profiles and spacer top rows grid_start = 2 else: grid_start = 0 ax = fig.add_subplot(grids[grid_start:, -1]) fig.colorbar(img, cax=ax, alpha=alpha) if box_around_heatmaps: plt.subplots_adjust(wspace=0.10, hspace=0.025, top=0.85, bottom=0, left=0.04, right=0.96) else: # When no box is plotted the space between heatmaps is reduced plt.subplots_adjust(wspace=0.05, hspace=0.01, top=0.85, bottom=0, left=0.04, right=0.96) plt.savefig(outFileName, bbox_inches='tight', pdd_inches=0, dpi=dpi, format=image_format) plt.close()
def __init__(self, hm, out_file_name, plot_title='', y_axis_label='', y_min=None, y_max=None, averagetype='median', reference_point_label='TSS', start_label='TSS', end_label="TES", plot_height=7, plot_width=11, per_group=False, plot_type='simple', image_format=None, color_list=None, legend_location='auto', plots_per_row=8): """ Using the hm matrix, makes a line plot either per group or per sample using the specified parameters. Args: hm: heatmapper object out_file_name: string plot_title: string y_axis_label: list y_min: int y_max: int averagetype: mean, sum, median reference_point_label: string start_label: string end_label: string plot_height: in cm plot_width: in cm per_group: bool plot_type: string image_format: string color_list: list legend_location: plots_per_row: int Returns: """ self.hm = hm self.out_file_name = out_file_name self.plot_title = plot_title self.y_axis_label = y_axis_label self.y_min = y_min self.y_max = y_max self.averagetype = averagetype self.reference_point_label = reference_point_label self.start_label = start_label self.end_label = end_label self.plot_height = plot_height self.plot_width = plot_width self.per_group = per_group self.plot_type = plot_type self.image_format = image_format self.color_list = color_list self.legend_location = legend_location self.plots_per_row = plots_per_row # decide how many plots are needed if self.per_group: self.numplots = self.hm.matrix.get_num_groups() self.numlines = self.hm.matrix.get_num_samples() else: self.numplots = self.hm.matrix.get_num_samples() self.numlines = self.hm.matrix.get_num_groups() if self.numplots > self.plots_per_row: rows = np.ceil(self.numplots / self.plots_per_row).astype(int) cols = self.plots_per_row else: rows = 1 cols = self.numplots self.grids = gridspec.GridSpec(rows, cols) plt.rcParams['font.size'] = 10.0 self.font_p = FontProperties() self.font_p.set_size('small') # convert cm values to inches plot_height_inches = rows * self.cm2inch(self.plot_height)[0] self.fig = plt.figure(figsize=self.cm2inch(cols * self.plot_width, rows * self.plot_height)) self.fig.suptitle(self.plot_title, y=(1 - (0.06 / plot_height_inches))) self.xticks, self.xtickslabel = getProfileTicks(self.hm, self.reference_point_label, self.start_label, self.end_label)
def plotMatrix(hm, outFileName, colorMapDict={'colorMap': ['binary'], 'missingDataColor': 'black', 'alpha': 1.0}, plotTitle='', xAxisLabel='', yAxisLabel='', regionsLabel='', zMin=None, zMax=None, yMin=None, yMax=None, averageType='median', reference_point_label='TSS', startLabel='TSS', endLabel="TES", heatmapHeight=25, heatmapWidth=7.5, perGroup=False, whatToShow='plot, heatmap and colorbar', image_format=None, legend_location='upper-left', box_around_heatmaps=True, dpi=200): matrix_flatten = None if zMin is None: matrix_flatten = hm.matrix.flatten() # try to avoid outliers by using np.percentile zMin = np.percentile(matrix_flatten, 1.0) if np.isnan(zMin): zMin = [None] else: zMin = [zMin] # convert to list to support multiple entries if zMax is None: if matrix_flatten is None: matrix_flatten = hm.matrix.flatten() # try to avoid outliers by using np.percentile zMax = np.percentile(matrix_flatten, 98.0) if np.isnan(zMax) or zMax <= zMin[0]: zMax = [None] else: zMax = [zMax] if yMin is None: yMin = [None] if yMax is None: yMax = [None] if not isinstance(yMin, list): yMin = [yMin] if not isinstance(yMax, list): yMax = [yMax] plt.rcParams['font.size'] = 8.0 fontP = FontProperties() showSummaryPlot = False showColorbar = False if whatToShow == 'plot and heatmap': showSummaryPlot = True elif whatToShow == 'heatmap and colorbar': showColorbar = True elif whatToShow == 'plot, heatmap and colorbar': showSummaryPlot = True showColorbar = True # colormap for the heatmap if colorMapDict['colorMap']: cmap = [] for color_map in colorMapDict['colorMap']: cmap.append(plt.get_cmap(color_map)) cmap[-1].set_bad(colorMapDict['missingDataColor']) # nans are printed using this color if colorMapDict['colorList'] and len(colorMapDict['colorList']) > 0: # make a cmap for each color list given cmap = [] for color_list in colorMapDict['colorList']: cmap.append(matplotlib.colors.LinearSegmentedColormap.from_list( 'my_cmap', color_list.replace(' ', '').split(","), N=colorMapDict['colorNumber'])) cmap[-1].set_bad(colorMapDict['missingDataColor']) # nans are printed using this color if len(cmap) > 1 or len(zMin) > 1 or len(zMax) > 1: # position color bar below heatmap when more than one # heatmap color is given colorbar_position = 'below' else: colorbar_position = 'side' grids = prepare_layout(hm.matrix, (heatmapWidth, heatmapHeight), showSummaryPlot, showColorbar, perGroup, colorbar_position) # figsize: w,h tuple in inches figwidth = heatmapWidth / 2.54 figheight = heatmapHeight / 2.54 if showSummaryPlot: # the summary plot ocupies a height # equal to the fig width figheight += figwidth numsamples = hm.matrix.get_num_samples() if perGroup: num_cols = hm.matrix.get_num_groups() else: num_cols = numsamples total_figwidth = figwidth * num_cols if showColorbar: if colorbar_position == 'below': figheight += 1 / 2.54 else: total_figwidth += 1 / 2.54 fig = plt.figure(figsize=(total_figwidth, figheight)) xticks, xtickslabel = getProfileTicks(hm, reference_point_label, startLabel, endLabel) xticks_heat, xtickslabel_heat = get_heatmap_ticks(hm, reference_point_label, startLabel, endLabel) fig.suptitle(plotTitle, y=1 - (0.06 / figheight)) # color map for the summary plot (profile) on top of the heatmap cmap_plot = plt.get_cmap('jet') numgroups = hm.matrix.get_num_groups() if perGroup: color_list = cmap_plot(np.arange(hm.matrix.get_num_samples()) / hm.matrix.get_num_samples()) else: color_list = cmap_plot(np.arange(numgroups) / numgroups) alpha = colorMapDict['alpha'] # check if matrix is reference-point based using the upstream >0 value # and is sorted by region length. If this is # the case, prepare the data to plot a border at the regions end if hm.parameters['upstream'] > 0 and \ hm.matrix.sort_using == 'region_length' and \ hm.matrix.sort_method != 'no': _regions = hm.matrix.get_regions() regions_length_in_bins = [] for _group in _regions: _reg_len = [] for ind_reg in _group: if isinstance(ind_reg, dict): _len = ind_reg['end'] - ind_reg['start'] else: _len = sum([x[1] - x[0] for x in ind_reg[1]]) _reg_len.append((hm.parameters['upstream'] + _len) / hm.parameters['bin size']) regions_length_in_bins.append(_reg_len) else: regions_length_in_bins = None # plot the profiles on top of the heatmaps if showSummaryPlot: if perGroup: iterNum = numgroups iterNum2 = hm.matrix.get_num_samples() else: iterNum = hm.matrix.get_num_samples() iterNum2 = numgroups ax_list = addProfilePlot(hm, plt, fig, grids, iterNum, iterNum2, perGroup, averageType, xticks, xtickslabel, yAxisLabel, color_list, yMin, yMax, None, None, colorbar_position) if len(yMin) > 1 or len(yMax) > 1: # replot with a tight layout import matplotlib.tight_layout as tl specList = tl.get_subplotspec_list(fig.axes, grid_spec=grids) renderer = tl.get_renderer(fig) kwargs = tl.get_tight_layout_figure(fig, fig.axes, specList, renderer, pad=1.08) for ax in ax_list: fig.delaxes(ax) ax_list = addProfilePlot(hm, plt, fig, grids, iterNum, iterNum2, perGroup, averageType, xticks, xtickslabel, yAxisLabel, color_list, yMin, yMax, kwargs['wspace'], kwargs['hspace'], colorbar_position) # reduce the number of yticks by half num_ticks = len(ax_list[0].get_yticks()) yticks = [ax_list[0].get_yticks()[i] for i in range(1, num_ticks, 2)] ax_list[0].set_yticks(yticks) if legend_location != 'none': ax_list[-1].legend(loc=legend_location.replace('-', ' '), ncol=1, prop=fontP, frameon=False, markerscale=0.5) first_group = 0 # helper variable to place the title per sample/group for sample in range(hm.matrix.get_num_samples()): sample_idx = sample for group in range(numgroups): group_idx = group # add the respective profile to the # summary plot sub_matrix = hm.matrix.get_matrix(group, sample) if showSummaryPlot: if perGroup: sample_idx = sample + 2 # plot + spacer else: group += 2 # plot + spacer first_group = 1 if perGroup: ax = fig.add_subplot(grids[sample_idx, group]) # the remainder (%) is used to iterate # over the available color maps (cmap). # if the user only provided, lets say two # and there are 10 groups, colormaps they are reused every # two groups. cmap_idx = group_idx % len(cmap) zmin_idx = group_idx % len(zMin) zmax_idx = group_idx % len(zMax) else: ax = fig.add_subplot(grids[group, sample]) # see above for the use of '%' cmap_idx = sample % len(cmap) zmin_idx = sample % len(zMin) zmax_idx = sample % len(zMax) if group == first_group and not showSummaryPlot and not perGroup: title = hm.matrix.sample_labels[sample] ax.set_title(title) if box_around_heatmaps is False: # Turn off the boxes around the individual heatmaps ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) ax.spines['bottom'].set_visible(False) ax.spines['left'].set_visible(False) rows, cols = sub_matrix['matrix'].shape interpolation_type = None if rows >= 1000 and cols >= 200 else 'nearest' img = ax.imshow(sub_matrix['matrix'], aspect='auto', interpolation=interpolation_type, origin='upper', vmin=zMin[zmin_idx], vmax=zMax[zmax_idx], cmap=cmap[cmap_idx], alpha=alpha, extent=[0, cols, rows, 0]) img.set_rasterized(True) # plot border at the end of the regions # if ordered by length if regions_length_in_bins is not None: x_lim = ax.get_xlim() y_lim = ax.get_ylim() ax.plot(regions_length_in_bins[group_idx], np.arange(len(regions_length_in_bins[group_idx])), '--', color='black', linewidth=0.5, dashes=(3, 2)) ax.set_xlim(x_lim) ax.set_ylim(y_lim) if perGroup: ax.axes.set_xlabel(sub_matrix['group']) if sample < hm.matrix.get_num_samples() - 1: ax.axes.get_xaxis().set_visible(False) else: ax.axes.get_xaxis().set_visible(False) ax.axes.set_xlabel(xAxisLabel) ax.axes.set_yticks([]) if perGroup and group == 0: ax.axes.set_ylabel(sub_matrix['sample']) elif not perGroup and sample == 0: ax.axes.set_ylabel(sub_matrix['group']) # add labels to last block in a column if (perGroup and sample == numsamples - 1) or \ (not perGroup and group_idx == numgroups - 1): # add xticks to the bottom heatmap (last group) ax.axes.get_xaxis().set_visible(True) if np.ceil(max(xticks_heat)) != float(sub_matrix['matrix'].shape[1]): tickscale = float(sub_matrix['matrix'].shape[1]) / max(xticks_heat) xticks_heat_use = [x * tickscale for x in xticks_heat] ax.axes.set_xticks(xticks_heat_use) else: ax.axes.set_xticks(xticks_heat) ax.axes.set_xticklabels(xtickslabel_heat, size=8) # align the first and last label # such that they don't fall off # the heatmap sides ticks = ax.xaxis.get_major_ticks() ticks[0].label1.set_horizontalalignment('left') ticks[-1].label1.set_horizontalalignment('right') ax.get_xaxis().set_tick_params( which='both', top='off', direction='out') if showColorbar and colorbar_position == 'below': # draw a colormap per each heatmap below the last block if perGroup: col = group_idx else: col = sample ax = fig.add_subplot(grids[-1, col]) tick_locator = ticker.MaxNLocator(nbins=3) cbar = fig.colorbar(img, cax=ax, alpha=alpha, orientation='horizontal', ticks=tick_locator) labels = cbar.ax.get_xticklabels() ticks = cbar.ax.get_xticks() if ticks[0] == 0: # if the label is at the start of the colobar # move it a bit inside to avoid overlapping # with other labels labels[0].set_horizontalalignment('left') if ticks[-1] == 1: # if the label is at the end of the colobar # move it a bit inside to avoid overlapping # with other labels labels[-1].set_horizontalalignment('right') # cbar.ax.set_xticklabels(labels, rotation=90) if showColorbar and colorbar_position != 'below': if showSummaryPlot: # we don't want to colorbar to extend # over the profiles and spacer top rows grid_start = 2 else: grid_start = 0 ax = fig.add_subplot(grids[grid_start:, -1]) fig.colorbar(img, cax=ax, alpha=alpha) if box_around_heatmaps: plt.subplots_adjust(wspace=0.10, hspace=0.025, top=0.85, bottom=0, left=0.04, right=0.96) else: # When no box is plotted the space between heatmaps is reduced plt.subplots_adjust(wspace=0.05, hspace=0.01, top=0.85, bottom=0, left=0.04, right=0.96) plt.savefig(outFileName, bbox_inches='tight', pdd_inches=0, dpi=dpi, format=image_format) plt.close()
def plotMatrix(hm, outFileName, colorMapDict={ 'colorMap': 'binary', 'missingDataColor': 'black' }, plotTitle='', xAxisLabel='', yAxisLabel='', regionsLabel='', zMin=None, zMax=None, yMin=None, yMax=None, averageType='median', reference_point_label='TSS', startLabel='TSS', endLabel="TES", heatmapHeight=25, heatmapWidth=7.5, perGroup=False, whatToShow='plot, heatmap and colorbar', plotType='simple', image_format=None, legend_location='upper-left'): matrix_flatten = None if zMin is None: matrix_flatten = hm.matrix.flatten() # try to avoid outliers by using np.percentile zMin = np.percentile(matrix_flatten, 1.0) if np.isnan(zMin): zMin = None if zMax is None: if matrix_flatten is None: matrix_flatten = hm.matrix.flatten() # try to avoid outliers by using np.percentile zMax = np.percentile(matrix_flatten, 98.0) if np.isnan(zMax): zMax = None plt.rcParams['font.size'] = 8.0 fontP = FontProperties() # fontP.set_size('small') showSummaryPlot = False showColorbar = False if whatToShow == 'plot and heatmap': showSummaryPlot = True elif whatToShow == 'heatmap and colorbar': showColorbar = True else: showSummaryPlot = True showColorbar = True grids = prepare_layout(hm.matrix, (heatmapWidth, heatmapHeight), showSummaryPlot, showColorbar, perGroup) # figsize: w,h tuple in inches figwidth = heatmapWidth / 2.54 figheight = heatmapHeight / 2.54 if showSummaryPlot: # the summary plot ocupies a height # equal to the fig width figheight += figwidth numsamples = hm.matrix.get_num_samples() total_figwidth = figwidth * numsamples if showColorbar: total_figwidth += 1 / 2.54 fig = plt.figure(figsize=(total_figwidth, figheight)) hm.parameters['upstream'] hm.parameters['downstream'] hm.parameters['body'] hm.parameters['bin size'] xticks, xtickslabel = getProfileTicks(hm, reference_point_label, startLabel, endLabel) xticks_heat, xtickslabel_heat = get_heatmap_ticks(hm, reference_point_label, startLabel, endLabel) fig.suptitle(plotTitle, y=1 - (0.06 / figheight)) # colormap for the heatmap if colorMapDict['colorMap']: cmap = plt.get_cmap(colorMapDict['colorMap']) if colorMapDict['colorList'] and len(colorMapDict['colorList']) > 0: cmap = matplotlib.colors.LinearSegmentedColormap.from_list( 'my_cmap', colorMapDict['colorList'], N=colorMapDict['colorNumber']) # color map for the summary plot (profile) on top of the heatmap cmap_plot = plt.get_cmap('jet') numgroups = hm.matrix.get_num_groups() if perGroup: color_list = cmap_plot( np.arange(hm.matrix.get_num_samples()) / hm.matrix.get_num_samples()) else: color_list = cmap_plot(np.arange(numgroups) / numgroups) cmap.set_bad( colorMapDict['missingDataColor']) # nans are printed using this color # check if matrix is reference-point based using the upstream >0 value # and is sorted by region length. If this is # the case, prepare the data to plot a border at the regions end if hm.parameters['upstream'] > 0 and \ hm.matrix.sort_using == 'region_length' and \ hm.matrix.sort_method != 'no': _regions = hm.matrix.get_regions() regions_length_in_bins = [] for _group in _regions: _reg_len = [] for ind_reg in _group: _len = ind_reg['end'] - ind_reg['start'] _reg_len.append((hm.parameters['upstream'] + _len) / hm.parameters['bin size']) # print hm.parameters['upstream'] + (_len / hm.parameters['bin size']) regions_length_in_bins.append(_reg_len) else: regions_length_in_bins = None first_group = 0 # helper variable to place the title per sample/group for sample in range(hm.matrix.get_num_samples()): sample_idx = sample for group in range(numgroups): group_idx = group # add the respective profile to the # summary plot sub_matrix = hm.matrix.get_matrix(group, sample) if showSummaryPlot: if perGroup: sample_idx = sample + 2 # plot + spacer else: group += 2 # plot + spacer first_group = 1 if perGroup: ax = fig.add_subplot(grids[sample_idx, group]) else: ax = fig.add_subplot(grids[group, sample]) if group == first_group and not showSummaryPlot and not perGroup: title = hm.matrix.sample_labels[sample] ax.set_title(title) rows, cols = sub_matrix['matrix'].shape interpolation_type = 'bicubic' if rows > 200 and \ cols > 1000 else 'nearest' img = ax.imshow(sub_matrix['matrix'], aspect='auto', interpolation=interpolation_type, origin='upper', vmin=zMin, vmax=zMax, cmap=cmap, extent=[0, cols, rows, 0]) # plot border at the end of the regions # if ordered by length if regions_length_in_bins is not None: x_lim = ax.get_xlim() y_lim = ax.get_ylim() ax.plot(regions_length_in_bins[group_idx], np.arange(len(regions_length_in_bins[group_idx])), '--', color='black', linewidth=0.5, dashes=(3, 2)) ax.set_xlim(x_lim) ax.set_ylim(y_lim) if perGroup: ax.axes.set_xlabel(sub_matrix['group']) if sample < hm.matrix.get_num_samples() - 1: ax.axes.get_xaxis().set_visible(False) else: ax.axes.get_xaxis().set_visible(False) ax.axes.set_xlabel(xAxisLabel) ax.axes.set_yticks([]) if perGroup and group == 0: ax.axes.set_ylabel(sub_matrix['sample']) elif not perGroup and sample == 0: ax.axes.set_ylabel(sub_matrix['group']) # add xticks to the bottom heatmap (last group) ax.axes.get_xaxis().set_visible(True) ax.axes.set_xticks(xticks_heat) ax.axes.set_xticklabels(xtickslabel_heat, size=8) # align the first and last label # such that they don't fall off # the heatmap sides ticks = ax.xaxis.get_major_ticks() ticks[0].label1.set_horizontalalignment('left') ticks[-1].label1.set_horizontalalignment('right') ax.get_xaxis().set_tick_params(which='both', top='off', direction='out') # plot the profiles on top of the heatmaps if showSummaryPlot: ax_list = [] if perGroup: iterNum = numgroups else: iterNum = hm.matrix.get_num_samples() # plot each of the profiles for sample_id in range(iterNum): if perGroup: title = hm.matrix.group_labels[sample_id] else: title = hm.matrix.sample_labels[sample_id] if sample_id > 0: ax_profile = fig.add_subplot(grids[0, sample_id], sharey=ax_list[0]) else: ax_profile = fig.add_subplot(grids[0, sample_id]) ax_profile.set_title(title) if perGroup: iterNum2 = hm.matrix.get_num_samples() else: iterNum2 = numgroups for group in range(iterNum2): if perGroup: sub_matrix = hm.matrix.get_matrix(sample_id, group) line_label = sub_matrix['sample'] else: sub_matrix = hm.matrix.get_matrix(group, sample_id) line_label = sub_matrix['group'] plot_single(ax_profile, sub_matrix['matrix'], averageType, color_list[group], line_label, plot_type='simple') if sample_id > 0: plt.setp(ax_profile.get_yticklabels(), visible=False) if sample_id == 0 and yAxisLabel != '': ax_profile.set_ylabel(yAxisLabel) ax_profile.axes.set_xticks(xticks) ax_profile.axes.set_xticklabels(xtickslabel) ax_list.append(ax_profile) # align the first and last label # such that they don't fall off # the heatmap sides ticks = ax_profile.xaxis.get_major_ticks() ticks[0].label1.set_horizontalalignment('left') ticks[-1].label1.set_horizontalalignment('right') # reduce the number of yticks by half num_ticks = len(ax_list[0].get_yticks()) yticks = [ax_list[0].get_yticks()[i] for i in range(1, num_ticks, 2)] ax_list[0].set_yticks(yticks) ax_list[0].set_ylim(yMin, yMax) if legend_location != 'none': ax_list[-1].legend(loc=legend_location.replace('-', ' '), ncol=1, prop=fontP, frameon=False, markerscale=0.5) if showColorbar: if showSummaryPlot: # we dont want to colorbar to extend # over the profiles row grid_start = 2 else: grid_start = 0 ax = fig.add_subplot(grids[grid_start:, -1]) fig.colorbar(img, cax=ax) plt.subplots_adjust(wspace=0.05, hspace=0.025, top=0.85, bottom=0, left=0.04, right=0.96) plt.savefig(outFileName, bbox_inches='tight', pdd_inches=0, dpi=200, format=image_format)