Ejemplo n.º 1
0
def add_traits_to_argparse(obj: HasTraits, parser: ArgumentParser,
                           prefix: str=None):
    """
    Add all traits from the given object to the argparse context.

    :param obj: an instance of HasTraits
    :param parser: argparse parser
    :param prefix: string to prefix keys with
    """
    for key, trait in obj.traits().items():
        if trait.get_metadata('config') is not True:
            continue

        argname = '--%s' % key
        if prefix is not None:
            argname = '--%s.%s' % (prefix, key)

        if isinstance(trait, Container):
            parser.add_argument(argname, nargs='+', help=trait.info_text)
        elif isinstance(trait, Enum):
            parser.add_argument(argname, type=str.lower,
                                choices=[x.lower() for x in trait.values],
                                help=trait.info_text)
        else:
            argtype = str
            if hasattr(trait, 'default_value'):
                argtype = type(trait.default_value)
            parser.add_argument(argname, type=argtype, help=trait.info_text)
Ejemplo n.º 2
0
def get_args_dict(obj: HasTraits, incl_all=False):
    """
    Return a dict of user-configurable traits for an object

    :param obj: an instance of HasTraits
    :param incl_all: If all items should be included, regardless of RO status
    :return: dict of arguments
    """
    argsdict = ArgsDict()
    for k in sorted(obj._trait_values.keys()):
        v = obj._trait_values[k]
        trait = obj.traits()[k]
        if incl_all or (not trait.get_metadata('hidden') and is_trait_writable(trait)):
            argsdict[k] = v
    return argsdict
Ejemplo n.º 3
0
def is_own_trait(model: traitlets.HasTraits, path: Tuple[str, ...],
                 trait: traitlets.TraitType) -> bool:
    return path[-1] in model.class_own_traits()
Ejemplo n.º 4
0
    def __init__(self, *coords, **kwargs):

        self._copy = kwargs.pop("copy", True)
        self._sorted = kwargs.pop("sorted", True)

        keepnames = kwargs.pop("keepnames", False)
        # if keepnames is false and the names of the dimensions are not passed in kwargs, then use dims if not none
        dims = kwargs.pop("dims", None)

        self.name = kwargs.pop("name", None)

        # initialise the coordinate list
        self._coords = []

        # First evaluate passed args
        # --------------------------

        # some cleaning
        if coords:

            if all([(isinstance(coords[i],
                                (np.ndarray, NDArray, list, CoordSet))
                     or coords[i] is None) for i in range(len(coords))]):
                # Any instance of a NDArray can be accepted as coordinates for a dimension.
                # If an instance of CoordSet is found, this means that all
                # coordinates in this set describe the same axis
                coords = tuple(coords)

            elif is_sequence(coords) and len(coords) == 1:
                # if isinstance(coords[0], list):
                #     coords = (CoordSet(*coords[0], sorted=False),)
                # else:
                coords = coords[0]

                if isinstance(coords, dict):
                    # we have passed a dict, postpone to the kwargs evaluation process
                    kwargs.update(coords)
                    coords = None

            else:
                raise ValueError("Did not understand the inputs")

        # now store the args coordinates in self._coords (validation is fired when this attribute is set)
        if coords:
            for coord in coords[::-1]:  # we fill from the end of the list
                # (in reverse order) because by convention when the
                # names are not specified, the order of the
                # coords follow the order of dims.
                if not isinstance(coord, CoordSet):
                    if isinstance(coord, list):
                        coord = CoordSet(*coord[::-1], sorted=False)
                    elif not isinstance(coord, LinearCoord):  # else
                        coord = Coord(coord, copy=True)
                else:
                    coord = cpy.deepcopy(coord)

                if not keepnames:
                    if dims is None:
                        # take the last available name of available names list
                        coord.name = self.available_names.pop(-1)
                    else:
                        # use the provided list of dims
                        coord.name = dims.pop(-1)

                self._append(coord)  # append the coord (but instead of append,
                # use assignation -in _append - to fire the validation process )

        # now evaluate keywords argument
        # ------------------------------

        for key, coord in list(kwargs.items())[:]:
            # remove the already used kwargs (Fix: deprecation warning in Traitlets - all args, kwargs must be used)
            del kwargs[key]

            # prepare values to be either Coord, LinearCoord or CoordSet
            if isinstance(coord, (list, tuple)):
                coord = CoordSet(
                    *coord, sorted=False
                )  # make sure in this case it becomes a CoordSet instance

            elif isinstance(coord, np.ndarray) or coord is None:
                coord = Coord(
                    coord, copy=True
                )  # make sure it's a Coord  # (even if it is None -> Coord(None)

            elif isinstance(coord, str) and coord in DEFAULT_DIM_NAME:
                # may be a reference to another coordinates (e.g. same coordinates for various dimensions)
                self._references[key] = coord  # store this reference
                continue

            # Populate the coords with coord and coord's name.
            if isinstance(coord,
                          (NDArray, Coord, LinearCoord, CoordSet)):  # NDArray,
                if key in self.available_names or (
                        len(key) == 2 and key.startswith("_")
                        and key[1] in list("123456789")):
                    # ok we can find it as a canonical name:
                    # this will overwrite any already defined coord value
                    # which means also that kwargs have priority over args
                    coord.name = key
                    self._append(coord)

                elif not self.is_empty and key in self.names:
                    # append when a coordinate with this name is already set in passed arg.
                    # replace it
                    idx = self.names.index(key)
                    coord.name = key
                    self._coords[idx] = coord

                else:
                    raise KeyError(
                        f"Probably an invalid key (`{key}`) for coordinates has been passed. "
                        f"Valid keys are among:{DEFAULT_DIM_NAME}")

            else:
                raise ValueError(
                    f"Probably an invalid type of coordinates has been passed: {key}:{coord} "
                )

        # store the item (validation will be performed)
        # self._coords = _coords

        # inform the parent about the update
        self._updated = True

        # set a notifier on the name traits name of each coordinates
        for coord in self._coords:
            if coord is not None:
                HasTraits.observe(coord, self._coords_update, "_name")

        # initialize the base class with the eventual remaining arguments
        super().__init__(**kwargs)
