easyvvuq.data_structs
Data structures to ensure consistency during serialization for databases.
1"""Data structures to ensure consistency during serialization for databases. 2 3""" 4import os 5import logging 6import json 7from easyvvuq import constants 8from easyvvuq.utils.helpers import easyvvuq_serialize 9import numpy 10 11__copyright__ = """ 12 13 Copyright 2018 Robin A. Richardson, David W. Wright 14 15 This file is part of EasyVVUQ 16 17 EasyVVUQ is free software: you can redistribute it and/or modify 18 it under the terms of the Lesser GNU General Public License as published by 19 the Free Software Foundation, either version 3 of the License, or 20 (at your option) any later version. 21 22 EasyVVUQ is distributed in the hope that it will be useful, 23 but WITHOUT ANY WARRANTY; without even the implied warranty of 24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 Lesser GNU General Public License for more details. 26 27 You should have received a copy of the Lesser GNU General Public License 28 along with this program. If not, see <https://www.gnu.org/licenses/>. 29 30""" 31__license__ = "LGPL" 32 33logger = logging.getLogger(__name__) 34 35 36def check_local_dir(path, dir_type='campaign'): 37 """ 38 Check that local path exists and if not create it. 39 40 Parameters 41 ---------- 42 path : str 43 Directory location to check. 44 dir_type : str, default='campaign' 45 Type of directory we are checking (used for user and debugging 46 information.) 47 48 Returns 49 ------- 50 51 """ 52 53 if not os.path.isdir(path): 54 55 if os.path.exists(path): 56 logger.critical(f'{path} specified as {dir_type} directory ' 57 f'for local run but is not a directory.') 58 raise IOError(f'Invalid {dir_type} directory') 59 else: 60 os.makedirs(path) 61 62 63def check_reference(ref, run_name, ref_type='campaign'): 64 """ 65 Validation check for a `RunInfo` reference. Checks that an integer value 66 has been passed to use as a reference to another 'table' - i.e. to a 67 specific campaign, app or sampler. 68 69 Parameters 70 ---------- 71 ref : int 72 Reference to be checked. 73 run_name : str 74 Name of run for which the check is being performed (user info/ 75 debugging). 76 ref_type : str, default='campaign' 77 Are we checking for a campaign, sampler or app (user info/ 78 debugging). 79 80 Returns 81 ------- 82 83 """ 84 85 if ref is None: 86 message = f'No {ref_type} id specified for run {run_name}' 87 logger.critical(message) 88 raise RuntimeError(message) 89 90 if not isinstance(ref, int): 91 message = (f'Invalid {ref_type} id ({ref}) specified for ' 92 f'run {run_name}') 93 logger.critical(message) 94 raise RuntimeError(message) 95 96 97class RunInfo: 98 """Handles information for individual application runs. 99 100 Parameters 101 ---------- 102 run_name : str 103 Human readable name of the run. 104 app : None or int 105 ID of the associated application. 106 params : None or dict 107 Dictionary of parameter values for this run. 108 sample: None or int 109 ID of the sampler that created the run. 110 campaign: None or int 111 ID of the associated campaign. 112 113 Attributes 114 ---------- 115 campaign : int 116 ID of the associated campaign. 117 sample : int 118 ID of the sampler that created the run. 119 app : int 120 ID of the associated application. 121 run_name : str 122 Human readable name of the run. 123 status : enum(Status) 124 """ 125 126 def __init__( 127 self, 128 run_name=None, 129 run_dir=None, 130 app=None, 131 params=None, 132 sample=None, 133 campaign=None, 134 status=constants.Status.NEW): 135 136 self.campaign = campaign 137 self.sample = sample 138 self.app = app 139 self.run_name = run_name 140 self.run_dir = run_dir 141 142 if not params: 143 message = f'No run configuration specified for run {run_name}' 144 raise RuntimeError(message) 145 146 self.params = params 147 self.status = status 148 149 self.iteration = 0 150 151 def to_dict(self, flatten=False): 152 """Convert to a dictionary (optionally flatten to single level) 153 154 Parameters 155 ---------- 156 flatten : bool 157 Should the return dictionary be single level (i.e. should `params` 158 or other dictionary variables be serialized). 159 160 Returns 161 ------- 162 dict 163 Dictionary representing the run - if flattened then params are 164 returned as a JSON format sting. 165 """ 166 167 def convert_nonserializable(obj): 168 if isinstance(obj, numpy.int64): 169 return int(obj) 170 raise TypeError('Unknown type:', type(obj)) 171 172 if flatten: 173 174 out_dict = { 175 'run_name': self.run_name, 176 'run_dir': self.run_dir, 177 'params': json.dumps(self.params, default=convert_nonserializable), 178 'status': constants.Status(self.status), 179 'campaign': self.campaign, 180 'sampler': self.sample, 181 'app': self.app, 182 'iteration': self.iteration, 183 } 184 185 else: 186 187 out_dict = { 188 'run_name': self.run_name, 189 'run_dir': self.run_dir, 190 'params': self.params, 191 'status': constants.Status(self.status), 192 'campaign': self.campaign, 193 'sampler': self.sample, 194 'app': self.app, 195 'iteration': self.iteration, 196 } 197 198 return out_dict 199 200 201class AppInfo: 202 """Handles information for particular application. 203 204 Attributes 205 ---------- 206 name : str or None 207 Human readable application name. 208 paramsspec : ParamsSpecification or None 209 Description of possible parameter values. 210 """ 211 212 def __init__( 213 self, 214 name=None, 215 paramsspec=None, 216 actions=None): 217 218 self.name = name 219 self.paramsspec = paramsspec 220 self.actions = actions 221 222 def to_dict(self, flatten=False): 223 """Convert to a dictionary (optionally flatten to single level) 224 225 Parameters 226 ---------- 227 flatten : bool 228 Should the return dictionary be single level (i.e. should `paramsspec` 229 be serialized). 230 231 Returns 232 ------- 233 dict 234 Dictionary representing the application- if flattened then `paramsspec` 235 is returned as a JSON format sting. 236 """ 237 238 if flatten: 239 240 out_dict = self.to_dict() 241 242 out_dict['params'] = self.paramsspec.serialize() 243 else: 244 245 out_dict = { 246 'name': self.name, 247 'params': self.paramsspec, 248 'actions': easyvvuq_serialize(self.actions), 249 } 250 251 return out_dict 252 253 254class CampaignInfo: 255 """Handles information on Campaign. 256 257 Parameters 258 ---------- 259 name : str or None 260 Human readable campaign name. 261 easyvvuq_version : str or None 262 Version of EasyVVUQ used to create the campaign. 263 campaign_dir_prefix : str or None 264 Prefix test for campaign directory. 265 campaign_dir : str or None, 266 Path to the campaign directory. 267 runs_dir : str or None 268 path to run directory (within the campaign directory) 269 local : bool, default=False 270 Is this campaign designed to be created and executed on the same 271 machine? 272 273 Attributes 274 ---------- 275 name : str or None 276 Human readable campaign name. 277 easyvvuq_version : str or None 278 Version of EasyVVUQ used to create the campaign. 279 campaign_dir_prefix : str or None 280 Prefix test for campaign directory. 281 campaign_dir : str or None, 282 Path to the campaign directory. 283 runs_dir : str or None 284 path to run directory (within the campaign directory) 285 """ 286 287 def __init__(self, name=None, easyvvuq_version=None, 288 campaign_dir_prefix=None, campaign_dir=None, 289 runs_dir=None, local=False): 290 291 if name is None: 292 message = "CampaignInfo constructor must be passed a 'name'." 293 logger.critical(message) 294 raise RuntimeError(message) 295 296 if campaign_dir is None: 297 message = "CampaignInfo constructor must be passed 'campaign_dir'" 298 logger.critical(message) 299 raise RuntimeError(message) 300 301 self.name = name 302 self.campaign_dir_prefix = campaign_dir_prefix 303 304 self.easyvvuq_version = easyvvuq_version 305 306 # TODO: think about right location for path check for remote runs 307 if local: 308 check_local_dir(campaign_dir) 309 310 self.campaign_dir = campaign_dir 311 312 if runs_dir is None: 313 runs_dir = os.path.join(campaign_dir, 'runs') 314 315 if local: 316 check_local_dir(runs_dir, 'runs') 317 318 self.runs_dir = runs_dir 319 320 @property 321 def easyvvuq_version(self): 322 return self._easyvvuq_version 323 324 @easyvvuq_version.setter 325 def easyvvuq_version(self, version_no): 326 # TODO: check validity and compatibility 327 self._easyvvuq_version = version_no 328 329 def to_dict(self, flatten=False): 330 """Convert this to a dictionary 331 332 Parameters 333 ---------- 334 flatten : bool 335 Should the return dictionary be single level (always true here). 336 337 Returns 338 ------- 339 dict 340 Dictionary representing the campaign. 341 """ 342 343 out_dict = { 344 'name': self.name, 345 'campaign_dir': self.campaign_dir, 346 'campaign_dir_prefix': self.campaign_dir_prefix, 347 'runs_dir': self.runs_dir, 348 'easyvvuq_version': self.easyvvuq_version 349 } 350 351 return out_dict
logger =
<Logger easyvvuq.data_structs (DEBUG)>
def
check_local_dir(path, dir_type='campaign'):
37def check_local_dir(path, dir_type='campaign'): 38 """ 39 Check that local path exists and if not create it. 40 41 Parameters 42 ---------- 43 path : str 44 Directory location to check. 45 dir_type : str, default='campaign' 46 Type of directory we are checking (used for user and debugging 47 information.) 48 49 Returns 50 ------- 51 52 """ 53 54 if not os.path.isdir(path): 55 56 if os.path.exists(path): 57 logger.critical(f'{path} specified as {dir_type} directory ' 58 f'for local run but is not a directory.') 59 raise IOError(f'Invalid {dir_type} directory') 60 else: 61 os.makedirs(path)
Check that local path exists and if not create it.
Parameters
- path (str): Directory location to check.
- dir_type (str, default='campaign'): Type of directory we are checking (used for user and debugging information.)
- Returns
- -------
def
check_reference(ref, run_name, ref_type='campaign'):
64def check_reference(ref, run_name, ref_type='campaign'): 65 """ 66 Validation check for a `RunInfo` reference. Checks that an integer value 67 has been passed to use as a reference to another 'table' - i.e. to a 68 specific campaign, app or sampler. 69 70 Parameters 71 ---------- 72 ref : int 73 Reference to be checked. 74 run_name : str 75 Name of run for which the check is being performed (user info/ 76 debugging). 77 ref_type : str, default='campaign' 78 Are we checking for a campaign, sampler or app (user info/ 79 debugging). 80 81 Returns 82 ------- 83 84 """ 85 86 if ref is None: 87 message = f'No {ref_type} id specified for run {run_name}' 88 logger.critical(message) 89 raise RuntimeError(message) 90 91 if not isinstance(ref, int): 92 message = (f'Invalid {ref_type} id ({ref}) specified for ' 93 f'run {run_name}') 94 logger.critical(message) 95 raise RuntimeError(message)
Validation check for a RunInfo reference. Checks that an integer value
has been passed to use as a reference to another 'table' - i.e. to a
specific campaign, app or sampler.
Parameters
- ref (int): Reference to be checked.
- run_name (str): Name of run for which the check is being performed (user info/ debugging).
- ref_type (str, default='campaign'): Are we checking for a campaign, sampler or app (user info/ debugging).
- Returns
- -------
class
RunInfo:
98class RunInfo: 99 """Handles information for individual application runs. 100 101 Parameters 102 ---------- 103 run_name : str 104 Human readable name of the run. 105 app : None or int 106 ID of the associated application. 107 params : None or dict 108 Dictionary of parameter values for this run. 109 sample: None or int 110 ID of the sampler that created the run. 111 campaign: None or int 112 ID of the associated campaign. 113 114 Attributes 115 ---------- 116 campaign : int 117 ID of the associated campaign. 118 sample : int 119 ID of the sampler that created the run. 120 app : int 121 ID of the associated application. 122 run_name : str 123 Human readable name of the run. 124 status : enum(Status) 125 """ 126 127 def __init__( 128 self, 129 run_name=None, 130 run_dir=None, 131 app=None, 132 params=None, 133 sample=None, 134 campaign=None, 135 status=constants.Status.NEW): 136 137 self.campaign = campaign 138 self.sample = sample 139 self.app = app 140 self.run_name = run_name 141 self.run_dir = run_dir 142 143 if not params: 144 message = f'No run configuration specified for run {run_name}' 145 raise RuntimeError(message) 146 147 self.params = params 148 self.status = status 149 150 self.iteration = 0 151 152 def to_dict(self, flatten=False): 153 """Convert to a dictionary (optionally flatten to single level) 154 155 Parameters 156 ---------- 157 flatten : bool 158 Should the return dictionary be single level (i.e. should `params` 159 or other dictionary variables be serialized). 160 161 Returns 162 ------- 163 dict 164 Dictionary representing the run - if flattened then params are 165 returned as a JSON format sting. 166 """ 167 168 def convert_nonserializable(obj): 169 if isinstance(obj, numpy.int64): 170 return int(obj) 171 raise TypeError('Unknown type:', type(obj)) 172 173 if flatten: 174 175 out_dict = { 176 'run_name': self.run_name, 177 'run_dir': self.run_dir, 178 'params': json.dumps(self.params, default=convert_nonserializable), 179 'status': constants.Status(self.status), 180 'campaign': self.campaign, 181 'sampler': self.sample, 182 'app': self.app, 183 'iteration': self.iteration, 184 } 185 186 else: 187 188 out_dict = { 189 'run_name': self.run_name, 190 'run_dir': self.run_dir, 191 'params': self.params, 192 'status': constants.Status(self.status), 193 'campaign': self.campaign, 194 'sampler': self.sample, 195 'app': self.app, 196 'iteration': self.iteration, 197 } 198 199 return out_dict
Handles information for individual application runs.
Parameters
- run_name (str): Human readable name of the run.
- app (None or int): ID of the associated application.
- params (None or dict): Dictionary of parameter values for this run.
- sample (None or int): ID of the sampler that created the run.
- campaign (None or int): ID of the associated campaign.
Attributes
- campaign (int): ID of the associated campaign.
- sample (int): ID of the sampler that created the run.
- app (int): ID of the associated application.
- run_name (str): Human readable name of the run.
- status (enum(Status)):
RunInfo( run_name=None, run_dir=None, app=None, params=None, sample=None, campaign=None, status=<Status.NEW: 1>)
127 def __init__( 128 self, 129 run_name=None, 130 run_dir=None, 131 app=None, 132 params=None, 133 sample=None, 134 campaign=None, 135 status=constants.Status.NEW): 136 137 self.campaign = campaign 138 self.sample = sample 139 self.app = app 140 self.run_name = run_name 141 self.run_dir = run_dir 142 143 if not params: 144 message = f'No run configuration specified for run {run_name}' 145 raise RuntimeError(message) 146 147 self.params = params 148 self.status = status 149 150 self.iteration = 0
def
to_dict(self, flatten=False):
152 def to_dict(self, flatten=False): 153 """Convert to a dictionary (optionally flatten to single level) 154 155 Parameters 156 ---------- 157 flatten : bool 158 Should the return dictionary be single level (i.e. should `params` 159 or other dictionary variables be serialized). 160 161 Returns 162 ------- 163 dict 164 Dictionary representing the run - if flattened then params are 165 returned as a JSON format sting. 166 """ 167 168 def convert_nonserializable(obj): 169 if isinstance(obj, numpy.int64): 170 return int(obj) 171 raise TypeError('Unknown type:', type(obj)) 172 173 if flatten: 174 175 out_dict = { 176 'run_name': self.run_name, 177 'run_dir': self.run_dir, 178 'params': json.dumps(self.params, default=convert_nonserializable), 179 'status': constants.Status(self.status), 180 'campaign': self.campaign, 181 'sampler': self.sample, 182 'app': self.app, 183 'iteration': self.iteration, 184 } 185 186 else: 187 188 out_dict = { 189 'run_name': self.run_name, 190 'run_dir': self.run_dir, 191 'params': self.params, 192 'status': constants.Status(self.status), 193 'campaign': self.campaign, 194 'sampler': self.sample, 195 'app': self.app, 196 'iteration': self.iteration, 197 } 198 199 return out_dict
Convert to a dictionary (optionally flatten to single level)
Parameters
- flatten (bool):
Should the return dictionary be single level (i.e. should
paramsor other dictionary variables be serialized).
Returns
- dict: Dictionary representing the run - if flattened then params are returned as a JSON format sting.
class
AppInfo:
202class AppInfo: 203 """Handles information for particular application. 204 205 Attributes 206 ---------- 207 name : str or None 208 Human readable application name. 209 paramsspec : ParamsSpecification or None 210 Description of possible parameter values. 211 """ 212 213 def __init__( 214 self, 215 name=None, 216 paramsspec=None, 217 actions=None): 218 219 self.name = name 220 self.paramsspec = paramsspec 221 self.actions = actions 222 223 def to_dict(self, flatten=False): 224 """Convert to a dictionary (optionally flatten to single level) 225 226 Parameters 227 ---------- 228 flatten : bool 229 Should the return dictionary be single level (i.e. should `paramsspec` 230 be serialized). 231 232 Returns 233 ------- 234 dict 235 Dictionary representing the application- if flattened then `paramsspec` 236 is returned as a JSON format sting. 237 """ 238 239 if flatten: 240 241 out_dict = self.to_dict() 242 243 out_dict['params'] = self.paramsspec.serialize() 244 else: 245 246 out_dict = { 247 'name': self.name, 248 'params': self.paramsspec, 249 'actions': easyvvuq_serialize(self.actions), 250 } 251 252 return out_dict
Handles information for particular application.
Attributes
- name (str or None): Human readable application name.
- paramsspec (ParamsSpecification or None): Description of possible parameter values.
def
to_dict(self, flatten=False):
223 def to_dict(self, flatten=False): 224 """Convert to a dictionary (optionally flatten to single level) 225 226 Parameters 227 ---------- 228 flatten : bool 229 Should the return dictionary be single level (i.e. should `paramsspec` 230 be serialized). 231 232 Returns 233 ------- 234 dict 235 Dictionary representing the application- if flattened then `paramsspec` 236 is returned as a JSON format sting. 237 """ 238 239 if flatten: 240 241 out_dict = self.to_dict() 242 243 out_dict['params'] = self.paramsspec.serialize() 244 else: 245 246 out_dict = { 247 'name': self.name, 248 'params': self.paramsspec, 249 'actions': easyvvuq_serialize(self.actions), 250 } 251 252 return out_dict
Convert to a dictionary (optionally flatten to single level)
Parameters
- flatten (bool):
Should the return dictionary be single level (i.e. should
paramsspecbe serialized).
Returns
- dict: Dictionary representing the application- if flattened then
paramsspecis returned as a JSON format sting.
class
CampaignInfo:
255class CampaignInfo: 256 """Handles information on Campaign. 257 258 Parameters 259 ---------- 260 name : str or None 261 Human readable campaign name. 262 easyvvuq_version : str or None 263 Version of EasyVVUQ used to create the campaign. 264 campaign_dir_prefix : str or None 265 Prefix test for campaign directory. 266 campaign_dir : str or None, 267 Path to the campaign directory. 268 runs_dir : str or None 269 path to run directory (within the campaign directory) 270 local : bool, default=False 271 Is this campaign designed to be created and executed on the same 272 machine? 273 274 Attributes 275 ---------- 276 name : str or None 277 Human readable campaign name. 278 easyvvuq_version : str or None 279 Version of EasyVVUQ used to create the campaign. 280 campaign_dir_prefix : str or None 281 Prefix test for campaign directory. 282 campaign_dir : str or None, 283 Path to the campaign directory. 284 runs_dir : str or None 285 path to run directory (within the campaign directory) 286 """ 287 288 def __init__(self, name=None, easyvvuq_version=None, 289 campaign_dir_prefix=None, campaign_dir=None, 290 runs_dir=None, local=False): 291 292 if name is None: 293 message = "CampaignInfo constructor must be passed a 'name'." 294 logger.critical(message) 295 raise RuntimeError(message) 296 297 if campaign_dir is None: 298 message = "CampaignInfo constructor must be passed 'campaign_dir'" 299 logger.critical(message) 300 raise RuntimeError(message) 301 302 self.name = name 303 self.campaign_dir_prefix = campaign_dir_prefix 304 305 self.easyvvuq_version = easyvvuq_version 306 307 # TODO: think about right location for path check for remote runs 308 if local: 309 check_local_dir(campaign_dir) 310 311 self.campaign_dir = campaign_dir 312 313 if runs_dir is None: 314 runs_dir = os.path.join(campaign_dir, 'runs') 315 316 if local: 317 check_local_dir(runs_dir, 'runs') 318 319 self.runs_dir = runs_dir 320 321 @property 322 def easyvvuq_version(self): 323 return self._easyvvuq_version 324 325 @easyvvuq_version.setter 326 def easyvvuq_version(self, version_no): 327 # TODO: check validity and compatibility 328 self._easyvvuq_version = version_no 329 330 def to_dict(self, flatten=False): 331 """Convert this to a dictionary 332 333 Parameters 334 ---------- 335 flatten : bool 336 Should the return dictionary be single level (always true here). 337 338 Returns 339 ------- 340 dict 341 Dictionary representing the campaign. 342 """ 343 344 out_dict = { 345 'name': self.name, 346 'campaign_dir': self.campaign_dir, 347 'campaign_dir_prefix': self.campaign_dir_prefix, 348 'runs_dir': self.runs_dir, 349 'easyvvuq_version': self.easyvvuq_version 350 } 351 352 return out_dict
Handles information on Campaign.
Parameters
- name (str or None): Human readable campaign name.
- easyvvuq_version (str or None): Version of EasyVVUQ used to create the campaign.
- campaign_dir_prefix (str or None): Prefix test for campaign directory.
- campaign_dir (str or None,): Path to the campaign directory.
- runs_dir (str or None): path to run directory (within the campaign directory)
- local (bool, default=False): Is this campaign designed to be created and executed on the same machine?
Attributes
- name (str or None): Human readable campaign name.
- easyvvuq_version (str or None): Version of EasyVVUQ used to create the campaign.
- campaign_dir_prefix (str or None): Prefix test for campaign directory.
- campaign_dir (str or None,): Path to the campaign directory.
- runs_dir (str or None): path to run directory (within the campaign directory)
CampaignInfo( name=None, easyvvuq_version=None, campaign_dir_prefix=None, campaign_dir=None, runs_dir=None, local=False)
288 def __init__(self, name=None, easyvvuq_version=None, 289 campaign_dir_prefix=None, campaign_dir=None, 290 runs_dir=None, local=False): 291 292 if name is None: 293 message = "CampaignInfo constructor must be passed a 'name'." 294 logger.critical(message) 295 raise RuntimeError(message) 296 297 if campaign_dir is None: 298 message = "CampaignInfo constructor must be passed 'campaign_dir'" 299 logger.critical(message) 300 raise RuntimeError(message) 301 302 self.name = name 303 self.campaign_dir_prefix = campaign_dir_prefix 304 305 self.easyvvuq_version = easyvvuq_version 306 307 # TODO: think about right location for path check for remote runs 308 if local: 309 check_local_dir(campaign_dir) 310 311 self.campaign_dir = campaign_dir 312 313 if runs_dir is None: 314 runs_dir = os.path.join(campaign_dir, 'runs') 315 316 if local: 317 check_local_dir(runs_dir, 'runs') 318 319 self.runs_dir = runs_dir
def
to_dict(self, flatten=False):
330 def to_dict(self, flatten=False): 331 """Convert this to a dictionary 332 333 Parameters 334 ---------- 335 flatten : bool 336 Should the return dictionary be single level (always true here). 337 338 Returns 339 ------- 340 dict 341 Dictionary representing the campaign. 342 """ 343 344 out_dict = { 345 'name': self.name, 346 'campaign_dir': self.campaign_dir, 347 'campaign_dir_prefix': self.campaign_dir_prefix, 348 'runs_dir': self.runs_dir, 349 'easyvvuq_version': self.easyvvuq_version 350 } 351 352 return out_dict
Convert this to a dictionary
Parameters
- flatten (bool): Should the return dictionary be single level (always true here).
Returns
- dict: Dictionary representing the campaign.