Skip to content

defectpl.plot

Plotter

Plotter()

Publication-quality static figure generator for DefectPL outputs.

Each method produces a single matplotlib figure and either displays it interactively (plot=True) or saves it at 600 dpi to out_dir (plot=False, the default used by :meth:~defectpl.defectpl.Photoluminescence.generate_plots).

All energy inputs follow the internal convention of eV; axis labels are converted to meV where appropriate for readability.

Methods:

Name Description
plot_penergy_vs_pmode

Phonon energy vs mode index (dispersionless Γ-point spectrum).

plot_ipr_vs_penergy

Phonon IPR vs phonon energy.

plot_loc_rat_vs_penergy

Localization ratio β_k = N·IPR_k vs phonon energy.

plot_qk_vs_penergy

Mode-projected displacement q_k vs phonon energy.

plot_HR_factor_vs_penergy

Partial Huang–Rhys factors S_k vs phonon energy.

plot_S_omega_vs_penergy

Continuous spectral density S(ω) vs phonon energy.

plot_S_omega_Sks_vs_penergy

S(ω) and S_k overlaid on dual y-axes.

plot_S_omega_Sks_Loc_rat_vs_penergy

S(ω) + S_k scatter coloured by localization ratio.

plot_S_omega_Sks_ipr_vs_penergy

S(ω) + S_k scatter coloured by IPR.

plot_intensity_vs_penergy

Normalised PL intensity spectrum vs photon energy.

Source code in defectpl\plot.py
def __init__(self):
    pass

plot_penergy_vs_pmode

plot_penergy_vs_pmode(
    frequencies,
    plot=False,
    out_dir="./",
    file_name="penergy_vs_pmode",
    fig_format="pdf",
    figsize=(3.3, 2.5),
)

Plot phonon energy (meV) vs mode index.

Parameters:

Name Type Description Default
frequencies (ndarray, shape(nmodes))

Phonon frequencies in eV.

required
plot bool

Show interactively instead of saving. Default False.

False
out_dir str or Path

Output directory. Default "./"

'./'
file_name str

Base file name (no extension). Default "penergy_vs_pmode".

'penergy_vs_pmode'
fig_format str

"pdf", "png", "svg", or "jpg". Default "pdf".

'pdf'
figsize tuple of float

Figure size in inches. Default (3.3, 2.5).

(3.3, 2.5)
Source code in defectpl\plot.py
def plot_penergy_vs_pmode(
    self,
    frequencies: np.ndarray,
    plot: bool = False,
    out_dir: Union[str, Path] = "./",
    file_name: str = "penergy_vs_pmode",
    fig_format: str = "pdf",
    figsize: Tuple[float, float] = (3.3, 2.5),
):
    """
    Plot phonon energy (meV) vs mode index.

    Parameters
    ----------
    frequencies : numpy.ndarray, shape (nmodes,)
        Phonon frequencies in **eV**.
    plot : bool, optional
        Show interactively instead of saving.  Default False.
    out_dir : str or Path, optional
        Output directory.  Default ``"./"``
    file_name : str, optional
        Base file name (no extension).  Default ``"penergy_vs_pmode"``.
    fig_format : str, optional
        ``"pdf"``, ``"png"``, ``"svg"``, or ``"jpg"``.  Default ``"pdf"``.
    figsize : tuple of float, optional
        Figure size in inches.  Default ``(3.3, 2.5)``.
    """
    fig, ax = plt.subplots(figsize=figsize)
    freq_mev = np.array(frequencies) * 1000.0
    mode_idx = np.arange(1, len(freq_mev) + 1)

    ax.plot(mode_idx, freq_mev, color="black")
    ax.set_xlabel("Phonon Mode Index")
    ax.set_ylabel("Phonon Energy (meV)")

    self._save_or_show(fig, out_dir, file_name, fig_format, plot)

plot_ipr_vs_penergy

plot_ipr_vs_penergy(
    frequencies,
    iprs,
    plot=False,
    out_dir="./",
    file_name="ipr_vs_penergy",
    fig_format="pdf",
    figsize=(3.3, 2.5),
)

