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