Current encoding scheme uses 3 LSB for the letter and 5 MSB for a count, note that consecutive ones of the same character
    combine to create one large count.  So to represent 34A, you would have 00010|001 followed by 00001|001 which can be though of
    as 2*1 + 32*1 = 34
    @param inputFN - the filename of the BWT to compress
    @param outputFN - the destination filename for the compressed BWT, .npy format
    @param numProcs - number of processes to use during compressing
    @param logger - logger from initLogger()

def compressBWT(inputFN, outputFN, numProcs, logger):
    '''
    Current encoding scheme uses 3 LSB for the letter and 5 MSB for a count, note that consecutive ones of the same character
    combine to create one large count.  So to represent 34A, you would have 00010|001 followed by 00001|001 which can be though of
    as 2*1 + 32*1 = 34
    @param inputFN - the filename of the BWT to compress
    @param outputFN - the destination filename for the compressed BWT, .npy format
    @param numProcs - number of processes to use during compressing
    @param logger - logger from initLogger()
    '''
    #create bit spacings
    letterBits = 3
    numberBits = 8-letterBits
    numPower = 2**numberBits
    mask = 255 >> letterBits
    
    #load the thing to compress
    logger.info('Loading src file...')
    bwt = np.load(inputFN, 'r')
    logger.info('Original size:'+str(bwt.shape[0])+'B')
    numProcs = min(numProcs, bwt.shape[0])
    
    #first locate boundaries
    tups = []
    binSize = 1000000
    numBins = max(numProcs, bwt.shape[0]/binSize)
    
    for i in xrange(0, numBins):
        startIndex = i*bwt.shape[0]/numBins
        endIndex = (i+1)*bwt.shape[0]/numBins
        tempFN = outputFN+'.temp.'+str(i)+'.npy'
        tups.append((inputFN, startIndex, endIndex, tempFN))
    
    logger.info('Compressing bwt...')
    
    #run our multi-processed builder
    if numProcs > 1:
        myPool = multiprocessing.Pool(numProcs)
        rets = myPool.map(compressBWTPoolProcess, tups)
    else:
        rets = []
        for tup in tups:
            rets.append(compressBWTPoolProcess(tup))
    
    #calculate how big it will be after combining the separate chunk
    totalSize = 0
    prevChar = -1
    prevTotal = 0
    for ret in rets:
        #start by just adding the raw size
        totalSize += ret[0]
        
        #check if we need to compensate for a break point like AAA|A
        if prevChar == ret[1]:
            totalSize -= int(math.floor(math.log(prevTotal, numPower)+1)+math.floor(math.log(ret[2], numPower)+1))
            prevTotal += ret[2]
            totalSize += int(math.floor(math.log(prevTotal, numPower)+1))
            if ret[0] == 1:
                #don't clear prev total
                pass
            else:
                prevTotal = ret[4]
        else:
            prevTotal = ret[4]
        prevChar = ret[3]
    
    #make the real output by joining all of the partial compressions into a single file
    finalBWT = np.lib.format.open_memmap(outputFN, 'w+', '<u1', (totalSize,))
    logger.info('Calculated compressed size:'+str(totalSize)+'B')
    logger.info('Joining sub-compressions...')
    
    #iterate a second time, this time storing things
    prevChar = -1
    prevTotal = 0
    offset = 0
    for ret in rets:
        copyArr = np.load(ret[5], 'r')
        if prevChar == ret[1]:
            #calculate byte usage of combining
            prevBytes = int(math.floor(math.log(prevTotal, numPower)+1))
            nextBytes = int(math.floor(math.log(ret[2], numPower)+1))
            prevTotal += ret[2]
            
            #actually combine them
            offset -= prevBytes
            power = 0
            while prevTotal >= numPower**power:
                finalBWT[offset] = (((prevTotal / (numPower**power)) & mask) << letterBits)+prevChar
                power += 1
                offset += 1
            
            #copy over the extra stuff and calculate the new offset
            finalBWT[offset:offset+(copyArr.shape[0]-nextBytes)] = copyArr[nextBytes:]
            offset += (copyArr.shape[0] - nextBytes)
            
            if ret[0] == 1:
                pass
            else:
                prevTotal = ret[4]
            
        else:
            #nothing shared, just copy the easy way
            finalBWT[offset:offset+copyArr.shape[0]] = copyArr
            offset += copyArr.shape[0]
            prevTotal = ret[4]
            
        prevChar = ret[3]
        
    #clear all intermediate files
    for ret in rets:
        os.remove(ret[5])
    
    logger.info('Compression finished.')
    
    #return this i guess
    return finalBWT