(datatypes)= # Datatypes The API has a defined set of internal datatypes to represent input and output data. Some are basic datatypes, and some are structured types to represent more complex data. (datatypes:int)= ## Integer A standard integer number. This type is also used for binary settings, where it is limited to 1 and 0. ### Example: module ID number To set the [module ID number](https://docs.prodrisk.sintef.energy/objects/module/module.html#number) for `new_module` in a prodrisk session called `ps` to 100:\ `ps.model.module['new_module'].number.set(100)`\ To get the module ID number of the module as a variable:\ `mod_number = ps.model.module['new_module'].number.get()` (datatypes:double)= ## Float A standard 8-byte float value (i.e., double precision). ### Example: reservoir volume To set the [reservoir volume](https://docs.prodrisk.sintef.energy/objects/module/module.html#rsvmax) for `new_module` in a prodrisk session called `ps` to 65.3 Mm^3^:\ `ps.model.module['new_module'].rsvMax.set(65.3)`\ To get the reservoir volume of the module as a variable:\ `rsv_max = ps.model.module['new_module'].rsvMax.get()` (datatypes:string)= ## String A standard string, with attribute-dependent maximum length. ### Example: plant name To set the [plant name](https://docs.prodrisk.sintef.energy/objects/module/module.html#plantname) for `new_module` in a prodrisk session called `ps` to 'hydro_plant':\ `ps.model.module['new_module'].plantName.set('hydro_plant')`\ To get the plant name of the module as a variable:\ `plant_name = ps.model.module['new_module'].plantName.get()` (datatypes:int-array)= ## List of integer values Data consisting of multiple integer values is passed / returned as a python List object, where each element is an integer value. The length of the list depends on the attribute. ### Example: module topology To set the [topology](https://docs.prodrisk.sintef.energy/objects/module/module.html#topology) for `new_module` in a prodrisk session called `ps` to modules with the ID numbers 101, 102, and 103:\ `ps.model.module['new_module'].plantName.set([101, 102, 103])`\ To get the topology of the module as a variable:\ `mod_topology = ps.model.module['new_module'].topology.get()` (datatypes:double-array)= ## List of double values Data consisting of multiple integer values is passed / returned as a python List object, where each element is a float value. Input can also be given as a numpy array. The length of the list depends on the attribute. ### Example: reservoir reference levels To set the [reservoir reference levels](https://docs.prodrisk.sintef.energy/objects/module/module.html#reservoirreferencelevels) for `new_module` in a prodrisk session called `ps` to the values 45.4 Mm^3^, 55.3 Mm^3^, and 62.7 Mm^3^:\ `ps.model.module['new_module'].reservoirReferenceLevels.set([45.4, 55.3, 62.7])`\ To get the reservoir reference levels as a variable:\ `rsv_ref_vol = ps.model.module['new_module'].reservoirReferenceLevels.get()` (datatypes:xy)= ## Table / xy curve Relation of two quantities given by discrete set of values. This datatype is represented as a [pandas Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html), where the two quantities are stored as index and data/values. Both index and data values are of type float and can be passed as a list or a numpy array. In addition, the `name` of the Series must be set. The name can be used as a label for this data set, but has no impact on the calculations. ### Example: PQ curve We set the [PQ curve](https://docs.prodrisk.sintef.energy/objects/module/module.html#pqcurve) for `new_module` in a prodrisk session called `ps` to the generated powers 0, 10, 20, 30 MW at the corresponding flow rates 0, 8.1, 16.5, 25.5 m^3^/s. We can use, e.g., the head that this PQ curve is refering to as a label, say 138 m. ``` import numpy as np import pandas as pd ... P = np.array([0, 10, 20, 30]) Q = np.array([0, 8.1, 16.5, 25.5]) pq_curve = pd.Series(name=138, index=P, data=Q) ps.model.module['new_module'].PQcurve.set(pq_curve) ``` To read out the PQ curve again: ``` pq_curve = ps.model.module['new_module'].PQcurve.get() P = pq_curve.index Q = pq_curve.values ``` Note that one has to set `data` in the pandas Series constructor, but use `values` to access this data later. (datatypes:xy-array)= ## List of tables A list of tables is represented by a list of [pandas Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html). Each element of the list works as described [above](datatypes:xy). This datatype is also used to manage lists of double arrays (e.g., cut coefficients), in which case only the `values` of each Series have a meaning, while the `index` is filled with zeros. ### Example: end value tables To set the [end values](https://docs.prodrisk.sintef.energy/objects/area/area.html#watervalue) with a set of aggregated water value tables for the area `my_area` in a prodrisk session called `ps`, we create a list of pandas Series, assuming for simplicity that we have the water values in an array `watervalue_1` for price level 1 etc. ``` import numpy as np import pandas as pd ... end_val_1 = pd.Series(name='price_level_1', index=np.linspace(100,0,51), data=watervalue_1) ... end_val_7 = pd.Series(name='price_level_7', index=np.linspace(100,0,51), data=watervalue_7) ps.area['my_area'].waterValue.set([end_val_1, end_val_2, end_val_3, end_val_4, end_val_5, end_val_6, end_val_7]) ``` (datatypes:txy)= ## Time series This dataype describes deterministic time-dependent data. It is represented by a [pandas Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html), where the index contains the time as [pandas Timestamp](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Timestamp.html) and the time-dependent values are given as data. It is recommended that the time axis is always set up relative to the start time of the simulation, using the sessions [`start_time`](https://docs.prodrisk.sintef.energy/functions.html#properties) property and [pandas Timedelta](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Timedelta.html). ### Example: minimum flow restriction To set the [minimum flow](https://docs.prodrisk.sintef.energy/objects/module/module.html#mindischarge) for `new_module` in a prodrisk session called `ps` to 3 m^3^/s from week 20 to week 34 in the simulation and 0 otherwise: ``` include pandas as pd ... ps.model.module['new_module'].set(pd.Series(index=[ps.start_time + pd.Timedelta(weeks=w) for w in [1,20,35]], data=[0,3,0])) ``` (datatypes:txy-stochastic)= ## Stochastic time series This dataype describes stochastic time-dependent data, i.e., one time series per scenario. It is represented by a [pandas DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html), where the index contains the time as [pandas Timestamp](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Timestamp.html) and the time-dependent values are given as data. It is recommended that the time axis is always set up relative to the start time of the simulation, using the sessions [`start_time`](https://docs.prodrisk.sintef.energy/functions.html#properties) property and [pandas Timedelta](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Timedelta.html). Each scenario is stored as one column in the DataFrame. ### Example: calculated reservoir trajectories To get the [reservoir filling](https://docs.prodrisk.sintef.energy/objects/module/module.html#reservoirvolume) of `new_module` in a prodrisk session called `ps` as a function of time for each scenario and access specifically results for the first scenario: ``` ... ps.run() ... vol = ps.model.module['new_module'].reservoirVolume.get() scenario_0 = vol[0] # this is a pandas Series ``` ```{contents} :local: :depth: 1 ``` # Timezones in pyprodrisk Pandas timestamps and datetime-indexes can be timezone-aware. To use timezones with pyprodrisk, the `set_optimization_period` function must have a start date with a timezone. This will be the base timezone for this session. Note that timezones only exist in the python package, but neither in the underlying API code nor in the Prodrisk core. Time series can be set with a timezone-aware index: - If the index has a timezone, pyprodrisk will use pandas functionality to calculate the time difference relative to the start date of the session. - If the index is not timezone-aware, pyprodrisk assumes that the timezone is the same as the sessions' base timezone. You may get a `NonExistentTimeError` from pandas if this is not possible. - If the index has a timezone but the session was created without a timezone, pyprodrisk will raise an error. Returning time series from the session using the `get` function will always return a series in the sessions' base timezone. Hence, if you `set` a series with a different timezone than the sessions' base timezone and `get` it afterwards, it will have the correct physical time but different timestamps than in your input.