def run(self): """Runs the script""" # Convert the units to the desired ones self.original_data = deepcopy(self.data) # Is needed for gradin # Plot deltas of each measurement abs_diff = self.data["All"][["C11R11", "C127R127", "C255R257"]].diff(axis=0) rel_diff = ( abs_diff / self.data["All"][["C11R11", "C127R127", "C255R257"]]).rename( columns={ "C11R11": "C11R11_reldiff", "C127R127": "C127R127_reldiff", "C255R257": "C255R257_reldiff" }) abs_diff = abs_diff.rename( columns={ "C11R11": "C11R11_absdiff", "C127R127": "C127R127_absdiff", "C255R257": "C255R257_absdiff" }) temp = rel_diff.join(abs_diff) self.data["All"] = self.data["All"].join(temp) self.data["columns"].extend([ "C11R11_absdiff", "C127R127_absdiff", "C255R257_absdiff", "C11R11_reldiff", "C127R127_reldiff", "C255R257_reldiff" ]) for file in self.data["keys"]: self.data[file]["measurements"].extend([ "C11R11_absdiff", "C127R127_absdiff", "C255R257_absdiff", "C11R11_reldiff", "C127R127_reldiff", "C255R257_reldiff" ]) self.data[file]["data"] = self.data["All"] self.data[file]["units"].extend( ["None", "urad", "urad", "urad", "%", "%", "%"]) # Plot all Measurements self.basePlots = plot_all_measurements(self.data, self.config, self.xaxis, self.analysisName, do_not_plot=self.donts, ErrorBars=self.errors) # self.basePlots = applyPlotOptions(self.basePlots, {'Curve': {'color': "hv.Cycle('PiYG')"}}) self.PlotDict["BasePlots"] = self.basePlots self.PlotDict["All"] = self.basePlots return self.PlotDict
def run(self): """Runs the script""" # Plot all Measurements self.basePlots = plot_all_measurements(self.data, self.config, self.xrow, self.analysisName, do_not_plot=self.donts) self.PlotDict["BasePlots"] = self.basePlots self.PlotDict["All"] = self.basePlots # Plot all special Plots: # Histogram Plot self.Histogram = dospecialPlots( self.data, self.config, self.analysisName, "concatHistogram", self.measurements, **self.config[self.analysisName].get( "AuxOptions", {}).get("concatHistogram", {})) if self.Histogram: self.PlotDict["Histogram"] = self.Histogram self.PlotDict["All"] = self.PlotDict["All"] + self.Histogram # Whiskers Plot self.WhiskerPlots = dospecialPlots(self.data, self.config, self.analysisName, "BoxWhisker", self.measurements) if self.WhiskerPlots: self.PlotDict["Whiskers"] = self.WhiskerPlots self.PlotDict["All"] = self.PlotDict["All"] + self.WhiskerPlots # Violin Plot self.Violin = dospecialPlots(self.data, self.config, self.analysisName, "Violin", self.measurements) if self.Violin: self.PlotDict["Violin"] = self.Violin self.PlotDict["All"] = self.PlotDict["All"] + self.Violin # singleHist Plot self.singleHist = dospecialPlots( self.data, self.config, self.analysisName, "Histogram", self.measurements, **self.config[self.analysisName].get( "AuxOptions", {}).get("singleHistogram", {})) if self.singleHist: self.PlotDict["singleHistogram"] = self.singleHist self.PlotDict["All"] = self.PlotDict["All"] + self.singleHist # Reconfig the plots to be sure self.PlotDict["All"] = config_layout( self.PlotDict["All"], **self.config[self.analysisName].get("Layout", {})) return self.PlotDict
def run(self): """Runs the script""" # Convert the units to the desired ones for meas in self.measurements: unit = (self.config[self.analysisname].get(meas, {}).get( "UnitConversion", None)) if unit: self.data = convert_to_EngUnits(self.data, meas, unit) # Plot all Measurements self.basePlots = plot_all_measurements( self.data, self.config, self.measurements[0], self.analysisname, do_not_plot=[self.measurements[0]], ) self.PlotDict["All"] = self.basePlots # Plot all special Plots: # Histogram Plot self.Histogram = dospecialPlots( self.data, self.config, self.analysisname, "concatHistogram", self.measurements, **self.config[self.analysisname].get( "AuxOptions", {}).get("concatHistogram", {})) if self.Histogram: self.PlotDict["Histogram"] = self.Histogram self.PlotDict["All"] = self.PlotDict["All"] + self.Histogram # Whiskers Plot self.WhiskerPlots = dospecialPlots(self.data, self.config, self.analysisname, "BoxWhisker", self.measurements) if self.WhiskerPlots: self.PlotDict["Whiskers"] = self.WhiskerPlots self.PlotDict["All"] = self.PlotDict["All"] + self.WhiskerPlots # Violin Plot self.Violin = dospecialPlots(self.data, self.config, self.analysisname, "Violin", self.measurements) if self.Violin: self.PlotDict["Violin"] = self.Violin self.PlotDict["All"] = self.PlotDict["All"] + self.Violin # Reconfig the plots to be sure self.PlotDict["All"] = config_layout( self.PlotDict["All"], **self.config.get(self.analysisname, {}).get("Layout", {})) return self.PlotDict
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"]
def analysis_diode(self, df): # global fdestimation diode_files.append(df) # Append to a list containing all the diode files self.data[df]["data"]["Voltage"] = list( map(abs, self.data[df]["data"]["Voltage"]) ) # take absolute value of Voltage # Try interpolation + filtered savitzy-golay derivative plot ( capacity_curve, derivative_onec2_curve, deronec2_savgol_plot, ) = self.interp_derivative_diode( df, self.data[df]["data"][self.xaxis], self.data[df]["data"]["Capacity"] ) self.insert_in_df(df, 3, "1C2", 1 / self.data[df]["data"]["Capacity"].pow(2)) # Compute first derivative of 1/C2 firstdev_invers_C2 = self.build_first_derivative( self.data[df]["data"][self.xaxis], self.data[df]["data"]["1C2"] ) self.insert_in_df(df, 4, "derivative1C2", firstdev_invers_C2) # Calculate deep x x = ( self.config["IV_PQC_parameter"]["epsilonNull"] * (1e-6) * float(self.data[df]["header"][0].split(":")[1]) * self.config["IV_PQC_parameter"]["epsilonSiliconOxide"] ) / self.data[df]["data"]["Capacity"][:42] self.insert_in_df(df, 5, "x", x) # Calculate doping profile N = (2) / ( self.config["IV_PQC_parameter"]["epsilonNull"] * (1e-2) * self.config["IV_PQC_parameter"]["q"] * self.config["IV_PQC_parameter"]["epsilonSiliconOxide"] * self.data[df]["data"]["derivative1C2"][:42] * (float(self.data[df]["header"][0].split(":")[1]) * (1e-8)) * (float(self.data[df]["header"][0].split(":")[1]) * (1e-8)) ) self.insert_in_df(df, 6, "N", N) # Plot all Measurements self.donts_diode = [ "timestamp", "voltage", "Voltage", "Stepsize", "Wait", "Stepsize", "Frequency", "x", "N", "Capacity", "Current", ] # do not plot capacity voltage plot self.basePlots4 = plot_all_measurements( self.data, self.config, self.xaxis, self.name, do_not_plot=self.donts_diode, keys=diode_files, ) self.PlotDict["BasePlots_diode"] = self.basePlots4 # Add a plot with a different x axis self.basePlots_2 = plot_all_measurements( self.data, self.config, "x", self.name, do_not_plot=["Voltage", "Current", "Capacity", "1C2", "derivative1C2", "x"], keys=diode_files, ) # diode is the list containing all the diode files self.PlotDict["BasePlots_diode"] += self.basePlots_2 # Add full depletion point to 1/c^2 curve if ( self.config["IV_PQC"] .get("1C2", {}) .get("DoFullDepletionCalculation", False) ): try: if self.basePlots4.Overlay.A_1C2.children: c2plot = self.basePlots4.Overlay.A_1C2.opts(clone=True) else: c2plot = self.basePlots4.Curve.A_1C2.opts(clone=True) fdestimation = self.find_full_depletion_c2( c2plot, self.data, self.config, diode_files, PlotLabel="Full depletion estimation", ) except Exception as err: self.log.warning( "No full depletion calculation possible... Error: {}".format(err) ) # Find resistivity C_min = np.mean(self.data[df]["data"]["Capacity"][-20:]) d_active = ( self.config["IV_PQC_parameter"]["epsilonNull"] * self.config["IV_PQC_parameter"]["epsilonSiliconOxide"] * (float(self.data[df]["header"][0].split(":")[1]) * (1e-8)) * (1e-2) / C_min ) # in cm T_n = 295 / 300 u_holes_mobility = 54.3 * pow(T_n, -0.57) + 1.36 * (1e8) * pow(295, -2.23) / ( 1 + ((5e12) / (2.35 * (1e17) * pow(T_n, 2.4))) * 0.88 * pow(T_n, -0.146) ) # in cm^2/(V*s) rho = ( d_active * d_active / ( 2 * self.config["IV_PQC_parameter"]["epsilonNull"] * (1e-2) * self.config["IV_PQC_parameter"]["epsilonSiliconOxide"] * fdestimation[1] * u_holes_mobility ) ) # in Ohm * cm rho_table = "{:.2e}".format( rho ) # value to show later on in the table showing the results of the analysis resistivity.append(rho_table) # Add a table that show the results of the analysis if len(diode_files) == 1: self.PlotDict["BasePlots_diode"] += fdestimation[0] # Add trial plots self.PlotDict["BasePlots_diode"] += capacity_curve ##self.PlotDict["BasePlots_diode"] += derivative_onec2_curve * deronec2_savgol_plot ##self.PlotDict["BasePlots_diode"] += deronec2_savgol_plot # Add table df3 = pd.DataFrame( { "Name": diode_files, "full depletion voltage (V)": fdepvoltage, " Bulk resistivity (Ohm * cm)": resistivity, } ) table2 = hv.Table(df3, label="Diode analysis") table2.opts(width=1300, height=800) self.PlotDict["BasePlots_diode"] += table2 else: df3 = pd.DataFrame( { "Name": diode_files, "full depletion voltage (V)": fdepvoltage, "Bulk resistivity (Ohm * cm)": resistivity, } ) table2 = hv.Table(df3, label="Diode analysis") table2.opts(width=1300, height=800) self.PlotDict["BasePlots_diode"] += table2 return self.PlotDict["BasePlots_diode"]
def analysis_mos(self, df): # global fBestimation cv_files.append( df ) # Append data-frame to a list containing all the cv mos files that you want to analyze. # Double check that the voltage values have increasing order. if ( "Voltage" in self.data[df]["data"] and self.data[df]["data"]["Voltage"][0] > 0 ): # If the first element is positive signifies that the voltage values have been stored in decreasing order self.data[df]["data"]["Voltage"] = list( reversed(self.data[df]["data"]["Voltage"]) ) # If voltage values have decreasing order, reverse them. self.data[df]["data"]["Capacity"] = list( reversed(self.data[df]["data"]["Capacity"]) ) # Normalize capacity by the Area and set to cm^2 self.data[df]["data"]["Capacity"] = self.data[df]["data"]["Capacity"] / ( float(self.data[df]["header"][0].split(":")[1]) * (1e-8) ) # Generate a capacity copy without the small kink at the begging of the curve CapacityCopy = self.data[df]["data"]["Capacity"].copy() capMin = np.max( self.data[df]["data"]["Capacity"][:20] ) # Find the Maximum among the first 20 values of the Capacity and set it as the minimum Capacity value for x in range(len(self.data[df]["data"]["Capacity"])): if CapacityCopy[x] < capMin: CapacityCopy[x] = capMin # Insert into the data frame self.insert_in_df(df, 3, "CapacityCopy", CapacityCopy) # Build second derivative seconddev = self.build_second_derivative( self.data[df]["data"][self.xaxis], self.data[df]["data"]["CapacityCopy"] ) self.insert_in_df(df, 4, "derivative2", seconddev) # Build interpolated plot and interpolated derivatives ( capa_interp_plot, derivative_interpolation_plot, secondderivative_interp_plot, max_firstder_plot, voltage_value_of_max_firstder, ) = self.interpol( df, self.data[df]["data"][self.xaxis], self.data[df]["data"]["CapacityCopy"] ) # Find the index of the row which contains the maximum value of the second derivative indexMax = self.data[df]["data"].index.get_loc( self.data[df]["data"]["derivative2"].values.argmax() ) # Find the index of the row which contains the minimum value of the second derivative indexMin = self.data[df]["data"].index.get_loc( self.data[df]["data"]["derivative2"].values.argmin() ) # Plot all Measurements self.donts_mos = [ "timestamp", "voltage", "Voltage", "Stepsize", "Wait", "Stepsize", "Frequency", "x", "N", "Current", ] # don't plot these. self.basePlots5 = plot_all_measurements( self.data, self.config, self.xaxis, self.name, do_not_plot=self.donts_mos, keys=cv_files, ) self.PlotDict["BasePlots_MOS"] = self.basePlots5 # Add flat bandage voltage point to the Capacity curve if ( self.config["IV_PQC"] .get("CapacityCopy", {}) .get("findFlatBandVoltage", False) ): try: if self.basePlots5.Overlay.MOS_CV_CURVES.children: clone_plot = self.basePlots5.Overlay.MOS_CV_CURVES.opts(clone=True) else: clone_plot = self.basePlots5.Curve.MOS_CV_CURVES.opts(clone=True) fBestimation = self.find_flatBand_voltage( clone_plot, self.data, self.config, indexMax, indexMin, df, cv_files, voltage_value_of_max_firstder, PlotLabel="Flat band voltage estimation", ) except Exception as err: self.log.warning( "No flat band voltage calculation possible... Error: {}".format(err) ) # Do these plots for the analysis of one single cv mos file if len(cv_files) == 1: self.PlotDict["BasePlots_MOS"] += fBestimation[0] self.PlotDict["BasePlots_MOS"] += derivative_interpolation_plot self.PlotDict["BasePlots_MOS"] += secondderivative_interp_plot self.PlotDict["BasePlots_MOS"] += capa_interp_plot self.PlotDict["BasePlots_MOS"] += ( capa_interp_plot * max_firstder_plot * derivative_interpolation_plot * secondderivative_interp_plot ) self.PlotDict["BasePlots_MOS"] += ( fBestimation[6] * max_firstder_plot * derivative_interpolation_plot ) # Add a Table that shows the differents analysis parameters values df2 = pd.DataFrame( { "Name": cv_files, "Flatband Voltage second_derivative (V)": fbvoltage, "Flatband Voltage first_derivative (V)": fbvoltage_firstderivative, "Accumulation capacitance (F)": Accum_capacitance_list, "Accumulation capacitance normalized (F/cm^2)": Accum_capacitance_normalized_list, "Tox (nm)": Tox_list, "Nox (cm^-2)": Nox_list, } ) table1 = hv.Table(df2, label="Mos analysis") table1.opts(width=1300, height=800) # Do plots self.PlotDict["BasePlots_MOS"] += table1 return self.PlotDict["BasePlots_MOS"]
def run(self): """Runs the script""" # Add the 1/c^2 data to the dataframes for df in self.data["keys"]: if "CV" in self.data[df]["data"]: self.data[df]["data"].insert( 3, "1C2", 1 / self.data[df]["data"]["CV"].pow(2)) self.data[df]["units"].append("arb. units") self.data[df]["measurements"].append("1C2") elif "capacitance" in self.data[df]["data"]: self.data[df]["data"].insert( 3, "1C2", 1 / self.data[df]["data"]["capacitance"].pow(2)) self.data[df]["units"].append("arb. units") self.data[df]["measurements"].append("1C2") # Add the measurement to the list # Plot all Measurements self.basePlots = plot_all_measurements(self.data, self.config, self.xaxis, self.analysisName, do_not_plot=self.donts) #self.basePlots = applyPlotOptions(self.basePlots, {'Curve': {'color': "hv.Cycle('PiYG')"}}) self.PlotDict["BasePlots"] = self.basePlots self.PlotDict["All"] = self.basePlots # Add full depletion point to 1/c^2 curve if self.config[self.analysisName].get("1C2", {}).get( "DoFullDepletionCalculation", False): try: if self.basePlots.Overlay.CV_CURVES_hyphen_minus_Full_depletion.children: c2plot = self.basePlots.Overlay.CV_CURVES_hyphen_minus_Full_depletion.opts( clone=True) else: c2plot = self.basePlots.Curve.CV_CURVES_hyphen_minus_Full_depletion.opts( clone=True) fdestimation = self.find_full_depletion( c2plot, self.data, self.config, PlotLabel="Full depletion estimation") self.PlotDict["All"] += fdestimation self.PlotDict["BasePlots"] += fdestimation except Exception as err: self.log.warning( "No full depletion calculation possible... Error: {}". format(err)) # Whiskers Plot self.WhiskerPlots = dospecialPlots(self.data, self.config, self.analysisName, "BoxWhisker", self.measurements) if self.WhiskerPlots: self.PlotDict["Whiskers"] = self.WhiskerPlots self.PlotDict["All"] = self.PlotDict["All"] + self.WhiskerPlots # Histogram Plot self.HistogramPlots = dospecialPlots(self.data, self.config, self.analysisName, "Histogram", self.measurements) if self.HistogramPlots: self.PlotDict["Histogram"] = self.HistogramPlots self.PlotDict["All"] = self.PlotDict["All"] + self.HistogramPlots # Reconfig the plots to be sure self.PlotDict["All"] = config_layout( self.PlotDict["All"], **self.config[self.analysisName].get("Layout", {})) return self.PlotDict
def run(self): """Runs the script""" # Convert the units to the desired ones self.original_data = deepcopy(self.data) # Is needed for grading for meas in self.measurements: unit = (self.config[self.analysisName].get(meas, {}).get( "UnitConversion", None)) if unit: self.data = convert_to_EngUnits(self.data, meas, unit) # Add the 1/c^2 data to the dataframes for df in self.data["keys"]: if "CV" in self.data[df]["data"]: self.data[df]["data"].insert( 3, "1C2", 1 / self.data[df]["data"]["CV"].pow(2)) self.data[df]["units"].append("arb. units") self.data[df]["measurements"].append("1C2") elif "capacitance" in self.data[df]["data"]: self.data[df]["data"].insert( 3, "1C2", 1 / self.data[df]["data"]["capacitance"].pow(2)) self.data[df]["units"].append("arb. units") self.data[df]["measurements"].append("1C2") # Add the measurement to the list # Plot all Measurements self.basePlots = plot_all_measurements( self.data, self.config, self.xaxis, self.analysisName, do_not_plot=self.donts, ) # self.basePlots = applyPlotOptions(self.basePlots, {'Curve': {'color': "hv.Cycle('PiYG')"}}) self.PlotDict["BasePlots"] = self.basePlots self.PlotDict["All"] = self.basePlots # Add full depletion point to 1/c^2 curve if (self.config[self.analysisName].get("1C2", {}).get( "DoFullDepletionCalculation", False)): try: if (self.basePlots.Overlay. CV_CURVES_hyphen_minus_Full_depletion.children): c2plot = self.basePlots.Overlay.CV_CURVES_hyphen_minus_Full_depletion.opts( clone=True) else: c2plot = self.basePlots.Curve.CV_CURVES_hyphen_minus_Full_depletion.opts( clone=True) fdestimation = self.find_full_depletion( c2plot, self.data, self.config, PlotLabel="Full depletion estimation", ) self.PlotDict["All"] += fdestimation self.PlotDict["BasePlots"] += fdestimation except Exception as err: self.log.warning( "No full depletion calculation possible... Error: {}". format(err)) # Whiskers Plot self.WhiskerPlots = dospecialPlots(self.data, self.config, self.analysisName, "BoxWhisker", self.measurements) if self.WhiskerPlots: self.PlotDict["Whiskers"] = self.WhiskerPlots self.PlotDict["All"] = self.PlotDict["All"] + self.WhiskerPlots # Histogram Plot self.HistogramPlots = dospecialPlots(self.data, self.config, self.analysisName, "Histogram", self.measurements) if self.HistogramPlots: self.PlotDict["Histogram"] = self.HistogramPlots self.PlotDict["All"] = self.PlotDict["All"] + self.HistogramPlots # Reconfig the plots to be sure self.PlotDict["All"] = config_layout( self.PlotDict["All"], **self.config[self.analysisName].get("Layout", {})) self.PlotDict["data"] = self.data # Grade the sensor try: self.grade_Sensor() except: self.log.critical( "Some error happend while evaluating grade of sensor. This can happen!", exc_info=True) return self.PlotDict
def run(self): """Runs the script""" from forge.tools import plainPlot # some elusive error in debugger it works while running it does not, but only here # Do some grouping and sanatizing groupedcountries = self.data["All"].groupby( self.data["All"]["Country/Region"]) # Data grouped by country self.countries = list(groupedcountries.groups) self.PlotDict["All"] = None prekeys = self.data["keys"] for items in self.config["COVID19"]["Countries"]: countryName = list(items.keys())[0] inhabitants = list(items.values())[0] countrycasegrouped = groupedcountries.get_group( countryName).groupby( "Name") # Grouped for death, confirmed, recovered seldata = { } # a dict containing all data from one country grouped by death, confirmed, recovered for i, key in enumerate( prekeys): # The three groups: death, confirmed, recovered rawdata = countrycasegrouped.get_group(key).sum( ) # Some countries have region information (I combine them to a single one) seldata[self.keys_basenames[i]] = rawdata[ self.measurements].reindex(self.measurements) # Now do the anlysis growth = {} relgrowth = {} for key, dat in seldata.items(): growth[key] = dat.diff() # Calculate the relative growth gr = growth[key].reindex(self.measurements) absc = dat.reindex(self.measurements) relgrowth[key] = gr.shift( periods=-1, fill_value=np.nan).divide( absc.replace(0, np.nan)).shift( periods=1, fill_value=np.nan ) * self.config["COVID19"]["GrowingRateMulti"] # Replace the data in the data structure newkeys = [ "Accumulated", "Growth", "RelativeGrowth*{}".format( self.config["COVID19"]["GrowingRateMulti"]) ] self.data["keys"] = newkeys self.data["columns"] = self.keys_basenames units = ["#" for i in self.keys_basenames] for key, dat in zip(newkeys, [seldata, growth, relgrowth]): self.data[key] = { "analysed": False, "plots": False, "header": "" } self.data[key]["measurements"] = self.keys_basenames self.data[key]["units"] = units #self.data[key]["units"][-2] = "%" # The last one is percent dat["Date"] = pd.to_datetime(pd.Series(self.measurements, name="Date", index=pd.Index( self.measurements)), infer_datetime_format=True) dat["Date"] = dat["Date"].dt.to_period('d') dat["Name"] = pd.Series([key for i in self.measurements], name="Name", index=pd.Index(self.measurements)) self.data[key]["measurements"].append("Date") self.data[key]["units"].append("") self.data[key]["data"] = pd.DataFrame(dat) # Start plotting # All individual donts = ["Date"] individual = plot_all_measurements( self.data, self.config, "Date", "COVID19", keys=[ "Accumulated", "Growth", "RelativeGrowth*{}".format( self.config["COVID19"]["GrowingRateMulti"]) ], do_not_plot=donts, PlotLabel="{}".format(countryName)) if self.Plots: self.Plots += individual else: self.Plots = individual self.relgrowth_all_countries(countryName) if self.config["COVID19"]["Normalize"] == True: self.accumulated_all_countries_normalizes( countryName, inhabitants) elif self.config["COVID19"]["Normalize"] == False: self.accumulated_all_countries(countryName) # Cases vs growth if not self.GrowthvsCases: self.GrowthvsCases = plainPlot( "Curve", self.data["Accumulated"]["data"]["confirmed"], self.data["Growth"]["data"]["confirmed"], label=countryName, ylabel="New Cases", **self.config['COVID19']['General'], **self.config['COVID19']['GvC']["PlotOptions"]) else: self.GrowthvsCases *= plainPlot( "Curve", self.data["Accumulated"]["data"]["confirmed"], self.data["Growth"]["data"]["confirmed"], label=countryName, ylabel="New Cases", **self.config['COVID19']['General'], **self.config['COVID19']['GvC']["PlotOptions"]) # Death vs growth if not self.DeathvsCases: self.DeathvsCases = plainPlot( "Curve", self.data["Accumulated"]["data"]["confirmed"], self.data["Accumulated"]["data"]["deaths"], label=countryName, ylabel="Total Deaths", **self.config['COVID19']['General'], **self.config['COVID19']['GvC']["PlotOptions"]) else: self.DeathvsCases *= plainPlot( "Curve", self.data["Accumulated"]["data"]["confirmed"], self.data["Accumulated"]["data"]["deaths"], label=countryName, ylabel="Total Deaths", **self.config['COVID19']['General'], **self.config['COVID19']['GvC']["PlotOptions"]) # Relabel the plots self.GrowthvsCases = relabelPlot( self.GrowthvsCases.opts(xlim=(1, None), ylim=(1, None)), "New Cases vs. Total Cases") self.DeathvsCases = relabelPlot( self.DeathvsCases.opts(xlim=(1, None), ylim=(1, None)), "Total Death vs. Total Cases") if not self.config["COVID19"]["Normalize"]: self.cases = relabelPlot(self.cases, "Confirmed Cases not normalized") self.recovered = relabelPlot(self.recovered, "Recovered Cases not normalized") self.deaths = relabelPlot(self.deaths, "Deaths not normalized") self.casesrelgrowth = relabelPlot(self.casesrelgrowth, "Confirmed Cases relative growth") self.recoveredrelgrowth = relabelPlot( self.recoveredrelgrowth, "Recovered Cases relative growth") self.deathsrelgrowth = relabelPlot(self.deathsrelgrowth, "Deaths relative growth") if self.config["COVID19"]["Normalize"]: self.casesNorm = relabelPlot(self.casesNorm, "Confirmed Cases normalized") self.recoveredNorm = relabelPlot(self.recoveredNorm, "Recovered Cases normalized") self.deathsNorm = relabelPlot(self.deathsNorm, "Deaths normalized") # Define Plotting order self.plottingOrder = [ self.GrowthvsCases, self.DeathvsCases, self.casesNorm, self.recoveredNorm, self.deathsNorm, self.casesrelgrowth, self.recoveredrelgrowth, self.deathsrelgrowth, self.cases, self.recovered, self.deaths, self.Plots ] for plot in self.plottingOrder: if plot: if self.PlotDict["All"]: self.PlotDict["All"] += plot else: self.PlotDict["All"] = plot # Reconfig the plots to be sure self.PlotDict["All"].opts(opts.Bars(stacked=True)) self.PlotDict["All"] = config_layout( self.PlotDict["All"], **self.config.get(self.analysisname, {}).get("Layout", {})) return self.PlotDict