#! /usr/bin/perl
# $Id: gmap_setup.pl.in,v 1.50 2010-07-21 22:01:03 twu Exp $

use warnings;

$gmapdb = "/private/tmp/Rtmpm1Kn96/R.INSTALL7da54ade7d11/gmapR/src/../inst/usr/share";
$bindir = "/private/tmp/Rtmpm1Kn96/R.INSTALL7da54ade7d11/gmapR/src/../inst/usr/bin";
$package_version = "2013-11-01";

use IO::File;
use Getopt::Std;

# Usage: gmap_setup -d <db> [-D <destdir>] [-k <kmersize>] [-o <Makefile>] [-M <.md file>] [-C] [-W] [-E] [-q interval] <fasta_files or command>
#

undef($opt_d);			# genome name
undef($opt_D);			# destination directory
$opt_b = 12;			# offsetscomp basesize
$opt_k = 15;			# k-mer size for GMAP genomic index (currently allowed: 16 or less)
undef($opt_o);			# name of output file (default is "Makefile.<genome>")

undef($opt_M);			# use seq_contig.md file (provide as argument)
undef($opt_s);			# Chromosome sort order
undef($opt_C);			# Tries to find a chromosome tag in each FASTA header (also turns ons chromosome sorting)

undef($opt_W);			# write directly to file, not RAM
undef($opt_E);			# interpret argument as a command

undef($opt_B);			# bindir (needed for "make check")

$opt_q = 3;			# GMAP interval

#undef($opt_9);			# debug

getopts("d:D:b:k:K:q:Q:o:M:s:CWEB:");

#if (defined($opt_S)) {
#    print STDERR "The -S flag is no longer available.  It is now the default behavior, so you may\n";
#    print STDERR "  simply call gmap_setup without it.  The other ways to call gmap_setup are with\n";
#    print STDERR "  the -C flag (to try to parse the chromosomal coordinates from each FASTA header)\n";
#    print STDERR "  or with the -M flag (to specify an NCBI .md file that contains chromosomal\n";
#    print STDERR "  coordinates.\n";
#    die;
#}

if (!defined($genome_name = $opt_d)) {
  print_usage();
  die "Must specify genome database name with -d flag.";
} elsif ($opt_d =~ /(\S+)\/(\S+)/) {
  $genome_name = $2;
  if (defined($opt_D)) {
    $opt_D = $opt_D . "/" . $1;
  } else {
    $opt_D = $1;
  }
}

$genome_name =~ s/\/$//;	# In case user gives -d argument with trailing slash

if (!defined($outputfile = $opt_o)) {
  $outputfile = "Makefile.$genome_name";
}

$gmap_basesize = $opt_b;

$gmap_kmersize = $opt_k;
$gmap_interval = $opt_q;


$MAKEFILE = new IO::File(">$outputfile") or die "Cannot write to file $outputfile";

print $MAKEFILE "# Makefile for creating genome $genome_name for use by GMAP.\n";
print $MAKEFILE "# Created by gmap_setup, but may be edited as needed\n\n";
#print $MAKEFILE ":SILENT: \n"; -- Doesn't work
print $MAKEFILE "\n";

# Remove unexpected suffix behavior
print $MAKEFILE ".SUFFIXES:\n";
print $MAKEFILE ".SUFFIXES: .txt\n\n";

print $MAKEFILE "GENOME = $genome_name\n";

if (!defined($destination = $opt_D)) {
    $destination = $gmapdb . "/" . $genome_name;
}
$destination =~ s/\/\//\//g;	# Remove double slashes
print $MAKEFILE "DESTINATION = $destination\n";
print $MAKEFILE "\n";


if (defined($opt_s)) {
    print $MAKEFILE "CHR_ORDER_FLAG = -s $opt_s\n";
} else {
    print $MAKEFILE "CHR_ORDER_FLAG = \n";
}


if (defined($opt_E)) {
  $incommand = $ARGV[0];
} else {
  #$incommand = "cat \$(FASTA)";
  print $MAKEFILE "FASTA = " . join(" \\\n         ",@ARGV) . "\n";
}

print $MAKEFILE "COORDS = coords.\$(GENOME)\n";