Scatter plot of phonon IPR vs phonon energy (meV).

IPR = Σp²/(Σp)² ranges from 1/N (fully delocalized) to 1 (fully localized).

Parameters:

Name Type Description Default
frequencies (ndarray, shape(nmodes))

Phonon frequencies in eV.

required
iprs (ndarray, shape(nmodes))

Inverse participation ratios per mode.

required
plot bool

See :meth:plot_penergy_vs_pmode.

False
out_dir bool

See :meth:plot_penergy_vs_pmode.

False
file_name bool

See :meth:plot_penergy_vs_pmode.

False
fig_format bool

See :meth:plot_penergy_vs_pmode.

False
figsize bool

See :meth:plot_penergy_vs_pmode.

False
Source code in defectpl\plot.py
def plot_ipr_vs_penergy(
    self,
    frequencies: np.ndarray,
    iprs: np.ndarray,
    plot: bool = False,
    out_dir: Union[str, Path] = "./",
    file_name: str = "ipr_vs_penergy",
    fig_format: str = "pdf",
    figsize: Tuple[float, float] = (3.3, 2.5),
):
    """
    Scatter plot of phonon IPR vs phonon energy (meV).

    IPR = Σp²/(Σp)² ranges from 1/N (fully delocalized) to 1 (fully localized).

    Parameters
    ----------
    frequencies : numpy.ndarray, shape (nmodes,)
        Phonon frequencies in **eV**.
    iprs : numpy.ndarray, shape (nmodes,)
        Inverse participation ratios per mode.
    plot, out_dir, file_name, fig_format, figsize
        See :meth:`plot_penergy_vs_pmode`.
    """
    fig, ax = plt.subplots(figsize=figsize)
    freq_mev = np.array(frequencies) * 1000.0

    ax.scatter(freq_mev, iprs, edgecolor="black", alpha=0.85)
    ax.set_xlabel("Phonon Energy (meV)")
    ax.set_ylabel("IPR")

    self._save_or_show(fig, out_dir, file_name, fig_format, plot)

plot_loc_rat_vs_penergy

plot_loc_rat_vs_penergy(
    frequencies,
    localization_ratio,
    plot=False,
    out_dir="./",
    file_name="loc_rat_vs_penergy",
    fig_format="pdf",
    figsize=(3.3, 2.5),
)

Scatter plot of localization ratio β_k = N·IPR_k vs phonon energy (meV).

β = 1 means perfectly delocalized; β = N means fully localized on one atom.

Parameters:

Name Type Description Default
frequencies (ndarray, shape(nmodes))

Phonon frequencies in eV.

required
localization_ratio (ndarray, shape(nmodes))

Localization ratio per mode.

required
plot bool

See :meth:plot_penergy_vs_pmode.

False
out_dir bool

See :meth:plot_penergy_vs_pmode.

False
file_name bool

See :meth:plot_penergy_vs_pmode.

False
fig_format bool

See :meth:plot_penergy_vs_pmode.

False
figsize bool

See :meth:plot_penergy_vs_pmode.

False
Source code in defectpl\plot.py
def plot_loc_rat_vs_penergy(
    self,
    frequencies: np.ndarray,
    localization_ratio: np.ndarray,
    plot: bool = False,
    out_dir: Union[str, Path] = "./",
    file_name: str = "loc_rat_vs_penergy",
    fig_format: str = "pdf",
    figsize: Tuple[float, float] = (3.3, 2.5),
):
    """
    Scatter plot of localization ratio β_k = N·IPR_k vs phonon energy (meV).

    β = 1 means perfectly delocalized; β = N means fully localized on one atom.

    Parameters
    ----------
    frequencies : numpy.ndarray, shape (nmodes,)
        Phonon frequencies in **eV**.
    localization_ratio : numpy.ndarray, shape (nmodes,)
        Localization ratio per mode.
    plot, out_dir, file_name, fig_format, figsize
        See :meth:`plot_penergy_vs_pmode`.
    """
    fig, ax = plt.subplots(figsize=figsize)
    freq_mev = np.array(frequencies) * 1000.0

    ax.scatter(freq_mev, localization_ratio, edgecolor="black", alpha=0.85)
    ax.set_xlabel("Phonon Energy (meV)")
    ax.set_ylabel("Localization Ratio")

    self._save_or_show(fig, out_dir, file_name, fig_format, plot)

