Source code for cuqi.array._array
import numpy as np
from cuqi.geometry import _DefaultGeometry1D
[docs]
class CUQIarray(np.ndarray):
"""
A class to represent data arrays, subclassed from numpy array, along with geometry and plotting
Parameters
----------
input_array : ndarray
A numpy array holding the parameter or function values.
is_par : bool, default True
Boolean flag whether input_array is to be interpreted as parameter (True) or function values (False).
geometry : cuqi.geometry.Geometry, default None
Contains the geometry related of the data.
"""
def __repr__(self) -> str:
return "CUQIarray: NumPy array wrapped with geometry.\n" + \
"---------------------------------------------\n\n" + \
"Geometry:\n {}\n\n".format(self.geometry) + \
"Parameters:\n {}\n\n".format(self.is_par) + \
"Array:\n" + \
super().__repr__()
def __new__(cls, input_array, is_par=True, geometry=None):
# Input array is an already formed ndarray instance
# We first cast to be our class type
obj = np.asarray(input_array).view(cls)
# add the new attribute to the created instance
obj.is_par = is_par
if (not is_par) and (geometry is None):
raise ValueError("geometry cannot be none when initializing a CUQIarray as function values (with is_par False).")
if is_par and (obj.ndim>1):
raise ValueError("input_array cannot be multidimensional when initializing CUQIarray as parameter (with is_par True).")
if geometry is None:
geometry = _DefaultGeometry1D(grid=obj.__len__())
obj.geometry = geometry
# Finally, we must return the newly created object:
return obj
def __array_finalize__(self, obj):
# see InfoArray.__array_finalize__ for comments
if obj is None: return
self.is_par = getattr(obj, 'is_par', True)
self.geometry = getattr(obj, 'geometry', None)
@property
def funvals(self):
""" Returns itself as function values. """
if self.is_par is True:
vals = self.geometry.par2fun(self)
else:
vals = self
if isinstance(vals, np.ndarray):
if vals.dtype == np.dtype('O'):
# if vals is of type np.ndarray, but the data type of the array
# is object (e.g. FEniCS function), then extract the object and
# return it. reshape(1) is needed to convert the shape from
# () to (1,).
return self.reshape(1)[0]
else:
# else, cast the np.ndarray to a CUQIarray
return type(self)(vals,is_par=False,geometry=self.geometry) #vals.view(np.ndarray)
else:
return vals
@property
def parameters(self):
""" Returns itself as parameters. """
if self.is_par is False:
if self.dtype == np.dtype('O'):
# If the current state if the CUQIarray is function values, and
# the data type of self is object (e.g. FEniCS function), then
# extract the object and save it. reshape(1) is needed to
# convert the shape from () to (1,).
funvals = self.reshape(1)[0]
else:
funvals = self
vals = self.geometry.fun2par(funvals)
else:
vals = self
return type(self)(vals,is_par=True,geometry=self.geometry)
[docs]
def to_numpy(self):
"""Return a numpy array of the CUQIarray data. If is_par is True, then
the parameters are returned as numpy.ndarray. If is_par is False, then
the function values are returned instead.
"""
try:
return self.view(np.ndarray)
except:
raise ValueError(
f"Cannot convert {self.__class__.__name__} to numpy array")
[docs]
def plot(self, plot_par=False, **kwargs):
""" Plot the data as function or parameters. """
if plot_par:
kwargs["is_par"]=True
return self.geometry.plot(self.parameters, plot_par=plot_par, **kwargs)
else:
kwargs["is_par"]=False
return self.geometry.plot(self.funvals, **kwargs)