def build_histogram(values, fhand, bins=10, range_=None, stacked=False,
                    color=None, label=None, log=False, **kwargs):
    'It draws a histogram of a pandas Series into a file'
    canvas, axes = get_canvas_and_axes()
    plot_format = _guess_output_for_matplotlib(fhand)
    if color is None:
        if label is None:
            axes.hist(values, bins=bins, range=range_, stacked=stacked,
                      log=log)
        else:
            axes.hist(values, bins=bins, range=range_, stacked=stacked,
                      label=label, log=log)
    else:
        axes.hist(values, bins=bins, range=range_, stacked=stacked,
                  label=label, color=color, log=log)
    for key, value in kwargs.items():
        getattr(axes, 'set_{}'.format(key))(value)
    if label is not None:
        axes.legend()

    canvas.print_figure(fhand, format=plot_format)
    fhand.flush() def draw_scatter(groups, fhand, plot_lines=False, **kwargs):
    # groups is a list of x,y and color_intensity
    canvas, axes = get_canvas_and_axes()
    plot_format = _guess_output_for_matplotlib(fhand)

    for key, value in kwargs.items():
        getattr(axes, 'set_{}'.format(key))(value)

    for index, group in enumerate(groups):
        x_vals = group['x']
        y_vals = group['y']
        sct_kwargs = {}
        sct_kwargs['marker'] = MARKERGLHYPS[index]
        # TODO. Review the API for the colors.
        # The following cases should be posible for color/value:
        #    - a tuple RGB
        #    - nothing. It has to chose one color by default
        #    - a string: 'blue', 'green', etc.
        #    - a list of numbers (intensities) and ColorMap
        # A possible option could be:
        # group['color] for anything that matplotlib could digest for a single
        # color: RGB tuple or string.
        # group['color_intensities'] for the values of the color. In this case
        # a color map should be given or a default one should be used.
        # In this is used 'color' and 'color_intensities' should be
        # incompatible
        # What about plot_lines? That should be incompatible with
        # color_intensities
        color = group.get('color', COLORS[index])
        if 'color_intensity' in group:
            # value is a list with color intensities
            sct_kwargs['c'] = group['color_intensity']
            sct_kwargs['norm'] = colors.Normalize()
            sct_kwargs['cmap'] = cm.get_cmap(COLORMAPS[index])
            sct_kwargs['s'] = 50
            sct_kwargs['alpha'] = 0.5
            sct_kwargs['edgecolor'] = 'white'
        else:
            sct_kwargs['c'] = color

        if plot_lines:
            sct_kwargs['ms'] = MARKER_SIZE3
            sct_kwargs['mec'] = color
            sct_kwargs['mfc'] = color
            axes.plot(x_vals, y_vals, **sct_kwargs)
        else:
            sct_kwargs['s'] = MARKER_SIZE2
            axes.scatter(x_vals, y_vals, **sct_kwargs)

    canvas.print_figure(fhand, format=plot_format)
    fhand.flush() def draw_density_plot(xs, ys, fhand=None, n_bins=40, canvas=None, axes=None,
                      range_=None, **kwargs):
    plot_format = _guess_output_for_matplotlib(fhand)
    if canvas is None and axes is None:
        canvas, axes = get_canvas_and_axes()
        using_given_axes = False
    elif canvas is not None and axes is not None and fhand is None:
        using_given_axes = True
    else:
        msg = 'If an axes is given the canvas is also required and no fhand'
        raise NotImplementedError(msg)

    for key, value in kwargs.items():
        getattr(axes, 'set_{}'.format(key))(value)

    # TODO check with norm=LogNorm() and/or normed=True
    if range_ is None:
        axes.hist2d(xs, ys, bins=n_bins)
    else:
        axes.hist2d(xs, ys, bins=n_bins, range=range_)

    if not using_given_axes:
        canvas.print_figure(fhand, format=plot_format)
        fhand.flush() def draw_histogram_in_fhand(counts, bin_limits, title=None, xlabel=None,
                            ylabel=None, fhand=None, kind=BAR, ylimits=None):
    'It draws an histogram and if the fhand is given it saves it'
    plot_format = _guess_output_for_matplotlib(fhand)
    canvas, axes = get_canvas_and_axes(figure_size=FIGURE_SIZE, left=0.1,
                                       right=0.9, top=0.9, bottom=0.1)
    draw_histogram_in_axes(counts, bin_limits, axes=axes, title=title,
                           xlabel=xlabel, ylabel=ylabel, kind=kind,
                           ylimits=ylimits)

    canvas.print_figure(fhand, format=plot_format)
    fhand.flush() def draw_histogram_in_axes(counts, bin_limits, kind=BAR, axes=None, title=None,
                           xlabel=None, ylabel=None, distrib_label=None,
                           linestyle=None, ylimits=None):

    if axes is None:
        canvas, axes = get_canvas_and_axes(figure_size=FIGURE_SIZE, left=0.1,
                                           right=0.9, top=0.9, bottom=0.1)
    else:
        canvas = None

    if xlabel:
        axes.set_xlabel(xlabel)
    if ylabel:
        axes.set_ylabel(ylabel)
    if title:
        axes.set_title(title)

    if kind == BAR:
        xvalues = range(len(counts))
        axes.bar(xvalues, counts)

        # the x axis label
        xticks_pos = [value + 0.5 for value in xvalues]

        left_val = None
        right_val = None
        xticks_labels = []
        for value in bin_limits:
            right_val = value
            if left_val:
                xticks_label = (left_val + right_val) / 2.0
                if xticks_label >= 10:
                    fmt = '%d'
                elif xticks_label >= 0.1 and xticks_label < 10:
                    fmt = '%.1f'
                elif xticks_label < 0.1:
                    fmt = '%.1e'
                xticks_label = fmt % xticks_label
                xticks_labels.append(xticks_label)
            left_val = right_val

        # we don't want to clutter the plot
        num_of_xlabels = 15
        step = int(len(counts) / float(num_of_xlabels))
        step = 1 if step == 0 else step
        xticks_pos = xticks_pos[::step]
        xticks_labels = xticks_labels[::step]
        axes.set_xticks(xticks_pos)
        axes.set_xticklabels(xticks_labels)
    elif LINE:
        kwargs = {}
        if distrib_label is not None:
            kwargs['label'] = distrib_label
        if linestyle is not None:
            kwargs['linestyle'] = linestyle

        x_values = []
        for index, i in enumerate(bin_limits):
            try:
                i2 = bin_limits[index + 1]
            except IndexError:
                break
            x_values.append((i + i2) / 2.0)
        y_values = counts
        axes.plot(x_values, y_values, **kwargs)

    if ylimits is not None:
        axes.set_ylim(ylimits)

    return axes, canvas LINE = 'line' def draw_histograms(counters, fhand, distrib_labels=None, num_cols=2,
                    plots_per_chart=3, xlabel=None, ylabel=None, titles=None,
                    kind=LINE, xmax=None, xmin=None, linestyles=None,
                    ylimits=None):
    if plots_per_chart > 1 and kind == BAR:
        raise ValueError('if kind is BAR only one plot per chart is allowed')

    plot_format = _guess_output_for_matplotlib(fhand)
    num_plots, mod = divmod(len(counters), plots_per_chart)
    if mod != 0:
        num_plots += 1

    num_rows, mod = divmod(num_plots, num_cols)
    if mod != 0:
        num_rows += 1
    fig, canvas = get_fig_and_canvas(num_rows=num_rows, num_cols=num_cols)

    counter_index = 0
    for plot_num in range(1, num_plots + 1):
        axes = fig.add_subplot(num_rows, num_cols, plot_num)
        for i in range(plots_per_chart):
            try:
                counter = counters[counter_index]
                if distrib_labels is None:
                    distrib_label = None
                else:
                    distrib_label = distrib_labels[counter_index]
                if linestyles is None:
                    linestyle = None
                else:
                    linestyle = linestyles[counter_index]
            except IndexError:
                break
            title = titles[counter_index] if titles else None
            try:
                distrib = counter.calculate_distribution(max_=xmax,
                                                         min_=xmin)
            except RuntimeError:
                axes.set_title(title + ' (NO DATA)')
                counter_index += 1
                continue
            except AttributeError as error:
                # if distributions is None
                err_msg = "'NoneType' object has no attribute "
                err_msg += "'calculate_distribution'"
                if err_msg in error:
                    axes.set_title(title + ' (NO DATA)')
                    counter_index += 1
                    continue
                raise
            title = titles[counter_index] if titles else None
            draw_histogram_in_axes(distrib['counts'], distrib['bin_limits'],
                                   kind=kind, axes=axes, ylabel=ylabel,
                                   distrib_label=distrib_label, xlabel=xlabel,
                                   title=title, linestyle=linestyle,
                                   ylimits=ylimits)
            counter_index += 1

        if distrib_labels is not None:
            axes.legend()

    canvas.print_figure(fhand, format=plot_format)
    fhand.flush() def draw_int_boxplot(boxplot, fhand=None, axes=None, title=None,
                     xlabel=None, ylabel=None):

    if axes is None:
        canvas, axes = get_canvas_and_axes()
        using_given_axes = False
    elif fhand is None:
        using_given_axes = True
    else:
        msg = 'If an axes is not given the fhand also required'
        raise NotImplementedError(msg)

    bar_width = 0.8

    x_vals = sorted(boxplot.counts.keys())

    # for the following line to work we would have to create all points in
    # memory, this is why we have reimplemented the boxplot
    # axes.boxplot([list(boxplot.counts[x_val].elements()) for x_val in x_vals]

    # we don't want more than 50 bars
    max_n_boxes = 40
    n_boxes = len(x_vals) - 1
    xpurge = n_boxes // max_n_boxes + 1

    xticks_lables = []
    xticks = []
    xpos = []
    for index, x_val in enumerate(x_vals):
        xpos.append(index + 0.5)
        if index % xpurge != 0:
            continue

        xticks_lables.append(str(x_val))
        # we add 0.5 to have the x ticks in  the
        # middle of the bar
        xticks.append(index + 0.5)

        intcounter = boxplot.counts[x_val]
        if intcounter.count < 5:
            # at least for values are required to calculate the qualties
            continue
        quart = intcounter.quartiles
        min_ = intcounter.min
        max_ = intcounter.max
        axes.bar(index + 0.5, quart[2] - quart[0], bottom=quart[0],
                 width=bar_width, facecolor='none', align='center')
        # median
        axes.plot([index + 0.5 - bar_width / 2, index + 0.5 + bar_width / 2],
                  [quart[1], quart[1]], color='red')
        # max
        axes.plot([index + 0.5 - bar_width / 4, index + 0.5 + bar_width / 4],
                  [max_, max_], color='black')
        axes.plot([index + 0.5, index + 0.5], [quart[0], min_], '--',
                  color='black')
        axes.plot([index + 0.5 - bar_width / 4, index + 0.5 + bar_width / 4],
                  [min_, min_], color='black')
        axes.plot([index + 0.5, index + 0.5], [quart[2], max_], '--',
                  color='black')

    max_x = len(x_vals) - 1
    axes.set_xlim(0, max_x + 1)

    axes.set_xticks(xticks)
    axes.set_xticklabels(xticks_lables)

    if title:
        axes.set_title(title)
    if xlabel:
        axes.set_xlabel(xlabel)
    if ylabel:
        axes.set_ylabel(ylabel)

    if not using_given_axes:
        canvas.print_figure(fhand)
        fhand.flush()
    return x_vals, xpos, xticks, xticks_lables class IntCounter(Counter):
    '''This is a subclass  of the Counter on python collections.

    It adds some statistical functionalities to the class'''

    def __init__(self, *args, **kwargs):
        'It inialices a '
        super(IntCounter, self).__init__(*args, **kwargs)
        self.labels = LABELS.copy()

    @property
    def min(self):
        'Get the minimun value'
        return min(self.keys())

    @property
    def max(self):
        'Get the maximun value'
        return max(self.keys())

    @property
    def count(self):
        'It returns the count of the values stored in the array'
        return sum(self.values())

    @property
    def median(self):
        'It calculates the median of the values appended'
        quotient, remainder = divmod(self.count, 2)
        if remainder == 0:
            val1 = self._get_value_for_index(quotient - 1)
            val2 = self._get_value_for_index(quotient)
            return (val1 + val2) / 2
        else:
            return self._get_value_for_index(quotient)

    @property
    def sum(self):
        'It gets the sum of the values'
        sum_ = 0
        for index, value in self.items():
            sum_ += (index * value)
        return int(sum_)

    @property
    def average(self):
        'It calculates the average'
        count = self.count
        sum_ = self.sum
        return sum_ / count

    @property
    def variance(self):
        'It gets the variance of the values'
        mean = self.average
        sum_ = 0
        for index, counts in self.items():
            sum_ += ((index - mean) ** 2) * counts
        return sum_ / self.count

    @property
    def quartiles(self):
        'It returns the quartiles'
        num_items = self.count
        if num_items < 4:
            msg = 'At least 4 values are required to calculate the quartiles'
            raise RuntimeError(msg)
        # quartile 1
        quotient, remainder = divmod(num_items + 1, 4)
        if not remainder:
            quartile1 = self._get_value_for_index(quotient - 1)
        else:
            val1 = self._get_value_for_index(quotient - 1)
            val2 = self._get_value_for_index(quotient)
            quartile1 = (val1 + val2) / 2
        # quartile 3
        quotient, remainder = divmod((num_items + 1) * 3, 4)
        if not remainder:
            quartile3 = self._get_value_for_index(quotient - 1)
        else:
            val1 = self._get_value_for_index(quotient - 1)
            val2 = self._get_value_for_index(quotient)
            quartile3 = (val1 + val2) / 2
        return quartile1, self.median, quartile3

    @property
    def irq(self):
        'It gets the interquartile range'
        # pylint: disable=W0612
        quart1 = self.quartiles[0]
        quart3 = self.quartiles[2]
        return quart3 - quart1

    @property
    def outlier_limits(self):
        'It returns the intercuartile'
        # pylint: disable=W0612
        quart1 = self.quartiles[0]
        quart3 = self.quartiles[2]

        iqr = self.irq
        limit_distance = round(iqr * 1.5)

        start = int(quart1 - limit_distance)
        end = int(quart3 + limit_distance)
        return (start, end)

    def _get_value_for_index(self, position):
        '''It takes a position and it returns the value for the given index'''
        cum_count = 0
        for index in sorted(self.keys()):
            count = self[index]
            cum_count += count
            if position <= cum_count - 1:
                return index
        else:
            if position >= cum_count:
                raise IndexError('You asked for an index beyond the scope')
            return index

    def _calculate_dist_range(self, min_, max_, outlier_threshold):
        'it calculates the range for the histogram'
        if ((min_ is not None or max_ is not None) and
            outlier_threshold is not None):
            msg = 'You can not pass max, min and outlier_threslhosld to '
            msg += 'calculate distribution range'
            raise ValueError(msg)

        if min_ is None:
            min_ = self.min
        if max_ is None:
            max_ = self.max
        if outlier_threshold:
            left_limit = self.count * outlier_threshold / 100
            rigth_limit = self.count - left_limit
            left_value = self._get_value_for_index(left_limit)
            rigth_value = self._get_value_for_index(rigth_limit)

            if min_ < left_value:
                min_ = left_value
            if max_ > rigth_value:
                max_ = rigth_value
        return min_, max_

    def calculate_bin_edges(self, min_, max_, n_bins=None):
        'It calculates the bin_edges'
        min_bins = get_setting('MIN_BINS')
        max_bins = get_setting('MAX_BINS')
        if n_bins is None:
            num_values = int(max_ - min_)
            if num_values == 0:
                n_bins = 1
            elif num_values < min_bins:
                n_bins = num_values
            else:
                n_bins = int(self.count / get_setting('MEAN_VALUES_IN_BIN'))
                if n_bins < min_bins:
                    n_bins = min_bins
                if n_bins > max_bins:
                    n_bins = max_bins
                if n_bins > num_values:
                    n_bins = num_values

        # now we can calculate the bin edges
        distrib_span = max_ - min_ if max_ != min_ else 1

        if distrib_span % n_bins:
            distrib_span = distrib_span + n_bins - (distrib_span % n_bins)
        bin_span = distrib_span // n_bins
        bin_edges = [min_ + bin_ * bin_span for bin_ in range(n_bins + 1)]
        return bin_edges

    def calculate_distribution(self, bins=None, min_=None, max_=None,
                               outlier_threshold=None):
        'It returns an histogram with the given range and bin'
        if self.count == 0:
            raise RuntimeError('No items in IntCounter')
        distrib = []
        min_, max_ = self._calculate_dist_range(min_, max_, outlier_threshold)
        if min_ is None or max_ is None:
            return None
        bin_edges = self.calculate_bin_edges(min_, max_, bins)
        for bin_index, left_edge in enumerate(bin_edges):
            try:
                rigth_edge = bin_edges[bin_index + 1]
            except IndexError:
                break
            sum_values = 0

            for index2 in sorted(self.keys()):
                value = self[index2]
                if index2 > rigth_edge:
                    break

                elif (left_edge <= index2 and index2 < rigth_edge or
                      left_edge <= index2 and index2 == max_):
                    sum_values += value

            distrib.append(sum_values)
        return {'counts': distrib, 'bin_limits': bin_edges}

    def update_labels(self, labels):
        'It prepares the labels for output files'
        self.labels.update(labels)

    def count_relative_to_value(self, value, comparison):
        'It counts the ints greater, equal, etc, relative to the given value.'
        return sum([counts for val, counts in self.items()
                    if comparison(val, value)])

    def __add__(self, other):
        'Add counts from two counters.'
        counter_python = super(IntCounter, self).__add__(other)
        return self.__class__(counter_python)

    def __str__(self):
        'It writes some basic stats of the values'
        if self.count != 0:
            labels = self.labels
            # now we write some basic stats
            format_num = lambda x: '{:,d}'.format(x) if isinstance(x, int) \
                                                                else '%.2f' % x
            text = '{}: {}\n'.format(labels['minimum'], format_num(self.min))
            text += '{}: {}\n'.format(labels['maximum'], format_num(self.max))
            text += '{}: {}\n'.format(labels['average'],
                                      format_num(self.average))

            if labels['variance'] is not None:
                text += '{}: {}\n'.format(labels['variance'],
                                          format_num(self.variance))
            if labels['sum'] is not None:
                text += '{}: {}\n'.format(labels['sum'],
                                          format_num(self.sum))
            if labels['items'] is not None:
                text += '{}: {}\n'.format(labels['items'], self.count)
            text += '\n'

            distrib = self.calculate_distribution()
            text += draw_histogram_ascii(distrib['bin_limits'],
                                         distrib['counts'])
            return text
        return '' class IntBoxplot(object):
    'It represents a Box and whisker plot'
    def __init__(self):
        'The init'
        self.counts = {}

    def append(self, category, value):
        'It appends a value to the distribution corresponding to a category'
        counts = self.counts
        try:
            cat_counts = counts[category]
        except KeyError:
            counts[category] = IntCounter()
            cat_counts = counts[category]
        cat_counts[value] += 1

    @property
    def aggregated_array(self):
        'It returns the IntSummarizedArray of all appended values.'
        aggregated_dist = None
        for cat_count in self.counts.viewvalues():
            if aggregated_dist is None:
                aggregated_dist = cat_count
            else:
                aggregated_dist += cat_count
        return aggregated_dist

    @property
    def ascii_plot(self):
        'It returns an string with an ASCII representation'
        distributions = self.counts
        categories = sorted(distributions.viewkeys())
        distrib_descriptions = {}
        for category in categories:
            distrib = distributions[category]
            min_ = distrib.min
            max_ = distrib.max
            try:
                quart1, median, quart3 = distrib.quartiles
                distrib_descriptions[category] = {'min': min_, 'max': max_,
                                            'quart1': quart1, 'median': median,
                                            'quart3': quart3}
            except RuntimeError:
                distrib_descriptions[category] = None

        min_value = min((d['min'] for d in distrib_descriptions.values()
                                                             if d is not None))
        max_value = max((d['max'] for d in distrib_descriptions.values()
                                                             if d is not None))

        len_str_float = lambda x: len('{:.1f}'.format(x))

        # how wide is the widest number of each type (min, max, median, etc)
        widths = {}
        for distrib in distrib_descriptions.values():
            if  distrib is None:
                continue
            for key in distrib.keys():
                value = len_str_float(distrib[key])
                if key not in widths or widths[key] < value:
                    widths[key] = value

        widths['labels'] = max([len(str(d)) for d in distrib_descriptions])

        category_format = '{:>' + str(widths['labels']) + 's}'
        header_format = category_format + ':{:>' + str(widths['min']) + '.1f}'
        header_format += ',{:>' + str(widths['quart1']) + '.1f}'
        header_format += ',{:>' + str(widths['median']) + '.1f}'
        header_format += ',{:>' + str(widths['quart3']) + '.1f}'
        header_format += ',{:>' + str(widths['max']) + '.1f}'

        header_len = None
        headers, distribs = [], []
        for category in categories:
            distrib = distrib_descriptions[category]
            if distrib is not None:
                header = header_format.format(str(category), distrib['min'],
                                          distrib['quart1'], distrib['median'],
                                          distrib['quart3'], distrib['max'])
                header += ' '
                if header_len is None or header_len < len(header):
                    header_len = len(header)
            else:
                header = None
            headers.append(header)
            distribs.append(distrib)

        plot_width = (get_setting('MAX_WIDTH_ASCII_PLOT') - widths['labels'] -
                      len(str(max_value)) - header_len)
        val_per_pixel = (max_value - min_value) / plot_width
        if val_per_pixel == 0:
            val_per_pixel = max_value / plot_width

        to_axis_scale = lambda x: int((x - min_value) / val_per_pixel)

        result = ''

        for distrib, header in zip(distribs, headers):
            if distrib is not None:
                line = header
                min_ = to_axis_scale(distrib['min'])
                line += ' ' * (min_ - 1)
                line += '<'  # min
                quart1 = to_axis_scale(distrib['quart1'])
                line += '-' * ((quart1 - min_) - 1)
                line += '['  # quartil 1
                median = to_axis_scale(distrib['median'])
                line += '=' * ((median - quart1) - 1)
                line += '|'  # median 1
                quart3 = to_axis_scale(distrib['quart3'])
                line += '=' * ((quart3 - median) - 1)
                line += ']'  # quart 2
                max_ = to_axis_scale(distrib['max'])
                line += '-' * ((max_ - quart3) - 1)
                line += '>'  # max
            else:
                line = category_format.format(str(category), 0, 0, 0, 0, 0)
            line += '\n'
            result += line

        axis1 = ' ' * header_len + '+' + '-' * (plot_width - 2) + '+' + '\n'
        axis2 = ' ' * header_len + str(min_value)
        axis2 += ' ' * (plot_width - len(str(min_value)) - len(str(max_value))
                       + 1)
        axis2 += str(max_value) + '\n'

        result += axis1
        result += axis2
        return result

    def __nonzero__(self):
        'It returns True if the object holds any counts'
        return bool(self.counts)
