Skip to content

Commit

Permalink
Refactor event classes: make meaning more explicit
Browse files Browse the repository at this point in the history
This is the largest class refactor since the initialization of 'mutwo'.
Let's pray it will be last one. Summarized it refactors:

    SimpleEvent         =>      Chronon
    SequentialEvent     =>      Consecution
    SimultaneousEvent   =>      Concurrence
    TempoEvent          =>      TempoChronon

Why?

'SequentialEvent' and 'SimultaneousEvent' are meaningless names:
an event is sequential to what? An event is simultaneous to what?
What is actually meant is: the events inside the event are happening
simultaneously / sequentially. Therefore it would be more precise
to describe 'SequentialEvent' as 'SequencedEvents' (suggested by @mdedwards)
or 'EventSequence'. But these names stress out too much the children of
the object and don't emphasize enough that a 'SequentialEvent' is an
event itself.

The name 'Event' may not be necessary: the context is already clear from
the 'core_events' module. Similarity in 'mutwos' early days converters
were named 'XConverter', but later simplified and renamed more explicit to
'X_To_Y' (see #18).

So alternative names could be:

(1) Sequence or Consecution for 'SequentialEvent'
(2) Simultaneity or Concurrence for 'SimultaneousEvent'

Regarding (1): 'Sequence' already has a different meaning in Python [1], [2].
Therefore it may be wiser to use 'Consecution'. According to
stackexchange 'consecutive' rather emphasizes that successive events
aren't interrupted [3]. This is true in 'mutwo', as mutwo events don't
know entry delays.

Regarding (2): Stackexchange says simultaneous events
have a stronger connection to each other than concurrent events
(which are more 'random') [4]. Since randomness is a super set of
intention (and I'm a Cage advocate) I'd prefer 'Concurrence'.

Finally when choosing more explicit, descriptive names for the complex
events, we could also choose a more explicit name for 'SimpleEvent'.
Initially I thought of 'Atom', because a 'SimpleEvent' isn't
describable by smaller elements, but is already the smallest element
itself. But there is even a more beautiful word: Chronon [5],
a discrete unit of the floating time. This is exactly what a
'SimpleEvent' (or 'NoteLike') denotes: a discrete passing of time.

[1] https://docs.python.org/3/c-api/sequence.html
[2] https://docs.python.org/3/library/collections.abc.html#collections.abc.Sequence
[3] https://english.stackexchange.com/questions/490293/is-consecutive-a-subset-of-sequential
[4] https://ell.stackexchange.com/questions/297831/difference-between-simultaneously-concurrently-and-at-the-same-time
[5] https://en.wikipedia.org/wiki/Chronon

---

In order to refactor fellow-up 'mutwo' projects an ugly,
but effective bash script may be used:

```

d=$1

find $d -type f  | xargs -I {}  sed -i 's/SimpleEvent/Chronon/g' {}
find $d -type f  | xargs -I {}  sed -i 's/SequentialEvent/Consecution/g' {}
find $d -type f  | xargs -I {}  sed -i 's/SimultaneousEvent/Concurrence/g' {}

find $d -type f  | xargs -I {}  sed -i 's/TempoEvent/TempoChronon/g' {}
find $d -type f  | xargs -I {}  sed -i 's/tempo_event/tempo_chronon/g' {}

find $d -type f  | xargs -I {}  sed -i 's/simple_event/chronon/g' {}
find $d -type f  | xargs -I {}  sed -i 's/simple\ event/chronon/g' {}
find $d -type f  | xargs -I {}  sed -i 's/sequential_event/consecution/g' {}
find $d -type f  | xargs -I {}  sed -i 's/sequential\ event/consecution/g' {}
find $d -type f  | xargs -I {}  sed -i 's/simultaneous\ event/concurrence/g' {}
```
  • Loading branch information
levinericzimmermann committed Dec 10, 2023
1 parent 51cf21f commit 8c54bb1
Show file tree
Hide file tree
Showing 19 changed files with 875 additions and 873 deletions.
92 changes: 46 additions & 46 deletions mutwo/core_converters/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,12 @@ class EventConverter(Converter):
method). Converting mutwo event often involves the same pattern:
due to the nested structure of an Event, the converter has
to iterate through the different layers until it reaches leaves
(any class that inherits from :class:`mutwo.core_events.SimpleEvent`).
(any class that inherits from :class:`mutwo.core_events.Chronon`).
This common iteration process and the different time treatment
between :class:`mutwo.core_events.SequentialEvent` and
:class:`mutwo.core_events.SimultaneousEvent` are implemented in
between :class:`mutwo.core_events.Consecution` and
:class:`mutwo.core_events.Concurrence` are implemented in
:class:`EventConverter`. For writing a new EventConverter class,
one only has to override the abstract method :func:`_convert_simple_event`
one only has to override the abstract method :func:`_convert_chronon`
and the abstract method :func:`convert` (where one will perhaps call
:func:`_convert_event`.).
Expand All @@ -70,7 +70,7 @@ class EventConverter(Converter):
>>> from mutwo import core_converters
>>> class DurationPrintConverter(core_converters.abc.EventConverter):
... def _convert_simple_event(self, event_to_convert, absolute_entry_delay):
... def _convert_chronon(self, event_to_convert, absolute_entry_delay):
... return "{}: {}".format(absolute_entry_delay, event_to_convert.duration),
... def convert(self, event_to_convert):
... data_per_event = self._convert_event(event_to_convert, 0)
Expand All @@ -79,11 +79,11 @@ class EventConverter(Converter):
>>> import random
>>> from mutwo import core_events
>>> random.seed(100)
>>> random_event = core_events.SimultaneousEvent(
>>> random_event = core_events.Concurrence(
... [
... core_events.SequentialEvent(
... core_events.Consecution(
... [
... core_events.SimpleEvent(random.uniform(0.5, 2))
... core_events.Chronon(random.uniform(0.5, 2))
... for _ in range(random.randint(2, 5))
... ]
... )
Expand All @@ -99,35 +99,35 @@ class EventConverter(Converter):
"""

@abc.abstractmethod
def _convert_simple_event(
def _convert_chronon(
self,
event_to_convert: core_events.SimpleEvent,
event_to_convert: core_events.Chronon,
absolute_entry_delay: core_parameters.abc.Duration | float | int,
depth: int = 0,
) -> typing.Sequence[typing.Any]:
"""Convert instance of :class:`mutwo.core_events.SimpleEvent`."""
"""Convert instance of :class:`mutwo.core_events.Chronon`."""

def _convert_simultaneous_event(
def _convert_concurrence(
self,
simultaneous_event: core_events.SimultaneousEvent,
concurrence: core_events.Concurrence,
absolute_entry_delay: core_parameters.abc.Duration | float | int,
depth: int = 0,
) -> typing.Sequence[typing.Any]:
"""Convert instance of :class:`mutwo.core_events.SimultaneousEvent`."""
"""Convert instance of :class:`mutwo.core_events.Concurrence`."""
d: list[tuple[typing.Any]] = []
for e in simultaneous_event:
for e in concurrence:
d.extend(self._convert_event(e, absolute_entry_delay, depth + 1))
return tuple(d)

def _convert_sequential_event(
def _convert_consecution(
self,
sequential_event: core_events.SequentialEvent,
consecution: core_events.Consecution,
absolute_entry_delay: core_parameters.abc.Duration | float | int,
depth: int = 0,
) -> typing.Sequence[typing.Any]:
"""Convert instance of :class:`mutwo.core_events.SequentialEvent`."""
"""Convert instance of :class:`mutwo.core_events.Consecution`."""
d: list[tuple[typing.Any]] = []
for t, e in zip(sequential_event.absolute_time_tuple, sequential_event):
for t, e in zip(consecution.absolute_time_tuple, consecution):
d.extend(self._convert_event(e, t + absolute_entry_delay, depth + 1))
return tuple(d)

Expand All @@ -142,19 +142,19 @@ def _convert_event(
The method calls different subroutines depending on whether
the passed event either are instances from:
1. :class:`mutwo.core_events.SimpleEvent` or
2. :class:`mutwo.core_events.SequentialEvent` or
3. :class:`mutwo.core_events.SimultaneousEvent`.
1. :class:`mutwo.core_events.Chronon` or
2. :class:`mutwo.core_events.Consecution` or
3. :class:`mutwo.core_events.Concurrence`.
"""
e = event_to_convert
t = core_events.configurations.UNKNOWN_OBJECT_TO_DURATION(absolute_entry_delay)
match e:
case core_events.SequentialEvent():
f = self._convert_sequential_event
case core_events.SimultaneousEvent():
f = self._convert_simultaneous_event
case core_events.SimpleEvent():
f = self._convert_simple_event
case core_events.Consecution():
f = self._convert_consecution
case core_events.Concurrence():
f = self._convert_concurrence
case core_events.Chronon():
f = self._convert_chronon
case _:
raise TypeError(
f"Can't convert object '{event_to_convert}' of type "
Expand All @@ -176,37 +176,37 @@ class SymmetricalEventConverter(EventConverter):
"""

@abc.abstractmethod
def _convert_simple_event(
def _convert_chronon(
self,
event_to_convert: core_events.SimpleEvent,
event_to_convert: core_events.Chronon,
absolute_entry_delay: core_parameters.abc.Duration | float | int,
depth: int = 0,
) -> core_events.SimpleEvent:
"""Convert instance of :class:`mutwo.core_events.SimpleEvent`."""
) -> core_events.Chronon:
"""Convert instance of :class:`mutwo.core_events.Chronon`."""

def _convert_simultaneous_event(
def _convert_concurrence(
self,
simultaneous_event: core_events.SimultaneousEvent,
concurrence: core_events.Concurrence,
absolute_entry_delay: core_parameters.abc.Duration | float | int,
depth: int = 0,
) -> core_events.SimultaneousEvent:
"""Convert instance of :class:`mutwo.core_events.SimultaneousEvent`."""
sim: core_events.SimultaneousEvent = simultaneous_event.empty_copy()
for e in simultaneous_event:
) -> core_events.Concurrence:
"""Convert instance of :class:`mutwo.core_events.Concurrence`."""
sim: core_events.Concurrence = concurrence.empty_copy()
for e in concurrence:
sim.append(self._convert_event(e, absolute_entry_delay, depth + 1))
return sim

def _convert_sequential_event(
def _convert_consecution(
self,
sequential_event: core_events.SequentialEvent,
consecution: core_events.Consecution,
absolute_entry_delay: core_parameters.abc.Duration | float | int,
depth: int = 0,
) -> core_events.SequentialEvent:
"""Convert instance of :class:`mutwo.core_events.SequentialEvent`."""
seq: core_events.SequentialEvent = sequential_event.empty_copy()
for t, e in zip(sequential_event.absolute_time_tuple, sequential_event):
seq.append(self._convert_event(e, t + absolute_entry_delay, depth + 1))
return seq
) -> core_events.Consecution:
"""Convert instance of :class:`mutwo.core_events.Consecution`."""
cons: core_events.Consecution = consecution.empty_copy()
for t, e in zip(consecution.absolute_time_tuple, consecution):
cons.append(self._convert_event(e, t + absolute_entry_delay, depth + 1))
return cons

def _convert_event(
self,
Expand Down
62 changes: 31 additions & 31 deletions mutwo/core_converters/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""Standardization for transformations between parameters and simple events
"""Standardization for transformations between parameters and chronons
Adds classes to allow transformations in two directions:
1. Extract data (e.g. mutwo parameters) from simple events
2. Convert data (e.g. mutwo parameters) to simple events
1. Extract data (e.g. mutwo parameters) from chronons
2. Convert data (e.g. mutwo parameters) to chronons
"""

import typing
Expand All @@ -31,20 +31,20 @@


__all__ = (
"SimpleEventToAttribute",
"ChrononToAttribute",
"MutwoParameterDict",
"MutwoParameterDictToKeywordArgument",
"MutwoParameterDictToDuration",
"MutwoParameterDictToSimpleEvent",
"MutwoParameterDictToChronon",
"UnknownObjectToObject",
)


class SimpleEventToAttribute(core_converters.abc.Converter):
"""Extract from a simple event an attribute.
class ChrononToAttribute(core_converters.abc.Converter):
"""Extract from a chronon an attribute.
:param attribute_name: The name of the attribute which is fetched
from a :class:`mutwo.core_events.SimpleEvent`.
from a :class:`mutwo.core_events.Chronon`.
:param exception_value: This value is returned in case an `AttributeError`
raises .
"""
Expand All @@ -53,36 +53,36 @@ def __init__(self, attribute_name: str, exception_value: typing.Any):
self._attribute_name = attribute_name
self._exception_value = exception_value

def convert(self, simple_event_to_convert: core_events.SimpleEvent) -> typing.Any:
"""Extract from a :class:`mutwo.core_events.SimpleEvent` an attribute.
def convert(self, chronon_to_convert: core_events.Chronon) -> typing.Any:
"""Extract from a :class:`mutwo.core_events.Chronon` an attribute.
:param simple_event_to_convert: The :class:`mutwo.core_events.SimpleEvent`
:param chronon_to_convert: The :class:`mutwo.core_events.Chronon`
from which an attribute shall be extracted.
:type simple_event_to_convert: mutwo.core_events.SimpleEvent
:type chronon_to_convert: mutwo.core_events.Chronon
**Example:**
>>> from mutwo import core_converters
>>> from mutwo import core_events
>>> simple_event = core_events.SimpleEvent(duration=10.0)
>>> simple_event_to_duration = core_converters.SimpleEventToAttribute(
>>> chronon = core_events.Chronon(duration=10.0)
>>> chronon_to_duration = core_converters.ChrononToAttribute(
... 'duration', 0
... )
>>> simple_event_to_duration.convert(simple_event)
>>> chronon_to_duration.convert(chronon)
DirectDuration(10.0)
>>> simple_event_to_pasta = core_converters.SimpleEventToAttribute(
>>> chronon_to_pasta = core_converters.ChrononToAttribute(
... 'pasta', 'spaghetti'
... )
>>> simple_event_to_pasta.convert(simple_event)
>>> chronon_to_pasta.convert(chronon)
'spaghetti'
>>> simple_event.pasta = 'tagliatelle'
>>> simple_event_to_pasta.convert(simple_event)
>>> chronon.pasta = 'tagliatelle'
>>> chronon_to_pasta.convert(chronon)
'tagliatelle'
"""

return core_utilities.call_function_except_attribute_error(
lambda simple_event: getattr(simple_event, self._attribute_name),
simple_event_to_convert,
lambda chronon: getattr(chronon, self._attribute_name),
chronon_to_convert,
self._exception_value,
)

Expand Down Expand Up @@ -159,36 +159,36 @@ def __init__(
)


class MutwoParameterDictToSimpleEvent(core_converters.abc.Converter):
"""Convert a dict of mutwo parameters to a :class:`mutwo.core_events.SimpleEvent`
class MutwoParameterDictToChronon(core_converters.abc.Converter):
"""Convert a dict of mutwo parameters to a :class:`mutwo.core_events.Chronon`
:param mutwo_parameter_dict_to_keyword_argument_sequence: A sequence of
:class:`MutwoParameterDictToKeywordArgument`. If set to `None`
a sequence with :class:`MutwoParameterDictToDuration` will be created.
Default to `None`.
:type mutwo_parameter_dict_to_keyword_argument_sequence: typing.Optional[typing.Sequence[MutwoParameterDictToKeywordArgument]]
:param simple_event_class: Default to :class:`mutwo.core_events.SimpleEvent`.
:type simple_event_class: typing.Type[core_events.SimpleEvent]
:param chronon_class: Default to :class:`mutwo.core_events.Chronon`.
:type chronon_class: typing.Type[core_events.Chronon]
"""

def __init__(
self,
mutwo_parameter_dict_to_keyword_argument_sequence: typing.Optional[
typing.Sequence[MutwoParameterDictToKeywordArgument]
] = None,
simple_event_class: typing.Type[
core_events.SimpleEvent
] = core_events.SimpleEvent,
chronon_class: typing.Type[
core_events.Chronon
] = core_events.Chronon,
):
self._mutwo_parameter_dict_to_keyword_argument_sequence = (
mutwo_parameter_dict_to_keyword_argument_sequence
or (MutwoParameterDictToDuration(),)
)
self._simple_event_class = simple_event_class
self._chronon_class = chronon_class

def convert(
self, mutwo_parameter_dict_to_convert: MutwoParameterDict
) -> core_events.SimpleEvent:
) -> core_events.Chronon:
keyword_argument_dict = {}
for (
mutwo_parameter_dict_to_keyword_argument
Expand All @@ -199,7 +199,7 @@ def convert(
if keyword_argument_or_none:
keyword, argument = keyword_argument_or_none
keyword_argument_dict.update({keyword: argument})
return self._simple_event_class(**keyword_argument_dict)
return self._chronon_class(**keyword_argument_dict)


T = typing.TypeVar("T")
Expand Down
18 changes: 9 additions & 9 deletions mutwo/core_converters/tempos.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,14 +229,14 @@ def _integrate(
] = self._beat_length_in_seconds_envelope.integrate_interval(start, end)
return i

def _convert_simple_event(
def _convert_chronon(
self,
simple_event: core_events.SimpleEvent,
chronon: core_events.Chronon,
absolute_entry_delay: core_parameters.abc.Duration | float | int,
depth: int = 0,
) -> tuple[typing.Any, ...]:
simple_event.duration = self._integrate(
absolute_entry_delay, absolute_entry_delay + simple_event.duration
chronon.duration = self._integrate(
absolute_entry_delay, absolute_entry_delay + chronon.duration
)
return tuple([])

Expand Down Expand Up @@ -296,9 +296,9 @@ def convert(self, event_to_convert: core_events.abc.Event) -> core_events.abc.Ev
... [[0, core_parameters.DirectTempoPoint(60)], [3, 60], [3, 30], [5, 50]],
... )
>>> my_tempo_converter = core_converters.TempoConverter(tempo_envelope)
>>> my_events = core_events.SequentialEvent([core_events.SimpleEvent(d) for d in (3, 2, 5)])
>>> my_events = core_events.Consecution([core_events.Chronon(d) for d in (3, 2, 5)])
>>> my_tempo_converter.convert(my_events)
SequentialEvent([SimpleEvent(duration=DirectDuration(3.0)), SimpleEvent(duration=DirectDuration(3.2)), SimpleEvent(duration=DirectDuration(6.0))])
Consecution([Chronon(duration=DirectDuration(3.0)), Chronon(duration=DirectDuration(3.2)), Chronon(duration=DirectDuration(6.0))])
"""
copied_event_to_convert = event_to_convert.destructive_copy()
self._convert_event(copied_event_to_convert, core_parameters.DirectDuration(0))
Expand All @@ -316,12 +316,12 @@ def __init__(
self._skip_level_count = skip_level_count
self._maxima_depth_count = maxima_depth_count

def _convert_simple_event(
def _convert_chronon(
self,
event_to_convert: core_events.SimpleEvent,
event_to_convert: core_events.Chronon,
absolute_entry_delay: core_parameters.abc.Duration | float | int,
depth: int = 0,
) -> core_events.SimpleEvent:
) -> core_events.Chronon:
return event_to_convert

def _convert_event(
Expand Down
6 changes: 3 additions & 3 deletions mutwo/core_events/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
The most often used classes are:
- :class:`mutwo.core_events.SimpleEvent`: the leaf or the node of a tree
- :class:`mutwo.core_events.SequentialEvent`: a sequence of other events
- :class:`mutwo.core_events.SimultaneousEvent`: a simultaneous set of other events
- :class:`mutwo.core_events.Chronon`: the leaf or the node of a tree
- :class:`mutwo.core_events.Consecution`: a sequence of other events
- :class:`mutwo.core_events.Concurrence`: a simultaneous set of other events
Further more complex Event classes with more relevant attributes
can be generated through inheriting from basic classes.
Expand Down
Loading

0 comments on commit 8c54bb1

Please sign in to comment.