
# crossmatch2SAM_v1.1.rb
# =================================================================================================================================================
#
#                           PUBLIC DOMAIN NOTICE
#            Human Genome Sequencing Center, and Department of Molecular and Human Genetics
#
#            Baylor College of Medicine
#
# This software is freely available to the public for use. We have not placed any restriction on its use or reproduction.
#
# Although all reasonable efforts have been taken to ensure the accuracy and reliability of the software and data, the authors do not and cannot
# warrant the performance or results that may be obtained by using this software. The authors disclaim all warranties, express or implied,
# including warranties of performance, merchantability or fitness for any particular purpose.
#
# Please cite the authors in any work or product based on this material.
#
# ==================================================================================================================================================
#
# File Name:  crossmatch2SAM_v1.1.rb
#
# Version: 1.1
#
# Modifications in version 1.1 compared to 1.0: the input read sequence file and read quality file are zipped gz files. 
#
# Author: Yong (Tony) Wang, Zhengzheng Wan from Fuli Yu group
#
# Contact: yw14@bcm.tmc.edu, zwan@bcm.tmc.edu, fyu@bcm.tmc.edu
#
# Version Creation Date:  05/30/2009
#
# Program overview:
#  'crossmatch2SAM_v1.1.rb' is a converter tool which converts a crossmatch output format file to a SAM (Sequence Alignment/Map) format file.
#
# Command Line Arguments:
# Usage: Crossmatch2SAM_v1.1.rb -i [crossmatch file] -o [SAM format outputfile] -r [read sequence file, zipped] -q [read quality file, zipped] -f [reference sequence file]
#  -i is a required argument, which must be followed by a crossmatch format file.
#  -o is a required argument which must be appended by the user-defined output file.
#  -r is a required argument which must be followed by the zipped query sequence file.
#  -q is a required argument which must be followed by the zipped quality file.
#  -f is a required argument which must be followed by the reference file.
#
# Example:
#   Create SAM format file by taking crossmatch output file, query sequence file, query quaity file and reference sequence file as the inputs.
#   For example: ruby Crossmatch2SAM_v1.1.rb -i crossmatch.txt -o sam.txt -r query.txt.gz -q quality.txt.gz -f reference.txt
#
# Output format:
#   query_name[tab]FLAG[tab]reference_name[tab]leftmost_postion[tab]mapping_quality[tab]CIGAR[tab]MRNM[tab]MPOS[tab] \
#   ISIZE[tab]query_sequence[tab]read_quality[tab]sub_percentage[tab]del_percentage[tab]ins_percentage[tab]
#   refer to SAM Format Specifications for detail"
# ====================================================================================================================================================

#!/usr/bin/env ruby
require 'getoptlong'
require 'bigdecimal'
require 'zlib'

class  Crossmatch2SAM

#Initialize options 
def Crossmatch2SAM.processArguments()

opts = GetoptLong.new(
    ["--input", "-i", GetoptLong::REQUIRED_ARGUMENT],
    ["--help","-h", GetoptLong::NO_ARGUMENT],
    ["--output","-o", GetoptLong::REQUIRED_ARGUMENT],
    ["--read","-r", GetoptLong::REQUIRED_ARGUMENT],
    ["--qual","-q", GetoptLong::REQUIRED_ARGUMENT],
    ["--refer","-f", GetoptLong::REQUIRED_ARGUMENT]
)

optHash = {}
opts.each do |opt, arg|
  optHash[opt] = arg
end

Crossmatch2SAM.usage() if (optHash.key?("--help"));

Crossmatch2SAM.usage() if (optHash.empty?);
return optHash
end

#The usage information of the program
def Crossmatch2SAM.usage(msg='')
    unless (msg.empty?)
        puts "\n#{msg}\n"
    end
    puts "
Program overview:
       'Crossmatch2SAM_v1.rb' is a converter tool which converts a crossmatch output format file to a SAM (Sequence Alignment/Map) format file.
   
Command Line Arguments:
  Usage: Crossmatch2SAM_v1.rb -i [crossmatch file] -o [SAM format outputfile] -r [read sequence file] -q [read quality file] -f [reference sequence file]
  -i is a required argument, which must be followed by a crossmatch format file.
  -o is a required argument which must be appended by the user-defined output file.
  -r is a required argument which must be followed by the query sequence file.
  -q is a required argument which must be followed by the quality file.
  -f is a required argument which must be followed by the reference file.
  