plot_qk_vs_penergy

plot_qk_vs_penergy(
    frequencies,
    qks,
    plot=False,
    out_dir="./",
    file_name="qk_vs_penergy",
    fig_format="pdf",
    figsize=(3.3, 2.5),
)

Scatter plot of mode-projected displacement q_k vs phonon energy (meV).

Parameters:

Name Type Description Default
frequencies (ndarray, shape(nmodes))

Phonon frequencies in eV.

required
qks (ndarray, shape(nmodes))

Mode configurational displacements in amu^(½)·Å.

required
plot bool

See :meth:plot_penergy_vs_pmode.

False
out_dir bool

See :meth:plot_penergy_vs_pmode.

False
file_name bool

See :meth:plot_penergy_vs_pmode.

False
fig_format bool

See :meth:plot_penergy_vs_pmode.

False
figsize bool

See :meth:plot_penergy_vs_pmode.

False
Source code in defectpl\plot.py
def plot_qk_vs_penergy(
    self,
    frequencies: np.ndarray,
    qks: np.ndarray,
    plot: bool = False,
    out_dir: Union[str, Path] = "./",
    file_name: str = "qk_vs_penergy",
    fig_format: str = "pdf",
    figsize: Tuple[float, float] = (3.3, 2.5),
):
    """
    Scatter plot of mode-projected displacement q_k vs phonon energy (meV).

    Parameters
    ----------
    frequencies : numpy.ndarray, shape (nmodes,)
        Phonon frequencies in **eV**.
    qks : numpy.ndarray, shape (nmodes,)
        Mode configurational displacements in amu^(1/2)·Å.
    plot, out_dir, file_name, fig_format, figsize
        See :meth:`plot_penergy_vs_pmode`.
    """
    fig, ax = plt.subplots(figsize=figsize)
    freq_mev = np.array(frequencies) * 1000.0

    ax.scatter(freq_mev, qks, edgecolor="black", alpha=0.85)
    ax.set_xlabel("Phonon Energy (meV)")
    ax.set_ylabel(r"Displacement $q_k$ ($\mathrm{amu}^{1/2}\cdot\mathrm{\AA}$)")

    self._save_or_show(fig, out_dir, file_name, fig_format, plot)

plot_HR_factor_vs_penergy

plot_HR_factor_vs_penergy(
    frequencies,
    Sks,
    plot=False,
    out_dir="./",
    file_name="HR_factor_vs_penergy",
    fig_format="pdf",
    figsize=(3.3, 2.5),
)

Scatter plot of partial Huang–Rhys factors S_k vs phonon energy (meV).

Parameters:

Name Type Description Default
frequencies (ndarray, shape(nmodes))

Phonon frequencies in eV.

required
Sks (ndarray, shape(nmodes))

Partial (mode-resolved) Huang–Rhys factors.

required
plot bool

See :meth:plot_penergy_vs_pmode.

False
out_dir bool

See :meth:plot_penergy_vs_pmode.

False
file_name bool

See :meth:plot_penergy_vs_pmode.

False
fig_format bool

See :meth:plot_penergy_vs_pmode.

False
figsize bool

See :meth:plot_penergy_vs_pmode.

