Python basemap change resolution upon zoom












0















I'm trying to change the resolution of a map when the user zooms in order to save on memory and processing time. I've tried the following code, but even though the map resolution gets changed each time you zoom, the figure does not update and I am stuck with the coarse resolution. Any ideas on how to force the map to update its resolution when the user zooms? Thanks!



Here's the code I've tried:



from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt

# create new figure, axes instances
fig = plt.figure(dpi=150)
ax = fig.add_axes([0.1,0.1,0.8,0.8])
# setup mercator map projection
map = Basemap(projection='merc',llcrnrlat=-58,urcrnrlat=80,
llcrnrlon=-180,urcrnrlon=180,resolution='c')

map.drawcoastlines(linewidth=0.50)
map.fillcontinents()
map.drawmapboundary()

# Declare and register callbacks for zoom control
def on_lims_change(axes):
xrange = abs(ax.get_xlim()[1] - ax.get_xlim()[0])
yrange = abs(ax.get_xlim()[1] - ax.get_xlim()[0])

# try to change map resolution based on zoom level
if max(xrange,yrange) < 1E7 and max(xrange,yrange) > 1E6: # 'l' = low
map.resolution = 'l'
elif max(xrange,yrange) < 1E6 and max(xrange,yrange) > 5E5: # 'i' = intermeditate
map.resolution = 'i'
elif max(xrange,yrange) < 5E5 and max(xrange,yrange) > 1E5: # 'h' = high
map.resolution = 'h'
elif max(xrange,yrange) < 1E5: # 'f' = full
map.resolution = 'f'
else: # 'c' = coarse
map.resolution = 'c'

print(map.resolution)
map.drawcoastlines(linewidth=0.50)
map.fillcontinents()
map.drawmapboundary()

ax.callbacks.connect('xlim_changed', on_lims_change)

plt.show()









share|improve this question

























  • Try adding a fig.canvas.draw() at the end of your on_lims_change() function. Also, I think you don't need to redraw the boundaries every time.

    – Thomas Kühn
    Dec 12 '18 at 7:47
















0















I'm trying to change the resolution of a map when the user zooms in order to save on memory and processing time. I've tried the following code, but even though the map resolution gets changed each time you zoom, the figure does not update and I am stuck with the coarse resolution. Any ideas on how to force the map to update its resolution when the user zooms? Thanks!



Here's the code I've tried:



from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt

# create new figure, axes instances
fig = plt.figure(dpi=150)
ax = fig.add_axes([0.1,0.1,0.8,0.8])
# setup mercator map projection
map = Basemap(projection='merc',llcrnrlat=-58,urcrnrlat=80,
llcrnrlon=-180,urcrnrlon=180,resolution='c')

map.drawcoastlines(linewidth=0.50)
map.fillcontinents()
map.drawmapboundary()

# Declare and register callbacks for zoom control
def on_lims_change(axes):
xrange = abs(ax.get_xlim()[1] - ax.get_xlim()[0])
yrange = abs(ax.get_xlim()[1] - ax.get_xlim()[0])

# try to change map resolution based on zoom level
if max(xrange,yrange) < 1E7 and max(xrange,yrange) > 1E6: # 'l' = low
map.resolution = 'l'
elif max(xrange,yrange) < 1E6 and max(xrange,yrange) > 5E5: # 'i' = intermeditate
map.resolution = 'i'
elif max(xrange,yrange) < 5E5 and max(xrange,yrange) > 1E5: # 'h' = high
map.resolution = 'h'
elif max(xrange,yrange) < 1E5: # 'f' = full
map.resolution = 'f'
else: # 'c' = coarse
map.resolution = 'c'

print(map.resolution)
map.drawcoastlines(linewidth=0.50)
map.fillcontinents()
map.drawmapboundary()

ax.callbacks.connect('xlim_changed', on_lims_change)

plt.show()









share|improve this question

























  • Try adding a fig.canvas.draw() at the end of your on_lims_change() function. Also, I think you don't need to redraw the boundaries every time.

    – Thomas Kühn
    Dec 12 '18 at 7:47














0












0








0








I'm trying to change the resolution of a map when the user zooms in order to save on memory and processing time. I've tried the following code, but even though the map resolution gets changed each time you zoom, the figure does not update and I am stuck with the coarse resolution. Any ideas on how to force the map to update its resolution when the user zooms? Thanks!



Here's the code I've tried:



from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt

