ListLooper

class auxjad.ListLooper(contents: list, *, window_size: int, step_size: int = 1, max_steps: int = 1, repetition_chance: float = 0.0, forward_bias: float = 1.0, head_position: int = 0, end_with_max_n_elements: bool = False, process_on_first_call: bool = False)[source]

Outputs slices of a list using the metaphor of a looping window of a constant number of elements. This number is given by the argument window_size, which is an int representing how many elements are to be included in each slice.

For instance, if the initial container had the elements [A, B, C, D, E, F] (where each letter represents an element of an arbitrary type) and the looping window was size 3, the output would be:

[A B C] [B C D] [C D E] [D E F] [E F] [F]

This can be better visualised as:

A B C
  B C D
    C D E
      D E F
        E F
          F
Basic usage:

Calling the object will return a list generated by the looping process. Each call of the object will move the window forwards and output the result.

>>> input_list = ['A', 'B', 'C', 'D', 'E', 'F']
>>> looper = auxjad.ListLooper(input_list, window_size=3)
>>> looper()
['A', 'B', 'C']
>>> looper()
['B', 'C', 'D']

The property current_window can be used to access the current window without moving the head forwards.

>>> looper.current_window
['B', 'C', 'D']
process_on_first_call:

The very first call will output the input list without processing it. To disable this behaviour and have the looping window move on the very first call, initialise the class with the keyword argument process_on_first_call set to True.

>>> input_list = ['A', 'B', 'C', 'D', 'E', 'F']
>>> looper = auxjad.ListLooper(input_list,
...                            window_size=3,
...                            process_on_first_call=True,
...                            )
>>> looper()
['B', 'C', 'D']
Using as iterator:

The instances of this class can also be used as an iterator, which can then be used in a for loop to exhaust all windows.

>>> input_list = ['A', 'B', 'C', 'D', 'E', 'F']
>>> looper = auxjad.ListLooper(input_list,
...                            window_size=3,
...                            )
>>> for window in looper:
...     print(window)
['A', 'B', 'C']
['B', 'C', 'D']
['C', 'D', 'E']
['D', 'E', 'F']
['E', 'F']
['F']
Arguments and properties:

This class can take many optional keyword arguments during its creation. step_size dictates the size of each individual step in number of elements (default value is 1). max_steps sets the maximum number of steps that the window can advance when the object is called, ranging between 1 and the input value (default is also 1). repetition_chance sets the chance of a window result repeating itself (that is, the window not moving forwards when called). It should range from 0.0 to 1.0 (default 0.0, i.e. no repetition). forward_bias sets the chance of the window moving forward instead of backwards. It should range from 0.0 to 1.0 (default 1.0, which means the window can only move forwards. A value of 0.5 gives 50% chance of moving forwards while a value of 0.0 will move the window only backwards). head_position can be used to offset the starting position of the looping window. It must be an int and its default value is 0. By default, calling the object will first return the original container and subsequent calls will process it; set process_on_first_call to True and the looping process will be applied on the very first call. Lastly, set end_with_max_n_elements to True to end the process when the final window has the maximum number of elements.

>>> input_list = ['A', 'B', 'C', 'D', 'E', 'F']
>>> looper = auxjad.ListLooper(input_list,
...                            window_size=3,
...                            step_size=1,
...                            max_steps=2,
...                            repetition_chance=0.25,
...                            forward_bias=0.2,
...                            head_position=0,
...                            end_with_max_n_elements=True,
...                            process_on_first_call=True,
...                            )
>>> looper.window_size
3
>>> looper.step_size
1
>>> looper.repetition_chance
0.25
>>> looper.forward_bias
0.2
>>> looper.max_steps
2
>>> looper.head_position
0
>>> looper.end_with_max_n_elements
True
>>> looper.process_on_first_call
True

Use the properties below to change these values after initialisation.

>>> looper.window_size = 2
>>> looper.step_size = 2
>>> looper.max_steps = 3
>>> looper.repetition_chance = 0.1
>>> looper.forward_bias = 0.8
>>> looper.head_position = 2
>>> looper.end_with_max_n_elements = False
>>> looper.process_on_first_call = False
>>> looper.window_size
2
>>> looper.step_size
2
>>> looper.max_steps
3
>>> looper.repetition_chance
0.1
>>> looper.forward_bias
0.8
>>> looper.head_position
2
>>> looper.end_with_max_n_elements
False
>>> looper.process_on_first_call
False
Setting forward_bias to 0.0:

