Factored out a mixin class for IC thresholding.
This commit is contained in:
parent
0523ebab05
commit
3f7215bc35
|
@ -491,7 +491,7 @@ class PlotDagFunction(workflow.Function):
|
||||||
ds = dataset.GraphDataset(networkx.adj_matrix(g),
|
ds = dataset.GraphDataset(networkx.adj_matrix(g),
|
||||||
[('go-terms', g.nodes()), ('_go-terms', g.nodes())],
|
[('go-terms', g.nodes()), ('_go-terms', g.nodes())],
|
||||||
name="DAG")
|
name="DAG")
|
||||||
return [DagPlot(g)]
|
return [ThresholdDagPlot(g)]
|
||||||
|
|
||||||
def get_network(self, terms, subtree='bp'):
|
def get_network(self, terms, subtree='bp'):
|
||||||
"""Returns a DAG connecting the given terms by including their parents
|
"""Returns a DAG connecting the given terms by including their parents
|
||||||
|
@ -558,13 +558,117 @@ class VolcanoPlot(plots.ScatterPlot):
|
||||||
name="Volcano plot",
|
name="Volcano plot",
|
||||||
sel_dim_2='_p', **kw)
|
sel_dim_2='_p', **kw)
|
||||||
|
|
||||||
|
|
||||||
|
class PlotThresholder:
|
||||||
|
"""Mixin class for plots that needs to filter nodes within a threshold
|
||||||
|
range.
|
||||||
|
"""
|
||||||
|
def __init__(self, text="x"):
|
||||||
|
"""Constructor.
|
||||||
|
|
||||||
|
@param text: Name of the variable the threshold is on.
|
||||||
|
"""
|
||||||
|
self._threshold_ds = None
|
||||||
|
self._add_spin_buttons(text)
|
||||||
|
self._sb_min.set_sensitive(False)
|
||||||
|
self._sb_max.set_sensitive(False)
|
||||||
|
|
||||||
|
def set_threshold_dataset(self, ds):
|
||||||
|
"""Sets the dataset to threshold on.
|
||||||
|
|
||||||
|
@param ds: A dataset where one dimension corresponds to the select dimension
|
||||||
|
in the plot, and any other dimensions have length 1
|
||||||
|
"""
|
||||||
|
self._threshold_ds = ds
|
||||||
|
self._sb_min.set_sensitive(True)
|
||||||
|
self._sb_max.set_sensitive(True)
|
||||||
|
|
||||||
|
def _add_spin_buttons(self, text):
|
||||||
|
"""Adds spin buttons to the toolbar for selecting minimum and maximum
|
||||||
|
threshold values on information content."""
|
||||||
|
sb_min = gtk.SpinButton(digits=2)
|
||||||
|
sb_min.set_range(0, 100)
|
||||||
|
sb_min.set_value(0)
|
||||||
|
sb_min.set_increments(.1, 1.)
|
||||||
|
sb_min.connect('value-changed', self._on_value_changed)
|
||||||
|
self._sb_min = sb_min
|
||||||
|
|
||||||
|
sb_max = gtk.SpinButton(digits=2)
|
||||||
|
sb_max.set_range(0, 100)
|
||||||
|
sb_max.set_value(1)
|
||||||
|
sb_max.set_increments(.1, 1.)
|
||||||
|
sb_max.connect('value-changed', self._on_value_changed)
|
||||||
|
self._sb_max = sb_max
|
||||||
|
|
||||||
|
label = gtk.Label(" < %s < " % text)
|
||||||
|
hbox = gtk.HBox()
|
||||||
|
hbox.pack_start(sb_min)
|
||||||
|
hbox.pack_start(label)
|
||||||
|
hbox.pack_start(sb_max)
|
||||||
|
ti = gtk.ToolItem()
|
||||||
|
ti.set_expand(False)
|
||||||
|
ti.add(hbox)
|
||||||
|
sb_min.show()
|
||||||
|
sb_max.show()
|
||||||
|
label.show()
|
||||||
|
hbox.show()
|
||||||
|
ti.show()
|
||||||
|
self._toolbar.insert(ti, -1)
|
||||||
|
ti.set_tooltip(self._toolbar.tooltips, "Set threshold")
|
||||||
|
|
||||||
|
def set_threshold(self, min, max):
|
||||||
|
"""Sets min and max to the given values.
|
||||||
|
Updates the plot accordingly to show only values that have a
|
||||||
|
value within the boundaries. Other values are
|
||||||
|
also excluded from being selected from the plot.
|
||||||
|
@param ic_min Do not show nodes with IC below this value.
|
||||||
|
@param ic_max Do not show nodes with IC above this value.
|
||||||
|
"""
|
||||||
|
ds = self._threshold_ds
|
||||||
|
if ds == None:
|
||||||
|
return
|
||||||
|
|
||||||
|
icnodes = ds.existing_identifiers('go-terms', self.nodes)
|
||||||
|
icindices = ds.get_indices('go-terms', icnodes)
|
||||||
|
a = ravel(ds.asarray()[icindices])
|
||||||
|
good = set(array(icnodes)[(a>=min) & (a<=max)])
|
||||||
|
|
||||||
|
sizes = zeros(len(self.nodes))
|
||||||
|
visible = set()
|
||||||
|
for i, n in enumerate(self.nodes):
|
||||||
|
if n in good:
|
||||||
|
sizes[i] = 50
|
||||||
|
visible.add(n)
|
||||||
|
else:
|
||||||
|
sizes[i] = 0
|
||||||
|
self.visible = visible
|
||||||
|
|
||||||
|
self.node_collection._sizes = sizes
|
||||||
|
self.canvas.draw()
|
||||||
|
|
||||||
|
def get_nodes_within_bounds(self):
|
||||||
|
"""Get a list of all nodes within the bounds of the selection in the
|
||||||
|
seleted dataset.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def filter_nodes(self, nodes):
|
||||||
|
"""Filter a list of nodes and return only those that are within the
|
||||||
|
threshold boundaries."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _on_value_changed(self, sb):
|
||||||
|
"""Callback on spin button value changes."""
|
||||||
|
min = self._sb_min.get_value()
|
||||||
|
max = self._sb_max.get_value()
|
||||||
|
self.set_threshold(min, max)
|
||||||
|
|
||||||
|
|
||||||
class DagPlot(plots.Plot):
|
class DagPlot(plots.Plot):
|
||||||
def __init__(self, graph, dim='go-terms', pos=None, nodecolor='b', nodesize=40,
|
def __init__(self, graph, dim='go-terms', pos=None, nodecolor='b', nodesize=40,
|
||||||
with_labels=False, name='DAG Plot'):
|
with_labels=False, name='DAG Plot'):
|
||||||
|
|
||||||
plots.Plot.__init__(self, name)
|
plots.Plot.__init__(self, name)
|
||||||
self._add_ic_spin_buttons()
|
|
||||||
self.nodes = graph.nodes()
|
self.nodes = graph.nodes()
|
||||||
self.graph = graph
|
self.graph = graph
|
||||||
self._pos = pos
|
self._pos = pos
|
||||||
|
@ -630,39 +734,6 @@ class DagPlot(plots.Plot):
|
||||||
self.axes.set_frame_on(False)
|
self.axes.set_frame_on(False)
|
||||||
self.fig.subplots_adjust(left=0, right=1, bottom=0, top=1)
|
self.fig.subplots_adjust(left=0, right=1, bottom=0, top=1)
|
||||||
|
|
||||||
def _add_ic_spin_buttons(self):
|
|
||||||
"""Adds spin buttons to the toolbar for selecting minimum and maximum
|
|
||||||
threshold values on information content."""
|
|
||||||
sb_min = gtk.SpinButton(digits=2)
|
|
||||||
sb_min.set_range(0, 100)
|
|
||||||
sb_min.set_value(0)
|
|
||||||
sb_min.set_increments(.1, 1.)
|
|
||||||
sb_min.connect('value-changed', self._on_ic_value_changed)
|
|
||||||
self._ic_sb_min = sb_min
|
|
||||||
|
|
||||||
sb_max = gtk.SpinButton(digits=2)
|
|
||||||
sb_max.set_range(0, 100)
|
|
||||||
sb_max.set_value(1)
|
|
||||||
sb_max.set_increments(.1, 1.)
|
|
||||||
sb_max.connect('value-changed', self._on_ic_value_changed)
|
|
||||||
self._ic_sb_max = sb_max
|
|
||||||
|
|
||||||
label = gtk.Label(" < IC < ")
|
|
||||||
hbox = gtk.HBox()
|
|
||||||
hbox.pack_start(sb_min)
|
|
||||||
hbox.pack_start(label)
|
|
||||||
hbox.pack_start(sb_max)
|
|
||||||
ti = gtk.ToolItem()
|
|
||||||
ti.set_expand(False)
|
|
||||||
ti.add(hbox)
|
|
||||||
sb_min.show()
|
|
||||||
sb_max.show()
|
|
||||||
label.show()
|
|
||||||
hbox.show()
|
|
||||||
ti.show()
|
|
||||||
self._toolbar.insert(ti, -1)
|
|
||||||
ti.set_tooltip(self._toolbar.tooltips, "Set information content threshold")
|
|
||||||
|
|
||||||
def _calc_pos(self, graph):
|
def _calc_pos(self, graph):
|
||||||
"""Calculates position for graph nodes using 'dot' layout."""
|
"""Calculates position for graph nodes using 'dot' layout."""
|
||||||
gv_graph = networkx.DiGraph()
|
gv_graph = networkx.DiGraph()
|
||||||
|
@ -678,44 +749,7 @@ class DagPlot(plots.Plot):
|
||||||
pos[k] = v
|
pos[k] = v
|
||||||
return pos
|
return pos
|
||||||
|
|
||||||
def set_ic_threshold(self, ic_min, ic_max):
|
def points_in_rect(self, x1, y1, x2, y2, key):
|
||||||
"""Sets Information Content min and max to the given values.
|
|
||||||
Updates the plot accordingly to show only values that have an
|
|
||||||
information content within the boundaries. Other values are
|
|
||||||
also excluded from being selected from the plot.
|
|
||||||
@param ic_min Do not show nodes with IC below this value.
|
|
||||||
@param ic_max Do not show nodes with IC above this value.
|
|
||||||
"""
|
|
||||||
ic = getattr(main.workflow, 'current_ic', None)
|
|
||||||
if ic == None:
|
|
||||||
print "no ic set"
|
|
||||||
return
|
|
||||||
|
|
||||||
icnodes = ic.existing_identifiers('go-terms', self.nodes)
|
|
||||||
icindices = ic.get_indices('go-terms', icnodes)
|
|
||||||
a = ravel(ic.asarray()[icindices])
|
|
||||||
ic_good = set(array(icnodes)[(a>=ic_min) & (a<=ic_max)])
|
|
||||||
|
|
||||||
sizes = zeros(len(self.nodes))
|
|
||||||
visible = set()
|
|
||||||
for i, n in enumerate(self.nodes):
|
|
||||||
if n in ic_good:
|
|
||||||
sizes[i] = 50
|
|
||||||
visible.add(n)
|
|
||||||
else:
|
|
||||||
sizes[i] = 0
|
|
||||||
self.visible = visible
|
|
||||||
|
|
||||||
self.node_collection._sizes = sizes
|
|
||||||
self.canvas.draw()
|
|
||||||
|
|
||||||
def _on_ic_value_changed(self, sb):
|
|
||||||
"""Callback on spin button value changes."""
|
|
||||||
ic_min = self._ic_sb_min.get_value()
|
|
||||||
ic_max = self._ic_sb_max.get_value()
|
|
||||||
self.set_ic_threshold(ic_min, ic_max)
|
|
||||||
|
|
||||||
def rectangle_select_callback(self, x1, y1, x2, y2, key):
|
|
||||||
ydata = self.yaxis_data
|
ydata = self.yaxis_data
|
||||||
xdata = self.xaxis_data
|
xdata = self.xaxis_data
|
||||||
|
|
||||||
|
@ -732,7 +766,12 @@ class DagPlot(plots.Plot):
|
||||||
ids = self.visible.intersection([self.nodes[i] for i in index])
|
ids = self.visible.intersection([self.nodes[i] for i in index])
|
||||||
else:
|
else:
|
||||||
ids = set([self.nodes[i] for i in index])
|
ids = set([self.nodes[i] for i in index])
|
||||||
|
return ids
|
||||||
|
|
||||||
|
def rectangle_select_callback(self, x1, y1, x2, y2, key):
|
||||||
|
ids = self.points_in_rect(x1, y1, x2, y2, key)
|
||||||
ids = self.update_selection(ids, key)
|
ids = self.update_selection(ids, key)
|
||||||
|
|
||||||
self.selection_listener(self.current_dim, ids)
|
self.selection_listener(self.current_dim, ids)
|
||||||
|
|
||||||
def lasso_select_callback(self, verts, key=None):
|
def lasso_select_callback(self, verts, key=None):
|
||||||
|
@ -807,9 +846,34 @@ class DagPlot(plots.Plot):
|
||||||
self.node_collection.set_array(map_vec)
|
self.node_collection.set_array(map_vec)
|
||||||
self.node_collection.set_clim(vec_min, vec_max)
|
self.node_collection.set_clim(vec_min, vec_max)
|
||||||
self.node_collection.update_scalarmappable() #sets facecolors from array
|
self.node_collection.update_scalarmappable() #sets facecolors from array
|
||||||
self._ic_sb_min.set_range(0, vec_max)
|
|
||||||
self._ic_sb_min.set_value(vec_min)
|
|
||||||
self._ic_sb_max.set_range(0, vec_max)
|
|
||||||
self._ic_sb_max.set_value(vec_max)
|
|
||||||
|
|
||||||
self.canvas.draw()
|
self.canvas.draw()
|
||||||
|
|
||||||
|
|
||||||
|
class ThresholdDagPlot(DagPlot, PlotThresholder):
|
||||||
|
def __init__(self, graph, dim='go-terms', pos=None, nodecolor='b', nodesize=40,
|
||||||
|
with_labels=False, name='DAG Plot'):
|
||||||
|
DagPlot.__init__(self, graph, dim='go-terms', pos=None,
|
||||||
|
nodecolor='b', nodesize=40,
|
||||||
|
with_labels=False, name='DAG Plot')
|
||||||
|
PlotThresholder.__init__(self, "IC")
|
||||||
|
|
||||||
|
def rectangle_select_callback(self, x1, y1, x2, y2, key):
|
||||||
|
ids = self.points_in_rect(x1, y1, x2, y2, key)
|
||||||
|
ids = self.visible.intersection(ids)
|
||||||
|
ids = self.update_selection(ids, key)
|
||||||
|
|
||||||
|
self.selection_listener(self.current_dim, ids)
|
||||||
|
|
||||||
|
def _update_color_from_dataset(self, ds):
|
||||||
|
DagPlot._update_color_from_dataset(self, ds)
|
||||||
|
self.set_threshold_dataset(ds)
|
||||||
|
a = ds.asarray()
|
||||||
|
a_max = max(a[a<inf])
|
||||||
|
a_min = min(a[a>-inf])
|
||||||
|
self._sb_min.set_range(0, a_max)
|
||||||
|
self._sb_min.set_value(a_min)
|
||||||
|
self._sb_max.set_range(0, a_max)
|
||||||
|
self._sb_max.set_value(a_max)
|
||||||
|
|
||||||
|
|
||||||
|
|
Reference in New Issue