How to animate and update the size of scatter? - python-2.7

I have two data sets, Points and Pointsize. I want to animate the plot with the change of coordinate(Points) and size(Pointsize) of points. But I only can update Points. The code below is showing that three points move with change of data of Points. What I want is, the points not only move, but also change their sizes.I tried to use scat.set_offsets(Points['xy'],Pointsize) to achieve my goal. But the error shows "TypeError: set_offsets() takes exactly 2 arguments (3 given)". I also tried to use duplicate set_offsets to update both Points['xy'] and Pointsize separately. The error shows "ValueError: total size of new array must be unchanged".
I have no idea how to solve that problem. Someone can tell me a way or solution to achieve my goal? I will appreciate your help. Thank you very much.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
def updata(frame_number):
current_index = frame_number % 3
a = [[10,20,30],[40,50,60],[70,80,90]]
Points['xy'][:,0] = np.asarray(a[current_index])
Points['xy'][:,1] = np.asarray(a[current_index])
Pointsize = a[current_index]
scat.set_offsets(Points['xy'])
#scat.set_offsets(Pointsize)
#scat.set_offsets(Points['xy'],Pointsize)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title("For Dataset %d" % current_index)
fig = plt.figure(figsize=(5,5))
ax = fig.add_subplot(111)
Points = np.zeros(3,dtype=[('xy',float,2)])
Pointsize = [10] * 3
scat = ax.scatter(Points['xy'][:,0],Points['xy'][:,1],s=Pointsize,alpha=0.3,edgecolors='none')
ax.set_xlim(0,100)
ax.set_ylim(0,100)
animation = FuncAnimation(fig,updata,frames=50,interval=600)
plt.show()

As seen in the official matplotlib example, you would use
scat.set_sizes(Pointsize)
to update the size of scatter points.

Related

How can I remove the negative sign from y tick labels in matplotlib.pyplot figure?

I am using the matplotlib.pylot module to generate thousands of figures that all deal with a value called "Total Vertical Depth(TVD)". The data that these values come from are all negative numbers but the industry standard is to display them as positive (I.E. distance from zero / absolute value). My y axis is used to display the numbers and of course uses the actual value (negative) to label the axis ticks. I do not want to change the values, but am wondering how to access the text elements and just remove the negative symbols from each value(shown in red circles on the image).
Several iterations of code after diving into the matplotlib documentation has gotten me to the following code, but I am still getting an error.
locs, labels = plt.yticks()
newLabels = []
for lbl in labels:
newLabels.append((lbl[0], lbl[1], str(float(str(lbl[2])) * -1)))
plt.yticks(locs, newLabels)
It appears that some of the strings in the "labels" list are empty and therefore the cast isn't working correctly, but I don't understand how it has any empty values if the yticks() method is retrieving the current tick configuration.
#SiHA points out that if we change the data then the order of labels on the y-axis will be reversed. So we can use a ticker formatter to just change the labels without changing the data as shown in the example below:
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import numpy as np
#ticker.FuncFormatter
def major_formatter(x, pos):
label = str(-x) if x < 0 else str(x)
return label
y = np.linspace(-3000,-1000,2001)
fig, ax = plt.subplots()
ax.plot(y)
ax.yaxis.set_major_formatter(major_formatter)
plt.show()
This gives me the following plot, notice the order of y-axis labels.
Edit:
based on the Amit's great answer, here's the solution if you want to edit the data instead of the tick formatter:
import matplotlib.pyplot as plt
import numpy as np
y = np.linspace(-3000,-1000,2001)
fig, ax = plt.subplots()
ax.plot(-y) # invert y-values of the data
ax.invert_yaxis() # invert the axis so that larger values are displayed at the bottom
plt.show()

Python24: Maplotlib Animation connecting the first and the last point

I am new to matplotlib and I was playing with this library to plot data from a csv file. Without using the animation function the graph looks correct, but When I tried to use the animation, the graph connected the first and the last point. I looked stuff up, but I can't figure out how to solve this. Does anyone know how to solve this issue? Below is my code. Thanks in advance!
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import csv
x = []
y = []
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
def animate(i):
with open("example.txt", "r") as csvfile:
plots = csv.reader(csvfile, delimiter=',')
for row in plots:
x.append(int(row[0]))
y.append(int(row[1]))
ax1.clear()
ax1.plot(x,y)
ani = animation.FuncAnimation(fig, animate, interval=1000)
plt.show()
You append all the same points over and over again to the lists to plot. So say the csv file contains numbers 1,2,3 what you are doing is reading them in, appending them to the list, plotting them, then reading them in again and appending them etc.
So x contains in
Step 1 : 1,2,3
Step 2 : 1,2,3,1,2,3
Step 3 : 1,2,3,1,2,3,1,2,3
Hence from step 2 on there will be a connection between 3 and 1.
I don't know what the purpose of this animation is since animating all the same points is quite useless. So there is no straight forward solution, apart from not animating at all.

How to change the the number of digits of the mantissa using offset notation in matplotlib colorbar

