Basemap reuse

Hi matplotlib users,

I have a small web application for calculating tsunami travel times
(http://ocean.dmi.dk/apps/tsunami). The application uses matplotlib/basemap
for producing contour maps of the tsunami travel times.

To speed up the response time of the application I made a version in which the
calculations are performed for every second integer longitude and latitude
for calculation windows of 60x60 degrees lon x lat, 90x90, 180x180 and
global. This is a lot of plots for which I am making a new Basemap instances
for each plot since:

llcrnrlon
llcrnrlat
urcrnrlon
urcrnrlat

differs for each plot. The initialization of the Basemap instances are
responsible for the vast majority of the CPU usage in the application.

In converting the application to numpy (from numarray) I was wondering whether
I could reduce the plotting time as well. Is it possible to reuse a Basemap
instance somehow in my case or is that out of the question?

Regards,
Jesper

Jesper Larsen wrote:

Hi matplotlib users,

I have a small web application for calculating tsunami travel times (http://ocean.dmi.dk/apps/tsunami). The application uses matplotlib/basemap for producing contour maps of the tsunami travel times.

To speed up the response time of the application I made a version in which the calculations are performed for every second integer longitude and latitude for calculation windows of 60x60 degrees lon x lat, 90x90, 180x180 and global. This is a lot of plots for which I am making a new Basemap instances for each plot since:

llcrnrlon
llcrnrlat
urcrnrlon
urcrnrlat

differs for each plot. The initialization of the Basemap instances are responsible for the vast majority of the CPU usage in the application.

In converting the application to numpy (from numarray) I was wondering whether I could reduce the plotting time as well. Is it possible to reuse a Basemap instance somehow in my case or is that out of the question?

Regards,
Jesper

Jesper: As long as you are using the cylindrical equidistant projection, something like this might work:

from matplotlib.toolkits.basemap import Basemap
import pylab as p
map = Basemap()
map.fillcontinents(color='coral')
map.drawparallels(p.arange(-90,91,30))
map.drawmeridians(p.arange(-180,181,30))
p.savefig('fig1.png')

ax = p.gca()
llcrnrlat = 20
llcrnrlon = -140
urcrnrlat = 55
urcrnrlon = -65
corners = ((llcrnrlon,llcrnrlat), (urcrnrlon,urcrnrlat))
ax.update_datalim( corners )
ax.set_xlim((llcrnrlon, urcrnrlon))
ax.set_ylim((llcrnrlat, urcrnrlat))
p.savefig('fig2.png')

llcrnrlat = 30
llcrnrlon = -20
urcrnrlat = 80
urcrnrlon = 50
corners = ((llcrnrlon,llcrnrlat), (urcrnrlon,urcrnrlat))
ax.update_datalim( corners )
ax.set_xlim((llcrnrlon, urcrnrlon))
ax.set_ylim((llcrnrlat, urcrnrlat))
p.savefig('fig3.png')

You might not be able to get labels on the meridians and parallels with this approach though.

-Jeff

···

--
Jeffrey S. Whitaker Phone : (303)497-6313
NOAA/OAR/CDC R/PSD1 FAX : (303)497-6449
325 Broadway Boulder, CO, USA 80305-3328

Jesper Larsen wrote:

Hi matplotlib users,

I have a small web application for calculating tsunami travel times (http://ocean.dmi.dk/apps/tsunami). The application uses matplotlib/basemap for producing contour maps of the tsunami travel times.

To speed up the response time of the application I made a version in which the calculations are performed for every second integer longitude and latitude for calculation windows of 60x60 degrees lon x lat, 90x90, 180x180 and global. This is a lot of plots for which I am making a new Basemap instances for each plot since:

llcrnrlon
llcrnrlat
urcrnrlon
urcrnrlat

differs for each plot. The initialization of the Basemap instances are responsible for the vast majority of the CPU usage in the application.

In converting the application to numpy (from numarray) I was wondering whether I could reduce the plotting time as well. Is it possible to reuse a Basemap instance somehow in my case or is that out of the question?

Regards,
Jesper

Jesper: Here's a better way, that allows you to label the meridians and parallels. It will only work for projection='cyl', although a similar solution could be worked up for 'merc' and 'mill'.

from matplotlib.toolkits.basemap import Basemap
import pylab as p

def resetmapbounds(map,llcrnrlon,llcrnrlat,urcrnrlon,urcrnrlat):
    map.llcrnrlat = llcrnrlat; map.llcrnrlon = llcrnrlon
    map.urcrnrlat = urcrnrlat; map.urcrnrlon = urcrnrlon
    map.llcrnry = map.llcrnrlat; map.llcrnrx=map.llcrnrlon
    map.urcrnry = map.urcrnrlat; map.urcrnrx=map.urcrnrlon
    return map

fig = p.figure()
# create the Basemap instance
map = Basemap()
map.fillcontinents(color='coral')
map.drawparallels(p.arange(-90,91,30),labels=[1,1,1,1])
map.drawmeridians(p.arange(-180,181,30),labels=[1,1,1,1])
#p.savefig('fig1.png')

# resuse the Basemap instance, resetting the lat/lon domain.
# US Domain.
fig = p.figure()
map = resetmapbounds(map,-140,20,-65,55)
map.fillcontinents(color='coral')
map.drawparallels(p.arange(-90,91,10),labels=[1,1,1,1])
map.drawmeridians(p.arange(-180,181,10),labels=[1,1,1,1])
#p.savefig('fig2.png')

# Europe Domain.
fig = p.figure()
map = resetmapbounds(map,-20,30,40,80)
map.fillcontinents(color='coral')
map.drawparallels(p.arange(-90,91,10),labels=[1,1,1,1])
map.drawmeridians(p.arange(-180,181,10),labels=[1,1,1,1])
#p.savefig('fig3.png')
p.show()

HTH,

-Jeff

···

--
Jeffrey S. Whitaker Phone : (303)497-6313
Meteorologist FAX : (303)497-6449
NOAA/OAR/PSD R/PSD1 Email : Jeffrey.S.Whitaker@...259...
325 Broadway Office : Skaggs Research Cntr 1D-124
Boulder, CO, USA 80303-3328 Web : Jeffrey S. Whitaker: NOAA Physical Sciences Laboratory

<snip>

Thanks,

I have implemented that solution. The only issue I have discovered so far is
that I also had to recalculate the aspect ratio of the map (since I use this
to calculate the figure size):

def resetmapbounds(map,llcrnrlon,llcrnrlat,urcrnrlon,urcrnrlat):
    map.llcrnrlat = llcrnrlat; map.llcrnrlon = llcrnrlon
    map.urcrnrlat = urcrnrlat; map.urcrnrlon = urcrnrlon
    map.llcrnry = map.llcrnrlat; map.llcrnrx=map.llcrnrlon
    map.urcrnry = map.urcrnrlat; map.urcrnrx=map.urcrnrlon
    map.aspect = (map.urcrnrlat-map.llcrnrlat)/(map.urcrnrlon-map.llcrnrlon)
    return map

This only works for projection='cyl'. For other projections more work is
needed (see basemap.py).

- Jesper

···

On Friday 01 June 2007 18:52, Jeff Whitaker wrote:

Jesper: Here's a better way, that allows you to label the meridians and
parallels. It will only work for projection='cyl', although a similar
solution could be worked up for 'merc' and 'mill'.