Commit 50066325 authored by Leo Gordon's avatar Leo Gordon
Browse files

diagram improvement: (1) no more "empty boxes" and (2) tables dataflown from a...

diagram improvement: (1) no more "empty boxes" and (2) tables dataflown from a box are shown in their boxes
parent af7da3a7
......@@ -74,6 +74,6 @@
"DisplayDetails" : 1,
"DisplayStretched" : 0,
"DisplaySemaphoreBoxes" : 1,
"DuplicateTables" : 0,
"DuplicateTables" : 0,
}
}
......@@ -108,6 +108,12 @@ sub _analysis_node_name {
return 'analysis_' . $analysis_id;
}
sub _table_node_name {
my $table_name = shift @_;
return 'table_' . $table_name;
}
sub _midpoint_name {
my $rule_id = shift @_;
......@@ -134,13 +140,14 @@ sub build {
my %inflow_count = (); # used to detect sources (nodes with zero inflow)
my %outflow_rules = (); # maps from anlaysis_node_name to a list of all dataflow rules that flow out of it
my %dfr_flows_into= (); # maps from dfr_id to target analysis_node_name
my %dfr_flows_into_node = (); # maps from dfr_id to target analysis_node_name
foreach my $rule ( @$all_dataflow_rules ) {
if(my $to_id = $rule->to_analysis->can('dbID') && $rule->to_analysis->dbID()) {
my $to_node_name = _analysis_node_name( $to_id );
my $target_object = $rule->to_analysis;
if(my $to_id = $target_object->can('dbID') && $target_object->dbID()) {
my $to_node_name = _analysis_node_name( $to_id );
$inflow_count{$to_node_name}++;
$dfr_flows_into{$rule->dbID()} = $to_node_name;
$dfr_flows_into_node{$rule->dbID()} = $to_node_name;
}
push @{$outflow_rules{ _analysis_node_name($rule->from_analysis_id()) }}, $rule;
}
......@@ -149,10 +156,9 @@ sub build {
# NB: this is a very approximate algorithm with rough edges!
# It will not find all start nodes in cyclic components!
foreach my $analysis_id ( map { $_->dbID } @$all_analyses ) {
my $analysis_node_name = _analysis_node_name( $analysis_id );
unless($inflow_count{$analysis_node_name}) {
$self->_allocate_to_subgraph(\%outflow_rules, \%dfr_flows_into, $analysis_node_name, \%subgraph_allocation ); # run the recursion in each component that has a non-cyclic start
foreach my $source_analysis_node_name ( map { _analysis_node_name( $_->dbID ) } @$all_analyses ) {
unless($inflow_count{$source_analysis_node_name}) { # if there is no dataflow into this analysis
$self->_allocate_to_subgraph(\%outflow_rules, \%dfr_flows_into_node, $source_analysis_node_name, \%subgraph_allocation ); # run the recursion in each component that has a non-cyclic start
}
}
......@@ -161,7 +167,7 @@ sub build {
$self->_add_analysis_node($a);
}
$self->_control_rules( $all_ctrl_rules );
$self->_dataflow_rules( $all_dataflow_rules );
$self->_dataflow_rules( $all_dataflow_rules, \%subgraph_allocation );
if($self->config_get('DisplayStretched') ) {
......@@ -191,50 +197,57 @@ sub build {
sub _allocate_to_subgraph {
my ($self, $outflow_rules, $dfr_flows_into, $parent_analysis_node_name, $subgraph_allocation ) = @_;
my ($self, $outflow_rules, $dfr_flows_into_node, $source_analysis_node_name, $subgraph_allocation ) = @_;
my $parent_allocation = $subgraph_allocation->{ $parent_analysis_node_name }; # for some analyses it will be undef
my $source_analysis_allocation = $subgraph_allocation->{ $source_analysis_node_name }; # for some analyses it will be undef
foreach my $rule ( @{ $outflow_rules->{$parent_analysis_node_name} } ) {
my $to_analysis = $rule->to_analysis();
next unless $to_analysis->can('dbID') or $self->config_get('DuplicateTables');
foreach my $rule ( @{ $outflow_rules->{$source_analysis_node_name} } ) {
my $target_object = $rule->to_analysis();
my $target_node_name;
my $this_analysis_node_name;
if ($to_analysis->can('dbID')) {
$this_analysis_node_name = _analysis_node_name( $rule->to_analysis->dbID() );
} else {
$this_analysis_node_name = $to_analysis->table_name();
$this_analysis_node_name .= '_'.$rule->from_analysis_id() if $self->config_get('DuplicateTables');
if ($target_object->can('dbID')) { # target is an analysis
$target_node_name = _analysis_node_name( $rule->to_analysis->dbID() );
} else { # target is a table
$target_node_name = _table_node_name($target_object->table_name()) . '_' .
($self->config_get('DuplicateTables') ? $rule->from_analysis_id() : ($source_analysis_allocation||''));
}
my $funnel_dataflow_rule_id = $rule->funnel_dataflow_rule_id();
my $proposed_allocation = $funnel_dataflow_rule_id # depends on whether we start a new semaphore
# ? $dfr_flows_into->{$funnel_dataflow_rule_id} # if we do, report to the new funnel (based on common funnel's analysis name)
? _midpoint_name( $funnel_dataflow_rule_id ) # if we do, report to the new funnel (based on common funnel rule's midpoint)
: $parent_allocation; # it we don't, inherit the parent's funnel
my $proposed_allocation; # will depend on whether we start a new semaphore
my $funnel_dataflow_rule_id = $rule->funnel_dataflow_rule_id();
if( $funnel_dataflow_rule_id ) {
$proposed_allocation =
$dfr_flows_into_node->{$funnel_dataflow_rule_id}; # if we do start a new semaphore, report to the new funnel (based on common funnel's analysis name)
# _midpoint_name( $funnel_dataflow_rule_id ); # if we do start a new semaphore, report to the new funnel (based on common funnel rule's midpoint)
if($funnel_dataflow_rule_id) {
my $fan_midpoint_name = _midpoint_name( $rule->dbID() );
$subgraph_allocation->{ $fan_midpoint_name } = $proposed_allocation;
my $funnel_midpoint_name = _midpoint_name( $funnel_dataflow_rule_id );
$subgraph_allocation->{ $funnel_midpoint_name } = $parent_allocation; # draw the funnel's midpoint outside of the box
$subgraph_allocation->{ $funnel_midpoint_name } = $source_analysis_allocation; # draw the funnel's midpoint outside of the box
} else {
$proposed_allocation = $source_analysis_allocation; # if we don't start a new semaphore, inherit the allocation of the source
}
if( exists $subgraph_allocation->{ $this_analysis_node_name } ) { # we allocate on first-come basis at the moment
my $known_allocation = $subgraph_allocation->{ $this_analysis_node_name } || '';
# we allocate on first-come basis at the moment:
if( exists $subgraph_allocation->{ $target_node_name } ) { # already allocated?
my $known_allocation = $subgraph_allocation->{ $target_node_name } || '';
$proposed_allocation ||= '';
if( $known_allocation eq $proposed_allocation) {
# warn "analysis '$this_analysis_node_name' has already been allocated to the same '$known_allocation' by another branch";
# warn "analysis '$target_node_name' has already been allocated to the same '$known_allocation' by another branch";
} else {
# warn "analysis '$this_analysis_node_name' has already been allocated to '$known_allocation' however this branch would allocate it to '$proposed_allocation'";
# warn "analysis '$target_node_name' has already been allocated to '$known_allocation' however this branch would allocate it to '$proposed_allocation'";
}
if($funnel_dataflow_rule_id) { # correction for multiple entries into the same box (probably needs re-thinking)
my $fan_midpoint_name = _midpoint_name( $rule->dbID() );
$subgraph_allocation->{ $fan_midpoint_name } = $subgraph_allocation->{ $target_node_name };
}
} else {
# warn "allocating analysis '$this_analysis_node_name' to '$proposed_allocation'";
$subgraph_allocation->{ $this_analysis_node_name } = $proposed_allocation;
# warn "allocating analysis '$target_node_name' to '$proposed_allocation'";
$subgraph_allocation->{ $target_node_name } = $proposed_allocation;
$self->_allocate_to_subgraph( $outflow_rules, $dfr_flows_into, $this_analysis_node_name, $subgraph_allocation );
$self->_allocate_to_subgraph( $outflow_rules, $dfr_flows_into_node, $target_node_name, $subgraph_allocation );
}
}
}
......@@ -341,7 +354,7 @@ sub _control_rules {
sub _dataflow_rules {
my ($self, $all_dataflow_rules) = @_;
my ($self, $all_dataflow_rules, $subgraph_allocation) = @_;
my $graph = $self->graph();
my $dataflow_colour = $self->config_get('Edge', 'Data', 'Colour');
......@@ -373,8 +386,10 @@ sub _dataflow_rules {
$to_id = $to->dbID();
$to_node = _analysis_node_name($to_id);
} elsif(check_ref($to, 'Bio::EnsEMBL::Hive::NakedTable')) {
$to_node = 'table_' . $to->table_name;
$to_node .= '_'.$from_analysis_id if $self->config_get('DuplicateTables');
$to_node = _table_node_name($to->table_name) . '_' .
( $self->config_get('DuplicateTables') ? $rule->from_analysis_id() : ($subgraph_allocation->{$from_node}||''));
$self->_add_table_node($to_node, $to->table_name);
} else {
warn('Do not know how to handle the type '.ref($to));
......
......@@ -41,9 +41,9 @@ sub get_top_clusters {
my $subgraphs = $self->subgraphs();
my %set = ();
foreach my $top_cluster (values %$subgraphs) {
if( $top_cluster and !$subgraphs->{ $top_cluster } ) { # if it's a valid node not mentioned in the keys, it is a top cluster
$set{$top_cluster}++;
foreach my $potential_top_cluster (values %$subgraphs) {
if( $potential_top_cluster and !$subgraphs->{ $potential_top_cluster } ) { # if it's a valid node not mentioned in the keys, it is a top cluster
$set{$potential_top_cluster}++;
}
}
return [ keys %set ];
......@@ -64,10 +64,9 @@ sub get_nodes_that_point_at {
}
sub generate_subgraph {
sub display_subgraph {
my ($self, $cluster_name, $depth) = @_;
my $subgraphs = $self->subgraphs();
my $colour_scheme = $self->colour_scheme();
my $colour_offset = $self->colour_offset();
......@@ -76,7 +75,7 @@ sub generate_subgraph {
my $text = '';
$text .= $prefix . "subgraph cluster_${cluster_name} {\n";
# $text .= $prefix . "\tlabel=\"$cluster_name\";\n";
# $text .= $prefix . "\tlabel=\"$cluster_name\";\n";
$text .= $prefix . "\tcolorscheme=$colour_scheme;\n";
$text .= $prefix . "\tstyle=filled;\n";
$text .= $prefix . "\tcolor=".($depth+$colour_offset).";\n";
......@@ -85,7 +84,7 @@ sub generate_subgraph {
$text .= $prefix . "\t${node_name};\n";
if( @{ $self->get_nodes_that_point_at( $node_name ) } ) {
$text .= $self->generate_subgraph( $node_name, $depth+1 );
$text .= $self->display_subgraph( $node_name, $depth+1 );
}
}
$text .= $prefix . "}\n";
......@@ -99,12 +98,10 @@ sub _as_debug {
my $text = $self->SUPER::_as_debug;
my $subgraphs = $self->subgraphs();
$text=~s/^}$//m;
foreach my $node_name ( @{ $self->get_top_clusters() } ) {
$text .= $self->generate_subgraph( $node_name, 1);
$text .= $self->display_subgraph( $node_name, 1);
}
$text .= "}\n";
......@@ -115,7 +112,7 @@ sub _as_debug {
$text=~s/^(\s+analysis_.*)"record"/$1"Mrecord"/mg;
# uncomment the following line to see the final input to dot
# print $text;
# print $text;
return $text;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment