Beispiel #1
0
    def __getitem__(self, key):

        # First case : g[:] = RHS ... will be g << RHS
        if key == self._full_slice:
            return self

        # Only one argument. Must be a mesh point
        if not isinstance(key, tuple):
            assert isinstance(key, (MeshPoint, Idx))
            return self.data[key.linear_index if isinstance(key, MeshPoint
                                                            ) else self._mesh.
                             index_to_linear(key.idx)]

        # If all arguments are MeshPoint, we are slicing the mesh or evaluating
        if all(isinstance(x, (MeshPoint, Idx)) for x in key):
            assert len(
                key
            ) == self.rank, "wrong number of arguments in [ ]. Expected %s, got %s" % (
                self.rank, len(key))
            return self.data[tuple(
                x.linear_index if isinstance(x, MeshPoint
                                             ) else m.index_to_linear(x.idx)
                for x, m in itertools.izip(key, self._mesh._mlist))]

        # If any argument is a MeshPoint, we are slicing the mesh or evaluating
        elif any(isinstance(x, (MeshPoint, Idx)) for x in key):
            assert len(
                key
            ) == self.rank, "wrong number of arguments in [[ ]]. Expected %s, got %s" % (
                self.rank, len(key))
            assert all(
                isinstance(x, (MeshPoint, Idx, slice)) for x in key
            ), "Invalid accessor of Green function, please combine only MeshPoints, Idx and slice"
            assert self.rank > 1, "Internal error : impossible case"  # here all == any for one argument
            mlist = self._mesh._mlist
            for x in key:
                if isinstance(x, slice) and x != self._full_slice:
                    raise NotImplementedError, "Partial slice of the mesh not implemented"
            # slice the data
            k = [
                x.linear_index if isinstance(x, MeshPoint) else
                m.index_to_linear(x.idx) if isinstance(x, Idx) else x
                for x, m in itertools.izip(key, mlist)
            ] + self._target_rank * [slice(0, None)]
            dat = self._data[k]
            # list of the remaining lists
            mlist = [
                m for i, m in itertools.ifilter(
                    lambda tup_im: not isinstance(tup_im[0], (MeshPoint, Idx)),
                    itertools.izip(key, mlist))
            ]
            assert len(mlist) > 0, "Internal error"
            mesh = MeshProduct(*mlist) if len(mlist) > 1 else mlist[0]
            sing = None
            r = Gf(mesh=mesh, data=dat)
            r.__check_invariants()
            return r

        # In all other cases, we are slicing the target space
        else:
            assert self.target_rank == len(
                key), "wrong number of arguments. Expected %s, got %s" % (
                    self.target_rank, len(key))

            # Assume empty indices (scalar_valued)
            ind = GfIndices([])

            # String access: transform the key into a list integers
            if all(isinstance(x, str) for x in key):
                assert self._indices, "Got string indices, but I have no indices to convert them !"
                key_lst = [
                    self._indices.convert_index(s, i)
                    for i, s in enumerate(key)
                ]  # convert returns a slice of len 1

            # Slicing with ranges -> Adjust indices
            elif all(isinstance(x, slice) for x in key):
                key_lst = list(key)
                ind = GfIndices(
                    [v[k] for k, v in zip(key_lst, self._indices.data)])

            # Integer access
            elif all(isinstance(x, int) for x in key):
                key_lst = list(key)

            # Invalid Access
            else:
                raise NotImplementedError, "Partial slice of the target space not implemented"

            dat = self._data[self._rank * [slice(0, None)] + key_lst]
            r = Gf(mesh=self._mesh, data=dat, indices=ind)

            r.__check_invariants()
            return r
Beispiel #2
0
class Gf(object):
    """
    Green function class

    Parameters
    ----------
    mesh: MeshXXX
          One of the meshes of the module 'meshes'
          The mesh of the Green function

    data: numpy.array, optional
          The data of the Gf.
          Must be of dimension mesh.rank + target_rank.
          Incompatible with target_shape

    target_shape: list of int, optional
                  Shape of the target space.
                  Incompatible with data

    is_real: bool
             Is the Green function real valued ?
             If true, and target_shape is set, the data will be real.
             Incompatible with data

    indices: GfIndices or list of str or list of list of str, Optional
             Optional string indices for the target space, to allow e.g g['eg', 'eg']
             list of list of str: the list of indices for each dimension.
             list of str: all indices are assumed to be the same for all dimensions.
   
    name: str 
          The name of the Green function. For plotting.

    NB : One of target_shape, data and indices must be set, and the other must be None.
    """
    __metaclass__ = AddMethod

    _hdf5_data_scheme_ = 'Gf'

    def __init__(self, **kw):  # enforce keyword only policy

        #print "Gf construct args", kw

        def delegate(self,
                     mesh,
                     data=None,
                     target_shape=None,
                     indices=None,
                     name='',
                     is_real=False):
            """
            target_shape and data  : must provide exactly one of them
            """
            # FIXME ? name is deprecated
            #if name:
            #    warnings.warn("constructor parameter 'name' is deprecated in gf constructor.\n It is only used in plots.\n Pass the name to the oplot function directly")
            self.name = name

            # input check
            assert (target_shape is None) or (
                data is None), "data and target_shape : one must be None"
            assert (data is None) or (
                is_real is
                False), "is_real can not be True is data is not None"
            if target_shape:
                for i in target_shape:
                    assert i > 0, "Target shape elements must be >0"

            # mesh
            assert isinstance(
                mesh, all_meshes
            ), "Mesh is unknown. Possible type of meshes are %s" % ', '.join(
                map(lambda m: m.__name__, all_meshes))
            self._mesh = mesh

            # indices
            # if indices is not a list of list, but a list, then the target_rank is assumed to be 2 !
            # backward compatibility only, it is not very logical (what about vector_valued gf ???)
            assert isinstance(
                indices, (type(None), list, GfIndices)
            ), "Type of indices incorrect : should be None, Gfindices, list of str, or list of list of str"
            if isinstance(indices, list):
                if not isinstance(indices[0], list):
                    indices = [indices, indices]
                # indices : transform indices into string
                indices = [[str(x) for x in v] for v in indices]
                indices = GfIndices(indices)
            self._indices = indices  # now indices are None or Gfindices

            # data
            if data is None:
                # if no data, we get the target_shape. If necessary, we find it from of the list of indices
                if target_shape is None:
                    assert indices, "Without data, target_shape, I need the indices to compute the shape !"
                    target_shape = [len(x) for x in indices.data]
                # we now allocate the data
                l = mesh.size_of_components() if isinstance(
                    mesh, MeshProduct) else [len(mesh)]
                data = np.zeros(list(l) + list(target_shape),
                                dtype=np.float64 if is_real else np.complex128)
            # Now we have the data at correct size. Set up a few short cuts
            self._data = data
            len_data_shape = len(self._data.shape)
            self._target_rank = len_data_shape - (
                self._mesh.rank if isinstance(mesh, MeshProduct) else 1)
            self._rank = len_data_shape - self._target_rank
            assert self._rank >= 0

            # target_shape. Ensure it is correct in any case.
            assert target_shape is None or tuple(
                target_shape) == self._data.shape[self._rank:]  # Debug only
            self._target_shape = self._data.shape[self._rank:]

            # If no indices was given, build the default ones
            if self._indices is None:
                self._indices = GfIndices([
                    list(str(i) for i in range(n)) for n in self._target_shape
                ])

            # Check that indices  have the right size
            if self._indices is not None:
                d, i = self._data.shape[self._rank:], tuple(
                    len(x) for x in self._indices.data)
                assert (
                    d == i
                ), "Indices are of incorrect size. Data size is %s while indices size is %s" % (
                    d, i)
            # Now indices are set, and are always a GfIndices object, with the
            # correct size

            # NB : at this stage, enough checks should have been made in Python in order for the C++ view
            # to be constructed without any INTERNAL exceptions.
            # Set up the C proxy for call operator for speed. The name has to
            # agree with the wrapped_aux module, it is of only internal use
            s = '_x_'.join(
                m.__class__.__name__[4:]
                for m in self.mesh._mlist) if isinstance(
                    mesh, MeshProduct) else self._mesh.__class__.__name__[4:]
            proxyname = 'CallProxy%s_%s%s' % (s, self.target_rank, '_R' if
                                              data.dtype == np.float64 else '')
            try:
                self._c_proxy = all_call_proxies.get(proxyname,
                                                     CallProxyNone)(self)
            except:
                self._c_proxy = None

            # check all invariants. Debug.
            self.__check_invariants()

        delegate(self, **kw)

    def __check_invariants(self):
        """Check various invariant. Mainly for debug"""
        # rank
        assert self.rank == self._mesh.rank if isinstance(
            self._mesh, MeshProduct) else 1
        # The mesh size must correspond to the size of the data
        assert self._data.shape[:self._rank] == tuple(
            len(m) for m in self._mesh.components) if isinstance(
                self._mesh, MeshProduct) else (len(self._mesh), )

    @property
    def rank(self):
        """Number of variable"""
        return self._rank

    @property
    def target_rank(self):
        """Dimension of the target shape"""
        return self._target_rank

    @property
    def target_shape(self):
        """Shape of the target_space"""
        return self._target_shape

    @property
    def mesh(self):
        """The mesh"""
        return self._mesh

    @property
    def data(self):
        """
           The data array, as a numpy array.
           Storage convention is self.data[x,y,z, ..., n0,n1,n2] 
           where x,y,z correspond to the variables (the mesh) and 
           n0, n1, n2 to the target_space
        """
        return self._data

    @property
    def indices(self):
        """
        Access to the indices
        """
        return self._indices

    def copy(self):
        """
        Deep copy of the Green function
        """
        return Gf(mesh=self._mesh.copy(),
                  data=self._data.copy(),
                  indices=self._indices.copy(),
                  name=self.name)

    def copy_from(self, another):
        """
        Copy the data of another into self.
        """
        self._mesh.copy_from(another.mesh)
        assert self._data.shape == another._data.shape, "Shapes are incompatible: " + str(
            self._data.shape) + " vs " + str(another._data.shape)
        self._data[:] = another._data[:]
        self._indices = another._indices.copy()
        self.__check_invariants()

    def __repr__(self):
        return "Green Function %s with mesh %s and target_rank %s: \n" % (
            self.name, self.mesh, self.target_rank)

    def __str__(self):
        return self.name if self.name else repr(self)

    #--------------  Bracket operator []  -------------------------

    _full_slice = slice(None, None, None)

    def __getitem__(self, key):

        # First case : g[:] = RHS ... will be g << RHS
        if key == self._full_slice:
            return self

        # Only one argument. Must be a mesh point
        if not isinstance(key, tuple):
            assert isinstance(key, (MeshPoint, Idx))
            return self.data[key.linear_index if isinstance(key, MeshPoint
                                                            ) else self._mesh.
                             index_to_linear(key.idx)]

        # If all arguments are MeshPoint, we are slicing the mesh or evaluating
        if all(isinstance(x, (MeshPoint, Idx)) for x in key):
            assert len(
                key
            ) == self.rank, "wrong number of arguments in [ ]. Expected %s, got %s" % (
                self.rank, len(key))
            return self.data[tuple(
                x.linear_index if isinstance(x, MeshPoint
                                             ) else m.index_to_linear(x.idx)
                for x, m in itertools.izip(key, self._mesh._mlist))]

        # If any argument is a MeshPoint, we are slicing the mesh or evaluating
        elif any(isinstance(x, (MeshPoint, Idx)) for x in key):
            assert len(
                key
            ) == self.rank, "wrong number of arguments in [[ ]]. Expected %s, got %s" % (
                self.rank, len(key))
            assert all(
                isinstance(x, (MeshPoint, Idx, slice)) for x in key
            ), "Invalid accessor of Green function, please combine only MeshPoints, Idx and slice"
            assert self.rank > 1, "Internal error : impossible case"  # here all == any for one argument
            mlist = self._mesh._mlist
            for x in key:
                if isinstance(x, slice) and x != self._full_slice:
                    raise NotImplementedError, "Partial slice of the mesh not implemented"
            # slice the data
            k = [
                x.linear_index if isinstance(x, MeshPoint) else
                m.index_to_linear(x.idx) if isinstance(x, Idx) else x
                for x, m in itertools.izip(key, mlist)
            ] + self._target_rank * [slice(0, None)]
            dat = self._data[k]
            # list of the remaining lists
            mlist = [
                m for i, m in itertools.ifilter(
                    lambda tup_im: not isinstance(tup_im[0], (MeshPoint, Idx)),
                    itertools.izip(key, mlist))
            ]
            assert len(mlist) > 0, "Internal error"
            mesh = MeshProduct(*mlist) if len(mlist) > 1 else mlist[0]
            sing = None
            r = Gf(mesh=mesh, data=dat)
            r.__check_invariants()
            return r

        # In all other cases, we are slicing the target space
        else:
            assert self.target_rank == len(
                key), "wrong number of arguments. Expected %s, got %s" % (
                    self.target_rank, len(key))

            # Assume empty indices (scalar_valued)
            ind = GfIndices([])

            # String access: transform the key into a list integers
            if all(isinstance(x, str) for x in key):
                assert self._indices, "Got string indices, but I have no indices to convert them !"
                key_lst = [
                    self._indices.convert_index(s, i)
                    for i, s in enumerate(key)
                ]  # convert returns a slice of len 1

            # Slicing with ranges -> Adjust indices
            elif all(isinstance(x, slice) for x in key):
                key_lst = list(key)
                ind = GfIndices(
                    [v[k] for k, v in zip(key_lst, self._indices.data)])

            # Integer access
            elif all(isinstance(x, int) for x in key):
                key_lst = list(key)

            # Invalid Access
            else:
                raise NotImplementedError, "Partial slice of the target space not implemented"

            dat = self._data[self._rank * [slice(0, None)] + key_lst]
            r = Gf(mesh=self._mesh, data=dat, indices=ind)

            r.__check_invariants()
            return r

    def __setitem__(self, key, val):

        # Only one argument. Must be a mesh point
        if not isinstance(key, tuple):
            assert isinstance(key, (MeshPoint, Idx))
            self.data[key.linear_index if isinstance(key, MeshPoint) else self.
                      _mesh.index_to_linear(key.idx)] = val

        # If all arguments are MeshPoint, we are slicing the mesh or evaluating
        elif all(isinstance(x, (MeshPoint, Idx)) for x in key):
            assert len(
                key
            ) == self.rank, "wrong number of arguments in [ ]. Expected %s, got %s" % (
                self.rank, len(key))
            self.data[tuple(
                x.linear_index if isinstance(x, MeshPoint
                                             ) else m.index_to_linear(x.idx)
                for x, m in itertools.izip(key, self._mesh._mlist))] = val

        else:
            self[key] << val

    # -------------- Various operations -------------------------------------

    @property
    def real(self):
        """A Gf with only the real part of data."""
        return Gf(mesh=self._mesh,
                  data=self._data.real,
                  name=("Re " + self.name) if self.name else '')

    @property
    def imag(self):
        """A Gf with only the imag part of data."""
        return Gf(mesh=self._mesh,
                  data=self._data.imag,
                  name=("Im " + self.name) if self.name else '')

    # --------------  Lazy system -------------------------------------

    def __lazy_expr_eval_context__(self):
        return LazyCTX(self)

    def __lshift__(self, A):
        """ A can be two things:
          * G << any_init will init the GFBloc with the initializer
          * G << g2 where g2 is a GFBloc will copy g2 into self
        """
        if isinstance(A, Gf):
            if self is not A:
                self.copy_from(
                    A)  # otherwise it is useless AND does not work !!
        elif isinstance(
                A, lazy_expressions.LazyExpr
        ):  # A is a lazy_expression made of GF, scalars, descriptors
            A2 = descriptors.convert_scalar_to_const(A)

            def e_t(x):
                if not isinstance(x, descriptors.Base): return x
                tmp = self.copy()
                x(tmp)
                return tmp

            self.copy_from(lazy_expressions.eval_expr_with_context(e_t, A2))
        elif isinstance(A, lazy_expressions.LazyExprTerminal
                        ):  #e.g. g<< SemiCircular (...)
            self << lazy_expressions.LazyExpr(A)
        elif descriptors.is_scalar(A):  #in the case it is a scalar ....
            self << lazy_expressions.LazyExpr(A)
        else:
            raise NotImplemented
        return self

    # -------------- call -------------------------------------

    def __call__(self, *args):
        assert self._c_proxy, " no proxy"
        return self._c_proxy(*args)

    # -------------- Various operations -------------------------------------

    def __le__(self, other):
        raise RuntimeError, " Operator <= not defined "

    def __ilshift__(self, A):
        warnings.warn(
            "The operator <<= is deprecated : update your code to use << instead",
            UserWarning,
            stacklevel=2)
        return self << A

    # ---------- Addition

    def __iadd__(self, arg):
        if descriptor_base.is_lazy(arg):
            return lazy_expressions.make_lazy(self) + arg
        if isinstance(arg, Gf):
            assert type(self.mesh) == type(
                arg.mesh), "Can not add two Gf with meshes of different type"
            assert self.mesh == arg.mesh, "Can not add two Gf with different mesh"
            self._data += arg._data
        else:
            if self._target_rank != 2 and not isinstance(arg, np.ndarray):
                self._data[:] += arg
            elif self._target_rank == 2:
                wrapped_aux._iadd_g_matrix_scalar(self, arg)
            else:
                raise NotImplemented
        return self

    def __add__(self, y):
        c = self.copy()
        c += y
        return c

    def __radd__(self, y):
        return self.__add__(y)

    # ---------- Substraction

    def __isub__(self, arg):
        if descriptor_base.is_lazy(arg):
            return lazy_expressions.make_lazy(self) - arg
        if isinstance(arg, Gf):
            assert type(self.mesh) == type(
                arg.mesh
            ), "Can not subtract two Gf with meshes of different type"
            assert self.mesh == arg.mesh, "Can not subtract two Gf with different mesh"
            self._data -= arg._data
        else:
            if self._target_rank != 2 and not isinstance(arg, np.ndarray):
                self._data[:] -= arg
            elif self._target_rank == 2:
                wrapped_aux._isub_g_matrix_scalar(self, arg)
            else:
                raise NotImplemented
        return self

    def __sub__(self, y):
        c = self.copy()
        c -= y
        return c

    def __rsub__(self, y):
        c = (-1) * self.copy()
        c += y
        return c

    # ---------- Multiplication
    # Naive implementation of G1 *= G2 without checks
    def __imul__impl(self, arg):  # need to separate for the ImTime case

        # reshaping the data. Smash the mesh indices into one
        rh = lambda d: np.reshape(d, (reduce(mul, d.shape[:self.rank]), ) +
                                  (d.shape[self.rank:]))
        d_self = rh(self.data)
        d_args = rh(arg.data)
        if self.target_rank == 2:
            for n in range(d_self.shape[0]):
                d_self[n] = np.dot(d_self[n],
                                   d_args[n])  # put to C if too slow.
        else:
            d_self *= d_args  # put to C if too slow.

    def __imul__(self, arg):
        if descriptor_base.is_lazy(arg):
            return lazy_expressions.make_lazy(self) * arg
        # If arg is a Gf
        if isinstance(arg, Gf):
            assert type(self.mesh) == type(
                arg.mesh
            ), "Can not multiply two Gf with meshes of different type"
            assert self.mesh == arg.mesh, "Can not use in-place multiplication for two Gf with different mesh"
            self.__imul__impl(arg)
        elif isinstance(arg, numbers.Number):
            self._data[:] *= arg
        elif isinstance(arg, np.ndarray):
            assert len(
                arg.shape) == 2, "Multiplication only supported for matrices"
            assert len(
                self.target_shape
            ) == 2, "Multiplication only supported for matrix_valued Gfs"
            self.data[:] = np.dot(self.data, arg)
        else:
            assert False, "Invalid operand type for Gf in-place multiplication"
        return self

    @staticmethod
    def _combine_mesh_mul(l, r):
        """ Apply the Fermion/Boson rules for ImTime mesh, and recursively for MeshProduct"""
        assert type(l) == type(
            r), "Can not multiply two Gf with meshes of different type"

        if type(l) is MeshProduct:
            return MeshProduct(*[
                Gf._combine_mesh_mul(l, r)
                for (l, r) in zip(l.components, r.components)
            ])

        if not type(l) is meshes.MeshImTime:  #regular case
            assert l == r, "Can not multiply two Gf with different mesh"
            return l.copy()
        else:
            assert abs(l.beta - r.beta) < 1.e-15 and len(l) == len(
                r), "Can not multiply two Gf with different mesh"
            return meshes.MeshImTime(
                l.beta, 'Boson' if l.statistic == r.statistic else 'Fermion',
                len(l))

    def __mul__(self, y):
        if isinstance(y, Gf):
            # make a copy, but special treatment of the mesh in the Imtime case.
            c = Gf(mesh=Gf._combine_mesh_mul(self._mesh, y.mesh),
                   data=self._data.copy(),
                   indices=self._indices.copy(),
                   name=self.name)
            c.__imul__impl(y)
        elif isinstance(y, (numbers.Number, np.ndarray)):
            c = self.copy()
            c *= y
        else:
            assert False, "Invalid operand type for Gf multiplication"
        return c

    def __rmul__(self, y):
        c = self.copy()
        if isinstance(y, np.ndarray):
            assert len(
                y.shape) == 2, "Multiplication only supported for matrices"
            assert len(
                self.target_shape
            ) == 2, "Multiplication only supported for matrix_valued Gfs"
            c.data[:] = np.tensordot(y, self.data, axes=([-1], [-2]))
        elif isinstance(y, numbers.Number):
            c *= y
        else:
            assert False, "Invalid operand type for Gf multiplication"
        return c

    # ---------- Division
    def __idiv__(self, arg):
        if descriptor_base.is_lazy(arg):
            return lazy_expressions.make_lazy(self) / arg
        self._data[:] /= arg
        return self

    def __div__(self, y):
        c = self.copy()
        c /= y
        return c

    # ---------- unary -
    def __neg__(self):
        c = self.copy()
        c *= -1
        return c

