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 __init__(self, name, cv_callable, cv_time_reversible=False, cv_requires_lists=False, cv_wrap_numpy_array=False, cv_scalarize_numpy_singletons=False, **kwargs): """ Parameters ---------- name cv_callable : callable (function or class with __call__) The callable to be used cv_time_reversible cv_requires_lists : If ``True`` the internal function always a list of elements instead of single values. It also means that if you call the CV with a list of snapshots a list of snapshot objects will be passed. If ``False`` a list of Snapshots like a trajectory will be passed snapshot by snapshot. cv_wrap_numpy_array : bool, default: False if ``True`` the returned array will be wrapped with a ``numpy.array()`` which will convert a list of numpy arrays into a single large numpy.array. This is useful for post-processing of larger data since numpy arrays are easier to manipulate. cv_scalarize_numpy_singletons : bool, default: True If ``True`` then arrays of length 1 will be treated as array with one dimension less. e.g. [[1], [2], [3]] will be turned into [1, 2, 3]. This is often useful, when you use en external function to get only a single value. **kwargs : kwargs a dictionary with named arguments which should be used with ``c``. Either for class creation or for calling the function Notes ----- This function is abstract and need _eval to be implemented to work. Problem is that there are two types of callable functions: 1. direct functions: these can be called and give the wanted value ``c(snapshot, **kwargs)`` would be the typical call 2. a generating function: a function the creates the callable object ``c(**kwargs)(snapshot)`` is the typical call. This is usually used for classes. Create the instance and then use it. This function is very powerful, but need some explanation if you want the function to be stored alongside all other information in your storage. The problem is that a python function relies (usually) on an underlying global namespace that can be accessed. This is especially important when using an iPython notebook. The problem is, that the function that stored your used-defined function has no knowledge about this underlying namespace and its variables. All it can save is names of variables from your namespace to be used. This means you can store arbitrary functions, but these will only work, if you call the reconstructed ones from the same context (scope). This is a powerful feature because a function might do something different in another context, but in our case we cannot store these additional information. What we can do, is analyse your function and determine which variables (if at all these are) and inform you, if you might run into trouble. To avoid problems you should try to: 1. import necessary modules inside of your function 2. create constants inside your function 3. if variables from the global scope are used these need to be stored with the function and this can only be done if they are passed as arguments to the function and added as kwargs to the FunctionCV >>> import openpathsampling as paths >>> def func(snapshot, indices): >>> import mdtraj as md >>> return md.compute_dihedrals( >>> paths.Trajectory([snapshot]).to_mdtraj(), indices=indices) >>> cv = FunctionCV('my_cv', func, indices=[[4, 6, 8, 10]]) The function will also check if non-standard modules are imported, which are now ``numpy``, ``math``, ``msmbuilder``, ``pandas`` and ``mdtraj`` """ super(CallableCV, self).__init__(name, cv_time_reversible=cv_time_reversible) self.cv_requires_lists = cv_requires_lists self.cv_wrap_numpy_array = cv_wrap_numpy_array self.cv_scalarize_numpy_singletons = cv_scalarize_numpy_singletons self.cv_callable = cv_callable if kwargs is None: kwargs = dict() self.kwargs = kwargs self._eval_dict = cd.Function(self._eval, self.cv_requires_lists, self.cv_scalarize_numpy_singletons) post = self._post > self._eval_dict if cv_wrap_numpy_array: # noinspection PyTypeChecker post = cd.MergeNumpy() > post self._post = post