import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class PARalyze {
	private static ArrayList<String> _inputFile = new ArrayList<String>(1);
	private static ArrayList<Boolean> _inputFileIsCollapsed = new ArrayList<Boolean>(1);
	private static String _outputClustersFile = "";
	
	private static boolean _outputDistributions = false;
	private static String _outputDistributionFile = "";
	private static boolean _outputGroups = false;
	private static String _outputGroupsFile = "";	
	
	private static BufferedWriter _outputFileDistributions;
	private static BufferedWriter _outputFileGroups;	
	private static BufferedWriter _outputFileClusters;
	
	private static Double _bandwidth = (double)3;
	private static String _conversion = "T>C";
	private static int _minimumReadCountPerGroup = 10;
	private static long _minimumClusterSize = 1;
	private static int _minimumCountPerNucleotideForCluster = 1;
	private static int _minimumCountPerNucleotideForKDE = 1;
	private static int _minimumConversionLocationsForCluster = 1;
	private static int _minimumConversionCountForCluster = 1; 
	private static int _minimumReadCountForCluster = 1;
	private static boolean _extendByRead = false;
	private static boolean _haffnerImplementation = false;

	private static int _additionalNucleotidesBeyondSignal = 0;
	private static boolean _seenGenomeFile = false;
	private static MyTwoBitParser _genomeFileParser;
	private static HashMap<String, MyTwoBitParser> _specialChromosome = new HashMap<String, MyTwoBitParser>(1, (float)1.0);
	
	
	private static HashMap<String, String> _filterFiles = new HashMap<String, String>(2, (float)0.99);
	private static boolean _filterLocations = false;	
	
	
	private static ArrayList<String> _seedFiles = new ArrayList<String>();	
	private static boolean _findMIRNAseedMatches = false;
	private static HashMap<String, MIRNA> _mirList = new HashMap<String,MIRNA>();
	private static String _outputTargetFile = "";
	private static BufferedWriter _outputMiRNAtargets;
	private static int _maximumSeedMatchLength = 8;
	private static final Pattern _matchLenPattern = Pattern.compile("^(\\d+)");
	private static final Transliteration _oppositeStrandTransliterate = Transliteration.compile("ACGT", "TGCA");
	
	
	private static ArrayList<ReadGroup> _groupList = new ArrayList<ReadGroup>(100000);
	private static ArrayList<FilterBlock> _filterBlocks = new ArrayList<FilterBlock>(1);
	
	
	private static int _maximumNonConversionMismatchesAllowed = 5;
	private static int _minimumReadLength = 1; 

        private static int chunk = 3; 
	
	public static void main( String[] commandLineArguments ) throws Exception {

	    //	    for(chunk = 0; chunk < 10; chunk++ ){
	    if (1==1) {
		//	_groupList = new ArrayList<ReadGroup>(100000);
		//	_filterBlocks = new ArrayList<FilterBlock>(1);

	    
		System.out.println("Running PARalyzer v1.1");
//***************************************************************	
// Command line & .ini parsing
		if( commandLineArguments.length == 0 || !parseINIfile(commandLineArguments[0]) ) {
			System.out.println("Usage:\nPARalyzer <.ini file> chunk");
			System.out.println("Please see documentation on how to setup your .ini file");
			System.exit(0);
		}
		chunk=10*(commandLineArguments[1].charAt(commandLineArguments[1].length()-2)-'0')+(commandLineArguments[1].charAt(commandLineArguments[1].length()-1)-'0');
//***************************************************************			
	
		
		
//***************************************************************			
// Parse the bowtie alignment files
		System.out.print("Parsing bowtie file(s)...");
		Genome genome = new Genome();
		Iterator<String> fileNameIterator = _inputFile.iterator();
		Iterator<Boolean> collapsedIterator = _inputFileIsCollapsed.iterator();
		PARCLIPbowtieParser currentFile = new PARCLIPbowtieParser(fileNameIterator.next());
		
		genome = currentFile.parseFile(collapsedIterator.next(), _conversion, _minimumReadLength, _maximumNonConversionMismatchesAllowed,chunk);
		
		while( fileNameIterator.hasNext() ) {
			currentFile = new PARCLIPbowtieParser(fileNameIterator.next());
			genome.mergeGenome( currentFile.parseFile(collapsedIterator.next(), _conversion, _minimumReadLength, _maximumNonConversionMismatchesAllowed,chunk) );
		}
		System.out.println("Done");

//***************************************************************			
		
		

		
//***************************************************************			
// Create Read Groups
		System.out.print("Creating Read Groups & Clusters...");
		HashMap<String, Chromosome> chromosomeMap = genome.getChromosomeMap();
		Iterator<String> chromIt = chromosomeMap.keySet().iterator();
		while( chromIt.hasNext() ) {
			Chromosome currentChromosome = chromosomeMap.get(chromIt.next());
			ArrayList<AlignedPARCLIPread> readList = currentChromosome.getReadList();
			Collections.sort(readList);
			Iterator<AlignedPARCLIPread> readIt = readList.iterator();
			ReadGroup currentReadGroup = new ReadGroup("", '\u0000', (long) -1, (long) -1 );
			while( readIt.hasNext() ) {
				AlignedPARCLIPread currentRead = readIt.next();
				if( currentRead.getStrand() != currentReadGroup.getStrand() || currentRead.getStartPosition() > currentReadGroup.getEndPosition() ) {
					if( currentReadGroup.getReadCount() >= _minimumReadCountPerGroup ) {
						String sequence = "";
						if( _specialChromosome.containsKey(currentReadGroup.getChromosome()) ) {
							sequence = _specialChromosome.get(currentReadGroup.getChromosome()).getSequence(
									currentReadGroup.getChromosome(), 
									currentReadGroup.getStrand(), 
									currentReadGroup.getStartPosition(), 
									currentReadGroup.getEndPosition()
							);
						}
						else {
							sequence = _genomeFileParser.getSequence(
									currentReadGroup.getChromosome(), 
									currentReadGroup.getStrand(), 
									currentReadGroup.getStartPosition(), 
									currentReadGroup.getEndPosition()
							);
						}
						currentReadGroup.setSequence(sequence);
						currentReadGroup.calculateDistributions(_conversion, _bandwidth, _minimumCountPerNucleotideForKDE);
// Which method do we use to generate the clusters				
						if( _extendByRead ) {
							currentReadGroup.createClustersBasedOnReads( _minimumCountPerNucleotideForCluster );
						}
						else if ( _haffnerImplementation ) {
							currentReadGroup.createHaffnerClusters( _minimumCountPerNucleotideForCluster, _additionalNucleotidesBeyondSignal );
						}
						else {
							currentReadGroup.createClustersBasedOnDistribution(_minimumCountPerNucleotideForCluster, _additionalNucleotidesBeyondSignal);
						}						
						currentReadGroup.determineClusterReads();
						_groupList.add(currentReadGroup);
					}
					currentReadGroup = new ReadGroup(
							currentChromosome.getName(),
							currentRead.getStrand(),
							currentRead.getStartPosition(),
							currentRead.getEndPosition()
					);
					currentReadGroup.addRead(currentRead);
				}
				else { 
					currentReadGroup.addRead(currentRead);
				}
			}
			if( currentReadGroup.getReadCount() >= _minimumReadCountPerGroup ) {
				String sequence = "";
				if( _specialChromosome.containsKey(currentReadGroup.getChromosome()) ) {
					sequence = _specialChromosome.get(currentReadGroup.getChromosome()).getSequence(
							currentReadGroup.getChromosome(), 
							currentReadGroup.getStrand(), 
							currentReadGroup.getStartPosition(), 
							currentReadGroup.getEndPosition()
					);
				}
				else {
					sequence = _genomeFileParser.getSequence(
							currentReadGroup.getChromosome(), 
							currentReadGroup.getStrand(), 
							currentReadGroup.getStartPosition(), 
							currentReadGroup.getEndPosition()
					);
				}
				currentReadGroup.setSequence(sequence);
				currentReadGroup.calculateDistributions(_conversion, _bandwidth, _minimumCountPerNucleotideForKDE);
				
// Which method do we use to generate the clusters	
				if( _extendByRead ) {
					currentReadGroup.createClustersBasedOnReads( _minimumCountPerNucleotideForCluster );
				}
				else if ( _haffnerImplementation ) {
					currentReadGroup.createHaffnerClusters( _minimumCountPerNucleotideForCluster, _additionalNucleotidesBeyondSignal );
				}
				else {
					currentReadGroup.createClustersBasedOnDistribution(_minimumCountPerNucleotideForCluster, _additionalNucleotidesBeyondSignal);
				}
				currentReadGroup.determineClusterReads();
				_groupList.add(currentReadGroup);
			}
		}
		System.out.println("Done");
		System.out.print("Sorting Groups...");
		Collections.sort(_groupList);
		System.out.println("Done");
		
//***************************************************************			
		
//***************************************************************
// Collect Filter Information;
		if( _filterLocations ) {
			System.out.print("Reading Filter file(s)...");
			Iterator<String> arrayIt = _filterFiles.keySet().iterator();
			while( arrayIt.hasNext() ) {
				String fileName = arrayIt.next();
				String filterType = _filterFiles.get(fileName);
				BufferedReader inputFile = new BufferedReader( new FileReader( fileName ) );
				String line;
				while( ( line = inputFile.readLine() ) != null ) {
					String[] lineInfo = line.split("\t");
					FilterBlock block = new FilterBlock(lineInfo[0], lineInfo[3].charAt(0), Long.parseLong(lineInfo[1]), Long.parseLong(lineInfo[2]), filterType);
					_filterBlocks.add(block);
				}
				inputFile.close();
			}
			Collections.sort(_filterBlocks);
			Iterator<FilterBlock> filterIt = _filterBlocks.iterator();
			FilterBlock currentBlock = new FilterBlock("", '\u0000', (long) -1, (long) -1, "");
			ListIterator<ReadGroup> groupIt = _groupList.listIterator();
			while( groupIt.hasNext() ) {
				ReadGroup currentGroup = groupIt.next();
				Collator chromCompare = Collator.getInstance();
				while( filterIt.hasNext() &&
					(chromCompare.compare( currentBlock.getChromosome(), currentGroup.getChromosome() ) < 0 
					||	(chromCompare.compare( currentBlock.getChromosome(), currentGroup.getChromosome() ) == 0
							&& currentGroup.getStrand() == '-' && currentBlock.getStrand() == '+'
						) 
					||
						(chromCompare.compare( currentBlock.getChromosome(), currentGroup.getChromosome() ) == 0
							&& currentGroup.getStrand() ==currentBlock.getStrand() 
							&& currentGroup.getStartPosition() > currentBlock.getEndPosition() 
						)
					) 
				) {
					currentBlock = filterIt.next();
				}
				if( anyOverlap(
						currentGroup.getStartPosition(), 
						currentGroup.getEndPosition(), 
						currentBlock.getStartPosition(), 
						currentBlock.getEndPosition() 
						) 
				) {
					currentGroup.setFilterType(currentBlock.getType());
				} else { currentGroup.setFilterType("NA"); }
				groupIt.set(currentGroup);
			}
			System.out.println("Done!");
		}
//***************************************************************			
	
		
//***************************************************************	
// If miRNAs, load seed sequences
		if( _findMIRNAseedMatches ) {
			System.out.print("Identifying miRNA targets...");
			Iterator<String> seedIt = _seedFiles.iterator();
			while( seedIt.hasNext() ) {
				BufferedReader inputFile = new BufferedReader( new FileReader( seedIt.next() ) );		
				String line = "";
				while( (line = inputFile.readLine()) != null ) {
					String[] lineArray = line.split(",");
					if( lineArray.length > 0 ) {
						if( lineArray[0].length() > 0 && lineArray[1].length() > 0 ) {
							MIRNA currentMiR = new MIRNA(lineArray[0], lineArray[1]);
							if( _mirList.containsKey(lineArray[0]) ) {
								int i = 2;
								String currentID;
								do {
									currentID = lineArray[0]+"(" + Integer.toString(i) + ")";
									i++;
								} while( _mirList.containsKey(currentID) );
								currentMiR.setName(currentID);
								_mirList.put(currentID, currentMiR);				
							} else {
								_mirList.put(lineArray[0], currentMiR);
							}
						}
					}
				}
				inputFile.close();
			}
			System.out.println("Done");
		}
//***************************************************************			

		
//***************************************************************
// Output Results
		int totalClusterCount = 0;
		System.out.print("Generating Output...");
		Iterator<ReadGroup> groupIt = _groupList.iterator();
		//#chunk
		//		_outputFileClusters = new BufferedWriter( new FileWriter( _outputClustersFile ) );
		_outputFileClusters = new BufferedWriter( new FileWriter( String.format("%s%02d",_outputClustersFile,chunk) ) );
		_outputFileClusters.write(
				"Chromosome,Strand,ClusterStart,ClusterEnd,ClusterID,ClusterSequence,ReadCount,ModeLocation,ModeScore,"
				+ "ConversionLocationCount,ConversionEventCount,NonConversionEventCount"
		);		
		if( _filterLocations ) { _outputFileClusters.write(",FilterType"); }
		_outputFileClusters.write("\n");
		
		//		if( _outputDistributions ) { _outputFileDistributions = new BufferedWriter( new FileWriter( _outputDistributionFile ) ); }
		if( _outputDistributions ) { _outputFileDistributions = new BufferedWriter( new FileWriter( String.format("%s%02d",_outputDistributionFile,chunk) ) ); }
		if( _outputGroups ) { 
		    //			_outputFileGroups = new BufferedWriter( new FileWriter( _outputGroupsFile ) ); 
		    _outputFileGroups = new BufferedWriter( new FileWriter( String.format("%s%02d",_outputGroupsFile,chunk) ) ); 
			_outputFileGroups.write(
				"Chromosome,Strand,GroupStart,GroupEnd,GroupID,GroupSequence,ReadCount,ConversionLocationCount,ConversionEventCount"
			);
			if( _filterLocations ) { _outputFileGroups.write(",FilterType"); }
			_outputFileGroups.write("\n");
		}
		int groupNumber = 1;
		if( _findMIRNAseedMatches ) { 
			_outputMiRNAtargets = new BufferedWriter( new FileWriter( _outputTargetFile ) ); 
			_outputMiRNAtargets.write(
				"Chromosome,Strand,SiteStart,SiteEnd,SeedSequence,SeedType,ClusterID,ClusterSequence,miRNAs"	
			);
			if( _filterLocations ) { _outputMiRNAtargets.write(",FilterType"); }
			_outputMiRNAtargets.write("\n");
		}

		
		while( groupIt.hasNext() ) {
			ReadGroup currentGroup = groupIt.next();
			String groupID = "G" + Integer.toString(groupNumber);
// Write to the group file
			if( _outputGroups ) { 
				_outputFileGroups.write(
						currentGroup.getChromosome() + "," +
						currentGroup.getStrand() + "," + 
						Long.toString(currentGroup.getStartPosition()) + "," +
						Long.toString(currentGroup.getEndPosition()) + "," +
						groupID + "," +
						currentGroup.getSequence() + "," +
						Integer.toString(currentGroup.getReadCount()) + "," +
						Integer.toString(currentGroup.getNumberOfConversionlocations()) + "," +
						Integer.toString(currentGroup.getNumberOfConversions())
				);
				if( _filterLocations ) { _outputFileGroups.write("," + currentGroup.getFilterType()); }
				_outputFileGroups.write("\n");
			}	
// Write to the distribution file			
//			if( _outputDistributions && currentGroup.getNumberOfConversions() > 0 ) {
			if( _outputDistributions && currentGroup.getNumberOfConversions() >= 0 ) {
					_outputFileDistributions.write(currentGroup.getChromosome() + "," +
					currentGroup.getStrand() + "," + 
					Long.toString(currentGroup.getStartPosition()) + "," +
					Long.toString(currentGroup.getEndPosition()) + "," +
					groupID + "," + "Signal" + 
					currentGroup.displaySignal()
					+ "\n"
				);
				_outputFileDistributions.write(currentGroup.getChromosome() + "," +
						currentGroup.getStrand() + "," + 
						Long.toString(currentGroup.getStartPosition()) + "," +
						Long.toString(currentGroup.getEndPosition()) + "," +
						groupID + "," + "Background" + 
						currentGroup.displayBackground()
						+ "\n"
				);
				_outputFileDistributions.write(currentGroup.getChromosome() + "," +
						currentGroup.getStrand() + "," + 
						Long.toString(currentGroup.getStartPosition()) + "," +
						Long.toString(currentGroup.getEndPosition()) + "," +
						groupID	+ "," + "ConversionPercent" + 
						currentGroup.displayConversionPercent()	
						+ "\n"
				);		
				_outputFileDistributions.write(currentGroup.getChromosome() + "," +
						currentGroup.getStrand() + "," + 
						Long.toString(currentGroup.getStartPosition()) + "," +
						Long.toString(currentGroup.getEndPosition()) + "," +
						groupID + "," + "ReadCount" + 
						currentGroup.displayReadCount()	
						+ "\n"
				);
			}
// output the clusters			
			
//if( groupID.equals("G8208") || groupID.equals("G8209") ) {
//	System.out.println(groupID + ": " + currentGroup.getNumberOfClusters());
//}
			
			
			if( currentGroup.getNumberOfClusters() > 0 ) {
				ArrayList<KDECluster> clusterList = currentGroup.getClusterList();
				Iterator<KDECluster> clusterIt = clusterList.iterator();
				int clusterNumber = 1;				
// Is it a valid cluster....									
				while( clusterIt.hasNext() ) {
					KDECluster currentCluster = clusterIt.next();
					if(
						currentCluster.getReadCount() >= 1
						&& currentCluster.getNumberOfConversionlocations() >= _minimumConversionLocationsForCluster
						&& currentCluster.getConversionCount() >= _minimumConversionCountForCluster
						&& currentCluster.getReadCount() >= _minimumReadCountForCluster
						&& (int) (currentCluster.getEndPosition() - currentCluster.getStartPosition() + 1) >= _minimumClusterSize
					) {
						String clusterID = groupID + "." + Integer.toString(clusterNumber);
						totalClusterCount++;
						_outputFileClusters.write(
							currentGroup.getChromosome() + "," +
							currentGroup.getStrand() + "," + 
							Long.toString(currentCluster.getStartPosition()) + "," +
							Long.toString(currentCluster.getEndPosition()) + "," +
							clusterID + "," +
							currentCluster.getSequence() + "," +
							Integer.toString(currentCluster.getReadCount()) + "," +
							Long.toString(currentCluster.getModePosition()) + "," +
							Double.toString(currentCluster.getModeScore()) + "," + 
							Integer.toString(currentCluster.getNumberOfConversionlocations()) + "," +
							Integer.toString(currentCluster.getConversionCount()) + "," +							
							Integer.toString(currentCluster.getNumberOfNonConversions(currentGroup.getStrand()))
						);
						if( _filterLocations ) { _outputFileClusters.write("," + currentGroup.getFilterType()); }
						_outputFileClusters.write("\n");
						
						if( _findMIRNAseedMatches ) {
							currentCluster.findmiRNAsites(_mirList, _maximumSeedMatchLength);
							if( currentCluster.foundSites() ) {
								TreeMap<MIRNAseedMatch, String> siteTree = currentCluster.getMiRsiteTree();
								Iterator<MIRNAseedMatch> treeIt = siteTree.keySet().iterator();
								while( treeIt.hasNext() ) {
									MIRNAseedMatch currentMatch = treeIt.next();
									String miRNAnames = siteTree.get(currentMatch);
									String currentType = currentMatch.getMatchType();
									Matcher matchLenMatcher = _matchLenPattern.matcher(currentType);
									matchLenMatcher.find();
									int location = Integer.parseInt(matchLenMatcher.group(1));
									if( currentType.substring(currentType.length() - 2).equals("1A") ) {
										location++;
									}
									String seedSequence = currentCluster.getSequence().substring(currentMatch.getLocation() - location, currentMatch.getLocation());
									seedSequence = _oppositeStrandTransliterate.translate(seedSequence);
									seedSequence = new StringBuffer(seedSequence).reverse().toString();									
									
									long start = 0;
									long end = 0;
									if( currentGroup.getStrand() == '+' ) {
										start = (long) (currentMatch.getLocation() - location) + currentCluster.getStartPosition() + 1;
										end = (long) currentMatch.getLocation() + currentCluster.getStartPosition();
									}
									else {
										start = currentCluster.getEndPosition() - (long) currentMatch.getLocation() + 1;
										end = currentCluster.getEndPosition() - (long) ( currentMatch.getLocation() - location);
									}
									_outputMiRNAtargets.write(
										currentGroup.getChromosome() + "," +
										currentGroup.getStrand() + "," +
										Long.toString(start) + "," +
										Long.toString(end) + "," + 
										seedSequence + "," +
										currentType + "," +
										clusterID + "," +
										currentCluster.getSequence() + "," +
										miRNAnames
									);
									if( _filterLocations ) { _outputMiRNAtargets.write("," + currentGroup.getFilterType()); }
									_outputMiRNAtargets.write("\n");
								}
							}
						}
						clusterNumber++;
					}
				}
			}
			groupNumber++;
		}
		_outputFileClusters.close();
		if( _outputDistributions ) { _outputFileDistributions.close(); }
		if( _outputGroups ) { _outputFileGroups.close(); }
		if( _findMIRNAseedMatches ) { _outputMiRNAtargets.close(); }
		_genomeFileParser.close();
		Iterator<String> closeIt = _specialChromosome.keySet().iterator();
		while( closeIt.hasNext() ) {
			_specialChromosome.get(closeIt.next()).close();
		}
		System.out.println("Done!");
		System.out.println("I identified a total of " + Integer.toString(genome.getReadCount()) + " reads mapping to " + Integer.toString(genome.getUniqueReadCount()) + " Unique genomic coordinates");
		System.out.println("Making up " + Integer.toString(_groupList.size()) + " groups");
		System.out.println("Consisting of " + Integer.toString(totalClusterCount) + " clusters");
		_groupList=null;
		_filterBlocks=null;
		genome=null;
		chromosomeMap =null;
		//		chromosomeIt=null;
		//		readList=null;
		//readIt=null;
		currentFile=null;
		System.gc();
	    }//chunk loop
//***************************************************************
	}

//***************************************************************			
// Determine if there is any overlap between any two genomic blocks
	private static boolean anyOverlap(long start1, long end1, long start2, long end2 ) {
		if( 
			( start1 >= start2 && start1 <= end2 ) ||
			( end1 >= start2 && end1 <= end2 ) ||
			( start2 >= start1 && start2 <= end1 ) ||
			( end2 >= start1 && end2 <= end1 ) 
		) {
			return true;
		}
		else {
			return false;
		}
	}
//***************************************************************			

	
//***************************************************************			
// Parase the .ini file and make sure everything necessary has been given
	private static boolean parseINIfile( String fileName ) {
		try {
			BufferedReader inputFile = new BufferedReader( new FileReader( fileName ) );
			String line;
			while( ( line = inputFile.readLine() ) != null ) {
				String[] lineArray = line.split("=");
				if( lineArray[0].equals("BOWTIE_FILE") ) {
					File file = new File(lineArray[1]);
					if( !file.exists() ) {
						System.out.println("Cannot find file: " + lineArray[1]);
						return false;
					}
					_inputFile.add(lineArray[1]);
					if( lineArray.length == 3 ) { _inputFileIsCollapsed.add(true); }
					else { _inputFileIsCollapsed.add(false); }
				}
				if( lineArray[0].equals("BANDWIDTH") ) {
					_bandwidth =  Double.parseDouble(lineArray[1]);
				}
				if( lineArray[0].equals("SPECIAL_CHROMOSOME") ) {
					File file = new File(lineArray[2]);
					if( !file.exists() ) {
						System.out.println("Cannot find file: " + lineArray[2]);
						return false;
					}
					_specialChromosome.put(lineArray[1], new MyTwoBitParser(lineArray[2]));
				}
				if( lineArray[0].equals("OUTPUT_DISTRIBUTIONS_FILE") ) {
					_outputDistributions = true;
					_outputDistributionFile = lineArray[1];
				}
				if( lineArray[0].equals("OUTPUT_GROUPS_FILE") ) {
					_outputGroups = true;
					_outputGroupsFile = lineArray[1];
				}
				if( lineArray[0].equals("OUTPUT_CLUSTERS_FILE") ) {
					_outputClustersFile = lineArray[1];
				}
				if( lineArray[0].equals("OUTPUT_MIRNA_TARGETS_FILE") ) {
					_outputTargetFile = lineArray[1];
				}
				if( lineArray[0].equals("CONVERSION") ) {
					_conversion = lineArray[1];
				}
				if( lineArray[0].equals("MINIMUM_READ_COUNT_PER_GROUP") ) {
					_minimumReadCountPerGroup = Integer.parseInt(lineArray[1]);
				}
				if( lineArray[0].equals("MINIMUM_CLUSTER_SIZE") ) {
					_minimumClusterSize = Integer.parseInt(lineArray[1]);
				}
				if( lineArray[0].equals("GENOME_2BIT_FILE") ) {
					File file = new File(lineArray[1]);
					if( !file.exists() ) {
						System.out.println("Cannot find file: " + lineArray[1]);
						return false;
					}
					_genomeFileParser = new MyTwoBitParser(lineArray[1]);
					_seenGenomeFile = true;
				}
				if( lineArray[0].equals("FILTER_FILE") ) {
					File file = new File(lineArray[1]);
					if( !file.exists() ) {
						System.out.println("Cannot find file: " + lineArray[1]);
						return false;
					}
					_filterLocations = true;
					_filterFiles.put(lineArray[1], lineArray[2]);
				}
				if( lineArray[0].equals("MINIMUM_READ_COUNT_PER_CLUSTER") ) {
					_minimumReadCountForCluster = Integer.parseInt(lineArray[1]);
				}
				if( lineArray[0].equals("MINIMUM_READ_COUNT_FOR_KDE") ) {
					_minimumCountPerNucleotideForKDE = Integer.parseInt(lineArray[1]);					
				}
				if( lineArray[0].equals("MINIMUM_CONVERSION_LOCATIONS_FOR_CLUSTER") ) {
					_minimumConversionLocationsForCluster = Integer.parseInt(lineArray[1]);
				}
				if( lineArray[0].equals("MINIMUM_CONVERSION_COUNT_FOR_CLUSTER") ) {
					_minimumConversionCountForCluster = Integer.parseInt(lineArray[1]);
				}				
				if( lineArray[0].equals("FIND_MIRNA_SEEDMATCHES") ) {
					File file = new File(lineArray[1]);
					if( !file.exists() ) {
						System.out.println("Cannot find file: " + lineArray[1]);
						return false;
					}
					_seedFiles.add(lineArray[1]);
					_findMIRNAseedMatches = true;
				}
				if( lineArray[0].equals("MAXIMUM_SEED_MATCH_LENGTH") ) {
					_maximumSeedMatchLength = (Integer.parseInt(lineArray[1]));
				}
				if( lineArray[0].equals("MINIMUM_READ_COUNT_FOR_CLUSTER_INCLUSION") ) {
					_minimumCountPerNucleotideForCluster = Integer.parseInt(lineArray[1]);
				}
				if( lineArray[0].equals("EXTEND_BY_READ") ) {
					_extendByRead = true;
				}
				if( lineArray[0].equals("HAFNER_APPROACH") ) {
					_haffnerImplementation = true;
				}
				if( lineArray[0].equals("ADDITIONAL_NUCLEOTIDES_BEYOND_SIGNAL") ) {
					_additionalNucleotidesBeyondSignal = Integer.parseInt(lineArray[1]);
				}
				if( lineArray[0].equals("MAXIMUM_NUMBER_OF_NON_CONVERSION_MISMATCHES") ) {
					_maximumNonConversionMismatchesAllowed = Integer.parseInt(lineArray[1]);
				}
				if( lineArray[0].equals("MINIMUM_READ_LENGTH") ) {
					_minimumReadLength = Integer.parseInt(lineArray[1]);
				}
			}
		}
		catch(FileNotFoundException e) {
			return false;
		} 
		catch (NumberFormatException e) {
			return false;
		} 
		catch (IOException e) {
			return false;
		} catch (Exception e) {
			return false;
		}
// Cases where we could run into an error
		if( _bandwidth == 0 ) { 
			System.out.println("You cannot have a bandwidth parameter set to 0");
			return false;
		}
		if( !_seenGenomeFile && _findMIRNAseedMatches ) { 
			System.out.println("You cannot identify seed matches if you do not specify a genome file");
			return false;
		}
		if( _extendByRead && _additionalNucleotidesBeyondSignal > 0 ) {
			System.out.println("You cannot extend a cluster by a given number of nucleotides if you are extending by the read information");
			return false;
		}
		if( !_seenGenomeFile ) {
			System.out.println("I currently require a .2bit genome file");
			return false;
		}
		return true;
	}
//***************************************************************			

}
