<commit_before>package de.davidm.textplots;

import com.google.common.base.Preconditions;
import org.apache.commons.math3.random.EmpiricalDistribution;
import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
import org.apache.commons.math3.util.Pair;

import java.util.ArrayList;
import java.util.List;

public class Histogram extends Plot {
    public static final int DEFAULT_NR_BINS = 10;
    public static final String CHARACTER_HISTOGRAM = "#";
    public static final String LEGEND_INTERVAL_LEFTBORDER = "[";
    public static final String LEGEND_INTERVAL_DIVISOR = ",";
    public static final String LEGEND_INTERVAL_RIGHTBORDER = ")";

    private final Pair<String, double[]> data;
    private final EmpiricalDistribution dist;
    private final int width;
    private final int bins;

    private Histogram(HistogramBuilder histogramBuilder){
        this.data = histogramBuilder.data;
        this.width = histogramBuilder.width;
        this.bins = histogramBuilder.bins;

        // Create a distribution of data for bins number of bins
        dist = new EmpiricalDistribution(bins);
        dist.load(data.getSecond());
    }

    public static class HistogramBuilder {

        Pair<String, double[]> data;
        int bins = DEFAULT_NR_BINS;
        int width = DEFAULT_WIDTH;

        public HistogramBuilder(Pair<String, double[]> data){
            this.data = data;
        }

        /**
         * @param bins number of bins in histogram
         * @return
         */
        public HistogramBuilder setBinNumber(int bins){
            this.bins = bins;
            return this;
        }

        /**
         * @param width width of plots - attention: additional width is added by names and table formatting
         * @return
         */
        public HistogramBuilder setWidth(int width){
            this.width = width;
            return this;
        }

        /**
         * @return a Histogram object with user settings
         */
        public Histogram plotObject(){
            // Check for correct width
            Preconditions.checkState(width >= MIN_WIDTH && width <= MAX_WIDTH,
                    "Width is set to " + width + " but needs to be in " + "[" + MIN_WIDTH + "," + MAX_WIDTH + "]");
            return new Histogram(this);
        }
    }

    /**
     * Print the Histogram to command line
     *
     * @param printLegend switch legend on/off
     */
    @Override
    public String plot(boolean printLegend) {
        String out = "";

        // Create the histogram out of given distribution
        List<Pair<double[], String>> plot = histogram();
        List<SummaryStatistics> bounds = dist.getBinStats();
        long N = dist.getSampleStats().getN();

        // Get the length of the longest bin interval string
        int maxLengthLeft = 0;
        if(printLegend) {
            for(Pair<double[], String> row : plot){
                int length = intervalString(row.getFirst()[0], row.getFirst()[1]).length();
                maxLengthLeft = Math.max(maxLengthLeft, length);
            }
        }

        // Add rows
        int rowCount = 0;
        for (Pair<double[], String> row : plot) {
            String line = "";

            // Add a legend to the left
            if (printLegend) {
                String interval = intervalString(row.getFirst()[0], row.getFirst()[1]);
                line += interval;
                // Fill in case of smaller interval strings
                for (int i = interval.length(); i < maxLengthLeft; i++) {
                    line += CHARACTER_EMPTY_BIN;
                }
                line += CHARACTER_COLUMN_DIVISOR;
            }
            line += row.getSecond();

            // Add bin count to the right
            if (printLegend) {
                line += CHARACTER_COLUMN_DIVISOR;
                line += "n=";
                long n = bounds.get(rowCount).getN();
                // Add spaces for right-alignment
                for (int i = String.valueOf(n).length(); i < String.valueOf(N).length(); i++) {
                    line += CHARACTER_EMPTY_BIN;
                }
                line += n;
            }
            out += line + "\n";
            rowCount++;
        }

        // Write x axis labelling under plot
        if(printLegend) {
            String line = "";
            for (int i = 0; i < maxLengthLeft; i++) {
               line += CHARACTER_EMPTY_BIN;
            }
            line += CHARACTER_COLUMN_DIVISOR;
            line += "0%";
            for (int i = 0; i < width - 6; i++) {
                line += CHARACTER_EMPTY_BIN;
            }
            line +=  "100%";
            line += CHARACTER_COLUMN_DIVISOR;
            out += line + "\n";
        }

        return out;
    }

