How do I fix Mayavi contour3d? - mayavi

I've used Mayavi 3d contour before and it was working fine, but when I tried it recently on a new machine, it doesn't seem to work as supposed to. It looks as if the depth was inverted.
To illustrate the example, here is a comparison of a 3D Gabor function plotted with contour3d and what the plot lookes like on my new machine (left) and old machine (right).
So basically the inner-most values are displayed as if they were outer.
The current mayavi version I have is 4.6.2 and vtk 8.1.2. I've downgraded to 4.5.0 and 8.1.0 respectively, but the same issue occurs. I am not really sure where else to look, so appreciate any help!
Edit: The same issue happens with volume_slice function (the planes do not overlap, but oddly render in front of one another):
Code example:
import numpy as np
import mayavi.mlab as mb
x, y, z = np.ogrid[-5:5:64j, -5:5:64j, -5:5:64j]
scalars = x * x * 0.5 + y * y + z * z * 2.0
mb.volume_slice(scalars, plane_orientation='y_axes')
mb.volume_slice(scalars, plane_orientation='x_axes')
mb.show()

Related

Trying to use the sum operator in matplotlib gives an error

So I would like to mention first that I am completely new to basically everything that is linked to Jupyter Notebook, matplotlib and numpy stuff. So that's why I most likely will not be able to express my problem clearly. Therefore I am begging for your patience :) (ah yeah and my English sucks too so...)
Anyways, I am trying to create an interactive plot. Therefore, I want to display the function of the first n polynomes of the square wave where the value of n can be choosen by using a slider. This is what I got so far:
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
%matplotlib inline
plt.rcParams['figure.figsize'] = (11,4)
plt.rcParams['figure.dpi'] = 150
from ipywidgets import interact,interactive, fixed, interact_manual
import ipywidgets as Widgets
def f(n):
plt.plot( np.arange(0,10), 1/pi * sum( 2/(i* pi) * (1- cos(i*pi) ) * sin(i*np.arange(0,10)) for i in range(1,n) ) )
plt.ylim(-2,2)
interact(f, n= 1)
Now, everything works fine until the line where I set my function, so the line with this
plt.plot(np.arange ...)
It gives me the following error:
ValueError: x and y must have same first dimension, but have shapes (10,) and (1,)
I already figured out that this has to do with the usage of the sum() Operator and using the variable n in it. If i don't put n in the sum, then everything works out nicely and I am getting my graph.
So, the question basically is what I will have to do to make my idea happen.
Thank you for your Responses, I know that my post might be very annoying to some of you because of its style or whatever and I am sorry for that.
Using the sum means you collapse the list of values down to a single value, that's what numpy is telling you - you have 10 x values and only 1 y value (because you just added them all up). I think what you are meaning to do is create a list of sums, so just move one closing parenthesis ()) from after the for i in range(n) to before it:
plt.plot(np.arange(0,10), 1/pi * sum(2/(i* pi) * (1- cos(i*pi)) * sin(i*np.arange(0,10))) for i in range(1,n))
So, for those of you who are interested in the answer (probably there are some): I found a nice and simple solution.
The Problem was the fact, that the line
interact(f, n= 1)
didn't work on its own. Now that I put it like this,
interact(f, n =widgets.IntSlider(min=2, max=100, step=1, value=2))
so by - most importantly - saying that the slider is supposed to be an IntSlider, everything works just fine!
Thank you for your help anyways! Since I am new on this platform, I don't know how solved questions can be closed, but this one here defenitely can be closed.

Difference between matplotlib.countourf and matlab.contourf() - odd sharp edges in matplotlib

