Coverage for tbkit/plot.py: 100%
323 statements
« prev ^ index » next coverage.py v7.17.0, created at 2026-10-30 11:04 +0000
« prev ^ index » next coverage.py v7.17.0, created at 2026-10-30 11:04 +0000
1from __future__ import annotations
3import numpy as np
4from numpy.typing import NDArray, ArrayLike
5import matplotlib.pyplot as plt
6from matplotlib.figure import Figure, SubFigure
7from matplotlib.axes import Axes
8import tbkit.error_handling as error_handling
9import tbkit.dos as dos
10from tbkit.system import System
13#################################
14# CLASS PLOT
15#################################
18class Plot:
19 '''
20 Plot the results of the classes **lattice** or **system**.
22 Parameters
23 ----------
24 sys : class instance **system**
25 colors
26 Default value None. Color plot.
27 '''
29 def __init__(self, sys: System, colors: list[str] | None = None) -> None:
30 error_handling.sys(sys)
31 self.sys = sys
32 if colors is None:
33 self.colors = ['b', 'r', 'g', 'y', 'm', 'k']
34 else:
35 self.colors = colors
37 def plt_hopping(self, coor: NDArray, hop: NDArray, c: float, ax: Axes | None = None) -> None:
38 '''
39 Private method called by *lattice_generic*.
40 '''
41 if ax is None:
42 ax = plt.gca()
43 # bonds that wrap around a torus would cross the whole sample
44 hop = hop[~self.sys._wrapped(hop['i'].astype(int), hop['j'].astype(int))]
45 for i in range(len(hop)):
46 ax.plot([coor['x'][hop['i'][i]],
47 coor['x'][hop['j'][i]]],
48 [coor['y'][hop['i'][i]],
49 coor['y'][hop['j'][i]]],
50 'k', lw=c*np.abs(hop['t'][i]))
52 def lattice_generic(
53 self,
54 coor: NDArray,
55 ms: float,
56 lw: float,
57 c: float,
58 fs: float,
59 axis: bool,
60 plt_hop: bool,
61 plt_hop_low: bool,
62 plt_index: bool,
63 figsize: tuple[float, float] | None,
64 ax: Axes | None = None,
65 ) -> Figure | SubFigure:
66 '''
67 Private method called by *lattice* and *lattice_hop*.
68 '''
69 error_handling.positive_real(ms, 'ms')
70 error_handling.positive_real(lw, 'lw')
71 error_handling.positive_real(c, 'c')
72 error_handling.positive_real(fs, 'fs')
73 error_handling.boolean(axis, 'axis')
74 error_handling.boolean(plt_hop, 'plt_hop')
75 error_handling.boolean(plt_hop_low, 'plt_hop_low')
76 error_handling.boolean(plt_index, 'plt_index')
77 error_handling.tuple_2elem(figsize, 'figsize')
78 fig: Figure | SubFigure
79 if ax is None:
80 fig, ax = plt.subplots(figsize=figsize)
81 else:
82 fig = ax.figure
83 # hoppings
84 if plt_hop:
85 error_handling.empty_ndarray(self.sys.hop, 'sys.hop')
86 self.plt_hopping(coor, self.sys.hop[self.sys.hop['ang']>=0], c, ax=ax)
87 if plt_hop_low:
88 error_handling.empty_ndarray(self.sys.hop, 'sys.hop')
89 self.plt_hopping(coor, self.sys.hop[self.sys.hop['ang']<0], c, ax=ax)
90 # plot sites
91 for color, tag in zip(self.colors, self.sys.lat.tags):
92 ax.plot(coor['x'][coor['tag'] == tag],
93 coor['y'][coor['tag'] == tag],
94 'o', color=color, ms=ms, markeredgecolor='none')
95 ax.set_aspect('equal')
96 ax.set_xlim(np.min(coor['x'])-1., np.max(coor['x'])+1.)
97 ax.set_ylim(np.min(coor['y'])-1., np.max(coor['y'])+1.)
98 if not axis:
99 ax.axis('off')
100 # plot indices
101 if plt_index:
102 indices = ['{}'.format(i) for i in range(self.sys.lat.sites)]
103 for l, x, y in zip(indices, coor['x'], coor['y']):
104 ax.annotate(l, xy=(x, y), xytext=(0, 0),
105 textcoords='offset points',
106 ha='right', va='bottom', size=fs)
107 plt.draw()
108 return fig
110 def lattice(
111 self,
112 ms: float = 20,
113 lw: float = 5.,
114 c: float = 3.,
115 fs: float = 20,
116 axis: bool = False,
117 plt_hop: bool = False,
118 plt_hop_low: bool = False,
119 plt_index: bool = False,
120 figsize: tuple[float, float] | None = None,
121 ax: Axes | None = None,
122 ) -> Figure | SubFigure:
123 '''
124 Plot lattice.
126 Parameters
127 ----------
128 ms : Positive number, default 20
129 Markersize.
130 c : Positive number, default 3
131 Coefficient. Hopping linewidths given by c*|hop['t']|.
132 fs : Positive number, default 20
133 Fontsize.
134 plt_hop : Boolean, default False
135 Plot hoppings.
136 plt_hop_low : Boolean, default False
137 Plot hoppings diagonal low.
138 plt_index : Boolean, default False
139 Plot site labels.
140 axis : Boolean, default False
141 Plot axis.
142 figsize : Tuple, default None
143 Figure size.
144 ax : Axes, default None
145 Draw on this axis instead of
146 creating a figure of its own -- to place several lattices side
147 by side in one figure. *figsize* is then ignored.
149 Returns
150 -------
151 fig : Figure
152 '''
153 error_handling.empty_ndarray(self.sys.lat.coor, 'lat.get_lattice')
154 return self.lattice_generic(self.sys.lat.coor, ms, lw, c, fs, axis, plt_hop,
155 plt_hop_low, plt_index, figsize, ax)
157 def lattice_hop(
158 self,
159 ms: float = 20,
160 lw: float = 5,
161 c: float = 3.,
162 fs: float = 20,
163 axis: bool = False,
164 plt_hop: bool = False,
165 plt_hop_low: bool = False,
166 plt_index: bool = False,
167 figsize: tuple[float, float] | None = None,
168 ax: Axes | None = None,
169 ) -> Figure | SubFigure:
170 '''
171 Plot lattice in hopping space.
173 Parameters
174 ----------
175 ms : Positive Float, default 20
176 Markersize.
177 c : Positive Float, default 3
178 Coefficient.
179 Hopping linewidths given by c*|hop['t']|.
180 fs : Positive Float, default 20
181 Fontsize.
182 axis : Boolean, default False
183 Plot axis.
184 plt_hop : Boolean, default False
185 Plot hoppings.
186 plt_index : Boolean, default False
187 Plot site labels.
188 figsize : Tuple, default None
189 Figure size.
190 ax : Axes, default None
191 Draw on this axis instead of
192 creating a figure of its own -- to place several lattices side
193 by side in one figure. *figsize* is then ignored.
195 Returns
196 -------
197 fig : Figure
198 '''
199 error_handling.empty_ndarray(self.sys.coor_hop, 'sys.get_coor_hop')
200 return self.lattice_generic(self.sys.coor_hop, ms, lw, c, fs, axis, plt_hop,
201 plt_hop_low, plt_index, figsize, ax)
204 def spectrum_hist(self, nbr_bins: int = 61, fs: float = 20, lims: tuple[float, float] | None = None) -> Figure:
205 """
206 Plot the spectrum (real part of the eigenenergies) as a histogram.
208 Parameters
209 ----------
210 nbr_bins : Positive integer, default 61
211 Number of bins of the histogram.
212 fs : Positive number, default 20
213 Fontsize.
214 lims : List, lims[0] energy min, lims[1] energy max
216 Returns
217 -------
218 fig : Figure
219 """
220 error_handling.empty_ndarray(self.sys.en, 'sys.get_eig')
221 error_handling.positive_int(nbr_bins, 'nbr_bins')
222 error_handling.positive_real(fs, 'fs')
223 error_handling.lims(lims)
224 fig, ax = plt.subplots()
225 en_real = self.sys.en.real
226 if lims is None:
227 ind_en = np.ones(len(self.sys.en), bool)
228 else:
229 ind_en = np.ravel(np.argwhere((en_real > lims[0]) & (en_real < lims[1])))
230 ax.set_xlim(lims)
231 en = en_real[ind_en]
232 n, bins, patches = plt.hist(en, bins=nbr_bins, color='b', alpha=0.8)
233 ax.set_title('Spectrum', fontsize=fs)
234 ax.set_xlabel('$E$', fontsize=fs)
235 ax.set_ylabel('number of states', fontsize=fs)
236 ax.set_ylim(0, np.max(n)+1)
237 for label in ax.xaxis.get_majorticklabels():
238 label.set_fontsize(fs)
239 for label in ax.yaxis.get_majorticklabels():
240 label.set_fontsize(fs)
241 return fig
243 def dos(
244 self,
245 broadening: float = 0.05,
246 kernel: str = 'gaussian',
247 e_grid: ArrayLike | None = None,
248 fs: float = 20,
249 lw: float = 2.,
250 figsize: tuple[float, float] | None = None,
251 ) -> Figure:
252 '''
253 Plot the (broadened) density of states, see *tbkit.dos.density_of_states*.
255 Parameters
256 ----------
257 broadening : Positive real number, default 0.05
258 Kernel width.
259 kernel : String, default 'gaussian'
260 'gaussian' or 'lorentzian'.
261 e_grid : Real ndarray, default None
262 Energies at which to
263 evaluate the density of states.
264 fs : Positive number, default 20
265 Fontsize.
266 lw : Positive number, default 2
267 Linewidth.
268 figsize : Tuple, default None
269 Figure size.
271 Returns
272 -------
273 fig : Figure
274 '''
275 error_handling.empty_ndarray(self.sys.en, 'sys.get_eig')
276 error_handling.positive_real(fs, 'fs')
277 error_handling.positive_real(lw, 'lw')
278 error_handling.tuple_2elem(figsize, 'figsize')
279 return dos._plot_density_of_states(self.sys.en, e_grid, broadening, kernel, fs, lw, figsize)
281 def spectrum(
282 self,
283 ms: float = 10,
284 fs: float = 20,
285 lims: tuple[float, float] | None = None,
286 tag_pola: str | None = None,
287 ipr: bool | None = None,
288 petermann: bool | None = None,
289 ) -> Figure:
290 '''
291 Plot spectrum (eigenenergies real part (blue circles),
292 and sublattice polarization if *pola* not empty (red circles).
294 Parameters
295 ----------
296 ms
297 Default value 10. Markersize.
298 fs
299 Default value 20. Fontsize.
300 lims : List, lims[0] energy min, lims[1] energy max
301 tag_pola
302 Default value None. One-character string. Tag of the sublattice.
303 ipr
304 Default value None. If True plot the Inverse Participation Ratio.
305 petermann
306 Default value None. If True plot the Petermann factor.
308 Returns
309 -------
310 fig : Figure
311 '''
312 error_handling.empty_ndarray(self.sys.en, 'sys.get_eig')
313 error_handling.positive_real(ms, 'ms')
314 error_handling.positive_real(fs, 'fs')
315 error_handling.lims(lims)
316 fig, ax1 = plt.subplots()
317 ax1 = plt.gca()
318 x = np.arange(len(self.sys.en))
319 if lims is None:
320 ax1.set_ylim(np.min(self.sys.en.real)-0.2, np.max(self.sys.en.real)+0.2)
321 ind = np.ones(len(self.sys.en), bool)
322 else:
323 ind = (self.sys.en.real > lims[0]) & (self.sys.en.real < lims[1])
324 ax1.set_ylim(lims[0]-0.1, lims[1]+0.1)
325 ax1.plot(x[ind], self.sys.en.real[ind], 'ob', markersize=ms)
326 ax1.set_title('Spectrum', fontsize=fs)
327 ax1.set_xlabel('$n$', fontsize=fs)
328 ax1.set_ylabel('$E_n$', fontsize=fs, color='blue')
329 for label in ax1.get_yticklabels():
330 label.set_color('b')
331 if tag_pola:
332 error_handling.tag(tag_pola, self.sys.lat.tags)
333 fig, ax2 = self.polarization(fig=fig, ax1=ax1, ms=ms, fs=fs, tag_pola=tag_pola, ind=ind)
334 elif ipr:
335 fig, ax2 = self.ipr(fig=fig, ax1=ax1, ms=ms, fs=fs, ind=ind)
336 elif petermann:
337 fig, ax2 = self.petermann(fig=fig, ax1=ax1, ms=ms, fs=fs, ind=ind)
338 for label in ax1.xaxis.get_majorticklabels():
339 label.set_fontsize(fs)
340 for label in ax1.yaxis.get_majorticklabels():
341 label.set_fontsize(fs)
342 xa = ax1.get_xaxis()
343 ax1.set_xlim(x[ind][0]-0.5, x[ind][-1]+0.5)
344 xa.set_major_locator(plt.MaxNLocator(integer=True))
345 fig.set_layout_engine('tight')
346 plt.draw()
347 return fig
349 def polarization(
350 self,
351 fig: Figure | None = None,
352 ax1: Axes | None = None,
353 ms: float = 10.,
354 fs: float = 20.,
355 lims: tuple[float, float] | None = None,
356 tag_pola: str | None = None,
357 ind: NDArray | None = None,
358 ) -> tuple[Figure, Axes]:
359 '''
360 Plot sublattice polarization.
362 Parameters
363 ----------
364 fig : Figure, default None
365 (used by the method spectrum).
366 ax1 : Axis, default None
367 (used by the method spectrum).
368 ms : Positive Float, default 10
369 Markersize.
370 fs : Positive Float, default 20
371 Fontsize.
372 lims : List, lims[0] energy min, lims[1] energy max
373 tag_pola : One-character string, default None
374 Tag of the sublattice.
375 ind : List, default None
376 List of indices. (used in the method spectrum).
378 Returns
379 -------
380 fig : Figure
381 '''
382 if fig is None:
383 error_handling.sys(self.sys)
384 error_handling.empty_ndarray(self.sys.en, 'sys.get_eig')
385 error_handling.positive_real(ms, 'ms')
386 error_handling.positive_real(fs, 'fs')
387 error_handling.lims(lims)
388 fig, ax2 = plt.subplots()
389 if lims is None:
390 ax2.set_ylim(-0.1, 1.1)
391 ind = np.ones(len(self.sys.en), bool)
392 else:
393 ind = (self.sys.en.real > lims[0]) & (self.sys.en.real < lims[1])
394 ax2.set_ylim(lims[0]-0.1, lims[1]+0.1)
395 else:
396 ax2 = plt.gca().twinx()
397 error_handling.empty_ndarray(self.sys.pola, 'sys.get_pola')
398 error_handling.tag(tag_pola, self.sys.lat.tags)
399 x = np.arange(len(self.sys.en))
400 i_tag = self.sys.lat.tags == tag_pola
401 ax2.plot(x[ind], np.ravel(self.sys.pola[ind, i_tag]), 'or', markersize=(4*ms)//5)
402 ylabel = '$<' + str(tag_pola).upper() + '|' + str(tag_pola).upper() + '>$'
403 ax2.set_ylabel(ylabel, fontsize=fs, color='red')
404 ax2.set_ylim(-0.1, 1.1)
405 ax2.set_xlim(-0.5, x[ind][-1]+0.5)
406 for tick in ax2.xaxis.get_major_ticks():
407 tick.label1.set_fontsize(fs)
408 for label in ax2.get_yticklabels():
409 label.set_color('r')
410 return fig, ax2
412 def ipr(
413 self,
414 fig: Figure | None = None,
415 ax1: Axes | None = None,
416 ms: float = 10,
417 fs: float = 20,
418 lims: tuple[float, float] | None = None,
419 ind: NDArray | None = None,
420 ) -> tuple[Figure, Axes]:
421 '''
422 Plot the Inverse Participation Ratio.
424 Parameters
425 ----------
426 fig : Figure, default None
427 (used by the method spectrum).
428 ax1 : Axis, default None
429 (used by the method spectrum).
430 ms : Positive Float, default 10
431 Markersize.
432 fs : Positive Float, default 20
433 Fontsize.
434 lims : List
435 lims[0] energy min, lims[1] energy max.
436 ind : List, default None
437 List of indices. (used in the method spectrum).
439 Returns
440 -------
441 fig : Figure
442 '''
443 if fig is None:
444 error_handling.sys(self.sys)
445 error_handling.empty_ndarray(self.sys.ipr, 'sys.get_ipr')
446 error_handling.positive_real(ms, 'ms')
447 error_handling.positive_real(fs, 'fs')
448 error_handling.lims(lims)
449 fig, ax2 = plt.subplots()
450 if lims is None:
451 ind = np.ones(len(self.sys.en), bool)
452 else:
453 ind = (self.sys.en.real > lims[0]) & (self.sys.en.real < lims[1])
454 else:
455 ax2 = plt.gca().twinx()
456 error_handling.empty_ndarray(self.sys.ipr, 'sys.get_ipr')
457 x = np.arange(len(self.sys.en))
458 ax2.plot(x[ind], self.sys.ipr[ind], 'or', markersize=(4*ms)//5)
459 ax2.set_ylabel( 'IPR' , fontsize=fs, color='red')
460 ax2.set_xlim(-0.5, x[ind][-1]+0.5)
461 for tick in ax2.xaxis.get_major_ticks():
462 tick.label1.set_fontsize(fs)
463 for label in ax2.get_yticklabels():
464 label.set_color('r')
465 return fig, ax2
467 def petermann(
468 self,
469 fig: Figure | None = None,
470 ax1: Axes | None = None,
471 ms: float = 10,
472 fs: float = 20,
473 lims: tuple[float, float] | None = None,
474 ind: NDArray | None = None,
475 ) -> tuple[Figure, Axes]:
476 '''
477 Plot the Petermann factor.
479 Parameters
480 ----------
481 fig : Figure, default None
482 (used by the method spectrum).
483 ax1 : Axis, default None
484 (used by the method spectrum).
485 ms : Positive Float, default 10
486 Markersize.
487 fs : Positive Float, default 20
488 Fontsize.
489 lims : List
490 lims[0] energy min, lims[1] energy max.
491 ind : List, default None
492 List of indices. (used in the method spectrum).
494 Returns
495 -------
496 fig : Figure
497 '''
498 if fig is None:
499 error_handling.sys(self.sys)
500 error_handling.empty_ndarray(self.sys.petermann, 'sys.get_petermann')
501 error_handling.positive_real(ms, 'ms')
502 error_handling.positive_real(fs, 'fs')
503 error_handling.lims(lims)
504 fig, ax2 = plt.subplots()
505 if lims is None:
506 ind = np.ones(len(self.sys.en), bool)
507 else:
508 ind = (self.sys.en.real > lims[0]) & (self.sys.en.real < lims[1])
509 else:
510 ax2 = plt.gca().twinx()
511 error_handling.empty_ndarray(self.sys.petermann, 'sys.get_petermann')
512 x = np.arange(len(self.sys.en))
513 ax2.plot(x[ind], self.sys.petermann[ind], 'or', markersize=(4*ms)//5)
514 ax2.set_ylabel( 'K' , fontsize=fs, color='red')
515 ax2.set_xlim(-0.5, x[ind][-1]+0.5)
516 for tick in ax2.xaxis.get_major_ticks():
517 tick.label1.set_fontsize(fs)
518 for label in ax2.get_yticklabels():
519 label.set_color('r')
520 return fig, ax2
522 def spectrum_complex(self, ms: float = 10., fs: float = 20., lims: tuple[float, float] | None = None) -> Figure:
523 '''
524 Plot complex value eigenenergies, real part (blue circles),
525 and imaginary part (red circles).
527 Parameters
528 ----------
529 ms : Positive Float, default 10
530 Markersize.
531 fs : Positive Float, default 20
532 Font size.
533 lims : List
534 lims[0] energy min, lims[1] energy max.
536 Returns
537 -------
538 fig : Figure
539 '''
540 error_handling.empty_ndarray(self.sys.en, 'sys.get_eig')
541 error_handling.positive_real(ms, 'ms')
542 error_handling.positive_real(fs, 'fs')
543 error_handling.lims(lims)
544 fig, ax1 = plt.subplots()
545 ax1 = plt.gca()
546 x = np.arange(len(self.sys.en))
547 if lims is None:
548 ax1.set_ylim(min(np.min(self.sys.en.real), np.min(self.sys.en.imag))-0.2,
549 max(np.max(self.sys.en.real), np.max(self.sys.en.imag))+0.2)
550 ind = np.ones(len(self.sys.en), bool)
551 else:
552 ind = (self.sys.en.real > lims[0]) & (self.sys.en.real < lims[1])
553 ax1.set_ylim(lims[0]-0.1, lims[1]+0.1)
554 ax1.plot(x[ind], self.sys.en.real[ind], 'ob', markersize=ms)
555 ax1.plot(x[ind], self.sys.en.imag[ind], 'or', markersize=ms)
556 ax1.set_title('Spectrum', fontsize=fs)
557 ax1.set_xlabel('$n$', fontsize=fs)
558 ax1.set_ylabel('Re '+r'$E_n$'+', Im '+r'$E_n$', fontsize=fs)
559 for label in ax1.xaxis.get_majorticklabels():
560 label.set_fontsize(fs)
561 for label in ax1.yaxis.get_majorticklabels():
562 label.set_fontsize(fs)
563 xa = ax1.get_xaxis()
564 ax1.set_xlim(x[ind][0]-0.1, x[ind][-1]+0.1)
565 xa.set_major_locator(plt.MaxNLocator(integer=True))
566 fig.set_layout_engine('tight')
567 plt.draw()
568 return fig
570 def intensity_1d(
571 self, intensity: NDArray, ms: float = 20., lw: float = 2., fs: float = 20.,
572 title: str = r'$|\psi^{(j)}|^2$',
573 ) -> Figure:
574 r'''
575 Plot intensity for 1D lattices.
577 Parameters
578 ----------
579 intensity : np.array
580 Field intensity.
581 ms : Positive Float, default 20
582 Markersize.
583 lw : Positive Float, default 2
584 Linewith, connect sublattice sites.
585 fs : Positive Float, default 20
586 Font size.
587 title : String
588 Default value '$|\psi^{(j)}|^2$'. Figure title.
590 Returns
591 -------
592 fig : Figure
593 '''
594 error_handling.ndarray(intensity, 'intensity', self.sys.lat.sites)
595 error_handling.empty_ndarray(self.sys.lat.coor, 'sys.get_lattice')
596 error_handling.positive_real(ms, 'ms')
597 error_handling.positive_real(lw, 'lw')
598 error_handling.positive_real(fs, 'fs')
599 error_handling.string(title, 'title')
600 fig, ax = plt.subplots()
601 ax.set_xlabel('$j$', fontsize=fs)
602 ax.set_ylabel(title, fontsize=fs)
603 ax.set_title(title, fontsize=fs)
604 for t, c in zip(self.sys.lat.tags, self.colors):
605 plt.plot(self.sys.lat.coor['x'][self.sys.lat.coor['tag'] == t],
606 intensity[self.sys.lat.coor['tag'] == t],
607 '-o', color=c, ms=ms, lw=lw)
608 plt.xlim(-1., self.sys.lat.sites)
609 plt.ylim(0., np.max(intensity)+.05)
610 fig.set_layout_engine('tight')
611 plt.draw()
612 return fig
614 def intensity_disk(
615 self,
616 intensity: NDArray,
617 s: float = 200.,
618 fs: float = 20.,
619 lims: tuple[float, float] | None = None,
620 figsize: tuple[float, float] | None = None,
621 title: str = r'$|\psi|^2$',
622 ) -> Figure:
623 r'''
624 Plot the intensity. Colormap with identical disk shape.
626 Parameters
627 ----------
628 intensity : np.array
629 Field intensity.
630 s
631 Default value 200. Disk size.
632 fs
633 Default value 20. Font size.
634 lims : List, default None
635 Colormap limits.
636 figsize : Tuple, default None
637 Figure size.
638 title : String, default '$|\psi|^2$'
639 Title.
641 Returns
642 -------
643 fig : Figure
644 '''
645 error_handling.empty_ndarray(self.sys.lat.coor, 'sys.get_lattice')
646 error_handling.ndarray(intensity, 'intensity', self.sys.lat.sites)
647 error_handling.positive_real(s, 's')
648 error_handling.positive_real(fs, 'fs')
649 error_handling.tuple_2elem(figsize, 'figsize')
650 error_handling.string(title, 'title')
651 fig, ax = plt.subplots(figsize=figsize)
652 plt.title(title, fontsize=fs+5)
653 map_red = plt.get_cmap('Reds')
654 if lims is None:
655 lims = (0., np.max(intensity))
656 y_ticks = ['0', 'max']
657 else:
658 y_ticks = [str(v) for v in lims]
659 plt.scatter(self.sys.lat.coor['x'], self.sys.lat.coor['y'], c=intensity, s=s,
660 cmap=map_red, vmin=lims[0], vmax=lims[1])
661 cbar = plt.colorbar(ticks=lims)
662 ax.set_xticks([])
663 ax.set_yticks([])
664 ax.set_xlim(np.min(self.sys.lat.coor['x'])-1., np.max(self.sys.lat.coor['x'])+1.)
665 ax.set_ylim(np.min(self.sys.lat.coor['y'])-1., np.max(self.sys.lat.coor['y'])+1.)
666 cbar.ax.set_yticklabels([y_ticks[0], y_ticks[1]])
667 cbar.ax.tick_params(labelsize=fs)
668 ax.set_aspect('equal')
669 fig.set_layout_engine('tight')
670 plt.draw()
671 return fig
673 def intensity_area(
674 self,
675 intensity: NDArray,
676 s: float = 1000.,
677 lw: float = 1.,
678 fs: float = 20.,
679 plt_hop: bool = False,
680 figsize: tuple[float, float] | None = None,
681 title: str = r'$|\psi|^2$',
682 ) -> Figure:
683 r'''
684 Plot the intensity. Intensity propotional to disk shape.
686 Parameters
687 ----------
688 intensity : np.array
689 Intensity.
690 s : Positive Float, default 1000
691 Circle size given by 100 * s * intensity.
692 lw : Positive Float, default 1
693 Hopping linewidths.
694 fs : Positive Float, default 20
695 Fontsize.
696 plt_hop : Boolean, default False
697 Plot hoppings.
698 figsize : Tuple, default None
699 Figure size.
700 title : String, default '$|\psi|^2$'
701 Figure title.
703 Returns
704 -------
705 fig : Figure
706 '''
707 error_handling.empty_ndarray(self.sys.lat.coor, 'sys.get_lattice')
708 error_handling.ndarray(intensity, 'intensity', self.sys.lat.sites)
709 error_handling.positive_real(s, 's')
710 error_handling.positive_real(fs, 'fs')
711 error_handling.boolean(plt_hop, 'plt_hop')
712 error_handling.tuple_2elem(figsize, 'figsize')
713 error_handling.string(title, 'title')
714 fig, ax = plt.subplots(figsize=figsize)
715 ax.set_xlabel('$i$', fontsize=fs)
716 ax.set_ylabel('$j$', fontsize=fs)
717 ax.set_title(title, fontsize=fs)
718 if plt_hop:
719 hop = self.sys.hop[~self.sys._wrapped(self.sys.hop['i'].astype(int),
720 self.sys.hop['j'].astype(int))]
721 plt.plot([self.sys.lat.coor['x'][hop['i'][:]],
722 self.sys.lat.coor['x'][hop['j'][:]]],
723 [self.sys.lat.coor['y'][hop['i'][:]],
724 self.sys.lat.coor['y'][hop['j'][:]]],
725 'k', lw=lw)
726 for tag, color in zip(self.sys.lat.tags, self.colors):
727 plt.scatter(self.sys.lat.coor['x'][self.sys.lat.coor['tag'] == tag],
728 self.sys.lat.coor['y'][self.sys.lat.coor['tag'] == tag],
729 s=100*s*intensity[self.sys.lat.coor['tag'] == tag],
730 c=color, alpha=0.5)
731 ax.set_aspect('equal')
732 ax.axis('off')
733 x_lim = (np.min(self.sys.lat.coor['x'])-2., np.max(self.sys.lat.coor['x'])+2.)
734 y_lim = (np.min(self.sys.lat.coor['y'])-2., np.max(self.sys.lat.coor['y'])+2.)
735 ax.set_xlim(x_lim)
736 ax.set_ylim(y_lim)
737 fig.set_layout_engine('tight')
738 plt.draw()
739 return fig
741 def butterfly(
742 self,
743 betas: NDArray,
744 butterfly: NDArray,
745 lw: float = 1.,
746 fs: float = 20.,
747 lims: tuple[float, float] | None = None,
748 title: str = '',
749 ) -> Figure:
750 '''
751 Plot energies depending on the strain (see
752 *GrapheneSystem.get_butterfly*). The energy levels plotted are the
753 ones lying in *lims* at the smallest strain.
755 Parameters
756 ----------
757 betas : np.array
758 Strain values, shape (N,).
759 butterfly : np.array
760 Eigenvalues, shape (N, sites).
761 lw : Positive Float, default 1
762 Linewidths.
763 fs : Positive Float, default 20
764 Fontsize.
765 lims : List, lims[0] energy min, lims[1] energy max
766 title
767 Default value ''. Figure title. If empty,
768 'Energies depending on strain'.
770 Returns
771 -------
772 fig : Figure
773 '''
774 error_handling.ndarray_empty(betas, 'betas')
775 error_handling.ndarray_empty(butterfly, 'butterfly')
776 error_handling.positive_real(lw, 'lw')
777 error_handling.positive_real(fs, 'fs')
778 error_handling.lims(lims)
779 error_handling.string(title, 'title')
780 i_beta_min = np.argmin(np.abs(betas))
781 if lims is None:
782 lims = (butterfly[i_beta_min, 0], butterfly[i_beta_min, -1])
783 ind_en = np.ravel(np.argwhere((butterfly[i_beta_min, :] > lims[0]) &
784 (butterfly[i_beta_min, :] < lims[1])))
785 fig, ax = plt.subplots()
786 plt.xlabel(r'$\beta/\beta_{max}$', fontsize=fs)
787 plt.ylabel('$E$', fontsize=fs)
788 ax.set_title(title if title else 'Energies depending on strain', fontsize=fs)
789 plt.yticks(np.arange(lims[0], lims[1]+1, (lims[1]-lims[0])/4), fontsize=fs)
790 plt.ylim(lims)
791 beta_max = np.max(np.abs(betas))
792 plt.xticks([-beta_max, -0.5*beta_max, 0,
793 0.5*beta_max, beta_max], fontsize=fs)
794 ax.set_xticklabels(('-1', '-1/2', '0', '1/2', '1'))
795 plt.xlim(betas[0], betas[-1])
796 for i in ind_en:
797 plt.plot(betas, butterfly[:, i], 'b', lw=lw)
798 fig.set_layout_engine('tight')
799 plt.draw()
800 return fig
802 def show(self) -> None:
803 """
804 Emulate Matplotlib method plt.show().
805 """
806 plt.show()
809# Backward-compatible lowercase alias (pre-0.2 API).
810plot = Plot