Coder Social home page Coder Social logo

plawt's Introduction

plawt - JSON-like sugar for matplotlib

Because sometimes you just want a good looking plot damnit. I don't like context switching from physics to python, and hopefully this will let me do less of it.

Installation

pip install plawt and then import plawt in your python file. Current version is here.

Features

See the examples folder for how to use plawt to make subplots, step plots, and other less common uses.

In addition to any usual single panel plot plawt also wraps these matplotlib features:

  • Arbitrary subplot grids, spacing between subplots
  • Step Plots
  • Log plots
  • legends, legend locations, legend labels
  • labelling, subplot titles (with location), super titles, font-size tweaking
  • x limits, y limits,
  • marker and linestyle, alpha, drawstyle
  • saving figures, showing figures to screen
  • tight_layout
  • matplotlib style (plt.style.use())
  • Tick parameters (axes.tick_params)
  • Text annotations

Example

Here's a simple logarithmic plot that shows why the strength of Balmer lines varies in different colored stars: plot

Here's the code for that plot using plawt:

from __future__ import division
from math import pi
from numpy import exp, sqrt, log10, e
import numpy as np
import plawt

### Functions to generate the data
# excitation potential
def Xn(n): return 13.6*(1-1/n**2)

# Boltzmann equation, N_n/N
def excitationEq(n, T):
	k = 8.63e-5 # eV/K
	gn = 2*n**2; Z = 2 # hydrogen atom
	return (gn/Z) * exp(-Xn(n)/(k*T))

T = np.arange(3000, 12000, 1)

### now all the data and metadata about the plot:
myplot = {
	0: {	# 'first' line
		'x': T,
		'y': excitationEq(1, T),
		'line': 'k-',
		'label': 'Lyman Series $\log{N_1 / N}$'
	},
	1:{		# 'second' line
		'x': T,
		'y': excitationEq(2, T),
		'line': 'k--',
		'label': 'Balmer Series $\log{N_2 / N}$'
	},
	'xlabel': 'Temperature (K)',
	'ylabel': 'Relative Population $N_n / N$',
	'title': 'log of Relative Populations of Hydrogen atoms in $n=1$ and $n=2$',
	'set_yscale': 'log',
	'grid': True,
	'legend': {'loc':4},
	'ylim': (10e-18, 10e2),
	'xlim': (2000,13e3),
	'filename': 'excitation_logarithmic.png',
	'show': True
}

### fire away fire awaaay
plawt.plot(myplot)

The plot is also saved. I prefer this because I can glance at what is completely just information about the physical problem I'm working on. What are my labels? What is my data? What are my limits? Is it a log scale? Plus a few extra aesthetic things like grid, line color, the name of the file it's being saved as, etc.

The same plot above is written like this without plawt:

plt.plot(T, excitationEq(1, T), 'k-', label='Lyman Series $\log{N_1 / N}$')
plt.plot(T, excitationEq(2, T), 'k--', label='Balmer Series $\log{N_2 / N}$')
plt.xlabel('Temperature (K)'); plt.ylabel('Relative Population $N_n / N$')
plt.title('log of Relative Populations of Hydrogen atoms in $n=1$ and $n=2$')
plt.gca().set_yscale('log')
plt.legend(loc=4)
plt.grid()
plt.ylim((10e-18,10e2))
plt.xlim((2000, 13e3))
plt.savefig('excitation_logarithmic.png')
plt.close()

Usage

There is only one exposed method:

plawt.plot(plotDictionary)

You specify your plot in a python dictionary, here called plotDictionary. Each line (data series) in your plot should be indexed by an integer key. The actual integer doesn't matter but I like to go 0, 1, 2, ...

I define my data series before anything else.

plotDictionary = {
	0: {
		'x': [1, 2, 3, 4, 5, 6],
		'y': [1, 2, 3, 4, 5, 6],
		'line': 'k-' # black, solid, like in matplotlib docs
	}
}

The value of the '0'th line is another dictionary. The only mandatory fields are 'x' and 'y'. The 'line' field is optional as well as 'label'.

In fact every field except for a 'x' and 'y' is optional.

