class BlochPlot(): ''' Dynamic plot context, intended for displaying geometries. like removing axes, equal axis, dynamically tune your figure and save it. Args: figsize (tuple, default=(6,4)): figure size. filename (filename, str): filename to store generated figure, if None, it will not save a figure. Attributes: figsize (tuple, default=(6,4)): figure size. filename (filename, str): filename to store generated figure, if None, it will not save a figure. ax (Axes): matplotlib Axes instance. Examples: with BlochPlot() as bp: bp.ball.add_vectors([0.4, 0.6, 0.8]) ''' def __init__(self, figsize=(6, 4), filename=None, dpi=300): self.figsize = figsize self.filename = filename self.ax = None def __enter__(self): from qutip import Bloch3d, Bloch plt.ion() self.fig = plt.figure(figsize=self.figsize) self.ax = Axes3D(self.fig, azim=-30, elev=15) self.ball = Bloch(axes=self.ax) self.ball.zlabel = [r'$|N\rangle$', r'$|S\rangle$'] return self def __exit__(self, *args): self.ax.axis('off') self.ax.set_aspect("equal") #self.ball.make_sphere() self.ball.make_sphere() plt.close() if self.filename is not None: print('Press `c` to save figure to "%s", `Ctrl+d` to break >>' % self.filename) pdb.set_trace() plt.savefig(self.filename, dpi=300) else: pdb.set_trace() def add_polar(self, theta, phi, color=None): self.ball.add_vectors(polar2vec([1, theta, phi])) self.ball.vector_color.append(color) def text(self, vec, txt, fontsize=14): if len(vec) == 2: vec = polar2vec(*vec) self.ax.text(vec[0], vec[1], vec[2], txt, fontsize=fontsize, va='center', ha='center')
def bloch_from_dataframe(df, fig, axes): """ Plot Bloch sphere :param df: pd.DataFrame :param axes: :return: """ bloch = Bloch(fig=fig, axes=axes) bloch.vector_color = plt.get_cmap('viridis')(np.linspace(0, 1, len(df))) bloch.add_states([ Qobj([[row.Jxx, row.beta + 1j * row.gamma], [row.beta - 1j * row.gamma, row.Jyy]]) for _, row in df.iterrows() ]) bloch.make_sphere()
class CVisualizeAnim(object): """ Class for drawing animation """ def __init__(self, fig): ################################################################# # # Initialize plotting exact plots tools # ################################################################# # p = np.linspace(-20., 20., 1000)[:, np.newaxis] # q = np.linspace(-20., 20., 1000)[np.newaxis, :] # # self.hybrid = CAnalyticQCHybrid(p, q, kT=0.5) # # img_params = dict( # extent=[q.min(), q.max(), p.min(), p.max()], # origin='lower', # cmap='seismic', # # norm=WignerNormalize(vmin=-0.1, vmax=0.1) # norm=WignerSymLogNorm(linthresh=1e-10, vmin=-0.01, vmax=0.1) # ) p = np.linspace(-25, 25, 600)[:, np.newaxis] q = np.linspace(-25, 25, 600)[np.newaxis, :] self.hybrid = CAnalyticQCHybrid(p=p, q=q, omega=1., beta=2., alpha=0.95) img_params = dict( extent=[q.min(), q.max(), p.min(), p.max()], origin='lower', cmap='seismic', # norm=WignerNormalize(vmin=-0.1, vmax=0.1) norm=WignerSymLogNorm(linthresh=1e-10, vmin=-0.01, vmax=0.1)) ################################################################# # # Initialize Pauli propagator # ################################################################# self.pauli = SplitOpPauliLike1D( X_amplitude=2. * q.max(), X_gridDIM=512, dt=0.0001, K0="0.5 * P ** 2", V0="0.5 * X ** 2", V1="0.5 * 0.95 * X ** 2", # kT=self.hybrid.kT, # parameters controlling the width of the initial wavepacket ).set_wavefunction("exp(-0.5 * X ** 2)") ################################################################# # # Initialize plotting facility # ################################################################# self.fig = fig self.fig.suptitle( "Quantum-classical hybrid $m=1$, $\omega=1$, $\\alpha=0.95$, $\\beta={:.1e}$ (a.u.) (a.u.)" .format(self.hybrid.beta)) self.ax = fig.add_subplot(221) self.ax.set_title('Classical density') # generate empty plots self.img_classical_density = self.ax.imshow([[0]], **img_params) self.ax.set_xlabel('$q$ (a.u.)') self.ax.set_ylabel('$p$ (a.u.)') ax = fig.add_subplot(222) ax.set_title('Quantum purity') self.quantum_purity_plot, = ax.plot([0., 40], [1, 0.5], label='hybrid') self.pauli_quantum_purity_plot, = ax.plot([0., 40], [1, 0.5], label='Pauli') ax.set_xlabel('time (a.u.)') ax.set_ylabel("quantum purity") ax.legend() self.time = [] self.qpurity = [] self.pauli_qpurity = [] ax = fig.add_subplot(223) ax.set_title("Coordinate distribution") self.c_coordinate_distribution, = ax.semilogy( [self.hybrid.q.min(), self.hybrid.q.max()], [1e-11, 1e0], label="hybrid") self.pauli_coordinate_distribution, = ax.semilogy( [self.hybrid.q.min(), self.hybrid.q.max()], [1e-11, 1e0], label="Pauli") ax.legend() ax.set_xlabel('$q$ (a.u.)') ax.set_ylabel('Probability density') ax = fig.add_subplot(224, projection='3d', azim=90, elev=0) self.bloch = Bloch(axes=ax) self.bloch.make_sphere() def __call__(self, frame_num): """ Draw a new frame :param frame_num: current frame number :return: image objects """ # convert the frame number to time #t = 0.05 * frame_num t = self.pauli.t # calculate the hybrid density matrix self.hybrid.calculate_D(t) # plot the classical density c_rho = self.hybrid.classical_density() self.img_classical_density.set_array(c_rho) self.ax.set_title( 'Classical density \n $t = {:.1f}$ (a.u.)'.format(t)) # plot the coordinate distribution for the classical density coordinate_marginal = c_rho.sum(axis=0) # coordinate_marginal *= self.hybrid.dp coordinate_marginal /= coordinate_marginal.max() self.c_coordinate_distribution.set_data(self.hybrid.q.reshape(-1), coordinate_marginal) coordinate_density = self.pauli.coordinate_density coordinate_density /= coordinate_density.max() self.pauli_coordinate_distribution.set_data( self.pauli.X, coordinate_density) # plot quantum purity self.time.append(t) self.qpurity.append(self.hybrid.quantum_purity()) self.quantum_purity_plot.set_data(self.time, self.qpurity) # Get the Pauli density matrix rho12 = np.sum(self.pauli.psi1 * self.pauli.psi2.conjugate()) rho_pauli = np.array( [[np.sum(np.abs(self.pauli.psi1)**2), rho12], [rho12.conjugate(), np.sum(np.abs(self.pauli.psi2)**2)]]) rho_pauli *= self.pauli.dX # plot Pauli purity self.pauli_qpurity.append(rho_pauli.dot(rho_pauli).trace().real) self.pauli_quantum_purity_plot.set_data(self.time, self.pauli_qpurity) # plot Bloch vector self.bloch.clear() self.bloch.add_states( [Qobj(self.hybrid.quantum_density()), Qobj(rho_pauli)]) self.bloch.make_sphere() # self.pauli.propagate(1000) return self.img_classical_density, self.quantum_purity_plot, self.pauli_quantum_purity_plot,\ self.bloch, self.pauli_coordinate_distribution
class CVisualizeAnim(object): """ Class for drawing animation """ def __init__(self, fig): ################################################################# # # Initialize plotting exact plots tools # ################################################################# # p = np.linspace(-20., 20., 1000)[:, np.newaxis] # q = np.linspace(-20., 20., 1000)[np.newaxis, :] # # self.hybrid = CAnalyticQCHybrid(p, q, kT=0.5) # # img_params = dict( # extent=[q.min(), q.max(), p.min(), p.max()], # origin='lower', # cmap='seismic', # # norm=WignerNormalize(vmin=-0.1, vmax=0.1) # norm=WignerSymLogNorm(linthresh=1e-10, vmin=-0.01, vmax=0.1) # ) p = np.linspace(-0.1, 0.1, 500)[:, np.newaxis] q = np.linspace(-0.1, 0.1, 500)[np.newaxis, :] self.hybrid = SolAGKEq(p=p, q=q, omega=1., beta=1e5, alpha=0.95) img_params = dict( extent=[q.min(), q.max(), p.min(), p.max()], origin='lower', cmap='seismic', #norm=WignerNormalize(vmin=-0.1, vmax=0.1) norm=WignerSymLogNorm(linthresh=1e-10, vmin=-0.01, vmax=0.1)) # List to save the total hybrid energy for testing (it must be a conserved quantity) self.total_energy = [] # List to save the x component of the Bloch vector self.sigma_1 = [] ################################################################# # # Initialize plotting facility # ################################################################# self.fig = fig self.fig.suptitle( "Quantum-classical hybrid $m=1$, $\omega=1$, $\\alpha=0.95$, $\\beta={:.1e}$ (a.u.) (a.u.)" .format(self.hybrid.beta)) self.ax = fig.add_subplot(221) self.ax.set_title('Classical density') # generate empty plots self.img_classical_density = self.ax.imshow([[0]], **img_params) self.ax.set_xlabel('$q$ (a.u.)') self.ax.set_ylabel('$p$ (a.u.)') ax = fig.add_subplot(222) ax.set_title('Quantum purity') self.quantum_purity_plot, = ax.plot([0., 1000000], [1, 0.5]) ax.set_xlabel('time (a.u.)') ax.set_ylabel("quantum purity") self.time = [] self.qpurity = [] ax = fig.add_subplot(223) ax.set_title("Coordinate distribution") self.c_coordinate_distribution, = ax.semilogy( [self.hybrid.q.min(), self.hybrid.q.max()], [1e-11, 1e0], label="hybrid") ax.legend() ax.set_xlabel('$q$ (a.u.)') ax.set_ylabel('Probability density') ax = fig.add_subplot(224, projection='3d', azim=0, elev=0) self.bloch = Bloch(axes=ax) self.bloch.make_sphere() def __call__(self, frame_num): """ Draw a new frame :param frame_num: current frame number :return: image objects """ # convert the frame number to time t = 4000. * frame_num # calculate the hybrid density matrix self.hybrid.calculate_D(t) # Save total energy self.total_energy.append(self.hybrid.energy()) # Save <sigma_1> self.sigma_1.append(self.hybrid.average_sigma_1()) # plot the classical density c_rho = self.hybrid.classical_density() self.img_classical_density.set_array(c_rho) self.ax.set_title( 'Classical density \n $t = {:.1f}$ (a.u.)'.format(t)) # plot the coordinate distribution for the classical density coordinate_marginal = c_rho.sum(axis=0) # coordinate_marginal *= self.hybrid.dp coordinate_marginal /= coordinate_marginal.max() self.c_coordinate_distribution.set_data(self.hybrid.q.reshape(-1), coordinate_marginal) # plot quantum purity self.time.append(t) self.qpurity.append(self.hybrid.quantum_purity()) self.quantum_purity_plot.set_data(self.time, self.qpurity) # plot Bloch vector self.bloch.clear() self.bloch.add_states(Qobj(self.hybrid.quantum_density())) self.bloch.make_sphere() # # self.pauli.propagate(100) return self.img_classical_density, self.quantum_purity_plot, self.bloch,
@author: wittek """ from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt from qutip import Bloch from graphics_utils import initialize_graphics colors = initialize_graphics() fig = plt.figure() axes = Axes3D(fig) axes.grid = True axes.axis("off") axes.set_axis_off() b=Bloch() b.fig = fig b.axes = axes #b.fig = fig #b.frame_width=1 b.sphere_color = 'white' b.sphere_alpha = 0.1 #b.size = [10, 10] b.make_sphere() plt.savefig('./bloch_sphere.svg',bbox_inches='tight') #b.show() #b.save('bloch_sphere.pdf',format='pdf')