Exemplo n.º 1
0
class Reinforcements(Domain):
    """A feature domain for specifying reinforcement signals."""

    # TODO: Can probably do away with the mapping... But will need to make 
    # changes to SimpleQNet. - Can

    _config = ("mapping",)

    def __init__(
        self, mapping: Dict[feature, Tuple[Hashable, int]]
    ) -> None:
        """
        Initialize Reinforcements instance.

        :param mapping: A one-to-one mapping from features to dimensions. Each 
            feature is assumed to represent a reinforcement signal for the 
            corresponding dimension. Will raise a ValueError if the mapping is 
            found not to be one-to-one.
        """

        with self.config():
            self.mapping = MappingProxyType(mapping)

    def update(self) -> None:

        if len(set(self.mapping.keys())) != len(set(self.mapping.values())):
            raise ValueError("Mapping must be one-to-one.")

        super().__init__(features=tuple(self.mapping)) 
Exemplo n.º 2
0
    def register(impl: Callable = None,
                 *,
                 arguments: MappingProxyType,
                 on: Hashable):
        """
        Registers a new implementation for the given value of key.

        :param on: dispatch value to register this implementation on.
        :param arguments: parameters to impl.
        :param impl: implementation to associate with value.
        """
        if impl is None:
            return functools.partial(register, arguments=arguments, on=on)

        if on in registry:
            raise ValueError(f'duplicate implementation for {on!r} for {name}')

        # Determine index of dispatch parameter in this signature.
        idx = None
        for i, parameter in enumerate(arguments.values()):
            if parameter.name == key:
                if parameter.kind == inspect.Parameter.KEYWORD_ONLY:
                    # Parameter is keyword-only, so it has no 'index'.
                    idx = -1
                else:
                    idx = i

        registry[on] = impl, idx

        return impl
Exemplo n.º 3
0
Arquivo: VSMD1X6.py Projeto: yo8/VSMD
    def __init_record(cls):
        """Init a list for query

            Hashed Map can not afford this , so we need more space to do this
        :return:
        """
        od = MappingProxyType(cls._member_map_)
        cls.__record = list(od.values())
Exemplo n.º 4
0
class CommandDispatcher:
    def __init__(self, bot, command, *, loop=None):
        self._bot = bot
        self._command = command
        self._child_dispatchers = {}
        self._handlers = []

        self.loop = loop or asyncio.get_event_loop()

        self.child_dispatchers = MappingProxyType(self._child_dispatchers)

    @property
    def command(self):
        return self._command

    @property
    def handlers(self):
        return list(self._handlers)

    @property
    def user_level(self):
        levels = []

        if self._handlers:
            levels += [h.user_level for h in self._handlers]

        if self.child_dispatchers:
            levels += [c.user_level for c in self.child_dispatchers.values()]

        levels = filter(None.__ne__, levels)

        return min(levels) if levels else None

    @property
    def is_leaf(self):
        return not self.child_dispatchers

    def ensure_child_dispatchers(self, commands):
        command, sub_commands = (commands.split(' ', 1) + [''])[:2]
        dispatcher = self._ensure_child_dispatcher(command)

        if sub_commands:
            return dispatcher.ensure_child_dispatchers(sub_commands)

        return dispatcher

    def _ensure_child_dispatcher(self, command):
        if command not in self._child_dispatchers:
            dispatcher = self.__class__(self._bot, command)
            self._child_dispatchers[command] = dispatcher

        return self._child_dispatchers[command]

    def register_handler(self, handler, command=None):
        if not command:
            self._handlers.append(handler)
            return self

        return self.ensure_child_dispatchers(command).register_handler(handler)

    def get(self, command_text, user_level):
        command, sub_commands = (command_text.split(' ', 1) + [''])[:2]
        command = self._get_command_from_alias(command)

        try:
            dispatcher = self.child_dispatchers[command]
            if dispatcher.user_level <= user_level:
                return dispatcher.get(sub_commands, user_level)

        except KeyError:
            pass

        return (self, command_text)

    def _get_command_from_alias(self, command):
        alias = self._bot.database.get_CommandAlias_by_alias(command)
        return alias.command if alias else command

    def dispatch(self, command, message):
        user_level = UserLevel.get(message.author, message.channel)
        dispatcher, attributes = self.get(command, user_level)
        handlers = [
            h for h in dispatcher.handlers if h.user_level <= user_level
        ]

        for handler in handlers:
            self.loop.create_task(
                self._wrapper(handler, attributes, message, command))

        return bool(handlers)

    async def _wrapper(self, handler, attributes, message, command):
        try:
            binding = self._get_binding_for(handler, attributes, message)
            await handler.coroutine(*binding.args, **binding.kwargs)

        except CommandException as ex:
            await self._bot.send_message(message.channel, str(ex))

        except BaseException:
            await self._bot.send_message(
                message.channel,
                'Oh no, something went horribly wrong trying to complete this'
                ' command. Please tell the owner of this bot what command you'
                ' entered and roughly when this happened, and I\'ll get all'
                ' fixed up as soon as possible. Thanks!')

            logging.exception('Error in command {} {}'.format(
                command, attributes))

    def _get_binding_for(self, handler, attributes, message):
        signature = inspect.signature(handler.coroutine)

        try:
            if len(signature.parameters) > 1:
                attributes = attributes.split(' ',
                                              len(signature.parameters) - 2)
                return signature.bind(
                    message, *[att for att in attributes if att is not ''])

            return signature.bind(message)

        except TypeError:
            raise CommandException('Syntax: `{}`'.format(handler.syntax))