if (defined($opt_B)) {
  print $MAKEFILE "FA_COORDS = $opt_B/fa_coords\n";
  print $MAKEFILE "MD_COORDS = $opt_B/md_coords\n";
  print $MAKEFILE "GMAP_PROCESS = $opt_B/gmap_process\n";
  print $MAKEFILE "GMAPINDEX = $opt_B/gmapindex\n";
} else {
  print $MAKEFILE "FA_COORDS = $bindir/fa_coords\n";
  print $MAKEFILE "MD_COORDS = $bindir/md_coords\n";
  print $MAKEFILE "GMAP_PROCESS = $bindir/gmap_process\n";
  print $MAKEFILE "GMAPINDEX = $bindir/gmapindex\n";
}
print $MAKEFILE "\n";

print $MAKEFILE "# If WRITEFILE is '-W', then gmapindex will write directly in the file, not in RAM\n";
if (defined($opt_W)) {
  print $MAKEFILE "WRITEFILE = -W\n"
} else {
  print $MAKEFILE "WRITEFILE = \n";
}
print $MAKEFILE "\n";

# Now hardcoded
#print $MAKEFILE "GMAPINDEX_INTERVAL = $opt_q # Change this only for special situations.  Intervals < 3\n";
#print $MAKEFILE "                       # may result in large index files that cannot be read on some machines\n";
#print $MAKEFILE "                       # If you set interval to be 3 (default) or 1, the file can also be used for GSNAP\n";

# Used only for deleting
print $MAKEFILE "FILE_ENDINGS = chromosome chromosome.iit chrsubset contig contig.iit \\\n";
print $MAKEFILE "               genome genomecomp genomealt version \\\n";
print $MAKEFILE "               ";
print $MAKEFILE "id*offsetscomp id*positions ref*offsets ref*bitpackptrs ref*bitpackcomp ref*gammaptrs ref*offsetscomp ref*positions snp*offsets snp*bitpackptrs snp*bitpackcomp snp*gammaptrs snp*offsetscomp snp*positions sarray saindex salcpptrs salcpcomp \\\n";
print $MAKEFILE "               ";
print $MAKEFILE "pf*gammaptrs pf*offsetscomp pf*positions pr*gammaptrs pr*offsetscomp pr*positions\n";

print $MAKEFILE "\n";


########################################################################
#   General commands
########################################################################

print $MAKEFILE "install:\n";
print $MAKEFILE "\tmkdir -p \$(DESTINATION)\n";
if (!defined($opt_D) || $opt_D ne ".") {
    print $MAKEFILE "\tfor s in \$(FILE_ENDINGS); do \\\n";
    print $MAKEFILE "\tif test -r \$(GENOME).\$\$s; then \\\n";
    print $MAKEFILE "\tmv -f \$(GENOME).\$\$s \$(DESTINATION); \\\n";
    print $MAKEFILE "\tfi \\\n";
    print $MAKEFILE "\tdone\n";
}
print $MAKEFILE "\tchmod 644 \$(DESTINATION)/\$(GENOME).*\n";
print $MAKEFILE "\tmkdir -p \$(DESTINATION)/\$(GENOME).maps\n";
print $MAKEFILE "\tchmod 755 \$(DESTINATION)/\$(GENOME).maps\n";
print $MAKEFILE "\n";

printf $MAKEFILE "gmapdb: checkcoords \$(GENOME).version \$(GENOME).sarray \$(GENOME).genomecomp \$(GENOME).ref%d%d%doffsetscomp \$(GENOME).ref%d%d%dpositions gmapmsg\n",
    $gmap_basesize,$gmap_kmersize,$gmap_interval,$gmap_basesize,$gmap_kmersize,$gmap_interval;
printf $MAKEFILE "gmapdb_lc: checkcoords \$(GENOME).version \$(GENOME).sarray \$(GENOME).genome \$(GENOME).ref%d%d%doffsetscomp_lc \$(GENOME).ref%d%d%dpositions gmapmsg\n",
    $gmap_basesize,$gmap_kmersize,$gmap_interval,$gmap_basesize,$gmap_kmersize,$gmap_interval;
printf $MAKEFILE "gmapdb_lc_masked: checkcoords \$(GENOME).version \$(GENOME).sarray \$(GENOME).genome \$(GENOME).ref%d%d%doffsetscomp.masked \$(GENOME).ref%d%d%dpositions.masked gmapmsg\n",
    $gmap_basesize,$gmap_kmersize,$gmap_interval,$gmap_basesize,$gmap_kmersize,$gmap_interval;

print $MAKEFILE "coords: \$(COORDS)\n";
print $MAKEFILE "\n";

print $MAKEFILE "checkcoords: \n";
print $MAKEFILE "\tif test -s \$(COORDS); then \\\n";
print $MAKEFILE "\techo File \$(COORDS) found.  Proceeding...; \\\n";
print $MAKEFILE "\telse \\\n";
print $MAKEFILE "\techo File \$(COORDS) not found.  Please run \"make -f $outputfile coords\" first.; \\\n";
print $MAKEFILE "\texit 1; \\\n";
print $MAKEFILE "\tfi\n";
print $MAKEFILE "\n";

print $MAKEFILE "gmapmsg:\n";
print $MAKEFILE "\techo gmapdb for $genome_name complete.\n";
print $MAKEFILE "\techo To install, do: make -f Makefile.$genome_name install\n";

print $MAKEFILE "cleanall: clean\n";
print $MAKEFILE "\trm -f \$(GENOME).version\n";
print $MAKEFILE "\trm -f Makefile.\$(GENOME)\n";
print $MAKEFILE "\techo To start over again, run gmap_setup\n";
print $MAKEFILE "\n";

print $MAKEFILE "clean:\n";
print $MAKEFILE "\tfor s in \$(FILE_ENDINGS); do \\\n";
print $MAKEFILE "\tif test -r \$(GENOME).\$\$s; then \\\n";
print $MAKEFILE "\trm -f \$(GENOME).\$\$s; \\\n";
print $MAKEFILE "\tfi; \\\n";
print $MAKEFILE "\tdone;\n";
print $MAKEFILE "\trm -f coords.\$(GENOME)\n";
print $MAKEFILE "\n";



########################################################################
#   Coords file
########################################################################

print $MAKEFILE "\$(COORDS):\n";
print $MAKEFILE "\tfor s in \$(FILE_ENDINGS); do \\\n";
print $MAKEFILE "\trm -f \$(GENOME).\$\$s; \\\n";
print $MAKEFILE "\tdone;\n";
if (defined($mdfile = $opt_M)) {
    print $MAKEFILE "\t\$(MD_COORDS) -o \$(COORDS) $mdfile\n";

} elsif (defined($opt_C)) {
# Try to parse chromosomal information
    if (defined($opt_E)) {
	print $MAKEFILE "\t$incommand | \$(FA_COORDS) -C -o \$(COORDS)\n";
    } else {
	print $MAKEFILE "\t\$(FA_COORDS) -C -o \$(COORDS) \$(FASTA)\n";
    }
} else {
    if (defined($opt_E)) {
	print $MAKEFILE "\t$incommand | \$(FA_COORDS) -o \$(COORDS)\n";
    } else {
	print $MAKEFILE "\t\$(FA_COORDS) -o \$(COORDS) \$(FASTA)\n";
    }
}


########################################################################
#   Contig files
########################################################################

if (defined($opt_E)) {
    print $MAKEFILE "\$(GENOME).contig.iit: \$(COORDS)\n";
} else {
    print $MAKEFILE "\$(GENOME).contig.iit: \$(COORDS) \$(FASTA)\n";
}
print $MAKEFILE "\techo Making contig files...\n";
if (defined($opt_E)) {
    print $MAKEFILE "\t$incommand | \$(GMAP_PROCESS) -c \$(COORDS) | \$(GMAPINDEX) -d \$(GENOME) -A \$(CHR_ORDER_FLAG)\n";
} else {
    print $MAKEFILE "\t\$(GMAP_PROCESS) -c \$(COORDS) \$(FASTA) | \$(GMAPINDEX) -d \$(GENOME) -A \$(CHR_ORDER_FLAG)\n";
}
print $MAKEFILE "\n";


########################################################################
#   Genome files
########################################################################

print $MAKEFILE "\$(GENOME).genomecomp: \$(GENOME).contig.iit\n";
print $MAKEFILE "\techo Making compressed genome file...\n";
if (defined($opt_E)) {
    print $MAKEFILE "\t$incommand | \$(GMAP_PROCESS) -c \$(COORDS) | \$(GMAPINDEX) -d \$(GENOME) \$(WRITEFILE) -G\n";
} else {
    print $MAKEFILE "\t\$(GMAP_PROCESS) -c \$(COORDS) \$(FASTA) | \$(GMAPINDEX) -d \$(GENOME) \$(WRITEFILE) -G\n";
}
print $MAKEFILE "\n";