import unittest
import numpy
from tempfile import NamedTemporaryFile
from array import array
from crumbs.plot import (build_histogram, draw_scatter, draw_density_plot,
                         draw_histogram_in_fhand, draw_histogram_in_axes, LINE,
                         draw_histograms, draw_int_boxplot)
from crumbs.statistics import IntCounter, IntBoxplot
'''
Created on 2013 urr 10

@author: peio
'''





class PlotTests(unittest.TestCase):
    def test_build_histogram(self):
        values = [1, 2, 3, 1, 2, 3, 2, 3, 2, 3, 2, 1, 4]
        fhand = NamedTemporaryFile(suffix='.png')
        build_histogram(values, fhand, bins=100, title='hola')
        # raw_input(fhand.name)

    def test_draw_scatter(self):
        fhand = NamedTemporaryFile(suffix='.png')
        data = [{'y': array('B', [40, 60, 13]),
                 'x': array('B', [20, 45, 45]),
                 'value': array('B', [9, 90, 90])}]

        draw_scatter(data, fhand, xlim=0, ylim=0)
        # raw_input(fhand.name)

    def test_draw_scatter_line(self):
        fhand = NamedTemporaryFile(suffix='.png')
        data = [{'y': array('B', [40, 60, 13]),
                 'x': array('B', [20, 45, 45])}]
        draw_scatter(data, fhand, plot_lines=True)
        # raw_input(fhand.name)

    def test_draw_density_plot(self):
        fhand = NamedTemporaryFile(suffix='.png')
        data = {'y': array('f', numpy.random.normal(40, 5, 40000)),
                'x': array('f', numpy.random.normal(40, 5, 40000))}
        draw_density_plot(data['x'], data['y'], fhand, n_bins=200)

    def test_draw_histogram_in_fhand(self):
        values = [1, 2, 3, 1, 2, 3, 2, 3, 2, 3, 2, 1, 4]
        fhand = NamedTemporaryFile(suffix='.png')
        counter = IntCounter(values)
        distrib = counter.calculate_distribution()
        draw_histogram_in_fhand(distrib['counts'], distrib['bin_limits'],
                                fhand=fhand)
        # raw_input(fhand.name)

    def test_draw_histogram_in_axes(self):
        values = [1, 2, 3, 1, 2, 3, 2, 3, 2, 3, 2, 1, 4]
        fhand = NamedTemporaryFile(suffix='.png')
        counter = IntCounter(values)
        distrib = counter.calculate_distribution()
        axes, canvas = draw_histogram_in_axes(distrib['counts'],
                                              distrib['bin_limits'],
                                              kind=LINE,
                                              distrib_label='test')
        axes.legend()
        canvas.print_figure(fhand, format='png')
        fhand.flush()
        # raw_input(fhand.name)

        # ylimit test
        values = [1, 2, 3, 1, 2, 3, 2, 3, 2, 3, 2, 1, 4, 0, 5, 4, 4, 4, 4, 4]
        fhand = NamedTemporaryFile(suffix='.png')
        counter = IntCounter(values)
        distrib = counter.calculate_distribution()
        axes, canvas = draw_histogram_in_axes(distrib['counts'],
                                              distrib['bin_limits'],
                                              kind=LINE,
                                              distrib_label='test',
                                              ylimits=(None, 4))
        axes.legend()
        canvas.print_figure(fhand, format='png')
        fhand.flush()
        # raw_input(fhand.name)

    def tests_draw_histograms(self):
        fhand = NamedTemporaryFile(suffix='.png')
        values = [1, 2, 3, 1, 2, 3, 2, 3, 2, 3, 2, 1, 4]
        counters = []
        counters.append(IntCounter(values))
        counters.append(IntCounter(values))
        counters.append(IntCounter(values))
        titles = ['t1', 't2', 't3']
        draw_histograms(counters, fhand, titles=titles, plots_per_chart=2)
        # raw_input(fhand.name)

        values = [1, 2, 3, 1, 2, 3, 2, 3, 2, 3, 2, 1, 4, 0, 5, 4, 4, 4, 4, 4]
        counters = []
        counters.append(IntCounter(values))
        counters.append(IntCounter(values))
        counters.append(IntCounter(values))
        titles = ['t1', 't2', 't3']

        draw_histograms(counters, fhand, titles=titles, plots_per_chart=2,