Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
107 commits
Select commit Hold shift + click to select a range
9e3a821
update to TrustRegion
Jul 9, 2025
400c79a
some design changes to TrustRegion
Jul 16, 2025
98211a0
decoupled GenOpt from Ensemble
Aug 5, 2025
6152b7f
decoupled GenOpt from Ensemble
Aug 5, 2025
544682a
Merge branch 'Python-Ensemble-Toolbox:main' into main
MathiasMNilsen Aug 6, 2025
8ff8d5f
Cleaned up code duplication and renamed some stuff
Aug 7, 2025
235948d
comments
Aug 7, 2025
e9d2281
Merge branch 'main' of https://github.com/Python-Ensemble-Toolbox/PET
Aug 7, 2025
2543ab6
Merge branch 'Python-Ensemble-Toolbox:main' into main
MathiasMNilsen Aug 8, 2025
1d0988f
improved and cleaned up LineSearch
Aug 20, 2025
87122f7
fixed conflicts
Aug 20, 2025
af046a0
added Newton-CG to LineSearch
Aug 21, 2025
ab6543e
improved logging for LineSearch
Sep 1, 2025
237b80a
dummy message for github check
MathiasMNilsen Sep 3, 2025
e29c159
empty commit
MathiasMNilsen Sep 3, 2025
32abdce
udpate BFGS to skip update if negetive curvature
MathiasMNilsen Sep 3, 2025
4ae14f7
made input more elegant and cleaned up popt structure
MathiasMNilsen Sep 8, 2025
3cdd192
changed @cache to @lru_cache
MathiasMNilsen Sep 8, 2025
c8c172a
Merge branch 'Python-Ensemble-Toolbox:main' into main
MathiasMNilsen Sep 8, 2025
1061cbf
branch commit
MathiasMNilsen Sep 11, 2025
37796f4
branch commit
MathiasMNilsen Sep 11, 2025
89f5f38
re-added stuff that got deleted
MathiasMNilsen Sep 11, 2025
9589a3a
dummy commit
MathiasMNilsen Sep 11, 2025
16ac748
fixed what got lost
MathiasMNilsen Sep 11, 2025
390c26b
fixed what got lost
MathiasMNilsen Sep 11, 2025
42ad4ab
fixed confusing naming of input keys
MathiasMNilsen Sep 11, 2025
16acee2
more input stuff
MathiasMNilsen Sep 12, 2025
b10f621
added extract_maxiter to extract_tools
MathiasMNilsen Sep 12, 2025
ff64901
assertion fix
MathiasMNilsen Sep 15, 2025
b2e3b27
fixed input for sim options
MathiasMNilsen Sep 15, 2025
18f49df
Merge branch 'main' into main
rolfjl Sep 19, 2025
2b22df6
Update extract_tools.py
rolfjl Sep 19, 2025
88cd325
Merge branch 'Python-Ensemble-Toolbox:main' into main
MathiasMNilsen Sep 19, 2025
da70d84
added a general file reader
MathiasMNilsen Sep 19, 2025
b1b566f
fixed an import error
MathiasMNilsen Sep 19, 2025
0d6b687
fixed a bug
MathiasMNilsen Sep 22, 2025
c0e008e
Started to introduce ensemble matrix (and code simplification)
MathiasMNilsen Sep 23, 2025
37b843a
replaced self.state with self.enX (matrix) for EnRML and ESMDA
MathiasMNilsen Sep 24, 2025
1e1b19a
removed temp_save functions (they are not in use anymore)
MathiasMNilsen Sep 24, 2025
52e41ab
Clean up and redsign update for EnRML and ESMDA
MathiasMNilsen Nov 5, 2025
f4d2907
Remove old function from analysis_tools.py
MathiasMNilsen Nov 5, 2025
162414a
Redefines state related variables
MathiasMNilsen Nov 5, 2025
4195844
Redefine the state scaler functions.
MathiasMNilsen Nov 5, 2025
042e90a
Correct logical bug for state scalers
MathiasMNilsen Nov 5, 2025
ff151a4
Update get_state() and get_cov()
MathiasMNilsen Nov 5, 2025
3fe6b5f
Rewrite self.function to accommodate state changes
MathiasMNilsen Nov 5, 2025
450b325
Rewrite ensemble.gradient to state changes
MathiasMNilsen Nov 6, 2025
2f6521a
Rewrite ensemble.hessian
MathiasMNilsen Nov 6, 2025
78f9fb5
Add save_stateX function
MathiasMNilsen Nov 6, 2025
1d3f774
remove save_final_state function
MathiasMNilsen Nov 6, 2025
1753335
Remove vec_to_state function
MathiasMNilsen Nov 6, 2025
f8efda8
Change order of some functions in ensemble
MathiasMNilsen Nov 7, 2025
4dd5582
Remove initialization of bias variables
MathiasMNilsen Nov 7, 2025
f0a47b6
Rewrite calc_ensemble_weights to accomodate changes
MathiasMNilsen Nov 7, 2025
160da50
Remove unused bias functions
MathiasMNilsen Nov 7, 2025
a8e7b5a
Remove unused function
MathiasMNilsen Nov 7, 2025
7556c4d
Remove unused imports
MathiasMNilsen Nov 7, 2025
582228e
Update docstring
MathiasMNilsen Nov 7, 2025
0196097
Update docstring
MathiasMNilsen Nov 17, 2025
08fce6b
Update GenOpt to state changes
MathiasMNilsen Nov 19, 2025
b709fd0
Improve readability of code
MathiasMNilsen Nov 20, 2025
8eb2a5c
Improve readability
MathiasMNilsen Nov 21, 2025
e59eb02
Improve readability
MathiasMNilsen Nov 21, 2025
918b169
Improve readability of subspace_update
MathiasMNilsen Nov 25, 2025
07339f2
Rewrite ESMDA
MathiasMNilsen Nov 25, 2025
f52ca5c
Rewrite EnKF for readability
MathiasMNilsen Nov 25, 2025
78edbf3
Use truncSVD function
MathiasMNilsen Nov 25, 2025
b077009
Rewrite local analysis for region params
MathiasMNilsen Dec 8, 2025
d13d0f2
Update the progressbar
MathiasMNilsen Dec 9, 2025
ded9473
Change style of logger
MathiasMNilsen Dec 9, 2025
0b4b9fd
Add alternative way of defining initial controls for optimization
MathiasMNilsen Dec 9, 2025
ada4235
Update style of progressbar
MathiasMNilsen Dec 9, 2025
afcecd8
Update logger for ESMDA and ENRML
MathiasMNilsen Dec 12, 2025
b864d19
Add savefolder option to Assimilation
MathiasMNilsen Dec 12, 2025
cf63b56
Fix logging bug
MathiasMNilsen Dec 12, 2025
00673cd
Fix logging bug
MathiasMNilsen Dec 12, 2025
9b4bfbb
Add logger.py
MathiasMNilsen Jan 5, 2026
dd99533
Use PetLogger
MathiasMNilsen Jan 5, 2026
3f9abf1
Update string
MathiasMNilsen Jan 5, 2026
9078c9f
Add convergence message
MathiasMNilsen Jan 6, 2026
a83a0e2
Remove lines
MathiasMNilsen Jan 8, 2026
91cf5d1
Add cosmetic changes to PetLogger
MathiasMNilsen Jan 12, 2026
8a263fd
Update dosctring for PetLogger
MathiasMNilsen Jan 12, 2026
f34a809
Improve logging for LineSearch
MathiasMNilsen Jan 12, 2026
aaa9786
Update docstring for Petlogger
MathiasMNilsen Jan 13, 2026
f1f7396
Update PetLogger
MathiasMNilsen Jan 13, 2026
3d021a7
Update calc_ml_prediction
MathiasMNilsen Jan 13, 2026
a7e1af2
Rewrite multilevel code
MathiasMNilsen Jan 13, 2026
18fc381
Fix multilevel bugs
MathiasMNilsen Jan 13, 2026
5083684
Fix bugs
MathiasMNilsen Jan 14, 2026
cb8132f
Merge branch 'Python-Ensemble-Toolbox:main' into main
MathiasMNilsen Jan 14, 2026
f88fe0e
Comment out log.info
MathiasMNilsen Jan 14, 2026
c8ae932
Reorganize code with ensemble-matrix
MathiasMNilsen Jan 14, 2026
c6ed492
Fix small bug
MathiasMNilsen Jan 14, 2026
fc4668c
Fix bug relating to data_mismatch for multilevel
MathiasMNilsen Jan 15, 2026
3cc09aa
Remove unused imports for multilevel
MathiasMNilsen Jan 15, 2026
5f935aa
Add progbar_settings to multilevel
MathiasMNilsen Jan 15, 2026
2950568
Update popt/update_schemes/linesearch.py
KriFos1 Jan 15, 2026
542c51e
Update pipt/update_schemes/update_methods_ns/hybrid_update.py
KriFos1 Jan 15, 2026
559c9ba
Update pipt/misc_tools/extract_tools.py
KriFos1 Jan 15, 2026
af200ca
Update pipt/loop/ensemble.py
KriFos1 Jan 15, 2026
16ed42e
Update optimize.py
rolfjl Jan 15, 2026
f8f1a74
Fix bugs
MathiasMNilsen Jan 15, 2026
e3cc78e
Merge branch 'main' of github.com:MathiasMNilsen/PET
MathiasMNilsen Jan 15, 2026
b52f83f
Fix bugs
MathiasMNilsen Jan 16, 2026
602bb6b
Update linesearch.py
MathiasMNilsen Jan 16, 2026
fc8bd60
Update ensemble_tools.py
MathiasMNilsen Jan 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
621 changes: 240 additions & 381 deletions ensemble/ensemble.py

