diff --git a/pysmurf/debug/smurf_noise.py b/pysmurf/debug/smurf_noise.py index cda1681fa..5c9ebbd9c 100644 --- a/pysmurf/debug/smurf_noise.py +++ b/pysmurf/debug/smurf_noise.py @@ -22,7 +22,6 @@ from pysmurf.util import tools import matplotlib.pyplot as plt from matplotlib.gridspec import GridSpec -import seaborn as sns class SmurfNoiseMixin(SmurfBase): @@ -1531,6 +1530,7 @@ def plot_svd_summary(self, u, s, save_plot=False, fig, ax = plt.subplots(1, 2, figsize=(10,5)) # heatmap of coefficients + import seaborn as sns n_det, _ = np.shape(u) n_tick = 10 tick = n_det//n_tick diff --git a/pysmurf/tune/smurf_tune.py b/pysmurf/tune/smurf_tune.py index b0b9341e3..ff7dde03d 100644 --- a/pysmurf/tune/smurf_tune.py +++ b/pysmurf/tune/smurf_tune.py @@ -388,7 +388,8 @@ def tune_band_serial(self, band, n_samples=2**19, self.log('Done with serial tuning') def plot_tune_summary(self, band, eta_scan=False, show_plot=False, - save_plot=True, eta_width=.3): + save_plot=True, eta_width=.3, channels=None, + plot_summary=True): """ Plots summary of tuning. Requires self.freq_resp to be filled. In other words, you must run find_freq and setup_notches @@ -408,6 +409,9 @@ def plot_tune_summary(self, band, eta_scan=False, show_plot=False, show_plot (bool) : Whether to display the plot. Default is False. save_plot (bool) : Whether to save the plot. Default is True. eta_width (float) : The width to plot in MHz. + channels (int list) : Which channels to plot. Default is None, + which plots all available channels. + plot_summary (bool) : Plot summary. """ if show_plot: plt.ion() @@ -416,60 +420,61 @@ def plot_tune_summary(self, band, eta_scan=False, show_plot=False, timestamp = self.get_timestamp() - fig, ax = plt.subplots(2,2, figsize=(10,6)) - - # Subband - sb = self.get_eta_scan_result_subband(band) - ch = self.get_eta_scan_result_channel(band) - idx = np.where(ch!=-1) # ignore unassigned channels - sb = sb[idx] - c = Counter(sb) - y = np.array([c[i] for i in np.arange(128)]) - ax[0,0].plot(np.arange(128), y, '.', color='k') - for i in np.arange(0, 128, 16): - ax[0,0].axvspan(i-.5, i+7.5, color='k', alpha=.2) - ax[0,0].set_ylim((-.2, np.max(y)+1.2)) - ax[0,0].set_yticks(np.arange(0,np.max(y)+.1)) - ax[0,0].set_xlim((0, 128)) - ax[0,0].set_xlabel('Subband') - ax[0,0].set_ylabel('# Res') - ax[0,0].text(.02, .92, 'Total: {}'.format(len(sb)), - fontsize=10, transform=ax[0,0].transAxes) - - # Eta stuff - eta = self.get_eta_scan_result_eta(band) - eta = eta[idx] - f = self.get_eta_scan_result_freq(band) - f = f[idx] - - ax[0,1].plot(f, np.real(eta), '.', label='Real') - ax[0,1].plot(f, np.imag(eta), '.', label='Imag') - ax[0,1].plot(f, np.abs(eta), '.', label='Abs', color='k') - ax[0,1].legend(loc='lower right') - bc = self.get_band_center_mhz(band) - ax[0,1].set_xlim((bc-250, bc+250)) - ax[0,1].set_xlabel('Freq [MHz]') - ax[0,1].set_ylabel('Eta') - - phase = np.rad2deg(np.angle(eta)) - ax[1,1].plot(f, phase, color='k') - ax[1,1].set_xlim((bc-250, bc+250)) - ax[1,1].set_ylim((-180,180)) - ax[1,1].set_yticks(np.arange(-180, 180.1, 90)) - ax[1,1].set_xlabel('Freq [MHz]') - ax[1,1].set_ylabel('Eta phase') - - fig.suptitle('Band {} {}'.format(band, timestamp)) - plt.subplots_adjust(left=.08, right=.95, top=.92, bottom=.08, - wspace=.21, hspace=.21) + if plot_summary: + fig, ax = plt.subplots(2,2, figsize=(10,6)) + + # Subband + sb = self.get_eta_scan_result_subband(band) + ch = self.get_eta_scan_result_channel(band) + idx = np.where(ch!=-1) # ignore unassigned channels + sb = sb[idx] + c = Counter(sb) + y = np.array([c[i] for i in np.arange(128)]) + ax[0,0].plot(np.arange(128), y, '.', color='k') + for i in np.arange(0, 128, 16): + ax[0,0].axvspan(i-.5, i+7.5, color='k', alpha=.2) + ax[0,0].set_ylim((-.2, np.max(y)+1.2)) + ax[0,0].set_yticks(np.arange(0,np.max(y)+.1)) + ax[0,0].set_xlim((0, 128)) + ax[0,0].set_xlabel('Subband') + ax[0,0].set_ylabel('# Res') + ax[0,0].text(.02, .92, 'Total: {}'.format(len(sb)), + fontsize=10, transform=ax[0,0].transAxes) + + # Eta stuff + eta = self.get_eta_scan_result_eta(band) + eta = eta[idx] + f = self.get_eta_scan_result_freq(band) + f = f[idx] - if save_plot: - save_name = '{}_tune_summary.png'.format(timestamp) - path = os.path.join(self.plot_dir, save_name) - plt.savefig(path, bbox_inches='tight') - self.pub.register_file(path, 'tune', plot=True) - if not show_plot: - plt.close() + ax[0,1].plot(f, np.real(eta), '.', label='Real') + ax[0,1].plot(f, np.imag(eta), '.', label='Imag') + ax[0,1].plot(f, np.abs(eta), '.', label='Abs', color='k') + ax[0,1].legend(loc='lower right') + bc = self.get_band_center_mhz(band) + ax[0,1].set_xlim((bc-250, bc+250)) + ax[0,1].set_xlabel('Freq [MHz]') + ax[0,1].set_ylabel('Eta') + + phase = np.rad2deg(np.angle(eta)) + ax[1,1].plot(f, phase, color='k') + ax[1,1].set_xlim((bc-250, bc+250)) + ax[1,1].set_ylim((-180,180)) + ax[1,1].set_yticks(np.arange(-180, 180.1, 90)) + ax[1,1].set_xlabel('Freq [MHz]') + ax[1,1].set_ylabel('Eta phase') + + fig.suptitle('Band {} {}'.format(band, timestamp)) + plt.subplots_adjust(left=.08, right=.95, top=.92, bottom=.08, + wspace=.21, hspace=.21) + + if save_plot: + save_name = '{}_tune_summary.png'.format(timestamp) + path = os.path.join(self.plot_dir, save_name) + plt.savefig(path, bbox_inches='tight') + self.pub.register_file(path, 'tune', plot=True) + if not show_plot: + plt.close() # Plot individual eta scan if eta_scan: @@ -480,28 +485,43 @@ def plot_tune_summary(self, band, eta_scan=False, show_plot=False, freq = self.freq_resp[band]['full_band_resp']['freq'] resp = self.freq_resp[band]['full_band_resp']['resp'] for k in keys: - r = self.freq_resp[band]['resonances'][k] - eta_width = .300 # in MHz. So this = 300 kHz + r = self.freq_resp[band]['resonances'][k] + channel=r['channel'] + # If user provides a channel restriction list, only + # plot channels in that list. + if channel is not None and channel not in channels: + continue center_freq = r['freq'] idx = np.logical_and(freq > center_freq - eta_width, freq < center_freq + eta_width) - # Actually plot the data + # Actually plot the data self.plot_eta_fit(band, freq[idx], resp[idx], eta_mag=r['eta_mag'], eta_phase_deg=r['eta_phase'], band=band, res_num=k, timestamp=timestamp, save_plot=save_plot, show_plot=show_plot, - peak_freq=center_freq, channel=r['channel']) + peak_freq=center_freq, channel=channel) # This is for data from find_freq/setup_notches else: for k in keys: - self.log('Eta plot {} of {}'.format(k+1, n_keys)) - r = self.freq_resp[band]['resonances'][k] + r = self.freq_resp[band]['resonances'][k] + channel=r['channel'] + # If user provides a channel restriction list, only + # plot channels in that list. + if channels is not None: + if channel not in channels: + continue + else: + self.log('Eta plot for channel {}'.format(channel)) + else: + self.log('Eta plot {} of {}'.format(k+1, n_keys)) + self.plot_eta_fit(r['freq_eta_scan'], r['resp_eta_scan'], eta=r['eta'], eta_mag=r['eta_mag'], eta_phase_deg=r['eta_phase'], band=band, res_num=k, timestamp=timestamp, save_plot=save_plot, - show_plot=show_plot, peak_freq=r['freq']) + show_plot=show_plot, peak_freq=r['freq'], + channel=channel) def full_band_resp(self, band, n_scan=1, n_samples=2**19, make_plot=False, save_plot=True, show_plot=False, save_data=False, timestamp=None, @@ -1171,7 +1191,6 @@ def plot_eta_fit(self, freq, resp, eta=None, eta_mag=None, peak_freq=None, plt.ion() else: plt.ioff() - I = np.real(resp) Q = np.imag(resp) @@ -2859,7 +2878,7 @@ def find_freq(self, band, subband=np.arange(13,115), drive_power=None, if drive_power is None: drive_power = self.config.get('init')['band_{}'.format(band)].get('amplitude_scale') self.log(f'No drive_power given. Using value in config ' + - 'file: {drive_power}') + f'file: {drive_power}') self.log('Sweeping across frequencies') f, resp = self.full_band_ampl_sweep(band, subband, drive_power, n_read) diff --git a/pysmurf/util/smurf_util.py b/pysmurf/util/smurf_util.py index c8870406c..d427e3c30 100644 --- a/pysmurf/util/smurf_util.py +++ b/pysmurf/util/smurf_util.py @@ -114,7 +114,11 @@ def take_debug_data(self, band, channel=None, nsamp=2**19, filename=None, while not done: done=True for k in range(2): - wr_addr = self.get_waveform_wr_addr(bay, engine=0) + # see pysmurf issue 161. This call is no longer used, + # and causes take_debug_data to crash if + # get_waveform_wr_addr is called before the + # acquisition completes. + #wr_addr = self.get_waveform_wr_addr(bay, engine=0) empty = self.get_waveform_empty(bay, engine=k) if not empty: done=False diff --git a/requirements.txt b/requirements.txt index 3f12e9eb4..d83bb2cb9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ numpy scipy pyepics +matplotlib