Package glue :: Package ligolw :: Package utils :: Module process
[hide private]
[frames] | no frames]

Source Code for Module glue.ligolw.utils.process

  1  # Copyright (C) 2006--2013,2015  Kipp Cannon 
  2  # 
  3  # This program is free software; you can redistribute it and/or modify it 
  4  # under the terms of the GNU General Public License as published by the 
  5  # Free Software Foundation; either version 2 of the License, or (at your 
  6  # option) any later version. 
  7  # 
  8  # This program is distributed in the hope that it will be useful, but 
  9  # WITHOUT ANY WARRANTY; without even the implied warranty of 
 10  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General 
 11  # Public License for more details. 
 12  # 
 13  # You should have received a copy of the GNU General Public License along 
 14  # with this program; if not, write to the Free Software Foundation, Inc., 
 15  # 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. 
 16   
 17   
 18  # 
 19  # ============================================================================= 
 20  # 
 21  #                                   Preamble 
 22  # 
 23  # ============================================================================= 
 24  # 
 25   
 26   
 27  """ 
 28  A collection of utilities to assist applications in manipulating the 
 29  process and process_params tables in LIGO Light-Weight XML documents. 
 30  """ 
 31   
 32   
 33  import os 
 34  import socket 
 35  from six import StringIO 
 36  import time 
 37   
 38   
 39  from glue import git_version 
 40  from .. import ligolw 
 41  from .. import lsctables 
 42  from .. import types as ligolwtypes 
 43  import six 
 44   
 45   
 46  try: 
 47          from lal import UTCToGPS as _UTCToGPS 
 48  except ImportError: 
 49          # lal is optional 
 50          # FIXME:  make it not optional 
 51          from glue import gpstime 
 52          _UTCToGPS = lambda utc: int(gpstime.GpsSecondsFromPyUTC(time.mktime(utc))) 
 53   
 54   
 55  __author__ = "Kipp Cannon <kipp.cannon@ligo.org>, Larne Pekowsky <lppekows@physics.syr.edu>" 
 56  __version__ = "git id %s" % git_version.id 
 57  __date__ = git_version.date 
 58   
 59   
 60  # 
 61  # ============================================================================= 
 62  # 
 63  #                               Process Metadata 
 64  # 
 65  # ============================================================================= 
 66  # 
 67   
 68   
