def test_height(self): # 5 lines assert_almost_equal( Staff((Mm(0), Mm(0)), Mm(100), self.flowable, staff_unit=Mm(1.5), line_count=5).height, Mm(6), ) assert_almost_equal( Staff((Mm(0), Mm(0)), Mm(100), self.flowable, staff_unit=Mm(1), line_count=5).height, Mm(4), ) # 4 lines assert_almost_equal( Staff((Mm(0), Mm(0)), Mm(100), self.flowable, staff_unit=Mm(1.5), line_count=4).height, Mm(4.5), ) assert_almost_equal( Staff((Mm(0), Mm(0)), Mm(100), self.flowable, staff_unit=Mm(1), line_count=4).height, Mm(3), )
def test_active_clef_at_with_explicit_clefs(self): staff = Staff((Mm(0), Mm(0)), Mm(100), self.flowable) Clef(staff, Mm(0), "treble") Clef(staff, Mm(10), "bass") # Test between two clefs should have treble in effect assert staff.active_clef_at(Mm(1)).clef_type == ClefType.TREBLE # Test after bass clef goes into effect assert staff.active_clef_at(Mm(11)).clef_type == ClefType.BASS
class TestFlag(unittest.TestCase): def setUp(self): neoscore.setup() self.staff = Staff((Mm(0), Mm(0)), Mm(100), flowable=None) def test_glyphnames(self): # All flags with durations in the following denominations should # be init-able without error. for i in [1024, 512, 256, 128, 64, 32, 16, 8]: Flag(Beat(1, i), 1, self.staff) Flag(Beat(1, i), -1, self.staff) def test_invalid_direction_raises_value_error(self): with pytest.raises(ValueError): Flag(Beat(1, 8), 0, self.staff) with pytest.raises(ValueError): Flag(Beat(1, 8), 2, self.staff) with pytest.raises(ValueError): Flag(Beat(1, 8), -2, self.staff) def test_needs_flag(self): assert Flag.needs_flag(Beat(1, 4)) is False assert Flag.needs_flag(Beat(1, 2)) is False assert Flag.needs_flag(Beat(1, 8)) is True assert Flag.needs_flag(Beat(1, 16)) is True def test_vertical_offset_needed(self): self.assertEqual( Flag.vertical_offset_needed(Beat(1, 4), self.staff.unit), self.staff.unit(0)) self.assertEqual( Flag.vertical_offset_needed(Beat(1, 8), self.staff.unit), self.staff.unit(1)) self.assertEqual( Flag.vertical_offset_needed(Beat(1, 16), self.staff.unit), self.staff.unit(1), ) def test_raises_no_flag_needed_error(self): # Test valid durations Flag(Beat(1, 16), 1, self.staff) Flag(Beat(1, 8), 1, self.staff) # Test invalid durations with pytest.raises(NoFlagNeededError): Flag(Beat(1, 4), 1, self.staff) with pytest.raises(NoFlagNeededError): Flag(Beat(1, 2), 1, self.staff) with pytest.raises(NoFlagNeededError): Flag(Beat(1, 1), 1, self.staff)
def test_middle_c_at_with_active_octave_line(self): staff = Staff((Mm(0), Mm(0)), Mm(100), self.flowable) Clef(staff, Mm(0), "treble") octave_line = OctaveLine((Mm(20), Mm(0)), staff, Mm(80), indication="8va") # Before octave_line goes into effect assert staff.middle_c_at(Mm(0)) == staff.unit(5) # While octave_line is in effect assert staff.middle_c_at(Mm(20)) == staff.unit(8.5) assert staff.middle_c_at(Mm(100)) == staff.unit(8.5) # After octave_line ends assert staff.middle_c_at(Mm(101)) == staff.unit(5)
class TestMultiStaffObject(unittest.TestCase): def setUp(self): neoscore.setup() self.flowable = Flowable((Mm(0), Mm(0)), Mm(10000), Mm(30), Mm(5)) self.staff_1 = Staff((Mm(0), Mm(0)), Mm(100), self.flowable) self.staff_2 = Staff((Mm(0), Mm(30)), Mm(100), self.flowable) self.staff_3 = Staff((Mm(0), Mm(50)), Mm(100), self.flowable) def test_visually_sorted_staves(self): multi_object = MultiStaffObject( {self.staff_1, self.staff_2, self.staff_3}) assert multi_object.visually_sorted_staves == [ self.staff_1, self.staff_2, self.staff_3, ] def test_highest_staff(self): multi_object = MultiStaffObject( {self.staff_1, self.staff_2, self.staff_3}) assert multi_object.highest_staff == self.staff_1 def test_lowest_staff(self): multi_object = MultiStaffObject( {self.staff_1, self.staff_2, self.staff_3}) assert multi_object.lowest_staff == self.staff_3 def test_vertical_span(self): multi_object = MultiStaffObject( {self.staff_1, self.staff_2, self.staff_3}) assert_almost_equal(multi_object.vertical_span, self.staff_3.unit(4) + Mm(50))
def setUp(self): neoscore.setup() self.staff = Staff((Mm(0), Mm(0)), Mm(100), flowable=None, staff_unit=Mm(1)) self.font = MusicFont(constants.DEFAULT_MUSIC_FONT_NAME, self.staff.unit)
def setUp(self): neoscore.setup() self.flowable = Flowable((Mm(0), Mm(0)), Mm(10000), Mm(30), Mm(5)) self.staff = Staff((Mm(0), Mm(0)), Mm(5000), self.flowable) self.left_parent = MockStaffObject((Mm(0), Mm(0)), self.staff) self.right_parent = MockStaffObject((Mm(10), Mm(2)), self.staff) self.char = "gClef" self.single_repetition_width = MusicText((Mm(0), Mm(0)), self.char, self.staff, scale=2).bounding_rect.width
def test_elements_when_not_located_at_origin(self): """Regression test Ensure lines are drawn at the correct locations when staff is not positioned at (0, 0) """ staff = Staff((Mm(2), Mm(3)), Mm(10), self.flowable, staff_unit=Mm(1), line_count=5) staff._render() # Top line assert staff.elements[0].pos == Point(Mm(0), Mm(0)) assert staff.elements[0].parent == staff assert staff.elements[1].pos == Point(Mm(10), Mm(0)) assert staff.elements[1].parent == staff # Second line assert staff.elements[2].pos == Point(Mm(0), Mm(1)) assert staff.elements[2].parent == staff assert staff.elements[3].pos == Point(Mm(10), Mm(1)) assert staff.elements[3].parent == staff
def test_middle_c_at_with_explicit_clefs(self): staff = Staff((Mm(0), Mm(0)), Mm(100), self.flowable) Clef(staff, Mm(0), "treble") Clef(staff, Mm(10), "bass") # Test between two clefs should be in treble mode assert staff.middle_c_at(Mm(1)) == staff.unit(5) # Test after bass clef goes into effect assert staff.middle_c_at(Mm(11)) == staff.unit(-1)
def __init__( self, pos_x: Unit, staff: Staff, pitches: Optional[list[PitchDef]], duration: BeatDef, stem_direction: Optional[int] = None, ): """ Args: pos_x: The horizontal position staff: The staff the object is attached to pitches: A list of pitch strings representing noteheads. An empty list or `None` indicates a rest. duration: The duration of the Chordrest stem_direction: An optional stem direction override where `1` points down and `-1` points up. If omitted, the direction is automatically calculated to point away from the furthest-out notehead. """ StaffObject.__init__(self, staff) ObjectGroup.__init__(self, Point(pos_x, staff.unit(0)), staff, None) self.duration = duration self._noteheads = set() self._accidentals = set() self._ledgers = set() self._dots = set() self._noteheads = set() self._stem_direction_override = stem_direction if pitches: for pitch in pitches: self._noteheads.add(Notehead(staff.unit(0), pitch, self.duration, self)) self.rest = None else: # TODO LOW support explicit rest Y positioning self.rest = Rest(Point(staff.unit(0), staff.unit(2)), self, duration) self._stem = None self._flag = None
def test_active_transposition_at_with_octave_line_with_staff_parent(self): staff = Staff((Mm(0), Mm(0)), Mm(100), self.flowable) octave_line = OctaveLine((Mm(20), Mm(0)), staff, Mm(80), indication="8va") assert staff.active_transposition_at(Mm(0)) is None assert staff.active_transposition_at( Mm(20)) == octave_line.transposition assert staff.active_transposition_at( Mm(100)) == octave_line.transposition assert staff.active_transposition_at(Mm(101)) is None
def __init__( self, pos_x: Unit, staff: Staff, key_signature_type: Union[KeySignatureType, str], ): """ Args: pos_x (Unit): The x position relative to the parent staff. staff (Staff): The parent staff key_signature_type (KeySignatureType or str): A description of the key signature. Any KeySignatureType may be used, or a str of one's name. """ ObjectGroup.__init__(self, Point(pos_x, staff.unit(0)), staff) StaffObject.__init__(self, staff) self._key_signature_type = ( key_signature_type if isinstance(key_signature_type, KeySignatureType) else KeySignatureType[key_signature_type.upper()]) self._create_pseudo_accidentals()
def __init__(self, staff: Staff, pos_x: Unit, clef_type: Union[ClefType, str]): """ Args: staff (Staff): pos_x (Unit): clef_type (ClefType or str): The type of clef. For convenience, any `str` of a `ClefType` enum name may be passed. Raises: KeyError: If the given `clef_type` is not a valid `ClefType` or `ClefType` enum name. """ if isinstance(clef_type, ClefType): self._clef_type = clef_type else: self._clef_type = ClefType[clef_type.upper()] MusicText.__init__(self, (pos_x, staff.unit(0)), self._canonical_names[self._clef_type], staff) StaffObject.__init__(self, staff) self.y = self.staff_position
def setUp(self): neoscore.setup() self.flowable = Flowable((Mm(0), Mm(0)), Mm(10000), Mm(30), Mm(5)) self.staff = Staff((Mm(0), Mm(0)), Mm(5000), self.flowable) self.left_parent = MockStaffObject((Unit(0), Unit(0)), self.staff) self.right_parent = MockStaffObject((Unit(10), Unit(2)), self.staff)
def setUp(self): neoscore.setup() self.staff = Staff((Mm(0), Mm(0)), Mm(100), flowable=None)
def setUp(self): neoscore.setup() self.flowable = Flowable((Mm(0), Mm(0)), Mm(10000), Mm(30), Mm(5)) self.staff_1 = Staff((Mm(0), Mm(0)), Mm(100), self.flowable) self.staff_2 = Staff((Mm(0), Mm(30)), Mm(100), self.flowable) self.staff_3 = Staff((Mm(0), Mm(50)), Mm(100), self.flowable)
class Score(ObjectGroup): _TEXT_FONT_SIZE = GridUnit(0.6).base_value _MUSIC_FONT_SIZE = Staff._make_unit_class(GridUnit(0.5)) _bar_line_pen = Pen(thickness=GridUnit(0.05), pattern=PenPattern.DOT) _instrument_divider_pen = Pen(thickness=GridUnit(0.05)) def __init__(self, pos, instruments, parent): super().__init__(pos, parent) self.events = [] self.text_font = neoscore.default_font.modified( size=Score._TEXT_FONT_SIZE, weight=60) self.music_font = MusicFont(constants.DEFAULT_MUSIC_FONT_NAME, Score._MUSIC_FONT_SIZE) self.instruments = instruments for i, instrument in enumerate(instruments): for event_data in instrument.event_data: self.events.append(self._create_event(i, event_data)) self.draw_instrument_dividers() self.draw_bar_lines() def _create_event(self, instrument_index, event_data): if isinstance(event_data.text, GlyphName): return self._create_music_text_event(instrument_index, event_data) return self._create_text_event(instrument_index, event_data) def _create_text_event(self, instrument_index, event_data): return TextEvent( ( event_data.pos_x, (Score._instrument_pos_y(instrument_index) + event_data.register.value), ), self, event_data.length, event_data.text, self.text_font, ) def _create_music_text_event(self, instrument_index, event_data): return MusicTextEvent( ( event_data.pos_x, (Score._instrument_pos_y(instrument_index) + event_data.register.value), ), self, event_data.length, event_data.text, self.music_font, ) @property def measure_count(self): return (max( max(int(Measure(e.pos_x).display_value) for e in i.event_data) for i in self.instruments) + 1) @staticmethod def _instrument_pos_y(instrument_index): return GridUnit(3 * instrument_index) @staticmethod def _divider_pos_y(divider_index): return GridUnit(3 * divider_index) @staticmethod def _divider_visible( instrument_above: Union[InstrumentData, None], instrument_below: Union[InstrumentData, None], measure_num: int, ) -> bool: return (instrument_above is not None and instrument_above.measure_has_events(measure_num)) or ( instrument_below is not None and instrument_below.measure_has_events(measure_num)) def _bar_line_extends_below(self, measure_num: int, divider_num: int) -> bool: if divider_num >= len(self.instruments): return False instrument = self.instruments[divider_num] return instrument.measure_has_events( measure_num - 1) or instrument.measure_has_events(measure_num) def draw_instrument_dividers(self): for divider in range(len(self.instruments) + 1): current_path = Path( (Measure(0), Score._divider_pos_y(divider)), pen=Score._instrument_divider_pen, parent=self, ) instrument_above = self.instruments[divider - 1] if divider > 0 else None instrument_below = (self.instruments[divider] if divider < len(self.instruments) else None) drawing = False for measure_num in range(self.measure_count + 1): if Score._divider_visible(instrument_above, instrument_below, measure_num): if not drawing: current_path.move_to(Measure(measure_num), GridUnit(0)) drawing = True else: if drawing: current_path.line_to(Measure(measure_num), GridUnit(0)) drawing = False def draw_bar_lines(self): for measure_num in range(self.measure_count + 1): current_path = Path( (Measure(measure_num), GridUnit(0)), pen=Score._bar_line_pen, parent=self, ) drawing = False for divider_num in range(len(self.instruments) + 1): if self._bar_line_extends_below(measure_num, divider_num): if not drawing: current_path.move_to( GridUnit(0), Score._instrument_pos_y(divider_num)) drawing = True else: if drawing: current_path.line_to( GridUnit(0), Score._instrument_pos_y(divider_num)) drawing = False
class TestChordrest(unittest.TestCase): def setUp(self): neoscore.setup() self.flowable = Flowable(Point(Mm(0), Mm(0)), Mm(10000), Mm(100)) self.staff = Staff(Point(Mm(0), Mm(0)), Mm(100), self.flowable) Clef(self.staff, Mm(0), "treble") def test_ledger_line_positions(self): pitches = ["c'", "b'", "f'''"] chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4)) assert chord.ledger_line_positions == [ self.staff.unit(5), self.staff.unit(-3), self.staff.unit(-2), self.staff.unit(-1), ] def test_ledger_line_positions_with_different_clef(self): Clef(self.staff, Mm(10), "bass") pitches = ["e,", "d", "e'"] chord = Chordrest(Mm(15), self.staff, pitches, Beat(1, 4)) assert chord.ledger_line_positions == [ self.staff.unit(5), self.staff.unit(-2), self.staff.unit(-1), ] def test_rhythm_dot_positions_with_rest(self): chord = Chordrest(Mm(1), self.staff, None, Beat(7, 16)) dots = list(chord.rhythm_dot_positions) dots.sort(key=lambda d: d.x) assert_almost_equal( dots[0], Point(self.staff.unit(1.326), self.staff.unit(1.5)) ) assert_almost_equal( dots[1], Point(self.staff.unit(1.826), self.staff.unit(1.5)) ) def test_rhythm_dot_positions_with_noteheads(self): pitches = ["e,", "d", "e'''"] chord = Chordrest(Mm(1), self.staff, pitches, Beat(7, 16)) dots = list(chord.rhythm_dot_positions) dots.sort(key=lambda d: d.x) dots.sort(key=lambda d: d.y) assert_almost_equal( dots[0], Point(self.staff.unit(1.43), self.staff.unit(-3.5)) ) assert_almost_equal( dots[1], Point(self.staff.unit(1.93), self.staff.unit(-3.5)) ) assert_almost_equal(dots[2], Point(self.staff.unit(1.43), self.staff.unit(7.5))) assert_almost_equal(dots[3], Point(self.staff.unit(1.93), self.staff.unit(7.5))) assert_almost_equal( dots[4], Point(self.staff.unit(1.43), self.staff.unit(10.5)) ) assert_almost_equal( dots[5], Point(self.staff.unit(1.93), self.staff.unit(10.5)) ) def test_furthest_notehead_with_one_note(self): pitches = ["b'"] chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4)) assert chord.furthest_notehead.pitch == Pitch("b'") pitches = ["f'''"] chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4)) assert chord.furthest_notehead.pitch == Pitch("f'''") pitches = ["c,,,,"] chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4)) assert chord.furthest_notehead.pitch == Pitch("c,,,,") def test_furthest_notehead_with_many_notes(self): pitches = ["b''", "bs'"] chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4)) assert chord.furthest_notehead.pitch == Pitch("b''") pitches = ["b'", "b,,,"] chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4)) assert chord.furthest_notehead.pitch == Pitch("b,,,") pitches = ["f''''", "b"] chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4)) assert chord.furthest_notehead.pitch == Pitch("f''''") pitches = ["c'", "c,,,,", "b'", "c'''"] chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4)) assert chord.furthest_notehead.pitch == Pitch("c,,,,") def test_highest_notehead(self): pitches = ["c'", "b'", "c'''"] chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4)) assert chord.highest_notehead.pitch == Pitch("c'''") def test_lowest_notehead(self): pitches = ["c'", "b'", "c'''"] chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4)) assert chord.lowest_notehead.pitch == Pitch("c'") def test_highest_and_lowest_notehead_same_with_one_note(self): pitches = ["c'"] chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4)) assert chord.highest_notehead == chord.lowest_notehead def test_stem_direction_down(self): pitches = ["c'", "b'", "c''''"] chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4)) assert chord.stem_direction == 1 def test_stem_direction_up(self): pitches = ["c,,,,,", "b'", "c'''"] chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4)) assert chord.stem_direction == -1 def test_stem_direction_down_with_one_note_at_staff_center(self): pitches = ["b'"] chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4)) assert chord.stem_direction == 1 def test_stem_direction_override(self): pitches = ["b'"] chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4), -1) assert chord.stem_direction == -1 # Setting stem_direction = None should revert to default 1 chord.stem_direction = None assert chord.stem_direction == 1 def test_stem_height_min(self): pitches = ["b'"] chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4)) assert_almost_equal(chord.stem_height, self.staff.unit(3)) def test_stem_height_fitted(self): pitches = ["c'''", "g"] chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4)) assert_almost_equal(chord.stem_height, self.staff.unit(-10.5))
def setUp(self): neoscore.setup() self.flowable = Flowable(Point(Mm(0), Mm(0)), Mm(10000), Mm(100)) self.staff = Staff(Point(Mm(0), Mm(0)), Mm(100), self.flowable) Clef(self.staff, Mm(0), "treble")
def setUp(self): neoscore.setup(Paper(*[Mm(val) for val in [210, 297, 20, 20, 20, 20, 10]])) self.flowable = Flowable((Mm(0), Mm(0)), Mm(10000), Mm(30), Mm(5)) self.staff = Staff((Mm(0), Mm(0)), Mm(5000), self.flowable)
def test_middle_c_at_with_implicit_default_clef(self): staff = Staff((Mm(0), Mm(0)), Mm(100), self.flowable) with pytest.raises(NoClefError): staff.middle_c_at(Mm(5))
def test_position_inside_staff_with_even_line_count(self): staff = Staff((Mm(0), Mm(0)), Mm(100), self.flowable, line_count=4) assert staff.y_inside_staff(staff.unit(0)) is True assert staff.y_inside_staff(staff.unit(3)) is True assert staff.y_inside_staff(staff.unit(4)) is False assert staff.y_inside_staff(staff.unit(-4)) is False
def test_active_clef_at_with_implicit_default_clef(self): staff = Staff((Mm(0), Mm(0)), Mm(100), self.flowable) assert staff.active_clef_at(Mm(5)) is None
def test_position_on_ledger_with_odd_line_count(self): staff = Staff((Mm(0), Mm(0)), Mm(100), self.flowable, line_count=5) assert staff.y_on_ledger(staff.unit(-1)) is True assert staff.y_on_ledger(staff.unit(-0.5)) is False assert staff.y_on_ledger(staff.unit(0)) is False assert staff.y_on_ledger(staff.unit(4)) is False assert staff.y_on_ledger(staff.unit(4.5)) is False assert staff.y_on_ledger(staff.unit(5)) is True
class TestNotehead(unittest.TestCase): def setUp(self): neoscore.setup() self.flowable = Flowable((Mm(0), Mm(0)), Mm(10000), Mm(30), Mm(5)) self.staff = Staff((Mm(0), Mm(0)), Mm(10000), flowable=self.flowable) Clef(self.staff, Mm(0), "treble") def test_staff_position_middle_c_treble(self): self.assertEqual( Notehead(Mm(10), "c'", Beat(1, 4), self.staff).staff_pos, self.staff.unit(5) ) def test_staff_position_low_octaves(self): self.assertEqual( Notehead(Mm(10), "c", Beat(1, 4), self.staff).staff_pos, self.staff.unit(8.5), ) self.assertEqual( Notehead(Mm(10), "c,", Beat(1, 4), self.staff).staff_pos, self.staff.unit(12), ) self.assertEqual( Notehead(Mm(10), "c,,", Beat(1, 4), self.staff).staff_pos, self.staff.unit(15.5), ) self.assertEqual( Notehead(Mm(10), "c,,,", Beat(1, 4), self.staff).staff_pos, self.staff.unit(19), ) def test_staff_position_high_octaves(self): self.assertEqual( Notehead(Mm(10), "c''", Beat(1, 4), self.staff).staff_pos, self.staff.unit(1.5), ) self.assertEqual( Notehead(Mm(10), "c'''", Beat(1, 4), self.staff).staff_pos, self.staff.unit(-2), ) self.assertEqual( Notehead(Mm(10), "c''''", Beat(1, 4), self.staff).staff_pos, self.staff.unit(-5.5), ) self.assertEqual( Notehead(Mm(10), "c'''''", Beat(1, 4), self.staff).staff_pos, self.staff.unit(-9), ) def test_staff_position_with_accidentals(self): self.assertEqual( Notehead(Mm(10), "cf'", Beat(1, 4), self.staff).staff_pos, self.staff.unit(5), ) self.assertEqual( Notehead(Mm(10), "cn'", Beat(1, 4), self.staff).staff_pos, self.staff.unit(5), ) self.assertEqual( Notehead(Mm(10), "cs'", Beat(1, 4), self.staff).staff_pos, self.staff.unit(5), ) def test_staff_position_with_all_letter_names(self): self.assertEqual( Notehead(Mm(10), "d'", Beat(1, 4), self.staff).staff_pos, self.staff.unit(4.5), ) self.assertEqual( Notehead(Mm(10), "e'", Beat(1, 4), self.staff).staff_pos, self.staff.unit(4) ) self.assertEqual( Notehead(Mm(10), "f'", Beat(1, 4), self.staff).staff_pos, self.staff.unit(3.5), ) self.assertEqual( Notehead(Mm(10), "g'", Beat(1, 4), self.staff).staff_pos, self.staff.unit(3) ) self.assertEqual( Notehead(Mm(10), "a'", Beat(1, 4), self.staff).staff_pos, self.staff.unit(2.5), ) self.assertEqual( Notehead(Mm(10), "b'", Beat(1, 4), self.staff).staff_pos, self.staff.unit(2) ) def test_staff_position_on_later_flowable_line(self): self.assertEqual( Notehead(Mm(1000), "c", Beat(1, 4), self.staff).staff_pos, self.staff.unit(8.5), )
def test_ledgers_needed_from_position_with_odd_line_count(self): staff = Staff((Mm(0), Mm(0)), Mm(100), self.flowable, line_count=5) # Inside the staff, no ledgers assert staff.ledgers_needed_for_y(staff.unit(0)) == [] assert staff.ledgers_needed_for_y(staff.unit(4)) == [] # Just outside the staff, no ledgers assert staff.ledgers_needed_for_y(staff.unit(-0.5)) == [] assert staff.ledgers_needed_for_y(staff.unit(4.5)) == [] # Right on the first ledger assert staff.ledgers_needed_for_y(staff.unit(-1)) == [staff.unit(-1)] assert staff.ledgers_needed_for_y(staff.unit(5)) == [staff.unit(5)] # Further outside with multiple ledgers, directly on lines assert staff.ledgers_needed_for_y(staff.unit(6)) == [ staff.unit(6), staff.unit(5), ] assert staff.ledgers_needed_for_y(staff.unit(-2)) == [ staff.unit(-2), staff.unit(-1), ] # Further outside with multiple ledgers, between lines assert staff.ledgers_needed_for_y(staff.unit(6.5)) == [ staff.unit(6), staff.unit(5), ] assert staff.ledgers_needed_for_y(staff.unit(-2.5)) == [ staff.unit(-2), staff.unit(-1), ]
def setUp(self): neoscore.setup() self.flowable = Flowable((Mm(0), Mm(0)), Mm(10000), Mm(30), Mm(5)) self.staff = Staff((Mm(0), Mm(0)), Mm(10000), flowable=self.flowable) Clef(self.staff, Mm(0), "treble")
def test_distance_to_next_of_type(self): staff = Staff((Mm(10), Mm(0)), Mm(100), self.flowable) treble = Clef(staff, Mm(11), "treble") bass = Clef(staff, Mm(31), "bass") assert_almost_equal(staff.distance_to_next_of_type(treble), Mm(20)) assert_almost_equal(staff.distance_to_next_of_type(bass), Mm(100 - 31))