I am a recent migrant from Matlab to Python and have recently worked with Numpy and Matplotlib. I recoded one of my scripts from Matlab, which employs Matlab's contourf-function, into Python using matplotlib's corresponding contourf-function. I managed to replicate the output in Python, apart that the contourf-plots are not exacly the same, for a reason that is unknown to me. As I run the contourf-function in matplotlib, I get this otherwise nice figure but it has these sharp edges on the contour-levels on top and bottom, which should not be there (see Figure 1 below, matplotlib-output). Now, when I export the arrays I used in Python to Matlab (i.e. the exactly same data set that was used to generate the matplotlib-contourf-plot) and use Matlab's contourf-function, I get a slightly different output, without those sharp contour-level edges (see Figure 2 below, Matlab-output). I used the same number of levels in both figures. In figure 3 I have made a scatterplot of the same data, which shows that there are no such sharp edges in the data as shown in the contourf-plot (I added contour-lines just for reference). Example dataset can be downloaded through Dropbox-link given below. The data set contains three txt-files: X, Y, Z. Each of them are an 500x500 arrays, which can be directly used with contourf(), i.e. plt.contourf(X,Y,Z,...). The code that used was
plt.contourf(X,Y,Z,10, cmap=plt.cm.jet)
plt.contour(X,Y,Z,10,colors='black', linewidths=0.5)
plt.axis('equal')
plt.axis('off')
Does anyone have an idea why this happens? I would appreciate any insight on this!
Cheers,
Jussi
Below are the details of my setup:
Python 3.7.0
IPython 6.5.0
matplotlib 2.2.3
Matplotlib output
Matlab output
Matplotlib-scatter
Link to data set
The confusing thing about the matlab plot is that its colorbar shows much more levels than there are actually in the plot. Hence you don't see the actual intervals that are contoured.
You would achieve the same result in matplotlib by choosing 12 instead of 11 levels.
import numpy as np
import matplotlib.pyplot as plt
X, Y, Z = [np.loadtxt("data/roundcontourdata/{}.txt".format(i)) for i in list("XYZ")]
levels = np.linspace(Z.min(), Z.max(), 12)
cntr = plt.contourf(X,Y,Z,levels, cmap=plt.cm.jet)
plt.contour(X,Y,Z,levels,colors='black', linewidths=0.5)
plt.colorbar(cntr)
plt.axis('equal')
plt.axis('off')
plt.show()
So in conclusion, both plots are correct and show the same data. Just the levels being automatically chosen are different. This can be circumvented by choosing custom levels depending on the desired visual appearance.

matplotlib figure tiny when using subplots

