コード例 #1
0
    def with_subranges(self, *subranges):
        """ Basically the same thing as calling `add_subrange()` multiple times, except returns `self` instead of
        the subrange, allowing for a different syntax (see below)

        :Examples:

        >>> IndexRange.reset_ranges()
        >>> orb = DeclareIndexRange('p,q,r,s', 10, name="Orbital space").with_subranges(
        ...           DeclareIndexRange('i,j,k,l', 0, 3, name="Occupied space").with_subranges(
        ...               DeclareIndexRange("i*,j*,k*,l*", 0, 1, name="Core"),
        ...               DeclareIndexRange("i',j',k',l'", 1, 3)
        ...           ),
        ...           DeclareIndexRange('a,b,c,d', 3, 10, name="Virtual space")
        ...       )
        >>> orb
        <IndexRange named 'Orbital space' represented by indices ['p', 'q', 'r', 's']>
        >>> len(orb.subranges)
        2
        >>> len(orb.subranges[0].subranges)
        2

        """
        for subrange in listify_args(subranges):
            self.add_subrange(subrange)
            # TODO raise an error if subrange's index_range_set is set to something other than the same thing as ours
        return self
コード例 #2
0
ファイル: einsum_indices.py プロジェクト: spring01/libPSI
    def with_subranges(self, *subranges):
        """ Basically the same thing as calling `add_subrange()` multiple times, except returns `self` instead of
        the subrange, allowing for a different syntax (see below)

        :Examples:

        >>> IndexRange.reset_ranges()
        >>> orb = DeclareIndexRange('p,q,r,s', 10, name="Orbital space").with_subranges(
        ...           DeclareIndexRange('i,j,k,l', 0, 3, name="Occupied space").with_subranges(
        ...               DeclareIndexRange("i*,j*,k*,l*", 0, 1, name="Core"),
        ...               DeclareIndexRange("i',j',k',l'", 1, 3)
        ...           ),
        ...           DeclareIndexRange('a,b,c,d', 3, 10, name="Virtual space")
        ...       )
        >>> orb
        <IndexRange named 'Orbital space' represented by indices ['p', 'q', 'r', 's']>
        >>> len(orb.subranges)
        2
        >>> len(orb.subranges[0].subranges)
        2

        """
        for subrange in listify_args(subranges):
            self.add_subrange(subrange)
            # TODO raise an error if subrange's index_range_set is set to something other than the same thing as ours
        return self
コード例 #3
0
ファイル: legacy_xml.py プロジェクト: SahanGH/psi4public
 def __init__(self, comparison_representation, *files):
     self.started = True
     self._files = listify_args(*files)
     self.properties = MoleculeDict(comparison_representation, default=lambda: [])
     self.properties_for_molecules = defaultdict(lambda: [])
     for file in files:
         self._parse_file(file)
コード例 #4
0
ファイル: legacy_xml.py プロジェクト: xwang862/psi4
 def __init__(self, comparison_representation, *files):
     self.started = True
     self._files = listify_args(*files)
     self.properties = MoleculeDict(comparison_representation,
                                    default=lambda: [])
     self.properties_for_molecules = defaultdict(lambda: [])
     for file in files:
         self._parse_file(file)
コード例 #5
0
 def available_pairs(self, *keys):
     for key in listify_args(keys):
         if key in self:
             value = self[key]
             if isinstance(value, Keyword):
                 if value.value is not None:
                     yield key, str(value.value)
                 else:
                     yield key, value._name
             else:
                 yield key, str(value)
コード例 #6
0
ファイル: einsum_indices.py プロジェクト: spring01/libPSI
    def __class_getitem__(cls, args):
        """
        When given multiple arguments, this functions as a serogate constructor, allowing Ellipsis literals and
        slice literals to be given.

        """
        items = listify_args(args)
        if len(items) == 3 and isinstance(items[2], basestring):
            name = items.pop()
            return IndexRange(*items, name=name)
        else:
            return IndexRange(*items)
コード例 #7
0
    def __class_getitem__(cls, args):
        """
        When given multiple arguments, this functions as a serogate constructor, allowing Ellipsis literals and
        slice literals to be given.

        """
        items = listify_args(args)
        if len(items) == 3 and isinstance(items[2], basestring):
            name = items.pop()
            return IndexRange(*items, name=name)
        else:
            return IndexRange(*items)
コード例 #8
0
ファイル: metaprogramming.py プロジェクト: SahanGH/psi4public
 def __attr_init__(self, types, strong, type_error_text):
     self.types = tuple(listify_args(types))
     if type_error_text is None:
         self.type_error_text = "Attribute '{name}'".format(name=self.__name__)
         self.type_error_text += " in class '{cls}' "
         if isinstance(types, Iterable):
             second_part = "must be an instance of one of the following: ('{types}');".format(types="', '".join(map(classname, types)))
         else:
             second_part = "must be an instance of '{types}'".format(types=classname(types))
         self.type_error_text += second_part + " (got '{got}')"
     else:
         self.type_error_text = type_error_text
     self.strong = strong
コード例 #9
0
ファイル: metaprogramming.py プロジェクト: xwang862/psi4
 def __attr_init__(self, types, strong, type_error_text):
     self.types = tuple(listify_args(types))
     if type_error_text is None:
         self.type_error_text = "Attribute '{name}'".format(
             name=self.__name__)
         self.type_error_text += " in class '{cls}' "
         if isinstance(types, Iterable):
             second_part = "must be an instance of one of the following: ('{types}');".format(
                 types="', '".join(map(classname, types)))
         else:
             second_part = "must be an instance of '{types}'".format(
                 types=classname(types))
         self.type_error_text += second_part + " (got '{got}')"
     else:
         self.type_error_text = type_error_text
     self.strong = strong
コード例 #10
0
ファイル: exceptions.py プロジェクト: xwang862/psi4
 def __new__(cls, argname, arg, *allowed_types, **kwargs):
     allowed = listify_args(allowed_types)
     my_caller = get_kwarg(kwargs, 'caller') or (caller() + '()')
     if len(allowed) == 1:
         return TypeError('Argument {0} to {1} must be {2} (got {3})'.format(
             argname,
             my_caller,
             classname(allowed[0]),
             type(arg).__name__
         ))
     else:
         return TypeError("Argument {0} to {1} must be one of ({2}) (got {3})".format(
             argname,
             my_caller,
             ', '.join(classname(a) for a in allowed),
             type(arg).__name__
         ))
コード例 #11
0
ファイル: tensor.py プロジェクト: guoyang0123/psi4release
 def remove_phase_factor(*args, **kwargs):
     """ Given any number of `Tensor` objects that are the same up to a phase factor,
     return a list of `Tensor` objects that have been.  Copies are only made if
     necessary.  The chosen phase is the one that makes the first non-zero element
     (in the `numpy.nditer(tensor)` iterator, using the `cutoff` keyword argument
     or Tensor.zero_cutoff if one is not given) positive.
     """
     cutoff = kwargs.pop('cutoff', Tensor.same_tensor_cutoff)
     force_list = kwargs.pop('force_list', False)
     args = listify_args(*args, ignore=np.ndarray)
     if len(args) == 0:
         return []
     if sanity_checking_enabled:
         if not args[0].same_upto_phase_factor(*args[1:], **
                                               {'cutoff': cutoff}):
             raise ValueError(
                 "can't align phases of tensors that are not the same to a phase factor"
             )
     it = np.nditer(args[0], flags=['multi_index'])
     idx = None
     for i in it:
         if abs(i) < Tensor.zero_cutoff:
             idx = it.multi_index
             break
     if idx is None:
         # it's the zero vector (and so are all of the rest, assuming sanity
         #   checking is enabled and/or the user is being safe)
         if len(args) == 1 and not force_list:
             return args[0]
         else:
             return args
     ret_val = []
     for arg in args:
         if arg[idx] < 0:
             ret_val.append(-1.0 * arg)
         else:
             ret_val.append(arg)
     if len(ret_val) == 1 and not force_list:
         return ret_val[0]
     else:
         return ret_val
コード例 #12
0
ファイル: tensor.py プロジェクト: keceli/psi4release
 def remove_phase_factor(*args, **kwargs):
     """ Given any number of `Tensor` objects that are the same up to a phase factor,
     return a list of `Tensor` objects that have been.  Copies are only made if
     necessary.  The chosen phase is the one that makes the first non-zero element
     (in the `numpy.nditer(tensor)` iterator, using the `cutoff` keyword argument
     or Tensor.zero_cutoff if one is not given) positive.
     """
     cutoff = kwargs.pop('cutoff', Tensor.same_tensor_cutoff)
     force_list = kwargs.pop('force_list', False)
     args = listify_args(*args, ignore=np.ndarray)
     if len(args) == 0:
         return []
     if sanity_checking_enabled:
         if not args[0].same_upto_phase_factor(*args[1:], **{'cutoff': cutoff}):
             raise ValueError("can't align phases of tensors that are not the same to a phase factor")
     it = np.nditer(args[0], flags=['multi_index'])
     idx = None
     for i in it:
         if abs(i) < Tensor.zero_cutoff:
             idx = it.multi_index
             break
     if idx is None:
         # it's the zero vector (and so are all of the rest, assuming sanity
         #   checking is enabled and/or the user is being safe)
         if len(args) == 1 and not force_list:
             return args[0]
         else:
             return args
     ret_val = []
     for arg in args:
         if arg[idx] < 0:
             ret_val.append(-1.0 * arg)
         else:
             ret_val.append(arg)
     if len(ret_val) == 1 and not force_list:
         return ret_val[0]
     else:
         return ret_val
コード例 #13
0
    def keywordify_if_available(self, format, *keys):
        """ Mostly for use by templates, this method returns a string of keyword-value pairs in using the given format
        for each argument in the argument list.
        `format` should use the str.format() protocol from the python standard library with the
        named slots `{key}` where the keyword name should go and `{value}` where the value of the
        detail should go (or, if the value of the detail is a `Keyword` object, the contents of the
        `value` attribute for that `Keyword`, or, if the `value` attribute for the keyword is not defined,
        the `_name` attribute for the `Keyword` object in question.

        Aliased as `keywordify`
        """
        ret_val = ""
        for key in listify_args(keys):
            if key in self:
                value = self[key]
                if isinstance(value, Keyword):
                    if value.value is not None:
                        ret_val += format.format(key, value.value) + "\n"
                    else:
                        ret_val += format.format(key, value._name) + "\n"
                else:
                    ret_val += format.format(key, value) + "\n"
        return ret_val
コード例 #14
0
ファイル: misc.py プロジェクト: SahanGH/psi4public
 def __class_getitem__(cls, args):
     return listify_args(args)
コード例 #15
0
ファイル: finite_difference.py プロジェクト: xwang862/psi4
 def __init__(self, function, *variables, **kwargs):
     """
     """
     if len(FiniteDifferenceDerivative.formulas) == 0:
         # Load the formulas generated "by hand", which (for now, anyway) require fewer
         #   displacements than the automatically generated formulas if we also need to
         #   compute the lower order derivatives as well, as is the case with the computation
         #   of quartic forcefields. (But not, for instance, the B tensor.  So the
         #   FiniteDifferenceDerivative constructor could be optimized to take a parameter
         #   which specifies whether we should choose the formula with the fewest overall
         #   displacements or the fewest "new" displacements not needed for smaller derivatives)
         load_formulas()
     #--------------------------------------------------------------------------------#
     # miscellanea
     self._target_robustness = kwargs.pop('target_robustness', 2)
     self._value_function = kwargs.pop('value_function', None)
     self._delta_function = kwargs.pop('delta_function', None)
     self._delta = kwargs.pop('delta', None)
     self._forward = kwargs.pop('forward', False)
     self._function = function
     #--------------------------------------------------------------------------------#
     # type checking
     if type_checking_enabled:
         if not all(isinstance(v, FiniteDifferenceVariable) for v in variables):
             raise TypeError
         if not isinstance(self.target_robustness, int):
             raise TypeError
     #--------------------------------------------------------------------------------#
     # Get the variables and the orders....
     vars = listify_args(*variables)
     # Determine which formula we need
     vars = sorted(vars, key=id)
     # This is nasty, but it works...The zip(*list_of_lists) effectively "unzips"
     self._orders, self._variables = zip(
         *sorted(
             [(len(list(g)), k) for k, g in groupby(vars)],
             reverse=True)
     )
     #--------------------------------------------------------------------------------#
     # Determine which formula to use
     # This gets reused, so define a quicky function...
     def get_possibilities(formula_list):
         return [f for f in formula_list
             if f.orders == list(self.orders)
                     and f.robustness >= self.target_robustness
                     and (f.is_forward() if self._forward else f.is_central())
         ]
     #----------------------------------------#
     # First, try and get a "hand-generated" formula
     possibilities = get_possibilities(FiniteDifferenceDerivative.formulas)
     if len(possibilities) == 0:
         # We know how to generate single variable formulas to arbitrary order, so let's do it
         n_derivative_vars = len(self.orders)
         derivative_order = sum(self.orders)
         if n_derivative_vars == 1:
             # This long name is unweildy...
             gen_dict = FiniteDifferenceDerivative.generated_single_variable_formulas
             # See if we've already generated it...
             formula = gen_dict.get(
                 (
                     derivative_order,
                     self.target_robustness
                         + (1 if not self._forward and self.target_robustness % 2 == 1 else 0),
                     self._forward
                 ),
                 None)
             if formula is None:
                 # okay, we can generate it.
                 generate_single_variable_formulas(
                     derivative_order,
                     self.target_robustness
                         + (1 if not self._forward and self.target_robustness % 2 == 1 else 0),
                     self._forward)
                 formula = gen_dict[(
                     derivative_order,
                     self.target_robustness
                         + (1 if not self._forward and self.target_robustness % 2 == 1 else 0),
                     self._forward)]
             possibilities.append(formula)
             if sanity_checking_enabled:
                 possibilities = get_possibilities(possibilities)
         else:
             # we don't know how to generate these...yet...but I'm working on it!
             raise RuntimeError("Can't find formula for orders {0} and"
                                " robustness {1}".format(
                 self.orders, self.target_robustness))
     # Use the minimum robustness for now.  Later we can make it use
     #   the best possible without additional calculations.
     self._formula = sorted(possibilities, key=attrgetter('robustness'))[0]
コード例 #16
0
    def __init__(self, function, *variables, **kwargs):
        """
        """
        if len(FiniteDifferenceDerivative.formulas) == 0:
            # Load the formulas generated "by hand", which (for now, anyway) require fewer
            #   displacements than the automatically generated formulas if we also need to
            #   compute the lower order derivatives as well, as is the case with the computation
            #   of quartic forcefields. (But not, for instance, the B tensor.  So the
            #   FiniteDifferenceDerivative constructor could be optimized to take a parameter
            #   which specifies whether we should choose the formula with the fewest overall
            #   displacements or the fewest "new" displacements not needed for smaller derivatives)
            load_formulas()
        # --------------------------------------------------------------------------------#
        # miscellanea
        self._target_robustness = kwargs.pop("target_robustness", 2)
        self._value_function = kwargs.pop("value_function", None)
        self._delta_function = kwargs.pop("delta_function", None)
        self._delta = kwargs.pop("delta", None)
        self._forward = kwargs.pop("forward", False)
        self._function = function
        # --------------------------------------------------------------------------------#
        # type checking
        if type_checking_enabled:
            if not all(isinstance(v, FiniteDifferenceVariable) for v in variables):
                raise TypeError
            if not isinstance(self.target_robustness, int):
                raise TypeError
        # --------------------------------------------------------------------------------#
        # Get the variables and the orders....
        vars = listify_args(*variables)
        # Determine which formula we need
        vars = sorted(vars, key=id)
        # This is nasty, but it works...The zip(*list_of_lists) effectively "unzips"
        self._orders, self._variables = zip(*sorted([(len(list(g)), k) for k, g in groupby(vars)], reverse=True))
        # --------------------------------------------------------------------------------#
        # Determine which formula to use
        # This gets reused, so define a quicky function...
        def get_possibilities(formula_list):
            return [
                f
                for f in formula_list
                if f.orders == list(self.orders)
                and f.robustness >= self.target_robustness
                and (f.is_forward() if self._forward else f.is_central())
            ]

        # ----------------------------------------#
        # First, try and get a "hand-generated" formula
        possibilities = get_possibilities(FiniteDifferenceDerivative.formulas)
        if len(possibilities) == 0:
            # We know how to generate single variable formulas to arbitrary order, so let's do it
            n_derivative_vars = len(self.orders)
            derivative_order = sum(self.orders)
            if n_derivative_vars == 1:
                # This long name is unweildy...
                gen_dict = FiniteDifferenceDerivative.generated_single_variable_formulas
                # See if we've already generated it...
                formula = gen_dict.get(
                    (
                        derivative_order,
                        self.target_robustness + (1 if not self._forward and self.target_robustness % 2 == 1 else 0),
                        self._forward,
                    ),
                    None,
                )
                if formula is None:
                    # okay, we can generate it.
                    generate_single_variable_formulas(
                        derivative_order,
                        self.target_robustness + (1 if not self._forward and self.target_robustness % 2 == 1 else 0),
                        self._forward,
                    )
                    formula = gen_dict[
                        (
                            derivative_order,
                            self.target_robustness
                            + (1 if not self._forward and self.target_robustness % 2 == 1 else 0),
                            self._forward,
                        )
                    ]
                possibilities.append(formula)
                if sanity_checking_enabled:
                    possibilities = get_possibilities(possibilities)
            else:
                # we don't know how to generate these...yet...but I'm working on it!
                raise RuntimeError(
                    "Can't find formula for orders {0} and"
                    " robustness {1}".format(self.orders, self.target_robustness)
                )
        # Use the minimum robustness for now.  Later we can make it use
        #   the best possible without additional calculations.
        self._formula = sorted(possibilities, key=attrgetter("robustness"))[0]
