|
27 | 27 | "ValidationTask", |
28 | 28 | "CheckModel", |
29 | 29 | "CheckProblemConfig", |
| 30 | + "CheckMeasuredObservablesDefined", |
| 31 | + "CheckOverridesMatchPlaceholders", |
| 32 | + "CheckMeasuredExperimentsDefined", |
| 33 | + "CheckMeasurementModelId", |
30 | 34 | "CheckPosLogMeasurements", |
31 | 35 | "CheckValidConditionTargets", |
32 | 36 | "CheckUniquePrimaryKeys", |
@@ -826,8 +830,39 @@ def run(self, problem: Problem) -> ValidationIssue | None: |
826 | 830 | return None |
827 | 831 |
|
828 | 832 |
|
829 | | -# TODO: check that Measurements model IDs match the available ones |
830 | | -# https://github.com/PEtab-dev/libpetab-python/issues/392 |
| 833 | +class CheckMeasurementModelId(ValidationTask): |
| 834 | + """Validate model IDs of measurements.""" |
| 835 | + |
| 836 | + def run(self, problem: Problem) -> ValidationIssue | None: |
| 837 | + messages = [] |
| 838 | + available_models = {m.model_id for m in problem.models} |
| 839 | + |
| 840 | + for measurement in problem.measurements: |
| 841 | + if not measurement.model_id: |
| 842 | + if len(available_models) < 2: |
| 843 | + # If there is only one model, it is not required to specify |
| 844 | + # the model ID in the measurement table. |
| 845 | + continue |
| 846 | + |
| 847 | + messages.append( |
| 848 | + f"Measurement `{measurement}' does not have a model ID, " |
| 849 | + "but there are multiple models available. " |
| 850 | + "Please specify the model ID in the measurement table." |
| 851 | + ) |
| 852 | + continue |
| 853 | + |
| 854 | + if measurement.model_id not in available_models: |
| 855 | + messages.append( |
| 856 | + f"Measurement `{measurement}' has model ID " |
| 857 | + f"`{measurement.model_id}' which does not match " |
| 858 | + "any of the available models: " |
| 859 | + f"{available_models}." |
| 860 | + ) |
| 861 | + |
| 862 | + if messages: |
| 863 | + return ValidationError("\n".join(messages)) |
| 864 | + |
| 865 | + return None |
831 | 866 |
|
832 | 867 |
|
833 | 868 | def get_valid_parameters_for_parameter_table( |
@@ -1068,6 +1103,7 @@ def get_placeholders( |
1068 | 1103 | CheckProblemConfig(), |
1069 | 1104 | CheckModel(), |
1070 | 1105 | CheckUniquePrimaryKeys(), |
| 1106 | + CheckMeasurementModelId(), |
1071 | 1107 | CheckMeasuredObservablesDefined(), |
1072 | 1108 | CheckPosLogMeasurements(), |
1073 | 1109 | CheckOverridesMatchPlaceholders(), |
|
0 commit comments