def draw(self, renderer, *args, **kwargs): if not self.get_visible(): return if self.dx == 0: return # Get parameters from matplotlib import rcParams # late import def _get_value(attr, default): value = getattr(self, attr) if value is None: value = rcParams.get('scalebar.' + attr, default) return value length_fraction = _get_value('length_fraction', 0.2) height_fraction = _get_value('height_fraction', 0.01) location = _get_value('location', 'upper right') if is_string_like(location): location = self._LOCATIONS[location] pad = _get_value('pad', 0.2) border_pad = _get_value('border_pad', 0.1) sep = _get_value('sep', 5) frameon = _get_value('frameon', True) color = _get_value('color', 'k') box_color = _get_value('box_color', 'w') box_alpha = _get_value('box_alpha', 1.0) scale_loc = _get_value('scale_loc', 'bottom') label_loc = _get_value('label_loc', 'top') font_properties = self.font_properties if font_properties is None: textprops = {'color': color} else: textprops = {'color': color, 'fontproperties': font_properties} ax = self.axes xlim, ylim = ax.get_xlim(), ax.get_ylim() label = self.label # Create label if label: txtlabel = TextArea(label, minimumdescent=False, textprops=textprops) else: txtlabel = None # Create sizebar length_px = abs(xlim[1] - xlim[0]) * length_fraction length_px, scale_label = self._calculate_length(length_px) size_vertical = abs(ylim[1] - ylim[0]) * height_fraction sizebar = AuxTransformBox(ax.transData) sizebar.add_artist( Rectangle((0, 0), length_px, size_vertical, fill=True, facecolor=color, edgecolor=color)) txtscale = TextArea(scale_label, minimumdescent=False, textprops=textprops) if scale_loc in ['bottom', 'right']: children = [sizebar, txtscale] else: children = [txtscale, sizebar] if scale_loc in ['bottom', 'top']: Packer = VPacker else: Packer = HPacker boxsizebar = Packer(children=children, align='center', pad=0, sep=sep) # Create final offset box if txtlabel: if label_loc in ['bottom', 'right']: children = [boxsizebar, txtlabel] else: children = [txtlabel, boxsizebar] if label_loc in ['bottom', 'top']: Packer = VPacker else: Packer = HPacker child = Packer(children=children, align='center', pad=0, sep=sep) else: child = boxsizebar box = AnchoredOffsetbox(loc=location, pad=pad, borderpad=border_pad, child=child, frameon=frameon) box.axes = ax box.set_figure(self.get_figure()) box.patch.set_color(box_color) box.patch.set_alpha(box_alpha) box.draw(renderer)
def draw(self, renderer, *args, **kwargs): if not self.get_visible(): return if not self.get_mappable(): return # Get parameters from matplotlib import rcParams # late import def _get_value(attr, default): value = getattr(self, attr) if value is None: value = rcParams.get('colorbar.' + attr, default) return value orientation = _get_value('orientation', 'vertical') length_fraction = _get_value('length_fraction', 0.2) width_fraction = _get_value('width_fraction', 0.01) location = _get_value('location', 'upper right') if isinstance(location, six.string_types): location = self._LOCATIONS[location] pad = _get_value('pad', 0.2) border_pad = _get_value('border_pad', 0.1) sep = _get_value('sep', 5) frameon = _get_value('frameon', True) color = _get_value('color', 'k') box_color = _get_value('box_color', 'w') box_alpha = _get_value('box_alpha', 1.0) font_properties = self.font_properties ticklocation = _get_value('ticklocation', 'auto') if ticklocation == 'auto': ticklocation = 'bottom' if orientation == 'horizontal' else 'right' mappable = self.mappable cmap = self.mappable.get_cmap() norm = self.mappable.norm label = self.label ticks = self.ticks ticklabels = self.ticklabels ax = self.axes # Calculate calculator = ColorbarCalculator(mappable, ticks=ticks, ticklabels=ticklabels) X, Y, C = calculator.calculate_colorbar() X *= width_fraction Y *= length_fraction widths = np.diff(X, axis=1)[:, 0] heights = np.diff(Y[:, 0]) if orientation == 'horizontal': X, Y = Y, X widths, heights = heights, widths ticks, ticklabels, offset_string = calculator.calculate_ticks() ticks *= length_fraction # Create colorbar colorbarbox = AuxTransformBox(ax.transAxes) patches = [] for x0, y0, width, height in zip(X[:-1, 0], Y[:-1, 0], widths, heights): patch = Rectangle((x0, y0), width, height) patches.append(patch) edgecolors = 'none' #if self.drawedges else 'none' #FIXME: drawedge property #FIXME: Filled property col = PatchCollection(patches, cmap=cmap, edgecolors=edgecolors, norm=norm) col.set_array(C[:, 0]) colorbarbox.add_artist(col) # Create outline if orientation == 'horizontal': outline = Rectangle((0, 0), length_fraction, width_fraction, fill=False, ec=color) else: outline = Rectangle((0, 0), width_fraction, length_fraction, fill=False, ec=color) colorbarbox.add_artist(outline) # Create ticks and tick labels w10th = width_fraction / 10.0 ticklines = [] ticktexts = [] for tick, ticklabel in zip(ticks, ticklabels): if ticklocation == 'bottom': x0 = x1 = xtext = tick y0 = w10th y1 = -w10th ytext = -2 * w10th ha = 'center' va = 'top' elif ticklocation == 'top': x0 = x1 = xtext = tick y0 = width_fraction - w10th y1 = width_fraction + w10th ytext = width_fraction + 2 * w10th ha = 'center' va = 'bottom' elif ticklocation == 'left': x0 = w10th x1 = -w10th xtext = -2 * w10th y0 = y1 = ytext = tick ha = 'right' va = 'center' elif ticklocation == 'right': x0 = width_fraction - w10th x1 = width_fraction + w10th xtext = width_fraction + 2 * w10th y0 = y1 = ytext = tick ha = 'left' va = 'center' ticklines.append([(x0, y0), (x1, y1)]) ticklabel = offset_string + ticklabel ticktext = Text(xtext, ytext, ticklabel, color=color, fontproperties=font_properties, horizontalalignment=ha, verticalalignment=va) ticktexts.append(ticktext) col = LineCollection(ticklines, color=color) colorbarbox.add_artist(col) for ticktext in ticktexts: colorbarbox.add_artist(ticktext) # Create label if label: labelbox = AuxTransformBox(ax.transAxes) va = 'baseline' if orientation == 'horizontal' else 'center' text = Text(0, 0, label, fontproperties=font_properties, verticalalignment=va, rotation=orientation, color=color) labelbox.add_artist(text) else: labelbox = None # Create final offset box if ticklocation == 'bottom': children = [colorbarbox, labelbox] if labelbox else [colorbarbox] child = VPacker(children=children, align='center', pad=0, sep=sep) elif ticklocation == 'top': children = [labelbox, colorbarbox] if labelbox else [colorbarbox] child = VPacker(children=children, align='center', pad=0, sep=sep) elif ticklocation == 'left': children = [labelbox, colorbarbox] if labelbox else [colorbarbox] child = HPacker(children=children, align='center', pad=0, sep=sep) elif ticklocation == 'right': children = [colorbarbox, labelbox] if labelbox else [colorbarbox] child = HPacker(children=children, align='center', pad=0, sep=sep) # box = AnchoredOffsetbox(loc=location, pad=pad, borderpad=border_pad, child=child, frameon=frameon) box.axes = ax box.set_figure(self.get_figure()) box.patch.set_color(box_color) box.patch.set_alpha(box_alpha) box.draw(renderer)
def draw(self, renderer, *args, **kwargs): if not self.get_visible(): return if not self.get_mappable(): return # Get parameters from matplotlib import rcParams # late import def _get_value(attr, default): value = getattr(self, attr) if value is None: value = rcParams.get('colorbar.' + attr, default) return value orientation = _get_value('orientation', 'vertical') length_fraction = _get_value('length_fraction', 0.2) width_fraction = _get_value('width_fraction', 0.01) location = _get_value('location', 'upper right') if is_string_like(location): location = self._LOCATIONS[location] pad = _get_value('pad', 0.2) border_pad = _get_value('border_pad', 0.1) sep = _get_value('sep', 5) frameon = _get_value('frameon', True) color = _get_value('color', 'k') box_color = _get_value('box_color', 'w') box_alpha = _get_value('box_alpha', 1.0) font_properties = self.font_properties ticklocation = _get_value('ticklocation', 'auto') if ticklocation == 'auto': ticklocation = 'bottom' if orientation == 'horizontal' else 'right' mappable = self.mappable cmap = self.mappable.cmap label = self.label ticks = self.ticks ticklabels = self.ticklabels ax = self.axes # Calculate calculator = ColorbarCalculator(mappable, ticks=ticks, ticklabels=ticklabels) X, Y, C = calculator.calculate_colorbar() X *= width_fraction Y *= length_fraction widths = np.diff(X, axis=1)[:, 0] heights = np.diff(Y[:, 0]) if orientation == 'horizontal': X, Y = Y, X widths, heights = heights, widths ticks, ticklabels, offset_string = calculator.calculate_ticks() ticks *= length_fraction # Create colorbar colorbarbox = AuxTransformBox(ax.transAxes) patches = [] for x0, y0, width, height in zip(X[:-1, 0], Y[:-1, 0], widths, heights): patch = Rectangle((x0, y0), width, height) patches.append(patch) edgecolors = 'none' #if self.drawedges else 'none' #FIXME: drawedge property #FIXME: Filled property col = PatchCollection(patches, cmap=cmap, edgecolors=edgecolors) col.set_array(C[:, 0]) colorbarbox.add_artist(col) # Create outline if orientation == 'horizontal': outline = Rectangle((0, 0), length_fraction, width_fraction, fill=False, ec=color) else: outline = Rectangle((0, 0), width_fraction, length_fraction, fill=False, ec=color) colorbarbox.add_artist(outline) # Create ticks and tick labels w10th = width_fraction / 10.0 ticklines = [] ticktexts = [] for tick, ticklabel in zip(ticks, ticklabels): if ticklocation == 'bottom': x0 = x1 = xtext = tick y0 = w10th y1 = -w10th ytext = -2 * w10th ha = 'center' va = 'top' elif ticklocation == 'top': x0 = x1 = xtext = tick y0 = width_fraction - w10th y1 = width_fraction + w10th ytext = width_fraction + 2 * w10th ha = 'center' va = 'bottom' elif ticklocation == 'left': x0 = w10th x1 = -w10th xtext = -2 * w10th y0 = y1 = ytext = tick ha = 'right' va = 'center' elif ticklocation == 'right': x0 = width_fraction - w10th x1 = width_fraction + w10th xtext = width_fraction + 2 * w10th y0 = y1 = ytext = tick ha = 'left' va = 'center' ticklines.append([(x0, y0), (x1, y1)]) ticklabel = offset_string + ticklabel ticktext = Text(xtext, ytext, ticklabel, color=color, fontproperties=font_properties, horizontalalignment=ha, verticalalignment=va) ticktexts.append(ticktext) col = LineCollection(ticklines, color=color) colorbarbox.add_artist(col) for ticktext in ticktexts: colorbarbox.add_artist(ticktext) # Create label if label: labelbox = AuxTransformBox(ax.transAxes) va = 'baseline' if orientation == 'horizontal' else 'center' text = Text(0, 0, label, fontproperties=font_properties, verticalalignment=va, rotation=orientation, color=color) labelbox.add_artist(text) else: labelbox = None # Create final offset box if ticklocation == 'bottom': children = [colorbarbox, labelbox] if labelbox else [colorbarbox] child = VPacker(children=children, align='center', pad=0, sep=sep) elif ticklocation == 'top': children = [labelbox, colorbarbox] if labelbox else [colorbarbox] child = VPacker(children=children, align='center', pad=0, sep=sep) elif ticklocation == 'left': children = [labelbox, colorbarbox] if labelbox else [colorbarbox] child = HPacker(children=children, align='center', pad=0, sep=sep) elif ticklocation == 'right': children = [colorbarbox, labelbox] if labelbox else [colorbarbox] child = HPacker(children=children, align='center', pad=0, sep=sep) # box = AnchoredOffsetbox(loc=location, pad=pad, borderpad=border_pad, child=child, frameon=frameon) box.axes = ax box.set_figure(self.get_figure()) box.patch.set_color(box_color) box.patch.set_alpha(box_alpha) box.draw(renderer)
def draw(self, renderer, *args, **kwargs): if not self.get_visible(): return if self.dx == 0: return # Late import from matplotlib import rcParams # Deprecation if rcParams.get("scalebar.height_fraction") is not None: warnings.warn( "The scalebar.height_fraction parameter in matplotlibrc is deprecated. " "Use scalebar.width_fraction instead.", DeprecationWarning, ) rcParams.setdefault("scalebar.width_fraction", rcParams["scalebar.height_fraction"]) # Get parameters def _get_value(attr, default): value = getattr(self, attr) if value is None: value = rcParams.get("scalebar." + attr, default) return value length_fraction = _get_value("length_fraction", 0.2) width_fraction = _get_value("width_fraction", 0.01) location = _get_value("location", "upper right") if isinstance(location, str): location = self._LOCATIONS[location.lower()] pad = _get_value("pad", 0.2) border_pad = _get_value("border_pad", 0.1) sep = _get_value("sep", 5) frameon = _get_value("frameon", True) color = _get_value("color", "k") box_color = _get_value("box_color", "w") box_alpha = _get_value("box_alpha", 1.0) scale_loc = _get_value("scale_loc", "bottom").lower() label_loc = _get_value("label_loc", "top").lower() font_properties = self.font_properties fixed_value = self.fixed_value fixed_units = self.fixed_units or self.units rotation = _get_value("rotation", "horizontal").lower() label = self.label # Create text properties textprops = {"color": color, "rotation": rotation} if font_properties is not None: textprops["fontproperties"] = font_properties # Calculate value, units and length ax = self.axes xlim = ax.get_xlim() ylim = ax.get_ylim() if rotation == "vertical": xlim, ylim = ylim, xlim # Mode 1: Auto if self.fixed_value is None: length_px = abs(xlim[1] - xlim[0]) * length_fraction length_px, value, units = self._calculate_best_length(length_px) # Mode 2: Fixed else: value = fixed_value units = fixed_units length_px = self._calculate_exact_length(value, units) scale_text = self.scale_formatter(value, self.dimension.to_latex(units)) width_px = abs(ylim[1] - ylim[0]) * width_fraction # Create scale bar if rotation == "horizontal": scale_rect = Rectangle( (0, 0), length_px, width_px, fill=True, facecolor=color, edgecolor="none", ) else: scale_rect = Rectangle( (0, 0), width_px, length_px, fill=True, facecolor=color, edgecolor="none", ) scale_bar_box = AuxTransformBox(ax.transData) scale_bar_box.add_artist(scale_rect) scale_text_box = TextArea(scale_text, textprops=textprops) if scale_loc in ["bottom", "right"]: children = [scale_bar_box, scale_text_box] else: children = [scale_text_box, scale_bar_box] if scale_loc in ["bottom", "top"]: Packer = VPacker else: Packer = HPacker scale_box = Packer(children=children, align="center", pad=0, sep=sep) # Create label if label: label_box = TextArea(label, textprops=textprops) else: label_box = None # Create final offset box if label_box: if label_loc in ["bottom", "right"]: children = [scale_box, label_box] else: children = [label_box, scale_box] if label_loc in ["bottom", "top"]: Packer = VPacker else: Packer = HPacker child = Packer(children=children, align="center", pad=0, sep=sep) else: child = scale_box box = AnchoredOffsetbox(loc=location, pad=pad, borderpad=border_pad, child=child, frameon=frameon) box.axes = ax box.set_figure(self.get_figure()) box.patch.set_color(box_color) box.patch.set_alpha(box_alpha) box.draw(renderer)
def draw(self, renderer, *args, **kwargs): if not self.get_visible(): return if self.dx == 0: return # Get parameters from matplotlib import rcParams # late import def _get_value(attr, default): value = getattr(self, attr) if value is None: value = rcParams.get('scalebar.' + attr, default) return value length_fraction = _get_value('length_fraction', 0.2) height_fraction = _get_value('height_fraction', 0.01) location = _get_value('location', 'upper right') if isinstance(location,six.string_types): location = self._LOCATIONS[location] pad = _get_value('pad', 0.2) border_pad = _get_value('border_pad', 0.1) sep = _get_value('sep', 5) frameon = _get_value('frameon', True) color = _get_value('color', 'k') box_color = _get_value('box_color', 'w') box_alpha = _get_value('box_alpha', 1.0) scale_loc = _get_value('scale_loc', 'bottom') label_loc = _get_value('label_loc', 'top') font_properties = self.font_properties if font_properties is None: textprops = {'color': color} else: textprops = {'color': color, 'fontproperties': font_properties} ax = self.axes xlim, ylim = ax.get_xlim(), ax.get_ylim() label = self.label # Create label if label: txtlabel = TextArea(label, minimumdescent=False, textprops=textprops) else: txtlabel = None # Create sizebar length_px = abs(xlim[1] - xlim[0]) * length_fraction length_px, scale_label = self._calculate_length(length_px) size_vertical = abs(ylim[1] - ylim[0]) * height_fraction sizebar = AuxTransformBox(ax.transData) sizebar.add_artist(Rectangle((0, 0), length_px, size_vertical, fill=True, facecolor=color, edgecolor=color)) txtscale = TextArea(scale_label, minimumdescent=False, textprops=textprops) if scale_loc in ['bottom', 'right']: children = [sizebar, txtscale] else: children = [txtscale, sizebar] if scale_loc in ['bottom', 'top']: Packer = VPacker else: Packer = HPacker boxsizebar = Packer(children=children, align='center', pad=0, sep=sep) # Create final offset box if txtlabel: if label_loc in ['bottom', 'right']: children = [boxsizebar, txtlabel] else: children = [txtlabel, boxsizebar] if label_loc in ['bottom', 'top']: Packer = VPacker else: Packer = HPacker child = Packer(children=children, align='center', pad=0, sep=sep) else: child = boxsizebar box = AnchoredOffsetbox(loc=location, pad=pad, borderpad=border_pad, child=child, frameon=frameon) box.axes = ax box.set_figure(self.get_figure()) box.patch.set_color(box_color) box.patch.set_alpha(box_alpha) box.draw(renderer)
def scalebar_based_on_planar_distance( ax, x_planar_size=1, rounding_value_for_xsize=0, bar_height=0.015, decimal_separator=',', fill_bar=True, fill_bar_color='k', fontproperties=None, label_top=True, loc='center', pad=0, borderpad=0, background_facecolor='k', face_alpha=1, length_unit='m', unit_transformation_function=None, background_edgecolor='k', background_linewidth=1, background_edgealpha=1, background_facealpha=1, sep=0, x0=0.91, y0=0.02, x1=1, y1=0.08, ): """ Function description: This function adds a sizebar in the axes. This sizebar is an artist of matplotlib. This artist x_size automatically dilates or contracts acoording to the zooming (in/out) \ of its parent axes. -------------------------------------------------------------------------------------------------------------- Parameters: ax: the parent axes that will be used to measure the distance for the sizebar -------------------------------------------------------------------------------------------------------------- x_planar_size (float): the planar longitudinal size to create the scalebar. Units in data coordinates transform. Standard = 200 (units) -------------------------------------------------------------------------------------------------------------- rounding_value_for_xsize: the rounding decimal cases to be used in the scalebar label. -------------------------------------------------------------------------------------------------------------- bar_height (float): the relative height of the scalebar in figure units Standard = 0.015 -------------------------------------------------------------------------------------------------------------- fill_bar (bool): this sets whether to fill or not the bar. The filling color is setted by the color attribute Standard = True -------------------------------------------------------------------------------------------------------------- fill_bar_color ('string' or Tuple): sets the color to be used in the filling process of the scalebar -------------------------------------------------------------------------------------------------------------- fontproperties (matplotlib.font_manager.FontProperties): sets the fontproperties to be used in the label of the scalebar Example: from matplotlib.font_manager import FontProperties fontproperties = FontProperties(family='calibri', weight='light', style='normal', size=10) -------------------------------------------------------------------------------------------------------------- label_top (Bool): sets the label vertical position relative to the scalebar. For standard, the legend is above the scalebar Standard = True -------------------------------------------------------------------------------------------------------------- loc (string): this attribute sets the label position relative to the bounding box Standard = 'upper right' Options available: [upper right, upper left, lower left, lower right, right, center left, center right, lower center, upper center, center] -------------------------------------------------------------------------------------------------------------- pad (float): sets the vertical distance from the scalebar and its background Bbox in fraction of the font \ size Standard = 0.1 -------------------------------------------------------------------------------------------------------------- background_facecolor = sets the color to the background color'k' -------------------------------------------------------------------------------------------------------------- face_alpha (string): sets the color to the background alpha Standard = 'grey' -------------------------------------------------------------------------------------------------------------- length_unit (string): The distance unit measurement that will be used in the scalebar. Available options: ['m', 'Km'] If other distance unit measurements are required, add a transformation function from meters to the required unit in the attr: "unit_transformation_function" Standard: 'Km' -------------------------------------------------------------------------------------------------------------- unit_transformation_function: the function to convert the scale unit into the desired distance measurement unit. If unit_transformation_function is provided, the returned value will be the transformation of the planar distance by this given function Example of converting a meter to mile: unit_transformation_function = lambda x: x*0,00062137 Standard: None (so that no transformation is applied) -------------------------------------------------------------------------------------------------------------- background_padding=100 -------------------------------------------------------------------------------------------------------------- background_edgecolor (string; or tuple(RGB); or tuple(RGBA) ): sets the color to be used in the edgecolor of the bbox Standard = 'k' -------------------------------------------------------------------------------------------------------------- background_linewidth (float): the width of the line surrounding the Bbox Standard = 1 -------------------------------------------------------------------------------------------------------------- sep (int): Separation between the label and the size bar, in points Standard = 5 -------------------------------------------------------------------------------------------------------------- x0 (float): the relative longitudinal position to be placed the scalebar in figure units. Standard = 0.8 -------------------------------------------------------------------------------------------------------------- y0 (float): the relative latitudinal position to be placed the scalebar in figure units. Standard = 0.1 -------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------- Returns (tuple): 1) The extent of the colorbar in rendered window units 2) The extent of the colorbar in figure window units """ # the x coords of this transformation are data, and the # y coord are axes trans = transforms.blended_transform_factory(ax.transData, ax.figure.transFigure) if not isinstance(fontproperties, matplotlib.font_manager.FontProperties): fontproperties = FontProperties(family='calibri', weight='light', style='normal', size=10) if unit_transformation_function != None: converted_string = round( unit_transformation_function(x_planar_size), rounding_value_for_xsize) else: converted_string = round( unit_transformation_function(x_planar_size), rounding_value_for_xsize) if rounding_value_for_xsize == 0: converted_string = int(converted_string) else: converted_string = str(converted_string).replace( '.', decimal_separator) Formatted_Label = '{0} {1}'.format(converted_string, length_unit) Bbox_bar = scale_bar_class.add_anchored_size_bar( ax=ax, transform=trans, loc=loc, color='k', horizontal_size=x_planar_size, label=Formatted_Label, label_top=label_top, pad=pad, bar_height=bar_height, fontproperties=fontproperties, borderpad=borderpad, sep=sep, frameon=True, fill_bar=fill_bar, bbox_to_anchor=(x0, y0, x1, y1), bbox_transform=ax.figure.transFigure) child = HPacker(pad=0.2, sep=0.2, width=0.2, height=0.2, align='baseline', mode='fixed', children=[Bbox_bar]) box = AnchoredOffsetbox(loc='center', pad=pad, borderpad=0.5, child=child, frameon=False, bbox_to_anchor=(x0, y0, x1, y1), bbox_transform=ax.figure.transFigure) box.patch.set_color(background_facecolor) box.patch.set_alpha(background_facealpha) box.patch.set_edgecolor(background_edgecolor) box.axes = ax box.set_figure(ax.get_figure()) return box
def scalebar_based_on_degree_distance(ax, distance_measuring_method='geopy', ellipsoid='WGS-84', distance_method='geodesic', x_size_in_degrees=1, rounding_value_for_xsize=0, decimal_separator=',', bar_height=0.015, fill_bar=True, fill_bar_color='k', fontproperties=None, label_top=True, loc='center', pad=0.3, borderpad=0, background_facecolor='white', face_alpha=1, length_unit='km', unit_transformation_function=None, background_edgecolor='k', background_linewidth=1, background_edgealpha=1, background_facealpha=1, sep=0, x0=0.91, y0=0.02, x1=1, y1=0.08, over_write_distance_metric=False): """ Function description: This function adds a sizebar in the axes. This sizebar is an artist of matplotlib. This artist x_size automatically dilates or contracts acoording to the zooming (in/out) \ of its parent axes. -------------------------------------------------------------------------------------------------------------- Parameters: ax: the parent axes that will be used to measure the distance for the sizebar -------------------------------------------------------------------------------------------------------------- distance_measuring_method (string): sets the type of distance measuring system over geodetic (degree) distances Available options: ['geopy', 'Transverse_mercator_projection'] Geopy option requires extra parameters for its evaluation which are set by the ellipsoid and distance_method parameters Standard: 'geopy' -------------------------------------------------------------------------------------------------------------- ellipsoid (string or (3d-tuple)): sets the ellipsoid that will be used for the distance measuring system. WGS-84 garantees standard error distance for all the globe. Better precision can be acchieved by local specific Ellipsoid Standard: 'WGS-84' Observation: this parameter is only applicable for distance_measuring_method == 'geopy' -------------------------------------------------------------------------------------------------------------- distance_method (string): sets the type of distance measuring system that will be applied over the scalebar. It will convert degree distance into planar distance. Available options: ['vincety': most precise 'geodetic/geodesic': will converge always 'great_circle': commonly used in the literature ] Standard: 'vincenty' Observation: this parameter is only applicable for distance_measuring_method == 'geopy' -------------------------------------------------------------------------------------------------------------- x_size_in_degrees (float): the longitudinal size to create the scalebar. Units in longitudinal data coordinates transform. Standard = 0.2 -------------------------------------------------------------------------------------------------------------- rounding_value_for_xsize: the rounding decimal cases to be used in the scalebar label. -------------------------------------------------------------------------------------------------------------- bar_height (float): the relative height of the scalebar in figure units Standard = 0.015 -------------------------------------------------------------------------------------------------------------- fill_bar (bool): this sets whether to fill or not the bar. The filling color is setted by the color attribute Standard = True -------------------------------------------------------------------------------------------------------------- fill_bar_color ('string' or Tuple): sets the color to be used in the filling process of the scalebar -------------------------------------------------------------------------------------------------------------- fontproperties (matplotlib.font_manager.FontProperties): sets the fontproperties to be used in the label of the scalebar Example: from matplotlib.font_manager import FontProperties fontproperties = FontProperties(family='calibri', weight='light', style='normal', size=10) -------------------------------------------------------------------------------------------------------------- label_top (Bool): sets the label vertical position relative to the scalebar. For standard, the legend is above the scalebar Standard = True -------------------------------------------------------------------------------------------------------------- loc (string): this attribute sets the label position relative to the bounding box Standard = 'upper right' Options available: [upper right, upper left, lower left, lower right, right, center left, center right, lower center, upper center, center] -------------------------------------------------------------------------------------------------------------- pad (float): sets the vertical distance from the scalebar and its background Bbox in fraction of the font \ size Standard = 0.1 -------------------------------------------------------------------------------------------------------------- background_facecolor = sets the color to the background color'k' -------------------------------------------------------------------------------------------------------------- face_alpha (string): sets the color to the background alpha Standard = 'grey' -------------------------------------------------------------------------------------------------------------- length_unit (string): The distance unit measurement that will be used in the scalebar. Available options: ['m', 'Km'] If other distance unit measurements are required, add a transformation function from meters to the required unit in the attr: "unit_transformation_function" Standard: 'Km' -------------------------------------------------------------------------------------------------------------- unit_transformation_function: the function to convert the scale unit into the desired distance measurement unit, in case that measurement unit is not "km" or 'm'. This passed function must convert meters to the desired unit, and return the converted value in the desired unit. Example of converting a meter to mile: unit_transformation_function = lambda x: x*0,00062137 Standard: None (so that no transformation is applied) Observation: this parameter is only applicable for distance_measuring_method == 'Transverse_mercator_projection' -------------------------------------------------------------------------------------------------------------- background_padding=100, -------------------------------------------------------------------------------------------------------------- background_edgecolor (string; or tuple(RGB); or tuple(RGBA) ): sets the color to be used in the edgecolor of the bbox Standard = 'k' -------------------------------------------------------------------------------------------------------------- background_linewidth (float): the width of the line surrounding the Bbox Standard = 1 -------------------------------------------------------------------------------------------------------------- sep (int): Separation between the label and the size bar, in points Standard = 5 -------------------------------------------------------------------------------------------------------------- x0 (float): the relative longitudinal position to be placed the scalebar in figure units. Standard = 0.8 -------------------------------------------------------------------------------------------------------------- y0 (float): the relative latitudinal position to be placed the scalebar in figure units. Standard = 0.1 -------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------- Returns: box that encompasses the scalebar """ if ax.projection.is_geodetic() == True: raise ValueError( "The axes projection must be the ccrs.PlateCarree() projection in order for this algorithm to work." ) # the x coords of this transformation are data, and the # y coord are axes trans = transforms.blended_transform_factory(ax.transData, ax.figure.transFigure) if not isinstance(fontproperties, matplotlib.font_manager.FontProperties): fontproperties = FontProperties(family='calibri', weight='light', style='normal', size=10) if distance_measuring_method == 'geopy': get_distancer = getattr(scale_bar_class, 'distance_from_degrees_using_geopy') Distance = get_distancer( ax=ax, longitudinal_distance_in_degrees=x_size_in_degrees, ellipsoid=ellipsoid, distance_method=distance_method, length_unit=length_unit, rounding_value_for_xsize=rounding_value_for_xsize) if rounding_value_for_xsize == 0: converted_string = int(Distance) else: converted_string = str(Distance).replace( '.', decimal_separator) Formatted_Label = '{0} {1}'.format(converted_string, length_unit) else: if (length_unit.lower() not in [ 'km', 'm', 'meter', 'kilometer' ]) and unit_transformation_function == None: raise Exception( """If length_unit is not Km or meter unit, a transformation function must be supplied for the attribute \ unit_transformation_function """) get_distancer = getattr( scale_bar_class, 'calculate_distance_based_on_Transverse_mercator_projection') Distance = get_distancer( ax=ax, x_size_in_degrees=x_size_in_degrees, rounding_value_for_xsize=rounding_value_for_xsize, length_unit=length_unit, unit_transformation_function=unit_transformation_function) if rounding_value_for_xsize == 0: converted_string = int(Distance) else: converted_string = str(Distance).replace( '.', decimal_separator) Formatted_Label = '{0} {1}'.format(converted_string, length_unit) if over_write_distance_metric is not False: Formatted_Label = '{0} {1}'.format(over_write_distance_metric, length_unit) print(Formatted_Label) from functools import partial P_scale_bar_c = partial(scale_bar_class.add_anchored_size_bar, ax=ax, transform=trans, loc=loc, color='k', horizontal_size=x_size_in_degrees, label=Formatted_Label, label_top=label_top, pad=pad, bar_height=bar_height, fontproperties=fontproperties, borderpad=borderpad, sep=sep, frameon=True, bbox_to_anchor=(x0, y0, x1, y1), bbox_transform=ax.figure.transFigure) Bbox_bar = P_scale_bar_c(fill_bar=True) child = HPacker(pad=0.2, sep=0, width=0.2, height=0.2, align='baseline', mode='fixed', children=[Bbox_bar]) box = AnchoredOffsetbox(loc='center', pad=pad, borderpad=0.5, child=child, frameon=False, bbox_to_anchor=(x0, y0, x1, y1), bbox_transform=ax.figure.transFigure) box.patch.set_color(background_facecolor) box.patch.set_alpha(background_facealpha) box.patch.set_edgecolor(background_edgecolor) box.axes = ax box.set_figure(ax.get_figure()) return box
def draw(self, renderer, *args, **kwargs): if not self.get_visible(): return if self.dx == 0: return # Get parameters from matplotlib import rcParams # late import def _get_value(attr, default): value = getattr(self, attr) if value is None: value = rcParams.get("scalebar." + attr, default) return value length_fraction = _get_value("length_fraction", 0.2) height_fraction = _get_value("height_fraction", 0.01) location = _get_value("location", "upper right") if isinstance(location, str): location = self._LOCATIONS[location] pad = _get_value("pad", 0.2) border_pad = _get_value("border_pad", 0.1) sep = _get_value("sep", 5) frameon = _get_value("frameon", True) color = _get_value("color", "k") box_color = _get_value("box_color", "w") box_alpha = _get_value("box_alpha", 1.0) scale_loc = _get_value("scale_loc", "bottom") label_loc = _get_value("label_loc", "top") font_properties = self.font_properties fixed_value = self.fixed_value fixed_units = self.fixed_units or self.units if font_properties is None: textprops = {"color": color} else: textprops = {"color": color, "fontproperties": font_properties} ax = self.axes xlim = ax.get_xlim() ylim = ax.get_ylim() label = self.label # Calculate value, units and length # Mode 1: Auto if self.fixed_value is None: length_px = abs(xlim[1] - xlim[0]) * length_fraction length_px, value, units = self._calculate_best_length(length_px) # Mode 2: Fixed else: value = fixed_value units = fixed_units length_px = self._calculate_exact_length(value, units) scale_label = self.label_formatter(value, self.dimension.to_latex(units)) size_vertical = abs(ylim[1] - ylim[0]) * height_fraction # Create size bar sizebar = AuxTransformBox(ax.transData) sizebar.add_artist( Rectangle( (0, 0), length_px, size_vertical, fill=True, facecolor=color, edgecolor="none", )) txtscale = TextArea(scale_label, minimumdescent=False, textprops=textprops) if scale_loc in ["bottom", "right"]: children = [sizebar, txtscale] else: children = [txtscale, sizebar] if scale_loc in ["bottom", "top"]: Packer = VPacker else: Packer = HPacker boxsizebar = Packer(children=children, align="center", pad=0, sep=sep) # Create text area if label: txtlabel = TextArea(label, minimumdescent=False, textprops=textprops) else: txtlabel = None # Create final offset box if txtlabel: if label_loc in ["bottom", "right"]: children = [boxsizebar, txtlabel] else: children = [txtlabel, boxsizebar] if label_loc in ["bottom", "top"]: Packer = VPacker else: Packer = HPacker child = Packer(children=children, align="center", pad=0, sep=sep) else: child = boxsizebar box = AnchoredOffsetbox(loc=location, pad=pad, borderpad=border_pad, child=child, frameon=frameon) box.axes = ax box.set_figure(self.get_figure()) box.patch.set_color(box_color) box.patch.set_alpha(box_alpha) box.draw(renderer)
def draw(self, renderer, *args, **kwargs): if not self.get_visible(): return if not self.get_mappable(): return # Get parameters from matplotlib import rcParams # late import cmap = self.mappable.get_cmap() array = self.mappable.get_array() label = self.label orientation = self.orientation or \ rcParams.get('colorbar.orientation', 'vertical') nbins = self.nbins or rcParams.get('colorbar.nbins', 50) length_fraction = self.length_fraction or \ rcParams.get('colorbar.length_fraction', 0.2) width_fraction = self.width_fraction or \ rcParams.get('colorbar.width_fraction', 0.01) location = self.location or \ self._LOCATIONS[rcParams.get('colorbar.location', 'upper right')] pad = self.pad or rcParams.get('colorbar.pad', 0.2) border_pad = self.border_pad or \ rcParams.get('colorbar.border_pad', 0.1) sep = self.sep or rcParams.get('colorbar.sep', 5) frameon = self.frameon or rcParams.get('colorbar.frameon', True) color = self.color or rcParams.get('colorbar.color', 'k') box_color = self.box_color or rcParams.get('colorbar.box_color', 'w') box_alpha = self.box_alpha or rcParams.get('colorbar.box_alpha', 1.0) font_properties = self.font_properties ticks = self.ticks ticklabels = self.ticklabels ax = self.axes children = [] # Create colorbar colorbarbox = AuxTransformBox(ax.transData) xlim, ylim = ax.get_xlim(), ax.get_ylim() if orientation == 'horizontal': length = abs(xlim[1] - xlim[0]) * length_fraction width = abs(ylim[1] - ylim[0]) * width_fraction else: length = abs(ylim[1] - ylim[0]) * length_fraction width = abs(xlim[1] - xlim[0]) * width_fraction step_length = length / nbins patches = [] for x in np.arange(0, length, step_length): if orientation == 'horizontal': patch = Rectangle((x, 0), step_length, width) else: patch = Rectangle((0, x), width, step_length) patches.append(patch) values = np.linspace(np.min(array), np.max(array), nbins) minvalue, maxvalue = values[0], values[-1] col = PatchCollection(patches, cmap=cmap, edgecolors='none') col.set_array(values) colorbarbox.add_artist(col) if orientation == 'horizontal': patch = Rectangle((0, 0), length, width, fill=False, ec=color) else: patch = Rectangle((0, 0), width, length, fill=False, ec=color) colorbarbox.add_artist(patch) children.append(colorbarbox) # Create ticks tickbox = AuxTransformBox(ax.transData) if ticks is None: ticks = [minvalue, maxvalue] # default if not ticklabels: ticklabels = ticks[:] # tick label by default if minvalue not in ticks: # little hack to get right layout position ticks.append(minvalue) ticklabels.append('') # no label for this extra tick if maxvalue not in ticks: # little hack to get right layout position ticks.append(maxvalue) ticklabels.append('') # no label for this extra tick for itick, tick in enumerate(ticks): if tick > maxvalue or tick < minvalue: continue # ignore it # Fraction of colorbar depending of min and max values of colorbar a = 1 / (maxvalue - minvalue) b = -a * minvalue tickfrac = a * tick + b if orientation == 'horizontal': tickx = tickfrac * length ticky = 0 ha = 'center' va = 'top' else: tickx = width ticky = tickfrac * length ha = 'left' va = 'center' ticktext = Text(tickx, ticky, ticklabels[itick], color=color, fontproperties=font_properties, horizontalalignment=ha, verticalalignment=va) tickbox.add_artist(ticktext) children.append(tickbox) # Create label if label: labelbox = AuxTransformBox(ax.transData) va = 'baseline' if orientation == 'horizontal' else 'center' text = Text(0, 0, label, fontproperties=font_properties, verticalalignment=va, rotation=orientation) labelbox.add_artist(text) children.insert(0, labelbox) # Create final offset box Packer = VPacker if orientation == 'horizontal' else HPacker child = Packer(children=children, align="center", pad=0, sep=sep) box = AnchoredOffsetbox(loc=location, pad=pad, borderpad=border_pad, child=child, frameon=frameon) box.axes = ax box.set_figure(self.get_figure()) box.patch.set_color(box_color) box.patch.set_alpha(box_alpha) box.draw(renderer)