Skip to content

Commit

Permalink
events: Refactor 'abc.ComplexEvent' to 'abc.Compound'
Browse files Browse the repository at this point in the history
In 8c54bb1 we refactored
all basic event classes, but we forgot to refactor 'abc.ComplexEvent'.
When refactoring 'SimpleEvent', it also makes sense to refactor
'ComplexEvent' (as the opposite between 'SimpleEvent' and 'CompexEvent'
created meaning before). As we dropped the '..Event' suffix in all event
class names, it also makes sense to drop it here for consistency.
'Compound' seems to be well suited as...

- it can be a noun and therefore makes sense as a single word without
  the '...Event' suffix

- it only says that it's composed of other events, but not in which way
  (consecutive or concurrent)

- 'compound event' seems to be a used term in probability theory to
  differentiate it from simple events (e.g. to describe an event that
  consist of multiple smaller events) [1]

- 'Compound' also start with 'C' (as 'Consecution', 'Concurrence' and
  'Chronon'), which is nice :)

[1] https://www3.nd.edu/~apilking/Math10120/Lectures/Solutions/Topic10.pdf
  • Loading branch information
levinericzimmermann committed Apr 8, 2024
1 parent 744b5c2 commit e7567d4
Show file tree
Hide file tree
Showing 10 changed files with 64 additions and 64 deletions.
4 changes: 2 additions & 2 deletions mutwo/core_converters/abc.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This file is part of mutwo, ecosystem for time-based arts.
#
# Copyright (C) 2020-2023
# Copyright (C) 2020-2024
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -213,5 +213,5 @@ def _convert_event(
event_to_convert: core_events.abc.Event,
absolute_time: core_parameters.abc.Duration | float | int,
depth: int = 0,
) -> core_events.abc.ComplexEvent[core_events.abc.Event]:
) -> core_events.abc.Compound[core_events.abc.Event]:
return super()._convert_event(event_to_convert, absolute_time, depth)
4 changes: 2 additions & 2 deletions mutwo/core_converters/tempos.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def _convert_event(
event_to_convert: core_events.abc.Event,
absolute_time: core_parameters.abc.Duration | float | int,
depth: int = 0,
) -> core_events.abc.ComplexEvent[core_events.abc.Event]:
) -> core_events.abc.Compound[core_events.abc.Event]:
tempo = core_parameters.FlexTempo.from_parameter(event_to_convert.tempo)
is_tempo_effectless = tempo.is_static and tempo.value_tuple[0] == 60
if self._apply_converter_on_events_tempo and not is_tempo_effectless:
Expand Down Expand Up @@ -225,7 +225,7 @@ def _convert_event(
event_to_convert: core_events.abc.Event,
absolute_time: core_parameters.abc.Duration | float | int,
depth: int = 0,
) -> core_events.abc.ComplexEvent[core_events.abc.Event]:
) -> core_events.abc.Compound[core_events.abc.Event]:
if (self._skip_level_count is None or self._skip_level_count < depth) and (
self._maxima_depth_count is None or depth < self._maxima_depth_count
):
Expand Down
74 changes: 37 additions & 37 deletions mutwo/core_events/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@
from mutwo import core_utilities


__all__ = ("Event", "ComplexEvent")
__all__ = ("Event", "Compound")


class Event(core_utilities.MutwoObject, abc.ABC):
"""Abstract Event-Object
:param tempo: An envelope which describes the dynamic tempo of an event.
:param tag: The name of the event. This can be used to find the event
inside a :class:`ComplexEvent`.
inside a :class:`Compound`.
"""

