Skip to content

Commit

Permalink
Merge pull request #105 from Deltares/feature/DEI-148-Fix-remaining-p…
Browse files Browse the repository at this point in the history
…ylint-warnings

DEI-148 fix remaining pylint warnings
  • Loading branch information
HiddeElzinga authored May 31, 2024
2 parents 6265546 + ba7db1f commit 18e85d9
Show file tree
Hide file tree
Showing 84 changed files with 1,417 additions and 1,199 deletions.
12 changes: 7 additions & 5 deletions decoimpact/business/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from decoimpact.crosscutting.i_logger import ILogger
from decoimpact.data.api.i_data_access_layer import IDataAccessLayer
from decoimpact.data.api.i_model_data import IModelData
from decoimpact.data.api.output_file_settings import OutputFileSettings


class Application:
Expand Down Expand Up @@ -93,12 +94,13 @@ def run(self, input_path: Path):

# write output file
if model.status == _ModelStatus.FINALIZED:
settings = OutputFileSettings(
self.APPLICATION_NAME, self.APPLICATION_VERSION
)
settings.variables_to_save = model_data.output_variables

self._da_layer.write_output_file(
model.output_dataset,
model_data.output_path,
model_data.output_variables,
self.APPLICATION_VERSION,
self.APPLICATION_NAME,
model.output_dataset, model_data.output_path, settings
)

