Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clear and readable grayscale line graphs in matplotlib?

I'm an undergraduate studying computer science. For most of my classes, I have to make some sort of graph to display my results. Most of my professors want these graphs to be printed out (or, if they accept PDFs, they go on to print out a copy themselves) in order to grade it. I use matplotlib in conjunction with a few other tools to generate the graphs, and that works well.

My issue, however, is that the (color) line graphs that I print out tend to be impossible to decipher. For a relatively mild example:

enter image description here

A worse example (and probably more of an issue with my design of the graph itself) would be:

enter image description here

When printed out in black and white, the series become impossible to distinguish.

An example of one of the scripts that I might use to generate a graph is below. I'd really like to find a way to make graphs that will look as clear as possible when printed out on a black and white printer --- how would I go about doing this? What techniques are most effective for increasing readability of charts and graphs in B/W?

from matplotlib import pyplot

SERIES_COLORS = 'bgrcmyk'

def plot_series(xy_pairs, series, color):
    label_fmt = "{}Lock"
    x, y_lists = zip(*xy_pairs)
    normalized_ys = [[y / numpy.linalg.norm(ys) for y in ys]
                     for ys in y_lists]

    y = [numpy.average(y_list) for i, y_list
         in enumerate(normalized_ys)]
    y_err = [numpy.std(y_list) for i, y_list in
             enumerate(normalized_ys)]

    pyplot.errorbar(x, y, y_err,
                    label=label_fmt.format(series),
                    fmt='{}o-'.format(color)
                    ls='-')


def main():
    big_dataset = {
        'a': data_for_a,
        'b': data_for_b,
        'c': data_for_c,.
        ....
    }

    for series, color in zip(SERIES_COLORS, big_dataset):
        processed = do_work(big_dataset[series])

        plot_series(processed, series, color)

    pyplot.show()
like image 463
Patrick Collins Avatar asked May 18 '26 07:05

Patrick Collins


1 Answers

You can play with different line styles and markers.

This is a nice example taken from http://matplotlib.org/examples/pylab_examples/line_styles.html

#!/usr/bin/env python
# This should probably be replaced with a demo that shows all
# line and marker types in a single panel, with labels.

import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
import numpy as np

t = np.arange(0.0, 1.0, 0.1)
s = np.sin(2*np.pi*t)
linestyles = ['_', '-', '--', ':']
markers = []
for m in Line2D.markers:
    try:
        if len(m) == 1 and m != ' ':
            markers.append(m)
    except TypeError:
        pass

styles = markers + [
    r'$\lambda$',
    r'$\bowtie$',
    r'$\circlearrowleft$',
    r'$\clubsuit$',
    r'$\checkmark$']

colors = ('b', 'g', 'r', 'c', 'm', 'y', 'k')

plt.figure(figsize=(8,8))

axisNum = 0
for row in range(6):
    for col in range(5):
        axisNum += 1
        ax = plt.subplot(6, 5, axisNum)
        color = colors[axisNum % len(colors)]
        if axisNum < len(linestyles):
            plt.plot(t, s, linestyles[axisNum], color=color, markersize=10)
        else:
            style = styles[(axisNum - len(linestyles)) % len(styles)]
            plt.plot(t, s, linestyle='None', marker=style, color=color, markersize=10)
        ax.set_yticklabels([])
        ax.set_xticklabels([])

plt.show()

You can also combine them all together.

x = linspace(0,1,10)
ls = ["-","--","-."]
markers = ["o","s","d"]
clrs = ["k"]
k = 1

for l in ls:
    for m in markers:
        for c in clrs:
            plot(x,x**k,m+l+c)
            k+=1

Hope it helps.

like image 75
mrcl Avatar answered May 20 '26 20:05

mrcl



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!