From 852f4cad1dc916e8af744feb2eda99cb995a4b9f Mon Sep 17 00:00:00 2001 From: Luke Date: Mon, 30 Jul 2018 19:01:37 -0700 Subject: [PATCH] Added support to plot measurement data Added support to plot measurement results, as well as some updates to the default style. --- LPRDefaultPlotting.py | 4 ++ TankGlobals.py | 8 +-- cadenceResults.py | 4 +- parsePy.py | 161 ++++++++++++++++++++++++++++++++++++------ runAll.sh | 1 + runParse.sh | 20 ++++++ tankPlot.py | 8 ++- 7 files changed, 176 insertions(+), 30 deletions(-) mode change 100644 => 100755 parsePy.py create mode 100755 runParse.sh diff --git a/LPRDefaultPlotting.py b/LPRDefaultPlotting.py index 32b383d..09b3fd2 100644 --- a/LPRDefaultPlotting.py +++ b/LPRDefaultPlotting.py @@ -12,6 +12,9 @@ import re from matplotlib import rcParams, pyplot as pp from cycler import cycler +POLAR_YLIM_CONST=(-18,-6) +POLAR_YLIM_CONST_ALT=(-32,-6) + fcFontList = FM.get_fontconfig_fonts() # Search only for fonts that have name matches similar to this # note this is ALSO a priority list @@ -50,6 +53,7 @@ rcParams['mathtext.it'] = 'serif:italic' rcParams['mathtext.bf'] = 'serif:bold' rcParams['mathtext.sf'] = 'serif' rcParams['mathtext.tt'] = 'monospace' +rcParams['lines.linewidth'] = 1.0 # axes.prop_cycle COLOR_CYCLE_LIST = [ diff --git a/TankGlobals.py b/TankGlobals.py index 5e324b5..711b2ea 100644 --- a/TankGlobals.py +++ b/TankGlobals.py @@ -38,7 +38,7 @@ class ampSystem: self.q1_L = 25 self.q1_C = 8 self.l1 = 140e-3 # nH - self.gm1 = 25e-3 # S + self.gm1 = 2.5e-3 # S self._gamma_steps=8 self._gamma_cap_ratio = 0.997 @@ -190,10 +190,10 @@ class bufferSystem: # Configuration Of Hardware ##### - self.q2_L = 25 - self.q2_C = 50 + self.q2_L = 15 + self.q2_C = 30 self.l2 = 140e-3 # nH - self.gm2 = 5e-3 # S + self.gm2 = 4e-3 # S if not quiet: ## Report System Descrption diff --git a/cadenceResults.py b/cadenceResults.py index 24bc9de..39fc3d9 100755 --- a/cadenceResults.py +++ b/cadenceResults.py @@ -41,6 +41,8 @@ default_window_position=['+20+80', '+120+80'] ################################################################################ search_curves = ( + ['2018-05-15',3.13], + ['2018-05-16',3.18], ['2018-05-21',3.19], ['2018-05-25',3.13] ) @@ -78,7 +80,7 @@ for ind in inds: GP=np.polyfit(buffer_freq, buffer_gain[:,ind], 2) PP=np.polyfit(buffer_freq, buffer_phase[:,ind], 2) #print(" %.2fe-3 x^2 + %.2fe-3 x + %.2fe-3 " % tuple(1e3*P)) - print(ind) + print(ind, bias_t_mA[ind]) print(GP) print(PP) ax[1].plot(freq_synthetic, np.polyval(GP,freq_synthetic)) diff --git a/parsePy.py b/parsePy.py old mode 100644 new mode 100755 index 34ca300..3e704a3 --- a/parsePy.py +++ b/parsePy.py @@ -5,16 +5,18 @@ import numpy as np import matplotlib ################################################################################ args_parser = argparse.ArgumentParser() -args_parser.add_argument('-n', type=int, default=1, - help='plot testing number') args_parser.add_argument('--save','-s', action='store_true', help='save to files') args_parser.add_argument('--raster','-r', action='store_true', help='save as raster') args_parser.add_argument('--debug','-d', action='store_true', help='hold for debugging') +args_parser.add_argument('--polar','-p', action='store_true', + help='do polar plotting (wide bandwidth)') args_parser.add_argument('--headless','-q', action='store_true', help='Remain neadless even if we aren\'t saving files.') +args_parser.add_argument('-n', type=int, default=3, + help='plot testing number') args = args_parser.parse_args() ################################################################################ @@ -34,6 +36,8 @@ import skrf as rf from scipy.io import loadmat from collections import namedtuple import LPRDefaultPlotting +import re +import json ################################################################################ # Override the defaults for this script @@ -48,12 +52,17 @@ SRC_DATA_NAMES = [\ 'Data_2018-05-16-clean', 'Data_2018-05-21-clean', 'Data_2018-05-25-clean'] -SRC_DATA_INDEX = 2 +SRC_DATA_INDEX = args.n-1 SRC_DATA_NAME = SRC_DATA_NAMES[SRC_DATA_INDEX] +#SRC_DATA_DATESTR = '-'.join(SRC_DATA_NAME.split('_')[1].split('-')[:-1]) SRC_DATA_LOC = '/media/ramdisk/' + SRC_DATA_NAME + '/'; -SRC_DATA_SUMMARY = 'dat_clean/' + SRC_DATA_NAME + '_sum.json'; +SRC_DATA_SUMMARY = '/home/luke/Dropbox/Grad School/1801_PS/' \ + '2018-05_Testing/results_plot/dat_clean/' + SRC_DATA_NAME + '_sum.json'; -FILE_PAT = '%s-trunk2.s2p'; +if args.polar: + FILE_PAT = '%s-trunk2.s2p'; +else: + FILE_PAT = '%s-trunk.s2p'; figdir = 'figures-measured' class MeasurementConfig(namedtuple('config', ['r','c','inv','bias'])): @@ -61,7 +70,10 @@ class MeasurementConfig(namedtuple('config', ['r','c','inv','bias'])): @property def fn_str(self): return "C%02d_R%1d_I%1d_B%0.4f" % (self.c, self.r, self.inv, self.bias) -Measurement = namedtuple('measurement', ['cfg','gain','phase','f','s21']) +Measurement = namedtuple('measurement', ['cfg','gain','phase','f','s21', 'slope']) + +slopeBandwidthMax = 1 +slopeBandwidthFreq = 28+np.array([-1,1])*0.5*slopeBandwidthMax def dB20(x): return 20*np.log10(np.abs(x)) @@ -70,20 +82,64 @@ def ang_deg(x): def ang(x): return np.angle(x) +BDE=namedtuple('BufferDeEmbed',['mstr','PolyGain','PolyPhase','PhiFix','test']) +BDE_list=[] +# 2018-05-15 +BDE_list.append(BDE( + '2018-05-15', + np.array([ 4.06488853e-03, -5.11527396e-01, 2.53053550e+01]), + np.array([-1.62202706e-03, 6.94343608e-01, -1.80381551e+02]), + -60, + 'S02bB_C+02dB_M0' +)) +# 2018-05-16 +BDE_list.append(BDE( + '2018-05-16', + np.array([ 4.08875413e-03, -5.13017311e-01, 2.54047949e+01]), + np.array([-1.29541398e-03, 6.74431785e-01, -1.80127388e+02]), + -60, + 'S02bB_C+02dB_M0' +)) # 2018-05-21 -PolyGain=np.array( [ 4.08875413e-03, -5.13017311e-01, 2.54047949e+01]) -PolyPhase=np.array([-1.29541398e-03, 6.74431785e-01, -1.80127388e+02]) +#PolyGain=np.array( [ 4.08875413e-03, -5.13017311e-01, 2.54047949e+01]) +#PolyPhase=np.array([-1.29541398e-03, 6.74431785e-01, -1.80127388e+02]) +BDE_list.append(BDE( + '2018-05-21', + np.array([ 4.08875413e-03, -5.13017311e-01, 2.54047949e+01]), + np.array([-1.29541398e-03, 6.74431785e-01, -1.80127388e+02]), + -60, + 'S02bB_C+02dB_M0' +)) # 2018-05-25 #PolyGain=np.array( [ 4.06488853e-03, -5.11527396e-01, 2.53053550e+01]) #PolyPhase=np.array([-1.62202706e-03, 6.94343608e-01, -1.80381551e+02]) +BDE_list.append(BDE( + '2018-05-25', + np.array([ 4.06488853e-03, -5.11527396e-01, 2.53053550e+01]), + np.array([-1.62202706e-03, 6.94343608e-01, -1.80381551e+02]), + -70, + 'S02bB_C+06dB_M0' +)) + +source_directory='fromMat/%s_mat/' % SRC_DATA_NAME +for BDEx in BDE_list: + if re.search(BDEx.mstr, source_directory) != None: + PolyGain=BDEx.PolyGain + PolyPhase=BDEx.PolyPhase + PhaseFixedRotationFactor=BDEx.PhiFix + StopTestString=BDEx.test + FamStr=BDEx.mstr + break -source_directory='fromMat/Data_2018-05-21-clean_mat/' -source_data_list=['fromMat/Data_2018-05-21-clean_mat/S02bB_C+01dB_M0.mat'] for filename in os.listdir(source_directory): filename=source_directory+filename group_filename_string = filename.split('/')[-1][:-4] src = loadmat(filename, struct_as_record=False) + if not HEADLESS and group_filename_string != StopTestString: + # skip until we hit some aribitrary targets + continue + collectedData=[] for sample in src['data'][0]: tmp = [sample.__getattribute__(key)[0,0] for key in ['r', 'c', 'inv', 'bias_dp_set']] @@ -93,37 +149,96 @@ for filename in os.listdir(source_directory): freq = np.squeeze(s2p_file.f*1e-9) buffer_gain = np.polyval(PolyGain,freq) buffer_phase = np.polyval(PolyPhase,freq) - buffer_phase = buffer_phase - np.mean(buffer_phase) - sdat = np.squeeze(s2p_file.s21.s) + buffer_phase = buffer_phase - np.mean(buffer_phase) + \ + PhaseFixedRotationFactor*np.pi/180 + buffer_sdat = np.power(10,buffer_gain/20)*np.exp(1j*buffer_phase) + + sdat = np.squeeze(s2p_file.s21.s)/buffer_sdat + + slope_valid_inds = np.where(np.all((freq >= slopeBandwidthFreq[0], + freq <= slopeBandwidthFreq[1]),0)) + sub_angles = np.unwrap(np.angle(sdat[slope_valid_inds]))*180/np.pi + sub_freq = freq[slope_valid_inds]-np.mean(freq[slope_valid_inds]) + slope = np.polyfit(sub_freq,sub_angles-np.mean(sub_angles),1)[0] index = np.squeeze(np.argwhere(freq==28)) collectedData.append(Measurement(pt, - dB20(sdat[index])-buffer_gain[index], - ang_deg(sdat[index])-buffer_phase[index], - freq, sdat)) + dB20(sdat[index]), + ang_deg(sdat[index]), + freq, sdat, slope)) + + # Find the indicies close to 0 and 180 as my reference curves + phis = np.array([s.phase for s in collectedData]) + best_slopes = np.argsort(np.abs(np.mod(phis+90,180)-90))[0:6] + slope_list = np.array([s.slope for s in collectedData]) + slope_avg = np.mean(slope_list[best_slopes]) h=pp.figure() - ax=h.add_subplot(1,1,1, projection='polar') + if args.polar: + ax=h.add_subplot(1,1,1, projection='polar') + else: + h2=pp.figure() + ax=h.subplots(2,1) + ax = np.append(ax, h2.subplots(1,1)) print("---------------------||------------------------------") print(" _C R I _Bias_ || Gain Phase ") print("---------------------||------------------------------") for imeas in collectedData: - ax.plot(ang(imeas.s21)-buffer_phase, dB20(imeas.s21)-buffer_gain) + if args.polar: + #ax.plot(ang(imeas.s21)-buffer_phase, dB20(imeas.s21)-buffer_gain) + ax.plot(ang(imeas.s21), dB20(imeas.s21)) + else: + #ax[0].plot(imeas.f, dB20(imeas.s21)-buffer_gain) + ax[0].plot(imeas.f, dB20(imeas.s21)) + #unwrapped_phase = 180/np.pi*np.unwrap(ang(imeas.s21)-buffer_phase) + #ax[1].plot(imeas.f, unwrapped_phase) + unwrapped_phase = 180/np.pi*np.unwrap(ang(imeas.s21)) + ax[1].plot(imeas.f, unwrapped_phase) + slope_relative = (imeas.f-28)*slope_avg + ax[2].plot(imeas.f, unwrapped_phase-slope_relative) print(" %2d %d %d %.4f || %+7.1f dB %+9.2f deg" % \ (imeas.cfg.c, imeas.cfg.r, imeas.cfg.inv, imeas.cfg.bias, \ imeas.gain, imeas.phase)) print("---------------------||------------------------------") - ax.set_ylim(-20,-6) - ax.set_title('Measured Performance') + if args.polar: + ax.set_ylim(LPRDefaultPlotting.POLAR_YLIM_CONST) + + if args.polar: + ax.set_title('Measured Performance') + else: + ax[0].set_title('Measured Performance') + ax[0].set_ylabel('Gain (dB)'); + ax[1].set_ylabel('Phase (deg)'); + ax[2].set_ylabel('Phase (deg)'); + ax[2].set_title('Relative Phase') + for aT in ax: + aT.set_xlabel('Frequency (GHz)') + aT.grid() + #aT.set_xlim((np.min(imeas.f), np.max(imeas.f))) + aT.set_xlim((28-1.0, 28+1.0)) + + if args.polar: + old_pos = ax.title.get_position() + ax.title.set_position((old_pos[0], 1.1)) - old_pos = ax.title.get_position() - ax.title.set_position((old_pos[0], 1.1)) h.tight_layout() + if not args.polar: + h2.tight_layout() if args.save: - h.savefig('%s/%s.%s' % (figdir, - 'PolarGain-%s' % group_filename_string, fig_ext)) + if args.polar: + h.savefig('%s/PolarGain-%s-%s.%s' % (figdir, FamStr, + group_filename_string, fig_ext)) + else: + h.savefig('%s/StdPlots-%s-%s.%s' % (figdir, FamStr, + group_filename_string, fig_ext)) + h2.savefig('%s/RelStdPlots-%s-%s.%s' % (figdir, FamStr, + group_filename_string, fig_ext)) if HEADLESS: + if not args.polar: + pp.close() pp.close() else: + if not args.polar: + h2.show() h.show() break diff --git a/runAll.sh b/runAll.sh index 889e0d6..54a149a 100755 --- a/runAll.sh +++ b/runAll.sh @@ -36,6 +36,7 @@ for n in 1 2 3 4 11 12 13 14; do ) & done +#bash ./runParse.sh & while [[ $(jobs -lr | wc -l) -gt 0 ]]; do sleep 0.1; done mkdir -p figures-png diff --git a/runParse.sh b/runParse.sh new file mode 100755 index 0000000..6a34ff1 --- /dev/null +++ b/runParse.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +MAX_JOBS=4 + +for n in $(seq 1 4); do + while [[ $MAX_JOBS -le $(jobs -l | wc -l) ]]; do sleep 0.1; done + echo " start $n →" + ( ./parsePy.py -rq -n $n 1>/dev/null ) & + while [[ $MAX_JOBS -le $(jobs -l | wc -l) ]]; do sleep 0.1; done + ( ./parsePy.py -rpq -n $n 1>/dev/null ) & + while [[ $MAX_JOBS -le $(jobs -l | wc -l) ]]; do sleep 0.1; done + ( ./parsePy.py -sq -n $n 1>/dev/null ) & + while [[ $MAX_JOBS -le $(jobs -l | wc -l) ]]; do sleep 0.1; done + ( ./parsePy.py -spq -n $n 1>/dev/null ) & +done + +while [[ $(jobs -lr | wc -l) -gt 0 ]]; do sleep 0.1; done +SELECT_STRING="S02bB_C+03dB" +rsync -aPv "figures-measured/"*"${SELECT_STRING}"* ../tex/figures-measured/ + diff --git a/tankPlot.py b/tankPlot.py index 44248d4..3a02b8f 100755 --- a/tankPlot.py +++ b/tankPlot.py @@ -103,8 +103,12 @@ print(' Max G1 boost %.2fmS (%.1f%% of gm1)' % \ ################################################################################ # Extract the computed tank conductanec, and the transfer functions. +(y_buf, tf_buf) = B.compute_ref(f) + (y_tank, tf) = S.compute_block(f) (_, tf_ref) = S.compute_ref(f) +tf = tf*(tf_buf*np.ones((tf.shape[1],1))).T +tf_ref = tf_ref*tf_buf # To produce full 360 dgree plots, double the two transfer functions by # considering inversion. @@ -126,8 +130,6 @@ y_tank = y_tank.T (bw_ang, rms_ang_swp)=rms_v_bw(tf_r_ang-tf_r_ang_ideal, S.bw_plt) (bw_mag, rms_gain_swp)=rms_v_bw(tf_r, S.bw_plt) -(y_buf, tf_buf) = B.compute_ref(f) - ################################################################################ ################################################################################ ################################################################################ @@ -231,6 +233,7 @@ if 4 in plot_list or 14 in plot_list: ax4[0].set_title('Tank Impedance') ax4[1].set_title('Transfer Function') + ax4[1].set_ylim(LPRDefaultPlotting.POLAR_YLIM_CONST) # Adjust placement of smith plot old_pos = ax4[0].title.get_position() @@ -276,6 +279,7 @@ if 5 in plot_list: ax5[0].set_title('Tank Impedance') ax5[1].set_title('Transfer Function') + ax5[1].set_ylim(LPRDefaultPlotting.POLAR_YLIM_CONST_ALT) # Adjust placement of smith plot old_pos = ax5[0].title.get_position()