#!/usr/bin/perl -w

############################################################
#
# $Id: convert-variations,v 1.1 2013/07/18 12:23:07 jeremy Exp $
#
############################################################

use warnings;

=pod

=head1 NAME

convert-variation

=head1 VERSION

$program_version

=head1 DESCRIPTION

Ensure inter-conversions between different formats of polymorphic
variations.

/!\ To convert to VCF format, raw genomic sequence must be installed
(I<download-ensembl-genome>).

=head1 AUTHORS

Jeremy.Delerce@univ-amu.fr

=head1 CATEGORY

=over

=item util

=back

=head1 USAGE

 covert-variations -i filename -from format -to format [-species #] [-v #] [-o #]

=head1 SUPPORTED FORMAT

GVF, VCF, varBed

=head2 Genome Variant Format (GVF)

"The Genome Variant Format (GVF) is a type of GFF3 file with additional
pragmas and attributes specified. The GVF format has the same nine
column tab delimited format as GFF3 and all of the requirements and
restrictions specified for GFF3 apply to the GVF specification as
well." (quoted from the Sequence Ontology)

http://www.sequenceontology.org/resources/gvf_1.00.html


A GVF file starts with a header providing general information about
the file content: format version, date, data source, length of the
chromosomes / contigs covered by the variations.


 ##gff-version 3
 ##gvf-version 1.07
 ##file-date 2014-09-21
 ##genome-build ensembl GRCh38
 ##species http://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?id=9606
 ##feature-ontology http://song.cvs.sourceforge.net/viewvc/song/ontology/so.obo?revision=1.283
 ##data-source Source=ensembl;version=77;url=http://e77.ensembl.org/Homo_sapiens
 ##file-version 77
 ##sequence-region Y 1 57227415
 ##sequence-region 17 1 83257441
 ##sequence-region 6 1 170805979
 ##sequence-region 1 1 248956422
 ## [...]

This header is followed by the actual description of the variations,
in a column-delimited format compying with the GFF format.

 Y       dbSNP   SNV     10015   10015   .       +       .       ID=1;variation_id=23299259;Variant_seq=C,G;Dbxref=dbSNP_138:rs113469508;allele_string=A,C,G;evidence_values=Multiple_observations;Reference_seq=A
 Y       dbSNP   SNV     10146   10146   .       +       .       ID=2;variation_id=26647928;Reference_seq=C;Variant_seq=G;evidence_values=Multiple_observations,1000Genomes;allele_string=C,G;Dbxref=dbSNP_138:rs138058540;global_minor_allele_frequency=0|0.0151515|33
 Y       dbSNP   SNV     10153   10153   .       +       .       ID=3;variation_id=21171339;Reference_seq=C;Variant_seq=G;evidence_values=Multiple_observations,1000Genomes;allele_string=C,G;Dbxref=dbSNP_138:rs111264342;global_minor_allele_frequency=1|0.00229568|5
 Y       dbSNP   SNV     10181   10181   .       +       .       ID=4;variation_id=47159994;Reference_seq=C;Variant_seq=G;evidence_values=1000Genomes;allele_string=C,G;Dbxref=dbSNP_138:rs189980076;global_minor_allele_frequency=0|0.00137741|3

The last column contains a lot of relevant information, but is not
very easy to read. We should keep in mind that this format was
initially defined to describe generic genomic features, so all the
specific attributes come in the last column (description).

For this reasons, we developed a custom tab-delimited format to store
variations, which we call I<varBed> (see description below).

=head2 Variant Call Format (VCF)

http://en.wikipedia.org/wiki/Variant_Call_Format

This format was defined for the 1000 genomes project. It is no longer
maintained. The converter supports it merely for the sake of backwards
compatibility.

=head2 RSAT variation format (varBed)

Tab-delimited format with a specific column order, used as input by
I<retrieve-variation-seq>.

This format presents several advantages for scanning variations with
matrices.

=over

=item tab-delimited organization

Each field comes in a separate column -> the parsing does not require
to further parse the last column of the GVF file.

=item File separated per chromosome

This is a matter of organization rather than an intrinsic property of
the format (we could as well have used chromosome-separated GVF files,
or whole-genomes RSAT variant files), but it speeds up the search for
variants.

=item Combined variations

When several variants are mutually overlapping,
I<install-ensembl-variations> enables to compute all possible
combinations of variations. However, this option may require
considerable computer resources (computing time, storage), so we
inactivate it by default. To support combinatory variants,
I<install-ensembl-variations> must be called with the option I<-task
combine>.

=back

=head1 OUTPUT FORMAT

A tab delimited on selected output format


=head1 SEE ALSO

=head2 retrieve-variation-seq

I<retrieve-variation-seq> retrieves variant information and sequences using ensembl variation
files obtained with the program I<download-ensembl-variations>.

=head1 WISH LIST

=cut

BEGIN {
  if ($0 =~ /([^(\/)]+)$/) {
    push (@INC, "$`lib/");
  }
  $ENV{'RSAT'} =$ENV{'RSAT'};
  #print "$ENV{'RSAT'}";
  push (@INC, "$ENV{'RSAT'}/perl-scripts/lib");

}

require "RSA.lib";
require "RSAT_to_ensembl.lib.pl";

################################################################
## Main package
package	main;
{

  ###############################################################
  ## Initialise parameters
  our $start_time = &RSAT::util::StartScript();
  our $program_version = do { my @r = (q$Revision: 1.1 $ =~ /\d+/g); sprintf"%d."."%02d" x $#r, @r };

  our %infile	= ();
  our %outfile = ();

  our $skip = 0; ## Skip the first N variations of the input file
  our $last = 0; ## Stop after N variations of the input file

  our $verbose = 0;
  our $in = STDIN;
  our $out = STDOUT;
  our @supported_format = ("vcf","gvf","varBed");
  our $data_dir = "$ENV{'RSAT'}/data/";

  our @validate_patterns = (
    "E_MO",
    "E_Freq",
    "E_HM",
    "E_1000G",
    "E_C",
    "evidence_values",
    'validation_status'
      );

  our %validate_pattern = ();
  our $from = "";
  our $to = "";
  our $species = "";
  our $assembly_version = "";
  our $species_suffix = "";
  our $db="ensembl";
  our $ensembl_version = "";
  our $genome_dir = "";
  our %chr_file = ();
  our $last_chr = "";

  ################################################################
  ## Read argument values
  &ReadArguments();

  foreach (@validate_patterns) {
    $validate_pattern{$_} = 1;
  }

  if ($to eq "" || $from eq "") {
    &RSAT::error::FatalError("Please specify input and/or output format ");
  }

  ################################################################
  ## Check argument values
  if ($to eq "vcf") {
    if ($species eq "") {
      &RSAT::error::FatalError("Species must be indicated if option -to equal vcf");
    }
    unless ($assembly_version || $ensembl_version) {
      &RSAT::error::FatalError("Ensembl or assembly version is required when output format equals vcf (option -to)");
    }
    unless ($assembly_version){
      $assembly_version=&Get_assembly_version($species,$ensembl_version,$species_suffix);
    }
    $genome_dir = &Get_genome_dir($species, $assembly_version,$ensembl_version)."/";
    &RSAT::error::FatalError("$genome_dir don't exist. Use download-ensembl-genome before covert-variation.") unless (-d $genome_dir);

    # Check if sequence file are not missing
    %chr_file = &Get_file_seq_name($genome_dir);
    foreach my $file (keys(%chr_file)) {
      unless (-f $genome_dir.$chr_file{$file}) {
        &RSAT::error::FatalError($genome_dir.$chr_file{$file}, " is missing.");
      }
    }
  }

  ################################################################
  ## Print verbose
  $out = &OpenOutputFile($outfile{output});
  if ($main::to eq "varBed") {
    &Verbose() if ($main::verbose >= 1);
  }

  ################################################################
  ## Download input from remote URL
  if ($main::infile{input_url}) {
    &RSAT::message::TimeWarn("Transferring input file from URL", $main::infile{input_url}) if ($main::verbose >= 2);
    use LWP::Simple;

    if (defined($outfile{output})) {
      $main::outfile{input} = $main::outfile{output};
      $main::outfile{input} =~ s/\.varBed$//;
      $main::outfile{input} =~ s/\.vcf$//;
      $main::outfile{input} =~ s/\.gvf$//;

      ## Add extension to the input file, in order to recognize compressed files
      if ($main::infile{input_url} =~ /\.(\w+)$/) {
        my $extension = $1;
        $main::outfile{input} .= ".".$extension;
      } else {
        $main::outfile{input} .= ".vcf" if ($from eq "vcf");
        $main::outfile{input} .= ".varBed" if ($from eq "varBed");
        $main::outfile{input} .= ".gvf" if ($from eq "gvf");
      }

    } else {
      $main::outfile{input} = &RSAT::util::make_temp_file("", "convert-variation");
      &RSAT::message::Info("Storing downloaded input file as", $main::outfile{input}) if ($main::verbose >= 3);
    }

    getstore($main::infile{input_url}, $main::outfile{input});
    &RSAT::message::TimeWarn("Variation file transferred to local file", $main::outfile{input}) if ($main::verbose >= 2);
    $main::infile{input} = $main::outfile{input};
  }


  ################################################################
  ## Read input
  &RSAT::message::TimeWarn("Reading input file") if ($main::verbose >= 2);
  my $legend = 1;

  print $out "##gff-version 3\n##gvf-version 1.07\n" if ($to eq "gvf");
  print $out "##fileformat=VCFv4.1\n" if ($to eq "vcf");

  ($main::in) = &OpenInputFile($main::infile{input});


  my $l = 0; ## Line counter for the input file
  while (<$main::in>) {
    $l++;
    next if (($skip > 0) && ($l <= $skip));
    last if (($skip > 0) && ($l > $last));
    next if (/^;/); ## Skip RSAT-like comment lines
    next unless (/\S/); ## Skip empty lines


    while (/^#/) {
      print $out $_ unless ((/^##fileformat/) || (/^#[^#]/));
      $_ = <$main::in>;
    }

    chomp();
    if ($legend) {
      print $out join("\t","#CHROM","POS","ID","REF","ALT","QUAL","FILTER","INFO\n") if ($to eq 'vcf');
      print $out join("\t","#seqid","source","type","start","end","score","strand","phase","attribute\n") if ($to eq 'gvf');
      print $out join("\t","#chr","start","end","strand","id","ref","alt","so_term","validate","minor_allele_freq","is_supvar","in_supvar\n") if ($to eq 'varBed');
      $legend = 0;
    }

    ### Read input files acording to the defined formart -from
    my %variation =  ();

    ## VCF file
    if ($from eq "vcf") {
      my @token = split("\t",$_);
      &RSAT::message::Debug("Input file vcf\n") if ($main::verbose >= 10);
      if (scalar( @token ) < 8 ) {
	&RSAT::message::Warning("line", $l, "Invalid VCF line: must contain at least 8 columns", "Skipped");
	print $_ if ($main::verbose >= 3);
	next;
      }

      %variation = &Get_var_from_vcf(\@token);
    }


    ## RSAT file
    if ($from eq 'varBed') {
      my @token = split("\t",$_);

      next if ($token[9] == 1);
      if (scalar( @token ) != 11 ) {
	&RSAT::message::Warning("$_ skip. varBed line must be cointain 11 columns");
	next;
      }

      %variation = &Get_var_from_rsat(\@token);
    }


    ## GVF file
    if ($from eq 'gvf') {
      chomp();
      my @token = split("\t",$_);

      if (scalar( @token ) != 9) {
        &RSAT::message::Warning("$_ skip. gvf line must be cointain 9 columns");
        next;
      }

      unless ( $token[8] =~ /ID\=/) {
        &RSAT::error::FatalError("No ID found. Put key 'ID' in attribute colunm");
        next;
      }

      unless ( $token[8] =~ /Reference_seq\=/) {
        &RSAT::error::FatalError("No reference variant found. Put key 'Variant_ref' in attribute colunm");
        next;
      }

      unless ( $token[8] =~ /Variant_seq\=/) {
        &RSAT::error::FatalError("No alternate variant found. Put key 'Variant_alt' in attribute colunm");
        next;
      }

      %variation = &Get_var_from_gvf(\@token);
    }

    ### Output variation
    print $out &Convert_var_to_rsat(%variation),"\n" if ($to eq "varBed");
    print $out &Convert_var_to_vcf(%variation),"\n" if ($to eq "vcf");
    print $out &Convert_var_to_gvf(%variation),"\n" if ($to eq "gvf");
  }

  ################################################################
  ## Report execution time and close output stream
  my $exec_time = &RSAT::util::ReportExecutionTime($start_time); ## This has to be exectuted by all scripts
  print $exec_time if ($main::verbose >= 2); ## only report exec time if verbosity is specified
  close $out;

  exit(0);
}


################################################################
################### SUBROUTINE DEFINITION ######################
################################################################

################################################################
## Get all variation information from a variation in vcf format
sub Get_var_from_vcf {
  my @token = @{$_[0]};
  my %variation = ();

  $variation{'chr'} = $token[0];
  $variation{'start'} = $token[1];
  $variation{'end'} = $variation{'start'} + length($token[3])-1;
  $variation{'strand'} = "+";
  $variation{'id'} = $token[2];
  $variation{'ref'} = $token[3];
  $variation{'alt'} = $token[4];
  $variation{'SO'} = "sequence_alteration";
  $variation{'validate'} = 0;
  $variation{'m_allele_freq'}="NA";
  $variation{'attribute'} = ();

  ## Check validate value and attribute
  ## Split attribuites and store values in a hash
  foreach (split(";",$token[7])) {
    my ($key,$value) = split("=",$_);
    $value = 1 unless ($value);
    if($key eq "CAF"){ ## Retrieve minor allele frequency information from vcf entry
	my ($major_freq,$minor_freq)=split(",",$value);
	$minor_freq=~s/\]//;
	$minor_freq="NA" if ($minor_freq eq ".");
	$variation{'m_allele_freq'}=$minor_freq;
	next; ## do not store the CAF information in attributes,include it manually on the gvf and rsat outfiles with the correct naming
    }
    push(@{$variation{'attribute'}},$key.'='.$value);
    $variation{'validate'} = 1 if ($validate_pattern{$key});
  }

  # Check len and first nucleotide  of variant (ref and alt)
  my $is_indel = 0;
  my $same_length = 1;

  foreach (split(",",$variation{'alt'})) {
    $is_indel = 1 if ( substr($_,0,1) eq substr($variation{'ref'},0,1));
    $same_length = 0 if ( length($_) !=  length($variation{'ref'}));
  }


  # Check variant and start/end coordinate
  if ($is_indel) {

    # Alternatif variant
    my @alts = ();
    foreach (split(",",$variation{'alt'})) {
      my $alt = ",".substr($variation{'alt'},1);
      $alt = "-" unless ($alt);
      push (@alts, $alt);
    }
    $variation{'alt'} = join(",",@alts);

    # Ref variant
    $variation{'ref'} = substr($variation{'ref'},1);
    $variation{'ref'} = "-" unless ($variation{'ref'});

    # Coordinate
    ## $variation{'start'} ++; ## VCF is one base coordintes in both start and end
    $variation{'end'} = $variation{'start'} + length($variation{'ref'})-1;
  }


  # Check SO Term
  if ($same_length && length($token[3]) == 1) {
    $variation{'SO'} = "SNV";
  } elsif ($same_length) {
    $variation{'SO'} = "substitution";
  } elsif ($is_indel && $variation{'ref'} eq "-") {
    $variation{'SO'} = "insertion";
  } elsif ($is_indel) {
    $variation{'SO'} = "deletion";
  }

  return %variation;
}


################################################################
## Get all variation information from a variation in rsat format
sub Get_var_from_rsat {
  my @token = @{$_[0]};
  my %variation = ();

  $variation{'chr'} = $token[0];
  $variation{'start'} = $token[1];
  $variation{'end'} = $token[2];
  $variation{'strand'} = $token[3];
  $variation{'id'} = $token[4];
  $variation{'ref'} = $token[5];
  $variation{'alt'} = $token[6];
  $variation{'SO'} = $token[7];
  $variation{'validate'} = $token[8];
  $variation{'m_allele_freq'} = $token[9];
  $variation{'attribute'} = ();
  push (@{$variation{'attribute'}}, "validate=1") if ($variation{'validate'});

  return %variation;
}


################################################################
## Get all variation information from a variation in gvf format
sub Get_var_from_gvf {
  my @token = @{$_[0]};
  my %variation = ();

  $variation{'chr'} = $token[0];
  $variation{'start'} = $token[3];
  $variation{'end'} = $token[4];
  $variation{'strand'} = $token[6];
  $variation{'id'} = "";
  $variation{'ref'} = "";
  $variation{'alt'} = "";
  $variation{'SO'} = $token[2];
  $variation{'validate'} = 0;
  $variation{'m_allele_freq'}="NA";
  $variation{'attribute'} = ();

  foreach (split(";",$token[8])) {
    my ($key,$value) = split("=",$_);


    if ($key eq "ID") {
      $variation{'id'} = $value;

    } elsif ($key eq "Dbxref") {
      my ($source,$id) = split (":",$value);
      $variation{'id'} = $id;

    } elsif ($key eq "Reference_seq") {
      $variation{'ref'} = $value;

    } elsif ($key eq "Variant_seq") {
	$variation{'alt'} = $value;

    } elsif ($key eq "global_minor_allele_frequency") { ## Recover value for minor allele frequency from gvf file
	my @gmaf = split("\\|",$value);
	$variation{'m_allele_freq'}=$gmaf[1];
	#print $variation{'id'}.$variation{'m_allele_freq'};
	#die "BOOM";

    } elsif ($validate_pattern{$key}) {
	$variation{'validate'} = 1;
	push(@{$variation{'attribute'}},$key.'='.$value);

    } elsif ($key eq 'validation_states' && $value ne "-") {
      $variation{'validate'} = 1;
      push(@{$variation{'attribute'}},$key.'='.$value);

    } else {
      push(@{$variation{'attribute'}},$key.'='.$value);
    }
  }

  return %variation;
}

################################################################
## Get all variation information from a variation in gvf format
sub Convert_var_to_rsat {
  my %variation = @_;

  $variation{'chr'}=~s/chr//;
  my $line = $variation{'chr'}."\t";
  $line .= $variation{'start'}."\t";
  $line .= $variation{'end'}."\t";
  $line .= $variation{'strand'}."\t";
  $line .= $variation{'id'}."\t";
  $line .= $variation{'ref'}."\t";
  $line .= $variation{'alt'}."\t";
  $line .= $variation{'SO'}."\t";
  $line .= $variation{'validate'}."\t";
  $line .= $variation{'m_allele_freq'}."\t";
  $line .= "0"."\t";
  $line .= "0";

  return  $line;
}

sub Convert_var_to_gvf {
  my %variation = @_;

  push (@{$variation{'attribute'}},"ID=".$variation{'id'});
  push (@{$variation{'attribute'}},"Reference_seq=".$variation{'ref'});
  push (@{$variation{'attribute'}},"Variant_seq=".$variation{'alt'});

  my $line = $variation{'chr'}."\t";
  $line .= '.'."\t";;
  $line .= $variation{'SO'}."\t";
  $line .= $variation{'start'}."\t";
  $line .= $variation{'end'}."\t";
  $line .= '.'."\t";
  $line .= $variation{'strand'}."\t";
  $line .= '.'."\t";
  $line .= join(";",@{$variation{'attribute'}});
  $line .=";global_minor_allele_frequency=NA|".$variation{'m_allele_freq'}."|NA" if $variation{'m_allele_freq'} ne "NA";
  return  $line;
}

sub Convert_var_to_vcf {
  my %variation = @_;

  if ($variation{'ref'} eq "-" || $variation{'alt'} =~ /\-/) {

    if ($variation{'chr'} ne $last_chr) {
      my $raw_file = $genome_dir.$chr_file{$variation{'chr'}};
      $ref_seq = qx($ENV{'RSAT'}/perl-scripts/sub-sequence -i $raw_file -from 1 -to 500000000 -format raw);
      $last_chr = $variation{'chr'};
    }

    $variation{'start'} --;
    $prev_nucle = substr($ref_seq,$variation{'start'},1);

    $variation{'ref'} = $prev_nucle.$variation{'ref'};
    $variation{'ref'} =~ s/\-//m;

    my @alts = ();
    foreach my $alt (split(",",$variation{'alt'})) {
      push (@alts,$prev_nucle.$alt);
    }
    $variation{'alt'} = join (",",@alts);
    $variation{'alt'} =~ s/\-//m;
  }

  push (@{$variation{'attribute'}},"TSA=".$variation{'SO'});

  my $line = $variation{'chr'}."\t";
  $line .= $variation{'start'}."\t";
  $line .= $variation{'id'}."\t";
  $line .= $variation{'ref'}."\t";
  $line .= $variation{'alt'}."\t";
  $line .= '.'."\t";
  $line .= '.'."\t";
  $line .= join(";",@{$variation{'attribute'}});
  if ($variation{'m_allele_freq'} ne "NA"){
      my $major_allele=1-$variation{'m_allele_freq'};
      $line .=";CAF=[". $major_allele.",".$variation{'m_allele_freq'}."]" ;
  }
  return  $line;
}




################################################################
## Display full help message
sub PrintHelp {
  system "pod2text -c $0";
  exit(0);
}

################################################################
## Display short help message
sub PrintOptions {
  &PrintHelp();
}

################################################################
## Read arguments
sub ReadArguments {
  my $arg;
  my @arguments = @ARGV; ## create a copy to shift, because we need ARGV to report command line in &Verbose()
  while (scalar(@arguments) >= 1) {
    $arg = shift (@arguments);

=pod

=head1 OPTIONS

=over 4

=item B<-v #>

Level of verbosity (detail in the warning messages during execution)

=cut
    if ($arg eq "-v") {
      if (&IsNatural($arguments[0])) {
        $main::verbose = shift(@arguments);
      } else {
        $main::verbose = 1;
      }

=pod

=item B<-h>

Display full help message

=cut
    } elsif ($arg eq "-h") {
      &PrintHelp();

=pod

=item B<-help>

Same as -h

=cut
    } elsif ($arg eq "-help") {
      &PrintOptions();

=pod

=item B<-i inputfile>

Variation files in tab format

If no input file is specified, the standard input is used.  This
allows to use the command within a pipe.

This option is mutually exclusive with option I<-u>.

=cut
    } elsif ($arg eq "-i") {
      &RSAT::error::FatalError("Options -i and -u are mutually exclusive") if ($main::infile{input_url});
      $main::infile{input} = shift(@arguments);

=pod

=item B<-u input_URL>

Use as input a file available on a remote Web server.

This option is mutually exclusive with option I<-i>.

=cut
    } elsif ($arg eq "-u") {
      &RSAT::error::FatalError("Options -i and -u are mutually exclusive") if ($main::infile{input});
      $main::infile{input_url} = shift(@arguments);

=pod

=item B<-from #>

Format of the input file
vcf,gvf,varBed

=cut
    } elsif ($arg eq "-from") {
      $main::from = shift(@arguments);
      &RSAT::error::FatalError("Not supported input format : $from") unless ( grep($_ eq $from, @supported_format ));

=pod

=item B<-to #>

Format of the output file
vcf,gvf,varBed

=cut
    } elsif ($arg eq "-to") {
      $main::to = shift(@arguments);
      &RSAT::error::FatalError("Not supported output format : $to") unless ( grep($_ eq $to, @supported_format ));

=pod

=item B<-skip>

Skip the N first variations of the input file. This option is useful
for quick tests, or to split an analysis in separate tasks.

=cut
	} elsif ($arg eq "-skip") {
	    $main::skip = shift(@arguments);

=pod

=item B<-last>

Stop after the N first variations of the list. This option is useful
for quick tests, or to split an analysis in separate tasks.

=cut
	} elsif ($arg eq "-last") {
	    $main::last = shift(@arguments);


=pod

=item B<-species species_name>

Species where variation are coming from (Homo_sapiens, Mus_musculus).

=cut
    } elsif ($arg eq "-species") {
      $main::species = shift(@arguments);

=pod

=item B<-e_version #>

The version of ensembl

=cut
    } elsif ($arg eq "-e_version") {
      $main::ensembl_version = shift(@arguments);

=pod

=item B<-a_version #>

The version of the assembly of the species

=cut
    } elsif ($arg eq "-a_version") {
      $main::assembly_version = shift(@arguments);

=pod

=item B<-species_suffix>

Suffix to append to the full species ID.

By default, the full species ID is composed by concatenating the
Ensembl species and assembly version. The option I<-species_suffix>
allows to specify a string (e.g. _ensembl76, _for_testing, ...) that
will be appended to the full species ID.

=cut
    } elsif ($arg eq "-species_suffix") {
    $species_suffix = shift(@arguments);


=pod

=item B<-o outputfile>

If no output file is specified, the standard output is used.  This
allows to use the command within a pipe.

=cut
    } elsif ($arg eq "-o") {
      $outfile{output} = shift(@arguments);
    } else {
      &FatalError(join("\t", "Invalid option", $arg));
    }
  }

=pod

=back

=cut

}

################################################################
## Verbose message
sub Verbose {
  print $out "; convert-variations ";
  &PrintArguments($out);

  if (%main::outfile) {
    print "; Output files\n";
    while (my ($key,$value) = each %main::outfile) {
      printf ";\t%-13s\t%s\n", $key, $value;
    }
  }
}
