Skip to content

Commit

Permalink
merged develop
Browse files Browse the repository at this point in the history
  • Loading branch information
rwijtvliet committed May 26, 2024
2 parents b9497f4 + cda6bfb commit 2de4d01
Show file tree
Hide file tree
Showing 101 changed files with 8,483 additions and 4,584 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/ci-on-pullreq.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ jobs:
matrix:
os: ["ubuntu-latest", "macos-latest", "windows-latest"]
python-version: ["3.10", "3.11", "3.12"]

exclude:
# Exclude Python 3.10 on macOS latest
- os: "macos-latest"
python-version: "3.10"
steps:
- name: Checkout source
uses: actions/checkout@v2
Expand Down
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
25 changes: 0 additions & 25 deletions dev_scripts/checks.py

This file was deleted.

Empty file modified dev_scripts/sphinx_autorun.sh
100644 → 100755
Empty file.
7 changes: 4 additions & 3 deletions docs/core/pfline.rst
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ Another slicing method is implemented with the ``.slice[]`` property. The improv




Concatenation
=============

Expand Down Expand Up @@ -757,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 @@ -767,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
5 changes: 4 additions & 1 deletion docs/core/toplevel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@ Work on pandas objects
Work on portfolyo objects
-------------------------

* ``portfolyo.concat()`` Concatenates PfLines into one PfLine.
* ``portfolyo.concat()`` Concatenates PfLines (or PfStates) into one PfLine (or PfState).

* ``portfolyo.plot_pfstates()`` Plots several PfStates in one figure.

* ``portfolyo.intersection()`` Intersect several dataframes and/or series and/or Pflines and/or PfStates.



14 changes: 0 additions & 14 deletions docs/requirements-docs.txt

This file was deleted.

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: 11 additions & 8 deletions portfolyo/__init__.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
"""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 .core.pfline import Kind, PfLine, Structure, create
from .core.pfstate import PfState
from .core.shared.concat import general as concat
from .core.shared.plot import plot_pfstates
from .prices.hedge import hedge
from .prices.utils import is_peak_hour
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 .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 .core.shared.concat import general as concat

VOLUME = Kind.VOLUME
PRICE = Kind.PRICE
REVENUE = Kind.REVENUE
Expand All @@ -29,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 2de4d01

Please sign in to comment.