casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables
publish_summary.py
Go to the documentation of this file.
00001 from casac import casac
00002 from taskinit import casalog
00003 from imageTest import * 
00004 from visTest import * 
00005 from testbase import *
00006 from tableMaker import *
00007 import time
00008 import os
00009 import shutil
00010 import commands
00011 import sys
00012 import signal
00013 import pdb
00014 import traceback
00015 import re
00016 import cProfile
00017 
00018 PYVER = str(sys.version_info[0]) + "." + str(sys.version_info[1])
00019 
00020 imager = casac.imager()
00021 image = casac.image()
00022 quantity=casac.quanta()
00023 
00024 AIPS_DIR = os.environ["CASAPATH"].split()[0]
00025 
00026 if os.access(AIPS_DIR+'/lib64', os.F_OK):
00027     SCRIPT_REPOS = AIPS_DIR+'/lib64/python'+PYVER+'/regressions/'
00028     UTILS_DIR = AIPS_DIR+'/lib64/casapy/bin/'
00029 elif os.access(AIPS_DIR+'/lib', os.F_OK):
00030     SCRIPT_REPOS = AIPS_DIR+'/lib/python'+PYVER+'/regressions/'
00031     UTILS_DIR = AIPS_DIR+'/lib/casapy/bin/'        
00032 elif os.access(AIPS_DIR + '/' + os.environ["CASAPATH"].split()[1] + '/python/' + PYVER + '/regressions/', os.F_OK):
00033     # devel
00034     SCRIPT_REPOS = AIPS_DIR + '/' + os.environ["CASAPATH"].split()[1] + '/python/' + PYVER + '/regressions/'
00035     UTILS_DIR = ''
00036 else:            #Mac release
00037     SCRIPT_REPOS = AIPS_DIR+'/Resources/python/regressions/'
00038     UTILS_DIR = AIPS_DIR+'/MacOS/'        
00039 # because casapy releases have a different directory structure
00040 
00041 
00042 # set to True to skip the test execution and reuse product files
00043 #dry=True
00044 dry = False
00045 
00046 class runTest:
00047     def __init__(self, test, \
00048                  DATA_REPOS=[AIPS_DIR+'/data'], \
00049                  WORKING_DIR='/tmp/casa_regression_work/', \
00050                  RESULT_DIR='/tmp/casa_regression_result/', \
00051                  retemplate=False,
00052                  cleanup=True,
00053                  CPP_PROFILE=False,
00054                  RESULT_SUBDIR='',
00055                  REDIRECT=True,
00056                  PY_PROFILE=True):
00057         """cleanup: set to False to keep data around.
00058         CPP_PROFILE: set to True to enable C++ profiling.  This requires that the command 'sudo opcontrol' must work.  You also need the 'dot' tool distributed as part of graphviz.  Run 'dot -Txxx' to verify that your dot installation supports PNG images.
00059         Note, a profile is created only for the casapy process. If you want to include profiles for async / child processes, refer to the documentation for opreport."""
00060         casalog.showconsole(onconsole=True)
00061         
00062         TEMPLATE_RESULT_DIR=AIPS_DIR+'/data/regression/'
00063         tests = [test]
00064         if type(tests) != type([]):
00065             raise TypeError
00066         self.resultdir=RESULT_DIR
00067         self.imdir=WORKING_DIR+'/IMAGES/'
00068         self.tester=testbase(WORKING_DIR)
00069         self.imagertests=[]
00070         self.result=[]
00071         self.numTests=0
00072         ####Get the directories right
00073         self.tester.setDataBaseDir(DATA_REPOS)
00074         self.tester.setScriptsDir(SCRIPT_REPOS)
00075         self.tester.setResultDir(RESULT_DIR)
00076         self.tester.setWorkingDir(WORKING_DIR)
00077         self.resultsubdir = ''
00078 
00079         print SCRIPT_REPOS
00080         
00081         if((len(tests)==1) and (tests[0]=='all')):
00082             self.numTests=self.tester.locateTests()
00083         else:
00084             self.numTests=self.tester.locateTests(tests)
00085         testName=''
00086              
00087         #pdb.set_trace()
00088         for k in range(self.numTests) :
00089             ### cleanup before each test
00090             if not dry and cleanup:
00091                 self.tester.cleanup()
00092 
00093             self.tester.createDirs()
00094 
00095             uname1 = os.uname()[1]
00096 
00097             if self.tester.testname(k)[0:6] == 'tests/':
00098                 testName=string.split(self.tester.testname(k)[6:], ".py")[0]
00099             else:
00100                 testName=string.split(self.tester.testname(k), ".py")[0]
00101             if not RESULT_SUBDIR:
00102                 self.resultsubdir = self.resultdir + "/result-" + \
00103                                     testName       + "-" + \
00104                                     uname1         + "-" + \
00105                                     time.strftime('%Y_%m_%d_%H_%M')
00106             else:
00107                 self.resultsubdir = self.resultdir + "/" + RESULT_SUBDIR
00108 
00109             if not os.path.isdir(self.resultsubdir):
00110                 os.mkdir(self.resultsubdir)
00111 
00112             logfilename = testName+'.log'
00113             if (os.path.isfile(self.resultsubdir+'/'+logfilename)):
00114                 os.remove(self.resultsubdir+'/'+logfilename)
00115 
00116             # redirect stdout and stderr and casalog
00117             print 'Run test '+testName
00118             if REDIRECT:
00119                 print "Redirect stdout/stderr to", self.resultsubdir+'/'+logfilename
00120                 save_stdout = sys.stdout
00121                 save_stderr = sys.stderr
00122                 fsock = open(self.resultsubdir+'/'+logfilename, 'w')
00123                 sys.stdout = logger("STDOUT", [save_stdout, fsock])
00124                 sys.stderr = logger("STDERR", [save_stderr, fsock])
00125 
00126                 testlog = self.tester.workingDirectory+"/test.log"
00127                 open(testlog, "w").close()  # create empty file
00128                 casalog.setlogfile(testlog) # seems to append to an existing file
00129 
00130             try:
00131                 self.tester.getTest(self.tester.testname(k), testName)
00132 
00133                 if PY_PROFILE:
00134                     if RESULT_SUBDIR != testName:
00135                         profilepage = RESULT_DIR+'/'+time.strftime('%Y_%m_%d/')+testName+'_profile.html'
00136                     else:
00137                         profilepage = RESULT_DIR+'/'+RESULT_SUBDIR+'/'+'profile.html'
00138 
00139                     process_data = "%s/profile.txt"  % self.tester.workingDirectory
00140 
00141                     os.system("echo -n > " + process_data)
00142                     pp = SCRIPT_REPOS + '/profileplot.py'  # for release
00143                     if not os.path.isfile(pp):
00144                         pp = SCRIPT_REPOS + '/../profileplot.py' # for devel
00145                         pyt = UTILS_DIR + '/python'  # for release
00146                     if not os.path.isfile(pyt):
00147                         lib = "lib64" if os.uname()[4] == 'x86_64' else "lib"
00148                         pyt = '/usr/' + lib + '/casapy/bin/python'
00149                     if not os.path.isfile(pyt):
00150                         pyt = '/usr/lib64/casapy/bin/python'    # for devel
00151                     if not os.path.isfile(pyt):
00152                         pyt = '/usr/lib/casapy/bin/python'    # for devel
00153                     if not os.path.isfile(pyt):
00154                         pyt = commands.getoutput('which python') # Mac devel
00155                     profileplot_pid=os.spawnlp(os.P_NOWAIT,
00156                                                pyt,
00157                                                pyt,
00158                                                pp,
00159                                                testName, RESULT_DIR + ("/" + RESULT_SUBDIR if RESULT_SUBDIR == testName else ''),
00160                                                profilepage,
00161                                                process_data,
00162                                                str(os.getpid()))
00163                     prof = cProfile.Profile()
00164                 else:
00165                     prof = False
00166 
00167                 presentDir=os.getcwd()
00168                 os.chdir(self.tester.workingDirectory)
00169 
00170                 short_description = self.tester.getDescription(testName, k)
00171                 if short_description != None and short_description.find("'") >= 0:
00172                     print >> sys.stderr, \
00173                           "Warning: Short description contains ': '%s'" % \
00174                           short_description
00175                     short_description = short_description.replace("'", "")
00176 
00177                 try:
00178                     self.op_init(CPP_PROFILE)
00179                     time1=time.time()
00180                     mem1 = commands.getoutput('ps -p ' + str(os.getpid()) + ' -o rss | tail -1')
00181                     if prof:
00182                         #prof.runctx("(leResult, leImages)=self.tester.runtests(testName, k, dry)", globals(), locals())
00183                         #prof.runctx("(leResult, leImages)=self.tester.runtests(testName, k, dry)", gl, lo)
00184                         #prof.run("(leResult, leImages) = self.tester.runtests(testName, k, dry)")
00185                         (leResult, leImages) = prof.runcall(self.tester.runtests, testName, k, dry)
00186                     else:
00187                         (leResult, leImages) = self.tester.runtests(testName, k, dry)
00188 
00189                     # returns absolute_paths, relative_paths
00190                     exec_success = True
00191                 except:
00192                     leResult=[]
00193                     exec_success = False
00194                     print >> sys.stderr, "%s failed, dumping traceback:" % testName
00195                     traceback.print_exc() # print and swallow exception
00196 
00197                 mem2 = commands.getoutput('ps -p ' + str(os.getpid()) + ' -o rss | tail -1')
00198                 time2=time.time()
00199                 time2=(time2-time1)/60.0
00200 
00201                 print "Net memory allocated:", (int(mem2) - int(mem1))/1024, "MB"
00202 
00203                 if prof:
00204                     try:
00205                         prof.dump_stats(self.resultsubdir+'/cProfile.profile')
00206                     except:
00207                         print >> sys.stderr, "Failed to write profiling data!"
00208                
00209                 self.op_done(CPP_PROFILE)
00210 
00211                 # Dump contents of any *.log file produced
00212                 # by the regression script
00213                 #
00214                 # !! Does not handle out of diskspace
00215                 #
00216                 files = os.listdir('.')
00217                 for f in files:
00218                     if f != 'casapy.log' and \
00219                            re.compile('.log$').search(f) != None:
00220 
00221                         for line in open(f, 'r'):
00222                             #print f + '    ddd'+line
00223                             if REDIRECT:
00224                                 fsock.write(f + ': ' + line.rstrip( ))
00225                             else:
00226                                 print f + ': ' + line.rstrip( )
00227 
00228                 #
00229                 # Report and deal with out of diskspace
00230                 #
00231                 space_left = commands.getoutput( \
00232                     "df -kP " + self.tester.workingDirectory + \
00233                     " | awk '{print $4}' | tail -1")
00234                 space_left_h = commands.getoutput( \
00235                     "df -hP " + self.tester.workingDirectory + \
00236                     " | awk '{print $4}' | tail -1")
00237                 space_used = commands.getoutput( \
00238                     "du -kc " + self.tester.workingDirectory + \
00239                     " | tail -1 | awk '{print $1}'")
00240                 space_used_h = commands.getoutput( \
00241                     "du -hc " + self.tester.workingDirectory + \
00242                     " | tail -1 | awk '{print $1}'")
00243 
00244                 if int(space_left) < 1000*1000:
00245                     print >> sys.stderr, "Warning: Only " + \
00246                           space_left_h + ' disk space left, ' + \
00247                           space_used_h + ' used'
00248                     # Clean up early, so that this infrastructure can continue
00249                     if not exec_success and cleanup:
00250                         self.tester.cleanup()
00251                         
00252                 # Copy C++ profiling info
00253                 if CPP_PROFILE:
00254                     os.system('cp cpp_profile.* ' + self.resultsubdir)
00255 
00256                 os.chdir(presentDir)
00257 
00258                 if PY_PROFILE:
00259                     # Terminate profiling process
00260                     os.kill(profileplot_pid,signal.SIGHUP)
00261                     status = os.waitpid(profileplot_pid, 0)[1]
00262                     #print str(profileplot_pid) + ' exit: ' + str(status)
00263 
00264                 pagename=time.strftime('%Y_%m_%d/')+testName+'_profile.html'
00265 
00266                 # entries common for all tests based on this run
00267                 self.result_common = {}
00268                 self.result_common['CASA'] = "'" + self.get_casa_version() + "'", "CASA version"
00269                 self.result_common['host'] = uname1, "os.uname[1]"
00270                 self.result_common['platform'] = "'" + self.get_platform()[0] + " " + self.get_platform()[1] + "'", "OS"
00271 
00272                 self.result_common['date'] = time.strftime('%Y_%m_%d_%H_%M'), ""
00273                 self.result_common['testid'] = testName, "test name"
00274                 if short_description != None:
00275                     self.result_common['description'] = "'" + short_description + "'", "test short description"
00276 
00277                 # Figure out data repository version
00278                 if os.system("which svnversion >/dev/null") == 0:
00279                     (errorcode, datasvnr) = commands.getstatusoutput('cd '+DATA_REPOS[0]+' && svnversion 2>&1 | grep -vi warning')
00280                 else:
00281                     errorcode = 1
00282                 if errorcode != 0 or datasvnr == "exported":
00283                     # If that didn't work, look at ./version in the toplevel dir
00284                     (errorcode, datasvnr) = commands.getstatusoutput( \
00285                         'cd '+DATA_REPOS[0]+" && grep -E 'Rev:' version" \
00286                         )
00287                     if errorcode != 0:
00288                         datasvnr = "Unknown version"
00289                         
00290                 self.result_common['data_version'] = "'"+datasvnr+"'", "Data repository version"
00291 
00292                 # execution test
00293                 exec_result = self.result_common.copy()
00294                 exec_result['version'] = 2, "version of this file"
00295                 exec_result['type'] = "exec", "test type"
00296                 exec_result['time'] = time2*60, "execution time in seconds"
00297                 exec_result['disk'] = space_used, "disk space (KB) in use after test"
00298                 exec_result['runlog'] = logfilename, "execution logfile"
00299 
00300 
00301                 if PY_PROFILE:
00302                     # read time/memory data
00303                     mem = ""
00304                     try:
00305                         process_file = open(process_data, "r")
00306                     except:
00307                         print "Warning: Failed to open file:", process_data
00308                         process_file = None
00309                 else:
00310                     process_file = None
00311 
00312                 if process_file != None:
00313                     lineno = 0
00314                     for line in process_file:
00315                         lineno += 1
00316                         if len(line) > 0 and line[0] != '#':
00317                             try:
00318                                 (t, m_virtual, m_resident, nfiledesc,
00319                                  cpu_us, cpu_sy, cpu_id, cpu_wa) = line.split()
00320                                 mem = mem + \
00321                                       str(t)          + ',' + \
00322                                       str(m_virtual)  + ',' + \
00323                                       str(m_resident) + ',' + \
00324                                       str(nfiledesc)  + ',' + \
00325                                       str(cpu_us)     + ',' + \
00326                                       str(cpu_sy)     + ',' + \
00327                                       str(cpu_id)     + ',' + \
00328                                       str(cpu_wa)     + ';'
00329                             except:
00330                                 print >> sys.stderr, "Error parsing %s:%d: '%s'" % \
00331                                       (process_data, lineno, line)
00332                     process_file.close()
00333                     exec_result['resource'] = mem, "time(s),virtual(Mbytes),resident(Mbytes),nfiledesc,cpu_us,cpu_sy,cpu_id,cpu_wa"
00334 
00335                 whatToTest=self.tester.whatQualityTest()
00336                 keys=[]
00337                 #if len(whatToTest) != 0:
00338                 #    keys=whatToTest.keys()
00339                 #    print 'THE KEYS ARE ', keys
00340                 for j in range(len(leResult)) :   
00341                     templateImage=TEMPLATE_RESULT_DIR+"/"+testName+"/reference/"+leImages[j]
00342                     if retemplate:
00343                         if os.access(templateImage, os.F_OK):
00344                             shutil.rmtree(templateImage)
00345                     print 'TemplateImage '+templateImage
00346                     print 'theImage '+leResult[j]
00347                     print 'theImage '+leImages[j]
00348 
00349                     product_exists  = os.access(leResult[j], os.F_OK)
00350                     template_exists = os.access(templateImage, os.F_OK)
00351 
00352                     if product_exists and retemplate:
00353                         print 'Create template from', leResult[j]
00354                         if not os.path.isdir(TEMPLATE_RESULT_DIR+"/"+testName):
00355                             os.mkdir(TEMPLATE_RESULT_DIR+"/"+testName)
00356                         shutil.copytree(leResult[j], templateImage)
00357 
00358                     if not product_exists:
00359                         print >> sys.stderr, leResult[j], 'missing!'
00360                         exec_success = False
00361                         whatToTest[leResult[j]] = []
00362                         
00363                     if not template_exists:
00364                         print >> sys.stderr, templateImage, 'missing!'
00365 
00366                     for leQualityTest in whatToTest[leResult[j]] :
00367                         print leResult[j]+' WHAT : ', whatToTest[leResult[j]]
00368                         self.result=self.result_common.copy()
00369                         self.result['version'] = 1, "version of this file"
00370                         self.result['type'] = leQualityTest, "test type"
00371                         self.result['image'] = leImages[j], "test image"
00372 
00373                         if not product_exists:
00374                             self.result['status'] = 'fail', "result of regression test"
00375                             self.result['reason'] = "'Product image missing'", "reason of failure"
00376                         elif not template_exists:
00377                             self.result['status'] = 'fail', "result of regression test"
00378                             self.result['reason'] = "'Reference image missing'", "reason of failure"
00379                         else:
00380                             if os.access(self.imdir, os.F_OK):
00381                                 shutil.rmtree(self.imdir)
00382                                 
00383                             if(leQualityTest=='simple'):
00384                                 self.simpleStats(leResult[j], templateImage, testName, WORKING_DIR, RESULT_DIR)
00385                             elif(leQualityTest=='pol2'):
00386                                 self.polImageTest(leResult[j], templateImage, testName, WORKING_DIR, RESULT_DIR, 2)
00387                             elif(leQualityTest=='pol4'):
00388                                 self.polImageTest(leResult[j], templateImage, testName, WORKING_DIR, RESULT_DIR, 4)
00389                             elif(leQualityTest=='cube'):
00390                                 self.cubeImageTest(leResult[j], templateImage, testName, WORKING_DIR, RESULT_DIR)
00391                             elif(leQualityTest=='ms'):
00392                                 self.visStats(leResult[j], templateImage, testName, WORKING_DIR, RESULT_DIR)
00393 # RI add visStats method here, image ones use ImageTest so going to have to build a MSTest class
00394                             else:
00395                                 self.polImageTest(leResult[j], templateImage, testName, WORKING_DIR, RESULT_DIR, 1)
00396 
00397                             # Pick up any images produced in test
00398                             if os.path.isdir(self.imdir):
00399                                 i = 0
00400                                 for image in os.listdir(self.imdir):
00401                                     i = i + 1
00402                                     shutil.copy(self.imdir + '/' + image, \
00403                                                 self.resultsubdir+'/'+os.path.basename(image))
00404                                     self.result['imagefile_'+str(i)] = "'"+os.path.basename(image)+"'", 'regression image '+str(i)
00405 
00406                         self.create_log(leImages[j].replace('/', '-'))
00407 
00408                 # Create exec log now that we now if
00409                 # required images were produced
00410                 exec_result['status'] = ("fail", "pass") [exec_success], "execution status"
00411                 self.result = exec_result
00412                 self.create_log("")
00413 
00414                 # Restore stdout/stderr
00415                 if REDIRECT:
00416                     sys.stderr = save_stderr
00417                     sys.stdout = save_stdout
00418                     fsock.close()
00419 
00420                     casalog.setlogfile("casapy.log")
00421                     os.system("sed 's/^/casapy.log: /' "+testlog+" >> "+self.resultsubdir+'/'+logfilename)
00422 
00423                 if not dry and cleanup:
00424                     self.tester.cleanup()
00425             except:
00426                 if REDIRECT:
00427                     sys.stderr = save_stderr
00428                     sys.stdout = save_stdout
00429                     fsock.close()
00430                     casalog.setlogfile("casapy.log")
00431                     os.system("sed 's/^/casapy.log: /' "+testlog+" >> "+self.resultsubdir+'/'+logfilename)
00432 
00433                 print "Unexpected error:", sys.exc_info()[0]
00434                 raise
00435             
00436         # end for k...
00437                 
00438         print "Created ", self.resultsubdir
00439 
00440 
00441     def op_init(self, oprofile):
00442         if oprofile:
00443             os.system("sudo opcontrol --deinit && sudo opcontrol --init && sudo opcontrol --reset && sudo opcontrol --start --callgraph=999 --no-vmlinux --separate=lib --event=\"default\"")
00444 
00445     def op_done(self, oprofile):
00446         if oprofile:
00447             casapy = os.environ["CASAPATH"].split()[0] + '/' + \
00448                      os.environ["CASAPATH"].split()[1] + '/bin/casapy'
00449 
00450             gprof2dot = SCRIPT_REPOS + "/../gprof2dot.py"
00451             
00452             os.system("sudo opcontrol --stop && sudo opcontrol --dump")
00453             os.system("opreport -clf image-exclude:/no-vmlinux " + casapy + " > cpp_profile.txt")
00454             os.system("cat cpp_profile.txt | " + gprof2dot + " -e0.1 -n1 -f oprofile > cpp_profile.dot")
00455             os.system("cat cpp_profile.dot | dot -Tpng -o cpp_profile.png")
00456             os.system("opannotate --source > cpp_profile.cc")
00457 
00458 
00459     def polImageTest(self, imageName, templateImage, testName, WORKING_DIR, RESULT_DIR, numPol=2):
00460         a = ImageTest(imageName, write=True,
00461                       resultDir = self.resultdir,
00462                       imDir=self.imdir)
00463         b = ImageTest(templateImage, write=False,
00464                       resultDir = self.resultdir,
00465                       imDir=self.imdir)
00466         status = 1
00467         pol=['I', 'V']
00468         if(numPol==4):
00469             pol=['I','Q','U','V']
00470         quickresult='<pre>'
00471         ##do only the 'I' subtraction
00472         for k in range(1):
00473             print 'POL TEST ', k, 'numpol ', numPol
00474             out1, rms1 = a.bmodel(plane=k)
00475             out2, rms2 = b.bmodel(plane=k)
00476  #           rms1=a.subtract(plane=k)
00477  #           rms2=b.subtract(plane=k)
00478         
00479 #            quickresult+=('Pol #%s\n  Image    coord: [%.3f,%.3f]\n  FWHM in x: %.6f\n  FWHM in y: %.6f\n'%(pol[k],out1[0][0],out1[0][1],out1[0][2],out1[0][3]))
00480 #            quickresult+=('Pol #%s\n  Template coord: [%.3f,%.3f]\n  FWHM in x: %.6f\n  FWHM in y: %.6f\n'%(pol[k],out2[0][0],out2[0][1],out2[0][2],out2[0][3]))
00481             if(out1[0] != False and out2[0] != False):
00482                 quickresult+=('Pol %s : Component Found in Image  :\nra %s  dec %s \nbmax %s bmin %s \nbpa %s flux %s \n'% \
00483                               (pol[k],\
00484                                out1[0][0],out1[0][1],\
00485                                out1[0][2],out1[0][3],\
00486                                out1[0][4],out1[0][5]))
00487                 quickresult+=('Pol %s : Component Found in Template:\nra %s dec %s \nbmax %s bmin %s \nbpa %s flux %s \n'% \
00488                               (pol[k],out2[0][0],out2[0][1],out2[0][2],out2[0][3],out2[0][4],out2[0][5]))
00489 
00490                 self.result['image_'+pol[k]+'_ra']   = "'"+out1[0][0]+"'", pol[k]+" component RA"
00491                 self.result['image_'+pol[k]+'_dec']  = "'"+out1[0][1]+"'", pol[k]+" component DEC"
00492                 self.result['image_'+pol[k]+'_bmax'] = "'"+out1[0][2]+"'", "major axis"
00493                 self.result['image_'+pol[k]+'_bmin'] = "'"+out1[0][3]+"'", "minor axis"
00494                 self.result['image_'+pol[k]+'_bpa']  = "'"+out1[0][4]+"'", "position angle"
00495                 self.result['image_'+pol[k]+'_flux'] = "'"+out1[0][5]+"'", "flux"
00496 
00497                 # Duplicate of above
00498                 self.result['ref_'+pol[k]+'_ra']   = "'"+out2[0][0]+"'", pol[k]+" component RA"
00499                 self.result['ref_'+pol[k]+'_dec']  = "'"+out2[0][1]+"'", pol[k]+" component DEC"
00500                 self.result['ref_'+pol[k]+'_bmax'] = "'"+out2[0][2]+"'", "major axis"
00501                 self.result['ref_'+pol[k]+'_bmin'] = "'"+out2[0][3]+"'", "minor axis"
00502                 self.result['ref_'+pol[k]+'_bpa']  = "'"+out2[0][4]+"'", "position angle"
00503                 self.result['ref_'+pol[k]+'_flux'] = "'"+out2[0][5]+"'", "flux"
00504 
00505 
00506                 if(abs(rms2-rms1) > rms2/2.0):
00507                     status=0
00508             else:
00509                 quickresult+=('Image fitting did not converge \n')
00510                 print >> sys.stderr, 'Image fitting did not converge'
00511                 status=2
00512         ### Do a simple stats for pol Q,U,V
00513         for k in range(1, numPol):
00514             rms1,max1,min1,returnFlag1=b.simple_stats(plane=k)
00515             rms2,max2,min2,returnFlag=a.simple_stats(plane=k, sigma=rms1)
00516             quickresult+='Image Pol %s   min: %f\nmax: %f\nrms: %f \n' %\
00517                           (pol[k],min2,max2,rms2)
00518             quickresult+='Template Pol %s min: %f\nmax: %f\nrms: %f \n' %\
00519                           (pol[k],min1,max1,rms1)
00520 
00521             self.result['image_'+pol[k]+'_min'] = min2, pol[k]+" min"
00522             self.result['image_'+pol[k]+'_max'] = max2, pol[k]+" max"
00523             self.result['image_'+pol[k]+'_rms'] = rms2, pol[k]+" rms"
00524 
00525             self.result['ref_'+pol[k]+'_min'] = min1, pol[k]+" min"
00526             self.result['ref_'+pol[k]+'_max'] = max1, pol[k]+" max"
00527             self.result['ref_'+pol[k]+'_rms'] = rms1, pol[k]+" rms"
00528             
00529             if(not returnFlag):
00530                 status=status*0
00531             if(abs(max2-max1) > rms2/2.0):
00532                 status=status*0
00533             if(abs(min2-min1) > rms2/2.0):
00534                 status=status*0   
00535         quickresult+='</pre>'
00536         page=a.done()
00537         b.done()
00538         
00539         self.result['status'] = ['fail', 'pass'][status==1], "result of regression test"
00540 
00541 
00542        
00543     def simpleStats(self, imageName, templateImage, testname, WORKING_DIR, RESULT_DIR):
00544         a=ImageTest(imageName,write=True,resultDir=self.resultdir,imDir=self.imdir)
00545         b=ImageTest(templateImage,write=False,resultDir=self.resultdir,imDir=self.imdir)
00546         rms1,max1,min1,returnFlag1=b.simple_stats()
00547         b.done()
00548         status=1   # 1     : pass
00549                    # 2     : unknown
00550                    # other : fail
00551         
00552         rms2,max2,min2,returnFlag=a.simple_stats(sigma=rms1)
00553         a.changeImage(templateImage)
00554         rms1,max1,min1,returnFlag1=a.simple_stats()
00555         if(not returnFlag):
00556             status=0
00557         quickresult='<pre>'
00558         quickresult+='Image    min: %f\nmax: %f\nrms: %f \n' %(min2,max2,rms2)
00559         quickresult+='Template min: %f\nmax: %f\nrms: %f \n' %(min1,max1,rms1)
00560         quickresult+='</pre>'
00561         page=a.done()
00562         #b.done()
00563 
00564         self.result['status'] = ['fail', 'pass'][status==1], "result of regression test"
00565         self.result['image_min'] = min2, "image min"
00566         self.result['image_max'] = max2, "image max"
00567         self.result['image_rms'] = rms2, "image rms"
00568         self.result['ref_min'] = min1, "reference min"
00569         self.result['ref_max'] = max1, "reference max"
00570         self.result['ref_rms'] = rms1, "reference rms"
00571 
00572 
00573         
00574     def visStats(self, msName, templateMS, testname, WORKING_DIR, RESULT_DIR):
00575         a=VisTest(msName,write=True,resultDir=self.resultdir,imDir=self.imdir)
00576         b=VisTest(templateMS,write=False,resultDir=self.resultdir,imDir=self.imdir)
00577         arms1,amax1,amin1,prms1,pmax1,pmin1,returnFlag1=b.simple_stats()
00578         b.done()
00579         status=1   # 1     : pass
00580                    # 2     : unknown
00581                    # other : fail
00582         
00583         arms2,amax2,amin2,prms2,pmax2,pmin2,returnFlag2=a.simple_stats()
00584         if(not returnFlag2):
00585             status=0
00586         quickresult='<pre>'
00587         quickresult+='MS       min: %f\nmax: %f\nrms: %f \n' %(amin2,amax2,arms2)
00588         quickresult+='Template min: %f\nmax: %f\nrms: %f \n' %(amin1,amax1,arms1)
00589         quickresult+='</pre>'
00590         page=a.done()
00591         #b.done()
00592 
00593         if(arms2 > 2.*arms1):
00594             status=status*0
00595         if(prms2 > 2.*prms1):
00596             status=status*0
00597 
00598         if(abs(amax2-amax1) > arms2/2.0):
00599             status=status*0
00600         if(abs(amin2-amin1) > arms2/2.0):
00601             status=status*0   
00602         if(abs(pmax2-pmax1) > prms2/2.0):
00603             status=status*0
00604         if(abs(pmin2-pmin1) > prms2/2.0):
00605             status=status*0   
00606                 
00607         self.result['status'] = ['fail', 'pass'][status==1], "result of regression test"
00608         self.result['ms_amp_min'] = amin2, "ms amp min"
00609         self.result['ms_amp_max'] = amax2, "ms amp max"
00610         self.result['ms_amp_rms'] = arms2, "ms amp rms"
00611         self.result['ref_amp_min'] = amin1, "reference amp min"
00612         self.result['ref_amp_max'] = amax1, "reference amp max"
00613         self.result['ref_amp_rms'] = arms1, "reference amp rms"
00614 
00615         self.result[ 'ms_pha_min'] = pmin2, "ms phase min"
00616         self.result[ 'ms_pha_max'] = pmax2, "ms phase max"
00617         self.result[ 'ms_pha_rms'] = prms2, "ms phase rms"
00618         self.result['ref_pha_min'] = pmin1, "reference phase min"
00619         self.result['ref_pha_max'] = pmax1, "reference phase max"
00620         self.result['ref_pha_rms'] = prms1, "reference phase rms"
00621 
00622         
00623     def cubeImageTest(self, imageName, templateImage, testname, WORKING_DIR, RESULT_DIR):
00624         a=ImageTest(imageName,write=True,resultDir=self.resultdir,imDir=self.imdir)
00625 #        b=ImageTest(templateImage,write=False,resultDir=self.resultdir,imDir=self.imdir)
00626         status=1
00627 #        XY1,fwhm1=a.auto_fitCube(a.b,verbose=0)
00628         XY1,fwhm1=a.auto_fitCube2()
00629         
00630         a.changeImage(templateImage)
00631         
00632 #        XY2,fwhm2=a.auto_fitCube(a.b,verbose=0)
00633 
00634         XY2,fwhm2=a.auto_fitCube2()
00635         
00636         if(abs((XY1[0][0]-XY2[0][0])/XY2[0][0]) > 0.1):
00637             status=0
00638         if(abs((fwhm1[0]-fwhm2[0])/fwhm2[0]) > 0.1):
00639             status=0
00640         quickresult='<pre>'
00641         quickresult+='On image    \n  optimized coord: [%.3f,%.3f]\n  FWHM: %.6f\n\nfit #1\n  optimized coord: [%.3f,%.3f]\n  FWHM: %.6f \n'%(XY1[0][0],XY1[0][1],fwhm1[0],XY1[1][0],XY1[1][1],fwhm1[1])
00642         quickresult+='On Template \n  optimized coord: [%.3f,%.3f]\n  FWHM: %.6f\n\nfit #1\n  optimized coord: [%.3f,%.3f]\n  FWHM: %.6f \n'%(XY2[0][0],XY2[0][1],fwhm2[0],XY2[1][0],XY2[1][1],fwhm2[1])
00643         quickresult+='</pre>'
00644         page=a.done()
00645 #        b.done()
00646 
00647         self.result['status'] = ['fail', 'pass'][status==1], "result of regression test"
00648 
00649         self.result['image_x'] = XY1[0][0], "image optimized coord"
00650         self.result['image_y'] = XY1[0][1], "image optimized coord"
00651         self.result['image_fwhm'] = fwhm1[0], "image FWHM"
00652         self.result['image_fit1_x'] = XY1[1][0], "image fit1 optimized coord"
00653         self.result['image_fit1_y'] = XY1[1][1], "image fit1 optimized coord"
00654         self.result['image_fit1_fwhm'] = fwhm1[1], "image fit1 FWHM"
00655 
00656         self.result['ref_x'] = XY2[0][0], "reference optimized coord"
00657         self.result['ref_y'] = XY2[0][1], "reference optimized coord"
00658         self.result['ref_fwhm'] = fwhm2[0], "reference FWHM"
00659         self.result['ref_fit1_x'] = XY2[1][0], "reference fit1 optimized coord"
00660         self.result['ref_fit1_y'] = XY2[1][1], "reference fit1 optimized coord"
00661         self.result['ref_fit1_fwhm'] = fwhm2[1], "reference fit1 FWHM"
00662 
00663     def get_casa_version(self):
00664         a=inspect.stack()
00665         stacklevel=0
00666         for k in range(len(a)):
00667             if (string.find(a[k][1], 'ipython console') > 0):
00668                 stacklevel=k     
00669         myf=sys._getframe(stacklevel).f_globals
00670 
00671         return "CASA Version " + myf['casa']['build']['version'] + " (r"+myf['casa']['source']['revision'] + ")"
00672 
00673     def create_log(self, product_file):
00674         filename = "%s/result-%s-%s.txt" % \
00675                    (self.resultsubdir, product_file, \
00676                     self.result['type'][0])
00677         filename = filename.replace("--", "-")
00678         
00679         print "Writing file", filename
00680         try:
00681             self.logfd=open(filename, "w")
00682         except:
00683             print "Could not open file", filename
00684             raise
00685         for k, v in self.result.iteritems():
00686             # too much output for time/mem stats:
00687             print k, "=", str(v[0])[0:100], "#", v[1]
00688             self.logfd.write("%-20s = %-40s # %-20s\n" % (k, v[0], v[1]))
00689         self.logfd.close()
00690 
00691     def get_platform(self):
00692         OS = os.uname()[0]
00693         REV = os.uname()[2]
00694         MACH = os.uname()[4]
00695         if OS == 'SunOS':
00696             OS='Solaris'
00697             ARCH=commands.getoutput("uname -p")
00698             #return "%s %s (%s %s)" % (OS,REV,ARCH, commands.getoutput("uname -v"))
00699             return "%s %s" % (OS, MACH), \
00700                    "%s (%s %s)" % (REV,ARCH, commands.getoutput("uname -v"))
00701         elif OS == "AIX":
00702             return "%s %s" % (OS, MACH), \
00703                    "%s (%s)" % (commands.getoutput("oslevel"),
00704                                 commands.getoutput("oslevel -r"))
00705         elif OS == "Linux" or OS == "Darwin":
00706             KERNEL=REV
00707             if os.path.isfile("/etc/redhat-release"):
00708                 DIST = commands.getoutput("head -1 /etc/redhat-release")
00709             elif os.path.isfile("/etc/SUSE-release"):
00710                 DIST = commands.getoutput("head -1 /etc/SUSE-release")
00711             elif os.path.isfile("/etc/SuSE-release"):
00712                 DIST = commands.getoutput("head -1 /etc/SuSE-release")
00713             elif os.path.isfile("/etc/mandrake-release"):
00714                 DIST = commands.getoutput("head -1 /etc/mandrake-release")
00715             elif os.path.isfile("/etc/lsb-release"):
00716                 DIST = \
00717                      commands.getoutput("grep DISTRIB_ID /etc/lsb-release | sed 's/.*=\s*//'") + \
00718                      ' release ' + commands.getoutput("grep DISTRIB_RELEASE /etc/lsb-release | sed 's/.*=\s*//'") + \
00719                      ' (' + commands.getoutput("grep DISTRIB_CODENAME /etc/lsb-release | sed 's/.*=\s*//'") + \
00720                      ')'
00721             elif os.path.isfile("/etc/debian_version"):
00722                 DIST = commands.getoutput("head -1 /etc/debian_version")
00723             else:
00724                 DIST = "???"
00725 
00726             if MACH == "i686" or MACH == "i386":
00727                 WORDSIZE = "32"
00728             elif MACH == "x86_64" or MACH == "ia64":
00729                 WORDSIZE = "64"
00730             else:
00731                 WORDSIZE = "??"
00732 
00733             if OS == "Darwin":
00734                 if commands.getoutput("sysctl  -n hw.optional.x86_64").find("1") >= 0:
00735                     WORDSIZE = "64"
00736                 else:
00737                     WORDSIZE = "32"
00738 
00739                 vers = commands.getoutput("/usr/bin/sw_vers -productVersion")
00740                 if vers.find("10.4") >= 0:
00741                     name = "Tiger"
00742                 elif vers.find("10.5") >= 0:
00743                     name = "Leopard"
00744                 elif vers.find("10.6") >= 0:
00745                     name = "Snow Leopard"
00746                 elif vers.find("10.7") >= 0:
00747                     name = "Tiger"
00748                 else :
00749                     name = "Unknown Mac OSX"
00750 
00751                 DIST = commands.getoutput("/usr/bin/sw_vers -productName") + " " + \
00752                        vers + " (" + name + " " + \
00753                        commands.getoutput("/usr/bin/sw_vers -buildVersion") + ")"
00754 
00755             return "%s %s %s-bit" % (OS, MACH, WORDSIZE), DIST
00756             #return "%s %s %s (%s %s %s)" % (OS, DIST, REV, PSEUDONAME, KERNEL, MACH)
00757             #return "%s %s %s (%s)" % (OS, DIST, REV, PSEUDONAME)
00758         else:
00759             return "??? ??? ??-bit", "???"
00760 
00761 
00762 class logger:
00763     def __init__(self, name, ss):
00764         self.streams = ss          # list of file objects where txt is sent
00765         self.name = name           # for printing only
00766         self.bol = True            # are we at beginning of line?
00767     def wwrite(self, txt, fback):  # this method is no throw
00768                                    # (because it is used to
00769                                    #   print error messages)
00770                                    #
00771                                    # fback: frame of caller
00772         try:
00773             #sys.__stderr__.write(txt)
00774             if self.bol:
00775                 fb = fback
00776                 if fb != None:
00777                     pos = " %s:%d" % \
00778                           (os.path.basename(fb.f_code.co_filename), \
00779                            fb.f_lineno)
00780                 else:
00781                     pos = ""
00782                 for s in self.streams:
00783                     s.write("%s%s: " % \
00784                                       (self.name, pos))
00785             for s in self.streams:
00786                 #s.write("'"+txt+"'")
00787                 s.write(txt)
00788                 s.flush()
00789             self.bol = (len(txt) > 0 and txt[-1] == '\n');
00790             # note: doesn't handle \n in the middle of a string
00791 
00792         except Exception, e:
00793             # should not happen
00794             sys.__stderr__.write(str(e) + " -- " + txt + "\n")
00795 
00796     def write(self, txt):
00797         self.wwrite(txt, inspect.currentframe().f_back)
00798 
00799     def writelines(self, lines):
00800         fb = inspect.currentframe().f_back
00801         for l in lines:
00802             self.wwrite(l, fb)
00803 
00804     def flush(self):
00805         for s in self.streams:
00806             s.flush()
00807 
00808     # fake remaining methods to make this class behave like a file
00809     #def __getattr__(self, name):
00810 #        return getattr(self.streams[0], name)
00811     
00812 #    def __setattr__(self, name, value):
00813 #        if name in dir(self):
00814 #            self.__dict__[name] = value
00815 #        else:
00816 #            setattr(self.streams[0], name, value)
00817        
00818     def __del__(self):
00819         pass
00820         #print >> sys.__stdout__,  "Die", self.name