Cartopy's use of ax.add_image leaves me with a blank background, after initial attemps - cartopy

I ran the following from https://scitools.org.uk/cartopy/docs/v0.15/examples/eyja_volcano.html
and it worked the first time (see first image)
I created another python module with the same code and it failed (see second image). I then started removing imports and making every as simple as possible. But I kept getting the second image blank image. Eventually, however even my first starting giving me blank (see how it looks in Pycharm in last image).
I have no errors, don't know how something can work once or few times and fail (maybe restart Python?)
Any debugging ideas would be greatly appreciated
# from https://scitools.org.uk/cartopy/docs/v0.13/examples/eyja_volcano.html
"""
https://scitools.org.uk/cartopy/docs/v0.15/examples/eyja_volcano.html
"""
import matplotlib.pyplot as plt
from matplotlib.transforms import offset_copy
import cartopy.crs as ccrs
import cartopy.io.img_tiles as cimgt
def main():
# Create a Stamen Terrain instance.
#stamen_terrain = cimgt.StamenTerrain() # got warning this way is depreciated
stamen_terrain = cimgt.Stamen('terrain-background')
# Create a GeoAxes in the tile's projection.
ax = plt.axes(projection=stamen_terrain.crs)
# Limit the extent of the map to a small longitude/latitude range.
ax.set_extent([-22, -15, 63, 65])
# Add the Stamen data at zoom level 8.
ax.add_image(stamen_terrain, 7)
# Add a marker for the Eyjafjallajökull volcano.
plt.plot(-19.613333, 63.62, marker='o', color='red', markersize=12,
alpha=0.7, transform=ccrs.Geodetic())
# removed the rest
plt.show()
if __name__ == '__main__':
main()
images are first when it worked, after it stopped working, and screen shot of Pycharm

Related

how to make plt plot do not show figure [duplicate]

I need to create a figure in a file without displaying it within IPython notebook. I am not clear on the interaction between IPython and matplotlib.pylab in this regard. But, when I call pylab.savefig("test.png") the current figure get's displayed in addition to being saved in test.png. When automating the creation of a large set of plot files, this is often undesirable. Or in the situation that an intermediate file for external processing by another app is desired.
Not sure if this is a matplotlib or IPython notebook question.
This is a matplotlib question, and you can get around this by using a backend that doesn't display to the user, e.g. 'Agg':
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
plt.plot([1,2,3])
plt.savefig('/tmp/test.png')
EDIT: If you don't want to lose the ability to display plots, turn off Interactive Mode, and only call plt.show() when you are ready to display the plots:
import matplotlib.pyplot as plt
# Turn interactive plotting off
plt.ioff()
# Create a new figure, plot into it, then close it so it never gets displayed
fig = plt.figure()
plt.plot([1,2,3])
plt.savefig('/tmp/test0.png')
plt.close(fig)
# Create a new figure, plot into it, then don't close it so it does get displayed
plt.figure()
plt.plot([1,3,2])
plt.savefig('/tmp/test1.png')
# Display all "open" (non-closed) figures
plt.show()
We don't need to plt.ioff() or plt.show() (if we use %matplotlib inline). You can test above code without plt.ioff(). plt.close() has the essential role. Try this one:
%matplotlib inline
import pylab as plt
# It doesn't matter you add line below. You can even replace it by 'plt.ion()', but you will see no changes.
## plt.ioff()
# Create a new figure, plot into it, then close it so it never gets displayed
fig = plt.figure()
plt.plot([1,2,3])
plt.savefig('test0.png')
plt.close(fig)
# Create a new figure, plot into it, then don't close it so it does get displayed
fig2 = plt.figure()
plt.plot([1,3,2])
plt.savefig('test1.png')
If you run this code in iPython, it will display a second plot, and if you add plt.close(fig2) to the end of it, you will see nothing.
In conclusion, if you close figure by plt.close(fig), it won't be displayed.

Multiprocessing with Matplotlib Animation (Python)