I have a contour plot in matplotlib using a colorbar which is created by
from mpl_toolkits.axes_grid1 import make_axes_locatable
divider = make_axes_locatable(axe) #adjust colorbar to fig height
cax = divider.append_axes("right", size=size, pad=pad)
cbar = f.colorbar(cf,cax=cax)
cbar.ax.yaxis.set_offset_position('left')
cbar.ax.tick_params(labelsize=17)#28
t = cbar.ax.yaxis.get_offset_text()
t.set_size(15)
How can I change the colorbar ticklabels (mantissa of exponent) showing up with only 2 digits after the '.' instead of 3 (keeping the off set notation)? Is there a possibility or do I have to set the ticks manually? Thanks
I have tried to use the str formatter
cbar.ax.yaxis.set_major_formatter(FormatStrFormatter('%.2g'))
so far but this doesn't give me the desired result.
The problem is that while the FormatStrFormatter allows to set the format precisely, it is not capable of handling offsets like the 1e-7 in the case from the question.
On the other hand the default ScalarFormatter automatically selects its own format, without letting the user change it. While this is mostly desireable, in this case, we want to specify the format ourself.
A solution is to subclass the ScalarFormatter and reimplement its ._set_format() method, similar to this answer.
Note that you would want "%.2f" instead of "%.2g" to always show 2 digits after the decimal point.
import numpy as np; np.random.seed(0)
import matplotlib.pyplot as plt
import matplotlib.ticker
class FormatScalarFormatter(matplotlib.ticker.ScalarFormatter):
def __init__(self, fformat="%1.1f", offset=True, mathText=True):
self.fformat = fformat
matplotlib.ticker.ScalarFormatter.__init__(self,useOffset=offset,
useMathText=mathText)
def _set_format(self, vmin, vmax):
self.format = self.fformat
if self._useMathText:
self.format = '$%s$' % matplotlib.ticker._mathdefault(self.format)
z = (np.random.random((10,10))*0.35+0.735)*1.e-7
fig, ax = plt.subplots()
plot = ax.contourf(z, levels=np.linspace(0.735e-7,1.145e-7,10))
fmt = FormatScalarFormatter("%.2f")
cbar = fig.colorbar(plot,format=fmt)
plt.show()
Sorry for getting in the loop so late. If you still are looking for a solution, an easier way is as follows.
import matplotlib.ticker as tick
cbar.ax.yaxis.set_major_formatter(tick.FormatStrFormatter('%.2f'))
Note: it's '%.2f' instead of '%.2g'.

networkx graph display using matplotlib- missing labels

I am writing a program which generates satisfiable models (connected graphs) for a specific input string. The details here are not important but the main problem is that each node has a label and such label can be lengthy one. So, what happens is that it does not fit into the figure which results in displaying all the nodes but some labels are partly displayed... Also, the figure that is displayed does not provide an option to zoom out so it is impossible to capture entire graph with full labels on one figure.
Can someone help me out and perhaps suggest a solution?
for i in range(0,len(Graphs)):
graph = Graphs[i]
custom_labels={}
node_colours=['y']
for node in graph.nodes():
custom_labels[node] = graph.node[node]
node_colours.append('c')
#nx.circular_layout(Graphs[i])
nx.draw(Graphs[i], nx.circular_layout(Graphs[i]), node_size=1500, with_labels=True, labels = custom_labels, node_color=node_colours)
#show with custom labels
fig_name = "graph" + str(i) + ".png"
#plt.savefig(fig_name)
plt.show()
Update picture added:
You could scale the figure
import networkx as nx
import matplotlib.pyplot as plt
G = nx.Graph()
G.add_edge('a'*50,'b'*50)
nx.draw(G,with_labels=True)
plt.savefig('before.png')
l,r = plt.xlim()
print(l,r)
plt.xlim(l-2,r+2)
plt.savefig('after.png')
before
after
You could reduce the font size, using the font_size parameter:
nx.draw(Graphs[i], nx.circular_layout(Graphs[i]), ... , font_size=6)

How to set offset with matplotlib

I'm trying to remove the offset that matplotlib automatically put on my graphs. For example, with the following code:
x=np.array([1., 2., 3.])
y=2.*x*1.e7
MyFig = plt.figure()
MyAx = MyFig.add_subplot(111)
MyAx.plot(x,y)
I obtain the following result (sorry, I cannot post image): the y-axis have the ticks 2, 2.5, 3, ..., 6, with a unique "x10^7" at the top of the y axis.
I would like to remove the "x10^7" from the top of the axis, and making it appearing with each tick (2x10^7, 2.5x10^7, etc...). If I understood well what I saw in other topics, I have to play with the use_Offset variable. So I tried the following thing:
MyFormatter = MyAx.axes.yaxis.get_major_formatter()
MyFormatter.useOffset(False)
MyAx.axes.yaxis.set_major_formatter(MyFormatter)
without any success (result unchanged).
Am I doing something wrong? How can I change this behaviour? Or have I to manually set the ticks ?
Thanks by advance for any help !
You can use the FuncFormatter from the ticker module to format the ticklabels as you please:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.ticker import FuncFormatter
x=np.array([1., 2., 3.])
y=2.*x*1.e7
MyFig = plt.figure()
MyAx = MyFig.add_subplot(111)
def sci_notation(x, pos):
return "${:.1f} \\times 10^{{6}}$".format(x / 1.e7)
MyFormatter = FuncFormatter(sci_notation)
MyAx.axes.yaxis.set_major_formatter(MyFormatter)
MyAx.plot(x,y)
plt.show()
On a side note; the "x10^7" value that appears at the top of your axis is not an offset, but a factor used in scientific notation. This behavior can be disabled by calling MyFormatter.use_scientific(False). Numbers will then be displayed as decimals.
An offset is a value you have to add (or subtract) to the tickvalues rather than multiply with, as the latter is a scale.
For reference, the line
MyFormatter.useOffset(False)
should be
MyFormatter.set_useOffset(False)
as the first one is a bool (can only have the values True or False), which means it can not be called as a method. The latter is the method used to enable/disable the offset.