From bedc78de4abe22213963404bd63d49f9f3321803 Mon Sep 17 00:00:00 2001
From: melkisedeath <manoskaristineos@gmail.com>
Date: Thu, 5 Sep 2024 12:15:48 +0200
Subject: [PATCH 1/9] Naive solution for estimate_symbolic_duration

Adressed issue #371
---
 partitura/utils/music.py | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/partitura/utils/music.py b/partitura/utils/music.py
index 38c60091..9ed17ac0 100644
--- a/partitura/utils/music.py
+++ b/partitura/utils/music.py
@@ -762,8 +762,18 @@ def estimate_symbolic_duration(
         # 2. The duration is a composite duration
         # For composite duration. We can use the following approach:
         j = find_nearest(COMPOSITE_DURS, qdur)
-        if np.abs(qdur - COMPOSITE_DURS[j]) < eps and return_com_durations:
-            return copy.copy(SYM_COMPOSITE_DURS[j])
+        if np.abs(qdur - COMPOSITE_DURS[j]) < eps:
+            if return_com_durations:
+                return copy.copy(SYM_COMPOSITE_DURS[j])
+            else:
+                warnings.warn(f"Quarter duration {qdur} from {dur}/{div} is a composite"
+                              f"duration but composite durations are not allowed. Returning empty symbolic duration.")
+                return {}
+        # Naive condition to only apply tuplet estimation if the quarter duration is less than a bar (4)
+        elif qdur > 4:
+            warnings.warn(f"Quarter duration {qdur} from {dur}/{div} is not a tuplet or composite duration."
+                          f"Returning empty symbolic duration.")
+            return {}
         else:
             # NOTE: Guess tuplets (Naive) it doesn't cover composite durations from tied notes.
             type = SYM_DURS[i + 3]["type"]

From ffeb58794b39fb3a21e371ee2385dccb0235958d Mon Sep 17 00:00:00 2001
From: melkisedeath <manoskaristineos@gmail.com>
Date: Mon, 9 Sep 2024 15:51:13 +0200
Subject: [PATCH 2/9] Update for symbolic estimation function to cover most
 cases from 0-4 quarters.

---
 partitura/utils/globals.py | 90 +++++++++++++++++++++++++++++++++++++-
 partitura/utils/music.py   |  7 ++-
 2 files changed, 94 insertions(+), 3 deletions(-)

diff --git a/partitura/utils/globals.py b/partitura/utils/globals.py
index 3739e0d4..ca42dbb6 100644
--- a/partitura/utils/globals.py
+++ b/partitura/utils/globals.py
@@ -192,6 +192,24 @@
     {"type": "long", "dots": 3},
 ]
 
