Skip to content

Commit

Permalink
Offer asset grouping by location (#148)
Browse files Browse the repository at this point in the history
* group assets by location, keep special 'Charge Point' case. Fix a few spelling problems.

Co-authored-by: Nicolas Höning <nicolas@seita.nl>
  • Loading branch information
create-issue-branch[bot] and nhoening committed Jun 29, 2021
1 parent bc341c6 commit 89fd9fe
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 27 deletions.
2 changes: 2 additions & 0 deletions documentation/changelog.rst
Expand Up @@ -7,6 +7,8 @@ v0.6.0 | July XX, 2021

New features
-----------
* Analytics view offers grouping of all assets by location [see `PR #148 <http://www.github.com/SeitaBV/flexmeasures/pull/148>`_]


Bugfixes
-----------
Expand Down
48 changes: 29 additions & 19 deletions flexmeasures/data/services/resources.py
Expand Up @@ -116,8 +116,8 @@ def get_asset_group_queries(
Valid names are:
- "renewables", to query all solar and wind assets
- "EVSE", to query all Electric Vehicle Supply Equipment
- "each Charge Point", to query each individual Charge Point
(i.e. all EVSE at 1 location)
- "location", to query each individual location with assets
(i.e. all EVSE at 1 location or each household)
:param all_users: if True, do not filter out assets that do not belong to the user (use with care)
"""

Expand All @@ -141,19 +141,18 @@ def get_asset_group_queries(
asset_type_name=asset_type.name
)

# 3. Finally, we group assets by location
if "location" in custom_additional_groups:
asset_queries.update(get_location_queries())

if not all_users:
asset_queries = mask_inaccessible_assets(asset_queries)

# 3. We group EVSE assets by location (if they share a location, they belong to the same Charge Point)
if "each Charge Point" in custom_additional_groups:
asset_queries.update(get_charge_point_queries())

return asset_queries


def get_charge_point_queries() -> Dict[str, Query]:
def get_location_queries() -> Dict[str, Query]:
"""
A Charge Point is defined similarly to asset groups (see get_asset_group_queries).
We group EVSE assets by location (if they share a location, they belong to the same Charge Point)
Like get_asset_group_queries, the values in the returned dict still need an executive call, like all(), count() or first().
Expand All @@ -163,18 +162,29 @@ def get_charge_point_queries() -> Dict[str, Query]:
evse_display_name = "Seoul Hilton - charger 1"
Then:
charge_point_display_name = "Seoul Hilton (Charge Point)"
A Charge Point is a special case. If all assets on a location are of type EVSE,
we can call the location a "Charge Point".
"""
asset_queries = {}
all_evse_assets = Asset.query.filter(
Asset.asset_type_name.in_(["one-way_evse", "two-way_evse"])
).all()
cp_groups = group_assets_by_location(all_evse_assets)
for cp_group in cp_groups:
charge_point_name = cp_group[0].display_name.split(" -")[0] + " (Charge Point)"
asset_queries[charge_point_name] = Asset.query.filter(
Asset.name.in_([evse.name for evse in cp_group])
all_assets = Asset.query.all()
loc_groups = group_assets_by_location(all_assets)
for loc_group in loc_groups:
if len(loc_group) == 1:
continue
location_type = "(Location)"
if all(
[
asset.asset_type_name in ["one-way_evse", "two-way_evse"]
for asset in loc_group
]
):
location_type = "(Charge Point)"
location_name = f"{loc_group[0].display_name.split(' -')[0]} {location_type}"
asset_queries[location_name] = Asset.query.filter(
Asset.name.in_([asset.name for asset in loc_group])
)
return mask_inaccessible_assets(asset_queries)
return asset_queries


def mask_inaccessible_assets(
Expand Down Expand Up @@ -316,7 +326,7 @@ def __init__(self, name: str):

# Query assets for all users to set some public information about the resource
asset_queries = get_asset_group_queries(
custom_additional_groups=["renewables", "EVSE", "each Charge Point"],
custom_additional_groups=["renewables", "EVSE", "location"],
all_users=True,
)
asset_query = (
Expand Down Expand Up @@ -382,7 +392,7 @@ def hover_label(self) -> Optional[str]:

@property
def parameterized_name(self) -> str:
"""Get a parameterized name for use in javascript."""
"""Get a parametrized name for use in javascript."""
return parameterize(self.name)

def load_sensor_data(
Expand Down
16 changes: 8 additions & 8 deletions flexmeasures/ui/views/analytics.py
Expand Up @@ -56,7 +56,7 @@ def analytics_view():
markets = get_markets()
assets = get_assets(order_by_asset_attribute="display_name", order_direction="asc")
asset_groups = get_asset_group_queries(
custom_additional_groups=["renewables", "EVSE", "each Charge Point"]
custom_additional_groups=["renewables", "EVSE", "location"]
)
asset_group_names: List[str] = [
group for group in asset_groups if asset_groups[group].count() > 0
Expand Down Expand Up @@ -138,7 +138,7 @@ def analytics_view():
tools=tools,
)
# the bottom plots need a separate x axis if they get their own legend (Bokeh complains otherwise)
# this means in that in that corner case zooming will not work across all foour plots
# this means in that in that corner case zooming will not work across all four plots
prices_fig = make_prices_figure(
data["prices"],
data["prices_forecast"],
Expand Down Expand Up @@ -230,7 +230,7 @@ def analytics_data_view(content, content_type):
# Maybe move some of this stuff into get_data_and_metrics
assets = get_assets(order_by_asset_attribute="display_name", order_direction="asc")
asset_groups = get_asset_group_queries(
custom_additional_groups=["renewables", "EVSE", "each Charge Point"]
custom_additional_groups=["renewables", "EVSE", "location"]
)
asset_group_names: List[str] = [
group for group in asset_groups if asset_groups[group].count() > 0
Expand Down Expand Up @@ -263,7 +263,7 @@ def analytics_data_view(content, content_type):
selected_resource.assets,
)

hor = session["forecast_horizon"]
horizon = session["forecast_horizon"]
rev_cost_header = (
"costs/revenues" if show_consumption_as_positive else "revenues/costs"
)
Expand All @@ -276,19 +276,19 @@ def analytics_data_view(content, content_type):
"power_data_label",
"power",
"power_forecast_label",
f"power_forecast_{hor}",
f"power_forecast_{horizon}",
f"{weather_type}_label",
f"{weather_type}",
f"{weather_type}_forecast_label",
f"{weather_type}_forecast_{hor}",
f"{weather_type}_forecast_{horizon}",
"price_label",
f"price_on_{selected_market.name}",
"price_forecast_label",
f"price_forecast_{hor}",
f"price_forecast_{horizon}",
f"{rev_cost_header}_label",
rev_cost_header,
f"{rev_cost_header}_forecast_label",
f"{rev_cost_header}_forecast_{hor}",
f"{rev_cost_header}_forecast_{horizon}",
]
source_units = [
"",
Expand Down

0 comments on commit 89fd9fe

Please sign in to comment.