source: TI03-DataExtractor/trunk/pydxc/DisplayManager.py @ 1244

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI03-DataExtractor/trunk/pydxc/DisplayManager.py@1244
Revision 1244, 51.6 KB checked in by astephen, 13 years ago (diff)

Close to alpha version.

Line 
1#   Copyright (C) 2004 CCLRC & NERC( Natural Environment Research Council ).
2#   This software may be distributed under the terms of the
3#   Q Public License, version 1.0 or later. http://ndg.nerc.ac.uk/public_docs/QPublic_license.txt
4
5"""
6DisplayManager.py
7=================
8
9Holds the DisplayManager class for displaying HTML output from
10the Data Extractor client.
11
12"""
13
14# Import standard library modules
15import os, re
16
17# Import package modules
18from clientConfig import *
19from common import *
20import DateTimeManager
21import jsFunctions
22
23
24class DisplayManager:
25    """
26    Class for displaying HTML output from the Data Extractor.
27    """         
28   
29    def __init__(self):
30        """
31        Initialiser for display manager. Just gives a handle for the instance.
32        """
33        pass   
34       
35    def _displayHTTPHeader(self):
36        """
37        Prints the HTTP header.
38        """
39        print HTTP_HEADER
40       
41
42    def _displayHTMLHeader(self):
43        """
44        Prints the configured HTML header.
45        """
46        headfile=os.path.join(HTML_DIR_LOCAL_PATH, "header.html")
47        header=" ".join(open(headfile).readlines())
48        header=header.replace("PACKAGE_NAME", PACKAGE_NAME)
49        header=header.replace("WEB_EXTRAS_URL_PATH", WEB_EXTRAS_URL_PATH)
50        header=header.replace("LEFT_LOGO", os.path.join(LOGO_DIR, LEFT_LOGO))
51        header=header.replace("RIGHT_LOGO", os.path.join(LOGO_DIR, RIGHT_LOGO))
52        print header
53
54        # Now write user message if there is one:
55        if MESSAGE_TO_USERS!=None:
56            print """<CENTER><I>
57<FONT FACE="Arial, Helvetica, sans-serif" SIZE="+1" COLOR="RED">*** %s ***</FONT></I></CENTER><BR>""" % MESSAGE_TO_USERS
58
59
60    def _displayIntroduction(self):
61        """
62        Prints an introduction to the service.
63        """
64        print """<P>Welcome to the <B>%s</B>. This product is powered by Python,
65              CDAT and CSML.
66              """ % PACKAGE_NAME
67                     
68
69    def _displaySummaryLine(self, selectionList):
70        """
71        Prints a summary line of what has been selected so far.
72        """
73        print "<P><B>Selected so far:"
74        for item in selectionList:
75            print " -> %s" % item
76
77
78    def _displayLoginBar(self, username, loginStatus, loginMessage=""):
79        """
80        If security applies then display the login information.
81        """
82        if RESTRICTED_DATA:
83            statusMap={"out":"not logged in", "in":"logged in as %s" % username}
84            print "<P><B>Login status: </B>%s&nbsp;&nbsp;&nbsp;&nbsp;" % statusMap[loginStatus]
85            if len(loginMessage)>0:
86                print '<FONT COLOR="red">&nbsp;&nbsp;&nbsp;&nbsp;[ %s ]</FONT>' % loginMessage
87            if loginStatus=="out":
88                # Display a login form
89                print """<FORM NAME="loginForm" method="POST" action="%s">
90                      Username: <INPUT TYPE="text" SIZE="20" NAME="yousirnaim" VALUE="">
91                      Password: <INPUT TYPE="password" SIZE="10" NAME="parcewerd" VALUE="">
92                      <INPUT TYPE="submit" NAME="login" VALUE="Login"></FORM>""" % CGI_SCRIPT_URL_PATH
93            elif loginStatus=="in":
94                # Display a logout form
95                print """<FORM NAME="loginForm" method="POST" action="%s">
96                      <INPUT TYPE="submit" NAME="logout" VALUE="Logout"></FORM>""" % CGI_SCRIPT_URL_PATH                     
97
98
99    def _displayNDGLoginBar(self, loginHosts, uriArgString):#, username, loginStatus, loginMessage=""):
100        """
101        If security applies then display the login information.
102        """
103        if RESTRICTED_DATA:
104            print """<P>Login:<P>
105<form action="https://glue.badc.rl.ac.uk/cgi-bin/security.py" method="POST">
106<table><tr>
107  <td><select name="requestURI">
108      <option value="">Select your home site...""" 
109     
110            for i,j in loginHosts:
111                print """<option value="%s"/>%s""" % (j,i)
112   
113            print """</select></td>
114<td><input type="submit" value="Login"></td>
115</tr></table>
116
117<input type="hidden" name="returnURI" value="%s%s">
118</form>
119""" % (CGI_SCRIPT_URL_PATH, uriArgString)
120#           statusMap={"out":"not logged in", "in":"logged in as %s" % username}
121#           print "<P><B>Login status: </B>%s&nbsp;&nbsp;&nbsp;&nbsp;" % statusMap[loginStatus]
122#           if len(loginMessage)>0:
123#               print '<FONT COLOR="red">&nbsp;&nbsp;&nbsp;&nbsp;[ %s ]</FONT>' % loginMessage
124#           if loginStatus=="out":
125#               # Display a login form
126#               print """<FORM NAME="loginForm" method="POST" action="%s">
127#                     Username: <INPUT TYPE="text" SIZE="20" NAME="yousirnaim" VALUE="">
128#                     Password: <INPUT TYPE="password" SIZE="10" NAME="parcewerd" VALUE="">
129#                      <INPUT TYPE="submit" NAME="login" VALUE="Login"></FORM>""" % CGI_SCRIPT_URL_PATH
130#           elif loginStatus=="in":
131#               # Display a logout form
132#               print """<FORM NAME="loginForm" method="POST" action="%s">
133#                      <INPUT TYPE="submit" NAME="logout" VALUE="Logout"></FORM>""" % CGI_SCRIPT_URL_PATH       
134                         
135       
136    def _displayHTMLFooter(self):
137        """
138        Prints the configured HTML footer.
139        """
140        footfile=os.path.join(HTML_DIR_LOCAL_PATH, "footer.html")
141        lines=open(footfile).read()
142        print lines % ("mailto:"+ADMIN_MAIL_ADDRESS)
143
144
145    def _displayErrorMessage(self, msg, sessionID=None, user=None):
146        """
147        Prints an error message, without a header or footer.
148        """
149        print "<P>An error has occurred with this application. The error message received is:<P>"
150        print "<P><B>%s</B>" % msg
151        print "<P>The administrator has been informed of this error and will look into it."
152        print """<P>You can try pressing the <I>Back</I> button to return to the previous page.
153                 Alternatively you can<P><A HREF="%s"><FONT SIZE="+1">restart your request</FONT></A>.""" % CGI_SCRIPT_URL_PATH
154       
155       
156    def _displayErrorPage(self, msg):
157        """
158        Prints an error page, including headers and footer.
159        """
160        self._displayHTTPHeader()
161        self._displayHTMLHeader()
162        self._displayErrorMessage(msg)
163
164       
165    def _displayMainTableHeader(self, sessionID, onSubmit=""):
166        """
167        Prints the header part of the main table used in the dx
168        web pages.
169        """
170        print '<TABLE WIDTH="100%"><TR>'
171               
172        print '<TABLE WIDTH="100%"><TR class="tablerow"><TD>FURTHER SELECTION</TD></TR></TABLE>'
173        # Begin form in HTML output
174        print """<FORM NAME="extract_info" method="POST" action="%s"%s>""" % (CGI_SCRIPT_URL_PATH, onSubmit)
175
176        print '<TABLE WIDTH="100%"><TR>'
177        print '<INPUT NAME="sessionID" TYPE="hidden" VALUE="%s">' % sessionID   
178       
179       
180    def _displayMainTableFooter(self):
181        """
182        Prints the footer part of the main table used in the dx
183        web pages.
184        """
185        print "</TR></TABLE>"
186        print '<P><INPUT TYPE="submit" NAME="proceed" VALUE="Proceed"><P>'
187        print "</FORM><P>"
188
189               
190    def _displayOptionsTable(self, summaryDict, optionCategories, options, optionStrings, sessionID, sessionObj):
191        """
192        Displays the options provided in the format (optionCategory, [option1,
193        option2, .., optionN]). Each dataset has these. It also sends the
194        sessionID as a hidden variable.
195        """     
196        # Get the category name to show on the
197        itemMap={"datasetGroup":"Dataset Group", "dataset":"Dataset",
198                 "variable":"Variable"} 
199       
200        if len(options)==0:
201            print """<BR><B>You do not have permission to view any of the available options.</B>
202            <P>You can apply for access to datasets at:
203<P><A HREF="%s">%s</A>.<P>
204</B></FONT>
205""" % (REGISTRATION_PAGE, REGISTRATION_PAGE)
206            return
207           
208        # Now loop through getting the appropriate list of values to show       
209        """
210        for dsetNumber in range(1, self.numberOfDatasets+1):
211            selectedFlag=None
212            tableWidth=100/(self.numberOfDatasets)
213            print '<TD WIDTH="%s%%" class="tablestyle" VALIGN="top">' % tableWidth
214
215            #print '<P>%s<P>' % options
216            itemTitle=itemMap[optionCategories[0].split("_")[0]]+(" %s" % dsetNumber)
217            print "<P><B>PLEASE SELECT: %s</B><P>" % itemTitle
218           
219            # Otherwise, write out the list of options.
220            radioName=optionCategories[dsetNumber-1]
221            if sessionObj.has_key(radioName):   
222                selectedFlag=sessionObj[radioName]
223               
224            if itemTitle.find("Dataset Group")>-1:
225                # Need to wade through metadata links to deal with this one...
226                datasetGroups=[]
227                detailedMetadataLinks=[]
228                discoveryMetadataLinks=[]
229               
230                for option in options[dsetNumber-1]:
231                    datasetGroups.append(option[0])
232                    detailedMetadataLinks.append(option[1][0])
233                    discoveryMetadataLinks.append(option[1][1])
234                if selectedFlag==None or selectedFlag not in datasetGroups:
235                    selectedFlag=datasetGroups[0]
236                   
237                for option in datasetGroups:
238                    counter=datasetGroups.index(option)
239                    optionString=optionStrings[dsetNumber-1][counter]
240                   
241                    if option==selectedFlag:
242                        print '<BR><INPUT TYPE="radio" NAME="%s" VALUE="%s" CHECKED>%s</INPUT>' % (radioName, option, optionString)                     
243                    else:
244                        print '<BR><INPUT TYPE="radio" NAME="%s" VALUE="%s">%s</INPUT>' % (radioName, option, optionString)                         
245                    if detailedMetadataLinks[counter].lower()!="none":
246                        print '&nbsp;<A HREF="%s">[ Detailed Metadata ]</A>' % detailedMetadataLinks[counter]
247                    if discoveryMetadataLinks[counter].lower()!="none":
248                        print '&nbsp;<A HREF="%s">[ Discovery Metadata ]</A>' % discoveryMetadataLinks[counter]
249                                           
250            else:
251                if selectedFlag==None or selectedFlag not in options[dsetNumber-1]:
252                    selectedFlag=options[dsetNumber-1][0]
253
254                for option in options[dsetNumber-1]:
255                    optionString=optionStrings[dsetNumber-1][options[dsetNumber-1].index(option)]
256                   
257                    if option==selectedFlag:
258                        print '<BR><INPUT TYPE="radio" NAME="%s" VALUE="%s" CHECKED>%s</INPUT>' % (radioName, option, optionString)
259                    else:
260                        print '<BR><INPUT TYPE="radio" NAME="%s" VALUE="%s">%s</INPUT>' % (radioName, option, optionString)     
261                         
262        print "</TD>" """
263       
264        itemTitle=itemMap[optionCategories[0].split("_")[0]]
265        print '<P><B>PLEASE SELECT: %s</B> (<A NAME="selectAll" onclick="selectAllCheckBoxes()">  select all </A> / <A NAME="deSelectAll" onclick="deSelectAllCheckBoxes()"> deselect all </A> )<P>' % itemTitle
266       
267        # Insert useful select all javascript function for checkboxes
268        print jsFunctions.js_selectAllCheckBoxes
269        print jsFunctions.js_deSelectAllCheckBoxes
270       
271        if itemTitle=="Dataset Group":
272                # Need to wade through metadata links to deal with this one...
273                selectionIDs=optionCategories
274                datasetGroupValues=[i[0] for i in options]
275                datasetGroupNames=[i[0] for i in optionStrings]
276                detailedMetadataLinks=[i[1][0] for i in options]
277                discoveryMetadataLinks=[i[1][1] for i in options]
278
279                selectedFlag=None                 
280                for i in range(len(selectionIDs)):
281                    selectionID=selectionIDs[i]
282                    datasetGroupValue=datasetGroupValues[i]
283                    datasetGroupName=datasetGroupNames[i]
284                    detailedMetadataLink=detailedMetadataLinks[i]
285                    discoveryMetadataLink=discoveryMetadataLinks[i]     
286                           
287                    if not selectedFlag:
288                        print '<BR><INPUT TYPE="checkBox" NAME="%s" VALUE="%s" CHECKED>%s</INPUT>' % (selectionID, datasetGroupName, datasetGroupValue)                 
289                        selectedFlag=1
290                    else:
291                        print '<BR><INPUT TYPE="checkBox" NAME="%s" VALUE="%s">%s</INPUT>' % (selectionID, datasetGroupName, datasetGroupValue)                     
292
293                    if detailedMetadataLink.lower()!="undefined":
294                        print '&nbsp;<A HREF="%s">[ Detailed Metadata ]</A>' % detailedMetadataLink
295                    if discoveryMetadataLink.lower()!="undefined":
296                        print '&nbsp;<A HREF="%s">[ Discovery Metadata ]</A>' % discoveryMetadataLink
297               
298
299        elif itemTitle=="Dataset":
300                selectionIDs=optionCategories
301                itemValues=options
302                itemNames=optionStrings
303                selectedFlag=None 
304               
305                lastDatasetGroup="WON'T MATCH"             
306                for i in range(len(selectionIDs)):
307                    selectionID=selectionIDs[i]
308                    itemName=itemNames[i]
309                    itemValue=itemValues[i]
310                   
311                    dsgKey=re.match("dataset_(\d+)\.", selectionID).groups()[0]
312                    datasetGroup=summaryDict["datasetGroups"][dsgKey]
313                    if datasetGroup!=lastDatasetGroup:
314                        print """<BR><B>%s -&gt; Dataset selection:</B>""" % datasetGroup           
315
316                    if not selectedFlag:
317                        print '<BR><INPUT TYPE="checkBox" NAME="%s" VALUE="%s" CHECKED>%s</INPUT>' % (selectionID, itemName, itemValue)                 
318                        selectedFlag=1
319                    else:
320                        print '<BR><INPUT TYPE="checkBox" NAME="%s" VALUE="%s">%s</INPUT>' % (selectionID, itemName, itemValue)                     
321               
322                    lastDatasetGroup=datasetGroup       
323                       
324
325        elif itemTitle=="Variable":
326                # Set up hidden option to direct client to call for domain options so it will get format as well
327                print '<INPUT TYPE="hidden" NAME="targetPage" VALUE="DomainAndFormatPage">' 
328               
329                selectionIDs=optionCategories
330                itemValues=[i[0] for i in options]
331                itemNames=[i[1] for i in optionStrings]
332                selectedFlag=None 
333               
334                lastDataset="WON'T MATCH"
335                lastDatasetGroup="WON'T MATCH"             
336                for i in range(len(selectionIDs)):
337                    selectionID=selectionIDs[i]
338                    itemName=itemNames[i]
339                    itemValue=itemValues[i]
340                    # Quick fudge for strange itemValue that is actually a list
341                    try:                   
342                        if type(itemValue)==type([]):
343                            itemValue=itemValue[0]
344                    except:
345                        pass
346
347                    if itemName[-5:]=="_dxvv":
348                        itemValue=itemValue+" (Virtual Variable)"
349                       
350                    (dsgKey, dsKey)=re.match("variable_(\d+)\.(\d+)\.", selectionID).groups()
351                    datasetGroup=summaryDict["datasetGroups"][dsgKey]
352                    dataset=summaryDict["datasets"]["%s.%s" % (dsgKey, dsKey)]
353                    if dataset!=lastDataset or lastDatasetGroup!=datasetGroup:
354                        print """<BR><B>%s -&gt; %s -&gt; Variable selection:</B>""" % (datasetGroup, dataset)
355
356                    if not selectedFlag:
357                        print '<BR><INPUT TYPE="checkBox" NAME="%s" VALUE="%s" CHECKED>%s</INPUT>' % (selectionID, itemName, itemValue)                 
358                        selectedFlag=1
359                    else:
360                        print '<BR><INPUT TYPE="checkBox" NAME="%s" VALUE="%s">%s</INPUT>' % (selectionID, itemName, itemValue)                     
361                    lastDataset=dataset
362                    lastDatasetGroup=datasetGroup
363                   
364           
365    def _displayDomainOptions(self, summaryDict, optionCategories, options, optionStrings, sessionID):
366        """
367        Displays the domain options for each variable.
368        """     
369        axisBucket=[[],[],[]]
370        formatDict={}
371        counter=0
372        for item in optionCategories:
373            if item[:4]=="axis":
374                axisBucket[0].append(item)
375                axisBucket[1].append(options[counter])
376                axisBucket[2].append(optionStrings[counter])
377            elif item[:6]=="output":
378                formatDict[item]=options[counter]
379            counter=counter+1
380       
381        """sameBucket=getIdenticalDomains(axisBucket)
382        if len(sameBucket)>0:
383            print "<P>Found the same: "
384            for sameVars in sameBucket:
385                print "<BR>", (" ".join(sameVars))
386            print "<P>"         """
387       
388        (optionCategories, options, optionStrings)=axisBucket
389        #print "<P>", formatDict, "<P>", optionCategories
390        print "<P><B>PLEASE SELECT: Domain options</B><P>"     
391        print "<TABLE>"
392        print """<TR CLASS="tablestyle">
393                        <TD><B>AXIS NAME</B></TD>
394                        <TD><B>RECOGNISED AS</B></TD>
395                        <TD><B>UNITS</B></TD>
396                        <TD COLSPAN="3"><B>SELECTION</B></TD>
397                        <TD><B>INFORMATION</B></TD></TR>"""
398       
399        # Predefine what we need for the axis selection in terms of interfaces...
400        knownAxisDict={}               
401               
402        # Loop through keys to get the number of variables
403        axisDict={}
404       
405        # Create some lists to collect time axis info for time validation functions
406        minNames=[]
407        minValues=[]
408        maxValues=[]   
409       
410        for i in range(len(optionCategories)):
411            optionName=optionCategories[i]
412            varIndex=".".join(optionName.split(".")[:-1])[5:]
413            axisIndex=int(optionName.split(".")[-1])
414            items=options[i]
415            [knownAxis, id, longName, units, listType, unused]=items[:6]       
416           
417            if not axisDict.has_key(varIndex):
418                axisDict[varIndex]={"axes":[]}
419            if knownAxis in ("time", "latitude", "longitude"):
420                axisDict[varIndex][knownAxis]=axisIndex
421                if knownAxis=="time":
422                    startTime=getDateTimeComponents(items[6])
423                    endTime=getDateTimeComponents(items[7])
424                    minNames.append(optionName)
425                    minValues.append(startTime[:])
426                    maxValues.append(endTime[:])
427           
428            axisDict[varIndex]["axes"].append([optionName, items])
429             
430        axisDictKeys=axisDict.keys()
431        axisDictKeys.sort()
432        #print axisDictKeys
433       
434        # Now print javascript time functions if needed
435        if len(minNames)>0:
436            minNames=str(minNames)
437            minValues=str([list(lst) for lst in minValues])
438            maxValues=str([list(lst) for lst in maxValues])
439            print jsFunctions.js_timeValidationFunctions % (minNames, minValues, maxValues)
440       
441        for key in axisDictKeys:
442
443            varID=summaryDict["variables"][key]
444            dsgKey, dsKey=re.match("(\d+)\.(\d+)", key).groups()
445            datasetGroup=summaryDict["datasetGroups"][dsgKey]
446            dataset=summaryDict["datasets"]["%s.%s" % (dsgKey, dsKey)]
447            print """<TR><TD COLSPAN="7">&nbsp;</TD></TR>"""   
448            print """<TR CLASS="tablestyle"><TD COLSPAN="7"><B>%s -&gt; %s -&gt; %s</TD></TR>""" % (datasetGroup, dataset, varID)           
449       
450            d=axisDict[key]
451            axes=d["axes"]
452           
453            found={}
454            # Check time, lat and lon
455            for ax in ("time", "latitude", "longitude"):
456                if d.has_key(ax):
457                    found[ax]=d[ax]
458           
459            for axis in axes:
460                (optionName, items)=axis
461                varIndex=".".join(optionName.split(".")[:-1])[5:]
462                axisIndex=int(optionName.split(".")[-1])
463                #items=options[i]
464                [knownAxis, id, longName, units, listType, unused]=items[:6]
465
466                if (found.has_key("latitude") and found.has_key("longitude")) and \
467                        axisIndex in (found["latitude"], found["longitude"]):
468               
469                    if found.has_key("used lat lon"):  continue
470               
471                    if axisIndex==found["latitude"]:
472                        # The current axis is latitude so need to get longitude
473                        latItems=items         
474                        latOptionName=optionName       
475                        lonIndex=found["longitude"]
476                       
477                        for x in axes:
478                            if int(x[0].split(".")[-1])==lonIndex:
479                                # Found longitude axis in list
480                                (lonOptionName, lonItems)=x                     
481                       
482                    elif axisIndex==found["longitude"]:
483                        # The current axis is longitude so need to get latitude
484                        lonItems=items
485                        lonOptionName=optionName                       
486                        latIndex=found["latitude"]
487                       
488                        for x in axes:
489                            if int(x[0].split(".")[-1])==latIndex:
490                                # Found latitude axis in list
491                                (latOptionName, latItems)=x             
492                                                               
493                    [latKnownAxis, latId, latLongName, latUnits, latListType, latUnused]=latItems[:6]
494                    northernExtent, southernExtent=latItems[6:8]
495                    [lonKnownAxis, lonId, lonLongName, lonUnits, lonListType, lonUnused]=lonItems[:6]
496                    westernExtent, easternExtent=lonItems[6:8]
497   
498                    found["used lat lon"]=1
499                     
500                    #print '<B>Horizontal Domain</B><P>'
501                     
502                    print """<TR><TD WIDTH="20%%"><B>%s</B></TD>
503                     <TD>%s</TD>
504                     <TD>%s</TD>
505                     <TD></TD>                               
506                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/><BR></TD>
507                     <TD><B></B></TD>
508                     <TD WIDTH="30%%"><FONT SIZE="-2"><B>NOTE ABOUT THE JAVA MAP APPLET:</B>
509<BR>1. The map will not work if you do not have Java enabled on your browser.</FONT></TD>
510                     </TR>""" % (latLongName, latKnownAxis, latUnits, 
511                                   latOptionName+"_high", northernExtent) 
512                                                                             
513                                                                             
514                    # Check existence of map applet page for this axis ID, otherwise make it
515                    mapHTMLFile=self._checkMapAppletHTMLPage(lonOptionName, latOptionName)
516                   
517                    print """<TR><TD WIDTH="20%%"><B>%s</B></TD>
518                     <TD>%s</TD>
519                     <TD>%s</TD>                     
520                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
521                     <TD><TABLE BORDER="0"><TR><TD ALIGN="LEFT">&nbsp;<B></B></TD><TD><CENTER><B><input type="button" value="Select from map"
522    onClick="newWindow('%s','window2',550,400);"></CENTER></TD></TR></TABLE></TD>                   
523                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
524                     <TD><BR><FONT SIZE="-2">2. This applet is known not to work on certain browsers: Mozilla, Konqueror.</FONT></TD>
525                     </TR>""" % (lonLongName, lonKnownAxis, lonUnits, 
526                                   lonOptionName+"_low", westernExtent, mapHTMLFile, lonOptionName+"_high",
527                                   easternExtent) 
528                                                   
529                    print """<TR><TD WIDTH="20%%"><B>%s</B></TD>
530                     <TD>%s</TD>
531                     <TD>%s</TD>                     
532                     <TD></TD>                               
533                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
534                     <TD><B>&nbsp;</B></TD>
535                     <TD><FONT SIZE="-2">
536<BR>3. On some browsers you may have to select your subset twice before it registers.</FONT></TD>
537                     </TR>""" % ("","","", 
538                                   latOptionName+"_low", southernExtent)                   
539
540                elif found.has_key("time") and axisIndex==found["time"]:
541                    (start,end,intervalValue)=items[6:9]
542                   
543                   
544                    print """<TR><TD WIDTH="20%%"><B>%s</B></TD>
545                     <TD>%s</TD>
546                     <TD>%s</TD>""" % (longName, knownAxis, units)
547
548                    self._displayTemporalDomainMenus(start, end, intervalValue, units, optionName)
549                    print """<TD><INPUT TYPE="button" NAME="validateTime" VALUE="Validate time selections" onClick='validateTimeSelections("%s")'/></TD></TR>""" % optionName
550                             
551                           
552                    """<TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
553                     <TD><TABLE BORDER="0"><TR><TD ALIGN="LEFT">&nbsp;<B>Low</B></TD><TD ALIGN="RIGHT"><B>High</B>&nbsp;</TD></TR></TABLE></TD>                     
554                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
555                     </TR>""" #% (optionName+"_low", start, optionName+"_high", end)   
556                         
557                else:
558                    start,end=items[6:8]
559                    print """<TR><TD WIDTH="20%%"><B>%s</B></TD>
560                     <TD>%s</TD>
561                     <TD>%s</TD>                     
562                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
563                     <TD><TABLE BORDER="0"><TR><TD ALIGN="LEFT">&lt;&nbsp;<B>Low</B></TD><TD ALIGN="RIGHT"><B>High</B>&nbsp;&gt;</TD></TR></TABLE></TD>             
564                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
565                     </TR>""" % (longName, knownAxis, units, 
566                     optionName+"_low", start, optionName+"_high", end)   
567
568            # Fudge output format for now
569            print """<TR><TD WIDTH="20%%"><B>OUTPUT FORMAT</B></TD>"""
570            print """<TD COLSPAN="3">Note that you should choose NetCDF format if you wish to visualise data.</TD>"""               
571            print '<TD COLSPAN="3"><SELECT NAME="outputFormat_%s">' % key
572            for format in formatDict["outputFormat_%s" % varIndex]:#("NetCDF", "NASA Ames"):
573                print "<OPTION>%s</OPTION>" % format
574            print "</SELECT></TD>"
575                     
576        print "</TABLE>"
577
578        print """<P><INPUT TYPE="checkbox" NAME="multipleFileOutput">
579               &nbsp;Use multiple output files [ this is the default large files as limited by the server ]."""
580               
581
582    def  _checkMapAppletHTMLPage(self, lonAxisID, latAxisID):
583        """
584        Generates a map applet HTML Page if one doesn't already exist.
585        """
586        mapAppletTemplatePath=MAP_APPLET_TEMPLATE_LOCAL_PATH
587        (mapAppletDir, templateFile)=os.path.split(mapAppletTemplatePath)
588        axisNumbers=lonAxisID[5:]+"_"+latAxisID[5:]
589        axisMapHTMLPage=os.path.join(mapAppletDir, "map_%s.html" % axisNumbers)
590        if not os.path.isfile(axisMapHTMLPage):
591            template=open(mapAppletTemplatePath).read()
592            outfile=open(axisMapHTMLPage, "w")
593            outfile.write(template % (lonAxisID, lonAxisID, latAxisID, latAxisID))
594            outfile.close()
595            os.chmod(axisMapHTMLPage, 0644)
596        urlToAxisMapHTMLPage=os.path.join(os.path.split(MAP_APPLET_TEMPLATE_URL_PATH)[0], os.path.split(axisMapHTMLPage)[-1])
597        return urlToAxisMapHTMLPage
598
599
600    def _displayUploadForm(self, sessionID):
601        """
602        Displays a form entry for browsing the local system
603        to upload a file. UPLOAD_TEMP_DIR needs to be configured in
604        the clientConfig.py module.
605        """
606        print '<FORM METHOD="post" ACTION="%s" ENCTYPE="multipart/form-data">' % CGI_SCRIPT_URL_PATH
607        print "<P>Please provide the location of the request file you wish to upload:"
608        print """&nbsp;<INPUT TYPE="file" NAME="uploadedFile" VALUE="" SIZE="40">
609                       <INPUT NAME="action" TYPE="hidden" VALUE="parseUploadedFile">
610                       <INPUT NAME="sessionID" TYPE="hidden" VALUE="%s">
611                       <INPUT TYPE="submit" NAME="submit" VALUE="Upload"></FORM><P>\n<FORM>""" % sessionID
612
613
614    def _displayMetadataForm(self, fileName, fileFormat, varList, globalMetadata):
615        """
616        Displays the metadata in the data file.
617        """
618        #print """<INPUT NAME="variable_1" TYPE="hidden" VALUE="pqn">"""
619        print """<P>Thank you for uploading your file to the NetCDF-NASA Ames convertor.
620               The following information has been extracted from the file:
621               <BR><B>Filename:     %s</B>
622               <BR><B>File format:  %s</B>
623               <P><B><FONT SIZE="+1">Variables:</FONT></B>
624               <BR>Select the variables that you wish convert (Default=ALL):<P>""" % (fileName, fileFormat)
625       
626        # Now print the variable list as a form
627        varCount=1
628        print '<BR><INPUT TYPE="hidden" NAME="selectionsMade" VALUE="complete">'
629        for var in varList:
630            longName, varID=var
631            varString=varID
632            displayVar="%s &nbsp;&nbsp;{%s}" % (longName, varID)
633            if varID in ("None", "", None):
634                varString=longName
635                displayVar=varString
636            print '<BR><INPUT TYPE="checkbox" NAME="variable_%s" VALUE="%s" CHECKED>%s</INPUT>' % (varCount, varString, displayVar)
637            #print "<BR>%s (%s)" % tuple(var) # prints var id and long_name
638            varCount=varCount+1
639       
640        outFileMap={"NetCDF":"NASA Ames", "NASA Ames":"NetCDF"}   
641        # Now print metadata
642        print """<P><BR><B><FONT SIZE="+1">Global Metadata</FONT></B>
643              <BR>The following global metadata will be written to your output %s file(s):<P>""" % outFileMap[fileFormat]
644             
645        print '<TABLE BORDER="0">'
646        maxSize=10
647        for item in globalMetadata:
648            key, value=item
649            if key=="VNAME":
650                continue
651                displayKey="VNAME Variables from NASA Ames (modify below to rename)"
652            elif key=="ANAME":
653                continue
654                if value!=None:
655                    displayKey="ANAME Auxiliary Variables from NASA Ames (modify below to rename)"
656                else:
657                    break
658            else:
659                displayKey=key
660               
661            print '<TR><TD WIDTH="25"><B>%s: </B>' % displayKey
662           
663            #print str(type(value))
664            if type(value)!=type(""):
665                # deal with list type by indexing each part
666                try:
667                    value=value.data
668                except:
669                    pass
670                   
671                partCount=1
672                lengthList=[len(str(i)) for i in value]
673                total=0
674                for i in lengthList: total=total+i
675                #print "<P>TOTAL:", total
676                if total<60: 
677                    # Put all on one line
678                    print "<BR>"
679                    separator=""
680                    sizeString="%s" % (max(lengthList)+5)
681                    inputType="textbox"
682                else:
683                    separator="<BR>"
684                    sizeString="100"
685                    inputType="textbox"
686                   
687                #print dir(value), value.data
688                for part in value:
689                    if key in ("VNAMEAAAAAAAAAAA", "ANAMEAAAAAAAA"): # if variable names
690                        partName="%s-RENAMED_%s" % (key, partCount)
691                    else:
692                        partName="%s_%s" % (key, partCount)
693                    part=str(part)                 
694                    print '%s<INPUT TYPE="%s" NAME="%s" VALUE="%s" SIZE="%s"/>' % (separator, inputType, partName, part, sizeString)
695                    partCount=partCount+1
696                print "</TD></TR>"
697               
698            else:
699                size=len(value)     
700                if size>100:
701                    inputType="textbox"
702                else:
703                    inputType="textbox"
704                print '<INPUT TYPE="%s" NAME="%s" VALUE="%s" SIZE="100"/></TD></TR>' % (inputType, key, value)
705            #print "<BR>%s = %s" % tuple(item) # prints name and value of metadata item
706        print "</TABLE>"
707
708
709
710    def _displayOutputPage(self, outputFilePaths):
711        """
712        Displays full HTML page with a link to the output file.
713        """
714        if len(outputFilePaths)==1:
715            file=outputFilePaths[0]
716            print "<P><B>Your output file is available at:</B>"
717            print """<P><A HREF="%s">%s</A><P>""" % (file, file) 
718        else:
719            print "<P><B>Your output files are available at:</B><P>"
720            for file in outputFilePaths:
721                print """<A HREF="%s">%s</A><BR>""" % (file, file) 
722       
723                     
724    def _displayFinalMessage(self, outputMessage=[]):
725        """
726        Prints an a message for the final page.
727        """
728        outputString=""
729        for i in outputMessage: outputString=outputString+"***LINEBREAK***"+str(i)
730        outputString=outputString.replace("<", "&LT;")
731        outputString=outputString.replace(">", "&GT;")
732        outputString=outputString.replace("***LINEBREAK***", "<P>")
733        outputString=outputString.replace("\n\n", "<P>")
734        outputString=outputString.replace("\n", "<BR>")
735       
736        print """<P>Thank you for using <B>%s</B>. You can now download your output file.
737                 <BR>Any output from the conversion package is printed below:
738                 <P><TABLE BORDER="1"><TR><TD BGCOLOR="#EEEEEE"><KBD>%s</KBD></TD></TR></TABLE><P>
739              """ % (PACKAGE_NAME, outputString)
740
741
742    def _displayFeatureOptions(self):
743        """
744        Prints the available Features in a table.
745        """   
746        pass
747       
748       
749    def _displayHorizontalDomainOptions(self, bounds):
750        """
751        Prints a form entry for specifying the horizontal domain.
752        """
753        (northernExtent, westernExtent, southernExtent, easternExtent)=bounds
754
755        # Horizontal Domain
756        print '<B>Horizontal Domain</B><P>'
757
758        print """<TABLE><TR><TD WIDTH="20%%"></TD><TD WIDTH="20%%"></TD>
759<TD WIDTH="20%%" ALIGN="CENTER"><INPUT TYPE="text" NAME="northernExtent" VALUE="%s" SIZE="6"><FONT SIZE="-1"><BR> Northern Extent </FONT></TD>
760<TD WIDTH="20%%"></TD><TD WIDTH="20%%"></TD></TR>
761<TR><TD><INPUT TYPE="text" NAME="westernExtent" VALUE="%s" SIZE="6"><FONT SIZE="-1"><BR> Western Extent </FONT></TD>
762<TD CLASS="tablestyle" COLSPAN="3"><B>NOTE ON LAT/LON SELECTION:</B> If you select a single latitude or longitude that is not on the actual grid the nearest neighbouring point will be used.</TD>
763<TD ALIGN="RIGHT"><INPUT TYPE="text" NAME="easternExtent" VALUE="%s" SIZE="6"><FONT SIZE="-1"><BR> Eastern Extent </FONT></TD>
764<TD></TD>
765<TR><TD></TD><TD></TD>
766<TD ALIGN="CENTER"><INPUT TYPE="text" NAME="southernExtent" VALUE="%s" SIZE="6"><FONT SIZE="-1"><BR> Southern Extent </FONT></TD>
767<TD></TD><TD></TD></TR></TABLE>
768<input type="button" value="Select from map"
769    onClick="newWindow('%s','window2',550,400);">
770<TABLE><TR><TD CLASS="tablestyle">
771<B>NOTE ABOUT THE JAVA MAP APPLET:</B> 
772<BR>1. The map will not work if you do not have Java enabled on your browser.
773<BR>2. This applet is known not to work on certain browsers: Mozilla, Konqueror.
774<BR>3. On some browsers you may have to select your subset twice before it registers.<P>
775</TD></TR></TABLE>""" % (northernExtent, westernExtent, easternExtent, southernExtent, MAP_APPLET_URL_PATH)
776
777        helpLink=os.path.join(WEB_EXTRAS_URL_PATH, "help_page.html#interpolation")
778        print """<P>[&nbsp;<A NAME="%s" onClick="help('%s')">Note about interpolation methods.</A>&nbsp;]<P>""" % (helpLink, helpLink)
779
780       
781    def _displayVerticalSpatialDomainOptions(self, options):
782        """
783        Prints a form entry for specifying the vertical domain.
784        """
785        print '<P><B>Vertical Domain</B><P><TABLE WIDTH="100%"><TR>'
786        for dsetNumber in range(1, self.numberOfDatasets+1):
787            (levels, vertical_units)=options[dsetNumber-1]
788
789            if type(levels)==type(""): levels=(levels,)
790            if len(levels)>3:
791                levboxheight=3
792            else:
793                levboxheight=len(levels)
794
795            print """<TD WIDTH="50%%">Levels<BR><SELECT MULTIPLE NAME="verticalDomain_%s"
796                  SIZE="%s" WIDTH="50" VALUE="%s">""" % (dsetNumber, levboxheight, levels[0])
797            levSelected=" SELECTED"
798            for level in levels:
799                print """<OPTION VALUE="%s"%s>%s</OPTION>""" % (level, levSelected, level)
800                levSelected=""
801            print "</SELECT>"
802            print '<INPUT NAME="verticalUnits" TYPE="hidden" VALUE="hPa">' 
803            print "</TD>"
804        print "</TR></TABLE>"
805
806
807    def _displayTemporalDomainMenus(self, startTime, endTime, intervalValue, intervalUnits, axisIndex):
808        """
809        Displays a set of menus for entering the date and time limits for this axis.
810        """ 
811        startTime=getDateTimeComponents(startTime)
812        endTime=getDateTimeComponents(endTime)
813        super_index_list=[]
814        index_list=[]
815       
816        # Get the bin list for all times
817        timeList=DateTimeManager.createList(startTime, endTime, (intervalValue, intervalUnits), listtype="tuple")
818        timeBins=DateTimeManager.getTimeBins(timeList)
819       
820        for i in range(len(startTime)):
821            index_list.append(timeBins[i].index(startTime[i]))
822        #super_index_list=super_index_list+index_list[:]+index_list[:]
823
824        # Insert javascript functions to do date checking.
825        #if len(super_index_list)==12:  super_index_list=super_index_list+[0,0,0,0,0,0,0,0,0,0,0,0]
826        #print jsFunctions.js_dateCheckFunctionGroup % tuple(super_index_list)     
827
828        # Temporal domain
829        #print '<P><B>Time</B><P><TABLE WIDTH="100%"><TR>'
830        #print '<INPUT NAME="timeIntervalUnits_%s" TYPE="hidden" VALUE="%s">' % (axisIndex, intervalUnits)
831        #print '<INPUT NAME="timeIntervalValue_%s" TYPE="hidden" VALUE="%s">' % (axisIndex, intervalValue)
832        #print '<TD WIDTH="50%">'
833        #print '<TABLE BORDER="1"><TR>'
834 
835        print '<TD COLSPAN="3"><CENTER><TABLE BORDER="1">'
836       
837        partMap={"low":"Start time", "high":"End time"}
838        for part in ("low", "gap", "high"):
839           
840            if part=="gap":
841                print '<TR><TD COLSPAN="6">&nbsp;</TD></TR>'
842            else:
843                print '<TR>'
844                fieldFlag=""
845                count=0
846                for key in TIME_KEYS:
847                    if part=="text":
848                        print "<TD>%s</TD>" % key
849                    elif part in ("low", "high"):
850                        print """<TD><SELECT NAME="%s_%s.time.%s" %s>""" % (axisIndex, 
851                                   part, key.lower(), fieldFlag)
852                        if key=="year":
853                            timeFormat="%.4d"
854                        else:
855                            timeFormat="%.2d"
856
857                        for item in timeBins[count]:
858                            timeItem=timeFormat % item
859                            print """<OPTION VALUE="%s">%s</OPTION>""" % (timeItem, timeItem)
860               
861                        print "</SELECT></TD>"
862                        count=count+1
863
864                print "</TR>"
865        print "</CENTER></TABLE></TD>"
866
867        #print "</TR></TABLE><P>"
868        # Call the javascript to update the date field at start
869        #print """<SCRIPT LANGUAGE="Javascript">resetAllDates(%s)</SCRIPT>""" % (dsetNumber-1)   
870       
871
872
873       
874    def DEPRACATED_displayTemporalDomainOptions(self, options):
875        """
876        Prints a form entry for specifying the temporal domain.
877        """ 
878        # timeDict holds time list dictionaries for start and end times,
879        # time units and time interval for each dataset
880        timeDict={}
881        for dsetNumber in range(1, self.numberOfDatasets+1):
882            (start_time, end_time, (intervalValue, intervalUnits))=options[dsetNumber-1]
883            timeDict["dataset_%s" % dsetNumber]=(start_time, end_time, intervalValue, intervalUnits) 
884 
885        super_index_list=[]
886        timeBins={}
887        for dsetNumber in range(1, self.numberOfDatasets+1):
888            (start_time, end_time, intervalValue, intervalUnits)=timeDict["dataset_%s" % dsetNumber]
889            index_list=[]
890            # Get the bin list for all times
891            timeList=DateTimeManager.createList(start_time, end_time, (intervalValue, intervalUnits), listtype="tuple")
892            timeBins[dsetNumber]=DateTimeManager.getTimeBins(timeList)
893            for i in range(len(start_time)):
894                index_list.append(timeBins[dsetNumber][i].index(start_time[i]))
895            super_index_list=super_index_list+index_list[:]+index_list[:] 
896
897        # Insert javascript functions to do date checking.
898        if len(super_index_list)==12:  super_index_list=super_index_list+[0,0,0,0,0,0,0,0,0,0,0,0]
899        print jsFunctions.js_dateCheckFunctionGroup % tuple(super_index_list)     
900
901        # Temporal domain
902        print '<P><B>Time</B><P><TABLE WIDTH="100%"><TR>'
903        for dsetNumber in range(1, self.numberOfDatasets+1):
904            (intervalValue, intervalUnits)=timeDict["dataset_%s" % dsetNumber][2:]
905            (start_time, end_time)=timeDict["dataset_%s" % dsetNumber][:2]
906            print '<INPUT NAME="timeIntervalUnits_%s" TYPE="hidden" VALUE="%s">' % (dsetNumber, intervalUnits) 
907            print '<INPUT NAME="timeIntervalValue_%s" TYPE="hidden" VALUE="%s">' % (dsetNumber, intervalValue)
908            print '<TD WIDTH="50%">'
909            print '<TABLE BORDER="1"><TR>'
910
911            for part in ("Dataset %s: Start time" % dsetNumber, "start", "text", "end", "End time"):
912                if part in ("Dataset %s: Start time" % dsetNumber, "End time"):
913                    print '<TD COLSPAN="6">%s</TD>' % part
914                else:
915                  fieldFlag=""
916                  count=0
917                  for key in TIME_KEYS:
918                    if part=="text":
919                        print "<TD>%s</TD>" % key
920                    elif part in ("start", "end"):
921                        print """<TD><SELECT NAME="%s%s_%s" %s onChange="checkDate('%s_%s')">""" % (part, 
922                                   key, dsetNumber, fieldFlag, part, dsetNumber)
923                        if key=="year":
924                            timeFormat="%.4d"
925                        else:
926                            timeFormat="%.2d"
927
928                        for item in timeBins[dsetNumber][count]:
929                            timeItem=timeFormat % item
930                            print """<OPTION VALUE="%s">%s</OPTION>""" % (timeItem, timeItem)
931               
932                        print "</SELECT></TD>"
933                        count=count+1
934
935                print "</TR>"
936            print "</TABLE>"
937            print "</TD>"
938
939        print "</TR></TABLE><P>"
940        # Call the javascript to update the date field at start
941        print """<SCRIPT LANGUAGE="Javascript">resetAllDates(%s)</SCRIPT>""" % (dsetNumber-1)   
942       
943
944
945
946    def _chopUpSummary(self, summary):
947        """
948        Chops up the summary string returning a dictionary of items and a
949        list of keys for that dictionary ordered in an appropriate manner.
950        """
951        summaryDict={}
952        orderedKeys=[]
953        for line in summary.split("\n"):
954            if line.find(":")>-1:
955                (key, value)=line.strip().split(":\t")
956                summaryDict[key]=value
957                orderedKeys.append(key) 
958        return (summaryDict, orderedKeys)               
959
960
961    def _displayDatasetSummaryLine(self, summary, optionCategory, sessionID):
962        """
963        Takes a string containing a request summary and parses into suitable
964        HTML format. Prints a summary line for the current request - with clickable
965        links.
966        """
967        # Chop up the request information into a dictionary
968        summaryDict=self._chopUpSummary(summary)[0]
969               
970        # Set up the form for the actions bar to allow various useful functions
971        print """<FORM NAME="actions_bar" method="POST" action="%s">""" % CGI_SCRIPT_URL_PATH
972       
973        # Show return to start link
974        print '<A HREF="%s?action=clearRequest">Return to Start</A>' % CGI_SCRIPT_URL_PATH
975
976        # Get current number of Datasets before showing option of selecting number of datasets
977        # This sets the instance variable that is re-used everywhere from now on - clunky, I know!
978        """self.numberOfDatasets=int(summaryDict["numberOfDatasets"])"""       
979       
980        if sessionID in (None, "None"):
981            sidString=""
982        else:
983            sidString="&sessionID=%s" % sessionID
984       
985        # Show option for number of datasets if more than one allowed
986        """if MAX_NUM_DATASETS>1:
987            print ' | Number of Datasets <SELECT NAME="ndsets" onchange="redirect(this);">'
988           
989            for n in range(1, MAX_NUM_DATASETS+1):
990                if n==self.numberOfDatasets:
991                    print '<OPTION SELECTED VALUE="%s?numberOfDatasets=%s%s">%s</OPTION>' % (CGI_SCRIPT_URL_PATH, n, sidString, n)
992                else:
993                    print '<OPTION VALUE="%s?numberOfDatasets=%s%s">%s</OPTION>' % (CGI_SCRIPT_URL_PATH, n, sidString, n)
994                   
995            print "</SELECT>"  """
996       
997        # Link to view request summary
998        print '&nbsp;| <A HREF="%s?action=viewRequestSummary%s">View Current Request Summary</A>' % (CGI_SCRIPT_URL_PATH, sidString)
999       
1000        # Allow save of request (XML format)
1001        #print ' | <A HREF="%s?action=saveRequest%s">Save Request (xml)</A>' % (CGI_SCRIPT_URL_PATH, sidString)
1002       
1003        # Allow upload of previous request (XML format)
1004        #print ' | <A HREF="%s?action=uploadRequest%s">Upload Request (xml)</A>' % (CGI_SCRIPT_URL_PATH, sidString)
1005       
1006        # Close actions bar form
1007        print "</FORM>"
1008                           
1009        # Set up link to call each section from a URL link so that you
1010        # can switch between one or two datasets
1011        selfCaller="%s?" % CGI_SCRIPT_URL_PATH
1012        firstCall=1
1013        for key in summaryDict.keys():
1014            if key=="targetPage":
1015                extra="%s=%s" % (key, "INSERT_STAGE_HERE")
1016            elif key=="numberOfDatasets":
1017                pass
1018            else:
1019                extra="%s=%s" % (key, summaryDict[key])
1020            if firstCall:
1021                selfCaller=selfCaller+extra
1022                firstCall=None
1023            else:
1024                selfCaller=selfCaller+"&"+extra
1025        """     
1026        if self.numberOfDatasets==1:
1027            selectLink=selfCaller.replace("numberOfDatasets=1", "numberOfDatasets=2")
1028            selectLink=selectLink.replace("targetPage=INSERT_STAGE_HERE", "")
1029            # Temporary measure - send back to start if changed
1030            selectLink="%s?numberOfDatasets=2" % CGI_SCRIPT_URL_PATH
1031            print ' | <A HREF="%s">Select 2 datasets</A>' % selectLink
1032        elif self.numberOfDatasets==2:
1033            selectLink=selfCaller.replace("numberOfDatasets=2", "numberOfDatasets=1")
1034            selectLink=selectLink.replace("targetPage=INSERT_STAGE_HERE", "")
1035            # Temporary measure - send back to start if changed
1036            selectLink="%s?numberOfDatasets=1" % CGI_SCRIPT_URL_PATH
1037            print ' | <A HREF="%s">Deselect dataset 2</A>' % selectLink"""
1038
1039        # Begin an HTML table
1040        """print '<TABLE WIDTH="100%"><TR class="tablerow"><TD COLSPAN="2">CURRENT REQUEST</TD></TR>'
1041
1042        print '<TR class="tablerow">'
1043
1044        # Get option category without number
1045        optcat=optionCategory.split("_")[0]
1046
1047        for count in range(1, self.numberOfDatasets+1):
1048          print '<TD WIDTH="50%%">Dataset %s: ' % count
1049          if not summaryDict.has_key("datasetGroup_%s" % count):
1050            print "None Specified"
1051          elif summaryDict.has_key("datasetGroup_%s" % count):
1052            displayString=' -&gt; <A HREF="%s&targetPage=%s">%s</A>' % (selfCaller, STAGES[0],
1053                           summaryDict["datasetGroup_%s" % count])
1054            print displayString.replace("INSERT_STAGE_HERE", STAGES[0])
1055            if summaryDict.has_key("dataset_%s" % count) and optcat not in ("datasetGroup", "dataset"):
1056                displayString=' -&gt; <A HREF="%s&targetPage=%s">%s</A>' % (selfCaller, STAGES[1],
1057                               summaryDict["dataset_%s" % count])
1058                print displayString.replace("INSERT_STAGE_HERE", STAGES[1])
1059                if summaryDict.has_key("variable_%s" % count) and optcat not in ("datasetGroup", "dataset", "variable"):
1060                    displayString=' -&gt; <A HREF="%s&targetPage=%s">%s</A>' % (selfCaller, STAGES[2],
1061                                   summaryDict["variable_%s" % count])
1062                    print displayString.replace("INSERT_STAGE_HERE", STAGES[2])
1063                    if summaryDict.has_key("horizontalDomain_%s" % count):
1064                        displayString=' -&gt; <A HREF="%s&targetPage=%s">%s</A>' % (selfCaller, STAGES[3],
1065                                        "domain selection")
1066                        print displayString.replace("INSERT_STAGE_HERE", STAGES[3])
1067          print "</TD>"
1068        print "</TR></TABLE>"
1069        print "</I></B><P>"   """
1070
1071
1072    def _sensibleTimeString(self, timeInSeconds):
1073        """
1074        Returns an appropriate string converting timeInSeconds to the most
1075        readable units.
1076        """
1077        if timeInSeconds<1:
1078            return "3 seconds"
1079        if timeInSeconds<60:
1080            return "%d seconds" % timeInSeconds
1081        if timeInSeconds<(60*60):
1082            (m, s)=divmod(timeInSeconds, 60)
1083            return "%s mins %s secs" % (m, s)
1084        else:
1085            (m, s)=divmod(timeInSeconds, 60)
1086            (h, m)=divmod(m, 60)
1087            return "%s hrs %s mins" % (h, m)   
1088
1089
1090    def _pathListFilter(self, pathList):
1091        """
1092        A sensible filter on path lists to a maximum of twenty.
1093        """
1094        if len(pathList)<21:
1095            return pathList
1096        else:
1097            return pathList[:10]+["..."]+pathList[-10:]
1098           
1099
1100    def _displayOutputFileList(self, pathList):
1101        """
1102        Prints links to all the files the user has requested.
1103        """
1104        print "<P><B>Your request has been processed.</B><HR><P>"       
1105        print "<H3>Output information:</H3>"
1106       
1107        nfiles=len(pathList)
1108        pathList=self._pathListFilter(pathList)
1109        if nfiles<21:
1110            displayedString="all the files produced"
1111        else:
1112            displayedString="the first 10 and the last 10 files, the rest follow the same file-naming system"
1113       
1114        plural="s have"
1115        if nfiles==1: plural=" has" 
1116        print "%s file%s been successfully written. The table below shows %s." % (nfiles, plural, displayedString)
1117        print "<TABLE>"
1118       
1119        for file in pathList:
1120            localPath=file
1121            url=translateURI(localPath)
1122               
1123            if localPath=="...":
1124                print """<TR class="tablerow"><TD COLSPAN="3">...</TD>"""
1125            elif url[-3:]=="xml": # No visualise for XML
1126                print """<TR class="tablerow">
1127                         <TD><B>%s</B></TD>
1128                         <TD><A HREF="%s">  Download  </A></TD>
1129                         <TD></TD>
1130                     </TR>""" % (url, url)             
1131            else:
1132                print """<TR class="tablerow">
1133                         <TD><B>%s</B></TD>
1134                         <TD><A HREF="%s">  Download  </A></TD>
1135                         <TD><A HREF="%s?fileURIList=%s&fileVariable_1.1=SELECT_AUTOMATICALLY">  Visualise  </A></TD>
1136                     </TR>""" % (url, url, GEOSPLAT_URL_PATH, localPath)
1137        print "</TABLE>"
1138        print '<P><A HREF="%s">Start a new request</A>.' % CGI_SCRIPT_URL_PATH
1139
1140       
1141    def _displayProcessingSection(self, estimatedDuration, estimatedVolume, sessionID):
1142        """
1143        Method to tell user that there job is underway with details of their selection.
1144        """
1145        print """<H3>Processing Information:</H3>
1146              <P>Your <B>job ID</B> is: %s
1147              <P>The estimated duration of your job is:  %s """ %  (sessionID, self._sensibleTimeString(estimatedDuration))
1148        print "<P>The estimated volume of your job is: %.2f MB" % ((estimatedVolume/1000000)+0.01)
1149        print "<P>Your extraction job is running...</P>"
1150       
1151        if estimatedDuration>60: 
1152            try:
1153                mailAddr=getUserEmail() 
1154                print "<P>You will be emailed at %s when the job has finished and the output is ready." % mailAddr       
1155            except:
1156                pass
1157               
1158        print "<P>Thank you for using the %s." % PACKAGE_NAME
1159        print "<P>If you remain on this page it should eventually produce your output but the server may time out if your request is large.<P>"
1160
1161
1162
1163    def _displayFileNameRuleOptions(self):
1164        """
1165        Prints the options for outputting to a single file or
1166        multiple files.
1167        """
1168        pass
1169       
1170
1171    def _displayRequestSummaryTable(self, summaryDict):
1172        """
1173        Prints a table summarising the current request.
1174        """
1175        print "<H3>The following is a summary of your request</H3>"
1176        print "<TABLE>"
1177        # Chop up the request information into a dictionary
1178        #(summaryDict, orderedKeys)=self._chopUpSummary(summary)
1179       
1180        d=summaryDict
1181        dsgKeys=d["datasetGroups"].keys()
1182        dsKeys=d["datasets"].keys()
1183        varKeys=d["variables"].keys()
1184        axisKeys=d["axes"].keys()
1185       
1186        dsgKeys.sort()
1187        dsKeys.sort()
1188        varKeys.sort()
1189        axisKeys.sort()
1190       
1191        template='<TR class="tablerow"><TD><B>%s%s</B></TD><TD>%s</TD></TR>'
1192       
1193        for dsg in dsgKeys:
1194            print template % ("Dataset Group ", dsg, d["datasetGroups"][dsg])       
1195           
1196            for ds in dsKeys:
1197                (dsgIndex, dsIndex)=re.match(r"^(\d+)\.(\d+)$", ds).groups()
1198                if dsg==dsgIndex:
1199                    print template % ("Dataset ", ds, d["datasets"][ds])
1200                   
1201                for var in varKeys:
1202                    (dsgIndex, dsIndex, varIndex)=re.match(r"^(\d+)\.(\d+)\.(\d+)$", var).groups()
1203                    if dsg==dsgIndex and ds=="%s.%s" % (dsgIndex, dsIndex):
1204                        print template % ("Variable ", var, d["variables"][var])
1205                        if d["outputFormats"].has_key(var):
1206                            print template % ("Output format ", var, d["outputFormats"][var])
1207
1208                        if d["datasetURIs"].has_key(var):
1209                            print template % ("Dataset URI ", var, d["datasetURIs"][var])                       
1210                       
1211                    for axis in axisKeys:
1212                        (dsgIndex, dsIndex, varIndex, axisIndex)=re.match(r"^(\d+)\.(\d+)\.(\d+)\.(\d+)$", axis).groups()
1213                        if (dsg==dsgIndex and ds=="%s.%s" % (dsgIndex, dsIndex)) and var=="%s.%s.%s" % (dsgIndex, dsIndex, varIndex):
1214                            print template % ("Axis ", axis, d["axes"][axis])
1215       
1216            print "<TR><TD>&nbsp;</TD></TR>"
1217
1218       
1219        # Now globals
1220        globalKeys=d["globals"].keys()
1221        globalKeys.sort()
1222       
1223        for key in globalKeys:
1224            print template % (key, "", d["globals"][key])
1225       
1226        print "</TABLE>"
1227       
1228
1229    def _displayConfirmationSection(self, summary):
1230        """
1231        Asks the user to confirm their request.
1232        """
1233        print '<P><INPUT TYPE="submit" NAME="confirm" VALUE="Confirm"> Click the "Confirm" button to fetch your request.<P>'
1234       
1235        self._displayRequestSummaryTable(summary) 
1236
1237        print """<P><INPUT TYPE="submit" NAME="confirm" VALUE="Confirm"> Click the "Confirm" button to fetch your request.
1238        <BR>If you wish to modify your request please press the <I>Back</I> button on your browser.<P>"""
1239        print "</FORM><P>"
1240       
1241       
1242    def _displayOperationOptions(self):
1243        """
1244        Prints a form entry for specifying the required operation.
1245        """
1246        pass
1247       
1248       
1249    def _displayOutputFormatOptions(self, options, sessionID):
1250        """
1251        Prints the available output format options in a form.
1252        """
1253        print """<P><INPUT TYPE="checkbox" NAME="multipleFileOutput">
1254               &nbsp;Use multiple output files [ this is the default large files as limited by the server ]."""
1255               
1256        print '<P>Format&nbsp;<SELECT NAME="outputFormat">'
1257        for format in options:
1258            print "<OPTION>%s</OPTION>" % format
1259        print "</SELECT>"
1260             
1261        print "&nbsp;&nbsp; Note that you should choose NetCDF format if you wish to visualise data."
1262        #print '<P><A HREF="%s?action=saveRequest&sessionID=%s">Get Request XML only.</A>' % (CGI_SCRIPT_URL_PATH, sessionID) 
1263        print '<P><INPUT TYPE="submit" NAME="proceed" VALUE="Proceed"><P>'
1264        print "</FORM><P>"     
1265
1266
1267    def _displayProcessesTable(self):
1268        """
1269        Prints the Processes table of current dx processes running.
1270        """     
1271        pass
1272   
1273       
1274    def _displayUploadRequestOptions(self, sessionID):
1275        """
1276        Generates an upload box for the user to load their own request.
1277        The current request is then overwritten by the uploaded version.
1278        """
1279        """
1280        How might this work.
1281        At any point I can click [ Upload Old Request ] which is an XML file.
1282        It opens a dialogue box for browse and it is saved onto the server and
1283        is referenced as http://localhost/cgi-bin/dxcgi.py?uploadedRequest=something/or/other.xml
1284        Then the dx opens it and parses it in, keeping the sessionID but losing all else!
1285        NOTE: Needs a visible REQUEST_XML_DIR_LOCAL_PATH dir.
1286        """
1287        print '<FORM METHOD="post" ACTION="%s" ENCTYPE="multipart/form-data">' % CGI_SCRIPT_URL_PATH
1288        print "<P>Please provide the location of the request file you wish to upload:"
1289        print """&nbsp;<INPUT TYPE="file" NAME="uploadedFile" VALUE="" SIZE="40">
1290                       <INPUT NAME="action" TYPE="hidden" VALUE="parseUploadedFile">
1291                       <INPUT NAME="sessionID" TYPE="hidden" VALUE="%s">
1292                       <INPUT TYPE="submit" NAME="submit" VALUE="Upload"></FORM><P>""" % sessionID
1293
1294       
1295    def _displaySaveRequestOptions(self, requestString, sessionID):
1296        """
1297        Generates an XML version of the request and writes this to a file locally.
1298        Then the user is pointed to that file in the same way they would be a data
1299        file.
1300        NOTE: Needs a visible REQUEST_XML_DIR_LOCAL_PATH dir.
1301        """
1302        # Write the file to the REQUEST_XML_DIR_LOCAL_PATH
1303        xmlFileName=sessionID+".xml"
1304        xmlFile=open(os.path.join(REQUEST_XML_DIR_LOCAL_PATH, xmlFileName), "w")
1305        xmlFile.write(requestString) # =dataSubsetSpecifier file
1306        xmlFile.close()
1307       
1308        httpFilePath=os.path.join(REQUEST_XML_DIR_URL_PATH, xmlFileName)
1309       
1310        print "<P>You can download your request file from:"
1311        print '<P><A HREF="%s">%s</A><P>' % (httpFilePath, httpFilePath)
1312
1313
1314    def _displayReturnLine(self, sessionID):
1315        """
1316        Displays a link to return to request.
1317        """
1318        print '<P><A HREF="%s?sessionID=%s">Return to your current request</A><P>' % (CGI_SCRIPT_URL_PATH, sessionID)
1319       
1320
1321if __name__=="__main__":
1322    print "Testing DisplayManager.py..."
1323    DisplayManager()
Note: See TracBrowser for help on using the repository browser.