# create new figure, axes instances
fig = plt.figure(dpi=150)
ax = fig.add_axes([0.1,0.1,0.8,0.8])
# setup mercator map projection
map = Basemap(projection='merc',llcrnrlat=-58,urcrnrlat=80,
llcrnrlon=-180,urcrnrlon=180,resolution='c')

map.drawcoastlines(linewidth=0.50)
map.fillcontinents()
map.drawmapboundary()

# Declare and register callbacks for zoom control
def on_lims_change(axes):
xrange = abs(ax.get_xlim()[1] - ax.get_xlim()[0])
yrange = abs(ax.get_xlim()[1] - ax.get_xlim()[0])

# try to change map resolution based on zoom level
if max(xrange,yrange) < 1E7 and max(xrange,yrange) > 1E6: # 'l' = low
map.resolution = 'l'
elif max(xrange,yrange) < 1E6 and max(xrange,yrange) > 5E5: # 'i' = intermeditate
map.resolution = 'i'
elif max(xrange,yrange) < 5E5 and max(xrange,yrange) > 1E5: # 'h' = high
map.resolution = 'h'
elif max(xrange,yrange) < 1E5: # 'f' = full
map.resolution = 'f'
else: # 'c' = coarse
map.resolution = 'c'

print(map.resolution)
map.drawcoastlines(linewidth=0.50)
map.fillcontinents()
map.drawmapboundary()

ax.callbacks.connect('xlim_changed', on_lims_change)

plt.show()









share|improve this question
















I'm trying to change the resolution of a map when the user zooms in order to save on memory and processing time. I've tried the following code, but even though the map resolution gets changed each time you zoom, the figure does not update and I am stuck with the coarse resolution. Any ideas on how to force the map to update its resolution when the user zooms? Thanks!



Here's the code I've tried:



from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt

# create new figure, axes instances
fig = plt.figure(dpi=150)
ax = fig.add_axes([0.1,0.1,0.8,0.8])
# setup mercator map projection
map = Basemap(projection='merc',llcrnrlat=-58,urcrnrlat=80,
llcrnrlon=-180,urcrnrlon=180,resolution='c')

map.drawcoastlines(linewidth=0.50)
map.fillcontinents()
map.drawmapboundary()

# Declare and register callbacks for zoom control
def on_lims_change(axes):
xrange = abs(ax.get_xlim()[1] - ax.get_xlim()[0])
yrange = abs(ax.get_xlim()[1] - ax.get_xlim()[0])

# try to change map resolution based on zoom level
if max(xrange,yrange) < 1E7 and max(xrange,yrange) > 1E6: # 'l' = low
map.resolution = 'l'
elif max(xrange,yrange) < 1E6 and max(xrange,yrange) > 5E5: # 'i' = intermeditate
map.resolution = 'i'
elif max(xrange,yrange) < 5E5 and max(xrange,yrange) > 1E5: # 'h' = high
map.resolution = 'h'
elif max(xrange,yrange) < 1E5: # 'f' = full
map.resolution = 'f'
else: # 'c' = coarse
map.resolution = 'c'

print(map.resolution)
map.drawcoastlines(linewidth=0.50)
map.fillcontinents()
map.drawmapboundary()

ax.callbacks.connect('xlim_changed', on_lims_change)

plt.show()






python matplotlib zoom resolution matplotlib-basemap






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 28 '18 at 23:50







Oak Nelson

















asked Nov 26 '18 at 3:56









Oak NelsonOak Nelson

165




165













  • Try adding a fig.canvas.draw() at the end of your on_lims_change() function. Also, I think you don't need to redraw the boundaries every time.

    – Thomas Kühn
    Dec 12 '18 at 7:47



















  • Try adding a fig.canvas.draw() at the end of your on_lims_change() function. Also, I think you don't need to redraw the boundaries every time.

    – Thomas Kühn
    Dec 12 '18 at 7:47

















Try adding a fig.canvas.draw() at the end of your on_lims_change() function. Also, I think you don't need to redraw the boundaries every time.

– Thomas Kühn
Dec 12 '18 at 7:47





Try adding a fig.canvas.draw() at the end of your on_lims_change() function. Also, I think you don't need to redraw the boundaries every time.

– Thomas Kühn
Dec 12 '18 at 7:47












1 Answer
1






active

oldest

votes


















1














Best way I found was to call something like