    /**
     * @param left left value for interval (inclusive)
     * @param right right value for interval (exclusive)
     * @return a string representation of an interval for a bin in the histogram
     */
    protected String intervalString(double left, double right){
        return (LEGEND_INTERVAL_LEFTBORDER +<commit_msg>fixing interval naming<commit_after>package de.davidm.textplots;

import com.google.common.base.Preconditions;
import org.apache.commons.math3.random.EmpiricalDistribution;
import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
import org.apache.commons.math3.util.Pair;

import java.util.ArrayList;
import java.util.List;

public class Histogram extends Plot {
    public static final int DEFAULT_NR_BINS = 10;
    public static final String CHARACTER_HISTOGRAM = "#";
    public static final String LEGEND_INTERVAL_LEFTBORDER_FIRST = "[";
    public static final String LEGEND_INTERVAL_LEFTBORDER = "(";
    public static final String LEGEND_INTERVAL_DIVISOR = ",";
    public static final String LEGEND_INTERVAL_RIGHTBORDER = "]";

    private final Pair<String, double[]> data;
    private final EmpiricalDistribution dist;
    private final int width;
    private final int bins;

    private Histogram(HistogramBuilder histogramBuilder){
        this.data = histogramBuilder.data;
        this.width = histogramBuilder.width;
        this.bins = histogramBuilder.bins;

        // Create a distribution of data for bins number of bins
        dist = new EmpiricalDistribution(bins);
        dist.load(data.getSecond());
    }

    public static class HistogramBuilder {

        Pair<String, double[]> data;
        int bins = DEFAULT_NR_BINS;
        int width = DEFAULT_WIDTH;

        public HistogramBuilder(Pair<String, double[]> data){
            this.data = data;
        }

        /**
         * @param bins number of bins in histogram
         * @return
         */
        public HistogramBuilder setBinNumber(int bins){
            this.bins = bins;
            return this;
        }

        /**
         * @param width width of plots - attention: additional width is added by names and table formatting
         * @return
         */
        public HistogramBuilder setWidth(int width){
            this.width = width;
            return this;
        }

        /**
         * @return a Histogram object with user settings
         */
        public Histogram plotObject(){
            // Check for correct width
            Preconditions.checkState(width >= MIN_WIDTH && width <= MAX_WIDTH,
                    "Width is set to " + width + " but needs to be in " + "[" + MIN_WIDTH + "," + MAX_WIDTH + "]");
            return new Histogram(this);
        }
    }

    /**
     * Print the Histogram to command line
     *
     * @param printLegend switch legend on/off
     */
    @Override
    public String plot(boolean printLegend) {
        String out = "";

        // Create the histogram out of given distribution
        List<Pair<double[], String>> plot = histogram();
        List<SummaryStatistics> bounds = dist.getBinStats();
        long N = dist.getSampleStats().getN();

        // Get the length of the longest bin interval string
        int maxLengthLeft = 0;
        if(printLegend) {
            for(Pair<double[], String> row : plot){
                int length1 = intervalString(false, row.getFirst()[0], row.getFirst()[1]).length();
                int length2 = intervalString(true, row.getFirst()[0], row.getFirst()[1]).length();
                maxLengthLeft = Math.max(maxLengthLeft, Math.max(length1, length2));
            }
        }

        // Add rows
        int rowCount = 0;
        for (Pair<double[], String> row : plot) {
            String line = "";

            // Add a legend to the left
            if (printLegend) {
                String interval = intervalString(rowCount == 0 ? true : false, row.getFirst()[0], row.getFirst()[1]);
                line += interval;
                // Fill in case of smaller interval strings
                for (int i = interval.length(); i < maxLengthLeft; i++) {
                    line += CHARACTER_EMPTY_BIN;
                }
                line += CHARACTER_COLUMN_DIVISOR;
            }
            line += row.getSecond();

            // Add bin count to the right
            if (printLegend) {
                line += CHARACTER_COLUMN_DIVISOR;
                line += "n=";
                long n = bounds.get(rowCount).getN();
                // Add spaces for right-alignment
                for (int i = String.valueOf(n).length(); i < String.valueOf(N).length(); i++) {
                    line += CHARACTER_EMPTY_BIN;
                }
                line += n;
            }
            out += line + "\n";
            rowCount++;
        }

        // Write x axis labelling under plot
        if(printLegend) {
            String line = "";
            for (int i = 0; i < maxLengthLeft; i++) {
               line += CHARACTER_EMPTY_BIN;
            }
            line += CHARACTER_COLUMN_DIVISOR;
            line += "0%";
            for (int i = 0; i < width - 6; i++) {
                line += CHARACTER_EMPTY_BIN;
            }
            line +=  "100%";
            line += CHARACTER_COLUMN_DIVISOR;
            out += line + "\n";
        }

        return out;
    }

    /**
     * @param left left value for interval (inclusive)
     * @param right right value for interval (exclusive)
     *
     * @return a string representation of an interval for a bin in the histogram
     */
    protected String intervalString(boolean first, double left, double right){
        return (
                (first ? LEGEND_INTERVAL_LEFTBORDER_FIRST : LEGEND_INTERVAL_LEFTBORDER) +
{'fraction_non_alphanumeric': 0.10069345492542985, 'fraction_numerical': 0.004084734492258003, 'mean_word_length': 1.8210075026795285, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3624696', 'n_tokens_mistral': 2915, 'n_tokens_neox': 2756, 'n_words': 806}