#----------------------------- other operations -----------------------------------

    def invert(self):
        if self.target_rank == 0:
            self.data[:] = 1. / self.data
            return
        """Inverts this Gf in place, in a matrix sense"""
        assert self.target_rank == 2, "Inversion only makes sense for matrix or scalar_valued Gf"
        d = self.data.view(
        )  # Cf https://docs.scipy.org/doc/numpy/reference/generated/numpy.reshape.html
        d.shape = (np.prod(
            d.shape[:-2]), ) + d.shape[-2:]  # reshaped view, guarantee no copy
        wrapped_aux._gf_invert_data_in_place(d)

    def inverse(self):
        """Returns a new Gf, inverse of self."""
        r = self.copy()
        r.invert()
        return r

    def transpose(self):
        """ Returns a NEW gf, with transposed data, i.e. it is NOT a transposed view."""
        # FIXME Why this assert ?
        #assert any( (isinstance(self.mesh, x) for x in [meshes.MeshImFreq, meshes.MeshReFreq])), "Method invalid for this Gf"
        d = np.transpose(self.data.copy(), (0, 2, 1))
        return Gf(mesh=self.mesh, data=d, indices=self.indices.transpose())

    def conjugate(self):
        """
        Returns a new functions, with the conjugate.
        """
        return Gf(mesh=self.mesh,
                  data=np.conj(self.data),
                  indices=self.indices)

    def zero(self):
        """Put self to 0"""
        self._data[:] = 0

    def from_L_G_R(self, L, G, R):
        """self[:] =  l * g * r"""
        assert self.target_rank == 2, "Function only makes sense for matrix valued Gf"
        assert self.rank == 1, "Not implemented for more than one var"  # A little generalization needed in C++ ?
        wrapped_aux.set_from_gf_data_mul_LR(self.data, L, G.data, R)

    def total_density(self, *args, **kwargs):
        """Total density"""
        return np.trace(gf_fnt.density(self, *args, **kwargs))

    #-----------------------------  IO  -----------------------------------

    def __reduce__(self):
        return call_factory_from_dict, (Gf, self.name,
                                        self.__reduce_to_dict__())

    def __reduce_to_dict__(self):
        d = {'mesh': self._mesh, 'data': self._data}
        if self.indices: d['indices'] = self.indices
        return d

    @classmethod
    def __factory_from_dict__(cls, name, d):
        # Backward compatibility layer
        # Drop singularity from the element and ignore it
        d.pop('singularity', None)
        #
        r = cls(name=name, **d)
        # Backward compatibility layer
        # In the case of an ImFreq function, old archives did store only the >0
        # frequencies, we need to duplicate it for negative freq.
        # Same code as in the C++ h5_read for gf.
        need_unfold = isinstance(r.mesh,
                                 meshes.MeshImFreq) and r.mesh.positive_only()
        return r if not need_unfold else wrapped_aux._make_gf_from_real_gf(r)

    #-----------------------------plot protocol -----------------------------------

    def _plot_(self, opt_dict):
        """ Implement the plot protocol"""
        return plot.dispatcher(self)(self, opt_dict)

    def x_data_view(self, x_window=None, flatten_y=False):
        """
        :param x_window: the window of x variable (omega/omega_n/t/tau) for which data is requested
                          if None, take the full window
        :param flatten_y: If the Green function is of size (1, 1) flatten the array as a 1d array
        :rtype: a tuple (X, data) where
                 * X is a 1d numpy of the x variable inside the window requested
                 * data is a 3d numpy array of dim (:,:, len(X)), the corresponding slice of data
                   If flatten_y is True and dim is (1, 1, *), returns a 1d numpy
        """
        X = [x.imag for x in self.mesh] if isinstance(
            self.mesh, meshes.MeshImFreq) else [x for x in self.mesh]
        X, data = np.array(X), self.data
        if x_window:
            # the slice due to clip option x_window
            sl = clip_array(X, *x_window) if x_window else slice(len(X))
            X, data = X[sl], data[sl, :, :]
        if flatten_y and data.shape[1:3] == (1, 1):
            data = data[:, 0, 0]
        return X, data

    #-------------- Deprecated. ---------------------------
    @property
    def beta(self):
        warnings.warn(
            "g.beta is deprecated and not generic. Use g.mesh.beta instead")
        return self.mesh.beta

    @property
    def statistic(self):
        warnings.warn(
            "g.statistic is deprecated and not generic. Use g.mesh.statistic instead"
        )
        return self.mesh.statistic

    #-------------- Deprecated. NB works only in 1 var, matrix_valued anyway  ---------------------------
    @property
    def N1(self):
        assert self.target_rank == 2, "N1 only makes sense for rank 2 targets"
        warnings.warn(
            "g.N1 is deprecated and not generic. Use g.target_shape[0] instead"
        )
        return self.target_shape[0]

    @property
    def N2(self):
        assert self.target_rank == 2, "N2 only makes sense for rank 2 targets"
        warnings.warn(
            "g.N2 is deprecated and not generic. Use g.target_shape[1] instead"
        )
        return self.target_shape[1]

    @property
    def indicesL(self):
        warnings.warn("g.indicesL is deprecated. Use g.indices[0] instead")
        return self.indices.data[0]

    @property
    def indicesR(self):
        warnings.warn("g.indicesR is deprecated. Use g.indices[1] instead")
        return self.indices.data[1]