# It looks tempting to drop the 'tempo' attribute of events.
Expand Down Expand Up @@ -92,15 +92,15 @@ class Event(core_utilities.MutwoObject, abc.ABC):
# something that belongs to a nested event (e.g. a 'Consecution' or
# a 'Concurrence'). But with the duration=seconds approach such a
# tempo trajectory couldn't be persistently mapped to a nested event,
# because the duration of a complex event isn't a statically mapped and
# because the duration of a Compound isn't a statically mapped and
# available entity, but ephemerally and dynamically calculated when
# needed. When the duration of a complex event is set, it becomes
# needed. When the duration of a Compound is set, it becomes
# propagated to the duration of its children until it finds a leaf that
# statically declares its duration and then it's lost. So in order to
# have a persistently available tempo trajectory on a complex event
# have a persistently available tempo trajectory on a Compound
# that can be read and modified-in-place, we need an extra tempo
# attribute. Otherwise we would break the rule that the duration of
# a complex event is only a sum or max of its children duration.
# a Compound is only a sum or max of its children duration.
#
# Due to these reasons, that describe new complexities by switching to a
# 'duration=seconds' model, we should stick to the beats/tempo
Expand Down Expand Up @@ -347,7 +347,7 @@ def set_parameter(
is only called once for each Event. So multiple references
of the same event will be ignored. This behaviour ensures,
that on a big scale level each item inside the
:class:`mutwo.core_events.abc.ComplexEvent` is treated equally
:class:`mutwo.core_events.abc.Compound` is treated equally
(so for instance the duration of each item is doubled, and
nor for some doubled and for those with references which
appear twice quadrupled).
Expand Down Expand Up @@ -397,7 +397,7 @@ def mutate_parameter(
only be called once for each Event. So multiple references
of the same event will be ignored. This behaviour ensures,
that on a big scale level each item inside the
:class:`mutwo.core_events.abc.ComplexEvent` is treated equally
:class:`mutwo.core_events.abc.Compound` is treated equally
(so for instance the duration of each item is doubled, and
nor for some doubled and for those with references which
appear twice quadrupled).
Expand Down Expand Up @@ -551,7 +551,7 @@ def split_at(
# FIXME(This Event can be initialised (no abstract error).
# Please see the following issue for comparison:
# https://bugs.python.org/issue35815
class ComplexEvent(Event, abc.ABC, list[T], typing.Generic[T]):
class Compound(Event, abc.ABC, list[T], typing.Generic[T]):
"""Abstract Event-Object, which contains other Event-Objects."""

_short_name_length = 4
Expand All @@ -575,14 +575,14 @@ def __init_subclass__(
# content of the parent class is available and we always have to explicitly
# make it available with something like:
#
# class MyComplexEvent(ComplexEvent):
# class MyCompound(Compound):
# _class_specific_side_attribute_tuple = (("new_attribute",) +
# ComplexEvent._class_specific_side_attribute_tuple)
# Compound._class_specific_side_attribute_tuple)
#
# With __init_subclass__ we can simply write:
#
# class MyComplexEvent(
# ComplexEvent,
# class MyCompound(
# Compound,
# class_specific_side_attribute_tuple = ("new_attribute",)
# ): pass
#
Expand All @@ -596,12 +596,12 @@ def __init_subclass__(
# magic methods #
# ###################################################################### #

def __add__(self, event: list[T]) -> ComplexEvent[T]:
def __add__(self, event: list[T]) -> Compound[T]:
e = self.empty_copy()
e.extend(super().__add__(event))
return e

def __mul__(self, factor: int) -> ComplexEvent[T]:
def __mul__(self, factor: int) -> Compound[T]:
e = self.empty_copy()
e.extend(super().__mul__(factor))
return e
Expand All @@ -611,7 +611,7 @@ def __getitem__(self, index_or_slice_or_tag: int) -> T:
...

@typing.overload
def __getitem__(self, index_or_slice_or_tag: slice) -> ComplexEvent[T]:
def __getitem__(self, index_or_slice_or_tag: slice) -> Compound[T]:
...

@typing.overload
Expand All @@ -620,7 +620,7 @@ def __getitem__(self, index_or_slice_or_tag: str) -> T:

def __getitem__(
self, index_or_slice_or_tag: int | slice | str
) -> T | ComplexEvent[T]:
) -> T | Compound[T]:
try:
event = super().__getitem__(index_or_slice_or_tag)
except TypeError as error:
Expand Down Expand Up @@ -714,7 +714,7 @@ def __str_content__(self):
@Event.duration.setter # type: ignore
def duration(self, duration: core_parameters.abc.Duration.Type):
if not self: # If empty and duration == 0, we'd run into ZeroDivision
raise core_utilities.CannotSetDurationOfEmptyComplexEvent()
raise core_utilities.CannotSetDurationOfEmptyCompound()

durf = core_parameters.abc.Duration.from_any(duration).beat_count
if (old_durf := self.duration.beat_count) != 0:
Expand All @@ -735,9 +735,9 @@ def f(event_duration: core_parameters.abc.Duration):

# Keep private because:
# (1) Then we can later change the internal implementation of
# ComplexEvent (for instance: no longer inheriting from list).
# Compound (for instance: no longer inheriting from list).
# (2) It's not sure if tag_to_index is valuable for end users of
# ComplexEvent
# Compound
def _tag_to_index(self, tag: str) -> int:
# Find index of an event by its tag.
# param tag: The `tag` of the event which shall be found.
Expand All @@ -759,7 +759,7 @@ def _assert_start_in_range(

def _apply_once_per_event(
self, method_name: str, *args, id_set: set[int], **kwargs
) -> ComplexEvent[T]:
) -> Compound[T]:
for e in self:
if (e_id := id(e)) not in id_set:
id_set.add(e_id)
Expand All @@ -772,7 +772,7 @@ def _set_parameter( # type: ignore
object_or_function: typing.Callable[[typing.Any], typing.Any] | typing.Any,
set_unassigned_parameter: bool,
id_set: set[int],
) -> ComplexEvent[T]:
) -> Compound[T]:
return self._apply_once_per_event(
"_set_parameter",
parameter_name,
Expand All @@ -786,15 +786,15 @@ def _mutate_parameter( # type: ignore
parameter_name: str,
function: typing.Callable[[typing.Any], None] | typing.Any,
id_set: set[int],
) -> ComplexEvent[T]:
) -> Compound[T]:
return self._apply_once_per_event(
"_mutate_parameter",
parameter_name,
function,
id_set=id_set,
)

def _concatenate_tempo(self, other: ComplexEvent):
def _concatenate_tempo(self, other: Compound):
"""Concatenate the tempo of event with tempo of other event.
If we concatenate events on the time axis, we also want to
Expand Down Expand Up @@ -842,15 +842,15 @@ def _concatenate_tempo(self, other: ComplexEvent):
# public methods #
# ###################################################################### #

def destructive_copy(self) -> ComplexEvent[T]:
def destructive_copy(self) -> Compound[T]:
empty_copy = self.empty_copy()
empty_copy.extend([event.destructive_copy() for event in self])
return empty_copy

def empty_copy(self) -> ComplexEvent[T]:
"""Make a copy of the `ComplexEvent` without any child events.
def empty_copy(self) -> Compound[T]:
"""Make a copy of the `Compound` without any child events.
This method is useful if one wants to copy an instance of :class:`ComplexEvent`
This method is useful if one wants to copy an instance of :class:`Compound`
and make sure that all side attributes (e.g. any assigned properties specific
to the respective subclass) get saved.
Expand Down Expand Up @@ -918,7 +918,7 @@ def get_parameter(

def remove_by( # type: ignore
self, condition: typing.Callable[[Event], bool]
) -> ComplexEvent[T]:
) -> Compound[T]:
"""Condition-based deletion of child events.
:param condition: Function which takes a :class:`Event` and returns ``True``
Expand Down Expand Up @@ -950,7 +950,7 @@ def tie_by( # type: ignore
),
event_type_to_examine: typing.Type[Event] = Event,
event_to_remove: bool = True,
) -> ComplexEvent[T]:
) -> Compound[T]:
"""Condition-based deletion of neighboring child events.
:param condition: Function which compares two neighboring
Expand Down Expand Up @@ -1010,7 +1010,7 @@ def tie_by_if_available(e: Event):

return self

def metrize(self) -> ComplexEvent:
def metrize(self) -> Compound:
metrized_event = self._event_to_metrized_event(self)
self.tempo = metrized_event.tempo
self[:] = metrized_event[:]
Expand All @@ -1023,14 +1023,14 @@ def metrize(self) -> ComplexEvent:
@abc.abstractmethod
def squash_in(
self, start: core_parameters.abc.Duration.Type, event_to_squash_in: Event
) -> typing.Optional[ComplexEvent[T]]:
) -> typing.Optional[Compound[T]]:
"""Time-based insert of a new event with overriding given event.
:param start: Absolute time where the event shall be inserted.
:param event_to_squash_in: the event that shall be squashed into
the present event.
Unlike `ComplexEvent.slide_in` the events duration won't change.
Unlike `Compound.slide_in` the events duration won't change.
If there is already an event at `start` this event will be shortened
or removed.
Expand All @@ -1045,14 +1045,14 @@ def squash_in(
@abc.abstractmethod
def slide_in(
self, start: core_parameters.abc.Duration.Type, event_to_slide_in: Event
) -> ComplexEvent[T]:
) -> Compound[T]:
"""Time-based insert of a new event into the present event.
:param start: Absolute time where the event shall be inserted.
:param event_to_slide_in: the event that shall be slide into
the present event.
Unlike `ComplexEvent.squash_in` the events duration will be prolonged
Unlike `Compound.squash_in` the events duration will be prolonged
by the event which is added. If there is an event at `start` the
event will be split into two parts, but it won't be shortened or
processed in any other way.
Expand All @@ -1068,7 +1068,7 @@ def slide_in(
@abc.abstractmethod
def split_child_at(
self, absolute_time: core_parameters.abc.Duration.Type
) -> typing.Optional[ComplexEvent[T]]:
) -> typing.Optional[Compound[T]]:
"""Split child event in two events at :attr:`absolute_time`.
:param absolute_time: where child event shall be split
Expand All @@ -1089,7 +1089,7 @@ def extend_until(
typing.Callable[[core_parameters.abc.Duration], Event]
] = None,
prolong_chronon: bool = True,
) -> ComplexEvent:
) -> Compound:
"""Prolong event until at least `duration` by appending an empty event.
:param duration: Until which duration the event shall be extended.
Expand Down
8 changes: 4 additions & 4 deletions mutwo/core_events/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ def cut_off( # type: ignore
T = typing.TypeVar("T", bound=core_events.abc.Event)


class Consecution(core_events.abc.ComplexEvent, typing.Generic[T]):
class Consecution(core_events.abc.Compound, typing.Generic[T]):
"""A :class:`Consecution`hosts events that take place one after the other."""

# ###################################################################### #
Expand Down Expand Up @@ -443,7 +443,7 @@ def _abstf_tuple_and_dur(
# properties #
# ###################################################################### #

@core_events.abc.ComplexEvent.duration.getter
@core_events.abc.Compound.duration.getter
def duration(self) -> core_parameters.abc.Duration:
try:
return functools.reduce(operator.add, (e.duration for e in self))
Expand Down Expand Up @@ -737,7 +737,7 @@ def extend_until(
return self


class Concurrence(core_events.abc.ComplexEvent, typing.Generic[T]):
class Concurrence(core_events.abc.Compound, typing.Generic[T]):
"""A :class:`Concurrence` hosts events that take place at the same time."""

# ###################################################################### #
Expand Down Expand Up @@ -808,7 +808,7 @@ def _make_event_slice_tuple(
# properties #
# ###################################################################### #

@core_events.abc.ComplexEvent.duration.getter
@core_events.abc.Compound.duration.getter
def duration(self) -> core_parameters.abc.Duration:
try:
return max(e.duration for e in self)
Expand Down
4 changes: 2 additions & 2 deletions mutwo/core_events/configurations.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This file is part of mutwo, ecosystem for time-based arts.
#
# Copyright (C) 2020-2023
# Copyright (C) 2020-2024
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -28,7 +28,7 @@ def __simpleEvent():

DEFAULT_DURATION_TO_WHITE_SPACE = lambda duration: __simpleEvent()(duration)
"""Default conversion for parameter `duration_to_white_space` in
:func:`mutwo.core_events.abc.ComplexEvent.extend_until`. This simply
:func:`mutwo.core_events.abc.Compound.extend_until`. This simply
returns a :class:`mutwo.core_events.Chronon` with the given
duration."""

Expand Down
2 changes: 1 addition & 1 deletion mutwo/core_parameters/configurations.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
with version 0.28.1 to avoid floating point rounding errors which
could occur in all duration related methods of the different event
classes (as it can happen in for instance the
:func:`mutwo.core_events.abc.ComplexEvent.squash_in` method or
:func:`mutwo.core_events.abc.Compound.squash_in` method or
the :func:`mutwo.core_events.abc.Event.cut_off` method)."""

DEFAULT_REFERENCE: fractions.Fraction = fractions.Fraction(1, 4)
Expand Down
Loading

0 comments on commit e7567d4

Please sign in to comment.