[807] | 1 | #!/usr/bin/python |
---|
[796] | 2 | ###!/usr/bin/env python |
---|
[793] | 3 | ###!/home/aymeric/Software/epd-7.0-2-rh5-x86/bin/python |
---|
| 4 | ####!/home/marshttp/EPD/epd-7.0-2-rh5-x86_64/bin/python |
---|
[639] | 5 | ### here the version used to f2py the MCD Fortran routines |
---|
| 6 | |
---|
| 7 | ################################################## |
---|
| 8 | ### A Python CGI for the Mars Climate Database ### |
---|
[761] | 9 | ### ------------------------------------------ ### |
---|
| 10 | ### Aymeric SPIGA 18-19/04/2012 ~ 11/08/2012 ### |
---|
| 11 | ### ------------------------------------------ ### |
---|
[639] | 12 | ### (see mcdtest.py for examples of use) ### |
---|
| 13 | ################################################## |
---|
[793] | 14 | ### ajouts et corrections par Franck Guyon 09/2012 |
---|
[796] | 15 | ### ajouts suite a brainstorm equipe AS 10/2012 |
---|
[639] | 16 | |
---|
| 17 | import cgi, cgitb |
---|
| 18 | import numpy as np |
---|
[793] | 19 | from modules import * |
---|
| 20 | from modules import mcd |
---|
| 21 | |
---|
[639] | 22 | import cStringIO |
---|
| 23 | import os as daos |
---|
| 24 | import matplotlib.pyplot as mpl |
---|
| 25 | |
---|
[812] | 26 | ### a function to read HTML arguments for coordinates |
---|
| 27 | def gethtmlcoord(userinput,defmin,defmax): |
---|
[821] | 28 | import string |
---|
| 29 | # accepted separators. the symbol - should always be last. |
---|
| 30 | separators = [":",";",",","/","_"] |
---|
[812] | 31 | # initial values |
---|
| 32 | val = -9999. ; vals = None ; vale = None ; foundinterv = False |
---|
| 33 | if userinput == None: userinput = "1" |
---|
[821] | 34 | # the main work. either all, or an interval, or a single value. |
---|
| 35 | # ... all |
---|
[812] | 36 | if userinput == "all": isfree = 1 ; vals = defmin ; vale = defmax ; foundinterv = True |
---|
[821] | 37 | # ... an interval |
---|
[812] | 38 | else: |
---|
| 39 | for sep in separators: |
---|
[821] | 40 | if not foundinterv: |
---|
[812] | 41 | isfree = 1 ; ind = userinput.find(sep) |
---|
| 42 | if ind != -1: vals = float(userinput[:ind]) ; vale = float(userinput[ind+1:]) ; foundinterv = True |
---|
[821] | 43 | # ... a single value (or an error) |
---|
| 44 | if not foundinterv: |
---|
| 45 | # treat the difficult case of possible - separator |
---|
| 46 | test = userinput[1:].find("-") # at this stage: |
---|
| 47 | # * if - is found in the first position, it could not be a separator |
---|
| 48 | # * if - found at positions > 0, it must be considered as a separator |
---|
| 49 | if test != -1: |
---|
| 50 | isfree = 1 ; ind=test+1 |
---|
| 51 | vals = float(userinput[:ind]) ; vale = float(userinput[ind+1:]) ; foundinterv = True |
---|
| 52 | else: |
---|
| 53 | # check if input is valid (each character is numeric or -) |
---|
| 54 | for char in userinput: |
---|
| 55 | if char not in string.digits: |
---|
| 56 | if char not in ["-","."]: userinput="yorgl" |
---|
| 57 | # either we are OK. if we are not we set isfree to -1. |
---|
| 58 | if userinput != "yorgl": isfree = 0 ; val = float(userinput) |
---|
| 59 | else: isfree = -1 |
---|
[812] | 60 | # return values |
---|
| 61 | return isfree, val, vals, vale |
---|
| 62 | |
---|
[821] | 63 | # set an errormess variable which must stay to None for interface to proceed |
---|
| 64 | errormess = "" |
---|
[812] | 65 | |
---|
[639] | 66 | # for debugging in web browser |
---|
| 67 | cgitb.enable() |
---|
| 68 | |
---|
| 69 | # Create instance of FieldStorage |
---|
| 70 | form = cgi.FieldStorage() |
---|
| 71 | |
---|
| 72 | # create a MCD object |
---|
[821] | 73 | query=mcd.mcd() |
---|
[639] | 74 | |
---|
[812] | 75 | # Get the kind of vertical coordinates and choose default behavior for "all" |
---|
[806] | 76 | try: query.zkey = int(form.getvalue("zkey")) |
---|
| 77 | except: query.zkey = int(3) |
---|
[821] | 78 | if query.zkey == 2: minxz = -5000. ; maxxz = 150000. |
---|
| 79 | elif query.zkey == 3: minxz = 0. ; maxxz = 250000. |
---|
| 80 | elif query.zkey == 5: minxz = -5000. ; maxxz = 150000. |
---|
| 81 | elif query.zkey == 4: minxz = 1.e3 ; maxxz = 1.e-6 |
---|
[812] | 82 | elif query.zkey == 1: minxz = 3396000. ; maxxz = 3596000. |
---|
[806] | 83 | |
---|
[812] | 84 | # Get data from user-defined fields and define free dimensions |
---|
| 85 | islatfree, query.lat, query.lats, query.late = gethtmlcoord( form.getvalue("latitude"), -90., 90. ) |
---|
| 86 | islonfree, query.lon, query.lons, query.lone = gethtmlcoord( form.getvalue("longitude"), -180., 180. ) |
---|
| 87 | isloctfree, query.loct, query.locts, query.locte = gethtmlcoord( form.getvalue("localtime"), 0., 24. ) |
---|
| 88 | isaltfree, query.xz, query.xzs, query.xze = gethtmlcoord( form.getvalue("altitude"), minxz, maxxz) |
---|
[793] | 89 | |
---|
[805] | 90 | try: query.datekey = int(form.getvalue("datekeyhtml")) |
---|
| 91 | except: query.datekey = float(1) |
---|
| 92 | if query.datekey == 1: |
---|
| 93 | try: query.xdate = float(form.getvalue("ls")) |
---|
| 94 | except: query.xdate = float(1) |
---|
| 95 | else: |
---|
| 96 | try: query.xdate = float(form.getvalue("julian")) |
---|
| 97 | except: query.xdate = float(1) |
---|
| 98 | query.loct = 0. |
---|
| 99 | |
---|
[821] | 100 | # Prevent the user from doing bad |
---|
| 101 | badinterv = (islatfree == -1) or (islonfree == -1) or (isloctfree == -1) or (isaltfree == -1) |
---|
| 102 | if badinterv: |
---|
| 103 | errormess = errormess+"<li>Bad syntax. Write a value (or) a range val1;val2 (or) 'all'. Separator shall be either ; : , / _ " |
---|
| 104 | badls = (query.datekey == 1 and (query.xdate < 0. or query.xdate > 360.)) |
---|
| 105 | if badls: |
---|
| 106 | errormess = errormess+"<li>Solar longitude must be between 0 and 360." |
---|
| 107 | badloct = (isloctfree == 0 and query.loct > 24.) \ |
---|
| 108 | or (isloctfree == 1 and (query.locts > 24. or query.locte > 24.)) \ |
---|
| 109 | or (isloctfree == 0 and query.loct < 0.) \ |
---|
| 110 | or (isloctfree == 1 and (query.locts < 0. or query.locte < 0.)) |
---|
| 111 | if badloct: |
---|
| 112 | errormess = errormess+"<li>Local time must be less than 24 martian hours (and not a negative number)." |
---|
| 113 | badlat = (islatfree == 0 and abs(query.lat) > 90.) \ |
---|
| 114 | or (islatfree == 1 and (abs(query.lats) > 90. or abs(query.late) > 90.)) |
---|
| 115 | if badlat: |
---|
| 116 | errormess = errormess+"<li>Latitude coordinates must be between -90 and 90." |
---|
| 117 | badlon = (islonfree == 0 and abs(query.lon) > 360.) \ |
---|
| 118 | or (islonfree == 1 and (abs(query.lons) > 360. or abs(query.lone) > 360.)) |
---|
| 119 | if badlon: |
---|
| 120 | errormess = errormess+"<li>Longitude coordinates must be between -360 and 360." |
---|
| 121 | badalt = (isaltfree == 0 and (query.zkey in [3]) and query.xz < 0.) \ |
---|
| 122 | or (isaltfree == 1 and (query.zkey in [3]) and (query.xzs < 0. or query.xze < 0.)) |
---|
| 123 | if badalt: |
---|
| 124 | errormess = errormess+"<li>Vertical coordinates must be positive when requesting altitude above surface." |
---|
| 125 | badalt2 = (isaltfree == 0 and (query.zkey in [1,4]) and query.xz <= 0.) \ |
---|
| 126 | or (isaltfree == 1 and (query.zkey in [1,4]) and (query.xzs <= 0. or query.xze <= 0.)) |
---|
| 127 | if badalt2: |
---|
| 128 | errormess = errormess+"<li>Vertical coordinates must be <b>strictly</b> positive when requesting pressure levels or altitude above Mars center." |
---|
| 129 | badalt3 = (isaltfree == 0 and query.zkey == 4 and query.xz > 1500.) \ |
---|
| 130 | or (isaltfree == 1 and query.zkey == 4 and min(query.xzs,query.xze) > 1500.) |
---|
| 131 | if badalt3: |
---|
| 132 | errormess = errormess+"<li>Pressure values larger than 1500 Pa are unlikely to be encountered in the Martian atmosphere." |
---|
| 133 | badrange = (isloctfree == 1 and query.locts == query.locte) \ |
---|
| 134 | or (islatfree == 1 and query.lats == query.late) \ |
---|
| 135 | or (islonfree == 1 and query.lons == query.lone) \ |
---|
| 136 | or (isaltfree == 1 and query.xzs == query.xze) |
---|
| 137 | if badrange: |
---|
| 138 | errormess = errormess+"<li>One or several coordinate intervals are not... intervals. Set either a real range or an unique value." |
---|
| 139 | |
---|
| 140 | # Get how many free dimensions we have |
---|
| 141 | sumfree = islatfree + islonfree + isloctfree + isaltfree |
---|
| 142 | if sumfree >= 3: errormess = errormess + "<li>3 or more free dimensions are set... but only 1D and 2D plots are supported!" |
---|
| 143 | |
---|
| 144 | # Get additional parameters |
---|
[793] | 145 | try: query.hrkey = int(form.getvalue("hrkey")) |
---|
| 146 | except: query.hrkey = int(1) |
---|
| 147 | try: query.dust = int(form.getvalue("dust")) |
---|
| 148 | except: query.dust = int(1) |
---|
[639] | 149 | # self.perturkey = 0 #integer perturkey ! perturbation type (0: none) |
---|
| 150 | # self.seedin = 1 #random number generator seed (unused if perturkey=0) |
---|
| 151 | # self.gwlength = 0. #gravity Wave wavelength (unused if perturkey=0) |
---|
[821] | 152 | try: query.colorm = form.getvalue("colorm") |
---|
| 153 | except: query.colorm = "jet" |
---|
[639] | 154 | |
---|
[761] | 155 | # Get variables to plot |
---|
| 156 | var1 = form.getvalue("var1") |
---|
| 157 | var2 = form.getvalue("var2") |
---|
| 158 | var3 = form.getvalue("var3") |
---|
| 159 | var4 = form.getvalue("var4") |
---|
[793] | 160 | |
---|
| 161 | # fg: init var as with form values |
---|
| 162 | if var1 == None: var1="t" |
---|
| 163 | |
---|
| 164 | vartoplot = [] |
---|
| 165 | if var1 != "none": vartoplot = np.append(vartoplot,var1) |
---|
[794] | 166 | if var2 != "none" and var2 != None: vartoplot = np.append(vartoplot,var2) |
---|
[793] | 167 | if var3 != "none" and var3 != None: vartoplot = np.append(vartoplot,var3) |
---|
| 168 | if var4 != "none" and var4 != None: vartoplot = np.append(vartoplot,var4) |
---|
| 169 | |
---|
[761] | 170 | iswind = form.getvalue("iswind") |
---|
| 171 | if iswind == "on": iswindlog = True |
---|
| 172 | else: iswindlog = False |
---|
| 173 | isfixedlt = form.getvalue("isfixedlt") |
---|
[821] | 174 | if isfixedlt == "on": query.fixedlt=True |
---|
| 175 | else: query.fixedlt=False |
---|
| 176 | iszonmean = form.getvalue("zonmean") |
---|
| 177 | if iszonmean == "on": query.zonmean=True |
---|
| 178 | else: query.zonmean=False |
---|
[639] | 179 | |
---|
[821] | 180 | ### now, proceed... |
---|
| 181 | if errormess == "": |
---|
[639] | 182 | |
---|
[821] | 183 | # reference name (to test which figures are already in the database) |
---|
| 184 | reference = query.getnameset()+str(var1)+str(var2)+str(var3)+str(var4)+str(iswind)+str(isfixedlt)+str(iszonmean)+query.colorm |
---|
| 185 | figname = '../img/'+reference+'.png' |
---|
| 186 | txtname = '../txt/'+reference+'.txt' |
---|
| 187 | testexist = daos.path.isfile(figname) |
---|
[639] | 188 | |
---|
[821] | 189 | # extract data from MCD if needed |
---|
| 190 | if not testexist: |
---|
| 191 | |
---|
[639] | 192 | ### 1D plots |
---|
| 193 | if sumfree == 1: |
---|
| 194 | |
---|
| 195 | ### getting data |
---|
[821] | 196 | if isloctfree == 1: query.diurnal(nd=25) |
---|
[812] | 197 | elif islonfree == 1: query.zonal(nd=64) |
---|
| 198 | elif islatfree == 1: query.meridional(nd=48) |
---|
| 199 | elif isaltfree == 1: query.profile(nd=35) |
---|
[639] | 200 | else: exit() |
---|
| 201 | |
---|
| 202 | ### generic building of figure |
---|
[811] | 203 | query.getascii(vartoplot,filename=txtname) |
---|
[800] | 204 | query.htmlplot1d(vartoplot,figname=figname) |
---|
[639] | 205 | |
---|
| 206 | ### 2D plots |
---|
| 207 | elif sumfree == 2: |
---|
| 208 | |
---|
| 209 | ### getting data |
---|
[821] | 210 | if islatfree == 1 and islonfree == 1: query.htmlmap2d(vartoplot,incwind=iswindlog,figname=figname) |
---|
| 211 | else: query.htmlplot2d(vartoplot,figname=figname) |
---|
[761] | 212 | |
---|
[821] | 213 | #### NOW WRITE THE HTML PAGE TO USER |
---|
| 214 | |
---|
[639] | 215 | ## This is quite common |
---|
[793] | 216 | print "Content-type:text/html\n" |
---|
| 217 | print " " #Apache needs a space after content-type |
---|
[639] | 218 | |
---|
[793] | 219 | #entete="""<?xml version="1.0" encoding="UTF-8"?> |
---|
| 220 | #<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN" "http://www.w3.org/Math/DTD/mathml2/xhtml-math11-f.dtd"> |
---|
| 221 | #<html xmlns="http://www.w3.org/1999/xhtml"> """ |
---|
| 222 | |
---|
| 223 | header="""<html><head><title>Mars Climate Database: The Web Interface</title></head><body>""" |
---|
| 224 | |
---|
| 225 | print header |
---|
[797] | 226 | #print query.printset() |
---|
| 227 | #print "<br />" |
---|
[793] | 228 | |
---|
[639] | 229 | ## Now the part which differs |
---|
[821] | 230 | if errormess != "": |
---|
| 231 | print "<h1>Ooops!</h1>" |
---|
| 232 | print "Please correct the following problems before submitting again." |
---|
| 233 | print "<ul>" |
---|
| 234 | print errormess |
---|
| 235 | print "</ul>" |
---|
| 236 | else: |
---|
| 237 | if sumfree == 0: query.update() ; query.htmlprinttabextvar(vartoplot) |
---|
| 238 | elif sumfree == 2: print "<img src='"+figname+"'><br />" |
---|
| 239 | elif sumfree == 1: |
---|
| 240 | print "<a href='"+txtname+"'>Click here to download an ASCII file containing data</a><br />" |
---|
| 241 | print "<hr>" |
---|
| 242 | print "<img src='"+figname+"'><br />" |
---|
[639] | 243 | |
---|
| 244 | ## This is quite common |
---|
[821] | 245 | bottom = "</body></html>" |
---|
| 246 | print bottom |
---|