Beispiel #3
0
        def delegate(self,
                     mesh,
                     data=None,
                     target_shape=None,
                     indices=None,
                     name='',
                     is_real=False):
            """
            target_shape and data  : must provide exactly one of them
            """
            # FIXME ? name is deprecated
            #if name:
            #    warnings.warn("constructor parameter 'name' is deprecated in gf constructor.\n It is only used in plots.\n Pass the name to the oplot function directly")
            self.name = name

            # input check
            assert (target_shape is None) or (
                data is None), "data and target_shape : one must be None"
            assert (data is None) or (
                is_real is
                False), "is_real can not be True is data is not None"
            if target_shape:
                for i in target_shape:
                    assert i > 0, "Target shape elements must be >0"

            # mesh
            assert isinstance(
                mesh, all_meshes
            ), "Mesh is unknown. Possible type of meshes are %s" % ', '.join(
                map(lambda m: m.__name__, all_meshes))
            self._mesh = mesh

            # indices
            # if indices is not a list of list, but a list, then the target_rank is assumed to be 2 !
            # backward compatibility only, it is not very logical (what about vector_valued gf ???)
            assert isinstance(
                indices, (type(None), list, GfIndices)
            ), "Type of indices incorrect : should be None, Gfindices, list of str, or list of list of str"
            if isinstance(indices, list):
                if not isinstance(indices[0], list):
                    indices = [indices, indices]
                # indices : transform indices into string
                indices = [[str(x) for x in v] for v in indices]
                indices = GfIndices(indices)
            self._indices = indices  # now indices are None or Gfindices

            # data
            if data is None:
                # if no data, we get the target_shape. If necessary, we find it from of the list of indices
                if target_shape is None:
                    assert indices, "Without data, target_shape, I need the indices to compute the shape !"
                    target_shape = [len(x) for x in indices.data]
                # we now allocate the data
                l = mesh.size_of_components() if isinstance(
                    mesh, MeshProduct) else [len(mesh)]
                data = np.zeros(list(l) + list(target_shape),
                                dtype=np.float64 if is_real else np.complex128)
            # Now we have the data at correct size. Set up a few short cuts
            self._data = data
            len_data_shape = len(self._data.shape)
            self._target_rank = len_data_shape - (
                self._mesh.rank if isinstance(mesh, MeshProduct) else 1)
            self._rank = len_data_shape - self._target_rank
            assert self._rank >= 0

            # target_shape. Ensure it is correct in any case.
            assert target_shape is None or tuple(
                target_shape) == self._data.shape[self._rank:]  # Debug only
            self._target_shape = self._data.shape[self._rank:]

            # If no indices was given, build the default ones
            if self._indices is None:
                self._indices = GfIndices([
                    list(str(i) for i in range(n)) for n in self._target_shape
                ])

            # Check that indices  have the right size
            if self._indices is not None:
                d, i = self._data.shape[self._rank:], tuple(
                    len(x) for x in self._indices.data)
                assert (
                    d == i
                ), "Indices are of incorrect size. Data size is %s while indices size is %s" % (
                    d, i)
            # Now indices are set, and are always a GfIndices object, with the
            # correct size

            # NB : at this stage, enough checks should have been made in Python in order for the C++ view
            # to be constructed without any INTERNAL exceptions.
            # Set up the C proxy for call operator for speed. The name has to
            # agree with the wrapped_aux module, it is of only internal use
            s = '_x_'.join(
                m.__class__.__name__[4:]
                for m in self.mesh._mlist) if isinstance(
                    mesh, MeshProduct) else self._mesh.__class__.__name__[4:]
            proxyname = 'CallProxy%s_%s%s' % (s, self.target_rank, '_R' if
                                              data.dtype == np.float64 else '')
            try:
                self._c_proxy = all_call_proxies.get(proxyname,
                                                     CallProxyNone)(self)
            except:
                self._c_proxy = None

            # check all invariants. Debug.
            self.__check_invariants()