Skip to content
Snippets Groups Projects
Commit cf02c73b authored by Andi Gerken's avatar Andi Gerken
Browse files

Renamed entity_poses to poses and select_entity_poses() to select_poses()

parent d7e6d77e
Branches
Tags
No related merge requests found
Pipeline #35782 passed
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#! /usr/bin/env python3 #! /usr/bin/env python3
import robofish.io import robofish.io
import numpy as np import numpy as np
from pathlib import Path from pathlib import Path
import os import os
# Helper function to enable relative paths from this file # Helper function to enable relative paths from this file
def full_path(path): def full_path(path):
return (Path(os.path.abspath("__file__")).parent / path).resolve() return (Path(os.path.abspath("__file__")).parent / path).resolve()
if __name__ == "__main__": if __name__ == "__main__":
# Create a new io file object with a 100x100cm world # Create a new io file object with a 100x100cm world
sf = robofish.io.File(world_size=[100, 100]) sf = robofish.io.File(world_size=[100, 100])
# create a simple obstacle, fixed in place, fixed outline # create a simple obstacle, fixed in place, fixed outline
obstacle_pose = [[50, 50, 0, 0]] obstacle_pose = [[50, 50, 0, 0]]
obstacle_outline = [[[-10, -10], [-10, 0], [0, 0], [0, -10]]] obstacle_outline = [[[-10, -10], [-10, 0], [0, 0], [0, -10]]]
obstacle_name = sf.create_entity( obstacle_name = sf.create_entity(
"obstacle", poses=obstacle_pose, outlines=obstacle_outline "obstacle", poses=obstacle_pose, outlines=obstacle_outline
) )
# create a robofish with 100 timesteps and 40ms between the timesteps. If we would not give a name, the name would be generated to be robot_1. # create a robofish with 100 timesteps and 40ms between the timesteps. If we would not give a name, the name would be generated to be robot_1.
robofish_timesteps = 4 robofish_timesteps = 4
robofish_poses = np.zeros((robofish_timesteps, 4)) robofish_poses = np.zeros((robofish_timesteps, 4))
sf.create_entity("robot", robofish_poses, name="robot", monotonic_step=40) sf.create_entity("robot", robofish_poses, name="robot", monotonic_step=40)
# create multiple fishes with timestamps. Since we don't specify names, but only the type "fish" the fishes will be named ["fish_1", "fish_2", "fish_3"] # create multiple fishes with timestamps. Since we don't specify names, but only the type "fish" the fishes will be named ["fish_1", "fish_2", "fish_3"]
agents = 3 agents = 3
timesteps = 5 timesteps = 5
timestamps = np.linspace(0, timesteps + 1, timesteps) timestamps = np.linspace(0, timesteps + 1, timesteps)
agent_poses = np.random.random((agents, timesteps, 4)) agent_poses = np.random.random((agents, timesteps, 4))
fish_names = sf.create_multiple_entities( fish_names = sf.create_multiple_entities(
"fish", agent_poses, monotonic_points=timestamps "fish", agent_poses, monotonic_points=timestamps
) )
# This would throw an exception if the file was invalid # This would throw an exception if the file was invalid
sf.validate() sf.validate()
# Save file validates aswell # Save file validates aswell
example_file = full_path("example.hdf5") example_file = full_path("example.hdf5")
sf.save(example_file) sf.save(example_file)
# Closing and opening files (just for demonstration) # Closing and opening files (just for demonstration)
sf.close() sf.close()
sf = robofish.io.File(path=example_file) sf = robofish.io.File(path=example_file)
print("\nEntity Names") print("\nEntity Names")
print(sf.entity_names) print(sf.entity_names)
# Get an array with all poses. As the length of poses varies per agent, it # Get an array with all poses. As the length of poses varies per agent, it
# is filled up with nans. The result is not interpolated and the time scales # is filled up with nans. The result is not interpolated and the time scales
# per agent are different. It is planned to create a warning in the case of # per agent are different. It is planned to create a warning in the case of
# different time scales and have another function, which generates an # different time scales and have another function, which generates an
# interpolated array. # interpolated array.
print("\nAll poses") print("\nAll poses")
print(sf.select_entity_poses()) print(sf.select_poses())
print("\nFish poses") print("\nFish poses")
print(sf.select_entity_poses(lambda e: e.category == "fish")) print(sf.select_poses(lambda e: e.category == "fish"))
print("\nFile structure") print("\nFile structure")
print(sf) print(sf)
``` ```
%% Output %% Output
Entity Names Entity Names
['fish_1', 'fish_2', 'fish_3', 'obstacle_1', 'robot'] ['fish_1', 'fish_2', 'fish_3', 'obstacle_1', 'robot']
All poses All poses
[[[8.86584103e-01 2.35670820e-01 5.41754842e-01 4.49850202e-01] [[[8.86584103e-01 2.35670820e-01 5.41754842e-01 4.49850202e-01]
[8.15511882e-01 4.78223324e-01 6.29803419e-01 1.12592392e-01] [8.15511882e-01 4.78223324e-01 6.29803419e-01 1.12592392e-01]
[1.53732300e-01 7.24954247e-01 9.38574493e-01 4.65665817e-01] [1.53732300e-01 7.24954247e-01 9.38574493e-01 4.65665817e-01]
[9.10354614e-01 4.47880208e-01 3.81429136e-01 9.67544317e-01] [9.10354614e-01 4.47880208e-01 3.81429136e-01 9.67544317e-01]
[6.07822955e-01 5.20158827e-01 8.17965686e-01 8.42760384e-01]] [6.07822955e-01 5.20158827e-01 8.17965686e-01 8.42760384e-01]]
[[2.29353935e-01 8.80753636e-01 7.94585168e-01 2.22074524e-01] [[2.29353935e-01 8.80753636e-01 7.94585168e-01 2.22074524e-01]
[6.13970399e-01 1.33511815e-02 2.89155185e-01 2.65219092e-01] [6.13970399e-01 1.33511815e-02 2.89155185e-01 2.65219092e-01]
[6.62197351e-01 6.47982001e-01 9.46004018e-02 6.59599364e-01] [6.62197351e-01 6.47982001e-01 9.46004018e-02 6.59599364e-01]
[4.86104101e-01 4.23153102e-01 1.39821902e-01 3.11809748e-01] [4.86104101e-01 4.23153102e-01 1.39821902e-01 3.11809748e-01]
[8.03322852e-01 9.52799857e-01 3.89638603e-01 6.43237352e-01]] [8.03322852e-01 9.52799857e-01 3.89638603e-01 6.43237352e-01]]
[[9.70978260e-01 6.75936878e-01 6.23196602e-01 8.42264950e-01] [[9.70978260e-01 6.75936878e-01 6.23196602e-01 8.42264950e-01]
[4.07079160e-01 8.46290290e-01 5.64092159e-01 3.56871307e-01] [4.07079160e-01 8.46290290e-01 5.64092159e-01 3.56871307e-01]
[4.84096229e-01 8.60232174e-01 1.39015794e-01 7.82253265e-01] [4.84096229e-01 8.60232174e-01 1.39015794e-01 7.82253265e-01]
[1.24170482e-01 2.21511930e-01 8.88282284e-02 4.53450561e-01] [1.24170482e-01 2.21511930e-01 8.88282284e-02 4.53450561e-01]
[1.28404438e-01 2.87771430e-02 4.57022637e-01 9.80571806e-01]] [1.28404438e-01 2.87771430e-02 4.57022637e-01 9.80571806e-01]]
[[5.00000000e+01 5.00000000e+01 0.00000000e+00 0.00000000e+00] [[5.00000000e+01 5.00000000e+01 0.00000000e+00 0.00000000e+00]
[ nan nan nan nan] [ nan nan nan nan]
[ nan nan nan nan] [ nan nan nan nan]
[ nan nan nan nan] [ nan nan nan nan]
[ nan nan nan nan]] [ nan nan nan nan]]
[[0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00] [[0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00] [0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00] [0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00] [0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ nan nan nan nan]]] [ nan nan nan nan]]]
Fish poses Fish poses
[[[0.8865841 0.23567082 0.54175484 0.4498502 ] [[[0.8865841 0.23567082 0.54175484 0.4498502 ]
[0.81551188 0.47822332 0.62980342 0.11259239] [0.81551188 0.47822332 0.62980342 0.11259239]
[0.1537323 0.72495425 0.93857449 0.46566582] [0.1537323 0.72495425 0.93857449 0.46566582]
[0.91035461 0.44788021 0.38142914 0.96754432] [0.91035461 0.44788021 0.38142914 0.96754432]
[0.60782295 0.52015883 0.81796569 0.84276038]] [0.60782295 0.52015883 0.81796569 0.84276038]]
[[0.22935393 0.88075364 0.79458517 0.22207452] [[0.22935393 0.88075364 0.79458517 0.22207452]
[0.6139704 0.01335118 0.28915519 0.26521909] [0.6139704 0.01335118 0.28915519 0.26521909]
[0.66219735 0.647982 0.0946004 0.65959936] [0.66219735 0.647982 0.0946004 0.65959936]
[0.4861041 0.4231531 0.1398219 0.31180975] [0.4861041 0.4231531 0.1398219 0.31180975]
[0.80332285 0.95279986 0.3896386 0.64323735]] [0.80332285 0.95279986 0.3896386 0.64323735]]
[[0.97097826 0.67593688 0.6231966 0.84226495] [[0.97097826 0.67593688 0.6231966 0.84226495]
[0.40707916 0.84629029 0.56409216 0.35687131] [0.40707916 0.84629029 0.56409216 0.35687131]
[0.48409623 0.86023217 0.13901579 0.78225327] [0.48409623 0.86023217 0.13901579 0.78225327]
[0.12417048 0.22151193 0.08882823 0.45345056] [0.12417048 0.22151193 0.08882823 0.45345056]
[0.12840444 0.02877714 0.45702264 0.98057181]]] [0.12840444 0.02877714 0.45702264 0.98057181]]]
File structure File structure
version: [1 0] version: [1 0]
world size: [100. 100.] world size: [100. 100.]
| entities | entities
|---| fish_1 |---| fish_1
|---|--- type: fish |---|--- type: fish
|---|--- poses: Shape (5, 4) |---|--- poses: Shape (5, 4)
|---|---| time |---|---| time
|---|---|--- monotonic points: Shape (5,) |---|---|--- monotonic points: Shape (5,)
|---| fish_2 |---| fish_2
|---|--- type: fish |---|--- type: fish
|---|--- poses: Shape (5, 4) |---|--- poses: Shape (5, 4)
|---|---| time |---|---| time
|---|---|--- monotonic points: Shape (5,) |---|---|--- monotonic points: Shape (5,)
|---| fish_3 |---| fish_3
|---|--- type: fish |---|--- type: fish
|---|--- poses: Shape (5, 4) |---|--- poses: Shape (5, 4)
|---|---| time |---|---| time
|---|---|--- monotonic points: Shape (5,) |---|---|--- monotonic points: Shape (5,)
|---| obstacle_1 |---| obstacle_1
|---|--- type: obstacle |---|--- type: obstacle
|---|--- outlines: Shape (1, 4, 2) |---|--- outlines: Shape (1, 4, 2)
|---|--- poses: Shape (1, 4) |---|--- poses: Shape (1, 4)
|---|---| time |---|---| time
|---| robot |---| robot
|---|--- type: robot |---|--- type: robot
|---|--- poses: Shape (4, 4) |---|--- poses: Shape (4, 4)
|---|---| time |---|---| time
|---|---|--- monotonic step: 40 |---|---|--- monotonic step: 40
......
...@@ -43,10 +43,10 @@ print(sf.entity_names) ...@@ -43,10 +43,10 @@ print(sf.entity_names)
# Get an array with all poses. As the length of poses varies per agent, it is filled up with nans. # Get an array with all poses. As the length of poses varies per agent, it is filled up with nans.
print("\nAll poses") print("\nAll poses")
print(sf.entity_poses) print(sf.poses)
print("\nFish poses") print("\nFish poses")
print(sf.select_entity_poses(lambda e: e.category == "fish")) print(sf.select_poses(lambda e: e.category == "fish"))
print("\nFile structure") print("\nFile structure")
print(sf) print(sf)
...@@ -32,4 +32,4 @@ with robofish.io.File(path, "w", world_size_cm=[100, 100], frequency_hz=25.0) as ...@@ -32,4 +32,4 @@ with robofish.io.File(path, "w", world_size_cm=[100, 100], frequency_hz=25.0) as
# Show and save the file # Show and save the file
print(f) print(f)
print("Poses Shape: ", f.entity_poses.shape) print("Poses Shape: ", f.poses.shape)
...@@ -322,10 +322,10 @@ class File(h5py.File): ...@@ -322,10 +322,10 @@ class File(h5py.File):
] ]
@property @property
def entity_poses(self): def poses(self):
return self.select_entity_poses(None) return self.select_poses(None)
def select_entity_poses(self, predicate=None) -> Iterable: def select_poses(self, predicate=None) -> Iterable:
""" Select an array of the poses of entities """ Select an array of the poses of entities
If no name or category is specified, all entities will be selected. If no name or category is specified, all entities will be selected.
...@@ -379,7 +379,7 @@ class File(h5py.File): ...@@ -379,7 +379,7 @@ class File(h5py.File):
predicate = lambda e: e.name in names predicate = lambda e: e.name in names
else: else:
predicate = None predicate = None
return self.select_entity_poses(predicate) return self.select_poses(predicate)
def validate(self, strict_validate: bool = True) -> (bool, str): def validate(self, strict_validate: bool = True) -> (bool, str):
"""Validate the file to the specification. """Validate the file to the specification.
......
...@@ -80,16 +80,16 @@ def test_multiple_entities(): ...@@ -80,16 +80,16 @@ def test_multiple_entities():
sf.validate() sf.validate()
# The returned poses should be equal to the inserted poses # The returned poses should be equal to the inserted poses
returned_poses = sf.entity_poses returned_poses = sf.poses
print(returned_poses) print(returned_poses)
assert (returned_poses == poses).all() assert (returned_poses == poses).all()
# Just get the array for some names # Just get the array for some names
returned_poses = sf.select_entity_poses(lambda e: e.name in ["fish_1", "fish_2"]) returned_poses = sf.select_poses(lambda e: e.name in ["fish_1", "fish_2"])
assert (returned_poses == poses[:2]).all() assert (returned_poses == poses[:2]).all()
# Filter on both category and name # Filter on both category and name
returned_poses = sf.select_entity_poses( returned_poses = sf.select_poses(
lambda e: e.category == "fish" and e.name == "fish_1" lambda e: e.category == "fish" and e.name == "fish_1"
) )
assert (returned_poses == poses[:1]).all() assert (returned_poses == poses[:1]).all()
...@@ -99,7 +99,7 @@ def test_multiple_entities(): ...@@ -99,7 +99,7 @@ def test_multiple_entities():
"obstacle", poses=np.random.random((agents, timesteps, 4)) "obstacle", poses=np.random.random((agents, timesteps, 4))
) )
# Obstacles should not be returned when only fish are selected # Obstacles should not be returned when only fish are selected
returned_poses = sf.select_entity_poses(lambda e: e.category == "fish") returned_poses = sf.select_poses(lambda e: e.category == "fish")
assert (returned_poses == poses).all() assert (returned_poses == poses).all()
# for each of the entities # for each of the entities
...@@ -138,6 +138,14 @@ def test_multiple_entities(): ...@@ -138,6 +138,14 @@ def test_multiple_entities():
return sf return sf
def test_deprecated_get_poses():
f = test_multiple_entities()
with pytest.warns(DeprecationWarning):
assert f.get_poses().shape[0] == 10
assert f.get_poses(category="fish").shape[0] == 7
assert f.get_poses(names="fish_1").shape[0] == 1
def test_load_validate(): def test_load_validate():
sf = robofish.io.File(path=valid_file_path) sf = robofish.io.File(path=valid_file_path)
sf.validate() sf.validate()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment