1#!@WHICHPYTHON@
2"""
3  CGI Module for checking on the status of an OPAL job
4"""
5
6__date__   = "4 January 2010"
7__author__ = "Wes Goodman, Samir Unni, Yong Huang"
8
9import sys
10import cgi
11import cgitb
12import os,shutil,glob,string,time,urllib
13from datetime import timedelta
14from src.server import *
15from src.aconf import *
16from src.utilities import getTrackingScriptString, getEventTrackingString
17
18cgitb.enable()
19form = cgi.FieldStorage()
20
21def printheader(pagetitle,refresh=None,jobid=None):
22    str = ""
23    str+= "<html>\n"
24    str+= "<HEAD>\n"
25    str+= '<img src="https://raw.githubusercontent.com/Electrostatics/apbs-pdb2pqr/master/apbs/doc/icons/APBS_128_v2.png" style="float:right; position:relative;right:200px; top: 2px;">'
26    if refresh:
27        str+= "\t<META HTTP-EQUIV=\"Refresh\" CONTENT=\"%s\">\n" % refresh
28    str+= "\t<TITLE>%s</TITLE>\n" % pagetitle
29    str+= "\t<link rel=\"stylesheet\" href=\"%s\" type=\"text/css\">\n" % STYLESHEET
30    str+= getTrackingScriptString(jobid)
31    str+= "</HEAD>\n"
32    return str
33
34def createcube(dx_input, pqr_input, output):
35
36    with open(dx_input, 'r') as in_f, open(output, 'w') as out_f, open(pqr_input, 'r') as in_pqr:
37        out_f.write("CPMD CUBE FILE.\n"
38                    "OUTER LOOP: X, MIDDLE LOOP: Y, INNER LOOP: Z\n")
39
40        #Discard comments at top of file.
41        line = in_f.readline()
42        newline = in_pqr.readline()
43        while line.startswith('#'):
44            line = in_f.readline()
45
46
47        split_line = line.split()
48        grid_sizes = [int(x)*-1 for x in split_line[-3:]]
49
50        split_line = in_f.readline().split()
51
52        origin = [float(x) for x in split_line[-3:]]
53
54        parameter_fmt = "{:>4} {:>11.6f} {:>11.6f} {:>11.6f}\n"
55        atom_num = 0
56        while newline.startswith('REMARK'):
57            newline = in_pqr.readline()
58
59        try:
60            while newline.startswith('ATOM') or newline.startswith('HETATM'):
61                newline =  in_pqr.readline()
62                new_split_line = newline.split()
63                atom_num = new_split_line[1]
64        except IndexError:
65            pass
66        in_pqr.seek(0)
67        newline = in_pqr.readline()
68        while newline.startswith('REMARK'):
69            newline = in_pqr.readline()
70
71        origin_line = parameter_fmt.format(atom_num, *origin)
72        out_f.write(origin_line)
73
74
75        for x in xrange(3):
76            split_line = in_f.readline().split()
77            grid_dims = [float(item) for item in split_line[-3:]]
78
79            dim_lin = parameter_fmt.format(grid_sizes[x], *grid_dims)
80            out_f.write(dim_lin)
81
82        atoms_parameter_fmt = "{:>4} {:>11.6f} {:>11.6f} {:>11.6f} {:>11.6f}\n"
83        a = True
84        xreal_center = []
85        yreal_center = []
86        zreal_center = []
87        try:
88            while newline.startswith('ATOM') or newline.startswith('HETATM'):
89                new_split_line = newline.split()
90                radius = new_split_line[-1]
91                xyz = new_split_line[-5:-2]
92                line_atom_num = new_split_line[1]
93                atom_radius = new_split_line[-1]
94                pqr_lin = atoms_parameter_fmt.format(int(line_atom_num), float(new_split_line[-2]), float(xyz[0]), float(xyz[1]), float(xyz[2]))
95                out_f.write(pqr_lin)
96                newline = in_pqr.readline()
97                xreal_center.append(float(xyz[0]))
98                yreal_center.append(float(xyz[1]))
99                zreal_center.append(float(xyz[2]))
100        except IndexError:
101            pass
102
103        x_avg = sum(xreal_center)/float(atom_num)
104        y_avg = sum(yreal_center)/float(atom_num)
105        z_avg = sum(zreal_center)/float(atom_num)
106
107        #print origin
108        #new_origin = []
109        #for item in origin:
110        #    newitem = item/0.529177
111            #new_new = item/2 + newitem/2
112        #    new_origin.append(newitem)
113        #print new_origin
114
115        #Consume unneeded object lines.
116        in_f.readline()
117        in_f.readline()
118
119        ##TODO: put atoms here
120
121        value_format = ["{:< 13.5E}"]
122        value_format = ' '.join(value_format * 6) + '\n'
123        group = []
124        line = in_f.readline()
125        while not line.startswith('attribute'):
126            values = [float(item) for item in line.split()]
127            group.extend(values)
128
129            if len(group) >= 6:
130                out_f.write(value_format.format(*group))
131                group = []
132
133            line = in_f.readline()
134
135        if group:
136            group_strs = ["{:< 13.5E}".format(item) for item in group]
137            out_f.write(' '.join(group_strs))
138
139def checkprogress(jobid=None,appServicePort=None,calctype=None):
140    """
141        Finds out if the job has been completed
142    """
143
144    if have_opal:
145
146        # construct soap request
147        try:
148            status=appServicePort.queryStatus(queryStatusRequest(jobid))
149        except Exception, e:
150            return ["error"]
151        if status._code == 4:
152            return ["error"]
153
154        if status._code == 8:
155            return ["complete",status]
156        else:
157            return ["running",status]
158
159    else:
160        progress = []
161        file = open('%s%s%s/%s_status' % (INSTALLDIR,TMPDIR,jobid, form["calctype"].value))
162
163        for line in file.readlines():
164            progress.append(string.strip(line))
165        file.close()
166        return progress
167
168def mainCGI():
169    """
170        Main method for determining the query page output
171    """
172    logopts = {}
173    print "Content-type: text/html\n\n"
174    calctype = form["calctype"].value
175
176    # prints version error, if it exists
177    if form["jobid"].value == 'False':
178        print printheader("%s Job Status Page" % calctype.upper())
179        progress = "version_mismatch"
180        runtime = 0
181    elif form["jobid"].value == 'notenoughmem':
182        print printheader("%s Job Status Page" % calctype.upper())
183        progress = "not_enough_memory"
184        runtime = 0
185    else:
186        progress = None
187
188    #Check for error html
189    errorpath = '%s%s%s.html' % (INSTALLDIR, TMPDIR, form["jobid"].value)
190    if os.path.isfile(errorpath):
191        string = ""
192        string+= "<html>\n"
193        string+= "\t<head>\n"
194        string+= "\t\t<meta http-equiv=\"Refresh\" content=\"0; url=%s%s%s.html\">\n" % (WEBSITE, TMPDIR, form["jobid"].value)
195        string+= "\t</head>\n"
196        string+= "</html>\n"
197        print string
198        return
199
200    # prepares for Opal query, if necessary
201    if have_opal:
202        if calctype=="pdb2pqr":
203            opal_url = PDB2PQR_OPAL_URL
204        elif calctype=="apbs":
205            opal_url = APBS_OPAL_URL
206        appLocator = AppServiceLocator()
207        appServicePort = appLocator.getAppServicePort(opal_url)
208    else:
209        appServicePort = None
210
211    # if PDB2PQR, determines if link to APBS calculation should be shown
212    if calctype=="pdb2pqr":
213        #if(form["apbsinput"].value=="True"): # change to use a file
214        #    apbs_input = True
215        #else:
216        #    apbs_input = False
217        apbsInputFile = open('%s%s%s/apbs_input' % (INSTALLDIR, TMPDIR, form["jobid"].value))
218        apbs_input = apbsInputFile.read()
219        apbsInputFile.close()
220        if apbs_input=="True":
221            apbs_input = True
222        else:
223            apbs_input = False
224
225        typemapInputFile = open('%s%s%s/typemap' % (INSTALLDIR, TMPDIR, form["jobid"].value))
226        typemap = typemapInputFile.read()
227        typemapInputFile.close()
228        if typemap=="True":
229            typemap = True
230        else:
231            typemap = False
232
233    if have_opal and progress == None:
234        if form["calctype"].value=="pdb2pqr":
235            pdb2pqrJobIDFile = open('%s%s%s/pdb2pqr_opal_job_id' % (INSTALLDIR, TMPDIR, form["jobid"].value))
236            jobid = pdb2pqrJobIDFile.read()
237            pdb2pqrJobIDFile.close()
238        elif form["calctype"].value=="apbs":
239            apbsJobIDFile = open('%s%s%s/apbs_opal_job_id' % (INSTALLDIR, TMPDIR, form["jobid"].value))
240            jobid = apbsJobIDFile.read()
241            apbsJobIDFile.close()
242    else:
243        jobid = form["jobid"].value
244
245    if progress == None:
246        cp = checkprogress(jobid,appServicePort,calctype) # finds out status of job
247        progress = cp[0]
248
249    #initialize with bogus value just in case
250    starttime = time.time()
251
252    if progress == "running" or progress == "complete":
253        timefile = open('%s%s%s/%s_start_time' % (INSTALLDIR, TMPDIR, form["jobid"].value, form["calctype"].value))
254        starttime = float(timefile.read())
255        timefile.close()
256
257    if progress == "running" or (have_opal and progress not in ("version_mismatch",
258                                                                "not_enough_memory",
259                                                                "error",
260                                                                "complete")):
261        runtime = time.time()-starttime
262        runtime = int(runtime)
263
264    elif progress == "complete":
265        endTimeFileString = '%s%s%s/%s_end_time' % (INSTALLDIR, TMPDIR, form["jobid"].value, form["calctype"].value)
266        if have_opal and not os.path.isfile(endTimeFileString):
267            runtime = time.time()-starttime
268            with open(endTimeFileString, 'w') as endTimeFile:
269                endTimeFile.write(str(time.time()))
270        else:
271            with open(endTimeFileString, 'r') as endTimeFile:
272                runtime = float(endTimeFile.read())-starttime
273    else:
274        runtime = -1
275
276    if progress == "running":
277        #if have_opal:
278        #    resultsurl = cp[1]._baseURL
279        #else:
280        if calctype=="pdb2pqr":
281            resultsurl = '%squerystatus.cgi?jobid=%s&apbsinput=%s&calctype=pdb2pqr' % (WEBSITE, form["jobid"].value, apbs_input)
282        else:
283            resultsurl = '%squerystatus.cgi?jobid=%s&calctype=apbs' % (WEBSITE, form["jobid"].value)
284
285    if progress == "complete":
286        print printheader("%s Job Status Page" % calctype.upper(), jobid=form["jobid"].value)
287
288    elif progress == "error":
289        print printheader("%s Job Status Page - Error" % calctype.upper(),0, jobid=form["jobid"].value)
290
291    elif progress == "running": # job is not complete, refresh in 30 seconds
292        print printheader("%s Job Status Page" % calctype.upper(), refresh, jobid=form["jobid"].value)
293
294    print "<BODY>\n<P>"
295    print "<p></p>"
296    print '<div id="content">'
297    print "<h3>Status:"
298
299    color = "FA3434"
300    image = WEBSITE+"images/red_x.png"
301
302    if progress == "complete":
303        color = "2CDE56"
304        image = WEBSITE+"images/green_check.png"
305    elif progress == "running":
306        color = "ffcc00"
307        image = WEBSITE+"images/yellow_exclamation.png"
308
309    print "<strong style=\"color:#%s;\">%s</strong>" % (color, progress)
310    print "<img src=\"%s\"><br />" % image
311    print "</h3>"
312    print "Run time: " + str(timedelta(seconds=round(runtime))) + '<br />'
313    print "Current time: %s<br />" % time.asctime()
314    print "</P>\n<HR>\n<P>"
315
316    if progress == "complete":
317        if calctype=="pdb2pqr":
318            nexturl = 'apbs_cgi.cgi?jobid=%s' % form["jobid"].value
319        else:
320            url_3dmol = 'visualize.cgi?jobid=%s&tool=%s' % (form["jobid"].value,'tool_3dmol')
321            url_jmol = 'visualize.cgi?jobid=%s&tool=%s' % (form["jobid"].value,'tool_jmol')
322
323
324        if have_opal:
325            resp = appServicePort.getOutputs(getOutputsRequest(jobid))
326            filelist = resp._outputFile
327
328        print "Here are the results:<ul>"
329        print "<li>Input files<ul>"
330
331        if calctype=="pdb2pqr":
332            # this code should be cleaned up once local PDB2PQR runs output the PDB file with the .pdb extension
333            if have_opal:
334                for i in range(0,len(filelist)):
335                    file_name = filelist[i]._name
336                    if ((len(file_name) == 4 and '.' not in file_name) or
337                        (file_name.lower().endswith(".pdb") and "pdb2pka_output" not in file_name)):
338                        print "<li><a href=%s>%s</a></li>" % (filelist[i]._url, filelist[i]._name)
339
340                    if file_name.lower().endswith((".mol", ".mol2", ".names", ".dat")) and "pdb2pka_output" not in file_name:
341                        print "<li><a href=%s>%s</a></li>" % (filelist[i]._url, filelist[i]._name)
342
343
344            else:
345                print "<li><a href=%s%s%s/%s.pdb>%s.pdb</a></li>" % (WEBSITE, TMPDIR, jobid, jobid, jobid)
346
347        elif calctype=="apbs":
348            if have_opal:
349                for i in range(0,len(filelist)):
350                    if filelist[i]._name == "apbsinput.in" or filelist[i]._name[-4:] == ".pqr":
351                        print "<li><a href=%s>%s</a></li>" % (filelist[i]._url, filelist[i]._name)
352            else:
353                print "<li><a href=%s%s%s/apbsinput.in>apbsinput.in</a></li>" % (WEBSITE, TMPDIR, jobid)
354                print "<li><a href=%s%s%s/%s.pqr>%s.pqr</a></li>" % (WEBSITE, TMPDIR, jobid, jobid, jobid)
355
356        print "</ul></li>"
357        print "<li>Output files<ul>"
358
359        queryString = [str(os.environ["REMOTE_ADDR"])]
360        # Getting PDB2PQR run log info
361        if os.path.isfile('%s%s%s/pdb2pqr_log' % (INSTALLDIR, TMPDIR, jobid)):
362            pdb2pqrLogFile=open('%s%s%s/pdb2pqr_log' % (INSTALLDIR, TMPDIR, jobid), 'r')
363            logstr=pdb2pqrLogFile.read().split('\n')
364            templogopts = eval(logstr[0])
365            pdb2pqrLogFile.close()
366            queryString.insert(0, templogopts.get('pdb',''))
367
368        if calctype=="pdb2pqr":
369            if have_opal:
370                for i in range(0,len(filelist)):
371                    if filelist[i]._name.endswith((".propka", "-typemap.html")):
372                        print "<li><a href=%s>%s</a></li>" % (filelist[i]._url, filelist[i]._name)
373
374                    if filelist[i]._name.endswith(".in") and "pdb2pka_output" not in filelist[i]._name:
375                        print "<li><a href=%s>%s</a></li>" % (filelist[i]._url, filelist[i]._name)
376
377                    if filelist[i]._name.endswith(".pqr") and not filelist[i]._name.endswith("background_input.pqr"):
378                        print "<li><a href=%s>%s</a></li>" % (filelist[i]._url, filelist[i]._name)
379
380                    #Get the first line of the summary file.
381                    if filelist[i]._name.endswith(".summary"):
382                        f=urllib.urlopen(filelist[i]._url)
383                        summaryLine = f.readline().strip()
384                        #logopts["pdb"]=logopts.get("pdb", "") + "|" + summaryLine
385                        queryString.append(summaryLine)
386                        f.close()
387#                logRun(logopts, runtime, pqrOpalFileLength, logff, REMOTE_ADDR)
388            else:
389                #Get the first line of the summary file.
390                summaryFile = '%s%s%s/%s%s' % (INSTALLDIR, TMPDIR, jobid, jobid, ".summary")
391                if os.path.isfile(summaryFile):
392                    with open(summaryFile) as f:
393                        summaryLine = f.readline().strip()
394                        #logopts["pdb"]=logopts.get("pdb", "") + "|" + summaryLine
395                        queryString.append(summaryLine)
396
397                outputfilelist = glob.glob('%s%s%s/*.propka' % (INSTALLDIR, TMPDIR, jobid))
398                for i in range(0,len(outputfilelist)):
399                    outputfilelist[i] = os.path.basename(outputfilelist[i])
400                for extension in ["-typemap.html", ".pqr", ".in"]:
401                    if extension != ".in" or apbs_input != False:
402                        if extension == "-typemap.html" and typemap == False:
403                            continue
404                        outputfilelist.append('%s%s' % (jobid, extension))
405                for outputfile in outputfilelist:
406                    print "<li><a href=%s%s%s/%s>%s</a></li>" % (WEBSITE, TMPDIR, jobid, outputfile, outputfile)
407
408            logopts['queryPDB2PQR'] = '|'.join(queryString)
409
410                #for extension in ["-typemap.html", ".pqr", ".in"]:
411                #    print "<li><a href=%s%s%s/%s%s>%s%s</a></li>" % (WEBSITE, TMPDIR, jobid, jobid, extension, jobid, extension)
412        elif calctype=="apbs":
413            if have_opal:
414                for i in range(0,len(filelist)):
415                    if filelist[i]._name[-3:]==".dx":
416                        # compressing APBS OpenDX output files
417                        currentpath = os.getcwd()
418                        zipjobid = filelist[i]._name.split("-")[0]
419                        dxfilename = '%s%s%s/%s' % (INSTALLDIR, TMPDIR, zipjobid, filelist[i]._name)
420                        urllib.urlretrieve(filelist[i]._url, dxfilename)
421                        os.chdir('%s%s%s' % (INSTALLDIR, TMPDIR, zipjobid))
422                        # making both the dx file and the compressed file (.gz) available in the directory
423                        syscommand = 'cp %s dxbkupfile' % (filelist[i]._name)
424                        os.system(syscommand)
425                        syscommand = 'gzip -9 ' + filelist[i]._name
426                        os.system(syscommand)
427                        syscommand = 'mv dxbkupfile %s' % (filelist[i]._name)
428                        os.system(syscommand)
429                        outputfilezip = filelist[i]._name + '.gz'
430
431                        pqrfilename = '%s%s%s/%s.pqr' % (INSTALLDIR, TMPDIR, zipjobid, zipjobid)
432                        cubefilename = '%s%s%s/%s.cube' % (INSTALLDIR, TMPDIR, zipjobid, zipjobid)
433
434                        # making both the cube file and the compressed file (.gz) available in the directory
435                        createcube(dxfilename, pqrfilename, cubefilename)
436                        cubefilebasename = os.path.basename(cubefilename)
437
438                        syscommand = 'cp %s cubebkupfile' % cubefilebasename
439                        os.system(syscommand)
440                        syscommand = 'gzip -9 ' + cubefilebasename
441                        os.system(syscommand)
442                        syscommand = 'mv cubebkupfile %s' % cubefilebasename
443                        os.system(syscommand)
444                        os.chdir(currentpath)
445                        outputcubefilezip = cubefilebasename+".gz"
446
447                        print "<li><a href=%s%s%s/%s>%s</a></li>" % (WEBSITE, TMPDIR, zipjobid, outputfilezip, outputfilezip)
448                        print "<li><a href=%s%s%s/%s>%s</a></li>" % (WEBSITE, TMPDIR, zipjobid, outputcubefilezip, outputcubefilezip)
449
450            else:
451                outputfilelist = glob.glob('%s%s%s/%s-*.dx' % (INSTALLDIR, TMPDIR, jobid, jobid))
452                for dxfile in outputfilelist:
453                    # compressing APBS OpenDX output files
454                    currentpath = os.getcwd()
455                    workingpath = os.path.dirname(dxfile)
456                    os.chdir(workingpath)
457                    # making both the dx file and the compressed file (.gz) available in the directory
458                    syscommand = 'cp %s dxbkupfile' % (os.path.basename(dxfile))
459                    os.system(syscommand)
460                    syscommand = 'gzip -9 ' + os.path.basename(dxfile)
461                    os.system(syscommand)
462                    syscommand = 'mv dxbkupfile %s' % (os.path.basename(dxfile))
463                    os.system(syscommand)
464                    os.chdir(currentpath)
465                    outputfilezip = dxfile+".gz"
466
467
468
469                    cubefilename = '%s%s%s/%s.cube' % (INSTALLDIR, TMPDIR, jobid, jobid)
470                    pqrfilename = '%s%s%s/%s.pqr' % (INSTALLDIR, TMPDIR, jobid, jobid)
471
472
473                    createcube(dxfile, pqrfilename, cubefilename)
474
475                    print "<li><a href=%s%s%s/%s>%s</a></li>" % (WEBSITE, TMPDIR, jobid, os.path.basename(outputfilezip), os.path.basename(outputfilezip))
476
477                outputcubefilelist = glob.glob('%s%s%s/%s.cube' % (INSTALLDIR, TMPDIR, jobid, jobid))
478                for cubefile in outputcubefilelist:
479                    # compressing cube output file
480                    currentpath = os.getcwd()
481                    os.chdir(workingpath)
482                    # making both the cube file and the compressed file (.gz) available in the directory
483                    syscommand = 'cp %s cubebkupfile' % (os.path.basename(cubefile))
484                    os.system(syscommand)
485                    syscommand = 'gzip -9 ' + os.path.basename(cubefile)
486                    os.system(syscommand)
487                    syscommand = 'mv cubebkupfile %s' % (os.path.basename(cubefile))
488                    os.system(syscommand)
489                    os.chdir(currentpath)
490                    outputcubefilezip = cubefile+".gz"
491
492                    print "<li><a href=%s%s%s/%s>%s</a></li>" % (WEBSITE, TMPDIR, jobid, os.path.basename(outputcubefilezip), os.path.basename(outputcubefilezip))
493
494            logopts['queryAPBS'] = '|'.join(queryString)
495
496        if calctype=="pdb2pqr":
497            if have_opal:
498                outputfilelist = []
499                for i in range(0,len(filelist)):
500                    if filelist[i]._name.endswith((".DAT", ".txt")):
501                        outputfilelist.append((filelist[i]._url, os.path.basename(filelist[i]._name)))
502                        #print "<li><a href=%s>%s</a></li>" % (filelist[i]._url, filelist[i]._name)
503                if outputfilelist:
504                    print "</ul></li>"
505                    print "<li>PDB2PKA files<ul>"
506                    for outputfile in outputfilelist:
507                        print "<li><a href=%s>%s</a></li>" % (outputfile[0], outputfile[1])
508            else:
509                outputfilelist = glob.glob('%s%s%s/pdb2pka_output/*.DAT' % (INSTALLDIR, TMPDIR, jobid))
510                outputfilelist.extend(glob.glob('%s%s%s/pdb2pka_output/*.txt' % (INSTALLDIR, TMPDIR, jobid)))
511                outputfilelist = [os.path.basename(outputfile) for outputfile in outputfilelist]
512                if outputfilelist:
513                    print "</ul></li>"
514                    print "<li>PDB2PKA files<ul>"
515                    for outputfile in outputfilelist:
516                        print "<li><a href=%s%s%s/pdb2pka_output/%s>%s</a></li>" % (WEBSITE, TMPDIR, jobid, outputfile, outputfile)
517
518        print "</ul></li>"
519        print "<li>Runtime and debugging information<ul>"
520
521        if have_opal:
522            stdouturl = resp._stdOut
523            stderrurl = resp._stdErr
524        else:
525            stdouturl = "%s%s%s/%s_stdout.txt" % (WEBSITE, TMPDIR, jobid, calctype)
526            stderrurl = "%s%s%s/%s_stderr.txt" % (WEBSITE, TMPDIR, jobid, calctype)
527
528        print "<li><a href=%s>Program output (stdout)</a></li>" % stdouturl
529        print "<li><a href=%s>Program errors and warnings (stderr)</a></li>" % stderrurl
530
531
532        print "</ul></li></ul>"
533
534
535        #if have_opal:
536        #    resp = appServicePort.getOutputs(getOutputsRequest(jobid))
537        #    for opalfile in resp._outputFile:
538        #        if opalfile._name[-8:]!="-input.p":
539        #            print "<li><a href=%s>%s</a></li>" % (opalfile._url, opalfile._name)
540        #    print "<li><a href=%s>Standard output</a></li>" % (resp._stdOut)
541        #    print "<li><a href=%s>Standard error</a></li>" % (resp._stdErr)
542        #else:
543        #    for line in cp[1:]:
544        #        line = os.path.basename(line)
545        #        if line[-8:]!="-input.p":
546        #            if line[-11:]=="_stdout.txt":
547        #                printname = "Standard output"
548        #            elif line[-11:]=="_stderr.txt":
549        #                printname = "Standard error"
550        #            else:
551        #                printname = line
552        #            print "<li><a href=%s>%s</a></li>" % (WEBSITE+TMPDIR+jobid+"/"+line,printname)
553
554        if calctype=="pdb2pqr" and apbs_input and HAVE_APBS:
555            print "</ul></p><hr><p><b><a href=%s>Click here</a> to run APBS with your results.</b></p>" % nexturl
556        elif calctype=="apbs":
557            #print "</ul></p><hr><p><b><a href=%s>Click here</a> to visualize your results in Jmol.</b></p>" % nexturl
558            print "</ul></p><hr><p><b>Visualize your results online:"
559            print "<ul> <li><a href=%s>3Dmol</a></li><li><a href=%s>Jmol</a></li></ul>" % (url_3dmol, url_jmol)
560
561    elif progress == "error":
562        print "There was an error with your query request. This page will not refresh."
563
564        print "</ul></li>"
565        print "<li>Runtime and debugging information<ul>"
566
567        if have_opal:
568            resp = appServicePort.getOutputs(getOutputsRequest(jobid))
569            stdouturl = resp._stdOut
570            stderrurl = resp._stdErr
571
572        else:
573            stdouturl = "%s%s%s/%s_stdout.txt" % (WEBSITE, TMPDIR, jobid, calctype)
574            stderrurl = "%s%s%s/%s_stderr.txt" % (WEBSITE, TMPDIR, jobid, calctype)
575
576        print "<li><a href=%s>Program output (stdout)</a></li>" % stdouturl
577        print "<li><a href=%s>Program errors and warnings (stderr)</a></li>" % stderrurl
578
579        print "</ul></li></ul>"
580
581        if have_opal:
582            print " <br />If your job has been running for a prolonged period of time and failed with no reason listed in the standard out or standard error, then the job probably timed out and was terminated by the system.<br />"
583
584        print '<br />If you are having trouble running PDB2PQR on the webserver, please download the <a href="http://www.poissonboltzmann.org/docs/downloads/">command line version of PDB2PQR</a> and run the job from there.'
585
586
587
588    elif progress == "running":
589        print "Page will refresh in %d seconds<br />" % refresh
590        print "<HR>"
591
592        if not have_opal:
593            print "</ul></li>"
594            print "<li>Runtime and debugging information<ul>"
595            stdouturl = "%s%s%s/%s_stdout.txt" % (WEBSITE, TMPDIR, jobid, calctype)
596            stderrurl = "%s%s%s/%s_stderr.txt" % (WEBSITE, TMPDIR, jobid, calctype)
597            print "<li><a href=%s>Program output (stdout)</a></li>" % stdouturl
598            print "<li><a href=%s>Program errors and warnings (stderr)</a></li>" % stderrurl
599            print "</ul></li></ul>"
600
601        print "<small>Your results will appear at <a href=%s>this page</a>. If you want, you can bookmark it and come back later (note: results are only stored for approximately 12-24 hours).</small>" % resultsurl
602    elif progress == "version_mismatch":
603        print "The versions of APBS on the local server and on the Opal server do not match, so the calculation could not be completed"
604
605    print "</P>"
606    print "<script type=\"text/javascript\">"
607    for key in logopts:
608        print getEventTrackingString('queryData', key, logopts[key]),
609        #print "_gaq.push(['_trackPageview', '/main_cgi/has_%s_%s.html']);" % (key, logopts[key])
610    print "</script>"
611    print "</div> <!--end content div-->"
612    print "</BODY>"
613    print "</HTML>"
614
615if __name__ == "__main__" and os.environ.has_key("REQUEST_METHOD"):
616    """ Determine if called from command line or CGI """
617    refresh=30
618
619    if not form.has_key("jobid") and form["calctype"].value=="pdb2pqr":
620        print "Content-type: text/html\n\n"
621        print printheader("PDB2PQR Job Status - Error")
622        text="<BODY>\n"
623        text+="\t<H2>Missing jobid field</H2>\n"
624        text+="\t<P>Your request url is missing the jobid field</P>\n"
625        text += "<script type=\"text/javascript\">"
626        text += "var gaJsHost = ((\"https:\" == document.location.protocol) ? \"https://ssl.\" : \"http://www.\");"
627        text += "document.write(unescape(\"%3Cscript src=\'\" + gaJsHost + \"google-analytics.com/ga.js\' type=\'text/javascript\'%3E%3C/script%3E\"));"
628        text += "</script>"
629        text += "<script type=\"text/javascript\">"
630        text += "try {"
631        text += "var pageTracker = _gat._getTracker(\"UA-11026338-3\");"
632        text += "pageTracker._trackPageview();"
633        text += "} catch(err) {}</script>"
634        text+="</BODY>\n</HTML>"
635        print text
636        sys.exit(2)
637
638
639    if (form["calctype"].value=="pdb2pqr" and HAVE_PDB2PQR_OPAL) or (form["calctype"].value=="apbs" and APBS_OPAL_URL!=""):
640        have_opal = True
641        from AppService_client import AppServiceLocator, queryStatusRequest, getOutputsRequest
642    else:
643        have_opal = False
644
645    mainCGI()
646