diff --git a/.travis.yml b/.travis.yml index 414104941..df908fdd8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ addons: packages: - build-essential - cmake - - python + - python3 - libboost-all-dev - libgsl-dev - libxerces-c-dev diff --git a/CMakeLists.txt b/CMakeLists.txt index 92e1209de..0ade21b9e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,13 +2,7 @@ # Copyright © 2005-2013 Swiss Tropical Institute and Liverpool School Of Tropical Medicine # Licence: GNU General Public Licence version 2 or later (see COPYING) -cmake_minimum_required (VERSION 2.4) -# We still (try to) support cmake 2.4, but cmake 2.8 policies also work: -if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 2.6) - cmake_policy(VERSION 2.8) -elseif("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 2.4) - cmake_policy(VERSION 2.6) -endif("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 2.6) +cmake_minimum_required (VERSION 3.0) project (OpenMalaria CXX) @@ -94,6 +88,11 @@ find_package (XSD) find_package (XERCESC) find_package (GSL) find_package (Z) +find_package (Python) + +if (NOT PYTHON_EXECUTABLE) + message (SEND_ERROR "Unable to find a Python interpreter (required).") +endif (NOT PYTHON_EXECUTABLE) # Find Boost: diff --git a/FindPython.cmake b/FindPython.cmake index 9c193304b..9aed8960e 100644 --- a/FindPython.cmake +++ b/FindPython.cmake @@ -4,7 +4,17 @@ # # Defines PYTHON_EXECUTABLE. Doesn't abort if not found. -find_program (PYTHON_EXECUTABLE python +# We need Python 3.x which is now often the default version. +# On Windows, install paths may help +find_program (PYTHON_EXECUTABLE + NAMES python3 python3.exe python python.exe + PATHS + "C:\\Python37-x64" "C:\\Python37" + "C:\\Python36-x64" "C:\\Python36" + "C:\\Python35-x64" "C:\\Python35" + "C:\\Python34-x64" "C:\\Python34" + "C:\\Python33-x64" "C:\\Python33" DOC "Path to python (required).") +message (STATUS "Found Python interpreter: ${PYTHON_EXECUTABLE}") mark_as_advanced (PYTHON_EXECUTABLE) diff --git a/schema/CMakeLists.txt b/schema/CMakeLists.txt index 2c92ef7d4..6930f34f5 100644 --- a/schema/CMakeLists.txt +++ b/schema/CMakeLists.txt @@ -2,8 +2,6 @@ # Copyright © 2005-2011 Swiss Tropical Institute and Liverpool School Of Tropical Medicine # Licence: GNU General Public Licence version 2 or later (see COPYING) -find_package (Python) - set (SCHEMA_NAMES scenario demography diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 87f6384c0..dfe3ea090 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -2,8 +2,6 @@ # Copyright © 2005-2009 Swiss Tropical Institute and Liverpool School Of Tropical Medicine # Licence: GNU General Public Licence version 2 or later (see COPYING) -find_package (Python) - # Testing via run.sh or run.py script: configure_file ( ${CMAKE_CURRENT_SOURCE_DIR}/run.py @@ -53,14 +51,11 @@ set (OM_BOXTEST_NAMES # tests with broken checkpointing: set (OM_BOXTEST_NC_NAMES) # Disabled due to "in-progress" work: (none) + # Use python script. -if (PYTHON_EXECUTABLE) - foreach (TEST_NAME ${OM_BOXTEST_NAMES}) +foreach (TEST_NAME ${OM_BOXTEST_NAMES}) add_test (${TEST_NAME} ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/run.py ${TEST_NAME} -- --checkpoint) - endforeach (TEST_NAME) - foreach (TEST_NAME ${OM_BOXTEST_NC_NAMES}) +endforeach (TEST_NAME) +foreach (TEST_NAME ${OM_BOXTEST_NC_NAMES}) add_test (${TEST_NAME} ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/run.py -- ${TEST_NAME}) - endforeach (TEST_NAME) -else (PYTHON_EXECUTABLE) - message(WARNING "Tests are disabled (Python is needed to run them)") -endif (PYTHON_EXECUTABLE) +endforeach (TEST_NAME) diff --git a/test/run.py b/test/run.py index b0e5ba3b5..a854174f5 100755 --- a/test/run.py +++ b/test/run.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # This file is part of OpenMalaria. @@ -51,7 +51,7 @@ def __str__(self): testSrcDir="@CMAKE_CURRENT_SOURCE_DIR@" testBuildDir="@CMAKE_CURRENT_BINARY_DIR@" if not os.path.isdir(testSrcDir) or not os.path.isdir(testBuildDir): - print "Don't run this script directly; configure CMake then use the version in the CMake build dir." + print("Don't run this script directly; configure CMake then use the version in the CMake build dir.") sys.exit(-1) # executable @@ -106,7 +106,7 @@ def linkOrCopy (src, dest): # This can still fail: a VirtualBox guest is not allowed to create # links on a drive shared by the host os.symlink(os.path.abspath(src), dest) - except OSError,e: + except OSError as e: shutil.copy2(src, dest) else: shutil.copy2(src, dest) @@ -133,13 +133,13 @@ def runScenario(options,omOptions,name): cmd=["xmllint","--noout","--schema",scenarioSchema,scenarioSrc] # alternative: ["xmlstarlet","val","-s",SCHEMA,scenarioSrc] if options.logging: - print "\033[0;32m "+(" ".join(cmd))+"\033[0;00m" + print("\033[0;32m "+(" ".join(cmd))+"\033[0;00m") return subprocess.call (cmd,cwd=testBuildDir) cmd=options.wrapArgs+[openMalariaExec,"--deprecation-warnings","--resource-path",os.path.abspath(testSrcDir),"--scenario",scenarioSrc]+omOptions if not options.run: - print "\033[0;32m "+(" ".join(cmd))+"\033[0;00m" + print("\033[0;32m "+(" ".join(cmd))+"\033[0;00m") return 0 # Run from a temporary directory, so checkpoint files won't conflict @@ -156,16 +156,16 @@ def runScenario(options,omOptions,name): linkOrCopy (scenarioSchema, scenario_xsd) if options.logging: - print time.strftime("\033[0;33m%a, %d %b %Y %H:%M:%S")+"\t\033[1;33m%s" % scenarioSrc + print(time.strftime("\033[0;33m%a, %d %b %Y %H:%M:%S")+"\t\033[1;33m%s" % scenarioSrc) startTime=lastTime=time.time() # While no output.txt file and cmd exits successfully: while (not os.path.isfile(outputFile)): if options.logging: - print "\033[0;32m "+(" ".join(cmd))+"\033[0;00m" + print("\033[0;32m "+(" ".join(cmd))+"\033[0;00m") ret=subprocess.call (cmd, shell=False, cwd=simDir) if ret != 0: - print "\033[1;31mNon-zero exit status: " + str(ret) + print("\033[1;31mNon-zero exit status: " + str(ret)) break # check for output.txt.gz in place of output.txt and uncompress: @@ -195,7 +195,7 @@ def runScenario(options,omOptions,name): lastTime=checkTime if ret == 0 and options.logging: - print "\033[0;33mDone in " + str(time.time()-startTime) + " seconds" + print("\033[0;33mDone in " + str(time.time()-startTime) + " seconds") if options.cleanup: os.remove(scenario_xsd) @@ -218,7 +218,7 @@ def runScenario(options,omOptions,name): ctsret,ctsident = compareCtsout.main (origCtsout, ctsoutFile) else: ctsret,ctsident = 3,False - print "\033[1;31mNo original ctsout.txt to compare with." + print("\033[1;31mNo original ctsout.txt to compare with.") if ctsident and options.cleanup: os.remove(ctsoutFile) if os.path.isfile(newCtsout): @@ -233,7 +233,7 @@ def runScenario(options,omOptions,name): ret,ident = compareOutput.main (origOutput, outputFile, 0) else: ret,ident = 3,False - print "\033[1;31mNo original output.txt to compare with." + print("\033[1;31mNo original output.txt to compare with.") if ident and options.cleanup: os.remove(outputFile) if os.path.isfile(newOutput): @@ -243,12 +243,12 @@ def runScenario(options,omOptions,name): ret,ident = 1,False stderrFile=os.path.join(simDir,"stderr.txt") if os.path.isfile (stderrFile): - print "\033[1;31mNo output 'output.txt'; error messages:" + print("\033[1;31mNo output 'output.txt'; error messages:") se = open(stderrFile) se.read() se.close() else: - print "\033[1;31mNo output 'output.txt'" + print("\033[1;31mNo output 'output.txt'") ret=max(ret,ctsret) ident=ident and ctsident @@ -265,9 +265,9 @@ def runScenario(options,omOptions,name): try: os.rmdir(simDir) except OSError: - print "\033[0;31mDirectory %s not empty, so not deleted!" % simDir + print("\033[0;31mDirectory %s not empty, so not deleted!" % simDir) - print "\033[0;00m" + print("\033[0;00m") return ret def setWrapArgs(option, opt_str, value, parser, *args, **kwargs): @@ -345,8 +345,8 @@ def main(args): retVal = r if retVal == 0 else retVal return retVal - except RunError,e: - print str(e) + except RunError as e: + print(str(e)) return -1 if __name__ == "__main__": diff --git a/unittest/AgeGroupInterpolationSuite.py b/unittest/AgeGroupInterpolationSuite.py index 5f0a99fb7..688df9bba 100755 --- a/unittest/AgeGroupInterpolationSuite.py +++ b/unittest/AgeGroupInterpolationSuite.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # This file is part of OpenMalaria. @@ -52,7 +52,7 @@ def set_age_groups(self,age_lower_bounds,values): self.v=[values[0]] self.v.extend(values) self.v.append(values[len(values)-1]) - print "Lengths:",len(self.a),len(self.v) + print("Lengths:",len(self.a),len(self.v)) def interpolate(self,t): i=0 @@ -141,9 +141,9 @@ def plot(self,subplot): # Generate sample data for unittest: x=[15.2,18.09,7.0, 2.5, 0.0,20.0,900.0,62.0] -print "Age points:",x -print "Piecewise constant:",[const.interpolate(t) for t in x] -print "Linear interpolation:",[linear.interpolate(t) for t in x] +print("Age points:",x) +print("Piecewise constant:",[const.interpolate(t) for t in x]) +print("Linear interpolation:",[linear.interpolate(t) for t in x]) # Third plot: CMF data diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt index 668939066..968cc2aac 100644 --- a/unittest/CMakeLists.txt +++ b/unittest/CMakeLists.txt @@ -2,8 +2,6 @@ # Copyright © 2005-2009 Swiss Tropical Institute and Liverpool School Of Tropical Medicine # Licence: GNU General Public Licence version 2 or later (see COPYING) -find_package (Python) - set (OM_CXXTEST_INTERPRETER ${PYTHON_EXECUTABLE}) set (OM_CXXTEST_SCRIPT ${CMAKE_SOURCE_DIR}/contrib/cxxtest/bin/cxxtestgen) @@ -50,18 +48,13 @@ set (OM_CXXTEST_HEADERS PkPdComplianceSuite.h ) -#Appears to be problems with this on windows... -if (OM_CXXTEST_INTERPRETER) - add_custom_command (OUTPUT tests.cpp - COMMAND ${OM_CXXTEST_INTERPRETER} ${OM_CXXTEST_SCRIPT} ${OM_CXXTEST_OPTIONS} --runner=ParenPrinter -o ${CMAKE_CURRENT_BINARY_DIR}/tests.cpp ${OM_CXXTEST_HEADERS} +add_custom_command (OUTPUT tests.cpp + COMMAND ${PYTHON_EXECUTABLE} ${OM_CXXTEST_SCRIPT} ${OM_CXXTEST_OPTIONS} --runner=ParenPrinter -o ${CMAKE_CURRENT_BINARY_DIR}/tests.cpp ${OM_CXXTEST_HEADERS} DEPENDS ${OM_CXXTEST_HEADERS} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Generating unittest code with cxxtestgen" VERBATIM - ) -else (OM_CXXTEST_INTERPRETER) - message (SEND_ERROR "Unable to find python executable. Thus I can't build tests.cpp which is required to run the unittests.") -endif (OM_CXXTEST_INTERPRETER) +) # These files are needed to run various infection model tests: configure_file (${CMAKE_SOURCE_DIR}/test/autoRegressionParameters.csv ${CMAKE_CURRENT_BINARY_DIR} COPYONLY) diff --git a/unittest/DecayFunctionSuite.py b/unittest/DecayFunctionSuite.py index 49307157f..cb44c23af 100755 --- a/unittest/DecayFunctionSuite.py +++ b/unittest/DecayFunctionSuite.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # This file is part of OpenMalaria. diff --git a/util/WriteParamDocu.py b/util/WriteParamDocu.py deleted file mode 100644 index a4a35ed09..000000000 --- a/util/WriteParamDocu.py +++ /dev/null @@ -1,134 +0,0 @@ -#!/usr/bin/env python2 -# -*- coding: utf-8 -*- -""" -This file is part of OpenMalaria. - -Copyright (C) 2005-2014 Swiss Tropical Institute - -OpenMalaria is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or (at -your option) any later version. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -""" -""" -Write parameter documenation to an Excel File. You may need to -install http://www.python-excel.org/ xlwt, e.g.: -apt-get install python-xlwt -or download the windows installer -""" - -from xlwt import Workbook -from xlwt import easyxf -from xml.etree.ElementTree import ElementTree - -import string -import re - -appinfoOrder=['name','units','type','min','max','exposed','sweepable'] -docu_xf = easyxf('align: wrap on, vert centre') -worksheets = {} - -def normalizeNewlines(string): - string=" ".join(string.split()) - return re.sub(r'(\r\n|\r|\n)', ' ', string) - -def formatElement(el,path): - if (el.find("{http://www.w3.org/2001/XMLSchema}annotation") is not None): - splitPath=string.split(path,'/') - #set default component to "scenario", i.e. write to the "Scenario" worksheet below - component="scenario" - printPath=string.replace(path,"/"+component,"") - #update component if a know child element of scenario, i.e. write to another worksheet below - if (len(splitPath)>2): - if (splitPath[2] in worksheets): - component=splitPath[2] - printPath=string.replace(printPath,"/"+component,"") - sheet= worksheets[component][0] - row=worksheets[component][1] - sheet.write(row,0,string.lstrip(printPath,"/")) - annotation=el.find("{http://www.w3.org/2001/XMLSchema}annotation") - docuElem=annotation.find("{http://www.w3.org/2001/XMLSchema}documentation") - if (docuElem is not None): - docu=docuElem.text - else: - docu="TODO" - content=string.strip(docu) - sheet.write(row,1,normalizeNewlines(content),docu_xf) - appInfoElem=el.find("{http://www.w3.org/2001/XMLSchema}annotation").find("{http://www.w3.org/2001/XMLSchema}appinfo") - if (appInfoElem is not None): - appInfo=string.strip(appInfoElem.text) - else: - appInfo="name:TODO" - appInfoList=string.split(appInfo,";")[0:-1] - for keyValue in appInfoList: - splitPair=string.split(keyValue,":") - colIndex=appinfoOrder.index(string.strip(str(splitPair[0])))+2 - sheet.write(row,colIndex,splitPair[1],docu_xf) - #update next row to be written in that sheet - worksheets[component][1]=worksheets[component][1]+1 - -def drillDown(el,path,isExtType): - name=el.get("name") - if (name and not isExtType): - path=path+"/"+name - formatElement(el,path) - for elem in el.getchildren(): - drillDown(elem,path,False) - elType=el.get("type") - if (elType): - for typeDefinition in tree.findall("{http://www.w3.org/2001/XMLSchema}complexType"): - if (typeDefinition.get("name")==elType): - drillDown(typeDefinition,path,True) - break - -def initWorksheets(elementName,sheetName): - sheet=book.add_sheet(sheetName) - worksheets[elementName]=[sheet,1] - sheet.col(0).width =10000 - sheet.col(1).width =15000 - sheet.col(2).width =6500 - sheet.col(3).width =4300 - sheet.col(4).width =4300 - sheet.col(5).width =4500 - sheet.col(6).width =4800 - sheet.col(7).width =6000 - sheet.col(8).width =5500 - sheet.write(0,0,"Parameter name and path (in XML document)") - sheet.write(0,1,"Parameter documentation ") - sheet.write(0,2,"Parameter name (in GUI)") - sheet.write(0,3,"Parameter units") - sheet.write(0,4,"Parameter type") - sheet.write(0,5,"Parameter min value") - sheet.write(0,6,"Parameter max value") - sheet.write(0,7,"Parameter exposed in GUI") - sheet.write(0,8,"Parameter is sweepable") - -def main(): - global tree,book - book = Workbook() - initWorksheets("scenario", "Scenario") - initWorksheets("demography", "Demography") - initWorksheets("monitoring", "Monitoring") - initWorksheets("interventions", "Interventions") - initWorksheets("healthSystem", "HealthSystem") - initWorksheets("entomology", "Entomology") - initWorksheets("pharmacology", "Pharmacology") - initWorksheets("model", "Model") - tree = ElementTree() - tree.parse("../schema/scenario_34.xsd") - #we know that the first element in the schema defines scenario - scenarioElement=tree.find("{http://www.w3.org/2001/XMLSchema}element") - drillDown(scenarioElement,"",False) - book.save('Documentation.xls') - -if __name__ == '__main__': - main() diff --git a/util/approxEqual.py b/util/approxEqual.py index 9233ca72f..624176b73 100755 --- a/util/approxEqual.py +++ b/util/approxEqual.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ This file is part of OpenMalaria. @@ -86,39 +86,39 @@ class TestApproxEqual (unittest.TestCase): def testNaN (self): Inf = 1e10000 NaN = Inf * 0.0 - self.assert_ (not self.approxEqual6 (NaN, 1)) - self.assert_ (not self.approxEqual6 (NaN, 0)) - self.assert_ (not self.approxEqual6 (NaN, NaN)) - self.assert_ (not self.approxEqual6 (NaN, Inf)) + self.assertTrue (not self.approxEqual6 (NaN, 1)) + self.assertTrue (not self.approxEqual6 (NaN, 0)) + self.assertTrue (not self.approxEqual6 (NaN, NaN)) + self.assertTrue (not self.approxEqual6 (NaN, Inf)) def testInf (self): Inf = 1e10000 - self.assert_ (not self.approxEqual6 (Inf, 1)) - self.assert_ (not self.approxEqual6 (Inf, 0)) - self.assert_ (not self.approxEqual6 (Inf, Inf)) - self.assert_ (not self.approxEqual6 (Inf, -Inf)) + self.assertTrue (not self.approxEqual6 (Inf, 1)) + self.assertTrue (not self.approxEqual6 (Inf, 0)) + self.assertTrue (not self.approxEqual6 (Inf, Inf)) + self.assertTrue (not self.approxEqual6 (Inf, -Inf)) def testZero (self): - self.assert_ (not self.approxEqual6 (0, 1e-6)) - self.assert_ ( self.approxEqual6 (0, 1e-7)) + self.assertTrue (not self.approxEqual6 (0, 1e-6)) + self.assertTrue ( self.approxEqual6 (0, 1e-7)) def testRegular (self): - self.assert_ (not self.approxEqual6 (1, 0)) - self.assert_ (not self.approxEqual6 (1, 0.999999)) - self.assert_ ( self.approxEqual6 (1, 0.9999995)) - self.assert_ (not self.approxEqual6 (1000000, 999999)) - self.assert_ ( self.approxEqual6 (1000000, 999999.5)) + self.assertTrue (not self.approxEqual6 (1, 0)) + self.assertTrue (not self.approxEqual6 (1, 0.999999)) + self.assertTrue ( self.approxEqual6 (1, 0.9999995)) + self.assertTrue (not self.approxEqual6 (1000000, 999999)) + self.assertTrue ( self.approxEqual6 (1000000, 999999.5)) # these are considered equal because of absolute precision limitation rather than relative: - self.assert_ ( self.approxEqual6 (0.000001, 0.0000005)) + self.assertTrue ( self.approxEqual6 (0.000001, 0.0000005)) # this is roughly on the verge of what isn't considered equal: - self.assert_ (not self.approxEqual6 (0.000001, 0.000002)) + self.assertTrue (not self.approxEqual6 (0.000001, 0.000002)) # if we only want to test relative precision: approxEqualRel = ApproxEqual(1e-6, 0) - self.assert_ (not approxEqualRel (0.000001, 0.000000999999)) - self.assert_ ( approxEqualRel (0.000001, 0.0000009999995)) + self.assertTrue (not approxEqualRel (0.000001, 0.000000999999)) + self.assertTrue ( approxEqualRel (0.000001, 0.0000009999995)) approxEqual = ApproxEqual(0, 1e-11) - self.assert_ (approxEqual (approxEqualRel.sumRelDiffs, 1.49999999994)) + self.assertTrue (approxEqual (approxEqualRel.sumRelDiffs, 1.49999999994)) if __name__ == '__main__': diff --git a/util/assimilateForDBImport.py b/util/assimilateForDBImport.py index 0b26ffe0e..d682715a9 100755 --- a/util/assimilateForDBImport.py +++ b/util/assimilateForDBImport.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ This file is part of OpenMalaria. @@ -20,7 +20,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ -import string import os.path import sys from optparse import OptionParser @@ -52,16 +51,16 @@ def main(args): return 1 sweeps,swArmIds = readSwArmIds(others[0]) - sce_id_ind = next((i for i in xrange(len(sweeps)) if sweeps[i] == 'sce_id'), None) + sce_id_ind = next((i for i in range(len(sweeps)) if sweeps[i] == 'sce_id'), None) if sce_id_ind is None: - raise Exception, "unable to find column for sce_id!" + raise Exception("unable to find column for sce_id!") # sce_id_ind is zero-indexed and misses first column, so add 2: - print "Column for sce_id:",sce_id_ind+2 + print(("Column for sce_id:",sce_id_ind+2)) outFile=open(others[2],'w') resultDir=others[1] - for f,k in swArmIds.iteritems(): + for f,k in list(swArmIds.items()): sce_id=k[sce_id_ind] lineStart=sce_id+'\t' resPath=os.path.join(resultDir,f+'.txt') diff --git a/util/compareCtsout.py b/util/compareCtsout.py index 376fdf263..f708da9db 100755 --- a/util/compareCtsout.py +++ b/util/compareCtsout.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ This file is part of OpenMalaria. @@ -21,7 +21,6 @@ """ import sys -import string from optparse import OptionParser from approxEqual import ApproxSame @@ -64,21 +63,21 @@ def sumsApproxEq (fn1,fn2): t2,vec2=readSums(fn2) approxSame = ApproxSame(REL_PRECISION,ABS_PRECISION) if t1 != t2: - print "\033[1;31mColumns not equal:" - print t1 - print t2 - print "\033[0;0m", + print("\033[1;31mColumns not equal:") + print(t1) + print(t2) + print("\033[0;0m", end=' ') return False allApEq=True assert len(vec1)==len(vec2) for i in range(len(vec1)): if not approxSame(vec1[i],vec2[i]): - print "\033[0;31mSignificantly different:",t1[i],"; sums:",vec1[i],",",vec2[i] + print("\033[0;31mSignificantly different:",t1[i],"; sums:",vec1[i],",",vec2[i]) allApEq=False if allApEq: - print "No significant differences (total relative diff: "+str(approxSame.getTotalRelDiff())+"), ok." + print("No significant differences (total relative diff: "+str(approxSame.getTotalRelDiff())+"), ok.") else: - print "\033[1;31mSome significant differences (total relative diff: "+str(approxSame.getTotalRelDiff())+ ")!\033[0;0m" + print("\033[1;31mSome significant differences (total relative diff: "+str(approxSame.getTotalRelDiff())+ ")!\033[0;0m") return allApEq def main(fn1,fn2): @@ -88,19 +87,19 @@ def main(fn1,fn2): opt+=" --rel-prescision="+str(REL_PRECISION) if ABS_PRECISION!=1e-6: opt+=" --abs-prescision="+str(ABS_PRECISION) - print "\033[1;36m compareCtsout.py"+opt+" "+fn1+" "+fn2+"\033[0;0m" + print("\033[1;36m compareCtsout.py"+opt+" "+fn1+" "+fn2+"\033[0;0m") # Read both files and combine into a map of key to pairs (v1, v2) try: if charEqual (fn1,fn2): - print "ctsout.txt files are identical" + print("ctsout.txt files are identical") return 0,True elif sumsApproxEq (fn1,fn2): return 0,False return 1,False # python 3000 syntax is "except IOError as e", backported to 2.6 but not always supported. Old syntax: - except IOError, e: - print str(e) + except IOError as e: + print(str(e)) return 1,False # Test for options @@ -131,6 +130,6 @@ def evalOptions (args): if (len(others) == 2): ret,ident = main (others[0],others[1]) else: - print "Usage: "+sys.argv[0]+" logfile1 logfile2" + print("Usage: "+sys.argv[0]+" logfile1 logfile2") ret=-1 sys.exit(ret) diff --git a/util/compareOutput.py b/util/compareOutput.py index db2fdf286..df058a0ff 100755 --- a/util/compareOutput.py +++ b/util/compareOutput.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ This file is part of OpenMalaria. @@ -53,29 +53,29 @@ def main(fn1,fn2,maxDiffsToPrint=6): opt+=" --rel-prescision="+str(REL_PRECISION) if ABS_PRECISION!=1e-6: opt+=" --abs-prescision="+str(ABS_PRECISION) - print "\033[1;34m compareOutput.py"+opt+" "+fn1+" "+fn2+" "+str(maxDiffsToPrint)+"\033[0;0m" + print(("\033[1;34m compareOutput.py"+opt+" "+fn1+" "+fn2+" "+str(maxDiffsToPrint)+"\033[0;0m")) # Read both files and combine into a map of key to pairs (v1, v2) try: if charEqual (fn1,fn2): - print "output.txt files are identical" + print("output.txt files are identical") return 0,True - print "output.txt files aren't binary-equal" + print("output.txt files aren't binary-equal") values1=readEntries(fn1) values2=readEntries(fn2) # python 3000 syntax is "except IOError as e", backported to 2.6 but not always supported. Old syntax: - except IOError, e: - print str(e) + except IOError as e: + print((str(e))) return 1,False values=dict() - for (k,v1) in values1.iteritems(): + for (k,v1) in list(values1.items()): v2=None if (k in values2): v2=values2[k] del values2[k] values[k] = (v1,v2) - for (k,v2) in values2.iteritems(): + for (k,v2) in list(values2.items()): values[k] = (None,v2) # Go through all values: @@ -91,7 +91,7 @@ def main(fn1,fn2,maxDiffsToPrint=6): perMeasureDiffAbsSum = dict() approxSame = ApproxSame(REL_PRECISION, ABS_PRECISION) - for (k,(v1,v2)) in values.iteritems(): + for (k,(v1,v2)) in list(values.items()): if v1==None: numMissing1 += 1 elif v2==None: @@ -113,17 +113,17 @@ def main(fn1,fn2,maxDiffsToPrint=6): numPrinted += 1 perMeasureNumDiff[k.a] = perMeasureNumDiff.get(k.a,0) + 1; if (numPrinted <= maxDiffsToPrint): - print "survey "+str(k.b)+", group "+str(k.c)+", measure "+str(k.a)+": "+str(v1)+" -> "+str(v2) + print(("survey "+str(k.b)+", group "+str(k.c)+", measure "+str(k.a)+": "+str(v1)+" -> "+str(v2))) if (numPrinted == maxDiffsToPrint): - print "[won't print any more line-by-line diffs]" + print("[won't print any more line-by-line diffs]") if (numMissing1 > 0) or (numMissing2 > 0): - print str(numMissing1) + " entries missing from first file, " + str(numMissing2) +" from second" + print((str(numMissing1) + " entries missing from first file, " + str(numMissing2) +" from second")) ret = 3 maxDiffSum=0.0 maxAbsDiffSum=0.0 - for (k.a,absDiff) in perMeasureDiffAbsSum.iteritems(): + for (k.a,absDiff) in list(perMeasureDiffAbsSum.items()): if not (absDiff <= 1e-6): # handle NANs # standard division throws on divide-by-zero, which I don't want def div(x,y): @@ -139,15 +139,15 @@ def div(x,y): maxDiffSum=max(maxDiffSum,math.fabs(diffSum)) absDiffSum=div(absDiff,sum1) maxAbsDiffSum=max(maxAbsDiffSum,absDiffSum) - print "for measure "+str(k.a)+":\tsum(1st file):"+str(sum1)+"\tsum(2nd file):"+str(sum2)+"\tdiff/sum: "+str(diffSum)+"\t(abs diff)/sum: "+str(absDiffSum) + print(("for measure "+str(k.a)+":\tsum(1st file):"+str(sum1)+"\tsum(2nd file):"+str(sum2)+"\tdiff/sum: "+str(diffSum)+"\t(abs diff)/sum: "+str(absDiffSum))) if maxDiffSum>0 or maxAbsDiffSum>0: - print "Max diff/sum:",maxDiffSum,"max (abs diff)/sum:",maxAbsDiffSum + print(("Max diff/sum:",maxDiffSum,"max (abs diff)/sum:",maxAbsDiffSum)) if numDiffs == 0: - print "No significant differences (total relative diff: "+str(approxSame.getTotalRelDiff())+"), ok." + print(("No significant differences (total relative diff: "+str(approxSame.getTotalRelDiff())+"), ok.")) return ret,False else: - print "\033[1;31m"+str(numDiffs)+" significant differences (total relative diff: "+str(approxSame.getTotalRelDiff())+ ")!\033[0;0m" + print(("\033[1;31m"+str(numDiffs)+" significant differences (total relative diff: "+str(approxSame.getTotalRelDiff())+ ")!\033[0;0m")) return 1,False # Test for options @@ -179,6 +179,6 @@ def evalOptions (args): elif (len(others) == 2): ret,ident = main (others[0],others[1]) else: - print "Usage: "+sys.argv[0]+" logfile1 logfile2 [max different lines to print]" + print(("Usage: "+sys.argv[0]+" logfile1 logfile2 [max different lines to print]")) ret=-1 sys.exit(ret) diff --git a/util/dataPlotter.py b/util/dataPlotter.py index f195d4f44..53510a408 100644 --- a/util/dataPlotter.py +++ b/util/dataPlotter.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # This file is part of OpenMalaria. @@ -28,7 +28,6 @@ # data from a particular arm may be picked (all others ignored) # data may be agglomerated using some expression involving the arm -import string import os.path import sys from optparse import OptionParser diff --git a/util/inlineSchema.py b/util/inlineSchema.py index 392e68e67..a99f7c711 100755 --- a/util/inlineSchema.py +++ b/util/inlineSchema.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ This file is part of OpenMalaria. @@ -35,7 +35,7 @@ def findIncludes(node,inlined,toInline): if node.nodeType==xd.Node.ELEMENT_NODE and node.tagName=="xs:include": incl=node.getAttribute("schemaLocation") if not os.path.isfile(incl): - raise Exception,"schema '{0}' not found".format(incl) + raise Exception("schema '{0}' not found".format(incl)) if not incl in inlined: if not incl in toInline: #print "new include: {0}".format(incl) @@ -49,7 +49,7 @@ def inlineSchema(sourcePath,destinationPath): doc=xd.parse(sourcePath) docElt=doc.documentElement if not (docElt.nodeType==xd.Node.ELEMENT_NODE and docElt.tagName=="xs:schema"): - raise Exception, "file {0} doesn't start with an elt of name xs:schema".format(sourcePath) + raise Exception("file {0} doesn't start with an elt of name xs:schema".format(sourcePath)) inlined=set() toInline=set() @@ -61,7 +61,7 @@ def inlineSchema(sourcePath,destinationPath): inclDoc=xd.parse(incl) iDElt=inclDoc.documentElement if not iDElt.nodeType==xd.Node.ELEMENT_NODE and iDElt.tagName=="xs:schema": - raise Exception, "file {0} doesn't start with an elt of name xs:schema".format(incl) + raise Exception("file {0} doesn't start with an elt of name xs:schema".format(incl)) findIncludes(iDElt.firstChild,inlined,toInline) for child in iDElt.childNodes: docElt.appendChild(child.cloneNode(True)) @@ -82,7 +82,7 @@ def main(args): (options, others) = parser.parse_args(args=args[1:]) if not len(others)==2: parser.print_usage() - raise Exception,"Expected 2 arguments" + raise Exception("Expected 2 arguments") inlineSchema(others[0],others[1]) #except Exception,e: diff --git a/util/readOutput.py b/util/readOutput.py index 9356bd682..8a4e09076 100644 --- a/util/readOutput.py +++ b/util/readOutput.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # This file is part of OpenMalaria. @@ -19,7 +19,6 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -import string import unittest class Keys: @@ -71,14 +70,14 @@ def setUp(self): self.b1 = Multi3Keys(0,"abc",5); self.b2 = Multi3Keys(0,"abc",5); def testEq (self): - self.assert_ (self.a1.a == self.a2.a) - self.assert_ (self.a1 == self.a2) - self.assert_ (self.b1 == self.b2) - self.assert_ (self.a1 != self.a3) + self.assertTrue (self.a1.a == self.a2.a) + self.assertTrue (self.a1 == self.a2) + self.assertTrue (self.b1 == self.b2) + self.assertTrue (self.a1 != self.a3) def testHash (self): - self.assert_ (self.a1.__hash__() == self.a2.__hash__()) - self.assert_ (self.a1.__hash__() != self.a3.__hash__()) # actually, hash collisions are possible - self.assert_ (self.b1.__hash__() == self.b2.__hash__()) + self.assertTrue (self.a1.__hash__() == self.a2.__hash__()) + self.assertTrue (self.a1.__hash__() != self.a3.__hash__()) # actually, hash collisions are possible + self.assertTrue (self.b1.__hash__() == self.b2.__hash__()) def isAgeGroup(measure): if measure in set([7,9,21,25,26,28,29,31,32,33,34,35,36,39,40,47,48,49,50,51,54]): @@ -123,11 +122,11 @@ def get(self,survey,group,cohort,genotype,f): except LookupError: return 1e1000 - 1e0000 # NaN def getGroups(self): - return range(0,self.nGroups) + return list(range(0,self.nGroups)) def getCohorts(self): - return range(0,self.nCohorts) + return list(range(0,self.nCohorts)) def getGenotypes(self): - return range(0,self.nGenotypes) + return list(range(0,self.nGenotypes)) def stringIndexAllMatch(strs,ind,char): for s in strs: @@ -153,7 +152,7 @@ def read(self,fileName,filterExpr,exprDebug): def filterFun(f,m,s,g,c,gt): r=eval(filterExpr) if exprDebug: - print "f="+str(f),"m="+str(m),"s="+str(s),"g="+str(g),"c="+str(c),"g="+str(g)+":",r + print(("f="+str(f),"m="+str(m),"s="+str(s),"g="+str(g),"c="+str(c),"g="+str(g)+":",r)) return r aKS = Keys.SURVEY in self.aggregateKeys aKG = Keys.GROUP in self.aggregateKeys @@ -168,10 +167,10 @@ def filterFun(f,m,s,g,c,gt): fileObj = open(fileName, 'r') nErrs=0 for line in fileObj: - items=string.split(line) + items=line.split() if (len(items) != 4): - print "expected 4 items on line; found (following line):" - print line + print("expected 4 items on line; found (following line):") + print(line) nErrs+=1 if nErrs>5: raise Exception ("Too many errors reading "+fileName) @@ -203,7 +202,7 @@ def filterFun(f,m,s,g,c,gt): self.values[m].add(s,g,c,gt,fID,robustFloat(items[3])) def getFiles(self): - return range(len(self.files)) + return list(range(len(self.files))) def getFileName(self,n): return self.files[n] def getFileNames(self,replaceFN): @@ -234,7 +233,7 @@ def getSurveys(self,m): if m==21: return [1] else: - return range(1,self.nSurveys+1) + return list(range(1,self.nSurveys+1)) def getAllGroups(self): groups=set() for x in self.values: @@ -282,10 +281,10 @@ def readEntries (fname): values=dict() fileObj = open(fname, 'r') for line in fileObj: - items=string.split(line) + items=line.split() if (len(items) != 4): - print "expected 4 items on line; found (following line):" - print line + print("expected 4 items on line; found (following line):") + print(line) continue key=Multi3Keys(int(items[2]),int(items[0]),int(items[1])) diff --git a/util/resultAssimilator.py b/util/resultAssimilator.py index 9fac27d8a..a990d6767 100755 --- a/util/resultAssimilator.py +++ b/util/resultAssimilator.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ This file is part of OpenMalaria. @@ -20,7 +20,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ -import string import os.path import sys from optparse import OptionParser @@ -61,7 +60,7 @@ def main(args): outFile.write('\t') outFile.write('survey\tgroup\tmeasure\tvalue\n') - for f,k in swArmIds.iteritems(): + for f,k in list(swArmIds.items()): lineStart='' for x in k: lineStart+=x+'\t' diff --git a/util/update-header.py b/util/update-header.py index 72e9e4fe3..c94692c60 100755 --- a/util/update-header.py +++ b/util/update-header.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ This file is part of OpenMalaria. @@ -83,8 +83,8 @@ def update_source(filename, copyright): elif header in nonheaders: pass else: - print header - r=raw_input("Remove above header? (y/N): ") + print(header) + r=eval(input("Remove above header? (y/N): ")) if r[0]=='y' or r[0]=='Y': oldheaders.add(header) fdata = fdata[len(header):] @@ -92,7 +92,7 @@ def update_source(filename, copyright): nonheaders.add(header) if not (fdata.startswith(copyright)): - print "updating "+filename + print(("updating "+filename)) fdata = copyright + fdata if (isUTF): file(filename,"w").write(utfstr+fdata)