docs: def mergeNewMSBWT(mergedDir, inputBwtDirs, numProcs, logger):
      '''
      This function will take a list of input BWTs (compressed or not) and merge them into a single BWT
      @param mergedFN - the destination for the final merged MSBWT
      @param inputBWTFN1 - the fn of the first BWT to merge
      @param inputBWTFN2 - the fn of the second BWT to merge
      @param numProcs - number of processes we're allowed to use
      @param logger - output goes here
      '''
      st = time.time()
      iterst = time.time()
      vcLen = 6
      
      #TODO: take advantage of these to skip an iteration or two perhaps
      numInputs = len(inputBwtDirs)
      msbwts = [None]*numInputs
      mergedLength = 0
      for i, dirName in enumerate(inputBwtDirs):
          '''
          NOTE: in practice, since we're allowing for multiprocessing, we construct the FM-index for each input BWT
          simply because in the long run, this allows us to figure out how to start processing chunks separately.
          Without this, we would need to track extra information that really just represent the FM-index.
          '''
          msbwts[i] = MultiStringBWT.loadBWT(dirName, logger)
          mergedLength += msbwts[i].totalSize
      
      #binSize = 2**1#small bin debugging
      #binSize = 2**15#this one is just for test purposes, makes easy to debug things
      #binSize = 2**25#diff in 22-23 is not that much, 23-24 was 8 seconds of difference, so REALLY no diff
      binSize = 2**28
      
      #allocate the mergedBWT space
      logger.info('Allocating space on disk...')
      mergedBWT = np.lib.format.open_memmap(mergedDir+'/msbwt.npy', 'w+', '<u1', (mergedLength,))
      
      #this one will create the array using bits
      logger.info('Initializing iterations...')
      placeArray = np.lib.format.open_memmap(mergedDir+'/temp.0.npy', 'w+', '<u1', (mergedBWT.shape[0],))
      copiedPlaceArray = np.lib.format.open_memmap(mergedDir+'/temp.1.npy', 'w+', '<u1', (mergedBWT.shape[0],))
      start = msbwts[0].totalSize
      end = 0
      
      #fill out the initial array with 0s, 1s, 2s, etc. as our initial condition
      for i, msbwt in enumerate(msbwts):
          end += msbwt.getTotalSize()
          placeArray[start:end].fill(i)
          copiedPlaceArray[start:end].fill(i)
          start = end
      
      #create something to track the offsets
      #TODO: x/binSize + 1 makes one too many bins if it's exactly divisible by binSize, ex: 4 length BWT with binSize 2
      nextBinHasChanged = np.ones(dtype='b', shape=(mergedBWT.shape[0]/binSize+1,))
      prevOffsetCounts = np.zeros(dtype='<u8', shape=(mergedBWT.shape[0]/binSize+1, numInputs))
      currOffsetCounts = np.zeros(dtype='<u8', shape=(mergedBWT.shape[0]/binSize+1, numInputs))
      nextOffsetCounts = np.zeros(dtype='<u8', shape=(mergedBWT.shape[0]/binSize+1, numInputs))
      binUpdates = [{}]*(mergedBWT.shape[0]/binSize+1)
      
      bwtInd = 0
      offsets = [0]*numInputs
      for x in xrange(0, currOffsetCounts.shape[0]):
          #set, then change for next iter
          nextOffsetCounts[x] = offsets
          remaining = binSize
          while remaining > 0 and bwtInd < numInputs:
              if remaining > msbwts[bwtInd].totalSize-offsets[bwtInd]:
                  remaining -= msbwts[bwtInd].totalSize-offsets[bwtInd]
                  offsets[bwtInd] = msbwts[bwtInd].totalSize
                  bwtInd += 1
              else:
                  offsets[bwtInd] += remaining
                  remaining = 0
      
      ignored = 0
      
      #original
      sys.stdout.write('\rcp ')
      sys.stdout.flush()
          
      del copiedPlaceArray
      needsMoreIterations = True
      
      i = 0
      sameOffsetCount = 0
      while needsMoreIterations:
          prevOffsetCounts = currOffsetCounts
          currOffsetCounts = nextOffsetCounts
          nextOffsetCounts = np.zeros(dtype='<u8', shape=(mergedBWT.shape[0]/binSize+1, numInputs))
          needsMoreIterations = False
          sameOffsetCount = 0
          
          #this method uses a condensed byte and will ignore regions that are already finished
          sys.stdout.write('\rld ')
          sys.stdout.flush()
          ignored = 0
          
          iteret = time.time()
          sys.stdout.write('\r')
          logger.info('Finished iter '+str(i)+' in '+str(iteret-iterst)+'seconds')
          iterst = time.time()
          i += 1
          
          sys.stdout.write('\rld')
          sys.stdout.flush()
          
          #track which bins are actually different
          binHasChanged = nextBinHasChanged
          nextBinHasChanged = np.zeros(dtype='b', shape=(mergedBWT.shape[0]/binSize+1))
          
          tups = []
          
          for x in xrange(0, mergedBWT.shape[0]/binSize + 1):
              #check if the current offset matches the previous iteration offset
              sameOffset = np.array_equal(currOffsetCounts[x], prevOffsetCounts[x])
              
              if sameOffset:
                  sameOffsetCount += 1
              
              '''
              TODO: the below False is there because this only works if you do a full file copy right now.  It's
              because unless we copy, then the appropriate parts of the nextPlaceArray isn't properly updated. It's
              unclear whether one of these is better than the other in terms of performance.  File copying is slow, but
              if only a couple sequences are similar then then skipping is good.  I think in general, we only skip at the
              beginning for real data though, so I'm going with the no-skip, no-copy form until I can resolve the
              problem (if there's a resolution).
              '''
              if False and not binHasChanged[x] and sameOffset:
                  for key in binUpdates[x]:
                      nextOffsetCounts[key] += binUpdates[x][key]
                  ignored += 1
              else:
                  #note these are swapped depending on the iteration, saves time since there is no file copying
                  if i % 2 == 0:
                      tup = (x, binSize, vcLen, currOffsetCounts[x], mergedDir+'/temp.0.npy', mergedDir+'/temp.1.npy', inputBwtDirs)
                  else:
                      tup = (x, binSize, vcLen, currOffsetCounts[x], mergedDir+'/temp.1.npy', mergedDir+'/temp.0.npy', inputBwtDirs)
                  tups.append(tup)
          
          if numProcs > 1:
              #TODO: tinker with chunksize, it might matter
              myPool = multiprocessing.Pool(numProcs)
              #myPool = multiprocessing.pool.ThreadPool(numProcs)
              rets = myPool.imap(mergeNewMSBWTPoolCall, tups, chunksize=10)
          else:
              rets = []
              for tup in tups:
                  rets.append(mergeNewMSBWTPoolCall(tup))
          
          progressCounter = ignored
          sys.stdout.write('\r'+str(100*progressCounter*binSize/mergedBWT.shape[0])+'%')
          sys.stdout.flush()
              
          for ret in rets:
              #iterate through the returns so we can figure out information necessary for continuation
              (x, nBHC, nOC, nMI) = ret
              binUpdates[x] = nOC
              for k in nBHC:
                  nextBinHasChanged[k] |= nBHC[k]
              for b in nOC:
                  nextOffsetCounts[b] += nOC[b]
              needsMoreIterations |= nMI
              
              progressCounter += 1
              sys.stdout.write('\r'+str(min(100*progressCounter*binSize/mergedBWT.shape[0], 100))+'%')
              sys.stdout.flush()
          
          nextOffsetCounts = np.cumsum(nextOffsetCounts, axis=0)-nextOffsetCounts
          if numProcs > 1:
              myPool.terminate()
              myPool.join()
              myPool = None
          
      sys.stdout.write('\r')
      sys.stdout.flush()
      logger.info('Order solved, saving final array...')
      
      #TODO: make this better
      offsets = np.zeros(dtype='<u8', shape=(numInputs,))
      for i in xrange(0, mergedBWT.shape[0]/binSize+1):
          ind = placeArray[i*binSize:(i+1)*binSize]
          if i == mergedBWT.shape[0]/binSize:
              ind = ind[0:mergedBWT.shape[0]-i*binSize]
          
          bc = np.bincount(ind, minlength=numInputs)
          
          for x in xrange(0, numInputs):
              mergedBWT[np.add(i*binSize, np.where(ind == x))] = msbwts[x].getBWTRange(int(offsets[x]), int(offsets[x]+bc[x]))
          offsets += bc
          
      et = time.time()
      
      logger.info('Finished all merge iterations in '+str(et-st)+' seconds.')