コード例 #17
0
ファイル: tensor.py プロジェクト: keceli/psi4release
    def __new__(cls, *args, **kwargs):
        """
        TODO Move this to class level documentation, since it doesn't show up in Sphinx
        Takes several different forms.  Given a number of arguments (possibly nested lists), a Tensor is created as
        expected.  *This is the only form in which arguments may be specified without keywords.*
        `Tensor` can also be initialized by giving a list of dimensions for the `shape` (aliased as `dimension`)
        keyword argument, with a possible default value keyword argument `default_val`.
        Unless otherwise specified via the `dtype` keyword argument, it is assumed that the input data should be cast
        as a `numpy.float64`.

        """
        # Pop off any special args or kwargs and store their values for later
        has_indices = False
        ret_val = None
        indices = None
        units = pop_kwarg(kwargs, 'units')
        name = kwargs.pop('name', None)
        #--------------------------------------------------------------------------------#
        # pop off any kwargs that the subclass's __init__ takes...
        subclass_kwargs = {}
        for supercls in cls.__mro__:
            if supercls is Tensor:
                break
            if hasattr(supercls, '__tensor_init__') and callable(supercls.__tensor_init__):
                if hasattr(supercls.__tensor_init__, 'getargspec'):
                    argspec = supercls.__tensor_init__.getargspec()
                else:
                    argspec = inspect.getargspec(supercls.__tensor_init__)
                for arg in argspec.args[1:]:
                    subclass_kwargs[arg] = kwargs.pop(arg, None)
        #--------------------------------------------------------------------------------#
        # Check for indices...
        indices_kwarg = kwargs.pop('indices', None)
        if indices_kwarg is None and len(args) == 1 and isinstance(args[0], basestring):
            args = list(args)
            indices_kwarg = args.pop(0)
            args = tuple(args)
        index_range_set = pop_multikwarg(kwargs, 'index_range_set', 'in_set', 'set')
        if indices_kwarg is not None:
            has_indices = True
            indices = EinsumTensor.split_indices(indices_kwarg)
            if index_range_set is None:
                index_range_set = IndexRange.global_index_range_set
            shape = []
            for idx in indices:
                if idx not in index_range_set.known_ranges:
                    raise IndexError("unknown index '" + idx + "'")
                shape.append(index_range_set.known_ranges[idx].size)
            shape = tuple(shape)
            if "shape" in kwargs:
                kwshape = kwargs.pop('shape')
                if shape != kwshape:
                    raise TypeError("inconsistent shape:  indices '{}' indicate a shape of {}, but"
                                    " the keyword 'shape' was given with the shape {}".format(
                        ",".join(indices), shape, kwshape
                    ))
            kwargs['shape'] = shape
        #--------------------------------------------------------------------------------#
        # Now create a numpy.ndarray object...
        def_val = pop_kwarg(kwargs, 'default_val', 'default_value', 'default') or 0.0
        # Set the default data type to float, unless the user specifies
        dtype = get_kwarg(kwargs, 'dtype') or float
        if not callable(dtype) and grendel.show_warnings:
            warn("dtype given to {0} constructor is not Callable and thus cannot be used for casting." \
                 "  It is better to use callable types for dtype if possible; e.g. numpy.float64 instead" \
                 "of numpy.dtype('float64')".format(classname(cls)))
        kwargs['dtype'] = dtype
        # Typecast the default value
        if callable(dtype):
            def_val = dtype(def_val)
        # See if we have a shape...
        shape = pop_kwarg(kwargs, 'shape', 'dimension')
        # See if we have data...
        # This allows us to support the form Tensor(1, 2, 3, 4)
        if len(args) == 1 and isinstance(args[0], np.ndarray):
            data = args[0]
        else:
            data = listify_args(*args)
        if 'data' in kwargs:
            if data:
                raise TypeError("`data` may be specified as a keyword argument or as " \
                                "the regular arguments to {0} constructor, but not both.".format(classname(cls)))
            else:
                data = pop_kwarg('data')
        if shape and not isinstance(data, np.ndarray):
            has_content = False
            if len(args) != 0:
                has_content = True
            if not has_content:
                if def_val == 0.0:
                    try:
                        ret_val = np.zeros(shape=shape, **kwargs)
                    except:
                        raise
                else:
                    ret_val = (np.ones(shape=shape, **kwargs) * def_val)
            else:
                if grendel.sanity_checking_enabled:
                    # Check data length
                    tmp = np.array(data)
                    needed_data_size = 1
                    for dim in shape: needed_data_size *= dim
                    try:
                        tmp.reshape((needed_data_size,))
                    except ValueError:
                        raise ValueError("Data provided to {0} constructor is incompatible with the shape {1}".format(classname(cls), shape))
                    # Check data type
                ret_val = np.array(data, **kwargs).reshape(shape)
        else:
            # Just pass on the data and any surviving kwargs
            try:
                if isinstance(data, np.ndarray) and (
                        len(kwargs) == 0
                     or (len(kwargs) == 1 and 'dtype' in kwargs and kwargs['dtype'] == data.dtype)
                ):
                    # Just do a view
                    ret_val = data.view(cls)
                else:
                    # Otherwise, we need to call the numpy "constructor" (actually a factory function) of ndarray
                    ret_val = np.array(data, **kwargs)
            except:
                # debugging breakpoint hook
                raise
            if shape and ret_val.shape != shape:
                raise ValueError("Shape mismatch: data shape {0} does not match specified shape {1}".format(
                    data.shape, shape
                ))
        #--------------------------------------------------------------------------------#
        # View-cast the ret_val to the class in question, but only if we haven't already
        if not isinstance(ret_val, cls):
            ret_val = ret_val.view(cls)
        # Now assign stuff from any special args...
        if has_indices:
            ret_val.indices = indices
            ret_val.index_range_set = index_range_set
        else:
            ret_val.indices = None
        ret_val.units = units
        ret_val.name = name
        if name is None:
            ret_val.name = "(unnamed tensor)"
        # pass the remaining kwargs to the initializer...
        ret_val.__tensor_init__(**subclass_kwargs)
        return ret_val
