Skip to content

Commit

Permalink
Merge pull request #140 from wind-python/dev
Browse files Browse the repository at this point in the history
Merge into master for release 0.2.2
  • Loading branch information
birgits authored Feb 20, 2024
2 parents 70f09b4 + 8f11ea4 commit 255be72
Show file tree
Hide file tree
Showing 35 changed files with 709 additions and 206 deletions.
68 changes: 68 additions & 0 deletions .github/workflows/tests-coverage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Tests with pytest the package and monitors the coverage and sends it to coveralls.io
# Coverage is only send to coveralls.io when no pytest tests fail
name: "Tests & Coverage"

on: [push]

# Cancel jobs on new push
concurrency:
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
cancel-in-progress: true

jobs:
build:
name: "${{ matrix.name-suffix }} at py${{ matrix.python-version }} on ${{ matrix.os }}"
runs-on: ${{ matrix.os }}

strategy:
fail-fast: false
matrix:
include:
- name-suffix: "coverage"
os: ubuntu-latest
python-version: "3.11"
- name-suffix: "basic"
os: ubuntu-latest
python-version: "3.10"
- name-suffix: "basic"
os: ubuntu-latest
python-version: "3.12"
- name-suffix: "basic"
os: windows-latest
python-version: "3.11"

steps:
- name: Checkout repo
uses: actions/checkout@v3

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- name: Set up Conda
if: runner.os == 'Windows'
uses: conda-incubator/setup-miniconda@v2
with:
miniconda-version: "latest"
python-version: ${{ matrix.python-version }}
activate-environment: testenv

- name: Install dependencies
run: |
python -m pip install --upgrade pip wheel setuptools
python -m pip install .[dev]
- name: Run tests
if: ${{ !(runner.os == 'Linux' && matrix.python-version == 3.9 && matrix.name-suffix == 'coverage') }}
run: |
python -m pytest --disable-warnings --color=yes -v
- name: Run tests, coverage and send to coveralls
if: runner.os == 'Linux' && matrix.python-version == 3.9 && matrix.name-suffix == 'coverage'
run: |
coverage run --source=windpowerlib -m pytest --disable-warnings --color=yes -v
coveralls
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COVERALLS_SERVICE_NAME: github
28 changes: 28 additions & 0 deletions .readthedocs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# .readthedocs.yml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details

# Required
version: 2

# Build documentation in the docs/ directory with Sphinx
sphinx:
configuration: doc/conf.py

# Build documentation with MkDocs
#mkdocs:
# configuration: mkdocs.yml

# Optionally build your docs in additional formats such as PDF and ePub
formats: all

# Optionally set the version of Python and requirements required to build your docs
python:
install:
- requirements: doc/requirements.txt

# Set the version of Python
build:
os: ubuntu-22.04
tools:
python: "3.11"
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ language: python

matrix:
include:
- python: 3.6
- python: 3.7
- python: 3.8
- python: 3.10
- python: 3.11
- python: 3.12

# command to install dependencies
#before_install:
Expand Down
8 changes: 4 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ Go to the `download page <http://readthedocs.org/projects/windpowerlib/downloads
Installation
============

If you have a working Python 3 (>= 3.6) environment, use pypi to install the latest windpowerlib version:
If you have a working Python 3 environment, use pypi to install the latest windpowerlib version:

::

pip install windpowerlib

The windpowerlib is designed for Python 3 and tested on Python >= 3.5. We highly recommend to use virtual environments.
The windpowerlib is designed for Python 3 and tested on Python >= 3.10. We highly recommend to use virtual environments.
Please see the `installation page <http://oemof.readthedocs.io/en/stable/installation_and_setup.html>`_ of the oemof documentation for complete instructions on how to install python and a virtual environment on your operating system.

Optional Packages
Expand Down Expand Up @@ -97,8 +97,8 @@ To update your local files with the latest version of the `oedb turbine library

.. code:: python
from windpowerlib.wind_turbine import load_turbine_data_from_oedb
load_turbine_data_from_oedb()
from windpowerlib.data import store_turbine_data_from_oedb
store_turbine_data_from_oedb()
If you find your turbine in the database it is very easy to use it in the
windpowerlib
Expand Down
2 changes: 1 addition & 1 deletion doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@

# General information about the project.
project = u'windpowerlib'
copyright = u'2016-2021, oemof developer group'
copyright = u'2016-2023, oemof developer group'
author = u'oemof developer group'

import windpowerlib
Expand Down
14 changes: 7 additions & 7 deletions doc/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ If you have a working Python 3 environment, use pypi to install the latest windp

pip install windpowerlib

The windpowerlib is designed for Python 3 and tested on Python >= 3.5. We highly recommend to use virtual environments.
The windpowerlib is designed for Python 3 and tested on Python >= 3.10. We highly recommend to use virtual environments.
Please see the `installation page <http://oemof.readthedocs.io/en/stable/installation_and_setup.html>`_ of the oemof documentation for complete instructions on how to install python and a virtual environment on your operating system.

