#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Plotting functions for defect calculations
"""
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import pandas as pd
from .defects import Defect, format_legend_with_charge_number, get_defect_from_string
[docs]
def plot_binding_energies(entries,
vbm,
band_gap,
temperature=0,
names=None,
xlim=None,
ylim=None,
figsize=(6,6),
fontsize=None,
colors=None,
format_legend=True,
ax=None,
**eform_kwargs):
"""
Plot binding energies for complex of defects as a function of the fermi level
Parameters
----------
entries : list
List of entries to calculate.
vbm : float
Valence band maximum in eV.
band_gap : float
Band gap of bulk material in eV.
temperature : float
Temperature in K. If no custom formation energy is provided, this arg has no effect.
names : list
List of strings with names of DefectEntry. If None, all defect complexes are plotted.
xlim : tuple
Tuple giving the range of the x (fermi energy) axis
ylim : tuple
Tuple giving the range for the formation energy axis
figsize : tuple
Figure size.
fontsize : float
Font size.
colors : list
List of colors for line plot.
format_legend : bool
Bool for getting latex-like legend based on the name of defect entries.
ax : matplotlib.axes.Axes
Axis to plot into. If None, a new figure and axis are created.
eform_kwargs : dict
Kwargs to pass to `entry.formation_energy`.
Returns
-------
matplotlib.axes.Axes
"""
ax = _get_ax(ax, figsize=figsize)
from .analysis import DefectsAnalysis
da = DefectsAnalysis(entries=entries,band_gap=band_gap,vbm=vbm,sort_entries=False)
if xlim is None:
xlim = (-0.5, da.band_gap + 0.5)
ef = np.arange(xlim[0], xlim[1] + 0.1, (xlim[1] - xlim[0]) / 200)
binding_energy = np.zeros(len(ef))
if not names:
names = []
for e in da.entries:
if e.defect_type == 'DefectComplex' and e.name not in names:
names.append(e.name)
if not names:
raise ValueError('No DefectComplex entries found')
for idx, name in enumerate(names):
label = da.select_entries(names=[name])[0].symbol if format_legend else name
for i in range(len(ef)):
binding_energy[i] = da.binding_energy(
name=name,
fermi_level=ef[i],
temperature=temperature,
**eform_kwargs)
color = colors[idx] if colors else None
ax.plot(ef, binding_energy,
linewidth=2.5*(figsize[1]/figsize[0]),
label=label,
color=color)
ax.axvline(x=0.0, linestyle='-', color='k', linewidth=2)
ax.axvline(x=da.band_gap, linestyle='-', color='k', linewidth=2)
ax.axvspan(xlim[0], 0, facecolor='k', alpha=0.2)
ax.axvspan(da.band_gap, xlim[1], facecolor='k', alpha=0.2)
ax.hlines(0, xlim[0], xlim[1], colors='k', linestyles='dashed', alpha=0.5)
ax.set_xlim(xlim)
if ylim:
ax.set_ylim(ylim)
ax.set_xlabel('Fermi level (eV)')
ax.set_ylabel('Binding energy (eV)')
_style_ax(ax=ax, fontsize=fontsize, legend=True, grid=False)
return ax
[docs]
def plot_charge_transition_levels(entries,
vbm,
band_gap,
temperature=0,
ylim=None,
figsize=(6,6),
fontsize=None,
colors=None,
fermi_level=None,
format_legend=True,
get_integers=True,
ax=None,
**eform_kwargs):
"""
Plotter for the charge transition levels.
Parameters
----------
entries : list
List of entries to calculate.
vbm : float
Valence band maximum in eV.
band_gap : float
Band gap of bulk material in eV.
temperature : float
Temperature in K. If no custom formation energy is provided, this arg has no effect.
ylim : tuple
y-axis limits.
figsize : tuple
Figure size.
fontsize : float
Font size.
colors : list or str
Colors for CTL lines and charge labels. Provide a string to use the same color for all species.
fermi_level : float
Plot Fermi energy position.
format_legend : bool
Bool for getting latex-like legend based on the name of defect entries.
get_integers : bool
Get charge transition levels as integers.
ax : matplotlib.axes.Axes
Axis to plot into. If None, a new figure and axis are created.
eform_kwargs : dict
Kwargs to pass to `entry.formation_energy`.
Returns
-------
matplotlib.axes.Axes
"""
from .analysis import DefectsAnalysis
ax = _get_ax(ax, figsize=figsize)
da = DefectsAnalysis(entries=entries,band_gap=band_gap,vbm=vbm,sort_entries=False)
default_colors = matplotlib.color_sequences['tab10'] + \
matplotlib.color_sequences['tab20'] + \
matplotlib.color_sequences['Pastel1']
if type(colors) == str:
colors = [colors] * len(default_colors)
elif not colors:
colors = default_colors
if ylim == None:
ylim = (-0.5,da.band_gap +0.5)
charge_transition_levels = da.charge_transition_levels(
temperature=temperature,
entries=entries,
get_integers=get_integers,
**eform_kwargs)
number_defects = len(charge_transition_levels)
x_max = 10
interval = x_max/(number_defects + 1)
x = np.arange(0,x_max,interval)
x_ticks_positions = []
for i in range(0,len(x)-1):
x_ticks_positions.append((x[i+1]-x[i])/2 + x[i])
x_ticks_labels = []
for name in charge_transition_levels:
x_ticks_labels.append(name)
for i in x:
ax.axvline(x=i, linestyle='-', color='k', linewidth=1.2, alpha=1, zorder=1)
xlim = (x[0],x[-1])
ax.axhspan(ylim[0], 0, facecolor='grey', alpha=0.5, zorder=2)
ax.axhspan(da.band_gap,ylim[1], facecolor = 'grey', alpha=0.5, zorder=2)
for i in range(0,len(x_ticks_labels)):
name = x_ticks_labels[i]
color = colors[i] if colors else 'black'
for ctl in charge_transition_levels[name]:
energy = ctl[2]
ax.hlines(energy,x[i],x[i+1],colors=color,linewidth=2.25, zorder=3)
charge1 = '+' + str(ctl[1]) if ctl[1] > 0 else str(ctl[1])
charge2 = '+' + str(ctl[0]) if ctl[0] > 0 else str(ctl[0])
label_charge = '(' + charge2 + '/' + charge1 + ')'
font_space = abs(ylim[1]-ylim[0]) / 100
if energy < ylim[1] and energy > ylim[0]:
ax.text(
x[i]+(interval/2)*2/number_defects,
energy+font_space,
label_charge,
fontsize=fontsize,
color=color)
if format_legend:
for name in x_ticks_labels:
x_ticks_labels[x_ticks_labels.index(name)] = get_defect_from_string(name).symbol
if fermi_level:
ax.axhline(y=fermi_level, linestyle='dashed', color='k', linewidth=1.5, label='$\\mu _{e}$')
ax.text(x[-1]-0.75,-0.3,'VB',fontsize=25*(fontsize/16))
ax.text(x[-1]-0.75,da.band_gap+0.2,'CB',fontsize=25*(fontsize/16))
ax.set_xticks(x_ticks_positions)
ax.set_xticklabels(x_ticks_labels,fontsize=(25-number_defects)*(fontsize/16))
ax.tick_params(axis='x',length=0,width=0)
ax.tick_params(axis='y',labelsize=16*(fontsize/16))
ax.set_xlim(xlim)
ax.set_ylim(ylim)
ax.set_ylabel('Energy(eV)',fontsize=20*(fontsize/16))
_style_ax(ax=ax, fontsize=fontsize, legend=False, grid=False)
return ax
[docs]
def plot_pO2_vs_concentrations(
thermodata,
output='total',
figsize=(8,8),
fontsize=22,
xlim=(1e-20,1e10),
ylim=None,
colors=None,
ax=None,
**kwargs):
"""
Plot defect and carrier concentrations in a range of oxygen partial pressure.
Parameters
----------
thermodata: ThermoData
ThermoData object that contains the thermodynamic data:
partial_pressures : (list)
list with partial pressure values.
defect_concentrations : (list or dict)
Defect concentrations in the same format as the output of DefectsAnalysis.
carrier_concentrations : (list)
List of tuples with intrinsic carriers concentrations (holes,electrons).
output : str
Type of output for defect concentrations:
- "all": The output is the concentration of every defect entry.
- "stable": The output is the concentration of the stable charge for every defect at each fermi level point.
- "total": The output is the sum of the concentration in every charge for each specie.
figsize : tuple
Size of the matplotlib figure.
fontsize : float
Size of font for matplotlib rcParams.
xlim : tuple
Range of x-axis.
ylim : tuple
Range of y-axis.
colors : list
List of colors to use for plotting with matplotlib. If None the defaults are used.
ax : matplotlib.axes.Axes
Axis to plot into. If None, a new figure and axis are created.
kwargs : dict
Kwargs to pass to `DefectConcentrations.filter_concentrations(**kwargs)`.
If provided, only the filtered concentrations will be plotted. If output
is set to "total", only the filtered concentrations will be used to
compute the total concentration.
Returns
-------
matplotlib.axes.Axes
"""
td = thermodata
p,dc,cc = td.partial_pressures,td.defect_concentrations,td.carrier_concentrations
xlabel = 'Oxygen partial pressure (atm)'
ax = plot_x_vs_concentrations(
x=p,
xlabel=xlabel,
defect_concentrations=dc,
carrier_concentrations=cc,
output=output,
figsize=figsize,
fontsize=fontsize,
xlim=xlim,
ylim=ylim,
colors=colors,
ax=ax,
**kwargs)
ax.set_xscale('log')
return ax
[docs]
def plot_pO2_vs_conductivity(
partial_pressures,
conductivities,
label=None,
figsize=(8,8),
fontsize=22,
xlim=(1e-20,1e10),
ylim=None,
ax=None):
"""
Plot conductivity as a function of the oxygen partial pressure.
Parameters
----------
partial_pressures : list
list with partial pressure values.
conductivities : dict or list
If is a dict multiples lines will be plotted, with labels as keys and conductivity list
as values. If is a list only one line is plotted with label taken from the "label" argument.
label : str
Label for the data.
figsize : tuple
Size of the matplotlib figure.
fontsize : float
Size of font for matplotlib rcParams.
xlim : tuple
Range of x-axis.
ylim : tuple
Range of y-axis.
ax : matplotlib.axes.Axes
Axis to plot into. If None, a new figure and axis are created.
Returns
-------
matplotlib.axes.Axes
"""
xlabel = 'Oxygen partial pressure (atm)'
ax = plot_x_vs_conductivity(
x=partial_pressures,
xlabel=xlabel,
conductivities=conductivities,
label=label,
figsize=figsize,
fontsize=fontsize,
xlim=xlim,
ylim=ylim,
ax=ax)
ax.set_xscale('log')
return ax
[docs]
def plot_pO2_vs_fermi_level(
partial_pressures,
fermi_levels,
band_gap,
label=None,
figsize=(8,8),
fontsize=22,
xlim=(1e-20,1e10),
ylim=None,
colors=None,
ax=None):
"""
Plot Fermi level as a function of the oxygen partial pressure.
Parameters
----------
partial_pressures : list
list with partial pressure values.
fermi_levels : dict or list
If is a dict multiples lines will be plotted, with labels as keys and fermi level list
as values. If is a list only one line is plotted with label taken from the "label" argument.
band_gap : float
Band gap of the bulk material.
label : str
Label for the data.
figsize : tuple
Size of the matplotlib figure.
fontsize : float
Size of font for matplotlib rcParams.
xlim : tuple
Range of x-axis.
ylim : tuple
Range of y-axis.
colors : list
List with colors for Fermi level data.
ax : matplotlib.axes.Axes
Axis to plot into. If None, a new figure and axis are created.
Returns
-------
matplotlib.axes.Axes
"""
xlabel = 'Oxygen partial pressure (atm)'
ax = plot_x_vs_fermi_level(
x=partial_pressures,
xlabel=xlabel,
fermi_levels=fermi_levels,
band_gap=band_gap,
label=label,
figsize=figsize,
fontsize=fontsize,
xlim=xlim,
ylim=ylim,
colors=colors,
ax=ax)
ax.set_xscale('log')
return ax
[docs]
def plot_variable_species_vs_concentrations(
thermodata,
output='total',
figsize=(8,8),
fontsize=22,
xlim=(1e-20,1e10),
ylim=None,
colors=None,
ax=None,
**kwargs):
"""
Plot defect and carrier concentrations in a range of oxygen partial pressure.
Parameters
----------
thermodata: ThermoData
ThermoData object that contains the thermodynamic data:
partial_pressures : (list)
list with partial pressure values.
defect_concentrations : (list or dict)
Defect concentrations in the same format as the output of DefectsAnalysis.
carrier_concentrations : (list)
List of tuples with intrinsic carriers concentrations (holes,electrons).
output : str
Type of output for defect concentrations:
- "all": The output is the concentration of every defect entry.
- "stable": The output is the concentration of the stable charge for every defect at each fermi level point.
- "total": The output is the sum of the concentration in every charge for each specie.
figsize : tuple
Size of the matplotlib figure.
fontsize : float
Size of font for matplotlib rcParams.
xlim : tuple
Range of x-axis.
ylim : tuple
Range of y-axis.
colors : list
List of colors to use for plotting with matplotlib. If None the defaults are used.
ax : matplotlib.axes.Axes
Axis to plot into. If None, a new figure and axis are created.
kwargs : dict
Kwargs to pass to `DefectConcentrations.filter_concentrations(**kwargs)`.
If provided, only the filtered concentrations will be plotted. If output
is set to "total", only the filtered concentrations will be used to
compute the total concentration.
Returns
-------
matplotlib.axes.Axes
"""
td = thermodata
c,dc,cc = td.variable_concentrations,td.defect_concentrations,td.carrier_concentrations
dname = _get_variable_defect_specie_label(td.variable_defect_specie)
xlabel = '[%s] (cm$^{-3})$' %dname
ax = plot_x_vs_concentrations(
x=c,
xlabel=xlabel,
defect_concentrations=dc,
carrier_concentrations=cc,
output=output,
figsize=figsize,
fontsize=fontsize,
xlim=xlim,
ylim=ylim,
colors=colors,
ax=ax,
**kwargs)
ax.set_xscale('log')
return ax
[docs]
def plot_variable_species_vs_conductivity(
xlabel,
variable_concentrations,
conductivities,
label=None,
figsize=(8,8),
fontsize=22,
xlim=(1e-20,1e10),
ylim=None,
ax=None):
"""
Plot conductivity as a function of the oxygen partial pressure.
Parameters
----------
xlabel : str
Label for concentration axis (cm^-3 is added).
variable_concentrations : list
List of concentrations of variable species.
conductivities : dict or list
If is a dict multiples lines will be plotted, with labels as keys and conductivity list
as values. If is a list only one line is plotted with label taken from the "label" argument.
label : str
Label for the data.
figsize : tuple
Size of the matplotlib figure.
fontsize : float
Size of font for matplotlib rcParams.
xlim : tuple
Range of x-axis.
ylim : tuple
Range of y-axis.
ax : matplotlib.axes.Axes
Axis to plot into. If None, a new figure and axis are created.
Returns
-------
matplotlib.axes.Axes
"""
xlabel = '%s (cm$^{-3})$' %xlabel
ax = plot_x_vs_conductivity(
x=variable_concentrations,
xlabel=xlabel,
conductivities=conductivities,
label=label,
figsize=figsize,
fontsize=fontsize,
xlim=xlim,
ylim=ylim,
ax=ax)
ax.set_xscale('log')
return ax
[docs]
def plot_variable_species_vs_fermi_level(
xlabel,
variable_concentrations,
fermi_levels,
band_gap,
label=None,
figsize=(8,8),
fontsize=22,
xlim=(1e-20,1e10),
ylim=None,
colors=None,
ax=None):
"""
Plot Fermi level as a function of the oxygen partial pressure.
Parameters
----------
xlabel : str
Label for concentration axis (cm^-3 is added).
variable_concentrations : list
List of concentrations of variable species.
fermi_levels : dict or list
If is a dict multiples lines will be plotted, with labels as keys and fermi level list
as values. If is a list only one line is plotted with label taken from the "label" argument.
band_gap : float
Band gap of the bulk material.
label : str
Label for the data.
figsize : tuple
Size of the matplotlib figure.
fontsize : float
Size of font for matplotlib rcParams.
xlim : tuple
Range of x-axis.
ylim : tuple
Range of y-axis.
colors : list
List with colors for Fermi level data.
ax : matplotlib.axes.Axes
Axis to plot into. If None, a new figure and axis are created.
Returns
-------
matplotlib.axes.Axes
"""
xlabel = '[%s] (cm$^{-3})$' %xlabel
ax = plot_x_vs_fermi_level(
x=variable_concentrations,
xlabel=xlabel,
fermi_levels=fermi_levels,
band_gap=band_gap,
label=label,
figsize=figsize,
fontsize=fontsize,
xlim=xlim,
ylim=ylim,
colors=colors,
ax=ax)
ax.set_xscale('log')
return ax
[docs]
def plot_x_vs_concentrations(
x,
xlabel,
defect_concentrations,
carrier_concentrations,
output='total',
figsize=(8,8),
fontsize=14,
xlim=(1e-20,1e10),
ylim=None,
colors=None,
ax=None,
**kwargs):
"""
Plot defect concentrations as a function of generic data on the x-axis.
Parameters
----------
x : list
List with data on x-axis.
xlabel : str
Label for x-axis.
defect_concentrations : list
List of DefectConcentrations objects.
carrier_concentrations : list
List of tuples with carrier concentrations (holes,electrons).
output : str
Type of output for defect concentrations:
- "all": The output is the concentration of every defect entry.
- "stable": The output is the concentration of the stable charge for every defect at each fermi level point.
- "total": The output is the sum of the concentration in every charge for each specie.
figsize : tuple
Size of the matplotlib figure.
fontsize : float
Size of font for matplotlib rcParams.
xlim : tuple
Range of x-axis.
ylim : tuple
Range of y-axis.
colors : list
List of colors to use for plotting with matplotlib. If None the defaults are used.
ax : matplotlib.axes.Axes
Axis to plot into. If None, a new figure and axis are created.
kwargs : dict
Kwargs to pass to `DefectConcentrations.filter_concentrations(**kwargs)`.
If provided, only the filtered concentrations will be plotted. If output
is set to "total", only the filtered concentrations will be used to
compute the total concentration.
Returns
-------
matplotlib.axes.Axes
"""
ax = _get_ax(ax,figsize=figsize)
if output == 'all' or output == 'stable':
ax = _plot_conc(
x=x,
defect_concentrations=defect_concentrations,
carrier_concentrations=carrier_concentrations,
output=output,figsize=figsize,colors=colors,
ax=ax,**kwargs)
elif output == 'total':
ax = _plot_conc_total(
x=x,
defect_concentrations=defect_concentrations,
carrier_concentrations=carrier_concentrations,
figsize=figsize,colors=colors,ax=ax,**kwargs)
else:
raise ValueError('The options for plot output are "all", "stable" or "total".')
ax.set_yscale('log')
ax.set_xlim(xlim)
if ylim:
ax.set_ylim(ylim)
ax.set_xlabel(xlabel)
ax.set_ylabel('Concentrations (cm$^{-3})$')
_style_ax(ax=ax,fontsize=fontsize)
return ax
[docs]
def plot_x_vs_conductivity(
x,
xlabel,
conductivities,
label=None,
figsize=(8,8),
fontsize=22,
xlim=(1e-20,1e10),
ylim=None,
ax=None):
"""
Plot conductivity as a function of the oxygen partial pressure.
Parameters
----------
x : list
List with data on x-axis.
xlabel : str
Label for x-axis.
conductivities : dict or list
If is a dict multiples lines will be plotted, with labels as keys and conductivity list
as values. If is a list only one line is plotted with label taken from the "label" argument.
label : str
Label for the data.
figsize : tuple
Size of the matplotlib figure.
fontsize : float
Size of font for matplotlib rcParams.
xlim : tuple
Range of x-axis.
ylim : tuple
Range of y-axis.
ax : matplotlib.axes.Axes
Axis to plot into. If None, a new figure and axis are created.
Returns
-------
matplotlib.axes.Axes
"""
ax = _get_ax(ax, figsize=figsize)
if isinstance(conductivities,dict):
for name,sigma in conductivities.items():
ax.plot(x,sigma,linewidth=4,marker='s',label=name)
else:
sigma = conductivities
ax.plot(x,sigma,linewidth=4,marker='s',label=label)
ax.set_yscale('log')
ax.set_xlim(xlim)
if ylim:
ax.set_ylim(ylim)
ax.set_xlabel(xlabel)
ax.set_ylabel('Conductivity (S/m)')
legend = True if isinstance(conductivities, dict) else False
_style_ax(ax=ax, fontsize=fontsize, legend=legend, grid=False)
return ax
[docs]
def plot_x_vs_fermi_level(
x,
xlabel,
fermi_levels,
band_gap,
label=None,
figsize=(8,8),
fontsize=20,
xlim=(1e-20,1e10),
ylim=None,
colors=None,
ax=None):
"""
Parameters
----------
x : list
List with data on x-axis.
xlabel : str
Label for x-axis.
fermi_levels : dict or list
If is a dict multiples lines will be plotted, with labels as keys and fermi level list
as values. If is a list only one line is plotted with label taken from the "label" argument.
band_gap : float
Band gap of the bulk material.
label : str
Label for the data.
figsize : tuple
Size of the matplotlib figure.
fontsize : float
Size of font for matplotlib rcParams.
xlim : tuple
Range of x-axis.
ylim : tuple
Range of y-axis.
colors : list,
List with colors for Fermi level data.
ax : matplotlib.axes.Axes
Axis to plot into. If None, a new figure and axis are created.
Returns
-------
matplotlib.axes.Axes
"""
ax = _get_ax(ax, figsize=figsize)
ylim = ylim if ylim else (-0.5, band_gap+0.5)
if isinstance(fermi_levels, dict):
for name, mue in fermi_levels.items():
clr = colors[list(fermi_levels.keys()).index(name)] if colors else None
ax.plot(x, mue, linewidth=4, label=name, color=clr)
else:
mue = fermi_levels
clr = colors[0] if colors else None
ax.plot(x, mue, linewidth=4, label=label, color=clr)
ax.set_xlim(xlim)
if ylim:
ax.set_ylim(ylim)
ax.hlines(0, xlim[0], xlim[1], color='k')
ax.text(xlim[1] + (xlim[1]-xlim[0]), -0.05, 'VB',fontsize=fontsize*1.1)
ax.text(xlim[1] + (xlim[1]-xlim[0]), band_gap - 0.05, 'CB',fontsize=fontsize*1.1)
ax.hlines(band_gap, xlim[0], xlim[1], color='k')
ax.axhspan(ylim[0], 0, alpha=0.2, color='k')
ax.axhspan(band_gap, ylim[1], alpha=0.2, color='k')
ax.set_xlabel(xlabel)
ax.set_ylabel('Electron chemical potential (eV)')
legend = True if isinstance(fermi_levels, dict) else False
_style_ax(ax, fontsize=fontsize, grid=False, legend=legend)
return ax
def _get_variable_defect_specie_label(variable_defect_specie):
try:
defect = get_defect_from_string(variable_defect_specie)
return defect.symbol
except:
return variable_defect_specie
def _plot_conc(
x,
defect_concentrations,
carrier_concentrations,
output,
figsize,
colors,
ax,
**kwargs):
width, height = ax.figure.get_size_inches()
dc = defect_concentrations if output != 'stable' else [c.stable for c in defect_concentrations]
if kwargs:
dc = [c.filter_concentrations(**kwargs) for c in dc] #filter concentrations based on kwargs
h = [cr[0] for cr in carrier_concentrations]
n = [cr[1] for cr in carrier_concentrations]
previous_charge = None
for i in range(0,len(dc[0])):
conc = [c[i].conc for c in dc]
charges = [c[i].charge for c in dc]
try:
label_txt = get_defect_from_string(dc[0][i].name).symbol
except:
label_txt = dc[0][i].name
if output == 'all':
label_txt = format_legend_with_charge_number(label_txt,dc[0][i].charge)
elif output == 'stable':
for q in charges:
if q != previous_charge:
previous_charge = q
label_charge = '+' + str(int(q)) if q > 0 else str(int(q))
index = charges.index(q)
ax.text(x[index],conc[index],label_charge,clip_on=True,fontsize=width*2.5)
color = colors[i] if colors else None
ax.plot(x,conc,label=label_txt,linewidth=4,color=color)
ax.plot(x,h,label='$n_{h}$',linestyle='--',color='r',linewidth=4)
ax.plot(x,n,label='$n_{e}$',linestyle='--',color='b',linewidth=4)
return ax
def _plot_conc_total(
x,
defect_concentrations,
carrier_concentrations,
figsize,
colors,
ax,
**kwargs):
dc = defect_concentrations
if kwargs:
dc = [c.filter_concentrations(**kwargs) for c in dc]
h = [cr[0] for cr in carrier_concentrations]
n = [cr[1] for cr in carrier_concentrations]
for name in dc[0].names:
conc = [c.total[name] for c in dc]
try:
label_txt = get_defect_from_string(name).symbol
except:
label_txt = name
color = colors[dc[0].names.index(name)] if colors else None
ax.plot(x,conc,label=label_txt,linewidth=4,color=color)
ax.plot(x,h,label='$n_{h}$',linestyle='--',color='r',linewidth=4)
ax.plot(x,n,label='$n_{e}$',linestyle='--',color='b',linewidth=4)
return ax
def _get_unstable_bool(defect_concentrations):
slist = []
for dc in defect_concentrations:
unstable = False
for d in dc:
if 'stable' in vars(d).keys() and d.stable == False:
unstable = True
slist.append(unstable)
return slist
def _get_ax(ax=None, **fig_kwargs):
if ax is None:
_, ax = plt.subplots(**fig_kwargs)
return ax
def _style_ax(ax, fontsize=None, legend=True, grid=True):
if fontsize is not None:
ax.set_xlabel(ax.get_xlabel(), fontsize=fontsize)
ax.set_ylabel(ax.get_ylabel(), fontsize=fontsize)
ax.tick_params(axis='both', labelsize=fontsize*0.9)
if legend:
ax.legend(fontsize=fontsize*0.9)
else:
if legend:
ax.legend()
if grid:
ax.grid()
return