source: TI03-DataExtractor/branches/titania_install/pydxc/DisplayManager.py.orig @ 1520

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI03-DataExtractor/branches/titania_install/pydxc/DisplayManager.py.orig@1709
Revision 1520, 60.2 KB checked in by astephen, 14 years ago (diff)

This is the live version on titania - changes have been made so safest to SVN it.

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       
391        # Predefine what we need for the axis selection in terms of interfaces...
392        knownAxisDict={}               
393               
394        # Loop through keys to get the number of variables
395        axisDict={}
396       
397        # Create some lists to collect time axis info for time validation functions
398        minNames=[]
399        minValues=[]
400        maxValues=[]   
401       
402        for i in range(len(optionCategories)):
403            optionName=optionCategories[i]
404            varIndex=".".join(optionName.split(".")[:-1])[5:]
405            axisIndex=int(optionName.split(".")[-1])
406            items=options[i]
407            [knownAxis, id, longName, units, listType, unused]=items[:6]       
408           
409            if not axisDict.has_key(varIndex):
410                axisDict[varIndex]={"axes":[]}
411            if knownAxis in ("time", "latitude", "longitude"):
412                axisDict[varIndex][knownAxis]=axisIndex
413                if knownAxis=="time":
414                    startTime=getDateTimeComponents(items[6])
415                    endTime=getDateTimeComponents(items[7])
416                    minNames.append(optionName)
417                    minValues.append(startTime[:])
418                    maxValues.append(endTime[:])
419           
420            axisDict[varIndex]["axes"].append([optionName, items])
421             
422        axisDictKeys=axisDict.keys()
423        axisDictKeys.sort()
424        #print axisDictKeys
425       
426        # Now print javascript time functions if needed
427        if len(minNames)>0:
428            minNames=str(minNames)
429            minValues=str([list(lst) for lst in minValues])
430            maxValues=str([list(lst) for lst in maxValues])
431            print jsFunctions.js_timeValidationFunctions % (minNames, minValues, maxValues)
432       
433        # Print options stuff   
434        print "<P><B>PLEASE SELECT: Domain options</B><P>"     
435
436        #print """<A NAME="groupDomainsSelector" onClick="toggleDomainGrouping('on')">Group all similar domains</a> |&nbsp;
437        #<A NAME="ungroupDomainSelector" onClick="toggleDomainGrouping('off')"> Keep  similar domains separate.</a></P>"""
438        # Set up the DIV tag that will allow javascript re-rendering of the selection
439        # interface.
440        print """<DIV ID="domainSelection">""" 
441       
442        print1=""
443        print1=print1+ """<TABLE ID="domainTable">\n"""
444        print1=print1+ """<TR CLASS="tablestyle">
445                        <TD><B>AXIS NAME</B></TD>
446                        <TD><B>RECOGNISED AS</B></TD>
447                        <TD><B>UNITS</B></TD>
448                        <TD COLSPAN="3"><B>SELECTION</B></TD>
449                        <TD><B>INFORMATION</B></TD></TR>\n"""   
450       
451        for key in axisDictKeys:
452
453            varID=summaryDict["variables"][key]
454            dsgKey, dsKey=re.match("(\d+)\.(\d+)", key).groups()
455            datasetGroup=summaryDict["datasetGroups"][dsgKey]
456            dataset=summaryDict["datasets"]["%s.%s" % (dsgKey, dsKey)]
457            print1=print1+ """<TR><TD COLSPAN="7">&nbsp;</TD></TR>\n"""
458            print1=print1+ """<TR CLASS="tablestyle"><TD COLSPAN="7"><B>%s -&gt; %s -&gt; %s</TD></TR>\n""" % (datasetGroup, dataset, varID)       
459       
460            d=axisDict[key]
461            axes=d["axes"]
462           
463            found={}
464            # Check time, lat and lon
465            for ax in ("time", "latitude", "longitude"):
466                if d.has_key(ax):
467                    found[ax]=d[ax]
468           
469            for axis in axes:
470                (optionName, items)=axis
471                varIndex=".".join(optionName.split(".")[:-1])[5:]
472                axisIndex=int(optionName.split(".")[-1])
473                #items=options[i]
474                [knownAxis, id, longName, units, listType, unused]=items[:6]
475
476                if (found.has_key("latitude") and found.has_key("longitude")) and \
477                        axisIndex in (found["latitude"], found["longitude"]):
478               
479                    if found.has_key("used lat lon"):  continue
480               
481                    if axisIndex==found["latitude"]:
482                        # The current axis is latitude so need to get longitude
483                        latItems=items         
484                        latOptionName=optionName       
485                        lonIndex=found["longitude"]
486                       
487                        for x in axes:
488                            if int(x[0].split(".")[-1])==lonIndex:
489                                # Found longitude axis in list
490                                (lonOptionName, lonItems)=x                     
491                       
492                    elif axisIndex==found["longitude"]:
493                        # The current axis is longitude so need to get latitude
494                        lonItems=items
495                        lonOptionName=optionName                       
496                        latIndex=found["latitude"]
497                       
498                        for x in axes:
499                            if int(x[0].split(".")[-1])==latIndex:
500                                # Found latitude axis in list
501                                (latOptionName, latItems)=x             
502                                                               
503                    [latKnownAxis, latId, latLongName, latUnits, latListType, latUnused]=latItems[:6]
504                    northernExtent, southernExtent=latItems[6:8]
505                    [lonKnownAxis, lonId, lonLongName, lonUnits, lonListType, lonUnused]=lonItems[:6]
506                    westernExtent, easternExtent=lonItems[6:8]
507   
508                    found["used lat lon"]=1
509                     
510                    #print '<B>Horizontal Domain</B><P>'
511                     
512                    print1=print1+ """<TR><TD WIDTH="20%%"><B>%s</B></TD>
513                     <TD>%s</TD>
514                     <TD>%s</TD>
515                     <TD></TD>                               
516                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/><BR></TD>
517                     <TD><B></B></TD>
518                     <TD WIDTH="30%%"><FONT SIZE="-2"><B>NOTE ABOUT THE JAVA MAP APPLET:</B>
519<BR>1. The map will not work if you do not have Java enabled on your browser.</FONT></TD>
520                     </TR>\n""" % (latLongName, latKnownAxis, latUnits,
521                                   latOptionName+"_high", northernExtent) 
522                                                                             
523                                                                             
524                    # Check existence of map applet page for this axis ID, otherwise make it
525                    mapHTMLFile=self._checkMapAppletHTMLPage(lonOptionName, latOptionName)
526                   
527                    print1=print1+ """<TR><TD WIDTH="20%%"><B>%s</B></TD>
528                     <TD>%s</TD>
529                     <TD>%s</TD>                     
530                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
531                     <TD><TABLE BORDER="0"><TR><TD ALIGN="LEFT">&nbsp;<B></B></TD><TD><CENTER><B><input type="button" value="Select from map"
532    onClick="newWindow('%s','window2',550,400);"></CENTER></TD></TR></TABLE></TD>                   
533                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
534                     <TD><BR><FONT SIZE="-2">2. This applet is known not to work on certain browsers: Mozilla, Konqueror.</FONT></TD>
535                     </TR>\n""" % (lonLongName, lonKnownAxis, lonUnits,
536                                   lonOptionName+"_low", westernExtent, mapHTMLFile, lonOptionName+"_high",
537                                   easternExtent) 
538                                                   
539                    print1=print1+ """<TR><TD WIDTH="20%%"><B>%s</B></TD>
540                     <TD>%s</TD>
541                     <TD>%s</TD>                     
542                     <TD></TD>                               
543                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
544                     <TD><B>&nbsp;</B></TD>
545                     <TD><FONT SIZE="-2">
546<BR>3. On some browsers you may have to select your subset twice before it registers.</FONT></TD>
547                     </TR>\n""" % ("","","",
548                                   latOptionName+"_low", southernExtent)                   
549
550                elif found.has_key("time") and axisIndex==found["time"]:
551                    (start,end,intervalValue)=items[6:9]
552                   
553                   
554                    print1=print1+ """<TR><TD WIDTH="20%%"><B>%s</B></TD>
555                     <TD>%s</TD>
556                     <TD>%s</TD>\n""" % (longName, knownAxis, units)
557
558                    print1=print1+self._displayTemporalDomainMenus(start, end, intervalValue, units, optionName)
559                    print1=print1+ """<TD><INPUT TYPE="button" NAME="validateTime" VALUE="Validate time selections" onClick='validateTimeSelections("%s")'/></TD></TR>\n""" % optionName
560                             
561                           
562                    """<TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
563                     <TD><TABLE BORDER="0"><TR><TD ALIGN="LEFT">&nbsp;<B>Low</B></TD><TD ALIGN="RIGHT"><B>High</B>&nbsp;</TD></TR></TABLE></TD>                     
564                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
565                     </TR>""" #% (optionName+"_low", start, optionName+"_high", end)   
566                         
567                else:
568                    listType=items[4]
569                    if listType=="full list":
570                        start,end=[items[6], items[-1]]
571                    else:
572                        start,end=items[6:8]
573                    print1=print1+ """<TR><TD WIDTH="20%%"><B>%s</B></TD>
574                     <TD>%s</TD>
575                     <TD>%s</TD>                     
576                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
577                     <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>             
578                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
579                     </TR>\n""" % (longName, knownAxis, units,
580                     optionName+"_low", start, optionName+"_high", end)   
581
582            # Fudge output format for now
583            print1=print1+ """<TR><TD WIDTH="20%%"><B>OUTPUT FORMAT</B></TD>\n"""
584            print1=print1+ """<TD COLSPAN="3">Note that you should choose NetCDF format if you wish to visualise data.</TD>\n"""                     
585            print1=print1+ '<TD COLSPAN="3"><SELECT NAME="outputFormat_%s">\n' % key
586            for format in formatDict["outputFormat_%s" % varIndex]:#("NetCDF", "NASA Ames"):
587                print1=print1+ "<OPTION>%s</OPTION>\n" % format
588            print1=print1+ "</SELECT></TD>\n"
589           
590        print2=""
591        print2=print2+ """<TABLE ID="domainTable">\n"""
592        print2=print2+ """<TR CLASS="tablestyle">
593                        <TD><B>AXIS NAME</B></TD>
594                        <TD><B>RECOGNISED AS</B></TD>
595                        <TD><B>UNITS</B></TD>
596                        <TD COLSPAN="3"><B>SELECTION</B></TD>
597                        <TD><B>INFORMATION</B></TD></TR>\n"""   
598       
599        # Now do the grouped bucket
600        varsAlreadyGrouped=[]
601        for key in axisDictKeys:
602
603            varIndices=re.match("(\d+\.\d+\.\d+)", key).groups()[0]
604           
605            if varIndices in varsAlreadyGrouped: continue
606           
607            varsToLoop=[key]
608            for sameVars in sameBucket:
609                if ("variable_"+varIndices) in sameVars:
610                    varsToLoop=[i.split("_")[-1] for i in sameVars]
611                    varsAlreadyGrouped=varsAlreadyGrouped+varsToLoop
612                    break
613           
614            if len(varsToLoop)>1:
615                domainFlag="SAME DOMAIN: "
616            else:
617                domainFlag=""
618               
619            print2=print2+ """<TR><TD COLSPAN="7">&nbsp;</TD></TR>\n"""
620           
621            for vkey in varsToLoop:
622                varID=summaryDict["variables"][vkey]
623                (dsgKey, dsKey, varKey)=re.match("(\d+)\.(\d+)\.(\d+)", key).groups()       
624                datasetGroup=summaryDict["datasetGroups"][dsgKey]
625                dataset=summaryDict["datasets"]["%s.%s" % (dsgKey, dsKey)]
626                       
627                print2=print2+ """<TR CLASS="tablestyle"><TD COLSPAN="7"><B>%s%s -&gt; %s -&gt; %s</TD></TR>\n""" % (domainFlag, datasetGroup, dataset, varID)     
628       
629            d=axisDict[key]
630            axes=d["axes"]
631           
632            found={}
633            # Check time, lat and lon
634            for ax in ("time", "latitude", "longitude"):
635                if d.has_key(ax):
636                    found[ax]=d[ax]
637           
638            for axis in axes:
639                (optionName, items)=axis
640                varIndex=".".join(optionName.split(".")[:-1])[5:]
641               
642                axisIndex=int(optionName.split(".")[-1])
643                #items=options[i]
644                [knownAxis, id, longName, units, listType, unused]=items[:6]
645
646                if (found.has_key("latitude") and found.has_key("longitude")) and \
647                        axisIndex in (found["latitude"], found["longitude"]):
648               
649                    if found.has_key("used lat lon"):  continue
650               
651                    if axisIndex==found["latitude"]:
652                        # The current axis is latitude so need to get longitude
653                        latItems=items         
654                        latOptionName=optionName       
655                        lonIndex=found["longitude"]
656                       
657                        for x in axes:
658                            if int(x[0].split(".")[-1])==lonIndex:
659                                # Found longitude axis in list
660                                (lonOptionName, lonItems)=x                     
661                       
662                    elif axisIndex==found["longitude"]:
663                        # The current axis is longitude so need to get latitude
664                        lonItems=items
665                        lonOptionName=optionName                       
666                        latIndex=found["latitude"]
667                       
668                        for x in axes:
669                            if int(x[0].split(".")[-1])==latIndex:
670                                # Found latitude axis in list
671                                (latOptionName, latItems)=x             
672                                                               
673                    [latKnownAxis, latId, latLongName, latUnits, latListType, latUnused]=latItems[:6]
674                    northernExtent, southernExtent=latItems[6:8]
675                    [lonKnownAxis, lonId, lonLongName, lonUnits, lonListType, lonUnused]=lonItems[:6]
676                    westernExtent, easternExtent=lonItems[6:8]
677   
678                    found["used lat lon"]=1
679                     
680                    #print '<B>Horizontal Domain</B><P>'
681                     
682                    print2=print2+ """<TR><TD WIDTH="20%%"><B>%s</B></TD>
683                     <TD>%s</TD>
684                     <TD>%s</TD>
685                     <TD></TD>                               
686                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/><BR></TD>
687                     <TD><B></B></TD>
688                     <TD WIDTH="30%%"><FONT SIZE="-2"><B>NOTE ABOUT THE JAVA MAP APPLET:</B>
689<BR>1. The map will not work if you do not have Java enabled on your browser.</FONT></TD>
690                     </TR>\n""" % (latLongName, latKnownAxis, latUnits,
691                                   latOptionName+"_high", northernExtent) 
692                                                                             
693                                                                             
694                    # Check existence of map applet page for this axis ID, otherwise make it
695                    mapHTMLFile=self._checkMapAppletHTMLPage(lonOptionName, latOptionName)
696                   
697                    print2=print2+ """<TR><TD WIDTH="20%%"><B>%s</B></TD>
698                     <TD>%s</TD>
699                     <TD>%s</TD>                     
700                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
701                     <TD><TABLE BORDER="0"><TR><TD ALIGN="LEFT">&nbsp;<B></B></TD><TD><CENTER><B><input type="button" value="Select from map"
702    onClick="newWindow('%s','window2',550,400);"></CENTER></TD></TR></TABLE></TD>                   
703                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
704                     <TD><BR><FONT SIZE="-2">2. This applet is known not to work on certain browsers: Mozilla, Konqueror.</FONT></TD>
705                     </TR>\n""" % (lonLongName, lonKnownAxis, lonUnits,
706                                   lonOptionName+"_low", westernExtent, mapHTMLFile, lonOptionName+"_high",
707                                   easternExtent) 
708                                                   
709                    print2=print2+ """<TR><TD WIDTH="20%%"><B>%s</B></TD>
710                     <TD>%s</TD>
711                     <TD>%s</TD>                     
712                     <TD></TD>                               
713                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
714                     <TD><B>&nbsp;</B></TD>
715                     <TD><FONT SIZE="-2">
716<BR>3. On some browsers you may have to select your subset twice before it registers.</FONT></TD>
717                     </TR>\n""" % ("","","",
718                                   latOptionName+"_low", southernExtent)                   
719
720                elif found.has_key("time") and axisIndex==found["time"]:
721                    (start,end,intervalValue)=items[6:9]
722                   
723                   
724                    print2=print2+ """<TR><TD WIDTH="20%%"><B>%s</B></TD>
725                     <TD>%s</TD>
726                     <TD>%s</TD>\n""" % (longName, knownAxis, units)
727
728                    print2=print2+self._displayTemporalDomainMenus(start, end, intervalValue, units, optionName)
729                    print2=print2+ """<TD><INPUT TYPE="button" NAME="validateTime" VALUE="Validate time selections" onClick='validateTimeSelections("%s")'/></TD></TR>\n""" % optionName
730                             
731                           
732                    """<TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
733                     <TD><TABLE BORDER="0"><TR><TD ALIGN="LEFT">&nbsp;<B>Low</B></TD><TD ALIGN="RIGHT"><B>High</B>&nbsp;</TD></TR></TABLE></TD>                     
734                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
735                     </TR>""" #% (optionName+"_low", start, optionName+"_high", end)   
736                         
737                else:
738                    start,end=items[6:8]
739                    print2=print2+ """<TR><TD WIDTH="20%%"><B>%s</B></TD>
740                     <TD>%s</TD>
741                     <TD>%s</TD>                     
742                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
743                     <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>             
744                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
745                     </TR>\n""" % (longName, knownAxis, units,
746                     optionName+"_low", start, optionName+"_high", end)   
747
748            # Fudge output format for now
749            print2=print2+ """<TR><TD WIDTH="20%%"><B>OUTPUT FORMAT</B></TD>\n"""
750            print2=print2+ """<TD COLSPAN="3">Note that you should choose NetCDF format if you wish to visualise data.</TD>\n"""                     
751            print2=print2+ '<TD COLSPAN="3"><SELECT NAME="outputFormat_%s">\n' % key
752            for format in formatDict["outputFormat_%s" % varIndex]:#("NetCDF", "NASA Ames"):
753                print2=print2+ "<OPTION>%s</OPTION>\n" % format
754            print2=print2+ "</SELECT></TD>\n"
755
756                     
757                     
758        print1=print1+ """</TABLE>\n"""
759        print2=print2+ """</TABLE>\n"""
760       
761        #print print1
762        print "</DIV>"
763
764        escapedprint1=print1.replace("\"", "\\\"")
765        escapedprint2=print2.replace("\"", "\\\"")
766
767        print """<SCRIPT language="javascript">
768        function toggleDomainGrouping(grouper) {
769            var domainElement=document.getElementById("domainSelection");
770            var ungrouped="";
771            var grouped=""; """
772        for line in escapedprint1.split("\n"):
773            print """            ungrouped+="%s"; """ % line       
774           
775        for line in escapedprint2.split("\n"):
776            print """            grouped+="%s"; """ % line
777               
778        print """            if (grouper=="off") {     
779                 domainElement.innerHTML=ungrouped;
780            } else {
781                 domainElement.innerHTML=grouped;
782            }
783        }
784        toggleDomainGrouping("off");
785            </SCRIPT> """
786
787        print """<P><INPUT TYPE="checkbox" NAME="multipleFileOutput">
788               &nbsp;Use multiple output files [ this is the default large files as limited by the server ]."""
789               
790
791    def  _checkMapAppletHTMLPage(self, lonAxisID, latAxisID):
792        """
793        Generates a map applet HTML Page if one doesn't already exist.
794        """
795        mapAppletTemplatePath=MAP_APPLET_TEMPLATE_LOCAL_PATH
796        (mapAppletDir, templateFile)=os.path.split(mapAppletTemplatePath)
797        axisNumbers=lonAxisID[5:]+"_"+latAxisID[5:]
798        axisMapHTMLPage=os.path.join(mapAppletDir, "map_%s.html" % axisNumbers)
799        if not os.path.isfile(axisMapHTMLPage):
800            template=open(mapAppletTemplatePath).read()
801            outfile=open(axisMapHTMLPage, "w")
802            outfile.write(template % (lonAxisID, lonAxisID, latAxisID, latAxisID))
803            outfile.close()
804            os.chmod(axisMapHTMLPage, 0644)
805        urlToAxisMapHTMLPage=os.path.join(os.path.split(MAP_APPLET_TEMPLATE_URL_PATH)[0], os.path.split(axisMapHTMLPage)[-1])
806        return urlToAxisMapHTMLPage
807
808
809    def _displayUploadForm(self, sessionID):
810        """
811        Displays a form entry for browsing the local system
812        to upload a file. UPLOAD_TEMP_DIR needs to be configured in
813        the clientConfig.py module.
814        """
815        print '<FORM METHOD="post" ACTION="%s" ENCTYPE="multipart/form-data">' % CGI_SCRIPT_URL_PATH
816        print "<P>Please provide the location of the request file you wish to upload:"
817        print """&nbsp;<INPUT TYPE="file" NAME="uploadedFile" VALUE="" SIZE="40">
818                       <INPUT NAME="action" TYPE="hidden" VALUE="parseUploadedFile">
819                       <INPUT NAME="sessionID" TYPE="hidden" VALUE="%s">
820                       <INPUT TYPE="submit" NAME="submit" VALUE="Upload"></FORM><P>\n<FORM>""" % sessionID
821
822
823    def _displayMetadataForm(self, fileName, fileFormat, varList, globalMetadata):
824        """
825        Displays the metadata in the data file.
826        """
827        #print """<INPUT NAME="variable_1" TYPE="hidden" VALUE="pqn">"""
828        print """<P>Thank you for uploading your file to the NetCDF-NASA Ames convertor.
829               The following information has been extracted from the file:
830               <BR><B>Filename:     %s</B>
831               <BR><B>File format:  %s</B>
832               <P><B><FONT SIZE="+1">Variables:</FONT></B>
833               <BR>Select the variables that you wish convert (Default=ALL):<P>""" % (fileName, fileFormat)
834       
835        # Now print the variable list as a form
836        varCount=1
837        print '<BR><INPUT TYPE="hidden" NAME="selectionsMade" VALUE="complete">'
838        for var in varList:
839            longName, varID=var
840            varString=varID
841            displayVar="%s &nbsp;&nbsp;{%s}" % (longName, varID)
842            if varID in ("None", "", None):
843                varString=longName
844                displayVar=varString
845            print '<BR><INPUT TYPE="checkbox" NAME="variable_%s" VALUE="%s" CHECKED>%s</INPUT>' % (varCount, varString, displayVar)
846            #print "<BR>%s (%s)" % tuple(var) # prints var id and long_name
847            varCount=varCount+1
848       
849        outFileMap={"NetCDF":"NASA Ames", "NASA Ames":"NetCDF"}   
850        # Now print metadata
851        print """<P><BR><B><FONT SIZE="+1">Global Metadata</FONT></B>
852              <BR>The following global metadata will be written to your output %s file(s):<P>""" % outFileMap[fileFormat]
853             
854        print '<TABLE BORDER="0">'
855        maxSize=10
856        for item in globalMetadata:
857            key, value=item
858            if key=="VNAME":
859                continue
860                displayKey="VNAME Variables from NASA Ames (modify below to rename)"
861            elif key=="ANAME":
862                continue
863                if value!=None:
864                    displayKey="ANAME Auxiliary Variables from NASA Ames (modify below to rename)"
865                else:
866                    break
867            else:
868                displayKey=key
869               
870            print '<TR><TD WIDTH="25"><B>%s: </B>' % displayKey
871           
872            #print str(type(value))
873            if type(value)!=type(""):
874                # deal with list type by indexing each part
875                try:
876                    value=value.data
877                except:
878                    pass
879                   
880                partCount=1
881                lengthList=[len(str(i)) for i in value]
882                total=0
883                for i in lengthList: total=total+i
884                #print "<P>TOTAL:", total
885                if total<60:
886                    # Put all on one line
887                    print "<BR>"
888                    separator=""
889                    sizeString="%s" % (max(lengthList)+5)
890                    inputType="textbox"
891                else:
892                    separator="<BR>"
893                    sizeString="100"
894                    inputType="textbox"
895                   
896                #print dir(value), value.data
897                for part in value:
898                    if key in ("VNAMEAAAAAAAAAAA", "ANAMEAAAAAAAA"): # if variable names
899                        partName="%s-RENAMED_%s" % (key, partCount)
900                    else:
901                        partName="%s_%s" % (key, partCount)
902                    part=str(part)                 
903                    print '%s<INPUT TYPE="%s" NAME="%s" VALUE="%s" SIZE="%s"/>' % (separator, inputType, partName, part, sizeString)
904                    partCount=partCount+1
905                print "</TD></TR>"
906               
907            else:
908                size=len(value)     
909                if size>100:
910                    inputType="textbox"
911                else:
912                    inputType="textbox"
913                print '<INPUT TYPE="%s" NAME="%s" VALUE="%s" SIZE="100"/></TD></TR>' % (inputType, key, value)
914            #print "<BR>%s = %s" % tuple(item) # prints name and value of metadata item
915        print "</TABLE>"
916
917
918
919    def _displayOutputPage(self, outputFilePaths):
920        """
921        Displays full HTML page with a link to the output file.
922        """
923        if len(outputFilePaths)==1:
924            file=outputFilePaths[0]
925            print "<P><B>Your output file is available at:</B>"
926            print """<P><A HREF="%s">%s</A><P>""" % (file, file)
927        else:
928            print "<P><B>Your output files are available at:</B><P>"
929            for file in outputFilePaths:
930                print """<A HREF="%s">%s</A><BR>""" % (file, file)
931       
932                     
933    def _displayFinalMessage(self, outputMessage=[]):
934        """
935        Prints an a message for the final page.
936        """
937        outputString=""
938        for i in outputMessage: outputString=outputString+"***LINEBREAK***"+str(i)
939        outputString=outputString.replace("<", "&LT;")
940        outputString=outputString.replace(">", "&GT;")
941        outputString=outputString.replace("***LINEBREAK***", "<P>")
942        outputString=outputString.replace("\n\n", "<P>")
943        outputString=outputString.replace("\n", "<BR>")
944       
945        print """<P>Thank you for using <B>%s</B>. You can now download your output file.
946                 <BR>Any output from the conversion package is printed below:
947                 <P><TABLE BORDER="1"><TR><TD BGCOLOR="#EEEEEE"><KBD>%s</KBD></TD></TR></TABLE><P>
948              """ % (PACKAGE_NAME, outputString)
949
950
951    def _displayFeatureOptions(self):
952        """
953        Prints the available Features in a table.
954        """   
955        pass
956       
957       
958    def _displayHorizontalDomainOptions(self, bounds):
959        """
960        Prints a form entry for specifying the horizontal domain.
961        """
962        (northernExtent, westernExtent, southernExtent, easternExtent)=bounds
963
964        # Horizontal Domain
965        print '<B>Horizontal Domain</B><P>'
966
967        print """<TABLE><TR><TD WIDTH="20%%"></TD><TD WIDTH="20%%"></TD>
968<TD WIDTH="20%%" ALIGN="CENTER"><INPUT TYPE="text" NAME="northernExtent" VALUE="%s" SIZE="6"><FONT SIZE="-1"><BR> Northern Extent </FONT></TD>
969<TD WIDTH="20%%"></TD><TD WIDTH="20%%"></TD></TR>
970<TR><TD><INPUT TYPE="text" NAME="westernExtent" VALUE="%s" SIZE="6"><FONT SIZE="-1"><BR> Western Extent </FONT></TD>
971<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>
972<TD ALIGN="RIGHT"><INPUT TYPE="text" NAME="easternExtent" VALUE="%s" SIZE="6"><FONT SIZE="-1"><BR> Eastern Extent </FONT></TD>
973<TD></TD>
974<TR><TD></TD><TD></TD>
975<TD ALIGN="CENTER"><INPUT TYPE="text" NAME="southernExtent" VALUE="%s" SIZE="6"><FONT SIZE="-1"><BR> Southern Extent </FONT></TD>
976<TD></TD><TD></TD></TR></TABLE>
977<input type="button" value="Select from map"
978    onClick="newWindow('%s','window2',550,400);">
979<TABLE><TR><TD CLASS="tablestyle">
980<B>NOTE ABOUT THE JAVA MAP APPLET:</B> 
981<BR>1. The map will not work if you do not have Java enabled on your browser.
982<BR>2. This applet is known not to work on certain browsers: Mozilla, Konqueror.
983<BR>3. On some browsers you may have to select your subset twice before it registers.<P>
984</TD></TR></TABLE>""" % (northernExtent, westernExtent, easternExtent, southernExtent, MAP_APPLET_URL_PATH)
985
986        helpLink=os.path.join(WEB_EXTRAS_URL_PATH, "help_page.html#interpolation")
987        print """<P>[&nbsp;<A NAME="%s" onClick="help('%s')">Note about interpolation methods.</A>&nbsp;]<P>""" % (helpLink, helpLink)
988
989       
990    def _displayVerticalSpatialDomainOptions(self, options):
991        """
992        Prints a form entry for specifying the vertical domain.
993        """
994        print '<P><B>Vertical Domain</B><P><TABLE WIDTH="100%"><TR>'
995        for dsetNumber in range(1, self.numberOfDatasets+1):
996            (levels, vertical_units)=options[dsetNumber-1]
997
998            if type(levels)==type(""): levels=(levels,)
999            if len(levels)>3:
1000                levboxheight=3
1001            else:
1002                levboxheight=len(levels)
1003
1004            print """<TD WIDTH="50%%">Levels<BR><SELECT MULTIPLE NAME="verticalDomain_%s"
1005                  SIZE="%s" WIDTH="50" VALUE="%s">""" % (dsetNumber, levboxheight, levels[0])
1006            levSelected=" SELECTED"
1007            for level in levels:
1008                print """<OPTION VALUE="%s"%s>%s</OPTION>""" % (level, levSelected, level)
1009                levSelected=""
1010            print "</SELECT>"
1011            print '<INPUT NAME="verticalUnits" TYPE="hidden" VALUE="hPa">'
1012            print "</TD>"
1013        print "</TR></TABLE>"
1014
1015
1016    def _displayTemporalDomainMenus(self, startTime, endTime, intervalValue, intervalUnits, axisIndex):
1017        """
1018        Displays a set of menus for entering the date and time limits for this axis.
1019        """ 
1020        startTime=getDateTimeComponents(startTime)
1021        endTime=getDateTimeComponents(endTime)
1022        super_index_list=[]
1023        index_list=[]
1024       
1025        # Get the bin list for all times
1026        timeList=DateTimeManager.createList(startTime, endTime, (intervalValue, intervalUnits), listtype="tuple")
1027        timeBins=DateTimeManager.getTimeBins(timeList)
1028       
1029        for i in range(len(startTime)):
1030            index_list.append(timeBins[i].index(startTime[i]))
1031        #super_index_list=super_index_list+index_list[:]+index_list[:]
1032
1033        # Insert javascript functions to do date checking.
1034        #if len(super_index_list)==12:  super_index_list=super_index_list+[0,0,0,0,0,0,0,0,0,0,0,0]
1035        #print jsFunctions.js_dateCheckFunctionGroup % tuple(super_index_list)     
1036
1037        # Temporal domain
1038        #print '<P><B>Time</B><P><TABLE WIDTH="100%"><TR>'
1039        #print '<INPUT NAME="timeIntervalUnits_%s" TYPE="hidden" VALUE="%s">' % (axisIndex, intervalUnits)
1040        #print '<INPUT NAME="timeIntervalValue_%s" TYPE="hidden" VALUE="%s">' % (axisIndex, intervalValue)
1041        #print '<TD WIDTH="50%">'
1042        #print '<TABLE BORDER="1"><TR>'
1043        print1=""
1044        print1=print1+ '<TD COLSPAN="3"><CENTER><TABLE BORDER="1">\n'
1045       
1046        partMap={"low":"Start time", "high":"End time"}
1047        for part in ("low", "gap", "high"):
1048           
1049            if part=="gap":
1050                print1=print1+ '<TR><TD COLSPAN="6">&nbsp;</TD></TR>\n'
1051            else:
1052                print1=print1+ '<TR>\n'
1053                fieldFlag=""
1054                count=0
1055                for key in TIME_KEYS:
1056                    if part=="text":
1057                        print1=print1+ "<TD>%s</TD>\n" % key
1058                    elif part in ("low", "high"):
1059                        print1=print1+ """<TD><SELECT NAME="%s_%s.time.%s"%s>\n""" % (axisIndex,
1060                                   part, key.lower(), fieldFlag)
1061                        if key=="year":
1062                            timeFormat="%.4d"
1063                        else:
1064                            timeFormat="%.2d"
1065
1066                        for item in timeBins[count]:
1067                            timeItem=timeFormat % item
1068                            print1=print1+ """<OPTION VALUE="%s">%s</OPTION>\n""" % (timeItem, timeItem)
1069               
1070                        print1=print1+ "</SELECT></TD>\n"
1071                        count=count+1
1072
1073                print1=print1+ "</TR>\n"
1074        print1=print1+ "</CENTER></TABLE></TD>\n"
1075
1076        return print1
1077        #print "</TR></TABLE><P>"
1078        # Call the javascript to update the date field at start
1079        #print """<SCRIPT LANGUAGE="Javascript">resetAllDates(%s)</SCRIPT>""" % (dsetNumber-1)   
1080       
1081
1082
1083       
1084    def DEPRACATED_displayTemporalDomainOptions(self, options):
1085        """
1086        Prints a form entry for specifying the temporal domain.
1087        """ 
1088        # timeDict holds time list dictionaries for start and end times,
1089        # time units and time interval for each dataset
1090        timeDict={}
1091        for dsetNumber in range(1, self.numberOfDatasets+1):
1092            (start_time, end_time, (intervalValue, intervalUnits))=options[dsetNumber-1]
1093            timeDict["dataset_%s" % dsetNumber]=(start_time, end_time, intervalValue, intervalUnits)
1094 
1095        super_index_list=[]
1096        timeBins={}
1097        for dsetNumber in range(1, self.numberOfDatasets+1):
1098            (start_time, end_time, intervalValue, intervalUnits)=timeDict["dataset_%s" % dsetNumber]
1099            index_list=[]
1100            # Get the bin list for all times
1101            timeList=DateTimeManager.createList(start_time, end_time, (intervalValue, intervalUnits), listtype="tuple")
1102            timeBins[dsetNumber]=DateTimeManager.getTimeBins(timeList)
1103            for i in range(len(start_time)):
1104                index_list.append(timeBins[dsetNumber][i].index(start_time[i]))
1105            super_index_list=super_index_list+index_list[:]+index_list[:]
1106
1107        # Insert javascript functions to do date checking.
1108        if len(super_index_list)==12:  super_index_list=super_index_list+[0,0,0,0,0,0,0,0,0,0,0,0]
1109        print jsFunctions.js_dateCheckFunctionGroup % tuple(super_index_list)     
1110
1111        # Temporal domain
1112        print '<P><B>Time</B><P><TABLE WIDTH="100%"><TR>'
1113        for dsetNumber in range(1, self.numberOfDatasets+1):
1114            (intervalValue, intervalUnits)=timeDict["dataset_%s" % dsetNumber][2:]
1115            (start_time, end_time)=timeDict["dataset_%s" % dsetNumber][:2]
1116            print '<INPUT NAME="timeIntervalUnits_%s" TYPE="hidden" VALUE="%s">' % (dsetNumber, intervalUnits)
1117            print '<INPUT NAME="timeIntervalValue_%s" TYPE="hidden" VALUE="%s">' % (dsetNumber, intervalValue)
1118            print '<TD WIDTH="50%">'
1119            print '<TABLE BORDER="1"><TR>'
1120
1121            for part in ("Dataset %s: Start time" % dsetNumber, "start", "text", "end", "End time"):
1122                if part in ("Dataset %s: Start time" % dsetNumber, "End time"):
1123                    print '<TD COLSPAN="6">%s</TD>' % part
1124                else:
1125                  fieldFlag=""
1126                  count=0
1127                  for key in TIME_KEYS:
1128                    if part=="text":
1129                        print "<TD>%s</TD>" % key
1130                    elif part in ("start", "end"):
1131                        print """<TD><SELECT NAME="%s%s_%s" %s onChange="checkDate('%s_%s')">""" % (part,
1132                                   key, dsetNumber, fieldFlag, part, dsetNumber)
1133                        if key=="year":
1134                            timeFormat="%.4d"
1135                        else:
1136                            timeFormat="%.2d"
1137
1138                        for item in timeBins[dsetNumber][count]:
1139                            timeItem=timeFormat % item
1140                            print """<OPTION VALUE="%s">%s</OPTION>""" % (timeItem, timeItem)
1141               
1142                        print "</SELECT></TD>"
1143                        count=count+1
1144
1145                print "</TR>"
1146            print "</TABLE>"
1147            print "</TD>"
1148
1149        print "</TR></TABLE><P>"
1150        # Call the javascript to update the date field at start
1151        print """<SCRIPT LANGUAGE="Javascript">resetAllDates(%s)</SCRIPT>""" % (dsetNumber-1)   
1152       
1153
1154
1155
1156    def _chopUpSummary(self, summary):
1157        """
1158        Chops up the summary string returning a dictionary of items and a
1159        list of keys for that dictionary ordered in an appropriate manner.
1160        """
1161        summaryDict={}
1162        orderedKeys=[]
1163        for line in summary.split("\n"):
1164            if line.find(":")>-1:
1165                (key, value)=line.strip().split(":\t")
1166                summaryDict[key]=value
1167                orderedKeys.append(key)
1168        return (summaryDict, orderedKeys)               
1169
1170
1171    def _displayDatasetSummaryLine(self, summary, optionCategory, sessionID):
1172        """
1173        Takes a string containing a request summary and parses into suitable
1174        HTML format. Prints a summary line for the current request - with clickable
1175        links.
1176        """
1177        # Chop up the request information into a dictionary
1178        summaryDict=self._chopUpSummary(summary)[0]
1179               
1180        # Set up the form for the actions bar to allow various useful functions
1181        print """<FORM NAME="actions_bar" method="POST" action="%s">""" % CGI_SCRIPT_URL_PATH
1182       
1183        # Show return to start link
1184        print '<A HREF="%s?action=clearRequest">Return to Start</A>' % CGI_SCRIPT_URL_PATH
1185
1186        # Get current number of Datasets before showing option of selecting number of datasets
1187        # This sets the instance variable that is re-used everywhere from now on - clunky, I know!
1188        """self.numberOfDatasets=int(summaryDict["numberOfDatasets"])"""       
1189       
1190        if sessionID in (None, "None"):
1191            sidString=""
1192        else:
1193            sidString="&sessionID=%s" % sessionID
1194       
1195        # Show option for number of datasets if more than one allowed
1196        """if MAX_NUM_DATASETS>1:
1197            print ' | Number of Datasets <SELECT NAME="ndsets" onchange="redirect(this);">'
1198           
1199            for n in range(1, MAX_NUM_DATASETS+1):
1200                if n==self.numberOfDatasets:
1201                    print '<OPTION SELECTED VALUE="%s?numberOfDatasets=%s%s">%s</OPTION>' % (CGI_SCRIPT_URL_PATH, n, sidString, n)
1202                else:
1203                    print '<OPTION VALUE="%s?numberOfDatasets=%s%s">%s</OPTION>' % (CGI_SCRIPT_URL_PATH, n, sidString, n)
1204                   
1205            print "</SELECT>"  """
1206       
1207        # Link to view request summary
1208        print '&nbsp;| <A HREF="%s?action=viewRequestSummary%s">View Current Request Summary</A>' % (CGI_SCRIPT_URL_PATH, sidString)
1209       
1210        # Allow save of request (XML format)
1211        #print ' | <A HREF="%s?action=saveRequest%s">Save Request (xml)</A>' % (CGI_SCRIPT_URL_PATH, sidString)
1212       
1213        # Allow upload of previous request (XML format)
1214        #print ' | <A HREF="%s?action=uploadRequest%s">Upload Request (xml)</A>' % (CGI_SCRIPT_URL_PATH, sidString)
1215       
1216        # Close actions bar form
1217        print "</FORM>"
1218                           
1219        # Set up link to call each section from a URL link so that you
1220        # can switch between one or two datasets
1221        selfCaller="%s?" % CGI_SCRIPT_URL_PATH
1222        firstCall=1
1223        for key in summaryDict.keys():
1224            if key=="targetPage":
1225                extra="%s=%s" % (key, "INSERT_STAGE_HERE")
1226            elif key=="numberOfDatasets":
1227                pass
1228            else:
1229                extra="%s=%s" % (key, summaryDict[key])
1230            if firstCall:
1231                selfCaller=selfCaller+extra
1232                firstCall=None
1233            else:
1234                selfCaller=selfCaller+"&"+extra
1235        """     
1236        if self.numberOfDatasets==1:
1237            selectLink=selfCaller.replace("numberOfDatasets=1", "numberOfDatasets=2")
1238            selectLink=selectLink.replace("targetPage=INSERT_STAGE_HERE", "")
1239            # Temporary measure - send back to start if changed
1240            selectLink="%s?numberOfDatasets=2" % CGI_SCRIPT_URL_PATH
1241            print ' | <A HREF="%s">Select 2 datasets</A>' % selectLink
1242        elif self.numberOfDatasets==2:
1243            selectLink=selfCaller.replace("numberOfDatasets=2", "numberOfDatasets=1")
1244            selectLink=selectLink.replace("targetPage=INSERT_STAGE_HERE", "")
1245            # Temporary measure - send back to start if changed
1246            selectLink="%s?numberOfDatasets=1" % CGI_SCRIPT_URL_PATH
1247            print ' | <A HREF="%s">Deselect dataset 2</A>' % selectLink"""
1248
1249        # Begin an HTML table
1250        """print '<TABLE WIDTH="100%"><TR class="tablerow"><TD COLSPAN="2">CURRENT REQUEST</TD></TR>'
1251
1252        print '<TR class="tablerow">'
1253
1254        # Get option category without number
1255        optcat=optionCategory.split("_")[0]
1256
1257        for count in range(1, self.numberOfDatasets+1):
1258          print '<TD WIDTH="50%%">Dataset %s: ' % count
1259          if not summaryDict.has_key("datasetGroup_%s" % count):
1260            print "None Specified"
1261          elif summaryDict.has_key("datasetGroup_%s" % count):
1262            displayString=' -&gt; <A HREF="%s&targetPage=%s">%s</A>' % (selfCaller, STAGES[0],
1263                           summaryDict["datasetGroup_%s" % count])
1264            print displayString.replace("INSERT_STAGE_HERE", STAGES[0])
1265            if summaryDict.has_key("dataset_%s" % count) and optcat not in ("datasetGroup", "dataset"):
1266                displayString=' -&gt; <A HREF="%s&targetPage=%s">%s</A>' % (selfCaller, STAGES[1],
1267                               summaryDict["dataset_%s" % count])
1268                print displayString.replace("INSERT_STAGE_HERE", STAGES[1])
1269                if summaryDict.has_key("variable_%s" % count) and optcat not in ("datasetGroup", "dataset", "variable"):
1270                    displayString=' -&gt; <A HREF="%s&targetPage=%s">%s</A>' % (selfCaller, STAGES[2],
1271                                   summaryDict["variable_%s" % count])
1272                    print displayString.replace("INSERT_STAGE_HERE", STAGES[2])
1273                    if summaryDict.has_key("horizontalDomain_%s" % count):
1274                        displayString=' -&gt; <A HREF="%s&targetPage=%s">%s</A>' % (selfCaller, STAGES[3],
1275                                        "domain selection")
1276                        print displayString.replace("INSERT_STAGE_HERE", STAGES[3])
1277          print "</TD>"
1278        print "</TR></TABLE>"
1279        print "</I></B><P>"   """
1280
1281
1282    def _sensibleTimeString(self, timeInSeconds):
1283        """
1284        Returns an appropriate string converting timeInSeconds to the most
1285        readable units.
1286        """
1287        if timeInSeconds<1:
1288            return "3 seconds"
1289        if timeInSeconds<60:
1290            return "%d seconds" % timeInSeconds
1291        if timeInSeconds<(60*60):
1292            (m, s)=divmod(timeInSeconds, 60)
1293            return "%s mins %s secs" % (m, s)
1294        else:
1295            (m, s)=divmod(timeInSeconds, 60)
1296            (h, m)=divmod(m, 60)
1297            return "%s hrs %s mins" % (h, m)   
1298
1299
1300    def _pathListFilter(self, pathList):
1301        """
1302        A sensible filter on path lists to a maximum of twenty.
1303        """
1304        if len(pathList)<21:
1305            return pathList
1306        else:
1307            return pathList[:10]+["..."]+pathList[-10:]
1308           
1309
1310    def _displayOutputFileList(self, pathList):
1311        """
1312        Prints links to all the files the user has requested.
1313        """
1314        print "<P><B>Your request has been processed.</B><HR><P>"       
1315        print "<H3>Output information:</H3>"
1316       
1317        nfiles=len(pathList)
1318        pathList=self._pathListFilter(pathList)
1319        if nfiles<21:
1320            displayedString="all the files produced"
1321        else:
1322            displayedString="the first 10 and the last 10 files, the rest follow the same file-naming system"
1323       
1324        plural="s have"
1325        if nfiles==1: plural=" has" 
1326        print "%s file%s been successfully written. The table below shows %s." % (nfiles, plural, displayedString)
1327        print "<TABLE>"
1328       
1329        for file in pathList:
1330            localPath=file
1331            url=translateURI(localPath)
1332               
1333            if localPath=="...":
1334                print """<TR class="tablerow"><TD COLSPAN="3">...</TD>"""
1335            elif url[-3:]=="xml": # No visualise for XML
1336                print """<TR class="tablerow">
1337                         <TD><B>%s</B></TD>
1338                         <TD><A HREF="%s">  Download  </A></TD>
1339                         <TD></TD>
1340                     </TR>""" % (url, url)             
1341            else:
1342                print """<TR class="tablerow">
1343                         <TD><B>%s</B></TD>
1344                         <TD><A HREF="%s">  Download  </A></TD>
1345                         <TD><A HREF="%s?fileURIList=%s&fileVariable_1.1=SELECT_AUTOMATICALLY">  Visualise  </A></TD>
1346                     </TR>""" % (url, url, GEOSPLAT_URL_PATH, localPath)
1347        print "</TABLE>"
1348        print '<P><A HREF="%s">Start a new request</A>.' % CGI_SCRIPT_URL_PATH
1349
1350       
1351    def _displayProcessingSection(self, estimatedDuration, estimatedVolume, sessionID):
1352        """
1353        Method to tell user that there job is underway with details of their selection.
1354        """
1355        print """<H3>Processing Information:</H3>
1356              <P>Your <B>job ID</B> is: %s
1357              <P>The estimated duration of your job is:  %s """ %  (sessionID, self._sensibleTimeString(estimatedDuration))
1358        print "<P>The estimated volume of your job is: %.2f MB" % ((estimatedVolume/1000000)+0.01)
1359        print "<P>Your extraction job is running...</P>"
1360       
1361        if estimatedDuration>60:
1362            try:
1363                mailAddr=getUserEmail()
1364                print "<P>You will be emailed at %s when the job has finished and the output is ready." % mailAddr       
1365            except:
1366                pass
1367               
1368        print "<P>Thank you for using the %s." % PACKAGE_NAME
1369        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>"
1370
1371
1372
1373    def _displayFileNameRuleOptions(self):
1374        """
1375        Prints the options for outputting to a single file or
1376        multiple files.
1377        """
1378        pass
1379       
1380
1381    def _displayRequestSummaryTable(self, summaryDict):
1382        """
1383        Prints a table summarising the current request.
1384        """
1385        print "<H3>The following is a summary of your request</H3>"
1386        print "<TABLE>"
1387        # Chop up the request information into a dictionary
1388        #(summaryDict, orderedKeys)=self._chopUpSummary(summary)
1389       
1390        d=summaryDict
1391        dsgKeys=d["datasetGroups"].keys()
1392        dsKeys=d["datasets"].keys()
1393        varKeys=d["variables"].keys()
1394        axisKeys=d["axes"].keys()
1395       
1396        dsgKeys.sort()
1397        dsKeys.sort()
1398        varKeys.sort()
1399        axisKeys.sort()
1400       
1401        template='<TR class="tablerow"><TD><B>%s%s</B></TD><TD>%s</TD></TR>'
1402       
1403        for dsg in dsgKeys:
1404            print template % ("Dataset Group ", dsg, d["datasetGroups"][dsg])       
1405           
1406            for ds in dsKeys:
1407                (dsgIndex, dsIndex)=re.match(r"^(\d+)\.(\d+)$", ds).groups()
1408                if dsg==dsgIndex:
1409                    print template % ("Dataset ", ds, d["datasets"][ds])
1410                   
1411                for var in varKeys:
1412                    (dsgIndex, dsIndex, varIndex)=re.match(r"^(\d+)\.(\d+)\.(\d+)$", var).groups()
1413                    if dsg==dsgIndex and ds=="%s.%s" % (dsgIndex, dsIndex):
1414                        print template % ("Variable ", var, d["variables"][var])
1415                        if d["outputFormats"].has_key(var):
1416                            print template % ("Output format ", var, d["outputFormats"][var])
1417
1418                        if d["datasetURIs"].has_key(var):
1419                            print template % ("Dataset URI ", var, d["datasetURIs"][var])                       
1420                       
1421                    for axis in axisKeys:
1422                        (dsgIndex, dsIndex, varIndex, axisIndex)=re.match(r"^(\d+)\.(\d+)\.(\d+)\.(\d+)$", axis).groups()
1423                        if (dsg==dsgIndex and ds=="%s.%s" % (dsgIndex, dsIndex)) and var=="%s.%s.%s" % (dsgIndex, dsIndex, varIndex):
1424                            print template % ("Axis ", axis, d["axes"][axis])
1425       
1426            print "<TR><TD>&nbsp;</TD></TR>"
1427
1428       
1429        # Now globals
1430        globalKeys=d["globals"].keys()
1431        globalKeys.sort()
1432       
1433        for key in globalKeys:
1434            print template % (key, "", d["globals"][key])
1435       
1436        print "</TABLE>"
1437       
1438
1439    def _displayConfirmationSection(self, summary):
1440        """
1441        Asks the user to confirm their request.
1442        """
1443        print '<P><INPUT TYPE="submit" NAME="confirm" VALUE="Confirm"> Click the "Confirm" button to fetch your request.<P>'
1444       
1445        self._displayRequestSummaryTable(summary) 
1446
1447        print """<P><INPUT TYPE="submit" NAME="confirm" VALUE="Confirm"> Click the "Confirm" button to fetch your request.
1448        <BR>If you wish to modify your request please press the <I>Back</I> button on your browser.<P>"""
1449        print "</FORM><P>"
1450       
1451       
1452    def _displayOperationOptions(self):
1453        """
1454        Prints a form entry for specifying the required operation.
1455        """
1456        pass
1457       
1458       
1459    def _displayOutputFormatOptions(self, options, sessionID):
1460        """
1461        Prints the available output format options in a form.
1462        """
1463        print """<P><INPUT TYPE="checkbox" NAME="multipleFileOutput">
1464               &nbsp;Use multiple output files [ this is the default large files as limited by the server ]."""
1465               
1466        print '<P>Format&nbsp;<SELECT NAME="outputFormat">'
1467        for format in options:
1468            print "<OPTION>%s</OPTION>" % format
1469        print "</SELECT>"
1470             
1471        print "&nbsp;&nbsp; Note that you should choose NetCDF format if you wish to visualise data."
1472        #print '<P><A HREF="%s?action=saveRequest&sessionID=%s">Get Request XML only.</A>' % (CGI_SCRIPT_URL_PATH, sessionID) 
1473        print '<P><INPUT TYPE="submit" NAME="proceed" VALUE="Proceed"><P>'
1474        print "</FORM><P>"     
1475
1476
1477    def _displayProcessesTable(self):
1478        """
1479        Prints the Processes table of current dx processes running.
1480        """     
1481        pass
1482   
1483       
1484    def _displayUploadRequestOptions(self, sessionID):
1485        """
1486        Generates an upload box for the user to load their own request.
1487        The current request is then overwritten by the uploaded version.
1488        """
1489        """
1490        How might this work.
1491        At any point I can click [ Upload Old Request ] which is an XML file.
1492        It opens a dialogue box for browse and it is saved onto the server and
1493        is referenced as http://localhost/cgi-bin/dxcgi.py?uploadedRequest=something/or/other.xml
1494        Then the dx opens it and parses it in, keeping the sessionID but losing all else!
1495        NOTE: Needs a visible REQUEST_XML_DIR_LOCAL_PATH dir.
1496        """
1497        print '<FORM METHOD="post" ACTION="%s" ENCTYPE="multipart/form-data">' % CGI_SCRIPT_URL_PATH
1498        print "<P>Please provide the location of the request file you wish to upload:"
1499        print """&nbsp;<INPUT TYPE="file" NAME="uploadedFile" VALUE="" SIZE="40">
1500                       <INPUT NAME="action" TYPE="hidden" VALUE="parseUploadedFile">
1501                       <INPUT NAME="sessionID" TYPE="hidden" VALUE="%s">
1502                       <INPUT TYPE="submit" NAME="submit" VALUE="Upload"></FORM><P>""" % sessionID
1503
1504       
1505    def _displaySaveRequestOptions(self, requestString, sessionID):
1506        """
1507        Generates an XML version of the request and writes this to a file locally.
1508        Then the user is pointed to that file in the same way they would be a data
1509        file.
1510        NOTE: Needs a visible REQUEST_XML_DIR_LOCAL_PATH dir.
1511        """
1512        # Write the file to the REQUEST_XML_DIR_LOCAL_PATH
1513        xmlFileName=sessionID+".xml"
1514        xmlFile=open(os.path.join(REQUEST_XML_DIR_LOCAL_PATH, xmlFileName), "w")
1515        xmlFile.write(requestString) # =dataSubsetSpecifier file
1516        xmlFile.close()
1517       
1518        httpFilePath=os.path.join(REQUEST_XML_DIR_URL_PATH, xmlFileName)
1519       
1520        print "<P>You can download your request file from:"
1521        print '<P><A HREF="%s">%s</A><P>' % (httpFilePath, httpFilePath)
1522
1523
1524    def _displayReturnLine(self, sessionID):
1525        """
1526        Displays a link to return to request.
1527        """
1528        print '<P><A HREF="%s?sessionID=%s">Return to your current request</A><P>' % (CGI_SCRIPT_URL_PATH, sessionID)
1529       
1530
1531if __name__=="__main__":
1532    print "Testing DisplayManager.py..."
1533    DisplayManager()
Note: See TracBrowser for help on using the repository browser.