<commit_before># Cared for by <NAME> <<EMAIL>>
#
# Copyright GRL & EBI
#
# You may distribute this module under the same terms as perl itself
#
# POD documentation - main docs before the code

=pod 

=head1 NAME

Bio::EnsEMBL::Analysis::Runnable::Lastz

=head1 SYNOPSIS

  # To run a lastz job from scratch do the following.

  my $query = new Bio::SeqIO(-file   => 'somefile.fa',
                           -format => 'fasta')->next_seq;

  my $database = 'multifastafile.fa';

  my $lastz =  Bio::EnsEMBL::Analysis::Runnable::Lastz->new 
    ('-query'     => $query,
     '-database'  => $database,
     '-options'   => 'T=2');

  $lastz->run();

  @featurepairs = $last->output();

  foreach my $fp (@featurepairs) {
      print $fp->gffstring . "\n";
  }

  # Additionally if you have lastz runs lying around that need parsing
  # you can use the EnsEMBL blastz parser module 
  # perldoc Bio::EnsEMBL::Analysis::Runnable::Parser::Blastz


=head1 DESCRIPTION

Lastz takes a Bio::Seq (or Bio::PrimarySeq) object and runs lastz with against 
the specified multi-FASTA file database. Tthe output is parsed by 
Bio::EnsEMBL::Analysis::Runnable::Parser::Lastz and stored as Bio::EnsEMBL::DnaDnaAlignFeature 

Other options can be passed to the lastz program using the -options method

=head1 CONTACT

Describe contact details here

=head1 APPENDIX


=cut

package Bio::EnsEMBL::Analysis::Runnable::Lastz;


use vars qw(@ISA);
use strict;

# Object preamble

use Bio::EnsEMBL::Analysis::Runnable;
use Bio::EnsEMBL::DnaDnaAlignFeature;
use Bio::EnsEMBL::Analysis::Tools::Blastz;
use Bio::EnsEMBL::Utils::Argument qw(rearrange);
use Bio::EnsEMBL::Utils::Exception;

@ISA = qw(Bio::EnsEMBL::Analysis::Runnable);


sub new {
  my ($class,@args) = @_;
  my $self = $class->SUPER::new(@args);

  my ($database) = rearrange(['DATABASE'], @args);
  $self->database($database) if defined $database;

  throw("You must supply a database") if not $self->database; 
  throw("You must supply a query") if not $self->query;

  $self->program("lastz") if not $self->program;

  return $self;
}

=head2 run

    Title   :  run
    Usage   :   $obj->run()
    Function:   Runs lastz and BPLite and creates array of feature pairs
    Returns :   none
    Args    :   none

=cut

sub run{
  my ($self, $dir) = @_;

  $DB::single = 1;
  $self->workdir($dir) if($dir);

  throw("Can't run ".$self." without a query sequence")
    unless($self->query);

  $self->write_seq_files();
  $self->run_analysis();

  $self->delete_files;
  return 1;
}



sub run_analysis {
  my $self = shift;

  my $cmd = $self->program  ." ".
            $self->query ." ".
            $self->database ." ".
            $self->options;

  my $BlastzParser;
  my $blastz_output_pipe = undef;
              
  if($self->results_to_file) {
    if (not $self->resultsfile) {
      my $resfile = $self->create_filename("lastz", "results");
      $self->resultsfile($resfile);
      $self->files_to_delete($resfile);
    }

    $cmd .=  " > ". $self->resultsfile;
    info("Running lastz...\n$cmd\n");

    throw("Error runing lastz cmd\n$cmd\n." .
                 " Returned error $? LASTZ EXIT: '" .
                 ($? >> 8) . "'," ." SIGNAL '" . ($? & 127) .
                 "', There was " . ($? & 128 ? 'a' : 'no') .
                 " core dump") unless(system($cmd) == 0);

    $BlastzParser = Bio::EnsEMBL::Analysis::Tools::Blastz->
        new('-file' => $self->resultsfile);
  } else {
    info("Running lastz to pipe...\n$cmd\n");

    open($blastz_output_pipe, "$cmd |") ||
      throw("Error opening lasts cmd <$cmd>." .
                   " Returned error $? LAST EXIT: '" .
                   ($? >> 8) . "'," ." SIGNAL '" . ($? & 127) .
                   "', There was " . ($? & 128 ? 'a' : 'no') .
                   " core dump");
    $BlastzParser = Bio::EnsEMBL::Analysis::Tools::Blastz->
        new('-fh' => $blastz_output_pipe);
  }

  my @results;

  while (defined (my $alignment = $BlastzParser->nextAlignment)) { # nextHSP-like
    push @results, $alignment;
  }
  close($blastz_output_pipe) if(defined($blastz_output_pipe));

  $self->output(\@results);
}


