Skip to content

Commit

Permalink
feat(bc): add group parameter to bc after v8.7
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinBelthle committed Jan 4, 2024
1 parent 49a6d7a commit 9de25d6
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 45 deletions.
2 changes: 1 addition & 1 deletion antarest/core/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ def __init__(self, message: str) -> None:
super().__init__(HTTPStatus.BAD_REQUEST, message)


class IncoherentConstraintMatrixTerm(HTTPException):
class InvalidFieldForVersionError(HTTPException):
def __init__(self, message: str) -> None:
super().__init__(HTTPStatus.BAD_REQUEST, message)

Expand Down
106 changes: 66 additions & 40 deletions antarest/study/business/binding_constraint_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
ConstraintAlreadyExistError,
ConstraintIdNotFoundError,
DuplicateConstraintName,
IncoherentConstraintMatrixTerm,
InvalidConstraintName,
InvalidFieldForVersionError,
MissingDataError,
NoBindingConstraintError,
NoConstraintError,
Expand All @@ -31,6 +31,7 @@
)
from antarest.study.storage.variantstudy.model.command.create_binding_constraint import (
BindingConstraintMatrices,
BindingConstraintProperties,
BindingConstraintProperties870,
CreateBindingConstraint,
)
Expand Down Expand Up @@ -59,20 +60,24 @@ class UpdateBindingConstProps(BaseModel):
value: Any


class BindingConstraintWithName(
BindingConstraintMatrices,
BindingConstraintProperties870,
):
class BindingConstraintCreation(BindingConstraintMatrices, BindingConstraintProperties870):
name: str
coeffs: Dict[str, List[float]]


class BindingConstraintConfig(BindingConstraintProperties870):
class BindingConstraintConfig(BindingConstraintProperties):
id: str
name: str
constraints: Optional[List[ConstraintTermDTO]]


class BindingConstraintConfig870(BindingConstraintConfig):
group: Optional[str] = None


BindingConstraintConfigType = Union[BindingConstraintConfig870, BindingConstraintConfig]


