Index: trunk/UTIL/PYTHON/mcd/mcd.py
===================================================================
--- trunk/UTIL/PYTHON/mcd/mcd.py	(revision 820)
+++ trunk/UTIL/PYTHON/mcd/mcd.py	(revision 821)
@@ -74,7 +74,10 @@
         self.zonwindtab = None ; self.merwindtab = None ; self.meanvartab = None ; self.extvartab = None
         ## plot stuff
-        self.xlabel = None ; self.ylabel = None
+        self.xlabel = None ; self.ylabel = None ; self.title = ""
         self.vertplot = False
-        self.fmt = "%.2e"
+        self.fmt = "%.2e" 
+        self.colorm = "jet"
+        self.fixedlt = False
+        self.zonmean = False
 
     def viking1(self): self.name = "Viking 1 site. MCD v4.3 output" ; self.lat = 22.48 ; self.lon = -49.97 ; self.xdate = 97.
@@ -97,10 +100,13 @@
         elif self.datekey == 0:  self.title = self.title + " JD " + str(self.xdate) + "."
         if not oneline: self.title = self.title + "\n"
-        if self.lats is None:  self.title = self.title + " Latitude " + str(self.lat) + "E"
-        if self.lons is None:  self.title = self.title + " Longitude " + str(self.lon) + "N"
+        if self.lats is None:  self.title = self.title + " Latitude " + str(self.lat) + "N"
+        if self.zonmean: self.title = self.title + "Zonal mean over all longitudes."
+        elif self.lons is None: self.title = self.title + " Longitude " + str(self.lon) + "E"
         if self.xzs is None:   
             self.vertunits()
             self.title = self.title + " Altitude " + str(self.xz) + " " + self.vunits
-        if self.locts is None: self.title = self.title + " Local time " + str(self.loct) + "h"
+        if self.locts is None:
+            self.title = self.title + " Local time " + str(self.loct) + "h"
+            if not self.fixedlt:  self.title = self.title + " (at longitude 0) "
 
     def getextvarlab(self,num):
@@ -269,5 +275,7 @@
     # print extra MCD variables
         num = self.convertlab(num)
-        print self.getextvarlab(num) + " ..... " + str(self.extvar[num-1])
+        dastr = str(self.extvar[num-1])
+        if dastr == "nan":   print "!!!! There is a problem, probably a value is requested below the surface !!!!"
+        else:                print self.getextvarlab(num) + " ..... " + dastr
 
     def printallextvar(self):
@@ -276,4 +284,5 @@
 
     def htmlprinttabextvar(self,tabtodo):
+        self.fixedlt = True ## local time is real local time
         self.gettitle()
         print "<hr>"
@@ -383,4 +392,5 @@
     def diurnal(self,nd=13):
     ### retrieve a local time slice
+      self.fixedlt = True  ## local time is real local time
       save = self.loct
       self.xlabel = "Local time (Martian hour)"
@@ -394,9 +404,14 @@
       self.xlabel = "East longitude (degrees)"
       self.prepare(ndx=nd) ; self.ininterv(-180.,180.,nd,start=self.lons,end=self.lone)
-      for i in range(nd): self.lon = self.xcoord[i] ; self.update() ; self.put1d(i)
+      if not self.fixedlt: umst = self.loct
+      for i in range(nd): 
+          self.lon = self.xcoord[i]
+          if not self.fixedlt: self.loct = (umst + self.lon/15.) % 24
+          self.update() ; self.put1d(i)
       self.lon = save
 
     def meridional(self,nd=19):
     ### retrieve a latitude slice
+      self.fixedlt = True  ## local time is real local time
       save = self.lat
       self.xlabel = "North latitude (degrees)"
@@ -407,4 +422,5 @@
     def profile(self,nd=20,tabperso=None):
     ### retrieve an altitude slice (profile)
+      self.fixedlt = True  ## local time is real local time
       save = self.xz
       self.vertlabel()
@@ -482,9 +498,12 @@
         yeah.plot(absc,ordo,'-bo') #; mpl.xticks(query.xcoord)
         ax = fig.gca() ; ax.set_ylabel(ordolab) ; ax.set_xlabel(absclab)
-        if self.zkey == 4: ax.set_yscale('log') ; ax.set_ylim(ax.get_ylim()[::-1])
+
+        if self.xzs is not None and self.zkey == 4: ax.set_yscale('log') ; ax.set_ylim(ax.get_ylim()[::-1])
 
         if self.lats is not None:      ax.set_xticks(np.arange(-90,91,15)) ; ax.set_xbound(lower=self.lats, upper=self.late)
         elif self.lons is not None:    ax.set_xticks(np.arange(-360,361,30)) ; ax.set_xbound(lower=self.lons, upper=self.lone)
         elif self.locts is not None:   ax.set_xticks(np.arange(0,26,2)) ; ax.set_xbound(lower=self.locts, upper=self.locte)
+
+        ax.grid(True, linestyle=':', color='grey')
 
       self.gettitle()
@@ -500,5 +519,5 @@
 ###################
 
-    def latlon(self,ndx=37,ndy=19,fixedlt=False):
+    def latlon(self,ndx=37,ndy=19):
     ### retrieve a latitude/longitude slice
     ### default is: local time is not fixed. user-defined local time is at longitude 0.
@@ -508,46 +527,94 @@
       self.ininterv(-180.,180.,ndx,start=self.lons,end=self.lone)
       self.ininterv(-90.,  90.,ndy,start=self.lats,end=self.late,yaxis=True)
-      if not fixedlt: umst = self.loct
+      if not self.fixedlt: umst = self.loct
       for i in range(ndx):
        for j in range(ndy):
          self.lon = self.xcoord[i] ; self.lat = self.ycoord[j]
-         if not fixedlt: self.loct = (umst + self.lon/15.) % 24
+         if not self.fixedlt: self.loct = (umst + self.lon/15.) % 24
          self.update() ; self.put2d(i,j)
