Listing, Retrieving, and Filtering¶
We assume that you have generated a SDK for the Windmill
model and have a client ready to go.
from windmill import WindmillClient
client = WindmillClient.from_toml("config.toml")
Reading Instances: List and Retrieve¶
Lets list the available windmills:
windmills = client.windmill.list()
windmills
space | external_id | blades | capacity | metmast | nacelle | name | rotor | windfarm | node_type | data_record | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | windmill-instances | hornsea_1_mill_3 | [blade:1, blade:2, blade:3, bladewrite:1, blad... | 7.0 | None | nacellewrite:1 | hornsea_1_mill_3 | rotorwrite:1 | Hornsea 1 | None | {'version': 2, 'last_updated_time': 2024-02-10... |
1 | windmill-instances | hornsea_1_mill_2 | [blade:4, blade:5, blade:6, bladewrite:4, blad... | 7.0 | None | nacellewrite:2 | hornsea_1_mill_2 | rotorwrite:2 | Hornsea 1 | None | {'version': 2, 'last_updated_time': 2024-02-10... |
2 | windmill-instances | hornsea_1_mill_1 | [blade:7, blade:8, blade:9, bladewrite:7, blad... | 7.0 | None | nacellewrite:3 | hornsea_1_mill_1 | rotorwrite:3 | Hornsea 1 | None | {'version': 2, 'last_updated_time': 2024-02-10... |
3 | windmill-instances | hornsea_1_mill_4 | [blade:10, blade:11, blade:12, bladewrite:10, ... | 7.0 | None | nacellewrite:4 | hornsea_1_mill_4 | rotorwrite:4 | Hornsea 1 | None | {'version': 2, 'last_updated_time': 2024-02-10... |
4 | windmill-instances | hornsea_1_mill_5 | [blade:13, blade:14, blade:15, bladewrite:13, ... | 7.0 | None | nacellewrite:5 | hornsea_1_mill_5 | rotorwrite:5 | Hornsea 1 | None | {'version': 2, 'last_updated_time': 2024-02-10... |
5 | windmill-instances | windmill:demo | [windmill:demo:blade1, windmill:demo:blade2, w... | 10.0 | None | windmill:demo:nacelle | Windmill ATH | windmill:demo:rotor | Fornebu | None | {'version': 1, 'last_updated_time': 2024-03-09... |
The windmill view has edges to Blades and Metmast. When we do a list
or retrieve
call on the client.windmill
, edges are automatically added with the external ID to the end node.
type Windmill {
name: String
windfarm: String
capacity: Float
rotor: Rotor
nacelle: Nacelle
blades: [Blade]
metmast: [Metmast]
}
This means that we easily can use those external ids to retrieve for example a sblade
director:
windmill3 = windmills[0]
windmill3
value | |
---|---|
space | windmill-instances |
external_id | hornsea_1_mill_3 |
data_record | {'version': 2, 'last_updated_time': 2024-02-10... |
node_type | None |
blades | [blade:1, blade:2, blade:3, bladewrite:1, blad... |
capacity | 7.0 |
metmast | None |
nacelle | nacellewrite:1 |
name | hornsea_1_mill_3 |
rotor | rotorwrite:1 |
windfarm | Hornsea 1 |
blade1 = client.blade.retrieve(external_id="blade:1")
blade1
value | |
---|---|
space | windmill-instances |
external_id | blade:1 |
data_record | {'version': 1, 'last_updated_time': 2023-12-25... |
node_type | None |
is_damaged | False |
name | A |
sensor_positions | [sensorposition:1, sensorposition:2, sensorpos... |
If we want to avoid retrieving the edges when doing .list
call we can set the parameter retrieve_edges
to false
client.windmill.list(retrieve_edges=False)
space | external_id | blades | capacity | metmast | nacelle | name | rotor | windfarm | node_type | data_record | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | windmill-instances | hornsea_1_mill_3 | None | 7.0 | None | nacellewrite:1 | hornsea_1_mill_3 | rotorwrite:1 | Hornsea 1 | None | {'version': 2, 'last_updated_time': 2024-02-10... |
1 | windmill-instances | hornsea_1_mill_2 | None | 7.0 | None | nacellewrite:2 | hornsea_1_mill_2 | rotorwrite:2 | Hornsea 1 | None | {'version': 2, 'last_updated_time': 2024-02-10... |
2 | windmill-instances | hornsea_1_mill_1 | None | 7.0 | None | nacellewrite:3 | hornsea_1_mill_1 | rotorwrite:3 | Hornsea 1 | None | {'version': 2, 'last_updated_time': 2024-02-10... |
3 | windmill-instances | hornsea_1_mill_4 | None | 7.0 | None | nacellewrite:4 | hornsea_1_mill_4 | rotorwrite:4 | Hornsea 1 | None | {'version': 2, 'last_updated_time': 2024-02-10... |
4 | windmill-instances | hornsea_1_mill_5 | None | 7.0 | None | nacellewrite:5 | hornsea_1_mill_5 | rotorwrite:5 | Hornsea 1 | None | {'version': 2, 'last_updated_time': 2024-02-10... |
5 | windmill-instances | windmill:demo | None | 10.0 | None | windmill:demo:nacelle | Windmill ATH | windmill:demo:rotor | Fornebu | None | {'version': 1, 'last_updated_time': 2024-03-09... |
We can investigate the data records by using the data_records
property. Note the data records contains information about when the entry was made into CDF, the version of it and so on
windmills = client.windmill.list()
windmills.data_records
version | last_updated_time | created_time | deleted_time | |
---|---|---|---|---|
0 | 2 | 2024-02-10 09:30:16.893000+00:00 | 2023-12-25 07:47:50.040000+00:00 | None |
1 | 2 | 2024-02-10 09:30:16.893000+00:00 | 2023-12-25 07:47:50.040000+00:00 | None |
2 | 2 | 2024-02-10 09:30:16.893000+00:00 | 2023-12-25 07:47:50.040000+00:00 | None |
3 | 2 | 2024-02-10 09:30:16.893000+00:00 | 2023-12-25 07:47:50.040000+00:00 | None |
4 | 2 | 2024-02-10 09:30:16.893000+00:00 | 2023-12-25 07:47:50.040000+00:00 | None |
5 | 1 | 2024-03-09 07:46:38.476000+00:00 | 2024-03-09 07:46:38.476000+00:00 | None |
client.blade.list(limit=5).data_records
version | last_updated_time | created_time | deleted_time | |
---|---|---|---|---|
0 | 1 | 2023-12-25 07:47:50.040000+00:00 | 2023-12-25 07:47:50.040000+00:00 | None |
1 | 1 | 2023-12-25 07:47:50.040000+00:00 | 2023-12-25 07:47:50.040000+00:00 | None |
2 | 1 | 2023-12-25 07:47:50.040000+00:00 | 2023-12-25 07:47:50.040000+00:00 | None |
3 | 1 | 2023-12-25 07:47:50.040000+00:00 | 2023-12-25 07:47:50.040000+00:00 | None |
4 | 1 | 2023-12-25 07:47:50.040000+00:00 | 2023-12-25 07:47:50.040000+00:00 | None |
To dictionary and JSON¶
Note that all the data classes returned by the API is pydantic
data classes. That means that methods such as .model_dump()
and .model_dump_json()
are readaliy available, or .dict()
and .json()
if you use pydantic
v1.
windmill = client.windmill.retrieve("hornsea_1_mill_4")
windmill.model_dump()
{'space': 'windmill-instances', 'external_id': 'hornsea_1_mill_4', 'data_record': {'version': 2, 'last_updated_time': datetime.datetime(2024, 2, 10, 9, 30, 16, 893000, tzinfo=TzInfo(UTC)), 'created_time': datetime.datetime(2023, 12, 25, 7, 47, 50, 40000, tzinfo=TzInfo(UTC)), 'deleted_time': None}, 'node_type': None, 'blades': ['blade:10', 'blade:11', 'blade:12', 'bladewrite:10', 'bladewrite:11', 'bladewrite:12'], 'capacity': 7.0, 'metmast': None, 'nacelle': 'nacellewrite:4', 'name': 'hornsea_1_mill_4', 'rotor': 'rotorwrite:4', 'windfarm': 'Hornsea 1'}
Note that for simplicity there pygen
wraps the model_dump
with the method dump
. This is to have the same method for both pydantic
v1
and v2
.
windmill.dump()
{'space': 'windmill-instances', 'externalId': 'hornsea_1_mill_4', 'data_record': {'version': 2, 'last_updated_time': datetime.datetime(2024, 2, 10, 9, 30, 16, 893000, tzinfo=TzInfo(UTC)), 'created_time': datetime.datetime(2023, 12, 25, 7, 47, 50, 40000, tzinfo=TzInfo(UTC)), 'deleted_time': None}, 'node_type': None, 'blades': ['blade:10', 'blade:11', 'blade:12', 'bladewrite:10', 'bladewrite:11', 'bladewrite:12'], 'capacity': 7.0, 'metmast': None, 'nacelle': 'nacellewrite:4', 'name': 'hornsea_1_mill_4', 'rotor': 'rotorwrite:4', 'windfarm': 'Hornsea 1'}
windmill.model_dump_json()
'{"space":"windmill-instances","external_id":"hornsea_1_mill_4","data_record":{"version":2,"last_updated_time":"2024-02-10T09:30:16.893000Z","created_time":"2023-12-25T07:47:50.040000Z","deleted_time":null},"node_type":null,"blades":["blade:10","blade:11","blade:12","bladewrite:10","bladewrite:11","bladewrite:12"],"capacity":7.0,"metmast":null,"nacelle":"nacellewrite:4","name":"hornsea_1_mill_4","rotor":"rotorwrite:4","windfarm":"Hornsea 1"}'
Furhermore, note that properties such as space
, version
, last_updated_time
are showing up when we call model_dump()
and model_json_dump()
. The reason is that, when we display an object in a Jupyter notebook, the data classes from pygen
is set up to automatically call .to_pandas()
. The .to_pandas()
method skips the node
properties by default to avoid cluttering the properties that are special to the node type. We can include them by setting the parameter include_instance_properties
to True
windmill.to_pandas()
space windmill-instances external_id hornsea_1_mill_4 data_record {'version': 2, 'last_updated_time': 2024-02-10... node_type None blades [blade:10, blade:11, blade:12, bladewrite:10, ... capacity 7.0 metmast None nacelle nacellewrite:4 name hornsea_1_mill_4 rotor rotorwrite:4 windfarm Hornsea 1 dtype: object
Filtering Instances: List¶
pygen
automatically generates filters for the list method based on the propery types of the fields in the views.
For example, if we want to find all windmills with capacity above 6.0 we can do it as follows
client.windmill.list(min_capacity=6.0)
space | external_id | blades | capacity | metmast | nacelle | name | rotor | windfarm | node_type | data_record | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | windmill-instances | hornsea_1_mill_3 | [blade:1, blade:2, blade:3, bladewrite:1, blad... | 7.0 | None | nacellewrite:1 | hornsea_1_mill_3 | rotorwrite:1 | Hornsea 1 | None | {'version': 2, 'last_updated_time': 2024-02-10... |
1 | windmill-instances | hornsea_1_mill_2 | [blade:4, blade:5, blade:6, bladewrite:4, blad... | 7.0 | None | nacellewrite:2 | hornsea_1_mill_2 | rotorwrite:2 | Hornsea 1 | None | {'version': 2, 'last_updated_time': 2024-02-10... |
2 | windmill-instances | hornsea_1_mill_1 | [blade:7, blade:8, blade:9, bladewrite:7, blad... | 7.0 | None | nacellewrite:3 | hornsea_1_mill_1 | rotorwrite:3 | Hornsea 1 | None | {'version': 2, 'last_updated_time': 2024-02-10... |
3 | windmill-instances | hornsea_1_mill_4 | [blade:10, blade:11, blade:12, bladewrite:10, ... | 7.0 | None | nacellewrite:4 | hornsea_1_mill_4 | rotorwrite:4 | Hornsea 1 | None | {'version': 2, 'last_updated_time': 2024-02-10... |
4 | windmill-instances | hornsea_1_mill_5 | [blade:13, blade:14, blade:15, bladewrite:13, ... | 7.0 | None | nacellewrite:5 | hornsea_1_mill_5 | rotorwrite:5 | Hornsea 1 | None | {'version': 2, 'last_updated_time': 2024-02-10... |
Or lets us find all windmills located at the windfarm Hornsea 1
client.windmill.list(windfarm="Hornsea 1")
space | external_id | blades | capacity | metmast | nacelle | name | rotor | windfarm | node_type | data_record | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | windmill-instances | hornsea_1_mill_3 | [blade:1, blade:2, blade:3, bladewrite:1, blad... | 7.0 | None | nacellewrite:1 | hornsea_1_mill_3 | rotorwrite:1 | Hornsea 1 | None | {'version': 2, 'last_updated_time': 2024-02-10... |
1 | windmill-instances | hornsea_1_mill_2 | [blade:4, blade:5, blade:6, bladewrite:4, blad... | 7.0 | None | nacellewrite:2 | hornsea_1_mill_2 | rotorwrite:2 | Hornsea 1 | None | {'version': 2, 'last_updated_time': 2024-02-10... |
2 | windmill-instances | hornsea_1_mill_1 | [blade:7, blade:8, blade:9, bladewrite:7, blad... | 7.0 | None | nacellewrite:3 | hornsea_1_mill_1 | rotorwrite:3 | Hornsea 1 | None | {'version': 2, 'last_updated_time': 2024-02-10... |
3 | windmill-instances | hornsea_1_mill_4 | [blade:10, blade:11, blade:12, bladewrite:10, ... | 7.0 | None | nacellewrite:4 | hornsea_1_mill_4 | rotorwrite:4 | Hornsea 1 | None | {'version': 2, 'last_updated_time': 2024-02-10... |
4 | windmill-instances | hornsea_1_mill_5 | [blade:13, blade:14, blade:15, bladewrite:13, ... | 7.0 | None | nacellewrite:5 | hornsea_1_mill_5 | rotorwrite:5 | Hornsea 1 | None | {'version': 2, 'last_updated_time': 2024-02-10... |
The available filters depends on the data type of the properties in the data model.
Typical filtering for the different data types are:
- Text -> Equals, Prefix, and In filters
- Number -> Range filter
- Boolean -> Equals filter
- Date and Timestamp -> Range filter
- Direct relation -> Equals and In filters
Next section: Searching