4

I'm using the Basemap object from basemap module in the matplotlib toolkit (mpl_toolkits.basemap.Basemap). In basemap's __init__.py file (i.e. the mpl_toolkits.basemap.__init__ module), a method drawparallels is defined which draws latitudes on the map. I aim to duplicate that method to make a new method called drawmlat, making some adjustments in order to plot magnetic latitudes instead of geographic latitudes.

Ideally, I want the new drawmlat to be equivalent to the original drawparallel (a bound method of the instances of Basemap that I can call with using BasemapInstance.drawmlats()), and I do not want to modify the original file. How would I accomplish this?

I have tried variations of the "recipe" MyObj.method = MethodType(new_method, None, MyObj), but without placing anything in the original source file, the new method does not have access to globals etc. from the Basemap module (e.g. defined in its __init__.py).

If it seems I have misunderstood something, I probably have - I am more or less completely new to object-oriented programming.

cmeeren
  • 3,890
  • 2
  • 20
  • 50
  • 1
    possible duplicate of [Adding a Method to an Existing Object](http://stackoverflow.com/questions/972/adding-a-method-to-an-existing-object) – Ivan Genchev Feb 26 '14 at 13:16

1 Answers1

6

Python is highly modifiable. Just add your function to the class:

from mpl_toolkits.basemap import Basemap


def drawmlat(self, arg1, arg2, kw=something):
    pass

Basemap.drawmlat = drawmlat

Now the Basemap class has a drawmlat method; call it on instances and self will be bound to the instance object. When looking up the method on instances, the function will automatically be bound as a method for you.

Anything defined in the Basemap.__init__ method that you need to care about are attributes on self.

Having looked over the mpl_toolkits.basemap.__init__ module, I do see that the drawparallel method relies on a few globals; you can import those from the module into your own namespace:

from mpl_toolkits.basemap import Basemap, _cylproj, _pseudocyl

This is no different from other imports you'd make; the original drawparallel method also relies on import numpy as np and from matplotlib.lines import Line2D, which make both np and Line2D globals in the original module.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Doesn't work. the `mpl_toolkits.basemap` module (folder) (note lower-case b) contains the file `__init__.py`, in which the `Basemap` class (uppercase B) is defined. The methods of the `Basemap` class use globals defined within this `__init__.py` file, but defined outside the `Basemap` class. When I follow your advice, but instead replace your dummy `drawmlat` function with an identical copy of the already-existing `drawparallels` method, I get `NameError: global name '_cylproj' is not defined` where `_cylproj` is one of the globals I mentioned which are used in the `drawparallels` method. – cmeeren Feb 26 '14 at 18:42
  • @cmeeren: You can import the additional globals from that module into your own. I'll take a look at the exact source code. – Martijn Pieters Feb 26 '14 at 18:47
  • @cmeeren: And my apologies, I thought you were talking about the `Basemap.__init__` method, not the `mpl_toolkits.basemap.__init__` module. – Martijn Pieters Feb 26 '14 at 18:52
  • @martijn-pieters, I can see I should have been clearer on this (updated). Thank you for the answer. I ran out of space on my comment. :p – cmeeren Feb 26 '14 at 18:55
  • @martijn-pieters, you can view the `__init__.py` file in question here: https://www.dropbox.com/s/tvfht9jcyw03a61/__init__.py – cmeeren Feb 27 '14 at 07:53
  • Yes, and I already saw it by looking at the Sourceforge project repository. Any global names you need can be imported from the same location as `Basemap` as I already stated in my answer. :-) – Martijn Pieters Feb 27 '14 at 09:59
  • @martijn-pieters thank you, I saw the update to your answer now. Works wonderfully. – cmeeren Mar 03 '14 at 01:09