Source code for mlfompy.plots
"""
============
Plots module
============
Auxiliar functions used in other modules
"""
import matplotlib.pyplot as plt
import numpy as np
from pathlib import Path
from . import auxiliar as aux
import seaborn as sns
import scipy.stats
import matplotlib.colors
from matplotlib.lines import Line2D
from scipy import interpolate
import torch
from sklearn.metrics import mean_squared_error
[docs]
def __fom_method_selector(fds, fom, method):
""" Auxiliar function to select the figure of merit method
Parameters
----------
fds: MLFoMpyDataset
Path to store the json file with the FoMs and statistics
fom: str
Figure of merit to plot, accepted values: ['vth','ioff','ss','ion_dd', 'ion_mc']
method: str
Extraction method used for vth, accepted values: ['SD','CC','LE']
Extraction method used for ioff: ['VG']
Extraction method used for ss: ['VGI']
Extraction method used for ion_dd: ['VG']
Extraction method used for ion_mc: ['VG']
"""
method = 'LE' if (fom == 'vth' and method == None) else method
if fom == 'ioff':
method = 'VG'
figure_of_merit = np.log10(fds.figure_of_merit[fom][method]['values'])
if fom == 'ion_dd' or fom == 'ion_mc':
method = 'VG'
figure_of_merit = fds.figure_of_merit[fom][method]['values']
if fom == 'ss':
method = 'VGI'
figure_of_merit = fds.figure_of_merit[fom][method]['values']
if fom == 'vth' and method == 'LE':
figure_of_merit = fds.figure_of_merit[fom][method]['values']
if fom == 'vth' and method != 'LE':
figure_of_merit = fds.figure_of_merit[fom][method]['values']
return method, figure_of_merit
[docs]
def hist(fds, fom, method = None):
"""Plots the histogram with the method defined.
The mean and the standard deviation are also shown together
with the gaussian density function. By default method=None is assigned to the LE.
Parameters
----------
fds: MLFoMpyDataset
Path to store the json file with the FoMs and statistics
fom: str
Figure of merit to plot, accepted values: ['vth','ioff','ss','ion_dd', 'ion_mc']
method: str
- Extraction method used for vth, accepted values: ['SD','CC','LE']
- Extraction method used for ioff: ['VG']
- Extraction method used for ss: ['VGI']
- Extraction method used for ion_dd: ['VG']
- Extraction method used for ion_mc: ['VG']
"""
method, figure_of_merit = __fom_method_selector(fds, fom, method)
mean = fds.figure_of_merit[fom][method]['stats']['mean']
stdev = fds.figure_of_merit[fom][method]['stats']['stdev']
units_values = fds.figure_of_merit[fom][method]['units']
units_stats = fds.figure_of_merit[fom][method]['stats']['units']
_, bins, _ = plt.hist(figure_of_merit, 'fd',density=True, edgecolor='b',facecolor='y', hatch='/', alpha=0.6)
y = ((1 / (np.sqrt(2 * np.pi) * stdev)) *np.exp(-0.5 * (1 / stdev * (bins - mean))**2))
plt.plot(bins, y, '--', color='red', linewidth=2)
plt.axvline(mean,color="black", linestyle="-", linewidth=2)
plt.axvline(mean-stdev,color="black", linestyle="-.", linewidth=1.5)
plt.axvline(mean+stdev,color="black", linestyle="-.", linewidth=1.5)
plt.xlabel(f'{fom} [{units_values}]',fontsize='xx-large')
plt.title(f'{method} method:\n \u03BC= {mean:.3e} {units_stats} \u03C3={stdev:.3e} {units_stats} ',fontsize='xx-large',family='sans-serif')
plt.legend(['Density function', '\u03BC','\u03BC-\u03C3','\u03BC+\u03C3'], fontsize='x-large')
plt.tick_params(axis='both', which='major', labelsize='x-large')
plt.tight_layout()
plt.savefig(Path(fds.device_path,f'hist_gauss_{fom}_{method}.png'), dpi=300)
plt.close()
aux.print_aux(f'--Output file--\nhist_{fom}_{method}.png file stored in {fds.device_path} ')
[docs]
def hist_kde(fds, fom, method=None):
"""Plots the histogram with the method defined.
The mean and the standard deviation are also shown together
with the kernel density function. By default method=None is assigned to the LE.
Parameters
----------
fds: MLFoMpyDataset
Path to store the json file with the FoMs and statistics
fom: str
Figure of merit to plot, accepted values: ['vth','ioff','ss','ion_dd', 'ion_mc']
method: str
- Extraction method used for vth, accepted values: ['SD','CC','LE']
- Extraction method used for ioff: ['VG']
- Extraction method used for ss: ['VGI']
- Extraction method used for ion_dd: ['VG']
- Extraction method used for ion_mc: ['VG']
"""
method, figure_of_merit = __fom_method_selector(fds, fom, method)
units = fds.figure_of_merit[fom][method]['units']
# Figure definition
fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(1, 1, 1)
# Histogram of figure_of_merit
sns.histplot(data=figure_of_merit, stat='count', kde=True, linewidth=2)
# Calculate mean and standard deviation
figure_of_merit_no_nans = np.array(figure_of_merit)[~np.isnan(np.array(figure_of_merit))]
mean = sum(figure_of_merit_no_nans) / len(figure_of_merit_no_nans)
std = (sum((x - mean) ** 2 for x in figure_of_merit_no_nans) / len(figure_of_merit_no_nans)) ** 0.5
# TODO: KDE TO THE LEGEND
if fom == 'ion_dd':
mean = float(format(mean, '.2e'))
std = float(format(std, '.2e'))
else:
mean = np.round(mean, 2)
std = np.round(std, 2)
# Add mean and standard deviation indicators
plt.axvline(mean, color='red', linestyle='-', label=r'$\mu=$'+f'{mean} {units}', linewidth=2)
plt.axvline(mean + std, color='green', linestyle='--', label=r'$\mu$ + $\sigma$, '+r'$\sigma=$'+f'{std} {units}', linewidth=2)
plt.axvline(mean - std, color='green', linestyle='--', label=r'$\mu$ - $\sigma$', linewidth=2)
ax.set_ylabel('Count', fontsize=20)
# X label depending on the fom and method
if fom == 'vth' and method is not None:
ax.set_xlabel(rf'{fom} {method} [{units}]', fontsize=20)
elif fom == 'ioff':
ax.set_xlabel(rf'$log_{{{10}}}${fom} [{units}]', fontsize=20)
else:
ax.set_xlabel(rf'{fom} [{units}]', fontsize=20)
ax.tick_params(axis='both', which='major', labelsize=20)
plt.legend(fontsize=20)
plt.tight_layout()
# Store figure
plt.savefig(Path(fds.device_path,f'hist_kde_{fom}_{method}.png'), dpi=300)
plt.close()
# Output message
aux.print_aux(f'--Output file--\nhist_kde_{fom}_{method}.png file stored in {fds.device_path} ')
[docs]
def fom_correlation(fds, fom1, fom2, method1=None, method2=None):
"""Scatter plots with histograms to show correlation between FoMs.
For Vth by default method=None is assigned to the LE.
Parameters
----------
fds: MLFoMpyDataset
Path to store the json file with the FoMs and statistics
fom1: str
Y-Axis Figure of merit to plot, accepted values: ['vth','ioff','ss','ion_dd', 'ion_mc']
method1: str
- Extraction method used for vth, accepted values: ['SD','CC','LE']
- Extraction method used for ioff: ['VG']
- Extraction method used for ss: ['VGI']
- Extraction method used for ion_dd: ['VG']
- Extraction method used for ion_mc: ['VG']
fom2: str
X-Axis Figure of merit to plot, accepted values: ['vth','ioff','ss','ion_dd', 'ion_mc']
method2: str
- Extraction method used for vth, accepted values: ['SD','CC','LE']
- Extraction method used for ioff: ['VG']
- Extraction method used for ss: ['VGI']
- Extraction method used for ion_dd: ['VG']
- Extraction method used for ion_mc: ['VG']
"""
method1, y = __fom_method_selector(fds, fom1, method1)
method2, x = __fom_method_selector(fds, fom2, method2)
units1 = fds.figure_of_merit[fom1][method1]['units']
units2 = fds.figure_of_merit[fom2][method2]['units']
# Calculate the point density
xy = np.vstack([x, y])
xy = xy[:, ~np.isnan(xy).any(axis=0)]
z = scipy.stats.gaussian_kde(xy)(xy)
# Create a colormap for the scatterplot points
colormap = matplotlib.colors.ListedColormap(sns.color_palette("summer", n_colors=256).as_hex())
# Create a Seaborn JointGrid with the scatter plot and histograms
g = sns.JointGrid(x=xy[0], y=xy[1], space=0)
# Plot the data
g.ax_joint.scatter(xy[0], xy[1], c=z, cmap=colormap, edgecolor="none")
g.plot_marginals(sns.histplot, color=".5")
g.ax_joint.tick_params(labelsize=20)
xlabel = rf'$log_{{{10}}}${fom2} [{units2}]' if fom2 == 'ioff' else rf'{fom2} {method2 if fom2 == "vth" else ""} [{units2}]'
ylabel = rf'$log_{{{10}}}${fom1} [{units1}]' if fom1 == 'ioff' else rf'{fom1} {method1 if fom1 == "vth" else ""} [{units1}]'
# Output message
g.set_axis_labels(xlabel=xlabel, ylabel=ylabel, fontsize=20)
plt.tight_layout()
plt.savefig(Path(fds.device_path,f'correlation_{fom1}_{method1}_{fom2}_{method2}.png'), dpi=300)
plt.close()
aux.print_aux(f'--Output file--\ncorrelation_{fom1}_{method1}_{fom2}_{method2}.png file stored in {fds.device_path} ')
[docs]
def extraction_vth_sd_plot(fds, curve_number):
""" Plot for SD vth extraction method
Parameters
----------
fds: MLFoMpy dataset
curve_number: float
Number of simulation curve to plot
"""
v_gate, i_drain = aux.iv_curve_dd_filter(fds, curve_number) # Removes the presimulation data (increase of Vd)
quartic_interpol, x_interp, _ = aux.iv_interpolation(fds, v_gate, i_drain)
fd = quartic_interpol.derivative(n=1)
sd = quartic_interpol.derivative(n=2)
upper_limit = x_interp[np.argmax(fd(x_interp))]
x_filter = x_interp[np.where(x_interp<upper_limit)]
vth_sd = round(x_interp[np.argmax(sd(x_filter))],3)
# Definición figura
fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(1, 1, 1)
# Duplicar ejes
ax2 = ax.twinx()
# PLOT
lns1 = ax.plot(x_interp, quartic_interpol(x_interp), linewidth=3, color='tab:green', label=r'$I_D$-$V_G$')
lns2 = ax2.plot(x_interp,sd(x_interp), color='tab:orange',linewidth=3, label='SD')
lns3 = ax2.plot(vth_sd, sd(vth_sd),'o',ms=15, color='tab:orange', label='SD max')
ax.axvline(vth_sd, linestyle='--',linewidth=3,color='k')
# Axis labels + format
ax.set_ylim(ymin=0.0)
ax.set_xlim(xmin=0.0)
ax.set_ylabel(r'$\sqrt{I_D}[A]$', fontsize=20, color='green')
ax2.set_ylabel(r'$\mathrm{d}^2 \sqrt{I_D}/\mathrm{d} V_G^2$ (SD)', fontsize=20, color='darkorange')
ax.set_xlabel(r'V$_G[V]$', fontsize=20)
ax.tick_params(axis='x', which='major', labelsize=20)
ax.tick_params(axis='y', which='major', labelsize=20, labelcolor='green')
ax2.tick_params(axis='y', which='major', labelsize=20, labelcolor='darkorange')
ax.ticklabel_format(style='scientific', axis='y', scilimits=(-3, -3),useMathText=True)
ax2.ticklabel_format(style='scientific', axis='y', scilimits=(-3, -3),useMathText=True)
ax.yaxis.offsetText.set_fontsize(20)
ax2.yaxis.offsetText.set_fontsize(20)
# Arrow Vth
arrow_text = r'$V_{th}^{SD}=$'+f'{vth_sd}'+r'$V$'
arrow_x = vth_sd
arrow_y = 0
arrow_props = dict(color='k')
ax.annotate(arrow_text, xy=(arrow_x, arrow_y), xytext=(arrow_x+0.3*v_gate[-1], arrow_y+0.1*i_drain[-1]**0.5), fontsize=20,
arrowprops=arrow_props, ha='center')
# Combine legends
lns = lns1 + lns2 + lns3
labs = [l.get_label() for l in lns]
plt.legend(lns, labs, loc=1, fontsize=20)
ax.grid()
fig.patch.set_facecolor('white')
plt.tight_layout()
plt.savefig(Path(fds.device_path,f'vth_sd_method.png'),dpi=400)
plt.close()
aux.print_aux(f'--Output file--\nvth_sd_method.png file stored in {fds.device_path} ')
[docs]
def extraction_vth_le_plot(fds, curve_number):
""" Plot for LE vth extraction method
Parameters
----------
fds: MLFoMpy dataset
curve_number: float
Number of simulation curve to plot
"""
v_gate, i_drain = aux.iv_curve_dd_filter(fds, curve_number) # Removes the presimulation data (increase of Vd)
quartic_interpol, x_interp, _ = aux.iv_interpolation(fds, v_gate, i_drain)
first_derivative = quartic_interpol.derivative(n=1) # n is the derivative order
idx = x_interp[np.argmax(first_derivative(x_interp))]
m_tan = first_derivative(idx)
vth_le = round(idx-quartic_interpol(idx)/m_tan, 3)
# Definición figura
fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(1, 1, 1)
# Duplicar ejes
ax2 = ax.twinx()
# Plots
lns1 = ax.plot(x_interp, quartic_interpol(x_interp),linewidth=3, color='tab:green',label=r'$I_D$-$V_G$')
lns2 = ax2.plot(x_interp, first_derivative(x_interp),linewidth=3, color='tab:orange', label='FD')
lns3 = ax2.plot(idx, first_derivative(idx),'o',ms=15, color='tab:orange', label='FD max')
lns4 = ax.plot(idx, quartic_interpol(idx),'o',ms=15, color='tab:green', label=r'$I_D$(FD max)')
lns5 = ax.plot(x_interp, m_tan*(x_interp-vth_le), linewidth=3, color='k', linestyle='--', label='LE')
ax.plot([idx, idx], [quartic_interpol(idx), first_derivative(idx)] ,linestyle='-.',linewidth=2, color='tab:grey')
# Axis labels + format
ax.set_ylim(ymin=0.0)
ax.set_xlim(xmin=0.0)
ax.set_ylabel(r'$\sqrt{I_D}[A]$', fontsize=20, color='green')
ax2.set_ylabel(r'$\mathrm{d} \sqrt{I_D}/\mathrm{d} V_G$ (FD)', fontsize=20, color='darkorange')
ax.set_xlabel(r'V$_G[V]$', fontsize=20)
ax.tick_params(axis='x', which='major', labelsize=20)
ax.tick_params(axis='y', which='major', labelsize=20, labelcolor='green')
ax2.tick_params(axis='y', which='major', labelsize=20, labelcolor='darkorange')
ax.ticklabel_format(style='scientific', axis='y', scilimits=(-3, -3),useMathText=True)
ax2.ticklabel_format(style='scientific', axis='y', scilimits=(-3, -3),useMathText=True)
ax.yaxis.offsetText.set_fontsize(20)
ax2.yaxis.offsetText.set_fontsize(20)
# Arrow Vth
arrow_text = r'$V_{Th}^{le}=$'+f'{round(vth_le,4)}'+r'$V$'
arrow_x = vth_le
arrow_y = 0
arrow_props = dict(color='k')
ax.annotate(arrow_text, xy=(arrow_x, arrow_y), xytext=(arrow_x+0.3*v_gate[-1], arrow_y+0.1*i_drain[-1]**0.5), fontsize=20,
arrowprops=arrow_props, ha='center')
# Legends
lns = lns1 + lns2 + lns3 + lns4 + lns5
labs = [l.get_label() for l in lns]
plt.legend(lns, labs, loc=1, fontsize=20)
ax.grid()
plt.tight_layout()
fig.patch.set_facecolor('white')
plt.savefig(Path(fds.device_path,f'vth_le_method.png'),dpi=400)
plt.close()
aux.print_aux(f'--Output file--\nvth_le_method.png file stored in {fds.device_path} ')
[docs]
def extraction_vth_cc_plot(fds, curve_number):
""" Plot for CC vth extraction method
Parameters
----------
fds: MLFoMpy dataset
curve_number: float
Number of simulation curve to plot
"""
v_gate, i_drain = aux.iv_curve_dd_filter(fds, curve_number) # Removes the presimulation data (increase of Vd)
cc_criteria = 2.2e-7
y_cc_criteria = [i-cc_criteria for i in i_drain]
x_interp, delta_x_interp = np.linspace(v_gate[0], v_gate[-1], 400, retstep=True)
cubic_interpol = interpolate.UnivariateSpline(v_gate, i_drain, s=0, k=3)
diff_curves = interpolate.UnivariateSpline(v_gate, y_cc_criteria, s=0, k=3)
vth_cc = diff_curves.roots()[0]
#PLOT
fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(1, 1, 1)
ax.set_yscale('log')
ax.plot(x_interp, cubic_interpol(x_interp),linewidth=3, color='tab:green')
ax.axhline(cc_criteria, color='tab:orange', linestyle='-', linewidth=3)
ax.plot(vth_cc, cubic_interpol(vth_cc),'o',ms=15, color='tab:orange')
ax.plot([vth_cc, vth_cc], [cubic_interpol(0.0), cubic_interpol(vth_cc)], linestyle='--', color='k', linewidth=3)
ax.set_ylim(ymin=i_drain[0])
ax.set_xlim(xmin=0.0)
ax.legend([r'$I_D$-$V_G$',r'$I_{D}^{CC}$',r'Intersection point'],fontsize=20, loc='upper left', bbox_to_anchor=(0.4, 0.8))
ax.set_ylabel(r'$I_D[A]$', fontsize=20)
ax.set_xlabel(r'V$_G[V]$', fontsize=20)
ax.tick_params(axis='both', which='major', labelsize=20)
# Arrow Vth
arrow_text = r'$V_{Th}^{cc}=$'+f'{round(vth_cc,3)}'+r'$V$'
arrow_x = vth_cc
arrow_y = i_drain[0]
arrow_props = dict(color='k')
ax.annotate(arrow_text, xy=(arrow_x, arrow_y), xytext=(arrow_x+0.3*v_gate[-1], arrow_y+i_drain[1]), fontsize=20,
arrowprops=arrow_props, ha='center')
plt.grid()
plt.tight_layout()
fig.patch.set_facecolor('white')
plt.savefig(Path(fds.device_path,f'vth_cc_method.png'),dpi=400)
plt.close()
aux.print_aux(f'--Output file--\nvth_cc_method.png file stored in {fds.device_path} ')
[docs]
def extraction_ioff_plot(fds, curve_number):
""" Plot for Ioff extraction method
Parameters
----------
fds: MLFoMpy dataset
curve_number: float
Number of simulation curve to plot
"""
v_gate, i_drain = aux.iv_curve_dd_filter(fds, curve_number) # Removes the presimulation data (increase of Vd)
x_interp, delta_x_interp = np.linspace(v_gate[0], v_gate[-1], retstep=True)
cubic_interpol = interpolate.UnivariateSpline(v_gate, i_drain, s=0, k=3)
ioff = float(cubic_interpol(0.0))
#PLOT
fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(1, 1, 1)
ax.plot(x_interp, cubic_interpol(x_interp),linewidth=3, color='tab:green')
ax.set_xlim(xmin=0.0)
ax.legend([r'$I_D$-$V_G$'], fontsize=20, loc=0)
ax.set_ylabel(r'$I_D[A]$', fontsize=20)
ax.set_xlabel(r'V$_G[V]$', fontsize=20)
ax.set_yscale('log')
ax.tick_params(axis='both', which='major', labelsize=20)
# Arrow Vth
arrow_text = r'$I_{off}=$'+f'{"{:.2e}".format(ioff)}'+r' $A$'
arrow_x = 0
arrow_y = ioff
arrow_props = dict(color='k')
ax.annotate(arrow_text, xy=(arrow_x, arrow_y), xytext=(arrow_x+0.5*v_gate[-1], arrow_y+(i_drain[1])), fontsize=25,
arrowprops=arrow_props, ha='center')
plt.grid()
plt.tight_layout()
fig.patch.set_facecolor('white')
plt.savefig(Path(fds.device_path,f'ioff_method.png'),dpi=400)
plt.close()
aux.print_aux(f'--Output file--\nioff_method.png file stored in {fds.device_path} ')
[docs]
def extraction_ion_plot(fds, curve_number):
""" Plot for Ion extraction method
Parameters
----------
fds: MLFoMpy dataset
curve_number: float
Number of simulation curve to plot
"""
v_gate, i_drain = aux.iv_curve_dd_filter(fds, curve_number) # Removes the presimulation data (increase of Vd)
iv_curve = interpolate.UnivariateSpline(v_gate, i_drain, s=0, k=3)
quartic_interpol, x_interp, _ = aux.iv_interpolation(fds, v_gate, i_drain)
fd = quartic_interpol.derivative(n=1)
sd = quartic_interpol.derivative(n=2)
upper_limit = x_interp[np.argmax(fd(x_interp))]
x_filter = x_interp[np.where(x_interp<upper_limit)]
vth_sd = round(x_interp[np.argmax(sd(x_filter))],3)
vth_vd = fds.drain_bias_value + vth_sd
ion = float(iv_curve(vth_vd))
#PLOT
fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(1, 1, 1)
ax.plot(x_interp, iv_curve(x_interp),linewidth=3, color='tab:green')
ax.set_xlim(xmin=0.0)
ax.axvline(vth_vd, linestyle='-.', linewidth=2, color='tab:grey')
ax.plot(vth_vd, ion,'o',ms=15, color='tab:green')
ax.legend([r'$I_D$-$V_G$'], fontsize=20, loc=0)
ax.set_ylabel(r'$I_D[A]$', fontsize=20)
ax.set_xlabel(r'V$_G[V]$', fontsize=20)
ax.set_yscale('log')
ax.tick_params(axis='both', which='major', labelsize=20)
# Arrow Ion
arrow_text = r'$I_{on}=$'+f'{"{:.2e}".format(ion)}'+r'$A$'
arrow_x = vth_vd
arrow_y = ion
arrow_props = dict(color='k')
ax.annotate(arrow_text, xy=(arrow_x, arrow_y), xytext=(arrow_x-0.2*v_gate[-1], arrow_y-0.9*ion), fontsize=20,
arrowprops=arrow_props, ha='center')
# Arrow VG
arrow_text = r'$V_{G}=$'+r'$V_{D}+V_{Th}$'
arrow_x = vth_vd
arrow_y = i_drain[0]
arrow_props = dict(color='k')
ax.annotate(arrow_text, xy=(arrow_x, arrow_y), xytext=(arrow_x-0.2*v_gate[-1], arrow_y+1e-4*ion), fontsize=20,
arrowprops=arrow_props, ha='center')
plt.grid()
plt.tight_layout()
fig.patch.set_facecolor('white')
plt.savefig(Path(fds.device_path,f'ion_method.png'),dpi=400)
plt.close()
aux.print_aux(f'--Output file--\nion_method.png file stored in {fds.device_path} ')
[docs]
def extraction_ss_plot(fds, curve_number):
""" Plot for SS extraction method
Parameters
----------
fds: MLFoMpy dataset
curve_number: float
Number of simulation curve to plot
"""
v_gate, i_drain = aux.iv_curve_dd_filter(fds, curve_number) # Removes the presimulation data (increase of Vd)
cubic_interpol = interpolate.UnivariateSpline(v_gate, i_drain, s=0, k=3)
quartic_interpol, x_interp, _ = aux.iv_interpolation(fds, v_gate, i_drain)
fd = quartic_interpol.derivative(n=1)
sd = quartic_interpol.derivative(n=2)
upper_limit = x_interp[np.argmax(fd(x_interp))]
x_filter = x_interp[np.where(x_interp<upper_limit)]
vth_sd = round(x_interp[np.argmax(sd(x_filter))],3)
start = v_gate[0]
end = vth_sd
t_ss = (end-start)*1000/(np.log10(cubic_interpol(end))-np.log10(cubic_interpol(start)))
m_tan = (np.log10(cubic_interpol(end))-np.log10(cubic_interpol(start)))/(end-start)
round(t_ss,2)
# PLOT
x_dumb = np.linspace(start, end, 100)
fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(1, 1, 1)
ax.plot(x_interp, np.log10(cubic_interpol(x_interp)),linewidth=3, color='tab:green',scaley='log')
ax.plot(x_interp, m_tan*(x_interp)+np.log10(cubic_interpol(start)),linestyle='--',linewidth=3, color='k',scaley='lin')
ax.axvline(0,linestyle='-.',linewidth=2, color='tab:grey',)
ax.axvline(end,linestyle='-.',linewidth=2, color='tab:grey')
ax.set_ylim(ymin=np.log10(cubic_interpol(start)), ymax=np.log10(cubic_interpol(x_interp[-1]))*0.9)
ax.legend(['$I_D$-$V_G$'], fontsize=20, loc=0)
#ax.legend(['I-V',r'$logI_{D}=SS^{-1}V_G$'], fontsize=20, loc=0)
ax.set_ylabel(r'$\log_{10}{I_D}[A]$', fontsize=20)
ax.set_xlabel(r'V$_G[V]$', fontsize=20)
ax.tick_params(axis='both', which='major', labelsize=20)
# # Arrow Vth start
arrow_text = r'$V_{G}^{start}=$'+f'{0}'+r' $V$'
arrow_x = start
arrow_y = np.log10(cubic_interpol(start))
arrow_props = dict(color='k')
ax.annotate(arrow_text, xy=(arrow_x, arrow_y), xytext=(arrow_x+0.25*v_gate[-1], arrow_y-0.3*np.log10(i_drain[-1])), fontsize=20,
arrowprops=arrow_props, ha='center')
# Arrow Vth end
arrow_text = r'$V_{G}^{end}=$'+r'$V_{Th}$'
arrow_x = end
arrow_y = np.log10(cubic_interpol(start))
arrow_props = dict(color='k')
ax.annotate(arrow_text, xy=(arrow_x, arrow_y), xytext=(arrow_x, arrow_y-0.1*np.log10(i_drain[-1])), fontsize=20,
arrowprops=arrow_props, ha='left')
# Arrow SS
arrow_text = r'$SS=$'+f'{round(t_ss,2)}'+r' mV/dec'
arrow_x = (start+end)/2
arrow_y = np.log10(cubic_interpol((start+end)/2))
arrow_props = dict(color='k')
ax.annotate(arrow_text, xy=(arrow_x, arrow_y), xytext=(arrow_x+0.52*v_gate[-1], arrow_y-0.25*np.log10(i_drain[-1])), fontsize=20,
arrowprops=arrow_props, ha='center')
plt.grid()
plt.tight_layout()
fig.patch.set_facecolor('white')
plt.savefig(Path(fds.device_path,f'ss_method.png'),dpi=400)
plt.close()
aux.print_aux(f'--Output file--\nss_method.png file stored in {fds.device_path} ')
[docs]
def extraction_method_plot(fds, fom, method = None, curve_number = 0):
""" Interface function to extraction method plot selection
Parameters
----------
fds: MLFoMpy dataset
curve_number: float
Number of simulation curve to see the LE extraction method
"""
if fom == 'vth':
if method == 'SD':
extraction_vth_sd_plot(fds, curve_number)
if method == 'CC':
extraction_vth_cc_plot(fds, curve_number)
elif method == None or method == 'LE':
extraction_vth_le_plot(fds, curve_number)
if fom == 'ioff':
extraction_ioff_plot(fds, curve_number)
if fom == 'ss':
extraction_ss_plot(fds, curve_number)
if fom == 'ion':
extraction_ion_plot(fds, curve_number)
[docs]
def prediction_versus_simulation_plot(simulation, prediction, r2, xlabel = None, ylabel = None, rms = None, storepath = None):
'''Plot for the comparison of the simulated versus predicted data with machine learning
Parameters
----------
simulation: list or torch.tensor
Simulated data
prediction: list or torch.tensor
Predicted data
r2: float
Coefficient of determination between simulated and predicted data
xlabel: str
Text for the xlabel
ylabel: str
Text fot the ylabel
rms: list
Root mean square errors in the prediction of each value
storepath: str
Path to store the plot, by default is stored in the execution directory
'''
fig, ax = plt.subplots()
if rms:
rms = mean_squared_error(simulation, prediction)**0.5
plt.errorbar(simulation, prediction, fmt='.', yerr=rms, label='RMSE')
else:
plt.plot(simulation, prediction,'.',color='darkorange',markersize=15,alpha=0.8)
plt.xlabel(xlabel,fontsize=20)
plt.ylabel(ylabel,fontsize=20)
plt.plot(simulation, simulation,'-', color='darkgrey')
textstr0 = rf'$R^2$={r2}'
props = dict(boxstyle='round', facecolor='wheat', alpha=0.3)
plt.text(x=0.1,y=0.8, s=textstr0, transform=ax.transAxes, fontsize=20,
verticalalignment='top', bbox=props)
plt.locator_params(axis='x', nbins=6)
plt.locator_params(axis='y', nbins=6)
plt.xticks(fontsize=20)
plt.yticks(fontsize=20)
if storepath:
plt.savefig(Path(storepath,f'prediction_vs_simulation.pdf'), bbox_inches='tight')
aux.print_aux(f'--Output file--\nprediction_vs_simulation.pdf file stored in {Path(storepath)}')
else:
plt.savefig('prediction_vs_simulation.pdf', bbox_inches='tight')
aux.print_aux(f'--Output file--\nprediction_vs_simulation.pdf file stored in {Path.cwd()} ')
plt.show()
[docs]
def iv_curves_simulation_prediction(i_simulated, i_predicted, vg_start = 0, vg_end = 1.0, scale = 'lin', storepath = None):
'''Plot for the comparison of the simulated versus predicted iv curves with machine learning
Parameters
----------
i_simulated: list or torch.tensor
Simulated data
i_predicted: list or torch.tensor
Predicted data
vg_start: float
Vg of the first current
vg_end: float
Vg of the last current
scale: str
Scale of the Y-Axis, two options: linear 'lin', or logarithmic 'log'
storepath: str
Path to store the plot, by default is stored in the execution directory
'''
v = np.linspace(vg_start, vg_end, len(i_simulated[0]))
if scale == 'lin':
plt.plot(v, torch.transpose((10**i_simulated)*1000, 0, 1),'--',label='Simulation', color='darkgray')
plt.plot(v, torch.transpose((10**i_predicted)*1000, 0, 1),'o',label='Prediction', color='tab:blue')
plt.xlabel(r'$V_{G}$ [V]', fontsize=20)
plt.ylabel(r'$I_{D}$ [mA]', fontsize=20)
elif scale == 'log':
plt.plot(v, torch.transpose(i_simulated, 0, 1),'--',label='Simulation', color='darkgray')
plt.plot(v, torch.transpose(i_predicted, 0, 1),'o',label='Prediction', color='tab:blue')
plt.xlabel(r'$V_{G}$ [V]', fontsize=20)
plt.ylabel(r'$log_{10}I_{D}$ [A]', fontsize=20)
plt.locator_params(axis='x', nbins=6)
plt.locator_params(axis='y', nbins=6)
plt.xticks(fontsize=20)
plt.yticks(fontsize=20)
# ax.ticklabel_format(axis='y',style='sci', scilimits=(0,0),useMathText = True)
legend_elements = [Line2D([0], [0], color='darkgray', lw=4, label='Simulation'),
Line2D([0], [0], marker='o', color='w', label='ML prediction',
markerfacecolor='tab:blue',linestyle=None, markersize=20)]
plt.legend(handles=legend_elements, loc='best', fontsize=20)
if storepath:
if scale == 'lin':
plt.savefig(Path(storepath,f'iv_curves.pdf'), bbox_inches='tight')
aux.print_aux(f'--Output file--\niv_curves.pdf file stored in {Path(storepath)} ')
elif scale == 'log':
plt.savefig(Path(storepath,f'logiv_curves.pdf'), bbox_inches='tight')
aux.print_aux(f'--Output file--\nlogiv_curves.pdf file stored in {Path(storepath)} ')
else:
if scale == 'lin':
plt.savefig('iv_curves.pdf', bbox_inches='tight')
aux.print_aux(f'--Output file--\niv_curves.pdf file stored in {Path.cwd()} ')
elif scale == 'log':
plt.savefig('logiv_curves.pdf', bbox_inches='tight')
aux.print_aux(f'--Output file--\nlogiv_curves.pdf file stored in {Path.cwd()} ')
plt.close()