Setting axes to semilog with Mayavi 3D plot - matplotlib

I'm sucessfully generating a 3D plot with Mayavi, but can't find any way to rescale the axes to a semilog representation.
Is this possible?
I also tried taking a screenshot (as suggested by another answer I read before), which I placed after my mayavi code
arr = mayavi.mlab.screenshot()
fig = plt.figure(figsize=(5, 5))
pylab.imshow(arr)
plt.semilogx()
plt.show()
However this just produces a segmentation fault.
Thanks in advance!

Related

Plotting xarray.DataArray and Geopandas together - aspect ratio errors

I am trying to create two images side by side: one satellite image alone, and next to it, the same satellite image with outlines of agricultural fields. My raster data "raster_clip" is loaded into rioxarray (original satellite image from NAIP, converted from .sid to .tif), and my vector data "ag_clip" is in geopandas. My code is as follows:
fig, (ax1, ax2) = plt.subplots(ncols = 2, figsize=(14,8))
raster_clip.plot.imshow(ax=ax1)
raster_clip.plot.imshow(ax=ax2)
ag_clip.boundary.plot(ax=ax1, color="yellow")
I can't seem to figure out how to get the y axes in each plot to be the same. When the vector data is excluded, then the two plots end up the same shape and size.
I have tried the following:
Setting sharey=True in the subplots method. Doesn't affect shape of resulting images, just removes the tic labels on the second image.
Setting "aspect='equal'" in the imshow method, leads to an error, which doesn't make sense because the 'aspect' kwarg is listed in the documentation for xarray.plot.imshow.
plt.imshow's 'aspect' kwarg is not available in xarray
Removing the "figsize" variable, doesn't affect the ratio of the two plots.
not entirely related to your question but i've used cartopy before for overlaying a GeoDataFrame to a DataArray
plt.figure(figsize=(16, 8))
ax = plt.subplot(projection=ccrs.PlateCarree())
ds.plot(ax=ax)
gdf.plot(ax=ax)

Imshow differs drastically from applying matplolib.cm to a segmented image

Hi and thanks for reading.
What I am trying to do is to make a web app that would take an image, run it through the model and return a segmented version. I can not use imshow in the webapp though. So I tried adding colormap through matplolib.cm.viridis however it returns a much darker image.
Here are some code and images for refernce:
pred = new_model.predict(np.expand_dims(img, 0))
pred_mask = np.argmax(pred, axis=-1)
pred_mask = pred_mask[0]
This returns me a 2D grayscale image, which when put into matplolib imshow looks like this.(last picture on the right is the output of the model). Code and image below.
axs[0].imshow(m1)
axs[0].set_title('Image')
axs[1].imshow(test_label1)
axs[1].set_title('Ground Truth')
axs[2].imshow(new_pred)
axs[2].set_title('Prediction')
However, when applying colormap to an image using matplolib.cm (something I have to do for app to function) I get this image. Code and image presented below.
Adding colormap. (Viridis, as far as I know is default one from matplolib 3.5)
from matplotlib import cm
pred_mask = cm.viridis(pred_mask / 255)*255
pred_mask = np.asarray(pred_mask, dtype='uint8')
Plotting Image
fig, axs = plt.subplots(1, 3, figsize=(20, 10))
axs[0].imshow(m1)
axs[0].set_title('Image')
axs[1].imshow(test_label1)
axs[1].set_title('Ground Truth')
axs[2].imshow(pred_mask)
axs[2].set_title('Prediction')
But as you can see image is much darker, without even a hint of lighter blue or yellow, i.e. worse. How can I make it closer to imshow output?
PS. Thank you very much for reading and hope that someone has an answer to that. Any suggestions would be much appreciated though.
This is most likely related to the number range of the image or colormap, respectively.
As the prediction mask can be faintly seen my money would be on either multiplying the prediction data with 255 or to set the vmax of imshow to a smaller value. In any case, it would be useful to know the min/max value of pred_mask and additionally show a colorbar for the right plot.
I hope that gets you on the right track.

Matplotlib modified histograms won't display after modification

I have plotted a histogram and would like to modify it, then re-plot it. It won't plot again without redefining the Figure and Axes object definitions. I'm using Jupyter Notebook, and I'm new to matplotlib, so I don't know if this is something that I'm not understanding about matplotlib, if it's an issue with the Jupyter Notebook or something else.
Here's my 1st block of code:
"""Here's some data."""
some_data = np.random.randn(150)
"""Here I define my `Figure` and `Axes` objects."""
fig, ax = plt.subplots()
"""Then I make a histogram from them, and it shows up just fine."""
ax.hist(some_data, range=(0, 5))
plt.show()
Here's the output from my 1st block of code:
Here's my 2nd block of code:
"""Here I modify the parameter `bins`."""
ax.hist(some_data, bins=20, range=(0, 5))
"""When I try to make a new histogram, it doesn't work."""
plt.show()
My 2nd block of code generates no visible output, which is the problem.
Here's my 3rd and final block of code:
"""But it does work if I define new `Figure` and `Axes` objects.
Why is this?
How can I display new, modified plots without defining new `Figure` and/or `Axes` objects? """
new_fig, new_ax = plt.subplots()
new_ax.hist(some_data, bins=20, range=(0, 5))
plt.show()
Here's the output from my 3rd and final block of code:
Thanks in advance.
When you generate a figure or an axis, it remains accessible for rendering or display until it's used for rendering or display. Once you execute plt.show() in your first block, the ax becomes unavailable. Your 3rd block of code is showing a plot because you're regenerating the figure and axes.