In short, I am trying to run a live monitoring dashboard while calculating data in the background. Here is the code for my monitoring dashboard:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.animation import FuncAnimation
import psutil
import collections
# function to update the data
def monitor_machine_metrics(i):
cpu_metrics.popleft()
cpu_metrics.append(psutil.cpu_percent(interval=1))
ram_metrics.popleft()
ram_metrics.append(psutil.virtual_memory().percent)
# clear axis
ax.cla()
ax1.cla()
# plot cpu usage
ax.plot(cpu_metrics)
ax.text(len(cpu_metrics)-1, cpu_metrics[-1]+2, "{}%".format(cpu_metrics[-1]))
ax.set_ylim(0,100)
# plot memory usage
ax1.plot(ram_metrics)
ax1.text(len(ram_metrics)-1, ram_metrics[-1]+2, "{}%".format(ram_metrics[-1]))
ax1.set_ylim(0,100)
legend = plt.legend(['CPU Usage', 'RAM Usage'], loc='upper left')
return legend
# start collections with zeros
cpu_metrics = collections.deque(np.zeros(10))
ram_metrics = collections.deque(np.zeros(10))
usage_fig = plt.figure()
ax = plt.subplot()
ax1 = plt.subplot()
def display_dynamic_data(figure, funct, time_interval):
ani = FuncAnimation(figure, funct, interval=time_interval)
plt.show()
For the sake of keeping this simple, let's pretend I just want to print hi while the dashboard is running.
if __name__ == '__main__':
machine_monitoring_process =
multiprocessing.Process(target=display_dynamic_data,args=(usage_fig, monitor_machine_metrics, 1000))
machine_monitoring_process.start()
print('Hi')
Since FuncAnimation runs similar to an infinite loop, I purposely designed for this sub-process to be completely decoupled. While 'hi' prints, the figure comes up but no points will be displayed. However, display_dynamic_data works just fine if we just call the function instead of instantiating it as a sub-process. Unfortunately, I need this to run in parallel, since the real code is doing computations in the background.
Is there something that I am missing here?
Thank you!
When you use multiprocessing.Process, a new process with its own memory and objects is created. Code running in the new process has no effect in the original one. If you want to interchange information, you should use queues or other type of information exchange mechanism.
In your example, display_dynamic_data runs in the new process and exits. Remember that you must keep a reference to the FuncAnimation object to prevent it from being garbage collected.
You can check this answer to grasp what happens when you use multiprocessing.

Zoom not working on Loading pickled matplotlib Figure

I want to store a matplotlib figure and load it later to use it interactively. To be more specific, I want to be able to use zoom in this figure.
I am using pickle to dump the figure handle into a file.
I then load the figure later using pickle, but the zoom does not work after loading the file even though I can use zoom in the figure before pickling it.
Here's a sample script that illustrates my problem.
import matplotlib.pyplot as plt
import pickle
import numpy as np
import os
import time
# Create Plot Data
x = np.arange(100)
# Create Figure, Axes and plot
fig1,axes1 = plt.subplots()
axes1.plot(x)
# Pickle plot
fileName = os.getcwd() + "/img"\
+ time.asctime(time.localtime()) + ".pickle"
with open(fileName,'wb') as pickle_file:
pickle.dump(fig1,pickle_file)
plt.show() # ZOOM WORKS HERE
plt.close()
# Load pickled plot
with open(fileName,'rb') as read_pickle:
fig_handle = pickle.load(read_pickle)
plt.show() # ZOOM DOES NOT WORK HERE
Zooming into the image before Pickle
Non-Zoomable image after Pickle
Version:
Python 3.7.0
Matplotlib 3.0.0
Pickle 4.0
Is this a limitation with Pickling matplotlib figure? Or is there something I can do to load/dump the figure in a zoomable way?
As #ImportanceOfBeingErnest pointed out I fixed the problem by changing my backends from MacOSX to TkAgg.
Here's what I did.
import matplotlib
matplotlib.get_backend() # Get the current backend
'MacOSX'
# Get Location where configuration file was loaded from.
matplotlib.matplotlib_fname()
'/usr/local/lib/python3.7/site-packages/matplotlib/mpl-data/matplotlibrc'
# Edit -> backend:TkAgg
matplotlib.get_backend()
'TkAgg'

