Source code for mtpy.modeling.modem.control_inv

"""
==================
ModEM
==================

# Generate files for ModEM

# revised by JP 2017
# revised by AK 2017 to bring across functionality from ak branch
# revised by OA 2024 to update docs

"""

# =============================================================================
# Imports
# =============================================================================
from pathlib import Path

from mtpy.utils import exceptions as mtex

# =============================================================================


[docs] class ControlInv(object): """Reads and writes control files for ModEM to control how the inversion starts and how it is run. ==================== ====================================================== Attributes Description ==================== ====================================================== output_fn Model and data output file name "prefix phrase", i.e. written to the front of ModEM output file names before the iteration number and file extension. str, *default* is 'MODULAR_NLCG' lambda_initial Initial damping factor lambda. int, *default* is 10 lambda_step To update lambda, divide by this value. int, *default* is 10 model_search_step Initial search step in model units. int, *default* is 1 rms_reset_search Restart when rms diff is less than this value. float, *default* is 0.002 rms_target Exit search when rms is less than this value. float, *default* is 1.05 lambda_exit Exit when lambda is less than this value. float, *default* is 0.0001 max_iterations Maximum number of iterations. int, *default* is 100 save_path Path at which to save the control file. PosixPath, *default* is current working directory fn_basename Name of the control file. str, *default* is 'control.inv' """ def __init__(self, **kwargs): self.output_fn = "MODULAR_NLCG" self.lambda_initial = 10 self.lambda_step = 10 self.model_search_step = 1 self.rms_reset_search = 2.0e-3 self.rms_target = 1.05 self.lambda_exit = 1.0e-4 self.max_iterations = 100 self.save_path = Path().cwd() self.fn_basename = "control.inv" self._control_keys = [ "Model and data output file name", "Initial damping factor lambda", "To update lambda divide by", "Initial search step in model units", "Restart when rms diff is less than", "Exit search when rms is less than", "Exit when lambda is less than", "Maximum number of iterations", ] self._control_dict = dict( [ (key, value) for key, value in zip( self._control_keys, [ self.output_fn, self.lambda_initial, self.lambda_step, self.model_search_step, self.rms_reset_search, self.rms_target, self.lambda_exit, self.max_iterations, ], ) ] ) self._string_fmt_dict = dict( [ (key, value) for key, value in zip( self._control_keys, [ "<", "<.1f", "<.1f", "<.1f", "<.1e", "<.2f", "<.1e", "<.0f", ], ) ] ) for key, value in kwargs.items(): setattr(self, key, value) @property def control_fn(self): """Control fn.""" return self.save_path.joinpath(self.fn_basename) @control_fn.setter def control_fn(self, value): """Control fn.""" if value is not None: value = Path(value) self.save_path = value.parent self.fn_basename = value.name
[docs] def write_control_file(self, control_fn=None, save_path=None, fn_basename=None): """Write control file. Arguments:: **control_fn** : string full path to save control file to *default* is save_path/fn_basename **save_path** : string directory path to save control file to *default* is cwd **fn_basename** : string basename of control file *default* is control.inv """ if control_fn is not None: self.control_fn = control_fn if save_path is not None: self.save_path = Path(save_path) if fn_basename is not None: self.fn_basename = fn_basename self._control_dict = dict( [ (key, value) for key, value in zip( self._control_keys, [ self.output_fn, self.lambda_initial, self.lambda_step, self.model_search_step, self.rms_reset_search, self.rms_target, self.lambda_exit, self.max_iterations, ], ) ] ) clines = [] for key in self._control_keys: value = self._control_dict[key] str_fmt = self._string_fmt_dict[key] clines.append("{0:<35}: {1:{2}}\n".format(key, value, str_fmt)) with open(self.control_fn, "w") as cfid: cfid.writelines(clines) print("Wrote ModEM control file to {0}".format(self.control_fn))
[docs] def read_control_file(self, control_fn=None): """Read in a control file.""" if control_fn is not None: self.control_fn = control_fn if self.control_fn is None: raise mtex.MTpyError_file_handling( "control_fn is None, input " "control file" ) if not self.control_fn.is_file(): raise mtex.MTpyError_file_handling( "Could not find {0}".format(self.control_fn) ) with open(self.control_fn, "r") as cfid: clines = cfid.readlines() for cline in clines: clist = cline.strip().split(":") if len(clist) == 2: try: self._control_dict[clist[0].strip()] = float(clist[1]) except ValueError: self._control_dict[clist[0].strip()] = clist[1] # set attributes attr_list = [ "output_fn", "lambda_initial", "lambda_step", "model_search_step", "rms_reset_search", "rms_target", "lambda_exit", "max_iterations", ] for key, kattr in zip(self._control_keys, attr_list): setattr(self, kattr, self._control_dict[key])