source: qesdi/geoplot/trunk/lib/geoplot/map_national_grid.py @ 7577

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/qesdi/geoplot/trunk/lib/geoplot/map_national_grid.py@7577
Revision 7577, 6.2 KB checked in by astephen, 10 years ago (diff)

Committed changes to be compatible with Matplotlib and Basemap versions
1.0.0. Note that these changes "should" be backwards compatible.
Egg created from this version.

Line 
1"""
2map_national_grid.py
3===================
4Holds the MapNationalGrid class which is used to draw a grid above a national grid scaled map. This class uses the matplotlib.toolkits.basemap class to render the national grid map.
5"""
6
7import logging
8import math
9
10from matplotlib.ticker import FuncFormatter, FixedLocator
11
12import geoplot.mpl_imports
13from geoplot.map_base import MapBase
14from geoplot.filtered_basemap import FilteredBasemap
15
16log = logging.getLogger(__name__)
17
18BASEMAP_RESOLUTION = 'l'
19
20# National Grid parameters
21trueOrigin = (358.0, 49.0)
22falseOrigin = (-400000, 100000)
23
24bmxLimits = (-20,20); bmyLimits = (40,70)
25
26llBasemaps = {}
27
28def getBasemap(resolution):
29   
30    if resolution not in llBasemaps.keys():
31        addBasemap(resolution)
32   
33    return llBasemaps[resolution]
34
35def addBasemap(resolution):
36   
37    # Create a basemap with the origin at the true origin.
38    # In order to cope with different Basemap versions you may need to
39    # Define the rsphere argument as the major and minor axis (of the sphere)
40    # - documented at:
41    #  http://proj.badc.rl.ac.uk/ndg/wiki/CowsFramework/CowsInstallation/MigrationToPython2.6?version=9#BasemapproblemwithTransverseMercatorprojection
42    rsphere = [6378137.00, 6356752.3142]
43
44   
45    llBasemaps[resolution] = \
46        FilteredBasemap(projection='tmerc',
47                    lon_0=trueOrigin[0],
48                    lat_0=trueOrigin[1],
49                    llcrnrlon=bmxLimits[0],
50                    llcrnrlat=bmyLimits[0],
51                    urcrnrlon=bmxLimits[1],
52                    urcrnrlat=bmyLimits[1],
53                    resolution=resolution,
54                    rsphere = rsphere,
55                    suppress_ticks=False)
56       
57
58class MapNationalGrid(MapBase):
59    """
60    Represents a map scaled to the national grid. This class is repsonsible for knowing about
61    the limits of the map, what is to be drawn on it as well as getting the grid to draw itself
62    and basemap to draw the map.
63    """
64    def __init__(self, xLimits, yLimits, drawCoast=True, drawRivers=True, addShapefile=False,
65                 resolution=None):
66        """
67        Constructs the map object.
68
69        @param xLimits:a tuple representing the (longitude) limits of the map
70        @type xLimits: a tuple of 2 floats, corresponding to (min, max)
71        @param yLimits:a tuple representing the (latitude) limits of the map
72        @type yLimits: a tuple of 2 floats , corresponding to (min, max)
73        @param drawCoast: indicates if coaslines should be drawn
74        @type drawCoast: boolean
75        @param drawRivers: indicates if rivers should be drawn
76        @type drawRivers: boolean
77        @param addShapefile: location of shapefile to overlay
78        @type addShapefile: string
79        """
80
81        if resolution == None:
82            self.basemap = getBasemap(BASEMAP_RESOLUTION)
83        else:
84            self.basemap = getBasemap(resolution)
85
86        MapBase.__init__(self, xLimits, yLimits, drawCoast, drawRivers, addShapefile)
87
88       
89    def _configAxes(self, axes):
90        """
91        Configure an axes instance to account for the false origin.
92
93        Call this method on the axes instance of a plot to make the
94        tick labels match the false origin of the projection.
95
96        @note: THIS IS A HACK.
97
98        """
99       
100
101        xff = FuncFormatter(self._makeFormatFunc('x'))
102        yff = FuncFormatter(self._makeFormatFunc('y'))
103
104        axes.xaxis.set_major_formatter(xff)
105        axes.yaxis.set_major_formatter(yff)
106
107        self._setFormatLocations(axes.xaxis, falseOrigin[0])
108        self._setFormatLocations(axes.yaxis, falseOrigin[1])
109
110    def _setFormatLocations(self, axis, shift):
111       
112        #get the min and max in terms of National grid units
113        if geoplot.mpl_imports.oldMatplotlib == True:
114            interval = axis.get_major_locator().viewInterval
115            min =  interval.get_bounds()[0]- shift
116            max = interval.get_bounds()[1]- shift
117        else:
118            interval = axis.get_view_interval()
119            min = interval[0] - shift
120            max = interval[1] - shift
121           
122        spacingList = [200000, 100000, 50000, 20000, 10000, 5000, 1000]
123
124        for spacing in spacingList:
125#            log.debug("trying spacing " + str(spacing))
126            #work out the first and last tick to be drawn,
127            #note that stop is the tick after the end of the axis, this is to make sure all
128            #the ticks are drawn
129            start = int(math.ceil(min/spacing) * spacing)
130            stop =  int(math.ceil(max/spacing) * spacing)
131#            log.debug("stop, start:" + str(stop) + "," + str(start))
132#            log.debug("(stop - start)/spacing:" + str((stop-start)/spacing))
133
134            #if there are at least 3 axis ticks use this spacing.
135            if (stop - start) / spacing > 2 :
136                break
137
138        #get the locations
139        locs =  [ p + shift for p in range(start, stop, spacing)]
140
141        #draw then on the axis
142        axis.set_major_locator(FixedLocator(locs))
143
144    def _makeFormatFunc(self, axis):
145        if axis == 'x':
146            offset = falseOrigin[0]
147        elif axis == 'y':
148            offset = falseOrigin[1]
149        else:
150            raise ValueError("axis must be 'x' or 'y'")
151
152        def kmFormatFunc(m, pos=None):
153            """Format a value in metres into a string in km.
154
155            """
156            km = (float(m)  - offset) / 1000
157            return '%.0f km'%km
158
159        return kmFormatFunc
160
161if __name__ == '__main__':
162   
163    import geoplot.log_util as log_util
164    log_util.setupGeoplotConsoleHandler(log)
165         
166    from matplotlib.backends.backend_agg import FigureCanvasAgg
167    from matplotlib.figure import Figure     
168   
169    import pkg_resources, os
170    outputsDir = os.path.abspath(pkg_resources.resource_filename('geoplot', '../../outputs'))   
171
172    #setup the figure
173    figsize=(600 / 80, 800 / 80)
174    fig = Figure(figsize=figsize, dpi=80)
175    axes = fig.add_axes([0.1, 0.1, 0.8, 0.8])
176   
177    xLimits=(-7.5, 7.5) ; yLimits=(45.0, 65.0)
178   
179    map = MapNationalGrid(xLimits, yLimits)
180   
181    map.drawMap(axes)
182   
183    canvas = FigureCanvasAgg(fig)
184    filename = "map_national_grid_test.png"
185   
186    fullPath = os.path.join(outputsDir, filename)
187    canvas.print_figure(fullPath)
188    log.debug("Wrote " + fullPath)
Note: See TracBrowser for help on using the repository browser.