Skip to content

Facilitate config of contributing gene trees #1095

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Aug 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion modules/EnsEMBL/Draw/GlyphSet/genetree.pm
Original file line number Diff line number Diff line change
Expand Up @@ -840,7 +840,22 @@ sub features {

if ($show_exons) {
my $ref_genetree = $tree->tree;
$ref_genetree = $ref_genetree->alternative_trees->{default} if $ref_genetree->ref_root_id;

if ($ref_genetree->ref_root_id) {

# If $ref_genetree is a contributing tree, we need to fetch the
# corresponding reference tree in order to get exon boundary data.
my @matching_ref_genetrees = grep {
!$_->ref_root_id && $_->root_id == $ref_genetree->ref_root_id
} values %{$ref_genetree->alternative_trees};

# Gene trees are uniquely identified by their root_id, so there can be at
# most one gene tree with a root_id matching $ref_genetree->ref_root_id
if (scalar(@matching_ref_genetrees) > 0) {
$ref_genetree = $matching_ref_genetrees[0];
}
}

unless ($ref_genetree->{_exon_boundaries_hash}) {
my $gtos_adaptor = $tree->adaptor->db->get_GeneTreeObjectStoreAdaptor;
my $json_string = $gtos_adaptor->fetch_by_GeneTree_and_label($ref_genetree, 'exon_boundaries');
Expand Down
2 changes: 1 addition & 1 deletion modules/EnsEMBL/Web/Command/DataExport/Output.pm
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ sub process {
$url_params->{'__clear'} = 1;
## Pass parameters needed for Back button to work
my @core_params = keys %{$hub->core_object('parameters')};
push @core_params, qw(export_action data_type data_action component align g1 node strain hom_id);
push @core_params, qw(export_action data_type data_action component align align_type clusterset_id g1 hom_id node strain);
push @core_params, $self->config_params;
foreach (@core_params) {
my @values = $component->param($_);
Expand Down
8 changes: 4 additions & 4 deletions modules/EnsEMBL/Web/Component/DataExport/GeneTree.pm
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ sub content {
my $view_config = $self->view_config;

my $settings = $view_config->form_fields('export');
$settings->{'Hidden'} = [qw(align align_type node strain)];
$settings->{'Hidden'} = [qw(align align_type clusterset_id node strain)];

## Add export-specific settings
my $fields_by_format;
Expand Down Expand Up @@ -87,9 +87,9 @@ sub content {

## Options per format
$fields_by_format = [{'Tree formats' => {
'Newick' => [qw(newick_mode clusterset_id)],
'NHX' => [qw(nhx_mode clusterset_id)],
'Text' => [qw(scale clusterset_id)],
'Newick' => [qw(newick_mode)],
'NHX' => [qw(nhx_mode)],
'Text' => [qw(scale)],
'OrthoXML' => [],
'PhyloXML' => $self->phyloxml_fields,
}}];
Expand Down
30 changes: 23 additions & 7 deletions modules/EnsEMBL/Web/Component/Gene/ComparaTree.pm
Original file line number Diff line number Diff line change
Expand Up @@ -164,20 +164,36 @@ sub content {
}

if ($hub->type eq 'Gene') {
if ($tree->tree->clusterset_id ne $clusterset_id) {
$html .= $self->_info('Phylogenetic model selection',
sprintf(
'The phylogenetic model <i>%s</i> is not available for this tree. Showing the <i>%s</i> tree instead.', $clusterset_id, $tree->tree->clusterset_id,
)
);
my $tree_clusterset_id = $tree->tree->clusterset_id;
if ($tree_clusterset_id ne $clusterset_id) {
my $strain_clusterset_id = $hub->species_defs->get_config($self->hub->species, 'RELATED_TAXON');
# When switching between the respective consensus trees of the default and strain gene-tree view
# (e.g. 'default' to 'murinae'), each clusterset_id represents the consensus clusterset for its
# respective view, so we skip the model selection info box in such cases.
unless ( $strain_clusterset_id
&&
(
($clusterset_id eq 'default' && $tree_clusterset_id eq $strain_clusterset_id)
||
($clusterset_id eq $strain_clusterset_id && $tree_clusterset_id eq 'default')
)
) {
$html .= $self->_info('Phylogenetic model selection',
sprintf(
'The phylogenetic model <i>%s</i> is not available for this tree. Showing the <i>%s</i> tree instead.',
$clusterset_id,
$tree_clusterset_id,
)
);
}
} elsif ($tree->tree->ref_root_id) {

my $text = sprintf(
'The tree displayed here has been built with the phylogenetic model <I>%s</I>. It has then been merged with trees built with other models to give the final tree and homologies. Data shown here may be inconsistent with the rest of the comparative analyses, especially homologies.', $clusterset_id
);
my $rank = $tree->tree->get_tagvalue('k_score_rank');
my $score = $tree->tree->get_tagvalue('k_score');
$text .= sprintf('<br/>This tree is the <b>n&deg;%d</b> closest to the final tree, with a K-distance of <b>%f</b>, as computed by <a href="http://molevol.cmima.csic.es/castresana/Ktreedist.html">Ktreedist</a>.', $rank, $score) if $rank;
$text .= sprintf('<br/>This tree is the <b>n&deg;%d</b> closest to the final tree, with a K-distance of <b>%f</b>, as computed by <a href="https://www.biologiaevolutiva.org/jcastresana/Ktreedist.html">Ktreedist</a>.', $rank, $score) if $rank;
$html .= $self->_info('Phylogenetic model selection', $text);
}
}
Expand Down
29 changes: 26 additions & 3 deletions modules/EnsEMBL/Web/Object/Gene.pm
Original file line number Diff line number Diff line change
Expand Up @@ -936,23 +936,46 @@ sub get_homologue_alignments {
}


sub _resolve_clusterset_ids {
my ($self, $strain_tree) = @_;

my $consensus_clusterset_id = $strain_tree || 'default';
my $clusterset_id = $self->hub->param('clusterset_id');
return [$consensus_clusterset_id, $clusterset_id];
}


sub get_GeneTree {
my $self = shift;
my $compara_db = shift || 'compara';
my $whole_tree = shift;
my $strain_tree = shift;
my $clusterset_id = $strain_tree || $self->hub->param('clusterset_id') || 'default';
my $cache_key = sprintf('_protein_tree_%s_%s_%s', $compara_db, $clusterset_id, $strain_tree);
my ($consensus_clusterset_id, $clusterset_id) = @{$self->_resolve_clusterset_ids($strain_tree)};

my $cache_key = sprintf('_protein_tree_%s_%s_%s', $compara_db, $clusterset_id, $consensus_clusterset_id);

if (!$self->{$cache_key}) {
my $args = {'stable_id' => $self->stable_id, 'cdb' => $compara_db};
my $member = $self->get_compara_Member($args) || return;
my $adaptor = $member->adaptor->db->get_adaptor('GeneTree') || return;
my $tree = $adaptor->fetch_all_by_Member($member, -clusterset_id => $clusterset_id)->[0];

# We fetch the consensus tree in the first instance. This is typically
# the 'default' tree for the current gene-tree view, which is either
# the tree we want, or the reference tree of the tree we want.
my $tree = $adaptor->fetch_default_for_Member($member, $consensus_clusterset_id);

unless ($tree) {
$tree = $adaptor->fetch_default_for_Member($member);
}
return unless $tree;

# If an alternative clusterset_id has been specified that
# is appropriate to the current gene-tree view, it should
# be one of the alternative trees of the consensus tree.
if ($clusterset_id && exists $tree->alternative_trees->{$clusterset_id}) {
$tree = $tree->alternative_trees->{$clusterset_id};
}

return $tree if $whole_tree;

$tree->preload;
Expand Down
21 changes: 19 additions & 2 deletions modules/EnsEMBL/Web/ViewConfig/Gene/ComparaTree.pm
Original file line number Diff line number Diff line change
Expand Up @@ -155,19 +155,27 @@ sub init_form_non_cacheable {
my $form = $self->SUPER::init_form_non_cacheable(@_);
my %other_clustersets;

my $page_action = $hub->referer->{'ENSEMBL_ACTION'};
my $consensus_clusterset_id = $hub->param('strain') || $page_action =~ /^Strain_/
? $hub->species_defs->get_config($hub->species, 'RELATED_TAXON')
: 'default'
;

if($hub->param('g')) {
my $database = $hub->database($cdb);
my $genome_db = $database->get_GenomeDBAdaptor->fetch_by_name_assembly($hub->species_defs->SPECIES_PRODUCTION_NAME);

my $member = $database->get_GeneMemberAdaptor->fetch_by_stable_id_GenomeDB($hub->core_params->{'g'}, $genome_db);
my $adaptor = $database->get_GeneTreeAdaptor;
my $gene_tree = $adaptor->fetch_default_for_Member($member);
my $gene_tree = $adaptor->fetch_default_for_Member($member, $consensus_clusterset_id);
$consensus_clusterset_id = $gene_tree->clusterset_id if $gene_tree->clusterset_id ne $consensus_clusterset_id;
%other_clustersets = map { $_->clusterset_id => 1 } @{$adaptor->fetch_all_linked_trees($gene_tree)};

delete $other_clustersets{'default'};
delete $other_clustersets{$consensus_clusterset_id};
}

if (my $dropdown = $form->get_elements_by_name('clusterset_id')->[0]) {
$self->_replace_default_clusterset_id_option($dropdown, $consensus_clusterset_id) if $consensus_clusterset_id ne 'default';
$dropdown->add_option({ 'value' => $_, 'caption' => $_ }) for sort keys %other_clustersets;
}

Expand All @@ -179,4 +187,13 @@ sub _groups {
return (@{ $_[0]->species_defs->TAXON_ORDER });
}

sub _replace_default_clusterset_id_option {
my ($self, $cset_id_dropdown, $clusterset_id) = @_;

my $default_option = $cset_id_dropdown->get_elements_by_attribute({'value' => 'default'})->[0];
my $cset_id_option = $cset_id_dropdown->dom->create_element('option', {'value' => $clusterset_id, 'inner_HTML' => 'Final (merged) tree'});
$default_option->after($cset_id_option);
$default_option->remove();
}

1;