##############################################################################
# Institute for the Design of Advanced Energy Systems Process Systems
# Engineering Framework (IDAES PSE Framework) Copyright (c) 2018-2019, by the
# software owners: The Regents of the University of California, through
# Lawrence Berkeley National Laboratory, National Technology & Engineering
# Solutions of Sandia, LLC, Carnegie Mellon University, West Virginia
# University Research Corporation, et al. All rights reserved.
#
# Please see the files COPYRIGHT.txt and LICENSE.txt for full copyright and
# license information, respectively. Both files are also available online
# at the URL "https://github.com/IDAES/idaes-pse".
##############################################################################
"""
The 'experiment' is a root container for a coherent
set of 'resources'.
"""
# stdlib
from copy import deepcopy
import logging
# local
from idaes.dmf import resource, errors
__author__ = 'Dan Gunter <dkgunter@lbl.gov>'
_log = logging.getLogger(__name__)
[docs]class Experiment(resource.Resource):
"""An experiment is a way of grouping resources in a way that
makes sense to the user.
It is also a useful unit for passing as an argument to functions,
since it has a standard 'slot' for the DMF instance that created it.
"""
def __init__(self, dmf, **kwargs):
"""Constructor. Adds the new experiment to the DMF.
Args:
dmf (DMF): Data Management Framework instance.
kwargs: Keyword arguments passed to parent class.
"""
super(Experiment, self).__init__(value=kwargs)
self.v[self.TYPE_FIELD] = resource.TY_EXPERIMENT
dmf.add(self)
self._dmf = dmf
@property
def dmf(self):
return self._dmf
[docs] def add(self, rsrc):
"""Add a resource to an experiment.
This does two things:
1. Establishes an "experiment" type of relationship between the
new resource and the experiment.
2. Adds the resource to the DMF
Args:
rsrc (resource.Resource): The resource to add.
Returns:
resource.Resource: Added (input) resource, for chaining calls.
"""
resource.create_relation_args(self, resource.PR_CONTAINS, rsrc)
self._dmf.update(rsrc, upsert=True)
self._dmf.update(self)
[docs] def copy(self, new_id=True, **kwargs):
"""Get a copy of this experiment. The returned object will
have been added to the DMF.
Args:
new_id (bool): If True, generate a new unique ID for the copy.
kwargs: Values to set in new instance after copying.
Returns:
Experiment: A (mostly deep) copy.
Note that the DMF instance is just a reference to the
same object as in the original, and they will share state.
"""
new_exp = Experiment(self._dmf)
new_exp.v = deepcopy(self.v)
new_exp.v.update(kwargs)
if new_id:
new_exp.set_id()
self._dmf.add(new_exp)
return new_exp
[docs] def update(self):
"""Update experiment to current values.
"""
self._dmf.update(self, sync_relations=True)
[docs] def remove(self):
"""Remove this experiment from the associated DMF instance.
"""
# remove from the DMF
self._dmf.remove(self.id)
# cut the connection to the DMF instance
self._dmf = None
# disable known methods (via monkeypatching!)
for m in 'add', 'update', 'remove', 'link', 'copy':
self.__dict__[m] = self._removed
[docs] def link(self, subj, predicate=resource.PR_CONTAINS, obj=None):
"""Add and update relation triple in DMF.
Args:
subj (resource.Resource): Subject
predicate (str): Predicate
obj (resource.Resource): Object
Returns:
None
"""
if obj is None:
obj = self
resource.create_relation_args(subj, predicate, obj)
self._dmf.update(subj)
self._dmf.update(obj)
def _removed(self, *args, **kwargs):
raise errors.BadResourceError('This experiment has been removed')