Large diffs are not rendered by default.

99 changes: 99 additions & 0 deletions ensemble/logger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import logging

class PetLogger:
'''
A custom logger that logs messages and key-value pairs in a formatted table.

Parameters:
filename (str): The name of the log file. Defaults to 'PET.log'.
'''
def __init__(self, filename=None):

self.filename = filename if filename else 'PET.log'
self.ns = 12 # Number of spaces for table formatting

# Configurate logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s : %(message)s',
datefmt='%Y-%m-%d│%H:%M:%S',
handlers=[
logging.FileHandler(self.filename, mode='w'),
logging.StreamHandler()
]
)
self._logger = logging.getLogger(__name__)


def __call__(self, *args, **kwargs):
'''
Log messages or key-value pairs in a formatted table.

Parameters:
*args: Positional arguments to log as a single message.
**kwargs: Keyword arguments to log in a formatted table.

Example:
>>> logger = PetLogger()
>>> logger('This is a log message.')
2024-06-01│12:00:00 : This is a log message.
>>>
>>> logger(iteration=1, fun=0.5, step_size=0.1)
2024-06-01│12:00:00 :
2024-06-01│12:00:00 : ┌────────────┬────────────┬────────────┐
2024-06-01│12:00:00 : │ iteration │ fun │ step_size │
2024-06-01│12:00:00 : ├────────────┼────────────┼────────────┤
2024-06-01│12:00:00 : │ 1 │ 5.000e-01 │ 1.000e-01 │
2024-06-01│12:00:00 : └────────────┴────────────┴────────────┘
2024-06-01│12:00:00 :
'''