Exemplo n.º 5
0
class LVPPool:
    """
    Communicates with more than one arduino simultaneously.
    """
    @classmethod
    def all_devices(cls, exclude=(), kind=LVP, merge_log=True, **kwargs):
        """
        Create an LVP pool using all connections
        """
        kwargs.setdefault('log_id', merge_log)
        kwargs.setdefault('log_path_with_id', not merge_log)
        devices = [p.device for p in comports() if p.device not in exclude]
        return cls([kind(device, **kwargs) for device in devices])

    def __init__(self, devices):
        self.devices = MappingProxyType({dev.id: dev for dev in devices})

    def __iter__(self):
        return iter(self.devices.values())

    def __len__(self):
        return len(self.devices)

    def __repr__(self):
        return f"<LVPPool with {[d.id for d in self]}>"

    def _parallel_map(self,
                      func,
                      devices=None,
                      args=(),
                      kwargs=MappingProxyType({}),
                      timeout=None):
        devices = self if devices is None else list(devices)

        results = [None] * len(devices)

        def target(i, dev):
            results[i] = func(dev, *args, **kwargs)

        threads = [
            Thread(target=target, args=item) for item in enumerate(devices)
        ]

        for thread in threads:
            thread.start()

        for thread in threads:
            thread.join(timeout=timeout)

        return {dev.id: res for dev, res in zip(devices, results)}

    def query(self, query) -> List[LVP]:
        """
        Filter devices using query.

        Return a list of all selected devices.
        """
        if query == ...:
            return list(self.devices.values())
        elif isinstance(query, LVP):
            return self.query(query.id)
        elif isinstance(query, (list, tuple)):
            result = set()
            for q in query:
                result.update(self.query(q))
            return list(result)
        elif query in self.devices:
            return [self.devices[query]]
        raise ValueError("invalid query")

    def get(self, ref, *args, timeout=None):
        """
        Get set of values from all selected devices.
        """

        devs = self.query(ref)
        return self._parallel_map(lambda d: d.get(*args), devs)

    def set(self, ref, *args, timeout=None, **kwargs):
        """
        Set of values on all selected all devices.
        """
        devs = self.query(ref)
        self._parallel_map(lambda d: d.set(*args, **kwargs), devs)

    def declare(self, spec, bind=True):
        """
        Declare function.
        """
        funcs = {dev.id: dev.declare(spec, bind=False) for dev in self}
        name = spec.split("(")[0]

        def func(query, *args, **kwargs):
            def target(dev):
                return funcs[dev.id](*args, **kwargs)

            return self._parallel_map(target, self.query(query))

        func.__name__ = name
        func.__doc__ = f"Calls the {spec} lvp function"
        if bind:
            setattr(self, name, func)
        return func

    def exec(self, query, cmd):
        self._parallel_map(lambda d: d.exec(cmd), self.query(query))

    def background(self, query, cmd):
        self._parallel_map(lambda d: d.exec(cmd), self.query(query))
"""MappingProxyType"""
from types import MappingProxyType

d = {'a': 1, 'b': 2}
mp = MappingProxyType(d)

# Read-only
print(list(mp.keys()))
print(list(mp.values()))

print(mp.get('a'))
print(mp.get('c', 'not found'))

# Immutable
# del mp['a']  # TypeError
# mp['a'] = 100  # TypeError

# Mutate the original dictionary
d['a'] = 100
d['c'] = 'new item'
del d['b']

print(mp)  # Reflect the changes in original dictionary
Exemplo n.º 7
0

def _get_jitclass_for_dtype(dtype, upper):
	"""
	Get the correct jitclass of NbTriMatrixBase for the data type and triangle.
	"""
	if upper:
		return _UPPER_JITCLASS_BY_TYPE[dtype]
	else:
		return _LOWER_JITCLASS_BY_TYPE[dtype]