How do I use colourmaps with variable alpha in a Seaborn kdeplot without seeing the contour lines?

Python version: 3.6.4 (Anaconda on Windows)
Seaborn: 0.8.1
Matplotlib: 2.1.2
I'm trying to create a 2D Kernel Density plot using Seaborn but I want each step in the colourmap to have a different alpha value. I had a look at this question to create a matplotlib colourmap with alpha values: Add alpha to an existing matplotlib colormap.
I have a problem in that the lines between contours are visible. The result I get is here:
I thought that I had found the answer when I found this question: Hide contour linestroke on pyplot.contourf to get only fills. I tried the method outlined in the answer (using set_edgecolor("face") but it did not work in this case. That question also seemed to be related to vector graphics formats and I am just writing out a PNG.
Here is my script:
import numpy as np
import seaborn as sns
import matplotlib.colors as cols
import matplotlib.pyplot as plt
def alpha_cmap(cmap):
my_cmap = cmap(np.arange(cmap.N))
# Set a square root alpha.
x = np.linspace(0, 1, cmap.N)
my_cmap[:,-1] = x ** (0.5)
my_cmap = cols.ListedColormap(my_cmap)
return my_cmap
xs = np.random.uniform(size=100)
ys = np.random.uniform(size=100)
kplot = sns.kdeplot(data=xs, data2=ys,
cmap=alpha_cmap(plt.cm.viridis),
shade=True,
shade_lowest=False,
n_levels=30)
plt.savefig("example_plot.png")
Guided by some comments on this question I have tried some other methods that have been successful when this problem has come up. Based on this question (Matplotlib Contourf Plots Unwanted Outlines when Alpha < 1) I have tried altering the plot call to:
sns.kdeplot(data=xs, data2=ys,
cmap=alpha_cmap(plt.cm.viridis),
shade=True,
shade_lowest=False,
n_levels=30,
antialiased=True)
With antialiased=True the lines between contours are replaced by a narrow white line:
I have also tried an approach similar to this question - Pyplot pcolormesh confused when alpha not 1. This approach is based on looping over the PathCollections in kplot.collections and tuning the parameters of the edges so that they become invisible. I have tried adding this code and tweaking the linewidth -
for thing in kplot.collections:
thing.set_edgecolor("face")
thing.set_linewidth(0.01)
fig.canvas.draw()
This results in a mix of white and dark lines - .
I believe that I will not be able to tune the line width to make the lines disappear because of the variable width of the contour bands.
Using both methods (antialiasing + linewidth) makes this version, which looks cool but isn't quite what I want:
I also found this question - Changing Transparency of/Remove Contour Lines in Matplotlib
This one suggests overplotting a second plot with a different number of contour levels on the same axis, like:
kplot = sns.kdeplot(data=xs, data2=ys,
ax=ax,
cmap=alpha_cmap(plt.cm.viridis),
shade=True,
shade_lowest=False,
n_levels=30,
antialiased=True)
kplot = sns.kdeplot(data=xs, data2=ys,
ax=ax,
cmap=alpha_cmap(plt.cm.viridis),
shade=True,
shade_lowest=False,
n_levels=35,
antialiased=True)
This results in:
This is better, and almost works. The problem here is I need variable (and non-linear) alpha throughout the colourmap. The variable banding and lines seem to be a result of the combinations of alpha when contours are plotted over each other. I also still see some clear/white lines in the result.

Matplotlib annotate doesn't work on log scale?

I am making log-log plots for different data sets and need to include the best fit line equation. I know where in the plot I should place the equation, but since the data sets have very different values, I'd like to use relative coordinates in the annotation. (Otherwise, the annotation would move for every data set.)
I am aware of the annotate() function of matplotlib, and I know that I can use textcoords='axes fraction' to enable relative coordinates. When I plot my data on the regular scale, it works. But then I change at least one of the scales to log and the annotation disappears. I get no error message.
Here's my code:
plt.clf()
samplevalues = [100,1000,5000,10^4]
ax = plt.subplot(111)
ax.plot(samplevalues,samplevalues,'o',color='black')
ax.annotate('hi',(0.5,0.5), textcoords='axes fraction')
ax.set_xscale('log')
ax.set_yscale('log')
plt.show()
If I comment out ax.set_xcale('log') and ax.set_ycale('log'), the annotation appears right in the middle of the plot (where it should be). Otherwise, it doesn't appear.
Thanks in advance for your help!
It may really be a bug as pointed out by #tcaswell in the comment but a workaround is to use text() in axis coords:
plt.clf()
samplevalues = [100,1000,5000,10^4]
ax = plt.subplot(111)
ax.loglog(samplevalues,samplevalues,'o',color='black')
ax.text(0.5, 0.5,'hi',transform=ax.transAxes)
plt.show()
Another approach is to use figtext() but that is more cumbersome to use if there are already several plots (panels).
By the way, in the code above, I plotted the data using log-log scale directly. That is, instead of:
ax.plot(samplevalues,samplevalues,'o',color='black')
ax.set_xscale('log')
ax.set_yscale('log')
I did:
ax.loglog(samplevalues,samplevalues,'o',color='black')