zoomcall = ax.callbacks.connect('ylim_changed', onzoom)
ax.patches.clear()
ax.collections.clear()
ax.callbacks.disconnect(zoomcall)


in order to (1) establish callback, (2) clear the old map and (3) clear the callback. This is done as part of a new class for ease of use.



Here is the code outline:



class ZoomPlot():

def __init__(self, pnts):
self.fig = plt.figure(figsize=(15,9))
self.ax = self.fig.add_subplot(111)

self.bnds = self.bnds_strt = [-58, 80, -180, 180]
self.resolution = 'c'

self.plot_map()

def plot_map(self):
self.map = Basemap(projection='merc',llcrnrlat=self.bnds[0],urcrnrlat=self.bnds[1],
llcrnrlon=self.bnds[2],urcrnrlon=self.bnds[3],resolution=self.resolution)

self.map.drawcoastlines()
self.map.drawmapboundary(fill_color='cornflowerblue')
self.map.fillcontinents(color='lightgreen', lake_color='aqua')
self.map.drawcountries()
self.map.drawstates()

self.plot_points()

self.fig.canvas.draw()

self.zoomcall = self.ax.callbacks.connect('ylim_changed', self.onzoom)

def onzoom(self, axes):
#print('zoom triggered')
self.ax.patches.clear()
self.ax.collections.clear()
self.ax.callbacks.disconnect(self.zoomcall)

x1, y1 = self.map(self.ax.get_xlim()[0], self.ax.get_ylim()[0], inverse = True)
x2, y2 = self.map(self.ax.get_xlim()[1], self.ax.get_ylim()[1], inverse = True)
self.bnds = [y1, y2, x1, x2]

# reset zoom to home (workaround for unidentified error when you press the home button)
if any([a/b > 1 for a,b in zip(self.bnds,self.bnds_strt)]):
self.bnds = self.bnds_strt # reset map boundaryies
self.ax.lines.clear() # reset points
self.ab.set_visible(False) # hide picture if visible

# change map resolution based on zoom level
zoom_set = max(abs(self.bnds[0]-self.bnds[1]),abs(self.bnds[2]-self.bnds[3]))
if zoom_set < 30 and zoom_set >= 3:
self.resolution = 'l'
#print(' --- low resolution')
elif zoom_set < 3:
self.resolution = 'i'
#print(' --- intermeditate resolution')
else:
self.resolution = 'c'
#print(' --- coarse resolution')

self.plot_map()





