combine two kwant.plotter.current figures into a single one
Dear all, sorry, this might be more a matplotlib question than a kwant question. Below is a minimal code which produces two figures, each showing a different dataset: a current in the scattering region due to a wavefunction in a lead. I would like to combine the two into a single plot, distinguishing the two datasets by e.g. different colormaps (and two different colorbars). Any ideas? Thanks a lot, Tibor ______________________________________ import kwant from math import pi, sqrt from cmath import exp import numpy from matplotlib import pyplot as plt #some parameters t=1 L=30 W=30 EF=0.1 phi=0.01 def hopping(sitei, sitej, phi): xi, yi = sitei.pos xj, yj = sitej.pos return -t*exp(1j*2*pi*phi*2/sqrt(3)*(yj - yi)*(xi + xj)/2) def make_system(): lat = kwant.lattice.general([(sqrt(3)*1/2, 1/2), (0, 1)], [(0, 0), (1/(2*sqrt(3)),1/2)], norbs=1) def central_region(pos): x, y = pos return abs(x) < L/2 and abs(y) < W/2 def lead0_shape(pos): x, y = pos return abs(x) < L/2 #scattering region sys = kwant.Builder() sys[lat.shape(central_region, (0,0))] = -EF sys[lat.neighbors()] = hopping sys.eradicate_dangling() #leads sym = kwant.TranslationalSymmetry(lat.vec((0,1))) lead0 = kwant.Builder(sym) lead0[lat.shape(lead0_shape, (0,0))] = -EF lead0[lat.neighbors()] = hopping lead0.eradicate_dangling() lead1=lead0.reversed() return sys, lead0, lead1 sys, lead0, lead1 = make_system() sys.attach_lead(lead0) sys.attach_lead(lead1) sysf = sys.finalized() wf = kwant.wave_function(sysf, energy=0.0001, params=dict(phi=phi)) J = kwant.operator.Current(sysf) psi1 = wf(0)[0] e_current1 = J(psi1, params=dict(phi=phi)) psi2 = wf(1)[0] e_current2 = J(psi2, params=dict(phi=phi)) kwant.plotter.current(sysf, e_current1, cmap="OrRd", colorbar=True, show=False) ax = plt.gca() plt.colorbar(ax.get_children()[-2], ax=ax) kwant.plotter.current(sysf, e_current2, cmap="Blues", colorbar=True, show=False) ax = plt.gca() plt.colorbar(ax.get_children()[-2], ax=ax) plt.show()
Dear Tibor, All Kwant plotting functions accept an Axes instance as an input argument, in which case they will modify that axes. Therefore to achieve what you want you need to prepare a figure with multiple axes and pass these axes to the Kwant plotting functions as input. Best, Anton On Tue, Jan 30, 2018 at 4:26 PM, Tibor Sekera <tibor.sekera@unibas.ch> wrote:
Dear all,
sorry, this might be more a matplotlib question than a kwant question.
Below is a minimal code which produces two figures, each showing a different dataset: a current in the scattering region due to a wavefunction in a lead.
I would like to combine the two into a single plot, distinguishing the two datasets by e.g. different colormaps (and two different colorbars).
Any ideas?
Thanks a lot, Tibor
______________________________________
import kwant from math import pi, sqrt from cmath import exp import numpy from matplotlib import pyplot as plt
#some parameters t=1 L=30 W=30 EF=0.1 phi=0.01
def hopping(sitei, sitej, phi): xi, yi = sitei.pos xj, yj = sitej.pos return -t*exp(1j*2*pi*phi*2/sqrt(3)*(yj - yi)*(xi + xj)/2)
def make_system():
lat = kwant.lattice.general([(sqrt(3)*1/2, 1/2), (0, 1)], [(0, 0), (1/(2*sqrt(3)),1/2)], norbs=1)
def central_region(pos): x, y = pos return abs(x) < L/2 and abs(y) < W/2
def lead0_shape(pos): x, y = pos return abs(x) < L/2
#scattering region sys = kwant.Builder() sys[lat.shape(central_region, (0,0))] = -EF sys[lat.neighbors()] = hopping sys.eradicate_dangling()
#leads sym = kwant.TranslationalSymmetry(lat.vec((0,1))) lead0 = kwant.Builder(sym) lead0[lat.shape(lead0_shape, (0,0))] = -EF lead0[lat.neighbors()] = hopping lead0.eradicate_dangling() lead1=lead0.reversed()
return sys, lead0, lead1
sys, lead0, lead1 = make_system() sys.attach_lead(lead0) sys.attach_lead(lead1) sysf = sys.finalized()
wf = kwant.wave_function(sysf, energy=0.0001, params=dict(phi=phi)) J = kwant.operator.Current(sysf)
psi1 = wf(0)[0] e_current1 = J(psi1, params=dict(phi=phi))
psi2 = wf(1)[0] e_current2 = J(psi2, params=dict(phi=phi))
kwant.plotter.current(sysf, e_current1, cmap="OrRd", colorbar=True, show=False) ax = plt.gca() plt.colorbar(ax.get_children()[-2], ax=ax)
kwant.plotter.current(sysf, e_current2, cmap="Blues", colorbar=True, show=False) ax = plt.gca() plt.colorbar(ax.get_children()[-2], ax=ax)
plt.show()
Dear Anthon, thank you, that's the way to go. One more thing: if the data plotted are very small, I don't want to show them. I know how to saturate the colorbar color using matplotlib.pyplot.clim But how to 'saturate' the streamlines (i.e. plot no streamlines)? Thanks again, Tibor ________________________________________ From: anton.akhmerov@gmail.com [anton.akhmerov@gmail.com] on behalf of Anton Akhmerov [anton.akhmerov+kd@gmail.com] Sent: Wednesday, January 31, 2018 1:04 PM To: Tibor Sekera Cc: kwant-discuss@kwant-project.org Subject: Re: [Kwant] combine two kwant.plotter.current figures into a single one Dear Tibor, All Kwant plotting functions accept an Axes instance as an input argument, in which case they will modify that axes. Therefore to achieve what you want you need to prepare a figure with multiple axes and pass these axes to the Kwant plotting functions as input. Best, Anton On Tue, Jan 30, 2018 at 4:26 PM, Tibor Sekera <tibor.sekera@unibas.ch> wrote:
Dear all,
sorry, this might be more a matplotlib question than a kwant question.
Below is a minimal code which produces two figures, each showing a different dataset: a current in the scattering region due to a wavefunction in a lead.
I would like to combine the two into a single plot, distinguishing the two datasets by e.g. different colormaps (and two different colorbars).
Any ideas?
Thanks a lot, Tibor
______________________________________
import kwant from math import pi, sqrt from cmath import exp import numpy from matplotlib import pyplot as plt
#some parameters t=1 L=30 W=30 EF=0.1 phi=0.01
def hopping(sitei, sitej, phi): xi, yi = sitei.pos xj, yj = sitej.pos return -t*exp(1j*2*pi*phi*2/sqrt(3)*(yj - yi)*(xi + xj)/2)
def make_system():
lat = kwant.lattice.general([(sqrt(3)*1/2, 1/2), (0, 1)], [(0, 0), (1/(2*sqrt(3)),1/2)], norbs=1)
def central_region(pos): x, y = pos return abs(x) < L/2 and abs(y) < W/2
def lead0_shape(pos): x, y = pos return abs(x) < L/2
#scattering region sys = kwant.Builder() sys[lat.shape(central_region, (0,0))] = -EF sys[lat.neighbors()] = hopping sys.eradicate_dangling()
#leads sym = kwant.TranslationalSymmetry(lat.vec((0,1))) lead0 = kwant.Builder(sym) lead0[lat.shape(lead0_shape, (0,0))] = -EF lead0[lat.neighbors()] = hopping lead0.eradicate_dangling() lead1=lead0.reversed()
return sys, lead0, lead1
sys, lead0, lead1 = make_system() sys.attach_lead(lead0) sys.attach_lead(lead1) sysf = sys.finalized()
wf = kwant.wave_function(sysf, energy=0.0001, params=dict(phi=phi)) J = kwant.operator.Current(sysf)
psi1 = wf(0)[0] e_current1 = J(psi1, params=dict(phi=phi))
psi2 = wf(1)[0] e_current2 = J(psi2, params=dict(phi=phi))
kwant.plotter.current(sysf, e_current1, cmap="OrRd", colorbar=True, show=False) ax = plt.gca() plt.colorbar(ax.get_children()[-2], ax=ax)
kwant.plotter.current(sysf, e_current2, cmap="Blues", colorbar=True, show=False) ax = plt.gca() plt.colorbar(ax.get_children()[-2], ax=ax)
plt.show()
Tibor Sekera wrote:
if the data plotted are very small, I don't want to show them. I know how to saturate the colorbar color using matplotlib.pyplot.clim But how to 'saturate' the streamlines (i.e. plot no streamlines)?
If I understand you correctly you'd like to have something similar to the vmin/vmax parameters of kwant.plotter.map? There, one can show two different plots with the same colorbar scales. This is not possible with stock Kwant, because matplotlib's streamplot that does the actual work of tracing the stream lines does not support such functionality. (It does not fit into its logic because streamplot's stream lines are not meant to blend into the background.) Kwant's streamplot (kwant.plotter.streamplot) builds on matplotlib's by showing a background image of local flow strength and by scaling the line width according to it. Some matplotlib backends (notably PDF) have a minimum line width, and that's why Kwant's streamplot simulates thinner lines by blending their color into the background color. Thanks to this, it would actually make sense to have a vmax argument for Kwant's streamplot. I made a quick prototype (patch attached). To apply it you must install Kwant from source. Use the command "git apply vmax.patch" if you are using git and otherwise use "patch -p1 <vmax.patch". If you don't want to install Kwant from source, you can also copy the source of Kwant's streamplot to your script and apply the patch manually. Note that since I added a new keyword argument to kwant.plotter.streamplot and that argument is not known by kwant.plotter.current, you'll have to call (as explained in the docstring of kwant.plotter.current): streamplot(*interpolate_current(syst, current), vmax=my_vmax) Do let me know if you think that this would be a useful addition to Kwant. Christoph
participants (3)
-
Anton Akhmerov
-
Christoph Groth
-
Tibor Sekera