-      if not fixedlt: self.loct = umst
+      if not self.fixedlt: self.loct = umst
       self.lon = save1 ; self.lat = save2 ; self.loct = save3
 
-    def lonalt(self,ndx=37,ndy=20,fixedlt=False):
-    ### retrieve a longitude/altitude slice
-      save1 = self.lon ; save2 = self.xz ; save3 = self.loct
+    def secalt(self,ndx=37,ndy=20,typex="lat"):
+    ### retrieve a coordinate/altitude slice
+      save1 = self.lon ; save2 = self.xz ; save3 = self.loct ; save4 = self.lat
+      self.prepare(ndx=ndx,ndy=ndy)
       self.vertlabel() ; self.ylabel = self.xlabel
-      self.xlabel = "East longitude (degrees)"
-      self.prepare(ndx=ndx,ndy=ndy)
-      self.ininterv(-180.,180.,ndx,start=self.lons,end=self.lone)
       self.vertaxis(ndy,yaxis=True)
-      if not fixedlt: umst = self.loct
+      if "lat" in typex:
+          self.xlabel = "North latitude (degrees)"
+          self.ininterv(-90.,90.,ndx,start=self.lats,end=self.late)
+      elif typex == "lon":
+          self.xlabel = "East longitude (degrees)"
+          self.ininterv(-180.,180.,ndx,start=self.lons,end=self.lone)
+      if not self.fixedlt: umst = self.loct
       for i in range(ndx):
        for j in range(ndy):
-         self.lon = self.xcoord[i] ; self.xz = self.ycoord[j] 
-         if not fixedlt: self.loct = (umst + self.lon/15.) % 24
+         if typex == "lat":   self.lat = self.xcoord[i]
+         elif typex == "lon": self.lon = self.xcoord[i]
+         self.xz = self.ycoord[j]
+         if not self.fixedlt: self.loct = (umst + self.lon/15.) % 24
          self.update() ; self.put2d(i,j)
-      if not fixedlt: self.loct = umst
-      self.lon = save1 ; self.xz = save2 ; self.loct = save3
-
-    def latalt(self,ndx=19,ndy=20,fixedlt=False):
-    ### retrieve a latitude/altitude slice
-      save1 = self.lat ; save2 = self.xz ; save3 = self.loct
+      if not self.fixedlt: self.loct = umst
+      self.lon = save1 ; self.xz = save2 ; self.loct = save3 ; self.lat = save4
+
+    def zonalmean(self,ndx=37,ndy=20,ndmean=32):
+    ### retrieve a zonalmean lat/altitude slice
+      self.fixedlt = False
+      save1 = self.lon ; save2 = self.xz ; save3 = self.loct ; save4 = self.lat
+      self.prepare(ndx=ndx,ndy=ndy)
       self.vertlabel() ; self.ylabel = self.xlabel
+      self.vertaxis(ndy,yaxis=True)
       self.xlabel = "North latitude (degrees)"
-      self.prepare(ndx=ndx,ndy=ndy)
+      self.ininterv(-180.,180.,ndmean)
+      coordmean = self.xcoord
       self.ininterv(-90.,90.,ndx,start=self.lats,end=self.late)
-      self.vertaxis(ndy,yaxis=True)
-      if not fixedlt: umst = self.loct
+      umst = self.loct #fixedlt false for this case
+      for i in range(ndx):
+       self.lat = self.xcoord[i]
+       for j in range(ndy):
+        self.xz = self.ycoord[j]
+        meanpres = 0. ; meandens = 0. ; meantemp = 0. ; meanzonwind = 0. ; meanmerwind = 0. ; meanmeanvar = np.zeros(5) ; meanextvar = np.zeros(100)        
+        for m in range(ndmean):
+           self.lon = coordmean[m]
+           self.loct = (umst + self.lon/15.) % 24 #fixedlt false for this case
+           self.update() 
+           meanpres = meanpres + self.pres/float(ndmean) ; meandens = meandens + self.dens/float(ndmean) ; meantemp = meantemp + self.temp/float(ndmean)
+           meanzonwind = meanzonwind + self.zonwind/float(ndmean) ; meanmerwind = meanmerwind + self.merwind/float(ndmean)
+           meanmeanvar = meanmeanvar + self.meanvar/float(ndmean) ; meanextvar = meanextvar + self.extvar/float(ndmean)
+        self.pres=meanpres ; self.dens=meandens ; self.temp=meantemp ; self.zonwind=meanzonwind ; self.merwind=meanmerwind
+        self.meanvar=meanmeanvar ; self.extvar=meanextvar
+        self.put2d(i,j)
+      self.loct = umst #fixedlt false for this case
+      self.lon = save1 ; self.xz = save2 ; self.loct = save3 ; self.lat = save4
+
+    def hovmoller(self,ndtime=25,ndcoord=20,typex="lat"):
+    ### retrieve a time/other coordinate slice
+      save1 = self.lat ; save2 = self.xz ; save3 = self.loct ; save4 = self.lon
+      if typex == "lat": 
+          ndx = ndcoord ; self.xlabel = "North latitude (degrees)" 
+          ndy = ndtime ; self.ylabel = "Local time (Martian hour)"
+          self.prepare(ndx=ndx,ndy=ndy)
+          self.ininterv(-90.,90.,ndx,start=self.lats,end=self.late)
+          self.ininterv(0.,24.,ndy,start=self.locts,end=self.locte,yaxis=True)
+      elif typex == "lon":
+          ndx = ndcoord ; self.xlabel = "East longitude (degrees)"
+          ndy = ndtime ; self.ylabel = "Local time (Martian hour)"
+          self.prepare(ndx=ndx,ndy=ndy)
+          self.ininterv(-180.,180.,ndx,start=self.lons,end=self.lone)
+          self.ininterv(0.,24.,ndy,start=self.locts,end=self.locte,yaxis=True)
+      elif typex == "alt":
+          ndy = ndcoord ; self.vertlabel() ; self.ylabel = self.xlabel
+          ndx = ndtime ; self.xlabel = "Local time (Martian hour)"
+          self.prepare(ndx=ndx,ndy=ndy)
+          self.vertaxis(ndy,yaxis=True)
+          self.ininterv(0.,24.,ndx,start=self.locts,end=self.locte)
       for i in range(ndx):
        for j in range(ndy):