if args:
# Log message from args
msg = ' ' + ' '.join(str(arg) for arg in args)
self._logger.info(msg)

if kwargs:
# Make strings for table logging
self._set_ns(**kwargs)
header = []
values = []
for key, value in kwargs.items():
header.append(f'{key:^{self.ns}}')
try:
if isinstance(value, int) or isinstance(value, str):
values.append(f'{value:^{self.ns}}')
elif '%' in key:
values.append(f'{value:^{self.ns}.1f}')
else:
values.append(f'{value:^{self.ns}.3e}')
except:
values.append(f'{"":^{self.ns}}')

# Log table
seperator = ['─' * self.ns for _ in kwargs.keys()]
self._logger.info('')
self._logger.info(' ┌' + '┬'.join(seperator) + '┐')
self._logger.info(' │' + '│'.join(header) + '│')
self._logger.info(' ├' + '┼'.join(seperator) + '┤')
self._logger.info(' │' + '│'.join(values) + '│')
self._logger.info(' └' + '┴'.join(seperator) + '┘')
self._logger.info('')

def info(self, *args, **kwargs):
self._logger.info(*args, **kwargs)

def _set_ns(self, **kwargs):
'''
Adjust the number of spaces for table formatting based on the length of keys and values.

Parameters:
**kwargs: Keyword arguments to consider for adjusting the space width.
'''
for key, value in kwargs.items():
try:
if (len(key) > self.ns) or (len(f'{value:.3e}') > self.ns):
self.ns = max(len(key), len(f'{value:.3e}')) + 2
except:
if len(key) > self.ns:
self.ns = len(key) + 2
31 changes: 22 additions & 9 deletions input_output/read_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@
import numpy as np


