LCOV - code coverage report
Current view: top level - src/pairinteraction/visualization - plot_functions.py (source / functions) Hit Total Coverage
Test: coverage.info Lines: 8 35 22.9 %
Date: 2026-08-14 15:26:44 Functions: 0 1 0.0 %

          Line data    Source code
       1             : # SPDX-FileCopyrightText: 2025 PairInteraction Developers
       2             : # SPDX-License-Identifier: LGPL-3.0-or-later
       3           1 : from __future__ import annotations
       4             : 
       5           1 : from typing import TYPE_CHECKING
       6             : 
       7           1 : import matplotlib as mpl
       8           1 : import matplotlib.pyplot as plt
       9           1 : import numpy as np
      10             : 
      11           1 : from pairinteraction.ket.ket_pair import KetPair, is_ket_atom_tuple
      12           1 : from pairinteraction.visualization.colormaps import alphamagma
      13             : 
      14             : if TYPE_CHECKING:
      15             :     from collections.abc import Sequence
      16             : 
      17             :     from matplotlib.axes import Axes
      18             :     from matplotlib.figure import Figure
      19             : 
      20             :     from pairinteraction.ket.ket_pair import KetPairLike
      21             :     from pairinteraction.system.system_pair import SystemPair
      22             :     from pairinteraction.units import NDArray
      23             : 
      24             : 
      25           1 : def plot_pair_potential(
      26             :     system_pairs: Sequence[SystemPair],
      27             :     ket_pair_of_interest: KetPairLike,
      28             :     ax: Axes | None = None,
      29             : ) -> tuple[Figure, Axes]:
      30             :     """Plot the pair potential of a sequence of SystemPair objects.
      31             : 
      32             :     Args:
      33             :         system_pairs: A sequence of SystemPair objects to plot.
      34             :         ket_pair_of_interest: The KetPair (or tuple of KetAtom) for whicht the overlaps will be plotted.
      35             :         ax: An optional matplotlib Axes object to plot on.
      36             :             If None, a new figure and axes will be created.
      37             : 
      38             :     """
      39           0 :     distances: NDArray = np.array([system.get_distance(unit="micrometer") for system in system_pairs])
      40             : 
      41           0 :     if is_ket_atom_tuple(ket_pair_of_interest):
      42           0 :         energy_of_interest = sum(ket.get_energy(unit="GHz") for ket in ket_pair_of_interest)
      43           0 :     elif isinstance(ket_pair_of_interest, KetPair):
      44           0 :         energy_of_interest = ket_pair_of_interest.get_energy(unit="GHz")
      45             :     else:
      46           0 :         raise TypeError("ket_pair_of_interest must be a KetPair or a tuple of KetAtom.")
      47             : 
      48           0 :     eigenenergies = [system.get_eigenenergies(unit="GHz") - energy_of_interest for system in system_pairs]
      49           0 :     overlaps = [system.get_eigenbasis().get_overlaps(ket_pair_of_interest) for system in system_pairs]
      50             : 
      51           0 :     if ax is None:
      52           0 :         owns_ax = True
      53           0 :         fig, ax = plt.subplots()
      54             :     else:
      55           0 :         owns_ax = False
      56           0 :         fig = ax.figure  # type: ignore[assignment]
      57             : 
      58           0 :     lw = mpl.rcParams["lines.linewidth"]
      59           0 :     ax.plot(distances, np.array(eigenenergies), c="k", lw=lw / 6, zorder=-10)
      60             : 
      61           0 :     x_repeated = np.hstack([val * np.ones_like(es) for val, es in zip(distances, eigenenergies, strict=True)])
      62           0 :     energies_flattend = np.hstack(eigenenergies)
      63           0 :     overlaps_flattend = np.hstack(overlaps)
      64           0 :     sorter = np.argsort(overlaps_flattend)
      65             : 
      66           0 :     ms = mpl.rcParams["lines.markersize"]
      67           0 :     scat = ax.scatter(
      68             :         x_repeated[sorter],
      69             :         energies_flattend[sorter],
      70             :         c=overlaps_flattend[sorter],
      71             :         s=ms * 2.5,
      72             :         vmin=0,
      73             :         vmax=1,
      74             :         cmap=alphamagma,
      75             :     )
      76             : 
      77           0 :     if owns_ax:
      78           0 :         ax.set_xlabel(r"Distance ($\mu$m)")
      79           0 :         ax.set_ylabel(r"Energy (h$\cdot$GHz)")
      80           0 :         fig.colorbar(scat, ax=ax, label="Overlap with state of interest")
      81           0 :         fig.tight_layout()
      82             : 
      83           0 :     return fig, ax

Generated by: LCOV version 1.16