False
Source code in defectpl\plot.py
def plot_HR_factor_vs_penergy(
    self,
    frequencies: np.ndarray,
    Sks: np.ndarray,
    plot: bool = False,
    out_dir: Union[str, Path] = "./",
    file_name: str = "HR_factor_vs_penergy",
    fig_format: str = "pdf",
    figsize: Tuple[float, float] = (3.3, 2.5),
):
    """
    Scatter plot of partial Huang–Rhys factors S_k vs phonon energy (meV).

    Parameters
    ----------
    frequencies : numpy.ndarray, shape (nmodes,)
        Phonon frequencies in **eV**.
    Sks : numpy.ndarray, shape (nmodes,)
        Partial (mode-resolved) Huang–Rhys factors.
    plot, out_dir, file_name, fig_format, figsize
        See :meth:`plot_penergy_vs_pmode`.
    """
    fig, ax = plt.subplots(figsize=figsize)
    freq_mev = np.array(frequencies) * 1000.0

    ax.scatter(freq_mev, Sks, edgecolor="black", alpha=0.85)
    ax.set_xlabel("Phonon Energy (meV)")
    ax.set_ylabel(r"Partial HR Factor ($S_k$)")

    self._save_or_show(fig, out_dir, file_name, fig_format, plot)

plot_S_omega_vs_penergy

plot_S_omega_vs_penergy(
    frequencies,
    S_omega,
    omega_range,
    plot=False,
    out_dir="./",
    file_name="S_omega_vs_penergy",
    max_freq=None,
    fig_format="pdf",
    figsize=(3.3, 2.5),
)

Line plot of the continuous Huang–Rhys spectral density S(ω) in 1/meV vs energy (meV).

S(ω) is the phonon sideband weight per unit energy; its integral equals the total Huang–Rhys factor S.

Parameters:

Name Type Description Default
frequencies (ndarray, shape(nmodes))

Phonon frequencies in eV (used to set x-axis upper limit).

required
S_omega (array - like, shape(n_grid))

Spectral density in eV^(-1).

required
omega_range list[ω_min, ω_max, n_points]

Energy grid parameters in eV matching the S(ω) array.

required
max_freq float

Upper frequency cut-off for the plot in eV.

None
plot bool

See :meth:plot_penergy_vs_pmode.

False
out_dir bool

See :meth:plot_penergy_vs_pmode.

False
file_name bool

See :meth:plot_penergy_vs_pmode.

False
fig_format bool

See :meth:plot_penergy_vs_pmode.

False
figsize bool

See :meth:plot_penergy_vs_pmode.

False
Source code in defectpl\plot.py
def plot_S_omega_vs_penergy(
    self,
    frequencies: np.ndarray,
    S_omega: Union[list, np.ndarray],
    omega_range: List[Union[int, float]],
    plot: bool = False,
    out_dir: Union[str, Path] = "./",
    file_name: str = "S_omega_vs_penergy",
    max_freq: Optional[float] = None,
    fig_format: str = "pdf",
    figsize: Tuple[float, float] = (3.3, 2.5),
):
    """
    Line plot of the continuous Huang–Rhys spectral density S(ω) in 1/meV vs energy (meV).

    S(ω) is the phonon sideband weight per unit energy; its integral equals
    the total Huang–Rhys factor S.

    Parameters
    ----------
    frequencies : numpy.ndarray, shape (nmodes,)
        Phonon frequencies in **eV** (used to set x-axis upper limit).
    S_omega : array-like, shape (n_grid,)
        Spectral density in **eV^(-1)**.
    omega_range : list [ω_min, ω_max, n_points]
        Energy grid parameters in **eV** matching the S(ω) array.
    max_freq : float, optional
        Upper frequency cut-off for the plot in **eV**.
    plot, out_dir, file_name, fig_format, figsize
        See :meth:`plot_penergy_vs_pmode`.
    """
    fig, ax = plt.subplots(figsize=figsize)
    omega_set = np.linspace(omega_range[0], omega_range[1], int(omega_range[2]))

    cutoff = max_freq if max_freq is not None else float(max(frequencies))
    mask = omega_set <= cutoff

    S_omega_mev = np.array(S_omega)[mask] / 1000.0
    energies_mev = omega_set[mask] * 1000.0

    ax.plot(energies_mev, S_omega_mev, color="black")
    ax.set_xlabel("Phonon Energy (meV)")
    ax.set_ylabel(r"$S(\hbar\omega)$ ($1/\mathrm{meV}$)")
    ax.set_xlim(0, cutoff * 1000.0)

    self._save_or_show(fig, out_dir, file_name, fig_format, plot)

