def prep_palette(self, pname, binverse=False): """ Prepares a palette based on a name :param pname: :return: """ res = palettes.grey(256) if pname == 'Greys256': res = palettes.grey(256) elif pname == 'Inferno256': res = palettes.inferno(256) elif pname == 'Magma256': res = palettes.magma(256) elif pname == 'Plasma256': res = palettes.plasma(256) elif pname == 'Viridis256': res = palettes.viridis(256) elif pname == 'Cividis256': res = palettes.cividis(256) elif pname == 'Turbo256': res = palettes.turbo(256) elif pname == 'Bokeh8': res = palettes.small_palettes['Bokeh'][8] elif pname == 'Spectral11': res = palettes.small_palettes['Spectral'][11] elif pname == 'RdGy11': res = palettes.small_palettes['RdGy'][11] elif pname == 'PiYG11': res = palettes.small_palettes['PiYG'][11] if binverse: res = res[::-1] return res
def test_cmap_generator_function(): assert pal.viridis(256) == pal.Viridis256 assert pal.magma(256) == pal.Magma256 assert pal.plasma(256) == pal.Plasma256 assert pal.inferno(256) == pal.Inferno256 assert pal.gray(256) == pal.Greys256 assert pal.grey(256) == pal.Greys256
def create_interact_ui(doc): x, y, z = echelle(freq, power, dnu, fmin, fmax) source = ColumnDataSource(data={'image': [np.sqrt(z)]}) plot = figure(x_range=(x.min(), x.max()), y_range=(y.min(), y.max())) cmap = grey(256)[::-1] full_plot = plot.image(image='image', x=x.min(), y=y.min(), dw=x.max(), dh=y.max(), source=source, palette=cmap) plot.xaxis.axis_label = r'Frequency mod $\Delta\nu$' plot.yaxis.axis_label = 'Frequency' slider = Slider(start=dnu - 2., end=dnu + 2., value=dnu, step=.001, title=r'$\Delta\nu$') def update_upon_cadence_change(attr, old, new): _, _, z = echelle(freq, power, new, 15, 80) full_plot.data_source.data['image'] = [np.sqrt(z)] slider.on_change('value', update_upon_cadence_change) # Layout all of the plots widgets_and_figures = column(slider, plot) doc.add_root(widgets_and_figures)
def test_cmap_generator_function(): assert pal.viridis(256) == pal.Viridis256 assert pal.magma(256) == pal.Magma256 assert pal.plasma(256) == pal.Plasma256 assert pal.inferno(256) == pal.Inferno256 assert pal.gray(256) == pal.Greys256 assert pal.grey(256) == pal.Greys256 assert pal.turbo(256) == pal.Turbo256 assert pal.diverging_palette(pal.Reds9, pal.Greys9, n=18, midpoint=0.5) == pal.Reds9 + pal.Greys9[::-1]
def state_count_tab(): plotter, StHimark, gsource = displayMap() url = join(basename(split(dirname(__file__))[0]), 'data', 'sensor_count.csv') state_count = pd.read_csv(url) palette = grey(19) palette = palette[::-1] color_mapper = LinearColorMapper(palette=palette, low=state_count['count'].min(), high=state_count['count'].max()) grey_merged = StHimark.merge(state_count, left_on='Nbrhood', right_on='Neighbourhood') merged_json = json.loads(grey_merged.to_json()) json_data = json.dumps(merged_json) geosource = GeoJSONDataSource(geojson=json_data) plotter.patches('xs', 'ys', source=geosource, fill_color={ 'field': 'count', 'transform': color_mapper }, line_color="black", line_width=0.05, fill_alpha=1.0) tick_labels = { '0': '0', '10': '10', '20': '20', '30': '30', '40': '40', '50': '>50' } color_bar = ColorBar(color_mapper=color_mapper, label_standoff=5, width=500, height=20, border_line_color=None, location=(0, 0), orientation='horizontal', major_label_overrides=tick_labels) plotter.add_layout(color_bar, 'below') layout = column(plotter) tab = Panel(child=layout, title='State Uncertainity') return tab
def plot_grids(values, grids, title=None, f_w=1000, f_h=1000, silent=False): """ plot the grids on map tile background. Args: values (array): either the input data or output data as a 1-d array grids (list): the bounds of each grid """ values = values cds = ColumnDataSource(data=grids_data_source(values, grids)) cm = LinearColorMapper(palette=palettes.grey(10)) center = (-8231000.0 - 3000, 4977500.0 - 2000) view_w = 7000 view_h = 5000 p = figure(title=title, plot_width=f_w, plot_height=f_h, x_range=(center[0] - view_w, center[0] + view_w), y_range=(center[1] - view_h, center[1] + view_h), tools="pan,wheel_zoom,box_zoom,reset,save") p.add_tile(CARTODBPOSITRON_RETINA) p.axis.visible = False r = p.quad(left='left', right='right', top='top', bottom='bottom', source=cds, line_alpha=0, alpha='alpha', color={ 'field': 'color', 'transform': cm }) if silent: return p, r else: show(p)
def plot_all(fig, df, start_year, end_year): lines = list() # empty list to hold each plotted line source = ColumnDataSource(df) offset = 5 # generate palette the size of dataset but offset each end palette = palettes.grey(end_year - start_year + 1 + offset * 2) unselected_kwargs = dict(line_width=1.5, line_alpha=0.5) # plot all years for i, yr in enumerate(range(start_year, end_year + 1)): lines.append( fig.line(x='day', y=str(yr), source=source, color=palette[i + offset], name=str(yr), **unselected_kwargs)) return fig, lines
"#FDE095", "#FDE299", "#FDE39E", "#FDE5A2", "#FDE6A6", "#FDE8AA", "#FEEAAF", "#FEEBB3", "#FEEDB7", "#FEEEBC", "#FEF0C0", "#FEF1C4", "#FEF3C9", "#FEF4CD", "#FEF6D1", "#FFF8D6" ] def totimestamp(dt, epoch=datetime(1970, 1, 1)): td = dt - epoch # return td.total_seconds() return (td.microseconds + (td.seconds + td.days * 86400) * 10**6) / 10**6 dir_path = os.path.dirname(os.path.realpath(__file__)) plotWidth = 1000 plotHeight = 600 colors = grey(100) colors = gradient mapper = LinearColorMapper(palette=colors) period = timedelta(hours=1) TOOLS = "hover,save,reset" df = pd.read_csv(dir_path + '/Tables/LIGHT_LEVELS.csv', index_col=0, parse_dates=True, dayfirst=True) cn = pd.read_csv(dir_path + '/Tables/channel_names.csv', index_col=0) an = pd.read_csv(dir_path + '/Tables/area_names.csv', index_col=0) columnNames = [] for x, y in zip(cn['Area'], cn['Name']): columnNames.append(an.loc[x, 'Name'] + " - " + y) df.columns = columnNames
def create_plot(df, title, power_unit, ylimit=None): """ :param df: :param title: string, plot title :param power_unit: string, the unit of power used in the database/model :param ylimit: float/int, upper limit of y-axis; optional :return: """ # Set up data source source = ColumnDataSource(data=df) # Determine column types for plotting, legend and colors x_col = "hour_on_period" power_col = "Power" commitment_col = "Committed Capacity" stable_level_col = "Minimum Output" all_reserves = [ "bottom_reserves", "Regulation Down", "Load Following Down", "Load Following Up", "Regulation Up", "Frequency Response", "Spinning Reserves", ] active_reserves = list( df[all_reserves].columns[df[all_reserves].notna().all() & df[all_reserves].mean() > 0]) # Setup the reserve colors colors = grey(len(active_reserves) + 2)[1:-1] # skip the white/black colors alphas = [0] + [1] * (len(active_reserves) - 1) if active_reserves else [] # Set up the figure plot = figure( plot_width=800, plot_height=500, tools=["pan", "reset", "zoom_in", "zoom_out", "save", "help"], title=title, ) # Add reserve area renderers area_renderers = plot.vbar_stack( stackers=active_reserves, x=x_col, source=source, fill_color=colors, fill_alpha=alphas, line_color=colors, line_alpha=alphas, width=1, ) # Add operations to plot power_renderer = plot.step( name="Power", source=source, x=x_col, y=power_col, color="black", mode="center", ) commitment_renderer = plot.step( name="Committed Capacity", source=source, x=x_col, y=commitment_col, color="black", line_dash="dashed", mode="center", ) stable_level_renderer = plot.step( name="Minimum Output", source=source, x=x_col, y=stable_level_col, color="black", line_dash="dotted", mode="center", ) # Add legend items legend_items = [ (commitment_renderer.name, [commitment_renderer]), (power_renderer.name, [power_renderer]), (stable_level_renderer.name, [stable_level_renderer]), ] + list(reversed([(r.name, [r]) for r in area_renderers[1:]])) # Add Legend legend = Legend(items=legend_items) plot.add_layout(legend, "right") plot.legend.click_policy = "hide" # Add interactivity to the legend # Note: Doesn't rescale the graph down, simply hides the area # Note2: There's currently no way to auto-size legend based on graph size(?) # except for maybe changing font size automatically? show_hide_legend(plot=plot) # Hide legend on double click # Format Axes (labels, number formatting, range, etc.) plot.xaxis.axis_label = "Hour" plot.yaxis.axis_label = power_unit plot.yaxis.formatter = NumeralTickFormatter(format="0,0") plot.y_range.end = ylimit # will be ignored if ylimit is None # Add HoverTools # Note: stepped lines or varea charts not yet supported (lines/bars OK) # Note: skip bottom renderer for vbars/areas since it's just a helper hover_renderers = area_renderers[1:] + [ commitment_renderer, power_renderer, stable_level_renderer, ] for r in hover_renderers: tooltips = [("Hour", "@%s" % x_col), (r.name, "@$name{0,0} %s" % power_unit)] if r.name == "Power": tooltips.append(("% of Committed", "@power_pct_of_committed{0%}")) elif r.name == "Minimum Output": tooltips.append( ("% of Committed", "@min_stable_level_pct_of_committed{0%}")) hover = HoverTool(tooltips=tooltips, renderers=[r], toggleable=False) plot.add_tools(hover) return plot
from bokeh.plotting import figure from bokeh.transform import factor_cmap, dodge from bokeh import palettes from bokeh import __version__ as bokeh_version import pandas as pd import numpy as np from solarforecastarbiter import datamodel from solarforecastarbiter.plotting.utils import line_or_step logger = logging.getLogger(__name__) PALETTE = (palettes.d3['Category20'][20][::2] + palettes.d3['Category20'][20][1::2]) _num_obs_colors = 3 # drop white OBS_PALETTE = list(palettes.grey(_num_obs_colors + 1)[0:_num_obs_colors]) OBS_PALETTE.reverse() OBS_PALETTE_TD_RANGE = pd.timedelta_range(freq='10min', end='60min', periods=_num_obs_colors) def construct_timeseries_cds(report): """Construct two standardized Bokeh CDS for the timeseries and scatter plot functions. One with timeseries data for all observations, aggregates, and forecasts in the report, and the other with associated metadata sharing a common `pair_index` key. Parameters ---------- report: :py:class:`solarforecastarbiter.datamodel.Report`
def plot_2d(data, summary_axis, time_axis): ''' Plot variance analysis along 2D Inputs data [array] Voxelwise data Can be scalar (vw_variance) or binary (regressor) summary_axis [tuple] One or more axes to summarise variance time_axis [scalar] Axis along which time is encoded Outputs handle [object] Figure handle ''' # Safety check if data.ndim - 2 != len(summary_axis): raise TypeError('Error: incorrect number of summary axes specified.') # Mean variance across summary axes y = np.mean(data, axis=summary_axis, keepdims=True) # Make time the 0th axis, squeeze and transpose # y = (slice, time) y = np.moveaxis(y, time_axis, 0) y = y.squeeze() y = y.T # Force data into float type y = y.astype(float) # Create figure handle = plotting.figure(plot_width=800, plot_height=500, title='', x_axis_label='Time (TR)', y_axis_label='Slice', tools='pan,box_zoom,reset', tooltips=[('x', '$x'), ('y', '$y'), ('value', '@image')]) # If the array is binary, set colour mapper to b/w # If it's not binary, use a continuous palette if np.array_equal(y, y.astype(bool)): # Grayscale colormap color_mapper = models.LinearColorMapper( palette=palettes.grey(2)[::-1], low=0, high=1, ) else: # Continuous colormap color_mapper = models.LinearColorMapper( palette=palettes.Viridis256, low=0, high=np.max(y), ) # Add image handle.image(image=[y], x=0, y=0, dh=y.shape[0], dw=y.shape[1], color_mapper=color_mapper, level='image') # Create colorbar colorbar = models.ColorBar( color_mapper=color_mapper, label_standoff=12, border_line_color=None, location=(0, 0), ticker=models.AdaptiveTicker(), ) # Add colorbar handle.add_layout(colorbar, 'right') # Tidy handle.x_range.range_padding = 0 handle.y_range.range_padding = 0 handle.grid.grid_line_width = 0.5 handle.title.align = 'center' handle.xaxis.axis_label_text_align = 'center' handle.yaxis.axis_label_text_align = 'center' handle.xaxis.axis_label_text_font_size = '10pt' handle.yaxis.axis_label_text_font_size = '10pt' handle.xaxis.axis_label_text_font_style = 'normal' handle.yaxis.axis_label_text_font_style = 'normal' # Return return handle
def plot_density( data, *, year, group, kernel_function, cell_size, crs=None, bandwidth, show_title, ): if crs is None: crs = {'init': 'epsg:3067'} pop = get_xy(data) pad = bandwidth * 2 minx, miny, maxx, maxy = pop['geometry'].total_bounds minx -= pad miny -= pad maxx += pad maxy += pad w, h = maxx - minx, maxy - miny fig = figure( title=f"Density of {group.capitalize()} population in Vyborg in {year}", x_range=(minx, maxx), y_range=(miny, maxy), ) fig.title.visible = show_title fig.xaxis.major_tick_line_color = None fig.xaxis.minor_tick_line_color = None fig.yaxis.major_tick_line_color = None fig.yaxis.minor_tick_line_color = None fig.xaxis.major_label_text_font_size = '0pt' fig.yaxis.major_label_text_font_size = '0pt' fig.xgrid.visible = False fig.ygrid.visible = False water = gpd.read_file('water_clip.shp') water.crs = {'init': 'epsg:4326'} water.geometry = water.geometry.to_crs(crs) water = get_xy(water) water_src = GeoJSONDataSource(geojson=water.to_json()) density = kernel_density_surface( data, group=group, bandwidth=bandwidth, cell_size=cell_size, kernel_function=kernel_function, ) fig.image( [density], minx, miny, w, h, palette=grey(10)[::-1], ) fig.patches( xs='x', ys='y', source=water_src, fill_color='#59d0ff', fill_alpha=0.8, line_color=None, line_width=0, ) return fig
class ColorController(object): """Controls the color of the elements based on the selected method and the active palette. When coloring by classification only one type of palette will be available. The rest of palettes are available when an axis is selected """ LOGGER = logging.getLogger(__name__) POINT_SELECTED_COLOR = 'red' POINT_UNSELECTED_COLOR = '#d3d3d3' INFERNO_PALETTE_ID = 'inferno' GREY_PALETTE_ID = 'grey' VIRIDIS_PALETTE_ID = 'viridis' CLUSTER_CATEGORY_PALETTE_ID = 'cluster' DEFAULT_PALETTE_ID = INFERNO_PALETTE_ID GREY_PALETTE = list(reversed(grey(256))) INFERNO_PALETTE = inferno(256) VIRIDIS_PALETTE = viridis(256) # 23 RGB colors from Red to Pink for Clustering categorization # Keep this list as reference for testing purposes # CATEGORY_PALETTE = ['#ff0000', '#ff4000', '#ff8000', '#ffbf00', # '#ffff00', '#bfff00', '#80ff00', '#40ff00', # '#00ff00', '#00ff40', '#00ff80', '#00ffbf', # '#00ffff', '#00bfff', '#0080ff', '#0040ff', # '#0000ff', '#4000ff', '#8000ff', '#bf00ff', # '#ff00ff', '#ff00bf', '#ff0080'] CATEGORY_PALETTE = [ "red", "black", "orange", "green", "grey", "yellow", "navy" ] NONE_PALETTE = ["navy"] NONE_PALETTE_ID = 'None' CATEGORY_METHOD_ID = 'Category' AXIS_METHOD_ID = 'Axis' NONE_METHOD_ID = 'None' NONE_AXIS_ID = 'None' DEFAULT_METHOD_ID = NONE_METHOD_ID @staticmethod def _get_axis_palette_dict(): """Returns a dictionary of palettes {palette_id, palette}""" return dict({ ColorController.INFERNO_PALETTE_ID: ColorController.INFERNO_PALETTE, ColorController.GREY_PALETTE_ID: ColorController.GREY_PALETTE, ColorController.VIRIDIS_PALETTE_ID: ColorController.VIRIDIS_PALETTE, ColorController.NONE_PALETTE_ID: ColorController.NONE_PALETTE }) def __init__(self, input_data_controller, normalization_controller, classification_controller, point_controller, palette_id=NONE_PALETTE_ID): self._palette_dict = ColorController._get_axis_palette_dict() self._input_data_controller = input_data_controller self._normalization_controller = normalization_controller self._classification_controller = classification_controller self._point_controller = point_controller self._active_palette_id = ColorController.NONE_PALETTE_ID self._selected_axis_id = ColorController.NONE_AXIS_ID self.update_palette(palette_id) self._active_method = ColorController.DEFAULT_METHOD_ID # Prevents any coloring when a user has selected a valid point # Note that the name must be unique self._selected_point_name = None def update_palette(self, palette_id): if palette_id not in self._palette_dict: ColorController.LOGGER.warn("Palette id '%s' is not known", palette_id) else: self._active_palette_id = palette_id def update_colors(self): """Update points' color accoring to selected method and axis or categories""" if self._selected_point_name: ColorController.LOGGER.warn( "Cannot update colors while a point is selected") return if self.in_category_mode(): self._color_points_by_categories() elif self.in_axis_mode(): self._color_points_by_axis() else: self._color_points_by_initial_settings() def update_method(self, method_id): self._active_method = method_id self.update_legend() def update_selected_axis(self, axis_id): ColorController.LOGGER.debug("Updating axis ID to '%s'", axis_id) if axis_id not in self.get_available_axis_ids(): raise ValueError("'{}' is not a valid axis".format(axis_id)) self._selected_axis_id = axis_id def update_legend(self): ColorController.LOGGER.debug("Updating categories") categories = [] if self.in_category_mode(): categories = self._classification_controller.get_categories() expected_no_categories = self._point_controller.get_number_of_points() if categories is None \ or len(categories) == 0 \ or len(categories) != expected_no_categories: categories = ['N/A' for i in range(0, expected_no_categories)] self._point_controller.update_categories(categories) def get_available_axis_ids(self): return [ColorController.NONE_AXIS_ID]\ + self._input_data_controller.get_dimensional_labels() def get_selected_axis_id(self): return self._selected_axis_id def get_active_palette(self): return self._active_palette_id def get_active_color_method(self): return self._active_method def get_available_palettes(self): return self._palette_dict.keys() def get_available_color_methods(self): return [ ColorController.AXIS_METHOD_ID, ColorController.CATEGORY_METHOD_ID, ColorController.NONE_METHOD_ID ] def select_point(self, point_name): self._selected_point_name = point_name self._update_colors_by_point(point_name) def unselect_point(self): self._selected_point_name = None self.update_colors() def get_selected_point(self): return self._selected_point_name def _update_colors_by_point(self, point_name): new_colors = [ColorController.POINT_UNSELECTED_COLOR\ if name != point_name\ else ColorController.POINT_SELECTED_COLOR\ for name in self._point_controller.get_point_names()] self._point_controller.update_colors(new_colors) def in_axis_mode(self): return self._active_method == ColorController.AXIS_METHOD_ID def in_category_mode(self): return self._active_method == ColorController.CATEGORY_METHOD_ID def _color_points_by_initial_settings(self): """Will set the color of all points based on the initial palette""" ColorController.LOGGER.debug("Coloring by initial settings") palette_index_list = np.zeros( self._input_data_controller.get_number_of_values()) self._map_source_points_color(palette_index_list, ColorController.NONE_PALETTE) def _color_points_by_axis(self): # get index of colors, we normalize by Feature Scaling to get all values between 0 and 1 # and then multiply by the length of the palette ColorController.LOGGER.debug("Coloring by axis '%s'", self._selected_axis_id) if self._selected_axis_id == ColorController.NONE_AXIS_ID: ColorController.LOGGER.warn( "No coloring was made since selected axis was None") return active_palette = self._get_palette() values_df = self._input_data_controller.get_dimensional_values( filtered=False) column_norm = self._normalization_controller\ .normalize_feature_scaling(values_df)[self._selected_axis_id] palette_index_list = (column_norm * len(active_palette) - 1).astype(int) # map index with color in the palette and assign to points self._map_source_points_color(palette_index_list, active_palette) def _color_points_by_categories(self): ColorController.LOGGER.debug("Coloring by category") categories = self._classification_controller.get_categories() if categories is None or len(categories) == 0: ColorController.LOGGER.warn( "No coloring was made since no categories were found") return palette = ColorController.CATEGORY_PALETTE # Map each category into a specific index palette_index_list = self._get_palette_index_list(categories, palette) self._map_source_points_color(palette_index_list, ColorController.CATEGORY_PALETTE) def _map_source_points_color(self, palette_index_list, palette): max_index_list = max(palette_index_list) max_index_palette = len(palette) - 1 if max_index_list > max_index_palette: ColorController.LOGGER.warn( ("Max index (%s) in palette index list is" "higher than the palette one (%s), " "higher indexes will be assigned the " "highest palette value"), max_index_list, max_index_palette) new_colors = [ palette[min(max_index_palette, index)] for index in palette_index_list ] self._point_controller.update_colors(new_colors) def _get_palette(self): return self._palette_dict[self._active_palette_id] def _get_palette_index_list(self, categories, palette): """Receives a list of category elements, of any type, and returns a list of numeric values which are the indexes of the palette """ palette_index_list = [] category_dict = dict() shift = 0 for category in categories: if not category in category_dict: category_dict[category] = shift shift += 1 palette_index_list.append(category_dict[category]) # Once we have the categories indexed, we normalize and multiply # by the length of the palette in order to distribute the values # return palette_index_list # _ is what you use when you run out of ideas for names _ = self._normalization_controller\ .normalize_feature_scaling(DataFrame(palette_index_list)) return (_ * (len(palette) - 1)).astype(int)[0]