14
14
from .parsing import ConfigValidationError , ErrorInfo
15
15
16
16
if TYPE_CHECKING :
17
- from ert .config import (
18
- ParameterConfig ,
19
- )
17
+ from ert .config import ParameterConfig
20
18
21
19
DESIGN_MATRIX_GROUP = "DESIGN_MATRIX"
22
20
@@ -28,10 +26,17 @@ class DesignMatrix:
28
26
default_sheet : str
29
27
30
28
def __post_init__ (self ) -> None :
31
- self .num_realizations : int | None = None
32
- self .active_realizations : list [bool ] | None = None
33
- self .design_matrix_df : pd .DataFrame | None = None
34
- self .parameter_configuration : dict [str , ParameterConfig ] | None = None
29
+ try :
30
+ (
31
+ self .active_realizations ,
32
+ self .design_matrix_df ,
33
+ self .parameter_configuration ,
34
+ ) = self .read_design_matrix ()
35
+ except (ValueError , AttributeError ) as exc :
36
+ raise ConfigValidationError .with_context (
37
+ f"Error reading design matrix { self .xls_filename } : { exc } " ,
38
+ str (self .xls_filename ),
39
+ ) from exc
35
40
36
41
@classmethod
37
42
def from_config_list (cls , config_list : list [str ]) -> DesignMatrix :
@@ -73,9 +78,60 @@ def from_config_list(cls, config_list: list[str]) -> DesignMatrix:
73
78
default_sheet = default_sheet ,
74
79
)
75
80
81
+ def merge_with_existing_parameters (
82
+ self , existing_parameters : list [ParameterConfig ]
83
+ ) -> tuple [list [ParameterConfig ], ParameterConfig | None ]:
84
+ """
85
+ This method merges the design matrix parameters with the existing parameters and
86
+ returns the new list of existing parameters, wherein we drop GEN_KW group having a full overlap with the design matrix group.
87
+ GEN_KW group that was dropped will acquire a new name from the design matrix group.
88
+ Additionally, the ParameterConfig which is the design matrix group is returned separately.
89
+
90
+ Args:
91
+ existing_parameters (List[ParameterConfig]): List of existing parameters
92
+
93
+ Raises:
94
+ ConfigValidationError: If there is a partial overlap between the design matrix group and any existing GEN_KW group
95
+
96
+ Returns:
97
+ tuple[List[ParameterConfig], ParameterConfig]: List of existing parameters and the dedicated design matrix group
98
+ """
99
+
100
+ new_param_config : list [ParameterConfig ] = []
101
+
102
+ design_parameter_group = self .parameter_configuration [DESIGN_MATRIX_GROUP ]
103
+ design_keys = []
104
+ if isinstance (design_parameter_group , GenKwConfig ):
105
+ design_keys = [e .name for e in design_parameter_group .transform_functions ]
106
+
107
+ design_group_added = False
108
+ for parameter_group in existing_parameters :
109
+ if not isinstance (parameter_group , GenKwConfig ):
110
+ new_param_config += [parameter_group ]
111
+ continue
112
+ existing_keys = [e .name for e in parameter_group .transform_functions ]
113
+ if set (existing_keys ) == set (design_keys ):
114
+ if design_group_added :
115
+ raise ConfigValidationError (
116
+ "Multiple overlapping groups with design matrix found in existing parameters!\n "
117
+ f"{ design_parameter_group .name } and { parameter_group .name } "
118
+ )
119
+
120
+ design_parameter_group .name = parameter_group .name
121
+ design_group_added = True
122
+ elif set (design_keys ) & set (existing_keys ):
123
+ raise ConfigValidationError (
124
+ "Overlapping parameter names found in design matrix!\n "
125
+ f"{ DESIGN_MATRIX_GROUP } :{ design_keys } \n { parameter_group .name } :{ existing_keys } "
126
+ "\n They need to much exactly or not at all."
127
+ )
128
+ else :
129
+ new_param_config += [parameter_group ]
130
+ return new_param_config , design_parameter_group
131
+
76
132
def read_design_matrix (
77
133
self ,
78
- ) -> None :
134
+ ) -> tuple [ list [ bool ], pd . DataFrame , dict [ str , ParameterConfig ]] :
79
135
# Read the parameter names (first row) as strings to prevent pandas from modifying them.
80
136
# This ensures that duplicate or empty column names are preserved exactly as they appear in the Excel sheet.
81
137
# By doing this, we can properly validate variable names, including detecting duplicates or missing names.
@@ -139,11 +195,11 @@ def read_design_matrix(
139
195
[[DESIGN_MATRIX_GROUP ], design_matrix_df .columns ]
140
196
)
141
197
reals = design_matrix_df .index .tolist ()
142
- self . num_realizations = len ( reals )
143
- self . active_realizations = [x in reals for x in range (max (reals ) + 1 )]
144
-
145
- self . design_matrix_df = design_matrix_df
146
- self . parameter_configuration = parameter_configuration
198
+ return (
199
+ [x in reals for x in range (max (reals ) + 1 )],
200
+ design_matrix_df ,
201
+ parameter_configuration ,
202
+ )
147
203
148
204
@staticmethod
149
205
def _read_excel (
0 commit comments