def plot(self, profile, statsResults): if len(profile.profileDict) <= 0: self.emptyAxis() return # *** Colour of plot elements axesColour = str(self.preferences['Axes colour'].name()) profile1Colour = str(self.preferences['Sample 1 colour'].name()) profile2Colour = str(self.preferences['Sample 2 colour'].name()) # *** Determine most abundant features features = [] field1 = [] field2 = [] parentField1 = [] parentField2 = [] tables = profile.getLabeledTables() for table in tables: feature, seq1, seq2, parentSeq1, parentSeq2 = table field1.append(seq1) field2.append(seq2) parentField1.append(parentSeq1) parentField2.append(parentSeq2) features.append(feature) fields = zip(field1, field2, parentField1, parentField2, features) fields.sort(reverse = True) field1, field2, parentField1, parentField2, features = zip(*fields) if len(field1) > self.numFeaturesToShow: field1 = list(field1[0:self.numFeaturesToShow]) field2 = list(field2[0:self.numFeaturesToShow]) parentField1 = parentField1[0:self.numFeaturesToShow] parentField2 = parentField2[0:self.numFeaturesToShow] features = list(features[0:self.numFeaturesToShow]) else: field1 = list(field1) field2 = list(field2) features = list(features) # *** Create lists for each quantity of interest and calculate CIs wilsonCI = WilsonCI() confInter1 = [] confInter2 = [] if self.fieldToPlot == 'Number of sequences': for i in xrange(0, len(field1)): if self.bShowCIs: lowerCI, upperCI, p = wilsonCI.run(field1[i], parentField1[i], 0.95, 1.96) confInter1.append(max((p - lowerCI)*parentField1[i], 0)) lowerCI, upperCI, p = wilsonCI.run(field2[i], parentField2[i], 0.95, 1.96) confInter2.append(max((p - lowerCI)*parentField2[i], 0)) else: confInter1.append(0) confInter2.append(0) elif self.fieldToPlot == 'Proportion of sequences (%)': for i in xrange(0, len(field1)): if self.bShowCIs: lowerCI, upperCI, p = wilsonCI.run(field1[i], parentField1[i], 0.95, 1.96) confInter1.append(max((p - lowerCI)*100, 0)) lowerCI, upperCI, p = wilsonCI.run(field2[i], parentField2[i], 0.95, 1.96) confInter2.append(max((p - lowerCI)*100, 0)) else: confInter1.append(0) confInter2.append(0) field1[i] = float(field1[i])*100 / max(parentField1[i],1) field2[i] = float(field2[i])*100 / max(parentField2[i],1) # *** Truncate feature labels highlightedFeatures = list(self.preferences['Highlighted sample features']) truncatedNames = list(features) if self.preferences['Truncate feature names']: length = self.preferences['Length of truncated feature names'] for i in xrange(0, len(truncatedNames)): if len(truncatedNames[i]) > length+3: truncatedNames[i] = truncatedNames[i][0:length] + '...' for i in xrange(0, len(highlightedFeatures)): if len(highlightedFeatures[i]) > length+3: highlightedFeatures[i] = highlightedFeatures[i][0:length] + '...' # *** Find longest label longestLabelLen = 0 for i in xrange(0, len(truncatedNames)): if len(truncatedNames[i]) > longestLabelLen: longestLabelLen = len(truncatedNames[i]) longestLabel = truncatedNames[i] # *** Set figure size self.fig.clear() figWidth = self.figColWidth*len(features) figHeight = self.figHeight if figWidth > 256 or figHeight > 256: QtGui.QApplication.instance().setOverrideCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) self.emptyAxis() QtGui.QMessageBox.question(self, 'Excessively large plot', 'The resulting plot is too large to display.') QtGui.QApplication.instance().restoreOverrideCursor() return self.fig.set_size_inches(figWidth, figHeight) xLabelBounds, yLabelBounds = self.labelExtents([longestLabel], 8, 90, ['%.0f' % max(max(field1), max(field2))], 8, 0) yLabelOffset = 0.3 padding = 0.15 # inches newFigWidth = figWidth + yLabelBounds.width / figWidth + 2*padding + yLabelOffset self.fig.set_size_inches(newFigWidth, figHeight) xOffsetFigSpace = yLabelBounds.width + padding/newFigWidth + yLabelOffset / newFigWidth yOffsetFigSpace = xLabelBounds.height + padding/figHeight axesBar = self.fig.add_axes([xOffsetFigSpace, yOffsetFigSpace, 1.0 - xOffsetFigSpace - padding/newFigWidth, 1.0 - yOffsetFigSpace - padding/figHeight]) # *** Plot data colWidth = self.figColWidth barWidth = (colWidth*(self.barWidth/100.0)) / 2 if self.bShowCIs == True: rects1 = axesBar.bar(np.arange(len(features))*colWidth, field1, width=barWidth, color=profile1Colour, yerr=confInter1, ecolor='black', capsize=self.endCapSize) rects2 = axesBar.bar(np.arange(len(features))*colWidth + barWidth, field2, width=barWidth, color=profile2Colour, yerr=confInter2, ecolor='black', capsize=self.endCapSize) else: rects1 = axesBar.bar(np.arange(len(features))*colWidth, field1, width=barWidth, color=profile1Colour) rects2 = axesBar.bar(np.arange(len(features))*colWidth + barWidth, field2, width=barWidth, color=profile2Colour) axesBar.set_xticks(np.arange(len(features))*colWidth + barWidth) axesBar.set_xlim([0, (len(features)-1.0)*colWidth + 2*barWidth + 0.1]) axesBar.set_ylim(0, axesBar.get_ylim()[1]) axesBar.set_xticklabels(truncatedNames, size=8) axesBar.set_ylabel(self.fieldToPlot, fontsize=8) # *** Mark significant features if self.bShowPvalue and statsResults.profile != None: offset = axesBar.get_ylim()[1]*0.02 x = [] y = [] for i in xrange(0, len(features)): pValue = float(statsResults.getFeatureStatistic(features[i], 'pValuesCorrected')) if pValue <= self.pValueThreshold: x.append(i*colWidth + barWidth) y.append(max(field1[i], field2[i]) + offset) axesBar.plot(x, y, color='k', linestyle='', marker='*', markeredgecolor='k', ms = 3) # *** Prettify plot if self.legendPos != -1: legend = axesBar.legend([rects1[0], rects2[0]], (profile.sampleNames[0], profile.sampleNames[1]), loc=self.legendPos) legend.get_frame().set_linewidth(0) for label in axesBar.get_xticklabels(): label.set_rotation(90) if label.get_text() in highlightedFeatures: label.set_color('red') for a in axesBar.yaxis.majorTicks: a.tick1On=False a.tick2On=False for a in axesBar.xaxis.majorTicks: a.tick1On=False a.tick2On=False for loc, spine in axesBar.spines.iteritems(): if loc in ['right','top']: spine.set_color('none') else: spine.set_color(axesColour) self.updateGeometry() self.draw()
def plot(self, profile): if len(profile.profileDict) <= 0: self.emptyAxis() return if len(profile.profileDict) > 1000: QtGui.QApplication.instance().setOverrideCursor( QtGui.QCursor(QtCore.Qt.ArrowCursor)) reply = QtGui.QMessageBox.question( self, 'Continue?', 'Profile contains ' + str(len(profile.profileDict)) + ' features. ' + 'It may take several seconds to generate this plot. Exploring the data at a higher hierarchy level is recommended. ' + 'Do you wish to continue?', QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) QtGui.QApplication.instance().restoreOverrideCursor() if reply == QtGui.QMessageBox.No: self.emptyAxis() return # *** Colour of plot elements profile1Colour = str(self.preferences['Sample 1 colour'].name()) profile2Colour = str(self.preferences['Sample 2 colour'].name()) # *** Set sample names if self.sampleName1 == '' and self.sampleName2 == '': self.sampleName1 = profile.sampleNames[0] self.sampleName2 = profile.sampleNames[1] # *** Create lists for each quantity of interest and calculate CIs wilsonCI = WilsonCI() zCoverage = inverseNormalCDF(0.95) confInter1 = [] confInter2 = [] tables = profile.getLabeledTables() features = [] field1 = [] field2 = [] for table in tables: feature, seq1, seq2, parentSeq1, parentSeq2 = table features.append(feature) field1.append(float(seq1) * 100 / max(parentSeq1, 1)) field2.append(float(seq2) * 100 / max(parentSeq2, 1)) if self.bShowCIs: lowerCI, upperCI, p = wilsonCI.run(seq1, parentSeq1, 0.95, zCoverage) confInter1.append( [max(lowerCI * 100, 0), min(upperCI * 100, 100)]) lowerCI, upperCI, p = wilsonCI.run(seq2, parentSeq2, 0.95, zCoverage) confInter2.append( [max(lowerCI * 100, 0), min(upperCI * 100, 100)]) # *** Set figure size self.fig.clear() self.fig.set_size_inches(self.figWidth, self.figHeight) if self.bShowHistograms: histogramSizeX = self.histogramSize / self.figWidth histogramSizeY = self.histogramSize / self.figHeight else: histogramSizeX = 0.0 histogramSizeY = 0.0 padding = 0.1 # inches xOffsetFigSpace = (0.4 + padding) / self.figWidth yOffsetFigSpace = (0.3 + padding) / self.figHeight axesScatter = self.fig.add_axes([ xOffsetFigSpace, yOffsetFigSpace, 1.0 - xOffsetFigSpace - histogramSizeX - (2 * padding) / self.figWidth, 1.0 - yOffsetFigSpace - histogramSizeY - (2 * padding) / self.figHeight ]) if self.bShowHistograms: axesTopHistogram = self.fig.add_axes([ xOffsetFigSpace, 1.0 - histogramSizeY - padding / self.figHeight, 1.0 - xOffsetFigSpace - histogramSizeX - (2 * padding) / self.figWidth, histogramSizeY ]) axesRightHistogram = self.fig.add_axes([ 1.0 - histogramSizeX - padding / self.figWidth, yOffsetFigSpace, histogramSizeX, 1.0 - yOffsetFigSpace - histogramSizeY - (2 * padding) / self.figHeight ]) # *** Handle mouse events tooltips = [] for i in xrange(0, len(field1)): tooltip = features[i] + '\n\n' tooltip += 'Sequences in ' + self.sampleName1 + ': ' + str( tables[i][1]) + '\n' tooltip += 'Sequences in ' + self.sampleName2 + ': ' + str( tables[i][2]) + '\n\n' tooltip += (self.sampleName1 + ' percentage: %.3f' % field1[i]) + '\n' tooltip += (self.sampleName2 + ' percentage: %.3f' % field2[i]) + '\n\n' tooltip += 'Difference between proportions (%): ' + ( '%.3f' % (field1[i] - field2[i])) + '\n' if field2[i] != 0: tooltip += 'Ratio of proportions: %.3f' % (field1[i] / field2[i]) else: tooltip += 'Ratio of proportions: undefined' tooltips.append(tooltip) self.plotEventHandler = PlotEventHandler(field1, field2, tooltips) self.mouseEventCallback(self.plotEventHandler) # *** Plot data # set visual properties of all points colours = [] highlightedField1 = [] highlightedField2 = [] highlighColours = [] for i in xrange(0, len(field1)): if field1[i] > field2[i]: colours.append(profile1Colour) else: colours.append(profile2Colour) if features[i] in self.preferences[ 'Selected exploratory features']: highlightedField1.append(field1[i]) highlightedField2.append(field2[i]) highlighColours.append(colours[i]) # scatter plot axesScatter.scatter(field1, field2, c=colours, zorder=5) if len(highlightedField1) > 0: axesScatter.scatter(highlightedField1, highlightedField2, c=highlighColours, edgecolors='red', linewidth=2, zorder=10) # plot CIs if self.bShowCIs: ciLinesX = [ Line2D([confInter1[i][0], confInter1[i][1]], [field2[i], field2[i]], color='black') for i in xrange(0, len(field1)) ] ciLinesY = [ Line2D([field1[i], field1[i]], [confInter2[i][0], confInter2[i][1]], color='black') for i in xrange(0, len(field1)) ] for i in xrange(0, len(ciLinesX)): e = ciLinesX[i] axesScatter.add_artist(e) e.set_clip_box(axesScatter.bbox) for i in xrange(0, len(ciLinesY)): e = ciLinesY[i] axesScatter.add_artist(e) e.set_clip_box(axesScatter.bbox) # plot y=x line maxProportion = max(max(field1), max(field2)) * 1.05 axesScatter.plot([0, maxProportion], [0, maxProportion], color='gray', linestyle='dashed', marker='', zorder=1) axesScatter.set_xlabel(self.sampleName1 + ' (%)', fontsize=8) axesScatter.set_ylabel(self.sampleName2 + ' (%)', fontsize=8) axesScatter.set_xlim(0, maxProportion) axesScatter.set_ylim(0, maxProportion) # *** Prettify scatter plot for label in axesScatter.get_xticklabels(): label.set_size(8) for label in axesScatter.get_yticklabels(): label.set_size(8) # plot histograms if self.bShowHistograms: # plot top histogram axesTopHistogram.xaxis.set_major_formatter(NullFormatter()) pdf, bins, patches = axesTopHistogram.hist( field1, bins=self.numBins, facecolor=profile1Colour) axesTopHistogram.set_xlim(axesScatter.get_xlim()) axesTopHistogram.set_yticks([0, max(pdf)]) # plot right histogram axesRightHistogram.yaxis.set_major_formatter(NullFormatter()) pdf, bins, patches = axesRightHistogram.hist( field2, bins=self.numBins, orientation='horizontal', facecolor=profile2Colour) axesRightHistogram.set_ylim(axesScatter.get_ylim()) axesRightHistogram.set_xticks([0, max(pdf)]) # *** Prettify histogram plot for label in axesTopHistogram.get_xticklabels(): label.set_size(8) for label in axesTopHistogram.get_yticklabels(): label.set_size(8) for label in axesRightHistogram.get_xticklabels(): label.set_size(8) for label in axesRightHistogram.get_yticklabels(): label.set_size(8) for a in axesTopHistogram.yaxis.majorTicks: a.tick1On = True a.tick2On = False for a in axesTopHistogram.xaxis.majorTicks: a.tick1On = True a.tick2On = False for loc, spine in axesTopHistogram.spines.iteritems(): if loc in ['right', 'top']: spine.set_color('none') for a in axesRightHistogram.yaxis.majorTicks: a.tick1On = True a.tick2On = False for a in axesRightHistogram.xaxis.majorTicks: a.tick1On = True a.tick2On = False for loc, spine in axesRightHistogram.spines.iteritems(): if loc in ['right', 'top']: spine.set_color('none') self.updateGeometry() self.draw()
def plot(self, profile, statsResults): if len(profile.profileDict) <= 0: self.emptyAxis() return # *** Colour of plot elements axesColour = str(self.preferences['Axes colour'].name()) profile1Colour = str(self.preferences['Sample 1 colour'].name()) profile2Colour = str(self.preferences['Sample 2 colour'].name()) # *** Determine most abundant features features = [] field1 = [] field2 = [] parentField1 = [] parentField2 = [] tables = profile.getLabeledTables() for table in tables: feature, seq1, seq2, parentSeq1, parentSeq2 = table field1.append(seq1) field2.append(seq2) parentField1.append(parentSeq1) parentField2.append(parentSeq2) features.append(feature) fields = zip(field1, field2, parentField1, parentField2, features) fields.sort(reverse=True) field1, field2, parentField1, parentField2, features = zip(*fields) if len(field1) > self.numFeaturesToShow: field1 = list(field1[0:self.numFeaturesToShow]) field2 = list(field2[0:self.numFeaturesToShow]) parentField1 = parentField1[0:self.numFeaturesToShow] parentField2 = parentField2[0:self.numFeaturesToShow] features = list(features[0:self.numFeaturesToShow]) else: field1 = list(field1) field2 = list(field2) features = list(features) # *** Create lists for each quantity of interest and calculate CIs wilsonCI = WilsonCI() confInter1 = [] confInter2 = [] if self.fieldToPlot == 'Number of sequences': for i in xrange(0, len(field1)): if self.bShowCIs: lowerCI, upperCI, p = wilsonCI.run(field1[i], parentField1[i], 0.95, 1.96) confInter1.append(max((p - lowerCI) * parentField1[i], 0)) lowerCI, upperCI, p = wilsonCI.run(field2[i], parentField2[i], 0.95, 1.96) confInter2.append(max((p - lowerCI) * parentField2[i], 0)) else: confInter1.append(0) confInter2.append(0) elif self.fieldToPlot == 'Proportion of sequences (%)': for i in xrange(0, len(field1)): if self.bShowCIs: lowerCI, upperCI, p = wilsonCI.run(field1[i], parentField1[i], 0.95, 1.96) confInter1.append(max((p - lowerCI) * 100, 0)) lowerCI, upperCI, p = wilsonCI.run(field2[i], parentField2[i], 0.95, 1.96) confInter2.append(max((p - lowerCI) * 100, 0)) else: confInter1.append(0) confInter2.append(0) field1[i] = float(field1[i]) * 100 / max(parentField1[i], 1) field2[i] = float(field2[i]) * 100 / max(parentField2[i], 1) # *** Truncate feature labels highlightedFeatures = list( self.preferences['Highlighted sample features']) truncatedNames = list(features) if self.preferences['Truncate feature names']: length = self.preferences['Length of truncated feature names'] for i in xrange(0, len(truncatedNames)): if len(truncatedNames[i]) > length + 3: truncatedNames[i] = truncatedNames[i][0:length] + '...' for i in xrange(0, len(highlightedFeatures)): if len(highlightedFeatures[i]) > length + 3: highlightedFeatures[ i] = highlightedFeatures[i][0:length] + '...' # *** Find longest label longestLabelLen = 0 for i in xrange(0, len(truncatedNames)): if len(truncatedNames[i]) > longestLabelLen: longestLabelLen = len(truncatedNames[i]) longestLabel = truncatedNames[i] # *** Set figure size self.fig.clear() figWidth = self.figColWidth * len(features) figHeight = self.figHeight if figWidth > 256 or figHeight > 256: QtGui.QApplication.instance().setOverrideCursor( QtGui.QCursor(QtCore.Qt.ArrowCursor)) self.emptyAxis() QtGui.QMessageBox.question( self, 'Excessively large plot', 'The resulting plot is too large to display.') QtGui.QApplication.instance().restoreOverrideCursor() return self.fig.set_size_inches(figWidth, figHeight) xLabelBounds, yLabelBounds = self.labelExtents( [longestLabel], 8, 90, ['%.0f' % max(max(field1), max(field2))], 8, 0) yLabelOffset = 0.3 padding = 0.15 # inches newFigWidth = figWidth + yLabelBounds.width / figWidth + 2 * padding + yLabelOffset self.fig.set_size_inches(newFigWidth, figHeight) xOffsetFigSpace = yLabelBounds.width + padding / newFigWidth + yLabelOffset / newFigWidth yOffsetFigSpace = xLabelBounds.height + padding / figHeight axesBar = self.fig.add_axes([ xOffsetFigSpace, yOffsetFigSpace, 1.0 - xOffsetFigSpace - padding / newFigWidth, 1.0 - yOffsetFigSpace - padding / figHeight ]) # *** Plot data colWidth = self.figColWidth barWidth = (colWidth * (self.barWidth / 100.0)) / 2 if self.bShowCIs == True: rects1 = axesBar.bar(np.arange(len(features)) * colWidth, field1, width=barWidth, color=profile1Colour, yerr=confInter1, ecolor='black', capsize=self.endCapSize) rects2 = axesBar.bar(np.arange(len(features)) * colWidth + barWidth, field2, width=barWidth, color=profile2Colour, yerr=confInter2, ecolor='black', capsize=self.endCapSize) else: rects1 = axesBar.bar(np.arange(len(features)) * colWidth, field1, width=barWidth, color=profile1Colour) rects2 = axesBar.bar(np.arange(len(features)) * colWidth + barWidth, field2, width=barWidth, color=profile2Colour) axesBar.set_xticks(np.arange(len(features)) * colWidth + barWidth) axesBar.set_xlim( [0, (len(features) - 1.0) * colWidth + 2 * barWidth + 0.1]) axesBar.set_ylim(0, axesBar.get_ylim()[1]) axesBar.set_xticklabels(truncatedNames, size=8) axesBar.set_ylabel(self.fieldToPlot, fontsize=8) # *** Mark significant features if self.bShowPvalue and statsResults.profile != None: offset = axesBar.get_ylim()[1] * 0.02 x = [] y = [] for i in xrange(0, len(features)): pValue = float( statsResults.getFeatureStatistic(features[i], 'pValuesCorrected')) if pValue <= self.pValueThreshold: x.append(i * colWidth + barWidth) y.append(max(field1[i], field2[i]) + offset) axesBar.plot(x, y, color='k', linestyle='', marker='*', markeredgecolor='k', ms=3) # *** Prettify plot if self.legendPos != -1: legend = axesBar.legend( [rects1[0], rects2[0]], (profile.sampleNames[0], profile.sampleNames[1]), loc=self.legendPos) legend.get_frame().set_linewidth(0) for label in axesBar.get_xticklabels(): label.set_rotation(90) if label.get_text() in highlightedFeatures: label.set_color('red') for a in axesBar.yaxis.majorTicks: a.tick1On = False a.tick2On = False for a in axesBar.xaxis.majorTicks: a.tick1On = False a.tick2On = False for loc, spine in axesBar.spines.iteritems(): if loc in ['right', 'top']: spine.set_color('none') else: spine.set_color(axesColour) self.updateGeometry() self.draw()
def plot(self, profile): if len(profile.profileDict) <= 0: self.emptyAxis() return if len(profile.profileDict) > 200: QtGui.QApplication.instance().setOverrideCursor( QtGui.QCursor(QtCore.Qt.ArrowCursor)) reply = QtGui.QMessageBox.question( self, 'Continue?', 'Profile contains ' + str(len(profile.profileDict)) + ' features. ' + 'It may take several seconds to generate this plot. Exploring the data at a higher hierarchy level is recommended. ' + 'Do you wish to continue?', QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) QtGui.QApplication.instance().restoreOverrideCursor() if reply == QtGui.QMessageBox.No: self.emptyAxis() return # *** Colour of plot elements profile1Colour = str(self.preferences['Sample 1 colour'].name()) profile2Colour = str(self.preferences['Sample 2 colour'].name()) # *** Set sample names if self.sampleName1 == '' and self.sampleName2 == '': self.sampleName1 = profile.sampleNames[0] self.sampleName2 = profile.sampleNames[1] # *** Create lists for each quantity of interest and calculate CIs wilsonCI = WilsonCI() zCoverage = inverseNormalCDF(0.95) confInter1 = [] confInter2 = [] tables = profile.getLabeledTables() features = [] field1 = [] field2 = [] if self.fieldToPlot == 'Number of sequences': for table in tables: feature, seq1, seq2, parentSeq1, parentSeq2 = table features.append(feature) field1.append(seq1) field2.append(seq2) if self.bShowCIs: lowerCI, upperCI, p = wilsonCI.run(seq1, parentSeq1, 0.95, zCoverage) confInter1.append(max((p - lowerCI) * parentSeq1, 0)) lowerCI, upperCI, p = wilsonCI.run(seq2, parentSeq2, 0.95, zCoverage) confInter2.append(max((p - lowerCI) * parentSeq2, 0)) else: confInter1.append(0) confInter2.append(0) elif self.fieldToPlot == 'Proportion of sequences': for table in tables: feature, seq1, seq2, parentSeq1, parentSeq2 = table features.append(feature) field1.append(float(seq1) * 100 / max(parentSeq1, 1)) field2.append(float(seq2) * 100 / max(parentSeq2, 1)) if self.bShowCIs: lowerCI, upperCI, p = wilsonCI.run(seq1, parentSeq1, 0.95, zCoverage) confInter1.append(max((p - lowerCI) * 100, 0)) lowerCI, upperCI, p = wilsonCI.run(seq2, parentSeq2, 0.95, zCoverage) confInter2.append(max((p - lowerCI) * 100, 0)) else: confInter1.append(0) confInter2.append(0) # *** Sort fields so they are in descending order of the values in sample 1 fields = zip(field1, field2, features, confInter1, confInter2) fields.sort(reverse=True) field1, field2, features, confInter1, confInter2 = zip(*fields) features = list(features) # *** Truncate feature labels selectedFeatures = list( self.preferences['Selected exploratory features']) if self.preferences['Truncate feature names']: length = self.preferences['Length of truncated feature names'] for i in xrange(0, len(features)): if len(features[i]) > length + 3: features[i] = features[i][0:length] + '...' for i in xrange(0, len(selectedFeatures)): if len(selectedFeatures[i]) > length + 3: selectedFeatures[i] = selectedFeatures[i][0:length] + '...' # *** Set figure size self.fig.clear() figWidth = self.figColWidth * len(features) figHeight = self.figHeight if figWidth > 256 or figHeight > 256: QtGui.QApplication.instance().setOverrideCursor( QtGui.QCursor(QtCore.Qt.ArrowCursor)) self.emptyAxis() QtGui.QMessageBox.question( self, 'Excessively large plot', 'The resulting plot is too large to display.') QtGui.QApplication.instance().restoreOverrideCursor() return self.fig.set_size_inches(figWidth, figHeight) xLabelBounds, yLabelBounds = self.labelExtents( features, 8, 90, [max(max(field1), max(field2))], 8, 0) padding = 0.1 # inches newFigWidth = figWidth * (1.0 + yLabelBounds.width) + 2 * padding self.fig.set_size_inches( figWidth * (1.0 + yLabelBounds.width) + 2 * padding, figHeight) xOffsetFigSpace = (yLabelBounds.width * figWidth) / newFigWidth + padding / newFigWidth yOffsetFigSpace = xLabelBounds.height + padding / figHeight axesBar = self.fig.add_axes([ xOffsetFigSpace, yOffsetFigSpace, 1.0 - xOffsetFigSpace - padding / newFigWidth, 1.0 - yOffsetFigSpace - padding / figHeight ]) # *** Plot data colWidth = self.figColWidth barWidth = (colWidth * 0.9) / 2 if self.bShowCIs == True: rects1 = axesBar.bar(np.arange(len(features)) * colWidth, field1, width=barWidth, color=profile1Colour, yerr=confInter1, ecolor='black', capsize=self.endCapSize) rects2 = axesBar.bar(np.arange(len(features)) * colWidth + barWidth, field2, width=barWidth, color=profile2Colour, yerr=confInter2, ecolor='black', capsize=self.endCapSize) else: rects1 = axesBar.bar(np.arange(len(features)) * colWidth, field1, width=barWidth, color=profile1Colour) rects2 = axesBar.bar(np.arange(len(features)) * colWidth + barWidth, field2, width=barWidth, color=profile2Colour) axesBar.set_xticks(np.arange(len(features)) * colWidth + barWidth) axesBar.set_xlim( [0, (len(features) - 1.0) * colWidth + 2 * barWidth + 0.1]) axesBar.set_xticklabels(features, size=8) # *** Prettify plot legend = axesBar.legend([rects1[0], rects2[0]], (self.sampleName1, self.sampleName2), loc=self.legendPos) legend.get_frame().set_linewidth(0) for label in legend.get_texts(): label.set_size(8) for label in axesBar.get_xticklabels(): label.set_size(8) label.set_rotation(90) if label.get_text() in selectedFeatures: label.set_color('red') for label in axesBar.get_yticklabels(): label.set_size(8) for a in axesBar.yaxis.majorTicks: a.tick1On = False a.tick2On = False for a in axesBar.xaxis.majorTicks: a.tick1On = False a.tick2On = False for loc, spine in axesBar.spines.iteritems(): if loc in ['right', 'top']: spine.set_color('none') self.updateGeometry() self.draw()
def plot(self, profile, statsResults): if len(profile.profileDict) <= 0: self.emptyAxis() return if len(profile.profileDict) > 10000: QtGui.QApplication.instance().setOverrideCursor( QtGui.QCursor(QtCore.Qt.ArrowCursor)) reply = QtGui.QMessageBox.question( self, 'Continue?', 'Profile contains ' + str(len(profile.profileDict)) + ' features. ' + 'It may take several seconds to generate this plot. Exploring the data at a higher hierarchy level is recommended. ' + 'Do you wish to continue?', QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) QtGui.QApplication.instance().restoreOverrideCursor() if reply == QtGui.QMessageBox.No: self.emptyAxis() return # *** Colour of plot elements axesColour = str(self.preferences['Axes colour'].name()) profile1Colour = str(self.preferences['Sample 1 colour'].name()) profile2Colour = str(self.preferences['Sample 2 colour'].name()) # *** Create lists for each quantity of interest and calculate CIs tables = profile.getLabeledTables() features = [] field1 = [] field2 = [] wilsonCI = WilsonCI() confInter1 = [] confInter2 = [] for table in tables: feature, seq1, seq2, parentSeq1, parentSeq2 = table features.append(feature) field1.append(float(seq1) * 100 / max(parentSeq1, 1)) field2.append(float(seq2) * 100 / max(parentSeq2, 1)) if self.bShowCIs: lowerCI, upperCI, p = wilsonCI.run(seq1, parentSeq1, 0.95, 1.96) confInter1.append( [max(lowerCI * 100, 0), min(upperCI * 100, 100)]) lowerCI, upperCI, p = wilsonCI.run(seq2, parentSeq2, 0.95, 1.96) confInter2.append( [max(lowerCI * 100, 0), min(upperCI * 100, 100)]) # *** Set figure size self.fig.clear() self.fig.set_size_inches(self.figWidth, self.figHeight) if self.bShowHistograms: histogramSizeX = self.histogramSize / self.figWidth histogramSizeY = self.histogramSize / self.figHeight else: histogramSizeX = 0.0 histogramSizeY = 0.0 padding = 0.1 # inches xOffsetFigSpace = (0.4 + padding) / self.figWidth yOffsetFigSpace = (0.3 + padding) / self.figHeight axesScatter = self.fig.add_axes([ xOffsetFigSpace, yOffsetFigSpace, 1.0 - xOffsetFigSpace - histogramSizeX - (2 * padding) / self.figWidth, 1.0 - yOffsetFigSpace - histogramSizeY - (2 * padding) / self.figHeight ]) if self.bShowHistograms: axesTopHistogram = self.fig.add_axes([ xOffsetFigSpace, 1.0 - histogramSizeY - padding / self.figHeight, 1.0 - xOffsetFigSpace - histogramSizeX - (2 * padding) / self.figWidth, histogramSizeY ]) axesRightHistogram = self.fig.add_axes([ 1.0 - histogramSizeX - padding / self.figWidth, yOffsetFigSpace, histogramSizeX, 1.0 - yOffsetFigSpace - histogramSizeY - (2 * padding) / self.figHeight ]) # *** Handle mouse events tooltips = [] for i in xrange(0, len(field1)): tooltip = features[i] + '\n\n' tooltip += 'Sequences in ' + profile.sampleNames[0] + ': ' + str( tables[i][1]) + '\n' tooltip += 'Sequences in ' + profile.sampleNames[1] + ': ' + str( tables[i][2]) + '\n\n' tooltip += (profile.sampleNames[0] + ' percentage: %.3f' % field1[i]) + '\n' tooltip += (profile.sampleNames[1] + ' percentage: %.3f' % field2[i]) + '\n\n' tooltip += 'Difference between proportions (%): ' + ( '%.3f' % (field1[i] - field2[i])) + '\n' if field2[i] != 0: tooltip += 'Ratio of proportions: %.3f' % (field1[i] / field2[i]) else: tooltip += 'Ratio of proportions: undefined' if statsResults.profile != None: pValue = statsResults.getFeatureStatisticAsStr( features[i], 'pValues') pValueCorrected = statsResults.getFeatureStatisticAsStr( features[i], 'pValuesCorrected') tooltip += '\n\n' tooltip += 'p-value: ' + pValue + '\n' tooltip += 'Corrected p-value: ' + pValueCorrected tooltips.append(tooltip) self.plotEventHandler = PlotEventHandler(field1, field2, tooltips) self.mouseEventCallback(self.plotEventHandler) # *** Calculate R^2 value slope, intercept, r_value, p_value, std_err = linregress( field1, field2) # *** Plot data # set visual properties of all points colours = [] highlightedField1 = [] highlightedField2 = [] highlighColours = [] for i in xrange(0, len(field1)): if field1[i] > field2[i]: colours.append(profile1Colour) else: colours.append(profile2Colour) if features[i] in self.preferences['Highlighted sample features']: highlightedField1.append(field1[i]) highlightedField2.append(field2[i]) highlighColours.append(colours[i]) # scatter plot axesScatter.scatter(field1, field2, c=colours, s=self.markerSize, zorder=5) if len(highlightedField1) > 0: axesScatter.scatter(highlightedField1, highlightedField2, c=highlighColours, s=self.markerSize, edgecolors='red', linewidth=2, zorder=10) # plot CIs if self.bShowCIs: xlist = [] ylist = [] for i in xrange(0, len(field1)): # horizontal CIs xlist.append(confInter1[i][0]) xlist.append(confInter1[i][1]) xlist.append(None) ylist.append(field2[i]) ylist.append(field2[i]) ylist.append(None) # vertical CIs xlist.append(field1[i]) xlist.append(field1[i]) xlist.append(None) ylist.append(confInter2[i][0]) ylist.append(confInter2[i][1]) ylist.append(None) axesScatter.plot(xlist, ylist, '-', color='gray', antialiased=False) # plot y=x line maxProportion = max(max(field1), max(field2)) * 1.05 axesScatter.plot([0, maxProportion], [0, maxProportion], color=axesColour, linestyle='dashed', marker='', zorder=1) axesScatter.set_xlabel(profile.sampleNames[0] + ' (%)') axesScatter.set_ylabel(profile.sampleNames[1] + ' (%)') if self.bShowR2: axesScatter.text(0.02, 0.98, r'R$^2$ = ' + ('%0.3f' % r_value**2), horizontalalignment='left', verticalalignment='top', transform=axesScatter.transAxes) axesScatter.set_xlim(0, maxProportion) axesScatter.set_ylim(0, maxProportion) # *** Prettify scatter plot for line in axesScatter.yaxis.get_ticklines(): line.set_color(axesColour) for line in axesScatter.xaxis.get_ticklines(): line.set_color(axesColour) for loc, spine in axesScatter.spines.iteritems(): spine.set_color(axesColour) # plot histograms if not self.bShowHistograms: for a in axesScatter.yaxis.majorTicks: a.tick1On = True a.tick2On = False for a in axesScatter.xaxis.majorTicks: a.tick1On = True a.tick2On = False for line in axesScatter.yaxis.get_ticklines(): line.set_color(axesColour) for line in axesScatter.xaxis.get_ticklines(): line.set_color(axesColour) for loc, spine in axesScatter.spines.iteritems(): if loc in ['right', 'top']: spine.set_color('none') else: spine.set_color(axesColour) else: # show histograms # plot top histogram axesTopHistogram.xaxis.set_major_formatter(NullFormatter()) pdf, bins, patches = axesTopHistogram.hist( field1, bins=self.numBins, facecolor=profile1Colour) axesTopHistogram.set_xlim(axesScatter.get_xlim()) axesTopHistogram.set_yticks([0, max(pdf)]) axesTopHistogram.set_ylim([0, max(pdf) * 1.05]) # plot right histogram axesRightHistogram.yaxis.set_major_formatter(NullFormatter()) pdf, bins, patches = axesRightHistogram.hist( field2, bins=self.numBins, orientation='horizontal', facecolor=profile2Colour) axesRightHistogram.set_ylim(axesScatter.get_ylim()) axesRightHistogram.set_xticks([0, max(pdf)]) axesRightHistogram.set_xlim([0, max(pdf) * 1.05]) # *** Prettify histogram plot for a in axesTopHistogram.yaxis.majorTicks: a.tick1On = True a.tick2On = False for a in axesTopHistogram.xaxis.majorTicks: a.tick1On = True a.tick2On = False for line in axesTopHistogram.yaxis.get_ticklines(): line.set_color(axesColour) for line in axesTopHistogram.xaxis.get_ticklines(): line.set_color(axesColour) for loc, spine in axesTopHistogram.spines.iteritems(): if loc in ['right', 'top']: spine.set_color('none') else: spine.set_color(axesColour) for a in axesRightHistogram.yaxis.majorTicks: a.tick1On = True a.tick2On = False for a in axesRightHistogram.xaxis.majorTicks: a.tick1On = True a.tick2On = False for line in axesRightHistogram.yaxis.get_ticklines(): line.set_color(axesColour) for line in axesRightHistogram.xaxis.get_ticklines(): line.set_color(axesColour) for loc, spine in axesRightHistogram.spines.iteritems(): if loc in ['right', 'top']: spine.set_color('none') else: spine.set_color(axesColour) self.updateGeometry() self.draw()
def plot(self, profile, statsResults): if len(profile.profileDict) <= 0: self.emptyAxis() return if len(profile.profileDict) > 10000: QtGui.QApplication.instance().setOverrideCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) reply = QtGui.QMessageBox.question(self, 'Continue?', 'Profile contains ' + str(len(profile.profileDict)) + ' features. ' + 'It may take several seconds to generate this plot. Exploring the data at a higher hierarchy level is recommended. ' + 'Do you wish to continue?', QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) QtGui.QApplication.instance().restoreOverrideCursor() if reply == QtGui.QMessageBox.No: self.emptyAxis() return # *** Colour of plot elements axesColour = str(self.preferences['Axes colour'].name()) profile1Colour = str(self.preferences['Sample 1 colour'].name()) profile2Colour = str(self.preferences['Sample 2 colour'].name()) # *** Create lists for each quantity of interest and calculate CIs tables = profile.getLabeledTables() features = [] field1 = [] field2 = [] wilsonCI = WilsonCI() confInter1 = [] confInter2 = [] for table in tables: feature, seq1, seq2, parentSeq1, parentSeq2 = table features.append(feature) field1.append(float(seq1)*100 / max(parentSeq1,1)) field2.append(float(seq2)*100 / max(parentSeq2,1)) if self.bShowCIs: lowerCI, upperCI, p = wilsonCI.run(seq1, parentSeq1, 0.95, 1.96) confInter1.append([max(lowerCI*100, 0), min(upperCI*100,100)]) lowerCI, upperCI, p = wilsonCI.run(seq2, parentSeq2, 0.95, 1.96) confInter2.append([max(lowerCI*100, 0), min(upperCI*100,100)]) # *** Set figure size self.fig.clear() self.fig.set_size_inches(self.figWidth, self.figHeight) if self.bShowHistograms: histogramSizeX = self.histogramSize /self.figWidth histogramSizeY = self.histogramSize /self.figHeight else: histogramSizeX = 0.0 histogramSizeY = 0.0 padding = 0.1 # inches xOffsetFigSpace = (0.4 + padding)/self.figWidth yOffsetFigSpace = (0.3 + padding)/self.figHeight axesScatter = self.fig.add_axes([xOffsetFigSpace, yOffsetFigSpace, 1.0 - xOffsetFigSpace - histogramSizeX - (2*padding)/self.figWidth, 1.0 - yOffsetFigSpace - histogramSizeY - (2*padding)/self.figHeight]) if self.bShowHistograms: axesTopHistogram = self.fig.add_axes([xOffsetFigSpace, 1.0 - histogramSizeY - padding/self.figHeight, 1.0 - xOffsetFigSpace - histogramSizeX - (2*padding)/self.figWidth, histogramSizeY]) axesRightHistogram = self.fig.add_axes([1.0 - histogramSizeX - padding/self.figWidth, yOffsetFigSpace, histogramSizeX, 1.0 - yOffsetFigSpace - histogramSizeY - (2*padding)/self.figHeight]) # *** Handle mouse events tooltips = [] for i in xrange(0, len(field1)): tooltip = features[i] + '\n\n' tooltip += 'Sequences in ' + profile.sampleNames[0] + ': ' + str(tables[i][1]) + '\n' tooltip += 'Sequences in ' + profile.sampleNames[1] + ': ' + str(tables[i][2]) + '\n\n' tooltip += (profile.sampleNames[0] + ' percentage: %.3f' % field1[i]) + '\n' tooltip += (profile.sampleNames[1] + ' percentage: %.3f' % field2[i]) + '\n\n' tooltip += 'Difference between proportions (%): ' + ('%.3f' % (field1[i] - field2[i])) + '\n' if field2[i] != 0: tooltip += 'Ratio of proportions: %.3f' % (field1[i]/field2[i]) else: tooltip += 'Ratio of proportions: undefined' if statsResults.profile != None: pValue = statsResults.getFeatureStatisticAsStr(features[i], 'pValues') pValueCorrected = statsResults.getFeatureStatisticAsStr(features[i], 'pValuesCorrected') tooltip += '\n\n' tooltip += 'p-value: ' + pValue + '\n' tooltip += 'Corrected p-value: ' + pValueCorrected tooltips.append(tooltip) self.plotEventHandler = PlotEventHandler(field1, field2, tooltips) self.mouseEventCallback(self.plotEventHandler) # *** Calculate R^2 value slope, intercept, r_value, p_value, std_err = linregress(field1, field2) # *** Plot data # set visual properties of all points colours = [] highlightedField1 = [] highlightedField2 = [] highlighColours = [] for i in xrange(0, len(field1)): if field1[i] > field2[i]: colours.append(profile1Colour) else: colours.append(profile2Colour) if features[i] in self.preferences['Highlighted sample features']: highlightedField1.append(field1[i]) highlightedField2.append(field2[i]) highlighColours.append(colours[i]) # scatter plot axesScatter.scatter(field1, field2, c=colours, s=self.markerSize, zorder=5) if len(highlightedField1) > 0: axesScatter.scatter(highlightedField1, highlightedField2, c=highlighColours, s=self.markerSize, edgecolors = 'red', linewidth = 2, zorder=10) # plot CIs if self.bShowCIs: xlist = [] ylist = [] for i in xrange(0, len(field1)): # horizontal CIs xlist.append(confInter1[i][0]) xlist.append(confInter1[i][1]) xlist.append(None) ylist.append(field2[i]) ylist.append(field2[i]) ylist.append(None) # vertical CIs xlist.append(field1[i]) xlist.append(field1[i]) xlist.append(None) ylist.append(confInter2[i][0]) ylist.append(confInter2[i][1]) ylist.append(None) axesScatter.plot(xlist, ylist, '-', color='gray', antialiased=False) # plot y=x line maxProportion = max(max(field1),max(field2))*1.05 axesScatter.plot([0,maxProportion],[0,maxProportion], color=axesColour, linestyle='dashed', marker='', zorder = 1) axesScatter.set_xlabel(profile.sampleNames[0] + ' (%)') axesScatter.set_ylabel(profile.sampleNames[1] + ' (%)') if self.bShowR2: axesScatter.text(0.02, 0.98, r'R$^2$ = ' + ('%0.3f' % r_value**2), horizontalalignment='left', verticalalignment='top', transform=axesScatter.transAxes) axesScatter.set_xlim(0, maxProportion) axesScatter.set_ylim(0, maxProportion) # *** Prettify scatter plot for line in axesScatter.yaxis.get_ticklines(): line.set_color(axesColour) for line in axesScatter.xaxis.get_ticklines(): line.set_color(axesColour) for loc, spine in axesScatter.spines.iteritems(): spine.set_color(axesColour) # plot histograms if not self.bShowHistograms: for a in axesScatter.yaxis.majorTicks: a.tick1On=True a.tick2On=False for a in axesScatter.xaxis.majorTicks: a.tick1On=True a.tick2On=False for line in axesScatter.yaxis.get_ticklines(): line.set_color(axesColour) for line in axesScatter.xaxis.get_ticklines(): line.set_color(axesColour) for loc, spine in axesScatter.spines.iteritems(): if loc in ['right','top']: spine.set_color('none') else: spine.set_color(axesColour) else: # show histograms # plot top histogram axesTopHistogram.xaxis.set_major_formatter(NullFormatter()) pdf, bins, patches = axesTopHistogram.hist(field1, bins = self.numBins, facecolor = profile1Colour) axesTopHistogram.set_xlim(axesScatter.get_xlim()) axesTopHistogram.set_yticks([0, max(pdf)]) axesTopHistogram.set_ylim([0, max(pdf)*1.05]) # plot right histogram axesRightHistogram.yaxis.set_major_formatter(NullFormatter()) pdf, bins, patches = axesRightHistogram.hist(field2, bins = self.numBins, orientation='horizontal', facecolor = profile2Colour) axesRightHistogram.set_ylim(axesScatter.get_ylim()) axesRightHistogram.set_xticks([0, max(pdf)]) axesRightHistogram.set_xlim([0, max(pdf)*1.05]) # *** Prettify histogram plot for a in axesTopHistogram.yaxis.majorTicks: a.tick1On=True a.tick2On=False for a in axesTopHistogram.xaxis.majorTicks: a.tick1On=True a.tick2On=False for line in axesTopHistogram.yaxis.get_ticklines(): line.set_color(axesColour) for line in axesTopHistogram.xaxis.get_ticklines(): line.set_color(axesColour) for loc, spine in axesTopHistogram.spines.iteritems(): if loc in ['right','top']: spine.set_color('none') else: spine.set_color(axesColour) for a in axesRightHistogram.yaxis.majorTicks: a.tick1On=True a.tick2On=False for a in axesRightHistogram.xaxis.majorTicks: a.tick1On=True a.tick2On=False for line in axesRightHistogram.yaxis.get_ticklines(): line.set_color(axesColour) for line in axesRightHistogram.xaxis.get_ticklines(): line.set_color(axesColour) for loc, spine in axesRightHistogram.spines.iteritems(): if loc in ['right','top']: spine.set_color('none') else: spine.set_color(axesColour) self.updateGeometry() self.draw()