code: public Observable<CellAndDistance> calculateDistanceByCellFromFiles(Observable<File> files) {
          // use a map-reduce approach where the parallel method shares out
          // ('maps') the fixes by craft to multiple threads (number determined by
          // available processors) and is passed the 'reduce'
          // calculateDistanceByCellFromFile() method to combine the results.
          int numFiles = files.count().toBlocking().single();
          log.info("numFiles=" + numFiles);
          AtomicLong fileCount = new AtomicLong();
          AtomicLong cellCount = new AtomicLong(1);
          return files
                  // buffer for parallel processing of groups of files
                  .buffer(Math.max(1,
                          (int) Math.round(
                                  Math.ceil(numFiles / Runtime.getRuntime().availableProcessors()))))
                  .flatMap(fileList -> extractCellDistances(fileCount, cellCount, fileList))
                  // sum distances into global map
                  .collect(bigMapFactory(), collectCellDistances())
                  // report the cell distances for the grid
                  .flatMap(listCellDistances())
                  // record total nm in metrics
                  .doOnNext(sumNauticalMiles());
      }
docs: Returns distinct cells and the the total nautical miles travelled in that
  cell. Uses RxJava {@link Observable}s to maximize throughput and will
  scale to use all available processors and to handle a large number of
  files (number of open file handles should be limited by number of
  available processors).
  
  @param files
  @return