Skip to content

Commit

Permalink
Merge pull request #2 from nivlekp/stateMapping
Browse files Browse the repository at this point in the history
Some state mapping logic
  • Loading branch information
nivlekp authored Aug 18, 2024
2 parents 2abf675 + ad66c3d commit f460b04
Show file tree
Hide file tree
Showing 10 changed files with 80 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ on:

env:
LILYPOND_VERSION: 2.25.16
PANG_COMMIT: b5dc6468810789ed8cf79136a7f0a31932904400
PANG_COMMIT: 63a6320d8bd680feffcb6d22e5743bf9d9ed28af
PANG_PATH: /tmp/pang

jobs:
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ check:
make black-check
make flake8
make isort-check
make mypy

test:
make black-check
Expand Down
4 changes: 2 additions & 2 deletions minamidera/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from . import library, states
from . import library, soundpointsgenerators, statemapper, statetransition

__all__ = ["library", "states"]
__all__ = ["library", "soundpointsgenerators", "statemapper", "statetransition"]
15 changes: 4 additions & 11 deletions minamidera/library.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
import dataclasses
import enum
PITCHES_SETS = [{-6, -5, -4, 0, (1, 2), 3}, {-32, -30, 24, 27}]

AXIS = enum.Enum("AXIS", ["FREQUENCY", "INTENSITY", "DENSITY"])
FREQUENCY_REGIONS = enum.Enum("FREQUENCY_REGIONS", ["F0", "F1"])
INTENSITY_REGIONS = enum.Enum("INTENSITY_REGIONS", ["G0", "G1"])
DENSITY_REGIONS = enum.Enum("DENSITY_REGIONS", ["D0", "D1"])
INTENSITY_SETS = [{-1, 0}, {-2, 2}]

DENSITY_SETS = [{0.7}, {3.0}]

@dataclasses.dataclass
class State:
frequency_region: FREQUENCY_REGIONS
intensity_region: INTENSITY_REGIONS
density_region: DENSITY_REGIONS
DURATION_SETS = [{0.3}, {1.0}]
9 changes: 9 additions & 0 deletions minamidera/soundpointsgenerators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import pang


class AtaxicSoundPointsGenerator(pang.SoundPointsGenerator):
def __init__(self, pitches_set, intensity_set, density_set, duration_set):
self.pitches_set = pitches_set
self.intensity_set = intensity_set
self.density_set = density_set
self.duration_set = duration_set
24 changes: 23 additions & 1 deletion minamidera/statemapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,35 @@
import numpy.typing as npt
import pang

from .library import DENSITY_SETS, DURATION_SETS, INTENSITY_SETS, PITCHES_SETS
from .soundpointsgenerators import AtaxicSoundPointsGenerator


def map_state_sequence(state_sequence: Iterable[npt.NDArray]) -> pang.Sequence:
sequence = pang.Sequence([], 0)
sequence = pang.Sequence.empty_sequence()
for state in state_sequence:
sequence.extend(map_state(state))
return sequence


def map_state(state: npt.NDArray) -> pang.Sequence:
raise NotImplementedError


def map_state_vector_to_sound_points_generator(
state_vector: npt.NDArray,
) -> pang.SoundPointsGenerator:
if len(state_vector) != 4:
raise ValueError(
f"The shape of the state vector {state_vector} does not match the number of state variables"
)
if any(state not in (0, 1) for state in state_vector):
raise ValueError(
f"The state vector {state_vector} contains value other than 0 and 1"
)
return AtaxicSoundPointsGenerator(
PITCHES_SETS[state_vector[0]],
INTENSITY_SETS[state_vector[1]],
DENSITY_SETS[state_vector[2]],
DURATION_SETS[state_vector[3]],
)
File renamed without changes.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ allow-direct-references = true

[project]
name = "minamidera"
version = "24.8b0"
version = "24.8b1"
authors = [
{ name="Tsz Kiu Pang" },
]
Expand Down
33 changes: 33 additions & 0 deletions tests/test_statemapper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import numpy as np
import pang
import pytest

from minamidera import library, statemapper


def test_mapping_empty_sequence():
assert statemapper.map_state_sequence([]) == pang.Sequence.empty_sequence()


def test_mapping_sound_point_generator_from_invalid_state_vector_length():
with pytest.raises(ValueError) as exception_info:
statemapper.map_state_vector_to_sound_points_generator(
np.array([0, 0, 1, 0, 0])
)
assert "does not match" in str(exception_info)


def test_mapping_sound_point_generator_from_invalid_state_vector_value():
with pytest.raises(ValueError) as exception_info:
statemapper.map_state_vector_to_sound_points_generator(np.array([0, 1, 0, 2]))
assert "contains value other than 0 and 1" in str(exception_info)


def test_mapping_state_vector_to_sound_point_generator():
sound_points_generator = statemapper.map_state_vector_to_sound_points_generator(
np.array([0, 1, 0, 1])
)
assert sound_points_generator.pitches_set == library.PITCHES_SETS[0]
assert sound_points_generator.intensity_set == library.INTENSITY_SETS[1]
assert sound_points_generator.density_set == library.DENSITY_SETS[0]
assert sound_points_generator.duration_set == library.DURATION_SETS[1]
11 changes: 6 additions & 5 deletions tests/test_states.py → tests/test_statetransition.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import numpy as np

from minamidera import states
from minamidera import statetransition


def test_getting_next_state():
state = (0, 0, 1, 1)
next_state = states.get_next_state(state, np.random.default_rng())
next_state = statetransition.get_next_state(state, np.random.default_rng())
assert len(next_state) == 4


def test_generating_state_sequence():
initial_state = (0, 0, 0, 0)
sequence_length = 100
state_sequence = states.generate_state_sequence(
state_sequence = statetransition.generate_state_sequence(
initial_state, sequence_length, np.random.default_rng()
)
assert len(state_sequence) == sequence_length
Expand All @@ -23,15 +23,16 @@ def test_generating_state_sequences():
number_of_state_vectors = 100
initial_states = tuple(initial_state for _ in range(number_of_state_vectors))
sequence_length = 10
state_sequences = states.generate_state_sequences(
state_sequences = statetransition.generate_state_sequences(
initial_states, sequence_length, np.random.default_rng()
)
assert len(state_sequences) == number_of_state_vectors
assert all([len(sequence) == sequence_length for sequence in state_sequences])
# TODO: assert statistical properties perhaps


def test_enumerating_state_vectors():
assert states.enumerate_state_vectors(4, 2) == {
assert statetransition.enumerate_state_vectors(4, 2) == {
0: (0, 0, 0, 0),
1: (0, 0, 0, 1),
2: (0, 0, 1, 0),
Expand Down

0 comments on commit f460b04

Please sign in to comment.