idmtools 0.0.0.dev0__py3-none-any.whl → 0.0.3__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.
- idmtools/__init__.py +27 -8
- idmtools/analysis/__init__.py +5 -0
- idmtools/analysis/add_analyzer.py +89 -0
- idmtools/analysis/analyze_manager.py +490 -0
- idmtools/analysis/csv_analyzer.py +103 -0
- idmtools/analysis/download_analyzer.py +96 -0
- idmtools/analysis/map_worker_entry.py +100 -0
- idmtools/analysis/platform_analysis_bootstrap.py +94 -0
- idmtools/analysis/platform_anaylsis.py +291 -0
- idmtools/analysis/tags_analyzer.py +93 -0
- idmtools/assets/__init__.py +9 -0
- idmtools/assets/asset.py +453 -0
- idmtools/assets/asset_collection.py +514 -0
- idmtools/assets/content_handlers.py +19 -0
- idmtools/assets/errors.py +23 -0
- idmtools/assets/file_list.py +191 -0
- idmtools/builders/__init__.py +11 -0
- idmtools/builders/arm_simulation_builder.py +152 -0
- idmtools/builders/csv_simulation_builder.py +76 -0
- idmtools/builders/simulation_builder.py +348 -0
- idmtools/builders/sweep_arm.py +109 -0
- idmtools/builders/yaml_simulation_builder.py +82 -0
- idmtools/config/__init__.py +7 -0
- idmtools/config/idm_config_parser.py +486 -0
- idmtools/core/__init__.py +10 -0
- idmtools/core/cache_enabled.py +114 -0
- idmtools/core/context.py +68 -0
- idmtools/core/docker_task.py +207 -0
- idmtools/core/enums.py +51 -0
- idmtools/core/exceptions.py +91 -0
- idmtools/core/experiment_factory.py +71 -0
- idmtools/core/id_file.py +70 -0
- idmtools/core/interfaces/__init__.py +5 -0
- idmtools/core/interfaces/entity_container.py +64 -0
- idmtools/core/interfaces/iassets_enabled.py +58 -0
- idmtools/core/interfaces/ientity.py +331 -0
- idmtools/core/interfaces/iitem.py +206 -0
- idmtools/core/interfaces/imetadata_operations.py +89 -0
- idmtools/core/interfaces/inamed_entity.py +17 -0
- idmtools/core/interfaces/irunnable_entity.py +159 -0
- idmtools/core/logging.py +387 -0
- idmtools/core/platform_factory.py +316 -0
- idmtools/core/system_information.py +104 -0
- idmtools/core/task_factory.py +145 -0
- idmtools/entities/__init__.py +10 -0
- idmtools/entities/command_line.py +229 -0
- idmtools/entities/command_task.py +155 -0
- idmtools/entities/experiment.py +787 -0
- idmtools/entities/generic_workitem.py +43 -0
- idmtools/entities/ianalyzer.py +163 -0
- idmtools/entities/iplatform.py +1106 -0
- idmtools/entities/iplatform_default.py +39 -0
- idmtools/entities/iplatform_ops/__init__.py +5 -0
- idmtools/entities/iplatform_ops/iplatform_asset_collection_operations.py +148 -0
- idmtools/entities/iplatform_ops/iplatform_experiment_operations.py +415 -0
- idmtools/entities/iplatform_ops/iplatform_simulation_operations.py +315 -0
- idmtools/entities/iplatform_ops/iplatform_suite_operations.py +322 -0
- idmtools/entities/iplatform_ops/iplatform_workflowitem_operations.py +301 -0
- idmtools/entities/iplatform_ops/utils.py +185 -0
- idmtools/entities/itask.py +316 -0
- idmtools/entities/iworkflow_item.py +167 -0
- idmtools/entities/platform_requirements.py +20 -0
- idmtools/entities/relation_type.py +14 -0
- idmtools/entities/simulation.py +255 -0
- idmtools/entities/suite.py +188 -0
- idmtools/entities/task_proxy.py +37 -0
- idmtools/entities/templated_simulation.py +325 -0
- idmtools/frozen/frozen_dict.py +71 -0
- idmtools/frozen/frozen_list.py +66 -0
- idmtools/frozen/frozen_set.py +86 -0
- idmtools/frozen/frozen_tuple.py +18 -0
- idmtools/frozen/frozen_utils.py +179 -0
- idmtools/frozen/ifrozen.py +66 -0
- idmtools/plugins/__init__.py +5 -0
- idmtools/plugins/git_commit.py +117 -0
- idmtools/registry/__init__.py +4 -0
- idmtools/registry/experiment_specification.py +105 -0
- idmtools/registry/functions.py +28 -0
- idmtools/registry/hook_specs.py +132 -0
- idmtools/registry/master_plugin_registry.py +51 -0
- idmtools/registry/platform_specification.py +138 -0
- idmtools/registry/plugin_specification.py +129 -0
- idmtools/registry/task_specification.py +104 -0
- idmtools/registry/utils.py +119 -0
- idmtools/services/__init__.py +5 -0
- idmtools/services/ipersistance_service.py +135 -0
- idmtools/services/platforms.py +13 -0
- idmtools/utils/__init__.py +5 -0
- idmtools/utils/caller.py +24 -0
- idmtools/utils/collections.py +246 -0
- idmtools/utils/command_line.py +45 -0
- idmtools/utils/decorators.py +300 -0
- idmtools/utils/display/__init__.py +22 -0
- idmtools/utils/display/displays.py +181 -0
- idmtools/utils/display/settings.py +25 -0
- idmtools/utils/dropbox_location.py +30 -0
- idmtools/utils/entities.py +127 -0
- idmtools/utils/file.py +72 -0
- idmtools/utils/file_parser.py +151 -0
- idmtools/utils/filter_simulations.py +182 -0
- idmtools/utils/filters/__init__.py +5 -0
- idmtools/utils/filters/asset_filters.py +88 -0
- idmtools/utils/general.py +286 -0
- idmtools/utils/gitrepo.py +336 -0
- idmtools/utils/hashing.py +239 -0
- idmtools/utils/info.py +124 -0
- idmtools/utils/json.py +82 -0
- idmtools/utils/language.py +107 -0
- idmtools/utils/local_os.py +40 -0
- idmtools/utils/time.py +22 -0
- idmtools-0.0.3.dist-info/METADATA +120 -0
- idmtools-0.0.3.dist-info/RECORD +116 -0
- idmtools-0.0.3.dist-info/entry_points.txt +9 -0
- idmtools-0.0.3.dist-info/licenses/LICENSE.TXT +3 -0
- idmtools-0.0.0.dev0.dist-info/METADATA +0 -41
- idmtools-0.0.0.dev0.dist-info/RECORD +0 -5
- {idmtools-0.0.0.dev0.dist-info → idmtools-0.0.3.dist-info}/WHEEL +0 -0
- {idmtools-0.0.0.dev0.dist-info → idmtools-0.0.3.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Defines our Simulation object.
|
|
3
|
+
|
|
4
|
+
The simulation object can be thought as a metadata object. It represents a configuration of a remote job execution metadata.
|
|
5
|
+
All simulations have a task. Optionally that have assets. All simulations should belong to an Experiment.
|
|
6
|
+
|
|
7
|
+
Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
|
|
8
|
+
"""
|
|
9
|
+
from dataclasses import dataclass, field, fields
|
|
10
|
+
from logging import getLogger, DEBUG
|
|
11
|
+
from typing import List, Union, Mapping, Any, Type, TypeVar, Dict, TYPE_CHECKING
|
|
12
|
+
from idmtools.assets import AssetCollection, Asset
|
|
13
|
+
from idmtools.core import ItemType, NoTaskFound
|
|
14
|
+
from idmtools.core.enums import EntityStatus
|
|
15
|
+
from idmtools.core.interfaces.iassets_enabled import IAssetsEnabled
|
|
16
|
+
from idmtools.core.interfaces.iitem import IItem
|
|
17
|
+
from idmtools.core.interfaces.inamed_entity import INamedEntity
|
|
18
|
+
from idmtools.entities.task_proxy import TaskProxy
|
|
19
|
+
from idmtools.utils.language import get_qualified_class_name_from_obj
|
|
20
|
+
|
|
21
|
+
if TYPE_CHECKING: # pragma: no cover
|
|
22
|
+
from idmtools.entities.itask import ITask
|
|
23
|
+
from idmtools.entities.iplatform import IPlatform
|
|
24
|
+
from idmtools.entities.experiment import Experiment
|
|
25
|
+
|
|
26
|
+
logger = getLogger(__name__)
|
|
27
|
+
user_logger = getLogger('user')
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass
|
|
31
|
+
class Simulation(IAssetsEnabled, INamedEntity):
|
|
32
|
+
"""
|
|
33
|
+
Class that represents a generic simulation.
|
|
34
|
+
|
|
35
|
+
This class needs to be implemented for each model type with specifics.
|
|
36
|
+
"""
|
|
37
|
+
#: Experiment ID
|
|
38
|
+
experiment_id: str = field(default=None)
|
|
39
|
+
#: Task representing the configuration of the command to be executed
|
|
40
|
+
task: 'ITask' = field(default=None) # noqa: F821
|
|
41
|
+
#: Item Type. Should not be changed from Simulation
|
|
42
|
+
item_type: ItemType = field(default=ItemType.SIMULATION, compare=False)
|
|
43
|
+
#: Control whether we should replace the task with a proxy after creation
|
|
44
|
+
__replace_task_with_proxy: bool = field(default=True, init=False, compare=False)
|
|
45
|
+
#: Ensure we don't gather assets twice
|
|
46
|
+
__assets_gathered: bool = field(default=False)
|
|
47
|
+
#: Extra arguments to pass on creation to platform
|
|
48
|
+
_platform_kwargs: dict = field(default_factory=dict)
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def experiment(self) -> 'Experiment': # noqa: F821
|
|
52
|
+
"""
|
|
53
|
+
Get experiment parent.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
Parent Experiment
|
|
57
|
+
"""
|
|
58
|
+
return self.parent
|
|
59
|
+
|
|
60
|
+
@experiment.setter
|
|
61
|
+
def experiment(self, experiment: 'Experiment'): # noqa: F821
|
|
62
|
+
"""
|
|
63
|
+
Set the parent experiment.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
experiment: Experiment to set as parent.
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
None
|
|
70
|
+
"""
|
|
71
|
+
self.parent = experiment
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def parent(self):
|
|
75
|
+
"""
|
|
76
|
+
Return parent object for item.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
Parent entity if set
|
|
80
|
+
"""
|
|
81
|
+
if not self._parent:
|
|
82
|
+
self.parent_id = self.parent_id or self.experiment_id
|
|
83
|
+
if not self.parent_id:
|
|
84
|
+
return None
|
|
85
|
+
if not self.platform:
|
|
86
|
+
from idmtools.core import NoPlatformException
|
|
87
|
+
raise NoPlatformException("The object has no platform set...")
|
|
88
|
+
exp = self.platform.get_item(self.parent_id, ItemType.EXPERIMENT, force=True)
|
|
89
|
+
self._parent = exp
|
|
90
|
+
self.parent_id = self.suite_id = exp.id
|
|
91
|
+
|
|
92
|
+
return self._parent
|
|
93
|
+
|
|
94
|
+
@parent.setter
|
|
95
|
+
def parent(self, parent: 'Experiment'):
|
|
96
|
+
"""
|
|
97
|
+
Sets the parent object for Entity.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
parent: Parent object
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
None
|
|
104
|
+
"""
|
|
105
|
+
if parent is not None:
|
|
106
|
+
self._parent = parent
|
|
107
|
+
self.parent_id = self.suite_id = parent.id
|
|
108
|
+
else:
|
|
109
|
+
self._parent = self.parent_id = self.experiment_id = None
|
|
110
|
+
|
|
111
|
+
def __repr__(self):
|
|
112
|
+
"""
|
|
113
|
+
String representation of simulation.
|
|
114
|
+
"""
|
|
115
|
+
return f"<Simulation: {self.uid} - Exp_id: {self.parent_id}>"
|
|
116
|
+
|
|
117
|
+
def __hash__(self):
|
|
118
|
+
"""
|
|
119
|
+
Hash of simulation(id).
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
Hash of simulation
|
|
123
|
+
"""
|
|
124
|
+
return id(self.uid)
|
|
125
|
+
|
|
126
|
+
def pre_creation(self, platform: 'IPlatform'):
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
Runs before a simulation is created server side.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
platform: Platform the item is being executed on
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
None
|
|
136
|
+
"""
|
|
137
|
+
# skip the IItem created function
|
|
138
|
+
IItem.pre_creation(self, platform)
|
|
139
|
+
if self.task is None:
|
|
140
|
+
msg = 'Task is required for simulations'
|
|
141
|
+
user_logger.error(msg)
|
|
142
|
+
raise NoTaskFound(msg)
|
|
143
|
+
|
|
144
|
+
if logger.isEnabledFor(DEBUG):
|
|
145
|
+
logger.debug('Calling task pre creation')
|
|
146
|
+
self.task.pre_creation(self, platform)
|
|
147
|
+
|
|
148
|
+
self.gather_assets()
|
|
149
|
+
|
|
150
|
+
if self.__class__ is not Simulation:
|
|
151
|
+
# Add a tag to keep the Simulation class name
|
|
152
|
+
sn = get_qualified_class_name_from_obj(self)
|
|
153
|
+
if logger.isEnabledFor(DEBUG):
|
|
154
|
+
logger.debug(f'Setting Simulation Tag "simulation_type" to "{sn}"')
|
|
155
|
+
self.tags["simulation_type"] = sn
|
|
156
|
+
|
|
157
|
+
def post_creation(self, platform: 'IPlatform') -> None:
|
|
158
|
+
"""
|
|
159
|
+
Called after a simulation is created.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
platform: Platform simulation is being executed on
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
None
|
|
166
|
+
"""
|
|
167
|
+
if logger.isEnabledFor(DEBUG):
|
|
168
|
+
logger.debug('Calling task post creation')
|
|
169
|
+
if self.task is not None and not isinstance(self.task, TaskProxy):
|
|
170
|
+
self.task.post_creation(self, self.platform)
|
|
171
|
+
|
|
172
|
+
IItem.post_creation(self, platform)
|
|
173
|
+
if self.__replace_task_with_proxy or (self.parent and self.parent._Experiment__replace_task_with_proxy):
|
|
174
|
+
if logger.isEnabledFor(DEBUG):
|
|
175
|
+
logger.debug('Replacing task with proxy')
|
|
176
|
+
self.task = TaskProxy.from_task(self.task)
|
|
177
|
+
if self.status is None:
|
|
178
|
+
self.status = EntityStatus.CREATED
|
|
179
|
+
self.platform = platform
|
|
180
|
+
|
|
181
|
+
def pre_getstate(self):
|
|
182
|
+
"""
|
|
183
|
+
Return default values for :meth:`pickle_ignore_fields`. Call before pickling.
|
|
184
|
+
"""
|
|
185
|
+
from idmtools.assets import AssetCollection
|
|
186
|
+
from idmtools.core.interfaces.entity_container import EntityContainer
|
|
187
|
+
return {"assets": AssetCollection(), "simulations": EntityContainer()}
|
|
188
|
+
|
|
189
|
+
def gather_assets(self):
|
|
190
|
+
"""
|
|
191
|
+
Gather all the assets for the simulation.
|
|
192
|
+
"""
|
|
193
|
+
if not self.__assets_gathered:
|
|
194
|
+
self.task.gather_transient_assets()
|
|
195
|
+
self.assets.add_assets(self.task.transient_assets, fail_on_duplicate=False)
|
|
196
|
+
self.__assets_gathered = True
|
|
197
|
+
|
|
198
|
+
@classmethod
|
|
199
|
+
def from_task(cls, task: 'ITask', tags: Dict[str, Any] = None, # noqa E821
|
|
200
|
+
asset_collection: AssetCollection = None):
|
|
201
|
+
"""
|
|
202
|
+
Create a simulation from a task.
|
|
203
|
+
|
|
204
|
+
Args:
|
|
205
|
+
task: Task to create from
|
|
206
|
+
tags: Tags to create on the simulation
|
|
207
|
+
asset_collection: Simulation Assets
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
Simulation using the parameters provided
|
|
211
|
+
"""
|
|
212
|
+
return Simulation(task=task, tags=dict() if tags is None else tags,
|
|
213
|
+
assets=asset_collection if asset_collection else AssetCollection())
|
|
214
|
+
|
|
215
|
+
def list_static_assets(self, platform: 'IPlatform' = None, **kwargs) -> List[Asset]:
|
|
216
|
+
"""
|
|
217
|
+
List assets that have been uploaded to a server already.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
platform: Optional platform to load assets list from
|
|
221
|
+
**kwargs:
|
|
222
|
+
|
|
223
|
+
Returns:
|
|
224
|
+
List of assets
|
|
225
|
+
|
|
226
|
+
Raises:
|
|
227
|
+
ValueError - If you try to list an assets for an simulation that hasn't been created/loaded from a remote platform.
|
|
228
|
+
"""
|
|
229
|
+
if self.id is None:
|
|
230
|
+
raise ValueError("You can only list static assets on an existing experiment")
|
|
231
|
+
p = super()._check_for_platform_from_context(platform)
|
|
232
|
+
return p._simulations.list_assets(self, **kwargs)
|
|
233
|
+
|
|
234
|
+
def to_dict(self) -> Dict:
|
|
235
|
+
"""
|
|
236
|
+
Do a lightweight conversation to json.
|
|
237
|
+
|
|
238
|
+
Returns:
|
|
239
|
+
Dict representing json of object
|
|
240
|
+
"""
|
|
241
|
+
result = dict()
|
|
242
|
+
for f in fields(self):
|
|
243
|
+
if not f.name.startswith("_") and f.name not in ['parent']:
|
|
244
|
+
result[f.name] = getattr(self, f.name)
|
|
245
|
+
result['_uid'] = self.uid
|
|
246
|
+
result['task'] = self.task.to_dict() if self.task else None
|
|
247
|
+
return result
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
# TODO Rename to T simulation once old simulation is one
|
|
251
|
+
TTSimulation = TypeVar("TTSimulation", bound=Simulation)
|
|
252
|
+
TTSimulationClass = Type[TTSimulation]
|
|
253
|
+
TTSimulationBatch = List[TTSimulation]
|
|
254
|
+
TTAllSimulationData = Mapping[TTSimulation, Any]
|
|
255
|
+
TTSimulationList = List[Union[TTSimulation, str]]
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Defines our Suite object.
|
|
3
|
+
|
|
4
|
+
The Suite object can be thought as a metadata object. It represents a container object for Experiments. All Suites should have one or more experiments.
|
|
5
|
+
|
|
6
|
+
Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
|
|
7
|
+
"""
|
|
8
|
+
from typing import NoReturn, Type, TYPE_CHECKING, Dict, List
|
|
9
|
+
from abc import ABC
|
|
10
|
+
from dataclasses import dataclass, field, fields
|
|
11
|
+
from idmtools.core.interfaces.iitem import IItem
|
|
12
|
+
from idmtools.core.interfaces.inamed_entity import INamedEntity
|
|
13
|
+
from idmtools.core import ItemType, EntityContainer
|
|
14
|
+
from idmtools.core.interfaces.irunnable_entity import IRunnableEntity
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING: # pragma: no cover
|
|
17
|
+
from idmtools.entities.iplatform import IPlatform
|
|
18
|
+
from idmtools.entities.experiment import Experiment
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass(repr=False)
|
|
22
|
+
class Suite(INamedEntity, ABC, IRunnableEntity):
|
|
23
|
+
"""
|
|
24
|
+
Class that represents a generic suite (a collection of experiments).
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
experiments: The child items of this suite.
|
|
28
|
+
"""
|
|
29
|
+
experiments: EntityContainer = field(
|
|
30
|
+
default_factory=lambda: EntityContainer(),
|
|
31
|
+
compare=False,
|
|
32
|
+
metadata={"pickle_ignore": True}
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
item_type: ItemType = field(default=ItemType.SUITE, compare=False, init=False)
|
|
36
|
+
description: str = field(default=None, compare=False)
|
|
37
|
+
|
|
38
|
+
def __post_init__(self):
|
|
39
|
+
"""
|
|
40
|
+
Initialize Suite.
|
|
41
|
+
"""
|
|
42
|
+
self.experiments = EntityContainer()
|
|
43
|
+
|
|
44
|
+
def add_experiment(self, experiment: 'Experiment') -> 'NoReturn': # noqa: F821
|
|
45
|
+
"""
|
|
46
|
+
Add an experiment to the suite.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
experiment: the experiment to be linked to suite
|
|
50
|
+
"""
|
|
51
|
+
# Link the suite to the experiment. Assumes the experiment suite setter adds the experiment to the suite.
|
|
52
|
+
experiment._parent = self
|
|
53
|
+
experiment.parent_id = experiment.suite_id = self.id
|
|
54
|
+
|
|
55
|
+
ids = [exp.uid for exp in self.experiments]
|
|
56
|
+
if experiment.uid in ids:
|
|
57
|
+
return
|
|
58
|
+
|
|
59
|
+
# add experiment
|
|
60
|
+
self.experiments.append(experiment)
|
|
61
|
+
|
|
62
|
+
# clear possible directory cache for Experiment and Simulation
|
|
63
|
+
experiment.clear_directory_cache()
|
|
64
|
+
|
|
65
|
+
def display(self):
|
|
66
|
+
"""
|
|
67
|
+
Display workflowitem.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
None
|
|
71
|
+
"""
|
|
72
|
+
from idmtools.utils.display import display, suite_table_display
|
|
73
|
+
display(self, suite_table_display)
|
|
74
|
+
|
|
75
|
+
def pre_creation(self, platform: 'IPlatform'):
|
|
76
|
+
"""
|
|
77
|
+
Pre Creation of IWorkflowItem.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
platform: Platform we are creating item on
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
None
|
|
84
|
+
"""
|
|
85
|
+
IItem.pre_creation(self, platform)
|
|
86
|
+
|
|
87
|
+
def post_creation(self, platform: 'IPlatform'):
|
|
88
|
+
"""
|
|
89
|
+
Post Creation of IWorkflowItem.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
platform: Platform
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
None
|
|
96
|
+
"""
|
|
97
|
+
IItem.post_creation(self, platform)
|
|
98
|
+
|
|
99
|
+
def __repr__(self):
|
|
100
|
+
"""
|
|
101
|
+
String representation of suite.
|
|
102
|
+
"""
|
|
103
|
+
count = len(self.experiments) if self.experiments is not None else 0
|
|
104
|
+
return f"<Suite {self.uid} - {count} experiments>"
|
|
105
|
+
|
|
106
|
+
@property
|
|
107
|
+
def done(self):
|
|
108
|
+
"""
|
|
109
|
+
Return if a suite has finished executing.
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
True if all experiments have ran, False otherwise
|
|
113
|
+
"""
|
|
114
|
+
return all([s.done for s in self.experiments])
|
|
115
|
+
|
|
116
|
+
@property
|
|
117
|
+
def succeeded(self) -> bool:
|
|
118
|
+
"""
|
|
119
|
+
Return if a suite has succeeded. A suite is succeeded when all experiments have succeeded.
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
True if all experiments have succeeded, False otherwise
|
|
123
|
+
"""
|
|
124
|
+
return all([s.succeeded for s in self.experiments])
|
|
125
|
+
|
|
126
|
+
def to_dict(self) -> Dict:
|
|
127
|
+
"""
|
|
128
|
+
Converts suite to a dictionary.
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
Dictionary of suite.
|
|
132
|
+
"""
|
|
133
|
+
result = dict()
|
|
134
|
+
for f in fields(self):
|
|
135
|
+
if not f.name.startswith("_") and f.name not in ['parent']:
|
|
136
|
+
result[f.name] = getattr(self, f.name)
|
|
137
|
+
result['_uid'] = self.uid
|
|
138
|
+
return result
|
|
139
|
+
|
|
140
|
+
def get_experiments(self) -> EntityContainer:
|
|
141
|
+
"""
|
|
142
|
+
Retrieve the experiments associated with this suite from the platform.
|
|
143
|
+
Returns:
|
|
144
|
+
EntityContainer: A container of Experiment objects belonging to this suite.
|
|
145
|
+
"""
|
|
146
|
+
experiments = self.experiments
|
|
147
|
+
if not experiments:
|
|
148
|
+
experiments = self.platform.get_children(self.id, ItemType.SUITE, force=True)
|
|
149
|
+
return experiments
|
|
150
|
+
|
|
151
|
+
def get_simulations_by_tags(self, tags=None, status=None, entity_type=False, skip_sims=None, max_simulations=None,
|
|
152
|
+
**kwargs) -> Dict[str, List[str]]:
|
|
153
|
+
"""
|
|
154
|
+
Retrieve simulation ids or simulation objects with matching tags across all experiments in the suite.
|
|
155
|
+
This method filters simulations based on the provided tags, skipping specified simulations,
|
|
156
|
+
and limiting the number of results if `max_simulations` is set. The return type can be
|
|
157
|
+
either a dictionary of simulation IDs or simulation objects, depending on the `entity_type` flag.
|
|
158
|
+
Args:
|
|
159
|
+
status:
|
|
160
|
+
tags (dict, optional): A simulation's tags to filter by.
|
|
161
|
+
status (EntityStatus, Optional): Simulation status.
|
|
162
|
+
entity_type (bool, optional): If True, return simulation objects; otherwise, return simulation IDs. Defaults to False.
|
|
163
|
+
skip_sims (List[str], optional): A list of simulation IDs to exclude from the results.
|
|
164
|
+
max_simulations (int, optional): The maximum number of simulations to return per experiment.
|
|
165
|
+
**kwargs: Additional filter parameters.
|
|
166
|
+
Returns:
|
|
167
|
+
Dict[str, List[str]]: A dictionary where the keys are experiment IDs and the values are lists of
|
|
168
|
+
simulation IDs or simulation objects, depending on the `entity_type` flag.
|
|
169
|
+
"""
|
|
170
|
+
experiments = self.get_experiments()
|
|
171
|
+
sims = {}
|
|
172
|
+
for experiment in experiments:
|
|
173
|
+
sims[experiment.id] = experiment.get_simulations_by_tags(tags=tags, status=status, entity_type=entity_type,
|
|
174
|
+
skip_sims=skip_sims,
|
|
175
|
+
max_simulations=max_simulations, **kwargs)
|
|
176
|
+
return sims
|
|
177
|
+
|
|
178
|
+
def __setstate__(self, state):
|
|
179
|
+
"""
|
|
180
|
+
Add ignored fields back since they don't exist in the pickle.
|
|
181
|
+
"""
|
|
182
|
+
# First call parent's __setstate__ to restore base attributes
|
|
183
|
+
super().__setstate__(state)
|
|
184
|
+
# Restore the pickle fields with values requested
|
|
185
|
+
self.experiments = EntityContainer()
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
ISuiteClass = Type[Suite]
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Defines our TaskProxy object.
|
|
3
|
+
|
|
4
|
+
The TaskProxy object is mean to reduce the memory requirements of large simulation sets/configurations after provisioning. Instead of keeping the full original object in memory,
|
|
5
|
+
the object is replaced with a proxy object with minimal information needed to work with the task.
|
|
6
|
+
|
|
7
|
+
Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
|
|
8
|
+
"""
|
|
9
|
+
from typing import Union
|
|
10
|
+
from dataclasses import dataclass, field
|
|
11
|
+
from idmtools.entities import CommandLine
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class TaskProxy:
|
|
16
|
+
"""
|
|
17
|
+
This class is used to reduce the memory footprint of tasks after a simulation has been provisioned.
|
|
18
|
+
"""
|
|
19
|
+
command: Union[str, CommandLine] = field(default=None)
|
|
20
|
+
is_docker: bool = False
|
|
21
|
+
is_gpu: bool = False
|
|
22
|
+
|
|
23
|
+
@staticmethod
|
|
24
|
+
def from_task(task: 'ITask'): # noqa: F821
|
|
25
|
+
"""
|
|
26
|
+
Create a task proxy from a task.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
task: Task to proxy
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
TaskProxy of task
|
|
33
|
+
"""
|
|
34
|
+
from idmtools.core.docker_task import DockerTask
|
|
35
|
+
is_docker = isinstance(task, DockerTask)
|
|
36
|
+
item = TaskProxy(command=task.command, is_docker=is_docker, is_gpu=is_docker and task.use_nvidia_run)
|
|
37
|
+
return item
|