source: trunk/UTIL/PYTHON/planetoplot_v2/ppplot.py @ 911

Last change on this file since 911 was 910, checked in by aslmd, 12 years ago

PLANETOPLOT v2


  1. Spiga LMD/UPMC 24/03/2013

Contents


core


  • ppclass.py --> main class with pp() objects (need ppplot and ppcompute)
  • ppplot.py --> plot class (can be used independently, need ppcompute)
  • ppcompute.py --> computation class (can be used independently)

scripts


  • pp.py --> command line utility to use ppclass
  • pp_reload.py --> command line utility to load saved plot objects *.ppobj
  • example/* --> example scripts using ppclass

settings files


  • set_area.txt --> setting file: predefined areas for plotting (can be omitted)
  • set_back.txt --> setting file: predefined backgrounds for plotting (can be omitted)
  • set_multiplot.txt --> setting file: predefined coefficients for multiplots (can be omitted)
  • set_ppclass.txt --> setting file: predefined variables for x,y,z,t (can be omitted)
  • set_var.txt --> setting file: predefined colorbars, format, labels, etc... for variables (can be omitted)

documentation


  • README.TXT --> this README file

data


  • demo_data/* --> plot objects for a demonstration tour and customizing tests

Requirements


python + numpy + matplotlib + netCDF4

  • for mapping --> Basemap
  • for scientific computations --> scipy

[recommended: Enthought Python Distribution (free for academics)]

Installation


  • install required softwares and librairies in requirements
  • add planetoplot_v2 in your PYTHONPATH environment variable (and in your PATH to use pp.py)

Take a demo tour


pp_reload.py demo_data/*

Improvements compared to v1


  • code readability and structuration for future improvements
  • modularity (class formulation) + easy definition/addition of attributes
  • separation between data retrieval and plotting
  • versatility + command line (pp.py)

--> for quick inspection

+ interactive session (ipython)

--> for testing and exploring

+ scripts

--> for powerful and fully customized results

  • performance (overall and on large files) + memory consumption (only retrieve what is needed)
  • saving/loading plot objects in/from *.ppobj
  • plot aesthetics and customizing (see header in ppplot)
  • multiplot flexibility with .plotin attribute
  • easy definition of presets with set_*.txt files
  • function: one field vs. another one
  • emulation of + - / * operations on fields (between two fields or between a field and a int/float)
  • computations of min/max in addition to mean
  • simple inspection of dimensions+variables in a file (pp.py -f file)
  • verbose / non verbose mode

Acknowledgements


Thanks to A. Colaitis, T. Navarro, J. Leconte
for feedbacks and contributions on version 1

File size: 25.2 KB
Line 
1###############################################
2## PLANETOPLOT                               ##
3## --> PPPLOT                                ##
4###############################################
5## Author: Aymeric Spiga. 02-03/2013         ##
6###############################################
7# python built-in librairies
8import time as timelib
9# added librairies
10import numpy as np
11import matplotlib.pyplot as mpl
12from matplotlib.cm import get_cmap
13from mpl_toolkits.basemap import Basemap
14# personal librairies
15import ppcompute
16###############################################
17
18#################################
19# global variables and settings #
20#################################
21
22# matplotlib settings
23# http://matplotlib.org/users/customizing.html
24# -------------------------------
25mpl.rcParams['font.family'] = "serif"
26mpl.rcParams['axes.color_cycle'] = "r,g,b,k"
27mpl.rcParams['contour.negative_linestyle'] = "dashed"
28mpl.rcParams['verbose.level'] = "silent"
29mpl.rcParams['lines.linewidth'] = 1.5
30mpl.rcParams['lines.markersize'] = 10
31mpl.rcParams['xtick.major.pad'] = 10
32mpl.rcParams['ytick.major.pad'] = 10
33
34# global variables
35# -------------------------------
36# - where settings files are located
37#   (None means planetoplot_v2 in PYTHONPATH)
38whereset = None
39# - some good default settings.
40# (bounds)
41how_many_sigma = 3.0 
42# (contours)
43ccol = 'black'
44cline = 0.55
45# (vectors)
46widthvec = 0.002
47reducevec = 30.
48# (colorbar)
49zeorientation="vertical"
50zefrac = 0.05
51# (save figures)
52pad_inches_value=0.25
53###############################################
54
55##########################
56# executed when imported #
57##########################
58###########################################
59# we load user-defined automatic settings #
60###########################################
61# initialize the warning variable about file not present...
62files_not_present = ""
63# ... and the whereset variable
64whereset = ppcompute.findset(whereset)
65
66# - variable settings
67# -------------------------------
68zefile = "set_var.txt"
69vf = {} ; vc = {} ; vl = {}
70try: 
71    f = open(whereset+zefile, 'r')
72    for line in f:
73        if "#" in line: pass
74        else:
75            var, format, colorb, label = line.strip().split(';')
76            ind = var.strip() 
77            vf[ind] = format.strip()
78            vc[ind] = colorb.strip()
79            vl[ind] = label.strip()
80    f.close()
81except IOError: 
82    files_not_present = files_not_present + zefile + " "
83
84## - file settings
85## -------------------------------
86#zefile = "set_file.txt"
87#prefix_t = {} ; suffix_t = {} ; name_t = {} ; proj_t = {} ; vecx_t = {} ; vecy_t = {}
88#try:
89#    f = open(whereset+zefile, 'r')
90#    for line in f:
91#        if "#" in line: pass
92#        else:
93#            prefix, suffix, name, proj, vecx, vecy = line.strip().split(';')
94#            ind = name.strip()
95#            prefix_t[ind] = prefix.strip()
96#            suffix_t[ind] = suffix.strip()
97#            #name_t[ind] = name.strip()
98#            proj_t[ind] = proj.strip()
99#            vecx_t[ind] = vecx.strip()
100#            vecy_t[ind] = vecy.strip()
101#    f.close()
102#except IOError:
103#    files_not_present = files_not_present + zefile + " "
104
105# - multiplot settings
106# -------------------------------
107zefile = "set_multiplot.txt"
108subv_t = {} ; subh_t = {} ; wspace_t = {} ; hspace_t = {} ; font_t = {}
109try:
110    f = open(whereset+zefile, 'r')
111    for line in f:
112        if "#" in line: pass
113        else:
114            num, subv, subh, wspace, hspace, font = line.strip().split(';')
115            ind = int(num.strip())
116            subv_t[ind] = int(subv.strip())
117            subh_t[ind] = int(subh.strip())
118            wspace_t[ind] = float(wspace.strip())
119            hspace_t[ind] = float(hspace.strip())
120            font_t[ind] = float(font.strip())
121    f.close()
122except IOError:
123    files_not_present = files_not_present + zefile + " "
124
125# - background settings
126# -------------------------------
127zefile = "set_back.txt"
128back = {}
129try:
130    f = open(whereset+zefile, 'r')
131    for line in f:
132        if "#" in line: pass
133        else:
134            name, link = line.strip().split(';')
135            ind = name.strip() 
136            back[ind] = link.strip()
137    f.close()
138except IOError:
139    files_not_present = files_not_present + zefile + " "
140
141# - area settings
142# -------------------------------
143zefile = "set_area.txt"
144area = {}
145try:
146    f = open(whereset+zefile, 'r')
147    for line in f:
148        if "#" in line: pass
149        else:
150            name, wlat1, wlat2, wlon1, wlon2 = line.strip().split(';')
151            area[name.strip()] = [[float(wlon1.strip()),float(wlon2.strip())],\
152                                  [float(wlat1.strip()),float(wlat2.strip())]]
153    f.close()
154except IOError:
155    files_not_present = files_not_present + zefile + " "
156# A note to the user about missing files
157if files_not_present != "":
158    print "warning: files "+files_not_present+" not in "+whereset+" ; those presets will be missing"
159
160# TBD: should change vector color with colormaps
161#"gist_heat":    "white",\
162#"hot":          "white",\
163#"gray":         "red",\
164
165####################
166# useful functions #
167####################
168
169# a function to define subplot
170# ... user can change settings in set_multiplot.txt read above
171# -------------------------------
172def definesubplot(numplot, fig):
173    try: 
174        mpl.rcParams['font.size'] = font_t[numplot]
175    except: 
176        mpl.rcParams['font.size'] = 18
177    try: 
178        fig.subplots_adjust(wspace = wspace_t[numplot], hspace = hspace_t[numplot])
179        subv, subh = subv_t[numplot],subh_t[numplot]
180    except: 
181        print "!! WARNING !! no preset found from set_multiplot.txt, or this setting file was not found."
182        subv = 1 ; subh = numplot
183    return subv,subh
184
185# a function to calculate automatically bounds (or simply prescribe those)
186# -------------------------------
187def calculate_bounds(field,vmin=None,vmax=None):
188    # prescribed cases first
189    zevmin = vmin
190    zevmax = vmax
191    # computed cases
192    if zevmin is None or zevmax is None:
193       # select values
194       ind = np.where(field < 9e+35)
195       fieldcalc = field[ ind ] # field must be a numpy array
196       # calculate stdev and mean
197       dev = np.std(fieldcalc)*how_many_sigma
198       damean = ppcompute.mean(fieldcalc)
199       # fill min/max if needed
200       if vmin is None: zevmin = damean - dev
201       if vmax is None: zevmax = damean + dev
202       # special case: negative values with stddev while field is positive
203       if zevmin < 0. and ppcompute.min(fieldcalc) > 0.: zevmin = 0.
204    return zevmin, zevmax   
205    #### treat vmin = vmax for continuity
206    #if vmin == vmax:  zevmin = damean - dev ; zevmax = damean + dev
207
208# a function to solve the problem with blank bounds !
209# -------------------------------
210def bounds(what_I_plot,zevmin,zevmax,miss=9e+35):
211    small_enough = 1.e-7
212    if zevmin < 0: what_I_plot[ what_I_plot < zevmin*(1.-small_enough) ] = zevmin*(1.-small_enough)
213    else:          what_I_plot[ what_I_plot < zevmin*(1.+small_enough) ] = zevmin*(1.+small_enough)
214    what_I_plot[ what_I_plot > miss  ] = -miss
215    what_I_plot[ what_I_plot > zevmax ] = zevmax*(1.-small_enough)
216    return what_I_plot
217
218# a generic function to show (GUI) or save a plot (PNG,EPS,PDF,...)
219# -------------------------------
220def save(mode="gui",filename="plot",folder="./",includedate=True,res=150):
221    # a few settings
222    possiblesave = ['eps','ps','svg','png','jpg','pdf'] 
223    # now the main instructions
224    if mode == "gui": 
225        mpl.show()
226    elif mode in possiblesave:
227        ## name of plot
228        name = folder+'/'+filename
229        if includedate:
230            for ttt in timelib.gmtime():
231                name = name + "_" + str(ttt)
232        name = name +"."+mode
233        ## save file
234        print "**** Saving file in "+mode+" format... Please wait."
235        mpl.savefig(name,dpi=res,bbox_inches='tight',pad_inches=pad_inches_value)
236    else:
237        print "!! ERROR !! File format not supported. Supported: ",possiblesave
238
239##################################
240# a generic class to make a plot #
241##################################
242class plot():
243
244    # print out a help string when help is invoked on the object
245    # -------------------------------
246    def __repr__(self):
247        whatprint = 'plot object. \"help(plot)\" for more information\n'
248        return whatprint
249
250    # default settings
251    # -- user can define settings by two methods.
252    # -- 1. yeah = plot2d(title="foo")
253    # -- 2. yeah = pp() ; yeah.title = "foo"
254    # -------------------------------
255    def __init__(self,\
256                 var=None,\
257                 field=None,\
258                 absc=None,\
259                 xlabel="",\
260                 ylabel="",\
261                 div=20,\
262                 logx=False,\
263                 logy=False,\
264                 swap=False,\
265                 swaplab=True,\
266                 invert=False,\
267                 xcoeff=1.,\
268                 ycoeff=1.,\
269                 title=""):
270        ## what could be defined by the user
271        self.var = var
272        self.field = field
273        self.absc = absc
274        self.xlabel = xlabel
275        self.ylabel = ylabel
276        self.title = title
277        self.div = div
278        self.logx = logx
279        self.logy = logy
280        self.swap = swap
281        self.swaplab = swaplab # NB: swaplab only used if swap=True
282        self.invert = invert
283        self.xcoeff = xcoeff
284        self.ycoeff = ycoeff
285        ## other useful arguments
286        ## ... not used here in ppplot but need to be attached to plot object
287        self.axisbg = "white"
288        self.superpose = False
289
290    # check
291    # -------------------------------
292    def check(self):
293        if self.field is None: print "!! ERROR !! Please define a field to be plotted" ; exit()
294
295    # define_from_var
296    # ... this uses settings in set_var.txt
297    # -------------------------------
298    def define_from_var(self):
299        if self.var is not None:
300         if self.var.upper() in vl.keys():
301          self.title = vl[self.var.upper()]
302
303    # make
304    # this is generic to all plots
305    # -------------------------------
306    def make(self):
307        self.check()
308        mpl.xlabel(self.xlabel)
309        mpl.ylabel(self.ylabel)
310        if self.swap:
311         if self.swaplab:
312           mpl.xlabel(self.ylabel)
313           mpl.ylabel(self.xlabel)
314        mpl.title(self.title)
315        # if masked array, set masked values to filled values (e.g. np.nan) for plotting purposes
316        if type(self.field).__name__ in 'MaskedArray':
317            self.field[self.field.mask] = self.field.fill_value
318
319################################
320# a subclass to make a 1D plot #
321################################
322class plot1d(plot):
323
324    # print out a help string when help is invoked on the object
325    # -------------------------------
326    def __repr__(self):
327        whatprint = 'plot1d object. \"help(plot1d)\" for more information\n'
328        return whatprint
329
330    # default settings
331    # -- user can define settings by two methods.
332    # -- 1. yeah = plot1d(title="foo")
333    # -- 2. yeah = pp() ; yeah.title = "foo"
334    # -------------------------------
335    def __init__(self,\
336                 lstyle='-',\
337                 color='b',\
338                 marker='x'):
339        ## get initialization from parent class
340        plot.__init__(self)
341        ## what could be defined by the user
342        self.lstyle = lstyle
343        self.color = color
344        self.marker = marker
345
346    # define_from_var
347    # ... this uses settings in set_var.txt
348    # -------------------------------
349    def define_from_var(self):
350        # get what is done in the parent class
351        plot.define_from_var(self)
352        # add specific stuff
353        if self.var is not None:
354         if self.var.upper() in vl.keys():
355          self.ylabel = vl[self.var.upper()]
356          self.title = ""
357
358    # make
359    # -------------------------------
360    def make(self):
361        # get what is done in the parent class
362        plot.make(self)
363        # add specific stuff
364        mpl.grid(color='grey')
365        if self.lstyle == "": self.lstyle = " " # to allow for no line at all with ""
366        # swapping if requested
367        if self.swap:  x = self.field ; y = self.absc
368        else:          x = self.absc ; y = self.field
369        # coefficients on axis
370        x=x*self.xcoeff ; y=y*self.ycoeff
371        # check axis
372        if x.size != y.size:
373            print "!! ERROR !! x and y sizes don't match on 1D plot.", x.size, y.size
374            exit()
375        # make the 1D plot
376        # either request linestyle or let matplotlib decide
377        if self.lstyle is not None and self.color is not None:
378            mpl.plot(x,y,self.color+self.lstyle,marker=self.marker)
379        else:
380            mpl.plot(x,y,marker=self.marker)
381        # make log axes and/or invert ordinate
382        # ... this must be after plot so that axis bounds are well-defined
383        # ... also inverting must be after making the thing logarithmic
384        if self.logx: mpl.semilogx()
385        if self.logy: mpl.semilogy()
386        if self.invert: ax = mpl.gca() ; ax.set_ylim(ax.get_ylim()[::-1])
387        ## TBD: set with .div the number of ticks
388        ## TBD: be able to control plot limits
389        #ticks = self.div + 1
390        #ax = mpl.gca()
391        #ax.get_xaxis().set_ticks(np.linspace(ppcompute.min(x),ppcompute.max(x),ticks/2+1))
392
393################################
394# a subclass to make a 2D plot #
395################################
396class plot2d(plot):
397
398    # print out a help string when help is invoked on the object
399    # -------------------------------
400    def __repr__(self):
401        whatprint = 'plot2d object. \"help(plot2d)\" for more information\n'
402        return whatprint
403
404    # default settings
405    # -- user can define settings by two methods.
406    # -- 1. yeah = plot2d(title="foo")
407    # -- 2. yeah = pp() ; yeah.title = "foo"
408    # -------------------------------
409    def __init__(self,\
410                 ordi=None,\
411                 mapmode=False,\
412                 proj="cyl",\
413                 back=None,\
414                 colorb="jet",\
415                 trans=1.0,\
416                 addvecx=None,\
417                 addvecy=None,\
418                 addcontour=None,\
419                 fmt="%.2e",\
420                 blon=None,\
421                 blat=None,\
422                 area=None,\
423                 vmin=None,\
424                 vmax=None,\
425                 colorvec="black"):
426        ## get initialization from parent class
427        plot.__init__(self)
428        ## what could be defined by the user
429        self.ordi = ordi
430        self.mapmode = mapmode
431        self.proj = proj
432        self.back = back
433        self.colorb = colorb
434        self.trans = trans
435        self.addvecx = addvecx
436        self.addvecy = addvecy
437        self.colorvec = colorvec
438        self.addcontour = addcontour
439        self.fmt = fmt
440        self.blon = blon ; self.blat = blat
441        self.area = area
442        self.vmin = vmin ; self.vmax = vmax
443
444    # define_from_var
445    # ... this uses settings in set_var.txt
446    # -------------------------------
447    def define_from_var(self):
448        # get what is done in the parent class
449        plot.define_from_var(self)
450        # add specific stuff
451        if self.var is not None:
452         if self.var.upper() in vl.keys():
453          self.colorb = vc[self.var.upper()]
454          self.fmt = vf[self.var.upper()]
455
456    # make
457    # -------------------------------
458    def make(self):
459        # get what is done in the parent class...
460        plot.make(self)
461        # ... then add specific stuff
462        ############################################################################################
463        ### PRE-SETTINGS
464        ############################################################################################
465        # transposing if necessary
466        shape = self.field.shape
467        if shape[0] != shape[1]:
468         if len(self.absc) == shape[0] and len(self.ordi) == shape[1]:
469            print "!! WARNING !! Transposing axes"
470            self.field = np.transpose(self.field)
471        # bound field
472        zevmin, zevmax = calculate_bounds(self.field,vmin=self.vmin,vmax=self.vmax)
473        what_I_plot = bounds(self.field,zevmin,zevmax)
474        # define contour field levels. define color palette
475        ticks = self.div + 1
476        zelevels = np.linspace(zevmin,zevmax,ticks)
477        palette = get_cmap(name=self.colorb)
478        # do the same thing for possible contourline entries
479        if self.addcontour is not None:
480            # if masked array, set masked values to filled values (e.g. np.nan) for plotting purposes
481            if type(self.addcontour).__name__ in 'MaskedArray':
482               self.addcontour[self.addcontour.mask] = self.addcontour.fill_value
483            zevminc, zevmaxc = calculate_bounds(self.addcontour)
484            what_I_contour = bounds(self.addcontour,zevminc,zevmaxc)
485            ticks = self.div + 1
486            zelevelsc = np.linspace(zevminc,zevmaxc,ticks)
487        ############################################################################################
488        ### MAIN PLOT
489        ### NB: contour lines are done before contour shades otherwise colorar error
490        ############################################################################################
491        if not self.mapmode:
492            ## A SIMPLE 2D PLOT
493            ###################
494            # swapping if requested
495            if self.swap:  x = self.ordi ; y = self.absc
496            else:          x = self.absc ; y = self.ordi
497            # coefficients on axis
498            x=x*self.xcoeff ; y=y*self.ycoeff
499            # make shaded and line contours
500            if self.addcontour is not None: 
501                mpl.contour(x, y, what_I_contour, \
502                            zelevelsc, colors = ccol, linewidths = cline)
503            mpl.contourf(x, y, \
504                         self.field, \
505                         zelevels, cmap=palette)
506            # make log axes and/or invert ordinate
507            if self.logx: mpl.semilogx()
508            if self.logy: mpl.semilogy()
509            if self.invert: ax = mpl.gca() ; ax.set_ylim(ax.get_ylim()[::-1])
510        else:
511            ## A 2D MAP USING PROJECTIONS (basemap)
512            #######################################
513            mpl.xlabel("") ; mpl.ylabel("")
514            # additional security in case self.proj is None here
515            # ... we set cylindrical projection (the simplest one)
516            if self.proj is None: self.proj = "cyl"
517            # get lon and lat in 2D version.
518            # (but first ensure we do have 2D coordinates)
519            if self.absc.ndim == 1:     [self.absc,self.ordi] = np.meshgrid(self.absc,self.ordi)
520            elif self.absc.ndim > 2:    print "!! ERROR !! lon and lat arrays must be 1D or 2D"
521            # get lat lon intervals and associated settings
522            wlon = [np.min(self.absc),np.max(self.absc)]
523            wlat = [np.min(self.ordi),np.max(self.ordi)]
524            # -- area presets are in set_area.txt
525            if self.area is not None:
526             if self.area in area.keys():
527                wlon, wlat = area[self.area]
528            # -- settings for meridians and parallels
529            steplon = abs(wlon[1]-wlon[0])/6.
530            steplat = abs(wlat[1]-wlat[0])/3.
531            mertab = np.r_[wlon[0]:wlon[1]:steplon] ; merlab = [0,0,0,1]
532            partab = np.r_[wlat[0]:wlat[1]:steplat] ; parlab = [1,0,0,0]
533            format = '%.1f'
534            # -- center of domain and bounding lats
535            lon_0 = 0.5*(wlon[0]+wlon[1])
536            lat_0 = 0.5*(wlat[0]+wlat[1])
537            # some tests, bug fixes, and good-looking settings
538            # ... cyl is good for global and regional
539            if self.proj == "cyl":
540                pass
541            # ... global projections
542            elif self.proj in ["ortho","moll","robin"]:
543                wlat[0] = None ; wlat[1] = None ; wlon[0] = None ; wlon[1] = None
544                steplon = 30. ; steplat = 30.
545                if self.proj == "robin": steplon = 60.
546                mertab = np.r_[-360.:360.:steplon]
547                partab = np.r_[-90.:90.:steplat]
548                if self.proj == "ortho": 
549                    merlab = [0,0,0,0] ; parlab = [0,0,0,0]
550                    # in ortho projection, blon and blat can be used to set map center
551                    if self.blon is not None: lon_0 = self.blon
552                    if self.blat is not None: lat_0 = self.blat
553                elif self.proj == "moll":
554                    merlab = [0,0,0,0]
555                format = '%.0f'
556            # ... regional projections
557            elif self.proj in ["lcc","laea","merc"]:
558                if self.proj in ["lcc","laea"] and wlat[0] == -wlat[1]: 
559                    print "!! ERROR !! with Lambert lat1 must be different than lat2" ; exit()
560                if wlat[0] < -80. and wlat[1] > 80.:
561                    print "!! ERROR !! set an area (not global)" ; exit()
562                format = '%.0f'
563            elif self.proj in ["npstere","spstere"]:
564                # in polar projections, blat gives the bounding lat
565                # if not set, set something reasonable
566                if self.blat is None:   self.blat = 60.
567                # help the user who forgets self.blat would better be negative in spstere
568                # (this actually serves for the default setting just above)
569                if self.proj == "spstere" and self.blat > 0: self.blat = -self.blat
570            # ... unsupported projections
571            else:
572                print "!! ERROR !! unsupported projection. supported: "+\
573                      "cyl, npstere, spstere, ortho, moll, robin, lcc, laea, merc"
574            # finally define projection
575            m = Basemap(projection=self.proj,\
576                        lat_0=lat_0,lon_0=lon_0,\
577                        boundinglat=self.blat,\
578                        llcrnrlat=wlat[0],urcrnrlat=wlat[1],\
579                        llcrnrlon=wlon[0],urcrnrlon=wlon[1])
580            # draw meridians and parallels
581            ft = int(mpl.rcParams['font.size']*3./4.)
582            m.drawmeridians(mertab,labels=merlab,color='grey',linewidth=0.75,fontsize=ft,fmt=format)
583            m.drawparallels(partab,labels=parlab,color='grey',linewidth=0.75,fontsize=ft,fmt=format)
584            # define background (see set_back.txt)
585            if self.back is not None:
586              if self.back in back.keys():
587                 print "**** info: loading a background, please wait.",self.back
588                 if back not in ["coast","sea"]:   m.warpimage(back[self.back],scale=0.75)
589                 elif back == "coast":             m.drawcoastlines()
590                 elif back == "sea":               m.drawlsmask(land_color='white',ocean_color='aqua')
591              else:
592                 print "!! ERROR !! requested background not defined. change name or fill in set_back.txt" ; exit()
593            # define x and y given the projection
594            x, y = m(self.absc, self.ordi)
595            # contour field. first line contour then shaded contour.
596            if self.addcontour is not None: 
597                m.contour(x, y, what_I_contour, \
598                            zelevelsc, colors = ccol, linewidths = cline)
599            m.contourf(x, y, what_I_plot, zelevels, cmap = palette, alpha = self.trans)
600        ############################################################################################
601        ### COLORBAR
602        ############################################################################################
603        if self.trans > 0.:
604            ## draw colorbar. settings are different with projections. or if not mapmode.
605            if not self.mapmode: orientation=zeorientation ; frac = 0.075
606            elif self.proj in ['moll']: orientation="horizontal" ; frac = 0.075
607            elif self.proj in ['cyl']: orientation="vertical" ; frac = 0.023
608            else: orientation = zeorientation ; frac = zefrac
609            zelevpal = np.linspace(zevmin,zevmax,num=min([ticks/2+1,21]))
610            zecb = mpl.colorbar(fraction=frac,pad=0.03,\
611                                format=self.fmt,orientation=orientation,\
612                                ticks=zelevpal,\
613                                extend='neither',spacing='proportional') 
614            if zeorientation == "horizontal": zecb.ax.set_xlabel(self.title) ; self.title = ""
615        ############################################################################################
616        ### VECTORS. must be after the colorbar. we could also leave possibility for streamlines.
617        ############################################################################################
618        ### not expecting NaN in self.addvecx and self.addvecy. masked arrays is just enough.
619        stride = 3
620        if self.addvecx is not None and self.addvecy is not None and self.mapmode:
621                ## for metwinds only ???
622                [vecx,vecy] = m.rotate_vector(self.addvecx,self.addvecy,self.absc,self.ordi) 
623                # reference vector is scaled
624                zescale = ppcompute.mean(np.sqrt(self.addvecx*self.addvecx+self.addvecy*self.addvecy))
625                # make vector field
626                q = m.quiver( x[::stride,::stride],y[::stride,::stride],\
627                              vecx[::stride,::stride],vecy[::stride,::stride],\
628                              angles='xy',color=self.colorvec,pivot='middle',\
629                              scale=zescale*reducevec,width=widthvec )
630                # make vector key. default is on upper left corner.
631                p = mpl.quiverkey(q,-0.06,0.98,\
632                                  zescale,str(int(zescale)),\
633                                  color='black',labelpos='S',labelsep = 0.07)
Note: See TracBrowser for help on using the repository browser.