picadae calibration programs
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

plot_calibrate.py 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. ##| Copyright: (C) 2019-2020 Kevin Larke <contact AT larke DOT org>
  2. ##| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file.
  3. import sys,os,json,types
  4. import numpy as np
  5. import matplotlib.pyplot as plt
  6. import matplotlib._color_data as mcd
  7. from matplotlib.pyplot import figure
  8. from rms_analysis import calibrate_recording_analysis
  9. from rms_analysis import key_info_dictionary
  10. def plot_by_pitch( inDir, keyInfoD, pitch=None ):
  11. anlD = calibrate_recording_analysis( inDir )
  12. jsonFn = os.path.join(inDir, "meas.json" )
  13. audioFn = os.path.join(inDir, "audio.wav" )
  14. with open(jsonFn,"r") as f:
  15. r = json.load(f)
  16. measD = r['measD']
  17. cfg = types.SimpleNamespace(**r['cfg'])
  18. axN = len(measD) if pitch is None else 1
  19. fig,axL = plt.subplots(axN,1)
  20. fig.set_size_inches(18.5, 10.5*axN)
  21. # for each pitch
  22. for axi,(midi_pitch,measL)in enumerate(measD.items()):
  23. midi_pitch = int(midi_pitch)
  24. if pitch is not None and pitch != midi_pitch:
  25. continue
  26. if pitch is not None:
  27. axi = 0
  28. axL = [ axL ]
  29. targetDbS = set()
  30. hmPulseDbL = []
  31. tdPulseDbL = []
  32. anPulseDbL = []
  33. # for each measurement on this pitch
  34. for mi,d in enumerate(measL):
  35. m = types.SimpleNamespace(**d)
  36. # form a list of pulse/db measurements associated with this pitch
  37. hmPulseDbL.append( (m.pulse_us,m.hm['db'],m.matchFl,m.hm['durMs'],m.skipMeasFl) )
  38. tdPulseDbL.append( (m.pulse_us,m.td['db'],m.matchFl,m.td['durMs'],m.skipMeasFl) )
  39. ar = next(ad for ad in anlD[midi_pitch] if ad['meas_idx']==mi )
  40. anPulseDbL.append( (m.pulse_us,ar['db'],m.matchFl,m.hm['durMs'],m.skipMeasFl))
  41. # get the unique set of targets
  42. targetDbS.add(m.targetDb)
  43. # sort measurements on pulse length
  44. hmPulseDbL = sorted(hmPulseDbL,key=lambda x: x[0])
  45. tdPulseDbL = sorted(tdPulseDbL,key=lambda x: x[0])
  46. anPulseDbL = sorted(anPulseDbL,key=lambda x: x[0])
  47. # plot the re-analysis
  48. pulseL,dbL,matchFlL,_,_ = zip(*anPulseDbL)
  49. axL[axi].plot( pulseL, dbL, label="post", marker='.' )
  50. # plot harmonic measurements
  51. pulseL,dbL,matchFlL,durMsL,skipFlL = zip(*hmPulseDbL)
  52. axL[axi].plot( pulseL, dbL, label="harm", marker='.' )
  53. # plot time-domain based measuremented
  54. pulseL,dbL,matchFlL,_,_ = zip(*tdPulseDbL)
  55. axL[axi].plot( pulseL, dbL, label="td", marker='.' )
  56. # plot target boundaries
  57. for targetDb in targetDbS:
  58. lwr = targetDb * ((100.0 - cfg.tolDbPct)/100.0)
  59. upr = targetDb * ((100.0 + cfg.tolDbPct)/100.0 )
  60. axL[axi].axhline(targetDb)
  61. axL[axi].axhline(lwr,color='lightgray')
  62. axL[axi].axhline(upr,color='gray')
  63. # plot match and 'too-short' markers
  64. for i,matchFl in enumerate(matchFlL):
  65. if durMsL[i] < cfg.minMeasDurMs:
  66. axL[axi].plot( pulseL[i], dbL[i], marker='x', color='black', linestyle='None')
  67. if skipFlL[i]:
  68. axL[axi].plot( pulseL[i], dbL[i], marker='+', color='blue', linestyle='None')
  69. if matchFl:
  70. axL[axi].plot( pulseL[i], dbL[i], marker='.', color='red', linestyle='None')
  71. axL[axi].set_title("pitch:%i %s" % (midi_pitch,keyInfoD[midi_pitch].type))
  72. plt.legend()
  73. plt.show()
  74. def plot_all_notes( inDir ):
  75. jsonFn = os.path.join(inDir, "meas.json" )
  76. audioFn = os.path.join(inDir, "audio.wav" )
  77. with open(jsonFn,"r") as f:
  78. r = json.load(f)
  79. measD = r['measD']
  80. axN = 0
  81. for midi_pitch,measL in measD.items():
  82. axN += len(measL)
  83. print(axN)
  84. fig,axL = plt.subplots(axN,1)
  85. fig.set_size_inches(18.5, 10.5*axN)
  86. i = 0
  87. for midi_pitch,measL in measD.items():
  88. for d in measL:
  89. axL[i].plot(d['td']['rmsDbV'])
  90. axL[i].plot(d['hm']['rmsDbV'])
  91. axL[i].axvline(d['td']['pk_idx'],color='red')
  92. axL[i].axvline(d['hm']['pk_idx'],color='green')
  93. i += 1
  94. plt.show()
  95. if __name__ == "__main__":
  96. pitch = None
  97. inDir = sys.argv[1]
  98. yamlFn = sys.argv[2]
  99. if len(sys.argv) > 3:
  100. pitch = int(sys.argv[3])
  101. keyInfoD = key_info_dictionary( yamlCfgFn=yamlFn)
  102. #plot_all_notes( inDir )
  103. plot_by_pitch(inDir,keyInfoD,pitch)
  104. #calibrate_recording_analysis( inDir )