print $MAKEFILE "\$(GENOME).genome: \$(GENOME).contig.iit\n";
print $MAKEFILE "\techo Making full ASCII genome file...\n";
if (defined($opt_E)) {
    print $MAKEFILE "\t$incommand | \$(GMAP_PROCESS) -c \$(COORDS) | \$(GMAPINDEX) -d \$(GENOME) \$(WRITEFILE) -l -G\n";
} else {
    print $MAKEFILE "\t\$(GMAP_PROCESS) -c \$(COORDS) \$(FASTA) | \$(GMAPINDEX) -d \$(GENOME) \$(WRITEFILE) -l -G\n";
}
print $MAKEFILE "\n";


########################################################################
#   GMAP index files, unmasked
########################################################################

$k_flag = "-k $gmap_kmersize";
$q_flag = "-q $gmap_interval";

printf $MAKEFILE "\$(GENOME).ref%d%d%doffsetscomp: \$(GENOME).genomecomp\n",$gmap_basesize,$gmap_kmersize,$gmap_interval;
print $MAKEFILE "\techo Making index offsetscomp file...\n";
print $MAKEFILE "\tcat \$(GENOME).genomecomp | \$(GMAPINDEX) -d \$(GENOME) $k_flag $q_flag -O; \n";
print $MAKEFILE "\n";

printf $MAKEFILE "\$(GENOME).ref%d%d%doffsetscomp_lc: \$(GENOME).genome\n",$gmap_basesize,$gmap_kmersize,$gmap_interval;
print $MAKEFILE "\techo Making index offsetscomp file...\n";
print $MAKEFILE "\tcat \$(GENOME).genome | \$(GMAPINDEX) -d \$(GENOME) -l $k_flag $q_flag -O; \n";
print $MAKEFILE "\n";

printf $MAKEFILE "\$(GENOME).ref%d%d%dpositions: \$(GENOME).ref%d%d%doffsetscomp\n",$gmap_basesize,$gmap_kmersize,$gmap_interval,$gmap_basesize,$gmap_kmersize,$gmap_interval;
print $MAKEFILE "\techo Making index positions file...\n";
print $MAKEFILE "\tif test -s \$(GENOME).genome; then \\\n";
print $MAKEFILE "\tcat \$(GENOME).genome | \$(GMAPINDEX) -d \$(GENOME) -l $k_flag $q_flag -P \$(WRITEFILE); \\\n";
print $MAKEFILE "\telse \\\n";
print $MAKEFILE "\tcat \$(GENOME).genomecomp | \$(GMAPINDEX) -d \$(GENOME) $k_flag $q_flag -P \$(WRITEFILE); \\\n";
print $MAKEFILE "\tfi\n";
print $MAKEFILE "\n";


########################################################################
#   GMAP index files, masked
########################################################################

printf $MAKEFILE "\$(GENOME).ref%d%d%doffsetscomp.masked: \$(GENOME).genome\n",$gmap_basesize,$gmap_kmersize,$gmap_interval;
print $MAKEFILE "\techo Making masked index offsetscomp file...\n";
print $MAKEFILE "\tcat \$(GENOME).genome | \$(GMAPINDEX) -d \$(GENOME) -l -m $k_flag $q_flag -O\n";
print $MAKEFILE "\n";

printf $MAKEFILE "\$(GENOME).ref%d%d%dpositions.masked: \$(GENOME).ref%d%d%doffsetscomp.masked\n",
    $gmap_basesize,$gmap_kmersize,$gmap_interval,$gmap_basesize,$gmap_kmersize,$gmap_interval;
print $MAKEFILE "\techo Making masked index positions file...\n";
print $MAKEFILE "\tcat \$(GENOME).genome | \$(GMAPINDEX) -d \$(GENOME) -l -m $k_flag $q_flag -P\n";
print $MAKEFILE "\n";


########################################################################
#   Suffix array files
########################################################################

print $MAKEFILE "\$(GENOME).sarray: \$(GENOME).genomecomp\n";
print $MAKEFILE "\techo Making suffix array...\n";
print $MAKEFILE "\t\$(GMAPINDEX) -d \$(GENOME) -S\n";
print $MAKEFILE "\n";

########################################################################
#   Version file
########################################################################

print $MAKEFILE "\$(GENOME).version:\n";
print $MAKEFILE "\techo \$(GENOME) > \$\@\n";
print $MAKEFILE "#\tThis file can be edited manually to change the genome name printed by GMAP\n";
print $MAKEFILE "\n";

close($MAKEFILE);


########################################################################
#   Final instructions
########################################################################

