python2.7-colorbar: how to set color scale tick font? - colorbar

import matplotlib.pyplot as plt
import numpy as np
from numpy import ma
from matplotlib import ticker, cm
N = 100
x = np.linspace(-3.0,3.0,N) # x value
y = np.linspace(-2.0,2.0,N) # y value
X, Y = np.meshgrid(x,y)
Z1 = np.exp(-(X)**2 - (Y)**2)
Z2 = np.exp(-(X*10)**2 - (Y*10)**2)
z = Z1 + 50 * Z2
z[:5, :5] = -1
z = ma.masked_where(z<=0,z)
fig, ax = plt.subplots()
cs = ax.contourf(X,Y,z,locator=ticker.LogLocator(),cmap=cm.PuBu_r)
cbar = fig.colorbar(cs) # add colorbar
plt.show()
the result is shown as follow:
image 1
question: how to set color scale tick font?

just add cbar.ax.set_yticklabels line of code
import matplotlib.pyplot as plt
import numpy as np
from numpy import ma
from matplotlib import ticker, cm
N = 100
x = np.linspace(-3.0,3.0,N) # x value
y = np.linspace(-2.0,2.0,N) # y value
X, Y = np.meshgrid(x,y)
Z1 = np.exp(-(X)**2 - (Y)**2)
Z2 = np.exp(-(X*10)**2 - (Y*10)**2)
z = Z1 + 50 * Z2
z[:5, :5] = -1
z = ma.masked_where(z<=0,z)
fig, ax = plt.subplots()
cs = ax.contourf(X,Y,z,locator=ticker.LogLocator(),cmap=cm.PuBu_r)
cbar = fig.colorbar(cs) # add colorbar
cbar.ax.set_yticklabels(cbar.values, fontname="Arial Black") #this line has been added, i am setting font as Arial Black
plt.show()
Please modify the values as per your need

Related

Bayesian calibration for ode system

I tried to use the 'pymc3' package in Python to calibrate a first-order ODE system in a Bayesian way.
I started with a toy ODE system first. It is dy1/dt = y2; dy2/dt = -b* y2 - c*sin(y1). b and c are the parameters I want to calibrate.
Firstly, I generated some outputs for y1 and y2 from t[0,10] by setting parameters b = 0.25 and c = 0.5 with normally distributed noise~N(0,0.7^2). Then, I calibrated the ODE system by setting prior distributions for b~N(0,1) and c~N(0,9) and sigma~HalfNormal
But it gave the errors: (1) TypeError: float() argument must be a string or a number, not 'TensorVariable'(2)ValueError: setting an array element with a sequence.
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
from scipy.integrate import ode
import pymc3 as pm
def pend(y, t, b, c):
theta, omega = y
dydt = [omega, -b*omega - c*np.sin(theta)]
return dydt
true_b = 0.25
true_c = 5.0
y0 = [np.pi - 0.1, 0.0]
t = np.linspace(0, 10, 101)
sol = odeint(pend, y0, t, args=(true_b, true_c))
true_sigma = 0.7
noise = np.random.randn(101,2)*true_sigma
Y_obs = sol+noise
pend_model = pm.Model()
with pend_model:
# Priors for unknown model parameters
b = pm.Normal('b', mu=0, sd=1)
c = pm.Normal('c', mu=7, sd=3)
sigma = pm.HalfNormal('sigma', sd=1)
# Expected value of outcome
mu = odeint(pend, y0, t, args=(b, c))
# Likelihood (sampling distribution) of observations
Y = pm.Normal('Y_obs', mu=mu, sd=sigma, observed=Y_obs)
trace = pm.sample(draws=5000, tune=500, chains=1)

convert hued displot of X to plot of hue vs mode(X given hue)?

