from typing import Optional, Union
import abjad
from .. import get
from .extract_trivial_tuplets import (
extract_trivial_tuplets as extract_trivial_tuplets_function,
)
from .merge_partial_tuplets import (
merge_partial_tuplets as merge_partial_tuplets_function,
)
from .prettify_rewrite_meter import (
prettify_rewrite_meter as prettify_rewrite_meter_function,
)
[docs]def auto_rewrite_meter(container: abjad.Container,
meter_list: Optional[list[Union[abjad.Meter,
abjad.TimeSignature,
]]] = None,
*,
prettify_rewrite_meter: bool = True,
extract_trivial_tuplets: bool = True,
fuse_across_groups_of_beats: bool = True,
fuse_quadruple_meter: bool = True,
fuse_triple_meter: bool = True,
boundary_depth: Optional[int] = None,
maximum_dot_count: Optional[int] = None,
rewrite_tuplets: bool = True,
merge_partial_tuplets: bool = True,
split_quadruple_meter: bool = True,
) -> None:
r"""Mutates an input container (of type |abjad.Container| or child class)
in place and has no return value; this function takes every measure of a
container, detects its time signature, and apply both
|abjad.Meter.rewrite_meter()| and
|auxjad.mutate.prettify_rewrite_meter()| to it.
Basic usage:
For this example, the following container will be mutated:
>>> staff = abjad.Staff(
... r"c'16 d'8 e'16 f'8 g'4 a'4 b'8 "
... r"c'16 d'4. e'16 f'8 g'4 a'16 b'16"
... )
>>> abjad.show(staff)
.. docs::
\new Staff
{
c'16
d'8
e'16
f'8
g'4
a'4
b'8
c'16
d'4.
e'16
f'8
g'4
a'16
b'16
}
.. figure:: ../_images/auto_rewrite_meter-xyx2wh7ufer.png
Abjad's |abjad.Meter.rewrite_meter()| mutates an |abjad.Selection|
of a measure, improving its notation.
>>> for measure in abjad.select(staff[:]).group_by_measure():
... abjad.Meter.rewrite_meter(measure, abjad.Meter((4, 4)))
>>> abjad.show(staff)
.. docs::
\new Staff
{
c'16
d'16
~
d'16
e'16
f'8
g'8
~
g'8
a'8
~
a'8
b'8
c'16
d'8.
~
d'8.
e'16
f'8
g'8
~
g'8
a'16
b'16
}
.. figure:: ../_images/auto_rewrite_meter-7fn2uj2xupb.png
This function mutates an |abjad.Container| (or child class),
identifying the implied meters of each measure and applying both
|abjad.Meter.rewrite_meter()| and
|auxjad.mutate.prettify_rewrite_meter()| to it. See the documentation
of the latter for a detailed explanation of what it does.
Applying |auxjad.mutate.auto_rewrite_meter()| to the same initial
container shown in the first figure above outputs:
>>> staff = abjad.Staff(
... r"c'16 d'8 e'16 f'8 g'4 a'4 b'8 "
... r"c'16 d'4. e'16 f'8 g'4 a'16 b'16"
... )
>>> auxjad.mutate.auto_rewrite_meter(staff)
>>> abjad.show(staff)
.. docs::
\new Staff
{
c'16
d'8
e'16
f'8
g'8
~
g'8
a'4
b'8
c'16
d'8.
~
d'8.
e'16
f'8
g'4
a'16
b'16
}
.. figure:: ../_images/auto_rewrite_meter-ahdaggaiqbc.png
.. note::
Auxjad automatically adds this function as an extension function to
|abjad.mutate|. It can thus be used from either |auxjad.mutate|_ or
|abjad.mutate| namespaces. Therefore, the two lines below are
equivalent:
>>> auxjad.mutate.auto_rewrite_meter(staff)
>>> abjad.mutate.auto_rewrite_meter(staff)
Time signature changes:
It automatically handles time signature changes.
>>> staff = abjad.Staff(
... r"c'16 d'8 e'16 f'8 g'4 a'4 b'8 "
... r"\time 6/8 b'4 c''4 r4 "
... )
>>> auxjad.mutate.auto_rewrite_meter(staff)
>>> abjad.show(staff)
.. docs::
\new Staff
{
c'16
d'8
e'16
f'8
g'8
~
g'8
a'4
b'8
\time 6/8
b'4
c''8
~
c''8
r4
}
.. figure:: ../_images/auto_rewrite_meter-08sckfp19vil.png
``prettify_rewrite_meter``:
By default, this function invokes both |abjad.Meter.rewrite_meter()|
and |auxjad.mutate.prettify_rewrite_meter()|.
>>> staff = abjad.Staff(
... r"c'16 d'8 e'16 f'8 g'4 a'4 b'8 "
... r"c'16 d'8 e'16 f'8 g'4 a'4 b'8"
... )
>>> auxjad.mutate.auto_rewrite_meter(staff)
>>> abjad.show(staff)
.. docs::
\new Staff
{
c'16
d'8
e'16
f'8
g'8
~
g'8
a'4
b'8
c'16
d'8
e'16
f'8
g'8
~
g'8
a'4
b'8
}
.. figure:: ../_images/auto_rewrite_meter-vbytyszlkng.png
Set ``prettify_rewrite_meter`` to ``False`` to not invoke
|auxjad.mutate.prettify_rewrite_meter()|.
>>> staff = abjad.Staff(
... r"c'16 d'8 e'16 f'8 g'4 a'4 b'8 "
... r"c'16 d'4. e'16 f'8 g'4 a'16 b'16"
... )
>>> auxjad.mutate.auto_rewrite_meter(
... staff,
... prettify_rewrite_meter=False,
... )
>>> abjad.show(staff)
.. docs::
\new Staff
{
c'16
d'16
~
d'16
e'16
f'8
g'8
~
g'8
a'8
~
a'8
b'8
c'16
d'8.
~
d'8.
e'16
f'8
g'8
~
g'8
a'16
b'16
}
.. figure:: ../_images/auto_rewrite_meter-64wse58hvko.png
``meter_list``:
When no ``meter_list`` is supplied, this function detects the time
signature of each measure and uses those when rewritting it:
>>> staff = abjad.Staff(
... r"\time 7/4 c'8 d'4 e'4 f'4 g'4 a'4 b'4 c''8 "
... r"\time 5/4 d''8 e''4 f''4 g''4 a''4 b''8"
... )
>>> auxjad.mutate.auto_rewrite_meter(staff)
>>> abjad.show(staff)
.. docs::
\new Staff
{
\time 7/4
c'8
d'4
e'4
f'8
~
f'8
g'4
a'8
~
a'8
b'4
c''8
\time 5/4
d''8
e''4
f''4
g''8
~
g''8
a''4
b''8
}
.. figure:: ../_images/auto_rewrite_meter-l4xnpevp3z.png
To use a custom list of meters (one for each measure), set
``meter_list`` to a :obj:`list` of |abjad.Meter|'s or
|abjad.TimeSignature|'s.
>>> staff = abjad.Staff(
... r"\time 7/4 c'8 d'4 e'4 f'4 g'4 a'4 b'4 c''8 "
... r"\time 5/4 d''8 e''4 f''4 g''4 a''4 b''8"
... )
>>> meter_list = [abjad.Meter((7, 4), increase_monotonic=True),
... abjad.Meter((5, 4), increase_monotonic=True),
... ]
>>> auxjad.mutate.auto_rewrite_meter(staff, meter_list=meter_list)
>>> abjad.show(staff)
.. docs::
\new Staff
{
\time 7/4
c'8
d'4
e'8
~
e'8
f'4
g'8
~
g'8
a'4
b'4
c''8
\time 5/4
d''8
e''4
f''8
~
f''8
g''4
a''4
b''8
}
.. figure:: ../_images/auto_rewrite_meter-uqif4i8tqxk.png
Number of measures:
This function handles a container with any number of measures and any
number of time signature changes:
>>> staff = abjad.Staff(
... r"\time 3/4 c'8 d'4 e'4 f'8 "
... r"\time 5/8 g'4 a'4 r8 "
... r"\time 6/8 b'4 c''4 r4 "
... r"\time 4/4 d''8 e''4 f''8 g''16 a''4 r8."
... )
>>> auxjad.mutate.auto_rewrite_meter(staff)
>>> abjad.show(staff)
.. docs::
\new Staff
{
\time 3/4
c'8
d'4
e'4
f'8
\time 5/8
g'4
a'8
~
a'8
r8
\time 6/8
b'4
c''8
~
c''8
r4
\time 4/4
d''8
e''4
f''8
g''16
a''8.
~
a''16
r8.
}
.. figure:: ../_images/auto_rewrite_meter-hkhtqnqita.png
``extract_trivial_tuplets``:
By default, tuplets filled with rests or tied notes or chords are
extracted:
>>> staff = abjad.Staff(
... r"\times 2/3 {c'4 ~ c'8} \times 2/3 {d'8 r4} "
... r"\times 2/3 {r8 r8 r8} \times 2/3 {<e' g'>8 ~ <e' g'>4}"
... )
>>> auxjad.mutate.auto_rewrite_meter(staff)
>>> abjad.show(staff)
.. docs::
\new Staff
{
c'4
\times 2/3
{
d'8
r4
}
r4
<e' g'>4
}
.. figure:: ../_images/auto_rewrite_meter-nq6t6qwka7a.png
Set ``extract_trivial_tuplets`` to ``False`` to disable this behaviour.
>>> staff = abjad.Staff(
... r"\times 2/3 {c'4 ~ c'8} \times 2/3 {d'8 r4} "
... r"\times 2/3 {r8 r8 r8} \times 2/3 {<e' g'>8 ~ <e' g'>4}"
... )
>>> auxjad.mutate.auto_rewrite_meter(
... staff,
... extract_trivial_tuplets=False,
... )
>>> abjad.show(staff)
.. docs::
\new Staff
{
\times 2/3
{
c'4.
}
\times 2/3
{
d'8
r4
}
\times 2/3
{
r4.
}
\times 2/3
{
<e' g'>4.
}
}
.. figure:: ../_images/auto_rewrite_meter-ssnsui7o9cc.png
``merge_partial_tuplets``:
By default, consecutive partial tuplets with the same ratio that sum up
to an assignable duration will be merged together:
>>> staff = abjad.Staff(
... r"\times 2/3 {c'2 d'1}"
... r"\times 2/3 {e'2} \times 2/3 {f'1}"
... )
>>> auxjad.mutate.auto_rewrite_meter(staff)
>>> abjad.show(staff)
.. docs::
\new Staff
{
\times 2/3
{
c'2
d'1
}
\times 2/3
{
e'2
f'1
}
}
.. figure:: ../_images/auto_rewrite_meter-ty72t5wvc1.png
Set ``merge_partial_tuplets`` to ``False`` to disable this behaviour.
>>> staff = abjad.Staff(
... r"\times 2/3 {c'2 d'1}"
... r"\times 2/3 {e'2} \times 2/3 {f'1}"
... )
>>> auxjad.mutate.auto_rewrite_meter(
... staff,
... merge_partial_tuplets=False,
... )
>>> abjad.show(staff)
.. docs::
\new Staff
{
\times 2/3
{
c'2
d'1
}
\tweak edge-height #'(0.7 . 0)
\times 2/3
{
e'2
}
\tweak edge-height #'(0.7 . 0)
\times 2/3
{
f'1
}
}
.. figure:: ../_images/auto_rewrite_meter-4rouf819bjb.png
.. note::
This function also accepts the arguments ``boundary_depth``,
``maximum_dot_count``, and ``rewrite_tuplets``, which are passed on to
|abjad.Meter.rewrite_meter()|, and ``fuse_across_groups_of_beats``,
``fuse_quadruple_meter``, ``fuse_triple_meter``, and
``split_quadruple_meter``, which are passed on to
|auxjad.mutate.prettify_rewrite_meter()|. ``merge_partial_tuplets``
is used to invoke |auxjad.mutate.merge_partial_tuplets()| See the
documentation of these functions for more details on these arguments.
.. warning::
Setting ``boundary_depth`` to a value equal to or larger than ``1``
will automatically disable ``fuse_across_groups_of_beats``,
``fuse_quadruple_meter``, and ``fuse_triple_meter``, regardless of
their values. This is because when any of those arguments is ``True``,
|auxjad.mutate.prettify_rewrite_meter()| will fuse across beats,
which goes against the purpose of using ``boundary_depth``. Compare the
results below. In the first case, simply applying
|auxjad.mutate.prettify_rewrite_meter()| with no arguments results in
some logical ties being tied across beats.
>>> staff = abjad.Staff(r"\time 4/4 c'4. d'4. e'4 f'8 g'4 a'4 b'4.")
>>> meter = abjad.Meter((4, 4))
>>> for measure in abjad.select(staff[:]).group_by_measure():
... abjad.mutate.rewrite_meter(measure, meter, boundary_depth=1)
>>> for measure in abjad.select(staff[:]).group_by_measure():
... auxjad.mutate.prettify_rewrite_meter(measure, meter)
>>> abjad.show(staff)
.. docs::
\new Staff
{
\time 4/4
c'4
~
c'8
d'8
~
d'4
e'4
f'8
g'4
a'8
~
a'8
b'8
~
b'4
}
.. figure:: ../_images/auto_rewrite_meter-cf09ysj16fo.png
By automatically setting all ``fuse_across_groups_of_beats``,
``fuse_quadruple_meter``, and ``fuse_triple_meter` to ``False`` when
``boundary_depth`` is equal to or larger than ``1``, this function will
not fuse those leaves against the required boundary depth.
>>> staff = abjad.Staff(r"\time 4/4 c'4. d'4. e'4 f'8 g'4 a'4 b'4.")
>>> auxjad.mutate.auto_rewrite_meter(staff, boundary_depth=1)
>>> abjad.show(staff)
.. docs::
\new Staff
{
\time 4/4
c'4
~
c'8
d'8
~
d'4
e'4
f'8
g'8
~
g'8
a'8
~
a'8
b'8
~
b'4
}
.. figure:: ../_images/auto_rewrite_meter-mm9xvmaqwfj.png
"""
if not isinstance(container, abjad.Container):
raise TypeError("first positional argument must be 'abjad.Container' "
"or child class")
if meter_list is not None:
if not isinstance(meter_list, list):
raise TypeError("'meter_list' must be a 'list' of 'abjad.Meter' "
"or 'abjad.TimeSignature'")
else:
for meter in meter_list:
if not isinstance(meter, (abjad.Meter, abjad.TimeSignature)):
raise TypeError("elements of 'meter_list' must be "
"'abjad.Meter' or 'abjad.TimeSignature'")
if isinstance(meter, abjad.TimeSignature):
meter = abjad.Meter(meter.pair)
if not isinstance(prettify_rewrite_meter, bool):
raise TypeError("'prettify_rewrite_meter' must be 'bool'")
if not isinstance(fuse_across_groups_of_beats, bool):
raise TypeError("'fuse_across_groups_of_beats' must be 'bool'")
if not isinstance(fuse_quadruple_meter, bool):
raise TypeError("'fuse_quadruple_meter' must be 'bool'")
if not isinstance(fuse_triple_meter, bool):
raise TypeError("'fuse_triple_meter' must be 'bool'")
if boundary_depth is not None:
if not isinstance(boundary_depth, int):
raise TypeError("'boundary_depth' must be 'int'")
if maximum_dot_count is not None:
if not isinstance(maximum_dot_count, int):
raise TypeError("'maximum_dot_count' must be 'int'")
if not isinstance(rewrite_tuplets, bool):
raise TypeError("'rewrite_tuplets' must be 'bool'")
if not isinstance(merge_partial_tuplets, bool):
raise TypeError("'merge_partial_tuplets' must be 'bool'")
if not isinstance(split_quadruple_meter, bool):
raise TypeError("'split_quadruple_meter' must be 'bool'")
if merge_partial_tuplets:
merge_partial_tuplets_function(container[:])
if extract_trivial_tuplets:
extract_trivial_tuplets_function(container[:])
if meter_list is None:
time_signatures = get.time_signature_list(
container,
do_not_use_none=True,
)
meter_list = [abjad.Meter(ts.pair) for ts in time_signatures]
measures = abjad.select(container[:]).group_by_measure()
for meter, measure in zip(meter_list, measures):
if isinstance(measure[0], abjad.MultimeasureRest):
continue
abjad.Meter.rewrite_meter(
measure,
meter,
boundary_depth=boundary_depth,
maximum_dot_count=maximum_dot_count,
rewrite_tuplets=rewrite_tuplets,
)
if prettify_rewrite_meter:
measures = abjad.select(container[:]).group_by_measure()
for meter, measure in zip(meter_list, measures):
if boundary_depth is None or boundary_depth < 1:
prettify_rewrite_meter_function(
measure,
meter,
fuse_across_groups_of_beats=fuse_across_groups_of_beats,
fuse_quadruple_meter=fuse_quadruple_meter,
fuse_triple_meter=fuse_triple_meter,
extract_trivial_tuplets=False,
split_quadruple_meter=split_quadruple_meter,
)
else:
prettify_rewrite_meter_function(
measure,
meter,
fuse_across_groups_of_beats=False,
fuse_quadruple_meter=False,
fuse_triple_meter=False,
extract_trivial_tuplets=False,
split_quadruple_meter=False,
)