Source code for pynoddy.history
'''Noddy history file wrapper
Created on 24/03/2014
@author: Florian Wellmann
'''
# import numpy as np
# import matplotlib.pyplot as plt
import events
[docs]class NoddyHistory():
"""Class container for Noddy history files"""
def __init__(self, history):
"""Methods to analyse and change Noddy history files
**Arguments**:
- *history* = string : Name of Noddy history file
"""
self.load_history(history)
self.determine_events()
[docs] def load_history(self, history):
"""Load Noddy history
**Arguments**:
- *history* = string : Name of Noddy history file
"""
self.history_lines = open(history, 'r').readlines()
[docs] def determine_events(self):
"""Determine events and save line numbers
.. note:: Parsing of the history file is based on a fixed Noddy output order.
If this is, for some reason (e.g. in a changed version of Noddy) not the case, then
this parsing might fail!
"""
self._raw_events = []
for i,line in enumerate(self.history_lines):
if "No of Events" in line:
self.n_events = int(line.split("=")[1])
elif "Event #" in line:
event = {}
event['type'] = line.split('=')[1].rstrip()
event['num'] = int(line[7:9])
event['line_start'] = i
self._raw_events.append(event)
# finally: if the definition for BlockOptions starts, the event definition is over
elif "BlockOptions" in line:
last_event_stop = i-2
# now: find the line ends for the single event blocks
for i,event in enumerate(self._raw_events[1:]):
self._raw_events[i]['line_end'] = event['line_start']-1
# now adjust for last event
self._raw_events[-1]['line_end'] = last_event_stop
self.events = {} # idea: create events as dictionary so that it is easier
# to swap order later!
# now create proper event objects for these events
for e in self._raw_events:
event_lines = self.history_lines[e['line_start']:e['line_end']+1]
if 'FAULT' in e['type']:
ev = events.Fault(lines = event_lines)
# set specific aspects first
elif 'STRATIGRAPHY' in e['type']:
ev = events.Stratigraphy(lines = event_lines)
else: continue
# now set shared attributes (those defined in superclass Event)
order = e['num']
self.events[order] = ev
# determine overall begin and end of the history events
self.all_events_begin = self._raw_events[0]['line_start']
self.all_events_end = self._raw_events[-1]['line_end']
[docs] def change_cube_size(self, cube_size):
"""Change the model cube size (isotropic)
**Arguments**:
- *cube_size* = float : new model cube size
"""
# create local copy of history
lines_new = self.history_lines[:]
for i,line in enumerate(self.history_lines):
if 'Geophysics Cube Size' in line:
l = line.split('=')
l_new = '%7.2f\r\n' % cube_size
line_new = l[0] + "=" + l_new
lines_new[i] = line_new
# assign changed lines back to object
self.history_lines = lines_new[:]
[docs] def write_history(self, filename):
"""Write history to new file
**Arguments**:
- *filename* = string : filename of new history file
.. hint:: Just love it how easy it is to 'write history' with Noddy ;-)
"""
# before saving: update all event properties (in case changes were made)
self.update_all_event_properties()
# First step: update history lines with events
all_event_lines = []
for event_id in sorted(self.events.keys()):
for line in self.events[event_id].event_lines:
all_event_lines.append(line)
# now substitute old with new lines:
self.history_lines[self.all_events_begin:self.all_events_end+1] = all_event_lines
f = open(filename, 'w')
for line in self.history_lines:
f.write(line)
f.close()
[docs] def swap_events(self, event_num_1, event_num_2):
"""Swap two geological events in the timeline
**Arguments**:
- *event_num_1/2* = int : number of events to be swapped ("order")
"""
# events have to be copied, otherwise only a reference is passed!
event_tmp = self.events[event_num_1]
self.events[event_num_1] = self.events[event_num_2]
self.events[event_num_2] = event_tmp
self.update_event_numbers()
[docs] def update_event_numbers(self):
"""Update event numbers in 'Event #' line in noddy history file"""
for key, event in self.events.items():
event.set_event_number(key)
[docs] def update_all_event_properties(self):
"""Update properties of all events - in case changes were made"""
for event in self.events.values():
event.update_properties()
if __name__ == '__main__':
# some testing and debugging:
import os
os.chdir(r'/Users/Florian/git/pynoddy/sandbox')
H1 = NoddyHistory("../examples/simple_two_faults.his")
H1.swap_events(2, 3)
H1.write_history("test")
H2 = NoddyHistory("test")
H2.events[2].properties['Dip'] = 12
H2.write_history("test2")