I have a Seaborn displot with a hued variable:
For each hued variable, I want to extract the mode of the density estimate and then plot each hue variable versus its mode, like so:
How do I do this?
You can use scipy.stats.gaussian_kde to create the density estimation function. And then call that function on an array of x-values to calculate its maximum.
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
df = pd.DataFrame({'x': np.random.normal(0.001, 1, 1300).cumsum() + 30,
'hue': np.repeat(np.arange(0.08, 0.20001, 0.01), 100).round(2)})
g = sns.displot(df, x='x', hue='hue', palette='turbo', kind='kde', fill=True, height=6, aspect=1.5)
plt.show()
from scipy.stats import gaussian_kde
from matplotlib.cm import ScalarMappable
fig, ax = plt.subplots(figsize=(10, 6))
hues = df['hue'].unique()
num_hues = len(hues)
colors = sns.color_palette('turbo', num_hues)
xmin, xmax = df['x'].min(), df['x'].max()
xs = np.linspace(xmin, xmax, 500)
for hue, color in zip(hues, colors):
data = df[df['hue'] == hue]['x'].values
kde = gaussian_kde(data)
mode_index = np.argmax(kde(xs))
mode_x = xs[mode_index]
sns.scatterplot(x=[hue], y=[mode_x], color=color, s=50, ax=ax)
cmap = sns.color_palette('turbo', as_cmap=True)
norm = plt.Normalize(hues.min(), hues.max())
plt.colorbar(ScalarMappable(cmap=cmap, norm=norm), ax=ax, ticks=hues)
plt.show()
Here is another approach, extracting the kde curves. It uses the legend of the kde plot to get the correspondence between the curves and the hue values. sns.kdeplot is the axes-level function used by sns.displot(kind='kde'). fill=False creates lines instead of filled polygons for the curves, for which the values are easier to extract. (ax1.fill_between can fill the curves during a second pass). The x and y axes of the second plot are switched to align the x-axes of both plots.
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
df = pd.DataFrame({'x': np.random.normal(0.007, 0.1, 1300).cumsum() + 30,
'hue': np.repeat(np.arange(0.08, 0.20001, 0.01), 100).round(2)})
fig, (ax1, ax2) = plt.subplots(nrows=2, figsize=(12, 10), sharex=True)
sns.kdeplot(data=df, x='x', hue='hue', palette='turbo', fill=False, ax=ax1)
hues = [float(txt.get_text()) for txt in ax1.legend_.get_texts()]
ax2.set_yticks(hues)
ax2.set_ylabel('hue')
for hue, line in zip(hues, ax1.lines[::-1]):
color = line.get_color()
x = line.get_xdata()
y = line.get_ydata()
ax1.fill_between(x, y, color=color, alpha=0.3)
mode_ind = np.argmax(y)
mode_x = x[mode_ind]
sns.scatterplot(x=[mode_x], y=hue, color=color, s=50, ax=ax2)
sns.despine()
plt.tight_layout()
plt.show()

Animated Polar Plot

I am trying to make an animated plot of planetary motion using python. I can get the correct path to show up when not animated but once I try to animate it, it just shows up blank even though r and i are being output as the correct values when I try to print each value in the console.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig = plt.figure(figsize=(6,6))
ax = plt.subplot(111, polar=True)
ax.set_ylim(0,1)
line, = ax.plot([],[])
semi_major_axis = 1
eccentricity = 0.1
theta = np.linspace(0,2*np.pi, num = 50)
point, = ax.plot(0,1, marker="o")
def frame(i):
r=(semi_major_axis*(1-eccentricity**2)/(1-eccentricity*np.cos(i)))
line.set_xdata(i)
line.set_ydata(r)
return line,
ax.set_rmax(semi_major_axis+1)
ax.set_rticks(np.linspace(0,semi_major_axis+1, num = 5))
ax.set_rlabel_position(-22.5)
animation = FuncAnimation(fig, func=frame, frames=theta, interval=10)
plt.show()
I think the problem is you are plotting a point and not a line. The following code worked for me:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig = plt.figure(figsize=(6, 6))
ax = plt.subplot(111, polar=True)
ax.set_ylim(0, 1)
semi_major_axis = 1
eccentricity = 0.1
theta = np.linspace(0, 2 * np.pi, num=50)
def frame(i):
r = (semi_major_axis * (1 - eccentricity ** 2) / (1 - eccentricity * np.cos(i)))
ax.plot(i,r,'b', marker='o')
ax.set_rmax(semi_major_axis + 1)
ax.set_rticks(np.linspace(0, semi_major_axis + 1, num=5))
ax.set_rlabel_position(-22.5)
animation = FuncAnimation(fig, func=frame, frames=theta, interval=10)
plt.show()

Matplotlib Countour not Connected