I'm trying to get a plot with custom aspect ratio to display properly. I am using Jupyter notebooks for the rendering, but the way I've normally done this is to adjust the 'figsize' attribute in the subplots. I've done it like below:
from matplotlib import pyplot as plt
fig,axes = plt.subplots(1,1,figsize=(16.0,8.0),frameon=False)
The problem is that, while the aspect ratio seems to come out correct (judging by eye), the figure does not use up even close to the whole page width, and is therefore tiny and hard to read.
I guess it's behaving like there are some sort of margins set on the left and right, but I can't find the global setting that controls this. I have been using the list of settings here, with no success finding a relevant one.
My question(s) are
How do I adjust the aspect ratio without impacting the overall size of the figure (think font sizes of the axis labels)? I don't need the width of my screen to be a constraint, I'd be perfectly happy for Jupyter notebooks to give me a horizontal scroll bar.
Is there a place with a more comprehensive and well-written documentation of all the matplotlib parameters that are available? The one I linked above is awkward because it gives the parameters in the form of an example matplotlibrc file. I'd like to know if a single page with (good) descriptions of all the parameters exists.
EDIT: it has been pointed out that this could be a jupyter problem and that I am setting the aspect ratio correctly. I'm using Jupyter version 1.0.0. Below is a picture of the output of a simplified notebook.
It's easy to see that the figure does not use even close to the available horizontal space.
The code in the notebook is:
#imports
import numpy as np
#set up a plot
import matplotlib as mpl
from matplotlib import pyplot as plt
#got smarter about the mpl config: see mplstyles/ directory
plt.style.use('standard')
#set up a 2-d plot
fig,axes = plt.subplots(1,1,figsize=(16.0,8.0),frameon=False)
ax1 = axes
#need to play with axis
mpl.rcParams['ytick.minor.visible'] = False
xmin = -10
xmax = 10
ymin = -10
ymax = 10
x = np.random.normal(0,5,(20000,))
y = np.random.normal(0,5,(20000,))
h = ax1.hist2d(x,y, bins=200, cmap='inferno')
ax1.set_xlim(xmin,xmax)
ax1.set_ylim(ymin,ymax)
ax1.set_xlabel('epoch time [Unix]',**axis_font)
ax1.set_ylabel(r'relative time [$\mu$s]',**axis_font)
ax1.grid(True)
#lgnd= ax1.legend(loc=2,prop={'size':22})
for axis in ['top','bottom','left','right']:
ax1.spines[axis].set_linewidth(2)
plt.tight_layout()
#plt.savefig('figures/thefigure.eps')
plt.show()
The mpl style file that I use in the plt.style.use command is:
#trying to customize here, see:
#https://matplotlib.org/users/customizing.html
#matplotlib.rc('figure', figsize=(3.4, 3.4*(4/6)))
lines.linewidth : 2
#ticks
xtick.top : False
xtick.bottom : True
xtick.minor.visible : True
xtick.direction : in
xtick.major.size : 8
xtick.minor.size : 4
xtick.major.width : 2
xtick.minor.width : 1
xtick.labelsize : 22
ytick.left : True
ytick.right : False
ytick.minor.visible : True
ytick.direction : in
ytick.major.size : 8
ytick.minor.size : 4
ytick.major.width : 2
ytick.minor.width : 1
ytick.labelsize : 22
#error bars
#errorbar.capsize : 3
#axis stuff
axes.labelsize : 22
EDIT 2: restricting the range of the vectors to the range of the axes before plotting results in the desired output. See the below figure:
The added/modified lines were:
xnew = x[(np.abs(x)<10) & (np.abs(y)<10)]
ynew = y[(np.abs(x)<10) & (np.abs(y)<10)]
h = ax1.hist2d(xnew,ynew, bins=200, cmap='inferno')
Apparently there was a bug in matplotlib 2.2.2 which got fixed by now in the development version. You may of course install the current development version from github.
The Problem comes from setting axes limits (ax1.set_xlim(-10,10)) which are smaller than the initial image. For some reason the original limits still got used to calculate the tight bbox for saving as png.
The workaround would be not to set any axes limits manually, but let the histogram plot be calculated directly with the desired limits in mind. In this case -10,10, e.g.:
x = np.random.normal(0,5,(20000,))
y = np.random.normal(0,5,(20000,))
bins = np.linspace(-10,10,201)
h = ax1.hist2d(x,y, bins=bins, cmap='inferno')
To change the font sizes of the axis label's, you'd have to use plt.rc or plt.rcParams (more on this here), so you needn't worry about doing that when using figsize.
I don't see any problems with the code you posted, could you post a picture of what you get and what you'd like to get? This is what I get using that configuration, on Jupyter notebooks, just plotting a very simple graph:
Do note, however, Jupyter limits the size of your plots automatically (see below):
And I'm afraid I can't help you with your second question, as I've always found matplotlib's documentation sufficient for all my needs... good luck!

Rendering a surface (or a smoothed volume) from a numpy array with VTK