Set forward_bias to 0.0 to move backwards instead of forwards (default is 1.0). The initial head_position must be greater than 0 otherwise the contents will already be exhausted in the very first call (since it will not be able to move backwards from that position).

>>> input_list = ['A', 'B', 'C', 'D']
>>> looper = auxjad.ListLooper(input_list,
...                            window_size=2,
...                            head_position=2,
...                            forward_bias=0.0,
...                            )
>>> looper.output_all()
['C', 'D', 'B', 'C', 'A', 'B']
forward_bias between 0.0 and 1.0:

Setingt forward_bias to a value in between 0.0 and 1.0 will result in random steps being taken forward or backward, according to the bias. The initial value of head_position will once gain play an important role here, as the contents might be exhausted if the looper attempts to move backwards after reaching the head position 0.

>>> input_list = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
>>> looper = auxjad.ListLooper(input_list,
...                            window_size=2,
...                            head_position=4,
...                            forward_bias=0.5,
...                            )
>>> looper.output_n(4)
['E', 'F', 'D', 'E', 'C', 'D', 'B', 'C']
max_steps:

Setting the keyword argument max_steps to a value larger than 1 will result in a random number of steps (between 1 and max_steps) being applied at each call.

>>> input_list = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
>>> looper = auxjad.ListLooper(input_list,
...                            window_size=2,
...                            head_position=2,
...                            max_steps=4,
...                            )
>>> looper.output_n(4)
['C', 'D', 'D', 'E', 'E', 'F', 'H']
len():

The function len() can be used to get the total number of elements in the container.

>>> input_list = ['A', 'B', 'C', 'D', 'E', 'F']
>>> looper = auxjad.ListLooper(input_list, window_size=3)
>>> len(looper)
6
output_all():

To run through the whole process and output it as a single list, from the initial head position until the process outputs the single last element, use the method output_all().

>>> input_list = ['A', 'B', 'C', 'D']
>>> looper = auxjad.ListLooper(input_list, window_size=3)
>>> looper.output_all()
['A', 'B', 'C', 'B', 'C', 'D', 'C', 'D', 'D']
output_n():

To run through just part of the process and output it as a single list, starting from the initial head position, use the method output_n() and pass the number of iterations as argument.

>>> input_list = ['A', 'B', 'C', 'D']
>>> looper = auxjad.ListLooper(input_list, window_size=3)
>>> looper.output_n(2)
['A', 'B', 'C', 'B', 'C', 'D']
end_with_max_n_elements:

When True, the last bar in the output will contain the maximum number of leaves given by window_size. E.g. consider the elements [A, B, C, D] and the looping window was size 3; setting end_with_max_n_elements to True will output:

[A B C] [B C D]

Setting it to False (which is this property’s default value) will produces:

[A B C] [B C D] [C D] [D]

Compare the two examples below:

>>> input_list = ['A', 'B', 'C', 'D']
>>> looper = auxjad.ListLooper(input_list, window_size=3)
>>> looper.output_all()
['A', 'B', 'C', 'B', 'C', 'D', 'C', 'D', 'D']
>>> input_list = ['A', 'B', 'C', 'D']
>>> looper = auxjad.ListLooper(input_list,
...                            window_size=3,
...                            end_with_max_n_elements=True,
...                            )
>>> looper.output_all()
['A', 'B', 'C', 'B', 'C', 'D']
window_size:

To change the size of the looping window after instantiation, use the property window_size. In the example below, the initial window is of size 3, and so the first call of the looper object outputs the first, second, and third elements of the list. The window size is then set to 4, and the looper is called again, moving to the element in the next position, thus outputting the second, third, fourth, and fifth elements.

>>> input_list = ['A', 'B', 'C', 'D', 'E', 'F']
>>> looper = auxjad.ListLooper(input_list, window_size=3)
>>> looper()
['A', 'B', 'C']
>>> looper.window_size = 4
>>> looper()
['B', 'C', 'D', 'E']
contents:

Use the contents property to read as well as overwrite the contents of the looper. Notice that the head_position will remain on its previous value and must be reset to 0 if that’s required.

