matplotlib node alignment and custom line style - python

I'm plotting netowrk graphs (Water distribution networks) using bokeh and or matplotlib. From the reference software the plots look like this:
As you can see pumps and water towers have their own little symbols.
I'm using matplotlib and bokeh to plot the same graphs (with a little more info on the system state):
As you can see we have squares and triangles as symbols now. So I would like to either add my own symbols based on some vector graphic of the symbols in the first plot, or at least rotate the triangles to be aligned with the arcs, such that they point along them. Any ideas on how to achieve either? I find the bokeh documentation rather confusing (as you can tell I'm a civil engineer not a programmer)

Instead of rotating the triangle, you may consider arrows.
If you really want to rotate the triangle, I normally rotate the three points of the triangle around its center (by rotation matrix).
About custom symbols, I have never import any external symbols into my matplotlib figure. I usually create the symbol as a polygon and then draw it using the polygon patches.
Hope it helps.

Related

What is the difference between draw and draw_networkx in Networkx library?

I was using regular draw function for my graphs and while reading someone's code I saw he used draw_networkx and looks like they are taking different parameters and default values.
I was wondering if anyone could explain me what they are more specifically used for.
Networkx docs give you the answer (bold text is mine):
draw():
draw the graph as a simple representation with no node labels or edge
labels and using the full Matplotlib figure area and no axis labels by
default. See draw_networkx() for more full-featured drawing that
allows title, axis labels etc.
draw_networkx():
draw the graph with Matplotlib with options for node positions,
labeling, titles, and many other drawing features. See draw() for
simple drawing without labels or axes.

In Plotly 3D Scatterplot, is there a way to freeze rotation of one axis?

I am making a 3-D Scatterplot with plotly in Python 3 and the Z-axis represents time. I would like to freeze that so that, when the using clicks around to rotate the plot, it spins on that axis, but that axis stays up and down. I'm not sure if it's possible, but that would be a great feature.
As it is, the oldest points are at the top (this is a genetic tree) and the newest are at the bottom. However, it's very easy to get this turned when clicking around the plot to rotate and then the time axis is going left-to-right or diagonal or something and it's a bit disorienting, especially for people who are not used to looking at complex visuals like this (i.e. my intended audience).
A first draft example: https://plot.ly/~seth127/6
Any help is greatly appreciated!
Thanks,
Seth

Matplotlib alternative for 3D scatter plots

I am having a hard time using Matplotlib to visualize reprojection results of my data in 3 dimensions after applying Principle components analysis or Linear discriminant analysis. After doing a scatter plot, I cannot rotate the data or change the point of view while zooming easily (Rotation axis stays the same even after you zoom, and if you zoom too much points just disappear) and every change takes one second to occur. Matplotlib is very useful but for this specific use case it starts to get very frustrating as it probably wasn't designed for such tasks. Is there an alternative to Matplotlib in Python that can handle 3d scatter plots better and where one could fluidly navigate through the cloud?
An example is shown in the next figure. I have drawn spheres around each data cluster corresponding to a specific class and colored overlapping spheres with red. Now I want to see how these sphere intersect. I think the biggest problem with Matplotlib is that it doesn't allow shifting of the whole graph with the mouse, it only allows rotation around a fixed point, which makes things very messy once you zoom a bit.
matplotlib is not quite mature for 3d graphics :
http://matplotlib.org/mpl_toolkits/mplot3d/faq.html
mplot3d was intended to allow users to create simple 3D graphs with the same “look-and-feel” as matplotlib’s 2D plots. Furthermore, users can use the same toolkit that they are already familiar with to generate both their 2D and 3D plots.
I don't think easy navigation in a 3d plot is easily doable (even 3d scaling is not possible without tweaking the lib). mplot3d was not really intended to be a full-fledged 3D graphics library in the beginning, but more a nice addition for people who needed basic 3D and who were acquainted with matplotlib 2D plot structure.
You might want to take a look at MayaVI (which is pretty good) :
MayaVi2 is a very powerful and featureful 3D graphing library. For advanced 3D scenes and excellent rendering capabilities, it is highly recomended to use MayaVi2.
Note that unlike matplotlib, MayaVI is not yet compatible with Python3 (and might not be in the foreseeable future), so you'll need a Python2 installation.
A very good alternative, but not in Python, is the 3D plot from ILNumerics (http://ilnumerics.net/). It is in .NET
Matplotlib works alright for 3D however, not too fast when interactivity is needed:
https://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html
Mayavi is really fast and compatible with Python 3:
https://docs.enthought.com/mayavi/mayavi/mlab.html#id1

How to place country boarders as background for a plot with matplotlib?

I have some data made of coordinates and the count of each coordinate which I plot in a heatmap like this:
pyplot.subplot(211)
pyplot.scatter(longitudes, latitudes, c=counts)
pyplot.colorbar()
which is inspired by this great answer here in SO.
If you look closely you can see, that the dots shape the worldmap somehow. To underline this effect I'd like to put the real country boarders (simply drawn would be enough) as background to my plot. Is this possible with matplotlib? Maybe there is some (hidden) builtin in matplotlib?
You can likely achieve this if you have some image of the world map that you want as a background. You can read this into a numpy array and plot the image. Then you should be able to add your scatter plot overtop of the image. This matplotlib cookbook example shows how to insert images and such. There is also the matplotlib image tutorial that may be of use.
I've not used it, but you may also be interested in the basemap toolkit for matplotlib. In particular, the section on drawing a map background mentions specifically a drawcountries() method.

Arched Relationship Infographic In Python

This is a very specific inforgraphic challange altough the fundemental question is how do you build archs between words using matplotlib, cario or an other python libary.
Given a the following data structure.
me, you, 7 |
me, apple, 9 |
apple, you, 1 |
bike, me, 5
Names would be displayed horizontally the names with the most relationships larger than the others and then there would be weighted archs between the names. A 10 weighted arch would be twice as thick as a 5 weighted arch.
Inspiration comes from: similar diverstiy. http://similardiversity.net/
Let the challange commence!
matplotlib isn't the right library here, since it's not a general purpose graphics library. What you need here is either something like Cairo, or much simpler, you can do with the graphics capabilities of any GUI toolkit, such as PyQt. Another feasible approach is PyGame, which has good drawing capabilities as well.
If you want an example, see this Cairo samples page, the first sample - arc. You just write the text words and then use the arc code for an arc of any width and color between them.
There are several libraries, at least one of which relies on Matplotlib, that will do what you want. I recommend Networkx (www.networkx.lanl.gov) to build your graph structure, and which you can then use to call the relevant Matplotlib methods to plot. Networkx and Matplotlib work very well together.
import networkx as NX
import matplotlib.pyplot as PLT
Gh = NX.Graph()
Gh.add_edge("You", "Bike", weight=1.0)
Gh.add_edge("Bike", "Apple", weight=0.9)
Gh.add_edge("Me", "Bike", weight=1.1)
all_nodes = Gh.nodes()
# to scale node size with degree:
scaled_node_size = lambda(node) : NX.degree(Gh, node) * 700
position = NX.spring_layout(Gh) # just choose a layout scheme
NX.draw_networkx_nodes(Gh, position, node_size=map(scaled_node_size, all_nodes))
NX.draw_network_edges(Gh, position, Gh.edges(), width=1.0, alpha=1.0, edge_color="red")
# now for the Matplotlib part:
PLT.axis("off")
PLT.show()
As you can see, you could scale the edges by applying a factor to vary the 'weight' parameter to any of the 'edge' methods, just the same way as i did it for node scaling.
I would also recommend pygraphviz (obviously using graphviz as its backend). It is very similar to Netwworkx (same lead developer).
I don't really see where the difficulty or challenge is. All you need is a graphics library that can draw text and half circles, which is possible in pretty much everything. There is no need for Bezier curves. For example you could simply create an SVG file (then you don't even need any library and can nicely embed this in a webpage and use some JavaScript to make it interactive).
The actual plotting is simple: the center of a circle is in the middle between the two words, the radius is half the distance between them. You can then adjust the stroke to reflect other quantities.

Categories

Resources