ert 16.0.9__py3-none-any.whl → 19.0.0rc2__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.
Files changed (286) hide show
  1. _ert/events.py +19 -2
  2. _ert/forward_model_runner/client.py +6 -2
  3. _ert/forward_model_runner/fm_dispatch.py +9 -6
  4. _ert/forward_model_runner/reporting/event.py +1 -0
  5. _ert/forward_model_runner/runner.py +1 -2
  6. _ert/utils.py +12 -0
  7. ert/__main__.py +58 -38
  8. ert/analysis/_enif_update.py +8 -4
  9. ert/analysis/_es_update.py +19 -6
  10. ert/analysis/_update_commons.py +16 -6
  11. ert/base_model_context.py +1 -1
  12. ert/cli/main.py +17 -12
  13. ert/cli/monitor.py +7 -0
  14. ert/config/__init__.py +17 -6
  15. ert/config/_create_observation_dataframes.py +118 -21
  16. ert/config/_get_num_cpu.py +1 -1
  17. ert/config/_observations.py +91 -2
  18. ert/config/_read_summary.py +74 -328
  19. ert/config/design_matrix.py +62 -23
  20. ert/config/distribution.py +1 -1
  21. ert/config/ensemble_config.py +9 -17
  22. ert/config/ert_config.py +155 -58
  23. ert/config/everest_control.py +234 -0
  24. ert/config/{everest_constraints_config.py → everest_response.py} +27 -15
  25. ert/config/field.py +99 -90
  26. ert/config/forward_model_step.py +122 -17
  27. ert/config/gen_data_config.py +5 -10
  28. ert/config/gen_kw_config.py +11 -41
  29. ert/config/known_response_types.py +14 -0
  30. ert/config/parameter_config.py +1 -33
  31. ert/config/parsing/_option_dict.py +10 -2
  32. ert/config/parsing/config_errors.py +1 -1
  33. ert/config/parsing/config_keywords.py +2 -1
  34. ert/config/parsing/config_schema.py +23 -11
  35. ert/config/parsing/config_schema_deprecations.py +3 -3
  36. ert/config/parsing/config_schema_item.py +26 -11
  37. ert/config/parsing/context_values.py +3 -3
  38. ert/config/parsing/file_context_token.py +1 -1
  39. ert/config/parsing/observations_parser.py +6 -2
  40. ert/config/parsing/queue_system.py +9 -0
  41. ert/config/parsing/schema_item_type.py +1 -0
  42. ert/config/queue_config.py +42 -50
  43. ert/config/response_config.py +0 -8
  44. ert/config/rft_config.py +275 -0
  45. ert/config/summary_config.py +3 -8
  46. ert/config/surface_config.py +73 -26
  47. ert/config/workflow_fixtures.py +2 -1
  48. ert/config/workflow_job.py +135 -54
  49. ert/dark_storage/client/__init__.py +2 -2
  50. ert/dark_storage/client/_session.py +4 -4
  51. ert/dark_storage/client/client.py +2 -2
  52. ert/dark_storage/common.py +12 -3
  53. ert/dark_storage/compute/misfits.py +11 -7
  54. ert/dark_storage/endpoints/compute/misfits.py +6 -4
  55. ert/dark_storage/endpoints/ensembles.py +4 -0
  56. ert/dark_storage/endpoints/experiment_server.py +30 -24
  57. ert/dark_storage/endpoints/experiments.py +2 -2
  58. ert/dark_storage/endpoints/observations.py +8 -6
  59. ert/dark_storage/endpoints/parameters.py +4 -12
  60. ert/dark_storage/endpoints/responses.py +24 -5
  61. ert/dark_storage/json_schema/ensemble.py +3 -0
  62. ert/dark_storage/json_schema/experiment.py +1 -1
  63. ert/data/_measured_data.py +6 -5
  64. ert/ensemble_evaluator/__init__.py +8 -1
  65. ert/ensemble_evaluator/config.py +2 -1
  66. ert/ensemble_evaluator/evaluator.py +81 -29
  67. ert/ensemble_evaluator/event.py +6 -0
  68. ert/ensemble_evaluator/snapshot.py +3 -1
  69. ert/ensemble_evaluator/state.py +1 -0
  70. ert/field_utils/__init__.py +8 -0
  71. ert/field_utils/field_utils.py +228 -15
  72. ert/field_utils/grdecl_io.py +1 -1
  73. ert/field_utils/roff_io.py +1 -1
  74. ert/gui/__init__.py +5 -2
  75. ert/gui/ertnotifier.py +1 -1
  76. ert/gui/ertwidgets/__init__.py +23 -16
  77. ert/gui/ertwidgets/analysismoduleedit.py +2 -2
  78. ert/gui/ertwidgets/checklist.py +1 -1
  79. ert/gui/ertwidgets/closabledialog.py +2 -0
  80. ert/gui/ertwidgets/copyablelabel.py +2 -0
  81. ert/gui/ertwidgets/create_experiment_dialog.py +3 -1
  82. ert/gui/ertwidgets/ensembleselector.py +2 -2
  83. ert/gui/ertwidgets/listeditbox.py +2 -0
  84. ert/gui/ertwidgets/models/__init__.py +2 -0
  85. ert/gui/ertwidgets/models/activerealizationsmodel.py +5 -1
  86. ert/gui/ertwidgets/models/path_model.py +1 -1
  87. ert/gui/ertwidgets/models/targetensemblemodel.py +5 -1
  88. ert/gui/ertwidgets/models/text_model.py +4 -1
  89. ert/gui/ertwidgets/pathchooser.py +0 -3
  90. ert/gui/ertwidgets/searchbox.py +17 -4
  91. ert/gui/ertwidgets/stringbox.py +2 -0
  92. ert/gui/{suggestor → ertwidgets/suggestor}/_suggestor_message.py +13 -4
  93. ert/gui/{suggestor → ertwidgets/suggestor}/suggestor.py +63 -30
  94. ert/gui/main.py +41 -13
  95. ert/gui/main_window.py +3 -7
  96. ert/gui/model/fm_step_list.py +3 -0
  97. ert/gui/model/real_list.py +1 -0
  98. ert/gui/model/snapshot.py +1 -0
  99. ert/gui/simulation/combobox_with_description.py +3 -0
  100. ert/gui/simulation/ensemble_experiment_panel.py +8 -2
  101. ert/gui/simulation/ensemble_information_filter_panel.py +7 -2
  102. ert/gui/simulation/ensemble_smoother_panel.py +8 -2
  103. ert/gui/simulation/evaluate_ensemble_panel.py +17 -7
  104. ert/gui/simulation/experiment_panel.py +18 -6
  105. ert/gui/simulation/manual_update_panel.py +35 -10
  106. ert/gui/simulation/multiple_data_assimilation_panel.py +13 -9
  107. ert/gui/simulation/run_dialog.py +47 -20
  108. ert/gui/simulation/single_test_run_panel.py +6 -3
  109. ert/gui/simulation/view/progress_widget.py +2 -0
  110. ert/gui/simulation/view/realization.py +5 -1
  111. ert/gui/simulation/view/update.py +2 -0
  112. ert/gui/summarypanel.py +20 -1
  113. ert/gui/tools/event_viewer/panel.py +3 -4
  114. ert/gui/tools/event_viewer/tool.py +2 -0
  115. ert/gui/tools/load_results/load_results_panel.py +1 -1
  116. ert/gui/tools/load_results/load_results_tool.py +2 -0
  117. ert/gui/tools/manage_experiments/export_dialog.py +136 -0
  118. ert/gui/tools/manage_experiments/manage_experiments_panel.py +2 -0
  119. ert/gui/tools/manage_experiments/storage_info_widget.py +121 -16
  120. ert/gui/tools/manage_experiments/storage_widget.py +4 -3
  121. ert/gui/tools/plot/customize/color_chooser.py +5 -2
  122. ert/gui/tools/plot/customize/customize_plot_dialog.py +2 -0
  123. ert/gui/tools/plot/customize/default_customization_view.py +4 -0
  124. ert/gui/tools/plot/customize/limits_customization_view.py +3 -0
  125. ert/gui/tools/plot/customize/statistics_customization_view.py +3 -0
  126. ert/gui/tools/plot/customize/style_chooser.py +2 -0
  127. ert/gui/tools/plot/customize/style_customization_view.py +3 -0
  128. ert/gui/tools/plot/data_type_keys_widget.py +2 -0
  129. ert/gui/tools/plot/data_type_proxy_model.py +3 -0
  130. ert/gui/tools/plot/plot_api.py +50 -28
  131. ert/gui/tools/plot/plot_ensemble_selection_widget.py +17 -10
  132. ert/gui/tools/plot/plot_widget.py +15 -2
  133. ert/gui/tools/plot/plot_window.py +41 -19
  134. ert/gui/tools/plot/plottery/plot_config.py +2 -0
  135. ert/gui/tools/plot/plottery/plot_context.py +14 -0
  136. ert/gui/tools/plot/plottery/plots/__init__.py +2 -0
  137. ert/gui/tools/plot/plottery/plots/cesp.py +3 -1
  138. ert/gui/tools/plot/plottery/plots/distribution.py +6 -1
  139. ert/gui/tools/plot/plottery/plots/ensemble.py +13 -5
  140. ert/gui/tools/plot/plottery/plots/gaussian_kde.py +12 -2
  141. ert/gui/tools/plot/plottery/plots/histogram.py +3 -1
  142. ert/gui/tools/plot/plottery/plots/misfits.py +436 -0
  143. ert/gui/tools/plot/plottery/plots/observations.py +18 -4
  144. ert/gui/tools/plot/plottery/plots/statistics.py +62 -20
  145. ert/gui/tools/plot/plottery/plots/std_dev.py +3 -1
  146. ert/gui/tools/plot/widgets/clearable_line_edit.py +9 -0
  147. ert/gui/tools/plot/widgets/filter_popup.py +2 -0
  148. ert/gui/tools/plot/widgets/filterable_kw_list_model.py +3 -0
  149. ert/gui/tools/plugins/plugin.py +1 -1
  150. ert/gui/tools/plugins/plugins_tool.py +2 -0
  151. ert/gui/tools/plugins/process_job_dialog.py +3 -0
  152. ert/gui/tools/workflows/workflow_dialog.py +2 -0
  153. ert/gui/tools/workflows/workflows_tool.py +2 -0
  154. ert/libres_facade.py +5 -7
  155. ert/logging/__init__.py +4 -1
  156. ert/mode_definitions.py +2 -0
  157. ert/plugins/__init__.py +4 -6
  158. ert/plugins/hook_implementations/workflows/csv_export.py +2 -3
  159. ert/plugins/hook_implementations/workflows/gen_data_rft_export.py +10 -2
  160. ert/plugins/hook_specifications/__init__.py +0 -10
  161. ert/plugins/hook_specifications/jobs.py +0 -9
  162. ert/plugins/plugin_manager.py +53 -124
  163. ert/resources/forward_models/run_reservoirsimulator.py +8 -4
  164. ert/resources/forward_models/template_render.py +10 -10
  165. ert/resources/shell_scripts/delete_directory.py +2 -2
  166. ert/run_models/__init__.py +24 -6
  167. ert/run_models/_create_run_path.py +133 -38
  168. ert/run_models/ensemble_experiment.py +10 -4
  169. ert/run_models/ensemble_information_filter.py +8 -1
  170. ert/run_models/ensemble_smoother.py +9 -3
  171. ert/run_models/evaluate_ensemble.py +8 -6
  172. ert/run_models/event.py +7 -3
  173. ert/run_models/everest_run_model.py +337 -113
  174. ert/run_models/initial_ensemble_run_model.py +25 -24
  175. ert/run_models/manual_update.py +6 -3
  176. ert/run_models/manual_update_enif.py +37 -0
  177. ert/run_models/model_factory.py +78 -18
  178. ert/run_models/multiple_data_assimilation.py +22 -11
  179. ert/run_models/run_model.py +72 -73
  180. ert/run_models/single_test_run.py +7 -4
  181. ert/run_models/update_run_model.py +4 -2
  182. ert/runpaths.py +5 -6
  183. ert/sample_prior.py +9 -4
  184. ert/scheduler/__init__.py +10 -5
  185. ert/scheduler/driver.py +40 -0
  186. ert/scheduler/event.py +3 -1
  187. ert/scheduler/job.py +23 -13
  188. ert/scheduler/lsf_driver.py +15 -5
  189. ert/scheduler/openpbs_driver.py +10 -4
  190. ert/scheduler/scheduler.py +5 -0
  191. ert/scheduler/slurm_driver.py +20 -5
  192. ert/services/__init__.py +2 -2
  193. ert/services/_base_service.py +37 -20
  194. ert/services/_storage_main.py +20 -18
  195. ert/services/ert_server.py +317 -0
  196. ert/shared/_doc_utils/__init__.py +4 -2
  197. ert/shared/_doc_utils/ert_jobs.py +1 -4
  198. ert/shared/net_utils.py +43 -18
  199. ert/shared/storage/connection.py +3 -3
  200. ert/shared/version.py +3 -3
  201. ert/storage/__init__.py +14 -1
  202. ert/storage/local_ensemble.py +44 -13
  203. ert/storage/local_experiment.py +54 -34
  204. ert/storage/local_storage.py +90 -58
  205. ert/storage/migration/to10.py +3 -2
  206. ert/storage/migration/to11.py +9 -10
  207. ert/storage/migration/to12.py +19 -20
  208. ert/storage/migration/to13.py +28 -27
  209. ert/storage/migration/to14.py +3 -3
  210. ert/storage/migration/to15.py +25 -0
  211. ert/storage/migration/to16.py +38 -0
  212. ert/storage/migration/to17.py +42 -0
  213. ert/storage/migration/to18.py +11 -0
  214. ert/storage/migration/to19.py +34 -0
  215. ert/storage/migration/to20.py +23 -0
  216. ert/storage/migration/to21.py +25 -0
  217. ert/storage/migration/to6.py +3 -2
  218. ert/storage/migration/to7.py +12 -13
  219. ert/storage/migration/to8.py +9 -11
  220. ert/storage/migration/to9.py +5 -4
  221. ert/storage/realization_storage_state.py +7 -7
  222. ert/substitutions.py +12 -28
  223. ert/validation/active_range.py +7 -7
  224. ert/validation/ensemble_realizations_argument.py +4 -2
  225. ert/validation/rangestring.py +16 -16
  226. ert/workflow_runner.py +6 -3
  227. {ert-16.0.9.dist-info → ert-19.0.0rc2.dist-info}/METADATA +21 -15
  228. ert-19.0.0rc2.dist-info/RECORD +524 -0
  229. {ert-16.0.9.dist-info → ert-19.0.0rc2.dist-info}/WHEEL +1 -1
  230. everest/api/everest_data_api.py +14 -1
  231. everest/assets/everest_logo.svg +406 -0
  232. everest/bin/config_branch_script.py +30 -14
  233. everest/bin/everconfigdump_script.py +2 -10
  234. everest/bin/everest_script.py +53 -33
  235. everest/bin/everlint_script.py +3 -5
  236. everest/bin/kill_script.py +7 -5
  237. everest/bin/main.py +11 -24
  238. everest/bin/monitor_script.py +64 -35
  239. everest/bin/utils.py +58 -43
  240. everest/bin/visualization_script.py +23 -13
  241. everest/config/__init__.py +4 -1
  242. everest/config/control_config.py +81 -6
  243. everest/config/control_variable_config.py +4 -3
  244. everest/config/everest_config.py +102 -79
  245. everest/config/forward_model_config.py +5 -3
  246. everest/config/install_data_config.py +7 -5
  247. everest/config/install_job_config.py +45 -3
  248. everest/config/install_template_config.py +3 -3
  249. everest/config/optimization_config.py +19 -6
  250. everest/config/output_constraint_config.py +8 -2
  251. everest/config/server_config.py +6 -55
  252. everest/config/simulator_config.py +62 -17
  253. everest/config/utils.py +25 -105
  254. everest/config/validation_utils.py +34 -15
  255. everest/config_file_loader.py +30 -21
  256. everest/detached/__init__.py +0 -6
  257. everest/detached/client.py +7 -52
  258. everest/detached/everserver.py +19 -45
  259. everest/everest_storage.py +24 -40
  260. everest/gui/everest_client.py +2 -3
  261. everest/gui/main_window.py +2 -2
  262. everest/optimizer/everest2ropt.py +68 -42
  263. everest/optimizer/opt_model_transforms.py +15 -20
  264. everest/optimizer/utils.py +0 -29
  265. everest/plugins/hook_specs.py +0 -24
  266. everest/strings.py +1 -6
  267. everest/util/__init__.py +3 -1
  268. ert/config/everest_objective_config.py +0 -95
  269. ert/config/ext_param_config.py +0 -107
  270. ert/gui/tools/export/__init__.py +0 -3
  271. ert/gui/tools/export/export_panel.py +0 -83
  272. ert/gui/tools/export/export_tool.py +0 -67
  273. ert/gui/tools/export/exporter.py +0 -36
  274. ert/plugins/hook_specifications/ecl_config.py +0 -29
  275. ert/services/storage_service.py +0 -127
  276. ert/summary_key_type.py +0 -234
  277. ert-16.0.9.dist-info/RECORD +0 -521
  278. everest/bin/everexport_script.py +0 -53
  279. everest/config/sampler_config.py +0 -103
  280. everest/simulator/__init__.py +0 -88
  281. everest/simulator/everest_to_ert.py +0 -252
  282. /ert/gui/{suggestor → ertwidgets/suggestor}/__init__.py +0 -0
  283. /ert/gui/{suggestor → ertwidgets/suggestor}/_colors.py +0 -0
  284. {ert-16.0.9.dist-info → ert-19.0.0rc2.dist-info}/entry_points.txt +0 -0
  285. {ert-16.0.9.dist-info → ert-19.0.0rc2.dist-info}/licenses/COPYING +0 -0
  286. {ert-16.0.9.dist-info → ert-19.0.0rc2.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,5 @@
1
1
  import asyncio
2
- import json
3
2
  import logging
4
- import os
5
3
  import re
6
4
  import ssl
7
5
  import time
@@ -17,9 +15,7 @@ from websockets import ConnectionClosedError, ConnectionClosedOK
17
15
  from websockets.sync.client import connect
18
16
 
19
17
  from ert.dark_storage.client import Client
20
- from ert.ensemble_evaluator import EndEvent
21
18
  from ert.run_models.event import EverestBatchResultEvent, status_event_from_json
22
- from ert.run_models.run_model import ExperimentState
23
19
  from ert.scheduler import create_driver
24
20
  from ert.scheduler.driver import Driver, FailedSubmit
25
21
  from ert.scheduler.event import StartedEvent
@@ -49,7 +45,7 @@ async def start_server(config: EverestConfig, logging_level: int) -> Driver:
49
45
  """
50
46
  Start an Everest server running the optimization defined in the config
51
47
  """
52
- driver = create_driver(config.server.queue_system) # type: ignore
48
+ driver = create_driver(config.server.queue_system, poll_period=0.1) # type: ignore
53
49
  try:
54
50
  args = [
55
51
  "--output-dir",
@@ -85,7 +81,7 @@ def stop_server(
85
81
  for retry in range(retries):
86
82
  try:
87
83
  url, cert, auth = server_context
88
- stop_endpoint = "/".join([url, EverEndpoints.stop])
84
+ stop_endpoint = f"{url}/{EverEndpoints.stop}"
89
85
  response = requests.post(
90
86
  stop_endpoint,
91
87
  verify=cert,
@@ -109,7 +105,7 @@ def start_experiment(
109
105
  for retry in range(retries):
110
106
  try:
111
107
  url, cert, auth = server_context
112
- start_endpoint = "/".join([url, EverEndpoints.start_experiment])
108
+ start_endpoint = f"{url}/{EverEndpoints.start_experiment}"
113
109
  response = requests.post(
114
110
  start_endpoint,
115
111
  verify=cert,
@@ -130,7 +126,7 @@ def extract_errors_from_file(path: str) -> list[str]:
130
126
  return re.findall(r"(Error \w+.*)", Path(path).read_text(encoding="utf-8"))
131
127
 
132
128
 
133
- def wait_for_server(client: Client, timeout: int | float) -> None:
129
+ def wait_for_server(client: Client, timeout: float) -> None:
134
130
  """
135
131
  Waits until the everest server has started. Polls every second
136
132
  for server availability until timeout (measured in seconds).
@@ -236,9 +232,7 @@ def start_monitor(
236
232
  try:
237
233
  message = websocket.recv(timeout=1.0)
238
234
  event = status_event_from_json(message)
239
- if isinstance(event, EndEvent):
240
- print(event.msg)
241
- elif isinstance(event, EverestBatchResultEvent):
235
+ if isinstance(event, EverestBatchResultEvent):
242
236
  if event.result_type == "FunctionResult":
243
237
  callback(
244
238
  {
@@ -261,45 +255,6 @@ def start_monitor(
261
255
  logger.error("Error when processing event %s", exc_info=e)
262
256
 
263
257
  time.sleep(polling_interval)
264
- except Exception:
265
- logger.debug(traceback.format_exc())
266
-
267
258
 
268
- def update_everserver_status(
269
- everserver_status_path: str, status: ExperimentState, message: str | None = None
270
- ) -> None:
271
- """Update the everest server status with new status information"""
272
- new_status = {"status": status, "message": message}
273
- path = everserver_status_path
274
- if not os.path.exists(os.path.dirname(path)):
275
- os.makedirs(os.path.dirname(path))
276
- with open(path, "w", encoding="utf-8") as outfile:
277
- json.dump(new_status, outfile)
278
- elif os.path.exists(path):
279
- server_status = everserver_status(path)
280
- if server_status["message"] is not None:
281
- if message is not None:
282
- new_status["message"] = "{}\n{}".format(
283
- server_status["message"], message
284
- )
285
- else:
286
- new_status["message"] = server_status["message"]
287
- with open(path, "w", encoding="utf-8") as outfile:
288
- json.dump(new_status, outfile)
289
-
290
-
291
- def everserver_status(everserver_status_path: str) -> dict[str, Any]:
292
- """Returns a dictionary representing the everest server status. If the
293
- status file is not found we assume the server has never ran before, and will
294
- return a status of ServerStatus.never_run
295
-
296
- Example: {
297
- 'status': ServerStatus.completed
298
- 'message': None
299
- }
300
- """
301
- if os.path.exists(everserver_status_path):
302
- with open(everserver_status_path, encoding="utf-8") as f:
303
- return json.load(f)
304
- else:
305
- return {"status": ExperimentState.never_run, "message": None}
259
+ except Exception:
260
+ logger.exception(traceback.format_exc())
@@ -4,7 +4,6 @@ import logging.config
4
4
  import os
5
5
  import pathlib
6
6
  import time
7
- import traceback
8
7
  from pathlib import Path
9
8
  from tempfile import NamedTemporaryFile
10
9
  from typing import Any
@@ -13,20 +12,17 @@ import yaml
13
12
  from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator
14
13
 
15
14
  from ert.plugins.plugin_manager import ErtPluginManager
16
- from ert.run_models.run_model import ExperimentStatus
17
- from ert.services import StorageService
15
+ from ert.services import ErtServer
18
16
  from ert.services._base_service import BaseServiceExit
17
+ from ert.storage import ExperimentStatus
18
+ from ert.storage.local_experiment import ExperimentState
19
19
  from ert.trace import tracer
20
20
  from everest.config import ServerConfig
21
- from everest.detached import (
22
- ExperimentState,
23
- everserver_status,
24
- update_everserver_status,
25
- )
26
21
  from everest.strings import (
27
22
  DEFAULT_LOGGING_FORMAT,
28
23
  EVEREST,
29
24
  EVERSERVER,
25
+ EXPERIMENT_SERVER,
30
26
  OPTIMIZATION_LOG_DIR,
31
27
  )
32
28
  from everest.util import makedirs_if_needed, version_info
@@ -35,7 +31,7 @@ logger = logging.getLogger(__name__)
35
31
 
36
32
 
37
33
  def _configure_loggers(
38
- detached_dir: Path, log_dir: Path, logging_level: int, output_file: str | None
34
+ log_dir: Path, logging_level: int, output_file: str | None
39
35
  ) -> None:
40
36
  def make_handler_config(path: Path, log_level: int) -> dict[str, Any]:
41
37
  makedirs_if_needed(str(path.parent))
@@ -50,7 +46,7 @@ def _configure_loggers(
50
46
  "version": 1,
51
47
  "handlers": {
52
48
  "endpoint_log": make_handler_config(
53
- detached_dir / "endpoint.log", logging_level
49
+ log_dir / "everserver.log", logging_level
54
50
  ),
55
51
  "everest_log": make_handler_config(log_dir / "everest.log", logging_level),
56
52
  "forward_models_log": make_handler_config(
@@ -67,6 +63,11 @@ def _configure_loggers(
67
63
  "level": logging_level,
68
64
  "propagate": False,
69
65
  },
66
+ EXPERIMENT_SERVER: {
67
+ "handlers": ["endpoint_log"],
68
+ "level": logging_level,
69
+ "propagate": False,
70
+ },
70
71
  EVEREST: {
71
72
  "handlers": ["everest_log"],
72
73
  "level": logging_level,
@@ -93,8 +94,9 @@ def _configure_loggers(
93
94
 
94
95
  yaml.add_representer(pathlib.PosixPath, path_representer)
95
96
  if output_file:
96
- with open(output_file, "w", encoding="utf-8") as outfile:
97
- yaml.dump(logging_config, outfile, default_flow_style=False)
97
+ Path(output_file).write_text(
98
+ yaml.dump(logging_config, default_flow_style=False), encoding="utf-8"
99
+ )
98
100
  logging.config.dictConfig(logging_config)
99
101
 
100
102
  plugin_manager = ErtPluginManager()
@@ -135,8 +137,6 @@ def main() -> None:
135
137
 
136
138
  output_dir = options.output_dir
137
139
 
138
- status_path = ServerConfig.get_everserver_status_path(output_dir)
139
-
140
140
  ctx = (
141
141
  TraceContextTextMapPropagator().extract(
142
142
  carrier={"traceparent": options.traceparent}
@@ -151,25 +151,22 @@ def main() -> None:
151
151
  ):
152
152
  try:
153
153
  _configure_loggers(
154
- detached_dir=Path(ServerConfig.get_detached_node_dir(output_dir)),
155
154
  log_dir=Path(output_dir) / OPTIMIZATION_LOG_DIR,
156
155
  logging_level=options.logging_level,
157
156
  output_file=log_file.name,
158
157
  )
159
158
 
160
159
  logging.getLogger(EVERSERVER).info("Everserver starting ...")
161
- update_everserver_status(status_path, ExperimentState.pending)
162
160
  logger.info(version_info())
163
161
  logger.info(f"Output directory: {output_dir}")
164
162
  # Starting the server
165
163
  server_path = os.path.abspath(ServerConfig.get_session_dir(output_dir))
166
164
  status = ""
167
- with StorageService.init_service(
168
- timeout=240, project=server_path, logging_config=log_file.name
165
+ with ErtServer.init_service(
166
+ timeout=240, project=Path(server_path), logging_config=log_file.name
169
167
  ) as server:
170
- server.fetch_conn_info()
171
- with StorageService.session(project=server_path) as client:
172
- update_everserver_status(status_path, ExperimentState.running)
168
+ server.fetch_connection_info()
169
+ with ErtServer.session(project=Path(server_path)) as client:
173
170
  done = False
174
171
  while not done:
175
172
  response = client.get(
@@ -181,33 +178,10 @@ def main() -> None:
181
178
  ExperimentState.running,
182
179
  }
183
180
  time.sleep(0.5)
184
- if status.status == ExperimentState.completed:
185
- update_everserver_status(
186
- status_path,
187
- ExperimentState.completed,
188
- message=status.message,
189
- )
190
- elif status.status == ExperimentState.stopped:
191
- update_everserver_status(
192
- status_path,
193
- ExperimentState.stopped,
194
- message=status.message,
195
- )
196
- elif status.status == ExperimentState.failed:
197
- update_everserver_status(
198
- status_path, ExperimentState.failed, message=status.message
199
- )
200
181
  except BaseServiceExit:
201
182
  # Server exit, happens on normal shutdown and keyboard interrupt
202
- server_status = everserver_status(status_path)
203
- if server_status["status"] == ExperimentState.running:
204
- update_everserver_status(status_path, ExperimentState.stopped)
183
+ logging.getLogger(EVERSERVER).info("Everserver stopped by user")
205
184
  except Exception as e:
206
- update_everserver_status(
207
- status_path,
208
- ExperimentState.failed,
209
- message=traceback.format_exc(),
210
- )
211
185
  logging.getLogger(EVERSERVER).exception(e)
212
186
 
213
187
 
@@ -12,8 +12,7 @@ import numpy as np
12
12
  import polars as pl
13
13
  from ropt.results import FunctionResults, GradientResults, Results
14
14
 
15
- from everest.config.objective_function_config import ObjectiveFunctionConfig
16
- from everest.config.output_constraint_config import OutputConstraintConfig
15
+ from ert.config import EverestConstraintsConfig, EverestObjectivesConfig
17
16
  from everest.strings import EVEREST
18
17
 
19
18
  logger = logging.getLogger(__name__)
@@ -153,16 +152,12 @@ class BatchStorageData:
153
152
 
154
153
  @cached_property
155
154
  def is_improvement(self) -> bool:
156
- with open(self._path / "batch.json", encoding="utf-8") as f:
157
- info = json.load(f)
158
-
155
+ info = json.loads((self._path / "batch.json").read_text(encoding="utf-8"))
159
156
  return bool(info["is_improvement"])
160
157
 
161
158
  @cached_property
162
159
  def batch_id(self) -> bool:
163
- with open(self._path / "batch.json", encoding="utf-8") as f:
164
- info = json.load(f)
165
-
160
+ info = json.loads((self._path / "batch.json").read_text(encoding="utf-8"))
166
161
  return info["batch_id"]
167
162
 
168
163
  def write_metadata(self, is_improvement: bool) -> None:
@@ -170,15 +165,9 @@ class BatchStorageData:
170
165
  if "is_improvement" in self.__dict__:
171
166
  del self.is_improvement
172
167
 
173
- with open(self._path / "batch.json", encoding="utf-8") as f:
174
- info = json.load(f)
175
- info["is_improvement"] = is_improvement
176
-
177
- with open(self._path / "batch.json", "w", encoding="utf-8") as f:
178
- json.dump(
179
- info,
180
- f,
181
- )
168
+ info = json.loads((self._path / "batch.json").read_text(encoding="utf-8"))
169
+ info["is_improvement"] = is_improvement
170
+ (self._path / "batch.json").write_text(json.dumps(info), encoding="utf-8")
182
171
 
183
172
 
184
173
  class FunctionBatchStorageData(BatchStorageData):
@@ -541,8 +530,8 @@ class EverestStorage:
541
530
  def init(
542
531
  self,
543
532
  formatted_control_names: list[str],
544
- objective_functions: list[ObjectiveFunctionConfig],
545
- output_constraints: list[OutputConstraintConfig] | None,
533
+ objective_functions: EverestObjectivesConfig,
534
+ output_constraints: EverestConstraintsConfig | None,
546
535
  realizations: list[int],
547
536
  ) -> None:
548
537
  controls = pl.DataFrame(
@@ -551,21 +540,22 @@ class EverestStorage:
551
540
  }
552
541
  )
553
542
 
554
- # TODO: The weight and normalization keys are only used by the everest api,
555
- # with everviz. They should be removed in the long run.
556
543
  weights = np.fromiter(
557
- (1.0 if obj.weight is None else obj.weight for obj in objective_functions),
544
+ (
545
+ 1.0 if weight is None else weight
546
+ for weight in objective_functions.weights
547
+ ),
558
548
  dtype=np.float64,
559
549
  )
560
550
 
561
551
  objective_functions_dataframe = pl.DataFrame(
562
552
  {
563
- "objective_name": [objective.name for objective in objective_functions],
553
+ "objective_name": objective_functions.keys,
564
554
  "weight": pl.Series(weights / sum(weights), dtype=pl.Float64),
565
555
  "scale": pl.Series(
566
556
  [
567
- 1.0 if obj.scale is None else obj.scale
568
- for obj in objective_functions
557
+ 1.0 if scale is None else scale
558
+ for scale in objective_functions.scales
569
559
  ],
570
560
  dtype=pl.Float64,
571
561
  ),
@@ -573,13 +563,7 @@ class EverestStorage:
573
563
  )
574
564
 
575
565
  nonlinear_constraints = (
576
- pl.DataFrame(
577
- {
578
- "constraint_name": [
579
- constraint.name for constraint in output_constraints
580
- ],
581
- }
582
- )
566
+ pl.DataFrame({"constraint_name": output_constraints.keys})
583
567
  if output_constraints
584
568
  else None
585
569
  )
@@ -906,18 +890,15 @@ class EverestStorage:
906
890
  for batch_id, batch_dict in batch_dicts.items():
907
891
  target_ensemble = self._experiment.get_ensemble_by_name(f"batch_{batch_id}")
908
892
 
909
- with open(
910
- target_ensemble.optimizer_mount_point / "batch.json",
911
- "w+",
912
- encoding="utf-8",
913
- ) as f:
914
- json.dump(
893
+ (target_ensemble.optimizer_mount_point / "batch.json").write_text(
894
+ json.dumps(
915
895
  {
916
896
  "batch_id": batch_id,
917
897
  "is_improvement": False,
918
898
  },
919
- f,
920
- )
899
+ ),
900
+ encoding="utf-8",
901
+ )
921
902
 
922
903
  batch_data = BatchStorageData(path=target_ensemble.optimizer_mount_point)
923
904
 
@@ -1011,6 +992,9 @@ class EverestStorage:
1011
992
  def export_dataframes(
1012
993
  self,
1013
994
  ) -> tuple[pl.DataFrame, pl.DataFrame, pl.DataFrame]:
995
+ if not self.data.batches:
996
+ return (pl.DataFrame(), pl.DataFrame(), pl.DataFrame())
997
+
1014
998
  batch_dfs_to_join = {} # type: ignore
1015
999
  realization_dfs_to_join = {} # type: ignore
1016
1000
  perturbation_dfs_to_join = {} # type: ignore
@@ -44,7 +44,7 @@ class EverestClient:
44
44
 
45
45
  def _http_get(self, endpoint: EverEndpoints) -> requests.Response:
46
46
  return requests.get(
47
- "/".join([self._url, endpoint]),
47
+ f"{self._url}/{endpoint}",
48
48
  verify=self._cert,
49
49
  auth=(self._username, self._password),
50
50
  proxies={"http": None, "https": None}, # type: ignore
@@ -52,7 +52,7 @@ class EverestClient:
52
52
 
53
53
  def _http_post(self, endpoint: EverEndpoints) -> requests.Response:
54
54
  return requests.post(
55
- "/".join([self._url, endpoint]),
55
+ f"{self._url}/{endpoint}",
56
56
  verify=self._cert,
57
57
  auth=(self._username, self._password),
58
58
  proxies={"http": None, "https": None}, # type: ignore
@@ -128,7 +128,6 @@ class EverestClient:
128
128
  supports_rerunning_failed_realizations=False,
129
129
  start_simulations_thread=start_fn,
130
130
  cancel=self.stop,
131
- get_runtime=self.get_runtime,
132
131
  has_failed_realizations=lambda: False,
133
132
  )
134
133
 
@@ -13,7 +13,7 @@ from PyQt6.QtWidgets import (
13
13
  from ert.gui.ertnotifier import ErtNotifier
14
14
  from ert.gui.simulation.run_dialog import RunDialog
15
15
  from ert.plugins import ErtPluginManager
16
- from ert.services import StorageService
16
+ from ert.services import ErtServer
17
17
  from everest.config import ServerConfig
18
18
  from everest.detached import wait_for_server
19
19
  from everest.gui.everest_client import EverestClient
@@ -43,7 +43,7 @@ class EverestMainWindow(QMainWindow):
43
43
  self.setCentralWidget(self.central_widget)
44
44
 
45
45
  def run(self) -> None:
46
- storage_client = StorageService.session(
46
+ storage_client = ErtServer.session(
47
47
  Path(ServerConfig.get_session_dir(self.output_dir))
48
48
  )
49
49
  wait_for_server(storage_client, 60)
@@ -3,34 +3,48 @@ from typing import Any
3
3
 
4
4
  from ropt.enums import PerturbationType, VariableType
5
5
 
6
+ from ert.config import EverestConstraintsConfig, EverestControl, EverestObjectivesConfig
6
7
  from everest.config import (
7
- ControlConfig,
8
8
  InputConstraintConfig,
9
9
  ModelConfig,
10
- ObjectiveFunctionConfig,
11
10
  OptimizationConfig,
12
11
  OutputConstraintConfig,
13
12
  )
14
- from everest.config.utils import FlattenedControls
13
+ from everest.config.utils import get_samplers
15
14
 
16
15
 
17
16
  def _parse_controls(
18
- controls: FlattenedControls, random_seed: int
17
+ controls: list[EverestControl], random_seed: int
19
18
  ) -> tuple[dict[str, Any], list[dict[str, Any]] | None]:
20
- control_types = [VariableType[type_.upper()] for type_ in controls.types]
19
+ control_types = [
20
+ VariableType[type_.upper()]
21
+ for control in controls
22
+ for type_ in control.control_types
23
+ ]
24
+ initial_guesses = [
25
+ initial_guess
26
+ for control in controls
27
+ for initial_guess in control.initial_guesses
28
+ ]
29
+ samplers, sampler_indices = get_samplers(controls)
21
30
  ropt_variables: dict[str, Any] = {
22
31
  "types": None if all(item is None for item in control_types) else control_types,
23
- "variable_count": len(controls.initial_guesses),
24
- "lower_bounds": controls.lower_bounds,
25
- "upper_bounds": controls.upper_bounds,
32
+ "variable_count": len(initial_guesses),
33
+ "lower_bounds": [min_ for control in controls for min_ in control.min],
34
+ "upper_bounds": [max_ for control in controls for max_ in control.max],
26
35
  "perturbation_types": [
27
36
  PerturbationType[perturbation_type.upper()]
28
- for perturbation_type in controls.perturbation_types
37
+ for control in controls
38
+ for perturbation_type in control.perturbation_types
29
39
  ],
30
- "perturbation_magnitudes": controls.perturbation_magnitudes,
31
- "mask": controls.enabled,
40
+ "perturbation_magnitudes": [
41
+ perturbation_magnitude
42
+ for control in controls
43
+ for perturbation_magnitude in control.perturbation_magnitudes
44
+ ],
45
+ "mask": [enabled for control in controls for enabled in control.enabled],
32
46
  "seed": random_seed,
33
- "samplers": controls.sampler_indices,
47
+ "samplers": sampler_indices,
34
48
  }
35
49
 
36
50
  ropt_samplers = [
@@ -41,23 +55,22 @@ def _parse_controls(
41
55
  "options": {} if sampler.options is None else sampler.options,
42
56
  "shared": False if sampler.shared is None else sampler.shared,
43
57
  }
44
- for sampler in controls.samplers
58
+ for sampler in samplers
45
59
  ]
46
60
 
47
61
  return ropt_variables, ropt_samplers
48
62
 
49
63
 
50
64
  def _parse_objectives(
51
- objective_functions: list[ObjectiveFunctionConfig],
65
+ objective_functions: EverestObjectivesConfig,
52
66
  ) -> tuple[dict[str, Any], list[dict[str, Any]]]:
53
- weights: list[float] = []
67
+ weights: list[float] = [
68
+ 1.0 if weight is None else weight for weight in objective_functions.weights
69
+ ]
54
70
  function_estimator_indices: list[int] = []
55
71
  function_estimators: list = [] # type: ignore
56
72
 
57
- for objective in objective_functions:
58
- assert isinstance(objective.name, str)
59
- weights.append(objective.weight or 1.0)
60
-
73
+ for objective_type in objective_functions.objective_types:
61
74
  # If any objective specifies an objective type, we have to specify
62
75
  # function estimators in ropt to implement these types. This is done by
63
76
  # supplying a list of estimators and for each objective an index into
@@ -66,14 +79,14 @@ def _parse_objectives(
66
79
  (
67
80
  idx
68
81
  for idx, estimator in enumerate(function_estimators)
69
- if estimator["method"] == objective.type
82
+ if estimator["method"] == objective_type
70
83
  ),
71
84
  None,
72
85
  )
73
86
  # If not, make a new estimator:
74
87
  if function_estimator_idx is None:
75
88
  function_estimator_idx = len(function_estimators)
76
- function_estimators.append({"method": objective.type})
89
+ function_estimators.append({"method": objective_type})
77
90
  function_estimator_indices.append(function_estimator_idx)
78
91
 
79
92
  ropt_objectives: dict[str, Any] = {"weights": weights}
@@ -103,13 +116,13 @@ def _get_bounds(
103
116
 
104
117
  def _parse_input_constraints(
105
118
  input_constraints: list[InputConstraintConfig],
106
- controls: list[ControlConfig],
119
+ controls: list[EverestControl],
107
120
  ) -> dict[str, Any]:
108
121
  formatted_control_names = [
109
- name for config in controls for name in config.formatted_control_names
122
+ name for config in controls for name in config.input_keys
110
123
  ]
111
124
  formatted_control_names_dotdash = [
112
- name for config in controls for name in config.formatted_control_names_dotdash
125
+ name for config in controls for name in config.input_keys_dotdash
113
126
  ]
114
127
 
115
128
  def _get_control_index(name: str) -> int:
@@ -144,13 +157,26 @@ def _parse_input_constraints(
144
157
 
145
158
 
146
159
  def _parse_output_constraints(
147
- output_constraints: list[OutputConstraintConfig],
160
+ output_constraints: EverestConstraintsConfig | None,
148
161
  ) -> dict[str, Any]:
149
162
  if output_constraints:
150
- lower_bounds, upper_bounds = _get_bounds(output_constraints)
151
163
  return {
152
- "lower_bounds": lower_bounds,
153
- "upper_bounds": upper_bounds,
164
+ "lower_bounds": [
165
+ target if target is not None else lb
166
+ for lb, target in zip(
167
+ output_constraints.lower_bounds,
168
+ output_constraints.targets,
169
+ strict=False,
170
+ )
171
+ ],
172
+ "upper_bounds": [
173
+ target if target is not None else ub
174
+ for ub, target in zip(
175
+ output_constraints.upper_bounds,
176
+ output_constraints.targets,
177
+ strict=False,
178
+ )
179
+ ],
154
180
  }
155
181
  return {}
156
182
 
@@ -249,18 +275,16 @@ def _parse_optimization(
249
275
 
250
276
 
251
277
  def everest2ropt(
252
- controls: list[ControlConfig],
253
- objective_functions: list[ObjectiveFunctionConfig],
278
+ controls: list[EverestControl],
279
+ objective_functions: EverestObjectivesConfig,
254
280
  input_constraints: list[InputConstraintConfig],
255
- output_constraints: list[OutputConstraintConfig],
281
+ output_constraints: EverestConstraintsConfig | None,
256
282
  optimization: OptimizationConfig | None,
257
283
  model: ModelConfig,
258
284
  random_seed: int,
259
285
  optimization_output_dir: str,
260
286
  ) -> tuple[dict[str, Any], list[float]]:
261
- flattened_controls = FlattenedControls(controls)
262
-
263
- ropt_variables, ropt_samplers = _parse_controls(flattened_controls, random_seed)
287
+ ropt_variables, ropt_samplers = _parse_controls(controls, random_seed)
264
288
  ropt_objectives, ropt_function_estimators = _parse_objectives(objective_functions)
265
289
  ropt_linear_constraints = _parse_input_constraints(input_constraints, controls)
266
290
  ropt_nonlinear_constraints = _parse_output_constraints(output_constraints)
@@ -294,13 +318,11 @@ def everest2ropt(
294
318
  "realizations": ropt_realizations,
295
319
  "optimizer": ropt_optimizer,
296
320
  "names": {
297
- "variable": [
298
- name for config in controls for name in config.formatted_control_names
299
- ],
300
- "objective": [objective.name for objective in objective_functions],
301
- "nonlinear_constraint": [
302
- constraint.name for constraint in output_constraints
303
- ],
321
+ "variable": [name for config in controls for name in config.input_keys],
322
+ "objective": objective_functions.keys,
323
+ "nonlinear_constraint": output_constraints.keys
324
+ if output_constraints is not None
325
+ else [],
304
326
  "realization": model.realizations,
305
327
  },
306
328
  }
@@ -317,4 +339,8 @@ def everest2ropt(
317
339
  if ropt_samplers:
318
340
  ropt_config["samplers"] = ropt_samplers
319
341
 
320
- return ropt_config, flattened_controls.initial_guesses
342
+ return ropt_config, [
343
+ initial_guess
344
+ for control in controls
345
+ for initial_guess in control.initial_guesses
346
+ ]