-         self.lat = self.xcoord[i] ; self.xz = self.ycoord[j] 
-         if not fixedlt: self.loct = (umst + self.lon/15.) % 24
+         if typex == "lat":   self.lat = self.xcoord[i] ; self.loct = self.ycoord[j]
+         elif typex == "lon": self.lon = self.xcoord[i] ; self.loct = self.ycoord[j]
+         elif typex == "alt": self.xz = self.ycoord[j] ; self.loct = self.xcoord[i]
          self.update() ; self.put2d(i,j)
-      if not fixedlt: self.loct = umst
-      self.lat = save1 ; self.xz = save2 ; self.loct = save3
+      self.lat = save1 ; self.xz = save2 ; self.loct = save3 ; self.lon = save4
 
     def put2d(self,i,j):
@@ -560,7 +627,7 @@
       self.extvartab[i,j,1:100] = self.extvar[0:99] ## note: var numbering according to MCD manual is kept
 
-    def makemap2d(self,choice,incwind=False,fixedlt=False,proj="cyl"):
+    def makemap2d(self,choice,incwind=False,proj="cyl"):
     ### one 2D map is created for the user-defined variable in choice.
-      self.latlon(fixedlt=fixedlt) ## a map is implicitely a lat-lon plot. otherwise it is a plot (cf. makeplot2d)
+      self.latlon() ## a map is implicitely a lat-lon plot. otherwise it is a plot (cf. makeplot2d)
       if choice == "wind" or incwind:
           (windx, fieldlabwx) = self.definefield("u")
@@ -575,5 +642,5 @@
       mpl.figtext(0.5, 0.0, self.ack, ha='center')
 
-    def map2d(self,tabtodo,incwind=False,fixedlt=False,proj="cyl"):
+    def map2d(self,tabtodo,incwind=False,proj="cyl"):
     ### complete 2D figure with possible multiplots
       if isinstance(tabtodo,np.str): tabtodo=[tabtodo] ## so that asking one element without [] is possible.
@@ -581,7 +648,7 @@
       fig = mpl.figure()
       subv,subh = myplot.definesubplot( len(tabtodo) , fig ) 
-      for i in range(len(tabtodo)): mpl.subplot(subv,subh,i+1) ; self.makemap2d(tabtodo[i],incwind=incwind,fixedlt=fixedlt,proj=proj)
-
-    def htmlmap2d(self,tabtodo,incwind=False,fixedlt=False,figname="temp.png",title="",back="zMOL"):
+      for i in range(len(tabtodo)): mpl.subplot(subv,subh,i+1) ; self.makemap2d(tabtodo[i],incwind=incwind,proj=proj)
+
+    def htmlmap2d(self,tabtodo,incwind=False,figname="temp.png",back="zMOL"):
     ### complete 2D figure with possible multiplots
     ### added in 09/2012 for online MCD
@@ -591,8 +658,7 @@
       from matplotlib.cm import get_cmap
       from matplotlib import rcParams 
-
-      #from mpl_toolkits.basemap import Basemap
-
+      #from mpl_toolkits.basemap import Basemap # does not work
       from Scientific.IO import NetCDF
+
       filename = "/home/marshttp/surface.nc"
       zefile = NetCDF.NetCDFFile(filename, 'r') 
@@ -600,5 +666,4 @@
       yc = zefile.variables['latitude']
       xc = zefile.variables['longitude']
-      ## plutot que fieldc = self.getextvar(self.convertlab("topo"))
 
       if isinstance(tabtodo,np.str): tabtodo=[tabtodo] ## so that asking one element without [] is possible.
@@ -616,11 +681,11 @@
         yeah = fig.add_subplot(subv,subh,i+1)
         choice = tabtodo[i]
-        self.latlon(fixedlt=fixedlt,ndx=64,ndy=48) 
+        self.latlon(ndx=64,ndy=48) 
         ## a map is implicitely a lat-lon plot. otherwise it is a plot (cf. makeplot2d)
         (field, fieldlab) = self.definefield(choice)
         if incwind: (windx, fieldlabwx) = self.definefield("u") ; (windy, fieldlabwy) = self.definefield("v")
 
-        proj="moll" ; colorb="jet" ; ndiv=20 ; zeback="molabw" ; trans=1.0 #0.6
-        title="" ; vecx=None ; vecy=None ; stride=2
+        proj="moll" ; colorb= self.colorm ; ndiv=20 ; zeback="molabw" ; trans=1.0 #0.6
+        vecx=None ; vecy=None ; stride=2
         lon = self.xcoord
         lat = self.ycoord
@@ -671,5 +736,5 @@
       canvas.print_figure(figname, dpi=80)
 
-    def htmlplot2d(self,tabtodo,fixedlt=False,figname="temp.png",title=""):
+    def htmlplot2d(self,tabtodo,figname="temp.png"):
     ### complete 2D figure with possible multiplots
     ### added in 10/2012 for online MCD
@@ -693,10 +758,18 @@
         choice = tabtodo[i]
 
-        if self.lons is not None:    self.lonalt(fixedlt=fixedlt,ndx=64,ndy=35)
-        elif self.lats is not None:  self.latalt(fixedlt=fixedlt,ndx=48,ndy=35)
+        if self.lons is not None:    
+           if self.locts is None:  self.secalt(ndx=64,ndy=35,typex="lon")
+           else:                   self.hovmoller(ndcoord=64,typex="lon")
+        elif self.lats is not None:  
+           if self.locts is None:  
+               if self.zonmean:   self.zonalmean()
+               else:         self.secalt(ndx=48,ndy=35,typex="lat")
+           else:                   self.hovmoller(ndcoord=48,typex="lat")
+        else:
+           self.hovmoller(ndcoord=35,typex="alt")
 
         (field, fieldlab) = self.definefield(choice)
 
