def _collect_lockdown_tooltip_layers(self, df, layers, base, cursor): # Since it's difficult to support a condition of type 'mouseover OR checkbox' # (due to broken alt.condition not two non-constants for if_true and if_false # and due to completely broken checkboxes in Vega Lite), we'll add two layers # to accompish the same thing. The first layer will be active when 'mouseover # AND NOT checkbox' and the second layer will be active when just 'checkbox'. def _make_base(tooltip): ret = base.mark_text( align='left', dx=15, dy=0, font=self._font, fontWeight=600, ).encode( x=self._get_x(), y=self._get_y(), text=tooltip, color=alt.value('black') ).transform_calculate( # AGP lockdown_tooltip_text=f'datum.{self._detailby} + " " + datum.lockdown_type+ " " +"("+ datum.lockdown_date + ")"' # lockdown_tooltip_text=f'datum.lockdown_type+ " " +"("+ datum.lockdown_date + ")"' lockdown_tooltip_text= 'datum.lockdown_type + " " + "(" + datum.lockdown_date + ")"') if 'event_index' in df.columns: ret = ret.transform_filter('datum.event_index == 0') return ret lockdown_tooltip_text = 'lockdown_tooltip_text' empty_if_checkbox = 'empty_if_checkbox' hover_layer = _make_base( alt.condition(cursor, f'{empty_if_checkbox}:N', alt.value(' '))) # Checkbox to print event details event_select = None calculate_kwargs = { empty_if_checkbox: f'datum.{lockdown_tooltip_text}' } if self.get('event_select', False): event_checkbox = alt.binding_checkbox( name='Show all intervention details ') event_select = alt.selection_single(bind=event_checkbox, name='events', init={'values': False}) calculate_kwargs[ empty_if_checkbox] = f'{self._show_events()} ? " " : datum.{lockdown_tooltip_text}' hover_layer = hover_layer.add_selection(event_select) if 'Coverage' in df.columns: # TODO: put this in a better place # I'm just putting it here so that it appears earlier than the "show all events" checkbox for now regional_checkbox = alt.binding_checkbox( name='Hide regional intervention icons ') regional_select = alt.selection_single(bind=regional_checkbox, name='hide_regional_icons', init={'values': False}) hover_layer = hover_layer.add_selection(regional_select) hover_layer = hover_layer.transform_calculate(**calculate_kwargs) layers['hover_layer'] = hover_layer if event_select is not None: layers['event_checkbox_layer'] = _make_base( f'{lockdown_tooltip_text}:N').transform_filter( self._show_events())
filter_genres = base.add_selection(genre_select).transform_filter( genre_select).properties(title="Dropdown Filtering") #color changing marks rating_radio = alt.binding_radio(options=ratings) rating_select = alt.selection_single(fields=['MPAA_Rating'], bind=rating_radio, name="Rating") rating_color_condition = alt.condition(rating_select, alt.Color('MPAA_Rating:N', legend=None), alt.value('lightgray')) highlight_ratings = base.add_selection(rating_select).encode( color=rating_color_condition).properties(title="Radio Button Highlighting") # Boolean selection for format changes input_checkbox = alt.binding_checkbox() checkbox_selection = alt.selection_single(bind=input_checkbox, name="Big Budget Films") size_checkbox_condition = alt.condition( checkbox_selection, alt.SizeValue(25), alt.Size('Hundred_Million_Production:Q')) budget_sizing = base.add_selection(checkbox_selection).encode( size=size_checkbox_condition).properties(title="Checkbox Formatting") (filter_year | filter_genres) & (highlight_ratings | budget_sizing).show()
r = pdk.Deck( layers=[layer], initial_view_state=view_state, mapbox_key= "pk.eyJ1IjoieXVhbnl1YTQiLCJhIjoiY2tnaDN2ODNuMHFjdTM3cXQ1cjZ4ZjZ1bSJ9.7Rc5ptwp4PBKWFHC8iwPWg", map_style="mapbox://styles/mapbox/light-v9") st.sidebar.write("## NYC map for reference") st.sidebar.write( "If you find a location on the main plots that interest you, you can use the map below to dive in for more details." ) st.sidebar.write(r) with st.spinner(text="Loading..."): selector_pick = alt.selection_interval(empty='none', encodings=['x', 'y']) selector_drop = alt.selection_interval(empty='none', encodings=['x', 'y']) binding_weekend = alt.binding_checkbox(name="weekend") weekend = alt.selection_single(name=None, fields=['weekend'], bind=binding_weekend, init={'weekend': True}) binding_weekday = alt.binding_checkbox(name="weekday") weekday = alt.selection_single(name=None, fields=['weekday'], bind=binding_weekday, init={'weekday': True}) taxi_map_dropoff_chart = alt.Chart( taxi_map_pickup_dropoff, title="Taxi Dropoffs (selectable)").mark_square(size=5).encode( alt.Y('dropoff_latitude', title='dropoff latitude',
df = df_raw for variable in df_raw['variable'].unique(): this_df = df_raw[df_raw['variable'] == variable].copy() this_df['value'] = list(np.diff(this_df['value']))+[0] this_df['operation'] = ['diff']*n_row df_raw = df_raw.append(this_df) this_df['value'] = np.cumsum(this_df['value']) this_df['operation'] = ['cumulative']*n_row df_raw = df_raw.append(this_df) line = alt.Chart(df).mark_line().encode( x='sample', y=alt.Y('value') ).properties(title='time series plots').interactive() op_selections = [alt.selection_single(bind=alt.binding_checkbox(), name=x, fields=['operation']) for x in df_raw['operation'].unique()] for op_selection in op_selections[::-1]: line = line.add_selection(op_selection).transform_filter(op_selection) dropdown_box = alt.binding_select(options=dataset_names) dropdown_selection = alt.selection_single(bind=dropdown_box, name='dataset', fields=['variable']) line = line.add_selection(dropdown_selection).transform_filter(dropdown_selection) alt.vconcat(line, data=df, title="Altair Example of time series" ).save('altair_example.html')
def compile(self, df): self.validate(df) self[self.TRANSIENT] = DotDict() try: self._populate_transient_props(df) base = alt.Chart(df, width=self._width, height=self._height) layers = {} extra_click_selection_kwargs = {} if not self._manual_legend: dropdown_options = [self.EMPTY_SELECTION] dropdown_name = " " if self.get('click_selection', False): dropdown_options.extend(list(df[self._detailby].unique())) dropdown_name = f'Select {self.get("readable_group_name", self.get("detailby", "group"))}: ' dropdown = alt.binding_select(options=dropdown_options, name=dropdown_name) extra_click_selection_kwargs['bind'] = dropdown click_init = self.get('click_selection_init', None) if click_init is not None: click_init = {self._detailby: click_init} if self._manual_legend: click_init = [click_init] extra_click_selection_kwargs['init'] = click_init if self._manual_legend: selection_type = getattr(alt, 'selection_multi') else: selection_type = getattr(alt, 'selection_single') click_selection = selection_type(fields=[self._detailby], on='click', name=self.click, empty='all', clear='dblclick', **extra_click_selection_kwargs) # put a fake layer in first with no click selection # since it has X and Y, it will help chart.interactive() to find x and y fields to bind to, # allowing us to pan up and down and zoom over both axes instead of just 1. layers['fake_interactive'] = base.mark_line().encode( x=self._get_x(), y=self._get_y()).transform_filter('false') # The first layer with a specified color channel is used to generate the legend. # as such, we need to make sure the marks in the first layer w/ specified color channel are not translucent, # otherwise we'll get a blank legend. # We put a fake layer in here before we add any other layers w/ color channel specified, and we # furthermore add the legend selection to it b/c it also seems like a multi-selection bound to the # legend needs to be added to the layer that generates the legend. if not self._manual_legend: legend_selection = alt.selection_multi( fields=[self._colorby], on='click', name=self.legend, empty='all', bind='legend', clear='dblclick', ) layers['legend'] = base.mark_point(size=0).encode( x=self._get_x(), y=self._get_y(), color=self._alt_color).add_selection(legend_selection) extra_mouseover_kwargs = {} if self._manual_legend: # don't set clear for selection_single click -- # it will disappear when mouse is over points extra_mouseover_kwargs['clear'] = 'mouseout' cursor = alt.selection_single(name=self.cursor, nearest=True, on='mouseover', fields=['x'], empty='none', **extra_mouseover_kwargs) # Next goes the mouseover interaction layer (needs to happen before click selection layer, # but only if click selection is "single" as opposed to "multi"). # We are binding the hover interaction to the 'x' column in the dataframe, so any other layers # that make use of the hover interaction need to use this column for their x encoding in Altair. # This means that things like lockdown tooltips need to use 'x' and then apply a filter to filter # out non-lockdown days if they want work with the mouseover interaction. if not self._manual_legend: layers['selectors'] = base.mark_point(size=0).encode( x=self._get_x()).add_selection(cursor) # Put a fake layer in first to attach the click selection to. We use a fake layer for a few reasons. # 1. It's not used as a base layer, so we won't get errors # about the spec having the selection added multiple times. # 2. We need a layer that has nice fat points that are easy to click for adding the click_selection to. # Since the layer has fat points, however, the points need to be translucent, and since they # need to be translucent, this layer cannot be the first layer that specifies color channel # and similarly cannot be the layer with the legend_selection added on (in the case of using # the built-in legend from Altair, which is only true if `use_manual_legend` is False). layers['fake_points'] = self._make_point_layer( base, point_size=400, is_fake=True).add_selection(click_selection) # Mouseover interaction goes after click interaction layer for manual legend, since manual legend # uses `selection_multi` for the click layer which does not stick if going later (and does not appear # at all if it goes first). if self._manual_legend: layers['selectors'] = self._make_point_layer( base, point_size=0, is_fake=True).add_selection(cursor) # now the meaty layers with actual content layers['lines'] = self._make_line_layer(base) layers['points'] = self._make_point_layer( base, point_size=self.get('point_size', self.DEFAULT_POINT_SIZE), is_fake=False) self._collect_tooltip_layers(df, layers, base, cursor) if self.get('lockdown_extrapolation', True): trend_checkbox = alt.binding_checkbox( name='Show trend lines for selected ') trend_select = alt.selection_single(bind=trend_checkbox, name='trends', init={'values': False}) layers[ 'model_lines'] = self._make_lockdown_extrapolation_layer( base) layers[ 'model_tooltip'] = self._make_extrapolation_tooltip_layer( layers['model_lines'], cursor, trend_select) if self.get('emoji_legend', False): self._collect_emoji_legend_layers(df, layers) layered = alt.layer(*layers.values()) layered = self._maybe_add_facet(layered) if self.get('interactive', False): layered = layered.interactive(bind_x=True, bind_y=True) if self.get('title', False): layered.title = self.get('title') final_chart = layered if self._manual_legend: final_chart = alt.hconcat(final_chart, self._make_manual_legend( df, click_selection), spacing=0) final_chart = final_chart.configure(background=self.get( 'background', self.DEFAULT_BACKGROUND_COLOR)) final_chart = final_chart.configure_axis(titleFontSize=self.get( 'axes_title_fontsize', self.DEFAULT_AXES_TITLE_FONTSIZE), ) final_chart = final_chart.configure_title(font=self._font) if not self._manual_legend: final_chart = final_chart.configure_legend( symbolType='diamond') alt.themes.register('customFont', _fontSettings(self._font)) alt.themes.enable('customFont') return final_chart finally: del self[self.TRANSIENT]
def compile(self, df): self.validate(df) self[self.TRANSIENT] = DotDict() try: self._populate_transient_props(df) base = alt.Chart(df, width=self.get('width', self.DEFAULT_WIDTH), height=self.get('height', self.DEFAULT_HEIGHT)) layers = {} dropdown_options = [self.EMPTY_SELECTION] dropdown_name = " " if self.get('click_selection', False): dropdown_options.extend(list(df[self._detailby].unique())) dropdown_name = f'Select {self.get("readable_group_name", self.detailby)}: ' dropdown = alt.binding_select(options=dropdown_options, name=dropdown_name) extra_click_selection_kwargs = {} click_init = self.get('click_selection_init', None) if click_init is not None: extra_click_selection_kwargs['init'] = { self._detailby: click_init } click_selection = alt.selection_single( fields=[self._detailby], on='click', name=self.click, empty='all', bind=dropdown, clear='dblclick', **extra_click_selection_kwargs) legend_selection = alt.selection_multi( fields=[self._colorby], on='click', name=self.legend, empty='all', bind='legend', clear='dblclick', ) # put a fake layer in first with no click selection # since it has X and Y, it will help chart.interactive() to find x and y fields to bind to, # allowing us to pan up and down and zoom over both axes instead of just 1. layers['fake_interactive'] = base.mark_line().encode( x=self._get_x(), y=self._get_y()).transform_filter('false') # next goes the tooltip selector layer (needs to happen before click selection layer) cursor, selectors = self._make_cursor_selection(base) layers['selectors'] = selectors # The first layer with a specified color channel is used to generate the legend. # as such, we need to make sure the marks in the first layer w/ specified color channel are not translucent, # otherwise we'll get a blank legend. # We put a fake layer in here before we add any other layers w/ color channel specified, and we # furthermore add the legend selection to it b/c it also seems like a multi-selection bound to the # legend needs to be added to the layer that generates the legend. layers['legend'] = base.mark_point(size=0).encode( x=self._get_x(), y=self._get_y(), color=self._alt_color).add_selection(legend_selection) # Put a fake layer in first to attach the click selection to. We use a fake layer for this for a few reasons. # 1. It's not used as a base layer, so we won't get errors # about the spec having the selection added multiple times. # 2. We need a layer that has nice fat points that are easy to click for adding the click_selection to. # Since the layer has fat points, however, the points need to be translucent, and since they # need to be translucent, this layer cannot be the first layer that specifies color channel # and similarly cannot be the layer with the legend_selection added on. layers['fake_points'] = self._make_point_layer( base, point_size=400, is_fake=True).add_selection(click_selection) # now the meaty layers with actual content layers['lines'] = self._make_line_layer(base) layers['points'] = self._make_point_layer( base, point_size=self.get('point_size', self.DEFAULT_POINT_SIZE), is_fake=False) self._collect_tooltip_layers(layers, base, cursor) if self.get('lockdown_extrapolation', False): trend_checkbox = alt.binding_checkbox( name='Show trend lines for selected ') trend_select = alt.selection_single(bind=trend_checkbox, name='trends', init={'values': True}) layers[ 'model_lines'] = self._make_lockdown_extrapolation_layer( base, trend_select) layers[ 'model_tooltip'] = self._make_extrapolation_tooltip_layer( layers['model_lines'], cursor, trend_select) layered = alt.layer(*layers.values()) layered = self._maybe_add_facet(layered) if self.get('interactive', False): layered = layered.interactive(bind_x=True, bind_y=True) if self.get('title', False): layered.title = self.get('title') layered = layered.configure(background=self.get( 'background', self.DEFAULT_BACKGROUND_COLOR)) layered = layered.configure_axis(titleFontSize=self.get( 'axes_title_fontsize', self.DEFAULT_AXES_TITLE_FONTSIZE)) layered = layered.configure_legend(symbolType='diamond') alt.themes.register('customFont', _fontSettings(self._font)) alt.themes.enable('customFont') return layered finally: del self[self.TRANSIENT]
def rooflines(neural_network: str) -> alt.vegalite.v4.api.Chart: """ This function creates an Altair line chart with checkboxes. Creates a lot of them and then sums them up. Note: Checkbox with default does not work after first click. Please keep track of when this issue is solved with this link: https://github.com/vega/vega-lite/issues/4870 Parameters ---------- data: pd.DataFrame Dataframe from which the plot will be created. neural_network:str neural network that will also be plotted besides all hardware platforms. Eg.:'imagenet|mnist|cifar' 'imagenet' Returns ------- Line Chart with checkboxes, all charts are summed up. """ maxX = 160000 width = 700 height = 500 nn_df, hw_df = clean_csv_rooflines( path_topologies='data/cnn_topologies_compute_memory_requirements.csv', path_hardware='data/peakPerfBandHardPlatf.csv') #select data to be plotted according to user input if neural_network in 'imagenet': nn_df = nn_df[nn_df['Name'].str.contains( "GoogLeNetv1|MobileNetv1|ResNet|EfficientNet")] elif neural_network in 'cifar': nn_df = nn_df[nn_df['Name'].str.contains("CNV")] elif neural_network in 'mnist': nn_df = nn_df[nn_df['Name'].str.contains("MLP")] elif neural_network != 'imagenet|mnist|cifar': return 'There were no results for the neural network asked. Please insert another network' #regex expression replace for all MLPs because they overlapp in the plot because they have the same value for MLP100%,MLP50%.. nn_df = util.replace_data_df(nn_df, 'Name', [('MLP 100%', 'MLP*'), ('MLP 50%', 'MLP*'), ('MLP 25%', 'MLP*'), ('MLP 12.5%', 'MLP*')]) nn_df = nn_df.drop_duplicates() #---------------Next part is to create all plots binded to checkboes------------- #Selecting data for each checkbox, from dataset. Each checkbox will be tied to each one of these data FPGA_data = hw_df[hw_df['Name'].str.contains("Ultra96 DPU|ZCU")] NVIDIA_data = hw_df[hw_df['Name'].str.contains("TX2")] GOOGLE_data = hw_df[hw_df['Name'].str.contains("EdgeTPU")] INTEL_data = hw_df[hw_df['Name'].str.contains("NCS")] INT2_data = nn_df[nn_df['Name'].str.contains("INT2")] INT4_data = nn_df[nn_df['Name'].str.contains("INT4")] INT8_data = nn_df[nn_df['Name'].str.contains("INT8")] FP16_data = nn_df[nn_df['Name'].str.contains("FP16")] FP32_data = nn_df[nn_df['Name'].str.contains("FP32")] #Stating that the binding type will be a checkbox filter_checkbox = alt.binding_checkbox() #To create all checkboxes with the specifications info for each set FPGA_select = alt.selection_single(fields=["Hide"], bind=filter_checkbox, name="FPGAs Ultra96 DPU ZCU ") NVIDIA_select = alt.selection_single( fields=["Hide"], bind=filter_checkbox, name="INVIDIA TX2 maxn, maxp, maxq ") GOOGLE_select = alt.selection_single(fields=["Hide"], bind=filter_checkbox, name="GOOGLE EdgeTPU, fast, slow ") INTEL_select = alt.selection_single(fields=["Hide"], bind=filter_checkbox, name="INTEL NCS ") INT2_select = alt.selection_single(fields=["Hide"], bind=filter_checkbox, name="INT2") INT4_select = alt.selection_single(fields=["Hide"], bind=filter_checkbox, name="INT4") INT8_select = alt.selection_single(fields=["Hide"], bind=filter_checkbox, name="INT8") FP16_select = alt.selection_single(fields=["Hide"], bind=filter_checkbox, name="FP16") FP32_select = alt.selection_single(fields=["Hide"], bind=filter_checkbox, name="FP32") #Color Conditions for each plot FPGA_cond = alt.condition(FPGA_select, alt.Color("Name:N"), alt.value("lightgray")) NVIDIA_cond = alt.condition(NVIDIA_select, alt.Color("Name:N"), alt.value("lightgray")) GOOGLE_cond = alt.condition(GOOGLE_select, alt.Color("Name:N"), alt.value("lightgray")) INTEL_cond = alt.condition(INTEL_select, alt.Color("Name:N"), alt.value("lightgray")) INT2_cond = alt.condition(INT2_select, alt.Color("Name:N"), alt.value("lightgray")) INT4_cond = alt.condition(INT4_select, alt.Color("Name:N"), alt.value("lightgray")) INT8_cond = alt.condition(INT8_select, alt.Color("Name:N"), alt.value("lightgray")) FP16_cond = alt.condition(FP16_select, alt.Color("Name:N"), alt.value("lightgray")) FP32_cond = alt.condition(FP32_select, alt.Color("Name:N"), alt.value("lightgray")) #Creating all plots FPGA_chart = line_chart_w_checkbox(FPGA_data, FPGA_cond, FPGA_select) NVIDIA_chart = line_chart_w_checkbox(NVIDIA_data, NVIDIA_cond, NVIDIA_select) GOOGLE_chart = line_chart_w_checkbox(GOOGLE_data, GOOGLE_cond, GOOGLE_select) INTEL_chart = line_chart_w_checkbox(INTEL_data, INTEL_cond, INTEL_select) INT2_chart = line_chart_w_checkbox(INT2_data, INT2_cond, INT2_select) INT4_chart = line_chart_w_checkbox(INT4_data, INT4_cond, INT4_select) INT8_chart = line_chart_w_checkbox(INT8_data, INT8_cond, INT8_select) FP16_chart = line_chart_w_checkbox(FP16_data, FP16_cond, FP16_select) FP32_chart = line_chart_w_checkbox(FP32_data, FP32_cond, FP32_select) #-------------------------------------------------------------------------------------------------- # Create line plot line_chart = alt.Chart().mark_line(clip=True).interactive().encode( alt.X('arith_intens:Q'), alt.Y('performance:Q'), alt.Color('Name:N', legend=alt.Legend(columns=2))) #Create the selection which chooses nearest point on mouse hoover selection = alt.selection(type='single', nearest=True, on='mouseover', fields=['arith_intens']) #to leave suggestions on, just replace arith_intens wiith anything else #Create text plot to show the text values on mouse hoovering text = (line_chart).mark_text(align='left', dx=3, dy=-3, clip=True).encode( text=alt.condition(selection, 'Name:N', alt.value(' '))) #Creates the points plot for the NNs. The points will be invisible selectors = alt.Chart().add_selection(selection).mark_point( clip=True).encode( alt.X('arith_intens:Q'), alt.Y('performance:Q'), opacity=alt.value(0), ) chart_all = (pd.Series( [INT2_chart, INT4_chart, INT8_chart, FP16_chart, FP32_chart], name="charts")).to_frame() Chart = alt.layer(chart_all.charts.sum(numeric_only=False) + FPGA_chart + NVIDIA_chart + GOOGLE_chart + INTEL_chart, selectors, text, data=pd.concat([nn_df, hw_df]), width=700, height=500) return Chart