Example:
  Create SAM format file by taking crossmatch output file, query sequence file, query quaity file and reference sequence file as the inputs.
  For example: ruby Crossmatch2SAM_v1.rb -i crossmatch.txt -o sam.txt -r query.txt -q quality.txt -f reference.txt

Output format:
  query_name[tab]FLAG[tab]reference_name[tab]leftmost_postion[tab]mapping_quality[tab]CIGAR[tab]MRNM[tab]MPOS[tab] \
  ISIZE[tab]query_sequence[tab]read_quality[tab]program[tab]Alignment score[tab]number of perfect hits[tab] \
  string for mismatch positions[tab]sub_percentage[tab]del_percentage[tab]ins_percentage[tab]
  refer to SAM Format Specifications for detail"
  exit(2);
end

#Initialize the object of the class "Crossmatch2SAM"
def initialize(optHash)
    @optHash=optHash
    setParameters()
end

#Initialize the parameters
def setParameters()
    if (!@optHash.key?('--input') or !@optHash.key?("--output") or !@optHash.key?("--read") or !@optHash.key?("--qual") or !@optHash.key?("--refer"))then
        Crossmatch2SAM.usage("Option missing!")
        exit(2);
    end
    
    @crossFile=@optHash["--input"]
    @outputFile=@optHash["--output"]
    @queryFile=@optHash["--read"]
    @qualityFile=@optHash["--qual"]
    @referenceFile=@optHash["--refer"]
        
end

$pattern=/^\s*(\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\S+)\s+([0-9]+)\s+(\d+)\s+\((\d+)\)\s+(C*?)\s*?(\S+)_(\d+)_(\d+)\s+\(*?(\d+)\)*?\s+(\d+)\s+\(*?(\d+)\)*?/