$FP = new IO::File(">INSTALL.$genome_name") or die "Cannot write to INSTALL.$genome_name";
print_instructions($FP);
close($FP);

$FP = new IO::File(">&STDOUT");
print_instructions($FP);
close($FP);

exit;



sub print_instructions {
  my ($FP) = @_;

  print $FP <<INSTRUCTIONS1;
============================================================

A Makefile called Makefile.$genome_name has been created for your genome.
You may inspect and edit it if necessary.  To start the build of your genome,
do

INSTRUCTIONS1

print $FP "    make -f $outputfile coords\n";
print $FP "    make -f $outputfile gmapdb\n";
print $FP "    make -f $outputfile install\n";

print $FP <<INSTRUCTIONS2;

If you need to start over again, do

    make -f $outputfile clean  (which preserves Makefile.$genome_name and INSTALL.$genome_name)
 or
    make -f $outputfile cleanall  (which deletes the above files)

A copy of these commands has been written to a file called
INSTALL.$genome_name.

============================================================
INSTRUCTIONS2

  return;
}



sub print_usage {
  print <<TEXT1;

gmap_setup: Sets up a Makefile for creating a genome by use by GMAP or GSNAP.
Part of GMAP package, version $package_version.

Note: It is easier to run the newer program gmap_build instead.

Usage: gmap_setup -d <genomename> [-D <destdir>] [-o <Makefile>] [-C] [-M <.md file>]
       [-E] [-s sorttype] [-k kmersize] [-b basesize] [-q interval] [-W] <fasta_files or command>

    -d    genome name
    -D    destination directory for installation (defaults to gmapdb directory specified at configure time)
    -o    name of output Makefile (default is "Makefile.<genome>")
    -M    use coordinates from an .md file (e.g., seq_contig.md file from NCBI)
    -C    try to parse chromosomal coordinates from each FASTA header
    -E    interpret argument as a command, instead of a list of FASTA files
    -s    use given sorttype to order chromosomes: none, alpha, numeric-alpha, or chrom (default)
    -k    kmer size

  Advanced flags, not typically used:
    -b    offsetscomp basesize
    -q    GMAP indexing interval (default: 3 nt)
    -W    write some output directly to file, instead of using RAM (use only if RAM is limited)

These flags are explained below:

If you want to treat each FASTA entry as a separate chromosome (either
because it is in fact an entire chromosome or because you have contigs
without any chromosomal information), you can simply call gmap_setup
like this:

    gmap_setup -d <genome> <fasta_file>...

The accession of each FASTA header (the word following each ">") will
be the name of each chromosome.  GMAP can handle an unlimited number
of "chromosomes", with arbitrarily long names.  In this way, GMAP
could be used as a general search program for near-identity matches
against a FASTA file.


* The -M and -C flags: If your sequences represent contigs that have
  mapping information to specific chromosomal regions, then you can
  have gmap_setup try to read each header to determine its chromosomal
  region (the -C flag) or read an .md file that contains information
  about chromosomal regions (the -M flag).  The .md files are often
  provided in NCBI releases, but since the formats change often,
  gmap_setup will prompt you to make sure it parses it correctly.


* The -E flag: If you need to pre-process the FASTA files before using
  these programs, perhaps because they are compressed or because you
  need to insert chromosomal information in the header lines, you can
  specify a command instead of multiple fasta_files, like these
  examples:

    gmap_setup -d <genome> -E 'gunzip -c genomefiles.gz'
    gmap_setup -d <genome> -E 'cat *.fa | ./add-chromosomal-info.pl'


* The -W flag: The gmap_setup process works best if you have a
  computer with enough RAM to hold the entire genome (e.g., 3
  gigabytes for a human- or mouse-sized genome).  Since the resulting
  genome files work across all machine architectures, you can find any
  machine with sufficient RAM to build the genome files and then
  transfer the files to another machine.  (GMAP itself runs fine on
  machines with limited RAM.)  If you cannot find any machine with
  sufficient RAM for gmap_setup, you can run the program with the -W
  flag to write the files directly, but this can be very slow.


* The -q flag: If you specify a smaller interval (for example,
  1 for the GMAP sampling interval), you can create a higher-resolution
  database, which can improve speed somewhat.  However, the corresponding
  genome index files will be larger (three times as big if you specify -q 1).
  These index files may exceed the 4-gigabyte filesize limit on some computers,
  and will therefore fail to work on those computers.


TEXT1
  return;
}