class BindingConstraintManager:
def __init__(
self,
Expand All @@ -81,7 +86,7 @@ def __init__(
self.storage_service = storage_service

@staticmethod
def parse_constraint(key: str, value: str, char: str, new_config: BindingConstraintConfig) -> bool:
def parse_constraint(key: str, value: str, char: str, new_config: BindingConstraintConfigType) -> bool:
split = key.split(char)
if len(split) == 2:
value1 = split[0]
Expand Down Expand Up @@ -117,20 +122,24 @@ def parse_constraint(key: str, value: str, char: str, new_config: BindingConstra
return False

@staticmethod
def process_constraint(
constraint_value: Dict[str, Any],
) -> BindingConstraintConfig:
new_config: BindingConstraintConfig = BindingConstraintConfig(
id=constraint_value["id"],
name=constraint_value["name"],
enabled=constraint_value["enabled"],
time_step=constraint_value["type"],
operator=constraint_value["operator"],
comments=constraint_value.get("comments", None),
filter_year_by_year=constraint_value.get("filter-year-by-year", ""),
filter_synthesis=constraint_value.get("filter-synthesis", ""),
constraints=None,
)
def process_constraint(constraint_value: Dict[str, Any], version: int) -> BindingConstraintConfigType:
args = {
"id": constraint_value["id"],
"name": constraint_value["name"],
"enabled": constraint_value["enabled"],
"time_step": constraint_value["type"],
"operator": constraint_value["operator"],
"comments": constraint_value.get("comments", None),
"filter_year_by_year": constraint_value.get("filter-year-by-year", ""),
"filter_synthesis": constraint_value.get("filter-synthesis", ""),
"constraints": None,
}
if version < 870:
new_config: BindingConstraintConfigType = BindingConstraintConfig(**args)
else:
args["group"] = constraint_value.get("group")
new_config = BindingConstraintConfig870(**args)

for key, value in constraint_value.items():
if BindingConstraintManager.parse_constraint(key, value, "%", new_config):
continue
Expand All @@ -140,7 +149,7 @@ def process_constraint(

@staticmethod
def constraints_to_coeffs(
constraint: BindingConstraintConfig,
constraint: BindingConstraintConfigType,
) -> Dict[str, List[float]]:
coeffs: Dict[str, List[float]] = {}
if constraint.constraints is not None:
Expand All @@ -154,49 +163,50 @@ def constraints_to_coeffs(

def get_binding_constraint(
self, study: Study, constraint_id: Optional[str]
) -> Union[BindingConstraintConfig, List[BindingConstraintConfig], None]:
) -> Union[BindingConstraintConfigType, List[BindingConstraintConfigType], None]:
storage_service = self.storage_service.get_storage(study)
file_study = storage_service.get_raw(study)
config = file_study.tree.get(["input", "bindingconstraints", "bindingconstraints"])
config_values = list(config.values())
study_version = int(study.version)
if constraint_id:
try:
index = [value["id"] for value in config_values].index(constraint_id)
config_value = config_values[index]
return BindingConstraintManager.process_constraint(config_value)
return BindingConstraintManager.process_constraint(config_value, study_version)
except ValueError:
return None

binding_constraint = []
for config_value in config_values:
new_config = BindingConstraintManager.process_constraint(config_value)
new_config = BindingConstraintManager.process_constraint(config_value, study_version)
binding_constraint.append(new_config)
return binding_constraint

def create_binding_constraint(
self,
study: Study,
data: BindingConstraintWithName,
data: BindingConstraintCreation,
) -> None:
bc_id = transform_name_to_id(data.name)

if not bc_id:
raise InvalidConstraintName(f"Invalid binding constraint name: {data.name}.")

file_study = self.storage_service.get_storage(study).get_raw(study)
binding_constraints = self.get_binding_constraint(study, None)
existing_ids = {bc.id for bc in binding_constraints} # type: ignore

if bc_id in existing_ids:
if bc_id in {bc.id for bc in self.get_binding_constraint(study, None)}: # type: ignore
raise DuplicateConstraintName(f"A binding constraint with the same name already exists: {bc_id}.")

if int(study.version) >= 870:
version = int(study.version)
if data.group and version < 870:
raise InvalidFieldForVersionError(
f"You cannot specify a group as your study version is older than v8.7: {data.group}"
)

if version >= 870:
if data.values is not None:
raise IncoherentConstraintMatrixTerm("You cannot fill 'values' as it refers to the matrix before v8.7")
raise InvalidFieldForVersionError("You cannot fill 'values' as it refers to the matrix before v8.7")
elif any([data.equal_term_matrix, data.less_term_matrix, data.greater_term_matrix]):
raise IncoherentConstraintMatrixTerm(
"You cannot fill a 'matrix_term' as these values refer to v8.7+ studies"
)
raise InvalidFieldForVersionError("You cannot fill a 'matrix_term' as these values refer to v8.7+ studies")

command = CreateBindingConstraint(
name=data.name,
Expand All @@ -211,8 +221,10 @@ def create_binding_constraint(
filter_year_by_year=data.filter_year_by_year,
filter_synthesis=data.filter_synthesis,
comments=data.comments or "",
group=data.group,
command_context=self.storage_service.variant_study_service.command_factory.command_context,
)
file_study = self.storage_service.get_storage(study).get_raw(study)
execute_or_add_commands(study, file_study, [command], self.storage_service)

def update_binding_constraint(
Expand All @@ -223,7 +235,9 @@ def update_binding_constraint(
) -> None:
file_study = self.storage_service.get_storage(study).get_raw(study)
constraint = self.get_binding_constraint(study, binding_constraint_id)
if not isinstance(constraint, BindingConstraintConfig):
if not isinstance(constraint, BindingConstraintConfig) and not isinstance(
constraint, BindingConstraintConfig870
):
raise NoBindingConstraintError(study.id)

args = {
Expand All @@ -238,10 +252,18 @@ def update_binding_constraint(
"command_context": self.storage_service.variant_study_service.command_factory.command_context,
}

study_version = int(study.version)
if data.key == "group" and data.value is not None:
if study_version < 870:
raise InvalidFieldForVersionError(
f"You cannot specify a group as your study version is older than v8.7: {data.value}"
)
args["group"] = data.value

if data.key == "time_step" and data.value != constraint.time_step:
# The user changed the time step, we need to update the matrix accordingly
args = BindingConstraintManager.replace_matrices_according_to_frequency_and_version(
data, int(study.version), args
data, study_version, args
)

command = UpdateBindingConstraint(**args)
Expand Down Expand Up @@ -295,7 +317,9 @@ def add_new_constraint_term(
) -> None:
file_study = self.storage_service.get_storage(study).get_raw(study)
constraint = self.get_binding_constraint(study, binding_constraint_id)
if not isinstance(constraint, BindingConstraintConfig):
if not isinstance(constraint, BindingConstraintConfig) and not isinstance(
constraint, BindingConstraintConfig870
):
raise NoBindingConstraintError(study.id)

if constraint_term.data is None:
Expand Down Expand Up @@ -341,7 +365,9 @@ def update_constraint_term(
) -> None:
file_study = self.storage_service.get_storage(study).get_raw(study)
constraint = self.get_binding_constraint(study, binding_constraint_id)
if not isinstance(constraint, BindingConstraintConfig):
if not isinstance(constraint, BindingConstraintConfig) and not isinstance(
constraint, BindingConstraintConfig870
):
raise NoBindingConstraintError(study.id)

constraints = constraint.constraints
Expand Down
4 changes: 3 additions & 1 deletion antarest/study/business/table_mode_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,9 @@ def set_table_data(

if current_binding:
col_values = columns.dict(exclude_none=True)
current_binding_dto = BindingConstraintManager.process_constraint(current_binding)
current_binding_dto = BindingConstraintManager.process_constraint(
current_binding, int(study.version)
)

commands.append(
UpdateBindingConstraint(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ def apply_binding_constraint(
equal_term_matrix: Optional[Union[List[List[MatrixData]], str]],
filter_year_by_year: Optional[str] = None,
filter_synthesis: Optional[str] = None,
group: Optional[str] = None,
) -> CommandOutput:
version = study_data.config.version
binding_constraints[new_key] = {
Expand All @@ -37,6 +38,8 @@ def apply_binding_constraint(
"type": freq.value,
"operator": operator.value,
}
if group:
binding_constraints[new_key]["group"] = group
if version >= 830:
if filter_year_by_year:
binding_constraints[new_key]["filter-year-by-year"] = filter_year_by_year
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"AbstractBindingConstraintCommand",
"CreateBindingConstraint",
"check_matrix_values",
"BindingConstraintProperties",
"BindingConstraintProperties870",
"BindingConstraintMatrices",
)
Expand Down Expand Up @@ -80,7 +81,7 @@ class BindingConstraintProperties(BaseModel, extra=Extra.forbid):


class BindingConstraintProperties870(BindingConstraintProperties):
group: str = "default"
group: Optional[str] = None


class BindingConstraintMatrices(BaseModel, extra=Extra.forbid):
Expand Down Expand Up @@ -124,6 +125,8 @@ def to_dto(self) -> CommandDTO:
"filter_year_by_year": self.filter_year_by_year,
"filter_synthesis": self.filter_synthesis,
}
if self.group:
args["group"] = self.group
for matrix_name in ["values", "less_term_matrix", "greater_term_matrix", "equal_term_matrix"]:
matrix_attr = getattr(self, matrix_name, None)
if matrix_attr is not None:
Expand Down Expand Up @@ -221,6 +224,7 @@ def _apply(self, study_data: FileStudy) -> CommandOutput:
self.equal_term_matrix,
self.filter_year_by_year,
self.filter_synthesis,
self.group,
)

def to_dto(self) -> CommandDTO:
Expand Down Expand Up @@ -248,6 +252,9 @@ def match(self, other: ICommand, equal: bool = False) -> bool:
and self.less_term_matrix == other.less_term_matrix
and self.greater_term_matrix == other.greater_term_matrix
and self.equal_term_matrix == other.equal_term_matrix
and self.group == other.group
and self.filter_synthesis == other.filter_synthesis
and self.filter_year_by_year == other.filter_year_by_year
)

def _create_diff(self, other: "ICommand") -> List["ICommand"]:
Expand All @@ -266,6 +273,7 @@ def _create_diff(self, other: "ICommand") -> List["ICommand"]:
"filter_synthesis": other.filter_synthesis,
"comments": other.comments,
"command_context": other.command_context,
"group": other.group,
}
for matrix_name in ["values", "less_term_matrix", "equal_term_matrix", "greater_term_matrix"]:
self_matrix = self.__getattribute__(matrix_name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ def _apply(self, study_data: FileStudy) -> CommandOutput:
self.equal_term_matrix,
self.filter_year_by_year,
self.filter_synthesis,
self.group,
)

def to_dto(self) -> CommandDTO:
Expand Down Expand Up @@ -106,6 +107,9 @@ def match(self, other: ICommand, equal: bool = False) -> bool:
and self.greater_term_matrix == other.greater_term_matrix
and self.equal_term_matrix == other.equal_term_matrix
and self.comments == other.comments
and self.group == other.group
and self.filter_synthesis == other.filter_synthesis
and self.filter_year_by_year == other.filter_year_by_year
)

def _create_diff(self, other: "ICommand") -> List["ICommand"]:
Expand Down
4 changes: 2 additions & 2 deletions antarest/study/web/study_data_blueprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
from antarest.study.business.areas.st_storage_management import *
from antarest.study.business.areas.thermal_management import *
from antarest.study.business.binding_constraint_management import (
BindingConstraintWithName,
BindingConstraintCreation,
ConstraintTermDTO,
UpdateBindingConstProps,
)
Expand Down Expand Up @@ -868,7 +868,7 @@ def update_binding_constraint(
response_model=None,
)
def create_binding_constraint(
uuid: str, data: BindingConstraintWithName, current_user: JWTUser = Depends(auth.get_current_user)
uuid: str, data: BindingConstraintCreation, current_user: JWTUser = Depends(auth.get_current_user)
) -> None:
logger.info(
f"Creating a new binding constraint for study {uuid}",
Expand Down

0 comments on commit 9de25d6

Please sign in to comment.