@nb.guvectorize(
	[
		(nbtype[:], nbtype[:], nb.intp[:], nb.intp[:], nbtype[:])
		for nbtype in NUMBA_TYPES.values()
	],
	'(n),(),(),()->()',
	nopython=True,
)
def getitem_advanced_int_lower(array, diag, row, col, out):
	"""getitem_advanced_int_lower(array, diag, row, col)

	Numpy ufunc. Get items from the condensed lower triangle of a symmetric
	matrix using the equivalent of numpy advanced indexing with integer arrays
	on both the rows and columns of the full matrix.

	This is meant to be vectorized on the ``row`` and ``col`` arguments only.

	Row/column indices do not need to fall on the lower triangle (may be on
	diagonal or upper), but are not bounds checked.
Exemplo n.º 8
0
    def __init__(self, raster, list_of_prod_fp, channel_ids, is_flat,
                 dst_nodata, interpolation, max_queue_size, parent_uid,
                 key_in_parent):
        # Mutable attributes ******************************************************************** **
        # Attributes that relates a query to a single optional computation phase
        self.cache_computation = None  # type: Union[None, CacheComputationInfos]

        # Immutable attributes ****************************************************************** **
        self.parent_uid = parent_uid
        self.key_in_parent = key_in_parent

        # The parameters given by user in invocation
        self.channel_ids = channel_ids  # type: Sequence[int]
        self.is_flat = is_flat  # type: bool
        self.unique_channel_ids = []
        for bi in channel_ids:
            if bi not in self.unique_channel_ids:
                self.unique_channel_ids.append(bi)
        self.unique_channel_ids = tuple(self.unique_channel_ids)

        self.dst_nodata = dst_nodata  # type: Union[int, float]
        self.interpolation = interpolation  # type: str

        # Output max queue size (Parameter given to queue.Queue)
        self.max_queue_size = max_queue_size  # type: int

        # How many arrays are requested
        self.produce_count = len(list_of_prod_fp)  # type: int

        # Build CacheProduceInfos objects **************************************
        to_zip = []

        # The list of Footprints requested
        list_of_prod_fp = list_of_prod_fp  # type: List[ProductionFootprint]
        to_zip.append(list_of_prod_fp)

        # Boolean attribute of each `prod_fp`
        # If `True` the resampling phase has to be performed on a Pool
        list_of_prod_same_grid = [
            fp.same_grid(raster.fp) for fp in list_of_prod_fp
        ]  # type: List[bool]
        to_zip.append(list_of_prod_same_grid)

        # Boolean attribute of each `prod_fp`
        # If `False` the queried footprint is outside of raster's footprint. It means that no
        # sampling is necessary and the outputed array will be full of `dst_nodata`
        list_of_prod_share_area = [
            fp.share_area(raster.fp) for fp in list_of_prod_fp
        ]  # type: List[bool]
        to_zip.append(list_of_prod_share_area)

        # The full Footprint that needs to be sampled for each `prod_fp`
        # Is `None` if `prod_fp` is fully outside of raster
        list_of_prod_sample_fp = []  # type: List[Union[None, SampleFootprint]]
        to_zip.append(list_of_prod_sample_fp)

        # The set of cache Footprints that are needed for each `prod_fp`
        list_of_prod_cache_fps = []  # type: List[FrozenSet[CacheFootprint]]
        to_zip.append(list_of_prod_cache_fps)

        # The list of resamplings to perform for each `prod_fp`
        # Always at least 1 resampling per `prod_fp`
        list_of_prod_resample_fps = [
        ]  # type: List[Tuple[ResampleFootprint, ...]]
        to_zip.append(list_of_prod_resample_fps)

        # The set of `cache_fp` necessary per `resample_fp` for each `prod_fp`
        list_of_prod_resample_cache_deps_fps = [
        ]  # type: List[Mapping[ResampleFootprint, FrozenSet[CacheFootprint]]]
        to_zip.append(list_of_prod_resample_cache_deps_fps)

        # The full Footprint that needs to be sampled par `resample_fp` for each `prod_fp`
        # Might be `None` if `prod_fp` is fully outside of raster
        list_of_prod_resample_sample_dep_fp = [
        ]  # type: List[Mapping[ResampleFootprint, Union[None, SampleFootprint]]]
        to_zip.append(list_of_prod_resample_sample_dep_fp)

        it = zip(list_of_prod_fp, list_of_prod_same_grid,
                 list_of_prod_share_area)
        # TODO: Speed up that piece of code
        # - Code footprint with lower level code
        # - Spawn a ProcessPoolExecutor when >100 prod. (The same could be done for fp.tile).
        # - What about a global process pool executor in `buzz.env`?
        for prod_fp, same_grid, share_area in it:
            if not share_area:
                # Resampling will be performed in one pass, on the scheduler
                list_of_prod_sample_fp.append(None)
                list_of_prod_cache_fps.append(frozenset())
                resample_fp = cast(ResampleFootprint, prod_fp)
                list_of_prod_resample_fps.append((resample_fp, ))
                list_of_prod_resample_cache_deps_fps.append(
                    MappingProxyType({resample_fp: frozenset()}))
                list_of_prod_resample_sample_dep_fp.append(
                    MappingProxyType({resample_fp: None}))
            else:
                if same_grid:
                    # Remapping will be performed in one pass, on the scheduler
                    sample_fp = raster.fp & prod_fp
                    resample_fps = [cast(ResampleFootprint, prod_fp)]
                    sample_dep_fp = {resample_fps[0]: sample_fp}
                else:
                    sample_fp = raster.build_sampling_footprint_to_remap_interpolate(
                        prod_fp, interpolation)

                    if raster.max_resampling_size is None:
                        # Remapping will be performed in one pass, on a Pool
                        resample_fps = [cast(ResampleFootprint, prod_fp)]
                        sample_dep_fp = {resample_fps[0]: sample_fp}
                    else:
                        # Resampling will be performed in several passes, on a Pool
                        rsize = np.maximum(prod_fp.rsize, sample_fp.rsize)
                        countx, county = np.ceil(
                            rsize / raster.max_resampling_size).astype(int)
                        resample_fps = prod_fp.tile_count(
                            countx, county,
                            boundary_effect='shrink').flatten().tolist()
                        sample_dep_fp = {
                            resample_fp:
                            (raster.
                             build_sampling_footprint_to_remap_interpolate(
                                 resample_fp, interpolation)
                             if resample_fp.share_area(raster.fp) else None)
                            for resample_fp in resample_fps
                        }

                resample_cache_deps_fps = MappingProxyType({
                    resample_fp:
                    frozenset(raster.cache_fps_of_fp(sample_subfp))
                    for resample_fp in resample_fps
                    for sample_subfp in [sample_dep_fp[resample_fp]]
                    if sample_subfp is not None
                })
                for s in resample_cache_deps_fps.items():
                    assert len(s) > 0

                # The `intersection of the cache_fps with sample_fp` might not be the same as the
                # the `intersection of the cache_fps with resample_fps`!
                cache_fps = frozenset(
                    itertools.chain.from_iterable(
                        resample_cache_deps_fps.values()))
                assert len(cache_fps) > 0

                list_of_prod_cache_fps.append(cache_fps)
                list_of_prod_sample_fp.append(sample_fp)
                list_of_prod_resample_fps.append(tuple(resample_fps))
                list_of_prod_resample_cache_deps_fps.append(
                    resample_cache_deps_fps)
                list_of_prod_resample_sample_dep_fp.append(
                    MappingProxyType(sample_dep_fp))

        self.prod = tuple([CacheProduceInfos(*args) for args in zip(*to_zip)
                           ])  # type: Tuple[CacheProduceInfos, ...]

        # Misc *****************************************************************
        # The list of all cache Footprints needed, ordered by priority
        self.list_of_cache_fp = []  # type: Sequence[CacheFootprint]
        seen = set()
        for fps in list_of_prod_cache_fps:
            for fp in fps:
                if fp not in seen:
                    seen.add(fp)
                    self.list_of_cache_fp.append(fp)
        self.list_of_cache_fp = tuple(self.list_of_cache_fp)
        del seen

        # The dict of cache Footprint to set of production idxs
        # For each `cache_fp`, the set of prod_idx that need this cache tile
        self.dict_of_prod_idxs_per_cache_fp = collections.defaultdict(
            set)  # type: Mapping[CacheFootprint, AbstractSet[int]]
        for i, (prod_fp, cache_fps) in enumerate(
                zip(list_of_prod_fp, list_of_prod_cache_fps)):
            for cache_fp in cache_fps:
                self.dict_of_prod_idxs_per_cache_fp[cache_fp].add(i)
        for k, v in self.dict_of_prod_idxs_per_cache_fp.items():
            self.dict_of_prod_idxs_per_cache_fp[k] = frozenset(v)
        self.dict_of_prod_idxs_per_cache_fp = MappingProxyType(
            self.dict_of_prod_idxs_per_cache_fp)

        # The dict of cache Footprint to production_idx
        # For each `cache_fp`, the minimum prod_idx that need this cache tile
        self.dict_of_min_prod_idx_per_cache_fp = {
        }  # type: Mapping[CacheFootprint, int]
        for k, v in self.dict_of_prod_idxs_per_cache_fp.items():
            self.dict_of_min_prod_idx_per_cache_fp[k] = min(v)
        self.dict_of_min_prod_idx_per_cache_fp = MappingProxyType(
            self.dict_of_min_prod_idx_per_cache_fp)
Exemplo n.º 9
0
class PackageLookup(SymbolLookup):
    """
    Caching structure to make lookups on type names within a :class:`Package` faster.
    """
    def __init__(self, archive: "Archive"):
        self.archive = archive

        data_types = {}  # type: Dict[str, Tuple[TypeConName, DefDataType]]
        values = {}  # type: Dict[str, Tuple[ValName, DefValue]]
        templates = {}  # type: Dict[str, Tuple[TypeConName, DefTemplate]]
        for module in self.archive.package.modules:
            module_ref = ModuleRef(archive.hash, module.name)

            for dt in module.data_types:
                dt_name = TypeConName(module_ref, dt.name.segments)
                data_types[f"{module.name}:{dt.name}"] = (dt_name, dt)

            for value in module.values:
                value_name = ValName(module_ref, value.name_with_type.name)
                values[f"{module.name}:{value.name_with_type.name}"] = (
                    value_name, value)

            for tmpl in module.templates:
                tmpl_name = TypeConName(module_ref, tmpl.tycon.segments)
                templates[f"{module.name}:{tmpl.tycon}"] = (tmpl_name, tmpl)

        self._data_types = MappingProxyType(data_types)
        self._values = MappingProxyType(values)
        self._templates = MappingProxyType(templates)

    def archives(self) -> "Collection[Archive]":
        return [self.archive]

    def package_ids(self) -> "AbstractSet[PackageRef]":
        return frozenset([self.archive.hash])

    def data_type_name(self, ref: "Any") -> "TypeConName":
        pkg, name = validate_template(ref)
        if pkg == self.archive.hash or pkg == STAR:
            dt_name = self.local_data_type_name(name)
            if dt_name is not None:
                return dt_name

        raise NameNotFoundError(ref)

    def data_type(self, ref: "Any") -> "DefDataType":
        pkg, name = validate_template(ref)
        if pkg == self.archive.hash or pkg == STAR:
            dt = self.local_data_type(name)
            if dt is not None:
                return dt

        raise NameNotFoundError(ref)

    def local_data_type_name(self, name: str) -> "Optional[TypeConName]":
        r = self._data_types.get(name)
        return r[0] if r is not None else None

    def local_data_type(self, name: str) -> "Optional[DefDataType]":
        """
        Variation of :meth:`data_type` that assumes the name is already scoped to this package.
        Unlike :meth:`data_type`, this method returns ``None`` in the case of no match.

        You should not normally use this method directly, and instead prefer to use the methods of
        the :class:`SymbolLookup` protocol.

        :param name:
            A name to search for. Must be of the form ``"ModuleName:EntityName"``, where both
            modules and entities are dot-delimited.
        :return:
            Either a matching :class:`DefDataType`, or ``None`` if no match.
        """
        r = self._data_types.get(name)
        return r[1] if r is not None else None

    def value(self, ref: "Any") -> "DefValue":
        pkg, name = validate_template(ref)
        if pkg == self.archive.hash or pkg == STAR:
            dt = self.local_value(name)
            if dt is not None:
                return dt

        raise NameNotFoundError(ref)

    def local_value(self, name: str) -> "Optional[DefValue]":
        """
        Variation of :meth:`data_type` that assumes the name is already scoped to this package.
        Unlike :meth:`data_type`, this method returns ``None`` in the case of no match.

        You should not normally use this method directly, and instead prefer to use the methods of
        the :class:`SymbolLookup` protocol.

        :param name:
            A name to search for. Must be of the form ``"ModuleName:EntityName"``, where both
            modules and entities are dot-delimited.
        :return:
            Either a matching :class:`DefDataType`, or ``None`` if no match.
        """
        r = self._values.get(name)
        return r[1] if r is not None else None

    def template_names(self, ref: "Any") -> "Collection[TypeConName]":
        pkg, name = validate_template(ref)
        if pkg == self.archive.hash or pkg == STAR:
            if name == "*":
                return self.local_template_names()
            elif name in self._templates:
                n, _ = self._templates.get(name)
                return n
        return []

    def template_name(self, ref: "Any") -> "TypeConName":
        pkg, name = validate_template(ref)
        if pkg == self.archive.hash or pkg == STAR:
            tmpl = self.local_template_name(name)
            if tmpl is not None:
                return tmpl

        raise NameNotFoundError(ref)

    def template(self, ref: "Any") -> "DefTemplate":
        pkg, name = validate_template(ref)
        if pkg == self.archive.hash or pkg == STAR:
            tmpl = self.local_template(name)
            if tmpl is not None:
                return tmpl

        raise NameNotFoundError(ref)

    def local_template_names(self) -> "Collection[TypeConName]":
        return [n for n, _ in self._templates.values()]

    def local_template_name(self, name: str) -> "Optional[TypeConName]":
        r = self._templates.get(name)
        return r[0] if r is not None else None

    def local_template(self, name: str) -> "Optional[DefTemplate]":
        """
        Variation of :meth:`data_type` that assumes the name is already scoped to this package.
        Unlike :meth:`data_type`, this method returns ``None`` in the case of no match.

        You should not normally use this method directly, and instead prefer to use the methods of
        the :class:`SymbolLookup` protocol.

        :param name:
            A name to search for. Must be of the form ``"ModuleName:EntityName"``, where both
            modules and entities are dot-delimited.
        :return:
            Either a matching :class:`DefDataType`, or ``None`` if no match.
        """
        r = self._templates.get(name)
        return r[1] if r is not None else None
Exemplo n.º 10
0
class Composition:
    """
    Defines a composition of a compound.

    To create a composition, use the class methods:

        - :meth:`from_pure`
        - :meth:`from_formula`
        - :meth:`from_mass_fractions`
        - :meth:`from_atomic_fractions`

    Use the following attributes to access the composition values:

        - :attr:`mass_fractions`: :class:`dict` where the keys are atomic numbers and the values weight fractions.
        - :attr:`atomic_fractions`: :class:`dict` where the keys are atomic numbers and the values atomic fractions.
        - :attr:`formula`: chemical formula

    The composition object is immutable, i.e. it cannot be modified once created.
    Equality can be checked.
    It is hashable.
    It can be pickled or copied.
    """

    _key = object()
    PRECISION = 0.000000001 # 1ppb

    def __init__(self, key, mass_fractions, atomic_fractions, formula):
        """
        Private constructor. It should never be used.
        """
        if key != Composition._key:
            raise TypeError('Composition cannot be created using constructor')
        if set(mass_fractions.keys()) != set(atomic_fractions.keys()):
            raise ValueError('Mass and atomic fractions must have the same elements')

        self.mass_fractions = MappingProxyType(mass_fractions)
        self.atomic_fractions = MappingProxyType(atomic_fractions)
        self._formula = formula

    @classmethod
    def from_pure(cls, z):
        """
        Creates a pure composition.

        Args:
            z (int): atomic number
        """
        return cls(cls._key, {z: 1.0}, {z: 1.0}, pyxray.element_symbol(z))

    @classmethod
    def from_formula(cls, formula):
        """
        Creates a composition from a chemical formula.

        Args:
            formula (str): chemical formula
        """
        atomic_fractions = convert_formula_to_atomic_fractions(formula)
        return cls.from_atomic_fractions(atomic_fractions)

    @classmethod
    def from_mass_fractions(cls, mass_fractions, formula=None):
        """
        Creates a composition from a mass fraction :class:`dict`.

        Args:
            mass_fractions (dict): mass fraction :class:`dict`.
                The keys are atomic numbers and the values weight fractions.
                Wildcard are accepted, e.g. ``{5: '?', 25: 0.4}`` where boron
                will get a mass fraction of 0.6.
            formula (str): optional chemical formula for the composition.
                If ``None``, a formula will be generated for the composition.
        """
        mass_fractions = process_wildcard(mass_fractions)
        atomic_fractions = convert_mass_to_atomic_fractions(mass_fractions)
        if not formula:
            formula = generate_name(atomic_fractions)
        return cls(cls._key, mass_fractions, atomic_fractions, formula)

    @classmethod
    def from_atomic_fractions(cls, atomic_fractions, formula=None):
        """
        Creates a composition from an atomic fraction :class:`dict`.

        Args:
            atomic_fractions (dict): atomic fraction :class:`dict`.
                The keys are atomic numbers and the values atomic fractions.
                Wildcard are accepted, e.g. ``{5: '?', 25: 0.4}`` where boron
                will get a atomic fraction of 0.6.
            formula (str): optional chemical formula for the composition.
                If ``None``, a formula will be generated for the composition.
        """
        atomic_fractions = process_wildcard(atomic_fractions)
        mass_fractions = convert_atomic_to_mass_fractions(atomic_fractions)
        if not formula:
            formula = generate_name(atomic_fractions)
        return cls(cls._key, mass_fractions, atomic_fractions, formula)

    def __len__(self):
        return len(self.mass_fractions)

    def __contains__(self, z):
        return z in self.mass_fractions

    def __iter__(self):
        return iter(self.mass_fractions.keys())

    def __repr__(self):
        return '<{}({})>'.format(self.__class__.__name__, self.inner_repr())

    def __eq__(self, other):
        if not isinstance(other, self.__class__):
            return False

        if len(self) != len(other):
            return False

        for z in self.mass_fractions:
            if z not in other.mass_fractions:
                return False

            fraction = self.mass_fractions[z]
            other_fraction = other.mass_fractions[z]

            if not math.isclose(fraction, other_fraction, abs_tol=self.PRECISION):
                return False

        return True

    def __ne__(self, other):
        return not self == other

    def __hash__(self):
        out = []
        for z in sorted(self.mass_fractions):
            out.append(z)
            out.append(int(self.mass_fractions[z] / self.PRECISION))

        return hash(tuple(out))

    def __getstate__(self):
        return {'mass_fractions': dict(self.mass_fractions),
                'atomic_fractions': dict(self.atomic_fractions),
                'formula': self.formula}

    def __setstate__(self, state):
        self.mass_fractions = MappingProxyType(state.get('mass_fractions', {}))
        self.atomic_fractions = MappingProxyType(state.get('atomic_fractions', {}))
        self._formula = state.get('formula', '')

    def is_normalized(self):
        return math.isclose(sum(self.mass_fractions.values()), 1.0, abs_tol=self.PRECISION)

    def inner_repr(self):
        return ', '.join('{}: {:.4f}'.format(pyxray.element_symbol(z), mass_fraction) for z, mass_fraction in self.mass_fractions.items())

    @property
    def formula(self):
        return self._formula
Exemplo n.º 11
0
from types import MappingProxyType
from typing import TypeVar

from src.util.format import color

PERMIT_ERROR = MappingProxyType({
    202: "WARNING",  # order canceled
    504: "DEBUG",  # not connected -- always thrown on start
    2103: "WARNING",  # datafarm connection broken
    2104: "DEBUG",  # Market data farm connection is OK
    2106: "DEBUG",  # A historical data farm is connected.
    2108: "DEBUG",  # data hiccup
    2158: "DEBUG",  # A historical data farm is connected.
})

assert not set(PERMIT_ERROR.values()) - {"DEBUG", "INFO", "WARNING"}


# noinspection SpellCheckingInspection
def init_sec_logger() -> Logger:
    seclog = getLogger("FINSEC")
    seclog.setLevel(INFO)
    seclog.addHandler(StreamHandler(sys.stderr))
    seclog.handlers[0].setFormatter(
        Formatter(
            color("yellow", "{asctime} SEC-{levelname} ∷ {message}"),
            style="{",
        ))
    return seclog

Exemplo n.º 12
0
class Snapshot:
    """
    An immutable snapshot of contract data.
    """
    def __init__(self, creates: Mapping[ContractId, CreateEvent],
                 offset: Optional[str]):
        self._offset = offset
        self._creates = MappingProxyType(dict(creates))
        self._contracts = ContractDataView(self._creates)
        self._template_ids = {
            cid.value_type: matching_normalizations(cid.value_type)
            for cid in self._creates
        }

    @property
    def offset(self) -> Optional[str]:
        """
        The offset point in a stream that contains all of the creates without offsetting archives
        in this snapshot.

        This value is ``None`` when connecting to a ledger that is completely empty.
        """
        return self._offset

    def earliest_contract(
            self,
            template_id: Union[str, TypeConName],
            match: Optional[ContractMatch] = None) -> Optional[ContractData]:
        """
        Return the earliest contract in the Active Contract Set (in other words, _still_ active)
        that was created in the transaction stream that matches the specified filter, or ``None``
        if there are no matches.
        """
        ev = self.earliest_create(template_id, match)
        return ev.payload if ev is not None else None

    def matching_contracts(
        self,
        template_id: Union[str, TypeConName],
        match: Optional[ContractMatch] = None
    ) -> Mapping[ContractId, ContractData]:
        """"""
        return ContractDataView(self.matching_creates(template_id, match))

    def latest_contract(
            self,
            template_id: Union[str, TypeConName],
            match: Optional[ContractMatch] = None) -> Optional[ContractData]:
        """
        Return the contract that was created last in the transaction stream that matches the
        specified filter, or ``None`` if there are no matches.
        """
        ev = self.latest_create(template_id, match)
        return ev.payload if ev is not None else None

    def earliest_create(
            self,
            template_id: Union[str, TypeConName],
            match: Optional[ContractMatch] = None) -> Optional[CreateEvent]:
        """
        Return the earliest :class:`CreateEvent` in the Active Contract Set (in other words, the
        corresponding contract is _still_ active) that was created in the transaction stream that
        matches the specified filter, or ``None``
        if there are no matches.
        """
        wanted_template_ids = self._matching_template_ids(template_id)

        # in Python 3.9, dict values can be `reversed`; sadly we're not there yet
        for cev in reversed(list(self._creates.values())):
            if cev.contract_id.value_type in wanted_template_ids and is_match(
                    match, cev.payload):
                return cev
        return None

    def matching_creates(
        self,
        template_id: Union[str, TypeConName],
        match: Optional[ContractMatch] = None
    ) -> Mapping[ContractId, CreateEvent]:
        """
        Return the :class:`CreateEvent`s (indexed by :class:`ContractId`) whose contracts match the
        specified criteria.
        """
        wanted_template_ids = self._matching_template_ids(template_id)
        matches = {}
        for cid, cev in self._creates.items():
            if cev.contract_id.value_type in wanted_template_ids and is_match(
                    match, cev.payload):
                matches[cev.contract_id] = cev
        return MappingProxyType(matches)

    def latest_create(
            self,
            template_id: Union[str, TypeConName],
            match: Optional[ContractMatch] = None) -> Optional[CreateEvent]:
        """
        Return the contract that was created last in the transaction stream that matches the
        specified filter, or ``None`` if there are no matches.
        """
        wanted_template_ids = self._matching_template_ids(template_id)
        for cev in self._creates.values():
            if cev.contract_id.value_type in wanted_template_ids and is_match(
                    match, cev.payload):
                return cev
        return None

    def _matching_template_ids(
            self, template_id: Union[str,
                                     TypeConName]) -> Collection[TypeConName]:
        t = normalize(template_id)
        return {
            tid
            for tid, matches in self._template_ids.items() if t in matches
        }

    @property
    def contracts(self) -> Mapping[ContractId, ContractData]:
        """
        A read-only map of contract IDs to contract data.
        """
        return self._contracts

    @property
    def creates(self) -> Mapping[ContractId, CreateEvent]:
        """
        A map of contract IDs to :class:`CreateEvent`s that represent the current set of contracts
        in this ACS.

        :class:`CreateEvent`'s expose additional information, including signatories and observers.
        """
        return self._creates

    def __bool__(self) -> bool:
        return bool(self._creates)

    def __len__(self) -> int:
        return len(self._creates)

    def __repr__(self) -> str:
        return f"Snapshot(len={len(self)})"
Exemplo n.º 13
0
class Composition:
    """
    Defines a composition of a compound.

    To create a composition, use the class methods:

        - :meth:`from_pure`
        - :meth:`from_formula`
        - :meth:`from_mass_fractions`
        - :meth:`from_atomic_fractions`

    Use the following attributes to access the composition values:

        - :attr:`mass_fractions`: :class:`dict` where the keys are atomic numbers and the values weight fractions.
        - :attr:`atomic_fractions`: :class:`dict` where the keys are atomic numbers and the values atomic fractions.
        - :attr:`formula`: chemical formula

    The composition object is immutable, i.e. it cannot be modified once created.
    Equality can be checked.
    It is hashable.
    It can be pickled or copied.
    """

    _key = object()
    PRECISION = 0.000000001  # 1ppb

    def __init__(self, key, mass_fractions, atomic_fractions, formula):
        """
        Private constructor. It should never be used.
        """
        if key != Composition._key:
            raise TypeError("Composition cannot be created using constructor")
        if set(mass_fractions.keys()) != set(atomic_fractions.keys()):
            raise ValueError(
                "Mass and atomic fractions must have the same elements")

        self.mass_fractions = MappingProxyType(mass_fractions)
        self.atomic_fractions = MappingProxyType(atomic_fractions)
        self._formula = formula

    @classmethod
    def from_pure(cls, z):
        """
        Creates a pure composition.

        Args:
            z (int): atomic number
        """
        return cls(cls._key, {z: 1.0}, {z: 1.0}, pyxray.element_symbol(z))

    @classmethod
    def from_formula(cls, formula):
        """
        Creates a composition from a chemical formula.

        Args:
            formula (str): chemical formula
        """
        atomic_fractions = convert_formula_to_atomic_fractions(formula)
        return cls.from_atomic_fractions(atomic_fractions)

    @classmethod
    def from_mass_fractions(cls, mass_fractions, formula=None):
        """
        Creates a composition from a mass fraction :class:`dict`.

        Args:
            mass_fractions (dict): mass fraction :class:`dict`.
                The keys are atomic numbers and the values weight fractions.
                Wildcard are accepted, e.g. ``{5: '?', 25: 0.4}`` where boron
                will get a mass fraction of 0.6.
            formula (str): optional chemical formula for the composition.
                If ``None``, a formula will be generated for the composition.
        """
        mass_fractions = process_wildcard(mass_fractions)
        atomic_fractions = convert_mass_to_atomic_fractions(mass_fractions)
        if not formula:
            formula = generate_name(atomic_fractions)
        return cls(cls._key, mass_fractions, atomic_fractions, formula)

    @classmethod
    def from_atomic_fractions(cls, atomic_fractions, formula=None):
        """
        Creates a composition from an atomic fraction :class:`dict`.

        Args:
            atomic_fractions (dict): atomic fraction :class:`dict`.
                The keys are atomic numbers and the values atomic fractions.
                Wildcard are accepted, e.g. ``{5: '?', 25: 0.4}`` where boron
                will get a atomic fraction of 0.6.
            formula (str): optional chemical formula for the composition.
                If ``None``, a formula will be generated for the composition.
        """
        atomic_fractions = process_wildcard(atomic_fractions)
        mass_fractions = convert_atomic_to_mass_fractions(atomic_fractions)
        if not formula:
            formula = generate_name(atomic_fractions)
        return cls(cls._key, mass_fractions, atomic_fractions, formula)

    def __len__(self):
        return len(self.mass_fractions)

    def __contains__(self, z):
        return z in self.mass_fractions

    def __iter__(self):
        return iter(self.mass_fractions.keys())

    def __repr__(self):
        return "<{}({})>".format(self.__class__.__name__, self.inner_repr())

    def __eq__(self, other):
        if not isinstance(other, self.__class__):
            return False

        if len(self) != len(other):
            return False

        for z in self.mass_fractions:
            if z not in other.mass_fractions:
                return False

            fraction = self.mass_fractions[z]
            other_fraction = other.mass_fractions[z]

            if not math.isclose(
                    fraction, other_fraction, abs_tol=self.PRECISION):
                return False

        return True

    def __ne__(self, other):
        return not self == other

    def __hash__(self):
        out = []
        for z in sorted(self.mass_fractions):
            out.append(z)
            out.append(int(self.mass_fractions[z] / self.PRECISION))

        return hash(tuple(out))

    def __getstate__(self):
        return {
            "mass_fractions": dict(self.mass_fractions),
            "atomic_fractions": dict(self.atomic_fractions),
            "formula": self.formula,
        }

    def __setstate__(self, state):
        self.mass_fractions = MappingProxyType(state.get("mass_fractions", {}))
        self.atomic_fractions = MappingProxyType(
            state.get("atomic_fractions", {}))
        self._formula = state.get("formula", "")

    def is_normalized(self):
        return math.isclose(sum(self.mass_fractions.values()),
                            1.0,
                            abs_tol=self.PRECISION)

    def inner_repr(self):
        return ", ".join(
            "{}: {:.4f}".format(pyxray.element_symbol(z), mass_fraction)
            for z, mass_fraction in self.mass_fractions.items())

    @property
    def formula(self):
        return self._formula