+STRAIGHT_DURS = np.array(
+    [ 4 / 256, 4 / 128, 4 / 64, 4 / 32, 4 / 16, 4 / 8, 4 / 4, 4 / 2, 4 / 1, 4 / 0.5, 4 / 0.25]
+)
+
+SYM_STRAIGHT_DURS = [
+    {"type": "256th", "dots": 0},
+    {"type": "128th", "dots": 0},
+    {"type": "64th", "dots": 0},
+    {"type": "32nd", "dots": 0},
+    {"type": "16th", "dots": 0},
+    {"type": "eighth", "dots": 0},
+    {"type": "quarter", "dots": 0},
+    {"type": "half", "dots": 0},
+    {"type": "whole", "dots": 0},
+    {"type": "breve", "dots": 0},
+    {"type": "long", "dots": 0},
+]
+
 MAJOR_KEYS = [
     "Cb",
     "Gb",
@@ -281,14 +299,84 @@
 # Standard tuning frequency of A4 in Hz
 A4 = 440.0
 
-COMPOSITE_DURS = np.array([1 + 4 / 32, 1 + 4 / 16, 2 + 4 / 32, 2 + 4 / 16, 2 + 4 / 8])
+COMPOSITE_DURS = np.array(
+    [
+        1/4 + 1/6,
+        1/2 + 1/12,
+        1/2 + 1/3,
+        1/2 + 1/4 + 1/6,
+        1 + 1/12,
+        1 + 1 / 8,
+        1 + 1 / 6,
+        1 + 1 / 4,
+        1 + 1 / 4 + 1 / 6,
+        1 + 1 / 2 + 1 / 12,
+        1 + 1 / 2 + 1 / 6,
+        1 + 1 / 2 + 1 / 3,
+        1 + 1 / 2 + 1 / 4 + 1 / 6,
+        2 + 1 / 12,
+        2 + 1 / 8,
+        2 + 1 / 6,
+        2 + 1 / 4,
+        2 + 1 / 3,
+        2 + 1 / 4 + 1 / 6,
+        2 + 1 / 2,
+        2 + 1 / 2 + 1 / 12,
+        2 + 2 / 3,
+        2 + 1 / 2 + 1 / 4,
+        2 + 1 / 2 + 1 / 3,
+        2 + 1 / 2 + 1 / 4 + 1 / 6,
+        3 + 1 / 12,
+        3 + 1 / 8,
+        3 + 1 / 6,
+        3 + 1 / 4,
+        3 + 1 / 3,
+        3 + 1 / 4 + 1 / 6,
+        3 + 1 / 2 + 1 / 12,
+        3 + 2 / 3,
+        3 + 1 / 2 + 1 / 3,
+        3 + 1 / 2 + 1 / 4 + 1 / 6,
+    ]
+)
 
 SYM_COMPOSITE_DURS = [
+    ({"type": "16th", "dots": 0}, {"type": "16th", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
+    ({"type": "eighth", "dots": 0}, {"type": "32nd", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
+    ({"type": "eighth", "dots": 0}, {"type": "eighth", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
+    ({"type": "eighth", "dots": 1}, {"type": "16th", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
+    ({"type": "quarter", "dots": 0}, {"type": "32nd", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
     ({"type": "quarter", "dots": 0}, {"type": "32nd", "dots": 0}),
+    ({"type": "quarter", "dots": 0}, {"type": "16th", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
     ({"type": "quarter", "dots": 0}, {"type": "16th", "dots": 0}),
+    ({"type": "quarter", "dots": 0}, {"type": "16th", "dots": 0}, {"type": "16th", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
+    ({"type": "quarter", "dots": 1}, {"type": "32nd", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
+    ({"type": "quarter", "dots": 1}, {"type": "16th", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
+    ({"type": "quarter", "dots": 1}, {"type": "eighth", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
+    ({"type": "quarter", "dots": 2}, {"type": "16th", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
+    ({"type": "half", "dots": 0}, {"type": "32nd", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
     ({"type": "half", "dots": 0}, {"type": "32nd", "dots": 0}),
+    ({"type": "half", "dots": 0}, {"type": "16th", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
     ({"type": "half", "dots": 0}, {"type": "16th", "dots": 0}),
+    ({"type": "half", "dots": 0}, {"type": "eighth", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
+    ({"type": "half", "dots": 0}, {"type": "16th", "dots": 0}, {"type": "16th", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
+    ({"type": "half", "dots": 0}, {"type": "16th", "dots": 0}, {"type": "16th", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
     ({"type": "half", "dots": 0}, {"type": "eighth", "dots": 0}),
+    ({"type": "half", "dots": 0}, {"type": "eighth", "dots": 0}, {"type": "32nd", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
+    ({"type": "half", "dots": 0}, {"type": "quarter", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
+    ({"type": "half", "dots": 0}, {"type": "eighth", "dots": 1}),
+    ({"type": "half", "dots": 0}, {"type": "eighth", "dots": 0}, {"type": "eighth", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
+    ({"type": "half", "dots": 0}, {"type": "eighth", "dots": 1}, {"type": "16th", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
+    ({"type": "half", "dots": 1}, {"type": "32nd", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
+    ({"type": "half", "dots": 1}, {"type": "32nd", "dots": 0}),
+    ({"type": "half", "dots": 1}, {"type": "16th", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
+    ({"type": "half", "dots": 1}, {"type": "16th", "dots": 0}),
+    ({"type": "half", "dots": 1}, {"type": "eighth", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
+    ({"type": "half", "dots": 1}, {"type": "16th", "dots": 0}, {"type": "16th", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
+    ({"type": "half", "dots": 1}, {"type": "16th", "dots": 0}, {"type": "16th", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
+    ({"type": "half", "dots": 2}, {"type": "32nd", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
+    ({"type": "half", "dots": 1}, {"type": "quarter", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
+    ({"type": "half", "dots": 2}, {"type": "eighth", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
+    ({"type": "half", "dots": 3}, {"type": "16th", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
 ]
 
 
diff --git a/partitura/utils/music.py b/partitura/utils/music.py
index 9ed17ac0..e6afe4ea 100644
--- a/partitura/utils/music.py
+++ b/partitura/utils/music.py
@@ -775,12 +775,15 @@ def estimate_symbolic_duration(
                           f"Returning empty symbolic duration.")
             return {}
         else:
+            i = find_nearest(STRAIGHT_DURS, qdur)
             # NOTE: Guess tuplets (Naive) it doesn't cover composite durations from tied notes.
-            type = SYM_DURS[i + 3]["type"]
+            type = SYM_STRAIGHT_DURS[i+1]["type"]
             normal_notes = 2
+            while (normal_notes * STRAIGHT_DURS[i + 1] / qdur) % 1 > eps:
+                normal_notes += 1
             return {
                 "type": type,
-                "actual_notes": math.ceil(normal_notes / qdur),
+                "actual_notes": math.ceil(normal_notes * STRAIGHT_DURS[i+1]  / qdur),
                 "normal_notes": normal_notes,
             }
 

From 0e7794762822412430362fad88dc9461316ab74f Mon Sep 17 00:00:00 2001
From: melkisedeath <manoskaristineos@gmail.com>
Date: Mon, 9 Sep 2024 15:51:34 +0200
Subject: [PATCH 3/9] Test for symbolic duration estimator.

---
 tests/test_utils.py | 65 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/tests/test_utils.py b/tests/test_utils.py
index 87e95bdd..1d558f4a 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -643,3 +643,68 @@ def test_tokenize2(self):
             pt_tokens = [tok for tok in pt_tokens if not tok.startswith("Velocity")]
             mtok_tokens = [tok for tok in mtok_tokens if not tok.startswith("Velocity")]
             self.assertTrue(pt_tokens == mtok_tokens)
+
+
+    class TestSymbolicDurationEstimator(unittest.TestCase):
+        def test_estimate_symbolic_duration(self):
+            """
+            Test `estimate_symbolic_duration`
+            """
+            divs = 12
+            quarters = 4
+            expected = [
+                {},
+                {'type': '32nd', 'actual_notes': 3, 'normal_notes': 2},
+                {'type': '16th', 'actual_notes': 3, 'normal_notes': 2},
+                {'type': '16th', 'dots': 0},
+                {'type': 'eighth', 'actual_notes': 3, 'normal_notes': 2},
+                ({'type': '16th', 'dots': 0}, {'type': '16th', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                {'type': 'eighth', 'dots': 0},
+                ({'type': 'eighth', 'dots': 0}, {'type': '32nd', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                {'type': 'quarter', 'actual_notes': 3, 'normal_notes': 2},
+                {'type': 'eighth', 'dots': 1},
+                ({'type': 'eighth', 'dots': 0}, {'type': 'eighth', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                ({'type': 'eighth', 'dots': 1}, {'type': '16th', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                {'type': 'quarter', 'dots': 0},
+                ({'type': 'quarter', 'dots': 0}, {'type': '32nd', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                ({'type': 'quarter', 'dots': 0}, {'type': '16th', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                ({'type': 'quarter', 'dots': 0}, {'type': '16th', 'dots': 0}),
+                {'type': 'half', 'actual_notes': 3, 'normal_notes': 2},
+                ({'type': 'quarter', 'dots': 0}, {'type': '16th', 'dots': 0}, {'type': '16th', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                {'type': 'quarter', 'dots': 1},
+                ({'type': 'quarter', 'dots': 1}, {'type': '32nd', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                ({'type': 'quarter', 'dots': 1}, {'type': '16th', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                {'type': 'quarter', 'dots': 2},
+                ({'type': 'quarter', 'dots': 1}, {'type': 'eighth', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                ({'type': 'quarter', 'dots': 2}, {'type': '16th', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                {'type': 'half', 'dots': 0},
+                ({'type': 'half', 'dots': 0}, {'type': '32nd', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                ({'type': 'half', 'dots': 0}, {'type': '16th', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                ({'type': 'half', 'dots': 0}, {'type': '16th', 'dots': 0}),
+                ({'type': 'half', 'dots': 0}, {'type': 'eighth', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                ({'type': 'half', 'dots': 0}, {'type': '16th', 'dots': 0}, {'type': '16th', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                ({'type': 'half', 'dots': 0}, {'type': '16th', 'dots': 0}, {'type': '16th', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                ({'type': 'half', 'dots': 0}, {'type': 'eighth', 'dots': 0}),
+                ({'type': 'half', 'dots': 0}, {'type': 'eighth', 'dots': 0}, {'type': '32nd', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                ({'type': 'half', 'dots': 0}, {'type': 'quarter', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                ({'type': 'half', 'dots': 0}, {'type': 'eighth', 'dots': 1}),
+                ({'type': 'half', 'dots': 0}, {'type': 'eighth', 'dots': 0}, {'type': 'eighth', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                {'type': 'half', 'dots': 1},
+                ({'type': 'half', 'dots': 0}, {'type': 'eighth', 'dots': 1}, {'type': '16th', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                ({'type': 'half', 'dots': 1}, {'type': '32nd', 'dots': 0}),
+                ({'type': 'half', 'dots': 1}, {'type': '16th', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                ({'type': 'half', 'dots': 1}, {'type': '16th', 'dots': 0}),
+                ({'type': 'half', 'dots': 1}, {'type': 'eighth', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                {'type': 'half', 'dots': 2},
+                ({'type': 'half', 'dots': 1}, {'type': '16th', 'dots': 0}, {'type': '16th', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                ({'type': 'half', 'dots': 1}, {'type': '16th', 'dots': 0}, {'type': '16th', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                {'type': 'half', 'dots': 3},
+                ({'type': 'half', 'dots': 2}, {'type': '32nd', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                ({'type': 'half', 'dots': 1}, {'type': 'quarter', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+            ]
+            predicted = []
+            for k in range(divs * 0, divs * quarters):
+                a = partitura.utils.estimate_symbolic_duration(
+                    k, divs, return_com_durations=True)
+                predicted.append(a)
+            self.assertTrue(all([expected[i] == predicted[i] for i in range(len(expected))]))
\ No newline at end of file

From 5784c1c874b8deb497dd6fd8fdfc3325b6c6300e Mon Sep 17 00:00:00 2001
From: sildater <silvandavidpeter@gmail.com>
Date: Tue, 24 Sep 2024 13:51:07 +0200
Subject: [PATCH 4/9] find closest straight duration below

---
 partitura/utils/music.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/partitura/utils/music.py b/partitura/utils/music.py
index e6afe4ea..dccc4192 100644
--- a/partitura/utils/music.py
+++ b/partitura/utils/music.py
@@ -775,7 +775,7 @@ def estimate_symbolic_duration(
                           f"Returning empty symbolic duration.")
             return {}
         else:
-            i = find_nearest(STRAIGHT_DURS, qdur)
+            i = np.searchsorted(STRAIGHT_DURS, qdur, side="left") - 1
             # NOTE: Guess tuplets (Naive) it doesn't cover composite durations from tied notes.
             type = SYM_STRAIGHT_DURS[i+1]["type"]
             normal_notes = 2

From c3e35cebd816db86963ed7afcd4b710f71695c64 Mon Sep 17 00:00:00 2001
From: sildater <silvandavidpeter@gmail.com>
Date: Tue, 24 Sep 2024 13:53:11 +0200
Subject: [PATCH 5/9] remove duplicate sym durs

---
 partitura/utils/globals.py | 2 --
 1 file changed, 2 deletions(-)

diff --git a/partitura/utils/globals.py b/partitura/utils/globals.py
index ca42dbb6..8571e025 100644
--- a/partitura/utils/globals.py
+++ b/partitura/utils/globals.py
@@ -359,7 +359,6 @@
     ({"type": "half", "dots": 0}, {"type": "16th", "dots": 0}),
     ({"type": "half", "dots": 0}, {"type": "eighth", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
     ({"type": "half", "dots": 0}, {"type": "16th", "dots": 0}, {"type": "16th", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
-    ({"type": "half", "dots": 0}, {"type": "16th", "dots": 0}, {"type": "16th", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
     ({"type": "half", "dots": 0}, {"type": "eighth", "dots": 0}),
     ({"type": "half", "dots": 0}, {"type": "eighth", "dots": 0}, {"type": "32nd", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
     ({"type": "half", "dots": 0}, {"type": "quarter", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
@@ -372,7 +371,6 @@
     ({"type": "half", "dots": 1}, {"type": "16th", "dots": 0}),
     ({"type": "half", "dots": 1}, {"type": "eighth", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
     ({"type": "half", "dots": 1}, {"type": "16th", "dots": 0}, {"type": "16th", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
-    ({"type": "half", "dots": 1}, {"type": "16th", "dots": 0}, {"type": "16th", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
     ({"type": "half", "dots": 2}, {"type": "32nd", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
     ({"type": "half", "dots": 1}, {"type": "quarter", "dots": 0, "actual_notes": 3, "normal_notes": 2}),
     ({"type": "half", "dots": 2}, {"type": "eighth", "dots": 0, "actual_notes": 3, "normal_notes": 2}),

From 7ab8b3f4852c2b779c55c799be04bbbea89b9a11 Mon Sep 17 00:00:00 2001
From: sildater <silvandavidpeter@gmail.com>
Date: Tue, 24 Sep 2024 14:28:19 +0200
Subject: [PATCH 6/9] set test to eighth note quintuplets

---
 tests/test_midi_import.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/test_midi_import.py b/tests/test_midi_import.py
index 0255d38e..9389a34b 100644
--- a/tests/test_midi_import.py
+++ b/tests/test_midi_import.py
@@ -136,7 +136,7 @@ def make_triplets_example_2():
     fill_track(track, notes, divs)
     # target:
     actual_notes = [5] * 5 + [3] * 3
-    normal_notes = [2] * 5 + [2] * 3
+    normal_notes = [4] * 5 + [2] * 3
     return mid, actual_notes, normal_notes
 
 

From e51b3e3fdff3564a555482fc0207f235974b85d1 Mon Sep 17 00:00:00 2001
From: sildater <silvandavidpeter@gmail.com>
Date: Tue, 24 Sep 2024 14:49:22 +0200
Subject: [PATCH 7/9] duration test estimation

---
 tests/test_utils.py | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/tests/test_utils.py b/tests/test_utils.py
index 1d558f4a..8eff8147 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -683,24 +683,24 @@ def test_estimate_symbolic_duration(self):
                 ({'type': 'half', 'dots': 0}, {'type': '16th', 'dots': 0}),
                 ({'type': 'half', 'dots': 0}, {'type': 'eighth', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
                 ({'type': 'half', 'dots': 0}, {'type': '16th', 'dots': 0}, {'type': '16th', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
-                ({'type': 'half', 'dots': 0}, {'type': '16th', 'dots': 0}, {'type': '16th', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
                 ({'type': 'half', 'dots': 0}, {'type': 'eighth', 'dots': 0}),
                 ({'type': 'half', 'dots': 0}, {'type': 'eighth', 'dots': 0}, {'type': '32nd', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
                 ({'type': 'half', 'dots': 0}, {'type': 'quarter', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
                 ({'type': 'half', 'dots': 0}, {'type': 'eighth', 'dots': 1}),
                 ({'type': 'half', 'dots': 0}, {'type': 'eighth', 'dots': 0}, {'type': 'eighth', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
-                {'type': 'half', 'dots': 1},
                 ({'type': 'half', 'dots': 0}, {'type': 'eighth', 'dots': 1}, {'type': '16th', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
-                ({'type': 'half', 'dots': 1}, {'type': '32nd', 'dots': 0}),
+                {'type': 'half', 'dots': 1},
+                ({'type': 'half', 'dots': 1}, {'type': '32nd', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
                 ({'type': 'half', 'dots': 1}, {'type': '16th', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
                 ({'type': 'half', 'dots': 1}, {'type': '16th', 'dots': 0}),
                 ({'type': 'half', 'dots': 1}, {'type': 'eighth', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
-                {'type': 'half', 'dots': 2},
                 ({'type': 'half', 'dots': 1}, {'type': '16th', 'dots': 0}, {'type': '16th', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
-                ({'type': 'half', 'dots': 1}, {'type': '16th', 'dots': 0}, {'type': '16th', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
-                {'type': 'half', 'dots': 3},
+                {'type': 'half', 'dots': 2},
                 ({'type': 'half', 'dots': 2}, {'type': '32nd', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
                 ({'type': 'half', 'dots': 1}, {'type': 'quarter', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                {'type': 'half', 'dots': 3},
+                ({'type': 'half', 'dots': 2}, {'type': 'eighth', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
+                ({'type': 'half', 'dots': 3}, {'type': '16th', 'dots': 0, 'actual_notes': 3, 'normal_notes': 2}),
             ]
             predicted = []
             for k in range(divs * 0, divs * quarters):

From 3056e0a6a54b2a8ef9d684c8a129f88b622cab3c Mon Sep 17 00:00:00 2001
From: sildater <silvandavidpeter@gmail.com>
Date: Tue, 24 Sep 2024 14:55:23 +0200
Subject: [PATCH 8/9] file formatting

---
 tests/test_utils.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/test_utils.py b/tests/test_utils.py
index 8eff8147..a8d539c5 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -707,4 +707,5 @@ def test_estimate_symbolic_duration(self):
                 a = partitura.utils.estimate_symbolic_duration(
                     k, divs, return_com_durations=True)
                 predicted.append(a)
-            self.assertTrue(all([expected[i] == predicted[i] for i in range(len(expected))]))
\ No newline at end of file
+            self.assertTrue(all([expected[i] == predicted[i] for i in range(len(expected))]))
+            
\ No newline at end of file

From c159bc99b4589c37eb4558c2f03fdaee8ed96027 Mon Sep 17 00:00:00 2001
From: Emmanouil Karystinaios <manoskaristineos@gmail.com>
Date: Wed, 2 Oct 2024 14:40:35 +0200
Subject: [PATCH 9/9] Update globals.py

added comment for global straght_durs.
---
 partitura/utils/globals.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/partitura/utils/globals.py b/partitura/utils/globals.py
index 8571e025..ad8e17dc 100644
--- a/partitura/utils/globals.py
+++ b/partitura/utils/globals.py
@@ -192,6 +192,7 @@
     {"type": "long", "dots": 3},
 ]
 
+# Straight durs do not include copies for naming or dots, when searching they work better for base triplet types in `estimate_symbolic_duration`.
 STRAIGHT_DURS = np.array(
     [ 4 / 256, 4 / 128, 4 / 64, 4 / 32, 4 / 16, 4 / 8, 4 / 4, 4 / 2, 4 / 1, 4 / 0.5, 4 / 0.25]
 )