Source code for ship.fmp.ief

"""

 Summary:
    Ief file data holder.
    
    Contains the functionality for loading ISIS .ief files from disk.

 Author:  
     Duncan Runnacles

  Created:  
     01 Apr 2016

 Copyright:  
     Duncan Runnacles 2016

 TODO:

 Updates:

"""


import os

from ship.utils import utilfunctions as uf
from ship.utils import filetools as ft

import logging
logger = logging.getLogger(__name__)
"""logging references with a __name__ set to this module."""


[docs]class IefDataTypes(object): """Enum for the different data types within the Ief class. Use these for easy access of the Ief class. """ HEADER, DETAILS, IED_DATA, SNAPSHOTS, DESCRIPTION = range(5)
[docs]class Ief(object): """Contains the details in the in the IEF file. Class data and a methods for accessing and upating the .ief file. """ def __init__(self, path_holder, header, details, snapshots = None, ied_data = None, description = None): """Constructor. Args: path_holder (PathHolder): Object containing the file path to this ief file. header: The [Event header] section of th ief file. It contains data like the title and main filepaths. details: The [Event Details] section of the ief file. It contains almost all the other data in the ief file, including all the flags for the run. snapshots: List containing a dictionary in each element that has the snapshot time and filepath. ied_data: List containing a dictionary in each element that contains the title and file path for every ied file referenced in the ief file. description: List containing the line of the description section of the file. """ self.event_header = header self.event_details = details self.snapshots = snapshots self.ied_data = ied_data self.description = description self.path_holder = path_holder
[docs] def getFilePaths(self): """Returns all the file paths that occur in the ief file. Most paths are extracted from the head and details data, when they exist, and are added to paths_dict. If any ied data or snapshot data exists it will be added as a list to the dictionary. If a particular path is not found the value will be set to None, unless, it's ied or snapshot data in which case it will be an empty list. Dict keys are: Datafile, Results, InitialConditions, 2DFile, ied, and snapshots. Returns: dict - containing all of the path data stored by this object. """ paths_dict = {} try: paths_dict['Datafile'] = self._findVarInDictionary(self.event_header, 'Datafile') except: paths_dict['Datafile'] = None try: paths_dict['Results'] = self._findVarInDictionary(self.event_header, 'Results') except: paths_dict['Results'] = None try: paths_dict['InitialConditions'] = self._findVarInDictionary(self.event_details, 'InitialConditions') except: paths_dict['InitialConditions'] = None try: paths_dict['2DFile'] = self._findVarInDictionary(self.event_details, '2DFile') except: paths_dict['2DFile'] = None if not self.ied_data is None and not self.ied_data == []: ied_paths = [ied['file'] for ied in self.ied_data] paths_dict['ieds'] = ied_paths else: paths_dict['ieds'] = [] if not self.snapshots is None and not self.snapshots == []: snapshot_paths = [snap['file'] for snap in self.snapshots] paths_dict['snapshots'] = snapshot_paths else: paths_dict['snapshots'] = [] return paths_dict
[docs] def getValue(self, key): """Get a value from one of the variables dictionaries. All single variables (i.e. not lists like ied data) are stored in two main dictionaries. This method will return the value associated with the given key from whichever dictionary it is stored in. Args: key(str): dict key for value. For a list of available keys use the getAvailableKeys method. Return: string: value referenced by the given key, in the ief file. Raises: KeyError: if the given key does not exist. """ if key in self.event_header.keys(): return self.event_header[key] elif key in self.event_details.keys(): return self.event_details[key]
[docs] def getIedData(self): """Get all of the ied data stored in this object. There can be multiple ied files referenced by an ief. This will return a dictionary containing all of them. If no ied files are included in the ief file the returned list will be empty. Returns: dict - containing {ied_name: ied_path} for all ied files referenced. """ if self.ied_data == None: return [] else: return self.ied_data
[docs] def getSnapshots(self): """Get all of the snapshot data stored in this object. There can be multiple snapshot files referenced by an ief. This will return a dictionary containing all of them. If no snapshots are included in the ief file the returned list will be empty. Returns: dict - containing {snapshot_time: snapshot_path} for all snapshot files referenced. """ if self.snapshots == None: return [] else: self.snapshots
[docs] def getDescription(self): """Returns the description component of the ief.""" return self.description
[docs] def setValue(self, key, value): """Set the value of one of dictionary entries in the ief. Args: key(str): The key of the value to update. value(str(: the value to update. Raises: KeyError: if given key is not recongised. Warning: Currently no checks are made on the validity of the the key given this is because it may be a legal key, but not yet exist in the dictionary. To fix this a list of all valid keys should be created and checked here before setting the value. These are the keys used in the ief file. """ headlist = ['Title', 'Path', 'Datafile', 'Results'] if key in headlist: self.event_header[key] = value else: self.event_details[key] = value
[docs] def addIedFile(self, ied_path, name=''): """Add a new ied file. Args: ied_path(str): path to an ied file. name=''(str): name for the ied file. """ if self.ied_data is None: self.ied_data = [] self.ied_data.append({'name': name, 'file': ied_path})
[docs] def addSnapshot(self, snapshot_path, time): """Add a new snapshot. Args: snapshot_path(str): the path for the snapshot. time(float): the time to assign to the snapshot. """ if self.snapshots is None: self.snapshots = [] if not uf.isNumeric(time): raise ValueError ('time is not a numeric value') self.snapshots.append({'time': time, 'file': snapshot_path})
def _findVarInDictionary(self, the_dict, key): """Returns the variable in a dictionary. Tests to see if a variables exists under the given key in the given dictionary. If it does it will return it. Args: the_dict (Dict): Dictionary in which to check the keys existence. key (str): Key to look for in the dictionary. Returns: The requested variable if it exists or False if not. """ try: variable = the_dict[key] except KeyError: logger.debug('No ' + key + ' key found in ief') return False return variable
[docs] def getPrintableContents(self): """Return the contents of the file for printing. Formats the contents of this Ief instance ready to be written back to file. Returns: List of the formatted lines for printing to file. TODO: This function is a bit long and messy at the moment. Could do with a good refactoring. """ contents = [] # Add the header data in a specific order headlist = ['Title', 'Path', 'Datafile', 'Results'] contents.append('[ISIS Event Header]') for h in headlist: var = self._findVarInDictionary(self.event_header, h) if not var == False: contents.append(h + '=' + var) # Add the top of the event list event_start = ['RunType', 'InitialConditions', 'Start', 'Finish', 'Timestep', 'SaveInterval'] contents.append('[ISIS Event Details]') for s in event_start: var = self._findVarInDictionary(self.event_details, s) if not var == False: contents.append(s + '=' + var) # Add snapshot stuff if not self.snapshots == None: for s in self.snapshots: contents.append('SnapshotTime=' + s['time']) contents.append('SnapshotFile=' + s['file']) # Add ied stuff if not self.ied_data == None: for d in self.ied_data: contents.append(';' + d['name']) contents.append('EventData=' + d['file']) # Now throw in everything else for key, value in self.event_details.items(): if not key in event_start: contents.append(key + '=' + value) # Finally, if there's a description add it on. if not self.description == None and not len(self.description) < 1 \ and not self.description[0] == '': contents.append('[Description]') for i, d in enumerate(self.description): contents.append(d) return contents
[docs] def write(self, filepath=None, overwrite=False): """Write the contents of this file to disk. Writes out to file in the format required for reading by ISIS/FMP. Note: If a filepath is not provided and the settings in this objects PathHolder class have not been updated you will write over the file that was loaded. Args: filepath=None(str): if a filename is provided it the file will be written to that location. If not, the current settings in this object path_holder object will be used. overwrite=False(bool): if the file already exists it will raise an IOError. Raises: IOError - If unable to write to file. """ if filepath is None: filepath = self.path_holder.absolutePath() if not overwrite and os.path.exists(filepath): raise IOError('filepath %s already exists. Set overwrite=True to ignore this warning.' % filepath) contents = self.getPrintableContents() ft.writeFile(contents, filepath)