Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: merge develop into master for v0.5.0 release #583

Merged
merged 13 commits into from
Feb 4, 2022
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
name: Lint

on: push
on:
push:
pull_request:
branches:
- develop

jobs:
formatting:
Expand Down
8 changes: 6 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
name: Pytest

on: push
on:
push:
pull_request:
branches:
- develop

jobs:
test:
Expand All @@ -9,7 +13,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [3.7, 3.8, 3.9]
python-version: [3.8, 3.9, '3.10']

name: Python ${{ matrix.python-version }}
steps:
Expand Down
1 change: 1 addition & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ tqdm = "==4.29.1"
requests = "~=2.25"
fs = "*"
"fs.sshfs" = "*"
fs-azureblob = "*"
608 changes: 315 additions & 293 deletions Pipfile.lock

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: '3.7'

services:
powersimdata:
image: powersimdata:latest
Expand Down
9 changes: 6 additions & 3 deletions powersimdata/data_access/data_access.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
import fs as fs2
from fs.tempfs import TempFS

from powersimdata.data_access.profile_helper import ProfileHelper
from powersimdata.data_access.profile_helper import (
get_profile_version_cloud,
get_profile_version_local,
)
from powersimdata.data_access.ssh_fs import WrapSSHFS
from powersimdata.utility import server_setup

Expand Down Expand Up @@ -127,8 +130,8 @@ def get_profile_version(self, grid_model, kind):
:param str kind: *'demand'*, *'hydro'*, *'solar'* or *'wind'*.
:return: (*list*) -- available profile version.
"""
blob_version = ProfileHelper.get_profile_version_cloud(grid_model, kind)
local_version = ProfileHelper.get_profile_version_local(grid_model, kind)
blob_version = get_profile_version_cloud(grid_model, kind)
local_version = get_profile_version_local(grid_model, kind)
return list(set(blob_version + local_version))


Expand Down
72 changes: 33 additions & 39 deletions powersimdata/data_access/profile_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,39 @@
from powersimdata.utility import server_setup


def _get_profile_version(_fs, kind):
"""Returns available raw profiles from the give filesystem
:param fs.base.FS _fs: filesystem instance
:param str kind: *'demand'*, *'hydro'*, *'solar'* or *'wind'*.
:return: (*list*) -- available profile version.
"""
matching = [f for f in _fs.listdir(".") if kind in f]
return [f.lstrip(f"{kind}_").rstrip(".csv") for f in matching]


def get_profile_version_cloud(grid_model, kind):
"""Returns available raw profile from blob storage.

:param str grid_model: grid model.
:param str kind: *'demand'*, *'hydro'*, *'solar'* or *'wind'*.
:return: (*list*) -- available profile version.
"""
bfs = fs.open_fs("azblob://besciences@profiles").opendir(f"raw/{grid_model}")
return _get_profile_version(bfs, kind)


def get_profile_version_local(grid_model, kind):
"""Returns available raw profile from local file.

:param str grid_model: grid model.
:param str kind: *'demand'*, *'hydro'*, *'solar'* or *'wind'*.
:return: (*list*) -- available profile version.
"""
profile_dir = fs.path.join(server_setup.LOCAL_DIR, "raw", grid_model)
lfs = fs.open_fs(profile_dir)
return _get_profile_version(lfs, kind)


class ProfileHelper:
BASE_URL = "https://besciences.blob.core.windows.net/profiles"

Expand Down Expand Up @@ -52,42 +85,3 @@ def download_file(file_name, from_dir):
pbar.update(len(chunk))

return dest

@staticmethod
def parse_version(grid_model, kind, version):
"""Parse available versions from the given spec.

:param str grid_model: grid model.
:param str kind: *'demand'*, *'hydro'*, *'solar'* or *'wind'*.
:param dict version: version information per grid model.
:return: (*list*) -- available profile version.
"""
if grid_model in version and kind in version[grid_model]:
return version[grid_model][kind]
print("No %s profiles available." % kind)
return []

@staticmethod
def get_profile_version_cloud(grid_model, kind):
"""Returns available raw profile from blob storage.

:param str grid_model: grid model.
:param str kind: *'demand'*, *'hydro'*, *'solar'* or *'wind'*.
:return: (*list*) -- available profile version.
"""

resp = requests.get(f"{ProfileHelper.BASE_URL}/version.json")
return ProfileHelper.parse_version(grid_model, kind, resp.json())

@staticmethod
def get_profile_version_local(grid_model, kind):
"""Returns available raw profile from local file.