コード例 #18
0
ファイル: tensor.py プロジェクト: guoyang0123/psi4release
    def __new__(cls, *args, **kwargs):
        """
        TODO Move this to class level documentation, since it doesn't show up in Sphinx
        Takes several different forms.  Given a number of arguments (possibly nested lists), a Tensor is created as
        expected.  *This is the only form in which arguments may be specified without keywords.*
        `Tensor` can also be initialized by giving a list of dimensions for the `shape` (aliased as `dimension`)
        keyword argument, with a possible default value keyword argument `default_val`.
        Unless otherwise specified via the `dtype` keyword argument, it is assumed that the input data should be cast
        as a `numpy.float64`.

        """
        # Pop off any special args or kwargs and store their values for later
        has_indices = False
        ret_val = None
        indices = None
        units = pop_kwarg(kwargs, 'units')
        name = kwargs.pop('name', None)
        #--------------------------------------------------------------------------------#
        # pop off any kwargs that the subclass's __init__ takes...
        subclass_kwargs = {}
        for supercls in cls.__mro__:
            if supercls is Tensor:
                break
            if hasattr(supercls, '__tensor_init__') and callable(
                    supercls.__tensor_init__):
                if hasattr(supercls.__tensor_init__, 'getargspec'):
                    argspec = supercls.__tensor_init__.getargspec()
                else:
                    argspec = inspect.getargspec(supercls.__tensor_init__)
                for arg in argspec.args[1:]:
                    subclass_kwargs[arg] = kwargs.pop(arg, None)
        #--------------------------------------------------------------------------------#
        # Check for indices...
        indices_kwarg = kwargs.pop('indices', None)
        if indices_kwarg is None and len(args) == 1 and isinstance(
                args[0], basestring):
            args = list(args)
            indices_kwarg = args.pop(0)
            args = tuple(args)
        index_range_set = pop_multikwarg(kwargs, 'index_range_set', 'in_set',
                                         'set')
        if indices_kwarg is not None:
            has_indices = True
            indices = EinsumTensor.split_indices(indices_kwarg)
            if index_range_set is None:
                index_range_set = IndexRange.global_index_range_set
            shape = []
            for idx in indices:
                if idx not in index_range_set.known_ranges:
                    raise IndexError("unknown index '" + idx + "'")
                shape.append(index_range_set.known_ranges[idx].size)
            shape = tuple(shape)
            if "shape" in kwargs:
                kwshape = kwargs.pop('shape')
                if shape != kwshape:
                    raise TypeError(
                        "inconsistent shape:  indices '{}' indicate a shape of {}, but"
                        " the keyword 'shape' was given with the shape {}".
                        format(",".join(indices), shape, kwshape))
            kwargs['shape'] = shape
        #--------------------------------------------------------------------------------#
        # Now create a numpy.ndarray object...
        def_val = pop_kwarg(kwargs, 'default_val', 'default_value',
                            'default') or 0.0
        # Set the default data type to float, unless the user specifies
        dtype = get_kwarg(kwargs, 'dtype') or float
        if not callable(dtype) and grendel.show_warnings:
            warn("dtype given to {0} constructor is not Callable and thus cannot be used for casting." \
                 "  It is better to use callable types for dtype if possible; e.g. numpy.float64 instead" \
                 "of numpy.dtype('float64')".format(classname(cls)))
        kwargs['dtype'] = dtype
        # Typecast the default value
        if callable(dtype):
            def_val = dtype(def_val)
        # See if we have a shape...
        shape = pop_kwarg(kwargs, 'shape', 'dimension')
        # See if we have data...
        # This allows us to support the form Tensor(1, 2, 3, 4)
        if len(args) == 1 and isinstance(args[0], np.ndarray):
            data = args[0]
        else:
            data = listify_args(*args)
        if 'data' in kwargs:
            if data:
                raise TypeError("`data` may be specified as a keyword argument or as " \
                                "the regular arguments to {0} constructor, but not both.".format(classname(cls)))
            else:
                data = pop_kwarg('data')
        if shape and not isinstance(data, np.ndarray):
            has_content = False
            if len(args) != 0:
                has_content = True
            if not has_content:
                if def_val == 0.0:
                    try:
                        ret_val = np.zeros(shape=shape, **kwargs)
                    except:
                        raise
                else:
                    ret_val = (np.ones(shape=shape, **kwargs) * def_val)
            else:
                if grendel.sanity_checking_enabled:
                    # Check data length
                    tmp = np.array(data)
                    needed_data_size = 1
                    for dim in shape:
                        needed_data_size *= dim
                    try:
                        tmp.reshape((needed_data_size, ))
                    except ValueError:
                        raise ValueError(
                            "Data provided to {0} constructor is incompatible with the shape {1}"
                            .format(classname(cls), shape))
                    # Check data type
                ret_val = np.array(data, **kwargs).reshape(shape)
        else:
            # Just pass on the data and any surviving kwargs
            try:
                if isinstance(data, np.ndarray) and (
                        len(kwargs) == 0 or
                    (len(kwargs) == 1 and 'dtype' in kwargs
                     and kwargs['dtype'] == data.dtype)):
                    # Just do a view
                    ret_val = data.view(cls)
                else:
                    # Otherwise, we need to call the numpy "constructor" (actually a factory function) of ndarray
                    ret_val = np.array(data, **kwargs)
            except:
                # debugging breakpoint hook
                raise
            if shape and ret_val.shape != shape:
                raise ValueError(
                    "Shape mismatch: data shape {0} does not match specified shape {1}"
                    .format(data.shape, shape))
        #--------------------------------------------------------------------------------#
        # View-cast the ret_val to the class in question, but only if we haven't already
        if not isinstance(ret_val, cls):
            ret_val = ret_val.view(cls)
        # Now assign stuff from any special args...
        if has_indices:
            ret_val.indices = indices
            ret_val.index_range_set = index_range_set
        else:
            ret_val.indices = None
        ret_val.units = units
        ret_val.name = name
        if name is None:
            ret_val.name = "(unnamed tensor)"
        # pass the remaining kwargs to the initializer...
        ret_val.__tensor_init__(**subclass_kwargs)
        return ret_val
コード例 #19
0
ファイル: misc.py プロジェクト: guoyang0123/psi4release
 def __class_getitem__(cls, args):
     return listify_args(args)