def _get_distribution_parameters(x, y, z, px, py, pz, q, n_slices, len_slice): a_x, b_x, g_x = bd.twiss_parameters(x, px, pz, py, w=q) a_y, b_y, g_y = bd.twiss_parameters(y, py, pz, px, w=q) ene = bd.mean_energy(px, py, pz, w=q) ene_sp = bd.relative_rms_energy_spread(px, py, pz, w=q) ene_sp_slice_params = bd.relative_rms_slice_energy_spread( z, px, py, pz, w=q, n_slices=n_slices, len_slice=len_slice) ene_sp_sl, sl_w, sl_e, ene_sp_sl_avg = ene_sp_slice_params em_x = bd.normalized_transverse_rms_emittance(x, px, py, pz, w=q) em_y = bd.normalized_transverse_rms_emittance(y, py, px, pz, w=q) emitt_x_slice_params = bd.normalized_transverse_rms_slice_emittance( z, x, px, py, pz, w=q, n_slices=n_slices, len_slice=len_slice) em_x_sl, sl_w, sl_e, em_x_sl_avg = emitt_x_slice_params emitt_y_slice_params = bd.normalized_transverse_rms_slice_emittance( z, y, py, px, pz, w=q, n_slices=n_slices, len_slice=len_slice) em_y_sl, sl_w, sl_e, em_y_sl_avg = emitt_y_slice_params s_z = bd.rms_length(z, w=q) s_x = bd.rms_size(x, w=q) s_y = bd.rms_size(y, w=q) x_avg = np.average(x, weights=q) y_avg = np.average(y, weights=q) px_avg = np.average(px, weights=q) py_avg = np.average(py, weights=q) theta_x = px_avg / ene theta_y = py_avg / ene i_peak = bd.peak_current(z, q, n_slices=n_slices, len_slice=len_slice) return (theta_x, theta_y, x_avg, y_avg, s_x, s_y, a_x, a_y, b_x, b_y, g_x, g_y, em_x, em_y, em_x_sl_avg, em_y_sl_avg, ene, ene_sp, ene_sp_sl_avg, i_peak, s_z)
def phase_space_overview(x, y, z, px, py, pz, q): em_x = bd.normalized_transverse_rms_emittance(x, px, w=q) * 1e6 em_y = bd.normalized_transverse_rms_emittance(y, py, w=q) * 1e6 a_x, b_x, g_x = bd.twiss_parameters(x, px, pz, w=q) a_y, b_y, g_y = bd.twiss_parameters(y, py, pz, w=q) s_x = bd.rms_size(x, w=q) s_y = bd.rms_size(y, w=q) em_l = bd.longitudinal_rms_emittance(z, px, py, pz, w=q) * 1e6 dz = z - np.average(z, weights=q) s_z = bd.rms_length(z, w=q) s_g = bd.relative_rms_energy_spread(pz, py, pz, w=q) s_g_sl, w_sl, sl_ed, s_g_sl_av = bd.relative_rms_slice_energy_spread( z, px, py, pz, w=q, n_slices=10) c_prof, _ = bd.current_profile(z, q, n_slices=50) c_peak = max(abs(c_prof))/1e3 # kA # s_g_sl_c = s_g_sl[int(len(s_g_sl)/2)] # make plot plt.figure(figsize=(8, 3)) with plt.rc_context(aptools_rc_params): # x - px ax_1 = plt.subplot(131) scatter_histogram(x*1e6, px) plt.xlabel("x [$\\mu m$]") plt.ylabel("$p_x \\ \\mathrm{[m_ec^2/e]}$") plt.text(0.1, 0.9, '$\\epsilon_{n,x} = $' + '{}'.format(np.around(em_x, 3)) + '$\\ \\mathrm{\\pi \\ \\mu m \\ rad}$', transform=ax_1.transAxes, fontsize=8) plt.text(0.1, 0.8, '$\\beta_{x} = $' + '{}'.format(np.around(b_x, 3)) + 'm', transform=ax_1.transAxes, fontsize=8) plt.text(0.1, 0.7, '$\\alpha_{x} = $' + '{}'.format(np.around(a_x, 3)), transform=ax_1.transAxes, fontsize=8) plt.text(0.1, 0.6, '$\\sigma_{x} = $' + '{}'.format(np.around(s_x*1e6, 3)) + '$\\ \\mathrm{\\mu m}$', transform=ax_1.transAxes, fontsize=8) # y - py ax_2 = plt.subplot(132) scatter_histogram(y * 1e6, py) plt.xlabel("y [$\\mu m$]") plt.ylabel("$p_y \\ \\mathrm{[m_ec^2/e]}$") plt.text(0.1, 0.9, '$\\epsilon_{n,y} = $' + '{}'.format(np.around(em_y, 3)) + '$\\ \\mathrm{\\pi \\ \\mu m \\ rad}$', transform=ax_2.transAxes, fontsize=8) plt.text(0.1, 0.8, '$\\beta_{y} = $' + '{}'.format(np.around(b_y, 3)) + 'm', transform=ax_2.transAxes, fontsize=8) plt.text(0.1, 0.7, '$\\alpha_{y} = $' + '{}'.format(np.around(a_y, 3)), transform=ax_2.transAxes, fontsize=8) plt.text(0.1, 0.6, '$\\sigma_{y} = $' + '{}'.format(np.around(s_y*1e6, 3)) + '$\\ \\mathrm{\\mu m}$', transform=ax_2.transAxes, fontsize=8) # z - pz ax_3 = plt.subplot(133) scatter_histogram(dz / ct.c * 1e15, pz) plt.xlabel("$\\Delta z$ [fs]") plt.ylabel("$p_z \\ \\mathrm{[m_ec^2/e]}$") plt.text(0.1, 0.9, '$\\epsilon_{L} = $' + '{}'.format(np.around(em_l, 3)) + '$\\ \\mathrm{\\pi \\ \\mu m}$', transform=ax_3.transAxes, fontsize=8) plt.text(0.1, 0.8, '$\\sigma_\\gamma/\\gamma=$' + '{}'.format(np.around(s_g*1e2, 3)) + '$\\%$', transform=ax_3.transAxes, fontsize=8) plt.text(0.1, 0.7, '$\\sigma^s_\\gamma/\\gamma=$' + '{}'.format(np.around(s_g_sl_av*1e2, 3)) + '$\\%$', transform=ax_3.transAxes, fontsize=8) plt.text(0.1, 0.6, '$\\sigma_z=$' + '{}'.format(np.around(s_z/ct.c*1e15, 3)) + ' fs', transform=ax_3.transAxes, fontsize=8) plt.text(0.1, 0.5, '$I_{peak}=$' + '{}'.format(np.around(c_peak, 2)) + ' kA', transform=ax_3.transAxes, fontsize=8) plt.tight_layout() plt.show()
def slice_analysis(x, y, z, px, py, pz, q, n_slices=50, len_slice=None, ene_bins=50, left=0.125, right=0.875, top=0.98, bottom=0.13, add_labels=False, include_twiss=False, fig=None, rasterized_scatter=None, show=True): # analyze beam current_prof, z_edges = bd.current_profile(z, q, n_slices=n_slices, len_slice=len_slice) ene_spectrum, ene_spec_edgs = bd.energy_spectrum(px, py, pz, w=q, bins=ene_bins) slice_ene, *_ = bd.energy_profile( z, px, py, pz, w=q, n_slices=n_slices, len_slice=len_slice) slice_ene_sp, *_ = bd.relative_rms_slice_energy_spread( z, px, py, pz, w=q, n_slices=n_slices, len_slice=len_slice) sl_tw, sl_w, *_ = bd.slice_twiss_parameters( z, x, px, pz, w=q, n_slices=n_slices, len_slice=len_slice) alpha_x, *_ = get_only_statistically_relevant_slices( sl_tw[0], sl_w, replace_with_nans=True) beta_x, *_ = get_only_statistically_relevant_slices( sl_tw[1], sl_w, replace_with_nans=True) sl_tw, *_ = bd.slice_twiss_parameters( z, y, py, pz, w=q, n_slices=n_slices, len_slice=len_slice) alpha_y, *_ = get_only_statistically_relevant_slices( sl_tw[0], sl_w, replace_with_nans=True) beta_y, *_ = get_only_statistically_relevant_slices( sl_tw[1], sl_w, replace_with_nans=True) slice_em_x, *_ = bd.normalized_transverse_rms_slice_emittance( z, x, px, w=q, n_slices=n_slices, len_slice=len_slice) slice_em_y, *_ = bd.normalized_transverse_rms_slice_emittance( z, y, py, w=q, n_slices=n_slices, len_slice=len_slice) s_z = bd.rms_length(z, w=q) len_fwhm = bd.fwhm_length(z, q, n_slices=n_slices, len_slice=len_slice) ene_sp_tot = bd.relative_rms_energy_spread(px, py, pz, w=q) # perform operations gamma = np.sqrt(1 + px**2 + py**2 + pz**2) ene = gamma * ct.m_e*ct.c**2/ct.e * 1e-9 # GeV z_center = np.average(z, weights=q) dz = z_edges[1] - z_edges[0] slice_z = (z_edges[1:] - dz/2 - z_center) * 1e6 # micron current_prof = np.abs(current_prof) * 1e-3 # kA peak_current = np.nanmax(current_prof) s_t = s_z * 1e15/ct.c len_fwhm *= 1e15/ct.c # fs slice_ene *= ct.m_e*ct.c**2/ct.e * 1e-9 # GeV ene_spec_edgs = ene_spec_edgs[:-1] + (ene_spec_edgs[1]-ene_spec_edgs[0])/2 ene_spec_edgs *= ct.m_e*ct.c**2/ct.e * 1e-9 # GeV slice_ene_sp *= 1e2 # % ene_sp_tot *= 1e2 # % slice_em_x *= 1e6 # micron slice_em_y *= 1e6 # micron max_beta = np.nanmax(beta_x) if max_beta <= 0.1: beta_units = 'mm' beta_x *= 1e3 beta_y *= 1e3 else: beta_units = 'm' max_ene = np.nanmax(ene) if max_ene <= 1: ene_units = 'MeV' ene *= 1e3 ene_spec_edgs *= 1e3 else: ene_units = 'GeV' ene_mean = np.average(ene, weights=q) # make plot if include_twiss: nrows = 3 hr = [2.5, 1, 1] fh = 3.3 else: nrows = 2 hr = [2.5, 1] fh = 2.5 if fig is None: fig = plt.figure(figsize=(4, fh)) gs = gridspec.GridSpec(nrows, 2, height_ratios=hr, width_ratios=[1, 0.02], hspace=0.1, wspace=0.05, figure=fig, left=left, right=right, top=top, bottom=bottom) leg_frac = 0.25 # space to reserve for legend with plt.rc_context(aptools_rc_params): ax_or = plt.subplot(gs[0]) pscatt = scatter_histogram((z-z_center)*1e6, ene, bins=300, weights=np.abs(q)*1e15, rasterized=rasterized_scatter) plt.ylabel('Energy [{}]'.format(ene_units)) plt.tick_params(axis='x', which='both', labelbottom=False) params_text = ('$\\langle E \\rangle = ' + '{:0.1f}$ {}\n'.format(ene_mean, ene_units) + '$\\sigma_\\mathrm{E,rel}=' + '{:0.1f}$ %\n'.format(ene_sp_tot) + '$I_\\mathrm{peak}=' + '{:0.1f}$ kA\n'.format(peak_current) + '$\\sigma_t=' + '{:0.1f}$ fs'.format(s_t)) plt.text(0.98, 0.95, params_text, transform=ax_or.transAxes, fontsize=6, horizontalalignment='right', verticalalignment='top') if add_labels: plt.text(0.03, 0.05, '(a)', transform=ax_or.transAxes, fontsize=6, horizontalalignment='left', verticalalignment='bottom') xlim = list(plt.xlim()) xlim[0] -= (xlim[1] - xlim[0])/8 xlim[1] += (xlim[1] - xlim[0])/3 plt.xlim(xlim) ylim = list(plt.ylim()) ylim[0] -= (ylim[1] - ylim[0])/3 plt.ylim(ylim) # current profile plot z_or = ax_or.get_zorder() pos = list(ax_or.get_position().bounds) pos[3] /= 5 ax_or.patch.set_alpha(0) ax = fig.add_axes(pos) ax.set_zorder(z_or-1) plt.plot(slice_z, current_prof, c='k', lw=0.5, alpha=0.5) plt.fill_between(slice_z, current_prof, facecolor='tab:gray', alpha=0.3) ax.spines['left'].set_position('zero') ax.spines['left'].set_color('tab:grey') ax.tick_params(axis='y', colors='tab:grey', labelsize=6, direction="in", pad=-4) ax.spines['right'].set_color('none') ax.spines['top'].set_color('none') ax.yaxis.set_ticks_position('left') ax.xaxis.set_ticks_position('bottom') plt.tick_params(axis='x', which='both', labelbottom=False) for label in ax.yaxis.get_ticklabels(): label.set_horizontalalignment('left') label.set_verticalalignment('bottom') plt.xlim(xlim) ylim_c = list(plt.ylim()) ylim_c[0] = 0 plt.ylim(ylim_c) plt.ylabel('I [kA]', color='tab:gray', fontsize=6) # energy profile plot pos = list(ax_or.get_position().bounds) pos[2] /= 8 ax = fig.add_axes(pos) ax.set_zorder(z_or-1) plt.plot(ene_spectrum, ene_spec_edgs, c='k', lw=0.5, alpha=0.5) plt.fill_betweenx(ene_spec_edgs, ene_spectrum, facecolor='tab:gray', alpha=0.3) plt.gca().axis('off') plt.ylim(ylim) xlim_e = list(plt.xlim()) xlim_e[0] = 0 plt.xlim(xlim_e) # colorbar ax = plt.subplot(gs[1]) matplotlib.colorbar.Colorbar(ax, pscatt, label='Q [fC]') # slice parameters plot plt.subplot(gs[2]) l1 = plt.plot(slice_z, slice_ene_sp, lw=1, c='tab:green', label='$\\sigma_\\gamma/\\gamma$') plt.ylabel('$\\sigma_\\gamma/\\gamma$ [%]') if include_twiss: plt.tick_params(axis='x', which='both', labelbottom=False) else: plt.xlabel('$\\Delta z \\ [\\mathrm{\\mu m}]$') # make room for legend # ylim = list(plt.ylim()) # ylim[1] += (ylim[1] - ylim[0]) * leg_frac plt.xlim(xlim) # plt.ylim(ylim) ax = plt.twinx() l2 = plt.plot(slice_z, slice_em_x, lw=1, c='tab:blue', label='$\\epsilon_{n,x}$') l3 = plt.plot(slice_z, slice_em_y, lw=1, c='tab:orange', label='$\\epsilon_{n,y}$') plt.ylabel('$\\epsilon_{n} \\ [\\mathrm{\\mu m}]$') # make room for legend # ylim = list(plt.ylim()) # ylim[1] += (ylim[1] - ylim[0]) * leg_frac # plt.ylim(ylim) lines = l1 + l2 + l3 labels = [line.get_label() for line in lines] plt.legend(lines, labels, fontsize=6, frameon=False, loc='center right', borderaxespad=0.3) if add_labels: plt.text(0.03, 0.05, '(b)', transform=plt.gca().transAxes, fontsize=6, horizontalalignment='left', verticalalignment='bottom') if include_twiss: plt.subplot(gs[4]) l1 = plt.plot(slice_z, beta_x, lw=1, c='tab:blue', label='$\\beta_x$') l2 = plt.plot(slice_z, beta_y, lw=1, c='tab:orange', label='$\\beta_y$') plt.xlabel('$\\Delta z \\ [\\mathrm{\\mu m}]$') plt.ylabel('$\\beta$ [{}]'.format(beta_units)) # make room for legend ylim = list(plt.ylim()) ylim[1] += (ylim[1] - ylim[0]) * leg_frac plt.ylim(ylim) plt.xlim(xlim) plt.twinx() l3 = plt.plot(slice_z, alpha_x, lw=1, c='tab:blue', ls='--', label='$\\alpha_x$') l4 = plt.plot(slice_z, alpha_y, lw=1, c='tab:orange', ls='--', label='$\\alpha_y$') lines = l1 + l2 + l3 + l4 labels = [line.get_label() for line in lines] # make room for legend # ylim = list(plt.ylim()) # ylim[1] += (ylim[1] - ylim[0]) * leg_frac # plt.ylim(ylim) plt.legend(lines, labels, fontsize=6, ncol=1, frameon=False, loc='center right', borderaxespad=0.3, labelspacing=0.20) if add_labels: plt.text(0.03, 0.05, '(c)', transform=plt.gca().transAxes, fontsize=6, horizontalalignment='left', verticalalignment='bottom') plt.ylabel('$\\alpha$') if show: plt.show()
def analyze_data(beam_list): print("Running data analysis... ") l = len(beam_list) x_part = np.zeros(l) g_part = np.zeros(l) px_part = np.zeros(l) a_x = np.zeros(l) a_y = np.zeros(l) b_x = np.zeros(l) b_y = np.zeros(l) g_x = np.zeros(l) g_y = np.zeros(l) ene = np.zeros(l) dist = np.zeros(l) chirp = np.zeros(l) ene_sp = np.zeros(l) ene_sp_sl = np.zeros(l) emitt = np.zeros(l) em_x = np.zeros(l) em_y = np.zeros(l) em_sl_x = np.zeros(l) em_sl_y = np.zeros(l) emitt_3 = np.zeros(l) dx = np.zeros(l) sx = np.zeros(l) sy = np.zeros(l) x_centroid = np.zeros(l) y_centroid = np.zeros(l) px_centroid = np.zeros(l) py_centroid = np.zeros(l) disp_x = np.zeros(l) sz = np.zeros(l) for i, beam in enumerate(beam_list): dist[i] = beam.prop_distance a_x[i], b_x[i], g_x[i] = bd.twiss_parameters(beam.x, beam.px, beam.pz, beam.py, w=beam.q) a_y[i], b_y[i], g_y[i] = bd.twiss_parameters(beam.y, beam.py, beam.pz, beam.px, w=beam.q) ene[i] = bd.mean_energy(beam.px, beam.py, beam.pz, w=beam.q) ene_sp[i] = bd.relative_rms_energy_spread(beam.px, beam.py, beam.pz, w=beam.q) enespls, sl_w, _ = bd.relative_rms_slice_energy_spread( beam.xi, beam.px, beam.py, beam.pz, w=beam.q, len_slice=0.1e-6) ene_sp_sl[i] = np.average(enespls, weights=sl_w) em_x[i] = bd.normalized_transverse_rms_emittance(beam.x, beam.px, beam.py, beam.pz, w=beam.q) em_y[i] = bd.normalized_transverse_rms_emittance(beam.y, beam.py, beam.px, beam.pz, w=beam.q) emsx, sl_w, _ = bd.normalized_transverse_rms_slice_emittance( beam.xi, beam.x, beam.px, beam.py, beam.pz, w=beam.q, len_slice=0.1e-6) em_sl_x[i] = np.average(emsx, weights=sl_w) emsy, sl_w, _ = bd.normalized_transverse_rms_slice_emittance( beam.xi, beam.y, beam.py, beam.px, beam.pz, w=beam.q, len_slice=0.1e-6) em_sl_y[i] = np.average(emsy, weights=sl_w) sz[i] = bd.rms_length(beam.xi, w=beam.q) sx[i] = bd.rms_size(beam.x, w=beam.q) sy[i] = bd.rms_size(beam.y, w=beam.q) x_centroid[i] = np.average(beam.x, weights=beam.q) y_centroid[i] = np.average(beam.y, weights=beam.q) px_centroid[i] = np.average(beam.px, weights=beam.q) py_centroid[i] = np.average(beam.py, weights=beam.q) disp_x[i] = bd.dispersion(beam.x, beam.px, beam.pz, beam.py, w=beam.q) plt.figure(1) plt.subplot(341) plt.semilogy(dist * 1e3, b_x * 1e3) plt.semilogy(dist * 1e3, b_y * 1e3) plt.xlabel("z [mm]") plt.ylabel("$\\beta_x$ [mm]") plt.subplot(342) plt.plot(dist * 1e3, a_x) plt.plot(dist * 1e3, a_y) plt.xlabel("z [mm]") plt.ylabel("$\\alpha_x$") plt.subplot(343) plt.plot(dist * 1e3, g_x) plt.plot(dist * 1e3, g_y) plt.xlabel("z [mm]") plt.ylabel("$\\gamma_x$") plt.subplot(344) plt.plot(dist * 1e3, ene) plt.xlabel("z [mm]") plt.ylabel("$\\gamma$") plt.subplot(345) plt.semilogy(dist * 1e3, ene_sp * 100) plt.semilogy(dist * 1e3, ene_sp_sl * 100) plt.xlabel("z [mm]") plt.ylabel("$\\frac{\\Delta \\gamma_z}{\\gamma}$ [%]") plt.subplot(346) plt.plot(dist * 1e3, em_x * 1e6) plt.plot(dist * 1e3, em_y * 1e6) plt.xlabel("z [mm]") plt.ylabel("$\\epsilon_{nx}$ [$\\mu$m]") plt.subplot(347) plt.plot(dist * 1e3, sx * 1e6) plt.plot(dist * 1e3, sy * 1e6) plt.xlabel("z [mm]") plt.ylabel("$\\sigma_{x,y}$ [$\\mu$m]") plt.subplot(348) plt.plot(dist * 1e3, sz / ct.c * 1e15) plt.xlabel("z [mm]") plt.ylabel("$\\sigma_z$ [fs]") plt.subplot(349) plt.plot(dist * 1e3, x_centroid * 1e6) plt.plot(dist * 1e3, y_centroid * 1e6) plt.xlabel("z [mm]") plt.ylabel("bunch centroid [$\\mu m$]") plt.subplot(3, 4, 10) plt.plot(dist * 1e3, px_centroid / ene * 1e6) plt.plot(dist * 1e3, py_centroid / ene * 1e6) plt.xlabel("z [mm]") plt.ylabel("pointing angle [$\\mu rad$]") plt.subplot(3, 4, 11) plt.plot(dist * 1e3, disp_x) plt.xlabel("z [mm]") plt.ylabel("$D_x$ [m]") plt.tight_layout() plt.show()
def lon_phase_space(x, y, z, px, py, pz, q, n_slices=50, len_slice=None, ene_bins=50, xlim=None, ylim=None, show_text=True, x_proj=True, y_proj=True, cbar=True, left=0.125, right=0.875, top=0.98, bottom=0.13, fig=None, rasterized_scatter=None, show=True): # analyze beam current_prof, z_edges = bd.current_profile(z, q, n_slices=n_slices, len_slice=len_slice) ene_spectrum, ene_spec_edgs = bd.energy_spectrum(px, py, pz, w=q, bins=ene_bins) s_z = bd.rms_length(z, w=q) len_fwhm = bd.fwhm_length(z, q, n_slices=n_slices, len_slice=len_slice) ene_sp_tot = bd.relative_rms_energy_spread(px, py, pz, w=q) # perform operations gamma = np.sqrt(1 + px**2 + py**2 + pz**2) ene = gamma * ct.m_e * ct.c**2 / ct.e * 1e-9 # GeV z_center = np.average(z, weights=q) dz = z_edges[1] - z_edges[0] slice_z = (z_edges[1:] - dz / 2 - z_center) * 1e6 # micron current_prof = np.abs(current_prof) * 1e-3 # kA peak_current = np.nanmax(current_prof) s_t = s_z * 1e15 / ct.c len_fwhm *= 1e15 / ct.c # fs ene_spec_edgs = ene_spec_edgs[:-1] + (ene_spec_edgs[1] - ene_spec_edgs[0]) / 2 ene_spec_edgs *= ct.m_e * ct.c**2 / ct.e * 1e-9 # GeV ene_sp_tot *= 1e2 # % max_ene = np.nanmax(ene) if max_ene <= 1: ene_units = 'MeV' ene *= 1e3 ene_spec_edgs *= 1e3 else: ene_units = 'GeV' ene_mean = np.average(ene, weights=q) # make plot if fig is None: fig = plt.figure(figsize=(4, 2.5)) if cbar: gs = gridspec.GridSpec(1, 2, width_ratios=[1, 0.02], hspace=0.1, wspace=0.05, figure=fig, left=left, right=right, top=top, bottom=bottom) else: gs = gridspec.GridSpec(1, 1, figure=fig, left=left, right=right, top=top, bottom=bottom) with plt.rc_context(aptools_rc_params): ax_or = plt.subplot(gs[0]) pscatt = scatter_histogram((z - z_center) * 1e6, ene, bins=300, weights=np.abs(q) * 1e15, rasterized=rasterized_scatter) plt.xlabel('$\\Delta z \\ [\\mathrm{\\mu m}]$') plt.ylabel('Energy [{}]'.format(ene_units)) if show_text: params_text = ('$\\langle E \\rangle = ' + '{:0.1f}$ {}\n'.format(ene_mean, ene_units) + '$\\sigma_\\mathrm{E,rel}=' + '{:0.1f}$ %\n'.format(ene_sp_tot) + '$I_\\mathrm{peak}=' + '{:0.1f}$ kA\n'.format(peak_current) + '$\\sigma_t=' + '{:0.1f}$ fs'.format(s_t)) plt.text(0.98, 0.95, params_text, transform=ax_or.transAxes, fontsize=6, horizontalalignment='right', verticalalignment='top') if xlim is not None: plt.xlim(xlim) else: xlim = list(plt.xlim()) if y_proj: xlim[0] -= (xlim[1] - xlim[0]) / 8 if show_text: xlim[1] += (xlim[1] - xlim[0]) / 3 plt.xlim(xlim) if ylim is not None: plt.ylim(ylim) else: ylim = list(plt.ylim()) if x_proj: ylim[0] -= (ylim[1] - ylim[0]) / 3 plt.ylim(ylim) # current profile plot if x_proj: z_or = ax_or.get_zorder() pos = list(ax_or.get_position().bounds) pos[3] /= 5 ax_or.patch.set_alpha(0) ax = fig.add_axes(pos) ax.set_zorder(z_or - 1) plt.plot(slice_z, current_prof, c='k', lw=0.5, alpha=0.5) plt.fill_between(slice_z, current_prof, facecolor='tab:gray', alpha=0.3) ax.spines['left'].set_position('zero') ax.spines['left'].set_color('tab:grey') ax.tick_params(axis='y', colors='tab:grey', labelsize=6, direction="in", pad=-4) ax.spines['right'].set_color('none') ax.spines['top'].set_color('none') ax.yaxis.set_ticks_position('left') ax.xaxis.set_ticks_position('bottom') plt.tick_params(axis='x', which='both', labelbottom=False) for label in ax.yaxis.get_ticklabels(): label.set_horizontalalignment('left') label.set_verticalalignment('bottom') plt.xlim(xlim) ylim_c = list(plt.ylim()) ylim_c[0] = 0 plt.ylim(ylim_c) plt.ylabel('I [kA]', color='tab:gray', fontsize=6) # energy profile plot if y_proj: z_or = ax_or.get_zorder() pos = list(ax_or.get_position().bounds) pos[2] /= 8 ax_or.patch.set_alpha(0) ax = fig.add_axes(pos) ax.set_zorder(z_or - 1) plt.plot(ene_spectrum, ene_spec_edgs, c='k', lw=0.5, alpha=0.5) plt.fill_betweenx(ene_spec_edgs, ene_spectrum, facecolor='tab:gray', alpha=0.3) plt.gca().axis('off') plt.ylim(ylim) xlim_e = list(plt.xlim()) xlim_e[0] = 0 plt.xlim(xlim_e) # colorbar if cbar: ax = plt.subplot(gs[1]) matplotlib.colorbar.Colorbar(ax, pscatt, label='Q [fC]') if show: plt.show()