From c2065034b5511484601710f4d0c0100f1edcd915 Mon Sep 17 00:00:00 2001 From: Jonathan Karlsen Date: Wed, 18 Dec 2024 14:16:36 +0100 Subject: [PATCH] init --- src/ert/dark_storage/endpoints/experiments.py | 4 +- src/ert/dark_storage/endpoints/records.py | 4 +- src/ert/gui/ertwidgets/ensembleselector.py | 38 ++++++++++++++++++- src/ert/gui/tools/plot/plot_api.py | 2 +- src/ert/storage/local_ensemble.py | 7 +++- src/ert/storage/local_experiment.py | 20 ++++++++++ src/ert/storage/local_storage.py | 14 ++++--- 7 files changed, 78 insertions(+), 11 deletions(-) diff --git a/src/ert/dark_storage/endpoints/experiments.py b/src/ert/dark_storage/endpoints/experiments.py index d0f61fe03d6..e41c50082af 100644 --- a/src/ert/dark_storage/endpoints/experiments.py +++ b/src/ert/dark_storage/endpoints/experiments.py @@ -22,7 +22,9 @@ def get_experiments( js.ExperimentOut( id=experiment.id, name=experiment.name, - ensemble_ids=[ens.id for ens in experiment.ensembles], + ensemble_ids=[ + ens.id for ens in experiment.ensembles if experiment.is_valid() + ], priors=create_priors(experiment), userdata={}, ) diff --git a/src/ert/dark_storage/endpoints/records.py b/src/ert/dark_storage/endpoints/records.py index 923968a60e2..d7800dc6ab9 100644 --- a/src/ert/dark_storage/endpoints/records.py +++ b/src/ert/dark_storage/endpoints/records.py @@ -124,8 +124,8 @@ def get_ensemble_responses( response_names_with_observations = set() observations = ensemble.experiment.observations - - if len(ensemble.has_data()) == 0: + print(f"TRYING TO GET_ENSEMBLE_RESPONSES for {ensemble.name}") + if not ensemble.experiment.is_valid() or len(ensemble.has_data()) == 0: return {} for ( diff --git a/src/ert/gui/ertwidgets/ensembleselector.py b/src/ert/gui/ertwidgets/ensembleselector.py index 62926ddf332..1ce69e65a4f 100644 --- a/src/ert/gui/ertwidgets/ensembleselector.py +++ b/src/ert/gui/ertwidgets/ensembleselector.py @@ -7,6 +7,7 @@ from qtpy.QtWidgets import QComboBox from ert.gui.ertnotifier import ErtNotifier +from ert.storage.local_ensemble import LocalEnsemble from ert.storage.realization_storage_state import RealizationStorageState if TYPE_CHECKING: @@ -22,6 +23,7 @@ def __init__( update_ert: bool = True, show_only_undefined: bool = False, show_only_no_children: bool = False, + show_only_with_valid_experiment: bool = False, ): super().__init__() self.notifier = notifier @@ -36,6 +38,7 @@ def __init__( # if the ensemble has not been used in an update, as that would # invalidate the result self._show_only_no_children = show_only_no_children + self._show_only_with_valid_experiment = show_only_with_valid_experiment self.setSizeAdjustPolicy(QComboBox.AdjustToContents) self.setEnabled(False) @@ -57,7 +60,16 @@ def __init__( @property def selected_ensemble(self) -> Ensemble: - return self.itemData(self.currentIndex()) + print("GETTING SELECTED_ENSEMBLE") + itemData: LocalEnsemble = self.itemData(self.currentIndex()) + print(f"{itemData.experiment.is_valid()=}") + return itemData + + def get_selected_ensemble(self) -> Ensemble: + print("GETTING SELECTED_ENSEMBLE") + itemData: LocalEnsemble = self.itemData(self.currentIndex()) + print(f"{itemData.experiment.is_valid()=}") + return itemData def populate(self) -> None: block = self.blockSignals(True) @@ -68,9 +80,27 @@ def populate(self) -> None: self.setEnabled(True) for ensemble in self._ensemble_list(): + model = self.model() self.addItem( f"{ensemble.experiment.name} : {ensemble.name}", userData=ensemble ) + if ( + self._show_only_with_valid_experiment + and not ensemble.experiment.is_valid() + ): + print( + f"FOUND INVALID EXPERIMENT {ensemble.experiment_id} FOR ENSEMBLE {ensemble.name}" + ) + index = self.count() - 1 + model_item = model.item(index) + model_item.setFlags( + model_item.flags() + & ~Qt.ItemFlag.ItemIsEnabled + & ~Qt.ItemFlag.ItemIsSelectable + ) + self.setItemData( + index, "This ensemble is invalid", Qt.ItemDataRole.ToolTipRole + ) current_index = self.findData( self.notifier.current_ensemble, Qt.ItemDataRole.UserRole @@ -84,6 +114,7 @@ def populate(self) -> None: def _ensemble_list(self) -> Iterable[Ensemble]: if self._show_only_undefined: + print("JONAK1") ensembles = ( ensemble for ensemble in self.notifier.storage.ensembles @@ -95,6 +126,9 @@ def _ensemble_list(self) -> Iterable[Ensemble]: else: ensembles = self.notifier.storage.ensembles ensemble_list = list(ensembles) + if self._show_only_with_valid_experiment: + print("FILTERED") + ensemble_list = [ens for ens in ensemble_list if ens.experiment.is_valid()] if self._show_only_no_children: parents = [ ens.parent for ens in self.notifier.storage.ensembles if ens.parent @@ -103,7 +137,9 @@ def _ensemble_list(self) -> Iterable[Ensemble]: return sorted(ensemble_list, key=lambda x: x.started_at, reverse=True) def _on_current_index_changed(self, index: int) -> None: + print("ON CURRENT INDEX CHANGED") self.notifier.set_current_ensemble(self.itemData(index)) def _on_global_current_ensemble_changed(self, data: Ensemble | None) -> None: + print("ON GLOBAL CURRENT ENSEMBLE CHANGED") self.setCurrentIndex(max(self.findData(data, Qt.ItemDataRole.UserRole), 0)) diff --git a/src/ert/gui/tools/plot/plot_api.py b/src/ert/gui/tools/plot/plot_api.py index b76ca97051b..7e112e3fc28 100644 --- a/src/ert/gui/tools/plot/plot_api.py +++ b/src/ert/gui/tools/plot/plot_api.py @@ -112,7 +112,7 @@ def all_data_type_keys(self) -> list[PlotApiKeyDefinition]: f"/experiments/{experiment['id']}/ensembles", timeout=self._timeout ) self._check_response(response) - + print(f"{experiment=}") for ensemble in response.json(): response = client.get( f"/ensembles/{ensemble['id']}/responses", timeout=self._timeout diff --git a/src/ert/storage/local_ensemble.py b/src/ert/storage/local_ensemble.py index 5c10872b57f..d9f4dc9ab6e 100644 --- a/src/ert/storage/local_ensemble.py +++ b/src/ert/storage/local_ensemble.py @@ -92,6 +92,7 @@ def create_realization_dir(realization: int) -> Path: return self._path / f"realization-{realization}" self._realization_dir = create_realization_dir + self.has_valid_experiment: bool | None = None @classmethod def create( @@ -406,7 +407,11 @@ def get_ensemble_state(self) -> list[set[RealizationStorageState]]: states : list of RealizationStorageState list of realization states. """ - + if not self.experiment.is_valid(): + logger.warning( + f"Could not get ensemble state for ensemble ({self.id}) due to invalid experiment ({self.experiment_id}): {self.experiment.error_message}" + ) + return [] response_configs = self.experiment.response_configuration def _parameters_exist_for_realization(realization: int) -> bool: diff --git a/src/ert/storage/local_experiment.py b/src/ert/storage/local_experiment.py index 39612949b10..efd28139472 100644 --- a/src/ert/storage/local_experiment.py +++ b/src/ert/storage/local_experiment.py @@ -75,6 +75,26 @@ def __init__( self._index = _Index.model_validate_json( (path / "index.json").read_text(encoding="utf-8") ) + self._validate_files() + + def _validate_files(self) -> None: + self.valid_parameters = (self._path / self._parameter_file).exists() + self.valid_responses = (self._path / self._responses_file).exists() + self.valid_metadata = (self._path / self._metadata_file).exists() + + def is_valid(self) -> bool: + return self.valid_parameters and self.valid_responses and self.valid_metadata + + @property + def error_message(self) -> str: + errors = [] + if not self.valid_parameters: + errors.append("Parameter file is missing") + if not self.valid_responses: + errors.append("Responses file is missing") + if not self.valid_metadata: + errors.append("Metadata file is missing") + return "\n".join(errors) @classmethod def create( diff --git a/src/ert/storage/local_storage.py b/src/ert/storage/local_storage.py index 7f75d449293..e31854b549f 100644 --- a/src/ert/storage/local_storage.py +++ b/src/ert/storage/local_storage.py @@ -226,11 +226,15 @@ def _load_ensembles(self) -> dict[UUID, LocalEnsemble]: } def _load_experiments(self) -> dict[UUID, LocalExperiment]: - experiment_ids = {ens.experiment_id for ens in self._ensembles.values()} - return { - exp_id: LocalExperiment(self, self._experiment_path(exp_id), self.mode) - for exp_id in experiment_ids - } + experiments = {} + for ens in self._ensembles.values(): + experiment = LocalExperiment( + self, self._experiment_path(ens.experiment_id), self.mode + ) + ens.has_valid_experiment = experiment.is_valid() + experiments[ens.experiment_id] = experiment + + return experiments def _ensemble_path(self, ensemble_id: UUID) -> Path: return self.path / self.ENSEMBLES_PATH / str(ensemble_id)