Source code for auxjad.mutate.close_container

import abjad

from .. import get


[docs]def close_container(container: abjad.Container) -> None: r"""Mutates an input container (of type |abjad.Container| or child class) in place and has no return value; this function changes the time signature of the last measure of an underfull in order to make it full. Basic usage: Returns the missing duration of the last measure of any container or child class. If no time signature is encountered, it uses LilyPond's convention and considers the container as in 4/4. >>> container1 = abjad.Staff(r"c'4 d'4 e'4 f'4") >>> container2 = abjad.Staff(r"c'4 d'4 e'4") >>> container3 = abjad.Staff(r"c'4 d'4 e'4 f'4 | c'4") >>> container4 = abjad.Staff(r"c'4 d'4 e'4 f'4 | c'4 d'4 e'4 f'4") >>> auxjad.mutate.close_container(container1) >>> auxjad.mutate.close_container(container2) >>> auxjad.mutate.close_container(container3) >>> auxjad.mutate.close_container(container4) >>> abjad.show(container1) .. docs:: \new Staff { c'4 d'4 e'4 f'4 } .. figure:: ../_images/close_container-nfnk06s90x.png >>> abjad.show(container2) .. docs:: \new Staff { \time 3/4 c'4 d'4 e'4 } .. figure:: ../_images/close_container-swyxwiup8pm.png >>> abjad.show(container3) .. docs:: \new Staff { c'4 d'4 e'4 f'4 \time 1/4 c'4 } .. figure:: ../_images/close_container-mms5hiysbwe.png >>> abjad.show(container4) .. docs:: \new Staff { c'4 d'4 e'4 f'4 c'4 d'4 e'4 f'4 } .. figure:: ../_images/close_container-aky7avbla4w.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.close_containers(staff) >>> abjad.mutate.close_containers(staff) Time signature changes: Handles any time signatures as well as changes of time signature. >>> container1 = abjad.Staff(r"\time 4/4 c'4 d'4 e'4 f'4 g'") >>> container2 = abjad.Staff(r"\time 3/4 a2. \time 2/4 c'4") >>> container3 = abjad.Staff(r"\time 5/4 g1 ~ g4 \time 4/4 af'2") >>> auxjad.mutate.close_container(container1) >>> auxjad.mutate.close_container(container2) >>> auxjad.mutate.close_container(container3) >>> abjad.show(container1) .. docs:: \new Staff { \time 4/4 c'4 d'4 e'4 f'4 \time 1/4 g'4 } .. figure:: ../_images/close_container-3tgyty245cq.png >>> abjad.show(container2) .. docs:: \new Staff { \time 3/4 a2. \time 1/4 c'4 } .. figure:: ../_images/close_container-st5d89zofoh.png >>> abjad.show(container3) .. docs:: \new Staff { \time 5/4 g1 ~ g4 \time 2/4 af'2 } .. figure:: ../_images/close_container-wd5irlm76l.png .. note:: When using |abjad.Container|'s, all time signatures in the output will be commented out with ``%%%.`` This is because Abjad only applies time signatures to containers that belong to a |abjad.Staff|. The present function works with either |abjad.Container| and |abjad.Staff|. >>> container = abjad.Container(r"\time 3/4 c'4 d'4 e'4") >>> abjad.show(container) .. docs:: { %%% \time 3/4 %%% c'4 d'4 e'4 } .. figure:: ../_images/close_container-xrwkorhtl5.png >>> staff = abjad.Staff([container]) >>> abjad.show(container) .. docs:: { \time 3/4 c'4 d'4 e'4 } .. figure:: ../_images/close_container-ys6pcdlywy.png Partial time signatures: Correctly handles partial time signatures. >>> container = abjad.Staff(r"c'4 d'4 e'4 f'4 g'4") >>> time_signature = abjad.TimeSignature((3, 4), partial=(1, 4)) >>> abjad.attach(time_signature, container[0]) >>> auxjad.mutate.close_container(container) >>> abjad.show(container) .. docs:: \new Staff { \partial 4 \time 3/4 c'4 d'4 e'4 f'4 \time 1/4 g'4 } .. figure:: ../_images/close_container-rfskjbbfnu.png .. error:: If a container is malformed, i.e. it has an underfilled measure before a time signature change, the function raises a :exc:`ValueError` exception. >>> container = abjad.Container(r"\time 5/4 g''1 \time 4/4 f'4") >>> auxjad.mutate.close_container(container) ValueError: 'container' is malformed, with an underfull measure preceding a time signature change .. warning:: The input container must be a contiguous logical voice. When dealing with a container with multiple subcontainers (e.g. a score containing multiple staves), the best approach is to cycle through these subcontainers, applying this function to them individually. """ if not isinstance(container, abjad.Container): raise TypeError("argument must be 'abjad.Container' or child class") if not abjad.select(container).leaves().are_contiguous_logical_voice(): raise ValueError("argument must be contiguous logical voice") try: if not get.selection_is_full(container[:]): missing_duration = get.underfull_duration(container[:]) leaves = abjad.select(container).leaves() for leaf in leaves[::-1]: time_signature = abjad.get.effective(leaf, abjad.TimeSignature) if time_signature is not None: last_time_signature = time_signature break else: last_time_signature = abjad.TimeSignature((4, 4)) last_bar_duration = last_time_signature.duration - missing_duration final_bar_time_signature = abjad.TimeSignature(last_bar_duration) final_bar_time_signature.simplify_ratio() duration = 0 for leaf in leaves[::-1]: duration += abjad.get.duration(leaf) if duration == last_bar_duration: if abjad.get.indicator(leaf, abjad.TimeSignature): abjad.detach(abjad.TimeSignature, leaf) abjad.attach(final_bar_time_signature, leaf) break except ValueError as err: raise ValueError("'container' is malformed, with an underfull measure " "preceding a time signature change") from err