def ab_distortion(v1=100.0, v2=500.0): v1_arrow = hv.Arrow(v1, 0, '𝜈₁', '^') v2_arrow = hv.Arrow(v2, 0, '𝜈₂', '^') # sufficient datapoints to mitigate inaccurate intensities and "jittering" datapoints = max(int(abs(v2 - v1) * 100), 800) coupled = lineshape_from_peaklist(ab_wrapper(v1, v2, 10), points=datapoints) plot = hv.Curve(zip(*coupled)) * v1_arrow * v2_arrow return plot.options(axiswise=True, invert_xaxis=True, xlabel='𝜈').redim(y=hv.Dimension('intensity', range=(-0.4, 1.2)))
def arrow_(self, xloc, yloc, text, orientation="v", arrowstyle='->'): """ Returns an arrow for a chart. Params: the text, xloc and yloc are coordinates to position the arrow. Orientation is the way to display the arrow: possible values are ``[<, ^, >, v]``. Arrow style is the graphic style of the arrow: possible values: ``[-, ->, -[, -|>, <->, <|-|>]`` """ try: arrow = hv.Arrow(xloc, yloc, text, orientation, arrowstyle=arrowstyle) return arrow except Exception as e: self.err(e, self.arrow_, "Can not draw arrow chart")
def analysis_gate(self, df): # global curr_savgol_plot, maxsavgol gate_files.append(df) # append to a list containing all the gate diode files # Remove initial kink from the data start_value = np.mean(self.data[df]["data"]["Current"][10:20]) CurrentCopy = self.data[df]["data"]["Current"].copy() for x in range(int(len(self.data[df]["data"]["Current"]) / 2)): if CurrentCopy[x] < start_value: CurrentCopy[x] = start_value # Generate curve plot_not_kink = self.add_single_plots( self.data[df]["data"][self.xaxis], CurrentCopy, "Current" ) # Try savgol filter ##try: ## i = 0 ## while i < 2: ## curr_savgol = scipy.signal.savgol_filter(self.data[df]['data']['Current'], 31, 3) # window size 51, polynomial order 3 ## i += 1 ## maxsavgol = max(curr_savgol) ## curr_savgol_plot = self.add_single_plots(self.data[df]['data']['Voltage'], curr_savgol, "SavgolCurrent") ##except Exception: ## self.log.warning("No savgol plot possible... Error: {}") # Interpolation current curve xnew, ynew = self.interpolated_axis( df, self.data[df]["data"][self.xaxis], CurrentCopy ) curr_interp_plot = self.add_single_plots(xnew, ynew, "InterpolatedCurrent") # Build the first derivatives firstderi_interp = self.build_first_derivative(xnew, ynew) dif_intep_plot = self.add_single_plots( xnew, firstderi_interp, "FirstDerivativeCurrent" ) # Second derivative second_deriv_interp = self.build_second_derivative(xnew, ynew) dif2_intep_plot = self.add_single_plots( xnew, second_deriv_interp, "SecondDerivativeCurrent" ) # Not interpolated first derivative firstdev_not_interp = self.build_first_derivative( self.data[df]["data"]["Current"], self.data[df]["data"]["Voltage"] ) self.insert_in_df(df, 3, "firstderivative_gate", firstdev_not_interp) # Try to find the start and ending indices of the points where you want to average, used to handle the problematic files max1_index = list(firstderi_interp).index(max(firstderi_interp)) min1_index = list(firstderi_interp).index(min(firstderi_interp)) if min1_index < max1_index: min1_index = max1_index + 1 max1_index = min1_index - 2 median_index = int(len(xnew) / 2) if median_index < max1_index: median_index = max1_index + 1 if min1_index < median_index: min1_index = median_index + 1 max1_index = median_index - 1 # Find the segment where you want to average using the second derivative interesting_section = sorted( list(second_deriv_interp[max1_index:median_index]), reverse=True ) firstminimum = interesting_section[0] interesting_section2 = sorted( list(second_deriv_interp[median_index:min1_index]), reverse=True ) second_minimum = interesting_section2[0] # Find average start_average = list(second_deriv_interp).index(firstminimum) end_average = list(second_deriv_interp).index(second_minimum) I_surf_maxima_average = np.mean(list(ynew[start_average:end_average])) # Compute the surface current with the average method mxx = max(ynew) # find maximum value of the current-voltage curve miny = np.mean( list(ynew[-1000:]) ) # find the minimum of the current-voltage curve by averaging 20 points values in the curve tail I_surf_average = ( I_surf_maxima_average - miny ) # compute the surface current by computing the difference between the maximum and minimum value I_surf_average_table = "{:.2e}".format(I_surf_average) Surface_current_average.append(I_surf_average_table) # Compute surface current with the maximum method Isurf_max = ( mxx - miny ) # compute the surface current by computing the difference between the maximum and minimum value Isurf_table = "{:.2e}".format(Isurf_max) Surface_current.append(Isurf_table) # Compute Surface_recombination_velocity with the maximum method S_null_max = Isurf_max / ( self.config["IV_PQC_parameter"]["q"] * self.config["IV_PQC_parameter"]["n_i_intrinsic_carrier_concentration"] * (float(self.data[df]["header"][0].split(":")[1]) * (1e-8)) ) Surface_recombination_velocity.append(S_null_max) # Compute Surface_recombination_velocity with the average method S_null_average = I_surf_average / ( self.config["IV_PQC_parameter"]["q"] * self.config["IV_PQC_parameter"]["n_i_intrinsic_carrier_concentration"] * (float(self.data[df]["header"][0].split(":")[1]) * (1e-8)) ) Surface_recombination_velocity_average.append(S_null_average) # Add text to the plot text = hv.Text( 3, 9 * (1e-11), "Isurf_max: {} A\n" "Isurf_average: {} A\n" "Surface recombination velocity_max: {} cm/s\n" "Surface recombination velocity_average: {} cm/s".format( np.round(Isurf_max, 15), np.round(I_surf_average, 15), np.round(S_null_max, 4), np.round(S_null_average, 4), ), ).opts(style=dict(text_font_size="20pt")) # Do this if the analysis is of just one file. if len(gate_files) == 1: # Add overlaid lines on the plot Path_min = hv.Path([(-2, miny), (6, miny)]).opts(line_width=2.0) Path_mxx = hv.Path([(-2, mxx), (6, mxx)]).opts(line_width=2.0) ##Path_savgolmax = hv.Path([(-2, maxsavgol), (6, maxsavgol)]).opts(line_width=2.0) Path_average = hv.Path( [(-2, I_surf_maxima_average), (6, I_surf_maxima_average)] ).opts(line_width=2.0) Path_Isurf = hv.Arrow(-1, mxx, "max", "^") Path_Isurf_average = hv.Arrow(0, I_surf_maxima_average, "average", "^") # Plot all Measurements self.donts_gatediode = [ "timestamp", "voltage", "Voltage", "Current", "Stepsize", "Wait", "Stepsize", "Frequency", "x", "N", ] # don't plot these. self.PlotDict["BasePlots_gate"] = plot_not_kink self.PlotDict["BasePlots_gate"] += dif_intep_plot self.PlotDict["BasePlots_gate"] += dif2_intep_plot self.PlotDict["BasePlots_gate"] += curr_interp_plot try: self.PlotDict["BasePlots_gate"] += curr_savgol_plot self.PlotDict["BasePlots_gate"] += curr_savgol_plot * plot_not_kink except Exception: self.log.warning("No savgol plot possible... Error: {}") self.PlotDict["BasePlots_gate"] += ( text * plot_not_kink * Path_min * Path_mxx * Path_average * Path_Isurf * Path_Isurf_average ) # * Path_savgolmax self.PlotDict["BasePlots_gate"] += ( curr_interp_plot * dif_intep_plot * dif2_intep_plot * plot_not_kink ) # Add table that shows resulting parameters of the analysis df4 = pd.DataFrame( { "Name": gate_files, "Surface current_max (A)": Surface_current, "Surface current_average (A)": Surface_current_average, "Surface recombination velocity_max (cm/s)": Surface_recombination_velocity, "Surface recombination velocity_average (cm/s)": Surface_recombination_velocity_average, } ) table3 = hv.Table((df4), label="Gate analysis") table3.opts(width=1300, height=800) self.PlotDict["BasePlots_gate"] += table3 # Do this if the analysis is of more than one file elif len(gate_files) > 1: self.donts = [ "timestamp", "voltage", "Voltage", "Stepsize", "Wait", "Stepsize", "Frequency", "firstderivative_gate", "x", "N", ] # do not plot this data self.basePlots3 = plot_all_measurements( self.data, self.config, self.xaxis, self.name, do_not_plot=self.donts, keys=gate_files, ) self.PlotDict["BasePlots_gate"] = self.basePlots3 # Add table that shows resulting parameters of the analysis df4 = pd.DataFrame( { "Name": gate_files, "Surface current_max (A)": Surface_current, "Surface current_average (A)": Surface_current_average, "Surface recombination velocity_max (cm/s)": Surface_recombination_velocity, "Surface recombination velocity_average (cm/s)": Surface_recombination_velocity_average, } ) table3 = hv.Table((df4), label="Gate analysis") table3.opts(width=1300, height=800) self.PlotDict["BasePlots_gate"] += table3 return self.PlotDict["BasePlots_gate"]
import pandas as pd import numpy as np import holoviews as hv from holoviews import opts, dim hv.extension('bokeh') macro_df = pd.read_csv('http://assets.holoviews.org/macro.csv', '\t') key_dimensions = [('year', 'Year'), ('country', 'Country')] value_dimensions = [('unem', 'Unemployment'), ('capmob', 'Capital Mobility'), ('gdp', 'GDP Growth'), ('trade', 'Trade')] macro = hv.Table(macro_df, key_dimensions, value_dimensions) gdp_curves = macro.to.curve('Year', 'GDP Growth') gdp_unem_scatter = macro.to.scatter('Year', ['GDP Growth', 'Unemployment']) annotations = hv.Arrow(1973, 8, 'Oil Crisis', 'v') * hv.Arrow(1975, 6, 'Stagflation', 'v') *\ hv.Arrow(1979, 8, 'Energy Crisis', 'v') * hv.Arrow(1981.9, 5, 'Early Eighties\n Recession', 'v') composition=(gdp_curves * gdp_unem_scatter* annotations) composition.opts( opts.Curve(color='k'), opts.Scatter(cmap='Blues', color='Unemployment', line_color='k', size=dim('Unemployment')*1.5), opts.Text(text_font_size='13px'), opts.Overlay(height=400, show_frame=False, width=700)) hv.save(composition, 'holomap.html')