plot_seq_1.py : Many changes and updates.

This commit is contained in:
kevin 2021-01-18 10:35:14 -05:00
parent e32f224d12
commit f36e7c8a64

View File

@ -1,6 +1,6 @@
##| Copyright: (C) 2019-2020 Kevin Larke <contact AT larke DOT org> ##| Copyright: (C) 2019-2020 Kevin Larke <contact AT larke DOT org>
##| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file. ##| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file.
import os, sys,json import os, sys,json,math
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import numpy as np import numpy as np
from common import parse_yaml_cfg from common import parse_yaml_cfg
@ -458,17 +458,43 @@ def _plot_us_db_takes( inDir, cfg, pitchL, takeIdL, printDir="", printFn="" ):
usL, dbL, durMsL, _, holdDutyPctL = get_merged_pulse_db_measurements( inDir, midi_pitch, analysisArgsD['rmsAnalysisArgs'], takeId=takeId ) usL, dbL, durMsL, _, holdDutyPctL = get_merged_pulse_db_measurements( inDir, midi_pitch, analysisArgsD['rmsAnalysisArgs'], takeId=takeId )
ax.plot(usL,dbL, marker='.',label="%i:%i %s %s" % (midi_pitch,takeId,keyMapD[midi_pitch]['class'],keyMapD[midi_pitch]['type'])) ax.plot(usL,dbL, marker='.',label="%i:%i %s %s" % (midi_pitch,takeId,keyMapD[midi_pitch]['class'],keyMapD[midi_pitch]['type']))
# for i,(x,y) in enumerate(zip(usL,dbL)): for i,(x,y) in enumerate(zip(usL,dbL)):
# ax.text(x,y,str(i)) ax.text(x,y,str(i))
f_usL,f_dbL = filter_us_db(usL,dbL)
ax.plot(f_usL,f_dbL, marker='.')
elbow_us,elbow_db = elbow.find_elbow(usL,dbL)
ax.plot([elbow_us],[elbow_db],marker='*',markersize=12,color='red',linestyle='None')
elb_idx = nearest_sample_point( dbL, usL, elbow_db, elbow_us )
if printDir: if printDir:
plt.savefig(os.path.join(printDir,printFn),format="png") plt.savefig(os.path.join(printDir,printFn),format="png")
plt.legend() plt.legend()
plt.show() plt.show()
def get_pitches_and_takes( inDir ):
pitchD = {}
inDirL = os.listdir( inDir )
for pitch in inDirL:
path = os.path.join( inDir, pitch )
takeIdL = os.listdir( path )
takeIdL = sorted([ int(takeId) for takeId in takeIdL ])
takeIdL = [ str(x) for x in takeIdL ]
pitchD[int(pitch)] = takeIdL
return pitchD
def plot_us_db_takes( inDir, cfg, pitchL, printDir=""): def plot_us_db_takes( inDir, cfg, pitchL, printDir=""):
@ -480,14 +506,11 @@ def plot_us_db_takes( inDir, cfg, pitchL, printDir=""):
def plot_us_db_takes_last( inDir, cfg, pitchL, printDir ): def plot_us_db_takes_last( inDir, cfg, pitchL, printDir ):
pitchD = get_pitches_and_takes(inDir)
takeIdL = [] takeIdL = []
for pitch in pitchL: for pitch in pitchL:
takeIdL.append( int(pitchD[pitch][-1]) )
inDirL = os.listdir( os.path.join(inDir,str(pitch)))
inDirL = sorted(inDirL)
takeIdL.append( int(inDirL[-1]) )
return _plot_us_db_takes( inDir, cfg, pitchL, takeIdL, printDir, "us_db_takes_last.png") return _plot_us_db_takes( inDir, cfg, pitchL, takeIdL, printDir, "us_db_takes_last.png")
@ -535,17 +558,21 @@ def plot_all_noise_curves( inDir, cfg, pitchL=None ):
plt.legend() plt.legend()
plt.show() plt.show()
def nearest_sample_point( dbL, usL, db0, us0 ):
xL = np.array([ abs(us-us0) for db,us in zip(dbL,usL) ])
return np.argmin(xL)
def plot_min_max_2_db( inDir, cfg, pitchL=None, takeId=2, printDir=None ): def plot_min_max_2_db( inDir, cfg, pitchL=None, takeId=2, printDir=None ):
takeIdArg = takeId
pitchTakeD = get_pitches_and_takes(inDir)
pitchFolderL = os.listdir(inDir) pitchFolderL = os.listdir(inDir)
print(pitchL)
if pitchL is None: if pitchL is None:
pitchL = [ int( int(pitchFolder) ) for pitchFolder in pitchFolderL ] pitchL = [ int( int(pitchFolder) ) for pitchFolder in pitchFolderL ]
print(pitchL)
okL = [] okL = []
outPitchL = [] outPitchL = []
minDbL = [] minDbL = []
@ -553,9 +580,11 @@ def plot_min_max_2_db( inDir, cfg, pitchL=None, takeId=2, printDir=None ):
for midi_pitch in pitchL: for midi_pitch in pitchL:
print(midi_pitch) takeId = None
if takeIdArg == -1:
takeId = pitchTakeD[midi_pitch][-1]
usL, dbL, durMsL, takeIdL, holdDutyPctL = get_merged_pulse_db_measurements( inDir, midi_pitch, cfg.analysisArgs['rmsAnalysisArgs'] ) usL, dbL, durMsL, takeIdL, holdDutyPctL = get_merged_pulse_db_measurements( inDir, midi_pitch, cfg.analysisArgs['rmsAnalysisArgs'], takeId )
okL.append(False) okL.append(False)
@ -571,6 +600,9 @@ def plot_min_max_2_db( inDir, cfg, pitchL=None, takeId=2, printDir=None ):
minDbL.append(elbow_db) minDbL.append(elbow_db)
outPitchL.append(midi_pitch) outPitchL.append(midi_pitch)
smp_idx = nearest_sample_point( dbL, usL, elbow_db, elbow_us )
print(" %i:[-1,%i], " % (midi_pitch,smp_idx))
p_dL = sorted( zip(outPitchL,minDbL,maxDbL,okL), key=lambda x: x[0] ) p_dL = sorted( zip(outPitchL,minDbL,maxDbL,okL), key=lambda x: x[0] )
@ -593,7 +625,9 @@ def plot_min_max_2_db( inDir, cfg, pitchL=None, takeId=2, printDir=None ):
plt.show() plt.show()
def plot_min_db_manual( inDir, cfg, printDir=None ): def plot_min_db_manual( inDir, cfg, printDir=None, absMaxDb=27, absMinDb=3 ):
pitchTakeD = get_pitches_and_takes(inDir)
pitchL = list(cfg.manualMinD.keys()) pitchL = list(cfg.manualMinD.keys())
@ -606,30 +640,40 @@ def plot_min_db_manual( inDir, cfg, printDir=None ):
for midi_pitch in pitchL: for midi_pitch in pitchL:
manual_take_id = cfg.manualMinD[midi_pitch][0] if cfg.manualLastFl:
manual_take_id = pitchTakeD[midi_pitch][-1]
takeId = manual_take_id
else:
manual_take_id = cfg.manualMinD[midi_pitch][0]
takeId = None
manual_sample_idx = cfg.manualMinD[midi_pitch][1] manual_sample_idx = cfg.manualMinD[midi_pitch][1]
usL, dbL, durMsL, takeIdL, holdDutyPctL = get_merged_pulse_db_measurements( inDir, midi_pitch, cfg.analysisArgs['rmsAnalysisArgs'] ) usL, dbL, durMsL, takeIdL, holdDutyPctL = get_merged_pulse_db_measurements( inDir, midi_pitch, cfg.analysisArgs['rmsAnalysisArgs'], takeId )
okL.append(False) okL.append(False)
takeId = len(set(takeIdL))-1 if takeId is None:
takeId = len(set(takeIdL))-1
# most pitches have 3 sample takes that do not
if len(set(takeIdL)) == 3 and manual_take_id == takeId:
okL[-1] = True
else:
okL[-1] = True
# maxDb is computed on all takes (not just the specified take) # maxDb is computed on all takes (not just the specified take)
db_maxL = sorted(dbL) db_maxL = sorted(dbL)
max_db = np.mean(db_maxL[-4:]) max_db = min(absMaxDb,np.mean(db_maxL[-4:]))
maxDbL.append( max_db ) maxDbL.append( max_db )
# get the us,db values for the specified take # get the us,db values for the specified take
usL,dbL = zip(*[(usL[i],dbL[i]) for i in range(len(usL)) if takeIdL[i]==manual_take_id ]) usL,dbL = zip(*[(usL[i],dbL[i]) for i in range(len(usL)) if takeIdL[i]==manual_take_id ])
# most pitches have 3 sample takes that do not
if len(set(takeIdL)) == 3 and manual_take_id == takeId:
okL[-1] = True
# min db from the sample index manually specified in cfg # min db from the sample index manually specified in cfg
manualMinDb = dbL[ manual_sample_idx ] manualMinDb = max(absMinDb,dbL[ manual_sample_idx ])
minDbL.append( manualMinDb ) minDbL.append( manualMinDb )
outPitchL.append(midi_pitch) outPitchL.append(midi_pitch)
@ -642,8 +686,6 @@ def plot_min_db_manual( inDir, cfg, printDir=None ):
# Form the complete set of min/max db levels for each pitch by interpolating the # Form the complete set of min/max db levels for each pitch by interpolating the
# db values between the manually selected anchor points. # db values between the manually selected anchor points.
interpMinDbL = np.interp( pitchL, cfg.manualAnchorPitchMinDbL, anchorMinDbL ) interpMinDbL = np.interp( pitchL, cfg.manualAnchorPitchMinDbL, anchorMinDbL )
@ -861,27 +903,67 @@ def report_take_ids( inDir ):
if len(takeDirL) == 0: if len(takeDirL) == 0:
print(pitch," directory empty") print(pitch," directory empty")
else: else:
with open( os.path.join(pitchDir,'0','seq.json'), "rb") as f:
r = json.load(f) fn = os.path.join(pitchDir,'0','seq.json')
if not os.path.isfile(fn):
print("Missing sequence file:",fn)
else:
with open( fn, "rb") as f:
r = json.load(f)
if len(r['eventTimeL']) != 81:
print(pitch," ",len(r['eventTimeL'])) if len(r['eventTimeL']) != 81:
print(pitch," ",len(r['eventTimeL']))
if len(takeDirL) != 3: if len(takeDirL) != 3:
print("***",pitch,len(takeDirL)) print("***",pitch,len(takeDirL))
def filter_us_db( us0L, db0L ):
us1L = [us0L[-1]]
db1L = [db0L[-1]]
dDb = 0
lastIdx = 0
for i,(us,db) in enumerate(zip( us0L[::-1],db0L[::-1])):
db1 = db1L[-1]
if db < db1 and db1-db >= dDb/2:
dDb = db1 - db
us1L.append(us)
db1L.append(db)
lastIdx = i
lastIdx = len(us0L) - lastIdx - 1
usL = [ us0L[lastIdx] ]
dbL = [ db0L[lastIdx] ]
dDb = 0
for us,db in zip(us0L[lastIdx::],db0L[lastIdx::]):
db1 = dbL[-1]
if db > db1:
dDb = db-db1
usL.append(us)
dbL.append(db)
return usL,dbL
def cache_us_db( inDir, cfg, outFn ): def cache_us_db( inDir, cfg, outFn ):
pitchTakeD = get_pitches_and_takes(inDir)
pitch_usDbD = {} pitch_usDbD = {}
pitchDirL = os.listdir(inDir) pitchDirL = os.listdir(inDir)
for pitch in pitchDirL: for pitch,takeIdL in pitchTakeD.items():
pitch = int(pitch) pitch = int(pitch)
takeId = takeIdL[-1]
print(pitch) print(pitch)
usL, dbL, durMsL, takeIdL, holdDutyPctL = get_merged_pulse_db_measurements( inDir, pitch, cfg.analysisArgs['rmsAnalysisArgs'] ) usL, dbL, durMsL, takeIdL, holdDutyPctL = get_merged_pulse_db_measurements( inDir, pitch, cfg.analysisArgs['rmsAnalysisArgs'], takeId )
pitch_usDbD[pitch] = { 'usL':usL, 'dbL':dbL, 'durMsL':durMsL, 'takeIdL':takeIdL, 'holdDutyPctL': holdDutyPctL } pitch_usDbD[pitch] = { 'usL':usL, 'dbL':dbL, 'durMsL':durMsL, 'takeIdL':takeIdL, 'holdDutyPctL': holdDutyPctL }
@ -889,7 +971,7 @@ def cache_us_db( inDir, cfg, outFn ):
with open(outFn,"w") as f: with open(outFn,"w") as f:
json.dump(pitch_usDbD,f) json.dump(pitch_usDbD,f)
def gen_vel_map( inDir, cfg, minMaxDbFn, dynLevelN, cacheFn ): def gen_vel_map( inDir, cfg, minMaxDbFn, dynLevelN, cacheFn ):
@ -897,28 +979,44 @@ def gen_vel_map( inDir, cfg, minMaxDbFn, dynLevelN, cacheFn ):
pitchDirL = os.listdir(inDir) pitchDirL = os.listdir(inDir)
# pitchUsDbD = { pitch:
with open(cacheFn,"r") as f: with open(cacheFn,"r") as f:
pitchUsDbD = json.load(f) pitchUsDbD = json.load(f)
# form minMaxDb = { pitch:(minDb,maxDb) }
with open("minInterpDb.json","r") as f: with open("minInterpDb.json","r") as f:
r = json.load(f) r = json.load(f)
minMaxDbD = { pitch:(minDb,maxDb) for pitch,minDb,maxDb in zip(r['pitchL'],r['minDbL'],r['maxDbL']) } minMaxDbD = { pitch:(minDb,maxDb) for pitch,minDb,maxDb in zip(r['pitchL'],r['minDbL'],r['maxDbL']) }
pitchL = sorted( [ int(pitch) for pitch in pitchUsDbD.keys()] )
for pitch in pitchL:
d = pitchUsDbD[str(pitch)]
usL = d['usL'] pitchL = sorted( [ int(pitch) for pitch in pitchUsDbD.keys()] )
dbL = np.array(d['dbL'])
# for each pitch
for pitch in pitchL:
# get the us/db map for this
d = pitchUsDbD[str(pitch)]
usL, dbL = filter_us_db( d['usL'], d['dbL'] )
#usL = d['usL']
#dbL = np.array(d['dbL'])
dbL = np.array(dbL)
velMapD[pitch] = [] velMapD[pitch] = []
for i in range(dynLevelN+1):
db = minMaxDbD[pitch][0] + (i * (minMaxDbD[pitch][1] - minMaxDbD[pitch][0])/ dynLevelN) maxDb = minMaxDbD[pitch][1]
minDb = minMaxDbD[pitch][0]
dynLevelN = len(cfg.velTableDbL)
# for each dynamic level
for i in range(dynLevelN):
#db = minDb + (i * (maxDb - minDb)/ dynLevelN)
db = cfg.velTableDbL[i]
usIdx = np.argmin( np.abs(dbL - db) ) usIdx = np.argmin( np.abs(dbL - db) )
@ -946,7 +1044,7 @@ def gen_vel_map( inDir, cfg, minMaxDbFn, dynLevelN, cacheFn ):
if __name__ == "__main__": if __name__ == "__main__":
printDir = None #os.path.expanduser( "~/src/picadae_ac_3/doc") printDir = os.path.expanduser("~/temp") # os.path.expanduser( "~/src/picadae_ac_3/doc")
cfgFn = sys.argv[1] cfgFn = sys.argv[1]
inDir = sys.argv[2] inDir = sys.argv[2]
mode = sys.argv[3] mode = sys.argv[3]
@ -981,7 +1079,7 @@ if __name__ == "__main__":
elif mode == 'manual_db': elif mode == 'manual_db':
plot_min_db_manual( inDir, cfg, printDir=printDir ) plot_min_db_manual( inDir, cfg, printDir=printDir )
elif mode == 'gen_vel_map': elif mode == 'gen_vel_map':
gen_vel_map( inDir, cfg, "minInterpDb.json", 9, "cache_us_db.json" ) gen_vel_map( inDir, cfg, "minInterpDb.json", 12, "cache_us_db.json" )
elif mode == 'cache_us_db': elif mode == 'cache_us_db':
cache_us_db( inDir, cfg, "cache_us_db.json") cache_us_db( inDir, cfg, "cache_us_db.json")
else: else: