# Path: nanopore/mappers/abstractMapper.py
# class AbstractMapper(Target):
#     """Base class for mappers. Inherit this class to create a mapper
#     """
#     def __init__(self, readFastqFile, readType, referenceFastaFile, outputSamFile, emptyHmmFile=None):
#         Target.__init__(self)
#         self.readFastqFile = readFastqFile
#         self.referenceFastaFile = referenceFastaFile
#         self.outputSamFile = outputSamFile
#         self.readType = readType
#         self.emptyHmmFile=emptyHmmFile
#         
#     def chainSamFile(self):
#         """Converts the sam file so that there is at most one global alignment of each read
#         """ 
#         tempSamFile = os.path.join(self.getLocalTempDir(), "temp.sam")
#         system("cp %s %s" % (self.outputSamFile, tempSamFile))
#         chainSamFile(tempSamFile, self.outputSamFile, self.readFastqFile, self.referenceFastaFile)
#     
#     def realignSamFile(self, gapGamma=0.5, matchGamma=0.0, doEm=False,  useTrainedModel=False, trainedModelFile="blasr_hmm_0.txt"):
#         """Chains and then realigns the resulting global alignments.
#         """
#         tempSamFile = os.path.join(self.getGlobalTempDir(), "temp.sam")
#         if useTrainedModel and doEm:
#             raise RuntimeError("Attempting to train stock model")
#         system("cp %s %s" % (self.outputSamFile, tempSamFile))
#         if doEm:
#             hmmFile = self.emptyHmmFile
#         elif useTrainedModel:
#             hmmFile = os.path.join(pathToBaseNanoporeDir(), "nanopore", "mappers", trainedModelFile)
#         else:
#             hmmFile = None
#         self.addChildTargetFn(realignSamFileTargetFn, args=(tempSamFile, self.outputSamFile, 
#                                                             self.readFastqFile, self.referenceFastaFile, gapGamma, matchGamma, hmmFile, doEm))
# 
# Path: nanopore/analyses/utils.py
# def getFastqDictionary(fastqFile):
#     """Returns a dictionary of the first words of fastq headers to their corresponding fastq sequence
#     """
#     names = map(lambda x : x[0].split()[0], fastqRead(open(fastqFile, 'r')))
#     assert len(names) == len(set(names)) #Check all the names are unique
#     return dict(map(lambda x : (x[0].split()[0], x[1]), fastqRead(open(fastqFile, 'r')))) #Hash of names to sequences


from nanopore.mappers.abstractMapper import AbstractMapper
from nanopore.analyses.utils import getFastqDictionary
from sonLib.bioio import system
import os
import pysam
    def run(self, args=""):
        tempSamFile = os.path.join(self.getLocalTempDir(), "temp.sam")
        system("blasr %s %s -sam -clipping hard %s > %s" % (self.readFastqFile, self.referenceFastaFile, args, tempSamFile))
        #Blasr seems to corrupt the names of read sequences, so lets correct them.
        sam = pysam.Samfile(tempSamFile, "r" )
        outputSam = pysam.Samfile(self.outputSamFile, "wh", template=sam)
        readSequences = getFastqDictionary(self.readFastqFile) #Hash of names to sequences
        for aR in sam: #Iterate on the sam lines and put into buckets by read
            if aR.qname not in readSequences:
                newName = '/'.join(aR.qname.split('/')[:-1])
                if newName not in readSequences:
                    raise RuntimeError("Tried to deduce correct read name: %s, %s" % (newName, readSequences.keys()))
                aR.qname = newName
            outputSam.write(aR)
        outputSam.close()
        

class BlasrChain(Blasr):
    def run(self):
        Blasr.run(self)
        self.chainSamFile()

class BlasrRealign(Blasr):
    def run(self):
        Blasr.run(self)
        self.realignSamFile()

class BlasrRealignEm(Blasr):
    def run(self):
        Blasr.run(self)

