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

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

Safe version pre-security installation and zsi versioning.

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