ert 19.0.0rc4__py3-none-any.whl → 20.0.0b0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ert/__main__.py +94 -63
- ert/analysis/_es_update.py +11 -14
- ert/config/__init__.py +3 -2
- ert/config/_create_observation_dataframes.py +51 -375
- ert/config/_observations.py +483 -200
- ert/config/_read_summary.py +4 -5
- ert/config/ert_config.py +53 -80
- ert/config/everest_control.py +40 -39
- ert/config/everest_response.py +1 -13
- ert/config/field.py +0 -72
- ert/config/forward_model_step.py +17 -1
- ert/config/gen_data_config.py +14 -17
- ert/config/observation_config_migrations.py +821 -0
- ert/config/parameter_config.py +18 -28
- ert/config/parsing/__init__.py +0 -1
- ert/config/parsing/_parse_zonemap.py +45 -0
- ert/config/parsing/config_keywords.py +1 -1
- ert/config/parsing/config_schema.py +2 -8
- ert/config/parsing/observations_parser.py +2 -0
- ert/config/response_config.py +5 -23
- ert/config/rft_config.py +44 -19
- ert/config/summary_config.py +1 -13
- ert/config/surface_config.py +0 -57
- ert/dark_storage/compute/misfits.py +0 -42
- ert/dark_storage/endpoints/__init__.py +0 -2
- ert/dark_storage/endpoints/experiments.py +2 -5
- ert/dark_storage/json_schema/experiment.py +1 -2
- ert/field_utils/__init__.py +0 -2
- ert/field_utils/field_utils.py +1 -117
- ert/gui/ertwidgets/listeditbox.py +9 -1
- ert/gui/ertwidgets/models/ertsummary.py +20 -6
- ert/gui/ertwidgets/pathchooser.py +9 -1
- ert/gui/ertwidgets/stringbox.py +11 -3
- ert/gui/ertwidgets/textbox.py +10 -3
- ert/gui/ertwidgets/validationsupport.py +19 -1
- ert/gui/main_window.py +11 -6
- ert/gui/simulation/experiment_panel.py +1 -1
- ert/gui/simulation/run_dialog.py +11 -1
- ert/gui/tools/manage_experiments/export_dialog.py +4 -0
- ert/gui/tools/manage_experiments/manage_experiments_panel.py +1 -0
- ert/gui/tools/manage_experiments/storage_info_widget.py +5 -2
- ert/gui/tools/manage_experiments/storage_widget.py +18 -3
- ert/gui/tools/plot/data_type_proxy_model.py +1 -1
- ert/gui/tools/plot/plot_api.py +35 -27
- ert/gui/tools/plot/plot_widget.py +5 -0
- ert/gui/tools/plot/plot_window.py +4 -7
- ert/run_models/ensemble_experiment.py +1 -3
- ert/run_models/ensemble_smoother.py +1 -3
- ert/run_models/everest_run_model.py +12 -13
- ert/run_models/initial_ensemble_run_model.py +19 -22
- ert/run_models/model_factory.py +7 -7
- ert/run_models/multiple_data_assimilation.py +1 -3
- ert/sample_prior.py +12 -14
- ert/services/__init__.py +7 -3
- ert/services/_storage_main.py +59 -22
- ert/services/ert_server.py +186 -24
- ert/shared/version.py +3 -3
- ert/storage/local_ensemble.py +46 -115
- ert/storage/local_experiment.py +0 -16
- ert/utils/__init__.py +20 -0
- ert/warnings/specific_warning_handler.py +3 -2
- {ert-19.0.0rc4.dist-info → ert-20.0.0b0.dist-info}/METADATA +4 -51
- {ert-19.0.0rc4.dist-info → ert-20.0.0b0.dist-info}/RECORD +75 -80
- everest/bin/everest_script.py +5 -5
- everest/bin/kill_script.py +2 -2
- everest/bin/monitor_script.py +2 -2
- everest/bin/utils.py +4 -4
- everest/detached/everserver.py +6 -6
- everest/gui/everest_client.py +0 -6
- everest/gui/main_window.py +2 -2
- everest/util/__init__.py +1 -19
- ert/dark_storage/compute/__init__.py +0 -0
- ert/dark_storage/endpoints/compute/__init__.py +0 -0
- ert/dark_storage/endpoints/compute/misfits.py +0 -95
- ert/services/_base_service.py +0 -387
- ert/services/webviz_ert_service.py +0 -20
- ert/shared/storage/command.py +0 -38
- ert/shared/storage/extraction.py +0 -42
- {ert-19.0.0rc4.dist-info → ert-20.0.0b0.dist-info}/WHEEL +0 -0
- {ert-19.0.0rc4.dist-info → ert-20.0.0b0.dist-info}/entry_points.txt +0 -0
- {ert-19.0.0rc4.dist-info → ert-20.0.0b0.dist-info}/licenses/COPYING +0 -0
- {ert-19.0.0rc4.dist-info → ert-20.0.0b0.dist-info}/top_level.txt +0 -0
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
from datetime import datetime
|
|
3
|
-
from typing import Annotated, Any
|
|
4
|
-
from uuid import UUID
|
|
5
|
-
|
|
6
|
-
import pandas as pd
|
|
7
|
-
from dateutil.parser import parse
|
|
8
|
-
from fastapi import APIRouter, Depends, Query, status
|
|
9
|
-
from fastapi.responses import Response
|
|
10
|
-
|
|
11
|
-
from ert.dark_storage import exceptions as exc
|
|
12
|
-
from ert.dark_storage.common import get_storage
|
|
13
|
-
from ert.dark_storage.compute.misfits import calculate_signed_chi_squared_misfits
|
|
14
|
-
from ert.dark_storage.endpoints.observations import (
|
|
15
|
-
_get_observations,
|
|
16
|
-
)
|
|
17
|
-
from ert.dark_storage.endpoints.responses import data_for_response
|
|
18
|
-
from ert.storage import Storage
|
|
19
|
-
|
|
20
|
-
router = APIRouter(tags=["misfits"])
|
|
21
|
-
DEFAULT_STORAGEREADER = Depends(get_storage)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
@router.get(
|
|
25
|
-
"/compute/misfits",
|
|
26
|
-
responses={
|
|
27
|
-
status.HTTP_200_OK: {
|
|
28
|
-
"content": {"text/csv": {}},
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
)
|
|
32
|
-
async def get_response_misfits(
|
|
33
|
-
*,
|
|
34
|
-
storage: Storage = DEFAULT_STORAGEREADER,
|
|
35
|
-
ensemble_id: UUID,
|
|
36
|
-
response_name: str,
|
|
37
|
-
realization_index: int | None = None,
|
|
38
|
-
summary_misfits: bool = False,
|
|
39
|
-
filter_on: Annotated[
|
|
40
|
-
str | None, Query(description="JSON string with filters")
|
|
41
|
-
] = None,
|
|
42
|
-
) -> Response:
|
|
43
|
-
ensemble = storage.get_ensemble(ensemble_id)
|
|
44
|
-
dataframe = data_for_response(
|
|
45
|
-
ensemble,
|
|
46
|
-
response_name,
|
|
47
|
-
json.loads(filter_on) if filter_on is not None else None,
|
|
48
|
-
)
|
|
49
|
-
if realization_index is not None:
|
|
50
|
-
dataframe = pd.DataFrame(dataframe.loc[realization_index]).T
|
|
51
|
-
|
|
52
|
-
response_dict = {}
|
|
53
|
-
for index, data in dataframe.iterrows():
|
|
54
|
-
data_df = pd.DataFrame(data).T
|
|
55
|
-
response_dict[index] = data_df
|
|
56
|
-
|
|
57
|
-
experiment = ensemble.experiment
|
|
58
|
-
response_type = experiment.response_key_to_response_type[response_name]
|
|
59
|
-
obs_keys = experiment.response_key_to_observation_key[response_type].get(
|
|
60
|
-
response_name, []
|
|
61
|
-
)
|
|
62
|
-
obs = _get_observations(
|
|
63
|
-
ensemble.experiment,
|
|
64
|
-
obs_keys,
|
|
65
|
-
json.loads(filter_on) if filter_on is not None else None,
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
if not obs_keys:
|
|
69
|
-
raise ValueError(f"No observations for key {response_name}")
|
|
70
|
-
if not obs:
|
|
71
|
-
raise ValueError(f"Cant fetch observations for key {response_name}")
|
|
72
|
-
o = obs[0]
|
|
73
|
-
|
|
74
|
-
def parse_index(x: Any) -> int | datetime:
|
|
75
|
-
try:
|
|
76
|
-
return int(x)
|
|
77
|
-
except ValueError:
|
|
78
|
-
return parse(x)
|
|
79
|
-
|
|
80
|
-
observation_df = pd.DataFrame(
|
|
81
|
-
data={"values": o["values"], "errors": o["errors"]},
|
|
82
|
-
index=[parse_index(x) for x in o["x_axis"]],
|
|
83
|
-
)
|
|
84
|
-
try:
|
|
85
|
-
result_df = calculate_signed_chi_squared_misfits(
|
|
86
|
-
response_dict, observation_df, summary_misfits
|
|
87
|
-
)
|
|
88
|
-
except Exception as misfits_exc:
|
|
89
|
-
raise exc.UnprocessableError(
|
|
90
|
-
f"Unable to compute misfits: {misfits_exc}"
|
|
91
|
-
) from misfits_exc
|
|
92
|
-
return Response(
|
|
93
|
-
content=result_df.to_csv().encode(),
|
|
94
|
-
media_type="text/csv",
|
|
95
|
-
)
|
ert/services/_base_service.py
DELETED
|
@@ -1,387 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
This file contains a more generic version of "ert services", and
|
|
3
|
-
is scheduled for removal when WebvizErt is removed.
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
from __future__ import annotations
|
|
7
|
-
|
|
8
|
-
import contextlib
|
|
9
|
-
import io
|
|
10
|
-
import json
|
|
11
|
-
import os
|
|
12
|
-
import signal
|
|
13
|
-
import sys
|
|
14
|
-
import threading
|
|
15
|
-
import types
|
|
16
|
-
from collections.abc import Callable, Mapping, Sequence
|
|
17
|
-
from logging import Logger, getLogger
|
|
18
|
-
from pathlib import Path
|
|
19
|
-
from select import PIPE_BUF, select
|
|
20
|
-
from subprocess import Popen, TimeoutExpired
|
|
21
|
-
from tempfile import NamedTemporaryFile
|
|
22
|
-
from time import sleep
|
|
23
|
-
from types import FrameType
|
|
24
|
-
from typing import TYPE_CHECKING, Any, Generic, Self, TypedDict, TypeVar
|
|
25
|
-
|
|
26
|
-
if TYPE_CHECKING:
|
|
27
|
-
pass
|
|
28
|
-
|
|
29
|
-
T = TypeVar("T", bound="BaseService")
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
class ErtServerConnectionInfo(TypedDict):
|
|
33
|
-
urls: list[str]
|
|
34
|
-
authtoken: str
|
|
35
|
-
host: str
|
|
36
|
-
port: str
|
|
37
|
-
cert: str
|
|
38
|
-
auth: str
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
SERVICE_CONF_PATHS: set[str] = set()
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
class BaseServiceExit(OSError):
|
|
45
|
-
pass
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
def cleanup_service_files(signum: int, frame: FrameType | None) -> None:
|
|
49
|
-
for file_path in SERVICE_CONF_PATHS:
|
|
50
|
-
file = Path(file_path)
|
|
51
|
-
if file.exists():
|
|
52
|
-
file.unlink()
|
|
53
|
-
raise BaseServiceExit(f"Signal {signum} received.")
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if threading.current_thread() is threading.main_thread():
|
|
57
|
-
signal.signal(signal.SIGTERM, cleanup_service_files)
|
|
58
|
-
signal.signal(signal.SIGINT, cleanup_service_files)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
def local_exec_args(script_args: str | list[str]) -> list[str]:
|
|
62
|
-
"""
|
|
63
|
-
Convenience function that returns the exec_args for executing a Python
|
|
64
|
-
script in the directory of '_base_service.py'.
|
|
65
|
-
|
|
66
|
-
This is done instead of using 'python -m [module path]' due to the '-m' flag
|
|
67
|
-
adding the user's current working directory to sys.path. Executing a Python
|
|
68
|
-
script by itself will add the directory of the script rather than the
|
|
69
|
-
current working directory, thus we avoid accidentally importing user's
|
|
70
|
-
directories that just happen to have the same names as the ones we use.
|
|
71
|
-
"""
|
|
72
|
-
if isinstance(script_args, str):
|
|
73
|
-
script = script_args
|
|
74
|
-
rest: list[str] = []
|
|
75
|
-
else:
|
|
76
|
-
script = script_args[0]
|
|
77
|
-
rest = script_args[1:]
|
|
78
|
-
script = f"_{script}_main.py"
|
|
79
|
-
return [sys.executable, str(Path(__file__).parent / script), *rest]
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
class _Context(Generic[T]):
|
|
83
|
-
def __init__(self, service: T) -> None:
|
|
84
|
-
self._service = service
|
|
85
|
-
|
|
86
|
-
def __enter__(self) -> T:
|
|
87
|
-
return self._service
|
|
88
|
-
|
|
89
|
-
def __exit__(
|
|
90
|
-
self,
|
|
91
|
-
exc_type: type[BaseException] | None,
|
|
92
|
-
exc_value: BaseException | None,
|
|
93
|
-
traceback: types.TracebackType | None,
|
|
94
|
-
) -> bool:
|
|
95
|
-
self._service.shutdown()
|
|
96
|
-
return exc_type is None
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
class _Proc(threading.Thread):
|
|
100
|
-
def __init__(
|
|
101
|
-
self,
|
|
102
|
-
service_name: str,
|
|
103
|
-
exec_args: Sequence[str],
|
|
104
|
-
timeout: int,
|
|
105
|
-
on_connection_info_received: Callable[
|
|
106
|
-
[ErtServerConnectionInfo | Exception | None], None
|
|
107
|
-
],
|
|
108
|
-
project: Path,
|
|
109
|
-
) -> None:
|
|
110
|
-
super().__init__()
|
|
111
|
-
|
|
112
|
-
self._shutdown = threading.Event()
|
|
113
|
-
|
|
114
|
-
self._service_name = service_name
|
|
115
|
-
self._exec_args = exec_args
|
|
116
|
-
self._timeout = timeout
|
|
117
|
-
self._propagate_connection_info_from_childproc = on_connection_info_received
|
|
118
|
-
self._service_config_path = project / f"{self._service_name}_server.json"
|
|
119
|
-
|
|
120
|
-
fd_read, fd_write = os.pipe()
|
|
121
|
-
self._comm_pipe = os.fdopen(fd_read)
|
|
122
|
-
|
|
123
|
-
env = os.environ.copy()
|
|
124
|
-
env["ERT_COMM_FD"] = str(fd_write)
|
|
125
|
-
|
|
126
|
-
SERVICE_CONF_PATHS.add(str(self._service_config_path))
|
|
127
|
-
|
|
128
|
-
# The process is waited for in _do_shutdown()
|
|
129
|
-
self._childproc = Popen(
|
|
130
|
-
self._exec_args,
|
|
131
|
-
pass_fds=(fd_write,),
|
|
132
|
-
env=env,
|
|
133
|
-
close_fds=True,
|
|
134
|
-
)
|
|
135
|
-
os.close(fd_write)
|
|
136
|
-
|
|
137
|
-
def run(self) -> None:
|
|
138
|
-
comm = self._read_connection_info_from_process(self._childproc)
|
|
139
|
-
|
|
140
|
-
if comm is None:
|
|
141
|
-
self._propagate_connection_info_from_childproc(TimeoutError())
|
|
142
|
-
return # _read_conn_info() has already cleaned up in this case
|
|
143
|
-
|
|
144
|
-
conn_info: ErtServerConnectionInfo | Exception | None = None
|
|
145
|
-
try:
|
|
146
|
-
conn_info = json.loads(comm)
|
|
147
|
-
except json.JSONDecodeError:
|
|
148
|
-
conn_info = ServerBootFail()
|
|
149
|
-
except Exception as exc:
|
|
150
|
-
conn_info = exc
|
|
151
|
-
|
|
152
|
-
try:
|
|
153
|
-
self._propagate_connection_info_from_childproc(conn_info)
|
|
154
|
-
|
|
155
|
-
while True:
|
|
156
|
-
if self._childproc.poll() is not None:
|
|
157
|
-
break
|
|
158
|
-
if self._shutdown.wait(1):
|
|
159
|
-
self._do_shutdown()
|
|
160
|
-
break
|
|
161
|
-
|
|
162
|
-
except Exception as e:
|
|
163
|
-
print(str(e))
|
|
164
|
-
self.logger.exception(e)
|
|
165
|
-
|
|
166
|
-
finally:
|
|
167
|
-
self._ensure_connection_info_file_is_deleted()
|
|
168
|
-
|
|
169
|
-
def shutdown(self) -> int:
|
|
170
|
-
"""Shutdown the server."""
|
|
171
|
-
self._shutdown.set()
|
|
172
|
-
self.join()
|
|
173
|
-
|
|
174
|
-
return self._childproc.returncode
|
|
175
|
-
|
|
176
|
-
def _read_connection_info_from_process(self, proc: Popen[bytes]) -> str | None:
|
|
177
|
-
comm_buf = io.StringIO()
|
|
178
|
-
first_iter = True
|
|
179
|
-
while first_iter or proc.poll() is None:
|
|
180
|
-
first_iter = False
|
|
181
|
-
ready = select([self._comm_pipe], [], [], self._timeout)
|
|
182
|
-
|
|
183
|
-
# Timeout reached, exit with a failure
|
|
184
|
-
if ready == ([], [], []):
|
|
185
|
-
self._do_shutdown()
|
|
186
|
-
self._ensure_connection_info_file_is_deleted()
|
|
187
|
-
return None
|
|
188
|
-
|
|
189
|
-
x = self._comm_pipe.read(PIPE_BUF)
|
|
190
|
-
if not x: # EOF
|
|
191
|
-
break
|
|
192
|
-
comm_buf.write(x)
|
|
193
|
-
return comm_buf.getvalue()
|
|
194
|
-
|
|
195
|
-
def _do_shutdown(self) -> None:
|
|
196
|
-
if self._childproc is None:
|
|
197
|
-
return
|
|
198
|
-
try:
|
|
199
|
-
self._childproc.terminate()
|
|
200
|
-
self._childproc.wait(10) # Give it 10s to shut down cleanly..
|
|
201
|
-
except TimeoutExpired:
|
|
202
|
-
try:
|
|
203
|
-
self._childproc.kill() # ... then kick it harder...
|
|
204
|
-
self._childproc.wait(self._timeout) # ... and wait again
|
|
205
|
-
except TimeoutExpired:
|
|
206
|
-
self.logger.error(
|
|
207
|
-
f"waiting for child-process exceeded timeout {self._timeout}s"
|
|
208
|
-
)
|
|
209
|
-
|
|
210
|
-
def _ensure_connection_info_file_is_deleted(self) -> None:
|
|
211
|
-
"""
|
|
212
|
-
Ensure that the JSON connection information file is deleted
|
|
213
|
-
"""
|
|
214
|
-
with contextlib.suppress(OSError):
|
|
215
|
-
if self._service_config_path.exists():
|
|
216
|
-
self._service_config_path.unlink()
|
|
217
|
-
|
|
218
|
-
@property
|
|
219
|
-
def logger(self) -> Logger:
|
|
220
|
-
return getLogger(f"ert.shared.{self._service_name}")
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
class ServerBootFail(RuntimeError):
|
|
224
|
-
pass
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
class BaseService:
|
|
228
|
-
"""
|
|
229
|
-
BaseService provides a block-only-when-needed mechanism for starting and
|
|
230
|
-
maintaining services as subprocesses.
|
|
231
|
-
|
|
232
|
-
This is achieved by using a POSIX communication pipe, over which the service
|
|
233
|
-
can communicate that it has started. The contents of the communication is
|
|
234
|
-
also written to a file inside of the ERT storage directory.
|
|
235
|
-
|
|
236
|
-
The service itself can implement the other side of the pipe as such::
|
|
237
|
-
|
|
238
|
-
import os
|
|
239
|
-
|
|
240
|
-
# ... perform initialisation ...
|
|
241
|
-
|
|
242
|
-
# BaseService provides this environment variable with the pipe's FD
|
|
243
|
-
comm_fd = os.environ["ERT_COMM_FD"]
|
|
244
|
-
|
|
245
|
-
# Open the pipe with Python's IO classes for ease of use
|
|
246
|
-
with os.fdopen(comm_fd, "wb") as comm:
|
|
247
|
-
# Write JSON over the pipe, which will be interpreted by a subclass
|
|
248
|
-
# of BaseService on ERT's side
|
|
249
|
-
comm.write('{"some": "json"}')
|
|
250
|
-
|
|
251
|
-
# The pipe is flushed and closed here. This tells BaseService that
|
|
252
|
-
# initialisation is finished and it will try to read the JSON data.
|
|
253
|
-
"""
|
|
254
|
-
|
|
255
|
-
_instance: BaseService | None = None
|
|
256
|
-
|
|
257
|
-
def __init__(
|
|
258
|
-
self,
|
|
259
|
-
exec_args: Sequence[str] = (),
|
|
260
|
-
timeout: int = 120,
|
|
261
|
-
conn_info: ErtServerConnectionInfo | Exception | None = None,
|
|
262
|
-
project: str | None = None,
|
|
263
|
-
) -> None:
|
|
264
|
-
self._exec_args = exec_args
|
|
265
|
-
self._timeout = timeout
|
|
266
|
-
|
|
267
|
-
self._proc: _Proc | None = None
|
|
268
|
-
self._conn_info: ErtServerConnectionInfo | Exception | None = conn_info
|
|
269
|
-
self._conn_info_event = threading.Event()
|
|
270
|
-
self._project = Path(project) if project is not None else Path.cwd()
|
|
271
|
-
|
|
272
|
-
# Flag that we have connection information
|
|
273
|
-
if self._conn_info:
|
|
274
|
-
self._conn_info_event.set()
|
|
275
|
-
else:
|
|
276
|
-
self._proc = _Proc(
|
|
277
|
-
self.service_name, exec_args, timeout, self.set_conn_info, self._project
|
|
278
|
-
)
|
|
279
|
-
|
|
280
|
-
@classmethod
|
|
281
|
-
def start_server(cls, *args: Any, **kwargs: Any) -> _Context[Self]:
|
|
282
|
-
if cls._instance is not None:
|
|
283
|
-
raise RuntimeError("Server already running")
|
|
284
|
-
cls._instance = obj = cls(*args, **kwargs)
|
|
285
|
-
if obj._proc is not None:
|
|
286
|
-
obj._proc.start()
|
|
287
|
-
return _Context(obj)
|
|
288
|
-
|
|
289
|
-
@classmethod
|
|
290
|
-
def connect(
|
|
291
|
-
cls,
|
|
292
|
-
*,
|
|
293
|
-
project: os.PathLike[str],
|
|
294
|
-
timeout: int | None = None,
|
|
295
|
-
) -> Self:
|
|
296
|
-
if cls._instance is not None:
|
|
297
|
-
cls._instance.wait_until_ready()
|
|
298
|
-
assert isinstance(cls._instance, cls)
|
|
299
|
-
return cls._instance
|
|
300
|
-
|
|
301
|
-
path = Path(project)
|
|
302
|
-
name = f"{cls.service_name}_server.json"
|
|
303
|
-
# Note: If the caller actually pass None, we override that here...
|
|
304
|
-
if timeout is None:
|
|
305
|
-
timeout = 240
|
|
306
|
-
t = -1
|
|
307
|
-
while t < timeout:
|
|
308
|
-
if (path / name).exists():
|
|
309
|
-
with (path / name).open() as f:
|
|
310
|
-
return cls((), conn_info=json.load(f), project=str(path))
|
|
311
|
-
|
|
312
|
-
sleep(1)
|
|
313
|
-
t += 1
|
|
314
|
-
|
|
315
|
-
raise TimeoutError("Server not started")
|
|
316
|
-
|
|
317
|
-
def wait_until_ready(self, timeout: int | None = None) -> bool:
|
|
318
|
-
if timeout is None:
|
|
319
|
-
timeout = self._timeout
|
|
320
|
-
|
|
321
|
-
if self._conn_info_event.wait(timeout):
|
|
322
|
-
return not (
|
|
323
|
-
self._conn_info is None or isinstance(self._conn_info, Exception)
|
|
324
|
-
)
|
|
325
|
-
if isinstance(self._conn_info, TimeoutError):
|
|
326
|
-
self.logger.critical(f"startup exceeded defined timeout {timeout}s")
|
|
327
|
-
return False # Timeout reached
|
|
328
|
-
|
|
329
|
-
def wait(self) -> None:
|
|
330
|
-
if self._proc is not None:
|
|
331
|
-
self._proc.join()
|
|
332
|
-
|
|
333
|
-
def set_conn_info(self, info: ErtServerConnectionInfo | Exception | None) -> None:
|
|
334
|
-
if self._conn_info is not None:
|
|
335
|
-
raise ValueError("Connection information already set")
|
|
336
|
-
if info is None:
|
|
337
|
-
raise ValueError
|
|
338
|
-
self._conn_info = info
|
|
339
|
-
|
|
340
|
-
if self._project is not None:
|
|
341
|
-
if not Path(self._project).exists():
|
|
342
|
-
raise RuntimeError(f"No storage exists at : {self._project}")
|
|
343
|
-
path = f"{self._project}/{self.service_name}_server.json"
|
|
344
|
-
else:
|
|
345
|
-
path = f"{self.service_name}_server.json"
|
|
346
|
-
|
|
347
|
-
if isinstance(info, Mapping):
|
|
348
|
-
with NamedTemporaryFile(dir=f"{self._project}", delete=False) as f:
|
|
349
|
-
f.write(json.dumps(info, indent=4).encode("utf-8"))
|
|
350
|
-
f.flush()
|
|
351
|
-
os.rename(f.name, path)
|
|
352
|
-
|
|
353
|
-
self._conn_info_event.set()
|
|
354
|
-
|
|
355
|
-
def fetch_conn_info(self) -> Mapping[str, Any]:
|
|
356
|
-
is_ready = self.wait_until_ready(self._timeout)
|
|
357
|
-
if isinstance(self._conn_info, Exception):
|
|
358
|
-
raise self._conn_info
|
|
359
|
-
if not is_ready:
|
|
360
|
-
raise TimeoutError
|
|
361
|
-
if self._conn_info is None:
|
|
362
|
-
raise ValueError("conn_info is None")
|
|
363
|
-
return self._conn_info
|
|
364
|
-
|
|
365
|
-
def shutdown(self) -> int:
|
|
366
|
-
"""Shutdown the server."""
|
|
367
|
-
if self._proc is None:
|
|
368
|
-
return -1
|
|
369
|
-
self.__class__._instance = None
|
|
370
|
-
proc, self._proc = self._proc, None
|
|
371
|
-
return proc.shutdown()
|
|
372
|
-
|
|
373
|
-
@property
|
|
374
|
-
def service_name(self) -> str:
|
|
375
|
-
"""
|
|
376
|
-
Subclass should return the name of the service, eg 'storage' for ERT Storage.
|
|
377
|
-
Used for identifying the server information JSON file.
|
|
378
|
-
"""
|
|
379
|
-
raise NotImplementedError
|
|
380
|
-
|
|
381
|
-
@property
|
|
382
|
-
def logger(self) -> Logger:
|
|
383
|
-
return getLogger(f"ert.shared.{self.service_name}")
|
|
384
|
-
|
|
385
|
-
@property
|
|
386
|
-
def _service_file(self) -> str:
|
|
387
|
-
return f"{self.service_name}_server.json"
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
from typing import Any
|
|
3
|
-
|
|
4
|
-
from ert.services._base_service import BaseService
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class WebvizErt(BaseService):
|
|
8
|
-
service_name = "webviz-ert"
|
|
9
|
-
|
|
10
|
-
def __init__(self, **kwargs: Any) -> None:
|
|
11
|
-
exec_args = [sys.executable, "-m", "webviz_ert"]
|
|
12
|
-
if kwargs.get("experimental_mode"):
|
|
13
|
-
exec_args.append("--experimental-mode")
|
|
14
|
-
if kwargs.get("verbose"):
|
|
15
|
-
exec_args.append("--verbose")
|
|
16
|
-
exec_args.extend(["--title", str(kwargs.get("title"))])
|
|
17
|
-
project = kwargs.get("project")
|
|
18
|
-
exec_args.extend(["--project_identifier", str(project)])
|
|
19
|
-
|
|
20
|
-
super().__init__(exec_args, project=project)
|
ert/shared/storage/command.py
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from argparse import ArgumentParser
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
def add_parser_options(ap: ArgumentParser) -> None:
|
|
6
|
-
ap.add_argument(
|
|
7
|
-
"config",
|
|
8
|
-
type=str,
|
|
9
|
-
help=("ERT config file to start the server from "),
|
|
10
|
-
nargs="?", # optional
|
|
11
|
-
)
|
|
12
|
-
ap.add_argument(
|
|
13
|
-
"--project",
|
|
14
|
-
"-p",
|
|
15
|
-
type=str,
|
|
16
|
-
help="Path to directory in which to create storage_server.json",
|
|
17
|
-
default=os.getcwd(),
|
|
18
|
-
)
|
|
19
|
-
ap.add_argument(
|
|
20
|
-
"--traceparent",
|
|
21
|
-
type=str,
|
|
22
|
-
help="Trace parent id to be used by the storage root span",
|
|
23
|
-
default=None,
|
|
24
|
-
)
|
|
25
|
-
ap.add_argument(
|
|
26
|
-
"--parent_pid",
|
|
27
|
-
type=int,
|
|
28
|
-
help="The parent process id",
|
|
29
|
-
default=os.getppid(),
|
|
30
|
-
)
|
|
31
|
-
ap.add_argument(
|
|
32
|
-
"--host", type=str, default=os.environ.get("ERT_STORAGE_HOST", "127.0.0.1")
|
|
33
|
-
)
|
|
34
|
-
ap.add_argument("--logging-config", type=str, default=None)
|
|
35
|
-
ap.add_argument(
|
|
36
|
-
"--verbose", action="store_true", help="Show verbose output.", default=False
|
|
37
|
-
)
|
|
38
|
-
ap.add_argument("--debug", action="store_true", default=False)
|
ert/shared/storage/extraction.py
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from collections.abc import Mapping
|
|
4
|
-
|
|
5
|
-
from ert.config import GenKwConfig
|
|
6
|
-
from ert.storage import Experiment
|
|
7
|
-
|
|
8
|
-
_PRIOR_NAME_MAP = {
|
|
9
|
-
"NORMAL": "normal",
|
|
10
|
-
"LOGNORMAL": "lognormal",
|
|
11
|
-
"TRIANGULAR": "trig",
|
|
12
|
-
"TRUNCATED_NORMAL": "ert_truncnormal",
|
|
13
|
-
"CONST": "const",
|
|
14
|
-
"UNIFORM": "uniform",
|
|
15
|
-
"LOGUNIF": "loguniform",
|
|
16
|
-
"DUNIF": "ert_duniform",
|
|
17
|
-
"RAW": "stdnormal",
|
|
18
|
-
"ERRF": "ert_erf",
|
|
19
|
-
"DERRF": "ert_derf",
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def create_priors(
|
|
24
|
-
experiment: Experiment,
|
|
25
|
-
) -> Mapping[str, dict[str, str | float]]:
|
|
26
|
-
priors_dict = {}
|
|
27
|
-
|
|
28
|
-
for param in experiment.parameter_configuration.values():
|
|
29
|
-
if isinstance(param, GenKwConfig):
|
|
30
|
-
prior: dict[str, str | float] = {
|
|
31
|
-
"function": _PRIOR_NAME_MAP[param.distribution.name.upper()],
|
|
32
|
-
**param.distribution.model_dump(exclude={"name"}),
|
|
33
|
-
}
|
|
34
|
-
# webviz-ert expects some variables names
|
|
35
|
-
if param.distribution.name == "triangular":
|
|
36
|
-
mapping = {"min": "_xmin", "max": "xmax", "mode": "xmode"}
|
|
37
|
-
else:
|
|
38
|
-
mapping = {"min": "_min", "max": "_max"}
|
|
39
|
-
prior = {mapping.get(k, k): v for k, v in prior.items()}
|
|
40
|
-
priors_dict[f"{param.group}:{param.name}"] = prior
|
|
41
|
-
|
|
42
|
-
return priors_dict
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|