plot_S_omega_Sks_vs_penergy

plot_S_omega_Sks_vs_penergy(
    frequencies,
    S_omega,
    omega_range,
    Sks,
    plot=False,
    out_dir="./",
    file_name="S_omega_Sks_vs_penergy",
    max_freq=None,
    fig_format="pdf",
    figsize=(3.5, 2.5),
)

Dual-axis plot of S(ω) (left axis) and partial S_k scatter (right axis).

Parameters:

Name Type Description Default
frequencies ndarray

See :meth:plot_S_omega_vs_penergy.

required
S_omega ndarray

See :meth:plot_S_omega_vs_penergy.

required
omega_range ndarray

See :meth:plot_S_omega_vs_penergy.

required
Sks (ndarray, shape(nmodes))

Partial Huang–Rhys factors.

required
max_freq float

Upper frequency cut-off in eV.

None
plot bool

See :meth:plot_penergy_vs_pmode.

False
out_dir bool

See :meth:plot_penergy_vs_pmode.

False
file_name bool

See :meth:plot_penergy_vs_pmode.

False
fig_format bool

See :meth:plot_penergy_vs_pmode.

False
figsize bool

See :meth:plot_penergy_vs_pmode.

False
Source code in defectpl\plot.py
def plot_S_omega_Sks_vs_penergy(
    self,
    frequencies: np.ndarray,
    S_omega: Union[list, np.ndarray],
    omega_range: List[Union[int, float]],
    Sks: np.ndarray,
    plot: bool = False,
    out_dir: Union[str, Path] = "./",
    file_name: str = "S_omega_Sks_vs_penergy",
    max_freq: Optional[float] = None,
    fig_format: str = "pdf",
    figsize: Tuple[float, float] = (3.5, 2.5),
):
    """
    Dual-axis plot of S(ω) (left axis) and partial S_k scatter (right axis).

    Parameters
    ----------
    frequencies, S_omega, omega_range
        See :meth:`plot_S_omega_vs_penergy`.
    Sks : numpy.ndarray, shape (nmodes,)
        Partial Huang–Rhys factors.
    max_freq : float, optional
        Upper frequency cut-off in **eV**.
    plot, out_dir, file_name, fig_format, figsize
        See :meth:`plot_penergy_vs_pmode`.
    """
    fig, ax1 = plt.subplots(figsize=figsize)
    omega_set = np.linspace(omega_range[0], omega_range[1], int(omega_range[2]))

    cutoff = max_freq if max_freq is not None else float(max(frequencies))
    mask = omega_set <= cutoff

    # Pull standard colors directly from cycler layout
    colors = plt.rcParams["axes.prop_cycle"].by_key()["color"]
    c1, c2 = colors[2], colors[0]  # Safe default color indices mapping

    ax1.set_xlabel("Phonon Energy (meV)")
    ax1.set_ylabel(r"$S(\hbar\omega)$ ($1/\mathrm{meV}$)", color=c1)
    ax1.plot(omega_set[mask] * 1000.0, np.array(S_omega)[mask] / 1000.0, color=c1)
    ax1.tick_params(axis="y", labelcolor=c1)

    ax2 = ax1.twinx()
    ax2.set_ylabel(r"Partial HR Factor ($S_k$)", color=c2)
    ax2.scatter(
        np.array(frequencies) * 1000.0, Sks, color=c2, edgecolor="black", alpha=0.85
    )
    ax2.tick_params(axis="y", labelcolor=c2)

    ax1.set_xlim(0, cutoff * 1000.0)

    self._save_or_show(fig, out_dir, file_name, fig_format, plot)

plot_S_omega_Sks_Loc_rat_vs_penergy