Ejemplo n.º 5
0
    def __init__(self, *coords, **kwargs):
        """
        A collection of Coord objects for a NDArray object with validation.

        This object is an iterable containing a collection of Coord objects.

        Parameters
        ----------
        *coords : |NDarray|, |NDArray| subclass or |CoordSet| sequence of objects.
            If an instance of CoordSet is found, instead of an array, this means
            that all coordinates in this coords describe the same axis.
            It is assumed that the coordinates are passed in the order of the
            dimensions of a nD numpy array (
            `row-major <https://docs.scipy.org/doc/numpy-1.14.1/glossary.html#term-row-major>`_
            order), i.e., for a 3d object : 'z', 'y', 'x'.
        **kwargs: dict
            See other parameters.

        Other Parameters
        ----------------
        x : |NDarray|, |NDArray| subclass or |CoordSet|
            A single coordinate associated to the 'x'-dimension.
            If a coord was already passed in the argument, this will overwrite
            the previous. It is thus not recommended to simultaneously use
            both way to initialize the coordinates to avoid such conflicts.
        y, z, u, ... : |NDarray|, |NDArray| subclass or |CoordSet|
            Same as `x` for the others dimensions.
        dims : list of string, optional
            Names of the dims to use corresponding to the coordinates. If not given, standard names are used: x, y, ...

        See Also
        --------
        Coord : Explicit coordinates object.
        LinearCoord : Implicit coordinates object.
        NDDataset: The main object of SpectroChempy which makes use of CoordSet.

        Examples
        --------
        >>> from spectrochempy import Coord, CoordSet

        Define 4 coordinates, with two for the same dimension

        >>> coord0 = Coord.linspace(10., 100., 5, units='m', title='distance')
        >>> coord1 = Coord.linspace(20., 25., 4, units='K', title='temperature')
        >>> coord1b = Coord.linspace(1., 10., 4, units='millitesla', title='magnetic field')
        >>> coord2 = Coord.linspace(0., 1000., 6, units='hour', title='elapsed time')

        Now create a coordset

        >>> cs = CoordSet(t=coord0, u=coord2, v=[coord1, coord1b])

        Display some coordinates

        >>> cs.u
        Coord: [float64] hr (size: 6)

        >>> cs.v
        CoordSet: [_1:temperature, _2:magnetic field]

        >>> cs.v_1
        Coord: [float64] K (size: 4)
        """

        self._copy = kwargs.pop('copy', True)
        self._sorted = kwargs.pop('sorted', True)

        keepnames = kwargs.pop('keepnames', False)
        # if keepnames is false and the names of the dimensions are not passed in kwargs, then use dims if not none
        dims = kwargs.pop('dims', None)

        self.name = kwargs.pop('name', None)

        # initialise the coordinate list
        self._coords = []

        # First evaluate passed args
        # --------------------------

        # some cleaning
        if coords:

            if all([(isinstance(coords[i],
                                (np.ndarray, NDArray, list, CoordSet))
                     or coords[i] is None) for i in range(len(coords))]):
                # Any instance of a NDArray can be accepted as coordinates for a dimension.
                # If an instance of CoordSet is found, this means that all
                # coordinates in this set describe the same axis
                coords = tuple(coords)

            elif is_sequence(coords) and len(coords) == 1:
                # if isinstance(coords[0], list):
                #     coords = (CoordSet(*coords[0], sorted=False),)
                # else:
                coords = coords[0]

                if isinstance(coords, dict):
                    # we have passed a dict, postpone to the kwargs evaluation process
                    kwargs.update(coords)
                    coords = None

            else:
                raise ValueError('Did not understand the inputs')

        # now store the args coordinates in self._coords (validation is fired when this attribute is set)
        if coords:
            for coord in coords[::-1]:  # we fill from the end of the list
                # (in reverse order) because by convention when the
                # names are not specified, the order of the
                # coords follow the order of dims.
                if not isinstance(coord, CoordSet):
                    if isinstance(coord, list):
                        coord = CoordSet(*coord, sorted=False)
                    elif not isinstance(coord, LinearCoord):  # else
                        coord = Coord(coord, copy=True)
                else:
                    coord = cpy.deepcopy(coord)

                if not keepnames:
                    if dims is None:
                        # take the last available name of available names list
                        coord.name = self.available_names.pop(-1)
                    else:
                        # use the provided list of dims
                        coord.name = dims.pop(-1)

                self._append(coord)  # append the coord (but instead of append,
                # use assignation -in _append - to fire the validation process )

        # now evaluate keywords argument
        # ------------------------------

        for key, coord in list(kwargs.items())[:]:
            # remove the already used kwargs (Fix: deprecation warning in Traitlets - all args, kwargs must be used)
            del kwargs[key]

            # prepare values to be either Coord, LinearCoord or CoordSet
            if isinstance(coord, (list, tuple)):
                coord = CoordSet(
                    *coord, sorted=False
                )  # make sure in this case it becomes a CoordSet instance

            elif isinstance(coord, np.ndarray) or coord is None:
                coord = Coord(
                    coord, copy=True
                )  # make sure it's a Coord  # (even if it is None -> Coord(None)

            elif isinstance(coord, str) and coord in DEFAULT_DIM_NAME:
                # may be a reference to another coordinates (e.g. same coordinates for various dimensions)
                self._references[key] = coord  # store this reference
                continue

            # Populate the coords with coord and coord's name.
            if isinstance(coord,
                          (NDArray, Coord, LinearCoord, CoordSet)):  # NDArray,
                if key in self.available_names or (
                        len(key) == 2 and key.startswith('_')
                        and key[1] in list("123456789")):
                    # ok we can find it as a canonical name:
                    # this will overwrite any already defined coord value
                    # which means also that kwargs have priority over args
                    coord.name = key
                    self._append(coord)

                elif not self.is_empty and key in self.names:
                    # append when a coordinate with this name is already set in passed arg.
                    # replace it
                    idx = self.names.index(key)
                    coord.name = key
                    self._coords[idx] = coord

                else:
                    raise KeyError(
                        f'Probably an invalid key (`{key}`) for coordinates has been passed. '
                        f'Valid keys are among:{DEFAULT_DIM_NAME}')

            else:
                raise ValueError(
                    f'Probably an invalid type of coordinates has been passed: {key}:{coord} '
                )

        # store the item (validation will be performed)
        # self._coords = _coords

        # inform the parent about the update
        self._updated = True

        # set a notifier on the name traits name of each coordinates
        for coord in self._coords:
            if coord is not None:
                HasTraits.observe(coord, self._coords_update, '_name')

        # initialize the base class with the eventual remaining arguments
        super().__init__(**kwargs)