source: trunk/UTIL/PYTHON/mcd/mcd.py @ 806

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

UTIL PYTHON. mcd online. sections lon alt and lat alt. and set 'all' mode for any choice of vertical coordinates

  • Property svn:executable set to *
File size: 31.0 KB
RevLine 
[639]1####################################################
2### A Python Class for the Mars Climate Database ###
3### ---------------------------------------------###
4### Aymeric SPIGA 17-21/04/2012                  ###
5### ---------------------------------------------###
6### (see mcdtest.py for examples of use)         ###
7####################################################
8
9import numpy as np
10import fmcd
11import matplotlib.pyplot as mpl
12import myplot
13
14
[793]15class mcd():
16 
[639]17    def __repr__(self):
18    # print out a help string when help is invoked on the object
19        whatprint = 'MCD object. \"help(mcd)\" for more information\n'
20        return whatprint
21
22########################
23### Default settings ###
24########################
25
26    def __init__(self):
27    # default settings
28        ## 0. general stuff
[800]29        self.name      = "MCD v4.3"
30        self.ack       = "Mars Climate Database (c) LMD/OU/IAA/ESA/CNES"
[793]31        #self.dset      = '/home/aymeric/Science/MCD_v4.3/data/'
32        self.dset      = '/home/marshttp/MCD_v4.3/data/'
[639]33        ## 1. spatio-temporal coordinates
34        self.lat       = 0.
[796]35        self.lats      = None
36        self.late      = None
[639]37        self.lon       = 0.
[796]38        self.lons      = None
39        self.lone      = None
[639]40        self.loct      = 0.
[796]41        self.locts     = None
42        self.locte     = None
[639]43        self.xdate     = 0.  # see datekey
[797]44        self.xdates    = None
45        self.xdatee    = None
[639]46        self.xz        = 10. # see zkey
[796]47        self.xzs       = None
48        self.xze       = None
[639]49        ## 1bis. related settings
50        self.zkey      = 3  # specify that xz is the altitude above surface (m)
[797]51                            # zkey  : <integer>   type of vertical coordinate xz
52                            # 1 = radius from centre of planet (m)
53                            # 2 = height above areoid (m) (MOLA zero datum)
54                            # 3 = height above surface (m)
55                            # 4 = pressure level (Pa)
56                            # 5 = altitude above mean Mars Radius(=3396000m) (m)
[639]57        self.datekey   = 1  # 0 = "Earth time": xdate is given in Julian days (localtime must be set to zero)
58                            # 1 = "Mars date": xdate is the value of Ls
59        ## 2. climatological options
60        self.dust      = 2  #our best guess MY24 scenario, with solar average conditions
61        self.hrkey     = 1  #set high resolution mode on (hrkey=0 to set high resolution off)
62        ## 3. additional settings for advanced use
63        self.extvarkey = 1  #extra output variables (1: yes, 0: no)
64        self.perturkey = 0  #integer perturkey ! perturbation type (0: none)
65        self.seedin    = 1  #random number generator seed (unused if perturkey=0)
66        self.gwlength  = 0. #gravity Wave wavelength (unused if perturkey=0)
67        ## outputs. just to define attributes.
68        ## --> in update
69        self.pres = None ; self.dens = None ; self.temp = None ; self.zonwind = None ; self.merwind = None ; self.meanvar = None ; self.extvar = None
70        self.seedout = None ; self.ierr = None
71        ## --> in prepare
72        self.xcoord = None ; self.ycoord = None
73        self.prestab = None ; self.denstab = None ; self.temptab = None 
74        self.zonwindtab = None ; self.merwindtab = None ; self.meanvartab = None ; self.extvartab = None
[800]75        ## plot stuff
76        self.xlabel = None ; self.ylabel = None
77        self.vertplot = False
[639]78
79    def viking1(self): self.name = "Viking 1 site. MCD v4.3 output" ; self.lat = 22.48 ; self.lon = -49.97 ; self.xdate = 97.
80    def viking2(self): self.name = "Viking 2 site. MCD v4.3 output" ; self.lat = 47.97 ; self.lon = -225.74 ; self.xdate = 117.6
81
[800]82    def getdustlabel(self):
83        if self.dust == 1: self.dustlabel = "MY24 minimum solar scenario"
84        elif self.dust == 2: self.dustlabel = "MY24 average solar scenario"
85        elif self.dust == 3: self.dustlabel = "MY24 maximum solar scenario"
86        elif self.dust == 4: self.dustlabel = "dust storm minimum solar scenario"
87        elif self.dust == 5: self.dustlabel = "dust storm average solar scenario"
88        elif self.dust == 6: self.dustlabel = "dust storm maximum solar scenario"
89        elif self.dust == 7: self.dustlabel = "warm scenario (dusty, maximum solar)"
90        elif self.dust == 8: self.dustlabel = "cold scenario (low dust, minimum solar)"
91
92    def gettitle(self):
93        self.getdustlabel()
94        self.title = self.name + " with " + self.dustlabel + "."
[805]95        if self.lats is None:  self.title = self.title + " Latitude " + str(self.lat) + "E"
96        if self.lons is None:  self.title = self.title + " Longitude " + str(self.lon) + "N"
97        if self.xzs is None:   
98            self.vertunits()
99            self.title = self.title + " Altitude " + str(self.xz) + " " + self.vunits
100        if self.locts is None: self.title = self.title + " Local time " + str(self.loct) + "h"
[800]101
[639]102    def getextvarlab(self,num):
103        whichfield = { \
[761]104        91: "Pressure (Pa)", \
105        92: "Density (kg/m3)", \
106        93: "Temperature (K)", \
107        94: "W-E wind component (m/s)", \
108        95: "S-N wind component (m/s)", \
[639]109        1: "Radial distance from planet center (m)",\
110        2: "Altitude above areoid (Mars geoid) (m)",\
111        3: "Altitude above local surface (m)",\
112        4: "orographic height (m) (surface altitude above areoid)",\
113        5: "Ls, solar longitude of Mars (deg)",\
114        6: "LST local true solar time (hrs)",\
115        7: "Universal solar time (LST at lon=0) (hrs)",\
116        8: "Air heat capacity Cp (J kg-1 K-1)",\
117        9: "gamma=Cp/Cv Ratio of specific heats",\
118        10: "density RMS day to day variations (kg/m^3)",\
119        11: "[not defined]",\
120        12: "[not defined]",\
121        13: "scale height H(p) (m)",\
122        14: "GCM orography (m)",\
123        15: "surface temperature (K)",\
124        16: "daily maximum mean surface temperature (K)",\
125        17: "daily minimum mean surface temperature (K)",\
126        18: "surf. temperature RMS day to day variations (K)",\
127        19: "surface pressure (high resolution if hireskey=1)",\
128        20: "GCM surface pressure (Pa)",\
129        21: "atmospheric pressure RMS day to day variations (Pa)",\
130        22: "surface pressure RMS day to day variations (Pa)",\
131        23: "temperature RMS day to day variations (K)",\
132        24: "zonal wind RMS day to day variations (m/s)",\
133        25: "meridional wind RMS day to day variations (m/s)",\
134        26: "vertical wind component (m/s) >0 when downwards!",\
135        27: "vertical wind RMS day to day variations (m/s)",\
136        28: "small scale perturbation (gravity wave) (kg/m^3)",\
137        29: "q2: turbulent kinetic energy (m2/s2)",\
138        30: "[not defined]",\
139        31: "thermal IR flux to surface (W/m2)",\
140        32: "solar flux to surface (W/m2)",\
141        33: "thermal IR flux to space (W/m2)",\
142        34: "solar flux reflected to space (W/m2)",\
143        35: "surface CO2 ice layer (kg/m2)",\
144        36: "DOD: Dust column visible optical depth",\
145        37: "Dust mass mixing ratio (kg/kg)",\
146        38: "DOD RMS day to day variations",\
147        39: "DOD total standard deviation over season",\
148        40: "Water vapor column (kg/m2)",\
149        41: "Water vapor vol. mixing ratio (mol/mol)",\
150        42: "Water ice column (kg/m2)",\
151        43: "Water ice mixing ratio (mol/mol)",\
152        44: "O3 ozone vol. mixing ratio (mol/mol)",\
153        45: "[CO2] vol. mixing ratio (mol/mol)",\
154        46: "[O] vol. mixing ratio (mol/mol)",\
155        47: "[N2] vol. mixing ratio (mol/mol)",\
156        48: "[CO] vol. mixing ratio (mol/mol)",\
157        49: "R: Molecular gas constant (J K-1 kg-1)",\
158        50: "Air viscosity estimation (N s m-2)"
159        }
[761]160        if num not in whichfield: myplot.errormess("Incorrect subscript in extvar.")
[639]161        return whichfield[num]
162
[761]163    def convertlab(self,num):       
164        ## a conversion from text inquiries to extvar numbers. to be completed.
165        if num == "p": num = 91
166        elif num == "rho": num = 92
167        elif num == "t": num = 93
168        elif num == "u": num = 94
169        elif num == "v": num = 95
170        elif num == "tsurf": num = 15
171        elif num == "topo": num = 4
172        elif num == "h": num = 13
173        elif num == "ps": num = 19
174        elif num == "tau": num = 36
175        elif num == "mtot": num = 40
176        elif num == "icetot": num = 42
177        elif num == "ps_ddv": num = 22
178        elif num == "h2ovap": num = 41
179        elif num == "h2oice": num = 43
180        elif num == "cp": num = 8
181        elif num == "rho_ddv": num = 10
182        elif num == "tsurfmx": num = 16
183        elif num == "tsurfmn": num = 17
184        elif num == "lwdown": num = 31
185        elif num == "swdown": num = 32
186        elif num == "lwup": num = 33
187        elif num == "swup": num = 34
188        elif num == "o3": num = 44
189        elif num == "o": num = 46
190        elif num == "co": num = 48
191        elif num == "visc": num = 50
192        elif num == "co2ice": num = 35
193        elif not isinstance(num, np.int): myplot.errormess("field reference not found.")
194        return num
195
[639]196###################
197### One request ###
198###################
199
200    def update(self):
201    # retrieve fields from MCD (call_mcd). more info in fmcd.call_mcd.__doc__
202        (self.pres, self.dens, self.temp, self.zonwind, self.merwind, \
203         self.meanvar, self.extvar, self.seedout, self.ierr) \
204         = \
205         fmcd.call_mcd(self.zkey,self.xz,self.lon,self.lat,self.hrkey, \
206             self.datekey,self.xdate,self.loct,self.dset,self.dust, \
207             self.perturkey,self.seedin,self.gwlength,self.extvarkey )
[761]208        ## we use the end of extvar (unused) to store meanvar. this is convenient for getextvar(lab)
209        self.extvar[90] = self.pres ; self.extvar[91] = self.dens
210        self.extvar[92] = self.temp ; self.extvar[93] = self.zonwind ; self.extvar[94] = self.merwind
[800]211        ## treat missing values
212        if self.temp == -999: self.extvar[:] = np.NaN ; self.meanvar[:] = np.NaN
[639]213
214    def printset(self):
215    # print main settings
216        print "zkey",self.zkey,"xz",self.xz,"lon",self.lon,"lat",self.lat,"hrkey",self.hrkey, \
217              "xdate",self.xdate,"loct",self.loct,"dust",self.dust
218
219    def getnameset(self):
220    # set a name referring to settings [convenient for databases]
[796]221        strlat = str(self.lat)+str(self.lats)+str(self.late)
222        strlon = str(self.lon)+str(self.lons)+str(self.lone)
223        strxz = str(self.xz)+str(self.xzs)+str(self.xze)
224        strloct = str(self.loct)+str(self.locts)+str(self.locte)
225        name = str(self.zkey)+strxz+strlon+strlat+str(self.hrkey)+str(self.datekey)+str(self.xdate)+strloct+str(self.dust)
[639]226        return name
227
228    def printcoord(self):
229    # print requested space-time coordinates
230        print "LAT",self.lat,"LON",self.lon,"LOCT",self.loct,"XDATE",self.xdate
231
232    def printmeanvar(self):
233    # print mean MCD variables
234        print "Pressure = %5.3f pascals. " % (self.pres)
235        print "Density = %5.3f kilograms per cubic meter. " % (self.dens)
236        print "Temperature = %3.0f kelvins (%4.0f degrees celsius)." % (self.temp,self.temp-273.15)
237        print "Zonal wind = %5.3f meters per second." % (self.zonwind)
238        print "Meridional wind = %5.3f meters per second." % (self.merwind)
[805]239        print "Total horizontal wind = %5.3f meters per second." % ( np.sqrt(self.zonwind**2 + self.merwind**2) )
[639]240
241    def printextvar(self,num):
242    # print extra MCD variables
[761]243        num = self.convertlab(num)
244        print self.getextvarlab(num) + " ..... " + str(self.extvar[num-1])
[639]245
246    def printallextvar(self):
247    # print all extra MCD variables   
248        for i in range(50): self.printextvar(i+1)
249
[761]250    def htmlprinttabextvar(self,tabtodo):
251        print "Results from the Mars Climate Database"
252        print "<ul>"
253        for i in range(len(tabtodo)): print "<li>" ; self.printextvar(tabtodo[i]) ; print "</li>"
254        print "</ul>"
255        print "<hr>"
256        print "SETTINGS<br />"
257        self.printcoord()
258        self.printset()
259
[639]260    def printmcd(self):
261    # 1. call MCD 2. print settings 3. print mean vars
262        self.update()
263        self.printcoord()
[761]264        print "-------------------------------------------"
[639]265        self.printmeanvar()
266
267########################
268### Several requests ###
269########################
270
271    def prepare(self,ndx=None,ndy=None):
272    ### prepare I/O arrays for 1d slices
273      if ndx is None:  print "No dimension in prepare. Exit. Set at least ndx." ; exit()
274      else:            self.xcoord = np.ones(ndx)
275      if ndy is None:  dashape = (ndx)     ; dashapemean = (ndx,6)     ; dashapeext = (ndx,101)     ; self.ycoord = None
276      else:            dashape = (ndx,ndy) ; dashapemean = (ndx,ndy,6) ; dashapeext = (ndx,ndy,101) ; self.ycoord = np.ones(ndy)
277      self.prestab = np.ones(dashape) ; self.denstab = np.ones(dashape) ; self.temptab = np.ones(dashape)
278      self.zonwindtab = np.ones(dashape) ; self.merwindtab = np.ones(dashape) 
279      self.meanvartab = np.ones(dashapemean) ; self.extvartab = np.ones(dashapeext)
280
281    def getextvar(self,num):
282    ### get a given var in extvartab
283      try: field=self.extvartab[:,:,num] 
284      except: field=self.extvartab[:,num]
285      return field
286
287    def definefield(self,choice):
288    ### for analysis or plot purposes, set field and field label from user-defined choice
[761]289      choice = self.convertlab(choice)
290      field = self.getextvar(choice); fieldlab = self.getextvarlab(choice)
[639]291      return field,fieldlab
292
[806]293    def ininterv(self,dstart,dend,nd,start=None,end=None,yaxis=False,vertcoord=False):
[797]294    ### user-defined start and end are used to create xcoord (or ycoord) vector
[806]295      if start is not None and end is not None:  first, second = self.correctbounds(start,end,vertcoord)
296      else:                                      first, second = self.correctbounds(dstart,dend,vertcoord) 
297      if self.zkey != 4 or not vertcoord:   tabtab = np.linspace(first,second,nd)
298      else:                                 tabtab = np.logspace(first,second,nd)
[800]299      if not yaxis:      self.xcoord = tabtab
300      else:              self.ycoord = tabtab
[797]301
[806]302    def correctbounds(self,start,end,vertcoord):
303      if self.zkey != 4 or not vertcoord:
[797]304        # regular altitudes
305        if start > end: first = end ; second = start
306        else:           first = start ; second = end
307      else:
308        # pressure: reversed avis
[800]309        if start < end: first = np.log10(end) ; second = np.log10(start)
310        else:           first = np.log10(start) ; second = np.log10(end)
[797]311      return first, second
312
[800]313    def vertlabel(self):
314      if self.zkey == 1:   self.xlabel = "radius from centre of planet (m)"
315      elif self.zkey == 2: self.xlabel = "height above areoid (m) (MOLA zero datum)"
316      elif self.zkey == 3: self.xlabel = "height above surface (m)"
317      elif self.zkey == 4: self.xlabel = "pressure level (Pa)"
318      elif self.zkey == 5: self.xlabel = "altitude above mean Mars Radius(=3396000m) (m)"
319
[805]320    def vertunits(self):
321      if self.zkey == 1:   self.vunits = "m CP"
322      elif self.zkey == 2: self.vunits = "m AMR"
323      elif self.zkey == 3: self.vunits = "m ALS"
324      elif self.zkey == 4: self.vunits = "Pa"
325      elif self.zkey == 5: self.vunits = "m AMMRad"
326
[806]327    def vertaxis(self,number,yaxis=False):
328      if self.zkey == 2:   self.ininterv(-5000.,100000.,number,start=self.xzs,end=self.xze,yaxis=yaxis,vertcoord=True)
329      elif self.zkey == 3: self.ininterv(0.,120000.,number,start=self.xzs,end=self.xze,yaxis=yaxis,vertcoord=True)
330      elif self.zkey == 5: self.ininterv(-5000.,100000.,number,start=self.xzs,end=self.xze,yaxis=yaxis,vertcoord=True)
331      elif self.zkey == 4: self.ininterv(1000.,0.001,number,start=self.xzs,end=self.xze,yaxis=yaxis,vertcoord=True)
332      elif self.zkey == 1: self.ininterv(3396000,3596000,number,start=self.xzs,end=self.xze,yaxis=yaxis,vertcoord=True)
333
[639]334###################
335### 1D analysis ###
336###################
337
338    def put1d(self,i):
339    ## fill in subscript i in output arrays
340    ## (arrays must have been correctly defined through prepare)
[761]341      if self.prestab is None:  myplot.errormess("arrays must be prepared first through self.prepare")
[639]342      self.prestab[i] = self.pres ; self.denstab[i] = self.dens ; self.temptab[i] = self.temp
343      self.zonwindtab[i] = self.zonwind ; self.merwindtab[i] = self.merwind
344      self.meanvartab[i,1:5] = self.meanvar[0:4]  ## note: var numbering according to MCD manual is kept
345      self.extvartab[i,1:100] = self.extvar[0:99] ## note: var numbering according to MCD manual is kept
346
[796]347    def diurnal(self,nd=13):
[639]348    ### retrieve a local time slice
[805]349      save = self.loct
[639]350      self.xlabel = "Local time (Martian hour)"
[797]351      self.prepare(ndx=nd) ; self.ininterv(0.,24.,nd,start=self.locts,end=self.locte) 
[639]352      for i in range(nd): self.loct = self.xcoord[i] ; self.update() ; self.put1d(i)
[805]353      self.loct = save
[639]354
[796]355    def zonal(self,nd=37):
[639]356    ### retrieve a longitude slice
[805]357      save = self.lon
[639]358      self.xlabel = "East longitude (degrees)"
[797]359      self.prepare(ndx=nd) ; self.ininterv(-180.,180.,nd,start=self.lons,end=self.lone)
[639]360      for i in range(nd): self.lon = self.xcoord[i] ; self.update() ; self.put1d(i)
[805]361      self.lon = save
[639]362
[796]363    def meridional(self,nd=19):
[639]364    ### retrieve a latitude slice
[805]365      save = self.lat
[639]366      self.xlabel = "North latitude (degrees)"
[797]367      self.prepare(ndx=nd) ; self.ininterv(-90.,90.,nd,start=self.lats,end=self.late)
[639]368      for i in range(nd): self.lat = self.xcoord[i] ; self.update() ; self.put1d(i)
[805]369      self.lat = save
[639]370
[796]371    def profile(self,nd=20,tabperso=None):
[639]372    ### retrieve an altitude slice (profile)
[805]373      save = self.xz
[800]374      self.vertlabel()
375      self.vertplot = True
[653]376      if tabperso is not None: nd = len(tabperso)
[797]377      correct = False
[806]378      self.prepare(ndx=nd) ; self.vertaxis(nd)
[797]379      if tabperso is not None: self.xcoord = tabperso
[639]380      for i in range(nd): self.xz = self.xcoord[i] ; self.update() ; self.put1d(i)
[805]381      self.xz = save
[639]382
[797]383    def seasonal(self,nd=12):
[723]384    ### retrieve a seasonal slice
[805]385      save = self.xdate
[723]386      self.xlabel = "Areocentric longitude (degrees)"
[797]387      self.prepare(ndx=nd) ; self.ininterv(0.,360.,nd,start=self.xdates,end=self.xdatee)
[723]388      for i in range(nd): self.xdate = self.xcoord[i] ; self.update() ; self.put1d(i)
[805]389      self.xdate = save
[723]390
[800]391    def makeplot1d(self,choice):
[639]392    ### one 1D plot is created for the user-defined variable in choice.
393      (field, fieldlab) = self.definefield(choice)
[800]394      if not self.vertplot:  absc = self.xcoord ; ordo = field ; ordolab = fieldlab ; absclab = self.xlabel
395      else:                  ordo = self.xcoord ; absc = field ; absclab = fieldlab ; ordolab = self.xlabel
[639]396      mpl.plot(absc,ordo,'-bo') ; mpl.ylabel(ordolab) ; mpl.xlabel(absclab) #; mpl.xticks(query.xcoord)
[800]397      if self.zkey == 4: mpl.semilogy() ; ax = mpl.gca() ; ax.set_ylim(ax.get_ylim()[::-1])
398      mpl.figtext(0.5, 0.01, self.ack, ha='center')
[639]399
[800]400    def plot1d(self,tabtodo):
[639]401    ### complete 1D figure with possible multiplots
402      if isinstance(tabtodo,np.str): tabtodo=[tabtodo] ## so that asking one element without [] is possible.
403      if isinstance(tabtodo,np.int): tabtodo=[tabtodo] ## so that asking one element without [] is possible.
404      fig = mpl.figure() ; subv,subh = myplot.definesubplot( len(tabtodo) , fig ) 
[800]405      for i in range(len(tabtodo)): mpl.subplot(subv,subh,i+1).grid(True, linestyle=':', color='grey') ; self.makeplot1d(tabtodo[i])
[639]406
[800]407    def htmlplot1d(self,tabtodo,figname="temp.png",title=""):
[793]408    ### complete 1D figure with possible multiplots
409    ### added in 09/2012 for online MCD
410    ### see http://www.dalkescientific.com/writings/diary/archive/2005/04/23/matplotlib_without_gui.html
411      from matplotlib.figure import Figure
412      from matplotlib.backends.backend_agg import FigureCanvasAgg
413      if isinstance(tabtodo,np.str): tabtodo=[tabtodo] ## so that asking one element without [] is possible.
414      if isinstance(tabtodo,np.int): tabtodo=[tabtodo] ## so that asking one element without [] is possible.
415      fig = Figure(figsize=(8,8)) ; subv,subh = myplot.definesubplot( len(tabtodo) , fig )
416      for i in range(len(tabtodo)):
417        yeah = fig.add_subplot(subv,subh,i+1) #.grid(True, linestyle=':', color='grey')
418        choice = tabtodo[i]
419        (field, fieldlab) = self.definefield(choice)
[800]420        if not self.vertplot:  absc = self.xcoord ; ordo = field ; ordolab = fieldlab ; absclab = self.xlabel
421        else:                  ordo = self.xcoord ; absc = field ; absclab = fieldlab ; ordolab = self.xlabel
[793]422        yeah.plot(absc,ordo,'-bo') #; mpl.xticks(query.xcoord)
423        ax = fig.gca() ; ax.set_ylabel(ordolab) ; ax.set_xlabel(absclab)
[800]424        if self.zkey == 4: ax.set_yscale('log') ; ax.set_ylim(ax.get_ylim()[::-1])
425      self.gettitle()
426      fig.text(0.5, 0.95, self.title, ha='center')
427      fig.text(0.5, 0.01, self.ack, ha='center')
[793]428      canvas = FigureCanvasAgg(fig)
429      # The size * the dpi gives the final image size
430      #   a4"x4" image * 80 dpi ==> 320x320 pixel image
431      canvas.print_figure(figname, dpi=80)
432
[639]433###################
434### 2D analysis ###
435###################
436
[796]437    def latlon(self,ndx=37,ndy=19,fixedlt=False):
[761]438    ### retrieve a latitude/longitude slice
439    ### default is: local time is not fixed. user-defined local time is at longitude 0.
[805]440      save1 = self.lon ; save2 = self.lat ; save3 = self.loct
[761]441      self.xlabel = "East longitude (degrees)" ; self.ylabel = "North latitude (degrees)"
442      self.prepare(ndx=ndx,ndy=ndy)
[797]443      self.ininterv(-180.,180.,ndx,start=self.lons,end=self.lone)
444      self.ininterv(-90.,  90.,ndy,start=self.lats,end=self.late,yaxis=True)
[761]445      if not fixedlt: umst = self.loct
446      for i in range(ndx):
447       for j in range(ndy):
448         self.lon = self.xcoord[i] ; self.lat = self.ycoord[j]
[805]449         if not fixedlt: 
450           if self.lons is not None and self.lone is not None: self.loct = (umst + (self.lons+self.lone)/30.) % 24
451           else:                                               self.loct = (umst + self.lon/15.) % 24
[761]452         self.update() ; self.put2d(i,j)
453      if not fixedlt: self.loct = umst
[805]454      self.lon = save1 ; self.lat = save2 ; self.loct = save3
[761]455
[806]456    def lonalt(self,ndx=37,ndy=20,fixedlt=False):
457    ### retrieve a longitude/altitude slice
458      save1 = self.lon ; save2 = self.xz ; save3 = self.loct
459      self.vertlabel() ; self.ylabel = self.xlabel
460      self.xlabel = "East longitude (degrees)"
461      self.prepare(ndx=ndx,ndy=ndy)
462      self.ininterv(-180.,180.,ndx,start=self.lons,end=self.lone)
463      self.vertaxis(ndy,yaxis=True)
464      if not fixedlt: umst = self.loct
465      for i in range(ndx):
466       for j in range(ndy):
467         self.lon = self.xcoord[i] ; self.xz = self.ycoord[j] 
468         if not fixedlt: 
469           if self.lons is not None and self.lone is not None: self.loct = (umst + (self.lons+self.lone)/30.) % 24
470           else:                                               self.loct = (umst + self.lon/15.) % 24
471         self.update() ; self.put2d(i,j)
472      if not fixedlt: self.loct = umst
473      self.lon = save1 ; self.xz = save2 ; self.loct = save3
474
475    def latalt(self,ndx=19,ndy=20,fixedlt=False):
476    ### retrieve a latitude/altitude slice
477      save1 = self.lat ; save2 = self.xz ; save3 = self.loct
478      self.vertlabel() ; self.ylabel = self.xlabel
479      self.xlabel = "North latitude (degrees)"
480      self.prepare(ndx=ndx,ndy=ndy)
481      self.ininterv(-90.,90.,ndx,start=self.lats,end=self.late)
482      self.vertaxis(ndy,yaxis=True)
483      if not fixedlt: umst = self.loct
484      for i in range(ndx):
485       for j in range(ndy):
486         self.lat = self.xcoord[i] ; self.xz = self.ycoord[j] 
487         if not fixedlt: self.loct = (umst + self.lon/15.) % 24
488         self.update() ; self.put2d(i,j)
489      if not fixedlt: self.loct = umst
490      self.lat = save1 ; self.xz = save2 ; self.loct = save3
491
[639]492    def put2d(self,i,j):
493    ## fill in subscript i,j in output arrays
494    ## (arrays must have been correctly defined through prepare)
[761]495      if self.prestab is None:  myplot.errormess("arrays must be prepared first through self.prepare")
[639]496      self.prestab[i,j] = self.pres ; self.denstab[i,j] = self.dens ; self.temptab[i,j] = self.temp
497      self.zonwindtab[i,j] = self.zonwind ; self.merwindtab[i,j] = self.merwind
498      self.meanvartab[i,j,1:5] = self.meanvar[0:4]  ## note: var numbering according to MCD manual is kept
499      self.extvartab[i,j,1:100] = self.extvar[0:99] ## note: var numbering according to MCD manual is kept
500
[796]501    def makemap2d(self,choice,incwind=False,fixedlt=False,proj="cyl"):
[639]502    ### one 2D map is created for the user-defined variable in choice.
[761]503      self.latlon(fixedlt=fixedlt) ## a map is implicitely a lat-lon plot. otherwise it is a plot (cf. makeplot2d)
[796]504      if choice == "wind" or incwind:
[723]505          (windx, fieldlabwx) = self.definefield("u")
506          (windy, fieldlabwy) = self.definefield("v")
[796]507      if choice == "wind":
508          field = np.sqrt(windx*windx + windy*windy)
509          fieldlab = "Horizontal wind speed (m/s)"
510      else:   
511          (field, fieldlab) = self.definefield(choice)
512      if incwind:   myplot.maplatlon(self.xcoord,self.ycoord,field,title=fieldlab,proj=proj,vecx=windx,vecy=windy) #,stride=1)
513      else:         myplot.maplatlon(self.xcoord,self.ycoord,field,title=fieldlab,proj=proj)
[800]514      mpl.figtext(0.5, 0.0, self.ack, ha='center')
[639]515
[796]516    def map2d(self,tabtodo,incwind=False,fixedlt=False,proj="cyl"):
[639]517    ### complete 2D figure with possible multiplots
518      if isinstance(tabtodo,np.str): tabtodo=[tabtodo] ## so that asking one element without [] is possible.
519      if isinstance(tabtodo,np.int): tabtodo=[tabtodo] ## so that asking one element without [] is possible.
[793]520      fig = mpl.figure()
521      subv,subh = myplot.definesubplot( len(tabtodo) , fig ) 
[796]522      for i in range(len(tabtodo)): mpl.subplot(subv,subh,i+1) ; self.makemap2d(tabtodo[i],incwind=incwind,fixedlt=fixedlt,proj=proj)
[639]523
[796]524    def htmlmap2d(self,tabtodo,incwind=False,fixedlt=False,figname="temp.png",title=""):
[793]525    ### complete 2D figure with possible multiplots
526    ### added in 09/2012 for online MCD
527    ### see http://www.dalkescientific.com/writings/diary/archive/2005/04/23/matplotlib_without_gui.html
528      from matplotlib.figure import Figure
529      from matplotlib.backends.backend_agg import FigureCanvasAgg
530      from matplotlib.cm import get_cmap
531      if isinstance(tabtodo,np.str): tabtodo=[tabtodo] ## so that asking one element without [] is possible.
532      if isinstance(tabtodo,np.int): tabtodo=[tabtodo] ## so that asking one element without [] is possible.
533      fig = Figure(figsize=(8,8)) ; subv,subh = myplot.definesubplot( len(tabtodo) , fig )
534
535      ### topocontours
536      fieldc = self.getextvar(self.convertlab("topo"))
537
538      for i in range(len(tabtodo)):
539        yeah = fig.add_subplot(subv,subh,i+1)
540        choice = tabtodo[i]
[796]541        self.latlon(fixedlt=fixedlt) 
542        ## a map is implicitely a lat-lon plot. otherwise it is a plot (cf. makeplot2d)
[793]543        (field, fieldlab) = self.definefield(choice)
544        if incwind: (windx, fieldlabwx) = self.definefield("u") ; (windy, fieldlabwy) = self.definefield("v")
545
546        proj="cyl" ; colorb="jet" ; ndiv=20 ; zeback="molabw" ; trans=1.0 #0.6
547        title="" ; vecx=None ; vecy=None ; stride=2
548        lon = self.xcoord
549        lat = self.ycoord
550
551        ### get lon and lat in 2D version. get lat/lon intervals
552        #numdim = len(np.array(lon).shape)
553        #if numdim == 2:     [lon2d,lat2d] = [lon,lat]
554        #elif numdim == 1:   [lon2d,lat2d] = np.meshgrid(lon,lat)
555        #else:               errormess("lon and lat arrays must be 1D or 2D")
556        #[wlon,wlat] = myplot.latinterv()
557        ### define projection and background. define x and y given the projection
558        #m = basemap.Basemap(projection='moll') marche pas
559        #m = myplot.define_proj(proj,wlon,wlat,back=zeback,blat=None,blon=None)
560        #x, y = m(lon2d, lat2d)
561        ### TEMP
562        x = lon ; y = lat
563        ## define field. bound field.
564        what_I_plot = np.transpose(field)
565        zevmin, zevmax = myplot.calculate_bounds(what_I_plot)  ## vmin=min(what_I_plot_frame), vmax=max(what_I_plot_frame))
566        what_I_plot = myplot.bounds(what_I_plot,zevmin,zevmax)
567        ## define contour field levels. define color palette
568        ticks = ndiv + 1
569        zelevels = np.linspace(zevmin,zevmax,ticks)
570        palette = get_cmap(name=colorb)
571        ## contours topo
572        zelevc = np.linspace(-8000.,20000.,20)
573        yeah.contour( x, y, np.transpose(fieldc), zelevc, colors='black',linewidths = 0.4)
574        # contour field
575        c = yeah.contourf( x, y, what_I_plot, zelevels, cmap = palette, alpha = trans )
[805]576        clb = Figure.colorbar(fig,c,orientation='vertical',format="%.1e")
577        clb.set_label(fieldlab)
[793]578        ax = fig.gca() ; ax.set_title(fieldlab) ; ax.set_ylabel("Latitude") ; ax.set_xlabel("Longitude")
[796]579        ax.set_xticks(np.arange(-180,181,45)) ; ax.set_xbound(lower=self.lons, upper=self.lone)
580        ax.set_yticks(np.arange(-90,91,30)) ; ax.set_ybound(lower=self.lats, upper=self.late)
[793]581        if incwind:
582          [x2d,y2d] = np.meshgrid(x,y)
583          yeah.quiver(x2d,y2d,np.transpose(windx),np.transpose(windy))
[800]584      self.gettitle()
585      fig.text(0.5, 0.95, self.title, ha='center')
586      fig.text(0.5, 0.01, self.ack, ha='center')
[793]587      canvas = FigureCanvasAgg(fig)
588      # The size * the dpi gives the final image size
589      #   a4"x4" image * 80 dpi ==> 320x320 pixel image
590      canvas.print_figure(figname, dpi=80)
591
[806]592    def htmlplot2d(self,tabtodo,fixedlt=False,figname="temp.png",title=""):
593    ### complete 2D figure with possible multiplots
594    ### added in 10/2012 for online MCD
595    ### see http://www.dalkescientific.com/writings/diary/archive/2005/04/23/matplotlib_without_gui.html
596      from matplotlib.figure import Figure
597      from matplotlib.backends.backend_agg import FigureCanvasAgg
598      from matplotlib.cm import get_cmap
599      if isinstance(tabtodo,np.str): tabtodo=[tabtodo] ## so that asking one element without [] is possible.
600      if isinstance(tabtodo,np.int): tabtodo=[tabtodo] ## so that asking one element without [] is possible.
601      fig = Figure(figsize=(8,8)) ; subv,subh = myplot.definesubplot( len(tabtodo) , fig )
[793]602
[806]603      for i in range(len(tabtodo)):
604        yeah = fig.add_subplot(subv,subh,i+1)
605        choice = tabtodo[i]
606
607        if self.lons is not None:    self.lonalt(fixedlt=fixedlt)
608        elif self.lats is not None:  self.latalt(fixedlt=fixedlt)
609
610        (field, fieldlab) = self.definefield(choice)
611
612        colorb="jet" ; ndiv=20 ; title=""
613
614        ## define field. bound field.
615        what_I_plot = np.transpose(field)
616        zevmin, zevmax = myplot.calculate_bounds(what_I_plot)  ## vmin=min(what_I_plot_frame), vmax=max(what_I_plot_frame))
617        what_I_plot = myplot.bounds(what_I_plot,zevmin,zevmax)
618        ## define contour field levels. define color palette
619        ticks = ndiv + 1
620        zelevels = np.linspace(zevmin,zevmax,ticks)
621        palette = get_cmap(name=colorb)
622        # contour field
623        c = yeah.contourf( self.xcoord, self.ycoord, what_I_plot, zelevels, cmap = palette )
624        clb = Figure.colorbar(fig,c,orientation='vertical',format="%.1e")
625        clb.set_label(fieldlab)
626        ax = fig.gca() ; ax.set_ylabel(self.ylabel) ; ax.set_xlabel(self.xlabel)
627        if self.zkey == 4: ax.set_yscale('log') ; ax.set_ylim(ax.get_ylim()[::-1])
628
629        #ax.set_xticks(np.arange(-180,181,45)) ; ax.set_xbound(lower=self.lons, upper=self.lone)
630        #ax.set_yticks(np.arange(-90,91,30)) ; ax.set_ybound(lower=self.lats, upper=self.late)
631
632      self.gettitle()
633      fig.text(0.5, 0.95, self.title, ha='center')
634      fig.text(0.5, 0.01, self.ack, ha='center')
635      canvas = FigureCanvasAgg(fig)
636      # The size * the dpi gives the final image size
637      #   a4"x4" image * 80 dpi ==> 320x320 pixel image
638      canvas.print_figure(figname, dpi=80)
639
640
[761]641    ### TODO: makeplot2d, plot2d, passer plot settings
[653]642
Note: See TracBrowser for help on using the repository browser.