share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53474600%2fpython-basemap-change-resolution-upon-zoom%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    Best way I found was to call something like



    zoomcall = ax.callbacks.connect('ylim_changed', onzoom)
    ax.patches.clear()
    ax.collections.clear()
    ax.callbacks.disconnect(zoomcall)


    in order to (1) establish callback, (2) clear the old map and (3) clear the callback. This is done as part of a new class for ease of use.



    Here is the code outline:



    class ZoomPlot():

    def __init__(self, pnts):
    self.fig = plt.figure(figsize=(15,9))
    self.ax = self.fig.add_subplot(111)

    self.bnds = self.bnds_strt = [-58, 80, -180, 180]
    self.resolution = 'c'

    self.plot_map()

    def plot_map(self):
    self.map = Basemap(projection='merc',llcrnrlat=self.bnds[0],urcrnrlat=self.bnds[1],
    llcrnrlon=self.bnds[2],urcrnrlon=self.bnds[3],resolution=self.resolution)

    self.map.drawcoastlines()
    self.map.drawmapboundary(fill_color='cornflowerblue')
    self.map.fillcontinents(color='lightgreen', lake_color='aqua')
    self.map.drawcountries()
    self.map.drawstates()

    self.plot_points()

    self.fig.canvas.draw()

    self.zoomcall = self.ax.callbacks.connect('ylim_changed', self.onzoom)

    def onzoom(self, axes):
    #print('zoom triggered')
    self.ax.patches.clear()
    self.ax.collections.clear()
    self.ax.callbacks.disconnect(self.zoomcall)

    x1, y1 = self.map(self.ax.get_xlim()[0], self.ax.get_ylim()[0], inverse = True)
    x2, y2 = self.map(self.ax.get_xlim()[1], self.ax.get_ylim()[1], inverse = True)
    self.bnds = [y1, y2, x1, x2]

    # reset zoom to home (workaround for unidentified error when you press the home button)
    if any([a/b > 1 for a,b in zip(self.bnds,self.bnds_strt)]):
    self.bnds = self.bnds_strt # reset map boundaryies
    self.ax.lines.clear() # reset points
    self.ab.set_visible(False) # hide picture if visible

    # change map resolution based on zoom level
    zoom_set = max(abs(self.bnds[0]-self.bnds[1]),abs(self.bnds[2]-self.bnds[3]))
    if zoom_set < 30 and zoom_set >= 3:
    self.resolution = 'l'
    #print(' --- low resolution')
    elif zoom_set < 3:
    self.resolution = 'i'
    #print(' --- intermeditate resolution')
    else:
    self.resolution = 'c'
    #print(' --- coarse resolution')

    self.plot_map()





    share|improve this answer




























      1














      Best way I found was to call something like



      zoomcall = ax.callbacks.connect('ylim_changed', onzoom)
      ax.patches.clear()
      ax.collections.clear()
      ax.callbacks.disconnect(zoomcall)


      in order to (1) establish callback, (2) clear the old map and (3) clear the callback. This is done as part of a new class for ease of use.



      Here is the code outline:



      class ZoomPlot():

      def __init__(self, pnts):
      self.fig = plt.figure(figsize=(15,9))
      self.ax = self.fig.add_subplot(111)

      self.bnds = self.bnds_strt = [-58, 80, -180, 180]
      self.resolution = 'c'

      self.plot_map()

      def plot_map(self):
      self.map = Basemap(projection='merc',llcrnrlat=self.bnds[0],urcrnrlat=self.bnds[1],
      llcrnrlon=self.bnds[2],urcrnrlon=self.bnds[3],resolution=self.resolution)

      self.map.drawcoastlines()
      self.map.drawmapboundary(fill_color='cornflowerblue')
      self.map.fillcontinents(color='lightgreen', lake_color='aqua')
      self.map.drawcountries()
      self.map.drawstates()

      self.plot_points()

      self.fig.canvas.draw()

      self.zoomcall = self.ax.callbacks.connect('ylim_changed', self.onzoom)

      def onzoom(self, axes):
      #print('zoom triggered')
      self.ax.patches.clear()
      self.ax.collections.clear()
      self.ax.callbacks.disconnect(self.zoomcall)

      x1, y1 = self.map(self.ax.get_xlim()[0], self.ax.get_ylim()[0], inverse = True)
      x2, y2 = self.map(self.ax.get_xlim()[1], self.ax.get_ylim()[1], inverse = True)
      self.bnds = [y1, y2, x1, x2]

      # reset zoom to home (workaround for unidentified error when you press the home button)
      if any([a/b > 1 for a,b in zip(self.bnds,self.bnds_strt)]):
      self.bnds = self.bnds_strt # reset map boundaryies
      self.ax.lines.clear() # reset points
      self.ab.set_visible(False) # hide picture if visible

      # change map resolution based on zoom level
      zoom_set = max(abs(self.bnds[0]-self.bnds[1]),abs(self.bnds[2]-self.bnds[3]))
      if zoom_set < 30 and zoom_set >= 3:
      self.resolution = 'l'
      #print(' --- low resolution')
      elif zoom_set < 3:
      self.resolution = 'i'
      #print(' --- intermeditate resolution')
      else:
      self.resolution = 'c'
      #print(' --- coarse resolution')

      self.plot_map()





      share|improve this answer


























        1












        1








        1







        Best way I found was to call something like



        zoomcall = ax.callbacks.connect('ylim_changed', onzoom)
        ax.patches.clear()
        ax.collections.clear()
        ax.callbacks.disconnect(zoomcall)


        in order to (1) establish callback, (2) clear the old map and (3) clear the callback. This is done as part of a new class for ease of use.



        Here is the code outline:



        class ZoomPlot():

        def __init__(self, pnts):
        self.fig = plt.figure(figsize=(15,9))
        self.ax = self.fig.add_subplot(111)

        self.bnds = self.bnds_strt = [-58, 80, -180, 180]
        self.resolution = 'c'

        self.plot_map()

        def plot_map(self):
        self.map = Basemap(projection='merc',llcrnrlat=self.bnds[0],urcrnrlat=self.bnds[1],
        llcrnrlon=self.bnds[2],urcrnrlon=self.bnds[3],resolution=self.resolution)

        self.map.drawcoastlines()
        self.map.drawmapboundary(fill_color='cornflowerblue')
        self.map.fillcontinents(color='lightgreen', lake_color='aqua')
        self.map.drawcountries()
        self.map.drawstates()

        self.plot_points()

        self.fig.canvas.draw()

        self.zoomcall = self.ax.callbacks.connect('ylim_changed', self.onzoom)

        def onzoom(self, axes):
        #print('zoom triggered')
        self.ax.patches.clear()
        self.ax.collections.clear()
        self.ax.callbacks.disconnect(self.zoomcall)

        x1, y1 = self.map(self.ax.get_xlim()[0], self.ax.get_ylim()[0], inverse = True)
        x2, y2 = self.map(self.ax.get_xlim()[1], self.ax.get_ylim()[1], inverse = True)
        self.bnds = [y1, y2, x1, x2]

        # reset zoom to home (workaround for unidentified error when you press the home button)
        if any([a/b > 1 for a,b in zip(self.bnds,self.bnds_strt)]):
        self.bnds = self.bnds_strt # reset map boundaryies
        self.ax.lines.clear() # reset points
        self.ab.set_visible(False) # hide picture if visible

        # change map resolution based on zoom level
        zoom_set = max(abs(self.bnds[0]-self.bnds[1]),abs(self.bnds[2]-self.bnds[3]))
        if zoom_set < 30 and zoom_set >= 3:
        self.resolution = 'l'
        #print(' --- low resolution')
        elif zoom_set < 3:
        self.resolution = 'i'
        #print(' --- intermeditate resolution')
        else:
        self.resolution = 'c'
        #print(' --- coarse resolution')

        self.plot_map()





        share|improve this answer













        Best way I found was to call something like



        zoomcall = ax.callbacks.connect('ylim_changed', onzoom)
        ax.patches.clear()
        ax.collections.clear()
        ax.callbacks.disconnect(zoomcall)


        in order to (1) establish callback, (2) clear the old map and (3) clear the callback. This is done as part of a new class for ease of use.



        Here is the code outline:



        class ZoomPlot():

        def __init__(self, pnts):
        self.fig = plt.figure(figsize=(15,9))
        self.ax = self.fig.add_subplot(111)

        self.bnds = self.bnds_strt = [-58, 80, -180, 180]
        self.resolution = 'c'

        self.plot_map()

        def plot_map(self):
        self.map = Basemap(projection='merc',llcrnrlat=self.bnds[0],urcrnrlat=self.bnds[1],
        llcrnrlon=self.bnds[2],urcrnrlon=self.bnds[3],resolution=self.resolution)

        self.map.drawcoastlines()
        self.map.drawmapboundary(fill_color='cornflowerblue')
        self.map.fillcontinents(color='lightgreen', lake_color='aqua')
        self.map.drawcountries()
        self.map.drawstates()

        self.plot_points()

        self.fig.canvas.draw()

        self.zoomcall = self.ax.callbacks.connect('ylim_changed', self.onzoom)

        def onzoom(self, axes):
        #print('zoom triggered')
        self.ax.patches.clear()
        self.ax.collections.clear()
        self.ax.callbacks.disconnect(self.zoomcall)

        x1, y1 = self.map(self.ax.get_xlim()[0], self.ax.get_ylim()[0], inverse = True)
        x2, y2 = self.map(self.ax.get_xlim()[1], self.ax.get_ylim()[1], inverse = True)
        self.bnds = [y1, y2, x1, x2]

        # reset zoom to home (workaround for unidentified error when you press the home button)
        if any([a/b > 1 for a,b in zip(self.bnds,self.bnds_strt)]):
        self.bnds = self.bnds_strt # reset map boundaryies
        self.ax.lines.clear() # reset points
        self.ab.set_visible(False) # hide picture if visible

        # change map resolution based on zoom level
        zoom_set = max(abs(self.bnds[0]-self.bnds[1]),abs(self.bnds[2]-self.bnds[3]))
        if zoom_set < 30 and zoom_set >= 3:
        self.resolution = 'l'
        #print(' --- low resolution')
        elif zoom_set < 3:
        self.resolution = 'i'
        #print(' --- intermeditate resolution')
        else:
        self.resolution = 'c'
        #print(' --- coarse resolution')

        self.plot_map()






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Mar 15 at 13:20









        Oak NelsonOak Nelson

        165




        165
































            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53474600%2fpython-basemap-change-resolution-upon-zoom%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Create new schema in PostgreSQL using DBeaver

            Deepest pit of an array with Javascript: test on Codility

            Costa Masnaga