Note: Not every pyplot field is implemented! I add fields as I need them. Send me pull requests if you'd like something added.

I try to keep a one-to-one mapping between the fields in plawt and in matplotlib:

Add an xlabel the same way as in matplotlib:

plt.xlabel('numbers<3')

## OR ##

plotDictionary = {
	0: {
		'x': [1, 2, 3, 4, 5, 6],
		'y': [1, 2, 3, 4, 5, 6],
	},
	'xlabel': 'numbers<3'
}

The values of some fields also match with their matplotlib counterparts: eg. a log scale:

plt.gca().set_yscale('log')

## OR ##

plotDictionary = {
	0: {
		'x': [1, 2, 3, 4, 5, 6],
		'y': [1, 2, 3, 4, 5, 6],
	},
	'set_yscale': 'log'
}

By default plawt will close your plot automatically after showing it to you or saving it to a file. If you set 'keepOpen':True you can take the return value and use it to do more things to your plot that haven't been implemented yet:

plotDictionary = {
	0: {
		'x': [1, 2, 3, 4, 5, 6],
		'y': [1, 2, 3, 4, 5, 6],
	},
	'keepOpen': True
}

plt = plawt.plot(plotDictionary)
plt.gca(). etc etc
plt.savefig('yo.png')
plt.show

## Or even just
plawt.plot(plotDictionary).show()

Copyright © 2017 Mohammed Chamma

MIT License

plawt's People

Contributors

mef51 avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

plawt's Issues

add support for subplots

the interface could be something like

plawt.plot([{
    0: {'x': x, 'y': y},
    'xlabel': 'some label',
    'filename': 'plot.png'
}, {
    0: {'x': x2, 'y': y2},
    'xlabel': 'some other label'
}])

That is, pass mutliple 'plot' dictionaries and inherit global properties like title or filename from the first plot dictionary as a convention

Subplot titles: 'subtitledict' doesn't behave as expected.

plawt's 'subtitledict' becomes the fontdict for matplotlib's [axes.set_title](https://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.set_title.html).

Only the 'verticalalignment' field of fontdict has the intended effect, and with inconsistently as well (you have to put 'center' when you mean 'bottom').
I think this is a matplotlib issue and not a plawt issue.

add support for animations

I can currently make animations using plawt and imageio like this (for example):

animation = {
		'ylabel': 'z/H', 'xlabel': 'r/H',
		'ylim': (-2, 10), 'xlim': (-6, 6),
		'figsize': (6/1.3, 6.5/1.3),
		'title': 'Likely how W4 expanded',
		'show': False,
		'keepOpen': True,
		'legend': {'loc':4}
	}
	y = np.arange(0.01, 2.05, 0.05)
	with imageio.get_writer('blast.gif', mode='I', fps=24) as writer:
		for i, t in enumerate(tqdm(y)):
			animation[0] = {'x': np.concatenate((r(z, y[i]), -r(z, y[i]))), 'y': np.concatenate((z,z)),
				'line':'k-', 'label':'$y=$'+str(y[i])}
			plt = plawt.plot(animation)
			fig = plt.gcf()
			fig.canvas.draw()
			data = fig.canvas.tostring_rgb()
			row, col = fig.canvas.get_width_height()
			image = np.fromstring(data, dtype=np.uint8).reshape(col, row, 3)
			writer.append_data(image)
			plt.close()

But I want to abstract some of the details away.
The method above is essentialy generating bitmap as frames and putting them together, but matplotlib has its own api for animating using functions which might be more efficient. I'll need to look into that and maybe support both ways of animating. (http://matplotlib.org/api/animation_api.html#animation)

refactor to use matplotlib's object-oriented api

right now things internally are done by importing pyplot and then calling things like plt.plot(), plt.xlabel(), etc... this is not great because i have to do weird if/else branches if for example only an x axis is provided and the call signature to plt.plot() is different. (also i got bashed on reddit for doing it this way and i kinda agree)

matplotlib has an api where you can do things like axis.xlabel = 'blah blah' and i think this might be a cleaner and more extensible way to have plawt work. But I don't really know this api and I need to look into it

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.