9 import os, sys, glob, shutil, hashlib, re, fnmatch
14 # collect pysam version
15 sys.path.insert( 0, "pysam")
18 version = version.__version__
20 samtools_exclude = ( "bamtk.c", "razip.c", "bgzip.c",
22 "main.c", "calDepth.c", "bam2bed.c",
23 "wgsim.c", "md5fa.c", "maq2sam.c",)
24 samtools_dest = os.path.abspath( "samtools" )
25 tabix_exclude = ( "main.c", )
26 tabix_dest = os.path.abspath( "tabix" )
28 def locate(pattern, root=os.curdir):
29 '''Locate all files matching supplied filename pattern in and below
30 supplied root directory.'''
31 for path, dirs, files in os.walk(os.path.abspath(root)):
32 for filename in fnmatch.filter(files, pattern):
33 yield os.path.join(path, filename)
35 def _update_pysam_files(cf, destdir):
37 if not filename: continue
38 dest = filename + ".pysam.c"
39 with open( filename ) as infile:
40 with open( dest, "w" ) as outfile:
41 outfile.write( '#include "pysam.h"\n\n' )
42 outfile.write( re.sub( "stderr", "pysamerr", "".join(infile.readlines()) ) )
43 with open( os.path.join( destdir, "pysam.h" ), "w" )as outfile:
44 outfile.write ("""#ifndef PYSAM_H
47 extern FILE * pysamerr;
51 # copy samtools source
52 if len(sys.argv) >= 2 and sys.argv[1] == "import":
53 if len(sys.argv) < 3: raise ValueError("missing PATH to samtools source directory")
54 if len(sys.argv) < 4: raise ValueError("missing PATH to tabix source directory")
56 for destdir, srcdir, exclude in zip(
57 (samtools_dest, tabix_dest),
59 (samtools_exclude, tabix_exclude)):
61 srcdir = os.path.abspath( srcdir )
62 if not os.path.exists( srcdir ): raise IOError( "samtools src dir `%s` does not exist." % srcdir )
64 cfiles = locate( "*.c", srcdir )
65 hfiles = locate( "*.h", srcdir )
68 def _compareAndCopy( src, srcdir, destdir, exclude ):
70 d, f = os.path.split(src)
71 if f in exclude: return None
72 common_prefix = os.path.commonprefix( (d, srcdir ) )
73 subdir = re.sub( common_prefix, "", d )[1:]
74 targetdir = os.path.join( destdir, subdir )
75 if not os.path.exists( targetdir ):
76 os.makedirs( targetdir )
77 old_file = os.path.join( targetdir, f )
78 if os.path.exists( old_file ):
79 md5_old = hashlib.md5("".join(open(old_file,"r").readlines())).digest()
80 md5_new = hashlib.md5("".join(open(src,"r").readlines())).digest()
81 if md5_old != md5_new:
82 raise ValueError( "incompatible files for %s and %s" % (old_file, src ))
84 shutil.copy( src, targetdir )
87 for src_file in hfiles:
88 _compareAndCopy( src_file, srcdir,destdir, exclude )
92 for src_file in cfiles:
93 cf.append( _compareAndCopy( src_file, srcdir, destdir, exclude ) )
96 print "installed latest source code from %s: %i files copied" % (srcdir, ncopied)
97 # redirect stderr to pysamerr and replace bam.h with a stub.
98 print "applying stderr redirection"
100 _update_pysam_files(cf, destdir)
105 if len(sys.argv) >= 2 and sys.argv[1] == "refresh":
106 print "refreshing latest source code from .c to .pysam.c"
107 # redirect stderr to pysamerr and replace bam.h with a stub.
108 print "applying stderr redirection"
109 for destdir in ('samtools', 'tabix'):
110 pysamcfiles = locate( "*.pysam.c", destdir )
111 for f in pysamcfiles: os.remove(f)
112 cfiles = locate( "*.c", destdir )
113 _update_pysam_files(cfiles, destdir)
119 from ez_setup import use_setuptools
122 from setuptools import Extension, setup
124 ## note that for automatic cythoning,
125 ## both pyrex and cython need to be installed.
126 ## see http://mail.python.org/pipermail/distutils-sig/2007-September/008204.html
129 from Cython.Distutils import build_ext
131 from setuptools.command.build_ext import build_ext
134 Development Status :: 2 - Alpha
135 Operating System :: MacOS :: MacOS X
136 Operating System :: Microsoft :: Windows :: Windows NT/2000
137 Operating System :: OS Independent
138 Operating System :: POSIX
139 Operating System :: POSIX :: Linux
140 Operating System :: Unix
141 Programming Language :: Python
142 Topic :: Scientific/Engineering
143 Topic :: Scientific/Engineering :: Bioinformatics
146 if platform.system()=='Windows':
147 include_os = ['win32']
148 os_c_files = ['win32/getopt.c']
153 samtools = Extension(
154 "csamtools", # name of extension
155 [ "pysam/csamtools.pyx" ] +\
156 [ "pysam/%s" % x for x in (
157 "pysam_util.c", )] +\
158 glob.glob( os.path.join( "samtools", "*.pysam.c" )) +\
160 glob.glob( os.path.join( "samtools", "*", "*.pysam.c" ) ),
162 include_dirs=[ "samtools", "pysam" ] + include_os,
165 define_macros = [('_FILE_OFFSET_BITS','64'),
166 ('_USE_KNETFILE','')],
170 "ctabix", # name of extension
171 [ "pysam/ctabix.pyx", ] +\
172 [ "pysam/%s" % x for x in ( "tabix_util.c", )] +\
174 glob.glob( os.path.join( "tabix", "*.pysam.c" ) ),
176 include_dirs=[ "tabix", "pysam" ] + include_os,
181 tabproxies = Extension(
182 "TabProxies", # name of extension
183 [ "pysam/TabProxies.pyx", ] + os_c_files,
185 include_dirs= include_os,
191 "cvcf", # name of extension
192 [ "pysam/cvcf.pyx", ] + os_c_files,
194 include_dirs= ["tabix",] + include_os,
202 'description': "pysam",
203 'long_description': __doc__,
204 'author': "Andreas Heger",
205 'author_email': "andreas.heger@gmail.com",
208 'url': "http://code.google.com/p/pysam/",
214 'requires' : ['cython (>=0.12)'],
215 'ext_modules': [samtools, tabix, tabproxies, cvcf ],
216 'cmdclass' : {'build_ext': build_ext},
217 'install_requires' : ['cython>=0.12.1',],
218 # do not pack in order to permit linking to csamtools.so
222 if __name__=='__main__':
223 dist = setup(**metadata)