#Read crossmatch file, query sequence file, query quality file and reference file. Then write the information to output file in SAM format
def readcrossmatchwritesam()
    
    #control parameters
    $start=0
    $found=0
    $num=0
    $num_id=0
    $pre_refer = ""
    $cur_refer = ""
    $round = 0
    $prev_num = 0
    $prev_type = ""

    #output information parameters
    #Alignment section parameters
    $qseq = ""
    $qualseq = ""
    type = []
    type_id = []
    type_num = []
    type_num_id = []
    qplace = []
    qplace_id = []
    tplace = []
    tplace_id = []
    ntype = []
    nqual = []
    nseq = []
    qualityArray = []
    referArray = []

    $lengthQuery = 0
    $lengthCross = 0
    $trim = 0

    #Tag section parameters
    $tag_NM =0
    $tag_H0 = 0
    $tag_MD = ""
    $tag_C = 0

    #Get file handlers
    crossReader=File.open(@crossFile,"r")
    samWriter=File.new(@outputFile,"w")
    #queryReader=File.open(@queryFile,"r")
    queryReader=Zlib::GzipReader.open(@queryFile)
    #qualityReader=File.open(@qualityFile,"r")
    qualityReader=Zlib::GzipReader.open(@qualityFile)
    referenceReader=File.open(@referenceFile,"r")
   
    #read query sequence file into a read hash table
    qseqHash = Hash.new
    $queryname=""
    queryReader.each do |qline|
        if qline =~ /^>/
            $queryname = qline.split(/[ \t>\n]+/)[1] 
            qseqHash[$queryname] = ""
        else
            qseqHash[$queryname] << qline.chomp.strip
        end
    end 
    #$stderr.puts "Good: finished hashing read file"

    #read quality file into a quality hash table
    qualityHash = Hash.new
    #open the quality sequence file and then convert it to Phred base score format (MAQ)  
    $qualseq = ""
    $queryname = ""
    qualityReader.each do |qline|
        if qline =~ /^>/
            $queryname = qline.split(/[ \t>\n]+/)[1] 
            qualityHash[$queryname] = ""
        else
            $qualseq = qline.chomp.strip
            qualityArray = $qualseq.split(/\s* \s*/)
            $qualseq = ""
            qualityArray.length.times do |i|
                temp=qualityArray[i].to_i+33
                $qualseq << temp.chr
            end
            qualityHash[$queryname] << $qualseq
        end
    end
    #$stderr.puts "Good: finished hashing quality file"  

    #read reference sequence file into hash table
    referenceHash = Hash.new
    $referenceName=""
    $round = 0
    referenceReader.each do |qline|
        #$round += 1
        #temp = $round % 10000
        #if temp == 0
        #$stderr.puts "Good: finished line #{$round} of reference file"
        #end
        
        if qline =~ /^>(\S+)/
            $referenceName = $1
            referenceHash[$referenceName]=""
        else
            referenceHash[$referenceName] << qline.chomp.strip
        end
    end
    #puts referenceHash[$referenceName]
    #$stderr.puts "Good: finished hashing reference file"
    $stderr.puts ""
    $sequenceLength = referenceHash[$referenceName].length

    #print header information
    samWriter.print "@HD\tVN:1.0\n"
    samWriter.print "@SQ\tSN:#{$referenceName}\tLN:#{$sequenceLength}\n"
    samWriter.print "@RG\tID:--\tLB:--\tPU:--\tCN:HGSC\tDT:--PL:--\n"
    samWriter.print "@PG\tID:crossmatch\n"
                            
    crossReader.rewind
    $round = 0
    crossReader.each do |line|

        if ( line.match($pattern) or crossReader.eof? )

            #$round += 1
            #temp = $round % 100
            #if temp == 0
                #$stderr.puts "Good: finished line #{$round} of crossmatch file"
            #end

            if $start!=0
             
                #get quality ASCII sequence from quality sequence hash
                $qualseq = ""
                if qualityHash.has_key?($qname)
                    $qualseq = qualityHash[$qname]
                    #$stderr.puts $qualseq
                else
                    #$stderr.puts "Warning:  can't find the quality sequence for the query:\t#{$qname}\n"
                end

                #get query sequence from query sequence hash
                $qseq = ""
                if qseqHash.has_key?($qname)
                    $qseq = qseqHash[$qname]
                    #$stderr.puts $qseq
                    $lengthQuery = $qseq.length
                    $lengthQual = $qualseq.length
                    $lengthCross = $eposq + $nofbases
                    temp = $lengthQuery - $lengthCross
                    
                    if temp >0 
                        #read length larger than cross length, need to trim the read sequence
                        if temp <= 20
                             #trim the head adapter
                             $qseq = $qseq[temp..-1]
                        else
                             #Trim the head adapter and tail adapter
                             $qseq = $qseq[20..-1]
                             temp = 19 - temp
                             $qseq = $qseq[0..temp]
                        end
                    elsif temp == 0
                        #perfect match, nothing needed to do
                    else
                        #read length smaller than cross length, potential problem with read sequence
                        $stderr.puts "read length smaller than cross length\n"
                        #exit(0);
                    end
 
                    temp = $lengthQual - $lengthCross
                    if temp >0
                        #read qual length larger than cross length, need to trim the read qual sequence
                        if temp <= 20
                             #trim the head adapter
                             $qualseq = $qualseq[temp..-1]
                        else
                             #Trim the head adapter and tail adapter
                             $qualseq = $qualseq[20..-1]
                             temp = 19 - temp
                             $qualseq = $qualseq[0..temp]
                        end
                    elsif temp == 0
                        #perfect match, nothing needed to do
                    else
                        #read length smaller than cross length, potential problem with read sequence
                        $stderr.puts "read length smaller than cross length\n"
                        #exit(0);
                    end

                else
                    #$stderr.puts "Warning:  can't find the query sequence for the query:\t#{$qname}\n"
                end

                $tag_NM = 0
                if $compl == "C"
                    if $sposr < $eposr
                       $pos = $pos1 + $sposr
                       $flag=0
                    else
                       $pos = $pos1 + $eposr
                       $flag=16
                    end
                else
                    $flag=0
                    if $sposr < $unk
                       $pos = $pos1 + $sposr
                    else
                       $pos = $pos1 + $unk
                    end
                end
                $pos -= 1

                if $compl == "C"
                    $tag_C = 0
                else
                    $tag_C = 1
                end

                               
                if $num > 0

                    #Start to formulate tag_MD code
                    #Count the number of positions of S and D, since I is counted as match
                    $num_id = 0
                    (0..$num-1).each do |i|
                        if ( type[i] != "I" )
                            type_id[$num_id]=type[i]
                            type_num_id[$num_id]=type_num[i]
                            qplace_id[$num_id]=qplace[i]
                            tplace_id[$num_id]=tplace[i]
                            $num_id = $num_id + 1
                        end 
                    end

                    if $num_id > 0
                        $tag_MD = ""
                        if type_num_id[0] > 1
                            if type_id[0] == "D"
                                #The first is more than one "D"
                                temp = qplace_id[0] - $sposq + 1
                            else
                                #The first is more than one "S"
                                temp = qplace_id[0] - $sposq
                            end
                            if temp > 0
                                $tag_MD << temp.to_s
                            end
                            temp = type_num_id[0] - 1
                            if type_id[0] == "D"
                                $tag_MD << "^"
                                if $tag_C == 0
                                    (0..temp).each do |j|
                                       $tag_MD << referenceHash[$cur_refer][$pos1 + tplace_id[0] + j - temp - 1]
                                    end
                                else
                                    (0..temp).each do |j|
                                       $tag_MD << referenceHash[$cur_refer][$pos1 + tplace_id[0] + j - 1]
                                    end
                                end
                            else
                                (0..temp).each do |j|
                                   $tag_MD << referenceHash[$cur_refer][$pos1 + tplace_id[0] + j -2]
                                end
                            end
                            $prev_num = type_num_id[0]
                            $prev_type = type_id[0]
                        else
                            if type_id[0] == "D"
                                #The first is one "D"
                                temp = qplace_id[0] - $sposq + 1
                            else
                                #The first is one "S"
                                temp = qplace_id[0] - $sposq
                            end
                            if temp > 0
                                $tag_MD << temp.to_s
                            end
                            if type_id[0] == "D"
                                $tag_MD << "^"
                                $tag_MD << referenceHash[$cur_refer][$pos1 + tplace_id[0] - 1]
                            else
                                $tag_MD << referenceHash[$cur_refer][$pos1 + tplace_id[0] - 2]
                            end
                            $prev_num = 1
                            $prev_type = type_id[0]
                        end
                        
                        #Calculate "D" and "S"
                        (1..$num_id-1).each do |i|
                            if type_num_id[i] > 1
                                if type_id[i] == "D"
                                    if $prev_type == "I"
                                        temp = qplace_id[i] - qplace_id[i-1] - $prev_num + 1
                                    else
                                        temp = qplace_id[i] - qplace_id[i-1]
                                    end 
                                else
                                    if $prev_type == "I"
                                        temp = qplace_id[i] - qplace_id[i-1] - $prev_num
                                    else
                                        temp = qplace_id[i] - qplace_id[i-1] - 1
                                    end
                                end
                                if temp > 0
                                    $tag_MD << temp.to_s
                                end
                                temp = type_num_id[i] - 1
                                if type_id[i] == "D"
                                    $tag_MD << "^"
                                    if $tag_C == 0
                                        (0..temp).each do |j|
                                           $tag_MD << referenceHash[$cur_refer][$pos1 + tplace_id[i] + j - temp - 1]
                                        end
                                    else
                                        (0..temp).each do |j|
                                           $tag_MD << referenceHash[$cur_refer][$pos1 + tplace_id[i] + j - 1]
                                        end
                                    end
                                else
                                    (0..temp).each do |j|
                                        $tag_MD << referenceHash[$cur_refer][$pos1 + tplace_id[i] + j - 1]
                                    end
                                end
                                $prev_num = type_num_id[i]
                                $prev_type = type_id[i]
                            else
                                if type_id[i] == "D"
                                    if $prev_type == "I"
                                        temp = qplace_id[i] - qplace_id[i-1] - $prev_num + 1
                                    else
                                        temp = qplace_id[i] - qplace_id[i-1]
                                    end 
                                else
                                    if $prev_type == "I"
                                        temp = qplace_id[i] - qplace_id[i-1] - $prev_num
                                    else
                                        temp = qplace_id[i] - qplace_id[i-1] - 1
                                    end
                                end
                                if temp > 0
                                    $tag_MD << temp.to_s
                                end
                                if type_id[i] == "D"
                                    $tag_MD << "^" 
                                    $tag_MD << referenceHash[$cur_refer][$pos1 + tplace_id[i] - 1]
                                else
                                    $tag_MD << referenceHash[$cur_refer][$pos1 + tplace_id[i] - 2]
                                end
                                $prev_num = 1
                                $prev_type = type_id[i]
                            end
                        end

                        #Calculate the last one
                        temp = $eposq - qplace_id[$num_id-1] 
                        if temp > 0
                            $tag_MD << temp.to_s
                        end
                    else
                        #If there is no S or D, all are insertion
                        $tag_MD = ""
                        temp = $eposq - $sposq + 1
                        if temp > 0
                            $tag_MD = temp.to_s
                        end
                    end
                    #tag_MD code is formulated and ready for output

                    #Start to formulate CIGAR code

                    #Count the number of positions of I and D, since S is counted as mismatch
                    #Also count the number of nucleotide differences and save to tag_NM
                    $num_id = 0
                    (0..$num-1).each do |i|
                        $tag_NM += type_num[i]
                        if ( type[i] == "I" or type[i] == "D")
                            type_id[$num_id]=type[i]
                            type_num_id[$num_id]=type_num[i]
                            qplace_id[$num_id]=qplace[i]
                            $num_id = $num_id + 1
                        end 
                    end

                    #Use the number of positions of I and D to formulate CIGAR code
                    
                    if $num_id > 0
                        #If there are I or D
                        $prev_num = 1
                        if $sposq > 1
                            #Soft clips in the beginning
                            temp = $sposq-1 
                            cigar = temp.to_s + "S"
                        else
                            cigar = ""
                        end

                        if type_id[0] == "I"
                            #The first is "I"
                            temp = qplace_id[0] - $sposq 
                        else
                            #The first is "D"
                            temp = qplace_id[0] - $sposq + 1
                        end
                        if temp > 0
                            cigar << temp.to_s + "M"
                        end
                        cigar << type_num_id[0].to_s + type_id[0]
                        $prev_num = type_num_id[0]
                        $prev_type = type_id[0]
                        
                        #Calculate "I" and "D"
                        (1..$num_id-1).each do |i|
                            if type_id[i] == "I"
                                if $prev_type == "I"
                                    temp = qplace_id[i] - qplace_id[i-1] - $prev_num
                                else
                                    temp = qplace_id[i] - qplace_id[i-1] - 1
                                end
                            else
                                if $prev_type == "I"
                                    temp = qplace_id[i] - qplace_id[i-1] - $prev_num + 1
                                else
                                    temp = qplace_id[i] - qplace_id[i-1]
                                end  
                            end
                            $prev_num = type_num_id[i]
                            $prev_type = type_id[i]

                            if temp > 0
                                cigar << temp.to_s + "M"
                            end
                            
                            cigar << type_num_id[i].to_s + type_id[i]
                        end

                        #Calculate the last one
                        if type_id[$num_id-1] =~ /^(\S+)\-(\d+)/
                            if $1 == "I"
                                temp = $eposq - qplace_id[$num_id-1] - $2.to_i + 1 
                            else
                                temp = $eposq - qplace_id[$num_id-1] 
                            end
                        else
                            if type_id[$num_id-1] == "I"
                                temp = $eposq - qplace_id[$num_id-1]
                            else
                                temp = $eposq - qplace_id[$num_id-1]
                            end
                        end
                        if type_num_id[$num_id-1] > 1
                            if type_id[$num_id-1] == "I"
                                temp = $eposq - qplace_id[$num_id-1] - type_num_id[$num_id-1] + 1 
                            else
                                temp = $eposq - qplace_id[$num_id-1] 
                            end
                        else
                            temp = $eposq - qplace_id[$num_id-1]
                        end
                        if temp > 0
                            cigar << temp.to_s + "M"
                        end
                        
                     else
                        #If there is no I or D, all are mismatch
                        if $sposq > 1
                            #Soft clips in the beginning
                            temp = $sposq-1 
                            cigar = temp.to_s + "S"
			    temp = $eposq - $sposq + 1
                            if temp > 0
                                cigar << temp.to_s + "M"
                            end
                            
                        else
                            temp = $eposq - $sposq + 1
                            if temp > 0
                                cigar = temp.to_s 
                                cigar << "M"
                            end
                        end
     
                     end
                     if $nofbases > 0
                        #Soft clips in the end
                        cigar << $nofbases.to_s + "S"
                     end
		     #puts cigar
                     #CIGAR code is formulated and ready to output
                     
                     samWriter.print "#{$qname}\t#{$flag}\t#{$rname}\t#{$pos}\t0\t#{cigar}\t*\t0\t0\t#{$qseq}\t#{$qualseq}\tPG:Z:crossmatch\tAS:i:#{$score}\tNM:i:#{$tag_NM}\tH0:i:0\tMD:Z:#{$tag_MD}\tXP:f:#{$psub}\tXD:f:#{$pdel}\tXI:f:#{$pins}\tXS:i:#{$tag_C}\n"
                     #samWriter.print "#{$qname}\t#{$flag}\t#{$rname}\t#{$pos}\t0\t#{cigar}\t*\t0\t0\t#{$qseq}\t#{$qualseq}\tPG:Z:crossmatch\tAS:i:#{$score}\tNM:i:#{$tag_NM}\tH0:i:0\tMD:Z: \tXP:f:#{$psub}\tXD:f:#{$pdel}\tXI:f:#{$pins}\tXS:i:#{$tag_C}\n"
                else
                     #Perfect match
                     $tag_H0 = 1
                     $tag_MD = ""
                     cigar = ""
                     if $sposq > 1
                         #Soft clips in the beginning
                         temp = $sposq-1
                         cigar = temp.to_s + "S"
                         $tag_H0 = 0
                     end
                     temp = $eposq - $sposq + 1
                     if temp > 0
                         cigar << temp.to_s + "M"
                         $tag_MD = temp.to_s
                     end
                     if $nofbases > 0
                         #Soft clips in the end
                         $tag_H0 = 0
                         cigar << $nofbases.to_s + "S"
                     end
                     samWriter.print "#{$qname}\t#{$flag}\t#{$rname}\t#{$pos}\t0\t#{cigar}\t*\t0\t0\t#{$qseq}\t#{$qualseq}\tPG:Z:crossmatch\tAS:i:#{$score}\tNM:i:0\tH0:i:#{$tag_H0}\tMD:Z:#{$tag_MD}\tXP:f:#{$psub}\tXD:f:#{$pdel}\tXI:f:#{$pins}\tXS:i:#{$tag_C}\n"
                     #samWriter.print "#{$qname}\t#{$flag}\t#{$rname}\t#{$pos}\t0\t#{cigar}\t*\t0\t0\t#{$qseq}\t#{$qualseq}\tPG:Z:crossmatch\tAS:i:#{$score}\tNM:i:0\tH0:i:#{$tag_H0}\tMD:Z: \tXP:f:#{$psub}\tXD:f:#{$pdel}\tXI:f:#{$pins}\tXS:i:#{$tag_C}\n"
                end
            else
                $start=1
            end
            
            $num=0
            $num_id=0
            line.match($pattern)
            $score,$psub,$pdel,$pins,$qname,$sposq,$eposq,$nofbases,$compl,$rname,$pos1, $pos2, $unk,$sposr,$eposr =$1.to_i,$2.to_f,$3.to_f,$4.to_f,$5,$6.to_i,$7.to_i,$8.to_i,$9,$10,$11.to_i, $12.to_i, $13.to_i,$14.to_i,$15.to_i
            #puts "#{$score}\t#{psub}\t#{pdel}\t#{pins}\t#{$qname}\t#{$sposq}\t#{$eposq}\t#{$nofbases}\t#{$compl}\t#{$rname}\t#{$pos1}\t#{$pos2}\t#{unk}\t#{$sposr}\t#{$eposr}\n"
            $cur_refer = $rname
               
        elsif line=~ /^\s(\S+)\s+(\d+)\s+(\S+)\((\d+)\)\s+(\d+)\s+(\S+)/
          temp_type, qplace[$num], ntype[$num], nqual[$num], tplace[$num], nseq[$num] = $1, $2.to_i, $3, $4.to_i, $5.to_i, $6
          if temp_type =~ /^(\S+)\-(\d+)/
              type[$num] = $1
              type_num[$num] = $2.to_i
          else
              type[$num] = temp_type
              type_num[$num] = 1
          end
          $num = $num + 1
	                
        end
    end
    
    crossReader.close
    queryReader.close
    samWriter.close
    qualityReader.close
    referenceReader.close
end

end

#Main methods
optHash=Crossmatch2SAM.processArguments()
Crossmatch2SAMDeterminter=Crossmatch2SAM.new(optHash)
Crossmatch2SAMDeterminter.readcrossmatchwritesam()
exit(0);
