This function does the grunt work behind string extraction for fastq files
    @param fastqFNs - a list of .fq filenames for parsing
    @param seqFNPrefix - this is always of the form '<DIR>/seqs.npy'
    @param offsetFN - this is always of the form '<DIR>/offsets.npy'
    @param abtFN - this is always of the form '<DIR>/about.npy'
    @param areUniform - True if all sequences are of uniform length
    @param logger - logger object for output

def preprocessFastqs(fastqFNs, seqFNPrefix, offsetFN, abtFN, areUniform, logger):
    '''
    This function does the grunt work behind string extraction for fastq files
    @param fastqFNs - a list of .fq filenames for parsing
    @param seqFNPrefix - this is always of the form '<DIR>/seqs.npy'
    @param offsetFN - this is always of the form '<DIR>/offsets.npy'
    @param abtFN - this is always of the form '<DIR>/about.npy'
    @param areUniform - True if all sequences are of uniform length
    @param logger - logger object for output 
    '''
    #create a seqArray
    seqArray = []
    
    tempFileId = 0
    seqsPerFile = 1000000
    maxSeqLen = -1
    numSeqs = 0
    
    subSortFNs = []
    
    for fnID, fn in enumerate(fastqFNs):
        #open the file and read in starting form the second, every 4th line
        logger.info('Loading \''+fn+'\'...')
        if fn.endswith('.gz'):
            fp = gzip.open(fn, 'r')
        else:
            fp = open(fn, 'r')
        i = -1
        
        #go through each line
        for line in fp:
            if i % 4 == 0:
                seqArray.append((line.strip('\n')+'$', fnID, i/4))
                if len(seqArray) == seqsPerFile:
                    if not areUniform or maxSeqLen == -1:
                        maxSeqLen = 0
                        for seq, fID, seqID in seqArray:
                            if len(seq) > maxSeqLen:
                                maxSeqLen = len(seq)
                    
                    tempFN = seqFNPrefix+'.sortTemp.'+str(tempFileId)+'.npy'
                    subSortFNs.append(tempFN)
                    
                    tempArray = np.lib.format.open_memmap(tempFN, 'w+', 'a'+str(maxSeqLen)+',<u1,<u8', (len(seqArray),))
                    tempArray[:] = sorted(seqArray)
                    numSeqs += len(seqArray)
                    del tempArray
                    tempFileId += 1
                    seqArray = []
            i += 1
                
        fp.close()
    
    if len(seqArray) > 0:
        if not areUniform or maxSeqLen == -1:
            maxSeqLen = 0
            for seq, fID, seqID in seqArray:
                if len(seq) > maxSeqLen:
                    maxSeqLen = len(seq)
        
        tempFN = seqFNPrefix+'.sortTemp.'+str(tempFileId)+'.npy'
        subSortFNs.append(tempFN)
        
        tempArray = np.lib.format.open_memmap(tempFN, 'w+', 'a'+str(maxSeqLen)+',<u1,<u8', (len(seqArray),))
        tempArray[:] = sorted(seqArray)
        numSeqs += len(seqArray)
        del tempArray
        tempFileId += 1
        seqArray = []
    
    logger.info('Pre-sorting '+str(numSeqs)+' sequences...')
    iters = []
    for fn in subSortFNs:
        iters.append(customiter(np.load(fn, 'r')))
    
    #save it
    tempFN = seqFNPrefix+'.temp.npy'
    fp = open(tempFN, 'w+')
    
    aboutFile = np.lib.format.open_memmap(abtFN, 'w+', '<u1,<u8', (numSeqs,))
    ind = 0
    
    for tup in heapq.merge(*iters):
        (seq, fID, seqID) = tup
        aboutFile[ind] = (fID, seqID)
        fp.write(seq)
        ind += 1
        
    fp.close()
    
    #clean up disk space
    for fn in subSortFNs:
        os.remove(fn)
    
    #convert the sequences into uint8s and then save it
    del seqArray
    seqArray = np.memmap(tempFN)
    
    if areUniform:
        uniformLength = maxSeqLen
    else:
        uniformLength = 0
    
    logger.info('Saving sorted sequences for BWT construction...')
    MSBWTGen.writeSeqsToFiles(seqArray, seqFNPrefix, offsetFN, uniformLength)
    
    #wipe this
    del seqArray
    os.remove(tempFN)