Skip to content

Commit

Permalink
Improved heatmaps, numpy 1.8.1 fixes
Browse files Browse the repository at this point in the history
Improved heatmaps to allow only active features to be plotted. Fixed
bugs relating to index slicing in numpy 1.8.1.
  • Loading branch information
donovan-h-parks committed Jul 26, 2014
1 parent e86dc18 commit f03afbb
Show file tree
Hide file tree
Showing 11 changed files with 125 additions and 60 deletions.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
('.', ['README.md'])]
setup(
name='STAMP',
version='2.0.6',
version='2.0.7',
author='Donovan Parks, Rob Beiko',
author_email='[email protected]',
packages=['stamp', 'stamp.GUI'] + pluginPkgs + metagenomicPkgs,
Expand Down
6 changes: 3 additions & 3 deletions stamp/STAMP.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
__copyright__ = 'Copyright 2013'
__credits__ = ['Donovan Parks']
__license__ = 'GPL3'
__version__ = '2.0.6'
__date__ = 'July 7, 2014'
__version__ = '2.0.7'
__date__ = 'July 26, 2014'
__maintainer__ = 'Donovan Parks'
__email__ = '[email protected]'
__status__ = 'Development'
Expand Down Expand Up @@ -1738,7 +1738,7 @@ def updateStatusBar(self):

def openAboutDlg(self):
QtGui.QMessageBox.about(self, 'About...',
'STAMP: STatistical Analysis of Metagenomic Profiles\n\n'
'STAMP: statistical analysis of taxonomic and functional profiles\n\n'
'%s\n'
'%s\n'
'%s\n\n'
Expand Down
2 changes: 0 additions & 2 deletions stamp/mainUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -2070,7 +2070,6 @@ def retranslateUi(self, MainWindow):
self.cboGroupSeqFilter.setItemText(2, _translate("MainWindow", "independent, maximum", None))
self.cboGroupSeqFilter.setItemText(3, _translate("MainWindow", "independent, minimum", None))
self.lblGroupSeqFilter1.setText(_translate("MainWindow", "Maximum (<):", None))
self.spinGroupFilter1.setStatusTip(_translate("MainWindow", "Filter out all features where sample 2 does not contain more than the specified number of sequences", None))
self.lblGroupSeqFilter2.setText(_translate("MainWindow", "Group 2 (<):", None))
self.label_24.setText(_translate("MainWindow", "Parent seq. filter:", None))
self.cboGroupParentSeqFilter.setItemText(0, _translate("MainWindow", "maximum", None))
Expand Down Expand Up @@ -2117,7 +2116,6 @@ def retranslateUi(self, MainWindow):
self.cboSampleSeqFilter.setItemText(1, _translate("MainWindow", "minimum", None))
self.cboSampleSeqFilter.setItemText(2, _translate("MainWindow", "independent", None))
self.lblSampleSeqFilterSample1.setText(_translate("MainWindow", "Maximum (<):", None))
self.spinSampleFilterSample1.setStatusTip(_translate("MainWindow", "Filter out all features where sample 2 does not contain more than the specified number of sequences", None))
self.lblSampleSeqFilterSample2.setText(_translate("MainWindow", "Sample 2 (<):", None))
self.label_12.setText(_translate("MainWindow", "Parent seq. filter:", None))
self.cboSampleParentSeqFilter.setItemText(0, _translate("MainWindow", "maximum", None))
Expand Down
10 changes: 8 additions & 2 deletions stamp/metagenomics/GroupProfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,12 @@ def getParentFeatureCounts(self, feature):
return data1, data2

def getFeatureCountsAll(self):
return self.getActiveFeatureCounts(self.profileDict.keys())

def getActiveFeatureCounts(self, activeFeatures):
seqGroup1 = []
seqGroup2 = []
for feature in self.profileDict.keys():
for feature in activeFeatures:
data1, data2 = self.getFeatureCounts(feature)
seqGroup1.append(data1)
seqGroup2.append(data2)
Expand Down Expand Up @@ -130,9 +133,12 @@ def getFeatureProportions(self, feature):
return data1, data2

def getFeatureProportionsAll(self):
return self.getActiveFeatureProportions(self.profileDict.keys())

def getActiveFeatureProportions(self, activeFeatures):
groupData1 = []
groupData2 = []
for feature in self.profileDict.keys():
for feature in activeFeatures:
data1, data2 = self.getFeatureProportions(feature)
groupData1.append(data1)
groupData2.append(data2)
Expand Down
16 changes: 16 additions & 0 deletions stamp/metagenomics/MultiGroupProfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,14 @@ def getActiveFeatureCountsAll(self):
allData.append(data)

return allData

def getActiveFeatureFromActiveSamplesCounts(self, activeFeatures):
allData = []
for feature in activeFeatures:
data = self.getActiveFeatureCounts(feature)
allData.append(data)

return allData

def getParentCounts(self, feature):
profile = self.profileDict[feature]
Expand Down Expand Up @@ -222,6 +230,14 @@ def getActiveFeatureProportionsAll(self):
allData.append(data)

return allData

def getActiveFeatureFromActiveSamplesProportions(self, activeFeatures):
allData = []
for feature in activeFeatures:
data = self.getActiveFeatureProportions(feature)
allData.append(data)

return allData

def getFeatureMatrix(self):
numSamples = len(self.profileDict[self.profileDict.keys()[0]].featureCounts)
Expand Down
57 changes: 34 additions & 23 deletions stamp/plugins/groups/plots/HeatmapPlot.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,9 @@ def __init__(self, preferences, parent=None):
self.name = 'Heatmap plot'
self.type = 'Exploratory'

self.bPlotFeaturesIndividually = False

self.settings = preferences['Settings']
self.fieldToPlot = self.settings.value('group: ' + self.name + '/field to plot', 'Proportion of sequences (%)').toString()
self.bPlotOnlyActiveFeatures = self.settings.value('group: ' + self.name + '/plot only active features', False).toBool()
self.figWidth = self.settings.value('group: ' + self.name + '/width', 7.0).toDouble()[0]
self.figHeight = self.settings.value('group: ' + self.name + '/height', 7.0).toDouble()[0]
self.dendrogramMethod = self.settings.value('group: ' + self.name + '/dendrogram method', 'Average neighbour (UPGMA)').toString()
Expand All @@ -79,6 +78,7 @@ def mirrorProperties(self, plotToCopy):
self.name = plotToCopy.name

self.fieldToPlot = plotToCopy.fieldToPlot
self.bPlotOnlyActiveFeatures = plotToCopy.bPlotOnlyActiveFeatures

self.figWidth = plotToCopy.figWidth
self.figHeight = plotToCopy.figHeight
Expand Down Expand Up @@ -115,10 +115,16 @@ def plotDendrogram(self, matrix, axis, clusteringThreshold, orientation, bPlot):
return index, dendrogram['leaves']

def plot(self, profile, statsResults):
if len(profile.profileDict) <= 0 or len(profile.samplesInGroup1) == 0 or len(profile.samplesInGroup2) == 0:

# determine features to plot
featuresToPlot = profile.profileDict.keys()
if self.bPlotOnlyActiveFeatures:
featuresToPlot = statsResults.activeFeatures

if len(featuresToPlot) <= 1 or (len(profile.samplesInGroup1) + len(profile.samplesInGroup2)) <= 1:
self.emptyAxis()
return
elif len(profile.profileDict) > 100 or len(profile.samplesInGroup1) + len(profile.samplesInGroup2) > 100:
elif len(featuresToPlot) > 100 or len(profile.samplesInGroup1) + len(profile.samplesInGroup2) > 100:
QtGui.QApplication.instance().setOverrideCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
QtGui.QMessageBox.information(self, 'Too much data!', 'Heatmap plots are limited to 100 samples and 100 features.', QtGui.QMessageBox.Ok)
QtGui.QApplication.instance().restoreOverrideCursor()
Expand Down Expand Up @@ -159,9 +165,9 @@ def plot(self, profile, statsResults):

# *** Get data for each group
if self.fieldToPlot == "Number of sequences":
data1, data2 = profile.getFeatureCountsAll()
data1, data2 = profile.getActiveFeatureCounts(featuresToPlot)
else: # Proportion of sequences (%)
data1, data2 = profile.getFeatureProportionsAll()
data1, data2 = profile.getActiveFeatureProportions(featuresToPlot)

matrix = []
for row in data1:
Expand All @@ -174,7 +180,7 @@ def plot(self, profile, statsResults):

# *** Get heatmap data
colHeaders = profile.samplesInGroup1 + profile.samplesInGroup2
rowHeaders = profile.getFeatures()
rowHeaders = featuresToPlot

# *** Find longest label
bTruncate = False
Expand Down Expand Up @@ -296,25 +302,27 @@ def plot(self, profile, statsResults):

sampleColourMap = mpl.colors.ListedColormap(sampleColourMap)
matrix = matrix[:,leafIndex2]
ind2 = ind2[:,leafIndex2]

axc = self.fig.add_axes([colClusterBarX, colClusterBarY, colClusterBarW, colClusterBarH]) # axes for column side colorbar
dc = numpy.array(numpy.arange(len(leafIndex2)), dtype=int)
dc.shape = (1,len(leafIndex2))
axc.matshow(dc, aspect='auto', origin='lower', cmap=sampleColourMap)
axc.set_xticks([])
axc.set_yticks([])
ind2 = ind2[leafIndex2]

if self.bShowTopDendrogram:
axc = self.fig.add_axes([colClusterBarX, colClusterBarY, colClusterBarW, colClusterBarH]) # axes for column side colorbar
dc = numpy.array(numpy.arange(len(leafIndex2)), dtype=int)
dc.shape = (1,len(leafIndex2))
axc.matshow(dc, aspect='auto', origin='lower', cmap=sampleColourMap)
axc.set_xticks([])
axc.set_yticks([])

# plot row clustering bars
matrix = matrix[leafIndex1,:]
ind1 = ind1[leafIndex1,:]

axr = self.fig.add_axes([rowClusterBarX, rowClusterBarY, rowClusterBarW, rowClusterBarH])
dr = numpy.array(ind1, dtype=int)
dr.shape = (len(ind1),1)
axr.matshow(dr, aspect='auto', origin='lower', cmap=self.discreteColourMap)
axr.set_xticks([])
axr.set_yticks([])
ind1 = ind1[leafIndex1]

if self.bShowLeftDendrogram:
axr = self.fig.add_axes([rowClusterBarX, rowClusterBarY, rowClusterBarW, rowClusterBarH])
dr = numpy.array(ind1, dtype=int)
dr.shape = (len(ind1),1)
axr.matshow(dr, aspect='auto', origin='lower', cmap=self.discreteColourMap)
axr.set_xticks([])
axr.set_yticks([])

# determine scale for colour map
minValue = 1e6
Expand Down Expand Up @@ -372,6 +380,7 @@ def configure(self, profile, statsResults):
configDlg = ConfigureDialog(Ui_HeatmapPlotDialog)

configDlg.ui.cboFieldToPlot.setCurrentIndex(configDlg.ui.cboFieldToPlot.findText(self.fieldToPlot))
configDlg.ui.chkPlotOnlyActiveFeatures.setChecked(self.bPlotOnlyActiveFeatures)

configDlg.ui.spinFigWidth.setValue(self.figWidth)
configDlg.ui.spinFigHeight.setValue(self.figHeight)
Expand Down Expand Up @@ -401,6 +410,7 @@ def configure(self, profile, statsResults):

if configDlg.exec_() == QtGui.QDialog.Accepted:
self.fieldToPlot = str(configDlg.ui.cboFieldToPlot.currentText())
self.bPlotOnlyActiveFeatures = configDlg.ui.chkPlotOnlyActiveFeatures.isChecked()

self.figWidth = configDlg.ui.spinFigWidth.value()
self.figHeight = configDlg.ui.spinFigHeight.value()
Expand Down Expand Up @@ -430,6 +440,7 @@ def configure(self, profile, statsResults):
self.dendrogramHeight = configDlg.ui.spinDendrogramHeight.value()

self.settings.setValue('group: ' + self.name + '/field to plot', self.fieldToPlot)
self.settings.setValue('group: ' + self.name + '/plot only active features', self.bPlotOnlyActiveFeatures)
self.settings.setValue('group: ' + self.name + '/width', self.figWidth)
self.settings.setValue('group: ' + self.name + '/height', self.figHeight)
self.settings.setValue('group: ' + self.name + '/dendrogram method', self.dendrogramMethod)
Expand Down
9 changes: 8 additions & 1 deletion stamp/plugins/groups/plots/configGUI/HeatmapPlot.ui
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>260</width>
<height>432</height>
<height>455</height>
</rect>
</property>
<property name="sizePolicy">
Expand Down Expand Up @@ -58,6 +58,13 @@
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="chkPlotOnlyActiveFeatures">
<property name="text">
<string>Plot only active features</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
Expand Down
10 changes: 7 additions & 3 deletions stamp/plugins/groups/plots/configGUI/HeatmapPlotUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Form implementation generated from reading ui file 'HeatmapPlot.ui'
#
# Created: Wed Oct 16 11:32:12 2013
# Created: Sat Jul 26 11:13:18 2014
# by: PyQt4 UI code generator 4.9.6
#
# WARNING! All changes made in this file will be lost!
Expand All @@ -26,14 +26,14 @@ def _translate(context, text, disambig):
class Ui_HeatmapPlotDialog(object):
def setupUi(self, HeatmapPlotDialog):
HeatmapPlotDialog.setObjectName(_fromUtf8("HeatmapPlotDialog"))
HeatmapPlotDialog.resize(260, 432)
HeatmapPlotDialog.resize(260, 455)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(HeatmapPlotDialog.sizePolicy().hasHeightForWidth())
HeatmapPlotDialog.setSizePolicy(sizePolicy)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/icons/icons/programIcon.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
icon.addPixmap(QtGui.QPixmap(_fromUtf8("../../../../../icons/programIcon.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
HeatmapPlotDialog.setWindowIcon(icon)
self.verticalLayout_3 = QtGui.QVBoxLayout(HeatmapPlotDialog)
self.verticalLayout_3.setObjectName(_fromUtf8("verticalLayout_3"))
Expand All @@ -53,6 +53,9 @@ def setupUi(self, HeatmapPlotDialog):
self.cboFieldToPlot.addItem(_fromUtf8(""))
self.horizontalLayout_6.addWidget(self.cboFieldToPlot)
self.verticalLayout_3.addLayout(self.horizontalLayout_6)
self.chkPlotOnlyActiveFeatures = QtGui.QCheckBox(HeatmapPlotDialog)
self.chkPlotOnlyActiveFeatures.setObjectName(_fromUtf8("chkPlotOnlyActiveFeatures"))
self.verticalLayout_3.addWidget(self.chkPlotOnlyActiveFeatures)
self.groupBox_3 = QtGui.QGroupBox(HeatmapPlotDialog)
self.groupBox_3.setObjectName(_fromUtf8("groupBox_3"))
self.verticalLayout = QtGui.QVBoxLayout(self.groupBox_3)
Expand Down Expand Up @@ -269,6 +272,7 @@ def retranslateUi(self, HeatmapPlotDialog):
self.label.setText(_translate("HeatmapPlotDialog", "Field to plot:", None))
self.cboFieldToPlot.setItemText(0, _translate("HeatmapPlotDialog", "Number of sequences", None))
self.cboFieldToPlot.setItemText(1, _translate("HeatmapPlotDialog", "Proportion of sequences (%)", None))
self.chkPlotOnlyActiveFeatures.setText(_translate("HeatmapPlotDialog", "Plot only active features", None))
self.groupBox_3.setTitle(_translate("HeatmapPlotDialog", "Figure size", None))
self.lblFigureWidth.setText(_translate("HeatmapPlotDialog", "Width:", None))
self.lblFigureHeight.setText(_translate("HeatmapPlotDialog", "Height:", None))
Expand Down
Loading

0 comments on commit f03afbb

Please sign in to comment.