diff --git a/README.md b/README.md index 26dc915d00..7ba387c7e2 100755 --- a/README.md +++ b/README.md @@ -7,9 +7,7 @@ deepTools deepTools addresses the challenge of handling the large amounts of data that are now routinely generated from DNA sequencing centers. To do so, deepTools contains useful modules to process the mapped reads data to create coverage files in standard bedGraph and bigWig file formats. By doing so, deepTools allows the creation of **normalized coverage files** or the comparison between two files (for example, treatment and control). Finally, using such normalized and standardized files, multiple **visualizations** can be created to identify enrichments with -functional annotations of the genome. For a gallery of images that -can be produced, see -http://f1000.com/posters/browse/summary/1094053 +functional annotations of the genome. For support, questions, or feature requests contact: deeptools@googlegroups.com @@ -31,53 +29,33 @@ deepTools are available for: Details on the installation routines can be found here. -[Installation from source](#linux) +[General Installation](#general) [Installation on a Mac](#mac) -[Troubleshooting](#trouble) - [Galaxy installation](#galaxy) - -### Installation from source (Linux, command line) + +### General Installation -The easiest way to install deepTools is by __downloading the source file and using python pip__ or easy_install tools: +The easiest way to install deepTools is by using python `pip` or `easy_install tools`: -Requirements: Python 2.7, numpy, scipy installed +Requirements: Python 2.7, numpy, scipy (http://www.scipy.org/install.html) installed Commands: - $ cd ~ - $ export PYTHONPATH=$PYTHONPATH:~/lib/python2.7/site-packages - $ export PATH=$PATH:~/bin:~/.local/bin - -If pip is not already available, install with: - - $ easy_install --prefix=~ pip - -Install deepTools and dependencies with pip: - - $ pip install --user deeptools + $ pip install deeptools Done. - - -__Another option is to clone the repository:__ +__A second option is to clone the repository:__ $ git clone https://github.com/fidelram/deepTools - -Then go to the deepTools directory, edit the `deepTools.cfg` -file and then run the install script a: - $ cd deepTools - $ vim deeptools/config/deepTools.cfg $ python setup.py install - -By default, the script will install python library and executable +By default, the script will install the python library and executable codes globally, which means you need to be root or administrator of the machine to complete the installation. If you need to provide a nonstandard install prefix, or any other nonstandard @@ -86,22 +64,16 @@ script. $ python setup.py --help -To install under a specific location use: +For example, to install under a specific location use: $ python setup.py install --prefix ### Installation on a MAC -Although the installation of deepTools itself is quite simple, -the installation of the required modules SciPy and NumPy demand -a bit of extra work. - -The easiest way to install them ois together with the +The easiest way to get numpy and scipy dependencies is to install the [Anaconda Scientific Python Distribution][]. After installation, open -a terminal ("Applications" --> "Terminal"): and type: - - $ pip install deeptools +a terminal ("Applications" → "Terminal") and follow the [General Installation](#general) If individual installation of the dependencies is preferred, follow those steps: @@ -112,35 +84,11 @@ Download the packages and install them using dmg images: - http://sourceforge.net/projects/numpy/files/NumPy/ - http://sourceforge.net/projects/scipy/files/scipy/ -Then install deepTools via the terminal ("Applications" --> "Terminal"): - - $ cd ~ - $ export PYTHONPATH=$PYTHONPATH:~/lib/python2.7/site-packages - $ export PATH=$PATH:~/bin:~/.local/bin:~/Library/Python/2.7/bin - -If pip is not already available, install with: - - $ easy_install --prefix=~ pip - -Install deepTools and dependencies with pip: - - $ pip install --user deeptools +Then open terminal ("Applications" → "Terminal") +and follow the [General Installation](#general) -##### Troubleshooting -The easy_install command is provided by the python package setuptools. -You can download the package from https://pypi.python.org/pypi/setuptools - - $ wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py -O - | python - -or the user-specific way: - - $ wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py - $ python ez_setup.py --user - -Numpy/Scipy Installation: -http://www.scipy.org/install.html #### Galaxy Installation diff --git a/bin/correctGCBias b/bin/correctGCBias index 314aa7ca8b..8d9af28baf 100755 --- a/bin/correctGCBias +++ b/bin/correctGCBias @@ -18,79 +18,108 @@ from deeptools.utilities import getGC_content, tbitToBamChrName from deeptools.countReadsPerBin import getFragmentFromRead from deeptools import config as cfg from deeptools import writeBedGraph, parserCommon, mapReduce +from deeptools import utilities debug = 0 - samtools = cfg.config.get('external_tools', 'samtools') global_vars = dict() + def parseArguments(args=None): parentParser = parserCommon.getParentArgParse() + requiredArgs = getRequiredArgs() parser = argparse.ArgumentParser( - parents=[parentParser], + parents=[requiredArgs, parentParser], formatter_class=argparse.ArgumentDefaultsHelpFormatter, description='Corrects the GC bias using Benjamini\'s method ' '[Benjamini & Speed (2012). Nucleic acids research, 40(10)]. ' - 'The tool computeGC bias needs to be run first.') + 'The tool computeGC bias needs to be run first.', + usage='An example usage is:\n %(prog)s ' + '-b file.bam --effectiveGenomeSize 2150570000 -g mm9.2bit ' + '-l 200 --GCbiasFrequenciesFile freq.txt -o gc_corrected.bam ' + '[options]', + conflict_handler='resolve', + add_help=False) - # define the arguments - parser.add_argument('--bamfile', '-b', - metavar='bam file', - help='Sorted Bam file to correct.', - required=True) - - parser.add_argument('--effectiveGenomeSize', - help='The effective genome size is the portion ' - 'of the genome that is mappable. Large fractions of ' - 'the genome are stretches of NNNN that should be ' - 'discarded. Also, if repetitive regions were not ' - 'included in the mapping of reads, the effective ' - 'genome size needs to be adjusted accordingly. ' - 'Common values are: mm9: 2150570000, ' - 'hg19:2451960000, dm3:121400000 and ce10:93260000. ' - 'See Table 2 of http://www.plosone.org/article/info%3Adoi%2F10.1371%2Fjournal.pone.0030377 ' - 'or http://www.nature.com/nbt/journal/v27/n1/fig_tab/nbt.1518_T1.html ' - 'for several effective genome sizes.', - default=None, - type=int, - required=False) - - parser.add_argument('--genome', '-g', - help='Genome in two bit format. Most genomes can be ' - 'found here: http://hgdownload.cse.ucsc.edu/gbdb/ ' - 'Search for the .2bit ending. Otherwise, fasta ' - 'files can be converted to 2bit using the UCSC ' - 'programm called faToTwoBit available for different ' - 'plattforms at ' - 'http://hgdownload.cse.ucsc.edu/admin/exe/', - metavar='two bit file', - required=True) + args = parser.parse_args(args) + if args.correctedFile.name.endswith('bam'): + if not cfg.checkProgram(samtools, 'view', + 'http://samtools.sourceforge.net/'): + exit(1) + if args.correctedFile.name.endswith('bw'): + if not cfg.checkProgram('bedGraphToBigWig', '-h', + 'http://hgdownload.cse.ucsc.edu/admin/exe/'): + exit(1) + return(args) - group = parser.add_argument_group('Output options') - group.add_argument('--GCbiasFrequenciesFile', '-freq', - help='Indicate the output file from ' - 'computeGCBias containing, ' - 'the observed and expected read frequencies per GC ' - 'content.', - type=argparse.FileType('r'), - metavar='FILE', - required=True) +def getRequiredArgs(): + parser = argparse.ArgumentParser(add_help=False) - group.add_argument('--correctedFile', '-o', - help='Name of the corrected file. The ending will ' - 'be used to decide the output file format. The options ' - 'are ".bam", ".bw" for a bigWig file, ".bg" for a ' - 'bedgraph file.', - metavar='FILE', - type=argparse.FileType('w'), - required=True) + required = parser.add_argument_group('Required arguments') + # define the arguments + required.add_argument('--bamfile', '-b', + metavar='bam file', + help='Sorted Bam file to correct.', + required=True) + + required.add_argument('--effectiveGenomeSize', + help='The effective genome size is the portion ' + 'of the genome that is mappable. Large fractions of ' + 'the genome are stretches of NNNN that should be ' + 'discarded. Also, if repetitive regions were not ' + 'included in the mapping of reads, the effective ' + 'genome size needs to be adjusted accordingly. ' + 'Common values are: mm9: 2150570000, ' + 'hg19:2451960000, dm3:121400000 and ce10:93260000. ' + 'See Table 2 of ' + 'http://www.plosone.org/article/info:doi/10.1371/journal.pone.0030377 ' + 'or http://www.nature.com/nbt/journal/v27/n1/fig_tab/nbt.1518_T1.html ' + 'for several effective genome sizes. This value is ' + 'needed to detect enriched regions that, if not ' + 'discarded can bias the results.', + default=None, + type=int, + required=True) + + required.add_argument('--genome', '-g', + help='Genome in two bit format. Most genomes can be ' + 'found here: http://hgdownload.cse.ucsc.edu/gbdb/ ' + 'Search for the .2bit ending. Otherwise, fasta ' + 'files can be converted to 2bit using the UCSC ' + 'programm called faToTwoBit available for different ' + 'plattforms at ' + 'http://hgdownload.cse.ucsc.edu/admin/exe/', + metavar='two bit file', + required=True) + + required.add_argument('--GCbiasFrequenciesFile', '-freq', + help='Indicate the output file from ' + 'computeGCBias containing, ' + 'the observed and expected read frequencies per GC ' + 'content.', + type=argparse.FileType('r'), + metavar='FILE', + required=True) + + output = parser.add_argument_group('Output options') + output.add_argument('--correctedFile', '-o', + help='Name of the corrected file. The ending will ' + 'be used to decide the output file format. The options ' + 'are ".bam", ".bw" for a bigWig file, ".bg" for a ' + 'bedgraph file.', + metavar='FILE', + type=argparse.FileType('w'), + required=True) - args = parser.parse_args(args) + # define the optional arguments + optional = parser.add_argument_group('Optional arguments') + optional.add_argument("--help", "-h", action="help", + help="show this help message and exit") - return(args) + return parser def getReadGCcontent(tbit, read, fragmentLength, chrNameBit): @@ -149,6 +178,7 @@ def writeCorrected_wrapper(args): def writeCorrected_worker(chrNameBam, chrNameBit, start, end, step): r"""writes a bedgraph file containing the GC correction of a region from the genome + >>> test = Tester() >>> tempFile = writeCorrected_worker(*test.testWriteCorrectedChunk()) >>> open(tempFile, 'r').readlines() @@ -221,7 +251,7 @@ def writeCorrected_worker(chrNameBam, chrNameBit, start, end, step): if i == 0: return None - _file = tempfile.NamedTemporaryFile(delete=False) + _file = open(utilities.getTempFileName(suffix='.bg'), 'w') # save in bedgraph format for bin in xrange(0, len(cvg_corr), step): value = np.mean(cvg_corr[bin:min(bin + step, end)]) @@ -267,6 +297,9 @@ def writeCorrectedSam_worker(chrNameBam, chrNameBit, start, end, r""" Writes a SAM file, deleting and adding some reads in order to compensate for the GC bias. **This is a stochastic method.** + + First, check if samtools can be executed, otherwise the test will fail + >>> resp = cfg.checkProgram(samtools, 'view', '') >>> np.random.seed(1) >>> test = Tester() >>> args = test.testWriteCorrectedSam() @@ -297,16 +330,7 @@ def writeCorrectedSam_worker(chrNameBam, chrNameBit, start, end, tbit = twobit.TwoBitFile(open(global_vars['2bit'])) bam = pysam.Samfile(global_vars['bam']) - # is /dev/shm available? - # working in this directory speeds the process - try: - _file = tempfile.NamedTemporaryFile(suffix=".sam", - dir='/dev/shm', delete=False) - except OSError: - _file = tempfile.NamedTemporaryFile(suffix=".sam", delete=False) - - tempFileName = _file.name - _file.close() + tempFileName = utilities.getTempFileName(suffix='.sam') outfile = pysam.Samfile(tempFileName, 'wh', template=bam) startTime = time.time() @@ -519,29 +543,32 @@ def main(args): if args.correctedFile.name.endswith('bg') or \ args.correctedFile.name.endswith('bw'): - _temp_bg_file = tempfile.NamedTemporaryFile() + _temp_bg_file_name = utilities.getTempFileName(suffix='_all.bg') if len(mp_args) > 1 and args.numberOfProcessors > 1: res = pool.map_async(writeCorrected_wrapper, mp_args).get(9999999) else: res = map(writeCorrected_wrapper, mp_args) + # concatenate intermediary bedgraph files + _temp_bg_file = open(_temp_bg_file_name, 'w') for tempFileName in res: if tempFileName: # concatenate all intermediate tempfiles into one # bedgraph file shutil.copyfileobj(open(tempFileName, 'rb'), _temp_bg_file) os.remove(tempFileName) - + _temp_bg_file.close() args.correctedFile.close() - chromSizes = [(x, bit[x].size) for x in bit.keys()] + if args.correctedFile.name.endswith('bg'): - os.system("mv {} {}".format(_temp_bg_file, - args.correctedFile.name)) + shutil.move(_temp_bg_file_name, args.correctedFile.name) + else: - writeBedGraph.bedGraphToBigWig(chromSizes, _temp_bg_file.name, + chromSizes = [(x, bit[x].size) for x in bit.keys()] + writeBedGraph.bedGraphToBigWig(chromSizes, _temp_bg_file_name, args.correctedFile.name) - _temp_bg_file.close() + os.remove(_temp_bg_file) class Tester(): diff --git a/deeptools/_version.py b/deeptools/_version.py index 7eda3ca825..5720d46c59 100755 --- a/deeptools/_version.py +++ b/deeptools/_version.py @@ -2,4 +2,4 @@ # This file is originally generated from Git information by running 'setup.py # version'. Distribution tarballs contain a pre-generated copy of this file. -__version__ = '1.5.6-45-g7190dd0' +__version__ = '1.5.7' diff --git a/deeptools/config.py b/deeptools/config.py index 1bd309f03e..bbdc9ea8be 100755 --- a/deeptools/config.py +++ b/deeptools/config.py @@ -1,5 +1,48 @@ import os +import sys import ConfigParser +import subprocess + + +def checkProgram(program, args, where_to_download): + """ + deeptools relies on some command line programs + to work properly. This is a generic routine + that will check for such programs + + """ + if os.environ.get('DEEP_TOOLS_NO_CONFIG', False): + return + + try: + _out = subprocess.Popen([program, args], stderr=subprocess.PIPE, + stdout=subprocess.PIPE) + return True + except OSError as e: + if e.errno == os.errno.ENOENT: + # handle file not found error. + # the config file is installed in: + msg = "\n######################################################\n"\ + "\nThe program *{}* was not found in your PATH. In\n" \ + "order for deeptools to work properly this program needs\n"\ + "to be installed. If you already have a copy of this\n"\ + "program please be sure that it is found in your PATH or\n"\ + "that is referred in the configuration file of deepTools\n"\ + "located at:\n\n{}\n\n" \ + "The program can be downloaded from here:\n " \ + " {}\n\n" \ + "\n########################################################"\ + "\n\n".format(program, config_file, where_to_download) + sys.stderr.write(msg) + else: + # Something else went wrong while + # trying to run `program` + raise + + except Exception as e: + sys.stderr.write("Error: {}".format(e)) + + return False """ @@ -28,3 +71,4 @@ 'config/deeptools.cfg') config = ConfigParser.ConfigParser() config.readfp(open(config_file, 'r')) + diff --git a/deeptools/parserCommon.py b/deeptools/parserCommon.py index d0ae1a36da..f5976f1e3b 100755 --- a/deeptools/parserCommon.py +++ b/deeptools/parserCommon.py @@ -1,3 +1,4 @@ +import sys import argparse import config as cfg from deeptools._version import __version__ @@ -194,33 +195,10 @@ def checkBigWig(string): Checks if the path to USCS bedGraphToBigWig as set in the config is installed and is executable. """ - import os - import sys - if os.environ.get('DEEP_TOOLS_NO_CONFIG', False): - return string - if string == 'bigwig': - import pkg_resources - config_file = pkg_resources.resource_filename(__name__, - 'config/deeptools.cfg') - import config as cfg - bedgraph_to_bigwig = cfg.config.get('external_tools', - 'bedgraph_to_bigwig') - if not os.path.isfile(bedgraph_to_bigwig) or \ - not os.access(bedgraph_to_bigwig, os.X_OK): - msg = "\nYour computer does not have the UCSC program \n" \ - "bedGraphToBigWig installed or configured in the \n" \ - "deepTools config file. In order to output bigwig \n" \ - "files this tool needs to be installed and referred in the \n"\ - "configuration file located at:\n\n{}\n\n" \ - "Optionally, setting the environment variable \n"\ - "DEEP_TOOLS_NO_CONFIG will search \n" \ - "the program using the PATH.\n\n" \ - "The program can be downloaded from here: " \ - "http://hgdownload.cse.ucsc.edu/admin/exe/ \n\n" \ - "The output is set by default to 'bedgraph'\n".format( - config_file) - + if not cfg.checkProgram('bedGraphToBigWig', 'h', + 'http://hgdownload.cse.ucsc.edu/admin/exe/'): + msg = "The output is set by default to 'bedgraph'\n" sys.stderr.write(msg) return 'bedgraph' @@ -273,7 +251,8 @@ def computeMatrixOutputArgs(args=None): help='If this option is given, then the matrix ' 'of values underlying the heatmap will be saved ' 'using the indicated name, e.g. IndividualValues.tab.' - 'This matrix can easily be loaded into R or other programs.', + 'This matrix can easily be loaded into R or ' + 'other programs.', metavar='FILE', type=writableFile) output.add_argument('--outFileSortedRegions', @@ -424,7 +403,7 @@ def computeMatrixOptArgs(case=['scale-regions', 'reference-point'][0]): '(e.g. major satellites) that may bias the average ' 'values.') - # in contrast to other tools, + # in contrast to other tools, # computeMatrix by default outputs # messages and the --quiet flag supresses them optional.add_argument('--quiet', '-q', @@ -503,22 +482,23 @@ def heatmapperOptionalArgs(mode=['heatmap', 'profile'][0]): parser = argparse.ArgumentParser(add_help=False) cluster = parser.add_argument_group('Clustering arguments') - cluster.add_argument('--kmeans', - help='Number of clusters to compute. When this ' - 'option is set, then the matrix is split into clusters ' - 'using the kmeans algorithm. Only works for data that ' - 'is not grouped, otherwise only the first group will ' - 'be clustered. If more specific clustering methods ' - 'are required it is advisable to save the underlying matrix ' - 'and run the clustering using other software. The plotting ' - 'of the clustering may fail (Error: Segmentation fault) if a ' - 'cluster has very few members compared to the total number ' - 'or regions.', - type=int) - + cluster.add_argument( + '--kmeans', + help='Number of clusters to compute. When this ' + 'option is set, then the matrix is split into clusters ' + 'using the kmeans algorithm. Only works for data that ' + 'is not grouped, otherwise only the first group will ' + 'be clustered. If more specific clustering methods ' + 'are required it is advisable to save the underlying matrix ' + 'and run the clustering using other software. The plotting ' + 'of the clustering may fail (Error: Segmentation fault) if a ' + 'cluster has very few members compared to the total number ' + 'or regions.', + type=int) + optional = parser.add_argument_group('Optional arguments') - optional.add_argument("--help", "-h", action="help", + optional.add_argument("--help", "-h", action="help", help="show this help message and exit") optional.add_argument('--version', action='version', version='%(prog)s {}'.format(__version__)) @@ -529,8 +509,8 @@ def heatmapperOptionalArgs(mode=['heatmap', 'profile'][0]): choices=["mean", "median", "min", "max", "std", "sum"], help='Define the type of statistic that should be used for the ' - 'profile. The options are: "mean", "median", "min", "max", "sum" and ' - '"std".') + 'profile. The options are: "mean", "median", "min", "max", ' + '"sum" and "std".') optional.add_argument('--plotHeight', help='height in cm. The default for the plot ' @@ -718,12 +698,13 @@ def heatmapperOptionalArgs(mode=['heatmap', 'profile'][0]): action='store_true') optional.add_argument('--plotFileFormat', - metavar='', - help='image format type. If given, this option overrides the ' - 'image format based on the plotFile ending. ' - 'The available options are: "png", "emf", ' - '"eps", "pdf" and "svg"', - choices=['png','pdf', 'svg','eps', 'emf']) + metavar='', + help='image format type. If given, this ' + 'option overrides the ' + 'image format based on the plotFile ending. ' + 'The available options are: "png", "emf", ' + '"eps", "pdf" and "svg"', + choices=['png', 'pdf', 'svg', 'eps', 'emf']) optional.add_argument('--verbose', help='If set warning messages and ' diff --git a/deeptools/utilities.py b/deeptools/utilities.py index addd65f882..c71fc41800 100755 --- a/deeptools/utilities.py +++ b/deeptools/utilities.py @@ -1,4 +1,5 @@ import sys +import os debug = 0 @@ -113,22 +114,24 @@ def getCommonChrNames(bamFileHandlers, verbose=True): # bam files chrSizes = [] for i in range(0, len(bamFileHandlers[0].references)): - if "{}|{}".format(bamFileHandlers[0].references[i], - bamFileHandlers[0].lengths[i]) in commonChr: + if "{}|{}".format(bamFileHandlers[0].references[i], + bamFileHandlers[0].lengths[i]) in commonChr: - chrSizes.append( (bamFileHandlers[0].references[i], bamFileHandlers[0].lengths[i] ) ) + chrSizes.append((bamFileHandlers[0].references[i], + bamFileHandlers[0].lengths[i])) - outMessage.append( "\nUsing the following set of common chromosome names and lengths:\n" ) + outMessage.append("\nUsing the following set of common chromosome " + "names and lengths:\n") for chrSize in chrSizes: - outMessage.append( "{0:>15}\t{1:>10}\n".format(chrSize[0], chrSize[1]) ) + outMessage.append("{0:>15}\t{1:>10}\n".format(chrSize[0], chrSize[1])) if verbose: - sys.stderr.write("".join(outMessage) ) + sys.stderr.write("".join(outMessage)) return chrSizes - + def copyFileInMemory(filePath, suffix=''): - """ + """ copies a file into the special /dev/shm device which moves the file into memory. This process speeds ups the multiprocessor access to such files @@ -138,14 +141,56 @@ def copyFileInMemory(filePath, suffix=''): if os.name == 'nt': return filePath - import tempfile + memFileName = getTempFileName(suffix=suffix) import shutil - _tempFile = tempfile.NamedTemporaryFile( prefix="_corr_", - suffix=suffix, - dir='/dev/shm', - delete=False) + shutil.copyfile(filePath, memFileName) + + return memFileName + + +def getTempFileName(suffix=''): + """ + returns a temporary file name. + If the special /dev/shm device is available, + the temporary file would be located in that folder. + /dv/shm is a folder that resides in memory and + which has much faster accession. + """ + import tempfile + # is /dev/shm available? + try: + _tempFile = tempfile.NamedTemporaryFile(prefix="_deeptools_", + suffix=suffix, + dir='/dev/shm', + delete=False) + except OSError: + _tempFile = tempfile.NamedTemporaryFile(suffix=".sam", + delete=False) memFileName = _tempFile.name _tempFile.close() - shutil.copyfile( filePath, memFileName ) return memFileName + + +def which(program): + """ method to identify if a program + is on the user PATH variable. + From: http://stackoverflow.com/questions/377017/test-if-executable-exists-in-python + """ + import os + + def is_exe(fpath): + return os.path.isfile(fpath) and os.access(fpath, os.X_OK) + + fpath, fname = os.path.split(program) + if fpath: + if is_exe(program): + return program + else: + for path in os.environ["PATH"].split(os.pathsep): + path = path.strip('"') + exe_file = os.path.join(path, program) + if is_exe(exe_file): + return exe_file + + return None diff --git a/deeptools/writeBedGraph.py b/deeptools/writeBedGraph.py index d103d99895..9a27a04ed7 100755 --- a/deeptools/writeBedGraph.py +++ b/deeptools/writeBedGraph.py @@ -1,6 +1,5 @@ import os import shutil -import tempfile import numpy as np # own modules @@ -8,6 +7,7 @@ from deeptools.utilities import getCommonChrNames from deeptools.countReadsPerBin import getCoverageOfRegion, getSmoothRange from deeptools import bamHandler +from deeptools import utilities import config as cfg debug = 0 @@ -94,14 +94,7 @@ def writeBedGraph_worker(chrom, start, end, tileSize, defaultFragmentLength, fragmentFromRead_func=fragmentFromRead_func)) bamHandle.close() - # is /dev/shm available? - # working in this directory speeds the process - try: - _file = tempfile.NamedTemporaryFile(dir="/dev/shm", - suffix=".bg", delete=False) - except OSError: - _file = tempfile.NamedTemporaryFile(suffix=".bg", delete=False) - + _file = open(utilities.getTempFileName(suffix='.bg'), 'w') previousValue = None lengthCoverage = len(coverage[0]) @@ -248,6 +241,7 @@ def writeBedGraph(bamFilesList, outputFileName, fragmentLength, and that is related to the coverage underlying the tile. >>> test = Tester() + >>> import tempfile >>> outFile = tempfile.NamedTemporaryFile() >>> funcArgs = {'scaleFactor': 1.0} >>> writeBedGraph( [test.bamFile1], outFile.name, diff --git a/setup.py b/setup.py index 9502821bcc..639e206b6f 100755 --- a/setup.py +++ b/setup.py @@ -1,6 +1,7 @@ #-*- coding: utf-8 -*- import os +import sys import subprocess import re @@ -61,35 +62,66 @@ def run(self): class install(_install): def run(self): _install.run(self) -# import ipdb;ipdb.set_trace() - # check the installation of UCSC tools + if os.environ.get('DEEP_TOOLS_NO_CONFIG', False): + return + self.config_file = self.install_platlib + \ + "/deeptools/config/deeptools.cfg" + + # check installation of several components + samtools_installed = self.checkProgramIsInstalled( + 'samtools', 'view', + 'http://samtools.sourceforge.net/', + 'correctGCbias') + + bedGraphToBigWig_installed = self.checkProgramIsInstalled( + 'bedGraphToBigWig', '-h', + 'http://hgdownload.cse.ucsc.edu/admin/exe/', + 'bamCoverage, bamCompare, correctGCbias') + + bigwigInfo_installed = self.checkProgramIsInstalled( + 'bigWigInfo', '-h', + 'http://hgdownload.cse.ucsc.edu/admin/exe/', + 'bigwigCompare') + + if not samtools_installed or not bedGraphToBigWig_installed \ + or not bigwigInfo_installed: + + msg = "\n##########\nSome tools were not fund.\n"\ + "If you already have a copy of this programs installed\n"\ + "please be sure that they are found in your PATH or\n"\ + "that they referred in the configuration file of deepTools\n"\ + "located at:\n\n {}\n\n".format(self.config_file) + sys.stderr.write(msg) + + def checkProgramIsInstalled(self, program, args, where_to_download, + affected_tools): try: - subprocess.call(["bedGraphToBigWig", "-h"]) + _out = subprocess.Popen([program, args], stderr=subprocess.PIPE, + stdout=subprocess.PIPE) + return True except OSError as e: if e.errno == os.errno.ENOENT: # handle file not found error. - import warnings # the config file is installed in: - config_file = self.install_platlib + \ - "/deeptools/config/deeptools.cfg" - msg = "\n#############################################\n\n"\ - "Your computer does not have the UCSC program \n" \ - "bedGraphToBigWig installed or configured in the \n" \ - "deepTools config file. In order to output bigwig \n" \ - "files this program needs to be installed and "\ - "referred in the \n"\ - "configuration file located at:\n\n{}\n\n" \ - "The program can be downloaded from here: " \ - "http://hgdownload.cse.ucsc.edu/admin/exe/ \n\n" \ - "The output is set by default to 'bedgraph'\n\n "\ - "\n#############################################"\ - "\n\n".format(config_file) - warnings.warn(msg) + msg = "\n**{0} not found. This " \ + "program is needed for the following "\ + "tools to work properly:\n"\ + " {1}\n"\ + "{0} can be downloaded from here:\n " \ + " {2}\n".format(program, affected_tools, + where_to_download) + sys.stderr.write(msg) else: # Something else went wrong while - # trying to run `bedGraphToBigWig` + # trying to run `program` raise + except Exception as e: + sys.stderr.write("Error: {}".format(e)) + + +######## + setup( name='deepTools', version=get_version(),