#!/usr/bin/perl

# Program to batch-process a genbank file with multiple chromosomes
# Outputs a protein and nucleotide multifasta and calculates for each chromosome
# Average gene length, coding density (inc RNA genes), Average gene length, GC%, GCintergenic, GC2, GC4, GCRna

# Usage: genbank_multi_process.pl <genbank> <output path>

use strict;
use warnings;
use Data::Dumper;

my $genbank_file = $ARGV[0];
my $output_path = $ARGV[1];

unless ($output_path)
{
	print "\nNot enough arguments\n";
	exit 1;
}

my @loci; # Array of split loci, each an array of lines

open (GENBANK, "<$genbank_file") or die "\nCouldn't open $genbank_file\n";
my $current_index = -1;
while (<GENBANK>)
{
	my $line = $_;
	chomp $line;
	if (substr($line, 0, 5) eq 'LOCUS') { $current_index++; }
	
	push (@{ $loci[$current_index] }, $line );
}
close GENBANK or warn "close failed\n";

# Print out as calculated, because the run can take a long time
my $table_output = $output_path . '/summary_table';
print "Table output path: $table_output\n";
open (TABLEOUTPUT, ">$table_output") or die "\nCouldn't open $table_output\n";

# Make filehandle hot - so write lines are not buffered but written immediately
select((select(TABLEOUTPUT), $|=1)[0]);

print TABLEOUTPUT "species\tstrain\taccession\tlength\tnum_cds\tnum_rna\tav_gene_length\tav_intergenic_length\tcoding_density\tgc_percent\tgc_coding\tgc_intergenic\tgc2\tgc4\tgcRNA\n";
print "species\tstrain\taccession\tlength\tnum_cds\tnum_rna\tav_gene_length\tav_intergenic_length\tcoding_density\tgc_percent\tgc_coding\tgc_intergenic\tgc2\tgc4\tgcRNA\n";

foreach my $chromosomeArrayRef (@loci)
{
	my $hashRef = processGenome( $chromosomeArrayRef );
	my %tmpHash = %{ $hashRef };
	print TABLEOUTPUT "$tmpHash{'species'}\t$tmpHash{'strain'}\t$tmpHash{'accession'}\t$tmpHash{'length'}\t$tmpHash{'num_cds'}\t$tmpHash{'num_rna'}\t$tmpHash{'av_gene_length'}\t$tmpHash{'av_intergenic_length'}\t$tmpHash{'coding_density'}\t$tmpHash{'gc_percent'}\t$tmpHash{'gc_coding'}\t$tmpHash{'gc_intergenic'}\t$tmpHash{'gc2'}\t$tmpHash{'gc4'}\t$tmpHash{'gcRNA'}\n";
	print "$tmpHash{'species'}\t$tmpHash{'strain'}\t$tmpHash{'accession'}\t$tmpHash{'length'}\t$tmpHash{'num_cds'}\t$tmpHash{'num_rna'}\t$tmpHash{'av_gene_length'}\t$tmpHash{'av_intergenic_length'}\t$tmpHash{'coding_density'}\t$tmpHash{'gc_percent'}\t$tmpHash{'gc_coding'}\t$tmpHash{'gc_intergenic'}\t$tmpHash{'gc2'}\t$tmpHash{'gc4'}\t$tmpHash{'gcRNA'}\n";
}
close TABLEOUTPUT;

