From 036287ffaae4b7ce0ecfc91356a6171825792824 Mon Sep 17 00:00:00 2001 From: Daniel Thom Date: Thu, 8 Feb 2024 14:26:10 -0700 Subject: [PATCH] Improve docs --- docs/explanation/system.md | 9 +++++-- docs/explanation/time_series.md | 36 ++++++++++++++++++++++++---- docs/index.md | 4 ++-- docs/reference/api/time_series.md | 9 +++++++ docs/tutorials/custom_system.md | 39 +++++++++++++++++++++++++++++-- 5 files changed, 86 insertions(+), 11 deletions(-) diff --git a/docs/explanation/system.md b/docs/explanation/system.md index 15471b5..56c1b04 100644 --- a/docs/explanation/system.md +++ b/docs/explanation/system.md @@ -9,7 +9,7 @@ Refer to the [System API](#system-api) for complete information. Parent packages must choose one of the following: 1. Derive a custom System class that inherits from `infrasys.System`. Re-implement methods -as desired. +as desired. Add custom attributes to the System that will be serialized to JSON. - Reimplement `System.add_components` in order to perform custom validation or custom behavior. For example, a package may implement a load that @@ -29,4 +29,9 @@ as desired. 2. Implement an independent System class and compose the `infrasys.System`. This can be beneficial if you want to make the underlying system opaque to users. -3. Use `infrasys.System` directly. This is probably not what most users want. + - This pattern requires that you call `System.to_json()` with the keyword argument `data` set + to a dictionary containing your system's attributes. `infrasys` will add its contents to a + field called `system` inside that dictionary. + +3. Use `infrasys.System` directly. This is probably not what most packages want because they will +not be able to serialize custom attributes or implement specialized behavior as discussed above. diff --git a/docs/explanation/time_series.md b/docs/explanation/time_series.md index 00c2ec9..0497f37 100644 --- a/docs/explanation/time_series.md +++ b/docs/explanation/time_series.md @@ -1,9 +1,35 @@ # Time Series -Infrastructure systems supports time series data expressed as a one-dimensional array of floats. -Users must provide a `variable_name` that is typically the field of a component being modeled. For -example, if the user has a time array associated with the active power of a generator, they would assign -`variable_name = "active_power"`. Users can attach their own attributes to each time array. For example, -there might be different profiles for different model years. +Infrastructure systems supports time series data expressed as a one-dimensional array of floats +using the class [SingleTimeSeries](#singe-time-series-api). Users must provide a `variable_name` +that is typically the field of a component being modeled. For example, if the user has a time array +associated with the active power of a generator, they would assign +`variable_name = "active_power"`. + +Here is an example of how to create an instance of `SingleTimeSeries`: + +```python + import random + time_series = SingleTimeSeries.from_array( + data=[random.random() for x in range(24)], + variable_name="active_power", + initial_time=datetime(year=2030, month=1, day=1), + resolution=timedelta(hours=1), + ) +``` + +Users can attach their own attributes to each time array. For example, +there might be different profiles for different scenarios or model years. + +```python + time_series = SingleTimeSeries.from_array( + data=[random.random() for x in range(24)], + variable_name="active_power", + initial_time=datetime(year=2030, month=1, day=1), + resolution=timedelta(hours=1), + scenario="high", + model_year="2035", + ) +``` ## Behaviors Users can customize time series behavior with these flags passed to the `System` constructor: diff --git a/docs/index.md b/docs/index.md index 930368b..c559390 100644 --- a/docs/index.md +++ b/docs/index.md @@ -2,8 +2,8 @@ This package implements a data store for components and time series in support of Python-based modeling packages. While it is designed to support teams modeling transmission and distribution -systems, it can be used by any package that needs to store components (e.g., generators and buses) -that have quantities (e.g., power and voltage) which may vary over time. +systems for electrical grids, it can be used by any package that needs to store components (e.g., +generators and buses) that have quantities (e.g., power and voltage) which may vary over time. ## Features - Stores components in data structures that provide fast lookup and iteration by type and name. diff --git a/docs/reference/api/time_series.md b/docs/reference/api/time_series.md index da15af5..0e3c7f5 100644 --- a/docs/reference/api/time_series.md +++ b/docs/reference/api/time_series.md @@ -7,3 +7,12 @@ .. autopydantic_model:: infrasys.time_series_models.TimeSeriesData :members: ``` + +```{eval-rst} +.. _singe-time-series-api: +``` + +```{eval-rst} +.. autopydantic_model:: infrasys.time_series_models.SingleTimeSeries + :members: +``` diff --git a/docs/tutorials/custom_system.md b/docs/tutorials/custom_system.md index 36ea185..51426ef 100644 --- a/docs/tutorials/custom_system.md +++ b/docs/tutorials/custom_system.md @@ -1,13 +1,15 @@ # Custom System -This tutorial describes how to create a custom system in a parent package. +This tutorial describes how to create and use a custom system in a parent package. 1. Define the system. This example defines some custom attributes to illustrate serialization and de-serialization behaviors. ```python +from typing import Any + from infrasys import System -class System(System): +class CustomSystem(System): """Custom System""" def __init__(self, my_attribute=5, *args, **kwargs): @@ -34,6 +36,7 @@ can handle format changes that might occur in the future. 2. Define some component classes. ```python +from uuid import UUID from infrasys.component_models import ComponentWithQuantities from infrasys.location import Location @@ -85,3 +88,35 @@ what a component might look like in the REPL. - The `Bus` class implements a custom check when it is added to the system. It raises an exception if its `Location` object is not already attached to the system. The same could be done for generators and buses. + +3. Build a system. + +```python +import random +from datetime import datetime, timedelta + +from infrasys.location import Location +from infrasys.time_series_models import SingleTimeSeries + +system = CustomSystem(name="my_system", my_attribute=10) +location = Location(x=0.0, y=0.0) +bus = Bus(name="bus1", voltage=1.1, coordinates=location) +gen = Generator(name="gen1", available=True, bus=bus, active_power=1.2, rating=1.1) +system.add_components(location, bus, gen) +time_series = SingleTimeSeries.from_array( + data=[random.random() for x in range(24)], + variable_name="active_power", + initial_time=datetime(year=2030, month=1, day=1), + resolution=timedelta(hours=1), +) +system.add_time_series(time_series, gen) +``` + +4. Serialize and de-serialize the system. + +```python +system.to_json("system.json") +system2 = CustomSystem.from_json("system.json") +assert system.get_component(Generator, "gen1").active_power == \ + system2.get_component(Generator, "gen1").active_power +```