Space: structured or unstructured set of points (current NIFTy's "Domain")SpaceTuple: external product of zero or more Spaces (current NIFTy's "DomainTuple") SpaceTuple = (Space, Space, ...)SpaceTupleDict: dictionary (with string keys) of one or more SpaceTuples SpaceTupleDict = {name1: SpaceTuple1, name2: SpaceTuple2, ...} (current NIFTy's "MultiDomain")Domain: This is an abstract concept. Can currently be represented by SpaceTuple or SpaceTupleDictSpecial domains: ScalarDomain: empty SpaceTupleOperator:- Operators take an Operand defined on an input domain, transform it in some way and return a new Operand defined on a (possibly different) target domain.- Operators can be concatenated, as long as the domains at the interface are identical. The result is another Operator.Operand:- Operand objects represent fields and potentially their Jacobians and metrics.- an Operand object can be asked for its "value" and (if configured accordingly) its Jacobian. If the target domain of an Operand object is scalar, a metric may also be available.- Applying an Operator to an Operand object will always return another Operand object.class Operator(object): @property def domain(self): # return input domain @property def target(self): # return output domain def __call__(self, other): # if isinstance(other, Operand) return an Operand object # else return an Operator object def __matmul__(self, other): return self(other) class LinearOperator(Operator): # more or less analogous to the current LinearOperatorclass Operand(object): # this unifies current NIFTy's Field, MultiField, and Linearization classes @property def domain(self): # if no Jacobian is present, return None, else the Jacobian's domain. @property def target(self): # return the domain on which the value of the Operand is defined. This is # also the Jacobian's target (if a Jacobian is defined) @property def val(self): # return a low level data structure holding the actual values (currently numpy.ndarray # or dictionary of numpy.ndarrays. Read-only. def val_rw(self): # return a writeable copy of `val` def fld(self): # return am Operand that only contains the value content of this object. Its Jacobian and # potential higher derivatives will be `None`. @property def jac(self): return a Jacobian LinearOperator if possible, else None @property def want_metric(self): return True or False @property def metric(self): if self.jacobian is None, raise an exception if self.target is not ScalarDomain, raise an exception if not self.want_metric, raise an exception if metric cannot be computed, raise an exception return metric