diff Syncopation models/TMC.py @ 20:b959c2acb927

Refactored all models except for KTH, all past testing except for SG.
author csong <csong@eecs.qmul.ac.uk>
date Tue, 07 Apr 2015 19:05:07 +0100
parents 031e2ccb1fb6
children df1e7c378ee0
line wrap: on
line diff
--- a/Syncopation models/TMC.py	Fri Apr 03 22:57:27 2015 +0100
+++ b/Syncopation models/TMC.py	Tue Apr 07 19:05:07 2015 +0100
@@ -4,52 +4,81 @@
 
 '''
 
-from BasicFuncs import get_H, ceiling, get_min_timeSpan
+from basic_functions import get_H, ceiling, get_min_timeSpan, get_rhythm_category
 
 # The get_metricity function calculates the metricity for a binary sequence with given sequence of metrical weights in a certain metrical level.
-def get_metricity(seq, H):
+def get_metricity(binarySequence, H):
 	metricity = 0
-	for m in range(len(seq)):
-		metricity = metricity + seq[m]*H[m]
+	for m in range(len(binarySequence)):
+		metricity = metricity + binarySequence[m]*H[m]
 	return metricity
 
 # The get_max_metricity function calculates the maximum metricity for the same number of notes in a binary sequence.
-def get_max_metricity(seq, H):
-	max_metricity = 0
+def get_max_metricity(binarySequence, H):
+	maxMetricity = 0
 	H.sort(reverse=True) # Sort the metrical weight sequence from large to small
-	for i in range(sum(seq)):
-		max_metricity = max_metricity+H[i]
-	return max_metricity
+	for i in range(sum(binarySequence)):
+		maxMetricity = maxMetricity+H[i]
+	return maxMetricity
+
+# find the metrical level L that contains the same number of metrical positions as the length of the binary sequence
+# if the given Lmax is not big enough to analyse the given sequence, request a bigger Lmax
+def find_L(rhythmSequence, Lmax, weightSequence, subdivisionSequence):
+	L = Lmax
+
+	# initially assuming the Lmax is not big enough
+	needBiggerLmax = True 
+	
+	# from the lowest metrical level (Lmax) to the highest, find the matching metrical level that 
+	# has the same length as the length of binary sequence  
+	while L >= 0:
+		if len(get_H(weightSequence,subdivisionSequence, L)) == len(rhythmSequence):
+			needBiggerLmax = False
+			break
+		else:
+			L = L - 1
+
+	# if need a bigger Lmax, print error message and return None; otherwise return the matching metrical level L
+	if needBiggerLmax:
+		print 'Error: needs a bigger L_max (i.e. the lowest metrical level) to match the given rhythm sequence.'
+		L = None
+	
+	return L
 
 # The get_syncopation function calculates the syncopation value of the given sequence for TMC model. 
-def get_syncopation(seq, subdivision_seq, weight_seq, L_max, rhythm_category):
+#def get_syncopation(seq, subdivision_seq, weight_seq, L_max, rhythm_category):
+def get_syncopation(bar, parameters = None):
 	syncopation = None
-	if rhythm_category == 'poly':
-		print 'Error: TMC model cannot deal with polyrhythms.'
+	binarySequence = bar.get_binary_sequence()
+	subdivisionSequence = bar.get_subdivision_sequence()
+
+	if get_rhythm_category(binarySequence, subdivisionSequence) == 'poly':
+		print 'Warning: TMC model detects polyrhythms so returning None.'
 	else:
-		seq = get_min_timeSpan(seq)	# converting to the minimum time-span format
+		binarySequence = get_min_timeSpan(binarySequence)	# converting to the minimum time-span format
 
-		# checking whether the given L_max is enough to analyse the given sequence, if not, request a bigger L_max
-		new_L_max = True
-		matching_level = L_max
-		while matching_level >= 0:
-			if len(get_H(weight_seq,subdivision_seq, matching_level)) == len(seq):
-				new_L_max = False
-				break
+		# If the parameters are not given, use the default settings
+		if parameters == None:
+			Lmax  = 5
+			weightSequence = range(Lmax+1,0,-1) # i.e. [6,5,4,3,2,1]
+		else:
+			if are_parameters_valid(parameters):
+				Lmax = parameters['Lmax']
+				weightSequence = parameters['W']
 			else:
-				matching_level = matching_level - 1
+				pass
+				#raise InvalidParameterError
 
-		if new_L_max == True:
-			print 'Error: needs a bigger L_max (i.e. the lowest metrical level) to match the given rhythm sequence.'
-		
-		else:
-			# generate the metrical weights of the lowest level, 
-			# using the last matching_level number of elements in the weight_seq list, to make sure the last element is 1
-			H = get_H (weight_seq[-(matching_level+1):], subdivision_seq, matching_level)
+		L = find_L(binarySequence, Lmax, weightSequence, subdivisionSequence) 
+		if L != None:
+			#? generate the metrical weights of the lowest level, 
+			#? using the last matching_level number of elements in the weightSequence, to make sure the last element is 1
+			H = get_H (weightSequence[-(L+1):], subdivisionSequence, L)
 			
-			metricity = get_metricity(ceiling(seq), H)	# converting to binary sequence then calculate metricity
-			max_metricity = get_max_metricity(ceiling(seq), H)
+			metricity = get_metricity(binarySequence, H)	# converting to binary sequence then calculate metricity
+			maxMetricity = get_max_metricity(binarySequence, H)
 
-			syncopation = max_metricity - metricity
+			syncopation = maxMetricity - metricity
+
 	return syncopation