-        colorb="jet" ; ndiv=20 ; title=""
+        colorb=self.colorm ; ndiv=20 
 
         ## define field. bound field.
@@ -714,12 +787,16 @@
         ax = fig.gca() ; ax.set_ylabel(self.ylabel) ; ax.set_xlabel(self.xlabel)
 
-        if self.zkey == 4: 
+        if self.lons is not None:   ax.set_xticks(np.arange(-360,361,45)) ; ax.set_xbound(lower=self.lons, upper=self.lone)
+        elif self.lats is not None: ax.set_xticks(np.arange(-90,91,30)) ; ax.set_xbound(lower=self.lats, upper=self.late)
+
+        if self.locts is not None: 
+            if self.xzs is not None: ax.set_xticks(np.arange(0,26,2)) ; ax.set_xbound(lower=self.locts, upper=self.locte)
+            else:                    ax.set_yticks(np.arange(0,26,2)) ; ax.set_ybound(lower=self.locts, upper=self.locte)
+
+        if self.zkey == 4 and self.xzs is not None: 
             ax.set_yscale('log') ; ax.set_ylim(ax.get_ylim()[::-1])
         else:
             #ax.set_yticks(np.arange(self.xzs,self.xze,10000.)) ; 
             ax.set_ybound(lower=self.xzs, upper=self.xze)
-
-        if self.lons is not None: ax.set_xticks(np.arange(-360,361,45)) ; ax.set_xbound(lower=self.lons, upper=self.lone)
-        elif self.lats is not None: ax.set_xticks(np.arange(-90,91,30)) ; ax.set_xbound(lower=self.lats, upper=self.late)
 
       self.gettitle()
Index: trunk/UTIL/PYTHON/mcd/proto/cgi-bin/mcdcgi.py
===================================================================
--- trunk/UTIL/PYTHON/mcd/proto/cgi-bin/mcdcgi.py	(revision 820)
+++ trunk/UTIL/PYTHON/mcd/proto/cgi-bin/mcdcgi.py	(revision 821)
@@ -17,5 +17,4 @@
 import cgi, cgitb 
 import numpy as np
-#from mcd import mcd
 from modules import *
 from modules import mcd
@@ -24,25 +23,44 @@
 import os as daos
 import matplotlib.pyplot as mpl
-from PIL import Image
-
-
 
 ### a function to read HTML arguments for coordinates
 def gethtmlcoord(userinput,defmin,defmax):
-   # accepted separators
-   separators = [":",";",",","/"] 
+   import string
+   # accepted separators. the symbol - should always be last.
+   separators = [":",";",",","/","_"] 
    # initial values
    val = -9999. ; vals = None ; vale = None ; foundinterv = False
    if userinput == None:   userinput = "1"
-   # the main work. either all -- or an interval -- or a single value.
+   # the main work. either all, or an interval, or a single value.
+   # ... all
    if userinput == "all":  isfree = 1 ; vals = defmin ; vale = defmax ; foundinterv = True
+   # ... an interval
    else:
        for sep in separators:
+         if not foundinterv:
            isfree = 1 ; ind = userinput.find(sep)
            if ind != -1: vals = float(userinput[:ind]) ; vale = float(userinput[ind+1:]) ; foundinterv = True
-   if not foundinterv: isfree = 0 ; val = float(userinput)
+   # ... a single value (or an error)
+   if not foundinterv: 
+       # treat the difficult case of possible - separator
+       test = userinput[1:].find("-") # at this stage:
+                                      # * if - is found in the first position, it could not be a separator 
+                                      # * if - found at positions > 0, it must be considered as a separator
+       if test != -1: 
+         isfree = 1 ; ind=test+1 
+         vals = float(userinput[:ind]) ; vale = float(userinput[ind+1:]) ; foundinterv = True
+       else:
+         # check if input is valid (each character is numeric or -)
+         for char in userinput: 
+            if char not in string.digits: 
+               if char not in ["-","."]: userinput="yorgl"
+         # either we are OK. if we are not we set isfree to -1.
+         if userinput != "yorgl":  isfree = 0 ; val = float(userinput)
+         else:                     isfree = -1
    # return values
    return isfree, val, vals, vale
 
+# set an errormess variable which must stay to None for interface to proceed
+errormess = ""
 
 # for debugging in web browser
@@ -53,14 +71,13 @@
 
 # create a MCD object
-#query = mcd()
-query=mcd.mcd() #FG: import from module mcd
+query=mcd.mcd() 
 
 # Get the kind of vertical coordinates and choose default behavior for "all"
 try: query.zkey = int(form.getvalue("zkey"))
 except: query.zkey = int(3)
-if query.zkey == 2:    minxz = -5000.   ; maxxz = 100000.
-elif query.zkey == 3:  minxz = 0.       ; maxxz = 120000.
-elif query.zkey == 5:  minxz = -5000.   ; maxxz = 100000.
-elif query.zkey == 4:  minxz = 1000.    ; maxxz = 0.001
+if query.zkey == 2:    minxz = -5000.   ; maxxz = 150000.
+elif query.zkey == 3:  minxz = 0.       ; maxxz = 250000.
+elif query.zkey == 5:  minxz = -5000.   ; maxxz = 150000.
+elif query.zkey == 4:  minxz = 1.e3     ; maxxz = 1.e-6
 elif query.zkey == 1:  minxz = 3396000. ; maxxz = 3596000.
 
@@ -70,7 +87,4 @@
 isloctfree, query.loct, query.locts, query.locte = gethtmlcoord( form.getvalue("localtime"),    0.,  24. )
 isaltfree,  query.xz,   query.xzs,   query.xze   = gethtmlcoord( form.getvalue("altitude"),  minxz, maxxz)
-
-sumfree = islatfree + islonfree + isloctfree + isaltfree 
-if sumfree > 2: exit() ## only 1D or 2D plots for the moment
 
 try: query.datekey = int(form.getvalue("datekeyhtml"))