except Exception as exc: # pylint: disable=broad-except
Expand Down
74 changes: 48 additions & 26 deletions decoimpact/business/entities/rule_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,36 +305,13 @@ def _process_by_multi_cell(
ref_var = value_arrays[_np.argmax(len_dims)]
for ind_vars, enough_dims in enumerate(most_dims_bool):
if not enough_dims:
# Let the user know which variables will be broadcast to all dimensions
var_orig = value_arrays[ind_vars]
dims_orig = var_orig.dims
dims_result = ref_var.dims
dims_diff = list(str(x) for x in dims_result if x not in dims_orig)
str_dims_broadcasted = ",".join(dims_diff)
logger.log_info(
f"""Variable {var_orig.name} will be expanded to the following \
dimensions: {str_dims_broadcasted} """
value_arrays[ind_vars] = self._expand_dimensions_of_variable(
var_orig, ref_var, logger
)
# perform the broadcast

var_broadcasted = _xr.broadcast(var_orig, ref_var)[0]
# Make sure the dimensions are in the same order
value_arrays[ind_vars] = var_broadcasted.transpose(*ref_var.dims)

# Check if all variables now have the same dimensions
for val_index in range(len(value_arrays) - 1):
var1 = value_arrays[val_index]
var2 = value_arrays[val_index + 1]
diff = set(var1.dims) ^ set(var2.dims)

# If the variables with the most dimensions have different dimensions,
# stop the calculation
if len(diff) != 0:
raise NotImplementedError(
f"Can not execute rule {rule.name} with variables with different \
dimensions. Variable {var1.name} with dimensions:{var1.dims} is \
different than {var2.name} with dimensions:{var2.dims}"
)
self._check_variable_dimensions(value_arrays, rule)

result_variable = _np.zeros_like(ref_var.to_numpy())
cell_values = {}
Expand Down Expand Up @@ -370,3 +347,48 @@ def _get_variable_by_name(
f"Key {name} was not found in input datasets or "
"in calculated output dataset.",
)

def _check_variable_dimensions(
self, value_arrays: List[_xr.DataArray], rule: IMultiCellBasedRule
):
for val_index in range(len(value_arrays) - 1):
var1 = value_arrays[val_index]
var2 = value_arrays[val_index + 1]
diff = set(var1.dims) ^ set(var2.dims)

# If the variables with the most dimensions have different dimensions,
# stop the calculation
if len(diff) != 0:
raise NotImplementedError(
f"Can not execute rule {rule.name} with variables with different \
dimensions. Variable {var1.name} with dimensions:{var1.dims} is \
different than {var2.name} with dimensions:{var2.dims}"
)

def _expand_dimensions_of_variable(
self, var_orig: _xr.DataArray, ref_var: _xr.DataArray, logger: ILogger
):
"""Creates a new data-array with the values of the var_org expanded to
include all dimensions of the ref_var
Args:
var_orig (_xr.DataArray): variable to expand with extra dimensions
ref_var (_xr.DataArray): reference variable to synchronize the
dimensions with
logger (ILogger): logger for logging messages
"""
# Let the user know which variables will be broadcast to all dimensions
dims_orig = var_orig.dims
dims_result = ref_var.dims
dims_diff = list(str(x) for x in dims_result if x not in dims_orig)
str_dims_broadcasted = ",".join(dims_diff)
logger.log_info(
f"""Variable {var_orig.name} will be expanded to the following \
dimensions: {str_dims_broadcasted} """
)

# perform the broadcast
var_broadcasted = _xr.broadcast(var_orig, ref_var)[0]

# Make sure the dimensions are in the same order
return var_broadcasted.transpose(*ref_var.dims)
24 changes: 10 additions & 14 deletions decoimpact/business/entities/rules/axis_filter_rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,34 +21,30 @@


class AxisFilterRule(RuleBase, IArrayBasedRule):

"""Implementation for the layer filter rule"""
"""Implementation for the axis filter rule"""

def __init__(
self,
name: str,
input_variable_names: List[str],
layer_number: int,
element_index: int,
axis_name: str,
output_variable_name: str = "output",
description: str = "",
):
super().__init__(name, input_variable_names, output_variable_name, description)
self._layer_number = layer_number
super().__init__(name, input_variable_names)
self._element_index = element_index
self._axis_name = axis_name

@property
def layer_number(self) -> int:
"""Layer number property"""
return self._layer_number
def element_index(self) -> int:
"""Value index of the provided axis to filter on"""
return self._element_index

@property
def axis_name(self) -> str:
"""Layer number property"""
return self._axis_name

def execute(self, value_array: _xr.DataArray, logger: ILogger) -> _xr.DataArray:

"""Obtain a 2D layer from a 3D variable
Args:
Expand All @@ -66,12 +62,12 @@ def execute(self, value_array: _xr.DataArray, logger: ILogger) -> _xr.DataArray:
raise IndexError(message)

if not (
self._layer_number >= 0
and self._layer_number <= len(getattr(value_array, self._axis_name))
self._element_index >= 0
and self._element_index <= len(getattr(value_array, self._axis_name))
):
message = f"""Layer number should be within range \
[0,{len(getattr(value_array, self._axis_name))}]"""
logger.log_error(message)
raise IndexError(message)

return value_array.isel({self._axis_name: self._layer_number - 1})
return value_array.isel({self._axis_name: self._element_index - 1})
66 changes: 37 additions & 29 deletions decoimpact/business/entities/rules/classification_rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
ClassificationRule
"""

from typing import Dict, List
from typing import Dict, List, Optional

import xarray as _xr

Expand All @@ -35,10 +35,8 @@ def __init__(
name: str,
input_variable_names: List[str],
criteria_table: Dict[str, List],
output_variable_name: str = "output",
description: str = "",
):
super().__init__(name, input_variable_names, output_variable_name, description)
super().__init__(name, input_variable_names)
self._criteria_table = criteria_table

@property
Expand Down Expand Up @@ -73,31 +71,9 @@ def execute(
# Retrieving criteria and applying it in correct format (number,
# range or comparison)
criteria = self.criteria_table[column_name][row]
criteria_class = type_of_classification(criteria)

comparison = True
if criteria_class == "number":
comparison = data == float(criteria)

elif criteria_class == "range":
begin, end = str_range_to_list(criteria)
comparison = (data >= begin) & (data <= end)

elif criteria_class == "larger_equal":
comparison_val = read_str_comparison(criteria, ">=")
comparison = data >= float(comparison_val)

elif criteria_class == "smaller_equal":
comparison_val = read_str_comparison(criteria, "<=")
comparison = data <= float(comparison_val)

elif criteria_class == "larger":
comparison_val = read_str_comparison(criteria, ">")
comparison = data > float(comparison_val)

elif criteria_class == "smaller":
comparison_val = read_str_comparison(criteria, "<")
comparison = data < float(comparison_val)
comparison = self._get_comparison_for_criteria(criteria, data)
if comparison is None:
comparison = True

# Criteria_comparison == 1 -> to check where the value is True
criteria_comparison = _xr.where(
Expand All @@ -111,3 +87,35 @@ def execute(

result_array = _xr.where(criteria_comparison, out, default_val)
return result_array

def _get_comparison_for_criteria(
self, criteria: str, data: _xr.DataArray
) -> Optional[_xr.DataArray]:

criteria_class = type_of_classification(criteria)

comparison = None
if criteria_class == "number":
comparison = data == float(criteria)

elif criteria_class == "range":
begin, end = str_range_to_list(criteria)
comparison = (data >= begin) & (data <= end)

elif criteria_class == "larger_equal":
comparison_val = read_str_comparison(criteria, ">=")
comparison = data >= float(comparison_val)

elif criteria_class == "smaller_equal":
comparison_val = read_str_comparison(criteria, "<=")
comparison = data <= float(comparison_val)

elif criteria_class == "larger":
comparison_val = read_str_comparison(criteria, ">")
comparison = data > float(comparison_val)

elif criteria_class == "smaller":
comparison_val = read_str_comparison(criteria, "<")
comparison = data < float(comparison_val)

return comparison
4 changes: 1 addition & 3 deletions decoimpact/business/entities/rules/combine_results_rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,8 @@ def __init__(
name: str,
input_variable_names: List[str],
operation_type: MultiArrayOperationType,
output_variable_name: str,
description: str = "",
):
super().__init__(name, input_variable_names, output_variable_name, description)
super().__init__(name, input_variable_names)
self._operation_type: MultiArrayOperationType = operation_type
self._operations = self._create_operations()

Expand Down
12 changes: 2 additions & 10 deletions decoimpact/business/entities/rules/formula_rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,8 @@ class FormulaRule(RuleBase, IMultiCellBasedRule):

formula_output_name: str = "formula_result"

def __init__(
self,
name: str,
input_variable_names: List[str],
formula: str,
output_variable_name: str = "output",
description: str = "",
):
super().__init__(name, input_variable_names, output_variable_name, description)
def __init__(self, name: str, input_variable_names: List[str], formula: str):
super().__init__(name, input_variable_names)
self._formula = formula
self._byte_code = None
self._setup_environment()
Expand All @@ -67,7 +60,6 @@ def formula(self) -> str:
return self._formula

def execute(self, values: Dict[str, float], logger: ILogger) -> float:

"""Calculates the formula based on the
Args:
values (DataArray): values to Formula
Expand Down
13 changes: 2 additions & 11 deletions decoimpact/business/entities/rules/layer_filter_rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,10 @@


class LayerFilterRule(RuleBase, IArrayBasedRule):

"""Implementation for the layer filter rule"""

def __init__(
self,
name: str,
input_variable_names: List[str],
layer_number: int,
output_variable_name: str = "output",
description: str = "",
):
super().__init__(name, input_variable_names, output_variable_name, description)
def __init__(self, name: str, input_variable_names: List[str], layer_number: int):
super().__init__(name, input_variable_names)
self._layer_number = layer_number

@property
Expand All @@ -41,7 +33,6 @@ def layer_number(self) -> int:
return self._layer_number

def execute(self, value_array: _xr.DataArray, logger: ILogger) -> _xr.DataArray:

"""Obtain a 2D layer from a 3D variable
Args:
Expand Down
19 changes: 8 additions & 11 deletions decoimpact/business/entities/rules/multiply_rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"""

from datetime import datetime as _dt
from typing import List
from typing import List, Optional

import numpy as _np
import xarray as _xr
Expand All @@ -30,11 +30,9 @@ def __init__(
name: str,
input_variable_names: List[str],
multipliers: List[List[float]],
output_variable_name: str = "output",
date_range: List[List[str]] = [],
description: str = "",
date_range: Optional[List[List[str]]] = None,
):
super().__init__(name, input_variable_names, output_variable_name, description)
super().__init__(name, input_variable_names)
self._multipliers = multipliers
self._date_range = date_range

Expand All @@ -44,7 +42,7 @@ def multipliers(self) -> List[List[float]]:
return self._multipliers

@property
def date_range(self) -> List[List[str]]:
def date_range(self) -> Optional[List[List[str]]]:
"""Date range property"""
return self._date_range

Expand All @@ -63,16 +61,15 @@ def execute(self, value_array: _xr.DataArray, logger: ILogger) -> _xr.DataArray:
result_multipliers = [_np.prod(mp) for mp in self._multipliers]
old_dr = _xr.DataArray(value_array)
new_dr = _xr.full_like(old_dr, _np.nan)
for (index, _mp) in enumerate(result_multipliers):
if len(self.date_range) != 0:

for index, _mp in enumerate(result_multipliers):
if self.date_range is not None and len(self.date_range) != 0:
# Date is given in DD-MM, convert to MM-DD for comparison
start = self._convert_datestr(self.date_range[index][0])
end = self._convert_datestr(self.date_range[index][1])
dr_date = old_dr.time.dt.strftime(r"%m-%d")
new_dr = _xr.where(
(start < dr_date) & (dr_date < end),
old_dr * _mp,
new_dr
(start < dr_date) & (dr_date < end), old_dr * _mp, new_dr
)
else:
new_dr = old_dr * _mp
Expand Down
4 changes: 1 addition & 3 deletions decoimpact/business/entities/rules/response_curve_rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,8 @@ def __init__(
input_variable_name: str,
input_values: List[float],
output_values: List[float],
output_variable_name="output",
description: str = "",
):
super().__init__(name, [input_variable_name], output_variable_name, description)
super().__init__(name, [input_variable_name])

self._input_values = _np.array(input_values)
self._output_values = _np.array(output_values)
Expand Down
Loading

0 comments on commit 18e85d9

Please sign in to comment.