docs: public <SignatureType> BrokenDownProvenancedConfusionMatrix<SignatureType, CellFiller>
    breakdown(Function<? super CellFiller, SignatureType> signatureFunction,
        Ordering<SignatureType> keyOrdering) {
      final Map<SignatureType, Builder<CellFiller>> ret = Maps.newHashMap();
  
      // a more efficient implementation should be used if the confusion matrix is
      // large and sparse, but this is unlikely. ~ rgabbard
      for (final Symbol leftLabel : leftLabels()) {
        for (final Symbol rightLabel : rightLabels()) {
          for (final CellFiller provenance : cell(leftLabel, rightLabel)) {
            final SignatureType signature = signatureFunction.apply(provenance);
            checkNotNull(signature, "Provenance function may never return null");
            if (!ret.containsKey(signature)) {
              ret.put(signature, ProvenancedConfusionMatrix.<CellFiller>builder());
            }
            ret.get(signature).record(leftLabel, rightLabel, provenance);
          }
        }
      }
  
      final ImmutableMap.Builder<SignatureType, ProvenancedConfusionMatrix<CellFiller>> trueRet =
          ImmutableMap.builder();
      // to get consistent output, we make sure to sort by the keys
      for (final Map.Entry<SignatureType, Builder<CellFiller>> entry :
          MapUtils.<SignatureType, Builder<CellFiller>>byKeyOrdering(keyOrdering).sortedCopy(
              ret.entrySet())) {
        trueRet.put(entry.getKey(), entry.getValue().build());
      }
      return BrokenDownProvenancedConfusionMatrix.fromMap(trueRet.build());
    }