source: orange-bioinformatics/_bioinformatics/widgets/OWVulcanoPlot.py @ 1726:6778e0225b86

Revision 1726:6778e0225b86, 28.4 KB checked in by Ales Erjavec <ales.erjavec@…>, 17 months ago (diff)

Added new icons by Peter Cuhalev and replaced existing ones with expanded paths.

RevLine 
[681]1"""
2<name>Vulcano Plot</name>
[1051]3<description>Plots fold change vs. p-value.)</description>
[1052]4<priority>1020</priority>
[681]5<contact>Ales Erjavec (ales.erjavec@fri.uni-lj.si)</contact>
[1726]6<icon>icons/VulcanoPlot.svg</icon>
[681]7"""
8
[1632]9from __future__ import absolute_import
10
[1322]11import itertools
[1385]12from operator import add
13from collections import defaultdict
[681]14from math import log
[1632]15
[1385]16import numpy
[681]17
[1632]18import orange
19from statc import mean, ttest_ind
[1118]20
[1632]21from Orange.orng.orngDataCaching import data_hints
22from Orange.OrangeWidgets.OWToolbars import ZoomSelectToolbar
23from Orange.OrangeWidgets.OWWidget import *
24from Orange.OrangeWidgets.OWGraph import *
25from Orange.OrangeWidgets import OWGUI
26
27from .. import obiExpression
28from ..obiGEO import transpose
[681]29
[1202]30class GraphSelections(QObject):
[1395]31    """ Selection manager using a union of rectangle areas
32    """
[1202]33    def __init__(self, parent):
34        QObject.__init__(self, parent)
35        self.selection = []
36       
37    def getPos(self, event):
38        graph = self.parent()
39        pos = graph.canvas().mapFrom(graph, event.pos())
40        x = graph.invTransform(QwtPlot.xBottom, pos.x())
41        y = graph.invTransform(QwtPlot.yLeft, pos.y())
42        return QPointF(x, y)
43       
44    def start(self, event):
45        pos = self.getPos(event)
46        if event.modifiers() & Qt.ControlModifier:
47            self.selection.append((pos, pos))
48        else:
49            self.selection = [(pos, pos)]
50        self.emit(SIGNAL("selectionGeometryChanged()"))
51   
52    def update(self, event):
53        pos = self.getPos(event)
54        self.selection[-1] = self.selection[-1][:-1] + (pos,)
55        self.emit(SIGNAL("selectionGeometryChanged()"))
56   
57    def end(self, event):
58        self.update(event)
59       
60    def testSelection(self, data):
[1274]61        if len(data) == 0:
62            return []
[1202]63        data = numpy.asarray(data)
64        region = QPainterPath()
65        for p1, p2 in self.selection:
66            region.addRect(QRectF(p1, p2).normalized())
67        def test(point):
68            return region.contains(QPointF(point[0], point[1]))
69        test = numpy.apply_along_axis(test, 1, data)
70        return test
71       
72class SymetricSelections(GraphSelections):
[1395]73    """ Selection manager using two symmetric areas extending to 'infinity' 
74    """
[1202]75    def __init__(self, parent, x=3, y=3):
76        GraphSelections.__init__(self, parent)
[1395]77        max = 100000
[1202]78        self.selection = [(QPointF(-max, max), QPointF(-x, y)), (QPointF(max, max), QPointF(x, y))]
79        self.updateAxes = None
80       
81    def updateSelection(self, axes, pos):
82        if axes == QwtPlot.xBottom or axes == -1:
83            self.selection[0][1].setX(-abs(pos.x()))
84            self.selection[1][1].setX(abs(pos.x()))
85        if axes == QwtPlot.yLeft or axes == -1:
86            self.selection[0][1].setY(pos.y())
87            self.selection[1][1].setY(pos.y())
88           
89        self.emit(SIGNAL("selectionGeometryChanged()"))
90       
91    def getAxesAndPos(self, event):
92        graph = self.parent()
93        pos = graph.canvas().mapFrom(graph, event.pos())
94        x = graph.invTransform(QwtPlot.xBottom, pos.x())
95        y = graph.invTransform(QwtPlot.yLeft, pos.y())
96       
97        offset = 3
98        dx = abs(graph.invTransform(QwtPlot.xBottom, pos.x() + offset) - x)
99        dy = abs(graph.invTransform(QwtPlot.yLeft, pos.y() + offset) - y)
100       
101        x = abs(x)
102       
103        cx = self.selection[1][1].x()
104        cy = self.selection[1][1].y()
105
106        bottom = QRectF(QPointF(cx, cy), QPointF(graph.maxX, cy)).adjusted(-dx, dy, dx, -dy).normalized()
107        left = QRectF(QPointF(cx, graph.maxY), QPointF(cx, cy)).adjusted(-dx, dy, dx, -dy).normalized()
108       
109        if bottom.contains(QPointF(x, y)) or bottom.contains(QPointF(-x, y)):
110            axes = QwtPlot.yLeft
111        elif left.contains(QPointF(x, y)) or left.contains(QPointF(-x, y)):
112            axes = QwtPlot.xBottom
113        else:
114            axes = -1
115        return axes, QPointF(x, y)
116       
117    def start(self, event):
118        axes, pos = self.getAxesAndPos(event)
119        self.updateAxes = axes
120        self.updateSelection(axes, pos)
121       
122    def update(self, event):
123        _, pos = self.getAxesAndPos(event)
124        self.updateSelection(self.updateAxes, pos)
125   
126    def end(self, event):
127        self.update(event)
128        self.updateAxes = None
129       
130    def testSelection(self, data):
[1274]131        if len(data) == 0:
132            return []
[1202]133        data = numpy.asarray(data)
134        cutoffX = self.selection[1][1].x()
135        cutoffY = self.selection[1][1].y()
136        return (numpy.abs(data[:, 0]) >= cutoffX) & (data[:, 1] >= cutoffY)
137   
[1632]138from Orange.OrangeWidgets.OWItemModels import PyListModel
[1385]139
140def item_selection(indices, model, selection=None, column=0):
141    """ Create an QItemSelection for indices in model.
142    """
143    if selection is None:
144        selection = QItemSelection()
145       
146    for i in indices:
147        selection.select(model.index(i, column))
148    return selection
149
150
151class LabelSelectionWidget(QWidget):
152    """ A widget for selection of label values.
153    """
154    def __init__(self, parent=None):
155        QWidget.__init__(self, parent)
156        self._values_model = PyListModel([], parent=self)
157        layout = QVBoxLayout()
158        layout.setContentsMargins(0, 0, 0, 0)
159        def group_box(title):
160            box = QGroupBox(title)
161            box.setFlat(True)
162            lay = QVBoxLayout()
163            lay.setContentsMargins(0, 0, 0, 0)
164            box.setLayout(lay)
165            return box
166       
167        self.labels_combo = QComboBox()
168        self.values_view = QListView()
169        self.values_view.setSelectionMode(QListView.ExtendedSelection)
170        self.values_view.setModel(self._values_model)
171       
172       
173        self.connect(self.labels_combo, SIGNAL("activated(int)"),
174                     self.on_label_activated)
175       
176        self.connect(self.values_view.selectionModel(),
177                     SIGNAL("selectionChanged(QItemSelection, QItemSelection)"),
178                     self.on_values_selection)
179       
180        l_box = group_box("Label")
181        v_box = group_box("Values")
182       
183        l_box.layout().addWidget(self.labels_combo)
184        v_box.layout().addWidget(self.values_view)
185       
186        layout.addWidget(l_box)
187        layout.addWidget(v_box)
188       
189        self.setLayout(layout)
190       
191        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
192       
193        self._block_selection_emit = False
194       
195        self.labels = []
196        self.set_labels([])
197       
198    def clear(self):
199        self.labels_combo.clear()
200        self._values_model[:] = []
201        self.labels = []
202       
203    def set_labels(self, labels):
204        """ Set the labels to display.
205        """
206        self.clear()
207        if isinstance(labels, dict):
208            labels = labels.items()
209           
210        self.labels = labels
211        for label, values in labels:
212            self.labels_combo.addItem(label)
213           
214        if labels:
215            self.set_current_label(0)
216#            self.labels_combo.setCurrentIndex(0)
217           
218    def set_selection(self, label, values):
219        """ Set the selection to label and values
220        """
221        if isinstance(label, basestring):
222            labels = [l for l, _ in self.labels]
223            index = labels.index(label) if label in labels else -1
224        else:
225            index = label
226           
227        if index >= 0:
228            if index != self.labels_combo.currentIndex():
229                self.set_current_label(index)
230               
231            all_values = list(self._values_model)
232            values = [v for v in values if v in all_values]
233            selection = QItemSelection()
234            for i, v in enumerate(self._values_model):
235                if v in values:
236                    index = self._values_model.index(i, 0)
237                    selection.select(index, index)
238            self.values_view.selectionModel().select(selection,  QItemSelectionModel.ClearAndSelect)
[1390]239        else:
240            self.values_view.selectionModel().clear()
[1385]241           
242    def set_current_label(self, index):
243        """ Set the current label
244        """
245        self.labels_combo.setCurrentIndex(index)
246        label, values = self.labels[index]
247        # Block selection changed
248        with self._blocked_signals():
249            self._values_model[:] = values
250       
251    def on_label_activated(self, index):
252        label, values = self.labels[index]
253        with self._blocked_signals():
254            self._values_model[:] = values
255        self.emit(SIGNAL("label_activated()"))
256        self.emit(SIGNAL("label_activated(int)"), index)
257   
258    def on_values_selection(self, selected, deselected):
259        label, values = self.current_selection()
260        self.emit(SIGNAL("selection_changed()"))
261        self.emit(SIGNAL("selection_changed(PyQt_PyObject, PyQt_PyObject)"),
262                  label, values)
263       
264    def selection_indexes(self):
265        """ Return the values selection indices.
266        """
267        selection = self.values_view.selectionModel().selection()
268        indexes = selection.indexes()
269        return sorted(set([i.row() for i in indexes]))       
270       
271    def current_selection(self):
272        """ Return the current label and selected values.
273        """
274        i = self.labels_combo.currentIndex()
[1622]275
276        if i == -1:
277            # When clearing the labels model / combobox
278            return None, None
279
[1385]280        label, all_values = self.labels[i]
281        values = [all_values[i] for i in self.selection_indexes()]
282        return label, values
283   
284    def _blocked_signals(self):
285        """ Return a context handler blocking all emited signals from this
286        object.
287         
288        """
289        class block(object):
290            def __enter__(blocker):
291                self.blockSignals(True)
292            def __exit__(blocker, *args):
293                self.blockSignals(False)
294                return False
295        return block()
296               
297    def sizeHint(self):
298        return QSize(100, 200)
299           
300       
[681]301class VulcanoGraph(OWGraph):
302    def __init__(self, master, *args, **kwargs):
303        OWGraph.__init__(self, *args, **kwargs)
304        self.master = master
305        self.cutoffX = 2.0
306        self.cutoffY = 3.0
[1202]307        self.maxX, self.maxY = 10, 10
[681]308        self.symbolSize = 5
[1202]309        self.symetricSelections = True
[681]310       
311        self.selectedCurve = self.addCurve("", brushColor=Qt.red)
312        self.unselectedCurve = self.addCurve("", brushColor=Qt.blue)
313       
314        self.plotValues = {}
315
316        self.setAxisAutoScale(QwtPlot.xBottom)
317        self.setAxisAutoScale(QwtPlot.yLeft)
[1202]318       
319        self.reselect(replot=False)
320       
321    def setSelection(self, selection):
322        self.selection = selection
323        self.connect(self.selection, SIGNAL("selectionGeometryChanged()"), self.onSelectionChanged)
324        if self.plotValues:
325            self.updateSelectionArea()
326           
327    def onSelectionChanged(self):
328        self.replot_()
[1395]329        self.emit(SIGNAL("selectionChanged()"))
[950]330       
[681]331    def splitSelected(self):
[1202]332        test =  self.selection.testSelection(self.plotData)
[950]333        return (self.plotData[numpy.nonzero(test)], self.plotData[numpy.nonzero(~test)])
[681]334   
335    def setPlotValues(self, values):
336        self.plotValues = values
[950]337        self.plotData = numpy.array(values.values())
[681]338        self.replot_(setScale=True)
339
[1202]340    def createSelectionRectCurve(self, p1, p2):
341        curve = self.addCurve("selection", style=QwtPlotCurve.Lines, penColor=Qt.red, symbol=QwtSymbol.NoSymbol)
342        curve.setData([p1.x(), p2.x(), p2.x(), p1.x(), p1.x()], [p1.y(), p1.y(), p2.y(), p2.y(), p1.y()])
343       
344    def items(self, title=None):
345        for item in self.itemList():
346            if str(item.title().text()) == title:
347                yield item
348       
[681]349    def updateSelectionArea(self):
[1202]350        for c in self.items(title="selection"):
351            c.detach()
352        for p1, p2 in self.selection.selection:
353            self.createSelectionRectCurve(p1, p2)
[681]354
355    def replot_(self, setScale=False):
356        if self.plotValues:
[1202]357            data = self.plotData
[681]358            self.maxX = numpy.max(numpy.abs(data[:,0]))
359            self.maxY = numpy.max(data[:, 1])
360            if setScale:
361                self.setAxisScale(QwtPlot.xBottom, -self.maxX, self.maxX)
362                self.setAxisScale(QwtPlot.yLeft, 0.0, self.maxY)
363           
364            selected, unselected = self.splitSelected()
365           
[950]366            self.selectedCurve.setData(selected[:,0], selected[:,1])
[681]367            self.selectedCurve.setBrush(QBrush(Qt.blue))
[950]368            self.unselectedCurve.setData(unselected[:, 0], unselected[:, 1])
[681]369            self.updateSelectionArea()
[687]370            self.master.infoLabel2.setText("%i selected genes" % len(selected))
[681]371        else:
[1202]372            for curve in [self.selectedCurve, self.unselectedCurve]:
[681]373                curve.setData([],[])
[687]374            self.master.infoLabel2.setText("0 selected genes")
[681]375        self.replot()
376
377    def updateCutoff(self, axis, pos):
378        if axis == QwtPlot.xBottom:
379            self.cutoffX = abs(self.invTransform(axis, self.canvas().mapFrom(self, pos).x()))
380        elif axis == QwtPlot.yLeft:
381            self.cutoffY = self.invTransform(axis, self.canvas().mapFrom(self, pos).y())
382        else:
383            self.cutoffX = abs(self.invTransform(QwtPlot.xBottom, self.canvas().mapFrom(self, pos).x()))
384            self.cutoffY = self.invTransform(QwtPlot.yLeft, self.canvas().mapFrom(self, pos).y())
385        self.replot_()
386
387    def mousePressEvent(self, event):
388        if self.state == SELECT:
[1202]389            if event.button() == Qt.LeftButton:
390                self.selection.start(event)
[681]391        else:
392            OWGraph.mousePressEvent(self, event)
393
394    def mouseMoveEvent(self, event):
395        if self.state == SELECT:
[1202]396            if event.buttons() & Qt.LeftButton:
397                self.selection.update(event)
398            if isinstance(self.selection, SymetricSelections):
399                axes, pos = self.selection.getAxesAndPos(event)
400                cursors = {QwtPlot.xBottom: Qt.SizeHorCursor,
401                           QwtPlot.yLeft: Qt.SizeVerCursor}
402                self.canvas().setCursor(cursors.get(axes, self._cursor))
[681]403        else:
404            OWGraph.mouseMoveEvent(self, event)
405
406    def mouseReleaseEvent(self, event):
407        if self.state == SELECT:
[1202]408            if event.button() == Qt.LeftButton:
409                self.selection.end(event)
[681]410        else:
411            OWGraph.mouseReleaseEvent(self, event)
[1202]412           
413    def reselect(self, replot=True):
414        if self.symetricSelections:
415            self.setSelection(SymetricSelections(self, x=self.maxX*0.80, y=self.maxY*0.80))
416        else:
417            self.setSelection(GraphSelections(self))
418            self.canvas().setCursor(self._cursor)
419        if replot:
420            self.replot_()
[681]421
422    def updateSymbolSize(self):
[1232]423        def setSize(curve, size):
424            symbol = curve.symbol()
425            symbol.setSize(size)
426            if QWT_VERSION_STR >= "5.2":
427                curve.setSymbol(symbol)
428        setSize(self.selectedCurve, self.symbolSize)
429        setSize(self.unselectedCurve, self.symbolSize)
[681]430        self.replot()
[1385]431       
[1632]432from .OWGenotypeDistances import SetContextHandler
433from .OWFeatureSelection import disable_controls
[681]434
435class OWVulcanoPlot(OWWidget):
[1395]436    settingsList = ["graph.cutoffX", "graph.cutoffY", "graph.symbolSize", "graph.symetricSelections", "showXTitle", "showYTitle"]
[1388]437    contextHandlers = {"":DomainContextHandler("", [ContextField("graph.symbolSize"), ContextField("graph.cutoffX"),
[1385]438                                                    ContextField("graph.cutoffY")]),
439                       "targets": SetContextHandler("targets")}
[681]440    def __init__(self, parent=None, signalManager=None, name="Vulcano Plot"):
441        OWWidget.__init__(self, parent, signalManager, name, wantGraph=True)
442       
[687]443        self.inputs = [("Examples", ExampleTable, self.setData)]
444        self.outputs =[("Examples with selected attributes", ExampleTable)]
[681]445
[1395]446        self.genes_in_columns = False
[681]447
448        self.showXTitle = True
449        self.showYTitle = True
450
[1395]451        self.auto_commit = False
452        self.selection_changed_flag = False
[1385]453        self.target_group = None, []
454        self.label_selections = []
[681]455
456        self.graph = VulcanoGraph(self)
[1395]457        self.connect(self.graph, SIGNAL("selectionChanged()"), self.on_selection_changed)
[681]458        self.mainArea.layout().addWidget(self.graph)
[1395]459       
[1385]460        self.loadSettings()
461       
[681]462        ## GUI
[687]463        box = OWGUI.widgetBox(self.controlArea, "Info")
464        self.infoLabel = OWGUI.label(box, self, "")
[1385]465        self.infoLabel.setText("No data on input")
[687]466        self.infoLabel2 = OWGUI.label(box, self, "")
467        self.infoLabel2.setText("0 selected genes")
[916]468       
[1385]469        box = OWGUI.widgetBox(self.controlArea, "Target Labels")
470       
471        self.target_widget = LabelSelectionWidget(self)
472        self.connect(self.target_widget,
473                     SIGNAL("selection_changed(PyQt_PyObject, PyQt_PyObject)"),
474                     self.on_target_changed)
475        self.connect(self.target_widget,
476                     SIGNAL("label_activated(int)"),
477                     self.on_label_activated)
478       
479        box.layout().addWidget(self.target_widget)
480       
[1395]481        self.genesInColumnsCheck = OWGUI.checkBox(box, self, "genes_in_columns",
[1385]482                                    "Genes in columns", 
[1390]483                                    callback=[self.init_from_data, self.plot])
[681]484
485        box = OWGUI.widgetBox(self.controlArea, "Settings")
486        OWGUI.hSlider(box, self, "graph.symbolSize", label="Symbol size:   ", minValue=2, maxValue=20, step=1, callback = self.graph.updateSymbolSize)
487        OWGUI.checkBox(box, self, "showXTitle", "X axis title", callback=self.setAxesTitles)
488        OWGUI.checkBox(box, self, "showYTitle", "Y axis title", callback=self.setAxesTitles)
489       
[1202]490        toolbar = ZoomSelectToolbar(self, self.controlArea, self.graph, buttons=[ZoomSelectToolbar.IconSelect, ZoomSelectToolbar.IconZoom, ZoomSelectToolbar.IconPan])
[1230]491       
[1232]492        top_layout = toolbar.layout()
493        top_layout.setDirection(QBoxLayout.TopToBottom)
494        button_layotu = QHBoxLayout()
495        top_layout.insertLayout(0, button_layotu)
496       
497        for i in range(1, top_layout.count()):
498            item = top_layout.itemAt(1)
499            top_layout.removeItem(item)
500            button_layotu.addItem(item)
501       
[1230]502        OWGUI.checkBox(toolbar, self, "graph.symetricSelections", "Symetric selection", callback=self.graph.reselect)
[681]503
504        box = OWGUI.widgetBox(self.controlArea, "Commit")
[1378]505        b = OWGUI.button(box, self, "Commit", callback=self.commit, default=True)
[1395]506        cb = OWGUI.checkBox(box, self, "auto_commit", "Commit automatically")
507        OWGUI.setStopper(self, b, cb, "selection_changed_flag", self.commit_if)
[681]508
509        self.connect(self.graphButton, SIGNAL("clicked()"), self.graph.saveToFile)
510       
511        OWGUI.rubber(self.controlArea)
512
[1001]513        self.data = None
[1385]514        self.target_group = None, []
[1395]515        self.current_selection = []
[1001]516       
[902]517        self.resize(800, 600)
[681]518
[1388]519    def clear(self):
520        self.target_widget.set_labels([])
521        self.targets = []
522        self.label_selections = []
523        self.target_group = None, []
[1390]524        self.clear_graph()
525       
526    def clear_graph(self):
[1388]527        self.values = {}
528        self.graph.setPlotValues({})
529        self.updateTooltips()
530       
[681]531    def setData(self, data=None):
[1390]532        self.closeContext("")
[1385]533        self.closeContext("targets")
[1388]534        self.clear()
[681]535        self.data = data
536        self.error(0)
[1388]537        self.warning([0,1])
[916]538        if data:
[1395]539            self.genes_in_columns = not bool(data.domain.classVar)
[1099]540            self.genesInColumnsCheck.setDisabled(not bool(data.domain.classVar))
[1395]541            if self.genes_in_columns:
542                self.genes_in_columns = not data_hints.get_hint(data, "genesinrows", not self.genes_in_columns)
[1390]543            self.openContext("", data)
544        else:
545            self.infoLabel.setText("No data on input.")
546        self.init_from_data()
547           
548    def init_from_data(self):
549        """ Init widget state from the data.
550        """ 
551        self.update_target_labels()
552        self.error(0)
553        if self.data:
[916]554            if not self.targets:
[1395]555                if self.genes_in_columns:
[1390]556                    self.error(0, "Data set with no column labels (attribute tags)")
557                else:
558                    self.error(0, "Data has no class.")
[1388]559       
[1385]560        self.openContext("targets", [(label, v) for label, vals in self.targets \
561                                                for v in vals])
[916]562       
[1390]563        if len(self.label_selections) != len(self.targets): # Some times this happens.
564            self.label_selections = [[] for t in self.targets]
565           
[1385]566        if self.target_group == (None, []) and self.targets:
567            label, values = self.targets[0]
568            self.target_group = (label, values[:1])
[1322]569           
[1385]570        if self.target_group != (None, []):
571            self.target_widget.set_selection(*self.target_group)
[1388]572        else:
[1390]573            self.clear_graph()
[1385]574
575    def update_target_labels(self):
576        if self.data:
[1395]577            if self.genes_in_columns:
[1385]578                items = [a.attributes.items() for a in self.data.domain.attributes]
579                items = reduce(add, items, [])
580               
581                targets = defaultdict(set)
582                for label, value in items:
583                    targets[label].add(value)
584                   
585                targets = [(key, list(sorted(vals))) for key, vals in targets.items() \
586                           if len(vals) >= 2]
587                self.targets = targets
588               
589            else:
590                var = self.data.domain.classVar
591                values = list(var.values)
592                if len(values) >= 2:
593                    self.targets = [(var.name, values)]
594                else:
595                    self.targets = []
596        else:
597            self.targets = []
[950]598           
[1388]599        if self.targets:
600            label, values = self.targets[0]
601            self.target_group = (label, values[:1])
602        else:
603            self.target_group = None, []
604           
[1385]605        self.label_selections = [[] for t in self.targets]
606        self.target_widget.set_labels(self.targets)
607               
[916]608       
[1385]609    def on_label_activated(self, index):
610        """ Try to restore a saved selection.
611        """
612        selected = self.label_selections[index]
613        if not selected:
[1388]614            selected = self.targets[index][1][:1]
[1385]615           
616        self.target_widget.set_selection(index, selected)
617       
618    def on_target_changed(self, label, values):
619        self.target_group = label, values
620        # Save the selection
621        labels = [l for l, _ in self.targets]
622        if label in labels:
623            index = labels.index(label)
624            self.label_selections[index] = values
625           
626        # replot
627        if label and values:
628            self.plot()
[1390]629        else:
630            self.clear_graph()
[1385]631   
632    @disable_controls
[681]633    def plot(self):
634        self.values = {}
[1395]635        self.current_selection = []
[1385]636        target_label, target_values = self.target_group
[1388]637        self.warning([0, 1])
638        self.error(1)
[1385]639        if self.data and target_values:
640            target_label, target_values = self.target_group
[1395]641            if self.genes_in_columns:
[1385]642                target = set([(target_label, value) for value in target_values])
643            else:
644                target = set(target_values)
645           
[1395]646            ttest = obiExpression.ExpressionSignificance_TTest(self.data, useAttributeLabels=self.genes_in_columns)
[1385]647            ind1, ind2 = ttest.test_indices(target)
648           
[1388]649            if not len(ind1) or not len(ind2):
650                self.error(1, "Target labels most exclude/include at least one value.")
651               
[1385]652            if len(ind1) < 2 and len(ind2) < 2:
[916]653                self.warning(0, "Insufficient data to compute statistics. More than one measurement per class should be provided")
[1385]654           
[681]655            self.progressBarInit()
[1388]656            try:
657                tt = ttest(target)
658                self.progressBarSet(25)
[1395]659                fold = obiExpression.ExpressionSignificance_FoldChange(self.data, useAttributeLabels=self.genes_in_columns)(target)
[1388]660                self.progressBarSet(50)
661            except ZeroDivisionError, ex:
662                tt, fold = [], []
[916]663            self.infoLabel.setText("%i genes on input" % len(fold))
[1385]664           
[916]665            invalid = set([key for (key, (t, p)), (_, f) in zip(tt, fold) if any(v is numpy.ma.masked for v in [t, p, f]) or f==0.0])
666            tt = [t for t in tt if t[0] not in invalid]
667            fold = [f for f in fold if f[0] not in invalid]
668            self.progressBarSet(75)
669            logratio = numpy.log2(numpy.abs([v for k, v in fold]))
670            logpval = -numpy.log10([p for k, (t, p) in tt])
671            self.values = dict(zip([k for k, v in tt], zip(logratio, logpval)))
[1383]672            if not self.values:
673                self.warning(1, "Could not compute statistics for any genes!")
[681]674            self.progressBarFinished()
675        self.graph.setPlotValues(self.values)
676        self.setAxesTitles()
677        self.updateTooltips()
678
679    def setAxesTitles(self):
[1252]680        self.graph.setAxisTitle(QwtPlot.xBottom, "log<sub>2</sub> (ratio)" if self.showXTitle else "")
681        self.graph.setAxisTitle(QwtPlot.yLeft, "-log<sub>10</sub> (p_value)" if self.showYTitle else "")
[681]682
683    def updateTooltips(self):
684        self.graph.tips.removeAll()
[916]685        for key, (logratio, logpval) in self.values.items():
[1252]686            self.graph.tips.addToolTip(logratio, logpval, "<b>%s</b><hr>log<sub>2</sub>(ratio): %.5f<br>p-value: %.5f" \
[1395]687                                       %(str(key) if self.genes_in_columns else key.name, logratio, math.pow(10, -logpval)))
688           
689    def selection(self, items=None):
690        """ Return the current selection.
691        """
692        if items is None:
693            items = sorted(self.values.items())
694        values = [val for key, val in items]
695        test = self.graph.selection.testSelection(values)
696        return test
697   
698    def on_selection_changed(self):
699        """ Called when user changes the selection area on the plot.
700        """
701        if self.auto_commit:
702            selection = list(self.selection())
703            # Did the selection actually change
704            if selection != self.current_selection: 
705                self.current_selection = selection
706                self.commit()
707        else:
708            self.selection_changed_flag = True
709   
[681]710    def commit(self):
[1395]711        if self.data and self.genes_in_columns:
[1202]712            items = sorted(self.values.items())
[1395]713            test = self.selection(items)
[1202]714            selected = [self.data[i] for t, (i, value) in zip(test, items) if t]
[916]715            if selected:
716                data = orange.ExampleTable(self.data.domain, selected)
717            else:
718                data = None
[1395]719            self.current_selection = list(test) # For testing in on_selection_changed
[916]720        elif self.data:
[1202]721            attrs = [(attr, self.values[attr])  for attr in self.data.domain.attributes if attr in self.values]
[1395]722            test = self.selection(attrs)
723#            test = self.graph.selection.testSelection([val for attr, val in attrs])
[1202]724            selected = [attr for t, (attr, val) in zip(test, attrs) if t]
[681]725            newdomain = orange.Domain(selected + [self.data.domain.classVar])
726            newdomain.addmetas(self.data.domain.getmetas())
727            data = orange.ExampleTable(newdomain, self.data)
[1395]728            self.current_selection = list(test) # For testing in on_selection_changed
[916]729        else:
730            data = None
[1202]731       
[916]732        self.send("Examples with selected attributes", data)
[1395]733        self.selection_changed_flag = False
[681]734
[1395]735    def commit_if(self):
736        if self.auto_commit:
[681]737            self.commit()
[916]738        else:
[1395]739            self.selection_changed_flag = True
[1385]740           
741    def settingsToWidgetCallbacktargets(self, handler, context):
742        self.label_selections = list(getattr(context, "label_selections", self.label_selections))
743        self.target_group = getattr(context, "target_group", self.target_group)
744       
745    def settingsFromWidgetCallbacktargets(self, handler, context):
746        context.label_selections = list(self.label_selections)
747        context.target_group = self.target_group
[681]748       
749if __name__ == "__main__":
750    ap = QApplication(sys.argv)
751    w = OWVulcanoPlot()
[694]752##    d = orange.ExampleTable("E:\\affy(HD-CC)_GS_C2cpC5.tab")
[1099]753#    d = orange.ExampleTable("E:\\steroltalk-smallchip.tab")
754    d = orange.ExampleTable("../../../doc/datasets/brown-selected.tab")
[681]755    w.setData(d)
756    w.show()
757    ap.exec_()
758    w.saveSettings()
759
760               
[764]761       
Note: See TracBrowser for help on using the repository browser.