@@ -84,4 +98,49 @@
     query.loct = 0.
 
+# Prevent the user from doing bad
+badinterv = (islatfree == -1) or (islonfree == -1) or (isloctfree == -1) or (isaltfree == -1)
+if badinterv: 
+    errormess = errormess+"<li>Bad syntax. Write a value (or) a range val1;val2 (or) 'all'. Separator shall be either ; : , / _ "
+badls = (query.datekey == 1 and (query.xdate < 0. or query.xdate > 360.))
+if badls: 
+    errormess = errormess+"<li>Solar longitude must be between 0 and 360."
+badloct = (isloctfree == 0 and query.loct > 24.) \
+       or (isloctfree == 1 and (query.locts > 24. or query.locte > 24.)) \
+       or (isloctfree == 0 and query.loct < 0.) \
+       or (isloctfree == 1 and (query.locts < 0. or query.locte < 0.))
+if badloct: 
+    errormess = errormess+"<li>Local time must be less than 24 martian hours (and not a negative number)."
+badlat = (islatfree == 0 and abs(query.lat) > 90.) \
+      or (islatfree == 1 and (abs(query.lats) > 90. or abs(query.late) > 90.))
+if badlat: 
+    errormess = errormess+"<li>Latitude coordinates must be between -90 and 90."
+badlon = (islonfree == 0 and abs(query.lon) > 360.) \
+      or (islonfree == 1 and (abs(query.lons) > 360. or abs(query.lone) > 360.))
+if badlon: 
+    errormess = errormess+"<li>Longitude coordinates must be between -360 and 360."
+badalt = (isaltfree == 0 and (query.zkey in [3]) and query.xz < 0.) \
+      or (isaltfree == 1 and (query.zkey in [3]) and (query.xzs < 0. or query.xze < 0.))
+if badalt: 
+    errormess = errormess+"<li>Vertical coordinates must be positive when requesting altitude above surface."
+badalt2 = (isaltfree == 0 and (query.zkey in [1,4]) and query.xz <= 0.) \
+      or (isaltfree == 1 and (query.zkey in [1,4]) and (query.xzs <= 0. or query.xze <= 0.))
+if badalt2: 
+    errormess = errormess+"<li>Vertical coordinates must be <b>strictly</b> positive when requesting pressure levels or altitude above Mars center."
+badalt3 = (isaltfree == 0 and query.zkey == 4 and query.xz > 1500.) \
+       or (isaltfree == 1 and query.zkey == 4 and min(query.xzs,query.xze) > 1500.)
+if badalt3: 
+    errormess = errormess+"<li>Pressure values larger than 1500 Pa are unlikely to be encountered in the Martian atmosphere."
+badrange = (isloctfree == 1 and query.locts == query.locte) \
+        or (islatfree == 1 and query.lats == query.late) \
+        or (islonfree == 1 and query.lons == query.lone) \
+        or (isaltfree == 1 and query.xzs == query.xze)
+if badrange: 
+    errormess = errormess+"<li>One or several coordinate intervals are not... intervals. Set either a real range or an unique value."
+
+# Get how many free dimensions we have
+sumfree = islatfree + islonfree + isloctfree + isaltfree 
+if sumfree >= 3: errormess = errormess + "<li>3 or more free dimensions are set... but only 1D and 2D plots are supported!"
+
+# Get additional parameters
 try: query.hrkey = int(form.getvalue("hrkey"))
 except: query.hrkey = int(1)
@@ -91,4 +150,6 @@
 #        self.seedin    = 1  #random number generator seed (unused if perturkey=0)
 #        self.gwlength  = 0. #gravity Wave wavelength (unused if perturkey=0)
+try: query.colorm = form.getvalue("colorm")
+except: query.colorm = "jet"
 
 # Get variables to plot
@@ -98,9 +159,6 @@
 var4 = form.getvalue("var4")
 
-# fg: vartoplot is not None without form values
-# vartoplot = [var1]
 # fg: init var as with form values
 if var1 == None: var1="t"
-#if var2 == None: var2="p"
 
 vartoplot = []
@@ -114,15 +172,21 @@
 else:              iswindlog = False
 isfixedlt = form.getvalue("isfixedlt")
-if isfixedlt == "on": input_fixedlt=True
-else:                 input_fixedlt=False  
-
-# reference name (to test which figures are already in the database)
-reference = query.getnameset()+str(var1)+str(var2)+str(var3)+str(var4)+str(iswind)+str(isfixedlt)
-figname = '../img/'+reference+'.png'
-txtname = '../txt/'+reference
-testexist = daos.path.isfile(figname)
-
-# extract data from MCD if needed
-if not testexist:
+if isfixedlt == "on": query.fixedlt=True
+else:                 query.fixedlt=False  
+iszonmean = form.getvalue("zonmean")
+if iszonmean  == "on": query.zonmean=True
+else:                  query.zonmean=False
+
+### now, proceed...
+if errormess == "":
+
+ # reference name (to test which figures are already in the database)
+ reference = query.getnameset()+str(var1)+str(var2)+str(var3)+str(var4)+str(iswind)+str(isfixedlt)+str(iszonmean)+query.colorm
+ figname = '../img/'+reference+'.png'
+ txtname = '../txt/'+reference+'.txt'
+ testexist = daos.path.isfile(figname)
+
+ # extract data from MCD if needed
+ if not testexist:
 
   ### 1D plots
@@ -130,5 +194,5 @@
 
     ### getting data
-    if isloctfree == 1:  	query.diurnal(nd=24) 
+    if isloctfree == 1:  	query.diurnal(nd=25) 
     elif islonfree == 1: 	query.zonal(nd=64)
     elif islatfree == 1: 	query.meridional(nd=48)
@@ -139,6 +203,4 @@
     query.getascii(vartoplot,filename=txtname)
     query.htmlplot1d(vartoplot,figname=figname)
-    #mpl.savefig("img/temp.png",dpi=85,bbox_inches='tight',pad_inches=0.25)
-    #Image.open("../img/temp.png").save(figname,'JPEG')
 
   ### 2D plots
