3636from LoopStructural .utils .helper import (all_heading , gradient_vec_names ,
3737 strike_dip_vector )
3838
39- from LoopStructural .utils import getLogger
39+ from LoopStructural .utils import getLogger , log_to_file
4040logger = getLogger (__name__ )
4141if not surfe :
4242 logger .warning ("Cannot import Surfe" )
@@ -86,7 +86,7 @@ class GeologicalModel:
8686
8787 """
8888 def __init__ (self , origin , maximum , rescale = True , nsteps = (40 , 40 , 40 ),
89- reuse_supports = False ):
89+ reuse_supports = False , logfile = None , loglevel = 'info' ):
9090 """
9191 Parameters
9292 ----------
@@ -120,6 +120,11 @@ def __init__(self, origin, maximum, rescale=True, nsteps=(40, 40, 40),
120120
121121
122122 """
123+ if logfile :
124+ self .logfile = logfile
125+ log_to_file (logfile ,loglevel )
126+
127+ logger .info ('Initialising geological model' )
123128 self .features = []
124129 self .feature_name_index = {}
125130 self .data = None
@@ -128,19 +133,23 @@ def __init__(self, origin, maximum, rescale=True, nsteps=(40, 40, 40),
128133 # we want to rescale the model area so that the maximum length is
129134 # 1
130135 self .origin = np .array (origin ).astype (float )
136+ logger .info ('Model origin: {} {} {}' .format (self .origin [0 ],self .origin [1 ],self .origin [2 ]))
131137
132138 self .maximum = np .array (maximum ).astype (float )
139+ logger .info ('Model maximum: {} {} {}' .format (self .maximum [0 ],self .maximum [1 ],self .maximum [2 ]))
133140 lengths = self .maximum - self .origin
134141 self .scale_factor = 1.
135142 self .bounding_box = np .zeros ((2 , 3 ))
136143 self .bounding_box [1 , :] = self .maximum - self .origin
137144 self .bounding_box [1 , :] = self .maximum - self .origin
138145 if rescale :
139146 self .scale_factor = np .max (lengths )
147+ logger .info ('Rescaling model using scale factor {}' .format (self .scale_factor ))
140148
141149 self .bounding_box /= self .scale_factor
142150 self .support = {}
143151 self .reuse_supports = reuse_supports
152+ logger .info ('Reusing interpolation supports: {}' .format (self .reuse_supports ))
144153 self .stratigraphic_column = None
145154 self .parameters = {'features' : [], 'model' : {'bounding_box' : self .origin .tolist () + self .maximum .tolist (),
146155 'rescale' : rescale ,
@@ -167,6 +176,7 @@ def from_map2loop_directory(cls, m2l_directory,**kwargs):
167176 the created geological model and a dictionary of the map2loop data
168177 """
169178 from LoopStructural .utils import build_model , process_map2loop
179+ logger .info ('LoopStructural model initialised from m2l directory: {}' .format (m2l_directory ))
170180 m2lflags = kwargs .pop ('m2lflags' ,{})
171181 m2l_data = process_map2loop (m2l_directory ,m2lflags )
172182 return build_model (m2l_data ,** kwargs ), m2l_data
@@ -192,11 +202,12 @@ def from_file(cls, file):
192202 return None
193203 model = pickle .load (open (file ,'rb' ))
194204 if type (model ) == GeologicalModel :
205+ logger .info ('GeologicalModel initialised from file' )
195206 return model
196207 else :
197208 logger .error ('{} does not contain a geological model' .format (file ))
198209 return None
199-
210+
200211 def __getitem__ (self , feature_name ):
201212 """Accessor for feature in features using feature_name_index
202213
@@ -227,6 +238,7 @@ def to_file(self, file):
227238 "pip install dill" )
228239 return
229240 try :
241+ logger .info ('Writing GeologicalModel to: {}' .format (file ))
230242 pickle .dump (self ,open (file ,'wb' ))
231243 except pickle .PicklingError :
232244 logger .error ('Error saving file' )
@@ -285,7 +297,7 @@ def set_model_data(self, data):
285297 data = pd .read_csv (data )
286298 except :
287299 logger .error ("Could not load pandas data frame from data" )
288-
300+ logger . info ( 'Adding data to GeologicalModel with {} data points' . format ( len ( data )))
289301 self .data = data .copy ()
290302 self .data ['X' ] -= self .origin [0 ]
291303 self .data ['Y' ] -= self .origin [1 ]
@@ -294,7 +306,7 @@ def set_model_data(self, data):
294306 self .data ['Y' ] /= self .scale_factor
295307 self .data ['Z' ] /= self .scale_factor
296308 if 'type' in self .data :
297- logger .warning ("'type' is being replaced with 'feature_name' \n " )
309+ logger .warning ("'type' is depreciated replace with 'feature_name' \n " )
298310 self .data .rename (columns = {'type' :'feature_name' },inplace = True )
299311 for h in all_heading ():
300312 if h not in self .data :
@@ -305,6 +317,7 @@ def set_model_data(self, data):
305317 self .data [h ] = 0
306318
307319 if 'strike' in self .data and 'dip' in self .data :
320+ logger .info ('Converting strike and dip to vectors' )
308321 mask = np .all (~ np .isnan (self .data .loc [:, ['strike' , 'dip' ]]),
309322 axis = 1 )
310323 self .data .loc [mask , gradient_vec_names ()] = strike_dip_vector (
@@ -359,6 +372,7 @@ def set_stratigraphic_column(self, stratigraphic_column,cmap='tab20'):
359372 """
360373 # if the colour for a unit hasn't been specified we can just sample from
361374 # a colour map e.g. tab20
375+ logger .info ('Adding stratigraphic column to model' )
362376 random_colour = True
363377 n_units = 0
364378 for g in stratigraphic_column .keys ():
@@ -403,7 +417,7 @@ def create_from_feature_list(self, features):
403417 self .create_and_add_folded_foliation (f )
404418
405419 def get_interpolator (self , interpolatortype = 'PLI' , nelements = 1e5 ,
406- buffer = 0.2 , ** kwargs ):
420+ buffer = 0.2 , element_volume = None , ** kwargs ):
407421 """
408422 Returns an interpolator given the arguments, also constructs a
409423 support for a discrete interpolator
@@ -435,11 +449,12 @@ def get_interpolator(self, interpolatortype='PLI', nelements=1e5,
435449 bb [1 , :] += buffer # *(bb[1,:]-bb[0,:])
436450 box_vol = (bb [1 , 0 ]- bb [0 , 0 ]) * (bb [1 , 1 ]- bb [0 , 1 ]) * (bb [1 , 2 ]- bb [0 , 2 ])
437451 if interpolatortype == "PLI" :
438- nelements /= 5
439- ele_vol = box_vol / nelements
452+ if element_volume is None :
453+ nelements /= 5
454+ element_volume = box_vol / nelements
440455 # calculate the step vector of a regular cube
441456 step_vector = np .zeros (3 )
442- step_vector [:] = ele_vol ** (1. / 3. )
457+ step_vector [:] = element_volume ** (1. / 3. )
443458 # step_vector /= np.array([1,1,2])
444459 # number of steps is the length of the box / step vector
445460 nsteps = np .ceil ((bb [1 , :] - bb [0 , :]) / step_vector ).astype (int )
@@ -457,10 +472,11 @@ def get_interpolator(self, interpolatortype='PLI', nelements=1e5,
457472
458473 if interpolatortype == 'FDI' :
459474 # find the volume of one element
460- ele_vol = box_vol / nelements
475+ if element_volume is None :
476+ element_volume = box_vol / nelements
461477 # calculate the step vector of a regular cube
462478 step_vector = np .zeros (3 )
463- step_vector [:] = ele_vol ** (1. / 3. )
479+ step_vector [:] = element_volume ** (1. / 3. )
464480 # number of steps is the length of the box / step vector
465481 nsteps = np .ceil ((bb [1 , :] - bb [0 , :]) / step_vector ).astype (int )
466482 if np .any (np .less (nsteps , 3 )):
@@ -478,11 +494,12 @@ def get_interpolator(self, interpolatortype='PLI', nelements=1e5,
478494 return FDI (grid )
479495
480496 if interpolatortype == "DFI" : # "fold" in kwargs:
481- nelements /= 5
482- ele_vol = box_vol / nelements
497+ if element_volume is None :
498+ nelements /= 5
499+ element_volume = box_vol / nelements
483500 # calculate the step vector of a regular cube
484501 step_vector = np .zeros (3 )
485- step_vector [:] = ele_vol ** (1. / 3. )
502+ step_vector [:] = element_volume ** (1. / 3. )
486503 # number of steps is the length of the box / step vector
487504 nsteps = np .ceil ((bb [1 , :] - bb [0 , :]) / step_vector ).astype (int )
488505 # create a structured grid using the origin and number of steps
0 commit comments