1

I need to know how to update the axes of a plot after creation. I saw in the matplotlib documentation here.

I have tried the following code:

    ax.update(ax.properties())

but I get the following error:

Traceback (most recent call last):

  File "<ipython-input-127-e6624b1841f4>", line 1, in <module>
    ax.update(ax.properties())

  File "C:\Users\cjmar\Anaconda3\lib\site-packages\matplotlib\artist.py", line 974, in update
    ret = [_update_property(self, k, v) for k, v in props.items()]

  File "C:\Users\cjmar\Anaconda3\lib\site-packages\matplotlib\artist.py", line 974, in <listcomp>
    ret = [_update_property(self, k, v) for k, v in props.items()]

  File "C:\Users\cjmar\Anaconda3\lib\site-packages\matplotlib\artist.py", line 970, in _update_property
    .format(type(self).__name__, k))

AttributeError: 'GeoAxesSubplot' object has no property 'children'

and yet examining ax.properties() there is indeed a 'children' key there. Not sure what is going on. I know that cartopy seems to override the GeoAxes class, however, there doesn't seem to be anything overloaded with respect to the update method.

Some example code. Best to run this in an iPython console so that you can access the ax object while the plot is still showing. May require a plt.show() at the bottom. I use Spyder, which doesn't require this.

        import os
        import sys
        import matplotlib.pyplot as plt
        import matplotlib
        import mpl_toolkits
        import numpy as np
        import cartopy

        import cartopy.crs as ccrs
        fig = plt.figure()
        ax = plt.axes(projection=ccrs.NorthPolarStereo())
        ax.stock_img()

        ny_lon, ny_lat = -75, 43
        delhi_lon, delhi_lat = 77.23, 28.61

        plt.plot([ny_lon, delhi_lon], [ny_lat, delhi_lat],
                  color='blue', linewidth=2, marker='o',
                  transform=ccrs.Geodetic(),
                  )

        plt.plot([ny_lon, delhi_lon], [ny_lat, delhi_lat],
                  color='gray', linestyle='--',
                  transform=ccrs.PlateCarree(),
                  )

        ax.add_patch(matplotlib.patches.Polygon([[0,0],[20,0],[20,20],[0,20]],
                                                fill = False,color='g',ls='--',
                                                transform=ccrs.PlateCarree()))

        ax.add_patch(matplotlib.patches.Circle([30,30],radius=10,color='g',ls='--',
                                               transform=ccrs.PlateCarree()))

        plt.text(ny_lon - 3, ny_lat - 12, 'New York',
                  horizontalalignment='right',
                  transform=ccrs.Geodetic())

        plt.text(delhi_lon + 3, delhi_lat - 12, 'Delhi',
                  horizontalalignment='left',
                  transform=ccrs.Geodetic())
        # ax.set_extent([-180,180,-90,90])
        ax.set_global()

How do I utilize this method properly?

EDIT: This question is in direct correlation to this other question asked by me. here

But the questions are indeed different, as this question is asking how to use the method, and that question is asking how to update an axes projection.