>>> input_list = ['A', 'B', 'C', 'D', 'E', 'F']
>>> looper = auxjad.ListLooper(input_list,
...                            window_size=3,
...                            )
>>> looper.contents
['A', 'B', 'C', 'D', 'E', 'F']
>>> looper()
['A', 'B', 'C']
>>> looper()
['B', 'C', 'D']
>>> looper.contents = [0, 1, 2, 3, 4]
>>> looper.contents
[0, 1, 2, 3, 4]
>>> looper()
[1, 2, 3]
>>> looper.head_position = 0
>>> looper()
[0, 1, 2]
Types in the input list:

The input list can contain any types of elements:

>>> input_list = [123, 'foo', (3, 4), 3.14]
>>> looper = auxjad.ListLooper(input_list, window_size=3)
>>> looper()
[123, 'foo', (3, 4)]

This also include Abjad’s types. Abjad’s exclusive membership requirement is respected since each call returns a copy.deepcopy() of the window. The same is true to the output_all() method.

>>> import abjad
>>> import copy
>>> input_list = [
...     abjad.Container(r"c'4 d'4 e'4 f'4"),
...     abjad.Container(r"fs'1"),
...     abjad.Container(r"r2 bf4 c'4"),
...     abjad.Container(r"c''2. r4"),
... ]
>>> looper = auxjad.ListLooper(input_list, window_size=3)
>>> staff = abjad.Staff()
>>> for element in looper.output_all():
...     staff.append(element)
>>> abjad.show(staff)
../_images/ListLooper-kvxaoz53y5f.png

Methods

__call__()

Calls the looping process for one iteration, returning an abjad.Selection.

__init__(contents, *, window_size[, …])

Initialises self.

__iter__()

Returns an iterator, allowing instances to be used as iterators.

__len__()

Returns a length of contents.

__next__()

Calls the looping process for one iteration, returning an abjad.Selection.

__repr__()

Returns interpreter representation of contents.

output_all()

Goes through the whole looping process and outputs a single list.

output_n(n)

Goes through n iterations of the looping process and outputs a single list.

Attributes

contents

The list to be sliced and looped.

current_window

Read-only property, returns the window at the current head position.

end_with_max_n_elements

When True, the last bar in the output will contain the maximum number of elements given by window_size.

forward_bias

The chance of the window moving forward instead of backwards.

head_position

The position of the head at the start of a looping window.

max_steps

The maximum number of steps per operation.

process_on_first_call

If True then contents will be processed in the very first call.

repetition_chance

The chance of the head not moving, thus repeating the output.

step_size

The size of each step when moving the head.

window_size

The length of the looping window.

__call__()abjad.select.Selection

Calls the looping process for one iteration, returning an abjad.Selection.

__init__(contents: list, *, window_size: int, step_size: int = 1, max_steps: int = 1, repetition_chance: float = 0.0, forward_bias: float = 1.0, head_position: int = 0, end_with_max_n_elements: bool = False, process_on_first_call: bool = False)None[source]

Initialises self.

__iter__()None

Returns an iterator, allowing instances to be used as iterators.

__len__()int[source]

Returns a length of contents.

__next__()abjad.select.Selection

Calls the looping process for one iteration, returning an abjad.Selection.

__repr__()str[source]

Returns interpreter representation of contents.

property contents: list

The list to be sliced and looped.

property current_window: Optional[list]

Read-only property, returns the window at the current head position.

property end_with_max_n_elements: bool

When True, the last bar in the output will contain the maximum number of elements given by window_size. E.g. consider the elements [A, B, C, D] and the looping window was size 3; setting end_with_max_n_elements to True will output:

[A B C] [B C D]

Setting it to False (which is this property’s default value) will produces:

[A B C] [B C D] [C D] [D]

property forward_bias: float

The chance of the window moving forward instead of backwards. It should range from 0.0 to 1.0 (default 1.0, which means the window can only move forwards. A value of 0.5 gives \(50\%\) chance of moving forwards while a value of 0.0 will move the window only backwards).

property head_position: int

The position of the head at the start of a looping window.

property max_steps: int

The maximum number of steps per operation.

output_all()list[source]

Goes through the whole looping process and outputs a single list. This method replaces the parent’s one since the parent’s method outputs an abjad.Selection.

output_n(n: int)list[source]

Goes through n iterations of the looping process and outputs a single list. This method replaces the parent’s one since the parent’s method outputs an abjad.Selection.

property process_on_first_call: bool

If True then contents will be processed in the very first call.

property repetition_chance: float

The chance of the head not moving, thus repeating the output.

property step_size: int

The size of each step when moving the head.

property window_size: int

The length of the looping window.