# pylint: disable=C0301
"""
The dictionary `rolling_limits` has key-value pairs where each key is
a string representing a parameter or process variable, and each value is another
dictionary with three key-value pairs:
1. `"rolling"`: This key represents the rolling window size to be used when
calculating statistics or aggregating data for the respective parameter
or process variable.
2. `"quant_one"`: This key is associated with a float value (between 0 and 1),
representing the lower quantile value for the respective parameter or process
variable. It determines thresholds to use when calculating the data ranges.
3. `"quant_two"`: This key is associated with a float value (between 0 and 1),
representing the upper quantile value for the respective parameter or process
variable. It determines thresholds to calculate data ranges.
"""
from typing import Any
rolling_limits = {
# "CONS EE PRENSA - US8": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
"Consumo de Energia (base minério úmido) kWh/ton 1": {
"rolling": 24,
"quant_one": 0.25,
"quant_two": 0.75,
},
"Consumo de Energia (base minério úmido) kWh/ton 2": {
"rolling": 24,
"quant_one": 0.25,
"quant_two": 0.75,
},
"Consumo de Energia (base minério úmido) kWh/ton 3": {
"rolling": 24,
"quant_one": 0.25,
"quant_two": 0.75,
},
# "GRAN_OCS_TM@08PE-BD-840I-01": {'rolling': 12, 'quant_one': 0.30, 'quant_two': 0.75},
# "GRAN_OCS_TM@08PE-BD-840I-02": {'rolling': 12, 'quant_one': 0.30, 'quant_two': 0.75},
# "GRAN_OCS_TM@08PE-BD-840I-03": {'rolling': 12, 'quant_one': 0.30, 'quant_two': 0.75},
# "GRAN_OCS_TM@08PE-BD-840I-04": {'rolling': 12, 'quant_one': 0.30, 'quant_two': 0.75},
# "GRAN_OCS_TM@08PE-BD-840I-05": {'rolling': 12, 'quant_one': 0.30, 'quant_two': 0.75},
# "GRAN_OCS_TM@08PE-BD-840I-06": {'rolling': 12, 'quant_one': 0.30, 'quant_two': 0.75},
# "GRAN_OCS_TM@08PE-BD-840I-07": {'rolling': 12, 'quant_one': 0.30, 'quant_two': 0.75},
# "GRAN_OCS_TM@08PE-BD-840I-08": {'rolling': 12, 'quant_one': 0.30, 'quant_two': 0.75},
# "GRAN_OCS_TM@08PE-BD-840I-09": {'rolling': 12, 'quant_one': 0.30, 'quant_two': 0.75},
# "GRAN_OCS_TM@08PE-BD-840I-10": {'rolling': 12, 'quant_one': 0.30, 'quant_two': 0.75},
# "GRAN_OCS_TM@08PE-BD-840I-11": {'rolling': 12, 'quant_one': 0.30, 'quant_two': 0.75},
# "GRAN_OCS_TM@08PE-BD-840I-12": {'rolling': 12, 'quant_one': 0.30, 'quant_two': 0.75},
"PESO1_I@08MI-LW-832I-01M1": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
"PESO1_I@08MI-LW-832I-02M1": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
"POTE1_I@08PR-RP-822I-01M1": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
"POTE1_I@08PR-RP-822I-01M2": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
"PRES1_C@08QU-PF-852I-06M1": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
"PRES1_C@08QU-VD-853I-17M1": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
# "PRES4_I@08QU-HO-851I-01": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
# "PRES6_I@08QU-HO-851I-01": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
# "ROTA1_I@08QU-PF-852I-05M1": {"rolling": 24, "quant_one": 0.3, "quant_two": 0.75},
# "ROTA1_I@08QU-PF-852I-06M1": {"rolling": 24, "quant_one": 0.3, "quant_two": 0.75},
# "ROTA1_I@08QU-PF-852I-08M1": {"rolling": 24, "quant_one": 0.3, "quant_two": 0.75},
# "TEMP1_I@08QU-QU-855I-GQ": {"rolling": 1, "quant_one": 0.35, "quant_two": 0.75},
"TEMP1_I@08QU-WB-851I-03B": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
"TEMP1_I@08QU-WB-851I-04": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
"TEMP1_I@08QU-WB-851I-05": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
"TEMP1_I@08QU-WB-851I-06": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
"TEMP1_I@08QU-WB-851I-07": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
"TEMP1_I@08QU-WB-851I-08": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
"TEMP1_I@08QU-WB-851I-09": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
"TEMP1_I@08QU-WB-851I-10": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
"TEMP1_I@08QU-WB-851I-11": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
"TEMP1_I@08QU-WB-851I-12": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
"TEMP1_I@08QU-WB-851I-13": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
"TEMP1_I@08QU-WB-851I-14": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
"TEMP1_I@08QU-WB-851I-15": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
"TEMP1_I@08QU-WB-851I-16": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
"TEMP1_I@08QU-WB-851I-17": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
"TEMP1_I@08QU-WB-851I-18": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
"TEMP1_I@08QU-WB-851I-19": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
"TEMP1_I@08QU-WB-851I-20": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
# "TEMP5_I@08QU-PF-852I-02M1": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
# "TEMP5_I@08QU-PF-852I-03M1": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
# "TEMP5_I@08QU-PF-852I-04M1": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
# "TEMP5_I@08QU-PF-852I-05M1": {"rolling": 24, "quant_one": 0.25, "quant_two": 0.75},
"VAZA1_I@08QU-ST-855I-01": {"rolling": 24, "quant_one": 0.0, "quant_two": 0.75},
"calcario": {"rolling": 24, "quant_one": 0.05, "quant_two": 0.75},
}
[docs]def check_quantile_values(quant_one: Any, quant_two: Any) -> str:
"""
Validate `quant_one` and `quant_two` quantile values.
This function checks if the provided quantile values are of a valid type
(int or float), are within the range [0, 1], and ensures that `quant_one`
is less than or equal to `quant_two`.
Parameters
----------
quant_one : int, float
The first quantile value to validate.
quant_two : int, float
The second quantile value to validate.
Returns
-------
str
An error message string detailing any validation issues found.
Returns an empty string if both quantile values are valid.
"""
inner_dict_values_error_message = ""
quantiles = {"quant_one": quant_one, "quant_two": quant_two}
for quantile_name, quantile_value in quantiles.items():
if not isinstance(quantile_value, (int, float)):
inner_dict_values_error_message += (
f"- Value {quantile_value!r} from `{quantile_name}` is not a number.\n"
)
elif not 0 <= quantile_value <= 1:
inner_dict_values_error_message += f"- Value {quantile_value!r} from `{quantile_name}` needs to be between 0 and 1.\n"
if inner_dict_values_error_message == "" and quant_one > quant_two:
inner_dict_values_error_message += (
f"- Value {quant_one!r} from `quant_one` needs to be smaller than "
f"value {quant_two!r} from `quant_two`. Redefine both values, "
"for numbers between 0 and 1, and make sure `quant_one` is "
"smaller than `quant_two`\n"
)
return inner_dict_values_error_message
[docs]def check_rolling_value(rolling: Any) -> str:
"""
Validate the `rolling` parameter.
This function checks if the provided rolling value is of the type integer
and ensures it's non-negative.
Parameters
----------
rolling : int
The rolling value to validate.
Returns
-------
str
An error message string detailing any validation issues found.
Returns an empty string if the rolling value is valid.
"""
if not isinstance(rolling, int):
return f"Value {rolling!r} from `rolling` is not an integer\n"
if rolling < 0:
return (
f"Value {rolling!r} from `rolling` needs to be greater than or equal to 0\n"
)
return ""
[docs]def check_rolling_limits_values(rolling_limits_dict: dict):
"""
Check if the `rolling_limits_dict` has the correct keys and values.
The function runs inside this module and ensures that the `rolling_limits`
dictionary doesn't contain errors that can cause the optimization model
to output wrong results.
Parameters
----------
rolling_limits_dict : dict
Dictionary containing the rolling limits for each tag.
Raises
------
TypeError
If the value of any tag isn't a dictionary.
ValueError
If values from each tag inner dictionary have the wrong type,
or are out of their respective ranges.
KeyError
If any tag is missing one of the necessary keys:
- rolling
- quant_one
- quant_two
"""
inner_dict_keys_needed = ["rolling", "quant_one", "quant_two"]
for tag, value in rolling_limits_dict.items():
if not isinstance(value, dict):
raise TypeError(
f"Value {value!r} from `rolling_limits` is not a dictionary"
)
if any(key not in value.keys() for key in inner_dict_keys_needed):
raise KeyError(
f"Tag {tag!r} defined inside the `rolling_limits` dictionary "
"is missing some of the necessary keys.\n\nNecessary keys:\n"
+ "\n".join(inner_dict_keys_needed)
+ "\nKeys found:\n"
+ "\n".join(value.keys())
+ "\nPlease make sure that the aforementioned tag, and all other"
+ "tags defined inside the `rolling_limits` dictionary, have "
+ "all the necessary keys."
)
rolling = value["rolling"]
quant_one = value["quant_one"]
quant_two = value["quant_two"]
inner_dict_values_error_message = check_quantile_values(quant_one, quant_two)
inner_dict_values_error_message += check_rolling_value(rolling)
if inner_dict_values_error_message != "":
raise ValueError(
f"Tag {tag!r} defined inside the `rolling_limits` dictionary "
"has some incorrect values.\nInconsistencies found:\n"
+ inner_dict_values_error_message
)
check_rolling_limits_values(rolling_limits)