docs: public void writeBootstrapData(String name,
        ImmutableMap<String, ImmutableListMultimap<String, Double>> measuresToBreakdownsToStats,
        File outputDir) throws IOException {
      final StringBuilder chart = new StringBuilder();
      final StringBuilder delim = new StringBuilder();
      final StringBuilder mediansDelim = new StringBuilder();
  
      final ImmutableSet<String> breakdownKeys =
          MapUtils.allMultimapKeys(measuresToBreakdownsToStats.values());
  
      // Set up chart title, delimited file headers
      chart.append(name).append("\n\n");
      addDelimPercentileHeader(name, delim);
      addDelimMediansHeader(name, measures(), mediansDelim);
  
      final ImmutableMap.Builder<String, ImmutableMap<String, ImmutableList<Double>>> samples =
          ImmutableMap.builder();
  
      final File bootstrapDataDir = new File(outputDir, "bootstrapData");
      bootstrapDataDir.mkdirs();
  
      // all four multimaps have the same keyset
      for (final String breakdownKey : breakdownKeys) {
        final ImmutableMap.Builder<String, Double> mediansMapBuilder =
            ImmutableMap.builder();
  
        final ImmutableMap.Builder<String, PercentileComputer.Percentiles> percentileMapB = ImmutableMap.builder();
        final ImmutableMap.Builder<String, ImmutableList<Double>> keySamples =
            ImmutableMap.builder();
  
        for (final Map.Entry<String, ImmutableListMultimap<String, Double>> e : measuresToBreakdownsToStats
            .entrySet()) {
          final String measureName = e.getKey();
          final ImmutableList<Double> samplesForBreakdownKey = e.getValue().get(breakdownKey);
          final PercentileComputer.Percentiles percentiles =
              percentileComputer().calculatePercentilesAdoptingData(
                  Doubles.toArray(samplesForBreakdownKey));
          percentileMapB.put(measureName, percentiles);
  
          // Raw samples
          keySamples.put(measureName, samplesForBreakdownKey);
  
          // Aggregate medians
          mediansMapBuilder.put(measureName, percentiles.median().or(Double.NaN));
        }
  
        // Write to chart
        final ImmutableMap<String, PercentileComputer.Percentiles> percentilesMap = percentileMapB.build();
        dumpPercentilesForMetric(breakdownKey, percentilesMap, chart);
        chart.append("\n");
  
        final JacksonSerializer serializer = JacksonSerializer.builder().forJson().prettyOutput().build();
        serializer.serializeTo(new SerializedBootstrapResults.Builder()
            .percentilesMap(percentilesMap).build(), Files.asByteSink(new File(bootstrapDataDir,
            breakdownKey + ".percentile.json")));
  
        // Write to delim
        addDelimPercentilesForMetric(breakdownKey, percentilesMap, delim);
        addMediansRow(breakdownKey, mediansMapBuilder.build(), mediansDelim);
      }
  
      // Make output dir as needed
      outputDir.mkdir();
  
      // Write chart
      Files.asCharSink(new File(outputDir, name + ".bootstrapped.txt"),
          Charsets.UTF_8).write(chart.toString());
      // Write delim
      Files.asCharSink(new File(outputDir, name + ".bootstrapped.csv"),
          Charsets.UTF_8).write(delim.toString());
      // Write means-only delimited
      Files.asCharSink(new File(outputDir, name + ".bootstrapped.medians.csv"),
          Charsets.UTF_8).write(mediansDelim.toString());
      // Write raw data
      Files.asCharSink(new File(outputDir, name + ".bootstrapped.raw"),
          Charsets.UTF_8).write(renderSamples(samples.build()));
    }