source: orange-bioinformatics/orangecontrib/bio/widgets/OWVulcanoPlot.py @ 1874:b3e32cc5cf6f

Revision 1874:b3e32cc5cf6f, 28.7 KB checked in by Ales Erjavec <ales.erjavec@…>, 7 months ago (diff)

Added new style widget meta descriptions.

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