#!/usr/bin/perl -w

###################
# Divide chromosome sequence (MIPS pseudo-molecule sequence file) into
# sequence fragments of specified length (in FASTA format). Output file contains
# a specified number of sequence fragments. The chromosome coordinates
# of the fragment limits are used as FASTA sequence IDs (locus names).


use strict;
use Getopt::Long;

# fragment and file LENGTH (number of nucleotides) should be a multiple of 80 as there are
# 80 nucleotides in a line of sequence data (in MIPS chromosome files)
my $fileLength = 400000000;    	# 400Mb maximum size
my $fragmentLength = 50000; 	# 50k bases per chunk

# convert file and fragment length to number of lines
$fileLength = $fileLength/80 - ($fileLength % 80);
$fragmentLength = $fragmentLength/80 - ($fragmentLength % 80);

my ($script) = ($0 =~ m|([^/]*)$|);
my $version = "03/06/2004";
my $USAGE = "USAGE: $script [-options] <MIPS chromosome sequence file> <output file name>
options:
	-h			(-help)		print options
	-v 			(-version)	print version of this script
";

#options list
my ($opt_v,$opt_h)=(0,0);

# get the supplied command line options, and set flags
&GetOptions('v|version'=>\$opt_v, 'h|help'=>\$opt_h);

if ($#ARGV == -1 && !($opt_h|$opt_v) ) {
    print "Required command line arguments: chromosome sequence file, output file name.\n\n";
    die $USAGE;
}
if ($opt_h) {
	print $USAGE;
	exit;
}
if ($opt_v) {
	print "version $version\n";
	exit;
}


# input file
my $path;
$path=$ENV{'PWD'} unless (defined($path));					# set path to current directory

my $chromoFileName = $ARGV[0];
$chromoFileName = $path."/".$chromoFileName if ($chromoFileName!~/\w+.*\//);	# append current directory path to input file if necessary

# output files
my $outFileName = ">".$ARGV[1];

# input file handle
my $IN = *IN;

# fragments file counter
my $fileCounter = 1;

# create fragments
open (IN, "<".$chromoFileName) || die "can't open file: $!";

while ( createFragmentsFromMIPSchromosome($IN,$fileCounter,$fileLength,$fragmentLength,$chromoFileName,$outFileName) ) {
	$fileCounter++;
}

close (IN) || die "can't close file: $!";


###################
# Create a file containing a fragment of specified length of the
# DNA sequence of a MIPS A.thaliana chromosome pseudomolecule file.
# Return TRUE if successful, FALSE otherwise (typically when the
# end of the chromosome file has been reached).

sub createFragmentsFromMIPSchromosome {
	# First argument is the input filehandle, second is a fragment ID,
 	# third is the proposed length of sequence fragments (to be
  	# rounded down to a multiple of 80). The fourth argument contains
    	# the name (and path) of the chromosome file preceded by ">". The
	# last argument contains ouput file(s) path.
	my($IN,$fileID,$numFileLines,$numFragmentLines,$chromoFile,$outFileName) = @_;
 	my $lineCounter;
  	my @coordinate;
   	my $sequence;
	my $chromoID;
 	my $fragmentID;
  	my $sequenceID;

  	# Get one line of sequence and check if end the input file hasn't been reached
  	if ( ( ($sequence,@coordinate) = getSequenceFromMIPSchromo($IN,1) )[0] ) {

 		# create new fragments file

 		# parse chromosome id (from input filename)
        	$chromoFile =~ /.*\//;
        	$chromoID = $';         # store chromosome id

        	# open file to store fragment sequences
		open (OUT, ">".$outFileName) || die "can't open file: $!";

 		#create fragments
  		READ: for ($fragmentID=1; $fragmentID<=($numFileLines/$numFragmentLines); $fragmentID++) {

			if ($fragmentID eq 1) {
			# first fragment's first line has already been read
   				if ( ((my $seq1, my @coord1) = getSequenceFromMIPSchromo($IN,$numFragmentLines-1))[0] ) {
					$sequence .= $seq1;
     					$coordinate[1] = $coord1[1];
				}
           			else {  		# end of file
             				last READ;
  				}
			}
     			else {
			# all subsequent fragments
				unless( (($sequence,@coordinate) = getSequenceFromMIPSchromo($IN,$numFragmentLines))[0] ) {
    					last READ;
				}
        		}

			# create FASTA entry for fragment in OUT file
  			printf OUT (">%08u::%08u  chromosomal coordinates, fragment %u \n", $coordinate[0],$coordinate[1],$fragmentID);
       			print OUT $sequence;
		}

		close (OUT) || die "can't close file: $!";
       		return 1;
 	}
 	else {  # end of input file has been reached!
  		return 0;
   	}
}



###################
# Takes a filehandle for an open MIPS chromosome file, and a number of lines.
# Returns a 3-element list consisting of:
# a) sequence (including 'new line' characters) from the specified number of lines
# (starting from current input file position);
# b) initial chromosome coordinate for the sequence;
# c) end chromosome coordinate for the sequence.
# NOTE: when the end of the input file has been reached the function will return zero!

sub getSequenceFromMIPSchromo {
	my($IN,$numLines) = @_;
 	my $sequence;
  	my $initialCoord;
  	my $numNucleotides;
 	my $lineCounter;

  	if (defined ($_=<$IN>)) {
		$lineCounter = 1;
  		# get initial coordinate and sequence
   		($initialCoord,$sequence) = /(\d+)\s*([a-zA-Z]+\n)/;
    		$numNucleotides = length($sequence)-1;  # exclude 'new line' from base count

     		# get remaining sequence and number of nucleotides
		while ( ($lineCounter < $numLines) && defined ($_=<$IN>) ) {
			$lineCounter++;
  			/[a-zA-Z]+/;
	 		$numNucleotides += length($&);
  			$sequence .= $&."\n";
     	  	}
		return ($sequence,$initialCoord,$initialCoord+$numNucleotides-1);
	}
	return 0;  # if end of input file has been reached
 }
