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

adjacent parts #4

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions sebastian/src/Checks/AdjacentPartsGreaterThanOctaveCheck.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import sebastian.src.Utils.Utils as Utils
import sebastian.src.SebastianStructures.Check as Check
import sebastian.src.SebastianStructures.Constants as Constants
from sebastian.src.Checks.Location import Location
from sebastian.src.Checks.AdjacentPartsGreaterThanOctaveError import AdjacentPartsGreaterThanOctaveError


class AdjacentPartsGreaterThanOctaveCheck(Check):
def run_check(self, chorale):
out = []
out.extend(self.run_check_for_parts(chorale, Constants.TENOR_PART_NUMBER, Constants.ALTO_PART_NUMBER))
out.extend(self.run_check_for_parts(chorale, Constants.ALTO_PART_NUMBER, Constants.SOPRANO_PART_NUMBER))
return out

def run_check_for_parts(self, chorale, part_1, part_2):
out = []
notes_for_part = chorale.reverse_note_maps
for offset in notes_for_part[part_1]:
#check if offset exists in notes_for_part[part_2]
if offset in notes_for_part[part_2]:
pitch_1 = notes_for_part[part_1][offset].pitch
pitch_2 = notes_for_part[part_2][offset].pitch
if pitch_2.ps - pitch_1.ps > 12.0:
error = AdjacentPartsGreaterThanOctaveError(pitch_1, pitch_2, part_1, part_2, chorale.get_location_from_offset(offset))
out.append(error)
return out
33 changes: 33 additions & 0 deletions sebastian/src/Checks/AdjacentPartsGreaterThanOctaveError.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from sebastian.src.SebastianStructures.ChoraleEvaluation import ChoraleError
import sebastian.src.SebastianStructures.Constants as Constants


class AdjacentPartsGreaterThanOctaveError(ChoraleError):

def __init__(self, pitch_1, pitch_2, part_number_1, part_number_2, measure_and_beat):
message = "The interval between %s in %s and %s in %s, at measure %s beat %s, is greater than an octave." % \
(pitch_1, Constants.PART_NAMES[part_number_1], pitch_2, Constants.PART_NAMES[part_number_2], measure_and_beat.measure, measure_and_beat.beat)

self.part_number_1 = part_number_1
self.part_number_2 = part_number_2
self.measure_and_beat = measure_and_beat
self.pitch_1 = pitch_1
self.pitch_2 = pitch_2
super(AdjacentPartsGreaterThanOctaveError, self).__init__(message)

print message

def get_part_number_1(self):
return self.part_number_1

def get_part_number_2(self):
return self.part_number_2

def get_measure(self):
return self.measure_and_beat[0]

def get_beat(self):
return self.measure_and_beat[1]

def get_error_name(self):
return "AdjacentPartsGreaterThanOctaveError"
3 changes: 3 additions & 0 deletions sebastian/src/ChoraleAnalysis/ChoraleAnalysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from sebastian.src.Checks.RangeCheck import RangeCheck
from sebastian.src.Checks.TritoneJumpCheck import TritoneJumpCheck
from sebastian.src.Checks.VoiceCrossingCheck import VoiceCrossingCheck
from sebastian.src.Checks.AdjacentPartsGreaterThanOctaveCheck import AdjacentPartsGreaterThanOctaveCheck



class ChoraleAnalysis():
Expand Down Expand Up @@ -75,4 +77,5 @@ def check_list(self):
RangeCheck(),
TritoneJumpCheck(),
VoiceCrossingCheck(),
AdjacentPartsGreaterThanOctaveCheck(),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from sebastian.src.ChoraleAnalysis.ChoraleAnalysis import XMLChoraleAnalysis
import sebastian.tests.testfiles.TestFilePaths as TestFilePaths
from sebastian.src.SebastianStructures import Constants
from sebastian.src.Utils.Utils import *

import unittest

class AdjacentPartsGreaterThanOctaveIntegrationTest(unittest.TestCase):

def test_ThrowsErrorWithAdjacentsGreaterThanOvtave(self):
analysis = XMLChoraleAnalysis(TestFilePaths.adjacents_greater_than_octave)
analysis.analyze()
errors = analysis.get_error_list("AdjacentPartsGreaterThanOctaveError")
self.assertEqual(1, len(errors))

def test_CorrectPropertiesOnAdjacentsGreaterThanOvtave(self):
analysis = XMLChoraleAnalysis(TestFilePaths.parallel_fifth)
analysis.analyze()
error = get_only_element(analysis.get_error_list("AdjacentPartsGreaterThanOctaveError"))

self.assertEqual(14, error.get_pitch_1().ps - error.get_pitch_2().ps)
self.assertEqual(Constants.ALTO_PART_NUMBER, error.get_part_number_1())
self.assertEqual(Constants.SOPRANO_PART_NUMBER, error.get_part_number_2())
self.assertEqual(2, error.get_measure())
self.assertEqual(0.0, error.get_beat_1())

if __name__ == "__main__":
unittest.main()
2 changes: 2 additions & 0 deletions sebastian/tests/testfiles/TestFilePaths.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@
out_of_range = TESTFILES_ROOT + "out_of_range.xml"
tritone_jump = TESTFILES_ROOT + "tritone_jump.xml"
voice_crossing = TESTFILES_ROOT + "voice_crossing.xml"
adjacents_greater_than_octave = TESTFILES_ROOT + "adjacents_greater_than_octave.xml"

Loading