Package Bio :: Package PopGen :: Package SimCoal :: Module Controller
[hide private]
[frames] | no frames]

Source Code for Module Bio.PopGen.SimCoal.Controller

  1  # Copyright 2007 by Tiago Antao <tiagoantao@gmail.com>. 
  2  # Revisions copyright 2014 by Melissa Gymrek <mgymrek@mit.edu>. 
  3  # All rights reserved. 
  4  # This code is part of the Biopython distribution and governed by its 
  5  # license.  Please see the LICENSE file that should have been included 
  6  # as part of this package. 
  7   
  8  """This module allows you to control Simcoal2 and FastSimcoal (DEPRECATED).""" 
  9   
 10  import os 
 11  import sys 
 12  from Bio.Application import AbstractCommandline, _Option, _Switch 
 13   
 14   
15 -class SimCoalController(object):
16 - def __init__(self, simcoal_dir):
17 """Initializes the controller. (DEPRECATED) 18 19 simcoal_dir is the directory where simcoal is. 20 21 The initializer checks for existence and executability of binaries. 22 """ 23 self.simcoal_dir = simcoal_dir 24 self.os_name = os.name # remove this? 25 dir_contents = os.listdir(self.simcoal_dir) 26 # We expect the tool to be installed as simcoal2(.exe) 27 # without any trailing version number. 28 self.bin_name = "simcoal2" 29 if self.bin_name not in dir_contents: 30 # Try case insensitive, 31 dir_contents = [x.lower() for x in dir_contents] 32 if self.bin_name not in dir_contents: 33 # Try with .exe 34 self.bin_name += '.exe' 35 if self.bin_name not in dir_contents: 36 raise IOError("SimCoal not available") 37 if not os.access(os.path.join(self.simcoal_dir, self.bin_name), 38 os.X_OK): 39 raise IOError("SimCoal not executable")
40
41 - def run_simcoal(self, par_file, num_sims, ploydi='1', par_dir='.'):
42 """Executes SimCoal. 43 """ 44 if par_dir is None: 45 par_dir = os.sep.join([".", 'SimCoal', 'runs']) 46 curr_dir = os.getcwd() 47 # TODO - Make sure we change drive on Windows as well? 48 os.chdir(par_dir) 49 exe = os.path.join(self.simcoal_dir, self.bin_name) 50 if " " in exe: 51 exe = '"' + exe + '"' 52 cmd = exe + ' ' + par_file + ' ' + str(num_sims) + ' ' + ploydi 53 # TODO - Better way to spot if on Jython on Windows? 54 if sys.platform == "win32" or self.bin_name.endswith(".exe"): 55 # There is no /dev/nul on Windows 56 cmd += ' > nul 2>nul' 57 else: 58 cmd += ' >/dev/null 2>&1' 59 os.system(cmd) 60 os.chdir(curr_dir)
61 62
63 -class _FastSimCoalCommandLine(AbstractCommandline):
64 """ Command Line Wrapper for Fastsimcoal 65 """
66 - def __init__(self, fastsimcoal_dir=None, cmd='fastsimcoal', **kwargs):
67 self.parameters = [ 68 _Option(["-i", "--ifile", "parfile"], "Name of the parameter file", 69 filename=True, equate=False, is_required=False, 70 checker_function=lambda x: isinstance(x, str)), 71 _Option(["-n", "--numsims", "numsims"], "Number of simulations to perform", 72 filename=False, equate=False, is_required=True, 73 checker_function=lambda x: isinstance(x, int)), 74 _Option(["-t", "--tfile", "tfile"], "Name of template parameter file", 75 filename=True, equate=False, is_required=False, 76 checker_function=lambda x: isinstance(x, str)), 77 _Option(["-f", "--dfile", "dfile"], "Name of parameter definition file", 78 filename=True, equate=False, is_required=False, 79 checker_function=lambda x: isinstance(x, str)), 80 _Option(["-F", "--dFile", "dFile"], 81 """Same as -f but only uses simple parameters defined 82 in the template file. Complex params are recomputed""", 83 filename=True, equate=False, is_required=False, 84 checker_function=lambda x: isinstance(x, str)), 85 _Option(["-e", "--efile", "efile"], 86 """Parameter prior definition file. 87 Parameters drawn from specified distributions are 88 substituted into template file.""", 89 filename=True, equate=False, is_required=False, 90 checker_function=lambda x: isinstance(x, str)), 91 _Option(["-E", "--numest", "numest"], 92 """Number of estimations from parameter priors. 93 Listed parameter values are substituted in template file.""", 94 filename=False, equate=False, is_required=False, 95 checker_function=lambda x: isinstance(x, int)), 96 _Switch(["-g", "--genotypic", "genotypic"], "Generates Arlequin projects with genotypic data"), 97 _Switch(["-p", "--phased", "phased"], "Specifies that phase is known in Arlequin output"), 98 _Option(["-s", "--dnatosnp", "dnatosnp"], 99 """"Output DNA as SNP data (0: ancestral, 1: derived 100 and specify maximum no. SNPs to output.""", 101 filename=False, equate=False, is_required=False, 102 checker_function=lambda x: isinstance(x, int)), 103 _Switch(["-S", "--allsites", "allsites"], 104 """Output the whole DNA sequence, including monomorphic sites"""), 105 _Switch(["-I", "--inf", "inf"], 106 """Generates DNA mutations according to an 107 infinite sites (IS) mutation model."""), 108 _Switch(["-d", "--dsfs", "dsfs"], "Computes derived site frequency spectrum"), 109 _Switch(["-m", "--msfs", "msfs"], "Computes minor site frequency spectrum"), 110 _Option(["-o", "--oname", "oname"], "Generic name for observed SFS files", 111 filename=False, equate=False, is_required=False, 112 checker_function=lambda x: isinstance(x, str)), 113 _Switch(["-H", "--header", "header"], "Generates header in site frequency spectrum files."), 114 _Switch(["-q", "--quiet", "quiet"], "Minimal messages output to console"), 115 _Switch(["-T", "--tree", "tree"], "Output coalescent tree in nexus format."), 116 _Option(["-k", "--keep", "keep"], 117 """Number of simulated polymorphic sites kept in memory. 118 If the simulated no. is larger, then temporary files are created.""", 119 filename=False, equate=False, is_required=False, 120 checker_function=lambda x: isinstance(x, int)), 121 _Option(["--seed", "seed"], "Seed for the random number generator (positive int <=1E6)", 122 filename=False, equate=False, is_required=False, 123 checker_function=lambda x: isinstance(x, int)), 124 _Switch(["-x", "--noarloutput", "noarloutput"], "Does not generate Arlequin output"), 125 _Switch(["-D", "--dadioutput", "dadioutput"], "Output SFS in dadi format"), 126 _Option(["-M", "--maxlhood", "maxlhood"], 127 """Perform parameter estimation by max lhood from SFS, and 128 define stop criterion as min., rel., diff. in parameter 129 values between iterations""", 130 filename=False, equate=False, is_required=False, 131 checker_function=lambda x: isinstance(x, float)), 132 _Option(["-N", "--maxnumsims", "maxnumsims"], 133 """Maximum number of simulations to perform during 134 likelihood maximization.""", 135 filename=False, equate=False, is_required=False, 136 checker_function=lambda x: isinstance(x, int)), 137 _Option(["-l", "--minnumloops", "minnumloops"], 138 """Minimum number of iteration loops to perform during 139 likelihood maximization.""", 140 filename=False, equate=False, is_required=False, 141 checker_function=lambda x: isinstance(x, int)), 142 _Option(["-L", "--maxnumloops", "maxnumloops"], 143 """Maximum number of iterations to perform during 144 likelihood maximization""", 145 filename=False, equate=False, is_required=False, 146 checker_function=lambda x: isinstance(x, int)), 147 _Option(["-C", "--minSFSCount", "minSFSCount"], 148 """Minimum observed SFS entry count taken into account 149 in likelihood computation""", 150 filename=False, equate=False, is_required=False, 151 checker_function=lambda x: isinstance(x, int)), 152 _Switch(["-0", "--removeZeroSFS", "removeZeroSFS"], 153 """Do not take into account monomorphic sites for 154 SFS likelihood computation."""), 155 _Option(["-a", "--ascDeme", "ascDeme"], 156 """This is the deme id where ascertainment is performed 157 when simulating SNPs.""", 158 filename=False, equate=False, is_required=False, 159 checker_function=lambda x: isinstance(x, int)), 160 _Option(["-A", "--ascSize", "ascSize"], 161 """Number of ascertained chromosomes used to define SNPs in 162 a given deme.""", 163 filename=False, equate=False, is_required=False, 164 checker_function=lambda x: isinstance(x, int)), 165 _Switch(["-u", "--multiSFS", "multiSFS"], 166 "Generate or use multidimensional SFS")] 167 AbstractCommandline.__init__(self, cmd, **kwargs)
168 169
170 -class FastSimCoalController(object):
171 - def __init__(self, fastsimcoal_dir=None, bin_name="fsc252"):
172 """Initializes the controller. 173 174 fastsimcoal_dir is the directory where fastsimcoal is. 175 By default the binary should be called fsc252. 176 bin_name specifies a different name for the binary. 177 178 The initializer checks for existence and executability of binaries 179 and sets up the command line controller. 180 181 Fastsimcoal2 is available here: http://cmpg.unibe.ch/software/fastsimcoal2/. 182 This wrapper was written and tested for fastsimcoal version 2.51. 183 """ 184 self.bin_name = bin_name 185 self.fastsimcoal_dir = fastsimcoal_dir 186 if fastsimcoal_dir is None: 187 for path in os.environ["PATH"].split(os.pathsep): 188 if os.path.isfile(os.path.join(path, self.bin_name)): 189 self.fastsimcoal_dir = path 190 if self.fastsimcoal_dir is None: 191 raise IOError("Fastsimcoal not available") 192 else: 193 dir_contents = os.listdir(fastsimcoal_dir) 194 if self.bin_name not in dir_contents: 195 raise IOError("Fastsimcoal not available") 196 if not os.access(os.path.join(self.fastsimcoal_dir, self.bin_name), os.X_OK): 197 raise IOError("Fastsimcoal not executable")
198
199 - def run_fastsimcoal(self, par_file, num_sims, par_dir='.', opts=None):
200 """Executes Fastsimcoal. 201 202 par_file is the input parameter file (--ifile) for fastsimcoal. 203 num_sims is the number of simulations to perform. 204 par_dir is the directory where par_file is and where output will be written. 205 opts is a dictionary of additional options to fastsimcoal. 206 """ 207 if opts is None: 208 opts = {} 209 if par_dir is None: 210 par_dir = os.sep.join([".", "Fastsimcoal", "runs"]) 211 if not os.path.exists(par_dir): 212 os.mkdir(par_dir) 213 curr_dir = os.getcwd() 214 os.chdir(par_dir) 215 if par_file is None: # Must use .tpl for -t instead if no par_file 216 controller = _FastSimCoalCommandLine(cmd=os.path.join(self.fastsimcoal_dir, self.bin_name), 217 numsims=num_sims, **opts) 218 else: 219 controller = _FastSimCoalCommandLine(cmd=os.path.join(self.fastsimcoal_dir, self.bin_name), 220 parfile=par_file, numsims=num_sims, **opts) 221 controller() 222 os.chdir(curr_dir)
223