# Path: nanopore/mappers/abstractMapper.py
# class AbstractMapper(Target):
#     """Base class for mappers. Inherit this class to create a mapper
#     """
#     def __init__(self, readFastqFile, readType, referenceFastaFile, outputSamFile, emptyHmmFile=None):
#         Target.__init__(self)
#         self.readFastqFile = readFastqFile
#         self.referenceFastaFile = referenceFastaFile
#         self.outputSamFile = outputSamFile
#         self.readType = readType
#         self.emptyHmmFile=emptyHmmFile
#         
#     def chainSamFile(self):
#         """Converts the sam file so that there is at most one global alignment of each read
#         """ 
#         tempSamFile = os.path.join(self.getLocalTempDir(), "temp.sam")
#         system("cp %s %s" % (self.outputSamFile, tempSamFile))
#         chainSamFile(tempSamFile, self.outputSamFile, self.readFastqFile, self.referenceFastaFile)
#     
#     def realignSamFile(self, gapGamma=0.5, matchGamma=0.0, doEm=False,  useTrainedModel=False, trainedModelFile="blasr_hmm_0.txt"):
#         """Chains and then realigns the resulting global alignments.
#         """
#         tempSamFile = os.path.join(self.getGlobalTempDir(), "temp.sam")
#         if useTrainedModel and doEm:
#             raise RuntimeError("Attempting to train stock model")
#         system("cp %s %s" % (self.outputSamFile, tempSamFile))
#         if doEm:
#             hmmFile = self.emptyHmmFile
#         elif useTrainedModel:
#             hmmFile = os.path.join(pathToBaseNanoporeDir(), "nanopore", "mappers", trainedModelFile)
#         else:
#             hmmFile = None
#         self.addChildTargetFn(realignSamFileTargetFn, args=(tempSamFile, self.outputSamFile, 
#                                                             self.readFastqFile, self.referenceFastaFile, gapGamma, matchGamma, hmmFile, doEm))
# 
# Path: nanopore/analyses/utils.py
# def getFastqDictionary(fastqFile):
#     """Returns a dictionary of the first words of fastq headers to their corresponding fastq sequence
#     """
#     names = map(lambda x : x[0].split()[0], fastqRead(open(fastqFile, 'r')))
#     assert len(names) == len(set(names)) #Check all the names are unique
#     return dict(map(lambda x : (x[0].split()[0], x[1]), fastqRead(open(fastqFile, 'r')))) #Hash of names to sequences


# Path: nanopore/mappers/blasr.py
from nanopore.mappers.abstractMapper import AbstractMapper
from nanopore.analyses.utils import getFastqDictionary
from sonLib.bioio import system
import os
import pysam

    def run(self, args=""):
        tempSamFile = os.path.join(self.getLocalTempDir(), "temp.sam")
        system("blasr %s %s -sam -clipping hard %s > %s" % (self.readFastqFile, self.referenceFastaFile, args, tempSamFile))
        #Blasr seems to corrupt the names of read sequences, so lets correct them.
        sam = pysam.Samfile(tempSamFile, "r" )
        outputSam = pysam.Samfile(self.outputSamFile, "wh", template=sam)
        readSequences = getFastqDictionary(self.readFastqFile) #Hash of names to sequences
        for aR in sam: #Iterate on the sam lines and put into buckets by read
            if aR.qname not in readSequences:
                newName = '/'.join(aR.qname.split('/')[:-1])
                if newName not in readSequences:
                    raise RuntimeError("Tried to deduce correct read name: %s, %s" % (newName, readSequences.keys()))
                aR.qname = newName
            outputSam.write(aR)
        outputSam.close()
        

class BlasrChain(Blasr):
    def run(self):
        Blasr.run(self)
        self.chainSamFile()

class BlasrRealign(Blasr):
    def run(self):
        Blasr.run(self)
        self.realignSamFile()

class BlasrRealignEm(Blasr):
    def run(self):
        Blasr.run(self)

        self.realignSamFile(doEm=True)