plot_S_omega_Sks_Loc_rat_vs_penergy(
    frequencies,
    S_omega,
    omega_range,
    Sks,
    localization_ratio,
    plot=False,
    out_dir="./",
    file_name="S_omega_HRf_loc_rat_vs_penergy",
    max_freq=None,
    pylim=[None, None],
    fig_format="pdf",
    figsize=(4.2, 2.5),
    cmap="viridis",
)

S(ω) line + S_k scatter coloured by localization ratio β_k.

Identifies phonon modes that simultaneously carry large HR weight and are localized near the defect.

Parameters:

Name Type Description Default
frequencies ndarray

See :meth:plot_S_omega_vs_penergy.

required
S_omega ndarray

See :meth:plot_S_omega_vs_penergy.

required
omega_range ndarray

See :meth:plot_S_omega_vs_penergy.

required
Sks (ndarray, shape(nmodes))

Partial Huang–Rhys factors (right y-axis).

required
localization_ratio (ndarray, shape(nmodes))

Colour-code values β_k = N·IPR_k.

required
pylim list of [float or None, float or None]

[ymin, ymax] for the right (S_k) axis.

[None, None]
cmap str

Matplotlib colormap name. Default "viridis".

'viridis'
plot bool

See :meth:plot_penergy_vs_pmode.

False
out_dir bool

See :meth:plot_penergy_vs_pmode.

False
file_name bool

See :meth:plot_penergy_vs_pmode.

False
fig_format bool

See :meth:plot_penergy_vs_pmode.

False
figsize bool

See :meth:plot_penergy_vs_pmode.

False
Source code in defectpl\plot.py
def plot_S_omega_Sks_Loc_rat_vs_penergy(
    self,
    frequencies: np.ndarray,
    S_omega: Union[list, np.ndarray],
    omega_range: List[Union[int, float]],
    Sks: np.ndarray,
    localization_ratio: np.ndarray,
    plot: bool = False,
    out_dir: Union[str, Path] = "./",
    file_name: str = "S_omega_HRf_loc_rat_vs_penergy",
    max_freq: Optional[float] = None,
    pylim: List[Optional[float]] = [None, None],
    fig_format: str = "pdf",
    figsize: Tuple[float, float] = (4.2, 2.5),
    cmap: str = "viridis",
):
    """
    S(ω) line + S_k scatter coloured by localization ratio β_k.

    Identifies phonon modes that simultaneously carry large HR weight *and*
    are localized near the defect.

    Parameters
    ----------
    frequencies, S_omega, omega_range
        See :meth:`plot_S_omega_vs_penergy`.
    Sks : numpy.ndarray, shape (nmodes,)
        Partial Huang–Rhys factors (right y-axis).
    localization_ratio : numpy.ndarray, shape (nmodes,)
        Colour-code values β_k = N·IPR_k.
    pylim : list of [float or None, float or None], optional
        ``[ymin, ymax]`` for the right (S_k) axis.
    cmap : str, optional
        Matplotlib colormap name.  Default ``"viridis"``.
    plot, out_dir, file_name, fig_format, figsize
        See :meth:`plot_penergy_vs_pmode`.
    """
    # FIX: Explicitly set layout="constrained" to cleanly handle twinx + colorbar spacing
    fig, ax1 = plt.subplots(figsize=figsize, layout="constrained")
    omega_set = np.linspace(omega_range[0], omega_range[1], int(omega_range[2]))

    cutoff = max_freq if max_freq is not None else float(max(frequencies))
    mask = omega_set <= cutoff

    ax1.set_xlabel("Phonon Energy (meV)")
    ax1.set_ylabel(r"$S(\hbar\omega)$ ($1/\mathrm{meV}$)", color="black")
    ax1.plot(
        omega_set[mask] * 1000.0, np.array(S_omega)[mask] / 1000.0, color="black"
    )
    ax1.tick_params(axis="y", labelcolor="black")

    ax2 = ax1.twinx()
    ax2.set_ylabel(r"Partial HR Factor ($S_k$)", color="black")

    sc = ax2.scatter(
        np.array(frequencies) * 1000.0,
        Sks,
        c=localization_ratio,
        cmap=plt.get_cmap(cmap),
        edgecolor="black",
        alpha=0.85,
    )
    ax2.tick_params(axis="y", labelcolor="black")
    if pylim[0] is not None or pylim[1] is not None:
        ax2.set_ylim(pylim[0], pylim[1])

    ax1.set_xlim(0, cutoff * 1000.0)

    # When using layout="constrained", we can target ax2 directly with an explicit pad
    cbar = fig.colorbar(sc, ax=ax2, pad=0.12)
    cbar.set_label("Localization Ratio")

    self._save_or_show(fig, out_dir, file_name, fig_format, plot)

