This is probably a stupid question, but whenever I'm using the .plot() function it plots the summary twice. Anyone knows, why it does that and how I can stop it?
As you can see I'm using jupyter notebooks if that matters.
It happens with any stan model (and on two separate installations)
This code would produce the problem for me
import pystan
import numpy as np
model_string = """
data {
int<lower=0> N;
int y[N];
}
parameters {
real<lower=0, upper=1> theta;
}
model {
theta ~ beta(1,1);
y ~ bernoulli(theta);
}
"""
N = 50
z = 10
y = np.append(np.repeat(1, z), np.repeat(0, N - z))
dat = {'y':y,
'N':N}
fit = pystan.stan(model_code=model_string, data=dat, iter=1000, warmup=200, thin=1, chains = 3)
fit.plot()
This is caused by the %matplotlib inline statement drawing more than you want it to. The StanFit4Model.plot method calls matplotlib.pyplot.subplot, and that call itself will draw a plot when your notebook has %matplotlib inline. Then the method returns the Figure object. If you don't capture it, your notebook decides to show it to you as an image instead of printing the type, and you get the double plot.
You can output a single plot by capturing the output Figure. Change your code from
fit.plot()
to instead be
fig = fit.plot()
Putting a semicolon after the `.plot()' also does the trick.
Learned it from https://github.com/stan-dev/pystan/issues/230
Related
Here is the Python code. I am using a function here which should return a float value. However, it is also returning the graph as sns.distplot is called. Is there any way to only return the numeric value?
data = []
for idx, var in enumerate(df):
myPlot = sns.distplot(df['Acceleration'])
lines2D = [obj for obj in myPlot.findobj() if str(type(obj)) == "<class 'matplotlib.lines.Line2D'>"]
x, y = lines2D[idx].get_data()[0], lines2D[idx].get_data()[1]
data.append(pd.DataFrame({'x':x, 'y':y}))
limit=pd.DataFrame(data[0]).loc[data[0]['y']>=0.01]['x']
limit=limit.values.tolist()
off= df[(df.Acceleration< limit[0]) | (df.Acceleration>limit[-1])]
return len(off)/len(df)
In case you're using jupyter:
I don't think your graph is returned by the function, it is simply displayed while "working" your function. Try inserting plt.close() at the end of your for loop block and I'm sure your plot won't show anymore. I've tried it and it works, the sns plot display will be suppressed. Make sure to put import matplotlib.pyplot as plt at the top of your file.
Maybe this will be duplicate question but I couldn't find any solution for this.
Normally what I coded should show me a curved line in python. But with this code I cant see it. Is there a problem with my code or pycharm ? This code only shows me an empty graphic with the correct axes.
And I did adding "ro" in plt.plot(at[i], st, "ro"). This showed me the spots on the graph but what I want to see the complete line.
at = [0,1,2,3,4,5,6]
for i in range(len(at)):
st = at[i]**2
plt.plot(at[i], st)
plt.show()
This is how you would normally do this:
import numpy as np
import matplotlib.pyplot as plt
at = np.array([0,1,2,3,4,5,6])
at2 = at ** 2
plt.plot(at,at2)
plt.show()
you can use something like plt.plot(at,at2, c='red', marker='o') to see the spots.
for detailed explanation please read the documentation.
Maybe rather calculate the to be plotted values entirely before plotting.
at = [0,1,2,3,4,5,6]
y = [xi**2 for xi in at]
plt.plot(at, y)
Or do it alternatively with a function
from math import pow
at = [0,1,2,3,4,5,6]
def parabolic(x):
return [pow(xi,2) for xi in x]
plt.plot(at, parabolic(at))
both return the following plot:
the other answers give fixes for your question, but don't tell you why your code is not working.
the reason for not "seeing anything" is that plt.plot(at[i], st) was trying to draw lines between the points you give it. but because you were only ever giving it single values it didn't have anything to draw lines between. as a result, nothing appeared on the plot
when you changed to call plt.plot(at[i], st, 'ro') you're telling it to draw single circles at points and these don't go between points so would appear
the other answers showed you how to pass multiple values to plot and hence matplotlib could draw lines between these values.
one of your comments says "its not parabolic still" and this is because matplotlib isn't a symbolic plotting library. you just give it numeric values and it draws these onto the output device. sympy is a library for doing symbolic computation and supports plotting, e.g:
from sympy import symbols, plot
x = symbols('x')
plot(x**2, (x, 0, 6))
does the right thing for me. the current release (1.4) doesn't handle discontinuities, but this will be fixed in the next release
I would like to create plot images from a NetCDF at each time step.
My NetCDF files look like this:
netcdf file:/C:/home/data/cmorph/test/reduced_cmorph_adjusted_spi_pearson_01.nc {
dimensions:
time = UNLIMITED; // (240 currently)
lat = 120;
lon = 360;
variables:
float spi_pearson_01(time=240, lat=120, lon=360);
:_FillValue = NaNf; // float
:valid_min = -3.09; // double
:valid_max = 3.09; // double
:long_name = "Standard Precipitation Index (Pearson Type III distribution), 1-month scale";
:_ChunkSizes = 1, 120, 360; // int
int time(time=240);
:units = "days since 1800-01-01 00:00:00";
:_ChunkSizes = 1024; // int
:_CoordinateAxisType = "Time";
float lat(lat=120);
:units = "degrees_north";
:_CoordinateAxisType = "Lat";
float lon(lon=360);
:units = "degrees_east";
:_CoordinateAxisType = "Lon";
// global attributes:
:title = "CMORPH Version 1.0BETA Version, daily precip from 00Z-24Z";
:history = "Wed Feb 28 07:30:01 2018: C:\\home\\miniconda\\Library\\bin\\ncks.exe --dmn lon,0,,4 --dmn lat,0,,4 CMORPH_V1.0_ADJ_0.25deg-DLY_00Z_1998_2017.nc cmorph_reduced_adjusted.nc";
:NCO = "4.7.1";
:_CoordSysBuilder = "ucar.nc2.dataset.conv.DefaultConvention";
}
I like the plots produced by Panoply but I haven't worked out how to script it (I don't want to go through the GUI for this since I'll have roughly 1500 plots to create). I'm not wedded to Panoply per se, so if someone has a better idea please advise. I could hammer this out in matplotlib but it'd take me quite a while and wouldn't look as good as the Panoply plots. I'm trying to avoid doing much if any of the plotting myself, but maybe there's something out there that provides easy plotting of NetCDFs which can be called from a script (I typically use Python and Bash).
Example using xarray:
import xarray as xr
import matplotlib
import matplotlib.pyplot as plt
matplotlib.use('Agg')
file_name = "reduced_cmorph_adjusted_spi_pearson_01.nc"
with xr.open_dataset(file_name) as ds:
for t in range(ds.time.shape[0]):
da = ds.spi_pearson_01.isel(time=t)
plt.figure()
da.plot()
plt.savefig('frame{}.png'.format(t))
Non-scripting method if you don't mind using a few clicks in Panoply: create a lat/lon plot and then choose File->Export Animation . You can output individual time steps as JPG or PNG.
I'm kind of assuming you don't want to insert 1500 figures in a report or talk and therefore the purpose of this is just to investigate the file slice by slice. If this is the case I would simply open the file using
ncview file.nc
This allows you to step through the slices, animate, pass the cursor over the slices to see the values and click on a point to see a timeseries. If you don't have it, you can install it easily with apt-get (ubuntu, mint etc) with
sudo apt-get install ncview
I am using ipython notebook and trying to use the following function to export seaborn distplots. It works just fine if I call the function and execute with only one variable at a time. If I call the function in a loop, it continues to build on top of the distplot from the previous function call.
My desired output would be for the function to output a new displot every time it is called in a loop. Is there a way to force evaluation or a new distplot?
def graph_extraversion (x):
file_name = "extraversion_" + str(x) + ".png"
sns_plot = sns.distplot(Personalities[Personalities.labels1 ==x].extraversion)
sns_plot = sns.distplot(df.extraversion)
fig = sns_plot.get_figure()
fig.savefig(file_name)
new_stat = Personalities[Personalities.labels1 ==x].extraversion.describe()
extraversion_drift = extraversion_median - new_stat[1]
drift = extraversion_drift / extraversion_std
if (drift >= 1) | (drift <= -1):
return "1 std deviation or more"
else:
return "Less than one std deviation"
This what is what the distplot looks like after one call
This is two calls later in a loop.
Again this works just fine with a single call and execution but when looped it keeps building.
So this has to do with matplotlib and closing figures.
additional code required is an import:
import matplotlib.pyplot as plt
Then at the end of the func:
plt.close(fig)
This should help with any looping with both seaborn and matplotlib
I am trying to create four gabor patches, very similar to those below.
I don't need them to be identical to the pictures below, but similar.
Despite a bit of tinkering, I have been unable to reproduce these images...
I believe they were created in MATLAB originally. I don't have access to the original MATLAB code.
I have the following code in python (2.7.10):
import numpy as np
from scipy.misc import toimage # One can also use matplotlib*
data = gabor_fn(sigma = ???, theta = 0, Lambda = ???, psi = ???, gamma = ???)
toimage(data).show()
*graphing a numpy array with matplotlib
gabor_fn, from here, is defined below:
def gabor_fn(sigma,theta,Lambda,psi,gamma):
sigma_x = sigma;
sigma_y = float(sigma)/gamma;
# Bounding box
nstds = 3;
xmax = max(abs(nstds*sigma_x*numpy.cos(theta)),abs(nstds*sigma_y*numpy.sin(theta)));
xmax = numpy.ceil(max(1,xmax));
ymax = max(abs(nstds*sigma_x*numpy.sin(theta)),abs(nstds*sigma_y*numpy.cos(theta)));
ymax = numpy.ceil(max(1,ymax));
xmin = -xmax; ymin = -ymax;
(x,y) = numpy.meshgrid(numpy.arange(xmin,xmax+1),numpy.arange(ymin,ymax+1 ));
(y,x) = numpy.meshgrid(numpy.arange(ymin,ymax+1),numpy.arange(xmin,xmax+1 ));
# Rotation
x_theta=x*numpy.cos(theta)+y*numpy.sin(theta);
y_theta=-x*numpy.sin(theta)+y*numpy.cos(theta);
gb= numpy.exp(-.5*(x_theta**2/sigma_x**2+y_theta**2/sigma_y**2))*numpy.cos(2*numpy.pi/Lambda*x_theta+psi);
return gb
As you may be able to tell, the only difference (I believe) between the images is contrast. So, gabor_fn would likely needed to be altered to do allow for this (unless I misunderstand one of the params)...I'm just not sure how.
UPDATE:
from math import pi
from matplotlib import pyplot as plt
data = gabor_fn(sigma=5.,theta=pi/2.,Lambda=12.5,psi=90,gamma=1.)
unit = #From left to right, unit was set to 1, 3, 7 and 9.
bound = 0.0009/unit
fig = plt.imshow(
data
,cmap = 'gray'
,interpolation='none'
,vmin = -bound
,vmax = bound
)
plt.axis('off')
The problem you are having is a visualization problem (although, I think you are chossing too large parameters).
By default matplotlib, and scipy's (toimage) use bilinear (or trilinear) interpolation, depending on your matplotlib's configuration script. That's why your image looks so smooth. It is because your pixels values are being interpolated, and you are not displaying the raw kernel you have just calculated.
Try using matplotlib with no interpolation:
from matplotlib import pyplot as plt
plt.imshow(data, 'gray', interpolation='none')
plt.show()
For the following parameters:
data = gabor_fn(sigma=5.,theta=pi/2.,Lambda=25.,psi=90,gamma=1.)
You get this output:
If you reduce lamda to 15, you get something like this:
Additionally, the sigma you choose changes the strength of the smoothing, adding parameters vmin=-1 and vmax=1 to imshow (similar to what #kazemakase) suggested, will give you the desired contrast.
Check this guide for sensible values (and ways to use) gabor kernels:
http://scikit-image.org/docs/dev/auto_examples/plot_gabor.html
It seems like toimage scales the input data so that the min/max values are mapped to black/white.
I do not know what amplitudes to reasonably expect from gabor patches, but you should try something like this:
toimage(data, cmin=-1, cmax=1).show()
This tells toimage what range your data is in. You can try to play around with cmin and cmax, but make sure they are symmetric (i.e. cmin=-x, cmax=x) so that a value of 0 maps to grey.