I'm discovering VTK and want to use it to plot a 3D numpy array. So far, I've managed to convert a numpy array to a vtk.Volume and displaying it but from there I am having a hard time getting something pretty.
I get a very blocky rendering like this :
and I would like a smooth rendering, so I guess either this volume but smoothed, or the surface extracted from this volume smoothed.
I've tested a bunch of vtk mappers for this volume, like SmartVolumeMapper, and played around with the Shader and the Interpolation, but did not get great results.
Here is my code (in Python) :
import vtk
import numpy as np
npa= #some 3D numpy array
[h,w,z]=npa.shape
#importing the numpy array (comes from http://www.vtk.org/Wiki/VTK/Examples/Python/vtkWithNumpy)
dataImporter = vtk.vtkImageImport()
data_string = npa.tostring()
dataImporter.CopyImportVoidPointer(data_string, len(data_string))
dataImporter.SetDataScalarTypeToUnsignedChar()
dataImporter.SetNumberOfScalarComponents(1)
dataImporter.SetDataExtent(0,z-1, 0, w-1, 0,h-1)
dataImporter.SetWholeExtent(0,z-1, 0,w-1, 0,h-1)
#Defining a transparency function
alphaChannelFunc = vtk.vtkPiecewiseFunction()
alphaChannelFunc.AddPoint(0, 0.0)
alphaChannelFunc.AddPoint(255, 1)
# Defining a color function
colorFunc = vtk.vtkColorTransferFunction()
colorFunc.AddRGBPoint(255, 1.0, 1.0, 1.0)
colorFunc.AddRGBPoint(128, 0.0, 0, 1.0)
#Creating the volume
volumeProperty = vtk.vtkVolumeProperty()
volumeProperty.SetColor(colorFunc)
volumeProperty.SetScalarOpacity(alphaChannelFunc)
volumeProperty.ShadeOn()
volumeProperty.SetInterpolationTypeToLinear()
#Creating the mapper
compositeFunction = vtk.vtkVolumeRayCastCompositeFunction()
volumeMapper = vtk.vtkVolumeRayCastMapper()
volumeMapper.SetVolumeRayCastFunction(compositeFunction)
volumeMapper.SetInputConnection(dataImporter.GetOutputPort())
#Creating the volume actor
volume = vtk.vtkVolume()
volume.SetMapper(volumeMapper)
volume.SetProperty(volumeProperty)
#Creating the renderer
renderer = vtk.vtkRenderer()
renderWin = vtk.vtkRenderWindow()
renderWin.AddRenderer(renderer)
renderInteractor = vtk.vtkRenderWindowInteractor()
renderInteractor.SetRenderWindow(renderWin)
#Adding the actor
renderer.AddVolume(volume)
renderer.SetBackground(0, 0, 0)
renderWin.SetSize(400, 400)
#Launching the renderer
renderInteractor.Initialize()
renderWin.Render()
renderInteractor.Start()
I get the impression that a Volume actor is not the way to go to get something pretty, maybe I should go for a PolyData or something ? I went through the Marching Cubes example (in C++) which seems to take a volume and extract a surface out of it, but I can't get it to work for the moment (no errors but output is a completely white buggy window which won't close).
I could dive more into it to try and get it to work but first I would like to get input from you guys, since I'm a beginner in VTK and maybe I'm handling this all wrong.
I'm using Python 2.7.12 and vtk 5.10.1 on Ubuntu 14.

Logarithmic scaling / colorbar in Julia using PyPlot (matplotlib)

I am using Julia 0.5 and the latest version of PyPlot.
I am printing an 2D-Array using plot.pcolorand it works pretty good. But now I have data that needs a logarithmic scaling. I searched on the web and what I found was an example using
plt.pcolor(X, Y, Z1, norm=LogNorm(vmin=Z1.min(), vmax=Z1.max()), cmap='PuBu_r')
But since LogNorm seems to be a python function ist doesn't work in Julia. Does anyone have an idea what I can hand over to norm=to get a logarithmic scaling?
An example would be:
using PyPlot
A = rand(20,20)
figure()
PyPlot.pcolor(A, cmap="PuBu_r")
colorbar()
Matplotlib fields and methods can be accessed using the
matplotlib[:colors][:LogNorm]
syntax (i.e. for the corresponding matplotlib.colors.LogNorm object).
UPDATE: Thank you for your mwe. Based on that example, I managed to make it work like this:
PyPlot.pcolor(A, norm=matplotlib[:colors][:LogNorm](vmin=minimum(A), vmax=maximum(A)), cmap="PuBu_r")