As a Python novice and trying to visualize the curve X2*Y + X*Y2 - X4 - Y4 = 0 with Matplotlib:
from matplotlib.pyplot import *
from sympy import *
from numpy import *
delta = 0.025
p = arange(-0.5, 1.5, delta)
q = arange(-0.5, 1.5, delta)
X, Y = meshgrid(p, q)
Z = X**2*Y + X*Y**2 - X**4 - Y**4
fig, ax = subplots()
CS = ax.contour(X, Y, Z, [0], colors ='k')
ax.set_title('x**2*y + x*y**2 - x**4 - y**4')
show()
the result is that the plot is not connected, whereas mathematically, it should be so. How can the level set be connected?
It's a year later, but for future reference: You just have to choose a smaller stepsize delta. With your delta = 0.025 your get the disconnected picture:
With delta = 0.001 you get a more accurate connected picture:

Updating matplotlib live graph in wxPython panel with scrolling x-axis

I am trying to animate a live graph in a wx.Panel. I would like to have the x-axis update like this example. Many of the examples I see are basic and don't take into consideration other controls and functions in the class. Others have so many extras that I get lost in the weeds. I can't get the animation command in the right place or update the x-axis. Here is the code:
import wx
import logging
import numpy as np
import matplotlib
import time
import matplotlib.animation as animation
matplotlib.use('WXAgg')
import matplotlib.pyplot as plt
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wx import NavigationToolbar2Wx
from matplotlib.figure import Figure
fTemp = ""
x = 0
class TempClass(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, title="", size=(600,500))
panel = wx.Panel(self)
self.fig = Figure(figsize=(6,4), dpi=75, facecolor='lightskyblue', edgecolor='r')
self.canvas = FigureCanvas(self, -1, self.fig)
self.ax = self.fig.add_subplot(111)
self.ax2 = self.ax.twinx()
self.ax.set_ylim(60,90)
self.ax.set_xlim(0,24)
self.ax2.set_ylim(0,100)
# major ticks every 5, minor ticks every 1
xmajor_ticks = np.arange(0, 24, 5)
xminor_ticks = np.arange(0, 24, 1)
self.ax.set_xticks(xmajor_ticks)
self.ax.set_xticks(xminor_ticks, minor=True)
self.ax.grid()
self.ax.set_xlabel('Hour')
self.ax.set_ylabel('Temp')
self.ax2.set_ylabel('Humidity')
self.ax.set_title('Temperature')
# The graph does not show in the panel when this in uncommented
#self.ani = animation.FuncAnimation(self.fig, self.onPlotTemp, interval=1000)
self.fanSensorTimer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.onPlotTemp, self.fanSensorTimer)
self.fanSensorBtn = wx.Button(self, -1, "Start Sensor")
self.Bind(wx.EVT_BUTTON, self.onStartTempPlot, self.fanSensorBtn)
font1 = wx.Font(18, wx.DEFAULT,wx.NORMAL,wx.BOLD)
self.displayTemp = wx.StaticText(self, -1, "Current Tempurature")
self.curTempTxt = wx.TextCtrl(self, -1, "0",size=(100,40), style=wx.TE_READONLY|wx.TE_CENTRE|wx.BORDER_NONE)
self.curTempTxt.SetFont(font1)
self.displayHum = wx.StaticText(self, -1, "Current Humidity")
self.curHumTxt = wx.TextCtrl(self, -1,"0", size=(100,40), style=wx.TE_READONLY|wx.TE_CENTRE|wx.BORDER_NONE)
self.curHumTxt.SetFont(font1)
self.displayBox = wx.GridBagSizer(hgap=5,vgap=5)
self.displayBox.Add(self.displayTemp, pos=(0,0), flag=wx.TOP|wx.LEFT, border=5)
self.displayBox.Add(self.displayHum, pos=(0,1), flag=wx.TOP, border=5)
self.displayBox.Add(self.curTempTxt, pos=(1,0), flag=wx.ALL, border=5)
self.displayBox.Add(self.curHumTxt, pos=(1,1), flag=wx.ALL, border=5)
#---------
self.vbox = wx.BoxSizer(wx.VERTICAL)
self.vbox.Add(self.canvas, wx.ALIGN_CENTER|wx.ALL, 1)
self.vbox.Add(self.fanSensorBtn)
self.vbox.Add(self.displayBox, wx.ALIGN_CENTER|wx.ALL, 1)
self.SetSizer(self.vbox)
self.vbox.Fit(self)
def start(self):
# get temp/humidity reading from node
pass
def readTemp(self, data1, data2):
"Populates Current Temp"
global fTemp
self.curTempTxt.Clear()
a = format(data1, '08b')
b = format(data2, '08b')
x = a+b
y = int(x, base=2)
cTemp = ((175.72 * y)/65536)-46.85
fTemp = cTemp *1.8+32
cel = format(cTemp,'.1f')
far = format(fTemp,'.1f')
self.curTempTxt.WriteText(far + (u'\u00b0')+"F")
def rh1(self, data1, data2):
"Populates Current RH"
global relhum
self.curHumTxt.Clear()
a = format(data1, '08b')
b = format(data2, '08b')
x = a+b
y = int(x, base=2)
rh = ((125 * y)/65536)-6
relhum = format(rh,'.1f')
self.curHumTxt.WriteText(relhum + " %")
def onStartTempPlot(self,event):
#set for a short time period for testing purposes
self.fanSensorTimer.Start(5000)
print "Timer Started"
def onPlotTemp(self,event):
global fTemp, x, relhum
x +=1
y = int(fTemp)
y2 = float(relhum)
self.ax.plot(x,y,'r.')
self.ax2.plot(x,y2,'k.')
self.fig.canvas.draw()
# send message to node for another reading of temp/humidity
if __name__ == "__main__":
app = wx.App(False)
frame = TempClass()
frame.Show()
frame.start()
logging.basicConfig(level=logging.DEBUG)
app.MainLoop()
I would like to see the x axis increment as the data is plotted beyond the 24 hour point on the graph; when data for point 25 appears, the first point is dropped and the x axis shows '25'. The animation is commented out because it causes the graph to disappear until a point is plotted.
Here is a runnable example of what I am trying to achieve with the x axis:
import numpy
from matplotlib.pylab import *
from mpl_toolkits.axes_grid1 import host_subplot
import matplotlib.animation as animation
# Sent for figure
font = {'size' : 9}
matplotlib.rc('font', **font)
# Setup figure and subplots
f0 = figure(num = 0, figsize = (6, 4))#, dpi = 100)
f0.suptitle("Oscillation decay", fontsize=12)
ax01 = subplot2grid((2, 2), (0, 0))
# Set titles of subplots
ax01.set_title('Position vs Time')
# set y-limits
ax01.set_ylim(0,2)
# sex x-limits
ax01.set_xlim(0,1)
# Turn on grids
ax01.grid(True)
# set label names
ax01.set_xlabel("x")
ax01.set_ylabel("py")
# Data Placeholders
yp1=zeros(0)
yv1=zeros(0)
yp2=zeros(0)
yv2=zeros(0)
t=zeros(0)
# set plots
p011, = ax01.plot(t,yp1,'b-', label="yp1")
p012, = ax01.plot(t,yp2,'g-', label="yp2")
# set lagends
ax01.legend([p011,p012], [p011.get_label(),p012.get_label()])
# Data Update
xmin = 0
xmax = 24
x = 0
def updateData(self):
global x
global yp1
global yv1
global yp2
global yv2
global t
tmpp1 = 1 + exp(-x) *sin(2 * pi * x)
tmpv1 = - exp(-x) * sin(2 * pi * x) + exp(-x) * cos(2 * pi * x) * 2 * pi
yp1=append(yp1,tmpp1)
yv1=append(yv1,tmpv1)
yp2=append(yp2,0.5*tmpp1)
yv2=append(yv2,0.5*tmpv1)
t=append(t,x)
x += 1
p011.set_data(t,yp1)
p012.set_data(t,yp2)
if x >= xmax-1:
p011.axes.set_xlim(x-xmax+1,x+1)
return p011
# interval: draw new frame every 'interval' ms
# frames: number of frames to draw
simulation = animation.FuncAnimation(f0, updateData, blit=False, frames=200, interval=20, repeat=False)
plt.show()
You are not incrementing the X axis limit or the ticks.
def onPlotTemp(self,event):
global fTemp, x, relhum
x +=1
y = int(fTemp)
y2 = float(relhum)
if x >= 24-1:
self.ax.set_xlim(x-24+1,x+1)
xmajor_ticks = np.arange(x-24+1,x+5, 5)
xminor_ticks = np.arange(x-24+1, x+1,1)
self.ax.set_xticks(xmajor_ticks)
self.ax.set_xticks(xminor_ticks, minor=True)
self.ax.plot(x,y,'r.')
self.ax2.plot(x,y2,'k.')
self.fig.canvas.draw()
I'm not sure if the above resets the ticks the way you want them but you get the idea. Obviously I have hard-coded 24 as your limit, you may want to create a variable to sort that out.

Resources