@@ -146,15 +208,8 @@
 
     ### getting data
-    if islatfree == 1 and islonfree == 1:  	
-        query.htmlmap2d(vartoplot,incwind=iswindlog,fixedlt=input_fixedlt,figname=figname) 
-        #mpl.savefig("img/temp.png",dpi=110,bbox_inches='tight',pad_inches=0.4)
-        #Image.open("img/temp.png").save(figname,'JPEG') ##lighter images   
-        ### http://www.pythonware.com/library/pil/handbook/introduction.htm
-    elif isaltfree == 1 and islonfree == 1:  	
-        query.htmlplot2d(vartoplot,fixedlt=input_fixedlt,figname=figname)
-    elif isaltfree == 1 and islatfree == 1:  	
-        query.htmlplot2d(vartoplot,fixedlt=input_fixedlt,figname=figname)
-    else:
-        exit()  
+    if islatfree == 1 and islonfree == 1:     query.htmlmap2d(vartoplot,incwind=iswindlog,figname=figname) 
+    else:                                     query.htmlplot2d(vartoplot,figname=figname)
+
+#### NOW WRITE THE HTML PAGE TO USER
 
 ## This is quite common
@@ -172,52 +227,20 @@
 #print "<br />"
 
-
-#print "<a href='../index.html'>Click here to start a new query</a><br />"
-#print "<hr>"
-
 ## Now the part which differs
-if sumfree == 0: 	query.update() ; query.htmlprinttabextvar(vartoplot)  #query.printmeanvar()
-elif sumfree == 2: 	print "<img src='"+figname+"'><br />"
-elif sumfree == 1:      
-    print "<a href='"+txtname+"'>Click here to download an ASCII file containing data</a><br />"
-    print "<hr>"
-    print "<img src='"+figname+"'><br />"
-else:			print "<h1>ERROR : sumfree is not or badly defined ...</h1></body></html>"
-
+if errormess != "":
+                       print "<h1>Ooops!</h1>"
+                       print "Please correct the following problems before submitting again."
+                       print "<ul>"
+                       print errormess
+                       print "</ul>"
+else:
+  if sumfree == 0: 	query.update() ; query.htmlprinttabextvar(vartoplot)
+  elif sumfree == 2: 	print "<img src='"+figname+"'><br />"
+  elif sumfree == 1:      
+                        print "<a href='"+txtname+"'>Click here to download an ASCII file containing data</a><br />"
+                        print "<hr>"
+                        print "<img src='"+figname+"'><br />"
 
 ## This is quite common
-bottom = "<hr><a href='../index.html'>Click here to start a new query</a>.<hr></body></html>"
-#print bottom
-
-##write to file object
-#f = cStringIO.StringIO()
-#mpl.savefig(f)
-#f.seek(0)
-
-##output to browser
-#print "Content-type: image/png\n"
-#print f.read()
-#exit()
-
-#print "Content-type:text/html\r\n\r\n"
-#print "<html>"
-#print "<head>"
-#print "<title>MCD. Simple Python interface</title>"
-#print "</head>"
-#print "<body>"
-
-
-
-
-
-
-## HTTP Header
-#print "Content-Type:application/octet-stream; name=\"FileName\"\r\n";
-#print "Content-Disposition: attachment; filename=\"FileName\"\r\n\n";
-## Actual File Content will go hear.
-#fo = open("foo.txt", "rb")
-#str = fo.read();
-#print str
-## Close opend file
-#fo.close()
-
+bottom = "</body></html>"
+print bottom
Index: trunk/UTIL/PYTHON/mcd/proto/index.html
===================================================================
--- trunk/UTIL/PYTHON/mcd/proto/index.html	(revision 820)
+++ trunk/UTIL/PYTHON/mcd/proto/index.html	(revision 821)
@@ -1,5 +1,3 @@
-
 <!-- Author Aymeric Spiga LMD -->
-
 <!DOCTYPE html>
 <html>
@@ -13,12 +11,9 @@
 <body onload="DefaultDateValues();DefaultTimeValues();Convert2Ls();PlaceValues(0.,0.);DefaultSpaceTime()">
 
+<form name="calendar" action="./cgi-bin/mcdcgi.py" method="post" target="_blank"> 
 <!-- aussi possible: get a la place de post. pour avoir un beau lien -->
-
-<!--<form name="calendar" action="/marscgi-bin/mcdcgi.py" method="post"-->
-<form name="calendar" action="./cgi-bin/mcdcgi.py" method="post" target="_blank"> <!--target="_new">-->
 
 <center>
 <b style="font-size: 125%;">Mars Climate Database: The Web Interface</b><br>
-<!--Welcome! To reset your query, click on the Mars panorama.-->
 <a href="index.html"><img src="PIA03610_red.jpg" height=80 width=1200></a><br>
 </center>
@@ -54,5 +49,6 @@
 <b><font color="red">MARS date</font></b> 
 Solar longitude <input type="text" size="3" name="ls"> degrees<br />
-Local Time <input type="text" size="4" name="localtime" value="0."> Martian hour<br />
+Local Time <input type="text" size="3" name="localtime" value="0."> Martian hour<br />
+<span style="font-size: 80%;">write a value (or) a range val1;val2 (or) 'all'</span><br />
 <br />
 <input type="radio" name="datekeyhtml" value="0">
@@ -64,5 +60,5 @@
 </td>
 <td align="center">
-Option for 2D maps: local time value is<br />
+If longitude is a free dimension, local time value is<br />
 <input type="radio" name="isfixedlt" value="off" checked /> at longitude 0
 <input type="radio" name="isfixedlt" value="on"          /> fixed for the whole planet<br />
@@ -83,5 +79,4 @@
 <input type="radio" name="tata" value="Evening" onClick="PlaceValues2(21.)">Evening
 <input type="radio" name="tata" value="Night" onClick="PlaceValues2(3.)">Night<br />
