Consider the following code:
import seaborn as sb
import matplotlib.pyplot as plt
import numpy as np
def main():
dst = np.ones((100,100),dtype=np.float32)
ax = plt.subplots(figsize=(17, 17))
sb.heatmap(dst, linewidths=.5, vmax=np.max(dst), vmin=np.min(dst), square=True, cmap="RdYlBu_r", cbar=False).get_figure().savefig("sb_save.png")
plt.show()
if __name__ == "__main__": main()
Now the saved plot looks like this,
which is clearly irregular; on the other hand, this is the output of plt.show(),
which although on a closer look you would still be able to recognize the uneven size of its square cells, it's overall acceptable.
The behavior might have been triggered because of the particulars of invoking savefig but I don't know of an alternative to try here. Any help would be much appreciated.
Related
I saw a post from a few days ago by someone else: pymc3 likelihood math with non-theano function. Even though I think the problem at its core is the same, I thought I would ask with a simpler example:
Inside logp_wrap, I put some made up definition of a likelihood function. It depends on the rv and an observation. In this case I could do this with theano operations, but let's say that I want this function to be more complex and so I cannot use theano.
The problem comes when I try to define the likelihood both in terms of an RV and observations. From what I have seen, this format would work if I was specifying everything in 'logp_wrap' as theano operations.
I have searched around for a solution to this, but haven't found anything where this problem is fully addressed.
The problem in my attempt to do this is actually that the logp_ function is correctly decorated, but the logp_wrap function is only correctly decorated for its input, and not for its output, so I get the error
TypeError: 'TensorVariable' object is not callable.
Would be great if someone had a solution - don't think I am the only one with this problem.
The theano version of this that works (and uses the same function within a function definition) without the #as_op code is here: https://pymc-devs.github.io/pymc3/notebooks/lda-advi-aevb.html?highlight=densitydist (Specifically the sections: "Log-likelihood of documents for LDA" and "LDA model section")
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
"""
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import pymc3 as pm
from theano import as_op
import theano.tensor as T
from scipy.stats import norm
#Some data that we observed
g_observed = [0.0, 1.0, 2.0, 3.0]
#Define a function to calculate the logp without using theano
#This as_op is where the problem is - the input is an rv but the output is a
#function.
#as_op(itypes=[T.dscalar],otypes=[T.dscalar])
def logp_wrap(rv):
#We are not using theano so we wrap the function.
#as_op(itypes=[T.dvector],otypes=[T.dscalar])
def logp_(ob):
#Some made up likelihood -
#The key here is that lp depends on the rv input and the observations
lp = np.log(norm.pdf(rv + ob))
return lp
return logp_
hb1_model = pm.Model()
with hb1_model:
I_mean = pm.Normal('I_mean', mu=0.1, sd=0.05)
xs = pm.DensityDist('x', logp_wrap(I_mean),observed = g_observed)
with hb1_model:
step = pm.Metropolis()
trace = pm.sample(1000, step)
Case 1: This code runs fine:
import numpy as np
import cv2
from matplotlib import pyplot as plt
imgL = cv2.imread('lena.png', 0)
imgR = cv2.imread('lena.png', 0)
stereo = cv2.StereoBM(0, ndisparities=16, SADWindowSize=15)
stereo.compute(imgL, imgR)
Case 2: But this fails on the last line:
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('lena.png', 1)
imgR = img[:,:,2]
imgL = img[:,:,1]
stereo = cv2.StereoBM(0, ndisparities=16, SADWindowSize=15)
stereo.compute(imgL, imgR)
The error says:
error: /build/buildd/opencv-2.3.1/modules/calib3d/src/stereobm.cpp:802: error: (-211) SADWindowSize must be odd, be within 5..255 and be not larger than image width or height in function findStereoCorrespondenceBM
The really strange thing is that it fails with the same message even if I put following two lines right in front of the imgR = and imgL = starting lines, i.e.:
img = cv2.imread('lena.png', 1)
img[:,:,2] = cv2.imread('lena.png', 0)
img[:,:,1] = cv2.imread('lena.png', 0)
imgR = img[:,:,2]
imgL = img[:,:,1]
I'm still quite new to Python so maybe its a misunderstanding: Can somebody explain why case 1 works but case 2 gives me an error?
It looks like it's a bug in old OpenCV version.
Part of OpenCV 2.4.4 changelog:
Numerous bug fixes, and optimizations, including in: blendLinear, square samples, erode/dilate, Canny, convolution fixes with AMD FFT library, mean shift filtering, Stereo BM.
Most likely using 2.4.4 or any higher version (I suggest that you use the latest stable release) will solve your problem.
I'm new to Python with a question about Cartopy being able to be used in a 3D plot. Below is an example using matplotlibBasemap.
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.basemap import Basemap
m = Basemap(projection='merc',
llcrnrlat=52.0,urcrnrlat=58.0,
llcrnrlon=19.0,urcrnrlon=40.0,
rsphere=6371200.,resolution='h',area_thresh=10)
fig = plt.figure()
ax = Axes3D(fig)
ax.add_collection3d(m.drawcoastlines(linewidth=0.25))
ax.add_collection3d(m.drawcountries(linewidth=0.35))
ax.add_collection3d(m.drawrivers(color='blue'))
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Height')
fig.show()
This creates a map within a 3D axis so that you can plot objects over the surface. But with Cartopy returns a matplotlib.axes.GeoAxesSubplot. Not clear how to take this and add to a 3D figure/axis as above with matplotlib-basemap.
So, can someone give any pointers on how to do a similar 3D plot with Cartopy?
The basemap mpl3d is a pretty neat hack, but it hasn't been designed to function in the described way. As a result, you can't currently use the same technique for much other than simple coastlines. For example, filled continents just don't work AFAICT.
That said, a similar hack is available when using cartopy. Since we can access shapefile information generically, this solution should work for any poly-line shapefile such as coastlines.
The first step is to get hold of the shapefile, and the respective geometries:
feature = cartopy.feature.NaturalEarthFeature('physical', 'coastline', '110m')
geoms = feature.geometries()
Next, we can convert these to the desired projection:
target_projection = ccrs.PlateCarree()
geoms = [target_projection.project_geometry(geom, feature.crs)
for geom in geoms]
Since these are shapely geometries, we then want to convert them to matplotlib paths with:
from cartopy.mpl.patch import geos_to_path
import itertools
paths = list(itertools.chain.from_iterable(geos_to_path(geom)
for geom in geoms))
With paths, we should be able to just create a PathCollection in matplotlib, and add it to the axes, but sadly, Axes3D doesn't seem to cope with PathCollection instances, so we need to workaround this by constructing a LineCollection (as basemap does). Sadly LineCollections don't take paths, but segments, which we can compute with:
segments = []
for path in paths:
vertices = [vertex for vertex, _ in path.iter_segments()]
vertices = np.asarray(vertices)
segments.append(vertices)
Pulling this all together, we end up with a similar result to the basemap plot which your code produces:
import itertools
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
import numpy as np
import cartopy.feature
from cartopy.mpl.patch import geos_to_path
import cartopy.crs as ccrs
fig = plt.figure()
ax = Axes3D(fig, xlim=[-180, 180], ylim=[-90, 90])
ax.set_zlim(bottom=0)
target_projection = ccrs.PlateCarree()
feature = cartopy.feature.NaturalEarthFeature('physical', 'coastline', '110m')
geoms = feature.geometries()
geoms = [target_projection.project_geometry(geom, feature.crs)
for geom in geoms]
paths = list(itertools.chain.from_iterable(geos_to_path(geom) for geom in geoms))
# At this point, we start working around mpl3d's slightly broken interfaces.
# So we produce a LineCollection rather than a PathCollection.
segments = []
for path in paths:
vertices = [vertex for vertex, _ in path.iter_segments()]
vertices = np.asarray(vertices)
segments.append(vertices)
lc = LineCollection(segments, color='black')
ax.add_collection3d(lc)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Height')
plt.show()
On top of this, mpl3d seems to handle PolyCollection well, which would be the route I would investigate for filled geometries, such as the land outline (as opposed to the coastline, which is strictly an outline).
The important step is to convert the paths to polygons, and use these in a PolyCollection object:
concat = lambda iterable: list(itertools.chain.from_iterable(iterable))
polys = concat(path.to_polygons() for path in paths)
lc = PolyCollection(polys, edgecolor='black',
facecolor='green', closed=False)
The complete code for this case would look something like:
import itertools
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection, PolyCollection
import numpy as np
import cartopy.feature
from cartopy.mpl.patch import geos_to_path
import cartopy.crs as ccrs
fig = plt.figure()
ax = Axes3D(fig, xlim=[-180, 180], ylim=[-90, 90])
ax.set_zlim(bottom=0)
concat = lambda iterable: list(itertools.chain.from_iterable(iterable))
target_projection = ccrs.PlateCarree()
feature = cartopy.feature.NaturalEarthFeature('physical', 'land', '110m')
geoms = feature.geometries()
geoms = [target_projection.project_geometry(geom, feature.crs)
for geom in geoms]
paths = concat(geos_to_path(geom) for geom in geoms)
polys = concat(path.to_polygons() for path in paths)
lc = PolyCollection(polys, edgecolor='black',
facecolor='green', closed=False)
ax.add_collection3d(lc)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Height')
plt.show()
To yield:
Following this example:
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
for i, label in enumerate(('A', 'B', 'C', 'D')):
ax = fig.add_subplot(2,2,i+1)
ax.text(0.05, 0.95, label, transform=ax.transAxes,
fontsize=16, fontweight='bold', va='top')
plt.show()
I get this output:
Why are my labels normal weight, while the documentation shows this should create bold letters A, B, C, D?
I also get this warning:
Warning (from warnings module):
File "C:\Python27\lib\site-packages\matplotlib\font_manager.py", line 1228
UserWarning)
UserWarning: findfont: Could not match :family=Bitstream Vera Sans:style=italic:variant=normal:weight=bold:stretch=normal:size=x-small. Returning C:\Python27\lib\site-packages\matplotlib\mpl-data\fonts\ttf\Vera.ttf
OP Resolution
From a deleted answer posted by the OP on Sep 15, 2013
Ok, it was a problem with the installation of matplotlib
Try using weight instead of fontweight.
Maybe try using this -
plt.rcParams['axes.labelsize'] = 16
plt.rcParams['axes.labelweight'] = 'bold'
Do this at a global level in your program.
The example from your question works on my machine. Hence you definately have a library problem. Have you considered using latex to make bold text? Here an example
Code
import numpy as np
import matplotlib.pyplot as plt
fig, axs = plt.subplots(3, 1)
ax0, ax1, ax2 = axs
ax0.text(0.05, 0.95, 'example from question',
transform=ax0.transAxes, fontsize=16, fontweight='bold', va='top')
ax1.text(0.05, 0.8, 'you can try \\textbf{this} using \\LaTeX', usetex=True,
transform=ax1.transAxes, fontsize=16, va='top')
ax2.text(0.05, 0.95,
'or $\\bf{this}$ (latex math mode with things like '
'$x_\mathrm{test}^2$)',
transform=ax2.transAxes, fontsize=10, va='top')
plt.show()
Not sure if you're still having the issue. I tried your code in Anaconda/Spyder, Python 2.7. The plots appear with Bold labels (A,B,C,D). I agree the issue is probably with the library. Try replacing / updating font_manager.py or confirming font files are present:
Lib\site-packages\matplotlib\mpl-data\fonts\ttf\
I had the same problem and spent quite a few hours today on that. Here`s the solution that helped me:
import matplotlib
matplotlib.font_manager._rebuild()
With this, the font_manager could be upgraded easily.
Is it possible to integrate any Ordinary Differential Equation backward in time
using scipy.integrate.odeint ?
If it is possible, could someone tell me what should be the arguement 'time' in 'odeint.
odeint handles negative values of the t argument. No special treatment is needed.
Here's an example:
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
def mysys(z, t):
"""A slightly damped oscillator."""
return [z[1] - 0.02*z[0], -z[0]]
if __name__ == "__main__":
# Note that t starts at 0 and goes "backwards"
t = np.linspace(0, -50, 501)
z0 = [1, 1]
sol = odeint(mysys, z0, t)
plt.plot(t, sol)
plt.xlabel('t')
plt.show()
The plot:
You can make a change of variables s = t_0 - t, and integrate the differential equation with respect to s. odeint doesn't do this for you.
It is not necessary to make a change of variables. Here an example:
import math
import numpy
import scipy
import pylab as p
from math import *
from numpy import *
from scipy.integrate import odeint
from scipy.interpolate import splrep
from scipy.interpolate import splev
g1=0.01
g2=0.01
w1=1
w2=1
b1=1.0/20.0
b2=1.0/20.0
b=1.0/20.0
c0=0
c1=0.2
wf=1
def wtime(t):
f=1+c0+c1*cos(2*wf*t)
return f
def dv(y,t):
return array([y[1], -(wtime(t)+g1*w1+g2*w2)*y[0]+w1*y[2]+w2*y[3], w1*y[2]-g1*w1*y[0], w2*y[3]-g2*w2*y[0]])
tv=linspace(100,0,1000)
v1zero=array([1,0,0,0])
v2zero=array([0,1,0,0])
v1s=odeint(dv,v1zero,tv)
v2s=odeint(dv,v2zero,tv)
p.plot(tv,v1s[:,0])
p.show()
I check the result with Wolfram Mathematica (that program can solve backward odes).