From 50a11fa7a729828d89ec6f695256adff889b8c37 Mon Sep 17 00:00:00 2001 From: Andre Date: Wed, 22 Nov 2023 17:22:42 +0100 Subject: [PATCH] Add PSR Capacity to psr_metadata Signed-off-by: Andre --- .../src/api/psr_metadata/views.py | 105 +++++++++++++++-- .../src/api/seed.py | 111 ++++++++++++------ 2 files changed, 174 insertions(+), 42 deletions(-) diff --git a/power_systems_data_api_demonstrator/src/api/psr_metadata/views.py b/power_systems_data_api_demonstrator/src/api/psr_metadata/views.py index e981e34..7bfccef 100644 --- a/power_systems_data_api_demonstrator/src/api/psr_metadata/views.py +++ b/power_systems_data_api_demonstrator/src/api/psr_metadata/views.py @@ -1,5 +1,5 @@ from enum import Enum -from typing import Annotated, Optional +from typing import Annotated, Optional, Sequence import pandas as pd from fastapi import APIRouter, Path, Query @@ -11,6 +11,12 @@ router = APIRouter() +class PowerUnit(str, Enum): + mw = "MW" + kw = "kW" + w = "W" + + class PSRList(SQLModel, table=True): id: str = Field(primary_key=True) level: int @@ -41,12 +47,6 @@ async def get_psr_list( return PSRListResponse(psr_list=psr_list) -class PowerUnit(str, Enum): - mw = "MW" - kw = "kW" - w = "W" - - class PSR(SQLModel): id: str @@ -72,6 +72,97 @@ class PSRCapacityResponse(SQLModel): capacity: list[PSRCapacity] +class Capacity(SQLModel): + value: float + startDatetime: str = Field(primary_key=True) + endDatetime: Optional[str] = None + + +class CapacityTable(Capacity, table=True): + id: str = Field(primary_key=True) + type: str = Field(primary_key=True) + unit: PowerUnit + technology: str + + +class FuelSource(SQLModel): + technology: str + type: str + unit: PowerUnit + capacity: list[Capacity] + + +class FuelSourceCapacity(SQLModel): + id: str = Field(primary_key=True) + fuelSource: list[FuelSource] + + +class FuelSourceCapacityResponse(SQLModel): + capacity: Sequence[FuelSourceCapacity] + + +@router.get( + "/power-system-resource/capacity", + summary="PSR CAPACITY", +) +async def get_psr_capacity( + id: Annotated[str, Query(description="Filter by PSR")] = "US-WECC-CISO", + session: Session = Depends(get_session), +) -> FuelSourceCapacityResponse: + result = session.execute(select(CapacityTable).filter_by(id=id)) + psr_capacity = result.scalars().all() + df = pd.DataFrame(g.dict() for g in psr_capacity) + print("This is the basic df") + print(df) + print(df.columns) + + # colapse the data frame to a single row per id and unit + df_psr_capacity = ( + df.groupby(["id", "unit", "technology", "type"]) + .agg( + { + "value": lambda x: list(x), + "startDatetime": lambda x: list(x), + "endDatetime": lambda x: list(x), + } + ) + .copy() + .reset_index() + ) + + print("This is after grouby") + print(df_psr_capacity.to_string()) + print(df_psr_capacity.columns) + + # print("this is psr capacity") + # print(df_psr_capacity) + + psr_capacity = [] + psr_capacity.append( + FuelSourceCapacity( + id=df_psr_capacity.loc[0, "id"], + fuelSource=[ + FuelSource( + technology=row["technology"], + type=row["type"], + unit=row["unit"], + capacity=[ + Capacity( + value=row["value"][i], + startDatetime=row["startDatetime"][i], + endDatetime=row["endDatetime"][i], + ) + for i in range(len(row["startDatetime"])) + ], + ) + for index, row in df_psr_capacity.iterrows() + ], + ) + ) + + return FuelSourceCapacityResponse(capacity=psr_capacity) + + @router.get( "/power-system-resource/transmission-capacity", summary="TRANSMISSION CAPACITY", diff --git a/power_systems_data_api_demonstrator/src/api/seed.py b/power_systems_data_api_demonstrator/src/api/seed.py index 5a8d444..73f19c5 100644 --- a/power_systems_data_api_demonstrator/src/api/seed.py +++ b/power_systems_data_api_demonstrator/src/api/seed.py @@ -11,6 +11,7 @@ TopologyLevel, ) from power_systems_data_api_demonstrator.src.api.psr_metadata.views import ( + CapacityTable, PSRInterconnectionTable, PSRList, ) @@ -83,48 +84,88 @@ def seed_fuelsource(session: Session) -> None: session.commit() +def extract_info(df: pd.DataFrame, column_name: str): + """ + Extracts the information from a column with a list of dicts and + adds them as columns to the dataframe. + + Input: + ---------- + df : pd.DataFrame + column_name : str + + Returns + ------- + df : pd.DataFrame + """ + df = df.explode(column_name).reset_index(drop=True) + extracted_info = df[column_name].apply(pd.Series).reset_index(drop=True) + df = df.join(extracted_info) + df = df.drop(column_name, axis=1) + + return df + + def seed_psr(session: Session) -> None: + psr_data = [] + generation_capacity = [] + transmission_capacity = [] + for grid_source in ["example"]: df = pd.read_json(os.path.join(DATA_DIR, grid_source, "psr_metadata.json")) + # PSR List + psr_data = [] + + for index, row in df.iterrows(): + psr_data.extend([PSRList(id=row["id"], level=row["topology_level"])]) + + # PSR GENERATION CAPACITY + + generation_capacity = [] + # select only the rows with generation capacity data + df_generation = df.dropna(subset=["fuelSource_capacity"]).copy() + df_generation = df_generation[["id", "fuelSource_capacity"]] + # extract fuelSource_capacity info + df_generation = extract_info(df_generation, "fuelSource_capacity") + df_generation = extract_info(df_generation, "capacity") + + for index, row in df_generation.iterrows(): + print("datetime") + print(pd.to_datetime(row["startDatetime"])) + capacity_table = CapacityTable( + id=row["id"], + unit=row["unit"], + type=row["type"], + technology=row["technology"], + value=row["value"], + startDatetime=row["startDatetime"], + ) - psr_data = [] + if not pd.isna(row["endDatetime"]): + capacity_table.endDatetime = row["endDatetime"] - for index, row in df.iterrows(): - psr_data.extend([PSRList(id=row["id"], level=row["topology_level"])]) + generation_capacity.extend([capacity_table]) - # extract transmission data from the dataframe dict - transmission_capacity = [] - # select only the rows with transmission capacity data - df_transmission = df.dropna(subset=["transmission_capacity"]).copy() - df_transmission = df_transmission[["id", "transmission_capacity"]] - # explode the transmission capacity list - df_transmission = df_transmission.explode("transmission_capacity") - # convert the dict to columns - transmission_data = ( - df_transmission["transmission_capacity"].apply(pd.Series).reset_index(drop=True) - ) - # remove the transmission_capacity column - df_transmission = df_transmission.drop("transmission_capacity", axis=1) - df_transmission = df_transmission.reset_index(drop=True) - # join the two dataframes - df_transmission = df_transmission.join(transmission_data) - print(df_transmission) - - for index, row in df_transmission.iterrows(): - print(row) - print(row["value"]) - print(type(row["value"])) - transmission_capacity.extend( - [ - PSRInterconnectionTable( - id=row["id"], - unit=row["unit"], - connectedPSR=row["connectedPSR"], - value=row["value"], - ) - ] - ) + # PSR TRANSMISSION CAPACITY + transmission_capacity = [] + # select only the rows with transmission capacity data + df_transmission = df.dropna(subset=["transmission_capacity"]).copy() + # extract transmission_capacity info + df_transmission = extract_info(df_transmission, "transmission_capacity") + + for index, row in df_transmission.iterrows(): + transmission_capacity.extend( + [ + PSRInterconnectionTable( + id=row["id"], + unit=row["unit"], + connectedPSR=row["connectedPSR"], + value=row["value"], + ) + ] + ) + session.add_all(generation_capacity) session.add_all(psr_data) session.add_all(transmission_capacity) session.commit()