source: TI04-geosplat/trunk/pygsc/DisplayManager.py @ 1660

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI04-geosplat/trunk/pygsc/DisplayManager.py@1660
Revision 1660, 18.6 KB checked in by astephen, 15 years ago (diff)

Version with overlay of trajectories on top of model fields draft version working before any rigourous testing.

  • Property svn:executable set to *
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 package client.
11
12"""
13
14# Import standard library modules
15import os, re
16
17# Import package modules
18from clientConfig import *
19from common import *
20import jsFunctions
21
22class DisplayManager:
23    """
24    Class for displaying HTML output from the client.
25    """         
26   
27    def __init__(self):
28        """
29        Initialiser for display manager. Just gives a handle for the instance.
30        """
31        pass   
32       
33    def _displayHTTPHeader(self):
34        """
35        Prints the HTTP header.
36        """
37        print HTTP_HEADER
38       
39
40    def _displayHTMLHeader(self):
41        """
42        Prints the configured HTML header.
43        """
44        headfile=os.path.join(HTML_DIR_LOCAL_PATH, "header.html")
45        header=" ".join(open(headfile).readlines())
46        header=header.replace("PACKAGE_NAME", PACKAGE_NAME)
47        header=header.replace("WEB_EXTRAS_URL_PATH", WEB_EXTRAS_URL_PATH)
48        header=header.replace("LEFT_LOGO", os.path.join(LOGO_DIR, LEFT_LOGO))
49        header=header.replace("RIGHT_LOGO", os.path.join(LOGO_DIR, RIGHT_LOGO))
50        print header
51
52        # Now write user message if there is one:
53        if MESSAGE_TO_USERS!=None:
54            print """<CENTER><I>
55<FONT FACE="Arial, Helvetica, sans-serif" SIZE="+1" COLOR="RED">*** %s ***</FONT></I></CENTER><BR>""" % MESSAGE_TO_USERS
56
57
58    def _displayIntroduction(self):
59        """
60        Prints an introduction to the service.
61        """
62        print """<P>Welcome to the <B>%s</B>. This product is powered by Python,
63              CDAT and CSML.
64              """ % PACKAGE_NAME.replace("<BR>", " - ")
65        print """<P>Please provide a list of files (by full path on the GeoSPlAT
66              server network) that you would like to visualise. Please type each new file
67              path on a new line in the box below."""
68                     
69
70    def _displaySummaryLine(self, selectionList):
71        """
72        Prints a summary line of what has been selected so far.
73        """
74        print "<P><B>Selected so far:"
75        for item in selectionList:
76            print " -> %s" % item
77
78
79    def _displayLoginBar(self, username, loginStatus, loginMessage=""):
80        """
81        If security applies then display the login information.
82        """
83        if RESTRICTED_DATA:
84            statusMap={"out":"not logged in", "in":"logged in as %s" % username }
85            print "<P><B>Login status: </B>%s&nbsp;&nbsp;&nbsp;&nbsp;" % statusMap[loginStatus]
86            if len(loginMessage)>0:
87                print '<FONT COLOR="red">&nbsp;&nbsp;&nbsp;&nbsp;[ %s ]</FONT>' % loginMessage
88            if loginStatus=="out":
89                # Display a login form
90                print """<FORM NAME="loginForm" method="POST" action="%s">
91                      Username: <INPUT TYPE="text" SIZE="20" NAME="yousirnaim" VALUE="">
92                      Password: <INPUT TYPE="password" SIZE="10" NAME="parcewerd" VALUE="">
93                      <INPUT TYPE="submit" NAME="login" VALUE="Login"></FORM>""" % CGI_SCRIPT_URL_PATH
94            elif loginStatus=="in":
95                # Display a logout form
96                print """<FORM NAME="loginForm" method="POST" action="%s">
97                      <INPUT TYPE="submit" NAME="logout" VALUE="Logout"></FORM>""" % CGI_SCRIPT_URL_PATH                     
98                         
99       
100    def _displayHTMLFooter(self):
101        """
102        Prints the configured HTML footer.
103        """
104        footfile=os.path.join(HTML_DIR_LOCAL_PATH, "footer.html")
105        lines=open(footfile).read()
106        print lines % ("mailto:"+ADMIN_MAIL_ADDRESS)
107
108
109    def _displayErrorMessage(self, msg, sessionID=None, user=None):
110        """
111        Prints an error message, without a header or footer.
112        """
113        print "<P>An error has occurred with this application. The error message received is:<P>"
114        print "<P><B>%s</B>" % msg
115        print "<P>The administrator has been informed of this error and will look into it."
116        print """<P>You can try pressing the <I>Back</I> button to return to the previous page.
117                 Alternatively you can<P><A HREF="%s"><FONT SIZE="+1">restart your request</FONT></A>.""" % CGI_SCRIPT_URL_PATH
118       
119       
120    def _displayErrorPage(self, msg):
121        """
122        Prints an error page, including headers and footer.
123        """
124        self._displayHTTPHeader()
125        self._displayHTMLHeader()
126        self._displayErrorMessage(msg)
127
128       
129    def _displayMainTableHeader(self, sessionID):
130        """
131        Prints the header part of the main table used in the dx
132        web pages.
133        """
134        print '<TABLE WIDTH="100%"><TR>'
135               
136        print '<TABLE WIDTH="100%"><TR class="tablerow"><TD>SELECTIONS</TD></TR></TABLE>'
137        # Begin form in HTML output
138        print """<FORM NAME="splat_info" method="POST" action="%s">""" % CGI_SCRIPT_URL_PATH
139
140        print '<TABLE WIDTH="100%"><TR>'
141       
142        print '<INPUT NAME="sessionID" TYPE="hidden" VALUE="%s">' % sessionID   
143       
144       
145    def _displayMainTableFooter(self):
146        """
147        Prints the footer part of the main table used in the dx
148        web pages.
149        """
150        print "</TR></TABLE>"
151        print '<P><INPUT TYPE="submit" NAME="proceed" VALUE="Proceed"><P>'
152        print "</FORM><P>"
153
154
155    def _displayFileURIInput(self):
156        """
157        Displays the input box for the fileURIs.
158        """
159        print """<TD><TEXTAREA COLS="80" ROWS="6" SIZE="80" VALUE=""
160                 NAME="fileURIList"></TEXTAREA></TD>"""
161                 
162                 
163    def _displayVariableSelections(self, options, optionStrings):
164        """
165        Displays the variables that can be selected by users from each file.
166        """
167        print "<TD><P></TD></TR>"
168        print """<TR CLASS="tablerow"><TD><B>VARIABLE SELECTION PAGE:</B></TD></TR>"""
169        print """<TR><TD>Please select the variable that you would like GeoSPlAT to use.</TD></TR>"""
170        print "<TR><TD><BR></TD></TR>"
171       
172        # Decode the options stuff
173        fileCount=0
174       
175        checkedString=" CHECKED"
176        for option in options:
177            (fileURI, varIDs)=option
178            varLongNames=optionStrings[fileCount][1]
179           
180            print """<TR><TD CLASS="tablestyle"><B><FONT COLOR="black">FILE: %s</FONT></B><P>""" % fileURI
181            varCount=0
182           
183            for varID in varIDs:
184                print """<BR><INPUT TYPE="Checkbox" NAME="fileVariable_%s.%s" VALUE="%s"%s>
185                      &nbsp;%s
186                      """% (fileCount+1, varCount+1, varID, checkedString, varLongNames[varCount])                   
187                checkedString=""
188                varCount=varCount+1 
189               
190            fileCount=fileCount+1
191        print "</TD></TR>"
192               
193               
194    def _displayGraphicalOutputTypeSelections(self, optionCategories, options, optionStrings):
195        """
196        Displays the graphical output type options available to the user.
197        """
198        print "<TD><P></TD></TR>"
199        print """<TR CLASS="tablerow"><TD><B>GRAPHICAL OUTPUT SELECTION PAGE:</B></TD></TR>"""
200        print """<TR><TD>Please select the output that you would like GeoSPlAT to use for the chosen variable(s).</TD></TR>"""
201        print "<TR><TD><BR></TD></TR>" 
202       
203        radioName="graphicalOutputType"
204        # First go around display the single-variable options
205        print """<TR><TD CLASS="tablestyle"><B><FONT COLOR="black">SINGLE VARIABLE OPTIONS:</FONT></B>"""
206       
207        selectedFlag=" CHECKED"
208        optCounter=0
209        for option in options:
210            optCat=optionCategories[optCounter]
211            # Work out if option is single or multi-variable
212            numbers=(optCat.split("_"))[-1]
213            nVars=numbers.count("-")+1
214           
215            valueCounter=0
216           
217            if nVars==1:
218                for value in option:
219                    value=value+"_"+numbers
220                    valueString=optionStrings[optCounter][valueCounter]
221                    print """<BR><INPUT TYPE="radio" NAME="%s" VALUE="%s"%s>%s</INPUT>""" % (radioName, value, selectedFlag, valueString)
222                    if selectedFlag:
223                        selectedFlag==None
224                    valueCounter=valueCounter+1
225                               
226            optCounter=optCounter+1
227                     
228        # Second time around display the multi-variable options
229        multiVarLine="""<TR><TD CLASS="tablestyle"><B><FONT COLOR="black">MULTIPLE VARIABLE OPTIONS:</FONT></B>"""
230
231        optCounter=0
232        for option in options:
233            optCat=optionCategories[optCounter]
234            # Work out if option is single or multi-variable
235            numbers=(optCat.split("_"))[-1]
236            nVars=numbers.count("-")+1
237           
238            valueCounter=0
239           
240            if nVars>1:
241                if multiVarLine:
242                    print multiVarLine
243                    multiVarLine=None
244                   
245                for value in option:
246                    value=value+"_"+numbers
247                    valueString=optionStrings[optCounter][valueCounter]
248                    print """<BR><INPUT TYPE="radio" NAME="%s" VALUE="%s"%s>%s</INPUT>""" % (radioName, value, selectedFlag, valueString)
249                    if selectedFlag:
250                        selectedFlag==None
251                    valueCounter=valueCounter+1
252                               
253            optCounter=optCounter+1
254           
255        print "</TD></TR>"     
256   
257   
258    def _displayAnimationAxisOptions(self, optionCategories, options, optionStrings): 
259        """
260        Displays the animation axis options for the user to select.
261        """
262        print "<TD><P></TD></TR>"
263        print """<TR CLASS="tablerow"><TD><B>ANIMATION AXIS SELECTION PAGE:</B></TD></TR>"""   
264        print """<TR><TD>GeoSPlAT allows you to animate multiple frames.
265                 Please select the axes that you would like to use as:
266                 <UL>
267                 <LI>the X-axis on your plots
268                 <LI>the Y-axis on your plots
269                 <LI>the axis you would like to loop over in the animation.
270                 </UL></TD></TR>"""             
271        print "<TR><TD><BR></TD></TR>"
272               
273        print """<TR><TD><TABLE BORDER="2">"""
274       
275        print """<TR><TD>%s</TD><TD>%s</TD><TD>%s</TD><TD>%s</TD></TR>""" % \
276                   ("<B>Axis ID</B>", "<B>Long name</B>", "<B>Length</B>", "<B>Usage in plots</B>")
277       
278        # Insert javascript functions to check mutually exclusive radio selection
279        nAxes=len(options)
280        indexStringForJavascript=str(range(nAxes))
281        print jsFunctions.js_animSelectionFunctions % indexStringForJavascript
282       
283        checkedStrings=[[" CHECKED","",""], [""," CHECKED",""], ["",""," CHECKED"], ["","",""],["","",""],["","",""],["","",""]]
284        for i in range(len(options)):
285            print """<TR><TD>%s</TD><TD>%s</TD><TD>%s</TD><TD>%s&nbsp;%s&nbsp;%s&nbsp;</TD></TR>""" % \
286                  (options[i][0], optionStrings[i][0], options[i][1], 
287                  """<INPUT TYPE="Radio" NAME="axisLoopForAnimation" onclick="return validateAnimSelections('axisLoopForAnimation')" VALUE="%s"%s> Loop""" % (options[i][0], checkedStrings[i][0]), 
288                  """<INPUT TYPE="Radio" NAME="axisYForAnimation" onclick="return validateAnimSelections('axisYForAnimation')" VALUE="%s""%s> Y""" % (options[i][0], checkedStrings[i][1]),               
289                  """<INPUT TYPE="Radio" NAME="axisXForAnimation" onclick="return validateAnimSelections('axisXForAnimation')" VALUE="%s""%s> X""" % (options[i][0], checkedStrings[i][2]))
290       
291        print "</TABLE>"
292        print "</TD></TR>"
293
294
295    def _displayPlotConfigurations(self, optionCategories, options, optionStrings):
296        """
297        Displays the configuration options that can be selected by users for the chosen plot.
298        """
299        print "<TD><P></TD></TR>"
300        print """<TR CLASS="tablerow"><TD><B>GRAPHICAL CONFIGURATION PAGE:</B></TD></TR>"""
301        print """<TR><TD>Please select the options that you would like GeoSPlAT to use.</TD></TR>"""
302        print "<TR><TD><BR></TD></TR>"         
303       
304        onChangeJavaScriptFuncs={"File Format":"DO THESE ONE DAY"}
305       
306        print """<TR><TD><TABLE BORDERWIDTH="0">"""
307       
308        optCounter=0
309        for optcat in optionCategories:
310            optcat=optcat.split("_")[0]
311            optionList=options[optCounter]
312            if optionList==["UNAVAILABLE"]: 
313                optCounter=optCounter+1
314                continue
315           
316            onChangeString=" onCHANGEJLKSDFJDSLjfdslk"
317           
318            print """<TR><TD CLASS="tablestyle"><P><B>%s:</TD><TD><SELECT NAME="%s"%s>""" % (makeSpacesBetweenCaps(optcat), optcat, onChangeString)
319                     
320            valueCounter=0
321            selectedString=[" SELECTED"]+([""]*1000)
322           
323            for value in options[optCounter]:
324                valueString=optionStrings[optCounter][valueCounter]
325                   
326                print """<OPTION VALUE="%s"%s>%s</OPTION>""" % (value, selectedString[valueCounter], valueString)
327                valueCounter=valueCounter+1
328               
329            optCounter=optCounter+1     
330            print "</SELECT></TD></TR>"
331           
332           
333        print "</TABLE></TD></TR>"
334           
335           
336    def _displayProcessingWaiter(self):
337        """
338        Displays some text about having to wait.
339        """
340        print """<TR><TD CLASS="tablestyle"><B>RESULTS PAGE</B><P>Please wait while your visualisation is being generated.<P></TD>"""
341       
342
343    def _displayUploadForm(self, sessionID):
344        """
345        Displays a form entry for browsing the local system
346        to upload a file. UPLOAD_TEMP_DIR needs to be configured in
347        the clientConfig.py module.
348        """
349        print '<FORM METHOD="post" ACTION="%s" ENCTYPE="multipart/form-data">' % CGI_SCRIPT_URL_PATH
350        print "<P>Please provide the location of the request file you wish to upload:"
351        print """&nbsp;<INPUT TYPE="file" NAME="uploadedFile" VALUE="" SIZE="40">
352                       <INPUT NAME="action" TYPE="hidden" VALUE="parseUploadedFile">
353                       <INPUT NAME="sessionID" TYPE="hidden" VALUE="%s">
354                       <INPUT TYPE="submit" NAME="submit" VALUE="Upload"></FORM><P>\n<FORM>""" % sessionID
355
356
357
358    def _displayOutputPage(self, outputFilePaths):
359        """
360        Displays full HTML page with a link to the output file.
361        """
362        if len(outputFilePaths)==1:
363            file=outputFilePaths[0]
364            print "<P><B>Your output file is available at:</B>"
365            print """<P><A HREF="%s">%s</A><P>""" % (file, file) 
366        else:
367            print "<P><B>Your output files are available at:</B><P>"
368            for file in outputFilePaths:
369                print """<A HREF="%s">%s</A><BR>""" % (file, file) 
370
371        if DATA_EXTRACTOR_URL_PATH not in (None, ""):
372            print '<P><A HREF="%s">Start new Data Extraction</A>.<P>' % DATA_EXTRACTOR_URL_PATH
373        print '<P><A HREF="%s">Re-start GeoSPlAT session</A>.<P>' % CGI_SCRIPT_URL_PATH
374       
375                     
376
377    def _chopUpSummary(self, summary):
378        """
379        Chops up the summary string returning a dictionary of items and a
380        list of keys for that dictionary ordered in an appropriate manner.
381        """
382        summaryDict={}
383        orderedKeys=[]
384        for line in summary.split("\n"):
385            if line.find(":")>-1:
386                (key, value)=line.strip().split(":\t")
387                summaryDict[key]=value
388                orderedKeys.append(key) 
389        return (summaryDict, orderedKeys)               
390
391
392    def _displayOutputFile(self, path):
393        """
394        Prints links to the file the user has requested.
395        """
396        print "<H3>Output information:</H3>"   
397        print """Your output file been successfully written and is now available at:
398              <A HREF="%s">%s</A>.""" % (path, path)
399        if path.split(".")[-1].lower()=="gif":
400            print """<P>Your output should also appear below when completed (Note: this may
401                  take longer than this web page takes to render).
402                  <P><IMG SRC="%s" BORDER="2" ALT="Your plot should appear here."><P>
403                  """ % path
404
405        if DATA_EXTRACTOR_URL_PATH not in (None, ""):
406            print '<P><A HREF="%s">Start new Data Extraction</A>.<P>' % DATA_EXTRACTOR_URL_PATH
407        print '<P><A HREF="%s">Re-start GeoSPlAT session</A>.<P>' % CGI_SCRIPT_URL_PATH
408
409       
410    def _displayProcessingSection(self, estimatedDuration, estimatedVolume, sessionID):
411        """
412        Method to tell user that there job is underway with details of their selection.
413        """
414        print """<H3>Processing Information:</H3>
415              <P>Your <B>job ID</B> is: %s
416              <P>The estimated duration of your job is:  %s """ %  (sessionID, self._sensibleTimeString(estimatedDuration))
417        print "<P>The estimated volume of your job is: %.2f MB" % (estimatedVolume/1000000)
418        print "<P>Your extraction is running...</P>"
419       
420        if estimatedDuration>60: 
421            try:
422                mailAddr=getUserEmail() 
423                print "<P>You will be emailed at %s when the job has finished and the output is ready." % mailAddr       
424            except:
425                pass
426               
427        print "<P>Thank you for using the %s." % PACKAGE_NAME
428        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>"
429       
430
431    def _displayRequestSummaryTable(self, summary):
432        """
433        Prints a table summarising the current request.
434        """
435        print "<H3>The following is a summary of your request</H3>"
436        print "<TABLE>"
437        # Chop up the request information into a dictionary
438        (summaryDict, orderedKeys)=self._chopUpSummary(summary)
439               
440        for key in orderedKeys:
441            print '<TR class="tablerow"><TD><B>%s</B></TD><TD>%s</TD></TR>' % (key, summaryDict[key])
442       
443        print "</TABLE>"
444       
445
446    def _displayConfirmationSection(self, summary):
447        """
448        Asks the user to confirm their request.
449        """
450        print '<INPUT NAME="action" TYPE="hidden" VALUE="createOutput">' 
451        print '<P><INPUT TYPE="submit" NAME="confirm" VALUE="Confirm"> Click the "Confirm" button to fetch your request.<P>'
452       
453        self._displayRequestSummaryTable(summary) 
454
455        print """<P><INPUT TYPE="submit" NAME="confirm" VALUE="Confirm"> Click the "Confirm" button to fetch your request.
456        <BR>If you wish to modify your request please press the <I>Back</I> button on your browser.<P>"""
457        print "</FORM><P>"
458
459
460    def _displayProcessesTable(self):
461        """
462        Prints the Processes table of current dx processes running.
463        """     
464        pass
465   
466       
467    def _displayUploadRequestOptions(self, sessionID):
468        """
469        Generates an upload box for the user to load their own request.
470        The current request is then overwritten by the uploaded version.
471        """
472        """
473        How might this work.
474        At any point I can click [ Upload Old Request ] which is an XML file.
475        It opens a dialogue box for browse and it is saved onto the server and
476        is referenced as http://localhost/cgi-bin/dxcgi.py?uploadedRequest=something/or/other.xml
477        Then the dx opens it and parses it in, keeping the sessionID but losing all else!
478        NOTE: Needs a visible REQUEST_XML_DIR dir.
479        """
480        print '<FORM METHOD="post" ACTION="%s" ENCTYPE="multipart/form-data">' % CGI_SCRIPT_URL_PATH
481        print "<P>Please provide the location of the request file you wish to upload:"
482        print """&nbsp;<INPUT TYPE="file" NAME="uploadedFile" VALUE="" SIZE="40">
483                       <INPUT NAME="action" TYPE="hidden" VALUE="parseUploadedFile">
484                       <INPUT NAME="sessionID" TYPE="hidden" VALUE="%s">
485                       <INPUT TYPE="submit" NAME="submit" VALUE="Upload"></FORM><P>""" % sessionID
486
487       
488    def _displaySaveRequestOptions(self, requestString, sessionID):
489        """
490        Generates an XML version of the request and writes this to a file locally.
491        Then the user is pointed to that file in the same way they would be a data
492        file.
493        NOTE: Needs a visible REQUEST_XML_DIR dir.
494        """
495        # Write the file to the REQUEST_XML_DIR
496        xmlFileName=sessionID+".xml"
497        xmlFile=open(os.path.join(REQUEST_XML_DIR, xmlFileName), "w")
498        xmlFile.write(requestString) # =dataSubsetSpecifier file
499        xmlFile.close()
500       
501        httpFilePath=os.path.join(HTTP_REQUEST_XML_DIR, xmlFileName)
502       
503        print "<P>You can download your request file from:"
504        print '<P><A HREF="%s">%s</A><P>' % (httpFilePath, httpFilePath)
505
506
507    def _displayReturnLine(self, sessionID):
508        """
509        Displays a link to return to request.
510        """
511        print '<P><A HREF="%s?sessionID=%s">Return to your current request</A><P>' % (CGI_SCRIPT_URL_PATH, sessionID)
512       
Note: See TracBrowser for help on using the repository browser.