plot_S_omega_Sks_ipr_vs_penergy

plot_S_omega_Sks_ipr_vs_penergy(
    frequencies,
    S_omega,
    omega_range,
    Sks,
    iprs,
    plot=False,
    out_dir="./",
    file_name="S_omega_HRf_ipr_vs_penergy",
    max_freq=None,
    fig_format="pdf",
    figsize=(4.2, 2.5),
    cmap="viridis",
)

S(ω) line + S_k scatter coloured by phonon IPR.

Parameters:

Name Type Description Default
frequencies ndarray

See :meth:plot_S_omega_vs_penergy.

required
S_omega ndarray

See :meth:plot_S_omega_vs_penergy.

required
omega_range ndarray

See :meth:plot_S_omega_vs_penergy.

required
Sks (ndarray, shape(nmodes))

Partial Huang–Rhys factors (right y-axis).

required
iprs (ndarray, shape(nmodes))

Phonon inverse participation ratios used as colour code.

required
cmap str

Matplotlib colormap name. Default "viridis".

'viridis'
plot bool

See :meth:plot_penergy_vs_pmode.

False
out_dir bool

See :meth:plot_penergy_vs_pmode.

False
file_name bool

See :meth:plot_penergy_vs_pmode.

False
fig_format bool

See :meth:plot_penergy_vs_pmode.

False
figsize bool

See :meth:plot_penergy_vs_pmode.

False
Source code in defectpl\plot.py
def plot_S_omega_Sks_ipr_vs_penergy(
    self,
    frequencies: np.ndarray,
    S_omega: Union[list, np.ndarray],
    omega_range: List[Union[int, float]],
    Sks: np.ndarray,
    iprs: np.ndarray,
    plot: bool = False,
    out_dir: Union[str, Path] = "./",
    file_name: str = "S_omega_HRf_ipr_vs_penergy",
    max_freq: Optional[float] = None,
    fig_format: str = "pdf",
    figsize: Tuple[float, float] = (4.2, 2.5),
    cmap: str = "viridis",
):
    """
    S(ω) line + S_k scatter coloured by phonon IPR.

    Parameters
    ----------
    frequencies, S_omega, omega_range
        See :meth:`plot_S_omega_vs_penergy`.
    Sks : numpy.ndarray, shape (nmodes,)
        Partial Huang–Rhys factors (right y-axis).
    iprs : numpy.ndarray, shape (nmodes,)
        Phonon inverse participation ratios used as colour code.
    cmap : str, optional
        Matplotlib colormap name.  Default ``"viridis"``.
    plot, out_dir, file_name, fig_format, figsize
        See :meth:`plot_penergy_vs_pmode`.
    """
    # FIX: Explicitly set layout="constrained" to cleanly handle twinx + colorbar spacing
    fig, ax1 = plt.subplots(figsize=figsize, layout="constrained")
    omega_set = np.linspace(omega_range[0], omega_range[1], int(omega_range[2]))

    cutoff = max_freq if max_freq is not None else float(max(frequencies))
    mask = omega_set <= cutoff

    ax1.set_xlabel("Phonon Energy (meV)")
    ax1.set_ylabel(r"$S(\hbar\omega)$ ($1/\mathrm{meV}$)", color="black")
    ax1.plot(
        omega_set[mask] * 1000.0, np.array(S_omega)[mask] / 1000.0, color="black"
    )
    ax1.tick_params(axis="y", labelcolor="black")

    ax2 = ax1.twinx()
    ax2.set_ylabel(r"Partial HR Factor ($S_k$)", color="black")

    sc = ax2.scatter(
        np.array(frequencies) * 1000.0,
        Sks,
        c=iprs,
        cmap=plt.get_cmap(cmap),
        edgecolor="black",
        alpha=0.85,
    )
    ax2.tick_params(axis="y", labelcolor="black")
    ax1.set_xlim(0, cutoff * 1000.0)

    # When using layout="constrained", we can target ax2 directly with an explicit pad
    cbar = fig.colorbar(sc, ax=ax2, pad=0.12)
    cbar.set_label("Inverse Participation Ratio")

    self._save_or_show(fig, out_dir, file_name, fig_format, plot)