:param str grid_model: grid model.
:param str kind: *'demand'*, *'hydro'*, *'solar'* or *'wind'*.
:return: (*list*) -- available profile version.
"""
profile_dir = fs.path.join(server_setup.LOCAL_DIR, "raw", grid_model)
lfs = fs.open_fs(profile_dir)
matching = [f for f in lfs.listdir(".") if kind in f]
return [f.lstrip(f"{kind}_").rstrip(".csv") for f in matching]
33 changes: 16 additions & 17 deletions powersimdata/data_access/tests/test_profile_helper.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
from powersimdata.data_access.profile_helper import ProfileHelper


def test_parse_version_default():
assert [] == ProfileHelper.parse_version("usa_tamu", "solar", {})


def test_parse_version_missing_key():
version = {"solar": ["v123"]}
assert [] == ProfileHelper.parse_version("usa_tamu", "solar", version)


def test_parse_version():
expected = ["v123", "v456"]
version = {"usa_tamu": {"solar": expected}}
assert expected == ProfileHelper.parse_version("usa_tamu", "solar", version)
assert [] == ProfileHelper.parse_version("usa_tamu", "hydro", version)
from fs.tempfs import TempFS

from powersimdata.data_access.profile_helper import ProfileHelper, _get_profile_version


def test_get_profile_version():
with TempFS() as tmp_fs:
tfs = tmp_fs.makedirs("raw/usa_tamu", recreate=True)
tfs.touch("solar_vOct2022.csv")
tfs.touch("foo_v1.0.1.csv")
v_solar = _get_profile_version(tfs, "solar")
v_foo = _get_profile_version(tfs, "foo")
v_missing = _get_profile_version(tfs, "missing")
assert "vOct2022" == v_solar[0]
assert "v1.0.1" == v_foo[0]
assert [] == v_missing


def test_get_file_components():
Expand Down
4 changes: 2 additions & 2 deletions powersimdata/design/generation/cost_curves.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def linearize_gencost(input_grid, num_segments=1):
price_label = "f" + str(i + 1)
capacity_data = plant.Pmin + power_step * i
price_data = (
quad_term * capacity_data ** 2 + lin_term * capacity_data + const_term
quad_term * capacity_data**2 + lin_term * capacity_data + const_term
)
gencost_after.loc[dispatchable_gens, capacity_label] = capacity_data[
dispatchable_gens
Expand All @@ -76,7 +76,7 @@ def linearize_gencost(input_grid, num_segments=1):
nondispatchable_gens, "n"
]
power = plant.Pmax
price_data = quad_term * power ** 2 + lin_term * power + const_term
price_data = quad_term * power**2 + lin_term * power + const_term
gencost_after.loc[nondispatchable_gens, ["c2", "c1"]] = 0
gencost_after.loc[nondispatchable_gens, "c0"] = price_data[nondispatchable_gens]

Expand Down
13 changes: 13 additions & 0 deletions powersimdata/input/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def check_grid(grid):
_check_line_voltages,
_check_plant_against_gencost,
_check_connected_components,
_check_for_loop_branches,
]:
try:
check(grid, error_messages)
Expand Down Expand Up @@ -225,6 +226,18 @@ def _check_connected_components(grid, error_messages):
)


def _check_for_loop_branches(grid, error_messages):
"""Check whether any branches in a grid have the same start and end bus.

:param powersimdata.input.grid.Grid grid: grid or grid-like object to check.
:param list error_messages: list, to be appended to with a str if:
there are any branches with the same start and end bus.
"""
if not all(grid.branch.from_bus_id != grid.branch.to_bus_id):
loop_lines = grid.branch.query("from_bus_id == to_bus_id").index # noqa: F841
error_messages.append(f"This grid contains loop lines: {list(loop_lines)}")


def _check_grid_models_match(grid1, grid2):
"""Check whether an object is an internally-consistent Grid object.

Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ coverage
pytest-cov
fs
fs.sshfs
fs-azureblob
3 changes: 2 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ classifiers =
[options]
zip_safe = False
packages = find:
python_requires = >=3.7
python_requires = >=3.8
install_requires =
networkx
numpy
Expand All @@ -31,6 +31,7 @@ install_requires =
requests
fs
fs.sshfs
fs-azureblob

[options.package_data]
powersimdata =
Expand Down