import numpy as np import matplotlib.pyplot as plt from matplotlib.figure import Figure from matplotlib import rc import matplotlib from scipy import interpolate from scipy import optimize import pandas as pd matplotlib.use("pgf") matplotlib.rcParams.update({ "pgf.texsystem": "pdflatex", 'font.family': 'serif', 'text.usetex': True, 'pgf.rcfonts': False, }) # rc('font', **{'family':'serif', 'sans-serif':['Times']}) # rc('text', usetex=False) def parse_ccurve(path, compliance=.98): """Parses the characteristic curve data from the data logs. :param path: path to the log :returns: voltage, current """ data = np.loadtxt(path, skiprows=11, encoding='latin1')[:, :2] data = data[data[:,1] < compliance] return data def plot_ccurve(ccurve, log=False, area=None, compliance=.99, median=False, mlp=None, save=False, **pyplot_args): """Plots the characteristic curve. :param ccurve: a numpy array with the ccurve data :returns: a figure with the plot """ fig = plt.figure() ax = fig.add_subplot(111) ax.axhline(y=0, color='gray') ax.axvline(x=0, color='gray') if median: compliance = np.median(ccurve[:, 0]) plot_ccurve_line(ax, ccurve, area=area, compliance=compliance, mlp=mlp, **pyplot_args) if log: ax.set_yscale('log') if save: save_fig(fig, save) return fig, ax def plot_ccurve_line(ax, ccurve, area=None, marker='.', compliance=.99, mlp=None, label=None, **pyplot_args): v, c = ccurve[ccurve[:,1] < compliance].T if area: c /= area if mlp: mlp[1] = mlp[1]/area ax.errorbar(v, c, linestyle='None', marker=marker, markersize=2, alpha=1, label=label, **pyplot_args) ax.set_xlabel("Spannung U [V]") ax.set_ylabel("Stromstaerke I [A]" \ if not area else r"Stromdichte j [$\frac{A}{cm^2}$]") ax.grid(True, which='both') ax.set_xlim(v[0], v[-1]) if mlp: plt.plot(*mlp, marker='x', markersize=10, label='MPP ' + label if label else 'MPP') ax.legend() def save_fig(fig, name): fig.set_size_inches(5, 4) fig.tight_layout() fig.savefig('./figs/' + name, tranparent=True, dpi=300) def parse_and_plot_ccurve(path, *args, **kwargs): return plot_ccurve(parse_ccurve(path), *args, **kwargs) def analyze_ccurve(ccurve, area, int_ein): """Calculates characteristic values from the char. curve by linear interpolation. :param ccurve: char. curve :param area: area of the solar cell :param int_ein: lighting intesity :returns: j_c, u_cc, u_mlp, p_mlp, ff, eta """ interpolated = interpolate.interp1d(*ccurve.T) i_c = interpolated(0) j_c = i_c / area u_cc = optimize.root_scalar(interpolated, bracket=[0, ccurve[:,0][-1]], method='brentq').root u_mlp = optimize.minimize_scalar(lambda u: u * interpolated(u), bracket=(0, u_cc), bounds=(0, u_cc), method='bounded').x i_mlp = interpolated(u_mlp) p_mlp = -i_mlp*u_mlp ff = -p_mlp / (i_c * u_cc) p_ein = int_ein * area eta = p_mlp / p_ein return {'j_c': -j_c, 'u_cc': u_cc, 'u_mlp': u_mlp, 'p_mlp': p_mlp, 'ff': ff, 'eta': eta, 'i_mlp': i_mlp, 'p_ein': p_ein} def load_and_analyze(files, intensity, formatter="{}".format, area=1, columns=['desc', 'curve', 'area', 'j_c', 'u_cc', 'ff', 'eta', 'p_mlp', 'u_mlp', 'i_mlp']): ccurves = pd.DataFrame(columns=columns) for point, desc, *rest in files: a = area*rest[0] if rest else area row = pd.Series({'desc': desc, 'area': a, 'curve': parse_ccurve(formatter(point))}) ccurves.loc[desc] = pd.concat((row, pd.Series(analyze_ccurve(row['curve'], row['area'], intensity)))) return ccurves