Skip to content

Commit

Permalink
Structure (#90)
Browse files Browse the repository at this point in the history
* changed to poetry

* fixed pint problem (groups in unitdef.txt) and pint-pandas dependency problem by fixing pandas to 2.0

* ci pipeline

* ci pipeline

* ci with poetry

* solve dependency problems between pandas and pint-pandas

* workaround pint-pandas bug

* typo

* seaborn pinned version to 0.8

* fixed to_excel function, updated version of pint

* fixed arithmatic on pflines without overlap

* small changes
small changes

* more consistent functions to get random pfline

* deleted comment

* change the python version for push request to 3.11

* test

* Removed unused dependency

* updated toml

* added exception if no clipboard available

* updated toml

* fixed pfline_excelclipboad.py

* changed lock file for pre-commit

* install poetry libraries in pre-commit step

* use black on all files in pre-commit

* updated flake8 version in pre-commit.yaml

* exclude .venv folder from flake8

* changed setup.cfg to ignore flake8 error messages

* initial commit

* first try at plotting children

* bar plot with children

* created plot_children(),fixed bug with darken

* area plots for children stacked on top of each other. for daily it plots only parent

* changed the logic of all plot_timeseries_as functions, now based on frequency

* created a function to test plotting pfline

* created slice attr, wrote tests for it

* more flexible intersec function with ignore freq, tz, start_of_day + tests

* small changes to intersect

* intersect_flex function is finished, more testing with frames needed

* finished intersect_flex, more testing with frames needed

* added children bool to plot pfstate

* added hash function for colors for children

* deleted unnecessary test

* changed hash function, and width of hline

* deleted unnecessary test

* plot with children

* changed plot_pfstate to work with new logic

* tests for plot function

* refactoring

* more powerful peak/offpeak functions

* removed longer_or_shorter from frequency tools; Use the up_or_down function instead

* tests for peakfn and peakconvert

* fixed test

* removed all Union and replaced with |


---------

Co-authored-by: rwijtvliet <[email protected]>
Co-authored-by: Alina Voilova <[email protected]>
  • Loading branch information
3 people authored May 24, 2024
1 parent 2666c1f commit cda6bfb
Show file tree
Hide file tree
Showing 93 changed files with 6,850 additions and 3,980 deletions.
17 changes: 17 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
=========
portfolyo
=========

Expand Down Expand Up @@ -28,6 +29,8 @@ portfolyo
Portfolyo is a Python package to analyse and manipulate timeseries related to power
and gas offtake portfolios.


------------
Installation
------------

Expand All @@ -45,13 +48,16 @@ NB: this package is under active development and the API will change without pri
portfolyo = "x.y.z"
-------------
Documentation
-------------

Documentation is hosted on readthedocs:

https://portfolyo.readthedocs.io/


----------
Repository
----------

Expand All @@ -60,6 +66,7 @@ The git repository is hosted on github:
http://www.github.com/rwijtvliet/portfolyo


----------
Developing
----------

Expand All @@ -74,6 +81,16 @@ the commit hooks.
Feature branches are merged into the ``develop`` branch via pull request.


Internal dependencies
---------------------

Inside the package, modules depend on each other in the following chain. A module may depend on another module if it is further to the left:

tools >> pfline >> pfstate >> tools2


----------
Publishing
----------

Expand Down
Empty file modified dev_scripts/sphinx_autorun.sh
100644 → 100755
Empty file.
6 changes: 3 additions & 3 deletions docs/core/pfline.rst
Original file line number Diff line number Diff line change
Expand Up @@ -758,7 +758,7 @@ Using the ``.hedge_with()`` method, the volume timeseries in a portfolio line is
Peak and offpeak
----------------

For portfolio lines with (quarter)hourly data, the ``.po()`` method splits the values in peak and offpeak. We can again specify if we want monthly, quarterly, or yearly values.
For markets that have a concept of "peak" and "offpeak" periods, the ``.po()`` method splits the values in peak and offpeak. We need to specifiy a ``PeakFunction`` to determine which periods are peak - we can create one with ``portfolyo.create_peakfn()``, or we use the one for the German power market which is provided under ``portfolyo.germanpower_peakfn``. We can again specify if we want monthly, quarterly, or yearly values.

.. exec_code::

Expand All @@ -768,9 +768,9 @@ For portfolio lines with (quarter)hourly data, the ``.po()`` method splits the v
offtake = pf.PfLine(pf.dev.w_offtake(index)) # mock offtake volumes
# --- hide: stop ---
# continuation of previous code example
offtake.po()
offtake.po(pf.germanpower_peakfn)
# --- hide: start ---
print(repr(offtake.po()))
print(repr(offtake.po(pf.germanpower_peakfn)))

NB: be cautious in using the output of this method. The values in the "sub-dataframes" do not apply to the entire time period, so the usual relations (e.g. energy = power * duration) do not hold if the duration of the entire time period is used. For convenience, the relevant duration (of only the peak or only the offpeak hours) is included in the dataframe.

Expand Down
Binary file modified docs/savefig/fig_hedge.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/savefig/fig_offtake.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/savefig/fig_plot_pfl.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/savefig/fig_plot_pfs.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 9 additions & 10 deletions portfolyo/__init__.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
"""Package to analyse and manipulate timeseries related to power and gas offtake portfolios."""

from . import _version, dev, testing, tools
from . import _version, dev, tools
from .core import extendpandas # extend functionalty of pandas
from .core import suppresswarnings
from .tools2.plot import plot_pfstates
from .core.pfline import Kind, PfLine, Structure, create
from .core.pfstate import PfState
from .tools import testing
from .tools2.changeyear import map_to_year
from .tools2.concat import general as concat
from .tools2.intersect import indexable as intersection
from .tools2.plot import plot_pfstates
from .prices.hedge import hedge
from .prices.utils import is_peak_hour
from .tools.changefreq import averagable as asfreq_avg
from .tools.changefreq import summable as asfreq_sum
from .tools.changeyear import characterize_index, map_frame_to_year
from .tools.freq import FREQUENCIES
from .tools.hedge import hedge
from .tools.peakfn import PeakFunction
from .tools.peakfn import factory as create_peakfn
from .tools.product import germanpower_peakfn, is_peak_hour
from .tools.standardize import frame as standardize
from .tools.tzone import force_agnostic, force_aware
from .tools.unit import Q_, Unit, ureg
from .tools.wavg import general as wavg
from .tools2.concat import general as concat
from .tools2.intersect import indexable as intersection

# from .core.shared.concat import general as concat


VOLUME = Kind.VOLUME
PRICE = Kind.PRICE
Expand All @@ -33,4 +32,4 @@
suppresswarnings.apply()

__version__ = _version.get_versions()["version"]
__all__ = ["tools", "dev", "testing", "PfLine", "PfState"]
__all__ = ["tools", "dev", "PfLine", "PfState"]
16 changes: 7 additions & 9 deletions portfolyo/core/pfline/arithmatic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

from __future__ import annotations

from typing import TYPE_CHECKING, Any, Union
from typing import TYPE_CHECKING, Any

import numpy as np
import pandas as pd

from ... import testing, tools
from ... import tools
from . import classes, create, interop
from .enums import Kind, Structure

Expand All @@ -23,7 +23,7 @@ def assert_objects_indexcompatibility(fn):

def wrapper(o1, o2, *args, **kwargs):
try:
testing.assert_indices_compatible(o1.index, o2.index)
tools.testing.assert_indices_compatible(o1.index, o2.index)
except AssertionError as e:
raise NotImplementedError from e
return fn(o1, o2, *args, **kwargs)
Expand Down Expand Up @@ -185,7 +185,7 @@ def __rmul__(self: PfLine, other: Any) -> PfLine:
@Prep.standardize_other # other converted to None, a PfLine, or dimless Series
@Prep.raiseerror_if_otherNone # other is now a PfLine or dimless Series...
@Prep.assert_objects_indexcompatibility # ... with a compatible index
def __truediv__(self: PfLine, other: Any) -> Union[PfLine, pd.Series]:
def __truediv__(self: PfLine, other: Any) -> PfLine | pd.Series:
if isinstance(other, pd.Series):
return Multiply.pfline_and_series(self, 1 / other)
else:
Expand All @@ -195,7 +195,7 @@ def __truediv__(self: PfLine, other: Any) -> Union[PfLine, pd.Series]:
@Prep.raiseerror_if_otherNone # other is now a PfLine or dimless Series
@Prep.raiseerror_if_otherdimlessseries # other is now a PfLine...
@Prep.assert_objects_indexcompatibility # ... with a compatible index
def __rtruediv__(self: PfLine, other: Any) -> Union[PfLine, pd.Series]:
def __rtruediv__(self: PfLine, other: Any) -> PfLine | pd.Series:
return Divide.two_pflines(other, self) # NB order!

@Prep.standardize_other # other converted to None, a PfLine, or dimless Series
Expand Down Expand Up @@ -285,12 +285,10 @@ def nestedpfline_and_series(pfl: NestedPfLine, s: pd.Series) -> NestedPfLine:

class Divide:
@Prep.ensure_pflines_flat # pfl1 and pfl2 are now both flat
def two_pflines(pfl1: PfLine, pfl2: PfLine) -> Union[pd.Series, PfLine]:
def two_pflines(pfl1: PfLine, pfl2: PfLine) -> pd.Series | PfLine:
return Divide.two_flatpflines(pfl1, pfl2)

def two_flatpflines(
pfl1: FlatPfLine, pfl2: FlatPfLine
) -> Union[pd.Series, FlatPfLine]:
def two_flatpflines(pfl1: FlatPfLine, pfl2: FlatPfLine) -> pd.Series | FlatPfLine:
if pfl1.kind is pfl2.kind:
if pfl1.kind is Kind.COMPLETE:
raise NotImplementedError(
Expand Down
10 changes: 4 additions & 6 deletions portfolyo/core/pfline/children.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
from __future__ import annotations

import warnings
from typing import TYPE_CHECKING, Any, Mapping, Union
from typing import TYPE_CHECKING, Any, Mapping

from ... import testing, tools
from ... import tools
from . import create

if TYPE_CHECKING:
from .classes import NestedPfLine, PfLine


class ChildFunctionality(Mapping):
def set_child(
self: NestedPfLine, name: str, child: Union[PfLine, Any]
) -> NestedPfLine:
def set_child(self: NestedPfLine, name: str, child: PfLine | Any) -> NestedPfLine:
"""Set/add/update child; returns new pfline instance without changing current instance."""
if name in ["w", "q", "p", "r"]:
raise ValueError("Name cannot be one of 'w', 'q', 'p', 'r'.")
Expand All @@ -28,7 +26,7 @@ def set_child(
f"Incompatible kinds; the portfolio line has {self.kind} but the child has {child.kind}."
)
try:
testing.assert_indices_compatible(self.index, child.index)
tools.testing.assert_indices_compatible(self.index, child.index)
except AssertionError as e:
raise ValueError(
"Index of new child is not compatible with the existing data."
Expand Down
Loading

0 comments on commit cda6bfb

Please sign in to comment.