Optional Packages
Expand All @@ -69,9 +69,9 @@ The basic usage of the windpowerlib is shown in the ModelChain example that is a
To run the example you need the example weather and turbine data used:

* :download:`Example weather data file <../example/weather.csv>`
* :download:`Example power curve data file <../example/data/power_curves.csv>`
* :download:`Example power coefficient curve data file <../example/data/power_coefficient_curves.csv>`
* :download:`Example nominal power data file <../example/data/turbine_data.csv>`
* :download:`Example power curve data file <../windpowerlib/data/default_turbine_data/power_curves.csv>`
* :download:`Example power coefficient curve data file <../windpowerlib/data/default_turbine_data/power_coefficient_curves.csv>`
* :download:`Example nominal power data file <../windpowerlib/data/default_turbine_data/turbine_data.csv>`

Furthermore, you have to install the windpowerlib and to run the notebook you also need to install `notebook` using pip3. To launch jupyter notebook type ``jupyter notebook`` in the terminal.
This will open a browser window. Navigate to the directory containing the notebook to open it. See the jupyter notebook quick start guide for more information on `how to install <http://jupyter-notebook-beginner-guide.readthedocs.io/en/latest/install.html>`_ and
Expand Down Expand Up @@ -102,8 +102,8 @@ To update your local files with the latest version of the `oedb turbine library

.. code:: python
from windpowerlib.wind_turbine import load_turbine_data_from_oedb
load_turbine_data_from_oedb()
from windpowerlib.data import store_turbine_data_from_oedb
store_turbine_data_from_oedb()
If you find your turbine in the database it is very easy to use it in the
windpowerlib
Expand Down Expand Up @@ -223,4 +223,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.
1 change: 1 addition & 0 deletions doc/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
sphinx>=1.4
sphinx_rtd_theme
ipykernel
nbsphinx
pandas
Expand Down
1 change: 1 addition & 0 deletions doc/whats_new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ These are new features and improvements of note in each release
:local:
:backlinks: top

.. include:: whatsnew/v0-2-2.rst
.. include:: whatsnew/v0-2-1.rst
.. include:: whatsnew/v0-2-0.rst
.. include:: whatsnew/v0-1-3.rst
Expand Down
12 changes: 12 additions & 0 deletions doc/whatsnew/v0-2-2.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
v0.2.2 (February 20, 2024)
++++++++++++++++++++++++++++++

* Updated the code basis to work for newer versions of python (support for python 3.6 to
python 3.9 is discontinued, supported python versions are now >= python 3.9) and added
github actions to run tests automatically when changes are pushed to github
(`PR 136 <https://github.com/wind-python/windpowerlib/pull/136>`_).

Contributors
############
* Birgit Schachler
* Florian Maurer
5 changes: 3 additions & 2 deletions example/modelchain_example.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@
" file,\n",
" index_col=0,\n",
" header=[0, 1],\n",
" date_parser=lambda idx: pd.to_datetime(idx, utc=True))\n",
" )\n",
" weather_df.index = pd.to_datetime(weather_df.index, utc=True)\n",
" \n",
" # change time zone\n",
" weather_df.index = weather_df.index.tz_convert(\n",
Expand Down Expand Up @@ -517,7 +518,7 @@
" x='wind_speed', y='value', style='*',\n",
" title='Enercon E126 power coefficient curve')\n",
" plt.xlabel('Wind speed in m/s')\n",
" plt.ylabel('Power in W')\n",
" plt.ylabel('Power coefficient $\\mathrm{C}_\\mathrm{P}$')\n",
" plt.show()\n",
" if e126.power_curve is not None:\n",
" e126.power_curve.plot(x='wind_speed', y='value', style='*',\n",
Expand Down
4 changes: 2 additions & 2 deletions example/modelchain_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ def get_weather_data(filename="weather.csv", **kwargs):
file,
index_col=0,
header=[0, 1],
date_parser=lambda idx: pd.to_datetime(idx, utc=True),
)
weather_df.index = pd.to_datetime(weather_df.index, utc=True)

# change time zone
weather_df.index = weather_df.index.tz_convert("Europe/Berlin")
Expand Down Expand Up @@ -274,7 +274,7 @@ def plot_or_print(my_turbine, e126, my_turbine2):
title="Enercon E126 power curve",
)
plt.xlabel("Wind speed in m/s")
plt.ylabel("Power in W")
plt.ylabel("Power coefficient $\mathrm{C}_\mathrm{P}$")
plt.show()
if my_turbine.power_curve is not False:
my_turbine.power_curve.plot(
Expand Down
145 changes: 145 additions & 0 deletions example/simple_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
"""
The ``turbine_cluster_modelchain_example`` module shows how to calculate the
power output of wind farms and wind turbine clusters with the windpowerlib.
A cluster can be useful if you want to calculate the feed-in of a region for
which you want to use one single weather data point.
Functions that are used in the ``modelchain_example``, like the initialization
of wind turbines, are imported and used without further explanations.
SPDX-FileCopyrightText: 2019 oemof developer group <contact@oemof.org>
SPDX-License-Identifier: MIT
"""
import pandas as pd
import requests
import os

from windpowerlib import WindFarm
from windpowerlib import WindTurbine
from windpowerlib import TurbineClusterModelChain
from windpowerlib import WindTurbineCluster

# You can use the logging package to get logging messages from the windpowerlib
# Change the logging level if you want more or less messages
import logging

logging.getLogger().setLevel(logging.INFO)


def get_weather_data(filename="weather.csv", **kwargs):
r"""
Imports weather data from a file.
The data include wind speed at two different heights in m/s, air
temperature in two different heights in K, surface roughness length in m
and air pressure in Pa. The height in m for which the data applies is
specified in the second row.
In case no weather data file exists, an example weather data file is
automatically downloaded and stored in the same directory as this example.
Parameters
----------
filename : str
Filename of the weather data file. Default: 'weather.csv'.
Other Parameters
----------------
datapath : str, optional
Path where the weather data file is stored.
Default is the same directory this example is stored in.
Returns
-------
:pandas:`pandas.DataFrame<frame>`
DataFrame with time series for wind speed `wind_speed` in m/s,
temperature `temperature` in K, roughness length `roughness_length`
in m, and pressure `pressure` in Pa.
The columns of the DataFrame are a MultiIndex where the first level
contains the variable name as string (e.g. 'wind_speed') and the
second level contains the height as integer at which it applies
(e.g. 10, if it was measured at a height of 10 m). The index is a
DateTimeIndex.
"""

if "datapath" not in kwargs:
kwargs["datapath"] = os.path.dirname(__file__)

file = os.path.join(kwargs["datapath"], filename)

# download example weather data file in case it does not yet exist
if not os.path.isfile(file):
logging.debug("Download weather data for example.")
req = requests.get("https://osf.io/59bqn/download")
with open(file, "wb") as fout:
fout.write(req.content)

# read csv file
weather_df = pd.read_csv(
file,
index_col=0,
header=[0, 1],
)
weather_df.index = pd.to_datetime(weather_df.index, utc=True)

# change time zone
weather_df.index = weather_df.index.tz_convert("Europe/Berlin")

return weather_df


def run_example():
r"""
Runs the example.
"""
weather = get_weather_data("weather.csv")
e126 = WindTurbine(
**{
"turbine_type": "E-126/4200", # turbine type as in register
"hub_height": 135, # in m
}
)
v90 = WindTurbine(
**{
"turbine_type": "V90/2000", # turbine name as in register
"hub_height": 120, # in m
}
)

# specification of wind farm data (2) containing a wind farm efficiency
# wind turbine fleet is provided using the to_group function
example_farm = WindFarm(
**{
"name": "example_farm_2",
"wind_turbine_fleet": [
v90.to_group(number_turbines=6),
e126.to_group(total_capacity=12.6e6),
],
"efficiency": 0.5
}
)

example_cluster = WindTurbineCluster(**{
"name": "Offshore_cluster",
"wind_farms": [example_farm, example_farm],
})

# ModelChain with wind farm
mc_farm = TurbineClusterModelChain(
example_farm, wake_losses_model=None,
).run_model(weather)
flh_farm = mc_farm.power_output.sum() / example_farm.nominal_power

# ModelChain with wind cluster
mc_cluster = TurbineClusterModelChain(
example_cluster, wake_losses_model=None,
).run_model(weather)
flh_cluster = mc_cluster.power_output.sum() / example_cluster.nominal_power

print("Full Load Hours of cluster:", flh_cluster)
print("Full Load Hours of farm:", flh_farm)


if __name__ == "__main__":
run_example()
Loading

0 comments on commit 255be72

Please sign in to comment.