69 -def get_username():
70 """ 71 Try to retrieve the username from a variety of sources. First the 72 environment variable LOGNAME is tried, if that is not set the 73 environment variable USERNAME is tried, if that is not set the 74 password database is consulted (only on Unix systems, if the import 75 of the pwd module succeeds), finally if that fails KeyError is 76 raised. 77 """ 78 try: 79 return os.environ["LOGNAME"] 80 except KeyError: 81 pass 82 try: 83 return os.environ["USERNAME"] 84 except KeyError: 85 pass 86 try: 87 import pwd 88 return pwd.getpwuid(os.getuid())[0] 89 except (ImportError, KeyError): 90 raise KeyError
91 92
93 -def append_process(xmldoc, program = None, version = None, cvs_repository = None, cvs_entry_time = None, comment = None, is_online = False, jobid = 0, domain = None, ifos = None):
94 """ 95 Add an entry to the process table in xmldoc. program, version, 96 cvs_repository, comment, and domain should all be strings or 97 unicodes. cvs_entry_time should be a string or unicode in the 98 format "YYYY/MM/DD HH:MM:SS". is_online should be a boolean, jobid 99 an integer. ifos should be an iterable (set, tuple, etc.) of 100 instrument names. 101 102 See also register_to_xmldoc(). 103 """ 104 try: 105 proctable = lsctables.ProcessTable.get_table(xmldoc) 106 except ValueError: 107 proctable = lsctables.New(lsctables.ProcessTable) 108 xmldoc.childNodes[0].appendChild(proctable) 109 110 proctable.sync_next_id() 111 112 process = proctable.RowType() 113 process.program = program 114 process.version = version 115 process.cvs_repository = cvs_repository 116 # FIXME: remove the "" case when the git versioning business is 117 # sorted out 118 if cvs_entry_time is not None and cvs_entry_time != "": 119 try: 120 # try the git_version format first 121 process.cvs_entry_time = _UTCToGPS(time.strptime(cvs_entry_time, "%Y-%m-%d %H:%M:%S +0000")) 122 except ValueError: 123 # fall back to the old cvs format 124 process.cvs_entry_time = _UTCToGPS(time.strptime(cvs_entry_time, "%Y/%m/%d %H:%M:%S")) 125 else: 126 process.cvs_entry_time = None 127 process.comment = comment 128 process.is_online = int(is_online) 129 process.node = socket.gethostname() 130 try: 131 process.username = get_username() 132 except KeyError: 133 process.username = None 134 process.unix_procid = os.getpid() 135 process.start_time = _UTCToGPS(time.gmtime()) 136 process.end_time = None 137 process.jobid = jobid 138 process.domain = domain 139 process.instruments = ifos 140 process.process_id = proctable.get_next_id() 141 proctable.append(process) 142 return process
143 144
145 -def set_process_end_time(process):
146 """ 147 Set the end time in a row in a process table to the current time. 148 """ 149 process.end_time = _UTCToGPS(time.gmtime()) 150 return process
151 152
153 -def append_process_params(xmldoc, process, params):
154 """ 155 xmldoc is an XML document tree, process is the row in the process 156 table for which these are the parameters, and params is a list of 157 (name, type, value) tuples one for each parameter. 158 159 See also process_params_from_dict(), register_to_xmldoc(). 160 """ 161 try: 162 paramtable = lsctables.ProcessParamsTable.get_table(xmldoc) 163 except ValueError: 164 paramtable = lsctables.New(lsctables.ProcessParamsTable) 165 xmldoc.childNodes[0].appendChild(paramtable) 166 167 for name, typ, value in params: 168 row = paramtable.RowType() 169 row.program = process.program 170 row.process_id = process.process_id 171 row.param = six.text_type(name) 172 if typ is not None: 173 row.type = six.text_type(typ) 174 if row.type not in ligolwtypes.Types: 175 raise ValueError("invalid type '%s' for parameter '%s'" % (row.type, row.param)) 176 else: 177 row.type = None 178 if value is not None: 179 row.value = six.text_type(value) 180 else: 181 row.value = None 182 paramtable.append(row) 183 return process
184 185
186 -def get_process_params(xmldoc, program, param, require_unique_program = True):
187 """ 188 Return a list of the values stored in the process_params table for 189 params named param for the program(s) named program. The values 190 are returned as Python native types, not as the strings appearing 191 in the XML document. If require_unique_program is True (default), 192 then the document must contain exactly one program with the 193 requested name, otherwise ValueError is raised. If 194 require_unique_program is not True, then there must be at least one 195 program with the requested name otherwise ValueError is raised. 196 """ 197 process_ids = lsctables.ProcessTable.get_table(xmldoc).get_ids_by_program(program) 198 if len(process_ids) < 1: 199 raise ValueError("process table must contain at least one program named '%s'" % program) 200 elif require_unique_program and len(process_ids) != 1: 201 raise ValueError("process table must contain exactly one program named '%s'" % program) 202 return [row.pyvalue for row in lsctables.ProcessParamsTable.get_table(xmldoc) if (row.process_id in process_ids) and (row.param == param)]
203 204
205 -def doc_includes_process(xmldoc, program):
206 """ 207 Return True if the process table in xmldoc includes entries for a 208 program named program. 209 """ 210 return program in lsctables.ProcessTable.get_table(xmldoc).getColumnByName(u"program")
211 212
213 -def process_params_from_dict(paramdict):
214 """ 215 Generator function yields (name, type, value) tuples constructed 216 from a dictionary of name/value pairs. The tuples are suitable for 217 input to append_process_params(). This is intended as a 218 convenience for converting command-line options into process_params 219 rows. The name values in the output have "--" prepended to them 220 and all "_" characters replaced with "-". The type strings are 221 guessed from the Python types of the values. If a value is a 222 Python list (or instance of a subclass thereof), then one tuple is 223 produced for each of the items in the list. 224 225 Example: 226 227 >>> list(process_params_from_dict({"verbose": True, "window": 4.0, "include": ["/tmp", "/var/tmp"]})) 228 [(u'--window', u'real_8', 4.0), (u'--verbose', None, None), (u'--include', u'lstring', '/tmp'), (u'--include', u'lstring', '/var/tmp')] 229 """ 230 for name, values in paramdict.items(): 231 # change the name back to the form it had on the command line 232 name = u"--%s" % name.replace("_", "-") 233 234 if values is True or values is False: 235 yield (name, None, None) 236 elif values is not None: 237 if not isinstance(values, list): 238 values = [values] 239 for value in values: 240 yield (name, ligolwtypes.FromPyType[type(value)], value)
241 242
243 -def register_to_xmldoc(xmldoc, program, paramdict, **kwargs):
244 """ 245 Register the current process and params to an XML document. 246 program is the name of the program. paramdict is a dictionary of 247 name/value pairs that will be used to populate the process_params 248 table; see process_params_from_dict() for information on how these 249 name/value pairs are interpreted. Any additional keyword arguments 250 are passed to append_process(). Returns the new row from the 251 process table. 252 """ 253 process = append_process(xmldoc, program = program, **kwargs) 254 append_process_params(xmldoc, process, process_params_from_dict(paramdict)) 255 return process
256 257 258 # The tables in the segment database declare most fields "NOT NULL", so provide stub values
259 -def register_to_ldbd(client, program, paramdict, version = u'0', cvs_repository = u'-', cvs_entry_time = 0, comment = u'-', is_online = False, jobid = 0, domain = None, ifos = u'-'):
260 """ 261 Register the current process and params to a database via a 262 LDBDClient. The program and paramdict arguments and any additional 263 keyword arguments are the same as those for register_to_xmldoc(). 264 Returns the new row from the process table. 265 """ 266 xmldoc = ligolw.Document() 267 xmldoc.appendChild(ligolw.LIGO_LW()) 268 process = register_to_xmldoc(xmldoc, program, paramdict, version = version, cvs_repository = cvs_repository, cvs_entry_time = cvs_entry_time, comment = comment, is_online = is_online, jobid = jobid, domain = domain, ifos = ifos) 269 270 fake_file = StringIO() 271 xmldoc.write(fake_file) 272 client.insert(fake_file.getvalue()) 273 274 return process
275