#################
# get/set methods 
#################

=head2 query

    Title   :   query
    Usage   :   $self->query($seq)
    Function:   Get/set method for query.  If set with a Bio::Seq object it
                will get written to the local tmp directory
    Returns :   filename
    Args    :   Bio::PrimarySeqI, or filename

=cut

sub query {
  my ($self, $val) = @_;

  if (defined $val) {
    if (not ref($val)) {   
      throw("[$val] : file does not exist\n") unless -e $val;
    } elsif (not $val->isa("Bio::PrimarySeqI")) {
      throw("[$val] is neither a Bio::Seq not a file");
    }
    $self->{_query} = $val;
  }<commit_msg>Detect lastz failure and throw an error eg when it detects an M in the alignment.<commit_after># Cared for by <NAME> <<EMAIL>>
#
# Copyright GRL & EBI
#
# You may distribute this module under the same terms as perl itself
#
# POD documentation - main docs before the code

=pod 

=head1 NAME

Bio::EnsEMBL::Analysis::Runnable::Lastz

=head1 SYNOPSIS

  # To run a lastz job from scratch do the following.

  my $query = new Bio::SeqIO(-file   => 'somefile.fa',
                           -format => 'fasta')->next_seq;

  my $database = 'multifastafile.fa';

  my $lastz =  Bio::EnsEMBL::Analysis::Runnable::Lastz->new 
    ('-query'     => $query,
     '-database'  => $database,
     '-options'   => 'T=2');

  $lastz->run();

  @featurepairs = $last->output();

  foreach my $fp (@featurepairs) {
      print $fp->gffstring . "\n";
  }

  # Additionally if you have lastz runs lying around that need parsing
  # you can use the EnsEMBL blastz parser module 
  # perldoc Bio::EnsEMBL::Analysis::Runnable::Parser::Blastz


=head1 DESCRIPTION

Lastz takes a Bio::Seq (or Bio::PrimarySeq) object and runs lastz with against 
the specified multi-FASTA file database. Tthe output is parsed by 
Bio::EnsEMBL::Analysis::Runnable::Parser::Lastz and stored as Bio::EnsEMBL::DnaDnaAlignFeature 

Other options can be passed to the lastz program using the -options method

=head1 CONTACT

Describe contact details here

=head1 APPENDIX


=cut

package Bio::EnsEMBL::Analysis::Runnable::Lastz;


use vars qw(@ISA);
use strict;

# Object preamble

use Bio::EnsEMBL::Analysis::Runnable;
use Bio::EnsEMBL::DnaDnaAlignFeature;
use Bio::EnsEMBL::Analysis::Tools::Blastz;
use Bio::EnsEMBL::Utils::Argument qw(rearrange);
use Bio::EnsEMBL::Utils::Exception;

@ISA = qw(Bio::EnsEMBL::Analysis::Runnable);


sub new {
  my ($class,@args) = @_;
  my $self = $class->SUPER::new(@args);

  my ($database) = rearrange(['DATABASE'], @args);
  $self->database($database) if defined $database;

  throw("You must supply a database") if not $self->database; 
  throw("You must supply a query") if not $self->query;

  $self->program("lastz") if not $self->program;

  return $self;
}

=head2 run

    Title   :  run
    Usage   :   $obj->run()
    Function:   Runs lastz and BPLite and creates array of feature pairs
    Returns :   none
    Args    :   none

=cut

sub run{
  my ($self, $dir) = @_;

  $self->workdir($dir) if($dir);

  throw("Can't run ".$self." without a query sequence")
    unless($self->query);

  $self->write_seq_files();
  $self->run_analysis();

  $self->delete_files;
  return 1;
}



sub run_analysis {
  my $self = shift;

  my $cmd = $self->program  ." ".
            $self->query ." ".
            $self->database ." ".
            $self->options;

  my $BlastzParser;
  my $blastz_output_pipe = undef;
  if($self->results_to_file) {
    if (not $self->resultsfile) {
      my $resfile = $self->create_filename("lastz", "results");
      $self->resultsfile($resfile);
      $self->files_to_delete($resfile);
    }

    $cmd .=  " > ". $self->resultsfile;
    info("Running lastz...\n$cmd\n");

    throw("Error runing lastz cmd\n$cmd\n." .
                 " Returned error $? LASTZ EXIT: '" .
                 ($? >> 8) . "'," ." SIGNAL '" . ($? & 127) .
                 "', There was " . ($? & 128 ? 'a' : 'no') .
                 " core dump") unless(system($cmd) == 0);

    $BlastzParser = Bio::EnsEMBL::Analysis::Tools::Blastz->
        new('-file' => $self->resultsfile);
  } else {
    info("Running lastz to pipe...\n$cmd\n");

    my $stderr_file = $self->workdir()."/lastz_$$.stderr";

    open($blastz_output_pipe, "$cmd 2>$stderr_file |") ||
      throw("Error opening lasts cmd <$cmd>." .
                   " Returned error $? LAST EXIT: '" .
                   ($? >> 8) . "'," ." SIGNAL '" . ($? & 127) .
                   "', There was " . ($? & 128 ? 'a' : 'no') .
                   " core dump");

    $BlastzParser = Bio::EnsEMBL::Analysis::Tools::Blastz->
        new('-fh' => $blastz_output_pipe) || print_error($stderr_file, "Unable to parse blastz_output_pipe");
  }

  my @results;

  while (defined (my $alignment = $BlastzParser->nextAlignment)) { # nextHSP-like
    push @results, $alignment;
  }
  close($blastz_output_pipe) if(defined($blastz_output_pipe));

  $self->output(\@results);
}


sub print_error {
    my ($stderr_file, $text) = @_;

    my $msg;
    if (-e $stderr_file) {
	print "$stderr_file\n";
	open FH, $stderr_file or die("Unable to open $stderr_file");
	while (<FH>) {
	    $msg .= $_;
	}
	unlink($stderr_file);
    }
    $msg .= $text;

    throw($msg);
}

#################
# get/set methods 
#################

=head2 query

    Title   :   query
    Usage   :   $self->query($seq)
    Function:   Get/set method for query.  If set with a Bio::Seq object it
                will get written to the local tmp directory
    Returns :   filename
    Args    :   Bio::PrimarySeqI, or filename

=cut

sub query {
  my ($self, $val) = @_;

  if (defined $val) {
    if (not ref($val)) {   
      throw("[$val] : file does not exist\n") unless -e $val;
    } elsif (not $val->isa("Bio::PrimarySeqI")) {
      throw("[$val] is neither a Bio::Seq not a file");
    }
    $self->{_query} = $val;
  }
{'fraction_non_alphanumeric': 0.16960637767812656, 'fraction_numerical': 0.004982561036372696, 'mean_word_length': 2.834925487199083, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 108, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '816877', 'n_tokens_mistral': 3634, 'n_tokens_neox': 3387, 'n_words': 875}