def read(filename: str):
''' Read configuration file. Supported formats are toml, .yaml, .pipt and .popt.'''
if filename.endswith('.pipt') or filename.endswith('.popt'):
return read_txt(filename)
elif filename.endswith('.yaml'):
return read_yaml(filename)
elif filename.endswith('.toml'):
return read_toml(filename)
else:
raise ValueError('File format not supported. Supported formats are toml, .yaml, .pipt, .popt')


def convert_txt_to_yaml(init_file):
# Read .pipt or .popt file
pr, fwd = read_txt(init_file)
Expand Down Expand Up @@ -46,30 +58,31 @@ def ndarray_constructor(loader, node):
# Add constructor to yaml with tag !ndarray
yaml.add_constructor('!ndarray', ndarray_constructor)

# Read
# Read yaml file
with open(init_file, 'rb') as fid:
y = yaml.load(fid, Loader=FullLoader)

# Check for dataassim and fwdsim
# Check for ensemble
if 'ensemble' in y.keys():
keys_en = y['ensemble']
check_mand_keywords_en(keys_en)
else:
keys_en = {}

if 'optim' in y.keys():
keys_pr = y['optim']
check_mand_keywords_opt(keys_pr)
elif 'dataassim' in y.keys():
# Check for dataassim
if 'dataassim' in y.keys():
keys_pr = y['dataassim']
check_mand_keywords_da(keys_pr)
elif 'optim' in y.keys():
keys_pr = y['optim']
check_mand_keywords_opt(keys_pr)
else:
raise KeyError
keys_pr = {}

if 'fwdsim' in y.keys():
keys_fwd = y['fwdsim']
else:
raise KeyError
keys_fwd = {}

# Organize keywords
org = Organize_input(keys_pr, keys_fwd, keys_en)
Expand Down Expand Up @@ -379,7 +392,7 @@ def check_mand_keywords_en(keys_en):

# Mandatory keywords in ENSEMBLE
assert 'ne' in keys_en, 'NE not in ENSEMBLE!'
assert 'state' in keys_en, 'STATE not in ENSEMBLE!'
assert ('state' in keys_en) or ('controls' in keys_en), 'STATE or CONTROLS not in ENSEMBLE!'
if 'importstaticvar' not in keys_en:
assert filter(list(keys_en.keys()),
'prior_*') != [], 'No PRIOR_<STATICVAR> in DATAASSIM'
Expand Down
6 changes: 3 additions & 3 deletions misc/ecl.py
Original file line number Diff line number Diff line change
Expand Up @@ -426,8 +426,8 @@ def __init__(self, root):
self.ni = grid_head[1] # pylint: disable=invalid-name
self.nj = grid_head[2] # pylint: disable=invalid-name
self.nk = grid_head[3] # pylint: disable=invalid-name
log.info("Grid dimension is %d x %d x %d",
self.ni, self.nj, self.nk)
#log.info("Grid dimension is %d x %d x %d",
# self.ni, self.nj, self.nk)

# also store a shape tuple which describes the grid cube
self.shape = (self.nk, self.nj, self.ni)
Expand Down Expand Up @@ -460,7 +460,7 @@ def __init__(self, root):
# restart properties are only saved for the active elements,
# so we can cache this number to compare
self.num_active = numpy.sum(self.actnum)
log.info("Grid has %d active cells", self.num_active)
#log.info("Grid has %d active cells", self.num_active)

def grid(self):
"""
Expand Down
Loading