#!/usr/local/bin/python
#-----------------------------------------------------------------||||||||||||--
# Name: MC.py
# Purpose: map class object used for all map processing.
# gets data from MCdata.py
# based on modle by Joseph N. Straus
#
# Authors: Christopher Ariza
#
# Copyright: (c) 2001-2006 Christopher Ariza
# License: GPL
#-----------------------------------------------------------------||||||||||||--
#smoothness
#smoothness vector: 7 registers
#uniformity
#uniformity vector: UV: 12 registers
#balance
#balance vector: 12 registers
#-----------------------------------------------------------------||||||||||||--
#-----------------------------------------------------------------||||||||||||--
import copy
from athenaCL.libATH import dialog
from athenaCL.libATH import drawer
from athenaCL.libATH import language
lang = language.LangObj()
from athenaCL.libATH import SC
from athenaCL.libATH import pitchTools
from athenaCL.libATH import MCdata
vlMapDict = MCdata.vlMapDict # table of all voice maping
_MOD = 'MC.py'
#-----------------------------------------------------------------||||||||||||--
# formats used here
#
class MapClass:
"""utility functions for map class operations
"""
def flipMap(self, sourceMap):
"""reverses the direction of a map, from Large-to-small, to small-to-large
length of map is number of positions in the source
"""
sourcePos = len(sourceMap)
noDifVal = 0
difValBasket = []
for entry in sourceMap:
if drawer.isList(entry): # not an int
for sub_entry in entry:
if sub_entry in difValBasket:
pass
else:
difValBasket.append(sub_entry)
else:
if entry in difValBasket:
pass
else:
difValBasket.append(entry)
difValBasket.sort()
# number of different values is the number of positions in the destination
destinationPos = len(difValBasket)
if sourcePos == destinationPos:
# if these are equal no flip necessary
return sourceMap
elif sourcePos > destinationPos:
flipedMap = []
# this is case where going from larger to smaller set.
#this is the form that the map dictionary uses for reference
for val in difValBasket:
# find register positions for each value in the basket.
# there will be more than one
tempImbedList = []
#if sp is > destP we do not need to check for imbedded tuples
indexCount = 0
for entry in sourceMap:
if entry == val:
tempImbedList.append(indexCount)
indexCount = indexCount + 1
if len(tempImbedList) > 1:
newMapEntry = tuple(tempImbedList)
else:
newMapEntry = tempImbedList[0]
flipedMap.append(newMapEntry)
else: # destination Pos > source Position
flipedMap = []
# construct an empty map
newMapNoRegisters = destinationPos
for entry in difValBasket:
flipedMap.append(0)
indexCount = 0
for entry in sourceMap:
if drawer.isList(entry): # not an int
for sub_entry in entry:
flipedMap[sub_entry] = indexCount
else:
flipedMap[entry] = indexCount
indexCount = indexCount + 1
flipedMap = tuple(flipedMap)
return flipedMap
#------------------------------------------------------------------------||--
# data access
def _getMapSrcDstSize(self, sourceMap):
#length of map is number of positions in the source
sourcePos = len(sourceMap)
noDifVal = 0
difValBasket = []
for entry in sourceMap:
if drawer.isList(entry): # not an int
for sub_entry in entry:
if sub_entry in difValBasket:
pass
else:
difValBasket.append(sub_entry)
else:
if entry in difValBasket:
pass
else:
difValBasket.append(entry)
difValBasket.sort()
# number of different values is the number of positions in the destination
destinationPos = len(difValBasket)
return sourcePos, destinationPos
def getMapDict(self, srcSize, dstSize):
"""returns a dictionary of index numbers : map pairs for the given sizes.
these are not sorted, and index numbers are only for permanent
reference to source
"""
if (srcSize > 6 or srcSize < 1 or
dstSize > 6 or srcSize < 1):
return None # returns None as error code
# no change nec, this is the format of the map dictionary
if srcSize >= dstSize:
return vlMapDict[(srcSize, dstSize)]
else: # need to flip all the maps in the reverse dictionary
# must reverse these to get a dict to then reverse the mappings of
sourceDict = vlMapDict[(dstSize, srcSize)]
newDict = {}
for key in sourceDict.keys():
map = sourceDict[key]
newMap = self.flipMap(map)
newDict[key] = newMap
return newDict
def getNoMaps(self, srcSize, dstSize):
"""return possible maps between any two sizes"""
map = self.getMapDict(srcSize, dstSize)
if map == None: return None
else:
return len(map.keys())
def getSingleMap(self, srcSize, dstSize, mapIndexNo):
# a single map corrolating to the index and size args
# map index numbers stat at 1, not at 0
if (srcSize > 6 or srcSize < 1 or
dstSize > 6 or srcSize < 1):
return -1
# no change nec, this is the format of the map dictionary
if srcSize >= dstSize:
try:
map = vlMapDict[(srcSize, dstSize)][mapIndexNo]
except:
return -1
else: # need to flip all the maps in the reverse dictionary
try:
# must reverse these to get a dict to then reverse the mappings
sourceMap = vlMapDict[(dstSize, srcSize)][mapIndexNo]
except:
return -1
map = self.flipMap(sourceMap)
return map
def fetchMap(self, mapIdTuple):
srcSize = mapIdTuple[0]
dstSize = mapIdTuple[1]
mapIndexNo = mapIdTuple[2]
return self.getSingleMap(srcSize, dstSize, mapIndexNo)
#------------------------------------------------------------------------||--
def mapIdTupleToString(self, mapIdTuple):
srcSize = mapIdTuple[0]
dstSize = mapIdTuple[1]
mapIndexNo = mapIdTuple[2]
return '%i:%i-%i' % (srcSize,dstSize,mapIndexNo)
def rawMapToString(self, rawMap):
### returns map as string with letters
translationDict = {0 : 'a',
1 : 'b',
2 : 'c',
3 : 'd',
4 : 'e',
5 : 'f' }
msg = '('
# length of map is number of positions in the source
sourcePos = len(rawMap)
for entry in rawMap:
if drawer.isList(entry): # not an int
msg = msg + '('
for sub_entry in entry:
msg = msg + translationDict[sub_entry]
msg = msg + ')'
else:
msg = msg + translationDict[entry]
msg = msg + ')'
return msg
def stringToMap(self, stringMap):
"""assumes that strings is a comma separated list of maps"""
goodMap = 0
goodKey = 0
# takes a string and returns a mapTuple Id, if the map exists
translationDict = {'a' : '0',
'b' : '1',
'c' : '2',
'd' : '3',
'e' : '4',
'f' : '5' }
for letter in translationDict.keys():
stringMap = stringMap.replace(letter, translationDict[letter])
try:
newMap = eval(stringMap)
except:
return None
srcSize, dstSize = self._getMapSrcDstSize(newMap)
mapDict = self.getMapDict(srcSize, dstSize)
if mapDict == None: return None
for key in mapDict.keys():
if mapDict[key] == newMap:
goodMap = 1
goodKey = key
if goodMap != 1: return None
### map is good, return it
return (srcSize, dstSize, goodKey)
#------------------------------------------------------------------------||--
def genVlPairs(self, pcsX, pcsY, map):
# generates one vl pair set for single map (takes rawmap, not mapTupleId)
# this method does not check for the appropriate map; should be
# checked elsewhere
srcSize = len(pcsX)
#length of map is number of positions in the source, i.e. size
sourcePos = len(map)
srcPosCount = 0
vlTuples = []
for mapEntry in map:
if drawer.isList(mapEntry):
for sub_entry in mapEntry:
sourcePC = pcsX[srcPosCount]
destinationPC = pcsY[sub_entry]
vlTuples.append((sourcePC, destinationPC))
else:
sourcePC = pcsX[srcPosCount]
destinationPC = pcsY[mapEntry]
vlTuples.append((sourcePC, destinationPC))
srcPosCount = srcPosCount + 1
return tuple(vlTuples)
def genSingleVlDiagram(self, pcsX, map):
# map here is a raw map, not an idTuple
# returns a dictionary of numbered rows, with pcsX and its next
# movement as strings
translationDict = {0 : 'a',
1 : 'b',
2 : 'c',
3 : 'd',
4 : 'e',
5 : 'f' }
rowDict = {0 : [],
1 : [],
2 : [],
3 : [],
4 : [],
5 : [] }
srcPosCount = 0
for mapEntry in map:
if drawer.isList(mapEntry):
mapTranslated = []
for sub_entry in mapEntry:
mapTranslated.append(translationDict[sub_entry])
stringMap = ''
for letter in mapTranslated:
stringMap = stringMap + '%s' % letter
mapTranslated = stringMap #+ ')'
rowDict[srcPosCount].append(pcsX[srcPosCount])
rowDict[srcPosCount].append(mapTranslated)
else:
mapTranslated = translationDict[mapEntry]
rowDict[srcPosCount].append(pcsX[srcPosCount])
rowDict[srcPosCount].append(mapTranslated)
srcPosCount = srcPosCount + 1
keyList = rowDict.keys()
keyList.sort()
for key in keyList:
if len(rowDict[key]) == 0:
rowDict[key] = ' ' * 9 # 9 spaces for spacer
else:
sourcePCS, mapToPosition = rowDict[key]
stringEntry = '%s %s' % (str(sourcePCS).rjust(2),
mapToPosition.ljust(6))
rowDict[key] = stringEntry
return rowDict
def genDoubleVlDiagram(self, pcsX, pcsY, map):
""" returns a dictionary of numbered rows,
with pcsX and its next movement as strings
"""
rowDict = self.genSingleVlDiagram(pcsX, map)
rowKeys = rowDict.keys()
for i in range(0,len(pcsY)):
if len(rowDict[i]) == 0:
pass
else:
rowDict[i] = rowDict[i] + '%s' % str(pcsY[i]).rjust(2)
return rowDict
#------------------------------------------------------------------------||--
def getAllVl(self, pcsX, pcsY):
"""returns a dictionary of key : ((), ()) vl tuple paris, pcsX and pcsY
can be of any size =< 6; the key is the same as the mapDict key
"""
if len(pcsX) > 6 or len(pcsX) < 1 or len(pcsY) > 6 or len(pcsY) < 1:
return 'pcs of this size are not supported'
vlDict = {}
srcSize = len(pcsX)
dstSize = len(pcsY)
mapDict = self.getMapDict(srcSize, dstSize)
for key in mapDict.keys():
map = mapDict[key]
vlPairs = self.genVlPairs(pcsX, pcsY, map)
vlDict[key] = vlPairs
return vlDict
def genMapFromVlPairs(self, rawVlPairs, pcsX, pcsY):
"""analizes vl pairs with appropriate pcsX and y and finds correct map
pcs should be a tuple and not a list
"""
# returns -1 on error
# NOTE! in some cases of dif sized boundaries this function will not
# identify a vlPair b/c of a slitting or merging pair being in the
# wrong internal (embedded) order. this hould be fixed in the future
foundPcsX = []
foundPcsY = []
# test pcsY is sorted so as to comparte to the extracted pcsY and test
# for eq dont know referential ordering of pcsY, so must sort and then
# comparte to prove eq
# added to anticipate strange error found from bug report
#if None in rawVlPairs: return -1 # something went wrong
pcsXconstituents = []
pcsYconstituents = []
for entry in pcsX:
if entry in pcsXconstituents:
pass
else:
pcsXconstituents.append(entry)
for entry in pcsY:
if entry in pcsYconstituents:
pass
else:
pcsYconstituents.append(entry)
pcsXconstituents.sort()
pcsYconstituents.sort()
testPcsY = copy.copy(pcsY)
testPcsY = list(testPcsY)
testPcsY.sort()
# rawVlPairs should alwas been in the order of pcsX, from top to bottom
for pair in rawVlPairs:
foundPcsX.append(pair[0])
foundPcsY.append(pair[1])
foundPcsX = tuple(foundPcsX)
testFoundPcsY = copy.copy(foundPcsY)
testFoundPcsY.sort()
foundPcsY = tuple(foundPcsY)
foundPcsXconstituents = []
foundPcsYconstituents = []
for entry in foundPcsX:
if entry in foundPcsXconstituents:
pass
else:
foundPcsXconstituents.append(entry)
for entry in foundPcsY:
if entry in foundPcsYconstituents:
pass
else:
foundPcsYconstituents.append(entry)
foundPcsXconstituents.sort()
foundPcsYconstituents.sort()
# every elemen in the pcs must be represented in the found; qunatity,
# thought, does not matter
if pcsXconstituents != foundPcsXconstituents: return -1
if pcsYconstituents != foundPcsYconstituents: return -1
srcSize = len(pcsX)
dstSize = len(pcsY)
foundMap = []
# fill with 0s for source positions
if srcSize == dstSize:
if foundPcsX != pcsX: return -1
if testFoundPcsY != testPcsY: return -1
elif srcSize < dstSize:
# if destination os larger, foundPCS will only match for Y
if testFoundPcsY != testPcsY: return -1
elif srcSize > dstSize:
# if source is larger, foundPCS will only match for X
if foundPcsX != pcsX: return -1
rawVlPairs = tuple(rawVlPairs)
vlPairDict = self.getAllVl(pcsX, pcsY)
foundMapKey = 0
for key in vlPairDict.keys():
if vlPairDict[key] == rawVlPairs:
foundMapKey = key
break
# search for single mistake made in rawVL if source<DEST
if foundMapKey == 0:
# if it does not eidentify a pair, it may still be there but entered
# in the wrong order
if srcSize < dstSize:
tempRawVlPairs = copy.copy(rawVlPairs)
tempRawVlPairs = list(tempRawVlPairs) # user may have entered tuple
for counter in range(0, len(tempRawVlPairs)):
if counter + 1 == len(tempRawVlPairs):
break
#check first postiion in this pair and next
if tempRawVlPairs[counter][0] == tempRawVlPairs[counter+1][0]:
a = tempRawVlPairs[counter]
b = tempRawVlPairs[counter+1]
tempRawVlPairs = list(tempRawVlPairs)
tempRawVlPairs[counter] = b
tempRawVlPairs[counter+1] = a
tempRawVlPairs = tuple(tempRawVlPairs)
for key in vlPairDict.keys():
if vlPairDict[key] == tempRawVlPairs:
foundMapKey = key
break
if foundMapKey != 0:
# replace the original vlPairs with the new, corrected ones
rawVlPairs = tempRawVlPairs
break
else:
# restore original if no match made.
#this will only correct 1 mistake, not two
tempRawVlPairs = copy.copy(rawVlPairs)
tempRawVlPairs = list(tempRawVlPairs)
else: return -1 ## failed search
# search for multiple mistakes in rawVL if source<DEST
if foundMapKey == 0:
# if it does not eidentify a pair, it may still be there but entered
# in the wrong order
if srcSize < dstSize:
tempRawVlPairs = copy.copy(rawVlPairs)
# user may have entered tuple
tempRawVlPairs = list(tempRawVlPairs)
for counter in range(0, len(tempRawVlPairs)):
if counter + 1 == len(tempRawVlPairs):
break
#check first postiion in this pair and next
if tempRawVlPairs[counter][0] == tempRawVlPairs[counter+1][0]:
a = tempRawVlPairs[counter]
b = tempRawVlPairs[counter+1]
tempRawVlPairs = list(tempRawVlPairs)
tempRawVlPairs[counter] = b
tempRawVlPairs[counter+1] = a
tempRawVlPairs = tuple(tempRawVlPairs)
for key in vlPairDict.keys():
if vlPairDict[key] == tempRawVlPairs:
foundMapKey = key
break
if foundMapKey != 0:
# replace the original vlPairs with the new, corrected ones
rawVlPairs = tempRawVlPairs
break
else:
# DONOT restore original if no match made. this will only
# correct > 1 mistake, not 1
pass #tempRawVlPairs = copy.copy(rawVlPairs)
else:
return -1 ## failed search
if foundMapKey == 0:
return -1
# returns a standard map partial ID for the given source dest. size
# returns vl pairs because they may have been auto corrected
# (srcSize, dstSize, foundMapKey)
return (foundMapKey, rawVlPairs)
#------------------------------------------------------------------------||--
def displacement(self, srcSet, dstSet, posToTransform):
"""finds value of displacement between two sets
position to transform is either 1 or 0, for second or first
finds a new set that has maximal displacement
"""
srcSize = len(srcSet)
dstSize = len(dstSet)
# dont care if inversion is the same, which it may be
if posToTransform == 0: # first set changes
setToChangeP = srcSet
setToChangeI = SC.psInverter(srcSet)
setConstant = dstSet
# this is a PitchSpace inversion
else: # second set changes
setToChangeP = dstSet
setToChangeI = SC.psInverter(dstSet)
setConstant = srcSet
setsToCompare = []
for transInt in range(0,12): ## all values 0 to 11
pcsetTP = SC.pcSetTransposer(setToChangeP, transInt)
pcsetTI = SC.pcSetTransposer(setToChangeI, transInt)
if pcsetTP == pcsetTI: # symmetrical set; dont need inversion
setsToCompare.append((pcsetTP,transInt))
else:
setsToCompare.append((pcsetTP,transInt))
setsToCompare.append((pcsetTI,transInt))
minDispl = 9999 # init value very large
maxDispl = 0 # init value very small
allResults = []
for setEntry in setsToCompare:
tSet, transInt = setEntry # this set is setToCahnge
if posToTransform == 0: # first set changes
SMTHdict, SMTHorderKey = self.sortSMTH(tSet, setConstant)
else: # last set changes
SMTHdict, SMTHorderKey = self.sortSMTH(setConstant, tSet)
# get most smooth
SMTHvector, SMTHdispl = SMTHdict[SMTHorderKey[0]]
mapTupleId = (srcSize, dstSize, SMTHorderKey[0])
scTupleID, dif = SC.findNormalT(tSet)
if SMTHdispl <= minDispl:
minDispl = SMTHdispl
else:
if SMTHdispl >= maxDispl:
maxDispl = SMTHdispl
allResults.append((SMTHdispl, tSet, scTupleID,
transInt, mapTupleId))
allResults.sort()
# list of four things: (1) smoothness displacement, (2) the pcs set (y)
# that was compared to x, (3) the set class of this set (3-11 obviously,
# but -1 is the inversion), (4) the transposition that was used, and (5)
# the map that was found as most smooth for that comparison
#for line in allResults:
# print _MOD, line
# does not matter what 'foundForm' is; could be the inverse of a
# forte inverse, which is a forte prime
return minDispl, maxDispl, allResults, len(setsToCompare)
#------------------------------------------------------------------------||--
def getSetSizeBounds(self, query=None, termObj=None):
"""utility interactive command to get src, dest pair from the user
if no query provided, one supplied
if minimum can be set to 2 or 1"""
if query == None:
query = lang.msgMCenterVoiceRange
while 1:
sizeInput = dialog.askStr(query, termObj)
if sizeInput == None or sizeInput == '':
return None
if sizeInput.find(':') != -1: # it has a ':'
sizeInput = sizeInput.replace(':', ',')
try:
voiceSizes = eval(sizeInput)
srcSize = voiceSizes[0]
dstSize = voiceSizes[1]
except:
dialog.msgOut(lang.msgMCbadVoiceRange, termObj)
continue
if (srcSize >= 1 and srcSize <= 6 and
dstSize >= 1 and dstSize <= 6 and
len(voiceSizes) == 2):
break
else:
dialog.msgOut(lang.msgMCbadVoiceValue, termObj)
continue
return srcSize, dstSize
def _parseMapInputTupe(self, usrStr):
""""determine type of map input
possible: completeMap, rawMap, rawVlPairs, partialMap"""
inputType = None
# scan for types of input
if usrStr.find('-') != -1 and usrStr.find(':') != -1:
inputType = 'completeMap'
# if the user has entered an incorrect format for a map class
# (only one -, or one :)
elif usrStr.find('-') != -1 or usrStr.find(':') != -1:
# this means that we already have proper source and dest sizes
return None # case 2
elif usrStr.find(',') != -1 or usrStr.find('.') != -1:
if (usrStr.find('a') != -1 or usrStr.find('b') != -1 or
usrStr.find('c') != -1 or usrStr.find('d') != -1 or
usrStr.find('e') != -1 or usrStr.find('f') != -1):
# raw maps are notated with letters, like (a,b,c)
inputType = 'rawMap'
else:
# raw vl pairs are notated with the ints of a pc class
inputType = 'rawVlPairs'
else: # case 3
usrStr = drawer.strToNum(usrStr, 'int')
if usrStr != None: # an integer
inputType = 'partialMap'
else:
return None
return inputType
def _evaluateCompleteMap(self, usrStr, updateSrcDst,
srcSize, dstSize, termObj):
"""convert usrStrings that encode complete mapClass specificiations
in the form 3:2-3 or the like
if updateSrcDst, will read srcDst value form map notation
otherwise, compares with supplied src/dst sizes"""
usrStr = usrStr.replace(':', ',')
usrStr = usrStr.replace('-', ',')
# value should be a three element list of integers after evaluation
tempMapTuple = drawer.strToSequence(usrStr, 3, ['int'])
if tempMapTuple == None: return None # forces value to be len of 3
# first two values must be between 1 and 6 (1:6, for ex)
if (tempMapTuple[0] >= 1 and tempMapTuple[0] <= 6 and
tempMapTuple[1] >= 1 and tempMapTuple[1] <= 6):
# check tt start and end size == src and dst
if updateSrcDst: # need to get new values
srcSize = tempMapTuple[0]
dstSize = tempMapTuple[1]
# update w/ new sizes
maxMapKey = self.getNoMaps(srcSize, dstSize)
# check values agains src/dst
if tempMapTuple[0] != srcSize or tempMapTuple[1] != dstSize:
query = lang.msgMCbadMapChoice % (srcSize, dstSize, maxMapKey)
dialog.msgOut(query, termObj)
return None
# length is not == 3, or values are greater/less than they should be
else: # this is an error
dialog.msgOut(lang.msgMCnoSuchMap, termObj)
return None
# only need last value from temp typle
map = self.getSingleMap(srcSize, dstSize, tempMapTuple[2])
if map == -1 or map == None: # returns -1 on error
dialog.msgOut(lang.msgMCnoSuchMap, termObj)
return None
else:
mapIdTuple = (srcSize, dstSize, tempMapTuple[2])
return map, mapIdTuple
def _evaluatePartialMap(self, usrStr, updateSrcDst,
srcSize, dstSize, termObj):
"""partial map is simply an integer; if src and dst sizes are known
then must be w/n range; otherwise, get from user w/ interactive
"""
usrData = drawer.strToNum(usrStr, 'int')
if usrData == None: return None # should not happen, as should be intable
if updateSrcDst:
post = self.getSetSizeBounds() # interactiv ecommand
if post == None: # bad sizes gotten from user
dialog.msgOut(lang.msgMCbadVoiceValue, termObj)
return None
else:
srcSize, dstSize = post # assign to src/dst
maxMapKey = self.getNoMaps(srcSize, dstSize)
# usrData must be less tn max and greater = to 1
if not (usrData <= maxMapKey and usrData >= 1):
query = lang.msgMCbadMapChoice % (srcSize, dstSize, maxMapKey)
dialog.msgOut(query, termObj)
return None
map = self.getSingleMap(srcSize, dstSize, usrData)
if map == -1 or map == None: # returns -1 on error
dialog.msgOut(lang.msgMCbadRawMapFormat, termObj)
return None
else:
mapIdTuple = (srcSize, dstSize, usrData)
return map, mapIdTuple
def _evaluateRawMap(self, usrStr, updateSrcDst,
srcSize, dstSize, termObj):
"""raw map is an alphabetic string notation tt may include
parenthesis"""
mapIdTuple = self.stringToMap(usrStr)
if mapIdTuple == None:
dialog.msgOut(lang.msgMCbadRawMapFormat, termObj)
return None
map = self.fetchMap(mapIdTuple)
if map == -1 or map == None:
dialog.msgOut(lang.msgMCbadRawMapFormat, termObj)
return None
usrSrcSize, usrDstSize = self._getMapSrcDstSize(map)
if not updateSrcDst: # provided src/dst
# if usrStr does not match src/dst sizes
if (usrSrcSize != srcSize or usrDstSize != dstSize):
query = lang.msgMCbadMapChoice % (srcSize,
dstSize, self.getNoMaps(srcSize, dstSize))
dialog.msgOut(query, termObj)
return None
return map, mapIdTuple
def _evaluateRawVlPairs(self, usrStr, updateSrcDst,
srcSet, dstSet, termObj):
"""raw vl pairs are a notation that uses a list of pairs
the pairs are separated by commas or double dashes?
note: this takes srcSet, dstSet, not sizees
"""
# updateSrcNecsesary
try:
rawVlPairs = eval(usrStr)
rawVlPairs = tuple(rawVlPairs)
except:
dialog.msgOut(lang.msgMCgetBadVlParse, termObj)
return None
# need to check if if rawVlPairs has the right data
# generate sample sets from size
if len(rawVlPairs) < 1 or len(rawVlPairs) > 6 or None in rawVlPairs:
dialog.msgOut(lang.msgMCgetBadVlParse, termObj)
return None
# examine that this is a list of lists, each w/ 2 values
for pair in rawVlPairs:
if not drawer.isList(pair) or len(pair) != 2:
dialog.msgOut(lang.msgMCgetBadVlParse, termObj)
return None
# must get user boundarys sizes, b/c in vl-pairs there is no way
# of telling if a duplication is a real or phanton redundancy
if not updateSrcDst: # if not, will be updated below
srcSize = len(srcSet)
dstSize = len(dstSet)
if updateSrcDst:
post = self.getSetSizeBounds() # interacitve command
if post == None:
dialog.msgOut(lang.msgMCbadVoiceValue, termObj)
return None
else: srcSize, dstSize = post
# need to search and extract voice leading from provided data
foundPcsX = []
foundPcsY = []
# rawVlPairs should alwas been in the order of pcsX,
# from top to bottom
for pair in rawVlPairs:
foundPcsX.append(pair[0])
foundPcsY.append(pair[1])
foundPcsX = tuple(foundPcsX)
foundPcsY = tuple(foundPcsY)
foundPcsYsorted = copy.copy(foundPcsY)
foundPcsYsorted.sort()
# if sizes are equal, strip of actual pcs from the user entered
# vl-parts. otherwise generate demos
if (len(foundPcsX) == srcSize and len(foundPcsY) == dstSize):
while 1:
usrStr = dialog.askStr(lang.msgMCgetRefOrder %
repr(foundPcsY).replace(' ',''), termObj)
if usrStr == None: return None
try: # what is this?
orderedPcsY = eval(usrStr)
except:
dialog.msgOut(lang.msgConfusedInput, termObj)
continue
testOrderedPcsY = copy.copy(orderedPcsY)
testOrderedPcsY = list(testOrderedPcsY)
testOrderedPcsY.sort()
# if these are not the same, the user has entered a bad
# referential ordering
if foundPcsYsorted != testOrderedPcsY:
dialog.msgOut(lang.msgMCgetRefOrderBad, termObj)
continue
else: break
srcSet = foundPcsX # was same as demoPcsX
dstSet = orderedPcsY # was same as demoPcsY
else:
dialog.msgOut(lang.msgMCgetBadVlPairs, termObj)
return None
# can apply to acquisition methods
mapSearchResult = self.genMapFromVlPairs(rawVlPairs, srcSet, dstSet)
if mapSearchResult == -1 or mapSearchResult == None:
dialog.msgOut(lang.msgMCgetBadVlParse, termObj)
return None
else:
partialMapId = mapSearchResult[0]
correctedVlPairs = mapSearchResult[1]
map = self.getSingleMap(srcSize, dstSize, partialMapId)
if map == -1 or map == None: # returns -1 on error
maxMapKey = self.getNoMaps(srcSize, dstSize)
query = lang.msgMCbadMapChoice % (srcSize, dstSize, maxMapKey)
dialog.msgOut(query, termObj)
return None
mapIdTuple = (srcSize, dstSize, partialMapId)
return map, mapIdTuple
def getUserMap(self, pcsX=(), pcsY=(), termObj=None, read=None):
"""gets map from user, returns -1 on cancel
if read == string will try to match this string to a map
returns None on error
problem is that map can be specified w/o a src or dst
"""
updateSrcDst = 1 # change to 0 if pcs args are passed in
mapGotten = ()
mapIdTuple = ()
# case where no pcs are supplied, user must enter
# will have to create dest set after getting boundary lengths
if len(pcsX) == 0 or len(pcsY) == 0:
updateSrcDst = 1
# set to empty values
srcSize = 0
dstSize = 0
srcSet = []
dstSet = []
else:
srcSize = len(pcsX)
dstSize = len(pcsY)
if (srcSize >= 1 and srcSize <= 6 and dstSize >= 1 and dstSize <= 6):
srcSet = tuple(pcsX)
dstSet = tuple(pcsY)
# stop sets from being recalculated based on length
updateSrcDst = 0
# source inputs are out of range for number of voices
else: return None, None
attempts = 0
while 1:
inputType = ''
if read != None:
# dont try more than once when reading
if attempts > 0: return None, None
usrStr = read
readMode = 1
else:
usrStr = dialog.askStr(lang.msgMCgetMapMenu, termObj)
if usrStr == None: return None, None
readMode = 0
attempts = attempts + 1
# get usrStr type
inputType = self._parseMapInputTupe(usrStr)
if inputType == None:
if not updateSrcDst: # if not updating src and dst sizes
msg = lang.msgMCbadMapChoice % (srcSize, dstSize,
self.getNoMaps(srcSize, dstSize))
dialog.msgOut(msg, termObj)
else: # dont know src or dst, but still got an error
dialog.msgOut(lang.msgMCnoSuchMap, termObj)
continue # get data again from user
# complete map is given as 3:2-1 or variant
# only need index value; strip src and st size
if inputType == 'completeMap':
post = self._evaluateCompleteMap(usrStr, updateSrcDst,
srcSize, dstSize, termObj)
if post == None: continue
mapGotten, mapIdTuple = post # assign values
# user enters single number but has not entered boundary sizes
elif inputType == 'partialMap':
post = self._evaluatePartialMap(usrStr, updateSrcDst,
srcSize, dstSize, termObj)
if post == None: continue
mapGotten, mapIdTuple = post # assign values
# rawMaps are alphabetic strings
elif inputType == 'rawMap': # no boundary entered
post = self._evaluateRawMap(usrStr, updateSrcDst,
srcSize, dstSize, termObj)
if post == None: continue
mapGotten, mapIdTuple = post # assign values
# note: this takes srcSet, dstSet, not sizes
elif inputType == 'rawVlPairs': # no boundary entered
post = self._evaluateRawVlPairs(usrStr, updateSrcDst,
srcSet, dstSet, termObj)
if post == None: continue
mapGotten, mapIdTuple = post # assign values
# this should not happen, but errors creep in here:
if mapIdTuple == None or len(mapIdTuple) == 0:
return None, None # two None args necessary
# provide display and ask user if this is what they want
if readMode: # if reading just return
return mapIdTuple, mapGotten
# provide dummy sets if only size provided
if updateSrcDst: # src/dst dize in 0,1 of mapIdTuple
srcSet = tuple(range(mapIdTuple[0]))
dstSet = tuple(range(mapIdTuple[1]))
rowDict = self.genDoubleVlDiagram(srcSet, dstSet, mapGotten)
printKeyList = rowDict.keys()
printKeyList.sort()
for key in printKeyList:
tempRow = rowDict[key].strip()
if tempRow == '': continue
else: dialog.msgOut('%s%s\n' % (lang.TAB, rowDict[key]))
# final confirmation
query = lang.msgMCthisAsthat % (self.mapIdTupleToString(mapIdTuple),
self.rawMapToString(mapGotten))
askUsr = dialog.askYesNoCancel(query, 1, termObj)
if askUsr != -1 and askUsr != 1:
continue # return to top of loop if rejected
elif askUsr == -1: return None, None
elif askUsr == 1: break
return mapIdTuple, mapGotten
#------------------------------------------------------------------------||--
def getUserMapFromRank(self, sourceSet, destinationSet, orderKey,
methodTypeString, termObj=None):
srcSize = len(sourceSet)
dstSize = len(destinationSet)
'gets map from user, returns -1 on cancel'
# type string is used in prompt
while 1:
query = lang.msgMCchooseRank % (methodTypeString, len(orderKey))
choice = dialog.askStr(query, termObj)
if choice == None:
return None
try:
choicePos = eval(choice)
choicePos = choicePos - 1 # human offset correction
except:
dialog.msgOut(lang.msgMCnoSuchRank, termObj)
continue
if choicePos in range(0, len(orderKey)):#success
mapIdTuple = (srcSize, dstSize, orderKey[choicePos])
### createa display
rowDict = self.genDoubleVlDiagram(sourceSet, destinationSet,
self.fetchMap(mapIdTuple))
printKeyList = rowDict.keys()
printKeyList.sort()
for key in printKeyList:
tempRow = rowDict[key].strip()
if tempRow == '':
continue
else:
dialog.msgOut(lang.TAB + ('%s\n' % rowDict[key]), termObj)
query = lang.msgMCthisAsthat % (self.mapIdTupleToString(mapIdTuple),
self.rawMapToString(self.fetchMap(mapIdTuple)))
askUsr = dialog.askYesNoCancel(query, 1, termObj)
if askUsr != -1 and askUsr != 1:
continue # return to top of loop if rejected
elif askUsr == -1:
return None
elif askUsr == 1:
return mapIdTuple
else:
dialog.msgOut(lang.msgMCnoSuchRank, termObj)
continue
#------------------------------------------------------------------------||--
def SMTH(self, pcsX, pcsY, map):
# this is the measure of smoothness
# pcs must be of same size before entering this_function, map is a
# rawMap, not mapTUpleId
if len(pcsX) > 6 or len(pcsX) < 1 or len(pcsY) > 6 or len(pcsY) < 1:
return 'pcs of this size are not supported'
vlPairs = self.genVlPairs(pcsX, pcsY, map)
vectorS = [0,0,0,0,0,0,0]
for pcs_voice in vlPairs:
x = pcs_voice[0]
y = pcs_voice[1]
dist = abs(x-y)
dist = pitchTools.pcTransposer(dist, 0) #trans by 0 to perf mod 12
if dist > 6:
dist = 12 - dist
vectorS[dist] = vectorS[dist] + 1
reg_i = 0
totalS = 0
for reg in vectorS:
totalS = totalS + (reg * reg_i)
reg_i = reg_i + 1
return vectorS, totalS
def sortSMTH(self, pcsX, pcsY):
# returns a dictionary and a list
# the dictionary containts refNo for map : values
# list contains ordered refNo according to sorting principles
if len(pcsX) > 6 or len(pcsX) < 1 or len(pcsY) > 6 or len(pcsY) < 1:
return None # error, bad size
mapDict = self.getMapDict(len(pcsX), len(pcsY))
keyList = mapDict.keys()
keyList.sort()
dictS = {}
for key in keyList:
vectorS, totalS = self.SMTH(pcsX, pcsY, mapDict[key])
dictS[key] = vectorS, totalS
# list of keys in sorted order
# the order of the pcs entered _does_ matter, b/c references are made only
# to map index numbers, not fleshed out vl-pair tuples.
# sorts smallest to largest in a list
orderKey = []
for key in keyList:
vectorS, totalS = dictS[key]
if orderKey == []:
orderKey.append(key)
continue
index = 0
for entry in orderKey:
# !!! want smallest first!!!
# if current total is > than this total | DO nothing
if totalS > dictS[entry][1]: #entry is a key, 1, gets the total
index = index + 1
if index == len(orderKey):
# if greater, and this is the last entry, put at end
# (its the largest)
orderKey.append(key)
break
# if current total is < than this total | DO insert
elif totalS < dictS[entry][1]: #entry is a key, 1, gets the total
# when less than or equal to in orderKey, insert at that index
orderKey.insert(index, key)
break
# if current total is == than this total | DO more analysis
elif totalS == dictS[entry][1]: #entry is a key, 1, gets the total
# if current vector reg 6 is < than this vector 6 | DO insert
if dictS[key][0][6] < dictS[entry][0][6]:
orderKey.insert(index, key)
break
elif dictS[key][0][6] > dictS[entry][0][6]: # if >, do nothing
index = index + 1
if index == len(orderKey):
orderKey.append(key)
break
else:
if dictS[key][0][5] < dictS[entry][0][5]:
orderKey.insert(index, key)
break
elif dictS[key][0][5] > dictS[entry][0][5]: # if >, do nothing
index = index + 1
if index == len(orderKey):
orderKey.append(key)
break
else:
if dictS[key][0][4] < dictS[entry][0][4]:
orderKey.insert(index, key)
break
elif dictS[key][0][4] > dictS[entry][0][4]:#if >,do nothing
index = index + 1
if index == len(orderKey):
orderKey.append(key)
break
else:
if dictS[key][0][3] < dictS[entry][0][3]:
orderKey.insert(index, key)
break
elif dictS[key][0][3] > dictS[entry][0][3]:
#if Greater, do nothing
index = index + 1
if index == len(orderKey):
orderKey.append(key)
break
else:
if dictS[key][0][2] < dictS[entry][0][2]:
orderKey.insert(index, key)
break
elif dictS[key][0][2] > dictS[entry][0][2]:
# if greater, do nothing
index = index + 1
if index == len(orderKey):
orderKey.append(key)
break
else:
if dictS[key][0][1] < dictS[entry][0][1]:
orderKey.insert(index, key)
break
elif (dictS[key][0][1] >
dictS[entry][0][1]):
# if greater, do nothing
index = index + 1
if index == len(orderKey):
orderKey.append(key)
break
else:
if (dictS[key][0][0] <
dictS[entry][0][0]):
orderKey.insert(index, key)
break
elif (dictS[key][0][0] >
dictS[entry][0][0]):
# if greater, do nothing
index = index + 1
if index == len(orderKey):
orderKey.append(key)
break
else: # do nothing
index = index + 1
if index == len(orderKey):
# if greater, and this is the last entry, put at end (its the largest)
orderKey.append(key)
break
else:
index = index + 1
# if greater, and this is the last entry,
# put at end (its the largest)
if index == len(orderKey):
orderKey.append(key)
break
return dictS, orderKey
def printSortSMTH(self, pcsX, pcsY):
dictS, orderKey = self.sortSMTH(pcsX, pcsY)
msg = 'final sort %s\n' % (repr(orderKey).replace(' ', ''))
msg = msg + '[vector]:[displacement]:\n'
for key in orderKey:
line = ''
map = self.getSingleMap(len(pcsX), len(pcsY), key)
for entry in dictS[key]:
line = line + repr(entry).replace(' ', '') + ':'
mapString = self.rawMapToString(map)
msg = msg + '%sMC %i, map %s\n' % (line.ljust(55), key, mapString)
print msg
#------------------------------------------------------------------------||--
def UNIF(self, pcsX, pcsY, map):
vlPairs = self.genVlPairs(pcsX, pcsY, map)
vectorU = [0,0,0,0,0,0,0,0,0,0,0,0]
for pcs_voice in vlPairs:
x = pcs_voice[0]
y = pcs_voice[1]
dist = y-x
if dist < 0 or dist > 11:
dist = pitchTools.pcTransposer(dist, 0) #trans by 0 to perf mod 12
vectorU[dist] = vectorU[dist] + 1
valuesU = []
for reg in vectorU:
valuesU.append(reg)
valuesU.sort()
valuesU.reverse() #in order form largest to smallest, with duplicates
orderedIcPeaksU = [] # contains ordered index positions, not values
dummy_vector = copy.copy(vectorU)
for value in valuesU: # has all values for every reg, incl 0s
if value != 0:
i = dummy_vector.index(value) #get value's index numver
orderedIcPeaksU.append(i)
dummy_vector[i] = -1 # knock out so that will not get chosen again
### use to finde span
double_range = range(0,12) + range(0,12)
start = 0
count = 0
max = 0
for i in double_range:
count = count + 1
if vectorU[i] == 0 and start == 0:
start = 1
count = 1
elif vectorU[i] == 0 and start == 1:
continue
elif vectorU[i] != 0 and start == 1:
start = 0
if (count - 1) >= max:
max = count - 1
elif vectorU[i] != 0 and start == 0:
continue
spanU = 12 - max
### find offset
UNIFoffsetCandidates = []
## print 'unif ordered ic peaks %r' % orderedIcPeaksU
for peaksIndex in orderedIcPeaksU:
# ordered peaks contains the register position of non-zero entries
mvt_from_list = []
# for the current peakIndex, this is the remaining index positions
# that need to be tested to
for i in range(0,12):
# dont want 0s or the value equal to peaks index
if vectorU[i] == 0 or i == peaksIndex:
continue
else:
mvt_from_list.append(i)
# find all possible mod 12 locations for the destination
destination = peaksIndex
destNegative = peaksIndex - 12
destPositive = peaksIndex + 12
temp_distance = 0 ### the accumulator of the distances in the mvt list
for currentOriginPeak in mvt_from_list:
startIndex = currentOriginPeak
a = abs(destination - startIndex)
# find all possible dstinances to the mod12 destinations,
# and choose the shortest
b = abs(destNegative - startIndex)
c = abs(destPositive - startIndex)
posibleDistanceList = [a,b,c]
shortestDistance = min(posibleDistanceList)
temp_distance = temp_distance + (shortestDistance *
vectorU[currentOriginPeak])
# print 'mvt from originPeak %r to peaksIndex %r, dis fnd %i, wghtd as
# %i' % (currentOriginPeak, peaksIndex, shortestDistance,
# (shortestDistance * vectorU[currentOriginPeak]))
#print 'Unif candidiate total distance %r' % (temp_distance)
UNIFoffsetCandidates.append((temp_distance, peaksIndex))
offsetU = 99999
for (offset, peaksIndex) in UNIFoffsetCandidates:
if offset <= offsetU:
offsetU = offset
offsetIcPeakU = []
for (offset, peaksIndex) in UNIFoffsetCandidates:
if offset == offsetU:
offsetIcPeakU.append(peaksIndex)
maxU = 0
for entry in vectorU:
if entry >= maxU:
maxU = entry
# vector, index of nonzero entries, ties for shortest Offset, span, offset
return vectorU, orderedIcPeaksU, offsetIcPeakU, maxU, spanU, offsetU
def sortUNIF(self, pcsX, pcsY):
# returns a dictionary and a list
# the dictionary containts refNo for map : values
# list contains ordered refNo according to sorting principles
if len(pcsX) > 6 or len(pcsX) < 1 or len(pcsY) > 6 or len(pcsY) < 1:
return None
mapDict = self.getMapDict(len(pcsX), len(pcsY))
keyList = mapDict.keys()
keyList.sort()
dictU = {}
for key in keyList:
n = self.UNIF(pcsX, pcsY, mapDict[key])
vectorU, orderedIcPeaksU, offsetIcPeakU, maxU, spanU, offsetU = n
dictU[key] = (vectorU, orderedIcPeaksU, offsetIcPeakU,
maxU, spanU, offsetU)
# list of keys in sorted order
# the order of the pcs entered _does_ matter, b/c references are made only
# to map index numbers, not fleshed out vl-pair tuples.
# sorts smallest to largest in a list (we want largest,
# to smallest, so reverse at end)
orderMax = [] # sort list according to
for key in keyList:
maxU = dictU[key][3] # 3 gets the max vale for any vector register
if orderMax == []:
orderMax.append(key)
continue
index = 0
for entry in orderMax:
if maxU > dictU[entry][3]: #entry is a key, 3, gets the MAX
index = index + 1
if index == len(orderMax):
orderMax.append(key)
break
elif maxU <= dictU[entry][3]: #entry is a key, 1, gets the max
orderMax.insert(index, key)
break
else:
index = index + 1
# was orderKey, not orderMax
if index == len(orderMax):
orderMax.append(key)
# orderKey.append(key) # was incorrect?
break
# 5 gets the offset vale for any vector register# this is a list of
# indexNos that give the order of Max values, from the highest
# to the lowest.
orderMax.reverse()
# this sort is necessary
# sorts smallest to largest in a list
orderSpan = [] ## sort list according to
for key in keyList:
spanU = dictU[key][4] ## 4 gets the span vale for any vector register
if orderSpan == []:
orderSpan.append(key)
continue
index = 0
for entry in orderSpan:
if spanU > dictU[entry][4]: #entry is a key, 4, gets the span
index = index + 1
if index == len(orderSpan):
orderSpan.append(key)
break
elif spanU <= dictU[entry][4]: #entry is a key, 4, gets the span
orderSpan.insert(index, key)
break
else:
index = index + 1
# orderSpan here was given as orderKey
if index == len(orderSpan):
orderSpan.append(key)
break
# sorts smallest to largest in a list
orderOffset = [] # sort list according to
for key in keyList:
# 5 gets the offset vale for any vector register
offsetU = dictU[key][5]
if orderOffset == []:
orderOffset.append(key)
continue
index = 0
for entry in orderOffset:
# entry is a key, 5, gets the offset
if offsetU > dictU[entry][5]:
index = index + 1
if index == len(orderOffset):
orderOffset.append(key)
break
# entry is a key, 5, gets the offset
elif offsetU <= dictU[entry][5]:
orderOffset.insert(index, key)
break
else:
index = index + 1
# orderOffset here was orderKeu
if index == len(orderOffset):
orderOffset.append(key)
break
# sort by offset, max, then span: orderOffset, orderMax, orderSpan
# conversion max >>> offset # span >>> max # offset >>> span
orderKey = [] # sort list according to
for key in orderOffset: # take offset list as initial sort
UNIF_max = dictU[key][3] ## 3 gets the max
spanU = dictU[key][4] # 4 gets the span
offsetU = dictU[key][5] # 5 gets the offset
if orderKey == []:
orderKey.append(key)
continue
index = 0
for entry in orderKey: ## this is the list of keys already sorted
# if current offset is > than this offset | DO nothing
if offsetU > dictU[entry][5]:
index = index + 1 # index keeps tracks of position in orderKey`
if index == len(orderKey):
orderKey.append(key)
break
# if current offset is < than this offset |
# current max is > this max | DO insert
elif offsetU < dictU[entry][5] and UNIF_max > dictU[entry][3]:
orderKey.insert(index, key)
break
# if current offset is < than this offset |
# current max is < this max | DO nothing
elif offsetU < dictU[entry][5] and UNIF_max < dictU[entry][3]:
index = index + 1 # index keeps tracks of position in orderKey`
if index == len(orderKey):
orderKey.append(key)
break
# if current offset is == than this offset |
# current max is > this max | DO insert
elif offsetU == dictU[entry][5] and UNIF_max > dictU[entry][3]:
orderKey.insert(index, key)
break
# if current offset is == than this offset |
# current max is < this max | DO nothing
elif offsetU == dictU[entry][5] and UNIF_max < dictU[entry][3]:
index = index + 1 # index keeps track of position in orderKey`
if index == len(orderKey):
orderKey.append(key)
break
# if current offset is == than this offset |
# current max is == this max | current span is <= this span |
# DO inset
elif (offsetU == dictU[entry][5] and UNIF_max == dictU[entry][3] and
spanU <= dictU[entry][4]):
orderKey.insert(index, key)
break
# if current offset is == than this offset |
#current max is == this max |
#current span is > this span | DO nothing
elif (offsetU == dictU[entry][5] and UNIF_max == dictU[entry][3] and
spanU <= dictU[entry][4]):
# index keeps tracks of position in orderKey`
index = index + 1
if index == len(orderKey):
orderKey.append(key)
break
else:
index = index + 1
if index == len(orderKey):
orderKey.append(key)
break
return dictU, orderKey, orderMax, orderSpan, orderOffset
def printSortUNIF(self, pcsX, pcsY):
a = self.sortUNIF(pcsX, pcsY)
dictU, orderKey, orderMax, orderSpan, orderOffset = a
msg = 'final sort %s\nmax sort %s\nspan sort %s\noffset sort %s\n' % (repr(orderKey).replace(' ', ''),
repr(orderMax).replace(' ', ''), repr(orderSpan).replace(' ', ''), repr(orderOffset).replace(' ', ''))
msg = msg + '[vector]:[peaks]:[offset-peaks]:max:span:offset:\n'
for key in orderKey:
line = ''
map = self.getSingleMap(len(pcsX), len(pcsY), key)
for entry in dictU[key]:
line = line + repr(entry).replace(' ', '') + ':'
mapString = self.rawMapToString(map)
msg = msg + '%sMC %i, map %s\n' % (line.ljust(55), key, mapString)
print msg
#------------------------------------------------------------------------||--
def BAL(self, pcsX, pcsY, map):
vlPairs = self.genVlPairs(pcsX, pcsY, map)
vectorB = [0,0,0,0,0,0,0,0,0,0,0,0]
for pcs_voice in vlPairs:
x = pcs_voice[0]
y = pcs_voice[1]
dist = x + y
dist = pitchTools.pcTransposer(dist, 0) #trans by 0 to perf mod 12
vectorB[dist] = vectorB[dist] + 1
valuesB = []
for reg in vectorB:
valuesB.append(reg)
valuesB.sort()
valuesB.reverse() # now in order form largest to smallest
orderedIcPeaksB = []
dummy_vector = copy.copy(vectorB)
for value in valuesB:
i = dummy_vector.index(value)
if value != 0:
orderedIcPeaksB.append(i)
dummy_vector[i] = -1 # knock out so that will not get chosen again
double_range = range(0,12) + range(0,12)
start = 0
count = 0
max = 0
for i in double_range:
count = count + 1
if vectorB[i] == 0 and start == 0:
start = 1
count = 1
elif vectorB[i] == 0 and start == 1:
continue
elif vectorB[i] != 0 and start == 1:
start = 0
if (count - 1) >= max:
max = count - 1
elif vectorB[i] != 0 and start == 0:
continue
spanB = 12 - max
# find offset
BALoffsetCandidates = []
# print 'bal ordered ic peaks %r' % orderedIcPeaksB
# ordered peaks contains the register position of non-zero entries
for peaksIndex in orderedIcPeaksB:
mvt_from_list = []
# for the current peakIndex, this is the remaining index positions
# that need to be tested to
for i in range(0,12):
# dont want 0s or the value equal to peaks index
if vectorB[i] == 0 or i == peaksIndex:
continue
else:
mvt_from_list.append(i)
# find all possible mod 12 locations for the destination
destination = peaksIndex
destNegative = peaksIndex - 12
destPositive = peaksIndex + 12
temp_distance = 0 ### the accumulator of the distances in the mvt list
for currentOriginPeak in mvt_from_list:
startIndex = currentOriginPeak
# find all possible dstinances to the mod12 destinations,
# and choose the shortest
a = abs(destination - startIndex)
b = abs(destNegative - startIndex)
c = abs(destPositive - startIndex)
posibleDistanceList = [a,b,c]
shortestDistance = min(posibleDistanceList)
temp_distance = temp_distance + (shortestDistance * vectorB[currentOriginPeak])
# print 'mvt from originPeak %r to peaksIndex %r, dis fnd %i, wghtd as %i' % (currentOriginPeak, peaksIndex, shortestDistance, (shortestDistance * vectorB[currentOriginPeak]))
#print 'Bal candidiate total distance %r' % (temp_distance)
BALoffsetCandidates.append((temp_distance, peaksIndex))
offsetB = 99999
for (offset, peaksIndex) in BALoffsetCandidates:
if offset <= offsetB:
offsetB = offset
BALoffset_icPeak = []
for (offset, peaksIndex) in BALoffsetCandidates:
if offset == offsetB:
BALoffset_icPeak.append(peaksIndex)
BALmax = 0
for entry in vectorB:
if entry >= BALmax:
BALmax = entry
# vector, index of nonzero entries, ties for shortest Offset, span, offset
return vectorB, orderedIcPeaksB, BALoffset_icPeak, BALmax, spanB, offsetB
def sortBAL(self, pcsX, pcsY):
# returns a dictionary and a list
# the dictionary containts refNo for map : values
# list contains ordered refNo according to sorting principles
if len(pcsX) > 6 or len(pcsX) < 1 or len(pcsY) > 6 or len(pcsY) < 1:
return None
mapDict = self.getMapDict(len(pcsX), len(pcsY))
keyList = mapDict.keys()
keyList.sort()
dictB = {}
for key in keyList:
a = self.BAL(pcsX, pcsY, mapDict[key])
vectorB, orderedIcPeaksB, BALoffset_icPeak, BALmax, spanB, offsetB = a
dictB[key] = (vectorB, orderedIcPeaksB, BALoffset_icPeak,
BALmax, spanB, offsetB)
# list of keys in sorted order
# the order of the pcs entered _does_ matter, b/c references are made only
# to map index numbers, not fleshed out vl-pair tuples.
# sorts smallest to largest in a list
# (we want largest, to smallest, so reverse at end)
orderMax = [] ## sort list according to
for key in keyList:
BALmax = dictB[key][3] # 3 gets the max vale for any vector register
if orderMax == []:
orderMax.append(key)
continue
index = 0
for entry in orderMax:
if BALmax > dictB[entry][3]: #entry is a key, 3, gets the MAX
index = index + 1
if index == len(orderMax):
orderMax.append(key)
break
elif BALmax <= dictB[entry][3]: #entry is a key, 1, gets the max
orderMax.insert(index, key)
break
else:
index = index + 1
# was orderKey, not orderMax
if index == len(orderMax):
orderMax.append(key)
break
orderMax.reverse()
# this is a list of indexNos that give the order of Max values,
# from the highest to the lowest.
# this sort is necessary
# sorts smallest to largest in a list
orderSpan = [] ## sort list according to
for key in keyList:
spanB = dictB[key][4]# 4 gets the span vale for any vector register
if orderSpan == []:
orderSpan.append(key)
continue
index = 0
for entry in orderSpan:
#entry is a key, 4, gets the span
if spanB > dictB[entry][4]:
index = index + 1
if index == len(orderSpan):
orderSpan.append(key)
break
#entry is a key, 4, gets the span
elif spanB <= dictB[entry][4]:
orderSpan.insert(index, key)
break
else:
index = index + 1
# was orderKey, not orderSpan
if index == len(orderSpan):
orderSpan.append(key)
break
# this sort is not nec, keep for testing
# sorts smallest to largest in a list
orderOffset = [] ## sort list according to
for key in keyList:
# 5 gets the offset vale for any vector register
offsetB = dictB[key][5]
if orderOffset == []:
orderOffset.append(key)
continue
index = 0
for entry in orderOffset:
#entry is a key, 5, gets the offset
if offsetB > dictB[entry][5]:
index = index + 1
if index == len(orderOffset):
orderOffset.append(key)
break
#entry is a key, 5, gets the offset
elif offsetB <= dictB[entry][5]:
orderOffset.insert(index, key)
break
else:
index = index + 1
# was orderKey, not orderOffset
if index == len(orderOffset):
orderOffset.append(key)
break
## sort by offset, max, then span: orderOffset, orderMax, orderSpan
## conversion max >>> offset # span >>> max # offset >>> span
orderKey = [] ## sort list according to
for key in orderOffset: # take offset list as initial sort
maxB = dictB[key][3] ## 3 gets the max
spanB = dictB[key][4] ## 4 gets the span
offsetB = dictB[key][5] ## 5 gets the offset
if orderKey == []:
orderKey.append(key)
continue
index = 0
for entry in orderKey: ## this is the list of keys already sorted
# if current offset is > than this offset | DO nothing
if offsetB > dictB[entry][5]:
index = index + 1
# index keeps tracks of position in orderKey`
if index == len(orderKey):
orderKey.append(key)
break
# if current offset is < than this offset |
# current max is > this max | DO insert
elif offsetB < dictB[entry][5] and maxB > dictB[entry][3]:
orderKey.insert(index, key)
break
# if current offset is < than this offset |
# current max is < this max | DO nothing
elif offsetB < dictB[entry][5] and maxB < dictB[entry][3]:
index = index + 1
# index keeps tracks of position in orderKey`
if index == len(orderKey):
orderKey.append(key)
break
# if current offset is == than this offset |
#current max is > this max | DO insert
elif offsetB == dictB[entry][5] and maxB > dictB[entry][3]:
orderKey.insert(index, key)
break
# if current offset is == than this offset |
# current max is < this max | DO nothing
elif (offsetB == dictB[entry][5] and maxB < dictB[entry][3]):
index = index + 1
# index keeps tracks of position in orderKey`
if index == len(orderKey):
orderKey.append(key)
break
# if current offset is == than this offset |
# current max is == this max | current span is <= this span |
# DO inset
elif (offsetB == dictB[entry][5] and maxB == dictB[entry][3]
and spanB <= dictB[entry][4]):
orderKey.insert(index, key)
break
# if current offset is == than this offset |
# current max is == this max | current span is > this span |
# DO nothing
elif (offsetB == dictB[entry][5] and maxB == dictB[entry][3]
and spanB <= dictB[entry][4]):
# index keeps tracks of position in orderKey`
index = index + 1
if index == len(orderKey):
orderKey.append(key)
break
else:
index = index + 1
if index == len(orderKey):
orderKey.append(key)
break
return dictB, orderKey, orderMax, orderSpan, orderOffset
def printSortBAL(self, pcsX, pcsY):
a = self.sortBAL(pcsX, pcsY)
dictB, orderKey, orderMax, orderSpan, orderOffset = a
msg = 'final sort %s\nmax sort %s\nspan sort %s\noffset sort %s\n' % (repr(orderKey).replace(' ', ''),
repr(orderMax).replace(' ', ''), repr(orderSpan).replace(' ', ''), repr(orderOffset).replace(' ', ''))
msg = msg + '[vector]:[peaks]:[offset-peaks]:max:span:offset:\n'
for key in orderKey:
line = ''
map = self.getSingleMap(len(pcsX), len(pcsY), key)
for entry in dictB[key]:
line = line + repr(entry).replace(' ', '') + ':'
mapString = self.rawMapToString(map)
msg = msg + '%sMC %i, map %s\n' % (line.ljust(55), key, mapString)
print msg
|