matplotlib tex renderer gives unexpected error

I am creating a scatter plot with color map based on some values and I am trying to make part of the x_axis label italic (inspired mostly by this post -> https://stackoverflow.com/a/8384685/1093485) but I am getting a LaTeX error that I can not explain myself, I would appreciate if anyone is able to explain what is going wrong with this chunk?
Minimum code required to reproduce problem here:
#! /usr/bin/env python
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rc
X = [1257.422648,1298.449197,1339.475746,1419.475471,1455.52309,1460.50202,1485.533655]
Y = [21.84637515,18.19617016,22.29456694,5.228978612,3.888695726,12.36598466,4.201838517]
Z = [44.02797944,9.758071204,21.58997772,64.53887544,53.09630431,8.461254471,291.4311435]
# Enable LaTeX style
rc('text',usetex=True)
# Plot the data
fig=plt.figure()
fig.patch.set_facecolor('white')
ax=fig.add_subplot(111)
s = ax.scatter(X,Y,c=np.log(Z))
ax.set_xlabel(r'Analyte \textit{m/z}')
ax.xaxis.labelpad = 7.5
cb = plt.colorbar(mappable=s,ax=ax)
plt.show()
Commenting the rc('text',usetex=True) causes the plot to show but obviously without italics. The whole traceback is rather large but seems to revolve around this part (if I read it correctly):
RuntimeError: LaTeX was not able to process the following string:
'$1450$'
Anyone have a suggestion on what to do to isolate the problem?

Calling pylab.savefig without display in ipython

I need to create a figure in a file without displaying it within IPython notebook. I am not clear on the interaction between IPython and matplotlib.pylab in this regard. But, when I call pylab.savefig("test.png") the current figure get's displayed in addition to being saved in test.png. When automating the creation of a large set of plot files, this is often undesirable. Or in the situation that an intermediate file for external processing by another app is desired.
Not sure if this is a matplotlib or IPython notebook question.
This is a matplotlib question, and you can get around this by using a backend that doesn't display to the user, e.g. 'Agg':
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
plt.plot([1,2,3])
plt.savefig('/tmp/test.png')
EDIT: If you don't want to lose the ability to display plots, turn off Interactive Mode, and only call plt.show() when you are ready to display the plots:
import matplotlib.pyplot as plt
# Turn interactive plotting off
plt.ioff()
# Create a new figure, plot into it, then close it so it never gets displayed
fig = plt.figure()
plt.plot([1,2,3])
plt.savefig('/tmp/test0.png')
plt.close(fig)
# Create a new figure, plot into it, then don't close it so it does get displayed
plt.figure()
plt.plot([1,3,2])
plt.savefig('/tmp/test1.png')
# Display all "open" (non-closed) figures
plt.show()
We don't need to plt.ioff() or plt.show() (if we use %matplotlib inline). You can test above code without plt.ioff(). plt.close() has the essential role. Try this one:
%matplotlib inline
import pylab as plt
# It doesn't matter you add line below. You can even replace it by 'plt.ion()', but you will see no changes.
## plt.ioff()
# Create a new figure, plot into it, then close it so it never gets displayed
fig = plt.figure()
plt.plot([1,2,3])
plt.savefig('test0.png')
plt.close(fig)
# Create a new figure, plot into it, then don't close it so it does get displayed
fig2 = plt.figure()
plt.plot([1,3,2])
plt.savefig('test1.png')
If you run this code in iPython, it will display a second plot, and if you add plt.close(fig2) to the end of it, you will see nothing.
In conclusion, if you close figure by plt.close(fig), it won't be displayed.