def components(self, start, window): component_data = self.transformer.fit_transform( self.data.iloc[start:(start + window), :].T) if self.labels: data_labels = reduce( mul, pd.DataFrame( component_data, index=self.data.columns.tolist(), columns=["Component_1", "Component_2"], ).reset_index().apply( lambda x: hv.Text( x[1], x[2], " ".join(x[0].split()[:-1]), fontsize=8), axis=1, ).tolist(), ) else: data_labels = hv.Text(0, 0, "") return (pd.DataFrame( component_data, columns=["Component_1", "Component_2"] ).hvplot.scatter(x="Component_1", y="Component_2").redim( Component_2={ "range": (-0.1, 0.3) }, Component_1={ "range": (-0.03, 0.05) }).redim.label( Component_1= f"Component 1 {self.transformer.explained_variance_ratio_[0].round(4)}%", Component_2= f"Component 2 {self.transformer.explained_variance_ratio_[1].round(4)}%", ).options(alpha=1) * data_labels)
def scalebar_cropped(self, x_range, y_range): if x_range and y_range: x0, x1 = x_range y0, y1 = y_range x_span = x1 - x0 y_span = y1 - y0 y0 = y0 + int(y_span / 20) y1 = y0 + int(y_span / 50) ytext = y1 + int(y_span / 30) x0 = x1 - self.scalebar_size_cropped - int(x_span / 30) x1 = x1 - int(x_span / 30) rect = hv.Rectangles((x0, y0, x1, y1)).opts(color="w") text = hv.Text(x0, ytext, str(self.scalebar_size_cropped) + " um").opts( text_color="w", text_align="left", text_font="Helvetica" ) scalebar = rect * text return scalebar else: x0 = self.x_range[0] y0 = self.y_range[0] x1 = self.x_range[1] y1 = self.y_range[1] x_span = x1 - x0 y_span = y1 - y0 y0 = y0 + int(y_span / 20) y1 = y0 + int(y_span / 50) x0 = x1 - self.scalebar_size_cropped - int(x_span / 40) x1 = x1 - int(x_span / 30) ytext = y1 + int(y_span / 30) rect = hv.Rectangles((x0, y0, x1, y1)).opts(color="w") text = hv.Text(x0, ytext, str(self.scalebar_size_cropped) + " um").opts( text_color="w", text_align="left", text_font="Helvetica" ) scalebar = rect * text return scalebar
def scalebar(self, x_range, y_range): if x_range and y_range: x0, x1 = x_range y0, y1 = y_range x_span = x1 - x0 y_span = y1 - y0 y0 = y0 + int(y_span / 20) y1 = y0 + int(y_span / 50) ytext = y1 + int(y_span / 30) x0 = x1 - self.scalebar_size - int(x_span / 30) x1 = x1 - int(x_span / 30) rect = hv.Rectangles((x0, y0, x1, y1)).opts(color="w") text = hv.Text(x0, ytext, str(self.scalebar_size) + " um").opts( text_color="w", text_align="left", text_font="Helvetica" ) scalebar = rect * text return scalebar else: x0 = 0 y0 = 0 x1 = self.rendered_image.data["x"].size y1 = self.rendered_image.data["y"].size x_span = x1 - x0 y_span = y1 - y0 y0 = y0 + int(y_span / 20) y1 = y0 + int(y_span / 50) x0 = x1 - self.scalebar_size - int(x_span / 40) x1 = x1 - int(x_span / 30) ytext = y1 + int(y_span / 30) rect = hv.Rectangles((x0, y0, x1, y1)).opts(color="w") text = hv.Text(x0, ytext, str(self.scalebar_size) + " um").opts( text_color="w", text_align="left", text_font="Helvetica" ) scalebar = rect * text return scalebar
def h_text(data): #function to write ycrop value center=frame.shape[1]//2 try: y=int(np.around(data['y'][0])) htext=hv.Text(center,y+10,'ycrop: {x}'.format(x=y)) return htext except: htext=hv.Text(center,10, 'ycrop: 0') return htext
def cross_hair_info(x, y): text = hv.Text(x + 0.05, y, "%.3f %.3f %.3f" % (x, y, img[x, y]), halign="left", valign="bottom") return hv.HLine(y) * hv.VLine(x) * text
def __init__(self, data, configs): '''removes wrong data''' for file in list(data.keys()): if "contact chain" not in data[file]["header"][3].lower(): data.pop(file) self.log = logging.getLogger(__name__) self.data = convert_to_df(data, abs=False) self.config = configs self.df = [] self.basePlots = None self.analysisname = "Contact_Chain" self.PlotDict = {"Name": self.analysisname} self.measurements = self.data["columns"] self.sort_parameter = self.config["Contact_Chain"]["Bar_chart"][ "CreateBarChart"] self.Substrate_Type = ["Polysilicon", "N+", "P+"] self.filename_df = pd.DataFrame(columns=[ "Filename", "Substrate Type", "_", "Batch", "Wafer No.", "_", "HM location", "Test structure", "Resistance", "Standard deviation" ]) self.PlotDict["All"] = None self.limits = {"Polysilicon": 4 * 10**7, "N+": 10**5, "P+": 8 * 10**4} self.files_to_fit = self.config["files_to_fit"] hvtext = hv.Text(0, 0, self.analysisname, fontsize=20).opts(color="black", xlabel='', ylabel='') box = hv.Polygons(hv.Box(0, 0, 1).opts(color="black")).opts(color="white") self.PlotDict["All"] = box * hvtext
def integrated_charge(limit_a, limit_b, y, iteration): # compute 1D histogram energy_hist, bin_edges, nbins = particle_energy_histogram( tseries=time_series, it=iteration, cutoff=np.inf, # no cutoff energy_max=e_max, ) histogram = hv.Histogram((bin_edges, energy_hist), kdims=energy, vdims=count) curve = hv.Curve(histogram) e_min = histogram.edges[0] limit_a = e_min if limit_a is None else np.clip(limit_a, e_min, e_max) limit_b = e_max if limit_b is None else np.clip(limit_b, e_min, e_max) area = hv.Area((curve.dimension_values('energy'), curve.dimension_values('frequency')))[limit_a:limit_b] charge = np.sum( np.diff(histogram[limit_a:limit_b].edges) * histogram[limit_a:limit_b].values) return curve * area * hv.VLine(limit_a) * hv.VLine(limit_b) * hv.Text( limit_b - 2., 5, 'Q = %.0f pC' % charge)
def plot_ana(self, x, y, dy, file, ana_type): curve = hv.Curve(zip(x, y), kdims=self.measurements[1], vdims=self.measurements[2]) derivative = hv.Curve(zip(x, dy)).opts(color="gray") df = pd.DataFrame({"x": x, "y": y, "dy": dy}) '''returns voltage and: for Ana 1 fit line, for Ana 2/3 line to show where the voltage is''' voltage, line = self.find_voltage(df, x, ana_type) voltage = round(voltage, 4) text_str = "voltage: " + str(voltage) if ana_type == "Ana 3": text_str += "\nDerivative scaled down by: \n/ (2 * 10^6)" text = hv.Text(min(dy) * (6 / 4), max(dy) * (7 / 8), text_str, fontsize=20) curve = curve * derivative * line * text if ana_type == "Ana 3": curve.opts(**self.config["FET"].get("General", {}), ylim=(min(dy) - 3 * min(y) / 20, max(dy) + max(dy) / 10)) else: curve.opts(**self.config["FET"].get("General", {}), ylim=(min(y) - 3 * min(y) / 20, max(y) + max(y) / 10)) self.data[file][ana_type] = voltage if self.PlotDict["All"] is None: self.PlotDict["All"] = curve else: self.PlotDict["All"] = self.PlotDict["All"] + curve
def plot_flatband_v(x, y, ana_type, **kwargs): ''' **kwargs for customizing the plot, ana_type must ether be "fit" or "derivative" ''' x, y = list(x), list(y) if ana_type == "fit": voltage, middle_line, right_line = fit_analysis(x, y) elif ana_type == "derivative": voltage = derivative_analysis(x, y) else: log.error("ana_type must either be 'derivative' or 'fit'") exit(1) curve = hv.Curve(zip(x, y), kdims="voltage_hvsrc", vdims="capactiance") text_str = "Flatband Voltage: " + str(voltage) + "\nAnalysis Type: " + ana_type text = hv.Text(max(x) * (3 / 4), max(y) * (3 / 4), text_str, fontsize=20) line = hv.VLine(voltage).opts(color="black", line_width=1.0) curve = curve * text * line if ana_type == "fit": mid = hv.Curve([*middle_line]).opts(color="red", line_width=1.5) right = hv.Curve([*right_line]).opts(color="blue", line_width=1.0) curve = curve * text * line * mid * right curve.opts(ylim=(min(y) - 3 * min(y) / 20, max(y) + max(y) / 10), **kwargs) return curve
def fetch_mpl_obj(self): group = "Gas Concentration vs Time" plot = dict(aspect=2) legend = dict(legend_position='best', aspect=2) graph = None options = hv.Store.options(backend='matplotlib') options.Curve = hv.Options('style', color=hv.Cycle(values=self.gases.values()), linewidth=2) for data in self.graph_data: graph_inter = hv.Curve(data['data'], vdims=['Gas Concentration'], kdims=['Time'], label=data['label'], group=group) if graph: graph *= graph_inter else: graph = graph_inter for data in self.text_labels: graph *= hv.Text(data['key'], data['value'], data['date'], fontsize=10) opts = {'Curve': {'plot': plot}, 'Overlay': {'plot': legend}} self.mpl_obj = graph(opts) if graph else None
def plot_flatband(self, file, ana_type, interpol): '''plot function for both "derivative" and "fit" analysis''' x, y = self.data[file][ana_type]["dataframe"]['x'], self.data[file][ ana_type]["dataframe"]['y'] curve = hv.Curve(zip(x, y), kdims=self.measurements[1], vdims=self.measurements[3]) text_str = "Flatband Voltage: " + str( self.data[file][ana_type]["flatband"] ) + "\nAnalysis Type: " + ana_type + "\nInterpolated: " + str(interpol) text = hv.Text(x.max() * (3 / 4), y.max() * (3 / 4), text_str, fontsize=20) line = hv.VLine(self.data[file][ana_type]["flatband"]).opts( color="black", line_width=1.0) curve = curve * text * line if ana_type == "fit": curve = curve * text * line * self.data[file]["fit"]["lines"][ 0] * self.data[file]["fit"]["lines"][1] curve.opts(**self.config["MOS_CV"].get("General", {}), ylim=(y.min() - 3 * y.min() / 20, y.max() + y.max() / 10)) if self.PlotDict["All"] is None: self.PlotDict["All"] = curve else: self.PlotDict["All"] = self.PlotDict["All"] + curve
def _legend_texts(df): width = _max_width(df) text_opts = LEGEND_TEXT_OPTS.copy() text_opts.update({"xlim": (-1, width)}) texts = [] for _, r in df.iterrows(): texts.append(hv.Text(r["x"] + 1, r["y"], r["name"]).opts(**text_opts)) return texts
def integral(limit_a, limit_b, y, time): limit_a = -3 if limit_a is None else np.clip(limit_a, -3, 3) limit_b = 3 if limit_b is None else np.clip(limit_b, -3, 3) curve = hv.Curve((xs, function(xs, time))) area = hv.Area((xs, function(xs, time)))[limit_a:limit_b] summed = area.dimension_values('y').sum() * 0.015 # Numeric approximation return (area * curve * hv.VLine(limit_a) * hv.VLine(limit_b) * hv.Text(limit_b - 0.8, 2.0, '%.2f' % summed))
def make_text(content): return hv.Text(0, 0, content).opts(img_opts).opts(toolbar=None, height=100, width=150, xaxis=None, yaxis=None, text_alpha=1.0, bgcolor='lightgrey')
def plot_surface(obj, **args): region = args.get('region', None) idx = obj.tag2idx(region) tags = args.get('tags', False) coord = args.get('coord', None) locator = args.get('locator', False) fill = args.get('fill', None) amin = np.min(obj.bbox_min[idx], axis=0) amax = np.max(obj.bbox_max[idx], axis=0) wh = amax - amin if np.min(wh) < 250: wh = wh / np.min(wh) * 250 hvobj = hv.Path([obj.boundary[i] for i in idx]).opts(style=dict(color='k'), plot=dict(yaxis=None, xaxis=None, aspect='equal', width=int(ceil(wh[0])), height=int(ceil(wh[1])))) if fill is not None: vals = np.nan * np.zeros((obj.num, )) for k in fill.keys(): _idx = obj.tag2idx(k) for i in _idx: vals[i] = fill[k] imin = np.min(obj.bbox_min[idx], axis=0).astype(int) imax = np.max(obj.bbox_max[idx], axis=0).astype(int) im = np.nan * np.zeros(tuple((imax - imin + 1)[::-1].tolist())) for i in idx: im[obj._coords[i][:, 1] - imin[1], obj._coords[i][:, 0] - imin[0]] = vals[i] hvobj = hv.Image(np.flipud(im), bounds=(imin[0], imin[1], imax[0], imax[1])).opts( plot=dict(yaxis=None, xaxis=None)) if coord is not None: hvobj *= hv.Curve([obj.hand2pixel((0,0)),obj.hand2pixel((coord,0))]) *\ hv.Curve([obj.hand2pixel((0,0)),obj.hand2pixel((0,coord))]) if tags: hvobj *= hv.Labels({ 'x': [obj._centers[i][0] for i in idx], 'y': [obj._centers[i][1] for i in idx], 'Label': [str(i) + ' ' + ''.join(obj.tags[i]) for i in idx] }) # show cursor position in hand coordinates (works only in bokeh) if locator: pointer = hv.streams.PointerXY(x=0, y=0) dm = hv.DynamicMap(lambda x, y: hvobj * hv.Text( x, y + 5, '(%d,%d)' % tuple(obj.pixel2hand(np.array([x, y])))), streams=[pointer]) return dm return hvobj
def _show_sunset_hour(df, geoloc): hover = HoverTool(tooltips=[ ('Date', '@datetime{%m/%d}'), ('Hour of Sunset', '@hour{0.1f}'), ('Length of Day', '@daylight{0.1f}'), ], formatters={ 'datetime': 'datetime', }, mode='vline') sunset_df = df.copy() sunset_df = df.loc[df['sun_down'] == False, :] sunset_df = sunset_df.assign(**{ 'hour': sunset_df['hour'] - 12, 'hour_24': sunset_df['hour_24'] - 12 }) lat, lon = geoloc.latitude, geoloc.longitude address = geoloc.address sunset_curve = sunset_df.hvplot('datetime', 'hour', hover_cols=['daylight'], responsive=True) sunset_curve = sunset_curve.opts( invert_yaxis=True, color='darkblue', xlabel='Date', ylabel='PM Hour of Sunset [Local Time]', title=f'Yearly Sunset Hour at {address} ({lat:.1f} N, {lon:.1f} E)', hooks=[_format_datetime_axis], show_grid=True, gridstyle={'ygrid_line_alpha': 0}, tools=[hover], ylim=(4, 9)) sun_up = hv.Area(df.loc[df['sun_down'] == False], 'datetime', 'hour') sun_up = sun_up.opts(color='tan', alpha=0.15, responsive=True) sun_down = hv.Area(sunset_df, 'datetime', ['hour', 'hour_24']) sun_down = sun_down.opts(color='darkblue', alpha=0.15, responsive=True) five_pm_line = hv.HLine(5).opts(color='black', alpha=0.1, line_dash='dotted', responsive=True) five_pm_txt = hv.Text(pd.datetime(2020, 7, 4), 5, '5 PM') five_pm_txt = five_pm_txt.opts(text_font_size='1.5em', text_alpha=0.2, text_baseline='bottom', text_align='left', responsive=True) overlay = (sunset_curve * sun_up * sun_down * five_pm_line * five_pm_txt) return overlay
def _timetable(self, x, y): if self.solutions.empty: return (hv.Points((0, 0)).opts(alpha=0) * hv.Text( 0, 0, 'No Journeys Found').opts(color='firebrick')).opts( xlim=(-1, 1), xaxis=None, yaxis=None, show_frame=False, toolbar=None) stop_time = self.stop_time * 10**3 time_delta = stop_time - self.solutions['start_time'].min() boxes_opts = { 'color': 'color', 'line_width': 0, 'tools': [ HoverTool( tooltips=[('From', '@station_name'), ('To', '@station_name_stop'), ('Departure Time', '@departure'), ('Arrival Time', '@arrival'), ('Travel Type', '@transport_type'), ( 'Line', '@line_text'), ('Trip', '@trip_id')]) ], } opts = { 'height': int(self.solutions['path'].max() + 3) * 50, 'width': 600, 'ylim': (-1, self.solutions['path'].max() + 2), 'xlim': (self.solutions['start_time'].min() - time_delta * 0.1, stop_time + time_delta * 0.1), 'hooks': [datetime_ticks], 'yaxis': None, 'show_frame': False, 'xlabel': '', 'toolbar': None, 'active_tools': [] } boxes = hv.Rectangles( self.line_aggregate, ['start_time', 'y_min', 'stop_time', 'y_max'], [ 'color', 'station_name', 'station_name_stop', 'departure', 'arrival', 'transport_type', 'trip_id', 'line_text' ]).opts(**boxes_opts) text = self._timetable_text() stop_line = hv.VLine(stop_time).opts(line_width=1, line_color='red') return (boxes * text * stop_line).opts(**opts)
def _timetable_text(self): fontsize = 8 texts = [] for _, connection in self.line_aggregate.iterrows(): start_time = connection['start_time'] y = connection['y_min'] icon = transport_icons[connection['transport_type']] short_line = connection['line_text'] texts.append( hv.Text(x=start_time, y=y - 0.15, text=f'{icon}{short_line}', halign='left', valign='top', fontsize=fontsize)) for _, journey in self.journey_aggregate.iterrows(): arrival_text = journey['travel_time_str'] + ' - ' + journey[ 'arrival'] probability_text = f" {journey['probability']:6.3%}" texts.extend([ hv.Text(x=journey['start_time'], y=journey['y_max'], text=journey['departure'], halign='left', valign='bottom', fontsize=fontsize), hv.Text(x=journey['stop_time'], y=journey['y_max'], text=arrival_text, halign='right', valign='bottom', fontsize=fontsize), hv.Text(x=self.stop_time * 10**3, y=journey['path'], text=probability_text, halign='left', valign='bottom', fontsize=fontsize) ]) return hv.Overlay(texts)
def text_box(text, xpos, ypos, boxsize, fontsize=30, fontcolor="black", bgcolor="white"): """Generates a box with text in it""" hvtext = hv.Text(xpos, ypos, text).opts(fontsize=fontsize, color=fontcolor) box = hv.Polygons(hv.Box(xpos, ypos, boxsize).opts(color="black")).opts(color=bgcolor) return box * hvtext
def map_indicators(self): self.indicateur_dpt_plot() for idx in self.df_indic_dpt.index: an_indic = self.df_indic_dpt.loc[idx, 'Parametre'] color = self.determine_color(an_indic, self.df_indic_dpt.loc[idx, 'value'], 20) self.df_indic_dpt.at[idx, 'color'] = color dates_to_print = [ date.strftime(format='%d-%m-%Y') for date in [self.date_ini, self.date_final] ] tooltips = [ ("Taux d'incidence", '@tx_incid_2'), ('Facteur de reproduction', '@R_2'), ("Taux d'occupation des lits en réa", '@taux_occupation_sae_2'), ('Taux de positivité', '@tx_pos_2'), ('Région', '@libelle_reg'), ('Département', '@libelle_dep') ] hover = HoverTool(tooltips=tooltips) key_dimensions = ['Longitude', 'Latitude', 'Date', 'Parametre'] MapDataSet = hv.Dataset(self.df_indic_dpt, vdims=[ 'value', 'color', 'libelle_reg', 'libelle_dep', 'tx_incid_2', 'R_2', 'taux_occupation_sae_2', 'tx_pos_2' ], kdims=key_dimensions) MapDataSet = MapDataSet.to(geoviews.Polygons) MapRel = MapDataSet.opts( width=1000, height=560, tools=[hover], color='color', xaxis=None, yaxis=None, title= f"Cartes des indicateurs du {dates_to_print[0]} au {dates_to_print[1]}" ) MapRel_tot = MapRel * gvts.CartoLight sum_map = MapRel_tot text = hv.Curve((0, 0)).opts(xaxis=None, yaxis=None) * hv.Text( 0, 0, 'Source: Santé Publique France\nGraph: C.Houzard') MapOutput = (geoviews.Layout(sum_map + text)).cols(1) renderer = hv.renderer('bokeh') #renderer.save(MapOutput, os.path.normcase(f'map')) file_fct.save_fig(MapOutput, 'Map_France_Indic', self.date_final)
def plot_pct_of_newborns(name, years): name_tot = _query_name(name, years) name_tseries = _finalize_obj(name_tot.hvplot( YEAR, PCT_NB, hover=False, groupby=[NAME], color=DEFAULT_COLORS, hover_cols=[COUNT, PCT_FM], ).overlay(NAME), years, hover=False) name_points = _finalize_obj( name_tot.hvplot.points( YEAR, PCT_NB, hover=False, hover_cols=[NAME, COUNT, PCT_FM], cmap='RdYlBu_r').options( color_index=PCT_FM, colorbar=True, marker='o', colorbar_opts={ 'title': '%F' }, size=15, alpha=0.15, line_color='lightgray', line_alpha=0.35).redim.range(pct_female=(0, 100)), years) top_year, top_name, top_count, top_pct_female, top_pct_newborns = ( name_tot.loc[name_tot[COUNT] == name_tot[COUNT].max()].values[0]) min_year = _decide_year(top_name, name_tot) text_align, text_offset = _smart_align(min_year) summary_kwds = [ top_year, top_count, top_name, newborns.loc[top_year][0], top_pct_newborns ] name_summary = (hv.Text( min_year + text_offset, name_tot[PCT_NB].quantile(0.985), SUMMARY_FMT.format(*summary_kwds)).options(color='#5B5B5B', text_align=text_align, text_baseline='top', text_font_size='1.05em', text_font='Helvetica', text_alpha=0.65)) return (name_tseries * name_points * name_summary)
def __init__(self, data, configs): '''removes wrong data''' for file in list(data.keys()): if "Linewidth".lower() not in data[file]["header"][3].lower(): data.pop(file) self.log = logging.getLogger(__name__) self.data = convert_to_df(data, abs=False) self.config = configs self.df = [] self.basePlots = None self.analysisname = "Linewidth" self.PlotDict = {"Name": self.analysisname} self.measurements = self.data["columns"] self.PlotDict["All"] = None self.sort_parameter = self.config["Linewidth"]["Bar_chart"][ "CreateBarChart"] self.Substrate_Type = ["P+", "N+", "P-stop"] self.filename_df = pd.DataFrame(columns=[ "Filename", "Substrate Type", "_", "Batch", "Wafer No.", "_", "HM location", "Test structure", "Linewidth [um]", "Standard deviation" ]) self.limits = {"P+": 0.05, "N+": 0.00001, "P-stop": 0.0005} self.files_to_fit = self.config["files_to_fit"] self.sheet_dic = { "P+": self.config["Linewidth"]["parameter"]["sheet_r_p+"], "N+": self.config["Linewidth"]["parameter"]["sheet_r_N+"], "P-stop": self.config["Linewidth"]["parameter"]["sheet_r_ps"] } self.std_dic = { "P+": self.config["Linewidth"]["parameter"]["std_p+"], "N+": self.config["Linewidth"]["parameter"]["std_N+"], "P-stop": self.config["Linewidth"]["parameter"]["std_ps"] } hvtext = hv.Text(0, 0, self.analysisname, fontsize=25).opts(color="black", xlabel='', ylabel='') box = hv.Polygons(hv.Box(0, 0, 300).opts(color="black")).opts(color="white") self.PlotDict["All"] = box * hvtext
def __init__(self, data, configs): '''removes wrong data''' for file in list(data.keys()): if "van-der-pauw" not in data[file]["header"][3].lower( ) and "bulk cross" not in data[file]["header"][3].lower(): data.pop(file) self.log = logging.getLogger(__name__) self.data = convert_to_df(data, abs=False) self.config = configs self.df = [] self.basePlots = None self.analysisname = "Van_der_Pauw" self.PlotDict = {"Name": self.analysisname} self.measurements = self.data["columns"] self.PlotDict["All"] = None self.sort_parameter = self.config["Van_der_Pauw"]["Bar_chart"][ "CreateBarChart"] self.Substrate_Type = [ "P-stop", "Polysilicon", "N+", "P+", "Metal", "bulk" ] '''columns have to be fitted according to sample_name + sample_type layout''' self.filename_df = pd.DataFrame(columns=[ "Filename", "Substrate Type", "_", "Batch", "Wafer No.", "_", "HM location", "Test structure", "_", "Sheet Resistance [Ohm/sq]", "Standard deviation" ]) self.limits = { "P-stop": 25000, "Polysilicon": 3000, "N+": 50, "P+": 1300, "Metal": 0.03, "bulk": 70000 } self.files_to_fit = self.config["files_to_fit"] hvtext = hv.Text(0, 0, self.analysisname, fontsize=13).opts(color="black", xlabel='', ylabel='') box = hv.Polygons(hv.Box(0, 0, 2).opts(color="black")).opts(color="white") self.PlotDict["All"] = box * hvtext
def value_plot( value, unit='°C', palette=palettes.Plasma5, ylim=(-20, 40), low=0, high=40, ): """ On représente les mesures environnementales (température, humidité, pression) avec un baton et un rond dans lequel sera inscrit la valeur numérique. """ scat = hv.Scatter({0: value}) #le rond en position 0 spik = hv.Spikes(scat) #le baton au même endroit lab = hv.Text(x=0, y=value, text=f"{value}{unit}") #la valeur numérique et l'unité mapper = linear_cmap( field_name='y', palette=palette, low=low, high=high) #la couleur du rond dépend de la valeur opts = dict( ylim=ylim, #on donne la même limite à tous color=mapper, responsive=True, #la dimension sera dynamique ou "responsive" xaxis=None, yaxis=None, #pas d'axe pour aléger toolbar='disable', #pas besoin de zoomer ou autre... min_width=80, height=150, border=0) layout = ( spik * scat * lab ).opts( #on met le label tout au dessus, puis le rond, puis le baton caché derrière hv.opts.Scatter(size=80, **opts), hv.opts.Spikes(line_width=3, **opts), hv.opts.Text(color='black'), ) return layout.opts(shared_axes=False)
def plot_ana(x, y, dy, ana_type, **kwargs): curve = hv.Curve(zip(x, y)) derivative = hv.Curve(zip(x, dy)).opts(color="gray") df = pd.DataFrame({"x": x, "y": y, "dy": dy}) '''returns voltage and: for Ana 1 fit line, for Ana 2/3 line to show where the voltage is''' voltage, line = find_voltage(df, x, ana_type) voltage = round(voltage, 4) text_str = "voltage: " + str(voltage) if ana_type == "Ana 3": text_str += "\nDerivative scaled down by: \n/ (2 * 10^6)" text = hv.Text(min(dy) * (6 / 4), max(dy) * (7 / 8), text_str, fontsize=20) curve = curve * derivative * line * text if ana_type == "Ana 3": curve.opts(ylim=(min(dy) - 3 * min(y) / 20, max(dy) + max(dy) / 10), **kwargs) else: curve.opts(ylim=(min(y) - 3 * min(y) / 20, max(y) + max(y) / 10), **kwargs) return curve
def __init__(self, data, configs): '''removes wrong data''' for file in list(data.keys()): if "meander" not in data[file]["header"][3]: data.pop(file) self.log = logging.getLogger(__name__) self.data = convert_to_df( data, abs=False ) ## funktioniert nicht komplet da metal und poly andere messungen haben self.complete_df(data) self.config = configs self.df = [] self.basePlots = None self.analysisname = "Meander" self.PlotDict = {"Name": self.analysisname} self.measurements = self.data["columns"] self.sort_parameter = self.config["Meander"]["Bar_chart"][ "CreateBarChart"] self.Substrate_Type = ["Polysilicon", "Metal"] self.filename_df = pd.DataFrame(columns=[ "Filename", "Substrate Type", "_", "Batch", "Wafer No.", "_", "HM location", "Test structure", "_", "Resistivity", "Standard deviation", "specific Resistivity [Ohm/sq]" ]) self.PlotDict["All"] = None self.limits = {"Polysilicon": 2 * 10**6, "Metal": 450} self.files_to_fit = self.config["files_to_fit"] self.squares = { "Polysilicon": self.config["Meander"]["parameter"]["squares_poly"], "Metal": self.config["Meander"]["parameter"]["squares_m"] } hvtext = hv.Text(0, 0, self.analysisname, fontsize=13).opts(color="black", xlabel='', ylabel='') box = hv.Polygons(hv.Box(0, 0, 2).opts(color="black")).opts(color="white") self.PlotDict["All"] = box * hvtext
def value_plot(value,unit='°C',palette=palettes.Plasma5,ylim=(-20,40),low=0,high=40,): scat = hv.Scatter({0:value},kdims='x',vdims='y') spik = hv.Spikes(scat,kdims='x',vdims='y') lab = hv.Text(x=0,y=value,text=f"{value}{unit}") mapper = linear_cmap(field_name='y',palette=palette,low=low,high=high) opts=dict(ylim=ylim, responsive=True, xaxis=None,yaxis=None, toolbar='disable', min_width=80, height=150, border=0) layout = (spik*scat*lab).opts( hv.opts.Scatter(size=80,color=mapper,**opts), hv.opts.Spikes(line_width=3,**opts), hv.opts.Text(color='black'), ) return layout.opts(shared_axes=False)
def Histogram(dfs, measurement, configs, analysisType, bins=50, iqr=None, **addConfigs): """Generates a Points Plot with a corresponding Histogram""" newConfigs = addConfigs log.info("Generating histograms for measurement {}...".format(measurement)) finalplots = None try: for key in dfs["keys"]: log.info("Generating histograms for measurement {} for file {}...". format(measurement, key)) # Sanatize data data = dfs[key]["data"][measurement].dropna() # Drop all nan if iqr: log.info("Outliers correction with iqr: {}".format(iqr)) data = reject_outliers(data, iqr) mean = np.round(np.mean(data), 2) rms = np.round(np.sqrt(np.mean(data**2)), 2) std = np.round(np.std(data), 2) median = np.round(np.median(data), 2) data = np.histogram(data, bins=bins) plt = hv.Histogram(data, label="Histogram: {}".format(measurement), group="Histogram: {}: {}".format( measurement, key)) try: xlabel = "{} [{}]".format( measurement, dfs[dfs["keys"][0]]["units"][dfs[ dfs["keys"][0]]["measurements"].index(measurement)]) except Exception as err: log.error( "Label could not be generated for Histogram {}. Error: {}". format(measurement, err)) xlabel = "X-Axis" plt.opts(xlabel=xlabel) # Update the plot specific options if need be generalOptions = configs[analysisType].get("General", {}) newConfigs.update(generalOptions.copy()) data_options = configs[analysisType].get(measurement, {}).get( "Single Histogram", {}).get("PlotOptions", {}) newConfigs.update(configs[analysisType].get( "{}Options".format("Histogram"), {})) newConfigs.update(data_options) plots = customize_plot(plt, "", configs[analysisType], **newConfigs) # Add text text = '\nMean: {mean} \n' \ 'Median: {median} \n' \ 'RMS: {rms}\n' \ 'std: {std}'.format(mean=mean, median=median, rms=rms, std=std) log.info(text) y = data[0].max() x = data[1][int(len(data[1]) * 0.9)] text = hv.Text(x, y, text).opts(fontsize=30) #text = text_box(text, x, y, boxsize= (100, 150)) plots = plots * text if finalplots: finalplots += plots else: finalplots = plots except Exception as err: log.error( "Unexpected error happened during Hist plot generation {}. Error: {}" .format(measurement, err)) return None return finalplots
def concatHistogram(dfs, measurement, configs, analysisType, bins=50, iqr=None, **addConfigs): """Concatenates dataframes and generates a Histogram for all passed columns""" newConfigs = addConfigs log.info("Generating concat histograms for measurements {}...".format( measurement)) try: df = dfs["All"] # Sanatize data data = df[measurement].dropna() # Drop all nan if iqr: log.info("Outliers correction with iqr: {}".format(iqr)) data = reject_outliers(data, iqr) mean = np.round(np.mean(data), 2) rms = np.round(np.sqrt(np.mean(data**2)), 2) std = np.round(np.std(data), 2) median = np.round(np.median(data), 2) data = np.histogram(data, bins=bins) plt = hv.Histogram( data, label="Concatenated Histogram: {}".format(measurement), group="Concatenated Histogram: {}".format(measurement)) #plt = hv.Histogram(data, vdims=to_plot, group="Concatenated Histogram: {}".format(to_plot)) try: xlabel = "{} [{}]".format( measurement, dfs[dfs["keys"][0]]["units"][dfs[ dfs["keys"][0]]["measurements"].index(measurement)]) except Exception as err: log.error( "Label could not be genereated for concatonated Histogram {}. Error: {}" .format(measurement, err)) xlabel = "X-Axis" plt.opts(xlabel=xlabel) # Update the plot specific options if need be generalOptions = configs[analysisType].get("General", {}) newConfigs.update(generalOptions.copy()) data_options = configs[analysisType].get(measurement, {}).get( "Concatenated Histogram", {}).get("PlotOptions", {}) newConfigs.update(configs[analysisType].get( "{}Options".format("Histogram"), {})) newConfigs.update(data_options) #addConfigs.update({"xlabel": measurement}) plots = customize_plot(plt, "", configs[analysisType], **newConfigs) # Add text text = '\nMean: {mean} \n' \ 'Median: {median} \n' \ 'RMS: {rms}\n' \ 'std: {std}'.format(mean=mean, median=median, rms=rms, std=std) log.info(text) y = data[0].max() x = data[1][int(len(data[1]) * 0.9)] text = hv.Text(x, y, text).opts(fontsize=30) plots = plots * text except Exception as err: log.error( "Unexpected error happened during concatHist plot generation {}. Error: {}" .format(measurement, err)) return None return plots
def h_track(x, y): #function to track pointer y = int(np.around(y)) text = hv.Text(x, y, str(y), halign='left', valign='bottom') return hv.HLine(y) * text