sub processGenome
{
	my $genomeArrayRef = $_[0];
	#print Dumper ( $genomeArrayRef );
	# Split into header, features and sequence
	my $features_index;
	my $origin_index;
	my %attributes_hash;
	
	for ( my $i = 0; $i < scalar(@$genomeArrayRef); $i++ )
	{
		my $line = ${ $genomeArrayRef }[$i];
		if (substr($line, 0, 8) eq 'FEATURES') 
		{ 
			#print "Set Features index $i\n";
			#print "Line: $$genomeArrayRef[$i]\n";
			$features_index = $i; 
		}
		
		if (substr($line, 0, 6) eq 'ORIGIN') 
		{ 
			#print "Set Origin index $i\n";
			#print "Line: $$genomeArrayRef[$i]\n";
			$origin_index = $i; 
		}
	}
	
	# Because splice removes the elements, will have to do in reverse order
	my @sequence_section = splice (@$genomeArrayRef, $origin_index);
	my @features = splice( @$genomeArrayRef, $features_index, ( $origin_index - ( $features_index - 1) ));
	my @header = splice( @$genomeArrayRef, 0, $features_index );
	#print Dumper ( \@header );
	#print Dumper ( \@features );
	#print Dumper ( \@sequence_section );
	#print Dumper ( \@sequence_section );
	
	# Get info from header
	foreach my $line (@header)
	{
		if (substr($line, 0, 9) eq 'ACCESSION')
		{
			my @linearray = split (/ +/, $line);
			$attributes_hash{ 'accession' } = $linearray[1];
		}
		
		if (substr($line, 0, 12) =~ 'ORGANISM')
		{
			my @linearray = split (/ +/, $line);
			my $species;
			my $strain;
			if ($linearray[2] eq 'Candidatus')
			{
				$species = join(' ', $linearray[3], $linearray[4], $linearray[5]);
				if ($linearray[5])
				{
					my @strainArray = splice (@linearray, 5);
					$strain = join(' ', @strainArray);
				} else {
					$strain = '';
				}
			} else {
				$species = join(' ', $linearray[2], $linearray[3]);
				if ($linearray[4])
				{
					my @strainArray = splice (@linearray, 4);
					$strain = join(' ', @strainArray);
				} else {
					$strain = '';
				}
			}
			
			$attributes_hash{ 'species' } = $species;
			$attributes_hash{ 'strain' } = $strain;
		}
	}
	
	print "Parsing $attributes_hash{'species'} $attributes_hash{'strain'} $attributes_hash{'accession'}\n";
	
	# Get full sequence
	my $genome_sequence = '';
	foreach my $line (@sequence_section)
	{
		if ($line)
		{
			unless ((substr($line, 0, 6) eq 'ORIGIN') || (substr($line, 0, 2) eq '//'))
			{
				my $seqPortion = substr($line, 10);
				$seqPortion =~ s/\s//g;
				$seqPortion = uc( $seqPortion );
				$genome_sequence = $genome_sequence . $seqPortion;
			}
		}
	}
	
	#my @genomeLines = unpack '(A60)*', $genome_sequence;
	#foreach my $line (@genomeLines)
	#{
	#	print "$line\n";
	#}
	
	# Get GC percent and length of whole sequence 
	$attributes_hash{ 'gc_percent' } = gc_percent( $genome_sequence );
	$attributes_hash{ 'length' } = length( $genome_sequence );
	
	# Make an array of features - only use 'CDS', 'ncRNA', 'rRNA', and 'tRNA'
	my @records;
	my $current_index = -1;
	my $record_feature = 0;
	foreach my $line (@features)
	{
		if (length( $line ) < 22)
		{
			next;
		}
		
		my $descriptor = substr($line, 0, 21);
		$descriptor =~ s/\s//g;
		my $value = substr($line, 21);
		if ($descriptor)
		{
			if (($descriptor eq 'CDS') || ($descriptor eq 'tRNA') || ($descriptor eq 'rRNA') || ($descriptor eq 'ncRNA'))
			{
				$record_feature = 1;
				$current_index++;
				
				# This line will contain the coordinates
				# First records will be stored as 0 - type, 1 - start, 2 - end, 3 - direction
				
				# Remove angle brackets from $value (i.e <1..1941)
				$value =~ s/\>//g;
				$value =~ s/\<//g;
				
				my @valueArray = split(/\(|\)/, $value);
				my $direction;
				if ($valueArray[0] eq 'complement')
				{
					$direction = 'reverse';
					shift @valueArray;
				} else {
					$direction = 'forward';
				}
				
				# Get coordinates for each section
				if ($valueArray[0] eq 'join')
				{
					# Split coordinate string into sections
					my @sectionArray = split(/\,/, $valueArray[-1]);
					my @recordStartArray = ( $descriptor );
					my $first_record = 1;
					foreach my $coordString (@sectionArray)
					{
						my @coordArray = split (/\.+/, $coordString);
						if ($first_record == 1)
						{
							push (@recordStartArray, $coordArray[0], $coordArray[-1], $direction);
							$first_record = 0;
						} else {
							push (@recordStartArray, 'join', $coordArray[0], $coordArray[-1], $direction);
						}
					}
					$records[$current_index] = [ @recordStartArray ];
				} else {
					# There is only one coord set
					my @coordArray = split (/\.+/, $valueArray[-1]);
					my @recordStartArray = ( $descriptor, $coordArray[0], $coordArray[-1], $direction );
					$records[$current_index] = [ @recordStartArray ];
				}
				
				# Old way - does not account for join(xxx..xxx,xxx..xxx) statements
				#if ($value =~ 'complement')
				#{
				#	my $coordLength = length($value) - 12;
				#	my @coordArray = split(/\.+/, substr($value, 11, $coordLength));
				#	my @recordStartArray = ( $descriptor, $coordArray[0], $coordArray[-1], 'reverse' );
				#	$records[$current_index] = [ @recordStartArray ];
				#} else {
				#	my @coordArray = split (/\.+/, $value);
				#	my @recordStartArray = ( $descriptor, $coordArray[0], $coordArray[-1], 'forward' );
				#	$records[$current_index] = [ @recordStartArray ];
				#}
			} else {
				$record_feature = 0;
			}
		} else {
			if ($record_feature)
			{
				push (@{ $records[ $current_index ] }, $value );
			}
		}
	}
	
	my @CDS;
	my @RNA;
	my @intergenic;
	my $intergenic_sequence = '';
	my $coding_sequence = '';
	my $rna_sequence = '';
	my $GC2_nucleotides = '';
	my $GC4_nucleotides = '';
	
	# Keeps track of coordinates that are part of coding sequence (including RNA genes).
	my @coding_coordinates = (0) x length( $genome_sequence );
	
	# Get CDS, RNA and intergenic sequences, also get nucleotide sequences and calculate other parameters
	foreach my $featureArrayRef ( @records )
	{
		# Keys as genbank except for 'startCoord', 'endCoord' and 'direction'
		my $hashRef = hashFromFeatureArray( $featureArrayRef );
		#print Dumper ( $hashRef );
		# Get nucleotide sequence for feature.  If it is a coding sequence, check the translation
		
		$hashRef->{ 'nucleotide' } = getNucleotideSeq( $hashRef, \$genome_sequence );
		# Old way - didn't take into account ribosomal slippages
		my $start_index = $hashRef->{ 'startCoord' } - 1;
		my $seqLength = $hashRef->{ 'endCoord' } - $start_index;
		#if ($hashRef->{ 'direction' } eq 'forward')
		#{
		#	$hashRef->{ 'nucleotide' } = substr( $genome_sequence, $start_index, $seqLength );
		#} else {
		#	$hashRef->{ 'nucleotide' } = reverseComp( substr( $genome_sequence, $start_index, $seqLength ) );
		#}
		
		#print Dumper ( $hashRef );
		
		# Check translation if CDS
		if ( $hashRef->{ 'type' } eq 'CDS' )
		{
			# Ignore CDS genes marked as 'pseudo'
			unless (defined $hashRef->{ 'pseudo' })
			{
				# Program will exit if there is a problem
				checkTranslation( $hashRef );
				# Calculate gc_percent, gc2, gc4
				$hashRef->{ 'gc_percent' } = gc_percent( $hashRef->{ 'nucleotide' } );
				my $gc2 = getGC2nucleotides( $hashRef->{ 'nucleotide' } );
				my $gc4 = getGC4nucleotides( $hashRef->{ 'nucleotide' }, $hashRef->{ 'transl_table' } );
				$GC2_nucleotides = $GC2_nucleotides . $gc2;
				$GC4_nucleotides = $GC4_nucleotides . $gc4;
				$hashRef->{ 'gc2' } = gc_percent( $gc2 );
				$hashRef->{ 'gc4' } = gc_percent( $gc4 );
				push (@CDS, $hashRef);
			}
		} else { # ncRNA, rRNA or tRNA
			# Calculate gc_percent
			$hashRef->{ 'gc_percent' } = gc_percent( $hashRef->{ 'nucleotide' });
			$rna_sequence = $rna_sequence . $hashRef->{ 'nucleotide' };
			push (@RNA, $hashRef);
		}
		
		# Mark coordinates as coding
		unless ( $hashRef->{ 'startCoord' } > $hashRef->{ 'endCoord' } )
		{
			for( my $i = $start_index; $i < ( $start_index + $seqLength ); $i++ )
			{
				$coding_coordinates[ $i ] = 1;
			}
		} else {
			# Gene/feature spans the origin point of the chromosome
			my @startCoords = @{ $hashRef->{ 'startCoords' } };
			my @endCoords = @{ $hashRef->{ 'endCoords' } };
			for( my $i = 0; $i < scalar( @startCoords ); $i++ )
			{
				my $tmpStartIndex = $startCoords[$i] - 1;
				my $tmpLength = $endCoords[$i] - $tmpStartIndex;
				for ( my $j = $tmpStartIndex; $j < ( $tmpStartIndex + $tmpLength ); $j++ )
				{
					$coding_coordinates[ $j ] = 1;
				}
			}
		}
	}
	
	# Get intergenic sequences
	my $last_value = 1;
	$current_index = -1;
	my $locus_tag_counter = 1;
	for ( my $i = 0; $i < ( length( $genome_sequence )); $i++ )
	{
		if (( $coding_coordinates[ $i ] - $last_value ) == -1 )
		{
			$current_index++;
		}
		$last_value = $coding_coordinates[$i];
		
		my $currentChar = substr( $genome_sequence, $i, 1 );
		
		if ( $coding_coordinates[ $i ] == 0 )
		{
			unless ($intergenic[ $current_index ])
			{
				my %hash;
				$hash{ 'startCoord' } = ( $i + 1 ); #Coordinate, not index
				$hash{ 'locus_tag' } = 'intergenic_' . $locus_tag_counter;
				$locus_tag_counter++;
				$hash{ 'seq' } = '';
				$intergenic[ $current_index ] = \%hash;
			}
			
			$intergenic_sequence = $intergenic_sequence . $currentChar;
			
			$intergenic[$current_index]->{ 'seq' } = $intergenic[$current_index]->{ 'seq' } . $currentChar;
			#print "Currentindex: $current_index CurrentChar: $currentChar\n";
		} else {
			$coding_sequence = $coding_sequence . $currentChar;
		}
	}
	
	# Set some global values
	$attributes_hash{ 'gc_coding' } = gc_percent( $coding_sequence );
	$attributes_hash{ 'gc_intergenic' } = gc_percent( $intergenic_sequence );
	$attributes_hash{ 'gc2' } = gc_percent( $GC2_nucleotides );
	$attributes_hash{ 'gc4' } = gc_percent( $GC4_nucleotides );
	$attributes_hash{ 'coding_density' } = (length( $coding_sequence ) / length( $genome_sequence )) * 100;
	$attributes_hash{ 'gcRNA' } = gc_percent( $rna_sequence );
	$attributes_hash{ 'num_cds' } = scalar(@CDS);
	$attributes_hash{ 'num_rna' } = scalar(@RNA);
	
	# Calculate end coordinates and GC% for each intergenic sequence
	#print Dumper ( \@intergenic );
	foreach my $hashRef (@intergenic)
	{
		#print Dumper ( \$hashRef );
		my $length = length ( $hashRef->{ 'seq' } );
		$hashRef->{ 'endCoord' } = $hashRef->{ 'startCoord' } + $length - 1;
		$hashRef->{ 'gc_percent' } = gc_percent( $hashRef->{ 'seq' });
	}
	
	# Calculate average gene size
	my $total_cds_length = 0;
	my $num_genes = @CDS;
	foreach my $hashRef (@CDS)
	{
		$total_cds_length += length( $hashRef->{ 'nucleotide' } );
	}
	
	# Protect from divide by zero
	if ( $num_genes )
	{
		$attributes_hash{ 'av_gene_length' } = $total_cds_length / $num_genes;
	} else {
		$attributes_hash{ 'av_gene_length' } = 0;
	}
	
	# Calculate average intergenic length
	my $total_intergenic_length = 0;
	my $num_intergenic = @intergenic;
	foreach my $hashRef (@intergenic)
	{
		$total_intergenic_length += length( $hashRef->{ 'seq' } );
	}
	$attributes_hash{ 'av_intergenic_length' } = $total_intergenic_length / $num_intergenic;
	
	# Output fasta files
	my @identifierArray = (split (' ', $attributes_hash{ 'species' }), split (' ', $attributes_hash{ 'strain' }), $attributes_hash{ 'accession'});
	my $identifierString = join('_', @identifierArray);
	my $protein_multifasta_file = $output_path . '/' . $identifierString . '_protein.fasta';
	my $nucleotide_multifasta_file = $output_path . '/' . $identifierString . '_nucleotide_CDS.fasta';
	my $rna_multifasta_file = $output_path . '/' . $identifierString . '_nucleotide_RNA.fasta';
	my $intergenic_multifasta_file = $output_path . '/' . $identifierString . '_intergenic.fasta';
	
	open (PROTEIN, ">$protein_multifasta_file") or die "\nCouldn't open $protein_multifasta_file\n";
	open (NUCLEOTIDE, ">$nucleotide_multifasta_file") or die "\nCouldn't open $nucleotide_multifasta_file\n";
	
	foreach my $hashRef (@CDS)
	{
		my $seq_header = '>' . $hashRef->{ 'locus_tag' };
		if ($hashRef->{ 'gene' })
		{
			$seq_header = $seq_header . ' ' . $hashRef->{ 'gene' };
		}
		if ($hashRef->{ 'product' })
		{
			$seq_header = $seq_header . ' ' . $hashRef->{ 'product' };
		}
		
		my $proteinSeq = $hashRef->{ 'translation' };
		my $nucleotideSeq = $hashRef->{ 'nucleotide' };
		my @proteinLines = unpack '(A60)*', $proteinSeq;
		my @nucleotideLines = unpack '(A60)*', $nucleotideSeq;
		
		print PROTEIN "$seq_header\n";
		print NUCLEOTIDE "$seq_header\n";
		
		foreach my $line (@proteinLines)
		{
			print PROTEIN "$line\n";
		}
		
		foreach my $line (@nucleotideLines)
		{
			print NUCLEOTIDE "$line\n";
		}
	}
	
	close PROTEIN;
	close NUCLEOTIDE;
	
	open (RNA, ">$rna_multifasta_file") or die ("\nCouldn't open $rna_multifasta_file\n");
	foreach my $hashRef (@RNA)
	{
		my $seq_header = '>' . $hashRef->{ 'locus_tag' };
		if ($hashRef->{ 'gene' })
		{
			$seq_header = $seq_header . ' ' . $hashRef->{ 'gene' };
		}
		if ($hashRef->{ 'product' })
		{
			$seq_header = $seq_header . ' ' . $hashRef->{ 'product' };
		}
		
		my $nucleotideSeq = $hashRef->{ 'nucleotide' };
		my @nucleotideLines = unpack '(A60)*', $nucleotideSeq;
		
		print RNA "$seq_header\n";
		
		foreach my $line (@nucleotideLines)
		{
			print RNA "$line\n";
		}
	}
	
	close RNA;
	
	open (INTERGENIC, ">$intergenic_multifasta_file") or die "\nCouldn't open $intergenic_multifasta_file\n";
	foreach my $hashRef (@intergenic)
	{
		my $seq_header = '>' . $hashRef->{ 'locus_tag' };
		my $nucleotideSeq = $hashRef->{ 'seq' };
		my @nucleotideLines = unpack '(A60)*', $nucleotideSeq;
		
		print INTERGENIC "$seq_header\n";
		
		foreach my $line (@nucleotideLines)
		{
			print INTERGENIC "$line\n";
		}
	}
	
	close INTERGENIC;
	
	# Output tables
	my $protein_table = $output_path . '/' . $identifierString . '_protein.tab';
	my $rna_table = $output_path . '/' . $identifierString . '_rna.tab';
	my $intergenic_table = $output_path . '/' . $identifierString . '_intergenic.tab';
	
	open (PROTEINTAB, ">$protein_table") or die "\nCouldn't open $protein_table\n";
	print PROTEINTAB "locus_tag\tlength\tstartCoord\tendCoord\tdirection\tgc_percent\tgc2\tgc4\n";
	
	foreach my $hashRef (@CDS)
	{
		my %tmpHash = %{ $hashRef };
		my $length = length( $tmpHash{ 'nucleotide' });
		print PROTEINTAB "$tmpHash{'locus_tag'}\t$length\t$tmpHash{'startCoord'}\t$tmpHash{'endCoord'}\t$tmpHash{'direction'}\t$tmpHash{'gc_percent'}\t$tmpHash{'gc2'}\t$tmpHash{'gc4'}\n";
	}
	
	close PROTEINTAB;
	
	open (RNATAB, ">$rna_table") or die "\nCouldn't open $rna_table\n";
	print RNATAB "locus_tag\tlength\tstartCoord\tendCoord\tdirection\tgc_percent\n";
	
	foreach my $hashRef (@RNA)
	{
		my %tmpHash = %{ $hashRef };
		my $length = length ( $tmpHash{ 'nucleotide' } );
		print RNATAB "$tmpHash{'locus_tag'}\t$length\t$tmpHash{'startCoord'}\t$tmpHash{'endCoord'}\t$tmpHash{'direction'}\t$tmpHash{'gc_percent'}\n";
	}
	
	close RNATAB;
	
	open (INTERGENICTAB, ">$intergenic_table") or die "\nCouldn't open $intergenic_table\n";
	print INTERGENICTAB "locus_tag\tlength\tstartCoord\tendCoord\tgc_percent\n";
	
	foreach my $hashRef (@intergenic)
	{
		my %tmpHash = %{ $hashRef };
		my $length = length ( $tmpHash{ 'seq' } );
		print INTERGENICTAB "$tmpHash{'locus_tag'}\t$length\t$tmpHash{'startCoord'}\t$tmpHash{'endCoord'}\t$tmpHash{'gc_percent'}\n";
	}
	
	close INTERGENICTAB;
	
	return \%attributes_hash;
}

