From c5c4ae61eed9a2af9471a783f606d9ab30836dc7 Mon Sep 17 00:00:00 2001 From: Luke Date: Sat, 27 Jul 2019 16:27:58 -0700 Subject: [PATCH] Random updates --- .gitignore | 2 + LPRDefaultPlotting.py | 6 +++ TankGlobals.py | 6 +-- comparisonPlots.py | 2 +- parsePy.py | 96 +++++++++++++++++++++++++++++++++++++----- runAll.sh | 2 +- runParse.sh | 28 ++++++++++--- runSome.sh | 28 +++++++++++++ tankComputers.py | 19 +++++++++ tankPlot.py | 98 ++++++++++++++++++++++++++++++++++++++++--- 10 files changed, 262 insertions(+), 25 deletions(-) create mode 100755 runSome.sh diff --git a/.gitignore b/.gitignore index 646d465..f48764d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ # Figures directory figures* from* +.vscode/ +revisedData # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/LPRDefaultPlotting.py b/LPRDefaultPlotting.py index 641bcf0..5420fb8 100644 --- a/LPRDefaultPlotting.py +++ b/LPRDefaultPlotting.py @@ -14,7 +14,13 @@ from cycler import cycler POLAR_YLIM_CONST=(-18,-6) POLAR_YLIM_CONST_MEAS=(-22,-10) +POLAR_YLIM_CONST_MEAS=(-15,-3) POLAR_YLIM_CONST_ALT=(-32,-6) +GAIN_FIXED_YLIM1=(-20,-0) +GAIN_FIXED_YLIM2=(-30,-0) +GAIN_FIXED_YLIM3=(-10,10) +GAIN_FIXED_YLIM4=(-0,20) +GAIN_FIXED_YLIM5=(-20,0) fcFontList = FM.get_fontconfig_fonts() # Search only for fonts that have name matches similar to this diff --git a/TankGlobals.py b/TankGlobals.py index 711b2ea..bc65864 100644 --- a/TankGlobals.py +++ b/TankGlobals.py @@ -36,7 +36,7 @@ class ampSystem: # Configuration Of Hardware ##### self.q1_L = 25 - self.q1_C = 8 + self.q1_C = 6 self.l1 = 140e-3 # nH self.gm1 = 2.5e-3 # S @@ -46,7 +46,7 @@ class ampSystem: if not quiet: ## Report System Descrption print(' L1 = %.3fpH, C1 = %.3ffF' % (1e3*self.l1, 1e6*self.c1)) - print(' Rp = %.3f Ohm' % (1/self.g1)) + print(' Rp = %.3f Ohm (Gp = %.3f mS)' % (1/self.g1, 1e3*self.g1)) print(' Q = %.1f' % (self.Q1)) self._gamma_warn = False @@ -100,7 +100,7 @@ class ampSystem: @property def alpha_swp(self): range_partial = np.ceil(self.gamma_len/2) - rhs = np.power(np.linspace(0,1,range_partial),2)*(self.alpha_min-1)+1 + rhs = np.power(np.linspace(0,1,range_partial),1)*(self.alpha_min-1)+1 lhs = np.flip(rhs,0) #lhs = np.linspace(np.sqrt(self.alpha_min),1, range_partial) #rhs = np.flip(lhs,0) diff --git a/comparisonPlots.py b/comparisonPlots.py index 307abb9..ab66d52 100755 --- a/comparisonPlots.py +++ b/comparisonPlots.py @@ -71,7 +71,7 @@ f=FreqClass(freq_pts, S1.f0, S1.bw_plt) S1.q1_L = 15 S2 = copy.deepcopy(S1) -gain_variation = +5 # dB +gain_variation = -2 # dB diff --git a/parsePy.py b/parsePy.py index db0f260..ff7fd80 100755 --- a/parsePy.py +++ b/parsePy.py @@ -17,6 +17,8 @@ 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=4, help='plot testing number') +args_parser.add_argument('-c', type=int, default=16, + help='number of phase states [16,32,64]') args = args_parser.parse_args() ################################################################################ @@ -65,6 +67,8 @@ if args.polar: else: FILE_PAT = '%s-trunk.s2p'; figdir = 'figures-measured' +if args.c != 16: + figdir=figdir+('-%d' % args.c) class MeasurementConfig(namedtuple('config', ['r','c','inv','bias'])): __slots__ = () @@ -87,13 +91,14 @@ def ang(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+00dB_M0' + 'S02bB_C+01dB_M0' )) # 2018-05-16 BDE_list.append(BDE( @@ -124,7 +129,7 @@ BDE_list.append(BDE( 'S02bB_C+00dB_M0' )) -source_directory='fromMat/%s_mat/' % SRC_DATA_NAME +source_directory='fromMat/figures-%d/%s_mat/' % (args.c, SRC_DATA_NAME) for BDEx in BDE_list: if re.search(BDEx.mstr, source_directory) != None: PolyGain=BDEx.PolyGain @@ -134,6 +139,26 @@ for BDEx in BDE_list: FamStr=BDEx.mstr break + +################################################################################ +################################################################################ +################################################################################ +# FIXME ######################################################################## +################################################################################ +################################################################################ +################################################################################ +PolyGain_balun=np.array([0, 0, -7]) +PolyPhase_balun=np.array([0, 0, 0]) +################################################################################ +################################################################################ +################################################################################ +################################################################################ + +if args.c == 64: + StopTestString='S05bB_C+05dB_M0_-64' +elif args.c == 32: + StopTestString='S03bB_C+00dB_M0_-32' + with open(SRC_DATA_SUMMARY, 'r') as h_sumDat: sumDat = json.load(h_sumDat) @@ -185,8 +210,13 @@ for filename in os.listdir(source_directory): 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) + + balun_gain = np.polyval(PolyGain_balun,freq) + balun_phase = np.polyval(PolyPhase_balun,freq) + balun_phase = balun_phase - np.mean(balun_phase) + balun_sdat = np.power(10,balun_gain/20)*np.exp(1j*balun_phase) - sdat = sdat_raw/buffer_sdat + sdat = sdat_raw/buffer_sdat/balun_sdat slope_valid_inds = np.where(np.all((freq >= slopeBandwidthFreq[0], freq <= slopeBandwidthFreq[1]),0)) @@ -213,17 +243,20 @@ for filename in os.listdir(source_directory): ax=h.add_subplot(1,1,1, projection='polar') else: h=pp.figure(figsize=(3.4*figScaleSize, 4.5*figScaleSize)) - h2=pp.figure(figsize=(3.4*figScaleSize, 2.8*figScaleSize)) + h2=pp.figure(figsize=(3.4*figScaleSize, 2.3*figScaleSize)) ax=h.subplots(2,1) ax = np.append(ax, h2.subplots(1,1)) ax = np.append(ax, ax[1].twinx()) ax = np.append(ax, ax[2].twinx()) + ax = np.append(ax, ax[0].twinx()) summary_msg = \ "/---------------------\/----------------------------------------\\\n"\ "| _C R I _Bias_ || Gain Phase Power |\n"\ "|---------------------||----------------------------------------|\n" all_sdat = np.column_stack([imeas.s21 for imeas in collectedData]) - ang_rms = delta_rms(np.angle(all_sdat), 2*np.pi/16)*180/np.pi + ang_rms = delta_rms(np.angle(all_sdat), 2*np.pi/args.c)*180/np.pi + gain_pm = gain_error(dB20(all_sdat), index_f0) + gain_rms = rms(dB20(all_sdat), index_f0) for imeas in collectedData: if args.polar: #ax.plot(ang(imeas.s21)-buffer_phase, dB20(imeas.s21)-buffer_gain) @@ -258,6 +291,7 @@ for filename in os.listdir(source_directory): "|===> RMS: %6.1f deg (%6.1f deg - %6.1f deg) | \n" \ "\_______________________________________________________________/" % \ (sumTuple_avgMinMax([pwr_list, gain_list, ang_rms])) + print(group_filename_string, sumTuple_avgMinMax([ang_rms])) if args.polar: ax.set_ylim(LPRDefaultPlotting.POLAR_YLIM_CONST_MEAS) @@ -269,9 +303,43 @@ for filename in os.listdir(source_directory): np.min([np.min(line.get_ydata()) for line in ax[2].get_lines()]) ax[0].set_title('Measured Performance') ax[0].set_ylabel('Gain (dB)') + ######### FIXME ######################################################## + #ax[0].set_ylim(np.array([-17.5, 2.5])) + ax[0].set_ylim(np.array([-20, 0])) ax[1].set_ylabel('Relative Phase (deg)') ax[2].set_ylabel('Relative Phase (deg)') ax[2].set_title('Relative Phase') + ax[1].set_ylim(np.array([-100, 360])) + ax[2].set_ylim(np.array([-100, 360])) + + marker_freq = 28.1 + LPRDefaultPlotting.annotateArrow(ax[0], -4, \ + [marker_freq+0.05+0.02, marker_freq+0.15+0.02], direction='left') + + for i in [5]: + aT=ax[i] + aR=ax[0] + #aT.plot(imeas.f, gain_pm) + aT.plot(imeas.f, gain_rms) + for axTLi,axTL in enumerate(aT.get_lines()): + axTL.set_linewidth(2.0) + axTL.set_color('black') + if axTLi == 0: + axTL.set_linestyle('-.') + else: + axTL.set_linestyle(':') + aT.set_ylabel('RMS Gain Variation (dB)') + + marker_freq = 27.7 + marker_point = np.argmin(np.abs(imeas.f-marker_freq)) + marker_height = gain_pm[marker_point] + marker_height = gain_rms[marker_point] + LPRDefaultPlotting.annotateArrow(aT, marker_height+0.5, \ + [marker_freq+0.05+0.02, marker_freq+0.15+0.02]) + aT.set_ylim(aR.get_ylim()/np.array(1)+20) + aT.grid() + ######### FIXME ######################################################## + for i in range(3,5): aT=ax[i] aR=ax[i-2] @@ -279,7 +347,8 @@ for filename in os.listdir(source_directory): # Recall that the ylimits should be 0-360 basically. aT.set_ylabel('RMS Error (deg)') aT.plot(imeas.f, ang_rms) - marker_freq = 27.5 + #marker_freq = 27.5 + marker_freq = 28.3 marker_point = np.argmin(np.abs(imeas.f-marker_freq)) marker_height = ang_rms[marker_point] @@ -301,19 +370,26 @@ for filename in os.listdir(source_directory): yXover = np.array([np.min(yRTover[:,0]), np.max(yRTover[:,1])]) aR.set_ylim(yRscl*yXover + yRmrks) aT.set_ylim(yTscl*yXover + yTmrks) - aT.set_ylim(aR.get_ylim()/np.array(50)+3) + #aT.set_ylim(aR.get_ylim()/np.array(20)+9) + aT.set_ylim((0,20)) aT.grid() aT.get_lines()[0].set_linewidth(2.0) aT.get_lines()[0].set_linestyle('-.') aT.get_lines()[0].set_color('black') - LPRDefaultPlotting.annotateArrow(aT, marker_height, \ - [marker_freq+0.05, marker_freq+0.25]) + LPRDefaultPlotting.annotateArrow(aT, marker_height-0.5, \ + [marker_freq+0.05, marker_freq+0.15]) + + ax[5].set_ylim(np.array([0, 20])) + #ax[3].set_ylim(np.array([0, 42])) + ax[3].set_ylim(np.array([0, 23])) + 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)) + #aT.set_xlim((28-1.0, 28+1.0)) + aT.set_xlim((28-0.5, 28+0.5)) if args.polar: old_pos = ax.title.get_position() diff --git a/runAll.sh b/runAll.sh index 54a149a..301476f 100755 --- a/runAll.sh +++ b/runAll.sh @@ -19,7 +19,7 @@ for n in 5 6; do echo " 止 end $n" ) & done -for n in 1 2 3 4 11 12 13 14; do +for n in 7 1 2 3 4 11 12 13 14; do while [[ $MAX_JOBS -le $(jobs -l | wc -l) ]]; do sleep 0.1; done ( echo " start $n →" diff --git a/runParse.sh b/runParse.sh index 301c582..9b989ed 100755 --- a/runParse.sh +++ b/runParse.sh @@ -2,19 +2,37 @@ MAX_JOBS=4 -for n in $(seq 1 4); do +#for n in $(seq 1 4); do +for n in 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 ) & + ( ./parsePy.py -rq -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 ) & + while [[ $MAX_JOBS -le $(jobs -l | wc -l) ]]; do sleep 0.1; done + ( ./parsePy.py -sq -n $n 1>/dev/null ) & done +if [[ 1 -eq 2 ]]; then + NC=32 + 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 -rpq -n $n -c "$NC" 1>/dev/null ) & + while [[ $MAX_JOBS -le $(jobs -l | wc -l) ]]; do sleep 0.1; done + ( ./parsePy.py -rq -n $n -c "$NC" 1>/dev/null ) & + while [[ $MAX_JOBS -le $(jobs -l | wc -l) ]]; do sleep 0.1; done + ( ./parsePy.py -spq -n $n -c "$NC" 1>/dev/null ) & + while [[ $MAX_JOBS -le $(jobs -l | wc -l) ]]; do sleep 0.1; done + ( ./parsePy.py -sq -n $n -c "$NC" 1>/dev/null ) & + done +fi + while [[ $(jobs -lr | wc -l) -gt 0 ]]; do sleep 0.1; done SELECT_STRING="S02bB_C+00dB" -rsync -aPv "figures-measured/"*"${SELECT_STRING}"* ../tex/figures-measured/ +cp -v "figures-measured/"*"${SELECT_STRING}"* ../tex/figures-measured/ +SELECT_STRING="S03bB_C+00dB" +cp -v "figures-measured-32/"*"${SELECT_STRING}"* ../tex/figures-measured-32/ diff --git a/runSome.sh b/runSome.sh new file mode 100755 index 0000000..216eb45 --- /dev/null +++ b/runSome.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +MAX_JOBS=4 + +for n in 2 12; do + while [[ $MAX_JOBS -le $(jobs -l | wc -l) ]]; do sleep 0.1; done + ( + echo " start $n →" + ./tankPlot.py -n $n --subplot -sq 1>/dev/null + ./tankPlot.py -n $n --subplot -rq 1>/dev/null + echo " 止 end $n" + ) & + while [[ $MAX_JOBS -le $(jobs -l | wc -l) ]]; do sleep 0.1; done + ( + echo " start $n →" + ./tankPlot.py -n $n -sq 1>/dev/null + ./tankPlot.py -n $n -rq 1>/dev/null + echo " 止 end $n" + ) & +done + +#bash ./runParse.sh & + +while [[ $(jobs -lr | wc -l) -gt 0 ]]; do sleep 0.1; done +#mkdir -p figures-png +#rm figures-png/*.png &>/dev/null +mv figures/*.png figures-png/ +echo "DONE!" diff --git a/tankComputers.py b/tankComputers.py index 190a249..6bee197 100644 --- a/tankComputers.py +++ b/tankComputers.py @@ -79,3 +79,22 @@ def delta_rms(signal, reference_delta, wrap_point=2*np.pi): signal_rms = np.sqrt(np.mean(np.power(signal_error,2),1)) return signal_rms + +def gain_error(signal, ref_freq_ind): + """compute the gain variation relative to a mean computed at ref_freq_ind""" + # First compute the matrix difference including folding + inband_gain = np.mean(signal[ref_freq_ind,:]) + signal_off = signal-inband_gain + range = np.max(signal_off,1)-np.min(signal_off,1) + + return range + +def rms(signal, ref_freq_ind=None): + """compute raw RMS""" + if ref_freq_ind == None: + offset_signal = signal-np.transpose(\ + np.ones((signal.shape[1],1))*np.mean(signal,1)\ + ) + else: + offset_signal = signal-np.mean(signal[ref_freq_ind,:]) + return np.sqrt(np.mean(np.power(offset_signal,2),1)) diff --git a/tankPlot.py b/tankPlot.py index 3a02b8f..ee5ad55 100755 --- a/tankPlot.py +++ b/tankPlot.py @@ -57,7 +57,7 @@ figScaleSize = 1.0 if args.save else 1.6 if args.subplot: rcParams['figure.figsize'] = [3.4*figScaleSize,4*figScaleSize] else: - rcParams['figure.figsize'] = [3.4*figScaleSize,2.25*figScaleSize] + rcParams['figure.figsize'] = [3.4*figScaleSize,2*figScaleSize] default_window_position=['+20+80', '+120+80'] ################################################################################ @@ -68,11 +68,12 @@ from tankComputers import * freq_pts = 501 S=TankGlobals.ampSystem() +#S.bw_plt=2 B=TankGlobals.bufferSystem() S.q1_L = 15 if plot_list[0] in [11, 12, 13, 14]: - gain_variation = +4 # dB + gain_variation = -2 # dB else: gain_variation = 0 # dB @@ -80,10 +81,11 @@ if plot_list[0] in [14, 4, 5]: S.bw_plt = 0.5 B.bw_plt = S.bw_plt freq_pts = 51 -if plot_list[0] == 5: +if plot_list[0] in [5, 7]: S.set_g1_swp(TankGlobals.g1_map_flat) S.set_gamma_swp(TankGlobals.gamma_map_flat) +S.bw_plt = 2; f=FreqClass(freq_pts, S.f0, S.bw_plt) ################################################################################ @@ -129,6 +131,11 @@ y_tank = y_tank.T # Compute RMS phase error relative to ideal reference across plotting bandwidth (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) +tf_ang_rms=delta_rms(tf_r_ang, 2*np.pi/16)*180/np.pi +index_f0 = np.squeeze(np.argwhere(f.hz==28)) +tf_gain_pm = gain_error(dB20(tf_r),index_f0) +tf_gain_rms = rms(dB20(tf_r), index_f0) + ################################################################################ ################################################################################ @@ -181,9 +188,9 @@ if 1 in plot_list or 11 in plot_list: ax1[0].plot(f.hz,dB20(tf)) ax1[1].plot(f.hz,ang_unwrap(tf)) - ax1[0].set_title('Stage Gain Response') + ax1[0].set_title('Enhanced Gain Response') ax1[0].set_ylabel('Gain (dB)') - ax1[1].set_title('Stage Phase Response') + ax1[1].set_title('Enhanced Phase Response') ax1[1].set_ylabel('Phase (deg)') for axT in ax1: @@ -191,6 +198,9 @@ if 1 in plot_list or 11 in plot_list: axT.set_xlabel('Freq (GHz)') axT.set_xlim(f.hz_range) + ax1[0].set_ylim(LPRDefaultPlotting.GAIN_FIXED_YLIM1) + + [hT.tight_layout() for hT in h1] if 11 in plot_list: for hT in h1: @@ -304,6 +314,49 @@ if 5 in plot_list: #mgr.window.geometry(default_window_position[0]) [hT.show() for hT in h5] +if 7 in plot_list: + if not args.subplot: + h1 = [pp.figure() for x in range(2)] + ax1 = [hT.add_subplot(1,1,1) for hT in h1] + else: + h1 = [pp.figure() for x in range(1)] + ax1 = h1[0].subplots(2,1) + + ax1[0].plot(f.hz,dB20(tf)) + ax1[1].plot(f.hz,ang_unwrap(tf)) + + ax1[0].set_title('Non-Enhanced Gain Response') + ax1[0].set_ylabel('Gain (dB)') + ax1[1].set_title('Non-Enhanced Phase Response') + ax1[1].set_ylabel('Phase (deg)') + ax1[0].set_ylim(LPRDefaultPlotting.GAIN_FIXED_YLIM2) + + for axT in ax1: + axT.grid() + axT.set_xlabel('Freq (GHz)') + axT.set_xlim(f.hz_range) + + [hT.tight_layout() for hT in h1] + if 11 in plot_list: + for hT in h1: + LPRDefaultPlotting.figAnnotateCorner(hT, + '%g dB gain variation' % (gain_variation)) + + if args.save: + if args.subplot: + h1[0].savefig('%s/%s.%s' % (figdir, + '07d-ideal-AbsGainPhase', fig_ext)) + else: + h1[0].savefig('%s/%s.%s' % (figdir, + '070-AbsGain', fig_ext)) + h1[1].savefig('%s/%s.%s' % (figdir, + '071-AbsPhase', fig_ext)) + if HEADLESS: + pp.close() + else: + #mgr.window.geometry(default_window_position[0]) + [hT.show() for hT in h1] + ################################################################################ if 2 in plot_list or 12 in plot_list: if not args.subplot: @@ -312,16 +365,51 @@ if 2 in plot_list or 12 in plot_list: else: h2 = [pp.figure() for x in range(1)] ax2 = h2[0].subplots(2,1) + ax2 = np.append(ax2, ax2[0].twinx()) + ax2 = np.append(ax2, ax2[1].twinx()) ax2[0].plot(f.hz,dB20(tf_r)) setLimitsTicks(ax2[0], dB20(tf_r), 6) + #ax2[2].plot(f.hz,tf_gain_pm) + ax2[2].plot(f.hz,tf_gain_rms) + ax2[1].plot(f.hz,ang_unwrap(tf_r.T).T) + ax2[3].plot(f.hz,tf_ang_rms) setLimitsTicks(ax2[1], ang_unwrap(tf_r.T), 6) ax2[0].set_title('Relative Gain') ax2[0].set_ylabel('Gain (dB)') + ax2[2].set_ylabel('RMS Gain Error (dB)') ax2[1].set_title('Relative Phase') ax2[1].set_ylabel('Phase (deg)') + ax2[3].set_ylabel('RMS Error (deg)') + for axT in ax2[[2,3]]: + for axTLi,axTL in enumerate(axT.get_lines()): + axTL.set_linewidth(2.0) + axTL.set_color('black') + if axTLi == 0: + axTL.set_linestyle('-.') + else: + axTL.set_linestyle(':') + axT.grid() + + ax2[0].set_ylim(LPRDefaultPlotting.GAIN_FIXED_YLIM3) + ax2[2].set_ylim(LPRDefaultPlotting.GAIN_FIXED_YLIM4) + + ax2[2].set_ylim(ax2[0].get_ylim()/np.array(1)+4) + ax2[3].set_ylim((0,20)) + + marker_freq = 28.2 + marker_point = np.argmin(np.abs(f.hz-marker_freq)) + marker_height = tf_gain_pm[marker_point] + LPRDefaultPlotting.annotateArrow(ax2[2], marker_height, \ + [marker_freq+0.05, marker_freq+0.25]) + + marker_freq = 28.39 + marker_point = np.argmin(np.abs(f.hz-marker_freq)) + marker_height = tf_ang_rms[marker_point] + LPRDefaultPlotting.annotateArrow(ax2[3], marker_height, \ + [marker_freq+0.05, marker_freq+0.25]) for axT in ax2: axT.grid()