<commit_before>=head1 LICENSE

  Copyright (c) 1999-2012 The European Bioinformatics Institute and
  Genome Research Limited.  All rights reserved.

  This software is distributed under a modified Apache license.
  For license details, please see

   http://www.ensembl.org/info/about/code_licence.html

=head1 CONTACT

  Please email comments or questions to the public Ensembl
  developers list at <<EMAIL>>.

  Questions may also be sent to the Ensembl help desk at
  <<EMAIL>>.

=head1 NAME

Bio::EnsEMBL::Compara::RunnableDB::ProteinTrees::NJTREE_PHYML

=head1 DESCRIPTION

This Analysis/RunnableDB is designed to take ProteinTree as input
This must already have a multiple alignment run on it. It uses that alignment
as input into the NJTREE PHYML program which then generates a phylogenetic tree

input_id/parameters format eg: "{'protein_tree_id'=>1234}"
    protein_tree_id : use 'id' to fetch a cluster from the ProteinTree

=head1 SYNOPSIS

my $db           = Bio::EnsEMBL::Compara::DBAdaptor->new($locator);
my $njtree_phyml = Bio::EnsEMBL::Compara::RunnableDB::ProteinTrees::NJTREE_PHYML->new
  (
   -db         => $db,
   -input_id   => $input_id,
   -analysis   => $analysis
  );
$njtree_phyml->fetch_input(); #reads from DB
$njtree_phyml->run();
$njtree_phyml->output();
$njtree_phyml->write_output(); #writes to DB

=head1 AUTHORSHIP

Ensembl Team. Individual contributions can be found in the CVS log.

=head1 MAINTAINER

$Author$

=head VERSION

$Revision$

=head1 APPENDIX

The rest of the documentation details each of the object methods.
Internal methods are usually preceded with an underscore (_)

=cut

package Bio::EnsEMBL::Compara::RunnableDB::ProteinTrees::NJTREE_PHYML;

use strict;

use IO::File;
use File::Basename;
use File::Path;
use Time::HiRes qw(time gettimeofday tv_interval);
use Data::Dumper;
use File::Glob;

use Bio::EnsEMBL::Compara::AlignedMember;
use Bio::EnsEMBL::Compara::Member;
use Bio::EnsEMBL::Compara::Graph::NewickParser;
use Bio::EnsEMBL::Compara::RunnableDB::ProteinTrees::MSA;

use base ('Bio::EnsEMBL::Compara::RunnableDB::GeneTrees::StoreTree', 'Bio::EnsEMBL::Compara::RunnableDB::GeneTrees::StoreClusters');


sub param_defaults {
    return {
            'cdna'              => 1,   # always use cdna for njtree_phyml
            'bootstrap'         => 1,
		'check_split_genes' => 1,
            'store_tree_support'    => 1,
            'intermediate_prefix'   => 'interm',
    };
}


sub fetch_input {
    my $self = shift @_;

    $self->check_if_exit_cleanly;

    $self->param('member_adaptor', $self->compara_dba->get_MemberAdaptor);
    $self->param('tree_adaptor', $self->compara_dba->get_GeneTreeAdaptor);

    my $protein_tree_id     = $self->param('protein_tree_id') or die "'protein_tree_id' is an obligatory parameter";
    my $protein_tree        = $self->param('tree_adaptor')->fetch_by_dbID( $protein_tree_id )
                                        or die "Could not fetch protein_tree with protein_tree_id='$protein_tree_id'";
    $protein_tree->print_tree(10) if($self->debug);

    $self->param('protein_tree', $protein_tree);
}


sub run {
  my $self = shift;

  $self->check_if_exit_cleanly;
  $self->run_njtree_phyml;
}


sub write_output {
    my $self = shift;

    $self->check_if_exit_cleanly;
    $self->store_genetree($self->param('protein_tree'));

    if ($self->param('store_intermediate_trees')) {
        foreach my $filename (glob(sprintf('%s/%s.*.nhx', $self->worker_temp_directory, $self->param('intermediate_prefix')) )) {
            $filename =~ /\.([^\.]*)\.nhx$/;
            my $clusterset_id = $1;
            next if $clusterset_id eq 'mmerge';
            next if $clusterset_id eq 'phyml';
            print STDERR "Found file $filename for clusterset $clusterset_id\n";
            my $clusterset = $self->fetch_or_create_clusterset($clusterset_id);
            my $newtree = $self->fetch_or_create_other_tree($clusterset, $self->param('protein_tree'));
            $self->parse_newick_into_tree($filename, $newtree);
            $self->store_genetree($newtree);
            $self->dataflow_output_id({'protein_tree_id' => $newtree->root_id}, 2);
        }
    }
    if ($self->param('store_filtered_align')) {
        my $filename = sprintf('%s/filtalign.fa', $self->worker_temp_directory);
        if (-e $filename) {
            print STDERR "Found filtered alignment: $filename\n";
            my $alignio = Bio::AlignIO->new(-file => $filename, -format => 'fasta');
            my $aln = $alignio->next_aln or die "Bio::AlignIO could not get next_aln() from file '$filename'";
            $self->param('protein_tree')->store_tag('filtered_alignment_length', $aln->length()/3);
            #my $clusterset = $self->fetch_or_create_clusterset('filtered-align');
            #my $newtree = $self->fetch_or_create_other_tree($clusterset, $self->param('protein_tree'));
            #$newtree->load_cigars_from_fasta($filename, $newtree, 1);
            #my $split_genes = $self->param('split_genes');
            #while ( my ($name, $other_name) = each(%{$split_genes})) {
            #    my $node = $newtree->find_node_by_name($name);
            #    $node->disavow_parent if $node;
            #    $node = $newtree->find_node_by_name($other_name);
            #    $node->disavow_parent if $node;
            #}
            #$self->store_genetree($newtree);
            #Bio::EnsEMBL::Compara::RunnableDB::ProteinTrees::MSA::_store_aln_tags($self, $newtree);
            #$newtree->store_tag('unfiltered_tree_root_id', $self->param('protein_tree_id'));
            #$self->param('protein_tree')->store_tag('other_tree_root_id', $newtree->root_id, 1);
        }
        $filename = sprintf('%s/prog-filtalign.fa', $self->worker_temp_directory);
        if (-e $filename) {
            print STDERR "Found filtered alignment: $filename\n";
            my $alignio = Bio::AlignIO->new(-file => $filename, -format => 'fasta');
            my $aln = $alignio->next_aln or die "Bio::AlignIO could not get next_aln() from file '$filename'";
            $self->param('protein_tree')->store_tag('progfiltered_alignment_length', $aln->length()/3);
        }
    }

    if (defined $self->param('output_dir')) {
        my $cmd = sprintf('zip -r -9 %s/%d.zip', $self->param('output_dir'), $self->param('protein_tree_id'));
        $cmd = sprintf('cd %s; %s', $self->worker_temp_directory, $cmd) if $self->worker_temp_directory;
        system($cmd);
    }
    rmtree([$self->worker_temp_directory]);
}

sub DESTROY {
  my $self = shift;

  if(my $protein_tree = $self->param('protein_tree')) {<commit_msg>Now storing the filtered multiple alignment as tag<commit_after>=head1 LICENSE

  Copyright (c) 1999-2012 The European Bioinformatics Institute and
  Genome Research Limited.  All rights reserved.

  This software is distributed under a modified Apache license.
  For license details, please see

   http://www.ensembl.org/info/about/code_licence.html

=head1 CONTACT

  Please email comments or questions to the public Ensembl
  developers list at <<EMAIL>>.

  Questions may also be sent to the Ensembl help desk at
  <<EMAIL>>.

=head1 NAME

Bio::EnsEMBL::Compara::RunnableDB::ProteinTrees::NJTREE_PHYML

=head1 DESCRIPTION

This Analysis/RunnableDB is designed to take ProteinTree as input
This must already have a multiple alignment run on it. It uses that alignment
as input into the NJTREE PHYML program which then generates a phylogenetic tree

input_id/parameters format eg: "{'protein_tree_id'=>1234}"
    protein_tree_id : use 'id' to fetch a cluster from the ProteinTree

=head1 SYNOPSIS

my $db           = Bio::EnsEMBL::Compara::DBAdaptor->new($locator);
my $njtree_phyml = Bio::EnsEMBL::Compara::RunnableDB::ProteinTrees::NJTREE_PHYML->new
  (
   -db         => $db,
   -input_id   => $input_id,
   -analysis   => $analysis
  );
$njtree_phyml->fetch_input(); #reads from DB
$njtree_phyml->run();
$njtree_phyml->output();
$njtree_phyml->write_output(); #writes to DB

=head1 AUTHORSHIP

Ensembl Team. Individual contributions can be found in the CVS log.

=head1 MAINTAINER

$Author$

=head VERSION

$Revision$

=head1 APPENDIX

The rest of the documentation details each of the object methods.
Internal methods are usually preceded with an underscore (_)

=cut

package Bio::EnsEMBL::Compara::RunnableDB::ProteinTrees::NJTREE_PHYML;

use strict;

use IO::File;
use File::Basename;
use File::Path;
use Time::HiRes qw(time gettimeofday tv_interval);
use Data::Dumper;
use File::Glob;

use Bio::EnsEMBL::Compara::AlignedMember;
use Bio::EnsEMBL::Compara::Member;
use Bio::EnsEMBL::Compara::Graph::NewickParser;
use Bio::EnsEMBL::Compara::RunnableDB::ProteinTrees::MSA;

use base ('Bio::EnsEMBL::Compara::RunnableDB::GeneTrees::StoreTree', 'Bio::EnsEMBL::Compara::RunnableDB::GeneTrees::StoreClusters');


sub param_defaults {
    return {
            'cdna'              => 1,   # always use cdna for njtree_phyml
            'bootstrap'         => 1,
		'check_split_genes' => 1,
            'store_tree_support'    => 1,
            'intermediate_prefix'   => 'interm',
    };
}


sub fetch_input {
    my $self = shift @_;

    $self->check_if_exit_cleanly;

    $self->param('member_adaptor', $self->compara_dba->get_MemberAdaptor);
    $self->param('tree_adaptor', $self->compara_dba->get_GeneTreeAdaptor);

    my $protein_tree_id     = $self->param('protein_tree_id') or die "'protein_tree_id' is an obligatory parameter";
    my $protein_tree        = $self->param('tree_adaptor')->fetch_by_dbID( $protein_tree_id )
                                        or die "Could not fetch protein_tree with protein_tree_id='$protein_tree_id'";
    $protein_tree->print_tree(10) if($self->debug);

    $self->param('protein_tree', $protein_tree);
}


sub run {
  my $self = shift;

  $self->check_if_exit_cleanly;
  $self->run_njtree_phyml;
}


sub write_output {
    my $self = shift;

    $self->check_if_exit_cleanly;
    $self->store_genetree($self->param('protein_tree'));

    if ($self->param('store_intermediate_trees')) {
        foreach my $filename (glob(sprintf('%s/%s.*.nhx', $self->worker_temp_directory, $self->param('intermediate_prefix')) )) {
            $filename =~ /\.([^\.]*)\.nhx$/;
            my $clusterset_id = $1;
            next if $clusterset_id eq 'mmerge';
            next if $clusterset_id eq 'phyml';
            print STDERR "Found file $filename for clusterset $clusterset_id\n";
            my $clusterset = $self->fetch_or_create_clusterset($clusterset_id);
            my $newtree = $self->fetch_or_create_other_tree($clusterset, $self->param('protein_tree'));
            $self->parse_newick_into_tree($filename, $newtree);
            $self->store_genetree($newtree);
            $self->dataflow_output_id({'protein_tree_id' => $newtree->root_id}, 2);
        }
    }
    if ($self->param('store_filtered_align')) {
        my $filename = sprintf('%s/filtalign.fa', $self->worker_temp_directory);
        if (-e $filename) {
            print STDERR "Found filtered alignment: $filename\n";
            my $alignio = Bio::AlignIO->new(-file => $filename, -format => 'fasta');
            my $aln = $alignio->next_aln or die "Bio::AlignIO could not get next_aln() from file '$filename'";

            #place all members in a hash on their member name
            my %member_hash;
            foreach my $member (@{$self->get_all_Members}) {
                $member_hash{$member->member_id} = $member;
            }

            # Storing the alignment as tags
            $self->param('protein_tree')->store_tag('filtered_alignment_length', $aln->length()/3);
            foreach my $seq ($aln->each_seq) {
                $seq->display_id =~ /(\d+)\_\d+/;
                $member_hash{$1}->store_tag('filtered_alignment') = $seq->seq();
            }

        }
        $filename = sprintf('%s/prog-filtalign.fa', $self->worker_temp_directory);
        if (-e $filename) {
            print STDERR "Found filtered alignment: $filename\n";
            my $alignio = Bio::AlignIO->new(-file => $filename, -format => 'fasta');
            my $aln = $alignio->next_aln or die "Bio::AlignIO could not get next_aln() from file '$filename'";
            $self->param('protein_tree')->store_tag('progfiltered_alignment_length', $aln->length()/3);
        }
    }

    if (defined $self->param('output_dir')) {
        my $cmd = sprintf('zip -r -9 %s/%d.zip', $self->param('output_dir'), $self->param('protein_tree_id'));
        $cmd = sprintf('cd %s; %s', $self->worker_temp_directory, $cmd) if $self->worker_temp_directory;
        system($cmd);
    }
    rmtree([$self->worker_temp_directory]);
}

sub DESTROY {
  my $self = shift;

  if(my $protein_tree = $self->param('protein_tree')) {
{'fraction_non_alphanumeric': 0.14299168105477947, 'fraction_numerical': 0.005101239993721551, 'mean_word_length': 3.429266597149809, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 168, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1792932', 'n_tokens_mistral': 4429, 'n_tokens_neox': 4172, 'n_words': 913}