Introduction
Supermongo (SM) is a domain-specific programming language for creating plots. It was first written in 1987. Astronomers adopted this language as a primary plotting package for data analysis. Many groundbreaking discoveries have been seen using supermongo plots. However, new tools exist for plotting which have evolved from first plotting languages like Supermongo. These new tools provide methods for creating plots with fewer lines of code. They provide better integration into other programming languages and code.
Matplotlib is a domain-specific plotting library for the general-purpose programming language Python. This library provides all the plotting capabilities of Supermongo and more. This post is to provide a 1-to-1 guide for Supermongo experts to apply their knowledge in Python with Matplotlib.
Other Python plotting packages include : bokeh, plotly, vispy
General Comparison
Variables: In Supermongo all variables are global so wherever you change them, within any macro, they change everywhere else. In Python variables have scope. You can use the same variable name in mulitple functions and be sure that they will act independantly.
Plot States: In Supermongo you have a single plot state which you update with the interactive commands. Matplotlib also uses a plot state which you edit with commands.
Object Oriented: Supermongo is a procedural programming language. You write out all the steps and they execute in that order. Python is object oriented meaning you can create data objects and write them into procedures. This method is how your operating system is built and is extremely useful.
Community Support: If you've ever searched the internet for help with Supermongo (chances are you have if you're reading this) you've come across a handful of useful sites: The SM manual, Annika Peter's Guide, Craig Rudick's Tutorial and Rebecca Stanek's Guide. These resources and only a few others are the mainstay of the Supermongo online support.
By contrast the community supporting Matplotlib is immense. Not only is it developed by many people to have lots of functionality, it also has a large user base. If you are unsure how to make some plot thing, a quick internet search often pulls up many solutions.
Python requirements
Because general purpose language you'll need specific subpackages. For this tutorial:
- maplotlib
- numpy
Hopefully, these packages came with your installation of Python. You can also install them using the command line utility pip
(e.g. pip install numpy
)
This tutorial will work with both Python 2 and 3.
Getting Started
Working interactively
In Supermongo all your plotting is done either interactively (you type and the plot is modified) or using a script. In Python you do the same.
To use the interactive mode, on the command line type python
(better yet try out ipython
for more interactive fun). Now you should have a new prompt, probably with '>>>' which you type your python code. (Check out TODO for a python tutorial)
import numpy as np
x = np.array(10)
# comment
for i in range(len(x)):
""" String doc """
print(" value {} = {}".format(i,x[i]))
Here's some comparisons of interactive mode.
Supermongo
div X11
set x = {2,3}
set y = {5,10}
con x y
xlabel time
ylabel temperature
Python
from matplotlib.pylab import *
x = [2,3]
y = [5,10]
plot(x,y)
xlabel("time")
ylabel("temperature")
show()
NOTE: The remainder of the tutorial I don't use from matplotlib.pylab import *
and instead use import matplotlib.pylab as plt
then commands like plt.plot
. The reason has to do with how many named things there are and to allow me to make my own plot
function different from the default plt.plot
function. Basically, it's good coding practice.
Writing Scripts
Both languages allow you to write a script to execute commands. If you're not doing this you really should. In a nut shell, you just write the lines you would type into the interactive mode into a text file and then execute that file. You will want to use Emacs, Sublime Text, TextWrangler or some equivalent text editor.
With Supermongo you write a script with at least one macro, for example:
"script.sm"
main_macro
dev x11
ctype white
set x=0.0,10.0,1.0
set y=x**2
lim x y
box
con x y
Then startup Supermongo using sm
enter macro read script.sm
and then main_macro
to execute.
For Python you write a script similarly
"script.py"
import matplotlib.pylab as plt
import numpy as np
x = np.arange(0.0,10.0,1.0)
y = x**2
plt.plot(x,y)
plt.show()
Then you can run it with python script.py
.
Comparisons of Supermongo and Python Plotting
Plotting libraries implement functions to display views of data. One of the basic views is comparing one data parameter (say X) against another (say Y) and just plotting the intersecting points (a.k.a. a scatter plot). In this section, I make direct comparisons of Supermongo to Python plotting methods.
Adding items to plots
Both plotting packages create some plot axes which you can then add views of your data to.
Both plotting packages have methods for adding XY data as lines, points, and with errorbars. Below is the side by side comparison.
Plot Lines
Supermongo
connect x y
Python
plt.plot(x, y)
Plot Line
Supermongo
line x1 y1 x2 y2
Python
plt.plot([x1, x2],[y1, y2])
Plot Points
Supermongo
points x y
Python
plt.scatter(x, y)
# or use
plt.plot(x, y, linestyle="none")
Plot Errorbars
Supermongo
errory x y yerr
errorx x y xerr
Python
plt.errorbar(x,y,yerr=yerr)
plt.errorbar(x,y,xerr=xerr)
plt.errobar(x,y,xerr=xerr,yerr=yerr)
Plot Horizontal Line
Supermongo
hzline y
Python
plt.axhline(y)
Plot Vertical Line
Supermongo
vtline x
Python
plt.axvline(x)
Plot Rectangle
Supermongo
relocate x1 y1
draw x1 y2
draw x2 y2
draw x2 y1
draw x1 y1
Python
rec = plt.Rectangle(x1,y1,(x2-x1),(y2-y1))
plt.gca().add_patch(rec)
Layout Axis Labels
Supermongo
toplabel title_of_plot
xlabel label_name
ylabel label_name
Python
plt.title("title_of_plot")
plt.xlabel("label_name")
plt.ylabel("label_name")
Layout Add Text
Supermongo
relocate x y
label label_text
Python
plt.text(x, y, "label_text")
Layout Legends
Supermongo
# Draw Rectangle box
relocate xpt= ypt
# Set ptype,ctype
dot
relocate xpt+dx ypt
label Item Label
Python
# just add label keyword
# to your plot call
plt.plot(x,y,label="Item Label")
plt.legend()
# use help(plt.legend) to find
# out about keywords
Plot legends are a pain in Supermongo. If you want a bounding box you need to draw the rectangle yourself specifying every corner. Then you have to specify the exact positions of each label, draw a point with the correct styles at the correct location, then add the text slightly offset. If you want to add/remove labels or if points styles change then you're often thrown into chaos. (Of course you can write macros, but why? when Python makes it so easy!)
The python plt.legend
function looks for any plot item you added a lable=? keyword argument to. This includes all lines and points as well as patches like plt.Rectangle and plt.Circle. It's also easy to manipulate the position using the loc=? keyword of plt.legend
.
Controlling Plot Styles
In Supermongo you must set the styles globally before adding them to the plot. This can lead to frustrating bugs if their out of order
This one may or may not be red points:
points x y
ctype red
This causes the points to be red:
ctype red
points x y
In Python you set the plot parameters at the same time you add the item. You do this using keywords in the function call.
plt.scatter(x,y,c='red')
You can find out about all the keywords by typing help(plt.scatter)
in the Python terminal or by using an internet search (the internet is your friend).
Caveat: Matplotlib has an rc file that sets some global variables. You can learn more about it here.
Alright, here comes the one to one of common styles you'll want to manipulate. The Python answers I'm going to use the most common function; Note though, Matplotlib has some inconsistencies with names and so you should refer to the internet or help if you run into problems in your own implementation.
Point Color
Supermongo
ctype red
ctype red
points x y
Python
plt.scatter(x,y,c='r')
plt.scatter(x,y,c='r')
# hex colors work
plt.scatter(x,y,c='#DC322F')
Point Style
Supermongo
ptype 10 3
ptype 10 3
Python
plt.scatter(x,y,marker='o')
plt.scatter(x,y,marker='o')
Point Size
Supermongo
expand 1.5
expand 1.5
Python
plt.scatter(x,y,s=100)
plt.scatter(x,y,s=100)
Line Color
Supermongo
ctype red
ctype red
connect x y
Python
plt.plot(x,y,color='r')
plt.plot(x,y,color='r')
# hex colors work
plt.plot(x,y,color='#DC322F')
Line Style
Supermongo
ltype 2
ltype 2
connect x y
Python
plt.plot(x,y,linestyle='--')
plt.plot(x,y,linestyle='--')
# or the shortcut
plt.plot(x,y,ls='--')
Line Width
Supermongo
lw 7
lw 7
Python
plt.plot(x,y,lw=7)
plt.plot(x,y,lw=7)
More with Matplotlib
In addition to the side by side comparison matplotlib provides you additional ways to plot your data and manipulate your figures.
- 3D Contours
- Interactive Plots
- And much more! Check out the Matplotlib Gallery
Modifying Plot Properties
In addition to add items to a plot you want to manipulate properties of the plot itself. For example, you often want to re-size the bounds of the plot.
It's important to talk about the figure. In Supermongo you only ever have one figure which you can add multiple sub-plots to but usually only one. In Matplotlib you have the option to create multiple figures if you store
Figure and Plot
Supermongo
page
box
Python
fig = plt.figure()
ax = fig.add_subplot(1,1,1) # ax = plt.gca() for shortcut
Multipanel Plot
Supermongo
page
window 2 2 1 2
Python
fig = plt.figure()
ax = fig.add_subplot(2,2,4)
Note: For Python, storing the plot in ax
is not necessary but it's a best practice to use matplotlib objects.
For multipanel plots Supermongo uses the window
command with arguments [number of columns] [number of rows] [x-index] [y-index]. window 2 2 1 2
indicates 2 rows 2 columns and the current plot is the bottom-right.
In Matplotlib there are several ways to accomplish this (add_subplot,plt.subplots,gridspec). I commonly create a figure fig = plt.figure()
and add a subplot ax = fig.add_subplot(1,1,1)
. The arguments are [number of rows] [number of columns] [current plot]. The current plot number starts counting at 1 from the top-left then continues as though you were reading English from left to right, top to bottom. To get the bottom right plot from the Supermongo example I would use ax = fig.add_subplot(2,2,4)
.
Saving plots to file
Saving in Supermongo requires setting up a state to put the plot into. The following example from Annika Peter shows how to set up the device then save to file (the last hardcopy
is critical, you can also use dev x11
to close).
dev postencap my_first_plot.eps
ctype black
set x=0.0,10.0,1.0
set y=x**2
lim x y
box
con x y
ptype 10 3
points x y
xlabel x
ylabel y
hardcopy
Matplotlib does not require you to set anything up prior to building the items. Instead, you can just save out the state or figure with a command. The following example mimics the Supermongo example.
import matplotlib.pylab as plt
import numpy as np
x = np.arange(0.0,10.0,1.0)
y = x**2
fig,ax = plt.subplots()
ax.plot(x,y,marker='o')
ax.set_xlabel("x")
ax.set_ylabel("y")
fig.savefig("my_first_plot.ps")
Note: Matplotlib is smart about it's saving methods. If you want to create a pdf not ps you just use the ".pdf" extension and it will save to that format. Many other formats are supported (e.g. png, pdf, jpg, gif, etc)
Could publish the programming section later
Programming
Supermongo was developed to be plotting language. However, within it's syntax you can specify any programming task which makes it more or less a complete language. However, you should avoid using SuperMongo for more than plots as much as possible. Other programming languages have much better implementations allowing you to write your code faster, debug easier, and for it to run more efficiently.
For example, Python is a complete language which has good implementations of many programming concepts. It's a language not just for plotting but
Syntax Differences
Supermongo
if(a == b) {
echo True condition for ${a}
} else {
if(a == c) {
echo else if condition
} else {
echo else condition
}
}
Python
if a == b:
print(f"True condition for {a}")
elif a == c:
print("else if condition")
else:
print("else condition")
Supermongo | Python | |
---|---|---|
Variables | define x 1 | x = 1 |
Arrays | set x = {1,2,3} | x = [1,2,3] |
Array Range | set x = 0,10,1 | x = list(range(0,10,1)) |
Conditionals | == != > < >= <= | # same |
And | a && b | a and b |
Or | a b | a or b |
Not | !a | !a |
Shout Outs
Acknowledgments go to Robert Lupton and Patricia Monger for creating SM which really was revolutionary for it's time. Special thanks to Annika Peter, Craig Rudick and Rebecca Stanek for their Supermongo guides. They helped me immensely when I learned Supermongo and in writing this guide.