humalab 0.0.6__py3-none-any.whl → 0.0.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of humalab might be problematic. Click here for more details.
- humalab/__init__.py +14 -0
- humalab/assets/__init__.py +6 -0
- humalab/assets/files/resource_file.py +70 -6
- humalab/assets/files/urdf_file.py +35 -1
- humalab/assets/resource_operator.py +51 -3
- humalab/constants.py +10 -1
- humalab/dists/__init__.py +7 -0
- humalab/dists/bernoulli.py +24 -0
- humalab/dists/categorical.py +25 -0
- humalab/dists/discrete.py +25 -0
- humalab/dists/distribution.py +11 -0
- humalab/dists/gaussian.py +25 -0
- humalab/dists/log_uniform.py +27 -1
- humalab/dists/truncated_gaussian.py +29 -0
- humalab/dists/uniform.py +24 -0
- humalab/episode.py +118 -8
- humalab/humalab.py +53 -14
- humalab/humalab_api_client.py +3 -8
- humalab/humalab_config.py +49 -0
- humalab/metrics/__init__.py +6 -0
- humalab/metrics/code.py +37 -6
- humalab/metrics/metric.py +42 -8
- humalab/metrics/scenario_stats.py +83 -15
- humalab/metrics/summary.py +23 -8
- humalab/run.py +53 -7
- humalab/scenarios/__init__.py +7 -0
- humalab/scenarios/scenario.py +41 -38
- humalab/scenarios/scenario_operator.py +41 -9
- {humalab-0.0.6.dist-info → humalab-0.0.7.dist-info}/METADATA +1 -1
- humalab-0.0.7.dist-info/RECORD +39 -0
- humalab-0.0.6.dist-info/RECORD +0 -39
- {humalab-0.0.6.dist-info → humalab-0.0.7.dist-info}/WHEEL +0 -0
- {humalab-0.0.6.dist-info → humalab-0.0.7.dist-info}/entry_points.txt +0 -0
- {humalab-0.0.6.dist-info → humalab-0.0.7.dist-info}/licenses/LICENSE +0 -0
- {humalab-0.0.6.dist-info → humalab-0.0.7.dist-info}/top_level.txt +0 -0
|
@@ -15,21 +15,55 @@ SCENARIO_STATS_NEED_FLATTEN = {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
DISTRIBUTION_GRAPH_TYPE = {
|
|
19
|
+
# 0D distributions
|
|
20
|
+
"uniform": GraphType.HISTOGRAM,
|
|
21
|
+
"bernoulli": GraphType.BAR,
|
|
22
|
+
"categorical": GraphType.BAR,
|
|
23
|
+
"discrete": GraphType.BAR,
|
|
24
|
+
"log_uniform": GraphType.HISTOGRAM,
|
|
25
|
+
"gaussian": GraphType.GAUSSIAN,
|
|
26
|
+
"truncated_gaussian": GraphType.GAUSSIAN,
|
|
27
|
+
|
|
28
|
+
# 1D distributions
|
|
29
|
+
"uniform_1d": GraphType.HISTOGRAM,
|
|
30
|
+
"bernoulli_1d": GraphType.BAR,
|
|
31
|
+
"categorical_1d": GraphType.BAR,
|
|
32
|
+
"discrete_1d": GraphType.BAR,
|
|
33
|
+
"log_uniform_1d": GraphType.HISTOGRAM,
|
|
34
|
+
"gaussian_1d": GraphType.GAUSSIAN,
|
|
35
|
+
"truncated_gaussian_1d": GraphType.GAUSSIAN,
|
|
36
|
+
|
|
37
|
+
# 2D distributions
|
|
38
|
+
"uniform_2d": GraphType.SCATTER,
|
|
39
|
+
"gaussian_2d": GraphType.HEATMAP,
|
|
40
|
+
"truncated_gaussian_2d": GraphType.HEATMAP,
|
|
41
|
+
|
|
42
|
+
# 3D distributions
|
|
43
|
+
"uniform_3d": GraphType.THREE_D_MAP,
|
|
44
|
+
"gaussian_3d": GraphType.THREE_D_MAP,
|
|
45
|
+
"truncated_gaussian_3d": GraphType.THREE_D_MAP,
|
|
46
|
+
}
|
|
47
|
+
|
|
18
48
|
class ScenarioStats(Metrics):
|
|
19
|
-
"""Metric to track scenario statistics
|
|
49
|
+
"""Metric to track scenario statistics across episodes.
|
|
50
|
+
|
|
51
|
+
This class logs sampled values from scenario distributions and tracks episode
|
|
52
|
+
statuses. It supports various distribution types and automatically handles
|
|
53
|
+
flattening for 1D distributions.
|
|
20
54
|
|
|
21
55
|
Attributes:
|
|
56
|
+
name (str): The name of the scenario statistic.
|
|
57
|
+
distribution_type (str): The type of distribution (e.g., 'uniform', 'gaussian').
|
|
58
|
+
artifact_type (ArtifactType): The artifact type, always SCENARIO_STATS.
|
|
22
59
|
"""
|
|
23
60
|
|
|
24
61
|
def __init__(self,
|
|
25
62
|
name: str,
|
|
26
63
|
distribution_type: str,
|
|
27
|
-
metric_dim_type: MetricDimType,
|
|
28
|
-
graph_type: GraphType,
|
|
29
64
|
) -> None:
|
|
30
65
|
super().__init__(
|
|
31
|
-
|
|
32
|
-
graph_type=graph_type
|
|
66
|
+
graph_type=DISTRIBUTION_GRAPH_TYPE[distribution_type]
|
|
33
67
|
)
|
|
34
68
|
self._name = name
|
|
35
69
|
self._distribution_type = distribution_type
|
|
@@ -39,17 +73,43 @@ class ScenarioStats(Metrics):
|
|
|
39
73
|
|
|
40
74
|
@property
|
|
41
75
|
def name(self) -> str:
|
|
76
|
+
"""The name of the scenario statistic.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
str: The statistic name.
|
|
80
|
+
"""
|
|
42
81
|
return self._name
|
|
43
|
-
|
|
82
|
+
|
|
44
83
|
@property
|
|
45
84
|
def distribution_type(self) -> str:
|
|
85
|
+
"""The type of distribution used for this statistic.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
str: The distribution type (e.g., 'uniform', 'gaussian').
|
|
89
|
+
"""
|
|
46
90
|
return self._distribution_type
|
|
47
91
|
|
|
48
92
|
@property
|
|
49
93
|
def artifact_type(self) -> ArtifactType:
|
|
94
|
+
"""The artifact type, always SCENARIO_STATS.
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
ArtifactType: The artifact type.
|
|
98
|
+
"""
|
|
50
99
|
return self._artifact_type
|
|
51
100
|
|
|
52
101
|
def log(self, data: Any, x: Any = None, replace: bool = False) -> None:
|
|
102
|
+
"""Log a sampled value from the scenario distribution.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
data (Any): The sampled value to log.
|
|
106
|
+
x (Any | None): The key/identifier for this sample (typically episode_id).
|
|
107
|
+
If None, auto-incrementing step is used.
|
|
108
|
+
replace (bool): Whether to replace an existing value. Defaults to False.
|
|
109
|
+
|
|
110
|
+
Raises:
|
|
111
|
+
ValueError: If data for the given x already exists and replace is False.
|
|
112
|
+
"""
|
|
53
113
|
if x in self._values:
|
|
54
114
|
if replace:
|
|
55
115
|
if self._distribution_type in SCENARIO_STATS_NEED_FLATTEN:
|
|
@@ -62,27 +122,35 @@ class ScenarioStats(Metrics):
|
|
|
62
122
|
data = data[0]
|
|
63
123
|
self._values[x] = data
|
|
64
124
|
|
|
65
|
-
def log_status(self,
|
|
125
|
+
def log_status(self,
|
|
66
126
|
episode_id: str,
|
|
67
|
-
episode_status: EpisodeStatus,
|
|
127
|
+
episode_status: EpisodeStatus,
|
|
68
128
|
replace: bool = False) -> None:
|
|
69
|
-
"""Log
|
|
129
|
+
"""Log the status of an episode.
|
|
70
130
|
|
|
71
131
|
Args:
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
132
|
+
episode_id (str): The unique identifier of the episode.
|
|
133
|
+
episode_status (EpisodeStatus): The status of the episode.
|
|
134
|
+
replace (bool): Whether to replace an existing status for this episode.
|
|
135
|
+
Defaults to False.
|
|
136
|
+
|
|
137
|
+
Raises:
|
|
138
|
+
ValueError: If status for the episode_id already exists and replace is False.
|
|
76
139
|
"""
|
|
77
140
|
if episode_id in self._results:
|
|
78
141
|
if replace:
|
|
79
|
-
self._results[episode_id] = episode_status
|
|
142
|
+
self._results[episode_id] = episode_status.value
|
|
80
143
|
else:
|
|
81
144
|
raise ValueError(f"Data for episode_id {episode_id} already exists. Use replace=True to overwrite.")
|
|
82
145
|
else:
|
|
83
|
-
self._results[episode_id] = episode_status
|
|
146
|
+
self._results[episode_id] = episode_status.value
|
|
84
147
|
|
|
85
148
|
def _finalize(self) -> dict:
|
|
149
|
+
"""Finalize and return all collected scenario statistics.
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
dict: Dictionary containing values, results, and distribution type.
|
|
153
|
+
"""
|
|
86
154
|
ret_val = {
|
|
87
155
|
"values": self._values,
|
|
88
156
|
"results": self._results,
|
humalab/metrics/summary.py
CHANGED
|
@@ -4,31 +4,46 @@ from humalab.constants import MetricDimType, GraphType
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class Summary(Metrics):
|
|
7
|
-
|
|
7
|
+
"""A metric that aggregates logged values into a single summary statistic.
|
|
8
|
+
|
|
9
|
+
Summary metrics collect values throughout a run or episode and compute a single
|
|
10
|
+
aggregated result. Supported aggregation methods include min, max, mean, first,
|
|
11
|
+
last, and none (no aggregation).
|
|
12
|
+
|
|
13
|
+
Attributes:
|
|
14
|
+
summary (str): The aggregation method used.
|
|
15
|
+
"""
|
|
16
|
+
def __init__(self,
|
|
8
17
|
summary: str,
|
|
9
18
|
) -> None:
|
|
10
19
|
"""
|
|
11
20
|
A summary metric that captures a single value per episode or run.
|
|
12
21
|
|
|
13
22
|
Args:
|
|
14
|
-
|
|
15
|
-
summary (str | None): Specify aggregate metrics added to summary.
|
|
23
|
+
summary (str): Specify the aggregation method for the summary.
|
|
16
24
|
Supported aggregations include "min", "max", "mean", "last",
|
|
17
|
-
"first", and "none". "none" prevents a summary
|
|
18
|
-
from being generated.
|
|
19
|
-
granularity (MetricGranularity): The granularity of the metric.
|
|
25
|
+
"first", and "none". "none" prevents a summary from being generated.
|
|
20
26
|
"""
|
|
21
27
|
if summary not in {"min", "max", "mean", "last", "first", "none"}:
|
|
22
28
|
raise ValueError(f"Unsupported summary type: {summary}. Supported types are 'min', 'max', 'mean', 'last', 'first', and 'none'.")
|
|
23
|
-
super().__init__(
|
|
24
|
-
graph_type=GraphType.NUMERIC)
|
|
29
|
+
super().__init__(graph_type=GraphType.NUMERIC)
|
|
25
30
|
self._summary = summary
|
|
26
31
|
|
|
27
32
|
@property
|
|
28
33
|
def summary(self) -> str:
|
|
34
|
+
"""The aggregation method for this summary metric.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
str: The summary type (e.g., 'min', 'max', 'mean').
|
|
38
|
+
"""
|
|
29
39
|
return self._summary
|
|
30
40
|
|
|
31
41
|
def _finalize(self) -> dict:
|
|
42
|
+
"""Compute the final aggregated value.
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
dict: Dictionary containing the aggregated value and summary type.
|
|
46
|
+
"""
|
|
32
47
|
if not self._values:
|
|
33
48
|
return {
|
|
34
49
|
"value": None,
|
humalab/run.py
CHANGED
|
@@ -16,6 +16,25 @@ from humalab.utils import is_standard_type
|
|
|
16
16
|
from humalab.scenarios.scenario import Scenario
|
|
17
17
|
|
|
18
18
|
class Run:
|
|
19
|
+
"""Represents a run containing multiple episodes for a scenario.
|
|
20
|
+
|
|
21
|
+
A Run is a context manager that tracks experiments or evaluations using a specific
|
|
22
|
+
scenario. It manages episode creation, metric logging, and code artifacts. The run
|
|
23
|
+
can contain multiple episodes, each representing a single execution instance.
|
|
24
|
+
|
|
25
|
+
Use as a context manager to automatically handle run lifecycle:
|
|
26
|
+
with Run(scenario=my_scenario) as run:
|
|
27
|
+
# Your code here
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
Attributes:
|
|
31
|
+
project (str): The project name under which the run is created.
|
|
32
|
+
id (str): The unique identifier for the run.
|
|
33
|
+
name (str): The name of the run.
|
|
34
|
+
description (str): A description of the run.
|
|
35
|
+
tags (list[str]): A list of tags associated with the run.
|
|
36
|
+
scenario (Scenario): The scenario associated with the run.
|
|
37
|
+
"""
|
|
19
38
|
def __init__(self,
|
|
20
39
|
scenario: Scenario,
|
|
21
40
|
project: str = DEFAULT_PROJECT,
|
|
@@ -110,9 +129,11 @@ class Run:
|
|
|
110
129
|
return self._scenario
|
|
111
130
|
|
|
112
131
|
def __enter__(self):
|
|
132
|
+
"""Enter the run context."""
|
|
113
133
|
return self
|
|
114
134
|
|
|
115
135
|
def __exit__(self, exception_type, exception_value, exception_traceback):
|
|
136
|
+
"""Exit the run context and finalize the run."""
|
|
116
137
|
if self._is_finished:
|
|
117
138
|
return
|
|
118
139
|
if exception_type is not None:
|
|
@@ -122,10 +143,14 @@ class Run:
|
|
|
122
143
|
self.finish()
|
|
123
144
|
|
|
124
145
|
def create_episode(self, episode_id: str | None = None) -> Episode:
|
|
125
|
-
"""
|
|
146
|
+
"""Create a new episode for this run.
|
|
126
147
|
|
|
127
148
|
Args:
|
|
128
|
-
|
|
149
|
+
episode_id (str | None): Optional unique identifier for the episode.
|
|
150
|
+
If None, a UUID is generated automatically.
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
Episode: The newly created episode instance.
|
|
129
154
|
"""
|
|
130
155
|
episode = None
|
|
131
156
|
episode_id = episode_id or str(uuid.uuid4())
|
|
@@ -142,15 +167,22 @@ class Run:
|
|
|
142
167
|
for metric_name, value in episode_vals.items():
|
|
143
168
|
if metric_name not in self._logs:
|
|
144
169
|
stat = ScenarioStats(name=metric_name,
|
|
145
|
-
distribution_type=value["distribution"]
|
|
146
|
-
metric_dim_type=value["metric_dim_type"],
|
|
147
|
-
graph_type=value["graph_type"])
|
|
170
|
+
distribution_type=value["distribution"])
|
|
148
171
|
self._logs[metric_name] = stat
|
|
149
172
|
self._logs[metric_name].log(data=value["value"],
|
|
150
173
|
x=episode.episode_id)
|
|
151
174
|
self._episodes[episode.episode_id] = episode
|
|
152
175
|
|
|
153
176
|
def add_metric(self, name: str, metric: Metrics) -> None:
|
|
177
|
+
"""Add a metric to track for this run.
|
|
178
|
+
|
|
179
|
+
Args:
|
|
180
|
+
name (str): The name of the metric.
|
|
181
|
+
metric (Metrics): The metric instance to add.
|
|
182
|
+
|
|
183
|
+
Raises:
|
|
184
|
+
ValueError: If the name is already used.
|
|
185
|
+
"""
|
|
154
186
|
if name in self._logs:
|
|
155
187
|
raise ValueError(f"{name} is a reserved name and is not allowed.")
|
|
156
188
|
self._logs[name] = metric
|
|
@@ -172,6 +204,16 @@ class Run:
|
|
|
172
204
|
|
|
173
205
|
|
|
174
206
|
def log(self, data: dict, x: dict | None = None, replace: bool = False) -> None:
|
|
207
|
+
"""Log data points or values for the run.
|
|
208
|
+
|
|
209
|
+
Args:
|
|
210
|
+
data (dict): Dictionary of key-value pairs to log.
|
|
211
|
+
x (dict | None): Optional dictionary of x-axis values for each key.
|
|
212
|
+
replace (bool): Whether to replace existing values. Defaults to False.
|
|
213
|
+
|
|
214
|
+
Raises:
|
|
215
|
+
ValueError: If a key is reserved or logging fails.
|
|
216
|
+
"""
|
|
175
217
|
for key, value in data.items():
|
|
176
218
|
if key in RESERVED_NAMES:
|
|
177
219
|
raise ValueError(f"{key} is a reserved name and is not allowed.")
|
|
@@ -219,6 +261,12 @@ class Run:
|
|
|
219
261
|
run_id=self._id,
|
|
220
262
|
code_content=self.scenario.yaml
|
|
221
263
|
)
|
|
264
|
+
|
|
265
|
+
self._api_client.upload_python(
|
|
266
|
+
artifact_key="seed",
|
|
267
|
+
run_id=self._id,
|
|
268
|
+
pickled_bytes=pickle.dumps(self.scenario.seed)
|
|
269
|
+
)
|
|
222
270
|
# TODO: submit final metrics
|
|
223
271
|
for key, value in self._logs.items():
|
|
224
272
|
if isinstance(value, ScenarioStats):
|
|
@@ -235,7 +283,6 @@ class Run:
|
|
|
235
283
|
run_id=self._id,
|
|
236
284
|
pickled_bytes=pickled,
|
|
237
285
|
graph_type=value.graph_type.value,
|
|
238
|
-
metric_dim_type=value.metric_dim_type.value
|
|
239
286
|
)
|
|
240
287
|
elif isinstance(value, Summary):
|
|
241
288
|
metric_val = value.finalize()
|
|
@@ -253,7 +300,6 @@ class Run:
|
|
|
253
300
|
run_id=self._id,
|
|
254
301
|
pickled_bytes=pickled,
|
|
255
302
|
graph_type=value.graph_type.value,
|
|
256
|
-
metric_dim_type=value.metric_dim_type.value
|
|
257
303
|
)
|
|
258
304
|
elif isinstance(value, Code):
|
|
259
305
|
self._api_client.upload_code(
|
humalab/scenarios/__init__.py
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
"""Scenario management and configuration.
|
|
2
|
+
|
|
3
|
+
This module provides the Scenario class and related utilities for managing scenario
|
|
4
|
+
configurations with probabilistic distributions, supporting randomized scenario generation
|
|
5
|
+
for robotics experiments.
|
|
6
|
+
"""
|
|
7
|
+
|
|
1
8
|
from .scenario import Scenario
|
|
2
9
|
from .scenario_operator import list_scenarios, get_scenario
|
|
3
10
|
|
humalab/scenarios/scenario.py
CHANGED
|
@@ -163,64 +163,51 @@ SCENARIO_STATS_DIM_TYPE_MAP = {
|
|
|
163
163
|
"truncated_gaussian_3d": MetricDimType.THREE_D,
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
"uniform": GraphType.HISTOGRAM,
|
|
169
|
-
"bernoulli": GraphType.BAR,
|
|
170
|
-
"categorical": GraphType.BAR,
|
|
171
|
-
"discrete": GraphType.BAR,
|
|
172
|
-
"log_uniform": GraphType.HISTOGRAM,
|
|
173
|
-
"gaussian": GraphType.GAUSSIAN,
|
|
174
|
-
"truncated_gaussian": GraphType.GAUSSIAN,
|
|
175
|
-
|
|
176
|
-
# 1D distributions
|
|
177
|
-
"uniform_1d": GraphType.HISTOGRAM,
|
|
178
|
-
"bernoulli_1d": GraphType.BAR,
|
|
179
|
-
"categorical_1d": GraphType.BAR,
|
|
180
|
-
"discrete_1d": GraphType.BAR,
|
|
181
|
-
"log_uniform_1d": GraphType.HISTOGRAM,
|
|
182
|
-
"gaussian_1d": GraphType.GAUSSIAN,
|
|
183
|
-
"truncated_gaussian_1d": GraphType.GAUSSIAN,
|
|
166
|
+
class Scenario:
|
|
167
|
+
"""Manages scenario configurations with probabilistic distributions.
|
|
184
168
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
169
|
+
A Scenario encapsulates a configuration template that can contain distribution
|
|
170
|
+
resolvers (e.g., ${uniform:0,1}). When resolved, these distributions are sampled
|
|
171
|
+
to produce concrete scenario instances. Each resolution creates a new episode
|
|
172
|
+
with different sampled values.
|
|
189
173
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
"gaussian_3d": GraphType.THREE_D_MAP,
|
|
193
|
-
"truncated_gaussian_3d": GraphType.THREE_D_MAP,
|
|
194
|
-
}
|
|
174
|
+
Supported distributions include uniform, gaussian, bernoulli, categorical,
|
|
175
|
+
discrete, log_uniform, and truncated_gaussian, with support for 0D-3D variants.
|
|
195
176
|
|
|
196
|
-
|
|
177
|
+
Attributes:
|
|
178
|
+
template (DictConfig | ListConfig): The template scenario configuration.
|
|
179
|
+
yaml (str): The current scenario configuration as a YAML string.
|
|
180
|
+
"""
|
|
197
181
|
dist_cache = {}
|
|
198
182
|
def __init__(self) -> None:
|
|
199
183
|
self._generator = np.random.default_rng()
|
|
200
184
|
self._scenario_template = OmegaConf.create()
|
|
201
185
|
self._cur_scenario = OmegaConf.create()
|
|
202
186
|
self._scenario_id = None
|
|
187
|
+
self._seed = None
|
|
203
188
|
|
|
204
189
|
self._episode_vals = {}
|
|
205
190
|
self._lock = RLock()
|
|
206
191
|
|
|
207
192
|
def init(self,
|
|
208
|
-
scenario: str | list | dict | None = None,
|
|
209
|
-
seed: int | None=None,
|
|
193
|
+
scenario: str | list | dict | None = None,
|
|
194
|
+
seed: int | None=None,
|
|
210
195
|
scenario_id: str | None=None,
|
|
211
196
|
# num_env: int | None = None
|
|
212
197
|
) -> None:
|
|
213
198
|
"""
|
|
214
199
|
Initialize the scenario with the given parameters.
|
|
215
|
-
|
|
200
|
+
|
|
216
201
|
Args:
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
seed: Optional seed for random number generation.
|
|
220
|
-
|
|
221
|
-
|
|
202
|
+
scenario (str | list | dict | None): The scenario configuration. Can be a YAML
|
|
203
|
+
string, list, or dict. If None, an empty configuration is used.
|
|
204
|
+
seed (int | None): Optional seed for random number generation. If None, uses
|
|
205
|
+
a non-deterministic seed.
|
|
206
|
+
scenario_id (str | None): Optional scenario ID in the format 'id' or 'id:version'.
|
|
207
|
+
If None, a new UUID is generated.
|
|
222
208
|
"""
|
|
223
209
|
self._num_env = None # num_env
|
|
210
|
+
self._seed = seed
|
|
224
211
|
|
|
225
212
|
# Parse scenario id
|
|
226
213
|
scenario_version = 1
|
|
@@ -328,8 +315,6 @@ class Scenario:
|
|
|
328
315
|
self._episode_vals[key_path] = {
|
|
329
316
|
"value": ret_val,
|
|
330
317
|
"distribution": dist_name,
|
|
331
|
-
"graph_type": DISTRIBUTION_GRAPH_TYPE[dist_name],
|
|
332
|
-
"metric_dim_type": SCENARIO_STATS_DIM_TYPE_MAP[dist_name],
|
|
333
318
|
}
|
|
334
319
|
return ret_val
|
|
335
320
|
|
|
@@ -353,6 +338,24 @@ class Scenario:
|
|
|
353
338
|
episode_vals = copy.deepcopy(self._episode_vals)
|
|
354
339
|
return cur_scenario, episode_vals
|
|
355
340
|
|
|
341
|
+
@property
|
|
342
|
+
def scenario_id(self) -> str | None:
|
|
343
|
+
"""The scenario ID.
|
|
344
|
+
|
|
345
|
+
Returns:
|
|
346
|
+
str | None: The scenario ID, or None if not set.
|
|
347
|
+
"""
|
|
348
|
+
return self._scenario_id
|
|
349
|
+
|
|
350
|
+
@property
|
|
351
|
+
def seed(self) -> int | None:
|
|
352
|
+
"""The random seed for the scenario.
|
|
353
|
+
|
|
354
|
+
Returns:
|
|
355
|
+
int | None: The random seed, or None if not set.
|
|
356
|
+
"""
|
|
357
|
+
return self._seed
|
|
358
|
+
|
|
356
359
|
@property
|
|
357
360
|
def template(self) -> Any:
|
|
358
361
|
"""The template scenario configuration.
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"""Operations for managing and retrieving scenarios."""
|
|
2
|
+
|
|
1
3
|
from typing import Optional
|
|
2
4
|
from dataclasses import dataclass
|
|
3
5
|
|
|
@@ -7,6 +9,17 @@ from humalab.constants import DEFAULT_PROJECT
|
|
|
7
9
|
|
|
8
10
|
@dataclass
|
|
9
11
|
class ScenarioMetadata:
|
|
12
|
+
"""Metadata for a scenario stored in HumaLab.
|
|
13
|
+
|
|
14
|
+
Attributes:
|
|
15
|
+
id (str): Unique identifier for the scenario.
|
|
16
|
+
version (int): Version number of the scenario.
|
|
17
|
+
project (str): Project name the scenario belongs to.
|
|
18
|
+
name (str): Human-readable scenario name.
|
|
19
|
+
description (str | None): Optional scenario description.
|
|
20
|
+
created_at (str): ISO timestamp when scenario was created.
|
|
21
|
+
updated_at (str): ISO timestamp when scenario was last updated.
|
|
22
|
+
"""
|
|
10
23
|
id: str
|
|
11
24
|
version: int
|
|
12
25
|
project: str
|
|
@@ -18,7 +31,7 @@ class ScenarioMetadata:
|
|
|
18
31
|
|
|
19
32
|
def list_scenarios(project: str = DEFAULT_PROJECT,
|
|
20
33
|
limit: int = 20,
|
|
21
|
-
offset: int = 0,
|
|
34
|
+
offset: int = 0,
|
|
22
35
|
include_inactive: bool = False,
|
|
23
36
|
search: Optional[str] = None,
|
|
24
37
|
status_filter: Optional[str] = None,
|
|
@@ -26,18 +39,23 @@ def list_scenarios(project: str = DEFAULT_PROJECT,
|
|
|
26
39
|
base_url: str | None = None,
|
|
27
40
|
api_key: str | None = None,
|
|
28
41
|
timeout: float | None = None,
|
|
29
|
-
) -> list[
|
|
42
|
+
) -> list[ScenarioMetadata]:
|
|
30
43
|
"""
|
|
31
44
|
List all scenarios for a given project.
|
|
32
|
-
|
|
45
|
+
|
|
33
46
|
Args:
|
|
34
|
-
project: The project name to list scenarios from.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
47
|
+
project (str): The project name to list scenarios from. Defaults to DEFAULT_PROJECT.
|
|
48
|
+
limit (int): Maximum number of scenarios to return. Defaults to 20.
|
|
49
|
+
offset (int): Number of scenarios to skip for pagination. Defaults to 0.
|
|
50
|
+
include_inactive (bool): Whether to include inactive scenarios. Defaults to False.
|
|
51
|
+
search (Optional[str]): Search query to filter scenarios by name or description. Defaults to None.
|
|
52
|
+
status_filter (Optional[str]): Filter scenarios by status. Defaults to None.
|
|
53
|
+
base_url (str | None): The base URL of the HumaLab API. If None, uses configured value.
|
|
54
|
+
api_key (str | None): The API key for authentication. If None, uses configured value.
|
|
55
|
+
timeout (float | None): The timeout for API requests in seconds. If None, uses configured value.
|
|
38
56
|
|
|
39
57
|
Returns:
|
|
40
|
-
A list of scenario metadata
|
|
58
|
+
list[ScenarioMetadata]: A list of scenario metadata objects.
|
|
41
59
|
"""
|
|
42
60
|
api_client = HumaLabApiClient(base_url=base_url,
|
|
43
61
|
api_key=api_key,
|
|
@@ -64,10 +82,24 @@ def get_scenario(scenario_id: str,
|
|
|
64
82
|
version: int | None = None,
|
|
65
83
|
project: str = DEFAULT_PROJECT,
|
|
66
84
|
seed: int | None=None,
|
|
67
|
-
|
|
85
|
+
|
|
68
86
|
base_url: str | None = None,
|
|
69
87
|
api_key: str | None = None,
|
|
70
88
|
timeout: float | None = None,) -> Scenario:
|
|
89
|
+
"""Retrieve and initialize a scenario from HumaLab.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
scenario_id (str): The unique identifier of the scenario.
|
|
93
|
+
version (int | None): Optional specific version to retrieve.
|
|
94
|
+
project (str): The project name. Defaults to DEFAULT_PROJECT.
|
|
95
|
+
seed (int | None): Optional seed for scenario randomization.
|
|
96
|
+
base_url (str | None): Optional API host override.
|
|
97
|
+
api_key (str | None): Optional API key override.
|
|
98
|
+
timeout (float | None): Optional timeout override.
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
Scenario: The initialized scenario instance.
|
|
102
|
+
"""
|
|
71
103
|
api_client = HumaLabApiClient(base_url=base_url,
|
|
72
104
|
api_key=api_key,
|
|
73
105
|
timeout=timeout)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
humalab/__init__.py,sha256=AfQjlYd-KIqWdKaW77ZI86zU5tYXk-kdXaj14sY27is,1022
|
|
2
|
+
humalab/constants.py,sha256=FuwO3FRREUYStXmly7dN6Phw2tIyyiCn8bbclibqh5I,1194
|
|
3
|
+
humalab/episode.py,sha256=EZCsvv51rEZyl6aVIVviIRi6lR5KAjKSmn0_m5EUL28,10760
|
|
4
|
+
humalab/humalab.py,sha256=_2wEGri-PEhi9WZ2XEHAVDPm8Iki8jZBG8nEmQSFuzo,8089
|
|
5
|
+
humalab/humalab_api_client.py,sha256=3udeKwplpYty-Zp_5IkZXONCJUalj_3pKkqaOBAGaBo,29339
|
|
6
|
+
humalab/humalab_config.py,sha256=GzC0W2-NGUrJGyJH5qst_iL4DfXJX5bD5eaT1XVvJjk,3792
|
|
7
|
+
humalab/humalab_test.py,sha256=YMwOIH-sAOMnxwq8yR-Ut4vYk5Ksix9zS9yUIxi3GU8,20725
|
|
8
|
+
humalab/run.py,sha256=hiJLIW5yO_c58dZdM9lncdd7x55HC5L_o7rBb-fTWt0,11753
|
|
9
|
+
humalab/utils.py,sha256=KMIPoduAbQzha9wvnyX8OjE8X-3TaNpecx2o-kgHbdw,1161
|
|
10
|
+
humalab/assets/__init__.py,sha256=dsBdfusLUNwXnnuGaqAwO83_JDghc4MKLARKGupfNhk,413
|
|
11
|
+
humalab/assets/archive.py,sha256=PALZRnpNExDfXiURVNEj6xxWqcW4nd9UBZ7QIHa8mI8,3119
|
|
12
|
+
humalab/assets/resource_operator.py,sha256=H2ERU2LuzF3nomR2L29Q6f5EuYwB_PgHlmDvZbCql5s,5961
|
|
13
|
+
humalab/assets/files/__init__.py,sha256=9XF-Zp2nldx060v8A3tMTcB5o5vJCUTFKF9rrIFZE_s,111
|
|
14
|
+
humalab/assets/files/resource_file.py,sha256=0h-WrQcwalEtKbS4ZJTkF3TciX7rqkTG_EVM8YshRHE,3763
|
|
15
|
+
humalab/assets/files/urdf_file.py,sha256=6J6MGgMvwttyC2Ru_3nReoPW6kHjNYFgkoD24URvIBY,3960
|
|
16
|
+
humalab/dists/__init__.py,sha256=IcVN1O4EOIcoOiWbiNWqeQOGBnEeVmjdaSpjR81WdTU,721
|
|
17
|
+
humalab/dists/bernoulli.py,sha256=h7QX5pMo5R_LQFJGx-Z-X9mdiz54cnjATGn6U2LppnM,2825
|
|
18
|
+
humalab/dists/categorical.py,sha256=tlpfmsnz4XrjxIqPlowHwBmYFRLYU_iENp_SbrOLXmk,3036
|
|
19
|
+
humalab/dists/discrete.py,sha256=2tJXHPakyzj4HAlbWC3_AeUbBdfQzvtlgTxba3gZvLo,3848
|
|
20
|
+
humalab/dists/distribution.py,sha256=wWm_bzfe-PHqBAOAszT2xW40CBkr7bDdSQbE_-Oztfw,1447
|
|
21
|
+
humalab/dists/gaussian.py,sha256=HYQ8KHxJBY4Y_PifQh4QKjfPcrqaeBpiSfcn_84BW1Y,3493
|
|
22
|
+
humalab/dists/log_uniform.py,sha256=6Bf-jkMYB0mFYiXX7mMMCAm0moYqfDvU99pOHrJiuLE,3586
|
|
23
|
+
humalab/dists/truncated_gaussian.py,sha256=qAPTiWFsci48pfgEyipg0E2Yl8HQSAFfxVAki_BX7cc,5185
|
|
24
|
+
humalab/dists/uniform.py,sha256=5_HOY7lU51v21Oyb3_VCGANMCatmZWeV97sTB57vu-A,3428
|
|
25
|
+
humalab/metrics/__init__.py,sha256=gYTsYpOJjx6Ouxyy2iZyHBSfMw0A4C0ZbQSgnIO6D2g,423
|
|
26
|
+
humalab/metrics/code.py,sha256=0cVlsC8nGta7Eb7-mr3ug5wgTy1FluyOtq252_fOEwE,1693
|
|
27
|
+
humalab/metrics/metric.py,sha256=MJ8oJoFJU9e4KE1Y_dw7cvKumFm85n3gWMkVfbDHzZM,3181
|
|
28
|
+
humalab/metrics/scenario_stats.py,sha256=SvbtEwOEeD-gNNqypfKZFDwsJ7bk8PNqw7LB-6h3R7k,5339
|
|
29
|
+
humalab/metrics/summary.py,sha256=x_GL12stCI3UtUds8w1FoD3WYSk25fGnXBhstV1MD_I,2656
|
|
30
|
+
humalab/scenarios/__init__.py,sha256=LRwueiMULXrEh37tZsKO9A4Obwoo5Zcsao_Wlk7j3vw,397
|
|
31
|
+
humalab/scenarios/scenario.py,sha256=llukLnS-vRtsB9hIiLXWoTrb6ATMRPnyxF43bjaZRwk,12530
|
|
32
|
+
humalab/scenarios/scenario_operator.py,sha256=PYAeUMQ3JPzNu5STfL543dYqcopO49td15QViybiTuw,4927
|
|
33
|
+
humalab/scenarios/scenario_test.py,sha256=YYSzKfaeZVK0Kv09pVYgZvLP7Zrz02jgUOpQ-0btanc,24397
|
|
34
|
+
humalab-0.0.7.dist-info/licenses/LICENSE,sha256=Gy0Nw_Z9pbrNSu-loW-PCDWJyrC8eWpIqqIGW-DFtp8,1064
|
|
35
|
+
humalab-0.0.7.dist-info/METADATA,sha256=fYRvNcaWq5XDn3x8oxwdSHHopMsyIAtUfRaHvEKuTxU,1704
|
|
36
|
+
humalab-0.0.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
37
|
+
humalab-0.0.7.dist-info/entry_points.txt,sha256=aY-hS7Kg8y5kGgYA14YmtTz5odBrgJIZ2fQMXAbVW_U,49
|
|
38
|
+
humalab-0.0.7.dist-info/top_level.txt,sha256=hp7XXBDE40hi9T3Jx6mPFc6wJbAMzektD5VWXlSCW6o,8
|
|
39
|
+
humalab-0.0.7.dist-info/RECORD,,
|
humalab-0.0.6.dist-info/RECORD
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
humalab/__init__.py,sha256=d6RcDYAWf4HzzF_is-_nlTZXAg2UjLSoWRJegNOYz9U,416
|
|
2
|
-
humalab/constants.py,sha256=gIdDoKnrAjfCMbnv4MnPncGYQXqELsaVYs3bQmH6k0s,852
|
|
3
|
-
humalab/episode.py,sha256=WpWIxzkQSBm-YGCEnvjL2b5pEN5OQBzFZJb_b3f8mKM,6917
|
|
4
|
-
humalab/humalab.py,sha256=FiC551LnCa1iQOvQ9tOUsbocs2Q2M3zy8gDgMAMFsJg,6712
|
|
5
|
-
humalab/humalab_api_client.py,sha256=uy6Re-e4v-Z5lPhZnu_HeSOcxDfdxW1uaMOb5Dbu0JE,29549
|
|
6
|
-
humalab/humalab_config.py,sha256=K-RC1MfAhuD_FCORySV7uyjKzW-bYf2tY6EOZslR0kg,2316
|
|
7
|
-
humalab/humalab_test.py,sha256=YMwOIH-sAOMnxwq8yR-Ut4vYk5Ksix9zS9yUIxi3GU8,20725
|
|
8
|
-
humalab/run.py,sha256=GSO_YrEkWqEBu7fvPjL1ru-xkEYMvXYXS2ReMm42V3k,10129
|
|
9
|
-
humalab/utils.py,sha256=KMIPoduAbQzha9wvnyX8OjE8X-3TaNpecx2o-kgHbdw,1161
|
|
10
|
-
humalab/assets/__init__.py,sha256=9WnZmRuS04q1GMAVfS8-SIjH5m50kmEnsKC2VAH1obA,167
|
|
11
|
-
humalab/assets/archive.py,sha256=PALZRnpNExDfXiURVNEj6xxWqcW4nd9UBZ7QIHa8mI8,3119
|
|
12
|
-
humalab/assets/resource_operator.py,sha256=YoKQ8_rfHDuvpn7zJsbaOIcouO5Oaehs0duFfB_rczg,4184
|
|
13
|
-
humalab/assets/files/__init__.py,sha256=9XF-Zp2nldx060v8A3tMTcB5o5vJCUTFKF9rrIFZE_s,111
|
|
14
|
-
humalab/assets/files/resource_file.py,sha256=HpPM4FVAya0kEggx8bFB__2S6CxyJyHyWZCQ6VcQLi4,1773
|
|
15
|
-
humalab/assets/files/urdf_file.py,sha256=UehIGgF9qL5oFiMX81l3aolSca7rkzN_B6t6k3o51UE,2802
|
|
16
|
-
humalab/dists/__init__.py,sha256=Q7zQbFGC_CnTgExMcnRtJdqJitqy1oBk4D6Qyvunlqc,387
|
|
17
|
-
humalab/dists/bernoulli.py,sha256=4RSYBkeyTHkqOzkn-of4y_oNJPhhfkMOuW2APjNa8Eo,1975
|
|
18
|
-
humalab/dists/categorical.py,sha256=plEIZIx5LRiaNreUCIk9EkhBD6eflxwMJy3XbseeUBw,2114
|
|
19
|
-
humalab/dists/discrete.py,sha256=X2VufaTsI7x125ev7RL7Sc59JhWh51tlE2dXAD51XBU,2889
|
|
20
|
-
humalab/dists/distribution.py,sha256=t0qTUjS_N0adiy_j2fdf-NHSlRs1pr0swpnszizs04I,1048
|
|
21
|
-
humalab/dists/gaussian.py,sha256=eezw8qpcRIRpoSM7Vgnny8berqsbcfKm0v00Hxv9KI8,2592
|
|
22
|
-
humalab/dists/log_uniform.py,sha256=mcJUYSoapxsIiynq_MZS_1NH1sxlC-Oupop2S3-EVHw,2626
|
|
23
|
-
humalab/dists/truncated_gaussian.py,sha256=tB0BQHaiSDmB1eNb143dKHysbDEG3_pjuCzYBOy4ks8,4009
|
|
24
|
-
humalab/dists/uniform.py,sha256=ouUAY8fvtu7azNCltU9g5t8jCw5OFQyYp8BlD7OWS5E,2545
|
|
25
|
-
humalab/metrics/__init__.py,sha256=lI1QCl_8mws5yfxxrAHCoIj1n5WEtiTZB5mTGFqAPCo,200
|
|
26
|
-
humalab/metrics/code.py,sha256=CybaYFX3KdJLFGshSY9Ss1jpkWwA5X2wD0hZNZJXUJw,713
|
|
27
|
-
humalab/metrics/metric.py,sha256=3lw3386UE3-pWHsOcYXoEM_RBfFR38bqd8Ehzj7aByw,1970
|
|
28
|
-
humalab/metrics/scenario_stats.py,sha256=lW-8tYrKh1nc_mclF7tg_o0UrhDoNgkVHPtabHgzdiQ,3004
|
|
29
|
-
humalab/metrics/summary.py,sha256=Y6AbDJv7vF4N82JqkTmJuwyaJ9WnlgJ6aExT8SSqnGQ,2194
|
|
30
|
-
humalab/scenarios/__init__.py,sha256=Q76ohPaMrU_NVwVVFQrxJIzIFjtibaOS60ljV1I54Os,148
|
|
31
|
-
humalab/scenarios/scenario.py,sha256=SmknTAZ3f304DmOSAKIkaZljrZ-ucxHs062CQKtS7js,12326
|
|
32
|
-
humalab/scenarios/scenario_operator.py,sha256=GxOB20UP-A6J5Y_ftHbWHpIrTMV6dx52r09Tr-WXfWU,3152
|
|
33
|
-
humalab/scenarios/scenario_test.py,sha256=YYSzKfaeZVK0Kv09pVYgZvLP7Zrz02jgUOpQ-0btanc,24397
|
|
34
|
-
humalab-0.0.6.dist-info/licenses/LICENSE,sha256=Gy0Nw_Z9pbrNSu-loW-PCDWJyrC8eWpIqqIGW-DFtp8,1064
|
|
35
|
-
humalab-0.0.6.dist-info/METADATA,sha256=KqqLNrCKPoBkDNYRwUKxjZoS2jogk7pHLaKYBHcBjmE,1704
|
|
36
|
-
humalab-0.0.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
37
|
-
humalab-0.0.6.dist-info/entry_points.txt,sha256=aY-hS7Kg8y5kGgYA14YmtTz5odBrgJIZ2fQMXAbVW_U,49
|
|
38
|
-
humalab-0.0.6.dist-info/top_level.txt,sha256=hp7XXBDE40hi9T3Jx6mPFc6wJbAMzektD5VWXlSCW6o,8
|
|
39
|
-
humalab-0.0.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|