class InVolumeCV(CollectiveVariable): """Turn a :class:`openpathsampling.volume.Volume` into a collective variable Attributes ---------- name volume """ def __init__(self, name, volume): """ Parameters ---------- name : string name of the collective variable volume : openpathsampling.Volume the Volume instance to be treated as a (storable) CV """ super(InVolumeCV, self).__init__(name, cv_time_reversible=True) self.volume = volume self._eval_dict = cd.Function(self._eval, requires_lists=False) self._post = self._post > self._eval_dict def _eval(self, items): return bool(self.volume(items)) to_dict = create_to_dict(['name', 'volume'])
class CollectiveVariable(PseudoAttribute): """ Wrapper for a function that acts on snapshots or iterables of snapshots Parameters ---------- name : string A descriptive name of the collectivevariable. It is used in the string representation. cv_time_reversible : bool If ``True`` (default) the CV assumes that reversed snapshots have the same value. This is the default case when CVs do not depend on momenta reversal. This will speed up computation of CVs by about a factor of two. In rare cases you might want to set this to ``False`` Attributes ---------- name cv_time_reversible _cache_dict : :class:`openpathsampling.chaindict.ChainDict` The ChainDict that will cache calculated values for fast access """ # do not store the settings for the disk cache. These are independent # and stored in the cache itself _excluded_attr = [ 'diskcache_enabled', 'diskcache_allow_incomplete', 'diskcache_chunksize' ] def __init__(self, name, cv_time_reversible=False): super(CollectiveVariable, self).__init__(name, paths.BaseSnapshot) self.cv_time_reversible = cv_time_reversible self.diskcache_allow_incomplete = not self.cv_time_reversible self.diskcache_chunksize = ObjectStore.default_store_chunk_size self._cache_dict = cd.ReversibleCacheChainDict( WeakKeyCache(), reversible=cv_time_reversible) self._single_dict._post = self._cache_dict # self._post = self._single_dict > self._cache_dict to_dict = create_to_dict(['name', 'cv_time_reversible'])
class CollectiveVariable(cd.Wrap, StorableNamedObject): """ Wrapper for a function that acts on snapshots or iterables of snapshots Parameters ---------- name : string A descriptive name of the collectivevariable. It is used in the string representation. cv_time_reversible : bool If `True` (default) the CV assumes that reversed snapshots have the same value. This is the default case when CVs do not depend on momenta reversal. This will speed up computation of CVs by about a factor of two. In rare cases you might want to set this to `False` Attributes ---------- name cv_time_reversible _single_dict : :class:`openpathsampling.chaindict.ChainDict` The ChainDict that takes care of using only a single element instead of an iterable. In the case of a single object. It will be wrapped in a list and later only the single element will be returned _cache_dict : :class:`openpathsampling.chaindict.ChainDict` The ChainDict that will cache calculated values for fast access """ # do not store the settings for the disk cache. These are independent # and stored in the cache itself _excluded_attr = [ 'diskcache_enabled', 'diskcache_allow_incomplete', 'diskcache_chunksize' ] def __init__( self, name, cv_time_reversible=False ): if (type(name) is not str and type(name) is not unicode) or len( name) == 0: raise ValueError('name must be a non-empty string') StorableNamedObject.__init__(self) self.name = name self.cv_time_reversible = cv_time_reversible # default settings if we should create a disk cache self.diskcache_enabled = False self.diskcache_template = None self.diskcache_allow_incomplete = not self.cv_time_reversible self.diskcache_chunksize = ObjectStore.default_store_chunk_size self._single_dict = cd.ExpandSingle() self._cache_dict = cd.ReversibleCacheChainDict( WeakKeyCache(), reversible=cv_time_reversible ) self._store_dict = None self._eval_dict = None self.stores = [] super(CollectiveVariable, self).__init__( post=self._single_dict > self._cache_dict) def enable_diskcache(self): self.diskcache_enabled = True return self def with_diskcache( self, template=None, chunksize=None, allow_incomplete=None): self.diskcache_enabled = True if template: self.diskcache_template = template if allow_incomplete: self.diskcache_allow_incomplete = allow_incomplete if chunksize: self.diskcache_chunksize = chunksize return self def disable_diskcache(self): self.diskcache_enabled = False return self def set_cache_store(self, value_store): """ Attach store variables to the collective variables. If used the collective variable will automatically sync values with the store and load from it if necessary. If the CV is created with `diskcache_enabled = True`. This will be done during CV creation. Parameters ---------- value_store : :class:`openpathsampling.netcdfplus.ObjectStore` the store / variable that holds the output values / objects """ if value_store is None: return if value_store not in self.stores: self.stores = [value_store] + self.stores self._update_store_dict() elif self.stores is not value_store: self.stores = [value_store] + \ [s for s in self.stores if s is not value_store] self._update_store_dict() def _update_store_dict(self): cv_stores = map(cd.StoredDict, self.stores) last_cv = self._eval_dict for s in reversed(cv_stores): s._post = last_cv last_cv = s if len(self.stores) > 0: self._store_dict = cv_stores[0] else: self._store_dict = None self._cache_dict._post = last_cv def add_cache_from_storage(self, storage): """ Attach store variables to the collective variables. If used the collective variable will automatically sync values with the store and load from it if necessary. If the CV is created with `diskcache_enabled = True`. This will be done during CV creation. Parameters ---------- storage : :class:`openpathsampling.storage.Storage` the storage """ idx = storage.cvs.index[self.__uuid__] if idx is not None: value_store = storage.snapshots.get_cv_cache(idx) if value_store is None: return if value_store not in self.stores: self.stores.append(value_store) self._update_store_dict() else: raise ValueError('The given storage does not contain this CV.') # This is important since we subclass from list and lists are not hashable # but CVs should be __hash__ = StorableNamedObject.__hash__ def sync(self): """ Sync this CV with the attached storages """ if self._store_dict: self._store_dict.sync() def cache_all(self): """ Sync this CV with attached storages """ if self._store_dict: self._store_dict.cache_all() def __eq__(self, other): """Override the default Equals behavior""" if isinstance(other, self.__class__): if self.name != other.name: return False return True return NotImplemented def __ne__(self, other): """Define a non-equality test""" if isinstance(other, self.__class__): return not self.__eq__(other) return NotImplemented to_dict = create_to_dict(['name', 'cv_time_reversible'])