-<!--<input type="radio" name="tata" value="Whole day!" onClick="PlaceValues2('all')"><i>Whole day!</i><br />-->
 <hr>
 <b>3) ALTITUDE</b>
@@ -89,24 +84,11 @@
 <input type="radio" name="toto" value="Boundary layer" onClick="PlaceValues3(1000.)">Boundary layer
 <input type="radio" name="toto" value="Troposphere" onClick="PlaceValues3(10000.)">Troposphere<br/>
-<input type="radio" name="toto" value="Mesophere" onClick="PlaceValues3(80000.)">Mesosphere<br />
-<!--<input type="radio" name="toto" value="Whole profile!" onClick="PlaceValues3('all')"><i>Whole profile!</i><br />-->
+<input type="radio" name="toto" value="Mesophere" onClick="PlaceValues3(80000.)">Mesosphere
+<input type="radio" name="toto" value="Thermosphere" onClick="PlaceValues3(180000.)">Thermosphere<br />
 <hr>
-<!--
-<b>4) COORDINATES</b> Automatic! <br />
-<input type="button" value="... or click here for global map!" onClick="PlaceValues('all','all')"><br />
--->
-<!--
-<b>4)</b>
-<input type="button" value="Click here for a global map!" onClick="PlaceValues('all','all')"><br />
--->
-<!--
-<input type="radio" name="titi" value="Global map" onClick="PlaceValues('all','all')">Global map<br />
-<input type="radio" name="toto" value="Vertical profile" onClick="PlaceValues3('all')">Vertical profile
-<input type="radio" name="tata" value="Diurnal cycle" onClick="PlaceValues2('all')">Diurnal cycle<br />
--->
 </td>
 <td align="center">
 <b>CUSTOMIZE COORDINATES ON MARS</b><br />
-write a value (or) a range val1;val2 (or) 'all'<br />
+<span style="font-size: 80%;">write a value (or) a range val1;val2 (or) 'all'</span><br />
 <ul>
 <li>Latitude <input type="text" size="7" name="latitude" value="0."> degree North
@@ -121,28 +103,9 @@
 -->
 </select>
-<!--
-<li>Latitude   
-<input type="radio" name="islatfree" value="0" checked> Value: <input type="text" size="2" name="latitude" value="0.">
-<input type="radio" name="islatfree" value="1"> All [-90 ; 90]
-</li>
-<li>Longitude 
-<input type="radio" name="islonfree" value="0" checked> Value: <input type="text" size="2" name="longitude" value="0.">
-<input type="radio" name="islonfree" value="1"> All [-180 ; 180]
-</li>
-<li>Local Time  
-<input type="radio" name="isloctfree" value="0" checked> Value: <input type="text" size="2" name="localtime" value="0.">
-<input type="radio" name="isloctfree" value="1"> All [0 ; 24]
-</li>
-<li>Altitude   
-<input type="radio" name="isaltfree" value="0" checked> Value: <input type="text" size="2" name="altitude" value="10.">
-<input type="radio" name="isaltfree" value="1"> All [0 ; 100000] m
-</li>
--->
 </ul>
 </td>
 <td align="center">
-<!--[Advanced settings for well-informed Martians]<br />-->
 <ul>
-<li>High resolution topography? <input type="radio" name="hrkey" value="1" checked /> Yes <input type="radio" name="hrkey" value="0" /> No </li>
+<li>High resolution mode? <input type="radio" name="hrkey" value="1" checked /> Yes <input type="radio" name="hrkey" value="0" /> No </li>
 <li>Dust scenario? <select name="dust">
 <option value="1"         >MY24 min solar</option>
@@ -155,14 +118,4 @@
 <option value="8"         >cold scenario (low dust, min solar)</option>
 </select></li>
-<!--<li>Presets
-<input type="button" value="Now!" onClick="DefaultDateValues();DefaultTimeValues();Convert2Ls();">
-<input type="button" value="Curiosity" onClick="DateAndTimeValues(2012,8,6,05,30,00);Convert2Ls();PlaceValues(137.4,-4.6)">
-<input type="button" value="Phoenix" onClick="DateAndTimeValues(2008,5,25,23,38,23);Convert2Ls();PlaceValues(234.25,68.22)">
-<input type="button" value="Opportunity" onClick="DateAndTimeValues(2004,1,25,4,55,0);Convert2Ls();PlaceValues(354.47,-1.95)">
-<input type="button" value="Spirit" onClick="DateAndTimeValues(2004,1,4,4,26,0);Convert2Ls();PlaceValues(175.48,-14.57)">
-<input type="button" value="Pathfinder" onClick="DateAndTimeValues(1997,7,4,16,56,55);Convert2Ls();PlaceValues(-33.22,19.13)">
-<input type="button" value="Viking Lander 2" onClick="DateAndTimeValues(1976,9,3,22,58,20);Convert2Ls();PlaceValues(-225.74,47.97)">
-<input type="button" value="Viking Lander 1" onClick="DateAndTimeValues(1976,7,20,11,53,6);Convert2Ls();PlaceValues(-49.97,22.48)">
-</li>-->
 </ul>
 </td>
@@ -171,14 +124,13 @@
 <td align="center">
 <b>4) INTEREST</b>