Carl
  • 111
  • 1
  • 1
  • 9
  • Can you edit your example to show where `ax.update()` is being called (in the error message is says it's called on line 1, but I don't see in the your example code). Also what's your overall goal that you're trying to achieve by using `ax.update`? – Jason Mar 26 '20 at 12:55
  • Hi Jason. The call to ax.update is done in an iPython console after the plot figure is already being shown (after the code submitted here has already been ran). Because I have access to the axes object this is perfectly valid. To reproduce what I'm doing. Run this in an iPython console as mentioned in the OP. – Carl Mar 26 '20 at 15:43
  • What I meant was what you want the call to `ax.update()` to perform because if you want to make changes to `ax` they'll be reflected in subsequent calls to show the plot. Your error is actually saying that `cartopy.mpl.geoaxes.GeoAxesSubplot` doesn't have a `.children` attribute meaning that the presence of the key `children` which is returned from your called to `ax.properties()` is what's causing your error. – Jason Mar 26 '20 at 15:54
  • Ah, I think I see. But to answer your initial question, I just want to update the children of the axes. Because Im trying to update the ax.projection attribute to a different cartopy projection. Say, PlateCarree -> NorthPolarStereo. I can change the projection attribute, however, the children of the axes are not updated automatically, hence why I am trying to use the ax.update() call. But I just don't know how to use it correctly. And Sorry, dont know how to format code in comment. – Carl Mar 26 '20 at 17:45
  • Have you tried calling `plt.show()` after making changes using an `ax` method? Because the methods modify the existing `ax` object in place. Reading your linked question I think that's the behaviour that you're after. Btw you can enclose your text in \` (backticks) to get it to appear as code. – Jason Mar 26 '20 at 18:55
  • I think there's some misunderstanding surround 'children' and the use of `ax.update()`. The `ax` object that you've created doesn't have children, all of your lines are modifying the original `ax` object created by `plt.axes(projection=ccrs.NorthPolarStereo())`. Under the hood the calls `matplotlib.pyplot.some_method()` are first looking for the current `ax` or `fig` object and modifying that. Which in common language is considered to be 'updating'. – Jason Mar 26 '20 at 19:01
  • That is very possible, however, even normal Matplotlib axes doesn't have `ax.children` property. I'm just don't know what Matplotlib dox means by props. Other than a properties dictionary, which is obtained by calling `ax.properties()`. – Carl Mar 26 '20 at 20:41
  • Also, a `plt.show()` is not needed after changing the `ax.projection`. This is because after I edit `ax.projection` I do a `ax.figure.canvas.draw()` which redraws the plot. This can be verified by doing something like `ax.set_facecolor(.4,.4,.4,.4)` `ax.figure.canvas.draw()` after the `plt.show()` has already been called. This will update the facecolor of the axis. – Carl Mar 26 '20 at 20:42
  • I'm sorry I still don't understand what you want `ax.update()` to do. The `plt` and `ax` methods already modify the `ax` object. `ax.properties()` is a convenient way to get all properties of `ax` but you don't modify that dictionary before passing it to `ax.update()`. Properties refer to the artists used in your plot (line, patch etc.). Their properties are listed [here](https://matplotlib.org/3.1.3/tutorials/intermediate/artists.html). There's no concept of an axis having children, you can clone axis to make a new instance but they're always their own instance of the `axes` class. – Jason Mar 26 '20 at 21:09
  • For the purposes of this question, It doesn't really matter what I want it to do. I just need to know how to use it. Since the documentation is lacking, that is why I came here. FWIW, the purpose of the project that I'm working on is to make interactive plots. I want to show data in one projection, and via the toolbar in matplotlib (I have made a tool option to change properties of the axes) change the projection to a different one, update the plot and it now shows the data in the new projection. I don't know how to copy all of the attributes from one axes to another vice the projection. – Carl Mar 26 '20 at 21:14
  • I can get a barebones code set of what I'm trying to do together.. but it will take a while to pull apart my code in a way to do that as it is highly modular. – Carl Mar 26 '20 at 21:21
  • I'm sorry, I didn't mean to offend you. I'm asking because if you remove the 'children' key from the dictionary returned from `ax.properites()` the expected behaviour would be reapply all of the current settings- which would have no effect on your plot. I assume that the by calling `ax.update()` you wanted _something_ to happen and that's why I'm asking what you want to happen so that I can suggest an approach to get you the results that you want. – Jason Mar 26 '20 at 21:22
  • Roger that. No offense taken (sorry if it came off that way). I just don't want to divulge the entire process to what I'm doing for purposes I cannot explain. I will link some code in the future. Please stay posted. – Carl Mar 26 '20 at 21:26
  • Okay, good luck with your project! Feel free to ping me if you have another question! – Jason Mar 26 '20 at 21:28
  • Depending on what you want to do this page might be useful for you. [Link to docs](https://matplotlib.org/3.2.0/users/event_handling.html) – Jason Mar 26 '20 at 21:30

0 Answers0