Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Let makeTies() iterate over parts #1561

Closed
TimFelixBeyer opened this issue May 9, 2023 · 8 comments · Fixed by #1571
Closed

Let makeTies() iterate over parts #1561

TimFelixBeyer opened this issue May 9, 2023 · 8 comments · Fixed by #1571

Comments

@TimFelixBeyer
Copy link
Contributor

TimFelixBeyer commented May 9, 2023

music21 version
master

Problem summary
makeTies throws StreamException: cannot process a stream without measures on score with measures.

Steps to reproduce

from music21 import stream, note, meter, tie

s = stream.Score(id='mainScore')
p0 = stream.Part(id='part0')

m01 = stream.Measure(number=1)
m01.append(meter.TimeSignature('4/4'))
d1 = note.Note('D', type="half", dots=1)
c1 = note.Note('C', type="quarter")
c1.tie = tie.Tie("start")
m01.append([d1, c1])
m02 = stream.Measure(number=2)
c2 = note.Note('C', type="quarter")
c2.tie = tie.Tie("stop")
c3 = note.Note("D", type="half")
m02.append([c2, c3])
p0.append([m01, m02])

s.insert(0, p0)
s.show("text")  # just to verify that there are measures in the score 
s = s.stripTies()
# s = s.makeMeasures()  # does not help
s = s.makeTies()

More information
Related to #1557


3
Your example is a score that has had stripTies() run on it, yielding an overfilled first measure and an underfilled second measure. I think I would expect that making rests on that would fill the second measure.

If you want to display the stripped ties score (are you sure you want to display that?) then you could makeTies() on it first, which restores the output I think you're expecting.


Originally posted by @jacobtylerwalls in #1557 (comment)

@mscuthbert
Copy link
Member

I've never really worked with stripTies() except in the context of a flatten()'d stream, so I'm not surprised this is a problem.

@TimFelixBeyer TimFelixBeyer changed the title makeTies fails after stripTies makeTies fails May 10, 2023
@TimFelixBeyer
Copy link
Contributor Author

Just found out that it also fails without stripTies():

from music21 import stream, note, meter, tie

s = stream.Score(id='mainScore')
p0 = stream.Part(id='part0')

m01 = stream.Measure(number=1)
m01.append(meter.TimeSignature('4/4'))
d1 = note.Note('D', type="half", dots=1)
c1 = note.Note('C', type="quarter")
c1.tie = tie.Tie("start")
m01.append([d1, c1])
m02 = stream.Measure(number=2)
c2 = note.Note('C', type="quarter")
c2.tie = tie.Tie("stop")
c3 = note.Note("D", type="half")
m02.append([c2, c3])
p0.append([m01, m02])

s.insert(0, p0)
s.show("text")  # just to verify that there are measures in the score 
# s = s.makeMeasures()  # does not help
s = s.makeTies()

This also fails when called on the example score from here (makeMeasures does not help there either): https://web.mit.edu/music21/doc/usersGuide/usersGuide_06_stream2.html

@jacobtylerwalls
Copy link
Member

jacobtylerwalls commented May 10, 2023

When the exception message says "with/without", it means "directly containing", not "recursively containing". Your score doesn't directly contain measures; the parts do.

Try:

>>> for p in s.parts:
...   p.makeTies(inPlace=True)
...

Leaving the issue open for now to discuss the possibility of adding the trivially easy enhancement to iterate over parts of a score automatically.

@jacobtylerwalls jacobtylerwalls changed the title makeTies fails Let makeTies() iterate over parts May 10, 2023
@TimFelixBeyer
Copy link
Contributor Author

I think that makeTies should be the conceptual opposite to stripTies, which itself already iterates over parts and voices if required

music21/music21/stream/base.py

Lines 7257 to 7278 in 42534a3

if returnObj.hasPartLikeStreams():
# part-like does not necessarily mean that the next level down is a stream.Part
# object or that this is a stream.Score object, so do not substitute
# returnObj.parts for this...
for p in returnObj.getElementsByClass(Stream):
# already copied if necessary; edit in place
p.stripTies(inPlace=True, matchByPitch=matchByPitch)
if not inPlace:
return returnObj
else:
return # exit
if returnObj.hasVoices():
for v in returnObj.voices:
# already copied if necessary; edit in place
v.stripTies(inPlace=True, matchByPitch=matchByPitch)
if not inPlace:
return returnObj
else:
return # exit
# need to just get .notesAndRests with a nonzero duration,

LMK if that's something I should prepare a PR for or whether further discussion is required!

@jacobtylerwalls
Copy link
Member

I'd welcome such a PR, it brings that method into alignment with other related stream methods without significantly increasing the API footprint. Many thanks!

@mscuthbert
Copy link
Member

I'm okay with having it in, but I think it is an extremely complex undertaking for an early PR to the project. Having makeTies iterate over parts (and for Opus objects, also Scores) is a more managable start.

@jacobtylerwalls
Copy link
Member

Having makeTies iterate over parts (and for Opus objects, also Scores) is a more managable start.

That's all I was referring to. @TimFelixBeyer were you referring to something else?

@mscuthbert
Copy link
Member

I thought he was referring to having makeTies() more fully undo stripTies() and also separate chords into multiple voices. I must have misread. Yes, having them iterate over parts is a very welcome and manageable first mergable PR.

TimFelixBeyer added a commit to TimFelixBeyer/music21 that referenced this issue May 15, 2023
Allows makeTies to iterate over substreams and includes a regression test.
mscuthbert added a commit that referenced this issue Jul 2, 2023
* Fix #1561: Let makeTies iterate over parts 

Allows makeTies to iterate over substreams and includes a regression test.

* Fix linting

* add tests, remove hasVoices check (untested code)

* flake

---------

Co-authored-by: Michael Scott Asato Cuthbert <michael.asato.cuthbert@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants