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

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

Merged with titania 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                if loginMessage.find("with roles")>-1:
87                    loginMessage=loginMessage.replace("[","").replace("]","").replace("'","")
88                print '<FONT COLOR="red">&nbsp;&nbsp;&nbsp;&nbsp;[ %s ]</FONT>' % loginMessage
89            if loginStatus=="out":
90                # Display a login form
91                print """<FORM NAME="loginForm" method="POST" action="%s">
92                      Username: <INPUT TYPE="text" SIZE="20" NAME="yousirnaim" VALUE="">
93                      Password: <INPUT TYPE="password" SIZE="10" NAME="parcewerd" VALUE="">
94                      <INPUT TYPE="submit" NAME="login" VALUE="Login"></FORM>""" % CGI_SCRIPT_URL_PATH
95            elif loginStatus=="in":
96                # Display a logout form
97                print """<FORM NAME="loginForm" method="POST" action="%s">
98                      <INPUT TYPE="submit" NAME="logout" VALUE="Logout"></FORM>""" % CGI_SCRIPT_URL_PATH                     
99
100
101    def _displayNDGLoginBar(self, loginHosts, uriArgString):#, username, loginStatus, loginMessage=""):
102        """
103        If security applies then display the login information.
104        """
105        if RESTRICTED_DATA:
106            print """<P>Login:<P>
107<form action="https://glue.badc.rl.ac.uk/cgi-bin/security.py" method="POST">
108<table><tr>
109  <td><select name="requestURI">
110      <option value="">Select your home site...""" 
111     
112            for i,j in loginHosts:
113                print """<option value="%s"/>%s""" % (j,i)
114   
115            print """</select></td>
116<td><input type="submit" value="Login"></td>
117</tr></table>
118
119<input type="hidden" name="returnURI" value="%s%s">
120</form>
121""" % (CGI_SCRIPT_URL_PATH, uriArgString)
122           
123       
124    def _displayHTMLFooter(self):
125        """
126        Prints the configured HTML footer.
127        """
128        footfile=os.path.join(HTML_DIR_LOCAL_PATH, "footer.html")
129        lines=open(footfile).read()
130        print lines % ("mailto:"+ADMIN_MAIL_ADDRESS)
131
132
133    def _displayErrorMessage(self, msg, sessionID=None, user=None):
134        """
135        Prints an error message, without a header or footer.
136        """
137        print "<P>An error has occurred with this application. The error message received is:<P>"
138        print "<P><B>%s</B>" % msg
139        print "<P>The administrator has been informed of this error and will look into it."
140        print """<P>You can try pressing the <I>Back</I> button to return to the previous page.
141                 Alternatively you can<P><A HREF="%s"><FONT SIZE="+1">restart your request</FONT></A>.""" % CGI_SCRIPT_URL_PATH
142       
143       
144    def _displayErrorPage(self, msg):
145        """
146        Prints an error page, including headers and footer.
147        """
148        self._displayHTTPHeader()
149        self._displayHTMLHeader()
150        self._displayErrorMessage(msg)
151
152       
153    def _displayMainTableHeader(self, sessionID, onSubmit=""):
154        """
155        Prints the header part of the main table used in the dx
156        web pages.
157        """
158        print '<TABLE WIDTH="100%"><TR>'
159               
160        print '<TABLE WIDTH="100%"><TR class="tablerow"><TD>SELECTIONS</TD></TR></TABLE>'
161        # Begin form in HTML output
162        print """<FORM NAME="extract_info" method="POST" action="%s"%s>""" % (CGI_SCRIPT_URL_PATH, onSubmit)
163
164        print '<TABLE WIDTH="100%"><TR>'
165        print '<INPUT NAME="sessionID" TYPE="hidden" VALUE="%s">' % sessionID   
166       
167       
168    def _displayMainTableFooter(self):
169        """
170        Prints the footer part of the main table used in the dx
171        web pages.
172        """
173        print "</TR></TABLE>"
174        print '<P><INPUT TYPE="submit" NAME="proceed" VALUE="Proceed"><P>'
175        print "</FORM><P>"
176
177               
178    def _displayOptionsTable(self, summaryDict, optionCategories, options, optionStrings, sessionID, sessionObj):
179        """
180        Displays the options provided in the format (optionCategory, [option1,
181        option2, .., optionN]). Each dataset has these. It also sends the
182        sessionID as a hidden variable.
183        """     
184        # Get the category name to show on the
185        itemMap={"datasetGroup":"Dataset Group", "dataset":"Dataset",
186                 "variable":"Variable"} 
187
188        print """<TD CLASS="tablestyle">"""     
189        if len(options)==0:
190            print """<BR><B>You do not have permission to view any of the available options.</B>
191            <P>You can apply for access to datasets at:
192<P><A HREF="%s">%s</A>.<P>
193</B></FONT>
194""" % (REGISTRATION_PAGE, REGISTRATION_PAGE)
195            return
196           
197        # Now loop through getting the appropriate list of values to show               
198        itemTitle=itemMap[optionCategories[0].split("_")[0]]
199        print """<P><FONT COLOR="black"><B>PLEASE SELECT: %s</B> (<A NAME="selectAll"
200onclick="selectAllCheckBoxes()">  select all </A> / <A NAME="deSelectAll"
201onclick="deSelectAllCheckBoxes()"> deselect all </A> )</FONT><P>""" % itemTitle
202       
203        # Insert useful select all javascript function for checkboxes
204        print jsFunctions.js_selectAllCheckBoxes
205        print jsFunctions.js_deSelectAllCheckBoxes
206       
207        if itemTitle=="Dataset Group":
208                # Need to wade through metadata links to deal with this one...
209                selectionIDs=optionCategories
210                datasetGroupValues=[i[0] for i in options]
211                datasetGroupNames=[i[0] for i in optionStrings]
212                detailedMetadataLinks=[i[1][0] for i in options]
213                discoveryMetadataLinks=[i[1][1] for i in options]
214
215                selectedFlag=None                 
216                for i in range(len(selectionIDs)):
217                    selectionID=selectionIDs[i]
218                    datasetGroupValue=datasetGroupValues[i]
219                    datasetGroupName=datasetGroupNames[i]
220                    detailedMetadataLink=detailedMetadataLinks[i]
221                    discoveryMetadataLink=discoveryMetadataLinks[i]     
222                           
223                    if not selectedFlag:
224                        print '<BR><INPUT TYPE="checkBox" NAME="%s" VALUE="%s" CHECKED>%s</INPUT>' % (selectionID, datasetGroupName, datasetGroupValue)                 
225                        selectedFlag=1
226                    else:
227                        print '<BR><INPUT TYPE="checkBox" NAME="%s" VALUE="%s">%s</INPUT>' % (selectionID, datasetGroupName, datasetGroupValue)                     
228
229                    if detailedMetadataLink.lower()!="undefined":
230                        print '&nbsp;<A HREF="%s">[ Detailed Metadata ]</A>' % detailedMetadataLink
231                    if discoveryMetadataLink.lower()!="undefined":
232                        print '&nbsp;<A HREF="%s">[ Discovery Metadata ]</A>' % discoveryMetadataLink
233               
234
235        elif itemTitle=="Dataset":
236                selectionIDs=optionCategories
237                itemValues=options
238                itemNames=optionStrings
239                selectedFlag=None 
240               
241                lastDatasetGroup="WON'T MATCH"             
242                for i in range(len(selectionIDs)):
243                    selectionID=selectionIDs[i]
244                    itemName=itemNames[i]
245                    itemValue=itemValues[i]
246                   
247                    dsgKey=re.match("dataset_(\d+)\.", selectionID).groups()[0]
248                    datasetGroup=summaryDict["datasetGroups"][dsgKey]
249                    if datasetGroup!=lastDatasetGroup:
250                        print """<BR><B>%s &gt;&gt;&gt; Dataset selection:</B>""" % datasetGroup           
251
252                    if not selectedFlag:
253                        print '<BR><INPUT TYPE="checkBox" NAME="%s" VALUE="%s" CHECKED>%s</INPUT>' % (selectionID, itemName, itemValue)                 
254                        selectedFlag=1
255                    else:
256                        print '<BR><INPUT TYPE="checkBox" NAME="%s" VALUE="%s">%s</INPUT>' % (selectionID, itemName, itemValue)                     
257               
258                    lastDatasetGroup=datasetGroup       
259                       
260
261        elif itemTitle=="Variable":
262                # Set up hidden option to direct client to call for domain options so it will get format as well
263                print '<INPUT TYPE="hidden" NAME="targetPage" VALUE="DomainAndFormatPage">' 
264               
265                selectionIDs=optionCategories
266                itemValues=[i[0] for i in options]
267                itemNames=[i[1] for i in optionStrings]
268                selectedFlag=None 
269               
270                lastDataset="WON'T MATCH"
271                lastDatasetGroup="WON'T MATCH"             
272                for i in range(len(selectionIDs)):
273                    selectionID=selectionIDs[i]
274                    itemName=itemNames[i]
275                    itemValue=itemValues[i]
276                    # Quick fudge for strange itemValue that is actually a list
277                    try:                   
278                        if type(itemValue)==type([]):
279                            itemValue=itemValue[0]
280                    except:
281                        pass
282
283                    if itemName[-5:]=="_dxvv":
284                        itemValue=itemValue+" (Virtual Variable)"
285                       
286                    (dsgKey, dsKey)=re.match("variable_(\d+)\.(\d+)\.", selectionID).groups()
287                    datasetGroup=summaryDict["datasetGroups"][dsgKey]
288                    dataset=summaryDict["datasets"]["%s.%s" % (dsgKey, dsKey)]
289                    if dataset!=lastDataset or lastDatasetGroup!=datasetGroup:
290                        print """<P><B>%s &gt;&gt;&gt; %s &gt;&gt;&gt; Variable
291selection:</B>""" % (datasetGroup, dataset)
292
293                    if not selectedFlag:
294                        print '<BR><INPUT TYPE="checkBox" NAME="%s" VALUE="%s" CHECKED>%s</INPUT>' % (selectionID, itemName, itemValue)                 
295                        selectedFlag=1
296                    else:
297                        print '<BR><INPUT TYPE="checkBox" NAME="%s" VALUE="%s">%s</INPUT>' % (selectionID, itemName, itemValue)                     
298                    lastDataset=dataset
299                    lastDatasetGroup=datasetGroup
300        print "</TD>"
301                   
302           
303    def _displayDomainOptions(self, summaryDict, optionCategories, options, optionStrings, sessionID):
304        """
305        Displays the domain options for each variable. Includes lots of code to
306        generate dictionaries and lists that are used later on to create an
307        appropriate user interface.
308        """     
309        # Define a bucket to store axis info in for later
310        axisBucket=[[],[],[]]
311        formatDict={}
312        counter=0
313        for item in optionCategories:
314            if item[:4]=="axis":
315                axisBucket[0].append(item)
316                axisBucket[1].append(options[counter])
317                axisBucket[2].append(optionStrings[counter])
318            elif item[:6]=="output":
319                formatDict[item]=options[counter]
320            counter=counter+1
321       
322        # define which variables have the same axes
323        sameBucket=getIdenticalDomains(axisBucket)
324       
325        (optionCategories, options, optionStrings)=axisBucket
326       
327        # Predefine what we need for the axis selection in terms of interfaces...
328        knownAxisDict={}               
329        axisDict={}
330       
331        # Create some lists to collect time axis info for time validation functions
332        minNames=[]
333        minValues=[]
334        maxValues=[]   
335
336        # Loop through keys to get varIndices in order 
337        for i in range(len(optionCategories)):
338            optionName=optionCategories[i]
339            varIndex=".".join(optionName.split(".")[:-1])[5:]
340            axisIndex=int(optionName.split(".")[-1])
341            items=options[i]
342            [knownAxis, id, longName, units, listType, unused]=items[:6]       
343           
344            if not axisDict.has_key(varIndex):
345                axisDict[varIndex]={"axes":[]}
346            if knownAxis in ("time", "latitude", "longitude"):
347                axisDict[varIndex][knownAxis]=axisIndex
348                if knownAxis=="time":
349                    startTime=getDateTimeComponents(items[6])
350                    endTime=getDateTimeComponents(items[7])
351                    minNames.append(optionName)
352                    minValues.append(startTime[:])
353                    maxValues.append(endTime[:])
354           
355            axisDict[varIndex]["axes"].append([optionName, items])
356             
357        axisDictKeys=axisDict.keys()
358        axisDictKeys.sort()
359       
360        # Now print javascript time functions if needed
361        if len(minNames)>0:
362            minNames=str(minNames)
363            minValues=str([list(lst) for lst in minValues])
364            maxValues=str([list(lst) for lst in maxValues])
365            print jsFunctions.js_timeValidationFunctions % (minNames, minValues, maxValues)
366       
367        # Print options stuff   
368        print "<P><B>PLEASE SELECT: Domain options</B><P>"     
369
370        print """<A NAME="groupDomainsSelector" onClick="toggleDomainGrouping('on')">Group all similar domains</a> |&nbsp;
371        <A NAME="ungroupDomainSelector" onClick="toggleDomainGrouping('off')"> Keep  similar domains separate.</a></P>"""
372        # Set up the DIV tag that will allow javascript re-rendering of the selection
373        # interface.
374        print """<DIV ID="domainSelection">""" 
375
376        # Define massive string that will hold all html to show ALL var domains
377        print1=""
378        print1=print1+ """<TABLE ID="domainTable">\n"""
379        print1=print1+ """<TR CLASS="tablestyle">
380                        <TD><B>AXIS NAME</B></TD>
381                        <TD><B>RECOGNISED AS</B></TD>
382                        <TD><B>UNITS</B></TD>
383                        <TD COLSPAN="3"><B>SELECTION</B></TD>
384                        <TD><B>INFORMATION</B></TD></TR>\n"""   
385       
386        # loop through axis dictionary contents and render each axis
387        # according to what we have learnt about it
388        for key in axisDictKeys:
389
390            # summaryDict is used to get string info about datasetgroup/dataset/var
391            varID=summaryDict["variables"][key]
392            dsgKey, dsKey=re.match("(\d+)\.(\d+)", key).groups()
393            datasetGroup=summaryDict["datasetGroups"][dsgKey]
394            dataset=summaryDict["datasets"]["%s.%s" % (dsgKey, dsKey)]
395            print1=print1+ """<TR><TD COLSPAN="7">&nbsp;</TD></TR>\n""" 
396            print1=print1+ """<TR CLASS="tablestyle"><TD COLSPAN="7"><B>%s &gt;&gt;&gt; %s &gt;&gt;&gt; %s</TD></TR>\n""" % (datasetGroup, dataset, varID)         
397       
398            # get sub-dictionary for this variable
399            d=axisDict[key]
400
401            # get axis list
402            axes=d["axes"]
403           
404            # create a dictionary of known axes that have been found
405            # that require particular rendering
406            found={}
407            # Check time, lat and lon
408            for ax in ("time", "latitude", "longitude"):
409                if d.has_key(ax):
410                    found[ax]=d[ax]
411           
412            # loop through all the axes and render them appropriately
413            for axis in axes:
414                (optionName, items)=axis
415                varIndex=".".join(optionName.split(".")[:-1])[5:]
416                axisIndex=int(optionName.split(".")[-1])
417                [knownAxis, id, longName, units, listType, unused]=items[:6]
418
419                # if latitude or longitude then render both in one code block
420                if (found.has_key("latitude") and found.has_key("longitude")) and \
421                        axisIndex in (found["latitude"], found["longitude"]):
422               
423                    if found.has_key("used lat lon"):  continue
424               
425                    if axisIndex==found["latitude"]:
426                        # The current axis is latitude so need to get longitude
427                        latItems=items         
428                        latOptionName=optionName       
429                        lonIndex=found["longitude"]
430                       
431                        for x in axes:
432                            if int(x[0].split(".")[-1])==lonIndex:
433                                # Found longitude axis in list
434                                (lonOptionName, lonItems)=x                     
435                       
436                    elif axisIndex==found["longitude"]:
437                        # The current axis is longitude so need to get latitude
438                        lonItems=items
439                        lonOptionName=optionName                       
440                        latIndex=found["latitude"]
441                       
442                        for x in axes:
443                            if int(x[0].split(".")[-1])==latIndex:
444                                # Found latitude axis in list
445                                (latOptionName, latItems)=x             
446                                                               
447                    [latKnownAxis, latId, latLongName, latUnits, latListType, latUnused]=latItems[:6]
448                    northernExtent, southernExtent=latItems[6:8]
449                    [lonKnownAxis, lonId, lonLongName, lonUnits, lonListType, lonUnused]=lonItems[:6]
450                    westernExtent, easternExtent=lonItems[6:8]
451   
452                    found["used lat lon"]=1
453                     
454                    #print '<B>Horizontal Domain</B><P>'
455                     
456                    print1=print1+ """<TR><TD WIDTH="20%%"><B>%s</B></TD>
457                     <TD>%s</TD>
458                     <TD>%s</TD>
459                     <TD></TD>                               
460                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/><BR></TD>
461                     <TD><B></B></TD>
462                     <TD WIDTH="30%%"><FONT SIZE="-2"><B>NOTE ABOUT THE JAVA MAP APPLET:</B>
463<BR>1. The map will not work if you do not have Java enabled on your browser.</FONT></TD>
464                     </TR>\n""" % (latLongName, latKnownAxis, latUnits, 
465                                   latOptionName+"_high", northernExtent) 
466                                                                             
467                                                                             
468                    # Check existence of map applet page for this axis ID, otherwise make it
469                    mapHTMLFile=self._checkMapAppletHTMLPage(lonOptionName, latOptionName)
470                   
471                    print1=print1+ """<TR><TD WIDTH="20%%"><B>%s</B></TD>
472                     <TD>%s</TD>
473                     <TD>%s</TD>                     
474                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
475                     <TD><TABLE BORDER="0"><TR><TD ALIGN="LEFT">&nbsp;<B></B></TD><TD><CENTER><B><input type="button" value="Select from map"
476    onClick="newWindow('%s','window2',550,400);"></CENTER></TD></TR></TABLE></TD>                   
477                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
478                     <TD><BR><FONT SIZE="-2">2. This applet is known not to work on certain browsers: Mozilla, Konqueror.</FONT></TD>
479                     </TR>\n""" % (lonLongName, lonKnownAxis, lonUnits, 
480                                   lonOptionName+"_low", westernExtent, mapHTMLFile, lonOptionName+"_high",
481                                   easternExtent) 
482                                                   
483                    print1=print1+ """<TR><TD WIDTH="20%%"><B>%s</B></TD>
484                     <TD>%s</TD>
485                     <TD>%s</TD>                     
486                     <TD></TD>                               
487                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
488                     <TD><B>&nbsp;</B></TD>
489                     <TD><FONT SIZE="-2">
490<BR>3. On some browsers you may have to select your subset twice before it registers.</FONT></TD>
491                     </TR>\n""" % ("","","", 
492                                   latOptionName+"_low", southernExtent)                   
493
494                # if time then render that in a particular way
495                elif found.has_key("time") and axisIndex==found["time"]:
496                    (calendar, start,end,intervalValue)=items[5:9]
497                   
498                   
499                    print1=print1+ """<TR><TD WIDTH="20%%"><B>%s</B></TD>
500                     <TD>%s</TD>
501                     <TD>%s</TD>\n""" % (longName, knownAxis, units)
502
503                    print1=print1+self._displayTemporalDomainMenus(start, end, intervalValue, units, calendar,optionName)
504                    print1=print1+ """<TD><INPUT TYPE="button" NAME="validateTime" VALUE="Validate time selections" onClick='validateTimeSelections("%s")'/></TD></TR>\n""" % optionName
505                             
506                           
507                    """<TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
508                     <TD><TABLE BORDER="0"><TR><TD ALIGN="LEFT">&nbsp;<B>Low</B></TD><TD ALIGN="RIGHT"><B>High</B>&nbsp;</TD></TR></TABLE></TD>                     
509                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
510                     </TR>""" #% (optionName+"_low", start, optionName+"_high", end)   
511               
512                # else deal with other axis types, noting that these also vary           
513                else:
514                    listType=items[4]
515                    if len(unused)>0: 
516                        comment=unused
517                    else:
518                        comment=""
519
520                    # render axis according to the type of list sent
521                    # "full list" is all the numbers
522                    # "comma-separated ..." is a text box for user to input text into
523                    # all others are rendered as two input boxes, one low and one high
524                    if listType=="full list":
525                        fullList=items[6:]
526                        uniqueList=[]
527                        for i in fullList: 
528                            if i not in uniqueList:
529                                uniqueList.append(i)
530                        optionsAsString="\n".join(["<OPTION>%s</OPTION>" % i for i in uniqueList])
531                        hght=5
532                        if len(uniqueList)<5: 
533                            hght=len(uniqueList)
534                        print1=print1+ """<TR><TD WIDTH="20%%"><B>%s</B></TD>
535                           <TD>%s</TD>
536                           <TD>%s</TD>
537                           <TD COLSPAN="3"><CENTER>
538                           <SELECT NAME="%s" SIZE="%s" MULTIPLE="multiple">
539                             %s
540                           </SELECT>
541                           </TD>
542                           <TD><FONT SIZE="-2"><B>NOTE ABOUT THIS SELECTION CATEGORY:</B><BR>%s</FONT></TD>
543                           </TR>\n""" % (longName, knownAxis, units, optionName, hght, optionsAsString, comment)
544
545                    # or deal with comma-separated input in text box
546                    elif listType.split()[0]=="comma-separated":
547                        # Render a textarea with option to insert text
548                        cs,lts=listType.split()
549                        if lts.find("integer")>-1:
550                            ntype="Integer"
551                            nlength=lts[7:]
552                        elif lts.find("float")>-1:
553                            ntype="Float"
554                            nlength=lts[5:]
555
556                        taString="[OPTIONAL] You can insert values here following the format: \n%s %ss of length %s." % (cs.title(), ntype.lower(), nlength)
557
558                        fullList=items[6:]
559                        optionsAsString="\n".join(["<OPTION>%s</OPTION>" % i for i in fullList])
560                        print1=print1+ """<TR><TD WIDTH="20%%"><B>%s</B></TD>
561                           <TD>%s</TD>
562                           <TD>%s</TD>
563                           <TD COLSPAN="3"><CENTER>
564                           <TEXTAREA NAME="%s" ROWS="5" COLS="50">%s</TEXTAREA>
565                           </TD>
566                           <TD><FONT SIZE="-2"><B>NOTE ABOUT THIS SELECTION CATEGORY:</B><BR>%s</FONT></TD>
567                           </TR>\n""" % (longName, knownAxis, units, optionName, taString, comment)
568
569                    # or deal with (low, high) range
570                    else:
571                        start,end=items[6:8]
572                        print1=print1+ """<TR><TD WIDTH="20%%"><B>%s</B></TD>
573                     <TD>%s</TD>
574                     <TD>%s</TD>                     
575                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
576                     <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>             
577                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
578                     </TR>\n""" % (longName, knownAxis, units, 
579                     optionName+"_low", start, optionName+"_high", end)   
580
581            # Display output format
582            print1=print1+ """<TR><TD WIDTH="20%%"><B>OUTPUT FORMAT</B></TD>\n"""
583            print1=print1+ """<TD COLSPAN="3">Note that you should choose NetCDF format if you wish to visualise data.</TD>\n"""                     
584            print1=print1+ '<TD COLSPAN="3"><SELECT NAME="outputFormat_%s">\n' % key
585            for format in formatDict["outputFormat_%s" % varIndex]:
586                print1=print1+ "<OPTION>%s</OPTION>\n" % format
587            print1=print1+ "</SELECT></TD>\n"
588           
589        # Now create a string holding all the html for grouping domains for similar variables
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                print2=print2+ """<TR CLASS="tablestyle"><TD COLSPAN="7"><B>%s%s &gt;&gt;&gt; %s &gt;&gt;&gt; %s</TD></TR>\n""" % (domainFlag, datasetGroup, dataset, varID)
627                # Create hidden field for cloning domain
628                if vkey!=varsToLoop[0]:
629                    print2=print2+ ("""<INPUT TYPE="hidden" NAME="clonedomain_%s" VALUE="%s"/>""" % (vkey, varsToLoop[0]))
630       
631            d=axisDict[key]
632            axes=d["axes"]
633           
634            found={}
635            # Check time, lat and lon
636            for ax in ("time", "latitude", "longitude"):
637                if d.has_key(ax):
638                    found[ax]=d[ax]
639
640            # loop through all the axes and render them appropriately       
641            for axis in axes:
642                (optionName, items)=axis
643                varIndex=".".join(optionName.split(".")[:-1])[5:]
644                axisIndex=int(optionName.split(".")[-1])
645                [knownAxis, id, longName, units, listType, unused]=items[:6]
646
647                # if latitude or longitude then render both in one code block
648                if (found.has_key("latitude") and found.has_key("longitude")) and \
649                        axisIndex in (found["latitude"], found["longitude"]):
650               
651                    if found.has_key("used lat lon"):  continue
652               
653                    if axisIndex==found["latitude"]:
654                        # The current axis is latitude so need to get longitude
655                        latItems=items         
656                        latOptionName=optionName       
657                        lonIndex=found["longitude"]
658                       
659                        for x in axes:
660                            if int(x[0].split(".")[-1])==lonIndex:
661                                # Found longitude axis in list
662                                (lonOptionName, lonItems)=x                     
663                       
664                    elif axisIndex==found["longitude"]:
665                        # The current axis is longitude so need to get latitude
666                        lonItems=items
667                        lonOptionName=optionName                       
668                        latIndex=found["latitude"]
669                       
670                        for x in axes:
671                            if int(x[0].split(".")[-1])==latIndex:
672                                # Found latitude axis in list
673                                (latOptionName, latItems)=x             
674                                                               
675                    [latKnownAxis, latId, latLongName, latUnits, latListType, latUnused]=latItems[:6]
676                    northernExtent, southernExtent=latItems[6:8]
677                    [lonKnownAxis, lonId, lonLongName, lonUnits, lonListType, lonUnused]=lonItems[:6]
678                    westernExtent, easternExtent=lonItems[6:8]
679   
680                    found["used lat lon"]=1
681                     
682                    #print '<B>Horizontal Domain</B><P>'
683                     
684                    print2=print2+ """<TR><TD WIDTH="20%%"><B>%s</B></TD>
685                     <TD>%s</TD>
686                     <TD>%s</TD>
687                     <TD></TD>                               
688                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/><BR></TD>
689                     <TD><B></B></TD>
690                     <TD WIDTH="30%%"><FONT SIZE="-2"><B>NOTE ABOUT THE JAVA MAP APPLET:</B>
691<BR>1. The map will not work if you do not have Java enabled on your browser.</FONT></TD>
692                     </TR>\n""" % (latLongName, latKnownAxis, latUnits, 
693                                   latOptionName+"_high", northernExtent) 
694                                                                             
695                                                                             
696                    # Check existence of map applet page for this axis ID, otherwise make it
697                    mapHTMLFile=self._checkMapAppletHTMLPage(lonOptionName, latOptionName)
698                   
699                    print2=print2+ """<TR><TD WIDTH="20%%"><B>%s</B></TD>
700                     <TD>%s</TD>
701                     <TD>%s</TD>                     
702                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
703                     <TD><TABLE BORDER="0"><TR><TD ALIGN="LEFT">&nbsp;<B></B></TD><TD><CENTER><B><input type="button" value="Select from map"
704    onClick="newWindow('%s','window2',550,400);"></CENTER></TD></TR></TABLE></TD>                   
705                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
706                     <TD><BR><FONT SIZE="-2">2. This applet is known not to work on certain browsers: Mozilla, Konqueror.</FONT></TD>
707                     </TR>\n""" % (lonLongName, lonKnownAxis, lonUnits, 
708                                   lonOptionName+"_low", westernExtent, mapHTMLFile, lonOptionName+"_high",
709                                   easternExtent) 
710                                                   
711                    print2=print2+ """<TR><TD WIDTH="20%%"><B>%s</B></TD>
712                     <TD>%s</TD>
713                     <TD>%s</TD>                     
714                     <TD></TD>                               
715                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
716                     <TD><B>&nbsp;</B></TD>
717                     <TD><FONT SIZE="-2">
718<BR>3. On some browsers you may have to select your subset twice before it registers.</FONT></TD>
719                     </TR>\n""" % ("","","", 
720                                   latOptionName+"_low", southernExtent)                   
721
722                # if time then render that in a particular way
723                elif found.has_key("time") and axisIndex==found["time"]:
724                    (calendar, start,end,intervalValue)=items[5:9]
725                   
726                   
727                    print2=print2+ """<TR><TD WIDTH="20%%"><B>%s</B></TD>
728                     <TD>%s</TD>
729                     <TD>%s</TD>\n""" % (longName, knownAxis, units)
730
731                    print2=print2+self._displayTemporalDomainMenus(start, end, intervalValue, units, calendar,optionName)
732                    print2=print2+ """<TD><INPUT TYPE="button" NAME="validateTime" VALUE="Validate time selections" onClick='validateTimeSelections("%s")'/></TD></TR>\n""" % optionName
733                             
734                           
735                    """<TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
736                     <TD><TABLE BORDER="0"><TR><TD ALIGN="LEFT">&nbsp;<B>Low</B></TD><TD ALIGN="RIGHT"><B>High</B>&nbsp;</TD></TR></TABLE></TD>                     
737                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
738                     </TR>""" #% (optionName+"_low", start, optionName+"_high", end)   
739               
740                # else deal with other axis types, noting that these also vary           
741                else:
742                    listType=items[4]
743                    if len(unused)>0: 
744                        comment=unused
745                    else:
746                        comment=""
747
748                    # render axis according to the type of list sent
749                    # "full list" is all the numbers
750                    # "comma-separated ..." is a text box for user to input text into
751                    # all others are rendered as two input boxes, one low and one high
752                    if listType=="full list":
753                        fullList=items[6:]
754                        uniqueList=[]
755                        for i in fullList: 
756                            if i not in uniqueList:
757                                uniqueList.append(i)
758                        optionsAsString="\n".join(["<OPTION>%s</OPTION>" % i for i in uniqueList])
759                        hght=5
760                        if len(uniqueList)<5: 
761                            hght=len(uniqueList)
762                        print2=print2+ """<TR><TD WIDTH="20%%"><B>%s</B></TD>
763                           <TD>%s</TD>
764                           <TD>%s</TD>
765                           <TD COLSPAN="3"><CENTER>
766                           <SELECT NAME="%s" SIZE="%s" MULTIPLE="multiple">
767                             %s
768                           </SELECT>
769                           </TD>
770                           <TD><FONT SIZE="-2"><B>NOTE ABOUT THIS SELECTION CATEGORY:</B><BR>%s</FONT></TD>
771                           </TR>\n""" % (longName, knownAxis, units, optionName, hght, optionsAsString, comment)
772
773                    # or deal with comma-separated input in text box
774                    elif listType.split()[0]=="comma-separated":
775                        # Render a textarea with option to insert text
776                        cs,lts=listType.split()
777                        if lts.find("integer")>-1:
778                            ntype="Integer"
779                            nlength=lts[7:]
780                        elif lts.find("float")>-1:
781                            ntype="Float"
782                            nlength=lts[5:]
783
784                        taString="[OPTIONAL] You can insert values here following the format: \n%s %ss of length %s." % (cs.title(), ntype.lower(), nlength)
785
786                        fullList=items[6:]
787                        optionsAsString="\n".join(["<OPTION>%s</OPTION>" % i for i in fullList])
788                        print2=print2+ """<TR><TD WIDTH="20%%"><B>%s</B></TD>
789                           <TD>%s</TD>
790                           <TD>%s</TD>
791                           <TD COLSPAN="3"><CENTER>
792                           <TEXTAREA NAME="%s" ROWS="5" COLS="50">%s</TEXTAREA>
793                           </TD>
794                           <TD><FONT SIZE="-2"><B>NOTE ABOUT THIS SELECTION CATEGORY:</B><BR>%s</FONT></TD>
795                           </TR>\n""" % (longName, knownAxis, units, optionName, taString, comment)
796
797                    # or deal with (low, high) range
798                    else:
799                        start,end=items[6:8]
800                        print2=print2+ """<TR><TD WIDTH="20%%"><B>%s</B></TD>
801                     <TD>%s</TD>
802                     <TD>%s</TD>                     
803                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
804                     <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>             
805                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD>
806                     </TR>\n""" % (longName, knownAxis, units, 
807                     optionName+"_low", start, optionName+"_high", end)   
808
809            # Display output format
810            print2=print2+ """<TR><TD WIDTH="20%%"><B>OUTPUT FORMAT</B></TD>\n"""
811            print2=print2+ """<TD COLSPAN="3">Note that you should choose NetCDF format if you wish to visualise data.</TD>\n"""                     
812            print2=print2+ '<TD COLSPAN="3"><SELECT NAME="outputFormat_%s">\n' % key
813            for format in formatDict["outputFormat_%s" % varIndex]:
814                print2=print2+ "<OPTION>%s</OPTION>\n" % format
815            print2=print2+ "</SELECT></TD>\n"
816
817        print1=print1+ """</TABLE>\n"""   
818        print2=print2+ """</TABLE>\n"""
819        #print print1
820        print "</DIV>"
821
822        escapedprint1=print1.replace("\"", "\\\"")
823        escapedprint2=print2.replace("\"", "\\\"")
824
825        print """<SCRIPT language="javascript">
826        function toggleDomainGrouping(grouper) {
827            var domainElement=document.getElementById("domainSelection");
828            var ungrouped="";
829            var grouped=""; """
830        for line in escapedprint1.split("\n"):
831            print """            ungrouped+="%s"; """ % line       
832           
833        for line in escapedprint2.split("\n"):
834            print """            grouped+="%s"; """ % line
835               
836        print """            if (grouper=="off") {     
837                 domainElement.innerHTML=ungrouped;
838            } else {
839                 domainElement.innerHTML=grouped;
840            }
841            validateAllTimeSelections("off");
842        }
843        toggleDomainGrouping("off");
844
845            </SCRIPT> """
846
847        print """<P><INPUT TYPE="checkbox" NAME="multipleFileOutput">
848               &nbsp;Use multiple output files [ this is the default large files as limited by the server ]."""
849
850        #print """<SCRIPT language="Javascript">validateAllTimeSelections("off");</SCRIPT>"""
851               
852
853    def  _checkMapAppletHTMLPage(self, lonAxisID, latAxisID):
854        """
855        Generates a map applet HTML Page if one doesn't already exist.
856        """
857        mapAppletTemplatePath=MAP_APPLET_TEMPLATE_LOCAL_PATH
858        (mapAppletDir, templateFile)=os.path.split(mapAppletTemplatePath)
859        axisNumbers=lonAxisID[5:]+"_"+latAxisID[5:]
860        axisMapHTMLPage=os.path.join(mapAppletDir, "map_%s.html" % axisNumbers)
861        if not os.path.isfile(axisMapHTMLPage):
862            template=open(mapAppletTemplatePath).read()
863            outfile=open(axisMapHTMLPage, "w")
864            outfile.write(template % (lonAxisID, lonAxisID, latAxisID, latAxisID))
865            outfile.close()
866            os.chmod(axisMapHTMLPage, 0644)
867        urlToAxisMapHTMLPage=os.path.join(os.path.split(MAP_APPLET_TEMPLATE_URL_PATH)[0], os.path.split(axisMapHTMLPage)[-1])
868        return urlToAxisMapHTMLPage
869
870
871    def _displayUploadForm(self, sessionID):
872        """
873        Displays a form entry for browsing the local system
874        to upload a file. UPLOAD_TEMP_DIR needs to be configured in
875        the clientConfig.py module.
876        """
877        print '<FORM METHOD="post" ACTION="%s" ENCTYPE="multipart/form-data">' % CGI_SCRIPT_URL_PATH
878        print "<P>Please provide the location of the request file you wish to upload:"
879        print """&nbsp;<INPUT TYPE="file" NAME="uploadedFile" VALUE="" SIZE="40">
880                       <INPUT NAME="action" TYPE="hidden" VALUE="parseUploadedFile">
881                       <INPUT NAME="sessionID" TYPE="hidden" VALUE="%s">
882                       <INPUT TYPE="submit" NAME="submit" VALUE="Upload"></FORM><P>\n<FORM>""" % sessionID
883
884
885    def _displayMetadataForm(self, fileName, fileFormat, varList, globalMetadata):
886        """
887        Displays the metadata in the data file.
888        """
889        #print """<INPUT NAME="variable_1" TYPE="hidden" VALUE="pqn">"""
890        print """<P>Thank you for uploading your file to the NetCDF-NASA Ames convertor.
891               The following information has been extracted from the file:
892               <BR><B>Filename:     %s</B>
893               <BR><B>File format:  %s</B>
894               <P><B><FONT SIZE="+1">Variables:</FONT></B>
895               <BR>Select the variables that you wish convert (Default=ALL):<P>""" % (fileName, fileFormat)
896       
897        # Now print the variable list as a form
898        varCount=1
899        print '<BR><INPUT TYPE="hidden" NAME="selectionsMade" VALUE="complete">'
900        for var in varList:
901            longName, varID=var
902            varString=varID
903            displayVar="%s &nbsp;&nbsp;{%s}" % (longName, varID)
904            if varID in ("None", "", None):
905                varString=longName
906                displayVar=varString
907            print '<BR><INPUT TYPE="checkbox" NAME="variable_%s" VALUE="%s" CHECKED>%s</INPUT>' % (varCount, varString, displayVar)
908            #print "<BR>%s (%s)" % tuple(var) # prints var id and long_name
909            varCount=varCount+1
910       
911        outFileMap={"NetCDF":"NASA Ames", "NASA Ames":"NetCDF"}   
912        # Now print metadata
913        print """<P><BR><B><FONT SIZE="+1">Global Metadata</FONT></B>
914              <BR>The following global metadata will be written to your output %s file(s):<P>""" % outFileMap[fileFormat]
915             
916        print '<TABLE BORDER="0">'
917        maxSize=10
918        for item in globalMetadata:
919            key, value=item
920            if key=="VNAME":
921                continue
922                displayKey="VNAME Variables from NASA Ames (modify below to rename)"
923            elif key=="ANAME":
924                continue
925                if value!=None:
926                    displayKey="ANAME Auxiliary Variables from NASA Ames (modify below to rename)"
927                else:
928                    break
929            else:
930                displayKey=key
931               
932            print '<TR><TD WIDTH="25"><B>%s: </B>' % displayKey
933           
934            #print str(type(value))
935            if type(value)!=type(""):
936                # deal with list type by indexing each part
937                try:
938                    value=value.data
939                except:
940                    pass
941                   
942                partCount=1
943                lengthList=[len(str(i)) for i in value]
944                total=0
945                for i in lengthList: total=total+i
946                #print "<P>TOTAL:", total
947                if total<60: 
948                    # Put all on one line
949                    print "<BR>"
950                    separator=""
951                    sizeString="%s" % (max(lengthList)+5)
952                    inputType="textbox"
953                else:
954                    separator="<BR>"
955                    sizeString="100"
956                    inputType="textbox"
957                   
958                #print dir(value), value.data
959                for part in value:
960                    if key in ("VNAMEAAAAAAAAAAA", "ANAMEAAAAAAAA"): # if variable names
961                        partName="%s-RENAMED_%s" % (key, partCount)
962                    else:
963                        partName="%s_%s" % (key, partCount)
964                    part=str(part)                 
965                    print '%s<INPUT TYPE="%s" NAME="%s" VALUE="%s" SIZE="%s"/>' % (separator, inputType, partName, part, sizeString)
966                    partCount=partCount+1
967                print "</TD></TR>"
968               
969            else:
970                size=len(value)     
971                if size>100:
972                    inputType="textbox"
973                else:
974                    inputType="textbox"
975                print '<INPUT TYPE="%s" NAME="%s" VALUE="%s" SIZE="100"/></TD></TR>' % (inputType, key, value)
976            #print "<BR>%s = %s" % tuple(item) # prints name and value of metadata item
977        print "</TABLE>"
978
979
980
981    def _displayOutputPage(self, outputFilePaths):
982        """
983        Displays full HTML page with a link to the output file.
984        """
985        if len(outputFilePaths)==1:
986            file=outputFilePaths[0]
987            print "<P><B>Your output file is available at:</B>"
988            print """<P><A HREF="%s">%s</A><P>""" % (file, file) 
989        else:
990            print "<P><B>Your output files are available at:</B><P>"
991            for file in outputFilePaths:
992                print """<A HREF="%s">%s</A><BR>""" % (file, file) 
993       
994                     
995    def _displayFinalMessage(self, outputMessage=[]):
996        """
997        Prints an a message for the final page.
998        """
999        outputString=""
1000        for i in outputMessage: outputString=outputString+"***LINEBREAK***"+str(i)
1001        outputString=outputString.replace("<", "&LT;")
1002        outputString=outputString.replace(">", "&GT;")
1003        outputString=outputString.replace("***LINEBREAK***", "<P>")
1004        outputString=outputString.replace("\n\n", "<P>")
1005        outputString=outputString.replace("\n", "<BR>")
1006       
1007        print """<P>Thank you for using <B>%s</B>. You can now download your output file.
1008                 <BR>Any output from the conversion package is printed below:
1009                 <P><TABLE BORDER="1"><TR><TD BGCOLOR="#EEEEEE"><KBD>%s</KBD></TD></TR></TABLE><P>
1010              """ % (PACKAGE_NAME, outputString)
1011
1012
1013    def _displayFeatureOptions(self):
1014        """
1015        Prints the available Features in a table.
1016        """   
1017        pass
1018       
1019       
1020    def _displayHorizontalDomainOptions(self, bounds):
1021        """
1022        Prints a form entry for specifying the horizontal domain.
1023        """
1024        (northernExtent, westernExtent, southernExtent, easternExtent)=bounds
1025
1026        # Horizontal Domain
1027        print '<B>Horizontal Domain</B><P>'
1028
1029        print """<TABLE><TR><TD WIDTH="20%%"></TD><TD WIDTH="20%%"></TD>
1030<TD WIDTH="20%%" ALIGN="CENTER"><INPUT TYPE="text" NAME="northernExtent" VALUE="%s" SIZE="6"><FONT SIZE="-1"><BR> Northern Extent </FONT></TD>
1031<TD WIDTH="20%%"></TD><TD WIDTH="20%%"></TD></TR>
1032<TR><TD><INPUT TYPE="text" NAME="westernExtent" VALUE="%s" SIZE="6"><FONT SIZE="-1"><BR> Western Extent </FONT></TD>
1033<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>
1034<TD ALIGN="RIGHT"><INPUT TYPE="text" NAME="easternExtent" VALUE="%s" SIZE="6"><FONT SIZE="-1"><BR> Eastern Extent </FONT></TD>
1035<TD></TD>
1036<TR><TD></TD><TD></TD>
1037<TD ALIGN="CENTER"><INPUT TYPE="text" NAME="southernExtent" VALUE="%s" SIZE="6"><FONT SIZE="-1"><BR> Southern Extent </FONT></TD>
1038<TD></TD><TD></TD></TR></TABLE>
1039<input type="button" value="Select from map"
1040    onClick="newWindow('%s','window2',550,400);">
1041<TABLE><TR><TD CLASS="tablestyle">
1042<B>NOTE ABOUT THE JAVA MAP APPLET:</B> 
1043<BR>1. The map will not work if you do not have Java enabled on your browser.
1044<BR>2. This applet is known not to work on certain browsers: Mozilla, Konqueror.
1045<BR>3. On some browsers you may have to select your subset twice before it registers.<P>
1046</TD></TR></TABLE>""" % (northernExtent, westernExtent, easternExtent, southernExtent, MAP_APPLET_URL_PATH)
1047
1048        helpLink=os.path.join(WEB_EXTRAS_URL_PATH, "help_page.html#interpolation")
1049        print """<P>[&nbsp;<A NAME="%s" onClick="help('%s')">Note about interpolation methods.</A>&nbsp;]<P>""" % (helpLink, helpLink)
1050
1051       
1052    def _displayVerticalSpatialDomainOptions(self, options):
1053        """
1054        Prints a form entry for specifying the vertical domain.
1055        """
1056        print '<P><B>Vertical Domain</B><P><TABLE WIDTH="100%"><TR>'
1057        for dsetNumber in range(1, self.numberOfDatasets+1):
1058            (levels, vertical_units)=options[dsetNumber-1]
1059
1060            if type(levels)==type(""): levels=(levels,)
1061            if len(levels)>3:
1062                levboxheight=3
1063            else:
1064                levboxheight=len(levels)
1065
1066            print """<TD WIDTH="50%%">Levels<BR><SELECT MULTIPLE NAME="verticalDomain_%s"
1067                  SIZE="%s" WIDTH="50" VALUE="%s">""" % (dsetNumber, levboxheight, levels[0])
1068            levSelected=" SELECTED"
1069            for level in levels:
1070                print """<OPTION VALUE="%s"%s>%s</OPTION>""" % (level, levSelected, level)
1071                levSelected=""
1072            print "</SELECT>"
1073            print '<INPUT NAME="verticalUnits" TYPE="hidden" VALUE="hPa">' 
1074            print "</TD>"
1075        print "</TR></TABLE>"
1076
1077
1078    def _displayTemporalDomainMenus(self, startTime, endTime, intervalValue, intervalUnits, calendar, axisIndex):
1079        """
1080        Displays a set of menus for entering the date and time limits for this axis.
1081        """ 
1082        startTime=getDateTimeComponents(startTime)
1083        endTime=getDateTimeComponents(endTime)
1084        super_index_list=[]
1085        index_list=[]
1086       
1087        # Get the bin list for all times
1088        if calendar=="360_day" and (intervalValue==30 and intervalUnits=="day"):
1089            intervalValue=1
1090            intervalUnits="month"
1091
1092        # This includes a little trick to avoid looping through masses of years
1093        startYear=startTime[0]
1094        endYear=endTime[0]
1095        ydiff=endYear-startYear
1096
1097        if intervalUnits.find("year")<0 and ydiff>6:
1098                # interval not years so assume that we can cut down years
1099                startPlus2=tuple([startYear+2]+list(startTime[1:]))
1100                l1=DateTimeManager.createList(startTime, startPlus2, (intervalValue,
1101                             intervalUnits), listtype="tuple")
1102                endMinus2=tuple([endYear-2]+list(endTime[1:]))
1103                l2=DateTimeManager.createList(endMinus2, endTime, (intervalValue,
1104                             intervalUnits), listtype="tuple")
1105                timeList=tuple(list(l1)+list(l2))
1106                timeBins=DateTimeManager.getTimeBins(timeList)
1107                allYears=range(startYear, endYear+1)
1108                timeBins[0]=allYears
1109
1110
1111        else:
1112            (intervalUnits, intervalValue)=DateTimeManager.getAppropriateUnitAndInterval(intervalValue, intervalUnits)
1113
1114            timeList=DateTimeManager.createList(startTime, endTime, 
1115                     (intervalValue, intervalUnits), listtype="tuple")
1116            timeBins=DateTimeManager.getTimeBins(timeList)
1117       
1118        for i in range(len(startTime)):
1119            index_list.append(timeBins[i].index(startTime[i]))
1120        #super_index_list=super_index_list+index_list[:]+index_list[:]
1121
1122        # Insert javascript functions to do date checking.
1123        #if len(super_index_list)==12:  super_index_list=super_index_list+[0,0,0,0,0,0,0,0,0,0,0,0]
1124        #print jsFunctions.js_dateCheckFunctionGroup % tuple(super_index_list)     
1125
1126        # Temporal domain
1127        #print '<P><B>Time</B><P><TABLE WIDTH="100%"><TR>'
1128        #print '<INPUT NAME="timeIntervalUnits_%s" TYPE="hidden" VALUE="%s">' % (axisIndex, intervalUnits)
1129        #print '<INPUT NAME="timeIntervalValue_%s" TYPE="hidden" VALUE="%s">' % (axisIndex, intervalValue)
1130        #print '<TD WIDTH="50%">'
1131        #print '<TABLE BORDER="1"><TR>'
1132        print1=""
1133        print1=print1+ '<TD COLSPAN="3"><CENTER><TABLE BORDER="1">\n'
1134       
1135        partMap={"low":"Start time", "high":"End time"}
1136        for part in ("low", "gap", "high"):
1137           
1138            if part=="gap":
1139                print1=print1+ '<TR><TD COLSPAN="6">&nbsp;</TD></TR>\n'
1140            else:
1141                print1=print1+ '<TR>\n'
1142                fieldFlag=""
1143                count=0
1144                for key in TIME_KEYS:
1145                    if part=="text":
1146                        print1=print1+ "<TD>%s</TD>\n" % key
1147                    elif part in ("low", "high"):
1148                        print1=print1+ """<TD><SELECT NAME="%s_%s.time.%s"%s>\n""" % (axisIndex, 
1149                                   part, key.lower(), fieldFlag)
1150                        if key=="year":
1151                            timeFormat="%.4d"
1152                        else:
1153                            timeFormat="%.2d"
1154
1155                        for item in timeBins[count]:
1156                            timeItem=timeFormat % item
1157                            print1=print1+ """<OPTION VALUE="%s">%s</OPTION>\n""" % (timeItem, timeItem)
1158               
1159                        print1=print1+ "</SELECT></TD>\n"
1160                        count=count+1
1161
1162                print1=print1+ "</TR>\n"
1163        print1=print1+ "</CENTER></TABLE></TD>\n"
1164
1165        return print1
1166        #print "</TR></TABLE><P>"
1167        # Call the javascript to update the date field at start
1168        #print """<SCRIPT LANGUAGE="Javascript">resetAllDates(%s)</SCRIPT>""" % (dsetNumber-1)   
1169       
1170
1171
1172       
1173    def DEPRACATED_displayTemporalDomainOptions(self, options):
1174        """
1175        Prints a form entry for specifying the temporal domain.
1176        """ 
1177        # timeDict holds time list dictionaries for start and end times,
1178        # time units and time interval for each dataset
1179        timeDict={}
1180        for dsetNumber in range(1, self.numberOfDatasets+1):
1181            (start_time, end_time, (intervalValue, intervalUnits))=options[dsetNumber-1]
1182            timeDict["dataset_%s" % dsetNumber]=(start_time, end_time, intervalValue, intervalUnits) 
1183 
1184        super_index_list=[]
1185        timeBins={}
1186        for dsetNumber in range(1, self.numberOfDatasets+1):
1187            (start_time, end_time, intervalValue, intervalUnits)=timeDict["dataset_%s" % dsetNumber]
1188            index_list=[]
1189            # Get the bin list for all times
1190            timeList=DateTimeManager.createList(start_time, end_time, (intervalValue, intervalUnits), listtype="tuple")
1191            timeBins[dsetNumber]=DateTimeManager.getTimeBins(timeList)
1192            for i in range(len(start_time)):
1193                index_list.append(timeBins[dsetNumber][i].index(start_time[i]))
1194            super_index_list=super_index_list+index_list[:]+index_list[:] 
1195
1196        # Insert javascript functions to do date checking.
1197        if len(super_index_list)==12:  super_index_list=super_index_list+[0,0,0,0,0,0,0,0,0,0,0,0]
1198        print jsFunctions.js_dateCheckFunctionGroup % tuple(super_index_list)     
1199
1200        # Temporal domain
1201        print '<P><B>Time</B><P><TABLE WIDTH="100%"><TR>'
1202        for dsetNumber in range(1, self.numberOfDatasets+1):
1203            (intervalValue, intervalUnits)=timeDict["dataset_%s" % dsetNumber][2:]
1204            (start_time, end_time)=timeDict["dataset_%s" % dsetNumber][:2]
1205            print '<INPUT NAME="timeIntervalUnits_%s" TYPE="hidden" VALUE="%s">' % (dsetNumber, intervalUnits) 
1206            print '<INPUT NAME="timeIntervalValue_%s" TYPE="hidden" VALUE="%s">' % (dsetNumber, intervalValue)
1207            print '<TD WIDTH="50%">'
1208            print '<TABLE BORDER="1"><TR>'
1209
1210            for part in ("Dataset %s: Start time" % dsetNumber, "start", "text", "end", "End time"):
1211                if part in ("Dataset %s: Start time" % dsetNumber, "End time"):
1212                    print '<TD COLSPAN="6">%s</TD>' % part
1213                else:
1214                  fieldFlag=""
1215                  count=0
1216                  for key in TIME_KEYS:
1217                    if part=="text":
1218                        print "<TD>%s</TD>" % key
1219                    elif part in ("start", "end"):
1220                        print """<TD><SELECT NAME="%s%s_%s" %s onChange="checkDate('%s_%s')">""" % (part, 
1221                                   key, dsetNumber, fieldFlag, part, dsetNumber)
1222                        if key=="year":
1223                            timeFormat="%.4d"
1224                        else:
1225                            timeFormat="%.2d"
1226
1227                        for item in timeBins[dsetNumber][count]:
1228                            timeItem=timeFormat % item
1229                            print """<OPTION VALUE="%s">%s</OPTION>""" % (timeItem, timeItem)
1230               
1231                        print "</SELECT></TD>"
1232                        count=count+1
1233
1234                print "</TR>"
1235            print "</TABLE>"
1236            print "</TD>"
1237
1238        print "</TR></TABLE><P>"
1239        # Call the javascript to update the date field at start
1240        print """<SCRIPT LANGUAGE="Javascript">resetAllDates(%s)</SCRIPT>""" % (dsetNumber-1)   
1241       
1242
1243
1244
1245    def _chopUpSummary(self, summary):
1246        """
1247        Chops up the summary string returning a dictionary of items and a
1248        list of keys for that dictionary ordered in an appropriate manner.
1249        """
1250        summaryDict={}
1251        orderedKeys=[]
1252        for line in summary.split("\n"):
1253            if line.find(":")>-1:
1254                (key, value)=line.strip().split(":\t")
1255                summaryDict[key]=value
1256                orderedKeys.append(key) 
1257        return (summaryDict, orderedKeys)               
1258
1259
1260    def _displayDatasetSummaryLine(self, summary, optionCategory, sessionID):
1261        """
1262        Takes a string containing a request summary and parses into suitable
1263        HTML format. Prints a summary line for the current request - with clickable
1264        links.
1265        """
1266        # Chop up the request information into a dictionary
1267        summaryDict=self._chopUpSummary(summary)[0]
1268               
1269        # Set up the form for the actions bar to allow various useful functions
1270        print """<FORM NAME="actions_bar" method="POST" action="%s">""" % CGI_SCRIPT_URL_PATH
1271       
1272        # Show return to start link
1273        print '<A HREF="%s?action=clearRequest">Return to Start</A>' % CGI_SCRIPT_URL_PATH
1274
1275        # Get current number of Datasets before showing option of selecting number of datasets
1276        # This sets the instance variable that is re-used everywhere from now on - clunky, I know!
1277        """self.numberOfDatasets=int(summaryDict["numberOfDatasets"])"""       
1278       
1279        if sessionID in (None, "None"):
1280            sidString=""
1281        else:
1282            sidString="&sessionID=%s" % sessionID
1283       
1284        # Show option for number of datasets if more than one allowed
1285        """if MAX_NUM_DATASETS>1:
1286            print ' | Number of Datasets <SELECT NAME="ndsets" onchange="redirect(this);">'
1287           
1288            for n in range(1, MAX_NUM_DATASETS+1):
1289                if n==self.numberOfDatasets:
1290                    print '<OPTION SELECTED VALUE="%s?numberOfDatasets=%s%s">%s</OPTION>' % (CGI_SCRIPT_URL_PATH, n, sidString, n)
1291                else:
1292                    print '<OPTION VALUE="%s?numberOfDatasets=%s%s">%s</OPTION>' % (CGI_SCRIPT_URL_PATH, n, sidString, n)
1293                   
1294            print "</SELECT>"  """
1295       
1296        # Link to view request summary
1297        #print '&nbsp;| <A HREF="%s?action=viewRequestSummary%s">View Current Request Summary</A>' % (CGI_SCRIPT_URL_PATH, sidString)
1298       
1299        # Allow save of request (XML format)
1300        #print ' | <A HREF="%s?action=saveRequest%s">Save Request (xml)</A>' % (CGI_SCRIPT_URL_PATH, sidString)
1301       
1302        # Allow upload of previous request (XML format)
1303        #print ' | <A HREF="%s?action=uploadRequest%s">Upload Request (xml)</A>' % (CGI_SCRIPT_URL_PATH, sidString)
1304       
1305        # Close actions bar form
1306        print "</FORM>"
1307                           
1308        # Set up link to call each section from a URL link so that you
1309        # can switch between one or two datasets
1310        selfCaller="%s?" % CGI_SCRIPT_URL_PATH
1311        firstCall=1
1312        for key in summaryDict.keys():
1313            if key=="targetPage":
1314                extra="%s=%s" % (key, "INSERT_STAGE_HERE")
1315            elif key=="numberOfDatasets":
1316                pass
1317            else:
1318                extra="%s=%s" % (key, summaryDict[key])
1319            if firstCall:
1320                selfCaller=selfCaller+extra
1321                firstCall=None
1322            else:
1323                selfCaller=selfCaller+"&"+extra
1324        """     
1325        if self.numberOfDatasets==1:
1326            selectLink=selfCaller.replace("numberOfDatasets=1", "numberOfDatasets=2")
1327            selectLink=selectLink.replace("targetPage=INSERT_STAGE_HERE", "")
1328            # Temporary measure - send back to start if changed
1329            selectLink="%s?numberOfDatasets=2" % CGI_SCRIPT_URL_PATH
1330            print ' | <A HREF="%s">Select 2 datasets</A>' % selectLink
1331        elif self.numberOfDatasets==2:
1332            selectLink=selfCaller.replace("numberOfDatasets=2", "numberOfDatasets=1")
1333            selectLink=selectLink.replace("targetPage=INSERT_STAGE_HERE", "")
1334            # Temporary measure - send back to start if changed
1335            selectLink="%s?numberOfDatasets=1" % CGI_SCRIPT_URL_PATH
1336            print ' | <A HREF="%s">Deselect dataset 2</A>' % selectLink"""
1337
1338        # Begin an HTML table
1339        """print '<TABLE WIDTH="100%"><TR class="tablerow"><TD COLSPAN="2">CURRENT REQUEST</TD></TR>'
1340
1341        print '<TR class="tablerow">'
1342
1343        # Get option category without number
1344        optcat=optionCategory.split("_")[0]
1345
1346        for count in range(1, self.numberOfDatasets+1):
1347          print '<TD WIDTH="50%%">Dataset %s: ' % count
1348          if not summaryDict.has_key("datasetGroup_%s" % count):
1349            print "None Specified"
1350          elif summaryDict.has_key("datasetGroup_%s" % count):
1351            displayString=' -&gt; <A HREF="%s&targetPage=%s">%s</A>' % (selfCaller, STAGES[0],
1352                           summaryDict["datasetGroup_%s" % count])
1353            print displayString.replace("INSERT_STAGE_HERE", STAGES[0])
1354            if summaryDict.has_key("dataset_%s" % count) and optcat not in ("datasetGroup", "dataset"):
1355                displayString=' -&gt; <A HREF="%s&targetPage=%s">%s</A>' % (selfCaller, STAGES[1],
1356                               summaryDict["dataset_%s" % count])
1357                print displayString.replace("INSERT_STAGE_HERE", STAGES[1])
1358                if summaryDict.has_key("variable_%s" % count) and optcat not in ("datasetGroup", "dataset", "variable"):
1359                    displayString=' -&gt; <A HREF="%s&targetPage=%s">%s</A>' % (selfCaller, STAGES[2],
1360                                   summaryDict["variable_%s" % count])
1361                    print displayString.replace("INSERT_STAGE_HERE", STAGES[2])
1362                    if summaryDict.has_key("horizontalDomain_%s" % count):
1363                        displayString=' -&gt; <A HREF="%s&targetPage=%s">%s</A>' % (selfCaller, STAGES[3],
1364                                        "domain selection")
1365                        print displayString.replace("INSERT_STAGE_HERE", STAGES[3])
1366          print "</TD>"
1367        print "</TR></TABLE>"
1368        print "</I></B><P>"   """
1369
1370
1371    def _sensibleTimeString(self, timeInSeconds):
1372        """
1373        Returns an appropriate string converting timeInSeconds to the most
1374        readable units.
1375        """
1376        if timeInSeconds<1:
1377            return "3 seconds"
1378        if timeInSeconds<60:
1379            return "%d seconds" % timeInSeconds
1380        if timeInSeconds<(60*60):
1381            (m, s)=divmod(timeInSeconds, 60)
1382            return "%s mins %s secs" % (m, s)
1383        else:
1384            (m, s)=divmod(timeInSeconds, 60)
1385            (h, m)=divmod(m, 60)
1386            return "%s hrs %s mins" % (h, m)   
1387
1388
1389    def _pathListFilter(self, pathList):
1390        """
1391        A sensible filter on path lists to a maximum of twenty.
1392        """
1393        if len(pathList)<21:
1394            return pathList
1395        else:
1396            return pathList[:10]+["..."]+pathList[-10:]
1397
1398
1399    def _displayStatus(self, status, errorString, sessionID):
1400        """
1401        Displays the status of your request.
1402        """
1403        # Show return to start link
1404        print '<P><A HREF="%s?action=clearRequest">Return to Start</A></P>' % CGI_SCRIPT_URL_PATH
1405
1406        print "<P><B>"
1407        if status=="complete":
1408            print "Your request has completed."
1409        elif status=="queued":
1410            print "Your current request is queued."
1411        else:
1412            if status=="failed":
1413                print "Your current request has %s with the following message:" % status
1414                print "</B><P>%s</P>" % errorString
1415                print """<P>We apologise for this problem.</P>
1416<P>Please report the above error to the administrator along with your session ID: <B>%s</B></P>""" % sessionID
1417            else:
1418                print "Your current request is %s." % status
1419        print "</B></P>"
1420       
1421        if status not in ("complete", "failed"):
1422            print """<P>Click the button below to update this page&nbsp;
1423                 <FORM NAME="extract_info" method="POST" action="%s">
1424                 <INPUT NAME="sessionID" TYPE="hidden" VALUE="%s"/>
1425                 <INPUT TYPE="hidden" NAME="action" VALUE="getStatus"/>
1426                 <INPUT TYPE="submit" NAME="statusGetter" VALUE="Check Status"/>
1427                 </FORM></P>""" % (CGI_SCRIPT_URL_PATH, sessionID)
1428                   
1429
1430    def _displayOutputFileList(self, pathList):
1431        """
1432        Prints links to all the files the user has requested.
1433        """
1434        print "<H3>Output information:</H3>"
1435       
1436        nfiles=len(pathList)
1437        pathList=self._pathListFilter(pathList)
1438        if nfiles<21:
1439            displayedString="all the files produced"
1440        else:
1441            displayedString="the first 10 and the last 10 files, the rest follow the same file-naming system"
1442       
1443        plural="s have"
1444        if nfiles==1: plural=" has" 
1445        print "%s file%s been successfully written. The table below shows %s." % (nfiles, plural, displayedString)
1446        print "<TABLE>"
1447       
1448        for file in pathList:
1449            localPath=file
1450            url=translateURI(localPath)
1451               
1452            if localPath=="...":
1453                print """<TR class="tablerow"><TD COLSPAN="3">...</TD>"""
1454            elif url[-3:] in ("xml", "txt"): # No visualise for XML
1455                print """<TR class="tablerow">
1456                         <TD><B>%s</B></TD>
1457                         <TD><A HREF="%s">  Download  </A></TD>
1458                         <TD></TD>
1459                     </TR>""" % (url, url)             
1460            else:
1461                print """<TR class="tablerow">
1462                         <TD><B>%s</B></TD>
1463                         <TD><A HREF="%s">  Download  </A></TD>
1464                         <TD><A HREF="%s?fileURIList=%s&fileVariable_1.1=SELECT_AUTOMATICALLY">  Visualise  </A></TD>
1465                     </TR>""" % (url, url, GEOSPLAT_URL_PATH, localPath)
1466        print "</TABLE>"
1467        print '<P><A HREF="%s">Start a new request</A>.' % CGI_SCRIPT_URL_PATH
1468
1469       
1470    def _displayProcessingSection(self, estimatedDuration, estimatedVolume, sessionID):
1471        """
1472        Method to tell user that there job is underway with details of their selection.
1473        """
1474        # Show return to start link
1475        print '<P><A HREF="%s?action=clearRequest">Return to Start</A></P>' % CGI_SCRIPT_URL_PATH
1476
1477        print """<H3>Processing Information:</H3>"""
1478        print "<TABLE>"
1479        template='<TR class="tablerow"><TD><B>%s</B></TD><TD>%s</TD></TR>'
1480        print template % ("Job ID", sessionID)
1481        print template % ("Estimated duration of job", self._sensibleTimeString(estimatedDuration))
1482        print template % ("Estimated volume of your job", "%.2f MB"%((estimatedVolume/1000000)+0.01))
1483        print "</TABLE>"
1484       
1485        print "<P>Thank you for using the %s." % PACKAGE_NAME
1486
1487        if RESTRICTED_DATA: 
1488            try:
1489                print " You will be emailed when the job has finished."
1490            except:
1491                pass
1492               
1493        print """<P><B>Click here to check the status of your request: </B>
1494                 <FORM NAME="extract_info" method="POST" action="%s">
1495                 <INPUT NAME="sessionID" TYPE="hidden" VALUE="%s"/>
1496                 <INPUT TYPE="hidden" NAME="action" VALUE="getStatus"/>
1497                 <INPUT TYPE="submit" NAME="statusGetter" VALUE="Check Status"/>
1498                 </FORM></P>""" % (CGI_SCRIPT_URL_PATH, sessionID)
1499
1500
1501    def _displayFileNameRuleOptions(self):
1502        """
1503        Prints the options for outputting to a single file or
1504        multiple files.
1505        """
1506        pass
1507       
1508
1509    def _displayRequestSummaryTable(self, summaryDict):
1510        """
1511        Prints a table summarising the current request.
1512        """
1513        print "<H3>The following is a summary of your request</H3>"
1514        print "<TABLE>"
1515        # Chop up the request information into a dictionary
1516        #(summaryDict, orderedKeys)=self._chopUpSummary(summary)
1517       
1518        d=summaryDict
1519        dsgKeys=d["datasetGroups"].keys()
1520        dsKeys=d["datasets"].keys()
1521        varKeys=d["variables"].keys()
1522        axisKeys=d["axes"].keys()
1523       
1524        dsgKeys.sort()
1525        dsKeys.sort()
1526        varKeys.sort()
1527        axisKeys.sort()
1528       
1529        template='<TR class="tablerow"><TD><B>%s%s</B></TD><TD>%s</TD></TR>'
1530       
1531        for dsg in dsgKeys:
1532            print template % ("Dataset Group ", dsg, d["datasetGroups"][dsg])       
1533           
1534            for ds in dsKeys:
1535                (dsgIndex, dsIndex)=re.match(r"^(\d+)\.(\d+)$", ds).groups()
1536                if dsg==dsgIndex:
1537                    print template % ("Dataset ", ds, d["datasets"][ds])
1538                   
1539                for var in varKeys:
1540                    (dsgIndex, dsIndex, varIndex)=re.match(r"^(\d+)\.(\d+)\.(\d+)$", var).groups()
1541                    if dsg==dsgIndex and ds=="%s.%s" % (dsgIndex, dsIndex):
1542                        print template % ("Variable ", var, d["variables"][var])
1543                        if d["outputFormats"].has_key(var):
1544                            print template % ("Output format ", var, d["outputFormats"][var])
1545
1546                        if d["datasetURIs"].has_key(var):
1547                            print template % ("Dataset URI ", var, d["datasetURIs"][var])                       
1548                       
1549                    for axis in axisKeys:
1550                        (dsgIndex, dsIndex, varIndex, axisIndex)=re.match(r"^(\d+)\.(\d+)\.(\d+)\.(\d+)$", axis).groups()
1551                        if (dsg==dsgIndex and ds=="%s.%s" % (dsgIndex, dsIndex)) and var=="%s.%s.%s" % (dsgIndex, dsIndex, varIndex):
1552                            print template % ("Axis ", axis, d["axes"][axis])
1553       
1554            print "<TR><TD>&nbsp;</TD></TR>"
1555
1556       
1557        # Now globals
1558        globalKeys=d["globals"].keys()
1559        globalKeys.sort()
1560       
1561        for key in globalKeys:
1562            if key=="outputFilePaths":
1563                value=d["globals"][key]
1564                vlist=[i[1:-1] for i in value[1:-1].split(",")]
1565                if len(vlist)>10:
1566                    value=str(vlist[:4]+["...", "..."]+vlist[-4:])
1567            else:
1568                value=d["globals"][key]
1569                if key=="estimatedDuration": value="%s seconds" % value
1570                if key=="estimatedVolume": value="%.2f MB" % (value/(2**20))
1571                if key=="userRoles": value=value[1:-1].replace("'","")
1572            print template % (key, "", value)
1573       
1574        print "</TABLE>"
1575       
1576
1577    def _displayConfirmationSection(self, summary):
1578        """
1579        Asks the user to confirm their request.
1580        """
1581        print '<P><INPUT TYPE="submit" NAME="confirm" VALUE="Confirm"> Click the "Confirm" button to fetch your request.<P>'
1582       
1583        self._displayRequestSummaryTable(summary) 
1584        print """<P>
1585             <INPUT TYPE="hidden" NAME="action" VALUE="getOutput">
1586             <INPUT TYPE="submit" NAME="confirm" VALUE="Confirm"> Click the "Confirm" button to fetch your
1587request.
1588             <BR>If you wish to modify your request please press the <I>Back</I> button on your browser.<P>"""
1589        print "</FORM><P>"
1590       
1591       
1592    def _displayOperationOptions(self):
1593        """
1594        Prints a form entry for specifying the required operation.
1595        """
1596        pass
1597       
1598       
1599    def _displayOutputFormatOptions(self, options, sessionID):
1600        """
1601        Prints the available output format options in a form.
1602        """
1603        print """<P><INPUT TYPE="checkbox" NAME="multipleFileOutput">
1604               &nbsp;Use multiple output files [ this is the default large files as limited by the server ]."""
1605               
1606        print '<P>Format&nbsp;<SELECT NAME="outputFormat">'
1607        for format in options:
1608            print "<OPTION>%s</OPTION>" % format
1609        print "</SELECT>"
1610             
1611        print "&nbsp;&nbsp; Note that you should choose NetCDF format if you wish to visualise data."
1612        #print '<P><A HREF="%s?action=saveRequest&sessionID=%s">Get Request XML only.</A>' % (CGI_SCRIPT_URL_PATH, sessionID) 
1613        print '<P><INPUT TYPE="submit" NAME="proceed" VALUE="Proceed"><P>'
1614        print "</FORM><P>"     
1615
1616
1617    def _displayProcessesTable(self):
1618        """
1619        Prints the Processes table of current dx processes running.
1620        """     
1621        pass
1622   
1623       
1624    def _displayUploadRequestOptions(self, sessionID):
1625        """
1626        Generates an upload box for the user to load their own request.
1627        The current request is then overwritten by the uploaded version.
1628        """
1629        """
1630        How might this work.
1631        At any point I can click [ Upload Old Request ] which is an XML file.
1632        It opens a dialogue box for browse and it is saved onto the server and
1633        is referenced as http://localhost/cgi-bin/dxcgi.py?uploadedRequest=something/or/other.xml
1634        Then the dx opens it and parses it in, keeping the sessionID but losing all else!
1635        NOTE: Needs a visible REQUEST_XML_DIR_LOCAL_PATH dir.
1636        """
1637        print '<FORM METHOD="post" ACTION="%s" ENCTYPE="multipart/form-data">' % CGI_SCRIPT_URL_PATH
1638        print "<P>Please provide the location of the request file you wish to upload:"
1639        print """&nbsp;<INPUT TYPE="file" NAME="uploadedFile" VALUE="" SIZE="40">
1640                       <INPUT NAME="action" TYPE="hidden" VALUE="parseUploadedFile">
1641                       <INPUT NAME="sessionID" TYPE="hidden" VALUE="%s">
1642                       <INPUT TYPE="submit" NAME="submit" VALUE="Upload"></FORM><P>""" % sessionID
1643
1644       
1645    def _displaySaveRequestOptions(self, requestString, sessionID):
1646        """
1647        Generates an XML version of the request and writes this to a file locally.
1648        Then the user is pointed to that file in the same way they would be a data
1649        file.
1650        NOTE: Needs a visible REQUEST_XML_DIR_LOCAL_PATH dir.
1651        """
1652        # Write the file to the REQUEST_XML_DIR_LOCAL_PATH
1653        xmlFileName=sessionID+".xml"
1654        xmlFile=open(os.path.join(REQUEST_XML_DIR_LOCAL_PATH, xmlFileName), "w")
1655        xmlFile.write(requestString) # =dataSubsetSpecifier file
1656        xmlFile.close()
1657       
1658        httpFilePath=os.path.join(REQUEST_XML_DIR_URL_PATH, xmlFileName)
1659       
1660        print "<P>You can download your request file from:"
1661        print '<P><A HREF="%s">%s</A><P>' % (httpFilePath, httpFilePath)
1662
1663
1664    def _displayReturnLine(self, sessionID):
1665        """
1666        Displays a link to return to request.
1667        """
1668        print '<P><A HREF="%s?sessionID=%s">Return to your current request</A><P>' % (CGI_SCRIPT_URL_PATH, sessionID)
1669       
1670
1671if __name__=="__main__":
1672    print "Testing DisplayManager.py..."
1673    DisplayManager()
Note: See TracBrowser for help on using the repository browser.