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.
Files changed (82) hide show
  1. ert/__main__.py +94 -63
  2. ert/analysis/_es_update.py +11 -14
  3. ert/config/__init__.py +3 -2
  4. ert/config/_create_observation_dataframes.py +51 -375
  5. ert/config/_observations.py +483 -200
  6. ert/config/_read_summary.py +4 -5
  7. ert/config/ert_config.py +53 -80
  8. ert/config/everest_control.py +40 -39
  9. ert/config/everest_response.py +1 -13
  10. ert/config/field.py +0 -72
  11. ert/config/forward_model_step.py +17 -1
  12. ert/config/gen_data_config.py +14 -17
  13. ert/config/observation_config_migrations.py +821 -0
  14. ert/config/parameter_config.py +18 -28
  15. ert/config/parsing/__init__.py +0 -1
  16. ert/config/parsing/_parse_zonemap.py +45 -0
  17. ert/config/parsing/config_keywords.py +1 -1
  18. ert/config/parsing/config_schema.py +2 -8
  19. ert/config/parsing/observations_parser.py +2 -0
  20. ert/config/response_config.py +5 -23
  21. ert/config/rft_config.py +44 -19
  22. ert/config/summary_config.py +1 -13
  23. ert/config/surface_config.py +0 -57
  24. ert/dark_storage/compute/misfits.py +0 -42
  25. ert/dark_storage/endpoints/__init__.py +0 -2
  26. ert/dark_storage/endpoints/experiments.py +2 -5
  27. ert/dark_storage/json_schema/experiment.py +1 -2
  28. ert/field_utils/__init__.py +0 -2
  29. ert/field_utils/field_utils.py +1 -117
  30. ert/gui/ertwidgets/listeditbox.py +9 -1
  31. ert/gui/ertwidgets/models/ertsummary.py +20 -6
  32. ert/gui/ertwidgets/pathchooser.py +9 -1
  33. ert/gui/ertwidgets/stringbox.py +11 -3
  34. ert/gui/ertwidgets/textbox.py +10 -3
  35. ert/gui/ertwidgets/validationsupport.py +19 -1
  36. ert/gui/main_window.py +11 -6
  37. ert/gui/simulation/experiment_panel.py +1 -1
  38. ert/gui/simulation/run_dialog.py +11 -1
  39. ert/gui/tools/manage_experiments/export_dialog.py +4 -0
  40. ert/gui/tools/manage_experiments/manage_experiments_panel.py +1 -0
  41. ert/gui/tools/manage_experiments/storage_info_widget.py +5 -2
  42. ert/gui/tools/manage_experiments/storage_widget.py +18 -3
  43. ert/gui/tools/plot/data_type_proxy_model.py +1 -1
  44. ert/gui/tools/plot/plot_api.py +35 -27
  45. ert/gui/tools/plot/plot_widget.py +5 -0
  46. ert/gui/tools/plot/plot_window.py +4 -7
  47. ert/run_models/ensemble_experiment.py +1 -3
  48. ert/run_models/ensemble_smoother.py +1 -3
  49. ert/run_models/everest_run_model.py +12 -13
  50. ert/run_models/initial_ensemble_run_model.py +19 -22
  51. ert/run_models/model_factory.py +7 -7
  52. ert/run_models/multiple_data_assimilation.py +1 -3
  53. ert/sample_prior.py +12 -14
  54. ert/services/__init__.py +7 -3
  55. ert/services/_storage_main.py +59 -22
  56. ert/services/ert_server.py +186 -24
  57. ert/shared/version.py +3 -3
  58. ert/storage/local_ensemble.py +46 -115
  59. ert/storage/local_experiment.py +0 -16
  60. ert/utils/__init__.py +20 -0
  61. ert/warnings/specific_warning_handler.py +3 -2
  62. {ert-19.0.0rc4.dist-info → ert-20.0.0b0.dist-info}/METADATA +4 -51
  63. {ert-19.0.0rc4.dist-info → ert-20.0.0b0.dist-info}/RECORD +75 -80
  64. everest/bin/everest_script.py +5 -5
  65. everest/bin/kill_script.py +2 -2
  66. everest/bin/monitor_script.py +2 -2
  67. everest/bin/utils.py +4 -4
  68. everest/detached/everserver.py +6 -6
  69. everest/gui/everest_client.py +0 -6
  70. everest/gui/main_window.py +2 -2
  71. everest/util/__init__.py +1 -19
  72. ert/dark_storage/compute/__init__.py +0 -0
  73. ert/dark_storage/endpoints/compute/__init__.py +0 -0
  74. ert/dark_storage/endpoints/compute/misfits.py +0 -95
  75. ert/services/_base_service.py +0 -387
  76. ert/services/webviz_ert_service.py +0 -20
  77. ert/shared/storage/command.py +0 -38
  78. ert/shared/storage/extraction.py +0 -42
  79. {ert-19.0.0rc4.dist-info → ert-20.0.0b0.dist-info}/WHEEL +0 -0
  80. {ert-19.0.0rc4.dist-info → ert-20.0.0b0.dist-info}/entry_points.txt +0 -0
  81. {ert-19.0.0rc4.dist-info → ert-20.0.0b0.dist-info}/licenses/COPYING +0 -0
  82. {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
- )
@@ -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)
@@ -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)
@@ -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