Skip to content

Commit

Permalink
Add validation for uninitialized ensembles in manual update and evaluate
Browse files Browse the repository at this point in the history
experiment

This commit adds validation for the realizations specified by the user
when trying to run `manual_update` or `evaluate_experiment`. The
validator checks the selected ensemble if the specified realization(s)
exists. If not, the field becomes red and a warning is displayed.
The commit also disables the realization field until an ensemble is
selected.
  • Loading branch information
jonathan-eq committed Oct 17, 2024
1 parent 74e401e commit b029fee
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 10 deletions.
11 changes: 7 additions & 4 deletions src/ert/gui/simulation/evaluate_ensemble_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from ert.gui.simulation.experiment_config_panel import ExperimentConfigPanel
from ert.mode_definitions import EVALUATE_ENSEMBLE_MODE
from ert.run_models.evaluate_ensemble import EvaluateEnsemble
from ert.validation import RangeStringArgument
from ert.validation import EnsembleRealizationsArgument


@dataclass
Expand Down Expand Up @@ -47,9 +47,10 @@ def __init__(self, ensemble_size: int, run_path: str, notifier: ErtNotifier):
ActiveRealizationsModel(ensemble_size, show_default=False), # type: ignore
"config/simulation/active_realizations",
)
self._active_realizations_field.setValidator(
RangeStringArgument(ensemble_size),
self._realizations_validator = EnsembleRealizationsArgument(
self._ensemble_selector.selected_ensemble, max_value=ensemble_size
)
self._active_realizations_field.setValidator(self._realizations_validator)
self._realizations_from_fs()
layout.addRow("Active realizations", self._active_realizations_field)

Expand All @@ -68,7 +69,7 @@ def isConfigurationValid(self) -> bool:
return (
self._active_realizations_field.isValid()
and self._ensemble_selector.currentIndex() != -1
and bool(self._active_realizations_field.text())
and self._active_realizations_field.isValid()
)

def get_experiment_arguments(self) -> Arguments:
Expand All @@ -80,7 +81,9 @@ def get_experiment_arguments(self) -> Arguments:

def _realizations_from_fs(self) -> None:
ensemble = self._ensemble_selector.selected_ensemble
self._active_realizations_field.setEnabled(ensemble is not None)
if ensemble:
self._realizations_validator.set_ensemble(ensemble)
parameters = ensemble.get_realization_mask_with_parameters()
missing_responses = ~ensemble.get_realization_mask_with_responses()
failures = ~ensemble.get_realization_mask_without_failure()
Expand Down
14 changes: 8 additions & 6 deletions src/ert/gui/simulation/manual_update_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from ert.gui.simulation.experiment_config_panel import ExperimentConfigPanel
from ert.mode_definitions import MANUAL_UPDATE_MODE
from ert.run_models.manual_update import ManualUpdate
from ert.validation import ProperNameFormatArgument, RangeStringArgument
from ert.validation import EnsembleRealizationsArgument, ProperNameFormatArgument


@dataclass
Expand Down Expand Up @@ -72,14 +72,13 @@ def __init__(
ActiveRealizationsModel(ensemble_size, show_default=False), # type: ignore
"config/simulation/active_realizations",
)
self._active_realizations_field.setValidator(
RangeStringArgument(ensemble_size),
self._realizations_validator = EnsembleRealizationsArgument(
self._ensemble_selector.selected_ensemble, max_value=ensemble_size
)
self._active_realizations_field.setValidator(self._realizations_validator)
self._realizations_from_fs()
layout.addRow("Active realizations", self._active_realizations_field)

self.setLayout(layout)

self._active_realizations_field.getValidationSupport().validationChanged.connect(
self.simulationConfigurationChanged
)
Expand All @@ -88,12 +87,13 @@ def __init__(
self.simulationConfigurationChanged
)
self._ensemble_selector.currentIndexChanged.connect(self._realizations_from_fs)
self.setLayout(layout)

def isConfigurationValid(self) -> bool:
return (
self._active_realizations_field.isValid()
and self._ensemble_selector.currentIndex() != -1
and bool(self._active_realizations_field.text())
and self._active_realizations_field.isValid()
)

def get_experiment_arguments(self) -> Arguments:
Expand All @@ -106,7 +106,9 @@ def get_experiment_arguments(self) -> Arguments:

def _realizations_from_fs(self) -> None:
ensemble = self._ensemble_selector.selected_ensemble
self._active_realizations_field.setEnabled(ensemble is not None)
if ensemble:
self._realizations_validator.set_ensemble(ensemble)
parameters = ensemble.get_realization_mask_with_parameters()
responses = ensemble.get_realization_mask_with_responses()
mask = np.logical_and(parameters, responses)
Expand Down
2 changes: 2 additions & 0 deletions src/ert/validation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
from .proper_name_format_argument import ProperNameFormatArgument
from .range_string_argument import RangeStringArgument
from .rangestring import mask_to_rangestring, rangestring_to_list, rangestring_to_mask
from .realizations_in_ensemble_argument import EnsembleRealizationsArgument
from .runpath_argument import RunPathArgument
from .validation_status import ValidationStatus

__all__ = [
"ActiveRange",
"ArgumentDefinition",
"EnsembleRealizationsArgument",
"IntegerArgument",
"NumberListStringArgument",
"ProperNameArgument",
Expand Down
49 changes: 49 additions & 0 deletions src/ert/validation/realizations_in_ensemble_argument.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from typing import TYPE_CHECKING, Optional

from .range_string_argument import RangeStringArgument
from .rangestring import rangestring_to_list
from .validation_status import ValidationStatus

if TYPE_CHECKING:
from ert.storage import Ensemble


class EnsembleRealizationsArgument(RangeStringArgument):
UNINITIALIZED_REALIZATIONS_SPECIFIED = (
"The specified realization(s) %s are not found in selected ensemble."
)

def __init__(
self, ensemble: "Ensemble", max_value: Optional[int], **kwargs: bool
) -> None:
super().__init__(max_value, **kwargs)
self.__ensemble = ensemble

def set_ensemble(self, ensemble: "Ensemble") -> None:
self.__ensemble = ensemble

def validate(self, token: str) -> ValidationStatus:
if not token:
return ValidationStatus()

validation_status = super().validate(token)
if not validation_status:
return validation_status
attempted_realizations = rangestring_to_list(token)

invalid_realizations = []
initialized_realization_ids = self.__ensemble.is_initalized()
for realization in attempted_realizations:
if not realization in initialized_realization_ids:
invalid_realizations.append(realization)

if invalid_realizations:
validation_status.setFailed()
validation_status.addToMessage(
EnsembleRealizationsArgument.UNINITIALIZED_REALIZATIONS_SPECIFIED
% str(invalid_realizations)
)
return validation_status

validation_status.setValue(token)
return validation_status

0 comments on commit b029fee

Please sign in to comment.