61846245aa9a5a7801f82cb0ea8bdb6e545df575
[htsworkflow.git] / bin / config_pipeline.py
1 #!/usr/bin/python
2 import subprocess
3 import re
4 import os
5 import logging
6
7 logging.basicConfig(level=logging.DEBUG,
8                     format='%(asctime)s %(levelname)-8s %(message)s',
9                     datefmt='%a, %d %b %Y %H:%M:%S',
10                     filename='config_pipeline.log',
11                     filemode='w')
12
13 class ConfigInfo:
14   
15   def __init__(self):
16     self.run_path = None
17     self.bustard_path = None
18     self.config_filepath = None
19
20 #FLAGS
21 RUN_ABORT = 'abort'
22
23 #Info
24 s_start = re.compile('Starting Genome Analyzer Pipeline')
25 s_gerald = re.compile("[\S\s]+--GERALD[\S\s]+--make[\S\s]+")
26 s_generating = re.compile('Generating journals, Makefiles and parameter files')
27 s_seq_folder = re.compile('^Sequence folder: ')
28 s_stderr_taskcomplete = re.compile('^Task complete, exiting')
29
30 #Errors
31 s_invalid_cmdline = re.compile('Usage:[\S\s]*goat_pipeline.py')
32 s_species_dir_err = re.compile('Error: Lane [1-8]:')
33
34 #Ignore
35 s_skip = re.compile('s_[0-8]_[0-9]+')
36
37 def config_stdout_handler(line, conf_info):
38   """
39   Processes each line of output from GOAT
40   and stores useful information using the logging module
41
42   Loads useful information into conf_info as well, for future
43   use outside the function.
44
45   returns True if found condition that signifies success.
46   """
47
48   # Irrelevant line
49   if s_skip.search(line):
50     pass
51   elif s_invalid_cmdline.search(line):
52     logging.error("Invalid commandline options!")
53   elif s_start.search(line):
54     logging.info('START: Configuring pipeline')
55   elif s_gerald.search(line):
56     logging.info('Running make now')
57   elif s_generating.search(line):
58     logging.info('Make files generted')
59     return True
60   elif s_seq_folder.search(line):
61     mo = s_seq_folder.search(line)
62     conf_info.bustard_path = line[mo.end():]
63     conf_info.run_path, temp = os.path.split(conf_info.bustard_path)
64   else:
65     logging.warning('How to handle: %s' % (line))
66
67   return False
68
69
70
71 def config_stderr_handler(line, conf_info):
72   """
73   Processes each line of output from GOAT
74   and stores useful information using the logging module
75
76   Loads useful information into conf_info as well, for future
77   use outside the function.
78
79   returns RUN_ABORT upon detecting failure; True on success message
80   """
81
82   if s_species_dir_err.search(line):
83     logging.error(line)
84     return RUN_ABORT
85   elif s_stderr_taskcomplete.search(line):
86     logging.info('Configure step successful (from: stderr)')
87     return True
88   else:
89     logging.debug('STDERR: How to handle: %s' % (line))
90
91   return False
92
93 #FIXME: Temperary hack
94 f = open('pipeline_run.log', 'w')
95
96 def pipeline_handler(line, conf_info):
97   """
98   Processes each line of output from running the pipeline
99   and stores useful information using the logging module
100
101   Loads useful information into conf_info as well, for future
102   use outside the function.
103
104   returns True if found condition that signifies success.
105   """
106
107   f.write(line + '\n')
108
109   return True
110
111
112 def configure(conf_info):
113   """
114   Attempts to configure the GA pipeline using goat.
115
116   Uses logging module to store information about status.
117
118   returns True if configuration successful, otherwise False.
119   """
120   #ERROR Test:
121   #pipe = subprocess.Popen(['goat_pipeline.py',
122   #                         '--GERALD=config32bk.txt',
123   #                         '--make .',],
124   #                         #'.'],
125   #                        stdout=subprocess.PIPE,
126   #                        stderr=subprocess.PIPE)
127
128   #Not a test; actual run attempt.
129   pipe = subprocess.Popen(['goat_pipeline.py',
130                     '--GERALD=%s' % (conf_info.config_filepath),
131                            '--make',
132                            '.'],
133                           stdout=subprocess.PIPE,
134                           stderr=subprocess.PIPE)
135
136   #Process stdout
137   stdout_line = pipe.stdout.readline()
138
139   complete = False
140   while stdout_line != '':
141     # Handle stdout
142     if config_stdout_handler(stdout_line, conf_info):
143       complete = True
144     stdout_line = pipe.stdout.readline()
145
146
147   error_code = pipe.wait()
148   if error_code:
149     logging.error('Recieved error_code: %s' % (error_code))
150   else:
151     logging.info ('We are go for launch!')
152
153   #Process stderr
154   stderr_line = pipe.stderr.readline()
155
156   abort = 'NO!'
157   stderr_success = False
158   while stderr_line != '':
159     stderr_status = config_stderr_handler(stderr_line, conf_info)
160     if stderr_status == RUN_ABORT:
161       abort = RUN_ABORT
162     elif stderr_status is True:
163       stderr_success = True
164     stderr_line = pipe.stderr.readline()
165
166
167   #Success requirements:
168   # 1) The stdout completed without error
169   # 2) The program exited with status 0
170   # 3) No errors found in stdout
171   print '#Expect: True, False, True, True'
172   print complete, bool(error_code), abort != RUN_ABORT, stderr_success is True
173   status = complete is True and \
174            bool(error_code) is False and \
175            abort != RUN_ABORT and \
176            stderr_success is True
177
178   # If everything was successful, but for some reason
179   #  we didn't retrieve the path info, log it.
180   if status is True:
181     if conf_info.bustard_path is None or conf_info.run_path is None:
182       logging.error("Failed to retrieve run_path")
183       return False
184   
185   return status
186
187
188 def run_pipeline(conf_info):
189
190   # Fail if the run_path doesn't actually exist
191   if not os.path.exists(conf_info.run_path):
192     logging.error('Run path does not exist: %s' \
193               % (conf_info.run_path))
194     return False
195
196   # Change cwd to run_path
197   os.chdir(conf_info.run_path)
198
199   # Start the pipeline (and hide!)
200   pipe = subprocess.Popen(['make',
201                            '-j8',
202                            'recursive'],
203                           stdout=subprocess.PIPE,
204                           stderr=subprocess.PIPE)
205
206   line = pipe.stdout.readline()
207
208   complete = False
209   while line != '':
210     if pipeline_handler(line, conf_info):
211       complete = True
212     line = pipe.stdout.readline()
213
214
215
216
217 if __name__ == '__main__':
218   ci = ConfigInfo()
219   ci.config_filepath = 'config32bk.txt'
220   
221   status = configure(ci)
222   if status:
223     print "Configure success"
224   else:
225     print "Configure failed"
226
227   #print 'Run Dir:', ci.run_path
228   #print 'Bustard Dir:', ci.bustard_path
229
230   #if status:
231   #  run_pipeline(ci)
232
233   #FIXME: Temperary hack
234   f.close()