plot_intensity_vs_penergy

plot_intensity_vs_penergy(
    frequencies,
    I,
    resolution,
    xlim,
    plot=False,
    out_dir="./",
    file_name="intensity_vs_penergy",
    iylim=None,
    fig_format="pdf",
    figsize=(3.3, 2.5),
)

Line plot of the normalised PL intensity spectrum vs photon energy (eV).

Parameters:

Name Type Description Default
frequencies ndarray

Phonon frequencies in eV (unused directly; kept for API consistency).

required
I ndarray

Complex or real intensity array from :func:~defectpl.utils.calc_Spectrum_Intensity. Absolute value is taken and the result is normalised to its maximum.

required
resolution int

Number of grid points per eV; sets the energy-axis scale.

required
xlim tuple of float

(x_min, x_max) for the photon energy axis in eV.

required
iylim tuple of float

(y_min, y_max) for the intensity axis.

None
plot bool

See :meth:plot_penergy_vs_pmode.

False
out_dir bool

See :meth:plot_penergy_vs_pmode.

False
file_name bool

See :meth:plot_penergy_vs_pmode.

False
fig_format bool

See :meth:plot_penergy_vs_pmode.

False
figsize bool

See :meth:plot_penergy_vs_pmode.

False
Source code in defectpl\plot.py
def plot_intensity_vs_penergy(
    self,
    frequencies: np.ndarray,
    I: np.ndarray,
    resolution: int,
    xlim: Tuple[float, float],
    plot: bool = False,
    out_dir: Union[str, Path] = "./",
    file_name: str = "intensity_vs_penergy",
    iylim: Optional[Tuple[float, float]] = None,
    fig_format: str = "pdf",
    figsize: Tuple[float, float] = (3.3, 2.5),
):
    """
    Line plot of the normalised PL intensity spectrum vs photon energy (eV).

    Parameters
    ----------
    frequencies : numpy.ndarray
        Phonon frequencies in eV (unused directly; kept for API consistency).
    I : numpy.ndarray
        Complex or real intensity array from :func:`~defectpl.utils.calc_Spectrum_Intensity`.
        Absolute value is taken and the result is normalised to its maximum.
    resolution : int
        Number of grid points per eV; sets the energy-axis scale.
    xlim : tuple of float
        ``(x_min, x_max)`` for the photon energy axis in eV.
    iylim : tuple of float, optional
        ``(y_min, y_max)`` for the intensity axis.
    plot, out_dir, file_name, fig_format, figsize
        See :meth:`plot_penergy_vs_pmode`.
    """
    fig, ax = plt.subplots(figsize=figsize)

    x_energy_ev = np.arange(len(I)) / float(resolution)
    I_abs = np.abs(I)
    I_norm = I_abs / np.max(I_abs) if np.max(I_abs) > 0 else I_abs

    ax.plot(x_energy_ev, I_norm, color="black")
    ax.set_ylabel("PL Intensity (arb. u.)")
    ax.set_xlabel("Photon Energy (eV)")
    ax.set_xlim(xlim[0], xlim[1])

    if iylim:
        ax.set_ylim(iylim[0], iylim[1])
    ax.set_yticks([])  # Clean look for publication spectra

    self._save_or_show(fig, out_dir, file_name, fig_format, plot)