-<input type="radio" name="yeah" value="Atmosphere" onClick="PlaceVar('t','p','none','none')" checked>Atmosphere<br />
-<input type="radio" name="yeah" value="Winds" onClick="PlaceVar('u','v','none','none')">Winds
-<input type="radio" name="yeah" value="Weather" onClick="PlaceVar('ps_ddv','t','none','none')">Weather<br />
-<input type="radio" name="yeah" value="Water clouds" onClick="PlaceVar('h2ovap','mtot','h2oice','icetot')">Water clouds
-<input type="radio" name="yeah" value="Chemistry" onClick="PlaceVar('o3','h2ovap','o','co')">Chemistry<br />
-<input type="radio" name="yeah" value="Landing engineering" onClick="PlaceVar('rho','rho_ddv','cp','visc')">Landing engineering<br />
-<input type="radio" name="yeah" value="Glaciology" onClick="PlaceVar('tsurfmn','tsurfmx','co2ice','icetot')">Glaciology
-<input type="radio" name="yeah" value="Surface meteorology" onClick="PlaceVar('ps','tsurf','none','none')">Surface meteorology<br />
-<input type="radio" name="yeah" value="Radiative balance" onClick="PlaceVar('lwdown','swdown','lwup','swup')">Radiative balance<br />
-<!--<input type="button" value="Surface data" onClick="PlaceVar('ps','tsurf','none','none')">-->
+<input type="radio" name="yeah" value="Atmosphere" onClick="PlaceVar('t','p','none','none');ChooseColor('jet')" checked>Atmosphere<br />
+<input type="radio" name="yeah" value="Winds" onClick="PlaceVar('u','v','none','none');ChooseColor('RdBu_r')">Winds
+<input type="radio" name="yeah" value="Weather" onClick="PlaceVar('ps_ddv','rho_ddv','none','none');ChooseColor('RdBu_r')">Weather<br />
+<input type="radio" name="yeah" value="Water cycle" onClick="PlaceVar('h2ovap','mtot','h2oice','icetot');ChooseColor('Blues')">Water cycle
+<input type="radio" name="yeah" value="Chemistry" onClick="PlaceVar('o3','h2ovap','none','none');ChooseColor('jet')">Chemistry<br />
+<input type="radio" name="yeah" value="Landing engineering" onClick="PlaceVar('rho','visc','none','none');ChooseColor('YlOrRd')">Landing engineering<br />
+<input type="radio" name="yeah" value="Glaciology" onClick="PlaceVar('tsurfmn','tsurfmx','co2ice','icetot');ChooseColor('spectral')">Glaciology
+<input type="radio" name="yeah" value="Surface meteorology" onClick="PlaceVar('ps','tsurf','none','none');ChooseColor('jet')">Surface meteorology<br />
+<input type="radio" name="yeah" value="Radiative balance" onClick="PlaceVar('lwdown','swdown','lwup','swup');ChooseColor('hot')">Radiative balance<br />
 </td>
 <td align="center">
@@ -301,27 +253,23 @@
 </td>
 <td align="center">
-<!--[Additional settings]<br />-->
 <ul>
 <li> Add wind vectors
 <input type="radio" name="iswind" value="off" checked /> No
 <input type="radio" name="iswind" value="on"          /> Yes</li>  
-<!--
-<li> Set same LT on whole planet
-<input type="radio" name="isfixedlt" value="off" checked /> No
-<input type="radio" name="isfixedlt" value="on"          /> Yes</li>
--->
-<!--
-<li> Add another variable 
-<input type="radio" name="superimposed" value="0" checked /> side-by-side
-<input type="radio" name="superimposed" value="1"         /> superimposed</li> 
--->
-<!--
-<li>
-Presets
-<input type="button" value="Usual meteorology" onClick="PlaceVar('p','t','u','v')">
-<input type="button" value="Surface data" onClick="PlaceVar('ps','tsurf','none','none')">
-<input type="button" value="Water cycle" onClick="PlaceVar('mtot','icetot','none','none')">
-</select>
--->
+</li>
+<li> Set colormap
+<select name="colorm">
+<option value="jet"       selected>blue green yellow red</option>
+<option value="Greys"             >grey</option>
+<option value="Blues"             >blue</option>
+<option value="YlOrRd"            >yellow orange red</option>
+<option value="spectral"          >rainbow</option>
+<option value="hot"               >black red yellow</option>
+<option value="RdBu_r"            >blue white red</option>
+</select>
+</li>
+<li> Ask for zonal mean in lat/alt plot<br />
+<input type="radio" name="zonmean" value="off" checked /> No
+<input type="radio" name="zonmean" value="on"          /> Yes (please be patient)
 </li>
 </ul>
@@ -336,27 +284,17 @@
 </td>
 <td align="center">
-<input type="submit" value="SUBMIT" style="font-weight:bold"/>
-<!--<input type="button" value="RESET" style="font-weight:bold" onClick="DefaultDateValues();DefaultTimeValues();Convert2Ls();PlaceValues(0.,0.);DefaultSpaceTime()"/><br />-->
+<input type="button" value="SUBMIT" style="font-weight:bold" onClick="submit_form()"/>
 <input type="button" value="RESET" style="font-weight:bold" onClick="window.open('index.html','_self')"/><br />
 </td>
 <td align="center">
 <a href="http://www-mars.lmd.jussieu.fr">Mars Climate Database</a> (c) LMD/OU/IAA/ESA/CNES.<br />
-Python-based interface by <a href="http://www.lmd.jussieu.fr/~aslmd/">Aymeric Spiga</a> (LMD).<br />
-</td>
-</tr>
-
-
+Interface written by <a href="http://www.lmd.jussieu.fr/~aslmd/">A. Spiga</a> (LMD) using <a href="http://www.python.org">Python</a>.<br />
+</td>
+</tr>
 </table>
-
-
-
 </body>
 </html>
 
 <!--
-<form action="/cgi-bin/checkbox.cgi" method="POST" target="_blank">
 <input type="checkbox" name="maths" value="on" /> Maths
-<input type="checkbox" name="physics" value="on" /> Physics
-<input type="submit" value="Select Subject" />
-</form>
 -->
Index: trunk/UTIL/PYTHON/mcd/proto/martian_time.js
===================================================================
--- trunk/UTIL/PYTHON/mcd/proto/martian_time.js	(revision 820)
+++ trunk/UTIL/PYTHON/mcd/proto/martian_time.js	(revision 821)
@@ -450,7 +450,11 @@
 }
 
+function ChooseColor(colorm){
+var colorm;
+document.calendar.colorm.value=colorm;
+}
 
 function submit_form_beginner() {
-document.calendar.submit();
+submit_form()
 document.calendar.reset();
 DefaultDateValues();
@@ -461,2 +465,6 @@
 }
 
+function submit_form() {
+Convert2Julian();
+document.calendar.submit();
+}
