 {
	my $usage = "kmers.pl\n
	PURPOSE:            A naive kmer-counting wrapper that outputs TAB files of kmers and their binding sites in a series of genomes.
                        \n
	USAGE: kmers.pl [options]
          
	=== INPUT PARAMETERS ===
	-i                       input CSV list of FASTA formatted genome files
	-il                      input file containing a list of genome files, one per line   

	=== OUTPUT PARAMETERS ===
	-outdir                  directory name for writing output files
           
	=== KMER COUNTING PARAMETERS ===
	-mink                    INT; the minimum value of k [Default: 8]
	-maxk                    INT; the maximum value of k [Default: 12]
	-step                    INT; the step size to use for comparing values of k. Default = 1
	
	=== FILTERING PARAMETERS ===
	-min_freq			int; discard a primer if it does not bind to the foreground genome with at least this frequency.  Default: 5
	-min_tm				int; discard a primer if the estimated melting temperature is below this threshold value.  Default: 15
	-max_tm				int; discard a primer if the estimated melting temperature is below this threshold value.  Default: 45
	-max_gini				int; discard a primer if the individual-based Gini index is above this threshold value.  Default: 1.00
	-allow_ambig			int; allow primer sequences to contain up to X ambiguous bases. Default: 0
	-min_bind_dist			int; discard a kmer if the mean binding distance is less than this threshold value.  Default: 5000
	-max_bind_dist			int; discard a kmer if the mean binding distance is greater than this threshold value.  Default: 1500000
	-filter_repeats			int; use advanced filtering to catch kmers with runs of length 4 or greater, dimer repeats (4 or more), and triplet repeats (3 or more)? Default: OFF
	-organelles				INT flag; How to handle contigs in the genomes that are identified as organelles (mitochondria, plasmids, apicoplasts, chloroplasts )?
								0 == SKIP organelles,  1 == count kmers on ALL contigs [Default],  2 == count kmers ONLY on organelles

	=== OPTIONAL EXTRAS ===
	-v 					verbose
	-t 					INT; number of threads to use for multi-threading
	
	\n";
	print $usage;
}
if ( scalar @ARGV == 0 ) { die usage(); }

GetOptions( 'in|i=s' => \$genome_list,
			'inlist|il=s' => \$input_list,
           'mink=i' => \$mink,
           'maxk=i' => \$maxk,
           'step=i' => \$step,
			'min_freq=i' => \$min_freq,
           'verbose|v' => \$v,
			'outdir|o=s' => \$outdir,
           'min_tm=i' => \$min_tm,
           'max_tm=i' => \$max_tm,
           'max_gini=f' => \$max_gini,
		 'min_bind_dist=i' => \$min_bind_dist,
		 'max_bind_dist=i' => \$max_bind_dist,
		  'allow_ambig=i' => \$allow_ambig,
		  'organelles=i' => \$organelles,
		  'threads|t=i' => \$threads,
		  	'temperature=f' => \$temperature,
			'mgcl=f' => \$mg_conc,
			'oligo_conc=f' => \$oligo_conc,
			'dntps=f' => \$dntp_conc,
			'monovalent=f' => \$monovalent_cation_conc,
			'filter_repeats=i' => \$advanced_filters,
			
) or die usage(); 

# Parameter setups
$mink = ( $mink && int($mink) >= 5 )? $mink : 8;
$maxk = ( $maxk && int($maxk) > int($mink) )? $maxk : $mink;
$step = ( $step && int($step) > 1 )? $step : 1;
$organelles = ( $organelles && $organelles =~ /[0-2]/ )? $organelles : 1;
$min_freq = ( $min_freq && $min_freq > -1 )? $min_freq : 5;
$min_tm = ( $min_tm && $min_tm >= 15 )? $min_tm : 15;
$max_tm = ( $max_tm && $max_tm <= 80 )? $max_tm : 45;		
$min_bind_dist = ( $min_bind_dist && $min_bind_dist >= 5000 )? $min_bind_dist : 5000;
$max_bind_dist = ( $max_bind_dist && $max_bind_dist <= 1500000 )? $max_bind_dist : 1500000;		# 1,500,000
$allow_ambig = ( $allow_ambig && $allow_ambig <= $maxk )? $allow_ambig : 0;
$max_gini = ( $max_gini && $max_gini <= 1.0 && $max_gini >= 0.0 )? $max_gini : 1.0;
$v = defined($v)? 1 : 0;
$threads = ( $threads && $threads >= 1 )? $threads : 1;
$advanced_filters = ( $advanced_filters && $advanced_filters!= 0 )? 1 : 0;
$outdir = ( $outdir )? $outdir : cwd();

# Notes on the "organelles" handling flag:
# 	0 = skip non-chromosomal contigs entirely, 
#	1 = include ALL contigs, disregarding labelling, 
# 	2 = count kmers ONLY on non-chromosomal contigs

##############################################
#       PHASE 0: INITIAL SETUP
##############################################

# Set up the possible values of k if we are using multiple ones
my @ks;
my @proc_order;
for ( my $k=$mink; $k <= $maxk; $k+=$step )                      {
	push @ks, $k;
}

# If it appears that we just gave a file containing a list of genomes, one per line
if ( $input_list )	{	
	open INPUT, $input_list or die "ERROR -- Where tf are your genomes?!\n$!\n";
		@proc_order = <INPUT>;
	close INPUT;
}
# If we just passed a CSV list of genomes directly
if ( $genome_list )	{
	my @tmp = split(",", $genome_list);
	push @proc_order, $_ foreach (@tmp);		# Add these to the proc_order list
}
die "ERROR -- Where tf are your genomes?!\n$!\n" if ( scalar @proc_order == 0 );		# We dont have any genomes!

mkdir $outdir if ( not -d $outdir );

############ THERMODYNAMICS SETUP ##################

# Some variables for primer dimer thermodynamics calculations --> the user can edit these, but they are currently directly set for MEPI lab@CDC standard protocols
# Starting ionic concentration variables
$oligo_conc = ( $oligo_conc )? $oligo_conc : 250; #in nM
$mg_conc = ( $mg_conc )? $mg_conc : 2.0; #in mM
$monovalent_cation_conc = ( $monovalent_cation_conc )? $monovalent_cation_conc : 50; #in mM
$dntp_conc = ( $dntp_conc )? $dntp_conc : 0.1; #in mM
$temperature = ( $temperature )? $temperature : 30;

# deltaG (kcal/mol)
my %oligo_dG =( 'initC' => 0.98, 'initG' => 0.98, 'initA' => 1.03, 'initT' => 1.03 );

# deltaH (kcal/mol)
my %oligo_dH = ( 
	AA => -7.9, TT => -7.9, AT => -7.2, TA => -7.2, CA => -8.5, TG => -8.5, GT => -8.4, AC => -8.4, 
	CT => -7.8, AG => -7.8, GA => -8.2