# Assumes seq is already in upper case
sub gc_percent
{
	my $nucleotide_seq = $_[0];
	my $total_length = length( $nucleotide_seq );
	
	if ($total_length == 0)
	{
		return 0;
	}
	
	my $GC_count = ($nucleotide_seq =~ tr/G//);
	$GC_count += ($nucleotide_seq =~ tr/C//);
	
	# Degenerate counting
	$GC_count += ($nucleotide_seq =~ tr/S//);
	$GC_count += (($nucleotide_seq =~ tr/M//) * 0.5);
	$GC_count += (($nucleotide_seq =~ tr/K//) * 0.5);
	$GC_count += (($nucleotide_seq =~ tr/R//) * 0.5);
	$GC_count += (($nucleotide_seq =~ tr/Y//) * 0.5);
	$GC_count += (($nucleotide_seq =~ tr/B//) * 0.667);
	$GC_count += (($nucleotide_seq =~ tr/D//) * 0.333);
	$GC_count += (($nucleotide_seq =~ tr/H//) * 0.333);
	$GC_count += (($nucleotide_seq =~ tr/V//) * 0.667);
	$GC_count += (($nucleotide_seq =~ tr/N//) * 0.5);
	
	my $GC_percent = ($GC_count / $total_length) * 100;
	return $GC_percent;
}

sub hashFromFeatureArray
{
	my $arrayRef = $_[0];
	my @tmpArray = @$arrayRef;
	my %featureHash;
	#print "hashFromFeatureArray: \n";
	#print Dumper ( $arrayRef );
	# Get initial values, which are stored sequentially
	
	# Old way - didn't take into account ribosomal slippage
	#$featureHash{ 'type' } = $tmpArray[0];
	#$featureHash{ 'startCoord' } = $tmpArray[1];
	#$featureHash{ 'endCoord' } = $tmpArray[2];
	#$featureHash{ 'direction' } = $tmpArray[3];
	
	my @startCoords;
	my @endCoords;
	my $keys_start_index = 4;
	# Grab first record
	$featureHash{ 'type' } = $tmpArray[0];
	push (@startCoords, $tmpArray[1]);
	push (@endCoords, $tmpArray[2]);
	$featureHash{ 'direction' } = $tmpArray[3];
	
	# Get subsequent records
	for ( my $i = 4; $i < scalar(@tmpArray); $i += 4 )
	{
		unless ( $tmpArray[$i] eq 'join' )
		{
			$keys_start_index = $i;
			last;
		}
		
		push (@startCoords, $tmpArray[$i + 1]);
		push (@endCoords, $tmpArray[$i + 2]);
		
		unless ( $tmpArray[$i + 3] eq $featureHash{ 'direction' } )
		{
			print "Error!  The different parts of this gene go in different directions!\n";
			exit 1;
		}
	}
	
	$featureHash{ 'startCoord' } = $startCoords[0];
	$featureHash{ 'endCoord' } = $endCoords[-1];
	
	$featureHash{ 'startCoords' } = [ @startCoords ];
	$featureHash{ 'endCoords' } = [ @endCoords ];
	
	# Parse subsequent lines which are equivalent to the $value parts of the original genbank
	my $last_key;
	for ( my $i = $keys_start_index; $i < scalar(@tmpArray); $i++ )
	{
		my $line = $tmpArray[$i];
		if ($line eq '/pseudo')
		{
			$featureHash{ 'pseudo' } = 1;
		}
		
		my @linearray = split ('=', $line);
		if (scalar(@linearray) > 1)
		{
			# New key line
			#print Dumper ( \@linearray );
			$last_key = substr($linearray[0], 1);
			my $value = $linearray[1];
			$value =~ s/\"//g;
			$featureHash{ $last_key } = $value;
		} else {
			# Value is part of last key on multiple lines
			my $value = $linearray[0];
			$value =~ s/\"//g;
			$featureHash{ $last_key } = $featureHash { $last_key } . $value;
		}
	}
	
	return \%featureHash;
}

sub reverseComp
{
	my $nucleotide_seq = $_[0];
	my $reverseComp = reverse ($nucleotide_seq);
	$reverseComp =~ tr/ACGT/TGCA/;
	return $reverseComp;
}

# Returns a string containing the nucleotides from the second position of codons
# The translation would have already been checked, so assume it is fine
sub getGC2nucleotides
{
	my $nucleotide_seq = $_[0];
	my @codons = unpack '(A3)*', $nucleotide_seq;
	my $second_position_nucleotides = '';
	
	my $first_codon = 1;
	foreach my $codon (@codons)
	{
		# Exclude start and stop codons
		if (($first_codon == 1) && (
			($codon eq 'TTG') || ($codon eq 'CTG') || ($codon eq 'ATT') || ($codon eq 'ATC') || ($codon eq 'ATA') ||
			($codon eq 'ATG') || ($codon eq 'GTG')))
		{
			$first_codon = 0;
			next;
		}
		if (($codon eq 'TAA') || ($codon eq 'TAG') || ($codon eq 'TGA'))
		{
			last;
		}
		
		$second_position_nucleotides = $second_position_nucleotides . substr($codon, 1, 1);
	}
	
	return $second_position_nucleotides;
}

# Returns a string containing the nucleotides from the third position of codons with
# fourfold degeneracy (assumes bacterial translation table 11)
sub getGC4nucleotides
{
	my $nucleotide_seq = $_[0];
	my $translation_table = $_[1];
	my @codons = unpack '(A3)*', $nucleotide_seq;
	my $third_position_nucleotides_gc4 = '';
	
	foreach my $codon (@codons)
	{
		my $first_two_positions = substr($codon, 0, 2);
		if (isGC4site( $codon, $translation_table ))
		{
			$third_position_nucleotides_gc4 = $third_position_nucleotides_gc4 . substr($codon, 2);
		}
	}
	
	return $third_position_nucleotides_gc4;
}

# Checks that:
# 1. Nucleotide length = 3 * protein length
# 2. Checks start codon present and correct.
# 3. Translation of nucleotide = given translation
# Exits program if there is a problem
# Assumes bacterial translation table 11
sub checkTranslation
{
	my $hashRef = $_[0];
	my $translation = $hashRef->{ 'translation' };
	my $nucleotide_seq = $hashRef->{ 'nucleotide' };
	my $locus_tag = $hashRef->{ 'locus_tag' };
	my $translation_table = $hashRef->{ 'transl_table' };
	my @codons = unpack '(A3)*', $nucleotide_seq;

	my $errors = 0;
	
	# Check length
	unless ( length( $nucleotide_seq ) == ( 3 * length( $translation ) ))
	{
		print "$locus_tag : Nucleotide sequence does not have the right length for the given translation\n";
		# Could just be missing the stop codon 'translation' (*), so try adding it
		if ( length( $nucleotide_seq ) == ( ( 3 * length( $translation )) + 3))
		{
			print "$locus_tag: It looks like you might just be including the stop codon in the nucleotide seq\n";
			$translation = $translation . '*';
		} else {
			$errors++;
		}
	}
	
	# Check start codon
	unless ( substr($translation, 0, 1) eq 'M')
	{
		print "$locus_tag: Protein sequence does not start with 'M'\n";
		#$errors++;
		# May be a truncated sequence at start or end of the chromosome, so allow this as long as the translation is OK
	}
	
	unless (isValidStartCodon( $codons[0], $translation_table ))
	{
		print "$locus_tag : Nucleotide sequence does not start with a valid start codon ($codons[0])\n";
		unless ( getTranslationForCodon( $codons[0], $translation_table ) eq substr($translation, 0, 1))
		{
			print "$locus_tag : Codon does not match the first amino acid in the given translation either\n";
			exit 1;
		}
	}
	
	# Check translation
	for ( my $i = 1; $i < scalar(@codons); $i++ )
	{
		my $translationChar = substr($translation, $i, 1);
		unless ( getTranslationForCodon( $codons[$i], $translation_table ) eq $translationChar )
		{
			print "$locus_tag, position $i : Codon $codons[$i] does not match the translation ( $translationChar )\n";
			$errors++;
		}
	}
	
	# Exit is there are errors
	if ($errors)
	{
		exit 1;
	}
}

sub isGC4site
{
	my $codon = $_[0];
	my $translation_table = $_[1];
	
	my $first_two_nucleotides = substr( $codon, 0, 2 );
	my @degenCodons = ( $first_two_nucleotides . 'A', $first_two_nucleotides . 'T', 
		$first_two_nucleotides . 'C', $first_two_nucleotides . 'G' );
	my %translations;

	foreach my $degenCodon (@degenCodons)
	{
		$translations{ getTranslationForCodon( $degenCodon, $translation_table ) } = 1;
	}
	
	if (scalar( keys %translations ) == 1)
	{
		return 1;
	} else {
		return 0;
	}
}

sub getTranslationForCodon
{
	my $codonString = $_[0];
	my $translation_table = $_[1];
	
	# Keyed by translation table and then by codon, stores translation
	my %codon_translations = (
		'1'		=>	{
			'TTT'	=>	'F', 'TTC'	=>	'F', 'TTA'	=>	'L', 'TTG'	=>	'L',
			'TCT'	=>	'S', 'TCC'	=>	'S', 'TCA'	=>	'S', 'TCG'	=>	'S',
			'TAT'	=>	'Y', 'TAC'	=>	'Y', 'TAA'	=>	'*', 'TAG'	=>	'*',
			'TGT'	=>	'C', 'TGC'	=>	'C', 'TGA'	=>	'*', 'TGG'	=>	'W',
			'CTT'	=>	'L', 'CTC'	=>	'L', 'CTA'	=>	'L', 'CTG'	=>	'L',
			'CCT'	=>	'P', 'CCC'	=>	'P', 'CCA'	=>	'P', 'CCG'	=>	'P',
			'CAT'	=>	'H', 'CAC'	=>	'H', 'CAA'	=>	'Q', 'CAG'	=>	'Q',
			'CGT'	=>	'R', 'CGC'	=>	'R', 'CGA'	=>	'R', 'CGG'	=>	'R',
			'ATT'	=>	'I', 'ATC'	=>	'I', 'ATA'	=>	'I', 'ATG'	=>	'M',
			'ACT'	=>	'T', 'ACC'	=>	'T', 'ACA'	=>	'T', 'ACG'	=>	'T',
			'AAT'	=>	'N', 'AAC'	=>	'N', 'AAA'	=>	'K', 'AAG'	=>	'K',
			'AGT'	=>	'S', 'AGC'	=>	'S', 'AGA'	=>	'R', 'AGG'	=>	'R',
			'GTT'	=>	'V', 'GTC'	=>	'V', 'GTA'	=>	'V', 'GTG'	=>	'V',
			'GCT'	=>	'A', 'GCC'	=>	'A', 'GCA'	=>	'A', 'GCG'	=>	'A',
			'GAT'	=>	'D', 'GAC'	=>	'D', 'GAA'	=>	'E', 'GAG'	=>	'E',
			'GGT'	=>	'G', 'GGC'	=>	'G', 'GGA'	=>	'G', 'GGG'	=>	'G',
		},
	
		'2'		=>	{
			'TTT'	=>	'F', 'TTC'	=>	'F', 'TTA'	=>	'L', 'TTG'	=>	'L',
			'TCT'	=>	'S', 'TCC'	=>	'S', 'TCA'	=>	'S', 'TCG'	=>	'S',
			'TAT'	=>	'Y', 'TAC'	=>	'Y', 'TAA'	=>	'*', 'TAG'	=>	'*',
			'TGT'	=>	'C', 'TGC'	=>	'C', 'TGA'	=>	'W', 'TGG'	=>	'W',
			'CTT'	=>	'L', 'CTC'	=>	'L', 'CTA'	=>	'L', 'CTG'	=>	'L',
			'CCT'	=>	'P', 'CCC'	=>	'P', 'CCA'	=>	'P', 'CCG'	=>	'P',
			'CAT'	=>	'H', 'CAC'	=>	'H', 'CAA'	=>	'Q', 'CAG'	=>	'Q',
			'CGT'	=>	'R', 'CGC'	=>	'R', 'CGA'	=>	'R', 'CGG'	=>	'R',
			'ATT'	=>	'I', 'ATC'	=>	'I', 'ATA'	=>	'M', 'ATG'	=>	'M',
			'ACT'	=>	'T', 'ACC'	=>	'T', 'ACA'	=>	'T', 'ACG'	=>	'T',
			'AAT'	=>	'N', 'AAC'	=>	'N', 'AAA'	=>	'K', 'AAG'	=>	'K',
			'AGT'	=>	'S', 'AGC'	=>	'S', 'AGA'	=>	'*', 'AGG'	=>	'*',
			'GTT'	=>	'V', 'GTC'	=>	'V', 'GTA'	=>	'V', 'GTG'	=>	'V',
			'GCT'	=>	'A', 'GCC'	=>	'A', 'GCA'	=>	'A', 'GCG'	=>	'A',
			'GAT'	=>	'D', 'GAC'	=>	'D', 'GAA'	=>	'E', 'GAG'	=>	'E',
			'GGT'	=>	'G', 'GGC'	=>	'G', 'GGA'	=>	'G', 'GGG'	=>	'G',
		},
		
		'3'		=>	{
			'TTT'	=>	'F', 'TTC'	=>	'F', 'TTA'	=>	'L', 'TTG'	=>	'L',
			'TCT'	=>	'S', 'TCC'	=>	'S', 'TCA'	=>	'S', 'TCG'	=>	'S',
			'TAT'	=>	'Y', 'TAC'	=>	'Y', 'TAA'	=>	'*', 'TAG'	=>	'*',
			'TGT'	=>	'C', 'TGC'	=>	'C', 'TGA'	=>	'W', 'TGG'	=>	'W',
			'CTT'	=>	'T', 'CTC'	=>	'T', 'CTA'	=>	'T', 'CTG'	=>	'T',
			'CCT'	=>	'P', 'CCC'	=>	'P', 'CCA'	=>	'P', 'CCG'	=>	'P',
			'CAT'	=>	'H', 'CAC'	=>	'H', 'CAA'	=>	'Q', 'CAG'	=>	'Q',
			'CGT'	=>	'R', 'CGC'	=>	'R', 'CGA'	=>	'R', 'CGG'	=>	'R',
			'ATT'	=>	'I', 'ATC'	=>	'I', 'ATA'	=>	'M', 'ATG'	=>	'M',
			'ACT'	=>	'T', 'ACC'	=>	'T', 'ACA'	=>	'T', 'ACG'	=>	'T',
			'AAT'	=>	'N', 'AAC'	=>	'N', 'AAA'	=>	'K', 'AAG'	=>	'K',
			'AGT'	=>	'S', 'AGC'	=>	'S', 'AGA'	=>	'R', 'AGG'	=>	'R',
			'GTT'	=>	'V', 'GTC'	=>	'V', 'GTA'	=>	'V', 'GTG'	=>	'V',
			'GCT'	=>	'A', 'GCC'	=>	'A', 'GCA'	=>	'A', 'GCG'	=>	'A',
			'GAT'	=>	'D', 'GAC'	=>	'D', 'GAA'	=>	'E', 'GAG'	=>	'E',
			'GGT'	=>	'G', 'GGC'	=>	'G', 'GGA'	=>	'G', 'GGG'	=>	'G',
		},
		
		'4'		=>	{
			'TTT'	=>	'F', 'TTC'	=>	'F', 'TTA'	=>	'L', 'TTG'	=>	'L',
			'TCT'	=>	'S', 'TCC'	=>	'S', 'TCA'	=>	'S', 'TCG'	=>	'S',
			'TAT'	=>	'Y', 'TAC'	=>	'Y', 'TAA'	=>	'*', 'TAG'	=>	'*',
			'TGT'	=>	'C', 'TGC'	=>	'C', 'TGA'	=>	'W', 'TGG'	=>	'W',
			'CTT'	=>	'L', 'CTC'	=>	'L', 'CTA'	=>	'L', 'CTG'	=>	'L',
			'CCT'	=>	'P', 'CCC'	=>	'P', 'CCA'	=>	'P', 'CCG'	=>	'P',
			'CAT'	=>	'H', 'CAC'	=>	'H', 'CAA'	=>	'Q', 'CAG'	=>	'Q',
			'CGT'	=>	'R', 'CGC'	=>	'R', 'CGA'	=>	'R', 'CGG'	=>	'R',
			'ATT'	=>	'I', 'ATC'	=>	'I', 'ATA'	=>	'I', 'ATG'	=>	'M',
			'ACT'	=>	'T', 'ACC'	=>	'T', 'ACA'	=>	'T', 'ACG'	=>	'T',
			'AAT'	=>	'N', 'AAC'	=>	'N', 'AAA'	=>	'K', 'AAG'	=>	'K',
			'AGT'	=>	'S', 'AGC'	=>	'S', 'AGA'	=>	'R', 'AGG'	=>	'R',
			'GTT'	=>	'V', 'GTC'	=>	'V', 'GTA'	=>	'V', 'GTG'	=>	'V',
			'GCT'	=>	'A', 'GCC'	=>	'A', 'GCA'	=>	'A', 'GCG'	=>	'A',
			'GAT'	=>	'D', 'GAC'	=>	'D', 'GAA'	=>	'E', 'GAG'	=>	'E',
			'GGT'	=>	'G', 'GGC'	=>	'G', 'GGA'	=>	'G', 'GGG'	=>	'G',
		},
		
		'5'		=>	{
			'TTT'	=>	'F', 'TTC'	=>	'F', 'TTA'	=>	'L', 'TTG'	=>	'L',
			'TCT'	=>	'S', 'TCC'	=>	'S', 'TCA'	=>	'S', 'TCG'	=>	'S',
			'TAT'	=>	'Y', 'TAC'	=>	'Y', 'TAA'	=>	'*', 'TAG'	=>	'*',
			'TGT'	=>	'C', 'TGC'	=>	'C', 'TGA'	=>	'W', 'TGG'	=>	'W',
			'CTT'	=>	'L', 'CTC'	=>	'L', 'CTA'	=>	'L', 'CTG'	=>	'L',
			'CCT'	=>	'P', 'CCC'	=>	'P', 'CCA'	=>	'P', 'CCG'	=>	'P',
			'CAT'	=>	'H', 'CAC'	=>	'H', 'CAA'	=>	'Q', 'CAG'	=>	'Q',
			'CGT'	=>	'R', 'CGC'	=>	'R', 'CGA'	=>	'R', 'CGG'	=>	'R',
			'ATT'	=>	'I', 'ATC'	=>	'I', 'ATA'	=>	'M', 'ATG'	=>	'M',
			'ACT'	=>	'T', 'ACC'	=>	'T', 'ACA'	=>	'T', 'ACG'	=>	'T',
			'AAT'	=>	'N', 'AAC'	=>	'N', 'AAA'	=>	'K', 'AAG'	=>	'K',
			'AGT'	=>	'S', 'AGC'	=>	'S', 'AGA'	=>	'S', 'AGG'	=>	'S',
			'GTT'	=>	'V', 'GTC'	=>	'V', 'GTA'	=>	'V', 'GTG'	=>	'V',
			'GCT'	=>	'A', 'GCC'	=>	'A', 'GCA'	=>	'A', 'GCG'	=>	'A',
			'GAT'	=>	'D', 'GAC'	=>	'D', 'GAA'	=>	'E', 'GAG'	=>	'E',
			'GGT'	=>	'G', 'GGC'	=>	'G', 'GGA'	=>	'G', 'GGG'	=>	'G',
		},
		
		'6'		=>	{
			'TTT'	=>	'F', 'TTC'	=>	'F', 'TTA'	=>	'L', 'TTG'	=>	'L',
			'TCT'	=>	'S', 'TCC'	=>	'S', 'TCA'	=>	'S', 'TCG'	=>	'S',
			'TAT'	=>	'Y', 'TAC'	=>	'Y', 'TAA'	=>	'Q', 'TAG'	=>	'Q',
			'TGT'	=>	'C', 'TGC'	=>	'C', 'TGA'	=>	'*', 'TGG'	=>	'W',
			'CTT'	=>	'L', 'CTC'	=>	'L', 'CTA'	=>	'L', 'CTG'	=>	'L',
			'CCT'	=>	'P', 'CCC'	=>	'P', 'CCA'	=>	'P', 'CCG'	=>	'P',
			'CAT'	=>	'H', 'CAC'	=>	'H', 'CAA'	=>	'Q', 'CAG'	=>	'Q',
			'CGT'	=>	'R', 'CGC'	=>	'R', 'CGA'	=>	'R', 'CGG'	=>	'R',
			'ATT'	=>	'I', 'ATC'	=>	'I', 'ATA'	=>	'I', 'ATG'	=>	'M',
			'ACT'	=>	'T', 'ACC'	=>	'T', 'ACA'	=>	'T', 'ACG'	=>	'T',
			'AAT'	=>	'N', 'AAC'	=>	'N', 'AAA'	=>	'K', 'AAG'	=>	'K',
			'AGT'	=>	'S', 'AGC'	=>	'S', 'AGA'	=>	'R', 'AGG'	=>	'R',
			'GTT'	=>	'V', 'GTC'	=>	'V', 'GTA'	=>	'V', 'GTG'	=>	'V',
			'GCT'	=>	'A', 'GCC'	=>	'A', 'GCA'	=>	'A', 'GCG'	=>	'A',
			'GAT'	=>	'D', 'GAC'	=>	'D', 'GAA'	=>	'E', 'GAG'	=>	'E',
			'GGT'	=>	'G', 'GGC'	=>	'G', 'GGA'	=>	'G', 'GGG'	=>	'G',
		},
		
		'9'		=>	{
			'TTT'	=>	'F', 'TTC'	=>	'F', 'TTA'	=>	'L', 'TTG'	=>	'L',
			'TCT'	=>	'S', 'TCC'	=>	'S', 'TCA'	=>	'S', 'TCG'	=>	'S',
			'TAT'	=>	'Y', 'TAC'	=>	'Y', 'TAA'	=>	'*', 'TAG'	=>	'*',
			'TGT'	=>	'C', 'TGC'	=>	'C', 'TGA'	=>	'W', 'TGG'	=>	'W',
			'CTT'	=>	'L', 'CTC'	=>	'L', 'CTA'	=>	'L', 'CTG'	=>	'L',
			'CCT'	=>	'P', 'CCC'	=>	'P', 'CCA'	=>	'P', 'CCG'	=>	'P',
			'CAT'	=>	'H', 'CAC'	=>	'H', 'CAA'	=>	'Q', 'CAG'	=>	'Q',
			'CGT'	=>	'R', 'CGC'	=>	'R', 'CGA'	=>	'R', 'CGG'	=>	'R',
			'ATT'	=>	'I', 'ATC'	=>	'I', 'ATA'	=>	'I', 'ATG'	=>	'M',
			'ACT'	=>	'T', 'ACC'	=>	'T', 'ACA'	=>	'T', 'ACG'	=>	'T',
			'AAT'	=>	'N', 'AAC'	=>	'N', 'AAA'	=>	'N', 'AAG'	=>	'K',
			'AGT'	=>	'S', 'AGC'	=>	'S', 'AGA'	=>	'S', 'AGG'	=>	'S',
			'GTT'	=>	'V', 'GTC'	=>	'V', 'GTA'	=>	'V', 'GTG'	=>	'V',
			'GCT'	=>	'A', 'GCC'	=>	'A', 'GCA'	=>	'A', 'GCG'	=>	'A',
			'GAT'	=>	'D', 'GAC'	=>	'D', 'GAA'	=>	'E', 'GAG'	=>	'E',
			'GGT'	=>	'G', 'GGC'	=>	'G', 'GGA'	=>	'G', 'GGG'	=>	'G',
		},
		
		'10'	=>	{
			'TTT'	=>	'F', 'TTC'	=>	'F', 'TTA'	=>	'L', 'TTG'	=>	'L',
			'TCT'	=>	'S', 'TCC'	=>	'S', 'TCA'	=>	'S', 'TCG'	=>	'S',
			'TAT'	=>	'Y', 'TAC'	=>	'Y', 'TAA'	=>	'*', 'TAG'	=>	'*',
			'TGT'	=>	'C', 'TGC'	=>	'C', 'TGA'	=>	'C', 'TGG'	=>	'W',
			'CTT'	=>	'L', 'CTC'	=>	'L', 'CTA'	=>	'L', 'CTG'	=>	'L',
			'CCT'	=>	'P', 'CCC'	=>	'P', 'CCA'	=>	'P', 'CCG'	=>	'P',
			'CAT'	=>	'H', 'CAC'	=>	'H', 'CAA'	=>	'Q', 'CAG'	=>	'Q',
			'CGT'	=>	'R', 'CGC'	=>	'R', 'CGA'	=>	'R', 'CGG'	=>	'R',
			'ATT'	=>	'I', 'ATC'	=>	'I', 'ATA'	=>	'I', 'ATG'	=>	'M',
			'ACT'	=>	'T', 'ACC'	=>	'T', 'ACA'	=>	'T', 'ACG'	=>	'T',
			'AAT'	=>	'N', 'AAC'	=>	'N', 'AAA'	=>	'K', 'AAG'	=>	'K',
			'AGT'	=>	'S', 'AGC'	=>	'S', 'AGA'	=>	'R', 'AGG'	=>	'R',
			'GTT'	=>	'V', 'GTC'	=>	'V', 'GTA'	=>	'V', 'GTG'	=>	'V',
			'GCT'	=>	'A', 'GCC'	=>	'A', 'GCA'	=>	'A', 'GCG'	=>	'A',
			'GAT'	=>	'D', 'GAC'	=>	'D', 'GAA'	=>	'E', 'GAG'	=>	'E',
			'GGT'	=>	'G', 'GGC'	=>	'G', 'GGA'	=>	'G', 'GGG'	=>	'G',
		},

		'11'	=>	{
			'TTT'	=>	'F', 'TTC'	=>	'F', 'TTA'	=>	'L', 'TTG'	=>	'L',
			'TCT'	=>	'S', 'TCC'	=>	'S', 'TCA'	=>	'S', 'TCG'	=>	'S',
			'TAT'	=>	'Y', 'TAC'	=>	'Y', 'TAA'	=>	'*', 'TAG'	=>	'*',
			'TGT'	=>	'C', 'TGC'	=>	'C', 'TGA'	=>	'*', 'TGG'	=>	'W',
			'CTT'	=>	'L', 'CTC'	=>	'L', 'CTA'	=>	'L', 'CTG'	=>	'L',
			'CCT'	=>	'P', 'CCC'	=>	'P', 'CCA'	=>	'P', 'CCG'	=>	'P',
			'CAT'	=>	'H', 'CAC'	=>	'H', 'CAA'	=>	'Q', 'CAG'	=>	'Q',
			'CGT'	=>	'R', 'CGC'	=>	'R', 'CGA'	=>	'R', 'CGG'	=>	'R',
			'ATT'	=>	'I', 'ATC'	=>	'I', 'ATA'	=>	'I', 'ATG'	=>	'M',
			'ACT'	=>	'T', 'ACC'	=>	'T', 'ACA'	=>	'T', 'ACG'	=>	'T',
			'AAT'	=>	'N', 'AAC'	=>	'N', 'AAA'	=>	'K', 'AAG'	=>	'K',
			'AGT'	=>	'S', 'AGC'	=>	'S', 'AGA'	=>	'R', 'AGG'	=>	'R',
			'GTT'	=>	'V', 'GTC'	=>	'V', 'GTA'	=>	'V', 'GTG'	=>	'V',
			'GCT'	=>	'A', 'GCC'	=>	'A', 'GCA'	=>	'A', 'GCG'	=>	'A',
			'GAT'	=>	'D', 'GAC'	=>	'D', 'GAA'	=>	'E', 'GAG'	=>	'E',
			'GGT'	=>	'G', 'GGC'	=>	'G', 'GGA'	=>	'G', 'GGG'	=>	'G',
		},
		
		'12'	=>	{
			'TTT'	=>	'F', 'TTC'	=>	'F', 'TTA'	=>	'L', 'TTG'	=>	'L',
			'TCT'	=>	'S', 'TCC'	=>	'S', 'TCA'	=>	'S', 'TCG'	=>	'S',
			'TAT'	=>	'Y', 'TAC'	=>	'Y', 'TAA'	=>	'*', 'TAG'	=>	'*',
			'TGT'	=>	'C', 'TGC'	=>	'C', 'TGA'	=>	'*', 'TGG'	=>	'W',
			'CTT'	=>	'L', 'CTC'	=>	'L', 'CTA'	=>	'L', 'CTG'	=>	'S',
			'CCT'	=>	'P', 'CCC'	=>	'P', 'CCA'	=>	'P', 'CCG'	=>	'P',
			'CAT'	=>	'H', 'CAC'	=>	'H', 'CAA'	=>	'Q', 'CAG'	=>	'Q',
			'CGT'	=>	'R', 'CGC'	=>	'R', 'CGA'	=>	'R', 'CGG'	=>	'R',
			'ATT'	=>	'I', 'ATC'	=>	'I', 'ATA'	=>	'I', 'ATG'	=>	'M',
			'ACT'	=>	'T', 'ACC'	=>	'T', 'ACA'	=>	'T', 'ACG'	=>	'T',
			'AAT'	=>	'N', 'AAC'	=>	'N', 'AAA'	=>	'K', 'AAG'	=>	'K',
			'AGT'	=>	'S', 'AGC'	=>	'S', 'AGA'	=>	'R', 'AGG'	=>	'R',
			'GTT'	=>	'V', 'GTC'	=>	'V', 'GTA'	=>	'V', 'GTG'	=>	'V',
			'GCT'	=>	'A', 'GCC'	=>	'A', 'GCA'	=>	'A', 'GCG'	=>	'A',
			'GAT'	=>	'D', 'GAC'	=>	'D', 'GAA'	=>	'E', 'GAG'	=>	'E',
			'GGT'	=>	'G', 'GGC'	=>	'G', 'GGA'	=>	'G', 'GGG'	=>	'G',
		},
		
		'13'	=>	{
			'TTT'	=>	'F', 'TTC'	=>	'F', 'TTA'	=>	'L', 'TTG'	=>	'L',
			'TCT'	=>	'S', 'TCC'	=>	'S', 'TCA'	=>	'S', 'TCG'	=>	'S',
			'TAT'	=>	'Y', 'TAC'	=>	'Y', 'TAA'	=>	'*', 'TAG'	=>	'*',
			'TGT'	=>	'C', 'TGC'	=>	'C', 'TGA'	=>	'W', 'TGG'	=>	'W',
			'CTT'	=>	'L', 'CTC'	=>	'L', 'CTA'	=>	'L', 'CTG'	=>	'L',
			'CCT'	=>	'P', 'CCC'	=>	'P', 'CCA'	=>	'P', 'CCG'	=>	'P',
			'CAT'	=>	'H', 'CAC'	=>	'H', 'CAA'	=>	'Q', 'CAG'	=>	'Q',
			'CGT'	=>	'R', 'CGC'	=>	'R', 'CGA'	=>	'R', 'CGG'	=>	'R',
			'ATT'	=>	'I', 'ATC'	=>	'I', 'ATA'	=>	'M', 'ATG'	=>	'M',
			'ACT'	=>	'T', 'ACC'	=>	'T', 'ACA'	=>	'T', 'ACG'	=>	'T',
			'AAT'	=>	'N', 'AAC'	=>	'N', 'AAA'	=>	'K', 'AAG'	=>	'K',
			'AGT'	=>	'S', 'AGC'	=>	'S', 'AGA'	=>	'G', 'AGG'	=>	'G',
			'GTT'	=>	'V', 'GTC'	=>	'V', 'GTA'	=>	'V', 'GTG'	=>	'V',
			'GCT'	=>	'A', 'GCC'	=>	'A', 'GCA'	=>	'A', 'GCG'	=>	'A',
			'GAT'	=>	'D', 'GAC'	=>	'D', 'GAA'	=>	'E', 'GAG'	=>	'E',
			'GGT'	=>	'G', 'GGC'	=>	'G', 'GGA'	=>	'G', 'GGG'	=>	'G',
		},
		
		'14'	=>	{
			'TTT'	=>	'F', 'TTC'	=>	'F', 'TTA'	=>	'L', 'TTG'	=>	'L',
			'TCT'	=>	'S', 'TCC'	=>	'S', 'TCA'	=>	'S', 'TCG'	=>	'S',
			'TAT'	=>	'Y', 'TAC'	=>	'Y', 'TAA'	=>	'Y', 'TAG'	=>	'*',
			'TGT'	=>	'C', 'TGC'	=>	'C', 'TGA'	=>	'W', 'TGG'	=>	'W',
			'CTT'	=>	'L', 'CTC'	=>	'L', 'CTA'	=>	'L', 'CTG'	=>	'L',
			'CCT'	=>	'P', 'CCC'	=>	'P', 'CCA'	=>	'P', 'CCG'	=>	'P',
			'CAT'	=>	'H', 'CAC'	=>	'H', 'CAA'	=>	'Q', 'CAG'	=>	'Q',
			'CGT'	=>	'R', 'CGC'	=>	'R', 'CGA'	=>	'R', 'CGG'	=>	'R',
			'ATT'	=>	'I', 'ATC'	=>	'I', 'ATA'	=>	'I', 'ATG'	=>	'M',
			'ACT'	=>	'T', 'ACC'	=>	'T', 'ACA'	=>	'T', 'ACG'	=>	'T',
			'AAT'	=>	'N', 'AAC'	=>	'N', 'AAA'	=>	'N', 'AAG'	=>	'K',
			'AGT'	=>	'S', 'AGC'	=>	'S', 'AGA'	=>	'R', 'AGG'	=>	'R',
			'GTT'	=>	'V', 'GTC'	=>	'V', 'GTA'	=>	'V', 'GTG'	=>	'V',
			'GCT'	=>	'A', 'GCC'	=>	'A', 'GCA'	=>	'A', 'GCG'	=>	'A',
			'GAT'	=>	'D', 'GAC'	=>	'D', 'GAA'	=>	'E', 'GAG'	=>	'E',
			'GGT'	=>	'G', 'GGC'	=>	'G', 'GGA'	=>	'G', 'GGG'	=>	'G',
		},
		
		'15'	=>	{
			'TTT'	=>	'F', 'TTC'	=>	'F', 'TTA'	=>	'L', 'TTG'	=>	'L',
			'TCT'	=>	'S', 'TCC'	=>	'S', 'TCA'	=>	'S', 'TCG'	=>	'S',
			'TAT'	=>	'Y', 'TAC'	=>	'Y', 'TAA'	=>	'*', 'TAG'	=>	'Q',
			'TGT'	=>	'C', 'TGC'	=>	'C', 'TGA'	=>	'*', 'TGG'	=>	'W',
			'CTT'	=>	'L', 'CTC'	=>	'L', 'CTA'	=>	'L', 'CTG'	=>	'L',
			'CCT'	=>	'P', 'CCC'	=>	'P', 'CCA'	=>	'P', 'CCG'	=>	'P',
			'CAT'	=>	'H', 'CAC'	=>	'H', 'CAA'	=>	'Q', 'CAG'	=>	'Q',
			'CGT'	=>	'R', 'CGC'	=>	'R', 'CGA'	=>	'R', 'CGG'	=>	'R',
			'ATT'	=>	'I', 'ATC'	=>	'I', 'ATA'	=>	'I', 'ATG'	=>	'M',
			'ACT'	=>	'T', 'ACC'	=>	'T', 'ACA'	=>	'T', 'ACG'	=>	'T',
			'AAT'	=>	'N', 'AAC'	=>	'N', 'AAA'	=>	'K', 'AAG'	=>	'K',
			'AGT'	=>	'S', 'AGC'	=>	'S', 'AGA'	=>	'R', 'AGG'	=>	'R',
			'GTT'	=>	'V', 'GTC'	=>	'V', 'GTA'	=>	'V', 'GTG'	=>	'V',
			'GCT'	=>	'A', 'GCC'	=>	'A', 'GCA'	=>	'A', 'GCG'	=>	'A',
			'GAT'	=>	'D', 'GAC'	=>	'D', 'GAA'	=>	'E', 'GAG'	=>	'E',
			'GGT'	=>	'G', 'GGC'	=>	'G', 'GGA'	=>	'G', 'GGG'	=>	'G',
		},
		
		'16'	=>	{
			'TTT'	=>	'F', 'TTC'	=>	'F', 'TTA'	=>	'L', 'TTG'	=>	'L',
			'TCT'	=>	'S', 'TCC'	=>	'S', 'TCA'	=>	'S', 'TCG'	=>	'S',
			'TAT'	=>	'Y', 'TAC'	=>	'Y', 'TAA'	=>	'*', 'TAG'	=>	'L',
			'TGT'	=>	'C', 'TGC'	=>	'C', 'TGA'	=>	'*', 'TGG'	=>	'W',
			'CTT'	=>	'L', 'CTC'	=>	'L', 'CTA'	=>	'L', 'CTG'	=>	'L',
			'CCT'	=>	'P', 'CCC'	=>	'P', 'CCA'	=>	'P', 'CCG'	=>	'P',
			'CAT'	=>	'H', 'CAC'	=>	'H', 'CAA'	=>	'Q', 'CAG'	=>	'Q',
			'CGT'	=>	'R', 'CGC'	=>	'R', 'CGA'	=>	'R', 'CGG'	=>	'R',
			'ATT'	=>	'I', 'ATC'	=>	'I', 'ATA'	=>	'I', 'ATG'	=>	'M',
			'ACT'	=>	'T', 'ACC'	=>	'T', 'ACA'	=>	'T', 'ACG'	=>	'T',
			'AAT'	=>	'N', 'AAC'	=>	'N', 'AAA'	=>	'K', 'AAG'	=>	'K',
			'AGT'	=>	'S', 'AGC'	=>	'S', 'AGA'	=>	'R', 'AGG'	=>	'R',
			'GTT'	=>	'V', 'GTC'	=>	'V', 'GTA'	=>	'V', 'GTG'	=>	'V',
			'GCT'	=>	'A', 'GCC'	=>	'A', 'GCA'	=>	'A', 'GCG'	=>	'A',
			'GAT'	=>	'D', 'GAC'	=>	'D', 'GAA'	=>	'E', 'GAG'	=>	'E',
			'GGT'	=>	'G', 'GGC'	=>	'G', 'GGA'	=>	'G', 'GGG'	=>	'G',
		},
		
		'21'	=>	{
			'TTT'	=>	'F', 'TTC'	=>	'F', 'TTA'	=>	'L', 'TTG'	=>	'L',
			'TCT'	=>	'S', 'TCC'	=>	'S', 'TCA'	=>	'S', 'TCG'	=>	'S',
			'TAT'	=>	'Y', 'TAC'	=>	'Y', 'TAA'	=>	'*', 'TAG'	=>	'*',
			'TGT'	=>	'C', 'TGC'	=>	'C', 'TGA'	=>	'W', 'TGG'	=>	'W',
			'CTT'	=>	'L', 'CTC'	=>	'L', 'CTA'	=>	'L', 'CTG'	=>	'L',
			'CCT'	=>	'P', 'CCC'	=>	'P', 'CCA'	=>	'P', 'CCG'	=>	'P',
			'CAT'	=>	'H', 'CAC'	=>	'H', 'CAA'	=>	'Q', 'CAG'	=>	'Q',
			'CGT'	=>	'R', 'CGC'	=>	'R', 'CGA'	=>	'R', 'CGG'	=>	'R',
			'ATT'	=>	'I', 'ATC'	=>	'I', 'ATA'	=>	'M', 'ATG'	=>	'M',
			'ACT'	=>	'T', 'ACC'	=>	'T', 'ACA'	=>	'T', 'ACG'	=>	'T',
			'AAT'	=>	'N', 'AAC'	=>	'N', 'AAA'	=>	'N', 'AAG'	=>	'K',
			'AGT'	=>	'S', 'AGC'	=>	'S', 'AGA'	=>	'S', 'AGG'	=>	'S',
			'GTT'	=>	'V', 'GTC'	=>	'V', 'GTA'	=>	'V', 'GTG'	=>	'V',
			'GCT'	=>	'A', 'GCC'	=>	'A', 'GCA'	=>	'A', 'GCG'	=>	'A',
			'GAT'	=>	'D', 'GAC'	=>	'D', 'GAA'	=>	'E', 'GAG'	=>	'E',
			'GGT'	=>	'G', 'GGC'	=>	'G', 'GGA'	=>	'G', 'GGG'	=>	'G',
		},
		
		'22'	=>	{
			'TTT'	=>	'F', 'TTC'	=>	'F', 'TTA'	=>	'L', 'TTG'	=>	'L',
			'TCT'	=>	'S', 'TCC'	=>	'S', 'TCA'	=>	'*', 'TCG'	=>	'S',
			'TAT'	=>	'Y', 'TAC'	=>	'Y', 'TAA'	=>	'*', 'TAG'	=>	'L',
			'TGT'	=>	'C', 'TGC'	=>	'C', 'TGA'	=>	'*', 'TGG'	=>	'W',
			'CTT'	=>	'L', 'CTC'	=>	'L', 'CTA'	=>	'L', 'CTG'	=>	'L',
			'CCT'	=>	'P', 'CCC'	=>	'P', 'CCA'	=>	'P', 'CCG'	=>	'P',
			'CAT'	=>	'H', 'CAC'	=>	'H', 'CAA'	=>	'Q', 'CAG'	=>	'Q',
			'CGT'	=>	'R', 'CGC'	=>	'R', 'CGA'	=>	'R', 'CGG'	=>	'R',
			'ATT'	=>	'I', 'ATC'	=>	'I', 'ATA'	=>	'I', 'ATG'	=>	'M',
			'ACT'	=>	'T', 'ACC'	=>	'T', 'ACA'	=>	'T', 'ACG'	=>	'T',
			'AAT'	=>	'N', 'AAC'	=>	'N', 'AAA'	=>	'K', 'AAG'	=>	'K',
			'AGT'	=>	'S', 'AGC'	=>	'S', 'AGA'	=>	'R', 'AGG'	=>	'R',
			'GTT'	=>	'V', 'GTC'	=>	'V', 'GTA'	=>	'V', 'GTG'	=>	'V',
			'GCT'	=>	'A', 'GCC'	=>	'A', 'GCA'	=>	'A', 'GCG'	=>	'A',
			'GAT'	=>	'D', 'GAC'	=>	'D', 'GAA'	=>	'E', 'GAG'	=>	'E',
			'GGT'	=>	'G', 'GGC'	=>	'G', 'GGA'	=>	'G', 'GGG'	=>	'G',
		},
		
		'23'	=>	{
			'TTT'	=>	'F', 'TTC'	=>	'F', 'TTA'	=>	'*', 'TTG'	=>	'L',
			'TCT'	=>	'S', 'TCC'	=>	'S', 'TCA'	=>	'S', 'TCG'	=>	'S',
			'TAT'	=>	'Y', 'TAC'	=>	'Y', 'TAA'	=>	'*', 'TAG'	=>	'*',
			'TGT'	=>	'C', 'TGC'	=>	'C', 'TGA'	=>	'*', 'TGG'	=>	'W',
			'CTT'	=>	'L', 'CTC'	=>	'L', 'CTA'	=>	'L', 'CTG'	=>	'L',
			'CCT'	=>	'P', 'CCC'	=>	'P', 'CCA'	=>	'P', 'CCG'	=>	'P',
			'CAT'	=>	'H', 'CAC'	=>	'H', 'CAA'	=>	'Q', 'CAG'	=>	'Q',
			'CGT'	=>	'R', 'CGC'	=>	'R', 'CGA'	=>	'R', 'CGG'	=>	'R',
			'ATT'	=>	'I', 'ATC'	=>	'I', 'ATA'	=>	'I', 'ATG'	=>	'M',
			'ACT'	=>	'T', 'ACC'	=>	'T', 'ACA'	=>	'T', 'ACG'	=>	'T',
			'AAT'	=>	'N', 'AAC'	=>	'N', 'AAA'	=>	'K', 'AAG'	=>	'K',
			'AGT'	=>	'S', 'AGC'	=>	'S', 'AGA'	=>	'R', 'AGG'	=>	'R',
			'GTT'	=>	'V', 'GTC'	=>	'V', 'GTA'	=>	'V', 'GTG'	=>	'V',
			'GCT'	=>	'A', 'GCC'	=>	'A', 'GCA'	=>	'A', 'GCG'	=>	'A',
			'GAT'	=>	'D', 'GAC'	=>	'D', 'GAA'	=>	'E', 'GAG'	=>	'E',
			'GGT'	=>	'G', 'GGC'	=>	'G', 'GGA'	=>	'G', 'GGG'	=>	'G',
		},
		
		'24'	=>	{
			'TTT'	=>	'F', 'TTC'	=>	'F', 'TTA'	=>	'L', 'TTG'	=>	'L',
			'TCT'	=>	'S', 'TCC'	=>	'S', 'TCA'	=>	'S', 'TCG'	=>	'S',
			'TAT'	=>	'Y', 'TAC'	=>	'Y', 'TAA'	=>	'*', 'TAG'	=>	'*',
			'TGT'	=>	'C', 'TGC'	=>	'C', 'TGA'	=>	'W', 'TGG'	=>	'W',
			'CTT'	=>	'L', 'CTC'	=>	'L', 'CTA'	=>	'L', 'CTG'	=>	'L',
			'CCT'	=>	'P', 'CCC'	=>	'P', 'CCA'	=>	'P', 'CCG'	=>	'P',
			'CAT'	=>	'H', 'CAC'	=>	'H', 'CAA'	=>	'Q', 'CAG'	=>	'Q',
			'CGT'	=>	'R', 'CGC'	=>	'R', 'CGA'	=>	'R', 'CGG'	=>	'R',
			'ATT'	=>	'I', 'ATC'	=>	'I', 'ATA'	=>	'I', 'ATG'	=>	'M',
			'ACT'	=>	'T', 'ACC'	=>	'T', 'ACA'	=>	'T', 'ACG'	=>	'T',
			'AAT'	=>	'N', 'AAC'	=>	'N', 'AAA'	=>	'K', 'AAG'	=>	'K',
			'AGT'	=>	'S', 'AGC'	=>	'S', 'AGA'	=>	'S', 'AGG'	=>	'K',
			'GTT'	=>	'V', 'GTC'	=>	'V', 'GTA'	=>	'V', 'GTG'	=>	'V',
			'GCT'	=>	'A', 'GCC'	=>	'A', 'GCA'	=>	'A', 'GCG'	=>	'A',
			'GAT'	=>	'D', 'GAC'	=>	'D', 'GAA'	=>	'E', 'GAG'	=>	'E',
			'GGT'	=>	'G', 'GGC'	=>	'G', 'GGA'	=>	'G', 'GGG'	=>	'G',
		}
	);
	
	if (defined $codon_translations{ $translation_table }{ $codonString })
	{
		return $codon_translations{ $translation_table }{ $codonString };
	} else {
		# Handle degenerate codons
		my @possibleCodons = getPossibleCodonsForDegenerate( $codonString );
		my %translationHash;
		foreach my $codon (@possibleCodons)
		{
			$translationHash{ $codon_translations{ $translation_table }{ $codon } } = 1;
		}
		#print Dumper ( \%translationHash );
		
		if (scalar( keys %translationHash ) == 1)
		{
			return $codon_translations{ $translation_table }{ $possibleCodons[0] };
		} else {
			return 'X';
		}
	}
}

sub isValidStartCodon
{
	my $codon = $_[0];
	my $translation_table = $_[1];
	
	my %valid_start_codons = (
		'1'		=>	{
			'TTG'	=>	'M',
			'CTG'	=>	'M',
			'ATG'	=>	'M'
		},
		
		'2'		=>	{
			'ATT'	=>	'M',
			'ATC'	=>	'M',
			'ATA'	=>	'M',
			'ATG'	=>	'M',
			'GTG'	=>	'M'
		},
		
		'3'		=>	{
			'ATA'	=>	'M',
			'ATG'	=>	'M'
		},
		
		'4'		=>	{
			'TTA'	=>	'M',
			'TTG'	=>	'M',
			'CTG'	=>	'M',
			'ATT'	=>	'M',
			'ATC'	=>	'M',
			'ATA'	=>	'M',
			'ATG'	=>	'M',
			'GTG'	=>	'M'
		},
		
		'5'		=>	{
			'TTG'	=>	'M',
			'ATT'	=>	'M',
			'ATC'	=>	'M',
			'ATA'	=>	'M',
			'ATG'	=>	'M',
			'GTG'	=>	'M'
		},
		
		'6'		=>	{
			'ATG'	=>	'M'
		},
		
		'9'		=>	{
			'ATG'	=>	'M',
			'GTG'	=>	'M'
		},
		
		'10'	=>	{
			'ATG'	=>	'M'
		},
		
		'11'	=>	{
			'TTG'	=>	'M',
			'CTG'	=>	'M',
			'ATT'	=>	'M',
			'ATC'	=>	'M',
			'ATA'	=>	'M',
			'ATG'	=>	'M',
			'GTG'	=>	'M'
		},
		
		'12'	=>	{
			'CTG'	=>	'M',
			'ATG'	=>	'M'
		},
		
		'13'	=>	{
			'TTG'	=>	'M',
			'ATA'	=>	'M',
			'ATG'	=>	'M',
			'GTG'	=>	'M'
		},
		
		'14'	=>	{
			'ATG'	=>	'M'
		},
		
		'15'	=>	{
			'ATG'	=>	'M'
		},
		
		'16'	=>	{
			'ATG'	=>	'M'
		},
		
		'21'	=>	{
			'ATG'	=>	'M',
			'GTG'	=>	'M'
		},
		
		'22'	=>	{
			'ATG'	=>	'M'
		},
		
		'23'	=>	{
			'ATT'	=>	'M',
			'ATG'	=>	'M',
			'GTG'	=>	'M'
		},
		
		'24'	=>	{
			'TTG'	=>	'M',
			'CTG'	=>	'M',
			'ATG'	=>	'M',
			'GTG'	=>	'M'
		}
	);
	
	if (defined $valid_start_codons{ $translation_table }{ $codon })
	{
		return 1;
	} else {
		return 0;
	}
}

sub getPossibleCodonsForDegenerate
{
	my $degenerateCodon = $_[0];
	my @possibleCodons;
	
	my @degeneratePositions;
	# Work out which positions are degenerate
	for ( my $i = 0; $i < 3; $i++ )
	{
		my $nucleotide = substr($degenerateCodon, $i, 1);
		unless ( ($nucleotide eq 'A') || ($nucleotide eq 'T') || ($nucleotide eq 'G') || ($nucleotide eq 'C') )
		{
			push (@degeneratePositions, $i);
		}
	}
	
	@possibleCodons = ( $degenerateCodon );
	foreach my $position (@degeneratePositions)
	{
		my @replacementArray;
		foreach my $codon ( @possibleCodons )
		{
			my $nucleotide = substr( $codon, $position, 1 );
			my @nucleotides = getNucleotidesForDegenerateCode ( $nucleotide );
			foreach my $nucleotideSubstitution (@nucleotides)
			{
				my $newCodon = $codon;
				substr($newCodon, $position, 1, $nucleotideSubstitution);
				push (@replacementArray, $newCodon);
			}
		}
		@possibleCodons = @replacementArray;
	}
	
	return @possibleCodons;
}

sub getNucleotidesForDegenerateCode
{
	my $nucleotide = $_[0];
	
	my %degenerate_codes = (
		'A'		=>		[ 'A' ],
		'T'		=>		[ 'T' ],
		'G'		=>		[ 'G' ],
		'C'		=>		[ 'C' ],
		'W'		=>		[ 'A', 'T' ],
		'S'		=>		[ 'C', 'G' ],
		'M'		=>		[ 'A', 'C' ],
		'K'		=>		[ 'G', 'T' ],
		'R'		=>		[ 'A', 'G' ],
		'Y'		=>		[ 'C', 'T' ],
		'B'		=>		[ 'C', 'G', 'T' ],
		'D'		=>		[ 'A', 'G', 'T' ],
		'H'		=>		[ 'A', 'C', 'T' ],
		'V'		=>		[ 'A', 'C', 'G' ],
		'N'		=>		[ 'A', 'T', 'G', 'C' ],
	);
	print "getNucleotidesForDegenerateCode: Nucleotide: $nucleotide\n";
	my @possiblenucleotides = @{ $degenerate_codes{ $nucleotide } };
	return @possiblenucleotides;
}
	
	

# Subroutine that gets the nucleotide seq, taking into account ribosomal slippage
sub getNucleotideSeq
{
	my $featureHashRef = $_[0];
	my $genomeRef = $_[1];
	my $contiguous_sequence = '';
	
	# Grab each piece and add to contiguous sequence
	my @startCoords = @{ $featureHashRef->{ 'startCoords' } };
	my @endCoords = @{ $featureHashRef->{ 'endCoords' } };
	
	if ( $featureHashRef->{ 'direction' } eq 'forward' )
	{
		for ( my $i = 0; $i < scalar(@startCoords); $i++ )
		{
			my $startCoord = $startCoords[$i];
			my $endCoord = $endCoords[$i];
			my $startIndex = $startCoord - 1;
			my $length = $endCoord - $startIndex;

			$contiguous_sequence = $contiguous_sequence . substr($$genomeRef, $startIndex, $length);
		}
	} else {
		for ( my $i = (scalar(@startCoords) - 1); $i >= 0; $i-- )
		{
			my $startCoord = $startCoords[$i];
			my $endCoord = $endCoords[$i];
			my $startIndex = $startCoord - 1;
			my $length = $endCoord - $startIndex;
			
			$contiguous_sequence = $contiguous_sequence . reverseComp( substr($$genomeRef, $startIndex, $length) );
		}
	}
	
	return $contiguous_sequence;
}